Simple SNES shoot-'em-up game.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

405 lines
8.2 KiB

9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
  1. .INCLUDE "header.asm"
  2. .INCLUDE "init.asm"
  3. .INCLUDE "registers.asm"
  4. ; The JSR and RTS instructions add a total of 12 cycles of overhead. For
  5. ; short, commonly-used functions, it makes sense to declare them as macros,
  6. ; which get inlined by the assembler at the point of use. This saves on
  7. ; CPU cycles, at the cost of code size.
  8. .MACRO ConvertXCoordinate
  9. ; Data in: world x-coordinate, in A register.
  10. ; Data out: SNES scroll data, in C (the 16-bit A register).
  11. rep #%00100000 ; 16-bit A
  12. eor #$FFFF ; Flip bits
  13. ina
  14. sep #%00100000 ; 8-bit A
  15. .ENDM
  16. .MACRO ConvertYCoordinate
  17. ; Data in: world y-coordinate, in A register.
  18. ; Data out: SNES scroll data, in C (the 16-bit A register).
  19. rep #%00100000 ; 16-bit A
  20. eor #$FFFF ; Flip bits
  21. sep #%00100000 ; 8-bit A
  22. .ENDM
  23. .BANK 0 SLOT 0
  24. .ORG 0
  25. .SECTION "MainCode"
  26. ; Memory layout:
  27. ; 00-0F: scratch space for functions.
  28. ; 10-11: controller state of joypad #1.
  29. ; 12-13: controller state of joypad #2.
  30. ; 14-17: 32-bit counter of vblanks.
  31. ; 20-21: (x, y) coordinates of player.
  32. ; 22-24: RGB color values to use for background color, from [0-31].
  33. Start:
  34. InitializeSNES
  35. jsr LoadPaletteAndTileData
  36. ; Turn on the screen.
  37. ; Format: x000bbbb
  38. ; x: 0 = screen on, 1 = screen off, bbbb: Brightness ($0-$F)
  39. lda #%00001111
  40. sta INIDISP
  41. ; Enable NMI interrupt & joypad.
  42. ; n-vh---j n: NMI interrupt enable v: vertical counter enable
  43. ; h: horizontal counter enable j: joypad enable
  44. lda #%10000001
  45. sta NMITIMEN
  46. ; Store zeroes to the controller status registers.
  47. ; TODO(mcmillen): is this needed? I think the system will overwrite these
  48. ; automatically.
  49. stz JOY1H
  50. stz JOY1L
  51. ; Write something recognizable into our scratch space.
  52. jsr FillScratch
  53. ; Start the background color as a sky blue.
  54. lda #16
  55. sta $23
  56. lda #31
  57. sta $24
  58. ; Player's initial starting location.
  59. lda #(256 / 4)
  60. sta $20
  61. lda #((224 - 8) / 2)
  62. sta $21
  63. MainLoop:
  64. wai ; Wait for interrupt.
  65. jmp MainLoop
  66. LoadPaletteAndTileData:
  67. ; For more details on DMA, see:
  68. ; http://wiki.superfamicom.org/snes/show/Grog%27s+Guide+to+DMA+and+HDMA+on+the+SNES
  69. ; http://wiki.superfamicom.org/snes/show/Making+a+Small+Game+-+Tic-Tac-Toe
  70. ;
  71. ; A lot of the graphics-related registers are explained in Qwertie's doc:
  72. ; http://emu-docs.org/Super%20NES/General/snesdoc.html
  73. ; ... but be careful, because there are some errors in this doc.
  74. ;
  75. ; bazz's tutorial (available from http://wiki.superfamicom.org/snes/) is
  76. ; quite helpful with palette / sprites / DMA, especially starting at
  77. ; http://wiki.superfamicom.org/snes/show/Working+with+VRAM+-+Loading+the+Palette
  78. ; 16-bit X/Y registers. Used for DMA source address & transfer size, both of
  79. ; which want 16-bit values.
  80. rep #%00010000
  81. ; 8-bit A/B registers. Used for DMA source bank & destination address.
  82. sep #%00100000
  83. ; Initialize the palette memory in a loop.
  84. ; We could also do this with a DMA transfer (like we do with the tile data
  85. ; below), but it seems overkill for just a few bytes. :)
  86. ldx #0
  87. lda #32 ; Palette entries for BG2 start at 32.
  88. sta CGADDR
  89. -
  90. lda.l UntitledPalette, x
  91. sta CGDATA
  92. inx
  93. cpx #8 ; 8 bytes of palette data.
  94. bne -
  95. ; DMA 0 source address & bank.
  96. ldx #UntitledData
  97. stx DMA0SRC
  98. lda #:UntitledData
  99. sta DMA0SRCBANK
  100. ; DMA 0 transfer size.
  101. ; See the helpful comment in tiles.asm to find the size of the tile data.
  102. ldy #384
  103. sty DMA0SIZE
  104. ; DMA 0 control register.
  105. ; Transfer type 001 = 2 addresses, LH.
  106. lda #%00000001
  107. sta DMA0CTRL
  108. ; DMA 0 destination.
  109. lda #$18 ; Upper-byte is assumed to be $21, so this is $2118 & $2119.
  110. sta DMA0DST
  111. ; $2116 sets the word address for accessing VRAM.
  112. ldy #$0000
  113. sty VMADDR
  114. ; Enable DMA channel 0.
  115. lda #%00000001
  116. sta DMAENABLE
  117. ; VRAM writing mode. Increments the address every time we write to $2119.
  118. lda #%10000000
  119. sta VMAIN
  120. ; Set word address for accessing VRAM to $6000.
  121. ldx #$6000 ; BG 2 starts here.
  122. stx VMADDR
  123. ldx #$0004 ; Stick one tile into BG2.
  124. stx VMDATA
  125. ; Set up the screen. 16x16 tiles for BG2, 8x8 tiles elsewhere, mode 0.
  126. lda #%00100000
  127. sta BGMODE
  128. ; $2108 is the BG2 VRAM location register.
  129. ; This tells it that the BG2 data starts at $6000.
  130. lda #%01100000
  131. sta BG2SC
  132. stz BG12NBA
  133. ; Main screen: enable BG2.
  134. lda #%00000010
  135. sta MSENABLE
  136. rts
  137. VBlankHandler:
  138. jsr VBlankCounter ; DEBUG
  139. jsr JoypadHandler
  140. jsr SetBackgroundColor
  141. jsr SetPlayerPosition
  142. rti
  143. VBlankCounter:
  144. ; Increment a counter of how many VBlanks we've done.
  145. inc $14
  146. lda $14
  147. cmp #$00
  148. bne VBlankCounterDone
  149. inc $15
  150. lda $15
  151. cmp #$00
  152. bne VBlankCounterDone
  153. inc $16
  154. lda $16
  155. cmp #$00
  156. bne VBlankCounterDone
  157. inc $17
  158. VBlankCounterDone:
  159. rts
  160. JoypadHandler:
  161. jsr JoypadDebug ; DEBUG
  162. JoypadUp:
  163. lda JOY1H
  164. and #$08 ; Up
  165. cmp #$08
  166. bne JoypadDown ; Button not pressed.
  167. lda $21
  168. cmp #0
  169. beq JoypadDown ; Value saturated.
  170. dec $21
  171. dec $21
  172. JoypadDown:
  173. lda JOY1H
  174. and #$04
  175. cmp #$04
  176. bne JoypadLeft ; Button not pressed.
  177. lda $21
  178. cmp #(224 - 16)
  179. beq JoypadLeft ; Value saturated.
  180. inc $21
  181. inc $21
  182. JoypadLeft:
  183. lda JOY1H
  184. and #$02 ; Left
  185. cmp #$02
  186. bne JoypadRight ; Button not pressed.
  187. lda $20
  188. cmp #0
  189. beq JoypadRight ; Value saturated.
  190. dec $20
  191. dec $20
  192. JoypadRight:
  193. lda JOY1H
  194. and #$01
  195. cmp #$01 ; Right
  196. bne JoypadB ; Button not pressed.
  197. lda $20
  198. cmp #(256 - 16)
  199. beq JoypadB ; Value saturated.
  200. inc $20
  201. inc $20
  202. JoypadB:
  203. lda JOY1H
  204. and #$80 ; B
  205. cmp #$80
  206. bne JoypadA ; Button not pressed.
  207. lda $22
  208. cmp #0
  209. beq JoypadA ; Value saturated.
  210. dec $22
  211. JoypadA:
  212. lda JOY1L
  213. and #$80 ; A
  214. cmp #$80
  215. bne JoypadY ; Button not pressed.
  216. lda $22
  217. cmp #31
  218. beq JoypadY ; Value saturated.
  219. inc $22
  220. JoypadY:
  221. lda JOY1H
  222. and #$40 ; Y
  223. cmp #$40
  224. bne JoypadX ; Button not pressed.
  225. lda $23
  226. cmp #0
  227. beq JoypadX ; Value saturated.
  228. dec $23
  229. JoypadX:
  230. lda JOY1L
  231. and #$40 ; X
  232. cmp #$40
  233. bne JoypadL ; Button not pressed.
  234. lda $23
  235. cmp #31
  236. beq JoypadL ; Value saturated.
  237. inc $23
  238. JoypadL:
  239. lda JOY1L
  240. and #$20 ; L
  241. cmp #$20
  242. bne JoypadR ; Button not pressed.
  243. lda $24
  244. cmp #0
  245. beq JoypadR ; Value saturated.
  246. dec $24
  247. JoypadR:
  248. lda JOY1L
  249. and #$10 ; R
  250. cmp #$10
  251. bne JoypadDone ; Button not pressed.
  252. lda $24
  253. cmp #31
  254. beq JoypadDone ; Value saturated.
  255. inc $24
  256. ; TODO(mcmillen): have Start and Select do something too.
  257. JoypadDone:
  258. rts
  259. JoypadDebug:
  260. ; Load joypad registers into RAM for easier inspection.
  261. lda JOY1L
  262. sta $10
  263. lda JOY1H
  264. sta $11
  265. lda JOY2L
  266. sta $12
  267. lda JOY2H
  268. sta $13
  269. rts
  270. SetBackgroundColor:
  271. ; $22 $23 $24 are (R, G, B), each ranging from [0-31].
  272. ; The palette color format is 15-bit: [0bbbbbgg][gggrrrrr]
  273. ; Set the background color.
  274. ; Entry 0 corresponds to the SNES background color.
  275. stz CGADDR
  276. ; Compute and the low-order byte and store it in CGDATA.
  277. lda $23 ; Green.
  278. .rept 5
  279. asl
  280. .endr
  281. ora $22 ; Red.
  282. sta CGDATA
  283. ; Compute the high-order byte and store it in CGDATA.
  284. lda $24 ; Blue.
  285. .rept 2
  286. asl
  287. .endr
  288. sta $00
  289. lda $23 ; Green.
  290. .rept 3
  291. lsr
  292. .endr
  293. ora $00
  294. sta CGDATA
  295. rts
  296. SetPlayerPosition:
  297. ; Make sure the high byte of A is zeroed out.
  298. lda #$00
  299. xba
  300. ; Get player x and convert it to a scroll offset.
  301. lda $0020
  302. ConvertXCoordinate
  303. sta BG2HOFS
  304. xba
  305. sta BG2HOFS
  306. ; Make sure the high byte of A is zeroed out.
  307. lda #$00
  308. xba
  309. ; Get player y and convert it to a scroll offset.
  310. lda $0021
  311. ConvertYCoordinate
  312. sta BG2VOFS
  313. xba
  314. sta BG2VOFS
  315. rts
  316. FillScratch:
  317. lda #$42 ; B
  318. ldx #0
  319. FillScratchLoop:
  320. sta $00,X
  321. inx
  322. cpx #$10
  323. bne FillScratchLoop
  324. rts
  325. .ENDS
  326. .BANK 1 SLOT 0
  327. .ORG 0
  328. .SECTION "TileData"
  329. .INCLUDE "tiles.asm"
  330. .ENDS