Forums

Sega Master System / Mark III / Game Gear
SG-1000 / SC-3000 / SF-7000 / OMV
Home - Forums - Games - Scans - Maps - Cheats - Credits
Music - Videos - Development - Hacks - Translations - Homebrew

View topic - What *is* proper behavior for the Mirrored RAM?

Reply to topic
Author Message
vecna
  • Guest
Reply with quote
What *is* proper behavior for the Mirrored RAM?
Post Posted: Wed Mar 29, 2000 7:48 pm
After my last post, Charles Mac Donald pointed out that I wasn't handling the mirrored RAM region correctly.. In fact, he was right - I had read in one of the docs that it was "Incomplete and shouldn't be used" -- so I didn't, at all. ^_^; Anyhow, now that I've implemented it, a bunch more games work, but now I'm left confused about just how it IS supposed to behave. I recently implemented SaveRAM stuff, and Phantasy Star for instance, works perfectly [PS now works 100% accurate]. But, Penguin Land wasn't loading the RAM, and, upon investigation, it never even touched 0xFFFC. It DID however touch 0xDFFC, and so I figured, aha, it's writing to that region instead, and I need to treat the mirror RAM exactly as the primary RAM, including the bank-switching bytes.

I did this, tho, and basically, it broke a whole crapload of games. One of these games was Hang-On, and I upon dissassembly I noticed that Hang-On puts SP at 0xDFFE -- Which would overwrite the bank registers if the RAM and the mirror RAM were truly equal. So... What's going on? If a program reads 0xDFFE for instance, should they get the same value as reading 0xFFFE, or should they get a value seperate to that main 8k RAM?

Oh, and thanks for all the responses regarding my last post, guys. :) I really appreciate the help. I got rid of the ghost sprites after all -- a simple miscommunication, I was starting from the LAST instance of a 208 yvalue, rather than the first instance of it, and that was causing my problems. My lineints are still bjorked, but I'm gonna worry about other things first. ^_^

- vecna
 
Nyef
  • Guest
Reply with quote
Post Posted: Wed Mar 29, 2000 8:04 pm
My parse on mirrored RAM (and I could very well be wrong about this) is that there is RAM from 0xC000-0xDFFF, and it is mirrored at 0xE000-0xEFFF. All reads and writes to these locations behave identically WRT the RAM.

The paging registers, on the other hand, are write-only, and mapped to 0xFFFC-0xFFFF. Any reads from these locations will simply load a value from RAM withoug affecting paging (there is another possibility, but it's too horrible to contemplate). Any writes to these locations not only write to the paging registers, but also write to RAM (I am told that the NES sound registers function the same way if you map RAM into that section of the address space).

Hope this helps.

--Nyef
 
Eric
  • Guest
Reply with quote
Post Posted: Wed Mar 29, 2000 8:24 pm
Quote
> My parse on mirrored RAM (and I could very well be wrong about this) is that there is RAM from 0xC000-0xDFFF, and it is mirrored at 0xE000-0xEFFF. All reads and writes to these locations behave identically WRT the RAM.

I concur. Note that this means WRITING to 0xDFFC - 0xDFFF does NOT write to the paging registers 0xFFFC - 0xFFFF. (This is why Hang-On can safely load SP with 0xDFFE).

Quote
> The paging registers, on the other hand, are write-only, and mapped to 0xFFFC-0xFFFF. Any reads from these locations will simply load a value from RAM withoug affecting paging (there is another possibility, but it's too horrible to contemplate). Any writes to these locations not only write to the paging registers, but also write to RAM (I am told that the NES sound registers function the same way if you map RAM into that section of the address space).

Yes, I agree. Additionally, the above explanations are in accordance with Mail Extract #2 available in the Technical Documents section.

Also, if I can be so bold, I'd like to suggest a "SMS/GG Programming Guideline":

Never write to RAM at addresses 0xDFFC through 0xDFFF. You can then use these addresses to read the current paging register values at any time.


Eric Quinn
 
Nyef
  • Guest
Reply with quote
Post Posted: Wed Mar 29, 2000 8:34 pm
Quote
> Never write to RAM at addresses 0xDFFC through 0xDFFF. You can then use these addresses to read the current paging register values at any time.

I'm afraid I have to dsagree here. I would much rather store a current copy elsewhere (so I can safely change it during an IRQ handler), than consider the values in those locations "correct". The real reason for not storing information in those memory areas is that an interrupt can change them at any time. Besides, in many cases, the current value of the paging registers is known at compile time (hint: the code executing in a given bank knows what bank it's in).

Quote
> Eric Quinn

--Nyef
 
Eric
  • Guest
Reply with quote
Post Posted: Wed Mar 29, 2000 10:02 pm
Quote
> > Never write to RAM at addresses 0xDFFC through 0xDFFF. You can then use these addresses to read the current paging register values at any time.

> I'm afraid I have to dsagree here. I would much rather store a current copy elsewhere (so I can safely change
> it during an IRQ handler), than consider the values in those locations "correct". The real reason for not
> storing information in those memory areas is that an interrupt can change them at any time.

Presumably, a programmer writes his/her own interrupt handlers (or at least understands how they work so simple modifications can be made). If a programmer obeyed the guideline, then the interrupt handlers wouldn't write to those addresses either. Interrupts don't pose a problem. Additionally, there wouldn't be a problem with the stack overwriting it, since the SP can be initialized to 0xDFFB. (A stack underflow would be a problem but an underflow indicates a serious programming bug.)

The difficulty with storing the paging register values elsewhere is making sure the variables are updated every time the paging registers are written. Forgetting to do this would result in some tricky bugs to track down.


Quote
> Besides, in many cases, the current value of the paging registers is known at compile time (hint: the code
> executing in a given bank knows what bank it's in).

Yes, but it doesn't know what is in the other banks. I can imagine cases where "reusable" library functions may need to know what pages are mapped into addressable space at run-time.

In any case, if a library of SMS/GG code is to be created a standard on where/how to retrieve the paging register values needs to be established. Either no code should write to 0xDFFC-0xDFFF, OR a pre-defined standard memory area is reserved for saving the values and every paging register write is accompanied by a write to the reserved memory area.


Eric Quinn
 
Nyef
  • Guest
Reply with quote
Post Posted: Thu Mar 30, 2000 1:10 pm
Quote
> > > Never write to RAM at addresses 0xDFFC through 0xDFFF. You can then use these addresses to read the current paging register values at any time.

> > I'm afraid I have to dsagree here. I would much rather store a current copy elsewhere (so I can safely change
> > it during an IRQ handler), than consider the values in those locations "correct". The real reason for not
> > storing information in those memory areas is that an interrupt can change them at any time.

> Presumably, a programmer writes his/her own interrupt handlers (or at least understands how they work so simple modifications can be made). If a programmer obeyed the guideline, then the interrupt handlers wouldn't write to those addresses either. Interrupts don't pose a problem. Additionally, there wouldn't be a problem with the stack overwriting it, since the SP can be initialized to 0xDFFB. (A stack underflow would be a problem but an underflow indicates a serious programming bug.)

No, the interrupt handler might write to the mirrored locations at 0xfffc-0xffff. Then what does it do when it wants to return?

Quote
> The difficulty with storing the paging register values elsewhere is making sure the variables are updated every time the paging registers are written. Forgetting to do this would result in some tricky bugs to track down.

So make a procedure to do the bankswitching for you. Kinda hard to forget that way, isn't it?

Quote
> > Besides, in many cases, the current value of the paging registers is known at compile time (hint: the code
> > executing in a given bank knows what bank it's in).

> Yes, but it doesn't know what is in the other banks. I can imagine cases where "reusable" library functions may need to know what pages are mapped into addressable space at run-time.

So can I. But does it really matter where where it looks for the information?

Quote
> In any case, if a library of SMS/GG code is to be created a standard on where/how to retrieve the paging register values needs to be established. Either no code should write to 0xDFFC-0xDFFF, OR a pre-defined standard memory area is reserved for saving the values and every paging register write is accompanied by a write to the reserved memory area.

"Let's do both!" [bonks a monitor with a root beer bottle].

I'm not arguing with your idea that those memory locations shouldn't be written to, I'm arguing with your reason why.

And I really don't see a problem with people each writing their own libraries. Especially since different games might want completely different libraries.

Quote
> Eric Quinn

--Nyef
 
Eric
  • Guest
Reply with quote
Post Posted: Thu Mar 30, 2000 6:23 pm
Quote
> No, the interrupt handler might write to the mirrored locations at 0xfffc-0xffff. Then what does it do when it wants to return?

Well, just as an interrupt handler needs to save and restore the general-purpose registers (on the stack) at the beginning and end of the handler, so too should it save the paging register values (read from 0xDFFC-0xDFFF) before it writes to them and restore them before RETI/RETN.

Quote
> > The difficulty with storing the paging register values elsewhere is making sure the variables are updated every time the paging registers are written. Forgetting to do this would result in some tricky bugs to track down.

> So make a procedure to do the bankswitching for you. Kinda hard to forget that way, isn't it?

Good point.

Quote
> > > Besides, in many cases, the current value of the paging registers is known at compile time (hint: the code
> > > executing in a given bank knows what bank it's in).

> > Yes, but it doesn't know what is in the other banks. I can imagine cases where "reusable" library functions may need to know what pages are mapped into addressable space at run-time.

> So can I. But does it really matter where where it looks for the information?

Does it really matter? No. Does it slightly matter? Yes, it slightly matters to me.

My argument (and guideline) are motivated by the facts that:

1.) I would definitely like to see a library of SMS/GG code created. One that can be used by assembly programmers and high-level language (C/C++) programmers alike. I feel that even though, as you say, different games may require custom functions, a library can only help to improve development time.

2.) Library code should only use dynamic memory allocation (either in a stack frame or from the heap). I believe that reserving a fixed static area in RAM for library data (such as would be required by the scheme you suggest) only complicates the memory map. However, I admit that a static library data area may prove to be necessary anyway (in which case there's no reason not to use your method.)

It seems, though, that the issue is moot until someone starts creating a library. (Which I would do, but I'm still working on my emulator.) Until that time, then, to each his own.


Eric Quinn
 
Reply to topic



Back to the top of this page

Back to SMS Power!