From 9aadc36361057a9a1114ba01a11b536e59a7d3d1 Mon Sep 17 00:00:00 2001
From: blondie7575 <qd@quinndunki.com>
Date: Fri, 29 Sep 2017 17:53:05 -0700
Subject: [PATCH] Basic Mr. Sprite integration

- Larger gameobject sprites
- Fixed some bugs in collision detection
---
 equates.s     |   2 +
 gamemanager.s |   4 +-
 gameobject.s  | 512 ++++++++++++++++++++++++++++++++++++++++++++------
 graphics.s    | 219 ++++++++++++++++++++-
 gscats.2mg    | Bin 819264 -> 819264 bytes
 macros.s      |  53 +++---
 player.s      |  34 +++-
 projectile.s  |  38 ++--
 8 files changed, 754 insertions(+), 108 deletions(-)

diff --git a/equates.s b/equates.s
index c4f96a5..9093928 100644
--- a/equates.s
+++ b/equates.s
@@ -8,6 +8,7 @@ KBD				= $e0c000
 KBDSTROBE		= $e0c010
 COUT			= $fded
 VRAM			= $e12000
+VRAMBANK		= $e10000
 
 ; Zero page locations we use (unused by Monitor, Applesoft, or ProDOS)
 PARAM0			= $06
@@ -21,3 +22,4 @@ SCRATCH1		= $1a
 SCRATCHL		= $19		; 16-bit version of scratch
 SCRATCHL2		= $67		; Second 16-bit scratch
 PARAM24			= $67		; 24-bit param (This is almost certainly messing up AppleSoft, but meh)
+STACKPTR		= $70		; Cache for stack pointer in fast graphics
diff --git a/gamemanager.s b/gamemanager.s
index 9a73128..8cc75ed 100644
--- a/gamemanager.s
+++ b/gamemanager.s
@@ -26,11 +26,11 @@ beginGameplay:
 	jsr clipTerrain
 
 	; Create players
-	lda #191
+	lda #40
 	ldy #0
 	jsr playerCreate
 
-	lda #40
+	lda #196
 	ldy #1
 	jsr playerCreate
 
diff --git a/gameobject.s b/gameobject.s
index 8752828..e5514ba 100644
--- a/gameobject.s
+++ b/gameobject.s
@@ -5,14 +5,17 @@
 ;  Created by Quinn Dunki on 8/13/17
 ;
 
-GAMEOBJECTWIDTH = 8
-GAMEOBJECTHEIGHT = 8
+GAMEOBJECTWIDTH = 16
+GAMEOBJECTHEIGHT = 16
 
 ; Base class sample:
 ;gameobjectData:
 ;	.word 40	; X pos in pixels (from right terrain edge)
 ;	.word 38	; Y pos in pixels (from bottom terrain edge)
-;	.word 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0	; Saved background
+;	.word 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0	; Saved background 64 bytes
+;	.word 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
+;	.word 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
+;	.word 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
 
 GO_POSX = 0		; Byte offsets into gameobject data structure
 GO_POSY = 2
@@ -65,6 +68,7 @@ placeGameObjectOnTerrain:
 
 	; X
 	lda ptr+GO_POSX,y
+
 	lsr
 	cmp leftScreenEdge
 	bmi renderGameobjectSkip	; Gameobject is off left edge of screen
@@ -79,6 +83,7 @@ placeGameObjectOnTerrain:
 	sec
 	lda #200
 	sbc ptr+GO_POSY,y
+
 	bmi renderGameobjectSkip	; Gameobject is off top edge of screen
 	cmp #200 - GAMEOBJECTHEIGHT
 	bpl renderGameobjectSkip	; Gameobject is off bottom edge of screen
@@ -88,7 +93,9 @@ placeGameObjectOnTerrain:
 	lda vramYOffset,x
 	clc
 	adc SCRATCHL
-	tax		; X now contains the VRAM offset of the upper left corner
+	adc #$2000
+	tax		; X now contains the bank address of the upper left corner
+
 	phx
 	bra renderGameobjectBackground
 
@@ -97,88 +104,279 @@ renderGameobjectSkip:
 
 renderGameobjectBackground:
 	; Save background
-	lda VRAM,x
+	lda VRAMBANK,x
 	sta ptr+GO_BACKGROUND,y
 	iny
 	iny
-	lda VRAM+2,x
+	lda VRAMBANK+2,x
 	sta ptr+GO_BACKGROUND,y
 	iny
 	iny
-	lda VRAM+160,x
+	lda VRAMBANK+4,x
 	sta ptr+GO_BACKGROUND,y
 	iny
 	iny
-	lda VRAM+160+2,x
+	lda VRAMBANK+6,x
 	sta ptr+GO_BACKGROUND,y
 	iny
 	iny
-	lda VRAM+160*2,x
+
+	lda VRAMBANK+160,x
 	sta ptr+GO_BACKGROUND,y
 	iny
 	iny
-	lda VRAM+160*2+2,x
+	lda VRAMBANK+160+2,x
 	sta ptr+GO_BACKGROUND,y
 	iny
 	iny
-	lda VRAM+160*3,x
+	lda VRAMBANK+160+4,x
 	sta ptr+GO_BACKGROUND,y
 	iny
 	iny
-	lda VRAM+160*3+2,x
+	lda VRAMBANK+160+6,x
 	sta ptr+GO_BACKGROUND,y
 	iny
 	iny
-	lda VRAM+160*4,x
+
+	lda VRAMBANK+160*2,x
 	sta ptr+GO_BACKGROUND,y
 	iny
 	iny
-	lda VRAM+160*4+2,x
+	lda VRAMBANK+160*2+2,x
 	sta ptr+GO_BACKGROUND,y
 	iny
 	iny
-	lda VRAM+160*5,x
+	lda VRAMBANK+160*2+4,x
 	sta ptr+GO_BACKGROUND,y
 	iny
 	iny
-	lda VRAM+160*5+2,x
+	lda VRAMBANK+160*2+6,x
 	sta ptr+GO_BACKGROUND,y
 	iny
 	iny
-	lda VRAM+160*6,x
+
+	lda VRAMBANK+160*3,x
 	sta ptr+GO_BACKGROUND,y
 	iny
 	iny
-	lda VRAM+160*6+2,x
+	lda VRAMBANK+160*3+2,x
 	sta ptr+GO_BACKGROUND,y
 	iny
 	iny
-	lda VRAM+160*7,x
+	lda VRAMBANK+160*3+4,x
 	sta ptr+GO_BACKGROUND,y
 	iny
 	iny
-	lda VRAM+160*7+2,x
+	lda VRAMBANK+160*3+6,x
 	sta ptr+GO_BACKGROUND,y
-	plx
+	iny
+	iny
+
+	lda VRAMBANK+160*4,x
+	sta ptr+GO_BACKGROUND,y
+	iny
+	iny
+	lda VRAMBANK+160*4+2,x
+	sta ptr+GO_BACKGROUND,y
+	iny
+	iny
+	lda VRAMBANK+160*4+4,x
+	sta ptr+GO_BACKGROUND,y
+	iny
+	iny
+	lda VRAMBANK+160*4+6,x
+	sta ptr+GO_BACKGROUND,y
+	iny
+	iny
+
+	lda VRAMBANK+160*5,x
+	sta ptr+GO_BACKGROUND,y
+	iny
+	iny
+	lda VRAMBANK+160*5+2,x
+	sta ptr+GO_BACKGROUND,y
+	iny
+	iny
+	lda VRAMBANK+160*5+4,x
+	sta ptr+GO_BACKGROUND,y
+	iny
+	iny
+	lda VRAMBANK+160*5+6,x
+	sta ptr+GO_BACKGROUND,y
+	iny
+	iny
+
+	lda VRAMBANK+160*6,x
+	sta ptr+GO_BACKGROUND,y
+	iny
+	iny
+	lda VRAMBANK+160*6+2,x
+	sta ptr+GO_BACKGROUND,y
+	iny
+	iny
+	lda VRAMBANK+160*6+4,x
+	sta ptr+GO_BACKGROUND,y
+	iny
+	iny
+	lda VRAMBANK+160*6+6,x
+	sta ptr+GO_BACKGROUND,y
+	iny
+	iny
+
+	lda VRAMBANK+160*7,x
+	sta ptr+GO_BACKGROUND,y
+	iny
+	iny
+	lda VRAMBANK+160*7+2,x
+	sta ptr+GO_BACKGROUND,y
+	iny
+	iny
+	lda VRAMBANK+160*7+4,x
+	sta ptr+GO_BACKGROUND,y
+	iny
+	iny
+	lda VRAMBANK+160*7+6,x
+	sta ptr+GO_BACKGROUND,y
+	iny
+	iny
+
+	lda VRAMBANK+160*8,x
+	sta ptr+GO_BACKGROUND,y
+	iny
+	iny
+	lda VRAMBANK+160*8+2,x
+	sta ptr+GO_BACKGROUND,y
+	iny
+	iny
+	lda VRAMBANK+160*8+4,x
+	sta ptr+GO_BACKGROUND,y
+	iny
+	iny
+	lda VRAMBANK+160*8+6,x
+	sta ptr+GO_BACKGROUND,y
+	iny
+	iny
+
+	lda VRAMBANK+160*9,x
+	sta ptr+GO_BACKGROUND,y
+	iny
+	iny
+	lda VRAMBANK+160*9+2,x
+	sta ptr+GO_BACKGROUND,y
+	iny
+	iny
+	lda VRAMBANK+160*9+4,x
+	sta ptr+GO_BACKGROUND,y
+	iny
+	iny
+	lda VRAMBANK+160*9+6,x
+	sta ptr+GO_BACKGROUND,y
+	iny
+	iny
+
+	lda VRAMBANK+160*10,x
+	sta ptr+GO_BACKGROUND,y
+	iny
+	iny
+	lda VRAMBANK+160*10+2,x
+	sta ptr+GO_BACKGROUND,y
+	iny
+	iny
+	lda VRAMBANK+160*10+4,x
+	sta ptr+GO_BACKGROUND,y
+	iny
+	iny
+	lda VRAMBANK+160*10+6,x
+	sta ptr+GO_BACKGROUND,y
+	iny
+	iny
+
+	lda VRAMBANK+160*11,x
+	sta ptr+GO_BACKGROUND,y
+	iny
+	iny
+	lda VRAMBANK+160*11+2,x
+	sta ptr+GO_BACKGROUND,y
+	iny
+	iny
+	lda VRAMBANK+160*11+4,x
+	sta ptr+GO_BACKGROUND,y
+	iny
+	iny
+	lda VRAMBANK+160*11+6,x
+	sta ptr+GO_BACKGROUND,y
+	iny
+	iny
+
+	lda VRAMBANK+160*12,x
+	sta ptr+GO_BACKGROUND,y
+	iny
+	iny
+	lda VRAMBANK+160*12+2,x
+	sta ptr+GO_BACKGROUND,y
+	iny
+	iny
+	lda VRAMBANK+160*12+4,x
+	sta ptr+GO_BACKGROUND,y
+	iny
+	iny
+	lda VRAMBANK+160*12+6,x
+	sta ptr+GO_BACKGROUND,y
+	iny
+	iny
+
+	lda VRAMBANK+160*13,x
+	sta ptr+GO_BACKGROUND,y
+	iny
+	iny
+	lda VRAMBANK+160*13+2,x
+	sta ptr+GO_BACKGROUND,y
+	iny
+	iny
+	lda VRAMBANK+160*13+4,x
+	sta ptr+GO_BACKGROUND,y
+	iny
+	iny
+	lda VRAMBANK+160*13+6,x
+	sta ptr+GO_BACKGROUND,y
+	iny
+	iny
+
+	lda VRAMBANK+160*14,x
+	sta ptr+GO_BACKGROUND,y
+	iny
+	iny
+	lda VRAMBANK+160*14+2,x
+	sta ptr+GO_BACKGROUND,y
+	iny
+	iny
+	lda VRAMBANK+160*14+4,x
+	sta ptr+GO_BACKGROUND,y
+	iny
+	iny
+	lda VRAMBANK+160*14+6,x
+	sta ptr+GO_BACKGROUND,y
+
+	lda VRAMBANK+160*15,x
+	sta ptr+GO_BACKGROUND,y
+	iny
+	iny
+	lda VRAMBANK+160*15+2,x
+	sta ptr+GO_BACKGROUND,y
+	iny
+	iny
+	lda VRAMBANK+160*15+4,x
+	sta ptr+GO_BACKGROUND,y
+	iny
+	iny
+	lda VRAMBANK+160*15+6,x
+	sta ptr+GO_BACKGROUND,y
+	iny
+	iny
 
 	; Draw sprite
-	lda #$FFFF
-	sta VRAM,x
-	sta VRAM+2,x
-	sta VRAM+160,x
-	sta VRAM+160+2,x
-	sta VRAM+160*2,x
-	sta VRAM+160*2+2,x
-	sta VRAM+160*3,x
-	sta VRAM+160*3+2,x
-	sta VRAM+160*4,x
-	sta VRAM+160*4+2,x
-	sta VRAM+160*5,x
-	sta VRAM+160*5+2,x
-	sta VRAM+160*6,x
-	sta VRAM+160*6+2,x
-	sta VRAM+160*7,x
-	sta VRAM+160*7+2,x
+	ply
+	jsr Spr_000
 
 renderGameobjectDone:
 	RESTORE_AXY
@@ -224,6 +422,7 @@ renderGameobjectDone:
 	lda vramYOffset,x
 	clc
 	adc SCRATCHL
+	adc #$2000
 	tax			; X now contains the VRAM offset of the upper left corner
 
 	bra unrenderGameobjectBackground
@@ -233,67 +432,272 @@ unrenderGameobjectSkip:
 
 unrenderGameobjectBackground:
 	lda ptr+GO_BACKGROUND,y
-	sta VRAM,x
+	sta VRAMBANK,x
 	iny
 	iny
 	lda ptr+GO_BACKGROUND,y
-	sta VRAM+2,x
+	sta VRAMBANK+2,x
 	iny
 	iny
 	lda ptr+GO_BACKGROUND,y
-	sta VRAM+160,x
+	sta VRAMBANK+4,x
 	iny
 	iny
 	lda ptr+GO_BACKGROUND,y
-	sta VRAM+160+2,x
+	sta VRAMBANK+6,x
+	iny
+	iny
+
+	lda ptr+GO_BACKGROUND,y
+	sta VRAMBANK+160,x
 	iny
 	iny
 	lda ptr+GO_BACKGROUND,y
-	sta VRAM+160*2,x
+	sta VRAMBANK+160+2,x
 	iny
 	iny
 	lda ptr+GO_BACKGROUND,y
-	sta VRAM+160*2+2,x
+	sta VRAMBANK+160+4,x
 	iny
 	iny
 	lda ptr+GO_BACKGROUND,y
-	sta VRAM+160*3,x
+	sta VRAMBANK+160+6,x
+	iny
+	iny
+
+	lda ptr+GO_BACKGROUND,y
+	sta VRAMBANK+160*2,x
 	iny
 	iny
 	lda ptr+GO_BACKGROUND,y
-	sta VRAM+160*3+2,x
+	sta VRAMBANK+160*2+2,x
 	iny
 	iny
 	lda ptr+GO_BACKGROUND,y
-	sta VRAM+160*4,x
+	sta VRAMBANK+160*2+4,x
 	iny
 	iny
 	lda ptr+GO_BACKGROUND,y
-	sta VRAM+160*4+2,x
+	sta VRAMBANK+160*2+6,x
+	iny
+	iny
+
+	lda ptr+GO_BACKGROUND,y
+	sta VRAMBANK+160*3,x
 	iny
 	iny
 	lda ptr+GO_BACKGROUND,y
-	sta VRAM+160*5,x
+	sta VRAMBANK+160*3+2,x
 	iny
 	iny
 	lda ptr+GO_BACKGROUND,y
-	sta VRAM+160*5+2,x
+	sta VRAMBANK+160*3+4,x
 	iny
 	iny
 	lda ptr+GO_BACKGROUND,y
-	sta VRAM+160*6,x
+	sta VRAMBANK+160*3+6,x
+	iny
+	iny
+
+	lda ptr+GO_BACKGROUND,y
+	sta VRAMBANK+160*4,x
 	iny
 	iny
 	lda ptr+GO_BACKGROUND,y
-	sta VRAM+160*6+2,x
+	sta VRAMBANK+160*4+2,x
 	iny
 	iny
 	lda ptr+GO_BACKGROUND,y
-	sta VRAM+160*7,x
+	sta VRAMBANK+160*4+4,x
 	iny
 	iny
 	lda ptr+GO_BACKGROUND,y
-	sta VRAM+160*7+2,x
+	sta VRAMBANK+160*4+6,x
+	iny
+	iny
+
+	lda ptr+GO_BACKGROUND,y
+	sta VRAMBANK+160*5,x
+	iny
+	iny
+	lda ptr+GO_BACKGROUND,y
+	sta VRAMBANK+160*5+2,x
+	iny
+	iny
+	lda ptr+GO_BACKGROUND,y
+	sta VRAMBANK+160*5+4,x
+	iny
+	iny
+	lda ptr+GO_BACKGROUND,y
+	sta VRAMBANK+160*5+6,x
+	iny
+	iny
+
+	lda ptr+GO_BACKGROUND,y
+	sta VRAMBANK+160*6,x
+	iny
+	iny
+	lda ptr+GO_BACKGROUND,y
+	sta VRAMBANK+160*6+2,x
+	iny
+	iny
+	lda ptr+GO_BACKGROUND,y
+	sta VRAMBANK+160*6+4,x
+	iny
+	iny
+	lda ptr+GO_BACKGROUND,y
+	sta VRAMBANK+160*6+6,x
+	iny
+	iny
+
+	lda ptr+GO_BACKGROUND,y
+	sta VRAMBANK+160*7,x
+	iny
+	iny
+	lda ptr+GO_BACKGROUND,y
+	sta VRAMBANK+160*7+2,x
+	iny
+	iny
+	lda ptr+GO_BACKGROUND,y
+	sta VRAMBANK+160*7+4,x
+	iny
+	iny
+	lda ptr+GO_BACKGROUND,y
+	sta VRAMBANK+160*7+6,x
+
+	lda ptr+GO_BACKGROUND,y
+	sta VRAMBANK+160*8,x
+	iny
+	iny
+	lda ptr+GO_BACKGROUND,y
+	sta VRAMBANK+160*8+2,x
+	iny
+	iny
+	lda ptr+GO_BACKGROUND,y
+	sta VRAMBANK+160*8+4,x
+	iny
+	iny
+	lda ptr+GO_BACKGROUND,y
+	sta VRAMBANK+160*8+6,x
+	iny
+	iny
+
+	lda ptr+GO_BACKGROUND,y
+	sta VRAMBANK+160*9,x
+	iny
+	iny
+	lda ptr+GO_BACKGROUND,y
+	sta VRAMBANK+160*9+2,x
+	iny
+	iny
+	lda ptr+GO_BACKGROUND,y
+	sta VRAMBANK+160*9+4,x
+	iny
+	iny
+	lda ptr+GO_BACKGROUND,y
+	sta VRAMBANK+160*9+6,x
+	iny
+	iny
+
+	lda ptr+GO_BACKGROUND,y
+	sta VRAMBANK+160*10,x
+	iny
+	iny
+	lda ptr+GO_BACKGROUND,y
+	sta VRAMBANK+160*10+2,x
+	iny
+	iny
+	lda ptr+GO_BACKGROUND,y
+	sta VRAMBANK+160*10+4,x
+	iny
+	iny
+	lda ptr+GO_BACKGROUND,y
+	sta VRAMBANK+160*10+6,x
+	iny
+	iny
+
+	lda ptr+GO_BACKGROUND,y
+	sta VRAMBANK+160*11,x
+	iny
+	iny
+	lda ptr+GO_BACKGROUND,y
+	sta VRAMBANK+160*11+2,x
+	iny
+	iny
+	lda ptr+GO_BACKGROUND,y
+	sta VRAMBANK+160*11+4,x
+	iny
+	iny
+	lda ptr+GO_BACKGROUND,y
+	sta VRAMBANK+160*11+6,x
+	iny
+	iny
+
+	lda ptr+GO_BACKGROUND,y
+	sta VRAMBANK+160*12,x
+	iny
+	iny
+	lda ptr+GO_BACKGROUND,y
+	sta VRAMBANK+160*12+2,x
+	iny
+	iny
+	lda ptr+GO_BACKGROUND,y
+	sta VRAMBANK+160*12+4,x
+	iny
+	iny
+	lda ptr+GO_BACKGROUND,y
+	sta VRAMBANK+160*12+6,x
+	iny
+	iny
+
+	lda ptr+GO_BACKGROUND,y
+	sta VRAMBANK+160*13,x
+	iny
+	iny
+	lda ptr+GO_BACKGROUND,y
+	sta VRAMBANK+160*13+2,x
+	iny
+	iny
+	lda ptr+GO_BACKGROUND,y
+	sta VRAMBANK+160*13+4,x
+	iny
+	iny
+	lda ptr+GO_BACKGROUND,y
+	sta VRAMBANK+160*13+6,x
+	iny
+	iny
+
+	lda ptr+GO_BACKGROUND,y
+	sta VRAMBANK+160*14,x
+	iny
+	iny
+	lda ptr+GO_BACKGROUND,y
+	sta VRAMBANK+160*14+2,x
+	iny
+	iny
+	lda ptr+GO_BACKGROUND,y
+	sta VRAMBANK+160*14+4,x
+	iny
+	iny
+	lda ptr+GO_BACKGROUND,y
+	sta VRAMBANK+160*14+6,x
+	iny
+	iny
+
+	lda ptr+GO_BACKGROUND,y
+	sta VRAMBANK+160*15,x
+	iny
+	iny
+	lda ptr+GO_BACKGROUND,y
+	sta VRAMBANK+160*15+2,x
+	iny
+	iny
+	lda ptr+GO_BACKGROUND,y
+	sta VRAMBANK+160*15+4,x
+	iny
+	iny
+	lda ptr+GO_BACKGROUND,y
+	sta VRAMBANK+160*15+6,x
 
 unrenderGameobjectDone:
 	RESTORE_AXY
diff --git a/graphics.s b/graphics.s
index b04a838..788d717 100644
--- a/graphics.s
+++ b/graphics.s
@@ -17,7 +17,7 @@ colorFill:
 colorFillLoop:
 	; 80 PHXs, for 1 line
 	; We could do the entire screen with PHXs, but this is a
-	; balance between speed and super-verbose code
+	; balance between speed and code size
 	.byte $da,$da,$da,$da,$da,$da,$da,$da,$da,$da,$da,$da,$da,$da,$da,$da,$da,$da,$da,$da
 	.byte $da,$da,$da,$da,$da,$da,$da,$da,$da,$da,$da,$da,$da,$da,$da,$da,$da,$da,$da,$da
 	.byte $da,$da,$da,$da,$da,$da,$da,$da,$da,$da,$da,$da,$da,$da,$da,$da,$da,$da,$da,$da
@@ -206,13 +206,220 @@ waitVBLToStart:
 	BITS16
 	rts
 
-
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+; TEST OF MR. SPRITE
+;
+Spr_000:
+	FASTGRAPHICS		; 16x16, 464 bytes, 722 cycles
+	clc	
+	tya		; Y = Sprite Target Screen Address (upper left corner)
+	tcs		; New Stack address
+	ldx	#$1111	; Pattern #1 : 14
+	ldy	#$4444	; Pattern #2 : 12
+	lda	#$3333	; Pattern #3 : 6
+	tcd	
+;--		
+	sep	#$20	
+	.a8
+	lda	$A0,S
+	and	#$0F
+	ora	#$10
+	sta	$A0,S
+	lda	$A7,S
+	and	#$F0
+	ora	#$01
+	sta	$A7,S
+	rep	#$30	
+	.a16
+	tsc	
+	adc	#$0007
+	tcs	
+	phx	
+	phx	
+	phx	
+	phx	
+	tsc		; Line 2
+	adc	#$0141
+	tcs	
+	lda	$00,S
+	and	#$000F
+	ora	#$3310
+	sta	$00,S
+	lda	$06,S
+	and	#$F000
+	ora	#$0133
+	sta	$06,S
+	lda	$A0,S
+	and	#$0F0F
+	ora	#$3010
+	sta	$A0,S
+	lda	$A6,S
+	and	#$F0F0
+	ora	#$0103
+	sta	$A6,S
+	tsc	
+	adc	#$0005
+	tcs	
+	phd	
+	phd	
+	tsc		; Line 4
+	adc	#$013F
+	tcs	
+	lda	$00,S
+	and	#$000F
+	ora	#$3410
+	sta	$00,S
+	lda	$06,S
+	and	#$F000
+	ora	#$0143
+	sta	$06,S
+	lda	$A0,S
+	and	#$000F
+	ora	#$3410
+	sta	$A0,S
+	lda	$A6,S
+	and	#$F000
+	ora	#$0143
+	sta	$A6,S
+	tsc	
+	adc	#$0005
+	tcs	
+	phy	
+	phy	
+	tsc		; Line 5
+	adc	#$00A4
+	tcs	
+	lda	$9B,S
+	and	#$0F0F
+	ora	#$3010
+	sta	$9B,S
+	lda	$A1,S
+	and	#$F0F0
+	ora	#$0103
+	sta	$A1,S
+	phy	
+	phy	
+	tsc		; Line 7
+	adc	#$013F
+	tcs	
+	lda	$00,S
+	and	#$000F
+	ora	#$3310
+	sta	$00,S
+	lda	$06,S
+	and	#$F000
+	ora	#$0133
+	sta	$06,S
+	lda	$A0,S
+	and	#$000F
+	ora	#$2210
+	sta	$A0,S
+	lda	$A6,S
+	and	#$F000
+	ora	#$0122
+	sta	$A6,S
+	tsc	
+	adc	#$0005
+	tcs	
+	phd	
+	phd	
+	tsc		; Line 8
+	adc	#$00A4
+	tcs	
+	lda	$9B,S
+	and	#$0F0F
+	ora	#$2010
+	sta	$9B,S
+	lda	$A1,S
+	and	#$F0F0
+	ora	#$0102
+	sta	$A1,S
+	pea	$2222
+	pea	$2222
+	tsc		; Line 10
+	adc	#$013F
+	tcs	
+	lda	$00,S
+	and	#$000F
+	ora	#$2410
+	sta	$00,S
+	lda	$06,S
+	and	#$F000
+	ora	#$0142
+	sta	$06,S
+	lda	$A0,S
+	and	#$000F
+	ora	#$2410
+	sta	$A0,S
+	lda	$A6,S
+	and	#$F000
+	ora	#$0142
+	sta	$A6,S
+	tsc	
+	adc	#$0005
+	tcs	
+	phy	
+	phy	
+	tsc		; Line 11
+	adc	#$00A4
+	tcs	
+	lda	$9B,S
+	and	#$0F0F
+	ora	#$2010
+	sta	$9B,S
+	lda	$A1,S
+	and	#$F0F0
+	ora	#$0102
+	sta	$A1,S
+	phy	
+	phy	
+	tsc		; Line 13
+	adc	#$013F
+	tcs	
+	lda	$00,S
+	and	#$000F
+	ora	#$2210
+	sta	$00,S
+	lda	$06,S
+	and	#$F000
+	ora	#$0122
+	sta	$06,S
+	sep	#$20	
+	.a8
+	lda	$A0,S
+	and	#$0F
+	ora	#$10
+	sta	$A0,S
+	lda	$A7,S
+	and	#$F0
+	ora	#$01
+	sta	$A7,S
+	rep	#$30	
+	.a16
+	tsc	
+	adc	#$0005
+	tcs	
+	pea	$2222
+	pea	$2222
+	tsc		; Line 15
+	adc	#$0146
+	tcs	
+	phx	
+	phx	
+	phx	
+	phx	
+;--		
+SLOWGRAPHICS		
+	rts	
+		
+;------------------------------		
+
+
+
 ; caches
 shadowRegister:
-	.byte 0
+.byte 0
 stackRegister:
-	.byte 0
+.byte 0
 stackPtr:
-	.word 0
-
+.word 0
diff --git a/gscats.2mg b/gscats.2mg
index aacd08266d337244394ba7611f1c459a288af10a..1923a81a023cd7c9461f28475bc8b7452cf6d17d 100644
GIT binary patch
delta 6471
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

delta 3964
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
On%<zg`~U8?qWIqg0n1ka

diff --git a/macros.s b/macros.s
index c688b5e..b1ad0bc 100644
--- a/macros.s
+++ b/macros.s
@@ -69,44 +69,45 @@
 .endmacro
 
 
-.macro FASTGRAPHICS
-	sei
-	sep #%00100000	; 16-bit A only, to preserve X/Y
+.macro FASTGRAPHICS			;51 cycles, 12 bytes
+	sei						;2
+	phd						;4
+	sep #%00100000	;		 3   16-bit A only, to preserve X/Y
 	.a8
 
-	lda SHADOW
-	sta shadowRegister
-	lda #0
-	sta SHADOW
+	lda SHADOW				;5
+	sta shadowRegister		;4
+	lda #0					;2
+	sta SHADOW				;5
 
-	lda STACKCTL
-	sta stackRegister
-	ora #$30
-	sta STACKCTL
+	lda STACKCTL			;5
+	sta stackRegister		;4
+	ora #$30				;2
+	sta STACKCTL			;5
 
-	rep #%00100000
+	rep #%00100000			;3
 	.a16
-	tsc
-	sta stackPtr
+	tsc						;2
+	sta stackPtr			;5
 .endmacro
 
 
-.macro SLOWGRAPHICS
-	sep #%00100000	; 16-bit A only, to preserve X/Y
+.macro SLOWGRAPHICS			;38 cycles, 12 bytes
+	sep #%00100000	;        3    16-bit A only, to preserve X/Y
 	.a8
 
-	lda shadowRegister
-	sta SHADOW
+	lda shadowRegister		;4
+	sta SHADOW				;5
 
-	lda stackRegister
-	sta STACKCTL
+	lda stackRegister		;4
+	sta STACKCTL			;5
 
-	rep #%00100000
+	rep #%00100000			;3
 	.a16
-	lda stackPtr
-	tcs
-
-	cli
+	lda stackPtr			;5
+	tcs						;2
+	pld						;5
+	cli						;2
 .endmacro
 
 
@@ -131,6 +132,8 @@
 	pha
 	lda breakpoint
 	beq nobrk
+	lda #1
+	sta $e1c029
 	pla
 	brk
 nobrk:
diff --git a/player.s b/player.s
index 79e781d..e40e2a5 100644
--- a/player.s
+++ b/player.s
@@ -11,29 +11,41 @@ playerData:
 	.word 0	; X pos in pixels (from left terrain edge)
 	.word 0	; Y pos in pixels (from bottom terrain edge)
 	.word 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0	; Saved background
+	.word 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
+	.word 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
+	.word 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
 
 	.word 90		; Angle in degrees from +X
 	.word 1		; Power
 	.word 100		; Anger
 	.byte 8,"SPROCKET "	; Name
-	.word 0,0,0,0,0,0 ;Padding
+
+	.repeat 108
+	.byte 0		; Padding to 256-byte boundary
+	.endrepeat
 
 	; gameobject data
 	.word 0	; X pos in pixels (from left terrain edge)
 	.word 0	; Y pos in pixels (from bottom terrain edge)
 	.word 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0	; Saved background
+	.word 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
+	.word 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
+	.word 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
 
-	.word 45		; Angle in degrees from +X
+	.word 135		; Angle in degrees from +X
 	.word 1	; Power
 	.word 100		; Anger
 	.byte 8,"TINKER   "	; Name
-	.word 0,0,0,0,0,0 ;Padding
 
-PD_ANGLE = 36
-PD_POWER = 38
-PD_ANGER = 40
-PD_NAME = 42
-PD_SIZE = 64
+	.repeat 108
+	.byte 0		; Padding to 256-byte boundary
+	.endrepeat
+
+PD_ANGLE = 132
+PD_POWER = 134
+PD_ANGER = 136
+PD_NAME = 138
+PD_SIZE = 256
 
 .macro PLAYERPTR_Y
 	tya		; Pointer to player structure from index
@@ -43,6 +55,8 @@ PD_SIZE = 64
 	asl
 	asl
 	asl
+	asl
+	asl
 	tay
 .endmacro
 
@@ -164,6 +178,7 @@ playerFire:
 ; A => non zero if rectangle is intersecting player
 ;
 playerIntersectRect:
+	phy
 	PLAYERPTR_Y
 
 	lda playerData+GO_POSX,y
@@ -174,8 +189,9 @@ playerIntersectRect:
 	sta rectParams2+4
 	lda #GAMEOBJECTHEIGHT
 	sta rectParams2+6
-	jsr intersectRectRect
 
+	jsr intersectRectRect
+	ply
 	rts
 
 
diff --git a/projectile.s b/projectile.s
index 82176bf..54181f7 100644
--- a/projectile.s
+++ b/projectile.s
@@ -11,6 +11,9 @@ projectileData:
 	.word -1	; Pos X in pixels (from left terrain edge)
 	.word 0		; Pos Y in pixels (from bottom terrain edge)
 	.word 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0	; Saved background
+	.word 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
+	.word 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
+	.word 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
 
 	.word 0		; Pos X (12.4 fixed point)
 	.word 0		; Pos Y (12.4 fixed point)
@@ -19,12 +22,16 @@ projectileData:
 	.word 0		; Type
 	.word 1		; New?
 
-JD_PRECISEX = 36		; Byte offsets into projectile data structure
-JD_PRECISEY = 38
-JD_VX = 40
-JD_VY = 42
-JD_TYPE = 44
-JD_NEW = 46
+	.repeat 112
+	.byte 0		; Padding to 256-byte boundary
+	.endrepeat
+
+JD_PRECISEX = 132		; Byte offsets into projectile data structure
+JD_PRECISEY = 134
+JD_VX = 136
+JD_VY = 138
+JD_TYPE = 140
+JD_NEW = 142
 
 GRAVITY = $ffff	; 8.8 fixed point
 
@@ -43,6 +50,10 @@ PT_RADIUS = 2
 	asl
 	asl
 	asl
+	asl
+	asl
+	asl
+	asl
 	tay
 .endmacro
 
@@ -234,16 +245,17 @@ updateProjectileCollisions:
 	sta rectParams+6
 
 updateProjectileCollisionsPlayerLoop:
-	iny
-	cpy #NUMPLAYERS
-	beq updateProjectileCollisionsPlayerDone
 	cpy currentPlayer
-	beq updateProjectileCollisionsPlayerLoop
+	beq updateProjectileCollisionsPlayerNext
+
 	jsr playerIntersectRect
 	cmp #0
 	bne updateProjectileCollisionsPlayerHit
 
-updateProjectileCollisionsPlayerDone:
+updateProjectileCollisionsPlayerNext:
+	iny
+	cpy #NUMPLAYERS
+	bne updateProjectileCollisionsPlayerLoop
 
 	; Check for terrain collisions
 	lda projectileData+GO_POSX
@@ -280,6 +292,7 @@ updateProjectileCollisionsTerrainHit:
 ; Trashes A and Y
 ;
 endProjectile:
+	UNRENDER_GAMEOBJECT projectileData
 	ldy #0
 	jsr deleteProjectile
 	lda #1
@@ -347,9 +360,10 @@ unrenderProjectilesDone:
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ; processPlayerImpact
 ;
-; Y = Byte offset of player that was hit
+; Y = Index of player that was hit
 ;
 processPlayerImpact:
+	PLAYERPTR_Y
 	tyx
 
 	ldy #0		; Assume projectile 0