+  RHDN Forum Archive
|-+  Romhacking
| |-+  ROM Hacking Discussion
| | |-+  SNES SRAM reading not working.
Pages: [1]
Author Topic: SNES SRAM reading not working.  (Read 2 times)
KingMike
Guest
« on: March 23, 2008, 01:18:36 pm »

EDIT: Fine, I've figured it out. $70:0000 = start of SRAM, not $70:8000. But shouldn't they be a mirror of the same thing (with only the minimum size $800)?


I'm hacking an SNES game to store passwords in SRAM.
I've gotten it to write passwords to SRAM successfully (starting at offset 0 in SRAM).
The game uses Mode 20, and I set it to use 2KB SRAM (the smallest).
I use a routine to load the password using LDA $708000,X and it seems to return a bunch of zeros, then $FA (this game uses $FA $FF as a code to signify the end of the password). I've checked the SRAM file in a hex editor and the initial data is not 0.
I ran the game in an emulator and saw the timestamp was updated, so I believe I'm looking at the SRAM in the proper directory (I know newer versions of SNES9x do some weird thing where they load from the ROM directory but save to their own directory), and reopened it to verify the SRAM data is indeed not zeroes.

Code:
CheckLoad:
REP #$20
LDA $7E  ;RAM variable with last registered button press
CMP #$4000 ;(I thought this was SELECT, but I guess it actually registers if Y is pressed)
BNE SkipLoad
STZ $7E
PHX
PHY
SEP #$20
LDX #$00 ;read from address
LDY #$00 ;write to address
LoadPassword:
LDA $708000,X
CMP #$FA
BEQ ReturnFromLoadCheck
CMP #$6F
BEQ SkipSpace  ;space character that must be stripped out
STA $084E,Y  ;password input buffer
INY
SkipSpace:
INX
BRA LoadPassword
ReturnFromLoadCheck:
REP #$20
PLY
PLX
SkipLoad:
LDA $7E
JML $03CCB0
« Last Edit: March 23, 2008, 11:00:28 pm by KingMike »
Nightcrawler
Guest
« Reply #1 on: March 24, 2008, 09:54:05 am »

Quote from: KingMike on March 23, 2008, 01:18:36 pm
EDIT: Fine, I've figured it out. $70:0000 = start of SRAM, not $70:8000. But shouldn't they be a mirror of the same thing (with only the minimum size $800)?

Why would you think they are mirrored?

Reread this post:

http://www.romhacking.net/forum/index.php/topic,5549.msg86934.html#msg86934

It's the same story here for bank $70. The only difference here is you've defined that the cart specifically responds with SRAM between $70:0000 and $70:0800. SRAM should not be accessible at any other address unless the cart were to map it. Smaller SRAM may repeat in the lower half of each bank in the 70-7d range (carts using the MAD-1 chip do this according to Neviksti) or it may map to ROM. In some cases you may also see it at bank F0. That's dependent on the cart really.

You shouldn't be accessing SRAM outside of the defined range though. I have read much conflicting information on mirrored SRAM. I'd be interested in byuu's comments here on how BSNES handles SRAM mapping in a case like this because all the discussion, documents, and information I can find are mostly theories that are cart dependent. It seems the most accepted mapping used is analysis of the MAD-1 decoder chip, however not all carts use that chip.

In summary, there is no clear answer I know of for 'standard' SRAM mapping beyond your defined starting spot.
KingMike
Guest
« Reply #2 on: March 24, 2008, 11:01:59 am »

As for mirroring, it was from looking at the development book, seems to indicate Mode 20 should have a RAM image there. Must be misreading it.

Might as well reveal it.
Super Ninja Boy is what I'm looking at.
When choosing PASSWORD on the main menu or at a convenience store, it'll prompt to record the password. Press B to save it and Y to not save.
On the password screen, press Y to load the saved password, then choose END to continue the game.

It works properly on ZSNES and SNES9X.
On bsnes, it mostly works, except that it doesn't display the save prompt text, nor does it display the password when loading it on the password screen. However, it is still functional.
But when I used a flashcart to play it on my actual SNES: the save prompt would not display (like bsnes) but the game continued, so I guess it worked.
But when I tried loading, the screen would display random garbage (0s at random points on the screen, slightly corrupted window border graphics) and crash. I've included the hack source if anyone wants to see what could be the problem.
I did
Code:
minus:
lda $4212 : bmi minus
plus:
lda $4212 : bpl plus
which I thought (from what byuu said in a response somewhere long ago about SNES VRAM access) is all that's necessary to ensure I write during VBlank.

Patch and source

(source ROM does not have a header. I used a ROM I dumped from my own cart, but it matches the good entry in NSRT's database)
Nightcrawler
Guest
« Reply #3 on: March 24, 2008, 01:04:51 pm »

The dev manual shows several PCB variations available for mode 20, but none of them allow for more than 256Kbit (32K or half a bank) of SRAM to be used as far as I see. They mentioned mirroring in the 71-7d range and some in the f0-ff range, however that's always the first 32K only. Anyway, as long as you access only 70:000 - 70:0800 for your SRAM access, that should work on all emulators and most  copiers and flashcarts I'd imagine. That seems to be what your findings are, right? Your problem is the text system only and not the actual data saving and retrieving from SRAM if I'm understanding you correctly.

A quick look at your code shows you seem to be using $4212 well enough for vblank waiting. Unfortunately, I don't have time for a closer look. I did notice this:

Code:
PassCopyLoop:
PassCopyLoop:
LDA $084E,X
STA $0883,X
PHX
LDX !SRAM_ADDRESS
STA $708000,X
DEC !SRAM_ADDRESS
PLX
DEX
BPL PassCopyLoop

You're still using the 708000 address here. Though it seems that's probably not cause of your described problem.
byuu
Guest
« Reply #4 on: March 25, 2008, 06:09:06 pm »

Since Nightcrawler is PMming me about this ...

bsnes SRAM mapper:

Code:
void sBus::map_generic_sram() {
  if(memory::cartram.size() == 0 || memory::cartram.size() == -1U) { return; }

  map(MapLinear, 0x20, 0x3f, 0x6000, 0x7fff, memory::cartram);
  map(MapLinear, 0xa0, 0xbf, 0x6000, 0x7fff, memory::cartram);

  //research shows only games with very large ROM/RAM sizes require MAD-1 memory mapping of SRAM
  //otherwise, default to safer, larger SRAM address window
  uint16 addr_hi = (memory::cartrom.size() > 0x200000 || memory::cartram.size() > 32 * 1024) ? 0x7fff : 0xffff;
  map(MapLinear, 0x70, 0x7f, 0x0000, addr_hi, memory::cartram);
  if(cartridge.info.mapper != Cartridge::LoROM) return;
  map(MapLinear, 0xf0, 0xff, 0x0000, addr_hi, memory::cartram);
}

MapLinear mode means that there's no shadowing. That means that if addr_hi = 0x8000, then 700000 = &SRAM[0 % SRAM_size], 710000 = &SRAM[0x8000 % SRAM_size], etc.

So, basically:

MAD-1: $[70-7f]:[0000-7fff] + LoROM ? $[f0-ff]:[0000-7fff]
74LS139: $[70-7f]:[0000-ffff] + LoROM ? $[f0-ff]:[0000-ffff] (required by Ys 3, etc)

Only HiROM really uses $[20-3f]:[6000-7fff] and $[a0-bf]:[6000-7fff], but some LoROM games might use it, too. Copiers map this range for LoROM as well. I'd say not to rely on that, just to be safe.

---

Bottom line, bsnes has some tests that basically make sure all commercial games work. The correct SRAM (and ROM) mapping depends upon the PCB and memory address decoder used. Sadly, that data is not dumped along with the actual cartridges.

Overload did a lot of research on this and began logging the PCB IDs for known games, so that the emulator implemented memory mapping correctly by matching CRCs to a database.

I wanted to move the PCB IDs to the ROM header, along with full, UTF-8 ROM titles (might as well use headers for something good, right?)

I tried to talk Nach into caching this information in the NSRT database, but he ignored me, saying that some carts have more than one PCB code (okay, log each observed one, default to the most common one -- no problem). He's happy that emulators can use a lot of black magic tests to get all known dumped games working in emulators. Basically, the games don't rely on the exact mappings, or they would fail.

Of course, that isn't foolproof, and I won't believe that it is until all PCBs are verified against actual carts. But, nothing I can do about it. I can't afford to obtain and re-dump all known SNES carts to get the info myself, so I'm at his mercy.

If someone rich wanted to donate a few thousand dollars, I'd go 50/50 and start mass purchasing carts, though. But yeah, I could never dump and verify something like FEoEZ : SJnS, that cart sells for several thousand dollars alone, and requires a specialized dumper due to the SPC7110.

But how awesome would it be to have a single, trusted source, to dump all carts, record SHA-512 hashes, PCB info, other cart info, and use a private key to sign the header cryptographically, so that nobody could ever fake the data again in the future? Why people trust [!] in a filename, which could be added by fucking anybody, is beyond me.

You'd distribute it as something like .cer(tificate), and emulators would load it just like .srm and .cht files now.
« Last Edit: March 25, 2008, 06:15:15 pm by byuu »
byuu
Guest
« Reply #5 on: March 25, 2008, 06:13:22 pm »

As for the text not appearing ...

Yes, that code will sync to vblank, but don't forget about NMIs / IRQs. If they trigger, they can eat up all of the available vblank time. The code after the sync and before / during the VRAM transfer may also eat up that time.

Try reading the vertical latch counter and logging it to SRAM somewhere after the VRAM transfer to make sure you had enough time (it should be >=225.)

Other factors may come into play ... illegal DMA transfer, DMA registers being modified by an interrupt, or your DMA register modifications throwing off the game itself that expects them not to be changed, etc etc.

Good luck with that.
Pages: [1]  


Powered by SMF 1.1.4 | SMF © 2006-2007, Simple Machines LLC