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; }