VR DMA timing hack added. Probably wrong.
[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 \r
11 int MainWidth=720,MainHeight=480;\r
12 \r
13 static HMENU mdisplay = 0;\r
14 static unsigned char *rom_data = NULL;\r
15 \r
16 static void UpdateRect()\r
17 {\r
18   WINDOWINFO wi;\r
19   memset(&wi, 0, sizeof(wi));\r
20   wi.cbSize = sizeof(wi);\r
21   GetWindowInfo(FrameWnd, &wi);\r
22   FrameRectMy = wi.rcClient;\r
23 }\r
24 \r
25 static void LoadROM(const char *cmdpath)\r
26 {\r
27   static char rompath[MAX_PATH] = { 0, };\r
28   unsigned char *rom_data_new = NULL;\r
29   unsigned int rom_size = 0;\r
30   pm_file *rom = NULL;\r
31   int oldwait=LoopWait;\r
32   int i, ret;\r
33 \r
34   if (cmdpath) {\r
35     strcpy(rompath, cmdpath + (cmdpath[0] == '\"' ? 1 : 0));\r
36     if (rompath[strlen(rompath)-1] == '\"') rompath[strlen(rompath)-1] = 0;\r
37     if (strlen(rompath) > 4) rom = pm_open(rompath);\r
38   }\r
39 \r
40   if (!rom) {\r
41     OPENFILENAME of; ZeroMemory(&of, sizeof(OPENFILENAME));\r
42     of.lStructSize = sizeof(OPENFILENAME);\r
43     of.lpstrFilter = "ROMs\0*.smd;*.bin;*.gen;*.zip\0";\r
44     of.lpstrFile = rompath; rompath[0] = 0;\r
45     of.nMaxFile = MAX_PATH;\r
46     of.Flags = OFN_FILEMUSTEXIST|OFN_HIDEREADONLY;\r
47     of.hwndOwner = FrameWnd;\r
48     if (!GetOpenFileName(&of)) return;\r
49     rom = pm_open(rompath);\r
50     if (!rom) { error("failed to open ROM"); return; }\r
51   }\r
52 \r
53   ret=PicoCartLoad(rom, &rom_data_new, &rom_size);\r
54   pm_close(rom);\r
55   if (ret) {\r
56     error("failed to load ROM");\r
57     return;\r
58   }\r
59 \r
60   // halt the work thread..\r
61   // just a hack, should've used proper sync. primitives here, but who will use this emu anyway..\r
62   LoopWaiting=0;\r
63   LoopWait=1;\r
64   for (i = 0; LoopWaiting == 0 && i < 10; i++) Sleep(100);\r
65 \r
66   PicoCartInsert(rom_data_new, rom_size);\r
67 \r
68   if (rom_data) free(rom_data);\r
69   rom_data = rom_data_new;\r
70   romname = rompath;\r
71   LoopWait=0;\r
72 }\r
73 \r
74 static int rect_widths[4]  = { 320, 256, 640, 512 };\r
75 static int rect_heights[4] = { 224, 224, 448, 448 };\r
76 \r
77 // Window proc for the frame window:\r
78 static LRESULT CALLBACK WndProc(HWND hwnd,UINT msg,WPARAM wparam,LPARAM lparam)\r
79 {\r
80   int i;\r
81   switch (msg)\r
82   {\r
83     case WM_CLOSE:   PostQuitMessage(0); return 0;\r
84     case WM_DESTROY: FrameWnd=NULL; break; // Blank handle\r
85     case WM_SIZE:\r
86     case WM_MOVE:\r
87     case WM_SIZING:  UpdateRect(); break;\r
88     case WM_COMMAND:\r
89       switch (LOWORD(wparam))\r
90       {\r
91         case 1000: LoadROM(NULL); break;\r
92         case 1001: PostQuitMessage(0); return 0;\r
93         case 1100:\r
94         case 1101:\r
95         case 1102:\r
96         case 1103:\r
97           LoopWait=1; // another sync hack\r
98           for (i = 0; !LoopWaiting && i < 10; i++) Sleep(10);\r
99           FrameRectMy.right  = FrameRectMy.left + rect_widths[wparam&3];\r
100           FrameRectMy.bottom = FrameRectMy.top  + rect_heights[wparam&3];\r
101           AdjustWindowRect(&FrameRectMy, WS_OVERLAPPEDWINDOW, 1);\r
102           MoveWindow(hwnd, FrameRectMy.left, FrameRectMy.top,\r
103             FrameRectMy.right-FrameRectMy.left, FrameRectMy.bottom-FrameRectMy.top, 1);\r
104           UpdateRect();\r
105           if (HIWORD(wparam) == 0) { // locally sent\r
106             lock_to_1_1=0;\r
107             CheckMenuItem(mdisplay, 1104, MF_UNCHECKED);\r
108           }\r
109           if (rom_data != NULL) LoopWait=0;\r
110           return 0;\r
111         case 1104:\r
112           lock_to_1_1=!lock_to_1_1;\r
113           CheckMenuItem(mdisplay, 1104, lock_to_1_1 ? MF_CHECKED : MF_UNCHECKED);\r
114           return 0;\r
115         case 1200: break;\r
116         case 1300:\r
117           MessageBox(FrameWnd, "PicoDrive v" VERSION " (c) notaz, 2006-2008\n"\r
118               "SVP demo edition\n\n"\r
119               "Credits:\n"\r
120               "fDave: base code of PicoDrive, GenaDrive (the frontend)\n"\r
121               "Chui: Fame/C\n"\r
122               "NJ: CZ80\n"\r
123               "MAME devs: YM2612 and SN76496 cores\n"\r
124               "Stéphane Dallongeville: Gens code, base of Fame/C (C68K), CZ80\n"\r
125               "Tasco Deluxe: SVP RE work\n",\r
126               "About", 0);\r
127           return 0;\r
128       }\r
129       break;\r
130   }\r
131 \r
132   return DefWindowProc(hwnd,msg,wparam,lparam);\r
133 }\r
134 \r
135 static int FrameInit()\r
136 {\r
137   WNDCLASS wc;\r
138   RECT rect={0,0,0,0};\r
139   HMENU mmain, mfile;\r
140   int style=0;\r
141   int left=0,top=0,width=0,height=0;\r
142 \r
143   memset(&wc,0,sizeof(wc));\r
144 \r
145   // Register the window class:\r
146   wc.lpfnWndProc=WndProc;\r
147   wc.hInstance=GetModuleHandle(NULL);\r
148   wc.hCursor=LoadCursor(NULL,IDC_ARROW);\r
149   wc.hbrBackground=CreateSolidBrush(0);\r
150   wc.lpszClassName="MainFrame";\r
151   RegisterClass(&wc);\r
152 \r
153   rect.right =320;//MainWidth;\r
154   rect.bottom=224;//MainHeight;\r
155 \r
156   // Adjust size of windows based on borders:\r
157   style=WS_OVERLAPPEDWINDOW;\r
158   AdjustWindowRect(&rect,style,1);\r
159   width =rect.right-rect.left;\r
160   height=rect.bottom-rect.top;\r
161 \r
162   // Place window in the centre of the screen:\r
163   SystemParametersInfo(SPI_GETWORKAREA,0,&rect,0);\r
164   left=rect.left+rect.right;\r
165   top=rect.top+rect.bottom;\r
166 \r
167   left-=width; left>>=1;\r
168   top-=height; top>>=1;\r
169 \r
170   // Create menu:\r
171   mfile = CreateMenu();\r
172   InsertMenu(mfile, -1, MF_BYPOSITION|MF_STRING, 1000, "&Load ROM");\r
173   InsertMenu(mfile, -1, MF_BYPOSITION|MF_STRING, 1001, "E&xit");\r
174   mdisplay = CreateMenu();\r
175   InsertMenu(mdisplay, -1, MF_BYPOSITION|MF_STRING, 1100, "320x224");\r
176   InsertMenu(mdisplay, -1, MF_BYPOSITION|MF_STRING, 1101, "256x224");\r
177   InsertMenu(mdisplay, -1, MF_BYPOSITION|MF_STRING, 1102, "640x448");\r
178   InsertMenu(mdisplay, -1, MF_BYPOSITION|MF_STRING, 1103, "512x448");\r
179   InsertMenu(mdisplay, -1, MF_BYPOSITION|MF_STRING, 1104, "Lock to 1:1");\r
180   mmain = CreateMenu();\r
181   InsertMenu(mmain, -1, MF_BYPOSITION|MF_STRING|MF_POPUP, (UINT_PTR) mfile, "&File");\r
182   InsertMenu(mmain, -1, MF_BYPOSITION|MF_STRING|MF_POPUP, (UINT_PTR) mdisplay, "&Display");\r
183 //  InsertMenu(mmain, -1, MF_BYPOSITION|MF_STRING|MF_POPUP, 1200, "&Config");\r
184   InsertMenu(mmain, -1, MF_BYPOSITION|MF_STRING, 1300, "&About");\r
185 \r
186   // Create the window:\r
187   FrameWnd=CreateWindow(wc.lpszClassName,"PicoDrive " VERSION,style|WS_VISIBLE,\r
188     left,top,width,height,NULL,mmain,NULL,NULL);\r
189 \r
190   CheckMenuItem(mdisplay, 1104, lock_to_1_1 ? MF_CHECKED : MF_UNCHECKED);\r
191   ShowWindow(FrameWnd, SW_NORMAL);\r
192   UpdateWindow(FrameWnd);\r
193   UpdateRect();\r
194 \r
195   return 0;\r
196 }\r
197 \r
198 // --------------------\r
199 \r
200 static DWORD WINAPI ThreadCode(void *)\r
201 {\r
202   LoopCode();\r
203   return 0;\r
204 }\r
205 \r
206 int WINAPI WinMain(HINSTANCE,HINSTANCE,LPSTR cmdline,int)\r
207 {\r
208   MSG msg;\r
209   int ret=0;\r
210   DWORD tid=0;\r
211   HANDLE thread=NULL;\r
212 \r
213   FrameInit();\r
214   ret=LoopInit(); if (ret) goto end0;\r
215 \r
216   // Make another thread to run LoopCode():\r
217   LoopQuit=0;\r
218   LoopWait=1; // wait for ROM to be loaded\r
219   thread=CreateThread(NULL,0,ThreadCode,NULL,0,&tid);\r
220 \r
221   LoadROM(cmdline);\r
222 \r
223   // Main window loop:\r
224   for (;;)\r
225   {\r
226     GetMessage(&msg,NULL,0,0);\r
227     if (msg.message==WM_QUIT) break;\r
228 \r
229     TranslateMessage(&msg);\r
230     DispatchMessage(&msg);\r
231   }\r
232 \r
233   // Signal thread to quit and wait for it to exit:\r
234   LoopQuit=1; WaitForSingleObject(thread,5000);\r
235   CloseHandle(thread); thread=NULL;\r
236 \r
237 end0:\r
238   LoopExit();\r
239   DestroyWindow(FrameWnd);\r
240 \r
241   _CrtDumpMemoryLeaks();\r
242   return 0;\r
243 }\r
244 \r
245 extern void error(char *text)\r
246 {\r
247   MessageBox(FrameWnd, text, "Error", 0);\r
248 }\r
249 \r