unsafe void DrawM4BG(MobileBmpView mbv, bool secondFrame) { mbv.ChangeAllSizes(240, 160); Bitmap bmp = mbv.BmpView.Bmp; var lockData = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb); int *pixels = (int *)lockData.Scan0; int pitch = lockData.Stride / sizeof(int); byte * frame = (byte *)_vram + (secondFrame ? 40960 : 0); ushort *palette = (ushort *)_palRam; for (int y = 0; y < 160; y++) { for (int x = 0; x < 240; x++) { *pixels++ = _colorConversion[palette[*frame++]]; } pixels -= 240; pixels += pitch; } bmp.UnlockBits(lockData); mbv.BmpView.Refresh(); }
unsafe void DrawSprites(MobileBmpView mbv) { mbv.BmpView.ChangeBitmapSize(1024, 512); Bitmap bmp = mbv.BmpView.Bmp; var lockData = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb); Win32Imports.MemSet(lockData.Scan0, 0xff, (uint)(lockData.Height * lockData.Stride)); int *pixels = (int *)lockData.Scan0; int pitch = lockData.Stride / sizeof(int); ushort *sprites = (ushort *)_oam; byte * tiles = (byte *)_vram + 65536; ushort dispcnt = ((ushort *)_mmio)[0]; bool twodee = !dispcnt.Bit(6); for (int sy = 0; sy < 8; sy++) { for (int sx = 0; sx < 16; sx++) { DrawSprite(pixels, pitch, sprites, tiles, twodee); pixels += 64; sprites += 4; } pixels -= 1024; pixels += pitch * 64; } bmp.UnlockBits(lockData); mbv.BmpView.Refresh(); }
void GenerateWidgets() { listBoxWidgets.BeginUpdate(); bg0 = MakeMBVWidget("Background 0", 256, 256); bg1 = MakeMBVWidget("Background 1", 256, 256); bg2 = MakeMBVWidget("Background 2", 256, 256); bg3 = MakeMBVWidget("Background 3", 256, 256); bgpal = MakeMBVWidget("Background Palettes", 256, 256); sppal = MakeMBVWidget("Sprite Palettes", 256, 256); sprites = MakeMBVWidget("Sprites", 1024, 512); sptiles16 = MakeMBVWidget("Sprite Tiles (4bpp)", 256, 256); sptiles256 = MakeMBVWidget("Sprite Tiles (8bpp)", 128, 256); bgtiles16 = MakeMBVWidget("Background Tiles (4bpp)", 512, 256); bgtiles256 = MakeMBVWidget("Background Tiles (8bpp)", 256, 256); MakeMDVWidget("Details", 128, 192); memory = MakeMDVWidget("Details - Memory", 128, 192); listBoxWidgets.EndUpdate(); foreach (var f in listBoxWidgets.Items) { Form form = (Form)f; // close becomes hide form.FormClosing += delegate(object sender, FormClosingEventArgs e) { e.Cancel = true; listBoxWidgets.Items.Add(sender); (sender as Form).Hide(); }; // hackish, and why doesn't winforms handle this directly? BringToFrontHack(form, form); } }
unsafe void DrawSpriteTiles(MobileBmpView mbv, bool tophalfonly, bool eightbit) { int tw = eightbit ? 16 : 32; int th = tophalfonly ? 16 : 32; mbv.BmpView.ChangeBitmapSize(tw * 8, 256); Bitmap bmp = mbv.BmpView.Bmp; var lockData = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb); int *pixels = (int *)lockData.Scan0; int pitch = lockData.Stride / sizeof(int); byte *tiles = (byte *)_vram + 65536; // TODO: palette changing (in 4 bit mode anyway) ushort *palette = (ushort *)_palRam + 256; if (tophalfonly) { Win32Imports.MemSet(lockData.Scan0, 0xff, (uint)(128 * lockData.Stride)); pixels += 128 * pitch; tiles += 16384; } DrawTileRange(pixels, pitch, tiles, palette, tw, th, eightbit); bmp.UnlockBits(lockData); mbv.BmpView.Refresh(); }
private void GenerateWidgets() { listBoxWidgets.BeginUpdate(); _bg0 = MakeMBVWidget("Background 0", 256, 256); _bg1 = MakeMBVWidget("Background 1", 256, 256); _bg2 = MakeMBVWidget("Background 2", 256, 256); _bg3 = MakeMBVWidget("Background 3", 256, 256); _bgPal = MakeMBVWidget("Background Palettes", 256, 256); _spPal = MakeMBVWidget("Sprite Palettes", 256, 256); _sprites = MakeMBVWidget("Sprites", 1024, 512); _spTiles16 = MakeMBVWidget("Sprite Tiles (4bpp)", 256, 256); _spTiles256 = MakeMBVWidget("Sprite Tiles (8bpp)", 128, 256); _bgTiles16 = MakeMBVWidget("Background Tiles (4bpp)", 512, 256); _bgTiles256 = MakeMBVWidget("Background Tiles (8bpp)", 256, 256); // todo: finish these // MakeMDVWidget("Details", 128, 192); // memory = MakeMDVWidget("Details - Memory", 128, 192); listBoxWidgets.EndUpdate(); foreach (var f in listBoxWidgets.Items) { Form form = (Form)f; // close becomes hide form.FormClosing += (sender, e) => { e.Cancel = true; listBoxWidgets.Items.Add(sender); (sender as Form).Hide(); }; // hackish, and why doesn't winforms handle this directly? BringToFrontHack(form, form); } }
MobileBmpView MakeMBVWidget(string text, int w, int h) { var mbv = new MobileBmpView(); mbv.Text = text; mbv.BmpView.Text = text; mbv.TopLevel = false; mbv.ChangeViewSize(w, h); mbv.BmpView.Clear(); panel1.Controls.Add(mbv); listBoxWidgets.Items.Add(mbv); return(mbv); }
unsafe void DrawBGTiles(MobileBmpView mbv, bool eightbit) { int tw = eightbit ? 32 : 64; int th = 32; mbv.BmpView.ChangeBitmapSize(tw * 8, th * 8); Bitmap bmp = mbv.BmpView.Bmp; var lockData = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb); int *pixels = (int *)lockData.Scan0; int pitch = lockData.Stride / sizeof(int); byte *tiles = (byte *)_vram; // TODO: palette changing (in 4 bit mode anyway) ushort *palette = (ushort *)_palRam; DrawTileRange(pixels, pitch, tiles, palette, tw, th, eightbit); bmp.UnlockBits(lockData); mbv.BmpView.Refresh(); }
unsafe void DrawAffineBG(int n, MobileBmpView mbv) { ushort bgcnt = ((ushort *)_mmio)[4 + n]; int ssize = bgcnt >> 14; switch (ssize) { case 0: mbv.ChangeAllSizes(128, 128); break; case 1: mbv.ChangeAllSizes(256, 256); break; case 2: mbv.ChangeAllSizes(512, 512); break; case 3: mbv.ChangeAllSizes(1024, 1024); break; } Bitmap bmp = mbv.BmpView.Bmp; var lockData = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb); int *pixels = (int *)lockData.Scan0; int pitch = lockData.Stride / sizeof(int); byte *tiles = (byte *)_vram + ((bgcnt & 0xc) << 12); byte *nametable = (byte *)_vram + ((bgcnt & 0x1f00) << 3); for (int ty = 0; ty < bmp.Height / 8; ty++) { for (int tx = 0; tx < bmp.Width / 8; tx++) { DrawTile256(pixels, pitch, tiles + *nametable++ *64, (ushort *)_palRam, false, false); pixels += 8; } pixels -= bmp.Width; pixels += 8 * pitch; } bmp.UnlockBits(lockData); mbv.BmpView.Refresh(); }
unsafe void DrawPalette(MobileBmpView mbv, bool sprite) { mbv.BmpView.ChangeBitmapSize(16, 16); Bitmap bmp = mbv.BmpView.Bmp; var lockData = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb); int *pixels = (int *)lockData.Scan0; int pitch = lockData.Stride / sizeof(int); ushort *palette = (ushort *)_palRam + (sprite ? 256 : 0); for (int j = 0; j < 16; j++) { for (int i = 0; i < 16; i++) { *pixels++ = _colorConversion[*palette++]; } pixels -= 16; pixels += pitch; } bmp.UnlockBits(lockData); mbv.BmpView.Refresh(); }
unsafe void DrawM5BG(MobileBmpView mbv, bool secondframe) { mbv.ChangeAllSizes(160, 128); Bitmap bmp = mbv.BmpView.bmp; var lockdata = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), System.Drawing.Imaging.ImageLockMode.WriteOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb); int *pixels = (int *)lockdata.Scan0; int pitch = lockdata.Stride / sizeof(int); ushort *frame = (ushort *)vram + (secondframe ? 20480 : 0); for (int y = 0; y < 128; y++) { for (int x = 0; x < 160; x++) { *pixels++ = ColorConversion[*frame++]; } pixels -= 160; pixels += pitch; } bmp.UnlockBits(lockdata); mbv.BmpView.Refresh(); }
unsafe void DrawTextBG(int n, MobileBmpView mbv) { ushort bgcnt = ((ushort*)mmio)[4 + n]; int ssize = bgcnt >> 14; switch (ssize) { case 0: mbv.ChangeAllSizes(256, 256); break; case 1: mbv.ChangeAllSizes(512, 256); break; case 2: mbv.ChangeAllSizes(256, 512); break; case 3: mbv.ChangeAllSizes(512, 512); break; } Bitmap bmp = mbv.BmpView.bmp; var lockdata = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), System.Drawing.Imaging.ImageLockMode.WriteOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb); int* pixels = (int*)lockdata.Scan0; int pitch = lockdata.Stride / sizeof(int); byte* tiles = (byte*)vram + ((bgcnt & 0xc) << 12); ushort* nametable = (ushort*)vram + ((bgcnt & 0x1f00) << 2); bool eightbit = bgcnt.Bit(7); switch (ssize) { case 0: DrawTextNameTable(pixels, pitch, nametable, tiles, eightbit); break; case 1: DrawTextNameTable(pixels, pitch, nametable, tiles, eightbit); pixels += 256; nametable += 1024; DrawTextNameTable(pixels, pitch, nametable, tiles, eightbit); break; case 2: DrawTextNameTable(pixels, pitch, nametable, tiles, eightbit); pixels += pitch * 256; nametable += 1024; DrawTextNameTable(pixels, pitch, nametable, tiles, eightbit); break; case 3: DrawTextNameTable(pixels, pitch, nametable, tiles, eightbit); pixels += 256; nametable += 1024; DrawTextNameTable(pixels, pitch, nametable, tiles, eightbit); pixels -= 256; pixels += pitch * 256; nametable += 1024; DrawTextNameTable(pixels, pitch, nametable, tiles, eightbit); pixels += 256; nametable += 1024; DrawTextNameTable(pixels, pitch, nametable, tiles, eightbit); break; } bmp.UnlockBits(lockdata); mbv.BmpView.Refresh(); }
unsafe void DrawM5BG(MobileBmpView mbv, bool secondframe) { mbv.ChangeAllSizes(160, 128); Bitmap bmp = mbv.BmpView.bmp; var lockdata = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), System.Drawing.Imaging.ImageLockMode.WriteOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb); int* pixels = (int*)lockdata.Scan0; int pitch = lockdata.Stride / sizeof(int); ushort* frame = (ushort*)vram + (secondframe ? 20480 : 0); for (int y = 0; y < 128; y++) { for (int x = 0; x < 160; x++) *pixels++ = ColorConversion[*frame++]; pixels -= 160; pixels += pitch; } bmp.UnlockBits(lockdata); mbv.BmpView.Refresh(); }
unsafe void DrawSprites(MobileBmpView mbv) { mbv.BmpView.ChangeBitmapSize(1024, 512); Bitmap bmp = mbv.BmpView.bmp; var lockdata = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), System.Drawing.Imaging.ImageLockMode.WriteOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb); // Clear() Win32.MemSet(lockdata.Scan0, 0xff, (uint)(lockdata.Height * lockdata.Stride)); int* pixels = (int*)lockdata.Scan0; int pitch = lockdata.Stride / sizeof(int); ushort* sprites = (ushort*)oam; byte* tiles = (byte*)vram + 65536; ushort dispcnt = ((ushort*)mmio)[0]; bool twodee = !dispcnt.Bit(6); for (int sy = 0; sy < 8; sy++) { for (int sx = 0; sx < 16; sx++) { DrawSprite(pixels, pitch, sprites, tiles, twodee); pixels += 64; sprites += 4; } pixels -= 1024; pixels += pitch * 64; } bmp.UnlockBits(lockdata); mbv.BmpView.Refresh(); }
unsafe void DrawPalette(MobileBmpView mbv, bool sprite) { mbv.BmpView.ChangeBitmapSize(16, 16); Bitmap bmp = mbv.BmpView.bmp; var lockdata = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), System.Drawing.Imaging.ImageLockMode.WriteOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb); int* pixels = (int*)lockdata.Scan0; int pitch = lockdata.Stride / sizeof(int); ushort* palette = (ushort*)palram + (sprite ? 256 : 0); for (int j = 0; j < 16; j++) { for (int i = 0; i < 16; i++) *pixels++ = ColorConversion[*palette++]; pixels -= 16; pixels += pitch; } bmp.UnlockBits(lockdata); mbv.BmpView.Refresh(); }
unsafe void DrawTextBG(int n, MobileBmpView mbv) { ushort bgcnt = ((ushort *)_mmio)[4 + n]; int ssize = bgcnt >> 14; switch (ssize) { case 0: mbv.ChangeAllSizes(256, 256); break; case 1: mbv.ChangeAllSizes(512, 256); break; case 2: mbv.ChangeAllSizes(256, 512); break; case 3: mbv.ChangeAllSizes(512, 512); break; } Bitmap bmp = mbv.BmpView.Bmp; var lockData = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb); int *pixels = (int *)lockData.Scan0; int pitch = lockData.Stride / sizeof(int); byte *tiles = (byte *)_vram + ((bgcnt & 0xc) << 12); ushort *nametable = (ushort *)_vram + ((bgcnt & 0x1f00) << 2); bool eighthBit = bgcnt.Bit(7); switch (ssize) { case 0: DrawTextNameTable(pixels, pitch, nametable, tiles, eighthBit); break; case 1: DrawTextNameTable(pixels, pitch, nametable, tiles, eighthBit); pixels += 256; nametable += 1024; DrawTextNameTable(pixels, pitch, nametable, tiles, eighthBit); break; case 2: DrawTextNameTable(pixels, pitch, nametable, tiles, eighthBit); pixels += pitch * 256; nametable += 1024; DrawTextNameTable(pixels, pitch, nametable, tiles, eighthBit); break; case 3: DrawTextNameTable(pixels, pitch, nametable, tiles, eighthBit); pixels += 256; nametable += 1024; DrawTextNameTable(pixels, pitch, nametable, tiles, eighthBit); pixels -= 256; pixels += pitch * 256; nametable += 1024; DrawTextNameTable(pixels, pitch, nametable, tiles, eighthBit); pixels += 256; nametable += 1024; DrawTextNameTable(pixels, pitch, nametable, tiles, eighthBit); break; } bmp.UnlockBits(lockData); mbv.BmpView.Refresh(); }
unsafe void DrawSpriteTiles(MobileBmpView mbv, bool tophalfonly, bool eightbit) { int tw = eightbit ? 16 : 32; int th = tophalfonly ? 16 : 32; mbv.BmpView.ChangeBitmapSize(tw * 8, 256); Bitmap bmp = mbv.BmpView.bmp; var lockdata = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), System.Drawing.Imaging.ImageLockMode.WriteOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb); int* pixels = (int*)lockdata.Scan0; int pitch = lockdata.Stride / sizeof(int); byte* tiles = (byte*)vram + 65536; // TODO: palette changing (in 4 bit mode anyway) ushort* palette = (ushort*)palram + 256; if (tophalfonly) { Win32.MemSet(lockdata.Scan0, 0xff, (uint)(128 * lockdata.Stride)); pixels += 128 * pitch; tiles += 16384; } DrawTileRange(pixels, pitch, tiles, palette, tw, th, eightbit); bmp.UnlockBits(lockdata); mbv.BmpView.Refresh(); }
unsafe void DrawAffineBG(int n, MobileBmpView mbv) { ushort bgcnt = ((ushort*)mmio)[4 + n]; int ssize = bgcnt >> 14; switch (ssize) { case 0: mbv.ChangeAllSizes(128, 128); break; case 1: mbv.ChangeAllSizes(256, 256); break; case 2: mbv.ChangeAllSizes(512, 512); break; case 3: mbv.ChangeAllSizes(1024, 1024); break; } Bitmap bmp = mbv.BmpView.bmp; var lockdata = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), System.Drawing.Imaging.ImageLockMode.WriteOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb); int* pixels = (int*)lockdata.Scan0; int pitch = lockdata.Stride / sizeof(int); byte* tiles = (byte*)vram + ((bgcnt & 0xc) << 12); byte* nametable = (byte*)vram + ((bgcnt & 0x1f00) << 3); for (int ty = 0; ty < bmp.Height / 8; ty++) { for (int tx = 0; tx < bmp.Width / 8; tx++) { DrawTile256(pixels, pitch, tiles + *nametable++ * 64, (ushort*)palram, false, false); pixels += 8; } pixels -= bmp.Width; pixels += 8 * pitch; } bmp.UnlockBits(lockdata); mbv.BmpView.Refresh(); }
MobileBmpView MakeMBVWidget(string text, int w, int h) { var mbv = new MobileBmpView(); mbv.Text = text; mbv.BmpView.Text = text; mbv.TopLevel = false; mbv.ChangeViewSize(w, h); mbv.BmpView.Clear(); panel1.Controls.Add(mbv); listBoxWidgets.Items.Add(mbv); return mbv; }
unsafe void DrawBGTiles(MobileBmpView mbv, bool eightbit) { int tw = eightbit ? 32 : 64; int th = 32; mbv.BmpView.ChangeBitmapSize(tw * 8, th * 8); Bitmap bmp = mbv.BmpView.bmp; var lockdata = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), System.Drawing.Imaging.ImageLockMode.WriteOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb); int* pixels = (int*)lockdata.Scan0; int pitch = lockdata.Stride / sizeof(int); byte* tiles = (byte*)vram; // TODO: palette changing (in 4 bit mode anyway) ushort* palette = (ushort*)palram; DrawTileRange(pixels, pitch, tiles, palette, tw, th, eightbit); bmp.UnlockBits(lockdata); mbv.BmpView.Refresh(); }