[SOLVED!] [Help Request] Homebrew Title Screen Code

Discuss technical or other issues relating to programming the Nintendo Entertainment System, Famicom, or compatible systems.

Moderator: Moderators

User avatar
eskayelle
Posts: 22
Joined: Wed Jul 29, 2020 5:07 pm
Contact:

[SOLVED!] [Help Request] Homebrew Title Screen Code

Post by eskayelle » Wed Jul 29, 2020 6:26 pm

Evening! I'm a romhacker trying to get a better understanding of 6502 and 658c16 coding, so I'm currently running through the old Nerdy Nights lessons. I have a partially complete game, the game's code being separated into one .asm doc for the game and one for the title screen (I did this because I'm working through the background lessons and still getting a feel for the attribute tables. Both .asm files, when compiled, will work in an NES emulator, one complied rom just displaying the intended background and the other providing a rudimentary Pong game.)

I'm having some difficulty figuring out how to merge the title screen code into the main game and am looking for some guidance.

Please note: The code is definitely not optimized, as I'm still working through the lessons, and my main goal is to get a "completed" game before going back and trying to better understand the optimizations that can be done. In that regard, right now I'm just trying to figure out how to merge in the background game code such that the game will properly play (i.e., first show the title screen, then move on to the gameplay screen, background, and sprites upon pressing Start).

Here is a link to the merged/broken code. I can also provide the two non merged/working files if anyone can help with my merging issue.

Thanks for reading!
Last edited by eskayelle on Sat Aug 01, 2020 10:22 am, edited 1 time in total.

User avatar
Controllerhead
Posts: 147
Joined: Tue Nov 13, 2018 4:58 am
Location: $4016
Contact:

Re: [Help Request] Homebrew Title Screen Code

Post by Controllerhead » Wed Jul 29, 2020 8:31 pm

Hey man! Congrats on starting your journey.

I took a look and didn't fix everything, but you were RTS'ing into the great beyond on line 216 from xxx:, so the JMP xxx on line 1238 should be a JSR xxx. Otherwise, it looks like you're trying to load your entire title screen on every frame after that in NMI at line 1217 with your gamestate, which takes until about scanline 140 or so, which is why you are (probably) seeing the garbly gook on the top half of the screen every frame.

It seems like your gamestate variable needs a "load the title screen graphics" state and a "wait for input on the title screen" state. Ideally, you should do something like load the title screen graphics with the PPU off, adjust your gamestate variable, turn the PPU on and goto a "wait for input on the title screen" gamestate.

Hope this helps!

PS: It would be helpful to include the CHR file
Image

User avatar
tokumaru
Posts: 11858
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Re: [Help Request] Homebrew Title Screen Code

Post by tokumaru » Wed Jul 29, 2020 10:32 pm

A simple way to handle multiple "modes" in a program is to code each one with three clearly distinct parts:

- Initialization: This is where you initialize everything a given program modes in order to work: you should initialize variables, reset the input, prepare name/attribute/pattern tables, and so on. Be careful to not let your vblank handler interfere with the tasks being done here - either disable NMIs entirely or use a flag to let the vblank handler know that it's not supposed to touch the PPU (the second option is better because you don't have to give up on other timely tasks, such as playing music). Once everything is ready, just roll right into the main loop.

- Main loop: The main loop is the "active" part of each program mode. This is where you read the controllers, process the inputs, update the game state, and schedule graphical updates to be carried out during vblank. You should wait for a vblank to happen between iterations of this loop, so that the game logic runs at a constant pace.

- Destruction: This doesn't necessarily have to be an independent part, it can actually be implemented inside the main loop, but it still exists, conceptually. Either way, this is where you clean up everything necessary to provide the next mode with a known state to work with. You may want to guarantee that rendering is off, as well as vblank updates. Once you're done, you can JMP right into the initialization step of the next program mode.

Each mode can have a simple structure like this:

Code: Select all

InitializeTitleScreen:
	;(prepare everything for the title screen)
UpdateTitleScreen:
	;(process everything the title screen needs in order to work)
	;(if an end condition is found, update InitializeGameMode and JMP to DestroyTitleScreen)
	;(enable vblank updates)
	;(wait for vblank)
	jmp UpdateTitleScreen
DestroyTitleScreen:
	;(put the system in a known state)
	;(disable vblank updates)
	jmp (InitializeGameMode)
This particular structure may not be possible if you're using the "everything in the NMI handler" taught in some tutorials. In that case, you can JSR to the initialization routines of each mode in order to switch to them, and instead of rolling into the main loop, you write the address of the main loop to a variable that the NMI handler indirectly calls every frame (e.g. jmp (UpdateGameMode)).

User avatar
eskayelle
Posts: 22
Joined: Wed Jul 29, 2020 5:07 pm
Contact:

Re: [Help Request] Homebrew Title Screen Code

Post by eskayelle » Thu Jul 30, 2020 9:52 am

Thanks to both of you for the responses! My hope is to work through them step by step if I can, so I can better understand the concepts being provided.
you were RTS'ing into the great beyond on line 216 from xxx:, so the JMP xxx on line 1238 should be a JSR xxx.
Whoops - done! I'll replace that JMP with a JSR, I presume because the distance between the code sections wouldn't have supported the JMP.
Otherwise, it looks like you're trying to load your entire title screen on every frame after that in NMI at line 1217 with your gamestate, which takes until about scanline 140 or so, which is why you are (probably) seeing the garbly gook on the top half of the screen every frame.
Admittedly, I don't know that this is my intent, as I'm likely putting my code in the wrong section and don't yet know why it's wrong. Is there a section of code I should relocate (The EngineTitle label?), and if so, where (in the Subroutines section, with a proper RTS at the end? and should it include all the LatchController stuff I had tacked on?)
It seems like your gamestate variable needs a "load the title screen graphics" state and a "wait for input on the title screen" state. Ideally, you should do something like load the title screen graphics with the PPU off, adjust your gamestate variable, turn the PPU on and goto a "wait for input on the title screen" gamestate.
Admittedly, I thought I was doing a screen off/on deal with this code.

Code: Select all

xxx:
  LDA #%00000000        ;Turn the screen off
  STA $2000
  STA $2001
;  JSR LoadNametable     ;Load the new Nametable, Attribute, and Palette
;  JSR LoadAttribute
;  JSR LoadPalette
;  JSR LoadSprites
  LDA #%10001000        ;Turn the screen on
  STA $2000
Not knowing my subroutine structures yet, I had put all the palette, sprites, and background commands just under this. Is there something in particular I can/should relocate to correct for this?

I also thought all the LatchController code was the "wait for input on the title screen" function, so I think I need some guidance as to what I've missed there. Do I have all the commands and the order is wrong, am I missing some command, or is it a bit of both AND I should be either inside of NMI or not? I'm more or less getting stuck here because - to some degree - my original separate files work, so I'm not sure how to compensate when merging the two together.
It would be helpful to include the CHR file
Sorry about that! Oversight on my part. For reference, I'm attaching that, plus the two .asm files that, when compiled (and when the two resulting .nes roms played separately), each rom runs "properly".
you can JSR to the initialization routines of each mode in order to switch to them, and instead of rolling into the main loop, you write the address of the main loop to a variable that the NMI handler indirectly calls every frame (e.g. jmp (UpdateGameMode)).
Using my bad code, is there a way to example this out a bit? I'm struggling a little to figure out how I'd accomplish this.

Thanks for any additional tips you can provide! I had hoped some sort of .incbin or .include or .import function moving the titlescreen code to the main code during the assembly process would be an easy enough approach, but my attempts there haven't worked either.

User avatar
Controllerhead
Posts: 147
Joined: Tue Nov 13, 2018 4:58 am
Location: $4016
Contact:

Re: [Help Request] Homebrew Title Screen Code

Post by Controllerhead » Thu Jul 30, 2020 10:39 am

Ok man. More or less, you can't just "merge" these two files together and have them work.

It seems like you're basically trying to run both of them at the same time. You're gonna need more code to determine what screen you are on and which inputs to process to do what. Multiple screens require a structure in place to handle them.

I would start again with your titlescreen file, and on button press, unload the titlescreen graphics from the nametable and load the playfield. After that, start reintroducing your pong code. Work piece by piece and make proper gamestates to accomplish what you want. Using a step through debugger is very helpful, if you aren't already using one.

I hope that makes sense. Good luck!
Image

User avatar
eskayelle
Posts: 22
Joined: Wed Jul 29, 2020 5:07 pm
Contact:

Re: [Help Request] Homebrew Title Screen Code

Post by eskayelle » Thu Jul 30, 2020 12:43 pm

Got it. To use that title screen code as my base (instead of my main game code), I think I need to get a better handle on some code optimization and getting portions outside of NMI/the main engine and into subroutines. Would you mind if I pick your brain with some examples to see how I might grasp some of this?

Example: The controllers. With no optimization, I have to do all this:

Code: Select all

ReadA1: 
  LDA $4016      	 ; player 1 - A
  AND #%00000001 	 ; only look at bit 0
  BEQ ReadA1Done 	 ; branch to ReadA1Done if button is NOT pressed (0)
  				 ; add some instructions, depending on if a button is to be used
ReadA1Done:      	 ; handling this button is done

ReadB1: 
  LDA $4016    		 ; player 1 - B
  AND #%00000001  	 ; only look at bit 0
  BEQ ReadB1Done   	 ; branch to ReadB1Done if button is NOT pressed (0)
ReadB1Done:      	 ; handling this button is done 

ReadSelect1: 
  LDA $4016      	 ; player 1 - Select
  AND #%00000001  	 ; only look at bit 0
  BEQ ReadSelect1Done  	 ; branch to ReadSelect1Done if button is NOT pressed (0)
ReadSelect1Done:         ; handling this button is done

ReadStart1: 
  LDA $4016   	         ; player 1 - Start
  AND #%00000001 	 ; only look at bit 0
  BEQ ReadStart1Done  	 ; branch to ReadStart1Done if button is NOT pressed (0)
ReadStart1Done: 	 ; handling this button is done

ReadUp1: 
  LDA $4016       	 ; player 1 - Up
  AND #%00000001  	 ; only look at bit 0
  BEQ ReadUp1Done   	 ; branch to ReadUp1Done if button is NOT pressed (0)
ReadUp1Done:         	 ; handling this button is done

ReadDown1: 
  LDA $4016       	; player 1 - Down
  AND #%00000001  	; only look at bit 0
  BEQ ReadDown1Done     ; branch to ReadDownDone if button is NOT pressed (0)
ReadDown1Done: 	        ; handling this button is done

ReadLeft1: 
  LDA $4016       	; player 1 - Left
  AND #%00000001  	; only look at bit 0
  BEQ ReadLeft1Done     ; branch to ReadLeft1Done if button is NOT pressed (0)
ReadLeft1Done:        	; handling this button is done

ReadRight1: 
  LDA $4016        	 ; player 1 - Right
  AND #%00000001 	 ; only look at bit 0
  BEQ ReadRight1Done     ; branch to ReadRight1Done if button is NOT pressed (0)
ReadRight1Done:          ; handling this button is done
I know that one optimization method is this:

Code: Select all

;ReadController1:
;  LDA #$01
;  STA $4016
;  LDA #$00
;  STA $4016
;  LDX #$08
;ReadController1Loop:
;  LDA $4016
;  LSR A           ; bit0 -> Carry
;  ROL buttons     ; bit0 <- Carry
;  DEX
;  BNE ReadController1Loop
;  RTS
What I'm struggling with is...
1) In the optimized code, I'm not sure what I'm supposed to write to reflect what to do when Start is pressed, versus A, B, etc. Do I do CMPs after the BNE ReadController1Loop for each of the 8 buttons, with BEQs to have something done each time I want a response from a button press? I'm basically not sure what is written beyond the optimized code.

Like...?

Code: Select all

;(Inside the ReadController1Loop?)
CMP #%00000001
BEQ right_button_subroutine
CMP #%00000010
BEQ left_button_subroutine
CMP #%00000100
BEQ down_button_subroutine
CMP #%00001000
BEQ up_button_subroutine
CMP #%00010000
BEQ start_button_subroutine
CMP #%00100000
BEQ select_button_subroutine
CMP #%01000000
BEQ B_button_subroutine
CMP #%10000000
BEQ A_button_subroutine
2) The LatchController code stays in NMI, right?

Code: Select all

LatchController:
  LDA #$01
  STA $4016	  ; controller 1 
  STA $4017	  ; controller 2
  LDA #$00
  STA $4016       ; tell both the controllers to latch buttons
  STA $4017
 
Do I then include a JSR to the ReadController1 subroutine, and another JSR right after to a ReadController2 subroutine?

User avatar
Controllerhead
Posts: 147
Joined: Tue Nov 13, 2018 4:58 am
Location: $4016
Contact:

Re: [Help Request] Homebrew Title Screen Code

Post by Controllerhead » Thu Jul 30, 2020 1:05 pm

I think you got a handle on it mostly. The "optimized" read code looks good, i would use that. You can keep it in NMI, for now, as you probably want to check the buttons every frame, but a good rule of thumb is to process drawing / graphics first, as they should be updated in vBlank when not changing the entire screen. To check buttons with the "optimized" method, if you are ROL'ing them onto variable "buttons", it would be something like:

Code: Select all

LDA buttons
AND %00010000		;	This singles out bit 4, Which is Start. Order is A B Sel St Up Down Left Right
BEQ startNotPressed	;	If start is not pressed, skip this code block
	; Start was pressed, process hitting Start here, or call a JSR
startNotPressed:
You should separate your button loading / storing code from the processing code (which it looks like you're already doing), have a buttonsP1 and buttonsP2, and have different subroutines to process input for each screen and each player, depending on, say, your gamestate variable.
Image

User avatar
eskayelle
Posts: 22
Joined: Wed Jul 29, 2020 5:07 pm
Contact:

Re: [Help Request] Homebrew Title Screen Code

Post by eskayelle » Thu Jul 30, 2020 5:54 pm

I think I got something going fairly well in optimizing the main gameplay code.

Code: Select all


  .inesprg 1   ; 1x 16KB PRG code
  .ineschr 1   ; 1x  8KB CHR data
  .inesmap 0   ; mapper 0 = NROM, no bank swapping
  .inesmir 1   ; background mirroring
  

;==================
; DECLARE VARIABLES
;==================
  .rsset $0000       	; start variables at ram location $0000
  
gamestate     .rs 1     ; .rs 1 means reserve one byte of space 	; RAM $0000
ballx         .rs 1     ; ball horizontal position			; RAM $0001
bally         .rs 1     ; ball vertical position			; RAM $0002
ballup        .rs 1     ; 1 = ball moving up				; RAM $0003
balldown      .rs 1     ; 1 = ball moving down				; RAM $0004
ballleft      .rs 1     ; 1 = ball moving left				; RAM $0005
ballright     .rs 1     ; 1 = ball moving right				; RAM $0006
ballspeedx    .rs 1     ; ball horizontal speed per frame		; RAM $0007
ballspeedy    .rs 1     ; ball vertical speed per frame			; RAM $0008
paddle1ytop   .rs 1  	; player 1 paddle top vertical position		; RAM $0009 
paddle1ybot   .rs 1  	; player 1 paddle bottom vertical position	; RAM $000A 
paddle2ytop   .rs 1  	; player 2 paddle top vertical position		; RAM $000B 
paddle2ybot   .rs 1  	; player 2 paddle bottom vertical position	; RAM $000C 
buttons1      .rs 1     ; player 1 gamepad buttons, one bit per button	; RAM $000D 
buttons2      .rs 1     ; player 2 gamepad buttons, one bit per button	; RAM $000E 
score1        .rs 1     ; player 1 score, 0-15				; RAM $000F 
score2        .rs 1     ; player 2 score, 0-15				; RAM $0010 
paddlespeed   .rs 1  	; paddle speed depending on button pressed	; RAM $0011 ;not yet used
scoreOnes1	.rs 1	; byte for each digit in the decimal score	; RAM $0012
scoreTens1	.rs 1							; RAM $0013
scoreOnes2	.rs 1	; byte for each digit in the decimal score	; RAM $0014
scoreTens2	.rs 1							; RAM $0015
pointerLo  .rs 1   ; pointer variables are declared in RAM		; RAM $0016 ;not yet used
pointerHi  .rs 1   ; low byte first, high byte immediately after	; RAM $0017 ;not yet used

;=================
;DECLARE CONSTANTS 
;=================
TRUE		= $01
FALSE		= $00

STATE_TITLE     = $00   ; displaying title screen
STATE_PLAYING   = $01   ; move paddles/ball, check for collisions
STATE_GAMEOVER  = $02   ; displaying game over screen
  
RIGHTWALL       = $FB   ; when ball reaches one of these, do something (was $F9)
TOPWALL         = $0A   ; touches bottom of background row 2 
BOTTOMWALL      = $DD   ; touches top of background table 4 row 6
LEFTWALL        = $01	; ($01)
  
PADDLE1X        = $20   ; horizontal position for paddles, doesn't move ($20)
PADDLE2X        = $E8   ; ($E8)
PADDLE1YINIT    = $68   ; initial horizontal position for top of paddles
PADDLE2YINIT    = $68	

SPRITE_SIZE     = $16   ; 3 horizontal sprites at 8 pixels each
PADDLE_WIDTH 	= $08   ; just the paddle, not the tortugas


;=========
;=========
;BANK ZERO
;========= 
;=========   
  .bank 0
  .org $C000 

;===========
;SUBROUTINES
;===========

;------
;vBlank
;------
vblankwait:
  BIT $2002
  BPL vblankwait
  RTS		   	; return from this subroutine

;-------------------------------------
;Controller 1 Gameplay (STATE_PLAYING)
;-------------------------------------
ReadController1:
  LDA #$01
  STA $4016
  LDA #$00
  STA $4016
  LDX #$08		; 8 increments, one per button
ReadController1Loop:
  LDA $4016
  LSR A    	        ; bit0 -> Carry
  ROL buttons1   	; bit0 <- Carry
  DEX
  BNE ReadController1Loop
  LDA buttons1
  CMP #%00000001
  BEQ jumpright1
  CMP #%00000010
  BEQ jumpleft1
  CMP #%00000100
  BEQ jumpdown1
  CMP #%00001000
  BEQ jumpup1
  CMP #%00010000
  BEQ jumpstart1
  CMP #%00100000
  BEQ jumpselect1
  CMP #%01000000
  BEQ jumpB1
  CMP #%10000000
  BEQ jumpA1
  RTS			;yes!  this works!

jumpright1:
  JSR right1_button_subroutine
  RTS

jumpleft1:
  JSR left1_button_subroutine
  RTS

jumpdown1:
  JSR down1_button_subroutine
  RTS

jumpup1:
  JSR up1_button_subroutine
  RTS

jumpstart1:
  JSR start1_button_subroutine
  RTS

jumpselect1:
  JSR select1_button_subroutine
  RTS

jumpB1:
  JSR B1_button_subroutine
  RTS

jumpA1:
  JSR A1_button_subroutine
  RTS

right1_button_subroutine:
  LDA paddle1ybot	 ; load into accumulator the bottom of the paddle
  CMP #BOTTOMWALL	 ; if it's below the floor, do nothing
  BCS ReadRight1Done 
  STA paddle1ytop
  LDY #$00		 ; RAM address $02xx
moveloop1right:
  LDA $0200, y		 ; load sprite Y position
  CLC        		 ; make sure the carry flag is clear
  ADC #$04    		 ; add 4 to accumulator (2x speed)      
  STA $0200, y 		 ; save sprite Y position
  INY
  INY
  INY
  INY			 ; increase x 4 times for 4 attibute bytes per sprite
  CPY #$30		 ; 48 bytes (12 sprites at 4 bytes of attribute each) later than #$00...
  BCC moveloop1right   
  STA paddle1ybot
ReadRight1Done: 	 ; handling this button is done
  RTS

left1_button_subroutine:
  LDA paddle1ytop	 ; load into accumulator the top of the paddle
  CMP #TOPWALL+24		 ; if it's above the ceiling, do nothing
  BCC ReadLeft1Done  
  STA paddle1ybot
  LDY #$00		 ; RAM address $02xx
moveloop1left:
  LDA $0200, y		 ; load sprite X position
  SEC        		 ; make sure the carry flag is clear
  SBC #$04    		 ; add 4 to accumulator (2x speed)      
  STA $0200, y 		 ; save sprite Y position
  INY
  INY
  INY
  INY			 ; increase x 4 times for 4 attibute bytes per sprite
  CPY #$30		 ; 48 bytes (12 sprites at 4 bytes of attribute each) later than #$00...
  BCC moveloop1left   
  STA paddle1ytop
ReadLeft1Done:
  RTS

down1_button_subroutine:
  LDA paddle1ybot	 ; load into accumulator the bottom of the paddle
  CMP #BOTTOMWALL	 ; if it's below the floor, do nothing
  BCS ReadDown1Done 
  STA paddle1ytop
  LDY #$00		 ; RAM address $02xx
moveloop1down:
  LDA $0200, y		 ; load sprite Y position
  CLC        		 ; make sure the carry flag is clear
  ADC #$02    		 ; add 2 to accumulator (1x speed)     
  STA $0200, y 		 ; save sprite Y position
  INY
  INY
  INY
  INY			 ; increase x 4 times for 4 attibute bytes per sprite
  CPY #$30		 ; 48 bytes (12 sprites at 4 bytes of attribute each) later than #$00...
  BCC moveloop1down   
  STA paddle1ybot
ReadDown1Done: 	        ; handling this button is done
  RTS

up1_button_subroutine:
  LDA paddle1ytop	 ; load into accumulator the top of the paddle
  CMP #TOPWALL+24		 ; if it's above the ceiling, do nothing
  BCC ReadUp1Done  
  STA paddle1ybot
  LDY #$00		 ; RAM address $02xx
moveloop1up:
  LDA $0200, y		 ; load sprite X position
  SEC        		 ; make sure the carry flag is clear
  SBC #$02    		 ; add 2 to accumulator (1x speed)      
  STA $0200, y 		 ; save sprite Y position
  INY
  INY
  INY
  INY			 ; increase x 4 times for 4 attibute bytes per sprite
  CPY #$30		 ; 48 bytes (12 sprites at 4 bytes of attribute each) later than #$00...
  BCC moveloop1up   
  STA paddle1ytop
ReadUp1Done:
  RTS

start1_button_subroutine:
  RTS

select1_button_subroutine:
  RTS

B1_button_subroutine:
  LDA paddle1ytop	 ; load into accumulator the top of the paddle
  CMP #TOPWALL+24		 ; if it's above the ceiling, do nothing
  BCC ReadB1Done  
  STA paddle1ybot
  LDY #$00		 ; RAM address $02xx
moveloop1b:
  LDA $0200, y		 ; load sprite X position
  SEC        		 ; make sure the carry flag is clear
  SBC #$06    		 ; add 6 to accumulator (3x speed)      
  STA $0200, y 		 ; save sprite Y position
  INY
  INY
  INY
  INY			 ; increase x 4 times for 4 attibute bytes per sprite
  CPY #$30		 ; 48 bytes (12 sprites at 4 bytes of attribute each) later than #$00...
  BCC moveloop1b   
  STA paddle1ytop
ReadB1Done:
  RTS

A1_button_subroutine:
  LDA paddle1ybot	 ; load into accumulator the bottom of the paddle
  CMP #BOTTOMWALL	 ; if it's below the floor, do nothing
  BCS ReadA1Done 
  STA paddle1ytop
  LDY #$00		 ; RAM address $02xx
moveloop1a:
  LDA $0200, y		 ; load sprite X position
  CLC        		 ; make sure the carry flag is clear
  ADC #$06    		 ; add 6 to accumulator (3x speed)      
  STA $0200, y 		 ; save sprite Y position
  INY
  INY
  INY
  INY			 ; increase x 4 times for 4 attibute bytes per sprite
  CPY #$30		 ; 48 bytes (12 sprites at 4 bytes of attribute each) later than #$00...
  BCC moveloop1a   
  STA paddle1ybot
ReadA1Done:
  RTS


;-------------------------------------
;Controller 2 Gameplay (STATE_PLAYING)
;-------------------------------------
ReadController2:
  LDA #$01
  STA $4017
  LDA #$00
  STA $4017
  LDX #$08		; 8 increments, one per button
ReadController2Loop:
  LDA $4017
  LSR A    	        ; bit0 -> Carry
  ROL buttons2   	; bit0 <- Carry
  DEX
  BNE ReadController2Loop
  LDA buttons2
  CMP #%00000001
  BEQ jumpright2
  CMP #%00000010
  BEQ jumpleft2
  CMP #%00000100
  BEQ jumpdown2
  CMP #%00001000
  BEQ jumpup2
  CMP #%00010000
  BEQ jumpstart2
  CMP #%00100000
  BEQ jumpselect2
  CMP #%01000000
  BEQ jumpB2
  CMP #%10000000
  BEQ jumpA2
  RTS			

jumpright2:
  JSR right2_button_subroutine
  RTS

jumpleft2:
  JSR left2_button_subroutine
  RTS

jumpdown2:
  JSR down2_button_subroutine
  RTS

jumpup2:
  JSR up2_button_subroutine
  RTS

jumpstart2:
  JSR start2_button_subroutine
  RTS

jumpselect2:
  JSR select2_button_subroutine
  RTS

jumpB2:
  JSR B2_button_subroutine
  RTS

jumpA2:
  JSR A2_button_subroutine
  RTS

right2_button_subroutine:
  LDA paddle2ybot	 ; load into accumulator the bottom of the paddle
  CMP #BOTTOMWALL	 ; if it's below the floor, do nothing
  BCS ReadRight2Done 
  STA paddle2ytop
  LDY #$30		 ; RAM address $02xx
moveloop2right:
  LDA $0200, y		 ; load sprite Y position
  CLC        		 ; make sure the carry flag is clear
  ADC #$04    		 ; add 4 to accumulator (2x speed)      
  STA $0200, y 		 ; save sprite Y position
  INY
  INY
  INY
  INY			 ; increase x 4 times for 4 attibute bytes per sprite
  CPY #$60		 ; 48 bytes (12 sprites at 4 bytes of attribute each) later than #$00...
  BCC moveloop2right   
  STA paddle2ybot
ReadRight2Done: 	 ; handling this button is done
  RTS

left2_button_subroutine:
  LDA paddle2ytop	 ; load into accumulator the top of the paddle
  CMP #TOPWALL+24		 ; if it's above the ceiling, do nothing
  BCC ReadLeft2Done  
  STA paddle2ybot
  LDY #$30		 ; RAM address $02xx
moveloop2left:
  LDA $0200, y		 ; load sprite X position
  SEC        		 ; make sure the carry flag is clear
  SBC #$04    		 ; add 4 to accumulator (2x speed)      
  STA $0200, y 		 ; save sprite Y position
  INY
  INY
  INY
  INY			 ; increase x 4 times for 4 attibute bytes per sprite
  CPY #$60		 ; 48 bytes (12 sprites at 4 bytes of attribute each) later than #$00...
  BCC moveloop2left   
  STA paddle2ytop
ReadLeft2Done:
  RTS

down2_button_subroutine:
  LDA paddle2ybot	 ; load into accumulator the bottom of the paddle
  CMP #BOTTOMWALL	 ; if it's below the floor, do nothing
  BCS ReadDown2Done 
  STA paddle2ytop
  LDY #$30		 ; RAM address $02xx
moveloop2down:
  LDA $0200, y		 ; load sprite Y position
  CLC        		 ; make sure the carry flag is clear
  ADC #$02    		 ; add 2 to accumulator (1x speed)     
  STA $0200, y 		 ; save sprite Y position
  INY
  INY
  INY
  INY			 ; increase x 4 times for 4 attibute bytes per sprite
  CPY #$60		 ; 48 bytes (12 sprites at 4 bytes of attribute each) later than #$00...
  BCC moveloop2down   
  STA paddle2ybot
ReadDown2Done: 	        ; handling this button is done
  RTS

up2_button_subroutine:
  LDA paddle2ytop	 ; load into accumulator the top of the paddle
  CMP #TOPWALL+24		 ; if it's above the ceiling, do nothing
  BCC ReadUp2Done  
  STA paddle2ybot
  LDY #$30		 ; RAM address $02xx
moveloop2up:
  LDA $0200, y		 ; load sprite X position
  SEC        		 ; make sure the carry flag is clear
  SBC #$02    		 ; add 2 to accumulator (1x speed)      
  STA $0200, y 		 ; save sprite Y position
  INY
  INY
  INY
  INY			 ; increase x 4 times for 4 attibute bytes per sprite
  CPY #$60		 ; 48 bytes (12 sprites at 4 bytes of attribute each) later than #$00...
  BCC moveloop2up   
  STA paddle2ytop
ReadUp2Done:
  RTS

start2_button_subroutine:
  RTS

select2_button_subroutine:
  RTS

B2_button_subroutine:
  LDA paddle2ytop	 ; load into accumulator the top of the paddle
  CMP #TOPWALL+24		 ; if it's above the ceiling, do nothing
  BCC ReadB2Done  
  STA paddle2ybot
  LDY #$30		 ; RAM address $02xx
moveloop2b:
  LDA $0200, y		 ; load sprite X position
  SEC        		 ; make sure the carry flag is clear
  SBC #$06    		 ; add 6 to accumulator (3x speed)      
  STA $0200, y 		 ; save sprite Y position
  INY
  INY
  INY
  INY			 ; increase x 4 times for 4 attibute bytes per sprite
  CPY #$60		 ; 48 bytes (12 sprites at 4 bytes of attribute each) later than #$00...
  BCC moveloop2b   
  STA paddle2ytop
ReadB2Done:
  RTS

A2_button_subroutine:
  LDA paddle2ybot	 ; load into accumulator the bottom of the paddle
  CMP #BOTTOMWALL	 ; if it's below the floor, do nothing
  BCS ReadA2Done 
  STA paddle2ytop
  LDY #$30		 ; RAM address $02xx
moveloop2a:
  LDA $0200, y		 ; load sprite X position
  CLC        		 ; make sure the carry flag is clear
  ADC #$06    		 ; add 6 to accumulator (3x speed)      
  STA $0200, y 		 ; save sprite Y position
  INY
  INY
  INY
  INY			 ; increase x 4 times for 4 attibute bytes per sprite
  CPY #$60		 ; 48 bytes (12 sprites at 4 bytes of attribute each) later than #$00...
  BCC moveloop2a   
  STA paddle2ybot
ReadA2Done:
  RTS


;--------------
;MAIN GAME CODE
;--------------

RESET:
  SEI 		        ; disable IRQs
  CLD          		; disable decimal mode
  LDX #$40
  STX $4017		; disable APU frame IRQ
  LDX #$FF
  TXS     		; Set up stack
  INX          		; now X = 0
  STX $2000    		; disable NMI
  STX $2001    		; disable rendering
  STX $4010    		; disable DMC IRQs

  JSR vblankwait        ; First wait for vblank to make sure PPU is ready

clrmem:
  LDA #$00
  STA $0000, x
  STA $0100, x
  STA $0200, x		; note that the background tutorials set #$00 to $0300 and #$FE to $0200
  STA $0400, x
  STA $0500, x
  STA $0600, x
  STA $0700, x
  LDA #$FE
  STA $0300, x
  INX
  BNE clrmem

  LDA #$68		; set in RAM initial paddle positions
  STA paddle1ytop
  STA paddle2ytop
  LDA #$87
  STA paddle1ybot
  STA paddle2ybot
   
  JSR vblankwait        ; Second wait for vblank, PPU is ready after this


LoadPalettes:
  LDA $2002             ; read PPU status to reset the high/low latch
  LDA #$3F
  STA $2006             ; write the high byte of $3F00 address
  LDA #$00
  STA $2006             ; write the low byte of $3F00 address
  LDX #$00              ; start out at 0
LoadPalettesLoop:
  LDA palette, x        ; load data from address (palette + the value in x)
                        ; 1st time through loop it will load palette+0
                        ; 2nd time through loop it will load palette+1
                        ; 3rd time through loop it will load palette+2
                        ; etc
  STA $2007             ; write to PPU
  INX                   ; X = X + 1
  CPX #$20              ; Compare X to hex $10, decimal 16 - copying 16 bytes = 4 sprites
  BNE LoadPalettesLoop  ; Branch to LoadPalettesLoop if compare was Not Equal to zero
                        ; if compare was equal to 32, keep going down



LoadSprites:
  LDX #$00              ; start at 0
LoadSpritesLoop:
  LDA sprites, x        ; load data from address (sprites +  x)
  STA $0200, x          ; store into RAM address ($0200 + x)
  INX                   ; X = X + 1
  CPX #$60              ; Compare X to hex $30, decimal 96 (# of bytes, 12 tiles x 4 bytes per, x2 paddles)
			; (Sprite size for this game is 24x32 pixels, or 3x4=12 tiles, x2 paddles.)
  BNE LoadSpritesLoop   ; Branch to LoadSpritesLoop if compare was Not Equal to zero
                        ; if compare was equal to 48x2 (96), keep going down
              
              

LoadBackground:
  LDA $2002             ; read PPU status to reset the high/low latch
  LDA #$20
  STA $2006             ; write the high byte of $2000 address
  LDA #$00
  STA $2006             ; write the low byte of $2000 address
  LDX #$00              ; start out at 0
LoadBackgroundLoop:
  LDA background, x     ; load data from address (background + the value in x)
  STA $2007             ; write to PPU
  INX                   ; X = X + 1
  CPX #$00              ; Compare X to hex $00, decimal 0 (or 256 when rolling over) - copying 256 bytes
  BNE LoadBackgroundLoop  ; Branch to LoadBackgroundLoop if compare was Not Equal to zero
                        ; if compare was equal to 0, keep going down
              
LoadBackground2:	; second loop for next 256 bytes 
  LDA $2002             ; read PPU status to reset the high/low latch
  LDA #$21
  STA $2006             ; write the high byte of $2100 address; $0100 or 256 bytes after first loop above
  LDA #$00
  STA $2006             ; write the low byte of $2100 address
  LDX #$00              ; start out at 0
LoadBackgroundLoop2:
  LDA background2, x    ; load data from address (background + the value in x)
  STA $2007             ; write to PPU
  INX                   ; X = X + 1
  CPX #$00              ; Compare X to hex $00, decimal 0 (or 256 when rolling over) - copying 256 bytes
  BNE LoadBackgroundLoop2  ; Branch to LoadBackgroundLoop2 if compare was Not Equal to zero
                        ; if compare was equal to 0, keep going down
    
LoadBackground3:	; third loop for next 256 bytes 
  LDA $2002             ; read PPU status to reset the high/low latch
  LDA #$22
  STA $2006             ; write the high byte of $2200 address
  LDA #$00
  STA $2006             ; write the low byte of $2200 address
  LDX #$00              ; start out at 0
LoadBackgroundLoop3:
  LDA background3, x    ; load data from address (background + the value in x)
  STA $2007             ; write to PPU
  INX                   ; X = X + 1
  CPX #$00              ; Compare X to hex $00, decimal 0 (or 256 when rolling over) - copying 256 bytes
  BNE LoadBackgroundLoop3  ; Branch to LoadBackgroundLoop3 if compare was Not Equal to zero
                        ; if compare was equal to 0, keep going down          

LoadBackground4:	; fourth loop for last batch of bytes - max is 960
  LDA $2002             ; read PPU status to reset the high/low latch
  LDA #$23
  STA $2006             ; write the high byte of $2300 address
  LDA #$00
  STA $2006             ; write the low byte of $2300 address
  LDX #$00              ; start out at 0
LoadBackgroundLoop4:
  LDA background4, x    ; load data from address (background + the value in x)
  STA $2007             ; write to PPU
  INX                   ; X = X + 1
  CPX #$C0              ; Compare X to hex $C0, decimal 192 - copying last bytes
  BNE LoadBackgroundLoop4  ; Branch to LoadBackgroundLoop4 if compare was Not Equal to zero
                        ; if compare was equal to 0, keep going down    

LoadAttribute:
  LDA $2002             ; read PPU status to reset the high/low latch
  LDA #$23
  STA $2006             ; write the high byte of $23C0 address
  LDA #$C0
  STA $2006             ; write the low byte of $23C0 address
  LDX #$00              ; start out at 0
LoadAttributeLoop:
  LDA attribute, x      ; load data from address (attribute + the value in x)
  STA $2007             ; write to PPU
  INX                   ; X = X + 1
;  CPX #$08             ;  Compare X to hex $08, decimal 8 - copying 8 bytes
  CPX #40		; #$08 is but one row; we've got 8		
  BNE LoadAttributeLoop  ; Branch to LoadAttributeLoop if compare was Not Equal to zero
                        ; if compare was equal to 128, keep going down
              
;---------------------------
;Set some initial ball stats
;---------------------------
  LDA #$01
  STA balldown
  STA ballright
  LDA #$00
  STA ballup
  STA ballleft
  
  LDA #$50
  STA bally
  
  LDA #$80
  STA ballx
  
  LDA #$02
  STA ballspeedx
  STA ballspeedy

;-----------------------
;Set initial score value
;-----------------------
  LDA #$00
  STA score1
  STA scoreOnes1
  STA scoreTens1
;  STA scoreHundreds1
  STA score2
  STA scoreOnes2
  STA scoreTens2
;  STA scoreHundreds2

;-----------------------
;Set starting game state
;-----------------------
  LDA #STATE_PLAYING
  STA gamestate

              
  LDA #%10010000  	 ; enable NMI, sprites from Pattern Table 0, background from Pattern Table 1
  STA $2000

  LDA #%00011110   	 ; enable sprites, enable background, no clipping on left side
  STA $2001

Forever:
  JMP Forever    	 ; jump back to Forever, infinite loop
  
 
;---
;NMI
;---

NMI:
  LDA #$00
  STA $2003       	 ; set the low byte (00) of the RAM address
  LDA #$02
  STA $4014      	 ; set the high byte (02) of the RAM address, start the transfer

  JSR DrawScore1
  JSR DrawScore2

  ;;This is the PPU clean up section, so rendering the next frame starts properly.
  LDA #%10010000  	 ; enable NMI, sprites from Pattern Table 0, background from Pattern Table 1
  STA $2000
  LDA #%00011110  	 ; enable sprites, enable background, no clipping on left side
  STA $2001
  LDA #$00       	 ; tell the ppu there is no background scrolling
  STA $2005
  STA $2005
    
  ;;;all graphics updates done by here, run game engine

LatchController:
  LDA #$01
  STA $4016	  	 ; controller 1 
  STA $4017		 ; controller 2
  LDA #$00
  STA $4016       	 ; tell both the controllers to latch buttons
  STA $4017
  JSR ReadController1	 ; keeps the controller reads in NMI, since you need them each frame
  JSR ReadController2
  
  ;;This is the PPU clean up section, so rendering the next frame starts properly.
  LDA #%10010000   	; enable NMI, sprites from Pattern Table 0, background from Pattern Table 1
  STA $2000
  LDA #%00011110   	; enable sprites, enable background, no clipping on left side
  STA $2001
  LDA #$00        	;;tell the ppu there is no background scrolling
  STA $2005
  STA $2005

GameEngine:  
  LDA gamestate
  CMP #STATE_TITLE	;;#$00
  BEQ EngineTitle    	;;game is displaying title screen
    
  LDA gamestate
  CMP #STATE_GAMEOVER	;;#$02
  BEQ EngineGameOver  	;;game is displaying ending screen
  
  LDA gamestate
  CMP #STATE_PLAYING	;;#$01
  BEQ EnginePlaying   	;;game is playing
GameEngineDone:  
  
  JSR UpdateSprites  ;;set ball/paddle sprites from positions


  RTI             	; return from interrupt
 
;;;;;;;;;;;;;;  

 
EngineTitle:
  ;;if start button pressed
  ;;  turn screen off
  ;;  load game screen
  ;;  set starting paddle/ball position
  ;;  go to Playing State
  ;;  turn screen on
  JMP GameEngineDone

;;;;;;;;; 
 
EngineGameOver:
  ;;if start button pressed
  ;;  turn screen off
  ;;  load title screen
  ;;  go to Title State
  ;;  turn screen on 
  JMP GameEngineDone
 
;;;;;;;;;;;
 
EnginePlaying:

MoveBallRight:
  LDA ballright
  BEQ MoveBallRightDone   ;;if ballright=0, skip this section

  LDA ballx
  CLC
  ADC ballspeedx       	  ;;ballx position = ballx + ballspeedx
  STA ballx

  LDA ballx
  CMP #RIGHTWALL
  BCC MoveBallRightDone   ;;if ball x < right wall, still on screen, skip next section
  LDA #$00
  STA ballright
  LDA #$01
  STA ballleft         	  ;;bounce, ball now moving left
  ;;in real game, give point to player 1, reset ball (see below)
  jsr IncrementScore1
  LDA #$80
  STA ballx
  STA bally
  LDA #$00
  STA ballleft
  LDA #$01
  STA ballright
MoveBallRightDone:


MoveBallLeft:
  LDA ballleft
  BEQ MoveBallLeftDone    ;;if ballleft=0, skip this section

  LDA ballx
  SEC
  SBC ballspeedx          ;;ballx position = ballx - ballspeedx
  STA ballx

  LDA ballx
  CMP #LEFTWALL
  BCS MoveBallLeftDone    ;;if ball x > left wall, still on screen, skip next section
  LDA #$01
  STA ballright
  LDA #$00
  STA ballleft            ;;bounce, ball now moving right
  ;;in real game, give point to player 2, reset ball (see below)
  jsr IncrementScore2
  LDA #$78
  STA ballx
  STA bally
  LDA #$00
  STA ballright
  LDA #$01
  STA ballleft
MoveBallLeftDone:


MoveBallUp:
  LDA ballup
  BEQ MoveBallUpDone      ;;if ballup=0, skip this section

  LDA bally
  SEC
  SBC ballspeedy          ;;bally position = bally - ballspeedy
  STA bally

  LDA bally
  CMP #TOPWALL
  BCS MoveBallUpDone      ;;if ball y > top wall, still on screen, skip next section
  LDA #$01
  STA balldown
  LDA #$00
  STA ballup         	  ;;bounce, ball now moving down
MoveBallUpDone:


MoveBallDown:
  LDA balldown
  BEQ MoveBallDownDone    ;;if ballup=0, skip this section

  LDA bally
  CLC
  ADC ballspeedy          ;;bally position = bally + ballspeedy
  STA bally

  LDA bally
  CMP #BOTTOMWALL
  BCC MoveBallDownDone    ;;if ball y < bottom wall, still on screen, skip next section
  LDA #$00
  STA balldown
  LDA #$01
  STA ballup         	  ;;bounce, ball now moving down
MoveBallDownDone:


CheckPaddle1Collision: ;checks for collision coming from the right only
  LDA ballx 
  CMP #PADDLE1X + PADDLE_WIDTH
  BCS CheckPaddle1CollisionDone 	; if ballx > PADDLE1X, there's no collision with the paddle
  LDA bally                     	; otherwise, check if it's actually on the paddle
  CMP paddle1ytop              		; if bally < paddle1ytop, it's above the paddle, so no collision
  BCC CheckPaddle1CollisionDone
  CMP paddle1ybot               	; if bally > paddle1ybot, it's below the paddle, so no collision
  BCS CheckPaddle1CollisionDone
  LDA #FALSE                      	; if we get here, it was a collision, so we switch direction
  STA ballleft
  LDA #TRUE
  STA ballright

CheckPaddle1CollisionDone:  		; checks for collision coming from the left only
  LDA ballx
  CMP #PADDLE2X - SPRITE_SIZE + 1
  BCC CheckPaddle2CollisionDone 	; if ballx < PADDLE2X, there's no collision with the paddle
  LDA bally
  CMP paddle2ytop
  BCC CheckPaddle2CollisionDone 	; if ballY < paddle2ytop, it's above the paddle, so no collision
  CMP paddle2ybot             
  BCS CheckPaddle2CollisionDone 	;i f ballY > paddle2ybot, it's below the paddle, so no collision
  LDA #FALSE
  STA ballright
  LDA #TRUE
  STA ballleft
  CheckPaddle2CollisionDone:


  JMP GameEngineDone
 
 
 
 
UpdateSprites:
  LDA bally  		  ;;update all ball sprite info
  STA $0280		  ; makes room for longer paddles if desired
  
  LDA #$0D		  ; PPU tile for sprite
  STA $0281
  
  LDA #$00
  STA $0282
  
  LDA ballx
  STA $0283
  
  ;;update paddle sprites
  RTS
 
 
DrawScore1:
  LDA $2002
  LDA #$20
  STA $2006
  LDA #$4D
  STA $2006          ; start drawing the p1 score at PPU $204D
  LDA scoreTens1      ; next digit
  STA $2007
  LDA scoreOnes1      ; last digit
  STA $2007
  RTS
 
DrawScore2:
  LDA $2002
  LDA #$20
  STA $2006
  LDA #$51
  STA $2006          ; start drawing the p2 score at PPU $2051
  LDA scoreTens2      ; next digit
  STA $2007
  LDA scoreOnes2      ; last digit
  STA $2007
  RTS
 
IncrementScore1:
  LDA score1
  CLC
  ADC #$01
  STA score1
IncOnes1:
  LDA scoreOnes1      ; load the lowest digit of the number
  CLC 
  ADC #$01           ; add one
  STA scoreOnes1
  CMP #$0A           ; check if it overflowed, now equals 10
  BNE IncDone1        ; if there was no overflow, all done
IncTens1:
  LDA #$00
  STA scoreOnes1      ; wrap digit to 0
 LDA scoreTens1      ; load the next digit
  CLC 
  ADC #$01           ; add one, the carry from previous digit
  STA scoreTens1
IncDone1:
   RTS		     ;not having this RTS will crash the game!
 
IncrementScore2:
  LDA score2
  CLC
  ADC #$01
  STA score2
IncOnes2:
  LDA scoreOnes2      ; load the lowest digit of the number
  CLC 
  ADC #$01           ; add one
  STA scoreOnes2
  CMP #$0A           ; check if it overflowed, now equals 10
  BNE IncDone2        ; if there was no overflow, all done
IncTens2:
  LDA #$00
  STA scoreOnes2      ; wrap digit to 0
 LDA scoreTens2      ; load the next digit
  CLC 
  ADC #$01           ; add one, the carry from previous digit
  STA scoreTens2
IncDone2:
  RTS 

 
;========        
;========
;BANK ONE    
;========
;========
  .bank 1
  .org $E000

palette:
  .db $0F,$0F,$0F,$30,  $0F,$30,$02,$2A,  $0F,$30,$02,$0A,  $0F,$30,$02,$11 ; background palette
;use $0F,$30,$02,$16 as a good score palette

  .db $0F,$0A,$2A,$30,  $0F,$0A,$2a,$11,  $0F,$0A,$2a,$17,  $0F,$0A,$2a,$04 ; sprite palette

;$0F = black ;$0A = dark green ;$2A = green ;$30 = white
;$11 = blue ;$04 = purple ;$17 = orange ;$16 = red
;black, dark green, green (can't do red), white (0)
;black, dark green, green, blue (1)
;black, dark green, green, orange (2)
;black, dark green, green, purple (3)
;MISSING: A red to differentiate Migs from Rafa.

sprites:
     		;vert tile attr horiz
  .db PADDLE1YINIT, $00, $01, PADDLE1X-$10  		; sprite 00; RAM $0200; p1; check tile numbers and palette colors
  .db PADDLE1YINIT, $01, $01, PADDLE1X-$08 		; sprite 01; RAM $0204
  .db PADDLE1YINIT, $02, $00, PADDLE1X   		; sprite 02; RAM $0208
  .db PADDLE1YINIT+$08, $03, $00, PADDLE1X-$10   	; sprite 03; RAM $020C
  .db PADDLE1YINIT+$08, $04, $01, PADDLE1X-$08   	; sprite 04; RAM $0210
  .db PADDLE1YINIT+$08, $05, $00, PADDLE1X   		; sprite 05; RAM $0214
  .db PADDLE1YINIT+$10, $06, $02, PADDLE1X-$10   	; sprite 06; RAM $0218
  .db PADDLE1YINIT+$10, $07, $02, PADDLE1X-$08   	; sprite 07; RAM $021C
  .db PADDLE1YINIT+$10, $08, $00, PADDLE1X   		; sprite 08; RAM $0220
  .db PADDLE1YINIT+$18, $09, $00, PADDLE1X-$10   	; sprite 09; RAM $0224
  .db PADDLE1YINIT+$18, $0A, $02, PADDLE1X-$08   	; sprite 10; RAM $0228
  .db PADDLE1YINIT+$18, $0B, $00, PADDLE1X   		; sprite 11; RAM $022C
; .db PADDLE1YINIT-$08, $0C, $80, PADDLE1X   		; sprite 24; RAM $0260 (not optimized)flipped vertically
; .db PADDLE1YINIT+$20, $0C, $00, PADDLE1X   		; sprite 25; RAM $0268 (not optimized)

  .db PADDLE2YINIT, $02, $40, PADDLE2X-$10   		; sprite 12; RAM $0230; p2; check tile numbers and palette colors
  .db PADDLE2YINIT, $01, $42, PADDLE2X-$08   		; sprite 13; RAM $0234; 64 = flip sprite horizontally
  .db PADDLE2YINIT, $00, $42, PADDLE2X   		; sprite 14; RAM $0238; using same sprite tiles as p1!!!
  .db PADDLE2YINIT+$08, $05, $40, PADDLE2X-$10   	; sprite 15; RAM $023C
  .db PADDLE2YINIT+$08, $04, $42, PADDLE2X-$08   	; sprite 16; RAM $0240
  .db PADDLE2YINIT+$08, $03, $40, PADDLE2X   		; sprite 17; RAM $0244
  .db PADDLE2YINIT+$10, $08, $40, PADDLE2X-$10   	; sprite 18; RAM $0248
  .db PADDLE2YINIT+$10, $07, $43, PADDLE2X-$08   	; sprite 19; RAM $024C
  .db PADDLE2YINIT+$10, $06, $43, PADDLE2X   		; sprite 20; RAM $0250
  .db PADDLE2YINIT+$18, $0B, $40, PADDLE2X-$10   	; sprite 21; RAM $0254
  .db PADDLE2YINIT+$18, $0A, $43, PADDLE2X-$08   	; sprite 22; RAM $0258
  .db PADDLE2YINIT+$18, $09, $40, PADDLE2X   		; sprite 23; RAM $025C
; .db PADDLE2YINIT-$08, $0C, $80, PADDLE2X   		; sprite 26; RAM $0270 (not optimized)flipped vertically
; .db PADDLE2YINIT+$20, $0C, $00, PADDLE2X   		; sprite 27; RAM $0278 (not optimized)


background:
  .db $24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24  ;; row 1 - left half - PAL
  .db $24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24  ;; row 1 - right half - PAL
  .db $2D,$2C,$2D,$2C,$F8,$2C,$2D,$2C,$2D,$2C,$2D,$2C,$2D,$2C,$2D,$30  ;; row 2
  .db $31,$2C,$2D,$2C,$2D,$2C,$2D,$2C,$2D,$2C,$2D,$2C,$2D,$2C,$2D,$2C  
  .db $24,$24,$15,$0E,$18,$17,$24,$22,$24,$16,$12,$10,$24,$24,$24,$30  ;; row 3 - Leon y Mig; Rafa y Don
  .db $31,$24,$24,$24,$1B,$0A,$0F,$0A,$24,$22,$24,$0D,$18,$17,$24,$24  
  .db $24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$30  ;; row 4
  .db $31,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24  
  .db $24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$30  ;; row 5
  .db $31,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24  
  .db $24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$30  ;; row 6
  .db $31,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24  
  .db $24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$30  ;; row 7
  .db $31,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24  
  .db $24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$30  ;; row 8
  .db $31,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24  

background2:
  .db $24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$30  ;; row 1 - left half
  .db $31,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24  ;; row 1 - right half
  .db $24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$30  ;; row 2
  .db $31,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24  
  .db $24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$30  ;; row 3
  .db $31,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24  
  .db $24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$30  ;; row 4
  .db $31,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24  
  .db $24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$30  ;; row 5
  .db $31,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24  
  .db $24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$30  ;; row 6
  .db $31,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24  
  .db $24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$30  ;; row 7
  .db $31,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24  
  .db $24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$30  ;; row 8
  .db $31,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24  

background3:
  .db $24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$30  ;; row 1 - left half
  .db $31,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24  ;; row 1 - right half
  .db $24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$30  ;; row 2
  .db $31,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24  
  .db $24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$30  ;; row 3
  .db $31,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24  
  .db $24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$30  ;; row 4
  .db $31,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24  
  .db $24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$30  ;; row 5
  .db $31,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24  
  .db $24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$30  ;; row 6
  .db $31,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24  
  .db $24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$30  ;; row 7
  .db $31,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24  
  .db $24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$30  ;; row 8
  .db $31,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24 

background4:
  .db $24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$30  ;; row 1 - left half
  .db $31,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24  ;; row 1 - right half
  .db $24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$30  ;; row 2
  .db $31,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24  
  .db $24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$30  ;; row 3
  .db $31,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24  
  .db $24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$30  ;; row 4
  .db $31,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24  
  .db $2F,$2E,$2F,$2E,$2F,$2E,$2F,$2E,$2F,$2E,$2F,$2E,$2F,$2E,$2F,$30  ;; row 5
  .db $31,$2E,$2F,$2E,$2F,$2E,$2F,$2E,$2F,$2E,$2F,$2E,$2F,$2E,$2F,$2E  
  .db $24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24  ;; row 6 - PAL
  .db $24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24  

attribute:
  .db %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000
  .db %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000
  .db %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000
  .db %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000
  .db %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000
  .db %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000
  .db %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000
  .db %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000



  .org $FFFA     	    ;first of the three vectors starts here
  .dw NMI        	    ;when an NMI happens (once per frame if enabled) the 
                  	    ;processor will jump to the label NMI:
  .dw RESET      	    ;when the processor first turns on or is reset, it will jump
                   	    ;to the label RESET:
  .dw 0          	    ;external interrupt IRQ is not used in this tutorial
  
  
;========
;========
;BANK TWO
;========
;========  
  .bank 2
  .org $0000
  .incbin "tortugas.chr"    ;modified 8KB graphics file, originally from SMB1
  
The Nerdy Night tutorials seem to go a route of starting with the gameplay state and then building a title screen state and a game over state within that gameplay code. That being the case, I'd like to work that angle if I can (i.e, build the title screen stuff into the code above).

I'm assuming I first set the gamestate to zero here...

Code: Select all

;-----------------------
;Set starting game state
;-----------------------
  LDA #STATE_PLAYING
  STA gamestate

              
  LDA #%10010000  	 ; enable NMI, sprites from Pattern Table 0, background from Pattern Table 1
  STA $2000

  LDA #%00011110   	 ; enable sprites, enable background, no clipping on left side
  STA $2001

Forever:
  JMP Forever  
  
Any tips on next step? I'm assuming it's a JSR to something that turns screen off and on, but I'm not sure if I should be using the initialization I already have, and then create some new subroutines before NMI to compare gamestate value and use the title screen subroutines (to load background, palette and tiles, then latch controller). Is that logic reasonably correct?

User avatar
Controllerhead
Posts: 147
Joined: Tue Nov 13, 2018 4:58 am
Location: $4016
Contact:

Re: [Help Request] Homebrew Title Screen Code

Post by Controllerhead » Thu Jul 30, 2020 6:57 pm

eskayelle wrote:
Thu Jul 30, 2020 5:54 pm
Any tips on next step?
Well, however you decide to do it, you're going to need to make a system to handle different screens and game states. If it were me, my next step would be making JSRs to load the title screen background, the gameplay background, the game over screen background, and unload the background. I'd map select to turn off the PPU, unload the current background, load the next background, and turn on the PPU again as a test. After that works, i'd hook those subroutines into your gamestate. That would be my approach...
Image

User avatar
eskayelle
Posts: 22
Joined: Wed Jul 29, 2020 5:07 pm
Contact:

Re: [Help Request] Homebrew Title Screen Code

Post by eskayelle » Thu Jul 30, 2020 7:58 pm

Sorry for the dumb question. How do you "unload a background"? Is there specific code for that?

Also, turning off the PPU is via storing %#00000000 in $2001, correct?

User avatar
Controllerhead
Posts: 147
Joined: Tue Nov 13, 2018 4:58 am
Location: $4016
Contact:

Re: [Help Request] Homebrew Title Screen Code

Post by Controllerhead » Thu Jul 30, 2020 8:37 pm

eskayelle wrote:
Thu Jul 30, 2020 7:58 pm
How do you "unload a background"?
Oh, i phrased that poorly, i meant storing blank tiles in the nametable(s) where the old tiles were so they aren't still on the screen when you load your new tiles. That depends on how you design your code, though; if you update the entirety of one or both nametables in your loading loop and specifically load blank tiles, it's unnecessary...

Also, if the code takes more than a frame to do, you probably want to disable NMI in bit 7 of $2000, and re-enable it when the background load is done, for now... You don't want more than one NMI interrupt on the stack or the process getting interrupted, or possibly causing an infinite loop and a stack overflow crash... Eventually, like tokumaru said, you may want to have NMI on for keeping music or other things running during the screen loading process, or stagger it between frames, or just RTI from NMI if you are in a screen loading state, but i wouldn't worry about that, yet...
eskayelle wrote:
Thu Jul 30, 2020 7:58 pm
Also, turning off the PPU is via storing %#00000000 in $2001, correct?
Yeah, that'l work, more specifically, as song as bits 3 and 4 are 0, like STA $2001 with %xxx00xxx
Image

User avatar
eskayelle
Posts: 22
Joined: Wed Jul 29, 2020 5:07 pm
Contact:

Re: [Help Request] Homebrew Title Screen Code

Post by eskayelle » Fri Jul 31, 2020 2:11 pm

I think I've gotten pretty far; I'm hung up for the most part in loading and unloading the screens.

Code: Select all

  .inesprg 1   ; 1x 16KB PRG code
  .ineschr 1   ; 1x  8KB CHR data
  .inesmap 0   ; mapper 0 = NROM, no bank swapping
  .inesmir 1   ; background mirroring
  

;==================
; DECLARE VARIABLES
;==================
  .rsset $0000       	; start variables at ram location $0000
  
gamestate     .rs 1     ; .rs 1 means reserve one byte of space 	; RAM $0000
ballx         .rs 1     ; ball horizontal position			; RAM $0001
bally         .rs 1     ; ball vertical position			; RAM $0002
ballup        .rs 1     ; 1 = ball moving up				; RAM $0003
balldown      .rs 1     ; 1 = ball moving down				; RAM $0004
ballleft      .rs 1     ; 1 = ball moving left				; RAM $0005
ballright     .rs 1     ; 1 = ball moving right				; RAM $0006
ballspeedx    .rs 1     ; ball horizontal speed per frame		; RAM $0007
ballspeedy    .rs 1     ; ball vertical speed per frame			; RAM $0008
paddle1ytop   .rs 1  	; player 1 paddle top vertical position		; RAM $0009 
paddle1ybot   .rs 1  	; player 1 paddle bottom vertical position	; RAM $000A 
paddle2ytop   .rs 1  	; player 2 paddle top vertical position		; RAM $000B 
paddle2ybot   .rs 1  	; player 2 paddle bottom vertical position	; RAM $000C 
buttons1      .rs 1     ; player 1 gamepad buttons, one bit per button	; RAM $000D 
buttons2      .rs 1     ; player 2 gamepad buttons, one bit per button	; RAM $000E 
score1        .rs 1     ; player 1 score, 0-15				; RAM $000F 
score2        .rs 1     ; player 2 score, 0-15				; RAM $0010 
paddlespeed   .rs 1  	; paddle speed depending on button pressed	; RAM $0011 ;not yet used
scoreOnes1	.rs 1	; byte for each digit in the decimal score	; RAM $0012
scoreTens1	.rs 1							; RAM $0013
scoreOnes2	.rs 1	; byte for each digit in the decimal score	; RAM $0014
scoreTens2	.rs 1							; RAM $0015
pointerLo  .rs 1   ; pointer variables are declared in RAM		; RAM $0016 
pointerHi  .rs 1   ; low byte first, high byte immediately after	; RAM $0017

;=================
;DECLARE CONSTANTS 
;=================
TRUE		= $01
FALSE		= $00

STATE_TITLE     = $00   ; displaying title screen
STATE_PLAYING   = $01   ; move paddles/ball, check for collisions
STATE_GAMEOVER  = $02   ; displaying game over screen
  
RIGHTWALL       = $FB   ; when ball reaches one of these, do something (was $F9)
TOPWALL         = $0A   ; touches bottom of background row 2 
BOTTOMWALL      = $DD   ; touches top of background table 4 row 6
LEFTWALL        = $01	; ($01)
  
PADDLE1X        = $20   ; horizontal position for paddles, doesn't move ($20)
PADDLE2X        = $E8   ; ($E8)
PADDLE1YINIT    = $68   ; initial horizontal position for top of paddles
PADDLE2YINIT    = $68	

SPRITE_SIZE     = $16   ; 3 horizontal sprites at 8 pixels each
PADDLE_WIDTH 	= $08   ; just the paddle, not the tortugas


;=========
;=========
;BANK ZERO
;========= 
;=========   
  .bank 0
  .org $C000 

;===========
;SUBROUTINES
;===========


titleclrmem:
  LDA #$FE
  STA $0200, x
  INX
  BNE titleclrmem
  RTS

;---------------------
;draw WIN at game over
;---------------------
DrawWin1:
  LDA $2002
  LDA #$20
  STA $2006
  LDA #$66
  STA $2006          ; start drawing the p1 score at PPU $2066
  LDA #$20           ; W
  STA $2007
  LDA #$12     	     ; I
  STA $2007
  LDA #$17           ; N
  STA $2007
  LDA #$2B           ; !
  STA $2007
  RTS

DrawWin2:
  LDA $2002
  LDA #$20
  STA $2006
  LDA #$78
  STA $2006          ; start drawing the p1 score at PPU $2078
  LDA #$20           ; W
  STA $2007
  LDA #$12     	     ; I
  STA $2007
  LDA #$17           ; N
  STA $2007
  LDA #$2B           ; !
  STA $2007
  RTS

;----------------
;hide ball sprite
;----------------
hidesprites:
  LDA gamestate
  CMP #STATE_GAMEOVER
  BEQ hidesprites2
hidesprites2:
  LDA #$FE
  STA $0200, x
  INX
  CPX #$FF
  BNE hidesprites2
  RTS

;------
;vBlank
;------
vblankwait:
  BIT $2002
  BPL vblankwait
  RTS		   	; return from this subroutine

;-------------------------------------
;Controller 1 Gameplay (STATE_PLAYING)
;-------------------------------------
ReadController1:
  LDA #$01
  STA $4016
  LDA #$00
  STA $4016
  LDX #$08		; 8 increments, one per button
ReadController1Loop:
  LDA $4016
  LSR A    	        ; bit0 -> Carry
  ROL buttons1   	; bit0 <- Carry
  DEX
  BNE ReadController1Loop
  LDA buttons1
  CMP #%00000001
  BEQ jumpright1
  CMP #%00000010
  BEQ jumpleft1
  CMP #%00000100
  BEQ jumpdown1
  CMP #%00001000
  BEQ jumpup1
  CMP #%00010000
  BEQ jumpstart1
  CMP #%00100000
  BEQ jumpselect1
  CMP #%01000000
  BEQ jumpB1
  CMP #%10000000
  BEQ jumpA1
  RTS			;yes!  this works!

jumpright1:
  JSR right1_button_subroutine
  RTS

jumpleft1:
  JSR left1_button_subroutine
  RTS

jumpdown1:
  JSR down1_button_subroutine
  RTS

jumpup1:
  JSR up1_button_subroutine
  RTS

jumpstart1:
  JSR start1_button_subroutine
  RTS

jumpselect1:
  JSR select1_button_subroutine
  RTS

jumpB1:
  JSR B1_button_subroutine
  RTS

jumpA1:
  JSR A1_button_subroutine
  RTS

right1_button_subroutine:
  LDA paddle1ybot	 ; load into accumulator the bottom of the paddle
  CMP #BOTTOMWALL	 ; if it's below the floor, do nothing
  BCS ReadRight1Done 
  STA paddle1ytop
  LDY #$00		 ; RAM address $02xx
moveloop1right:
  LDA $0200, y		 ; load sprite Y position
  CLC        		 ; make sure the carry flag is clear
  ADC #$04    		 ; add 4 to accumulator (2x speed)      
  STA $0200, y 		 ; save sprite Y position
  INY
  INY
  INY
  INY			 ; increase x 4 times for 4 attibute bytes per sprite
  CPY #$30		 ; 48 bytes (12 sprites at 4 bytes of attribute each) later than #$00...
  BCC moveloop1right   
  STA paddle1ybot
ReadRight1Done: 	 ; handling this button is done
  RTS

left1_button_subroutine:
  LDA paddle1ytop	 ; load into accumulator the top of the paddle
  CMP #TOPWALL+24		 ; if it's above the ceiling, do nothing
  BCC ReadLeft1Done  
  STA paddle1ybot
  LDY #$00		 ; RAM address $02xx
moveloop1left:
  LDA $0200, y		 ; load sprite X position
  SEC        		 ; make sure the carry flag is clear
  SBC #$04    		 ; add 4 to accumulator (2x speed)      
  STA $0200, y 		 ; save sprite Y position
  INY
  INY
  INY
  INY			 ; increase x 4 times for 4 attibute bytes per sprite
  CPY #$30		 ; 48 bytes (12 sprites at 4 bytes of attribute each) later than #$00...
  BCC moveloop1left   
  STA paddle1ytop
ReadLeft1Done:
  RTS

down1_button_subroutine:
  LDA paddle1ybot	 ; load into accumulator the bottom of the paddle
  CMP #BOTTOMWALL	 ; if it's below the floor, do nothing
  BCS ReadDown1Done 
  STA paddle1ytop
  LDY #$00		 ; RAM address $02xx
moveloop1down:
  LDA $0200, y		 ; load sprite Y position
  CLC        		 ; make sure the carry flag is clear
  ADC #$02    		 ; add 2 to accumulator (1x speed)     
  STA $0200, y 		 ; save sprite Y position
  INY
  INY
  INY
  INY			 ; increase x 4 times for 4 attibute bytes per sprite
  CPY #$30		 ; 48 bytes (12 sprites at 4 bytes of attribute each) later than #$00...
  BCC moveloop1down   
  STA paddle1ybot
ReadDown1Done: 	        ; handling this button is done
  RTS

up1_button_subroutine:
  LDA paddle1ytop	 ; load into accumulator the top of the paddle
  CMP #TOPWALL+24		 ; if it's above the ceiling, do nothing
  BCC ReadUp1Done  
  STA paddle1ybot
  LDY #$00		 ; RAM address $02xx
moveloop1up:
  LDA $0200, y		 ; load sprite X position
  SEC        		 ; make sure the carry flag is clear
  SBC #$02    		 ; add 2 to accumulator (1x speed)      
  STA $0200, y 		 ; save sprite Y position
  INY
  INY
  INY
  INY			 ; increase x 4 times for 4 attibute bytes per sprite
  CPY #$30		 ; 48 bytes (12 sprites at 4 bytes of attribute each) later than #$00...
  BCC moveloop1up   
  STA paddle1ytop
ReadUp1Done:
  RTS

start1_button_subroutine:
  LDA gamestate
  CMP #STATE_GAMEOVER    ; if it's not game over, check for title screen
  BNE checktitle
  JSR RESET		 ; if it is game over, this is a crude way to just reset the game versus head to title screen
checktitle:
  LDA gamestate
  CMP #STATE_TITLE  	 ; if it's not title screen, do nothing
  BNE ReadStart1Done
  LDA #STATE_PLAYING	 ; if it is title screen, begin play
  STA gamestate
ReadStart1Done
  RTS

select1_button_subroutine:
  RTS

B1_button_subroutine:
  LDA paddle1ytop	 ; load into accumulator the top of the paddle
  CMP #TOPWALL+24		 ; if it's above the ceiling, do nothing
  BCC ReadB1Done  
  STA paddle1ybot
  LDY #$00		 ; RAM address $02xx
moveloop1b:
  LDA $0200, y		 ; load sprite X position
  SEC        		 ; make sure the carry flag is clear
  SBC #$06    		 ; add 6 to accumulator (3x speed)      
  STA $0200, y 		 ; save sprite Y position
  INY
  INY
  INY
  INY			 ; increase x 4 times for 4 attibute bytes per sprite
  CPY #$30		 ; 48 bytes (12 sprites at 4 bytes of attribute each) later than #$00...
  BCC moveloop1b   
  STA paddle1ytop
ReadB1Done:
  RTS

A1_button_subroutine:
  LDA paddle1ybot	 ; load into accumulator the bottom of the paddle
  CMP #BOTTOMWALL	 ; if it's below the floor, do nothing
  BCS ReadA1Done 
  STA paddle1ytop
  LDY #$00		 ; RAM address $02xx
moveloop1a:
  LDA $0200, y		 ; load sprite X position
  CLC        		 ; make sure the carry flag is clear
  ADC #$06    		 ; add 6 to accumulator (3x speed)      
  STA $0200, y 		 ; save sprite Y position
  INY
  INY
  INY
  INY			 ; increase x 4 times for 4 attibute bytes per sprite
  CPY #$30		 ; 48 bytes (12 sprites at 4 bytes of attribute each) later than #$00...
  BCC moveloop1a   
  STA paddle1ybot
ReadA1Done:
  RTS


;-------------------------------------
;Controller 2 Gameplay (STATE_PLAYING)
;-------------------------------------
ReadController2:
  LDA #$01
  STA $4017
  LDA #$00
  STA $4017
  LDX #$08		; 8 increments, one per button
ReadController2Loop:
  LDA $4017
  LSR A    	        ; bit0 -> Carry
  ROL buttons2   	; bit0 <- Carry
  DEX
  BNE ReadController2Loop
  LDA buttons2
  CMP #%00000001
  BEQ jumpright2
  CMP #%00000010
  BEQ jumpleft2
  CMP #%00000100
  BEQ jumpdown2
  CMP #%00001000
  BEQ jumpup2
  CMP #%00010000
  BEQ jumpstart2
  CMP #%00100000
  BEQ jumpselect2
  CMP #%01000000
  BEQ jumpB2
  CMP #%10000000
  BEQ jumpA2
  RTS			

jumpright2:
  JSR right2_button_subroutine
  RTS

jumpleft2:
  JSR left2_button_subroutine
  RTS

jumpdown2:
  JSR down2_button_subroutine
  RTS

jumpup2:
  JSR up2_button_subroutine
  RTS

jumpstart2:
  JSR start2_button_subroutine
  RTS

jumpselect2:
  JSR select2_button_subroutine
  RTS

jumpB2:
  JSR B2_button_subroutine
  RTS

jumpA2:
  JSR A2_button_subroutine
  RTS

right2_button_subroutine:
  LDA paddle2ybot	 ; load into accumulator the bottom of the paddle
  CMP #BOTTOMWALL	 ; if it's below the floor, do nothing
  BCS ReadRight2Done 
  STA paddle2ytop
  LDY #$30		 ; RAM address $02xx
moveloop2right:
  LDA $0200, y		 ; load sprite Y position
  CLC        		 ; make sure the carry flag is clear
  ADC #$04    		 ; add 4 to accumulator (2x speed)      
  STA $0200, y 		 ; save sprite Y position
  INY
  INY
  INY
  INY			 ; increase x 4 times for 4 attibute bytes per sprite
  CPY #$60		 ; 48 bytes (12 sprites at 4 bytes of attribute each) later than #$00...
  BCC moveloop2right   
  STA paddle2ybot
ReadRight2Done: 	 ; handling this button is done
  RTS

left2_button_subroutine:
  LDA paddle2ytop	 ; load into accumulator the top of the paddle
  CMP #TOPWALL+24		 ; if it's above the ceiling, do nothing
  BCC ReadLeft2Done  
  STA paddle2ybot
  LDY #$30		 ; RAM address $02xx
moveloop2left:
  LDA $0200, y		 ; load sprite X position
  SEC        		 ; make sure the carry flag is clear
  SBC #$04    		 ; add 4 to accumulator (2x speed)      
  STA $0200, y 		 ; save sprite Y position
  INY
  INY
  INY
  INY			 ; increase x 4 times for 4 attibute bytes per sprite
  CPY #$60		 ; 48 bytes (12 sprites at 4 bytes of attribute each) later than #$00...
  BCC moveloop2left   
  STA paddle2ytop
ReadLeft2Done:
  RTS

down2_button_subroutine:
  LDA paddle2ybot	 ; load into accumulator the bottom of the paddle
  CMP #BOTTOMWALL	 ; if it's below the floor, do nothing
  BCS ReadDown2Done 
  STA paddle2ytop
  LDY #$30		 ; RAM address $02xx
moveloop2down:
  LDA $0200, y		 ; load sprite Y position
  CLC        		 ; make sure the carry flag is clear
  ADC #$02    		 ; add 2 to accumulator (1x speed)     
  STA $0200, y 		 ; save sprite Y position
  INY
  INY
  INY
  INY			 ; increase x 4 times for 4 attibute bytes per sprite
  CPY #$60		 ; 48 bytes (12 sprites at 4 bytes of attribute each) later than #$00...
  BCC moveloop2down   
  STA paddle2ybot
ReadDown2Done: 	        ; handling this button is done
  RTS

up2_button_subroutine:
  LDA paddle2ytop	 ; load into accumulator the top of the paddle
  CMP #TOPWALL+24		 ; if it's above the ceiling, do nothing
  BCC ReadUp2Done  
  STA paddle2ybot
  LDY #$30		 ; RAM address $02xx
moveloop2up:
  LDA $0200, y		 ; load sprite X position
  SEC        		 ; make sure the carry flag is clear
  SBC #$02    		 ; add 2 to accumulator (1x speed)      
  STA $0200, y 		 ; save sprite Y position
  INY
  INY
  INY
  INY			 ; increase x 4 times for 4 attibute bytes per sprite
  CPY #$60		 ; 48 bytes (12 sprites at 4 bytes of attribute each) later than #$00...
  BCC moveloop2up   
  STA paddle2ytop
ReadUp2Done:
  RTS

start2_button_subroutine:
  LDA gamestate
  CMP #STATE_GAMEOVER
  BNE ReadStart2Done
;  LDA #STATE_PLAYING
;  STA gamestate
  JSR RESET		 ; this is a crude way to just reset the game versus head to title screen
ReadStart2Done
  RTS

select2_button_subroutine:
  RTS

B2_button_subroutine:
  LDA paddle2ytop	 ; load into accumulator the top of the paddle
  CMP #TOPWALL+24		 ; if it's above the ceiling, do nothing
  BCC ReadB2Done  
  STA paddle2ybot
  LDY #$30		 ; RAM address $02xx
moveloop2b:
  LDA $0200, y		 ; load sprite X position
  SEC        		 ; make sure the carry flag is clear
  SBC #$06    		 ; add 6 to accumulator (3x speed)      
  STA $0200, y 		 ; save sprite Y position
  INY
  INY
  INY
  INY			 ; increase x 4 times for 4 attibute bytes per sprite
  CPY #$60		 ; 48 bytes (12 sprites at 4 bytes of attribute each) later than #$00...
  BCC moveloop2b   
  STA paddle2ytop
ReadB2Done:
  RTS

A2_button_subroutine:
  LDA paddle2ybot	 ; load into accumulator the bottom of the paddle
  CMP #BOTTOMWALL	 ; if it's below the floor, do nothing
  BCS ReadA2Done 
  STA paddle2ytop
  LDY #$30		 ; RAM address $02xx
moveloop2a:
  LDA $0200, y		 ; load sprite X position
  CLC        		 ; make sure the carry flag is clear
  ADC #$06    		 ; add 6 to accumulator (3x speed)      
  STA $0200, y 		 ; save sprite Y position
  INY
  INY
  INY
  INY			 ; increase x 4 times for 4 attibute bytes per sprite
  CPY #$60		 ; 48 bytes (12 sprites at 4 bytes of attribute each) later than #$00...
  BCC moveloop2a   
  STA paddle2ybot
ReadA2Done:
  RTS


;--------------
;MAIN GAME CODE
;--------------

RESET:
  SEI 		        ; disable IRQs
  CLD          		; disable decimal mode
  LDX #$40
  STX $4017		; disable APU frame IRQ
  LDX #$FF
  TXS     		; Set up stack
  INX          		; now X = 0
  STX $2000    		; disable NMI
  STX $2001    		; disable rendering
  STX $4010    		; disable DMC IRQs

  JSR vblankwait        ; First wait for vblank to make sure PPU is ready

clrmem:
  LDA #$00
  STA $0000, x
  STA $0100, x
  STA $0200, x		; note that the background tutorials set #$00 to $0300 and #$FE to $0200
  STA $0400, x
  STA $0500, x
  STA $0600, x
  STA $0700, x
  LDA #$FE
  STA $0300, x
  INX
  BNE clrmem

  LDA #$68		; set in RAM initial paddle positions
  STA paddle1ytop
  STA paddle2ytop
  LDA #$87
  STA paddle1ybot
  STA paddle2ybot
   
  JSR vblankwait        ; Second wait for vblank, PPU is ready after this



              
;---------------------------
;Set some initial ball stats
;---------------------------
  LDA #$01
  STA balldown
  STA ballright
  LDA #$00
  STA ballup
  STA ballleft
  
  LDA #$50
  STA bally
  
  LDA #$80
  STA ballx
  
  LDA #$02
  STA ballspeedx
  STA ballspeedy

;-----------------------
;Set initial score value
;-----------------------
  LDA #$00
  STA score1
  STA scoreOnes1
  STA scoreTens1
  STA score2
  STA scoreOnes2
  STA scoreTens2

;-----------------------------
;!!!SET STARTING GAME STATE!!!
;-----------------------------
  LDA #STATE_TITLE
;  LDA #STATE_PLAYING
;  LDA #STATE_GAMEOVER
  STA gamestate


LoadField:
  LDA gamestate
  CMP #STATE_TITLE
  BNE checkgameplay
LoadTitlescreen:
  LDA #%00000000  ;does nothing
  STA $2001       ;does nothing
  JSR titleclrmem ;does nothing
  JSR LoadBackgroundt
  JSR LoadPalettest
  JSR LoadAttributet
checkgameplay:  
  LDA gamestate
  CMP #STATE_PLAYING
  BNE LoadFieldDone
LoadPlayfield:
  JSR LoadBackground
  JSR LoadPalettes
  JSR LoadAttribute
  JSR LoadSprites
LoadFieldDone:

             
  LDA #%10010000  	 ; enable NMI, sprites from Pattern Table 0, background from Pattern Table 1
  STA $2000

  LDA #%00011110   	 ; enable sprites, enable background, no clipping on left side
  STA $2001

  LDA #$00		 ; no background scrolling
  STA $2006
  STA $2006
  STA $2005
  STA $2005

Forever:
  JMP Forever    	 ; jump back to Forever, infinite loop
  

;------------------------------------------------------------------------
;nametable, attributes, palettes, and sprites subroutines (STATE_TITLE)
;------------------------------------------------------------------------
LoadBackgroundt:		; fairly standard code for loading a background but loads dec 1024 bytes instead of the max 960
  LDA gamestate
  CMP #STATE_TITLE
  BNE End2
  LDA $2002
  LDA #$20
  STA $2006
  LDA #$00
  STA $2006
  LDA #LOW(backgroundt)
  STA pointerLo
  LDA #HIGH(backgroundt)
  STA pointerHi
  LDX #$00
  LDY #$00
Loopt:
  LDA [pointerLo], y
  STA $2007
  INY
  CPY #$00
  BNE Loopt
  INC pointerHi
  INX
  CPX #$04
  BNE Loopt
  RTS 

LoadAttributet:
  LDA $2002             ; read PPU status to reset the high/low latch
  LDA #$23
  STA $2006             ; write the high byte of $23C0 address
  LDA #$C0
  STA $2006             ; write the low byte of $23C0 address
  LDX #$00              ; start out at 0
LoadAttributeLoopt:
  LDA attributet, x      ; load data from address (attribute + the value in x)
  STA $2007             ; write to PPU
  INX                   ; X = X + 1
;  CPX #$08             ;  Compare X to hex $08, decimal 8 - copying 8 bytes
  CPX #40		; #$08 is but one row; we've got 8		
  BNE LoadAttributeLoopt  ; Branch to LoadAttributeLoop if compare was Not Equal to zero
                        ; if compare was equal to 128, keep going down
  RTS             

LoadPalettest:
  LDA $2002             ; read PPU status to reset the high/low latch
  LDA #$3F
  STA $2006             ; write the high byte of $3F00 address
  LDA #$00
  STA $2006             ; write the low byte of $3F00 address
  LDX #$00              ; start out at 0
LoadPalettesLoopt:
  LDA palettet, x        ; load data from address (palette + the value in x)
                        ; 1st time through loop it will load palette+0
                        ; 2nd time through loop it will load palette+1
                        ; 3rd time through loop it will load palette+2
                        ; etc
  STA $2007             ; write to PPU
  INX                   ; X = X + 1
  CPX #$20              ; Compare X to hex $10, decimal 16 - copying 16 bytes = 4 sprites
  BNE LoadPalettesLoopt  ; Branch to LoadPalettesLoop if compare was Not Equal to zero
                        ; if compare was equal to 32, keep going down
End2:
  RTS



;------------------------------------------------------------------------
;nametable, attributes, palettes, and sprites subroutines (STATE_PLAYING)
;------------------------------------------------------------------------

LoadBackground:		; fairly standard code for loading a background but loads dec 1024 bytes instead of the max 960
  LDA gamestate
  CMP #STATE_PLAYING
  BNE End1
  LDA $2002
  LDA #$20
  STA $2006
  LDA #$00
  STA $2006
  LDA #LOW(background)
  STA pointerLo
  LDA #HIGH(background)
  STA pointerHi
  LDX #$00
  LDY #$00
Loop:
  LDA [pointerLo], y
  STA $2007
  INY
  CPY #$00
  BNE Loop
  INC pointerHi
  INX
  CPX #$04
  BNE Loop
End1:
  RTS 

LoadAttribute:
  LDA $2002             ; read PPU status to reset the high/low latch
  LDA #$23
  STA $2006             ; write the high byte of $23C0 address
  LDA #$C0
  STA $2006             ; write the low byte of $23C0 address
  LDX #$00              ; start out at 0
LoadAttributeLoop:
  LDA attribute, x      ; load data from address (attribute + the value in x)
  STA $2007             ; write to PPU
  INX                   ; X = X + 1
;  CPX #$08             ;  Compare X to hex $08, decimal 8 - copying 8 bytes
  CPX #40		; #$08 is but one row; we've got 8		
  BNE LoadAttributeLoop  ; Branch to LoadAttributeLoop if compare was Not Equal to zero
                        ; if compare was equal to 128, keep going down
  RTS             

LoadPalettes:
  LDA $2002             ; read PPU status to reset the high/low latch
  LDA #$3F
  STA $2006             ; write the high byte of $3F00 address
  LDA #$00
  STA $2006             ; write the low byte of $3F00 address
  LDX #$00              ; start out at 0
LoadPalettesLoop:
  LDA palette, x        ; load data from address (palette + the value in x)
                        ; 1st time through loop it will load palette+0
                        ; 2nd time through loop it will load palette+1
                        ; 3rd time through loop it will load palette+2
                        ; etc
  STA $2007             ; write to PPU
  INX                   ; X = X + 1
  CPX #$20              ; Compare X to hex $10, decimal 16 - copying 16 bytes = 4 sprites
  BNE LoadPalettesLoop  ; Branch to LoadPalettesLoop if compare was Not Equal to zero
                        ; if compare was equal to 32, keep going down
  RTS

LoadSprites:
  LDX #$00              ; start at 0
LoadSpritesLoop:
  LDA sprites, x        ; load data from address (sprites +  x)
  STA $0200, x          ; store into RAM address ($0200 + x)
  INX                   ; X = X + 1
  CPX #$60              ; Compare X to hex $30, decimal 96 (# of bytes, 12 tiles x 4 bytes per, x2 paddles)
			; (Sprite size for this game is 24x32 pixels, or 3x4=12 tiles, x2 paddles.)
  BNE LoadSpritesLoop   ; Branch to LoadSpritesLoop if compare was Not Equal to zero
                        ; if compare was equal to 48x2 (96), keep going down
  RTS

 
;---
;NMI
;---

NMI:
  LDA #$00
  STA $2003       	 ; set the low byte (00) of the RAM address
  LDA #$02
  STA $4014      	 ; set the high byte (02) of the RAM address, start the transfer

  JSR DrawScore1
  JSR DrawScore2

  ;;This is the PPU clean up section, so rendering the next frame starts properly.
  LDA #%10010000  	 ; enable NMI, sprites from Pattern Table 0, background from Pattern Table 1
  STA $2000
  LDA #%00011110  	 ; enable sprites, enable background, no clipping on left side
  STA $2001
  LDA #$00       	 ; tell the ppu there is no background scrolling
  STA $2006
  STA $2006
  STA $2005
  STA $2005
    
  ;;;all graphics updates done by here, run game engine

LatchController:
  LDA #$01
  STA $4016	  	 ; controller 1 
  STA $4017		 ; controller 2
  LDA #$00
  STA $4016       	 ; tell both the controllers to latch buttons
  STA $4017
  JSR ReadController1	 ; keeps the controller reads in NMI, since you need them each frame
  JSR ReadController2
  
  ;;This is the PPU clean up section, so rendering the next frame starts properly.
  LDA #%10010000   	; enable NMI, sprites from Pattern Table 0, background from Pattern Table 1
  STA $2000
  LDA #%00011110   	; enable sprites, enable background, no clipping on left side
  STA $2001
  LDA #$00        	; tell the ppu there is no background scrolling
  STA $2005
  STA $2005

GameEngine:  
  LDA gamestate
  CMP #STATE_TITLE	;;#$00
  BEQ EngineTitle    	;;game is displaying title screen
    
  LDA gamestate
  CMP #STATE_GAMEOVER	;;#$02
  BEQ EngineGameOver  	;;game is displaying ending events
  
  LDA gamestate
  CMP #STATE_PLAYING	;;#$01
  BEQ EnginePlaying   	;;game is playing
GameEngineDone:  
  
  JSR UpdateSprites	;;set ball/paddle sprites from positions


  RTI             	; return from interrupt
 
;;;;;;;;;;;;;;  

 
EngineTitle:
  ;;if start button pressed
  ;;  turn screen off
  ;;  load game screen
  ;;  set starting paddle/ball position
  ;;  go to Playing State
  ;;  turn screen on
  JMP GameEngineDone

;;;;;;;;; 
 
EngineGameOver:
  ;;if start button pressed
  ;;  turn screen off
  ;;  load title screen
  ;;  go to Title State
  ;;  turn screen on 
  JMP GameEngineDone
 
;;;;;;;;;;;
 
EnginePlaying:

MoveBallRight:
  LDA ballright
  BEQ MoveBallRightDone   ;;if ballright=0, skip this section

  LDA ballx
  CLC
  ADC ballspeedx       	  ;;ballx position = ballx + ballspeedx
  STA ballx

  LDA ballx
  CMP #RIGHTWALL
  BCC MoveBallRightDone   ;;if ball x < right wall, still on screen, skip next section
  LDA #$00
  STA ballright
  LDA #$01
  STA ballleft         	  ;;bounce, ball now moving left
  ;;in real game, give point to player 1, reset ball (see below)
  jsr IncrementScore1
  LDA #$7C
  STA ballx
  STA bally
  LDA #$00
  STA ballleft
  LDA #$01
  STA ballright
MoveBallRightDone:


MoveBallLeft:
  LDA ballleft
  BEQ MoveBallLeftDone    ;;if ballleft=0, skip this section

  LDA ballx
  SEC
  SBC ballspeedx          ;;ballx position = ballx - ballspeedx
  STA ballx

  LDA ballx
  CMP #LEFTWALL
  BCS MoveBallLeftDone    ;;if ball x > left wall, still on screen, skip next section
  LDA #$01
  STA ballright
  LDA #$00
  STA ballleft            ;;bounce, ball now moving right
  ;;in real game, give point to player 2, reset ball (see below)
  jsr IncrementScore2
  LDA #$7C
  STA ballx
  STA bally
  LDA #$00
  STA ballright
  LDA #$01
  STA ballleft
MoveBallLeftDone:


MoveBallUp:
  LDA ballup
  BEQ MoveBallUpDone      ;;if ballup=0, skip this section

  LDA bally
  SEC
  SBC ballspeedy          ;;bally position = bally - ballspeedy
  STA bally

  LDA bally
  CMP #TOPWALL
  BCS MoveBallUpDone      ;;if ball y > top wall, still on screen, skip next section
  LDA #$01
  STA balldown
  LDA #$00
  STA ballup         	  ;;bounce, ball now moving down
MoveBallUpDone:


MoveBallDown:
  LDA balldown
  BEQ MoveBallDownDone    ;;if ballup=0, skip this section

  LDA bally
  CLC
  ADC ballspeedy          ;;bally position = bally + ballspeedy
  STA bally

  LDA bally
  CMP #BOTTOMWALL
  BCC MoveBallDownDone    ;;if ball y < bottom wall, still on screen, skip next section
  LDA #$00
  STA balldown
  LDA #$01
  STA ballup         	  ;;bounce, ball now moving down
MoveBallDownDone:


CheckPaddle1Collision: ;checks for collision coming from the right only
  LDA ballx 
  CMP #PADDLE1X + PADDLE_WIDTH
  BCS CheckPaddle1CollisionDone 	; if ballx > PADDLE1X, there's no collision with the paddle
  LDA bally                     	; otherwise, check if it's actually on the paddle
  CMP paddle1ytop              		; if bally < paddle1ytop, it's above the paddle, so no collision
  BCC CheckPaddle1CollisionDone
  CMP paddle1ybot               	; if bally > paddle1ybot, it's below the paddle, so no collision
  BCS CheckPaddle1CollisionDone
  LDA #FALSE                      	; if we get here, it was a collision, so we switch direction
  STA ballleft
  LDA #TRUE
  STA ballright

CheckPaddle1CollisionDone:  		; checks for collision coming from the left only
  LDA ballx
  CMP #PADDLE2X - SPRITE_SIZE + 1
  BCC CheckPaddle2CollisionDone 	; if ballx < PADDLE2X, there's no collision with the paddle
  LDA bally
  CMP paddle2ytop
  BCC CheckPaddle2CollisionDone 	; if ballY < paddle2ytop, it's above the paddle, so no collision
  CMP paddle2ybot             
  BCS CheckPaddle2CollisionDone 	;i f ballY > paddle2ybot, it's below the paddle, so no collision
  LDA #FALSE
  STA ballright
  LDA #TRUE
  STA ballleft
  CheckPaddle2CollisionDone:


  JMP GameEngineDone
 
 
 
 
UpdateSprites:
  LDA bally  		  ;;update all ball sprite info
  STA $0280		  ; makes room for longer paddles if desired
  
  LDA #$0D		  ; PPU tile for sprite
  STA $0281
  
  LDA #$00
  STA $0282
  
  LDA ballx
  STA $0283
  
  ;;update paddle sprites
  RTS
 
 
DrawScore1:
  LDA $2002
  LDA #$20
  STA $2006
  LDA #$4D
  STA $2006           ; start drawing the p1 score at PPU $204D
  LDA scoreTens1      ; next digit
  STA $2007
  LDA scoreOnes1      ; last digit
  STA $2007
  LDA score1
  CMP #$03	      ; play to 15
  BNE DrawScore1Done
  JSR DrawWin1
  LDA #STATE_GAMEOVER
  STA gamestate
DrawScore1Done:
  RTS
 
DrawScore2:
  LDA $2002
  LDA #$20
  STA $2006
  LDA #$51
  STA $2006           ; start drawing the p2 score at PPU $2051
  LDA scoreTens2      ; next digit
  STA $2007
  LDA scoreOnes2      ; last digit
  STA $2007
  LDA score2
  CMP #$03	      ; play to 15	
  BNE DrawScore2Done
  JSR DrawWin2
  LDA #STATE_GAMEOVER
  STA gamestate
DrawScore2Done:
  RTS
 
IncrementScore1:
  LDA score1
  CLC
  ADC #$01
  STA score1
IncOnes1:
  LDA scoreOnes1      ; load the lowest digit of the number
  CLC 
  ADC #$01           ; add one
  STA scoreOnes1
  CMP #$0A           ; check if it overflowed, now equals 10
  BNE IncDone1        ; if there was no overflow, all done
IncTens1:
  LDA #$00
  STA scoreOnes1      ; wrap digit to 0
  LDA scoreTens1      ; load the next digit
  CLC 
  ADC #$01           ; add one, the carry from previous digit
  STA scoreTens1
IncDone1:
  RTS		     ; not having this RTS will crash the game!
 
IncrementScore2:
  LDA score2
  CLC
  ADC #$01
  STA score2
IncOnes2:
  LDA scoreOnes2      ; load the lowest digit of the number
  CLC 
  ADC #$01           ; add one
  STA scoreOnes2
  CMP #$0A           ; check if it overflowed, now equals 10
  BNE IncDone2        ; if there was no overflow, all done
IncTens2:
  LDA #$00
  STA scoreOnes2      ; wrap digit to 0
  LDA scoreTens2      ; load the next digit
  CLC 
  ADC #$01           ; add one, the carry from previous digit
  STA scoreTens2
IncDone2:
  RTS 

 
;========        
;========
;BANK ONE    
;========
;========
  .bank 1
  .org $E000

;--------------------------------------
;sprites and background (STATE_PLAYING)
;--------------------------------------
palette:
  .db $0F,$0F,$0F,$30,  $0F,$30,$02,$2A,  $0F,$30,$02,$0A,  $0F,$30,$02,$11 ; background palette
;use $0F,$30,$02,$16 as a good score palette

  .db $0F,$0A,$2A,$30,  $0F,$0A,$2a,$11,  $0F,$0A,$2a,$17,  $0F,$0A,$2a,$04 ; sprite palette

;$0F = black ;$0A = dark green ;$2A = green ;$30 = white
;$11 = blue ;$04 = purple ;$17 = orange ;$16 = red
;black, dark green, green (can't do red), white (0)
;black, dark green, green, blue (1)
;black, dark green, green, orange (2)
;black, dark green, green, purple (3)
;MISSING: A red to differentiate Migs from Rafa.

sprites:
     		;vert tile attr horiz
  .db PADDLE1YINIT, $00, $01, PADDLE1X-$10  		; sprite 00; RAM $0200; p1; check tile numbers and palette colors
  .db PADDLE1YINIT, $01, $01, PADDLE1X-$08 		; sprite 01; RAM $0204
  .db PADDLE1YINIT, $02, $00, PADDLE1X   		; sprite 02; RAM $0208
  .db PADDLE1YINIT+$08, $03, $00, PADDLE1X-$10   	; sprite 03; RAM $020C
  .db PADDLE1YINIT+$08, $04, $01, PADDLE1X-$08   	; sprite 04; RAM $0210
  .db PADDLE1YINIT+$08, $05, $00, PADDLE1X   		; sprite 05; RAM $0214
  .db PADDLE1YINIT+$10, $06, $02, PADDLE1X-$10   	; sprite 06; RAM $0218
  .db PADDLE1YINIT+$10, $07, $02, PADDLE1X-$08   	; sprite 07; RAM $021C
  .db PADDLE1YINIT+$10, $08, $00, PADDLE1X   		; sprite 08; RAM $0220
  .db PADDLE1YINIT+$18, $09, $00, PADDLE1X-$10   	; sprite 09; RAM $0224
  .db PADDLE1YINIT+$18, $0A, $02, PADDLE1X-$08   	; sprite 10; RAM $0228
  .db PADDLE1YINIT+$18, $0B, $00, PADDLE1X   		; sprite 11; RAM $022C
; .db PADDLE1YINIT-$08, $0C, $80, PADDLE1X   		; sprite 24; RAM $0260 (not optimized)flipped vertically
; .db PADDLE1YINIT+$20, $0C, $00, PADDLE1X   		; sprite 25; RAM $0268 (not optimized)

  .db PADDLE2YINIT, $02, $40, PADDLE2X-$10   		; sprite 12; RAM $0230; p2; check tile numbers and palette colors
  .db PADDLE2YINIT, $01, $42, PADDLE2X-$08   		; sprite 13; RAM $0234; 64 = flip sprite horizontally
  .db PADDLE2YINIT, $00, $42, PADDLE2X   		; sprite 14; RAM $0238; using same sprite tiles as p1!!!
  .db PADDLE2YINIT+$08, $05, $40, PADDLE2X-$10   	; sprite 15; RAM $023C
  .db PADDLE2YINIT+$08, $04, $42, PADDLE2X-$08   	; sprite 16; RAM $0240
  .db PADDLE2YINIT+$08, $03, $40, PADDLE2X   		; sprite 17; RAM $0244
  .db PADDLE2YINIT+$10, $08, $40, PADDLE2X-$10   	; sprite 18; RAM $0248
  .db PADDLE2YINIT+$10, $07, $43, PADDLE2X-$08   	; sprite 19; RAM $024C
  .db PADDLE2YINIT+$10, $06, $43, PADDLE2X   		; sprite 20; RAM $0250
  .db PADDLE2YINIT+$18, $0B, $40, PADDLE2X-$10   	; sprite 21; RAM $0254
  .db PADDLE2YINIT+$18, $0A, $43, PADDLE2X-$08   	; sprite 22; RAM $0258
  .db PADDLE2YINIT+$18, $09, $40, PADDLE2X   		; sprite 23; RAM $025C
; .db PADDLE2YINIT-$08, $0C, $80, PADDLE2X   		; sprite 26; RAM $0270 (not optimized)flipped vertically
; .db PADDLE2YINIT+$20, $0C, $00, PADDLE2X   		; sprite 27; RAM $0278 (not optimized)


background:
  .db $24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24  ;; row 1 - left half - PAL
  .db $24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24  ;; row 1 - right half - PAL
  .db $2D,$2C,$2D,$2C,$F8,$2C,$2D,$2C,$2D,$2C,$2D,$2C,$2D,$2C,$2D,$30  ;; row 2
  .db $31,$2C,$2D,$2C,$2D,$2C,$2D,$2C,$2D,$2C,$2D,$2C,$2D,$2C,$2D,$2C  
  .db $24,$24,$15,$0E,$18,$17,$24,$22,$24,$16,$12,$10,$24,$24,$24,$30  ;; row 3 - Leon y Mig; Rafa y Don
  .db $31,$24,$24,$24,$1B,$0A,$0F,$0A,$24,$22,$24,$0D,$18,$17,$24,$24  
  .db $24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$30  ;; row 4
  .db $31,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24  
  .db $24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$30  ;; row 5
  .db $31,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24  
  .db $24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$30  ;; row 6
  .db $31,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24  
  .db $24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$30  ;; row 7
  .db $31,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24  
  .db $24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$30  ;; row 8
  .db $31,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24  
  .db $24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$30  ;; row 1 - left half
  .db $31,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24  ;; row 1 - right half
  .db $24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$30  ;; row 2
  .db $31,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24  
  .db $24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$30  ;; row 3
  .db $31,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24  
  .db $24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$30  ;; row 4
  .db $31,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24  
  .db $24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$30  ;; row 5
  .db $31,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24  
  .db $24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$30  ;; row 6
  .db $31,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24  
  .db $24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$30  ;; row 7
  .db $31,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24  
  .db $24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$30  ;; row 8
  .db $31,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24  
  .db $24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$30  ;; row 1 - left half
  .db $31,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24  ;; row 1 - right half
  .db $24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$30  ;; row 2
  .db $31,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24  
  .db $24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$30  ;; row 3
  .db $31,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24  
  .db $24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$30  ;; row 4
  .db $31,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24  
  .db $24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$30  ;; row 5
  .db $31,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24  
  .db $24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$30  ;; row 6
  .db $31,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24  
  .db $24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$30  ;; row 7
  .db $31,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24  
  .db $24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$30  ;; row 8
  .db $31,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24 
  .db $24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$30  ;; row 1 - left half
  .db $31,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24  ;; row 1 - right half
  .db $24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$30  ;; row 2
  .db $31,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24  
  .db $24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$30  ;; row 3
  .db $31,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24  
  .db $24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$30  ;; row 4
  .db $31,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24  
  .db $2F,$2E,$2F,$2E,$2F,$2E,$2F,$2E,$2F,$2E,$2F,$2E,$2F,$2E,$2F,$30  ;; row 5
  .db $31,$2E,$2F,$2E,$2F,$2E,$2F,$2E,$2F,$2E,$2F,$2E,$2F,$2E,$2F,$2E  
  .db $24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24  ;; row 6 - PAL
  .db $24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24  

attribute:
  .db %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000
  .db %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000
  .db %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000
  .db %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000
  .db %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000
  .db %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000
  .db %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000
  .db %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000

;--------------------------------------
;sprites and background (STATE_TITLE)
;--------------------------------------
palettet:
  .db $0F,$0A,$2a,$30,  $0F,$0A,$2a,$30,  $0F,$0A,$2a,$30,  $0F,$0A,$2a,$30 ; background palette

  .db $0F,$0A,$2A,$30,  $0F,$0A,$2a,$11,  $0F,$0A,$2a,$17,  $0F,$0A,$2a,$04 ; sprite palette
;$0F = black; ;$0A = dark green ;$2A = green ;$30 = white
;$11 = blue ;$04 = purple ;$17 = orange ;$16 = red

backgroundt:
  .db $24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24  ;;row 1 - left half - PAL
  .db $24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24  ;;row 1 - right half - PAL
  .db $2d,$2c,$2d,$2c,$2d,$2c,$2d,$2c,$2d,$2c,$2d,$2c,$2d,$2c,$2d,$30  ;;row 2
  .db $31,$2c,$2d,$2c,$2d,$2c,$2d,$2c,$2d,$2c,$2d,$2c,$2d,$2c,$2d,$2c  
  .db $24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$30  ;;row 3
  .db $31,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24  
  .db $24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$30  ;;row 4
  .db $31,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24  
  .db $24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$30  ;;row 5
  .db $31,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24  
  .db $24,$24,$24,$24,$24,$24,$24,$4a,$4b,$4c,$4d,$4e,$4f,$50,$51,$52  ;;row 6
  .db $53,$54,$55,$56,$57,$58,$59,$5a,$5b,$5c,$5d,$5e,$5f,$60,$24,$24  
  .db $24,$24,$24,$24,$24,$24,$24,$61,$62,$63,$64,$65,$66,$67,$68,$69  ;;row 7
  .db $6a,$6b,$6c,$6d,$6e,$6f,$70,$71,$72,$73,$74,$75,$76,$77,$24,$24  
  .db $24,$24,$24,$24,$24,$24,$24,$78,$79,$7a,$7b,$7c,$7d,$7e,$7f,$80  ;;row 8
  .db $81,$82,$83,$84,$85,$86,$87,$88,$89,$8a,$8b,$8c,$8d,$8e,$24,$24  
  .db $24,$24,$24,$24,$24,$24,$24,$8f,$90,$91,$92,$93,$94,$95,$96,$97  ;;row 9
  .db $98,$99,$9a,$9b,$9c,$9d,$9e,$9f,$a0,$a1,$a2,$a3,$24,$24,$24,$24  
  .db $24,$24,$24,$24,$24,$a4,$a5,$a6,$a7,$a8,$a9,$aa,$ab,$ac,$ad,$ae  ;;row 10
  .db $af,$b0,$b1,$b2,$b3,$b4,$b5,$b6,$b7,$b8,$b9,$ba,$24,$24,$24,$24  
  .db $24,$24,$24,$24,$24,$bb,$bc,$bd,$be,$bf,$c0,$c1,$c2,$c3,$c4,$c5  ;;row 11
  .db $c6,$c7,$c8,$c9,$ca,$cb,$cc,$cd,$ce,$cf,$d0,$d1,$24,$24,$24,$24  
  .db $24,$24,$24,$24,$24,$d2,$d3,$d4,$d5,$d6,$d7,$d8,$d9,$da,$db,$dc  ;;row 12
  .db $dd,$de,$df,$e0,$e1,$e2,$e3,$e4,$e5,$e6,$e7,$e8,$24,$24,$24,$24  
  .db $24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24  ;;row 13
  .db $24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24  
  .db $24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$30  ;;row 14
  .db $31,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24  
  .db $24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$30  ;;row 15
  .db $31,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24  
  .db $24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$30  ;;row 16 
  .db $31,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24  
  .db $24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24  ;;row 17
  .db $24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24  
  .db $24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$19,$1e,$15,$1c,$0e,$24  ;;row 18 - pulse start
  .db $24,$1c,$1d,$0a,$1b,$1d,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24  
  .db $24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24  ;;row 19
  .db $24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24  
  .db $24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$30  ;;row 20
  .db $31,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24  
  .db $24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$30  ;;row 21
  .db $31,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24  
  .db $24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$30  ;;row 22
  .db $31,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24  
  .db $24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$30  ;;row 23
  .db $31,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24  
  .db $24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$30  ;;row 24
  .db $31,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24 
  .db $24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$30  ;;row 25 - left half
  .db $31,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24  ;;row 25 - right half
  .db $24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$30  ;;row 26
  .db $31,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24  
  .db $24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24  ;;row 27
  .db $24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24  
  .db $24,$24,$24,$24,$0a,$24,$F6,$F5,$F6,$F5,$24,$0d,$18,$1e,$0b,$15  ;;row 28 - a 2020 double z homebrew
  .db $0e,$24,$23,$24,$11,$18,$F3,$0E,$0B,$1b,$0e,$20,$24,$24,$24,$24  
  .db $2F,$2E,$2F,$2E,$2F,$2E,$2F,$2E,$2F,$2E,$2F,$2E,$2F,$2E,$2F,$2E  ;;row 29
  .db $2F,$2E,$2F,$2E,$2F,$2E,$2F,$2E,$2F,$2E,$2F,$2E,$2F,$2E,$2F,$2E  
  .db $24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24  ;;row 30 - PAL
  .db $24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24  



attributet:
;1 row per row in the background 32x32 pixel grid (4x4 tiles consisting of 4 2x2s) - see Nerdy Nights week 6
;8x8 = 64 bytes
  .db %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000
  .db %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000
  .db %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000
  .db %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000
  .db %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000
  .db %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000
  .db %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000
  .db %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000



  .org $FFFA     	    ;first of the three vectors starts here
  .dw NMI        	    ;when an NMI happens (once per frame if enabled) the 
                  	    ;processor will jump to the label NMI:
  .dw RESET      	    ;when the processor first turns on or is reset, it will jump
                   	    ;to the label RESET:
  .dw 0          	    ;external interrupt IRQ is not used in this tutorial
  
  
;========
;========
;BANK TWO
;========
;========  
  .bank 2
  .org $0000
  .incbin "tortugas.chr"    ;modified 8KB graphics file, originally from SMB1
  
I've further optimized the code, and have the title screen inside the gameplay code. When a player wins, Start resets to gameplay mode. The title screen only appears upon first hard reset, which is fine. But... I can't get sprites to disappear just yet or the two backgrounds to not draw, despite a likely improperly worded branching function. Any more advice I can steal from ya?

User avatar
Controllerhead
Posts: 147
Joined: Tue Nov 13, 2018 4:58 am
Location: $4016
Contact:

Re: [Help Request] Homebrew Title Screen Code

Post by Controllerhead » Fri Jul 31, 2020 2:38 pm

eskayelle wrote:
Fri Jul 31, 2020 2:11 pm
Any more advice I can steal from ya?
Yeah. Zip and link your source code folder! =p

Are you using a step through debugger?
Image

User avatar
eskayelle
Posts: 22
Joined: Wed Jul 29, 2020 5:07 pm
Contact:

Re: [Help Request] Homebrew Title Screen Code

Post by eskayelle » Fri Jul 31, 2020 2:50 pm

FCEUX, but I'm admittedly not the greatest with it just yet.

Here's my up-to-date CHR and ASM.

It seems like there are some nasty little shortcuts I'm taking with the gamestates which aren't boding well, as I'm currently using them as workarounds while I figure out how to get the screen to blank and load the "next" screen (i.e., title to playing field). The #%00000000 to $2001 didn't work, but I'm imagining I just have it in the wrong place.

Thanks for putting up with my learning curve!

User avatar
Controllerhead
Posts: 147
Joined: Tue Nov 13, 2018 4:58 am
Location: $4016
Contact:

Re: [Help Request] Homebrew Title Screen Code

Post by Controllerhead » Fri Jul 31, 2020 3:03 pm

I'm not seeing any sprites besides the ball with that build...
Image
Image

Post Reply