Files
openroller/tools/idmac_shim.c
T
tsuki 831d96e562 Initial public source release
Split reusable rendering and format support into vectorail-core and vectorail-gc.
2026-08-02 17:05:27 +02:00

235 lines
6.0 KiB
C

typedef unsigned int u32;
typedef unsigned char u8;
typedef int i32;
__declspec(dllimport) void *__stdcall CreateFileA(const char *name, u32 access, u32 share,
void *security, u32 creation,
u32 flags, void *template_file);
__declspec(dllimport) u32 __stdcall SetFilePointer(void *file, i32 distance,
i32 *distance_high, u32 method);
__declspec(dllimport) int __stdcall WriteFile(void *file, const void *buffer, u32 bytes,
u32 *written, void *overlapped);
__declspec(dllimport) int __stdcall CloseHandle(void *object);
#define GENERIC_WRITE 0x40000000u
#define FILE_SHARE_READ_WRITE 0x00000003u
#define OPEN_ALWAYS 4u
#define FILE_ATTRIBUTE_NORMAL 0x00000080u
#define FILE_END 2u
#define INVALID_HANDLE_VALUE ((void *)-1)
static u32 g_handle = 0x49444d43u; /* "IDMC" */
static u32 g_status = 0;
static u32 g_regs[0x2000] = {
[0x4150 >> 2] = 0x0000825cu,
[0x4140 >> 2] = 0x80000004u,
[0x41a4 >> 2] = 0x80000005u,
};
static u8 g_buffer[0x8000];
static u32 g_log_count;
static char *append_char(char *p, char c)
{
*p++ = c;
return p;
}
static char *append_text(char *p, const char *s)
{
while (*s) {
*p++ = *s++;
}
return p;
}
static char *append_hex(char *p, u32 value)
{
static const char digits[] = "0123456789abcdef";
int i;
p = append_text(p, "0x");
for (i = 7; i >= 0; --i) {
*p++ = digits[(value >> (i * 4)) & 0xf];
}
return p;
}
static void log3(const char *name, u32 a, u32 b, u32 c)
{
char line[160];
char *p;
u32 written;
void *file;
if (g_log_count++ > 20000) {
return;
}
p = line;
p = append_text(p, name);
p = append_char(p, '(');
p = append_hex(p, a);
p = append_text(p, ", ");
p = append_hex(p, b);
p = append_text(p, ", ");
p = append_hex(p, c);
p = append_text(p, ")\r\n");
file = CreateFileA("Z:\\tmp\\idmac_shim.log", GENERIC_WRITE, FILE_SHARE_READ_WRITE,
0, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
if (file == INVALID_HANDLE_VALUE) {
return;
}
SetFilePointer(file, 0, 0, FILE_END);
WriteFile(file, line, (u32)(p - line), &written, 0);
CloseHandle(file);
}
static u32 load_le32(const void *ptr)
{
const u8 *p = (const u8 *)ptr;
return ((u32)p[0]) | ((u32)p[1] << 8) | ((u32)p[2] << 16) | ((u32)p[3] << 24);
}
int __attribute__((stdcall)) DllMain(void *module, unsigned long reason, void *reserved)
{
(void)module;
(void)reason;
(void)reserved;
return 1;
}
int iDmacDrvOpen(u32 device, u32 *handle_out, u32 *status_out)
{
log3("Open", device, (u32)handle_out, (u32)status_out);
(void)device;
if (handle_out) {
*handle_out = g_handle;
}
if (status_out) {
*status_out = g_status;
}
return 0;
}
int iDmacDrvClose(u32 handle, u32 *status_out)
{
log3("Close", handle, (u32)status_out, 0);
(void)handle;
if (status_out) {
*status_out = g_status;
}
return 0;
}
int iDmacDrvRegisterRead(u32 handle, u32 address, u32 *value_out, u32 *status_out)
{
log3("RegisterRead", handle, address, (u32)value_out);
(void)handle;
if (status_out) {
*status_out = g_status;
}
if (!value_out) {
return 0x57;
}
switch (address) {
case 0x400:
*value_out = 0x01010313u;
break;
case 0x4000:
*value_out = 0x00ff00ffu;
break;
case 0x4004:
*value_out = 0x00ff0000u;
break;
default:
if ((address >> 2) < (sizeof(g_regs) / sizeof(g_regs[0]))) {
*value_out = g_regs[address >> 2];
} else {
*value_out = 0;
}
break;
}
log3("RegisterReadValue", address, *value_out, status_out ? *status_out : 0);
return 0;
}
int iDmacDrvRegisterWrite(u32 handle, u32 address, u32 value, u32 *status_out)
{
log3("RegisterWrite", handle, address, value);
(void)handle;
if (status_out) {
*status_out = g_status;
}
if ((address >> 2) < (sizeof(g_regs) / sizeof(g_regs[0]))) {
g_regs[address >> 2] = value;
}
return 0;
}
int iDmacDrvRegisterBufferRead(u32 handle, u32 address, void *buffer, u32 bytes, u32 *status_out)
{
u32 i;
log3("BufferRead", handle, address, bytes);
(void)handle;
if (status_out) {
*status_out = g_status;
}
if (!buffer) {
return 0x57;
}
if (bytes >= 4) {
log3("BufferReadBefore", address, bytes, load_le32(buffer));
}
for (i = 0; i < bytes; i++) {
((u8 *)buffer)[i] = (address + i < sizeof(g_buffer)) ? g_buffer[address + i] : 0;
}
if (bytes >= 4) {
log3("BufferReadAfter", address, bytes, load_le32(buffer));
}
return 0;
}
int iDmacDrvRegisterBufferWrite(u32 handle, u32 address, const void *buffer, u32 bytes, u32 *status_out)
{
u32 i;
log3("BufferWrite", handle, address, bytes);
(void)handle;
if (status_out) {
*status_out = g_status;
}
if (!buffer) {
return 0x57;
}
if (bytes >= 4) {
log3("BufferWriteData", address, bytes, load_le32(buffer));
}
for (i = 0; i < bytes; i++) {
if (address + i < sizeof(g_buffer)) {
g_buffer[address + i] = ((const u8 *)buffer)[i];
}
}
return 0;
}
int iDmacDrvDmaRead(u32 handle, u32 address, void *buffer, u32 bytes, u32 *status_out)
{
return iDmacDrvRegisterBufferRead(handle, address, buffer, bytes, status_out);
}
int iDmacDrvDmaWrite(u32 handle, u32 address, const void *buffer, u32 bytes, u32 *status_out)
{
return iDmacDrvRegisterBufferWrite(handle, address, buffer, bytes, status_out);
}
int iDmacDrvProgramDownload(u32 handle, u32 command, u32 *status_out)
{
log3("ProgramDownload", handle, command, (u32)status_out);
(void)handle;
(void)command;
if (status_out) {
*status_out = g_status;
}
return 0;
}