[stella] Gravity Ball v015 - Thanks!

Subject: [stella] Gravity Ball v015 - Thanks!
From: R Mundschau <rmundsc@xxxxxxxxx>
Date: Wed, 04 Jun 2003 02:26:15 -0500
Hi All,

Thanks for the feedback.  Here is the updated version.  I am going to take
this one to the Midwest Classic.   I am not reattaching the .h files because
they did not change since v014

The biggest bug I found was that I wasn't setting VBLANK at the start of the
overscan period in the Title Screen.   That's why Stella was showing more
lines in the title screen than the game screen, and I was confused.   Thanks
again!

Regards,
Rob

> From: R Mundschau <rmundsc@xxxxxxxxx>
> Reply-To: stella@xxxxxxxxxxx
> Date: Tue, 03 Jun 2003 15:58:01 -0500
> To: <stella@xxxxxxxxxxx>
> Subject: [stella] Gravity Ball v014 -  Please help!
> 
> Hi,
> 
> Please find attached the source code and binary for the current version of
> Gravity Ball.  Its not much yet.  There are no controls just a looping
> visual demo.   I want to show this demo at the Midwest Classic this
> Saturday.  I need some help getting it debugged.
> 
> Specifically I am not confident that my code is generating the right number
> of scanlines.   I am writing this on a Mac, and I haven't found any feature
> in the Stella emulator to tell me how many lines I am generating.  Someone
> please correct me if I am wrong.   I believe line counts is a feature of the
> Z26 emulator.  If it is, could someone please try it and let me know how
> many scanlines I am producing for each of the 2 screens in the demo.
> 
> If someone would load it into a Cuttle cart and see if it have a stable
> picture on a real TV I would be very grateful.   I need to get a ROM to
> Albert within the next 24 hours to get a demo cart done for the MWC.
> 
> I really appreciate your help.   BTW its a 4K image.
> 
> Sincerely,
> Rob Mundschau
> 
> 
> 

Attachment: gravity_ball_v015.bin
Description: Binary data

Attachment: gravity_ball_v015.asm
Description: application/applefile

;
; Gravity Ball
; by Rob Mundschau  
; Last Modified:  6/3/03 
; Version: 015
; Assembler: DASM
; Target ROM Size: 4K
; build command:
; dasm gravity_ball_v015.asm -f3 -v2 -ogravity_ball_v015.bin -lgravity_ball_v015.list -sgravity_ball_v015.sym
;

	processor 6502
	include vcs.h

	org $F000          ; Setting the org to $F000 rather than $1000 ensures that the upper 3 bits of all 16-bit addresses
	                   ; generated by the compiler will be set to 1.
;
; Global Constants
; 
Mode_TITLE = $00  ; Enumeration of possible values for variable b_Mode.
Mode_MENU  = $01
Mode_GAME  = $02
  
c_VerticalBlankOff = $00  
  
;
; Global RAM Variable Allocations
;
; 10 Byte array to store a string for rendering on the screen.
a_StringBuf = $80
b_Char0 	= $80
b_Char1 	= $81
b_Char2		= $82
b_Char3		= $83
b_Char4		= $84
b_Char5		= $85
b_Char6		= $86
b_Char7		= $87
b_Char8		= $88
b_Char9		= $89

b_TextColor	= $8A

b_GraphicBuf0 = $8B
b_GraphicBuf1 = $8C
b_GraphicBuf2 = $8D
b_GraphicBuf3 = $8E
b_GraphicBuf4 = $8F

b_Mode	= $90	; The current game state. ($00 = Title)
b_Count	= $91   ; Absolute 8-bit frame count.
b_Randm = $92   ; Pseudo Random numer = (b_Count * 7 + b_Count + Carry) MOD 256
b_Lum   = $93   ; Base luminance for color shifting effects, reset from b_Count each frame.

;--- The following locations store the actual X and Y locations of the visible graphic objects
; on the screen.
; The on screen position of the graphics is a translation of the virtual position of the objects. 
b_P0scrX	= $94
b_P0scrY	= $95	; Line on which P0 begins display minus 1
b_P1scrX	= $96
b_P1scrY	= $97	; Line on which P1 begins display minus 1 
b_M0scrX	= $98
b_M0scrY	= $99 	; y-pos of Missle 0 graphic
b_M1scrX	= $9A
b_M1scrY	= $9B	; y-pos of Missle 1 graphic
b_BallscrX	= $9C
b_BallscrY	= $9D	; y-pos of Ball graphic

w_PF1ptr	= $9E	; pointer to graphic data for PF1, indirect indexed by line count in Y.
w_PF2ptr	= $A0	; pointer to graphic data for PF2, indirect indexed by line count in Y.
w_P0ptr		= $A2	; pointer to p0 sprite graphics
w_P1ptr		= $A4	; pointer to p1 sprite graphics
b_Zero		= $A6	; This zeropage location always holds $00.  We use it to waste cycles in the kernal.
b_PFColor   = $A7	; The color of the arena walls.
b_PF1baseY	= $A8	; Starting Y-pos of PF1 walls
b_PF2baseY	= $A9 	; Starting Y-pos of PF2 walls

b_Delay		= $AA	; Slow down demo screen switches.

;
; ----------------------- CODE ---------------------------------
;

Powerup
; **************************************************************
; Powerup routine.  This routine executes only once, when the system is
; intially powered on
; [begin] Powerup
	SEI	; Disable interrupts, just in case this is running in a future system which has interrupts.
	CLD ; Clear the decimal mode flag.
	
; Initiaize the stack pointer
	LDX	#$FF
	TXS

;
; Clear RAM and TIA registers.  Loop assumes X contains $FF
;
	LDA #0
B1  STA 0,X
	DEX
	BNE B1
;
; The above routine does not clear location 0, which is VSYNC.  At the end of the loop
; both A and X are zero.  Y is undefined.  The stack is empty.
;
; Initialize Global variables
;
;   LDA #Mode_TITLE  ; Mode_TITLE == 0.  A = 0 so this instruction is implied and can be commented out
; 	STA b_Mode	     ; The loop above to clear RAM and 
;
; Initialize PIA DDR registers to set up Joysticks
;

; TBD

; Enable Vertical Blanking to start the system. From the point of view
; of the game logic we are in the Overscan portion of the initial frame.  
	LDA #2
	STA VBLANK
	;TBD - do we need to enable the I4 and I5 latches?

; The first screen after powerup is the title screen so call the 
; subroutine to init our custom text mode, and then jump to the 
; routine to perform vertical sync for frame 0.
	JSR	S_InitTextScreenMode
	JMP	VerticalSync

; [end] Powerup
; **************************************************************

S_InitTextScreenMode
; **************************************************************
; This routine sets up the TIA Registers to display a text mode
; screen.  The background is set to blue.  The Player's and Missles
; are set to a different shade of blue to create the vertical stripe
; effect on the text screen.
; The sprites and missle HMOVE constants and graphics are set.
; The audio volume registers are cleared
; The Foreground colorwave variables are initialized
; [begin] InitTitleScreen
	LDX #13  ; We will copy 2 banks of 14 values into TIA registers.
B2	LDA TextTIA_1,X
	STA NUSIZ0,X
	LDA TextTIA_2,X
	STA AUDV0,X
	DEX
	BPL B2
	RTS

TextTIA_1
	.byte $13, $06, $82, $82, $1E, $80, $14, $00, $00, $00, $00, $00, $00, $00
TextTIA_2
	.byte $00, $00, $B3, $ED, $02, $02, $00, $20, $E0, $F0, $10, $00, $00, $00

; [end] InitTextScreenMode
;****************************************************************

VerticalSync
;****************************************************************
; This routine performs the 3 line vertical sync and then passes
; control to the Screen Mode Router to render the next frame.
; It is assumed that Vblank is already enabled from the overscan of
; the previous frame.  Before exiting this routine the T64 timer 
; is set to count down the vertical blank time.   It will also increment
; the b_Count frame counter and update b_Randm.  The routine ends
; by passing control to the address indicated by the value in b_Mode.
; [begin] VerticalSync
	STA WSYNC  ; sync with end of last line of overscan from previous frame.
	LDA #02
	STA VSYNC  ; Enable vsync
	STA WSYNC  ; vsync for 2 scanlines
	STA WSYNC
	STA	WSYNC


; Initilize the VBlank Timer:
; Atari says we have to have 37 scanlines of VBLANK time.  Since
; each scanline uses 76 cycles, that makes 37*76=2888 cycles.
; We must also subtract the five cycles it will take to set the
; timer, and the three cycles it will take to STA WSYNC to the next
; line.  Plus the checking loop is only accurate to six cycles, making
; a total of fourteen cycles we have to waste.  2888-14=2876.
;
; We almost always use TIM64T for this, since the math just won't
; work out with the other intervals.  2880/64=44.something.  It
; doesn't matter what that something is, we have to round DOWN.
;
	LDA #44				
	STA VSYNC ; The value 44 does not have bit 1 set so we can use it to clear VSYNC register.
	STA WSYNC			
	STA TIM64T			


; The RTS instruction pull the address we pushed onto the stack earlier and jumps to that location.
	
	; Add one to the frame count.
	INC b_Count		;[0]+5
	
; Update the psuedo Random Number generator.  This method for producing
; Random Numbers assumes that it is sampled infrequently.  No more
; than once every few frames.	
	LDA b_Randm		
	ADC b_Count		
	ADC #7			
	STA b_Randm		

; b_Lum is the base luminance for any color cycling on the screen.   We update its
; value every frame as b_Count/4
	LDA b_Count
	LSR
	LSR
	AND #$0F	
	STA b_Lum	; Store base luminence

; The value in b_Mode tells us what we are doing, and hence what
; type of screen to draw, and how to process user inputs.  The 
; Timer is set from the VerticalSync routine above.  This routine
; will pass control to the correct Frame handler based on b_Mode.
; Each frame routine must monitor the Timer to know when to begin
; drawing the frame.  We pass control by pushing the target address
; onto the stack and then performing an RTS instruction.

;------ Demo Code
	LDA	b_Count			; this code switches between the title and game screen every 256*3 frames.
	BNE	F21
	LSR	b_Delay
	BNE	F21
	LDA	#%00001111
	STA b_Delay
	
	LDA	b_Mode
	BEQ	F22
	JSR	S_InitTextScreenMode
	LDA #0
	JMP	F23
F22	JSR S_InitGameScreenMode
	LDA #2
F23	STA	b_Mode
F21
;------ End Demo code

	LDX b_Mode			
	LDA FrameJumpHi,X	
	PHA					
	LDA FrameJumpLo,X	
	PHA					

	RTS

FrameJumpHi
	.byte	>DTSVector			; Title Screen
	.byte	$00					; placeholder for menu
	.byte	>DGSVector			; Game Screen
	
	
FrameJumpLo
	.byte	<DTSVector			; Title Screen
	.byte	$00					; Place holder for menu
	.byte	<DGSVector			; Game Screen
	
	
; [end] Vertical Sync
;****************************************************************


S_TextModeCommonVB
;*******************************************************************
; This subroutine performs the tasks common to all Text Mode 
; screens during the Vertical Blank Period.
; [begin] S_TextModeCommonVB
	LDA b_Count ; Perform HMOVE every fourth frame.
	AND #03
	BNE F1
	
	STA WSYNC
	STA HMOVE	; Move sprites and missles (Vertical lines) on text screen.
	
F1	
	RTS
; [end] S_TextModeCommonVB
;********************************************************************


DrawTitleScreen
DTSVector = DrawTitleScreen - 1 
;******************************************************************
; Vertical Blank:
; During vertical blank we execute the HMOVE to move the vertical bars 
; in the background of the title screen.  I will also initialize any 
; variables needed to generate the frame.
; [begin] DrawTitleScreen
	

	JSR S_TextModeCommonVB
	
	LDY #59 		; Set Y to count 60 blank scanlines
	
	LDX #15			; We will use X to index the title graphic data table. 
		
	
B3	LDA INTIM		;Wait for the end of vertical blank.
	BNE B3
	STA VBLANK		;A=0, so use it to clear vertical blank.
	
; Visible Screen:
B4	STA WSYNC		; Synchronize to start of first visible line.
	
	DEY
	BNE B4			; No title yet, just the vertical lines.
	
	
; top of scanline loop			
B6	STA WSYNC			;[72]+3 = 75  Worst case timing of scanline loop to display title.
						; We need to throw away a whole line to synchronize for cycle counting.
						; Note that Y is zero entering the loop which means the top line of the
						; title will be 1 scanline thick.
						; This loop assumes that PF0 is set to $00 upon entry.

	LDA b_Lum			;[0]+3 = 3 Animate color cycling of title text.
;	AND #$0F			;---------- Not needed because color is $F0. 
	ORA #$F0			;[3]+2 = 5
	STA COLUPF			;[5]+3 = 8	; Set Playfield color for this line
	
	LDA TitleColumn1,X	;[8]+4 = 12
	STA PF1				;[12]+3 = 15  < 29 PF1 Visible
	LDA TitleColumn2,X	;[15]+4 = 19  < 40 PF2 Visible
	STA PF2				;[19]+3 = 22
	
	LDA TitleColumn3,X	;[22]+4 = 26
	STA PF0				;[26]+3 = 29  > 28 PF0 Not Visible

	LDA TitleColumn4,X	;[29]+4 = 33
	DEY					;[33]+2 = 35
	NOP					;[35]+2 = 37
	STA PF1				;[37]+3 = 40 >= 40 PF1 not visible
	BPL F3				;[40]+2 = 42					;[40]+3=43 Branch Taken

	DEX					;[42]+2 = 44
	BMI F2				;[44]+2 = 46  ; If the branch is taken, then the loop to draw the title is finished.  


	INY				;[46]+2 = 48  ; If X is even set Y=6 otherwise Y=0
	TXA				;[48]+2 = 50  
	LSR				;[50]+2 = 52
	BCS F3			;[52]+2 = 54	
	LDY #6			;[54]+2 = 56
			
F3	LDA #0			;[56]+2 = 58						;[43]+2=45	
	STA PF2			;[58]+3 = 61 < 65 PF2 visible		;[45]+3=48	= PF2 invisible starting cycle 48			
	DEC b_Lum		;[61]+5 = 66						;[48]+5=53
	STA PF0			;[66]+3 = 69 > 54 PF0 invisible		;[53]+3=56	> PF0 invisible starting cycle 54
	JMP B6			;[69]+3 = 72

F2	LDY #55			;Use Y to count 55 blank lines
B7	STA WSYNC
	DEY
	BNE B7	

	LDX	#9	
B16	LDA	S_RPM_Games,X
	STA	a_StringBuf,X
	DEX
	BPL	B16
	LDA	#$44
	STA	b_TextColor

	JSR	S_DrawText

	LDY #3			;Use Y to count remaining 3 blank lines
B8	STA WSYNC
	DEY
	BNE B8	

	
; Overscan:
	LDA #$02
	STA	VBLANK

	LDY #30 		; Count 30 lines of overscan.  Later
					; We will check the Joysticks and console switches
					; during overscan.
B5	STA WSYNC		; Sync to the end  of the last visible line, and all
					; overscan lines except the last one.
	DEY
	BNE B5
	
	;With the Title frame complete we jump to the VerticalSync routine.
	JMP VerticalSync	

; [end] DrawTitleScreen
;**********************************************************************	


S_DrawText 
;******************************************************************
; This routine assumes that the string to be displayed is stored in
; a_StringBuffer.   The color for the string must be stored in b_TextColor.
; This routine will consume 10+ scanlines = 2 blank lines followed by
; 7 lines of text graphics, then 1 blank line.  The routine turns off vertical
; blanking at the start of the 1st line of visible graphics.  Therefore it is
; possible to begin this routine during vertical blank and have the text appear
; begining with the first visible line on the screen.
;
; Important identifiers used:
;
; a_StringBuf[10]	The string of 10 characters to be displayed.
; b_Char0			Each character is a 8-bit offset into the 4 
; b_Char1 			Char set graphic tables stored in ROM.
; b_Char2
; b_Char3
; b_Char4
; b_Char5
; b_Char6
; b_Char7
; b_Char8
; b_Char9
;
; g_CharSetPF1Lo	Four 128 byte tables of Character graphics
; g_CharSetPF1Hi	stored in ROM.  Since PF1 bytes are reversed
; g_CharSetPF2Hi    from PF0 and PF2 bytes we decided to use
; g_CharSetPF2Lo    separate tables rather than try to reverse
;                   bytes in real time.
;
; b_GraphicBuf0		We use these Buffer bytes to store values
; b_GraphicBuf1     destined for the PF registers until we actually
; b_GraphicBuf2     are ready to load them.
; b_GraphicBuf3
; b_GraphicBuf4
; b_GraphicBuf5
; b_GraphicBuf...

	STA WSYNC		; Synchronize to start of line for cycle counting.	
	
	LDX	b_Char8				;[0]+3
	LDY	b_Char9				;[3]+3
	LDA g_CharSetPF2Lo,X	;[6]+4
	ORA	g_CharSetPF2Hi,Y	;[10]+4
	STA	b_GraphicBuf2		;[14]+3	
	LDA g_CharSetPF2Lo+1,X	;[17]+4
	ORA	g_CharSetPF2Hi+1,Y	;[21]+4
	STA	b_GraphicBuf3		;[25]+3
	LDA g_CharSetPF2Lo+2,X	;[28]+4
	ORA	g_CharSetPF2Hi+2,Y	;[32]+4
	STA	b_GraphicBuf4		;[36]+3
	LDA g_CharSetPF2Lo+3,X	;[39]+4
	ORA	g_CharSetPF2Hi+3,Y	;[43]+4
	STA	b_Char8				;[47]+3
	LDA g_CharSetPF2Lo+4,X	;[50]+4
	ORA	g_CharSetPF2Hi+4,Y	;[54]+4
	STA	b_Char9				;[58]+3 = 61
	
	LDX	b_Char6				;[61]+3
	LDY	b_Char7				;[64]+3
	LDA	g_CharSetPF1Hi+1,X	;[67]+4
	ORA	g_CharSetPF1Lo+1,Y	;[71]+4
	STA	b_GraphicBuf0		;[75]+3		; End of scanline -2
	LDA	g_CharSetPF1Hi+2,X	;[2]+4
	ORA	g_CharSetPF1Lo+2,Y	;[6]+4
	STA	b_GraphicBuf1		;[10]+3
	LDA	g_CharSetPF1Hi+3,X	;[13]+4
	ORA	g_CharSetPF1Lo+3,Y	;[17]+4
	STA	b_Char6				;[21]+3
	LDA	g_CharSetPF1Hi+4,X	;[24]+4
	ORA	g_CharSetPF1Lo+4,Y	;[28]+4
	STA	b_Char7				;[32]+3
	LDA	g_CharSetPF1Hi,X	;[35]+4
	ORA	g_CharSetPF1Lo,Y	;[39]+4
	TAY						;[43]+2	= 45 ; Save a copy of PF1 - Right - Line 0 in Y.
	
	LDA	b_Lum				;[45]+3				
	AND	#$0F				;[48]+2
	ORA	b_TextColor			;[50]+3
	STA	COLUPF				;[53]+3		Text color line 0

	LDX	b_Char0				;[56]+3
	LDA	g_CharSetPF2Hi,X	;[59]+4	
	STA	PF0					;[63]+3 = 66	PF0 - Left - Line 0
	
	LDX	b_Char1				;[67]+3
		
	LDA #c_VerticalBlankOff	;[70]+2
	STA	VBLANK				;[72]+3   Turn off veritcal blank if it is on.
	
	LDA	g_CharSetPF1Hi,X	;[75]+4		; End of scanline -1.
	LDX b_Char2				;[3]+3
	ORA	g_CharSetPF1Lo,X	;[6]+4
	STA	PF1					;[10]+3 = 13 	PF1 - Left - Line 0
	
	LDX b_Char3				;[13]+3
	LDA g_CharSetPF2Lo,X	;[16]+4
	LDX	b_Char4				;[20]+3
	ORA g_CharSetPF2Hi,X	;[23]+4
	STA	PF2					;[27]+3	= 30	PF2 - Left - Line 0	
	
	LDX	b_Char5				;[30]+3
	LDA	g_CharSetPF2Hi,X	;[33]+4
	STA	PF0					;[37]+3 = 40 	PF0 - Right - Line 0
	STY	PF1					;[40]+3 = 43	PF1 - Right - Line 0

	LDA	b_GraphicBuf2		;[43]+3
	LDY	b_Char0				;[46]+3
	STA	PF2					;[49]+3 = 52	PF2 - Right - Line 0
	
	LDA	g_CharSetPF2Hi+1,Y	;[52]+4
	STA	PF0					;[56]+3	= 59	PF0 - Left - Line 1
	
	LDY	b_Char1				;[59]+3
	
	DEC	b_Lum				;[62]+5
	LDA	b_Lum				;[67]+3
	AND	#$0F				;[70]+2	
	ORA	b_TextColor			;[72]+3
	STA	COLUPF				;[75]+3			Text color line 1; End of Scanline 0, Note X = b_Char5
					
	LDA	g_CharSetPF1Hi+1,Y	;[2]+4
	LDY	b_Char2				;[6]+3
	ORA	g_CharSetPF1Lo+1,Y	;[9]+4
	STA	PF1					;[13]+3 = 16	PF1 - Left - Line 1
	STA b_GraphicBuf2		;[16]+3 = 19 	Save a copy in b_GraphicBuf2
	
	LDY b_Char3				;[19]+3
	LDA	g_CharSetPF2Lo+1,Y	;[22]+4
	LDY	b_Char4				;[26]+3
	ORA	g_CharSetPF2Hi+1,Y	;[29]+4
	STA	PF2					;[33]+3 = 36 	PF2 - Left - Line 1
	
;	LDX	b_Char5				;Still in X from previous scanline.
	LDY	g_CharSetPF2Hi+1,X	;[36]+3
	STY	PF0					;[39]+3	= 42	PF0	- Right - Line 1
	LDX	b_GraphicBuf0		;[42]+3
	STX	PF1					;[45]+3 = 48	PF1 - Right - Line 1
	LDX	b_GraphicBuf3		;[48]+3
	STX	PF2					;[51]+3 = 54	PF2 - Right - Line 1
	
	TAX						;[54]+2			Save a copy of PF2 - Left - 1 in X
	DEC b_Lum				;[56]+5 
	
	LDA	b_GraphicBuf2		;[61]+3			Load saved copy
	STA	PF1					;[64]+3 = 67	PF1 - Left - Line 2
	
	LDA	b_Lum				;[67]+3
	AND	#$0F				;[70]+2	
	ORA	b_TextColor			;[72]+3
	STA	COLUPF				;[75]+3			Text color line 2; End of Scanline 1
	
	STX	PF2					;[2]+3			PF2 - Left - Line 2
	
	LDX b_Char0
	LDA	g_CharSetPF2Hi+1,X	;[5]+4
	STA	PF0					;[9]+3 = 12		PF0 - Left - Line 2
	
	LDX	b_Char1				;[12]+3
	LDA	g_CharSetPF1Hi+2,X	;[15]+4
	LDX	b_Char2				;[19]+3
	ORA g_CharSetPF1Lo+2,X	;[22]+4
	TAX						;[26]+2			Save PF1 - Left - Line 3 in X
	
	STY	PF0					;[28]+3 = 31	PF0 - Right - Line 2
	
	LDY	b_Char3				;[31]+3
	LDA	g_CharSetPF2Lo+2,Y	;[34]+4
	LDY b_Char4				;[38]+3
	ORA	g_CharSetPF2Hi+2,Y	;[41]+4
	
	LDY	b_GraphicBuf0		;[45]+3			b_GraphicBuf 0 is available.
	STY	PF1					;[48]+3	= 51	PF1 - Right - Line 2
	LDY b_GraphicBuf3		;[51]+3			b_GraphicBuf 3 is now available
	STY	PF2					;[54]+3 = 57	PF2 - Right - Line 2
	
	TAY						;[57]+2			Save PF2 - Left - Line 3 in Y
	
	DEC b_Lum				;[59]+5
	LDA	b_Lum				;[64]+3
	AND	#$0F				;[67]+2	
	ORA	b_TextColor			;[69]+3
	
	STX	PF1					;[72]+3			PF1 - Left - Line 3
	STA	COLUPF				;[75]+3			Text color line 3; 		End of Scanline 2
	STY	PF2					;[2]+3			PF2 - Left - Line 3
	
	LDY	b_Char0				;[5]+3
	LDA	g_CharSetPF2Hi+2,Y	;[8]+4
	STA	PF0					;[12]+3 = 15 	PF0 - Left Line 3
	
	LDY b_Char5				;[15]+3
	LDA	g_CharSetPF2Hi+2,Y	;[18]+4
	
	LDX	b_Char1				;[22]+3
	LDY	b_Char2				;[25]+3
	
	STA	PF0					;[28]+3 = 31 	PF0	- Right Line 3
	
	LDA g_CharSetPF1Hi+4,X	;[31]+4
	ORA	g_CharSetPF1Lo+4,Y	;[35]+4
	STA	b_GraphicBuf0		;[39]+3			Save a copy of PF1 - Left - Line 6
	
	LDA	b_GraphicBuf1		;[42]+3
	STA	PF1					;[45]+3	= 48	PF1 - Right - Line 3
	LDA	b_GraphicBuf4		;[48]+3
	STA	PF2					;[51]+3 = 54	PF2 - Right - Line3
	
	LDA	g_CharSetPF1Hi+3,X	;[54]+4
	ORA g_CharSetPF1Lo+3,Y	;[58]+4 
	STA	b_GraphicBuf3		;[62]+3			Save a copy of PF1 - Left Line 5
	STA PF1					;[65]+3 = 68	PF1 - Left - Line 4
	
	DEC b_Lum				;[68]+5			End of Scanline 3
	LDA	b_Lum				;[73]+3		
	AND	#$0F				;[0]+2		
	ORA	b_TextColor			;[2]+3
	STA	COLUPF				;[5]+3			Text color line 4
	
	LDX b_Char0				;[8]+3
	LDA	g_CharSetPF2Hi+3,X	;[11]+4
	STA	PF0					;[15]+3	= 18	PF0 - Left - Line 4
	
	LDY	b_Char3				;[18]+3
	LDA	g_CharSetPF2Lo+3,Y	;[21]+4
	LDY	b_Char4				;[25]+3
	ORA	g_CharSetPF2Hi+3,Y	;[28]+4	
	STA	PF2					;[32]+3 = 35	PF2 - Left - Line 4		Save a copy of PF2 - Left - Line 5 in A.
	
	LDX	b_Char5				;[35]+3
	LDY	g_CharSetPF2Hi+3,X	;[38]+4
	STY	PF0					;[42]+3 = 45	PF0 - Right - Line 4;  	Save a copy of PF0 - Right - Line 5 in Y
	
	LDX	b_Char6				;[45]+3			Load copy of PF1 - Right - Line 4
	STX	PF1					;[48]+3 = 51 	PF1 - Right - Line 4
	
	LDX	b_Char8				;[51]+3			Load copy of PF2 - Right - Line 4
	STX	PF2					;[54]+3 = 57	PF2 - Right - Line 4
	
	DEC b_Lum				;[57]+5
	
	LDX	b_GraphicBuf3		;[62]+3 		Load copy of PF1 - Left - Line 5
	STX	PF1					;[65]+3 = 68	PF1 - Left - Line 5

	LDX	b_Char0				;[68]+3
	NOP						;[71]+2
	STA	PF2					;[73]+3			PF2 - Left - Line 5;  End of scanline 4
	LDA	g_CharSetPF2Hi+3,X	;[0]+4
	STA	PF0					;[4]+3 = 7		PF0 - Left - Line 5
	
	LDA	b_Lum				;[7]+3		
	AND	#$0F				;[10]+2		
	ORA	b_TextColor			;[12]+3
	STA	COLUPF				;[15]+3			Text color line 5
	
	LDX	b_Char3				;[18]+3
	LDA	g_CharSetPF2Lo+4,X	;[21]+4
	LDX	b_Char4				;[25]+3
	ORA	g_CharSetPF2Hi+4,X	;[28]+4			Save a copy of PF2 - Left - Line 6 in A
	
	STY	PF0					;[32]+3	= 35	PF0	- Right - Line 5; We saved a copy in Y from last scanline.
	
	LDX	b_Char6				;[35]+3			Load copy of PF1 - Right - Line 5
	STX	PF1					;[38]+3 = 41 	PF1 - Right - Line 5
	
	DEC b_Lum				;[41]+5
	
	LDX	b_Char8				;[46]+3			Load copy of PF2 - Right - Line 4
	STX	PF2					;[49]+3 = 52	PF2 - Right - Line 5
	
	LDX	b_Char0				;[52]+3
	LDY	g_CharSetPF2Hi+4,X	;[55]+4
	STY	PF0					;[59]+2 = 61    PF0 - Left - Line 6
	
	LDY	b_GraphicBuf0		;[61]+3
	STY	PF1					;[64]+3	= 67	PF1 - Left - Line 6
	
	LDX b_Char5				;[67]+3
	LDY	g_CharSetPF2Hi+4,X	;[70]+4			Save a copy of PF0 - Right - Line 6 in Y
	
	STA	PF2					;[74]+3 = 1		PF2 - Left - Line 6
	
	LDA	b_Lum				;[1]+3		
	AND	#$0F				;[4]+2		
	ORA	b_TextColor			;[6]+3
	STA	COLUPF				;[9]+3			Text color line 6
	
	LDX	b_Char7				;[12]+3			Load a copy of PF1 - Right - Line 6
	LDA	b_Char9				;[15]+3			Load a copy of PF2 - Right - Line 6
	
	NOP						;[18]+2			;We will exploit this free time when we 
	NOP						;[20]+2			;get a better understanding of ideal
	NOP						;[22]+2			; exit conditions from this routine.
	NOP						;[24]+2
	NOP						;[26]+2
	NOP						;[28]+2
	NOP						;[30]+2
	NOP						;[32]+2
	NOP						;[34]+2
	NOP						;[36]+2
	NOP						;[38]+2
	NOP						;[40]+2
	
	STY PF0					;[42]+3 = 45	PF0 - Right - Line 6
	STX	PF1					;[45]+3 = 48	PF1 - Right - Line 6
	STA	PF2					;[48]+3 = 51	PF2 - Right - Line 6
	
	LDA	#$00				;[51]+2	= 53	
	STA	PF0					;[53]+3 = 56	PF0 - Clear
	
	NOP						;[56]+2			;More free cycles to exploit latter if we can.
	NOP						;[58]+2
	NOP						;[60]+2
	NOP						;[62]+2
	NOP						;[64]+2
	NOP						;[66]+2
	NOP						;[68]+2
	
	STA	PF1					;[70]+3 = 73	PF1 Clear
	STA	PF2					;[73]+3 = 76	PF2 Clear
	RTS						;[0]+6			Return from subroutine 6 cycles in to next scanline
	
; [end] S_DrawText
;**********************************************************************	



DrawGameScreen
DGSVector = DrawGameScreen - 1
;**************************************************************
;Assumptions:
;1. The sprites missles and balls are all positioned horizontally during vertical blank.
;2. The ball and missles are disabled.
;3. Sprite facing and colors are set during vertical blanking.
;4. X holds the address of the BallEnable register for use in the Stack trick
;5. Y holds the current scanline of the visible arena 0 through 127, 0 is at the top.
;
;Variables:
;b_P0scrY 		-> Line on which P0 begins display minus 1
;b_M0scrY		-> y-pos of Missle 0 graphic
;b_P1scrY		-> Line on which P1 begins display minus 1 
;b_M1scrY		-> y-pos of Missle 1 graphic
;b_BallscrY	-> y-pos of Ball graphic
;w_PF1ptr	-> pointer to graphic data for PF1, indirect indexed by line count in Y.
;w_PF2ptr	-> pointer to graphic data for PF2, indirect indexed by line count in Y.
;b_Zero		-> This zeropage location always holds $00.  We use it to waste cycles in the kernal.
;
;Constants:
;g_PF0data	-> Table of graphics data for PF0 during the main ArenaDrawKernal.

ArenaVerticalBlank

;	This code will set garbage into the display variables just to test the code.
;b_Mode	= $90	; The current game state. ($00 = Title)
;b_Count	= $91   ; Absolute 8-bit frame count.
;b_Randm = $92   ; Pseudo Random numer = (b_Count * 7 + b_Count + Carry) MOD 256
;b_Lum   = $93   ; Base luminance for color shifting effects, reset from b_Count each frame.

;--- The following locations store the actual X and Y locations of the visible graphic objects
; on the screen.
; The on screen position of the graphics is a translation of the virtual position of the objects. 
;b_P0scrX	= $94
;b_P0scrY	= $95	; Line on which P0 begins display minus 1
;b_P1scrX	= $96
;b_P1scrY	= $97	; Line on which P1 begins display minus 1 
;b_M0scrX	= $98
;b_M0scrY	= $99 	; y-pos of Missle 0 graphic
;b_M1scrX	= $9A
;b_M1scrY	= $9B	; y-pos of Missle 1 graphic
;b_BallscrX	= $9C
;b_BallscrY	= $9D	; y-pos of Ball graphic

;w_PF1ptr	= $9E	; pointer to graphic data for PF1, indirect indexed by line count in Y.
;w_PF2ptr	= $A0	; pointer to graphic data for PF2, indirect indexed by line count in Y.
;w_P0ptr		= $A2	; pointer to p0 sprite graphics
;w_P1ptr		= $A4	; pointer to p1 sprite graphics
;b_Zero		= $A6	; This zeropage location always holds $00.  We use it to waste cycles in the kernal.
;b_PFColor   = $A7	; The color of the arena walls.

	LDA	b_Count
	AND	#%00011111
	LSR				; Yields Wall position from 0 - 15.
	TAY
	
	LDA	b_Count			; There are 8 phases of areana wall movement.
	BMI	PFphases4_7
	;else PFphases0_3
	ASL
	ASL
	BCS	PFphases2_3
	;else PFphases0_1
	BPL	PFphase0
	BMI	PFphase1
PFphases2_3
	BPL	PFphase2
	BMI	PFphase3
PFphases4_7
	ASL
	ASL
	BCS	PFphases6_7
	;else PFphases4_5
	BPL	PFphase4
	BMI	PFphase5
PFphases6_7
	BPL	PFphase6
	BMI	PFphase7
	
PFphase0	; Both sections up.
	LDX	b_PF1baseY
	LDA	b_PF2baseY
	JMP EndPFPhasing
PFphase1	; PF1 moving Down
	TYA	
	CLC
	ADC	b_PF1baseY
	TAX
	LDA	b_PF2baseY
	JMP	EndPFPhasing
PFphase2	; PF1 Down, PF2 UP
	CLC
	LDA	b_PF1baseY
	ADC #16
	TAX
	LDA b_PF2baseY
	JMP EndPFPhasing
PFphase3	; PF1 Down, PF2 moving Down
	CLC
	LDA	b_PF1baseY
	ADC #16
	TAX
	TYA
	ADC	b_PF2baseY
	JMP EndPFPhasing
PFphase4	; Both Sections down
	CLC
	LDA b_PF1baseY
	ADC #16
	TAX
	LDA b_PF2baseY
	ADC #16
	JMP EndPFPhasing
PFphase5	; PF1 moving up, PF2 dowm
	CLC
	TYA
	EOR	#$0F
	ADC	b_PF1baseY
	TAX
	LDA b_PF2baseY
	ADC #16
	JMP EndPFPhasing
PFphase6	; PF1 UP, PF2 Down
	LDX b_PF1baseY
	CLC
	LDA b_PF2baseY
	ADC	#16
	JMP EndPFPhasing
PFphase7	; PF1 UP, PF2 Moving Up
	LDX	b_PF1baseY
	CLC
	TYA
	EOR	#$0F
	ADC	b_PF2baseY
	;fall through

EndPFPhasing
	STX w_PF1ptr
	STA w_PF2ptr

B30	LDA INTIM		;Wait for the end of vertical blank.
	BNE B30
	STA VBLANK		;A=0, so use it to clear vertical blank.



DrawArenaTopFrame
	STA	WSYNC					; Synchronize to end of vertical blank.
	
	
	
	LDA	#%00000101	;[0]+2		; Set Playfield to Reflection Mode with Playfield priority over sprites.
	STA	CTRLPF		;[2]+3		; Also set the Ball width to 1.
	
	LDA	b_PFColor	;[5]+3
	AND	#$F0		;[8]+2
	STA	COLUPF		;[10]+3		
	
	LDY	#$FF		;[13]+2		; Initialize the linecounter, for main arena draw.
	STY	PF0			;[15]+3		; Draw the top of the Arena.
	STY	PF1			;[18]+3
	STY	PF2			;[21]+3
	
	LDX	#$0F
	
B31	STA	WSYNC
	CLC
	ADC	#$01
	STA	COLUPF
	DEX
	BNE	B31
	
	
	STA	CXCLR		;[16]+3		; Clear all collision registers.

	STA	WSYNC
	
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	BIT	b_Zero
	
	;--- There are 4 entry points into the main DrawArena kernel.  The entry point used
	;--- depends on whether P0 or P1 need to be drawn as part of the first line.
	;--- The DrawArena Kernal does not use WSYNC at any point.  Synchronization is maintained
	;--- by consuming exactly 76 cycles every time through the kernal loop.  The 4 kernal entry
	;--- points all are at cycle 35 in the 76 cycle loop.   So in the tests below we are sure to
	;--- jump to the right entry point on cycle 32 to arrive on cycle 35.
	
	
	CPY	b_P0scrY		;[15]+3		; Test to see if P0 needs to be drawn at the top line of the arena display.
	BEQ	TopP0Yes	;[18]+2/3	; $FF = Yes
	CPY	b_P1scrY	;[20]+3
	BEQ	TopP1Yes	;[23]+2/3	; Same test for P1
	
	NOP				;[25]+2
	NOP				;[27]+2
	BIT	b_Zero		;[29]+3
	JMP	NoP0NoP1StartKernal		;[32]+3 = 35 cycles!

TopP0Yes
	CPY	b_P1scrY	;[21]+3
	BEQ	TopP0P1Yes	;[24]+2/3
	
	NOP				;[26]+2
	NOP				;[28]+2
	NOP				;[30]+2
	JMP	YesP0NoP1StartKernal	;[32]+3 = 35 cycles!
	
TopP1Yes
	NOP				;[26]+2
	NOP				;[28]+2
	NOP				;[30]+2
	JMP	NoP0YesP1StartKernal	;[32]+3 = 35 cycles!
	
TopP0P1Yes
	NOP				;[27]+2
	BIT	b_Zero		;[29]+3
	JMP	YesP0YesP1StartKernal	;[32]+3 = 35 cycles!

DrawArena
;***************************************************************************************
NoP0NoP1
;--- At this point X=P0 graphics data for next line, and A=P1 graphic data for next line.
    CPY b_BallscrY			;[65]+3
;------------------------- 		End of visible Arena space is cycle 71 for players, and cycle 72 for Ball and Missles.	
	STX	GRP0			;[68]+3		P0 on/off
	STA	GRP1			;[71]+3		P1 on/off
    PHP					;[74]+3		Ball on/off
    CPY b_M1scrY		;[1]+3
    PHP					;[4]+3		M1 on/off
    CPY b_M0scrY			;[7]+3		
    PHP 				;[10]+3 	M0 on/off
	
    LDA	g_PF0data,Y		;[13]+4
    STA	PF0				;[17]+3	= 20 < 23 PF0 visible.
    LDA	(w_PF1ptr),Y 	;[20]+5
    STA PF1				;[25]+3 = 28 => 28 PF1 visible!!!!!
    LDA (w_PF2ptr),Y 	;[28]+5		
    STA	PF2				;[33]+3 = 36 < 39 PF2 visible! cycles to render arena

;------ (65 - 36) = 29 cycles to do remaining work for each line.

NoP0NoP1StartKernal

	LDX	#ENABL			;[36]+2		; Set the stack pointer to point at the ENABL register
	TXS					;[38]+2 	; So we can use the status register push trick from "Combat".

	INY					;[40]+2		; Increment line counter in Y
	BMI	ExitArena		;[42]+2/3	; When the line count reaches 128 we are done.
	
;------- At this point the code varies depending on whether the sprites are being drawn or not.
;------- We have (65 - 44) = 21 cycles left.  We must spend exactly 21 cycles to remain in sync.

	LDX	#00				;[44]+2		; Load $00 into A and X because both sprites are off.
	LDA #00				;[46]+2
	CPY	b_P0scrY		;[48]+3		; Check if P0 is on next line?
	BEQ	P0Yes			;[51]+2/3
	CPY	b_P1scrY		;[53]+3
	BEQ	P1Yes			;[56]+2/3
	NOP					;[58]+2
	NOP					;[60]+2
	JMP	NoP0NoP1		;[62]+3	= 65 cycles spent!	
P0Yes				
	CPY b_P1scrY		;[54]+3
	BEQ P0andP1Yes		;[57]+2/3
	BIT b_Zero			;[59]+3		; Just wasting 3 cycles.
	JMP	YesP0NoP1		;[62]+3 = 65 cycles spent
P1Yes
	BIT b_Zero			;[59]+3
	JMP	NoP0YesP1		;[62]+3 = 65 cycles spent
P0andP1Yes
	NOP					;[60]+2
	JMP	YesP0YesP1		;[62]+3 = 65 cycles spent.
;***************************************************************************************

;***************************************************************************************
YesP0NoP1
;--- At this point X=P0 graphics data for next line, and A=P1 graphic data for next line.
    CPY b_BallscrY			;[65]+3
;------------------------- 		End of visible Arena space is cycle 71 for players, and cycle 72 for Ball and Missles.	
	STX	GRP0			;[68]+3		P0 on/off
	STA	GRP1			;[71]+3		P1 on/off
    PHP					;[74]+3		Ball on/off
    CPY b_M1scrY		;[1]+3
    PHP					;[4]+3		M1 on/off
    CPY b_M0scrY			;[7]+3		
    PHP 				;[10]+3 	M0 on/off
	
    LDA	g_PF0data,Y		;[13]+4
    STA	PF0				;[17]+3	= 20 < 23 PF0 visible.
    LDA	(w_PF1ptr),Y 	;[20]+5
    STA PF1				;[25]+3 = 28 => 28 PF1 visible!!!!!
    LDA (w_PF2ptr),Y 	;[28]+5		
    STA	PF2				;[33]+3 = 36 < 39 PF2 visible! cycles to render arena

;------ (65 - 36) = 29 cycles to do remaining work for each line.

YesP0NoP1StartKernal

	LDX	#ENABL			;[36]+2		; Set the stack pointer to point at the ENABL register
	TXS					;[38]+2 	; So we can use the status register push trick from "Combat".

	INY					;[40]+2		; Increment line counter in Y
	BMI	ExitArena		;[42]+2/3	; When the line count reaches 128 we are done.
	
;------- At this point the code varies depending on whether the sprites are being drawn or not.
;------- We have (65 - 44) = 21 cycles left.  We must spend exactly 21 cycles to remain in sync.

	LDA	(w_P0ptr),Y		;[44]+5		;Load Graphic Data for P0
	TAX					;[49]+2
	BEQ	P0No			;[51]+2/3	;If the graphic data is $00, then we have reached the end of P0
	CPY	b_P1scrY		;[53]+3
	BEQ	P1Yes3			;[56]+2/3
	LDA	#00				;[58]+2		;Load graphic data for P1
	NOP					;[60]+2
	JMP	YesP0NoP1		;[62]+3	= 65 cycles spent!	
P0No
						; P1 is off, we know A is 0 from the BEQ that brought us here so no need to load 0
						; so there is no need to load 0 into A for the P1 graphics.s
	CPY b_P1scrY		;[54]+3		; Check if P1 is on next line.
	BEQ P1Yes2			;[57]+2/3
	BIT b_Zero			;[59]+3
	JMP	NoP0NoP1		;[62]+3 = 65 cycles spent
P1Yes3
	LDA b_Zero			;[59]+3		; Load 0 into A for P1 graphics.
	JMP	YesP0YesP1		;[62]+3 = 65 cycles spent
P1Yes2
	LDA	#00				;[60]+2		; Load 0 into A for P1 graphics.
	JMP	NoP0YesP1		;[62]+3 = 65 cycles spent.  Fall through to NoP0YesP1
;***************************************************************************************	

ExitArena
	JMP	DrawBottomArenaFrame	;[45] + 3 = 48 

;***************************************************************************************
NoP0YesP1
;--- At this point X=P0 graphics data for next line, and A=P1 graphic data for next line.
    CPY b_BallscrY			;[65]+3
;------------------------- 		End of visible Arena space is cycle 71 for players, and cycle 72 for Ball and Missles.	
	STX	GRP0			;[68]+3		P0 on/off
	STA	GRP1			;[71]+3		P1 on/off
    PHP					;[74]+3		Ball on/off
    CPY b_M1scrY		;[1]+3
    PHP					;[4]+3		M1 on/off
    CPY b_M0scrY			;[7]+3		
    PHP 				;[10]+3 	M0 on/off
	
    LDA	g_PF0data,Y		;[13]+4
    STA	PF0				;[17]+3	= 20 < 23 PF0 visible.
    LDA	(w_PF1ptr),Y 	;[20]+5
    STA PF1				;[25]+3 = 28 => 28 PF1 visible!!!!!
    LDA (w_PF2ptr),Y 	;[28]+5		
    STA	PF2				;[33]+3 = 36 < 39 PF2 visible! cycles to render arena

;------ (65 - 36) = 29 cycles to do remaining work for each line.

NoP0YesP1StartKernal

	LDX	#ENABL			;[36]+2		; Set the stack pointer to point at the ENABL register
	TXS					;[38]+2 	; So we can use the status register push trick from "Combat".

	INY					;[40]+2		; Increment line counter in Y
	BMI	ExitArena		;[42]+2/3	; When the line count reaches 128 we are done.
	
;------- At this point the code varies depending on whether the sprites are being drawn or not.
;------- We have (65 - 44) = 21 cycles left.  We must spend exactly 21 cycles to remain in sync.

	LDX	#00				;[44]+2		;Load 0 for P0 Graphic Data
	LDA	(w_P1ptr),Y		;[46]+5		;Load Graphic Data for P1
	BEQ	P1No			;[51]+2/3	;If the graphic data is $00, then we have reached the end of P0
	CPY	b_P0scrY			;[53]+3
	BEQ	P0Yes3			;[56]+2/3
	NOP					;[58]+2	
	NOP					;[60]+2
	JMP	NoP0YesP1		;[62]+3	= 65 cycles spent!	
P1No					
	CPY b_P0scrY		;[54]+3		; Check if P1 is on next line.
	BEQ P0Yes2			;[57]+2/3
	BIT b_Zero			;[59]+3		; Waste 3 cycles
	JMP	NoP0NoP1		;[62]+3 = 65 cycles spent
P0Yes3
	BIT b_Zero			;[59]+3		; Waste 3 cycles
	JMP	YesP0YesP1		;[62]+3 = 65 cycles spent
P0Yes2
	NOP					;[60]+2	
	JMP	YesP0NoP1		;[62]+3 = 65 cycles spent.  Fall through to NoP0YesP1
;***************************************************************************************	


;***************************************************************************************
P0P1Yes4
	NOP					;[61]+2
	NOP					;[63]+2 = 65 cycles spent

YesP0YesP1
;--- At this point X=P0 graphics data for next line, and A=P1 graphic data for next line.
    CPY b_BallscrY			;[65]+3
;------------------------- 		End of visible Arena space is cycle 71 for players, and cycle 72 for Ball and Missles.	
	STX	GRP0			;[68]+3		P0 on/off
	STA	GRP1			;[71]+3		P1 on/off
    PHP					;[74]+3		Ball on/off
    CPY b_M1scrY		;[1]+3
    PHP					;[4]+3		M1 on/off
    CPY b_M0scrY			;[7]+3		
    PHP 				;[10]+3 	M0 on/off
	
    LDA	g_PF0data,Y		;[13]+4
    STA	PF0				;[17]+3	= 20 < 23 PF0 visible.
    LDA	(w_PF1ptr),Y	;[20]+5
    STA PF1				;[25]+3 = 28 => 28 PF1 visible!!!!!
    LDA (w_PF2ptr),Y	;[28]+5		
    STA	PF2				;[33]+3 = 36 < 39 PF2 visible! cycles to render arena

;------ (65 - 36) = 29 cycles to do remaining work for each line.

YesP0YesP1StartKernal

	LDX	#ENABL			;[36]+2		; Set the stack pointer to point at the ENABL register
	TXS					;[38]+2 	; So we can use the status register push trick from "Combat".

	INY					;[40]+2		; Increment line counter in Y
	BMI	ExitArena		;[42]+2/3	; When the line count reaches 128 we are done.
	
;------- At this point the code varies depending on whether the sprites are being drawn or not.
;------- We have (65 - 44) = 21 cycles left.  We must spend exactly 21 cycles to remain in sync.

;Need to invert tests in order to get the right number of cycles to stay in sync.

	LDA	(w_P0ptr),Y		;[44]+5
	BEQ	P0No11			;[49]+2/3
	TAX					;[51]+2
	LDA	(w_P1ptr),Y		;[53]+5
	BNE	P0P1Yes4		;[58]+2/3
	NOP					;[60]+2
	JMP	YesP0NoP1		;[62]+3 = 65 cycles spent

P0No11
	LDA (w_P1ptr),Y		;[52]+5 
	BEQ	P0P1No2			;[57]+2/3
	LDX	b_Zero			;[59]+3
	JMP	NoP0YesP1		;[62]+3 = 65 cycles spent
	
P0P1No2
	LDX #00				;[60]+2
	JMP NoP0NoP1		;[62]+3 = 65 cycles spent
	
;**************************************************************	

DrawBottomArenaFrame
; We always arrive at this point on cycle 48 of the last scanline of the arena.  The stack pointer
; is pointing at the ENABL register so we can use PHA instructions to turn off the ball and missles.

	LDX	#$FF			;[48]+2
	LDA	#$00			;[50]+2
	
	STA	WSYNC			;Wait for end of last arena line to be drawn before turning things off.
	
	STA	GRP0			;[0]+3		P0 off
	STA	GRP1			;[3]+3		P1 off
	PHA					;[6]+3		Ball off
	PHA					;[9]+3		M1 off
	PHA					;[12]+3		M2 off
	
	STX	PF0				;[15]+3		PF0 solid wall
	STX	PF1				;[18]+3		PF1 solid wall
	STX	PF2				;[21]+3		PF2 solid wall
	
	TXS					;[24]+2		Reset SP to top of stack space.
	
	LDA	b_PFColor
	ORA	#$0F
	
	LDX	#15
B32	STA	WSYNC
	SEC	
	SBC #01
	STA	COLUPF
	DEX
	BNE B32
	
	LDA	#00
	STA	WSYNC
	
	STA	PF0
	STA	PF1
	STA	PF2
	
;	At this point we have drawn 160 scanlines.  So 192 - 130 = 32 scanlines remaining.
	
	LDY	#3
B20	STA	WSYNC		
	DEY	
	BNE	B20
	
	LDA	#$00
	STA CTRLPF
	
	LDX	#9	
B46	LDA	S___Coming__,X
	STA	a_StringBuf,X
	DEX
	BPL	B46
	LDA	#$C8
	STA	b_TextColor
	JSR	S_DrawText
	
	LDX	#9	
B47	LDA	S__Aug_2003_,X
	STA	a_StringBuf,X
	DEX
	BPL	B47
	LDA	#$C8
	STA	b_TextColor
	JSR	S_DrawText	
	
	LDA #%00000101
	STA CTRLPF

	LDY	#3
B50	STA	WSYNC		
	DEY	
	BNE	B50
	
	LDA	#$02
	STA	VBLANK
	
; Overscan:
	LDY #30 		; Count 30 lines of overscan.  Later
					; We will check the Joysticks and console switches
					; and collisions during overscan.
B21	STA WSYNC		; Sync to the end  of the last visible line, and all
					; overscan lines except the last one.
	DEY
	BNE B21
	
	;With the Game Screen frame complete we jump to the VerticalSync routine.
	JMP VerticalSync
	
S_InitGameScreenMode
;**************************************************************
; This Routine sets up the TIA and necessary variables for 
; display of the Game Screen.
; [Begin]

	LDA	b_PFColor
	ADC #16
	STA	b_PFColor
		
	LDX #36 ; We will copy 1 bank of 37 values into TIA registers.
B25	LDA GameTIA_1,X
	STA NUSIZ0,X
	DEX
	BPL B25
	
;----------- Start Demo Setup code

	LDA	#>g_ArenaWalls	; Set pointers for PF1 and PF2 graphics.
	STA	w_PF1ptr+1
	STA	w_PF2ptr+1
	LDA	b_PF1baseY
	ADC	#48
	AND	#%01110000
	STA	b_PF1baseY
	LDA	b_PF2baseY
	SBC #80
	AND	#%01110000
	STA	b_PF2baseY
	
	LDA	#129			; Disable display of P0, P1, M0, M1, and Ball
	STA	b_P0scrY
	STA	b_P1scrY
	STA	b_M0scrY
	STA	b_M1scrY
	STA	b_BallscrY
	
	
;------------- End Demo Setup Code	
	
	RTS

GameTIA_1
	.byte $00, $00, $1C, $BD, $00, $02, $05, $00
	.byte $08, $00, $00, $00, $00, $00, $00, $00,
	.byte $00, $00, $00, $00, $00, $00, $00, $00, 
	.byte $00, $02, $02, $02, $00, $00, $00, $00,
	.byte $00, $00, $00, $00, $00

; [end] InitTextScreenMode
;****************************************************************
	
;**************************************************************
	org	$FA00
	include Graphics.h
	
;**************************************************************

	org $FD00   ; Character Set Graphic Data Tables 512 bytes.
	
	include Generic_Char_Set.h

	
	org $FF00	; We must ensure that the main title graphics do not
				; cross a page boundary.
				
; Main Title Graphics.
; They are stored in Reverse order to faciltate counting down.
; The playfield will be reflected PF0 is left at $00 throughout the 
; rendering of the Title.
TitleColumn1 ;= PF1 7-0
	.byte	$00,$00,$00,$00,$00,$00,$00,$00,$00,$3D,$25,$25,$25,$2D,$20,$3F
TitleColumn2 ;= PF2 0-7
	.byte	$00,$EE,$AA,$EA,$8A,$EE,$02,$03,$00,$B8,$A8,$B8,$A2,$BB,$00,$FF
TitleColumn3 ;= PF2 7-0
	.byte	$00,$A0,$A0,$A0,$A0,$A0,$A0,$A0,$00,$90,$A0,$A0,$A0,$A0,$00,$80
TitleColumn4 ;= PF1 0-7
	.byte	$00,$00,$00,$00,$00,$00,$00,$3F,$01,$37,$25,$25,$25,$75,$20,$00
	
;Sample Strings
S_RPM_Games
	.byte	C_Letter_R
	.byte	C_Letter_P
	.byte	C_Letter_M
	.byte	C_Symbol_Hyphen
	.byte	C_Letter_G
	.byte	C_Letter_A
	.byte	C_Letter_M
	.byte	C_Letter_E
	.byte	C_Letter_S
	.byte	C_Symbol_Exclamation

S___Coming__
	.byte	C_Symbol_Space
	.byte	C_Symbol_Space
	.byte	C_Letter_C
	.byte	C_Letter_O
	.byte	C_Letter_M
	.byte	C_Letter_I
	.byte	C_Letter_N
	.byte	C_Letter_G
	.byte	C_Symbol_Space
	.byte	C_Symbol_Space
	
S__Aug_2003_
	.byte	C_Symbol_Space
	.byte	C_Letter_A
	.byte	C_Letter_U
	.byte	C_Letter_G
	.byte	C_Symbol_Space
	.byte	C_Digit_2
	.byte	C_Digit_0
	.byte	C_Digit_0
	.byte	C_Digit_3
	.byte	C_Symbol_Space

;**************************************************************
; We must set the vector to our PowerUp routine.
	org $FFFC
ResetVector
	.word Powerup
	.word Powerup
	
;---------------------------------------------------------------
; END OF LISTING
;---------------------------------------------------------------
Current Thread