From 839982c7bdd2a6f691d03844cc066f45337e93b6 Mon Sep 17 00:00:00 2001 From: Christophe Parent Date: Wed, 13 Dec 2023 00:22:53 -0800 Subject: [PATCH] Move area and enemy data to Bank 1 --- src/linker.cfg | 5 ++- src/main.asm | 108 ++++++++++++++++++++++++++++++++----------------- 2 files changed, 74 insertions(+), 39 deletions(-) diff --git a/src/linker.cfg b/src/linker.cfg index 24a4491..ac83dba 100644 --- a/src/linker.cfg +++ b/src/linker.cfg @@ -16,10 +16,13 @@ SEGMENTS { BSS: load = RAM, type = bss, optional = yes; HEADER: load = HDR, type = ro; STARTUP: load = PRG0, type = ro; + BANK0: load = PRG0, type = ro, optional = yes; + AREADATA: load = PRG1, type = ro, optional = yes; + ENEMYDATA: load = PRG1, type = ro, optional = yes; CHARS: load = PRG2, type = ro, optional = yes; COPYCHARS: load = PRG2, type = ro, optional = yes; SOUNDENGINE: load = PRG2, type = ro, optional = yes; - CODE: load = PRG3, type = ro, optional = yes; + BANK3: load = PRG3, type = ro, optional = yes; BANKSWITCH: load = PRG3, type = ro, optional = yes; VECTORS: load = PRGV, type = ro; } diff --git a/src/main.asm b/src/main.asm index 09eda52..e6b890b 100644 --- a/src/main.asm +++ b/src/main.asm @@ -531,6 +531,7 @@ AltRegContentFlag = $07ca CurrentBank = $15 ; The mapper is read-only; need to track its state separately CharsCopy = $41 ; Reserving $41 and $42 +XStore = $43 ; To store the X register ;------------------------------------------------------------------------------------- ;CONSTANTS @@ -3298,13 +3299,13 @@ ProcADLoop: stx ObjectOffset lda #$00 ;reset flag sta BehindAreaParserFlag ldy AreaDataOffset ;get offset of area data pointer - lda (AreaData),y ;get first byte of area object + jsr AreaDataBankSwitch ;get first byte of area object cmp #$fd ;if end-of-area, skip all this crap beq RdyDecode lda AreaObjectLength,x ;check area object buffer flag bpl RdyDecode ;if buffer not negative, branch, otherwise iny - lda (AreaData),y ;get second byte of area object + jsr AreaDataBankSwitch ;get second byte of area object asl ;check for page select bit (d7), branch if not set bcc Chk1Row13 lda AreaObjectPageSel ;check page select @@ -3312,19 +3313,19 @@ ProcADLoop: stx ObjectOffset inc AreaObjectPageSel ;if not already set, set it now inc AreaObjectPageLoc ;and increment page location Chk1Row13: dey - lda (AreaData),y ;reread first byte of level object + jsr AreaDataBankSwitch ;reread first byte of level object and #$0f ;mask out high nybble cmp #$0d ;row 13? bne Chk1Row14 iny ;if so, reread second byte of level object - lda (AreaData),y + jsr AreaDataBankSwitch dey ;decrement to get ready to read first byte and #%01000000 ;check for d6 set (if not, object is page control) bne CheckRear lda AreaObjectPageSel ;if page select is set, do not reread bne CheckRear iny ;if d6 not set, reread second byte - lda (AreaData),y + jsr AreaDataBankSwitch and #%00011111 ;mask out all but 5 LSB and store in page control sta AreaObjectPageLoc inc AreaObjectPageSel ;increment page select @@ -3349,7 +3350,8 @@ ProcLoopb: dex ;decrement buffer offset lda BehindAreaParserFlag ;check for flag set if objects were behind renderer bne ProcessAreaData ;branch if true to load more level data, otherwise lda BackloadingFlag ;check for flag set if starting right of page $00 - bne ProcessAreaData ;branch if true to load more level data, otherwise leave + beq EndAParse ;branch if true to load more level data, otherwise leave + jmp ProcessAreaData EndAParse: rts IncAreaObjOffset: @@ -3364,7 +3366,7 @@ DecodeAreaData: bmi Chk1stB ldy AreaObjOffsetBuffer,x ;if not, get offset from buffer Chk1stB: ldx #$10 ;load offset of 16 for special row 15 - lda (AreaData),y ;get first byte of level object again + jsr AreaDataBankSwitch ;get first byte of level object again cmp #$fd beq EndAParse ;if end of level, leave this routine and #$0f ;otherwise, mask out low nybble @@ -3387,10 +3389,10 @@ ChkRow13: cmp #$0d ;row 13? lda #$22 ;if so, load offset with 34 sta $07 iny ;get next byte - lda (AreaData),y + jsr AreaDataBankSwitch and #%01000000 ;mask out all but d6 (page control obj bit) beq LeavePar ;if d6 clear, branch to leave (we handled this earlier) - lda (AreaData),y ;otherwise, get byte again + jsr AreaDataBankSwitch ;otherwise, get byte again and #%01111111 ;mask out d7 cmp #$4b ;check for loop command in low nybble bne Mask2MSB ;(plus d6 set for object other than page control) @@ -3400,18 +3402,18 @@ Mask2MSB: and #%00111111 ;mask out d7 and d6 ChkSRows: cmp #$0c ;row 12-15? bcs SpecObj iny ;if not, get second byte of level object - lda (AreaData),y + jsr AreaDataBankSwitch and #%01110000 ;mask out all but d6-d4 bne LrgObj ;if any bits set, branch to handle large object lda #$16 sta $07 ;otherwise set offset of 24 for small object - lda (AreaData),y ;reload second byte of level object + jsr AreaDataBankSwitch ;reload second byte of level object and #%00001111 ;mask out higher nybble and jump jmp NormObj LrgObj: sta $00 ;store value here (branch for large objects) cmp #$70 ;check for vertical pipe object bne NotWPipe - lda (AreaData),y ;if not, reload second byte + jsr AreaDataBankSwitch ;if not, reload second byte and #%00001000 ;mask out all but d3 (usage control bit) beq NotWPipe ;if d3 clear, branch to get original value lda #$00 ;otherwise, nullify value for warp pipe @@ -3419,7 +3421,7 @@ LrgObj: sta $00 ;store value here (branch for large objects NotWPipe: lda $00 ;get value and jump ahead jmp MoveAOId SpecObj: iny ;branch here for rows 12-15 - lda (AreaData),y + jsr AreaDataBankSwitch and #%01110000 ;get next byte and mask out all but d6-d4 MoveAOId: lsr ;move d6-d4 to lower nybble lsr @@ -3432,7 +3434,7 @@ NormObj: sta $00 ;store value here (branch for small objects cmp CurrentPageLoc ;same page as the renderer, and if so, branch beq InitRear ldy AreaDataOffset ;if not, get old offset of level pointer - lda (AreaData),y ;and reload first byte + jsr AreaDataBankSwitch ;and reload first byte and #%00001111 cmp #$0e ;row 14? bne LeavePar @@ -3447,7 +3449,7 @@ InitRear: lda BackloadingFlag ;check backloading flag to see if it's been sta ObjectOffset LoopCmdE: rts BackColC: ldy AreaDataOffset ;get first byte again - lda (AreaData),y + jsr AreaDataBankSwitch and #%11110000 ;mask out low nybble and move high to low lsr lsr @@ -3530,7 +3532,7 @@ RunAObj: lda $00 ;get stored value and add offset to it AlterAreaAttributes: ldy AreaObjOffsetBuffer,x ;load offset for level object data saved in buffer iny ;load second byte - lda (AreaData),y + jsr AreaDataBankSwitch pha ;save in stack for now and #%01000000 bne Alter2 ;branch if d6 is set @@ -4280,11 +4282,11 @@ LenSet: rts GetLrgObjAttrib: ldy AreaObjOffsetBuffer,x ;get offset saved from area obj decoding routine - lda (AreaData),y ;get first byte of level object + jsr AreaDataBankSwitch ;get first byte of level object and #%00001111 sta $07 ;save row location iny - lda (AreaData),y ;get next byte, save lower nybble (length or height) + jsr AreaDataBankSwitch ;get next byte, save lower nybble (length or height) and #%00001111 ;as Y, then leave tay rts @@ -4392,7 +4394,7 @@ GetAreaDataAddrs: lda AreaDataAddrHigh,y sta AreaDataHigh ldy #$00 ;load first byte of header - lda (AreaData),y + jsr AreaDataBankSwitch pha ;save it to the stack for now and #%00000111 ;save 3 LSB for foreground scenery or bg color control cmp #$04 @@ -4415,7 +4417,7 @@ StoreFore: sta ForegroundScenery ;if less, save value here as foreground sce rol sta GameTimerSetting ;save value here as game timer setting iny - lda (AreaData),y ;load second byte of header + jsr AreaDataBankSwitch ;load second byte of header pha ;save to stack and #%00001111 ;mask out all but lower nybble sta TerrainControl @@ -4512,6 +4514,8 @@ AreaDataAddrHigh: .byte >L_GroundArea22, >L_UndergroundArea1, >L_UndergroundArea2, >L_UndergroundArea3, >L_CastleArea1 .byte >L_CastleArea2, >L_CastleArea3, >L_CastleArea4, >L_CastleArea5, >L_CastleArea6 +.segment "ENEMYDATA" + ;ENEMY OBJECT DATA ;level 1-4/6-4 @@ -4761,6 +4765,8 @@ E_WaterArea3: .byte $56, $07, $88, $1b, $07, $9d, $2e, $65, $f0 .byte $ff +.segment "AREADATA" + ;AREA OBJECT DATA ;level 1-4/6-4 @@ -5271,6 +5277,8 @@ L_WaterArea3: .byte $4e, $0f, $ed, $47 .byte $fd +.segment "BANK0" + ;------------------------------------------------------------------------------------- ;unused space @@ -7689,7 +7697,7 @@ RedPTroopaGrav: ldx ObjectOffset ;get enemy object offset and leave rts -.segment "CODE" +.segment "BANK3" ;------------------------------------------------------------------------------------- ;$00 - used for downward force @@ -7880,7 +7888,7 @@ ChkEnemyFrenzy: ProcessEnemyData: ldy EnemyDataOffset ;get offset of enemy object data - lda (EnemyData),y ;load first byte + jsr EnemyDataBankSwitch ;load first byte cmp #$ff ;check for EOD terminator bne CheckEndofBuffer jmp CheckFrenzyBuffer ;if found, jump to check frenzy buffer, otherwise @@ -7892,7 +7900,7 @@ CheckEndofBuffer: cpx #$05 ;check for end of buffer bcc CheckRightBounds ;if not at end of buffer, branch iny - lda (EnemyData),y ;check for specific value here + jsr EnemyDataBankSwitch ;check for specific value here and #%00111111 ;not sure what this was intended for, exactly cmp #$2e ;this part is quite possibly residual code beq CheckRightBounds ;but it has the effect of keeping enemies out of @@ -7909,7 +7917,7 @@ CheckRightBounds: sta $06 ;store page location + carry ldy EnemyDataOffset iny - lda (EnemyData),y ;if MSB of enemy object is clear, branch to check for row $0f + jsr EnemyDataBankSwitch ;if MSB of enemy object is clear, branch to check for row $0f asl bcc CheckPageCtrlRow lda EnemyObjectPageSel ;if page select already set, do not set again @@ -7919,14 +7927,14 @@ CheckRightBounds: CheckPageCtrlRow: dey - lda (EnemyData),y ;reread first byte + jsr EnemyDataBankSwitch ;reread first byte and #$0f cmp #$0f ;check for special row $0f bne PositionEnemyObj ;if not found, branch to position enemy object lda EnemyObjectPageSel ;if page select set, bne PositionEnemyObj ;branch without reading second byte iny - lda (EnemyData),y ;otherwise, get second byte, mask out 2 MSB + jsr EnemyDataBankSwitch ;otherwise, get second byte, mask out 2 MSB and #%00111111 sta EnemyObjectPageLoc ;store as page control for enemy object data inc EnemyDataOffset ;increment enemy object data offset 2 bytes @@ -7937,14 +7945,14 @@ CheckPageCtrlRow: PositionEnemyObj: lda EnemyObjectPageLoc ;store page control as page location sta Enemy_PageLoc,x ;for enemy object - lda (EnemyData),y ;get first byte of enemy object + jsr EnemyDataBankSwitch ;get first byte of enemy object and #%11110000 sta Enemy_X_Position,x ;store column position cmp ScreenRight_X_Pos ;check column position against right boundary lda Enemy_PageLoc,x ;without subtracting, then subtract borrow sbc ScreenRight_PageLoc ;from page location bcs CheckRightExtBounds ;if enemy object beyond or at boundary, branch - lda (EnemyData),y + jsr EnemyDataBankSwitch and #%00001111 ;check for special row $0e cmp #$0e ;if found, jump elsewhere beq ParseRow0e @@ -7958,7 +7966,7 @@ CheckRightExtBounds: bcc CheckFrenzyBuffer ;if enemy object beyond extended boundary, branch lda #$01 ;store value in vertical high byte sta Enemy_Y_HighPos,x - lda (EnemyData),y ;get first byte again + jsr EnemyDataBankSwitch ;get first byte again asl ;multiply by four to get the vertical asl ;coordinate asl @@ -7967,19 +7975,19 @@ CheckRightExtBounds: cmp #$e0 ;do one last check for special row $0e beq ParseRow0e ;(necessary if branched to $c1cb) iny - lda (EnemyData),y ;get second byte of object + jsr EnemyDataBankSwitch ;get second byte of object and #%01000000 ;check to see if hard mode bit is set beq CheckForEnemyGroup ;if not, branch to check for group enemy objects lda SecondaryHardMode ;if set, check to see if secondary hard mode flag beq Inc2B ;is on, and if not, branch to skip this object completely CheckForEnemyGroup: - lda (EnemyData),y ;get second byte and mask out 2 MSB + jsr EnemyDataBankSwitch ;get second byte and mask out 2 MSB and #%00111111 - cmp #$37 ;check for value below $37 + cmp #$37 ;check for value below $37 bcc BuzzyBeetleMutate - cmp #$3f ;if $37 or greater, check for value - bcc DoGroup ;below $3f, branch if below $3f + cmp #$3f ;if $37 or greater, check for value + bcc DoGroup ;below $3f, branch if below $3f BuzzyBeetleMutate: cmp #Goomba ;if below $37, check for goomba @@ -8016,7 +8024,7 @@ DoGroup: ParseRow0e: iny ;increment Y to load third byte of object iny - lda (EnemyData),y + jsr EnemyDataBankSwitch lsr ;move 3 MSB to the bottom, effectively lsr ;making %xxx00000 into %00000xxx lsr @@ -8025,17 +8033,17 @@ ParseRow0e: cmp WorldNumber ;is it the same world number as we're on? bne NotUse ;if not, do not use (this allows multiple uses dey ;of the same area, like the underground bonus areas) - lda (EnemyData),y ;otherwise, get second byte and use as offset + jsr EnemyDataBankSwitch ;otherwise, get second byte and use as offset sta AreaPointer ;to addresses for level and enemy object data iny - lda (EnemyData),y ;get third byte again, and this time mask out + jsr EnemyDataBankSwitch ;get third byte again, and this time mask out and #%00011111 ;the 3 MSB from before, save as page number to be sta EntrancePage ;used upon entry to area, if area is entered NotUse: jmp Inc3B CheckThreeBytes: ldy EnemyDataOffset ;load current offset for enemy object data - lda (EnemyData),y ;get first byte + jsr EnemyDataBankSwitch ;get first byte and #%00001111 ;check for special row $0e cmp #$0e bne Inc2B @@ -16358,6 +16366,30 @@ NonMaskableInterruptBankSwitch: jsr BankSwitchNoSave rti +AreaDataBankSwitch: + stx XStore + ldx #$01 + jsr BankSwitchNoSave + lda (AreaData),y + pha + ldx #$00 + jsr BankSwitchNoSave + pla + ldx XStore + rts + +EnemyDataBankSwitch: + stx XStore + ldx #$01 + jsr BankSwitchNoSave + lda (EnemyData),y + pha + ldx #$00 + jsr BankSwitchNoSave + pla + ldx XStore + rts + CopyCharsBankSwitch: ldx #$02 jsr BankSwitch