Refactor to use .defines for many memory locations.
This commit is contained in:
parent
7b6cd3f583
commit
a0532f0429
222
pewpew.asm
222
pewpew.asm
@ -4,19 +4,53 @@
|
||||
|
||||
|
||||
|
||||
; Assumes 16-bit X & 8-bit A.
|
||||
; Memory layout:
|
||||
; 0000-000F: scratch space for functions.
|
||||
; 0010-0011: controller state of joypad #1.
|
||||
; 0012-0013: controller state of joypad #2.
|
||||
; 0014-0016: 24-bit counter of vblanks.
|
||||
; 0017-0019: RGB color values to use for background color, from [0-31].
|
||||
; 001A-001B: 16-bit pointer to next random byte.
|
||||
; [gap]
|
||||
; 0020-0021: (x, y) coordinates of player.
|
||||
; 0022: shot cooldown timer.
|
||||
; 0030-0032: enable / x / y of shot.
|
||||
;
|
||||
; Sprite table buffers -- copied each frame to OAM during VBlank, using DMA.
|
||||
; 0100-02FF: table 1 (4 bytes each: x/y coord, tile #, flip/priority/palette)
|
||||
; 0300-031F: table 2 (2 bits each: high x-coord bit, size)
|
||||
.define joy1 $10
|
||||
.define joy2 $12
|
||||
.define vBlankCounter $14
|
||||
.define backgroundRed $17
|
||||
.define backgroundGreen $18
|
||||
.define backgroundBlue $19
|
||||
.define randomBytePtr $1A
|
||||
.define playerX $40
|
||||
.define playerY $41
|
||||
.define shotCooldown $42
|
||||
.define shotData $50
|
||||
|
||||
; TODO(mcmillen): verify that we can relocate these without messing things up.
|
||||
.define spriteTableStart $100
|
||||
.define spriteTable1Size $200
|
||||
.define spriteTable2Start $300 ; TODO(mcmillen): use this.
|
||||
.define spriteTableSize $220
|
||||
|
||||
|
||||
; Stores result to A.
|
||||
; Assumes 16-bit X & 8-bit A.
|
||||
; Modifies X.
|
||||
; Updates $0018-$0019 to point at the next available random byte.
|
||||
; Updates randomBytePtr.
|
||||
.MACRO GetRandomByte
|
||||
ldx $18
|
||||
ldx randomBytePtr
|
||||
lda $028000, X ; $028000: beginning of ROM bank 2.
|
||||
inx
|
||||
cpx #$8000 ; This is the size of the entire ROM bank.
|
||||
bne +
|
||||
ldx #0
|
||||
+
|
||||
stx $18
|
||||
stx randomBytePtr
|
||||
.ENDM
|
||||
|
||||
|
||||
@ -26,25 +60,16 @@
|
||||
.SECTION "MainCode"
|
||||
|
||||
|
||||
; Memory layout:
|
||||
; 0000-000F: scratch space for functions.
|
||||
; 0010-0011: controller state of joypad #1.
|
||||
; 0012-0013: controller state of joypad #2.
|
||||
; 0014-0016: 24-bit counter of vblanks.
|
||||
; 0018-0019: 16-bit pointer to next random byte.
|
||||
; 0020-0021: (x, y) coordinates of player.
|
||||
; 0022-0024: RGB color values to use for background color, from [0-31].
|
||||
; 0025: shot cooldown timer.
|
||||
; 0030-0032: enable / x / y of shot.
|
||||
;
|
||||
; Sprite table buffers -- copied each frame to OAM during VBlank, using DMA.
|
||||
; 0100-02FF: table 1 (4 bytes each: x/y coord, tile #, flip/priority/palette)
|
||||
; 0300-031F: table 2 (2 bits each: high x-coord bit, size)
|
||||
|
||||
|
||||
Start:
|
||||
InitializeSNES
|
||||
|
||||
; By default we assume 16-bit X/Y and 8-bit A.
|
||||
; If any code wants to change this, it's expected to do so itself,
|
||||
; and to change them back to the defaults before returning.
|
||||
rep #%00010000 ; 16-bit X/Y.
|
||||
sep #%00100000 ; 8-bit A/B.
|
||||
|
||||
; Store zeroes to the controller status registers.
|
||||
; TODO(mcmillen): is this needed? I think the system will overwrite these
|
||||
; automatically.
|
||||
@ -96,12 +121,6 @@ LoadPaletteAndTileData:
|
||||
; quite helpful with palette / sprites / DMA, especially starting at
|
||||
; http://wiki.superfamicom.org/snes/show/Working+with+VRAM+-+Loading+the+Palette
|
||||
|
||||
; 16-bit X/Y registers. Used for DMA source address & transfer size, both of
|
||||
; which want 16-bit values.
|
||||
rep #%00010000
|
||||
; 8-bit A/B registers. Used for DMA source bank & destination address.
|
||||
sep #%00100000
|
||||
|
||||
; Initialize the palette memory in a loop.
|
||||
; We could also do this with a DMA transfer (like we do with the tile data
|
||||
; below), but it seems overkill for just a few bytes. :)
|
||||
@ -225,7 +244,7 @@ InitializeSpriteTables:
|
||||
; It uses the same approach we're using, in which we keep a buffer of the
|
||||
; sprite tables in RAM, and DMA the sprite tables to the system's OAM
|
||||
; during VBlank.
|
||||
rep #%00110000 ; 16-bit A/X/Y.
|
||||
rep #%00100000 ; 16-bit A.
|
||||
|
||||
ldx #$0000
|
||||
; Fill sprite table 1. 4 bytes per sprite, laid out as follows:
|
||||
@ -236,12 +255,12 @@ InitializeSpriteTables:
|
||||
; p: palette #
|
||||
lda #$01
|
||||
-
|
||||
sta $0100, X ; We keep our sprite table at $0100 and DMA it to OAM later.
|
||||
sta spriteTableStart, X
|
||||
inx
|
||||
inx
|
||||
inx
|
||||
inx
|
||||
cpx #$0200
|
||||
cpx #spriteTable1Size
|
||||
bne -
|
||||
|
||||
; Fill sprite table 2. 2 bits per sprite, like so:
|
||||
@ -250,10 +269,10 @@ InitializeSpriteTables:
|
||||
; Setting all the high bits keeps the sprites offscreen.
|
||||
lda #%0101010101010101
|
||||
-
|
||||
sta $0100, X
|
||||
sta spriteTableStart, X
|
||||
inx
|
||||
inx
|
||||
cpx #$0220
|
||||
cpx #spriteTableSize
|
||||
bne -
|
||||
|
||||
sep #%00100000 ; 8-bit A.
|
||||
@ -268,9 +287,9 @@ InitializeWorld:
|
||||
|
||||
; Player's initial starting location.
|
||||
lda #(256 / 4)
|
||||
sta $20
|
||||
sta playerX
|
||||
lda #((224 - 32) / 2)
|
||||
sta $21
|
||||
sta playerY
|
||||
rts
|
||||
|
||||
|
||||
@ -287,14 +306,10 @@ MainLoop:
|
||||
|
||||
JoypadDebug:
|
||||
; Load joypad registers into RAM for easier inspection.
|
||||
lda JOY1L
|
||||
sta $10
|
||||
lda JOY1H
|
||||
sta $11
|
||||
lda JOY2L
|
||||
sta $12
|
||||
lda JOY2H
|
||||
sta $13
|
||||
ldx JOY1L
|
||||
stx joy1
|
||||
ldx JOY2L
|
||||
stx joy2
|
||||
rts
|
||||
|
||||
|
||||
@ -306,104 +321,104 @@ JoypadUp:
|
||||
and #$08 ; Up
|
||||
cmp #$08
|
||||
bne JoypadDown ; Button not pressed.
|
||||
lda $21
|
||||
lda playerY
|
||||
cmp #0
|
||||
beq JoypadDown ; Value saturated.
|
||||
dec $21
|
||||
dec $21
|
||||
dec playerY
|
||||
dec playerY
|
||||
|
||||
JoypadDown:
|
||||
lda JOY1H
|
||||
and #$04
|
||||
cmp #$04
|
||||
bne JoypadLeft ; Button not pressed.
|
||||
lda $21
|
||||
lda playerY
|
||||
cmp #(224 - 32)
|
||||
beq JoypadLeft ; Value saturated.
|
||||
inc $21
|
||||
inc $21
|
||||
inc playerY
|
||||
inc playerY
|
||||
|
||||
JoypadLeft:
|
||||
lda JOY1H
|
||||
and #$02 ; Left
|
||||
cmp #$02
|
||||
bne JoypadRight ; Button not pressed.
|
||||
lda $20
|
||||
lda playerX
|
||||
cmp #0
|
||||
beq JoypadRight ; Value saturated.
|
||||
dec $20
|
||||
dec $20
|
||||
dec playerX
|
||||
dec playerX
|
||||
|
||||
JoypadRight:
|
||||
lda JOY1H
|
||||
and #$01
|
||||
cmp #$01 ; Right
|
||||
bne JoypadStart ; Button not pressed.
|
||||
lda $20
|
||||
lda playerX
|
||||
cmp #(256 - 32)
|
||||
beq JoypadStart ; Value saturated.
|
||||
inc $20
|
||||
inc $20
|
||||
inc playerX
|
||||
inc playerX
|
||||
|
||||
JoypadStart:
|
||||
lda JOY1H
|
||||
and #$10 ; Start
|
||||
cmp #$10
|
||||
bne JoypadSelect ; Button not pressed.
|
||||
lda $22
|
||||
lda backgroundRed
|
||||
cmp #0
|
||||
beq JoypadSelect ; Value saturated.
|
||||
dec $22
|
||||
dec backgroundRed
|
||||
|
||||
JoypadSelect:
|
||||
lda JOY1H
|
||||
and #$20 ; Select
|
||||
cmp #$20
|
||||
bne JoypadY ; Button not pressed.
|
||||
lda $22
|
||||
lda backgroundRed
|
||||
cmp #31
|
||||
beq JoypadY ; Value saturated.
|
||||
inc $22
|
||||
inc backgroundRed
|
||||
|
||||
JoypadY:
|
||||
lda JOY1H
|
||||
and #$40 ; Y
|
||||
cmp #$40
|
||||
bne JoypadX ; Button not pressed.
|
||||
lda $23
|
||||
lda backgroundGreen
|
||||
cmp #0
|
||||
beq JoypadX ; Value saturated.
|
||||
dec $23
|
||||
dec backgroundGreen
|
||||
|
||||
JoypadX:
|
||||
lda JOY1L
|
||||
and #$40 ; X
|
||||
cmp #$40
|
||||
bne JoypadL ; Button not pressed.
|
||||
lda $23
|
||||
lda backgroundGreen
|
||||
cmp #31
|
||||
beq JoypadL ; Value saturated.
|
||||
inc $23
|
||||
inc backgroundGreen
|
||||
|
||||
JoypadL:
|
||||
lda JOY1L
|
||||
and #$20 ; L
|
||||
cmp #$20
|
||||
bne JoypadR ; Button not pressed.
|
||||
lda $24
|
||||
lda backgroundBlue
|
||||
cmp #0
|
||||
beq JoypadR ; Value saturated.
|
||||
dec $24
|
||||
dec backgroundBlue
|
||||
|
||||
JoypadR:
|
||||
lda JOY1L
|
||||
and #$10 ; R
|
||||
cmp #$10
|
||||
bne JoypadB ; Button not pressed.
|
||||
lda $24
|
||||
lda backgroundBlue
|
||||
cmp #31
|
||||
beq JoypadB ; Value saturated.
|
||||
inc $24
|
||||
inc backgroundBlue
|
||||
|
||||
JoypadB:
|
||||
lda JOY1H
|
||||
@ -419,19 +434,19 @@ JoypadDone:
|
||||
|
||||
MaybeShoot:
|
||||
; If the cooldown timer is non-zero, don't shoot.
|
||||
lda $25
|
||||
lda shotCooldown
|
||||
cmp #0
|
||||
bne +
|
||||
; Enable shot; set its position to player position.
|
||||
lda #1
|
||||
sta $30
|
||||
lda $20
|
||||
sta $31
|
||||
lda $21
|
||||
sta $32
|
||||
sta shotData
|
||||
lda playerX
|
||||
sta shotData + 1
|
||||
lda playerY
|
||||
sta shotData + 2
|
||||
; Set cooldown timer.
|
||||
lda #16
|
||||
sta $25
|
||||
sta shotCooldown
|
||||
+
|
||||
rts
|
||||
|
||||
@ -439,17 +454,17 @@ MaybeShoot:
|
||||
|
||||
UpdateWorld:
|
||||
; Update shot cooldown.
|
||||
lda $0025
|
||||
lda shotCooldown
|
||||
cmp #0
|
||||
beq +
|
||||
dea
|
||||
sta $0025
|
||||
sta shotCooldown
|
||||
+
|
||||
|
||||
; Copy player coords into sprite table.
|
||||
lda $0020
|
||||
lda playerX
|
||||
sta $0100
|
||||
lda $0021
|
||||
lda playerY
|
||||
sta $0101
|
||||
; Set the sprite.
|
||||
lda #0
|
||||
@ -458,37 +473,37 @@ UpdateWorld:
|
||||
lda #%00110000
|
||||
sta $0103
|
||||
; Clear x-MSB so that the sprite is displayed.
|
||||
lda $0300
|
||||
lda spriteTable2Start
|
||||
and #%11111110
|
||||
ora #%00000010 ; ... and make it the large size. (32x32)
|
||||
sta $0300
|
||||
sta spriteTable2Start
|
||||
|
||||
; Move shot coords.
|
||||
ldx $0
|
||||
lda $30
|
||||
lda shotData
|
||||
cmp #1
|
||||
bne DisableShot
|
||||
|
||||
lda $31
|
||||
lda shotData + 1
|
||||
; TODO(mcmillen): do this with an add, then check the carry bit?
|
||||
.rept 6
|
||||
ina
|
||||
cmp #$00 ; If it wraps around, disable it.
|
||||
bne +
|
||||
stz $30
|
||||
stz shotData
|
||||
+
|
||||
.endr
|
||||
sta $0031 ; Store new x-coord.
|
||||
sta shotData + 1 ; Store new x-coord.
|
||||
|
||||
; See if sprite is still enabled after move.
|
||||
lda $0030
|
||||
lda shotData
|
||||
cmp #1
|
||||
bne DisableShot
|
||||
|
||||
; Set up shot sprite.
|
||||
lda $0031 ; x
|
||||
lda shotData + 1 ; x
|
||||
sta $0104
|
||||
lda $0032 ; y
|
||||
lda shotData + 2 ; y
|
||||
sta $0105
|
||||
lda #8 ; which sprite
|
||||
sta $0106
|
||||
@ -500,8 +515,9 @@ UpdateWorld:
|
||||
jmp ShotDone
|
||||
|
||||
DisableShot:
|
||||
; Disable it by setting x-position to zero and setting the high x-bit.
|
||||
stz $104
|
||||
; Disable it by setting x-position to 1 and setting the high x-bit.
|
||||
lda #1
|
||||
sta $104
|
||||
lda $0300
|
||||
ora #%00000100
|
||||
sta $0300
|
||||
@ -509,11 +525,11 @@ DisableShot:
|
||||
ShotDone:
|
||||
; Make the background scroll. Horizontal over time; vertical depending on
|
||||
; player's y-coordinate.
|
||||
lda $14
|
||||
lda vBlankCounter
|
||||
sta BG3HOFS
|
||||
lda $15
|
||||
lda vBlankCounter + 1
|
||||
sta BG3HOFS
|
||||
lda $21
|
||||
lda playerY
|
||||
.rept 3
|
||||
lsr
|
||||
.endr
|
||||
@ -525,7 +541,7 @@ ShotDone:
|
||||
|
||||
|
||||
SetBackgroundColor:
|
||||
; $22 $23 $24 are (R, G, B), each ranging from [0-31].
|
||||
; The background-color bytes are (R, G, B), each ranging from [0-31].
|
||||
; The palette color format is 15-bit: [0bbbbbgg][gggrrrrr]
|
||||
|
||||
; Set the background color.
|
||||
@ -533,20 +549,20 @@ SetBackgroundColor:
|
||||
stz CGADDR
|
||||
|
||||
; Compute and the low-order byte and store it in CGDATA.
|
||||
lda $23 ; Green.
|
||||
lda backgroundGreen
|
||||
.rept 5
|
||||
asl
|
||||
.endr
|
||||
ora $22 ; Red.
|
||||
ora backgroundRed
|
||||
sta CGDATA
|
||||
|
||||
; Compute the high-order byte and store it in CGDATA.
|
||||
lda $24 ; Blue.
|
||||
lda backgroundBlue
|
||||
.rept 2
|
||||
asl
|
||||
.endr
|
||||
sta $00
|
||||
lda $23 ; Green.
|
||||
lda backgroundGreen
|
||||
.rept 3
|
||||
lsr
|
||||
.endr
|
||||
@ -565,25 +581,23 @@ VBlankHandler:
|
||||
|
||||
VBlankCounter:
|
||||
; Increment a counter of how many VBlanks we've done.
|
||||
; This is a 24-bit counter. At 60 vblanks/second, this will take over
|
||||
; This is a 24-bit counter. At 60 vblanks/second, this will take
|
||||
; 77 hours to wrap around; that's good enough for me :)
|
||||
inc $14
|
||||
lda $14
|
||||
inc vBlankCounter
|
||||
lda vBlankCounter
|
||||
cmp #$00
|
||||
bne VBlankCounterDone
|
||||
inc $15
|
||||
lda $15
|
||||
inc vBlankCounter + 1
|
||||
lda vBlankCounter + 1
|
||||
cmp #$00
|
||||
bne VBlankCounterDone
|
||||
inc $16
|
||||
inc vBlankCounter + 2
|
||||
VBlankCounterDone:
|
||||
rts
|
||||
|
||||
|
||||
|
||||
DMASpriteTables:
|
||||
rep #%00010000 ; 16-bit X/Y.
|
||||
sep #%00100000 ; 8-bit A.
|
||||
; Store at the base OAM address.
|
||||
ldx #$0000
|
||||
stx OAMADDR
|
||||
@ -592,10 +606,10 @@ DMASpriteTables:
|
||||
lda #$04
|
||||
sta DMA0DST
|
||||
; Our sprites start at $0100 in bank 0 and are #$220 bytes long.
|
||||
ldx #$0100
|
||||
ldx #spriteTableStart
|
||||
stx DMA0SRC
|
||||
stz DMA0SRCBANK
|
||||
ldx #$0220
|
||||
ldx #spriteTableSize
|
||||
stx DMA0SIZE
|
||||
; Kick off the DMA transfer.
|
||||
lda #%00000001
|
||||
|
Loading…
Reference in New Issue
Block a user