00001
00007 #define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
00008
00009 #include <windows.h>
00010 #include <stdlib.h>
00011 #include <malloc.h>
00012 #include <memory.h>
00013 #include <tchar.h>
00014 #include <commdlg.h>
00015 #include <commctrl.h>
00016 #include <stdio.h>
00017
00018
00019 #include "emu6502.h"
00020 #define MAX_LOADSTRING 512
00021 #define CR 13
00022 #define LF 10
00023
00025 HINSTANCE hInst;
00027 HWND hMainWnd;
00029 HWND hToolBar;
00030
00032 DllMsgList* DMList = NULL;
00034 PtrList* DHInstList = NULL;
00035
00036
00037 TCHAR szTitle[MAX_LOADSTRING];
00038 TCHAR szWindowClass[MAX_LOADSTRING];
00039
00040
00041 int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
00042 LPSTR lpCmdLine, int nCmdShow)
00043 {
00044 MSG msg;
00045 int gotMsg = FALSE;
00046 BOOL run = TRUE;
00047 int i = 0;
00048
00049 LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
00050 LoadString(hInstance, IDC_EMU6502, szWindowClass, MAX_LOADSTRING);
00051 MyRegisterClass(hInstance);
00052
00053 InitMem();
00054
00055 if (!InitInstance(hInstance, nCmdShow)) {
00056 return FALSE;
00057 }
00058
00059
00060 while (GetMessage(&msg, NULL, 0, 0)) {
00061 TranslateMessage(&msg);
00062 DispatchMessage(&msg);
00063 }
00064
00065 return msg.wParam;
00066 }
00067
00068
00069 ATOM MyRegisterClass(HINSTANCE hInstance)
00070 {
00071 WNDCLASSEX wcex;
00072
00073 wcex.cbSize = sizeof(WNDCLASSEX);
00074
00075 wcex.style = CS_HREDRAW | CS_VREDRAW;
00076 wcex.lpfnWndProc = (WNDPROC)WndProc;
00077 wcex.cbClsExtra = 0;
00078 wcex.cbWndExtra = 0;
00079 wcex.hInstance = hInstance;
00080 wcex.hIcon = LoadIcon(hInstance, (LPCTSTR)IDI_EMU6502);
00081 wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
00082 wcex.hbrBackground = (HBRUSH)(COLOR_BTNFACE+1);
00083 wcex.lpszMenuName = (LPCSTR)IDC_EMU6502;
00084 wcex.lpszClassName = szWindowClass;
00085 wcex.hIconSm = LoadIcon(wcex.hInstance, (LPCTSTR)IDI_SMALL);
00086
00087 return RegisterClassEx(&wcex);
00088 }
00089
00090
00091 BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
00092 {
00093 RECT rc, rcToolB;
00094
00095 hInst = hInstance;
00096
00097 hMainWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX,
00098 0, 0, 0, 0, NULL, NULL, hInstance, NULL);
00099
00100 if (!hMainWnd) {
00101 return FALSE;
00102 }
00103
00104 rc.top = GetSystemMetrics(SM_CYSCREEN) / 2 - 138;
00105 rc.left = GetSystemMetrics(SM_CXSCREEN) / 2 - 128;
00106 rc.right = GetSystemMetrics(SM_CXSCREEN) / 2 + 127;
00107 rc.bottom = GetSystemMetrics(SM_CYSCREEN) / 2 + 117;
00108 AdjustWindowRect(&rc, WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX, TRUE);
00109
00110 hToolBar = CreateToolBar(hMainWnd);
00111
00112 GetWindowRect(hToolBar, &rcToolB);
00113 rc.bottom += rcToolB.bottom - rcToolB.top;
00114
00115 SetWindowPos(hMainWnd, HWND_TOP, rc.left, rc.top,
00116 rc.right - rc.left + 1, rc.bottom - rc.top + 1, SWP_NOZORDER);
00117 SendMessage(hToolBar, TB_AUTOSIZE, 0, 0);
00118
00119 LoadPlugins(&DMList, &DHInstList);
00120
00121 ShowWindow(hMainWnd, nCmdShow);
00122 UpdateWindow(hMainWnd);
00123
00124 return TRUE;
00125 }
00126
00127 HWND CreateToolBar(HWND hParentWnd)
00128 {
00129 HWND hTb;
00130 TBBUTTON TBtns[3];
00131 INITCOMMONCONTROLSEX iccs;
00132
00133 iccs.dwSize = sizeof(INITCOMMONCONTROLSEX);
00134 iccs.dwICC = ICC_BAR_CLASSES;
00135
00136 if (!InitCommonControlsEx(&iccs)) {
00137 return NULL;
00138 }
00139
00140 ZeroMemory(&TBtns, sizeof(TBBUTTON) * 1);
00141 TBtns[0].fsState = TBSTATE_ENABLED;
00142 TBtns[0].fsStyle = TBSTYLE_BUTTON | TBSTYLE_AUTOSIZE ;
00143 TBtns[0].iBitmap = 0;
00144 TBtns[0].idCommand = IDM_FILE_LOADMEMORYFILE;
00145
00147 hTb = CreateToolbarEx(hParentWnd, WS_CHILD | TBSTYLE_FLAT,
00148 0, 1, hInst, IDR_TOOLBAR, TBtns, 1, 16, 16, 16, 16, sizeof(TBBUTTON));
00149
00150 ShowWindow(hTb, SW_SHOW);
00151 return hTb;
00152 }
00153
00154
00155 LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
00156 {
00157 int wmId, wmEvent;
00158 BOOL MsgProcessed;
00159
00160
00161 MsgProcessed = ForwardDllMessage(message, wParam, lParam, DMList);
00162
00163 switch (message)
00164 {
00165 case WM_COMMAND:
00166 wmId = LOWORD(wParam);
00167 wmEvent = HIWORD(wParam);
00168
00169 switch (wmId)
00170 {
00171 case IDM_ABOUT:
00172 DialogBox(hInst, (LPCTSTR)IDD_ABOUTBOX, hWnd, (DLGPROC)About);
00173 break;
00174 case IDM_EXIT:
00175 DestroyWindow(hWnd);
00176 break;
00177 case IDM_FILE_LOADMEMORYFILE:
00178 LoadMemFile(hWnd);
00179 break;
00180 default:
00181 if (MsgProcessed == FALSE) {
00182 return DefWindowProc(hWnd, message, wParam, lParam);
00183 }
00184 }
00185 break;
00186 case WM_DESTROY:
00187 UnloadPlugins(DHInstList);
00188 PostQuitMessage(0);
00189 break;
00190 default:
00191 if (MsgProcessed == FALSE) {
00192 return DefWindowProc(hWnd, message, wParam, lParam);
00193 }
00194 }
00195 return 0;
00196 }
00197
00198 LRESULT CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
00199 {
00200 switch (message)
00201 {
00202 case WM_INITDIALOG:
00203 return TRUE;
00204
00205 case WM_COMMAND:
00206 if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
00207 {
00208 EndDialog(hDlg, LOWORD(wParam));
00209 return TRUE;
00210 }
00211 break;
00212 }
00213 return FALSE;
00214 }
00215
00216 BOOL LoadMemFile(HWND hWnd)
00217 {
00218 OPENFILENAME ofn;
00219 TCHAR FileName[_MAX_PATH];
00220 HANDLE hFile;
00221 DWORD dwSize;
00222 DWORD dwRead;
00223
00224
00225 SendMessage(hWnd, PAUSECPU, 0, 0);
00226 SendMessage(hWnd, WAITEND, 0, 0);
00227
00228 lstrcpy(FileName, "");
00229 ZeroMemory(&ofn, sizeof(OPENFILENAME));
00230
00231 ofn.lStructSize = sizeof(OPENFILENAME);
00232 ofn.lpstrFile = FileName;
00233 ofn.hwndOwner = hWnd;
00234 ofn.nMaxFile = sizeof(FileName);
00235 ofn.lpstrFilter =
00236 TEXT("Memory image files (*.img)\0*.img\0All Files (*.*)\0*.*\0");
00237 ofn.nFilterIndex = 1;
00238 ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST;
00239
00240 if (!GetOpenFileName(&ofn))
00241 return FALSE;
00242
00243
00244 hFile=CreateFile((LPCSTR) FileName, GENERIC_READ, 0,NULL, OPEN_EXISTING, 0, NULL);
00245 if (hFile==INVALID_HANDLE_VALUE) {
00246 error(hWnd, IDS_EOPEN, NULL);
00247 return FALSE;
00248 }
00249
00250 dwSize=GetFileSize(hFile, NULL);
00251 if(dwSize!=MEMSIZE) {
00252 error(hWnd, IDS_ECORRUPT, NULL);
00253 return FALSE;
00254 }
00255
00256 SendMessage(hWnd, STOPVIDEO, 0, 0);
00257
00258 if (!ReadFile(hFile, &memory, dwSize, &dwRead, NULL) ) {
00259 CloseHandle(hFile);
00260 error(hWnd, IDS_EREAD, NULL);
00261 return FALSE;
00262 }
00263 SendMessage(hWnd, RESETMSG, 0, 0);
00264 CloseHandle(hFile);
00265 return TRUE;
00266 }
00267
00268 void error(HWND hWnd, UINT uID, TCHAR* name)
00269 {
00270 TCHAR msg[MAX_LOADSTRING];
00271 TCHAR out[MAX_LOADSTRING];
00272 LoadString(hInst, uID, msg, MAX_LOADSTRING);
00273 _stprintf(out, msg, name);
00274 MessageBox(hWnd, out, "Error", MB_OK | MB_ICONERROR | MB_DEFBUTTON1);
00275 }
00276
00277 BOOL ForwardDllMessage(UINT message, WPARAM wParam, LPARAM lParam, DllMsgList* actlist)
00278 {
00279 PtrList* actnode;
00280 MESSAGEDLLSTRUCT mds;
00281
00282 actlist = DMList;
00283 while (actlist != NULL && actlist->MesgID != message) {
00284 actlist = actlist->next;
00285 }
00286 if (actlist == NULL) {
00287 return FALSE;
00288 }
00289
00290 mds.lParam = lParam;
00291 mds.wParam = wParam;
00292 mds.message = message;
00293
00294 actnode = actlist->Functions;
00295
00296 while (actnode != NULL) {
00297 ((pForwardDllMsgProc) actnode->ptr)(&mds);
00298 actnode = actnode->next;
00299 }
00300 return TRUE;
00301 }
00302
00303 void LoadPlugins(DllMsgList** list, PtrList** InstList)
00304 {
00305 HANDLE hFile;
00306 TCHAR buf[65536];
00307 TCHAR* str;
00308 TCHAR* param;
00309 DWORD dwRead;
00310
00311 hFile = CreateFile("plugins.txt", GENERIC_READ, FILE_SHARE_READ,
00312 NULL, OPEN_EXISTING, 0, NULL);
00313 if (hFile == INVALID_HANDLE_VALUE) {
00314 error(hMainWnd, IDS_EPLUGINSTXT, NULL);
00315 return;
00316 }
00317
00318 if (!ReadFile(hFile, buf, 65536, &dwRead, NULL)) {
00319 error(hMainWnd, IDS_EPLUGINSTXT, NULL);
00320 return;
00321 }
00322 buf[dwRead] = '\0';
00323
00324 param = (TCHAR*) buf;
00325 while((str = GetNextStrToken(¶m)) != NULL) {
00326 if (LoadPlugin(str, list, InstList) == FALSE) {
00327 error(hMainWnd, IDS_EPLUGIN, str);
00328 }
00329 }
00330
00331 CloseHandle(hFile);
00332 }
00333
00334 BOOL LoadPlugin(TCHAR* name, DllMsgList** list, PtrList** InstList)
00335 {
00336 HINSTANCE hInstLib;
00337 pInitDllProc IDProc;
00338 pForwardDllMsgProc FDMProc;
00339 pIOFunc IOFunc;
00340 INITDLLSTRUCT ids;
00341 INITDLLINFO idi;
00342 RECT rcT, rcC;
00343 int i;
00344
00345
00346 hInstLib = LoadLibrary(name);
00347 if (hInstLib == NULL) {
00348 error(hMainWnd, IDS_EOPEN, NULL);
00349 return FALSE;
00350 }
00351
00352
00353 IDProc = (pInitDllProc) GetProcAddress(hInstLib, "InitDll");
00354 FDMProc = (pForwardDllMsgProc) GetProcAddress(hInstLib, "OnMessage");
00355 IOFunc = (pIOFunc) GetProcAddress(hInstLib, "IOFunc");
00356
00357
00358 AddToPtrList((void*) hInstLib, InstList);
00359
00360
00361 ids.hInst = hInst;
00362 ids.hWnd = hMainWnd;
00363 ids.hTb = hToolBar;
00364 ids.memory = memory;
00365 ids.optional = NULL;
00366 ids.CSMemory = CSMemory;
00367 ids.memgetb = &memgetb;
00368 ids.memsetb = &memsetb;
00369 GetClientRect(hMainWnd, &rcC);
00370 GetWindowRect(hToolBar, &rcT);
00371 rcC.top += rcT.bottom - rcT.top;
00372 ids.rcPaint = rcC;
00373
00374
00375
00376
00377 (IDProc) (&ids, &idi);
00378
00379
00380 if (idi.msglist != NULL) {
00381 for (i=0; idi.msglist[i]!=ENDOFMSGLIST; i++) {
00382 AddDllMsg(list, idi.msglist[i], FDMProc);
00383 }
00384 }
00385
00386
00387 if (idi.iolo !=0 && idi.iohi != 0) {
00388 if (IOFunc == NULL) {
00389 error(hMainWnd, IDS_EIOFNOTFOUND, name);
00390 }
00391 else {
00392 SetIOFunc(IOFunc, idi.iolo, idi.iohi);
00393 }
00394 }
00395
00396 return TRUE;
00397 }
00398
00399 void AddDllMsg(DllMsgList** list, UINT message,
00400 pForwardDllMsgProc FDMProc)
00401 {
00402 DllMsgList* newlist;
00403 DllMsgList* prev = NULL;
00404 DllMsgList* actlist = *list;
00405
00406 while (actlist != NULL && actlist->MesgID != message) {
00407 prev = actlist;
00408 actlist = actlist->next;
00409 }
00410
00411 if (actlist == NULL) {
00412 newlist = (DllMsgList*) malloc(sizeof(DllMsgList));
00413 newlist->MesgID = message;
00414 newlist->Functions = NULL;
00415 newlist->next = NULL;
00416 AddToPtrList((void*) FDMProc, &newlist->Functions);
00417
00418 if (prev == NULL) {
00419 *list = newlist;
00420 return;
00421 }
00422 else {
00423
00424 prev->next = newlist;
00425 return;
00426 }
00427 }
00428
00429
00430 AddToPtrList((void*) FDMProc, &actlist->Functions);
00431 return;
00432 }
00433
00434 void UnloadPlugins(PtrList* list)
00435 {
00436 PtrList* p = list;
00437 while (p != NULL) {
00438 FreeLibrary((HINSTANCE) list->ptr);
00439 p = list->next;
00440 free(list);
00441 list = p;
00442 }
00443 }
00444
00445
00446 void AddToPtrList(void* ptr, PtrList** list)
00447 {
00448 PtrList* node = (PtrList*) malloc(sizeof(PtrList));
00449 node->ptr = ptr;
00450 node->next = *list;
00451 *list = node;
00452 }
00453
00454 TCHAR* GetNextStrToken(TCHAR** buf)
00455 {
00456 TCHAR* start = *buf;
00457
00458 if (*buf == NULL || **buf == '\0' || **buf == CR || **buf == LF) {
00459 return NULL;
00460 }
00461
00462 while (**buf != CR && **buf != '\0') {
00463 (*buf)++;
00464 }
00465
00466 if (**buf == CR) {
00467 **buf = '\0';
00468 (*buf)++;
00469 if (**buf == LF) {
00470 (*buf)++;
00471 }
00472 }
00473 return start;
00474 }
00475
00476
00477
00478