gbhawk gpu viewer: work correctly with palettes and CGB extended BG data
This commit is contained in:
parent
271d4102e8
commit
32a3d9db80
|
@ -149,10 +149,15 @@ namespace BizHawk.Emulation.Consoles.GB
|
|||
if (scanlinecallback != null)
|
||||
{
|
||||
IntPtr vram = IntPtr.Zero;
|
||||
int vramlength = 0;
|
||||
if (!LibGambatte.gambatte_getmemoryarea(GambatteState, LibGambatte.MemoryAreas.vram, ref vram, ref vramlength))
|
||||
IntPtr bgpal = IntPtr.Zero;
|
||||
IntPtr sppal = IntPtr.Zero;
|
||||
int unused = 0;
|
||||
if (!LibGambatte.gambatte_getmemoryarea(GambatteState, LibGambatte.MemoryAreas.vram, ref vram, ref unused)
|
||||
|| !LibGambatte.gambatte_getmemoryarea(GambatteState, LibGambatte.MemoryAreas.bgpal, ref bgpal, ref unused)
|
||||
|| !LibGambatte.gambatte_getmemoryarea(GambatteState, LibGambatte.MemoryAreas.sppal, ref sppal, ref unused))
|
||||
throw new Exception();
|
||||
scanlinecallback(vram, vramlength, LibGambatte.gambatte_cpuread(GambatteState, 0xff40));
|
||||
|
||||
scanlinecallback(vram, IsCGBMode(), LibGambatte.gambatte_cpuread(GambatteState, 0xff40), bgpal, sppal);
|
||||
}
|
||||
|
||||
LibGambatte.gambatte_runfor(GambatteState, VideoBuffer, 160, soundbuff, ref nsamp);
|
||||
|
@ -587,12 +592,14 @@ namespace BizHawk.Emulation.Consoles.GB
|
|||
|
||||
#region ppudebug
|
||||
/// <summary>
|
||||
/// a callback to be registered at a particular scanline
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="vram"></param>
|
||||
/// <param name="vramlength">length of vram in bytes</param>
|
||||
/// <param name="lcdc">current LCDC status</param>
|
||||
public delegate void ScanlineCallback(IntPtr vram, int vramlength, int lcdc);
|
||||
/// <param name="cgb"></param>
|
||||
/// <param name="lcdc"></param>
|
||||
/// <param name="bgpal"></param>
|
||||
/// <param name="sppal"></param>
|
||||
public delegate void ScanlineCallback(IntPtr vram, bool cgb, int lcdc, IntPtr bgpal, IntPtr sppal);
|
||||
|
||||
ScanlineCallback scanlinecallback;
|
||||
|
||||
|
|
|
@ -315,7 +315,10 @@ namespace BizHawk.Emulation.Consoles.GB
|
|||
wram = 2,
|
||||
cartram = 3,
|
||||
oam = 4,
|
||||
hram = 5
|
||||
hram = 5,
|
||||
// these last two aren't returning native memory area data
|
||||
bgpal = 6,
|
||||
sppal = 7
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
|
@ -45,7 +45,7 @@ namespace BizHawk.MultiClient.GBtools
|
|||
gb.SetScanlineCallback(null, 0);
|
||||
}
|
||||
|
||||
static unsafe void DrawTile(byte* tile, int* dest, int pitch)
|
||||
static unsafe void DrawTileDMG(byte* tile, int* dest, int pitch, int *pal)
|
||||
{
|
||||
for (int y = 0; y < 8; y++)
|
||||
{
|
||||
|
@ -55,10 +55,8 @@ namespace BizHawk.MultiClient.GBtools
|
|||
dest += 7;
|
||||
for (int x = 0; x < 8; x++) // right to left
|
||||
{
|
||||
int palcolor = loplane & 1 | hiplane & 2;
|
||||
// todo: palette transformation
|
||||
int color = palcolor * 0x555555 | unchecked((int)0xff000000);
|
||||
*dest-- = color;
|
||||
int color = loplane & 1 | hiplane & 2;
|
||||
*dest-- = pal[color];
|
||||
loplane >>= 1;
|
||||
hiplane >>= 1;
|
||||
}
|
||||
|
@ -67,28 +65,65 @@ namespace BizHawk.MultiClient.GBtools
|
|||
}
|
||||
}
|
||||
|
||||
static unsafe void DrawBG(Bitmap b, IntPtr _map, IntPtr _tiles, bool wrap)
|
||||
static unsafe void DrawTileCGB(byte* tile, int* dest, int pitch, int* pal, bool hflip, bool vflip)
|
||||
{
|
||||
if (vflip)
|
||||
dest += pitch * 7;
|
||||
for (int y = 0; y < 8; y++)
|
||||
{
|
||||
int loplane = *tile++;
|
||||
int hiplane = *tile++;
|
||||
hiplane <<= 1; // msb
|
||||
if (!hflip)
|
||||
dest += 7;
|
||||
for (int x = 0; x < 8; x++) // right to left
|
||||
{
|
||||
int color = loplane & 1 | hiplane & 2;
|
||||
*dest = pal[color];
|
||||
if (!hflip)
|
||||
dest--;
|
||||
else
|
||||
dest++;
|
||||
loplane >>= 1;
|
||||
hiplane >>= 1;
|
||||
}
|
||||
if (!hflip)
|
||||
dest++;
|
||||
else
|
||||
dest -= 8;
|
||||
if (!vflip)
|
||||
dest += pitch;
|
||||
else
|
||||
dest -= pitch;
|
||||
}
|
||||
}
|
||||
|
||||
static unsafe void DrawBGCGB(Bitmap b, IntPtr _map, IntPtr _tiles, bool wrap, IntPtr _pal)
|
||||
{
|
||||
if (b.Width != 256 || b.Height != 256)
|
||||
throw new Exception("GPUView screwed up.");
|
||||
|
||||
var lockdata = b.LockBits(new Rectangle(0, 0, 256, 256), System.Drawing.Imaging.ImageLockMode.WriteOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
|
||||
|
||||
byte* map = (byte*)_map;
|
||||
|
||||
int* dest = (int*)lockdata.Scan0;
|
||||
|
||||
int pitch = lockdata.Stride / sizeof(int); // in int*s, not bytes
|
||||
|
||||
int* pal = (int*)_pal;
|
||||
|
||||
for (int ty = 0; ty < 32; ty++)
|
||||
{
|
||||
{
|
||||
for (int tx = 0; tx < 32; tx++)
|
||||
{
|
||||
int tileindex = map[0];
|
||||
int tileext = map[8192];
|
||||
if (wrap && tileindex >= 128)
|
||||
tileindex -= 256;
|
||||
byte* tile = (byte*)(_tiles + tileindex * 16);
|
||||
DrawTile(tile, dest, pitch);
|
||||
if (tileext.Bit(3)) // second bank
|
||||
tile += 8192;
|
||||
|
||||
int* thispal = pal + 4 * (tileext & 7);
|
||||
|
||||
DrawTileCGB(tile, dest, pitch, thispal, tileext.Bit(5), tileext.Bit(6));
|
||||
map++;
|
||||
dest += 8;
|
||||
}
|
||||
|
@ -98,29 +133,83 @@ namespace BizHawk.MultiClient.GBtools
|
|||
b.UnlockBits(lockdata);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// core calls this on scanlines
|
||||
/// </summary>
|
||||
/// <param name="vram"></param>
|
||||
/// <param name="vramlength"></param>
|
||||
/// <param name="lcdc"></param>
|
||||
void ScanlineCallback(IntPtr vram, int vramlength, int lcdc)
|
||||
static unsafe void DrawBGDMG(Bitmap b, IntPtr _map, IntPtr _tiles, bool wrap, IntPtr _pal)
|
||||
{
|
||||
if (b.Width != 256 || b.Height != 256)
|
||||
throw new Exception("GPUView screwed up.");
|
||||
|
||||
DrawBG(
|
||||
bmpViewBG.bmp,
|
||||
vram + (lcdc.Bit(3) ? 0x1c00 : 0x1800),
|
||||
vram + (lcdc.Bit(4) ? 0x0000 : 0x1000),
|
||||
!lcdc.Bit(4));
|
||||
var lockdata = b.LockBits(new Rectangle(0, 0, 256, 256), System.Drawing.Imaging.ImageLockMode.WriteOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
|
||||
byte* map = (byte*)_map;
|
||||
int* dest = (int*)lockdata.Scan0;
|
||||
int pitch = lockdata.Stride / sizeof(int); // in int*s, not bytes
|
||||
int* pal = (int*)_pal;
|
||||
|
||||
for (int ty = 0; ty < 32; ty++)
|
||||
{
|
||||
for (int tx = 0; tx < 32; tx++)
|
||||
{
|
||||
int tileindex = map[0];
|
||||
if (wrap && tileindex >= 128)
|
||||
tileindex -= 256;
|
||||
byte* tile = (byte*)(_tiles + tileindex * 16);
|
||||
DrawTileDMG(tile, dest, pitch, pal);
|
||||
map++;
|
||||
dest += 8;
|
||||
}
|
||||
dest -= 256;
|
||||
dest += pitch * 8;
|
||||
}
|
||||
b.UnlockBits(lockdata);
|
||||
}
|
||||
|
||||
void ScanlineCallback(IntPtr vram, bool cgb, int lcdc, IntPtr bgpal, IntPtr sppal)
|
||||
{
|
||||
// set alpha on all pixels
|
||||
unsafe
|
||||
{
|
||||
int* p;
|
||||
p = (int*)bgpal;
|
||||
for (int i = 0; i < 32; i++)
|
||||
p[i] |= unchecked((int)0xff000000);
|
||||
p = (int*)sppal;
|
||||
for (int i = 0; i < 32; i++)
|
||||
p[i] |= unchecked((int)0xff000000);
|
||||
}
|
||||
|
||||
if (!cgb)
|
||||
{
|
||||
DrawBGDMG(
|
||||
bmpViewBG.bmp,
|
||||
vram + (lcdc.Bit(3) ? 0x1c00 : 0x1800),
|
||||
vram + (lcdc.Bit(4) ? 0x0000 : 0x1000),
|
||||
!lcdc.Bit(4),
|
||||
bgpal);
|
||||
|
||||
DrawBGDMG(
|
||||
bmpViewWin.bmp,
|
||||
vram + (lcdc.Bit(6) ? 0x1c00 : 0x1800),
|
||||
vram + 0x1000, // force win to second tile bank???
|
||||
true,
|
||||
bgpal);
|
||||
}
|
||||
else
|
||||
{
|
||||
DrawBGCGB(
|
||||
bmpViewBG.bmp,
|
||||
vram + (lcdc.Bit(3) ? 0x1c00 : 0x1800),
|
||||
vram + (lcdc.Bit(4) ? 0x0000 : 0x1000),
|
||||
!lcdc.Bit(4),
|
||||
bgpal);
|
||||
|
||||
DrawBGCGB(
|
||||
bmpViewWin.bmp,
|
||||
vram + (lcdc.Bit(6) ? 0x1c00 : 0x1800),
|
||||
vram + 0x1000, // force win to second tile bank???
|
||||
true,
|
||||
bgpal);
|
||||
}
|
||||
bmpViewBG.Refresh();
|
||||
|
||||
DrawBG(
|
||||
bmpViewWin.bmp,
|
||||
vram + (lcdc.Bit(6) ? 0x1c00 : 0x1800),
|
||||
vram + 0x1000, // force win to second tile bank???
|
||||
true);
|
||||
bmpViewWin.Refresh();
|
||||
|
||||
}
|
||||
|
||||
private void GBGPUView_FormClosed(object sender, FormClosedEventArgs e)
|
||||
|
|
|
@ -1742,6 +1742,7 @@ namespace BizHawk.MultiClient
|
|||
NESPPU1.Restart();
|
||||
NESNameTableViewer1.Restart();
|
||||
NESDebug1.Restart();
|
||||
GBGPUView1.Restart();
|
||||
PCEBGViewer1.Restart();
|
||||
TI83KeyPad1.Restart();
|
||||
TAStudio1.Restart();
|
||||
|
|
Binary file not shown.
|
@ -1019,6 +1019,14 @@ bool Memory::getMemoryArea(int which, unsigned char **data, int *length) {
|
|||
*data = &ioamhram[384];
|
||||
*length = 127;
|
||||
return true;
|
||||
case 6: // bgpal
|
||||
*data = (unsigned char *)display.bgPalette();
|
||||
*length = 32;
|
||||
return true;
|
||||
case 7: // sppal
|
||||
*data = (unsigned char *)display.spPalette();
|
||||
*length = 32;
|
||||
return true;
|
||||
default: // pass to cartridge
|
||||
return cart.getMemoryArea(which, data, length);
|
||||
}
|
||||
|
|
|
@ -250,6 +250,9 @@ public:
|
|||
|
||||
bool isCgb() const { return ppu.cgb(); }
|
||||
bool isDoubleSpeed() const { return ppu.lyCounter().isDoubleSpeed(); }
|
||||
|
||||
unsigned long *bgPalette() { return ppu.bgPalette(); }
|
||||
unsigned long *spPalette() { return ppu.spPalette(); }
|
||||
};
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue