It is currently Fri Sep 20, 2019 2:32 am

All times are UTC - 7 hours





Post new topic Reply to topic  [ 21 posts ]  Go to page 1, 2  Next
Author Message
PostPosted: Thu Dec 13, 2018 8:15 am 
Offline

Joined: Tue Oct 16, 2018 5:46 am
Posts: 99
Location: Gothenburg, Sweden
Hey, not sure where to post this but I thought it was a little interesting, so here it goes.

I've just started experimenting with scrolling where I've added the ability to change scroll values while my game is paused. If I run the game in an emulator (fceux/mesen) and scroll to an area where I have no tiles loaded, it will just show black. However, when I try this on real hardware I get different kinds of garbage tiles:

PAL NES modded with Famicom PPU, NTSC crystal and NESRGB
https://drive.google.com/open?id=1Ty6gzQS6oC4K84drIva7KNNcrGBSXAGT

PAL NES modded with NESRGB
https://drive.google.com/open?id=1IDvoxL6gUXkdYRU4pxzJrkEilYGRwSHy

PAL Famiclone system (unmodded)
https://drive.google.com/open?id=1rYAu9EdsDzJST5GBCgp0l9H4flIfW5Ng

What I'm curious about is whether this is coming from the PPU itself or the VRAM chip? Currently it's a bit of an annoyance, as the garbage flashes on screen whenever the machine is turned on or the game is reset. It only shows up on half the screen though, so I guess maybe the scroll is not being correctly setup on the first frame(s) and doing so might fix the issue.

Anyways, any knowledge into this would be interesting to hear.

Cheers!


Top
 Profile  
 
PostPosted: Thu Dec 13, 2018 8:22 am 
Offline

Joined: Sun Sep 19, 2004 11:12 pm
Posts: 21594
Location: NE Indiana, USA (NTSC)
The VRAM is a 2Kx8 SRAM. The initial values stored in this RAM at power-on may vary from unit to unit, from address to address, and from power-on to power-on. Multicarts and CF/SD adapters may leave menu maps in memory before starting your program.

The workaround is to clear the RAM to a known value sometime after the PPU has warmed up but before you turn on rendering. In 22 bytes:
Code:
  lda #$24  ; $2400-$2BFF covers both nametables in v and h mirroring
  ldx #$00
  ldy #$08  ; 4 times number of nametables to clear
  sta $2006  ; set video memory address
  stx $2006
  txa
ntclearloop:
  sta $2007
  inx
  bne ntclearloop
  dey
  bne ntclearloop


Or shorter if your program already includes a subroutine to clear a nametable, as I've been using in everything since Zap Ruder (my first project based on nrom-template):
Code:
  lda #$00  ; value for first 960 bytes
  tay       ; attribute value
  ldx #$24
  jsr ppu_clear_nt
  ldx #$28
  jsr ppu_clear_nt

_________________
Pin Eight | Twitter | GitHub | Patreon


Top
 Profile  
 
PostPosted: Thu Dec 13, 2018 8:30 am 
Offline
User avatar

Joined: Sat Feb 12, 2005 9:43 pm
Posts: 11412
Location: Rio de Janeiro - Brazil
Uninitialized RAM can contain anything, but each RAM chip may favor a specific pattern. If you point the scroll to an uninitialized name table, the PPU will render it as usual, but since it contains garbage, the result looks like garbage.

As for getting half a screen work of garbage the first frame, maybe that's because you're turning rendering on mid-screen, so the scroll is messed up. Try waiting for vblank before turning rendering on, that might solve the problem.


Top
 Profile  
 
PostPosted: Thu Dec 13, 2018 9:50 am 
Offline
User avatar

Joined: Thu Sep 15, 2016 6:29 am
Posts: 903
Location: Denmark (PAL)
I love garbage screens when turning on a game :) It reminds me of arcade games, almost all the ones I own do that.

... But yeah... as with anything else that is changed by the program, you want to initialize your entire video RAM before turning on rendering - just like it's usually a good idea to clear all the RAM accessible to you with $00, set the stack pointer, initialize mapper registers, etc., etc.

Insufficient initlialization is usually the issue for most problems that only show up on hardware.


Top
 Profile  
 
PostPosted: Thu Dec 13, 2018 10:57 am 
Offline

Joined: Tue Oct 16, 2018 5:46 am
Posts: 99
Location: Gothenburg, Sweden
Thanks for the replies guys, I'm learning a lot! I'm going to look into my initialization code again to see what I can improve.

You guys wouldn't happen to know of an emulator with the ability to emulate the uninitialized behavior found in real chips? If so, that would be really helpful in debugging my code.


Top
 Profile  
 
PostPosted: Thu Dec 13, 2018 11:07 am 
Offline
User avatar

Joined: Sun Jan 22, 2012 12:03 pm
Posts: 7582
Location: Canada
FCEUX and Mesen both have options to randomize RAM at power-on. I think Nintendulator does as well.


Top
 Profile  
 
PostPosted: Thu Dec 13, 2018 11:38 am 
Offline

Joined: Tue Oct 16, 2018 5:46 am
Posts: 99
Location: Gothenburg, Sweden
rainwarrior wrote:
FCEUX and Mesen both have options to randomize RAM at power-on. I think Nintendulator does as well.


I only found a setting for it in Mesen but it does not recreate the issue, so I'm guessing it only randomizes the RAM that's directly accessible to the CPU.

Hey, maybe uninitialized RAM could be used to create the initial seed for a random number generator! That way you'd get different behavior from console-to-console.

EDIT: It appears Mesen does in fact recreate the issue after all! Must've missed it the first time somehow.


Top
 Profile  
 
PostPosted: Fri Dec 14, 2018 1:19 am 
Offline
User avatar

Joined: Thu Sep 15, 2016 6:29 am
Posts: 903
Location: Denmark (PAL)
pwnskar wrote:
Hey, maybe uninitialized RAM could be used to create the initial seed for a random number generator! That way you'd get different behavior from console-to-console.

It wouldn't be reliable for randomness, as there would usually be a lot of bias towards specific numbers, and often the same ones at every power-on. There was a thread about getting a random number for any input from the player, but I can't find it now.

However, there was also this recent discussion about Impossible Mission 2 which seems to do exactly what you suggest!
viewtopic.php?f=3&t=18111

It's kind of an interesting way to add a little "mystery" to your game. Though I probably wouldn't want to use it for anything affecting gameplay.

Btw, does anyone know if powerpak/everdrive manually clears all RAM before loading in a new game, or does it just leave it as is? And what about popular multi-carts, like Action 53? (or 52)


Top
 Profile  
 
PostPosted: Fri Dec 14, 2018 2:08 am 
Offline

Joined: Tue Oct 16, 2018 5:46 am
Posts: 99
Location: Gothenburg, Sweden
Sumez wrote:
It wouldn't be reliable for randomness, as there would usually be a lot of bias towards specific numbers, and often the same ones at every power-on. There was a thread about getting a random number for any input from the player, but I can't find it now.

However, there was also this recent discussion about Impossible Mission 2 which seems to do exactly what you suggest!
viewtopic.php?f=3&t=18111

It's kind of an interesting way to add a little "mystery" to your game. Though I probably wouldn't want to use it for anything affecting gameplay.

My starting seed right now is a frame counter taken when the player first hits start but I wonder if it would be a good idea to combine it somehow with an uninitialized value. Maybe something like adding one to the value and multiplying it with my frame counter. That way I would always at least get the frame counter by itself as a starting seed but then have the extra mystery of the uninitialized value added on real hardware. Perhaps even a simple add would suffice.

Sumez wrote:
Btw, does anyone know if powerpak/everdrive manually clears all RAM before loading in a new game, or does it just leave it as is? And what about popular multi-carts, like Action 53? (or 52)

tepples wrote:
The VRAM is a 2Kx8 SRAM. The initial values stored in this RAM at power-on may vary from unit to unit, from address to address, and from power-on to power-on. Multicarts and CF/SD adapters may leave menu maps in memory before starting your program.

Thanks for all the replies guys! I've made sure to initialize both nametables at startup and the issue is gone. I still get the weird scroll happening the first frame but it's not visible with a black screen ofcourse. I've narrowed it down to something happening when I first load my palettes, although I make sure to do it straight after NMI, so not sure what's going on there. I'll probably get back to it later.


Top
 Profile  
 
PostPosted: Fri Dec 14, 2018 2:53 am 
Offline
User avatar

Joined: Thu Sep 15, 2016 6:29 am
Posts: 903
Location: Denmark (PAL)
pwnskar wrote:
My starting seed right now is a frame counter taken when the player first hits start but I wonder if it would be a good idea to combine it somehow with an uninitialized value. Maybe something like adding one to the value and multiplying it with my frame counter. That way I would always at least get the frame counter by itself as a starting seed but then have the extra mystery of the uninitialized value added on real hardware. Perhaps even a simple add would suffice.

.. as long as you aren't planning on something like TASbot ever playing your game :P


Top
 Profile  
 
PostPosted: Fri Dec 14, 2018 3:29 am 
Offline
User avatar

Joined: Thu Mar 31, 2016 11:15 am
Posts: 529
Apparently the startup state of OAM is more random than other RAM states. Read OAM and use that to seed your RNG instead.


Top
 Profile  
 
PostPosted: Fri Dec 14, 2018 3:53 am 
Offline

Joined: Tue Oct 16, 2018 5:46 am
Posts: 99
Location: Gothenburg, Sweden
Sumez wrote:
.. as long as you aren't planning on something like TASbot ever playing your game :P

That's a good point. I guess it would limit the game in some sense. Perhaps I could add a small TAS friendly workaround by having the randomness being taken strictly from the frame counter if a certain button was held down at reset or something. Perhaps two opposing directions on the d-pad.. :P

pubby wrote:
Apparently the startup state of OAM is more random than other RAM states. Read OAM and use that to seed your RNG instead.

Good idea!


Top
 Profile  
 
PostPosted: Fri Dec 14, 2018 8:00 am 
Offline

Joined: Sun Sep 19, 2004 11:12 pm
Posts: 21594
Location: NE Indiana, USA (NTSC)
Sumez wrote:
Btw, does anyone know if powerpak/everdrive manually clears all RAM before loading in a new game, or does it just leave it as is? And what about popular multi-carts, like Action 53? (or 52)

As I wrote earlier:
tepples wrote:
Multicarts and CF/SD adapters may leave menu maps in memory before starting your program.

It's impossible to switch from the system software of a multicart or CF/SD adapter to the chosen activity without either A. leaving some trampoline code in RAM, B. patching every program with both entry and exit code, or C. triggering bank switching on a time delay or a read of $FFFC. However, jroatch recently contributed commit f3a63b0 to Action 53, which clears the vast majority of CPU memory before starting an activity in a trampoline copied to the top of stack.

pwnskar wrote:
My starting seed right now is a frame counter taken when the player first hits start

If someone times pressing Start to title screen music, this press might land in a 66 ms window, which provides only four possibilities from power-on to game start. It might be useful to combine this with sub-frame measurement of key down timing. I've made a tech demo of this on Game Boy (called Telling LYs); do you want one on NES?

Sumez wrote:
as long as you aren't planning on something like TASbot ever playing your game

Some game publishers might actually want to make a game incompatible with TASbot as a means to suppress public awareness of TAS. Nintendo, for example, has asserted copyright against uploaders of TAS videos of its games in the past.

_________________
Pin Eight | Twitter | GitHub | Patreon


Top
 Profile  
 
PostPosted: Fri Dec 14, 2018 9:33 am 
Offline

Joined: Tue Oct 16, 2018 5:46 am
Posts: 99
Location: Gothenburg, Sweden
tepples wrote:
If someone times pressing Start to title screen music, this press might land in a 66 ms window, which provides only four possibilities from power-on to game start. It might be useful to combine this with sub-frame measurement of key down timing. I've made a tech demo of this on Game Boy (called Telling LYs); do you want one on NES?

Sure, that sounds rad! How do you do that without constantly checking the joypad registers?


Top
 Profile  
 
PostPosted: Fri Dec 14, 2018 10:46 am 
Offline

Joined: Sun Sep 19, 2004 11:12 pm
Posts: 21594
Location: NE Indiana, USA (NTSC)
pwnskar wrote:
tepples wrote:
do you want [a Telling LYs port] on NES?

Sure, that sounds rad! How do you do that without constantly checking the joypad registers?

By constantly checking the joypad registers in a 100% CPU loop, a DPCM interrupt handler, or a mapper-generated timer interrupt handler. If your game uses a discrete mapper or MMC1, and your title screen plays music with DPCM, the technique may not be as applicable.

_________________
Pin Eight | Twitter | GitHub | Patreon


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 21 posts ]  Go to page 1, 2  Next

All times are UTC - 7 hours


Who is online

Users browsing this forum: No registered users and 4 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB® Forum Software © phpBB Group