From cf00fcdaa4ed5a44b3f373b5ba467b3eab80f7c6 Mon Sep 17 00:00:00 2001 From: Tyrel Souza Date: Sun, 4 Dec 2022 23:13:27 -0500 Subject: [PATCH] a bunch more work --- atlantico/._atlantico.asm | Bin 0 -> 4096 bytes atlantico/._nes.cfg | Bin 0 -> 4096 bytes atlantico/._reset.inc | Bin 0 -> 4096 bytes atlantico/._utils.inc | Bin 0 -> 4096 bytes atlantico/Makefile | 18 + atlantico/actor.inc | 17 + atlantico/atlantico.asm | 707 ++++++++++++++++++++++++++++ atlantico/atlantico.chr | Bin 0 -> 8192 bytes atlantico/atlantico.nes | Bin 0 -> 40976 bytes atlantico/atlantico.o | Bin 0 -> 48142 bytes atlantico/consts.inc | 29 ++ atlantico/header.inc | 13 + atlantico/nes.cfg | 16 + atlantico/reset.inc | 43 ++ atlantico/tagbardebug.log | 49 ++ atlantico/utils.inc | 37 ++ bgnam.py | 10 + clearmem.nes | Bin 0 -> 40976 bytes clearmem.o | Bin 0 -> 607 bytes helloppu/Makefile | 2 +- helloppu/helloppu.nes | Bin 0 -> 40976 bytes helloppu/helloppu.o | Bin 0 -> 1535 bytes loadbackground/._Makefile | Bin 0 -> 4096 bytes loadbackground/._loadbackground.asm | Bin 0 -> 4096 bytes loadbackground/._nes.cfg | Bin 0 -> 4096 bytes loadbackground/Makefile | 18 + loadbackground/background.nam | Bin 0 -> 1024 bytes loadbackground/consts.inc | 31 ++ loadbackground/header.inc | 13 + loadbackground/loadbackground.asm | 306 ++++++++++++ loadbackground/loadbackground.nes | Bin 0 -> 40976 bytes loadbackground/loadbackground.o | Bin 0 -> 19543 bytes loadbackground/mario.chr | Bin 0 -> 8192 bytes loadbackground/nes.cfg | 16 + loadbackground/reset.inc | 43 ++ loadbackground/utils.inc | 12 + loadtext/._Makefile | Bin 0 -> 4096 bytes loadtext/._loadtext.asm | Bin 0 -> 4096 bytes loadtext/._nes.cfg | Bin 0 -> 4096 bytes loadtext/Makefile | 18 + loadtext/consts.inc | 11 + loadtext/header.inc | 13 + loadtext/loadtext.asm | 193 ++++++++ loadtext/loadtext.nes | Bin 0 -> 40976 bytes loadtext/loadtext.o | Bin 0 -> 20386 bytes loadtext/mario.chr | Bin 0 -> 8192 bytes loadtext/nes.cfg | 16 + loadtext/reset.inc | 39 ++ loadtext/utils.inc | 12 + 49 files changed, 1681 insertions(+), 1 deletion(-) create mode 100755 atlantico/._atlantico.asm create mode 100755 atlantico/._nes.cfg create mode 100755 atlantico/._reset.inc create mode 100755 atlantico/._utils.inc create mode 100755 atlantico/Makefile create mode 100644 atlantico/actor.inc create mode 100755 atlantico/atlantico.asm create mode 100755 atlantico/atlantico.chr create mode 100644 atlantico/atlantico.nes create mode 100644 atlantico/atlantico.o create mode 100755 atlantico/consts.inc create mode 100755 atlantico/header.inc create mode 100755 atlantico/nes.cfg create mode 100755 atlantico/reset.inc create mode 100644 atlantico/tagbardebug.log create mode 100755 atlantico/utils.inc create mode 100644 bgnam.py create mode 100644 clearmem.nes create mode 100644 clearmem.o create mode 100644 helloppu/helloppu.nes create mode 100644 helloppu/helloppu.o create mode 100755 loadbackground/._Makefile create mode 100755 loadbackground/._loadbackground.asm create mode 100755 loadbackground/._nes.cfg create mode 100755 loadbackground/Makefile create mode 100755 loadbackground/background.nam create mode 100755 loadbackground/consts.inc create mode 100755 loadbackground/header.inc create mode 100755 loadbackground/loadbackground.asm create mode 100644 loadbackground/loadbackground.nes create mode 100644 loadbackground/loadbackground.o create mode 100755 loadbackground/mario.chr create mode 100755 loadbackground/nes.cfg create mode 100755 loadbackground/reset.inc create mode 100644 loadbackground/utils.inc create mode 100755 loadtext/._Makefile create mode 100755 loadtext/._loadtext.asm create mode 100755 loadtext/._nes.cfg create mode 100755 loadtext/Makefile create mode 100755 loadtext/consts.inc create mode 100755 loadtext/header.inc create mode 100755 loadtext/loadtext.asm create mode 100644 loadtext/loadtext.nes create mode 100644 loadtext/loadtext.o create mode 100755 loadtext/mario.chr create mode 100755 loadtext/nes.cfg create mode 100755 loadtext/reset.inc create mode 100755 loadtext/utils.inc diff --git a/atlantico/._atlantico.asm b/atlantico/._atlantico.asm new file mode 100755 index 0000000000000000000000000000000000000000..e806e0955d54c99e520b50925a03e38a8a46eac6 GIT binary patch literal 4096 zcmeH~!Ab)$5Qb-~wHBoAK@_Bxpq{s_Z&17{6?bWSD`_^%hNj7qWDCAXAHj1UMeq%L z36C|gt)dq%1uq#0|70?gOupMd^|S^RfO||(KSm?8F&BfnT{i%YrB%Ccya5C)>;GZB zBzd$c!MXxotpEJ0#NF=V3xG=^XAv$6PNO?q3X;cE%^9IO>K9ZDnaS6+L1r}sIRDP) zSesJQG{uHqJ;cCLIw?5Qrqg*1Dtr6YgW;Si&7?>QZ1Qm!PD+t-YV(9)8KWwMad_SC z+1DAt#wP0afawx*6q_<-65Yy_y6(o|iF}`nCK|-<=IrxPo`5Id33vjYfG6Mycmke)C$MV*ZY$Vqox1Ojhs@R)|o50+1L3ClDJkFz{^v(m+1nBL)UWIUt(=a103v0xDsI z=wMg?WDB5a0m{L|rIPb=^%4sTa#Hnj5{pYpi&Ill5=&B*1A;+%WNxod0@1GVD`i0R zC>RZa(GVC7fzc2c4S~@R7!85Z5Eu=C(GVC7fzc2c4FOys0P1XlFc`>%WMmdA6r~pD zmlh?bDx~EXWh-Rnm89mCWaj53=Hyf=!cbj9nnLwI+$%B+a{vDW E0OP+YaR2}S literal 0 HcmV?d00001 diff --git a/atlantico/._reset.inc b/atlantico/._reset.inc new file mode 100755 index 0000000000000000000000000000000000000000..5b40f69ec352f3b390ed4dc51d1e8194787ab06a GIT binary patch literal 4096 zcmeH~%}N6?5XWb$wR&myAPQ1S@Z%=i>KhcVO2u8;-byx`Wkb_s*<=g8h>zgKi}(ya zfZ!YW4Bl&Ew~Ai86ue|0{3nx{Wb(TW)b|=t1GvHj4MH?VmDw2Vm~{@&d^BqI%{KtA zWBfm?A4NAN#amXui}CM&mDt;D{0`ud$XS5%oYUYEmx5#=E#{0+6%2AJMoeeRS}!%~ z0~~zkbF6f!Xp&$}kFG;t35|2kl$Vqox1Ojhs@R)|o50+1L3ClDJkFz{^v(m+1nBL)UWIUt(=a103v0xDsI z=wMg?WDB5a0m{L|rIPb=^%4sTa#Hnj5{pYpi&Ill5=&B*1A;+%cGBS%5ic*X7 zON)|I71HvHvK2D(N>cMmGV}8ib8;#ba#GVu6q0fh^Rj_`VW_SlO`-Z9?iCpZx&QwG Djan$Q literal 0 HcmV?d00001 diff --git a/atlantico/Makefile b/atlantico/Makefile new file mode 100755 index 0000000..317fe0d --- /dev/null +++ b/atlantico/Makefile @@ -0,0 +1,18 @@ +############################################################################### +# Rule to assemble and link all assembly files +############################################################################### +build: + ca65 atlantico.asm -o atlantico.o + ld65 -C nes.cfg atlantico.o -o atlantico.nes + +############################################################################### +# Rule to remove all object (.o) and cartridge (.nes) files +############################################################################### +clean: + rm *.o *.nes + +############################################################################### +# Rule to run the final cartridge .nes file in the FCEUX emulator +############################################################################### +run: + on-workspace 6 "fceux atlantico.nes" diff --git a/atlantico/actor.inc b/atlantico/actor.inc new file mode 100644 index 0000000..b707c9f --- /dev/null +++ b/atlantico/actor.inc @@ -0,0 +1,17 @@ +.enum ActorType + NULL = 0 + PLAYER = 1 + SUBMARINE = 2 + AIRPLANE = 3 + MISSILE = 4 + BOMB = 5 + SPRITE0 = 6 +.endenum + +.struct Actor + Type .byte + XPos .byte + YPos .byte + XVel .byte + YVel .byte +.endstruct diff --git a/atlantico/atlantico.asm b/atlantico/atlantico.asm new file mode 100755 index 0000000..0d65b1e --- /dev/null +++ b/atlantico/atlantico.asm @@ -0,0 +1,707 @@ +.include "consts.inc" +.include "header.inc" +.include "actor.inc" +.include "reset.inc" +.include "utils.inc" + +.segment "ZEROPAGE" +Buttons: .res 1 ; Pressed buttons (A|B|Select|Start|Up|Dwn|Lft|Rgt) + +XPos: .res 2 ; Player X 16-bit position (8.8 fixed-point): hi+lo/256px +YPos: .res 2 ; Player Y 16-bit position (8.8 fixed-point): hi+lo/256px + +XVel: .res 1 ; Player X (signed) velocity (in pixels per 256 frames) +YVel: .res 1 ; Player Y (signed) velocity (in pixels per 256 frames) + +Frame: .res 1 ; Counts frames (0 to 255 and repeats) +IsDrawComplete: .res 1 ; Flag to indicate when vblank is done drawing +Clock60: .res 1 ; Counter that increments per second (60 frames) +BgPtr: .res 2 ; Pointer to background address - 16bits (lo,hi) + +XScroll: .res 1 ; Store the horizontal scroll position +CurrNametable: .res 1 ; Store the current starting nametable (0 or 1) +Column: .res 1 ; Stores the column (of tiles) we are in the level +NewColAddr: .res 2 ; The destination address of the new column in PPU +SourceAddr: .res 2 ; The source address in ROM of the new column tiles + +ParamType: .res 1 ; Used as param to subrouting +ParamXPos: .res 1 ; Used as param to subrouting +ParamYPos: .res 1 ; Used as param to subrouting +ParamXVel: .res 1 ; Used as param to subrouting +ParamYVel: .res 1 ; Used as param to subrouting + +; Store enough space for an array of actors +ActorsArray: .res MAX_ACTORS * .sizeof(Actor) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; PRG-ROM code located at $8000 +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +.segment "CODE" + +;ReadControllers +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Routine to read controller state and store it inside "Buttons" in RAM +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +.proc ReadControllers + lda #1 ; A = 1 + sta Buttons ; Buttons = 1 + sta JOYPAD1 ; Set Latch=1 to begin 'Input'/collection mode + lsr ; A = 0 + sta JOYPAD1 ; Set Latch=0 to begin 'Output' mode +LoopButtons: + lda JOYPAD1 ; This reads a bit from the controller data line and inverts its value, + ; And also sends a signal to the Clock line to shift the bits + lsr ; We shift-right to place that 1-bit we just read into the Carry flag + rol Buttons ; Rotate bits left, placing the Carry value into the 1st bit of 'Buttons' in RAM + bcc LoopButtons ; Loop until Carry is set (from that initial 1 we loaded inside Buttons) + rts +.endproc + +;LoadPalette +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Subroutine to load all 32 color palette values from ROM +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +.proc LoadPalette + PPU_SETADDR $3F00 + ldy #0 ; Y = 0 +: lda PaletteData,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 + + +;DrawNewColumn +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Routine to draw a new column of tiles off-screen as we scroll horizontally +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +.proc DrawNewColumn + ; [ Destination ] + lda XScroll ;Set newColAddr low and hi byte + lsr + lsr + lsr ; shift left three times to divide Xscroll by 3 + sta NewColAddr ; set the lo byte + + lda CurrNametable ; hi byte comes from nametable + eor #1 ; invert low bit (0 or 1) + asl + asl ; multiply by 4 (A is $00 or $04) + clc + adc #$20 ; add $20 (A is $20 or $24) for nametable 0 or 1 + sta NewColAddr+1 ; set the hi0-byte of the column address ($20xx or $24xx) + ;;;;;;;;;;; + + ; [SourceAddr low and hi byte] + lda Column ; Multiply by 32 to compute the offset + asl ; *2 + asl ; *4 + asl ; *8 + asl ; *16 + asl ; *32 + sta SourceAddr ; store lo byte of column source address + + lda Column + lsr ; /2 + lsr ; /4 + lsr ; Divide current column by 8 using 3 shift rights + sta SourceAddr+1 ; store hi byte of column source address + + ; here we'll add the offset the column source address with the address where the backggroun + lda SourceAddr ; lo byte of the column data + offset = address to load column data from + clc + adc #BackgroundData ; add the hi byte + sta SourceAddr+1 ; add the result of the offset back to the source address hi byte + + ;;; Loop all tiles from column, sending them to destination + DrawColumn: + lda #%00000100 ; + sta PPU_CTRL ; Tell the PPU that the increments will be +32 mode + + lda PPU_STATUS ; reset latch + lda NewColAddr+1 ; + sta PPU_ADDR ; set hi-byte of start address + lda NewColAddr ; + sta PPU_ADDR ; set lo-byte of start address + + ldx #30 ; Looping 30 times + ldy #0 ; + DrawColumnLoop: ; + lda (SourceAddr), y ; Copy from the address of the column source + y offset + sta PPU_DATA ; + iny ; Y++ + dex ; X-- + bne DrawColumnLoop ; loop 30 times + + rts +.endproc + +;DrawNewAttribs +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Routine to draw a attributes off-screen eveery 32 pixels +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +.proc DrawNewAttribs + lda CurrNametable + eor #1 ; invert low bit + asl ; Multiply by 2 (00 or 02) + asl ; multiply by 2 again (00, or 04) + clc + adc #$23 ; Add high byte of attribute 23-- or 27-- + sta NewColAddr+1 + + lda XScroll + lsr + lsr + lsr + lsr + lsr + clc + adc #$C0 + sta NewColAddr ; Low Byte + + ;; Source Address + lda Column ; Column/4 *8 since each row is 8bytes + and #%11111100 ; mask the lowest two bits to get the closest lowest multiple of 4 + asl ; one shift left - multiply by 2 + sta SourceAddr ; store low byte of offset in rom + + lda Column ; compute high + lsr ;/2 + lsr + lsr + lsr + lsr + lsr + lsr ; /128 + sta SourceAddr+1 ; store high byte + + lda SourceAddr + clc + adc #AttributeData ; hi byte of where attrib is in rom + sta SourceAddr+1 + + DrawAttribute: + bit PPU_STATUS + ldy #0 ; reset latch and back to 0 + DrawAttribLoop: + lda NewColAddr+1 + sta PPU_ADDR ; high byte of ppu dest + lda NewColAddr + sta PPU_ADDR ; low byte + lda (SourceAddr),y ; fetch attribute data + sta PPU_DATA ; store new data into ppu memory + iny + cpy #8 + beq :+ ; loop 8 times + lda NewColAddr + clc + adc #8 + sta NewColAddr ; next addr will be at NewColAddr +8 + jmp DrawAttribLoop + : + rts +.endproc + +;AddNewActor +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Subroutine to add new actor to the array in the first empty slot found +;; Params: ParamType, ParamXPos, ParamYPos, ParamXVel, ParamYVel +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +.proc AddNewActor + ldx #0 + ArrayLoop: + cpx #MAX_ACTORS * .sizeof(Actor); too many actors, skip + beq EndRoutine + lda ActorsArray+Actor::Type,x + cmp #ActorType::NULL + beq AddNewActorToArray ; If found empty slot, add to position + NextActor: + txa + clc + adc #.sizeof(Actor) + tax + jmp ArrayLoop + AddNewActorToArray: + lda ParamType + sta ActorsArray+Actor::Type,x + lda ParamXPos + sta ActorsArray+Actor::XPos,x + lda ParamYPos + sta ActorsArray+Actor::YPos,x + lda ParamXVel + sta ActorsArray+Actor::XVel,x + lda ParamYVel + sta ActorsArray+Actor::YVel,x + EndRoutine: + rts +.endproc + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Reset handler (called when the NES resets or powers on) +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +Reset: + INIT_NES ; Macro to initialize the NES to a known state + +InitVariables: + lda #0 + sta Frame ; Frame = 0 + sta Clock60 ; Clock60 = 0 + sta XScroll ; XScroll = 0 + sta CurrNametable ; CurrNametable = 0 + sta Column ; Column = 0 + lda #113 + sta XPos + lda #165 + sta YPos + +Main: + jsr LoadPalette ; Call LoadPalette subroutine to load 32 colors into our palette + +AddSprite0: + lda #ActorType::SPRITE0 + sta ParamType + lda #0 + sta ParamXPos + lda #27 + sta ParamYPos + lda #0 + sta ParamXVel + sta ParamYVel + jsr AddNewActor + +AddPlayer: + lda #ActorType::PLAYER + sta ParamType + lda XPos + sta ParamXPos + lda YPos + sta ParamYPos + lda #0 + sta ParamXVel + sta ParamYVel + jsr AddNewActor + +InitBackgroundTiles: + lda #1 + sta CurrNametable ;current nametable= 1 + lda #0 + sta XScroll + sta Column +InitBackgroundLoop: + jsr DrawNewColumn ; draw all rows of new column + + lda XScroll + clc + adc #8 + sta XScroll ; xscroll += 8 + + inc Column ;column++ + + lda Column + cmp #32 + bne InitBackgroundLoop ; loop 32 times to repeat all 32 columns of the first nametable + + lda #0 + sta CurrNametable ;current nametable = 0 + lda #1 + sta XScroll ;Scroll = 1 + + jsr DrawNewColumn ; draw first column of 2nd nametable + inc Column ; Column ++ + + lda #%00000000 + sta PPU_CTRL ; PPU back to +1 mode + +InitAttribs: + lda #1 + sta CurrNametable ;current nametable= 1 + lda #0 + sta XScroll + sta Column +InitAttribsLoop: + jsr DrawNewAttribs ; draw all rows of new column + lda XScroll + clc + adc #32 + sta XScroll ; xscroll += 32 + + lda Column + clc + adc #4 + sta Column + cmp #32 + bne InitAttribsLoop ; loop 32 times to repeat all 32 columns of the first nametable + + lda #0 + sta CurrNametable ;current nametable = 0 + lda #1 + sta XScroll ;Scroll = 1 + jsr DrawNewAttribs ; draw first column of 2nd nametable + + inc Column + +EnableRendering: + lda #%10010000 ; Enable NMI and set background to use the 2nd pattern table (at $1000) + sta PPU_CTRL + lda #0 + sta PPU_SCROLL ; Disable scroll in X + sta PPU_SCROLL ; Disable scroll in Y + lda #%00011110 + sta PPU_MASK ; Set PPU_MASK bits to render the background + +;;;;;;; START GAME LOOP +GameLoop: + ;Perform Game Logic Here + jsr ReadControllers + +CheckAButton: + lda Buttons + and #BUTTON_A + beq :+ + lda YPos + lda #ActorType::MISSILE + sta ParamType + lda XPos + sta ParamXPos + lda YPos + sta ParamYPos + lda #0 + sta ParamXVel + lda #255 + sta ParamYVel + jsr AddNewActor + : + + ;; TODO + ;;------------------ + ;jsr SpawnActors + ;jsr UpdateActors + ;jsr RenderActors + ;;------------------ + + WaitForVBlank: ; we lock execution + lda IsDrawComplete ; check and only perform game loop call once NMI is done drawing + beq WaitForVBlank ; otherwise keep looping + + lda #0 ; + sta IsDrawComplete ; set back to 0 + + jmp GameLoop; Force an infinite execution loop +;;;;;;; END GAME LOOP + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; NMI interrupt handler +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +NMI: + PUSH_REGS ; push registers to the stack + + inc Frame ; Frame++ + +OAMStartDMACopy: ; DMA copy of OAM data from RAM to PPU + lda #$02 ; Every frame, we copy spite data starting at $02** + sta PPU_OAM_DMA ; The OAM-DMA copy starts when we write to $4014 + +NewColumnCheck: + lda XScroll + and #%00000111 ; Check if the scroll a multiple of 8 + bne EndColCheck ; If it isn't, we still don't need to draw a new column + jsr DrawNewColumn ; If it is a multiple of 8, we proceed to draw a new column of tiles! + + Clamp128Cols: + lda Column + clc + adc #1 + and #%01111111 ; drop left most bit to wrap around 128 + sta Column ; clamping the value to never go over 128 + + EndColCheck: + +NewAttribsCheck: + lda XScroll + and #%00011111 + bne :+ + jsr DrawNewAttribs + : + +;SetPPUNoScroll: +; lda #0 +; sta PPU_SCROLL +; sta PPU_SCROLL +; +;EnablePPUSprite0: +; lda #%10010000 +; sta PPU_CTRL +; lda #%00011110 +; sta PPU_MASK +; +;WaitForNoSprite0: +; lda PPU_STATUS +; and #%01000000 +; bne WaitForNoSprite0 +; +;WaitForSprite0: +; lda PPU_STATUS +; and #%01000000 ; PPU address $2002 bit 6 is the sprite hit flag +; beq WaitForSprite0 ; loop until we do NOT have a sprite 0 hit + +ScrollBackground: + inc XScroll ; XScroll++ + lda XScroll + bne :+ ; Check if XScroll rolled back to 0, then we swap nametables! + lda CurrNametable + eor #1 ; An XOR with %00000001 will flip the right-most bit. + sta CurrNametable ; If it was 0, it becomes 1. If it was 1, it becomes 0. + : + lda XScroll + sta PPU_SCROLL ; Set the horizontal X scroll first + lda #0 + sta PPU_SCROLL ; No vertical scrolling + +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) + sta PPU_CTRL + lda #%00011110 ; Enable sprites, enable background, no clipping on left side + sta PPU_MASK + +SetGameClock: + lda Frame ; Increment Clock60 every time we reach 60 frames (NTSC = 60Hz) + cmp #60 ; Is Frame equal to #60? + bne :+ ; If not, bypass Clock60 increment + inc Clock60 ; But if it is 60, then increment Clock60 and zero Frame counter + lda #0 + sta Frame +: + +SetDrawComplete: + lda #1 + sta IsDrawComplete + inc Frame + + + PULL_REGS + rti ; Return from interrupt + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; IRQ interrupt handler +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +IRQ: + rti ; Return from interrupt + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Hardcoded list of color values in ROM to be loaded by the PPU +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +PaletteData: +.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 + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Background data (contains 4 screens that should scroll horizontally) +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +BackgroundData: +.byte $13,$13,$13,$13,$20,$21,$21,$21,$21,$21,$21,$21,$21,$21,$21,$21,$21,$21,$21,$23,$33,$15,$21,$12,$00,$31,$31,$31,$55,$56,$00,$00 ; ---> screen column 1 (from top to bottom) +.byte $13,$13,$75,$13,$20,$21,$21,$21,$21,$21,$21,$21,$21,$21,$21,$42,$21,$21,$21,$24,$34,$15,$15,$12,$00,$31,$31,$53,$56,$56,$00,$00 ; ---> screen column 2 (from top to bottom) +.byte $13,$13,$6e,$13,$20,$21,$21,$21,$21,$21,$21,$21,$21,$21,$21,$43,$21,$21,$21,$14,$11,$3e,$15,$12,$00,$00,$00,$31,$52,$56,$00,$00 ; ---> screen column 3 (from top to bottom) +.byte $13,$13,$7f,$13,$20,$21,$21,$21,$21,$21,$21,$21,$42,$21,$21,$44,$21,$21,$21,$14,$11,$3f,$15,$12,$00,$00,$00,$31,$5a,$56,$00,$00 ; ... +.byte $13,$13,$6e,$13,$20,$21,$21,$21,$21,$21,$21,$21,$44,$21,$21,$45,$21,$21,$21,$22,$32,$15,$15,$12,$00,$00,$00,$31,$58,$56,$00,$00 ; ... +.byte $13,$13,$75,$13,$20,$21,$21,$21,$21,$21,$21,$21,$45,$21,$21,$46,$21,$21,$21,$26,$36,$15,$15,$12,$00,$00,$00,$51,$5c,$56,$00,$00 ; ... +.byte $13,$13,$84,$13,$20,$21,$21,$21,$21,$21,$21,$21,$21,$21,$21,$21,$21,$21,$21,$27,$37,$15,$15,$12,$00,$00,$00,$00,$58,$56,$00,$00 +.byte $13,$13,$61,$13,$20,$21,$21,$21,$21,$21,$21,$21,$21,$21,$21,$21,$21,$21,$21,$28,$38,$15,$15,$12,$00,$00,$00,$00,$5c,$56,$00,$00 +.byte $13,$13,$13,$13,$20,$21,$21,$21,$21,$21,$21,$21,$21,$21,$21,$21,$21,$21,$21,$14,$11,$15,$15,$12,$00,$00,$00,$00,$57,$56,$00,$00 +.byte $13,$13,$13,$13,$20,$21,$21,$21,$21,$21,$21,$21,$47,$21,$21,$21,$48,$21,$21,$22,$32,$3e,$15,$12,$00,$00,$00,$00,$58,$56,$00,$00 +.byte $13,$13,$13,$13,$20,$21,$21,$21,$21,$21,$21,$21,$42,$21,$21,$21,$4a,$21,$21,$23,$33,$4e,$15,$12,$00,$00,$00,$00,$59,$56,$00,$00 +.byte $13,$13,$13,$13,$20,$21,$21,$21,$21,$21,$21,$21,$43,$21,$21,$21,$21,$21,$21,$24,$34,$3f,$15,$12,$00,$00,$00,$00,$58,$56,$00,$00 +.byte $13,$13,$7c,$13,$20,$21,$21,$21,$21,$21,$21,$21,$44,$21,$21,$21,$21,$21,$21,$14,$11,$15,$15,$12,$00,$00,$00,$00,$57,$56,$00,$00 +.byte $13,$13,$6c,$13,$20,$21,$21,$21,$21,$21,$21,$21,$45,$21,$21,$21,$21,$21,$21,$14,$11,$15,$15,$12,$00,$00,$00,$00,$59,$56,$00,$00 +.byte $13,$13,$78,$13,$20,$21,$21,$21,$21,$21,$21,$21,$21,$21,$15,$15,$21,$21,$21,$14,$11,$15,$15,$12,$00,$00,$00,$00,$58,$56,$00,$00 +.byte $13,$13,$7b,$13,$20,$21,$21,$21,$21,$21,$21,$21,$21,$21,$15,$15,$15,$21,$21,$14,$11,$15,$15,$12,$00,$00,$00,$00,$53,$56,$00,$00 +.byte $13,$13,$6e,$13,$20,$21,$21,$21,$21,$21,$21,$21,$21,$21,$15,$21,$15,$21,$21,$25,$35,$15,$15,$12,$00,$60,$00,$00,$54,$56,$00,$00 +.byte $13,$13,$84,$13,$20,$21,$21,$21,$21,$21,$21,$21,$21,$21,$21,$15,$21,$21,$21,$26,$36,$15,$15,$12,$00,$00,$00,$00,$58,$56,$00,$00 +.byte $13,$13,$60,$13,$20,$21,$21,$21,$21,$21,$21,$21,$21,$21,$21,$21,$21,$21,$15,$27,$37,$15,$15,$12,$00,$00,$00,$00,$58,$56,$00,$00 +.byte $13,$13,$60,$13,$20,$21,$21,$21,$21,$21,$21,$21,$21,$21,$21,$48,$21,$21,$15,$27,$37,$15,$15,$12,$00,$00,$00,$00,$5d,$55,$00,$00 +.byte $13,$13,$60,$13,$20,$21,$21,$21,$21,$21,$21,$21,$21,$21,$21,$49,$21,$21,$21,$28,$38,$3e,$21,$12,$00,$00,$00,$00,$58,$56,$00,$00 +.byte $13,$13,$13,$13,$20,$21,$21,$21,$21,$21,$21,$21,$21,$21,$21,$49,$21,$21,$21,$22,$35,$3f,$21,$12,$00,$00,$00,$00,$58,$56,$00,$00 +.byte $13,$13,$13,$13,$20,$21,$21,$21,$21,$21,$21,$21,$21,$21,$21,$49,$21,$21,$21,$26,$36,$3f,$21,$12,$00,$00,$00,$00,$57,$56,$00,$00 +.byte $13,$13,$13,$13,$20,$21,$21,$21,$21,$21,$21,$21,$21,$21,$21,$4a,$21,$21,$21,$27,$37,$21,$15,$12,$00,$00,$00,$00,$58,$56,$00,$00 +.byte $13,$13,$76,$13,$20,$21,$21,$21,$21,$21,$21,$21,$42,$21,$21,$21,$21,$21,$21,$28,$38,$15,$15,$12,$00,$00,$00,$00,$58,$56,$00,$00 +.byte $13,$13,$72,$13,$20,$21,$21,$21,$21,$21,$21,$21,$44,$21,$21,$21,$21,$21,$21,$14,$11,$3e,$21,$12,$00,$00,$00,$00,$59,$56,$00,$00 +.byte $13,$13,$7c,$13,$20,$21,$21,$21,$21,$21,$21,$21,$43,$21,$21,$21,$21,$21,$21,$14,$11,$4e,$21,$12,$00,$00,$00,$51,$59,$56,$00,$00 +.byte $13,$13,$7c,$13,$20,$21,$21,$21,$21,$21,$21,$21,$44,$21,$21,$21,$21,$21,$21,$14,$11,$3f,$15,$12,$00,$00,$00,$00,$5c,$56,$00,$00 +.byte $13,$13,$75,$13,$20,$21,$21,$21,$21,$21,$21,$21,$44,$21,$21,$21,$21,$21,$21,$29,$39,$21,$21,$12,$00,$00,$00,$00,$55,$56,$00,$00 +.byte $13,$13,$84,$13,$20,$21,$21,$21,$21,$21,$21,$21,$45,$21,$21,$21,$48,$21,$2c,$2a,$3a,$3c,$21,$12,$00,$00,$00,$54,$56,$56,$00,$00 +.byte $13,$13,$65,$13,$20,$21,$21,$21,$21,$21,$21,$21,$46,$21,$21,$21,$4a,$21,$2d,$2a,$3a,$3d,$15,$12,$00,$00,$00,$00,$52,$56,$00,$00 +.byte $13,$13,$13,$13,$20,$21,$21,$21,$21,$21,$21,$21,$21,$21,$21,$21,$21,$21,$21,$2b,$3b,$15,$15,$12,$00,$00,$00,$00,$57,$56,$00,$00 + +.byte $13,$13,$13,$13,$20,$21,$21,$21,$21,$21,$21,$21,$21,$21,$21,$21,$21,$21,$21,$14,$11,$15,$21,$12,$00,$31,$31,$31,$55,$56,$ff,$9a +.byte $13,$13,$75,$13,$20,$21,$21,$21,$21,$21,$21,$21,$21,$21,$21,$15,$21,$15,$21,$14,$11,$15,$15,$12,$00,$31,$31,$53,$56,$56,$ff,$5a +.byte $13,$13,$6e,$13,$20,$21,$21,$21,$21,$21,$21,$21,$21,$21,$21,$15,$15,$15,$21,$14,$11,$3e,$15,$12,$00,$00,$00,$31,$52,$56,$ff,$5a +.byte $13,$13,$7f,$13,$20,$21,$21,$21,$21,$21,$21,$21,$42,$21,$21,$15,$15,$15,$21,$14,$11,$3f,$15,$12,$00,$00,$00,$31,$5a,$56,$ff,$56 +.byte $13,$13,$6e,$13,$20,$21,$21,$21,$21,$21,$21,$21,$44,$21,$21,$15,$15,$15,$21,$14,$11,$15,$15,$12,$00,$00,$00,$31,$58,$56,$ff,$59 +.byte $13,$13,$75,$13,$20,$21,$21,$21,$21,$21,$21,$21,$45,$21,$21,$15,$15,$21,$21,$14,$11,$15,$15,$12,$00,$00,$00,$51,$5c,$56,$ff,$5a +.byte $13,$13,$84,$13,$20,$21,$21,$21,$21,$21,$21,$21,$21,$21,$21,$21,$15,$15,$21,$14,$11,$15,$15,$12,$00,$00,$00,$00,$58,$56,$ff,$5a +.byte $13,$13,$61,$13,$20,$21,$21,$21,$21,$21,$21,$21,$21,$21,$21,$21,$21,$21,$21,$14,$11,$15,$15,$12,$00,$00,$00,$00,$5c,$56,$ff,$5a +.byte $13,$13,$13,$13,$20,$21,$21,$21,$21,$21,$21,$21,$21,$21,$21,$21,$21,$21,$21,$14,$11,$15,$15,$12,$00,$00,$00,$00,$57,$56,$aa,$00 +.byte $13,$13,$13,$13,$20,$21,$21,$21,$21,$21,$21,$21,$47,$21,$21,$21,$48,$21,$21,$14,$11,$3e,$15,$12,$00,$00,$00,$00,$58,$56,$aa,$00 +.byte $13,$13,$13,$13,$20,$21,$21,$21,$21,$21,$21,$21,$42,$21,$21,$21,$4a,$21,$21,$14,$11,$4e,$15,$12,$00,$00,$00,$00,$59,$56,$aa,$00 +.byte $13,$13,$13,$13,$20,$21,$21,$21,$21,$21,$21,$21,$43,$21,$21,$21,$21,$21,$21,$25,$35,$3f,$15,$12,$00,$00,$00,$00,$58,$56,$aa,$00 +.byte $13,$13,$7c,$13,$20,$21,$21,$21,$21,$21,$21,$21,$44,$21,$21,$21,$21,$21,$21,$26,$36,$15,$15,$12,$00,$00,$00,$00,$57,$56,$aa,$00 +.byte $13,$13,$6c,$13,$20,$21,$21,$21,$21,$21,$21,$21,$45,$21,$21,$21,$21,$21,$21,$27,$37,$15,$15,$12,$00,$00,$00,$00,$59,$56,$aa,$00 +.byte $13,$13,$78,$13,$20,$21,$21,$21,$21,$21,$21,$21,$21,$21,$15,$15,$21,$21,$21,$28,$38,$15,$15,$12,$00,$00,$00,$00,$58,$56,$aa,$00 +.byte $13,$13,$7b,$13,$20,$21,$21,$21,$21,$21,$21,$21,$21,$21,$15,$15,$15,$21,$21,$29,$39,$15,$15,$12,$00,$00,$00,$00,$53,$56,$aa,$00 +.byte $13,$13,$6e,$13,$20,$21,$21,$21,$21,$21,$21,$21,$21,$21,$15,$21,$15,$21,$1f,$2a,$3a,$3c,$15,$12,$00,$61,$00,$00,$54,$56,$aa,$00 +.byte $13,$13,$84,$13,$20,$21,$21,$21,$21,$21,$21,$21,$21,$21,$21,$15,$21,$21,$21,$28,$3b,$15,$15,$12,$00,$00,$00,$00,$58,$56,$aa,$00 +.byte $13,$13,$60,$13,$20,$21,$21,$21,$21,$21,$21,$21,$21,$21,$21,$21,$21,$21,$15,$14,$11,$15,$15,$12,$00,$00,$00,$00,$58,$56,$aa,$00 +.byte $13,$13,$60,$13,$20,$21,$21,$21,$21,$21,$21,$21,$21,$21,$21,$48,$21,$21,$15,$14,$11,$15,$15,$12,$00,$00,$00,$00,$5d,$56,$aa,$00 +.byte $13,$13,$60,$13,$20,$21,$21,$21,$21,$21,$21,$21,$21,$21,$21,$49,$21,$21,$21,$14,$11,$3e,$21,$12,$00,$00,$00,$00,$58,$56,$aa,$00 +.byte $13,$13,$13,$13,$20,$21,$21,$21,$21,$21,$21,$21,$21,$21,$21,$49,$21,$21,$21,$14,$11,$3f,$21,$12,$00,$00,$00,$00,$58,$56,$aa,$00 +.byte $13,$13,$13,$13,$20,$21,$21,$21,$21,$21,$21,$21,$21,$21,$21,$49,$21,$21,$21,$14,$11,$3f,$21,$12,$00,$00,$00,$00,$57,$56,$aa,$00 +.byte $13,$13,$13,$13,$20,$21,$21,$21,$21,$21,$21,$21,$21,$21,$21,$4a,$21,$21,$21,$14,$11,$21,$15,$12,$00,$00,$00,$00,$58,$56,$aa,$00 +.byte $13,$13,$76,$13,$20,$21,$21,$21,$21,$21,$21,$21,$42,$21,$21,$21,$21,$21,$21,$14,$11,$15,$15,$12,$00,$00,$00,$00,$58,$56,$5a,$00 +.byte $13,$13,$72,$13,$20,$21,$21,$21,$21,$21,$21,$21,$44,$21,$21,$21,$21,$21,$21,$14,$11,$3e,$21,$12,$00,$00,$00,$00,$59,$56,$9a,$00 +.byte $13,$13,$7c,$13,$20,$21,$21,$21,$21,$21,$21,$21,$43,$21,$21,$21,$21,$21,$21,$22,$32,$4e,$21,$12,$00,$00,$00,$51,$59,$56,$aa,$00 +.byte $13,$13,$7c,$13,$20,$21,$21,$21,$21,$21,$21,$21,$44,$21,$21,$21,$21,$21,$21,$23,$33,$3f,$15,$12,$00,$00,$00,$00,$5c,$56,$6a,$00 +.byte $13,$13,$75,$13,$20,$21,$21,$21,$21,$21,$21,$21,$44,$21,$21,$21,$21,$21,$21,$24,$34,$21,$21,$12,$00,$00,$00,$00,$55,$56,$9a,$00 +.byte $13,$13,$84,$13,$20,$21,$21,$21,$21,$21,$21,$21,$45,$21,$21,$21,$48,$15,$15,$14,$11,$15,$21,$12,$00,$00,$00,$54,$56,$56,$aa,$00 +.byte $13,$13,$65,$13,$20,$21,$21,$21,$21,$21,$21,$21,$46,$21,$21,$21,$4a,$21,$15,$14,$11,$15,$15,$12,$00,$00,$00,$00,$52,$56,$aa,$00 +.byte $13,$13,$13,$13,$20,$21,$21,$21,$21,$21,$21,$21,$21,$21,$21,$21,$21,$21,$21,$14,$11,$15,$15,$12,$00,$00,$00,$00,$57,$56,$aa,$00 + +.byte $13,$13,$13,$13,$20,$21,$21,$21,$21,$21,$21,$21,$21,$21,$21,$21,$21,$21,$21,$14,$11,$15,$21,$12,$00,$31,$31,$31,$58,$56,$ff,$9a +.byte $13,$13,$75,$13,$20,$21,$21,$21,$21,$21,$21,$21,$21,$21,$21,$42,$21,$21,$21,$14,$11,$15,$15,$12,$00,$31,$31,$00,$5d,$56,$ff,$5a +.byte $13,$13,$6e,$13,$20,$21,$21,$21,$21,$21,$21,$21,$21,$21,$21,$43,$21,$21,$21,$14,$11,$3e,$15,$12,$00,$00,$00,$31,$58,$56,$ff,$5a +.byte $13,$13,$7f,$13,$20,$21,$21,$21,$21,$21,$21,$21,$42,$21,$21,$44,$21,$21,$21,$14,$11,$3f,$15,$12,$00,$00,$00,$31,$58,$56,$ff,$aa +.byte $13,$13,$6e,$13,$20,$21,$21,$21,$21,$21,$21,$21,$44,$21,$21,$45,$21,$21,$21,$22,$32,$15,$15,$12,$00,$00,$00,$31,$58,$56,$ff,$56 +.byte $13,$13,$75,$13,$20,$21,$21,$21,$21,$21,$21,$21,$45,$21,$21,$46,$21,$21,$21,$26,$36,$15,$15,$12,$00,$00,$00,$51,$58,$56,$ff,$9a +.byte $13,$13,$84,$13,$20,$21,$21,$21,$21,$21,$21,$21,$21,$21,$21,$21,$21,$21,$21,$27,$37,$15,$15,$12,$00,$00,$00,$00,$58,$56,$ff,$59 +.byte $13,$13,$61,$13,$20,$21,$21,$21,$21,$21,$21,$21,$21,$21,$21,$21,$21,$21,$21,$28,$38,$15,$15,$12,$00,$00,$00,$00,$55,$56,$ff,$5a +.byte $13,$13,$13,$13,$20,$21,$21,$21,$21,$21,$21,$21,$21,$21,$21,$21,$21,$21,$21,$14,$11,$15,$15,$12,$00,$00,$00,$57,$56,$56,$aa,$00 +.byte $13,$13,$13,$13,$20,$21,$21,$21,$21,$21,$21,$21,$47,$21,$21,$21,$48,$21,$21,$22,$32,$3e,$15,$12,$00,$00,$00,$00,$52,$56,$aa,$00 +.byte $13,$13,$13,$13,$20,$21,$21,$21,$21,$21,$21,$21,$42,$21,$21,$21,$4a,$21,$21,$23,$33,$4e,$15,$12,$00,$00,$00,$00,$53,$56,$aa,$00 +.byte $13,$13,$13,$13,$20,$21,$21,$21,$21,$21,$21,$21,$43,$21,$21,$21,$21,$21,$21,$24,$34,$3f,$15,$12,$00,$00,$00,$00,$58,$56,$aa,$00 +.byte $13,$13,$7c,$13,$20,$21,$21,$21,$21,$21,$21,$21,$44,$21,$21,$21,$21,$21,$21,$14,$11,$15,$15,$12,$00,$00,$00,$00,$58,$56,$aa,$00 +.byte $13,$13,$6c,$13,$20,$21,$21,$21,$21,$21,$21,$21,$45,$21,$21,$21,$21,$21,$21,$14,$11,$15,$15,$12,$00,$00,$00,$00,$58,$56,$aa,$00 +.byte $13,$13,$78,$13,$20,$21,$21,$21,$21,$21,$21,$21,$21,$21,$21,$21,$21,$21,$21,$14,$11,$15,$15,$12,$00,$00,$00,$00,$58,$56,$aa,$00 +.byte $13,$13,$7b,$13,$20,$21,$21,$21,$21,$21,$21,$21,$21,$21,$21,$21,$21,$21,$21,$14,$11,$15,$15,$12,$00,$00,$00,$00,$59,$56,$aa,$00 +.byte $13,$13,$6e,$13,$20,$21,$21,$21,$21,$21,$21,$21,$21,$21,$21,$21,$21,$21,$21,$14,$11,$15,$15,$12,$00,$62,$00,$00,$58,$56,$aa,$00 +.byte $13,$13,$84,$13,$20,$21,$21,$21,$21,$21,$21,$21,$21,$21,$21,$21,$21,$21,$21,$29,$39,$15,$15,$12,$00,$00,$00,$00,$59,$56,$aa,$00 +.byte $13,$13,$60,$13,$20,$21,$21,$21,$21,$21,$21,$21,$21,$21,$21,$21,$21,$15,$1f,$2a,$3a,$3d,$15,$12,$00,$00,$00,$00,$58,$56,$aa,$00 +.byte $13,$13,$60,$13,$20,$21,$21,$21,$21,$21,$21,$21,$21,$21,$21,$48,$21,$15,$2d,$2a,$3a,$3c,$15,$12,$00,$00,$00,$00,$5b,$56,$aa,$00 +.byte $13,$13,$60,$13,$20,$21,$21,$21,$21,$21,$21,$21,$21,$21,$21,$49,$21,$21,$2f,$2a,$3a,$3d,$21,$12,$00,$00,$00,$00,$58,$56,$aa,$00 +.byte $13,$13,$13,$13,$20,$21,$21,$21,$21,$21,$21,$21,$21,$21,$21,$49,$21,$21,$21,$28,$3b,$3e,$21,$12,$00,$00,$00,$00,$58,$56,$aa,$00 +.byte $13,$13,$13,$13,$20,$21,$21,$21,$21,$21,$21,$21,$21,$21,$21,$49,$21,$21,$21,$14,$11,$4e,$21,$12,$00,$00,$00,$51,$58,$56,$aa,$00 +.byte $13,$13,$13,$13,$20,$21,$21,$21,$21,$21,$21,$21,$21,$21,$21,$4a,$21,$21,$21,$14,$11,$21,$15,$12,$00,$00,$00,$51,$58,$56,$aa,$00 +.byte $13,$13,$76,$13,$20,$21,$21,$21,$21,$21,$21,$21,$42,$21,$21,$21,$21,$21,$15,$29,$39,$15,$15,$12,$00,$00,$00,$00,$58,$56,$aa,$00 +.byte $13,$13,$72,$13,$20,$21,$21,$21,$21,$21,$21,$21,$44,$21,$21,$21,$21,$15,$2c,$2a,$3a,$3e,$21,$12,$00,$00,$00,$00,$58,$56,$aa,$00 +.byte $13,$13,$7c,$13,$20,$21,$21,$21,$21,$21,$21,$21,$43,$21,$21,$21,$21,$21,$2e,$2a,$3a,$4e,$21,$12,$00,$00,$00,$51,$58,$56,$aa,$00 +.byte $13,$13,$7c,$13,$20,$21,$21,$21,$21,$21,$21,$21,$44,$21,$21,$21,$21,$21,$1f,$2a,$3a,$3f,$15,$12,$00,$00,$00,$00,$5d,$56,$aa,$00 +.byte $13,$13,$75,$13,$20,$21,$21,$21,$21,$21,$21,$21,$44,$21,$21,$21,$21,$21,$15,$28,$3b,$3f,$21,$12,$00,$00,$00,$00,$57,$56,$aa,$00 +.byte $13,$13,$84,$13,$20,$21,$21,$21,$21,$21,$21,$21,$45,$21,$21,$21,$48,$21,$15,$14,$11,$15,$21,$12,$00,$00,$00,$00,$58,$56,$aa,$00 +.byte $13,$13,$65,$13,$20,$21,$21,$21,$21,$21,$21,$21,$46,$21,$21,$21,$4a,$21,$15,$14,$11,$15,$15,$12,$00,$00,$00,$00,$58,$56,$aa,$00 +.byte $13,$13,$13,$13,$20,$21,$21,$21,$21,$21,$21,$21,$21,$21,$21,$21,$21,$21,$21,$14,$11,$15,$15,$12,$00,$00,$00,$00,$58,$56,$aa,$00 + +.byte $13,$13,$13,$13,$20,$21,$21,$21,$21,$21,$21,$21,$21,$21,$21,$21,$21,$21,$21,$14,$11,$15,$21,$12,$00,$31,$31,$31,$58,$56,$ff,$9a +.byte $13,$13,$75,$13,$20,$21,$21,$21,$21,$21,$21,$21,$21,$21,$21,$15,$21,$21,$21,$14,$11,$15,$15,$12,$00,$31,$31,$00,$58,$56,$ff,$5a +.byte $13,$13,$6e,$13,$20,$21,$21,$21,$21,$21,$21,$21,$21,$21,$21,$15,$21,$21,$21,$14,$11,$15,$15,$12,$00,$00,$00,$31,$58,$56,$ff,$5a +.byte $13,$13,$7f,$13,$20,$21,$21,$21,$21,$21,$21,$21,$15,$21,$21,$15,$21,$21,$21,$14,$11,$15,$15,$12,$00,$00,$00,$31,$54,$56,$ff,$59 +.byte $13,$13,$6e,$13,$20,$21,$21,$21,$21,$21,$21,$21,$15,$21,$21,$15,$21,$21,$21,$14,$11,$3e,$15,$12,$00,$00,$00,$31,$54,$56,$ff,$56 +.byte $13,$13,$75,$13,$20,$21,$21,$21,$21,$21,$21,$42,$15,$21,$21,$15,$21,$21,$21,$14,$11,$4e,$15,$12,$00,$00,$00,$51,$58,$56,$ff,$5a +.byte $13,$13,$84,$13,$20,$21,$21,$21,$21,$21,$21,$43,$21,$21,$21,$21,$21,$21,$21,$14,$11,$4e,$15,$12,$00,$00,$00,$00,$58,$56,$ff,$59 +.byte $13,$13,$61,$13,$20,$21,$21,$21,$21,$21,$21,$44,$21,$21,$21,$21,$21,$21,$21,$14,$11,$3f,$15,$12,$00,$00,$00,$00,$58,$56,$ff,$5a +.byte $13,$13,$13,$13,$20,$21,$21,$21,$21,$21,$21,$45,$21,$21,$21,$21,$21,$21,$21,$14,$11,$15,$15,$12,$00,$00,$00,$00,$58,$56,$aa,$00 +.byte $13,$13,$13,$13,$20,$21,$21,$21,$21,$21,$21,$47,$15,$21,$21,$21,$15,$21,$21,$14,$11,$15,$15,$12,$00,$00,$00,$00,$53,$56,$aa,$00 +.byte $13,$13,$13,$13,$20,$21,$21,$21,$21,$21,$21,$21,$15,$21,$21,$21,$15,$21,$21,$14,$11,$15,$15,$12,$00,$00,$00,$00,$58,$56,$aa,$00 +.byte $13,$13,$13,$13,$20,$21,$21,$21,$21,$21,$21,$21,$15,$21,$21,$21,$21,$21,$21,$14,$11,$15,$15,$12,$00,$00,$00,$00,$57,$56,$aa,$00 +.byte $13,$13,$7c,$13,$20,$21,$21,$21,$21,$21,$21,$21,$15,$21,$21,$21,$21,$21,$21,$29,$39,$15,$15,$12,$00,$00,$00,$00,$58,$56,$aa,$00 +.byte $13,$13,$6c,$13,$20,$21,$21,$21,$21,$21,$48,$21,$15,$21,$21,$21,$21,$1d,$1e,$2a,$3a,$3c,$15,$12,$00,$00,$00,$00,$58,$56,$aa,$00 +.byte $13,$13,$78,$13,$20,$21,$21,$21,$21,$21,$49,$21,$21,$21,$21,$21,$21,$21,$21,$2b,$3b,$3e,$15,$12,$00,$00,$00,$00,$58,$56,$aa,$00 +.byte $13,$13,$7b,$13,$20,$21,$21,$21,$21,$21,$4a,$21,$21,$21,$21,$21,$21,$21,$21,$14,$11,$4e,$15,$12,$00,$00,$00,$00,$58,$56,$aa,$00 +.byte $13,$13,$6e,$13,$20,$21,$21,$21,$21,$15,$48,$21,$21,$21,$21,$21,$21,$21,$21,$14,$11,$4e,$15,$12,$00,$63,$00,$00,$58,$56,$aa,$00 +.byte $13,$13,$84,$13,$20,$21,$21,$21,$21,$21,$49,$21,$21,$21,$21,$21,$21,$21,$21,$14,$11,$3f,$15,$12,$00,$00,$00,$00,$58,$56,$aa,$00 +.byte $13,$13,$60,$13,$20,$21,$21,$21,$21,$21,$4a,$21,$21,$21,$21,$21,$21,$15,$15,$14,$11,$15,$15,$12,$00,$00,$00,$00,$59,$56,$aa,$00 +.byte $13,$13,$60,$13,$20,$21,$21,$21,$21,$21,$21,$21,$21,$21,$21,$15,$21,$15,$15,$14,$11,$15,$15,$12,$00,$00,$00,$00,$59,$56,$aa,$00 +.byte $13,$13,$60,$13,$20,$21,$21,$21,$21,$21,$21,$21,$15,$21,$21,$15,$21,$21,$15,$14,$11,$15,$21,$12,$00,$00,$00,$00,$58,$56,$aa,$00 +.byte $13,$13,$13,$13,$20,$21,$21,$21,$21,$21,$21,$42,$21,$21,$21,$15,$21,$21,$21,$29,$39,$15,$21,$12,$00,$00,$00,$00,$58,$56,$aa,$00 +.byte $13,$13,$13,$13,$20,$21,$21,$21,$21,$21,$21,$43,$21,$21,$21,$15,$21,$21,$2c,$2a,$3a,$3c,$21,$12,$00,$00,$00,$50,$58,$56,$aa,$00 +.byte $13,$13,$13,$13,$20,$21,$21,$21,$21,$21,$21,$44,$15,$21,$21,$15,$21,$21,$2d,$2a,$3a,$3e,$15,$12,$00,$00,$00,$50,$58,$56,$aa,$00 +.byte $13,$13,$76,$13,$20,$21,$21,$21,$21,$21,$21,$45,$15,$21,$21,$21,$21,$21,$15,$2b,$3b,$3f,$15,$12,$00,$00,$00,$00,$54,$56,$aa,$00 +.byte $13,$13,$72,$13,$20,$21,$21,$21,$21,$21,$21,$46,$15,$21,$21,$21,$21,$15,$15,$14,$11,$3f,$21,$12,$00,$00,$00,$00,$59,$56,$aa,$00 +.byte $13,$13,$7c,$13,$20,$21,$21,$21,$21,$21,$21,$21,$15,$21,$21,$21,$21,$21,$15,$14,$11,$15,$21,$12,$00,$00,$00,$51,$58,$56,$aa,$00 +.byte $13,$13,$7c,$13,$20,$21,$21,$21,$21,$21,$21,$21,$15,$21,$21,$21,$21,$21,$15,$14,$11,$15,$15,$12,$00,$00,$00,$00,$58,$56,$aa,$00 +.byte $13,$13,$75,$13,$20,$21,$21,$21,$21,$21,$21,$21,$15,$21,$21,$21,$21,$21,$15,$14,$11,$15,$21,$12,$00,$00,$00,$00,$5d,$56,$aa,$00 +.byte $13,$13,$84,$13,$20,$21,$21,$21,$21,$21,$21,$21,$15,$21,$21,$21,$15,$21,$15,$14,$11,$15,$21,$12,$00,$00,$00,$00,$58,$56,$aa,$00 +.byte $13,$13,$65,$13,$20,$21,$21,$21,$21,$21,$21,$21,$15,$21,$21,$21,$15,$15,$15,$14,$11,$15,$15,$12,$00,$00,$00,$00,$58,$56,$aa,$00 +.byte $13,$13,$13,$13,$20,$21,$21,$21,$21,$21,$21,$21,$21,$21,$21,$21,$21,$21,$21,$22,$32,$15,$15,$12,$00,$00,$00,$00,$58,$56,$aa,$00 + +AttributeData: +.byte $FF,$AA,$AA,$AA,$9A,$00,$00,$00 +.byte $FF,$AA,$AA,$AA,$5A,$00,$00,$00 +.byte $FF,$AA,$AA,$AA,$5A,$00,$00,$00 +.byte $FF,$AA,$AA,$6A,$A6,$00,$00,$00 +.byte $FF,$AA,$AA,$9A,$59,$00,$00,$00 +.byte $FF,$AA,$AA,$AA,$5A,$00,$00,$00 +.byte $FF,$AA,$AA,$AA,$9A,$00,$00,$00 +.byte $FF,$AA,$AA,$AA,$5A,$00,$00,$00 + +.byte $FF,$AA,$AA,$5A,$9A,$00,$00,$00 +.byte $FF,$AA,$AA,$9A,$5A,$00,$00,$00 +.byte $FF,$AA,$AA,$AA,$5A,$00,$00,$00 +.byte $FF,$AA,$AA,$6A,$56,$00,$00,$00 +.byte $FF,$AA,$AA,$9A,$59,$00,$00,$00 +.byte $FF,$AA,$AA,$AA,$5A,$00,$00,$00 +.byte $FF,$AA,$AA,$AA,$5A,$00,$00,$00 +.byte $FF,$AA,$AA,$AA,$5A,$00,$00,$00 + +.byte $FF,$AA,$AA,$AA,$9A,$00,$00,$00 +.byte $FF,$AA,$AA,$AA,$5A,$00,$00,$00 +.byte $FF,$AA,$AA,$AA,$5A,$00,$00,$00 +.byte $FF,$AA,$AA,$AA,$AA,$00,$00,$00 +.byte $FF,$AA,$AA,$AA,$56,$00,$00,$00 +.byte $FF,$AA,$AA,$AA,$9A,$00,$00,$00 +.byte $FF,$AA,$AA,$AA,$59,$00,$00,$00 +.byte $FF,$AA,$AA,$AA,$5A,$00,$00,$00 + +.byte $FF,$AA,$AA,$AA,$9A,$00,$00,$00 +.byte $FF,$AA,$AA,$AA,$5A,$00,$00,$00 +.byte $FF,$AA,$AA,$AA,$5A,$00,$00,$00 +.byte $FF,$AA,$AA,$AA,$59,$00,$00,$00 +.byte $FF,$AA,$AA,$AA,$56,$00,$00,$00 +.byte $FF,$AA,$AA,$AA,$5A,$00,$00,$00 +.byte $FF,$AA,$AA,$AA,$59,$00,$00,$00 +.byte $FF,$AA,$AA,$AA,$5A,$00,$00,$00 + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; This is the OAM sprite attribute data data we will use in our game. +;; We have only one big metasprite that is composed of 2x4 hardware sprites. +;; The OAM is organized in sets of 4 bytes per tile. +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +SpriteData: +; Y tile# attributes +.byte $27, $70, %00100001, $6 ; [] Sprite 0, used to split screen +; Y tile# attributes X +.byte $A6, $60, %00000000, $70 ; _______________ +.byte $A6, $61, %00000000, $78 ; \ o o o o o / <-- Ship (4 tiles) +.byte $A6, $62, %00000000, $80 ; \___________/ +.byte $A6, $63, %00000000, $88 ; + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Here we add the CHR-ROM data, included from an external .CHR file +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +.segment "CHARS" +.incbin "atlantico.chr" + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Vectors with the addresses of the handlers that we always add at $FFFA +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +.segment "VECTORS" +.word NMI ; Address (2 bytes) of the NMI handler +.word Reset ; Address (2 bytes) of the Reset handler +.word IRQ ; Address (2 bytes) of the IRQ handler diff --git a/atlantico/atlantico.chr b/atlantico/atlantico.chr new file mode 100755 index 0000000000000000000000000000000000000000..3fb49e34656e687d0456e9326d7aaf0e67579a3d GIT binary patch literal 8192 zcmeHLPiP}m7=P0VPJ7v;#lCCZqL%C-f#`(bVf9!VJ*kVwJ@wGTDobW!R(laF zyCNGX8xaMG2d^H4ofz175PMr#sF{==0)lNI%4W=TK7ZevOePg8>_P38`55NC-~0Z& z@AtholgSezZ#8whC4{9uWeF+2|8hj=(A(#ygqXP?^7SGK?Fph{UFzSuU2@TJf4gi- z{NB4I9Uc9J#}py9Zi%U4oy7V&QN1Yj-@I{0#{1)|Jg}lR-Qm6vs`afZ)&KYH+)Fq7 z6jWrXOvPpj8#c1k;zSpX4pjMG&+J&HX^(Bm7xUi0NcDVZ!$8Pt+VvoO87 zw0y-xTbQ4D$2@y{|H{ZH8p6OJTDk1z9U%s6q{j$`asoSDTa$(guv?&oI7I7{{b?!_H z&tohS^fhCq?hbf=m?n9y+$aDBk3)i1+5wN+*vKwurR}M>F{ep66-h-&L=}iC5LFGjAZcA){`;3AoO*)T#i=RZj=kx3*n zrBI(=czW)WH^YH|?@2APjhUK` z({KV4<}7<-409Yt1^N;v0|~54J{)6)4iXCVjA_t2hI#CtL`~@fmod&6{+=2Q$Y7Itj{lHCR0`uiq_5TUpOs^7 zxl+JGi21osHy+OgWfy8ZrRzQg=`!Xu5#YsZ6aI31bg+tk;riO@=U?0i<73R~4EVrh zB>APnEARUUu{@HP&tKa5a*SiwFTJ*UF*D95@H(lbR=eGH8&t_cD#&&S!PC`kb-Ud% zaO?J9pG@fYHdFji{y<$1_T>jnN7^6#`ZImx(0=n~TIoaIpiS1Ry6Wp2n1SQ#svrOE zw$p#mB_-SM?(A@U*Vku}0nguRdw2bO$`0eh9SpR$TQ{>=C7WeEJCqTPFQV>`woUF{ zv#RTQwMn#Nx7)i;MN5NE8m}J9riM+XqU)-zgMh?#&Br=X2M(UsY1H(UY_&nu=IPqo z@WynQZ{QcCjB?0=cn}cUa~ww|ynDZom+P%;`kA=4xWaE;2w62LWg^eJcaP)ED$6n+ zyEDEpqb#gQK5_xT9sT>6^JSjRp9hg;7@(9c&`8e literal 0 HcmV?d00001 diff --git a/atlantico/atlantico.nes b/atlantico/atlantico.nes new file mode 100644 index 0000000000000000000000000000000000000000..42ea5d88874083bc87ac98e790933314fe5db845 GIT binary patch literal 40976 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 literal 0 HcmV?d00001 diff --git a/atlantico/consts.inc b/atlantico/consts.inc new file mode 100755 index 0000000..867d4b7 --- /dev/null +++ b/atlantico/consts.inc @@ -0,0 +1,29 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Constants for PPU registers mapped from addresses $2000 to $2007 +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +PPU_CTRL = $2000 +PPU_MASK = $2001 +PPU_STATUS = $2002 +OAM_ADDR = $2003 +OAM_DATA = $2004 +PPU_SCROLL = $2005 +PPU_ADDR = $2006 +PPU_DATA = $2007 +PPU_OAM_DMA = $4014 + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Controller ports and buttons +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +JOYPAD1 = $4016 +JOYPAD2 = $4017 + +BUTTON_A = $80 ; 10000000 +BUTTON_B = $40 ; 01000000 +BUTTON_SELECT = $20 ; 00100000 +BUTTON_START = $10 ; 00010000 +BUTTON_UP = $08 ; 00001000 +BUTTON_DOWN = $04 ; 00000100 +BUTTON_LEFT = $02 ; 00000010 +BUTTON_RIGHT = $01 ; 00000001 + +MAX_ACTORS = 10 diff --git a/atlantico/header.inc b/atlantico/header.inc new file mode 100755 index 0000000..7dc8f99 --- /dev/null +++ b/atlantico/header.inc @@ -0,0 +1,13 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; The iNES header (contains a total of 16 bytes with the flags at $7FF0) +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +.segment "HEADER" +.byte $4E,$45,$53,$1A ; 4 bytes with the characters 'N','E','S','\n' +.byte $02 ; How many 16KB of PRG-ROM we'll use (=32KB) +.byte $01 ; How many 8KB of CHR-ROM we'll use (=8KB) +.byte %00000001 ; Vertical mirroring, no battery, mapper 0 +.byte %00000000 ; mapper 0, playchoice, NES 2.0 +.byte $00 ; No PRG-RAM +.byte $00 ; NTSC TV format +.byte $00 ; Extra flags for TV format and PRG-RAM +.byte $00,$00,$00,$00,$00 ; Unused padding to complete 16 bytes of header diff --git a/atlantico/nes.cfg b/atlantico/nes.cfg new file mode 100755 index 0000000..7daa74b --- /dev/null +++ b/atlantico/nes.cfg @@ -0,0 +1,16 @@ +MEMORY { + ZP: start = $0000, size = $0100, type = rw, file = ""; + OAM: start = $0200, size = $0100, type = rw, file = ""; + RAM: start = $0300, size = $0500, type = rw, file = ""; + HDR: start = $7FF0, size = $0010, type = ro, file = %O, fill = yes, fillval = $00; + PRG: start = $8000, size = $8000, type = ro, file = %O, fill = yes, fillval = $00; + CHR: start = $0000, size = $2000, type = ro, file = %O, fill = yes, fillval = $00; +} + +SEGMENTS { + ZEROPAGE: load = ZP, type = zp; + HEADER: load = HDR, type = ro; + CODE: load = PRG, type = ro, start = $8000; + CHARS: load = CHR, type = ro, optional = yes; + VECTORS: load = PRG, type = ro, start = $FFFA; +} \ No newline at end of file diff --git a/atlantico/reset.inc b/atlantico/reset.inc new file mode 100755 index 0000000..9e924fa --- /dev/null +++ b/atlantico/reset.inc @@ -0,0 +1,43 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Macro to initialize the NES by disabling rendering and clearing RAM values +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +.macro INIT_NES + sei ; Disable all IRQ interrupts + cld ; Clear decimal mode (not supported by the NES) + ldx #$FF + txs ; Initialize the stack pointer at address $FF + + inx ; Increment X, causing a rolloff from $FF to $00 + stx PPU_CTRL ; Disable NMI + stx PPU_MASK ; Disable rendering (masking background and sprites) + stx $4010 ; Disable DMC IRQs + + lda #$40 + sta $4017 ; Disable APU frame IRQ + + bit PPU_STATUS ; Read from PPU_STATUS to reset the VBlank flag +Wait1stVBlank: ; Wait for the first VBlank from the PPU + bit PPU_STATUS ; Perform a bit-wise check with the PPU_STATUS port + bpl Wait1stVBlank ; Loop until bit-7 (sign bit) is 1 (inside VBlank) + + txa ; A = 0 +ClearRAM: + sta $0000,x ; Zero RAM addresses from $0000 to $00FF + sta $0100,x ; Zero RAM addresses from $0100 to $01FF + + lda #$FF ; We cannot load $0200-$02FF (OAM) with zero + sta $0200,x ; So we load it with $FF (all sprites off-screen) + + lda #0 ; And we proceed to zero the next ranges + sta $0300,x ; Zero RAM addresses from $0300 to $03FF + sta $0400,x ; Zero RAM addresses from $0400 to $04FF + sta $0500,x ; Zero RAM addresses from $0500 to $05FF + sta $0600,x ; Zero RAM addresses from $0600 to $06FF + sta $0700,x ; Zero RAM addresses from $0700 to $07FF + inx + bne ClearRAM + +Wait2ndVBlank: ; Wait for the second VBlank from the PPU + bit PPU_STATUS ; Perform a bit-wise check with the PPU_STATUS port + bpl Wait2ndVBlank ; Loop until bit-7 (sign bit) is 1 (inside VBlank) +.endmacro diff --git a/atlantico/tagbardebug.log b/atlantico/tagbardebug.log new file mode 100644 index 0000000..bf7248e --- /dev/null +++ b/atlantico/tagbardebug.log @@ -0,0 +1,49 @@ + + +NVIM v0.8.1 +Build type: Debug +LuaJIT 2.1.0-beta3 +Compilation: /usr/bin/cc -DNVIM_TS_HAS_SET_MATCH_LIMIT -DNVIM_TS_HAS_SET_ALLOCATOR -g -Wall -Wextra -pedantic -Wno-unused-parameter -Wstrict-prototypes -std=gnu99 -Wshadow -Wconversion -Wdouble-promotion -Wmissing-noreturn -Wmissing-format-attribute -Wmissing-prototypes -Wimplicit-fallthrough -Wvla -fstack-protector-strong -fno-common -fdiagnostics-color=always -DINCLUDE_GENERATED_DECLARATIONS -D_GNU_SOURCE -DNVIM_MSGPACK_HAS_FLOAT32 -DNVIM_UNIBI_HAS_VAR_FROM -DMIN_LOG_LEVEL=1 -DEXITFREE -I/opt/nightlies/neovim/build/cmake.config -I/opt/nightlies/neovim/src -I/opt/nightlies/neovim/.deps/usr/include -I/usr/include -I/opt/nightlies/neovim/build/src/nvim/auto -I/opt/nightlies/neovim/build/include +Compiled by tyrel@blackbox-jr + +Features: +acl +iconv +tui +See ":help feature-compile" + + system vimrc file: "$VIM/sysinit.vim" + fall-back for $VIM: "/usr/local/share/nvim" + +Run :checkhealth for more info1970-01-01 21:57:14.324701: goto_win(): wincmd p, 1 +1970-01-01 21:57:14.325123: goto_win(): 2wincmd w, 1 +1970-01-01 21:57:14.333705: goto_win(): 2wincmd w, 1 +1970-01-01 21:57:14.333977: goto_win(): 3wincmd w, 1 +1970-01-01 21:57:14.335883: AutoUpdate called [/home/tyrel/code/6502nes/atlantico/] +1970-01-01 21:57:14.336102: Vim filetype: 'asm_ca65', sanitized filetype: 'asm_ca65' +1970-01-01 21:57:14.336214: Checking if file is valid [/home/tyrel/code/6502nes/atlantico/] +1970-01-01 21:57:14.336360: File not readable +1970-01-01 21:57:14.336459: Not a valid file, stopping processing +1970-01-01 21:57:14.340545: AutoUpdate called [/home/tyrel/code/6502nes/atlantico/] +1970-01-01 21:57:14.340720: Vim filetype: 'asm_ca65', sanitized filetype: 'asm_ca65' +1970-01-01 21:57:14.340811: Checking if file is valid [/home/tyrel/code/6502nes/atlantico/] +1970-01-01 21:57:14.340927: File not readable +1970-01-01 21:57:14.341007: Not a valid file, stopping processing +1970-01-01 21:57:14.349687: AutoUpdate called [term://~/code/6502nes/atlantico//146139:/bin/fish] +1970-01-01 21:57:14.349788: Vim filetype: 'floaterm', sanitized filetype: 'floaterm' +1970-01-01 21:57:14.349826: Checking if file is valid [term://~/code/6502nes/atlantico//146139:/bin/fish] +1970-01-01 21:57:14.349900: File not readable +1970-01-01 21:57:14.349932: Not a valid file, stopping processing +1970-01-01 21:57:15.291586: AutoUpdate called [/home/tyrel/code/6502nes/atlantico/__Tagbar__.1] +1970-01-01 21:57:15.291682: In Tagbar window, stopping processing +1970-01-01 21:57:15.574356: ToggleWindow called +1970-01-01 21:57:15.574851: CloseWindow called +1970-01-01 21:57:15.597904: AutoUpdate called [/home/tyrel/code/6502nes/atlantico/atlantico.asm] +1970-01-01 21:57:15.597985: Vim filetype: 'asm_ca65', sanitized filetype: 'asm_ca65' +1970-01-01 21:57:15.598027: Checking if file is valid [/home/tyrel/code/6502nes/atlantico/atlantico.asm] +1970-01-01 21:57:15.598108: Unsupported filetype: asm_ca65 +1970-01-01 21:57:15.598141: Not a valid file, stopping processing +1970-01-01 21:57:15.598199: goto_win(): wincmd p, 0 +1970-01-01 21:57:15.598267: CloseWindow finished +1970-01-01 21:57:19.699439: AutoUpdate called [/home/tyrel/code/6502nes/atlantico/atlantico.asm] +1970-01-01 21:57:19.699592: Vim filetype: 'asm_ca65', sanitized filetype: 'asm_ca65' +1970-01-01 21:57:19.699667: Checking if file is valid [/home/tyrel/code/6502nes/atlantico/atlantico.asm] +1970-01-01 21:57:19.699815: Unsupported filetype: asm_ca65 +1970-01-01 21:57:19.699876: Not a valid file, stopping processing diff --git a/atlantico/utils.inc b/atlantico/utils.inc new file mode 100755 index 0000000..b21f1f6 --- /dev/null +++ b/atlantico/utils.inc @@ -0,0 +1,37 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Macro to set a 16-bit address to the PPU_ADDR register (at $2006) +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +.macro PPU_SETADDR addr + bit PPU_STATUS ; Read from PPU_STATUS to reset the address latch + lda #>addr ; Fetch the hi-byte from 16-bit address + sta PPU_ADDR ; Store the hi-byte into PPU_ADDR $2006 + lda #@>TfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009F3EARv6 CHxJGL literal 0 HcmV?d00001 diff --git a/clearmem.o b/clearmem.o new file mode 100644 index 0000000000000000000000000000000000000000..494017c5aaa30ce0b7e790deea7d5a5df7d193c1 GIT binary patch literal 607 zcmX|-%P#|A6vglTW;%VV*0Uv4QWm65S|RLIl}JjNJ|q&Nnprear7aN)A)*m`8;^~J zrN70}PHcp~f_oY*7e`e85e9s7vC zSWa%(LF$%Rk@iT;228ONrm+X6a{y-JewZPbirKjj3wnuPSttGkG8}aAC0&fj#T+D_ zV?Piwq`PFK2+94QJpainiQA_g?HM-s$CQx{(4%exx2?5;YF=qI!S`su#%xi~@bYxQG&f4|MQ$>6 zD>bU2a%p-hTuj8`GvR2suzR%MJPJ#jjmB-J)v%hjSfg@kIa2t>Os=>ywc5dAt!^D# xb!~NJSz9*O^;C8tZJ61GWIn0Q=W;rNV>4}L*OE(VeYKFu*o)~@K5OQPegTDLNe=)3 literal 0 HcmV?d00001 diff --git a/helloppu/Makefile b/helloppu/Makefile index 4eeb862..761e146 100755 --- a/helloppu/Makefile +++ b/helloppu/Makefile @@ -15,4 +15,4 @@ clean: # Rule to run the final cartridge .nes file in the FCEUX emulator ############################################################################### run: - fceux helloppu.nes + on-workspace 1 "fceux helloppu.nes" diff --git a/helloppu/helloppu.nes b/helloppu/helloppu.nes new file mode 100644 index 0000000000000000000000000000000000000000..6039ab741f5839e87c28b52e63b47499cd9b6f3a GIT binary patch literal 40976 zcmeIup-Kc{5C`ztRqu*;+XRDr$#D1t7Pr{MVii2!!uVxjw^@V_j&1h{Hly*PPayXK zCW9V^L%VS0H}D?@Cd}}=y0|{7tJu^$p6_xuPOmR%`7yhH8@`@aeWbohebX-5?yxY}j6o$_^Gag@mB~DA5*7=&GY6A(eNFbp}S~U~f{h)Rn#&(bpQZghX)xy}3 z?I6?@QKcY(%8msUNQfOjfJJvmEMUo!Ur_M}SRg*nJGNM{g2jE#d){;Iy+>o;#=~|n zMnng?61tkYrgWX@`bLO0Eh1KZV;FC0RGYRmeyD}-ZK5@ef5ZlTw}yRx4s#LN`uOz8 z=Z?*1ADkVYj#&u5OB&%jCxh@=()_ANjwJ3X z`3KICeCzT#;vbobe*q47lK6cw3&cN(nJ4+`FEJa$PsC)1e-`rsS)Y(ACasY*mNaI! z#3V_+)^LHW$Kx7fWW6X_wurN0?i2qO@gp&>k$g&G#>x7ESj;q{h&5@RFUVnz^S zVy+=NV%8AjVkV*~rgUa8mx!N%gRAaDSFJ`@twtUfb^cqtsUtcrU)6*-HArp{yS$Wq zM7*SfPxF?}tame4Qv4a&zsYcSwX-xU=;XIo}=?l z=*U7)lm96F9}c}~RUB1kB5zOoT*|U!iFde6Tmou94iMhf4SXH*-2?=<3wXdQz~z6# zyq-Ku4vQ6i%6(0FHj*Qdg-9Mi;?)rC=x9Xe@gx$Y%-WVimw^nRe=3Jks7?Ye>7pbG zb4U$T49Ec~9f;P^QUK1OB?fN@?b+$#D=K&APkPeE{;uf!(P~jN|igo(QeQR`~6UL z=Xj`N`Cjv3m>OoqpdZA1?8&?lH2cfF{@!*gXuo3$tuW~NUL~?u+D8N1t_00?blUAs zH+(PbT050{);<4qyHG8b9KVWjtnFIOhA?lI{OYcEr)2Lm%4O$n$t#xp_+F_{ulhBj FzX2wbzDocA literal 0 HcmV?d00001 diff --git a/loadbackground/._Makefile b/loadbackground/._Makefile new file mode 100755 index 0000000000000000000000000000000000000000..fb522db0253fb6b9cc6ea88458c694c57ff1940e GIT binary patch literal 4096 zcmZQz6=P>$Vqox1Ojhs@R)|o50+1L3ClDJkFz{^v(m+1nBL)UWIUt(=a103v0xDsI z>fivfE6}ts1EoRY{0t1@$@#f@i3J5Ysd^!)6(z2D$@wXndFfycjN(8_fPp~@p(ZD> zxTLf=H6&Mz%WPE|$Vqox1Ojhs@R)|o50+1L3ClDJkFz{^v(m+1nBL)UWIUt(=a103v0xDsI z=wMg?WDB5a0m{L|rIPb=^%4sTa#Hnj5{pYpi&Ill5=&B*1A;+%CU4l81fqA%PSXL= zqhK@yMnhmU1V%$(Gz3ONU^E0qLtr!nMnhmU1V%$(Gz4&k0I0JG!eAg5l95@gP?TDn zUs{x$s*sjnl&z4NSCX1nl9`{En3GefkdvBLqL7r6n3oOg3qy4cX$sZBh E0GvZAMF0Q* literal 0 HcmV?d00001 diff --git a/loadbackground/._nes.cfg b/loadbackground/._nes.cfg new file mode 100755 index 0000000000000000000000000000000000000000..f06e1f5e60a594266cf3ab5d6fa920cdffc422c3 GIT binary patch literal 4096 zcmZQz6=P>$Vqox1Ojhs@R)|o50+1L3ClDJkFz{^v(m+1nBL)UWIUt(=a103v0xDsI z=wMg?WDB5a0m{L|rIPb=^%4sTa#Hnj5{pYpi&Ill5=&B*1A;+%WNxod0@1GVD`i0R zC>RZa(GVC7fzc2c4S~@R7!85Z5Eu=C(GVC7fzc2c4FOys0P1XlFc`>%WMmdA6r~pD zmlh?bDx~EXWh-Rnm89mCWaj53=Hyf=!cbj9nnLwI+$%B+a{vDW E0OP+YaR2}S literal 0 HcmV?d00001 diff --git a/loadbackground/Makefile b/loadbackground/Makefile new file mode 100755 index 0000000..b6fc78a --- /dev/null +++ b/loadbackground/Makefile @@ -0,0 +1,18 @@ +############################################################################### +# Rule to assemble and link all assembly files +############################################################################### +build: + ca65 loadbackground.asm -o loadbackground.o + ld65 -C nes.cfg loadbackground.o -o loadbackground.nes + +############################################################################### +# Rule to remove all object (.o) files and cartridge (.nes) files +############################################################################### +clean: + rm *.o *.nes + +############################################################################### +# Rule to run the final cartridge .nes file in the FCEUX emulator +############################################################################### +run: + on-workspace 1 "fceux loadbackground.nes" diff --git a/loadbackground/background.nam b/loadbackground/background.nam new file mode 100755 index 0000000000000000000000000000000000000000..64ab54fa8d3db9807fcd88542ccf26b21f60a8dc GIT binary patch literal 1024 zcmY#U83e%090YMX#8edwEKn36skgMU20^lv4kf0Y)~e`W>-2Ch}B dfFuYrFc^RcW(FR9ejvfX0HWaFKNRpo0RRQb3?2Xg literal 0 HcmV?d00001 diff --git a/loadbackground/consts.inc b/loadbackground/consts.inc new file mode 100755 index 0000000..922ec59 --- /dev/null +++ b/loadbackground/consts.inc @@ -0,0 +1,31 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Constants for PPU registers mapped from addresses $2000 to $2007 +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +PPU_CTRL = $2000 +PPU_MASK = $2001 +PPU_STATUS = $2002 +OAM_ADDR = $2003 +OAM_DATA = $2004 +PPU_SCROLL = $2005 +PPU_ADDR = $2006 +PPU_DATA = $2007 +PPU_OAM_DMA = $4014 + + + + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Constants for BUTTONS +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +JOYPAD1 = $4016 +JOYPAD2 = $4017 + +BUTTON_A = $80 ; 10000000 +BUTTON_B = $40 ; 01000000 +BUTTON_SELECT = $20 ; 00100000 +BUTTON_START = $10 ; 00010000 +BUTTON_UP = $08 ; 00001000 +BUTTON_DOWN = $04 ; 00000100 +BUTTON_LEFT = $02 ; 00000010 +BUTTON_RIGHT = $01 ; 00000001 diff --git a/loadbackground/header.inc b/loadbackground/header.inc new file mode 100755 index 0000000..768b34f --- /dev/null +++ b/loadbackground/header.inc @@ -0,0 +1,13 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; The iNES header (contains a total of 16 bytes with the flags at $7F00) +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +.segment "HEADER" +.byte $4E,$45,$53,$1A ; 4 bytes with the characters 'N','E','S','\n' +.byte $02 ; How many 16KB of PRG-ROM we'll use (=32KB) +.byte $01 ; How many 8KB of CHR-ROM we'll use (=8KB) +.byte %00000000 ; Horz mirroring, no battery, mapper 0 +.byte %00000000 ; mapper 0, playchoice, NES 2.0 +.byte $00 ; No PRG-RAM +.byte $00 ; NTSC TV format +.byte $00 ; Extra flags for TV format and PRG-RAM +.byte $00,$00,$00,$00,$00 ; Unused padding to complete 16 bytes of header diff --git a/loadbackground/loadbackground.asm b/loadbackground/loadbackground.asm new file mode 100755 index 0000000..4142aed --- /dev/null +++ b/loadbackground/loadbackground.asm @@ -0,0 +1,306 @@ +; HEADER +.include "consts.inc" +.include "header.inc" +.include "reset.inc" +.include "utils.inc" +;;;;;;;;;;;;;;;;;;;;;;;;;;;; +.segment "ZEROPAGE" +Buttons: .res 1 ; Button bytes +XPos: .res 1 ; Char X position +YPos: .res 1 ; Char Y Position +Frame: .res 1 ; Reserve 1 byte to store the number of frames +Clock60: .res 1 ; Store a counter that increments every second (60 frames) +BgPtr: .res 2 ; Reserve 2 bytes store a ptr to bg address + ; Store low then high bytes (little endian) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; PRG-ROM code located at $8000 +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +.segment "CODE" + +; LoadPalette +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Subroutine to load all 32 color palette values from ROM +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +.proc LoadPalette + PPU_SETADDR $3F00 + ldy #0 ; Y = 0 +: lda PaletteData,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 +; LoadBackground +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Subroutine to load the background 255 tiles in first nametable +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +.proc LoadBackground + lda #BackgroundData + sta BgPtr+1 + + PPU_SETADDR $2000 ; nametable 0 + + ldx #$00 ; high byte (0-3) + ldy #$00 ; low byte (0-FF) + +OuterLoop: +InnerLoop: + lda (BgPtr),y ; fetch the value pointed by bgptr+y + sta PPU_DATA ; store value in ppu data + iny ; y++ + cpy #0 ; if y == 0 then wrapped + beq IncreaseHiByte ; then: increase hi byte + jmp InnerLoop ; else: continue inner loop +IncreaseHiByte: + inc BgPtr+1 ; we increment the hi byte pointer to point to the next bg section + inx ; X++ + cpx #4 ; break condition (4 sections bg) + bne OuterLoop ; if x is stil not 4, loop back to outer loop + + rts ; Return from subroutine +.endproc +; LoadText +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Subroutine to load text in the nametable until it finds a 0-terminator +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +.proc LoadText + PPU_SETADDR $21CB + + ldy #0 ;y=0 +Loop: + lda TextMessage,y ; Fetch character byte from ROM + beq EndLoop ; If the character is 0, end loop + + cmp #32 ; Compare to ASCII 32 + bne DrawLetter ; if its not, draw the letter +DrawSpace: + lda #$24 ; tile $24 is a space + sta PPU_DATA ; Store PPU_DATA with the empty tile + jmp NextChar ; go to next character +DrawLetter: + sec ; set carry + sbc #55 ; subtract 55 from the ASCII value, to get the character tile as chars start at 10 + sta PPU_DATA ; store the data and advance the PPU_ADDR +NextChar: + iny ; y++, next character from the string + jmp Loop ; go back to top of loop + +EndLoop: + rts ; Return from subroutine +.endproc +; LoadSprites +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Subroutine to load all 16 sprites into OAM-RAM starting at $0200 +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +.proc LoadSprites + ldx #0 ; +LoadSprites: ; + lda SpriteData,x ; fetch bytes from SpriteData lookup table + sta $0200,x ; store bytes starting at OAM $0200 + inx ; X++ + cpx #32; + bne LoadSprites ; Loop 16 times (4 hardware sprites, 4 bytes each) + rts ; Return from subroutine +.endproc +;ReadControllers +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Reset handler (called when the NES resets or powers on) +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +.proc ReadControllers + lda #1 ; A=1 + sta Buttons ; Buttons=1 (This will carry to the bcc, not an input value) + + sta JOYPAD1 ; Set latch to 1 to begin input + lsr ; A=0 by shifting right, quicker maybe + sta JOYPAD1 ; Set latch to 0 to begin output +LoopButtons: + lda JOYPAD1 ; 1. reads a bit from the controller line and inverts its value + ; 2. sends a signal to the clock line to shift the bits inside the controller + + lsr ; we shift right to place that 1bit + rol Buttons ; rolls bits to the left, placing the carry inside the first bit of `Buttons` in ram + bcc LoopButtons ; loop until carry is set (from that initial 1 we had inside buttons + rts +.endproc + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Reset handler (called when the NES resets or powers on) +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +Reset: + INIT_NES ; Macro to initialize the NES to a known state + +InitVariables: + lda #0 + sta Frame + sta Clock60 + + + ldx #0 + lda SpriteData,x + sta YPos + inx + inx + inx + lda SpriteData,x + sta XPos + + +Main: + jsr LoadPalette ; Jump to subroutine LoadPalette + jsr LoadBackground ; Jump to subroutine LoadBackground + jsr LoadSprites + +EnablePPURendering: + lda #%10010000 ; enable NMI and set bg to use second pattern table + sta PPU_CTRL + lda #0 ; disable ppu scrolling + sta PPU_SCROLL ; latch (in X) + sta PPU_SCROLL ; latch (in y) + lda #%00011110 + sta PPU_MASK + +LoopForever: + jmp LoopForever ; Force an infinite execution loop + +; NMI +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; NMI interrupt handler +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +NMI: + inc Frame ; Frame ++ + ; ------------------------------------- + ; As soon as we enter the NMI handler, start OAM copy + lda #$02 ; every frame we copy sprite data starting at $02** + sta PPU_OAM_DMA ; The OAM DMA Copy starts when we write to PPU_OAM_DMA + ; ------------------------------------- + + jsr ReadControllers ; Jump to the subroutine that checks the controllers + +CheckRightButton: + lda Buttons + and #BUTTON_RIGHT + beq CheckLeftButton + inc XPos ; X++ +CheckLeftButton: + lda Buttons + and #BUTTON_LEFT + beq CheckDownButton + dec XPos ; X-- +CheckDownButton: + lda Buttons + and #BUTTON_DOWN + beq CheckUpButton + inc YPos ; Y++ +CheckUpButton: + lda Buttons + and #BUTTON_UP + beq :+ + dec YPos ; Y-- +: + +UpdateSpritePosition: + lda XPos + sta $0203 + sta $020B + clc + adc #8 + sta $0207 + sta $020F + + lda YPos + sta $0200 + sta $0204 + clc + adc #8 + sta $0208 + sta $020C + +;;;; + lda Frame ; increment clock60 every time the frame reaches 60 + cmp #60 ; frame equal to 60? + bne :+ ; branch to end if not 60, carry on! + inc Clock60 + lda #0 + sta Frame ; Zero Frame Counter +: + + rti ; Return from interrupt + +; IRQ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; IRQ interrupt handler +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +IRQ: + rti ; Return from interrupt + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Hardcoded list of color values in ROM to be loaded by the PPU +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +PaletteData: +.byte $22,$29,$1A,$0f, $22,$36,$17,$0f, $22,$30,$21,$0f, $22,$27,$17,$0f ; Background CP 00 01 10 11 +.byte $22,$16,$27,$18, $22,$1a,$30,$27, $22,$16,$30,$27, $22,$0f,$36,$17 ; sprite CP 00 01 10 11 + +;BackgroundData +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Background data with tile numbers that must be copied to the nametable +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +BackgroundData: +.incbin "background.nam" + + +;SpriteData +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; This is the OAM sprite attribute data data we will use in our game +;; We have only one big metasprite that is composed of 4 hardware sprites +;; the OAM is organized in sets of 4 bytes per tile +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; Sprite Attribute Byte: +; ---------------------- +; 76543210 +; ||| || +; ||| ++- Color Palette of Sprite: Choose which set of 4 from the 16 colors to use +; ||| +; ||+------ Priority (0: in front of BG, 1: Behind BG) +; |+------- Flip Horizontally +; +-------- Flip Vertically +SpriteData: +;-------------------------------- +; Mario: +; Y tile# attributes X +.byte $AE, $3A, %00000000, $98 +.byte $AE, $37, %00000000, $A0 +.byte $B6, $4F, %00000000, $98 +.byte $B6, $4F, %01000000, $A0 +;-------------------------------- +; Goomba: +; Y tile# attributes X +.byte $93, $70, %00100011, $C7 +.byte $93, $71, %00100011, $CF +.byte $9B, $72, %00100011, $C7 +.byte $9B, $73, %00100011, $CF +;-------------------------------- +;End Sprites + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Hardcoded ASCII message stored in ROM with 0-terminator +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +TextMessage: +.byte "TYREL SOUZA",$0 + + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Here we add the CHR-ROM data, included from an external .CHR file +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +.segment "CHARS" +.incbin "mario.chr" +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Vectors with the addresses of the handlers that we always add at $FFFA +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +.segment "VECTORS" +.word NMI ; Address (2 bytes) of the NMI handler +.word Reset ; Address (2 bytes) of the Reset handler +.word IRQ ; Address (2 bytes) of the IRQ handler diff --git a/loadbackground/loadbackground.nes b/loadbackground/loadbackground.nes new file mode 100644 index 0000000000000000000000000000000000000000..df3623bc02053f8565f1fc049a2207d84c562035 GIT binary patch literal 40976 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 E3G(&CEC2ui literal 0 HcmV?d00001 diff --git a/loadbackground/loadbackground.o b/loadbackground/loadbackground.o new file mode 100644 index 0000000000000000000000000000000000000000..82d990c8ad418a6d4295564a826dee2922f1c945 GIT binary patch literal 19543 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 literal 0 HcmV?d00001 diff --git a/loadbackground/mario.chr b/loadbackground/mario.chr new file mode 100755 index 0000000000000000000000000000000000000000..0e3a3cbea6cad91408e984204388767b9fec619a GIT binary patch literal 8192 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 literal 0 HcmV?d00001 diff --git a/loadbackground/nes.cfg b/loadbackground/nes.cfg new file mode 100755 index 0000000..7daa74b --- /dev/null +++ b/loadbackground/nes.cfg @@ -0,0 +1,16 @@ +MEMORY { + ZP: start = $0000, size = $0100, type = rw, file = ""; + OAM: start = $0200, size = $0100, type = rw, file = ""; + RAM: start = $0300, size = $0500, type = rw, file = ""; + HDR: start = $7FF0, size = $0010, type = ro, file = %O, fill = yes, fillval = $00; + PRG: start = $8000, size = $8000, type = ro, file = %O, fill = yes, fillval = $00; + CHR: start = $0000, size = $2000, type = ro, file = %O, fill = yes, fillval = $00; +} + +SEGMENTS { + ZEROPAGE: load = ZP, type = zp; + HEADER: load = HDR, type = ro; + CODE: load = PRG, type = ro, start = $8000; + CHARS: load = CHR, type = ro, optional = yes; + VECTORS: load = PRG, type = ro, start = $FFFA; +} \ No newline at end of file diff --git a/loadbackground/reset.inc b/loadbackground/reset.inc new file mode 100755 index 0000000..bbd04e4 --- /dev/null +++ b/loadbackground/reset.inc @@ -0,0 +1,43 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Macro to initialize the NES by disabling rendering and clearing RAM values +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +.macro INIT_NES + sei ; Disable all IRQ interrupts + cld ; Clear decimal mode (not supported by the NES) + ldx #$FF + txs ; Initialize the stack pointer at address $FF + + inx ; Increment X, causing a rolloff from $FF to $00 + stx PPU_CTRL ; Disable NMI + stx PPU_MASK ; Disable rendering (masking background and sprites) + stx $4010 ; Disable DMC IRQs + + lda #$40 + sta $4017 ; Disable APU frame IRQ + + bit PPU_STATUS ; Read from PPU_STATUS to reset the VBlank flag +Wait1stVBlank: ; Wait for the first VBlank from the PPU + bit PPU_STATUS ; Perform a bit-wise check with the PPU_STATUS port + bpl Wait1stVBlank ; Loop until bit-7 (sign bit) is 1 (inside VBlank) + + txa ; A = 0 +ClearRAM: + sta $0000,x ; Zero RAM addresses from $0000 to $00FF + sta $0100,x ; Zero RAM addresses from $0100 to $01FF + + lda #$FF ; We init OAM data with $FF to hide sprites + sta $0200,x ; Zero RAM addresses from $0200 to $02FF with $FF + lda #0 + + sta $0300,x ; Zero RAM addresses from $0300 to $03FF + sta $0400,x ; Zero RAM addresses from $0400 to $04FF + sta $0500,x ; Zero RAM addresses from $0500 to $05FF + sta $0600,x ; Zero RAM addresses from $0600 to $06FF + sta $0700,x ; Zero RAM addresses from $0700 to $07FF + inx + bne ClearRAM + +Wait2ndVBlank: ; Wait for the second VBlank from the PPU + bit PPU_STATUS ; Perform a bit-wise check with the PPU_STATUS port + bpl Wait2ndVBlank ; Loop until bit-7 (sign bit) is 1 (inside VBlank) +.endmacro diff --git a/loadbackground/utils.inc b/loadbackground/utils.inc new file mode 100644 index 0000000..09f23ee --- /dev/null +++ b/loadbackground/utils.inc @@ -0,0 +1,12 @@ +.macro PPU_SETADDR addr + bit PPU_STATUS ; read from PPU_STATUS to reset latch + lda #>addr ; > means get high byte from `addr` + sta PPU_ADDR + lda #$Vqox1Ojhs@R)|o50+1L3ClDJkFz{^v(m+1nBL)UWIUt(=a103v0xDsI z>fivfE6}ts1EoRY{0t1@$@#f@i3J5Ysd^!)6(z2D$@wXndFfycjN(8_fPp~@p(ZD> zxTLf=H6&Mz%WPE|$Vqox1Ojhs@R)|o50+1L3ClDJkFz{^v(m+1nBL)UWIUt(=a103v0xDsI z=wMg?WDB5a0m{L|rIPb=^%4sTa#Hnj5{pYpi&Ill5=&B*1A;+%LbmTs0@0g0u1JFD zQ7{?;qaiRF0;3@?8UmvsFd71*Aut*OqaiRF0;3@?8UnaN0Myw8VK9&j$;d2LC`v8P zFD*(=RY=P(%2vqCD@n~O$;{77%*m-#$Vp8rQAo;3%*zJ$g`v8JG==JaxL0Ht$Vqox1Ojhs@R)|o50+1L3ClDJkFz{^v(m+1nBL)UWIUt(=a103v0xDsI z=wMg?WDB5a0m{L|rIPb=^%4sTa#Hnj5{pYpi&Ill5=&B*1A;+%WNxod0@1GVD`i0R zC>RZa(GVC7fzc2c4S~@R7!85Z5Eu=C(GVC7fzc2c4FOys0P1XlFc`>%WMmdA6r~pD zmlh?bDx~EXWh-Rnm89mCWaj53=Hyf=!cbj9nnLwI+$%B+a{vDW E0OP+YaR2}S literal 0 HcmV?d00001 diff --git a/loadtext/Makefile b/loadtext/Makefile new file mode 100755 index 0000000..d13d385 --- /dev/null +++ b/loadtext/Makefile @@ -0,0 +1,18 @@ +############################################################################### +# Rule to assemble and link all assembly files +############################################################################### +build: + ca65 loadtext.asm -o loadtext.o + ld65 -C nes.cfg loadtext.o -o loadtext.nes + +############################################################################### +# Rule to remove all object (.o) files and cartridge (.nes) files +############################################################################### +clean: + rm *.o *.nes + +############################################################################### +# Rule to run the final cartridge .nes file in the FCEUX emulator +############################################################################### +run: + fceux loadtext.nes diff --git a/loadtext/consts.inc b/loadtext/consts.inc new file mode 100755 index 0000000..2b75ec9 --- /dev/null +++ b/loadtext/consts.inc @@ -0,0 +1,11 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Constants for PPU registers mapped from addresses $2000 to $2007 +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +PPU_CTRL = $2000 +PPU_MASK = $2001 +PPU_STATUS = $2002 +OAM_ADDR = $2003 +OAM_DATA = $2004 +PPU_SCROLL = $2005 +PPU_ADDR = $2006 +PPU_DATA = $2007 diff --git a/loadtext/header.inc b/loadtext/header.inc new file mode 100755 index 0000000..768b34f --- /dev/null +++ b/loadtext/header.inc @@ -0,0 +1,13 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; The iNES header (contains a total of 16 bytes with the flags at $7F00) +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +.segment "HEADER" +.byte $4E,$45,$53,$1A ; 4 bytes with the characters 'N','E','S','\n' +.byte $02 ; How many 16KB of PRG-ROM we'll use (=32KB) +.byte $01 ; How many 8KB of CHR-ROM we'll use (=8KB) +.byte %00000000 ; Horz mirroring, no battery, mapper 0 +.byte %00000000 ; mapper 0, playchoice, NES 2.0 +.byte $00 ; No PRG-RAM +.byte $00 ; NTSC TV format +.byte $00 ; Extra flags for TV format and PRG-RAM +.byte $00,$00,$00,$00,$00 ; Unused padding to complete 16 bytes of header diff --git a/loadtext/loadtext.asm b/loadtext/loadtext.asm new file mode 100755 index 0000000..55525d4 --- /dev/null +++ b/loadtext/loadtext.asm @@ -0,0 +1,193 @@ +.include "consts.inc" +.include "header.inc" +.include "reset.inc" +.include "utils.inc" + +.segment "ZEROPAGE" +Frame: .res 1 ; Reserve 1 byte to store the number of frames +Clock60: .res 1 ; Reserve 1 byte to store a counter that increments every second (60 frames) +BgPtr: .res 2 ; Reserve 2 bytes (16 bits) to store a pointer to the background address + ; (we store first the lo-byte, and immediately after, the hi-byte) - little endian + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; PRG-ROM code located at $8000 +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +.segment "CODE" + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Subroutine to load all 32 color palette values from ROM +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +.proc LoadPalette + PPU_SETADDR $3F00 + ldy #0 ; Y = 0 +: lda PaletteData,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 + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Subroutine to load tiles and attributes into the first nametable +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +.proc LoadBackground + lda #BackgroundData ; Fetch the hi-byte of BackgroundData address + sta BgPtr+1 + + PPU_SETADDR $2000 + + ldx #$00 ; X = 0 --> x is the outer loop index (hi-byte) from $0 to $4 + ldy #$00 ; Y = 0 --> y is the inner loop index (lo-byte) from $0 to $FF +OuterLoop: +InnerLoop: + lda (BgPtr),y ; Fetch the value *pointed* by BgPtr + Y + sta PPU_DATA ; Store in the PPU data + iny ; Y++ + cpy #0 ; If Y == 0 (wrapped around 256 times)? + beq IncreaseHiByte ; Then: we need to increase the hi-byte + jmp InnerLoop ; Else: Continue with the inner loop +IncreaseHiByte: + inc BgPtr+1 ; We increment the hi-byte pointer to point to the next background section (next 255-chunk) + inx ; X++ + cpx #4 ; Compare X with #4 + bne OuterLoop ; If X is still not 4, then we keep looping back to the outer loop + rts ; Return from subroutine +.endproc + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Subroutine to load text in the nametable until it finds a 0-terminator +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +.proc LoadText + + ;; TODO: + ;; Loop all characters from ROM and load/display the text in the nametable. + ;; Bonus points if you code manages to display an empty tile for [space]. + + rts ; Return from subroutine +.endproc + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Reset handler (called when the NES resets or powers on) +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +Reset: + INIT_NES ; Macro to initialize the NES to a known state + + lda #0 + sta Frame ; Frame = 0 + sta Clock60 ; Clock60 = 0 + +Main: + jsr LoadPalette ; Call LoadPalette subroutine to load 32 colors into our palette + jsr LoadBackground ; Call LoadBackground subroutine to load a full nametable of tiles and attributes + jsr LoadText ; Call LoadText subroutine to draw the text message on the nametable + +EnablePPURendering: + lda #%10010000 ; Enable NMI and set background to use the 2nd pattern table (at $1000) + sta PPU_CTRL + lda #0 + sta PPU_SCROLL ; Disable scroll in X + sta PPU_SCROLL ; Disable scroll in Y + lda #%00011110 + sta PPU_MASK ; Set PPU_MASK bits to render the background + +LoopForever: + jmp LoopForever ; Force an infinite execution loop + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; NMI interrupt handler +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +NMI: + inc Frame ; Frame++ + + lda Frame ; Increment Clock60 every time we reach 60 frames (NTSC = 60Hz) + cmp #60 ; Is Frame equal to #60? + bne :+ ; If not, bypass Clock60 increment + inc Clock60 ; But if it is 60, then increment Clock60 and zero Frame counter + lda #0 + sta Frame +: + rti ; Return from interrupt + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; IRQ interrupt handler +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +IRQ: + rti ; Return from interrupt + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Hardcoded list of color values in ROM to be loaded by the PPU +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +PaletteData: +.byte $22,$29,$1A,$0F, $22,$36,$17,$0F, $22,$30,$21,$0F, $22,$27,$17,$0F ; Background palette +.byte $22,$16,$27,$18, $22,$1A,$30,$27, $22,$16,$30,$27, $22,$0F,$36,$17 ; Sprite palette + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Background data with tile numbers that must be copied to the nametable +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +BackgroundData: +.byte $24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24 +.byte $24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24 +.byte $24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24 +.byte $24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24 +.byte $24,$24,$24,$24,$24,$36,$37,$36,$37,$36,$37,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24 +.byte $24,$24,$24,$24,$35,$25,$25,$25,$25,$25,$25,$38,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$36,$37,$24,$24,$24,$24,$24 +.byte $24,$24,$24,$24,$39,$3A,$3B,$3A,$3B,$3A,$3B,$3C,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$35,$25,$25,$38,$24,$24,$24,$24 +.byte $24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$39,$3A,$3B,$3C,$24,$24,$24,$24 +.byte $24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24 +.byte $24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24 +.byte $24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$53,$54,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24 +.byte $24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$55,$56,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24 +.byte $24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24 +.byte $24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24 +.byte $24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24 +.byte $24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24 +.byte $24,$24,$53,$54,$24,$24,$24,$24,$24,$24,$24,$24,$45,$45,$53,$54,$45,$45,$53,$54,$45,$45,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24 +.byte $24,$24,$55,$56,$24,$24,$24,$24,$24,$24,$24,$24,$47,$47,$55,$56,$47,$47,$55,$56,$47,$47,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24 +.byte $24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24 +.byte $24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24 +.byte $24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$60,$61,$62,$63,$24,$24,$24,$24 +.byte $24,$24,$24,$24,$24,$24,$31,$32,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$64,$65,$66,$67,$24,$24,$24,$24 +.byte $24,$24,$24,$24,$24,$30,$26,$34,$33,$24,$24,$24,$24,$36,$37,$36,$37,$24,$24,$24,$24,$24,$24,$24,$68,$69,$26,$6A,$24,$24,$24,$24 +.byte $24,$24,$24,$24,$30,$26,$26,$26,$26,$33,$24,$24,$35,$25,$25,$25,$25,$38,$24,$24,$24,$24,$24,$24,$68,$69,$26,$6A,$24,$24,$24,$24 +.byte $B4,$B5,$B4,$B5,$B4,$B5,$B4,$B5,$B4,$B5,$B4,$B5,$B4,$B5,$B4,$B5,$B4,$B5,$B4,$B5,$B4,$B5,$B4,$B5,$B4,$B5,$B4,$B5,$B4,$B5,$B4,$B5 +.byte $B6,$B7,$B6,$B7,$B6,$B7,$B6,$B7,$B6,$B7,$B6,$B7,$B6,$B7,$B6,$B7,$B6,$B7,$B6,$B7,$B6,$B7,$B6,$B7,$B6,$B7,$B6,$B7,$B6,$B7,$B6,$B7 +.byte $B4,$B5,$B4,$B5,$B4,$B5,$B4,$B5,$B4,$B5,$B4,$B5,$B4,$B5,$B4,$B5,$B4,$B5,$B4,$B5,$B4,$B5,$B4,$B5,$B4,$B5,$B4,$B5,$B4,$B5,$B4,$B6 +.byte $B6,$B7,$B6,$B7,$B6,$B7,$B6,$B7,$B6,$B7,$B6,$B7,$B6,$B7,$B6,$B7,$B6,$B7,$B6,$B7,$B6,$B7,$B6,$B7,$B6,$B7,$B6,$B7,$B6,$B7,$B6,$B7 +.byte $B4,$B5,$B4,$B5,$B4,$B5,$B4,$B5,$B4,$B5,$B4,$B5,$B4,$B5,$B4,$B5,$B4,$B5,$B4,$B5,$B4,$B5,$B4,$B5,$B4,$B5,$B4,$B5,$B4,$B5,$B4,$B5 +.byte $B6,$B7,$B6,$B7,$B6,$B7,$B6,$B7,$B6,$B7,$B6,$B7,$B6,$B7,$B6,$B7,$B6,$B7,$B6,$B7,$B6,$B7,$B6,$B7,$B6,$B7,$B6,$B7,$B6,$B7,$B6,$B7 + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Attributes tell which palette is used by a group of tiles in the nametable +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +AttributeData: +.byte %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000 +.byte %00000000, %10101010, %10101010, %00000000, %00000000, %00000000, %10101010, %00000000 +.byte %00000000, %00000000, %00000000, %00000000, %11111111, %00000000, %00000000, %00000000 +.byte %00000000, %00000000, %10101010, %10101010, %10101010, %10101010, %00000000, %00000000 +.byte %11111111, %00000000, %00000000, %00001111, %00001111, %00000011, %00000000, %00000000 +.byte %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000 +.byte %11111111, %11111111, %11111111, %11111111, %11111111, %11111111, %11111111, %11111111 +.byte %11111111, %11111111, %11111111, %11111111, %11111111, %11111111, %11111111, %11111111 + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Hardcoded ASCII message stored in ROM with 0-terminator +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +TextMessage: +.byte "HELLO WORLD",$0 + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Here we add the CHR-ROM data, included from an external .CHR file +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +.segment "CHARS" +.incbin "mario.chr" + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Vectors with the addresses of the handlers that we always add at $FFFA +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +.segment "VECTORS" +.word NMI ; Address (2 bytes) of the NMI handler +.word Reset ; Address (2 bytes) of the Reset handler +.word IRQ ; Address (2 bytes) of the IRQ handler diff --git a/loadtext/loadtext.nes b/loadtext/loadtext.nes new file mode 100644 index 0000000000000000000000000000000000000000..378f4c280c978b3285979b4bbaf510cbb397eedf GIT binary patch literal 40976 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 literal 0 HcmV?d00001 diff --git a/loadtext/loadtext.o b/loadtext/loadtext.o new file mode 100644 index 0000000000000000000000000000000000000000..2660b08cd0dede32fa24cbc2a43bb007e82a7c26 GIT binary patch literal 20386 zcmdUX3z$^ZmF_-O)m7CGx{8NTLeo_ZZ9@{3>Yz|S*{7O^q9RRrNKA-SgAI}(lr%yM zO;sWIxEUkFI~d|k0!b!L#F;PVPGU?ZBSlEsB-aGI*El3NbSXy6T!W>klv382|6ltQ zUC?dfd|zfhvK!X<&pKQ|Euu-WBC8K`2WPUN?muI zQU>t#_Hho54xG2)c$ZVDXKzsI5CrzNX}P(!+}G`Mhr`jI+nqIwarl{g(EpD`5(`Vj{ElbBLj|7w&r(UTv9J?!(ajB!_ zK|?tlA$@$*bhP}vp^Ps$TIMQ;8(bV7RgRW>H1kuMiNjuH+@Opf8n;#%+tk({!D{1H zp;>HkVJZk)nQ8}AAe}|k3XUe$Sm|tmZb8V#u zjQN!5sJymMq=OQ{N~0vQm7X(#tU|)Bf*cS{~L0{<$Sd;C#CODubLs1iDT&Ikju}K+Dk~zi$bG1||!u3Z_g8doYu z)@7`q4<;z%HIlgTF_Ov3=yEiVQ^pZT^HkVlIhsGMjE5b~W0B9%98k^&RLIdh9Y+Jl zi8%UWj^;tA4-O9)%K3#608Zt+6b;yXi+$`;hTqZbQ^pygpLaCRRE}NB(d<>uuPVdQ z{1F}(FYqxpZ~@QNICu}LZJ z>)@h19N=tYH5==S%55&=3ZlW{T4}Js$_N=>GOD&IP~zF*#8GtOY@XN1IeLdOYM^VU z@d)dwLdLhW>M!%OB4m74A6$^BH-_N^c^9!&Iz_?XQ$Z(NB|aw^F*lIRCpu#)y&z+{)S|6ea%PXGSJ z$O5Wb_?OeyXk0`4{$gYiRo(cP)7NN>q-jMJ|7=<3%3n^0Uch7w z?Yn?UH|_gxCvg_pPO^+-`3GC@O^MGxMVk#?{kYJ^|6+QJ=mrQ{rXxZ+{Xd zuZiRel8FO|NVZA5Fqxze4W#cp-mT2BibTrzEYW!)_UWa(a1IIcv}ph`@m#qpd3wnJ zByz6YdFti#R*I}5k%B(^K{>u>T(6AplU$hS31f*een4_zqVE~^qi=j)=wBCpLTrA* z7)AerT$t#4#zwjqtGrHMFj&{v zw8Ge;yeL}*O*2KD&7=$Ij0y=q6j!-Iu}B={K*!j zGFf8FDi#ab*j{22GEBsi$BlK$0|ek)4pl)S{}~u(C6rg^wTih+TI_^Ou7u%}uCA_R zk~02yT9vS}8-RQ<9}OVbZUD{K4M4mi9uC0&B9ls)K{b5B1oA`D0NEUI5rt*qp)fJ* zXA=7-Oqk&F;F%uzxt+>eQ&$lC{j@Wy>+bV;*j!G^;2D#vg!8# zrhm!L5+I3;-2fVs8x;M@^-9*Vc5EZRmI2_@_B1ucy8^zH*oLl>3aX@FqoKIT4aZYn zOgpw@wctbd!k;>Rz%S$I81-?$S2c`XxReFVhbjk@CXNWD7+r<+Sx6b2Jj59;N(| zv)JkJR8`lA3`#|K>R46TLMY_NoGbDiu5@f8nuEcX27`Q$Z&bh^))o5{ywp)Qrt`m^~$J}20$MQ`lZ<5l6089Zp$IG2C9z%EJo zWWB4Vrbc61zqB>SD(D|X8GyPP7)xAVSMT#EjkEDw0;Z=K(Plf!=-aZAd2X0uO#pBwRD%s$4c_? zcpN#ke9E%Uum>=2=c(LVxm+SnY$m(Aqfy;|DOq4gXSPKeVzDxbaZMYtTbj>Oq3t9h-u>(V&w^1 zo}kYySc`}Z`y;BbLGurJQg+@@-a7bxF&ESPXrY+ZI%C;bthKf68uEe7mX@%@gI1Z% z*!t1)1Hzwi^~@L(`OzuU&W<_hOiZ$n-xYb19Y*YF4oA9EFo=B9^ljXD`t)gHPN(%n zJ!W#Ge($|gC&;&~;|K4Z9hF#u|GK*(8Y}DIwr!}H$f$!`w;r@aKcd!CnsdbfyWHFv zL}W{i#FeTJ2J3Ci@y%n)l*>chvTVK+0l)#2WvM_kxu&*%QV*y9P$Fl)13OfX4sJeTioNlFak zeVvNiQ+l2?m!?{3tFQ_!$-|I7Tr1@|9LgAq;e~u0im(0BmXE~~o#X7aR&4pk?nwUS zQeG$eu*ObLO+fQ8K$+5((Bqsr-tToer7X&t8#lg9dE#-KyTt$K7kTPlLS9|x0eDuBVu6y%n?^5!WYwrCuDcwg{q+z)0 zg^v?CrHq}($3h6b$0>84>VE#gADt{pOj_GMa@(xI#?zAbB6HbNYtI&9uh$VA!v;T3 zj~(U`=M(C&io9r$_}^depXay7;qr2Ui#(^EI!qE)v0KWm`{>4#|F&=ac+n3BF%e^Y zP_MuKy2xv;=4046%TL)CByVadB3Q@dt#dh(=Vd&3@@sTrUShypGG*F7zpKY*HFj~^ z;&BHXm^T9_bLJ5};Y6Z@i-mR{!X``pP+xrx^Sj_RG0r@CoP26$I>WZ74DR5Z9t3qC z-f|VO+hayA-mLj?$^1M=P%ZU0~x zjiES^fiRW|I>u~q(Vs;I-g(f5ELTx@g-vXO{FI54Q-TM1)ucAYs;#*HFxIA^TfxVej%cHOsIuhXzd*#685KbF3eOj$usxUPmW6Fr{e5mV!2 zYmNNcGbp3`6N$Cr`5pG+m zV@#>RRabmek9(<=-+cVYu@`<$`P9ngiAYQLlY&vwHHpL&;!jk${{7CB#;?Ab&G-{K zem)uThZ%g7fgeIER;*Yi*jpFfv}u#v8}j}mg@SDvDVTU;%KX7U9sS)A;?x#%^2BLV zrCm@%tV*sgdTDS4!XX1@~Z@SRc~*)7fmI zQ^tXpv7Y@(y^e>Gn5DXk1&J$6pHB2fZ8J7;BHc;Rqn2_88zy`+7RTN7Q0XriaKaHR z7O6jz4If4l8BAqkLYG_;B;Vt6j1G<*=^!o^lT#f=Yb$Z2yHF?;pL&WoXeO7$(s$iO zT-Somnc5<8cvpJw%o(wUdh)lVmQIVBctA-R+#Qw4BWScd`eypUuRi@cW#HrZvJO4J zsIe2FQ@48}ip2(Ak)=#AzZYWZH1VNLpYr2ANN_T>#jM}4<6`pf-hNNdiO$X!iLUtee|A|?m|AFiIE@Aq+MUL^jw)r zb{U?aUSl^J9*lfuiZX@#UbJXh5g*!ARV=^|Vr(&(!5up!hVQ;-+rbwTi7ffhpU+1F zd1B~SyKyT@oJv9e&^IJL8x{3icC6No9(C}z_{8ZOyX=-|owQN*SEJibTBgao!K-d- zJ9#Q3@+MZ&i6;vZC%7dweb?wd#pMrflDjC6p%Jq|Fi6b#Ydu&-Z3j`Emw zMokLq`El&HAgZr1rmrUhM~*y6nQS^8E6urv!{zdN{eJTG+RV~6`-To0G_)o}e$Zbt zWXPr3=c*BZE?w5-Ns}fGA3j9-ov&5hr)FxtAM3q$HcTDKypir=ahg51DiuLaE#sWH zIc1&Eb1qnsn9YA71Iz67Kw&SvZ`W(7Y5sFw`_?m#>x~1_UYLGxa}trUada70p?ExD z@0UWoe@@_@M%t4v6q3mnyT44YiuoO0v0r5pPrmi$+xA?Uj(KaUwo_j9`mJ8edRMSI z6bgl!E+@vO2e&B1=W>H@+lf)$vU+=kKVfV`C}i^wym99iOpwxE2flmLZC6gy*x|0N zt*>v<@#9cl2R65cP#Lt0oW@td!eb6VU4i@);47A-{wXBG@MK3*YOr2bd=ZEGoB|_)(%WW&iD_+4$V&y5@SABNgeA7)g-F#$s zAHN%~po`xid&UU{c@?AQJ6fuE83w>zBK z14r~Lm-5G+!B1C8aaf9no}OP1WM|hinQr$0`n4Yd{q)e9f$RbEWOu|rfc*2t;>rH? zqICBFeDt&^8laz^Vr^X{F+jg4?+fJ^w|0`w_rnLtl*^Z6$S0E^{q0c84CfA<{U7xTN;mVNhOn z0qpggtG2dw%`Ndb`Q>%T!Xuc%odNkCuV2Nn<{)-rZDyKx${wcE6~KIY^?l@Ho&Q#G zf3K943HgUrwKhmuJD<$I2febU+WGC-RTYLIbKd{?t|5p0=zg`LXm*;K74}QH^3TA6Mj~ddj_9W7vQc692$9+0+o7aFChG z3SYOQZm;{kavxhSO&PnrL?@PmlE^Rjk9Sz(Po1%^H;GQn28I1M|F$HeD_7ciEyJ)-0g+dB!OSa0_Swmzq%7z=D_?G>Wd|$smg^}R z#>JztrD5|=oEX5iay=%ZoQd*gJeHvy#KN@q2FXiroi6R7`C7i*2F)*aOS!boxJz(< z{x&H~?z(Z2@_Cm70jzD-@_J8Fcy_tmrGww3?X--}3*UBic6N%dQt7?-?s(vVd&CCI zGWYD+6C^Gg6$f6t{q{GA@vIg9Qc~{Lt?8{>_ofAdC7z(n8wU<-J@7NU3IPnAti6sO zyI@|q>=4G5{eIJCB%ViG&kh5MPb&AE4&1S?-9lje(Y+W&UI zX}+;|0{#RW)}znjk64tSvP@!8e!s?|9Cys*i}Fgl9Ywvywtqy1x+g5Q3Y4erXCKuV z!?q;y$J&V)k1-?>^SJ~Q@sF42KjN8xr~in9p;!z)+A3Ig2Hi&3n8xs?G47q=ed$vY zB_4f$gn0oQL;BuU`T`!_P>nr~#q8ZXqqdRc0wYKBvsl%-t7zXTJYy%1g1^fB9Wv z(bM~nvj4!cjD`hYAb+EsO8PerP*%AO6sH}wPRUISjU1OsHgH@L9O_D)9fwszLn{;I zT@SzaK9iIyhUz|;j5H{Ne~@WtprJ^>?|pu|NDHa^lAH@3h`lD zk43WHuq?43pl5;4nRBF6JLByFeW zYJNJs?>GBw8O!?3zTenBaXKGc{FogxmbLh?#ZDd1YSF$$5Et95eT(+dQ0jLr{D&oQ zL{x0}&f>?at51z3#v%uOS@)6ha`70vYal-MF}Q@$b+I#04?EyMeDL5kyIpvKM0vS= z0U_30&BwA!h7|J4?RoLt_c8j|J}fIYhe;4gw~K7a==XmRvweI%T0x@D2OoS8Pm^?6 zvuCdc((^)9)zm7)e>G()Dt`7h;$Ozeojdp7Z>Ns`L?V?+BqaWIN7H?+++)92UA zd*2tIU9h0jJX^2gQ!?gY*UVQlYSgHbywfh1Z_)A1GR=>N!@GCyCWh#!QTDS%j^!@< z{R)WUwGI8O3ZlDrhr@BozcF|)T_OJQ;o%xmmV7XCC4N@(#XqV2y{~f>Ng1xCOMWAd zZYQ5SY%~iduO!2Dd%4W%Gw+wiH?l=u`>KDtL*Lo;2IrvCo;I@Kf?3aU%lE)Jk8ms? zpYup*FC8q-23_R08Wm%H;@B=2>rYAKr=gLF_*i>;`|UTU+KJnHk*ou~B9qSK_V3s# z;}{Gx+iutOZEwe7XzMnqS8wnB{Utrvv!zc&CvXk!Wn$E$lz!l0<1iNQa$f*DCF!#I zY%AxN#~8}tgF4wihj&8ZI*nObZ172YaR8}_Xv{W2m`Iz-bK9B<8Qa;82osU_b9*Vg zcOGrndf=Pi{3_P*VrT1^F}ROY#K%t`KstR~@G$Q74HH}*x0c1o)BUbIZqalm7oE&o z9=Fm>Pw9R8^0fXHJjypDv zSSkG8*T3_fwXe%Fh-qgwpE+|XFKax!lV&ECpZGmxxE*UoyEYNC)7AX+X#D#;SYa!{iWkMi+IC^4T&w?+Mb6Vdgz_2duk;f)~;Ra+i#Y~xn8$NlS!C2UHloH z{^hTK{mc5^p?ut+2?!slBj3czASA>dF+$HTcqJ1PhaPhn4hV=KWw12MWbOAV*(W$B zk&opRGf10C{2+stX9oKnQD(5`5opGeO2>>n&Wp_=0m8iYINy)Y6*kHc`w>Qx#0H&N z>?zlexRsJA!zxJvrVb|Z&)0)$B}J#6Ld71crytA8628`=_2}N!H@_pxS$p_e1oLX^ z`^UWCOMht0k6w8(ld=7|@}{rt-%lKRWMNaNXQAu^ zgkD+L)Zn)9-Nww&Jqu@x%)`dDp>O@-YQaDH#dV=astyxBd*sNmXAl4GnBY)P)&Ko} zM~@O8{q4~gj`oILA+CDvH_!d{=u6KL|L$nE!Cm$IzY;(HuP-(||8Fn8NZimg?C`74 z9)6bi*t16tKihQ7#)rXeY9RmWVMnJ=KRR9XPd|Eeded19Zd1bwkvZD1y0+K0q3LKZ z{zU%e-#0bfGtA~6n{hOIRO6zhxy^#|QKO4Su z*REaUwCf?lFYOloriMS(9x~)!(p%9uV#tWm@-EGYL4h&X55mvFkoV$? zs>algYV;FV4X+*ZH-j7l@?Ud}4v75tG4B{^>@SFKTr~D2*O&M0Bi=Xm-w6d{F(!$8 z8=}9AM~F{QZo}b}57uDSsEm-n>j)PL{2}50;DZyT_8AwuaHv#xz2r6`zsu=XONc&8 za-WFdk&aRq^UB?FzD+2;!GyGkVuN@MpFBdki10F^dAw3b5+?Z!$z39YkN+U8CZmet z(ld7m^J_xK@cLR3eDn#aiK6=jR`UEIf!Ka@s}(#SMzWZsg1mo{%OeT#;RdCqFgrdq zgoIE1AmLL8Nb+=W3(*`3;QKvF)i6^VPbZNiNM@0&Bnk4Wn*<+B!aH4}W;D+);^pmf zUeEK-@w}R7BGCw<$K*1;J%ofWEg>!BH5bcmCc_l!4dH5j-QlkQtMLK?mf`pG(AzjIwR} z;Sw?@li({_NFzw_LlmS>lZ)>rA@lzQhd}Ye5@TDcC+IjlFMfx9w z)=@ovBaJkS@KU0WQ|cdti4Qm-{ZQy76d1*8^U1uP#6ztc$eTbimAnd8G(_P$czQrG zkL2aCBwv+tFEjcm)n@iKn!goF>SAmKw|NH;P6CrNN;;6|(=|HpV5RyC{Fw%@Y8qig-;?VY!c zT;4wE%FvA;zq~mTx-7J4*&S=v-x0#ul*^i{makpYxxVxARcn@e=gnKRbjHH@a|GPb zy5RaMauzIXUASn0x2^StrL8k(&KEGVbz!T%IAea>9GyWfGJ{;awWIx(j&)R9xvrzL zW4)j|)~{MEMO9qAuKl)-ipx7!ZR+sMSiN@n=O%?Krmvj0eqHq(*gda(b;tVk9o6=6 zX8Zc~TJop2FaO-ib!+cfb4zU>O zbA5-G3Kqg474vD&pvCR0);D*qzj6BN_BEgL&RE^izHWZ&4Z{BTnp-s6bwm5AHA7~t zXNS)7cP|wa*@~qghpTo`z|Ttll@T?xJ`le$ZVN^?tdDE|7_v_c)uV24eIi{+~uI?=iplX_KnTBhaEX~qIX1ktOEG3kf zs_D9}DlDbxZiO++b{yAr%wKI?daJH;t|+mXUUkuHm#%sL={Q%W_^r2WU`&!#RpZ<( zm9pWkG221QIakG8sw!Fx0(W!{^)VJhpKY05p$H_NVU9Osm(u2ndwp`YN^#htPQCfkM@fa92mmsl82&o&L}x2c8R<#M@NjTa3@Et7o%fK?cP z)eXSv2G~-}B(Q!MKvUWLrAyPo0G91RkXcM;Fh7C1bm`KVB4hr37LFucCrB5od`wa~zN7Q(88YVJj}g z$Oti|oHD#>6;}7$+A|k9&uQq?+S8aisz4E1FDz5yx)wD}%ZeR1f!9=&8LxTNrcJ}3 zrCRh5;2XeyS2Y$q58LkB9VMg6oOgE@%ZZrI$pR{?a;e?h8N%YlG$R`x<|m%S`cxIT z>l`jZXZr~Ge@P}$fd6A4fMgo+_s1*?wgslqTrmK(AM@|5x#ZuB1CAI*7m#6104!4CDL!_Tf4|IslGsTCT@+ znPJshK9@}({Ia5z6{Wc)LIUBwn9M9UosQ=S$M$d?cvn^P?FiyUiFl@6!Xky=f8;tC zVp>WpI&Xf0Va?<}C1*N?Lb}XMc))QntrkUeRZ3a+FX$?kvbJ;1r4Xy8f{_TOt@FcH zg1;3)k`YXrN~U58QxvOcmoTMK>}LixrlF|XoVj83W)`QAm1Cw|V3~voWoW*`*_)Tc zq8qC@?B;0fo=Oh>f?F8*jX?s2xr-Oi&Ic7mo+O`Yx<=c7U0&yB@6MJA&Xp@aTu$wd4ijE01E!NXBIXOw`E#+ZK?Bc6eCoXV4cI?SJb4adkrJT*Vj33**n^a=Q z`udJ>#A{5Uyw?DG3at4^khQ343N7s)r9ngsGI$x%9)S82x#}aMqodUBn3|emi3H4* zOR{)8O~AqeSiKFS4HAH!CCF8KrVea;CJp{*G|1S7&+OB7^;BWkU?`PKu(|8BL2ajl zwMxwkVoOyPZi+2!^X=ZG_^Jh36rl!$!#{=Q<22vwb|pBKc|sRu<<;T^}@wuC4@{ z!0OeTmW6V;DjB+(6Y`O+Mf>3DAtB%MxM?uJ+W%=&E`s(LrORusUw9Om&f!=U9pmxBR4e;F_4lhmNWV@j?8c)UV zj$^;h0FU02NDSPoWRsujx%h`eUthwo00ExI#>dBJpgykG$xPn}uj=|g-i3q!lOOp$ zEzGHC8yZNZky4KK8z$LQ zl4Mzdll``LRY=it3wP;SD46LCJyc{GjxkMBLP#(yoe75E7c#rtFcmiK!86biTd)98 zv`vt5vB&C`v@n1w3X4t)m`ehE`LbJesWr@Q`EPpwDev zdv*z5KQ$nd?VjWB{xVn9xvFH6k!6Z9merDxYWDJ9Mzf{jz^ku4n{i4-m{W@ zj6ndN1_|g90!nsS2+(cY7m&;O0uX=AHzrdpVHSt6p;%JWR-uw%^0MVC=#;}&`r=)8 zt$j3}&3%2xj%qIzf$KKvI%Bh&Kl`aKrS+{pJbZfO-PiQ350@OU=PQ zKc<(KzxSSH#!Hs@@*2nuG_~+V4{-$B?)xgJSqrnrAGR&P!#8(fmp%z5wV9eF+uzs$1;JF zUzzZb;4ULh;`5N8%1(yrI}$*2A;9zn5DthD|8)V?39l|7Ap}%LV0UtTn6;)-Da1h; zX~BH`b+c@<8@11U4u|6bq=v7jp_yfswzr?dnfYDpz8jHk%ARW@rOCAIm=s{yN>yVU zDFe-8TA_&Qajt}*&t!3snO5c`fX>5?^i4OZN-WT(-gslc^QtQX((2XOitD=G(W9zX z-B2(de>|DjG)?dAecU*B`)!5xRIk2qWll@6B&wG>9ft4ig`3Cq_@G3*yT%ne<{!E9X>o zdp1*eRoP-ad>~(O9mgybO(XbyZaaFlEGcTP(j_U_QMg|?2VpgXo!Hsz(IH=jxzv68 z5>M>iee6uBWP#statR0gY=BBO9sF}I$z6>2IRYWsw&>W{89COu`Jr4gW&O5o-9?T) zx$3LyE>5InO=GNd#C1`&X|X$GvNsim*q4+EQ2ZhP4C3$=`Df{9JCX_jiU6pk`~!_r zoyb2)w08O2YsZfs%`+pB`7F+CCczL84u=OrAq93peT363rsU>3oWCmM!4%u8CPNk9&|-4}CUj+Akc>Qx;Qx9%@HQL7|b&wAEW& zn~EjW*kF%;F|oG`7sYBdkN8;AT!;t40cMtteE7jf$YVw!9BJOeM&o>x^DC&Y(&=>f zXHZO2SgXs>naM;ektzAtV8E6egGf9bdT#(DSuM*XI2<-1PY;CO>H4|MJ2M zFMRaT;*JLX!4psX@rD~F&o=PQ`|tb8Pxn8+xq+weCMcyF_$S*f=aGfCPE2<{aR2@H zKX7`$$17RC4Tf3vi?v$qp*oJne<%IbZaxldo@@W7up6?K%7YjQVm7Q4Km9<47b#3(>R3DziB+T#Wc+=xoO-v zj`bXOrg6_SUDLd-zmJ>K^nB5LqqZeKje{H0U7xQ?=9poRR0zwPv7XxT)3)>O8`Jzn z0oUzUyXbju&yZI;f7u&(PXPs=0v$nl-iIOuQ8oUeS`tb}Ip`}!uP z$CLD#@_}5eWD&!4sMX%~yo=ZMA!=m?jws5(0FB|yizc(B8SyYpsK20e67c`^H|UKP zHnab#%&)hM1QrEw(ddOnHmoUIUK=}JNS zn8~3?1XmbYZfa?vx)1p?98VVvsh&W^v`W_WTMc;uU?u&0Y`NShq;YQuNTOOrZVE=D z(MKLCB2V~$B(3V0UJ1up5jk4MIiqQhP0GOp^4r>{aNd9D4UTd%9iP{{x?So&;#>u% z*Z-qCo0}vlu(B;GE=65)W`%KhFg}c?2UuMUlIR2C8FhB5Hnr(t?s-?|m!xFm5Xz#E0Xn9QG##OPoV^oAVYz)-E; z;YrfMwpN^soL|7@7vg+qjMp#)fmSS-BwHZ3XVJUSw!4q|V@!b;y+;E>J;M~4U zz*%e-LBo*K4&~DNrTB4)|M(Psf_Z{#g86B#31(D?g84dkeRZ4@FSuReJ@sSmVmk}y ztOGtl2oT#9k6&)^f4Bdu|5MY20@l!n;#P-H5BuIkLxrG5w?DM_AT7)2r{cjCaexmc z0`OUa{5>|**GK+tgADO4h3l#dp@vaZQDxKpf}2YtpYcAC zZMdgvZ8XyN)6`Gj5aRZ{{u9A4`tRF?liKh3=bkzcf6oj#4Z%bv8gMZZe6$}(F6{>| zUDm~ZW$o>&34-6bdX0dI2@Ru~ZAS?zfh=Z}u6}b*o#HnEe7Ru-1C|Pfk&(=nmX$42 zEiKK#;42?~7z{S`$5s5|{UzH*DA*;feBs2GzkGMU`DEfS;%WS_dv<7O_rB_*xBUa% zBe*BWzEvuwZ#t+?h2wq~rd;e_%6wdLN z*T2-#GSP`-ulertCE{~sc_xl}S)}#Gd=ykO>3DCfhF3}wZI;6mu|A7K+26aXN^9g87)4&^kfe2g?V+yoSXOc06l*0werl5{wZJTTXbH~K@ zyhu|s*$d{j<8*z<9K5@4=!ZZ29?o{Qx}yX25*wQw0!)sL&7+&tys?HqVF9pNR>Pk# zlST($!=ED9CdkviKS4Th02#unE6hr291*40w=`$6!(?Q7LH77~W!H{xe4}T-1L;6Gn!3 zkwWliI~fOnMCOHoRrt}g@b@^11#v>)s}%%| zeZNoRbSgu}C+n+ee)v;JoZ)X8{;}~0(W*#@lu-e+G=DY`%wqf};z!6w^(*_O*B5~3>~ZO zaouQO@aTW-+NDffi>Et&e*TPUVtrfh|Nh`$`o(*@(>44*e{Xkt2<;Qn?diSu-kJW6 z^w;SZezP|H^WXeU`o-pxr%s<9Id$^)Bd5}}=Kubm;o;$ThTk0?O`mUm^Q|}E89w{w z?}x4SQ1jcrd;521y5Ii8nKSL(^G?2Z>g1`BQ>Ra!>K;LR62I>DweyD8tQn@?@S1MX z;=Q|l%i7`ghohsA+dVvr-|)FVcDL`H2YlqVVM}z6QG0%@yZuG#CIQ25zS9jo(7gH1 zh4x?1-?+aH&kvOMKevDX^8?Qh?BCh`m*@#;R=BBa!JGwc(FLuEjxV%IT?=n$?uahx viZ{=XcKlOo;A8mv!M4Q0B^{R~*7=*iy|43Z@Y{zD9qRnEXr>)m50L)_AOs@p literal 0 HcmV?d00001 diff --git a/loadtext/nes.cfg b/loadtext/nes.cfg new file mode 100755 index 0000000..7daa74b --- /dev/null +++ b/loadtext/nes.cfg @@ -0,0 +1,16 @@ +MEMORY { + ZP: start = $0000, size = $0100, type = rw, file = ""; + OAM: start = $0200, size = $0100, type = rw, file = ""; + RAM: start = $0300, size = $0500, type = rw, file = ""; + HDR: start = $7FF0, size = $0010, type = ro, file = %O, fill = yes, fillval = $00; + PRG: start = $8000, size = $8000, type = ro, file = %O, fill = yes, fillval = $00; + CHR: start = $0000, size = $2000, type = ro, file = %O, fill = yes, fillval = $00; +} + +SEGMENTS { + ZEROPAGE: load = ZP, type = zp; + HEADER: load = HDR, type = ro; + CODE: load = PRG, type = ro, start = $8000; + CHARS: load = CHR, type = ro, optional = yes; + VECTORS: load = PRG, type = ro, start = $FFFA; +} \ No newline at end of file diff --git a/loadtext/reset.inc b/loadtext/reset.inc new file mode 100755 index 0000000..7895424 --- /dev/null +++ b/loadtext/reset.inc @@ -0,0 +1,39 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Macro to initialize the NES by disabling rendering and clearing RAM values +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +.macro INIT_NES + sei ; Disable all IRQ interrupts + cld ; Clear decimal mode (not supported by the NES) + ldx #$FF + txs ; Initialize the stack pointer at address $FF + + inx ; Increment X, causing a rolloff from $FF to $00 + stx PPU_CTRL ; Disable NMI + stx PPU_MASK ; Disable rendering (masking background and sprites) + stx $4010 ; Disable DMC IRQs + + lda #$40 + sta $4017 ; Disable APU frame IRQ + + bit PPU_STATUS ; Read from PPU_STATUS to reset the VBlank flag +Wait1stVBlank: ; Wait for the first VBlank from the PPU + bit PPU_STATUS ; Perform a bit-wise check with the PPU_STATUS port + bpl Wait1stVBlank ; Loop until bit-7 (sign bit) is 1 (inside VBlank) + + txa ; A = 0 +ClearRAM: + sta $0000,x ; Zero RAM addresses from $0000 to $00FF + sta $0100,x ; Zero RAM addresses from $0100 to $01FF + sta $0200,x ; Zero RAM addresses from $0200 to $02FF + sta $0300,x ; Zero RAM addresses from $0300 to $03FF + sta $0400,x ; Zero RAM addresses from $0400 to $04FF + sta $0500,x ; Zero RAM addresses from $0500 to $05FF + sta $0600,x ; Zero RAM addresses from $0600 to $06FF + sta $0700,x ; Zero RAM addresses from $0700 to $07FF + inx + bne ClearRAM + +Wait2ndVBlank: ; Wait for the second VBlank from the PPU + bit PPU_STATUS ; Perform a bit-wise check with the PPU_STATUS port + bpl Wait2ndVBlank ; Loop until bit-7 (sign bit) is 1 (inside VBlank) +.endmacro diff --git a/loadtext/utils.inc b/loadtext/utils.inc new file mode 100755 index 0000000..47c9536 --- /dev/null +++ b/loadtext/utils.inc @@ -0,0 +1,12 @@ +.macro PPU_SETADDR addr + bit PPU_STATUS ; Read from PPU_STATUS to reset my address latch + lda #>addr ; Fetch the hi-byte from 16-bit address + sta PPU_ADDR ; Store the hi-byte into PPU_ADDR $2006 + lda #