Actually provide proper OAM memory domain in bsnes

This commit is contained in:
Morilli 2023-12-10 00:48:50 +01:00
parent cc0b6c0d99
commit 83e784ecec
7 changed files with 68 additions and 51 deletions

Binary file not shown.

View File

@ -46,6 +46,10 @@ namespace BizHawk.Emulation.Cores.Nintendo.BSNES
[BizImport(CallingConvention.Cdecl)]
public abstract void snes_bus_write(uint address, byte value);
[BizImport(CallingConvention.Cdecl)]
public abstract byte snes_read_oam(ushort address);
[BizImport(CallingConvention.Cdecl)]
public abstract void snes_write_oam(ushort address, byte value);
[BizImport(CallingConvention.Cdecl)]
public abstract IntPtr snes_get_sgb_memory_region(int id, out int size);
[BizImport(CallingConvention.Cdecl)]
public abstract byte snes_sgb_bus_read(ushort address);

View File

@ -102,7 +102,7 @@
WRAM,
APURAM,
VRAM,
OBJECTS,
OAM,
CGRAM,
}

View File

@ -14,6 +14,13 @@ namespace BizHawk.Emulation.Cores.Nintendo.BSNES
foreach (int i in Enum.GetValues(typeof(BsnesApi.SNES_MEMORY)))
{
var data = Api.core.snes_get_memory_region(i, out var size, out var wordSize);
if (i == (int)BsnesApi.SNES_MEMORY.OAM)
{
mm.Add(new MemoryDomainDelegate("OAM", size, MemoryDomain.Endian.Little,
address => Api.core.snes_read_oam((ushort)address),
(address, value) => Api.core.snes_write_oam((ushort)address, value), wordSize));
continue;
}
if (data == IntPtr.Zero) continue;
if (i == (int) BsnesApi.SNES_MEMORY.CARTRAM)
{

View File

@ -1,6 +1,5 @@
using System;
using System.Drawing;
using System.Runtime.InteropServices;
using BizHawk.Emulation.Cores.Nintendo.SNES;
using static BizHawk.Emulation.Cores.Nintendo.BSNES.BsnesApi.SNES_REGISTER;
using static BizHawk.Emulation.Cores.Nintendo.SNES.SNESGraphicsDecoder;
@ -9,23 +8,8 @@ namespace BizHawk.Emulation.Cores.Nintendo.BSNES
{
public sealed unsafe class SNESGraphicsDecoder : ISNESGraphicsDecoder
{
[StructLayout(LayoutKind.Sequential)]
public struct Object // size: 10 bytes; equivalent to the c++ version
{
public readonly ushort x;
public readonly byte y;
public readonly byte character;
public readonly bool nameSelect;
public readonly bool vflip;
public readonly bool hflip;
public readonly byte priority;
public readonly byte palette;
public readonly bool size;
}
private readonly BsnesApi _api;
private readonly byte* vram; // waterbox pointer, ALWAYS access with EnterExit()
private readonly Object* objects; // waterbox pointer, ALWAYS access with EnterExit()
private readonly ushort* cgram; // waterbox pointer, ALWAYS access with EnterExit()
private readonly byte[][] cachedTiles = new byte[5][];
private readonly int[] bppArrayIndex = { 0, 0, 0, 0, 1, 0, 0, 0, 2 };
@ -66,7 +50,6 @@ namespace BizHawk.Emulation.Cores.Nintendo.BSNES
{
_api = api;
vram = (byte*)api.core.snes_get_memory_region((int)BsnesApi.SNES_MEMORY.VRAM, out _, out _);
objects = (Object*)api.core.snes_get_memory_region((int)BsnesApi.SNES_MEMORY.OBJECTS, out _, out _);
cgram = (ushort*)api.core.snes_get_memory_region((int)BsnesApi.SNES_MEMORY.CGRAM, out _, out _);
generate_palette();
generate_directColorTable();
@ -157,7 +140,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.BSNES
}
}
public ISNESGraphicsDecoder.OAMInfo CreateOAMInfo(ScreenInfo si, int num) => new OAMInfo(objects, si, num);
public ISNESGraphicsDecoder.OAMInfo CreateOAMInfo(ScreenInfo si, int num) => new OAMInfo(_api.core.snes_read_oam, si, num);
public void DecodeBG(
int* screen,
@ -343,31 +326,31 @@ namespace BizHawk.Emulation.Cores.Nintendo.BSNES
int destx,
int desty, ScreenInfo si,
int spritenum,
ISNESGraphicsDecoder.OAMInfo oam,
ISNESGraphicsDecoder.OAMInfo oamInfo,
int xlimit,
int ylimit,
byte[,] spriteMap)
{
oam ??= new OAMInfo(objects, si, spritenum);
Size dim = ObjSizes[si.OBSEL_Size, oam.Size ? 1 : 0];
oamInfo ??= new OAMInfo(_api.core.snes_read_oam, si, spritenum);
Size dim = ObjSizes[si.OBSEL_Size, oamInfo.Size ? 1 : 0];
byte[] cachedTileBuffer = cachedTiles[bppArrayIndex[4]];
int baseaddr = oam.Table ? si.OBJTable1Addr : si.OBJTable0Addr;
int baseaddr = oamInfo.Table ? si.OBJTable1Addr : si.OBJTable0Addr;
//TODO - flips of 'undocumented' rectangular oam settings are wrong. probably easy to do right, but we need a test
int bcol = oam.Tile & 0xF;
int brow = (oam.Tile >> 4) & 0xF;
int bcol = oamInfo.Tile & 0xF;
int brow = (oamInfo.Tile >> 4) & 0xF;
for (int oy = 0; oy < dim.Height; oy++)
for (int ox = 0; ox < dim.Width; ox++)
{
int dy, dx;
if (oam.HFlip)
if (oamInfo.HFlip)
dx = dim.Width - 1 - ox;
else dx = ox;
if (oam.VFlip)
if (oamInfo.VFlip)
dy = dim.Height - 1 - oy;
else dy = oy;
@ -394,7 +377,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.BSNES
else
{
screen[dofs] = color;
Paletteize(screen, dofs, oam.Palette * 16 + 128, 1);
Paletteize(screen, dofs, oamInfo.Palette * 16 + 128, 1);
Colorize(screen, dofs, 1);
if (spriteMap != null) spriteMap[dx, dy] = (byte)spritenum;
}
@ -623,17 +606,26 @@ namespace BizHawk.Emulation.Cores.Nintendo.BSNES
public bool Size { get; }
public int Address { get; }
public unsafe OAMInfo(SNESGraphicsDecoder.Object* objects, ScreenInfo si, int index)
public OAMInfo(Func<ushort, byte> readOam, ScreenInfo si, int index)
{
X = objects[index].x;
Y = objects[index].y;
Table = objects[index].nameSelect;
Palette = objects[index].palette;
Priority = objects[index].priority;
HFlip = objects[index].hflip;
VFlip = objects[index].vflip;
Size = objects[index].size;
byte character = objects[index].character;
ushort lowaddr = (ushort)(index * 4);
X = readOam(lowaddr++);
Y = readOam(lowaddr++);
byte character = readOam(lowaddr++);
Table = (readOam(lowaddr) & 1) == 1;
Palette = (readOam(lowaddr) >> 1) & 7;
Priority = (byte)((readOam(lowaddr) >> 4) & 3);
HFlip = ((readOam(lowaddr) >> 6) & 1) == 1;
VFlip = ((readOam(lowaddr) >> 7) & 1) == 1;
int highaddr = index / 4;
int shift = (index % 4) * 2;
byte high = readOam((ushort)(512 + highaddr));
bool highX = (high & (1 << shift++)) != 0;
Size = (high & (1 << shift)) != 0;
if (highX) X += 256;
Tile = character + (Table ? 256 : 0);
Address = character * 32 + (Table ? si.OBJTable1Addr : si.OBJTable0Addr);
Address &= 0xFFFF;

View File

@ -405,11 +405,11 @@ EXPORT void* snes_get_memory_region(int id, int* size, int* word_size)
*size = sizeof(ppufast.vram);
*word_size = sizeof(*ppufast.vram);
return ppufast.vram;
case SNES_MEMORY::OBJECTS: // returns a pointer to an array of "objects", not raw OAM memory
case SNES_MEMORY::OAM:
if (!fast_ppu) break;
*size = sizeof(ppufast.objects);
*word_size = sizeof(*ppufast.objects);
return (void*) ppufast.objects;
*size = (128 * 32 + 128 * 2) / 8;
*word_size = 1;
return nullptr; // needs read_oam / write_oam functions below
case SNES_MEMORY::CGRAM:
if (!fast_ppu) break;
*size = sizeof(ppufast.cgram);
@ -430,6 +430,20 @@ EXPORT void snes_bus_write(unsigned addr, uint8_t value)
bus.write(addr, value);
}
EXPORT uint8_t snes_read_oam(uint16_t addr)
{
if (!SuperFamicom::system.fastPPU()) return 0;
return ppufast.readObject(addr);
}
EXPORT void snes_write_oam(uint16_t addr, uint8_t value)
{
if (!SuperFamicom::system.fastPPU()) return;
return ppufast.writeObject(addr, value);
}
EXPORT void* snes_get_sgb_memory_region(int id, int* size)
{
if(!emulator->loaded()) return nullptr;

View File

@ -21,7 +21,7 @@ enum SNES_MEMORY {
WRAM,
APURAM,
VRAM,
OBJECTS,
OAM,
CGRAM
};