higan
higan copied to clipboard
icarus fails to import certain SMC files, based size
When attempting to import a ROM file of 4194816 bytes, icarus failed with the message "Error: missing program.rom"
Since this was an SMC file, it was recommended that I try stripping the 512 byte header, renaming with the extension .sfc and trying again. After doing so, icarus succeeded in importing the file and higan succeeded in running it.
Screwtape in the Discord was able to reproduce this problem with an empty file of the same size, with the additional commentary:
Looking at the icarus code, that message comes from:
if(size > buffer.size()) return {"missing ", filename};
That is, if the size expected by the generated manifest is larger than the actual file we have, it assumes the file is missing.
I think that I having this same issue. I'm trying to import the SMC file, but I'm getting the message "missing program.rom". Some SMC files with the same size works though, I'm not sure why. I didn't understand what you did to solve it. You said "stripping the 512 byte header, renaming with the extension .sfc" but i'm not sure what is the 512 byte header, can you explain to me? Thanks in advance.
Due to the way the SNES is constructed, a legitimate SNES ROM dump will always be a multiple of 32KB (32,767 bytes) in size: 32KB, 64KB, 96KB, 128KB, etc. Early ROM dumping tools (like the Super Magicom, hence "SMC") would dump the ROM contents, and add an extra 512 bytes at the beginning which contained device-specific data. As a result, when a SNES emulator tries to load a game, it takes the size and divides it by 32KB. If the remainder is exactly 512, there's a header, and it can be trimmed off before the game is loaded. bsnes actually does the same trick to supported embedded firmware blobs
Again due to a quirk of hardware, when a cartridge is inserted the SNES CPU will see not just a multiple of 32KB of data, but 32KB times some power of two: 32KB, 64KB, 128KB, 256KB, etc. If a cartridge contains some other amount of data, an effect called "mirroring" duplicates the cartridge contents up to the next power of two. For example, if a cartridge contains 192KB of data (6×32KB banks), the SNES will "see" the last two banks repeated, as if there were a full 256KB of data: 1, 2, 3, 4, 5, 6, 5, 6.
Some homebrew authors depend on the emulator implementing this "mirroring" behaviour: they produce a ROM file that is not a multiple of 32KB, and trust that the emulator will repeatedly mirror the last parts of the ROM until it reaches an appropriate size. Unfortunately, if the homebrew ROM just accidentally happens to be 512 bytes larger than a multiple of 32KB, the import process will assume there's a header and trim it off, rather than mirroring it out to the next larger block size.
To remove the 512byte header, if you're using Linux and are comfortable with the command-line, you can use a tool like dd
to do the job. If you're on Windows, you can probably find a SNES header removing tool by web-searching for "SNES header removing tool". Or, hopefully someday this issue will be fixed and you can just use icarus.
Thanks for the reply! Now I understand a little better how it works. I did as you say by searching "SNES header removing tool" on google and managed to find a variety of sites that convert .SMC to .SFC and it worked!
Bash script to remove the first 512 bytes others may find useful:
ext=`echo "$1" | cut -d'.' -f2`
fileNoExt=$(echo "$1" | cut -f 1 -d '.')
outFile="${fileNoExt}_noheader.${ext}"
dd bs=1 skip=512 if="$1" of="$outFile"
More info here.