nes

My nes projects
Log | Files | Refs | README

commit fc78033950edc16cedae8f492a2c9f5d5bccfe6a
Author: benjamin paul <bpaul@bpaul.xyz>
Date:   Sun, 21 Nov 2021 17:54:39 +1000

Square game!

Diffstat:
AREADME.md | 3+++
Asquare/Makefile | 2++
Asquare/README.md | 5+++++
Asquare/square.asm | 173+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asquare/square.nes | 0
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.