5 #include "../../common/readpng.h"
\r
10 int lock_to_1_1 = 1;
\r
11 static HWND PicoSwWnd=NULL, PicoPadWnd=NULL;
\r
13 int MainWidth=720,MainHeight=480;
\r
15 static HMENU mmain = 0, mdisplay = 0, mpicohw = 0;
\r
16 static int rom_loaded = 0;
\r
17 static HBITMAP ppad_bmp = 0;
\r
18 static HBITMAP ppage_bmps[6] = { 0, };
\r
19 static char rom_name[0x20*3+1];
\r
21 static void UpdateRect()
\r
24 memset(&wi, 0, sizeof(wi));
\r
25 wi.cbSize = sizeof(wi);
\r
26 GetWindowInfo(FrameWnd, &wi);
\r
27 FrameRectMy = wi.rcClient;
\r
30 static int extract_rom_name(char *dest, const unsigned char *src, int len)
\r
32 char *p = dest, s_old = 0;
\r
35 for (i = len - 1; i >= 0; i--)
\r
37 if (src[i^1] != ' ') break;
\r
41 for (i = 0; i < len; i++)
\r
43 unsigned char s = src[i^1];
\r
44 if (s == 0x20 && s_old == 0x20) continue;
\r
45 else if (s >= 0x20 && s < 0x7f && s != '%')
\r
51 sprintf(p, "%%%02x", s);
\r
62 static HBITMAP png2hb(const char *fname, int is_480)
\r
64 BITMAPINFOHEADER bih;
\r
69 bmem = calloc(1, is_480 ? 480*240*3 : 320*240*3);
\r
70 if (bmem == NULL) return NULL;
\r
71 ret = readpng(bmem, fname, is_480 ? READPNG_480_24 : READPNG_320_24);
\r
77 memset(&bih, 0, sizeof(bih));
\r
78 bih.biSize = sizeof(bih);
\r
79 bih.biWidth = is_480 ? 480 : 320;
\r
80 bih.biHeight = -240;
\r
82 bih.biBitCount = 24;
\r
83 bih.biCompression = BI_RGB;
\r
84 bmp = CreateDIBitmap(GetDC(FrameWnd), &bih, CBM_INIT, bmem, (BITMAPINFO *)&bih, 0);
\r
86 lprintf("CreateDIBitmap failed with %i", GetLastError());
\r
92 static void PrepareForROM(unsigned char *rom_data)
\r
94 int i, ret, show = PicoAHW & PAHW_PICO;
\r
95 EnableMenuItem(mmain, 2, MF_BYPOSITION|(show ? MF_ENABLED : MF_GRAYED));
\r
96 ShowWindow(PicoPadWnd, show ? SW_SHOWNA : SW_HIDE);
\r
97 ShowWindow(PicoSwWnd, show ? SW_SHOWNA : SW_HIDE);
\r
98 CheckMenuItem(mpicohw, 1210, show ? MF_CHECKED : MF_UNCHECKED);
\r
99 CheckMenuItem(mpicohw, 1211, show ? MF_CHECKED : MF_UNCHECKED);
\r
100 PostMessage(FrameWnd, WM_COMMAND, 1220 + PicoPicohw.page, 0);
\r
101 DrawMenuBar(FrameWnd);
\r
102 InvalidateRect(PicoSwWnd, NULL, 1);
\r
104 PicoPicohw.pen_pos[0] =
\r
105 PicoPicohw.pen_pos[1] = 0x8000;
\r
106 picohw_pen_pressed = 0;
\r
108 ret = extract_rom_name(rom_name, rom_data + 0x150, 0x20);
\r
110 extract_rom_name(rom_name, rom_data + 0x130, 0x20);
\r
114 char path[MAX_PATH], *p;
\r
115 GetModuleFileName(NULL, path, sizeof(path) - 32);
\r
116 p = strrchr(path, '\\');
\r
117 if (p == NULL) p = path;
\r
119 if (ppad_bmp == NULL) {
\r
120 strcpy(p, "pico\\pad.png");
\r
121 ppad_bmp = png2hb(path, 0);
\r
124 for (i = 0; i < 6; i++) {
\r
125 if (ppage_bmps[i] != NULL) DeleteObject(ppage_bmps[i]);
\r
126 sprintf(p, "pico\\%s_%i.png", rom_name, i);
\r
127 ppage_bmps[i] = png2hb(path, 1);
\r
132 static void LoadROM(const char *cmdpath)
\r
134 static char rompath[MAX_PATH] = { 0, };
\r
135 unsigned char *rom_data_new = NULL;
\r
136 unsigned int rom_size = 0;
\r
137 pm_file *rom = NULL;
\r
138 int oldwait=LoopWait;
\r
142 strcpy(rompath, cmdpath + (cmdpath[0] == '\"' ? 1 : 0));
\r
143 if (rompath[strlen(rompath)-1] == '\"') rompath[strlen(rompath)-1] = 0;
\r
144 if (strlen(rompath) > 4) rom = pm_open(rompath);
\r
148 OPENFILENAME of; ZeroMemory(&of, sizeof(OPENFILENAME));
\r
149 of.lStructSize = sizeof(OPENFILENAME);
\r
150 of.lpstrFilter = "ROMs\0*.smd;*.bin;*.gen;*.zip\0";
\r
151 of.lpstrFile = rompath; rompath[0] = 0;
\r
152 of.nMaxFile = MAX_PATH;
\r
153 of.Flags = OFN_FILEMUSTEXIST|OFN_HIDEREADONLY;
\r
154 of.hwndOwner = FrameWnd;
\r
155 if (!GetOpenFileName(&of)) return;
\r
156 rom = pm_open(rompath);
\r
157 if (!rom) { error("failed to open ROM"); return; }
\r
160 ret=PicoCartLoad(rom, &rom_data_new, &rom_size);
\r
163 error("failed to load ROM");
\r
167 // halt the work thread..
\r
168 // just a hack, should've used proper sync. primitives here, but who will use this emu anyway..
\r
171 for (i = 0; LoopWaiting == 0 && i < 10; i++) Sleep(100);
\r
174 PicoCartInsert(rom_data_new, rom_size);
\r
176 PrepareForROM(rom_data_new);
\r
183 static int rect_widths[4] = { 320, 256, 640, 512 };
\r
184 static int rect_heights[4] = { 224, 224, 448, 448 };
\r
186 // Window proc for the frame window:
\r
187 static LRESULT CALLBACK WndProc(HWND hwnd,UINT msg,WPARAM wparam,LPARAM lparam)
\r
194 case WM_CLOSE: PostQuitMessage(0); return 0;
\r
195 case WM_DESTROY: FrameWnd=NULL; break; // Blank handle
\r
198 case WM_SIZING: UpdateRect(); break;
\r
200 switch (LOWORD(wparam))
\r
202 case 1000: LoadROM(NULL); break;
\r
203 case 1001: PicoReset(); return 0;
\r
204 case 1002: PostQuitMessage(0); return 0;
\r
209 LoopWait=1; // another sync hack
\r
210 for (i = 0; !LoopWaiting && i < 10; i++) Sleep(10);
\r
211 FrameRectMy.right = FrameRectMy.left + rect_widths[wparam&3];
\r
212 FrameRectMy.bottom = FrameRectMy.top + rect_heights[wparam&3];
\r
213 AdjustWindowRect(&FrameRectMy, WS_OVERLAPPEDWINDOW, 1);
\r
214 MoveWindow(hwnd, FrameRectMy.left, FrameRectMy.top,
\r
215 FrameRectMy.right-FrameRectMy.left, FrameRectMy.bottom-FrameRectMy.top, 1);
\r
217 if (HIWORD(wparam) == 0) { // locally sent
\r
219 CheckMenuItem(mdisplay, 1104, MF_UNCHECKED);
\r
221 if (rom_loaded) LoopWait=0;
\r
224 lock_to_1_1=!lock_to_1_1;
\r
225 CheckMenuItem(mdisplay, 1104, lock_to_1_1 ? MF_CHECKED : MF_UNCHECKED);
\r
229 i = IsWindowVisible((LOWORD(wparam)&1) ? PicoPadWnd : PicoSwWnd);
\r
231 ShowWindow((LOWORD(wparam)&1) ? PicoPadWnd : PicoSwWnd, i ? SW_SHOWNA : SW_HIDE);
\r
232 CheckMenuItem(mpicohw, LOWORD(wparam), i ? MF_CHECKED : MF_UNCHECKED);
\r
241 PicoPicohw.page = LOWORD(wparam) % 10;
\r
242 for (i = 0; i < 7; i++)
\r
243 CheckMenuItem(mpicohw, 1220 + i, MF_UNCHECKED);
\r
244 CheckMenuItem(mpicohw, 1220 + PicoPicohw.page, MF_CHECKED);
\r
245 InvalidateRect(PicoSwWnd, NULL, 1);
\r
248 MessageBox(FrameWnd, "PicoDrive v" VERSION " (c) notaz, 2006-2008\n"
\r
249 "SVP and Pico demo edition\n\n"
\r
251 "fDave: base code of PicoDrive, GenaDrive (the frontend)\n"
\r
254 "MAME devs: YM2612 and SN76496 cores\n"
\r
255 "Stéphane Dallongeville: Gens code, base of Fame/C (C68K), CZ80\n"
\r
256 "Tasco Deluxe: SVP RE work\n"
\r
257 "Pierpaolo Prazzoli: info about SSP16 chips\n",
\r
264 GetWindowRect(PicoSwWnd, &rc);
\r
265 if (PtInRect(&rc, pt)) break;
\r
266 GetWindowRect(PicoPadWnd, &rc);
\r
267 if (PtInRect(&rc, pt)) break;
\r
268 PicoPicohw.pen_pos[0] |= 0x8000;
\r
269 PicoPicohw.pen_pos[1] |= 0x8000;
\r
270 picohw_pen_pressed = 0;
\r
274 return DefWindowProc(hwnd,msg,wparam,lparam);
\r
277 static LRESULT CALLBACK PicoSwWndProc(HWND hwnd,UINT msg,WPARAM wparam,LPARAM lparam)
\r
284 case WM_CLOSE: return 0;
\r
285 case WM_DESTROY: PicoSwWnd=NULL; break;
\r
286 case WM_LBUTTONDOWN: picohw_pen_pressed = 1; return 0;
\r
287 case WM_LBUTTONUP: picohw_pen_pressed = 0; return 0;
\r
289 PicoPicohw.pen_pos[0] = 0x03c + LOWORD(lparam) * 2/3;
\r
290 PicoPicohw.pen_pos[1] = 0x2f8 + HIWORD(lparam);
\r
291 SetTimer(FrameWnd, 100, 1000, NULL);
\r
294 hdc = BeginPaint(hwnd, &ps);
\r
295 if (ppage_bmps[PicoPicohw.page] == NULL)
\r
297 SelectObject(hdc, GetStockObject(DEFAULT_GUI_FONT));
\r
298 SetTextColor(hdc, RGB(255, 255, 255));
\r
299 SetBkColor(hdc, RGB(0, 0, 0));
\r
300 TextOut(hdc, 2, 2, "missing PNGs for", 16);
\r
301 TextOut(hdc, 2, 18, rom_name, strlen(rom_name));
\r
305 hdc2 = CreateCompatibleDC(GetDC(FrameWnd));
\r
306 SelectObject(hdc2, ppage_bmps[PicoPicohw.page]);
\r
307 BitBlt(hdc, 0, 0, 480, 240, hdc2, 0, 0, SRCCOPY);
\r
310 EndPaint(hwnd, &ps);
\r
314 return DefWindowProc(hwnd,msg,wparam,lparam);
\r
317 static LRESULT CALLBACK PicoPadWndProc(HWND hwnd,UINT msg,WPARAM wparam,LPARAM lparam)
\r
324 case WM_CLOSE: return 0;
\r
325 case WM_DESTROY: PicoPadWnd=NULL; break;
\r
326 case WM_LBUTTONDOWN: picohw_pen_pressed = 1; return 0;
\r
327 case WM_LBUTTONUP: picohw_pen_pressed = 0; return 0;
\r
329 PicoPicohw.pen_pos[0] = 0x03c + LOWORD(lparam);
\r
330 PicoPicohw.pen_pos[1] = 0x1fc + HIWORD(lparam);
\r
331 SetTimer(FrameWnd, 100, 1000, NULL);
\r
334 if (ppad_bmp == NULL) break;
\r
335 hdc = BeginPaint(hwnd, &ps);
\r
336 hdc2 = CreateCompatibleDC(GetDC(FrameWnd));
\r
337 SelectObject(hdc2, ppad_bmp);
\r
338 BitBlt(hdc, 0, 0, 320, 240, hdc2, 0, 0, SRCCOPY);
\r
339 EndPaint(hwnd, &ps);
\r
344 return DefWindowProc(hwnd,msg,wparam,lparam);
\r
348 static int FrameInit()
\r
351 RECT rect={0,0,0,0};
\r
354 int left=0,top=0,width=0,height=0;
\r
356 memset(&wc,0,sizeof(wc));
\r
358 // Register the window class:
\r
359 wc.lpfnWndProc=WndProc;
\r
360 wc.hInstance=GetModuleHandle(NULL);
\r
361 wc.hCursor=LoadCursor(NULL,IDC_ARROW);
\r
362 wc.hbrBackground=CreateSolidBrush(0);
\r
363 wc.lpszClassName="PicoMainFrame";
\r
364 RegisterClass(&wc);
\r
366 wc.lpszClassName="PicoSwWnd";
\r
367 wc.lpfnWndProc=PicoSwWndProc;
\r
368 RegisterClass(&wc);
\r
370 wc.lpszClassName="PicoPadWnd";
\r
371 wc.lpfnWndProc=PicoPadWndProc;
\r
372 RegisterClass(&wc);
\r
374 rect.right =320;//MainWidth;
\r
375 rect.bottom=224;//MainHeight;
\r
377 // Adjust size of windows based on borders:
\r
378 style=WS_OVERLAPPEDWINDOW;
\r
379 AdjustWindowRect(&rect,style,1);
\r
380 width =rect.right-rect.left;
\r
381 height=rect.bottom-rect.top;
\r
383 // Place window in the centre of the screen:
\r
384 SystemParametersInfo(SPI_GETWORKAREA,0,&rect,0);
\r
385 left=rect.left+rect.right;
\r
386 top=rect.top+rect.bottom;
\r
388 left-=width; left>>=1;
\r
389 top-=height; top>>=1;
\r
392 mfile = CreateMenu();
\r
393 InsertMenu(mfile, -1, MF_BYPOSITION|MF_STRING, 1000, "&Load ROM");
\r
394 InsertMenu(mfile, -1, MF_BYPOSITION|MF_STRING, 1001, "&Reset");
\r
395 InsertMenu(mfile, -1, MF_BYPOSITION|MF_STRING, 1002, "E&xit");
\r
396 mdisplay = CreateMenu();
\r
397 InsertMenu(mdisplay, -1, MF_BYPOSITION|MF_STRING, 1100, "320x224");
\r
398 InsertMenu(mdisplay, -1, MF_BYPOSITION|MF_STRING, 1101, "256x224");
\r
399 InsertMenu(mdisplay, -1, MF_BYPOSITION|MF_STRING, 1102, "640x448");
\r
400 InsertMenu(mdisplay, -1, MF_BYPOSITION|MF_STRING, 1103, "512x448");
\r
401 InsertMenu(mdisplay, -1, MF_BYPOSITION|MF_STRING, 1104, "Lock to 1:1");
\r
402 mpicohw = CreateMenu();
\r
403 InsertMenu(mpicohw, -1, MF_BYPOSITION|MF_STRING, 1210, "Show &Storyware");
\r
404 InsertMenu(mpicohw, -1, MF_BYPOSITION|MF_STRING, 1211, "Show &Drawing pad");
\r
405 InsertMenu(mpicohw, -1, MF_BYPOSITION|MF_SEPARATOR, 0, NULL);
\r
406 InsertMenu(mpicohw, -1, MF_BYPOSITION|MF_STRING, 1220, "Title page (&0)");
\r
407 InsertMenu(mpicohw, -1, MF_BYPOSITION|MF_STRING, 1221, "Page &1");
\r
408 InsertMenu(mpicohw, -1, MF_BYPOSITION|MF_STRING, 1222, "Page &2");
\r
409 InsertMenu(mpicohw, -1, MF_BYPOSITION|MF_STRING, 1223, "Page &3");
\r
410 InsertMenu(mpicohw, -1, MF_BYPOSITION|MF_STRING, 1224, "Page &4");
\r
411 InsertMenu(mpicohw, -1, MF_BYPOSITION|MF_STRING, 1225, "Page &5");
\r
412 InsertMenu(mpicohw, -1, MF_BYPOSITION|MF_STRING, 1226, "Page &6");
\r
413 mmain = CreateMenu();
\r
414 InsertMenu(mmain, -1, MF_BYPOSITION|MF_STRING|MF_POPUP, (UINT_PTR) mfile, "&File");
\r
415 InsertMenu(mmain, -1, MF_BYPOSITION|MF_STRING|MF_POPUP, (UINT_PTR) mdisplay, "&Display");
\r
416 InsertMenu(mmain, -1, MF_BYPOSITION|MF_STRING|MF_POPUP, (UINT_PTR) mpicohw, "&Pico");
\r
417 EnableMenuItem(mmain, 2, MF_BYPOSITION|MF_GRAYED);
\r
418 // InsertMenu(mmain, -1, MF_BYPOSITION|MF_STRING|MF_POPUP, 1200, "&Config");
\r
419 InsertMenu(mmain, -1, MF_BYPOSITION|MF_STRING, 1300, "&About");
\r
421 // Create the window:
\r
422 FrameWnd=CreateWindow("PicoMainFrame","PicoDrive " VERSION,style|WS_VISIBLE,
\r
423 left,top,width,height,NULL,mmain,NULL,NULL);
\r
425 CheckMenuItem(mdisplay, 1104, lock_to_1_1 ? MF_CHECKED : MF_UNCHECKED);
\r
426 ShowWindow(FrameWnd, SW_NORMAL);
\r
427 UpdateWindow(FrameWnd);
\r
430 // create Pico windows
\r
431 style = WS_OVERLAPPED|WS_CAPTION|WS_BORDER;
\r
432 rect.left=rect.top=0;
\r
436 AdjustWindowRect(&rect,style,1);
\r
437 width =rect.right-rect.left;
\r
438 height=rect.bottom-rect.top;
\r
441 PicoSwWnd=CreateWindow("PicoSwWnd","Storyware",style,
\r
442 left,top,width+160,height,FrameWnd,NULL,NULL,NULL);
\r
445 PicoPadWnd=CreateWindow("PicoPadWnd","Drawing Pad",style,
\r
446 left,top,width,height,FrameWnd,NULL,NULL,NULL);
\r
451 // --------------------
\r
453 static DWORD WINAPI ThreadCode(void *)
\r
459 int WINAPI WinMain(HINSTANCE,HINSTANCE,LPSTR cmdline,int)
\r
464 HANDLE thread=NULL;
\r
467 ret=LoopInit(); if (ret) goto end0;
\r
469 // Make another thread to run LoopCode():
\r
471 LoopWait=1; // wait for ROM to be loaded
\r
472 thread=CreateThread(NULL,0,ThreadCode,NULL,0,&tid);
\r
476 // Main window loop:
\r
479 GetMessage(&msg,NULL,0,0);
\r
480 if (msg.message==WM_QUIT) break;
\r
482 TranslateMessage(&msg);
\r
483 DispatchMessage(&msg);
\r
486 // Signal thread to quit and wait for it to exit:
\r
487 LoopQuit=1; WaitForSingleObject(thread,5000);
\r
488 CloseHandle(thread); thread=NULL;
\r
492 DestroyWindow(FrameWnd);
\r
494 _CrtDumpMemoryLeaks();
\r
498 extern void error(char *text)
\r
500 MessageBox(FrameWnd, text, "Error", 0);
\r