5e40e4738673c2c6010e35d1024a5c380b5ccf62
[picodrive.git] / platform / win32 / GenaDrive / Main.cpp
1 #include "app.h"\r
2 #include "version.h"\r
3 #include <crtdbg.h>\r
4 #include <commdlg.h>\r
5 \r
6 char *romname=NULL;\r
7 HWND FrameWnd=NULL;\r
8 RECT FrameRectMy;\r
9 int lock_to_1_1 = 1;\r
10 static HWND PicoSwWnd=NULL, PicoPadWnd=NULL;\r
11 \r
12 int MainWidth=720,MainHeight=480;\r
13 \r
14 static HMENU mmain = 0, mdisplay = 0, mpicohw = 0;\r
15 static int rom_loaded = 0;\r
16 \r
17 static void UpdateRect()\r
18 {\r
19   WINDOWINFO wi;\r
20   memset(&wi, 0, sizeof(wi));\r
21   wi.cbSize = sizeof(wi);\r
22   GetWindowInfo(FrameWnd, &wi);\r
23   FrameRectMy = wi.rcClient;\r
24 }\r
25 \r
26 static void PrepareFroROM()\r
27 {\r
28   int show = PicoAHW & PAHW_PICO;\r
29   EnableMenuItem(mmain, 2, MF_BYPOSITION|(show ? MF_ENABLED : MF_GRAYED));\r
30   ShowWindow(PicoPadWnd, show ? SW_SHOWNA : SW_HIDE);\r
31   ShowWindow(PicoSwWnd, show ? SW_SHOWNA : SW_HIDE);\r
32   CheckMenuItem(mpicohw, 1210, show ? MF_CHECKED : MF_UNCHECKED);\r
33   CheckMenuItem(mpicohw, 1211, show ? MF_CHECKED : MF_UNCHECKED);\r
34   PostMessage(FrameWnd, WM_COMMAND, 1220 + PicoPicohw.page, 0);\r
35   DrawMenuBar(FrameWnd);\r
36 \r
37   PicoPicohw.pen_pos[0] =\r
38   PicoPicohw.pen_pos[1] = 0x8000;\r
39   picohw_pen_pressed = 0;\r
40 }\r
41 \r
42 static void LoadROM(const char *cmdpath)\r
43 {\r
44   static char rompath[MAX_PATH] = { 0, };\r
45   unsigned char *rom_data_new = NULL;\r
46   unsigned int rom_size = 0;\r
47   pm_file *rom = NULL;\r
48   int oldwait=LoopWait;\r
49   int i, ret;\r
50 \r
51   if (cmdpath) {\r
52     strcpy(rompath, cmdpath + (cmdpath[0] == '\"' ? 1 : 0));\r
53     if (rompath[strlen(rompath)-1] == '\"') rompath[strlen(rompath)-1] = 0;\r
54     if (strlen(rompath) > 4) rom = pm_open(rompath);\r
55   }\r
56 \r
57   if (!rom) {\r
58     OPENFILENAME of; ZeroMemory(&of, sizeof(OPENFILENAME));\r
59     of.lStructSize = sizeof(OPENFILENAME);\r
60     of.lpstrFilter = "ROMs\0*.smd;*.bin;*.gen;*.zip\0";\r
61     of.lpstrFile = rompath; rompath[0] = 0;\r
62     of.nMaxFile = MAX_PATH;\r
63     of.Flags = OFN_FILEMUSTEXIST|OFN_HIDEREADONLY;\r
64     of.hwndOwner = FrameWnd;\r
65     if (!GetOpenFileName(&of)) return;\r
66     rom = pm_open(rompath);\r
67     if (!rom) { error("failed to open ROM"); return; }\r
68   }\r
69 \r
70   ret=PicoCartLoad(rom, &rom_data_new, &rom_size);\r
71   pm_close(rom);\r
72   if (ret) {\r
73     error("failed to load ROM");\r
74     return;\r
75   }\r
76 \r
77   // halt the work thread..\r
78   // just a hack, should've used proper sync. primitives here, but who will use this emu anyway..\r
79   LoopWaiting=0;\r
80   LoopWait=1;\r
81   for (i = 0; LoopWaiting == 0 && i < 10; i++) Sleep(100);\r
82 \r
83   PicoCartUnload();\r
84   PicoCartInsert(rom_data_new, rom_size);\r
85 \r
86   PrepareFroROM();\r
87 \r
88   rom_loaded = 1;\r
89   romname = rompath;\r
90   LoopWait=0;\r
91 }\r
92 \r
93 static int rect_widths[4]  = { 320, 256, 640, 512 };\r
94 static int rect_heights[4] = { 224, 224, 448, 448 };\r
95 \r
96 // Window proc for the frame window:\r
97 static LRESULT CALLBACK WndProc(HWND hwnd,UINT msg,WPARAM wparam,LPARAM lparam)\r
98 {\r
99   POINT pt;\r
100   RECT rc;\r
101   int i;\r
102   switch (msg)\r
103   {\r
104     case WM_CLOSE:   PostQuitMessage(0); return 0;\r
105     case WM_DESTROY: FrameWnd=NULL; break; // Blank handle\r
106     case WM_SIZE:\r
107     case WM_MOVE:\r
108     case WM_SIZING:  UpdateRect(); break;\r
109     case WM_COMMAND:\r
110       switch (LOWORD(wparam))\r
111       {\r
112         case 1000: LoadROM(NULL); break;\r
113         case 1001: PicoReset(); return 0;\r
114         case 1002: PostQuitMessage(0); return 0;\r
115         case 1100:\r
116         case 1101:\r
117         case 1102:\r
118         case 1103:\r
119           LoopWait=1; // another sync hack\r
120           for (i = 0; !LoopWaiting && i < 10; i++) Sleep(10);\r
121           FrameRectMy.right  = FrameRectMy.left + rect_widths[wparam&3];\r
122           FrameRectMy.bottom = FrameRectMy.top  + rect_heights[wparam&3];\r
123           AdjustWindowRect(&FrameRectMy, WS_OVERLAPPEDWINDOW, 1);\r
124           MoveWindow(hwnd, FrameRectMy.left, FrameRectMy.top,\r
125             FrameRectMy.right-FrameRectMy.left, FrameRectMy.bottom-FrameRectMy.top, 1);\r
126           UpdateRect();\r
127           if (HIWORD(wparam) == 0) { // locally sent\r
128             lock_to_1_1=0;\r
129             CheckMenuItem(mdisplay, 1104, MF_UNCHECKED);\r
130           }\r
131           if (rom_loaded) LoopWait=0;\r
132           return 0;\r
133         case 1104:\r
134           lock_to_1_1=!lock_to_1_1;\r
135           CheckMenuItem(mdisplay, 1104, lock_to_1_1 ? MF_CHECKED : MF_UNCHECKED);\r
136           return 0;\r
137         case 1210:\r
138         case 1211:\r
139           i = IsWindowVisible((LOWORD(wparam)&1) ? PicoPadWnd : PicoSwWnd);\r
140           i = !i;\r
141           ShowWindow((LOWORD(wparam)&1) ? PicoPadWnd : PicoSwWnd, i ? SW_SHOWNA : SW_HIDE);\r
142           CheckMenuItem(mpicohw, LOWORD(wparam), i ? MF_CHECKED : MF_UNCHECKED);\r
143           return 0;\r
144         case 1220:\r
145         case 1221:\r
146         case 1222:\r
147         case 1223:\r
148         case 1224:\r
149         case 1225:\r
150         case 1226:\r
151           PicoPicohw.page = LOWORD(wparam) % 10;\r
152           for (i = 0; i < 7; i++)\r
153             CheckMenuItem(mpicohw, 1220 + i, MF_UNCHECKED);\r
154           CheckMenuItem(mpicohw, 1220 + PicoPicohw.page, MF_CHECKED);\r
155           return 0;\r
156         case 1300:\r
157           MessageBox(FrameWnd, "PicoDrive v" VERSION " (c) notaz, 2006-2008\n"\r
158               "SVP and Pico demo edition\n\n"\r
159               "Credits:\n"\r
160               "fDave: base code of PicoDrive, GenaDrive (the frontend)\n"\r
161               "Chui: Fame/C\n"\r
162               "NJ: CZ80\n"\r
163               "MAME devs: YM2612 and SN76496 cores\n"\r
164               "Stéphane Dallongeville: Gens code, base of Fame/C (C68K), CZ80\n"\r
165               "Tasco Deluxe: SVP RE work\n"\r
166               "Pierpaolo Prazzoli: info about SSP16 chips\n",\r
167               "About", 0);\r
168           return 0;\r
169       }\r
170       break;\r
171     case WM_TIMER:\r
172       GetCursorPos(&pt);\r
173       GetWindowRect(PicoSwWnd, &rc);\r
174       if (PtInRect(&rc, pt)) break;\r
175       GetWindowRect(PicoPadWnd, &rc);\r
176       if (PtInRect(&rc, pt)) break;\r
177       PicoPicohw.pen_pos[0] |= 0x8000;\r
178       PicoPicohw.pen_pos[1] |= 0x8000;\r
179       picohw_pen_pressed = 0;\r
180       break;\r
181   }\r
182 \r
183   return DefWindowProc(hwnd,msg,wparam,lparam);\r
184 }\r
185 \r
186 static LRESULT CALLBACK PicoSwWndProc(HWND hwnd,UINT msg,WPARAM wparam,LPARAM lparam)\r
187 {\r
188   switch (msg)\r
189   {\r
190     case WM_CLOSE: return 0;\r
191     case WM_DESTROY: PicoSwWnd=NULL; break;\r
192     case WM_LBUTTONDOWN: picohw_pen_pressed = 1; return 0;\r
193     case WM_LBUTTONUP:   picohw_pen_pressed = 0; return 0;\r
194     case WM_MOUSEMOVE:\r
195       PicoPicohw.pen_pos[0] = 0x03c + LOWORD(lparam) * 2/3;\r
196       PicoPicohw.pen_pos[1] = 0x2f8 + HIWORD(lparam);\r
197       SetTimer(FrameWnd, 100, 1000, NULL);\r
198       break;\r
199   }\r
200 \r
201   return DefWindowProc(hwnd,msg,wparam,lparam);\r
202 }\r
203 \r
204 static LRESULT CALLBACK PicoPadWndProc(HWND hwnd,UINT msg,WPARAM wparam,LPARAM lparam)\r
205 {\r
206   switch (msg)\r
207   {\r
208     case WM_CLOSE: return 0;\r
209     case WM_DESTROY: PicoPadWnd=NULL; break;\r
210     case WM_LBUTTONDOWN: picohw_pen_pressed = 1; return 0;\r
211     case WM_LBUTTONUP:   picohw_pen_pressed = 0; return 0;\r
212     case WM_MOUSEMOVE:\r
213       PicoPicohw.pen_pos[0] = 0x03c + LOWORD(lparam);\r
214       PicoPicohw.pen_pos[1] = 0x1fc + HIWORD(lparam);\r
215       SetTimer(FrameWnd, 100, 1000, NULL);\r
216       break;\r
217   }\r
218 \r
219   return DefWindowProc(hwnd,msg,wparam,lparam);\r
220 }\r
221 \r
222 \r
223 static int FrameInit()\r
224 {\r
225   WNDCLASS wc;\r
226   RECT rect={0,0,0,0};\r
227   HMENU mfile;\r
228   int style=0;\r
229   int left=0,top=0,width=0,height=0;\r
230 \r
231   memset(&wc,0,sizeof(wc));\r
232 \r
233   // Register the window class:\r
234   wc.lpfnWndProc=WndProc;\r
235   wc.hInstance=GetModuleHandle(NULL);\r
236   wc.hCursor=LoadCursor(NULL,IDC_ARROW);\r
237   wc.hbrBackground=CreateSolidBrush(0);\r
238   wc.lpszClassName="PicoMainFrame";\r
239   RegisterClass(&wc);\r
240 \r
241   wc.lpszClassName="PicoSwWnd";\r
242   wc.lpfnWndProc=PicoSwWndProc;\r
243   RegisterClass(&wc);\r
244 \r
245   wc.lpszClassName="PicoPadWnd";\r
246   wc.lpfnWndProc=PicoPadWndProc;\r
247   RegisterClass(&wc);\r
248 \r
249   rect.right =320;//MainWidth;\r
250   rect.bottom=224;//MainHeight;\r
251 \r
252   // Adjust size of windows based on borders:\r
253   style=WS_OVERLAPPEDWINDOW;\r
254   AdjustWindowRect(&rect,style,1);\r
255   width =rect.right-rect.left;\r
256   height=rect.bottom-rect.top;\r
257 \r
258   // Place window in the centre of the screen:\r
259   SystemParametersInfo(SPI_GETWORKAREA,0,&rect,0);\r
260   left=rect.left+rect.right;\r
261   top=rect.top+rect.bottom;\r
262 \r
263   left-=width; left>>=1;\r
264   top-=height; top>>=1;\r
265 \r
266   // Create menu:\r
267   mfile = CreateMenu();\r
268   InsertMenu(mfile, -1, MF_BYPOSITION|MF_STRING, 1000, "&Load ROM");\r
269   InsertMenu(mfile, -1, MF_BYPOSITION|MF_STRING, 1001, "&Reset");\r
270   InsertMenu(mfile, -1, MF_BYPOSITION|MF_STRING, 1002, "E&xit");\r
271   mdisplay = CreateMenu();\r
272   InsertMenu(mdisplay, -1, MF_BYPOSITION|MF_STRING, 1100, "320x224");\r
273   InsertMenu(mdisplay, -1, MF_BYPOSITION|MF_STRING, 1101, "256x224");\r
274   InsertMenu(mdisplay, -1, MF_BYPOSITION|MF_STRING, 1102, "640x448");\r
275   InsertMenu(mdisplay, -1, MF_BYPOSITION|MF_STRING, 1103, "512x448");\r
276   InsertMenu(mdisplay, -1, MF_BYPOSITION|MF_STRING, 1104, "Lock to 1:1");\r
277   mpicohw = CreateMenu();\r
278   InsertMenu(mpicohw, -1, MF_BYPOSITION|MF_STRING, 1210, "Show &Storyware");\r
279   InsertMenu(mpicohw, -1, MF_BYPOSITION|MF_STRING, 1211, "Show &Drawing pad");\r
280   InsertMenu(mpicohw, -1, MF_BYPOSITION|MF_SEPARATOR, 0, NULL);\r
281   InsertMenu(mpicohw, -1, MF_BYPOSITION|MF_STRING, 1220, "Title page (&0)");\r
282   InsertMenu(mpicohw, -1, MF_BYPOSITION|MF_STRING, 1221, "Page &1");\r
283   InsertMenu(mpicohw, -1, MF_BYPOSITION|MF_STRING, 1222, "Page &2");\r
284   InsertMenu(mpicohw, -1, MF_BYPOSITION|MF_STRING, 1223, "Page &3");\r
285   InsertMenu(mpicohw, -1, MF_BYPOSITION|MF_STRING, 1224, "Page &4");\r
286   InsertMenu(mpicohw, -1, MF_BYPOSITION|MF_STRING, 1225, "Page &5");\r
287   InsertMenu(mpicohw, -1, MF_BYPOSITION|MF_STRING, 1226, "Page &6");\r
288   mmain = CreateMenu();\r
289   InsertMenu(mmain, -1, MF_BYPOSITION|MF_STRING|MF_POPUP, (UINT_PTR) mfile,    "&File");\r
290   InsertMenu(mmain, -1, MF_BYPOSITION|MF_STRING|MF_POPUP, (UINT_PTR) mdisplay, "&Display");\r
291   InsertMenu(mmain, -1, MF_BYPOSITION|MF_STRING|MF_POPUP, (UINT_PTR) mpicohw,  "&Pico");\r
292   EnableMenuItem(mmain, 2, MF_BYPOSITION|MF_GRAYED);\r
293 //  InsertMenu(mmain, -1, MF_BYPOSITION|MF_STRING|MF_POPUP, 1200, "&Config");\r
294   InsertMenu(mmain, -1, MF_BYPOSITION|MF_STRING, 1300, "&About");\r
295 \r
296   // Create the window:\r
297   FrameWnd=CreateWindow("PicoMainFrame","PicoDrive " VERSION,style|WS_VISIBLE,\r
298     left,top,width,height,NULL,mmain,NULL,NULL);\r
299 \r
300   CheckMenuItem(mdisplay, 1104, lock_to_1_1 ? MF_CHECKED : MF_UNCHECKED);\r
301   ShowWindow(FrameWnd, SW_NORMAL);\r
302   UpdateWindow(FrameWnd);\r
303   UpdateRect();\r
304 \r
305   // create Pico windows\r
306   style = WS_OVERLAPPED|WS_CAPTION|WS_BORDER;\r
307   rect.left=rect.top=0;\r
308   rect.right =320;\r
309   rect.bottom=224;\r
310 \r
311   AdjustWindowRect(&rect,style,1);\r
312   width =rect.right-rect.left;\r
313   height=rect.bottom-rect.top;\r
314 \r
315   left += 326;\r
316   PicoSwWnd=CreateWindow("PicoSwWnd","Storyware",style,\r
317     left,top,width+160,height,FrameWnd,NULL,NULL,NULL);\r
318 \r
319   top += 266;\r
320   PicoPadWnd=CreateWindow("PicoPadWnd","Drawing Pad",style,\r
321     left,top,width,height,FrameWnd,NULL,NULL,NULL);\r
322 \r
323   return 0;\r
324 }\r
325 \r
326 // --------------------\r
327 \r
328 static DWORD WINAPI ThreadCode(void *)\r
329 {\r
330   LoopCode();\r
331   return 0;\r
332 }\r
333 \r
334 int WINAPI WinMain(HINSTANCE,HINSTANCE,LPSTR cmdline,int)\r
335 {\r
336   MSG msg;\r
337   int ret=0;\r
338   DWORD tid=0;\r
339   HANDLE thread=NULL;\r
340 \r
341   FrameInit();\r
342   ret=LoopInit(); if (ret) goto end0;\r
343 \r
344   // Make another thread to run LoopCode():\r
345   LoopQuit=0;\r
346   LoopWait=1; // wait for ROM to be loaded\r
347   thread=CreateThread(NULL,0,ThreadCode,NULL,0,&tid);\r
348 \r
349   LoadROM(cmdline);\r
350 \r
351   // Main window loop:\r
352   for (;;)\r
353   {\r
354     GetMessage(&msg,NULL,0,0);\r
355     if (msg.message==WM_QUIT) break;\r
356 \r
357     TranslateMessage(&msg);\r
358     DispatchMessage(&msg);\r
359   }\r
360 \r
361   // Signal thread to quit and wait for it to exit:\r
362   LoopQuit=1; WaitForSingleObject(thread,5000);\r
363   CloseHandle(thread); thread=NULL;\r
364 \r
365 end0:\r
366   LoopExit();\r
367   DestroyWindow(FrameWnd);\r
368 \r
369   _CrtDumpMemoryLeaks();\r
370   return 0;\r
371 }\r
372 \r
373 extern void error(char *text)\r
374 {\r
375   MessageBox(FrameWnd, text, "Error", 0);\r
376 }\r
377 \r