; ; global.macros ; BuGS ; ; Created by Jeremy Rand on 2020-07-30. ;Copyright © 2020 Jeremy Rand. All rights reserved. ; macro _drawDirtyGameRow &rowNum _drawDirtyGameRow_wait&rowNum anop ; This code loads into the accumulator the line currently being drawn to the ; screen by HW. It allows code to race just behind the beam and redraw the ; screen. ; ; Based on code found here: ; https://iigs.dreamhosters.com/gte/blitter.html ; ; Unlike that code, it does not change the baseline of the values. According ; to GS technote 39, this number ranges from $fa to $1ff. Scan line zero is ; $100 and scan line 199 is $1c7. We will race the beam by comparing to these ; offset numbers. ; ; Also according to that technote, it looks like these numbers are different ; in PAL mode. Do I need something here to handle PAL correctly? I switched ; my GS to 50Hz mode (startup/reboot with option held down to get the menu) ; and I didnt't detect any graphics glitches at all. I did notice that the ; game is noticably easier because things run a bit slower. If I do an online ; score system, I should record whether a score was gotten at 50Hz vs 60Hz. ; (and in fact, I have since implemented online high scores and record the ; frequency at which the game was played) lda >VERTICAL_COUNTER ; load the counter value and #$80ff ; mask out the VBL bits asl a ; shift the word around adc #0 ; move MSB -> LSB lcla &scanLineNum &scanLineNum seta &rowNum &scanLineNum seta &scanLineNum*8 &scanLineNum seta &scanLineNum+264 cmp #&scanLineNum blt _drawDirtyGameRow_wait&rowNum lcla &tileOffset &tileOffset seta &rowNum*50 lcla &lastTileOffset &lastTileOffset seta 50+&tileOffset .drawDirtyGameRowLoop lda tileDirty+&tileOffset beq _drawDirtyGameRow_skip&tileOffset stz tileDirty+&tileOffset ldy tileScreenOffset+&tileOffset lda tileType+&tileOffset jsl drawTile _drawDirtyGameRow_skip&tileOffset anop &tileOffset seta &tileOffset+2 aif &tileOffset<&lastTileOffset,.drawDirtyGameRowLoop mend macro _dirtyGameOrNonGameTile &tileOffset ldx &tileOffset cpx #RHS_FIRST_TILE_OFFSET bge _dirtyGameTile_nonGame&SYSCNT lda #TILE_STATE_DIRTY sta tileDirty,x bra _dirtyGameTile_skip&SYSCNT _dirtyGameTile_nonGame&SYSCNT anop lda tileDirty,x bne _dirtyGameTile_skip&SYSCNT lda #TILE_STATE_DIRTY sta tileDirty,x ldy numDirtyNonGameTiles txa sta dirtyNonGameTiles,y iny iny sty numDirtyNonGameTiles _dirtyGameTile_skip&SYSCNT anop mend macro _dirtyGameOrNonGameTileX &tileOffset ldy &tileOffset,x cpy #RHS_FIRST_TILE_OFFSET bge _dirtyGameTile_nonGame&SYSCNT lda #TILE_STATE_DIRTY sta tileDirty,y bra _dirtyGameTile_skip&SYSCNT _dirtyGameTile_nonGame&SYSCNT anop lda tileDirty,y bne _dirtyGameTile_skip&SYSCNT lda #TILE_STATE_DIRTY sta tileDirty,y tya ldy numDirtyNonGameTiles sta dirtyNonGameTiles,y iny iny sty numDirtyNonGameTiles _dirtyGameTile_skip&SYSCNT anop mend ; Pass the tile offset to mark as dirty in the X register macro _dirtyNonGameTile lda tileDirty,x bne _dirtyNonGameTile_skip&SYSCNT lda #TILE_STATE_DIRTY sta tileDirty,x ldy numDirtyNonGameTiles txa sta dirtyNonGameTiles,y iny iny sty numDirtyNonGameTiles _dirtyNonGameTile_skip&SYSCNT anop mend macro _overwriteGameTile &type lda #&type jsl overwriteGameTile mend macro _setGameTile &type lda #&type jsl setGameTile mend macro _highScoreRow &nthScore ldy #SETTINGS_HIGH_SCORE_OFFSET+HIGH_SCORE_SCORE_TEXT_OFFSET+&nthScore*SETTINGS_HIGH_SCORE_SIZE lda settings,y jsl asciiToTileType jsl setGameTile iny lda settings,y jsl asciiToTileType jsl setGameTile iny lda settings,y jsl asciiToTileType jsl setGameTile iny lda settings,y jsl asciiToTileType jsl setGameTile iny lda settings,y jsl asciiToTileType jsl setGameTile iny lda settings,y jsl asciiToTileType jsl setGameTile iny lda settings,y jsl asciiToTileType jsl setGameTile iny lda settings,y jsl asciiToTileType jsl setGameTile iny lda settings,y jsl asciiToTileType jsl setGameTile iny lda settings,y jsl asciiToTileType jsl setGameTile lda #TILE_EMPTY jsl setGameTile iny lda settings,y jsl asciiToTileType jsl setGameTile iny lda settings,y jsl asciiToTileType jsl setGameTile iny lda settings,y jsl asciiToTileType jsl setGameTile mend macro _globalHighScoreRow &nthScore ldy #&nthScore*SETTINGS_HIGH_SCORE_SIZE lda globalHighScores,y jsl asciiToTileType jsl setGameTile iny lda globalHighScores,y jsl asciiToTileType jsl setGameTile iny lda globalHighScores,y jsl asciiToTileType jsl setGameTile iny lda globalHighScores,y jsl asciiToTileType jsl setGameTile iny lda globalHighScores,y jsl asciiToTileType jsl setGameTile iny lda globalHighScores,y jsl asciiToTileType jsl setGameTile iny lda globalHighScores,y jsl asciiToTileType jsl setGameTile iny lda globalHighScores,y jsl asciiToTileType jsl setGameTile iny lda globalHighScores,y jsl asciiToTileType jsl setGameTile iny lda globalHighScores,y jsl asciiToTileType jsl setGameTile lda #TILE_EMPTY jsl setGameTile iny lda globalHighScores,y jsl asciiToTileType jsl setGameTile iny lda globalHighScores,y jsl asciiToTileType jsl setGameTile iny lda globalHighScores,y jsl asciiToTileType jsl setGameTile mend ; Update the score macro _incrementScore &increment lda playerNum asl a tax lda #&increment clc adc gameScore,x sta gameScore,x bcc _incrementScore_noCarry&SYSCNT inc gameScore+2,x _incrementScore_noCarry&SYSCNT anop ldx playerNum lda #&increment clc adc scoreWithin12000,x cmp #12000 blt _incrementScore_noExtraMan&SYSCNT sec sbc #12000 pha jsl playerAddLife pla ldx playerNum _incrementScore_noExtraMan&SYSCNT anop sta scoreWithin12000,x lda #&increment clc adc scoreWithin20000,x cmp #20000 blt _incrementScore_no2000&SYSCNT sec sbc #20000 inc scoreNum20000,x _incrementScore_no2000&SYSCNT anop sta scoreWithin20000,x mend ; Wait for the DOC to be ready macro _docWait _docWait_&SYSCNT anop lda >SOUND_CONTROL_REG bmi _docWait_&SYSCNT mend macro _writeReg ®,&value ldy ® lda &value jsr writeReg mend