aboutsummaryrefslogtreecommitdiff
path: root/space/src/space.s
diff options
context:
space:
mode:
Diffstat (limited to 'space/src/space.s')
-rw-r--r--space/src/space.s147
1 files changed, 147 insertions, 0 deletions
diff --git a/space/src/space.s b/space/src/space.s
new file mode 100644
index 0000000..eec893c
--- /dev/null
+++ b/space/src/space.s
@@ -0,0 +1,147 @@
+;;;
+;;; TODO: reduce the scope of this to just:
+;;; - Movement through subpixels.
+;;; - Shooting (no collision or anything)
+;;; -> link to jetpac.nes for more stuff
+;;;
+;; This is similar to the sprite.s example, but it expands on it greatly into a
+;; full game by:
+;; - Having a moving background.
+;; - The ship can be moved:
+;; - The movement is done through subpixels for a smoother experience.
+;; - The ship's sprites are updated accordingly: resting, acceleration, full
+;; speed.
+;; - Random asteroids will appear from time to time and they can collide with
+;; the ship:
+;; - A collision decreases the live status from the ship (cracks will appear
+;; to the sprite).
+;; - When the live status reaches 0 -> game over.
+;; - The ship can shoot and destroy asteroids.
+;; - There is a score.
+;;;
+
+.segment "HEADER"
+ .byte 'N', 'E', 'S', $1A
+
+ ;; 2x PRG-ROM; 1x CHR-ROM
+ .byte $02
+ .byte $01
+
+ ;; Horizontal mirroring, no special mapper.
+ .byte $00
+ .byte $00
+
+.segment "VECTORS"
+ .addr nmi, reset, irq
+
+.segment "CHARS"
+ .incbin "../assets/space.chr"
+
+.segment "STARTUP"
+
+.segment "CODE"
+
+.include "../include/apu.s"
+.include "../include/oam.s"
+.include "../include/ppu.s"
+.include "../include/joypad.s"
+
+.include "states/game.s"
+.include "states/player.s"
+.include "vectors/reset.s"
+.include "vectors/nmi.s"
+.include "vectors/irq.s"
+
+;;;
+;; This is our main subroutine, the reset procedure will call at the very end of
+;; initializing the hardware.
+;;;
+.proc main
+ ;; Before starting the game loop proper we initialize all our assets: load
+ ;; the palettes, nametables and sprites for this game.
+ jsr init_palettes
+ jsr init_nametable
+ jsr Player::init
+
+ ;; Reset scroll.
+ bit PPU::STATUS
+ lda #$00
+ sta PPU::SCROLL
+ sta PPU::SCROLL
+
+ cli
+
+ ;; 7: allow NMI; 5: sprite size is 8x16; 4: background pattern table starts
+ ;; at $1000.
+ lda #%10110000
+ sta PPU::CONTROL
+
+ ;; 4: show sprites; 3: show background; 2: show sprites in leftmost pixels
+ ;; on the screen; 1: same as 2 but for background.
+ lda #%00011110
+ sta PPU::MASK
+
+@main_game_loop:
+ jsr Joypad::read
+ jsr Player::Movement::update
+ jsr Player::Sprite::update
+
+ ;; This is a hand-shake between the code on `main` and the code on the
+ ;; `nmi`. See Game::flags for more.
+ SET_RENDER_FLAG
+@wait_for_render:
+ bit Game::flags
+ bmi @wait_for_render
+
+ ;; Rendering is done, we can perform another iteration of the loop!
+ jmp @main_game_loop
+.endproc
+
+;; init_palettes copies all the palettes for our game into the proper PPU
+;; address.
+.proc init_palettes
+ PPU_ADDR $3F00
+
+ ldx #0
+@load_palettes_loop:
+ lda palettes, x
+ sta PPU::DATA
+ inx
+ cpx #$20
+ bne @load_palettes_loop
+ rts
+palettes:
+ ;; Background
+ .byte $0F, $12, $22, $32
+ .byte $0F, $00, $28, $30
+ .byte $0F, $28, $16, $2D
+ .byte $0F, $28, $16, $2D
+
+ ;; Foreground
+ .byte $0F, $00, $05, $30
+ .byte $0F, $00, $00, $00
+ .byte $0F, $00, $00, $00
+ .byte $0F, $00, $00, $00
+.endproc
+
+;; init_nametable loads the relevant data to the nametable that is then going to
+;; be used in order to build up the background.
+.proc init_nametable
+ bit PPU::STATUS
+
+ ;; Big stars.
+ WRITE_PPU_DATA $20C8, $02
+ WRITE_PPU_DATA $227A, $02
+
+ ;; Small stars.
+ WRITE_PPU_DATA $20B9, $04
+ WRITE_PPU_DATA $21CE, $04
+ WRITE_PPU_DATA $21BA, $04
+ WRITE_PPU_DATA $22B8, $04
+ WRITE_PPU_DATA $22E7, $04
+
+ ;; Select palette 1 for one of the small stars, giving it a red-ish look.
+ WRITE_PPU_DATA $23CE, %00000001
+
+ rts
+.endproc