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.

381 lines
7.4 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
9 years ago
  1. .INCLUDE "header.asm"
  2. .INCLUDE "InitSNES.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 dark blue.
  54. lda #16
  55. sta $24
  56. MainLoop:
  57. wai ; Wait for interrupt.
  58. jmp MainLoop
  59. LoadPaletteAndTileData:
  60. ; 16-bit X/Y registers. Used for DMA source address & transfer size, both of
  61. ; which want 16-bit values.
  62. ; TODO(mcmillen): change back to 8-bit when we're done?
  63. rep #%00010000
  64. ; 8-bit A/B registers. Used for DMA source bank & destination address.
  65. sep #%00100000
  66. ; We only need one palette entry, so we just initialize it manually.
  67. ; We could also do this with a DMA transfer (like we do with the tile data
  68. ; below), but it seems overkill for just one entry :)
  69. lda #34 ; Set the 34th palette entry.
  70. sta CGADDR
  71. lda.l PaletteData
  72. sta CGDATA
  73. lda.l PaletteData + 1
  74. sta CGDATA
  75. ; DMA 0 source address & bank.
  76. ldx #TileData
  77. stx DMA0SRC
  78. lda #:TileData
  79. sta DMA0SRCBANK
  80. ; DMA 0 transfer size.
  81. ldy #(15 * 16 *2) ; Also see the helpful "480 bytes" comment in tiles.asm.
  82. sty DMA0SIZE
  83. ; DMA 0 control register.
  84. ; Transfer type 001 = 2 addresses, LH.
  85. lda #%00000001
  86. sta DMA0CTRL
  87. ; DMA 0 destination.
  88. lda #$18 ; Upper-byte is assumed to be $21, so this is $2118 & $2119.
  89. sta DMA0DST
  90. ; $2116 sets the word address for accessing VRAM.
  91. ldy #$0000
  92. sty VMADDR
  93. ; Enable DMA channel 0.
  94. lda #%00000001
  95. sta DMAENABLE
  96. ; VRAM writing mode. Increments the address every time we write to $2119.
  97. lda #%10000000
  98. sta VMAIN
  99. ; Set word address for accessing VRAM to $6000.
  100. ldx #$6000 ; BG 2 starts here.
  101. stx VMADDR
  102. ldx #$000A ; Stick one tile into BG2.
  103. stx VMDATA
  104. ; Set up the screen. 16x16 tiles for BG2, 8x8 tiles elsewhere, mode 0.
  105. lda #%00100000
  106. sta BGMODE
  107. ; $2108 is the BG2 VRAM location register.
  108. ; This tells it that the BG2 data starts at $6000.
  109. lda #%01100000
  110. sta BG2SC
  111. stz BG12NBA
  112. ; Main screen: enable BG2.
  113. lda #%00000010
  114. sta MSENABLE
  115. rts
  116. VBlankHandler:
  117. jsr VBlankCounter ; DEBUG
  118. jsr JoypadHandler
  119. jsr SetBackgroundColor
  120. jsr SetPlayerPosition
  121. rti
  122. VBlankCounter:
  123. ; Increment a counter of how many VBlanks we've done.
  124. inc $14
  125. lda $14
  126. cmp #$00
  127. bne VBlankCounterDone
  128. inc $15
  129. lda $15
  130. cmp #$00
  131. bne VBlankCounterDone
  132. inc $16
  133. lda $16
  134. cmp #$00
  135. bne VBlankCounterDone
  136. inc $17
  137. VBlankCounterDone:
  138. rts
  139. JoypadHandler:
  140. jsr JoypadDebug ; DEBUG
  141. JoypadUp:
  142. lda JOY1H
  143. and #$08 ; Up
  144. cmp #$08
  145. bne JoypadDown ; Button not pressed.
  146. lda $21
  147. cmp #0
  148. beq JoypadDown ; Value saturated.
  149. dec $21
  150. dec $21
  151. JoypadDown:
  152. lda JOY1H
  153. and #$04
  154. cmp #$04
  155. bne JoypadLeft ; Button not pressed.
  156. lda $21
  157. cmp #(224 - 16)
  158. beq JoypadLeft ; Value saturated.
  159. inc $21
  160. inc $21
  161. JoypadLeft:
  162. lda JOY1H
  163. and #$02 ; Left
  164. cmp #$02
  165. bne JoypadRight ; Button not pressed.
  166. lda $20
  167. cmp #0
  168. beq JoypadRight ; Value saturated.
  169. dec $20
  170. dec $20
  171. JoypadRight:
  172. lda JOY1H
  173. and #$01
  174. cmp #$01 ; Right
  175. bne JoypadB ; Button not pressed.
  176. lda $20
  177. cmp #(256 - 16)
  178. beq JoypadB ; Value saturated.
  179. inc $20
  180. inc $20
  181. JoypadB:
  182. lda JOY1H
  183. and #$80 ; B
  184. cmp #$80
  185. bne JoypadA ; Button not pressed.
  186. lda $22
  187. cmp #0
  188. beq JoypadA ; Value saturated.
  189. dec $22
  190. JoypadA:
  191. lda JOY1L
  192. and #$80 ; A
  193. cmp #$80
  194. bne JoypadY ; Button not pressed.
  195. lda $22
  196. cmp #31
  197. beq JoypadY ; Value saturated.
  198. inc $22
  199. JoypadY:
  200. lda JOY1H
  201. and #$40 ; Y
  202. cmp #$40
  203. bne JoypadX ; Button not pressed.
  204. lda $23
  205. cmp #0
  206. beq JoypadX ; Value saturated.
  207. dec $23
  208. JoypadX:
  209. lda JOY1L
  210. and #$40 ; X
  211. cmp #$40
  212. bne JoypadL ; Button not pressed.
  213. lda $23
  214. cmp #31
  215. beq JoypadL ; Value saturated.
  216. inc $23
  217. JoypadL:
  218. lda JOY1L
  219. and #$20 ; L
  220. cmp #$20
  221. bne JoypadR ; Button not pressed.
  222. lda $24
  223. cmp #0
  224. beq JoypadR ; Value saturated.
  225. dec $24
  226. JoypadR:
  227. lda JOY1L
  228. and #$10 ; R
  229. cmp #$10
  230. bne JoypadDone ; Button not pressed.
  231. lda $24
  232. cmp #31
  233. beq JoypadDone ; Value saturated.
  234. inc $24
  235. ; TODO(mcmillen): have Start and Select do something too.
  236. JoypadDone:
  237. rts
  238. JoypadDebug:
  239. ; Load joypad registers into RAM for easier inspection.
  240. lda JOY1L
  241. sta $10
  242. lda JOY1H
  243. sta $11
  244. lda JOY2L
  245. sta $12
  246. lda JOY2H
  247. sta $13
  248. rts
  249. SetBackgroundColor:
  250. ; $22 $23 $24 are (R, G, B), each ranging from [0-31].
  251. ; The palette color format is 15-bit: [0bbbbbgg][gggrrrrr]
  252. ; Set the background color.
  253. ; Entry 0 corresponds to the SNES background color.
  254. stz CGADDR
  255. ; Compute and the low-order byte and store it in CGDATA.
  256. lda $23 ; Green.
  257. .rept 5
  258. asl
  259. .endr
  260. ora $22 ; Red.
  261. sta CGDATA
  262. ; Compute the high-order byte and store it in CGDATA.
  263. lda $24 ; Blue.
  264. .rept 2
  265. asl
  266. .endr
  267. sta $00
  268. lda $23 ; Green.
  269. .rept 3
  270. lsr
  271. .endr
  272. ora $00
  273. sta CGDATA
  274. rts
  275. SetPlayerPosition:
  276. ; Make sure the high byte of A is zeroed out.
  277. lda #$00
  278. xba
  279. ; Get player x and convert it to a scroll offset.
  280. lda $0020
  281. ConvertXCoordinate
  282. sta BG2HOFS
  283. xba
  284. sta BG2HOFS
  285. ; Make sure the high byte of A is zeroed out.
  286. lda #$00
  287. xba
  288. ; Get player y and convert it to a scroll offset.
  289. lda $0021
  290. ConvertYCoordinate
  291. sta BG2VOFS
  292. xba
  293. sta BG2VOFS
  294. rts
  295. FillScratch:
  296. lda #$42 ; B
  297. ldx #0
  298. FillScratchLoop:
  299. sta $00,X
  300. inx
  301. cpx #$10
  302. bne FillScratchLoop
  303. rts
  304. .ENDS
  305. .BANK 1 SLOT 0
  306. .ORG 0
  307. .SECTION "TileData"
  308. .INCLUDE "tiles.asm"
  309. .ENDS