From 48f2e17491ce2270da2ff69a1dd6c1fd3b3cddb5 Mon Sep 17 00:00:00 2001 From: blondie7575 Date: Sun, 5 Jan 2020 15:11:14 -0800 Subject: [PATCH] Dirt clod creation and explosion working --- GSCats.xcodeproj/project.pbxproj | 5 + dirt.s | 298 +++++++++++++++++++++++++++++++ equates.s | 5 +- gamemanager.s | 9 +- gameobject.s | 2 +- gscats.2mg | Bin 819264 -> 819264 bytes gscats.s | 3 +- projectile.s | 3 + random.s | 52 ++++++ 9 files changed, 373 insertions(+), 4 deletions(-) create mode 100644 dirt.s create mode 100644 random.s diff --git a/GSCats.xcodeproj/project.pbxproj b/GSCats.xcodeproj/project.pbxproj index a3bfa78..50dcf15 100644 --- a/GSCats.xcodeproj/project.pbxproj +++ b/GSCats.xcodeproj/project.pbxproj @@ -35,6 +35,8 @@ 70E9D8611F2BD95400555C19 /* gscats.s */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.asm; path = gscats.s; sourceTree = ""; }; 70E9D8621F2BD95400555C19 /* macros.s */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.asm; path = macros.s; sourceTree = ""; }; 70E9D8631F2BD95400555C19 /* Makefile */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.make; path = Makefile; sourceTree = ""; }; + 70F011D023B91B2900C8873F /* dirt.s */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.asm; path = dirt.s; sourceTree = ""; }; + 70F011D123B989B800C8873F /* random.s */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.asm; path = random.s; sourceTree = ""; }; 70F0869F1F413A89002446C3 /* player.s */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.asm; path = player.s; sourceTree = ""; }; 70F086A01F4230CB002446C3 /* utility.s */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.asm; path = utility.s; sourceTree = ""; }; 70FE79D21F8814A600E0095C /* MerlinToCA65.sh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = MerlinToCA65.sh; sourceTree = ""; }; @@ -49,11 +51,13 @@ 70E9D8601F2BD95400555C19 /* graphics.s */, 70E9D8621F2BD95400555C19 /* macros.s */, 7099E3841F41022100182A82 /* gameobject.s */, + 70F011D123B989B800C8873F /* random.s */, 706DF1641F2D39F700AA6680 /* loader.s */, 700FFAFB1F40F3BF00A442DE /* font.s */, 7002647320CD78C40015B184 /* smallNumbers.s */, 706DF1651F2D4A8100AA6680 /* terrain.s */, 705AAFA920040B0D001BB0ED /* terrain_e1.s */, + 70F011D023B91B2900C8873F /* dirt.s */, 70C073091F5BAA3E009844A9 /* collision.s */, 70F086A01F4230CB002446C3 /* utility.s */, 700C39C51F2E5CA800C24F9C /* tables.s */, @@ -114,6 +118,7 @@ developmentRegion = English; hasScannedForEncodings = 0; knownRegions = ( + English, en, ); mainGroup = 70E9D8541F2BD8EF00555C19; diff --git a/dirt.s b/dirt.s new file mode 100644 index 0000000..46a1897 --- /dev/null +++ b/dirt.s @@ -0,0 +1,298 @@ +; +; dirt +; +; Created by Quinn Dunki on 12/29/19 +; + +MAXPARTICLES = 64 + +.macro PARTICLEPTR_XY + txa ; Pointer to particle structure from index + asl + asl + asl + asl + tay +.endmacro + + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; createDirtExplosion +; +; Simulate a bunch of dirt flying everywhere +; +; PARAML0 = X pos of circle left edge +; PARAML1 = Y pos of circle center +; PARAML2 = Radius (16 bits) +; +; Trashes SCRATCHL,SCRATCHL2,CACHEDATA +; +createDirtExplosion: + SAVE_AXY + + lda #1 + sta dirtExplosionActive + + lda #120 + sta PARAML0 + lda #100 + sta PARAML1 + lda #3 + sta PARAML2 + asl + sta CACHEDATA ; Cache diameter + + ldx #0 + ldy #0 +createDirtExplosionLoop: + jsr createDirtExplosionColumn + inc PARAML0 + inc PARAML0 + iny + cpy CACHEDATA + bne createDirtExplosionLoop + + RESTORE_AXY + rts + + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; createDirtExplosionColumn +; +; Create one column of a starting dirt explosion circle +; X = Particle index to start filling from +; Y = Local X index of column +; PARAML0 = X pos of column +; PARAML1 = Y pos of circle center +; PARAML2 = Radius (16 bits) +; +; X=> Last particle index we filled in +1 +; Trashse SCRATCHL,SCRATCHL2 +; +createDirtExplosionColumn: + SAVE_AY + lda PARAML2 + pha + + stx SCRATCHL2 ; Cache particle index + + phy ; Look up circle table for our radius + lda PARAML2 + asl + tay + lda circleTable,y + sta SCRATCHL + + ; Find starting Y from circle table + pla + asl + tay + lda (SCRATCHL),y + tax ; Row counter + pha + eor #$ffff + inc + sta PARAML2 ; Row counter end + + pla + clc + adc PARAML1 + sta SCRATCHL ; Current Y position + +createDirtExplosionColumnLoop: + phx ; Find pointer to next particle to fill out + ldx SCRATCHL2 + PARTICLEPTR_XY + plx + + ; X position - Always the same + lda PARAML0 + sta dirtParticles+DP_POSX,y + asl ; Convert to 12.4 + asl + asl + asl + sta dirtParticles+DP_PRECISEX,y + + ; Y position - Iterates from computed cache + lda SCRATCHL + sta dirtParticles+DP_POSY,y + asl ; Convert to 12.4 + asl + asl + asl + sta dirtParticles+DP_PRECISEY,y + + ; X velocity. Need half to be negative. I feel like there + ; should be a clever branchless way to do this, but I couldn't + ; come up with it. + jsr random + lda RANDOM + bmi createDirtExplosionColumnLoopNegX + and #$00ff + bra createDirtExplosionColumnLoopNowY + +createDirtExplosionColumnLoopNegX: + ora #$ff00 + +createDirtExplosionColumnLoopNowY: + sta dirtParticles+DP_VX,y + + ; Y velocity + jsr random + lda RANDOM + and #$00ff + ora #$0100 + sta dirtParticles+DP_VY,y + + ; Advance to next particle + inc SCRATCHL2 + inc SCRATCHL + inx + cpx PARAML2 + bmi createDirtExplosionColumnLoop + + ; Gather return values + ldx SCRATCHL2 + + pla + sta PARAML2 + RESTORE_AY + rts + + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; renderDirtExplosion +; +; Update and render the current dirt explosion +; +renderDirtExplosion: + SAVE_AXY + lda dirtExplosionActive + beq renderDirtExplosionDone + + ldx #0 +renderDirtExplosionLoop: + PARTICLEPTR_XY + jsr updateDirtParticle + inx ; Advance array pointer to next particle + cpx #MAXPARTICLES + bne renderDirtExplosionLoop + +renderDirtExplosionDone: + RESTORE_AXY + rts + + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; updateDirtParticle +; +; Y = Offset to particle in array +; Update and render the current dirt explosion +; +; Trashes SCRATCHL,PARAML0 + +updateDirtParticle: + SAVE_AXY + + lda dirtParticles+DP_POSX,y + bmi updateDirtParticleDone ; Particle is dead + + ; Erase old position + lda #dirtParticles ; Calculate pointer to struct + sta PARAML0 + clc + tya + adc PARAML0 + sta PARAML0 + jsr vramPtr + lda #00 + sta SHADOWVRAMBANK,x + + ; Integrate gravity over velocity + lda dirtParticles+DP_VY,y + clc + adc #GRAVITY + sta dirtParticles+DP_VY,y + + ; Integrate X velocity over position + lda dirtParticles+DP_VX,y + ; Convert 8.8 to 12.4 + cmp #$8000 + ror + cmp #$8000 + ror + cmp #$8000 + ror + cmp #$8000 + ror + clc + adc dirtParticles+DP_PRECISEX,y + sta dirtParticles+DP_PRECISEX,y + + ; Convert to integer for rendering + lsr + lsr + lsr + lsr + sta dirtParticles+DP_POSX,y + + ; Integrate Y velocity over position + lda dirtParticles+DP_VY,y + ; Convert 8.8 to 12.4 + cmp #$8000 + ror + cmp #$8000 + ror + cmp #$8000 + ror + cmp #$8000 + ror + clc + adc dirtParticles+DP_PRECISEY,y + sta dirtParticles+DP_PRECISEY,y + + ; Convert to integer for rendering + lsr + lsr + lsr + lsr + sta dirtParticles+DP_POSY,y + + ; Draw new position + jsr vramPtr ; PARAML0 still holds struct pointer + cpx #$ffff + beq updateDirtParticleKill + lda #$11 + sta SHADOWVRAMBANK,x + +updateDirtParticleDone: + RESTORE_AXY + rts + +updateDirtParticleKill: + lda #-1 + sta dirtParticles+DP_POSX,y + bra updateDirtParticleDone + +dirtExplosionActive: + .word 0 + +dirtParticles: +.repeat MAXPARTICLES + .word -1 ; Pos X in pixels + .word 100 ; Pos Y in pixels + .word $a00 ; Pos X (12.4 fixed point) + .word $640 ; Pos Y (12.4 fixed point) + .word $ff00 ; Velocity X (8.8 fixed point) + .word $100 ; Velocity Y (8.8 fixed point) + .word 0,0 ; Pad to 16 bytes +.endrepeat + + +DP_POSX = 0 ; Byte offsets into dirtParticles data structure +DP_POSY = 2 +DP_PRECISEX = 4 +DP_PRECISEY = 6 +DP_VX = 8 +DP_VY = 10 diff --git a/equates.s b/equates.s index d4d907c..557cad0 100644 --- a/equates.s +++ b/equates.s @@ -21,6 +21,7 @@ PARAM2 = $08 PARAM3 = $09 PARAML0 = $06 ; 16-bit versions of params PARAML1 = $08 +PARAML2 = $d0 SCRATCH0 = $19 SCRATCH1 = $1a SCRATCHL = $19 ; 16-bit version of scratch @@ -33,7 +34,9 @@ STACKPTR = $70 ; Cache for stack pointer in fast graphics SHADOWREGISTER = $72 ; Cache for shadow register in fast graphics STACKREGISTER = $73 ; Cache for stack register in fast graphics lastCompiledTerrainY = $75 ; The highest Y value that the compiled renderer must handle - +RANDOM = $ce ; 16 bit random number +RANDOML = $ce ; Low byte of random number generator +RANDOMH = $cf ; High byte of random number generator ; Terrain constants diff --git a/gamemanager.s b/gamemanager.s index 30f9cc8..ead409e 100644 --- a/gamemanager.s +++ b/gamemanager.s @@ -9,6 +9,9 @@ NUMPLAYERS = 2 beginGameplay: + ; Initialize random numbers + lda #1 + jsr seedRandom ; Set up palette for terrain and players lda #basePalette @@ -132,7 +135,7 @@ gameplayLoopRender: ; Render the terrain if needed lda terrainDirty - beq gameplayLoopProjectiles + beq gameplayLoopExplosions ; jsl renderTerrainSpans ; Part of the now disabled fill-mode renderer jsr renderTerrain stz terrainDirty @@ -140,6 +143,10 @@ gameplayLoopRender: ; Render players jsr renderPlayers +gameplayLoopExplosions: + ; Render explosions + jsr renderDirtExplosion + gameplayLoopProjectiles: ; BORDER_COLOR #$3 diff --git a/gameobject.s b/gameobject.s index 253923e..4e205b2 100644 --- a/gameobject.s +++ b/gameobject.s @@ -58,7 +58,7 @@ placeGameObjectOnTerrain: ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; vramPtr ; -; PARAML0 = Pointer to X,Y (16 bits each) +; PARAML0 = Pointer to X,Y (16 bits each, Y is bottom relative) ; X => Offset to upper left corner of VRAM, or ffff if offscreen ; ; Trashes SCRATCHL diff --git a/gscats.2mg b/gscats.2mg index 1967dc92be2bd49d0302c82a994732fb737c5dd6..9b21d7b77b8807e8258d197ae917bef0bcbcdae9 100644 GIT binary patch delta 5383 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 delta 4953 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 Random 8 bits +; Y => Less random 8 bits +; +; Taken from https://codebase64.org/doku.php?id=base:16bit_xorshift_random_generator +; This routine is not very fast, but it'll do for now. It's intended +; for 6502 so we're making due with it. +; +rng_zp_low = RANDOML +rng_zp_high = RANDOMH + +random: + SAVE_AXY + EMULATION + LDA rng_zp_high + LSR + LDA rng_zp_low + ROR + EOR rng_zp_high + STA rng_zp_high ; high part of x ^= x << 7 done + ROR ; A has now x >> 9 and high bit comes from low byte + EOR rng_zp_low + STA rng_zp_low ; x ^= x >> 9 and the low part of x ^= x << 7 done + EOR rng_zp_high + STA rng_zp_high ; x ^= x << 8 done + NATIVE + RESTORE_AXY + RTS + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; seedRandom +; A = Seed +; +; Taken from https://codebase64.org/doku.php?id=base:16bit_xorshift_random_generator +; +seedRandom: + SAVE_AXY + EMULATION + STA rng_zp_low + LDA #0 + STA rng_zp_high + NATIVE + RESTORE_AXY + rts