透過を指定するアドレスを発見&サムネイル抽出
ページ透過
ページの透過情報を探してみた。透過のみ違わせたメモを4つ用意して確認してみた。
Stirlingで比較したところ、タイムスタンプを格納してある「0x009A」、チェックサムが格納されている「0x0964」以下以外に、もう一箇所だけ違う部分があった。
それは0x06A6。1byteだけ違う。
上から、両方見える、上だけ、下だけ、両方見えない。
疑う余地なくここだ!確実にここだ!!
Wikiのほうにはココのアドレスは、アニメーションセクションのUnKnowとなっていた。バージョン2から使うようになったのだろう。
上紙を隠す場合下のビットを、下紙を隠す場合、上のビットをオンにするようですね。
サムネイルを取得
とりあえず、サムネイル解析に入る。
Wikiからの情報に従って、変換する。
static Color[] PalletEntries = {Color.White,Color.DimGray,Color.White,Color.DarkGray,Color.Red, Color.DarkRed , Color.Pink, Color.Green,Color.Blue,Color.DarkBlue,Color.LightBlue,Color.Green,Color.Purple,Color.Green,Color.Green,Color.Green}; Bitmap GetPreviewImage(byte[] bin) { GCHandle gh = GCHandle.Alloc(bin, GCHandleType.Pinned); IntPtr pointer = gh.AddrOfPinnedObject(); Bitmap bmp = new Bitmap(64, 48); Graphics g = Graphics.FromImage(bmp); pointer = new IntPtr(pointer.ToInt32() ); for (int i = 0; i < (6 * 8); i++) { Bitmap tmp = new Bitmap(8, 8, 4, PixelFormat.Format4bppIndexed, pointer); /*Bitmap tmp = new Bitmap(8,8,PixelFormat.Format4bppIndexed); BitmapData bd = tmp.LockBits(new Rectangle(0, 0, 8, 8), ImageLockMode.WriteOnly, PixelFormat.Format4bppIndexed); Marshal.Copy( bin, i * 32, bd.Scan0 , 32); tmp.UnlockBits(bd); */ ColorPalette cp = tmp.Palette; for (int j = 0; j < PalletEntries.Length; j++) { cp.Entries[j] = PalletEntries[j]; } tmp.Palette = cp; g.DrawImage(tmp, (i % 8) * 8, (i / 8) * 8); pointer = new IntPtr(pointer.ToInt32() + 32); } gh.Free(); return bmp; }
それで、取得したものがこちら。
う〜む、若干違和感を覚える。
完全ではないらしい。
コメントアウトしてある部分のやり方も試したが、同じでした。
いったいなぜ・・・
よく見ると、1つづつ入れ替わっているのがわかります。
・・・ということは!上位ビットと下位ビットを反転!
ーーーーーーーキターーーーーーーーーー(゚∀゚)ーーーーーーーーーーーー
やっとできた!これに数時間かかったぞ!バカヤロウ!
で、完全なソースこれにサムネイルの1536byteの大きさの配列を渡せば画像が帰ってきます☆
カラーパレットもWikiにあわせて変更してみました
static Color[] PalletEntries = {Color.White,Color.FromArgb(0x52,0x52,0x52),Color.White,Color.FromArgb(0xA4,0xA4,0xA4),Color.Red, Color.FromArgb(0x7B,0,0) , Color.FromArgb(0xFF,0x7B,0x7B), Bitmap GetPreviewImage(byte[] bin) { GCHandle gh = GCHandle.Alloc(bin, GCHandleType.Pinned); IntPtr pointer = gh.AddrOfPinnedObject(); Bitmap bmp = new Bitmap(64, 48); Graphics g = Graphics.FromImage(bmp); pointer = new IntPtr(pointer.ToInt32()); for (int i = 0; i < 6 * 8 * 32; i++) { int tmp = bin[i] & 0x0F; bin[i] = (byte)(bin[i] >> 4); bin[i] |= (byte)(tmp << 4); } for (int i = 0; i < (6 * 8); i++) { Bitmap tmp = new Bitmap(8, 8, 4, PixelFormat.Format4bppIndexed, pointer); ColorPalette cp = tmp.Palette; for (int j = 0; j < PalletEntries.Length; j++) { cp.Entries[j] = PalletEntries[j]; } tmp.Palette = cp; g.DrawImage(tmp, (i % 8) * 8, (i / 8) * 8); pointer = new IntPtr(pointer.ToInt32() + 32); } gh.Free(); return bmp; }
いや〜、カラーパレットの設定とビット交換に気づくのに一日かかったわ。
プログラムって難しい。
アニメーションセクションのほうにも挑戦しようとしたけど、あえなく撃沈。
英語が読めないんだもん!
気が向いたら続きをやろう。