main.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634
  1. #include <windows.h>
  2. #include <commdlg.h>
  3. #include <stdio.h>
  4. #include <pico/pico.h>
  5. #include "../common/readpng.h"
  6. #include "../common/config.h"
  7. #include "../common/emu.h"
  8. #include "../common/menu.h"
  9. #include "../common/input.h"
  10. #include "../common/plat.h"
  11. #include "../common/version.h"
  12. #include "direct.h"
  13. #include "in_vk.h"
  14. char *romname=NULL;
  15. HWND FrameWnd=NULL;
  16. RECT FrameRectMy;
  17. RECT EmuScreenRect = { 0, 0, 320, 224 };
  18. int lock_to_1_1 = 1;
  19. static HWND PicoSwWnd=NULL, PicoPadWnd=NULL;
  20. static HMENU mmain = 0, mdisplay = 0, mpicohw = 0;
  21. static HBITMAP ppad_bmp = 0;
  22. static HBITMAP ppage_bmps[7] = { 0, };
  23. static char rom_name[0x20*3+1];
  24. static int main_wnd_as_pad = 0;
  25. static HANDLE loop_enter_event, loop_end_event;
  26. void error(char *text)
  27. {
  28. MessageBox(FrameWnd, text, "Error", 0);
  29. }
  30. static void UpdateRect(void)
  31. {
  32. WINDOWINFO wi;
  33. memset(&wi, 0, sizeof(wi));
  34. wi.cbSize = sizeof(wi);
  35. GetWindowInfo(FrameWnd, &wi);
  36. FrameRectMy = wi.rcClient;
  37. }
  38. static int extract_rom_name(char *dest, const unsigned char *src, int len)
  39. {
  40. char *p = dest, s_old = 0x20;
  41. int i;
  42. for (i = len - 1; i >= 0; i--)
  43. {
  44. if (src[i^1] != ' ') break;
  45. }
  46. len = i + 1;
  47. for (i = 0; i < len; i++)
  48. {
  49. unsigned char s = src[i^1];
  50. if (s == 0x20 && s_old == 0x20) continue;
  51. else if (s >= 0x20 && s < 0x7f && s != '%')
  52. {
  53. *p++ = s;
  54. }
  55. else
  56. {
  57. sprintf(p, "%%%02x", s);
  58. p += 3;
  59. }
  60. s_old = s;
  61. }
  62. *p = 0;
  63. return p - dest;
  64. }
  65. static void check_name_alias(const char *afname)
  66. {
  67. char buff[256], *var, *val;
  68. FILE *f;
  69. int ret;
  70. f = fopen(afname, "r");
  71. if (f == NULL) return;
  72. while (1)
  73. {
  74. ret = config_get_var_val(f, buff, sizeof(buff), &var, &val);
  75. if (ret == 0) break;
  76. if (ret == -1) continue;
  77. if (strcmp(rom_name, var) == 0) {
  78. lprintf("rom aliased: \"%s\" -> \"%s\"\n", rom_name, val);
  79. strncpy(rom_name, val, sizeof(rom_name));
  80. break;
  81. }
  82. }
  83. fclose(f);
  84. }
  85. static HBITMAP png2hb(const char *fname, int is_480)
  86. {
  87. BITMAPINFOHEADER bih;
  88. HBITMAP bmp;
  89. void *bmem;
  90. int ret;
  91. bmem = calloc(1, is_480 ? 480*240*3 : 320*240*3);
  92. if (bmem == NULL) return NULL;
  93. ret = readpng(bmem, fname, READPNG_24, is_480 ? 480 : 320, 240);
  94. if (ret != 0) {
  95. free(bmem);
  96. return NULL;
  97. }
  98. memset(&bih, 0, sizeof(bih));
  99. bih.biSize = sizeof(bih);
  100. bih.biWidth = is_480 ? 480 : 320;
  101. bih.biHeight = -240;
  102. bih.biPlanes = 1;
  103. bih.biBitCount = 24;
  104. bih.biCompression = BI_RGB;
  105. bmp = CreateDIBitmap(GetDC(FrameWnd), &bih, CBM_INIT, bmem, (BITMAPINFO *)&bih, 0);
  106. if (bmp == NULL)
  107. lprintf("CreateDIBitmap failed with %i", GetLastError());
  108. free(bmem);
  109. return bmp;
  110. }
  111. static void PrepareForROM(void)
  112. {
  113. unsigned char *rom_data = NULL;
  114. int i, ret, show = PicoIn.AHW & PAHW_PICO;
  115. PicoGetInternal(PI_ROM, (pint_ret_t *) &rom_data);
  116. EnableMenuItem(mmain, 2, MF_BYPOSITION|(show ? MF_ENABLED : MF_GRAYED));
  117. ShowWindow(PicoPadWnd, show ? SW_SHOWNA : SW_HIDE);
  118. ShowWindow(PicoSwWnd, show ? SW_SHOWNA : SW_HIDE);
  119. CheckMenuItem(mpicohw, 1210, show ? MF_CHECKED : MF_UNCHECKED);
  120. CheckMenuItem(mpicohw, 1211, show ? MF_CHECKED : MF_UNCHECKED);
  121. PostMessage(FrameWnd, WM_COMMAND, 1220 + PicoPicohw.page, 0);
  122. DrawMenuBar(FrameWnd);
  123. InvalidateRect(PicoSwWnd, NULL, 1);
  124. PicoPicohw.pen_pos[0] =
  125. PicoPicohw.pen_pos[1] = 0x8000;
  126. in_vk_add_pl12 = 0;
  127. ret = extract_rom_name(rom_name, rom_data + 0x150, 0x20);
  128. if (ret == 0)
  129. extract_rom_name(rom_name, rom_data + 0x130, 0x20);
  130. if (show)
  131. {
  132. char path[MAX_PATH], *p;
  133. GetModuleFileName(NULL, path, sizeof(path) - 32);
  134. p = strrchr(path, '\\');
  135. if (p == NULL) p = path;
  136. else p++;
  137. if (ppad_bmp == NULL) {
  138. strcpy(p, "pico\\pad.png");
  139. ppad_bmp = png2hb(path, 0);
  140. }
  141. strcpy(p, "pico\\alias.txt");
  142. check_name_alias(path);
  143. for (i = 0; i < 7; i++) {
  144. if (ppage_bmps[i] != NULL) DeleteObject(ppage_bmps[i]);
  145. sprintf(p, "pico\\%s_%i.png", rom_name, i);
  146. ppage_bmps[i] = png2hb(path, 1);
  147. }
  148. // games usually don't have page 6, so just duplicate page 5.
  149. if (ppage_bmps[6] == NULL && ppage_bmps[5] != NULL) {
  150. sprintf(p, "pico\\%s_5.png", rom_name);
  151. ppage_bmps[6] = png2hb(path, 1);
  152. }
  153. }
  154. }
  155. static void LoadROM(const char *cmdpath)
  156. {
  157. char rompath[MAX_PATH];
  158. int ret;
  159. if (cmdpath != NULL && strlen(cmdpath)) {
  160. strcpy(rompath, cmdpath + (cmdpath[0] == '\"' ? 1 : 0));
  161. if (rompath[strlen(rompath)-1] == '\"')
  162. rompath[strlen(rompath)-1] = 0;
  163. }
  164. else {
  165. OPENFILENAME of; ZeroMemory(&of, sizeof(of));
  166. rompath[sizeof(rompath) - 1] = 0;
  167. strncpy(rompath, rom_fname_loaded, sizeof(rompath) - 1);
  168. of.lStructSize = sizeof(of);
  169. of.lpstrFilter = "ROMs, CD images\0*.smd;*.bin;*.gen;*.zip;*.32x;*.sms;*.iso;*.cso;*.cue\0"
  170. "whatever\0*.*\0";
  171. of.lpstrFile = rompath;
  172. of.nMaxFile = MAX_PATH;
  173. of.Flags = OFN_FILEMUSTEXIST|OFN_HIDEREADONLY;
  174. of.hwndOwner = FrameWnd;
  175. if (!GetOpenFileName(&of))
  176. return;
  177. }
  178. if (engineState == PGS_Running) {
  179. engineState = PGS_Paused;
  180. WaitForSingleObject(loop_end_event, 5000);
  181. }
  182. ret = emu_reload_rom(rompath);
  183. if (ret == 0) {
  184. extern char menu_error_msg[]; // HACK..
  185. error(menu_error_msg);
  186. return;
  187. }
  188. PrepareForROM();
  189. engineState = PGS_Running;
  190. SetEvent(loop_enter_event);
  191. }
  192. static const int rect_widths[4] = { 320, 256, 640, 512 };
  193. static const int rect_heights[4] = { 224, 224, 448, 448 };
  194. // Window proc for the frame window:
  195. static LRESULT CALLBACK WndProc(HWND hwnd,UINT msg,WPARAM wparam,LPARAM lparam)
  196. {
  197. POINT pt;
  198. RECT rc;
  199. int i;
  200. switch (msg)
  201. {
  202. case WM_CLOSE:
  203. PostQuitMessage(0);
  204. return 0;
  205. case WM_DESTROY:
  206. FrameWnd = NULL; // Blank the handle
  207. break;
  208. case WM_SIZE:
  209. case WM_MOVE:
  210. case WM_SIZING:
  211. UpdateRect();
  212. if (lock_to_1_1 && FrameRectMy.right - FrameRectMy.left != 0 &&
  213. (FrameRectMy.right - FrameRectMy.left != EmuScreenRect.right - EmuScreenRect.left ||
  214. FrameRectMy.bottom - FrameRectMy.top != EmuScreenRect.bottom - EmuScreenRect.top)) {
  215. lock_to_1_1 = 0;
  216. CheckMenuItem(mdisplay, 1104, MF_UNCHECKED);
  217. }
  218. break;
  219. case WM_COMMAND:
  220. switch (LOWORD(wparam))
  221. {
  222. case 1000:
  223. LoadROM(NULL);
  224. break;
  225. case 1001:
  226. emu_reset_game();
  227. return 0;
  228. case 1002:
  229. PostQuitMessage(0);
  230. return 0;
  231. case 1100:
  232. case 1101:
  233. case 1102:
  234. case 1103:
  235. // LoopWait=1; // another sync hack
  236. // for (i = 0; !LoopWaiting && i < 10; i++) Sleep(10);
  237. FrameRectMy.right = FrameRectMy.left + rect_widths[wparam&3];
  238. FrameRectMy.bottom = FrameRectMy.top + rect_heights[wparam&3];
  239. AdjustWindowRect(&FrameRectMy, WS_OVERLAPPEDWINDOW, 1);
  240. MoveWindow(hwnd, FrameRectMy.left, FrameRectMy.top,
  241. FrameRectMy.right-FrameRectMy.left, FrameRectMy.bottom-FrameRectMy.top, 1);
  242. UpdateRect();
  243. lock_to_1_1 = 0;
  244. CheckMenuItem(mdisplay, 1104, MF_UNCHECKED);
  245. // if (rom_loaded) LoopWait=0;
  246. return 0;
  247. case 1104:
  248. lock_to_1_1 = !lock_to_1_1;
  249. CheckMenuItem(mdisplay, 1104, lock_to_1_1 ? MF_CHECKED : MF_UNCHECKED);
  250. /* FALLTHROUGH */
  251. case 2000: // EmuScreenRect/FrameRectMy sync request
  252. if (!lock_to_1_1)
  253. return 0;
  254. FrameRectMy.right = FrameRectMy.left + (EmuScreenRect.right - EmuScreenRect.left);
  255. FrameRectMy.bottom = FrameRectMy.top + (EmuScreenRect.bottom - EmuScreenRect.top);
  256. AdjustWindowRect(&FrameRectMy, WS_OVERLAPPEDWINDOW, 1);
  257. MoveWindow(hwnd, FrameRectMy.left, FrameRectMy.top,
  258. FrameRectMy.right-FrameRectMy.left, FrameRectMy.bottom-FrameRectMy.top, 1);
  259. UpdateRect();
  260. return 0;
  261. case 1210:
  262. case 1211:
  263. i = IsWindowVisible((LOWORD(wparam)&1) ? PicoPadWnd : PicoSwWnd);
  264. i = !i;
  265. ShowWindow((LOWORD(wparam)&1) ? PicoPadWnd : PicoSwWnd, i ? SW_SHOWNA : SW_HIDE);
  266. CheckMenuItem(mpicohw, LOWORD(wparam), i ? MF_CHECKED : MF_UNCHECKED);
  267. return 0;
  268. case 1212:
  269. main_wnd_as_pad = !main_wnd_as_pad;
  270. CheckMenuItem(mpicohw, 1212, main_wnd_as_pad ? MF_CHECKED : MF_UNCHECKED);
  271. return 0;
  272. case 1220:
  273. case 1221:
  274. case 1222:
  275. case 1223:
  276. case 1224:
  277. case 1225:
  278. case 1226:
  279. PicoPicohw.page = LOWORD(wparam) % 10;
  280. for (i = 0; i < 7; i++)
  281. CheckMenuItem(mpicohw, 1220 + i, MF_UNCHECKED);
  282. CheckMenuItem(mpicohw, 1220 + PicoPicohw.page, MF_CHECKED);
  283. InvalidateRect(PicoSwWnd, NULL, 1);
  284. return 0;
  285. case 1300:
  286. MessageBox(FrameWnd, plat_get_credits(), "About", 0);
  287. return 0;
  288. }
  289. break;
  290. case WM_TIMER:
  291. GetCursorPos(&pt);
  292. GetWindowRect(PicoSwWnd, &rc);
  293. if (PtInRect(&rc, pt)) break;
  294. GetWindowRect(PicoPadWnd, &rc);
  295. if (PtInRect(&rc, pt)) break;
  296. PicoPicohw.pen_pos[0] |= 0x8000;
  297. PicoPicohw.pen_pos[1] |= 0x8000;
  298. in_vk_add_pl12 = 0;
  299. break;
  300. case WM_LBUTTONDOWN: in_vk_add_pl12 |= 0x20; return 0;
  301. case WM_LBUTTONUP: in_vk_add_pl12 &= ~0x20; return 0;
  302. case WM_MOUSEMOVE:
  303. if (!main_wnd_as_pad) break;
  304. PicoPicohw.pen_pos[0] = 0x03c + (320 * LOWORD(lparam) / (FrameRectMy.right - FrameRectMy.left));
  305. PicoPicohw.pen_pos[1] = 0x1fc + (232 * HIWORD(lparam) / (FrameRectMy.bottom - FrameRectMy.top));
  306. SetTimer(FrameWnd, 100, 1000, NULL);
  307. break;
  308. case WM_KEYDOWN:
  309. if (wparam == VK_TAB) {
  310. emu_reset_game();
  311. break;
  312. }
  313. if (wparam == VK_ESCAPE) {
  314. LoadROM(NULL);
  315. break;
  316. }
  317. in_vk_keydown(wparam);
  318. break;
  319. case WM_KEYUP:
  320. in_vk_keyup(wparam);
  321. break;
  322. }
  323. return DefWindowProc(hwnd,msg,wparam,lparam);
  324. }
  325. static LRESULT CALLBACK PicoSwWndProc(HWND hwnd,UINT msg,WPARAM wparam,LPARAM lparam)
  326. {
  327. PAINTSTRUCT ps;
  328. HDC hdc, hdc2;
  329. switch (msg)
  330. {
  331. case WM_DESTROY: PicoSwWnd=NULL; break;
  332. case WM_LBUTTONDOWN: in_vk_add_pl12 |= 0x20; return 0;
  333. case WM_LBUTTONUP: in_vk_add_pl12 &= ~0x20; return 0;
  334. case WM_MOUSEMOVE:
  335. if (HIWORD(lparam) < 0x20) break;
  336. PicoPicohw.pen_pos[0] = 0x03c + LOWORD(lparam) * 2/3;
  337. PicoPicohw.pen_pos[1] = 0x2f8 + HIWORD(lparam) - 0x20;
  338. SetTimer(FrameWnd, 100, 1000, NULL);
  339. break;
  340. case WM_KEYDOWN: in_vk_keydown(wparam); break;
  341. case WM_KEYUP: in_vk_keyup(wparam); break;
  342. case WM_PAINT:
  343. hdc = BeginPaint(hwnd, &ps);
  344. if (ppage_bmps[PicoPicohw.page] == NULL)
  345. {
  346. SelectObject(hdc, GetStockObject(DEFAULT_GUI_FONT));
  347. SetTextColor(hdc, RGB(255, 255, 255));
  348. SetBkColor(hdc, RGB(0, 0, 0));
  349. TextOut(hdc, 2, 2, "missing PNGs for", 16);
  350. TextOut(hdc, 2, 18, rom_name, strlen(rom_name));
  351. }
  352. else
  353. {
  354. hdc2 = CreateCompatibleDC(GetDC(FrameWnd));
  355. SelectObject(hdc2, ppage_bmps[PicoPicohw.page]);
  356. BitBlt(hdc, 0, 0, 480, 240, hdc2, 0, 0, SRCCOPY);
  357. DeleteDC(hdc2);
  358. }
  359. EndPaint(hwnd, &ps);
  360. return 0;
  361. case WM_CLOSE:
  362. ShowWindow(hwnd, SW_HIDE);
  363. CheckMenuItem(mpicohw, 1210, MF_UNCHECKED);
  364. return 0;
  365. }
  366. return DefWindowProc(hwnd,msg,wparam,lparam);
  367. }
  368. static LRESULT CALLBACK PicoPadWndProc(HWND hwnd,UINT msg,WPARAM wparam,LPARAM lparam)
  369. {
  370. PAINTSTRUCT ps;
  371. HDC hdc, hdc2;
  372. switch (msg)
  373. {
  374. case WM_DESTROY: PicoPadWnd=NULL; break;
  375. case WM_LBUTTONDOWN: in_vk_add_pl12 |= 0x20; return 0;
  376. case WM_LBUTTONUP: in_vk_add_pl12 &= ~0x20; return 0;
  377. case WM_MOUSEMOVE:
  378. PicoPicohw.pen_pos[0] = 0x03c + LOWORD(lparam);
  379. PicoPicohw.pen_pos[1] = 0x1fc + HIWORD(lparam);
  380. SetTimer(FrameWnd, 100, 1000, NULL);
  381. break;
  382. case WM_KEYDOWN: in_vk_keydown(wparam); break;
  383. case WM_KEYUP: in_vk_keyup(wparam); break;
  384. case WM_PAINT:
  385. if (ppad_bmp == NULL) break;
  386. hdc = BeginPaint(hwnd, &ps);
  387. hdc2 = CreateCompatibleDC(GetDC(FrameWnd));
  388. SelectObject(hdc2, ppad_bmp);
  389. BitBlt(hdc, 0, 0, 320, 240, hdc2, 0, 0, SRCCOPY);
  390. EndPaint(hwnd, &ps);
  391. DeleteDC(hdc2);
  392. return 0;
  393. case WM_CLOSE:
  394. ShowWindow(hwnd, SW_HIDE);
  395. CheckMenuItem(mpicohw, 1211, MF_UNCHECKED);
  396. return 0;
  397. }
  398. return DefWindowProc(hwnd,msg,wparam,lparam);
  399. }
  400. static int FrameInit()
  401. {
  402. WNDCLASS wc;
  403. RECT rect={0,0,0,0};
  404. HMENU mfile;
  405. int style=0;
  406. int left=0,top=0,width=0,height=0;
  407. memset(&wc,0,sizeof(wc));
  408. // Register the window class:
  409. wc.lpfnWndProc=WndProc;
  410. wc.hInstance=GetModuleHandle(NULL);
  411. wc.hCursor=LoadCursor(NULL,IDC_ARROW);
  412. wc.hbrBackground=CreateSolidBrush(0);
  413. wc.lpszClassName="PicoMainFrame";
  414. RegisterClass(&wc);
  415. wc.lpszClassName="PicoSwWnd";
  416. wc.lpfnWndProc=PicoSwWndProc;
  417. RegisterClass(&wc);
  418. wc.lpszClassName="PicoPadWnd";
  419. wc.lpfnWndProc=PicoPadWndProc;
  420. RegisterClass(&wc);
  421. rect.right =320;
  422. rect.bottom=224;
  423. // Adjust size of windows based on borders:
  424. style=WS_OVERLAPPEDWINDOW;
  425. AdjustWindowRect(&rect,style,1);
  426. width =rect.right-rect.left;
  427. height=rect.bottom-rect.top;
  428. // Place window in the centre of the screen:
  429. SystemParametersInfo(SPI_GETWORKAREA,0,&rect,0);
  430. left=rect.left+rect.right;
  431. top=rect.top+rect.bottom;
  432. left-=width; left>>=1;
  433. top-=height; top>>=1;
  434. // Create menu:
  435. mfile = CreateMenu();
  436. InsertMenu(mfile, -1, MF_BYPOSITION|MF_STRING, 1000, "&Load ROM");
  437. InsertMenu(mfile, -1, MF_BYPOSITION|MF_STRING, 1001, "&Reset");
  438. InsertMenu(mfile, -1, MF_BYPOSITION|MF_STRING, 1002, "E&xit");
  439. mdisplay = CreateMenu();
  440. InsertMenu(mdisplay, -1, MF_BYPOSITION|MF_STRING, 1100, "320x224");
  441. InsertMenu(mdisplay, -1, MF_BYPOSITION|MF_STRING, 1101, "256x224");
  442. InsertMenu(mdisplay, -1, MF_BYPOSITION|MF_STRING, 1102, "640x448");
  443. InsertMenu(mdisplay, -1, MF_BYPOSITION|MF_STRING, 1103, "512x448");
  444. InsertMenu(mdisplay, -1, MF_BYPOSITION|MF_STRING, 1104, "Lock to 1:1");
  445. mpicohw = CreateMenu();
  446. InsertMenu(mpicohw, -1, MF_BYPOSITION|MF_STRING, 1210, "Show &Storyware");
  447. InsertMenu(mpicohw, -1, MF_BYPOSITION|MF_STRING, 1211, "Show &Drawing pad");
  448. InsertMenu(mpicohw, -1, MF_BYPOSITION|MF_STRING, 1212, "&Main window as pad");
  449. InsertMenu(mpicohw, -1, MF_BYPOSITION|MF_SEPARATOR, 0, NULL);
  450. InsertMenu(mpicohw, -1, MF_BYPOSITION|MF_STRING, 1220, "Title page (&0)");
  451. InsertMenu(mpicohw, -1, MF_BYPOSITION|MF_STRING, 1221, "Page &1");
  452. InsertMenu(mpicohw, -1, MF_BYPOSITION|MF_STRING, 1222, "Page &2");
  453. InsertMenu(mpicohw, -1, MF_BYPOSITION|MF_STRING, 1223, "Page &3");
  454. InsertMenu(mpicohw, -1, MF_BYPOSITION|MF_STRING, 1224, "Page &4");
  455. InsertMenu(mpicohw, -1, MF_BYPOSITION|MF_STRING, 1225, "Page &5");
  456. InsertMenu(mpicohw, -1, MF_BYPOSITION|MF_STRING, 1226, "Page &6");
  457. mmain = CreateMenu();
  458. InsertMenu(mmain, -1, MF_BYPOSITION|MF_STRING|MF_POPUP, (UINT_PTR) mfile, "&File");
  459. InsertMenu(mmain, -1, MF_BYPOSITION|MF_STRING|MF_POPUP, (UINT_PTR) mdisplay, "&Display");
  460. InsertMenu(mmain, -1, MF_BYPOSITION|MF_STRING|MF_POPUP, (UINT_PTR) mpicohw, "&Pico");
  461. EnableMenuItem(mmain, 2, MF_BYPOSITION|MF_GRAYED);
  462. // InsertMenu(mmain, -1, MF_BYPOSITION|MF_STRING|MF_POPUP, 1200, "&Config");
  463. InsertMenu(mmain, -1, MF_BYPOSITION|MF_STRING, 1300, "&About");
  464. // Create the window:
  465. FrameWnd=CreateWindow("PicoMainFrame","PicoDrive " VERSION,style|WS_VISIBLE,
  466. left,top,width,height,NULL,mmain,NULL,NULL);
  467. CheckMenuItem(mdisplay, 1104, lock_to_1_1 ? MF_CHECKED : MF_UNCHECKED);
  468. ShowWindow(FrameWnd, SW_NORMAL);
  469. UpdateWindow(FrameWnd);
  470. UpdateRect();
  471. // create Pico windows
  472. style = WS_OVERLAPPED|WS_CAPTION|WS_BORDER|WS_SYSMENU;
  473. rect.left=rect.top=0;
  474. rect.right =320;
  475. rect.bottom=224;
  476. AdjustWindowRect(&rect,style,1);
  477. width =rect.right-rect.left;
  478. height=rect.bottom-rect.top;
  479. left += 326;
  480. PicoSwWnd=CreateWindow("PicoSwWnd","Storyware",style,
  481. left,top,width+160,height,FrameWnd,NULL,NULL,NULL);
  482. top += 266;
  483. PicoPadWnd=CreateWindow("PicoPadWnd","Drawing Pad",style,
  484. left,top,width,height,FrameWnd,NULL,NULL,NULL);
  485. return 0;
  486. }
  487. // --------------------
  488. static DWORD WINAPI work_thread(void *x)
  489. {
  490. while (engineState != PGS_Quit) {
  491. WaitForSingleObject(loop_enter_event, INFINITE);
  492. if (engineState != PGS_Running)
  493. continue;
  494. printf("loop..\n");
  495. emu_loop();
  496. SetEvent(loop_end_event);
  497. }
  498. return 0;
  499. }
  500. // XXX: use main.c
  501. void xxinit(void)
  502. {
  503. /* in_init() must go before config, config accesses in_ fwk */
  504. in_init();
  505. emu_prep_defconfig();
  506. emu_read_config(NULL, 0);
  507. config_readlrom(PicoConfigFile);
  508. plat_init();
  509. in_probe();
  510. emu_init();
  511. menu_init();
  512. }
  513. int WINAPI WinMain(HINSTANCE p1, HINSTANCE p2, LPSTR cmdline, int p4)
  514. {
  515. MSG msg;
  516. DWORD tid = 0;
  517. HANDLE thread;
  518. int ret;
  519. xxinit();
  520. FrameInit();
  521. ret = DirectInit();
  522. if (ret)
  523. goto end0;
  524. loop_enter_event = CreateEvent(NULL, 0, 0, NULL);
  525. if (loop_enter_event == NULL)
  526. goto end0;
  527. loop_end_event = CreateEvent(NULL, 0, 0, NULL);
  528. if (loop_end_event == NULL)
  529. goto end0;
  530. thread = CreateThread(NULL, 0, work_thread, NULL, 0, &tid);
  531. if (thread == NULL)
  532. goto end0;
  533. LoadROM(cmdline);
  534. // Main window loop:
  535. for (;;)
  536. {
  537. GetMessage(&msg,NULL,0,0);
  538. if (msg.message==WM_QUIT) break;
  539. TranslateMessage(&msg);
  540. DispatchMessage(&msg);
  541. }
  542. // Signal thread to quit and wait for it to exit:
  543. if (engineState == PGS_Running) {
  544. engineState = PGS_Quit;
  545. WaitForSingleObject(loop_end_event, 5000);
  546. }
  547. CloseHandle(thread); thread=NULL;
  548. emu_write_config(0);
  549. emu_finish();
  550. //plat_finish();
  551. end0:
  552. DirectExit();
  553. DestroyWindow(FrameWnd);
  554. // _CrtDumpMemoryLeaks();
  555. return 0;
  556. }