diff --git a/atlantico/Makefile b/atlantico/Makefile index e953e5d..b4b6c20 100755 --- a/atlantico/Makefile +++ b/atlantico/Makefile @@ -15,5 +15,5 @@ clean: # Rule to run the final cartridge .nes file in the FCEUX emulator ############################################################################### run: - on-workspace 1 "fceux ./atlantico.nes && i3-msg '[id=$(xdotool getactivewindow)] floating enable'" + on-workspace 1 "fceux /home/tyrel/code/6502nes/atlantico/atlantico.nes && i3-msg '[id=$(xdotool getactivewindow)] floating enable'" #on-workspace 1 "fceux atlantico.nes" diff --git a/atlantico/atlantico.asm b/atlantico/atlantico.asm index 61d90bd..473e835 100755 --- a/atlantico/atlantico.asm +++ b/atlantico/atlantico.asm @@ -2,12 +2,14 @@ .include "header.inc" .include "actor.inc" .include "reset.inc" +.include "state.inc" .include "utils.inc" ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Variables declared in RAM zero-page ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; .segment "ZEROPAGE" +MenuItem: .res 1 ; Keep track of menu item Score: .res 4 ; Score (1s, 10s, 100s, and 1000s digits in decimal) Collision: .res 1 ; Flag if a collision happened or not @@ -31,6 +33,7 @@ Clock60: .res 1 ; Counter that increments per second (60 frames) BgPtr: .res 2 ; Pointer to background address - 16bits (lo,hi) SprPtr: .res 2 ; Pointer to the sprite address - 16bits (lo,hi) BufPtr: .res 2 ; Pointer to the buffer address - 16bits (lo,hi) +PalPtr: .res 2 XScroll: .res 1 ; Store the horizontal scroll position CurrNametable: .res 1 ; Store the current starting nametable (0 or 1) @@ -53,6 +56,8 @@ PrevOAMCount: .res 1 ; Store the previous number of bytes that were sent Seed: .res 2 ; Initialize 16-bit seed to any value except 0 +GameState: .res 1 ; Keep track of game state + ActorsArray: .res MAX_ACTORS * .sizeof(Actor) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; @@ -207,13 +212,44 @@ DoneIncrementing: ;; Subroutine to load all 32 color palette values from ROM ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; .proc LoadPalette + ldx MenuItem + cpx #0 + bne :+ + lda #PaletteDataClear + sta PalPtr+1 + jmp LoadPaletteBytes + : + ldx MenuItem + cpx #1 + bne :+ + lda #PaletteDataCloudy + sta PalPtr+1 + jmp LoadPaletteBytes + : + ldx MenuItem + cpx #2 + bne :+ + lda #PaletteDataNight + sta PalPtr+1 + jmp LoadPaletteBytes + : + + +LoadPaletteBytes: PPU_SETADDR $3F00 ldy #0 ; Y = 0 -: lda PaletteData,y ; Lookup byte in ROM +: lda (PalPtr),y ; Lookup byte in ROM sta PPU_DATA ; Set value to send to PPU_DATA iny ; Y++ cpy #32 ; Is Y equal to 32? bne :- ; Not yet, keep looping + rts ; Return from subroutine .endproc @@ -774,6 +810,34 @@ FinishCollisionCheck: rts .endproc +.proc LoadTitleScreen + lda #TitleScreenData + sta BgPtr+1 + + PPU_SETADDR $2000 + ldx #$00 + ldy #$00 + OuterLoop: + InnerLoop: + lda (BgPtr),y + sta PPU_DATA + iny + cpy #0 + beq IncreaseHiByte + jmp InnerLoop + IncreaseHiByte: + inc BgPtr+1 + inx + cpx #4 + bne OuterLoop + + rts +.endproc + + + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Subroutine to switch CHR banks ;; Params = A has the bank number @@ -789,6 +853,133 @@ FinishCollisionCheck: Reset: INIT_NES ; Macro to initialize the NES to a known state +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;;;;;;;;;;;;;;;;;;;; T I T L E S C R E E N ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +.proc TitleScreen ; using proc to define scope + lda #1 + jsr SwitchCHRBank + + lda #State::TITLESCREEN + sta GameState ; GameState = TITLESCREEN + + lda #1 + sta MenuItem + + jsr LoadPalette + jsr LoadTitleScreen ; Load tiles and attributes to the PPU + + lda #0 + sta MenuItem + + +DrawMenuArrow: + ; Sprite y pos $0200 + lda #92 + sta $0200 + + ; Sprite Tile# $0201 + lda #$23 + sta $0201 + + ; Sprite Attribs $0202 + lda #%00000001 + sta $0202 + + ; Sprite X positon $0203 + lda #95 + sta $0203 + + +EnableNMI: + lda #%10010000 + sta PPU_CTRL + lda #%00011110 + sta PPU_MASK + +TitleScreenLoop: + lda Buttons + sta PrevButtons + + jsr ReadControllers + CheckStartButtons: + lda Buttons + and #BUTTON_START + beq :+ + jmp GamePlay + : + CheckDownButton: + lda Buttons + and #BUTTON_DOWN + beq :+ + cmp PrevButtons ; only one press considered, not hold + beq :+ + lda MenuItem + cmp #2 ; prevent past 2 + beq :+ + ;; increment menu item + inc MenuItem + + lda $0200 + clc + adc #17 + sta $0200 + : + + CheckUpButton: + lda Buttons + and #BUTTON_UP + beq :+ + cmp PrevButtons ; only one press considered, not hold + beq :+ + lda MenuItem + beq :+ + dec MenuItem + lda $0200 + sec + sbc #17 + sta $0200 + : + + WaitForVBlank: ; We lock the execution of the game logic here + lda IsDrawComplete ; Here we check and only perform a game loop call once NMI is done drawing + beq WaitForVBlank ; Otherwise, we keep looping + + lda #0 + sta IsDrawComplete ; Once we're done, we set the DrawComplete flag back to 0 + + jmp TitleScreenLoop + +.endproc ; End titleScreen + + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;;;;;;;;;;;;;;;;;;;; G A M E P L A Y ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +.proc GamePlay + lda #0 + jsr SwitchCHRBank + + lda #State::PLAYING + sta GameState ; GameState = Playing + + PPU_DISABLE_NMI + + InitVariables: lda #0 sta Frame ; Frame = 0 @@ -938,6 +1129,8 @@ GameLoop: jmp GameLoop +.endproc ; EndGameplay Proc + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; NMI interrupt handler ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; @@ -979,7 +1172,11 @@ BackgroundCopy: ; Here is where we copy/draw the background buffer jmp BufferLoop ; Loop back until we finish the buffer (find an entry with Length=0) EndBackgroundCopy: + lda GameState + cmp #State::PLAYING + bne EndScrolling ; Bypass scrolling if not in gameplay state +;; Only GAMEPLAY NewColumnCheck: lda XScroll and #%00000111 ; Check if the scroll a multiple of 8 @@ -1034,6 +1231,8 @@ ScrollBackground: lda #0 sta PPU_SCROLL ; No vertical scrolling +EndScrolling: + RefreshRendering: lda #%10010000 ; Enable NMI, sprites from Pattern Table 0, background from Pattern Table 1 ora CurrNametable ; OR with CurrNametable (0 or 1) to set PPU_CTRL bit-0 (starting nametable) @@ -1067,9 +1266,15 @@ IRQ: ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Hardcoded list of color values in ROM to be loaded by the PPU ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -PaletteData: +PaletteDataCloudy: .byte $1C,$0F,$22,$1C, $1C,$37,$3D,$0F, $1C,$37,$3D,$30, $1C,$0F,$3D,$30 ; Background palette .byte $1C,$0F,$2D,$10, $1C,$0F,$20,$27, $1C,$2D,$38,$18, $1C,$0F,$1A,$32 ; Sprite palette +PaletteDataClear: +.byte $1C,$0F,$22,$1C, $1C,$36,$21,$0B, $1C,$36,$21,$30, $1C,$0F,$3D,$30 ; Background palette +.byte $1C,$0F,$2D,$10, $1C,$0F,$20,$27, $1C,$2D,$38,$18, $1C,$0F,$1A,$32 ; Sprite palette +PaletteDataNight: +.byte $0C,$0F,$1C,$0C, $0C,$26,$0C,$0F, $0C,$26,$0C,$2D, $0C,$36,$07,$2D ; Background palette +.byte $0C,$0F,$1D,$2D, $0C,$0F,$20,$27, $0C,$2D,$38,$18, $0C,$0F,$1A,$21 ; Sprite palette ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Background data (contains 4 screens that should scroll horizontally) @@ -1244,6 +1449,11 @@ AttributeData: .byte $ff,$aa,$aa,$aa,$59,$00,$00,$00 .byte $ff,$aa,$aa,$aa,$5a,$00,$00,$00 + +TitleScreenData: +.incbin "titlescreen.nam" + + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Here we add the CHR-ROM data, included from an external .CHR file ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; diff --git a/atlantico/atlantico.nes b/atlantico/atlantico.nes index cbf190d..bc29113 100644 Binary files a/atlantico/atlantico.nes and b/atlantico/atlantico.nes differ diff --git a/atlantico/atlantico.o b/atlantico/atlantico.o index 69d69f7..f51db0d 100644 Binary files a/atlantico/atlantico.o and b/atlantico/atlantico.o differ diff --git a/atlantico/state.inc b/atlantico/state.inc new file mode 100644 index 0000000..3a05801 --- /dev/null +++ b/atlantico/state.inc @@ -0,0 +1,6 @@ +.enum State + TITLESCREEN + PLAYING + GAMEOVER + PAUSED +.endenum diff --git a/atlantico/titlescreen.chr b/atlantico/titlescreen.chr index 7da32cf..90b5daf 100755 Binary files a/atlantico/titlescreen.chr and b/atlantico/titlescreen.chr differ diff --git a/atlantico/titlescreen.nam b/atlantico/titlescreen.nam new file mode 100755 index 0000000..e6dceb7 Binary files /dev/null and b/atlantico/titlescreen.nam differ diff --git a/atlantico/utils.inc b/atlantico/utils.inc index 2320f11..8c21cd0 100755 --- a/atlantico/utils.inc +++ b/atlantico/utils.inc @@ -40,3 +40,10 @@ tax pla ; Pull A from the stack .endmacro + + +.macro PPU_DISABLE_NMI + lda #0 + sta PPU_CTRL + sta PPU_MASK +.endmacro