; 6502bench SourceGen v1.7.3
item_spiritLamp .eq $01 {const}
RWTSCMD_read .eq $01 {const}
STARVED_food .eq $01 {const}
PLAYER_Herd .eq $02 {const}
STARVED_rest .eq $02 {const}
PLAYER_Charn .eq $04 {const}
item_pan_bread .eq $05 {const}
item_fruit_nuts .eq $06 {const}
item_shuba .eq $07 {const}
item_berries .eq $0a {const}
item_fallaKey .eq $0d {const}
tile_brambles .eq $1c {const}
tile_water .eq $20 {const}
LASTKEY .eq $02 {addr/1} ;last key pressed via checkkey
TXTPTR .eq $03 {addr/2} ;current tile position on text page 1
TXTCOL .eq $05 {addr/1} ;prob col on 40x24 scrn
TXTROW .eq $06 {addr/1} ;prob row on 40x24 scrn
temp08 .eq $08
temp09 .eq $09
temp0a .eq $0a
temp11_textlo .eq $11 ; often used to hold text page address of tile (lo)
temp12_texthi .eq $12 ; often used to hold text page address of tile (lo)
hires_addr .eq $14 {addr/2}
tileptr .eq $16 {addr/2} ;pointer to current tile data
MASK .eq $18 {addr/1} ;may or may not be global
playerX .eq $19 ; tile X of player
playerY .eq $1a ; tile Y of player
MAPPOS .eq $1b ; playfield position
MAPHALF .eq $1c ; playfield half (top/bottom); like top bit of MAPPOS
zp1d .eq $1d {addr/2} ; used as a read ptr when drawing player; may be anim frame via $A3
zp1f .eq $1f
PLAYER .eq $20 ;active player (0-4)
timeOfDay .eq $21 ; 0 (early morning) .. 7 (late night)
dayNum .eq $22 ; day number (1-based)
levelSpirit .eq $23 ; level of spirit
levelFood .eq $24 ; level of food, max limit-1
levelRest .eq $25 ; level of rest, max limit-1
levelStamina .eq $26 ; level of stamina
limitSpirit .eq $27 ; spirit limit
limitFood .eq $2a ; not shown, levelStamina/2 + 1
limitRest .eq $2b ; not shown, levelStamina/2 + 1
maxWeight .eq $2c ; max weight you can carry
homePos .eq $2d ; used when teleporting player home
homeHalf .eq $2e ; used when teleporting player home
homeX .eq $2f ; used when teleporting player home
homeY .eq $30 ; used when teleporting player home
MON_INVFLAG .eq $32 ;text mask (255=normal, 127=flash, 63=inv)
temp34_npctype .eq $34 ; holds NPC type when $e0..$ef? Not really a temp.
doorNeshom .eq $35 ; FF = door goes to Neshom house, 01 = Neshom realm
spokeTo .eq $37 ; spoke to or bought from NPC while on this screen
fallaKeyOffered .eq $38 ; if D'Ol Falla's key has been offered (?)
suppressSound0 .eq $39 ; $FF=suppress sound 0 for 1 call, set on inventory menu entry
litLamp .eq $3a ; slot number of lit lamp, or 0 if unlit
MON_PCH .eq $3b ;program counter save
STARVED .eq $3c ; 0 = ok, 1 = out of food, 2 = out of rest
GAMEOVER .eq $3d ;game over bool (0/1)
visionNum .eq $3e ; vision number to have next, 0..5
gainSpirit .eq $3f ; spirit gained so far, modulo 5
MON_A3H .eq $41 ;general purpose
MON_A4L .eq $42 ;general purpose
lampFuel .eq $44 ; number of rooms left in lamp; 00..13
MON_A5H .eq $45 ;general purpose
SOUNDFLG .eq $4a ;0 = sound off, 1 = on
NINEIDX .eq $55 ;cur index into $900 block
ODDLINE_MASK .eq $5f {addr/1} ;and mask odd tile lines ($00 disables)
tileset .eq $60 {addr/1} ;which tileset to use, 0 or 1
HTAB .eq $64 ; horiz text pos (next line at +$28)
INVTEXT .eq $66 {addr/1} ;0=normal,1=inverse
INSIDE .eq $67 ; Are we inside? Toggled when entering a door, or set manually on teleport.
zp6b_npcHere .eq $6b ; NPC is on this screen? (0=no, 1=yes)
npcX .eq $6c ; NPC X location on this screen
npcY .eq $6d ; NPC Y location on this screen
zp6e .eq $6e ; set in NPC code; initial from RWTSBUF+227 & 0x0F
npcFacing .eq $6f ; NPC facing direction on this screen
WEIGHT .eq $70 ; current item weight carried (< limitWeight)
MENUCOL .eq $71 ;menu column (0..4)
MENUROW .eq $72 ;menu row (0..3)
MENUCOL_NEXT .eq $73 ;next menu col, used only during movement
MENUROW_NEXT .eq $74 ;next menu row, used only during movement
temp75 .eq $75
temp76 .eq $76
selItemSlot .eq $77 ; last selected item slot (00..FE or FF)
selItemNum .eq $78 ; last selected item number (01..0E)
temp79 .eq $79
temp7a .eq $7a
temp7b .eq $7b
TICKS .eq $7c ; number of ticks until next minute (0..$FF)
MINUTES .eq $7d ; number of minutes until next time period (0..$25)
temp7e .eq $7e ; only used in $84CC sub
temp7f .eq $7f ; only used in $84CC sub
touchedWater .eq $80 ; we touched water and will pass out
temp82 .eq $82
waitMelody .eq $83 ; always 0, but could be interrupt placeholder
VIRTBTN .eq $84 ; virtual button press, used only in kbd handler
XDIR .eq $85 ;last x dir pressed, -1 (left) or 1 (right)
YDIR .eq $86 ;last y dir pressed, -1 (up) or 1 (down)
TICKING .eq $87 ; 1 if timer is ticking, 0 if paused
animTimer .eq $88 ; counts up to animDelay
temp89 .eq $89 {addr/2}
temp8b .eq $8b
jumpFlag .eq $8c ; 1=jumping, 0=not
jumpFrame .eq $8d ; frame 1..4 (when jumpFlag=1)
nextRoomDir .eq $8f ; 00,01,02,03,04 -- next map room direction
animDelay .eq $90 ; ticks to hold current player animation frame
FALLCNT .eq $92 ;# of tiles we've fallen; $0A head bonked
bonkFrame .eq $93
flyFlag .eq $94 ; # 1 when flying (button pressed in air after > 2 tiles fell)
FACING .eq $95 ;FF=left, 01=right facing
takingStep .eq $96 ; 0 or 1 depending on taking step in cycle
runFlag .eq $99 ; 1=running, 0=not
crawlFlag .eq $9a ; 1=crawling, 0=not
crouchFlag .eq $9b ; 1=crouching; reset on next frame
playerXold .eq $9c
playerYold .eq $9d
doorTransit .eq $9e ; 1..3 (entering onscreen door #) or 0
enterMenu .eq $9f ; show menu on next frame
bonkAlt .eq $a1 ; 0 or 1 to alternate bonk frames
MOVING .eq $a2 ;1=moving,0=stationary
animFrame .eq $a3 ; character anim frame (see $6ED6)
animFrame_unused .eq $a4 ; always $A3+1; never read, seems unused
XMOVFLG .eq $af
YMOVFLG .eq $b0 ;FF=up,01=down (edge at end of action)
JOYFLG .eq $b1 ;01 = joystick, 00 = kbd
erasePlayer .eq $b2 ; flag to erase player on next frame
longJump .eq $b4 ; 2 (stamina >= 20) or 1 (stamina < 20); if 2, prolongs jump in frame 3
tempB7 .eq $b7 ; temp used only in handle_food_rest
foodRestTimer .eq $b8 ; remaining time until food/rest decreases
zpBC_bellrings .eq $bc ; if 1, spirit bell rings, if 0, get attacked
DEMOWAIT .eq $c0 ; number of frames to wait
DEMOPTR .eq $c2 ; ptr to current demo byte
DEMOFLG .eq $c4 ; 00 = game, 01 = demo mode
DEMOTEXT .eq $c8 ; demo text to show (1..5, or 0 = none)
tileFeet .eq $e0 ; 0, 0 tile at player's feet
tileFeetLeft .eq $e1 ; -1, 0 tile left of player's feet
tileFeetRight .eq $e2 ; 1, 0 tile right of player's feet
tileUnder .eq $e3 ; 0, 1 tile under player's feet
tileUnderLeft .eq $e4 ; -1, 1 left tile under player's feet
tileUnderRight .eq $e5 ; 1, 1 right tile under player's feet
tileKnee .eq $e6 ; 0,-1 tile 1 above player's feet
tileArm .eq $e7 ; 0,-2 tile 2 at arm height (item on table/shelf)
tileShoulder .eq $e8 ; 0,-3 tile at shoulder height
tileArmLeft .eq $e9 ; -1,-2 tile left at arm level (table/shelf)
tileArmRight .eq $ea ; 1,-2 tile right at arm level (table/shelf)
ySolid .eq $f0 ; selected tile is solid ground
xSolid .eq $f1 ; selected tile prevents x motion
climbable .eq $f2 ; selected tile is a ladder/vine
digits .eq $f9 {addr/5} ; decimal digit output of num_to_str
RWTSBUF .eq $0200 {addr/256} ; 256-byte sector r/w buffer
RWTSBUF_npc .eq $02e1 ; nonzero if NPC is present; may contain data in top 4 bits
RWTSBUF_npcX .eq $02e4 ; NPC initial X location
RWTSBUF_npcY .eq $02e5 ; NPC initial Y location
RWTSBUF_npcnum .eq $02f1 ; NPC number (00..??) ; $49 raamo
RWTSBUF_npctype .eq $02f2 ; 0 offers item, 1 animal, $d0 dol falla, $40 gain level, $20-$2f ??, $c0 door 1, $c1 door 2, $e0-$ef,
RWTS_IOB_track .eq $0304
RWTS_IOB_sector .eq $0305
RWTS_IOB_buf .eq $0308
RWTS_IOB_command .eq $030c
DIRECT_RWTS .eq $0315
SCREEN_0900 .eq $0900
GAME1_player_names .eq $1ad0
GAME1_tileset_bitmap .eq $1d00
GAME1_hireslo .eq $1d40
GAME1_hireshi .eq $1d60
GAME1_texthi .eq $1d80
GAME1_textlo .eq $1da0
GAME1_BITTAB0 .eq $1db8
GAME1_BITTAB1 .eq $1db9
GAME1_BITTAB2 .eq $1dba
GAME1_BITTAB3 .eq $1dbb
GAME1_BITTAB4 .eq $1dbc
GAME1_BITTAB5 .eq $1dbd
GAME1_BITTAB6 .eq $1dbe
GAME1_BITTAB7 .eq $1dbf
GAME1_player_stats .eq $1dc0
GAME1_odd_col_mask .eq $1fa0
GAME1_even_col_mask .eq $1fb0
GAME1_odd_col_even_line_mask .eq $1fc0
GAME1_even_col_even_line_mask .eq $1fd0
GAME1_odd_col_odd_line_mask .eq $1fe0
GAME1_even_col_odd_line_mask .eq $1ff0
GAME1_chardata .eq $2c00
GAME1_tileset1_masks .eq $2e00
GAME1_tileset0_masks .eq $3700
SCRN_demo_handler .eq $9600
SCRN_show_demo_text .eq $9603
SCRN_heal .eq $9c00
SCRN_grunspreke .eq $9c03
SCRN_kiniport .eq $9c06
SCRN_speak .eq $9c0c
SCRN_pense .eq $9c0f
SCRN_sell .eq $9c15
SCRN_offer .eq $9c18
SCRN_triumph_melody .eq $9c1e
SCRN_warm_start .eq $a840
SCRN_sound_status .eq $a849
state_npc1 .eq $b200
state_npc .eq $b280 ; per npc bitfield; 7=gained a level from this NPC; 0..6=last spoken daynum or 0..4=time of day (NPC $E0..$EF)
itemStatePos .eq $b300 {addr/256} ; 256 map positions, one per item
itemStateCol .eq $b400 {addr/256} ; 256 column tile positions, one per item
itemState .eq $b500 {addr/256} ; 7=mappos high bit, 6=in world, 5=in inv, 4..0=map row
inv_shuba .eq $b558 {addr/20}
inv_token .eq $b56c {addr/75}
SCRN_play_melody .eq $b600
SCRN_play_sound .eq $b603
SCRN_play_sound_0 .eq $b606
SCRN_chkkey .eq $b609
BUTN0 .eq $c061 ;R switch input 0 / open-apple
BUTN1 .eq $c062 ;R switch input 1 / closed-apple
MON_PREAD .eq $fb1e ;read paddle specifed by X-reg, return in Y-reg
.org $6000
6000: 4c 00 5b jmp $5b00
; Common external entry vectors for intermodule jumps.
6003: 4c a9 67 GAME2_drawtile jmp drawtile
6006: 4c e6 63 GAME2_cleartext jmp cleartext
GAME2_write_tiles_to_text
6009: 4c 8b 64 jmp write_tiles_to_text ;local only
600c: 4c d6 66 GAME2_PRNTSTR jmp PRNTSTR
600f: 4c 09 67 GAME2_printchar jmp printchar
6012: 4c e1 69 GAME2_delayXtimes256 jmp delayXtimes256
6015: 4c a2 69 GAME2_swapzp8 jmp swapzp8
6018: 4c 6c 67 jmp drawfield ;vector never used
601b: 4c a3 66 GAME2_teleport_home jmp teleport_home ;local only
601e: 4c 3c 64 GAME2_read_playfield jmp read_playfield
6021: 4c 63 61 GAME2_read_0900 jmp read_0900_next ;read next byte at $0900
6024: 4c 00 b6 GAME2_play_melody jmp SCRN_play_melody
6027: 4c 57 60 GAME2_intro jmp intro?
602a: 4c a3 61 jmp move_room
602d: 4c 52 61 jmp @cont
6030: 4c b6 69 GAME2_copypages jmp copypages
6033: 4c cf 69 GAME2_clearpages jmp clearpages
6036: 4c ea 69 GAME2_delay2 jmp delay2
6039: 4c 6f 61 GAME2_player_init jmp player_init ;vector never used
603c: 4c 77 60 jmp L6077
603f: 4c bf 6a GAME2_init_item_state jmp init_item_state ;Read T22,S00..02 into $B300..$B5FF
GAME2_calc_hires_textpos
6042: 4c 5b 68 jmp calc_hires_textpos
6045: 4c b3 67 GAME2_writetile jmp writetile
6048: 4c 82 60 jmp game_loop?
604b: 4c 7f 64 L604B jmp L647F ;might redraw screen after drop/take lamp
; MENUFLG is non-zero. Pop up menu, await selection, and return.
604e: 20 00 77 enter_menu jsr GAME2_action_menu
6051: a9 00 lda #$00
6053: 85 9f sta enterMenu
6055: f0 2b beq game_loop? ;always
6057: 20 8e 62 intro? jsr L628E ;might be general game loop
605a: a5 c9 lda $c9
605c: c9 0d cmp #$0d ;$c9 == #$0d during intro
605e: d0 17 bne L6077
6060: 20 e6 63 jsr cleartext
6063: a9 01 lda #$01 ;set demo mode
6065: 85 c4 sta DEMOFLG
6067: a5 d0 lda $d0
6069: 10 09 bpl L6074 ;if in gameplay mode (??)
606b: 20 e8 62 jsr L62E8
606e: 20 8e 62 jsr L628E
6071: 4c 77 60 jmp L6077
6074: 20 b2 62 L6074 jsr L62B2
6077: 20 9f 62 L6077 jsr L629F
607a: a9 00 lda #$00
607c: 85 88 sta animTimer
607e: a9 08 lda #$08
6080: 85 90 sta animDelay
NOTE: Multiple entries
6082: a9 01 game_loop? lda #$01 ;start game timer
6084: 85 87 sta TICKING
6086: 20 00 6b tick0 jsr GAME2_next_frame ;entered from multiple subs
6089: a2 0a ldx #$0a
608b: a5 6b lda zp6b_npcHere ;check $6b
608d: f0 02 beq @delay ;0, delay $0A * 256
608f: a2 06 ldx #$06 ;!0, delay $06 * 256, allowing more time for NPC CPU?
6091: 20 e1 69 @delay jsr delayXtimes256 ;delay X * 256
6094: a5 87 lda TICKING
6096: d0 ee bne tick0
6098: a5 8f lda nextRoomDir
609a: d0 48 bne move_next_room
; Below is a state machine which checks several flags/values in zero page in
; order, and performs the first non-zero action it finds.
609c: a5 9e lda doorTransit ;transiting a door? (1..3)
609e: f0 03 beq @check_menu_entry
60a0: 4c d6 61 jmp enterDoor
60a3: a5 9f @check_menu_entry lda enterMenu ;enter menu on this frame?
60a5: f0 03 beq @no
60a7: 4c 4e 60 jmp enter_menu
60aa: a5 80 @no lda touchedWater
60ac: f0 06 beq L60B4
60ae: 4c 6c 66 jmp found_near_water
60b1: 4c .dd1 $4c
60b2: 86 .dd1 $86
60b3: 60 .dd1 $60
60b4: a5 c6 L60B4 lda $c6
60b6: f0 03 beq L60BB
60b8: 4c 0e 63 jmp L630E
; Show demo text on this frame if DEMOTEXT is 1..5. Otherwise continue.
; Note that demo text 5 is clears text; 0 simply checks the next action.
60bb: a5 c8 L60BB lda DEMOTEXT ;demo text to show 1..5, or 0 for not demo
60bd: f0 0a beq check_gameover
60bf: 20 03 96 jsr SCRN_show_demo_text
60c2: a9 00 lda #$00 ;do not update on next frame
60c4: 85 c8 sta DEMOTEXT
60c6: 4c 82 60 jmp game_loop?
60c9: a5 3d check_gameover lda GAMEOVER
60cb: f0 03 beq check_starvation
60cd: 4c 36 6a jmp game_over
60d0: a5 3c check_starvation lda STARVED
60d2: f0 03 beq check_spirit_bell_rings ;we're fine
60d4: 4c 66 63 jmp spent_a_day_recovering ;starved of food or rest
check_spirit_bell_rings
60d7: a5 bc lda zpBC_bellrings
60d9: f0 03 beq @get_attacked
60db: 4c f4 69 jmp spirit_bell_rings
60de: 20 1e 77 @get_attacked jsr GAME2_attacked ;unclear when this happens
60e1: 4c 82 60 jmp game_loop?
; Based on the value in nextRoomDir, update the user's map position by 1 offset
; to the top (01), right (02), bottom (03) or left (04). Then load the new room
; and continue.
60e4: a5 8f move_next_room lda nextRoomDir ;this was already in A, in fact
60e6: c9 01 cmp #$01
60e8: d0 15 bne L60FF
60ea: 38 sec
60eb: a5 1b lda MAPPOS
60ed: e9 20 sbc #$20
60ef: 85 1b sta MAPPOS
60f1: b0 02 bcs L60F5
60f3: c6 1c dec MAPHALF
60f5: 20 a3 61 L60F5 jsr move_room
60f8: a9 12 lda #$12
60fa: 85 1a sta playerY
60fc: 4c 52 61 jmp @cont
60ff: c9 02 L60FF cmp #$02
6101: d0 1d bne L6120
6103: a5 1b lda MAPPOS
6105: 29 1f and #$1f
6107: c9 1f cmp #$1f
6109: d0 09 bne L6114
610b: a5 1b lda MAPPOS
610d: 29 e0 and #$e0
610f: 85 1b sta MAPPOS
6111: 4c 16 61 jmp L6116
6114: e6 1b L6114 inc MAPPOS
6116: 20 a3 61 L6116 jsr move_room
6119: a9 00 lda #$00
611b: 85 19 sta playerX
611d: 4c 52 61 jmp @cont
6120: c9 03 L6120 cmp #$03
6122: d0 15 bne L6139
6124: 18 clc
6125: a5 1b lda MAPPOS
6127: 69 20 adc #$20
6129: 85 1b sta MAPPOS
612b: 90 02 bcc L612F
612d: e6 1c inc MAPHALF
612f: 20 a3 61 L612F jsr move_room
6132: a9 00 lda #$00
6134: 85 1a sta playerY
6136: 4c 52 61 jmp @cont
6139: a5 1b L6139 lda MAPPOS
613b: 29 1f and #$1f
613d: d0 0a bne L6149
613f: 18 clc
6140: a5 1b lda MAPPOS
6142: 69 1f adc #$1f
6144: 85 1b sta MAPPOS
6146: 4c 4b 61 jmp L614B
6149: c6 1b L6149 dec MAPPOS
614b: 20 a3 61 L614B jsr move_room
614e: a9 27 lda #$27
6150: 85 19 sta playerX
6152: a9 00 @cont lda #$00
6154: 85 8f sta nextRoomDir
6156: 20 03 6b jsr GAME2_draw_player
6159: 20 82 68 jsr handle_npc2?
615c: a9 01 lda #$01 ;resume tick, stopped when we started room transition
615e: 85 87 sta TICKING
6160: 4c 86 60 jmp tick0
; Read next byte in $0900 block (pointed to by $55) and return it in A.
; The $55 ptr is (pre)incremented. All access to $55 is encapsulated here.
xsav .var $1e {addr/1} ;save x
6163: 86 1e read_0900_next stx xsav
6165: e6 55 inc NINEIDX
6167: a6 55 ldx NINEIDX
6169: bd 00 09 lda SCREEN_0900,x
616c: a6 1e ldx xsav
616e: 60 rts
; Init player. Copies player's starting stats to active stats, resets the time,
; and sets carry weight to 0 (note: inventory is not zeroed out here). The demo
; player (5) has a shuba added.
616f: a6 20 player_init ldx PLAYER
6171: a5 c4 lda DEMOFLG
6173: f0 07 beq @notdemo
6175: a2 05 ldx #$05 ;phantom character 5 during demo
6177: a9 60 lda #%01100000 ;give the demo player a shuba
6179: 8d 58 b5 sta inv_shuba
617c: bc 9d 61 @notdemo ldy player_stat_offsets,x
617f: a2 0d ldx #$0d ;copy $0E bytes from player stats to cur stats
6181: b9 c0 1d @loop lda GAME1_player_stats,y ;pointer to END of player's stats
6184: 95 23 sta levelSpirit,x
6186: 88 dey ;copy from end to beginning
6187: ca dex
6188: 10 f7 bpl @loop
618a: a9 00 lda #$00
618c: 85 21 sta timeOfDay
618e: 85 70 sta WEIGHT
6190: 85 3e sta visionNum
6192: 85 3f sta gainSpirit
6194: a9 01 lda #$01
6196: 85 22 sta dayNum
6198: a9 23 lda #$23
619a: 85 7d sta MINUTES
619c: 60 rts
; Offset to END of player stats. E.g. $0D = $00..$0D, $1B = $0E..$1B.
619d: 0d player_stat_offsets .dd1 $0d
619e: 1b .dd1 $1b
619f: 29 .dd1 $29
61a0: 37 .dd1 $37
61a1: 45 .dd1 $45
61a2: 53 .dd1 $53
; Called when moving to another room. This will expend 1 lamp fuel (if the lamp
; is lit), destroy your lit lamp if it runs out of fuel, and then read the new
; room data from disk.
61a3: a5 44 move_room lda lampFuel
61a5: f0 14 beq L61BB ;already out of fuel
61a7: c6 44 dec lampFuel
61a9: d0 10 bne L61BB ;still has fuel left
61ab: a6 3a ldx litLamp ;lamp goes out
61ad: a9 00 lda #$00
61af: 85 3a sta litLamp
61b1: 9d 00 b5 sta itemState,x ;destroy lamp item
61b4: 8a txa
61b5: 20 03 77 jsr GAME2_slot_to_item
61b8: 20 12 77 jsr GAME2_lose_weight ;remove its weight
61bb: 20 06 6b L61BB jsr GAME2_erase_player
61be: a5 67 lda INSIDE
61c0: d0 05 bne @light
61c2: 20 15 64 jsr select_tileset_harder
61c5: f0 04 beq @dark
61c7: 20 3c 64 @light jsr read_playfield
61ca: 60 rts
61cb: a9 00 @dark lda #$00
61cd: 8d e1 02 sta RWTSBUF_npc ;remove NPC presence by overwriting read map data
61d0: 20 c1 63 jsr clearfield
61d3: 4c 82 68 jmp handle_npc2?
********************************************************************************
* $9E is non-zero here, implying we are transiting a door. The next 2 *
* subroutines are special teleports, based on whether $35 is FF or 01. That's *
* because when you sleep in D'Ol Neshom's house, the door changes to send you *
* to the cloud realm (01), and the return door sends you back to her house *
* (FF). (It's possible the return door must be handled specially because it's *
* not a standard door tile, so can't use normal door teleporting, but *
* uncertain.) *
* *
* If $35 is 0, branch to the 3rd sub, which handles doors and repositioning *
* more generally. *
********************************************************************************
61d6: a5 35 enterDoor lda doorNeshom
61d8: f0 2e beq @normal_door ;zero, handle regular doors
; 01 sends you to the cloud realm where D'Ol Neshom gives you the spirit bell.
61da: 30 17 bmi @to_dol_neshom ;FF, go to her house
61dc: a9 be lda #$be ;otherwise, teleport
61de: 85 1b sta MAPPOS
61e0: a9 12 lda #$12
61e2: 85 19 sta playerX
61e4: a9 0e lda #$0e
61e6: 85 1a sta playerY
61e8: a9 00 lda #$00
61ea: 85 67 sta INSIDE
61ec: a9 ff lda #$ff ;next door takes you back
61ee: 85 35 sta doorNeshom ;to her house
61f0: 4c 68 62 jmp do_door_entry
; FF sends you to the D'Ol Neshom's small house in the high trees where if you
; sleep, you are transported to a cloud realm and she grants you the spirit
; bell.
61f3: a9 09 @to_dol_neshom lda #$09
61f5: 85 1b sta MAPPOS
61f7: a9 18 lda #$18
61f9: 85 19 sta playerX
61fb: a9 0d lda #$0d
61fd: 85 1a sta playerY
61ff: a9 00 lda #$00
6201: 85 67 sta INSIDE
6203: 85 35 sta doorNeshom
6205: 4c 68 62 jmp do_door_entry
NOTE: Handles, I think, entering doors. Checks $02F2 for $C0/C1, which I think
signify 2 types of locked doors. Then checks a location in game storage,
probably whether the player has one of 2 keys, and a final zp location which is
unknown.
If the door is unlocked, OR $02F2 is any other value, then teleports the user to
the new map position. It's unclear what the other values mean.
From 02F3..F5, 02F6..8, or 02F9..B are a position triple consisting of the new
map position (including high bit), and probably character X and Y. Which one to
use is determined by $9E (unclear why).
6208: ad f2 02 @normal_door lda RWTSBUF_npctype
620b: c9 c0 cmp #$c0 ;possibly locked door, or presence of certain NPC
620d: d0 2a bne L6239
620f: ad 34 b2 lda $b234 ;0=possibly locked (either has_key, or door_unlocked)
6212: d0 2e bne L6242
6214: a5 42 L6214 lda MON_A4L ;0=locked (either has_key, or door_unlocked)
6216: d0 2a bne L6242
6218: 20 d6 66 jsr PRNTSTR
621b: 01 .dd1 $01
621c: d4 c8 c5 a0+ .str ↑“THE DOOR IS LOCKED”
622e: ff .dd1 $ff
622f: 20 06 77 jsr GAME2_message_wait
6232: a9 00 lda #$00
6234: 85 9e sta doorTransit ;note $9e is 1..3 below
6236: 4c 82 60 jmp game_loop?
6239: c9 c1 L6239 cmp #$c1 ;possibly locked door, or presence of certain NPC
623b: d0 05 bne L6242
623d: ad 35 b2 lda $b235 ;possibly inventory check for this key
6240: f0 d2 beq L6214
6242: a4 9e L6242 ldy doorTransit ;Y is 1..3 here (on entry must be nonzero)
6244: be 8a 62 ldx @posptr-1,y
6247: bd 01 02 lda RWTSBUF+1,x
624a: 85 1b sta MAPPOS ;first byte is map position
624c: a0 00 ldy #$00
624e: bd 02 02 lda RWTSBUF+2,x ;second byte is map side (bit 7) + something (0..6)
6251: 48 pha
6252: 29 80 and #$80 ;check bit 7
6254: f0 01 beq L6257 ;bit 7 unset, MAPSIDE=0
6256: c8 iny
6257: 84 1c L6257 sty MAPHALF ;bit 7 set, MAPSIDE=1
6259: 68 pla
625a: 29 7f and #$7f ;bits 0..6 of second byte
625c: 85 19 sta playerX
625e: bd 03 02 lda RWTSBUF+3,x
6261: 29 7f and #$7f ;bits 0..6 of third byte
6263: 85 1a sta playerY
6265: 20 06 6b jsr GAME2_erase_player
6268: 20 3c 64 do_door_entry jsr read_playfield ;read new map screen from disk
626b: a9 00 lda #$00 ;Toggle FACING between 01 and FF
626d: 38 sec ;so the player faces the opposite direction
626e: e5 95 sbc FACING ;when entering/exiting a door
6270: 85 95 sta FACING
6272: 20 21 6b jsr L6B21
6275: 20 03 6b jsr GAME2_draw_player
6278: 20 82 68 jsr handle_npc2?
627b: a9 00 lda #$00 ;reset triple posptr to 0
627d: 85 9e sta doorTransit
627f: a5 67 lda INSIDE
6281: 49 01 eor #$01 ;bitflip
6283: 85 67 sta INSIDE
6285: 20 20 6a jsr L6A20
6288: 4c 82 60 jmp game_loop?
628b: f2 @posptr .dd1 $f2 ;$2f3,$2f4,$2f5
628c: f5 .dd1 $f5 ;$2f6,$2f7,$2f8
628d: f8 .dd1 $f8 ;$2f9,$2fa,$2fb
628e: 20 bf 6a L628E jsr init_item_state
6291: a9 b2 lda #$b2
6293: a2 01 ldx #$01
6295: 20 cf 69 jsr clearpages
6298: a9 ff lda #$ff
629a: 85 b8 sta foodRestTimer
629c: 4c 6f 61 jmp player_init
629f: 20 21 6b L629F jsr L6B21
62a2: a5 31 lda $31
62a4: 85 19 sta playerX
62a6: a5 32 lda MON_INVFLAG
62a8: 85 1a sta playerY
62aa: 20 03 6b jsr GAME2_draw_player
62ad: a9 00 lda #$00
62af: 85 88 sta animTimer
62b1: 60 rts
62b2: a9 9d L62B2 lda #$9d
62b4: 85 1b sta MAPPOS
62b6: a9 00 lda #$00
62b8: 85 1c sta MAPHALF
62ba: a9 01 lda #$01
62bc: 85 67 sta INSIDE
62be: 20 a3 61 jsr move_room
62c1: a9 10 lda #$10
62c3: 85 c2 sta DEMOPTR
62c5: a9 9b lda #$9b
62c7: 85 c3 sta $c3
62c9: a9 06 lda #$06
62cb: 85 31 sta $31
62cd: a9 0e lda #$0e
62cf: 85 32 sta MON_INVFLAG
62d1: a9 01 lda #$01
62d3: 85 9a sta crawlFlag
62d5: 85 c0 sta DEMOWAIT
62d7: a9 ff lda #$ff
62d9: 85 95 sta FACING
62db: 4c 8e 62 jmp L628E
62de: a0 .dd1 $a0
62df: b3 .dd1 $b3
62e0: a2 .dd1 $a2
62e1: 03 .dd1 $03
62e2: 4c .dd1 $4c
62e3: b6 .dd1 $b6
62e4: 69 .dd1 $69
; Pages that T22,S00..02 are read into
62e5: b3 item_state_pages .dd1 $b3
62e6: b4 .dd1 $b4
62e7: b5 .dd1 $b5
62e8: a9 e4 L62E8 lda #$e4
62ea: 85 1b sta MAPPOS
62ec: a9 00 lda #$00
62ee: 85 1c sta MAPHALF
62f0: 85 67 sta INSIDE
62f2: 20 a3 61 jsr move_room
62f5: a9 00 lda #$00
62f7: 85 c2 sta DEMOPTR
62f9: a9 99 lda #$99
62fb: 85 c3 sta $c3
62fd: a9 18 lda #$18
62ff: 85 31 sta $31
6301: a9 0e lda #$0e
6303: 85 32 sta MON_INVFLAG
6305: a9 01 lda #$01
6307: 85 c0 sta DEMOWAIT
6309: a9 ff lda #$ff
630b: 85 95 sta FACING
630d: 60 rts
630e: a2 00 L630E ldx #$00
6310: 86 c6 stx $c6
6312: c9 ff cmp #$ff
6314: d0 03 bne L6319
6316: 4c 40 a8 L6316 jmp SCRN_warm_start
6319: c9 9d L6319 cmp #$9d
631b: d0 06 bne L6323
631d: 20 b2 62 jsr L62B2
6320: 4c 77 60 jmp L6077
6323: a5 d0 L6323 lda $d0
6325: c9 01 cmp #$01
6327: f0 ed beq L6316
6329: 20 e8 62 jsr L62E8
632c: 4c 77 60 jmp L6077
tileset_tmp .var $5c {addr/1}
632f: a9 00 select_tileset lda #$00
6331: 85 5c sta tileset_tmp ;tileset 0 (temp var?)
6333: a5 1c lda MAPHALF
6335: f0 0a beq @choose ;top half, choose tileset
6337: a5 1b lda MAPPOS ;bottom half, check pos
6339: c9 80 cmp #$80 ;test pos top bit
633b: 90 04 bcc @choose ;side 1 pos 00..7F, choose tileset
633d: e6 5c @tileset1 inc tileset_tmp ;set tileset 1 ($5C=1)
633f: d0 17 bne @set_tileset ;always
6341: a5 1b @choose lda MAPPOS
; Special treatment for side 0 pos $9d,$9e, and side 0/1 pos $7d,$7e -- always
; use tileset 0.
6343: c9 9d cmp #$9d
6345: f0 11 beq @set_tileset
6347: c9 9e cmp #$9e
6349: f0 0d beq @set_tileset
634b: c9 7d cmp #$7d
634d: f0 09 beq @set_tileset
634f: c9 7e cmp #$7e
6351: f0 05 beq @set_tileset
; Choose tileset for remaining positions -- 000..0FF and 100..17F -- using the
; tileset bitmap. (Minus 4 special positions above.) Note that 0160..017F is
; ground level.
6353: 20 15 64 jsr select_tileset_harder
6356: f0 e5 beq @tileset1 ;Z clear, use tileset 1
6358: a5 5c @set_tileset lda tileset_tmp
635a: c5 60 cmp tileset ;looks useless; does set Z if tileset differed
635c: f0 02 beq @rts ;however Z is unused by caller
635e: 85 60 sta tileset
6360: 60 @rts rts
6361: a6 5d ldx $5d
6363: 4c 82 60 jmp game_loop?
spent_a_day_recovering
6366: 20 a3 66 jsr teleport_home
6369: a9 04 lda #$04
636b: 20 d6 66 jsr PRNTSTR
636e: 01 .dd1 $01
636f: d9 cf d5 a0+ .str ↑“YOU SPENT A DAY RECOVERING”
6389: ff .dd1 $ff
638a: 20 d6 66 jsr PRNTSTR
638d: 29 .dd1 $29
638e: c6 d2 cf cd+ .str ↑“FROM LACK OF ”
639b: ff .dd1 $ff
639c: a5 3c lda STARVED
639e: c9 01 cmp #STARVED_food ;01 = lack of food
63a0: d0 0c bne @of_rest
63a2: 20 d6 66 jsr PRNTSTR
63a5: 36 .dd1 $36
63a6: c6 cf cf c4 .str ↑“FOOD”
63aa: ff .dd1 $ff
63ab: 4c b7 63 jmp @end
63ae: 20 d6 66 @of_rest jsr PRNTSTR
63b1: 36 .dd1 $36
63b2: d2 c5 d3 d4 .str ↑“REST”
63b6: ff .dd1 $ff
63b7: a9 00 @end lda #$00 ;clear starved attr
63b9: 85 3c sta STARVED
63bb: 20 06 77 jsr GAME2_message_wait
63be: 4c 82 60 jmp game_loop?
63c1: a9 00 clearfield lda #$00
63c3: 85 05 sta TXTCOL
63c5: 85 06 sta TXTROW
63c7: aa tax
63c8: 20 93 67 @loop jsr gettextaddr
63cb: a9 00 lda #$00
63cd: 81 03 sta (TXTPTR,x)
63cf: e6 05 inc TXTCOL
63d1: a5 05 lda TXTCOL
63d3: c9 28 cmp #40
63d5: d0 f1 bne @loop
63d7: a9 00 lda #$00
63d9: 85 05 sta TXTCOL
63db: e6 06 inc TXTROW
63dd: a5 06 lda TXTROW
63df: c9 14 cmp #20
63e1: d0 e5 bne @loop
63e3: 4c 6c 67 jmp drawfield
coltmp .var $08 {addr/1} ;column counter (+216)
rowtmp .var $65 {addr/1} ;row counter (+252)
63e6: a9 14 cleartext lda #$14 ;from $6006 vec
63e8: 85 06 sta TXTROW
63ea: a9 fc lda #252 ;256 - 252 = 4 (rows)
63ec: 85 65 sta rowtmp
63ee: a9 d8 @row lda #216 ;256 - 16 = 40 (cols)
63f0: 85 08 sta coltmp
63f2: a9 00 lda #$00
63f4: 85 05 sta TXTCOL
63f6: a9 00 @col lda #$00
63f8: 20 e6 67 jsr calc_tile
63fb: 20 5b 68 jsr calc_hires_textpos
63fe: 20 b3 67 jsr writetile
6401: e6 05 inc TXTCOL ;next column
6403: e6 08 inc coltmp ;40 times (counting up from 216!)
6405: d0 ef bne @col
6407: e6 06 inc TXTROW ;next row
6409: e6 65 inc rowtmp ;4 times (counting up from 252!)
640b: d0 e1 bne @row
640d: 60 rts
640e: 20 .dd1 $20
640f: e6 .dd1 $e6
6410: 63 20 6c 67+ .str “c lg`”
********************************************************************************
* Use the tileset bitmap to select tileset 0 or 1 based on the 9-bit map *
* position. The top 6 bits select the bitmap byte, and the bottom 3 bits *
* select the bit in that byte. This code is not called for certain positions *
* (see select_tileset). *
* *
* Clears Z for tileset 1, sets for tileset 0. (The bits are the opposite of *
* the tileset #.) *
********************************************************************************
maptmp .var $11 {addr/1}
6415: a5 1c select_tileset_harder lda MAPHALF
6417: 85 11 sta maptmp ;0 or 1 ($11=0000000S)
6419: a5 1b lda MAPPOS ;A=PPPPPPPP
641b: a2 03 ldx #$03
641d: 46 11 @loop lsr maptmp ;divide 16-bit value in $11/A by 8
641f: 6a ror A
6420: ca dex
6421: d0 fa bne @loop ;A=00SPPPPP (lowest 3 bits discarded)
6423: aa tax ;X=00..3F
6424: bd 00 1d lda GAME1_tileset_bitmap,x ;get byte from tileset bitmap
6427: 85 11 sta maptmp
6429: a5 1b lda MAPPOS ;now handle the lower 3 bits (0..7) of pos
642b: 29 07 and #$07
642d: aa tax
642e: bd 34 64 lda tileset_bittab,x ;each pos 0..7 corresponds to 1 bit in tileset byte
6431: 24 11 bit maptmp
6433: 60 rts
; Used in previous subroutine to test bits 7..0 of $11 based on X=0..7.
6434: 80 tileset_bittab .dd1 $80 ;test bit 7 (x=0)
6435: 40 .dd1 $40
6436: 20 .dd1 $20
6437: 10 .dd1 $10
6438: 08 .dd1 $08
6439: 04 .dd1 $04
643a: 02 .dd1 $02
643b: 01 .dd1 $01 ;test bit 0 (x=7)
643c: a9 00 read_playfield lda #$00
643e: 85 37 sta spokeTo
6440: 85 42 sta MON_A4L
6442: 85 6b sta zp6b_npcHere
6444: a5 1b lda MAPPOS ;lower 4 bits: sector
6446: 29 0f and #$0f
6448: 8d 05 03 sta RWTS_IOB_sector
644b: a5 1b lda MAPPOS ;upper 4 bits: track (-1)
644d: 4a lsr A
644e: 4a lsr A
644f: 4a lsr A
6450: 4a lsr A
6451: 8d 04 03 sta RWTS_IOB_track ;track $01..$10
6454: ee 04 03 inc RWTS_IOB_track ;track + 1
6457: a5 1c lda MAPHALF ;high byte
6459: f0 09 beq L6464 ;0, track unchanged
645b: ad 04 03 lda RWTS_IOB_track ;1, tracks $11..$20
645e: 18 clc
645f: 69 10 adc #$10 ;(add $10 to track)
6461: 8d 04 03 sta RWTS_IOB_track
6464: a9 01 L6464 lda #RWTSCMD_read
6466: 8d 0c 03 sta RWTS_IOB_command
6469: 20 a2 69 jsr swapzp8 ;save ZP
646c: 20 15 03 jsr DIRECT_RWTS
646f: 20 a2 69 jsr swapzp8 ;restore ZP
6472: 20 2f 63 jsr select_tileset
6475: 20 8b 64 jsr write_tiles_to_text
6478: 20 6c 67 jsr drawfield
647b: 20 e6 63 jsr cleartext
647e: 60 rts
647f: 20 8b 64 L647F jsr write_tiles_to_text
6482: 20 6c 67 jsr drawfield
6485: 20 03 6b jsr GAME2_draw_player
6488: 4c 15 6b jmp L6B15
********************************************************************************
* Write tiles to text page, copying them from the run-length encoded RWTS *
* buffer starting at $201. Continues until all text rows are written. *
* *
* Then, reads more data from RWTS and processes it (so it is kind of a *
* misnomer to say it writes tiles). This is really the start point for reading *
* and handling all data for a new map screen. *
* *
* $09/$0A are temp vars but $09 at least is used through several subroutines *
* here. *
********************************************************************************
tiletmp .var $08 {addr/1}
rwtsbuf_idx .var $09 {addr/1}
tilecnt .var $0a {addr/1} ;RLE
648b: a2 03 write_tiles_to_text ldx #$03 ;copy from RWTSBUF into ZP
648d: bd fc 02 @loop lda RWTSBUF+252,x ;<- $2ff,$2fe,$2fd
6490: 95 0b sta $0b,x ;-> $0e,$0d,$0c
6492: ca dex
6493: 10 f8 bpl @loop
6495: a9 00 lda #$00
6497: 85 05 sta TXTCOL ;text col 0
6499: 85 06 sta TXTROW ;text row 0
649b: 20 93 67 jsr gettextaddr ;get address on text page 1
649e: a9 01 lda #$01 ;start with $201
64a0: 85 09 sta rwtsbuf_idx
64a2: a6 09 @next_tile ldx rwtsbuf_idx
64a4: e6 09 inc rwtsbuf_idx
64a6: bd 00 02 lda RWTSBUF,x ;get tile
64a9: 30 0a bmi @rle ;repeating tile 80..FF, branch
64ab: a0 00 ldy #$00
64ad: 91 03 sta (TXTPTR),y ;write tile byte to text screen
64af: 20 d4 64 jsr @next_text_pos ;does not return if all rows written
64b2: 4c a2 64 jmp @next_tile
; When the tile byte has the high bit set, the next byte is a repeat count of
; tile & 0x7F. In other words this is run-length encoded.
64b5: 29 7f @rle and #$7f ;tile 80..FF, strip high bit
64b7: 85 08 sta tiletmp ;tile 00..7F
64b9: a6 09 ldx rwtsbuf_idx
64bb: e6 09 inc rwtsbuf_idx
64bd: bd 00 02 lda RWTSBUF,x ;read next tile byte
64c0: 85 0a sta tilecnt
64c2: e6 0a inc tilecnt
64c4: a0 00 @repeat_tile ldy #$00
64c6: a5 08 lda tiletmp
64c8: 91 03 sta (TXTPTR),y ;write tile byte to text screen
64ca: 20 d4 64 jsr @next_text_pos ;does not return if done
64cd: c6 0a dec tilecnt
64cf: d0 f3 bne @repeat_tile ;repeat tilecnt times
64d1: 4c a2 64 jmp @next_tile
64d4: 20 5e 65 @next_text_pos jsr bump_text_pos ;check if done
64d7: d0 01 bne @read_combo_section ;1 = finish up
64d9: 60 rts ;0 = more tiles
NOTE: $08, $11 and possibly $0a change meanings below.
; Once the screen has been filled with tiles, read additional "combo" bytes
; consisting of a command and a repeat count, followed by a tiled screen
; position. 5 combos write a hardcoded tile triple N times, 1 writes a tile and
; tile+1, and the last terminates the section (in practice, $E0).
64da: 68 @read_combo_section pla ;remove caller address from stack
64db: 68 pla ;(we jsr'ed here)
64dc: a6 09 read_combo_byte ldx rwtsbuf_idx
64de: bd 00 02 lda RWTSBUF,x ;read another byte
64e1: 48 pha ;save it temporarily
64e2: 29 1f and #$1f
64e4: 85 0a sta tilecnt ;save lower 5 bits in $0a
64e6: 68 pla ;restore the read byte
64e7: 29 e0 and #$e0 ;check the top 3 bits only
64e9: c9 e0 cmp #$e0 ;are all 3 top bits set? (in practice byte is $E0)
64eb: d0 07 bne @other_combos ;no, check other combos
64ed: 20 b2 65 jsr display_map_items ;yep, display items
64f0: 20 fc 65 jsr L65FC
64f3: 60 rts
; Write 3 tiles (specified by top 3 bits in last RWTS byte), repeated N rows
; (the low 5 bits in this byte). In other words, %TTTNNNNN. The starting
; position is specified by the next two bytes (to be read).
;
; Check for various combos of TTT (we handled 111 above, which terminates). 5 of
; 6 combos map to hardcoded tile triples. If the tile is b4 or b7, it will write
; b4,b5,b6 or b7,b8,b9. If ba, bb or bc, it will write ba,ba,ba (etc.) These are
; for ladders, vines and doors, which are all 3 tiles across repeated for some
; distance down the screen.
;
; The last combo (011) writes double-wide tiles (letters) at the specified
; position. Here N is the number of tile bytes to read from the stream, written
; as consecutive double-wide tiles.
• Clear variables
64f4: c9 20 @other_combos cmp #%00100000 ;001 -> b4,b5,b6 -> outside green ladder
64f6: d0 02 bne L64FA
64f8: a0 b4 ldy #$b4
64fa: c9 40 L64FA cmp #%01000000 ;010 -> b7,b8,b9 -> inside brown ladder
64fc: d0 02 bne L6500
64fe: a0 b7 ldy #$b7
6500: c9 80 L6500 cmp #%10000000 ;100 -> ba,ba,ba -> outside blue door
6502: d0 02 bne L6506
6504: a0 ba ldy #$ba
6506: c9 a0 L6506 cmp #%10100000 ;101 -> bb,bb,bb -> outside purple door
6508: d0 02 bne L650C
650a: a0 bb ldy #$bb
650c: c9 c0 L650C cmp #%11000000 ;110 -> bc,bc,bc -> inside green / outside black door
650e: d0 02 bne L6512
6510: a0 bc ldy #$bc
6512: c9 60 L6512 cmp #%01100000 ;011 -> read more data
6514: f0 28 beq @combo_011
6516: 84 11 sty temp11_textlo ;store computed tile
6518: 20 7d 65 jsr readTilePos
651b: 86 09 stx temp09
651d: a0 00 @outer_loop ldy #$00
651f: a6 11 ldx temp11_textlo ;computed tile
6521: a9 03 lda #$03
6523: 85 08 sta temp08
6525: 8a @inner_loop txa ;get tile in A
6526: 91 03 sta (TXTPTR),y ;write tile to text screen
6528: e0 ba cpx #$ba ;check tile number
652a: b0 01 bcs @no_inctile ;>= $ba, repeat same tile
652c: e8 inx ;otherwise, increment tile
652d: c8 @no_inctile iny ;next column
652e: c6 08 dec temp08
6530: d0 f3 bne @inner_loop ;3 times
6532: e6 06 inc TXTROW ;next row
6534: 20 93 67 jsr gettextaddr
6537: c6 0a dec temp0a ;repeat %NNNNN rows
6539: d0 e2 bne @outer_loop
653b: 4c dc 64 jmp read_combo_byte
; Combo 011 reads the next 2 position bytes (as normal),
653e: 20 7d 65 @combo_011 jsr readTilePos
; and then reads NNNNN more bytes, each of which is a tile number of a double-
; wide tile. It writes tile and tile+1 to the screen for each tile byte.
;
; This is used, for example, when there are text banners on the screen such as
; "TO TEMPLE GRUND". Each letter is double-width, and each word is (may be)
; written as a separate command block, on top of the background. For example, TO
; TEMPLE GRUND is 3 commands: 62, 66 and 65. (Command $60 with 2, 6, and 5
; letters.)
6541: a0 00 @loop ldy #$00
6543: bd 00 02 lda RWTSBUF,x
6546: e8 inx
6547: 91 03 sta (TXTPTR),y
6549: 18 clc
654a: 69 01 adc #$01
654c: c8 iny
654d: 91 03 sta (TXTPTR),y
654f: 20 5e 65 jsr bump_text_pos
6552: 20 5e 65 jsr bump_text_pos
6555: c6 0a dec temp0a
6557: d0 e8 bne @loop
6559: 86 09 stx temp09
655b: 4c dc 64 jmp read_combo_byte ;more rwts data
; Bump text page 1 position for writing tiles. If we have not written a full
; screen, return 0; if we have, return 1, which is the end condition for reading
; tiles from the RWTS RLE tile buffer.
655e: e6 05 bump_text_pos inc TXTCOL
6560: e6 03 inc TXTPTR
6562: a5 05 lda TXTCOL
6564: c9 28 cmp #$28
6566: d0 12 bne @ret00
6568: a9 00 lda #$00
656a: 85 05 sta TXTCOL
656c: e6 06 inc TXTROW
656e: 20 93 67 jsr gettextaddr
6571: a5 06 lda TXTROW
6573: c9 14 cmp #$14
6575: d0 03 bne @ret00
6577: a9 01 lda #$01
6579: 60 rts
657a: a9 00 @ret00 lda #$00 ;we are not done
657c: 60 rts
NOTE: Unclear why we subtract $40 (or mask top bit) from 16-bit tile position in
combo byte data. If it is for metadata, there are 3 bits left with a simple 2
byte ROW (6 bits) and COL (7 bits) representation.
Since this game was multiplatform, they may have (sanely) assumed contiguous
memory for a 40x20 screen, and kept that representation. The function of the
upper bit is unknown (an actual address?) but the real question is the
subtraction of $40 instead of ANDing it out.
; Called just before any tile combo is written. Reads 2 position bytes from
; RWTSBUF which become a 16-bit address into a 40x20 matrix. Converts that
; address into a (row,col) tuple and returns the resulting address on text page
; 1, where the tile will be written.
;
; First, do some initial munging of the top byte, masking off its top bit, and
; subtracting $40 (for some reason, instead of AND #$3F).
;
; Then, divide the 16-bit value in $03/04 by the 8 bit value #40 (cols/row),
; placing the quotient (row) in TXTROW and the remainder (col) in TXTCOL.
;
; E.g. $A9 $C1 -> $A9 $01 -> $01A9
; $01A9 // 40 = 10 (row 10, 0..23)
; $01A9 % 40 = 25 (col 25, 0..39)
;
; Last, call gettextaddr to compute the screen address of TXTROW/TXTCOL and
; place it in TXTPTR for the caller. Note TXTPTR was used as a temp for the
; divide, and is overwritten.
;
; A simple 2-byte ROW/COL representation would have been easier to deal with and
; still left 3 bits for metadata. This representation looks geared toward the
; contiguous screen memory of other platforms this game was released for.
657d: e8 readTilePos inx
657e: bd 00 02 lda RWTSBUF,x ;read rwts byte into TXTPTR (temp) lo
6581: 85 03 sta TXTPTR ;used as a 16-bit temporary, overwritten at end
6583: e8 inx
6584: bd 00 02 lda RWTSBUF,x ;read rwts byte into TXTPTR (temp) hi
6587: 29 7f and #$7f ;ignoring top bit of second byte
6589: 38 sec
658a: e9 40 sbc #$40 ;and subtracting $40 from second byte
658c: 85 04 sta TXTPTR+1
658e: e8 inx
658f: a9 00 lda #$00
6591: 85 06 sta TXTROW
6593: a5 03 @loop lda TXTPTR ;16-bit subtract of #$0028 from tmpaddr
6595: 38 sec
6596: e9 28 sbc #40
6598: 85 03 sta TXTPTR
659a: a5 04 lda TXTPTR+1
659c: e9 00 sbc #$00 ;propagate low-byte borrow to high byte
659e: 30 07 bmi @done ;finish up
65a0: 85 04 sta TXTPTR+1
65a2: e6 06 inc TXTROW
65a4: 4c 93 65 jmp @loop
65a7: a9 28 @done lda #40
65a9: 18 clc
65aa: 65 03 adc TXTPTR ;overshot $03 by 40, add back in (didn't update $04)
65ac: 85 05 sta TXTCOL
65ae: 20 93 67 jsr gettextaddr ;wipes out $03/04
65b1: 60 rts ;return to caller
********************************************************************************
* Display all the free-standing items in this room, called after the *
* background is displayed. These are all the items from $b500-$b5ff with bit 6 *
* set and bit 5 clear. For item x (00..ff), *
* *
* $b300,x is the item's map position (room) *
* $b500,x bit 7 is the map position high bit *
* $b500,x bit 6 must be set (unknown purpose) *
* $b500,x bit 5 must be clear (used to indicate item is in your inventory) *
* $b500,x bits 0..4 are the screen tile row 0..20 *
* $b400,x is the screen tile column 0..39 *
* *
* All items are 2 tiles in width and the tile number is $fd - (item * 2). *
* Items are duplicated in both tilesets. *
********************************************************************************
65b2: a2 00 display_map_items ldx #$00
65b4: bd 00 b3 @loop lda itemStatePos,x ;256 possible item positions (map rooms)
65b7: c5 1b cmp MAPPOS
65b9: d0 3d bne @next_item
65bb: bd 00 b5 lda itemState,x
65be: 0a asl A
65bf: a9 00 lda #$00
65c1: 2a rol A ;bit 7 -- high bit of map position
65c2: c5 1c cmp MAPHALF
65c4: d0 32 bne @next_item
65c6: bd 00 b5 lda itemState,x
65c9: 2c be 1d bit GAME1_BITTAB6 ;bit 6 -- unknown (must be set here)
65cc: f0 2a beq @next_item
65ce: 2c bd 1d bit GAME1_BITTAB5 ;bit 5 -- item in inventory
65d1: d0 25 bne @next_item
65d3: 29 1f and #$1f ;bits 0..4 (tile row)
65d5: a8 tay
65d6: b9 a0 1d lda GAME1_textlo,y ;Y is the text row
65d9: 85 11 sta temp11_textlo
65db: b9 80 1d lda GAME1_texthi,y
65de: 85 12 sta temp12_texthi
65e0: 8a txa
65e1: 20 03 77 jsr GAME2_slot_to_item
65e4: 84 08 sty temp08
65e6: 06 08 asl temp08 ;because tiles are double-wide?
65e8: a9 fd lda #$fd ;convert item num to tile ($fd-item*2)
65ea: 38 sec
65eb: e5 08 sbc temp08
65ed: bc 00 b4 ldy itemStateCol,x ;item tile column
65f0: 91 11 sta (temp11_textlo),y
65f2: c8 iny
65f3: 18 clc
65f4: 69 01 adc #$01 ;right half of tile
65f6: 91 11 sta (temp11_textlo),y
65f8: e8 @next_item inx
65f9: d0 b9 bne @loop
65fb: 60 rts
65fc: a2 04 L65FC ldx #$04
65fe: 86 08 stx temp08
6600: 20 4f 66 jsr L664F
6603: a5 60 lda tileset
6605: d0 0b bne L6612
6607: a9 00 lda #$00
6609: 85 11 sta temp11_textlo
660b: a9 37 lda #$37
660d: 85 12 sta temp12_texthi
660f: 4c 1a 66 jmp L661A
6612: a9 00 L6612 lda #$00
6614: 85 11 sta temp11_textlo
6616: a9 2e lda #$2e
6618: 85 12 sta temp12_texthi
661a: a9 59 L661A lda #$59
661c: 85 03 sta TXTPTR
661e: a0 52 ldy #$52
6620: a5 0c lda $0c
6622: 20 47 66 jsr L6647
6625: a9 73 lda #$73
6627: 85 03 sta TXTPTR
6629: a0 59 ldy #$59
662b: a5 0d lda $0d
662d: 20 47 66 jsr L6647
6630: a9 77 lda #$77
6632: 85 03 sta TXTPTR
6634: a0 73 ldy #$73
6636: a5 0e lda $0e
6638: 20 47 66 jsr L6647
663b: a9 b4 lda #$b4
663d: 85 03 sta TXTPTR
663f: a0 77 ldy #$77
6641: a5 0b lda $0b
6643: 20 47 66 jsr L6647
6646: 60 rts
6647: 91 11 L6647 sta (temp11_textlo),y
6649: c8 iny
664a: c4 03 cpy TXTPTR
664c: d0 f9 bne L6647
664e: 60 rts
664f: a2 00 L664F ldx #$00
6651: a5 1c lda MAPHALF
6653: f0 14 beq L6669
6655: a5 1b lda MAPPOS
6657: c9 80 cmp #$80
6659: 90 0e bcc L6669
665b: ad 01 b5 lda itemState+1
665e: 2c bd 1d bit GAME1_BITTAB5
6661: d0 06 bne L6669
6663: a5 3a lda litLamp
6665: d0 02 bne L6669
6667: a2 01 ldx #$01
6669: 86 5e L6669 stx $5e
666b: 60 rts
666c: 20 a3 66 found_near_water jsr teleport_home
666f: 20 d6 66 jsr PRNTSTR
6672: 29 .dd1 $29
6673: d9 cf d5 a0+ .str ↑“YOU WERE FOUND NEAR THE WATER.”
6691: ff .dd1 $ff
6692: 20 09 77 jsr L7709
6695: 20 06 77 jsr GAME2_message_wait
6698: a9 00 lda #$00
669a: 85 80 sta touchedWater
669c: a9 01 lda #$01 ;start the clock
669e: 85 87 sta TICKING
66a0: 4c 86 60 jmp tick0
66a3: a9 00 teleport_home lda #$00
66a5: 85 6b sta zp6b_npcHere
66a7: a5 2d lda homePos
66a9: 85 1b sta MAPPOS
66ab: a5 2e lda homeHalf
66ad: 85 1c sta MAPHALF
66af: a9 01 lda #$01
66b1: 85 67 sta INSIDE
66b3: 20 3c 64 jsr read_playfield
66b6: a5 2f lda homeX
66b8: 85 19 sta playerX
66ba: a5 30 lda homeY
66bc: 85 1a sta playerY
66be: a2 2e ldx #$2e
66c0: 86 a3 stx animFrame
66c2: e8 inx
66c3: 86 a4 stx animFrame_unused
66c5: 20 03 6b jsr GAME2_draw_player
66c8: e6 22 inc dayNum ;lose a day
66ca: a5 27 lda limitSpirit ;restore spirit
66cc: 85 23 sta levelSpirit
66ce: a6 2a ldx limitFood ;limitFood and limitRest are always identical, so
66d0: ca dex ;I guess they realized checking 2 vars was pointless
66d1: 86 24 stx levelFood ;restore food and rest (to limit - 1)
66d3: 86 25 stx levelRest
66d5: 60 rts
********************************************************************************
* Print inline string to hires text area (last 4 lines). The inline data is: *
* 1 byte -- hpos, the horizontal position of the string *
* x bytes - high ascii string data *
* $ff - string terminator *
* *
* The hpos byte starts from $00 (col 1, row 1) and wraps at $28 (col 1, row *
* 2), $50 and $78, so it encodes vertical position as well. In practice, *
* strings are indented by 1 so $01, $29 etc are typical. Strings will wrap at *
* end of screen. *
* *
* The use of $ff instead of $00 to terminate strings could be a cross-platform *
* concession, although platforms where $00 is a valid character would not be *
* using high-ascii anyway. *
********************************************************************************
inlinedata .var $61 {addr/2}
ysav .var $63 {addr/1}
66d6: 68 PRNTSTR pla ;inline data; store addr-1 in $61/$62
66d7: 85 61 sta inlinedata
66d9: 68 pla
66da: 85 62 sta inlinedata+1
66dc: a0 01 ldy #$01 ;addr-1+1
66de: b1 61 lda (inlinedata),y
66e0: 85 64 sta HTAB ;first byte of inline data is indent
66e2: c8 iny
66e3: b1 61 @loop lda (inlinedata),y ;A=char
66e5: c9 ff cmp #$ff ;end of string?
66e7: f0 0e beq @continue
66e9: 84 63 sty ysav ;save y
66eb: 20 09 67 jsr printchar
66ee: e6 05 inc TXTCOL ;??
66f0: e6 64 inc HTAB
66f2: a4 63 ldy ysav ;restore y
66f4: c8 iny
66f5: d0 ec bne @loop ;always, effectively
; Offset the return address in $61/$62 with the inline data length, then jump to
; it to continue.
66f7: c8 @continue iny
66f8: 98 tya
66f9: 18 clc
66fa: 65 61 adc inlinedata
66fc: 85 61 sta inlinedata
66fe: 90 02 bcc @nowrap ;check for page wrap
6700: e6 62 inc inlinedata+1 ;and wrap page
6702: a9 00 @nowrap lda #$00
6704: 85 66 sta INVTEXT
6706: 6c 61 00 jmp ($0061)
; Print char in A at horiz pos htab in text area. Converts position to
; fullscreen TXTROW/COL. Indexes the char ($00..$3F) into hires char bitmap
; $2C00 at 8 bytes per char. Then draws the char on the hires screen.
6709: 48 printchar pha ;save char
670a: a9 13 lda #19 ;screen line 19 (will be 20)
670c: 85 06 sta TXTROW
670e: a5 64 lda HTAB
; Add quotient(htab,40)+1 to TXTROW -- implement wrapping.
6710: 38 @incrow sec ;subtract 40 cols from htab
6711: e9 28 sbc #40
6713: e6 06 inc TXTROW
6715: b0 f9 bcs @incrow ;add 1 to TXTROW until htab < 0
6717: 18 clc
6718: 69 28 adc #40
671a: 85 05 sta TXTCOL ;adjust +40 (we overshot 1 iter of -40)
671c: 68 pla ;restore char
671d: 29 3f and #$3f ;convert $C0..DF to $00..1F, $A0..BF to $20..3F (?)
671f: 85 16 sta tileptr ;store char # in $16/17
6721: a9 00 lda #$00
6723: 85 17 sta tileptr+1
6725: 06 16 asl tileptr ;mult $16 (addr/2) by 8 bytes (per char data)
6727: 26 17 rol tileptr+1
6729: 06 16 asl tileptr
672b: 26 17 rol tileptr+1
672d: 06 16 asl tileptr
672f: 26 17 rol tileptr+1
6731: a5 16 lda tileptr
6733: 18 clc
6734: 69 00 adc #<GAME1_chardata
6736: 85 16 sta tileptr
6738: a5 17 lda tileptr+1
673a: 69 2c adc #>GAME1_chardata
673c: 85 17 sta tileptr+1
673e: 20 5b 68 jsr calc_hires_textpos ;calc hires addr in $14
6741: 20 45 67 jsr drawchar ;draw ($16) data at ($14)
6744: 60 rts
; Draw 8 lines of character data at ($16) to the hires screen at ($14).
; Actually, the first written line is blank, and then the first 7 lines of
; actual data are written; the 8th line is ignored. This creates line spacing by
; shifting everything down a pixel. This is a little odd, but perhaps let them
; switch to top-spacing (which offsets text from the playfield) without changing
; the char data.
lines .var $07 {addr/1} ;lines left to draw
6745: a2 00 drawchar ldx #$00 ;this will draw normal pixels
6747: a5 66 lda INVTEXT ;inverse text?
6749: f0 02 beq @draw
674b: a2 7f ldx #$7f ;this will flip (XOR) pixels (inverse?)
674d: 86 18 @draw stx MASK ;mask. may be global var
674f: a9 08 lda #$08 ;8 lines
6751: 85 07 sta lines
6753: a2 00 ldx #$00
6755: a0 00 ldy #$00
6757: a9 80 lda #$80 ;first line empty (note bit 7 color set)
6759: 45 18 @loop eor MASK ;possibly invert text
NOTE: Is $14/15 global? Is $16/17?
675b: 81 14 sta (hires_addr,x) ;$14 (addr/2) prob hires screen, unsure where set
675d: a5 15 lda hires_addr+1
675f: 18 clc
6760: 69 04 adc #$04 ;next hires line (+$0400)
6762: 85 15 sta hires_addr+1
6764: b1 16 lda (tileptr),y
6766: c8 iny
6767: c6 07 dec lines
6769: d0 ee bne @loop
676b: 60 rts
NOTE: Draws 20 lines of text, sourced from text page 1, to hires screen. This
looks like 40x20 tiled graphics data stored as text, made further apparent by
NOPing out the 4 instructions at $A857 to set HIRES2, leaving GR active. This
shows lores colored blocks in the obvious shape of game screens.
text1 .var $03 {addr/2} ;FIXME: this is TXTPTR
676c: a9 00 drawfield lda #$00
676e: 85 05 sta TXTCOL
6770: 85 06 sta TXTROW
6772: 20 93 67 @line jsr gettextaddr
6775: a0 00 @char ldy #$00
6777: b1 03 lda (text1),y ;load from text page 1
6779: 20 a9 67 jsr drawtile
677c: e6 03 inc text1 ;page aligned, so no high byte inc
677e: e6 05 inc TXTCOL ;next col
6780: a5 05 lda TXTCOL
6782: c9 28 cmp #40 ;comp $05 with 40; def looks like a column now
6784: d0 ef bne @char
6786: a9 00 lda #$00
6788: 85 05 sta TXTCOL ;reset to column 1
678a: e6 06 inc TXTROW ;and bump row
678c: a5 06 lda TXTROW
678e: c9 14 cmp #20 ;reached row 21?
6790: d0 e0 bne @line ;no, keep going
6792: 60 rts
; Converting a col/row ($05/$06) to an address on text page 1. Output address is
; in $03/04. X is preserved.
6793: 8a gettextaddr txa
6794: 48 pha
6795: a6 06 ldx TXTROW
6797: bd a0 1d lda GAME1_textlo,x ;low byte of text page line
679a: 18 clc
679b: 65 05 adc TXTCOL
679d: 85 03 sta text1
679f: bd 80 1d lda GAME1_texthi,x ;high byte of text page line
67a2: 69 00 adc #$00
67a4: 85 04 sta text1+1
67a6: 68 pla
67a7: aa tax
67a8: 60 rts
; Input: A = tile number.
67a9: 20 e6 67 drawtile jsr calc_tile
67ac: 20 5b 68 jsr calc_hires_textpos
67af: 20 b3 67 jsr writetile
67b2: 60 rts
67b3: a5 5e writetile lda $5e
67b5: f0 05 beq L67BC
67b7: a9 00 lda #$00
67b9: 20 e6 67 jsr calc_tile
67bc: a9 00 L67BC lda #$00
67be: a2 00 ldx #$00
67c0: a9 08 lda #$08 ;8 lines in a tile
67c2: 85 07 sta lines
67c4: a0 00 ldy #$00
67c6: b1 16 @line lda (tileptr),y ;read tile data
67c8: 25 18 and MASK ;apply global mask
67ca: 81 14 sta (hires_addr,x) ;write tile data
67cc: a5 07 lda lines
67ce: 6a ror A ;check if A (lines) is odd
67cf: 90 08 bcc @no_and ;ignore odd line mask on even lines
67d1: a5 5f lda ODDLINE_MASK
67d3: f0 04 beq @no_and ;ignore odd line mask when zero
; If the sta to $14 is removed, the purple odd-line hatching on the title screen
; is gone, and houses are now a single color. The odd line mask is a clever way
; to add shading/hatching. Note that odd lines are written twice if masked; the
; second write clobbers the first.
67d5: 31 16 and (tileptr),y
67d7: 81 14 sta (hires_addr,x)
67d9: c8 @no_and iny ;next line
67da: a5 15 lda hires_addr+1 ;next hires line (+$0400)
67dc: 18 clc
67dd: 69 04 adc #$04
67df: 85 15 sta hires_addr+1
67e1: c6 07 dec lines
67e3: d0 e1 bne @line ;write 8 lines
67e5: 60 rts
********************************************************************************
* Calculate tile data. A is the tile number. There appear to be 2 tilesets, *
* tileset 1 at $2E00 ($2F00), and tileset 0 at $3700 ($3800), selected by the *
* value of $60. *
* *
* The tile mask and odd line mask are retrieved from 6 possible 16-element *
* mask arrays; the first $100 bytes of data are mask indices. Tiles $00-$49 *
* and $75..$ff use one mask array for even columns and a second array for odd *
* columns; their oddline mask is disabled. Tiles $4a-$74 use a mask array for *
* even columns/even lines, one for odd columns/even lines, one for even *
* columns/odd lines, and one for odd columns/odd lines. *
* *
* Finally, tileptr ($16) is set to the hires tile bitmap. *
********************************************************************************
67e6: 85 16 calc_tile sta tileptr
67e8: a8 tay ;Y used in L681A
67e9: a9 00 lda #$00
67eb: 85 5f sta ODDLINE_MASK ;disable oddline mask by default
67ed: a5 60 lda tileset
67ef: d0 29 bne tileset_1
67f1: b9 00 37 lda GAME1_tileset0_masks,y ;note very close to $3800
67f4: aa tax
67f5: a5 16 lda tileptr
67f7: c9 4a cmp #$4a ;is tile between $4a and $74?
67f9: 90 23 bcc @mask_tileset ;no, use simple tileset mask
67fb: c9 75 cmp #$75
67fd: b0 1f bcs @mask_tileset
67ff: a5 05 lda TXTCOL
6801: 6a ror A
6802: 90 0b bcc @evencol ;branch if column even
6804: bd e0 1f lda GAME1_odd_col_odd_line_mask,x ;apply odd column odd line mask
6807: 85 5f sta ODDLINE_MASK
6809: bd c0 1f lda GAME1_odd_col_even_line_mask,x
680c: 4c 29 68 jmp @finalize
680f: bd f0 1f @evencol lda GAME1_even_col_odd_line_mask,x ;apply even column odd line mask
6812: 85 5f sta ODDLINE_MASK
6814: bd d0 1f lda GAME1_even_col_even_line_mask,x
6817: 4c 29 68 jmp @finalize
681a: b9 00 2e tileset_1 lda GAME1_tileset1_masks,y ;note very close to $2F00 (see just below)
681d: aa tax
681e: a5 05 @mask_tileset lda TXTCOL
6820: 6a ror A
6821: bd b0 1f lda GAME1_even_col_mask,x ;even column mask
6824: 90 03 bcc @finalize
6826: bd a0 1f lda GAME1_odd_col_mask,x ;odd column mask
; Everything ends up here to write A to MASK and calculate tileptr.
6829: 85 18 @finalize sta MASK
682b: a9 00 lda #$00
682d: 85 17 sta tileptr+1
682f: 06 16 asl tileptr ;16-bit mul $16 by 8
6831: 26 17 rol tileptr+1
6833: 06 16 asl tileptr
6835: 26 17 rol tileptr+1
6837: 06 16 asl tileptr
6839: 26 17 rol tileptr+1
683b: a5 60 lda tileset
683d: d0 0e bne add_2F00_to_zp16 ;*$16 += $2F00 (when $60 is nonzero)
683f: a5 16 lda tileptr ;*$16 += $3800 (when $60 is zero)
6841: 18 clc
6842: 69 00 adc #$00
6844: 85 16 sta tileptr
6846: a5 17 lda tileptr+1
6848: 69 38 adc #$38
684a: 85 17 sta tileptr+1
684c: 60 rts
; Add $2F00 to the 16-bit address in $16.
684d: a5 16 add_2F00_to_zp16 lda tileptr
684f: 18 clc
6850: 69 00 adc #$00
6852: 85 16 sta tileptr
6854: a5 17 lda tileptr+1
6856: 69 2f adc #$2f
6858: 85 17 sta tileptr+1
685a: 60 rts
; Convert TEXTROW/TEXTCOL to hires address and stores addr in $14.
685b: a2 20 calc_hires_textpos ldx #$20 ;offset into hireshi ($20+$20 will be page 2)
685d: 86 15 stx hires_addr+1
685f: a9 00 lda #$00
6861: 85 14 sta hires_addr
6863: a4 06 ldy TXTROW
6865: b9 40 1d lda GAME1_hireslo,y ;hires line table
6868: 18 clc
6869: 65 14 adc hires_addr
686b: 85 14 sta hires_addr
686d: b9 60 1d lda GAME1_hireshi,y ;hires page 2
6870: 65 15 adc hires_addr+1
6872: 85 15 sta hires_addr+1
6874: a5 05 lda TXTCOL
6876: 18 clc
6877: 65 14 adc hires_addr
6879: 85 14 sta hires_addr
687b: a9 00 lda #$00
687d: 65 15 adc hires_addr+1
687f: 85 15 sta hires_addr+1
6881: 60 rts
NOTE: There's already a handle_npc? so this is another temp name.
6882: a9 00 handle_npc2? lda #$00
6884: 85 6b sta zp6b_npcHere
6886: a9 32 lda #$32
6888: 85 6c sta npcX
688a: 85 6d sta npcY
688c: ae f1 02 ldx RWTSBUF_npcnum
688f: bd 00 b2 lda state_npc1,x ;differs from state_npc
6892: 2c bf 1d bit GAME1_BITTAB7 ;test bit 7
6895: f0 01 beq @check_npc_present ;if 0
6897: 60 rts
6898: ad e1 02 @check_npc_present lda RWTSBUF_npc
689b: d0 01 bne @npc_present
689d: 60 rts
689e: ad f2 02 @npc_present lda RWTSBUF_npctype
68a1: 29 f0 and #$f0
68a3: c9 e0 cmp #$e0
68a5: d0 1b bne L68C2
68a7: bd 80 b2 lda state_npc,x ;npctype $e0..$ef -- check state bits 0..4
68aa: 29 1f and #$1f
68ac: c5 21 cmp timeOfDay
68ae: f0 12 beq L68C2
68b0: 20 63 61 jsr read_0900_next ;probably pseudo-randomness
68b3: 29 03 and #$03 ;test lowest 2 bits
68b5: f0 01 beq L68B8 ;25% chance?
68b7: 60 rts
NOTE: May handle periodic NPC behavior... walking?
68b8: bd 80 b2 L68B8 lda state_npc,x
68bb: 29 e0 and #$e0
68bd: 05 21 ora timeOfDay ;update NPC's state with current time of day
68bf: 9d 80 b2 sta state_npc,x
68c2: ad e1 02 L68C2 lda RWTSBUF_npc ;the only place where the value (not bool) of NPC is used
68c5: 4a lsr A
68c6: 4a lsr A
68c7: 4a lsr A
68c8: 4a lsr A
68c9: 85 6a sta $6a ;store top 4 bits (shifted to low bits)
68cb: aa tax
68cc: bd 86 69 lda L6986,x
68cf: 85 11 sta temp11_textlo
68d1: bd 91 69 lda L6991,x
68d4: 85 12 sta temp12_texthi
68d6: a9 02 lda #$02
68d8: 85 08 sta temp08
68da: a6 08 L68DA ldx temp08
68dc: bd 8b 69 lda L698B,x
68df: 85 09 sta temp09
68e1: bd 9c 69 lda L699C,x
68e4: 85 0a sta temp0a
68e6: bd 8e 69 lda L698E,x
68e9: 85 68 sta $68
68eb: bd 9f 69 lda L699F,x
68ee: 85 69 sta $69
68f0: a0 7e ldy #$7e
68f2: a2 08 L68F2 ldx #$08
68f4: b1 11 lda (temp11_textlo),y
68f6: 91 09 sta (temp09),y
68f8: 0a L68F8 asl A
68f9: 66 65 ror $65
68fb: ca dex
68fc: d0 fa bne L68F8
68fe: a5 65 lda $65
6900: 91 68 sta ($68),y
6902: 88 dey
6903: 10 ed bpl L68F2
6905: a0 7e ldy #$7e
6907: b1 68 L6907 lda ($68),y
6909: 48 pha
690a: 88 dey
690b: 88 dey
690c: b1 68 lda ($68),y
690e: c8 iny
690f: c8 iny
6910: 91 68 sta ($68),y
6912: 88 dey
6913: 88 dey
6914: 68 pla
6915: 91 68 sta ($68),y
6917: c0 40 cpy #$40
6919: d0 01 bne L691C
691b: 88 dey
691c: 88 L691C dey
691d: 10 e8 bpl L6907
691f: 18 clc
6920: a5 11 lda temp11_textlo
6922: 69 80 adc #$80
6924: 90 02 bcc L6928
6926: e6 12 inc temp12_texthi
6928: 85 11 L6928 sta temp11_textlo
692a: c6 08 dec temp08
692c: 10 ac bpl L68DA
692e: ad e4 02 lda RWTSBUF_npcX
6931: 85 6c sta npcX
6933: ad e5 02 lda RWTSBUF_npcY
6936: 85 6d sta npcY
6938: ad e3 02 lda RWTSBUF+227
693b: 48 pha
693c: 29 0f and #$0f
693e: 85 6e sta zp6e
6940: 68 pla
6941: 4a lsr A
6942: 4a lsr A
6943: 4a lsr A
6944: 4a lsr A
6945: 85 08 sta temp08
6947: 20 63 61 L6947 jsr read_0900_next
694a: 29 1f and #$1f
694c: c5 08 cmp temp08
694e: b0 f7 bcs L6947
6950: 18 clc
6951: 65 6c adc npcX
6953: 85 6c sta npcX
6955: 20 63 61 jsr read_0900_next
6958: 29 01 and #$01
695a: d0 02 bne L695E
695c: a9 ff lda #$ff
695e: 85 6f L695E sta npcFacing
6960: 20 18 6b jsr L6B18
6963: 20 15 6b jsr L6B15
6966: a9 00 lda #$00
6968: 85 50 sta $50
696a: 85 51 sta $51
696c: 85 52 sta $52
696e: 85 53 sta $53
6970: a9 04 lda #$04
6972: 85 54 sta $54
6974: ad e2 02 lda RWTSBUF+226
6977: 48 pha
6978: 29 0f and #$0f ;lower 4 bits in $45
697a: 85 45 sta MON_A5H ;used only in LA065 in combo with $28
697c: 68 pla
697d: 4a lsr A
697e: 4a lsr A
697f: 4a lsr A
6980: 4a lsr A
6981: 85 46 sta $46 ;upper 4 bits in $46 (shifted right 4)
6983: e6 6b inc zp6b_npcHere
6985: 60 rts
6986: 80 L6986 .dd1 $80
6987: 00 .dd1 $00
6988: 80 .dd1 $80
6989: 00 .dd1 $00
698a: 80 .dd1 $80
698b: 00 L698B .dd1 $00
698c: 80 .dd1 $80
698d: 00 .dd1 $00
698e: 80 L698E .dd1 $80
698f: 00 .dd1 $00
6990: 80 .dd1 $80
6991: 85 L6991 .dd1 $85
6992: 87 .dd1 $87
6993: 88 .dd1 $88
6994: 8a .dd1 $8a
6995: 8b .dd1 $8b
6996: 8d .dd1 $8d
6997: 8e .dd1 $8e
6998: 90 .dd1 $90
6999: 91 .dd1 $91
699a: 93 .dd1 $93
699b: 94 .dd1 $94
699c: b0 L699C .dd1 $b0
699d: af .dd1 $af
699e: af .dd1 $af
699f: b1 L699F .dd1 $b1
69a0: b1 .dd1 $b1
69a1: b0 .dd1 $b0
; Swap $0000..00FF with $0800..08FF. Generally called to save/restore
; zero page when reading a new sector (screen) from disk.
69a2: a2 00 swapzp8 ldx #$00
69a4: bd 00 00 @loop lda a:$0000,x
69a7: 48 pha
69a8: bd 00 08 lda $0800,x
69ab: 9d 00 00 sta a:$0000,x
69ae: 68 pla
69af: 9d 00 08 sta $0800,x
69b2: e8 inx
69b3: d0 ef bne @loop
69b5: 60 rts
; Copy X pages of data from page A ($AA00) to page Y ($YY00).
dst .var $09 {addr/2}
src .var $11 {addr/2}
69b6: 85 12 copypages sta src+1
69b8: 84 0a sty dst+1
69ba: a0 00 ldy #$00
69bc: 84 11 sty src
69be: 84 09 sty dst
69c0: b1 11 @loop lda (src),y
69c2: 91 09 sta (dst),y
69c4: c8 iny
69c5: d0 f9 bne @loop
69c7: e6 12 inc src+1 ;next page
69c9: e6 0a inc dst+1
69cb: ca dex
69cc: d0 f2 bne @loop
69ce: 60 rts
; Zero out X pages starting from page A ($AA00).
dst .var $11 {addr/2}
69cf: 85 12 clearpages sta dst+1
69d1: a9 00 lda #$00
69d3: 85 11 sta dst
69d5: a8 tay ;A and Y are now 0
69d6: 91 11 @loop sta (dst),y
69d8: c8 iny
69d9: d0 fb bne @loop
69db: e6 12 inc dst+1
69dd: ca dex
69de: d0 f6 bne @loop
69e0: 60 rts
; Delay loop. Decrement Y 256 times, X times. X and Y are 0 on exit.
69e1: a0 00 delayXtimes256 ldy #$00
69e3: 88 @dey dey
69e4: d0 fd bne @dey
69e6: ca dex
69e7: d0 f8 bne delayXtimes256
69e9: 60 rts
; Delay loop. Decrement Y 512 times, X times. X and Y are 0 on exit.
69ea: 88 delay2 dey
69eb: d0 fd bne delay2
69ed: 88 @dey dey
69ee: d0 fd bne @dey
69f0: ca dex
69f1: d0 f7 bne delay2
69f3: 60 rts
69f4: 20 e6 63 spirit_bell_rings jsr cleartext
69f7: 20 d6 66 jsr PRNTSTR
69fa: 01 .dd1 $01
69fb: d4 c8 c5 a0+ .str ↑“THE SPIRIT BELL RINGS”
6a10: ff .dd1 $ff
6a11: a2 0c ldx #$0c
6a13: 20 03 b6 jsr SCRN_play_sound
6a16: 20 06 77 jsr GAME2_message_wait
6a19: a9 00 lda #$00
6a1b: 85 bc sta zpBC_bellrings
6a1d: 4c 82 60 jmp game_loop?
6a20: a5 1c L6A20 lda MAPHALF
6a22: d0 0a bne L6A2E
6a24: a5 1b lda MAPPOS
6a26: c9 be cmp #$be
6a28: d0 03 bne L6A2D
6a2a: 20 1e 9c L6A2A jsr SCRN_triumph_melody
6a2d: 60 L6A2D rts
6a2e: a5 1b L6A2E lda MAPPOS
6a30: c9 80 cmp #$80
6a32: d0 f9 bne L6A2D
6a34: f0 f4 beq L6A2A
6a36: 20 d6 66 game_over jsr PRNTSTR
6a39: 01 .dd1 $01
6a3a: d4 c8 c5 a0+ .str ↑“THE LIGHT FADES INTO DARKNESS...”
6a5a: ff .dd1 $ff
6a5b: 20 d6 66 jsr PRNTSTR
6a5e: 29 .dd1 $29
6a5f: d4 c8 c5 a0+ .str ↑“THE TIME FOR YOUR QUEST HAS ENDED.”
6a81: ff .dd1 $ff
6a82: 20 d6 66 jsr PRNTSTR
6a85: 51 .dd1 $51
6a86: c7 d2 c5 c5+ .str ↑“GREEN-SKY AWAITS ANOTHER QUESTER.”
6aa7: ff .dd1 $ff
6aa8: a9 00 lda #$00
6aaa: 20 00 b6 jsr SCRN_play_melody
6aad: a5 83 L6AAD lda waitMelody
6aaf: d0 fc bne L6AAD
6ab1: 20 09 6b L6AB1 jsr GAME2_ongoing_input
6ab4: f0 fb beq L6AB1
6ab6: a9 00 lda #$00
6ab8: 85 3d sta GAMEOVER ;unset gameover
6aba: 85 ba sta $ba
6abc: 4c 40 a8 jmp SCRN_warm_start
; Read T22,S00..02 into $B300..$B5FF. This sets the initial item state from the
; game disk. Note the RWTS IOB r/w buffer points to $0200 by default, and that
; is temporarily changed during this read.
6abf: a9 22 init_item_state lda #$22
6ac1: 8d 04 03 sta RWTS_IOB_track
6ac4: a9 00 lda #$00
6ac6: 85 41 sta MON_A3H
6ac8: 85 35 sta doorNeshom
6aca: 85 44 sta lampFuel
6acc: 85 3a sta litLamp
6ace: 85 38 sta fallaKeyOffered
6ad0: 8d 05 03 sta RWTS_IOB_sector
6ad3: a9 01 lda #RWTSCMD_read
6ad5: 8d 0c 03 sta RWTS_IOB_command
6ad8: ae 05 03 L6AD8 ldx RWTS_IOB_sector
6adb: bd e5 62 lda item_state_pages,x ;override page to read into
6ade: 8d 09 03 sta RWTS_IOB_buf+1
6ae1: 20 a2 69 jsr swapzp8
6ae4: 20 15 03 jsr DIRECT_RWTS
6ae7: 20 a2 69 jsr swapzp8
6aea: ee 05 03 inc RWTS_IOB_sector
6aed: ad 05 03 lda RWTS_IOB_sector
6af0: c9 03 cmp #$03
6af2: d0 e4 bne L6AD8 ;read sectors 00..02
6af4: a9 02 lda #$02 ;restore read buffer to page $02
6af6: 8d 09 03 sta RWTS_IOB_buf+1
6af9: 60 rts
6afa: 05 .dd1 $05
6afb: 03 .dd1 $03
6afc: ad .dd1 $ad
6afd: 05 .dd1 $05
6afe: 03 .dd1 $03
6aff: c9 .dd1 $c9
NOTE: Jump vectors at $6b00
6b00: 4c 30 6b GAME2_next_frame jmp frame ;game tick
6b03: 4c 4f 74 GAME2_draw_player jmp draw_player
6b06: 4c 20 75 GAME2_erase_player jmp erase_old_player
6b09: 4c c3 75 GAME2_ongoing_input jmp get_ongoing_input
6b0c: 4c 4c 74 GAME2_redraw_player jmp redraw_player
6b0f: 4c 2a 72 GAME2_adjacent_tiles jmp get_adjacent_tiles
6b12: 4c 7e 72 L6B12 jmp tile_to_f0_f1_f2
6b15: 4c 79 75 L6B15 jmp draw_npc? ;called in SCREEN
6b18: 4c 62 75 L6B18 jmp L7562
6b1b: 4c .dd1 $4c ;called in SCREEN
6b1c: a6 .dd1 $a6
6b1d: 75 .dd1 $75
6b1e: 4c 60 72 GAME2_tile_at_xy jmp get_tile_at_xy ;get_tile_at_xy
6b21: 4c d6 72 L6B21 jmp stop_frame_ground
6b24: 4c f6 72 GAME2_win_game jmp win_game
6b27: 4c 09 b6 GAME2_chkkey jmp SCRN_chkkey ;external entry point
6b2a: 4c b1 75 GAME2_menu_input jmp get_menu_input
6b2d: 4c .dd1 $4c
6b2e: 7d .dd1 $7d
6b2f: 71 .dd1 $71
6b30: 20 57 6b frame jsr maybe_tick
6b33: a5 b3 lda $b3
6b35: f0 03 beq L6B3A
6b37: 20 a6 75 jsr L75A6
6b3a: a5 b2 L6B3A lda erasePlayer ;May indicate player needs to be erased
6b3c: d0 05 bne @erase_and_draw
6b3e: a5 b3 lda $b3
6b40: d0 04 bne L6B46
6b42: 60 rts
6b43: 20 20 75 @erase_and_draw jsr erase_old_player
6b46: a5 6b L6B46 lda zp6b_npcHere
6b48: f0 03 beq @draw
6b4a: 20 79 75 jsr draw_npc? ;?
6b4d: 20 4f 74 @draw jsr draw_player
6b50: a9 00 lda #$00
6b52: 85 b3 sta $b3
6b54: 85 b2 sta erasePlayer
6b56: 60 rts
; Tick if the game timer is running.
6b57: a5 87 maybe_tick lda TICKING
6b59: d0 01 bne tick
6b5b: 60 rts
6b5c: 20 1b 77 tick jsr GAME2_next_tick
6b5f: 20 a9 6f jsr handle_npc?
6b62: e6 88 inc animTimer
6b64: a5 88 lda animTimer ;? timer counting up until animDelay to update player frame
6b66: c5 90 cmp animDelay ;why not just dec animDelay
6b68: f0 01 beq @update
6b6a: 60 rts
6b6b: a9 00 @update lda #$00
6b6d: 85 88 sta animTimer
6b6f: 20 2a 72 jsr get_adjacent_tiles
6b72: a5 e3 lda tileUnder
6b74: 20 7e 72 jsr tile_to_f0_f1_f2
6b77: a5 9b lda crouchFlag
6b79: f0 03 beq L6B7E
6b7b: 4c cf 6e jmp uncrouch ;resets $9b and returns -- noop frame?
6b7e: a5 f0 L6B7E lda ySolid
6b80: f0 14 beq L6B96
6b82: a5 92 lda FALLCNT
6b84: f0 10 beq L6B96 ;not falling, branch
6b86: c9 06 cmp #$06 ;did we fall less than 6 tiles?
6b88: 90 03 bcc @footfall
6b8a: 20 0e 6e jsr fell_6_or_more ;>=6 tiles, jsr
6b8d: a2 02 @footfall ldx #$02 ;landing noise
6b8f: 20 03 b6 jsr SCRN_play_sound
6b92: a9 00 lda #$00 ;reset fall count
6b94: 85 92 sta FALLCNT
6b96: a5 96 L6B96 lda takingStep
6b98: f0 03 beq check_bonk
6b9a: 4c d6 6e jmp walk_crawl_cycle
6b9d: a5 93 check_bonk lda bonkFrame
6b9f: f0 03 beq check_jumping
6ba1: 4c cf 6d jmp bonking
6ba4: a5 8c check_jumping lda jumpFlag
6ba6: f0 03 beq check_flying
6ba8: 4c 12 6d jmp jumping
6bab: a5 94 check_flying lda flyFlag
6bad: f0 03 beq @notflying_check_x
6baf: 4c 66 6e jmp flying
6bb2: a5 85 @notflying_check_x lda XDIR
6bb4: 85 91 sta $91 ;save old xdir ?
6bb6: 20 c3 75 jsr get_ongoing_input
6bb9: f0 54 beq check_non_door_tile ;no button pressed
6bbb: a5 92 lda FALLCNT ;(virtual) button press
6bbd: c9 02 cmp #$02 ;have we fallen >= 2 tiles?
6bbf: 90 0b bcc button_check_x
6bc1: a5 f0 lda ySolid ;and no solid ground below us?
6bc3: d0 07 bne button_check_x
6bc5: a5 a0 lda $a0 ;and ???
6bc7: d0 03 bne button_check_x
6bc9: 4c 40 6e jmp check_has_shuba ;then do shuba check, we may fly
; Reached here after (virtual) button press, and not trying to deploy shuba.
; Check X motion.
6bcc: a5 85 button_check_x lda XDIR
6bce: f0 1a beq button_check_y
6bd0: a5 f0 lda ySolid ;ignore x motion if we are standing on air
6bd2: f0 3b beq check_non_door_tile ;this tile will be handled as air
6bd4: a5 85 lda XDIR
6bd6: c5 95 cmp FACING
6bd8: f0 0d beq @jump
6bda: 85 95 sta FACING ;face the way we are moving
6bdc: 20 2e 6e jsr is_climbing
6bdf: b0 06 bcs @jump ;when climbing, allow jump in opposite direction
6be1: 20 d6 72 jsr stop_frame_ground
6be4: 4c c0 6c jmp finish_move
6be7: 4c 8a 6d @jump jmp try_jump
; Virtual button press, check Y motion. (Remember, keyboard input is translated
; into the joystick API, so SPACE -> JOY DOWN + BUTTON, which enters the menu
; below.)
6bea: a5 86 button_check_y lda YDIR
6bec: f0 14 beq check_door_tile ;not moving, check door etc.
6bee: 30 12 bmi check_door_tile ;moving up, check door etc.
6bf0: a5 e3 lda tileUnder ;moving down, check tile below us
6bf2: 20 7e 72 jsr tile_to_f0_f1_f2
6bf5: a5 f0 lda ySolid
6bf7: f0 09 beq check_door_tile ;not solid, I guess we can enter doors while falling?
6bf9: a9 00 lda #$00 ;solid ground, pressing button+down enters menu
6bfb: 85 87 sta TICKING
6bfd: a9 01 lda #$01
6bff: 85 9f sta enterMenu
6c01: 60 rts
; Check the tile we are in front of, and if it is a door tile (BA,BB,BC) then
; handle it as a door (1..3). We will only reach this when the (virtual) button
; is pressed.
6c02: a5 e0 check_door_tile lda tileFeet
6c04: c9 ba cmp #$ba
6c06: 90 07 bcc check_non_door_tile ;< $BA
6c08: c9 bd cmp #$bd
6c0a: b0 03 bcs check_non_door_tile ;> $BC
6c0c: 4c 97 71 jmp handle_door ;$E0 == BA..BC; becomes door pointer 1..3
; The button may or may not be pressed when we arrive here, but the selected
; tile ($F0..$F2) is always the one under our feet. If the button is pressed, we
; know we're not entering a door or the menu, as that was handled earlier.
6c0f: a5 f0 check_non_door_tile lda ySolid ;the tile under our feet, checked above
6c11: d0 16 bne check_on_ladder ;branch if on solid ground
6c13: e6 1a inc playerY ;only air below us, fall one tile
6c15: a9 04 lda #$04
6c17: 85 90 sta animDelay
6c19: e6 92 inc FALLCNT
6c1b: a5 92 lda FALLCNT
6c1d: c9 02 cmp #$02 ;have we fallen 2 tiles
6c1f: d0 05 bne @cont
6c21: a2 09 ldx #$09 ;yes, play this sound, which appears to make no sound
6c23: 20 03 b6 jsr SCRN_play_sound ;change to #$01 to beep after falling 2 tiles
6c26: 4c c4 6c @cont jmp finish_move2 ;(skips resetting FALLCNT to 0)
; Check if the player is centered on a ladder/vine, with a center ladder/vine
; tile both at their feet and just under them. This implies the player is on a
; ladder, since both tiles wouldn't be present if you are at the top or the
; bottom of a ladder. Since horizontal motion on a ladder is disallowed, skip
; XDIR handling if on the ladder.
6c29: a5 e0 check_on_ladder lda tileFeet
6c2b: c9 b5 cmp #$b5 ;ladder middle tile
6c2d: f0 04 beq @atfeet
6c2f: c9 b8 cmp #$b8 ;vine middle tile
6c31: d0 0d bne @check_horiz_motion
6c33: a5 e3 @atfeet lda tileUnder
6c35: c9 b5 cmp #$b5
6c37: f0 04 beq @on_ladder
6c39: c9 b8 cmp #$b8
6c3b: d0 03 bne @check_horiz_motion
6c3d: 4c 5e 6c @on_ladder jmp check_vert_motion ;on ladder; skip horiz motion check
; Check horizontal motion. If yes, and we are facing the opposite direction,
; face the new direction and cancel motion.
6c40: a5 85 @check_horiz_motion lda XDIR
6c42: f0 1a beq check_vert_motion ;no horiz motion; check vertical
6c44: c5 95 cmp FACING
6c46: f0 0c beq @facing_same_dir
6c48: 85 95 sta FACING ;moved opposite dir we are facing
6c4a: a9 00 lda #$00 ;update facing direction, and cancel movement
6c4c: 85 af sta XMOVFLG
6c4e: 20 d6 72 jsr stop_frame_ground
6c51: 4c c0 6c jmp finish_move
6c54: 38 @facing_same_dir sec ;toggle $97 between 0 and 2 (step frame offset)
6c55: a9 02 lda #$02 ;2-2=0, 2-0=2
6c57: e5 97 sbc $97
6c59: 85 97 sta $97
6c5b: 4c d6 6e jmp walk_crawl_cycle
; Check vertical motion. If moving up, and the tile at our feet is climbable,
; start climbing up; if it's not climbable then stand up from a crawl (if
; needed).
;
; (You can arrive here after already confirming we are on the ladder. The below
; checks are more general though, since you don't need to be centered on the
; ladder, and it may be above or below you.)
6c5e: 18 check_vert_motion clc
6c5f: a5 86 lda YDIR
6c61: f0 54 beq @no_vert_motion ;no vertical motion
6c63: 10 33 bpl @moving_down ;moving down
6c65: a5 e0 lda tileFeet ;we are moving up
6c67: 20 7e 72 jsr tile_to_f0_f1_f2
6c6a: a5 f2 lda climbable
6c6c: d0 0b bne @climb_up
6c6e: a5 9a lda crawlFlag
6c70: f0 4d beq @rts
6c72: a9 00 lda #$00
6c74: 85 9a sta crawlFlag
6c76: 4c bc 6e jmp crouch
; Climb; move player up 1 tile. Snap to the center of the ladder or vine.
6c79: a9 0a @climb_up lda #$0a
6c7b: 85 90 sta animDelay
6c7d: c6 1a dec playerY ;move up 1 tile
6c7f: a5 e0 lda tileFeet
6c81: c9 b4 @check_left_side cmp #$b4 ;left ladder tile
6c83: f0 04 beq @adjust_right
6c85: c9 b7 cmp #$b7 ;left vine tile
6c87: d0 02 bne @check_right_side
6c89: e6 19 @adjust_right inc playerX
6c8b: c9 b6 @check_right_side cmp #$b6 ;right ladder tile
6c8d: f0 04 beq @adjust_left
6c8f: c9 b9 cmp #$b9 ;right vine tile
6c91: d0 02 bne @cont
6c93: c6 19 @adjust_left dec playerX
6c95: 4c 4b 6f @cont jmp L6F4B
; If moving down and the tile below us is climbable, start climbing down; if
; it's not climbable, start crawling (if not already doing so).
6c98: a5 e3 @moving_down lda tileUnder
6c9a: 20 7e 72 jsr tile_to_f0_f1_f2
6c9d: a5 f2 lda climbable ;is tile at knee climbable?
6c9f: d0 0b bne @climb_down
6ca1: a5 9a lda crawlFlag ;no, try to crawl
6ca3: d0 1a bne @rts ;already crawling, return
6ca5: a9 01 lda #$01
6ca7: 85 9a sta crawlFlag ;now set crawl flag
6ca9: 4c bc 6e jmp crouch
; Climb down; move down one tile. Snap to the center of the ladder or vine.
6cac: a9 0a @climb_down lda #$0a ;signal climb start?
6cae: 85 90 sta animDelay
6cb0: e6 1a inc playerY
6cb2: a5 e3 lda tileUnder
6cb4: 4c 81 6c jmp @check_left_side
6cb7: a9 08 @no_vert_motion lda #$08
6cb9: 85 90 sta animDelay
6cbb: a9 00 lda #$00
6cbd: 85 99 sta runFlag
6cbf: 60 @rts rts
********************************************************************************
* Finishes up player movement for this frame. *
* *
* Stops any falling motion; assumes called when on solid ground. In one case *
* this is bypassed, when it is known the player is in the air. *
* *
* Checks for collision with water and sets a flag handled next frame. *
* *
* Checks for collision with brambles or walls. *
* *
* Checks if the player is offscreen (presumably by one tile) in either or both *
* of the X or Y axes. The player is moved 1 tile in the onscreen X direction *
* if needed (Y position is not modified), and zp $8f is set to *
* 01 -- was off top *
* 02 -- was off right *
* 03 -- was off bottom *
* 04 -- was off left *
* with the Y axis taking precedence. *
* *
* This is called via JMP, so we will continue in the caller's caller. *
********************************************************************************
tmp_offScreenFlag .var $81 {addr/1} ;whether the player was offscreen
6cc0: a9 00 finish_move lda #$00 ;stop falling, unless you enter this just below
6cc2: 85 92 sta FALLCNT
6cc4: 20 28 71 finish_move2 jsr check_brambles
6cc7: 20 4a 71 jsr check_walls ;(implicitly populates tileFeet)
; Check if we touched water. If so, stop time and set a flag which will teleport
; us home on the next frame. This subroutine continues but its offscreen
; computations are irrelevant; it could just return instead.
6cca: a5 e0 lda tileFeet
6ccc: c9 20 cmp #tile_water
6cce: d0 08 bne @left
6cd0: a9 01 lda #$01
6cd2: 85 80 sta touchedWater
6cd4: a9 00 lda #$00 ;halt timer in prep for teleport
6cd6: 85 87 sta TICKING
6cd8: a9 00 @left lda #$00
6cda: 85 81 sta tmp_offScreenFlag
6cdc: a5 19 lda playerX
6cde: 10 08 bpl @right
6ce0: a2 04 ldx #$04 ;player offscreen to left
6ce2: e6 19 inc playerX
6ce4: e6 81 inc tmp_offScreenFlag
6ce6: d0 0a bne @top ;(always)
6ce8: c9 28 @right cmp #$28
6cea: d0 06 bne @top
6cec: a2 02 ldx #$02 ;player offscreen to right
6cee: c6 19 dec playerX
6cf0: e6 81 inc tmp_offScreenFlag
6cf2: a5 1a @top lda playerY
6cf4: 10 04 bpl @bottom
6cf6: a2 01 ldx #$01 ;player offscreen to top
6cf8: d0 0c bne @offscreen ;(always)
6cfa: c9 13 @bottom cmp #$13
6cfc: 90 04 bcc @is_onscreen
6cfe: a2 03 ldx #$03 ;player offscreen to bottom
6d00: d0 04 bne @offscreen ;(always)
6d02: a5 81 @is_onscreen lda tmp_offScreenFlag ;was the player offscreen?
6d04: f0 07 beq @queue_erase ;no, queue up player erase
; X is guaranteed to be set to 01..04 when the offscreen flag is set.
6d06: 86 8f @offscreen stx nextRoomDir ;yes, record in which direction
6d08: a9 00 lda #$00 ;and halt timer
6d0a: 85 87 sta TICKING
6d0c: 60 rts
6d0d: a9 01 @queue_erase lda #$01
6d0f: 85 b2 sta erasePlayer
6d11: 60 rts
• Clear variables
6d12: a9 04 jumping lda #$04
6d14: 85 90 sta animDelay
6d16: a2 18 ldx #$18 ;left jump frame
6d18: a5 95 lda FACING
6d1a: 30 02 bmi @left
6d1c: a2 1c ldx #$1c ;right jump frame
6d1e: 20 b2 6e @left jsr set_anim_frame
6d21: a5 8d lda jumpFrame
6d23: c9 01 cmp #$01
6d25: f0 18 beq update_jump_pos ;start of jump, do not check x solidity
6d27: a5 e3 lda tileUnder ;check tile under our feet
6d29: 20 7e 72 jsr tile_to_f0_f1_f2
6d2c: a5 f1 lda xSolid
6d2e: f0 0f beq update_jump_pos
6d30: a9 00 lda #$00 ;tile is solid, so land on it (?)
6d32: 85 8c sta jumpFlag
6d34: 20 d6 72 jsr stop_frame_ground
6d37: a2 02 ldx #$02 ;footstep (landing sound)?
6d39: 20 03 b6 jsr SCRN_play_sound
6d3c: 4c 6b 6b jmp @update
; Update player position during jump. Player moves 1 tile horizontally during
; each of 4 jump frames. During each of frames 1 & 2, player moves up 1 tile;
; and down 1 tile during frames 3 & 4. If the player's stamina is 20 or more,
; they jump farther by adding an extra frame (frame 3 is repeated, but the
; player only moves horizontally).
6d3f: 18 update_jump_pos clc
6d40: a5 95 lda FACING
6d42: 65 19 adc playerX
6d44: 85 19 sta playerX
6d46: a6 8d ldx jumpFrame
6d48: e0 03 cpx #$03 ;third frame?
6d4a: d0 04 bne @yupdate
6d4c: c6 b4 dec longJump ;1 (stamina <20) or 2 (>=20), set at start of jump
6d4e: d0 1c bne @finish ;if 2, keep player at same Y, repeat frame 3 (with longJump 1)
6d50: bd 85 6d @yupdate lda jump_frame_yoffset-1,x ;up,up,down,down
6d53: 18 clc
6d54: 65 1a adc playerY
6d56: 85 1a sta playerY
6d58: e8 inx
6d59: 86 8d stx jumpFrame
6d5b: e0 04 cpx #$04 ;was this the 3rd or 4th frame?
6d5d: b0 10 bcs land_player
6d5f: a6 8d @chk_last_frame ldx jumpFrame
6d61: e0 05 cpx #$05
6d63: d0 07 bne @finish
6d65: a9 00 lda #$00 ;last jump frame, always finish jump now
6d67: 85 8c sta jumpFlag
6d69: 20 d6 72 jsr stop_frame_ground
6d6c: 4c c0 6c @finish jmp finish_move
6d6f: a5 95 land_player lda FACING
6d71: 10 05 bpl @right
6d73: a5 e4 lda tileUnderLeft
6d75: 4c 7a 6d jmp @check_ground
6d78: a5 e5 @right lda tileUnderRight
6d7a: 20 7e 72 @check_ground jsr tile_to_f0_f1_f2
6d7d: a5 f1 lda xSolid
6d7f: f0 de beq @chk_last_frame
6d81: c6 1a dec playerY
6d83: 4c 5f 6d jmp @chk_last_frame
6d86: ff jump_frame_yoffset .dd1 $ff ;jump frame 1..4 y offset
6d87: ff .dd1 $ff ;(move up 2, then down 2)
6d88: 01 .dd1 $01
6d89: 01 .dd1 $01
; Underground, in the the bottom 4 map rows (positions $0180-$01FF), you cannot
; jump while climbing. This is probably an easy way to handle most ladders being
; surrounded by solid rock; the few that are not, you don't notice this.
6d8a: a5 1c try_jump lda MAPHALF
6d8c: f0 0c beq jump
6d8e: a5 1b lda MAPPOS
6d90: c9 80 cmp #$80
6d92: 90 06 bcc jump
6d94: 20 2e 6e jsr is_climbing
6d97: 90 01 bcc jump
6d99: 60 rts ;maphalf=$1,mappos>=$80,climbing
6d9a: a9 06 jump lda #$06
6d9c: 85 90 sta animDelay
6d9e: a9 01 lda #$01
6da0: 85 8c sta jumpFlag
6da2: 85 8d sta jumpFrame
6da4: 85 99 sta runFlag
6da6: a9 00 lda #$00
6da8: 85 9a sta crawlFlag
6daa: a2 16 ldx #$16 ;left crouch frame (to start the jump)
6dac: a5 95 lda FACING
6dae: 30 02 bmi @set_frame
6db0: a2 1a ldx #$1a ;right crouch frame
6db2: 86 a3 @set_frame stx animFrame
6db4: e8 inx
6db5: 86 a4 stx animFrame_unused
6db7: a2 06 ldx #$06
6db9: 20 03 b6 jsr SCRN_play_sound
6dbc: a2 05 ldx #$05
6dbe: 20 a2 71 jsr handle_food_rest
6dc1: a2 02 ldx #$02
6dc3: a5 26 lda levelStamina
6dc5: c9 14 cmp #$14
6dc7: b0 01 bcs @long
6dc9: ca dex
6dca: 86 b4 @long stx longJump ;1 if stamina level < 20, 2 if >= 20
6dcc: 4c c0 6c jmp finish_move
; Handle frame of bonking head. Bonk frames 1..8 alternate frames $1E and $20
; (rubbing head). Frame 9 is a crouch (getting up). Frame 10 stands up and
; finishes.
6dcf: a5 93 bonking lda bonkFrame
6dd1: c9 02 cmp #$02
6dd3: d0 05 bne @nosound
6dd5: a2 07 ldx #$07 ;Play bonk sound during frame 2
6dd7: 20 03 b6 jsr SCRN_play_sound
6dda: e6 93 @nosound inc bonkFrame
6ddc: a5 93 lda bonkFrame
6dde: c9 0a cmp #$0a ;in frame 10, start getting up
6de0: f0 1f beq @get_up
6de2: c9 0b cmp #$0b
6de4: f0 0d beq @end_bonk
6de6: a5 a1 lda bonkAlt ;alternate frames (why not just AND $93 with #$01)
6de8: 49 01 eor #$01
6dea: 85 a1 sta bonkAlt
6dec: a8 tay
6ded: be 0c 6e ldx bonk_frame,y ;frame 0 ($1e) or 1 ($20)
6df0: 4c b2 6e jmp set_anim_frame
6df3: a9 00 @end_bonk lda #$00
6df5: 85 93 sta bonkFrame
6df7: a9 08 lda #$08
6df9: 85 90 sta animDelay
6dfb: 20 d6 72 jsr stop_frame_ground
6dfe: 4c 06 60 jmp GAME2_cleartext
6e01: a2 16 @get_up ldx #$16 ;set left or right crouch frame to arise
6e03: a5 95 lda FACING
6e05: 30 02 bmi @ret
6e07: a2 1a ldx #$1a
6e09: 4c b2 6e @ret jmp set_anim_frame
6e0c: 1e bonk_frame .dd1 $1e ;alternate bonk frames
6e0d: 20 .dd1 $20
6e0e: a9 01 fell_6_or_more lda #$01
6e10: 85 93 sta bonkFrame
6e12: a2 1e ldx #$1e ;bonk start frame
6e14: 20 b2 6e jsr set_anim_frame
6e17: a9 00 lda #$00 ;not falling any more!
6e19: 85 92 sta FALLCNT
6e1b: 85 a0 sta $a0
6e1d: 85 af sta XMOVFLG
6e1f: 20 7d 71 jsr reset_after_hurt
6e22: a9 0f lda #$0f
6e24: 85 90 sta animDelay
6e26: a2 40 ldx #$40
6e28: 20 a2 71 jsr handle_food_rest
6e2b: 4c f2 71 jmp maybe_tear_shuba ;and return to caller
; Returns bool in carry. Returns true (set) if game timer is running AND $a3 is
; between $10 and $15, implying player is climbing.
6e2e: a5 87 is_climbing lda TICKING
6e30: f0 0c beq @clc ;game paused; clear carry
6e32: a5 a3 lda animFrame
6e34: c9 10 cmp #$10
6e36: 90 06 bcc @clc ;$a3 < $10 or
6e38: c9 16 cmp #$16 ;$a3 > $15; clear carry
6e3a: b0 02 bcs @clc
6e3c: 38 sec
6e3d: 60 rts
6e3e: 18 @clc clc
6e3f: 60 rts
; Check if we have a shuba in inventory. Reached when the button is pressed and
; we have falled 2 or more tiles.
6e40: a2 13 check_has_shuba ldx #$13 ;check all shuba slots
6e42: bd 58 b5 @loop lda inv_shuba,x
6e45: 2c bd 1d bit GAME1_BITTAB5
6e48: d0 06 bne @has_shuba
6e4a: ca dex
6e4b: 10 f5 bpl @loop
6e4d: 4c 0f 6c jmp check_non_door_tile ;no shuba, return to normal processing
; If we did have a shuba, stop falling (and crawling, if we crawled off a ledge)
; and fly!
6e50: a9 01 @has_shuba lda #$01
6e52: 85 94 sta flyFlag ;whee!
6e54: 20 aa 6e jsr L6EAA
6e57: a9 00 lda #$00
6e59: 85 92 sta FALLCNT
6e5b: 85 9a sta crawlFlag
6e5d: a9 08 lda #$08
6e5f: 85 90 sta animDelay
6e61: a2 08 ldx #$08
6e63: 20 03 b6 jsr SCRN_play_sound
6e66: a5 e0 flying lda tileFeet ;external entry, when already flying
6e68: 20 7e 72 jsr tile_to_f0_f1_f2
6e6b: a5 f1 lda xSolid
6e6d: f0 11 beq L6E80
6e6f: c6 1a dec playerY
6e71: a9 00 @land lda #$00
6e73: 85 94 sta flyFlag
6e75: 20 d6 72 jsr stop_frame_ground
6e78: a2 02 ldx #$02
6e7a: 20 03 b6 jsr SCRN_play_sound
6e7d: 4c c0 6c jmp finish_move
6e80: a5 e3 L6E80 lda tileUnder
6e82: 20 7e 72 jsr tile_to_f0_f1_f2
6e85: a5 f1 lda xSolid
6e87: d0 e8 bne @land
; We are clear of obstacles.
6e89: 20 c3 75 jsr get_ongoing_input
6e8c: a5 85 lda XDIR
6e8e: f0 0e beq L6E9E
; We pressed left or right, so if we are changing direction, face that way and
; play a sound.
6e90: c5 95 cmp FACING
6e92: f0 0a beq L6E9E
6e94: 85 95 sta FACING
6e96: 20 aa 6e jsr L6EAA
6e99: a2 0b ldx #$0b
6e9b: 20 03 b6 jsr SCRN_play_sound
6e9e: a5 95 L6E9E lda FACING
6ea0: 18 clc
6ea1: 65 19 adc playerX
6ea3: 85 19 sta playerX
6ea5: e6 1a inc playerY
6ea7: 4c c0 6c jmp finish_move
6eaa: a2 0c L6EAA ldx #$0c
6eac: a5 95 lda FACING
6eae: 30 02 bmi set_anim_frame
6eb0: a2 0e ldx #$0e
6eb2: 86 a3 set_anim_frame stx animFrame
6eb4: e8 inx
6eb5: 86 a4 stx animFrame_unused
6eb7: a9 01 lda #$01
6eb9: 85 b2 sta erasePlayer
6ebb: 60 rts
; Crouch. Whether we are about to stand or about to crawl in the next frame is
; encoded in crawlFlag.
6ebc: a9 01 crouch lda #$01
6ebe: 85 9b sta crouchFlag ;writes to $9b are contained here
6ec0: a9 05 lda #$05
6ec2: 85 90 sta animDelay
6ec4: a2 16 ldx #$16 ;crouch left
6ec6: a4 95 ldy FACING
6ec8: 30 02 bmi @left
6eca: a2 1a ldx #$1a ;crouch right
6ecc: 4c b2 6e @left jmp set_anim_frame
; Called from main tick loop when crouching. Resets crouchFlag and sets the
; player animation frame to stand or crawl. crawlFlag will be set along with
; crouchFlag when crawling, effectively queueing a stand or crawl.
6ecf: a9 00 uncrouch lda #$00
6ed1: 85 9b sta crouchFlag
6ed3: 4c d6 72 jmp stop_frame_ground
********************************************************************************
* This appears to handle walk/run/crawl cycle. Sets the animation delay (hold *
* time for current player animation frame) appropriately for the current *
* action. Crawling is slow, walking is medium and running is fast. Each is 4 *
* frames long, with frames 0 and 2 being identical (standing still) and frames *
* 1 and 3 being left and right steps. *
* *
* $A3 animation frames: *
* Left walk animation: $00, $02, $00, $04 *
* Right walk animation: $06, $08, $06, $0A *
* Left glide: $0C *
* Right glide: $0E *
* Climb: $10, $12 *
* Unknown (unused?): $14 *
* Left crouch: $16 *
* Left jump: $18 *
* Right crouch: $1A (between standing and crawling/bonk, or start of jump) *
* Right jump: $1C *
* Bonk: $1E, $20, $1E, $20, $1E, $20 *
* Left crawl animation: $22, $24, $22, $26 *
* Right crawl animation: $28, $2A, $28, $2C *
* Resting: $2E *
********************************************************************************
6ed6: a6 96 walk_crawl_cycle ldx takingStep ;0 or 1, alternating frames; basically, taking a step
6ed8: bd 3f 6f lda next_step_value,x
6edb: 85 96 sta takingStep
6edd: a5 9a lda crawlFlag
6edf: f0 0b beq @not_crawling
6ee1: bd 45 6f lda crawling_delay,x ;crawling
6ee4: 85 90 sta animDelay
6ee6: bd 49 6f lda crawl_frames,x
6ee9: 4c fb 6e jmp @facing
6eec: bd 41 6f @not_crawling lda walking_delay,x
6eef: a4 99 ldy runFlag
6ef1: f0 03 beq @walking
6ef3: bd 43 6f lda running_delay,x
6ef6: 85 90 @walking sta animDelay
6ef8: bd 47 6f lda walk_frames,x
6efb: a6 95 @facing ldx FACING
6efd: 30 03 bmi @left
6eff: 18 clc
6f00: 69 06 adc #$06 ;right facing frames are left facing + 6
6f02: a6 96 @left ldx takingStep
6f04: f0 03 beq @step
6f06: 18 clc
6f07: 65 97 adc $97 ;should add 2 only on right step
6f09: 85 a3 @step sta animFrame ;or maybe no step
6f0b: 85 a4 sta animFrame_unused
6f0d: e6 a4 inc animFrame_unused ;maintain A4=A3+1
6f0f: a5 96 lda takingStep
6f11: d0 26 bne @nostep ;note meaning may be reversed
6f13: 18 clc
6f14: a5 95 lda FACING ;move the player
6f16: 65 19 adc playerX
6f18: 85 19 sta playerX
6f1a: a5 95 lda FACING ;and check left/right tile at feet, depending on facing
6f1c: 10 05 bpl @right ;note this is the tile we are now directly over
6f1e: a5 e1 lda tileFeetLeft
6f20: 4c 25 6f jmp @gettile
6f23: a5 e2 @right lda tileFeetRight
6f25: 20 7e 72 @gettile jsr tile_to_f0_f1_f2
6f28: a5 f1 lda xSolid
6f2a: f0 02 beq @solid
6f2c: c6 1a dec playerY ;tile was not solid, so fall through one tile
6f2e: a2 02 @solid ldx #$02 ;footstep sound 1
6f30: a5 97 lda $97
6f32: d0 02 bne @sound
6f34: a2 03 ldx #$03 ;footstep sound 2
6f36: 20 03 b6 @sound jsr SCRN_play_sound
6f39: 20 d1 71 @nostep jsr check_cave_door?
6f3c: 4c c0 6c jmp finish_move
6f3f: 01 next_step_value .dd1 $01
6f40: 00 .dd1 $00
6f41: 06 walking_delay .dd1 $06
6f42: 04 .dd1 $04
6f43: 03 running_delay .dd1 $03 ;not crawling nor walking, unsure
6f44: 02 .dd1 $02
6f45: 08 crawling_delay .dd1 $08
6f46: 08 .dd1 $08
6f47: 02 walk_frames .dd1 $02
6f48: 00 .dd1 $00
6f49: 24 crawl_frames .dd1 $24
6f4a: 22 .dd1 $22
6f4b: a9 00 L6F4B lda #$00
6f4d: 85 99 sta runFlag
6f4f: 85 9a sta crawlFlag
6f51: a5 1a lda playerY
6f53: 30 4f bmi L6FA4
6f55: f0 30 beq L6F87
6f57: c9 13 cmp #$13
6f59: f0 49 beq L6FA4
6f5b: a5 e6 lda tileKnee
6f5d: a6 86 ldx YDIR
6f5f: 30 02 bmi L6F63
6f61: a5 e3 lda tileUnder
6f63: 20 7e 72 L6F63 jsr tile_to_f0_f1_f2
6f66: a5 f2 lda climbable
6f68: d0 06 bne L6F70
6f6a: 20 bc 6e jsr crouch
6f6d: 4c c0 6c jmp finish_move
6f70: a5 e7 L6F70 lda tileArm
6f72: a6 86 ldx YDIR
6f74: 30 02 bmi L6F78
6f76: a5 e0 lda tileFeet
6f78: 20 7e 72 L6F78 jsr tile_to_f0_f1_f2
6f7b: a5 f2 lda climbable
6f7d: d0 08 bne L6F87
6f7f: a2 14 ldx #$14
6f81: 20 b2 6e jsr set_anim_frame
6f84: 4c c0 6c jmp finish_move
6f87: a5 98 L6F87 lda $98
6f89: 49 01 eor #$01
6f8b: 85 98 sta $98
6f8d: a8 tay
6f8e: be a7 6f ldx L6FA7,y
6f91: 20 b2 6e jsr set_anim_frame
6f94: a2 04 ldx #$04
6f96: a5 86 lda YDIR
6f98: 30 02 bmi L6F9C
6f9a: a2 05 ldx #$05
6f9c: 20 03 b6 L6F9C jsr SCRN_play_sound
6f9f: a2 01 ldx #$01
6fa1: 20 a2 71 jsr handle_food_rest
6fa4: 4c c0 6c L6FA4 jmp finish_move
6fa7: 10 L6FA7 .dd1 $10
6fa8: 12 .dd1 $12
6fa9: a5 6b handle_npc? lda zp6b_npcHere
6fab: d0 01 bne L6FAE
6fad: 60 rts
6fae: e6 53 L6FAE inc $53
6fb0: a5 53 lda $53
6fb2: c5 54 cmp $54
6fb4: f0 01 beq L6FB7
6fb6: 60 rts
6fb7: a9 00 L6FB7 lda #$00
6fb9: 85 53 sta $53
6fbb: a5 6c lda npcX
6fbd: 18 clc
6fbe: 65 6f adc npcFacing
6fc0: aa tax
6fc1: a4 6d ldy npcY
6fc3: 20 60 72 jsr get_tile_at_xy
6fc6: 85 a7 sta $a7
6fc8: a6 6c ldx npcX
6fca: a4 6d ldy npcY
6fcc: c8 iny
6fcd: 20 60 72 jsr get_tile_at_xy
6fd0: 85 a8 sta $a8
6fd2: a5 50 lda $50
6fd4: f0 03 beq L6FD9
6fd6: 4c 9f 70 jmp L709F
6fd9: a5 a8 L6FD9 lda $a8
6fdb: 20 7e 72 jsr tile_to_f0_f1_f2
6fde: a5 f0 lda ySolid
6fe0: d0 0b bne L6FED
6fe2: e6 6d inc npcY
6fe4: a9 04 lda #$04
6fe6: 85 54 sta $54
6fe8: a9 01 lda #$01
6fea: 85 b3 sta $b3
6fec: 60 rts
6fed: a5 6a L6FED lda $6a
6fef: c9 08 cmp #$08
6ff1: f0 32 beq L7025
6ff3: c9 09 cmp #$09
6ff5: f0 2e beq L7025
6ff7: ad f2 02 lda RWTSBUF_npctype
6ffa: 29 f0 and #$f0
6ffc: c9 e0 cmp #$e0
6ffe: d0 03 bne L7003
7000: 4c f5 70 jmp L70F5
7003: a5 6c L7003 lda npcX
7005: 18 clc
7006: 65 6f adc npcFacing
7008: c5 19 cmp playerX
700a: f0 07 beq L7013
700c: 18 clc
700d: 65 6f adc npcFacing
700f: c5 19 cmp playerX
7011: d0 39 bne L704C
7013: a6 6d L7013 ldx npcY
7015: e4 1a cpx playerY
7017: f0 0b beq L7024
7019: e8 inx
701a: e4 1a cpx playerY
701c: f0 06 beq L7024
701e: ca dex
701f: ca dex
7020: e4 1a cpx playerY
7022: d0 28 bne L704C
7024: 60 L7024 rts
7025: a5 93 L7025 lda bonkFrame
7027: d0 23 bne L704C
7029: a6 6d ldx npcY
702b: e4 1a cpx playerY
702d: f0 05 beq L7034
702f: ca dex
7030: e4 1a cpx playerY
7032: d0 18 bne L704C
7034: a5 6c L7034 lda npcX
7036: c5 19 cmp playerX
7038: f0 0e beq L7048
703a: 18 clc
703b: 65 6f adc npcFacing
703d: c5 19 cmp playerX
703f: f0 07 beq L7048
7041: 18 clc
7042: 65 6f adc npcFacing
7044: c5 19 cmp playerX
7046: d0 04 bne L704C
NOTE: Setting fallcnt to $0A is observed to happen when you bump your head.
7048: a9 0a L7048 lda #$0a
704a: 85 92 sta FALLCNT
704c: a5 52 L704C lda $52
704e: d0 28 bne L7078
7050: a5 6c lda npcX
7052: cd e6 02 cmp RWTSBUF+230
7055: f0 05 beq L705C
7057: cd e7 02 cmp RWTSBUF+231
705a: d0 1c bne L7078
705c: a9 00 L705C lda #$00
705e: 38 sec
705f: e5 6f sbc npcFacing
7061: 85 6f sta npcFacing
7063: 20 62 75 jsr L7562
7066: a9 01 lda #$01
7068: 85 b3 sta $b3
706a: a6 6e ldx zp6e
706c: bd 76 70 lda L7076,x
706f: 85 54 sta $54
7071: a9 01 lda #$01
7073: 85 52 sta $52
7075: 60 rts
7076: 0c L7076 .dd1 $0c
7077: 08 .dd1 $08
7078: 20 21 60 L7078 jsr GAME2_read_0900
707b: 29 07 and #$07 ;check lower 3 bits
707d: d0 12 bne L7091
707f: a6 6a ldx $6a
7081: e0 08 cpx #$08
7083: f0 0b beq @rts
7085: e0 09 cpx #$09
7087: f0 07 beq @rts
7089: 20 21 60 jsr GAME2_read_0900
708c: 29 7f and #$7f
708e: 85 54 sta $54
7090: 60 @rts rts
7091: a5 52 L7091 lda $52
7093: d0 0a bne L709F
7095: 20 21 60 jsr GAME2_read_0900
7098: 29 0f and #$0f
709a: d0 03 bne L709F
709c: 4c 5c 70 jmp L705C
709f: a9 00 L709F lda #$00
70a1: 85 52 sta $52
70a3: a5 50 lda $50
70a5: 49 01 eor #$01
70a7: 85 50 sta $50
70a9: a8 tay
70aa: b9 ef 70 lda L70EF,y
70ad: a6 6e ldx zp6e
70af: f0 03 beq L70B4
70b1: b9 f1 70 lda L70F1,y
70b4: 85 54 L70B4 sta $54
70b6: b9 f3 70 lda L70F3,y
70b9: a6 6f ldx npcFacing
70bb: 30 03 bmi L70C0
70bd: 18 clc
70be: 69 06 adc #$06
70c0: a6 50 L70C0 ldx $50
70c2: f0 0c beq L70D0
70c4: 18 clc
70c5: 65 97 adc $97
70c7: 48 pha
70c8: a9 02 lda #$02
70ca: 38 sec
70cb: e5 51 sbc $51
70cd: 85 51 sta $51
70cf: 68 pla
70d0: aa L70D0 tax
70d1: 20 6d 75 jsr L756D
70d4: a5 50 lda $50
70d6: d0 12 bne L70EA
70d8: 18 clc
70d9: a5 6c lda npcX
70db: 65 6f adc npcFacing ;move one tile in direction they are facing
70dd: 85 6c sta npcX
70df: a5 a7 lda $a7
70e1: 20 7e 72 jsr tile_to_f0_f1_f2
70e4: a5 f1 lda xSolid
70e6: f0 02 beq L70EA
70e8: c6 6d dec npcY
70ea: a9 01 L70EA lda #$01
70ec: 85 b3 sta $b3
70ee: 60 rts
70ef: 08 L70EF .dd1 $08
70f0: 0c .dd1 $0c
70f1: 06 L70F1 .dd1 $06
70f2: 0a .dd1 $0a
70f3: 00 L70F3 .dd1 $00
70f4: 02 .dd1 $02
NOTE: Might control NPC behavior (stopping) near player.
70f5: a6 6c L70F5 ldx npcX
70f7: e4 19 cpx playerX
70f9: f0 10 beq L710B
70fb: e8 inx
70fc: e4 19 cpx playerX
70fe: f0 0b beq L710B
7100: ca dex
7101: ca dex
7102: e4 19 cpx playerX
7104: f0 05 beq L710B
7106: ca dex
7107: e4 19 cpx playerX
7109: d0 1a bne L7125
710b: a6 6d L710B ldx npcY
710d: e4 1a cpx playerY
710f: f0 0b beq L711C
7111: e8 inx
7112: e4 1a cpx playerY
7114: f0 06 beq L711C
7116: ca dex
7117: ca dex
7118: e4 1a cpx playerY
711a: d0 09 bne L7125
711c: ad f2 02 L711C lda RWTSBUF_npctype
711f: 85 34 sta temp34_npctype
7121: a9 00 lda #$00
7123: 85 87 sta TICKING
7125: 4c 4c 70 L7125 jmp L704C
; Checks and handles collision with brambles at foot level. Ignored when flying.
7128: 20 2a 72 check_brambles jsr get_adjacent_tiles
712b: a5 e0 lda tileFeet
712d: c9 1c cmp #tile_brambles
712f: f0 01 beq @check_brambles
7131: 60 @rts rts
7132: a5 92 @check_brambles lda FALLCNT
7134: c9 02 cmp #$02
7136: b0 f9 bcs @rts
7138: a5 94 lda flyFlag ;ignore brambles if flying. only contact on ground
713a: d0 f5 bne @rts
713c: a5 9c lda playerXold
713e: 85 19 sta playerX
7140: a5 9d lda playerYold
7142: 85 1a sta playerY
7144: 20 7d 71 jsr reset_after_hurt
7147: 4c 72 71 jmp @ouch
; Checks and handles collision with wall tiles (locked gate, house wall) at foot
; and shoulder level.
714a: a5 e0 check_walls lda tileFeet
714c: 20 8a 71 jsr @is_collision_tile
714f: f0 0c beq @collide
7151: a5 9a lda crawlFlag
7153: f0 01 beq @chk_collide_shoulder ;if crawling, don't test collision at shoulder height
7155: 60 @rts rts
7156: a5 e8 @chk_collide_shoulder lda tileShoulder
7158: 20 8a 71 jsr @is_collision_tile
715b: d0 f8 bne @rts
715d: a5 9c @collide lda playerXold
715f: 85 19 sta playerX
7161: a5 9d lda playerYold
7163: 85 1a sta playerY
7165: a9 00 lda #$00
7167: 85 8c sta jumpFlag
7169: 85 94 sta flyFlag
716b: 20 d6 72 jsr stop_frame_ground
716e: a9 01 lda #$01
7170: 85 a0 sta $a0
7172: a9 0a @ouch lda #$0a ;full stop, max fall, get hurt
7174: 85 92 sta FALLCNT
7176: a9 00 lda #$00
7178: 85 af sta XMOVFLG
717a: 85 b0 sta YMOVFLG
717c: 60 rts
717d: a9 00 reset_after_hurt lda #$00
717f: 85 8c sta jumpFlag
7181: 85 94 sta flyFlag
7183: 85 96 sta takingStep
7185: 85 99 sta runFlag
7187: 85 9a sta crawlFlag
7189: 60 rts
; Sets Z flag if tile in A is $07,$08 or $52. These are tiles that cause you to
; get hurt when you contact them.
718a: c9 07 @is_collision_tile cmp #$07 ;unknown; probably a wall
718c: f0 08 beq @rts
718e: c9 08 cmp #$08 ;a locked gate (Temple Grund entrance)
7190: f0 04 beq @rts ; or impassable wall (hostage house)
7192: c9 52 cmp #$52 ;a checkerboard pattern (internal house wall)
7194: f0 00 beq @rts
7196: 60 @rts rts
; Translate BA..BC (the 3 door tiles, in A) to a door slot number (1..3) and
; store it in doorTransit.
7197: 38 handle_door sec ;A is BA..BC on entry (the door tile)
7198: e9 b9 sbc #$b9 ;subtract B9
719a: 85 9e sta doorTransit ;result is 1..3
719c: a9 00 lda #$00 ;pause during transit
719e: 85 87 sta TICKING
71a0: a2 0a ldx #$0a ;use 10 food during a door transit
; (Multiple entry.) X is the amount to decrease food/rest by ($0A, $01, ...).
; Subtract this from the food/rest timer, unless we are in the Neshom realm,
; where time does not pass.
;
; If the food/rest timer falls below zero, decrease food and rest by 1 each. The
; timer ranges from 00..FF so no post-adjustment is needed.
71a2: a5 35 handle_food_rest lda doorNeshom ;in neshom's house or realm?
71a4: d0 2a bne @rts ;yep, return; never starve
71a6: 86 b7 stx tempB7 ;temp used only for subtracting X from A
71a8: a5 b8 lda foodRestTimer
71aa: 38 sec
71ab: e5 b7 sbc tempB7
71ad: 85 b8 sta foodRestTimer
71af: 90 01 bcc @dec_food
71b1: 60 rts
71b2: c6 24 @dec_food dec levelFood
71b4: 10 0c bpl @dec_rest
71b6: e6 24 inc levelFood
71b8: e6 24 inc levelFood
71ba: a9 01 lda #STARVED_food ;starved of food
71bc: 85 3c sta STARVED
71be: a9 00 lda #$00 ;pause
71c0: 85 87 sta TICKING
71c2: c6 25 @dec_rest dec levelRest
71c4: 10 0a bpl @rts
71c6: e6 25 inc levelRest
71c8: a9 02 lda #STARVED_rest ;starved of rest
71ca: 85 3c sta STARVED
71cc: a9 00 lda #$00 ;pause
71ce: 85 87 sta TICKING
71d0: 60 @rts rts
NOTE: Suspect this is checking if we are in front of a certain type of door in
the caves, and if so, sets the flag for the spirit bell to ring.
71d1: a5 e0 check_cave_door? lda tileFeet
71d3: c9 bb cmp #$bb ;a door tile
71d5: d0 1a bne @rts
71d7: a5 1c lda MAPHALF
71d9: f0 16 beq @rts
71db: a5 1b lda MAPPOS
71dd: c9 80 cmp #$80
71df: 90 10 bcc @rts
71e1: ad 00 b5 lda itemState ;might be checking spirit bell in inventory
71e4: 2c bd 1d bit GAME1_BITTAB5
71e7: f0 08 beq @rts
71e9: a9 00 lda #$00
71eb: 85 87 sta TICKING
71ed: a9 01 lda #$01
71ef: 85 bc sta zpBC_bellrings ;spirit bell rings?
71f1: 60 @rts rts
71f2: 20 21 60 maybe_tear_shuba jsr GAME2_read_0900 ;pseudo-randomness?
71f5: c9 f0 cmp #$f0 ;essentially, a 1 in 16 chance to tear
71f7: 90 0d bcc @rts
71f9: a2 13 ldx #19 ;20 shuba inventory slots
71fb: bd 58 b5 @loop lda inv_shuba,x
71fe: 2c bd 1d bit GAME1_BITTAB5 ;check if slot is occupied by a shuba
7201: d0 04 bne @shuba_has_torn
7203: ca dex
7204: 10 f5 bpl @loop
7206: 60 @rts rts
7207: a9 00 @shuba_has_torn lda #$00 ;clear inventory slot
7209: 9d 58 b5 sta inv_shuba,x
720c: a0 07 ldy #$07
720e: 20 12 77 jsr GAME2_lose_weight
7211: 20 0c 60 jsr GAME2_PRNTSTR
7214: 01 .dd1 $01
7215: d9 cf d5 d2+ .str ↑“YOUR SHUBA HAS TORN” ;ow
7228: ff .dd1 $ff
7229: 60 rts
; Populates $E0..EA with tiles near the player's feet. See notes at @xoffset.
722a: a9 0a get_adjacent_tiles lda #$0a
722c: 85 82 sta temp82
722e: a6 82 @loop ldx temp82
7230: a5 1a lda playerY
7232: 18 clc
7233: 7d 55 72 adc @yoffset,x
7236: a8 tay
7237: a5 19 lda playerX
7239: 18 clc
723a: 7d 4a 72 adc @xoffset,x
723d: aa tax
723e: 20 60 72 jsr get_tile_at_xy
7241: a6 82 ldx temp82
7243: 95 e0 sta tileFeet,x
7245: c6 82 dec temp82
7247: 10 e5 bpl @loop ;loop 11 times
7249: 60 rts
; the 3 tiles at the player's feet (center, left, right)
724a: 00 @xoffset .dd1 $00 ;E0: 0, 0
724b: ff .dd1 $ff ;E1: -1, 0
724c: 01 .dd1 $01 ;E2: 1, 0
; the 3 tiles under the player (center, left, right)
724d: 00 .dd1 $00 ;E3: 0, 1
724e: ff .dd1 $ff ;E4: -1, 1
724f: 01 .dd1 $01 ;E5: 1, 1
; the 3 tiles at knee (-1), arm (-2) and shoulder (-3) height
7250: 00 .dd1 $00 ;E6: 0,-1
7251: 00 .dd1 $00 ;E7: 0,-2
7252: 00 .dd1 $00 ;E8: 0,-3
; the 2 tiles (left, right) at -2 (arm level), which is the height of items on
; tables and shelves for taking
7253: ff .dd1 $ff ;E9: -1,-2
7254: 01 .dd1 $01 ;EA: 1,-2
7255: 00 @yoffset .dd1 $00
7256: 00 .dd1 $00
7257: 00 .dd1 $00
7258: 01 .dd1 $01
7259: 01 .dd1 $01
725a: 01 .dd1 $01
725b: ff .dd1 $ff
725c: fe .dd1 $fe
725d: fd .dd1 $fd
725e: fe .dd1 $fe
725f: fe .dd1 $fe
; Input: X=col, Y=line. Output: A=tile at X,Y. A=0 if X=-1, X=40, or Y<0.
7260: e0 ff get_tile_at_xy cpx #$ff
7262: f0 17 beq @tile0
7264: e0 28 cpx #$28
7266: f0 13 beq @tile0
7268: c0 00 cpy #$00
726a: 30 0f bmi @tile0
726c: b9 a0 1d lda GAME1_textlo,y
726f: 85 89 sta temp89 ;$89 {addr/2} is temp
7271: b9 80 1d lda GAME1_texthi,y
7274: 85 8a sta temp89+1
7276: 8a txa
7277: a8 tay
7278: b1 89 lda (temp89),y
727a: 60 rts
727b: a9 00 @tile0 lda #$00
727d: 60 rts
; Maps a tile in A to 3 output values in $F0, $F1, $F2.
;
; On return ($F0,$F1,$F2) is (0,0,0) for all A except:
; (1,1,0) when A = 01..06, 19..1b (bush), 75, df
; (1,0,1) when A = b4..b6 (ladder) and b7..b9 (vine)
; (1,1,0) when A = e0 and $9A != 0
;
; It's likely these denote permeability in different directions, with $F2=1 as
; climbable. The (1,1,0) tiles appear to be solid.
727e: 48 tile_to_f0_f1_f2 pha
727f: a2 02 ldx #$02 ;Store 0 in $F0..$F2
7281: a9 00 lda #$00
7283: 95 f0 @loop sta ySolid,x
7285: ca dex
7286: 10 fb bpl @loop
7288: 68 pla
7289: c9 00 cmp #$00 ;(0,0,0) -- $00
728b: f0 48 beq @rts
728d: c9 07 cmp #$07
728f: b0 06 bcs @p1
7291: e6 f0 inc ySolid ;(1,1,0) -- $01..06
7293: e6 f1 inc xSolid
7295: d0 3e bne @rts
7297: c9 19 @p1 cmp #$19 ;(0,0,0) -- $07..18
7299: 90 3a bcc @rts
729b: c9 1c cmp #$1c
729d: b0 06 bcs @p2
729f: e6 f0 inc ySolid ;(1,1,0) -- $19..1b
72a1: e6 f1 inc xSolid
72a3: d0 30 bne @rts ;always
72a5: c9 75 @p2 cmp #$75
72a7: d0 06 bne @p3
72a9: e6 f0 inc ySolid ;(1,1,0) -- $75
72ab: e6 f1 inc xSolid
72ad: d0 26 bne @rts
72af: c9 b4 @p3 cmp #$b4
72b1: 90 22 bcc @rts ;(0,0,0) -- $1c..74,76..b3
72b3: c9 ba cmp #$ba
72b5: b0 06 bcs @p4
72b7: e6 f0 inc ySolid ;(1,0,1) -- $b4..b9
72b9: e6 f2 inc climbable
72bb: d0 18 bne @rts
72bd: c9 e0 @p4 cmp #$e0
72bf: d0 0a bne @p5
72c1: a5 9a lda crawlFlag
72c3: f0 10 beq @rts ;(0,0,0) -- $e0 (when $9a == 0)
72c5: e6 f0 inc ySolid ;(1,1,0) -- $e0 (when $9a == 1)
72c7: e6 f1 inc xSolid
72c9: d0 0a bne @rts
72cb: c9 df @p5 cmp #$df
72cd: d0 06 bne @rts ;(0,0,0) -- $ba..$de,$e1..$ff
72cf: e6 f0 inc ySolid ;(1,1,0) -- $df
72d1: e6 f1 inc xSolid
72d3: d0 00 bne @rts
72d5: 60 @rts rts
; Sets animation frame to $00/$06 (crawling) or $22/$28 (standing), depending on
; facing direction. Often called in tandem with FACING being updated.
; Essentially, the initial animation frame when you are stopped on the ground.
72d6: a5 9a stop_frame_ground lda crawlFlag
72d8: d0 0a bne @crawling
72da: a2 00 ldx #$00
72dc: a5 95 lda FACING
72de: 30 0c bmi @cont
72e0: a2 06 ldx #$06
72e2: d0 08 bne @cont ;always
72e4: a2 22 @crawling ldx #$22
72e6: a5 95 lda FACING
72e8: 30 02 bmi @cont ;if facing left
72ea: a2 28 ldx #$28
72ec: 86 a3 @cont stx animFrame
72ee: e8 inx
72ef: 86 a4 stx animFrame_unused
72f1: a9 01 lda #$01
72f3: 85 b2 sta erasePlayer
72f5: 60 rts
72f6: 20 06 60 win_game jsr GAME2_cleartext
72f9: 20 0c 60 jsr GAME2_PRNTSTR
72fc: 01 .dd1 $01
72fd: c9 a0 c1 cd+ .str ↑“I AM RAAMO, THE SPIRIT GIFTED.”
731b: ff .dd1 $ff
731c: 20 0c 60 jsr GAME2_PRNTSTR
731f: 29 .dd1 $29
7320: d9 cf d5 a0+ .str ↑“YOU HAVE SAVED MY LIFE AND FULFILLED THE PROPHESY. THE QU”
+ “EST IS OVER AND GREEN-SKY IS SAVED.”
7383: ff .dd1 $ff
7384: a9 00 lda #$00
7386: 20 00 b6 jsr SCRN_play_melody
; This weird test (which is always 0 so never loops) only occurs after a melody
; is played, and only on win or lose. It might be a vestige of another platform,
; as it would enter an infinite loop unless there is an interrupt handler
; (music?) that updates this value.
7389: a5 83 @loop lda waitMelody
738b: d0 fc bne @loop
738d: a2 ff ldx #$ff
738f: 20 12 60 jsr GAME2_delayXtimes256
7392: 20 06 60 jsr GAME2_cleartext
7395: 20 0c 60 jsr GAME2_PRNTSTR
7398: 01 .dd1 $01
7399: d9 cf d5 a0+ .str ↑“YOU HAVE FINISHED THE QUEST IN DAYS. YOU ARE A”
73ca: ff .dd1 $ff
73cb: a6 22 ldx dayNum
73cd: a0 00 ldy #$00
73cf: 20 18 77 jsr GAME2_num_to_str
73d2: a9 20 lda #$20
73d4: 85 64 sta HTAB
73d6: a5 fc lda digits+3
73d8: 20 0f 60 jsr GAME2_printchar
73db: a9 21 lda #$21
73dd: 85 64 sta HTAB
73df: a5 fd lda digits+4
73e1: 20 0f 60 jsr GAME2_printchar
73e4: a5 22 lda dayNum
73e6: c9 1e cmp #30 ;>= 30 days, gifted quester
73e8: 90 17 bcc @highly_gifted
73ea: 20 0c 60 jsr GAME2_PRNTSTR
73ed: 33 .dd1 $33
73ee: c7 c9 c6 d4+ .str ↑“GIFTED QUESTER.”
73fd: ff .dd1 $ff
73fe: 4c 37 74 jmp @melody
7401: c9 0f @highly_gifted cmp #15 ;>= 15 days, highly gifted quester
7403: 90 1e bcc @master_quester
7405: 20 0c 60 jsr GAME2_PRNTSTR
7408: 33 .dd1 $33
7409: c8 c9 c7 c8+ .str ↑“HIGHLY GIFTED QUESTER.”
741f: ff .dd1 $ff
7420: 4c 37 74 jmp @melody
7423: 20 0c 60 @master_quester jsr GAME2_PRNTSTR ;< 15 days, master quester
7426: 33 .dd1 $33
7427: cd c1 d3 d4+ .str ↑“MASTER QUESTER.”
7436: ff .dd1 $ff
7437: a9 02 @melody lda #$02
7439: 20 00 b6 jsr SCRN_play_melody
743c: a5 83 @loop lda waitMelody ;again the weird loop that never loops
743e: d0 fc bne @loop
7440: 20 c3 75 @wait_for_input jsr get_ongoing_input
7443: f0 fb beq @wait_for_input
7445: a9 00 lda #$00
7447: 85 ba sta $ba
7449: 4c 0c 77 jmp GAME2_await_button_up
744c: 20 20 75 redraw_player jsr erase_old_player
744f: a5 19 draw_player lda playerX ;Save old player X,Y for later erase
7451: 85 9c sta playerXold
7453: a5 1a lda playerY
7455: 85 9d sta playerYold
; Bit 0 (odd/even) in $A3 is discarded. Bit 1 becomes the high bit in A, and is
; stored in $1d. Bits 7..2 are shifted to 5..0, and 32 added and stored in $1e.
7457: a5 a3 lda animFrame
7459: 4a lsr A
745a: 4a lsr A
745b: 85 82 sta temp82
745d: a9 00 lda #$00
745f: 6a ror A ;Bit 7 is carry (bit 1 from $A3); Bit 6-0 is 0
7460: 18 clc
7461: 69 00 adc #$00 ;cannot understand this. clc+adc #$00 should be nop
7463: 85 1d sta zp1d
7465: a5 82 lda temp82 ;$a3/4
7467: 69 20 adc #$20 ;carry should always be 0
7469: 85 1e sta zp1d+1
746b: a5 19 lda playerX
746d: 85 05 sta TXTCOL
746f: c6 05 dec TXTCOL
7471: a5 1a lda playerY ;playerY * 8 hires lines
7473: 0a L7473 asl A
7474: 0a asl A
7475: 0a asl A
7476: 38 sec
7477: e9 22 sbc #$22
7479: 85 06 sta TXTROW
747b: a9 ff lda #$ff
747d: 85 1f sta zp1f
747f: a0 00 ldy #$00
7481: a5 05 L7481 lda TXTCOL
7483: 85 8b sta temp8b
7485: a5 06 lda TXTROW
7487: 4a lsr A
7488: 4a lsr A
7489: 4a lsr A
748a: aa tax
748b: bd 40 1d lda GAME1_hireslo,x
748e: 85 0f sta $0f
7490: bd 60 1d lda GAME1_hireshi,x
7493: 85 10 sta $10
7495: a5 06 lda TXTROW
7497: 29 07 and #$07
7499: 0a asl A
749a: 0a asl A
749b: 18 clc
749c: 65 10 adc $10
749e: 18 clc
749f: 69 20 adc #$20
74a1: 85 10 sta $10
74a3: a5 05 lda TXTCOL
74a5: 10 0e bpl L74B5
74a7: a5 0f lda $0f
74a9: 38 sec
74aa: e9 01 sbc #$01
74ac: 85 0f sta $0f
74ae: b0 12 bcs L74C2
74b0: c6 10 dec $10
74b2: 4c c2 74 jmp L74C2
74b5: a5 0f L74B5 lda $0f
74b7: 18 clc
74b8: 65 05 adc TXTCOL
74ba: 85 0f sta $0f
74bc: a9 00 lda #$00
74be: 65 10 adc $10
74c0: 85 10 sta $10
74c2: a9 03 L74C2 lda #$03
74c4: 85 07 sta $07
74c6: a2 00 ldx #$00
74c8: a5 8b lda temp8b
74ca: 30 26 bmi L74F2
74cc: c9 28 cmp #$28
74ce: b0 22 bcs L74F2
74d0: a5 06 lda TXTROW
74d2: c9 a0 cmp #$a0
74d4: b0 1c bcs L74F2
74d6: b1 1d lda (zp1d),y
74d8: 4a lsr A
74d9: 4c ec 74 jmp L74EC
74dc: a5 8b @line lda temp8b
74de: 30 12 bmi L74F2
74e0: c9 28 cmp #$28
74e2: b0 0e bcs L74F2
74e4: a5 06 lda TXTROW
74e6: c9 a0 cmp #$a0
74e8: b0 08 bcs L74F2
74ea: b1 1d lda (zp1d),y
74ec: 29 7f L74EC and #$7f
74ee: 01 0f ora ($0f,x) ;OR with hires screen
74f0: 81 0f sta ($0f,x) ;note x=0; ora/sta ($0f)
74f2: c8 L74F2 iny ;next zp1d index
74f3: e6 8b inc temp8b
74f5: e6 0f inc $0f ;16-bit inc $0f ptr
74f7: d0 02 bne @no16
74f9: e6 10 inc $10
74fb: c6 07 @no16 dec $07
74fd: d0 dd bne @line ;loop 3 times total
74ff: e6 06 inc TXTROW
7501: 98 tya
7502: c9 3f cmp #$3f ;processed 64 yet?
7504: f0 03 beq L7509
7506: 4c 81 74 jmp L7481
; Increase $1d by 64 and continue. Do this twice.
7509: e6 1f L7509 inc zp1f ;zp1f starts at #$FF
750b: d0 12 bne @rts ;so this loops twice
750d: a9 40 lda #$40 ;16-bit add of 64 to $1d/$1e
750f: 18 clc
7510: 65 1d adc zp1d
7512: 85 1d sta zp1d
7514: a9 00 lda #$00
7516: 65 1e adc zp1d+1
7518: 85 1e sta zp1d+1
751a: a0 00 ldy #$00 ;reset zp1d index
751c: 4c 81 74 jmp L7481
751f: 60 @rts rts
; Redraw a 3x6 tile area at the old player position ($9c-1,$9d-5), copying tiles
; from the text screen. This erases the old player.
7520: a5 9c erase_old_player lda playerXold
7522: 85 05 sta TXTCOL
7524: c6 05 dec TXTCOL
7526: a5 9d lda playerYold
7528: 38 L7528 sec
7529: e9 05 sbc #$05 ;probably related to the 6 tiles printed
752b: 85 06 sta TXTROW
752d: a9 00 lda #$00
752f: a9 06 lda #$06
7531: 85 8b sta temp8b
7533: a5 06 @row lda TXTROW
7535: 30 24 bmi @nextrow ;skip to next row if row < 0
7537: c9 14 cmp #20
7539: b0 20 bcs @nextrow ;or if row > 19 (why not just exit)
753b: a5 05 lda TXTCOL
753d: 48 pha
753e: a9 03 lda #$03
7540: 85 82 sta temp82
7542: a6 05 @col ldx TXTCOL
7544: 30 0c bmi @nextcol
7546: e0 28 cpx #$28
7548: b0 08 bcs @nextcol
754a: a4 06 ldy TXTROW
754c: 20 60 72 jsr get_tile_at_xy
754f: 20 03 60 jsr GAME2_drawtile ;draw tile in A
7552: e6 05 @nextcol inc TXTCOL
7554: c6 82 dec temp82
7556: d0 ea bne @col ;3 times
7558: 68 pla
7559: 85 05 sta TXTCOL
755b: e6 06 @nextrow inc TXTROW
755d: c6 8b dec temp8b
755f: d0 d2 bne @row ;6 times
7561: 60 rts
7562: a2 00 L7562 ldx #$00
7564: a5 6f lda npcFacing
7566: 30 02 bmi L756A
7568: a2 06 ldx #$06
756a: 4c 6d 75 L756A jmp L756D
756d: 86 ad L756D stx $ad
756f: e8 inx
7570: 86 ae stx $ae
7572: 60 rts
7573: 20 a6 75 4c+ .junk 6 ;unused code
7579: a5 6b draw_npc? lda zp6b_npcHere
757b: d0 01 bne L757E
757d: 60 rts
757e: a6 ad L757E ldx $ad
7580: bd 9a 75 lda L759A,x
7583: 85 1d sta zp1d
7585: e8 inx
7586: bd 9a 75 lda L759A,x
7589: 85 1e sta zp1d+1
758b: a5 6c lda npcX
758d: 85 ab sta $ab
758f: 85 05 sta TXTCOL
7591: c6 05 dec TXTCOL
7593: a5 6d lda npcY
7595: 85 ac sta $ac
7597: 4c 73 74 jmp L7473
759a: 00 L759A .dd1 $00
759b: af .dd1 $af
759c: 80 .dd1 $80
759d: af .dd1 $af
759e: 00 .dd1 $00
759f: b0 .dd1 $b0
75a0: 80 .dd1 $80
75a1: b0 .dd1 $b0
75a2: 00 .dd1 $00
75a3: b1 .dd1 $b1
75a4: 80 .dd1 $80
75a5: b1 .dd1 $b1
75a6: a5 ab L75A6 lda $ab
75a8: 85 05 sta TXTCOL
75aa: c6 05 dec TXTCOL
75ac: a5 ac lda $ac
75ae: 4c 28 75 jmp L7528
NOTE: Wraps a call to input code at $6b09 ($75c3). It ensures any latched
keyboard motion is stopped, gets input, and ignores any returned button press if
we are moving upward (the keyboard handler adds a virtual button press for UP).
This is the exact behavior you'd want in a menu.
Returns 0 or 1 (button press status) in A.
75b1: a9 00 get_menu_input lda #$00 ;clear the kbd movement latches
75b3: 85 b0 sta YMOVFLG
75b5: 85 af sta XMOVFLG
75b7: 20 c3 75 jsr get_ongoing_input
75ba: a6 b0 ldx YMOVFLG
75bc: 10 02 bpl @ret ;branch if not moving up
75be: a9 00 lda #$00 ;or clear button press if we are moving up
; ORA #0 (AND #$FF, EOR #0) will make the N and Z flags reflect the value in A.
; This is used to ensure the Z flag still reflects A (return value from $75C3)
; after the LDX, so callers can BEQ/BNE.
75c0: 09 00 @ret ora #$00 ;update N and Z from A, even when LDA skipped
75c2: 60 rts
NOTE: Input code called via $6b09 vector or directly. Vector $6b29 ($75b1) also
calls this as its main action, but with a bit of wrapper code. This code
respects any latched keyboard movement.
This code behaves in 1 of 2 ways after its preamble. If DEMOFLG is 0, it handles
keyboard/joystick input. If 1, it calls $9600, which calls back into this
handler in non-demo mode and does a bunch of processing, then we update
XDIR/YDIR/MOVING/BUTTON based on its return value, just as if we were handling
input.
Amusingly, if you set $C4 to 0 while the sample quest or intro screen is
playing, you can take over.
75c3: a9 00 get_ongoing_input lda #$00 ;from $6b09 or
75c5: 85 85 sta XDIR
75c7: 85 86 sta YDIR
75c9: 85 a2 sta MOVING
75cb: 85 84 sta VIRTBTN
75cd: 20 2e 6e jsr is_climbing
75d0: b0 04 bcs L75D6
75d2: a9 00 lda #$00
75d4: 85 b0 sta YMOVFLG
75d6: a5 92 L75D6 lda FALLCNT
75d8: c9 01 cmp #$01
75da: 10 04 bpl @falling ;branch when falling, it seems
75dc: a5 94 lda flyFlag
75de: f0 04 beq L75E4
75e0: a9 00 @falling lda #$00 ;cancel X movement when falling
75e2: 85 af sta XMOVFLG
75e4: a5 c4 L75E4 lda DEMOFLG ;If not in demo mode,
75e6: f0 32 beq handle_kbd_or_joy ;handle kbd/joy input and return to caller
75e8: 20 00 96 jsr SCRN_demo_handler ;otherwise get demo movement for this frame in A
75eb: 2c bb 1d bit GAME1_BITTAB3 ;test bit 3 of A
75ee: d0 04 bne @test_left
75f0: e6 85 inc XDIR ;moving right
75f2: e6 a2 inc MOVING ;we moved
75f4: 2c ba 1d @test_left bit GAME1_BITTAB2 ;test bit 2 of A
75f7: d0 04 bne @test_down
75f9: c6 85 dec XDIR ;moving left
75fb: e6 a2 inc MOVING
75fd: 2c b9 1d @test_down bit GAME1_BITTAB1 ;test bit 1 of A
7600: d0 04 bne @test_up
7602: e6 86 inc YDIR
7604: e6 a2 inc MOVING
7606: 2c b8 1d @test_up bit GAME1_BITTAB0 ;test bit 0 of A
7609: d0 04 bne @test_button?
760b: c6 86 dec YDIR
760d: e6 a2 inc MOVING
760f: 2c bc 1d @test_button? bit GAME1_BITTAB4 ;test bit 4 of A -- !button
7612: d0 03 bne @ret00 ;set, return 0
7614: a9 01 lda #$01 ;clear, return 1
7616: 60 rts
7617: a9 00 @ret00 lda #$00
7619: 60 rts
761a: a5 b1 handle_kbd_or_joy lda JOYFLG
761c: f0 03 beq handle_ijkm_space
761e: 4c ac 76 jmp handle_joystick
********************************************************************************
* Handle cursor/character motion. Supports both IJKM and RDFC for up-left- *
* right-down, along with spacebar for execute/jump. The keyboard handler *
* translates its inputs into the equivalent joystick actions (horiz/vert *
* movement and button presses), and callers just handle joystick actions. It *
* keeps some extra state since keys don't need to be held down to move. *
* *
* $84 (VIRTBTN) is a temporary used only in this handler. It represents a *
* virtual joystick button press; this is returned in A to match the joystick *
* API. For example, pressing UP (I) will return a virtual button press to the *
* caller, because KBD UP enters a door, just like JOY BTN. As another example, *
* a double press of KBD LEFT/RIGHT will trigger a virtual button press because *
* this will switch to run mode, just like JOY BTN + LEFT/RIGHT. And KBD SPACE *
* simulates JOY BTN + DOWN, which brings up the action menu. *
* *
* $AF/$B0 are X/Y movement latches (-1, 0, +1), set on initial keypress and *
* maintained until you hit something, press another movement key, etc. *
* *
* On return, XDIR and YDIR and MOVING are set as their joystick equivalents, *
* along with A as the virtual button press. *
********************************************************************************
7621: 20 09 b6 handle_ijkm_space jsr SCRN_chkkey
7624: f0 70 beq @finish
7626: a5 02 lda LASTKEY
7628: c9 c6 cmp #‘F’ | $80
762a: f0 04 beq @right
762c: c9 cb cmp #‘K’ | $80
762e: d0 0d bne @chk_left
7630: e6 af @right inc XMOVFLG
7632: a5 af lda XMOVFLG
7634: c9 02 cmp #$02 ;was x motion previously 1?
7636: d0 19 bne @move_horiz ;no, move right
7638: c6 af dec XMOVFLG ;yes, double press; set back to 1
763a: 4c 4f 76 jmp @run ;and start running
763d: c9 c4 @chk_left cmp #‘D’ | $80
763f: f0 04 beq @left
7641: c9 ca cmp #‘J’ | $80
7643: d0 20 bne @chk_up
7645: c6 af @left dec XMOVFLG
7647: a5 af lda XMOVFLG
7649: c9 fe cmp #$fe ;was this previously -1?
764b: d0 04 bne @move_horiz ;nope, we've just started to move left
764d: e6 af inc XMOVFLG ;yes, double press; set back to -1
764f: e6 84 @run inc VIRTBTN ;...and press button (to run)
7651: a9 00 @move_horiz lda #$00
7653: 85 b0 sta YMOVFLG ;halt vertical motion
7655: 20 2e 6e jsr is_climbing
7658: b0 06 bcs L7660
765a: a5 92 lda FALLCNT ;might be, how many tiles we have fallen
765c: c9 03 cmp #$03 ;because we can't fly until we fall a bit
765e: 30 36 bmi @finish
; So far I can get here if we are falling and press right, or if we are on a
; ladder and press right. VIRTBTN appears to be zero on entry.
7660: e6 84 L7660 inc VIRTBTN
7662: 4c 96 76 jmp @finish
7665: c9 d2 @chk_up cmp #‘R’ | $80
7667: f0 04 beq @up
7669: c9 c9 cmp #‘I’ | $80
766b: d0 0a bne @chk_down
766d: a5 b0 @up lda YMOVFLG
766f: 30 21 bmi @haltx ;if already moving up, stop x motion and return
7671: e6 84 inc VIRTBTN ;otherwise, press button (as if to enter door)
7673: c6 b0 dec YMOVFLG ;and also start moving up
7675: 30 1b bmi @haltx
7677: c9 c3 @chk_down cmp #‘C’ | $80
7679: f0 04 beq @down
767b: c9 cd cmp #‘M’ | $80
767d: d0 0b bne @chk_space
767f: a5 b0 @down lda YMOVFLG
7681: c9 01 cmp #$01 ;were we already moving down?
7683: f0 0d beq @haltx ;yes, just stop x motion and return
7685: e6 b0 inc YMOVFLG ;no, start moving down
7687: 4c 92 76 jmp @haltx ;stop x motion (and return)
768a: c9 a0 @chk_space cmp #‘ ’ | $80
768c: d0 08 bne @finish
768e: e6 84 inc VIRTBTN ;SPACE is JOY BTN + JOY DOWN
7690: e6 86 inc YDIR ;which will bring up the menu
7692: a9 00 @haltx lda #$00 ;halt horizontal motion
7694: 85 af sta XMOVFLG
7696: a5 af @finish lda XMOVFLG
7698: f0 05 beq @no_x_motion
769a: 85 85 sta XDIR ;we are moving horizontally
769c: 4c a5 76 jmp @moving
769f: a5 b0 @no_x_motion lda YMOVFLG ;only check Y if no X motion, can't move diagonally
76a1: f0 06 beq @no_y_motion
76a3: 85 86 sta YDIR
76a5: a9 01 @moving lda #$01 ;effectively, MOVING <- XDIR|YDIR
76a7: 85 a2 sta MOVING
76a9: a5 84 @no_y_motion lda VIRTBTN ;return virtual joystick button press in A
76ab: 60 rts ;end of cursor/character keypress handler
; Joystick handling is less complicated than the keyboard. This subroutine
; updates XDIR (when horizontal joystick movement), YDIR (vertical movement) and
; MOVING (XDIR | YDIR).
;
; On return, accumulator is 0 for no button currently pressed, or 1 for pressed.
76ac: a2 04 handle_joystick ldx #$04
76ae: 20 12 60 jsr GAME2_delayXtimes256
76b1: a2 00 ldx #$00
76b3: 20 1e fb jsr MON_PREAD
76b6: 98 tya
76b7: a2 ff ldx #$ff
76b9: c9 40 cmp #$40
76bb: 90 08 bcc L76C5
76bd: a2 01 ldx #$01
76bf: c9 c0 cmp #$c0
76c1: b0 02 bcs L76C5
76c3: a2 00 ldx #$00
76c5: 86 85 L76C5 stx XDIR
76c7: a2 04 ldx #$04
76c9: 20 12 60 jsr GAME2_delayXtimes256
76cc: a2 01 ldx #$01
76ce: 20 1e fb jsr MON_PREAD
76d1: 98 tya
76d2: a0 ff ldy #$ff
76d4: c9 40 cmp #$40
76d6: 90 08 bcc L76E0
76d8: a0 01 ldy #$01
76da: c9 c0 cmp #$c0
76dc: b0 02 bcs L76E0
76de: a0 00 ldy #$00
76e0: 84 86 L76E0 sty YDIR
76e2: a5 86 lda YDIR ;moving if XDIR or YDIR is non-zero
76e4: 05 85 ora XDIR
76e6: f0 04 beq @nomove ;stationary, branch
76e8: a9 01 lda #$01 ;we are moving
76ea: 85 a2 sta MOVING
76ec: a2 04 @nomove ldx #$04
76ee: 20 12 60 jsr GAME2_delayXtimes256
76f1: a2 00 ldx #$00
76f3: ad 62 c0 lda BUTN1 ;treat either button equally
76f6: 0d 61 c0 ora BUTN0
76f9: 10 02 bpl L76FD
76fb: a2 01 ldx #$01
76fd: 8a L76FD txa ;return A=0 if no button press, 1 if press
76fe: 60 rts
76ff: 20 .dd1 $20
; Vectors! This section deals with menus and actions.
7700: 4c 27 77 GAME2_action_menu jmp action_menu
7703: 4c c0 7f GAME2_slot_to_item jmp slot_to_item ;input slot $00-fe (A), output item 0-14 (Y)
7706: 4c e3 7f GAME2_message_wait jmp message_wait ;wait for input after a message
7709: 4c 4b 84 L7709 jmp time_has_passed
770c: 4c f2 7f GAME2_await_button_up jmp await_button_up
770f: 4c a2 7e GAME2_print_item_desc jmp print_item_desc
7712: 4c 48 7e GAME2_lose_weight jmp lose_weight
7715: 4c dd 81 jmp L81DD
7718: 4c cc 84 GAME2_num_to_str jmp num_to_str
771b: 4c 61 84 GAME2_next_tick jmp next_tick
771e: 4c fd 79 GAME2_attacked jmp attacked
7721: 4c 90 7e GAME2_txtpos_to_addr jmp txtpos_to_addr
7724: 4c 51 7e jmp L7E51
7727: 20 2f 78 action_menu jsr display_actions
772a: a9 00 lda #$00
772c: 85 71 sta MENUCOL ;set top left of menu (0,0)
772e: 85 72 sta MENUROW
7730: 85 73 sta MENUCOL_NEXT ;next menucol/row, so we can unhighlight old row
7732: 85 74 sta MENUROW_NEXT ;these are really temp vars, only used here
7734: 85 9f sta enterMenu
7736: 20 f6 78 jsr highlight_menu_action
7739: 20 f2 7f action_menu_no_effect jsr await_button_up ;jmp here when no effect (RENEW in Neshom)
773c: 20 2a 6b @check_input jsr GAME2_menu_input ;get input
773f: f0 08 beq @check_moving ;no button, branch
7741: a2 01 ldx #$01 ;button pressed, boop
7743: 20 03 b6 jsr SCRN_play_sound
7746: 4c 92 77 jmp select_menu_item
tmpMoved .var $08 {addr/1} ;did we actually move menu pos?
7749: a5 a2 @check_moving lda MOVING ;no button, check direction
774b: f0 ef beq @check_input ;no input, loop
774d: a9 00 lda #$00
774f: 85 08 sta tmpMoved
7751: 18 clc
7752: a5 85 lda XDIR ;FF (left), 01 (right)
7754: f0 0c beq @check_ymove ;no attempt to move
7756: 65 73 adc MENUCOL_NEXT
7758: 30 08 bmi @check_ymove ;off left edge, don't move
775a: c9 05 cmp #$05 ;off the right edge?
775c: f0 04 beq @check_ymove ;yes, don't move
775e: 85 73 sta MENUCOL_NEXT ;no, set next column
7760: e6 08 inc tmpMoved ;and note that we moved
7762: 18 @check_ymove clc
7763: a5 86 lda YDIR ;FF (up), 01 (down)
7765: f0 0c beq @check_moved ;no attempt to move vertically
7767: 65 74 adc MENUROW_NEXT
7769: 30 08 bmi @check_moved ;off top edge, don't move
776b: c9 04 cmp #$04 ;off the bottom?
776d: f0 04 beq @check_moved ;yes, don't move
776f: 85 74 sta MENUROW_NEXT ;no, set next row
7771: e6 08 inc tmpMoved ;and note that we moved
7773: a5 08 @check_moved lda tmpMoved
7775: f0 c5 beq @check_input ;no movement, get more input
7777: 20 10 79 jsr unhighlight_menu_action ;unhighlight old menu item
777a: a5 73 lda MENUCOL_NEXT
777c: 85 71 sta MENUCOL ;update menu position
777e: a5 74 lda MENUROW_NEXT
7780: 85 72 sta MENUROW
7782: 20 f6 78 jsr highlight_menu_action ;and highlight new menu item
7785: a2 00 ldx #$00
7787: 20 03 b6 jsr SCRN_play_sound ;beep
778a: a2 60 ldx #$60
778c: 20 12 60 jsr GAME2_delayXtimes256 ;delay repeat
778f: 4c 3c 77 jmp @check_input ;get more input
7792: a5 71 select_menu_item lda MENUCOL ;col 0, row 0 (PAUSE)
7794: d0 18 bne menu_take
7796: a5 72 lda MENUROW
7798: d0 03 bne menu_speak
779a: 4c 06 60 jmp GAME2_cleartext
779d: c9 01 menu_speak cmp #$01 ;row 1
779f: d0 03 bne menu_pense
77a1: 4c 0c 9c jmp SCRN_speak
77a4: c9 02 menu_pense cmp #$02
77a6: d0 03 bne menu_offer
77a8: 4c 0f 9c jmp SCRN_pense
77ab: 4c 18 9c menu_offer jmp SCRN_offer
77ae: c9 01 menu_take cmp #$01 ;col 1
77b0: d0 18 bne menu_drop
77b2: a5 72 lda MENUROW
77b4: d0 03 bne menu_buy
77b6: 4c e6 7b jmp take
77b9: c9 01 menu_buy cmp #$01
77bb: d0 03 bne menu_use
77bd: 4c 12 9c jmp $9c12
77c0: c9 02 menu_use cmp #$02
77c2: d0 03 bne menu_eat
77c4: 4c 09 9c jmp $9c09
77c7: 4c fc 7f menu_eat jmp what_will_you_eat
77ca: c9 02 menu_drop cmp #$02 ;col 2
77cc: d0 18 bne menu_examine
77ce: a5 72 lda MENUROW
77d0: d0 03 bne menu_sell
77d2: 4c d0 7c jmp L7CD0
77d5: c9 01 menu_sell cmp #$01
77d7: d0 03 bne menu_heal
77d9: 4c 15 9c jmp SCRN_sell
77dc: c9 02 menu_heal cmp #$02
77de: d0 03 bne menu_rest
77e0: 4c 00 9c jmp SCRN_heal
77e3: 4c b5 7a menu_rest jmp L7AB5
77e6: c9 03 menu_examine cmp #$03 ;col 3
77e8: d0 18 bne menu_status
77ea: a5 72 lda MENUROW
77ec: d0 03 bne menu_inventory
77ee: 4c 13 82 GAME2_examine jmp examine
77f1: c9 01 menu_inventory cmp #$01
77f3: d0 03 bne menu_grunspreke
77f5: 4c 65 82 jmp do_menu_inventory
77f8: c9 02 menu_grunspreke cmp #$02
77fa: d0 03 bne menu_kiniport
77fc: 4c 03 9c jmp SCRN_grunspreke
77ff: 4c 06 9c menu_kiniport jmp SCRN_kiniport
7802: a5 72 menu_status lda MENUROW ;col 4
7804: d0 03 bne menu_renew
7806: 4c c1 82 jmp do_menu_status ;row 0
7809: c9 01 menu_renew cmp #$01 ;row 1
780b: d0 0a bne menu_menu
780d: a5 35 lda doorNeshom
780f: f0 03 beq @renew
7811: 4c 39 77 jmp action_menu_no_effect ;RENEW does nothing in Neshom realm
7814: 4c 1f 84 @renew jmp renew
7817: c9 02 menu_menu cmp #$02 ;row 2
7819: d0 08 bne menu_sound
781b: 20 06 60 jsr GAME2_cleartext
781e: 68 pla ;discard game loop
781f: 68 pla
7820: 4c 40 a8 jmp SCRN_warm_start ;return to menu
7823: a9 01 menu_sound lda #$01 ;row 3
7825: 45 4a eor SOUNDFLG ;toggle sound
7827: 85 4a sta SOUNDFLG
7829: 20 49 a8 jsr SCRN_sound_status ;display sound status
782c: 4c e3 7f jmp message_wait
; Display action menu. This is a single string that wraps around the screen as
; it is printed in one shot.
782f: a9 00 display_actions lda #$00
7831: 85 64 sta HTAB
7833: a6 64 @char ldx HTAB
7835: bd 44 78 lda action_text,x
7838: 20 0f 60 jsr GAME2_printchar
783b: e6 64 inc HTAB
783d: a5 64 lda HTAB
783f: c9 9f cmp #$9f ;hardcoded length of action_text
7841: d0 f0 bne @char
7843: 60 rts
7844: a0 d0 c1 d5+ action_text .str ↑“ PAUSE TAKE DROP EXAMINE STATUS SPEAK BUY SELL I”
+ “NVENTORY RENEW PENSE USE HEAL GRUNSPREKE MENU OF”
+ “FER EAT REST KINIPORT SOUND ”
; Given menu row # and col #, get entry's htab (in HTAB) and width (in $77).
tmp_menuwidth .var $77 {addr/1} ;width of current menu column
78e3: a6 72 get_menu_pos ldx MENUROW ;menu row number we are on
78e5: bd 26 79 lda text_col1,x ;get the htab of col 1 in row
78e8: a6 71 ldx MENUCOL ;menu column we are on
78ea: 18 clc
78eb: 7d 2a 79 adc text_colx,x ;get htab of menu column
78ee: 85 64 sta HTAB
78f0: bd 2f 79 lda text_colw,x ;get width of menu column
78f3: 85 77 sta tmp_menuwidth ;save for later
78f5: 60 rts
; Highlight text of currently selected action menu item by drawing it in inverse
; text over the existing menu item.
78f6: 20 e3 78 highlight_menu_action jsr get_menu_pos
78f9: a9 01 lda #$01
78fb: 85 66 sta INVTEXT ;enable inverse
78fd: a6 64 @char ldx HTAB ;HTAB is also the index into the action text string
78ff: bd 44 78 lda action_text,x
7902: 20 0f 60 jsr GAME2_printchar
7905: e6 64 inc HTAB ;next screen col & string char
7907: c6 77 dec tmp_menuwidth
7909: d0 f2 bne @char
790b: a9 00 lda #$00
790d: 85 66 sta INVTEXT ;disable inverse
790f: 60 rts
; Unhighlight selected menu action, after we have previously highlighted it and
; are moving away.
unhighlight_menu_action
7910: 20 e3 78 jsr get_menu_pos
7913: a9 00 lda #$00
7915: 85 66 sta INVTEXT ;disable inverse
7917: a6 64 @char ldx HTAB
7919: bd 44 78 lda action_text,x
791c: 20 0f 60 jsr GAME2_printchar
791f: e6 64 inc HTAB
7921: c6 77 dec tmp_menuwidth
7923: d0 f2 bne @char
7925: 60 rts
7926: 00 28 50 78 text_col1 .bulk 00285078 ;col #s of first col of text
792a: 00 07 0d 13+ text_colx .bulk 00070d131f ;col #s of each menu col
792f: 07 06 06 0c+ text_colw .bulk 0706060c08 ;width of each menu col
• Clear variables
7934: a2 4a L7934 ldx #$4a
7936: bd 6c b5 L7936 lda inv_token,x
7939: 2c bd 1d bit GAME1_BITTAB5
793c: f0 0a beq L7948
793e: a9 00 lda #$00
7940: 9d 6c b5 sta inv_token,x
7943: a0 08 ldy #$08
7945: 20 48 7e jsr lose_weight
7948: ca L7948 dex
7949: 10 eb bpl L7936
794b: 60 rts
794c: a2 13 L794C ldx #$13
794e: bd 58 b5 @loop lda inv_shuba,x
7951: 2c bd 1d bit GAME1_BITTAB5
7954: f0 0a beq L7960
7956: a9 00 lda #$00
7958: 9d 58 b5 sta inv_shuba,x
795b: a0 07 ldy #item_shuba
795d: 20 48 7e jsr lose_weight
7960: ca L7960 dex
7961: 10 eb bpl @loop
7963: 60 rts
7964: a9 1c kidnapped_by_salaat lda #$1c
7966: 85 1b sta MAPPOS
7968: a9 00 lda #$00
796a: 85 1c sta MAPHALF
796c: a9 01 lda #$01
796e: 85 67 sta INSIDE
7970: 20 4c a8 jsr $a84c
7973: 20 1e 60 jsr GAME2_read_playfield
7976: a9 15 lda #$15
7978: 85 19 sta playerX
797a: a9 0f lda #$0f
797c: 85 1a sta playerY
797e: 20 0c 60 jsr GAME2_PRNTSTR
7981: 01 .dd1 $01
7982: d9 cf d5 a0+ .str ↑“YOU WERE KIDNAPPED BY THE FOLLOWERS OF D'OL SALAAT”
79b8: ff .dd1 $ff
79b9: 4c 03 6b @cont jmp GAME2_draw_player
79bc: a9 3b kidnapped_by_nekom lda #$3b
79be: 85 1b sta MAPPOS
79c0: a9 00 lda #$00
79c2: 85 1c sta MAPHALF
79c4: a9 01 lda #$01
79c6: 85 67 sta INSIDE
79c8: 20 4c a8 jsr $a84c
79cb: 20 1e 60 jsr GAME2_read_playfield
79ce: a9 13 lda #$13
79d0: 85 19 sta playerX
79d2: a9 0f lda #$0f
79d4: 85 1a sta playerY
79d6: 20 0c 60 jsr GAME2_PRNTSTR
79d9: 01 .dd1 $01
79da: d9 cf d5 a0+ .str ↑“YOU WERE KIDNAPPED BY THE NEKOM”
79f9: ff .dd1 $ff
79fa: 4c b9 79 jmp @cont
79fd: a5 34 attacked lda temp34_npctype
79ff: c9 e0 cmp #$e0 ;E0 = kidnapped by salaat
7a01: d0 0a bne @salaat_attack
7a03: 20 64 79 jsr kidnapped_by_salaat
7a06: a9 00 @finish_attack lda #$00
7a08: 85 34 sta temp34_npctype
7a0a: 4c e3 7f jmp message_wait
7a0d: c9 e1 @salaat_attack cmp #$e1 ;E1 = D'OL SALAAT attack
7a0f: d0 50 bne @nekom_kidnap
7a11: 20 1b 60 jsr GAME2_teleport_home
7a14: 20 0c 60 jsr GAME2_PRNTSTR
7a17: 01 .dd1 $01
7a18: d9 cf d5 a0+ .str ↑“YOU WERE ATTACKED BY A FOLLOWER OF D'OL SALAAT. TIME HAS”
+ “ PASSED.”
7a5d: ff .dd1 $ff
7a5e: 4c 06 7a jmp @finish_attack
7a61: c9 e2 @nekom_kidnap cmp #$e2 ;E2 = kidnapped by nekom
7a63: d0 06 bne @nekom_attack
7a65: 20 bc 79 jsr kidnapped_by_nekom
7a68: 4c 06 7a jmp @finish_attack
7a6b: 20 1b 60 @nekom_attack jsr GAME2_teleport_home ;otherwise (E3..EF?) = NEKOM attack
7a6e: 20 0c 60 jsr GAME2_PRNTSTR
7a71: 01 .dd1 $01
7a72: d9 cf d5 a0+ .str ↑“YOU WERE ATTACKED BY A MEMBER OF THE NEKOM. TIME HAS PASSE”
+ “D.”
7ab1: ff .dd1 $ff
7ab2: 4c 06 7a jmp @finish_attack
7ab5: 20 06 60 L7AB5 jsr GAME2_cleartext
7ab8: a5 67 lda INSIDE
7aba: d0 03 bne L7ABF
7abc: 4c c7 7b jmp no_nid_here
7abf: a5 e6 L7ABF lda tileKnee
7ac1: c9 3c cmp #$3c
7ac3: f0 03 beq L7AC8
7ac5: 4c c7 7b jmp no_nid_here
7ac8: a5 1b L7AC8 lda MAPPOS
7aca: c9 09 cmp #$09
7acc: d0 04 bne L7AD2
7ace: a5 1c lda MAPHALF
7ad0: f0 37 beq L7B09
7ad2: a5 1b L7AD2 lda MAPPOS
7ad4: c5 2d cmp homePos
7ad6: d0 06 bne L7ADE
7ad8: a5 1c lda MAPHALF
7ada: c5 2e cmp homeHalf
7adc: f0 2b beq L7B09
7ade: a5 37 L7ADE lda spokeTo
7ae0: f0 07 beq L7AE9
7ae2: ad f0 02 lda RWTSBUF+240
7ae5: c9 10 cmp #$10
7ae7: f0 20 beq L7B09
7ae9: 20 0c 60 L7AE9 jsr GAME2_PRNTSTR
7aec: 01 .dd1 $01
7aed: ce cf a0 cf+ .str ↑“NO ONE OFFERED YOU A NID”
7b05: ff .dd1 $ff
7b06: 4c e3 7f jmp message_wait
7b09: e6 19 L7B09 inc playerX
7b0b: 20 0f 6b jsr GAME2_adjacent_tiles
7b0e: a5 e6 lda tileKnee
7b10: c9 3d cmp #$3d
7b12: d0 f5 bne L7B09
7b14: c6 19 dec playerX
7b16: a2 2e ldx #$2e
7b18: 86 a3 stx animFrame
7b1a: e8 inx
7b1b: 86 a4 stx animFrame_unused
7b1d: 20 0c 6b jsr GAME2_redraw_player
7b20: 4c 7d 7b jmp sleep_loop
7b23: 20 75 84 L7B23 jsr next_time_period
7b26: a9 04 lda #$04
7b28: 18 clc
7b29: 65 25 adc levelRest
7b2b: 85 25 sta levelRest
7b2d: c5 2b cmp limitRest
7b2f: 90 05 bcc L7B36
7b31: a6 2b ldx limitRest ;cap level of rest
7b33: ca dex
7b34: 86 25 stx levelRest
7b36: a5 1c L7B36 lda MAPHALF
7b38: d0 0a bne L7B44
7b3a: a5 1b lda MAPPOS
7b3c: c9 09 cmp #$09
7b3e: d0 04 bne L7B44
7b40: a9 01 lda #$01
7b42: 85 35 sta doorNeshom
7b44: ae f1 02 L7B44 ldx RWTSBUF_npcnum
7b47: bd 00 b2 lda state_npc1,x
7b4a: d0 31 bne sleep_loop
7b4c: ad f2 02 lda RWTSBUF_npctype
NOTE: Handle sleeping in NPC $20..$23 nid
7b4f: c9 20 cmp #$20
7b51: d0 06 bne L7B59
7b53: 20 34 79 jsr L7934
7b56: 4c 7d 7b jmp sleep_loop
7b59: c9 22 L7B59 cmp #$22
7b5b: d0 06 bne L7B63
7b5d: 20 4c 79 jsr L794C
7b60: 4c 7d 7b jmp sleep_loop
7b63: c9 21 L7B63 cmp #$21
7b65: d0 09 bne L7B70
7b67: 20 06 60 jsr GAME2_cleartext
7b6a: 20 64 79 jsr kidnapped_by_salaat
7b6d: 4c e3 7f jmp message_wait
7b70: c9 23 L7B70 cmp #$23
7b72: d0 09 bne sleep_loop
7b74: 20 06 60 jsr GAME2_cleartext
7b77: 20 bc 79 jsr kidnapped_by_nekom
7b7a: 4c e3 7f jmp message_wait
; Looks like this does the sleeping loop, which goes tick-tock 3 times and then
; boop. Any input during this loop terminates it and returns to caller.
7b7d: 20 d6 82 sleep_loop jsr display_status
7b80: 20 f2 7f jsr await_button_up
7b83: 20 a9 7b jsr @terminate_on_input
7b86: 20 a9 7b jsr @terminate_on_input
7b89: a9 03 lda #$03 ;thrice
7b8b: 85 79 sta temp79
7b8d: a2 0d @loop ldx #$0d ;tick
7b8f: 20 03 b6 jsr SCRN_play_sound
7b92: 20 a9 7b jsr @terminate_on_input
7b95: a2 00 ldx #$00 ;tock
7b97: 20 03 b6 jsr SCRN_play_sound
7b9a: 20 a9 7b jsr @terminate_on_input
7b9d: c6 79 dec temp79
7b9f: d0 ec bne @loop
7ba1: a2 01 ldx #$01 ;boop
7ba3: 20 03 b6 jsr SCRN_play_sound
7ba6: 4c 23 7b jmp L7B23
; Read joystick (keyboard) input up to $15 times (effects a constant delay if no
; input). If any input occurred, terminate the calling subroutine.
7ba9: a9 15 @terminate_on_input lda #$15
7bab: 85 08 sta temp08
7bad: 20 2a 6b @loop jsr GAME2_menu_input
7bb0: d0 09 bne @got_input
7bb2: a5 a2 lda MOVING
7bb4: d0 05 bne @got_input
7bb6: c6 08 dec temp08
7bb8: d0 f3 bne @loop ;try $15 times
7bba: 60 rts
7bbb: 68 @got_input pla ;discard caller
7bbc: 68 pla
7bbd: 20 06 60 jsr GAME2_cleartext
7bc0: 20 21 6b jsr L6B21
7bc3: 20 f2 7f jsr await_button_up
7bc6: 60 rts
7bc7: 20 06 60 no_nid_here jsr GAME2_cleartext
7bca: 20 0c 60 jsr GAME2_PRNTSTR
7bcd: 29 .dd1 $29
7bce: d4 c8 c5 d2+ .str ↑“THERE IS NO NID HERE”
7be2: ff .dd1 $ff
7be3: 4c e3 7f jmp message_wait
7be6: 20 06 60 take jsr GAME2_cleartext
7be9: 20 b5 81 jsr item_of_interest
7bec: 90 03 bcc take_item
7bee: 4c 88 7c jmp nothing_to_take
7bf1: 20 c0 7f take_item jsr slot_to_item ;A=slot -> Y=item
7bf4: c0 0d cpy #item_fallaKey
7bf6: d0 04 bne @std_item
7bf8: a5 38 lda fallaKeyOffered
7bfa: d0 4c bne take_legally ;otherwise fall thru, should fail
7bfc: a5 67 @std_item lda INSIDE
7bfe: f0 48 beq take_legally
7c00: a5 c4 lda DEMOFLG
7c02: d0 44 bne take_legally ;anything can be taken during the demo
7c04: a5 1c lda MAPHALF
7c06: d0 16 bne @side1
7c08: a5 1b lda MAPPOS
7c0a: c5 2d cmp homePos
7c0c: f0 3a beq take_legally ;anything in your house is fair game
7c0e: c9 1c cmp #$1c ;or in room 1c, 3b, 4b or 51
7c10: f0 36 beq take_legally
7c12: c9 3b cmp #$3b
7c14: f0 32 beq take_legally
7c16: c9 4b cmp #$4b
7c18: f0 2e beq take_legally
7c1a: c9 51 cmp #$51
7c1c: f0 2a beq take_legally
7c1e: a5 37 @side1 lda spokeTo
7c20: f0 05 beq not_offered
7c22: cc f0 02 cpy RWTSBUF+240
7c25: f0 21 beq take_legally
7c27: 20 0c 60 not_offered jsr GAME2_PRNTSTR
7c2a: 01 .dd1 $01
7c2b: c9 d4 a0 d7+ .str ↑“IT WAS NOT OFFERED TO YOU”
7c44: ff .dd1 $ff
7c45: 4c e3 7f jmp message_wait
7c48: b9 c1 7c take_legally lda item_weights,y ;can we carry this?
7c4b: 18 clc
7c4c: 65 70 adc WEIGHT
7c4e: c5 2c cmp maxWeight
7c50: b0 52 bcs carry_no_more ;too heavy!
7c52: 85 70 sta WEIGHT
7c54: bd 00 b5 lda itemState,x
7c57: 09 20 ora #%00100000 ;set bit 5 of inv slot -- item possession
7c59: 9d 00 b5 sta itemState,x
7c5c: 84 77 sty selItemSlot
7c5e: 98 tya
7c5f: 20 51 7e jsr L7E51
7c62: 20 0c 60 jsr GAME2_PRNTSTR
7c65: 29 .dd1 $29
7c66: d9 cf d5 a0+ .str ↑“YOU FIND”
7c6e: ff .dd1 $ff
7c6f: a4 77 ldy selItemSlot
7c71: a9 32 lda #$32
7c73: 85 64 sta HTAB
7c75: 20 a2 7e jsr print_item_desc
7c78: a9 00 lda #$00
7c7a: 85 37 sta spokeTo
7c7c: a5 77 lda selItemSlot
7c7e: c9 01 cmp #item_spiritLamp
7c80: d0 03 bne L7C85
7c82: 20 4b 60 jsr L604B
7c85: 4c e3 7f L7C85 jmp message_wait
7c88: 20 0c 60 nothing_to_take jsr GAME2_PRNTSTR
7c8b: 29 .dd1 $29
7c8c: ce cf d4 c8+ .str ↑“NOTHING HERE TO TAKE”
7ca0: ff .dd1 $ff
7ca1: 4c e3 7f jmp message_wait
7ca4: 20 0c 60 carry_no_more jsr GAME2_PRNTSTR
7ca7: 29 .dd1 $29
7ca8: d9 cf d5 a0+ .str ↑“YOU CAN CARRY NO MORE”
7cbd: ff .dd1 $ff
7cbe: 4c e3 7f jmp message_wait
; Item weight table. Everything weighs 5 units except for tokens (1).
7cc1: 05 item_weights .dd1 $05 ;0 spirit bell
7cc2: 05 .dd1 $05
7cc3: 05 .dd1 $05
7cc4: 05 .dd1 $05
7cc5: 05 .dd1 $05
7cc6: 05 .dd1 $05
7cc7: 05 .dd1 $05
7cc8: 05 .dd1 $05
7cc9: 01 .dd1 $01 ;8 token
7cca: 05 .dd1 $05
7ccb: 05 .dd1 $05
7ccc: 05 .dd1 $05
7ccd: 05 .dd1 $05
7cce: 05 .dd1 $05
7ccf: 05 .dd1 $05 ;14 strange elixer
7cd0: 20 06 60 L7CD0 jsr GAME2_cleartext
7cd3: a5 19 lda playerX
7cd5: f0 04 beq L7CDB
7cd7: c9 27 cmp #$27
7cd9: d0 03 bne L7CDE
7cdb: 4c 35 7e L7CDB jmp L7E35
7cde: a5 67 L7CDE lda INSIDE
7ce0: a5 67 lda INSIDE ;??
7ce2: f0 42 beq L7D26
7ce4: a5 2d lda homePos
7ce6: c5 1b cmp MAPPOS
7ce8: d0 06 bne L7CF0
7cea: a5 2e lda homeHalf
7cec: c5 1c cmp MAPHALF
7cee: f0 03 beq L7CF3
7cf0: 4c 35 7e L7CF0 jmp L7E35
7cf3: a5 e6 L7CF3 lda tileKnee
7cf5: c9 57 cmp #$57
7cf7: 90 2d bcc L7D26
7cf9: c9 59 cmp #$59
7cfb: b0 29 bcs L7D26
7cfd: a5 e7 lda tileArm
7cff: c9 e2 cmp #$e2
7d01: b0 23 bcs L7D26
7d03: a5 95 lda FACING
7d05: 30 0b bmi L7D12
7d07: a5 ea lda tileArmRight
7d09: c9 e2 cmp #$e2
7d0b: b0 19 bcs L7D26
7d0d: a6 19 ldx playerX
7d0f: 4c 1b 7d jmp L7D1B
7d12: a5 e9 L7D12 lda tileArmLeft
7d14: c9 e2 cmp #$e2
7d16: b0 0e bcs L7D26
7d18: a6 19 ldx playerX
7d1a: ca dex
7d1b: 86 75 L7D1B stx temp75
7d1d: a6 1a ldx playerY
7d1f: ca dex
7d20: ca dex
7d21: 86 76 stx temp76
7d23: 4c 6d 7d jmp what_will_you_drop
7d26: a5 e3 L7D26 lda tileUnder
7d28: c9 e0 cmp #$e0
7d2a: b0 3e bcs L7D6A
7d2c: 20 12 6b jsr L6B12
7d2f: a5 f1 lda xSolid
7d31: f0 37 beq L7D6A
7d33: a5 e0 lda tileFeet
7d35: c9 e2 cmp #$e2
7d37: b0 31 bcs L7D6A
7d39: a5 95 lda FACING
7d3b: 30 07 bmi L7D44
7d3d: a5 e2 lda tileFeetRight
7d3f: a6 19 ldx playerX
7d41: 4c 49 7d jmp L7D49
7d44: a5 e1 L7D44 lda tileFeetLeft
7d46: a6 19 ldx playerX
7d48: ca dex
7d49: 86 75 L7D49 stx temp75
7d4b: a6 1a ldx playerY
7d4d: 86 76 stx temp76
7d4f: c9 e1 cmp #$e1
7d51: b0 17 bcs L7D6A
7d53: c9 07 cmp #$07
7d55: f0 13 beq L7D6A
7d57: c9 08 cmp #$08
7d59: f0 0f beq L7D6A
7d5b: c9 52 cmp #$52
7d5d: f0 0b beq L7D6A
7d5f: c9 1c cmp #$1c
7d61: f0 07 beq L7D6A
7d63: 20 12 6b jsr L6B12
7d66: a5 f1 lda xSolid
7d68: f0 03 beq what_will_you_drop
7d6a: 4c 35 7e L7D6A jmp L7E35
7d6d: 20 0c 60 what_will_you_drop jsr GAME2_PRNTSTR
7d70: 29 .dd1 $29
7d71: d7 c8 c1 d4+ .str ↑“WHAT WILL YOU DROP?”
7d84: ff .dd1 $ff
7d85: a9 ff lda #$ff ;iterate through all slots
7d87: 85 77 sta selItemSlot ;holds current slot index
7d89: 85 39 sta suppressSound0
7d8b: 20 f2 7f jsr await_button_up
7d8e: e6 77 @next_slot inc selItemSlot
7d90: a6 77 ldx selItemSlot
7d92: e0 ff cpx #$ff ;0-fe items, ff=nothing
7d94: d0 18 bne @valid_slot
7d96: 20 0c 60 jsr GAME2_PRNTSTR
7d99: 3e .dd1 $3e
7d9a: ce cf d4 c8+ .str ↑“NOTHING ”
7daa: ff .dd1 $ff
7dab: 4c c1 7d jmp L7DC1
7dae: bd 00 b5 @valid_slot lda itemState,x
7db1: 2c bd 1d bit GAME1_BITTAB5 ;do we have an item in this slot
7db4: f0 d8 beq @next_slot
7db6: 8a txa ;yes
7db7: 20 c0 7f jsr slot_to_item ;get item in Y
7dba: a9 3e lda #$3e
7dbc: 85 64 sta HTAB
7dbe: 20 a2 7e jsr print_item_desc
7dc1: 20 06 b6 L7DC1 jsr SCRN_play_sound_0
7dc4: 20 2a 6b L7DC4 jsr GAME2_menu_input
7dc7: d0 07 bne L7DD0
7dc9: a5 86 lda YDIR
7dcb: 10 f7 bpl L7DC4
7dcd: 4c 8e 7d jmp @next_slot
7dd0: 20 06 60 L7DD0 jsr GAME2_cleartext
7dd3: a6 77 ldx selItemSlot
7dd5: e0 ff cpx #$ff ;nothing
7dd7: f0 5b beq @rts
7dd9: a5 1b lda MAPPOS
7ddb: 9d 00 b3 sta itemStatePos,x
7dde: a5 75 lda temp75
7de0: 9d 00 b4 sta itemStateCol,x
7de3: a5 76 lda temp76
7de5: a4 1c ldy MAPHALF
7de7: f0 02 beq L7DEB
7de9: 09 80 ora #$80
7deb: 09 40 L7DEB ora #$40
7ded: 9d 00 b5 sta itemState,x
7df0: 20 51 7e jsr L7E51
7df3: a6 77 ldx selItemSlot
7df5: a5 3a lda litLamp
7df7: f0 2a beq L7E23
7df9: e4 3a cpx litLamp
7dfb: d0 26 bne L7E23
7dfd: a9 00 lda #$00
7dff: 9d 00 b5 sta itemState,x
7e02: 85 3a sta litLamp
7e04: 85 3b sta MON_PCH
7e06: 20 29 7e jsr L7E29
7e09: 20 0c 60 jsr GAME2_PRNTSTR
7e0c: 01 .dd1 $01
7e0d: d9 cf d5 d2+ .str ↑“YOUR LAMP VANISHES”
7e1f: ff .dd1 $ff
7e20: 4c e3 7f jmp message_wait
7e23: a5 77 L7E23 lda selItemSlot
7e25: c9 01 cmp #$01
7e27: d0 03 bne L7E2C
7e29: 20 4b 60 L7E29 jsr L604B
7e2c: a5 77 L7E2C lda selItemSlot
7e2e: 20 c0 7f jsr slot_to_item
7e31: 20 48 7e jsr lose_weight
7e34: 60 @rts rts
7e35: 20 06 60 L7E35 jsr GAME2_cleartext
7e38: 20 0c 60 jsr GAME2_PRNTSTR
7e3b: 29 .dd1 $29
7e3c: ce cf d4 a0+ .str ↑“NOT HERE”
7e44: ff .dd1 $ff
7e45: 4c e3 7f jmp message_wait
; Subtracts weight of item (in Y) from current carry weight.
7e48: a5 70 lose_weight lda WEIGHT
7e4a: 38 sec
7e4b: f9 c1 7c sbc item_weights,y
7e4e: 85 70 sta WEIGHT
7e50: 60 rts
7e51: 8a L7E51 txa
7e52: 48 pha
7e53: 20 09 60 jsr GAME2_write_tiles_to_text
7e56: 68 pla
7e57: aa tax
7e58: bd 00 b5 lda itemState,x
7e5b: 29 1f and #$1f
7e5d: 85 06 sta TXTROW
7e5f: bd 00 b4 lda itemStateCol,x
7e62: 85 05 sta TXTCOL
7e64: 20 90 7e jsr txtpos_to_addr
7e67: 8a txa
7e68: 20 c0 7f jsr slot_to_item
7e6b: 84 08 sty temp08
7e6d: 06 08 asl temp08
7e6f: a9 fd lda #$fd
7e71: 38 sec
7e72: e5 08 sbc temp08
7e74: a0 00 ldy #$00
7e76: b1 11 lda (temp11_textlo),y
7e78: 20 03 60 jsr GAME2_drawtile
7e7b: e6 05 inc TXTCOL
7e7d: e6 11 inc temp11_textlo
7e7f: d0 02 bne L7E83
7e81: e6 12 inc temp12_texthi
7e83: a0 00 L7E83 ldy #$00
7e85: b1 11 lda (temp11_textlo),y
7e87: 20 03 60 jsr GAME2_drawtile
7e8a: 20 03 6b jsr GAME2_draw_player
7e8d: 4c 15 6b jmp L6B15
; Convert the text position in (TXTCOL,TXTROW) to a text page address and store
; it in $11/12. Clobbers A,Y but preserves X.
7e90: a4 06 txtpos_to_addr ldy TXTROW
7e92: b9 a0 1d lda GAME1_textlo,y
7e95: 18 clc
7e96: 65 05 adc TXTCOL
7e98: 85 11 sta temp11_textlo
7e9a: b9 80 1d lda GAME1_texthi,y
7e9d: 69 00 adc #$00
7e9f: 85 12 sta temp12_texthi
7ea1: 60 rts
7ea2: be b0 7f print_item_desc ldx item_desc_idx,y ;item in Y
7ea5: 86 7a stx temp7a ;item
7ea7: a9 10 lda #16 ;length of item desc
7ea9: 85 7b sta temp7b ;len
7eab: a6 7a @printchar ldx temp7a
7ead: bd c0 7e lda item_desc,x
7eb0: 20 0f 60 jsr GAME2_printchar
7eb3: e6 7a inc temp7a
7eb5: e6 64 inc HTAB
7eb7: c6 7b dec temp7b
7eb9: d0 f0 bne @printchar
7ebb: a9 00 lda #$00
7ebd: 85 66 sta INVTEXT
7ebf: 60 rts
; There are 15 possible items, with 16 description indices in this string (the
; last not used). Each is 16 bytes long so the indices aren't really needed.
7ec0: c1 a0 d3 d0+ item_desc .str ↑“A SPIRIT BELL A SPIRIT LAMP A HONEYLAMP A WAND OF BEF”
+ “AL A ROAST LAPAN PAN BREAD FRUIT & NUTS A SHUBA ”
+ “ A TOKEN A TRENCHER BEAK WISSENBERRIES A VINE RO”
+ “PE THE TEMPLE KEY D'OL FALLA'S KEYA STRANGE ELIXER”
7fb0: 00 10 20 30+ item_desc_idx .bulk 00102030405060708090a0b0c0d0e0f0
; Compute the item number (0-14) from the inventory slot ($00-$fe). Takes the
; slot number in A, and sets Y to the index of the first byte in the item
; address table that is less than that.
7fc0: a0 00 slot_to_item ldy #$00
7fc2: d9 d1 7f @loop cmp @item_slots,y
7fc5: 90 06 bcc @iny
7fc7: d9 d2 7f cmp @item_slots+1,y
7fca: b0 01 bcs @iny
7fcc: 60 rts
7fcd: c8 @iny iny
7fce: d0 f2 bne @loop ;always--y<16
7fd0: 60 rts
; One pair of overlapping bytes for each of 15 items, or looked at another way,
; one byte for the first slot address an item can be in.
7fd1: 00 @item_slots .dd1 $00 ;spirit bell ($00)
7fd2: 01 .dd1 $01 ;spirit lamp ($01)
7fd3: 02 .dd1 $02 ;honeylamp ($02-$1a)
7fd4: 1b .dd1 $1b ;wand of befal ($1b)
7fd5: 1c .dd1 $1c ;roast lapan ($1c-$25)
7fd6: 26 .dd1 $26 ;pan bread ($26-$3e)
7fd7: 3f .dd1 $3f ;fruit and nuts
7fd8: 58 .dd1 $58 ;shuba
7fd9: 6c .dd1 $6c ;token
7fda: b7 .dd1 $b7 ;trencher beak
7fdb: d0 .dd1 $d0 ;wissenberries
7fdc: da .dd1 $da ;vine rope
7fdd: f8 .dd1 $f8 ;temple key ($f8)
7fde: f9 .dd1 $f9 ;d'ol falla's key ($f9)
7fdf: fa .dd1 $fa ;elixer ($fa-$fe)
7fe0: ff .dd1 $ff ;(terminator)
7fe1: e6 .dd1 $e6 ;unused
7fe2: ff .dd1 $ff ;unused
; Called, for example, after selecting SOUND menu item, which displays a status
; screen / message immediately, so wait for the select button to be released.
; Then, loop until a button or direction is pressed, clear the screen, and
; return.
7fe3: 20 f2 7f message_wait jsr await_button_up
7fe6: 20 2a 6b @loop jsr GAME2_menu_input
7fe9: d0 04 bne @ret
7feb: a5 a2 lda MOVING
7fed: f0 f7 beq @loop ;if no direction pressed
7fef: 4c 06 60 @ret jmp GAME2_cleartext ;and then rts
; Loop until (menu select) button released (or at least not being pressed).
7ff2: 20 2a 6b await_button_up jsr GAME2_menu_input
7ff5: d0 fb bne await_button_up
7ff7: a2 10 ldx #$10
7ff9: 4c 12 60 jmp GAME2_delayXtimes256 ;and then rts
tempEatenFood .var $78 {addr/1} ;which food was eaten
7ffc: 20 06 60 what_will_you_eat jsr GAME2_cleartext
7fff: 20 0c 60 jsr GAME2_PRNTSTR
8002: 01 .dd1 $01
8003: d7 c8 c1 d4+ .str ↑“WHAT WILL YOU EAT?”
8015: ff .dd1 $ff
8016: a9 ff lda #$ff
8018: 85 77 sta selItemSlot
801a: 85 78 sta tempEatenFood
801c: 85 39 sta suppressSound0
801e: 20 f2 7f jsr await_button_up
8021: e6 77 L8021 inc selItemSlot
8023: a6 77 ldx selItemSlot
8025: e0 ff cpx #$ff
8027: d0 1a bne L8043
8029: 86 78 stx tempEatenFood ;temp, which food
802b: 20 0c 60 jsr GAME2_PRNTSTR
802e: 15 .dd1 $15
802f: ce cf d4 c8+ .str ↑“NOTHING ”
803f: ff .dd1 $ff
8040: 4c 70 80 jmp L8070
8043: bd 00 b5 L8043 lda itemState,x
8046: 2c bd 1d bit GAME1_BITTAB5
8049: f0 d6 beq L8021
804b: 8a txa
804c: 20 c0 7f jsr slot_to_item
804f: c4 78 cpy tempEatenFood
8051: f0 ce beq L8021
8053: c0 04 cpy #$04
8055: f0 10 beq L8067
8057: c0 05 cpy #$05
8059: f0 0c beq L8067
805b: c0 06 cpy #$06
805d: f0 08 beq L8067
805f: c0 0a cpy #$0a
8061: f0 04 beq L8067
8063: c0 0e cpy #$0e
8065: d0 ba bne L8021
8067: 84 78 L8067 sty tempEatenFood
8069: a9 15 lda #$15
806b: 85 64 sta HTAB
806d: 20 a2 7e jsr print_item_desc
8070: 20 06 b6 L8070 jsr SCRN_play_sound_0
8073: 20 2a 6b L8073 jsr GAME2_menu_input
8076: d0 07 bne L807F
8078: a5 86 lda YDIR
807a: 10 f7 bpl L8073
807c: 4c 21 80 jmp L8021
807f: 20 06 60 L807F jsr GAME2_cleartext
8082: a6 77 ldx selItemSlot
8084: e0 ff cpx #$ff
8086: d0 01 bne L8089
8088: 60 rts
8089: a4 78 L8089 ldy tempEatenFood
808b: c0 04 cpy #$04
808d: d0 53 bne @is_pan_bread
808f: a5 20 lda PLAYER
8091: c9 02 cmp #PLAYER_Herd ;only the 2 Erdling
8093: f0 34 beq @lapan_is_good
8095: c9 04 cmp #PLAYER_Charn ;can eat lapan
8097: f0 30 beq @lapan_is_good
8099: 20 0c 60 jsr GAME2_PRNTSTR
809c: 01 .dd1 $01
809d: d4 c8 c5 a0+ .str ↑“THE LAPAN HAS A STRANGE TASTE”
80ba: ff .dd1 $ff
80bb: a5 23 lda levelSpirit
80bd: 38 sec
80be: e9 0f sbc #$0f
80c0: b0 02 bcs L80C4
80c2: a9 00 lda #$00
80c4: 85 23 L80C4 sta levelSpirit
80c6: 4c 25 81 jmp sate_hunger
80c9: 20 0c 60 @lapan_is_good jsr GAME2_PRNTSTR
80cc: 01 .dd1 $01
80cd: d4 c8 c5 a0+ .str ↑“THE LAPAN IS GOOD”
80de: ff .dd1 $ff
80df: 4c 25 81 jmp sate_hunger
80e2: c0 05 @is_pan_bread cpy #item_pan_bread
80e4: d0 1d bne @is_fruit_and_nuts
80e6: 20 0c 60 jsr GAME2_PRNTSTR
80e9: 01 .dd1 $01
80ea: d4 c8 c5 a0+ .str ↑“THE PAN BREAD IS GOOD”
80ff: ff .dd1 $ff
8100: 4c 25 81 jmp sate_hunger
8103: c0 06 @is_fruit_and_nuts cpy #item_fruit_nuts
8105: d0 31 bne @is_wissenberries
8107: 20 0c 60 jsr GAME2_PRNTSTR
810a: 01 .dd1 $01
810b: d4 c8 c5 a0+ .str ↑“THE FRUIT & NUTS ARE GOOD”
8124: ff .dd1 $ff
8125: a9 05 sate_hunger lda #$05 ;gain 5 food
8127: 18 clc
8128: 65 24 adc levelFood
812a: 85 24 sta levelFood
812c: c5 2a cmp limitFood ;cap at limit - 1
812e: 90 05 bcc @done
8130: a6 2a ldx limitFood
8132: ca dex
8133: 86 24 stx levelFood
8135: 4c a6 81 @done jmp L81A6
8138: c0 0a @is_wissenberries cpy #item_berries
813a: d0 36 bne @strange_elixer
813c: 20 75 84 jsr next_time_period ;lose 2 time periods
813f: 20 75 84 jsr next_time_period
8142: 20 0c 60 jsr GAME2_PRNTSTR
8145: 01 .dd1 $01
8146: d9 cf d5 a0+ .str ↑“YOU FEEL STRANGE. TIME PASSES”
8163: ff .dd1 $ff
8164: a5 23 lda levelSpirit
8166: 38 sec
8167: e9 0f sbc #$0f ;lose 10 spirit
8169: b0 02 bcs @done
816b: a9 00 lda #$00 ;floor
816d: 85 23 @done sta levelSpirit
816f: 4c a6 81 jmp L81A6
8172: 20 0c 60 @strange_elixer jsr GAME2_PRNTSTR
8175: 01 .dd1 $01
8176: d9 cf d5 a0+ .str ↑“YOU FEEL MUCH STRONGER”
818c: ff .dd1 $ff
818d: a5 26 lda levelStamina
818f: 18 clc
8190: 69 05 adc #$05
8192: 85 26 sta levelStamina
8194: 4a lsr A
8195: aa tax
8196: 86 25 stx levelRest
8198: 86 24 stx levelFood
819a: e8 inx
819b: 86 2b stx limitRest
819d: 86 2a stx limitFood
819f: a5 2c lda maxWeight
81a1: 18 clc
81a2: 69 05 adc #$05
81a4: 85 2c sta maxWeight
81a6: a6 77 L81A6 ldx selItemSlot
81a8: a9 00 lda #$00
81aa: 9d 00 b5 sta itemState,x
81ad: a4 78 ldy tempEatenFood
81af: 20 48 7e jsr lose_weight
81b2: 4c e3 7f jmp message_wait
; Check for item of interest at arm-level (take height) or at feet. Clears carry
; and sets A to the item slot if so. Sets carry if no item of interest.
• Clear variables
81b5: a5 e7 item_of_interest lda tileArm
81b7: c9 e0 cmp #$e0
81b9: 90 09 bcc L81C4
81bb: a6 1a ldx playerY
81bd: ca dex
81be: ca dex
81bf: 86 65 stx $65
81c1: 4c d1 81 jmp L81D1
81c4: a5 e0 L81C4 lda tileFeet
81c6: c9 e0 cmp #$e0
81c8: b0 03 bcs L81CD
81ca: 4c 11 82 jmp L8211
81cd: a6 1a L81CD ldx playerY
81cf: 86 65 stx $65
81d1: a6 19 L81D1 ldx playerX
81d3: 2c b8 1d bit GAME1_BITTAB0
81d6: d0 01 bne L81D9
81d8: ca dex
81d9: 86 08 L81D9 stx temp08
81db: 85 79 sta temp79 ;never used!
81dd: a2 00 L81DD ldx #$00
81df: bd 00 b3 L81DF lda itemStatePos,x
81e2: c5 1b cmp MAPPOS
81e4: d0 28 bne L820E
81e6: bd 00 b5 lda itemState,x
81e9: 0a asl A
81ea: a9 00 lda #$00
81ec: 2a rol A
81ed: c5 1c cmp MAPHALF
81ef: d0 1d bne L820E
81f1: bd 00 b5 lda itemState,x
81f4: 2c be 1d bit GAME1_BITTAB6
81f7: f0 15 beq L820E
81f9: 2c bd 1d bit GAME1_BITTAB5
81fc: d0 10 bne L820E
81fe: 29 1f and #$1f
8200: c5 65 cmp $65
8202: d0 0a bne L820E
8204: bd 00 b4 lda itemStateCol,x
8207: c5 08 cmp temp08
8209: d0 03 bne L820E
820b: 8a txa
820c: 18 clc
820d: 60 rts
820e: e8 L820E inx
820f: d0 ce bne L81DF
8211: 38 L8211 sec
8212: 60 rts
8213: 20 06 60 examine jsr GAME2_cleartext
8216: 20 b5 81 jsr item_of_interest
8219: 90 29 bcc it_looks_like
821b: 20 0c 60 jsr GAME2_PRNTSTR
821e: 01 .dd1 $01
821f: d4 c8 c5 d2+ .str ↑“THERE IS NOTHING OF INTEREST HERE”
8240: ff .dd1 $ff
8241: 4c e3 7f jmp message_wait
8244: 48 it_looks_like pha
8245: 20 0c 60 jsr GAME2_PRNTSTR
8248: 01 .dd1 $01
8249: c9 d4 a0 cc+ .str ↑“IT LOOKS LIKE”
8256: ff .dd1 $ff
8257: 68 pla
8258: 20 c0 7f jsr slot_to_item
825b: a9 0f lda #$0f
825d: 85 64 sta HTAB
825f: 20 a2 7e jsr print_item_desc
8262: 4c e3 7f jmp message_wait
8265: 20 06 60 do_menu_inventory jsr GAME2_cleartext
8268: 20 0c 60 jsr GAME2_PRNTSTR
826b: 01 .dd1 $01
826c: d9 cf d5 a0+ .str ↑“YOU HAVE”
8274: ff .dd1 $ff
8275: a9 ff lda #$ff
8277: 85 77 sta selItemSlot
8279: 85 78 sta selItemNum
827b: 85 39 sta suppressSound0 ;suppress beep for first item display
827d: e6 77 L827D inc selItemSlot
827f: a6 77 ldx selItemSlot
8281: e0 ff cpx #$ff
8283: d0 17 bne L829C
8285: e4 78 cpx selItemNum
8287: d0 10 bne @done
8289: 20 0c 60 jsr GAME2_PRNTSTR
828c: 0a .dd1 $0a
828d: ce cf d4 c8+ .str ↑“NOTHING ”
8295: ff .dd1 $ff
8296: 4c e3 7f jmp message_wait
8299: 4c 06 60 @done jmp GAME2_cleartext
829c: bd 00 b5 L829C lda itemState,x
829f: 2c bd 1d bit GAME1_BITTAB5
82a2: f0 d9 beq L827D
82a4: a9 00 lda #$00
82a6: 85 78 sta selItemNum
82a8: 8a txa
82a9: 20 c0 7f jsr slot_to_item
82ac: a9 0a lda #$0a
82ae: 85 64 sta HTAB
82b0: 20 a2 7e jsr print_item_desc
82b3: 20 06 b6 jsr SCRN_play_sound_0
82b6: 20 2a 6b L82B6 jsr GAME2_menu_input
82b9: d0 c2 bne L827D
82bb: a5 86 lda YDIR
82bd: 30 be bmi L827D
82bf: 10 f5 bpl L82B6
• Clear variables
82c1: 20 d3 82 do_menu_status jsr @status
82c4: 20 f2 7f jsr await_button_up
82c7: 20 2a 6b @loop jsr GAME2_menu_input ;await button or direction
82ca: d0 04 bne @ret
82cc: a5 a2 lda MOVING
82ce: f0 f7 beq @loop
82d0: 4c 06 60 @ret jmp GAME2_cleartext
82d3: 20 06 60 @status jsr GAME2_cleartext
82d6: 20 0c 60 display_status jsr GAME2_PRNTSTR
82d9: 01 .dd1 $01
82da: c4 c1 d9 .str ↑“DAY”
82dd: ff .dd1 $ff
82de: a6 20 ldx PLAYER
82e0: bd 94 83 lda player_name_idx,x
82e3: 85 7b sta temp7b
82e5: a9 18 lda #$18
82e7: 85 64 sta HTAB
82e9: a4 7b @loop1 ldy temp7b
82eb: b9 d0 1a lda GAME1_player_names,y
82ee: 20 0f 60 jsr GAME2_printchar
82f1: c6 7b dec temp7b ;print name right-to-left
82f3: c6 64 dec HTAB
82f5: a5 64 lda HTAB
82f7: c9 13 cmp #$13 ;each name is 5 chars -- use HTAB to track this
82f9: d0 ee bne @loop1
82fb: a6 21 ldx timeOfDay
82fd: bd 17 84 lda time_of_day_idx,x
8300: 85 7b sta temp7b
8302: a9 37 lda #$37
8304: 85 64 sta HTAB
8306: a4 7b @loop2 ldy temp7b
8308: b9 99 83 lda time_of_day_str,y
830b: 20 0f 60 jsr GAME2_printchar
830e: c6 7b dec temp7b
8310: c6 64 dec HTAB
8312: a5 64 lda HTAB
8314: c9 28 cmp #$28 ;each time of day is 15 chars long
8316: d0 ee bne @loop2
8318: 20 0c 60 jsr GAME2_PRNTSTR
831b: 3c .dd1 $3c
831c: cc c5 d6 c5+ .str ↑“LEVEL OF REST”
8329: ff .dd1 $ff
832a: 20 0c 60 jsr GAME2_PRNTSTR
832d: 51 .dd1 $51
832e: d3 d0 c9 d2+ .str ↑“SPIRIT LIMIT”
833a: ff .dd1 $ff
833b: 20 0c 60 jsr GAME2_PRNTSTR
833e: 64 .dd1 $64
833f: cc c5 d6 c5+ .str ↑“LEVEL OF FOOD”
834c: ff .dd1 $ff
834d: 20 0c 60 jsr GAME2_PRNTSTR
8350: 79 .dd1 $79
8351: d3 d4 c1 cd+ .str ↑“STAMINA”
8358: ff .dd1 $ff
8359: 20 0c 60 jsr GAME2_PRNTSTR
835c: 8c .dd1 $8c
835d: cc c5 d6 c5+ .str ↑“LEVEL OF SPIRIT”
836c: ff .dd1 $ff
836d: a9 05 lda #$05 ;6 values, accessed in reverse order ($27..$22)
836f: 85 7b sta temp7b
8371: a4 7b @loop3 ldy temp7b
8373: b6 22 ldx dayNum,y ;status values are sequential in zero page
8375: a0 00 ldy #$00
8377: 20 cc 84 jsr num_to_str
837a: a4 7b ldy temp7b
837c: b9 11 84 lda status_digit_pos,y ;position to print each value
837f: 85 64 sta HTAB
8381: a5 fc lda digits+3 ;write the 2-digit, zero-padded value
8383: 20 0f 60 jsr GAME2_printchar
8386: e6 64 inc HTAB
8388: a5 fd lda digits+4
838a: 20 0f 60 jsr GAME2_printchar
838d: c6 7b dec temp7b
838f: a5 7b lda temp7b
8391: 10 de bpl @loop3
8393: 60 rts
8394: 04 player_name_idx .dd1 $04 ;oddly, an index into player names at $1AD0
8395: 09 .dd1 $09 ;(pointing to the last char of each)
8396: 0e .dd1 $0e
8397: 13 .dd1 $13
8398: 18 .dd1 $18
8399: c5 c1 d2 cc+ time_of_day_str .str ↑“EARLY MORNING ”
83a8: cc c1 d4 c5+ .str ↑“LATE MORNING ”
83b7: c5 c1 d2 cc+ .str ↑“EARLY AFTERNOON”
83c6: cc c1 d4 c5+ .str ↑“LATE AFTERNOON ”
83d5: c5 c1 d2 cc+ .str ↑“EARLY EVENING ”
83e4: cc c1 d4 c5+ .str ↑“LATE EVENING ”
83f3: cd c9 c4 ce+ .str ↑“MIDNIGHT ”
8402: cc c1 d4 c5+ .str ↑“LATE NIGHT ”
8411: 05 status_digit_pos .dd1 $05 ;positions for the 6 status numbers
8412: 9c .dd1 $9c
8413: 74 .dd1 $74
8414: 4c .dd1 $4c
8415: 81 .dd1 $81
8416: 5e .dd1 $5e
8417: 0e time_of_day_idx .dd1 $0e ;index into times of day
8418: 1d .dd1 $1d ;(pointing to the last char of each)
8419: 2c .dd1 $2c
841a: 3b .dd1 $3b
841b: 4a .dd1 $4a
841c: 59 .dd1 $59
841d: 68 .dd1 $68
841e: 77 .dd1 $77
841f: 20 06 60 renew jsr GAME2_cleartext
8422: 20 1b 60 jsr GAME2_teleport_home
8425: 20 0c 60 jsr GAME2_PRNTSTR
8428: 29 .dd1 $29
8429: d9 cf d5 a0+ .str ↑“YOU WERE FOUND UNCONSCIOUS.”
8444: ff .dd1 $ff
8445: 20 4b 84 jsr time_has_passed
8448: 4c e3 7f jmp message_wait
844b: 20 0c 60 time_has_passed jsr GAME2_PRNTSTR
844e: 51 .dd1 $51
844f: d4 c9 cd c5+ .str ↑“TIME HAS PASSED.”
845f: ff .dd1 $ff
8460: 60 rts
; There are 256 ticks per minute, $25 (or $23) minutes per period, and 8 periods
; per day.
8461: a5 35 next_tick lda doorNeshom ;time does not pass automatically
8463: d0 04 bne @rts ;in the neshom realm
8465: c6 7c dec TICKS
8467: f0 01 beq next_minute
8469: 60 @rts rts
846a: c6 7d next_minute dec MINUTES
846c: d0 fb bne @rts
846e: a9 25 lda #$25
8470: 85 7d sta MINUTES
8472: 4c 75 84 jmp next_time_period
; Usually reached when game timer is running and minutes reaches 0. May also be
; called when we are resting, or when passing out drunk.
8475: e6 21 next_time_period inc timeOfDay
8477: a5 21 lda timeOfDay
8479: c9 08 cmp #$08 ;end of day?
847b: d0 06 bne check_time_expired
847d: a9 00 lda #$00 ;yes, go to next day
847f: 85 21 sta timeOfDay
8481: e6 22 inc dayNum
8483: a5 22 check_time_expired lda dayNum
8485: c9 33 cmp #$33 ;game over on day 50
8487: 90 09 bcc update_period_stats
8489: a9 00 lda #$00 ;pause timer (permanently!)
848b: 85 87 sta TICKING
848d: a9 01 lda #$01
848f: 85 3d sta GAMEOVER ;game over, man
8491: 60 rts
8492: c6 24 update_period_stats dec levelFood
8494: 10 10 bpl @has_food ;branch if food left
8496: a9 00 lda #$00 ;food floor is 0
8498: 85 24 sta levelFood
849a: a5 87 lda TICKING ;don't starve if paused
849c: f0 08 beq @has_food ;(paused when we are resting)
849e: a9 01 lda #$01
84a0: 85 3c sta STARVED
84a2: a9 00 lda #$00 ;pause timer
84a4: 85 87 sta TICKING
84a6: c6 25 @has_food dec levelRest
84a8: 10 10 bpl L84BA
84aa: a9 00 lda #$00 ;rest floor is 0
84ac: 85 25 sta levelRest
84ae: a5 87 lda TICKING
84b0: f0 08 beq L84BA
84b2: a9 02 lda #$02
84b4: 85 3c sta STARVED
84b6: a9 00 lda #$00
84b8: 85 87 sta TICKING
84ba: a5 23 L84BA lda levelSpirit ;spirit increases by 5 every period
84bc: 18 clc
84bd: 69 05 adc #$05
84bf: c5 27 cmp limitSpirit
84c1: 90 02 bcc L84C5
84c3: a5 27 lda limitSpirit ;cap spirit at limit
84c5: 85 23 L84C5 sta levelSpirit
84c7: a9 23 lda #$23
84c9: 85 7d sta MINUTES
84cb: 60 rts
; Convert unsigned 16-bit value in (Y,X) to 5-digit string in $F9..$FD, left-
; padded with zeroes. Uses standard 10s division algorithm, implemented via
; subtraction on the 6502, of course.
;
; ($7e/$7f are temps and only used in this subroutine.)
84cc: 86 7e num_to_str stx temp7e
84ce: 84 7f sty temp7f
84d0: a9 b0 lda #‘0’ | $80 ;the digit 0
84d2: a2 06 ldx #$06 ;#$05 would also work fine
84d4: 95 f8 @loop sta digits-1,x ;set $f9..$fe to #$b0 ($fe unused)
84d6: ca dex
84d7: d0 fb bne @loop
; 16-bit subtract the highest decimal place's value from the total value, until
; it would underflow, and increase the digit that many times. Then move on to
; the next digit. In other words, take quotient(x,10000), set x=remainder, take
; quotient(x,1000), and so on.
84d9: 38 @loop2 sec ;x=0 on entry
84da: a5 7e lda temp7e
84dc: fd f6 84 sbc tenslo,x
84df: a8 tay ;save
84e0: a5 7f lda temp7f
84e2: fd fb 84 sbc tenshi,x
84e5: 10 06 bpl @inc
84e7: e8 inx ;next digit
84e8: e0 05 cpx #$05 ;digits 0..4
84ea: d0 ed bne @loop2
84ec: 60 rts
84ed: f6 f9 @inc inc digits,x ;'0' -> '1', etc.
84ef: 85 7f sta temp7f
84f1: 84 7e sty temp7e
84f3: 4c d9 84 jmp @loop2
; Low and high 8 bits of decimal 10s places. E.g. 0x2710 = 10,000.
84f6: 10 e8 64 0a+ tenslo .bulk 10e8640a01 ;10000,1000,100,10,1 (low 8 bits)
84fb: 27 03 00 00+ tenshi .bulk 2703000000 ;10000,1000,100,10,1 (high 8 bits)
NOTE: The rest of the file $8500-$95FF appears to be junk
8500: 00 00 00 00+ .junk 4352