Skip navigation
Welcome, Guest! Please Login or Join

Loading...

Nerdy Nights week 5 multiple sprites, reading controllers, more instructions

Sep 27, 2012 at 12:16:47 PM
bunnyboy (81)
avatar
(Funktastic B) < Bowser >
Posts: 7474 - Joined: 02/28/2007
California
Profile
The A accumulator only holds 8 bits. If you do LDA twice in a row, the first one is overwritten. So the first 3x LDA are ignored when you do the last LDA $020F, and the same value gets written to $0203/$0207/$020B/$020F.

Sep 27, 2012 at 3:06:55 PM
The Adventurer (0)
avatar
(James Purcell) < Cherub >
Posts: 7 - Joined: 09/27/2012
Connecticut
Profile
Originally posted by: bunnyboy

The A accumulator only holds 8 bits. If you do LDA twice in a row, the first one is overwritten. So the first 3x LDA are ignored when you do the last LDA $020F, and the same value gets written to $0203/$0207/$020B/$020F.

Ah. Okay that makes sense.


Oct 17, 2012 at 9:13:30 AM
jarrodparkes (0)
avatar
(Jarrod Parkes) < Little Mac >
Posts: 62 - Joined: 09/13/2012
Alabama
Profile
I can't get next to a debugger at the moment, but I hoped this question might have a quick answer.

If directives like the following are handled first by the assembler like "C pre-processor directives", then will each piece of data be stored off in memory prior to the first line of opcode being executed? Additionally, if that is the case, wouldn't the assembler be generating similar machine code to handle the initial storage of data in .db directives? If so, is there ever a need to worry about the time taken for those operations?

sprites:
;vert tile attr horiz
.db $80, $32, $00, $80 ;sprite 0
.db $80, $33, $00, $88 ;sprite 1
.db $88, $34, $00, $80 ;sprite 2
.db $88, $35, $00, $88 ;sprite 3


Edited: 10/17/2012 at 09:15 AM by jarrodparkes

Oct 17, 2012 at 10:07:21 AM
removed04092017 (0)
This user has been banned -- click for more information.
< Bowser >
Posts: 7316 - Joined: 12/04/2010
Other
Profile
Nope. The data goes in to the ROM how you set it up. Imagine this as assembly:

Code:
LDA #$Whatever
JMP .NextCode
CodeData: .db $00,$00
.NextCode
STA Wherever
RTS

That would be compiled in the order it is put in. First two commands, then come data, then two more commands. It does not optimize anything for you, you have to do that by managing the data and program yourself.

And the speed for all the instructions can be found online. Minimum is two, maximum is 7 CPU clocks. LDA #$00 is 2 clocks for example, while a more complex instruction like LDA [$20],Y would take 5 (or 6 if a page is crossed).

Oct 17, 2012 at 10:18:06 AM
jarrodparkes (0)
avatar
(Jarrod Parkes) < Little Mac >
Posts: 62 - Joined: 09/13/2012
Alabama
Profile
I'm not sure I am following. In the controller.asm example the following code is used...

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)

The "palette" label is defined near the bottom of the assembly file. Also, right before the label, the directive is given to start loading data/instructions into memory location $E000. For the above execution to work as intended, I'm guessing the assembler would have to ensure that all the palette data has been stored in memory locations starting at $E000 prior to execution?

Oct 17, 2012 at 10:46:26 AM
MODERATOR
KHAN Games (88)
avatar
(Kevin Hanley) < Master Higgins >
Posts: 7760 - Joined: 06/21/2007
Florida
Profile
It is just pulling data from the "palette" data map right at that moment. Nothing is stored in memory beforehand.


Edited: 10/17/2012 at 10:46 AM by KHAN Games

Oct 17, 2012 at 10:51:35 AM
jarrodparkes (0)
avatar
(Jarrod Parkes) < Little Mac >
Posts: 62 - Joined: 09/13/2012
Alabama
Profile
So is data ever getting stored in those locations (the ones at $E000)? If so, when? Or is this all hindering on some sort of pseudo-state of storage?


Edited: 10/17/2012 at 10:51 AM by jarrodparkes

Oct 17, 2012 at 12:13:42 PM
Mario's Right Nut (350)
avatar
(Cunt Punch) < Bowser >
Posts: 6574 - Joined: 11/21/2008
Texas
Profile
??

It's only stored when you do a STA command.


...unless it's the ROM, that is.

-------------------------

This is my shiny thing, and if you try to take it off me, I may have to eat you.

Check out my dev blog.


Oct 17, 2012 at 12:24:58 PM
jarrodparkes (0)
avatar
(Jarrod Parkes) < Little Mac >
Posts: 62 - Joined: 09/13/2012
Alabama
Profile
$E000 falls into the range of 32KB cartridge ROM. So are the .DB directives seen below "storing" those values beforehand, so that when the LoadPalette's label is hit it can retrieve those values?

.bank 1
.org $E000
palette:
.db $0F,$31,$32,$33,$34,$35,$36,$37,$38,$39,$3A,$3B,$3C,$3D,$3E,$0F
.db $0F,$1C,$15,$14,$31,$02,$38,$3C,$0F,$1C,$15,$14,$31,$02,$38,$3C


Oct 17, 2012 at 12:43:41 PM
removed04092017 (0)
This user has been banned -- click for more information.
< Bowser >
Posts: 7316 - Joined: 12/04/2010
Other
Profile
No, this is not like C where you have to TELL the preprocessor that a function will come up sometime later in the program and what type and what variables it needs. I reread it and that makes sense what you're asking now. But yes, if you use hardcoded values and not labels, then yes you need to make sure the ROM data at $E000 is the palette. If you use labels though, it keeps "track" of everything for you and you don't need to do anything. And technically it's "storing" the values, but it's not doing it before hand. ROM is programmed with that data, it just puts it there. And you can access any part of the ROM (In the 32KB range) at any time, but yeah in that program it uses it. But if you're talking about $3F00 for the palette, that's on the PPU.


Edited: 10/17/2012 at 03:26 PM by removed04092017

Oct 17, 2012 at 1:46:26 PM
jarrodparkes (0)
avatar
(Jarrod Parkes) < Little Mac >
Posts: 62 - Joined: 09/13/2012
Alabama
Profile
Thanks for all the help. I think I am turning the corner on this concept now.

I'm going to try to summarize, please tweak if necessary:
The assembler has already assembled those values of the palette into ROM, so when the .NES is executing it can access them. Thus, the palette values are not "stored" during execution, but have already been placed in the correct memory addresses via assembling/compiling.


Edited: 10/17/2012 at 01:46 PM by jarrodparkes

Oct 17, 2012 at 3:13:30 PM
bunnyboy (81)
avatar
(Funktastic B) < Bowser >
Posts: 7474 - Joined: 02/28/2007
California
Profile
Thats right, anything that is ".db" is in ROM so there is no load time.

Oct 15, 2013 at 5:18:31 AM
MODERATOR
Vectrex28 (120)
avatar
(A Metroid) < Bowser >
Posts: 7149 - Joined: 07/28/2012
Switzerland
Profile

I managed to move my little dude in all 4 directions, but the screen is garbled! My code is as follows...
  .inesprg 1 ; 1x 16KB PRG code 
  .ineschr 1 ; 1x 8KB CHR data 
  .inesmap 0 ; mapper 0 = NROM, no bank swapping 
  .inesmir 1 ; background mirroring 
 
 
;;;;;;;;;;;;;;; 
 
 
  .bank 0 
  .org $C000 
RESET: 
  SEI 
  CLD 
  LDX #$40 
  STX $4017 
  LDX #$FF 
  TXS 
  INX 
  STX $2000 
  STX $2001 
  STX $4010 
 
vblankwait1: 
  BIT $2002 
  BPL vblankwait1 
 
clrmem: 
  LDA #$00 
  STA $0000, x 
  STA $0100, x 
  STA $0300, x 
  STA $0400, x 
  STA $0500, x 
  STA $0600, x 
  STA $0700, x 
  LDA #$FE 
  STA $0200, x 
  INX 
  BNE clrmem 
 
vblankwait2: 
  BIT $2002 
  BPL vblankwait2 
 
 
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 
LoadPalettesLoop: 
  LDA palette, x ;load palette byte 
  STA $2007 ;write to PPU 
  INX ;set index to next byte 
  CPX #$20 
  BNE LoadPalettesLoop ;if x = $20, 32 bytes copied, all done 
 
 
load_sprite_data: 
 
  LDX #$00 
 
.loop: 
  LDA data, x 
  STA $0200, x 
  INX 
  CPX #$FF 
  BNE .loop 
 
RTS 
 
  LDA #%10000000 ; enable NMI, sprites from Pattern Table 1 
  STA $2000 
  LDA #%00010000 ; enable sprites 
  STA $2001 
 
Forever: 
  JMP Forever ;jump back to Forever, infinite loop 
 
 
 
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 
 
 
LatchController: 
  LDA #$01 
  STA $4016 
  LDA #$00 
  STA $4016 ; tell both the controllers to latch buttons 
 
ReadA: 
  LDA $4016       ; player 1 - A
  AND #%00000001  ; only look at bit 0
  BEQ ReadADone   ; branch to ReadADone if button is NOT pressed (0)
ReadADone:
ReadB: 
  LDA $4016       ; player 1 - A
  AND #%00000001  ; only look at bit 0
  BEQ ReadBDone   ; branch to ReadADone if button is NOT pressed (0)
ReadBDone:
ReadSe: 
  LDA $4016       ; player 1 - A
  AND #%00000001  ; only look at bit 0
  BEQ ReadSeDone   ; branch to ReadADone if button is NOT pressed (0)
ReadSeDone:
ReadSt: 
  LDA $4016       ; player 1 - A
  AND #%00000001  ; only look at bit 0
  BEQ ReadStDone   ; branch to ReadADone if button is NOT pressed (0)
ReadStDone:
ReadD: 
  LDA $4016 ; dans l'ordre - A,B,Se,St,H,B,G,D 
  AND #%00000001 
  BEQ ReadDDone 
 
  LDA $0200 
  SEC 
  SBC #$01 
  STA $0200 
  LDA $0204 
  SEC 
  SBC #$01 
  STA $0204 
  LDA $0208 
  SEC 
  SBC #$01 
  STA $0208 
  LDA $020C 
  SEC 
  SBC #$01 
  STA $020C 
ReadDDone: 
 
 
ReadU: 
  LDA $4016 ; dans l'ordre - A,B,Se,St,H,B,G,D 
  AND #%00000001 
  BEQ ReadUDone 
  LDA $0200 
  CLC 
  ADC #$01 
  STA $0200 
  LDA $0204 
  CLC 
  ADC #$01 
  STA $0204 
  LDA $0208 
  CLC 
  ADC #$01 
  STA $0208 
  LDA $020C 
  CLC 
  ADC #$01 
  STA $020C 
ReadUDone: 
 
  LDA $4016 ; dans l'ordre - A,B,Se,St,H,B,G,D 
  AND #%00000001 
  BEQ ReadLDone 
 
  LDA $0203 
  SEC 
  SBC #$01 
  STA $0203 
  LDA $0207 
  SEC 
  SBC #$01 
  STA $0207 
  LDA $020B 
  SEC 
  SBC #$01 
  STA $020B 
  LDA $020F 
  SEC 
  SBC #$01 
  STA $020F 
ReadLDone: 
  LDA $4016 ; dans l'ordre - A,B,Se,St,H,B,G,D 
  AND #%00000001 
  BEQ ReadRDone 
  LDA $0203 
  CLC 
  ADC #$01 
  STA $0203 
  LDA $0207 
  CLC 
  ADC #$01 
  STA $0207 
  LDA $020B 
  CLC 
  ADC #$01 
  STA $020B 
  LDA $020F 
  CLC 
  ADC #$01 
  STA $020F 
ReadRDone: 
 
RTI 
 
;;;;;;;;;;;;;; 
 
 
 
  .bank 1 
  .org $E000 
palette: 
  .db $0F,$29,$37,$3D,$0F,$35,$36,$37,$0F,$39,$3A,$3B,$0F,$3D,$3E,$0F 
  .db $0F,$29,$37,$3D,$0F,$02,$38,$3C,$0F,$1C,$15,$14,$0F,$02,$38,$3C 
 
data: 
  .db $80,$00,$00,$80,$80,$01,$00,$88,$88,$02,$00,$80,$88,$03,$00,$88 
  .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 2 
  .org $0000 
  .incbin "mario.chr" ;includes 8KB graphics file from SMB1


Edited: 10/15/2013 at 10:25 AM by Vectrex28

Oct 15, 2013 at 8:54:45 AM
removed04092017 (0)
This user has been banned -- click for more information.
< Bowser >
Posts: 7316 - Joined: 12/04/2010
Other
Profile
Well, when you don't set the screen up in any way, you expect it to be right? Also, don't read straight off of $4016.

Oct 15, 2013 at 10:26:32 AM
MODERATOR
Vectrex28 (120)
avatar
(A Metroid) < Bowser >
Posts: 7149 - Joined: 07/28/2012
Switzerland
Profile
 
Never mind. I got it now!


Edited: 10/15/2013 at 10:34 AM by Vectrex28

Apr 23, 2014 at 1:56:57 AM
Dreadmoc (18)
avatar
(Iron Worker) < Eggplant Wizard >
Posts: 314 - Joined: 03/02/2013
Colorado
Profile
How do you know the location of each sprite. I gathered 203 from from reading the code, but I can't seem to find 207, 20b, or 20f anywhere.

I wanted to do the "homework" on my own as best I could, but I had to read through the thread to figure out the location of the other three sprites. How would I locate them on my own?

-------------------------

            

Apr 23, 2014 at 8:11:22 AM
Mega Mario Man (58)
avatar
(Tim ) < Kraid Killer >
Posts: 2251 - Joined: 02/13/2014
Nebraska
Profile
Originally posted by: Dread

How do you know the location of each sprite. I gathered 203 from from reading the code, but I can't seem to find 207, 20b, or 20f anywhere.

I wanted to do the "homework" on my own as best I could, but I had to read through the thread to figure out the location of the other three sprites. How would I locate them on my own?

Sprite data starts at $0200 and the address is increased by 1 for each byte afterwards. Each sprite needs 4 bytes of data and is loaded in this order:
1. Vertical Position
2. Tile Number
3. Sprite Attribute
4. Horizontal Position

If you look at the sprites section, you will see this.

sprites:
     ;vert tile attr horiz
  .db $80, $32, $00, $80   ;sprite 0
  .db $80, $33, $00, $88   ;sprite 1
  .db $88, $34, $00, $80   ;sprite 2
  .db $88, $35, $00, $88   ;sprite 3

So, the first sprite would load like this:
SPRITE 0
1. Vertical Position       =$0200
2. Tile Number             =$0201
3. Sprite Attribute         =$0202
4. Horizontal Position   =$0203

After Sprite 0 loads, the sprite loading loop will continue on to the next sprite (if the loop is set for loading more sprite data). So this:

     ;vert tile attr horiz
  .db $80, $32, $00, $80   ;sprite 0
  .db $80, $33, $00, $88   ;sprite 1
  .db $88, $34, $00, $80   ;sprite 2
  .db $88, $35, $00, $88   ;sprite 3

Will load like this:
    vert        tile       attr    horiz
 $0200, $0201, $0202, $0203   ;sprite 0
 $0204, $0205, $0206, $0207   ;sprite 1
 $0208, $0209, $020A, $020B   ;sprite 2
 $020C, $020D, $020E, $020F   ;sprite 3

-------------------------
Current Project
Isometric Survival Horror

Older Projects
Tailgate Party, Power Pad Demo, Happy Hour

Links
Store, Facebook, Twitter


Edited: 04/23/2014 at 10:56 AM by Mega Mario Man

Apr 23, 2014 at 10:22:27 AM
Dreadmoc (18)
avatar
(Iron Worker) < Eggplant Wizard >
Posts: 314 - Joined: 03/02/2013
Colorado
Profile
Originally posted by: Mega Mario Man

Originally posted by: Dread

How do you know the location of each sprite. I gathered 203 from from reading the code, but I can't seem to find 207, 20b, or 20f anywhere.

I wanted to do the "homework" on my own as best I could, but I had to read through the thread to figure out the location of the other three sprites. How would I locate them on my own?

Sprite data starts at $0200 and the address is increased by 1 for each byte afterwards. Each sprite needs 4 bytes of data and is loadedin this order:
1. Vertical Position
2. Tile Number
3. Sprite Attribute
4. Horizontal Position

If you look at the sprites section, you will see this.

sprites:
     ;vert tile attr horiz
  .db $80, $32, $00, $80   ;sprite 0
  .db $80, $33, $00, $88   ;sprite 1
  .db $88, $34, $00, $80   ;sprite 2
  .db $88, $35, $00, $88   ;sprite 3

So, the first sprite would load like this:
SPRITE 0
1. Vertical Position       =$0200
2. Tile Number             =$0201
3. Sprite Attribute         =$0202
4. Horizontal Position   =$0203

After Sprite 0 loads, the sprite loading loop will continue on to the next sprite (if the loop is set load more sprite data). So this:

     ;vert tile attr horiz
  .db $80, $32, $00, $80   ;sprite 0
  .db $80, $33, $00, $88   ;sprite 1
  .db $88, $34, $00, $80   ;sprite 2
  .db $88, $35, $00, $88   ;sprite 3

Will load like this:
    vert        tile       attr    horiz
 $0200, $0201, $0202, $0203   ;sprite 0
 $0204, $0205, $0206, $0207   ;sprite 1
 $0208, $0209, $020A, $020B   ;sprite 2
 $020C, $020D, $020E, $020F   ;sprite 3

Awesome.

That makes perfect sense to me. Thanks. I'm gonna try to make all four sprites move today, but I'm a liitle confused regarding x and y axis movement. I'll mess around and see what happens. What you just said really makes sense, and I'm starting to understand the code too. I have a very long way to go and if your going to explain everything so well, I might have to bother you a lot over the next few days.




-------------------------

            

Apr 23, 2014 at 10:38:26 AM
Mario's Right Nut (350)
avatar
(Cunt Punch) < Bowser >
Posts: 6574 - Joined: 11/21/2008
Texas
Profile
x and y should not be confused with the registers x and y. In the sprite case, it refers to the vertical and horizontal movement.

The "vert" byte is the number of pixels the top of the sprite is from the top of the screen.

The "horz" byte is the number of pixels the left side of the sprite is from the left side of the screen.

-------------------------

This is my shiny thing, and if you try to take it off me, I may have to eat you.

Check out my dev blog.


Apr 23, 2014 at 10:55:46 AM
Mega Mario Man (58)
avatar
(Tim ) < Kraid Killer >
Posts: 2251 - Joined: 02/13/2014
Nebraska
Profile
Keep at it Dread, I'm less than 2 months into programming and you can go a long way really fast. I was in the same boat you were just a few weeks ago, and now I have a functional game but it is no where close to done.

Many have helped me along the way. My advice, once you get through the Nerdy Nights and have a working program, go back and read it all again. It's amazing what you pick up the second, third, and fourth time through.

Also, if you would like, I would can invite you to my private thread that sort of documents my journey of programming my first game. I also try to keep an up-to-date ROM posted in the first post of the private thread so you can see my bugs and play with the game mechanics.

-------------------------
Current Project
Isometric Survival Horror

Older Projects
Tailgate Party, Power Pad Demo, Happy Hour

Links
Store, Facebook, Twitter

Apr 23, 2014 at 2:24:37 PM
Dreadmoc (18)
avatar
(Iron Worker) < Eggplant Wizard >
Posts: 314 - Joined: 03/02/2013
Colorado
Profile
Originally posted by: Mega Mario Man

Keep at it Dread, I'm less than 2 months into programming and you can go a long way really fast. I was in the same boat you were just a few weeks ago, and now I have a functional game but it is no where close to done.

Many have helped me along the way. My advice, once you get through the Nerdy Nights and have a working program, go back and read it all again. It's amazing what you pick up the second, third, and fourth time through.

Also, if you would like, I would can invite you to my private thread that sort of documents my journey of programming my first game. I also try to keep an up-to-date ROM posted in the first post of the private thread so you can see my bugs and play with the game mechanics.

That would be awesome. I'm having a lot of fun learning, so none of this is a chore. It's just good fun, challenging and worth every minute.

MRN!!! Dude, thanks. so when I'm coding movement for up and down, what changes do I need to make so the program knows it's working vertically. I have the left right movement set to the arrow keys and all other buttons have no function.


-------------------------

            

Apr 23, 2014 at 2:47:31 PM
Dreadmoc (18)
avatar
(Iron Worker) < Eggplant Wizard >
Posts: 314 - Joined: 03/02/2013
Colorado
Profile
Ah,

0203 Is horizontal
0200 is vertical?

So LDA $0200 for up/down?

-------------------------

            

Apr 23, 2014 at 3:20:18 PM
MODERATOR
KHAN Games (88)
avatar
(Kevin Hanley) < Master Higgins >
Posts: 7760 - Joined: 06/21/2007
Florida
Profile

Apr 23, 2014 at 3:47:48 PM
Mega Mario Man (58)
avatar
(Tim ) < Kraid Killer >
Posts: 2251 - Joined: 02/13/2014
Nebraska
Profile
Here's a nice confusing tip:

Adding is Down
Subtrating is Up

Why?
Vertical line 00 starts at the top and the numbers increase as you work from the top to the bottom.
00
01
02
03
04
05
etc
etc

-------------------------
Current Project
Isometric Survival Horror

Older Projects
Tailgate Party, Power Pad Demo, Happy Hour

Links
Store, Facebook, Twitter

Apr 23, 2014 at 3:54:58 PM
Dreadmoc (18)
avatar
(Iron Worker) < Eggplant Wizard >
Posts: 314 - Joined: 03/02/2013
Colorado
Profile
Originally posted by: KHAN Games

up/down for sprite 0, yes.





So then just add all other positions for sprites 1,2,3?

-------------------------