int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { RECT rc; int nWidth; int nHeight; HWND hWndTS = FindTSWindow(); if(hWndTS != NULL) { GetWindowRect(hWndTS, &rc); nWidth = rc.right - rc.left; nHeight = rc.bottom - rc.top; } else { ExitProcess(0); } bool bUseJoystick = true; int nArgCount; LPSTR *pArgList; pArgList = CommandLineToArgvA(GetCommandLine(), &nArgCount); for (int i = 0; i < nArgCount; ++i) { if (pArgList[i][0] != '-') continue; if (strcmp(pArgList[i]+1, "j") == 0) bUseJoystick = !bUseJoystick; if (strcmp(pArgList[i]+1, "v") == 0) ToggleDisplaySection(0); if (strcmp(pArgList[i]+1, "f") == 0) ToggleFontOutline(); if (strcmp(pArgList[i]+1, "s") == 0) ToggleSpeedLimitOnly(); if (pArgList[i][1] == 'm') { if (isdigit(pArgList[i][2])) { int nSection = atoi(pArgList[i]+2); if (nSection >= 1 && nSection <= 12) ToggleDisplaySection(nSection); } } if (pArgList[i][1] == 's') { if (isdigit(pArgList[i][2])) { int nSection = atoi(pArgList[i]+2); if (nSection >= 1 && nSection <= 12) ToggleDisplaySection(nSection + 12); } } } margin.cxRightWidth = nWidth; margin.cyBottomHeight = nHeight; WNDCLASSEX wc; ZeroMemory(&wc, sizeof(WNDCLASSEX)); wc.cbSize = sizeof(WNDCLASSEX); wc.style = CS_HREDRAW | CS_VREDRAW; wc.lpfnWndProc = WindowProc; wc.hInstance = hInstance; wc.hCursor = LoadCursor(NULL, IDC_ARROW); wc.hbrBackground = (HBRUSH)RGB(0,0,0); wc.lpszClassName = "WindowClass"; RegisterClassEx(&wc); hWnd = CreateWindowEx(0, "WindowClass", "TrainSim Helper", WS_EX_TOPMOST | WS_POPUP, rc.left, rc.top, nWidth, nHeight, NULL, NULL, hInstance, NULL); SetWindowLong(hWnd, GWL_EXSTYLE,(int)GetWindowLong(hWnd, GWL_EXSTYLE) | WS_EX_LAYERED |WS_EX_TRANSPARENT); SetLayeredWindowAttributes(hWnd, RGB(0,0,0), 255, ULW_COLORKEY | LWA_ALPHA); ShowWindow(hWnd, nCmdShow); InitD3D(hWnd, nWidth, nHeight); MSG msg; ::SetWindowPos(hWndTS, HWND_NOTOPMOST,0,0,0,0,SWP_NOMOVE|SWP_NOSIZE); // V for the whole overlay RegisterHotKey(hWnd, 0, MOD_SHIFT | MOD_ALT, 0x56 /* V key */); // F1-F12 for the main overlay for (int i = 1; i <= 12; ++i) RegisterHotKey(hWnd, i, MOD_SHIFT | MOD_ALT, VK_F1 + i - 1); // F1-F12 for the steam overlay for (int i = 13; i <= 24; ++i) RegisterHotKey(hWnd, i, MOD_SHIFT | MOD_CONTROL, VK_F1 + i - 13); // 0-9 digits for the countdown for (int i = 100; i <= 109; ++i) RegisterHotKey(hWnd, i, MOD_SHIFT | MOD_ALT, 0x30 + i - 100); // R for the countdown reset RegisterHotKey(hWnd, 110, MOD_SHIFT | MOD_ALT, 0x52 /* R key */); // D for driving direction RegisterHotKey(hWnd, 201, MOD_SHIFT | MOD_ALT, 0x44 /* D key */); // F for font outline RegisterHotKey(hWnd, 202, MOD_SHIFT | MOD_ALT, 0x46 /* F key */); // S for speed limit only RegisterHotKey(hWnd, 203, MOD_SHIFT | MOD_ALT, 0x53 /* S key */); if (bUseJoystick) if (FAILED(InitDirectInput())) ExitProcess(0); bool fDone = false; while(!fDone) { hWndTS = FindTSWindow(); if (!hWndTS) { msg.wParam = 0; break; } RECT rcNew; GetWindowRect(hWndTS, &rcNew); if (rcNew.left != rc.left || rcNew.top != rc.top) { rc = rcNew; MoveWindow(hWnd, rc.left, rc.top, nWidth, nHeight, FALSE); } ::SetWindowPos(hWnd, HWND_TOPMOST,0,0,0,0,SWP_NOMOVE|SWP_NOSIZE); Sleep(10); RenderOverlay(); if (bUseJoystick) UpdateJoystick(); while(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { TranslateMessage(&msg); DispatchMessage(&msg); switch(msg.message) { case WM_QUIT: fDone = true; break; } } } if (bUseJoystick) FreeDirectInput(); return msg.wParam; }
int main (int argc, char *argv[]) { int i, Sense; long lj; char s[513]; GetParameters (ControllerNumber); Roll.CurrentAdjustedReading = 0; Roll.LastRawReading = 0; Pitch.CurrentAdjustedReading = 0; Pitch.LastRawReading = 0; Yaw.CurrentAdjustedReading = 0; Yaw.LastRawReading = 0; fprintf (stdout, "yaACA3 Apollo ACA simulation, ver " VER(NVER) ", built " __DATE__ " " __TIME__ "\n"); fprintf (stdout, "Copyright 2009 by Ronald S. Burkey\n"); fprintf (stdout, "Refer to http://www.ibiblio.org/apollo/index.html for more information.\n"); Portnum = 19803; for (i = 1; i < argc; i++) { if (1 == sscanf (argv[i], "--ip=%s", s)) { strcpy (NonDefaultHostname, s); Hostname = NonDefaultHostname; } else if (1 == sscanf (argv[i], "--port=%ld", &lj)) { Portnum = lj; if (Portnum <= 0 || Portnum >= 0x10000) { fprintf (stdout, "The --port switch is out of range. Must be 1-64K.\n"); goto Help; } } else if (1 == sscanf (argv[i], "--delay=%ld", &lj)) { StartupDelay = lj; } else if (1 == sscanf (argv[i], "--controller=%ld", &lj)) { if (lj < 0 || lj > 1) { fprintf (stdout, "Only --controller=0 and --controller=1 are allowed.\n"); goto Help; } else ControllerNumber = lj; } else if (1 == sscanf (argv[i], "--pitch=-%ld", &lj)) { Pitch.PositiveSense = 0; Pitch.Axis = lj; CfgExisted = 0; } else if (1 == sscanf (argv[i], "--pitch=+%ld", &lj) || 1 == sscanf (argv[i], "--pitch=%ld", &lj)) { Pitch.PositiveSense = 1; Pitch.Axis = lj; CfgExisted = 0; } else if (1 == sscanf (argv[i], "--roll=-%ld", &lj)) { Roll.PositiveSense = 0; Roll.Axis = lj; CfgExisted = 0; } else if (1 == sscanf (argv[i], "--roll=+%ld", &lj) || 1 == sscanf (argv[i], "--roll=%ld", &lj)) { Roll.PositiveSense = 1; Roll.Axis = lj; CfgExisted = 0; } else if (1 == sscanf (argv[i], "--yaw=-%ld", &lj)) { Yaw.PositiveSense = 0; Yaw.Axis = lj; CfgExisted = 0; } else if (1 == sscanf (argv[i], "--yaw=+%ld", &lj) || 1 == sscanf (argv[i], "--yaw=%ld", &lj)) { Yaw.PositiveSense = 1; Yaw.Axis = lj; CfgExisted = 0; } else { Help: fprintf (stdout, "USAGE:\n"); fprintf (stdout, "\tyaACA3 [OPTIONS]\n"); fprintf (stdout, "The available options are:\n"); fprintf (stdout, "--ip=Hostname\n"); fprintf (stdout, "\tThe yaACA2 program and the yaAGC Apollo Guidance Computer simulation\n"); fprintf (stdout, "\texist in a \"client/server\" relationship, in which the yaACA2 program\n"); fprintf (stdout, "\tneeds to be aware of the IP address or symbolic name of the host \n"); fprintf (stdout, "\tcomputer running the yaAGC program. By default, this is \"localhost\",\n"); fprintf (stdout, "\tmeaning that both yaACA2 and yaAGC are running on the same computer.\n"); fprintf (stdout, "--port=Portnumber\n"); fprintf (stdout, "\tBy default, yaACA2 attempts to connect to the yaAGC program using port\n"); fprintf (stdout, "\tnumber %d. However, if more than one instance of yaACA2 is being\n", Portnum); fprintf (stdout, "\trun, or if yaAGC has been configured to listen on different ports, then\n"); fprintf (stdout, "\tdifferent port settings for yaACA2 are needed. Note that by default,\n"); fprintf (stdout, "\tyaAGC listens for new connections on ports %d-%d.\n", 19697, 19697 + 10 - 1); fprintf (stdout, "--delay=N\n"); fprintf (stdout, "\t\"Start-up delay\", in ms. Defaults to %d. What the start-up\n", StartupDelay); fprintf (stdout, "\tdelay does is to prevent yaACA2 from attempting to communicate with\n"); fprintf (stdout, "\tyaAGC for a brief time after power-up. This option is really only\n"); fprintf (stdout, "\tuseful in Win32, to work around a problem with race-conditions at\n"); fprintf (stdout, "\tstart-up.\n"); fprintf (stdout, "--roll=N\n"); fprintf (stdout, "--pitch=N\n"); fprintf (stdout, "--yaw=N\n"); fprintf (stdout, "\tThese options allow you to relate the axis numbers (0, 1, ...) by\n"); fprintf (stdout, "\twhich the joystick controller works to physical axes (pitch, roll,\n"); fprintf (stdout, "\tyaw) by which the spacecraft works. In almost all cases --roll=0\n"); fprintf (stdout, "\tand --pitch=1 (the defaultswill be correct, but the --yaw=N setting\n"); fprintf (stdout, "\tvaries from target platform to target platform, and joystick model\n"); fprintf (stdout, "\tto joystick model. Once you use these command-line switches once,\n"); fprintf (stdout, "\tthe settings are saved to a configuration file and you don't have\n"); fprintf (stdout, "\tto use them again. The axis-number N can optionally be preceded by\n"); fprintf (stdout, "\ta \'-\' to indicate that the sense of the axis is reversed from the\n"); fprintf (stdout, "\tdefault expectation. For example, if axis 5 was used for yaw, but\n"); fprintf (stdout, "\tyou found you were getting yaw left where you expected yaw-right, you\n"); fprintf (stdout, "\tshould use--yaw=-5 rather than --yaw=5.\n"); fprintf (stdout, "--controller=N\n"); fprintf (stdout, "\tIn case there are two joystick controllers attached, this allows\n"); fprintf (stdout, "\tselection of just one of them. The default is N=0, but N=1 is also\n"); fprintf (stdout, "\tallowed. If there are more than two attached, only the first two can\n"); fprintf (stdout, "\tbe accessed.\n"); return (1); } } if (!CfgExisted) WriteParameters (ControllerNumber); // Now we start polling the joystick from time to time. The way Allegro works is to // maintain an array containing info on each joystick. This array is updated only when // poll_joystick is called (which you have to do explicitly). To see what has changed, // we maintain a copy of the joy[] array. while (1) { // Sleep for a while so that this job won't monopolize CPU cycles. #ifdef WIN32 Sleep (UPDATE_INTERVAL); #else // WIN32 struct timespec req, rem; req.tv_sec = 0; req.tv_nsec = 1000000 * UPDATE_INTERVAL; nanosleep (&req, &rem); #endif // WIN32 ServiceJoystick_sdl (); // Get joystick physical values. if (Initialization >= 2) { UpdateJoystick (); // Translate physical to logical values. PrintJoy (); // Display them locally. } PulseACA (); // Manage server connection. } #ifndef SOLARIS return (0); #endif }