diff --git a/atlantico/Makefile b/atlantico/Makefile index d8efe12..12f762d 100755 --- a/atlantico/Makefile +++ b/atlantico/Makefile @@ -15,4 +15,5 @@ clean: # Rule to run the final cartridge .nes file in the FCEUX emulator ############################################################################### run: + #on-workspace 4 "fceux atlantico.nes && i3-msg '[id=$(xdotool getactivewindow)] floating enable'" on-workspace 4 "fceux atlantico.nes" diff --git a/atlantico/atlantico.asm b/atlantico/atlantico.asm index 22a1246..610ef11 100755 --- a/atlantico/atlantico.asm +++ b/atlantico/atlantico.asm @@ -4,41 +4,44 @@ .include "reset.inc" .include "utils.inc" +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Variables declared in RAM zero-page +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; .segment "ZEROPAGE" -Buttons: .res 1 ; Pressed buttons (A|B|Select|Start|Up|Dwn|Lft|Rgt) -PrevButtons: .res 1 ; Pressed buttons (A|B|Select|Start|Up|Dwn|Lft|Rgt) PREVIOUSLY +Buttons: .res 1 ; Pressed buttons (A|B|Sel|Start|Up|Dwn|Lft|Rgt) +PrevButtons: .res 1 ; Stores the previous buttons from the last frame -XPos: .res 1 ; Player X 16-bit position (8.8 fixed-point): hi+lo/256px -YPos: .res 1 ; Player Y 16-bit position (8.8 fixed-point): hi+lo/256px +XPos: .res 1 ; Player X 16-bit position (8.8 fixed-point): hi+lo/256px +YPos: .res 1 ; 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) +XVel: .res 1 ; Player X (signed) velocity (in pixels per 256 frames) +YVel: .res 1 ; Player Y (signed) velocity (in pixels per 256 frames) -PrevSubmarine: .res 1 ; how long ago we added previous submarine in seconds +PrevSubmarine: .res 1 ; Stores the value in seconds that the last submarine was added +PrevAirplane: .res 1 ; Stores the value in seconds that the last airplane was added -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) +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) -SprPtr: .res 2 ; pointer to the sprite address - 16bits (lo,hi) +BgPtr: .res 2 ; Pointer to background address - 16bits (lo,hi) +SprPtr: .res 2 ; Pointer to the sprite 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 +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 -ParamTileNum: .res 1 ; Used as param to subrouting -ParamNumTiles: .res 1 ; Used as param to subrouting -ParamAttribs: .res 1 ; Used as param to subrouting +ParamType: .res 1 ; Used as parameter to subroutine +ParamXPos: .res 1 ; Used as parameter to subroutine +ParamYPos: .res 1 ; Used as parameter to subroutine +ParamTileNum: .res 1 ; Used as parameter to subroutine +ParamNumTiles: .res 1 ; Used as parameter to subroutine +ParamAttribs: .res 1 ; Used as parameter to subroutine -PrevOAMCount: .res 1 ; Store previous number of bytes sent to the OAM +PrevOAMCount: .res 1 ; Store the previous number of bytes that were sent to the OAM -; Store enough space for an array of actors ActorsArray: .res MAX_ACTORS * .sizeof(Actor) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; @@ -46,26 +49,24 @@ ActorsArray: .res MAX_ACTORS * .sizeof(Actor) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; .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 + 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) + 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 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; @@ -80,406 +81,437 @@ LoopButtons: rts ; Return from subroutine .endproc - -;DrawNewColumn ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; Routine to draw a new column of tiles off-screen as we scroll horizontally +;; Routine to draw a new column of tiles off-screen every 8 pixels ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; .proc DrawNewColumn - ; [ Destination ] - lda XScroll ;Set newColAddr low and hi byte + lda XScroll ; We'll set the NewColAddr lo-byte and hi-byte lsr lsr - lsr ; shift left three times to divide Xscroll by 3 - sta NewColAddr ; set the lo byte + lsr ; Shift right 3 times to divide XScroll by 8 + sta NewColAddr ; Set the lo-byte of the column address - lda CurrNametable ; hi byte comes from nametable - eor #1 ; invert low bit (0 or 1) + lda CurrNametable ; The hi-byte comes from the nametable + eor #1 ; Invert the low bit (0 or 1) asl - asl ; multiply by 4 (A is $00 or $04) + 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) - ;;;;;;;;;;; + adc #$20 ; Add $20 (A is $20 or $24) for nametabe 0 or 1 + sta NewColAddr+1 ; Set the hi-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 ; Multiply (col * 32) to compute the data offset + asl + asl + asl + asl + asl + sta SourceAddr ; Store lo-byte (--XX) 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 + lsr + lsr + lsr ; Divide current Column by 8 (using 3 shift rights) + sta SourceAddr+1 ; Store hi-byte (XX--) of column source addres - ; 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 + ; Here we'll add the offset the column source address with the address of where the BackgroundData + lda SourceAddr ; Lo-byte of the column data start + 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 + lda SourceAddr+1 ; Hi-byte of the column source address + 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 #%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 + lda PPU_STATUS ; Hit PPU_STATUS to reset hi/lo address latch + lda NewColAddr+1 + sta PPU_ADDR ; Set the hi-byte of the new column start address + lda NewColAddr + sta PPU_ADDR ; Set the lo-byte of the new column start address + ldx #30 ; We'll loop 30 times (=30 rows) + 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 to draw all 30 rows of this column rts .endproc -;DrawNewAttribs ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; Routine to draw a attributes off-screen eveery 32 pixels +;; Routine to draw attributes off-screen every 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 CurrNametable + eor #1 ; Invert low bit (0 or 1) + asl ; Multiuply by 2, ($00 or $02) + asl ; Multiply by 2 again ($00 or $04) + clc + adc #$23 ; Add high byte of attribute base address ($23-- or $27--) + sta NewColAddr+1 ; The hi-byte now has address = $23 or $27 for nametable 0 or 1 - lda XScroll - lsr - lsr - lsr - lsr - lsr - clc - adc #$C0 - sta NewColAddr ; Low Byte + lda XScroll + lsr + lsr + lsr + lsr + lsr ; Divide by 32 (shift right 5 times) + clc + adc #$C0 + sta NewColAddr ; The lo-byte contains (attribute base + XScroll/32) - ;; 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 ; (Column/4) * 8, since each row of attribute data in ROM is 8 bytes + and #%11111100 ; Mask the lowest two bits to get the closest lowest multiple of 4 + asl ; One shift left equivelant to a multiplication by 2 + sta SourceAddr ; Stores the lo-byte of the source attribute address offset (in ROM) - lda Column ; compute high - lsr ;/2 - lsr - lsr - lsr - lsr - lsr - lsr ; /128 - sta SourceAddr+1 ; store high byte + lda Column ; Proceed to compute the hi-byte of the source address offset in ROM + lsr ; /2 + lsr ; /4 + lsr ; /8 + lsr ; /16 + lsr ; /32 + lsr ; /64 + lsr ; /128, shift right 7 times to divide by 128 + sta SourceAddr+1 ; Stores the hi-byte of the Source address offset - lda SourceAddr - clc - adc #AttributeData ; hi byte of where attrib is in rom - sta SourceAddr+1 + lda SourceAddr+1 + adc #>AttributeData ; Add the hi-byte of the base address where AttributeData is in ROM + sta SourceAddr+1 ; Stores the result of the add back into the hi-byte of the SourceAddr - 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 + DrawAttribute: + bit PPU_STATUS ; Hit PPU_STATUS to reset the high/low address latch + ldy #0 ; Y = 0 + DrawAttribLoop: + lda NewColAddr+1 + sta PPU_ADDR ; Write the hi-byte of attribute PPU destination address lda NewColAddr - clc - adc #8 - sta NewColAddr ; next addr will be at NewColAddr +8 - jmp DrawAttribLoop - : - rts + sta PPU_ADDR ; Write the lo-byte of attribute PPU destination address + lda (SourceAddr),y ; Fetch attribute byte from ROM + sta PPU_DATA ; Stores new attribute data into the PPU memory + iny ; Y++ + cpy #8 + beq :+ ; Loop 8 times (to copy 8 attribute bytes) + lda NewColAddr + clc + adc #8 + sta NewColAddr ; Next attribute 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, ParamYVel +;; Params = ParamType, ParamXPos, ParamYPos ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; .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: + ldx #0 ; X = 0 + ArrayLoop: + cpx #MAX_ACTORS * .sizeof(Actor) ; Reached maximum number of actors allowed in the array? + beq EndRoutine ; Then we skip and don't add a new actor + lda ActorsArray+Actor::Type,x + cmp #ActorType::NULL ; If the actor type of this array position is NULL + beq AddNewActorToArray ; Then: we found an empty slot, proceed to add actor to position [x] + NextActor: + txa + clc + adc #.sizeof(Actor) ; Otherwise, we offset to the check the next actor in the array + tax ; X += sizeof(Actor) + jmp ArrayLoop + + AddNewActorToArray: ; Here we add a new actor at index [x] of the array + lda ParamType ; Fetch parameter "actor type" from RAM + sta ActorsArray+Actor::Type,x + lda ParamXPos ; Fetch parameter "actor position X" from RAM + sta ActorsArray+Actor::XPos,x + lda ParamYPos ; Fetch parameter "actor position Y" from RAM + sta ActorsArray+Actor::YPos,x +EndRoutine: + rts +.endproc + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Subroutine to spawn actors when certain conditions are met +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +.proc SpawnActors + SpawnSubmarine: + lda Clock60 ; Submarines are added in intervals of 3 seconds + sec + sbc PrevSubmarine + cmp #3 ; Only add a new submarine if the difference in time from the previous one is equal to 3 + bne :+ + lda #ActorType::SUBMARINE + sta ParamType ; Load parameter for the actor type + lda #223 + sta ParamXPos ; Load parameter for actor position X + lda #185 + sta ParamYPos + + jsr AddNewActor ; Call the subroutine to add the new missile actor + + lda Clock60 + sta PrevSubmarine ; Save the current Clock60 time as the submarine last spawn time + : + + SpawnAirplane: + lda Clock60 ; Submarines are added in intervals of 3 seconds + sec + sbc PrevAirplane + cmp #2 ; Only add a new airplane if the difference in time from the previous one is equal to 2 + bne :+ + lda #ActorType::AIRPLANE + sta ParamType ; Load parameter for the actor type + lda #235 + sta ParamXPos ; Load parameter for actor position X + lda #60 + sta ParamYPos + + jsr AddNewActor ; Call the subroutine to add the new missile actor + + lda Clock60 + sta PrevAirplane ; Save the current Clock60 time as the submarine last spawn time + : + rts +.endproc + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Subroutine to loop all actors and update them (position, velocity, etc.) +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +.proc UpdateActors + ldx #0 + ActorsLoop: + lda ActorsArray+Actor::Type,x + + cmp #ActorType::MISSILE + bne :+ + lda ActorsArray+Actor::YPos,x + sec + sbc #1 ; Decrement Y position of missiles by 1 + sta ActorsArray+Actor::YPos,x + bcs SkipMissile + lda #ActorType::NULL + sta ActorsArray+Actor::Type,x ; Remove the missile from the array + SkipMissile: + jmp NextActor + : + + cmp #ActorType::SUBMARINE + bne :+ + lda ActorsArray+Actor::XPos,x + sec + sbc #1 ; Decrement Y position of submarine by 1 + sta ActorsArray+Actor::XPos,x + bcs SkipSubmarine + lda #ActorType::NULL + sta ActorsArray+Actor::Type,x ; Remove the submarine from the array + SkipSubmarine: + jmp NextActor + : + + cmp #ActorType::AIRPLANE + bne :+ + lda ActorsArray+Actor::XPos,x + sec + sbc #1 ; Decrement Y position of submarine by 1 + sta ActorsArray+Actor::XPos,x + bcs SkipAirplane + lda #ActorType::NULL + sta ActorsArray+Actor::Type,x ; Remove the submarine from the array + SkipAirplane: + jmp NextActor + : + + 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 - EndRoutine: - rts -.endproc - -.proc SpawnActors - SpawnSubmarine: - lda Clock60 ; Submarines added in 3 second intervals - sec ; - sbc PrevSubmarine ; - cmp #3 ; Only add if 3 seconds have pased - bne :+ ; - lda #ActorType::SUBMARINE ; - sta ParamType ; Load Param for the actor type - lda #223 ; - sta ParamXPos ; Load X Pos - lda #185 ; - sta ParamYPos ; - ; - jsr AddNewActor ; Call subroutine - ; - lda Clock60 ; - sta PrevSubmarine ; Save the current clocktime as the submarine clock spawn time - : + cmp #MAX_ACTORS * .sizeof(Actor) + bne ActorsLoop rts .endproc - -.proc UpdateActors - ldx #0 ; counter of how many actors - ActorsLoop: - lda ActorsArray+Actor::Type,x - - cmp #ActorType::MISSILE - bne :+ - ;;Update y Pos - ;; y-- - lda ActorsArray+Actor::YPos,x - sec - sbc #1 ; Decrement Y Position - sta ActorsArray+Actor::YPos,x ; - bcs SkipMissile - ;; Delete Missile - lda #ActorType::NULL - sta ActorsArray+Actor::Type,x ; - SkipMissile: - jmp NextActor - : - - cmp #ActorType::SUBMARINE - bne :+ - ;;Update x Pos - ;; x-- - lda ActorsArray+Actor::XPos,x - sec - sbc #1 ; Decrement X Position - sta ActorsArray+Actor::XPos,x ; - bcs SkipSubmarine - ;; Delete SUB - lda #ActorType::NULL - sta ActorsArray+Actor::Type,x ; - SkipSubmarine: - jmp NextActor - : - - NextActor: - txa - clc - adc #.sizeof(Actor) - tax - cmp #MAX_ACTORS * .sizeof(Actor) - bne ActorsLoop - rts -.endproc - - - +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Subroutine to loop all actors and send their tiles to the OAM-RAM at $200 +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; .proc RenderActors - lda #$02 ; - sta SprPtr+1 ; - lda #$00 ; - sta SprPtr ; set SprPtr to $0200 + lda #$02 + sta SprPtr+1 + lda #$00 + sta SprPtr ; Point SprPtr to $0200 - ldy #0 ; counter of how many tiles - ldx #0 ; counter of how many actors + ldy #0 ; Count how many tiles we are sending + ldx #0 ; Counts how many actors we are looping ActorsLoop: - lda ActorsArray+Actor::Type,x + lda ActorsArray+Actor::Type,x + + cmp #ActorType::SPRITE0 + bne :+ + lda ActorsArray+Actor::XPos,x + sta ParamXPos + lda ActorsArray+Actor::YPos,x + sta ParamYPos + lda #$70 + sta ParamTileNum + lda #%00100000 + sta ParamAttribs + lda #1 + sta ParamNumTiles + jsr DrawSprite ; Call routine to draw 1 SPRITE0 tile to the OAM + jmp NextActor + : + cmp #ActorType::PLAYER + bne :+ + lda ActorsArray+Actor::XPos,x + sta ParamXPos + lda ActorsArray+Actor::YPos,x + sta ParamYPos + lda #$60 + sta ParamTileNum + lda #%00000000 + sta ParamAttribs + lda #4 + sta ParamNumTiles + jsr DrawSprite ; Call routine to draw 4 PLAYER tiles to the OAM + jmp NextActor + : - cmp #ActorType::SPRITE0 - bne :+ - ;; Load Params with Y, TileNumber, Attribs, X,NumTiles=4 - lda ActorsArray+Actor::XPos,x - sta ParamXPos - lda ActorsArray+Actor::YPos,x - sta ParamYPos - lda #$70 - sta ParamTileNum - lda #%00100000 - sta ParamAttribs - lda #1 - sta ParamNumTiles - jsr DrawSprite - jmp NextActor + cmp #ActorType::SUBMARINE + bne :+ + lda ActorsArray+Actor::XPos,x + sta ParamXPos + lda ActorsArray+Actor::YPos,x + sta ParamYPos + lda #$04 + sta ParamTileNum + lda #%00100000 + sta ParamAttribs + lda #4 + sta ParamNumTiles + jsr DrawSprite ; Call routine to draw 4 SUBMARINE tile to the OAM + jmp NextActor + : + + cmp #ActorType::AIRPLANE + bne :+ + lda ActorsArray+Actor::XPos,x + sta ParamXPos + lda ActorsArray+Actor::YPos,x + sta ParamYPos + lda #$10 + sta ParamTileNum + lda #%00000011 + sta ParamAttribs + lda #3 + sta ParamNumTiles + jsr DrawSprite ; Call routine to draw 4 SUBMARINE tile to the OAM + jmp NextActor + : + + cmp #ActorType::MISSILE + bne :+ + lda ActorsArray+Actor::XPos,x + sta ParamXPos + lda ActorsArray+Actor::YPos,x + sta ParamYPos + lda #$50 + sta ParamTileNum + lda #%00000001 + sta ParamAttribs + lda #1 + sta ParamNumTiles + jsr DrawSprite ; Call routine to draw 1 MISSILE tile to the OAM + jmp NextActor + : + + NextActor: + txa + clc + adc #.sizeof(Actor) + tax + cmp #MAX_ACTORS * .sizeof(Actor) + + beq :+ + jmp ActorsLoop ; Use absolute jump to avoid branch limit of [-128..127] + : + + tya + pha ; Save the Y register to the stack + + LoopTrailingTiles: + cpy PrevOAMCount + bcs :+ + lda #$FF + sta (SprPtr),y ; Set Y position to $FF (to hide tile) + iny + sta (SprPtr),y ; Set tile number as $FF + iny + sta (SprPtr),y ; Set attribs as $FF + iny + sta (SprPtr),y ; Set X position to $FF (to hide tile) + iny + jmp LoopTrailingTiles : - cmp #ActorType::PLAYER - bne :+ - ;; Load Params with Y, TileNumber, Attribs, X,NumTiles=4 - lda ActorsArray+Actor::XPos,x - sta ParamXPos - lda ActorsArray+Actor::YPos,x - sta ParamYPos - lda #$60 - sta ParamTileNum - lda #%00000000 - sta ParamAttribs - lda #4 - sta ParamNumTiles - jsr DrawSprite - jmp NextActor - : + pla ; Save the previous value of Y into PrevOAMCount + sta PrevOAMCount ; This is the total number of bytes that we just sent to the OAM - cmp #ActorType::MISSILE - bne :+ - ;; Load Params with Y, TileNumber, Attribs, X,NumTiles=1 - lda ActorsArray+Actor::XPos,x - sta ParamXPos - lda ActorsArray+Actor::YPos,x - sta ParamYPos - lda #$50 - sta ParamTileNum - lda #%00000001 - sta ParamAttribs - lda #1 - sta ParamNumTiles - jsr DrawSprite - jmp NextActor - : - - cmp #ActorType::SUBMARINE - bne :+ - ;; Load Params with Y, TileNumber, Attribs, X,NumTiles=1 - lda ActorsArray+Actor::XPos,x - sta ParamXPos - lda ActorsArray+Actor::YPos,x - sta ParamYPos - lda #$04 - sta ParamTileNum - lda #%00000000 - sta ParamAttribs - lda #4 - sta ParamNumTiles - jsr DrawSprite - jmp NextActor - : - - NextActor: - txa - clc - adc #.sizeof(Actor) - tax - cmp #MAX_ACTORS * .sizeof(Actor) - - beq :+ - jmp ActorsLoop - : - - tya - pha ; Save Y to the Stack - - LoopTrailingTiles: - ;; Loop all bytes until we reach PrevOAMCount - cpy PrevOAMCount - bcs :+ - lda #$FF - sta (SprPtr),y ; set Y position to $ff to hide - iny ; - sta (SprPtr),y ; Set tile number as $FF - iny ; - sta (SprPtr),y ; Set attribs as $FF - iny ; - sta (SprPtr),y ; Setr X Position to $FF to hide tile - iny ; - jmp LoopTrailingTiles - : - - pla - sta PrevOAMCount - rts + rts .endproc ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; Routine to loop "NumTiles" times, sending bytes to the OAM-RAM +;; Routine to loop "NumTiles" times, sending bytes to the OAM-RAM. ;; Params = ParamXPos, ParamYPos, ParamTileNum, ParamAttribs, ParamNumTiles ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; .proc DrawSprite - txa ;push x to stack - pha ; save value of X register before anything - + txa + pha ; Save the value of the X register before anything + ldx #0 TileLoop: - lda ParamYPos - sta (SprPtr),y ; Send Y Position to Ram - iny + lda ParamYPos ; Send Y position to the OAM + sta (SprPtr),y + iny - lda ParamTileNum ; Send Tile# to the OAM - sta (SprPtr),y ; - inc ParamTileNum ; ParamTileNum++ - iny + lda ParamTileNum ; Send the Tile # to the OAM + sta (SprPtr),y + inc ParamTileNum ; ParamTileNum++ + iny - lda ParamAttribs ; Send Attribs to the OAM - sta (SprPtr),y - iny + lda ParamAttribs ; Send the attributes to the OAM + sta (SprPtr),y + iny - lda ParamXPos ; Send X Position to the OAM - sta (SprPtr),y - clc - adc #8 - sta ParamXPos ; increment X Pos 8 pixels + lda ParamXPos ; Send X position to the OAM + sta (SprPtr),y + clc + adc #8 + sta ParamXPos ; ParamXPos += 8 - iny + iny - inx ; X++ - cpx ParamNumTiles ; loop NumTiles times - bne TileLoop + inx ; X++ + cpx ParamNumTiles ; Loop until X == NumTiles + bne TileLoop - ; pop x from stack pla - tax ; pull value of X from stack and transfer to x + tax ; Restore the previous value of X register rts .endproc - ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Reset handler (called when the NES resets or powers on) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; @@ -491,15 +523,15 @@ InitVariables: sta Frame ; Frame = 0 sta Clock60 ; Clock60 = 0 sta XScroll ; XScroll = 0 - sta CurrNametable ; CurrNametable = 0 - sta Column ; Column = 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 + jsr LoadPalette ; Call LoadPalette subroutine to load 32 colors into our palette AddSprite0: lda #ActorType::SPRITE0 @@ -508,7 +540,7 @@ AddSprite0: sta ParamXPos lda #27 sta ParamYPos - jsr AddNewActor + jsr AddNewActor ; Add new actor to array AddPlayer: lda #ActorType::PLAYER @@ -517,168 +549,164 @@ AddPlayer: sta ParamXPos lda YPos sta ParamYPos - jsr AddNewActor + jsr AddNewActor ; Add new actor to array InitBackgroundTiles: lda #1 - sta CurrNametable ;current nametable= 1 + sta CurrNametable ; CurrNametable = 1 lda #0 - sta XScroll - sta Column + sta XScroll ; XScroll = 0 + sta Column ; Column = 0 InitBackgroundLoop: - jsr DrawNewColumn ; draw all rows of new column + jsr DrawNewColumn ; Draw all rows of new column (from top to bottom) lda XScroll clc adc #8 - sta XScroll ; xscroll += 8 - - inc Column ;column++ - + 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 + bne InitBackgroundLoop ; Repeat all 32 columns of the first nametable lda #0 - sta CurrNametable ;current nametable = 0 + sta CurrNametable ; CurrNametable = 0 lda #1 - sta XScroll ;Scroll = 1 + sta XScroll ; Scroll = 1 - jsr DrawNewColumn ; draw first column of 2nd nametable - inc Column ; Column ++ + jsr DrawNewColumn ; Draw first column of the second nametable + inc Column ; Column++ lda #%00000000 - sta PPU_CTRL ; PPU back to +1 mode + sta PPU_CTRL ; Set PPU increment to +1 mode InitAttribs: lda #1 - sta CurrNametable ;current nametable= 1 + sta CurrNametable lda #0 sta XScroll sta Column InitAttribsLoop: - jsr DrawNewAttribs ; draw all rows of new column + jsr DrawNewAttribs ; Draw attributes in the correct place of the first nametable lda XScroll clc adc #32 - sta XScroll ; xscroll += 32 + sta XScroll ; XScroll += 32 - lda Column + lda Column ; Repeat for all elements of the first nametable clc adc #4 - sta Column + sta Column ; Column += 4 cmp #32 - bne InitAttribsLoop ; loop 32 times to repeat all 32 columns of the first nametable + bne InitAttribsLoop ; Loop until we reach Column 32 lda #0 - sta CurrNametable ;current nametable = 0 + sta CurrNametable lda #1 - sta XScroll ;Scroll = 1 - jsr DrawNewAttribs ; draw first column of 2nd nametable + sta XScroll + jsr DrawNewAttribs ; Draw first attributes of second nametable - inc Column + inc Column ; Column = 33 EnableRendering: - lda #%10010000 ; Enable NMI and set background to use the 2nd pattern table (at $1000) + 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 + 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 + sta PPU_MASK ; Set PPU_MASK bits to render the background -;;;;;;; START GAME LOOP GameLoop: lda Buttons - sta PrevButtons + sta PrevButtons ; Stores the previously pressed buttons - ;Perform Game Logic Here - jsr ReadControllers - -CheckAButton: + jsr ReadControllers ; Read joypad and load button state + + CheckAButton: lda Buttons and #BUTTON_A beq :+ - lda Buttons - and #BUTTON_A ; DEBOUNCE A PRESS - cmp PrevButtons ; Compare current buttons and check if A was previously pressed - beq:+ - lda #ActorType::MISSILE - sta ParamType - lda XPos - sta ParamXPos - lda YPos - jsr AddNewActor + lda Buttons + and #BUTTON_A + cmp PrevButtons ; Compare the current buttons and check if button A was previously pressed + beq :+ ; If it was, we bypass the creation of a new missile + lda #ActorType::MISSILE + sta ParamType + lda XPos + sta ParamXPos + lda YPos + sta ParamYPos + jsr AddNewActor ; Call the subroutine to add a new missile actor : 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 + WaitForVBlank: ; We lock the execution of the game logic here + lda IsDrawComplete ; Here we check and only perform a game loop call once NMI is done drawing + beq WaitForVBlank ; Otherwise, we keep looping - lda #0 ; - sta IsDrawComplete ; set back to 0 + lda #0 + sta IsDrawComplete ; Once we're done, we set the DrawComplete flag back to 0 - jmp GameLoop; Force an infinite execution loop -;;;;;;; END GAME LOOP + jmp GameLoop ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; NMI interrupt handler ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; NMI: - PUSH_REGS ; push registers to the stack + PUSH_REGS ; Macro to save register values by pushing them to the stack - inc Frame ; Frame++ + 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 +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! - + and #%00000111 ; Check if the scroll a multiple of 8 + bne :+ ; 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: + adc #1 ; Column++ + and #%01111111 ; Drop the left-most bit to wrap around 128 + sta Column ; Clamping the value to never go beyond 128 + : NewAttribsCheck: - lda XScroll - and #%00011111 - bne :+ - jsr DrawNewAttribs - : + lda XScroll + and #%00011111 ; Check if the scroll is a multiple of 32 (lowest 5 bits are 00000) + bne :+ ; If it isn't, we still don't need to draw new attributes + jsr DrawNewAttribs ; It it is a multiple of 32, we draw the new attributes! + : SetPPUNoScroll: - lda #0 - sta PPU_SCROLL - sta PPU_SCROLL + lda #0 + sta PPU_SCROLL + sta PPU_SCROLL ; Set *no* scroll for the status bar EnablePPUSprite0: - lda #%10010000 - sta PPU_CTRL - lda #%00011110 - sta PPU_MASK + lda #%10010000 ; Enable PPU sprites for sprite 0 + sta PPU_CTRL + lda #%00011110 ; Enable sprites and enable background + sta PPU_MASK WaitForNoSprite0: - lda PPU_STATUS - and #%01000000 - bne WaitForNoSprite0 + lda PPU_STATUS + and #%01000000 ; PPU address $2002 bit 6 is the sprite 0 hit flag + bne WaitForNoSprite0 ; Loop until we do *not* have a sprite 0 hit 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 + lda PPU_STATUS + and #%01000000 ; PPU address $2002 bit 6 is the sprite 0 hit flag + beq WaitForSprite0 ; Loop until we do have a sprite 0 hit ScrollBackground: inc XScroll ; XScroll++ @@ -711,11 +739,10 @@ SetGameClock: SetDrawComplete: lda #1 - sta IsDrawComplete - inc Frame - + sta IsDrawComplete ; Set the DrawComplete flag to indicate we are done drawing to the PPU PULL_REGS + rti ; Return from interrupt ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; @@ -751,10 +778,10 @@ BackgroundData: .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,$6e,$13,$20,$21,$21,$21,$21,$21,$21,$21,$21,$21,$15,$21,$15,$21,$21,$25,$35,$15,$15,$12,$00,$00,$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,$48,$21,$21,$15,$27,$37,$15,$15,$12,$00,$00,$00,$00,$5d,$56,$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 @@ -784,7 +811,7 @@ BackgroundData: .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,$6e,$13,$20,$21,$21,$21,$21,$21,$21,$21,$21,$21,$15,$21,$15,$21,$1f,$2a,$3a,$3c,$15,$12,$00,$00,$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 @@ -817,7 +844,7 @@ BackgroundData: .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,$6e,$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,$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 @@ -850,7 +877,7 @@ BackgroundData: .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,$6e,$13,$20,$21,$21,$21,$21,$15,$48,$21,$21,$21,$21,$21,$21,$21,$21,$14,$11,$4e,$15,$12,$00,$00,$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 @@ -868,55 +895,41 @@ BackgroundData: .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,$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,$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,$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 ; +.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 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Here we add the CHR-ROM data, included from an external .CHR file diff --git a/atlantico/atlantico.nes b/atlantico/atlantico.nes index c003e50..18fe21f 100644 Binary files a/atlantico/atlantico.nes and b/atlantico/atlantico.nes differ diff --git a/atlantico/atlantico.o b/atlantico/atlantico.o index 1b16774..3a82003 100644 Binary files a/atlantico/atlantico.o and b/atlantico/atlantico.o differ