Zelda Automap 0.2 Source

Below is the source for the Zelda Automap hack (0.2). You can also download the source with the needed GFX file. The code should be assembled with snarfblASM. The resulting IPS file should be applied to the PRG0 version of the ROM (PRG1 appears to work as well, but the hack was created and tested on PRG0). Comments are welcome.



  1. ; Zelda auto-map Patch
  2. ; 0.2
  3. ;
  4. ; By snarfblam
  5. ; —————————-
  6. ; Includes:
  7. ;   -Auto-map
  8. ;   -1/8 heart increments
  9. ;   -Faster potion/fairy refill
  10. ;   -Changed magic key count from "A" to "infinity" symbol
  11.  
  12.  
  13. ; snarfblASM
  14. ; ———-
  15. ; This code should be assembled with snarfblASM. snarfblASM was
  16. ; used for two reasons:
  17. ;   -The PATCH directive
  18. ;   -I authored snarfblASM and I look for every opportunity to test it.
  19.  
  20. ; PATCH directive
  21. ; —————
  22. ; The .PATCH directive specifies a ROM offset for the code that
  23. ; follows. This is good for hacks that need to insert code at
  24. ; many locations. Syntax is as follows:
  25. ; .PATCH offset     ; decimal
  26. ; .PATCH $offset    ; hex
  27. ; .PATCH 0xoffset   ; hex
  28. ; .PATCH BB:AAAA    ; B = bank, A = address (both hex). Assumes 16kb banks. Header is accounted for.
  29.  
  30.  
  31.  
  32. ; CODE!!!
  33. ; ——-
  34.  
  35. ;========================================================
  36. ; Map image
  37. ;========================================================
  38.  
  39. .PATCH $16D10
  40. .incbin "MapTiles.gfx"
  41.  
  42.  
  43.  
  44. ;========================================================
  45. ; Variable declarations
  46. ;========================================================
  47.  
  48.  
  49. ; Game variables
  50. ; ————–
  51. LevelNumber         := $10
  52. SaveSlot            := $16
  53. PendingPpuMacro     := $14
  54. CurrentMapLocation  := $EB
  55. NewMapLocation      := $EC
  56. OAM_MapBlipY        := $0254
  57.  
  58.  
  59. ; Game routines
  60. ; ————-
  61. BankSwap        := $FFAC
  62. SendPpuMacro    := $A0F6
  63.  
  64.  
  65. ; Our addresses
  66. ;———————-
  67. MapTiles    = $AD00 ; 06:AD00
  68. VRAM_MapTiles = $1300
  69.  
  70.  
  71. ; Our variables
  72. ; —————–
  73. .enum $6C00
  74.     tileFlag:   .dsb 1  ; Used to indicate that there is a pending PPU macro for the map
  75.     mapVar:     .dsb 1  ; Temporary storage variable
  76.     mapVar_X:   .dsb 1  
  77.     mapVar_Y:   .dsb 1
  78.     mapLoop_X:  .dsb 1
  79.     mapLoop_Y:  .dsb 1
  80. .endenum
  81. .enum $7F10
  82.     SecondPpuStringIndex: .DSB 1    ;
  83.    
  84.     MapBits_Left:   .DSB 1      ; Stores flags for whether the two screens in the left/right side
  85.     MapBits_Right:  .DSB 1      ; of the current map tile have been visited, in lower 2 bits
  86.    
  87.     MapFilter_Top:    .DSB 1    ; Stores a value to be ANDed with the bytes of a map tile to black out unvisited screens
  88.     MapFilter_Bottom: .DSB 1
  89.    
  90.     MapTileMacro:   .DSB $14    ; 10 bytes of tile data, 2 byte pointer, 1 byte len specifier, 1 byte FF terminator
  91.    
  92. ;    TempAddress:    .DW 1
  93.  
  94.     MapBlipY:       .DSB $1     ; Stores the y-coordinate of the map blip
  95. .ende
  96. .enum $7F50
  97.     MapRam:     .DSB $10
  98.     MapSaveRam: .DSB $30
  99. .ende
  100.  
  101.  
  102. ; Registers
  103. ; ———
  104. PpuControl1     := $2000
  105. PpuControl2     := $2001
  106. PpuStatus       := $2002
  107. OamAddress      := $2003
  108. OamData         := $2004
  109. PpuScroll       := $2005
  110. PpuAddress      := $2006
  111. PpuData         := $2007
  112.  
  113.  
  114.  
  115. ; ===========================================================
  116. ;  "AUTOMAP BY SNARF"
  117. ; ===========================================================
  118. ; Adds by-line to title screen
  119.  
  120. .PATCH $1A8C5
  121. .db $0A, $1E, $1D, $18, $16, $0A, $19, $24, $00, $2C, $02, $24, $0B, $22, $24, $1C, $17, $0A, $1B, $0F
  122. ;    A    U    T    O    M    A    P         0    .    1         B    Y         S    N    A    R    F
  123.  
  124.  
  125. ;========================================================
  126. ; Map blip blinking
  127. ;========================================================
  128.  
  129. ; New blip pattern
  130. .PATCH $846F
  131. .HEX e0 e0 e0 00 00 00 00 00 e0 a0 e0 00 00 00 00 00
  132.  
  133. ; Corrects positioning of map blip
  134. ;   :71F7:     LDA #$11       ; A = left edge of map
  135.  
  136. ; Blip update routine
  137. ; ——————-
  138. .PATCH 05:BC00
  139. BlipUpdate:
  140.     PHA
  141.    
  142.     ; Exit if in a dungeon
  143.     LDA LevelNumber
  144.     BNE exitHijack
  145.    
  146.     ; Grab the current blip position if it is on-screen
  147.     LDA OAM_MapBlipY
  148.     CMP #$FF
  149.     BEQ +
  150.         STA MapBlipY
  151.     *
  152.  
  153. OW_BlipUpdate:
  154.     LDA $15 ; Get frame counter
  155.    
  156.     ; Blink every 32 frames
  157.     LSR
  158.     LSR
  159.     LSR
  160.     LSR
  161.     LSR
  162.     BCC +
  163.    
  164.     ; Show blip
  165.     LDA MapBlipY
  166.     STA OAM_MApBlipY
  167.     BNE exitHijack
  168.    
  169.     ; Hide blip
  170. *   LDA #$FF
  171.     STA OAM_MapBlipY
  172.    
  173. exitHijack:
  174.     PLA
  175.     JMP $77E7
  176.    
  177.    
  178. ; Hijack
  179. ; ——
  180. .PATCH 07:F322 ; Per-frame update hijack    
  181.     JSR SafeBlipUpdate
  182.  
  183.    
  184. ; SafeBlipUpdate
  185. ; ————–
  186.  
  187. ;This routine is placed after DoWholeMapHijack (under "Draw whole map -HIJACK-") below
  188. ;because these two functions must be placed in the fixed bank, together in the small available space.
  189.  
  190.    
  191.    
  192.    
  193. ; ===========================================================
  194. ;  New heart data
  195. ; ===========================================================
  196.  
  197. ; New heart PPU macros
  198. ; ——————–
  199. ; The PPU addresses of these macros have been swapped so that the hearts fill the top row before the bottom row.
  200.  
  201. .PATCH $6517
  202. ; First row of hearts
  203. .db $20, $D6
  204. .db $08
  205. .db $24, $24, $24, $24, $24, $24, $24, $24
  206.  
  207. ; Second row of hearts
  208. .db $20, $B6
  209. .db $08
  210. .db $24, $24, $24, $24, $24, $24, $24, $24
  211.  
  212. ; "-LIFE-" (unchanged)
  213. .PATCH $1bF1E
  214. .db $62, $15, $12, $0F, $0E, $62
  215.  
  216.  
  217. ; New heart tiles
  218. ; —————
  219. .PATCH $8C8F
  220. .HEX 6c ee ee ee fe 7c 38 10 6c 9e de fe fe 7c 38 10 ; Partial hearts
  221. .HEX 6c ee ee ee fe 7c 38 10 6c 9e 9e 9e fe 7c 38 10
  222. .HEX 6c ee ee ee ee 5c 38 10 6c 9e 9e 9e 9e 7c 38 10
  223. .HEX 6c ee ee ee ee 6c 38 10 6c 9e 9e 9e 9e 5c 28 10
  224. .HEX 6c fe ee ee f6 7c 38 10 6c 9e 9e 9e 8e 44 28 10
  225. .HEX 6c fe ee fe fe 7c 38 10 6c 9e 9e 82 82 44 28 10
  226. .HEX 6c fa e6 fe fe 7c 38 10 6c 9e 9a 82 82 44 28 10
  227. .HEX 6c fa e6 fe fe 7c 38 10 6c 9e 9a 82 82 44 28 10
  228. .HEX 6c 9e 9a b2 f2 6c 00 00 00 00 00 00 00 00 00 00
  229.  
  230. .PATCH $8E8F
  231. .HEX 6c fe fe fe fe 7c 38 10 6c 92 82 82 82 44 28 10 ; Whole heart
  232.  
  233. ; Magic key tile index
  234. ; ——————–
  235. ; This byte specifies the tile index to use for the key count when player has the magic key
  236. .PATCH $65b2
  237. .db $58
  238.  
  239.  
  240.  
  241.  
  242. ; ===========================================================
  243. ;  Map PPU macros
  244. ; ===========================================================
  245. ; New tilemap for the map to allow each tile to be unique.
  246.  
  247. .PATCH $1935F
  248. ; Whole overworld map
  249. .db $20, $62
  250. .db $08
  251. ;.db $30,$30,$30,$30,$30,$30,$30,$30
  252. .db $30, $31, $32, $33, $34, $35, $36, $37
  253.  
  254. .db $20, $82
  255. .db $08
  256. ;.db $30,$30,$30,$30,$30,$30,$30,$30
  257. .db $38, $39, $3A, $3B, $3C, $3D, $3E, $3F
  258.  
  259. .db $20, $A2
  260. .db $08
  261. ;.db $30,$30,$30,$30,$30,$30,$30,$30
  262. .db $40, $41, $42, $43, $44, $45, $46, $47
  263.  
  264. .db $20, $C2
  265. .db $08
  266. ;.db $30,$30,$30,$30,$30,$30,$30,$30
  267. .db $48, $49, $4A, $4B, $4C, $4D, $4E, $4F
  268.  
  269. .db $FF
  270.  
  271.  
  272. ; ===========================================================
  273. ;  New Map Attribute
  274. ; ===========================================================
  275. ; Used to apply the proper palette for the overworld map.
  276.  
  277. ; This is the original routine that queues the PPU macro that sets HUD palettes
  278. ;05:B005:A9 18     LDA #$18
  279. ;05:B007:D0 0F     BNE $B018
  280. ;05:B009:A9 D0     LDA #$D0
  281. ;05:B00B:A0 17     LDY #$17
  282. ;05:B00D:4C 01 85  JMP $8501
  283. ;05:B010:A9 E8     LDA #$E8
  284. ;05:B012:A0 2F     LDY #$2F
  285. ;05:B014:D0 F7     BNE $B00D
  286. ;05:B016:A9 0E     LDA #$0E
  287. ;05:B018:85 14     STA $0014 = #$00
  288. ;05:B01A:E6 13     INC $0013 = #$05
  289. ;05:B01C:60        RTS
  290.  
  291. OriginalHudAttributeMacro = $A2D3
  292.  
  293. .PATCH 05:B01A
  294.     ; Hijack the routine that queues the attribute macro
  295.     JMP NewHudMacroSelector
  296.    
  297.  
  298. .PATCH 05:AF20
  299.  
  300. ; Map palette selection routine
  301. ; —————————–
  302. ; If the overworld map attribute macro is queued in a level, we swap in the
  303. ; dungeon map attribute macro (since we’ve changed the overworld map macro)
  304.  
  305. NewHudMacroSelector:
  306. ; Skip this routine for overworld
  307.     LDA LevelNumber
  308.     BEQ +
  309.    
  310.     ; Only run this routine if the pending macro is the HUD attribute macro
  311.     LDA PendingPpuMacro
  312.     CMP #$0E
  313.     BNE +
  314.  
  315.     ; Change 0E to 7E to load dungeon hud attributes    
  316.     LDA #$7E
  317.     STA PendingPpuMacro
  318.    
  319. *   INC $13
  320.     RTS
  321.  
  322. ; Modifications to PPU macro pointer table
  323. ; —————————————-
  324. ; Pointer to below attributes (new overworld attribute macro)
  325. .PATCH 06:A00E
  326.     .DW OverworldAttributeData      ; New overworld map attribute macro
  327. .PATCH 06:A07E
  328.     .DW OriginalHudAttributeMacro   ; Original attribute macro to be used for dungeons
  329.    
  330.    
  331.    
  332. ; New attribute data    
  333. ; ——————
  334. .PATCH 06:BEF0
  335. OverworldAttributeData:
  336.    
  337.     ; New data to change map colors
  338.     .DB $23, $C0
  339.     .DB $10
  340.     .DB $C0, $FF, $70, $00, $00, $44, $55, $55, $FF, $FF, $37, $00, $00, $44, $55, $55
  341.  
  342.     ; This is additional macros from the original data. It needs to be part of the same PPU macro string.
  343.     .DB $20, $6F, $0E, $69, $0B, $6B, $69, $0A, $6B, $24, $24, $62, $15, $12, $0F, $0E
  344.     .DB $62, $20, $CF, $06, $6E, $6A, $6D, $6E, $6A, $6D, $20, $8F, $C2, $6C, $20, $91
  345.     .DB $C2, $6C, $20, $92, $C2, $6C, $20, $94, $C2, $6C, $20, $6B, $84, $F7, $24, $F9
  346.     .DB $61, $FF, $29, $84, $09, $12, $17, $1F, $0E, $17, $1D, $18, $1B, $22
  347.  
  348.     ; Terminator
  349.     .DB $FF
  350.    
  351.  
  352. ;========================================================
  353. ; Save/Load/Delete Hijacks
  354. ;========================================================
  355.  
  356. ; Save Hijack
  357. ; ———–
  358. ;   02:A77A:    JSR $9D2A
  359. .PATCH 02:A77A
  360.     JSR SaveMapData
  361.     SaveHijackReturn = $9D2A
  362.  
  363.  
  364. ; Load Hijack
  365. ; ———–
  366. ;   02:A5FE:    JSR $E625
  367. .PATCH 02:A5FE
  368.     JSR LoadMapData
  369.     LoadHijackReturn = $E625
  370.  
  371.    
  372. ; Delete Map Hijack – Register Name
  373. ; ————————————
  374.    ;02:A2C7:  JSR $A764 = File creation hijack
  375. .PATCH 02:A2C7
  376.     JSR DeleteMap_RegisterName
  377.  
  378.    
  379. ; Delete Map Hijack 2 – Second Quest
  380. ; ———————————-
  381.    ;02:ABB5:  JMP $AF5A = Second quest hijack
  382. .PATCH 02:ABB5
  383.     JMP DeleteMap_SecondQuest
  384.  
  385.    
  386.    
  387. ;========================================================
  388. ; Save/Load/Delete routines
  389. ;========================================================
  390.  
  391. ; Save map data
  392. ; ————-
  393. .PATCH 02:B000
  394. SaveMapData:
  395.  
  396.     JSR PrepLoadSaveIndexers
  397.  
  398. *   LDA MapRam,X
  399.     STA MapSaveRam,Y
  400.    
  401.     DEY
  402.     DEX
  403.     BPL
  404.    
  405.     JMP SaveHijackReturn
  406.    
  407.    
  408. ; Load map data
  409. ; ————-
  410. LoadMapData:
  411.     JSR PrepLoadSaveIndexers
  412.  
  413. *   LDA MapSaveRam,Y
  414.     STA MapRam,X
  415.    
  416.     DEY
  417.     DEX
  418.     BPL
  419.  
  420.     JMP LoadHijackReturn
  421.    
  422.  
  423.     ; Delete routines
  424. ; —————
  425. DeleteMap_RegisterName:
  426.     JSR DeleteMap
  427.     JMP $A764       ; Return from hijack
  428.  
  429. DeleteMap_SecondQuest:
  430.     JSR DeleteMap
  431.     JMP $AF5A       ; Return from hijack
  432.  
  433.    
  434. ; Delete map data
  435. ; —————
  436. DeleteMap:
  437.  
  438.     LDX #$0F
  439.     LDA #$00
  440.    
  441. *   STA MapRam,X
  442.     DEX
  443.     BPL
  444.  
  445.     RTS    
  446.    
  447.    
  448. ; Common routines
  449. ; —————
  450. PrepLoadSaveIndexers:
  451. ; Sets the Y register to point to the end of the player’s map save data (MapSaveRam,Y),
  452. ; and sets X to point to the end of map data ram.
  453.  
  454.     LDY #$0F
  455.  
  456.     LDX SaveSlot    ; Save slot 1
  457.     BEQ +
  458.    
  459.     LDY #$1F        ; Save slot 2
  460.     DEX
  461.     BEQ +
  462.    
  463.     LDY #$2F        ; Save slot 3
  464.    
  465. *   LDX #$0F
  466.  
  467.     RTS
  468.    
  469.    
  470.  
  471. ;========================================================
  472. ; Updating map spot
  473. ;========================================================
  474. ; Updates a single tile on the map as the player walks around
  475.  
  476.  
  477. ; Hijack
  478. ; ——
  479. .PATCH 05:A8BE
  480.     ;05:A8BE:20 F4 A9  JSR $A9F4
  481.     UpdateMapSpotReturn = $A9F4
  482.     JSR UpdateMapSpot ;$85A0
  483.  
  484.    
  485. ; Update routine
  486. ; ————–
  487. .PATCH 05:85A0
  488. UpdateMapSpot:
  489.     ;JSR $752F           ; Displaced code
  490.  
  491.     ; Update map data
  492.     LDA CurrentMapLocation
  493.     AND #$0F            ; Get X-coordinate
  494.     TAX                 ; Used to index into map data
  495.    
  496.     LSR                 ; Push tile-X onto stack
  497.     PHA
  498.    
  499.     LDA CurrentMapLocation
  500.     LSR                 ; A /= 16 (get map Y)
  501.     LSR
  502.     LSR
  503.     LSR
  504.     TAY
  505.    
  506.     LSR
  507.     PHA                 ; Push Tile-Y onto stack
  508.    
  509.     ; Set bit for y location
  510.     LDA #$01
  511.     CPY #$00
  512.     BEQ ++
  513.    
  514. *   ASL
  515.     DEY
  516.     BNE
  517.     *
  518.    
  519.     ORA MapRam,X
  520.     STA MapRam,X
  521.  
  522.     ; Pull tile index into registers
  523.     PLA
  524.     TAY
  525.     PLA
  526.     TAX
  527.    
  528.     JSR UpdateMapTile
  529.    
  530.     ;RTS
  531.     JMP UpdateMapSpotReturn
  532.  
  533.  
  534.  
  535. ; ===========================================================
  536. ;  Update map tile
  537. ; ===========================================================    
  538. ;  Processes map data and invokes the rendering routine.
  539. ;  Used by "Update map spot" and "draw whole map" code
  540.  
  541. ;PlayerMapData = $7F50
  542. PpuMapMacroBase = $6BCD     ; Map macros
  543. SingleTileMacro = $6BFA     ; Single map tile macro
  544. SingleTileMacroByte = $6BFD
  545.  
  546. PpuMapMacroLen = $B     ; 11 Bytes: 8 tiles + 3-byte header
  547.  
  548. MapTiles = $30
  549.  
  550.  
  551. .PATCH 05:BC30
  552.  
  553. UpdateMapTile:
  554. ;————————-
  555. ; A – Unused
  556. ; X – Tile X
  557. ; Y – Tile Y
  558.  
  559.     STX mapVar_X
  560.     STY mapVar_Y
  561.  
  562.     TXA                     ; X = X * 2
  563.     ASL
  564.     TAX
  565.    
  566.     ; We need to extract four bits out of the player’s "explored map data"
  567.     ; and use them as a tile index
  568.     LDA MapRam,X     ; Load map byte
  569.     JSR ProcessMapByte      ; Get relevant two bits
  570.     STA mapVar              ; Store semi-calculated tile value
  571.     STA MapBits_Left
  572.  
  573.     LDY mapVar_Y
  574.  
  575.     LDA MapRam + 1,X ; Get next map byte
  576.     JSR ProcessMapByte      ; Get relevant two bits
  577.     STA MapBits_Right
  578.  
  579.  
  580.     ; Set flag to update single tile on screen
  581.     LDA #$01
  582.     STA tileFlag
  583.  
  584.     JSR RenderMapTile
  585.  
  586.     RTS
  587.    
  588.    
  589. ProcessMapByte:
  590.     ; Takes a player-map data byte and gets the relevant two bits out of it
  591.  
  592.     ; A – Map byte
  593.     ; Y – Map Tile Y
  594.     ; Return via A
  595.  
  596.     ; A = A >> (Y * 2) | 3
  597.     CPY #$00                ; While Y != 0
  598.     BEQ ++
  599. *   LSR                     ;   A >> 2
  600.     LSR
  601.     DEY                     ;   Y–
  602.     BNE
  603.    
  604. *   AND #$03                ; A
  605.  
  606.     RTS
  607.    
  608.    
  609.    
  610.    
  611. ; ===========================================================
  612. ;  Draw whole map
  613. ; ===========================================================    
  614.  
  615. DrawWholeMap:
  616.  
  617.     ; Prepare PPU to write map data
  618.     LDA $2002
  619.     LDA #>VRAM_MapTiles ; Set PPU address
  620.     STA $2006
  621.     LDA #<VRAM_MapTiles
  622.     STA $2006
  623.    
  624.  
  625.     LDA #$00                    ; Loop over Y
  626.     STA mapLoop_Y
  627.     *   LDA #$00                ;   Loop over X
  628.         STA mapLoop_X
  629.    
  630.         *   LDX mapLoop_X       ;       Render one map tile
  631.             LDY mapLoop_Y
  632.             JSR UpdateMapTile
  633.    
  634.             ;TYA
  635.             ;PHA
  636.             TXA                 ;       Send to PPU (preserve registers)
  637.             PHA
  638.             JSR SendTileToPPU
  639.             PLA
  640.             TAX
  641.             ;PLA
  642.             ;TAY
  643.    
  644.    
  645.             INC mapLoop_X
  646.             LDA mapLoop_X
  647.             CMP #$08
  648.         BNE
  649.    
  650.         INC mapLoop_Y
  651.         LDA mapLoop_Y
  652.         CMP #$04
  653.     BNE
  654.    
  655.     RTS
  656.    
  657.     SendTileToPPU:
  658.     LDX #$00
  659. *   LDA MapTileMacro+3,X    ; Load tile data byte
  660.     STA $2007               ; Write to PPU
  661.     INX
  662.     CPX #$10
  663.     BNE
  664.    
  665.     RTS
  666.    
  667.    
  668. ; ===========================================================
  669. ;  Map tile rendering
  670. ; ===========================================================    
  671.  
  672. RenderMapTile:
  673. ; Parameters
  674. ;   – mapVar_X :     Tile X
  675. ;   – mapVar_Y :     Tile Y
  676. ;   – mapBits_Left:  Bit-0 = TL screen discovered, Bit-1 = BL screen discovered
  677. ;   – mapBits_Right: Bit-0 = TR screen discovered, Bit-1 = BR  screen discovered
  678.  
  679.  
  680.     ; Preserve zp variables
  681.     LDA $00
  682.     PHA
  683.     LDA $01
  684.     PHA
  685.  
  686.     ; Calculate the source address of tile data, to copy to macro
  687.     ; and the PPU dest address to write to the macro.
  688.     ;
  689.     ; Address = BaseAddress + tileX * $10 + tileY * $80
  690.  
  691.     ; Y = tileY / 2
  692.     ; Set x to low byte of pointer (will be 00 or 80)
  693.     LDX #$00        ; Low byte of src/dest pointers
  694.     LDA mapVar_Y
  695.     LSR
  696.     TAY
  697.     BCC +           ; If carry was set (Y was odd), add 80 to low byte of pointers
  698.     LDX #$80
  699.  
  700. *   STX $00         ; Write low byte of pointer
  701.  
  702.     LDA mapVar_X    ; Add mapVar_X * #$10 to $00
  703.     ASL
  704.     ASL
  705.     ASL
  706.     ASL
  707.     CLC
  708.     ADC $00
  709.    
  710.     ; Write low byte of ROM source and PPU dest (low byte will be same on both)
  711.     STA $00
  712.     STA MapTileMacro + 1
  713.    
  714.     ; Calculate high byte of src pointer
  715.     TYA
  716.     ADC #$AD
  717.     STA $01
  718.    
  719.     ; Calculate high byte of dest pointer
  720.     TYA
  721.     ADC #$13
  722.     STA MapTileMacro
  723.    
  724.     ; Write macro-length
  725.     LDA #$10
  726.     STA MapTileMacro + 2
  727.    
  728.  
  729.    
  730.     ; Run this code twice to create two bit filters (to be ANDed) for tile data, one for top half, one for bottom
  731.     ; This "blacks out" map areas that have not been visited.
  732.     LDY #$00    
  733. MapBitLoop:
  734.         LDA #$FF
  735.         LSR MapBits_Left    ; Grab low bit (for top-left or bottom-left)
  736.         BCS +
  737.         AND #$0F            ; If clear, AND out high nibble
  738.        
  739.     *   LSR MapBits_Right   ; Grab low bit (for top-right or bottom-right)
  740.         BCS +
  741.         AND #$F0            ; If clear, AND out low nibble
  742.     *   STA MapFilter_Top,Y
  743.     INY
  744.     CPY #$02
  745.     BNE MapBitLoop
  746.    
  747.    
  748.    
  749.     ; Copy 10 bytes of tile data
  750.     ; We use four loops:
  751.     ;   -Top half, first plane
  752.     ;   -Bottom half, first plane
  753.     ;   -Top half, second plane
  754.     ;   -Bottom half, second plane
  755.     LDY #$03
  756.     *   LDA ($00),Y
  757.         AND MapFilter_Top
  758.         STA MapTileMacro + 3,Y
  759.  
  760.         DEY
  761.         BPL
  762.     LDY #$07
  763.     *   LDA ($00),Y
  764.         AND MapFilter_Bottom
  765.         STA MapTileMacro + 3,Y
  766.  
  767.         DEY
  768.         CPY #$03
  769.         BNE
  770.     LDY #$0B
  771.     *   LDA ($00),Y
  772.         AND MapFilter_Top
  773.         STA MapTileMacro + 3,Y
  774.  
  775.         DEY
  776.         CPY #$07
  777.         BNE    
  778.     LDY #$0F
  779.     *   LDA ($00),Y
  780.         AND MapFilter_Bottom
  781.         STA MapTileMacro + 3,Y
  782.  
  783.         DEY
  784.         CPY #$0B
  785.         BNE
  786.        
  787.     ; Write terminator to end of macro
  788.     LDA #$FF
  789.     STA MapTileMacro + $13
  790.    
  791.     ; Restore zero-page
  792.     PLA
  793.     STA $01
  794.     PLA
  795.     STA $00
  796.    
  797.     RTS
  798.    
  799.  
  800.    
  801.    
  802. ; ===========================================================
  803. ;  Partial heart routine
  804. ; ===========================================================  
  805.  
  806.  
  807. ; Partial heart routine
  808. ; ———————
  809.  
  810. PartialHeartRoutine:
  811. ;   Returns appropriate tile index in A
  812.  
  813.     LDA $0F     ; Load partial-heart value
  814.     LSR         ; Divide by $20 (into a range of 0-7)
  815.     LSR
  816.     LSR
  817.     LSR
  818.     LSR
  819.    
  820.     CLC
  821.     ADC #$50    ; Partial-heart tiles are # 50-57
  822.    
  823.     JMP $6ED7   ; Return from hijack
  824.    
  825.    
  826.      
  827. ; Hijack
  828. ; ——
  829.  
  830. ; Original code
  831. ; (1):6EC8:C9 80     CMP #$80          ; If partial-heart-value >= #$80, load full-heart-tile
  832. ;    :6ECA:B0 F4     BCS $6EC0        
  833. ;    :6ECC:A9 00     LDA #$00          ; ??????????????
  834. ;    :6ECE:8D 29 05  STA $0529    
  835. ; (2):6ED1:A9 65     LDA #$65          ; Load half-full heart tile
  836. ;    :6ED3:D0 02     BNE $6ED7         ; Branch always  
  837. ;
  838. ; (1) – Update value of CMP #$80 to run our partial heart routine for smaller increments
  839. ; (2) – Hijack goes here
  840.        
  841. .PATCH $6748
  842. .BASE  $6EC8    ; This code is run from RAM
  843.  
  844.     CMP #$F8
  845.     BCS $6EC0
  846.    
  847. *   LDA #$00
  848.     STA $0529
  849.    
  850.     JMP PartialHeartRoutine
  851.  
  852.  
  853.  
  854.  
  855.    
  856.  
  857. ; ===========================================================
  858. ;  Draw whole map -HIJACK-
  859. ; ===========================================================  
  860.  
  861. ; Original code
  862. ; ————-
  863. ;       Displaced code is called at end of DoWholeMapHijack routine
  864. ;        -06:8089:E6 11     INC $0011 = #$00
  865. ;         06:808B:60        RTS
  866.  
  867.  
  868. ; Hijack
  869. ; ——
  870. .PATCH 06:8089
  871.     JMP DoWholeMapHijack
  872.  
  873.  
  874. ; Hijack code
  875. ; ———–
  876. ; This routine must go in the fixed bank because bank-swapping is
  877. ; needed to run the desired code.
  878.  
  879. .PATCH  07:FFC0
  880. DoWholeMapHijack:    
  881.  
  882.     LDA LevelNumber ; Only run this routine for the overworld
  883.     BNE Exit
  884.  
  885.     ; Load bank 5
  886.     LDA #$05        ; The code we want to run is in a different bank than is currently loaded
  887.     JSR BankSwap
  888.  
  889.     JSR DrawWholeMap
  890.  
  891.     ; Load bank 6    
  892.     LDA #$06        ; This is the bank that was previously loaded
  893.     JSR BankSwap
  894.    
  895. Exit:
  896.     ; Displaced code
  897.     INC $11
  898.     RTS
  899.    
  900.  
  901. ; Safe blip update
  902. ; —————-
  903. ;
  904. ; This code really  belongs under the "Map blip blinking" section, but is placed with DoWholeMapHijack, because
  905. ; they need to be placed together in the tiny bit of free space in the fixed bank.
  906.  
  907. .PATCH 07:FFD6
  908. SafeBlipUpdate:
  909. ; Only runs the blip-flashing code when it is banked in.
  910.  
  911.     PHA         ; Need to preserve A
  912.     LDA $8000
  913.     CMP #$20    ; Is this bank 5? (checking for a known value)
  914.    
  915.     BNE +
  916.    
  917.     PLA
  918.     JMP BlipUpdate
  919.    
  920. *   PLA
  921.     JMP $77E7
  922.    
  923.  
  924. ; ===========================================================
  925. ;  PPU Transfers
  926. ; ===========================================================
  927. ;WholeMapMacro = $6BCD
  928.  
  929.  
  930. ; PPU update hijack
  931. ; —————–
  932. ;       07:E4C1:      JSR $A080
  933. .Patch 07:E4C1
  934.     JSR $9D70
  935.  
  936. ; PPU Trasnfer
  937. ; ————
  938. .PATCH 06:9D70
  939.  
  940.     ; Call displaced code
  941.     JSR $A080  
  942.  
  943.     lda LevelNumber         ; If we aren’t in overworld, clear flag and return
  944.     bne ClearAndReturn
  945.  
  946.     ; this bit is from the old automap (without an actual image of overworld)
  947.     ldx tileFlag    
  948.     beq return              ; If there is no pending tile, return
  949. ;    dex
  950. ;    beq UpdateOneTile       ; A value of 1 indicates one tile will be updated
  951. ;    dex
  952. ;    beq UpdateAllTiles      ; A value of 2 indicates whole map will be updated
  953. ;    rts                     ; Invalid value    
  954.  
  955. UpdateOneTile:
  956.     lda #<MapTileMacro
  957.     sta $00
  958.     lda #>MapTileMacro
  959.     sta $01
  960.     JSR SendPpuMacro
  961.    
  962. ClearAndReturn:
  963.     lda #$00        ; Clear tile flag
  964.     sta TileFlag
  965.    
  966.     return:
  967.     RTS
  968.  
  969. ; from old map
  970. ;UpdateAllTiles:
  971. ;    lda #<WholeMapMacro
  972. ;    sta $00
  973. ;    lda #>WholeMapMacro
  974. ;    sta $01
  975. ;    JSR SendPpuMacro
  976. ;    
  977. ;    JMP ClearAndReturn
  978.  
  979.  
  980.    
  981. ; ===========================================================
  982. ;  Fast life fill
  983. ; ===========================================================
  984. ; Causes life to fill faster with potion/fairy
  985.  
  986. ; ORIGINAL CODE
  987. ;   05:B1EF   LDA $0670             ; If current heart > #$F8 (out of #$100):
  988. ;   05:B1F2   CMP #$F8              ;
  989. ;   05:B1F4   BCS $B1FD             ;   Jump to routine to set current heart to 0 and increment full-heart count
  990. ;
  991. ;   05:B1F6   CLC                   ; Add #$06 to current heart value (out of #$100), and return
  992. ;   05:B1F7   ADC #$06              ;
  993. ;   05:B1F9   STA $0670             ;
  994. ;   05:B1FC   RTS                   ;
  995.  
  996.  
  997. ;.ORG $B1EF
  998. ;.PATCH $171FF
  999. .PATCH 05:B1EF
  1000.     LDA $0670
  1001.     CMP #$D7              ;
  1002.     BCS $B1FD             ;   Jump to routine to set current heart to 0 and increment full-heart count
  1003.  
  1004.     CLC                   ; Add #$06 to current heart value (out of #$100), and return
  1005.     ADC #$18              ;
  1006.     STA $0670             ;
  1007.     RTS                   ;
Leave a comment

1 Comments.

  1. Realy impressed with your work.
    too bad the automap doesn’t fully work on the PRG1 or EU version of the game. It works untill you enter a dungeon, then the life heart turns blue, the stats for bombs, keys etc blanks out and the game crashes when you try to go into another dungeon room…

Leave a Reply

Your email address will not be published. Required fields are marked *