Skip navigation
NintendoAge
Welcome, Guest! Please Login or Join
Loading...

Ask all programming questions here!

Apr 09 at 8:00:03 PM
SoleGooseProductions (129)
avatar
(Beau ) < King Solomon >
Posts: 3504 - Joined: 04/22/2013
Michigan
Profile
You can also toggle on/off sprites or BG objects. That is probably more handy, but since it is not natively mapped to any buttons I have not ever used it much (finally re-mapped buttons a few months back, only six years late). If the well is that bottom portion, I think you'll see what is going on pretty quick.

Hadn't played Palamedes until now, I had only seen pictures. Interesting...

-------------------------
"The light that burns twice as bright burns half as long..." ~ Blade Runner

SoleGooseProductions.com


Apr 09 at 11:01:28 PM
Roc Studios (0)
avatar
(Elias ) < Cherub >
Posts: 8 - Joined: 08/21/2018
California
Profile
Thanks for the tip   I guess the dice blocks Palamedes uses are part of the background, so that's how it avoids the 8 sprite per scanline limit. It's an interesting workaround, so hopefully I can make use of it. I hadn't heard of Palamedes myself until I saw James Rolfe and Mike Matei play it on their show.

Apr 10 at 12:10:55 AM
SoleGooseProductions (129)
avatar
(Beau ) < King Solomon >
Posts: 3504 - Joined: 04/22/2013
Michigan
Profile
Yeah, Tetris confounded me for the longest time when starting out. I just couldn't figure out how it was being done, and then I couldn't figure out how to do it programming-wise. The whole idea of sprites becoming background objects for a while, or vice versa, baffled me. Now I enjoy it and use it a lot. A nice clean way of cheating those scan line restrictions, palette restrictions, and some other stuff probably too.

-------------------------
"The light that burns twice as bright burns half as long..." ~ Blade Runner

SoleGooseProductions.com


Apr 10 at 6:15:02 PM
Roc Studios (0)
avatar
(Elias ) < Cherub >
Posts: 8 - Joined: 08/21/2018
California
Profile
Sounds like it was tough but worth the effort. I may end up asking how you converted the sprites into background objects when I get to that point if I can't figure it out myself  

Jul 11 at 5:12:17 AM
oleSchool (0)
avatar
(Jonathon Wright) < Little Mac >
Posts: 72 - Joined: 11/02/2011
Hawaii
Profile
New Question: Backgrounds

I tried week 6 Nerdy Nights example and I kinda understand it. But translating it to my first test game isn't going well.
In the NN example, its only loading in 5 rows of a screen, I obviously want all 32 rows loaded.
So I did this for a loop and a hard coded background of 32 rows:

...
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 #$FF ; Compare X to hex $FF, decimal 256 - copying 256 bytes
BNE LoadBackgroundLoop ; Branch to LoadBackgroundLoop if compare was Not Equal to zero

...;further down in bottom of code, bg / screen hard coded:
background: ;specify the tiles (32 per row)
.db $26,$26,$26,$26,$26,$26,$26,$26,$26,$26,$26,$26,$26,$26,$26,$26,$26,$26,$26,$26,$26,$26,$26,$26,$26,$26,$26,$26,$26,$26,$26,$26 ;row 1
.db $26,$26,$26,$26,$26,$26,$26,$26,$26,$26,$26,$26,$26,$26,$26,$26,$26,$26,$26,$26,$26,$26,$26,$26,$26,$26,$26,$26,$26,$26,$26,$26 ;row 2
.db $26,$26,$26,$26,$26,$26,$26,$26,$26,$26,$26,$26,$26,$26,$26,$26,$26,$26,$26,$26,$26,$26,$26,$26,$26,$26,$26,$26,$26,$26,$26,$26 ;row 3
.db $26,$26,$26,$26,$26,$26,$26,$26,$26,$26,$26,$26,$26,$26,$26,$26,$26,$26,$26,$26,$26,$26,$26,$26,$26,$26,$26,$26,$26,$26,$26,$26 ;row 4
.db $25,$25,$25,$25,$25,$25,$25,$25,$25,$25,$25,$25,$25,$25,$25,$25,$25,$25,$25,$25,$25,$25,$25,$25,$25,$25,$25,$25,$25,$25,$25,$25 ;row 5
.db $25,$25,$25,$25,$25,$25,$25,$25,$25,$25,$25,$25,$25,$25,$25,$25,$25,$25,$25,$25,$25,$25,$25,$25,$25,$25,$25,$25,$25,$25,$25,$25 ;row 6
.db $25,$25,$25,$25,$25,$25,$25,$25,$25,$25,$25,$25,$25,$25,$25,$25,$25,$25,$25,$25,$25,$25,$25,$25,$25,$25,$25,$25,$25,$25,$25,$25 ;row 7
.db $25,$25,$25,$25,$25,$25,$25,$25,$25,$25,$25,$25,$25,$25,$25,$25,$25,$25,$25,$25,$25,$25,$25,$25,$25,$25,$25,$25,$25,$25,$25,$25 ;row 8
.db $27,$27,$27,$27,$27,$27,$27,$27,$27,$27,$27,$27,$27,$27,$27,$27,$27,$27,$27,$27,$27,$27,$27,$27,$27,$27,$27,$27,$27,$27,$27,$27 ;row 9
.db $27,$27,$27,$27,$27,$27,$27,$27,$27,$27,$27,$27,$27,$27,$27,$27,$27,$27,$27,$27,$27,$27,$27,$27,$27,$27,$27,$27,$27,$27,$27,$27 ;row 10
.db $27,$27,$27,$27,$27,$27,$27,$27,$27,$27,$27,$27,$27,$27,$27,$27,$27,$27,$27,$27,$27,$27,$27,$27,$27,$27,$27,$27,$27,$27,$27,$27 ;row 11
.db $27,$27,$27,$27,$27,$27,$27,$27,$27,$27,$27,$27,$27,$27,$27,$27,$27,$27,$27,$27,$27,$27,$27,$27,$27,$27,$27,$27,$27,$27,$27,$27 ;row 12
.db $28,$28,$28,$28,$28,$28,$28,$28,$28,$28,$28,$28,$28,$28,$28,$28,$28,$28,$28,$28,$28,$28,$28,$28,$28,$28,$28,$28,$28,$28,$28,$28 ;row 13
.db $28,$28,$28,$28,$28,$28,$28,$28,$28,$28,$28,$28,$28,$28,$28,$28,$28,$28,$28,$28,$28,$28,$28,$28,$28,$28,$28,$28,$28,$28,$28,$28 ;row 14
.db $28,$28,$28,$28,$28,$28,$28,$28,$28,$28,$28,$28,$28,$28,$28,$28,$28,$28,$28,$28,$28,$28,$28,$28,$28,$28,$28,$28,$28,$28,$28,$28 ;row 15
.db $28,$28,$28,$28,$28,$28,$28,$28,$28,$28,$28,$28,$28,$28,$28,$28,$28,$28,$28,$28,$28,$28,$28,$28,$28,$28,$28,$28,$28,$28,$28,$28 ;row 16

.db $26,$26,$26,$26,$26,$26,$26,$26,$26,$26,$26,$26,$26,$26,$26,$26,$26,$26,$26,$26,$26,$26,$26,$26,$26,$26,$26,$26,$26,$26,$26,$26 ;row 17
.db $26,$26,$26,$26,$26,$26,$26,$26,$26,$26,$26,$26,$26,$26,$26,$26,$26,$26,$26,$26,$26,$26,$26,$26,$26,$26,$26,$26,$26,$26,$26,$26 ;row 18
.db $26,$26,$26,$26,$26,$26,$26,$26,$26,$26,$26,$26,$26,$26,$26,$26,$26,$26,$26,$26,$26,$26,$26,$26,$26,$26,$26,$26,$26,$26,$26,$26 ;row 19
.db $26,$26,$26,$26,$26,$26,$26,$26,$26,$26,$26,$26,$26,$26,$26,$26,$26,$26,$26,$26,$26,$26,$26,$26,$26,$26,$26,$26,$26,$26,$26,$26 ;row 21
.db $25,$25,$25,$25,$25,$25,$25,$25,$25,$25,$25,$25,$25,$25,$25,$25,$25,$25,$25,$25,$25,$25,$25,$25,$25,$25,$25,$25,$25,$25,$25,$25 ;row 22
.db $25,$25,$25,$25,$25,$25,$25,$25,$25,$25,$25,$25,$25,$25,$25,$25,$25,$25,$25,$25,$25,$25,$25,$25,$25,$25,$25,$25,$25,$25,$25,$25 ;row 23
.db $25,$25,$25,$25,$25,$25,$25,$25,$25,$25,$25,$25,$25,$25,$25,$25,$25,$25,$25,$25,$25,$25,$25,$25,$25,$25,$25,$25,$25,$25,$25,$25 ;row 24
.db $25,$25,$25,$25,$25,$25,$25,$25,$25,$25,$25,$25,$25,$25,$25,$25,$25,$25,$25,$25,$25,$25,$25,$25,$25,$25,$25,$25,$25,$25,$25,$25 ;row 25
.db $27,$27,$27,$27,$27,$27,$27,$27,$27,$27,$27,$27,$27,$27,$27,$27,$27,$27,$27,$27,$27,$27,$27,$27,$27,$27,$27,$27,$27,$27,$27,$27 ;row 26
.db $27,$27,$27,$27,$27,$27,$27,$27,$27,$27,$27,$27,$27,$27,$27,$27,$27,$27,$27,$27,$27,$27,$27,$27,$27,$27,$27,$27,$27,$27,$27,$27 ;row 27
.db $27,$27,$27,$27,$27,$27,$27,$27,$27,$27,$27,$27,$27,$27,$27,$27,$27,$27,$27,$27,$27,$27,$27,$27,$27,$27,$27,$27,$27,$27,$27,$27 ;row 28
.db $27,$27,$27,$27,$27,$27,$27,$27,$27,$27,$27,$27,$27,$27,$27,$27,$27,$27,$27,$27,$27,$27,$27,$27,$27,$27,$27,$27,$27,$27,$27,$27 ;row 29
.db $28,$28,$28,$28,$28,$28,$28,$28,$28,$28,$28,$28,$28,$28,$28,$28,$28,$28,$28,$28,$28,$28,$28,$28,$28,$28,$28,$28,$28,$28,$28,$28 ;row 30
.db $28,$28,$28,$28,$28,$28,$28,$28,$28,$28,$28,$28,$28,$28,$28,$28,$28,$28,$28,$28,$28,$28,$28,$28,$28,$28,$28,$28,$28,$28,$28,$28 ;row 31
.db $28,$28,$28,$28,$28,$28,$28,$28,$28,$28,$28,$28,$28,$28,$28,$28,$28,$28,$28,$28,$28,$28,$28,$28,$28,$28,$28,$28,$28,$28,$28,$28 ;row 32

I'm only getting first 8 rows, which makes sense, 8x32 = 256 = #$FF. But #$FF is the highest I can use in a 8 bit system, I can't compare X to #$400 (32 x 32 = 1024 decimal = #$400 hex).
So since this is my first bg loop / test program ever, lol, I'm obviously missing something very easy.

Please help,
OleSchool

-------------------------
"It's Dangerous to go alone. Take This!"
The Old Man

https://www.youtube.com/channel/U...

Jul 11 at 7:03:35 AM
Nallebeorn (0)
avatar
(Benjamin Larsson) < Cherub >
Posts: 4 - Joined: 03/25/2019
Sweden
Profile
It's explained in Nerdy Nights week 8, so you can take a peek at that. Basically, you do two loops, one inner than runs 256 times and one outer that runs 4 times (4*256=1024).

Jul 12 at 2:29:58 AM
oleSchool (0)
avatar
(Jonathon Wright) < Little Mac >
Posts: 72 - Joined: 11/02/2011
Hawaii
Profile
Originally posted by: Nallebeorn

It's explained in Nerdy Nights week 8, so you can take a peek at that. Basically, you do two loops, one inner than runs 256 times and one outer that runs 4 times (4*256=1024).

Awesome! Hey, and I’m honored to be your first post haha! Thanks again!
 

-------------------------
"It's Dangerous to go alone. Take This!"
The Old Man

https://www.youtube.com/channel/U...

Jul 13 at 4:12:51 AM
oleSchool (0)
avatar
(Jonathon Wright) < Little Mac >
Posts: 72 - Joined: 11/02/2011
Hawaii
Profile
I finally got the background to populate with the two loops, yay!!

But now I'm chasing a random sprite.. I've got a sprite at 0,0 of tile $00 of my 1st nametable. I've commented out everything except the standard required stuff ( NMI/RTI, Infinite loop,.org, bank, clear memory, vblank waiting, etc.)
The only thing that makes it go away is commenting out the PPU control settings:

...
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
...

Is there a bug in my emulator (MESEN), or a bug in the code somehow? This only started after I changed my code around to match the week 8 nerdy nights format.

-------------------------
"It's Dangerous to go alone. Take This!"
The Old Man

https://www.youtube.com/channel/U...

Jul 14 at 11:12:16 AM
Nallebeorn (0)
avatar
(Benjamin Larsson) < Cherub >
Posts: 4 - Joined: 03/25/2019
Sweden
Profile
Originally posted by: oleSchool

Is there a bug in my emulator (MESEN), or a bug in the code somehow? This only started after I changed my code around to match the week 8 nerdy nights format.
I would be very surprised if it was a Mesen bug  

If it started to happen only after your week 8 updates, then it's obviously a problem with one of the things you changed. Since you said you commented out almost everything, I assume you've already verified that it's not a problem with the new background copy loop, but is there something else you changed at the same time? Could you maybe post the full code?
 

Jul 14 at 8:02:06 PM
oleSchool (0)
avatar
(Jonathon Wright) < Little Mac >
Posts: 72 - Joined: 11/02/2011
Hawaii
Profile
Originally posted by: Nallebeorn
 
Originally posted by: oleSchool

Is there a bug in my emulator (MESEN), or a bug in the code somehow? This only started after I changed my code around to match the week 8 nerdy nights format.
I would be very surprised if it was a Mesen bug  

If it started to happen only after your week 8 updates, then it's obviously a problem with one of the things you changed. Since you said you commented out almost everything, I assume you've already verified that it's not a problem with the new background copy loop, but is there something else you changed at the same time? Could you maybe post the full code?
 

Yeah, definitely been scratching my head on this one.
I zipped up the asm with my chr just in case its something with the chr file... I also uncommented everything back. 
Any help is appreciated. Here is the link

Thanks!
 

-------------------------
"It's Dangerous to go alone. Take This!"
The Old Man

https://www.youtube.com/channel/U...

Jul 15 at 10:45:28 AM
Nallebeorn (0)
avatar
(Benjamin Larsson) < Cherub >
Posts: 4 - Joined: 03/25/2019
Sweden
Profile
Your clrmem routine is wrong. You use $0200 as the OAM buffer, but you're clearing $0300 with $fe and $0200 with zeroes. That means you get a bunch of sprites with $00 for all values, which of course means tile $00 at position (0; 0) with palette 0. And don't forget that the sprites data at the bottom is commented out at the moment, so your LoadSprites loop will be loading garbage data, which will probably be a bunch of zeroes again since that's what assemblers generally fill unused ROM space with.

Jul 15 at 4:42:08 PM
KHAN Games (89)
avatar
(Kevin Hanley) < Master Higgins >
Posts: 8124 - Joined: 06/21/2007
Florida
Profile
Thanks for answering these, Nallebeorn. I was out of town for the week so I missed all these!

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

gauauu: look, we all paid $10K at some point in our lives for the privilege of hanging out with Kevin


Jul 16 at 3:51:17 AM
oleSchool (0)
avatar
(Jonathon Wright) < Little Mac >
Posts: 72 - Joined: 11/02/2011
Hawaii
Profile
Originally posted by: Nallebeorn

Your clrmem routine is wrong. You use $0200 as the OAM buffer, but you're clearing $0300 with $fe and $0200 with zeroes. That means you get a bunch of sprites with $00 for all values, which of course means tile $00 at position (0; 0) with palette 0. And don't forget that the sprites data at the bottom is commented out at the moment, so your LoadSprites loop will be loading garbage data, which will probably be a bunch of zeroes again since that's what assemblers generally fill unused ROM space with.

Thanks Nallebeorn, that worked!

I changed my clrmem to this based on what you said:
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

I understand what you said, but I'm a little confused on how its working. 
Here is what I understand:

1st Loop
  $0000, $0100, $0300..$0700 are set to value A which is 0
  $0200 is set to $FE

2nd Loop
  $0001, $0101, $0301..$0701 are set to value A which is 0
  $0201 is set to $FE

...etc

255th loop
  $00FF, $01FF, $03FF...$07FF are set to value A which is 0
  $02FF is set to $FE

If this is correct, why is the OAM buffer $0200-$02FF being set to $FE? Wouldn't I have the same issue from my original post up top if I had my spaceship on tile $FE in my .chr file?
Just trying to understand. 

Thanks!

 

-------------------------
"It's Dangerous to go alone. Take This!"
The Old Man

https://www.youtube.com/channel/U...

Jul 16 at 7:37:06 AM
KHAN Games (89)
avatar
(Kevin Hanley) < Master Higgins >
Posts: 8124 - Joined: 06/21/2007
Florida
Profile
No, because all the sprites are being set to $FE on the vertical axis which is off the bottom of the screen. Sprites set to 0 will bleed onto the screen a little bit and won't fully be hidden. Think less about the tile number and more about the sprite positioning. It's setting all the values of each sprite to $FE: y axis, tile number, palette number, x axis.

The actual sprite loading routine will obviously happen after this, so all the sprites you actually plan on loading will have their proper values loaded at that time. This is just clearing the memory and "resetting" everything since RAM can be unpredictable upon power on.

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

gauauu: look, we all paid $10K at some point in our lives for the privilege of hanging out with Kevin



Edited: 07/16/2019 at 07:40 AM by KHAN Games

Jul 17 at 2:08:33 AM
oleSchool (0)
avatar
(Jonathon Wright) < Little Mac >
Posts: 72 - Joined: 11/02/2011
Hawaii
Profile
Originally posted by: KHAN Games

No, because all the sprites are being set to $FE on the vertical axis which is off the bottom of the screen. Sprites set to 0 will bleed onto the screen a little bit and won't fully be hidden. Think less about the tile number and more about the sprite positioning. It's setting all the values of each sprite to $FE: y axis, tile number, palette number, x axis.

The actual sprite loading routine will obviously happen after this, so all the sprites you actually plan on loading will have their proper values loaded at that time. This is just clearing the memory and "resetting" everything since RAM can be unpredictable upon power on.

Ahh, makes sense.  Couple additional questions come to mind now. 

When I do my background loops, I noticed that I only needed 31 rows (992 bytes) vice 32 rows (1024 bytes) declared in my .db rows to get it to display all rows top to bottom properly. 
So I commented out the last .db row declaration in the "background:" label section. 

1.) Is this an issue with the emulator, and / or do I need to code this for working on other mappers / emulators or even the NES differently? 
2.) I also thought about saving cycles if I don't need all 32 rows. Instead of processing 32 x 32 rows, I should process 32x31 (992 bytes). This would also mean my attributes start at a different address saving some memory correct?
3.) I currently have it setup to do 256 bytes in the inner loop, outer loop runs 4 times  = 256 x 4 = 1024. Since I only need 992 bytes, whats the best way to do that? I could do 128 x 7, but not really ready to rewrite this thing yet until I get a feel for what everyone else does / recommends.  

Second item is for more cycle saving on the clrmem. You made a great point that its more about the tile position rather than the other bytes of info which got me thinking. Would clrmem be faster if I looped through only setting the positioning and skipping the other 2 bytes, something like this?

clrmem:
  LDA #$00
  STA $0000, x
  STA $0100, x
  STA $0300, x
  STA $0400, x
  STA $0500, x
  STA $0600, x
  STA $0700, x
  INX
  BNE clrmem

clr_oam_mem:
  LDX #$00
  LDA #$FE
  STA $0200, x
  INX
  INX
  INX
  STA $0200, x
  BNE clr_oam_mem

-------------------------
"It's Dangerous to go alone. Take This!"
The Old Man

https://www.youtube.com/channel/U...

Jul 17 at 7:29:25 AM
KHAN Games (89)
avatar
(Kevin Hanley) < Master Higgins >
Posts: 8124 - Joined: 06/21/2007
Florida
Profile
From nerdy nights week 2:
 
Originally posted by: bunnyboy

Background
This is the landscape graphics, which scrolls all at once. The sprites can either be displayed in front or behind the background. The screen is big enough for 32x30 background tiles, and there is enough internal RAM to hold 2 screens. When games scroll the background graphics are updated off screen before they are scrolled on screen.
As you can see, backgrounds are 32x30 tiles. Yes, you could code your background loops accordingly. It isn't an emulator issue. This is just how the NES architecture is. It saves that space for the attribute data.

Attribute data already starts at $23C0 (if the backgrounds were 32x32 there would be no room for attribute data. It would have to start at $2400, but that's where the second nametable data is stored).

I've always just left the loops running a full four times. Whatever garbage gets written there will immediately be overwritten when you write your attribute loops, so long as you write it after you load your background.

As for your last question, that second loop wouldn't work since you're resetting X to zero every time, but other than that, you're already not saving space by having to write a second loop in the first place.   It's cool that you're making sense of it though. Getting it to be "faster" isn't really needed, since the screen is always off upon bootup initialization.

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

gauauu: look, we all paid $10K at some point in our lives for the privilege of hanging out with Kevin



Edited: 07/17/2019 at 07:32 AM by KHAN Games

Jul 17 at 9:18:51 AM
Nallebeorn (0)
avatar
(Benjamin Larsson) < Cherub >
Posts: 4 - Joined: 03/25/2019
Sweden
Profile
1) A full NES screen isn't actually square; its native resolution in 256x240 pixels. It always outputs in that resolution, on hardware and in emulators. The size of the visible area of the screen might differ depending on the TV and emulator configuration because of overscan, but the internal resolution if always the same.
Anyway, 240 pixels vertically gives us just 30 rows of 8x8 tiles, but 32 columns. This is also the reason you want to clear OAM with $fe: as long as a sprite's Y value is larger than or equal to 240 ($f0), it will be off-screen and therefore invisible. The other sprite values (tile ID, attributes and even the X position) don't actually matter.
2) & 3) A full screen of tile indices takes up 960 bytes (32x30, not 32x31). Conveniently, attribute data for a full screen takes up exactly 64 bytes, so we're back at 1024 bytes in total. So if you just want to copy a full screen of uncompressed background data, you can very easily copy nametable and attribute data in the same 256x4 nested loop – just makes sure you only have 30 rows worth of tile indices, and then put the attribute data directly after that in ROM. 

EDIT: Didn't see KHAN's post there, so sorry for duplicate information  
 


Edited: 07/17/2019 at 09:23 AM by Nallebeorn

Jul 17 at 1:03:57 PM
KHAN Games (89)
avatar
(Kevin Hanley) < Master Higgins >
Posts: 8124 - Joined: 06/21/2007
Florida
Profile
You explained things in a different way, so I appreciate the post. <3

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

gauauu: look, we all paid $10K at some point in our lives for the privilege of hanging out with Kevin


Jul 18 at 2:26:14 AM
oleSchool (0)
avatar
(Jonathon Wright) < Little Mac >
Posts: 72 - Joined: 11/02/2011
Hawaii
Profile
Thanks to both of you, I appreciate different explanations as well.

I'm a little concerned about the 32x30 vice 32x31 dilemma I'm having in my code. When my background db rows have 32x31 rows defined, I get all visible rows filled up with tiles. When I do 32x30, the bottom row is full of other random tiles.
See my code on previous page. Comment out line 254 so you only have 32x31 instead of 32x32 and when you compile it and open it up in the emulator you'll see all the rows have tiles.

So I am definitely getting what you're saying, that the 32x30 = 960 bytes and the attributes conveniently take 64 bytes to give us 1024 bytes (I'm gonna add attributes into my Loadbackground tiles loop btw, great idea!). But I keep scratching my head because if I don't load 32x31 rows, then the bottom row (32) of my screen is filled with other tiles (probably selecting one based on hex value of the attributes binary value equivalent).

Anyway, any thoughts or do i have another bug =)

-------------------------
"It's Dangerous to go alone. Take This!"
The Old Man

https://www.youtube.com/channel/U...

Jul 18 at 7:14:41 AM
KHAN Games (89)
avatar
(Kevin Hanley) < Master Higgins >
Posts: 8124 - Joined: 06/21/2007
Florida
Profile
Well, if the code is exactly like it is in that zip file, you are missing row 20, so you actually only have 31 rows listed, and commenting out 1 row (which is working perfect for you) is bringing you down to 30, and commenting out 2 rows (which is giving you a blank row/garbage tiles) is bringing you down to 29.

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

gauauu: look, we all paid $10K at some point in our lives for the privilege of hanging out with Kevin



Edited: 07/18/2019 at 07:16 AM by KHAN Games

Jul 18 at 3:20:53 PM
oleSchool (0)
avatar
(Jonathon Wright) < Little Mac >
Posts: 72 - Joined: 11/02/2011
Hawaii
Profile
Originally posted by: KHAN Games

Well, if the code is exactly like it is in that zip file, you are missing row 20, so you actually only have 31 rows listed, and commenting out 1 row (which is working perfect for you) is bringing you down to 30, and commenting out 2 rows (which is giving you a blank row/garbage tiles) is bringing you down to 29.
  Wow... I mustve looked at my code a hundred times and never saw that I was missing row 20... 
Okay, so the laws of physics are still in place haha. So yeah, 32x30 is what I got, now I'm good!
 

-------------------------
"It's Dangerous to go alone. Take This!"
The Old Man

https://www.youtube.com/channel/U...

Jul 20 at 6:04:36 AM
oleSchool (0)
avatar
(Jonathon Wright) < Little Mac >
Posts: 72 - Joined: 11/02/2011
Hawaii
Profile
Trying to mimick Asteroids for my controller reading demo. Its a simple game, single screen, but I got stuck at turning the sprite. Here's where I'm at.

My chr file has three tiles for the player ship sprite. One facing up ($00), one facing left ($01), one facing diagonally up left ($02).
I figured with a flip of the vertical or horizontal bits I can cover 8 directions: facing up, down, left, right, and all the diagonals.

Moving left and right and up and down isn't hard (I'll try diagonals tomorrow), its turning I'm stuck on. I'd like to do the same as in the 2600's version of asteroids, where I can turn my ship in place by pressing left or right. I'm thinking I need something like this (psuedo):


;Move from facing up to diagonal up left
If $0201 is set to $00,
and left is pressed, then
set $0201 to $02

;Move from facing diagonal up left to left
If $0201 is set to $02,
and left is pressed, then
set $0201 to $01

;Move from facing left to diagonal down left (flip $02 horizontally)
If $0201 is set to $01
and left is pressed, then
set $0201 to $02
set $0202 to #%01000000

...etc.


Even if this is the way (seems this could be looped or easier somehow), I would only have 8 directions, I'd like to get as close to 360 as possible, 16 minimum I suppose.
Do I need more tiles for my sprites to get more directions (16 - 360)? Also, is my psuedo example the best way to code "turning in place"?

Thanks!

-------------------------
"It's Dangerous to go alone. Take This!"
The Old Man

https://www.youtube.com/channel/U...

Jul 20 at 10:11:20 AM
KHAN Games (89)
avatar
(Kevin Hanley) < Master Higgins >
Posts: 8124 - Joined: 06/21/2007
Florida
Profile
Correct, you would need more tiles in order to make it seem "more fluid."

Your pseudo code won't really work without multiple compares, since your tile could be the same value in different orientations and you're just modifying the attribute byte to flip it.

I'd probably do something like.

;if left or right button is pressed, increment timer
;if timer >=value, turn ship ;you can adjust this value to change the speed the ship turns
;reset timer
;look to see which of the two directions is pressed
;if left, decrement lookup table value by 2
;if right, increment lookup table value by 2
;check to see if value wrapped off the table, and reset accordingly
;store lookup table value
;set lookup table value to sprite
;increment lookup table value
;set lookup table value to attribute
;end

Then you would have a lookup table for turning, including direction and attribute data for each position (obviously adjusted for more directions if you wanted it to be smoother).
.db $00,$00;up
.db $02,%01000000;up/right
.db $01,%01000000;right
.db $02,%11000000;down/right
.db $00,%10000000;down
.db $02;%01000000;down/left
.db $01,$00;left
.db $02,$00;up/left

This is probably slightly more advanced than the Nerdy Nights week you're on, so just do your best and let me know if/where you get stuck. Lookup tables like this are going to be your main way of storing values for various things, so you should definitely learn how to do it. It's very similar to how your background loading code works. You're just additioanlly keeping a variable that stores where in the lookup table you are at all times, even when the button is not pressed.

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

gauauu: look, we all paid $10K at some point in our lives for the privilege of hanging out with Kevin



Edited: 07/20/2019 at 12:51 PM by KHAN Games

Jul 21 at 2:27:04 AM
oleSchool (0)
avatar
(Jonathon Wright) < Little Mac >
Posts: 72 - Joined: 11/02/2011
Hawaii
Profile
Originally posted by: KHAN Games

Correct, you would need more tiles in order to make it seem "more fluid."

Your pseudo code won't really work without multiple compares, since your tile could be the same value in different orientations and you're just modifying the attribute byte to flip it.

I'd probably do something like.

;if left or right button is pressed, increment timer
;if timer >=value, turn ship ;you can adjust this value to change the speed the ship turns
;reset timer
;look to see which of the two directions is pressed
;if left, decrement lookup table value by 2
;if right, increment lookup table value by 2
;check to see if value wrapped off the table, and reset accordingly
;store lookup table value
;set lookup table value to sprite
;increment lookup table value
;set lookup table value to attribute
;end

Then you would have a lookup table for turning, including direction and attribute data for each position (obviously adjusted for more directions if you wanted it to be smoother).
.db $00,$00;up
.db $02,%01000000;up/right
.db $01,%01000000;right
.db $02,%11000000;down/right
.db $00,%10000000;down
.db $02;%01000000;down/left
.db $01,$00;left
.db $02,$00;up/left

This is probably slightly more advanced than the Nerdy Nights week you're on, so just do your best and let me know if/where you get stuck. Lookup tables like this are going to be your main way of storing values for various things, so you should definitely learn how to do it. It's very similar to how your background loading code works. You're just additioanlly keeping a variable that stores where in the lookup table you are at all times, even when the button is not pressed.


Very cool for you to reply with this info bud, much appreciated! But I must've read this about 5 times today and I'm still having a little difficulty with the lookup table piece. Storing values makes sense, but I don't know how to store them and retrieve them because they are values that have no location in memory... or do I just pick something in the 2K RAM? Even so, I'd need a little push / example on initializing the constants like this for a lookup table. If I knew how to do that, then I could store / retrieve them like any other constant variable. 

I think I'll start working on what I know how to do...making more tiles, haha. I think 16 is enough, 8 won't cut it, as you only get one diagonal between each cardinal direction, and I don't want to waste a lot of tiles (I'm using NROM / mapper 0 so I only have 256) for the sprites.  I'll work on that, once its done (hopefully by tomorrow) I'll let ya know where I get stuck on the table lookup initialization stuff. 

thanks!

 

-------------------------
"It's Dangerous to go alone. Take This!"
The Old Man

https://www.youtube.com/channel/U...


Edited: 07/21/2019 at 02:27 AM by oleSchool

Jul 21 at 8:22:51 AM
KHAN Games (89)
avatar
(Kevin Hanley) < Master Higgins >
Posts: 8124 - Joined: 06/21/2007
Florida
Profile
You're only storing a variable that keeps track of where on the table you currently are.

I'm not sure how you're doing controller reads, but I'll post code here like is described in one of the later nerdy nights tutorials, week 7, as "Better Controller Reading."

Buttons: .rs 1 ;current button presses
MovementTimer: .rs 1 ;timer that needs to be reached in order for movement to begin
ShipDirection: .rs 1 ;current position on our lookup table for the ship direction

MoveShip:
  LDA Buttons ;load buttons variable
  AND #%00100000 ;only keep Left bit
  BEQ .TryRight ;if Left isn't held, branch to try Right
;;left is held
  INC MovementTimer ;increment movement timer
  LDA MovementTimer ;load increment timer
  CMP #$xx ;compare to whatever value you want
  BCC .End ;if it's less than this, go to end
  DEC ShipDirection ;decrement ship direction x2
  DEC ShipDirection
  LDA ShipDirection ;check to see if ShipDirection has wrapped around the table
  CMP #$FE
  BNE .Rotate ;if it hasn't jump to Rotate
  LDA #$0E
  STA ShipDirection ;reset ShipDirection to the highest starting value (you'll change this number when you add more directions to your table)
  JMP .Rotate ;jump to Rotate
.TryRight:
  LDA Buttons ;load buttons variable
  AND #%00010000 ;only keep Right bit
  BEQ .Reset ;if Right isn't held, branch to Reset to reset the MovementTimer variable since button isn't pressed
;;right is held
  INC MovementTimer ;increment movement timer
  LDA MovementTimer ;load increment timer
  CMP #$xx ;compare to whatever value you want
  BCC .End ;if it's less than this, go to end
  INC ShipDirection ;increment ship direction x2
  INC ShipDirection
  LDA ShipDirection ;check to see if ShipDirection has wrapped around the table
  CMP #$10
  BNE .Rotate ;if it hasn't, jump to Rotate
  LDA #$00
  STA ShipDirection ;reset ShipDirection to the lowest starting value
.Rotate:
  LDY ShipDirection ;load ShipDirection in the Y register
  LDA ShipLookupTable,y ;look at the sprite for the current direction using the Y register as the offset
  STA $0201 ;store
  LDA ShipLookupTable+1,y ;look at the attribute data for this direction
  STA $0202 ;store
  JMP .Reset ;reset MovementTimer
.End:
  RTS
.Reset:
  LDA #$00 ;reset the timer if Left or Right isn't pressed
  STA MovementTimer
  RTS

ShipLookupTable:
  .db $00,$00 ;up
  .db $02,%01000000 ;up/right
  .db $01,%01000000 ;right
  .db $02,%11000000 ;down/right
  .db $00,%10000000 ;down
  .db $02;%01000000 ;down/left
  .db $01,$00 ;left
  .db $02,$00 ;up/left

A better solution would probably be to move the Rotate part of the subroutine to its own subroutine that's constantly called so that when you implement de-accelaration (making the ship slowly stop spinning when you release the button) it isn't requiring a button press to set the current direction.

This should get you started though. Let me know if anything doesn't make sense.

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

gauauu: look, we all paid $10K at some point in our lives for the privilege of hanging out with Kevin



Edited: 07/21/2019 at 08:38 AM by KHAN Games