Wikia

ROM Hack City

Watchlist Recent changes

Detection of SMC header in BSNES, Snes9x

Kernigh September 19, 2009

BSNES and Snes9x use different methods to detect if the ROM image of some SNES game has an SMC header of 512 bytes ($200 bytes in hexadecimal).

Snes9x Edit

For Snes9x, the crucial function is CMemory::LoadROM in memmap.cpp, which calls FileLoader to read the ROM image. FileLoader reads the file and calls HeaderRemove. For each file, HeaderRemove removes the header if the file size divided by $2000 has remainder $200.

uint32 CMemory::HeaderRemove (uint32 size, int32 &headerCount, uint8 *buf)
{
        uint32  calc_size = (size / 0x2000) * 0x2000;

        if ((size - calc_size == 512 && !Settings.ForceNoHeader) || Settings.ForceHeader)
        {
                ...

                memmove(buf, buf + 512, calc_size);
                headerCount++;
                size -= 512;
        }

        return (size);
}

If HeaderRemove removed the header, then headerCount is 1, else headerCount if 0. (For a multi-file ROM image, FileLoader calls HeaderRemove for each file, so headerCount can be greater than 1.)

Then LoadROM calls ScoreLoROM and ScoreHiROM to examine the candidate SNES headers at offsets x7fc0 and xffc0. If headerCount is zero, then FileLoader again calls ScoreLoROM and ScoreHiROM to examine the candidate SNES headers at offsets x7fc0 + x200 and xffc0 + x200. If the SNES header at x7fc0 + x200 or xffc0 + x200 has the highest score, then LoadROM removes the SMC header.

int CMemory::ScoreHiROM (bool8 skip_header, int32 romoff)
{
        uint8   *buf = ROM + 0xff00 + romoff + (skip_header ? 0x200 : 0);
        ...

int CMemory::ScoreLoROM (bool8 skip_header, int32 romoff)
{
        uint8   *buf = ROM + 0x7f00 + romoff + (skip_header ? 0x200 : 0);
        ...

bool8 CMemory::LoadROM (const char *filename)
{
        ...

        hi_score = ScoreHiROM(FALSE);
        lo_score = ScoreLoROM(FALSE);

        if (HeaderCount == 0 && !Settings.ForceNoHeader &&
                ((hi_score >  lo_score && ScoreHiROM(TRUE) > hi_score) ||
                 (hi_score <= lo_score && ScoreLoROM(TRUE) > lo_score)))
        {
                memmove(ROM, ROM + 512, totalFileSize - 512);
                totalFileSize -= 512;
                ...
                // modifying ROM, so we need to rescore
                hi_score = ScoreHiROM(FALSE);
                lo_score = ScoreLoROM(FALSE);
        }

BSNES Edit

For BSNES, the crucial function is Utility::loadCartridge in src/ui_qt/utility/cartridge.cpp, which has exactly one line of code to check the SMC header. BSNES removes the header if the file size divided by $8000 has remainder $200.

 //remove copier header, if it exists
 if((size & 0x7fff) == 512) memmove(data, data + 512, size -= 512);

BSNES, unlike Snes9x, never uses the SNES header to decide whether to remove the SMC header. In BSNES, Cartridge::find_header in src/cartridge/header.cpp only examines the candidate SNES headers at x7fc0, xffc0 and x40ffc0.

unsigned Cartridge::find_header(const uint8_t *data, unsigned size) const {
  unsigned score_lo = score_header(data, size, 0x007fc0);
  unsigned score_hi = score_header(data, size, 0x00ffc0);
  unsigned score_ex = score_header(data, size, 0x40ffc0);
  if(score_ex) score_ex += 4;  //favor ExHiROM on images > 32mbits

  if(score_lo >= score_hi && score_lo >= score_ex) {
    return 0x007fc0;
  } else if(score_hi >= score_ex) {
    return 0x00ffc0;
  } else {
    return 0x40ffc0;
  }
}

Conclusion Edit

Snes9x divides the ROM size by 0x2000; BSNES divides the ROM size by $8000. If the remainder equals 0x200, then these emulators remove the SMC header of $200 bytes.

Snes9x also removes the SMC header if the candidate SNES header at offset x7fc0 + x200 or xffc0 + x200 has a higher score. BSNES does not consider these candidates.

  • Showing 0 most recent

0 comments

 
10.8.56.52Anonymous User
Log in?
  Loading editor

Pages on ROM Hack City

Add a Page
77pages on
this wiki
Advertisement | Your ad here

Latest Photos

Add a Photo
14photos on this wiki
See more >

No recent blog posts. Write one now!


What are Wikia Blogs?

Wikia community blogs allow you to contribute a blog post to any wiki's Community Blog.

Blogs are used by wiki communities for fan fiction or original work, news and announcements, questions or recommendations to the community, or reviews or op-eds. Check out Fallout Wiki's News Blog and Lostpedia's Theories Blog to see two examples.

Around Wikia's network

Random Wiki