Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Increase SNES max rom size #172

Open
raphatex opened this issue Dec 18, 2024 · 3 comments
Open

Increase SNES max rom size #172

raphatex opened this issue Dec 18, 2024 · 3 comments
Labels
enhancement New feature or request

Comments

@raphatex
Copy link

raphatex commented Dec 18, 2024

Currently the max rom size for SNES roms is 2.4MB or
Ox240000
The problem is that lot of roms are bigger than that so I increased it to 4MB or 0x400000 and It seems to work fine on the esp32-s3 with 8MB PSRAM.
I was wondering why this value was so low in the beginning (I guess that is because some modules have only 4MB PSRAM) and if it would be possible to add an option to the target config file or directly change it for all targets

@raphatex raphatex added the enhancement New feature or request label Dec 18, 2024
@ducalex
Copy link
Owner

ducalex commented Dec 19, 2024

The value is low because of limited memory yes and it took a lot of work to even get to that mere 2.25MB. I think it's a good idea to support larger sizes but I don't want to make it configurable (unless we have no other choice)...

The largest commercial ROM seems to be 6MB, max addressable is 8MB, and Snes9x originally had a 12MB MAX_ROM_SIZE (for reasons that are irrelevant to us). So I guess any of 4/6/8 would be reasonable upper limits.

But finding the lower limit is what we're concerned with. A few ideas:

  1. Check for available memory at run time and decide based on that. It's a bigger change across two components but it will be the most accurate because we can do things like "if 8MB PSRAM then allocate exactly 5.3628MB".

  2. Try the largest size then reduce it until it succeeds. I can already see problems with doing it in fixed steps of 512KB/1MB, but I can't think of any issue if we just continually divide by 2. The downside is that for 8MB PSRAM the ROM size will be 4MB, whereas it could fit possibly the full 6MB in reality.

But look how small the change would be:

 for (size_t AllocSize = 0x800000; AllocSize > 0 && !Memory.ROM; AllocSize /= 2)
 {
       Memory.ROM_AllocSize = AllocSize + 0x40000 + 0x200;
       Memory.ROM = (uint8_t*) calloc(Memory.ROM_AllocSize, 1);
 }

Let me know what you think!

@raphatex
Copy link
Author

raphatex commented Dec 19, 2024

It works fine indeed !
I'm trusting you on that change, but here is an another idea that rely on the same principe, we just try differents decreasing "exacts" values until it succeeds.
Anyway, the best option I can think about would be to check the rom size then try to allocate it in ram and if it fail we could have an error like "rom size: ROM_SIZE is too large" but it will be hard to handle .zip roms.
Also, I was wondering about the (+ 0x40000) ?
solution 1

bool S9xInitMemory(void)
{
   Memory.RAM   = (uint8_t*) calloc(RAM_SIZE, 1);
   Memory.SRAM  = (uint8_t*) calloc(SRAM_SIZE, 1);
   Memory.VRAM  = (uint8_t*) calloc(VRAM_SIZE, 1);
   Memory.FillRAM = (uint8_t*) calloc(0x8000, 1);

   Memory.Map = (uint8_t**)calloc(MEMMAP_NUM_BLOCKS, sizeof(uint8_t*));
   Memory.MapInfo = (SMapInfo*)calloc(MEMMAP_NUM_BLOCKS, sizeof(SMapInfo));

   IPPU.ScreenColors = (uint16_t *)calloc(256 * 9, sizeof(uint16_t));
   IPPU.DirectColors = IPPU.ScreenColors + 256;
   IPPU.TileCache = (uint8_t*) calloc(MAX_2BIT_TILES, 128);
   IPPU.TileCached = (uint8_t*) calloc(MAX_2BIT_TILES, 1);

   bytes0x2000 = (uint8_t *)calloc(0x2000, 1);

   // example list of "standard" rom sizes
   size_t AllocSizes[] = {0x800000, 0x600000, 0x400000, 0x200000, 0x100000, 0x80000, 0x40000};
   for (int i = 0; i < sizeof(AllocSizes) && !Memory.ROM; i += 1)
   {
      Memory.ROM_AllocSize = AllocSizes[i] + 0x200;
      Memory.ROM = (uint8_t*) calloc(Memory.ROM_AllocSize, 1);
   }

   if (!Memory.RAM || !Memory.SRAM || !Memory.VRAM || !Memory.ROM || !Memory.Map || !Memory.MapInfo
      || !IPPU.ScreenColors || !IPPU.TileCache || !IPPU.TileCached || !bytes0x2000)
   {
      S9xDeinitMemory();
      return false;
   }

   return true;
}

solution 2

bool S9xInitMemory(const char* filename)
{
   size_t TotalFileSize = 0;
   FILE *fp;

   Memory.RAM   = (uint8_t*) calloc(RAM_SIZE, 1);
   Memory.SRAM  = (uint8_t*) calloc(SRAM_SIZE, 1);
   Memory.VRAM  = (uint8_t*) calloc(VRAM_SIZE, 1);
   Memory.FillRAM = (uint8_t*) calloc(0x8000, 1);

   Memory.Map = (uint8_t**)calloc(MEMMAP_NUM_BLOCKS, sizeof(uint8_t*));
   Memory.MapInfo = (SMapInfo*)calloc(MEMMAP_NUM_BLOCKS, sizeof(SMapInfo));

   IPPU.ScreenColors = (uint16_t *)calloc(256 * 9, sizeof(uint16_t));
   IPPU.DirectColors = IPPU.ScreenColors + 256;
   IPPU.TileCache = (uint8_t*) calloc(MAX_2BIT_TILES, 128);
   IPPU.TileCached = (uint8_t*) calloc(MAX_2BIT_TILES, 1);

   bytes0x2000 = (uint8_t *)calloc(0x2000, 1);

   if (Memory.ROM_Offset)
   {
      Memory.ROM -= Memory.ROM_Offset;
      Memory.ROM_Offset = 0;
   }

   if ((fp = fopen(filename, "rb")))
   {
      fseek(fp, 0, SEEK_END);
      TotalFileSize = ftell(fp);
      fclose(fp);
   }
   else
   {
      printf("Failed to open %s\n", filename);
      return false;
   }

   Memory.ROM_AllocSize = TotalFileSize + 0x200;
   Memory.ROM = (uint8_t*) calloc(Memory.ROM_AllocSize, 1);

   if(!Memory.ROM){
      RG_LOGE("ROM too big for available memory");
      S9xDeinitMemory();
      return false;
   }

   if (!Memory.RAM || !Memory.SRAM || !Memory.VRAM || !Memory.Map || !Memory.MapInfo
      || !IPPU.ScreenColors || !IPPU.TileCache || !IPPU.TileCached || !bytes0x2000)
   {
      S9xDeinitMemory();
      return false;
   }

   return true;
}

edit: after implementing second method, 6MB roms launch and we have this RAM left
[debug] STACK:4836, HEAP:226+653 (132+640)

@raphatex raphatex changed the title Increase SNES max rom size to 4MB Increase SNES max rom size Dec 19, 2024
@ducalex
Copy link
Owner

ducalex commented Dec 24, 2024

Solution 1 is interesting (though your usage of sizeof makes you go out of the array) and might indeed be better than plain arithmetic.

Solution 2 is a no-go because it won't work with zip files, which are loaded outside snes9x and much later in the process :(.

I'll play around with solution 1 as well as the solutions I've proposed to see what works the best across all possible RAM configurations I have to support. But that might take some time, so I'll also add dumb support for 4MB ROMs right now to be sure it's part of the next release.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants