Actually provide proper OAM memory domain in bsnes
This commit is contained in:
parent
cc0b6c0d99
commit
83e784ecec
Assets/dll
src/BizHawk.Emulation.Cores/Consoles/Nintendo/BSNES
waterbox/bsnescore/bsnes/target-bsnescore
Binary file not shown.
|
@ -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);
|
||||
|
|
|
@ -102,7 +102,7 @@
|
|||
WRAM,
|
||||
APURAM,
|
||||
VRAM,
|
||||
OBJECTS,
|
||||
OAM,
|
||||
CGRAM,
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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();
|
||||
|
@ -131,7 +114,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.BSNES
|
|||
cachedTiles[3] ??= new byte[pixelCount];
|
||||
|
||||
for (int i = 0; i < pixelCount; i++)
|
||||
cachedTiles[3][i] = vram[2*i + 1];
|
||||
cachedTiles[3][i] = vram[2 * i + 1];
|
||||
}
|
||||
|
||||
private void CacheTilesMode7ExtBg()
|
||||
|
@ -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,
|
||||
|
@ -255,7 +238,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.BSNES
|
|||
|
||||
public TileEntry[] FetchMode7Tilemap()
|
||||
{
|
||||
var buf = new TileEntry[128*128];
|
||||
var buf = new TileEntry[128 * 128];
|
||||
for (int tidx = 0; tidx < 128 * 128; tidx++)
|
||||
{
|
||||
buf[tidx].address = tidx * 2;
|
||||
|
@ -270,7 +253,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.BSNES
|
|||
Dimensions blockDimensions = SizeInBlocksForBGSize(size);
|
||||
int realWidth = blockDimensions.Width * 32;
|
||||
int realHeight = blockDimensions.Height * 32;
|
||||
TileEntry[] buf = new TileEntry[realWidth*realHeight];
|
||||
TileEntry[] buf = new TileEntry[realWidth * realHeight];
|
||||
|
||||
for (int by = 0; by < blockDimensions.Height; by++)
|
||||
for (int bx = 0; bx < blockDimensions.Width; bx++)
|
||||
|
@ -343,38 +326,38 @@ 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;
|
||||
for(int oy=0;oy<dim.Height;oy++)
|
||||
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;
|
||||
|
||||
dx += destx;
|
||||
dy += desty;
|
||||
|
||||
if(dx>=xlimit || dy>=ylimit || dx<0 || dy<0)
|
||||
if (dx >= xlimit || dy >= ylimit || dx < 0 || dy < 0)
|
||||
continue;
|
||||
|
||||
int col = (bcol + (ox >> 3)) & 0xF;
|
||||
|
@ -382,10 +365,10 @@ namespace BizHawk.Emulation.Cores.Nintendo.BSNES
|
|||
int sx = ox & 0x7;
|
||||
int sy = oy & 0x7;
|
||||
|
||||
int addr = baseaddr*2 + (row * 16 + col) * 64;
|
||||
int addr = baseaddr * 2 + (row * 16 + col) * 64;
|
||||
addr += sy * 8 + sx;
|
||||
|
||||
int dofs = stride*dy+dx;
|
||||
int dofs = stride * dy + dx;
|
||||
int color = cachedTileBuffer[addr];
|
||||
if (spriteMap != null && color == 0)
|
||||
{
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -473,7 +456,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.BSNES
|
|||
M7SEL_VFLIP = _api.core.snes_peek_logical_register(M7SEL_VFLIP) == 1
|
||||
};
|
||||
|
||||
screenInfo.ObjSizeBounds = ObjSizes[screenInfo.OBSEL_Size,1];
|
||||
screenInfo.ObjSizeBounds = ObjSizes[screenInfo.OBSEL_Size, 1];
|
||||
int square = Math.Max(screenInfo.ObjSizeBounds.Width, screenInfo.ObjSizeBounds.Height);
|
||||
screenInfo.ObjSizeBoundsSquare = new Size(square, square);
|
||||
|
||||
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -21,7 +21,7 @@ enum SNES_MEMORY {
|
|||
WRAM,
|
||||
APURAM,
|
||||
VRAM,
|
||||
OBJECTS,
|
||||
OAM,
|
||||
CGRAM
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in New Issue