Index du Forum
IDENTIFICATION SERVEUR : 10.0.97.129 - CLIENT : 54.225.57.89

 FAQFAQ   RechercherRechercher   Liste des MembresListe des Membres   Groupes d'utilisateursGroupes d'utilisateurs   S'enregistrerS'enregistrer 
 ProfilProfil   Se connecter pour vérifier ses messages privésSe connecter pour vérifier ses messages privés   ConnexionConnexion 

Captain Goodnight and the Islands of Fear (Broderbund, 1985)

 
Poster un nouveau sujet   Répondre au sujet     Index du Forum -> PROTECTION MALEFIQUE
Voir le sujet précédent :: Voir le sujet suivant  
Auteur Message
qkumba



Inscrit le: 29 Jan 2012
Messages: 171

MessagePosté le: Mer 17 Aoû 2016, 23:37    Sujet du message: Captain Goodnight and the Islands of Fear (Broderbund, 1985) Répondre en citant

Race against time to disarm the bomb, while avoiding robots and planes and missiles, drive jeeps and a boat, fly a helicopter! What a game.

I wrote this one nearly a year ago and never released it. I don't remember why. The write-up is in the style of 4am. Maybe I was hoping that he'd add funny parts to it or something.

Code:
[S6,D1=original disk]
[S5,D1=my work disk]

]PR#5
]CALL-151
*8600<C600.C6FCM N 86F9:69 FF N 8600G
...reboots slot 6...

; save the boot sector in a safe place
*2800<800.8FFM N C500G
...reboots slot 5...
]BSAVE BOOT0,A$2800,L$100

; move it back to the original place
; to make disassembly easier to follow
]CALL-151
*800<2800.28FFM
*801L

; clear hi-res graphics screens (both)
0801-   A0 00       LDY   #$00
0803-   A9 20       LDA   #$20
0805-   A2 40       LDX   #$40
0807-   84 00       STY   $00
0809-   85 01       STA   $01
080B-   98          TYA
080C-   91 00       STA   ($00),Y
080E-   C8          INY
080F-   D0 FB       BNE   $080C
0811-   E6 01       INC   $01
0813-   CA          DEX
0814-   D0 F6       BNE   $080C

; show hi-res graphics screen 1
; aesthetic reasons, because text screen
; is about to be filled with garbage
0816-   2C 52 C0    BIT   $C052
0819-   2C 57 C0    BIT   $C057
081C-   2C 54 C0    BIT   $C054
081F-   2C 50 C0    BIT   $C050

; save slot number (x16)
0822-   A6 2B       LDX   $2B
0824-   86 08       STX   $08

; decrypt rest of boot0 and store it in
; zero page (starting at $60)
0826-   EA          NOP
0827-   EA          NOP
0828-   A0 00       LDY   #$00
082A-   EA          NOP
082B-   EA          NOP
082C-   B9 50 08    LDA   $0850,Y
082F-   EA          NOP
0830-   EA          NOP
0831-   49 A5       EOR   #$A5
0833-   EA          NOP
0834-   EA          NOP
0835-   99 60 00    STA   $0060,Y
0838-   EA          NOP
0839-   EA          NOP
083A-   C8          INY
083B-   D0 EF       BNE   $082C
083D-   EA          NOP
083E-   EA          NOP

; reset stack pointer
083F-   A2 FF       LDX   #$FF
0841-   EA          NOP
0842-   EA          NOP
0843-   EA          NOP
0844-   9A          TXS
0845-   EA          NOP
0846-   EA          NOP

; and exit
0847-   60          RTS


We can run that code directly, so let's do that, but first, we must change the destination of the write.
We can't let the monitor corrupt the code because of shared zero-page addresses.
Let's write to $2060 instead.

Code:
*837:20


We also can't let it mess with our stack, otherwise the RTS might crash the machine because of jumping to an uninitialised address.
Let's NOP the TXS.

Code:
*844:EA


Let's see...

Code:
*801G
*C500G
]BSAVE BOOT0 0060-015F,A$2060,L$100


Stack pointer was #$FF before the RTS, so the stack would wrap around and fetch from $0100-0101, which we have at $2100-2101.

Code:
]CALL-151
*2100.2107

2100- B3 00 5F 00 FF 03 00 04


The RTS would fetch $00B3, and resume from $00B3+1=$00B4, which we have at $20B4.

Code:
*20B4L

20B4-   A2 D4       LDX     #$D4
20B6-   86 00       STX     $00 ;$00=#$D4
20B8-   E8          INX
20B9-   86 01       STX     $01 ;$01=#$D5
20BB-   E8          INX
20BC-   86 02       STX     $02 ;$02=#$D6
20BE-   E8          INX
20BF-   86 03       STX     $03 ;$03=#$D7
20C1-   A9 04       LDA     #04
20C3-   AA          TAX         ;A=X=#$04
20C4-   60          RTS


Setting up some obviously very important values, then another RTS.
From above, that one will fetch $005F, and resume from $005F+1=$0060, which we have at $2060.

Code:
*2060L

2060-   86 3E       STX   $3E   ;$3E=#$04
2062-   85 3A       STA   $3A   ;$3A=#$04
2064-   A6 3E       LDX   $3E
2066-   86 40       STX   $40   ;$40=#$04
2068-   A0 00       LDY   #$00
206A-   A5 3A       LDA   $3A
206C-   84 3C       STY   $3C   ;$3C=#$00
206E-   85 3D       STA   $3D   ;$3D=#$04

; watch for prologue #$D4 #$D5 #$D6
2070-   A6 08       LDX   $08   ;slot (x16)
2072-   20 AE 00    JSR   $00AE
2075-   C5 00       CMP   $00   ;#$D4
2077-   D0 F9       BNE   $2072
2079-   20 AE 00    JSR   $00AE
207C-   C5 01       CMP   $01   ;#$D5
207E-   D0 F5       BNE   $2075
2080-   20 AE 00    JSR   $00AE
2083-   C5 02       CMP   $02   ;#$D6
2085-   D0 F5       BNE   $207C

; decode one 4x4-encoded sector
; to $0400...07FF, 1024-bytes long
2087-   BD 8C C0    LDA   $C08C,X
208A-   10 FB       BPL   $2087
208C-   2A          ROL
208D-   85 3F       STA   $3F
208F-   BD 8C C0    LDA   $C08C,X
2092-   10 FB       BPL   $208F
2094-   25 3F       AND   $3F
2096-   91 3C       STA   ($3C),Y
2098-   C8          INY
2099-   D0 EC       BNE   $2087
209B-   0E 00 C0    ASL   $C000

; verify epilogue #$D7, no checksum
209E-   BD 8C C0    LDA   $C08C,X
20A1-   10 FB       BPL   $209E
20A3-   C5 03       CMP   $03   ;#$D7
20A5-   D0 BD       BNE   $2064

; four pages
20A7-   E6 3D       INC   $3D   ;increment address
20A9-   C6 40       DEC   $40   ;decrement count
20AB-   D0 DA       BNE   $2087

; and go there
20AD-   60          RTS


The RTS would fetch $03FF, and resume from $03FF+1=$0400.
We need to intercept that. One way to do that is to change the indirect "LDA $3A" to an absolute "LDA #$xx" (#$A9 #$xx) like, say, #$24.
To do that, we have to encode those two values and store them first.
The key is a fixed value of #$A5, so #$A9^#$A5=#$0C goes to $085A, and #$24^#$A5=#$81 goes to $085B.
That leaves the stack to update. We want to transfer to $870F (but -1 because RTS), where we place a jump to the boot PROM for the work disk.
That looks like #$87^#$A5=#$22 and #$0E^#$A5=#$AB.

Code:
; change the write destination to $2400
86F8-   A9 0C       LDA   #$0C
86FA-   8D 5A 08    STA   $085A
86FD-   A9 81       LDA   #$81
86FF-   8D 5B 08    STA   $085B

; set up the callback
8702-   A9 AB       LDA   #$AB
8704-   8D F4 08    STA   $08F4
8707-   A9 22       LDA   #$22
8709-   8D F5 08    STA   $08F5

; start the boot
870C-   4C 01 08    JMP   $0801

; callback is here
; just reboot to my work disk
870F-   4C 00 C5    JMP   $C500

*BSAVE TRACE1,A$8600,L$112
*8600G
...reboots slot 6...
...reboots slot 5...
]BSAVE BOOT1 0400-07FF,A$2400,L$400

At $25D4, we can see "ROLAND WAS HERE !!! "

]CALL -151
*2400L

2400-   60          RTS


That takes us to the last value that we saw in the stack: $0401.

Code:
*2401L

2401-   4C 06 04    JMP   $0406
...

; restore 40-column mode
2406-   8D 5F C0    STA   $C05F
2409-   8D 0C C0    STA   $C00C
240C-   8D 00 C0    STA   $C000

; move some code to $0300
240F-   A0 00       LDY   #$00
2411-   B9 3D 06    LDA   $063D,Y
2414-   99 00 03    STA   $0300,Y
2417-   C8          INY
2418-   D0 F7       BNE   $2411

*263DL

; standard Broderbund Badlands -- put a
; debugging character in the upper-left
; corner of the screen, wipe main
; memory, play a sound, restore banked
; memory, reboot
263D-   A9 D0       LDA   #$D0
263F-   2C A9 D2    BIT   $D2A9
2642-   48          PHA
2643-   AD 81 C0    LDA   $C081
2646-   20 2F FB    JSR   $FB2F
2649-   20 58 FC    JSR   $FC58
264C-   20 84 FE    JSR   $FE84
264F-   20 93 FE    JSR   $FE93
2652-   20 89 FE    JSR   $FE89
2655-   AD 80 C0    LDA   $C080
2658-   68          PLA
2659-   8D 00 04    STA   $0400
265C-   A0 00       LDY   #$00
265E-   A9 08       LDA   #$08
2660-   84 83       STY   $83
2662-   85 84       STA   $84
2664-   A2 B8       LDX   #$B8
2666-   98          TYA
2667-   91 83       STA   ($83),Y
2669-   C8          INY
266A-   D0 FB       BNE   $2667
266C-   2C 30 C0    BIT   $C030
266F-   E6 84       INC   $84
2671-   CA          DEX
2672-   D0 F3       BNE   $2667
2674-   20 43 03    JSR   $0343
2677-   AD 81 C0    LDA   $C081
267A-   EE F4 03    INC   $03F4
267D-   4C 00 C6    JMP   $C600
2680-   AD 81 C0    LDA   $C081
2683-   AD 81 C0    LDA   $C081
2686-   A0 00       LDY   #$00
2688-   A9 F8       LDA   #$F8
268A-   84 83       STY   $83
268C-   85 84       STA   $84
268E-   B1 83       LDA   ($83),Y
2690-   91 83       STA   ($83),Y
2692-   C8          INY
2693-   D0 F9       BNE   $268E
2695-   E6 84       INC   $84
2697-   D0 F5       BNE   $268E
2699-   AD 83 C0    LDA   $C083
269C-   AD 83 C0    LDA   $C083
269F-   60          RTS


Continuing...

Code:
241A-   20 63 03    JSR   $0363


That's at $26A0.

Code:
*26A0L

; restore banked memory
26A0-   20 43 03    JSR   $0343

;set I/O, break, and reset vectors to the Badlands
;I/O and break will print 'P', reset will print 'R'

26A3-   A0 00       LDY   #$00
26A5-   A9 03       LDA   #$03
26A7-   84 36       STY   $36
26A9-   85 37       STA   $37
26AB-   84 38       STY   $38
26AD-   85 39       STA   $39
26AF-   8C F0 03    STY   $03F0
26B2-   8D F1 03    STA   $03F1
26B5-   8D FE FF    STA   $FFFE
26B8-   8D FF FF    STA   $FFFF
26BB-   A0 03       LDY   #$03
26BD-   8C F2 03    STY   $03F2
26C0-   8D F3 03    STA   $03F3
26C3-   8C FC FF    STY   $FFFC
26C6-   8D FD FF    STA   $FFFD
26C9-   49 A5       EOR   #$A5
26CB-   8D F4 03    STA   $03F4
26CE-   60          RTS


Continuing...

Code:
; save slot (x16)
241D-   A5 2B       LDA   $2B
241F-   8D FF BF    STA     $BFFF

; convert to address ($Cx)
2422-   4A          LSR
2423-   4A          LSR
2424-   4A          LSR
2425-   4A          LSR
2426-   09 C0       ORA   #$C0
2428-   8D 42 03    STA   $0342

; check for 64kb of RAM
242B-   A2 00       LDX   #$00
242D-   8E 00 F0    STX   $F000
2430-   EC 00 F0    CPX   $F000
2433-   D0 05       BNE   $243A
2435-   E8          INX
2436-   D0 F5       BNE   $242D
2438-   F0 05       BEQ   $243F

; else print 'M' and reboot
243A-   A9 CD       LDA   #$CD
243C-   4C 05 03    JMP   $0305

; colour hi-res graphics screen 2
; a nice shade of orange
243F-   A0 00       LDY   #$00
2441-   A9 40       LDA   #$40
2443-   84 83       STY   $83
2445-   85 84       STA   $84
2447-   A2 20       LDX   #$20
2449-   A9 AA       LDA   #$AA
244B-   91 83       STA   ($83),Y
244D-   49 7F       EOR   #$7F
244F-   C8          INY
2450-   D0 F9       BNE   $244B
2452-   E6 84       INC   $84
2454-   CA          DEX
2455-   D0 F4       BNE   $244B

; and display it
2457-   2C 52 C0    BIT   $C052
245A-   2C 57 C0    BIT   $C057
245D-   2C 55 C0    BIT   $C055
2460-   2C 50 C0    BIT   $C050

; set current track to zero
2463-   A9 00       LDA   #$00
2465-   85 FF       STA   $FF

; seek to track 1 (two phases per track)
2467-   A9 02       LDA   #$02
2469-   20 44 05    JSR   $0544

; set prologue index and
; fetch page to write
246C-   A0 00       LDY   #$00
246E-   84 80       STY   $80
2470-   84 81       STY   $81
2472-   20 AB 04    JSR   $04AB

; check for end of list
2475-   F0 08       BEQ   $247F

; read sectors
2477-   20 8C 04    JSR   $048C

; adjust index, the branch is unconditional
247A-   A4 81       LDY   $81
247C-   C8          INY
247D-   D0 F1       BNE   $2470

; seek to nearest whole track
247F-   A5 FF       LDA   $FF
2481-   29 FE       AND   #$FE
2483-   20 44 05    JSR   $0544

; turn off drive
2486-   BD 88 C0    LDA   $C088,X

; we'll come back to this one
2489-   4C E3 05    JMP   $05E3

; this is the read sector routine
248C-   A0 00       LDY   #$00
248E-   84 82       STY   $82
2490-   48          PHA

; read two 4-and-4 encoded
; 512-bytes large sectors
2491-   20 D2 04    JSR   $04D2

; adjust quarter-track position
; the only difference between the
; quarter-track and full-track seek...
; is the delay that's used (#$0A vs #$13)
2494-   A4 82       LDY   $82
2496-   18          CLC
2497-   A5 FF       LDA   $FF
2499-   79 31 06    ADC   $0631,Y
249C-   20 47 05    JSR   $0547
249F-   68          PLA
24A0-   18          CLC
24A1-   69 02       ADC   #$02
24A3-   A4 82       LDY   $82
24A5-   C8          INY
24A6-   C0 04       CPY   #$04
24A8-   90 E4       BCC   $248E
24AA-   60          RTS


As an aside, the loader is very interesting - it reads one 512-bytes sector, advances by a quarter-track, reads one 512-bytes sector, retreats by a quarter-track, reads another 512-bytes sector, advances by a quarter-track, reads another 512-bytes sector, and then advances by one more quarter-track.
This produces a zig-zag movement, with a distinct "chattering" sound. Half of each quarter-track is used, which is the maximum possible that avoids cross-talk.

Code:
; conditionally select bank 1 or 2
; depending on the page to be read
24AB-   AD 83 C0    LDA   $C083
24AE-   AD 83 C0    LDA   $C083
24B1-   B9 C3 04    LDA   $04C3,Y
24B4-   48          PHA
24B5-   29 01       AND   #$01
24B7-   F0 06       BEQ   $24BF
24B9-   AD 8B C0    LDA   $C08B
24BC-   AD 8B C0    LDA   $C08B
24BF-   68          PLA
24C0-   29 FE       AND   #$FE
24C2-   60          RTS

; the routine that we neglected earlier
; calculate a checksum of the read pages
25E3-   A0 00       LDY   #$00
25E5-   84 90       STY   $90
25E7-   84 91       STY   $91
25E9-   84 92       STY   $92
25EB-   84 81       STY   $81
25ED-   20 AB 04    JSR   $04AB
25F0-   F0 20       BEQ   $2612
25F2-   85 93       STA   $93
25F4-   A2 08       LDX   #$08
25F6-   A0 00       LDY   #$00
25F8-   B1 92       LDA   ($92),Y
25FA-   45 90       EOR   $90
25FC-   85 90       STA   $90
25FE-   B1 92       LDA   ($92),Y
2600-   18          CLC
2601-   65 91       ADC   $91
2603-   85 91       STA   $91
2605-   C8          INY
2606-   D0 F0       BNE   $25F8
2608-   E6 93       INC   $93
260A-   CA          DEX
260B-   D0 EB       BNE   $25F8
260D-   A4 81       LDY   $81
260F-   C8          INY
2610-   D0 D9       BNE   $25EB

; compare first half of the checksum
; against expected values
2612-   A5 90       LDA   $90
2614-   CD 04 04    CMP   $0404
2617-   F0 05       BEQ   $261E

; else print 'L' and reboot
2619-   A9 CC       LDA   #$CC
261B-   4C 05 03    JMP   $0305

; compare second half of the checksum
; against expected values
261E-   A5 91       LDA   $91
2620-   CD 05 04    CMP   $0405
2623-   D0 F4       BNE   $2619

; hook the break and reset vectors again
2625-   20 66 03    JSR   $0366
2628-   A5 FF       LDA   $FF
262A-   8D 0E D4    STA   $D40E

; jump to title screen
262D-   4C 00 63    JMP   $6300


The disk activity isn't over yet (and there's an entire second side to the game), but it should be enough to give us an idea of how to proceed.
We just need to ask the disk nicely to read itself. Let's change our program.
We discard the read redirection, and leave only the stack callback.

We want to transfer to $8705 (but -1 because RTS), where we place the new code.
That looks like #$87^#$A5=#$22 and #$0E^#$A5=#$A1.

Code:
; set up the callback
86F8-   A9 A1       LDA   #$A1
86FA-   8D F4 08    STA   $08F4
86FD-   A9 22       LDA   #$22
86FF-   8D F5 08    STA   $08F5

; start the boot
8702-   4C 01 08    JMP   $0801

; callback is here
; select proper prologue value
8705-   A4 18       LDY   $18
8707-   88          DEY
8708-   88          DEY
8709-   84 80       STY   $80

; seek to specified track
870B-   A5 19       LDY   $19
870D-   A0 00       LDY   #$00
870F-   84 FF       STY   $FF
8711-   20 44 05    JSR   $0544

; read 7 whole tracks at a time
; to specified address ($1000+)
; until we reach $8000
8714-   A9 10       LDA   #$10
8716-   85 18       STA   $18
8718-   20 8C 04    JSR   $048C
871B-   A5 18       LDA   $18
871D-   69 07       ADC   #$07
871F-   10 F5       BPL   $8717

; remember which track we reached
8721-   A5 FF       LDA   $FF
8723-   85 18       STA   $18
8725-   4A          LSR
8726-   A8          TAY
8727-   C8          INY
8728-   84 19       STY   $19

; and then reboot to work disk
; so that we can save it
872A-   4C 00 C5    JMP   $C500

*BSAVE TRACE2,A$8600,L$12D
*18:2 2 N 8600G
...reboots slot 6...
...reboots slot 5...
]BSAVE T01-07,A$1000,L$7000
]CALL-151

; see how far it gets in case it hangs
*1000:DD N 1001<1000.7FFFM

; resume reading the disk
*8600G
...reboots slot 6...
; and it does hang
; ctrl-reset
]PR#5
...reboots slot 5
]CALL-151
*6800
6800- DD
*6000
6000- DD
*5800
5800- 00

; that's the one
]BSAVE T08-12,A$1000,L$5000


A disassembly of the code (not shown) tells us that tracks 16-31, and 33-34 are regular and readable.
Trying to copy the disk shows the same result. A sector editor also shows big chunks of source code.

We change the boot0 to use $Cx5C to read the four sectors, so that it looks like this:

Code:
0066-   86 42       STX   $42   ;set count, boot PROM reserves $40
0068-   86 27       STX   $27   ;address to read
006A-   A9 60       LDA   #$60  ;RTS
006C-   8D 01 08    STA   $0801 ;now we can JSR
006F-   A6 2B       LDX   $2B   ;slot*16
0071-   8A          TXA
0072-   4A          LSR
0073-   4A          LSR
0074-   4A          LSR
0075-   4A          LSR
0076-   09 C0       ORA   #$C0  ;slot to address
0078-   85 7C       STA   $7C   ;self-modify
007A-   20 5C 00    JSR   $005C ;boot PROM
007D-   B0 2A       BCS   $00A9 ;branch always
...
00A9-   C6 42       DEC   $42   ;dec count
00AB-   D0 CD       BNE   $007A ;until zero


Unfortunately, there's no getting around the substantial rewrite required for the boot1.
Fortunately, we have more than one entire sector available, and need less than one.
I used a routine that I wrote for just such an occasion.

The back side of the disk is composed entirely of regular sectors that we can copy.

Two things remain:
the off-disk protection, and loading and saving the highscores.
Let's start with the off-disk protection:
The first one triggers when entering the submarine: it asks for the confirmation code.
It's on side 2, T0F S00 A55. Change 03 -> 02 to allow any confirmation code.
The second one is the doomsday device itself.
When entering the aeroplane, it tells you the self-destruct code.
You use the code to know the combination of switches to deactivate the device.
It's on side 2, T1E S02 A7A. Change A5 44 -> D0 1D to just press the button. No switches.

As for the highscores, they're stored on track 32, the same as Airheart.
The code to read and write them is on tracks 33 and 34. Track 32 is a single 256-bytes sector of 4-and-4 encoded data, so replacing it is fairly easy.
I found the routine by using a debugger to step through the code after the prompt appeared.
The replacement technique is the same as I used for Airheart - track 32 is converted to 16-sectors, and the read routine loads the highscores *and the write routine* from track 32.
That way, nothing is touched on the other tracks, and there's plenty of room to move.

Miscellaneous notes:

The cruise missiles will appear unless you destroy the big radar installations.
They home in on you until you crash. After that, they just fly in a straight line.

To make yourself invulnerable in the jeep, press button 1 to get out of the car, then hold joystick down to kneel, and then hold button 0 while pressing button 1 to re-enter the jeep.

You also lose one hour per "death" (crash the plane, hit a mine, catch a grenade, etc), so... don't die.

The credits say "No thanks to Russ Thorp". According to Roland Gustafsson, it's a joke, and he's actually a nice guy.
Revenir en haut de page
Voir le profil de l'utilisateur Envoyer un message privé Visiter le site web de l'utilisateur
Montrer les messages depuis:   
Poster un nouveau sujet   Répondre au sujet     Index du Forum -> PROTECTION MALEFIQUE Toutes les heures sont au format GMT + 1 Heure
Page 1 sur 1

 
Sauter vers:  
Vous ne pouvez pas poster de nouveaux sujets dans ce forum
Vous ne pouvez pas répondre aux sujets dans ce forum
Vous ne pouvez pas éditer vos messages dans ce forum
Vous ne pouvez pas supprimer vos messages dans ce forum
Vous ne pouvez pas voter dans les sondages de ce forum


Powered by phpBB © 2001, 2005 phpBB Group
Traduction par : phpBB-fr.com