******************************************************************************** * Golden Voyage for the Apple II * * Game database created by William Demas and Scott Adams * * Apple II interpreter reportedly written by Mak Jukic * * Copyright 1981 Adventure International * ******************************************************************************** * Disassembly by Andy McFadden, using 6502bench SourceGen v1.7.5 * * Last updated 2021/08/24 * ******************************************************************************** * The focus of this disassembly is on the interpreter. The game data itself * * has received minimal formatting. * * * * The implementation uses 7 "virtual" 16-bit registers, stored in zero page * * locations $f0-f1 through $fc-fd. Various operations are defined for these * * registers, which may hold values or addresses. Most of the basic functions * * preserve all CPU registers when called, including the status register. * * * * This can make the code a bit inefficient at times, e.g. copying $f0-f1 to * * $f2-f3 requires a lot of pushing and popping, but the code is more compact * * that way. The only other zero page locations used are those needed by the * * monitor text routines and disk or tape I/O. * * * * It looks like the source code was broken into several pieces, which were * * loaded at fixed addresses. This was likely done to make development easier * * on a small system. Each chunk starts with a table of JMP instructions, a * * few of which are actually just references to data tables with a JMP opcode * * added to make the listing nicer. * ******************************************************************************** ITEM_HELD .eq $ff {const} ;room number of player's inventory MON_WNDWDTH .eq $21 ;width of scroll window MON_WNDTOP .eq $22 ;top of scroll window MON_CH .eq $24 ;cursor horizontal displacement MON_CV .eq $25 ;cursor vertical displacement MON_BASL .eq $28 ;base address for text output (lo) MON_A1L .eq $3c ;general purpose MON_A1H .eq $3d ;general purpose MON_A2L .eq $3e ;general purpose MON_A2H .eq $3f ;general purpose STACK .eq $0100 {addr/256} ;CPU stack MON_USRADDR .eq $03f8 {addr/3} ;jump to function that handles monitor Ctrl-Y KBD .eq $c000 ;R last key pressed + 128 KBDSTRB .eq $c010 ;RW keyboard strobe MON_BASCALC .eq $fbc1 ;calculate text base address MON_VIDOUT .eq $fbfd ;output Acc as text MON_BS .eq $fc10 ;move cursor left MON_HOME .eq $fc58 ;clear screen and reset text output to top-left MON_CR .eq $fc62 ;perform a carriage return MON_CLREOLZ .eq $fc9e MON_COUT .eq $fded ;print Acc to output device via $36-37 MON_WRITE .eq $fecd ;write data to cassette MON_READ .eq $fefd ;read data from cassette MON_OLDRST .eq $ff59 ;RESET entry point .org $0800 ; ; Program entry point. ; 0800: 4c 27 08 Entry jmp Start 0803: 4c cc 0b J_PrintNonNull jmp PrintNonNull 0806: 4c c5 0b J_PrintCR jmp PrintCR 0809: 4c 6b 0b J_PrintL1Str jmp PrintL1Str 080c: 4c 62 0b J_PrintNChars jmp PrintNChars 080f: 4c 95 0b J_PrintString jmp PrintString 0812: 4c be 0b J_PrintFlashStr jmp PrintFlashStr 0815: 4c 37 0c J_GetInput jmp GetInput 0818: 4c b1 0c J_ClearScreen jmp ClearScreen J_PrintSignedDec 081b: 4c ec 0f jmp PrintSignedDec J_GetItemLocation 081e: 4c ca 0f jmp GetItemLocation 0821: 4c c2 0c J_PushRegs jmp PushRegs 0824: 4c f2 0c J_PopRegs jmp PopRegs ; ; Program initialization. ; 0827: a9 4c Start lda #$4c ;point monitor Ctrl+Y vector at game loop 0829: 8d f8 03 sta MON_USRADDR 082c: a9 4e lda #<MainLoop 082e: 8d f9 03 sta MON_USRADDR+1 0831: a9 08 lda #>MainLoop 0833: 8d fa 03 sta MON_USRADDR+2 0836: a2 ff ldx #$ff 0838: 9a txs ;reset 6502 stack 0839: 20 3c 2e jsr JJ_ClearScreen ;clear screen 083c: 20 0c 0d jsr GameInit ;initialize game state 083f: 20 5c 10 jsr AskRestoreGame ;restore saved game if desired 0842: 20 62 08 jsr PrintIntro ;print intro message 0845: 20 3c 2e jsr JJ_ClearScreen ;clear screen 0848: 20 15 2e jsr JJ_DescribeRoom ;describe current room 084b: 4c 57 08 jmp MainLoop2 ;jump into main loop ; ; Main game loop. ; 084e: 20 3c 0e MainLoop jsr GetCommand ;get a command from user 0851: 20 03 2e jsr JJ_ProcessActions ;process actions for that verb/noun 0854: 20 b7 0d jsr DecrementLampLevel ;decrement the lamp level 0857: a9 00 MainLoop2 lda #$00 0859: 8d bc 30 sta parsed_verb_idx ;zero out the verb 085c: 20 03 2e jsr JJ_ProcessActions ;process occurrences 085f: 4c 4e 08 jmp MainLoop ;loop ; ; Prints the introductory screen. ; 0862: 20 3c 2e PrintIntro jsr JJ_ClearScreen ;clear text screen 0865: 20 54 2e jsr InA_GetInlineData 0868: 96 08 .dd2 msg_intro1 086a: 20 36 2e jsr JJ_PrintString ;print first part of message 086d: 20 93 2e jsr InA_GetIndirectValue 0870: 53 30 .dd2 adventure_vers 0872: 20 48 2e jsr JJ_PrintSignedDec ;print version number 0875: 20 54 2e jsr InA_GetInlineData 0878: b8 08 .dd2 msg_intro2 087a: 20 36 2e jsr JJ_PrintString 087d: 20 54 2e jsr InA_GetInlineData 0880: 25 0b .dd2 msg_intro3 0882: 20 4b 2e jsr JJ_PrintFlashing ;please don't copy 0885: 20 54 2e jsr InA_GetInlineData 0888: 37 0b .dd2 msg_intro4 088a: 20 36 2e jsr JJ_PrintString 088d: 20 54 2e jsr InA_GetInlineData ;get pointer to intro text again (why?) 0890: b8 08 .dd2 msg_intro2 0892: 20 39 2e jsr JJ_GetInput ;wait for user to hit return 0895: 60 rts ; ; Intro message, formatted for 40 columns. ; 0896: 2a 20 41 44+ msg_intro1 .zstr ‘* ADAMS ADVENTURE * (VERSION 1.2/’ 08b8: 29 0d 28 43+ msg_intro2 .zstr ‘)’,$0d,‘(C) ADVENTURE BOX 3435 LONGWOOD FL 327’ + ‘50’,$0d,‘ THIS PROGRAM WILL ALLOW YOU TO HAVE’ + ‘ AN ADVENTURE WITHOUT EVER LEAVING YOUR’,$0d + ‘ ARMCHAIR! YOU WILL FIND YOURSELF IN A’,$0d + ‘ STRANGE NEW WORLD. YOU'LL BE ABLE TO’,$0d,‘ E’ + ‘XAMINE, TAKE AND OTHERWISE MANIPULATE THE OBJ’ + ‘ECTS YOU FIND THERE. YOU WILL’,$0d,‘ ALSO BE A’ + ‘BLE TO TRAVEL FROM LOCATION TO LOCATION.’,$0d + $0d,‘ I'LL BE YOUR PUPPET IN THIS ADVENTURE. Y’ + ‘OU COMMAND ME WITH 2 WORD ENGLISH’,$0d,‘ SENTE’ + ‘NCES. I DO HAVE OVER A 120 WORD’,$0d,‘ VOCABUL’ + ‘ARY SO IF A WORD DOESN'T WORK’,$0d,‘ TRY ANOTH’ + ‘ER!’,$0d,$0d,‘ SOME COMMANDS I KNOW: HELP, SAV’ + ‘E GAME,’,$0d,‘ QUIT, SCORE, TAKE INVENTORY.’ + $0d,$0d,‘THE AUTHOR HAS WORKED OVER A YEAR ON’ + $0d,‘THIS PROGRAM SO ’ 0b25: 50 4c 45 41+ msg_intro3 .zstr ‘PLEASE DON'T COPY’ 0b37: 20 4f 52 0d+ msg_intro4 .zstr ‘ OR’,$0d,‘ACCEPT A PIRATED COPY! NOW HIT RETUR’ + ‘N!’ ; ; Prints a string that is N characters long. Does not output $00 bytes. ; ; On entry: ; $f0-f1: pointer to string ; A-reg: length of string ; ; On exit: ; (all registers preserved) ; 0b62: 20 57 2e PrintNChars jsr JJ_PushRegs ;preserve registers 0b65: 20 5d 2e jsr JJ_PushF0F1 ;preserve $f0-f1 0b68: 4c 78 0b jmp :Loop ;jump into loop with string len in A-reg ; ; Prints a string that starts with a length byte. Does not output $00 bytes. ; ; On entry: ; $f0-f1: pointer to start of string ; ; On exit: ; (all registers preserved) ; ]ptr .var $f0 {addr/2} 0b6b: 20 57 2e PrintL1Str jsr JJ_PushRegs ;preserve registers 0b6e: a0 00 ldy #$00 0b70: b1 f0 lda (]ptr),y ;get length byte 0b72: 20 5d 2e jsr JJ_PushF0F1 ;preserve $f0-f1 0b75: 20 51 2e jsr JJ_IncF0F1 ;advance pointer past it 0b78: c9 00 :Loop cmp #$00 ;reached the end? 0b7a: f0 12 beq :PopReturn ;yes, bail 0b7c: 38 sec 0b7d: e9 01 sbc #$01 ;reduce by 1 0b7f: 48 pha ;save remaining len 0b80: a0 00 ldy #$00 0b82: b1 f0 lda (]ptr),y ;get char 0b84: 20 51 2e jsr JJ_IncF0F1 ;advance pointer 0b87: 20 30 2e jsr JJ_PrintNonNull ;print char 0b8a: 68 pla ;restore remaining len 0b8b: 4c 78 0b jmp :Loop ;loop 0b8e: 20 60 2e :PopReturn jsr JJ_PopF0F1 ;restore $f0-f1 0b91: 20 5a 2e jsr JJ_PopRegs ;restore registers 0b94: 60 rts ; ; Prints a null-terminated string. ; ; On entry: ; $f0-f1: pointer to string ; ; On exit: ; (all registers preserved) ; ]str_ptr .var $f0 {addr/2} 0b95: 20 57 2e PrintString jsr JJ_PushRegs ;preserve registers 0b98: a9 01 lda #$01 ;set not flashing 0b9a: 8d af 2e PrintString1 sta noflash_flag 0b9d: 20 5d 2e jsr JJ_PushF0F1 ;preserve $f0-f1 0ba0: a0 00 :Loop ldy #$00 ;set to zero (and leave it there) 0ba2: b1 f0 lda (]str_ptr),y ;get char 0ba4: f0 e8 beq :PopReturn ;reached end, bail 0ba6: c9 0d cmp #$0d ;carriage return? 0ba8: f0 0b beq :DoPrint ;yes, print without modification 0baa: ac af 2e ldy noflash_flag ;flashing? 0bad: f0 04 beq :FlashMod ;yes, branch 0baf: 29 7f and #%01111111 ;make sure char has high bit clear 0bb1: d0 02 bne :DoPrint ;(branch always, unless char was $80) 0bb3: 09 c0 :FlashMod ora #%11000000 ;set bits so it'll be flashing after EOR #$80 0bb5: 20 30 2e :DoPrint jsr JJ_PrintNonNull ;print char 0bb8: 20 51 2e jsr JJ_IncF0F1 ;advance pointer 0bbb: 4c a0 0b jmp :Loop ; ; Prints a null-terminated string as flashing text. ; ; On entry: ; $f0-f1: pointer to string ; ; On exit: ; (all registers preserved) ; 0bbe: 20 57 2e PrintFlashStr jsr JJ_PushRegs ;preserve registers 0bc1: a9 00 lda #$00 ;set flashing 0bc3: f0 d5 beq PrintString1 ; ; Prints a carriage return (clear to EOL, move CH/CV to start of new line). ; 0bc5: 20 57 2e PrintCR jsr JJ_PushRegs 0bc8: a9 0d lda #$0d ;carriage return 0bca: d0 03 bne PrintNonNull1 ;(always) ; ; Prints a character, unless it's $00, in which case we return immediately. ; ; If we output a non-space character at the start of a line, we back up to the ; end of the previous text line and look for a non-space character. If we find ; one, we keep looking until we find a space, and then redraw all the characters ; at the start of a new line. (This is how sentences are broken across lines at ; word boundaries.) ; ; On entry: ; A-reg: character to print ($00-7f) ; ; On exit: ; (all registers preserved) ; 0bcc: 20 57 2e PrintNonNull jsr JJ_PushRegs ;preserve registers 0bcf: c9 00 PrintNonNull1 cmp #$00 ;is it a null byte? 0bd1: d0 04 bne :DoPrint ;no, print it 0bd3: 20 5a 2e :PullReturn jsr JJ_PopRegs ;restore registers 0bd6: 60 rts 0bd7: c9 61 :DoPrint cmp #‘a’ ;see if this is a lower-case letter 0bd9: 90 07 bcc :NotLower 0bdb: c9 7b cmp #$7b ;'z'+1 0bdd: b0 03 bcs :NotLower 0bdf: 38 sec ;it is; convert to upper case 0be0: e9 20 sbc #$20 0be2: ea :NotLower nop 0be3: 49 80 eor #$80 ;flip high bit (to high for norm, low for flash) 0be5: c9 8a cmp #$8a ;linefeed? 0be7: d0 02 bne :NotLF ;no, branch 0be9: a9 a0 lda #$a0 ;replace with space 0beb: 48 :NotLF pha ;save character to print on stack 0bec: c9 8d cmp #$8d ;carriage return? 0bee: d0 0d bne :NotCR ;no, branch ; Found a CR, clear screen to end of line. MON_VIDOUT will set CH to zero and ; increment CV. 0bf0: a4 21 ldy MON_WNDWDTH ;get width of window 0bf2: 88 :EraseLoop dey ;move left 0bf3: c4 24 cpy MON_CH ;have we reached current output position? 0bf5: 30 06 bmi :NotCR ;yes, continue on 0bf7: a9 a0 lda #$a0 0bf9: 91 28 sta (MON_BASL),y ;store a space 0bfb: d0 f5 bne :EraseLoop 0bfd: 68 :NotCR pla ;restore character to print 0bfe: 48 pha ;save it again 0bff: 20 fd fb jsr MON_VIDOUT ;print it to the screen (updates CH/CV and BASL) 0c02: 68 pla ;restore it 0c03: c9 8d cmp #$8d ;carriage return? 0c05: f0 cc beq :PullReturn ;yes, bail 0c07: a0 01 ldy #$01 0c09: c4 24 cpy MON_CH ;at posn 1 (so char was output at posn 0)? 0c0b: d0 c6 bne :PullReturn ;no, bail 0c0d: a4 25 ldy MON_CV ;are we at the top of the screen? 0c0f: f0 c2 beq :PullReturn ;yes, bail 0c11: a2 00 ldx #$00 ;init saved-char count to zero 0c13: c9 a0 cmp #$a0 ;was it a space? 0c15: f0 bc beq :PullReturn ;yes, return ; We output a non-space character at offset 0. Back up to the end of the ; previous line to see if this was part of a longer word. Push chars on the ; stack as we erase them, output a CR, then output the chars. ; ; For the case where this was not part of a longer word, we will erase and ; redraw the original character. 0c17: ea :BackupLoop nop 0c18: 20 10 fc jsr MON_BS ;back up one space (updates CH/CV and BASL) 0c1b: a4 24 ldy MON_CH 0c1d: b1 28 lda (MON_BASL),y ;get char 0c1f: c9 a0 cmp #“ ” ;is it a space? 0c21: f0 08 beq :FoundBreak ;yes, found break 0c23: e8 inx ;no, increment count 0c24: 48 pha ;push char on stack 0c25: a9 a0 lda #“ ” 0c27: 91 28 sta (MON_BASL),y ;erase screen char 0c29: d0 ec bne :BackupLoop ;loop 0c2b: 20 62 fc :FoundBreak jsr MON_CR ;move to start of new line 0c2e: 68 :OutputLoop pla ;pull char 0c2f: 20 fd fb jsr MON_VIDOUT ;write on screen 0c32: ca dex ;done yet? 0c33: d0 f9 bne :OutputLoop ;no, loop 0c35: f0 9c beq :PullReturn ;yes, bail ; ; Gets up to 18 characters of input from the player. Returns when the player ; hits Return or types the 18th character. Handles backspace. ; ; Keys are written to an input buffer, terminated with $00. ; ]buf_ptr .var $f0 {addr/2} 0c37: 20 57 2e GetInput jsr JJ_PushRegs ;preserve registers 0c3a: 20 5d 2e jsr JJ_PushF0F1 ;preserve $f0-f1 0c3d: 20 54 2e jsr InA_GetInlineData ;get pointer to input buffer in $f0-f1 0c40: 32 2f .dd2 kbd_scratch_buf-1 0c42: a0 19 ldy #25 ;erase 24 bytes (+1) 0c44: a9 00 lda #$00 0c46: 91 f0 :ClearLoop sta (]buf_ptr),y 0c48: 88 dey 0c49: d0 fb bne :ClearLoop ;stop before writting to offset zero ; 0c4b: 20 54 2e jsr InA_GetInlineData 0c4e: 33 2f .dd2 kbd_scratch_buf 0c50: a4 24 ldy MON_CH ;get current horizontal text position 0c52: a2 00 ldx #$00 ;set X-reg to zero so we can use as index 0c54: b1 28 :SetFlashCursor lda (MON_BASL),y ;read value from screen 0c56: 29 3f and #%00111111 ;upper-case, low ASCII 0c58: 09 40 ora #%01000000 ;make it flash 0c5a: 91 28 sta (MON_BASL),y ;store on screen ; 0c5c: ee b0 2e :KeyLoop inc kbd_rng_seed ;increment random seed 0c5f: d0 03 bne :NoInc 0c61: ee b1 2e inc kbd_rng_seed+1 0c64: ad 00 c0 :NoInc lda KBD ;check for input 0c67: 10 f3 bpl :KeyLoop ; 0c69: 91 28 sta (MON_BASL),y ;store character on screen (incl. Ctrl+H / Ctrl+M) 0c6b: 49 80 eor #%10000000 ;strip high bit 0c6d: 2c 10 c0 bit KBDSTRB ;reset keyboard strobe 0c70: c9 08 cmp #$08 ;backspace key? 0c72: d0 1e bne :NotBackspace ; 0c74: 20 7e 2e jsr InA_SubF0F1_Inline ;subtract current position from initial position 0c77: 33 2f .dd2 kbd_scratch_buf 0c79: d0 06 bne :NotAtStart ;haven't backed up to start yet, branch 0c7b: a9 40 lda #$40 ;flashing space 0c7d: 91 28 sta (MON_BASL),y ;store on screen 0c7f: d0 db bne :KeyLoop ;loop 0c81: 20 4e 2e :NotAtStart jsr JJ_DecF0F1 ;decrement buffer pointer 0c84: 8a txa ;A-reg=0 0c85: 81 f0 sta (]buf_ptr,x) ;write zero to buffer 0c87: a9 a0 lda #“ ” ;high-ASCII space 0c89: 91 28 sta (MON_BASL),y ;write to screen (replaces $88 we just wrote) 0c8b: c6 24 dec MON_CH ;decrement text position 0c8d: 88 dey 0c8e: 91 28 sta (MON_BASL),y ;write to screen (replaces char we backed over) 0c90: d0 c2 bne :SetFlashCursor ;(always, assuming there's prompt text so Y-reg != 0) ; 0c92: c9 0d :NotBackspace cmp #$0d ;return key? 0c94: d0 0a bne :AddChar ;no, branch ; Return key hit, return input to caller. 0c96: 20 60 2e :FinishInput jsr JJ_PopF0F1 ;restore $f0-f1 0c99: 20 33 2e jsr JJ_PrintCR ;clear to EOL, move CH/CV to start of new line 0c9c: 20 5a 2e jsr JJ_PopRegs ;restore registers 0c9f: 60 rts 0ca0: 81 f0 :AddChar sta (]buf_ptr,x) ;add character to buffer 0ca2: e6 24 inc MON_CH ;advance text position 0ca4: c8 iny 0ca5: 20 51 2e jsr JJ_IncF0F1 ;advance buffer position 0ca8: 20 7e 2e jsr InA_SubF0F1_Inline ;have we input 18 chars? 0cab: 45 2f .dd2 kbd_scratch_buf+18 0cad: f0 e7 beq :FinishInput ;yes, accept line and bail 0caf: d0 a3 bne :SetFlashCursor ;no, loop (always) ; ; Clears the full screen. Resets the scroll window top. ; 0cb1: 20 57 2e ClearScreen jsr JJ_PushRegs ;preserve registers 0cb4: a9 00 lda #$00 0cb6: 8d 59 30 sta screen_cleared? ;? 0cb9: 85 22 sta MON_WNDTOP ;reset scroll window 0cbb: 20 58 fc jsr MON_HOME ;clear it 0cbe: 20 5a 2e jsr JJ_PopRegs ;restore registers 0cc1: 60 rts ; ; Pushes registers onto stack and returns to caller. ; Order: P A X Y. ; ; On exit: ; (all registers preserved) ; 0cc2: 8d ab 2e PushRegs sta regsv_tmp_a ;save A-reg 0cc5: 08 php ;save P-reg 0cc6: 68 pla 0cc7: 8d ac 2e sta regsv_tmp_p 0cca: 68 pla ;pull return address off stack 0ccb: 8d ad 2e sta regsv_ret_addr 0cce: 68 pla 0ccf: 8d ae 2e sta regsv_ret_addr+1 0cd2: ee ad 2e inc regsv_ret_addr ;increment return address so we jump to 0cd5: d0 03 bne :NoInc ; byte after the JSR 0cd7: ee ae 2e inc regsv_ret_addr+1 0cda: ea :NoInc nop 0cdb: ad ac 2e lda regsv_tmp_p ;push P-reg 0cde: 48 pha 0cdf: ad ab 2e lda regsv_tmp_a ;push A-reg 0ce2: 48 pha 0ce3: 8a txa ;push X-reg 0ce4: 48 pha 0ce5: 98 tya ;push Y-reg 0ce6: 48 pha 0ce7: ad ac 2e lda regsv_tmp_p ;push P-reg 0cea: 48 pha 0ceb: ad ab 2e lda regsv_tmp_a ;restore A-reg 0cee: 28 plp ;restore P-reg 0cef: 6c ad 2e jmp (regsv_ret_addr) ;resume execution at caller (same as RTS) ; ; Pops registers off stack and returns to caller. ; Order: Y X A P ; ; On exit: ; (all registers restored from stack) ; 0cf2: 68 PopRegs pla ;pull return address 0cf3: 8d ad 2e sta regsv_ret_addr 0cf6: 68 pla 0cf7: 8d ae 2e sta regsv_ret_addr+1 0cfa: ee ad 2e inc regsv_ret_addr ;increment return address so we jump to 0cfd: d0 03 bne :NoInc ; byte after the JSR 0cff: ee ae 2e inc regsv_ret_addr+1 0d02: ea :NoInc nop 0d03: 68 pla ;pull Y-reg 0d04: a8 tay 0d05: 68 pla ;pull X-reg 0d06: aa tax 0d07: 68 pla ;pull A-reg 0d08: 28 plp ;pull P-reg 0d09: 6c ad 2e jmp (regsv_ret_addr) ; ; Initializes game state. Puts objects in default locations, clears flags, etc. ; ]item_init_ptr .var $f0 {addr/2} ]item_cur_ptr .var $f2 {addr/2} ]table_len .var $f5 {addr/1} 0d0c: 20 93 2e GameInit jsr InA_GetIndirectValue ;get max item value into $f0-f1 0d0f: 6f 30 .dd2 hdr_max_item 0d11: 20 84 2e jsr JJ_SetF4F5_F0F1 ;copy to $f4-f5 0d14: 20 87 2e jsr JJ_AddF0F1_F4F5 ;add to itself 0d17: 20 84 2e jsr JJ_SetF4F5_F0F1 ;save in $f4-f5 0d1a: 20 93 2e jsr InA_GetIndirectValue ;get pointer to item location data 0d1d: 26 2f .dd2 item_rooms_ptr 0d1f: 20 81 2e jsr JJ_SetF2F3_F0F1 ;copy pointer to $f2-f3 0d22: 20 93 2e jsr InA_GetIndirectValue ;get pointer to ? in $f0-f1 0d25: 2a 2f .dd2 item_initroom_ptr ; Initialize item locations. 0d27: a0 00 ldy #$00 0d29: b1 f0 :Loop lda (]item_init_ptr),y ;get initial location 0d2b: 91 f2 sta (]item_cur_ptr),y ;copy to location data area 0d2d: 20 51 2e jsr JJ_IncF0F1 ;advance src ptr 0d30: 20 6c 2e jsr JJ_IncF2F3 ;advance dst ptr 0d33: 20 63 2e jsr JJ_DecF4F5 ;decrement length 0d36: a5 f5 lda ]table_len ;done yet? 0d38: 10 ef bpl :Loop ;no, loop ; 0d3a: ad 77 30 lda hdr_start_room ;set initial player location 0d3d: 8d e9 30 sta current_room 0d40: ad 78 30 lda hdr_start_room+1 0d43: 8d ea 30 sta current_room+1 0d46: ad 7b 30 lda hdr_lamp_capacity ;fill lightsource object 0d49: 8d 01 31 sta lamp_fuel_level 0d4c: ad 7c 30 lda hdr_lamp_capacity+1 0d4f: 8d 02 31 sta lamp_fuel_level+1 0d52: a9 00 lda #$00 ;clear debug flag 0d54: 8d 7d 30 sta debug_flag ; Clear all action flags (0-31). 0d57: 20 54 2e jsr InA_GetInlineData ;get pointer to flags 0d5a: c9 30 .dd2 action_flags 0d5c: a0 1f ldy #31 0d5e: 91 f0 :Loop sta (]item_init_ptr),y ;store zero 0d60: 88 dey 0d61: 10 fb bpl :Loop 0d63: 60 rts ; ; Finds a match for the trimmed string in the list of words. The caller points ; to either the verb list or the noun list, which are padded to be the same ; length. ; ; The trimmed word buffer and the items in the word list are both padded with ; trailing $00 bytes, so we can simply compare all N bytes (where N is ; configurable, 4 in this case). ; ; If we match on an alias, we return the index of the "base" word, and replace ; the word in the trim buffer with the base. ; ; On entry: ; $f0-f1: pointer to verb or noun collection ; (trimmed input word at $3080) ; ; On exit: ; Z-flag set if match found ; (word index in $309d) ; ]trim_verb .var $f0 {addr/2} ]word_list .var $f2 {addr/2} 0d64: ad 6b 30 FindWord lda hdr_max_nounverb ;get dictionary size 0d67: 8d 9e 30 sta tmp_save_reg2 ;use as counter 0d6a: 20 81 2e jsr JJ_SetF2F3_F0F1 ;copy word collection pointer into $f2-f3 0d6d: a9 00 lda #$00 0d6f: 8d 9d 30 sta tmp_save_reg1 0d72: 20 54 2e jsr InA_GetInlineData ;get pointer to trimmed word in $f0-f1 0d75: 80 30 .dd2 word_trim_buf ;this points at first char, but dictionary words 0d77: 20 4e 2e jsr JJ_DecF0F1 ; start with $00 or '*', so back up 1 to match ; 0d7a: ac 69 30 :CmpWord ldy hdr_word_len ;get word length (3/4/5) 0d7d: b1 f0 :CmpLoop lda (]trim_verb),y ;get char from trimmed input buffer 0d7f: d1 f2 cmp (]word_list),y ;compare to word in list 0d81: d0 22 bne :TryNext ;didn't match, branch 0d83: 88 dey ;tried all 4? 0d84: d0 f7 bne :CmpLoop ;no, branch ; If this word was an alias, back up until we find one that isn't. 0d86: b1 f2 :DeAlias lda (]word_list),y ;get first char (Y-reg=0) 0d88: c9 2a cmp #‘*’ ;is it an asterisk? 0d8a: d0 0e bne :NotAlias ;no, this word is not an alias 0d8c: ae 69 30 ldx hdr_word_len ;back up a full word 0d8f: 20 69 2e :BackLoop jsr JJ_DecF2F3 ;decrement pointer 0d92: ca dex ;done yet? 0d93: 10 fa bpl :BackLoop ;no, loop 0d95: ce 9d 30 dec tmp_save_reg1 ;adjust result value 0d98: d0 ec bne :DeAlias ;branch always (unless this was first word in list) ; Copy word from list back to trim buffer. 0d9a: ac 69 30 :NotAlias ldy hdr_word_len ;get word length 0d9d: b1 f2 :CopyLoop lda (]word_list),y ;copy word from word list into trim buffer; this 0d9f: 91 f0 sta (]trim_verb),y ; is a no-op unless the word was an alias 0da1: 88 dey 0da2: d0 f9 bne :CopyLoop 0da4: 60 rts ;return with Z-flag=1 0da5: ac 69 30 :TryNext ldy hdr_word_len ;get full word length 0da8: 20 6c 2e :IncrLoop jsr JJ_IncF2F3 ;increment pointer until we're at start of next 0dab: 88 dey ;done yet? 0dac: 10 fa bpl :IncrLoop ;no, loop 0dae: ee 9d 30 inc tmp_save_reg1 ;increment result value 0db1: ce 9e 30 dec tmp_save_reg2 ;done yet? 0db4: 10 c4 bpl :CmpWord ;no, loop 0db6: 60 rts ;return with Z-flag=0 ; ; Reduces the lamp fuel level by 1, unless the lamp is in room 0 ("nowhere"). ; If we drop below 25, print a warning. If we drop below 0, set the ; "lightsource empty" flag. ; ; It's up to the game to provide an action that removes the lightsource object ; (#9) from the player's inventory, e.g. replacing it with "empty lamp". If ; they don't, the object will continue to provide light, and we will continue to ; decrement the counter (until it rolls under). ; ]item_room .var $f0 {addr/2} DecrementLampLevel 0db7: 20 93 2e jsr InA_GetIndirectValue 0dba: 26 2f .dd2 item_rooms_ptr 0dbc: a0 12 ldy #18 ;object #9 (lamp) 0dbe: b1 f0 lda (]item_room),y ;get current room (low byte) 0dc0: c8 iny 0dc1: 11 f0 ora (]item_room),y ;OR with current room (high byte) 0dc3: f0 26 beq :Return ;if it's in room zero, don't modify the fuel level ; 0dc5: 20 93 2e jsr InA_GetIndirectValue ;get lamp level in $f0-f1 0dc8: 01 31 .dd2 lamp_fuel_level 0dca: 20 4e 2e jsr JJ_DecF0F1 ;decrement 0dcd: 20 90 2e jsr InA_SetIndirectValue ;store value 0dd0: 01 31 .dd2 lamp_fuel_level 0dd2: ad 02 31 lda lamp_fuel_level+1 ;fuel level high byte nonzero? 0dd5: d0 14 bne :Return ;yes, got fuel, bail 0dd7: ad 01 31 lda lamp_fuel_level ;check low byte 0dda: 30 0f bmi :Return ;sub-zero, we've already complained, bail 0ddc: d0 0e bne :WarnLow ;not zero yet, print warning ; Counter just hit zero. Tell the player the bad news. 0dde: a9 ff lda #$ff 0de0: 8d d9 30 sta lamp_empty_flag ;set flag #16, indicating lamp is empty 0de3: 20 54 2e jsr InA_GetInlineData 0de6: 26 0e .dd2 msg_light_out 0de8: 20 4b 2e jsr JJ_PrintFlashing ;print "light has run out" message 0deb: 60 :Return rts 0dec: c9 19 :WarnLow cmp #25 ;do we have at least 25 moves left? 0dee: 10 fb bpl :Return ;yes, bail 0df0: 20 54 2e jsr InA_GetInlineData ;no, print warning message 0df3: 09 0e .dd2 msg_light_runs_out 0df5: 20 4b 2e jsr JJ_PrintFlashing ;flashing for emphasis 0df8: 20 93 2e jsr InA_GetIndirectValue ;get fuel level 0dfb: 01 31 .dd2 lamp_fuel_level 0dfd: 20 48 2e jsr JJ_PrintSignedDec ;print as integer 0e00: 20 54 2e jsr InA_GetInlineData 0e03: 1e 0e .dd2 msg_light_turns 0e05: 20 4b 2e jsr JJ_PrintFlashing 0e08: 60 rts msg_light_runs_out 0e09: 0d 20 4c 49+ .zstr $0d,‘ LIGHT RUNS OUT IN ’ 0e1e: 20 54 55 52+ msg_light_turns .zstr ‘ TURNS’,$0d 0e26: 0d 20 4c 49+ msg_light_out .zstr $0d,‘ LIGHT HAS RUN OUT!’,$0d ; ; Gets a line of input from the player, tokenizes it, and parse it into ; verb/noun. Converts single-character built-in commands like "I" and "N" into ; verbs. ; ; This does not return until it has received valid input. ; ; On exit: ; (parsed_verb_idx and parsed_noun_idx set) ; (input trim buffer holds trimmed noun) ; ]kbd_buf .var $f4 {addr/2} 0e3c: 20 54 2e GetCommand jsr InA_GetInlineData 0e3f: 3c 0f .dd2 msg_prompt 0e41: 20 36 2e jsr JJ_PrintString ;print prompt for command 0e44: 20 39 2e jsr JJ_GetInput ;get a buffer full of keystrokes 0e47: 20 54 2e jsr InA_GetInlineData ;get pointer to input buffer 0e4a: 33 2f .dd2 kbd_scratch_buf 0e4c: 20 84 2e jsr JJ_SetF4F5_F0F1 ;copy kbd input pointer to $f4-f5 ; Look for a verb. 0e4f: 20 94 0f jsr TrimWord ;copy to buf, trimming whitespace; advances $f4-f5 0e52: ad 81 30 lda word_trim_buf+1 ;test for single-char command 0e55: d0 51 bne :MultiChar ;multi-char, branch ; Handle some built-in single-character commands. 0e57: ad 80 30 lda word_trim_buf ;get first char 0e5a: c9 58 cmp #‘X’ ;was it X? 0e5c: d0 06 bne :CheckP ;no, branch 0e5e: a9 00 lda #$00 ;set debug flat to 0 0e60: 8d 7d 30 :SetDebug sta debug_flag 0e63: 60 rts 0e64: c9 50 :CheckP cmp #‘P’ ;was it P? 0e66: d0 04 bne :CheckT ;no, branch 0e68: a9 01 lda #$01 ;set debug flag to 1 0e6a: d0 f4 bne :SetDebug 0e6c: c9 54 :CheckT cmp #‘T’ ;was it T? 0e6e: d0 04 bne :CheckI ;no, branch 0e70: a9 02 lda #$02 ;set debug flag to 2 0e72: d0 ec bne :SetDebug 0e74: c9 49 :CheckI cmp #‘I’ ;inventory? 0e76: d0 17 bne :CheckDir ;no, branch 0e78: a9 4e lda #‘N’ ;yes, stuff in chars to make it "INVE" 0e7a: 8d 81 30 sta word_trim_buf+1 0e7d: a9 56 lda #‘V’ 0e7f: 8d 82 30 sta word_trim_buf+2 0e82: a9 45 lda #‘E’ 0e84: 8d 83 30 sta word_trim_buf+3 0e87: d0 1f bne :MultiChar ;handle as multi-char entry :direction_chars 0e89: 4e 53 45 57+ .str ‘NSEWUD’ ;north/south/east/west/up/down ]dc_ptr .var $f0 {addr/2} 0e8f: 20 54 2e :CheckDir jsr InA_GetInlineData ;get pointer to direction chars, -1 so result 0e92: 88 0e .dd2 :direction_chars-1 ; will be [1,6] instead of [0,5] 0e94: a0 06 ldy #6 ;6 chars in direction_chars 0e96: d1 f0 :DirLoop cmp (]dc_ptr),y ;match? 0e98: f0 05 beq :FoundDir ;yes, branch 0e9a: 88 dey ;done yet? 0e9b: d0 f9 bne :DirLoop ;no, branch 0e9d: f0 09 beq :MultiChar ;(always) 0e9f: 8c be 30 :FoundDir sty parsed_noun_idx ;save noun index (1-6) 0ea2: a9 01 lda #$01 0ea4: 8d bc 30 sta parsed_verb_idx 0ea7: 60 rts ; Find a match for a multi-character verb. 0ea8: 20 93 2e :MultiChar jsr InA_GetIndirectValue ;get pointer to verb table 0eab: 30 2f .dd2 verb_words_ptr 0ead: 20 64 0d jsr FindWord ;look for a matching word 0eb0: f0 1b beq :GotVerb ;found match, branch 0eb2: 20 54 2e jsr InA_GetInlineData ;didn't match, complain 0eb5: 53 0f .dd2 msg_dont_how 0eb7: 20 36 2e jsr JJ_PrintString 0eba: 20 54 2e jsr InA_GetInlineData 0ebd: 80 30 .dd2 word_trim_buf 0ebf: 20 4b 2e jsr JJ_PrintFlashing ;print verb, flashing 0ec2: 20 54 2e jsr InA_GetInlineData 0ec5: 6a 0f .dd2 msg_dont_how2 0ec7: 20 36 2e jsr JJ_PrintString 0eca: 4c 3c 0e jmp GetCommand ;go get a new command (w/o actions or lamp--) 0ecd: ad 9d 30 :GotVerb lda tmp_save_reg1 ;save verb index in global 0ed0: 8d bc 30 sta parsed_verb_idx ; Now look for a noun. 0ed3: 20 94 0f jsr TrimWord ;copy to buf, trimming whitespace; advances $f4-f5 0ed6: ad 80 30 lda word_trim_buf ;get first char of noun 0ed9: 8d be 30 sta parsed_noun_idx ;if it's $00, set the noun index to zero 0edc: f0 2b beq :Chk3 ; and branch (otherwise, parsed_noun_idx is garbage) 0ede: 20 93 2e jsr InA_GetIndirectValue ;get pointer to noun table 0ee1: 2e 2f .dd2 noun_words_ptr 0ee3: 20 64 0d jsr FindWord ;look for a matching word 0ee6: f0 1b beq :GotNoun ;found match, branch 0ee8: 20 54 2e jsr InA_GetInlineData ;didn't match, complain 0eeb: 78 0f .dd2 msg_dont_what 0eed: 20 36 2e jsr JJ_PrintString 0ef0: 20 54 2e jsr InA_GetInlineData ;print noun, flashing 0ef3: 80 30 .dd2 word_trim_buf 0ef5: 20 4b 2e jsr JJ_PrintFlashing 0ef8: 20 54 2e jsr InA_GetInlineData 0efb: 8d 0f .dd2 msg_dont_what2 0efd: 20 36 2e jsr JJ_PrintString 0f00: 4c 3c 0e jmp GetCommand ;go get a new command (w/o actions or lamp--) 0f03: ad 9d 30 :GotNoun lda tmp_save_reg1 ;save noun index in global 0f06: 8d be 30 sta parsed_noun_idx ; Check for a third word. $f4-f5 points at end of noun in kbd buf. 0f09: a0 00 :Chk3 ldy #$00 0f0b: b1 f4 :Chk3Loop lda (]kbd_buf),y ;get char 0f0d: d0 01 bne :AfterSpace ;not $00, check it 0f0f: 60 rts ;all good, return 0f10: c8 :AfterSpace iny ;advance to next char 0f11: c9 20 cmp #$20 ;was this one a space? 0f13: f0 f6 beq :Chk3Loop ;yes, keep looking 0f15: 20 54 2e jsr InA_GetInlineData ;no, they entered 3+ words 0f18: 20 0f .dd2 msg_max_2words 0f1a: 20 4b 2e jsr JJ_PrintFlashing ;complain 0f1d: 4c 3c 0e jmp GetCommand ;go get a new command (w/o actions or lamp--) 0f20: 20 55 53 45+ msg_max_2words .zstr ‘ USE NO MORE THAN 2 WORDS!’,$0d ;max two per customer 0f3c: 20 2d 2d 3e+ msg_prompt .zstr ‘ --> WHAT SHALL I DO? ’ ;basic command prompt 0f53: 0d 49 20 44+ msg_dont_how .zstr $0d,‘I DON'T KNOW HOW TO "’ ;unknown verb 0f6a: 22 20 53 4f+ msg_dont_how2 .zstr ‘" SOMETHING.’,$0d 0f78: 0d 49 20 44+ msg_dont_what .zstr $0d,‘I DON'T KNOW WHAT "’ ;unknown noun 0f8d: 22 20 49 53+ msg_dont_what2 .zstr ‘" IS.’,$0d ; ; Trims a word, copying it while stripping leading/trailing whitespace. ; ; On entry: ; $f4-f5: pointer to source data (key input buffer) ; ; On exit: ; $f4-f5: moved to first byte past end of input string ; (trimmed word in output buffer, terminated with $00) ; • Clear variables ]trim_buf .var $f0 {addr/2} ]kbd_buf .var $f4 {addr/2} 0f94: 20 75 2e TrimWord jsr JJ_PushF2F3 ;preserve $f2-f3 0f97: a9 00 lda #$00 0f99: a0 17 ldy #23 0f9b: 20 54 2e jsr InA_GetInlineData ;get buffer pointer ($3080) in $f0-f1 0f9e: 80 30 .dd2 word_trim_buf 0fa0: 20 81 2e jsr JJ_SetF2F3_F0F1 ;copy $f0-f1 to $f2-f3 (why?) 0fa3: 91 f0 :ClearLoop sta (]trim_buf),y ;clear buffer to zeroes 0fa5: 88 dey 0fa6: 10 fb bpl :ClearLoop ; 0fa8: a2 00 ldx #$00 ;found-non-space flag 0faa: a0 00 ldy #$00 ;always zero 0fac: b1 f4 :GetLoop lda (]kbd_buf),y ;get char 0fae: 20 66 2e jsr JJ_IncF4F5 ;advance kbd buf pointer (preserves flags) 0fb1: d0 04 bne :CheckSpace ;if it's not $00, branch 0fb3: 20 78 2e :PopReturn jsr JJ_PopF2F3 ;all done; restore $f2-f3 0fb6: 60 rts 0fb7: c9 20 :CheckSpace cmp #‘ ’ ;is it a space? 0fb9: d0 06 bne :NotSpace ;no, branch 0fbb: e0 00 cpx #$00 ;have we found a non-space char yet? 0fbd: f0 ed beq :GetLoop ;no, skip over leading space 0fbf: d0 f2 bne :PopReturn ;yes, found end of word; branch 0fc1: 91 f0 :NotSpace sta (]trim_buf),y ;copy to trim buffer 0fc3: 20 51 2e jsr JJ_IncF0F1 ;advance output pointer 0fc6: a2 01 ldx #$01 ;set found-non-space flag 0fc8: d0 e2 bne :GetLoop ;(always) ; ; Get item's current location. ; ; On entry: ; $f0-f1: index of item ; ; On exit: ; $f0-f1: pointer to location data in item table ; A-reg: room number ; (X-reg and Y-reg preserved) ; 0fca: 8e 9d 30 GetItemLocation stx tmp_save_reg1 0fcd: 20 6f 2e jsr JJ_PushF4F5 ;preserve $f4-f5 0fd0: 20 84 2e jsr JJ_SetF4F5_F0F1 ;set $f4-f5 = $f0-f1 0fd3: 20 87 2e jsr JJ_AddF0F1_F4F5 ;$f0-f1 += $f4-f5 (i.e. double the value) 0fd6: 20 84 2e jsr JJ_SetF4F5_F0F1 ;set $f4-f5 = $f0-f1 0fd9: 20 93 2e jsr InA_GetIndirectValue ;get pointer to item room data 0fdc: 26 2f .dd2 item_rooms_ptr 0fde: 20 87 2e jsr JJ_AddF0F1_F4F5 ;add doubled index 0fe1: 20 72 2e jsr JJ_PopF4F5 ;restore $f4-f5 0fe4: a2 00 ldx #$00 0fe6: a1 f0 lda (]trim_buf,x) ;get room number 0fe8: ae 9d 30 ldx tmp_save_reg1 0feb: 60 rts ; ; Prints a 16-bit integer as a signed decimal value. ; ; On entry: ; $f0-f1: value to print ; ]value .var $f0 {addr/2} ]rem .var $f2 {addr/1} ]out_ptr .var $f4 {addr/2} 0fec: 20 8a 2e PrintSignedDec jsr JJ_PushFullState ;preserve all regs and ZP 0fef: a5 f0 lda ]value ;stash value in temporary mem 0ff1: 8d 9d 30 sta tmp_save_reg1 0ff4: a5 f1 lda ]value+1 0ff6: 8d 9e 30 sta tmp_save_reg2 0ff9: 20 54 2e jsr InA_GetInlineData ;get pointer to output buffer, past the length byte 0ffc: b6 30 .dd2 dec_outbuf+1 0ffe: a0 05 ldy #$05 ;max of six chars (e.g. "-32767") 1000: a9 00 :ClearLoop lda #$00 1002: 91 f0 sta (]value),y ;zero out the output buffer 1004: 88 dey 1005: 10 f9 bpl :ClearLoop ; 1007: ad 9e 30 lda tmp_save_reg2 ;check the high byte 100a: 10 16 bpl :IsPos ;it's positive, branch 100c: a9 2d lda #‘-’ 100e: 8d b6 30 sta dec_outbuf+1 ;output a minus sign 1011: 38 sec ;negate the value so we're working 1012: a9 00 lda #$00 ; with a positive number 1014: ed 9d 30 sbc tmp_save_reg1 ; (this has classic issue with -32768) 1017: 8d 9d 30 sta tmp_save_reg1 101a: a9 00 lda #$00 101c: ed 9e 30 sbc tmp_save_reg2 101f: 8d 9e 30 sta tmp_save_reg2 1022: 20 54 2e :IsPos jsr InA_GetInlineData ;get pointer to output buffer 1025: b6 30 .dd2 dec_outbuf+1 1027: 20 84 2e jsr JJ_SetF4F5_F0F1 ;put pointer in $f4-f5 102a: 20 93 2e jsr InA_GetIndirectValue ;load positive value into $f0-f1 102d: 9d 30 .dd2 tmp_save_reg1 102f: a0 05 ldy #$05 ;start at offset 5 1031: 20 81 2e :OutLoop jsr JJ_SetF2F3_F0F1 ;set $f2-f3 to $f0-f1 1034: 20 54 2e jsr InA_GetInlineData ;set $f0-f1 to 10 1037: 0a 00 .dd2 10 1039: 20 21 2e jsr JJ_Divide16 ;divide by 10 103c: a5 f2 lda ]rem ;get remainder 103e: 09 30 ora #‘0’ ;convert to ASCII digit 1040: 91 f4 sta (]out_ptr),y ;store in output buffer 1042: a5 f0 lda ]value ;are we done yet? 1044: 05 f1 ora ]value+1 1046: f0 03 beq :OutputDone ;yes, branch 1048: 88 dey ;no, reduce index 1049: d0 e6 bne :OutLoop ;and loop ; 104b: a0 06 :OutputDone ldy #$06 104d: 8c b5 30 sty dec_outbuf ;set the length to 6 characters 1050: 20 54 2e jsr InA_GetInlineData ;get pointer to output buffer 1053: b5 30 .dd2 dec_outbuf 1055: 20 42 2e jsr JJ_PrintL1Str ;print string, ignoring leading $00 bytes 1058: 20 8d 2e jsr JJ_PopFullState ;restore all regs and ZP 105b: 60 rts ; ; Asks the user if they want to restore a saved game. If the answer is yes, ; this proceeds to do the restore. ; 105c: 20 54 2e AskRestoreGame jsr InA_GetInlineData 105f: 0a 11 .dd2 msg_restore_game 1061: 20 36 2e jsr JJ_PrintString ;ask if they want to restore a game 1064: 20 39 2e jsr JJ_GetInput ;get line of input 1067: ad 33 2f lda kbd_scratch_buf ;check first char 106a: c9 59 cmp #‘Y’ ;yes? 106c: f0 05 beq :DoLoad ;yes, do it 106e: c9 4e cmp #‘N’ ;no? 1070: d0 ea bne AskRestoreGame ;none of the above, loop 1072: 60 rts 1073: 20 1b 2e :DoLoad jsr JJ_AskDiskOrTape ;ask if they want disk or tape 1076: ad b2 2e lda use_disk_flag ;check flag 1079: f0 19 beq :FromTape1 ;go do tape 107b: 20 54 2e jsr InA_GetInlineData ;get pointer to DOS command string 107e: e3 10 .dd2 dos_load_cmd 1080: a9 31 lda #‘1’ ;set filename for part 1 1082: 8d ef 10 sta dos_load_cmd+12 1085: ad 57 30 lda adventure_num ;set adventure number in filename 1088: 8d f0 10 sta dos_load_cmd+13 ; (will be a control character) 108b: 20 1e 2e jsr JJ_PrintStringCOUT ;issue DOS command to load file #1 108e: ee ef 10 inc dos_load_cmd+12 ;increment digit for part 2 1091: 4c 97 10 jmp :CheckPart1 1094: 20 33 11 :FromTape1 jsr ReadTape ;read data from tape ; 1097: 20 93 2e :CheckPart1 jsr InA_GetIndirectValue ;get adventure number (12 in our case) 109a: 57 30 .dd2 adventure_num 109c: 20 7b 2e jsr InA_SubF0F1_Ind ;subtract value we read from file 109f: 33 2f .dd2 kbd_scratch_buf 10a1: f0 0b beq :Part1Good ;if they match, continue 10a3: 20 54 2e jsr InA_GetInlineData 10a6: f3 10 .dd2 msg_bad_save 10a8: 20 36 2e jsr JJ_PrintString ;complain about saved game 10ab: 4c 5c 10 jmp AskRestoreGame ;ask again ; Copy $2f35-2f71 to $30c7-3103 (flags, counters, current room etc.). 10ae: a2 3c :Part1Good ldx #$3c 10b0: bd 35 2f :Loop lda save_game_data,x ;read from scratch area 10b3: 9d c7 30 sta counter_register,x ;write to state area 10b6: ca dex 10b7: 10 f7 bpl :Loop ; 10b9: ad b2 2e lda use_disk_flag ;disk or tape? 10bc: f0 0b beq :FromTape2 ;tape, branch 10be: 20 54 2e jsr InA_GetInlineData 10c1: e3 10 .dd2 dos_load_cmd 10c3: 20 1e 2e jsr JJ_PrintStringCOUT ;issue DOS command to load file #2 10c6: 4c cc 10 jmp :ReadCommon 10c9: 20 33 11 :FromTape2 jsr ReadTape ;read part 2 from tape ; Copy item location data from file #2. ]item_room .var $f0 {addr/2} 10cc: a0 00 :ReadCommon ldy #$00 10ce: a2 ff ldx #$ff ;init to -1 10d0: 20 93 2e jsr InA_GetIndirectValue 10d3: 26 2f .dd2 item_rooms_ptr 10d5: e8 :Loop inx 10d6: bd 33 2f lda kbd_scratch_buf,x ;copy location value 10d9: 91 f0 sta (]item_room),y 10db: c8 iny 10dc: c8 iny 10dd: ec 6f 30 cpx hdr_max_item ;all items done? 10e0: d0 f3 bne :Loop ;no, loop 10e2: 60 rts ; DOS 3.3 load command. The last two characters are modified by the code. 10e3: 0d 04 42 4c+ dos_load_cmd .zstr $0d,$04,‘BLOAD AREC2’,$05,$0d 10f3: 20 42 41 44+ msg_bad_save .zstr ‘ BAD SAVE FILE FOUND!’,$0d msg_restore_game 110a: 57 41 4e 54+ .zstr ‘WANT TO RESTORE PREVIOUSLY’,$0d,‘ SAVED GAME? ’ ; ; Reads data from tape. We're expecting 256 bytes. ; 1133: a9 33 ReadTape lda #<kbd_scratch_buf ;set buffer pointer 1135: 85 3c sta MON_A1L 1137: a9 2f lda #>kbd_scratch_buf 1139: 85 3d sta MON_A1H 113b: 20 fd fe jsr MON_READ ;invoke monitor tape read routine 113e: 60 rts 113f: 74 68 72 6f+ .align $0400 (705 bytes) J_SetIndirectValue 1400: 4c 55 14 jmp SetIndirectValue 1403: 4c eb 14 J_PushF0F1 jmp PushF0F1 1406: 4c f3 14 J_PopF0F1 jmp PopF0F1 1409: 4c db 14 J_PushF4F5 jmp PushF4F5 140c: 4c e3 14 J_PopF4F5 jmp PopF4F5 140f: 4c fb 14 J_PushF2F3 jmp PushF2F3 1412: 4c 03 15 J_PopF2F3 jmp PopF2F3 1415: 4c 34 15 J_PushFullState jmp PushFullState 1418: 4c 69 15 J_PopFullState jmp PopFullState 141b: 4c 8e 15 J_IncF0F1 jmp IncF0F1 141e: 4c 97 15 J_IncF4F5 jmp IncF4F5 1421: 4c a1 15 J_IncF2F3 jmp IncF2F3 1424: 4c c5 15 J_DecF0F1 jmp DecF0F1 1427: 4c bd 15 J_DecF4F5 jmp DecF4F5 142a: 4c cd 15 J_DecF2F3 jmp DecF2F3 142d: 4c ea 15 J_SetF2F3_F0F1 jmp SetF2F3_F0F1 1430: 4c e2 15 J_SetF4F5_F0F1 jmp SetF4F5_F0F1 1433: 4c 29 16 J_SubF0F1_Ind jmp SubF0F1_Ind J_SubF0F1_Inline 1436: 4c 18 16 jmp SubF0F1_Inline 1439: 4c 3d 16 J_AddF0F1_F4F5 jmp AddF0F1_F4F5 143c: 4c 64 16 J_GetInlineData jmp GetInlineData J_GetIndirectValue 143f: 4c 4f 16 jmp GetIndirectValue 1442: 4c 13 15 J_PushF6F7 jmp PushF6F7 1445: 4c 0b 15 J_PopF6F7 jmp PopF6F7 1448: 4c 23 15 J_PushF8F9 jmp PushF8F9 144b: 4c 1b 15 J_PopF8F9 jmp PopF8F9 144e: 4c 2b 15 J_IncF8F9 jmp IncF8F9 1451: 30 1a ind_jmp_1 .dd2 $1a30 1453: d8 18 ind_jmp_2 .dd2 $18d8 ; ; Stores a 16-bit value to a location specified by a pointer in inline data that ; follows the caller's caller. ; ; On entry: ; $f0-f1: value to store ; ; On exit: ; $fc-fd: pointer from inline data ; ]arg .var $f0 {addr/2} ]dest_ptr .var $fc {addr/2} SetIndirectValue 1455: 20 57 2e jsr JJ_PushRegs 1458: 20 6a 14 jsr GetCCInlineValue ;get pointer in $fc-fd 145b: a0 00 ldy #$00 145d: a5 f0 lda ]arg 145f: 91 fc sta (]dest_ptr),y ;write value to pointer 1461: c8 iny 1462: a5 f1 lda ]arg+1 1464: 91 fc sta (]dest_ptr),y 1466: 20 5a 2e jsr JJ_PopRegs 1469: 60 rts ; ; Gets the inline data that follows the caller's caller, and modifies the return ; address to skip over it. The data is usually a pointer, so this is a way to ; load a fixed address into $fc-fd. ; ; The caller does this: ; JSR func ; .dd2 <addr> ; Then func does this: ; JSR PushRegs (pushes 4 Y/X/A/P on stack) ; JSR <this function> ; ; So the stack is: ; 2 byte caller return address ; 4 byte saved registers ; 2 byte caller's caller return address ; ; So we need to get the caller's caller address from SP +7/+8, and load the ; values we find there. We then want to modify the caller's caller return ; address to skip over the data. ; ; On entry: ; stack as described above ; ; On exit: ; $fa-fb hold caller's caller address ; $fc-fd hold 16-bit inline data value ; • Clear variables ]caller_ptr .var $fa {addr/2} ]result_ptr .var $fc {addr/2} GetCCInlineValue 146a: ba tsx ;get stack pointer 146b: bd 07 01 lda STACK+7,x ;get caller's caller address 146e: 85 fa sta ]caller_ptr 1470: bd 08 01 lda STACK+8,x 1473: 85 fb sta ]caller_ptr+1 1475: a0 01 ldy #$01 ;move past last byte of instruction 1477: b1 fa lda (]caller_ptr),y ;copy inline data to zero page 1479: 85 fc sta ]result_ptr 147b: c8 iny 147c: b1 fa lda (]caller_ptr),y 147e: 85 fd sta ]result_ptr+1 1480: bd 07 01 lda STACK+7,x ;modify caller's caller address 1483: 18 clc 1484: 69 02 adc #$02 ;add 2 to skip over inline data 1486: 9d 07 01 sta STACK+7,x 1489: bd 08 01 lda STACK+8,x 148c: 69 00 adc #$00 148e: 9d 08 01 sta STACK+8,x 1491: 60 rts ; ; Loads a 16-bit value from zero page and pushes it onto the stack. ; ; On entry: ; X-reg: index into zero page ; (caller's previous X-reg value stashed at $14da) ; ; On exit: ; value from ZP pushed on stack ; (all registers preserved) ; • Clear variables ]saved_areg .var $fa {addr/1} ]saved_preg .var $fb {addr/1} ]jmp_addr .var $fc {addr/2} 1492: 85 fa Push16Idx sta ]saved_areg ;save A-reg 1494: 68 pla ;pull P-reg we saved earlier 1495: 85 fb sta ]saved_preg ;save that 1497: 68 pla ;pull return address 1498: 85 fc sta ]jmp_addr 149a: 68 pla 149b: 85 fd sta ]jmp_addr+1 149d: e6 fc inc ]jmp_addr ;increment return addr so we jump past JSR 149f: d0 02 bne :NoInc 14a1: e6 fd inc ]jmp_addr+1 14a3: ea :NoInc nop 14a4: b5 01 lda $01,x ;get 16-bit value from zero page 14a6: 48 pha ; and push on stack 14a7: b5 00 lda $00,x 14a9: 48 pha 14aa: ae da 14 ldx tmp_save_x ;restore X-reg 14ad: a5 fb lda ]saved_preg 14af: 48 pha 14b0: a5 fa lda ]saved_areg ;restore A-reg 14b2: 28 plp ;restore P-reg 14b3: 6c fc 00 jmp ($00fc) ;return to caller ; ; Pulls a 16-bit value from the stack and stores it in zero page. ; ; On entry: ; X-reg: index into zero page ; (caller's previous X-reg value stashed at $14da) ; ; On exit: ; value from top of stack written to ZP ; (all registers preserved) ; 14b6: 85 fa Pop16Idx sta ]saved_areg ;save A-reg 14b8: 68 pla ;pull P-reg we saved earlier 14b9: 85 fb sta ]saved_preg ;save that 14bb: 68 pla ;pull return address 14bc: 85 fc sta ]jmp_addr 14be: 68 pla 14bf: 85 fd sta ]jmp_addr+1 14c1: e6 fc inc ]jmp_addr ;increment return addr so we jump past JSR 14c3: d0 02 bne :NoInc 14c5: e6 fd inc ]jmp_addr+1 14c7: ea :NoInc nop 14c8: 68 pla ;pull 16-bit value from stack and store 14c9: 95 00 sta $00,x ; in zero page 14cb: 68 pla 14cc: 95 01 sta $01,x 14ce: ae da 14 ldx tmp_save_x ;restore X-reg 14d1: a5 fb lda ]saved_preg 14d3: 48 pha 14d4: a5 fa lda ]saved_areg ;restore A-reg 14d6: 28 plp ;restore P-reg 14d7: 6c fc 00 jmp ($00fc) ;return to caller 14da: 05 tmp_save_x .dd1 $05 ; ; Pushes $f4-f5 onto stack. ; • Clear variables 14db: 08 PushF4F5 php 14dc: 8e da 14 stx tmp_save_x 14df: a2 f4 ldx #$f4 14e1: d0 af bne Push16Idx ;(always) ; ; Pops $f4-f5 off of stack. ; 14e3: 8e da 14 PopF4F5 stx tmp_save_x 14e6: 08 php 14e7: a2 f4 ldx #$f4 14e9: d0 cb bne Pop16Idx ;(always) ; ; Pushes $f0-f1 onto stack. ; 14eb: 08 PushF0F1 php ;save P-reg 14ec: 8e da 14 stx tmp_save_x ;save X-reg 14ef: a2 f0 ldx #$f0 14f1: d0 9f bne Push16Idx ;(always) ; ; Pops $f0-f1 off of stack. ; 14f3: 08 PopF0F1 php 14f4: 8e da 14 stx tmp_save_x 14f7: a2 f0 ldx #$f0 14f9: d0 bb bne Pop16Idx ;(always) ; ; Pushes $f2-f3 onto stack. ; 14fb: 08 PushF2F3 php 14fc: 8e da 14 stx tmp_save_x 14ff: a2 f2 ldx #$f2 1501: d0 8f B_Push16Idx bne Push16Idx ;(always) ; ; Pops $f2-f3 off of stack. ; 1503: 08 PopF2F3 php 1504: 8e da 14 stx tmp_save_x 1507: a2 f2 ldx #$f2 1509: d0 ab B_Pop16Idx bne Pop16Idx ;(always) ; ; Pops $f6-f7 off of stack. ; 150b: 08 PopF6F7 php 150c: 8e da 14 stx tmp_save_x 150f: a2 f6 ldx #$f6 1511: d0 f6 bne B_Pop16Idx ;(always) ; ; Pushes $f6-f7 onto stack. ; 1513: 08 PushF6F7 php 1514: 8e da 14 stx tmp_save_x 1517: a2 f6 ldx #$f6 1519: d0 e6 bne B_Push16Idx ;(always) ; ; Pops $f8-f9 off of stack. ; 151b: 08 PopF8F9 php 151c: 8e da 14 stx tmp_save_x 151f: a2 f8 ldx #$f8 1521: d0 e6 bne B_Pop16Idx ;(always) ; ; Pushes $f8-f9 onto stack. ; 1523: 08 PushF8F9 php 1524: 8e da 14 stx tmp_save_x 1527: a2 f8 ldx #$f8 1529: d0 d6 bne B_Push16Idx ;(always) ; ; Increments $f8-f9. Preserves all registers. ; 152b: 08 IncF8F9 php 152c: e6 f8 inc $f8 152e: d0 65 bne PlpReturn 1530: e6 f9 inc $f9 1532: 28 plp 1533: 60 rts ; ; Pushes registers and $f0-f9 onto the stack. ; ; Preserves all registers except parts of P. ; 1534: 08 PushFullState php ;push P-reg 1535: 8d 51 14 sta ind_jmp_1 ;save A-reg 1538: 68 pla ;get P-reg 1539: 8d 52 14 sta ind_jmp_1+1 ;save P-reg 153c: 68 pla ;pull return address 153d: 8d 53 14 sta ind_jmp_2 ;store it 1540: 68 pla 1541: 8d 54 14 sta ind_jmp_2+1 1544: ad 52 14 lda ind_jmp_1+1 ;get P-reg 1547: 48 pha ;push on stack 1548: ad 51 14 lda ind_jmp_1 ;restore A-reg 154b: 28 plp ;restore P-reg ; 154c: 20 57 2e jsr JJ_PushRegs ;push AXYP 154f: 20 5d 2e jsr JJ_PushF0F1 ;push $f0 through $f9 1552: 20 6f 2e jsr JJ_PushF4F5 1555: 20 75 2e jsr JJ_PushF2F3 1558: 20 96 2e jsr JJ_PushF6F7 155b: 20 9c 2e jsr JJ_PushF8F9 155e: ee 53 14 inc ind_jmp_2 ;increment return address past end of JSR 1561: d0 03 bne :NoInc 1563: ee 54 14 inc ind_jmp_2+1 1566: 6c 53 14 :NoInc jmp (ind_jmp_2) ;jump back to caller ; ; Pops registers and $f0-f9 from the stack. ; 1569: 68 PopFullState pla ;pull return address 156a: 8d 51 14 sta ind_jmp_1 ;store it 156d: 68 pla 156e: 8d 52 14 sta ind_jmp_1+1 1571: 20 9f 2e jsr JJ_PopF8F9 ;pop $f0 through $f9 1574: 20 99 2e jsr JJ_PopF6F7 1577: 20 78 2e jsr JJ_PopF2F3 157a: 20 72 2e jsr JJ_PopF4F5 157d: 20 60 2e jsr JJ_PopF0F1 1580: 20 5a 2e jsr JJ_PopRegs ;pop AXYP 1583: ee 51 14 inc ind_jmp_1 ;increment return address past end of JSR 1586: d0 03 bne :NoInc 1588: ee 52 14 inc ind_jmp_1+1 158b: 6c 51 14 :NoInc jmp (ind_jmp_1) ;jump back to caller 158e: 08 IncF0F1 php 158f: e6 f0 inc $f0 1591: d0 02 bne PlpReturn 1593: e6 f1 inc $f1 1595: 28 PlpReturn plp 1596: 60 rts ; ; Increments $f4-f5. Preserves all registers. ; 1597: 08 IncF4F5 php 1598: e6 f4 inc $f4 159a: d0 f9 bne PlpReturn 159c: e6 f5 inc $f5 159e: 4c 95 15 jmp PlpReturn ; ; Increments $f2-f3. Preserves all registers. ; 15a1: 08 IncF2F3 php 15a2: e6 f2 inc $f2 15a4: d0 ef bne PlpReturn 15a6: e6 f3 inc $f3 15a8: 4c 95 15 jmp PlpReturn ; ; Decrements a 16-bit zero-page value. ; ; On entry: ; X-reg: index into zero page ; stack holds saved P-reg and A-reg ; ; On exit: ; (all registers from original call preserved) ; 15ab: 38 Dec16Idx sec 15ac: b5 00 lda $00,x 15ae: e9 01 sbc #$01 15b0: 95 00 sta $00,x 15b2: b5 01 lda $01,x 15b4: e9 00 sbc #$00 15b6: 95 01 sta $01,x 15b8: 68 pla 15b9: aa tax 15ba: 68 pla 15bb: 28 plp 15bc: 60 rts ; ; Decrements $f4-f5. Preserves all registers. ; 15bd: 08 DecF4F5 php 15be: 48 pha 15bf: 8a txa 15c0: 48 pha 15c1: a2 f4 ldx #$f4 15c3: d0 e6 bne Dec16Idx ; ; Decrements $f0-f1. Preserves all registers. ; 15c5: 08 DecF0F1 php 15c6: 48 pha 15c7: 8a txa 15c8: 48 pha 15c9: a2 f0 ldx #$f0 15cb: d0 de bne Dec16Idx ; ; Decrements $f2-f3. Preserves all registers. ; 15cd: 08 DecF2F3 php 15ce: 48 pha 15cf: 8a txa 15d0: 48 pha 15d1: a2 f2 ldx #$f2 15d3: d0 d6 bne Dec16Idx ; ; Sets a 16-bit zero-page value. ; ; On entry: ; X-reg: index into zero page ; $f0-f1: value to store ; stack holds saved P-reg and A-reg ; ; On exit: ; (all registers from original call preserved) ; ]value .var $f0 {addr/2} 15d5: a5 f0 Set16Idx lda ]value ;set ZP value 15d7: 95 00 sta $00,x 15d9: a5 f1 lda ]value+1 15db: 95 01 sta $01,x 15dd: 68 pla 15de: aa tax 15df: 68 pla 15e0: 28 plp 15e1: 60 rts ; ; Sets $f4-f5 to the value in $f0-f1. Preserves all registers. ; 15e2: 08 SetF4F5_F0F1 php 15e3: 48 pha 15e4: 8a txa 15e5: 48 pha 15e6: a2 f4 ldx #$f4 15e8: d0 eb bne Set16Idx ; ; Sets $f2-f3 to the value in $f0-f1. Preserves all registers. ; 15ea: 08 SetF2F3_F0F1 php 15eb: 48 pha 15ec: 8a txa 15ed: 48 pha 15ee: a2 f2 ldx #$f2 15f0: d0 e3 bne Set16Idx ; ; Computes (value1 - value2) and stores the result in value2. Sets Z/C flags ; based on result. ; ; On entry: ; $f0-f1: value1 ; $fa-fb: value2 ; (preserved registers on stack) ; ; On exit: ; $fa-fb: result ; (all registers preserved except P) ; Z-flag set if result is zero ; C-flag set if <= 0 or >= 256 ; N-flag set if result < 0 ; ]value1 .var $f0 {addr/2} ]value2 .var $fa {addr/2} ]saved_areg .var $fc {addr/1} 15f2: 20 5a 2e DoSubtract jsr JJ_PopRegs ;restore all registers 15f5: 85 fc sta ]saved_areg ;save A-reg 15f7: 38 sec ;perform 16-bit subtraction 15f8: a5 f0 lda ]value1 15fa: e5 fa sbc ]value2 15fc: 85 fa sta ]value2 15fe: a5 f1 lda ]value1+1 1600: e5 fb sbc ]value2+1 1602: 08 php ;save flags 1603: d0 09 bne :Return ;result was nonzero, bail (C=?, N=?, Z=0) 1605: 05 fa ora ]value2 ;check low byte 1607: d0 09 bne :HighZero ;nonzero, branch ; Result zero. 1609: 68 pla ;pull saved P-reg 160a: 38 sec ;set carry (no borrow) 160b: a9 00 lda #$00 ;set Z-flag, clear N flag 160d: 08 :PushReturn php ;save registers 160e: a5 fc :Return lda ]saved_areg ;restore A-reg 1610: 28 plp ;restore flags 1611: 60 rts 1612: 68 :HighZero pla ;pull saved P-reg 1613: 18 clc ;clear carry (borrow) 1614: a9 01 lda #$01 ;clear Z-flag and N-flag 1616: d0 f5 bne :PushReturn ;bail (C=0, N=0, Z=0) ; ; Takes the value in $f0-f1 and subtracts the inline data value, storing the ; result in $fa-fb. ; ; (all registers preserved except P-reg; N/C/Z set) ; ]inline_val .var $fc {addr/2} 1618: 20 57 2e SubF0F1_Inline jsr JJ_PushRegs ;preserve registers 161b: 20 6a 14 jsr GetCCInlineValue ;get inline value in $fc-fd 161e: a5 fc lda ]inline_val ;copy value from $fc-fd to $fa-fb 1620: 85 fa sta ]value2 1622: a5 fd lda ]inline_val+1 1624: 85 fb sta ]value2+1 1626: 4c f2 15 jmp DoSubtract ;perform subtraction ; ; Takes the value in $f0-f1 and subtracts the value pointed to by the inline ; pointer. Stores the result in $fa-fb. ; ; (all registers preserved except P-reg; N/C/Z set) ; 1629: 20 57 2e SubF0F1_Ind jsr JJ_PushRegs ;preserve registers 162c: 20 6a 14 jsr GetCCInlineValue ;get inline value in $fc-fd 162f: a0 00 ldy #$00 1631: b1 fc lda (]inline_val),y ;get value pointed to by inline pointer 1633: 85 fa sta ]value2 1635: c8 iny 1636: b1 fc lda (]inline_val),y 1638: 85 fb sta ]value2+1 163a: 4c f2 15 jmp DoSubtract ;perform subtraction ; ; Adds the value in $f0-f1 to the value in $f4-f5, and stores the result in $f0- ; f1. ; ]value2 .var $f4 {addr/2} 163d: 08 AddF0F1_F4F5 php ;save flags 163e: 48 pha ;save A-reg 163f: a5 f4 lda ]value2 ;add values 1641: 18 clc 1642: 65 f0 adc ]value1 1644: 85 f0 sta ]value1 1646: a5 f5 lda ]value2+1 1648: 65 f1 adc ]value1+1 164a: 85 f1 sta ]value1+1 164c: 68 pla ;restore A-reg 164d: 28 plp ;restore flags 164e: 60 rts ; ; Gets the value pointed to by an inline pointer. ; ; On exit: ; $f0-f1: return value, from pointed-to location ; $fc-fd: pointer extracted from inline data ; ]ret_val .var $f0 {addr/2} ]ind_ptr .var $fc {addr/2} GetIndirectValue 164f: 20 57 2e jsr JJ_PushRegs 1652: 20 6a 14 jsr GetCCInlineValue 1655: a0 00 ldy #$00 1657: b1 fc lda (]ind_ptr),y 1659: 85 f0 sta ]ret_val 165b: c8 iny 165c: b1 fc lda (]ind_ptr),y 165e: 85 f1 sta ]ret_val+1 1660: 20 5a 2e :PullReturn jsr JJ_PopRegs 1663: 60 rts ; ; Extracts the 16-bit inline value from the caller's caller. This is usually a ; pointer, but sometimes it's a constant. ; ; On exit: ; $f0-f1: inline data value ; ]ret_val .var $f0 {addr/2} ]inline_val .var $fc {addr/2} 1664: 20 57 2e GetInlineData jsr JJ_PushRegs ;save registers 1667: 20 6a 14 jsr GetCCInlineValue ;get value 166a: a5 fc lda ]inline_val ;copy value to $f0-f1 166c: 85 f0 sta ]ret_val 166e: a5 fd lda ]inline_val+1 1670: 85 f1 sta ]ret_val+1 1672: 4c 60 16 jmp :PullReturn 1675: 79 3f 22 1e+ .junk 139 1700: 4c d5 18 J_DescribeRoom jmp DescribeRoom 1703: 4c 1a 18 J_ShowInventory jmp ShowInventory 1706: 4c 9b 1a J_GetActionArg jmp GetActionArg 1709: 4c 06 1b J_SaveGame jmp SaveGame 170c: 4c J_CondHandlers .dd1 $4c ;not used as a jump 170d: 18 17 .dd2 cond_handlers 170f: 4c d8 1b J_AskDiskOrTape jmp AskDiskOrTape J_PrintStringCOUT 1712: 4c f5 1a jmp PrintStringCOUT 1715: 4c 9d 18 J_PrintItemName jmp PrintItemName ; ; Condition handlers. These functions are called to perform a logic test. For ; all handlers: ; ; On entry (see call at $208f): ; A-reg: room number for item [arg] (even if arg is not item#) ; X-reg: $ff ; Y-reg: $00 ; $f0-f1: pointer to global that holds current room number ; $f2-f3: condition argument ; ; On exit: ; X-reg: result ($00 or $ff) ; 1718: 40 17 cond_handlers .dd2 C00_NoOp ;$00 (no-op) 171a: 6b 17 .dd2 C01_Carried ;$01 carried 171c: 7f 17 .dd2 C02_Here ;$02 here 171e: 8c 17 .dd2 C03_Accessible ;$03 accessible 1720: 9a 17 .dd2 C04_At ;$04 at 1722: b1 17 .dd2 C05_NotHere ;$05 !here 1724: c5 17 .dd2 C06_NotCarried ;$06 !carried 1726: e0 17 .dd2 C07_NotAt ;$07 !at 1728: fd 17 .dd2 C08_Flag ;$08 flag 172a: 04 18 .dd2 C09_NotFlag ;$09 !flag 172c: 41 17 .dd2 C0A_Loaded ;$0a loaded 172e: 45 17 .dd2 C0B_NotLoaded ;$0b !loaded 1730: 71 17 .dd2 C0C_NotAccessible ;$0c !accessible 1732: 86 17 .dd2 C0D_Exists ;$0d exists 1734: 95 17 .dd2 C0E_NotExists ;$0e !exists 1736: a1 17 .dd2 C0F_CounterLE ;$0f counter_le 1738: b6 17 .dd2 C10_CounterGT ;$10 counter_ge 173a: ca 17 .dd2 C11_NotMoved ;$11 !moved 173c: e7 17 .dd2 C12_Moved ;$12 moved 173e: 0d 18 .dd2 C13_CounterEq ;$13 counter_eq ; ; Condition $00: no-op. ; • Clear variables ]cur_room_ptr .var $f0 {addr/2} ]cond_arg .var $f2 {addr/2} ]tmp .var $f4 {addr/1} 1740: 60 C00_NoOp rts ; ; Condition $0a: true if at least one item is in player's inventory. ; 1741: a2 ff C0A_Loaded ldx #$ff ;return true if inventory item found 1743: d0 02 bne CheckLoaded ;(always) ; ; Condition $0b: true if no items are in player's inventory. ; 1745: a2 00 C0B_NotLoaded ldx #$00 ;return false if inventory item found 1747: 20 93 2e CheckLoaded jsr InA_GetIndirectValue ;get pointer to item location data 174a: 26 2f .dd2 item_rooms_ptr 174c: ac 6f 30 ldy hdr_max_item ;count down from max item number 174f: 86 f4 stx ]tmp ;save default return value 1751: a2 00 ldx #$00 1753: a1 f0 :Loop lda (]cur_room_ptr,x) ;get item's room # 1755: c9 ff cmp #ITEM_HELD ;in inventory? 1757: d0 03 bne :NonInv ;no, branch 1759: a6 f4 ldx ]tmp ;restore default return value 175b: 60 rts 175c: 20 51 2e :NonInv jsr JJ_IncF0F1 ;advance pointer 175f: 20 51 2e jsr JJ_IncF0F1 1762: 88 dey ;are we done? 1763: 10 ee bpl :Loop ;no, branch 1765: a5 f4 lda ]tmp ;didn't find an inventory item, so 1767: 49 ff eor #$ff ; invert result 1769: aa tax ;put result in X-reg 176a: 60 :Return rts ; ; Condition $01: true if specified item is in player's inventory. ; 176b: c9 ff C01_Carried cmp #$ff ;(room # in A-reg) - in player inventory? 176d: f0 fb beq :Return ;yes, return true 176f: d0 12 bne ReturnXZero ;no, return false ; ; Condition $0c: true if item is NOT carried and NOT in current room. ; C0C_NotAccessible 1771: a2 00 ldx #$00 ;set default return value to false 1773: c9 ff cmp #ITEM_HELD ;(room # in A-reg) - in player inventory? 1775: f0 f3 beq :Return ;yes, accessible, return false 1777: d1 f0 cmp (]cur_room_ptr),y ;(ptr to current room in $f0-f1) in current room? 1779: f0 ef beq :Return ;yes, accessible, return false 177b: a2 ff ldx #$ff ;set return value to true 177d: d0 eb bne :Return ;(always) ; ; Condition $02: true if item is in current room. ; 177f: d1 f0 C02_Here cmp (]cur_room_ptr),y ;(room # in A-reg, ptr to cur room in $f0-f1) 1781: f0 e7 beq :Return ;if item is in current room, return default result 1783: a2 00 ReturnXZero ldx #$00 ;not in current room, return false 1785: 60 rts ; ; Condition $0d: return true if item is NOT in room zero ("nowhere"). ; 1786: c9 00 C0D_Exists cmp #$00 ;(room # in A-reg) - in room zero? 1788: d0 e0 bne :Return ;no, return true 178a: f0 f7 beq ReturnXZero ;yes, return false ; ; Condition $03: return true if item is carried OR is in current room. ; 178c: d1 f0 C03_Accessible cmp (]cur_room_ptr),y ;(room # in A-reg, ptr to cur room in $f0-f1) 178e: f0 da beq :Return ;if item is in current room, return default result 1790: c9 ff cmp #ITEM_HELD ;in inventory? 1792: d0 ef bne ReturnXZero ;no, return false 1794: 60 rts ; ; Condition $0e: true if item is in room zero ("nowhere"). ; 1795: c9 00 C0E_NotExists cmp #$00 ;(room # in A-reg) - in room zero? 1797: d0 ea bne ReturnXZero ;no, return false 1799: 60 rts ; ; Condition $04: true if arg matches current room. ; 179a: a5 f2 C04_At lda ]cond_arg ;get argument 179c: d1 f0 cmp (]cur_room_ptr),y ;compare to current room number 179e: d0 e3 bne ReturnXZero ;didn't match, return false 17a0: 60 :Return rts ; ; Condition $0f: true if current counter value is <= arg. ; 17a1: 20 93 2e C0F_CounterLE jsr InA_GetIndirectValue ;get pointer to "current counter" 17a4: c7 30 .dd2 counter_register 17a6: 20 7b 2e jsr InA_SubF0F1_Ind ;subtract argument in $f2-f3 17a9: f2 00 .dd2 $00f2 ; (in a slightly awkward way) 17ab: f0 f3 beq :Return ;if arg is equal, return true 17ad: 30 f1 bmi :Return ;if arg is smaller, return true 17af: d0 d2 BneRetXZero bne ReturnXZero ;return false ; ; Condition $05: true if item is NOT in current room. ; 17b1: d1 f0 C05_NotHere cmp (]cur_room_ptr),y ;(room # in A-reg, ptr to cur room in $f0-f1) 17b3: f0 ce beq ReturnXZero ;if item in current room, branch to return false 17b5: 60 rts ; ; Condition $10: true if current counter value is > arg. ; 17b6: 20 93 2e C10_CounterGT jsr InA_GetIndirectValue ;get pointer to "current counter" 17b9: c7 30 .dd2 counter_register 17bb: 20 7b 2e jsr InA_SubF0F1_Ind ;subtract argument in $f2-f3 17be: f2 00 .dd2 $00f2 ; (in a slightly awkward way) 17c0: f0 c1 beq ReturnXZero ;if arg is equal, return false 17c2: 30 bf bmi ReturnXZero ;if arg is smaller, return false 17c4: 60 rts ; ; Condition $06: true if player is NOT carrying item. ; 17c5: c9 ff C06_NotCarried cmp #ITEM_HELD ;(room # in A-reg) - item carried? 17c7: f0 ba beq ReturnXZero ;yes, return false 17c9: 60 rts ; ; Condition $11: true if item is in its original location. ; 17ca: 20 75 2e C11_NotMoved jsr JJ_PushF2F3 ;copy cond arg in $f2-f3... 17cd: 20 72 2e jsr JJ_PopF4F5 ;...to $f4-f5 17d0: 20 93 2e jsr InA_GetIndirectValue ;get pointer to initial room data 17d3: 2a 2f .dd2 item_initroom_ptr 17d5: 20 87 2e jsr JJ_AddF0F1_F4F5 ;double arg to convert index to offset 17d8: 20 87 2e jsr JJ_AddF0F1_F4F5 17db: d1 f0 cmp (]cur_room_ptr),y ;(room # in A-reg) - compare to initial room # 17dd: d0 a4 bne ReturnXZero ;not the same, branch to return false 17df: 60 rts ; ; Condition $07: true if player is NOT in the specified room. ; 17e0: a5 f2 C07_NotAt lda ]cond_arg ;get argument 17e2: d1 f0 cmp (]cur_room_ptr),y ;compare to current room number 17e4: f0 9d beq ReturnXZero ;if they match, return false 17e6: 60 rts ; ; Condition $12: true if item is NOT in its original location. ; 17e7: 20 75 2e C12_Moved jsr JJ_PushF2F3 ;copy cond arg in $f2-f3... 17ea: 20 72 2e jsr JJ_PopF4F5 ;...to $f4-f5 17ed: 20 93 2e jsr InA_GetIndirectValue ;get pointer to initial room data 17f0: 2a 2f .dd2 item_initroom_ptr 17f2: 20 87 2e jsr JJ_AddF0F1_F4F5 ;double arg to convert index to offset 17f5: 20 87 2e jsr JJ_AddF0F1_F4F5 17f8: d1 f0 cmp (]cur_room_ptr),y ;(room # in A-reg) - compare to initial room # 17fa: f0 87 beq ReturnXZero ;same, branch to return false 17fc: 60 rts ; ; Condition $08: true if specified flag is true. ; 17fd: a4 f2 C08_Flag ldy ]cond_arg ;use argument as index 17ff: b9 c9 30 lda action_flags,y ;get flag 1802: aa tax ;return value in X-reg 1803: 60 rts ; ; Condition $09: true if the specified flag is NOT true. ; 1804: a4 f2 C09_NotFlag ldy ]cond_arg ;use argument as index 1806: b9 c9 30 lda action_flags,y ;get flag 1809: 49 ff eor #$ff ;flip it 180b: aa tax ;return value in X-reg 180c: 60 rts ; ; Condition $13: true if current counter value is equal to arg. ; 180d: 20 93 2e C13_CounterEq jsr InA_GetIndirectValue ;get pointer to "current counter" 1810: c7 30 .dd2 counter_register 1812: 20 7b 2e jsr InA_SubF0F1_Ind ;subtract argument in $f2-f3 1815: f2 00 .dd2 $00f2 ; (in a slightly awkward way) 1817: d0 96 bne BneRetXZero ;if not equal, branch to return false 1819: 60 rts ; ; Prints a list of items in the player's inventory. ; ]name_ptrs .var $f0 {addr/2} ]item_room_data .var $f2 {addr/2} 181a: 20 8a 2e ShowInventory jsr JJ_PushFullState ;push registers and ZP data 181d: 20 33 2e jsr JJ_PrintCR ;move to start of new line 1820: 20 54 2e jsr InA_GetInlineData 1823: 6f 18 .dd2 msg_im_carrying 1825: 20 36 2e jsr JJ_PrintString ;print "I'm carrying" 1828: ac 6f 30 ldy hdr_max_item ;going to loop through all items 182b: c8 iny ;+1 to make it a count 182c: a9 00 lda #$00 182e: 8d 33 30 sta thing_found_flag ;init "have something" flag 1831: 20 93 2e jsr InA_GetIndirectValue ;get pointer to item room data 1834: 26 2f .dd2 item_rooms_ptr 1836: 20 81 2e jsr JJ_SetF2F3_F0F1 ;copy pointer to $f2-f3 1839: 20 93 2e jsr InA_GetIndirectValue ;get pointer to item name pointers 183c: 28 2f .dd2 item_names_ptr ; 183e: a2 00 :Loop ldx #$00 1840: a1 f2 lda (]item_room_data,x) ;get room number 1842: c9 ff cmp #ITEM_HELD ;in inventory? 1844: d0 06 bne :NotHeld ;no, branch 1846: 8d 33 30 sta thing_found_flag ;set "have something" flag to True 1849: 20 12 2e jsr JJ_PrintItemName ;print name of item 184c: 20 6c 2e :NotHeld jsr JJ_IncF2F3 ;advance item name pointer 184f: 20 6c 2e jsr JJ_IncF2F3 1852: 20 51 2e jsr JJ_IncF0F1 ;advance item room data pointer 1855: 20 51 2e jsr JJ_IncF0F1 1858: 88 dey ;done yet? 1859: d0 e3 bne :Loop ;no, branch ; 185b: ad 33 30 lda thing_found_flag ;did we find anything? 185e: d0 08 bne :FoundSome ;yes, branch 1860: 20 54 2e jsr InA_GetInlineData 1863: 8d 18 .dd2 msg_nothing_ata 1865: 20 36 2e jsr JJ_PrintString ;print "nothing at all" 1868: 20 33 2e :FoundSome jsr JJ_PrintCR ;finish with a newline 186b: 20 8d 2e jsr JJ_PopFullState ;restore registers and ZP data 186e: 60 rts 186f: 0d 49 27 4d+ msg_im_carrying .zstr $0d,‘I'M CARRYING THE FOLLOWING:’,$0d 188d: 20 4e 4f 54+ msg_nothing_ata .zstr ‘ NOTHING AT ALL’ ; ; Prints an item name string. Used for the "inventory" command and when drawing ; the room description. ; ; Names of get/drop items end with "/WORD/", which we want to ignore here. ; ; On entry: ; $f0-f1: pointer to pointer to string ; ]ptr .var $f0 {addr/2} 189d: 20 57 2e PrintItemName jsr JJ_PushRegs ;preserve registers 18a0: 20 5d 2e jsr JJ_PushF0F1 ;preserve $f0-f1 18a3: a0 00 ldy #$00 18a5: b1 f0 lda (]ptr),y ;get pointer low byte 18a7: 48 pha ;stash it 18a8: c8 iny 18a9: b1 f0 lda (]ptr),y ;get pointer high byte 18ab: 85 f1 sta ]ptr+1 ;store in ZP 18ad: 68 pla ;restore low byte 18ae: 85 f0 sta ]ptr ;store that 18b0: 88 dey ;set Y-reg=0 18b1: b1 f0 lda (]ptr),y ;get first byte of string, which holds the length 18b3: aa tax ;copy to X-reg 18b4: 20 51 2e jsr JJ_IncF0F1 ;advance pointer past the length byte 18b7: b1 f0 :Loop lda (]ptr),y ;get char 18b9: c9 2f cmp #‘/’ ;did we find a get/drop suffix? 18bb: f0 07 beq :StrEnd ;yes, branch 18bd: 20 30 2e jsr JJ_PrintNonNull ;no, print char 18c0: c8 iny ;advance to next char 18c1: ca dex ;done yet? 18c2: d0 f3 bne :Loop ;no, loop ; 18c4: a9 2e :StrEnd lda #‘.’ ;separate items with ". " 18c6: 20 30 2e jsr JJ_PrintNonNull 18c9: a9 20 lda #‘ ’ 18cb: 20 30 2e jsr JJ_PrintNonNull 18ce: 20 60 2e jsr JJ_PopF0F1 ;restore $f0-f1 18d1: 20 5a 2e jsr JJ_PopRegs ;restore registers 18d4: 60 rts ; ; Prints the room description at the top of the screen. This includes the room ; text, a list of all objects present, and a list of all "standard" exits. ; 18d5: 20 8a 2e DescribeRoom jsr JJ_PushFullState ;preserve regs and ZP ; Start by clearing all the lines in the area above the scroll window. 18d8: a6 22 ldx MON_WNDTOP ;get current top of screen 18da: f0 1c beq :AtTop ;empty window, branch 18dc: a9 00 lda #$00 18de: 85 25 sta MON_CV ;start at top of screen 18e0: a5 25 :Loop lda MON_CV ;get line number 18e2: 20 c1 fb jsr MON_BASCALC ;set BASL/BASH 18e5: a0 00 ldy #$00 ;start from column 0 18e7: 20 9e fc jsr MON_CLREOLZ ;clear to end of line 18ea: e6 25 inc MON_CV ;move to next line 18ec: ca dex ;done yet? 18ed: d0 f1 bne :Loop ;no, loop ; 18ef: a9 00 lda #$00 18f1: 85 22 sta MON_WNDTOP ;reset scroll window top 18f3: 85 25 sta MON_CV ;position at top line 18f5: 20 c1 fb jsr MON_BASCALC ;recalc BASL/BASH 18f8: ad d8 30 :AtTop lda darkness_flag ;is the room dark? 18fb: f0 1d beq :NotDark ;no, branch 18fd: 20 93 2e jsr InA_GetIndirectValue ;get pointer to item location data 1900: 26 2f .dd2 item_rooms_ptr 1902: a0 12 ldy #18 ;item #9 (lightsource) 1904: b1 f0 lda (]ptr),y ;check current location 1906: c9 ff cmp #ITEM_HELD ;in inventory? 1908: f0 10 beq :NotDark ;yes, not dark (must swap item when light expires) 190a: cd e9 30 cmp current_room ;is lightsource in current room? 190d: f0 0b beq :NotDark ;yes, not dark 190f: 20 54 2e jsr InA_GetInlineData ;complain about darkness 1912: 31 1a .dd2 msg_too_dark 1914: 20 4b 2e jsr JJ_PrintFlashing 1917: 4c 09 1a jmp :FinishDescr ;nothing else to say, finish up ]room_text .var $f2 {addr/2} 191a: 20 93 2e :NotDark jsr InA_GetIndirectValue ;get pointer to room descr table in $f0-f1 191d: 16 2f .dd2 room_descrs_ptr 191f: ad e9 30 lda current_room ;get current room number 1922: 18 clc 1923: 6d e9 30 adc current_room ;double it 1926: a8 tay 1927: b1 f0 lda (]ptr),y ;get ptr to text for the room (low byte) 1929: 85 f2 sta ]room_text 192b: c8 iny 192c: b1 f0 lda (]ptr),y ;repeat for high byte 192e: 85 f3 sta ]room_text+1 ; 1930: a0 00 ldy #$00 1932: b1 f2 lda (]room_text),y ;get string length 1934: aa tax ;hold in X-reg 1935: 20 6c 2e jsr JJ_IncF2F3 ;advance pointer 1938: b1 f2 lda (]room_text),y ;get first char 193a: c9 2a cmp #‘*’ ;does it start with a '*'? 193c: d0 06 bne :PrintPfx ;no, show standard "I'm in a" prefix 193e: ca dex ;yes, decrement string length 193f: 20 6c 2e jsr JJ_IncF2F3 ;advance pointer (preserves flags) 1942: d0 08 bne :RoomCont ;(branch always, assuming text follows '*') 1944: 20 54 2e :PrintPfx jsr InA_GetInlineData 1947: 47 1a .dd2 msg_im_in_a 1949: 20 36 2e jsr JJ_PrintString ;print "I'm in a" ; 194c: 20 75 2e :RoomCont jsr JJ_PushF2F3 ;copy room text string pointer from $f2-f3... 194f: 20 60 2e jsr JJ_PopF0F1 ;...to $f0-f1 1952: 8a txa ;copy string length back to A-reg 1953: 20 3f 2e jsr JJ_PrintNChars ;print room description string ; Now print a list of items found here. ]item_room_ptr .var $f2 {addr/2} 1956: a0 00 ldy #$00 1958: 98 tya 1959: 8d 33 30 sta thing_found_flag ;clear the "thing found" flag (could STY?) 195c: ae 6f 30 ldx hdr_max_item ;get max item # 195f: e8 inx ;increment it to make it a count 1960: 20 93 2e jsr InA_GetIndirectValue ;get pointer to item location data 1963: 26 2f .dd2 item_rooms_ptr 1965: 20 81 2e jsr JJ_SetF2F3_F0F1 ;copy pointer to $f2-f3 1968: 20 93 2e jsr InA_GetIndirectValue ;get pointer to item name table 196b: 28 2f .dd2 item_names_ptr 196d: ad e9 30 :ItemLoop lda current_room ;get player's room # 1970: d1 f2 cmp (]item_room_ptr),y ;is the item in this room? 1972: d0 1b bne :NotHere ;no, branch 1974: ad 33 30 lda thing_found_flag ;check "thing found" flag 1977: d0 0e bne :NotFirst ;not first item, branch 1979: 20 5d 2e jsr JJ_PushF0F1 ;preserve $f0-f1 197c: 20 54 2e jsr InA_GetInlineData 197f: 75 1a .dd2 msg_vis_items 1981: 20 36 2e jsr JJ_PrintString ;print "visible items:" 1984: 20 60 2e jsr JJ_PopF0F1 ;restore $f0-f1 1987: 20 12 2e :NotFirst jsr JJ_PrintItemName ;print the item's name 198a: a9 01 lda #$01 198c: 8d 33 30 sta thing_found_flag ;set the "thing found" flag 198f: 20 51 2e :NotHere jsr JJ_IncF0F1 ;advance pointer to item descriptions 1992: 20 51 2e jsr JJ_IncF0F1 1995: 20 6c 2e jsr JJ_IncF2F3 ;advance pointer to item room data 1998: 20 6c 2e jsr JJ_IncF2F3 199b: ca dex ;have we examined all items? 199c: d0 cf bne :ItemLoop ;not yet, branch 199e: 20 33 2e jsr JJ_PrintCR ;finish with a carriage return ; Print visible exits. For each of the 6 directions (NSEWUD), find the entry in ; the appropriate table for the current room. If the room # there is nonzero, ; show that direction in the list. ]dir_name_ptr .var $f2 {addr/2} ]vis_exit_tab .var $f4 {addr/2} 19a1: a9 00 lda #$00 19a3: 8d 33 30 sta thing_found_flag ;clear "thing found" flag 19a6: a2 06 ldx #$06 ;six directions 19a8: 20 54 2e jsr InA_GetInlineData ;get pointer to exit name strings 19ab: 51 1a .dd2 msg_exit_name 19ad: 20 81 2e jsr JJ_SetF2F3_F0F1 ;copy pointer to $f2-f3 19b0: 20 54 2e jsr InA_GetInlineData ;get pointer to room exit table pointers 19b3: 18 2f .dd2 vis_exits_n_ptr 19b5: 20 84 2e jsr JJ_SetF4F5_F0F1 ;copy pointer to $f4-f5 19b8: a0 00 :ExitsLoop ldy #$00 19ba: b1 f4 lda (]vis_exit_tab),y ;get pointer to table for this direction 19bc: 85 f0 sta ]ptr ;store in ZP 19be: c8 iny 19bf: b1 f4 lda (]vis_exit_tab),y ;repeat for high byte 19c1: 85 f1 sta ]ptr+1 19c3: ad e9 30 lda current_room ;get current room number 19c6: 18 clc 19c7: 6d e9 30 adc current_room ;double it 19ca: a8 tay ;move to Y-reg for use as index 19cb: b1 f0 lda (]ptr),y ;get exit for this room in this direction 19cd: f0 1b beq :NotThisDir ;if zero, we can't go that way ; 19cf: ad 33 30 lda thing_found_flag ;did we already find something? 19d2: d0 0d bne :NotFirst ;yes, skip this 19d4: 20 54 2e jsr InA_GetInlineData 19d7: 88 1a .dd2 msg_some_exits 19d9: 20 36 2e jsr JJ_PrintString ;print "some exits are" 19dc: a9 01 lda #$01 19de: 8d 33 30 sta thing_found_flag ;set "thing found" flag 19e1: 20 75 2e :NotFirst jsr JJ_PushF2F3 ;copy pointer to direction string from $f2-f3... 19e4: 20 60 2e jsr JJ_PopF0F1 ;...to $f0-f1 19e7: 20 36 2e jsr JJ_PrintString ;print direction string ; 19ea: 20 66 2e :NotThisDir jsr JJ_IncF4F5 ;advance to next direction table 19ed: 20 66 2e jsr JJ_IncF4F5 19f0: a0 00 :NxtDirStrLp ldy #$00 ;move to next direction string 19f2: b1 f2 lda (]dir_name_ptr),y ; by walking through the strings to find a $00 19f4: f0 05 beq :FoundZ ;found it, branch 19f6: 20 6c 2e jsr JJ_IncF2F3 ;advance pointer (preserves flags) 19f9: d0 f5 bne :NxtDirStrLp ;(always) 19fb: 20 6c 2e :FoundZ jsr JJ_IncF2F3 ;advance pointer past the $00 byte 19fe: ca dex ;done yet? 19ff: d0 b7 bne :ExitsLoop ;no, keep going 1a01: ad 33 30 lda thing_found_flag ;did we print any exits? 1a04: f0 03 beq :FinishDescr ;no, branch 1a06: 20 33 2e jsr JJ_PrintCR ;yes, finish it with a newline ; Finish up by printing "<------->" (full width of screen). 1a09: a9 3c :FinishDescr lda #‘<’ 1a0b: 20 30 2e jsr JJ_PrintNonNull 1a0e: a9 2d lda #‘-’ 1a10: a2 26 ldx #38 1a12: 20 30 2e :DashLoop jsr JJ_PrintNonNull 1a15: ca dex 1a16: d0 fa bne :DashLoop 1a18: a9 3e lda #‘>’ 1a1a: 20 30 2e jsr JJ_PrintNonNull ; Set top of scrolling text window to be below separator line. 1a1d: a6 25 ldx MON_CV ;get current vertical position 1a1f: e8 inx ;add one so it's below current line 1a20: 86 22 stx MON_WNDTOP ;set as top 1a22: a9 00 lda #0 ;set text position to left edge 1a24: 85 24 sta MON_CH 1a26: a9 17 lda #23 ;bottom of screen 1a28: 85 25 sta MON_CV 1a2a: 20 c1 fb jsr MON_BASCALC ;set BASL 1a2d: 20 8d 2e jsr JJ_PopFullState ;restore regs and ZP 1a30: 60 rts 1a31: 49 54 53 20+ msg_too_dark .zstr ‘ITS TOO DARK TO SEE!’,$0d 1a47: 49 27 4d 20+ msg_im_in_a .zstr ‘I'M IN A ’ 1a51: 4e 4f 52 54+ msg_exit_name .zstr ‘NORTH ’ 1a58: 53 4f 55 54+ .zstr ‘SOUTH ’ 1a5f: 45 41 53 54+ .zstr ‘EAST ’ 1a65: 57 45 53 54+ .zstr ‘WEST ’ 1a6b: 55 50 20 00 .zstr ‘UP ’ 1a6f: 44 4f 57 4e+ .zstr ‘DOWN ’ 1a75: 2e 20 56 49+ msg_vis_items .zstr ‘. VISIBLE ITEMS:’,$0d,$0d 1a88: 0d 20 53 4f+ msg_some_exits .zstr $0d,‘ SOME EXITS ARE: ’ ; ; Finds the argument for an action operation. The arguments are stored in the ; condition table, using entries where the condition opcode is zero. ; ; This is only called when an arg is needed, so action ops without arguments ; don't consume slots in the condition table. ; ; On entry: ; $f6-f7: action index ; (actionop_arg_idx at $3067 specifies first table to check) ; ; On exit: ; $f0-f1: argument ; ]argval .var $f2 {addr/2} 1a9b: 20 57 2e GetActionArg jsr JJ_PushRegs ;preserve registers 1a9e: 20 75 2e jsr JJ_PushF2F3 ;preserve $f2-f3 1aa1: 20 6f 2e jsr JJ_PushF4F5 ;preserve $f4-f5 ; Search the condition table entries for this action index for an entry with ; condition opcode $00, starting with the table specified by the action opcode ; argument index. 1aa4: 20 54 2e :Loop jsr InA_GetInlineData ;get pointer to pointers to condition data 1aa7: 0c 2f .dd2 condition0_ptr 1aa9: ad 67 30 lda actionop_arg_idx ;get index to arg 1aac: 18 clc 1aad: 6d 67 30 adc actionop_arg_idx ;double it 1ab0: a8 tay ;use as index into table 1ab1: ee 67 30 inc actionop_arg_idx ;incr index for next time 1ab4: b1 f0 lda (]ptr),y ;get pointer to table N (where N is arg index) 1ab6: 85 f2 sta ]argval 1ab8: c8 iny 1ab9: b1 f0 lda (]ptr),y 1abb: 85 f3 sta ]argval+1 1abd: 20 96 2e jsr JJ_PushF6F7 ;copy action index in $f6-f7... 1ac0: 20 60 2e jsr JJ_PopF0F1 ;...into $f0-f1 1ac3: 20 84 2e jsr JJ_SetF4F5_F0F1 ;...and $f4-f5 1ac6: 20 87 2e jsr JJ_AddF0F1_F4F5 ;set $f0-f1 to double the action index 1ac9: 20 75 2e jsr JJ_PushF2F3 ;copy cond table pointer in $f2-f3... 1acc: 20 72 2e jsr JJ_PopF4F5 ;...into $f4-f5 1acf: 20 87 2e jsr JJ_AddF0F1_F4F5 ;add to 2*index to get pointer to condition ; 1ad2: a0 00 ldy #$00 1ad4: b1 f0 lda (]ptr),y ;get low byte of condition 1ad6: 85 f2 sta ]argval 1ad8: c8 iny 1ad9: b1 f0 lda (]ptr),y ;get high byte of condition 1adb: 85 f3 sta ]argval+1 ;save in $f2-f3 1add: 20 54 2e jsr InA_GetInlineData ;load 20 into $f0-f1 1ae0: 14 00 .dd2 20 1ae2: 20 21 2e jsr JJ_Divide16 ;set $f0-f1 to condition / 20 (cond arg) 1ae5: a5 f3 lda ]argval+1 ; and $f2-f3 to the remainder (cond opcode) 1ae7: 05 f2 ora ]argval ;was opcode zero? 1ae9: d0 b9 bne :Loop ;no, branch 1aeb: 20 72 2e jsr JJ_PopF4F5 ;restore $f4-f5 1aee: 20 78 2e jsr JJ_PopF2F3 ;restore $f2-f3 1af1: 20 5a 2e jsr JJ_PopRegs ;restore regs 1af4: 60 :Return rts ; ; Prints a null-terminated string using COUT. Useful for DOS commands. ; 1af5: a0 00 PrintStringCOUT ldy #$00 1af7: b1 f0 lda (]ptr),y ;get char 1af9: f0 f9 beq :Return ;if it's $00, bail 1afb: 09 80 ora #$80 ;convert to to high ASCII 1afd: 20 ed fd jsr MON_COUT ;output in a way that DOS will see 1b00: 20 51 2e jsr JJ_IncF0F1 ;advance pointer 1b03: 4c f5 1a jmp PrintStringCOUT ;loop ; ; Saves a game to disk or tape. ; 1b06: 20 8a 2e SaveGame jsr JJ_PushFullState ;preserve all regs and ZP 1b09: 20 54 2e jsr InA_GetInlineData 1b0c: 9d 1b .dd2 msg_save_game 1b0e: 20 36 2e jsr JJ_PrintString ;confirm that we're saving the game 1b11: 20 1b 2e jsr JJ_AskDiskOrTape ;ask if they want disk or tape 1b14: ad 57 30 lda adventure_num ;copy adventure number into start of buffer 1b17: 8d 33 2f sta kbd_scratch_buf 1b1a: ad 58 30 lda adventure_num+1 1b1d: 8d 34 2f sta adv_num_hi ; Copy $30c7-3103 to $2f35-2f71 (counters, flags, current room, etc.). 1b20: a0 3c ldy #$3c 1b22: b9 c7 30 :Loop lda counter_register,y 1b25: 99 35 2f sta save_game_data,y 1b28: 88 dey 1b29: 10 f7 bpl :Loop 1b2b: ad b2 2e lda use_disk_flag ;disk or tape? 1b2e: f0 19 beq :Tape1 ;tape, branch ; 1b30: 20 54 2e jsr InA_GetInlineData ;get pointer to DOS save command 1b33: ac 1b .dd2 dos_save_cmd 1b35: ad 57 30 lda adventure_num ;put adventure number in filename (as control char) 1b38: 8d b9 1b sta dos_save_cmd+13 1b3b: a9 31 lda #‘1’ ;file #1 1b3d: 8d b8 1b sta dos_save_cmd+12 1b40: 20 1e 2e jsr JJ_PrintStringCOUT ;issue DOS command for file #1 1b43: ee b8 1b inc dos_save_cmd+12 ;update filename for next part 1b46: 4c 4c 1b jmp :Part2 1b49: 20 05 1c :Tape1 jsr WriteTape ;write part 1 1b4c: ea :Part2 nop 1b4d: a0 00 ldy #$00 1b4f: a2 ff ldx #$ff ;init to -1, so first iteration uses X-reg=0 1b51: 20 93 2e jsr InA_GetIndirectValue ;get pointer to item location data 1b54: 26 2f .dd2 item_rooms_ptr 1b56: e8 :Loop inx 1b57: b1 f0 lda (]ptr),y ;get item room # 1b59: 9d 33 2f sta kbd_scratch_buf,x ;copy to save buffer 1b5c: c8 iny ;(we always write 256 bytes, so max 128 items) 1b5d: c8 iny 1b5e: ec 6f 30 cpx hdr_max_item ;have we copied all items? 1b61: d0 f3 bne :Loop ;no, branch ; 1b63: ad b2 2e lda use_disk_flag ;disk or tape? 1b66: f0 0b beq :Tape2 ;tape, branch 1b68: 20 54 2e jsr InA_GetInlineData 1b6b: ac 1b .dd2 dos_save_cmd 1b6d: 20 1e 2e jsr JJ_PrintStringCOUT ;issue DOS command for file #2 1b70: 4c 76 1b jmp :Done 1b73: 20 05 1c :Tape2 jsr WriteTape ;write part 2 1b76: ea :Done nop 1b77: 20 8d 2e jsr JJ_PopFullState ;restore regs and ZP 1b7a: 60 rts 1b7b: 20 52 45 41+ msg_ready_tape .zstr ‘ READY SAVE TAPE. THEN HIT ENTER.’ 1b9d: 20 53 41 56+ msg_save_game .zstr ‘ SAVING GAME ’,$0d 1bac: 0d 04 42 53+ dos_save_cmd .zstr $0d,$04,‘BSAVE AREC2’,$05,‘,A$2F33,L256’,$0d msg_disk_or_tape 1bc8: 20 44 49 53+ .zstr ‘ DISK OR TAPE? ’ ; ; Asks the player if the want to load/save from disk or tape. If tape, the ; player is prompted to get their recorder ready. ; ; On exit: ; global flag set to $00 for tape, $01 for disk ; 1bd8: 20 54 2e AskDiskOrTape jsr InA_GetInlineData 1bdb: c8 1b .dd2 msg_disk_or_tape 1bdd: 20 36 2e jsr JJ_PrintString ;ask for preference 1be0: 20 39 2e jsr JJ_GetInput ;get line of input 1be3: ad 33 2f lda kbd_scratch_buf ;check first char 1be6: c9 44 cmp #‘D’ ;disk? 1be8: d0 06 bne :NotDisk ;no, branch 1bea: a9 01 lda #$01 1bec: 8d b2 2e sta use_disk_flag 1bef: 60 rts 1bf0: c9 54 :NotDisk cmp #‘T’ ;tape? 1bf2: d0 e4 bne AskDiskOrTape ;no, try again 1bf4: a9 00 lda #$00 1bf6: 8d b2 2e sta use_disk_flag 1bf9: 20 54 2e jsr InA_GetInlineData 1bfc: 7b 1b .dd2 msg_ready_tape 1bfe: 20 36 2e jsr JJ_PrintString ;prompt player to prepare tape 1c01: 20 39 2e jsr JJ_GetInput ;wait for player to hit return 1c04: 60 rts ; ; Invokes the tape write routine. ; 1c05: a9 33 WriteTape lda #<kbd_scratch_buf ;set up start/end (inclusive bounds) 1c07: 85 3c sta MON_A1L 1c09: a9 2f lda #>kbd_scratch_buf 1c0b: 85 3d sta MON_A1H 1c0d: a9 32 lda #<save_state_end 1c0f: 85 3e sta MON_A2L 1c11: a9 30 lda #>save_state_end 1c13: 85 3f sta MON_A2H 1c15: 20 cd fe jsr MON_WRITE ;call monitor write routine 1c18: 60 rts 1c19: 69 6e 67 20+ .junk 743 ;bunch of data from another game in this area J_ProcessActions 1f00: 4c 08 1f jmp ProcessActions 1f03: 4c 6e 21 J_ActionLoopEnd jmp ActionLoopEnd 1f06: 00 fail_msg_index .dd1 $00 ;holds a failure code (see e.g. $2327) 1f07: 00 action_opcode .dd1 $00 ;written, never read ; ; Process action list. Called from main loop. ; ; On entry: ; (first time: verb and noun indices set) ; (second time: verb index set to zero) ; 1f08: a9 00 ProcessActions lda #$00 1f0a: 8d c4 30 sta continue_flag ;init the "continue" flag 1f0d: 8d c3 30 sta occur_flag ;clear the "processing occurrences" flag 1f10: a9 ff lda #$ff 1f12: 8d c2 30 sta accum_cond_result ;init cumulative condition test result 1f15: 8d c0 30 sta cmd_not_hnd_flag ;init "command not handled" flag to true 1f18: ad bc 30 lda parsed_verb_idx ;get the verb index 1f1b: c9 01 cmp #$01 ;is it "GO" (actual or implied)? 1f1d: d0 0b bne :FindAction ;no, branch 1f1f: ad be 30 lda parsed_noun_idx ;check the noun 1f22: c9 07 cmp #$07 ;is it missing (0) or NSEWUD (1-6)? 1f24: 10 04 bpl :FindAction ;no, branch 1f26: 20 f7 23 jsr HandleGo ;handle GO command 1f29: 60 :Return rts ]action_index .var $f6 {addr/2} 1f2a: a9 ff :FindAction lda #$ff ;init index to -1 1f2c: 85 f6 sta ]action_index 1f2e: 85 f7 sta ]action_index+1 1f30: e6 f6 :FindActionLoop inc ]action_index ;increment index 1f32: d0 02 bne :NoInc 1f34: e6 f7 inc ]action_index+1 1f36: ea :NoInc nop 1f37: 20 96 2e jsr JJ_PushF6F7 ;push index 1f3a: 20 60 2e jsr JJ_PopF0F1 ;copy to $f0-f1 1f3d: 20 4e 2e jsr JJ_DecF0F1 ;decrement it 1f40: 20 7b 2e jsr InA_SubF0F1_Ind ;subtract max action; this is just comparing 1f43: 6d 30 .dd2 hdr_max_action ; the index to see if we've reached the end 1f45: d0 23 bne :NotEnd ;not end of list, branch ; We didn't find a matching action for this noun/verb. Look for implicit ; get/drop action (from /WORD/ in item descriptions). 1f47: ad bc 30 :CheckGetDrop lda parsed_verb_idx ;is verb index zero (doing occurrences)? 1f4a: f0 dd beq :Return ;yes, done 1f4c: 20 e6 21 jsr ImplicitGetDrop ;look for /WORD/ matches if this is TAKE or DROP 1f4f: 20 54 2e jsr InA_GetInlineData 1f52: 7e 21 .dd2 msg_be_stupid 1f54: ad c0 30 lda cmd_not_hnd_flag ;is command still unhandled? 1f57: f0 03 beq :NotUnhand ;no, getdrop handler took care of it; branch 1f59: 20 36 2e jsr JJ_PrintString ;print "I don't understand" (WEAR MERCHANT) 1f5c: 20 54 2e :NotUnhand jsr InA_GetInlineData 1f5f: bd 21 .dd2 msg_cant_yet 1f61: ad c2 30 lda accum_cond_result ;were all conditions true? 1f64: d0 c3 bne :Return ;yes, branch 1f66: 20 36 2e jsr JJ_PrintString ;some cond not satisfied, print "can't do that yet" 1f69: 60 :Return rts ]verb_ptr .var $f4 {addr/2} 1f6a: 20 96 2e :NotEnd jsr JJ_PushF6F7 ;copy action index in $f6-f7... 1f6d: 20 72 2e jsr JJ_PopF4F5 ;...to $f4-f5 1f70: 20 93 2e jsr InA_GetIndirectValue ;get pointer to action verb table 1f73: 00 2f .dd2 action_verb_ptr 1f75: 20 87 2e jsr JJ_AddF0F1_F4F5 ;add action index to pointer 1f78: a0 00 ldy #$00 1f7a: b1 f0 lda (]ptr),y ;get verb index for this action 1f7c: 8d c6 30 sta action_verb_idx ;save it 1f7f: 20 93 2e jsr InA_GetIndirectValue ;get pointer to noun index or occurrence percent 1f82: 02 2f .dd2 action_nou_prc_ptr 1f84: 20 87 2e jsr JJ_AddF0F1_F4F5 ;add action index to pointer 1f87: b1 f0 lda (]ptr),y ;get percent chance of occurrence firing 1f89: 8d c5 30 sta noun_or_percent ;save it 1f8c: ad bc 30 lda parsed_verb_idx ;get command verb index 1f8f: d0 05 bne :Cont ;nonzero (looking for match), branch 1f91: ad c6 30 lda action_verb_idx ;get action's verb index 1f94: d0 d3 bne :Return ;nonzero, end of occurrences reached; bail ; 1f96: ad c4 30 :Cont lda continue_flag ;are we continuing a previous item? 1f99: f0 12 beq :NotCont ;no, branch 1f9b: ad c5 30 lda noun_or_percent 1f9e: d0 05 bne :HaveNoun 1fa0: ad c6 30 lda action_verb_idx ;is this action an occurrence? 1fa3: f0 4f beq :TestConds ;yes, branch 1fa5: ad bc 30 :HaveNoun lda parsed_verb_idx 1fa8: d0 bf bne :Return 1faa: 8d c4 30 sta continue_flag ;(A-reg=0) clear the continue flag ; 1fad: ad bc 30 :NotCont lda parsed_verb_idx ;get command verb index 1fb0: cd c6 30 cmp action_verb_idx ;compare to action verb index 1fb3: d0 13 bne :WordMismatch ;mismatch, branch 1fb5: c9 00 cmp #$00 ;is verb zero (looking for occurrences)? 1fb7: d0 12 bne :NotOccur ;no, branch 1fb9: a9 00 lda #$00 1fbb: 8d c0 30 sta cmd_not_hnd_flag ;clear the not-handled flag 1fbe: 20 d4 23 jsr GetRandom ;get a random number (1-100) 1fc1: cd c5 30 cmp noun_or_percent ;compare to value specified in occurrence 1fc4: f0 2e beq :TestConds ;if we rolled <= value, do the occurrence 1fc6: 90 2c bcc :TestConds 1fc8: 4c 30 1f :WordMismatch jmp :FindActionLoop 1fcb: ad c5 30 :NotOccur lda noun_or_percent ;get noun index from action 1fce: cd be 30 cmp parsed_noun_idx ;compare to noun index from command 1fd1: f0 04 beq :NounMatch ;match, branch 1fd3: c9 00 cmp #$00 ;does action require a noun? 1fd5: d0 f1 bne :WordMismatch ;yes, this action doesn't apply; branch ; 1fd7: ad 7d 30 :NounMatch lda debug_flag ;check debug flag 1fda: c9 01 cmp #$01 ;'P' mode? 1fdc: d0 16 bne :TestConds ;no, "T" mode or off, don't show this message 1fde: 20 54 2e jsr InA_GetInlineData 1fe1: de 21 .dd2 msg_psbl 1fe3: 20 36 2e jsr JJ_PrintString 1fe6: 20 96 2e jsr JJ_PushF6F7 ;push action index 1fe9: 20 60 2e jsr JJ_PopF0F1 1fec: 20 48 2e jsr JJ_PrintSignedDec ;print action index 1fef: a9 20 lda #‘ ’ 1ff1: 20 30 2e jsr JJ_PrintNonNull ]cond_tab_ptr .var $f8 {addr/2} 1ff4: a9 00 :TestConds lda #$00 1ff6: 8d c0 30 sta cmd_not_hnd_flag ;clear the command-not-handled flag 1ff9: a9 ff lda #$ff 1ffb: 8d c2 30 sta accum_cond_result ;init result to "true" 1ffe: 8d c3 30 sta occur_flag 2001: a9 0c lda #<condition0_ptr ;get pointer to first condition table 2003: 85 f8 sta ]cond_tab_ptr 2005: a9 2f lda #>condition0_ptr 2007: 85 f9 sta ]cond_tab_ptr+1 ; Test up to 5 conditions, all of which must evaluate to True. Each condition ; is a 16-bit value that holds both the operation and the argument (value = op + ; value * 20). If an operation returns false, we bail. ]cond_raw .var $f2 {addr/2} 2009: a2 05 ldx #$05 ;5 conditions max 200b: a0 00 :Loop ldy #$00 200d: b1 f8 lda (]cond_tab_ptr),y ;get pointer to first table 200f: 85 f0 sta ]ptr 2011: c8 iny 2012: b1 f8 lda (]cond_tab_ptr),y 2014: 85 f1 sta ]ptr+1 2016: 20 5d 2e jsr JJ_PushF0F1 ;preserve table pointer 2019: 20 96 2e jsr JJ_PushF6F7 ;copy action index in $f6-f7... 201c: 20 60 2e jsr JJ_PopF0F1 ;...to $f0-f1 201f: 20 84 2e jsr JJ_SetF4F5_F0F1 ;copy that to $f4-f5 2022: 20 87 2e jsr JJ_AddF0F1_F4F5 ;add it to itself (i.e. double the index) 2025: 20 72 2e jsr JJ_PopF4F5 ;pop table pointer 2028: 20 87 2e jsr JJ_AddF0F1_F4F5 ;set pointer to (pointer + index*2) 202b: b1 f0 lda (]ptr),y ;get condition table entry (note Y-reg=1) 202d: 85 f3 sta ]cond_raw+1 ;save high byte 202f: 88 dey 2030: b1 f0 lda (]ptr),y ;get low byte of condition table entry 2032: 85 f2 sta ]cond_raw ;save it 2034: 20 54 2e jsr InA_GetInlineData 2037: 14 00 .dd2 20 2039: 20 21 2e jsr JJ_Divide16 ;divide value by 20 to separate pieces 203c: 20 5d 2e jsr JJ_PushF0F1 ;push quotient (arg) 203f: 20 75 2e jsr JJ_PushF2F3 ;push remainder (cond op code) 2042: 20 81 2e jsr JJ_SetF2F3_F0F1 ;set $f2-f3 to quotient 2045: 20 60 2e jsr JJ_PopF0F1 ;set $f0-f1 to remainder 2048: 20 84 2e jsr JJ_SetF4F5_F0F1 ;set $f4-f5 to remainder 204b: 20 87 2e jsr JJ_AddF0F1_F4F5 ;double it 204e: 20 84 2e jsr JJ_SetF4F5_F0F1 ;store op code * 2 in $f4-f5 2051: 20 93 2e jsr InA_GetIndirectValue ;get a pointer to the cond op handlers table pointer 2054: 0d 2e .dd2 cond_handlers_ind 2056: c8 iny ;skip past the fake JMP instruction 2057: b1 f0 lda (]ptr),y ;get low byte of pointer to table 2059: 48 pha ;save it 205a: c8 iny 205b: b1 f0 lda (]ptr),y ;get high byte 205d: 85 f1 sta ]ptr+1 ;overwrite $f0-f1 with table pointer 205f: 68 pla 2060: 85 f0 sta ]ptr ; 2062: a0 00 ldy #$00 2064: 20 87 2e jsr JJ_AddF0F1_F4F5 ;add doubled op code to $f0-f1 to get entry pointer 2067: 20 72 2e jsr JJ_PopF4F5 ;pop quotient (arg) into $f4-f5 206a: b1 f0 lda (]ptr),y ;get pointer to func, low byte 206c: 8d 90 20 sta _CondCall+1 ;self-modify the JSR 206f: c8 iny 2070: b1 f0 lda (]ptr),y ;same for high byte 2072: 8d 91 20 sta _CondCall+2 ; We have the cond op arg in $f2-f3 and $f4-f5. Set up registers and ZP with ; values we're likely to need. 2075: 20 93 2e jsr InA_GetIndirectValue ;get pointer to item location data 2078: 26 2f .dd2 item_rooms_ptr 207a: 20 87 2e jsr JJ_AddF0F1_F4F5 ;add cond arg 207d: 20 87 2e jsr JJ_AddF0F1_F4F5 ;twice (16-bit data) 2080: a0 00 ldy #$00 2082: 8a txa ;X-reg still holds the condition counter 2083: 48 pha ;preserve it 2084: b1 f0 lda (]ptr),y ;set A-reg to room number of item N 2086: 20 54 2e jsr InA_GetInlineData ;get pointer to current room in $f0-f1 2089: e9 30 .dd2 current_room 208b: a2 ff ldx #$ff ;set X-reg to default return value 208d: a0 00 ldy #$00 ;set Y-reg to zero 208f: 20 9a 17 _CondCall jsr C04_At ;self-mod; call relevant condition handler 2092: 8a txa ;copy result ($00 or $ff) to A-reg 2093: 2d c2 30 and accum_cond_result ;merge with previous results 2096: 8d c2 30 sta accum_cond_result 2099: 68 pla ;restore count 209a: aa tax 209b: 20 a2 2e jsr JJ_IncF8F9 ;advance condition table pointer 209e: 20 a2 2e jsr JJ_IncF8F9 20a1: ad c2 30 lda accum_cond_result ;check current result 20a4: d0 03 bne :NotFalse ;not yet false, so keep going 20a6: 4c 30 1f jmp :FindActionLoop ;condition failed, go find another action 20a9: ca :NotFalse dex ;done yet? 20aa: f0 03 beq :DoActionOps ;yes, do action operations 20ac: 4c 0b 20 jmp :Loop ;no, loop ; All conditions for this action have succeeded. Invoke operations. ]index .var $f4 {addr/2} ]table_ptr .var $f8 {addr/2} 20af: ea :DoActionOps nop 20b0: ad 7d 30 lda debug_flag ;check debug flag 20b3: f0 16 beq :NoDebug ;not enabled, skip 20b5: 20 54 2e jsr InA_GetInlineData ;show for 'P' or 'T' mode 20b8: d7 21 .dd2 msg_did 20ba: 20 36 2e jsr JJ_PrintString 20bd: 20 96 2e jsr JJ_PushF6F7 ;push action index 20c0: 20 60 2e jsr JJ_PopF0F1 20c3: 20 48 2e jsr JJ_PrintSignedDec ;print action index 20c6: a9 20 lda #‘ ’ 20c8: 20 30 2e jsr JJ_PrintNonNull 20cb: a9 00 :NoDebug lda #$00 20cd: 8d 67 30 sta actionop_arg_idx ;init action op arg index to zero 20d0: 8d 68 30 sta actionop_arg_idx+1 20d3: 20 54 2e jsr InA_GetInlineData ;get pointer to pointers to action opcodes 20d6: 04 2f .dd2 action_op0_ptr 20d8: 20 5d 2e jsr JJ_PushF0F1 ;copy table pointer in $f0-f1... 20db: 20 9f 2e jsr JJ_PopF8F9 ;...to $f8-f9 ; 20de: a2 04 ldx #$04 ;at most four operations 20e0: ea :OpLoop nop 20e1: a0 00 ldy #$00 20e3: b1 f8 lda (]table_ptr),y ;get pointer to table N 20e5: 85 f0 sta ]ptr ;store in $f0-f1 20e7: c8 iny 20e8: b1 f8 lda (]table_ptr),y 20ea: 85 f1 sta ]ptr+1 20ec: 20 96 2e jsr JJ_PushF6F7 ;copy action index in $f6-f7 20ef: 20 72 2e jsr JJ_PopF4F5 ; to $f4-f5 20f2: 20 87 2e jsr JJ_AddF0F1_F4F5 ;add to index to get pointer to opcode 20f5: 88 dey ;set Y-reg=0 20f6: b1 f0 lda (]ptr),y ;get action opcode 20f8: 8d 07 1f sta action_opcode ;store (not used?) 20fb: f0 65 beq :NextOp ;opcode $00, do nothing 20fd: 30 08 bmi :HighMsg ;negative value, must be message 51-99; branch 20ff: c9 34 cmp #$34 ;message 1-50? 2101: 30 07 bmi :LowMsg ;yes, branch 2103: c9 66 cmp #$66 ;msg 51-99? 2105: 30 2a bmi :OpNotMsg ;no, branch ; Print a message. 2107: 38 :HighMsg sec 2108: e9 32 sbc #$32 ;change [$66,$96] to [$34,$64] (52-100) 210a: 85 f4 :LowMsg sta ]index ;save message index 210c: a9 00 lda #$00 210e: 85 f5 sta ]index+1 ;set high byte of index to zero 2110: 20 93 2e jsr InA_GetIndirectValue ;get pointer to pointers to messages 2113: 24 2f .dd2 messages_ptr 2115: 20 87 2e jsr JJ_AddF0F1_F4F5 ;add index 2118: 20 87 2e jsr JJ_AddF0F1_F4F5 ;twice (16-bit address values) 211b: a0 00 ldy #$00 211d: b1 f0 lda (]ptr),y ;get pointer to message N 211f: 48 pha ;push low byte 2120: c8 iny 2121: b1 f0 lda (]ptr),y ;get high byte 2123: 85 f1 sta ]ptr+1 ;set $f0-f1 to string pointer 2125: 68 pla 2126: 85 f0 sta ]ptr 2128: 20 42 2e jsr JJ_PrintL1Str ;print message string 212b: 20 33 2e jsr JJ_PrintCR ;follow with CR 212e: 4c 62 21 jmp :NextOp ;loop ; Perform non-message operation. At this point, $f4-f5 and $f6-f7 hold the ; action index. 2131: 38 :OpNotMsg sec 2132: e9 34 sbc #$34 ;remap [$34,$65] to [$00,$31] 2134: 85 f4 sta ]index ;save opcode index 2136: a9 00 lda #$00 2138: 85 f5 sta ]index+1 ;set high byte of index to zero 213a: 20 93 2e jsr InA_GetIndirectValue ;get pointer to pointer to op func table 213d: 2b 2e .dd2 act_oper_ind 213f: a0 01 ldy #$01 ;move past JMP operand 2141: b1 f0 lda (]ptr),y ;get pointer and replace $f0-f1 2143: 48 pha 2144: c8 iny 2145: b1 f0 lda (]ptr),y 2147: 85 f1 sta ]ptr+1 2149: 68 pla 214a: 85 f0 sta ]ptr ;now pointing to opcode table ($270c) 214c: 20 87 2e jsr JJ_AddF0F1_F4F5 ;add opcode index 214f: 20 87 2e jsr JJ_AddF0F1_F4F5 ;add index again to double it (16-bit addrs) ; 2152: a0 00 ldy #$00 2154: b1 f0 lda (]ptr),y ;get pointer to action op function 2156: 8d 60 21 sta _OpCall+1 ;store in self-modified JSR 2159: c8 iny 215a: b1 f0 lda (]ptr),y 215c: 8d 61 21 sta _OpCall+2 215f: 20 0f 28 _OpCall jsr O49_Continue ;self mod; call action operation 2162: 20 a2 2e :NextOp jsr JJ_IncF8F9 ;advance to next table 2165: 20 a2 2e jsr JJ_IncF8F9 ; (16-bit pointers to tables) 2168: ca dex ;done yet? 2169: f0 03 beq ActionLoopEnd ;yes, branch 216b: 4c e0 20 jmp :OpLoop ; Note: we jump here after GET action op fails due to excess inventory, ; presumably to skip the remaining part of the action after the op failed. 216e: ad c4 30 ActionLoopEnd lda continue_flag ;is this a continuation of the previous action? 2171: f0 03 beq :NotCont ;no, branch 2173: 4c 30 1f :JLoop jmp :FindActionLoop ;yes, back to the loop 2176: ad bc 30 :NotCont lda parsed_verb_idx ;is the verb index zero (processing occurrences)? 2179: f0 f8 beq :JLoop ;yes, branch 217b: 4c 47 1f jmp :CheckGetDrop ;no, go check for implicit TAKE and DROP 217e: 0d 49 20 4d+ msg_be_stupid .zstr $0d,‘I MUST BE STUPID, BUT I JUST DON'T’,$0d,‘ ’ ;words are valid, but no action found + ‘UNDERSTAND WHAT YOU MEAN’,$0d 21bd: 0d 49 20 43+ msg_cant_yet .zstr $0d,‘I CAN'T DO THAT... YET!’,$0d ;found matching action, but conditions failed 21d7: 20 44 49 44+ msg_did .zstr ‘ DID: ’ ;debug 21de: 20 50 53 42+ msg_psbl .zstr ‘ PSBL: ’ ;debug ("possible?") ; ; See if an implict get/drop action applies here. If we handle the command, we ; clear the "command not handled" flag ($30c0) whether or not the action was ; successful. ; ; On entry: ; (parsed verb and noun indices set) ; ; On exit: ; "command not handled" flag ($30c0) cleared if handled ; ]count .var $f4 {addr/1} 21e6: ad bc 30 ImplicitGetDrop lda parsed_verb_idx ;get verb index 21e9: c9 0a cmp #10 ;TAKE? 21eb: f0 05 beq :HandleTakeDrop ;yes, handle it 21ed: c9 12 cmp #18 ;DROP? 21ef: f0 01 beq :HandleTakeDrop ;yes, handle it 21f1: 60 :Return rts 21f2: ad c3 30 :HandleTakeDrop lda occur_flag ;processing occurrences? 21f5: d0 fa bne :Return ;yes, bail 21f7: ad be 30 lda parsed_noun_idx ;get noun index 21fa: d0 0b bne :HaveNoun 21fc: 20 54 2e jsr InA_GetInlineData 21ff: 62 23 .dd2 msg_huh 2201: 20 36 2e jsr JJ_PrintString ;no noun provided (or GET ANY); act confused 2204: 4c 21 23 jmp :ActionHandled ;bail 2207: ad bc 30 :HaveNoun lda parsed_verb_idx ;get verb index 220a: c9 0a cmp #10 ;TAKE? 220c: d0 48 bne :SkipInvCount ;no, must be drop; branch ; Handle TAKE action. 220e: 20 a5 2e jsr JJ_CountHeldObjs ;count objects 2211: ac 75 30 ldy hdr_max_held ;get limit 2214: 88 dey ;reduce by one (for >= comparison) 2215: c4 f4 cpy ]count ;are we over limit? 2217: 10 3d bpl :SkipInvCount ;no, branch to common processing 2219: 20 54 2e jsr InA_GetInlineData 221c: 24 22 .dd2 msg_carry_2_much 221e: 20 36 2e jsr JJ_PrintString ;print "carrying too much" message 2221: 4c 21 23 jmp :ActionHandled ;bail msg_carry_2_much 2224: 0d 20 49 27+ .zstr $0d,‘ I'M CARRYING TOO MUCH!’,$0d,‘ TRY: "TAKE ’ + ‘INVENTORY"’,$0d,$0d ; Search the item names for /WORD/. We do this by walking through the strings ; as a pile. This is a little imprecise because the getdrop strings in the item ; list both start and end with a '/', but in practice it's unlikely to false- ; positive since the next character will be an item number, followed by a string ; length. ]item_str_ptr .var $f2 {addr/2} ]remain_len .var $f4 {addr/2} 2256: a9 00 :SkipInvCount lda #$00 2258: 8d 06 1f sta fail_msg_index ;clear flag 225b: 20 93 2e jsr InA_GetIndirectValue ;get total length of item name string pool 225e: 03 31 .dd2 item_names_len 2260: 20 84 2e jsr JJ_SetF4F5_F0F1 ;copy to $f4-f5 2263: 20 93 2e jsr InA_GetIndirectValue ;get pointer to table of pointers to names ($439f) 2266: 28 2f .dd2 item_names_ptr 2268: a0 00 ldy #$00 226a: b1 f0 lda (]ptr),y ;get pointer to item 0 226c: c8 iny 226d: 48 pha 226e: b1 f0 lda (]ptr),y 2270: 85 f1 sta ]ptr+1 ;put in $f0-f1 2272: 68 pla 2273: 85 f0 sta ]ptr ; 2275: ea :SearchLoop nop 2276: 20 51 2e :SearchLoop1 jsr JJ_IncF0F1 ;advance string pointer 2279: 20 63 2e jsr JJ_DecF4F5 ;decrement remaining len 227c: a5 f5 lda ]remain_len+1 ;check for zero: load high byte 227e: 30 06 bmi :JDone ;if negative, we're done 2280: d0 07 bne :InnerLoop ;if nonzero, keep going 2282: c5 f4 cmp ]remain_len ;must be zero; is low byte also zero? 2284: d0 03 bne :InnerLoop ;no, keep going 2286: 4c 27 23 :JDone jmp :SearchDone ;len at zero, exit loop 2289: a0 00 :InnerLoop ldy #$00 228b: a9 2f lda #‘/’ ;looking for a '/' 228d: d1 f0 cmp (]ptr),y ;test char 228f: f0 0f beq :FoundSlash ;got match, check further 2291: 20 51 2e jsr JJ_IncF0F1 ;advance string pointer 2294: 20 63 2e jsr JJ_DecF4F5 ;decrement remaining len 2297: a5 f4 lda ]remain_len ;check remaining len 2299: 05 f5 ora ]remain_len+1 229b: d0 ec bne :InnerLoop ;not zero, loop 229d: 4c 27 23 jmp :SearchDone ;done with search, exit loop 22a0: 20 81 2e :FoundSlash jsr JJ_SetF2F3_F0F1 ;copy string pointer to $f2-f3 22a3: 20 6c 2e jsr JJ_IncF2F3 ;advance past '/' 22a6: a0 00 ldy #$00 22a8: b9 80 30 :MatchLoop lda word_trim_buf,y ;compare to trimmed noun string 22ab: f0 0a beq :FoundMatch ;if we hit end of user input, branch 22ad: d1 f2 cmp (]item_str_ptr),y ;compare to string in item list 22af: d0 c4 bne :SearchLoop ;if we didn't match, branch to loop 22b1: c8 iny ;advance pointer 22b2: cc 69 30 cpy hdr_word_len ;have we matched the max chars required? 22b5: 30 f1 bmi :MatchLoop ;not yet, branch ; ]item_num .var $f4 {addr/2} 22b7: a9 2f :FoundMatch lda #‘/’ ;all chars matched; if the trimmed noun was < 4 22b9: d1 f2 cmp (]item_str_ptr),y ; chars, make sure the item string is as well 22bb: d0 b8 bne :SearchLoop ;no, partial match only; branch to loop 22bd: c8 iny ;advance past '/' 22be: 20 6f 2e jsr JJ_PushF4F5 ;preserve $f4-f5 22c1: 20 5d 2e jsr JJ_PushF0F1 ;preserve $f0-f1 22c4: b1 f2 lda (]item_str_ptr),y ;get item number (follows closing '/') 22c6: 85 f4 sta ]item_num 22c8: a9 00 lda #$00 ;set item number high byte to zero 22ca: 85 f5 sta ]item_num+1 22cc: 20 93 2e jsr InA_GetIndirectValue ;get pointer to item location data 22cf: 26 2f .dd2 item_rooms_ptr 22d1: 20 87 2e jsr JJ_AddF0F1_F4F5 ;add item number to pointer 22d4: 20 87 2e jsr JJ_AddF0F1_F4F5 ;add it again (16-bit values) 22d7: 20 81 2e jsr JJ_SetF2F3_F0F1 ;copy pointer to item's room data to $f2-f3 22da: 20 60 2e jsr JJ_PopF0F1 ;restore $f0-f1 22dd: 20 72 2e jsr JJ_PopF4F5 ;restore $f4-f5 ; We've identified the desired item. Do the actual TAKE or DROP. 22e0: ad bc 30 lda parsed_verb_idx ;get verb index 22e3: a0 00 ldy #$00 22e5: c9 0a cmp #10 ;TAKE? 22e7: f0 16 beq :DoTake ;yes, branch 22e9: b1 f2 lda (]item_str_ptr),y ;get item location 22eb: c9 ff cmp #ITEM_HELD ;is it in player's inventory? 22ed: f0 08 beq :DropIt ;yes, branch 22ef: a9 01 lda #$01 22f1: 8d 06 1f :SetFailure sta fail_msg_index ;set failure code 22f4: 4c 76 22 jmp :SearchLoop1 ;search for another match (why?) 22f7: ad e9 30 :DropIt lda current_room 22fa: 91 f2 sta (]item_str_ptr),y ;set item location to the current room 22fc: 4c 16 23 jmp :SayOkay 22ff: b1 f2 :DoTake lda (]item_str_ptr),y ;get item location 2301: c9 ff cmp #ITEM_HELD ;already in inventory? 2303: d0 04 bne :NotInInv ;no, branch 2305: a9 04 lda #$04 2307: d0 e8 bne :SetFailure ;set failure code and loop 2309: cd e9 30 :NotInInv cmp current_room ;is item in the current room? 230c: f0 04 beq :TakeIt ;yes, branch 230e: a9 02 lda #$02 2310: d0 df bne :SetFailure ;set failure code and loop 2312: a9 ff :TakeIt lda #ITEM_HELD 2314: 91 f2 sta (]item_str_ptr),y ;move item to player's inventory 2316: 20 54 2e :SayOkay jsr InA_GetInlineData 2319: 69 23 .dd2 msg_ok 231b: 20 36 2e jsr JJ_PrintString ;print "ok" 231e: 20 15 2e jsr JJ_DescribeRoom ;redraw room description 2321: a9 00 :ActionHandled lda #$00 2323: 8d c0 30 sta cmd_not_hnd_flag ;clear flag to indicate that command was handled 2326: 60 :Return rts ; Search complete, report appropriate failure message. 2327: ad 06 1f :SearchDone lda fail_msg_index ;get failure code 232a: c9 01 cmp #$01 232c: d0 08 bne :Not1 232e: 20 54 2e jsr InA_GetInlineData 2331: 6e 23 .dd2 msg_not_carrying 2333: 20 36 2e jsr JJ_PrintString ;failure #1: DROP on item not carried 2336: c9 02 :Not1 cmp #$02 2338: d0 08 bne :Not2 233a: 20 54 2e jsr InA_GetInlineData 233d: 86 23 .dd2 msg_dont_see 233f: 20 36 2e jsr JJ_PrintString ;failure #2: TAKE on item not present 2342: c9 04 :Not2 cmp #$04 2344: d0 08 bne :Not4 2346: 20 54 2e jsr InA_GetInlineData 2349: 9d 23 .dd2 msg_already_have 234b: 20 36 2e jsr JJ_PrintString ;failure #4: TAKE on item already in inventory 234e: c9 00 :Not4 cmp #$00 2350: d0 cf bne :ActionHandled 2352: ad c3 30 lda occur_flag ;processing an occurrence? 2355: d0 cf bne :Return ;yes, don't show message 2357: 20 54 2e jsr InA_GetInlineData 235a: b2 23 .dd2 msg_beyond_power 235c: 20 36 2e jsr JJ_PrintString ;failure #0: incompatible noun ("TAKE MERCHANT") 235f: 4c 21 23 jmp :ActionHandled 2362: 20 48 55 48+ msg_huh .zstr ‘ HUH?’,$0d 2369: 20 4f 4b 0d+ msg_ok .zstr ‘ OK’,$0d msg_not_carrying 236e: 0d 20 49 27+ .zstr $0d,‘ I'M NOT CARRYING IT!’,$0d 2386: 0d 49 20 44+ msg_dont_see .zstr $0d,‘I DON'T SEE IT HERE!’,$0d msg_already_have 239d: 0d 20 49 20+ .zstr $0d,‘ I ALREADY HAVE IT’,$0d msg_beyond_power 23b2: 0d 49 54 53+ .zstr $0d,‘ITS BEYOND MY POWER TO DO THAT.’,$0d ; ; Generates a crude random number from 1-100. ; ; The first call uses the keyboard input counter, so is reasonably random. ; Subsequent calls without keyboard input will have a short cycle. ; ; On exit: ; A-reg: result (1-100) ; (X-reg and Y-reg preserved) ; 23d4: 8e 35 30 GetRandom stx tmp_save_x2 ;preserve X-reg 23d7: ad b0 2e lda kbd_rng_seed ;get random seed 23da: a2 0c ldx #12 ;multiply by 12 (by adding) 23dc: 18 :MulLoop clc 23dd: 6d b0 2e adc kbd_rng_seed 23e0: ca dex 23e1: d0 f9 bne :MulLoop 23e3: 69 01 adc #$01 ;add 1 23e5: 8d b0 2e sta kbd_rng_seed ;update seed 23e8: ae 35 30 ldx tmp_save_x2 ;restore X-reg 23eb: c9 64 :ModLoop cmp #100 ;is it < 100? 23ed: 90 05 bcc :Done ;yes, branch 23ef: 38 sec ;subtract 100 23f0: e9 64 sbc #100 23f2: d0 f7 bne :ModLoop ;loop (unless we hit zero) 23f4: 69 01 :Done adc #$01 ;add 1 to make it 1-100 23f6: 60 rts ; ; Handles a "GO" command, such as "GO NORTH" or "N". ; ]dir_index .var $f0 {addr/2} 23f7: a9 00 HandleGo lda #$00 23f9: 8d 06 1f sta fail_msg_index ;init failure message index 23fc: ad d8 30 lda darkness_flag ;is this a dark area? 23ff: f0 1d beq :Lit ;no, branch 2401: 20 93 2e jsr InA_GetIndirectValue ;get pointer to item location data 2404: 26 2f .dd2 item_rooms_ptr 2406: a0 12 ldy #18 ;lightsource object (#9) 2408: b1 f0 lda (]dir_index),y ;get current location 240a: c9 ff cmp #ITEM_HELD ;in inventory? 240c: f0 10 beq :Lit ;yes, branch 240e: cd e9 30 cmp current_room ;in current room? 2411: f0 0b beq :Lit ;yes, branch 2413: 8c 06 1f sty fail_msg_index ;store nonzero value 2416: 20 54 2e jsr InA_GetInlineData 2419: bf 24 .dd2 msg_dark_danger 241b: 20 4b 2e jsr JJ_PrintFlashing ;don't have light, print warning ; 241e: ad be 30 :Lit lda parsed_noun_idx ;get noun (1-6), or 0 if not specified 2421: 38 sec 2422: e9 01 sbc #$01 ;subtract 1 2424: 10 0b bpl :HaveDir ;if it went negative, no direction was specified 2426: 20 54 2e jsr InA_GetInlineData 2429: e5 24 .dd2 msg_need_dir 242b: 20 36 2e jsr JJ_PrintString ;print "I also need a direction" 242e: 4c 99 24 jmp :Return 2431: 85 f0 :HaveDir sta ]dir_index ;save direction index 2433: a9 00 lda #$00 2435: 85 f1 sta ]dir_index+1 ;set high byte to zero 2437: 20 84 2e jsr JJ_SetF4F5_F0F1 ;copy direction index to $f4-f5 243a: 20 87 2e jsr JJ_AddF0F1_F4F5 ;add it to itself 243d: 20 84 2e jsr JJ_SetF4F5_F0F1 ;copy doubled value to $f4-f5 2440: 20 54 2e jsr InA_GetInlineData ;get pointer to table of pointers to exit tables 2443: 18 2f .dd2 vis_exits_n_ptr 2445: 20 87 2e jsr JJ_AddF0F1_F4F5 ;add doubled direction index to it ]ptr .var $f0 {addr/2} ]exit_ptr .var $f4 {addr/2} 2448: a0 00 ldy #$00 244a: b1 f0 lda (]ptr),y ;get pointer low byte from table entry 244c: 85 f4 sta ]exit_ptr ;store in ZP 244e: c8 iny 244f: b1 f0 lda (]ptr),y ;repeat for high byte 2451: 85 f5 sta ]exit_ptr+1 ;now $f4-f5 points to exit table for this direction 2453: 20 93 2e jsr InA_GetIndirectValue ;get current room 2456: e9 30 .dd2 current_room 2458: 20 87 2e jsr JJ_AddF0F1_F4F5 ;add to exit table pointer 245b: ac e9 30 ldy current_room ;get current room as index (effectively doubling it) 245e: b1 f0 lda (]ptr),y ;get exit room # (just the low byte of 16-bit value) 2460: d0 29 bne :ValidExit ;if nonzero, this is valid ; 2462: ae 06 1f ldx fail_msg_index ;is the room dark? 2465: d0 0b bne :DarkFail ;yes, branch 2467: 20 54 2e jsr InA_GetInlineData 246a: 01 25 .dd2 msg_cant_go 246c: 20 36 2e jsr JJ_PrintString ;tell them they can't go that way 246f: 4c 99 24 jmp :Return 2472: 20 54 2e :DarkFail jsr InA_GetInlineData ;going the wrong way in the dark is fatal 2475: 9a 24 .dd2 msg_fell_broke 2477: 20 36 2e jsr JJ_PrintString ;let them know 247a: a9 00 lda #$00 247c: 8d d8 30 sta darkness_flag ;reset darkness flag 247f: ad 73 30 lda hdr_max_room ;limbo room 2482: 8d e9 30 sta current_room ;move them there 2485: 20 15 2e jsr JJ_DescribeRoom ;redraw room description 2488: 4c 99 24 jmp :Return ;enjoy the afterlife 248b: 8d e9 30 :ValidExit sta current_room 248e: 20 54 2e jsr InA_GetInlineData 2491: 69 23 .dd2 msg_ok 2493: 20 36 2e jsr JJ_PrintString 2496: 20 15 2e jsr JJ_DescribeRoom 2499: 60 :Return rts 249a: 0d 20 49 20+ msg_fell_broke .zstr $0d,‘ I FELL & BROKE MY NECK!’,$0d,‘I'M DEAD!’ + $0d 24bf: 0d 20 49 54+ msg_dark_danger .zstr $0d,‘ ITS DANGEROUS TO MOVE IN THE DARK!’,$0d 24e5: 0d 20 49 20+ msg_need_dir .zstr $0d,‘ I ALSO NEED A DIRECTION.’,$0d 2501: 0d 20 49 20+ msg_cant_go .zstr $0d,‘ I CAN'T GO IN THAT DIRECTION.’,$0d 2522: 00 00 00 00+ .junk 478 2700: 4c 38 2b jmp Divide16 2703: 4c 0c 27 J_act_oper_tab jmp act_oper_tab ;not used as a jump 2706: 4c 56 27 J_CountHeldObjs jmp CountHeldObjs 2709: 4c 38 2b J_Divide16 jmp Divide16 270c: 7c 27 act_oper_tab .dd2 O34_Get ;$34 get ITEM# 270e: a6 27 .dd2 O35_Drop ;$35 drop ITEM# 2710: c7 27 .dd2 O36_MoveTo ;$36 moveto ROOM# 2712: ff 27 .dd2 O37_Destroy ;$37 destroy ITEM# 2714: 15 28 .dd2 O38_SetDark ;$38 set_dark 2716: 56 28 .dd2 O39_ClearDark ;$39 clear_dark 2718: d4 28 .dd2 O3A_SetFlag ;$3a set_flag FLAG# 271a: ff 27 .dd2 O37_Destroy ;$3b destroy2 (same as $37) 271c: f2 28 .dd2 O3C_ClearFlag ;$3c clear_flag FLAG# 271e: fd 28 .dd2 O3D_Die ;$3d die 2720: 20 29 .dd2 O3E_Put ;$3e put ITEM#, ROOM# 2722: 4a 29 .dd2 O3F_GameOver ;$3f game_over 2724: 66 29 .dd2 O40_DescribeRoom ;$40 look 2726: d9 29 .dd2 O41_Score ;$41 score 2728: d9 2a .dd2 O42_Inventory ;$42 inventory 272a: dd 2a .dd2 O43_Set0 ;$43 set_0 272c: e2 2a .dd2 O44_Clear0 ;$44 clear_0 272e: e7 2a .dd2 O45_RefillLamp ;$45 refill_lamp 2730: 06 2b .dd2 O46_ClearScreen ;$46 clear_screen 2732: b5 27 .dd2 O47_SaveGame ;$47 save_game 2734: d3 27 .dd2 O48_Swap ;$48 swap ITEM#, ITEM# 2736: 0f 28 .dd2 O49_Continue ;$49 continue 2738: 96 27 .dd2 O4A_SuperGet ;$4a superget ITEM# 273a: 07 2b .dd2 O4B_PutWith ;$4b put_with ITEM#, ITEM# 273c: 66 29 .dd2 O40_DescribeRoom ;$4c look2 (same as $40) 273e: 1a 28 .dd2 O4D_DecreaseCounter ;$4d decrease_counter 2740: 2d 28 .dd2 O4E_PrintCounter ;$4e print_counter 2742: 3b 28 .dd2 O4F_SetCounter ;$4f set_counter VALUE 2744: 49 28 .dd2 O50_SwapLocDefault ;$50 swap_loc_default 2746: 5b 28 .dd2 O51_SelectCounter ;$51 select_counter 2748: 8b 28 .dd2 O52_AddCounter ;$52 add_counter 274a: a7 28 .dd2 O53_SubtractCounter ;$53 subtract_counter 274c: bf 28 .dd2 O54_PrintNoun ;$54 print_noun 274e: c8 28 .dd2 O55_PrintNounNl ;$55 print_noun_nl 2750: d0 28 .dd2 O56_Nl ;$56 nl 2752: df 28 .dd2 O57_SwapLoc ;$57 swap_loc ALT# 2754: b9 27 .dd2 O58_Pause ;$58 pause ; ; Counts the number of items in the player's inventory. ; ; On exit: ; $f4: number of items ; • Clear variables ]ptr .var $f0 {addr/2} ]counter .var $f4 {addr/1} 2756: 20 57 2e CountHeldObjs jsr JJ_PushRegs ;preserve registers 2759: ae 6f 30 ldx hdr_max_item ;run through full set of items 275c: a9 00 lda #$00 275e: 85 f4 sta ]counter ;init count to zero 2760: 20 93 2e jsr InA_GetIndirectValue ;get pointer to item room data 2763: 26 2f .dd2 item_rooms_ptr 2765: a0 00 ldy #$00 2767: b1 f0 :Loop lda (]ptr),y ;get item's room 2769: c9 ff cmp #ITEM_HELD ;in player inventory? 276b: d0 02 bne :NotHeld ;no, branch 276d: e6 f4 inc ]counter ;yes, increment count 276f: 20 51 2e :NotHeld jsr JJ_IncF0F1 ;advance pointer 2772: 20 51 2e jsr JJ_IncF0F1 ; twice (16-bit data) 2775: ca dex ;done yet? 2776: d0 ef bne :Loop ;no, loop 2778: 20 5a 2e jsr JJ_PopRegs ;restore registers 277b: 60 rts ; ; Action op $34: get item. Checks to see if inventory is full. ; ]action_arg .var $f0 {addr/2} ]count .var $f4 {addr/1} 277c: 20 a5 2e O34_Get jsr JJ_CountHeldObjs ;get count of held items into $f4 277f: ad 75 30 lda hdr_max_held ;get inventory limit 2782: 38 sec 2783: e9 01 sbc #$01 ;subtract one 2785: c5 f4 cmp ]count ;compare to current count 2787: 10 0d bpl O4A_SuperGet ;if (max-1) >= count, branch to grab item 2789: 68 pla ;failed, pull return address off stack 278a: 68 pla 278b: 20 54 2e jsr InA_GetInlineData 278e: a7 29 .dd2 msg_overburden 2790: 20 36 2e jsr JJ_PrintString ;display failure message 2793: 4c 06 2e jmp JJ_ActionLoopEnd ;skip remaining actions ; ; Action op $4a: get item, regardless of inventory count. ; 2796: 20 18 2e O4A_SuperGet jsr JJ_GetActionArg ;item index in $f0-f1 2799: 20 45 2e jsr JJ_GetItemLocation ;get location; puts room pointer in $f0-f1 279c: a9 ff lda #ITEM_HELD ;put in inventory 279e: a0 00 ldy #$00 27a0: 91 f0 sta (]action_arg),y ;update location 27a2: 20 15 2e :DescribeReturn jsr JJ_DescribeRoom ;redraw room description 27a5: 60 rts ; ; Action op $35: drop item. ; 27a6: 20 18 2e O35_Drop jsr JJ_GetActionArg 27a9: 20 45 2e jsr JJ_GetItemLocation ;get location; puts room pointer in $f0-f1 27ac: ad e9 30 lda current_room ;move to current room 27af: a0 00 ldy #$00 27b1: 91 f0 sta (]action_arg),y ;update location 27b3: f0 ed beq :DescribeReturn ;(always) ; ; Action op $47: save game. ; 27b5: 20 09 2e O47_SaveGame jsr JJ_SaveGame 27b8: 60 rts ; ; Action op $58: pause briefly. Inner loop is 256*8 cycles, outer loop adds 8 ; cycles, total is 256*(8+256*8-1)-1 = 526079. With the complicated ; initialization call it's about 526355, which is about half a second. ; 27b9: 20 54 2e O58_Pause jsr InA_GetInlineData ;set $f0-f1 to zero 27bc: 00 00 .dd2 $0000 27be: e6 f0 :DelayLoop inc ]action_arg 27c0: d0 fc bne :DelayLoop 27c2: e6 f1 inc ]action_arg+1 27c4: d0 f8 bne :DelayLoop 27c6: 60 rts ; ; Action op $36: move to specified room. ; 27c7: 20 18 2e O36_MoveTo jsr JJ_GetActionArg ;get argument in $f0-f1 27ca: a5 f0 lda ]action_arg 27cc: 8d e9 30 sta current_room ;set current room 27cf: 20 15 2e :RedrawReturn jsr JJ_DescribeRoom ;redraw room description 27d2: 60 rts ; ; Action op $48: swap the locations of two items. ; ; If both items are in the current room, the screen will be redrawn twice. ; ]item2_loc .var $f0 {addr/2} ]item1_loc .var $f2 {addr/2} 27d3: 20 18 2e O48_Swap jsr JJ_GetActionArg ;get argument in $f0-f1 27d6: 20 45 2e jsr JJ_GetItemLocation ;get location ptr in $f0-f1 27d9: 20 5d 2e jsr JJ_PushF0F1 ;push item #1 location ptr 27dc: 20 18 2e jsr JJ_GetActionArg ;get argument in $f0-f1 27df: 20 45 2e jsr JJ_GetItemLocation ;get item #2 location ptr in $f0-f1 27e2: 20 78 2e jsr JJ_PopF2F3 ;pop item #1 location ptr into $f2-f3 27e5: 48 pha ;push room # of item #2 27e6: a0 00 ldy #$00 27e8: b1 f2 lda (]item1_loc),y ;get location of item #1 27ea: 91 f0 sta (]item2_loc),y ;move item #2 there 27ec: 68 pla ;pull room # of item #2 27ed: 91 f2 sta (]item1_loc),y ;move item #1 there 27ef: cd e9 30 cmp current_room ;is item #1 now in the current room? 27f2: d0 03 bne :NotHere1 ;no, branch 27f4: 20 15 2e jsr JJ_DescribeRoom ;yes, redraw room description 27f7: b1 f0 :NotHere1 lda (]item2_loc),y 27f9: cd e9 30 cmp current_room ;is item #2 now in the current room? 27fc: f0 d1 beq :RedrawReturn ;yes, redraw room description 27fe: 60 rts ; ; Action op $37: destroy item (move to room zero). ; ]ptr .var $f0 {addr/2} 27ff: 20 18 2e O37_Destroy jsr JJ_GetActionArg ;get argument in $f0-f1 2802: 20 45 2e jsr JJ_GetItemLocation ;get location ptr in $f0-f1 2805: a9 00 lda #$00 ;nowhere 2807: a0 00 ldy #$00 2809: 91 f0 sta (]ptr),y ;set location 280b: 20 15 2e jsr JJ_DescribeRoom ;redraw room description 280e: 60 rts ; ; Action $49: continue into next action slot. ; 280f: a9 ff O49_Continue lda #$ff 2811: 8d c4 30 sta continue_flag ;set flag, read by action loop 2814: 60 rts ; ; Action $38: set the darkness flag (#15). ; 2815: a0 0f O38_SetDark ldy #15 ;set flag 15 2817: 4c d9 28 jmp SetFlagN ; ; Action $4d: decrease current counter. ; ]counter_value .var $f0 {addr/2} O4D_DecreaseCounter 281a: 20 93 2e jsr InA_GetIndirectValue ;get value of "current counter" in $f0-f1 281d: c7 30 .dd2 counter_register 281f: 20 4e 2e jsr JJ_DecF0F1 ;decrement it 2822: a5 f0 lda ]counter_value ;save it 2824: 8d c7 30 sta counter_register 2827: a5 f1 lda ]counter_value+1 2829: 8d c8 30 sta counter_register+1 282c: 60 rts ; ; Action $4e: print current counter. ; O4E_PrintCounter 282d: 20 93 2e jsr InA_GetIndirectValue ;get value of "current counter" in $f0-f1 2830: c7 30 .dd2 counter_register 2832: 20 48 2e jsr JJ_PrintSignedDec ;print as signed decimal 2835: a9 20 lda #‘ ’ 2837: 20 30 2e jsr JJ_PrintNonNull ;add a space 283a: 60 rts ; ; Action $4f: set value of current counter. ; 283b: 20 18 2e O4F_SetCounter jsr JJ_GetActionArg ;get new value in $f0-f1 283e: a5 f0 lda ]counter_value ;copy value to "current counter" 2840: 8d c7 30 sta counter_register 2843: a5 f1 lda ]counter_value+1 2845: 8d c8 30 sta counter_register+1 2848: 60 rts ; ; Action $50: swaps "current" and "default alternate" locations. ; O50_SwapLocDefault 2849: ad e9 30 lda current_room 284c: ac eb 30 ldy def_alt_room 284f: 8c e9 30 sty current_room 2852: 8d eb 30 sta def_alt_room 2855: 60 rts ; ; Action $39: clear darkness flag. ; 2856: a0 0f O39_ClearDark ldy #15 ;clear flag 15 2858: 4c f7 28 jmp ClearFlagN ; ; Action $51: swap current counter with numbered storage location. ; ; Most docs refer to this as "selecting" a counter, but it's more like swapping ; the contents of the "current counter" register with a value in RAM. ; ]ptr .var $f0 {addr/2} O51_SelectCounter 285b: 20 18 2e jsr JJ_GetActionArg ;get argument in $f0-f1 285e: 20 84 2e jsr JJ_SetF4F5_F0F1 ;copy to $f4-f5 2861: 20 87 2e jsr JJ_AddF0F1_F4F5 ;double it 2864: 20 84 2e jsr JJ_SetF4F5_F0F1 ;copy doubled value to $f4-f5 2867: 20 54 2e jsr InA_GetInlineData ;get pointer to counter storage 286a: f1 30 .dd2 game_counters 286c: 20 87 2e jsr JJ_AddF0F1_F4F5 ;add doubled arg ; 286f: a0 00 ldy #$00 2871: ad c7 30 lda counter_register ;get current value 2874: 48 pha ;push on stack 2875: b1 f0 lda (]ptr),y ;get value from counter array 2877: 8d c7 30 sta counter_register ;replace current value 287a: 68 pla ;pull previous current value from stack 287b: 91 f0 sta (]ptr),y ;store into array 287d: c8 iny ;repeat for high byte 287e: b1 f0 lda (]ptr),y 2880: 48 pha 2881: ad c8 30 lda counter_register+1 2884: 91 f0 sta (]ptr),y 2886: 68 pla 2887: 8d c8 30 sta counter_register+1 288a: 60 rts ; ; Action $52: add argument to the "current counter". ; ]new_value .var $f0 {addr/2} 288b: 20 18 2e O52_AddCounter jsr JJ_GetActionArg ;get argument in $f0-f1 288e: 20 84 2e jsr JJ_SetF4F5_F0F1 ;copy to $f4-f5 2891: 20 93 2e jsr InA_GetIndirectValue ;get current counter value 2894: c7 30 .dd2 counter_register 2896: 20 87 2e jsr JJ_AddF0F1_F4F5 ;add argument to it 2899: a0 00 ldy #$00 ;? 289b: a5 f0 lda ]new_value ;copy new value to the counter 289d: 8d c7 30 sta counter_register 28a0: c8 iny ;? 28a1: a5 f1 lda ]new_value+1 28a3: 8d c8 30 sta counter_register+1 28a6: 60 rts ; ; Action $53: subtract argument from the "current counter". ; O53_SubtractCounter 28a7: 20 18 2e jsr JJ_GetActionArg ;get argument in $f0-f1 28aa: a0 00 ldy #$00 ;? 28ac: 38 sec 28ad: ad c7 30 lda counter_register ;do the subtraction manually 28b0: e5 f0 sbc ]new_value 28b2: 8d c7 30 sta counter_register 28b5: c8 iny ;? 28b6: ad c8 30 lda counter_register+1 28b9: e5 f1 sbc ]new_value+1 28bb: 8d c8 30 sta counter_register+1 28be: 60 rts ; ; Action op $54: prints the noun the user typed. ; ; The command parser left the noun, with whitespace trimmed away, in the trim ; buffer. ; 28bf: 20 54 2e O54_PrintNoun jsr InA_GetInlineData ;get pointer to trim buf 28c2: 80 30 .dd2 word_trim_buf 28c4: 20 36 2e jsr JJ_PrintString ;print it 28c7: 60 rts ; ; Action op $55: print the noun the user typed, then a newline. ; 28c8: 20 54 2e O55_PrintNounNl jsr InA_GetInlineData ;get pointer to trim buf 28cb: 80 30 .dd2 word_trim_buf 28cd: 20 36 2e jsr JJ_PrintString ;print it, fall through to print newline ; ; Action op $56: print a newline. ; 28d0: 20 33 2e O56_Nl jsr JJ_PrintCR ;print a newline 28d3: 60 rts ; ; Action op $3a: set flag to true. ; ]arg_val .var $f0 {addr/2} 28d4: 20 18 2e O3A_SetFlag jsr JJ_GetActionArg ;get arg in $f0-f1 28d7: a4 f0 ldy ]arg_val ;use low byte as index ; Sets game flag N, specified by Y-reg. 28d9: a9 ff SetFlagN lda #$ff 28db: 99 c9 30 sta action_flags,y ;set flag 28de: 60 rts ; ; Action op $57: swap the player's current location with the Nth alternate room ; slot. ; ; NOTE: this is using the action argument as a pointer. Since the argument is a ; small integer, this will use low zero-page addresses for storage, which is bad ; since it won't be saved/restored. Another weird thing is that it's using the ; room number from the default alt slot as an index. (Compare to implementation ; of O50_SwapLocDefault at $2849.) ; ; I suspect this is broken, but I haven't found a game that uses it. ; 28df: 20 18 2e O57_SwapLoc jsr JJ_GetActionArg ;get action argument (should be alt room slot number) 28e2: ac eb 30 ldy def_alt_room ;get default alt room number 28e5: b1 f0 lda (]arg_val),y ;get ?! 28e7: 48 pha 28e8: ad e9 30 lda current_room ;get current room 28eb: 91 f0 sta (]arg_val),y ;store ?! 28ed: 68 pla 28ee: 8d e9 30 sta current_room ;update current room 28f1: 60 rts ; ; Action op $3c: clear flag. ; 28f2: 20 18 2e O3C_ClearFlag jsr JJ_GetActionArg ;get arg in $f0-f1 28f5: a4 f0 ldy ]arg_val ;use low byte as index ; Clears game flag N, specified by Y-reg. 28f7: a9 00 ClearFlagN lda #$00 28f9: 99 c9 30 sta action_flags,y ;clear flag 28fc: 60 rts ; ; Action op $3d: die. ; 28fd: 20 54 2e O3D_Die jsr InA_GetInlineData 2900: 14 29 .dd2 msg_im_dead 2902: 20 36 2e jsr JJ_PrintString ;print "I'm dead" message 2905: ad 73 30 lda hdr_max_room ;get last room defined (limbo) 2908: 8d e9 30 sta current_room ;make current 290b: a9 00 lda #$00 290d: 8d d8 30 sta darkness_flag ;clear darkness flag 2910: 20 15 2e jsr JJ_DescribeRoom ;redraw room description 2913: 60 rts 2914: 20 49 27 4d+ msg_im_dead .zstr ‘ I'M DEAD!’,$0d ; ; Action op $3e: put item in specified room. ; 2920: 20 18 2e O3E_Put jsr JJ_GetActionArg ;get item # arg 2923: 20 45 2e jsr JJ_GetItemLocation ;get item location ptr in $f0-f1 2926: 20 5d 2e jsr JJ_PushF0F1 ;push that 2929: 20 18 2e jsr JJ_GetActionArg ;get room # arg 292c: 20 78 2e jsr JJ_PopF2F3 ;pop item location ptr into $f2-f3 ; 292f: a0 00 ldy #$00 2931: b1 f2 lda (]item1_loc),y ;get item's current location 2933: 48 pha ;save on stack 2934: a5 f0 lda ]arg_val ;get new room # 2936: 91 f2 sta (]item1_loc),y ;move item there 2938: cd e9 30 cmp current_room ;is current room the new room? 293b: d0 03 bne :NotNew ;no, branch 293d: 20 15 2e jsr JJ_DescribeRoom ;redraw room description 2940: 68 :NotNew pla ;pull item's previous room # 2941: cd e9 30 cmp current_room ;was it in this room? 2944: d0 03 bne :Return ;no, branch 2946: 20 15 2e jsr JJ_DescribeRoom ;redraw room description 2949: 60 :Return rts ; ; Action op $3f: game over. Inform the user and ask if they want to play again. ; 294a: 20 54 2e O3F_GameOver jsr InA_GetInlineData 294d: 6a 29 .dd2 msg_advent_over 294f: 20 36 2e jsr JJ_PrintString ;print game over, ask if they want to go again 2952: 20 39 2e jsr JJ_GetInput ;get input 2955: ad 33 2f lda kbd_scratch_buf 2958: c9 4e cmp #‘N’ ;no? 295a: d0 03 bne :NotN 295c: 4c 59 ff jmp MON_OLDRST ;exit to monitor 295f: c9 59 :NotN cmp #‘Y’ ;yes? 2961: d0 e7 bne O3F_GameOver 2963: 4c 2d 2e jmp J_Start ;restart game ; ; Action op $40: describe room. ; O40_DescribeRoom 2966: 20 15 2e jsr JJ_DescribeRoom ;redraw room description 2969: 60 rts 296a: 20 54 48 49+ msg_advent_over .zstr ‘ THIS ADVENTURE IS OVER.’,$0d,‘ WANT TO TRY TH’ + ‘IS ADVENTURE AGAIN? ’ 29a7: 0d 20 49 27+ msg_overburden .zstr $0d,‘ I'M CARRYING TOO MUCH.’,$0d,‘ TRY: "TAKE ’ + ‘INVENTORY"’,$0d,$0d ; ; Action op $41: display score. ; ; If all treasures are in the treasure room, this will print the victory message ; and jump to the game-over handler. ; ; (preserves X-reg) ; • Clear variables ]name_ptr .var $f0 {addr/2} ]str_ptr .var $f2 {addr/2} ]tr_count .var $f4 {addr/1} ]room_ptr .var $f8 {addr/2} 29d9: a9 00 O41_Score lda #$00 ;init treasure counter 29db: 85 f4 sta ]tr_count 29dd: 8a txa ;preserve X-reg (why?) 29de: 48 pha 29df: ae 6f 30 ldx hdr_max_item ;get max item # 29e2: e8 inx ;add one to make it a count 29e3: 20 9c 2e jsr JJ_PushF8F9 ;preserve $f8-f9 29e6: 20 93 2e jsr InA_GetIndirectValue ;get pointer to item room data 29e9: 26 2f .dd2 item_rooms_ptr 29eb: 20 5d 2e jsr JJ_PushF0F1 ;copy $f0-f1... 29ee: 20 9f 2e jsr JJ_PopF8F9 ;...into $f8-f9 29f1: 20 93 2e jsr InA_GetIndirectValue ;get pointer to item name data 29f4: 28 2f .dd2 item_names_ptr ; 29f6: a0 00 :CountLoop ldy #$00 29f8: b1 f0 lda (]name_ptr),y ;get pointer to name, low byte 29fa: 85 f2 sta ]str_ptr ;copy into $f2 29fc: 20 51 2e jsr JJ_IncF0F1 ;advance ptr 29ff: b1 f0 lda (]name_ptr),y ;repeat for high byte 2a01: 85 f3 sta ]str_ptr+1 2a03: 20 51 2e jsr JJ_IncF0F1 2a06: 20 6c 2e jsr JJ_IncF2F3 ;step over length byte 2a09: b1 f2 lda (]str_ptr),y ;get first char of name 2a0b: c9 2a cmp #‘*’ ;is this a treasure item? 2a0d: d0 09 bne :NotTreasure ;no, branch 2a0f: ad 7e 30 lda hdr_treasure_room ;is it in the treasure room? 2a12: d1 f8 cmp (]room_ptr),y 2a14: d0 02 bne :NotTreasure ;no, branch 2a16: e6 f4 inc ]tr_count ;yes, this one counts 2a18: 20 a2 2e :NotTreasure jsr JJ_IncF8F9 ;advance room pointer to next room 2a1b: 20 a2 2e jsr JJ_IncF8F9 2a1e: ca dex ;done yet? 2a1f: d0 d5 bne :CountLoop ;no, loop ; ]count16 .var $f0 {addr/2} 2a21: 20 9f 2e jsr JJ_PopF8F9 ;restore $f8-f9 2a24: 20 54 2e jsr InA_GetInlineData 2a27: 88 2a .dd2 msg_i_stored 2a29: 20 36 2e jsr JJ_PrintString ;print "I stored" 2a2c: a5 f4 lda ]tr_count ;copy treasure count to $f0-f1 2a2e: 85 f0 sta ]count16 2a30: 48 pha ;stash count on stack 2a31: a9 00 lda #$00 ;high byte always 0 (max 255 treasures) 2a33: 85 f1 sta ]count16+1 2a35: 20 48 2e jsr JJ_PrintSignedDec ;print count 2a38: 20 54 2e jsr InA_GetInlineData 2a3b: 93 2a .dd2 msg_treasures 2a3d: 20 36 2e jsr JJ_PrintString ;print "treasures" 2a40: 20 54 2e jsr InA_GetInlineData 2a43: a0 2a .dd2 msg_scale_of 2a45: 20 36 2e jsr JJ_PrintString ;"on scale of 0-100"... ; Compute score. We add 100 for every treasure we've found and stored, then ; divide by the max number of treasures. ]score .var $f0 {addr/2} 2a48: a9 00 lda #$00 2a4a: 85 f0 sta ]score 2a4c: 85 f1 sta ]score+1 2a4e: a6 f4 ldx ]tr_count 2a50: f0 1c beq :NoTreasure ;avoid divide-by-zero 2a52: 20 54 2e jsr InA_GetInlineData 2a55: 64 00 .dd2 100 2a57: 20 84 2e jsr JJ_SetF4F5_F0F1 ;set $f4-f5 to 100 2a5a: ca dex 2a5b: f0 06 beq :OneTreasure 2a5d: 20 87 2e :AddLoop jsr JJ_AddF0F1_F4F5 ;$f0-f1 += $f4-f5 2a60: ca dex 2a61: d0 fa bne :AddLoop 2a63: 20 81 2e :OneTreasure jsr JJ_SetF2F3_F0F1 ;set $f2-f3 to $f0-f1 (found * 100) 2a66: 20 93 2e jsr InA_GetIndirectValue ;set $f0-f1 to number of treasures 2a69: 79 30 .dd2 hdr_num_treasures 2a6b: 20 21 2e jsr JJ_Divide16 ;divide, quotient in $f0-f1 2a6e: 20 48 2e :NoTreasure jsr JJ_PrintSignedDec ;print score 2a71: 20 33 2e jsr JJ_PrintCR 2a74: 68 pla ;pull saved count off stack 2a75: cd 79 30 cmp hdr_num_treasures ;compare to max treasures 2a78: f0 03 beq :Victory ;it matches, game won; branch 2a7a: 68 pla ;restore X-reg 2a7b: aa tax 2a7c: 60 rts 2a7d: 20 54 2e :Victory jsr InA_GetInlineData 2a80: bc 2a .dd2 msg_victory 2a82: 20 36 2e jsr JJ_PrintString ;print victory message 2a85: 4c 4a 29 jmp O3F_GameOver ;jump to game-over handler 2a88: 20 49 20 53+ msg_i_stored .zstr ‘ I STORED ’ 2a93: 20 54 52 45+ msg_treasures .zstr ‘ TREASURES.’,$0d 2aa0: 4f 4e 20 41+ msg_scale_of .zstr ‘ON A SCALE OF 0-100 THATS: ’ 2abc: 20 46 41 4e+ msg_victory .zstr ‘ FANTASTIC! YOU'VE DONE IT!’,$0d ; ; Action $42: show inventory. ; 2ad9: 20 0f 2e O42_Inventory jsr JJ_ShowInventory 2adc: 60 rts ; ; Action $43: set flag 0 to true. ; 2add: a0 00 O43_Set0 ldy #$00 2adf: 4c d9 28 jmp SetFlagN ;set flag #0 ; ; Action $44: clear flag 0. ; 2ae2: a0 00 O44_Clear0 ldy #$00 2ae4: 4c f7 28 jmp ClearFlagN ;clear flag #0 ; ; Action op $45: refill lightsource. ; ]ptr .var $f0 {addr/2} 2ae7: ad 7b 30 O45_RefillLamp lda hdr_lamp_capacity ;reset lamp fuel level to max 2aea: 8d 01 31 sta lamp_fuel_level 2aed: ad 7c 30 lda hdr_lamp_capacity+1 2af0: 8d 02 31 sta lamp_fuel_level+1 2af3: 20 93 2e jsr InA_GetIndirectValue ;get pointer to $42ff 2af6: 26 2f .dd2 item_rooms_ptr 2af8: a0 12 ldy #18 ;lamp is always object 9 2afa: a9 ff lda #ITEM_HELD 2afc: 91 f0 sta (]ptr),y ;add lightsource object to inventory 2afe: a9 00 lda #$00 ; (in case torch disappeared when it went out?) 2b00: 8d d9 30 sta lamp_empty_flag ;clear lamp-empty flag 2b03: 20 15 2e jsr JJ_DescribeRoom ;redraw room description ; ; Action op $45: clear screen. (This is a no-op.) ; 2b06: 60 O46_ClearScreen rts ; ; Action op $4b: put item A in the same location as item B. ; ; If item A and item B are in the same location, we will redraw the room ; description twice. ; 2b07: 20 18 2e O4B_PutWith jsr JJ_GetActionArg ;get item A index in $f0-f1 2b0a: 20 45 2e jsr JJ_GetItemLocation ;get pointer to item A room data in $f0-f1 2b0d: 20 5d 2e jsr JJ_PushF0F1 ;push on stack 2b10: 20 18 2e jsr JJ_GetActionArg ;get item B index in $f0-f1 2b13: 20 45 2e jsr JJ_GetItemLocation ;get item B room # in A-reg 2b16: 20 60 2e jsr JJ_PopF0F1 ;restore $f0-f1 2b19: a0 00 ldy #$00 2b1b: cd e9 30 cmp current_room ;is item B (destination) in the current room? 2b1e: d0 03 bne :NotCur ;no, branch 2b20: 20 15 2e jsr JJ_DescribeRoom ;yes, redraw room description 2b23: 48 :NotCur pha ;save item B (destination) room 2b24: b1 f0 lda (]ptr),y ;get item A's room 2b26: 8d 99 30 sta div_q_tmp ;save it 2b29: 68 pla ;restore item B's room 2b2a: 91 f0 sta (]ptr),y ;set item A's location to that 2b2c: ad 99 30 lda div_q_tmp ;get item A's original location 2b2f: cd e9 30 cmp current_room ;was it in the current room? 2b32: d0 03 bne :Return ;no, branch 2b34: 20 15 2e jsr JJ_DescribeRoom ;yes, redraw room description 2b37: 60 :Return rts ; ; Computes $f2-f3 / $f0-f1. ; ; On exit: ; $f0-f1: quotient ; $f2-f3: remainder ; ; (preserves all registers) ; • Clear variables ]denom .var $f0 {addr/2} ]numer .var $f2 {addr/2} 2b38: 20 57 2e Divide16 jsr JJ_PushRegs ;preserve registers 2b3b: a2 10 ldx #16 2b3d: 20 6f 2e jsr JJ_PushF4F5 ;preserve $f4-f5 (why?) 2b40: a9 00 lda #$00 2b42: 8d 99 30 sta div_q_tmp 2b45: 8d 9a 30 sta div_q_tmp+1 2b48: 8d 9b 30 sta div_r_tmp 2b4b: 8d 9c 30 sta div_r_tmp+1 2b4e: 0e 99 30 :Loop asl div_q_tmp 2b51: 2e 9a 30 rol div_q_tmp+1 2b54: 06 f2 asl ]numer 2b56: 26 f3 rol ]numer+1 2b58: 2e 9b 30 rol div_r_tmp 2b5b: 2e 9c 30 rol div_r_tmp+1 2b5e: 20 5d 2e jsr JJ_PushF0F1 ;save denominator 2b61: 38 sec 2b62: a5 f0 lda ]denom 2b64: ed 9b 30 sbc div_r_tmp 2b67: 85 f0 sta ]denom 2b69: a5 f1 lda ]denom+1 2b6b: ed 9c 30 sbc div_r_tmp+1 2b6e: 85 f1 sta ]denom+1 2b70: 05 f0 ora ]denom 2b72: f0 04 beq :Den0 2b74: a5 f1 lda ]denom+1 2b76: 10 17 bpl :DenPos 2b78: ee 99 30 :Den0 inc div_q_tmp 2b7b: d0 03 bne :NoInc 2b7d: ee 9a 30 inc div_q_tmp+1 2b80: 38 :NoInc sec 2b81: a9 00 lda #$00 2b83: e5 f0 sbc ]denom 2b85: 8d 9b 30 sta div_r_tmp 2b88: a9 00 lda #$00 2b8a: e5 f1 sbc ]denom+1 2b8c: 8d 9c 30 sta div_r_tmp+1 2b8f: 20 60 2e :DenPos jsr JJ_PopF0F1 ;restore denominator 2b92: ca dex ;done all bits? 2b93: d0 b9 bne :Loop ;no, branch ; 2b95: ad 99 30 lda div_q_tmp ;copy results to zero page 2b98: 85 f0 sta ]denom 2b9a: ad 9a 30 lda div_q_tmp+1 2b9d: 85 f1 sta ]denom+1 2b9f: ad 9b 30 lda div_r_tmp 2ba2: 85 f2 sta ]numer 2ba4: ad 9c 30 lda div_r_tmp+1 2ba7: 85 f3 sta ]numer+1 2ba9: 20 72 2e jsr JJ_PopF4F5 ;restore $f4-f5 2bac: 20 5a 2e jsr JJ_PopRegs ;restore registers 2baf: 60 rts 2bb0: 00 00 00 00+ .junk 592 2e00: 4c 00 08 jmp Entry JJ_ProcessActions 2e03: 4c 00 1f jmp J_ProcessActions ;process actions and occurrences JJ_ActionLoopEnd 2e06: 4c 03 1f jmp J_ActionLoopEnd ;jump to end of action scan loop 2e09: 4c 09 17 JJ_SaveGame jmp J_SaveGame ;save the game 2e0c: 4c .dd1 $4c ;not used as a jump cond_handlers_ind 2e0d: 0c 17 .dd2 J_CondHandlers JJ_ShowInventory 2e0f: 4c 03 17 jmp J_ShowInventory ;print the player's inventory JJ_PrintItemName 2e12: 4c 15 17 jmp J_PrintItemName ;print the name of an item 2e15: 4c 00 17 JJ_DescribeRoom jmp J_DescribeRoom ;redraw room description 2e18: 4c 06 17 JJ_GetActionArg jmp J_GetActionArg ;$f0-f1 = action argument JJ_AskDiskOrTape 2e1b: 4c 0f 17 jmp J_AskDiskOrTape ;ask player: "disk or tape?" JJ_PrintStringCOUT 2e1e: 4c 12 17 jmp J_PrintStringCOUT ;print null-terminated string through COUT routine 2e21: 4c 09 27 JJ_Divide16 jmp J_Divide16 ;$f0-f1 = $f2-f3 / $f0-f1 (rem in $f2-f3) 2e24: 4c a8 2e jmp NopRts 2e27: 4c a8 2e jmp NopRts 2e2a: 4c .dd1 $4c 2e2b: 03 27 act_oper_ind .dd2 J_act_oper_tab 2e2d: 4c 00 08 J_Start jmp Entry ;begin (or restart) 2e30: 4c 03 08 JJ_PrintNonNull jmp J_PrintNonNull ;prints char ($01-7f) unless it's $00 2e33: 4c 06 08 JJ_PrintCR jmp J_PrintCR ;prints CR (clear to EOL, move to start of new line) 2e36: 4c 0f 08 JJ_PrintString jmp J_PrintString ;prints a null-terminated string ($f0-f1) 2e39: 4c 15 08 JJ_GetInput jmp J_GetInput ;get player input into key buffer 2e3c: 4c 18 08 JJ_ClearScreen jmp J_ClearScreen ;clear screen 2e3f: 4c 0c 08 JJ_PrintNChars jmp J_PrintNChars ;print the next N chars 2e42: 4c 09 08 JJ_PrintL1Str jmp J_PrintL1Str ;print a string start starts with a len byte JJ_GetItemLocation 2e45: 4c 1e 08 jmp J_GetItemLocation ;$f0-f1 point into room data; A-reg=room# JJ_PrintSignedDec 2e48: 4c 1b 08 jmp J_PrintSignedDec ;print $f0-f1 as decimal value JJ_PrintFlashing 2e4b: 4c 12 08 jmp J_PrintFlashStr ;print null-terminated string ($f0-f1), flash mode 2e4e: 4c 24 14 JJ_DecF0F1 jmp J_DecF0F1 ;$f0-f1 -- 2e51: 4c 1b 14 JJ_IncF0F1 jmp J_IncF0F1 ;$f0-f1 ++ InA_GetInlineData 2e54: 4c 3c 14 jmp J_GetInlineData ;$f0-f1 = inline (copy in $fc-fd) 2e57: 4c 21 08 JJ_PushRegs jmp J_PushRegs ;AXYP -> stack 2e5a: 4c 24 08 JJ_PopRegs jmp J_PopRegs ;stack -> AXYP 2e5d: 4c 03 14 JJ_PushF0F1 jmp J_PushF0F1 ;$f0-f1 -> stack 2e60: 4c 06 14 JJ_PopF0F1 jmp J_PopF0F1 ;stack -> $f0-f1 2e63: 4c 27 14 JJ_DecF4F5 jmp J_DecF4F5 ;$f4-f5 -- 2e66: 4c 1e 14 JJ_IncF4F5 jmp J_IncF4F5 ;$f4-f5 ++ 2e69: 4c 2a 14 JJ_DecF2F3 jmp J_DecF2F3 ;$f2-f3 -- 2e6c: 4c 21 14 JJ_IncF2F3 jmp J_IncF2F3 ;$f2-f3 ++ 2e6f: 4c 09 14 JJ_PushF4F5 jmp J_PushF4F5 ;$f4-f5 -> stack 2e72: 4c 0c 14 JJ_PopF4F5 jmp J_PopF4F5 ;stack -> $f4-f5 2e75: 4c 0f 14 JJ_PushF2F3 jmp J_PushF2F3 ;$f2-f3 -> stack 2e78: 4c 12 14 JJ_PopF2F3 jmp J_PopF2F3 ;stack -> $f2-f3 2e7b: 4c 33 14 InA_SubF0F1_Ind jmp J_SubF0F1_Ind ;$fa-fb = $f0-f1 - (*inline); N/Z/C set InA_SubF0F1_Inline 2e7e: 4c 36 14 jmp J_SubF0F1_Inline ;$fa-fb = $f0-f1 - inline; N/Z/C set 2e81: 4c 2d 14 JJ_SetF2F3_F0F1 jmp J_SetF2F3_F0F1 ;$f2-f3 = $f0-f1 2e84: 4c 30 14 JJ_SetF4F5_F0F1 jmp J_SetF4F5_F0F1 ;$f4-f5 = $f0-f1 2e87: 4c 39 14 JJ_AddF0F1_F4F5 jmp J_AddF0F1_F4F5 ;$f0-f1 += $f4-f5 JJ_PushFullState 2e8a: 4c 15 14 jmp J_PushFullState ;AXYP $f0-f9 -> stack 2e8d: 4c 18 14 JJ_PopFullState jmp J_PopFullState ;stack -> AXYP $f0-f9 InA_SetIndirectValue 2e90: 4c 00 14 jmp J_SetIndirectValue ;(*inline) = $f0-f1 InA_GetIndirectValue 2e93: 4c 3f 14 jmp J_GetIndirectValue ;$f0-f1 = (*inline) 2e96: 4c 42 14 JJ_PushF6F7 jmp J_PushF6F7 ;$f6-f7 -> stack 2e99: 4c 45 14 JJ_PopF6F7 jmp J_PopF6F7 ;stack -> $f6-f7 2e9c: 4c 48 14 JJ_PushF8F9 jmp J_PushF8F9 ;$f8-f9 -> stack 2e9f: 4c 4b 14 JJ_PopF8F9 jmp J_PopF8F9 ;stack -> $f8-f9 2ea2: 4c 4e 14 JJ_IncF8F9 jmp J_IncF8F9 ;$f8-f9 ++ JJ_CountHeldObjs 2ea5: 4c 06 27 jmp J_CountHeldObjs ;$f4 = number of objects in inventory 2ea8: ea NopRts nop 2ea9: 60 rts 2eaa: 00 .dd1 $00 2eab: 00 regsv_tmp_a .dd1 $00 ;temporary storage 2eac: 32 regsv_tmp_p .dd1 $32 ;temporary storage 2ead: 63 16 regsv_ret_addr .dd2 $1663 ;temporary storage 2eaf: 01 noflash_flag .dd1 $01 ;used for text output 2eb0: bc f4 kbd_rng_seed .dd2 $f4bc ;random number seed, updated while waiting for key 2eb2: 01 use_disk_flag .dd1 $01 ;0=tape, 1=disk 2eb3: 00 00 00 00+ .align $0100 (77 bytes) ; ; Pointers to tables. ; 2f00: df 44 action_verb_ptr .dd2 action_verb ;pointer to table with verb indices for actions action_nou_prc_ptr 2f02: db 45 .dd2 action_nou_prc ;pointer to table with noun or percent values for act 2f04: d7 46 action_op0_ptr .dd2 action_op0_tab ;pointer to action opcodes 2f06: d3 47 .dd2 action_op1_tab ; (max 4 per action) 2f08: cf 48 .dd2 action_op2_tab 2f0a: cb 49 .dd2 action_op3_tab 2f0c: c7 4a condition0_ptr .dd2 condition0_tab ;pointer to action conditions 2f0e: bf 4c .dd2 condition1_tab ; (max 5 per action) 2f10: b7 4e .dd2 condition2_tab 2f12: af 50 .dd2 condition3_tab 2f14: a7 52 .dd2 condition4_tab 2f16: 9f 54 room_descrs_ptr .dd2 room_descrs ;pointer to room description text pointers 2f18: eb 54 vis_exits_n_ptr .dd2 visible_exits_n ;pointer to north exits table 2f1a: 37 55 .dd2 visible_exits_s ;pointer to south exits table 2f1c: 83 55 .dd2 visible_exits_e ;pointer to east exits table 2f1e: cf 55 .dd2 visible_exits_w ;pointer to west exits table 2f20: 1b 56 .dd2 visible_exits_u ;pointer to up exits table 2f22: 67 56 .dd2 visible_exits_d ;pointer to down exits table 2f24: b3 56 messages_ptr .dd2 messages ;pointer to messages table 2f26: ff 42 item_rooms_ptr .dd2 item_rooms ;pointer to item location data table 2f28: 9f 43 item_names_ptr .dd2 item_names ;pointer to item name table item_initroom_ptr 2f2a: 3f 44 .dd2 item_initrooms ;pointer to item initial location table 2f2c: fe 42 .dd2 T42FE ;(not used? points to end of item name string pool) 2f2e: 38 31 noun_words_ptr .dd2 noun_words ;pointer to noun list 2f30: af 32 verb_words_ptr .dd2 verb_words ;pointer to verb list 2f32: 01 .dd1 $01 ; ; Player command input buffer. The first 24 bytes are zeroed, though we accept ; at most 18 characters. (I have a sneaking suspicion somebody mixed up "18" ; and "$18" in the sources, though it's necessary to be at least 19 so that the ; contents are properly null-terminated.) ; ; The first 256 bytes is also used as a buffer for game state while loading or ; saving it. ; 2f33: 00 kbd_scratch_buf .dd1 $00 ;saved game: adventure number (low) 2f34: 00 adv_num_hi .dd1 $00 ;saved game: adventure number (high) ; ; The next 61 bytes ($2f35-2f71) are copied out to $30c7-3103 when the game is ; loaded, and back before it's saved. 2f35: 00 00 00 00+ save_game_data .junk 61 ; 2f72: 0d 22 22 0d+ .junk 192 3032: 00 save_state_end .dd1 $00 ;last byte in saved-game scratch area ; thing_found_flag 3033: 50 .dd1 $50 3034: 6f .junk 1 3035: 50 tmp_save_x2 .dd1 $50 3036: 6f 50 6f d0+ .junk 29 3053: b4 00 adventure_vers .dd2 180 ;version number 3055: 59 57 .junk 2 3057: 0c 00 adventure_num .dd2 12 ;adventure #12 3059: 40 screen_cleared? .dd1 $40 ;written, never read 305a: 3c 50 6f 50+ .junk 13 actionop_arg_idx 3067: ff 8a .dd2 $8aff ;current index into action op args (really 8-bit) ; ; These values are defined in the header of an adventure data file on other ; systems. They're global values that affect the interpretation of the other ; structures. ; 3069: 04 00 hdr_word_len .dd2 $0004 ;char length of nouns and verbs hdr_max_nounverb 306b: 4a 00 .dd2 $004a ;max verb/noun number (one list is padded to match) 306d: fb 00 hdr_max_action .dd2 $00fb ;max action number 306f: 4f 00 hdr_max_item .dd2 $004f ;maximum item number (count - 1) 3071: 52 00 hdr_max_msg .dd2 $0052 ;maximum message number (count - 1) 3073: 25 00 hdr_max_room .dd2 $0025 ;maximum room number (count - 1) 3075: 07 00 hdr_max_held .dd2 $0007 ;maximum number of objects player can hold 3077: 04 00 hdr_start_room .dd2 $0004 ;initial room number hdr_num_treasures 3079: 00 00 .dd2 $0000 ;number of treasures in the game (victory cond) hdr_lamp_capacity 307b: 64 00 .dd2 $0064 ;maximum capacity of lightsource obj 307d: 00 debug_flag .dd1 $00 ;debug level: 0 (off), 1, or 2 hdr_treasure_room 307e: 00 00 .dd2 $0000 ;room# where treasures are stored ; ; Input trim buffer. Holds up to 24 bytes. 3080: 00 43 59 43+ word_trim_buf .junk 24 ; 3098: 6f .junk 1 3099: 00 00 div_q_tmp .dd2 $0000 309b: 00 00 div_r_tmp .dd2 $0000 309d: 5b tmp_save_reg1 .dd1 $5b 309e: b0 tmp_save_reg2 .dd1 $b0 309f: a7 b0 f3 b0+ .junk 22 30b5: 06 2d 00 00+ dec_outbuf .junk 7 ;output buf for decimal print: len byte + 6 chars 30bc: 00 parsed_verb_idx .dd1 $00 ;index of parsed verb (0-74 here) 30bd: 00 .junk 1 30be: 00 parsed_noun_idx .junk 1 ;index of parsed noun (uses 0 "ANY" if none) 30bf: 00 .junk 1 cmd_not_hnd_flag 30c0: 00 .dd1 $00 ;true until command is handled 30c1: 00 .junk 1 accum_cond_result 30c2: 00 .dd1 $00 ;cumulative result of testing conditions 30c3: ff occur_flag .dd1 $ff ;set if we're processing occurrences (vs. ops)? 30c4: 00 continue_flag .dd1 $00 ;set by "continue" action op 30c5: 27 noun_or_percent .dd1 $27 ;action noun index, or occurrence percent chance 30c6: 0a action_verb_idx .dd1 $0a ; ; $30c7-3103 are stored in save game file part 1. This includes the flags, ; counters, and current/alternate rooms. ; counter_register 30c7: d6 00 .dd2 $00d6 ;counter register, a/k/a "current counter" ; ; 32 action flags. Action conditions and operations can set/clear/test these as ; boolean values. They hold $00 for false and $ff for true. ; 30c9: 00 00 00 00+ action_flags .fill 15,$00 ;flags 0-14 30d8: 00 darkness_flag .dd1 $00 ;flag 15: room is dark (so you need to bring light) 30d9: 00 lamp_empty_flag .dd1 $00 ;flag 16: nonzero if lightsource is empty 30da: 00 00 00 00+ .fill 15,$00 ;flags 17-31 ; 30e9: 04 00 current_room .dd2 $0004 ;number of room player is currently in 30eb: 00 6f def_alt_room .dd2 $6f00 ;default "alternate room" 30ed: 00 6f 00 6f .junk 4 ; ; Nine storage slots for the 16-bit counters. ; 30f1: 03 00 50 6f+ game_counters .junk 16 ;counters 0-7 3101: 64 00 lamp_fuel_level .dd2 $0064 ;counter #8 is time remaining on lamp ; ; (Byte at $3103 is saved and restored, but shouldn't be.) 3103: 15 04 item_names_len .dd2 $0415 ;total length of item name data ; 3105: 50 6f 50 6f+ .junk 51 ; ; Nouns 0-74. These aren't really null-terminated strings; rather, they are 4- ; character words that begin with $00 or '*', indicating whether they are ; distinct words or aliases. They're formatted as strings because it's ; (usually) easier to read that way. ; 3138: 00 noun_words .dd1 $00 3139: 41 4e 59 00 .zstr ‘ANY’ ;noun 0 (implied when no noun provided) 313d: 00 .dd1 $00 313e: 4e 4f 52 54+ .zstr ‘NORT’ ;nouns 1-6 must be the directions 3143: 53 4f 55 54+ .zstr ‘SOUT’ 3148: 45 41 53 54+ .zstr ‘EAST’ 314d: 57 45 53 54+ .zstr ‘WEST’ 3152: 55 50 00 .zstr ‘UP’ 3155: 00 .dd1 $00 3156: 00 .dd1 $00 3157: 44 4f 57 4e+ .zstr ‘DOWN’ 315c: 4b 49 4e 47+ .zstr ‘KING’ 3161: 47 55 41 52+ .zstr ‘GUAR’ 3166: 50 41 4c 41+ .zstr ‘PALA’ 316b: 4d 45 52 43+ .zstr ‘MERC’ 3170: 53 48 49 50+ .zstr ‘SHIP*BOAT*ABOA’ 317f: 4d 41 53 54+ .zstr ‘MAST’ 3184: 53 41 49 4c+ .zstr ‘SAIL’ 3189: 4d 45 44 49+ .zstr ‘MEDI’ ;$10 318e: 41 52 4f 55+ .zstr ‘AROU’ 3193: 4f 43 45 41+ .zstr ‘OCEA*WATE*LIQU’ 31a2: 50 41 53 53+ .zstr ‘PASS’ 31a7: 48 41 4c 4c+ .zstr ‘HALL’ 31ac: 43 41 56 45+ .zstr ‘CAVE’ 31b1: 54 41 42 4c+ .zstr ‘TABL’ 31b6: 53 54 4f 4e+ .zstr ‘STON’ 31bb: 53 4b 45 4c+ .zstr ‘SKEL*BONE’ 31c5: 4d 41 4e 00 .zstr ‘MAN’ 31c9: 00 .dd1 $00 31ca: 46 4c 49 4e+ .zstr ‘FLIN*STEE’ 31d4: 53 48 4f 56+ .zstr ‘SHOV’ 31d9: 48 55 54 00 .zstr ‘HUT’ ;$20 31dd: 00 .dd1 $00 31de: 4d 4f 55 4e+ .zstr ‘MOUN’ 31e3: 43 52 45 56+ .zstr ‘CREV’ 31e8: 42 4f 58 00 .zstr ‘BOX’ 31ec: 00 .dd1 $00 31ed: 53 54 41 49+ .zstr ‘STAI’ 31f2: 43 49 54 59+ .zstr ‘CITY’ 31f7: 53 54 41 54+ .zstr ‘STAT’ 31fc: 53 43 4f 52+ .zstr ‘SCOR’ 3201: 41 4c 54 41+ .zstr ‘ALTA’ 3206: 43 48 45 53+ .zstr ‘CHES’ 320b: 4b 45 59 00 .zstr ‘KEY’ 320f: 00 .dd1 $00 3210: 43 59 43 4c+ .zstr ‘CYCL’ 3215: 4a 55 4e 47+ .zstr ‘JUNG’ 321a: 50 49 54 00 .zstr ‘PIT’ 321e: 00 .dd1 $00 321f: 43 41 42 49+ .zstr ‘CABI’ 3224: 46 4f 55 4e+ .zstr ‘FOUN’ 3229: 4e 4f 54 45+ .zstr ‘NOTE’ ;$30 322e: 43 4f 54 00 .zstr ‘COT’ 3232: 00 .dd1 $00 3233: 4d 41 52 4b+ .zstr ‘MARK’ 3238: 42 4c 4f 43+ .zstr ‘BLOC’ 323d: 54 4f 52 43+ .zstr ‘TORC’ 3242: 52 55 42 42+ .zstr ‘RUBB’ 3247: 54 45 4c 45+ .zstr ‘TELE’ 324c: 43 4f 4d 50+ .zstr ‘COMP’ 3251: 53 41 4e 44+ .zstr ‘SAND’ 3256: 47 4c 4f 42+ .zstr ‘GLOB’ 325b: 4d 41 53 4b+ .zstr ‘MASK’ 3260: 43 48 41 4c+ .zstr ‘CHAL’ 3265: 49 4e 56 45+ .zstr ‘INVE’ 326a: 53 55 4e 00 .zstr ‘SUN’ 326e: 00 .dd1 $00 326f: 53 57 4f 52+ .zstr ‘SWOR’ 3274: 53 54 52 41+ .zstr ‘STRA’ 3279: 42 45 41 43+ .zstr ‘BEAC’ ;$40 327e: 49 53 4c 41+ .zstr ‘ISLA’ 3283: 41 4e 43 48+ .zstr ‘ANCH’ 3288: 41 53 48 4f+ .zstr ‘ASHO’ 328d: 47 41 4d 45+ .zstr ‘GAME’ 3292: 53 54 41 4c+ .zstr ‘STAL’ 3297: 47 52 4f 55+ .zstr ‘GROU*FLOO’ 32a1: 52 4f 50 45+ .zstr ‘ROPE’ 32a6: 42 41 47 00 .zstr ‘BAG’ 32aa: 2a 47 4f 4c+ .str ‘*GOLD’ ;$4a ; ; Like the nouns, these are four-character strings that begin with $00 or '*'. ; 32af: 00 verb_words .dd1 $00 32b0: 41 55 54 4f+ .zstr ‘AUTO’ ;verb 0 (used for "continue" actions) 32b5: 47 4f 00 .zstr ‘GO’ ;verb 1 must be GO 32b8: 00 .dd1 $00 32b9: 2a 50 52 4f+ .zstr ‘*PROC*RIDE*RUN’ 32c8: 2a 43 4c 49+ .zstr ‘*CLIM*ENTE*EXIT’ 32d8: 53 41 56 45+ .zstr ‘SAVE’ 32dd: 44 49 47 00 .zstr ‘DIG’ 32e1: 00 .dd1 $00 32e2: 54 41 4b 45+ .zstr ‘TAKE*GET’ ;verb 10 must be TAKE 32eb: 2a 43 41 52+ .zstr ‘*CARR*GRAB*HOLD*STEA’ 3300: 46 49 4c 4c+ .zstr ‘FILL’ ;$10 3305: 47 49 56 45+ .zstr ‘GIVE’ 330a: 44 52 4f 50+ .zstr ‘DROP*LOWE*PUT’ ;verb 18 must be DROP 3318: 2a 54 48 52+ .zstr ‘*THRO’ 331e: 45 58 41 4d+ .zstr ‘EXAM*STUD*LOOK*SEE’ 3331: 2a 57 41 54+ .zstr ‘*WATC’ 3337: 53 41 49 4c+ .zstr ‘SAIL*NAVI’ 3341: 50 55 53 48+ .zstr ‘PUSH*SHOV*MOVE*SHAK’ ;$20 (SHAK) 3355: 4f 50 45 4e+ .zstr ‘OPEN*UNLO’ 335f: 4c 49 47 48+ .zstr ‘LIGH*IGNI*BURN’ 336e: 42 52 45 41+ .zstr ‘BREA*DEST*SMAS’ 337d: 41 54 54 41+ .zstr ‘ATTA*KILL’ 3387: 45 4d 50 54+ .zstr ‘EMPT’ 338c: 50 4f 55 52+ .zstr ‘POUR*SPIL’ 3396: 55 4e 54 49+ .zstr ‘UNTI’ 339b: 55 4e 4c 49+ .zstr ‘UNLI’ 33a0: 52 45 41 44+ .zstr ‘READ’ ;$30 33a5: 53 4c 45 45+ .zstr ‘SLEE’ 33aa: 57 45 41 52+ .zstr ‘WEAR’ 33af: 52 45 4d 4f+ .zstr ‘REMO’ 33b4: 44 52 49 4e+ .zstr ‘DRIN’ 33b9: 48 45 4c 50+ .zstr ‘HELP’ 33be: 53 41 59 00 .zstr ‘SAY’ 33c2: 2a 53 43 52+ .zstr ‘*SCRE*YELL*HOLL’ 33d2: 51 55 49 54+ .zstr ‘QUIT’ 33d7: 49 4e 56 45+ .zstr ‘INVE’ 33dc: 4a 55 4d 50+ .zstr ‘JUMP’ 33e1: 50 52 41 59+ .zstr ‘PRAY’ 33e6: 54 49 45 00 .zstr ‘TIE’ 33ea: 00 .dd1 $00 33eb: 54 4f 00 .zstr ‘TO’ 33ee: 00 .dd1 $00 33ef: 00 .dd1 $00 33f0: 42 55 59 00 .zstr ‘BUY’ ;$40 33f4: 2a 50 55 52+ .zstr ‘*PURC’ 33fa: 4f 4e 00 .zstr ‘ON’ 33fd: 00 .dd1 $00 33fe: 2a 41 54 00 .zstr ‘*AT’ 3402: 00 .dd1 $00 3403: 00 .dd1 $00 3404: 49 4e 00 .zstr ‘IN’ 3407: 00 .dd1 $00 3408: 00 .dd1 $00 3409: 52 41 49 53+ .zstr ‘RAIS*LIFT*WEIG’ 3418: 53 54 45 50+ .zstr ‘STEP*WALK’ 3422: 57 41 49 54+ .zstr ‘WAIT’ ;$4a ; ; Room description text. ; ; On screen, these are prefixed with "I'm in a". If something different is ; desired, such as "I'm in an" or "I'm on a", a leading '*' suppresses the ; prefix string. ; 3427: 0c 52 6f 79+ T3427 .l1str ‘Royal palace’ ;room #1 3434: 0c 50 65 72+ T3434 .l1str ‘Persian city’ 3441: 0c 50 65 72+ T3441 .l1str ‘Persian city’ 344e: 0c 50 65 72+ T344E .l1str ‘Persian city’ 345b: 16 2a 49 20+ T345B .l1str ‘*I am at a Persian bay’ 3472: 15 2a 49 20+ T3472 .l1str ‘*I am on a large ship’ 3488: 15 2a 49 27+ T3488 .l1str ‘*I'm on a sandy beach’ 349e: 00 T349E .dd1 $00 349f: 0c 64 65 6e+ T349F .l1str ‘dense jungle’ 34ac: 0c 64 65 6e+ T34AC .l1str ‘dense jungle’ 34b9: 09 64 61 6d+ T34B9 .l1str ‘damp cave’ 34c3: 0b 63 72 6f+ T34C3 .l1str ‘crow's-nest’ 34cf: 16 2a 49 27+ T34CF .l1str ‘*I'm on a small island’ 34e6: 16 2a 49 27+ T34E6 .l1str ‘*I'm on a small island’ 34fd: 09 67 72 61+ T34FD .l1str ‘grass hut’ 3507: 0b 64 61 72+ T3507 .l1str ‘dark cavern’ 3513: 12 2a 49 27+ T3513 .l1str ‘*I'm on a mountain’ 3526: 16 2a 49 27+ T3526 .l1str ‘*I'm on a small island’ 353d: 16 2a 49 27+ T353D .l1str ‘*I'm on a rocky strand’ 3554: 18 2a 49 27+ T3554 .l1str ‘*I'm on a long staircase’ 356d: 0d 73 61 63+ T356D .l1str ‘sacred temple’ 357b: 0d 73 61 63+ T357B .l1str ‘sacred temple’ 3589: 0e 68 69 64+ T3589 .l1str ‘hidden chamber’ 3598: 0e 68 69 64+ T3598 .l1str ‘hidden chamber’ 35a7: 0d 73 61 63+ T35A7 .l1str ‘sacred temple’ 35b5: 00 T35B5 .dd1 $00 35b6: 0d 6d 75 73+ T35B6 .l1str ‘musty hallway’ 35c4: 0b 73 6d 61+ T35C4 .l1str ‘small cabin’ 35d0: 08 63 6f 7a+ T35D0 .l1str ‘cozy cot’ 35d9: 0b 64 61 6d+ T35D9 .l1str ‘damp grotto’ 35e5: 00 T35E5 .dd1 $00 35e6: 16 2a 49 27+ T35E6 .l1str ‘*I'm on a grassy plain’ 35fd: 08 64 65 65+ T35FD .l1str ‘deep pit’ 3606: 08 64 65 65+ T3606 .l1str ‘deep pit’ 360f: 18 2a 49 27+ T360F .l1str ‘*I'm in an enormous cave’ 3628: 18 2a 49 27+ T3628 .l1str ‘*I'm in an enormous cave’ 3641: 0f 4c 4f 54+ T3641 .l1str ‘LOT OF TROUBLE!’ ;limbo room ; ; Message text. ; 3651: 00 T3651 .dd1 $00 3652: 6b 57 65 6c+ T3652 .l1str ‘Welcome to Adventure 12: "THE GOLDEN VOYAGE"’ + $0a,‘by William Demas & Scott Adams’,$0a,‘Dedic’ + ‘ated: British band "QUEEN"’ 36be: 0a 73 6f 6d+ T36BE .l1str ‘something!’ 36c9: 06 57 68 65+ T36C9 .l1str ‘Where?’ 36d0: 12 53 6f 6d+ T36D0 .l1str ‘Something rattles.’ 36e3: 23 54 68 65+ T36E3 .l1str ‘The statue topples down the stairs.’ 3707: 07 49 20 66+ T3707 .l1str ‘I found’ 370f: 08 6e 6f 74+ T370F .l1str ‘nothing.’ 3718: 36 49 74 20+ T3718 .l1str ‘It appears to be broken. Strange markings are ’ + ‘present.’ 374f: 1e 54 68 65+ T374F .l1str ‘The stones mysteriously unite!’ 376e: 15 49 74 20+ T376E .l1str ‘It contains medicine.’ 3784: 18 45 76 65+ T3784 .l1str ‘Everything appears grey.’ 379d: 02 4f 4b T379D .l1str ‘OK’ 37a0: 05 4f 55 43+ T37A0 .l1str ‘OUCH!’ 37a6: 16 49 20 73+ T37A6 .l1str ‘I see nothing special.’ 37bd: 1d 48 65 27+ T37BD .l1str ‘He's been stung by scorpions.’ 37db: 08 4c 41 4e+ T37DB .l1str ‘LAND HO!’ 37e4: 06 49 20 68+ T37E4 .l1str ‘I hear’ 37eb: 2e 4f 6e 65+ T37EB .l1str ‘One great big EYE has a focus in my direction!’ 381a: 30 49 20 73+ T381A .l1str ‘I see a picture of a mountain and the word "SU’ + ‘N"’ 384b: 1f 49 20 63+ T384B .l1str ‘I can't tell which way that is!’ 386b: 2e 4d 65 72+ T386B .l1str ‘Merchant calls me a thief and slits my throat!’ 389a: 24 54 68 65+ T389A .l1str ‘There's a tremendous flash of light!’ 38bf: 0a 49 27 6d+ T38BF .l1str ‘I'm blind!’ 38ca: 18 48 65 20+ T38CA .l1str ‘He gives a great big CRY’ 38e3: 24 48 69 67+ T38E3 .l1str ‘High atop the mast is a crow's-nest.’ 3908: 7e 4b 49 4e+ T3908 .l1str ‘KING: I have been given only 3 days to live. Y’ + ‘ou are to seek for a way to restore my vi’ + ‘tality. The gold is yours. Go now!’ 3987: 14 4f 48 20+ T3987 .l1str ‘OH NO! I can't swim!’ 399c: 07 43 79 63+ T399C .l1str ‘Cyclops’ 39a4: 0c 49 74 27+ T39A4 .l1str ‘It's locked.’ 39b1: 1a 49 20 73+ T39B1 .l1str ‘I see a picture of a cave.’ 39cc: 1b 67 72 61+ T39CC .l1str ‘grabs me and eats me alive!’ 39e8: 19 54 68 65+ T39E8 .l1str ‘The statue comes to life!’ 3a02: 15 49 74 27+ T3A02 .l1str ‘It's holding a sword.’ 3a18: 16 53 6f 72+ T3A18 .l1str ‘Sorry, it won't BUDGE!’ 3a2f: 0c 54 65 6c+ T3A2F .l1str ‘Tell me how?’ 3a3c: 47 4d 41 4e+ T3A3C .l1str ‘MAN: I'm afraid it's too late for me. Appeal t’ + ‘o the’,$0a,‘ Gods for help!’ 3a84: 1c 54 68 65+ T3A84 .l1str ‘The ground shakes violently!’ 3aa1: 44 49 27 76+ T3AA1 .l1str ‘I've desecrated the holy fountain.’,$0a,‘I'm s’ + ‘truck down by a THUNDERBOLT!’ 3ae6: 11 54 68 65+ T3AE6 .l1str ‘The King grabs it’ 3af8: 22 61 6e 64+ T3AF8 .l1str ‘and DIES! Guards have me beheaded.’ 3b1b: 19 49 20 68+ T3B1B .l1str ‘I have failed my mission.’ 3b35: 12 49 74 27+ T3B35 .l1str ‘It's getting dark!’ 3b48: 0f 4d 6f 72+ T3B48 .l1str ‘Morning! I have’ 3b58: 0a 47 6f 6f+ T3B58 .l1str ‘Goodnight.’ 3b63: 06 32 20 64+ T3B63 .l1str ‘2 days’ 3b6a: 05 31 20 64+ T3B6A .l1str ‘1 day’ 3b70: 1c 6c 65 66+ T3B70 .l1str ‘left to complete my mission.’ 3b8d: 10 54 68 65+ T3B8D .l1str ‘The sun has set.’ 3b9e: 2d 4e 69 67+ T3B9E .l1str ‘Night air is COLD!’,$0a,‘I catch pneumonia and’ + ‘ die.’ 3bcc: 12 66 61 69+ T3BCC .l1str ‘failed my mission.’ 3bdf: 12 49 27 6d+ T3BDF .l1str ‘I'm in great PAIN!’ 3bf2: 22 4d 79 20+ T3BF2 .l1str ‘My whole body has become infected.’ 3c15: 12 53 74 61+ T3C15 .l1str ‘Statue follows me.’ 3c28: 18 53 74 61+ T3C28 .l1str ‘Statue swings its sword.’ 3c41: 0d 49 74 20+ T3C41 .l1str ‘It missed me!’ 3c4f: 15 49 27 76+ T3C4F .l1str ‘I've been cut in two!’ 3c65: 16 49 20 66+ T3C65 .l1str ‘I fend off its attack.’ 3c7c: 42 49 27 6d+ T3C7C .l1str ‘I'm lynched by angry mourners.’,$0a,‘Their Kin’ + ‘g is dead. (AND SO AM I)!!’ 3cbf: 10 54 68 65+ T3CBF .l1str ‘The man is dead!’ 3cd0: 3b 47 65 74+ T3CD0 .l1str ‘Get your copy of "FROG" from Adventure Interna’ + ‘tional today!’ 3d0c: 15 54 68 65+ T3D0C .l1str ‘The ship drifts away.’ 3d22: 10 4e 6f 74+ T3D22 .l1str ‘Nothing happens.’ 3d33: 0c 49 74 27+ T3D33 .l1str ‘It's full of’ 3d40: 06 77 61 74+ T3D40 .l1str ‘water.’ 3d47: 11 61 20 73+ T3D47 .l1str ‘a strange liquid.’ 3d59: 48 61 6e 64+ T3D59 .l1str ‘and transforms into a young man. CONGRATULATIO’ + ‘NS!!’,$0a,‘Mission accomplished.’ 3da2: 11 64 72 69+ T3DA2 .l1str ‘drinks the liquid’ 3db4: 18 61 6e 64+ T3DB4 .l1str ‘and yells "It's EMPTY!".’ 3dcd: 0d 77 6f 6e+ T3DCD .l1str ‘won't let me.’ 3ddb: 21 43 79 63+ T3DDB .l1str ‘Cyclops staggers and steps on me!’ 3dfd: 18 49 27 6c+ T3DFD .l1str ‘I'll only defend myself.’ 3e16: 08 4d 65 72+ T3E16 .l1str ‘Merchant’ 3e1f: 18 50 6c 65+ T3E1F .l1str ‘Please be more specific.’ 3e38: 13 49 20 66+ T3E38 .l1str ‘I feel much better.’ 3e4c: 09 45 6d 70+ T3E4C .l1str ‘Empty it?’ 3e56: 06 53 6f 72+ T3E56 .l1str ‘Sorry.’ 3e5d: 13 48 65 20+ T3E5D .l1str ‘He has me executed.’ 3e71: 32 53 75 72+ T3E71 .l1str ‘Surprised merchant grabs it and runs like a th’ + ‘ief!’ 3ea4: 1d 53 74 61+ T3EA4 .l1str ‘Statue attacks while I sleep!’ 3ec2: 19 52 6f 70+ T3EC2 .l1str ‘Rope slides into the pit.’ 3edc: 06 50 4c 4f+ T3EDC .l1str ‘PLOOSH’ 3ee3: 05 59 55 43+ T3EE3 .l1str ‘YUCK!’ ; ; Item name data, stored as strings with a leading length byte. If the name ; ends with "/WORD/", the item will effectively have GET/DROP actions created ; for it. The byte that follows the slash is the item number. ; ; (The item number could be inferred from the string's position in the list, but ; it's a little simpler to make it explicit.) ; 3ee9: 00 L3EE9 .dd1 $00 ;item 0 doesn't exist 3eea: 0d 50 61 6c+ L3EEA .l1str ‘Palace guards’ 3ef8: 09 41 67 65+ L3EF8 .l1str ‘Aged King’ 3f02: 06 50 61 6c+ L3F02 .l1str ‘Palace’ 3f09: 0a 4c 61 72+ L3F09 .l1str ‘Large ship’ 3f14: 04 4d 61 73+ L3F14 .l1str ‘Mast’ 3f19: 04 53 61 69+ L3F19 .l1str ‘Sail’ 3f1e: 06 41 6e 63+ L3F1E .l1str ‘Anchor’ 3f25: 0e 53 6b 65+ L3F25 .l1str ‘Skeleton/SKEL/’ 3f34: 08 .dd1 $08 3f35: 0f 4c 69 74+ L3F35 .l1str ‘Lit torch/TORC/’ ;light source is always item #9 3f45: 09 .dd1 $09 3f46: 0c 4f 6c 64+ L3F46 .l1str ‘Old box/BOX/’ 3f53: 0a .dd1 $0a 3f54: 10 53 74 72+ L3F54 .l1str ‘Strange fountain’ 3f65: 07 43 72 65+ L3F65 .l1str ‘Crevice’ 3f6d: 03 4d 61 6e L3F6D .l1str ‘Man’ 3f71: 06 4a 75 6e+ L3F71 .l1str ‘Jungle’ 3f78: 0e 48 69 64+ L3F78 .l1str ‘Hidden passage’ 3f87: 12 47 6f 6c+ L3F87 .l1str ‘Gold chalice/CHAL/’ 3f9a: 10 .dd1 $10 3f9b: 04 43 61 76+ L3F9B .l1str ‘Cave’ 3fa0: 0e 4c 6f 6e+ L3FA0 .l1str ‘Long staircase’ 3faf: 13 46 6c 69+ L3FAF .l1str ‘Flint & steel/FLIN/’ 3fc3: 13 .dd1 $13 3fc4: 0f 47 6f 6c+ L3FC4 .l1str ‘Gold mask/MASK/’ 3fd4: 14 .dd1 $14 3fd5: 0e 49 27 6d+ L3FD5 .l1str ‘I'm wearing it’ 3fe4: 0b 53 6d 61+ L3FE4 .l1str ‘Small stone’ 3ff0: 0b 53 6d 61+ L3FF0 .l1str ‘Small stone’ 3ffc: 0b 53 6d 61+ L3FFC .l1str ‘Small stone’ 4008: 0d 53 74 6f+ L4008 .l1str ‘Stone Goddess’ 4016: 11 57 68 69+ L4016 .l1str ‘White globe/GLOB/’ 4028: 1a .dd1 $1a 4029: 09 47 72 61+ L4029 .l1str ‘Grass hut’ 4033: 08 4d 65 72+ L4033 .l1str ‘Merchant’ 403c: 08 4d 65 72+ L403C .l1str ‘Merchant’ 4045: 08 4d 65 72+ L4045 .l1str ‘Merchant’ 404e: 0c 53 68 6f+ L404E .l1str ‘Shovel/SHOV/’ 405b: 1f .dd1 $1f 405c: 0d 53 61 6e+ L405C .l1str ‘Sandals/SAND/’ 406a: 20 .dd1 $20 406b: 10 49 27 6d+ L406B .l1str ‘I'm wearing them’ 407c: 0d 43 6f 6d+ L407C .l1str ‘Compass/COMP/’ 408a: 22 .dd1 $22 408b: 0f 54 65 6c+ L408B .l1str ‘Telescope/TELE/’ 409b: 23 .dd1 $23 409c: 08 44 65 61+ L409C .l1str ‘Dead man’ 40a5: 08 4b 65 79+ L40A5 .l1str ‘Key/KEY/’ 40ae: 25 .dd1 $25 40af: 14 50 69 6c+ L40AF .l1str ‘Pile of rubble/RUBB/’ 40c4: 26 .dd1 $26 40c5: 08 4d 6f 75+ L40C5 .l1str ‘Mountain’ 40ce: 0b 53 74 6f+ L40CE .l1str ‘Stone block’ 40da: 12 4f 72 6e+ L40DA .l1str ‘Ornate chest/CHES/’ 40ed: 29 .dd1 $29 40ee: 03 43 6f 74 L40EE .l1str ‘Cot’ 40f2: 0a 4e 6f 74+ L40F2 .l1str ‘Note/NOTE/’ 40fd: 2b .dd1 $2b 40fe: 08 44 65 65+ L40FE .l1str ‘Deep pit’ 4107: 07 43 79 63+ L4107 .l1str ‘Cyclops’ 410f: 04 43 61 76+ L410F .l1str ‘Cave’ 4114: 14 4d 61 67+ L4114 .l1str ‘Magnificent fountain’ 4129: 05 4f 63 65+ L4129 .l1str ‘Ocean’ 412f: 14 50 69 6c+ L412F .l1str ‘Pile of rubble/RUBB/’ 4144: 31 .dd1 $31 4145: 00 L4145 .dd1 $00 4146: 10 4f 70 65+ L4146 .l1str ‘Open chest/CHES/’ 4157: 33 .dd1 $33 4158: 0d 59 6f 75+ L4158 .l1str ‘Youthful King’ 4166: 10 42 61 67+ L4166 .l1str ‘Bag of gold/BAG/’ 4177: 35 .dd1 $35 4178: 0c 42 72 6f+ L4178 .l1str ‘Broken globe’ 4185: 09 53 63 6f+ L4185 .l1str ‘Scorpions’ 418f: 0b 54 6f 72+ L418F .l1str ‘Torch/TORC/’ 419b: 38 .dd1 $38 419c: 11 43 72 6f+ L419C .l1str ‘Crowd of mourners’ 41ae: 0c 53 74 6f+ L41AE .l1str ‘Stone tablet’ 41bb: 05 41 6c 74+ L41BB .l1str ‘Altar’ 41c1: 0f 53 63 6f+ L41C1 .l1str ‘Scorpion stings’ 41d1: 19 46 65 73+ L41D1 .l1str ‘Festering scorpion stings’ 41eb: 0f 41 6e 69+ L41EB .l1str ‘Animated statue’ 41fb: 0b 53 77 6f+ L41FB .l1str ‘Sword/SWOR/’ 4207: 3f .dd1 $3f 4208: 0c 52 6f 63+ L4208 .l1str ‘Rocky strand’ 4215: 0b 53 61 6e+ L4215 .l1str ‘Sandy beach’ 4221: 0c 53 6d 61+ L4221 .l1str ‘Small island’ 422e: 10 53 68 69+ L422E .l1str ‘Ship is anchored’ 423f: 0c 53 74 6f+ L423F .l1str ‘Stone tablet’ 424c: 0d 42 6c 69+ L424C .l1str ‘Blind cyclops’ 425a: 0a 53 74 61+ L425A .l1str ‘Stalagmite’ 4265: 04 52 6f 70+ L4265 .l1str ‘Rope’ 426a: 17 52 6f 70+ L426A .l1str ‘Rope tied to stalagmite’ 4282: 15 4f 74 68+ L4282 .l1str ‘Other end of the rope’ 4298: 1a 52 6f 70+ L4298 .l1str ‘Rope leading down into pit’ 42b3: 1b 52 6f 70+ L42B3 .l1str ‘Rope leading out of the pit’ 42cf: 0c 44 61 72+ L42CF .l1str ‘Dark hallway’ 42dc: 05 43 61 62+ L42DC .l1str ‘Cabin’ 42e2: 0c 50 65 72+ L42E2 .l1str ‘Persian city’ 42ef: 0e 4c 6f 6e+ L42EF .l1str ‘Long staircase’ 42fe: 00 T42FE .dd1 $00 ; ; 16-bit value indicating which room an item is in. There are 80 entries, but ; entry 0 isn't used. ; ; (Unlike everything else nearby, this is mutable state.) ; 42ff: 00 00 01 00+ item_rooms .bulk $00,$00,$01,$00,$01,$00,$02,$00,$05,$00,$06,$00 + $06,$00,$00,$00,$0d,$00,$00,$00,$0f,$00,$0b,$00 + $00,$00,$07,$00,$07,$00,$00,$00,$00,$00,$0a,$00 + $13,$00,$14,$00,$00,$00,$00,$00,$18,$00,$00,$00 + $00,$00,$13,$00,$00,$00,$0e,$00,$04,$00,$03,$00 + $05,$00,$12,$00,$04,$00,$00,$00,$03,$00,$03,$00 + $00,$00,$00,$00,$00,$00,$0e,$00,$17,$00,$19,$00 + $1c,$00,$1d,$00,$1e,$00,$22,$00,$22,$00,$24,$00 + $05,$00,$00,$00,$00,$00,$00,$00,$00,$00,$08,$00 + $00,$00,$00,$00,$00,$00,$00,$00,$03,$00,$16,$00 + $00,$00,$00,$00,$00,$00,$11,$00,$00,$00,$00,$00 + $00,$00,$06,$00,$24,$00,$00,$00,$1e,$00,$00,$00 + $00,$00,$00,$00,$00,$00,$21,$00,$00,$00,$06,$00 + $00,$00,$15,$00 ; ; Pointers to item names (0-79). ; 439f: e9 3e item_names .dd2 L3EE9 ;item #0 (doesn't exist) 43a1: ea 3e .dd2 L3EEA 43a3: f8 3e .dd2 L3EF8 43a5: 02 3f .dd2 L3F02 43a7: 09 3f .dd2 L3F09 43a9: 14 3f .dd2 L3F14 43ab: 19 3f .dd2 L3F19 43ad: 1e 3f .dd2 L3F1E 43af: 25 3f .dd2 L3F25 43b1: 35 3f .dd2 L3F35 ;item #9 (lightsource) 43b3: 46 3f .dd2 L3F46 43b5: 54 3f .dd2 L3F54 43b7: 65 3f .dd2 L3F65 43b9: 6d 3f .dd2 L3F6D 43bb: 71 3f .dd2 L3F71 43bd: 78 3f .dd2 L3F78 43bf: 87 3f .dd2 L3F87 43c1: 9b 3f .dd2 L3F9B 43c3: a0 3f .dd2 L3FA0 43c5: af 3f .dd2 L3FAF 43c7: c4 3f .dd2 L3FC4 43c9: d5 3f .dd2 L3FD5 43cb: e4 3f .dd2 L3FE4 43cd: f0 3f .dd2 L3FF0 43cf: fc 3f .dd2 L3FFC 43d1: 08 40 .dd2 L4008 43d3: 16 40 .dd2 L4016 43d5: 29 40 .dd2 L4029 43d7: 33 40 .dd2 L4033 43d9: 3c 40 .dd2 L403C 43db: 45 40 .dd2 L4045 43dd: 4e 40 .dd2 L404E 43df: 5c 40 .dd2 L405C 43e1: 6b 40 .dd2 L406B 43e3: 7c 40 .dd2 L407C 43e5: 8b 40 .dd2 L408B 43e7: 9c 40 .dd2 L409C 43e9: a5 40 .dd2 L40A5 43eb: af 40 .dd2 L40AF 43ed: c5 40 .dd2 L40C5 ;$27 43ef: ce 40 .dd2 L40CE 43f1: da 40 .dd2 L40DA 43f3: ee 40 .dd2 L40EE 43f5: f2 40 .dd2 L40F2 43f7: fe 40 .dd2 L40FE 43f9: 07 41 .dd2 L4107 43fb: 0f 41 .dd2 L410F 43fd: 14 41 .dd2 L4114 43ff: 29 41 .dd2 L4129 4401: 2f 41 .dd2 L412F 4403: 45 41 .dd2 L4145 4405: 46 41 .dd2 L4146 4407: 58 41 .dd2 L4158 4409: 66 41 .dd2 L4166 440b: 78 41 .dd2 L4178 440d: 85 41 .dd2 L4185 440f: 8f 41 .dd2 L418F 4411: 9c 41 .dd2 L419C 4413: ae 41 .dd2 L41AE 4415: bb 41 .dd2 L41BB 4417: c1 41 .dd2 L41C1 4419: d1 41 .dd2 L41D1 441b: eb 41 .dd2 L41EB 441d: fb 41 .dd2 L41FB 441f: 08 42 .dd2 L4208 4421: 15 42 .dd2 L4215 4423: 21 42 .dd2 L4221 4425: 2e 42 .dd2 L422E 4427: 3f 42 .dd2 L423F 4429: 4c 42 .dd2 L424C 442b: 5a 42 .dd2 L425A 442d: 65 42 .dd2 L4265 442f: 6a 42 .dd2 L426A 4431: 82 42 .dd2 L4282 4433: 98 42 .dd2 L4298 4435: b3 42 .dd2 L42B3 4437: cf 42 .dd2 L42CF 4439: dc 42 .dd2 L42DC 443b: e2 42 .dd2 L42E2 443d: ef 42 .dd2 L42EF ; ; Initial room numbers for items. This is copied into item_rooms during game ; init. ; 443f: 00 00 01 00+ item_initrooms .bulk $00,$00,$01,$00,$01,$00,$02,$00,$05,$00,$06,$00 + $06,$00,$00,$00,$0d,$00,$00,$00,$0f,$00,$0b,$00 + $00,$00,$07,$00,$07,$00,$00,$00,$00,$00,$0a,$00 + $13,$00,$14,$00,$00,$00,$00,$00,$18,$00,$00,$00 + $00,$00,$13,$00,$00,$00,$0e,$00,$04,$00,$03,$00 + $05,$00,$12,$00,$04,$00,$00,$00,$03,$00,$03,$00 + $00,$00,$00,$00,$00,$00,$0e,$00,$17,$00,$19,$00 + $1c,$00,$1d,$00,$1e,$00,$22,$00,$22,$00,$24,$00 + $05,$00,$00,$00,$00,$00,$00,$00,$00,$00,$08,$00 + $00,$00,$00,$00,$00,$00,$00,$00,$03,$00,$16,$00 + $00,$00,$00,$00,$00,$00,$11,$00,$00,$00,$00,$00 + $00,$00,$06,$00,$24,$00,$00,$00,$1e,$00,$00,$00 + $00,$00,$00,$00,$00,$00,$21,$00,$00,$00,$06,$00 + $00,$00,$15,$00 ; ; Verb for action N (0-251). Will be $00 for occurrences. ; ; Occurrences must come first in the list. ; 44df: 00 00 00 00+ action_verb .bulk $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 + $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 + $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 + $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 + $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 + $00,$00,$00,$0a,$01,$01,$01,$01,$01,$01,$01,$01 + $01,$01,$01,$01,$01,$08,$09,$09,$0a,$01,$0a,$0a + $0a,$0a,$09,$09,$01,$09,$0a,$0a,$0a,$0a,$0a,$0a + $0a,$0a,$0a,$0a,$0a,$0a,$16,$4a,$0a,$0a,$11,$01 + $11,$00,$11,$00,$11,$00,$11,$00,$3d,$11,$11,$11 + $00,$31,$3c,$01,$01,$01,$01,$01,$01,$01,$01,$01 + $01,$01,$0a,$10,$10,$10,$10,$10,$10,$12,$34,$12 + $12,$12,$12,$12,$12,$16,$16,$16,$16,$16,$16,$16 + $16,$16,$16,$16,$16,$16,$16,$16,$16,$16,$16,$16 + $16,$16,$01,$01,$0a,$0a,$0a,$1b,$1b,$1b,$1b,$1b + $1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1b,$1d,$1d,$1d + $1d,$42,$12,$00,$00,$21,$23,$26,$21,$29,$2b,$2c + $16,$2e,$2e,$2f,$30,$32,$32,$0a,$33,$33,$2b,$42 + $12,$36,$36,$3a,$3b,$48,$48,$45,$3e,$3f,$12,$42 + $44,$44,$40,$40,$40,$40,$40,$01,$01,$01,$01,$35 + $44,$3d,$44,$44,$34,$34,$16,$16,$12,$1b,$12,$12 ; ; For occurrences (verb=$00), this is the percent chance of the action ; happening. For actions (verb!=$00), this is the index of the noun (NOT the ; item). ; 45db: 64 00 64 64+ action_nou_prc .bulk $64,$00,$64,$64,$64,$64,$64,$64,$64,$64,$64,$64 + $00,$64,$00,$64,$64,$64,$32,$00,$64,$00,$00,$00 + $64,$2d,$28,$46,$27,$64,$3c,$2d,$64,$64,$64,$00 + $64,$64,$00,$2d,$64,$64,$00,$64,$64,$64,$64,$3c + $64,$64,$64,$64,$64,$64,$64,$64,$64,$64,$64,$64 + $64,$64,$64,$27,$2d,$2f,$31,$3f,$40,$41,$43,$43 + $43,$48,$48,$15,$16,$44,$00,$00,$3c,$09,$10,$10 + $10,$12,$00,$00,$0b,$00,$19,$19,$19,$18,$18,$18 + $36,$36,$37,$37,$38,$38,$2f,$00,$48,$48,$10,$2f + $3b,$00,$3b,$00,$3b,$00,$3b,$00,$00,$49,$49,$49 + $00,$00,$2d,$43,$25,$2e,$0b,$0e,$12,$2c,$17,$20 + $21,$22,$05,$3b,$3b,$3b,$3b,$3b,$3b,$10,$12,$19 + $19,$19,$18,$18,$48,$0e,$18,$18,$19,$19,$19,$1c + $23,$26,$26,$28,$29,$2b,$30,$36,$36,$36,$35,$3b + $3b,$3b,$17,$17,$3e,$3e,$3e,$00,$04,$03,$02,$03 + $02,$01,$03,$01,$04,$03,$04,$04,$00,$26,$26,$26 + $00,$46,$39,$00,$00,$29,$34,$00,$29,$00,$3b,$12 + $2f,$48,$48,$34,$30,$38,$3a,$48,$38,$3a,$3b,$46 + $42,$3d,$00,$00,$00,$05,$06,$42,$48,$45,$48,$46 + $2f,$2f,$0b,$38,$37,$36,$18,$22,$24,$24,$24,$00 + $2d,$00,$2f,$2f,$12,$12,$2f,$00,$3a,$00,$38,$38 ; ; Action opcode table. See the operations function table at $270c. ; ; One table for each of the four possible operations per action. ; 46d7: 01 51 4d 35+ action_op0_tab .bulk $01,$51,$4d,$35,$30,$38,$3a,$3c,$48,$81,$39,$58 + $31,$58,$4f,$2d,$2e,$32,$0d,$51,$51,$33,$66,$51 + $67,$68,$20,$6b,$6a,$69,$18,$1f,$3c,$3c,$58,$3d + $3b,$25,$48,$78,$3c,$09,$3b,$38,$2a,$38,$39,$6f + $35,$38,$39,$35,$35,$35,$35,$35,$39,$39,$35,$35 + $1a,$3a,$39,$84,$0c,$0c,$0c,$0c,$0c,$0c,$0c,$0c + $0c,$0c,$0c,$0c,$0c,$47,$06,$06,$42,$0c,$0c,$0c + $0c,$0c,$06,$06,$0c,$06,$34,$34,$34,$34,$34,$34 + $34,$34,$34,$34,$34,$34,$71,$0c,$34,$0c,$56,$0c + $27,$58,$27,$58,$27,$58,$27,$58,$0c,$37,$37,$37 + $3a,$2c,$0c,$0c,$36,$0c,$0c,$0c,$0c,$0c,$0c,$0c + $0c,$0c,$0c,$7e,$7e,$7e,$0c,$0c,$0c,$0c,$0c,$0c + $0c,$0c,$03,$03,$03,$19,$13,$1e,$08,$08,$08,$0f + $0a,$21,$21,$06,$06,$12,$7b,$10,$10,$10,$06,$71 + $71,$71,$0c,$0c,$22,$22,$34,$7e,$0c,$0c,$0c,$0c + $0c,$0c,$0c,$0c,$0c,$0c,$0c,$0c,$14,$04,$3b,$70 + $23,$0c,$35,$58,$58,$0c,$0c,$7e,$7e,$7e,$70,$7d + $06,$3b,$37,$0c,$6e,$0c,$0c,$0c,$0c,$0c,$0c,$0c + $0c,$0c,$0c,$29,$42,$0c,$0c,$0c,$0c,$0c,$0c,$0c + $0c,$0c,$0c,$0c,$0c,$0c,$0c,$0c,$36,$36,$7b,$7e + $0c,$0c,$0c,$0c,$0c,$0c,$71,$0e,$0c,$0c,$0c,$00 47d3: 4f 4f 00 00+ action_op1_tab .bulk $4f,$4f,$00,$00,$00,$00,$38,$00,$00,$3c,$00,$49 + $3d,$39,$51,$2f,$2f,$51,$4a,$4f,$4d,$48,$3d,$00 + $35,$58,$48,$3c,$39,$3c,$58,$3d,$00,$00,$58,$3f + $3b,$3a,$3e,$3d,$00,$3b,$35,$40,$00,$40,$40,$37 + $00,$40,$40,$00,$00,$00,$00,$00,$40,$40,$00,$00 + $35,$00,$40,$7e,$23,$26,$36,$36,$36,$36,$36,$36 + $36,$36,$36,$36,$36,$00,$02,$02,$00,$36,$3b,$3b + $70,$23,$02,$02,$36,$07,$0c,$0c,$0c,$0c,$0c,$0c + $0c,$0c,$0c,$0c,$0c,$0c,$73,$58,$0c,$3b,$24,$26 + $75,$70,$75,$28,$75,$48,$58,$76,$11,$80,$80,$80 + $3a,$3a,$3d,$36,$35,$36,$58,$36,$1b,$36,$36,$36 + $36,$36,$36,$00,$00,$00,$3a,$3a,$3a,$35,$3d,$35 + $35,$35,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 + $00,$00,$00,$02,$02,$00,$00,$3a,$3a,$3a,$02,$72 + $73,$73,$58,$36,$00,$00,$0c,$00,$58,$58,$58,$58 + $58,$58,$58,$58,$58,$58,$58,$58,$00,$00,$05,$00 + $00,$35,$48,$3a,$48,$48,$48,$00,$1d,$79,$00,$00 + $02,$3b,$37,$48,$00,$4a,$4a,$4a,$37,$37,$3c,$35 + $48,$55,$55,$3f,$00,$36,$36,$48,$03,$35,$35,$35 + $3b,$3b,$3a,$3a,$3a,$3a,$3a,$36,$00,$00,$00,$00 + $3b,$70,$3e,$3e,$3c,$3d,$73,$00,$35,$58,$35,$00 48cf: 3a 3a 00 00+ action_op2_tab .bulk $3a,$3a,$00,$00,$00,$00,$40,$00,$00,$3d,$00,$00 + $29,$49,$53,$3c,$3c,$3e,$49,$51,$49,$49,$49,$00 + $00,$58,$00,$00,$3d,$00,$58,$00,$00,$00,$6c,$00 + $3b,$3a,$83,$00,$00,$3b,$00,$00,$00,$00,$00,$00 + $00,$00,$29,$00,$00,$00,$00,$00,$00,$3c,$00,$00 + $00,$00,$00,$00,$00,$3d,$00,$35,$35,$35,$35,$35 + $35,$00,$00,$38,$00,$00,$35,$35,$00,$00,$7c,$7c + $00,$00,$35,$35,$35,$00,$00,$00,$00,$15,$00,$00 + $15,$00,$15,$00,$15,$00,$00,$53,$00,$4a,$48,$3d + $58,$7f,$58,$3d,$58,$74,$49,$7f,$02,$3a,$3a,$3a + $3b,$58,$00,$35,$00,$00,$7a,$00,$3d,$00,$3a,$00 + $00,$35,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 + $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 + $00,$00,$00,$35,$35,$00,$00,$00,$00,$00,$35,$00 + $00,$00,$1c,$00,$00,$00,$00,$00,$3c,$3c,$3c,$3c + $3c,$3c,$3c,$3c,$3c,$3c,$3c,$3c,$00,$00,$3e,$00 + $00,$00,$16,$49,$00,$00,$00,$00,$00,$00,$00,$00 + $3c,$82,$35,$00,$00,$00,$0b,$00,$00,$00,$3c,$3e + $3a,$25,$70,$00,$00,$00,$00,$3c,$00,$48,$00,$00 + $83,$83,$00,$00,$00,$00,$00,$35,$00,$00,$00,$00 + $35,$00,$83,$83,$84,$00,$00,$00,$37,$00,$37,$00 49cb: 49 3a 00 00+ action_op3_tab .bulk $49,$3a,$00,$00,$00,$00,$17,$00,$00,$37,$00,$00 + $3f,$00,$2b,$51,$51,$00,$00,$3a,$00,$00,$00,$00 + $00,$3a,$00,$00,$3c,$00,$3a,$00,$00,$00,$49,$00 + $3b,$49,$00,$00,$00,$49,$00,$00,$00,$00,$00,$00 + $00,$00,$3f,$00,$00,$00,$00,$00,$00,$00,$00,$00 + $00,$00,$00,$00,$00,$00,$00,$35,$35,$35,$35,$35 + $35,$00,$00,$3a,$00,$00,$00,$00,$00,$00,$3c,$3c + $00,$00,$00,$00,$00,$00,$00,$00,$00,$3d,$00,$00 + $3d,$00,$3d,$00,$3d,$00,$00,$00,$00,$00,$6d,$00 + $49,$3d,$49,$00,$49,$3f,$00,$3d,$35,$3b,$3b,$49 + $00,$00,$00,$00,$00,$00,$77,$00,$00,$00,$35,$00 + $00,$35,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 + $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 + $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 + $00,$00,$77,$00,$00,$00,$00,$00,$3a,$3a,$3a,$3a + $3a,$3a,$3a,$3a,$3a,$3a,$3a,$3a,$00,$00,$00,$00 + $00,$00,$49,$00,$00,$00,$00,$00,$00,$00,$00,$00 + $35,$00,$0c,$00,$00,$00,$00,$00,$00,$00,$3c,$35 + $00,$35,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 + $00,$00,$00,$00,$00,$00,$00,$3c,$00,$00,$00,$00 + $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 ; ; Action conditions table. Each 16-bit entry holds the condition opcode and ; argument, which have been merged as (opcode + arg * 20). ; ; There is one table for each of the 5 possible conditions per action. ; ; Entries with an opcode of zero hold the arguments for action opcodes. (So if ; you have 3 conditions and 3 actions with arguments, you can't hold the whole ; thing in a single action slot.) ; 4ac7: 75 02 00 00+ condition0_tab .bulk $75,$02,$00,$00,$00,$00,$52,$00,$13,$00,$c0,$00 + $20,$01,$bc,$01,$b7,$00,$4c,$02,$b7,$00,$4c,$02 + $4b,$02,$4c,$02,$cc,$10,$4c,$02,$4c,$02,$4c,$02 + $9a,$02,$3c,$00,$d4,$01,$77,$00,$0f,$00,$d4,$01 + $dd,$04,$da,$04,$e6,$04,$fc,$01,$fc,$01,$fc,$01 + $70,$01,$10,$02,$10,$02,$4c,$02,$76,$04,$00,$00 + $7c,$00,$96,$04,$f8,$02,$81,$00,$71,$05,$ba,$01 + $e0,$01,$c0,$00,$d7,$00,$44,$01,$1c,$01,$85,$01 + $08,$00,$c0,$00,$e8,$02,$08,$00,$1c,$00,$1c,$00 + $6c,$00,$6c,$00,$35,$01,$cc,$00,$7c,$00,$f4,$00 + $18,$00,$ac,$02,$bc,$01,$4e,$04,$5c,$02,$de,$00 + $34,$02,$02,$05,$16,$05,$2a,$05,$7c,$00,$7c,$00 + $7c,$00,$ca,$05,$de,$05,$2e,$01,$f2,$05,$00,$00 + $84,$02,$b8,$00,$00,$00,$2c,$00,$cb,$00,$cb,$00 + $cb,$00,$00,$00,$cc,$00,$cc,$00,$52,$00,$6d,$02 + $ba,$01,$ce,$01,$e2,$01,$8a,$04,$8a,$04,$52,$05 + $be,$02,$be,$02,$aa,$02,$aa,$02,$82,$02,$82,$02 + $de,$00,$78,$00,$8e,$05,$ca,$05,$06,$01,$d4,$02 + $18,$00,$00,$00,$18,$00,$00,$00,$18,$00,$28,$00 + $18,$00,$00,$00,$bc,$01,$27,$04,$27,$04,$27,$04 + $3c,$00,$44,$02,$5c,$02,$7c,$00,$1a,$06,$7c,$00 + $52,$00,$7c,$00,$c2,$03,$90,$00,$cc,$00,$1c,$01 + $1c,$01,$f2,$00,$48,$02,$41,$01,$41,$01,$41,$01 + $de,$00,$c2,$03,$ae,$03,$c9,$00,$41,$01,$b9,$01 + $cd,$01,$e1,$01,$89,$04,$51,$05,$b5,$05,$7c,$00 + $53,$05,$8b,$04,$e3,$01,$cf,$01,$bb,$01,$06,$01 + $cb,$00,$f6,$01,$da,$04,$bc,$01,$ff,$03,$86,$03 + $5f,$03,$bd,$02,$bd,$02,$bd,$02,$d7,$03,$43,$01 + $43,$01,$43,$01,$ac,$02,$ac,$02,$f6,$01,$da,$04 + $ee,$04,$7c,$00,$7c,$00,$7c,$00,$7c,$00,$7c,$00 + $7c,$00,$7c,$00,$7c,$00,$7c,$00,$7c,$00,$7c,$00 + $7c,$00,$7c,$00,$7c,$00,$f6,$01,$da,$04,$00,$00 + $00,$00,$b5,$05,$09,$02,$aa,$01,$86,$03,$37,$03 + $63,$04,$00,$00,$37,$03,$00,$00,$41,$01,$41,$01 + $de,$00,$a2,$05,$a2,$05,$b7,$00,$5f,$03,$81,$02 + $91,$01,$b6,$05,$95,$02,$a5,$01,$41,$01,$89,$04 + $7c,$00,$1c,$01,$00,$00,$00,$00,$00,$00,$94,$01 + $94,$01,$7c,$00,$8d,$05,$5c,$02,$8d,$05,$51,$05 + $89,$04,$51,$05,$52,$00,$82,$02,$aa,$02,$be,$02 + $8a,$04,$f2,$00,$80,$01,$a8,$01,$94,$01,$00,$00 + $b5,$05,$00,$00,$89,$04,$51,$05,$41,$01,$41,$01 + $d4,$02,$00,$00,$91,$01,$7c,$00,$81,$02,$81,$02 4cbf: 3c 00 cc 10+ condition1_tab .bulk $3c,$00,$cc,$10,$00,$00,$c0,$03,$00,$00,$0f,$00 + $40,$01,$21,$01,$48,$01,$e5,$04,$21,$01,$00,$00 + $00,$00,$00,$00,$00,$00,$3b,$00,$27,$00,$0f,$00 + $ca,$04,$c8,$00,$3c,$00,$b0,$04,$00,$00,$3c,$00 + $e5,$04,$f4,$01,$f6,$01,$ed,$04,$f4,$01,$f4,$01 + $86,$03,$00,$00,$08,$02,$44,$02,$00,$00,$00,$00 + $00,$05,$5e,$05,$20,$03,$66,$05,$78,$00,$ce,$01 + $50,$05,$a8,$00,$10,$00,$c0,$00,$10,$00,$52,$00 + $7c,$00,$34,$01,$00,$00,$f4,$00,$7c,$00,$f4,$00 + $7c,$00,$f4,$00,$21,$01,$10,$00,$5c,$01,$5c,$01 + $35,$04,$68,$01,$10,$00,$00,$00,$00,$00,$00,$00 + $44,$02,$7c,$00,$7c,$00,$7c,$00,$02,$05,$16,$05 + $2a,$05,$94,$02,$58,$02,$cc,$01,$1c,$02,$00,$00 + $f2,$02,$9a,$05,$00,$00,$14,$00,$bd,$04,$d1,$04 + $00,$00,$00,$00,$6e,$04,$ee,$01,$30,$00,$00,$00 + $b8,$01,$cc,$01,$e0,$01,$81,$00,$88,$04,$50,$05 + $95,$00,$bc,$02,$45,$00,$a8,$02,$59,$00,$80,$02 + $61,$02,$00,$00,$8c,$05,$c8,$05,$04,$01,$00,$00 + $41,$01,$00,$00,$41,$01,$00,$00,$41,$01,$10,$04 + $41,$01,$00,$00,$31,$01,$68,$00,$54,$00,$40,$00 + $8c,$00,$00,$00,$00,$00,$1a,$06,$7c,$00,$30,$02 + $31,$00,$f0,$00,$00,$00,$b4,$00,$dc,$00,$2c,$01 + $54,$01,$1c,$01,$30,$02,$d0,$00,$e4,$00,$f8,$00 + $41,$01,$41,$01,$41,$01,$c8,$00,$e4,$00,$b8,$01 + $cc,$01,$e0,$01,$00,$00,$00,$00,$00,$00,$00,$00 + $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 + $00,$00,$00,$00,$00,$00,$4e,$01,$9e,$01,$00,$00 + $00,$00,$f4,$00,$f4,$00,$f4,$00,$da,$01,$d0,$00 + $e4,$00,$f8,$00,$91,$03,$bc,$02,$f1,$04,$f1,$04 + $ec,$04,$3e,$05,$5c,$01,$5c,$01,$5c,$01,$98,$01 + $98,$01,$ac,$01,$ac,$01,$c0,$01,$c0,$01,$24,$02 + $24,$02,$38,$02,$b4,$02,$00,$00,$94,$01,$00,$00 + $00,$00,$b4,$05,$08,$02,$18,$01,$84,$03,$e5,$02 + $7f,$01,$00,$00,$00,$00,$00,$00,$d1,$00,$00,$00 + $60,$02,$ca,$05,$a0,$05,$b4,$00,$00,$00,$9a,$02 + $aa,$01,$b4,$05,$94,$02,$a4,$01,$c8,$00,$88,$04 + $8e,$00,$53,$05,$00,$00,$00,$00,$00,$00,$a4,$01 + $7c,$01,$3e,$05,$00,$00,$8f,$05,$8c,$05,$50,$05 + $e0,$00,$44,$01,$25,$04,$25,$04,$25,$04,$25,$04 + $25,$04,$44,$01,$90,$01,$90,$01,$00,$00,$00,$00 + $b4,$05,$00,$00,$44,$01,$e0,$00,$d0,$00,$f8,$00 + $00,$00,$00,$00,$90,$01,$00,$00,$80,$02,$00,$00 4eb7: 7c 01 6c 02+ condition2_tab .bulk $7c,$01,$6c,$02,$00,$00,$00,$00,$00,$00,$00,$00 + $00,$00,$a0,$00,$b4,$00,$48,$02,$00,$00,$00,$00 + $00,$00,$00,$00,$14,$00,$44,$02,$44,$02,$00,$00 + $b6,$04,$3c,$00,$00,$00,$c4,$04,$00,$00,$00,$00 + $d8,$04,$00,$00,$f4,$01,$f4,$01,$00,$00,$00,$00 + $08,$02,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 + $14,$05,$bd,$00,$f0,$05,$00,$00,$00,$00,$e2,$01 + $00,$00,$00,$00,$00,$00,$00,$00,$21,$01,$50,$00 + $c0,$01,$00,$00,$00,$00,$c0,$01,$98,$01,$98,$01 + $38,$02,$38,$02,$00,$00,$21,$01,$18,$06,$18,$06 + $24,$04,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 + $00,$00,$7c,$01,$8c,$00,$04,$01,$7c,$01,$8c,$00 + $04,$01,$00,$00,$00,$00,$a0,$00,$00,$00,$00,$00 + $6d,$02,$6d,$02,$00,$00,$00,$00,$b0,$04,$c4,$04 + $00,$00,$00,$00,$6d,$02,$6d,$02,$78,$00,$00,$00 + $00,$00,$00,$00,$00,$00,$88,$04,$00,$00,$00,$00 + $bc,$02,$00,$00,$a8,$02,$00,$00,$00,$00,$00,$00 + $00,$00,$00,$00,$00,$00,$b4,$05,$d0,$02,$00,$00 + $d0,$00,$00,$00,$e4,$00,$00,$00,$f8,$00,$00,$00 + $00,$00,$00,$00,$2c,$01,$24,$04,$24,$04,$24,$04 + $44,$02,$00,$00,$00,$00,$64,$00,$64,$00,$00,$00 + $00,$00,$00,$00,$00,$00,$00,$00,$a0,$00,$00,$00 + $00,$00,$40,$01,$00,$00,$00,$00,$00,$00,$00,$00 + $d1,$00,$e5,$00,$d1,$00,$00,$00,$00,$00,$00,$00 + $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 + $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 + $00,$00,$00,$00,$00,$00,$40,$01,$90,$01,$00,$00 + $00,$00,$c0,$01,$38,$02,$98,$01,$cc,$01,$00,$00 + $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 + $00,$00,$00,$00,$ab,$02,$ab,$02,$ab,$02,$ab,$02 + $ab,$02,$ab,$02,$ab,$02,$ab,$02,$ab,$02,$ab,$02 + $ab,$02,$ab,$02,$00,$00,$00,$00,$d8,$04,$00,$00 + $00,$00,$00,$00,$08,$02,$00,$00,$64,$05,$34,$03 + $49,$01,$00,$00,$00,$00,$00,$00,$e5,$00,$00,$00 + $58,$02,$a0,$05,$b4,$05,$60,$04,$00,$00,$94,$02 + $a4,$01,$00,$00,$00,$00,$00,$00,$dc,$00,$88,$04 + $3c,$05,$f0,$00,$00,$00,$00,$00,$00,$00,$00,$00 + $00,$00,$3c,$05,$00,$00,$a0,$05,$00,$00,$00,$00 + $88,$04,$50,$05,$31,$00,$59,$00,$45,$00,$95,$00 + $81,$00,$18,$01,$00,$00,$00,$00,$00,$00,$00,$00 + $c8,$05,$00,$00,$88,$04,$50,$05,$c8,$00,$00,$00 + $00,$00,$00,$00,$a4,$01,$00,$00,$94,$02,$00,$00 50af: 00 00 54 01+ condition3_tab .bulk $00,$00,$54,$01,$00,$00,$00,$00,$00,$00,$00,$00 + $00,$00,$00,$00,$60,$04,$44,$02,$00,$00,$00,$00 + $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$74,$04 + $4f,$04,$cc,$01,$00,$00,$3c,$00,$00,$00,$00,$00 + $00,$00,$00,$00,$d8,$04,$00,$00,$00,$00,$00,$00 + $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 + $28,$05,$58,$02,$cc,$01,$00,$00,$00,$00,$b8,$01 + $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 + $00,$05,$00,$00,$00,$00,$00,$05,$28,$05,$28,$05 + $14,$05,$14,$05,$00,$00,$a0,$00,$00,$00,$00,$00 + $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 + $00,$00,$4c,$04,$4c,$04,$4c,$04,$4c,$04,$4c,$04 + $4c,$04,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 + $e4,$02,$8c,$05,$00,$00,$00,$00,$cc,$01,$cc,$01 + $00,$00,$00,$00,$60,$04,$e0,$01,$c0,$03,$00,$00 + $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 + $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 + $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 + $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 + $00,$00,$00,$00,$00,$00,$28,$00,$50,$00,$78,$00 + $00,$00,$00,$00,$00,$00,$50,$00,$50,$00,$00,$00 + $00,$00,$00,$00,$00,$00,$00,$00,$dc,$00,$00,$00 + $00,$00,$f0,$00,$00,$00,$00,$00,$00,$00,$00,$00 + $f9,$00,$f9,$00,$e5,$00,$00,$00,$00,$00,$00,$00 + $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 + $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 + $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 + $00,$00,$0e,$05,$22,$05,$36,$05,$00,$00,$00,$00 + $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 + $00,$00,$00,$00,$54,$01,$54,$01,$54,$01,$90,$01 + $90,$01,$a4,$01,$a4,$01,$b8,$01,$b8,$01,$1c,$02 + $1c,$02,$30,$02,$00,$00,$00,$00,$d4,$03,$00,$00 + $00,$00,$00,$00,$38,$04,$00,$00,$00,$00,$fc,$03 + $60,$04,$00,$00,$00,$00,$00,$00,$f9,$00,$00,$00 + $08,$02,$c8,$05,$8c,$05,$00,$00,$00,$00,$00,$00 + $00,$00,$00,$00,$00,$00,$00,$00,$f0,$00,$58,$02 + $8c,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 + $00,$00,$8c,$00,$00,$00,$b4,$05,$00,$00,$00,$00 + $00,$00,$00,$00,$28,$00,$50,$00,$3c,$00,$8c,$00 + $78,$00,$f0,$00,$00,$00,$00,$00,$00,$00,$00,$00 + $00,$00,$00,$00,$a0,$00,$a0,$00,$00,$00,$00,$00 + $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 52a7: 00 00 00 00+ condition4_tab .bulk $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 + $00,$00,$00,$00,$00,$00,$d8,$04,$00,$00,$00,$00 + $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$28,$00 + $b0,$04,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 + $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 + $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 + $18,$06,$b4,$00,$00,$00,$00,$00,$00,$00,$cc,$01 + $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 + $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 + $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 + $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 + $00,$00,$50,$00,$50,$00,$50,$00,$50,$00,$50,$00 + $50,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 + $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 + $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 + $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 + $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 + $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 + $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 + $00,$00,$00,$00,$00,$00,$58,$02,$30,$02,$00,$00 + $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 + $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 + $00,$00,$dc,$00,$00,$00,$00,$00,$00,$00,$00,$00 + $dc,$00,$c8,$00,$f0,$00,$00,$00,$00,$00,$00,$00 + $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 + $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 + $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 + $00,$00,$00,$00,$64,$00,$14,$00,$00,$00,$00,$00 + $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 + $00,$00,$00,$00,$90,$01,$1c,$02,$b8,$01,$54,$01 + $a4,$01,$90,$01,$b8,$01,$54,$01,$a4,$01,$30,$02 + $54,$01,$1c,$02,$00,$00,$00,$00,$7c,$01,$00,$00 + $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 + $b4,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 + $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 + $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$f8,$02 + $7c,$01,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 + $00,$00,$7c,$01,$00,$00,$8c,$05,$00,$00,$00,$00 + $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 + $00,$00,$a0,$00,$00,$00,$00,$00,$00,$00,$00,$00 + $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 + $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 ; ; Pointers to room descriptions. ; ; There are 38 rooms (0-37), though room 0 is "nowhere". ; 549f: 26 34 room_descrs .dd2 T3427-1 54a1: 27 34 .dd2 T3427 54a3: 34 34 .dd2 T3434 54a5: 41 34 .dd2 T3441 54a7: 4e 34 .dd2 T344E 54a9: 5b 34 .dd2 T345B 54ab: 72 34 .dd2 T3472 54ad: 88 34 .dd2 T3488 54af: 9e 34 .dd2 T349E 54b1: 9f 34 .dd2 T349F 54b3: ac 34 .dd2 T34AC 54b5: b9 34 .dd2 T34B9 54b7: c3 34 .dd2 T34C3 54b9: cf 34 .dd2 T34CF 54bb: e6 34 .dd2 T34E6 54bd: fd 34 .dd2 T34FD 54bf: 07 35 .dd2 T3507 54c1: 13 35 .dd2 T3513 54c3: 26 35 .dd2 T3526 54c5: 3d 35 .dd2 T353D 54c7: 54 35 .dd2 T3554 54c9: 6d 35 .dd2 T356D 54cb: 7b 35 .dd2 T357B 54cd: 89 35 .dd2 T3589 54cf: 98 35 .dd2 T3598 54d1: a7 35 .dd2 T35A7 54d3: b5 35 .dd2 T35B5 54d5: b6 35 .dd2 T35B6 54d7: c4 35 .dd2 T35C4 54d9: d0 35 .dd2 T35D0 54db: d9 35 .dd2 T35D9 54dd: e5 35 .dd2 T35E5 54df: e6 35 .dd2 T35E6 54e1: fd 35 .dd2 T35FD 54e3: 06 36 .dd2 T3606 54e5: 0f 36 .dd2 T360F 54e7: 28 36 .dd2 T3628 54e9: 41 36 .dd2 T3641 ; ; Destination rooms for visible exits. Each exit direction has a separate ; table; each table has one 16-bit entry per room. If the room has no exit in ; that direction, the entry will be zero. ; 54eb: 00 00 00 00+ visible_exits_n .bulk $00,$00,$00,$00,$00,$00,$02,$00,$00,$00,$00,$00 + $00,$00,$00,$00,$00,$00,$0a,$00,$0a,$00,$00,$00 + $00,$00,$0e,$00,$00,$00,$00,$00,$00,$00,$00,$00 + $00,$00,$00,$00,$00,$00,$00,$00,$19,$00,$16,$00 + $00,$00,$00,$00,$00,$00,$17,$00,$00,$00,$00,$00 + $00,$00,$00,$00,$13,$00,$00,$00,$21,$00,$22,$00 + $00,$00,$00,$00 5537: 00 00 00 00+ visible_exits_s .bulk $00,$00,$00,$00,$03,$00,$00,$00,$00,$00,$00,$00 + $00,$00,$00,$00,$00,$00,$09,$00,$09,$00,$00,$00 + $00,$00,$00,$00,$0d,$00,$00,$00,$00,$00,$00,$00 + $00,$00,$20,$00,$00,$00,$00,$00,$00,$00,$00,$00 + $00,$00,$16,$00,$00,$00,$00,$00,$00,$00,$00,$00 + $00,$00,$00,$00,$00,$00,$22,$00,$00,$00,$00,$00 + $00,$00,$00,$00 5583: 00 00 02 00+ visible_exits_e .bulk $00,$00,$02,$00,$00,$00,$04,$00,$00,$00,$03,$00 + $00,$00,$00,$00,$00,$00,$09,$00,$0a,$00,$00,$00 + $00,$00,$00,$00,$00,$00,$0e,$00,$00,$00,$00,$00 + $0d,$00,$00,$00,$00,$00,$00,$00,$15,$00,$00,$00 + $17,$00,$00,$00,$00,$00,$1e,$00,$00,$00,$00,$00 + $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 + $23,$00,$00,$00 55cf: 00 00 00 00+ visible_exits_w .bulk $00,$00,$00,$00,$00,$00,$05,$00,$03,$00,$00,$00 + $00,$00,$00,$00,$00,$00,$07,$00,$0a,$00,$0a,$00 + $00,$00,$12,$00,$00,$00,$00,$00,$00,$00,$00,$00 + $00,$00,$00,$00,$00,$00,$16,$00,$00,$00,$18,$00 + $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 + $1b,$00,$00,$00,$00,$00,$00,$00,$00,$00,$24,$00 + $00,$00,$00,$00 561b: 00 00 00 00+ visible_exits_u .bulk $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 + $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 + $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 + $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 + $00,$00,$00,$00,$00,$00,$00,$00,$06,$00,$00,$00 + $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 + $00,$00,$00,$00 5667: 00 00 00 00+ visible_exits_d .bulk $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 + $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 + $06,$00,$00,$00,$00,$00,$00,$00,$00,$00,$0e,$00 + $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 + $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 + $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 + $00,$00,$00,$00 ; ; Pointers to messages. ; ; There are 83 messages (0-82), though message 0 is empty. ; 56b3: 51 36 messages .dd2 T3651 56b5: 52 36 .dd2 T3652 56b7: be 36 .dd2 T36BE 56b9: c9 36 .dd2 T36C9 56bb: d0 36 .dd2 T36D0 56bd: e3 36 .dd2 T36E3 56bf: 07 37 .dd2 T3707 56c1: 0f 37 .dd2 T370F 56c3: 18 37 .dd2 T3718 56c5: 4f 37 .dd2 T374F 56c7: 6e 37 .dd2 T376E 56c9: 84 37 .dd2 T3784 56cb: 9d 37 .dd2 T379D 56cd: a0 37 .dd2 T37A0 56cf: a6 37 .dd2 T37A6 56d1: bd 37 .dd2 T37BD 56d3: db 37 .dd2 T37DB 56d5: e4 37 .dd2 T37E4 56d7: eb 37 .dd2 T37EB 56d9: 1a 38 .dd2 T381A 56db: 4b 38 .dd2 T384B 56dd: 6b 38 .dd2 T386B 56df: 9a 38 .dd2 T389A 56e1: bf 38 .dd2 T38BF 56e3: ca 38 .dd2 T38CA 56e5: e3 38 .dd2 T38E3 56e7: 08 39 .dd2 T3908 56e9: 87 39 .dd2 T3987 56eb: 9c 39 .dd2 T399C 56ed: a4 39 .dd2 T39A4 56ef: b1 39 .dd2 T39B1 56f1: cc 39 .dd2 T39CC 56f3: e8 39 .dd2 T39E8 56f5: 02 3a .dd2 T3A02 56f7: 18 3a .dd2 T3A18 56f9: 2f 3a .dd2 T3A2F 56fb: 3c 3a .dd2 T3A3C 56fd: 84 3a .dd2 T3A84 56ff: a1 3a .dd2 T3AA1 5701: e6 3a .dd2 T3AE6 5703: f8 3a .dd2 T3AF8 5705: 1b 3b .dd2 T3B1B 5707: 35 3b .dd2 T3B35 5709: 48 3b .dd2 T3B48 570b: 58 3b .dd2 T3B58 570d: 63 3b .dd2 T3B63 570f: 6a 3b .dd2 T3B6A 5711: 70 3b .dd2 T3B70 5713: 8d 3b .dd2 T3B8D 5715: 9e 3b .dd2 T3B9E 5717: cc 3b .dd2 T3BCC 5719: df 3b .dd2 T3BDF 571b: f2 3b .dd2 T3BF2 571d: 15 3c .dd2 T3C15 571f: 28 3c .dd2 T3C28 5721: 41 3c .dd2 T3C41 5723: 4f 3c .dd2 T3C4F 5725: 65 3c .dd2 T3C65 5727: 7c 3c .dd2 T3C7C 5729: bf 3c .dd2 T3CBF 572b: d0 3c .dd2 T3CD0 572d: 0c 3d .dd2 T3D0C 572f: 22 3d .dd2 T3D22 5731: 33 3d .dd2 T3D33 5733: 40 3d .dd2 T3D40 5735: 47 3d .dd2 T3D47 5737: 59 3d .dd2 T3D59 5739: a2 3d .dd2 T3DA2 573b: b4 3d .dd2 T3DB4 573d: cd 3d .dd2 T3DCD 573f: db 3d .dd2 T3DDB 5741: fd 3d .dd2 T3DFD 5743: 16 3e .dd2 T3E16 5745: 1f 3e .dd2 T3E1F 5747: 38 3e .dd2 T3E38 5749: 4c 3e .dd2 T3E4C 574b: 56 3e .dd2 T3E56 574d: 5d 3e .dd2 T3E5D 574f: 71 3e .dd2 T3E71 5751: a4 3e .dd2 T3EA4 5753: c2 3e .dd2 T3EC2 5755: dc 3e .dd2 T3EDC 5757: e3 3e .dd2 T3EE3 ; 5759: 00 00 00 00+ .junk 23