Let us start here, from square one. No, from Zero!
This commit is contained in:
@@ -0,0 +1,158 @@
|
||||
#include "gunio.h"
|
||||
#include "util/logging.h"
|
||||
|
||||
bool games::mga::SpiceGearGunHandle::open(LPCWSTR lpFileName) {
|
||||
if (wcscmp(lpFileName, L"COM1") != 0) {
|
||||
return false;
|
||||
}
|
||||
log_info("metalgear", "Opened gun device on COM1");
|
||||
return true;
|
||||
}
|
||||
|
||||
int games::mga::SpiceGearGunHandle::read(LPVOID lpBuffer, DWORD nNumberOfBytesToRead) {
|
||||
|
||||
// minimum buffer size
|
||||
if ((command == 0u) || nNumberOfBytesToRead < 2)
|
||||
return 0;
|
||||
|
||||
// execute command
|
||||
int bytes_read = 0;
|
||||
switch (command) {
|
||||
case 0x04: // get version
|
||||
|
||||
// write version
|
||||
*((unsigned char *) lpBuffer + bytes_read++) = version;
|
||||
|
||||
break;
|
||||
case 0x08: // get input state
|
||||
{
|
||||
// check buffer size
|
||||
if (nNumberOfBytesToRead < 12)
|
||||
return 0;
|
||||
|
||||
// get cursor position
|
||||
POINT cursor_pos{};
|
||||
GetCursorPos(&cursor_pos);
|
||||
|
||||
// get screen size
|
||||
RECT screen_size{};
|
||||
GetWindowRect(GetDesktopWindow(), &screen_size);
|
||||
auto screen_width = (unsigned short) (screen_size.right - screen_size.left);
|
||||
auto screen_height = (unsigned short) (screen_size.bottom - screen_size.top);
|
||||
|
||||
// calculate cursor position
|
||||
p1_x = (unsigned short) (((cursor_pos.x * 1024) / screen_width) % 1024);
|
||||
p1_y = (unsigned short) (1024 - (((cursor_pos.y * 1024) / screen_height) % 1024));
|
||||
|
||||
// gun P1
|
||||
*((unsigned char *) lpBuffer + bytes_read++) = 0x00;
|
||||
*((unsigned char *) lpBuffer + bytes_read++) = HIBYTE(p1_x);
|
||||
*((unsigned char *) lpBuffer + bytes_read++) = LOBYTE(p1_x);
|
||||
*((unsigned char *) lpBuffer + bytes_read++) = HIBYTE(p1_y);
|
||||
*((unsigned char *) lpBuffer + bytes_read++) = LOBYTE(p1_y);
|
||||
bytes_read += 3;
|
||||
|
||||
// fill buffer
|
||||
*((unsigned char *) lpBuffer + bytes_read++) = 0x75;
|
||||
*((unsigned char *) lpBuffer + bytes_read++) = 0x75;
|
||||
*((unsigned char *) lpBuffer + bytes_read++) = 0x75;
|
||||
|
||||
break;
|
||||
}
|
||||
case 0x0C: // not called in game - empty
|
||||
|
||||
// empty data
|
||||
*((unsigned char *) lpBuffer + bytes_read++) = 0x00;
|
||||
|
||||
break;
|
||||
case 0x10: // get DIP switches
|
||||
|
||||
// clear bits
|
||||
*((unsigned char *) lpBuffer + bytes_read) = 0x00;
|
||||
|
||||
// set bits
|
||||
if (frequency == 1)
|
||||
*((unsigned char *) lpBuffer + bytes_read) |= 0x80;
|
||||
if (frequency == 2)
|
||||
*((unsigned char *) lpBuffer + bytes_read) |= 0x40;
|
||||
if (frequency == 3)
|
||||
*((unsigned char *) lpBuffer + bytes_read) |= 0x20;
|
||||
if (frequency == 4)
|
||||
*((unsigned char *) lpBuffer + bytes_read) |= 0x10;
|
||||
|
||||
break;
|
||||
case 0x14: // frequency 1
|
||||
|
||||
// set frequency and return empty data
|
||||
frequency = 1;
|
||||
*((unsigned char *) lpBuffer + bytes_read++) = 0x00;
|
||||
|
||||
break;
|
||||
case 0x18: // frequency 2
|
||||
|
||||
// set frequency and return empty data
|
||||
frequency = 2;
|
||||
*((unsigned char *) lpBuffer + bytes_read++) = 0x00;
|
||||
|
||||
break;
|
||||
case 0x19: // frequency 3
|
||||
|
||||
// set frequency and return empty data
|
||||
frequency = 3;
|
||||
*((unsigned char *) lpBuffer + bytes_read++) = 0x00;
|
||||
|
||||
break;
|
||||
case 0x1A: // frequency 4
|
||||
|
||||
// set frequency and return empty data
|
||||
frequency = 4;
|
||||
*((unsigned char *) lpBuffer + bytes_read++) = 0x00;
|
||||
|
||||
break;
|
||||
case 0x1C: // led board check
|
||||
|
||||
// check buffer size
|
||||
if (nNumberOfBytesToRead < 11)
|
||||
return 0;
|
||||
|
||||
// set all bits
|
||||
memset(lpBuffer, 0xFF, 10);
|
||||
bytes_read += 10;
|
||||
|
||||
break;
|
||||
default:
|
||||
log_warning("metalgear", "unknown opcode: 0x{:02X}", command);
|
||||
*((unsigned char *) lpBuffer + bytes_read++) = 0x01;
|
||||
}
|
||||
|
||||
// reset command
|
||||
command = 0;
|
||||
|
||||
// calculate checksum
|
||||
unsigned char checksum = 0xFF;
|
||||
for (int i = 0; i < bytes_read; i++)
|
||||
checksum -= *((unsigned char *) lpBuffer + i);
|
||||
*((unsigned char *) lpBuffer + bytes_read++) = checksum;
|
||||
|
||||
// return amount of bytes read
|
||||
return bytes_read;
|
||||
}
|
||||
|
||||
int games::mga::SpiceGearGunHandle::write(LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite) {
|
||||
|
||||
// save command
|
||||
if (nNumberOfBytesToWrite > 0)
|
||||
command = *((unsigned char *) lpBuffer);
|
||||
|
||||
return (int) nNumberOfBytesToWrite;
|
||||
}
|
||||
|
||||
int games::mga::SpiceGearGunHandle::device_io(DWORD dwIoControlCode, LPVOID lpInBuffer, DWORD nInBufferSize,
|
||||
LPVOID lpOutBuffer, DWORD nOutBufferSize) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool games::mga::SpiceGearGunHandle::close() {
|
||||
log_info("metalgear", "Closed gun device on COM1");
|
||||
return true;
|
||||
}
|
||||
Reference in New Issue
Block a user