commit fc78033950edc16cedae8f492a2c9f5d5bccfe6a
Author: benjamin paul <bpaul@bpaul.xyz>
Date: Sun, 21 Nov 2021 17:54:39 +1000
Square game!
Diffstat:
5 files changed, 183 insertions(+), 0 deletions(-)
diff --git a/README.md b/README.md
@@ -0,0 +1,3 @@
+# NES adventures
+
+My adventures in NES programming
diff --git a/square/Makefile b/square/Makefile
@@ -0,0 +1,2 @@
+all:
+ nasm -o square.nes square.asm
diff --git a/square/README.md b/square/README.md
@@ -0,0 +1,5 @@
+# Moving square
+
+This was my first complete program. All it is is a square that you can move around with the controller, with a constant note playing in the background. This program taught me a lot of things, being the basics of audio, graphics and controller input.
+
+I didn't write this in an assembler because I started by using nasm, and couldn't be bothered to switch after realising it didn't have any 6502 support (It doesn't have any support right).
diff --git a/square/square.asm b/square/square.asm
@@ -0,0 +1,173 @@
+segment HEADER ; NES 2.0 Header section
+ db "NES", 0x1A ; Identification string
+ db 0x02 ; LSB of PGR-ROM size (32 KiB)
+ db 0x01 ; LSB of CHR-ROM size (8 KiB)
+ db 0x00 ; Flag 6 (Use the NROM mapper and horizontal mirroring)
+ db 0x08 ; Flag 7 (Use the NROM mapper and the NES 2.0 file format)
+ db 0x00 ; Use the NROM mapper and no submapper
+ db 0x00 ; No need to increase the ROM sizes
+ db 0x00 ; No PRG-RAM
+ db 0x00 ; NO CHR-RAM
+ db 0x00 ; 0 is for NTSC, 1 is for PAL
+ db 0x00 ; No special PPU
+
+segment PGR-ROM
+ ; Init
+ db 0x78 ; sei ; ignore IRQ interrupts
+ ; db 0xD8 ; cld ; clear decimal mode (not needed for the nes)
+ ; Disable PPU NMI interrupts
+ db 0xA9, 0x00 ; lda #0x00
+ db 0x8D, 0x00, 0x20 ; sta 0x2000
+ ; Disable the APU's DMC IRQ interrupts
+ db 0x8D, 0x10, 0x40 ; sta 0x4010
+ ; Initialize the stack at 0xFF
+ db 0xA2, 0xFF ; ldx #0xFF
+ db 0x9A ; txs
+
+ ; Wait for 2 vertical blanks
+ ; the 8th bit of 0x2002 is set when in a vblank
+ db 0x2C, 0x02, 0x20 ; bit 0x2002
+ db 0x10, 0xFB ; bpl -5
+ db 0x2C, 0x02, 0x20 ; bit 0x2002
+ db 0x10, 0xFB ; bpl -5
+
+ ; Play a triangle wave (E5)
+ db 0xA9, 0x40 ; lda #0x40
+ db 0x8D, 0x17, 0x40 ; sta 0x4017
+ db 0xA9, 0x04 ; lda #0x04
+ db 0x8D, 0x15, 0x40 ; sta 0x4015
+ db 0xA9, 0x81 ; lda #0x81
+ db 0x8D, 0x08, 0x40 ; sta 0x4008
+ db 0xA9, 0x55 ; lda #0x55 ; Wave frequency for an E5
+ db 0x8D, 0x0A, 0x40 ; sta 0x400A
+ db 0xA9, 0x00 ; lda #0x00
+ db 0x8D, 0x0B, 0x40 ; sta 0x400B
+
+ ; Prepare for vblank interrupts
+ db 0xA9, 0b10010000 ; lda #0b10010000
+ db 0x8D, 0x00, 0x20 ; sta 0x2000
+
+ ; Make the default background palette gray
+ db 0xA9, 0x3F ; ldb #0x3F
+ db 0x8D, 0x06, 0x20 ; sta 0x2006
+ db 0xA9, 0x00 ; ldb #0x00
+ db 0x8D, 0x06, 0x20 ; sta 0x2006
+ db 0x8D, 0x07, 0x20 ; sta 0x2007
+
+ ; Reset the address latch
+ db 0x8D, 0x02, 0x20 ; sta 0x2002
+ ; Set the colour of the square to black (0x0D)
+ db 0xA9, 0x3F ; ldb #0x3F
+ db 0x8D, 0x06, 0x20 ; sta 0x2006
+ db 0xA9, 0x11 ; ldb #0x11
+ db 0x8D, 0x06, 0x20 ; sta 0x2006
+ db 0xA9, 0x0D ; ldb #0x0D ; Colour for black
+ db 0x8D, 0x07, 0x20 ; sta 0x2007
+
+ ; Allow drawing sprites and tiles
+ db 0xA9, 0b00011000 ; lda #0b00011000
+ db 0x8D, 0x01, 0x20 ; sta 0x2001
+
+ ; Set the initial x and y positions of the square
+ db 0xA9, 0x80 ; lda #0x80
+ db 0x8D, 0x01, 0x00 ; sta 0x0001
+ db 0xA9, 0x80 ; lda #0x80
+ db 0x8D, 0x02, 0x00 ; sta 0x0002
+
+ ; OAM data
+ db 0xA9, 0x80 ; lda #0x80 ; y position
+ db 0x8D, 0x00, 0x02 ; sta 0x0200
+ db 0xA9, 0x00 ; lda #0x00 ; Sprite number
+ db 0x8D, 0x01, 0x02 ; sta 0x0201
+ db 0xA9, 0x00 ; lda #0x00 ; Attributes (palette 0)
+ db 0x8D, 0x02, 0x02 ; sta 0x0202
+ db 0xA9, 0x80 ; lda #0x80 ; x position
+ db 0x8D, 0x03, 0x02 ; sta 0x0203
+
+ ; Allow interrupts
+ db 0x58 ; cli
+
+; loop:
+ db 0x4C, 0x77, 0x80 ; jmp loop
+
+; read_input:
+
+ db 0xA2, 0x00 ; ldx #0x00
+ ; Empty the memory which will store the controller inputs
+ db 0x86, 0x00 ; stx 0x00
+
+ ; Probe the controller
+ db 0xA9, 0x01 ; lda #0x01
+ db 0x8D, 0x16, 0x40 ; sta 0x4016
+
+ db 0xA9, 0x00 ; lda #0x00
+ db 0x8D, 0x16, 0x40 ; sta 0x4016
+
+ ; Loop reading buttons
+ db 0xAD, 0x16, 0x40 ; lda 0x4016
+ db 0x4A ; lsr a
+ db 0x66, 0x00 ; ror 0x00
+ db 0xE8 ; inx
+ db 0xE0, 0x08 ; cpx #0x08
+ db 0xD0, 0xF5 ; bne -11
+
+ db 0x60
+
+; vblank:
+ ; Draw
+ db 0xA9, 0x02 ; lda #0x02
+ db 0x8D, 0x14, 0x40 ; sta 0x4014
+
+ ; Read controller inputs
+ db 0x20, 0x7A, 0x80 ; jsr read_input
+
+ ; Move the square based on the inputs
+ ; Up
+ db 0xA9, 0x10 ; lda #0x10
+ db 0x25, 0x00 ; and 0x00
+ db 0xF0, 0x02 ; beq 0x02
+
+ db 0xC6, 0x01 ; inc 0x01
+
+ ; Down
+ db 0xA9, 0x20 ; lda #0x20
+ db 0x25, 0x00 ; and 0x00
+ db 0xF0, 0x02 ; beq 0x02
+
+ db 0xE6, 0x01 ; inc 0x01
+
+ ; Left
+ db 0xA9, 0x40 ; lda #0x40
+ db 0x25, 0x00 ; and 0x00
+ db 0xF0, 0x02 ; beq 0x02
+
+ db 0xC6, 0x02 ; inc 0x02
+
+ ; Right
+ db 0xA9, 0x80 ; lda #0x80
+ db 0x25, 0x00 ; and 0x00
+ db 0xF0, 0x02 ; beq 0x02
+
+ db 0xE6, 0x02 ; inc 0x02
+
+ ; Write x and y positions to the OAM data
+ db 0xA5, 0x01 ; lda 0x01
+ db 0x8D, 0x00, 0x02 ; sta 0x0200 ; y pos
+ db 0xA5, 0x02 ; lda 0x02
+ db 0x8D, 0x03, 0x02 ; sta 0x0203 ; x pos
+
+ db 0xA5, 0x02 ; lda 0x02
+
+ db 0x40 ; rti
+
+; Vectors
+segment VECTORS start=0x10+0x8000-0x06
+ db 0x94, 0x80 ; NMI
+ db 0x00, 0x80 ; RESET
+ db 0x00, 0x00 ; IRQ
+
+; Graphical area
+segment CHR-ROM start=0x10+0x8000
+ ; The sprite for a box using colour 1
+ times 8 db 0xFF
+ times 8 db 0x00
diff --git a/square/square.nes b/square/square.nes
Binary files differ.