Page 1 of 1

Reading and saving $2000: Why does this change the behavior?

Posted: Wed Aug 12, 2015 3:41 pm
by DRW
When I write this:

Code: Select all

	LDA $2000
	STA $2000
this shouldn't do anything useful, right? It reads the value and writes it back.

So, how come that if I do this and then I do some background graphics work, that my new tiles are drawn vertically while they would be drawn horizontally without these two calls?

The acual code:

Code: Select all

	LDA $2000
	STA $2000
	; --> Should actually be useless, but influences the following output.
	
	LDA $2002
	LDA $20
	STA $2006
	LDA $00
	STA $2006
	
	LDX #$00
@loop:
	LDA TilesForUpdate, X
	STA $2007
	INX
	CPX #TILES_FOR_UPDATE_COUNT
	BNE @loop

Re: Reading and saving $2000: Why does this change the behav

Posted: Wed Aug 12, 2015 3:51 pm
by rainwarrior
I believe $2000 is a write-only register, which means trying to read it will give you some sort of open busweird behaviour? It doesn't give you the contents of the register. (You need to store that in a variable if you want to recover it later.)

Edit: tepples explains in detail below.

Re: Reading and saving $2000: Why does this change the behav

Posted: Wed Aug 12, 2015 3:58 pm
by DRW
O.k., I'll do. I didn't know that you cannot read from it. But it makes sense since all these $200x values are just for writing.

Re: Reading and saving $2000: Why does this change the behav

Posted: Wed Aug 12, 2015 4:00 pm
by rainwarrior
$2002 is just for reading.

$2004 and $2007 are read-write, though there are some big caveats about reading from $2007 (there is a buffer delay, it's... weird)

wiki: PPU registers

Re: Reading and saving $2000: Why does this change the behav

Posted: Wed Aug 12, 2015 6:17 pm
by tepples
Reading any write-only PPU port will give you the last value written to or read from any PPU port. For example, if you just wrote to $2001 or $2007, then reading $2000 will return that last value you wrote. Reading video memory through $2007 also sets the previous value. Reads from $2002 return the status in bits 7-5 and bits 4-0 of the previous value in bits 4-0. (Low-level explanation: The PPU uses an 8-bit internal data bus for communication with the CPU, which functions as a dynamic latch.)

But I'd recommend against relying on that behavior, as a dynamic latch decays at an unspecified rate, and emulators and famiclones are unlikely to implement it perfectly. If you want to do read-modify-write on a PPU port, save a backup copy of the port in a variable in RAM:

Code: Select all

VRAM_DOWN = $04

  lda last_PPUCTRL
  ora #VRAM_DOWN
  sta last_PPUCTRL
  sta $2000

Re: Reading and saving $2000: Why does this change the behav

Posted: Wed Aug 12, 2015 9:06 pm
by rainwarrior
tepples wrote:a dynamic latch decays at an unspecified rate, and emulators and famiclones are unlikely to implement it perfectly
I'm trying to imagine an emulator with a room temperature setting, and simulation of heat dissipation within the NES.

Re: Reading and saving $2000: Why does this change the behav

Posted: Thu Aug 13, 2015 1:02 am
by DRW
tepples wrote:But I'd recommend against relying on that behavior
Exactly. After reading all your posts, I won't try to read any of these values at all. If I still need the value, I'll save it into an own variable.

Re: Reading and saving $2000: Why does this change the behav

Posted: Sat Aug 15, 2015 9:16 pm
by bootmii
rainwarrior wrote:
tepples wrote:a dynamic latch decays at an unspecified rate, and emulators and famiclones are unlikely to implement it perfectly
I'm trying to imagine an emulator with a room temperature setting, and simulation of heat dissipation within the NES.
Can you also simulate ZIF stress if region is not set to Japan? :mrgreen:

Re: Reading and saving $2000: Why does this change the behav

Posted: Sun Aug 16, 2015 6:32 am
by tepples
bootmii wrote:Can you also simulate ZIF stress if region is not set to Japan? :mrgreen:
Not if we're also simulating a Blinking Light Win.

Re: Reading and saving $2000: Why does this change the behav

Posted: Sun Aug 16, 2015 10:51 am
by Quietust
tepples wrote:But I'd recommend against relying on that behavior, as a dynamic latch decays at an unspecified rate, and emulators and famiclones are unlikely to implement it perfectly.
Interestingly, it's not a true dynamic latch - the value just sits on the bus lines (via capacitance). Furthermore, writing to VRAM via $2007 actually "stores" the to-be-written value directly on the bus, relying on it not decaying within the dozen or so cycles it takes for the VRAM write to finish. If you were somehow able to write to another PPU register before the VRAM write finished, you'd overwrite the value to be written.