gbhawk gpu viewer: work correctly with palettes and CGB extended BG data

This commit is contained in:
goyuken 2012-11-05 04:09:04 +00:00
parent 271d4102e8
commit 32a3d9db80
7 changed files with 150 additions and 39 deletions

View File

@ -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;

View File

@ -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>

View File

@ -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)

View File

@ -1742,6 +1742,7 @@ namespace BizHawk.MultiClient
NESPPU1.Restart();
NESNameTableViewer1.Restart();
NESDebug1.Restart();
GBGPUView1.Restart();
PCEBGViewer1.Restart();
TI83KeyPad1.Restart();
TAStudio1.Restart();

View File

@ -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);
}

View File

@ -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(); }
};
}