back to project page

CF.OBJ Disassembly

                   ********************************************************************************
                   * Caverns of Freitag, by David Shapiro                                         *
                   * Copyright 1982                                                               *
                   *                                                                              *
                   * Disassembly of "CF.OBJ".                                                     *
                   ********************************************************************************
                   * This does all of the heavy lifting for the game, including:                  *
                   *  - Initial generation of monsters and chests.                                *
                   *  - Movement and attacks of all monsters.                                     *
                   *    - Special attacks (wizard zap, dragon breath).                            *
                   *  - Rendering of mode 1 (hi-res), mode 2 (text mini-map), and mode 3 (text    *
                   * map).                                                                        *
                   *  - Sound effects.                                                            *
                   *                                                                              *
                   * The actual rendering on the hi-res screen is done with calls to GRAPHIX II.  *
                   ********************************************************************************
                   * Disassembly by Andy McFadden, using 6502bench SourceGen v1.5.                *
                   * Last updated 2020/01/26                                                      *
                   ********************************************************************************
                   ptr1            .eq     $06    {addr/2}
                   ptr2            .eq     $08    {addr/2}
                   ARG_DRAW_MODE   .eq     $1c               ;0=draw, 1=erase, 2=invert
                   ARG_ITEM_INDEX  .eq     $1e               ;LINESET/CHARSET item index
                   ARG_COLOR       .eq     $1f               ;0=green, 1=orange, 2=purple, 3=blue
                   MON_RNDL        .eq     $4e               ;low byte of KEYIN "random" value
                   ARG_EXT_PTR     .eq     $e8    {addr/2}   ;pointer to external data
                   ARG_X0          .eq     $f9    {addr/2}   ;X coord #0 (0-255 or 0-139)
                   ARG_Y0          .eq     $fb               ;Y coord #0 (0-191)
                   ARG_X1          .eq     $fc    {addr/2}   ;X coord #1 (0-255 or 0-139)
                   ARG_Y1          .eq     $fe               ;Y coord #1 (0-191)
                   ARG_FF          .eq     $ff               ;shape fill flag -or- CLR color
                   win_left        .eq     $0300             ;CX
                   win_top         .eq     $0301
                   player_win_x    .eq     $0302             ;position within window (AX) (0-9)
                   player_win_y    .eq     $0303             ;position within window (AY) (0-8)
                   display_mode    .eq     $0304
                   monster_map_x   .eq     $0305
                   monster_map_y   .eq     $0306
                   turn_timer      .eq     $0307
                   keyval_or_atk   .eq     $0308             ;key hit -or- monster attack flag
                   player_map_x    .eq     $0309             ;(0-79)
                   player_map_y    .eq     $030a             ;(0-79)
                   monster_move_x  .eq     $030b
                   monster_move_y  .eq     $030c
                   monster_count   .eq     $030d
                   mon_attack_count .eq    $030e             ;number of monsters that attacked player (0-4)
                   mon_attack_id0  .eq     $030f
                   mon_attack_id1  .eq     $0310
                   mon_attack_id2  .eq     $0311
                   mon_attack_id3  .eq     $0312
                   sound_pitch     .eq     $0313  {addr/2}
                   sound_duration  .eq     $0315  {addr/2}
                   sound_pitch_adj .eq     $0317  {addr/2}
                   turn_speed      .eq     $0319             ;speed - 1 (0-49)
                   skill_level_plus_4 .eq  $031a             ;Skill level + 4 (5-13)
                   atk_wiz1_x      .eq     $031b             ;window X coord of 1st attacking wizard
                   atk_wiz1_y      .eq     $031c             ;window Y coord of 1st attacking wizard
                   atk_wiz2_x      .eq     $031d             ;window X coord of 2nd attacking wizard
                   atk_wiz2_y      .eq     $031e             ;window Y coord of 2nd attacking wizard
                   hit_by_flame    .eq     $031f
                   dragon_breath_ready .eq $0320             ;zero when dragon ready to breathe
                   col_counter     .eq     $0323  {addr/1}
                   row_counter     .eq     $0324
                   map_row_addr    .eq     $0325  {addr/2}
                   row_tmp         .eq     $0327  {addr/2}
                   player_xc       .eq     $0329
                   player_yc       .eq     $032a
                   monster_move_tmp .eq    $032b
                   mon_taxicab_dist .eq    $032d
                   CHARSET         .eq     $081e             ;draw dots from bitmap
                   BDRW            .eq     $0821             ;blit hi-res bitmap
                   CBOX            .eq     $0833             ;draw a colored box
                   monster_x       .eq     $4000  {addr/170}
                   monster_y       .eq     $40aa  {addr/170}
                   monster_type    .eq     $4154  {addr/170}
                   sketchz_tiles   .eq     $7fc0             ;start of tile bitmap data
                   wall_tile       .eq     $8014  {addr/84}  ;gfx inverted near dragon
                   map             .eq     $a000  {addr/6400}
                   bad_breath_data .eq     $bc00  {addr/512}
                   KBD             .eq     $c000             ;R last key pressed + 128
                   KBDSTRB         .eq     $c010             ;RW keyboard strobe
                   SPKR            .eq     $c030             ;RW toggle speaker

                                   .org    $6d00
6d00: 4c 30 6d                     jmp     DrawHiRes         ;called from line 10000

6d03: 4c d1 6d                     jmp     DrawMiniMap       ;called from line 10210

6d06: 4c 3e 6e                     jmp     DrawTextMap       ;called from line 11000

6d09: 4c 01 6f                     jmp     UpdateOneTile     ;called from line 12000

6d0c: 4c 86 6f                     jmp     WaitForKey        ;called from line 20000

6d0f: 4c 60 70                     jmp     MoveMonsters      ;called from line 30010

6d12: 4c db 74                     jmp     CreateMonsters    ;called from lines 55-56 (also creates chests)

6d15: 4c 49 75                     jmp     Copy84Bytes       ;called from line 16000

6d18: 4c 53 75                     jmp     Invert8014

6d1b: 4c 67 75                     jmp     CleanMap          ;init; called from line 2

6d1e: 4c 87 75                     jmp     MoveMap           ;init; called from line 2

6d21: 4c b1 75                     jmp     PlayTone

6d24: 4c 02 76                     jmp     PlayFuneral

6d27: 4c 35 76                     jmp     PlayIndexedTone

6d2a: 4c 5f 76                     jmp     PlayIndexedDualTone

6d2d: 4c 99 76                     jmp     FindMonsterIndex  ;called from 20255, 54020

                   ********************************************************************************
                   * Draws the mode 1 hi-res tiles.                                               *
                   *                                                                              *
                   * On entry:                                                                    *
                   *   $300: CX (map center X coord)                                              *
                   *   $301: CY (map center Y coord)                                              *
                   ********************************************************************************
                   ]data_ptr       .var    $e8    {addr/2}
                   ]tmp1           .var    $f9    {addr/1}
                   ]tmp2           .var    $fb    {addr/1}

6d30: a5 4e        DrawHiRes       lda     MON_RNDL
6d32: 8d 47 77                     sta     random_value
6d35: ad 00 03                     lda     win_left          ;get CX
6d38: c9 32                        cmp     #50               ;less than 50?
6d3a: 90 12                        bcc     :NotBotRight      ;yes
6d3c: ad 01 03                     lda     win_top           ;check CY
6d3f: c9 33                        cmp     #51               ;less than 51?
6d41: 90 0b                        bcc     :NotBotRight      ;yes
6d43: ad 40 80                     lda     wall_tile+44      ;bottom right; see if walls are already orange
6d46: 30 0e                        bmi     :Cont             ;yes, nothing to do
6d48: 20 53 75                     jsr     Invert8014        ;no, make them orange
6d4b: 4c 56 6d                     jmp     :Cont

6d4e: ad 40 80     :NotBotRight    lda     wall_tile+44      ;are walls purple?
6d51: 10 03                        bpl     :Cont             ;yes?
6d53: 20 53 75                     jsr     Invert8014        ;no, invert them
6d56: a9 00        :Cont           lda     #$00              ;init row counter (0-8)
6d58: 8d 24 03                     sta     row_counter
6d5b: ad 01 03                     lda     win_top           ;get CY
6d5e: 20 ea 76                     jsr     GetMapRowAddr     ;get row address
                   ; loop for 9 rows
6d61: a9 09        :Loop2          lda     #$09              ;init col counter (0-9)
6d63: 8d 23 03                     sta     col_counter
                   ; loop for 10 columns
                   ; 
                   ; compute col * 4
6d66: ad 23 03     :Loop1          lda     col_counter
6d69: 0a                           asl     A
6d6a: 0a                           asl     A
6d6b: 85 f9                        sta     ]tmp1
                   ; compute row * 21
6d6d: ad 24 03                     lda     row_counter
6d70: 0a                           asl     A                 ;x2
6d71: 0a                           asl     A                 ;x4
6d72: 85 fb                        sta     ]tmp2
6d74: 0a                           asl     A                 ;x8
6d75: 0a                           asl     A                 ;x16
6d76: 18                           clc
6d77: 65 fb                        adc     ]tmp2             ;x16+x4 = x20
6d79: 6d 24 03                     adc     row_counter       ;x20+x1 = x21
6d7c: 85 fb                        sta     ]tmp2
                   ; set data ptr to map address
6d7e: ad 25 03                     lda     map_row_addr      ;current addr is $A000 + CY*80
6d81: 18                           clc
6d82: 6d 00 03                     adc     win_left          ;factor in CX
6d85: 85 e8                        sta     ]data_ptr
6d87: ad 26 03                     lda     map_row_addr+1
6d8a: 69 00                        adc     #$00
6d8c: 85 e9                        sta     ]data_ptr+1
6d8e: a5 e8                        lda     ]data_ptr
6d90: 18                           clc
6d91: 6d 23 03                     adc     col_counter
6d94: 85 e8                        sta     ]data_ptr
6d96: a5 e9                        lda     ]data_ptr+1
6d98: 69 00                        adc     #$00
6d9a: 85 e9                        sta     ]data_ptr+1
6d9c: a0 00                        ldy     #$00
6d9e: b1 e8                        lda     (]data_ptr),y
6da0: 85 1e                        sta     ARG_ITEM_INDEX
6da2: a9 c0                        lda     #<sketchz_tiles
6da4: 85 e8                        sta     ]data_ptr
6da6: a9 7f                        lda     #>sketchz_tiles
6da8: 85 e9                        sta     ]data_ptr+1
6daa: 20 21 08                     jsr     BDRW
6dad: ce 23 03                     dec     col_counter
6db0: 10 b4                        bpl     :Loop1
6db2: ee 24 03                     inc     row_counter       ;update row counter
6db5: ad 25 03                     lda     map_row_addr      ;row += 80
6db8: 18                           clc
6db9: 69 50                        adc     #80
6dbb: 8d 25 03                     sta     map_row_addr
6dbe: ad 26 03                     lda     map_row_addr+1
6dc1: 69 00                        adc     #$00
6dc3: 8d 26 03                     sta     map_row_addr+1
6dc6: ad 24 03                     lda     row_counter       ;check row counter
6dc9: c9 09                        cmp     #$09              ;all done?
6dcb: f0 03                        beq     :Done             ;yup, bail
6dcd: 4c 61 6d                     jmp     :Loop2

6dd0: 60           :Done           rts

                   ********************************************************************************
                   * Draws the mode 2 text mini-map.                                              *
                   *                                                                              *
                   * On entry:                                                                    *
                   *   $300: CX (map center X coord)                                              *
                   *   $301: CY (map center Y coord)                                              *
                   ********************************************************************************
6dd1: a9 00        DrawMiniMap     lda     #$00
6dd3: 8d 24 03                     sta     row_counter
6dd6: ad 01 03                     lda     win_top
6dd9: 20 ea 76                     jsr     GetMapRowAddr     ;get map address
6ddc: a9 09        :RowLoop        lda     #$09              ;10 across
6dde: 8d 23 03                     sta     col_counter
6de1: ae 24 03     :ColLoop        ldx     row_counter
6de4: bd 4b 77                     lda     minimap_addr_lo,x ;get text screen addr
6de7: 18                           clc
6de8: 6d 23 03                     adc     col_counter       ;add column
6deb: 85 06                        sta     ptr1              ;set dst pointer
6ded: bd 54 77                     lda     minimap_addr_hi,x
6df0: 85 07                        sta     ptr1+1
6df2: ad 25 03                     lda     map_row_addr      ;set up src pointer
6df5: 18                           clc
6df6: 6d 00 03                     adc     win_left          ;map row += win left coord
6df9: 85 e8                        sta     ]data_ptr
6dfb: ad 26 03                     lda     map_row_addr+1
6dfe: 69 00                        adc     #$00
6e00: 85 e9                        sta     ]data_ptr+1
6e02: a5 e8                        lda     ]data_ptr         ;+= current column
6e04: 18                           clc
6e05: 6d 23 03                     adc     col_counter
6e08: 85 e8                        sta     ]data_ptr
6e0a: a5 e9                        lda     ]data_ptr+1
6e0c: 69 00                        adc     #$00
6e0e: 85 e9                        sta     ]data_ptr+1
                   ; draw map char
6e10: a0 00                        ldy     #$00
6e12: b1 e8                        lda     (]data_ptr),y     ;get src value
6e14: aa                           tax
6e15: bd 5d 77                     lda     minimap_chars,x   ;look up char
6e18: 91 06                        sta     (ptr1),y          ;store directly on screen (may be inv/flash)
6e1a: ce 23 03                     dec     col_counter       ;move to next column
6e1d: 10 c2                        bpl     :ColLoop          ;not < 0, continue
6e1f: ee 24 03                     inc     row_counter       ;move to next row
6e22: ad 25 03                     lda     map_row_addr      ;update map ptr
6e25: 18                           clc
6e26: 69 50                        adc     #80               ;map width
6e28: 8d 25 03                     sta     map_row_addr
6e2b: ad 26 03                     lda     map_row_addr+1
6e2e: 69 00                        adc     #$00
6e30: 8d 26 03                     sta     map_row_addr+1
6e33: ad 24 03                     lda     row_counter       ;check row counter
6e36: c9 09                        cmp     #$09              ;are we done?
6e38: f0 03                        beq     :Done
6e3a: 4c dc 6d                     jmp     :RowLoop          ;no, keep going

6e3d: 60           :Done           rts

                   ********************************************************************************
                   * Draws the mode 3 full-screen text map.                                       *
                   *                                                                              *
                   * On entry:                                                                    *
                   *   $300: CX (map center X coord)                                              *
                   *   $301: CY (map center Y coord)                                              *
                   ********************************************************************************
6e3e: ad 00 03     DrawTextMap     lda     win_left          ;compute player map coordinates
6e41: 18                           clc
6e42: 6d 02 03                     adc     player_win_x
6e45: 8d 29 03                     sta     player_xc
6e48: ad 01 03                     lda     win_top
6e4b: 18                           clc
6e4c: 6d 03 03                     adc     player_win_y
6e4f: 8d 2a 03                     sta     player_yc
6e52: ad 29 03                     lda     player_xc         ;center player on map
6e55: 38                           sec
6e56: e9 14                        sbc     #20
6e58: 8d 29 03                     sta     player_xc
6e5b: ad 2a 03                     lda     player_yc
6e5e: 38                           sec
6e5f: e9 0c                        sbc     #12
6e61: 8d 2a 03                     sta     player_yc
6e64: ad 29 03                     lda     player_xc         ;range-check X
6e67: 10 05                        bpl     :XLeftOk
6e69: a9 00                        lda     #$00              ;clamp
6e6b: 8d 29 03                     sta     player_xc
6e6e: c9 29        :XLeftOk        cmp     #41
6e70: 90 05                        bcc     :XRightOk
6e72: a9 28                        lda     #40               ;clamp (80-40 = 40)
6e74: 8d 29 03                     sta     player_xc
6e77: ad 2a 03     :XRightOk       lda     player_yc         ;range-check Y
6e7a: 10 05                        bpl     :YTopOk
6e7c: a9 00                        lda     #$00              ;clamp
6e7e: 8d 2a 03                     sta     player_yc
6e81: c9 39        :YTopOk         cmp     #57
6e83: 90 05                        bcc     :YBotOk
6e85: a9 38                        lda     #56               ;clamp (80 - 24 = 56)
6e87: 8d 2a 03                     sta     player_yc
                   ; draw
6e8a: a9 00        :YBotOk         lda     #$00              ;start at the top
6e8c: 8d 24 03                     sta     row_counter
6e8f: ad 2a 03                     lda     player_yc         ;get player Y coord
6e92: 20 ea 76                     jsr     GetMapRowAddr     ;get map addr for that row
6e95: a9 27        :RowLoop        lda     #39
6e97: 8d 23 03                     sta     col_counter       ;draw 40 columns
6e9a: ae 24 03     :ColLoop        ldx     row_counter
6e9d: bd 85 77                     lda     text1_addr_lo,x   ;setup ptr into text page 1
6ea0: 18                           clc
6ea1: 6d 23 03                     adc     col_counter
6ea4: 85 06                        sta     ptr1
6ea6: bd 9d 77                     lda     text1_addr_hi,x
6ea9: 85 07                        sta     ptr1+1
6eab: ad 25 03                     lda     map_row_addr      ;setup map pointer
6eae: 18                           clc
6eaf: 6d 29 03                     adc     player_xc         ;adding player X coord
6eb2: 85 e8                        sta     ]data_ptr
6eb4: ad 26 03                     lda     map_row_addr+1
6eb7: 69 00                        adc     #$00
6eb9: 85 e9                        sta     ]data_ptr+1
6ebb: a5 e8                        lda     ]data_ptr
6ebd: 18                           clc
6ebe: 6d 23 03                     adc     col_counter       ;add current column
6ec1: 85 e8                        sta     ]data_ptr
6ec3: a5 e9                        lda     ]data_ptr+1
6ec5: 69 00                        adc     #$00
6ec7: 85 e9                        sta     ]data_ptr+1
                   ; show player, walls, and healers
                   ; don't show monsters, chests, or the Inn
6ec9: a0 00                        ldy     #$00
6ecb: b1 e8                        lda     (]data_ptr),y     ;get map value
6ecd: aa                           tax
6ece: bd 5d 77                     lda     minimap_chars,x   ;get the character
6ed1: e0 03                        cpx     #$03              ;is it 0/1/2 (empty/wall/player)?
6ed3: 90 06                        bcc     :Show             ;yes, show it
6ed5: e0 0e                        cpx     #14               ;is it a healer?
6ed7: f0 02                        beq     :Show             ;yes, show it
6ed9: a9 a0                        lda     #$a0              ;otherwise just show a space
6edb: 91 06        :Show           sta     (ptr1),y          ;store it
6edd: ce 23 03                     dec     col_counter       ;next column
6ee0: 10 b8                        bpl     :ColLoop          ;branch if more to do
6ee2: ee 24 03                     inc     row_counter       ;next row
6ee5: ad 25 03                     lda     map_row_addr      ;update map ptr
6ee8: 18                           clc
6ee9: 69 50                        adc     #80
6eeb: 8d 25 03                     sta     map_row_addr
6eee: ad 26 03                     lda     map_row_addr+1
6ef1: 69 00                        adc     #$00
6ef3: 8d 26 03                     sta     map_row_addr+1
6ef6: ad 24 03                     lda     row_counter       ;check row counter
6ef9: c9 18                        cmp     #24               ;more to do?
6efb: f0 03                        beq     :Done             ;no
6efd: 4c 95 6e                     jmp     :RowLoop          ;yes, loop

6f00: 60           :Done           rts

                   ********************************************************************************
                   * Updates a single tile on the mode 1 (hi-res) and mode 2 (text minimap)       *
                   * displays.                                                                    *
                   *                                                                              *
                   * On entry:                                                                    *
                   *   $304: display mode (1-3)                                                   *
                   *   $305: tile X position (0-79)                                               *
                   *   $306: tile Y position (0-79)                                               *
                   ********************************************************************************
6f01: ad 06 03     UpdateOneTile   lda     monster_map_y
6f04: 20 ea 76                     jsr     GetMapRowAddr
6f07: ad 05 03                     lda     monster_map_x
6f0a: 38                           sec
6f0b: ed 00 03                     sbc     win_left
6f0e: 8d 23 03                     sta     col_counter
6f11: 0a                           asl     A
6f12: 0a                           asl     A
6f13: 85 f9                        sta     ]tmp1
6f15: ad 06 03                     lda     monster_map_y
6f18: 38                           sec
6f19: ed 01 03                     sbc     win_top
6f1c: 8d 24 03                     sta     row_counter
6f1f: 0a                           asl     A
6f20: 0a                           asl     A
6f21: 85 fb                        sta     ]tmp2
6f23: 0a                           asl     A
6f24: 0a                           asl     A
6f25: 18                           clc
6f26: 65 fb                        adc     ]tmp2
6f28: 6d 24 03                     adc     row_counter
6f2b: 85 fb                        sta     ]tmp2
6f2d: ad 25 03                     lda     map_row_addr
6f30: 18                           clc
6f31: 6d 05 03                     adc     monster_map_x
6f34: 85 e8                        sta     ]data_ptr
6f36: ad 26 03                     lda     map_row_addr+1
6f39: 69 00                        adc     #$00
6f3b: 85 e9                        sta     ]data_ptr+1
6f3d: a0 00                        ldy     #$00
6f3f: b1 e8                        lda     (]data_ptr),y
6f41: 85 1e                        sta     ARG_ITEM_INDEX
6f43: a9 c0                        lda     #<sketchz_tiles
6f45: 85 e8                        sta     ]data_ptr
6f47: a9 7f                        lda     #>sketchz_tiles
6f49: 85 e9                        sta     ]data_ptr+1
6f4b: ad 23 03                     lda     col_counter       ;check column number
6f4e: 30 10                        bmi     :NoDraw
6f50: c9 0a                        cmp     #10               ;if < 0 or >= 10, it's offscreen
6f52: b0 0c                        bcs     :NoDraw
6f54: ad 24 03                     lda     row_counter       ;check row number
6f57: 30 07                        bmi     :NoDraw
6f59: c9 09                        cmp     #9                ;if < 0 or >= 9, it's offscreen
6f5b: b0 03                        bcs     :NoDraw
6f5d: 4c 61 6f                     jmp     :DrawTile

6f60: 60           :NoDraw         rts

6f61: 20 21 08     :DrawTile       jsr     BDRW
6f64: ad 04 03                     lda     display_mode      ;get display mode
6f67: c9 03                        cmp     #$03              ;text map mode?
6f69: f0 1a                        beq     :Done             ;yup, bail
6f6b: ae 24 03                     ldx     row_counter
6f6e: bd 4b 77                     lda     minimap_addr_lo,x
6f71: 18                           clc
6f72: 6d 23 03                     adc     col_counter
6f75: 85 06                        sta     ptr1
6f77: bd 54 77                     lda     minimap_addr_hi,x
6f7a: 85 07                        sta     ptr1+1
6f7c: a6 1e                        ldx     ARG_ITEM_INDEX
6f7e: bd 5d 77                     lda     minimap_chars,x   ;look up screen char
6f81: a0 00                        ldy     #$00
6f83: 91 06                        sta     (ptr1),y          ;store onto text page
6f85: 60           :Done           rts

                   ********************************************************************************
                   * Waits for the player to hit a key.                                           *
                   *                                                                              *
                   * On entry:                                                                    *
                   *   $304: display mode (1-3)                                                   *
                   *   $307: zero (turn timer)                                                    *
                   *   $319: turn speed (0-49)                                                    *
                   *                                                                              *
                   * On exit:                                                                     *
                   *   $308: key hit, or 0 if timeout                                             *
                   ********************************************************************************
                   • Clear variables

6f86: a9 01        WaitForKey      lda     #$01
6f88: 85 1f                        sta     ARG_COLOR
6f8a: e6 4e                        inc     MON_RNDL          ;update random seed
6f8c: ad 07 03                     lda     turn_timer
6f8f: 85 f9                        sta     ARG_X0
6f91: 85 fc                        sta     ARG_X1
6f93: e6 fc                        inc     ARG_X1
6f95: a9 bd                        lda     #189              ;draw box at bottom of screen
6f97: 85 fb                        sta     ARG_Y0
6f99: a9 bf                        lda     #191
6f9b: 85 fe                        sta     ARG_Y1
6f9d: a9 00                        lda     #$00
6f9f: 85 1c                        sta     ARG_DRAW_MODE     ;draw
6fa1: 85 ff                        sta     ARG_FF
6fa3: 20 11 70                     jsr     DrawTurnTimer     ;draw timer
6fa6: ee 07 03                     inc     turn_timer        ;advance
6fa9: ac 19 03                     ldy     turn_speed        ;get speed (0-49, 0 is no delay)
6fac: d0 0a                        bne     :DelayLoop
6fae: c8                           iny                       ;set Y=1
6faf: ee 07 03                     inc     turn_timer
6fb2: ee 07 03                     inc     turn_timer
6fb5: 4c bd 6f                     jmp     :CheckKey

6fb8: a2 00        :DelayLoop      ldx     #$00              ;spin for 256 iterations
6fba: ca           :Stall          dex
6fbb: d0 fd                        bne     :Stall
6fbd: ad 00 c0     :CheckKey       lda     KBD               ;key hit?
6fc0: 30 03                        bmi     :KeyHit           ;yes
6fc2: 88                           dey                       ;no, wait some more
6fc3: d0 f3                        bne     :DelayLoop
                   ; A key has been hit, or we've waited for one timer tick.
6fc5: ad 07 03     :KeyHit         lda     turn_timer        ;fiddle with the coordinates
6fc8: 85 f9                        sta     ARG_X0
6fca: 85 fc                        sta     ARG_X1
6fcc: c6 f9                        dec     ARG_X0
6fce: ac 19 03                     ldy     turn_speed        ;are we delaying at all?
6fd1: d0 08                        bne     L6FDB             ;yes
6fd3: c6 f9                        dec     ARG_X0
6fd5: c6 f9                        dec     ARG_X0
6fd7: c6 fc                        dec     ARG_X1
6fd9: c6 fc                        dec     ARG_X1
6fdb: a9 bd        L6FDB           lda     #189              ;set the Y coordinates
6fdd: 85 fb                        sta     ARG_Y0
6fdf: a9 bf                        lda     #191
6fe1: 85 fe                        sta     ARG_Y1
6fe3: a9 01                        lda     #$01              ;erase
6fe5: 85 1c                        sta     ARG_DRAW_MODE
6fe7: 20 11 70                     jsr     DrawTurnTimer     ;erase timer indicator
6fea: ad 00 c0                     lda     KBD               ;check key again
6fed: 30 0c                        bmi     :KeyHit2          ;key hit
6fef: ad 07 03     :ReCheck        lda     turn_timer        ;check timer
6ff2: c9 8b                        cmp     #139              ;reached limit?
6ff4: 90 90                        bcc     WaitForKey        ;no, go again
6ff6: a9 00                        lda     #$00              ;reset the turn timer
6ff8: 8d 07 03                     sta     turn_timer
6ffb: 8d 08 03     :KeyHit2        sta     keyval_or_atk     ;store key where CF can find it
6ffe: c9 93                        cmp     #$93              ;Ctrl+S?
7000: d0 0e                        bne     :Done             ;nope
7002: ad fe 75                     lda     _SpeakerClick+2   ;yes, toggle speaker by changing $C030 to $3F30
7005: 49 ff                        eor     #$ff
7007: 8d fe 75                     sta     _SpeakerClick+2
700a: 8d 10 c0                     sta     KBDSTRB           ;clear key, loop
700d: 4c ef 6f                     jmp     :ReCheck          ;doesn't count as a move

7010: 60           :Done           rts

                   ; Draws the turn-timer box on the hi-res screen, and an asterisk on the text
                   ; screen.
                   ; 
                   ; On entry:
                   ;   $1C: draw mode (0 for draw, 1 for erase)
7011: ad 04 03     DrawTurnTimer   lda     display_mode
7014: c9 03                        cmp     #$03              ;mode 3 (map)?
7016: f0 0e                        beq     :SkipText         ;don't put asterisk on text screen
7018: a6 f9                        ldx     ARG_X0            ;0-139
701a: bd b9 77                     lda     hi_res_col,x      ;convert to column byte offset
701d: aa                           tax
701e: a4 1c                        ldy     ARG_DRAW_MODE
7020: b9 4d 78                     lda     text_time_indic,y
7023: 9d d0 07                     sta     $07d0,x           ;line 24
7026: 4c 33 08     :SkipText       jmp     CBOX              ;go draw on the hi-res screen

7029: d4 c8 c9 d3+                 .dstr   “THIS PROGRAM COPYRIGHT 1982 BY DAVID (DR. CAT) SHAPIRO.”

                   ********************************************************************************
                   * Move all monsters.  Report attacks on player.                                *
                   *                                                                              *
                   * Also draws dragon breath and checks for a hit.                               *
                   *                                                                              *
                   * On entry:                                                                    *
                   *   $302: player X within window (AX) (0-9)                                    *
                   *   $303: player Y within window (AY) (0-8)                                    *
                   *   $304: display mode (1-3)                                                   *
                   *   $309: player X coord (CX+AX) (0-79)                                        *
                   *   $30A: player Y coord (CY+AY) (0-79)                                        *
                   *   $30D: number of active monsters (NM)                                       *
                   *                                                                              *
                   * On exit:                                                                     *
                   *   $30E: number of monsters that attacked (0-4)                               *
                   *   $30F-312: indexes of attacking monsters                                    *
                   *     (scribbles up to $316)                                                   *
                   *   $31B/31C: X/Y of 1st zapping wizard ($FF/$FF if none)                      *
                   *   $31D/31E: X/Y of 2nd zapping wizard ($FF/$FF if none)                      *
                   ********************************************************************************
7060: a9 00        MoveMonsters    lda     #$00
7062: 8d 0f 03                     sta     mon_attack_id0
7065: 8d 10 03                     sta     mon_attack_id1
7068: 8d 11 03                     sta     mon_attack_id2
706b: 8d 12 03                     sta     mon_attack_id3
706e: 8d 0e 03                     sta     mon_attack_count
7071: 20 af 70     :MonsterLoop    jsr     MoveMonster
7074: ae 0d 03                     ldx     monster_count     ;start at end of list
7077: bd 54 41                     lda     monster_type,x    ;get type
707a: c9 0a                        cmp     #10               ;thunderbug?
707c: d0 03                        bne     :NotTbug          ;no
707e: 20 af 70                     jsr     MoveMonster       ;yes, go again: thunderbugs move 2x
7081: ad 08 03     :NotTbug        lda     keyval_or_atk     ;did monster attack player?
7084: f0 0c                        beq     :NoAttack         ;no
7086: ad 0d 03                     lda     monster_count     ;ID of monster that attacked
7089: ae 0e 03                     ldx     mon_attack_count  ;X-reg=next available entry
708c: 9d 0f 03                     sta     mon_attack_id0,x  ;add to list ($30f-316)
708f: ee 0e 03                     inc     mon_attack_count
7092: ce 0d 03     :NoAttack       dec     monster_count     ;move on to next monster
7095: d0 da                        bne     :MonsterLoop
7097: ad 0e 03                     lda     mon_attack_count  ;at most 4 monsters can attack
709a: c9 05                        cmp     #$05              ; (even if completely surrounded)
709c: 90 05                        bcc     :ValOk
709e: a9 04                        lda     #$04              ;cap it
70a0: 8d 0e 03                     sta     mon_attack_count
70a3: 20 5e 73     :ValOk          jsr     CheckRangedAttack
70a6: a9 00                        lda     #$00              ;clear hit-by-flame flag
70a8: 8d 1f 03                     sta     hit_by_flame
70ab: 20 3a 74                     jsr     CheckDragonBreath
70ae: 60                           rts

                   ; 
                   ; Moves a single monster.
                   ; 
                   ; On entry:
                   ;   $30d: monster index
                   ; 
                   ; On exit:
                   ;   $308: nonzero if monster attacked player
                   ;   also, wizard attack values may be updated
                   ; 
70af: a9 00        MoveMonster     lda     #$00              ;clear attack flag
70b1: 8d 08 03                     sta     keyval_or_atk
70b4: ae 0d 03                     ldx     monster_count     ;get index
70b7: bd 00 40                     lda     monster_x,x       ;get map X/Y
70ba: 8d 05 03                     sta     monster_map_x
70bd: bd aa 40                     lda     monster_y,x
70c0: 8d 06 03                     sta     monster_map_y
70c3: 38                           sec
70c4: ed 0a 03                     sbc     player_map_y      ;calc Y distance
70c7: 10 05                        bpl     :YPos
70c9: 49 ff                        eor     #$ff              ;negative, invert
70cb: 18                           clc
70cc: 69 01                        adc     #$01
70ce: 8d 27 03     :YPos           sta     row_tmp           ;y_dist
70d1: ad 05 03                     lda     monster_map_x     ;calc X distance
70d4: 38                           sec
70d5: ed 09 03                     sbc     player_map_x
70d8: 10 05                        bpl     :XPos
70da: 49 ff                        eor     #$ff              ;negative, invert
70dc: 18                           clc
70dd: 69 01                        adc     #$01
70df: 18           :XPos           clc
70e0: 6d 27 03                     adc     row_tmp           ;add Y dist ("taxicab distance")
70e3: c9 14                        cmp     #20               ;less than 20?
70e5: 90 01                        bcc     :CloseEnough      ;yes, update this monster
70e7: 60                           rts                       ;no, too far, bail

70e8: 8d 2d 03     :CloseEnough    sta     mon_taxicab_dist
70eb: 20 b1 76                     jsr     Random            ;generate random 0-255
70ee: c9 20                        cmp     #32               ;is it 0-31? (1 in 8 chance)
70f0: b0 03                        bcs     :MoveNonRandom    ;no, move with purpose
70f2: 4c 78 72                     jmp     MoveRandomly      ;yes, do something random

70f5: a9 00        :MoveNonRandom  lda     #$00              ;zero out moves
70f7: 8d 0b 03                     sta     monster_move_x
70fa: 8d 0c 03                     sta     monster_move_y
70fd: ad 09 03                     lda     player_map_x      ;compare X coords
7100: 38                           sec
7101: ed 05 03                     sbc     monster_map_x
7104: f0 0f                        beq     :SameCol          ;in same column
7106: 30 08                        bmi     :PlayerToLeft
7108: a9 01                        lda     #$01              ;player to right, move right
710a: 8d 0b 03                     sta     monster_move_x
710d: 4c 15 71                     jmp     :SameCol

7110: a9 ff        :PlayerToLeft   lda     #$ff              ;player to left, move left
7112: 8d 0b 03                     sta     monster_move_x
7115: ad 0a 03     :SameCol        lda     player_map_y      ;compare Y coords
7118: 38                           sec
7119: ed 06 03                     sbc     monster_map_y
711c: f0 0f                        beq     :SameRow          ;in same row
711e: 30 08                        bmi     :PlayerAbove
7120: a9 01                        lda     #$01              ;player below, move down
7122: 8d 0c 03                     sta     monster_move_y
7125: 4c 2d 71                     jmp     :SameRow

7128: a9 ff        :PlayerAbove    lda     #$ff              ;player above, move up
712a: 8d 0c 03                     sta     monster_move_y
712d: ae 0d 03     :SameRow        ldx     monster_count
7130: bd 54 41                     lda     monster_type,x    ;get the type
7133: c9 0f                        cmp     #15               ;wizard?
7135: d0 22                        bne     :NotWizard
7137: ad 2d 03                     lda     mon_taxicab_dist  ;wizard; check distance
713a: c9 02                        cmp     #$02              ;distance = 2?
713c: d0 01                        bne     L713F             ;no, keep going
713e: 60                           rts                       ;yes, get no closer

713f: c9 01        L713F           cmp     #$01              ;distance = 1?
7141: d0 16                        bne     :NotWizard        ;no, do regular move
7143: ad 0b 03                     lda     monster_move_x    ;invert X move (run away!)
7146: 49 ff                        eor     #$ff
7148: 8d 0b 03                     sta     monster_move_x
714b: ee 0b 03                     inc     monster_move_x
714e: ad 0c 03                     lda     monster_move_y    ;invert Y move
7151: 49 ff                        eor     #$ff
7153: 8d 0c 03                     sta     monster_move_y
7156: ee 0c 03                     inc     monster_move_y
7159: ad 0b 03     :NotWizard      lda     monster_move_x    ;movement in X direction?
715c: f0 08                        beq     :NoMoveDir        ;no, branch
715e: ad 0c 03                     lda     monster_move_y    ;movement in Y direction?
7161: f0 03                        beq     :NoMoveDir        ;no, branch
7163: 4c b4 71                     jmp     :MoveDiagonal

7166: 20 94 72     :NoMoveDir      jsr     MoveOrAttack      ;try to move or attack
7169: ae 0b 03                     ldx     monster_move_x    ;didn't work, reverse axes
716c: ac 0c 03                     ldy     monster_move_y
716f: 8e 0c 03                     stx     monster_move_y
7172: 8c 0b 03                     sty     monster_move_x
7175: ae 0d 03                     ldx     monster_count
7178: bd 54 41                     lda     monster_type,x    ;check the monster type
717b: 29 01                        and     #$01              ;odd?
717d: f0 16                        beq     :Odd
717f: ad 0b 03                     lda     monster_move_x    ;invert X/Y
7182: 49 ff                        eor     #$ff
7184: 8d 0b 03                     sta     monster_move_x
7187: ee 0b 03                     inc     monster_move_x
718a: ad 0c 03                     lda     monster_move_y
718d: 49 ff                        eor     #$ff
718f: 8d 0c 03                     sta     monster_move_y
7192: ee 0c 03                     inc     monster_move_y
7195: 20 94 72     :Odd            jsr     MoveOrAttack      ;try to move or attack
7198: ad 0b 03                     lda     monster_move_x    ;didn't work, reverse axes
719b: 49 ff                        eor     #$ff
719d: 8d 0b 03                     sta     monster_move_x
71a0: ee 0b 03                     inc     monster_move_x
71a3: ad 0c 03                     lda     monster_move_y
71a6: 49 ff                        eor     #$ff
71a8: 8d 0c 03                     sta     monster_move_y
71ab: ee 0c 03                     inc     monster_move_y
71ae: 20 94 72                     jsr     MoveOrAttack      ;try again
71b1: 4c 78 72                     jmp     MoveRandomly      ;give up, just move randomly

71b4: ae 0d 03     :MoveDiagonal   ldx     monster_count
71b7: bd 54 41                     lda     monster_type,x    ;check type
71ba: c9 04                        cmp     #4                ;mad robot (no diagonal movement)
71bc: f0 13                        beq     :TryFirst
71be: c9 0d                        cmp     #13               ;mimic
71c0: f0 0f                        beq     :TryFirst
71c2: c9 09                        cmp     #9                ;invisoid
71c4: f0 0b                        beq     :TryFirst
71c6: c9 0a                        cmp     #10               ;thunderbug
71c8: f0 07                        beq     :TryFirst
71ca: 4c d4 71                     jmp     :NoTryFirst

71cd: c9 0e f0 00                  .junk   4

71d1: 20 94 72     :TryFirst       jsr     MoveOrAttack
71d4: ad 0a 03     :NoTryFirst     lda     player_map_y      ;get Y distance
71d7: 38                           sec
71d8: ed 06 03                     sbc     monster_map_y
71db: 8d 27 03                     sta     row_tmp
71de: 10 0b                        bpl     :YPos
71e0: ad 27 03                     lda     row_tmp           ;make positive
71e3: 49 ff                        eor     #$ff
71e5: 8d 27 03                     sta     row_tmp
71e8: ee 27 03                     inc     row_tmp
71eb: ad 09 03     :YPos           lda     player_map_x      ;get X distance
71ee: 38                           sec
71ef: ed 05 03                     sbc     monster_map_x
71f2: 8d 28 03                     sta     row_tmp+1
71f5: 10 0b                        bpl     :XPos
71f7: ad 28 03                     lda     row_tmp+1         ;make positive
71fa: 49 ff                        eor     #$ff
71fc: 8d 28 03                     sta     row_tmp+1
71ff: ee 28 03                     inc     row_tmp+1
7202: ae 0d 03     :XPos           ldx     monster_count
7205: bd 54 41                     lda     monster_type,x    ;get type
7208: 29 02                        and     #$02              ;subset
720a: f0 0c                        beq     :FlipPattern
720c: ad 27 03                     lda     row_tmp           ;compute deltaY - deltaX
720f: 38                           sec
7210: ed 28 03                     sbc     row_tmp+1
7213: 90 39                        bcc     :MovePattern2     ;deltaX is greater
7215: 4c 21 72                     jmp     :MovePattern1

7218: ad 27 03     :FlipPattern    lda     row_tmp           ;compute deltaY - deltaX
721b: 38                           sec
721c: ed 28 03                     sbc     row_tmp+1
721f: b0 2d                        bcs     :MovePattern2     ;deltaY is greater
7221: ad 0c 03     :MovePattern1   lda     monster_move_y    ;zero out moveY
7224: 8d 2b 03                     sta     monster_move_tmp
7227: a9 00                        lda     #$00
7229: 8d 0c 03                     sta     monster_move_y
722c: 20 94 72                     jsr     MoveOrAttack      ;try it
722f: a9 00                        lda     #$00              ;restore moveY, zero out moveX
7231: 8d 0b 03                     sta     monster_move_x
7234: ad 2b 03                     lda     monster_move_tmp
7237: 8d 0c 03                     sta     monster_move_y
723a: 20 94 72                     jsr     MoveOrAttack      ;try it
723d: ad 0c 03                     lda     monster_move_y    ;invert moveY
7240: 49 ff                        eor     #$ff
7242: 8d 0c 03                     sta     monster_move_y
7245: ee 0c 03                     inc     monster_move_y
7248: 20 94 72                     jsr     MoveOrAttack      ;try it
724b: 4c 78 72                     jmp     MoveRandomly      ;give up

724e: ad 0b 03     :MovePattern2   lda     monster_move_x    ;zero out moveX
7251: 8d 2b 03                     sta     monster_move_tmp
7254: a9 00                        lda     #$00
7256: 8d 0b 03                     sta     monster_move_x
7259: 20 94 72                     jsr     MoveOrAttack      ;try it
725c: a9 00                        lda     #$00              ;restore moveX, zero out moveY
725e: 8d 0c 03                     sta     monster_move_y
7261: ad 2b 03                     lda     monster_move_tmp
7264: 8d 0b 03                     sta     monster_move_x
7267: 20 94 72                     jsr     MoveOrAttack      ;try it
726a: ad 0b 03                     lda     monster_move_x    ;invert moveX
726d: 49 ff                        eor     #$ff
726f: 8d 0b 03                     sta     monster_move_x
7272: ee 0b 03                     inc     monster_move_x
7275: 20 94 72                     jsr     MoveOrAttack      ;try it
7278: 20 b1 76     MoveRandomly    jsr     Random            ;generate random number
727b: 29 03                        and     #$03              ;reduce to 0-3
727d: aa                           tax
727e: bd b5 77                     lda     move_dir,x
7281: 8d 0b 03                     sta     monster_move_x
7284: 20 b1 76                     jsr     Random            ;again
7287: 29 03                        and     #$03
7289: aa                           tax
728a: bd b5 77                     lda     move_dir,x
728d: 8d 0c 03                     sta     monster_move_y
7290: 20 94 72                     jsr     MoveOrAttack
7293: 60                           rts

                   ; 
                   ; Evaluate the monster's movement.  If we tried to move onto the player,
                   ; register an attack instead.
                   ; 
                   ; If we move or attack, the caller's return address will be popped off, which
                   ; will short-circut the caller's logic.  If we don't move, we return to the
                   ; caller.
                   ; 
7294: ad 0b 03     MoveOrAttack    lda     monster_move_x    ;did we move at all?
7297: 0d 0c 03                     ora     monster_move_y
729a: d0 01                        bne     :DidMove          ;yes, do the update
729c: 60                           rts                       ;no, bail

729d: ae 0d 03     :DidMove        ldx     monster_count
72a0: bd 54 41                     lda     monster_type,x
72a3: c9 0e                        cmp     #14               ;healer
72a5: d0 16                        bne     :NotHealer
72a7: ad 0b 03                     lda     monster_move_x    ;invert move -- healers tend to run
72aa: 49 ff                        eor     #$ff              ; away from player
72ac: 8d 0b 03                     sta     monster_move_x
72af: ee 0b 03                     inc     monster_move_x
72b2: ad 0c 03                     lda     monster_move_y
72b5: 49 ff                        eor     #$ff
72b7: 8d 0c 03                     sta     monster_move_y
72ba: ee 0c 03                     inc     monster_move_y
72bd: ad 06 03     :NotHealer      lda     monster_map_y     ;update monster X/Y
72c0: 18                           clc
72c1: 6d 0c 03                     adc     monster_move_y
72c4: 8d 24 03                     sta     row_counter
72c7: ad 05 03                     lda     monster_map_x
72ca: 18                           clc
72cb: 6d 0b 03                     adc     monster_move_x
72ce: 8d 23 03                     sta     col_counter
72d1: ad 24 03                     lda     row_counter       ;get pointer to new map position
72d4: 20 ea 76                     jsr     GetMapRowAddr
72d7: ad 25 03                     lda     map_row_addr
72da: 18                           clc
72db: 6d 23 03                     adc     col_counter
72de: 85 06                        sta     ptr1
72e0: ad 26 03                     lda     map_row_addr+1
72e3: 69 00                        adc     #$00
72e5: 85 07                        sta     ptr1+1
72e7: a0 00                        ldy     #$00              ;check what we're trying to move onto
72e9: b1 06                        lda     (ptr1),y
72eb: c9 02                        cmp     #$02              ;is this the player?
72ed: d0 08                        bne     :NotPlayer
72ef: a9 7b                        lda     #$7b              ;set attack flag
72f1: 8d 08 03                     sta     keyval_or_atk     ; instead of moving
72f4: 68                           pla                       ;pop caller address off
72f5: 68                           pla
72f6: 60                           rts

72f7: c9 00        :NotPlayer      cmp     #$00              ;empty space?
72f9: f0 01                        beq     DoMoveMaybe
72fb: 60                           rts                       ;no, can't move there

72fc: ae 0d 03     DoMoveMaybe     ldx     monster_count
72ff: bd 54 41                     lda     monster_type,x    ;check monster type
7302: c9 0d                        cmp     #13               ;mimic?
7304: d0 01                        bne     MoveUpdateMap     ;mimics don't move
7306: 60                           rts

                   ; 
                   ; Update the map for a monster move.
                   ; 
                   ; On entry:
                   ;   $06/07: pointer to map entry for new location
                   ;   $305: old location X
                   ;   $306: old location Y
                   ; 
                   ; Important: the caller's return address is popped off before returning.
                   ; 
7307: a5 06        MoveUpdateMap   lda     ptr1              ;save ptr1
7309: 48                           pha
730a: a5 07                        lda     ptr1+1
730c: 48                           pha
                   ; erase monster from old position
730d: ad 06 03                     lda     monster_map_y     ;get pointer to monster's position on map
7310: 20 ea 76                     jsr     GetMapRowAddr
7313: ad 25 03                     lda     map_row_addr
7316: 18                           clc
7317: 6d 05 03                     adc     monster_map_x
731a: 85 06                        sta     ptr1
731c: ad 26 03                     lda     map_row_addr+1
731f: 69 00                        adc     #$00
7321: 85 07                        sta     ptr1+1
7323: a0 00                        ldy     #$00
7325: a9 00                        lda     #$00              ;change it to empty space
7327: 91 06                        sta     (ptr1),y
7329: 68                           pla                       ;restore ptr1
732a: 85 07                        sta     ptr1+1
732c: 68                           pla
732d: 85 06                        sta     ptr1
                   ; store monster in map in new position
732f: ae 0d 03                     ldx     monster_count
7332: bd 54 41                     lda     monster_type,x
7335: 91 06                        sta     (ptr1),y
                   ; call UpdateOneTile to redraw the old and new positions
7337: ad 23 03                     lda     col_counter
733a: 9d 00 40                     sta     monster_x,x
733d: 8d 29 03                     sta     player_xc
7340: ad 24 03                     lda     row_counter
7343: 9d aa 40                     sta     monster_y,x
7346: 8d 2a 03                     sta     player_yc
7349: 20 01 6f                     jsr     UpdateOneTile
734c: ad 29 03                     lda     player_xc
734f: 8d 05 03                     sta     monster_map_x
7352: ad 2a 03                     lda     player_yc
7355: 8d 06 03                     sta     monster_map_y
7358: 20 01 6f                     jsr     UpdateOneTile
735b: 68                           pla                       ;remove caller address
735c: 68                           pla
735d: 60                           rts

                   CheckRangedAttack
735e: a9 ff                        lda     #$ff              ;clear wizard attack values
7360: 8d 1b 03                     sta     atk_wiz1_x
7363: 8d 1d 03                     sta     atk_wiz2_x
                   ; look for a wizard on the same vertical line
7366: a9 00                        lda     #$00              ;top of window
7368: 85 fb                        sta     ARG_Y0
736a: ad 02 03                     lda     player_win_x      ;player X coord
736d: 85 f9                        sta     ARG_X0
736f: 20 8f 73     :CheckVert      jsr     CheckWizard       ;if wizard here, try zap
7372: e6 fb                        inc     ARG_Y0
7374: a5 fb                        lda     ARG_Y0
7376: c9 09                        cmp     #9                ;reached bottom of window?
7378: d0 f5                        bne     :CheckVert        ;not yet
                   ; look for a wizard on the same horizontal line
737a: a9 00                        lda     #$00              ;left of window
737c: 85 f9                        sta     ARG_X0
737e: ad 03 03                     lda     player_win_y      ;player Y coord
7381: 85 fb                        sta     ARG_Y0
7383: 20 8f 73     :CheckHoriz     jsr     CheckWizard       ;if wizard here, try zap
7386: e6 f9                        inc     ARG_X0
7388: a5 f9                        lda     ARG_X0
738a: c9 0a                        cmp     #10               ;reached right edge of window?
738c: d0 f5                        bne     :CheckHoriz       ;not yet
738e: 60                           rts

738f: 20 1d 74     CheckWizard     jsr     GetMapValue
7392: c9 0f                        cmp     #15               ;wizard?
7394: f0 01                        beq     CheckWizardZap
7396: 60                           rts

                   ; Try to zap the player with a wizard.  Must be lined up vertically or
                   ; horizontally.
                   ; 
                   ; (the code re-uses the storage locations that the sound code uses, so the names
                   ; are a bit funny)
7397: a9 01        CheckWizardZap  lda     #$01              ;assume shooting down/right
7399: 8d 17 03                     sta     sound_pitch_adj
739c: a5 fb                        lda     ARG_Y0            ;are we lined up?
739e: cd 03 03                     cmp     player_win_y
73a1: d0 29                        bne     :CheckVertical    ;not horizontally
73a3: a5 f9                        lda     ARG_X0            ;yes, check position
73a5: cd 02 03                     cmp     player_win_x
73a8: 90 05                        bcc     :WizLeft          ;wizard to left, shooting right
73aa: a9 ff                        lda     #$ff              ;wizard to right, shooting left
73ac: 8d 17 03                     sta     sound_pitch_adj
73af: a5 f9        :WizLeft        lda     ARG_X0
73b1: 8d 15 03                     sta     sound_duration
                   ; scan tiles, looking for non-empty squares
73b4: a5 f9        :Loop           lda     ARG_X0
73b6: 18                           clc
73b7: 6d 17 03                     adc     sound_pitch_adj
73ba: 85 f9                        sta     ARG_X0
73bc: cd 02 03                     cmp     player_win_x      ;reached the player?
73bf: f0 34                        beq     ZapPlayer_H       ;yes, zap them
73c1: 20 1d 74                     jsr     GetMapValue       ;no, see what's there
73c4: f0 ee                        beq     :Loop             ;empty space, keep going
73c6: ad 15 03                     lda     sound_duration    ;not empty; restore X0 and bail
73c9: 85 f9                        sta     ARG_X0
73cb: 60                           rts

73cc: a5 fb        :CheckVertical  lda     ARG_Y0            ;check position
73ce: cd 03 03                     cmp     player_win_y
73d1: 90 05                        bcc     :WizAbove         ;wizard above, shooting down
73d3: a9 ff                        lda     #$ff              ;wizard below, shooting up
73d5: 8d 17 03                     sta     sound_pitch_adj
73d8: a5 fb        :WizAbove       lda     ARG_Y0
73da: 8d 15 03                     sta     sound_duration
                   ; scan tiles, looking for non-empty squares
73dd: a5 fb        :Loop           lda     ARG_Y0
73df: 18                           clc
73e0: 6d 17 03                     adc     sound_pitch_adj
73e3: 85 fb                        sta     ARG_Y0
73e5: cd 03 03                     cmp     player_win_y      ;reached the player?
73e8: f0 13                        beq     ZapPlayer_V       ;yes, zap them
73ea: 20 1d 74                     jsr     GetMapValue       ;no, see what's there
73ed: f0 ee                        beq     :Loop             ;empty space, keep going
73ef: ad 15 03                     lda     sound_duration    ;not empty; restore Y0 and bail
73f2: 85 fb                        sta     ARG_Y0
73f4: 60                           rts

73f5: ad 15 03     ZapPlayer_H     lda     sound_duration    ;restore X0
73f8: 85 f9                        sta     ARG_X0
73fa: 4c 02 74                     jmp     ZapPlayer

73fd: ad 15 03     ZapPlayer_V     lda     sound_duration    ;restore Y0
7400: 85 fb                        sta     ARG_Y0
7402: ad 1b 03     ZapPlayer       lda     atk_wiz1_x        ;already attacked by a wizard?
7405: 10 0b                        bpl     L7412             ;yes, try second storage
7407: a5 f9                        lda     ARG_X0            ;no, put in first storage
7409: 8d 1b 03                     sta     atk_wiz1_x
740c: a5 fb                        lda     ARG_Y0
740e: 8d 1c 03                     sta     atk_wiz1_y
7411: 60                           rts

7412: a5 f9        L7412           lda     ARG_X0
7414: 8d 1d 03                     sta     atk_wiz2_x
7417: a5 fb                        lda     ARG_Y0
7419: 8d 1e 03                     sta     atk_wiz2_y
741c: 60                           rts

                   ; Gets the tile value for the tile at left+X0,top+Y0.
                   ; 
                   ; On exit:
                   ;   A-reg: value
741d: ad 01 03     GetMapValue     lda     win_top
7420: 18                           clc
7421: 65 fb                        adc     ARG_Y0
7423: 20 ea 76                     jsr     GetMapRowAddr
7426: ad 25 03                     lda     map_row_addr
7429: 85 06                        sta     ptr1
742b: ad 26 03                     lda     map_row_addr+1
742e: 85 07                        sta     ptr1+1
7430: ad 00 03                     lda     win_left
7433: 18                           clc
7434: 65 f9                        adc     ARG_X0
7436: a8                           tay
7437: b1 06                        lda     (ptr1),y
7439: 60                           rts

                   ; If we're close enough to see the dragon breathe, show it and play the sound
                   ; effect.  If we're hit by it, set the flag.
                   ; 
                   ; The dragon breathes every-other turn.  CF sets the value to zero, and we
                   ; toggle the low bit on every breath.  When the dragon dies, CF sets the value
                   ; to 9 to disable it.
                   ; 
                   ; On Exit:
                   ;   $31f: 0 if not hit by flames, $ff if hit
                   CheckDragonBreath
743a: ad 20 03                     lda     dragon_breath_ready ;set to 9 on dragon death?
743d: 49 01                        eor     #$01              ; (line 40020)
743f: 8d 20 03                     sta     dragon_breath_ready
7442: f0 01                        beq     :ReadyToBreathe
7444: 60                           rts

7445: ad 00 03     :ReadyToBreathe lda     win_left          ;are we far enough east to see it?
7448: c9 42                        cmp     #66
744a: b0 01                        bcs     L744D             ;maybe, branch
744c: 60                           rts                       ;no

744d: ad 01 03     L744D           lda     win_top           ;are we far enough south to see it?
7450: c9 3f                        cmp     #63
7452: b0 01                        bcs     :CalcXY           ;yes, branch
7454: 60                           rts                       ;no

                   ; find screen position; map tiles are 28x21 pixels
7455: a9 47        :CalcXY         lda     #71               ;start in col 71
7457: 38                           sec
7458: ed 00 03                     sbc     win_left          ;adjust for window position
745b: 0a                           asl     A
745c: 0a                           asl     A                 ;A=col*4
745d: 85 f9                        sta     ARG_X0
745f: 06 f9                        asl     ARG_X0            ;x0=col*8
7461: 18                           clc
7462: 65 f9                        adc     ARG_X0            ;A=col*4 + col*8 = col*12
7464: 06 f9                        asl     ARG_X0            ;x0=col*16
7466: 18                           clc
7467: 65 f9                        adc     ARG_X0            ;A=col*12 + col*16 = col*28
7469: 85 f9                        sta     ARG_X0
746b: a9 00                        lda     #$00              ;update high byte if needed
746d: 85 fa                        sta     ARG_X0+1
746f: a9 47                        lda     #71               ;start in row 71
7471: 38                           sec
7472: ed 01 03                     sbc     win_top           ;adjust for window position
7475: 85 fb                        sta     ARG_Y0
7477: 06 fb                        asl     ARG_Y0
7479: 06 fb                        asl     ARG_Y0            ;y0=row*4
747b: 18                           clc
747c: 65 fb                        adc     ARG_Y0            ;A=row + row*4 = row*5
747e: 06 fb                        asl     ARG_Y0
7480: 06 fb                        asl     ARG_Y0            ;y0=row*16
7482: 18                           clc
7483: 65 fb                        adc     ARG_Y0            ;A=row*5 + row*16 = row*21
7485: 85 fb                        sta     ARG_Y0
                   ; draw
7487: a9 00                        lda     #<bad_breath_data
7489: 85 e8                        sta     ARG_EXT_PTR
748b: a9 bc                        lda     #>bad_breath_data
748d: 85 e9                        sta     ARG_EXT_PTR+1
748f: a9 02                        lda     #$02
7491: 85 1c                        sta     ARG_DRAW_MODE     ;mode=invert
7493: a9 00                        lda     #$00
7495: 85 1e                        sta     ARG_ITEM_INDEX    ;item 0
7497: 20 bc 74                     jsr     CharsetSaveXY
749a: 20 cc 74                     jsr     PlayDragonSound
749d: 20 bc 74                     jsr     CharsetSaveXY
74a0: ad 01 03                     lda     win_top
74a3: 18                           clc
74a4: 6d 03 03                     adc     player_win_y
74a7: c9 47                        cmp     #71               ;on row 71?
74a9: d0 10                        bne     :NotHit           ;nope, not hit
74ab: ad 00 03                     lda     win_left
74ae: 18                           clc
74af: 6d 02 03                     adc     player_win_x
74b2: c9 47                        cmp     #71               ;on col >= 71?
74b4: 90 05                        bcc     :NotHit           ;(71-74 open, 75-77 dragon, 78-79 wall)
74b6: a9 ff                        lda     #$ff              ;hit!
74b8: 8d 1f 03                     sta     hit_by_flame
74bb: 60           :NotHit         rts

                   ; Invokes CHARSET function, preserving X0/Y0.
74bc: a5 f9        CharsetSaveXY   lda     ARG_X0
74be: 48                           pha
74bf: a5 fb                        lda     ARG_Y0
74c1: 48                           pha
74c2: 20 1e 08                     jsr     CHARSET
74c5: 68                           pla
74c6: 85 fb                        sta     ARG_Y0
74c8: 68                           pla
74c9: 85 f9                        sta     ARG_X0
74cb: 60                           rts

                   ; Plays the dragon breath sound effects.
74cc: a9 06        PlayDragonSound lda     #$06
74ce: 85 06                        sta     ptr1
74d0: 20 35 76                     jsr     PlayIndexedTone
74d3: a9 07                        lda     #$07
74d5: 85 06                        sta     ptr1
74d7: 20 35 76                     jsr     PlayIndexedTone
74da: 60                           rts

                   ********************************************************************************
                   * Create a set of objects (monsters or chests).                                *
                   *                                                                              *
                   * On entry:                                                                    *
                   *   $300: 3 or 37 (monsters or chests)                                         *
                   *   $301: number of items to create                                            *
                   *                                                                              *
                   * Called from lines 55-56 with:                                                *
                   *  $300=3 $301=110 (create monsters)                                           *
                   *  $300=37 $301=62 (create chests)                                             *
                   ********************************************************************************
74db: a5 4e        CreateMonsters  lda     MON_RNDL          ;update random seed
74dd: 8d 47 77                     sta     random_value
                   ; Generate random (X,Y) coordinate.
74e0: 20 b1 76     :Retry1         jsr     Random            ;generate random number
74e3: 29 7f                        and     #$7f              ;reduce to 0-127
74e5: c9 50                        cmp     #80
74e7: b0 f7                        bcs     :Retry1           ;>= 80, try again
74e9: 8d 05 03                     sta     monster_map_x     ;store X coord (0-79)
74ec: 20 b1 76     :Retry2         jsr     Random            ;do same thing again
74ef: 29 7f                        and     #$7f
74f1: c9 50                        cmp     #80
74f3: b0 f7                        bcs     :Retry2
74f5: 8d 06 03                     sta     monster_map_y     ;store Y coord (0-79)
74f8: 20 ea 76                     jsr     GetMapRowAddr     ;get row address
74fb: ad 25 03                     lda     map_row_addr
74fe: 18                           clc
74ff: 6d 05 03                     adc     monster_map_x     ;add X coord
7502: 85 06                        sta     ptr1
7504: ad 26 03                     lda     map_row_addr+1
7507: 69 00                        adc     #$00
7509: 85 07                        sta     ptr1+1
                   ; check to see if cell is empty
750b: a0 00                        ldy     #$00
750d: b1 06                        lda     (ptr1),y
750f: d0 cf                        bne     :Retry1           ;not empty, pick another location
7511: ad 00 03                     lda     win_left          ;get object type
7514: 91 06                        sta     (ptr1),y          ;store it
7516: c9 03                        cmp     #$03              ;is it wall/empty/player?
7518: 90 29                        bcc     :Next             ;yes, move on
751a: c9 20                        cmp     #$20              ;is it a monster?
751c: b0 25                        bcs     :Next             ;no, move on
751e: ae 01 03                     ldx     win_top           ;get index
7521: ad 05 03                     lda     monster_map_x     ;get XC
7524: 9d 00 40                     sta     monster_x,x       ;store in monster table
7527: ad 06 03                     lda     monster_map_y     ;get YC
752a: 9d aa 40                     sta     monster_y,x       ;store in monster table
752d: ad 00 03                     lda     win_left          ;get type
7530: 9d 54 41                     sta     monster_type,x    ;store in monster table
                   ; pick a new monster type
7533: 20 b1 76     :ChangeMonster  jsr     Random
7536: 29 1f                        and     #$1f              ;0-31
7538: 18                           clc
7539: 69 03                        adc     #$03              ;3-34
753b: cd 1a 03                     cmp     skill_level_plus_4 ;exceeds skill level?
753e: b0 f3                        bcs     :ChangeMonster    ;yes, re-roll
7540: 8d 00 03                     sta     win_left          ;use for next one
7543: ce 01 03     :Next           dec     win_top           ;done yet?
7546: d0 98                        bne     :Retry1           ;nope (note we don't populate entry 0)
7548: 60                           rts

                   ********************************************************************************
                   * Copies (4*21)=84 bytes, the size of one hi-res tile.                         *
                   *                                                                              *
                   * On entry:                                                                    *
                   *   $08/09: src ptr                                                            *
                   *   $06/07: dst ptr                                                            *
                   ********************************************************************************
7549: a0 53        Copy84Bytes     ldy     #83
754b: b1 08        :Loop           lda     (ptr2),y
754d: 91 06                        sta     (ptr1),y
754f: 88                           dey
7550: 10 f9                        bpl     :Loop
7552: 60                           rts

                   ********************************************************************************
                   * Inverts the bytes from $8014-8067.                                           *
                   *                                                                              *
                   * This is the 4x21 wall bitmap.  The walls in most of the cavern are purple    *
                   * with black cross-hatching, but the walls near the dragon are orange with     *
                   * white cross-hatching.  There's a large empty zone around the dragon area so  *
                   * we don't have to worry about drawing both kinds.                             *
                   ********************************************************************************
7553: a0 53        Invert8014      ldy     #83               ;(21 * 4) - 1
7555: a9 14                        lda     #<wall_tile
7557: 85 06                        sta     ptr1
7559: a9 80                        lda     #>wall_tile
755b: 85 07                        sta     ptr1+1
755d: b1 06        :Loop           lda     (ptr1),y
755f: 49 ff                        eor     #$ff
7561: 91 06                        sta     (ptr1),y
7563: 88                           dey
7564: 10 f7                        bpl     :Loop
7566: 60                           rts

                   ********************************************************************************
                   * Removes all non-wall elements from the map.  Useful when restarting the      *
                   * game.                                                                        *
                   ********************************************************************************
7567: a9 00        CleanMap        lda     #<map
7569: 85 06                        sta     ptr1
756b: a9 a0                        lda     #>map
756d: 85 07                        sta     ptr1+1
756f: a0 00                        ldy     #$00
7571: b1 06        :Loop           lda     (ptr1),y
7573: c9 02                        cmp     #$02              ;empty space or wall?
7575: 90 04                        bcc     :NoWrite          ;yes, leave it alone
7577: a9 00                        lda     #$00              ;no, turn it into blank space
7579: 91 06                        sta     (ptr1),y
757b: c8           :NoWrite        iny
757c: d0 f3                        bne     :Loop
757e: e6 07                        inc     ptr1+1
7580: a5 07                        lda     ptr1+1
7582: c9 bc                        cmp     #$bc              ;erasing $1c00=7168, but map is only $1900=6400?
7584: d0 eb                        bne     :Loop
7586: 60                           rts

                   ********************************************************************************
                   * If it looks like the map is sitting on the hi-res screen, move it to $A000.  *
                   *                                                                              *
                   * This also relocates "BAD BREATH" from $3C00-3DFF to $BC00-BDFF.              *
                   ********************************************************************************
7587: ad 00 20     MoveMap         lda     $2000             ;check first byte of hi-res page
758a: c9 01                        cmp     #$01              ;does it look like the map is here?
758c: f0 01                        beq     :MoveIt           ;yes, copy it
758e: 60                           rts

758f: a9 00        :MoveIt         lda     #$00              ;copy $2000-3fff to $a000-bfff
7591: 85 06                        sta     ptr1
7593: 85 08                        sta     ptr2
7595: a9 20                        lda     #$20
7597: 85 07                        sta     ptr1+1
7599: a9 a0                        lda     #$a0
759b: 85 09                        sta     ptr2+1
759d: a0 00                        ldy     #$00
759f: b1 06        :Loop           lda     (ptr1),y
75a1: 91 08                        sta     (ptr2),y
75a3: c8                           iny
75a4: d0 f9                        bne     :Loop
75a6: e6 07                        inc     ptr1+1
75a8: e6 09                        inc     ptr2+1
75aa: a5 07                        lda     ptr1+1
75ac: c9 40                        cmp     #$40
75ae: d0 ef                        bne     :Loop
75b0: 60                           rts

                   ********************************************************************************
                   * Play a tone                                                                  *
                   *                                                                              *
                   * On entry:                                                                    *
                   *   $313-314 - pitch                                                           *
                   *   $315-316 - duration                                                        *
                   *   $317-318 - pitch adjustment                                                *
                   *                                                                              *
                   * If the pitch adjustment is nonzero, instead of a steady tone the code will   *
                   * generate a rising or falling note.                                           *
                   ********************************************************************************
75b1: a0 00        PlayTone        ldy     #$00
75b3: ad 13 03     L75B3           lda     sound_pitch       ;copy pitch value to var
75b6: 8d 27 03                     sta     row_tmp
75b9: ad 14 03                     lda     sound_pitch+1
75bc: 8d 28 03                     sta     row_tmp+1
75bf: c8           :SilenceLoop    iny                       ;duration=1 means 256 iterations
75c0: d0 27                        bne     :DecPitch         ;not time to dec duration; go dec pitch
75c2: ad 15 03                     lda     sound_duration    ;decrement duration
75c5: d0 03                        bne     :NoDec
75c7: ce 16 03                     dec     sound_duration+1
75ca: ce 15 03     :NoDec          dec     sound_duration
75cd: ad 13 03                     lda     sound_pitch       ;update pitch value with adjustment
75d0: 18                           clc
75d1: 6d 17 03                     adc     sound_pitch_adj
75d4: 8d 13 03                     sta     sound_pitch
75d7: ad 14 03                     lda     sound_pitch+1
75da: 6d 18 03                     adc     sound_pitch_adj+1
75dd: 8d 14 03                     sta     sound_pitch+1
75e0: ad 15 03                     lda     sound_duration    ;is duration zero?
75e3: 0d 16 03                     ora     sound_duration+1
75e6: d0 01                        bne     :DecPitch         ;not yet
75e8: 60                           rts

75e9: ad 27 03     :DecPitch       lda     row_tmp           ;count down pitch value
75ec: d0 03                        bne     :NoDec
75ee: ce 28 03                     dec     row_tmp+1
75f1: ce 27 03     :NoDec          dec     row_tmp
75f4: ad 27 03                     lda     row_tmp           ;is pitch counter zero?
75f7: 0d 28 03                     ora     row_tmp+1
75fa: d0 c3                        bne     :SilenceLoop      ;not yet
75fc: 2c 30 c0     _SpeakerClick   bit     SPKR              ;click speaker
75ff: 4c b3 75                     jmp     L75B3

                   ********************************************************************************
                   * Play Chopin's Funeral March when the player dies.                            *
                   ********************************************************************************
7602: a2 00        PlayFuneral     ldx     #$00              ;note number
7604: 8e 14 03                     stx     sound_pitch+1
7607: 8e 16 03                     stx     sound_duration+1
760a: 8e 17 03                     stx     sound_pitch_adj
760d: 8e 18 03                     stx     sound_pitch_adj+1
7610: bd 50 78     :PlayLoop       lda     funeral_song_pitch,x
7613: 8d 13 03                     sta     sound_pitch
7616: bd 5b 78                     lda     funeral_song_dur,x
7619: 4a                           lsr     A
761a: 8d 15 03                     sta     sound_duration
761d: 20 b1 75                     jsr     PlayTone
                   ; Pause briefly.
7620: a0 09                        ldy     #$09              ;delay length
7622: 8a                           txa
7623: 48                           pha
7624: a2 00        :DelayLoop1     ldx     #$00
7626: ea           :DelayLoop2     nop
7627: ca                           dex
7628: d0 fc                        bne     :DelayLoop2
762a: 88                           dey
762b: d0 f7                        bne     :DelayLoop1
762d: 68                           pla
762e: aa                           tax
762f: e8                           inx                       ;advance to next note
7630: e0 0b                        cpx     #11               ;played 11 notes?
7632: d0 dc                        bne     :PlayLoop         ;not yet
7634: 60                           rts

                   ********************************************************************************
                   * Play a single tone, determined by index.                                     *
                   *                                                                              *
                   * On entry:                                                                    *
                   *   $06: tone to play (0-7)                                                    *
                   *                                                                              *
                   * Tones used by CF:                                                            *
                   *   0: attack with sword                                                       *
                   *   1: hit monster with sword                                                  *
                   *   2: hit by monster                                                          *
                   *   3: dragon killed                                                           *
                   *   4: monster killed                                                          *
                   *   5: attacked by wizard                                                      *
                   * Tones used by CF.OBJ:                                                        *
                   *   6/7: dragon breath                                                         *
                   ********************************************************************************
7635: a6 06        PlayIndexedTone ldx     ptr1
7637: bd 66 78                     lda     st_pitch_lo,x
763a: 8d 13 03                     sta     sound_pitch
763d: bd 6e 78                     lda     st_pitch_hi,x
7640: 8d 14 03                     sta     sound_pitch+1
7643: bd 76 78                     lda     st_dur_lo,x
7646: 8d 15 03                     sta     sound_duration
7649: bd 7e 78                     lda     st_dur_hi,x
764c: 8d 16 03                     sta     sound_duration+1
764f: bd 86 78                     lda     st_pitchadj_lo,x
7652: 8d 17 03                     sta     sound_pitch_adj
7655: bd 8e 78                     lda     st_pitchadj_hi,x
7658: 8d 18 03                     sta     sound_pitch_adj+1
765b: 20 b1 75                     jsr     PlayTone
765e: 60                           rts

                   ********************************************************************************
                   * Play two tones, determined by index.                                         *
                   *                                                                              *
                   * On entry:                                                                    *
                   *   $06: tone to play (0-2)                                                    *
                   *                                                                              *
                   * Tones used by CF:                                                            *
                   *   0: moved, regular (20161)                                                  *
                   *   1: moved, running (20161)                                                  *
                   *   2: "OOF!  HIT A WALL" (20120), "BLOCKED BY <monster>" (20135)              *
                   ********************************************************************************
                   PlayIndexedDualTone
765f: a9 00                        lda     #$00
7661: 8d 14 03                     sta     sound_pitch+1
7664: 8d 16 03                     sta     sound_duration+1
7667: 8d 18 03                     sta     sound_pitch_adj+1
766a: a6 06                        ldx     ptr1
766c: bd 96 78                     lda     dt_pitch1,x
766f: 8d 13 03                     sta     sound_pitch
7672: bd 99 78                     lda     dt_dur1,x
7675: 8d 15 03                     sta     sound_duration
7678: bd 9c 78                     lda     dt_pitchadj1,x
767b: 8d 17 03                     sta     sound_pitch_adj
767e: 20 b1 75                     jsr     PlayTone
7681: a6 06                        ldx     ptr1
7683: bd 9f 78                     lda     dt_pitch2,x
7686: 8d 13 03                     sta     sound_pitch
7689: bd a2 78                     lda     dt_dur2,x
768c: 8d 15 03                     sta     sound_duration
768f: bd a5 78                     lda     dt_pitchadj2,x
7692: 8d 17 03                     sta     sound_pitch_adj
7695: 20 b1 75                     jsr     PlayTone
7698: 60                           rts

                   ********************************************************************************
                   * Finds the index of the monster at (X,Y).                                     *
                   *                                                                              *
                   * Called from 20255 to identify which monster the player is swinging at.       *
                   *                                                                              *
                   * On entry:                                                                    *
                   *   $06: map X coordinate                                                      *
                   *   $07: map Y coordinate                                                      *
                   *   $30d: number of monsters                                                   *
                   *                                                                              *
                   * On exit:                                                                     *
                   *   $30d: index of monster, or 0 if not found                                  *
                   ********************************************************************************
                   • Clear variables
                   ]map_x          .var    $06    {addr/1}
                   ]map_y          .var    $07    {addr/1}

                   FindMonsterIndex
7699: ae 0d 03                     ldx     monster_count
769c: bd 00 40                     lda     monster_x,x
769f: c5 06                        cmp     ]map_x
76a1: d0 08                        bne     :Nope
76a3: bd aa 40                     lda     monster_y,x
76a6: c5 07                        cmp     ]map_y
76a8: d0 01                        bne     :Nope
76aa: 60                           rts

76ab: ce 0d 03     :Nope           dec     monster_count
76ae: d0 e9                        bne     FindMonsterIndex
76b0: 60                           rts

                   ; 
                   ; Random number generator (16-bit state).
                   ; 
                   ; On exit:
                   ;   A-reg: random value (0-255)
                   ; 
76b1: a2 07        Random          ldx     #$07
76b3: ad 48 77     :Loop           lda     random_value+1
76b6: 6a                           ror     A
76b7: 4d 48 77                     eor     random_value+1
76ba: 6a                           ror     A
76bb: 6a                           ror     A
76bc: 4d 48 77                     eor     random_value+1
76bf: 6a                           ror     A
76c0: 4d 47 77                     eor     random_value
76c3: 6a                           ror     A
76c4: 6a                           ror     A
76c5: 6a                           ror     A
76c6: 49 01                        eor     #$01
76c8: 29 01                        and     #$01
76ca: a8                           tay
76cb: ad 47 77                     lda     random_value
76ce: 18                           clc
76cf: 6d 47 77                     adc     random_value
76d2: 8d 47 77                     sta     random_value
76d5: ad 48 77                     lda     random_value+1
76d8: 6d 48 77                     adc     random_value+1
76db: 8d 48 77                     sta     random_value+1
76de: 98                           tya
76df: 18                           clc
76e0: 6d 47 77                     adc     random_value
76e3: 8d 47 77                     sta     random_value
76e6: ca                           dex
76e7: d0 ca                        bne     :Loop
76e9: 60                           rts

                   ; 
                   ; Given a map row number, generate the row address.
                   ; 
                   ; On entry:
                   ;   A-reg: map row (0-79)
                   ; 
                   ; On exit:
                   ;   $325-326: map row address ($A000+)
                   ; 
76ea: 8d 27 03     GetMapRowAddr   sta     row_tmp
76ed: a9 00                        lda     #$00
76ef: 8d 28 03                     sta     row_tmp+1
76f2: a9 00                        lda     #<map             ;get map base address
76f4: 8d 25 03                     sta     map_row_addr
76f7: a9 a0                        lda     #>map
76f9: 8d 26 03                     sta     map_row_addr+1
76fc: 0e 27 03                     asl     row_tmp           ;multiply row by 80
76ff: 2e 28 03                     rol     row_tmp+1
7702: 0e 27 03                     asl     row_tmp
7705: 2e 28 03                     rol     row_tmp+1
7708: 0e 27 03                     asl     row_tmp
770b: 2e 28 03                     rol     row_tmp+1
770e: 0e 27 03                     asl     row_tmp
7711: 2e 28 03                     rol     row_tmp+1
7714: ad 25 03                     lda     map_row_addr
7717: 18                           clc
7718: 6d 27 03                     adc     row_tmp
771b: 8d 25 03                     sta     map_row_addr
771e: ad 26 03                     lda     map_row_addr+1
7721: 6d 28 03                     adc     row_tmp+1
7724: 8d 26 03                     sta     map_row_addr+1
7727: 0e 27 03                     asl     row_tmp
772a: 2e 28 03                     rol     row_tmp+1
772d: 0e 27 03                     asl     row_tmp
7730: 2e 28 03                     rol     row_tmp+1
7733: ad 25 03                     lda     map_row_addr      ;add result to map base address
7736: 18                           clc
7737: 6d 27 03                     adc     row_tmp
773a: 8d 25 03                     sta     map_row_addr
773d: ad 26 03                     lda     map_row_addr+1
7740: 6d 28 03                     adc     row_tmp+1
7743: 8d 26 03                     sta     map_row_addr+1
7746: 60                           rts

7747: 0c 62        random_value    .dd2    $620c
7749: ff                           .dd1    $ff               ;unused?
774a: 00                           .dd1    $00               ;unused?
                   ; Text page 1 base addresses for mini-map lines (upper-right corner).
774b: 9d 1d 9d 1d+ minimap_addr_lo .bulk   9d1d9d1d9d1d9d45c5
7754: 04 05 05 06+ minimap_addr_hi .bulk   040505060607070404
                   ; Characters to use for mini-map and full map.
775d: a0           minimap_chars   .dd1    “ ”               ;normal space
775e: 20                           .dd1    ‘ ’               ;wall: inverse space
775f: aa                           .dd1    “*”               ;player
7760: d3                           .dd1    “S”
7761: cd                           .dd1    “M”
7762: d2                           .dd1    “R”
7763: c2                           .dd1    “B”
7764: c7                           .dd1    “G”
7765: c6                           .dd1    “F”
7766: a0                           .dd1    “ ”
7767: d4                           .dd1    “T”
7768: c3                           .dd1    “C”
7769: d0                           .dd1    “P”
776a: a4                           .dd1    “$”               ;mimic
776b: c8                           .dd1    “H”
776c: d7                           .dd1    “W”
776d: 00 00 00 00+                 .bulk   0000000000000000000000000000 ;16-29 not stored in map
777b: 00 00 00 00+                 .bulk   000000000000      ;dragon parts: inverse '@'
7781: c0                           .dd1    “@”               ;(blank)
7782: a4                           .dd1    “$”               ;chest
7783: 63                           .dd1    $63               ;Inn: flashing '#'
7784: 2a                           .dd1    ‘*’               ;"poof": inverse asterisk
                   ; Text page 1 base addresses for all lines.  Used for mode 3 map.
7785: 00 80 00 80+ text1_addr_lo   .bulk   008000800080008028a828a828a828a850d050d050d050d0
779d: 04 04 05 05+ text1_addr_hi   .bulk   040405050606070704040505060607070404050506060707
                   ; Move direction, for random movement.
77b5: 00           move_dir        .dd1    $00
77b6: 01                           .dd1    $01
77b7: 00                           .dd1    $00
77b8: ff                           .dd1    $ff
                   ; Convert a color X coordinate (0-139) to (0-39).
77b9: 00 00 00 01+ hi_res_col      .bulk   0000000101010102020203030303040404050505050606060707070708080809
                                    +      0909090a0a0a0b0b0b0b0c0c0c0d0d0d0e0e0e0e0f0f0f101010101111111212
                                    +      12121313131414141415151516161616171717181818181919191a1a1a1a1b1b
                                    +      1b1c1c1c1c1d1d1d1e1e1e1e1f1f1f2020202021212122222222232323242424
                                    +      242525252626262627272727
7845: 27 27 27 27+                 .bulk   2727272727272727  ;unused?
784d: aa           text_time_indic .dd1    “*”               ;turn timeout indicator char
784e: a0                           .dd1    “ ”
784f: 00                           .dd1    $00               ;unused?
                   ; 
                   ; Pitch/duration for funeral song.
                   ; 
                   funeral_song_pitch
7850: 57 57 57 57+                 .bulk   57575757484b4c57575a57
                   funeral_song_dur
785b: 6f 6f 17 6f+                 .bulk   6f6f176f424f7a63535353
                   ; 
                   ; Pitch/duration data for indexed single-tone.
                   ; 
7866: 10 44 40 90+ st_pitch_lo     .bulk   10444090080170ec
786e: 00 00 00 00+ st_pitch_hi     .bulk   0000000000000000
7876: 10 1c 0d 28+ st_dur_lo       .bulk   101c0d280c401522
787e: 00 00 00 00+ st_dur_hi       .bulk   0000000000000000
7886: ff 02 fb fc+ st_pitchadj_lo  .bulk   ff02fbfc00070cfe
788e: ff 00 ff ff+ st_pitchadj_hi  .bulk   ff00ffff000000ff
                   ; 
                   ; Pitch/duration data for indexed dual-tone.
                   ; 
7896: 77 40 c0     dt_pitch1       .bulk   7740c0
7899: 07 07 20     dt_dur1         .bulk   070720
789c: 00 00 00     dt_pitchadj1    .bulk   000000
789f: f0 60 ff     dt_pitch2       .bulk   f060ff
78a2: 07 07 20     dt_dur2         .bulk   070720
78a5: 00 00 00     dt_pitchadj2    .bulk   000000

Symbol Table

No exported symbols found.