mirror of
https://github.com/safiire/n65.git
synced 2024-12-12 00:29:03 +00:00
214 lines
3.2 KiB
NASM
214 lines
3.2 KiB
NASM
;;;;
|
|
; Create an iNES header
|
|
.ines {"prog": 1, "char": 0, "mapper": 0, "mirror": 0}
|
|
|
|
|
|
;;;;
|
|
; Include all the symbols in the nes library
|
|
.inc <nes.sym>
|
|
|
|
|
|
;;;;
|
|
; Open the prog section bank 0
|
|
.segment prog 0
|
|
|
|
|
|
;;;;
|
|
; Structure to keep track of input
|
|
.org $0000
|
|
.scope controller_state
|
|
.space b 1
|
|
.space a 1
|
|
.
|
|
|
|
|
|
;;;;
|
|
; Setup the interrupt vectors
|
|
.org $FFFA
|
|
.dw vblank
|
|
.dw reset
|
|
.dw irq
|
|
|
|
|
|
;;;;
|
|
; Here is our code entry point
|
|
.org $C000
|
|
.scope reset
|
|
sei ; SEt Interrupt (Disables them)
|
|
cld ; CLear Decimal Mode
|
|
|
|
ldx #$ff
|
|
txs ; Set the stack pointer
|
|
|
|
ldx #$00
|
|
stx nes.ppu.control
|
|
stx nes.ppu.mask ; Disable Vblank & Rendering
|
|
|
|
jsr zero_apu ; Zero all APU registers
|
|
|
|
; We need to wait for at least 2 Vblanks to happen
|
|
; before we know the PPU has stabilized at startup
|
|
; Here we wait for the first one.
|
|
wait_vblank1:
|
|
bit nes.ppu.status
|
|
bpl wait_vblank1
|
|
|
|
; Before we wait for the second vblank, lets
|
|
; zero all of the working RAM $0 to $800
|
|
; The $200s are sprite OAM, and should be set to $ff
|
|
clear_ram:
|
|
lda #$00
|
|
sta $00, x
|
|
sta $100, x
|
|
sta $300, x
|
|
sta $400, x
|
|
sta $500, x
|
|
sta $600, x
|
|
sta $700, x
|
|
lda #$ff
|
|
sta $200, x
|
|
inx
|
|
bne clear_ram
|
|
|
|
; Now wait for the second vblank
|
|
wait_vblank2:
|
|
bit nes.ppu.status
|
|
bpl wait_vblank2
|
|
|
|
jsr initialize
|
|
|
|
forever:
|
|
jmp forever
|
|
rti
|
|
.
|
|
|
|
|
|
;;;;
|
|
; Initialize everything
|
|
.scope initialize
|
|
; Enable pulse1 and pulse2 in the APU
|
|
lda #%00000011
|
|
sta nes.apu.channel_enable
|
|
|
|
; Initialize the controller states
|
|
lda #$00
|
|
sta controller_state.a zp
|
|
sta controller_state.b zp
|
|
|
|
; Reenable interrupts, Turn Vblank back on
|
|
lda #%10000000
|
|
sta nes.ppu.control
|
|
cli
|
|
rts
|
|
.
|
|
|
|
|
|
;;;;
|
|
; VBlank is called 60 times per second
|
|
.scope vblank
|
|
jsr read_input
|
|
rti
|
|
.
|
|
|
|
|
|
;;;;
|
|
; IRQ, we are not using
|
|
.scope irq
|
|
rti
|
|
.
|
|
|
|
|
|
;;;;
|
|
; Zero all the APU registers
|
|
.scope zero_apu
|
|
lda #$00
|
|
ldx #$00
|
|
loop:
|
|
sta $4000, x
|
|
inx
|
|
cpx $18
|
|
bne loop
|
|
rts
|
|
.
|
|
|
|
|
|
;;;;
|
|
; Read input from controller 1
|
|
.scope read_input
|
|
lda #$01 ; strobe joypad
|
|
sta nes.controller1
|
|
lda #$00
|
|
sta nes.controller1
|
|
|
|
; Handle Button A
|
|
lda nes.controller1
|
|
and #$01
|
|
beq update_a_state
|
|
|
|
; A is pressed, but did it just change to being pressed now?
|
|
ldx controller_state.a zp
|
|
bne update_a_state
|
|
|
|
; do the thing A does
|
|
jsr play_e329
|
|
|
|
update_a_state:
|
|
sta controller_state.a zp
|
|
|
|
; Handle Button B
|
|
lda nes.controller1
|
|
and #$01
|
|
beq update_b_state
|
|
|
|
; B is pressed, but did it just change to being pressed now?
|
|
ldx controller_state.b zp
|
|
bne update_b_state
|
|
|
|
; Do the thing B does
|
|
jsr play_a220
|
|
|
|
update_b_state:
|
|
sta controller_state.b zp
|
|
|
|
rts
|
|
.
|
|
|
|
|
|
;;;;
|
|
;; This will play an A 220hz note
|
|
;; On the pulse1 generator
|
|
.scope play_a220
|
|
pha
|
|
lda #%10011111
|
|
sta nes.apu.pulse1.control
|
|
|
|
lda #%11111011
|
|
sta nes.apu.pulse1.ft
|
|
|
|
lda #%11111001
|
|
sta nes.apu.pulse1.ct
|
|
|
|
pla
|
|
rts
|
|
.
|
|
|
|
|
|
;;;;
|
|
;; This will play an E 329.63hz note
|
|
;; On the pulse2 generator
|
|
.scope play_e329
|
|
pha
|
|
lda #%10011111
|
|
sta nes.apu.pulse2.control
|
|
|
|
lda #%01010010
|
|
sta nes.apu.pulse2.ft
|
|
|
|
lda #%11111001
|
|
sta nes.apu.pulse2.ct
|
|
|
|
pla
|
|
rts
|
|
.
|
|
|