|
|
1.1 ! root 1: // ! 2: // X680x0 CGROM ビューア ! 3: // ! 4: // Copyright (C) 2012-2019 [email protected] ! 5: // ! 6: ! 7: #include <wx/wx.h> ! 8: #include <wx/aboutdlg.h> ! 9: #include <wx/cmdline.h> ! 10: #include <wx/file.h> ! 11: #include <wx/image.h> ! 12: #include <wx/statline.h> ! 13: ! 14: #define TITLE "X680x0 CGROMビューア" ! 15: #define COPYRIGHT "Copyright (C) 2012-2019 [email protected]" ! 16: ! 17: /* CGROM.DAT の大きさ(バイト単位) */ ! 18: #define CGROM_SIZE (768 * 1024) ! 19: ! 20: /* キャンバス全体の大きさ (ピクセル単位) */ ! 21: #define VIEW_WIDTH (25 * 16) ! 22: #define VIEW_HEIGHT (25 * 16) ! 23: ! 24: /* 文字境界線の色 (これを3バイト並べる) */ ! 25: #define BORDER_COLOR (0xaa) ! 26: ! 27: #define countof(x) (sizeof(x) / sizeof(x[0])) ! 28: ! 29: #define ROUND(x, y) (((x) + (y - 1)) / (y)) ! 30: #define ROUND8(x) ROUND(x, 8) ! 31: ! 32: /* 独自のイベントタイプ */ ! 33: DECLARE_EVENT_TYPE(WXEVT_CREATE, -1); ! 34: DEFINE_EVENT_TYPE(WXEVT_CREATE); ! 35: ! 36: class MyFrame; ! 37: ! 38: struct ctxmenu_t { ! 39: int id; ! 40: int addr; ! 41: const char *label; ! 42: int size; ! 43: }; ! 44: ! 45: const wxSize view(VIEW_WIDTH, VIEW_HEIGHT); ! 46: ! 47: class ViewCtrl : public wxWindow ! 48: { ! 49: typedef wxWindow inherited; ! 50: public: ! 51: ViewCtrl(wxWindow *parent); ! 52: ! 53: unsigned char *imagebuf; ! 54: private: ! 55: void OnPaint(wxPaintEvent& event); ! 56: DECLARE_EVENT_TABLE(); ! 57: }; ! 58: ! 59: class MyFrame : public wxFrame ! 60: { ! 61: typedef wxFrame inherited; ! 62: public: ! 63: MyFrame(); ! 64: ! 65: private: ! 66: void OnCreate(wxCommandEvent& event); ! 67: void OnOpen(wxCommandEvent& event); ! 68: void DoOpenDialog(); ! 69: void DoOpen(); ! 70: void OnExit(wxCommandEvent& event); ! 71: void OnAbout(wxCommandEvent& event); ! 72: void OnContextMenu(wxContextMenuEvent& event); ! 73: void OnReloadUI(wxUpdateUIEvent& event); ! 74: void OnReload(wxCommandEvent& event); ! 75: bool DoReload(); ! 76: void OnAddr(wxCommandEvent& event); ! 77: void OnMouseWheel(wxMouseEvent& event); ! 78: void OnScroll(wxScrollEvent& event); ! 79: void OnTextEnter(wxCommandEvent& event); ! 80: void OnSizeBox(wxCommandEvent& event); ! 81: void DoUpdateSize(); ! 82: void DoUpdateAddr(); ! 83: bool CreateImage(); ! 84: ! 85: ViewCtrl *viewctrl; ! 86: wxScrollBar *scrlbar; ! 87: wxTextCtrl *addrctrl; ! 88: wxChoice *sizectrl; ! 89: wxMenu *menu; ! 90: wxString filename; ! 91: wxFile file; ! 92: int start_addr; /* 現在のサイズのフォントの開始アドレス */ ! 93: int start_offset; /* 現在のサイズのフォントの開始オフセット */ ! 94: int start_line; /* 現在のサイズのフォントの開始行 */ ! 95: int total_line; /* 現在のサイズのフォントでの行数 */ ! 96: int line; /* 表示開始行 */ ! 97: int addr; /* 表示開始アドレス */ ! 98: int size; /* フォントサイズ (番号) */ ! 99: wxSize pxsz; /* フォントサイズ (ピクセル数) */ ! 100: wxSize bdsz; /* 境界線を含めた大きさ (ピクセル数) */ ! 101: wxSize num; /* 1画面の文字数 */ ! 102: wxSize oct; /* 1文字のバイト数(縦,横) */ ! 103: int bytes; /* 1文字のバイト数 */ ! 104: int w_bytes; /* 1行分のバイト数(スクロールバー用) */ ! 105: ! 106: static ctxmenu_t ctxmenu[]; ! 107: ! 108: DECLARE_EVENT_TABLE(); ! 109: }; ! 110: ! 111: class MyApp : public wxApp ! 112: { ! 113: public: ! 114: virtual bool OnInit(); ! 115: wxString filename; ! 116: ! 117: private: ! 118: MyFrame *frame; ! 119: static const wxCmdLineEntryDesc desc[]; ! 120: }; ! 121: ! 122: IMPLEMENT_APP(MyApp) ! 123: ! 124: // --- ! 125: ! 126: enum { ! 127: ID_SCROLL, ! 128: ID_ADDRBOX, ! 129: ID_SIZEBOX, ! 130: ID_RELOAD, ! 131: ID_FONT_BEGIN, ! 132: ID_FONT_16x16 = ID_FONT_BEGIN, ! 133: ID_FONT_8x8, ! 134: ID_FONT_8x16, ! 135: ID_FONT_12x12, ! 136: ID_FONT_12x24, ! 137: ID_FONT_24x24, ! 138: ID_FONT_6x12, ! 139: ID_FONT_END, ! 140: }; ! 141: ! 142: enum { ! 143: SIZE_8x8 = 0, ! 144: SIZE_8x16, ! 145: SIZE_12x12, ! 146: SIZE_12x24, ! 147: SIZE_16x16, ! 148: SIZE_24x24, ! 149: SIZE_6x12, ! 150: SIZE_MAXxMAX, ! 151: }; ! 152: ! 153: const wxCmdLineEntryDesc MyApp::desc[] = ! 154: { ! 155: { wxCMD_LINE_PARAM, NULL, NULL, "<path of CGROM.DAT>", ! 156: wxCMD_LINE_VAL_STRING, wxCMD_LINE_PARAM_OPTIONAL, }, ! 157: { wxCMD_LINE_NONE, }, ! 158: }; ! 159: ! 160: bool MyApp::OnInit() ! 161: { ! 162: wxCmdLineParser cmd(argc, argv); ! 163: cmd.SetDesc(desc); ! 164: if (cmd.Parse() != 0) { ! 165: return false; ! 166: } ! 167: if (cmd.GetParamCount() > 0) { ! 168: filename = cmd.GetParam(0); ! 169: } ! 170: ! 171: frame = new MyFrame(); ! 172: frame->Show(); ! 173: SetTopWindow(frame); ! 174: return true; ! 175: } ! 176: ! 177: // イベントテーブル ! 178: BEGIN_EVENT_TABLE(MyFrame, inherited) ! 179: EVT_CONTEXT_MENU(MyFrame::OnContextMenu) ! 180: EVT_MENU(ID_RELOAD, MyFrame::OnReload) ! 181: EVT_UPDATE_UI(ID_RELOAD, MyFrame::OnReloadUI) ! 182: EVT_COMMAND_SCROLL(ID_SCROLL, MyFrame::OnScroll) ! 183: EVT_MOUSEWHEEL(MyFrame::OnMouseWheel) ! 184: EVT_TEXT_ENTER(ID_ADDRBOX, MyFrame::OnTextEnter) ! 185: EVT_CHOICE(ID_SIZEBOX, MyFrame::OnSizeBox) ! 186: EVT_BUTTON(ID_FONT_16x16, MyFrame::OnAddr) ! 187: EVT_BUTTON(ID_FONT_8x8, MyFrame::OnAddr) ! 188: EVT_BUTTON(ID_FONT_8x16, MyFrame::OnAddr) ! 189: EVT_BUTTON(ID_FONT_12x12, MyFrame::OnAddr) ! 190: EVT_BUTTON(ID_FONT_12x24, MyFrame::OnAddr) ! 191: EVT_BUTTON(ID_FONT_24x24, MyFrame::OnAddr) ! 192: EVT_BUTTON(ID_FONT_6x12, MyFrame::OnAddr) ! 193: EVT_MENU(wxID_OPEN, MyFrame::OnOpen) ! 194: EVT_MENU(wxID_EXIT, MyFrame::OnExit) ! 195: EVT_MENU(wxID_ABOUT, MyFrame::OnAbout) ! 196: EVT_COMMAND(wxID_ANY, WXEVT_CREATE, MyFrame::OnCreate) ! 197: END_EVENT_TABLE() ! 198: ! 199: // ショートカット用データ ! 200: struct ctxmenu_t MyFrame::ctxmenu[] = { ! 201: { ID_FONT_16x16, 0x00000, "16x16フォント", SIZE_16x16, }, ! 202: { ID_FONT_8x8, 0x3a000, "8x8フォント", SIZE_8x8, }, ! 203: { ID_FONT_8x16, 0x3a800, "8x16フォント", SIZE_8x16, }, ! 204: { ID_FONT_12x12, 0x3b800, "12x12フォント", SIZE_12x12, }, ! 205: { ID_FONT_12x24, 0x3d000, "12x24フォント", SIZE_12x24, }, ! 206: { ID_FONT_24x24, 0x40000, "24x24フォント", SIZE_24x24, }, ! 207: { ID_FONT_6x12, 0xbf400, "6x12フォント", SIZE_6x12, }, ! 208: }; ! 209: ! 210: // コンストラクタ ! 211: MyFrame::MyFrame() ! 212: : inherited(NULL, wxID_ANY, TITLE) ! 213: { ! 214: wxMenuBar *menubar = new wxMenuBar(); ! 215: wxMenu *menuFile = new wxMenu(); ! 216: menuFile->Append(wxID_OPEN, wxT("開く(&O)")); ! 217: menuFile->Append(wxID_EXIT, wxT("終了(&Q)")); ! 218: #if defined(__WXMAC__) ! 219: /* ! 220: * Macでは wxID_ABOUT は自動的にリンゴメニューのほうに移され、 ! 221: * 「ヘルプ」が子要素なしのメニューとして出来てしまう。 ! 222: * それを防ぐため Mac では「ヘルプ」メニューごとなくす。 ! 223: */ ! 224: menuFile->Append(wxID_ABOUT, wxT("バージョン(&A)")); ! 225: #endif ! 226: menubar->Append(menuFile, wxT("ファイル(&F)")); ! 227: #if !defined(__WXMAC__) ! 228: /* Mac以外なら「ヘルプ > バージョン」メニューを作成 */ ! 229: wxMenu *menuHelp = new wxMenu(); ! 230: menuHelp->Append(wxID_ABOUT, wxT("バージョン(&A)")); ! 231: menubar->Append(menuHelp, wxT("ヘルプ(&H)")); ! 232: #endif ! 233: SetMenuBar(menubar); ! 234: ! 235: wxPanel *panel = new wxPanel(this, wxID_ANY); ! 236: ! 237: wxBoxSizer *hbox = new wxBoxSizer(wxHORIZONTAL); ! 238: ! 239: /* ビュー */ ! 240: viewctrl = new ViewCtrl(panel); ! 241: hbox->Add(viewctrl); ! 242: ! 243: /* スクロールバー */ ! 244: scrlbar = new wxScrollBar(panel, ID_SCROLL, ! 245: wxDefaultPosition, wxDefaultSize, wxSB_VERTICAL); ! 246: hbox->Add(scrlbar, 0, wxEXPAND); ! 247: ! 248: hbox->AddSpacer(5); ! 249: ! 250: /* コントロールパネル */ ! 251: wxBoxSizer *ctrlbox = new wxBoxSizer(wxVERTICAL); ! 252: hbox->Add(ctrlbox); ! 253: ! 254: /* 開始アドレス */ ! 255: ctrlbox->Add(new wxStaticText(panel, wxID_ANY, wxT("開始アドレス"))); ! 256: ! 257: /* 開始アドレス(コントロール) */ ! 258: addrctrl = new wxTextCtrl(panel, ID_ADDRBOX, "", ! 259: wxDefaultPosition, wxDefaultSize, wxTE_PROCESS_ENTER); ! 260: ctrlbox->Add(addrctrl); ! 261: ! 262: ctrlbox->AddSpacer(5); ! 263: ! 264: /* フォントサイズ */ ! 265: ctrlbox->Add(new wxStaticText(panel, wxID_ANY, "フォントサイズ")); ! 266: ! 267: /* フォントサイズ(コントロール) */ ! 268: wxString sizelist[] = { ! 269: "8x8", ! 270: "8x16", ! 271: "12x12", ! 272: "12x24", ! 273: "16x16", ! 274: "24x24", ! 275: "6x12", ! 276: }; ! 277: sizectrl = new wxChoice(panel, ID_SIZEBOX, ! 278: wxDefaultPosition, wxDefaultSize, ! 279: countof(sizelist), sizelist); ! 280: ctrlbox->Add(sizectrl); ! 281: ! 282: ctrlbox->AddSpacer(10); ! 283: ctrlbox->Add(new wxStaticLine(panel), 0, wxEXPAND); ! 284: ctrlbox->AddSpacer(10); ! 285: ! 286: /* ショートカットボタン */ ! 287: for (int i = 0; i < countof(ctxmenu); i++) { ! 288: ctxmenu_t *c = &ctxmenu[i]; ! 289: wxString label; ! 290: ! 291: label.Printf("%05X: ", c->addr); ! 292: label += c->label; ! 293: wxButton *btn = new wxButton(panel, c->id, label, ! 294: wxDefaultPosition, wxDefaultSize, wxBU_LEFT); ! 295: ctrlbox->Add(btn, 0, wxEXPAND); ! 296: } ! 297: ! 298: ctrlbox->AddSpacer(5); ! 299: ctrlbox->Add(new wxStaticText(panel, wxID_ANY, ! 300: "(6x12 フォントは\nX68030 のみ)")); ! 301: ! 302: panel->SetSizer(hbox); ! 303: hbox->SetSizeHints(this); ! 304: ! 305: /* コンテキストメニュー */ ! 306: menu = new wxMenu(); ! 307: menu->Append(ID_RELOAD, "リロード"); ! 308: ! 309: /* 固定地 */ ! 310: num.x = 16; ! 311: ! 312: /* 初期値を入れて更新 */ ! 313: size = SIZE_16x16; ! 314: DoUpdateSize(); ! 315: ! 316: addr = 0; ! 317: line = -1; ! 318: DoUpdateAddr(); ! 319: ! 320: /* すぐに OnCreate を呼ぶように仕掛けておく */ ! 321: wxCommandEvent event(WXEVT_CREATE); ! 322: AddPendingEvent(event); ! 323: } ! 324: ! 325: // ウィンドウ作成イベントのつもり ! 326: void ! 327: MyFrame::OnCreate(wxCommandEvent& event) ! 328: { ! 329: if (!::wxGetApp().filename.IsEmpty()) { ! 330: /* 引数でファイルが指定されていればそれを使う */ ! 331: filename = ::wxGetApp().filename; ! 332: ! 333: /* ファイルオープン */ ! 334: DoOpen(); ! 335: } ! 336: } ! 337: ! 338: // オープン ! 339: void ! 340: MyFrame::OnOpen(wxCommandEvent& event) ! 341: { ! 342: DoOpenDialog(); ! 343: DoOpen(); ! 344: } ! 345: ! 346: // ファイルを開くダイアログ ! 347: void ! 348: MyFrame::DoOpenDialog() ! 349: { ! 350: wxFileDialog dialog(this, "Select a file", ! 351: ::wxGetCwd(), wxEmptyString, ! 352: "DAT files (*.DAT)|*.DAT;*.dat|すべてのファイル (*.*)|*.*"); ! 353: ! 354: if (dialog.ShowModal() != wxID_OK) { ! 355: return; ! 356: } ! 357: ! 358: filename = dialog.GetPath(); ! 359: } ! 360: ! 361: // オープン処理 ! 362: void ! 363: MyFrame::DoOpen() ! 364: { ! 365: /* すでにオープンしてあればそれは閉じる */ ! 366: if (file.IsOpened()) { ! 367: file.Close(); ! 368: } ! 369: ! 370: /* ファイル名がなければ (タイトルを戻して) 帰る */ ! 371: if (filename.IsEmpty()) { ! 372: SetTitle(TITLE); ! 373: return; ! 374: } ! 375: ! 376: if (!file.Open(filename, wxFile::read)) { ! 377: Close(); ! 378: return; ! 379: } ! 380: ! 381: /* オープンできたのでタイトルを変更 */ ! 382: wxString title; ! 383: title = TITLE; ! 384: title += " - "; ! 385: title += filename; ! 386: SetTitle(title); ! 387: ! 388: CreateImage(); ! 389: } ! 390: ! 391: // 終了 ! 392: void ! 393: MyFrame::OnExit(wxCommandEvent& event) ! 394: { ! 395: Close(); ! 396: } ! 397: ! 398: // ヘルプ ! 399: void ! 400: MyFrame::OnAbout(wxCommandEvent& event) ! 401: { ! 402: wxAboutDialogInfo ab; ! 403: ! 404: ab.SetName("viewcgrom"); ! 405: ab.SetVersion("1.1"); ! 406: ab.SetDescription(TITLE); ! 407: ab.SetCopyright(COPYRIGHT); ! 408: ! 409: wxAboutBox(ab); ! 410: } ! 411: ! 412: // コンテキストメニュー ! 413: void ! 414: MyFrame::OnContextMenu(wxContextMenuEvent& event) ! 415: { ! 416: PopupMenu(menu); ! 417: } ! 418: ! 419: // リロード UI ! 420: void ! 421: MyFrame::OnReloadUI(wxUpdateUIEvent& event) ! 422: { ! 423: event.Enable(file.IsOpened()); ! 424: } ! 425: ! 426: // リロードイベント ! 427: void ! 428: MyFrame::OnReload(wxCommandEvent& event) ! 429: { ! 430: DoReload(); ! 431: } ! 432: ! 433: // リロード処理 ! 434: bool ! 435: MyFrame::DoReload() ! 436: { ! 437: if (file.IsOpened()) { ! 438: file.Close(); ! 439: } ! 440: ! 441: if (!file.Open(filename, wxFile::read)) { ! 442: return false; ! 443: } ! 444: ! 445: CreateImage(); ! 446: return true; ! 447: } ! 448: ! 449: // フォント帯変更 ! 450: void ! 451: MyFrame::OnAddr(wxCommandEvent& event) ! 452: { ! 453: ctxmenu_t *c; ! 454: for (int i = 0; i < countof(ctxmenu); i++) { ! 455: c = &ctxmenu[i]; ! 456: if (event.GetId() == c->id) { ! 457: /* 一致したら変更 */ ! 458: size = c->size; ! 459: DoUpdateSize(); ! 460: ! 461: addr = c->addr; ! 462: line = -1; ! 463: DoUpdateAddr(); ! 464: return; ! 465: } ! 466: } ! 467: } ! 468: ! 469: // マウスホイール ! 470: void ! 471: MyFrame::OnMouseWheel(wxMouseEvent& event) ! 472: { ! 473: if (event.GetWheelRotation() < 0) { ! 474: line += 4; ! 475: if (line > total_line - num.y) { ! 476: line = total_line - num.y; ! 477: } ! 478: } else { ! 479: line -= 4; ! 480: if (line < 0) { ! 481: line = 0; ! 482: } ! 483: } ! 484: DoUpdateAddr(); ! 485: } ! 486: ! 487: // スクロール ! 488: void ! 489: MyFrame::OnScroll(wxScrollEvent& event) ! 490: { ! 491: line = event.GetPosition(); ! 492: DoUpdateAddr(); ! 493: } ! 494: ! 495: // アドレス変更 ! 496: void ! 497: MyFrame::OnTextEnter(wxCommandEvent& event) ! 498: { ! 499: long val = 0; ! 500: ! 501: event.GetString().ToLong(&val, 16); ! 502: line = -1; ! 503: addr = val; ! 504: DoUpdateAddr(); ! 505: } ! 506: ! 507: // サイズ変更 ! 508: void ! 509: MyFrame::OnSizeBox(wxCommandEvent& event) ! 510: { ! 511: size = event.GetSelection(); ! 512: DoUpdateSize(); ! 513: DoUpdateAddr(); ! 514: } ! 515: ! 516: // サイズ変更 (アドレス変更も呼び出す) ! 517: void ! 518: MyFrame::DoUpdateSize() ! 519: { ! 520: /* 範囲チェック */ ! 521: if (size < 0 || size >= SIZE_MAXxMAX) { ! 522: size = SIZE_16x16; ! 523: } ! 524: ! 525: /* コントロールを更新 */ ! 526: sizectrl->SetSelection(size); ! 527: ! 528: /* ! 529: * サイズに付随する変数を更新 ! 530: */ ! 531: /* ピクセルサイズ、開始アドレス、開始オフセット */ ! 532: start_offset = 0; ! 533: switch (size) { ! 534: case SIZE_6x12: ! 535: pxsz = wxSize(6, 12); ! 536: break; ! 537: case SIZE_8x8: ! 538: pxsz = wxSize(8, 8); ! 539: start_addr = 0x3a000; ! 540: break; ! 541: case SIZE_8x16: ! 542: pxsz = wxSize(8, 16); ! 543: start_addr = 0x3a800; ! 544: break; ! 545: case SIZE_12x12: ! 546: pxsz = wxSize(12, 12); ! 547: start_addr = 0x3b800; ! 548: start_offset = 128; ! 549: break; ! 550: case SIZE_12x24: ! 551: pxsz = wxSize(12, 24); ! 552: start_addr = 0x3d000; ! 553: start_offset = 512; ! 554: break; ! 555: case SIZE_16x16: ! 556: pxsz = wxSize(16, 16); ! 557: start_addr = 0; ! 558: break; ! 559: case SIZE_24x24: ! 560: pxsz = wxSize(24, 24); ! 561: start_addr = 0x40000; ! 562: start_offset = 512; ! 563: break; ! 564: } ! 565: ! 566: /* バイト数 */ ! 567: oct.x = (pxsz.x + 7) / 8; ! 568: oct.y = pxsz.y; ! 569: bytes = oct.x * oct.y; ! 570: w_bytes = bytes * num.x; ! 571: ! 572: /* 境界線入りサイズ */ ! 573: bdsz.x = (oct.x * 8) + 1; ! 574: bdsz.y = oct.y + 1; ! 575: ! 576: /* 縦文字数(1画面の行数)は計算 */ ! 577: num.y = view.y / bdsz.y; ! 578: ! 579: /* 負側の行数(端数行も含めるため round up) */ ! 580: /* これが基準行 */ ! 581: start_line = ROUND(start_addr, w_bytes); ! 582: /* 正側の行数(端数行も含めるため round up) */ ! 583: int pline = ROUND(CGROM_SIZE - start_addr, w_bytes); ! 584: /* 足したものが全行数 */ ! 585: total_line = pline + start_line; ! 586: ! 587: /* line は一旦無効に */ ! 588: line = -1; ! 589: ! 590: /* スクロールバーに反映 */ ! 591: /* 現在位置は後で計算するのではみださないように 0 にしておく */ ! 592: scrlbar->SetScrollbar(0, num.y, total_line, num.y - 1); ! 593: } ! 594: ! 595: // アドレス変更 ! 596: void ! 597: MyFrame::DoUpdateAddr() ! 598: { ! 599: if (line < 0) { ! 600: /* line が無効ならアドレスを近いところに */ ! 601: line = (addr + start_offset) / w_bytes; ! 602: } ! 603: ! 604: /* 行からアドレスを求める */ ! 605: addr = line * w_bytes - start_offset; ! 606: ! 607: /* アドレス欄に反映 */ ! 608: wxString str; ! 609: str.Printf("%05X", addr); ! 610: addrctrl->SetValue(str); ! 611: ! 612: /* スクロールバーに反映 */ ! 613: int current = scrlbar->GetThumbPosition(); ! 614: if (addr / w_bytes != current) { ! 615: scrlbar->SetThumbPosition(line); ! 616: } ! 617: ! 618: /* イメージ作成 */ ! 619: CreateImage(); ! 620: } ! 621: ! 622: // イメージ作成 ! 623: bool ! 624: MyFrame::CreateImage() ! 625: { ! 626: unsigned char *imagebuf; ! 627: unsigned char buf[bytes]; ! 628: size_t n; ! 629: int minus_addr; ! 630: ! 631: imagebuf = viewctrl->imagebuf; ! 632: ! 633: /* 全面クリア */ ! 634: memset(imagebuf, 0xff, view.x * view.y * 3); ! 635: ! 636: /* ファイルが準備できていなければ何もしない */ ! 637: if (!file.IsOpened()) { ! 638: return true; ! 639: } ! 640: ! 641: if (addr >= 0) { ! 642: file.Seek(addr); ! 643: minus_addr = 0; ! 644: } else { ! 645: file.Seek(0); ! 646: minus_addr = addr; ! 647: } ! 648: ! 649: for (int cy = 0; cy < num.y; cy++) { ! 650: for (int cx = 0; cx < num.x; cx++) { ! 651: unsigned char *p = ! 652: &imagebuf[((view.x * bdsz.y) * cy + bdsz.x * cx) * 3]; ! 653: /* ファイルオフセットが正なら1文字分読み込み */ ! 654: if (minus_addr >= 0) { ! 655: n = file.Read(buf, bytes); ! 656: } else { ! 657: /* 負なら0バイト読んだことにしてカウントだけする */ ! 658: /* 文字の途中でプラスに転じるケースは面倒なので無視 */ ! 659: minus_addr += bytes; ! 660: n = 0; ! 661: } ! 662: ! 663: /* 展開 */ ! 664: for (int y = 0; y < oct.y; y++) { ! 665: for (int x = 0; x < oct.x; x++) { ! 666: int offset = y * oct.x + x; ! 667: if (offset >= n) { ! 668: /* ファイルからはみ出る部分は塗りつぶし? */ ! 669: memset(p, BORDER_COLOR, 8 * 3); ! 670: p += 8 * 3; ! 671: continue; ! 672: } ! 673: unsigned char ch = buf[offset]; ! 674: for (int b = 0; b < 8; b++) { ! 675: if ((ch & 0x80)) { ! 676: p[0] = 0; ! 677: p[1] = 0; ! 678: p[2] = 0; ! 679: } ! 680: ch <<= 1; ! 681: p += 3; ! 682: } ! 683: } ! 684: /* 右境界線 */ ! 685: p[0] = BORDER_COLOR; ! 686: p[1] = BORDER_COLOR; ! 687: p[2] = BORDER_COLOR; ! 688: p += 3; ! 689: ! 690: p -= bdsz.x * 3; ! 691: p += view.x * 3; ! 692: } ! 693: /* 下境界線 */ ! 694: memset(p, BORDER_COLOR, bdsz.x * 3); ! 695: } ! 696: } ! 697: ! 698: /* 画面を再描画させる */ ! 699: viewctrl->Refresh(false); ! 700: ! 701: return true; ! 702: } ! 703: ! 704: // イベントテーブル ! 705: BEGIN_EVENT_TABLE(ViewCtrl, inherited) ! 706: EVT_PAINT(ViewCtrl::OnPaint) ! 707: END_EVENT_TABLE() ! 708: ! 709: // コンストラクタ ! 710: ViewCtrl::ViewCtrl(wxWindow *parent) ! 711: : inherited(parent, wxID_ANY, ! 712: wxDefaultPosition, wxSize(VIEW_WIDTH, VIEW_HEIGHT)) ! 713: { ! 714: imagebuf = new unsigned char [ VIEW_WIDTH * VIEW_HEIGHT * 3 ]; ! 715: } ! 716: ! 717: // ペイントイベント ! 718: void ! 719: ViewCtrl::OnPaint(wxPaintEvent& event) ! 720: { ! 721: wxPaintDC dc(this); ! 722: ! 723: wxImage image(VIEW_WIDTH, VIEW_HEIGHT, imagebuf, true); ! 724: wxBitmap bitmap(image); ! 725: wxMemoryDC memDC(bitmap); ! 726: ! 727: dc.Blit(0, 0, VIEW_WIDTH, VIEW_HEIGHT, &memDC, 0, 0); ! 728: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.