├── tools └── inject │ ├── .gitignore │ ├── makefile │ ├── README.md │ └── inject.c ├── bin └── .gitignore ├── debugger.png ├── run.sh ├── games ├── .gitignore └── README.md ├── src ├── debug.h ├── utf.h ├── sjis.h ├── debug.c ├── utf.c ├── op_sys0.c ├── patch.h ├── disassembler.c ├── bgi.h ├── disasm_basic.c ├── patch.c ├── bgi.c ├── breakpoints.c ├── gui.c ├── disasm_blank.c ├── disasm_sys0.c └── op_basic.c ├── makefile ├── README.md └── LICENSE /tools/inject/.gitignore: -------------------------------------------------------------------------------- 1 | *.o 2 | *.exe -------------------------------------------------------------------------------- /bin/.gitignore: -------------------------------------------------------------------------------- 1 | *.o 2 | *.tmp 3 | *.bin 4 | *.dll 5 | *.map -------------------------------------------------------------------------------- /debugger.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cytlan/openbgi/HEAD/debugger.png -------------------------------------------------------------------------------- /run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | wine tools/inject/inject.exe games/tayutama/tayutama.exe bin/openbgi.dll 4 | -------------------------------------------------------------------------------- /games/.gitignore: -------------------------------------------------------------------------------- 1 | # Ignore everything 2 | * 3 | 4 | # But not these files... 5 | !.gitignore 6 | !README.md 7 | -------------------------------------------------------------------------------- /games/README.md: -------------------------------------------------------------------------------- 1 | OpenBGI - games/ 2 | ================ 3 | 4 | Place your Ethornell/BGI games here. Everything except this file is `.gitignore`'d, so we won't be commiting anything we're not allowed to. 5 | -------------------------------------------------------------------------------- /src/debug.h: -------------------------------------------------------------------------------- 1 | // 2 | // Debug helper functions 3 | // 4 | 5 | #include 6 | #include 7 | 8 | #ifndef _DEBUG_H_ 9 | #define _DEBUG_H_ 10 | 11 | void Debug_PrintfSJIS(uint16_t* message, uint8_t* str); 12 | 13 | #endif 14 | -------------------------------------------------------------------------------- /src/utf.h: -------------------------------------------------------------------------------- 1 | // 2 | // Unicode helpers 3 | // 4 | 5 | #include 6 | 7 | #ifndef _UTF_H_ 8 | #define _UTF_H_ 9 | 10 | int UTF32ToUTF8(uint32_t in, uint8_t* out); 11 | int UTF16ToUTF8Length(uint16_t codepoint); 12 | int UTF16ToUTF8Strlen(uint16_t* str); 13 | int UTF16ToUTF8(uint16_t* in, uint8_t* out); 14 | 15 | #endif 16 | -------------------------------------------------------------------------------- /src/sjis.h: -------------------------------------------------------------------------------- 1 | // 2 | // SJIS to UTF16 conversion 3 | // 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | #ifndef _SJIS_H_ 10 | #define _SJIS_H_ 11 | 12 | uint16_t SjisToUTF16(uint8_t* in); 13 | bool SjisIsTwobyte(uint8_t* in); 14 | uint16_t SjisGetChar(uint8_t* in, bool* isTwoByte); 15 | 16 | #endif 17 | -------------------------------------------------------------------------------- /tools/inject/makefile: -------------------------------------------------------------------------------- 1 | 2 | TARGET := inject.exe 3 | CC := i686-w64-mingw32-gcc-win32 4 | 5 | CFLAGS := 6 | 7 | # C sources 8 | CSOURCES := inject.c 9 | 10 | # Get object names 11 | OBJS = $(CSOURCES:.c=.o) 12 | 13 | all: $(TARGET) 14 | 15 | $(TARGET): $(OBJS) 16 | $(CC) $(OBJS) -o $(TARGET) 17 | 18 | %.o: %.c 19 | $(CC) $(CFLAGS) -c $< -o $@ 20 | 21 | clean: 22 | rm -f $(TARGET) $(OBJS) 23 | -------------------------------------------------------------------------------- /src/debug.c: -------------------------------------------------------------------------------- 1 | // 2 | // Debug helper functions 3 | // 4 | 5 | #include "debug.h" 6 | #include "sjis.h" 7 | 8 | #define UNICODE_BUF_SIZE 1024 9 | uint16_t unicodeStrBuf[UNICODE_BUF_SIZE]; 10 | 11 | void Debug_PrintfSJIS(uint16_t* message, uint8_t* str) 12 | { 13 | char* ptr = str; 14 | char c = *ptr; 15 | int i = 0; 16 | while(c) 17 | { 18 | c = *ptr; 19 | unicodeStrBuf[i] = SjisToUTF16(ptr); 20 | i++; 21 | if(SjisIsTwobyte(ptr)) 22 | ptr++; 23 | ptr++; 24 | if(i == UNICODE_BUF_SIZE - 1) 25 | break; 26 | } 27 | unicodeStrBuf[i] = 0; 28 | 29 | wprintf(L"%s: %s\n", message, &unicodeStrBuf[0]); 30 | } -------------------------------------------------------------------------------- /tools/inject/README.md: -------------------------------------------------------------------------------- 1 | # Inject 2 | 3 | Inject is a tool which injects an ordered list of shared libraries into the address space of a binary executable. The created process is initially suspended, and resumes execution once the ordered list of shared libraries have been loaded into its address space, and their respective DllMain functions have finished executing. 4 | 5 | ## Usage 6 | 7 | ``` 8 | $ inject EXE [DLL...] 9 | ``` 10 | 11 | ## Examples 12 | 13 | ``` 14 | $ inject a.exe b.dll c.dll 15 | ``` 16 | 17 | Order of execution: 18 | 19 | 1. Create a suspended process of `a.exe`. 20 | 2. Load `b.dll` into the address space of `a.exe`. 21 | 3. Execute the `DllMain` function of `b.dll`. 22 | 4. Load `c.dll` into the address space of `a.exe`. 23 | 5. Execute the `DllMain` function of `d.dll`. 24 | 6. Resume execution of `a.exe`. 25 | 26 | ## Credits 27 | 28 | Inject was greatly inspired by Risc's use of DLL-injection in [diablo-improvements](https://github.com/r1sc/diablo-improvements). 29 | 30 | Original source: https://github.com/mewrev/inject/ 31 | -------------------------------------------------------------------------------- /makefile: -------------------------------------------------------------------------------- 1 | # ------------------------------------------------------------------------------ 2 | # 3 | # Makefile for OpenBGI 4 | # 5 | # ------------------------------------------------------------------------------ 6 | 7 | # Name of the executable 8 | TARGET := openbgi.dll 9 | 10 | # Directories 11 | SRCDIR := src 12 | BUILDDIR := bin 13 | TOOLSDIR := tools 14 | 15 | # Tools 16 | TOOLS := $(TOOLSDIR)/inject 17 | 18 | # C sources 19 | CSOURCES := $(shell find $(SRCDIR) -name '*.c') 20 | 21 | # Additional libraries 22 | LIBRARIES := 23 | 24 | # ------------------------------------------------------------------------------ 25 | # 26 | # Tools 27 | # 28 | # ------------------------------------------------------------------------------ 29 | 30 | # Compile & Link, Compile, Assemble and Link utilities 31 | CC = i686-w64-mingw32-gcc-win32 32 | 33 | # Compiler, assembler and linker options 34 | CFLAGS = -O3 35 | LDFLAGS = -O3 -shared -static-libgcc -lwinmm -lgdi32 36 | 37 | # System utilities 38 | RM = rm -f 39 | 40 | # ------------------------------------------------------------------------------ 41 | # 42 | # Flags and argument finalization 43 | # 44 | # ------------------------------------------------------------------------------ 45 | 46 | # Finalizing flags 47 | CFLAGS += $(patsubst %,-I%,$(INCDIR)) 48 | 49 | # Get object names 50 | OBJS_ = $(CSOURCES:.c=.o) 51 | OBJS = $(patsubst $(SRCDIR)/%,$(BUILDDIR)/%,$(OBJS_)) $(LIBRARIES) 52 | PATHS = $(sort $(dir $(OBJS))) 53 | 54 | # ------------------------------------------------------------------------------ 55 | # 56 | # Targets 57 | # 58 | # ------------------------------------------------------------------------------ 59 | 60 | all: setup $(TOOLS) $(BUILDDIR)/$(TARGET) 61 | 62 | setup: 63 | mkdir -p $(PATHS) 64 | 65 | $(BUILDDIR)/$(TARGET): $(OBJS) 66 | $(CC) $(OBJS) $(LDFLAGS) -o $(BUILDDIR)/$(TARGET) 67 | 68 | $(BUILDDIR)/%.o: $(SRCDIR)/%.c 69 | $(CC) $(CFLAGS) -c -o $@ $< 70 | 71 | $(TOOLS): 72 | echo $@ 73 | $(MAKE) -C $@ 74 | 75 | clean: 76 | $(RM) $(OBJS) $(BUILDDIR)/$(TARGET) 77 | 78 | .PHONY: all setup $(TOOLS) 79 | 80 | # EOF -------------------------------------------------------------------------- -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | OpenBGI 2 | ======= 3 | 4 | This project aims to reverse-engineer the Ethornell Buriko General Interpreter (BGI), and create an open source re-implementation of the engine. 5 | 6 | We now have a Discord server: https://discord.gg/3zFTJWUNt7 7 | 8 | Workflow 9 | -------- 10 | 11 | Currently, the workflow is to use `Ghidra` for analysing the engine, then reimplement opcodes and support functions on a per-opcode basis. 12 | 13 | The strategy is just to implement an opcode, run the game and see if it crashes. It's a pretty crude technique, but it'll work for now. 14 | 15 | Milestones reached: 16 | * Reimplemented enough basic opcodes for Tayutama to run. 17 | 18 | Architecture 19 | ------------ 20 | 21 | While we're still working on reimplementing opcodes, it doesn't make sense to compile a stand-alone program yet. Therefore our strategy is to hook into an existing engine and redirect functions and opcodes to a shared library instead. 22 | 23 | How it works is that we inject a DLL into the game that contains our reimplementation and the debugger. The DLL patches the engine and redirects opcodes to our reimplementations. 24 | 25 | Eventually this method will be retired once our code is developed to the point where it can boot a game on its own. 26 | 27 | Debugger 28 | -------- 29 | 30 | To help reverse-engineering the game, we have created a debugging tool for the engine. After patching the game, the debugger is loaded and allows us to inspect threads, halt the execution and single-step through the program. 31 | 32 | The debugger window will be the very first window that pops up, and the engine will be started in a *halted* state. Hit the `Run` button to start the game. 33 | 34 | ![Screenshot of the debugger as of 2020-11-13](debugger.png) 35 | 36 | Building 37 | -------- 38 | 39 | Despite building a DLL and hooking into a Windows based game, the toolchain currently only supports Linux. 40 | 41 | Before you do anything else, you need to install the various tools and dependencies needed: 42 | ```sh 43 | apt install build-essential g++-mingw-w64-i686 44 | ``` 45 | 46 | Building the DLL is as simple as running: 47 | ```sh 48 | make 49 | ``` 50 | 51 | Finally, run the game with this helper: 52 | ```sh 53 | ./run.sh 54 | ``` 55 | 56 | The only supported game right now is `Tayutama Trial`. 57 | 58 | Contact 59 | ------- 60 | 61 | Feel free to join our Discord server: https://discord.gg/3zFTJWUNt7 62 | -------------------------------------------------------------------------------- /src/utf.c: -------------------------------------------------------------------------------- 1 | // 2 | // Unicode Helpers 3 | // 4 | 5 | #include "utf.h" 6 | 7 | int UTF32ToUTF8(uint32_t in, uint8_t* out) 8 | { 9 | // 0x0000 to 0x007F 10 | if(in < 0x00000080) 11 | { 12 | *out = in & 0xFF; 13 | return 1; 14 | } 15 | // 0x0080 to 0x07FF 16 | else if(in < 0x00000800) 17 | { 18 | *out++ = 0xC0 | ((in >> 6) & 0x1F); 19 | *out = 0x80 | (in & 0x3F); 20 | return 2; 21 | } 22 | // 0x0800 to 0xFFFF 23 | else if(in < 0x00010000) 24 | { 25 | *out++ = 0xE0 | ((in >> 12) & 0x0F); 26 | *out++ = 0x80 | ((in >> 6) & 0x3F); 27 | *out = 0x80 | (in & 0x3F); 28 | return 3; 29 | } 30 | // 0x10000 to 0x10FFFF 31 | else if(in < 0x00110000) 32 | { 33 | *out++ = 0xF0 | ((in >> 18) & 0x07); 34 | *out++ = 0x80 | ((in >> 16) & 0x3F); 35 | *out++ = 0x80 | ((in >> 6) & 0x3F); 36 | *out = 0x80 | (in & 0x3F); 37 | return 4; 38 | } 39 | // Invalid code point 40 | else 41 | return -1; 42 | } 43 | 44 | int UTF16ToUTF8Length(uint16_t codepoint) 45 | { 46 | // Surrogate pairs 47 | if(codepoint >= 0xD800 && codepoint <= 0xDFFF) 48 | return 4; 49 | // 0x0000 to 0x007F 50 | if(codepoint < 0x80) 51 | return 1; 52 | // 0x0080 to 0x07FF 53 | if(codepoint < 0x800) 54 | return 2; 55 | // 0x0800 to 0xFFFF 56 | return 3; 57 | } 58 | 59 | // Count how many bytes are needed to convert a UFT-16 string into UTF-8 60 | int UTF16ToUTF8Strlen(uint16_t* str) 61 | { 62 | int len = 0; 63 | uint16_t* ptr = str; 64 | uint16_t c = *ptr++; 65 | while(c) 66 | { 67 | int uLen = UTF16ToUTF8Length(c); 68 | len += uLen; 69 | 70 | // Skip trailing surrogate 71 | if(uLen == 4) 72 | ptr++; 73 | 74 | c = *ptr++; 75 | } 76 | return len; 77 | } 78 | 79 | // Convert UTF-16 string into UTF-8 80 | int UTF16ToUTF8(uint16_t* in, uint8_t* out) 81 | { 82 | int len = 0; 83 | uint16_t* inPtr = in; 84 | uint8_t* outPtr = out; 85 | uint32_t c = *inPtr++; // UTF-32 intermediate 86 | while(c) 87 | { 88 | int uLen = UTF16ToUTF8Length(c); 89 | 90 | // Decode surrogate pair 91 | if(uLen == 4) 92 | { 93 | c -= 0xD800; 94 | c <<= 10; 95 | c |= (*inPtr++) - 0xDC00; 96 | } 97 | 98 | // Invalid code point 99 | if(c >= 0x00110000) 100 | return -1; 101 | 102 | int utf8Len = UTF32ToUTF8(c, outPtr); 103 | outPtr += utf8Len; 104 | len += utf8Len; 105 | 106 | c = *inPtr++; 107 | } 108 | return len; 109 | } 110 | -------------------------------------------------------------------------------- /src/op_sys0.c: -------------------------------------------------------------------------------- 1 | // 2 | // Sys0 opcode re-implementations 3 | // 4 | 5 | #include "bgi.h" 6 | #include "patch.h" 7 | 8 | // ----------------------------------------------------------------------------- 9 | // Mnemonic: sys.islauncher 10 | // Opcode: 0x80 11 | // Stack in: 0 12 | // Stack out: 1 13 | // Bytes: 0 14 | // ----------------------------------------------------------------------------- 15 | int op_sys0_islauncher(VMThread_t* thread) 16 | { 17 | printf("fixme: sys.islauncher is not implemented\n"); 18 | BGI_PushStack(thread, 0); 19 | return 0; 20 | } 21 | 22 | // ----------------------------------------------------------------------------- 23 | // Mnemonic: sys.settimer 24 | // Opcode: 0x58 25 | // Stack in: 0 26 | // Stack out: 1 27 | // Bytes: 0 28 | // ----------------------------------------------------------------------------- 29 | int op_sys0_settimer(VMThread_t* thread) 30 | { 31 | int32_t time = BGI_PopStack(thread); 32 | BGI_SetTimer(thread, time); 33 | return 0; 34 | } 35 | 36 | int(*sys0Jumptable[0x100])(VMThread_t* thread) = { 37 | // 0x00 - 0x0F 38 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 39 | // 0x10 - 0x1F 40 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 41 | // 0x20 - 0x2F 42 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 43 | // 0x30 - 0x3F 44 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 45 | // 0x40 - 0x4F 46 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 47 | // 0x50 - 0x5F 48 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, op_sys0_settimer, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 49 | // 0x60 - 0x6F 50 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 51 | // 0x70 - 0x7F 52 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 53 | // 0x80 - 0x8F 54 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 55 | // 0x90 - 0x9F 56 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 57 | // 0xA0 - 0xAF 58 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 59 | // 0xB0 - 0xBF 60 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 61 | // 0xC0 - 0xCF 62 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 63 | // 0xD0 - 0xDF 64 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 65 | // 0xE0 - 0xEF 66 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 67 | // 0xF0 - 0xFF 68 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, op_sys0_islauncher, NULL, NULL 69 | }; 70 | -------------------------------------------------------------------------------- /tools/inject/inject.c: -------------------------------------------------------------------------------- 1 | // Inject is a tool which injects an ordered list of shared libraries into the 2 | // address space of a binary executable. The created process is initially 3 | // suspended, and resumes execution once the ordered list of shared libraries 4 | // have been loaded into its address space, and their respective DllMain 5 | // functions have finished executing. 6 | // 7 | // Usage 8 | // 9 | // $ inject EXE [DLL...] 10 | // 11 | // Examples 12 | // 13 | // $ inject a.exe b.dll c.dll 14 | // 15 | // Order of execution: 16 | // 17 | // 1. Creates a suspended process of "a.exe". 18 | // 2. Loads "b.dll" into the address space of "a.exe". 19 | // 3. Executes the "DllMain" function of "b.dll". 20 | // 4. Loads "c.dll" into the address space of "a.exe". 21 | // 5. Executes the "DllMain" function of "d.dll". 22 | // 6. Resumes execution of "a.exe". 23 | // 24 | // Original source: https://github.com/mewrev/inject 25 | // 26 | #include 27 | #include 28 | 29 | int main(int argc, char** argv) 30 | { 31 | STARTUPINFO si = {0}; 32 | PROCESS_INFORMATION pi = {0}; 33 | HANDLE hThread; 34 | 35 | // Print usage. 36 | if(argc < 2) 37 | { 38 | fprintf(stderr, "Usage: inject EXE [DLL...]\n"); 39 | fprintf(stderr, "Inject an ordered list of shared libraries into the address space of a binary executable.\n"); 40 | return 1; 41 | } 42 | 43 | // Execute the process in suspended mode. 44 | char* exe_path = argv[1]; 45 | si.cb = sizeof(STARTUPINFO); 46 | if(!CreateProcess(NULL, exe_path, NULL, NULL, FALSE, CREATE_SUSPENDED, NULL, NULL, &si, &pi)) 47 | { 48 | fprintf(stderr, "CreateProcess(\"%s\") failed; error code = 0x%08X\n", exe_path, GetLastError()); 49 | return 1; 50 | } 51 | 52 | // Allocate a page in memory for the arguments of LoadLibrary. 53 | void* page = VirtualAllocEx(pi.hProcess, NULL, MAX_PATH, MEM_COMMIT|MEM_RESERVE, PAGE_READWRITE); 54 | if(page == NULL) 55 | { 56 | fprintf(stderr, "VirtualAllocEx failed; error code = 0x%08X\n", GetLastError()); 57 | return 1; 58 | } 59 | 60 | // Inject the ordered list of shared libraries into the address space of the 61 | // process. 62 | for(int i = 2; i < argc; i++) 63 | { 64 | // Verify path length. 65 | char* lib_path = argv[i]; 66 | int len = strlen(lib_path) + 1; 67 | if(len > MAX_PATH) 68 | { 69 | fprintf(stderr, "path length (%d) exceeds MAX_PATH (%d).\n", len, MAX_PATH); 70 | return 1; 71 | } 72 | if(GetFileAttributes(lib_path) == INVALID_FILE_ATTRIBUTES) 73 | { 74 | fprintf(stderr, "unable to locate library (%s).\n", lib_path); 75 | return 1; 76 | } 77 | 78 | // Write library path to the page used for LoadLibrary arguments. 79 | if(WriteProcessMemory(pi.hProcess, page, lib_path, len, NULL) == 0) 80 | { 81 | fprintf(stderr, "WriteProcessMemory failed; error code = 0x%08X\n", GetLastError()); 82 | return 1; 83 | } 84 | 85 | // Inject the shared library into the address space of the process, 86 | // through a call to LoadLibrary. 87 | hThread = CreateRemoteThread(pi.hProcess, NULL, 0, (LPTHREAD_START_ROUTINE) LoadLibraryA, page, 0, NULL); 88 | if(hThread == NULL) 89 | { 90 | fprintf(stderr, "CreateRemoteThread failed; error code = 0x%08X\n", GetLastError()); 91 | return 1; 92 | } 93 | 94 | // Wait for DllMain to return. 95 | if(WaitForSingleObject(hThread, INFINITE) == WAIT_FAILED) 96 | { 97 | fprintf(stderr, "WaitForSingleObject failed; error code = 0x%08X\n", GetLastError()); 98 | return 1; 99 | } 100 | 101 | // Cleanup. 102 | CloseHandle(hThread); 103 | } 104 | 105 | // Resume the execution of the process, once all libraries have been injected 106 | // into its address space. 107 | if(ResumeThread(pi.hThread) == -1) 108 | { 109 | fprintf(stderr, "ResumeThread failed; error code = 0x%08X\n", GetLastError()); 110 | return 1; 111 | } 112 | 113 | // Cleanup. 114 | CloseHandle(pi.hProcess); 115 | VirtualFreeEx(pi.hProcess, page, MAX_PATH, MEM_RELEASE); 116 | 117 | return 0; 118 | } -------------------------------------------------------------------------------- /src/patch.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #ifndef _PATCH_H_ 8 | #define _PATCH_H_ 9 | 10 | #include "bgi.h" 11 | 12 | // ----------------------------------------------------------------------------- 13 | // 14 | // Debugger structs 15 | // 16 | // ----------------------------------------------------------------------------- 17 | typedef struct LogOperation 18 | { 19 | uint8_t opcode; 20 | uint8_t res; 21 | uint8_t thread; 22 | uint16_t numStackIn; 23 | uint16_t numStackOut; 24 | uint16_t numBytesIn; 25 | uint32_t pc; 26 | uint32_t stackIn[512]; 27 | uint32_t stackOut[512]; 28 | uint8_t bytesIn[1024]; 29 | } __attribute__((__packed__)) LogOperation_t; 30 | 31 | typedef struct Breakpoint Breakpoint_t; 32 | struct Breakpoint 33 | { 34 | bool inUse; 35 | int type; 36 | bool enabled; 37 | char name[64]; 38 | uint32_t value; 39 | }; 40 | extern Breakpoint_t gBreakpoints[32]; 41 | 42 | // ----------------------------------------------------------------------------- 43 | // 44 | // Disassembler 45 | // 46 | // ----------------------------------------------------------------------------- 47 | typedef struct BGIOpcode 48 | { 49 | char* mnemonic; 50 | int numOperands; 51 | char operands[4]; 52 | } BGIOpcode_t; 53 | 54 | typedef struct DisasmLine DisasmLine_t; 55 | struct DisasmLine 56 | { 57 | char* str; 58 | uint32_t location; 59 | int isLabel; 60 | DisasmLine_t* next; 61 | }; 62 | 63 | typedef struct Disasm Disasm_t; 64 | struct Disasm 65 | { 66 | VMThread_t* thread; 67 | VMProgramList_t* program; 68 | char* filename; 69 | uint32_t location; 70 | uint32_t size; 71 | DisasmLine_t* disasm; 72 | Disasm_t* next; 73 | }; 74 | 75 | // ----------------------------------------------------------------------------- 76 | // 77 | // Debugger globals 78 | // 79 | // ----------------------------------------------------------------------------- 80 | // Windows 81 | extern HMODULE gDllHModule; 82 | extern HWND gDebuggerWindow; 83 | extern HFONT gFont; 84 | 85 | // Debugger 86 | extern VMThread_t** gVMThread; 87 | extern VMThread_t* gLastExecutedVMThread; 88 | extern VMThread_t* curThreadPtr; 89 | 90 | // Execution control 91 | extern int gHaltExecution; 92 | extern int gStepExecution; 93 | extern int gStepThread; 94 | 95 | // Disassembler 96 | extern BGIOpcode_t basicInstructions[256]; 97 | extern BGIOpcode_t sys0Instructions[256]; 98 | 99 | // ----------------------------------------------------------------------------- 100 | // 101 | // VM funcs 102 | // 103 | // ----------------------------------------------------------------------------- 104 | 105 | typedef VMThread_t* (__thiscall *BGI_AllocateVMThread_)(VMThread_t* parent, int stackSize, unsigned int codeSpaceSize, unsigned int localMemSize); 106 | #define BGI_AllocateVMThread ((BGI_AllocateVMThread_)0x0042e030) 107 | 108 | // ----------------------------------------------------------------------------- 109 | // 110 | // Debugger funcs 111 | // 112 | // ----------------------------------------------------------------------------- 113 | int buildBuffer(); 114 | int countThreads(); 115 | uint32_t getThreadIP(int threadId); 116 | void updateVMInfo(VMThread_t* thread); 117 | 118 | // Called from assembly 119 | void init(); 120 | int executeOpcode(int opcode, VMThread_t* vmThread); 121 | 122 | // Misc 123 | void shutdownDebugger(); 124 | void fatalError(char* error); 125 | HWND makeButton(char* title, HWND wnd, int x, int y, int width, int height, int id); 126 | 127 | // Debugging 128 | bool createDebugWindow(); 129 | Disasm_t* disassembleProgram(VMThread_t* thread, VMProgramList_t* program); 130 | void freeDisassemblies(Disasm_t* disasm); 131 | 132 | // Breakpoints 133 | bool createBreakpointsWindow(); 134 | void disableBreakpointsInputs(); 135 | void showBreakpointsWindow(); 136 | void hideBreakpointsWindow(); 137 | void populateBreakpointList(); 138 | void setBreakpointsWindow(Breakpoint_t* breakpoint); 139 | Breakpoint_t* getFreeBreakpoint(); 140 | 141 | // Switch opcodes to our re-implementations 142 | void overrideVMOpcodes(); 143 | 144 | // Windows stuff 145 | BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved); 146 | LRESULT WINAPI DLLWindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam); 147 | 148 | 149 | 150 | #endif 151 | -------------------------------------------------------------------------------- /src/disassembler.c: -------------------------------------------------------------------------------- 1 | // 2 | // Disassembler 3 | // 4 | 5 | #include "patch.h" 6 | 7 | char* jmpOps[] = { 8 | "jnz", 9 | "jz", 10 | "jg", 11 | "jge", 12 | "jle", 13 | "jl", 14 | "ja" 15 | }; 16 | 17 | DisasmLine_t* addLine(DisasmLine_t* prev, uint32_t location, int isLabel, char* str) 18 | { 19 | DisasmLine_t* newLine = (DisasmLine_t*)malloc(sizeof(DisasmLine_t)); 20 | if(!newLine) 21 | { 22 | printf("Failed to malloc\n"); 23 | return NULL; 24 | } 25 | if(prev) 26 | prev->next = newLine; 27 | 28 | newLine->str = NULL; 29 | newLine->str = (char*)malloc(strlen(str)+1); 30 | strcpy(newLine->str, str); 31 | 32 | newLine->isLabel = isLabel; 33 | newLine->location = location; 34 | newLine->next = NULL; 35 | 36 | return newLine; 37 | } 38 | 39 | Disasm_t* disassembleProgram(VMThread_t* thread, VMProgramList_t* program) 40 | { 41 | if(!program || !thread) return NULL; 42 | 43 | uint8_t* ptr = thread->codeSpace; 44 | off_t end = program->location + program->size; 45 | off_t pos = program->location; 46 | 47 | DisasmLine_t* top = NULL; 48 | DisasmLine_t* cur = NULL; 49 | 50 | char str[256]; 51 | if(program->filename) 52 | snprintf(&str[0], 256, "; Program: %s", program->filename); 53 | else 54 | snprintf(&str[0], 256, "; Program: ?"); 55 | printf("%s\n", &str[0]); 56 | top = addLine(NULL, pos, 0, &str[0]); 57 | cur = top; 58 | 59 | while(1) 60 | { 61 | uint8_t bytecode = ptr[pos++]; 62 | BGIOpcode_t* opcode = &basicInstructions[bytecode]; 63 | if(opcode->mnemonic == NULL) 64 | { 65 | snprintf(&str[0], 256, " %.8LX: .db 0x%.2X", pos, bytecode); 66 | cur = addLine(cur, pos, 0, &str[0]); 67 | continue; 68 | } 69 | 70 | // Conditional jmp is special 71 | if(bytecode == 0x15) 72 | { 73 | int jmpOp = ptr[pos++]; 74 | if(jmpOp > 0x05) 75 | jmpOp = 0x06; 76 | char* opStr = jmpOps[jmpOp]; 77 | snprintf(&str[0], 256, " %.8LX: %s", pos, opStr); 78 | cur = addLine(cur, pos, 0, &str[0]); 79 | continue; 80 | } 81 | 82 | // Multi-byte instructions 83 | uint8_t multibyteBytecode = 0; 84 | BGIOpcode_t* multibyteOpcode = NULL; 85 | switch(bytecode) 86 | { 87 | case 0x80: 88 | multibyteBytecode = ptr[pos++]; 89 | multibyteOpcode = &sys0Instructions[multibyteBytecode]; 90 | break; 91 | } 92 | 93 | int operands[4]; 94 | char fmt[128]; 95 | int sPos = 0; 96 | fmt[sPos++] = ' '; 97 | fmt[sPos++] = ' '; 98 | fmt[sPos++] = '%'; 99 | fmt[sPos++] = '.'; 100 | fmt[sPos++] = '8'; 101 | fmt[sPos++] = 'L'; 102 | fmt[sPos++] = 'X'; 103 | fmt[sPos++] = ':'; 104 | fmt[sPos++] = ' '; 105 | fmt[sPos++] = '%'; 106 | fmt[sPos++] = 's'; 107 | if(multibyteOpcode && multibyteOpcode->mnemonic) 108 | { 109 | fmt[sPos++] = '.'; 110 | fmt[sPos++] = '%'; 111 | fmt[sPos++] = 's'; 112 | } 113 | else if(multibyteOpcode && !multibyteOpcode->mnemonic) 114 | { 115 | fmt[sPos++] = '.'; 116 | fmt[sPos++] = '0'; 117 | fmt[sPos++] = 'x'; 118 | fmt[sPos++] = '%'; 119 | fmt[sPos++] = '.'; 120 | fmt[sPos++] = '2'; 121 | fmt[sPos++] = 'X'; 122 | } 123 | 124 | BGIOpcode_t* parseOpcode = opcode; 125 | if(multibyteOpcode) 126 | parseOpcode = multibyteOpcode; 127 | for(int i = 0; i < parseOpcode->numOperands; i++) 128 | { 129 | char pres = '0'; 130 | switch(parseOpcode->operands[i]) 131 | { 132 | case 1: 133 | operands[i] = ptr[pos]; 134 | pres = '2'; 135 | break; 136 | case 2: 137 | operands[i] = *(uint16_t*)&ptr[pos]; 138 | pres = '4'; 139 | break; 140 | case 4: 141 | operands[i] = *(uint32_t*)&ptr[pos]; 142 | pres = '8'; 143 | break; 144 | } 145 | fmt[sPos++] = ' '; 146 | fmt[sPos++] = '0'; 147 | fmt[sPos++] = 'x'; 148 | fmt[sPos++] = '%'; 149 | fmt[sPos++] = '.'; 150 | fmt[sPos++] = pres; 151 | fmt[sPos++] = 'L'; 152 | fmt[sPos++] = 'X'; 153 | pos += parseOpcode->operands[i]; 154 | } 155 | fmt[sPos++] = 0; 156 | 157 | if(multibyteOpcode && multibyteOpcode->mnemonic) 158 | snprintf(&str[0], 256, fmt, pos, opcode->mnemonic, multibyteOpcode->mnemonic, operands[0], operands[1], operands[2], operands[3]); 159 | else if(multibyteOpcode && !multibyteOpcode->mnemonic) 160 | snprintf(&str[0], 256, fmt, pos, opcode->mnemonic, multibyteBytecode, operands[0], operands[1], operands[2], operands[3]); 161 | else 162 | snprintf(&str[0], 256, fmt, pos, opcode->mnemonic, operands[0], operands[1], operands[2], operands[3]); 163 | cur = addLine(cur, pos, 0, &str[0]); 164 | 165 | if(pos >= end) 166 | break; 167 | } 168 | 169 | Disasm_t* disasm = (Disasm_t*)malloc(sizeof(Disasm_t)); 170 | disasm->thread = thread; 171 | disasm->program = program; 172 | disasm->location = program->location; 173 | disasm->size = program->size; 174 | disasm->filename = (char*)malloc(strlen(program->filename)+1); 175 | strcpy(disasm->filename, program->filename); 176 | disasm->disasm = top; 177 | disasm->next = NULL; 178 | 179 | return disasm; 180 | } 181 | 182 | void freeDisassemblies(Disasm_t* disasm) 183 | { 184 | while(disasm) 185 | { 186 | DisasmLine_t* line = disasm->disasm; 187 | while(line) 188 | { 189 | DisasmLine_t* next = line->next; 190 | if(line->str) 191 | free(line->str); 192 | free(line); 193 | line = next; 194 | } 195 | Disasm_t* n = disasm->next; 196 | if(disasm->filename) 197 | free(disasm->filename); 198 | free(disasm); 199 | disasm = n; 200 | } 201 | } 202 | -------------------------------------------------------------------------------- /src/bgi.h: -------------------------------------------------------------------------------- 1 | // 2 | // 3 | // 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | #ifndef _BGI_H_ 10 | #define _BGI_H_ 11 | 12 | #include "sjis.h" 13 | 14 | #define BGI_MEMORY_OFFSET 0x12000000 15 | #define BGI_CODE_OFFSET 0x10000000 16 | 17 | // 18 | // Forward declarations - Structs 19 | // 20 | typedef struct VMMemory VMMemory_t; 21 | typedef struct VMThread VMThread_t; 22 | typedef struct VMUnknownStruct VMUnknownStruct_t; 23 | typedef struct VMProgramList VMProgramList_t; 24 | 25 | // 26 | // Forward declarations - Functions 27 | // 28 | // Note: These must be __thiscall, as it's expected when calling from assembly 29 | char __thiscall BGI_ReadCode8(VMThread_t* vmThread); 30 | short __thiscall BGI_ReadCode16(VMThread_t* vmThread); 31 | int __thiscall BGI_ReadCode32(VMThread_t* vmThread); 32 | int __thiscall BGI_PopStack(VMThread_t* vmThread); 33 | void __thiscall BGI_PushStack(VMThread_t* vmThread, int data); 34 | 35 | uint8_t* BGI_PopAndResolveAddress(VMThread_t* thread); 36 | uint8_t* BGI_ResolveAddr(uint32_t address, VMThread_t* thread); 37 | uint32_t BGI_GetMemPointer(VMThread_t* thread); 38 | void BGI_SetMemPointer(VMThread_t* thread, uint32_t newPtr); 39 | uint32_t BGI_GetLocalMemSize(VMThread_t* thread); 40 | uint32_t BGI_GetInstructionPointer(VMThread_t* thread); 41 | void BGI_SetInstructionPointer(VMThread_t* thread, uint32_t address); 42 | uint8_t* BGI_GetCodeSpace(VMThread_t* thread); 43 | uint32_t BGI_GetCodeSpaceSize(VMThread_t* thread); 44 | uint8_t* BGI_GetLocalMem(VMThread_t* thread); 45 | uint8_t* BGI_GetUnknownStuctMem(VMThread_t* thread, uint32_t address); 46 | uint8_t* BGI_GetAuxMemory(int slot); 47 | void BGI_WriteIntToMemory(uint8_t* ptr, int intSize, uint32_t data); 48 | void BGI_WriteReturnAddr(VMThread_t* thread, uint32_t addr); 49 | uint32_t BGI_ReadReturnAddr(VMThread_t* thread); 50 | void BGI_Sprintf(char* dst, char* fmt, VMThread_t* thread); 51 | bool BGI_IsDoubleByteSJIS(char c); 52 | void BGI_StrToLowerCase(char* ptr); 53 | bool BGI_IsDelimiter(uint16_t c); 54 | void BGI_SetTimer(VMThread_t* thread, int time); 55 | 56 | // Note: Must be __cdecl 57 | int __cdecl op_push8(VMThread_t* thread); // 0x00 58 | int __cdecl op_push16(VMThread_t* thread); // 0x01 59 | int __cdecl op_push32(VMThread_t* thread); // 0x02 60 | int __cdecl op_memptr(VMThread_t* thread); // 0x04 61 | int __cdecl op_codeptr(VMThread_t* thread); // 0x05 62 | int __cdecl op_codeoffset(VMThread_t* thread); // 0x06 63 | int __cdecl op_readmem(VMThread_t* thread); // 0x08 64 | int __cdecl op_writecopy(VMThread_t* thread); // 0x09 65 | int __cdecl op_write(VMThread_t* thread); // 0x0A 66 | int __cdecl op_copystack(VMThread_t* thread); // 0x0C 67 | int __cdecl op_memptr2(VMThread_t* thread); // 0x10 68 | int __cdecl op_storememptr(VMThread_t* thread); // 0x11 69 | int __cdecl op_jmp(VMThread_t* thread); // 0x14 70 | int __cdecl op_cjmp(VMThread_t* thread); // 0x15 71 | int __cdecl op_call(VMThread_t* thread); // 0x16 72 | int __cdecl op_ret(VMThread_t* thread); // 0x17 73 | int __cdecl op_add(VMThread_t* thread); // 0x20 74 | int __cdecl op_sub(VMThread_t* thread); // 0x21 75 | int __cdecl op_mul(VMThread_t* thread); // 0x22 76 | int __cdecl op_div(VMThread_t* thread); // 0x23 77 | int __cdecl op_mod(VMThread_t* thread); // 0x24 78 | int __cdecl op_and(VMThread_t* thread); // 0x25 79 | int __cdecl op_or(VMThread_t* thread); // 0x26 80 | int __cdecl op_xor(VMThread_t* thread); // 0x27 81 | int __cdecl op_not(VMThread_t* thread); // 0x28 82 | int __cdecl op_shl(VMThread_t* thread); // 0x29 83 | int __cdecl op_shr(VMThread_t* thread); // 0x2A 84 | int __cdecl op_sar(VMThread_t* thread); // 0x2B 85 | int __cdecl op_eq(VMThread_t* thread); // 0x30 86 | int __cdecl op_neq(VMThread_t* thread); // 0x31 87 | int __cdecl op_leq(VMThread_t* thread); // 0x32 88 | int __cdecl op_geq(VMThread_t* thread); // 0x33 89 | int __cdecl op_le(VMThread_t* thread); // 0x34 90 | int __cdecl op_ge(VMThread_t* thread); // 0x35 91 | int __cdecl op_dnotzero(VMThread_t* thread); // 0x38 92 | int __cdecl op_dnotzero2(VMThread_t* thread); // 0x39 93 | int __cdecl op_iszero(VMThread_t* thread); // 0x3A 94 | int __cdecl op_ternary(VMThread_t* thread); // 0x40 95 | int __cdecl op_muldiv(VMThread_t* thread); // 0x42 96 | int __cdecl op_sin(VMThread_t* thread); // 0x48 97 | int __cdecl op_cos(VMThread_t* thread); // 0x49 98 | int __cdecl op_memcpy(VMThread_t* thread); // 0x60 99 | int __cdecl op_memclr(VMThread_t* thread); // 0x61 100 | int __cdecl op_memset(VMThread_t* thread); // 0x62 101 | int __cdecl op_memcmp(VMThread_t* thread); // 0x63 102 | int __cdecl op_strreplace(VMThread_t* thread); // 0x67 103 | int __cdecl op_strlen(VMThread_t* thread); // 0x68 104 | int __cdecl op_streq(VMThread_t* thread); // 0x69 105 | int __cdecl op_strcpy(VMThread_t* thread); // 0x6A 106 | int __cdecl op_strconcat(VMThread_t* thread); // 0x6B 107 | int __cdecl op_getchar(VMThread_t* thread); // 0x6C 108 | int __cdecl op_tolower(VMThread_t* thread); // 0x6D 109 | int __cdecl op_sprintf(VMThread_t* thread); // 0x6F 110 | int __cdecl op_addmemboundary(VMThread_t* thread); // 0x75 111 | int __cdecl op_sys0(VMThread_t* thread); // 0x80 112 | 113 | int __cdecl op_sys0_settimer(VMThread_t* thread); // 0x58 114 | 115 | // 116 | // Allocated memory 117 | // 118 | struct VMMemory 119 | { 120 | int isAllocated; 121 | uint8_t* mem; 122 | int size; 123 | }; 124 | 125 | // 126 | // Thread state 127 | // 128 | struct VMThread 129 | { 130 | uint32_t programId; 131 | uint32_t threadId; 132 | VMThread_t* nextThread; 133 | uint32_t flags; 134 | uint32_t stackPointer; 135 | uint32_t instructionPointer; 136 | uint32_t programCounter; 137 | uint32_t memPtr; 138 | uint32_t stackSize; 139 | VMMemory_t* stackMemConfig; 140 | uint32_t* stack; 141 | uint32_t codeSpaceSize; 142 | VMMemory_t* codeSpaceMemConfig; 143 | uint8_t* codeSpace; 144 | VMProgramList_t* programList; 145 | uint32_t programCount; 146 | uint32_t codeSpaceTop; 147 | uint32_t localMemSize; 148 | VMMemory_t* localMemConfig; 149 | uint8_t* localMem; 150 | VMUnknownStruct_t* unknownStruct; 151 | int (*field_0x54)(int); 152 | uint32_t field_0x58; 153 | uint32_t field_0x5c; 154 | uint32_t field_0x60; 155 | }; 156 | 157 | // 158 | // ???? 159 | // 160 | struct VMUnknownStruct 161 | { 162 | int field_0x0; 163 | uint8_t* buf; 164 | int field_0x8; 165 | int field_0xc; 166 | VMMemory_t* mem; 167 | int field_0x14; 168 | int field_0x18; 169 | int field_0x1c; 170 | }; 171 | 172 | // 173 | // List of loaded programs - Unique per thread 174 | // 175 | struct VMProgramList 176 | { 177 | char* filename; 178 | int size; 179 | int location; 180 | VMProgramList_t* prevProgram; 181 | }; 182 | 183 | extern int(**opcodeJumptable)(VMThread_t* thread); 184 | extern VMThread_t** gVMThread; 185 | extern VMThread_t* gLastExecutedVMThread; 186 | 187 | extern int(*sys0Jumptable[0x100])(VMThread_t* thread); 188 | 189 | #define gAuxMemory ((uint8_t**)0x004beac0) // Pointer to array of uint8_t* pointers (uint8_t* gAuxMemory[]) 190 | #define gGlobalMem (*((uint8_t**)0x004bd43c)) // Pointer to uint8_t* array (uint8_t* gGlobalMem) 191 | 192 | #define bgiThreadCount (*((volatile int*) 0x004994f4)) 193 | #define gTimerPrecision (*((volatile int*) 0x004c0600)) 194 | 195 | #define gSys0Jumptable (((int(**)(VMThread_t*)) 0x0048d438)) 196 | 197 | #endif 198 | -------------------------------------------------------------------------------- /src/disasm_basic.c: -------------------------------------------------------------------------------- 1 | // 2 | // Basic instructions 3 | // 4 | 5 | #include "patch.h" 6 | 7 | BGIOpcode_t basicInstructions[256] = 8 | { 9 | // 0x00 push8 10 | { 11 | .mnemonic = "push8", 12 | .numOperands = 1, 13 | .operands = {1,0,0,0} 14 | }, 15 | // 0x01 push16 16 | { 17 | .mnemonic = "push16", 18 | .numOperands = 1, 19 | .operands = {2,0,0,0} 20 | }, 21 | // 0x02 push32 22 | { 23 | .mnemonic = "push32", 24 | .numOperands = 1, 25 | .operands = {4,0,0,0} 26 | }, 27 | // 0x03 ---- 28 | {}, 29 | // 0x04 memptr 30 | { 31 | .mnemonic = "memptr", 32 | .numOperands = 1, 33 | .operands = {2,0,0,0} 34 | }, 35 | // 0x05 codeptr 36 | { 37 | .mnemonic = "codeptr", 38 | .numOperands = 1, 39 | .operands = {2,0,0,0} 40 | }, 41 | // 0x06 codeoffset 42 | { 43 | .mnemonic = "codeoffset", 44 | .numOperands = 1, 45 | .operands = {2,0,0,0} 46 | }, 47 | // 0x07 ----- 48 | {}, 49 | // 0x08 readmem 50 | { 51 | .mnemonic = "readmem", 52 | .numOperands = 1, 53 | .operands = {1,0,0,0} 54 | }, 55 | // 0x09 writecopy 56 | { 57 | .mnemonic = "writecopy", 58 | .numOperands = 1, 59 | .operands = {1,0,0,0} 60 | }, 61 | // 0x0A writemem 62 | { 63 | .mnemonic = "writemem", 64 | .numOperands = 1, 65 | .operands = {1,0,0,0} 66 | }, 67 | // 0x0B copycode 68 | { 69 | .mnemonic = "copycode", 70 | .numOperands = 1, 71 | .operands = {1,0,0,0} 72 | }, 73 | // 0x0C copystack 74 | { 75 | .mnemonic = "copystack", 76 | .numOperands = 2, 77 | .operands = {1,1,0,0} 78 | }, 79 | // 0x0D ----- 80 | {}, 81 | // 0x0E ----- 82 | {}, 83 | // 0x0F ----- 84 | {}, 85 | // 0x10 memptr 86 | { 87 | .mnemonic = "memptr" 88 | }, 89 | // 0x11 storememptr 90 | { 91 | .mnemonic = "storememptr" 92 | }, 93 | // 0x12 ----- 94 | {}, 95 | // 0x13 ----- 96 | {}, 97 | // 0x14 jmp 98 | { 99 | .mnemonic = "jmp" 100 | }, 101 | // 0x15 cjmp 102 | { 103 | .mnemonic = "cjmp", 104 | .numOperands = 1, 105 | .operands = {1,0,0,0} 106 | }, 107 | // 0x16 call 108 | { 109 | .mnemonic = "call" 110 | }, 111 | // 0x17 ret 112 | { 113 | .mnemonic = "ret" 114 | }, 115 | // 0x18 ----- 116 | {}, 117 | // 0x19 ----- 118 | {}, 119 | // 0x1A ----- 120 | {}, 121 | // 0x1B ----- 122 | {}, 123 | // 0x1C ----- 124 | {}, 125 | // 0x1D ----- 126 | {}, 127 | // 0x1E ----- 128 | {}, 129 | // 0x1F ----- 130 | {}, 131 | // 0x20 add 132 | { 133 | .mnemonic = "add" 134 | }, 135 | // 0x21 sub 136 | { 137 | .mnemonic = "sub" 138 | }, 139 | // 0x22 mul 140 | { 141 | .mnemonic = "mul" 142 | }, 143 | // 0x23 div 144 | { 145 | .mnemonic = "div" 146 | }, 147 | // 0x24 mod 148 | { 149 | .mnemonic = "mod" 150 | }, 151 | // 0x25 and 152 | { 153 | .mnemonic = "and" 154 | }, 155 | // 0x26 or 156 | { 157 | .mnemonic = "or" 158 | }, 159 | // 0x27 xor 160 | { 161 | .mnemonic = "xor" 162 | }, 163 | // 0x28 not 164 | { 165 | .mnemonic = "not" 166 | }, 167 | // 0x29 shl 168 | { 169 | .mnemonic = "shl" 170 | }, 171 | // 0x2A shr 172 | { 173 | .mnemonic = "shr" 174 | }, 175 | // 0x2B sar 176 | { 177 | .mnemonic = "sar" 178 | }, 179 | // 0x2C ----- 180 | {}, 181 | // 0x2D ----- 182 | {}, 183 | // 0x2E ----- 184 | {}, 185 | // 0x2F ----- 186 | {}, 187 | // 0x30 eq 188 | { 189 | .mnemonic = "eq" 190 | }, 191 | // 0x31 neq 192 | { 193 | .mnemonic = "neq" 194 | }, 195 | // 0x32 geq 196 | { 197 | .mnemonic = "leq" 198 | }, 199 | // 0x33 leq 200 | { 201 | .mnemonic = "geq" 202 | }, 203 | // 0x34 ge 204 | { 205 | .mnemonic = "ge" 206 | }, 207 | // 0x35 le 208 | { 209 | .mnemonic = "le" 210 | }, 211 | // 0x36 ----- 212 | {}, 213 | // 0x37 ----- 214 | {}, 215 | // 0x38 216 | { 217 | .mnemonic = "dnotzero2" 218 | }, 219 | // 0x39 220 | { 221 | .mnemonic = "dnotzero" 222 | }, 223 | // 0x3A 224 | { 225 | .mnemonic = "iszero" 226 | }, 227 | // 0x3B 228 | {}, 229 | // 0x3C 230 | {}, 231 | // 0x3D 232 | {}, 233 | // 0x3E 234 | {}, 235 | // 0x3F 236 | {}, 237 | // 0x40 ternary 238 | { 239 | .mnemonic = "ternary" 240 | }, 241 | // 0x41 ----- 242 | {}, 243 | // 0x42 ----- 244 | { 245 | .mnemonic = "muldiv" 246 | }, 247 | // 0x43 ----- 248 | {}, 249 | // 0x44 ----- 250 | {}, 251 | // 0x45 ----- 252 | {}, 253 | // 0x46 ----- 254 | {}, 255 | // 0x47 ----- 256 | {}, 257 | // 0x48 sin 258 | { 259 | .mnemonic = "sin" 260 | }, 261 | // 0x49 cos 262 | { 263 | .mnemonic = "cos" 264 | }, 265 | // 0x4A-4F ----- 266 | {},{},{},{},{},{}, 267 | // 0x50-5F ----- 268 | {},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{}, 269 | // 0x60 memcpy 270 | { 271 | .mnemonic = "memcpy" 272 | }, 273 | // 0x61 memcpy 274 | { 275 | .mnemonic = "memclr" 276 | }, 277 | // 0x62 memset 278 | { 279 | .mnemonic = "memset" 280 | }, 281 | // 0x63 memcmp 282 | { 283 | .mnemonic = "memcmp" 284 | }, 285 | // 0x64 ----- 286 | {}, 287 | // 0x65 ----- 288 | {}, 289 | // 0x66 ----- 290 | {}, 291 | // 0x67 ----- 292 | { 293 | .mnemonic = "strreplace" 294 | }, 295 | // 0x68 strlen 296 | { 297 | .mnemonic = "strlen" 298 | }, 299 | // 0x69 streq 300 | { 301 | .mnemonic = "streq" 302 | }, 303 | // 0x6A ----- 304 | { 305 | .mnemonic = "strcpy" 306 | }, 307 | // 0x6B ----- 308 | { 309 | .mnemonic = "strconcat" 310 | }, 311 | // 0x6C ----- 312 | { 313 | .mnemonic = "getchar" 314 | }, 315 | // 0x6D ----- 316 | { 317 | .mnemonic = "tolower" 318 | }, 319 | // 0x6E ----- 320 | { 321 | .mnemonic = "quote" 322 | }, 323 | // 0x6F sprintf 324 | { 325 | .mnemonic = "sprintf" 326 | }, 327 | // 0x70 malloc 328 | { 329 | .mnemonic = "malloc" 330 | }, 331 | // 0x71 free 332 | { 333 | .mnemonic = "free" 334 | }, 335 | // 0x72 ----- 336 | {}, 337 | // 0x73 ----- 338 | {}, 339 | // 0x74 ----- 340 | { 341 | .mnemonic = "memorychecking" 342 | }, 343 | // 0x75 ----- 344 | { 345 | .mnemonic = "addmemboundary" 346 | }, 347 | // 0x76 ----- 348 | {}, 349 | // 0x77 ----- 350 | {}, 351 | // 0x78 confirm 352 | { 353 | .mnemonic = "confirm" 354 | }, 355 | // 0x79 message 356 | { 357 | .mnemonic = "message" 358 | }, 359 | // 0x7A assert 360 | { 361 | .mnemonic = "assert" 362 | }, 363 | // 0x7B dumpmem 364 | { 365 | .mnemonic = "dumpmem" 366 | }, 367 | // 0x7C ----- 368 | {}, 369 | // 0x7D ----- 370 | {}, 371 | // 0x7E ----- 372 | {}, 373 | // 0x7F ----- 374 | {}, 375 | // 0x80 sys 376 | { 377 | .mnemonic = "sys", 378 | .numOperands = 1, 379 | .operands = {1,0,0,0} 380 | }, 381 | // 0x81 sys 382 | { 383 | .mnemonic = "sys", 384 | .numOperands = 1, 385 | .operands = {1,0,0,0} 386 | }, 387 | // 0x82 - 0x8F ----- 388 | {},{},{},{},{},{},{},{},{},{},{},{},{},{}, 389 | // 0x90 grp 390 | { 391 | .mnemonic = "grp", 392 | .numOperands = 1, 393 | .operands = {1,0,0,0} 394 | }, 395 | // 0x91 grp 396 | { 397 | .mnemonic = "grp", 398 | .numOperands = 1, 399 | .operands = {1,0,0,0} 400 | }, 401 | // 0x92 grp 402 | { 403 | .mnemonic = "grp", 404 | .numOperands = 1, 405 | .operands = {1,0,0,0} 406 | }, 407 | // 0x93 - 0x9F ----- 408 | {},{},{},{},{},{},{},{},{},{},{},{},{}, 409 | // 0xA0 snd 410 | { 411 | .mnemonic = "snd", 412 | .numOperands = 1, 413 | .operands = {1,0,0,0} 414 | }, 415 | // 0xA1 - 0xAF ----- 416 | {},{},{},{},{},{},{},{},{},{},{},{},{},{},{}, 417 | // 0xB0 ext 418 | { 419 | .mnemonic = "ext", 420 | .numOperands = 1, 421 | .operands = {1,0,0,0} 422 | }, 423 | // 0xB1 - 0xBF ----- 424 | {},{},{},{},{},{},{},{},{},{},{},{},{},{},{}, 425 | // 0xC0 ext 426 | { 427 | .mnemonic = "ext", 428 | .numOperands = 1, 429 | .operands = {1,0,0,0} 430 | }, 431 | // 0xC1 - 0xCF ----- 432 | {},{},{},{},{},{},{},{},{},{},{},{},{},{},{}, 433 | // 0xD0 eval 434 | { 435 | .mnemonic = "eval", 436 | .numOperands = 1, 437 | .operands = {1,0,0,0} 438 | }, 439 | // 0xD1 - 0xDF ----- 440 | {},{},{},{},{},{},{},{},{},{},{},{},{},{},{}, 441 | // 0xE0 ext 442 | { 443 | .mnemonic = "ext", 444 | .numOperands = 1, 445 | .operands = {1,0,0,0} 446 | }, 447 | // 0xE1 - 0xEF ----- 448 | {},{},{},{},{},{},{},{},{},{},{},{},{},{},{}, 449 | // 0xF0 - 0xFF ----- 450 | {},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{}, 451 | }; 452 | -------------------------------------------------------------------------------- /src/patch.c: -------------------------------------------------------------------------------- 1 | // 2 | // Code that is called into from patches in the game and 3 | // code that pokes around at the internals of the game. 4 | // 5 | 6 | #include 7 | #include 8 | 9 | #include "patch.h" 10 | 11 | int gHaltExecution = 1; 12 | int gStepExecution = 0; 13 | int gStepThread = 0; 14 | 15 | bool inInstruction = false; 16 | int numOperations = 0; 17 | LogOperation_t operation; 18 | FILE* logFile; 19 | 20 | uint8_t buf[4096]; 21 | 22 | int buildBuffer() 23 | { 24 | int index = 0; 25 | 26 | buf[index++] = operation.opcode; 27 | buf[index++] = operation.res; 28 | buf[index++] = operation.thread; 29 | 30 | *(uint16_t*)(&buf[index]) = operation.numStackIn; index += 2; 31 | *(uint16_t*)(&buf[index]) = operation.numStackOut; index += 2; 32 | *(uint16_t*)(&buf[index]) = operation.numBytesIn; index += 2; 33 | 34 | *(uint32_t*)(&buf[index]) = operation.pc; index += 4; 35 | 36 | for(int i = 0; i < operation.numStackIn; i++) 37 | { 38 | *(uint32_t*)(&buf[index]) = operation.stackIn[i]; index += 4; 39 | } 40 | for(int i = 0; i < operation.numStackOut; i++) 41 | { 42 | *(uint32_t*)(&buf[index]) = operation.stackOut[i]; index += 4; 43 | } 44 | for(int i = 0; i < operation.numBytesIn; i++) 45 | { 46 | buf[index++] = operation.bytesIn[i]; 47 | } 48 | return index; 49 | } 50 | 51 | void printThreadInfo(char* out, VMThread_t* thread) 52 | { 53 | sprintf(out, 54 | "programId %.8LX\n" 55 | "threadId %.8LX\n" 56 | "nextThread %.8LX\n" 57 | "flags %.8LX\n" 58 | "stackPointer %.8LX\n" 59 | "instructionPointer %.8LX\n" 60 | "programCounter %.8LX\n" 61 | "memPtr %.8LX\n" 62 | "stackSize %.8LX\n" 63 | "stackMemConfig %.8LX\n" 64 | "stack %.8LX\n" 65 | "codeSpaceSize %.8LX\n" 66 | "codeSpaceMemConfig %.8LX\n" 67 | "codeSpace %.8LX\n" 68 | "programList %.8LX\n" 69 | "programCount %.8LX\n" 70 | "codeSpaceTop %.8LX\n" 71 | "localMemSize %.8LX\n" 72 | "localMemConfig %.8LX\n" 73 | "localMem %.8LX\n" 74 | "unknownStruct %.8LX\n" 75 | "field_0x54 %.8LX\n" 76 | "field_0x58 %.8LX\n" 77 | "field_0x5c %.8LX\n" 78 | "field_0x60 %.8LX\n", 79 | (uint32_t)thread->programId, 80 | (uint32_t)thread->threadId, 81 | (uint32_t)thread->nextThread, 82 | (uint32_t)thread->flags, 83 | (uint32_t)thread->stackPointer, 84 | (uint32_t)thread->instructionPointer, 85 | (uint32_t)thread->programCounter, 86 | (uint32_t)thread->memPtr, 87 | (uint32_t)thread->stackSize, 88 | (uint32_t)thread->stackMemConfig, 89 | (uint32_t)thread->stack, 90 | (uint32_t)thread->codeSpaceSize, 91 | (uint32_t)thread->codeSpaceMemConfig, 92 | (uint32_t)thread->codeSpace, 93 | (uint32_t)thread->programList, 94 | (uint32_t)thread->programCount, 95 | (uint32_t)thread->codeSpaceTop, 96 | (uint32_t)thread->localMemSize, 97 | (uint32_t)thread->localMemConfig, 98 | (uint32_t)thread->localMem, 99 | (uint32_t)thread->unknownStruct, 100 | (uint32_t)thread->field_0x54, 101 | (uint32_t)thread->field_0x58, 102 | (uint32_t)thread->field_0x5c, 103 | (uint32_t)thread->field_0x60 104 | ); 105 | } 106 | 107 | uint32_t getThreadIP(int threadId) 108 | { 109 | if(!gVMThread) 110 | return 0; 111 | int count = 0; 112 | VMThread_t* t = *gVMThread; 113 | while(t) 114 | { 115 | if(count == threadId) 116 | return t->instructionPointer; 117 | count++; 118 | t = t->nextThread; 119 | } 120 | return 0; 121 | } 122 | 123 | int countThreads() 124 | { 125 | if(!gVMThread) 126 | return 0; 127 | int count = 0; 128 | VMThread_t* t = *gVMThread; 129 | while(t) 130 | { 131 | count++; 132 | t = t->nextThread; 133 | } 134 | return count; 135 | } 136 | 137 | // This should be called as soon as possible in WinMain 138 | void init() 139 | { 140 | //logFile = fopen("execution.log", "wb"); 141 | //if(logFile == NULL) 142 | //{ 143 | // MessageBoxA(NULL, "Failed to create execution log file", "Error", 0); 144 | // ExitProcess(1); 145 | //} 146 | 147 | // Unicode, please 148 | //SetConsoleOutputCP(CP_UTF8); 149 | //_setmode(_fileno(stdout), _O_U8TEXT); 150 | //_setmode(_fileno(stderr), _O_U8TEXT); 151 | 152 | overrideVMOpcodes(); 153 | } 154 | 155 | // Called whenever the VM tries to execute an instruction 156 | int executeOpcode(int opcode, VMThread_t* vmThread) 157 | { 158 | gLastExecutedVMThread = vmThread; 159 | 160 | inInstruction = true; 161 | numOperations = 0; 162 | 163 | // Log opcode 164 | operation.opcode = opcode; 165 | operation.pc = vmThread->instructionPointer; 166 | operation.thread = vmThread->threadId; 167 | operation.numStackIn = 0; 168 | operation.numStackOut = 0; 169 | operation.numBytesIn = 0; 170 | 171 | bool doRun = true; 172 | int res; 173 | 174 | if(gHaltExecution) 175 | { 176 | if(gStepExecution && vmThread->threadId == gStepThread) 177 | { 178 | doRun = true; 179 | gStepExecution = 0; 180 | gStepThread = 0; 181 | } 182 | else 183 | { 184 | // Pretend the current thread yielded 185 | doRun = false; 186 | res = 1; 187 | vmThread->instructionPointer--; // Correct the counters, so that we don't skip the real 188 | vmThread->programCounter--; // instruction when we begin execution again. 189 | } 190 | } 191 | 192 | if(doRun) 193 | { 194 | // Execute opcode 195 | res = opcodeJumptable[opcode](vmThread); 196 | } 197 | 198 | operation.res = res; 199 | 200 | inInstruction = false; 201 | 202 | // Write log file 203 | //int size = buildBuffer(); 204 | //fwrite(&buf[0], 1, size, logFile); 205 | 206 | return res; 207 | } 208 | 209 | void haltExecution(VMThread_t* thread) 210 | { 211 | curThreadPtr = thread; 212 | doHaltExecution(1); 213 | } 214 | 215 | int __cdecl op_unknown(VMThread_t* thread) 216 | { 217 | uint8_t opcode = thread->codeSpace[thread->instructionPointer]; 218 | wprintf(L"Undefined opcode: 0x%.2X (%d) at address %.8LX\n", opcode, opcode, thread->instructionPointer); 219 | thread->instructionPointer--; 220 | thread->programCounter--; 221 | haltExecution(thread); 222 | } 223 | 224 | // Switch opcodes to our re-implementations 225 | void overrideVMOpcodes() 226 | { 227 | for(int i = 0; i < 0x100; i++) 228 | { 229 | if(i >= 0x80) 230 | continue; 231 | opcodeJumptable[i] = op_unknown; 232 | } 233 | 234 | opcodeJumptable[0x00] = op_push8; 235 | opcodeJumptable[0x01] = op_push16; 236 | opcodeJumptable[0x02] = op_push32; 237 | opcodeJumptable[0x04] = op_memptr; 238 | opcodeJumptable[0x05] = op_codeptr; 239 | opcodeJumptable[0x06] = op_codeoffset; 240 | opcodeJumptable[0x08] = op_readmem; 241 | opcodeJumptable[0x09] = op_writecopy; 242 | opcodeJumptable[0x0A] = op_write; 243 | opcodeJumptable[0x0B] = op_unknown; // TODO: op_copycode 244 | opcodeJumptable[0x0C] = op_copystack; 245 | opcodeJumptable[0x10] = op_memptr2; 246 | opcodeJumptable[0x11] = op_storememptr; 247 | opcodeJumptable[0x14] = op_jmp; 248 | opcodeJumptable[0x15] = op_cjmp; 249 | opcodeJumptable[0x16] = op_call; 250 | opcodeJumptable[0x17] = op_ret; 251 | opcodeJumptable[0x20] = op_add; 252 | opcodeJumptable[0x21] = op_sub; 253 | opcodeJumptable[0x22] = op_mul; 254 | opcodeJumptable[0x23] = op_div; 255 | opcodeJumptable[0x24] = op_mod; 256 | opcodeJumptable[0x25] = op_and; 257 | opcodeJumptable[0x26] = op_or; 258 | opcodeJumptable[0x27] = op_xor; 259 | opcodeJumptable[0x28] = op_not; 260 | opcodeJumptable[0x29] = op_shl; 261 | opcodeJumptable[0x2A] = op_shr; 262 | opcodeJumptable[0x2B] = op_sar; 263 | opcodeJumptable[0x30] = op_eq; 264 | opcodeJumptable[0x31] = op_neq; 265 | opcodeJumptable[0x32] = op_leq; 266 | opcodeJumptable[0x33] = op_geq; 267 | opcodeJumptable[0x34] = op_le; 268 | opcodeJumptable[0x35] = op_ge; 269 | opcodeJumptable[0x38] = op_dnotzero; 270 | opcodeJumptable[0x39] = op_dnotzero2; 271 | opcodeJumptable[0x3A] = op_iszero; 272 | opcodeJumptable[0x40] = op_ternary; 273 | opcodeJumptable[0x42] = op_muldiv; 274 | opcodeJumptable[0x48] = op_sin; 275 | opcodeJumptable[0x49] = op_cos; 276 | opcodeJumptable[0x60] = op_memcpy; 277 | opcodeJumptable[0x61] = op_memclr; 278 | opcodeJumptable[0x62] = op_memset; 279 | opcodeJumptable[0x63] = op_memcmp; 280 | opcodeJumptable[0x67] = op_strreplace; 281 | opcodeJumptable[0x68] = op_strlen; 282 | opcodeJumptable[0x69] = op_streq; 283 | opcodeJumptable[0x6A] = op_strcpy; 284 | opcodeJumptable[0x6B] = op_strconcat; 285 | opcodeJumptable[0x6C] = op_getchar; 286 | opcodeJumptable[0x6D] = op_tolower; 287 | opcodeJumptable[0x6F] = op_sprintf; 288 | opcodeJumptable[0x75] = op_addmemboundary; 289 | opcodeJumptable[0x80] = op_sys0; 290 | } 291 | -------------------------------------------------------------------------------- /src/bgi.c: -------------------------------------------------------------------------------- 1 | // 2 | // 3 | // 4 | 5 | #include "bgi.h" 6 | #include "patch.h" 7 | 8 | int(**opcodeJumptable)(VMThread_t* thread) = (int(**)(VMThread_t*))0x00488420; 9 | 10 | VMThread_t** gVMThread = (VMThread_t**)0x0049d2f8; 11 | 12 | //int* bgiThreadCount = (int*)0x004994f4; 13 | //extern uint8_t* gAuxMemory[]; // = (uint8_t**)0x004beac0; 14 | //uint8_t* gAuxMemory = (uint8_t**)0x004beac0; 15 | 16 | //asm(".global bgiThreadCount"); 17 | //asm("bgiThreadCount org 0x004994f4"); 18 | 19 | VMThread_t* gLastExecutedVMThread = NULL; 20 | 21 | // Read 1 immediate byte from the code 22 | char __thiscall BGI_ReadCode8(VMThread_t* vmThread) 23 | { 24 | // Read data from code space 25 | char data = vmThread->codeSpace[vmThread->programCounter]; 26 | vmThread->programCounter++; 27 | 28 | return data; 29 | } 30 | 31 | // Read 2 immediate bytes from the code 32 | short __thiscall BGI_ReadCode16(VMThread_t* vmThread) 33 | { 34 | // Read data from code space 35 | short data = *(short*)(vmThread->codeSpace + vmThread->programCounter); 36 | vmThread->programCounter += 2; 37 | 38 | return data; 39 | } 40 | 41 | // Read 4 immediate bytes from the code 42 | int __thiscall BGI_ReadCode32(VMThread_t* vmThread) 43 | { 44 | // Read data from code space 45 | int data = *(int*)(vmThread->codeSpace + vmThread->programCounter); 46 | vmThread->programCounter += 4; 47 | 48 | return data; 49 | } 50 | 51 | int __thiscall BGI_PopStack(VMThread_t *vmThread) 52 | { 53 | // Stack underflow 54 | if(vmThread->stackPointer == 0) 55 | vmThread->stackPointer = vmThread->stackSize; 56 | vmThread->stackPointer--; 57 | 58 | // Read data from stack 59 | int data = vmThread->stack[vmThread->stackPointer]; 60 | 61 | return data; 62 | } 63 | 64 | void __thiscall BGI_PushStack(VMThread_t* vmThread, int data) 65 | { 66 | // Write data to stack 67 | vmThread->stack[vmThread->stackPointer++] = data; 68 | 69 | // Stack overflow 70 | if(vmThread->stackPointer >= vmThread->stackSize) 71 | vmThread->stackPointer = 0; 72 | } 73 | 74 | uint8_t* BGI_ResolveAddr(uint32_t address, VMThread_t* thread) 75 | { 76 | if(address == 0) 77 | return NULL; 78 | 79 | int addrUpper = address >> 24; 80 | 81 | switch(addrUpper) 82 | { 83 | case 0x00: 84 | case 0x01: 85 | return gGlobalMem + (address & 0x1ffffff); 86 | case 0x10: 87 | case 0x11: 88 | return BGI_GetCodeSpace(thread) + (address & 0x1ffffff); 89 | case 0x12: 90 | case 0x13: 91 | return BGI_GetLocalMem(thread) + (address & 0x1ffffff); 92 | case 0x14: 93 | case 0x15: 94 | return BGI_GetUnknownStuctMem(thread, address & 0x1ffffff); 95 | default: 96 | if(addrUpper < 0x20) 97 | { 98 | // Crash - Undefined area between 0x00xxxxxx and 0x20xxxxxx 99 | MessageBox(NULL, "Undefined memory area", "Memory error", 0); 100 | return NULL; 101 | } 102 | 103 | uint8_t* auxMem = BGI_GetAuxMemory((addrUpper >> 1) - 0x10); 104 | if(auxMem == NULL) 105 | { 106 | // Crash - Aux mem out of bounds 107 | MessageBox(NULL, "Undefined aux memory area", "Memory error", 0); 108 | return NULL; 109 | } 110 | return auxMem + (address & 0x1ffffff); 111 | } 112 | } 113 | 114 | uint8_t* BGI_PopAndResolveAddress(VMThread_t* thread) 115 | { 116 | uint32_t address = BGI_PopStack(thread); 117 | uint8_t* ptr = BGI_ResolveAddr(address, thread); 118 | return ptr; 119 | } 120 | 121 | uint32_t BGI_GetMemPointer(VMThread_t* thread) 122 | { 123 | return thread->memPtr; 124 | } 125 | 126 | void BGI_SetMemPointer(VMThread_t* thread, uint32_t newPtr) 127 | { 128 | thread->memPtr = newPtr; 129 | } 130 | 131 | uint32_t BGI_GetLocalMemSize(VMThread_t* thread) 132 | { 133 | return thread->localMemSize; 134 | } 135 | 136 | uint32_t BGI_GetInstructionPointer(VMThread_t* thread) 137 | { 138 | return thread->instructionPointer; 139 | } 140 | 141 | void BGI_SetInstructionPointer(VMThread_t* thread, uint32_t address) 142 | { 143 | thread->instructionPointer = address; 144 | thread->programCounter = address; 145 | } 146 | 147 | uint8_t* BGI_GetCodeSpace(VMThread_t* thread) 148 | { 149 | return thread->codeSpace; 150 | } 151 | 152 | uint32_t BGI_GetCodeSpaceSize(VMThread_t* thread) 153 | { 154 | return thread->codeSpaceSize; 155 | } 156 | 157 | uint8_t* BGI_GetLocalMem(VMThread_t* thread) 158 | { 159 | return thread->localMem; 160 | } 161 | 162 | uint8_t* BGI_GetUnknownStuctMem(VMThread_t* thread, uint32_t address) 163 | { 164 | return thread->unknownStruct->buf + address; 165 | } 166 | 167 | uint8_t* BGI_GetAuxMemory(int slot) 168 | { 169 | if(slot > 0x30) 170 | return NULL; 171 | return gAuxMemory[slot]; 172 | } 173 | 174 | void BGI_WriteIntToMemory(uint8_t* ptr, int intSize, uint32_t data) 175 | { 176 | if(intSize == 0) 177 | { 178 | *ptr = (uint8_t)data; 179 | } 180 | else if(intSize == 1) 181 | { 182 | *(uint16_t*)ptr = (uint16_t)data; 183 | } 184 | else if(intSize == 2) 185 | { 186 | *(uint32_t*)ptr = (uint32_t)data; 187 | } 188 | } 189 | 190 | void BGI_WriteReturnAddr(VMThread_t* thread, uint32_t addr) 191 | { 192 | *(uint32_t*)(thread->localMem + thread->memPtr) = addr; 193 | thread->memPtr += 4; 194 | } 195 | 196 | uint32_t BGI_ReadReturnAddr(VMThread_t* thread) 197 | { 198 | thread->memPtr -= 4; 199 | return *(uint32_t *)(thread->localMem + thread->memPtr); 200 | } 201 | 202 | void BGI_Sprintf(char* dst, char* fmt, VMThread_t* thread) 203 | { 204 | uint32_t args[16]; 205 | int argCount = 0; 206 | char* ptr = fmt; 207 | char c = *ptr; 208 | while(c) 209 | { 210 | c = *ptr++; 211 | 212 | if(c != '%') 213 | continue; 214 | 215 | c = *ptr++; 216 | if(!c) break; // Check for string end 217 | 218 | // Flags 219 | while(c == '-' || c == '+' || c == ' ' || c == '#' || c == '0') 220 | c = *ptr++; 221 | if(!c) break; // Check for string end 222 | 223 | // Width 224 | if(c == '*') 225 | { 226 | // Variable width 227 | args[argCount++] = BGI_PopStack(thread); 228 | c = *ptr++; 229 | } 230 | else 231 | { 232 | while(c >= '0' && c <= '9') 233 | c = *ptr++; 234 | } 235 | if(!c) break; // Check for string end 236 | 237 | // Precision 238 | if(c == '.') 239 | { 240 | c = *ptr++; 241 | if(c == '*') 242 | { 243 | // Variable precision 244 | args[argCount++] = BGI_PopStack(thread); 245 | c = *ptr++; 246 | } 247 | else 248 | { 249 | while(c >= '0' && c <= '9') 250 | c = *ptr++; 251 | } 252 | } 253 | if(!c) break; // Check for string end 254 | 255 | // Length 256 | while(c == 'h' || c == 'l' || c == 'j' || c == 'z' || c == 't' || c == 'L') 257 | c = *ptr++; 258 | if(!c) break; // Check for string end 259 | 260 | // Specifier 261 | if(c == 's') 262 | args[argCount++] = (uint32_t)BGI_PopAndResolveAddress(thread); 263 | else 264 | args[argCount++] = BGI_PopStack(thread); 265 | } 266 | switch(argCount) 267 | { 268 | case 0: sprintf(dst, fmt); break; 269 | case 1: sprintf(dst, fmt, args[0]); break; 270 | case 2: sprintf(dst, fmt, args[0], args[1]); break; 271 | case 3: sprintf(dst, fmt, args[0], args[1], args[2]); break; 272 | case 4: sprintf(dst, fmt, args[0], args[1], args[2], args[3]); break; 273 | case 5: sprintf(dst, fmt, args[0], args[1], args[2], args[3], args[4]); break; 274 | case 6: sprintf(dst, fmt, args[0], args[1], args[2], args[3], args[4], args[5]); break; 275 | case 7: sprintf(dst, fmt, args[0], args[1], args[2], args[3], args[4], args[5], args[6]); break; 276 | case 8: sprintf(dst, fmt, args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7]); break; 277 | case 9: sprintf(dst, fmt, args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8]); break; 278 | case 10: sprintf(dst, fmt, args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], args[9]); break; 279 | case 11: sprintf(dst, fmt, args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], args[9], args[10]); break; 280 | case 12: sprintf(dst, fmt, args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], args[9], args[10], args[11]); break; 281 | case 13: sprintf(dst, fmt, args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], args[9], args[10], args[11], args[12]); break; 282 | case 14: sprintf(dst, fmt, args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], args[9], args[10], args[11], args[12], args[13]); break; 283 | case 15: sprintf(dst, fmt, args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], args[9], args[10], args[11], args[12], args[13], args[14]); break; 284 | case 16: sprintf(dst, fmt, args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], args[9], args[10], args[11], args[12], args[13], args[14], args[15]); break; 285 | } 286 | printf("dst: %s, fmt: %s, Number of arguments: %d\n", dst, fmt, argCount); 287 | } 288 | 289 | bool BGI_IsDoubleByteSJIS(char c) 290 | { 291 | if((c < 0x80 || c > 0x9F) && c < 0xE0) 292 | return false; 293 | return true; 294 | } 295 | 296 | void BGI_StrToLowerCase(char* ptr) 297 | { 298 | char c = *ptr; 299 | while(c) 300 | { 301 | if(BGI_IsDoubleByteSJIS(c)) 302 | ptr++; 303 | else 304 | { 305 | if(c >= 'A' && c <= 'Z') 306 | *ptr |= 0x20; 307 | } 308 | ptr++; 309 | c = *ptr; 310 | } 311 | } 312 | 313 | uint16_t delimiters[36] = { 314 | 0x002C, // , 315 | 0x002E, // . 316 | 0x00A4, // 、 317 | 0x00A1, // 。 318 | 0x003A, // : 319 | 0x003B, // ; 320 | 0x003F, // ? 321 | 0x0021, // ! 322 | 0x00DE, // ゙ 323 | 0x00DF, // ゚ 324 | 0x00A5, // ・ 325 | 0x8141, // 、 326 | 0x8142, // 。 327 | 0x8143, // , 328 | 0x8144, // . 329 | 0x8146, // : 330 | 0x8147, // ; 331 | 0x8148, // ? 332 | 0x8149, // ! 333 | 0x814A, // ゛ 334 | 0x814B, // ゜ 335 | 0x815D, // ‐ 336 | 0x005D, // ] 337 | 0x007D, // } 338 | 0x0029, // ) 339 | 0x816A, // ) 340 | 0x816C, // 〕 341 | 0x816E, // ] 342 | 0x8170, // } 343 | 0x8172, // 〉 344 | 0x8174, // 》 345 | 0x8176, // 」 346 | 0x8178, // 』 347 | 0x817A, // 】 348 | 0x8165, // ‘ 349 | 0x8167 // “ 350 | }; 351 | 352 | bool BGI_IsDelimiter(uint16_t c) 353 | { 354 | for(int i = 0; i < 36; i++) 355 | { 356 | if(c == delimiters[i]) 357 | return true; 358 | } 359 | return false; 360 | } 361 | 362 | uint32_t BGI_GetSysTime() 363 | { 364 | if(gTimerPrecision) 365 | return timeGetTime(); 366 | else 367 | return GetTickCount(); 368 | } 369 | 370 | void BGI_SetTimer(VMThread_t* thread, int time) 371 | { 372 | thread->field_0x58 = BGI_GetSysTime() + time; 373 | } 374 | -------------------------------------------------------------------------------- /src/breakpoints.c: -------------------------------------------------------------------------------- 1 | // 2 | // Breakpoints 3 | // 4 | 5 | #include "patch.h" 6 | 7 | #define ID_BREAKPOINT_ADD 1000 8 | #define ID_BREAKPOINT_REMOVE 1001 9 | #define ID_BREAKPOINT_LIST 1002 10 | #define ID_BREAKPOINT_EXECUTE 1004 11 | #define ID_BREAKPOINT_OPCODE 1005 12 | #define ID_BREAKPOINT_READ 1006 13 | #define ID_BREAKPOINT_WRITE 1007 14 | #define ID_BREAKPOINT_NAME 1008 15 | #define ID_BREAKPOINT_VALUE 1009 16 | 17 | HWND gBreakpointWindow; 18 | ATOM gBreakpointAtom; 19 | 20 | // Buttons 21 | HWND gBreakpointAdd; 22 | HWND gBreakpointRemove; 23 | 24 | // Radio buttons 25 | HWND gBreakpointTypeExecute; // When execution reaches a certain address 26 | HWND gBreakpointTypeOpcode; // When a certain opcode is executed 27 | HWND gBreakpointTypeRead; // When a certain address is read from 28 | HWND gBreakpointTypeWrite; // When a certain address is written to 29 | 30 | // Textboxes 31 | HWND gBreakpointName; // Breakpoint name 32 | HWND gBreakpointNameLabel; // Breakpoint name label 33 | HWND gBreakpointValue; // Breakpoint opcode/address (Depending on type) 34 | HWND gBreakpointValueLabel; // Breakpoint opcode/address label 35 | 36 | // List 37 | HWND gBreakpointList; // List of breakpoints 38 | 39 | // Actual breakpoints 40 | Breakpoint_t gBreakpoints[32]; 41 | 42 | // Current breakpoint being edited 43 | Breakpoint_t* curBreakpoint; 44 | 45 | // List index to breakpoint index 46 | int gBreakpointListIndices[32]; 47 | 48 | WNDPROC orgValueProc = NULL; 49 | 50 | uint32_t parseHex(char* str) 51 | { 52 | uint32_t val = 0; 53 | char c = *str; 54 | str++; 55 | while(c) 56 | { 57 | if(c >= 'A') 58 | val = (val << 4) | (c - 'A' + 0xA); 59 | else 60 | val = (val << 4) | (c - '0'); 61 | c = *str; 62 | str++; 63 | } 64 | return val; 65 | } 66 | 67 | LRESULT CALLBACK ValueProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) 68 | { 69 | switch(msg) 70 | { 71 | // Only allow hex characters 72 | case WM_CHAR: 73 | if(!((wParam >= '0' && wParam <= '9') || 74 | (wParam >= 'A' && wParam <= 'F') || 75 | (wParam >= 'a' && wParam <= 'f') || 76 | wParam == VK_RETURN || 77 | wParam == VK_DELETE || 78 | wParam == VK_BACK)) 79 | { 80 | return 0; 81 | } 82 | break; 83 | } 84 | return CallWindowProc(orgValueProc, hwnd, msg, wParam, lParam); 85 | } 86 | 87 | LRESULT WINAPI BreakpointProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) 88 | { 89 | switch(msg) 90 | { 91 | case WM_CLOSE: 92 | hideBreakpointsWindow(); 93 | break; 94 | 95 | case WM_TIMER: 96 | break; 97 | 98 | case WM_CREATE: 99 | break; 100 | 101 | case WM_COMMAND: 102 | switch(LOWORD(wParam)) 103 | { 104 | case ID_BREAKPOINT_NAME: 105 | if(HIWORD(wParam) == EN_CHANGE) 106 | { 107 | GetWindowText(gBreakpointName, &curBreakpoint->name[0], 64); 108 | populateBreakpointList(); 109 | } 110 | break; 111 | 112 | case ID_BREAKPOINT_VALUE: 113 | if(HIWORD(wParam) == EN_CHANGE) 114 | { 115 | char valueText[10]; 116 | GetWindowText(gBreakpointValue, &valueText[0], 9); 117 | uint32_t value = parseHex(&valueText[0]); 118 | curBreakpoint->value = value; 119 | populateBreakpointList(); 120 | } 121 | break; 122 | 123 | case ID_BREAKPOINT_ADD: 124 | curBreakpoint = getFreeBreakpoint(); 125 | if(!curBreakpoint) 126 | break; 127 | curBreakpoint->inUse = true; 128 | curBreakpoint->type = 1; 129 | curBreakpoint->enabled = false; 130 | curBreakpoint->name[0] = '\0'; 131 | curBreakpoint->value = 0; 132 | setBreakpointsWindow(curBreakpoint); 133 | break; 134 | case ID_BREAKPOINT_EXECUTE: 135 | case ID_BREAKPOINT_OPCODE: 136 | case ID_BREAKPOINT_READ: 137 | case ID_BREAKPOINT_WRITE: 138 | switch(HIWORD(wParam)) 139 | { 140 | case BN_CLICKED: 141 | if(LOWORD(wParam) == ID_BREAKPOINT_EXECUTE) 142 | { 143 | curBreakpoint->type = 1; 144 | SendDlgItemMessage(gBreakpointWindow, ID_BREAKPOINT_EXECUTE, BM_SETCHECK, 1, 0); 145 | } 146 | else 147 | SendDlgItemMessage(gBreakpointWindow, ID_BREAKPOINT_EXECUTE, BM_SETCHECK, 0, 0); 148 | if(LOWORD(wParam) == ID_BREAKPOINT_OPCODE) 149 | { 150 | curBreakpoint->type = 2; 151 | SendDlgItemMessage(gBreakpointWindow, ID_BREAKPOINT_OPCODE, BM_SETCHECK, 1, 0); 152 | } 153 | else 154 | SendDlgItemMessage(gBreakpointWindow, ID_BREAKPOINT_OPCODE, BM_SETCHECK, 0, 0); 155 | if(LOWORD(wParam) == ID_BREAKPOINT_READ) 156 | { 157 | curBreakpoint->type = 3; 158 | SendDlgItemMessage(gBreakpointWindow, ID_BREAKPOINT_READ, BM_SETCHECK, 1, 0); 159 | } 160 | else 161 | SendDlgItemMessage(gBreakpointWindow, ID_BREAKPOINT_READ, BM_SETCHECK, 0, 0); 162 | if(LOWORD(wParam) == ID_BREAKPOINT_WRITE) 163 | { 164 | curBreakpoint->type = 4; 165 | SendDlgItemMessage(gBreakpointWindow, ID_BREAKPOINT_WRITE, BM_SETCHECK, 1, 0); 166 | } 167 | else 168 | SendDlgItemMessage(gBreakpointWindow, ID_BREAKPOINT_WRITE, BM_SETCHECK, 0, 0); 169 | populateBreakpointList(); 170 | break; 171 | } 172 | break; 173 | 174 | case ID_BREAKPOINT_LIST: 175 | switch(HIWORD(wParam)) 176 | { 177 | case LBN_SELCHANGE: 178 | { 179 | int index = SendMessage(gBreakpointList, LB_GETCARETINDEX, 0, 0); 180 | setBreakpointsWindow(&gBreakpoints[gBreakpointListIndices[index]]); 181 | populateBreakpointList(); 182 | break; 183 | } 184 | } 185 | break; 186 | } 187 | 188 | default: 189 | return DefWindowProc(hwnd, msg, wParam, lParam); 190 | } 191 | return 0; 192 | } 193 | 194 | bool createBreakpointsWindow() 195 | { 196 | memset(&gBreakpoints[0], 0, sizeof(Breakpoint_t) * 32); 197 | 198 | WNDCLASSEXA wclass; 199 | wclass.cbSize = sizeof(WNDCLASSEXA); 200 | wclass.style = CS_OWNDC; 201 | wclass.lpfnWndProc = BreakpointProc; 202 | wclass.cbClsExtra = 0; 203 | wclass.cbWndExtra = 0; 204 | wclass.hInstance = gDllHModule; 205 | wclass.hIcon = LoadIcon(NULL, IDI_APPLICATION); 206 | wclass.hCursor = LoadCursor(NULL, IDC_ARROW); 207 | wclass.hbrBackground = (HBRUSH)COLOR_APPWORKSPACE; 208 | wclass.lpszMenuName = NULL; 209 | wclass.lpszClassName = "classPatchBreakpoints"; 210 | wclass.hIconSm = LoadIcon(NULL, IDI_APPLICATION); 211 | gBreakpointAtom = RegisterClassExA(&wclass); 212 | if(!gBreakpointAtom) 213 | { 214 | fatalError("RegisterClassExA"); 215 | return false; 216 | } 217 | 218 | gBreakpointWindow = CreateWindowExA( 219 | 0, 220 | (LPCSTR)gBreakpointAtom, 221 | "Breakpoints", 222 | WS_OVERLAPPEDWINDOW, 223 | CW_USEDEFAULT, CW_USEDEFAULT, 224 | 500, 230, 225 | NULL, NULL, 226 | gDllHModule, NULL 227 | ); 228 | if(!gBreakpointWindow) 229 | { 230 | fatalError("CreateWindowExA"); 231 | return false; 232 | } 233 | 234 | // Breakpoint list 235 | gBreakpointList = CreateWindowEx( 236 | WS_EX_CLIENTEDGE, 237 | "LISTBOX", NULL, 238 | WS_VISIBLE | WS_CHILD | LBS_STANDARD | LBS_NOTIFY, 239 | 10, 10, 240 | 250, 190, 241 | gBreakpointWindow, 242 | (HMENU)ID_BREAKPOINT_LIST, 243 | gDllHModule, NULL 244 | ); 245 | SendMessage(gBreakpointList, WM_SETFONT, (WPARAM)gFont, true); 246 | 247 | // Buttons 248 | gBreakpointAdd = makeButton("Add", gBreakpointWindow, 270, 160, 100, 30, ID_BREAKPOINT_ADD); 249 | gBreakpointRemove = makeButton("Remove", gBreakpointWindow, 375, 160, 100, 30, ID_BREAKPOINT_REMOVE); 250 | 251 | // Radio buttons 252 | gBreakpointTypeExecute = CreateWindow( 253 | "BUTTON", "Execute", 254 | WS_TABSTOP | WS_VISIBLE | WS_CHILD | BS_RADIOBUTTON, 255 | 270, 10, 256 | 100, 20, 257 | gBreakpointWindow, 258 | (HMENU)ID_BREAKPOINT_EXECUTE, 259 | gDllHModule, NULL 260 | ); 261 | SendMessage(gBreakpointTypeExecute, WM_SETFONT, (WPARAM)gFont, true); 262 | gBreakpointTypeOpcode = CreateWindow( 263 | "BUTTON", "Opcode", 264 | WS_TABSTOP | WS_VISIBLE | WS_CHILD | BS_RADIOBUTTON, 265 | 270, 30, 266 | 100, 20, 267 | gBreakpointWindow, 268 | (HMENU)ID_BREAKPOINT_OPCODE, 269 | gDllHModule, NULL 270 | ); 271 | SendMessage(gBreakpointTypeOpcode, WM_SETFONT, (WPARAM)gFont, true); 272 | gBreakpointTypeRead = CreateWindow( 273 | "BUTTON", "Read", 274 | WS_TABSTOP | WS_VISIBLE | WS_CHILD | BS_RADIOBUTTON, 275 | 370, 10, 276 | 100, 20, 277 | gBreakpointWindow, 278 | (HMENU)ID_BREAKPOINT_READ, 279 | gDllHModule, NULL 280 | ); 281 | SendMessage(gBreakpointTypeRead, WM_SETFONT, (WPARAM)gFont, true); 282 | gBreakpointTypeWrite = CreateWindow( 283 | "BUTTON", "Write", 284 | WS_TABSTOP | WS_VISIBLE | WS_CHILD | BS_RADIOBUTTON, 285 | 370, 30, 286 | 100, 20, 287 | gBreakpointWindow, 288 | (HMENU)ID_BREAKPOINT_WRITE, 289 | gDllHModule, NULL 290 | ); 291 | SendMessage(gBreakpointTypeWrite, WM_SETFONT, (WPARAM)gFont, true); 292 | 293 | // Inputs 294 | gBreakpointNameLabel = CreateWindow( 295 | "STATIC", "Name", 296 | WS_CHILD | WS_VISIBLE, 297 | 270, 60, 298 | 50, 16, 299 | gBreakpointWindow, 300 | (HMENU)ID_BREAKPOINT_NAME, 301 | gDllHModule, NULL 302 | ); 303 | SendMessage(gBreakpointNameLabel, WM_SETFONT, (WPARAM)gFont, true); 304 | gBreakpointName = CreateWindowEx( 305 | WS_EX_CLIENTEDGE, 306 | "EDIT", NULL, 307 | WS_TABSTOP | WS_VISIBLE | WS_CHILD | WS_BORDER | ES_LEFT, 308 | 270, 76, 309 | 150, 25, 310 | gBreakpointWindow, 311 | (HMENU)ID_BREAKPOINT_NAME, 312 | gDllHModule, NULL 313 | ); 314 | SendMessage(gBreakpointName, WM_SETFONT, (WPARAM)gFont, true); 315 | 316 | gBreakpointValueLabel = CreateWindow( 317 | "STATIC", "Value", 318 | WS_CHILD | WS_VISIBLE, 319 | 270, 105, 320 | 50, 16, 321 | gBreakpointWindow, 322 | (HMENU)ID_BREAKPOINT_NAME, 323 | gDllHModule, NULL 324 | ); 325 | SendMessage(gBreakpointValueLabel, WM_SETFONT, (WPARAM)gFont, true); 326 | gBreakpointValue = CreateWindowEx( 327 | WS_EX_CLIENTEDGE, 328 | "EDIT", NULL, 329 | WS_TABSTOP | WS_VISIBLE | WS_CHILD | WS_BORDER | ES_RIGHT | ES_UPPERCASE, 330 | 270, 121, 331 | 150, 25, 332 | gBreakpointWindow, 333 | (HMENU)ID_BREAKPOINT_VALUE, 334 | gDllHModule, NULL 335 | ); 336 | SendMessage(gBreakpointValue, WM_SETFONT, (WPARAM)gFont, true); 337 | orgValueProc = SetWindowLongPtr(gBreakpointValue, GWLP_WNDPROC, ValueProc); 338 | SendMessage(gBreakpointValue, EM_SETLIMITTEXT, 8, 0); 339 | 340 | disableBreakpointsInputs(); 341 | 342 | return true; 343 | } 344 | 345 | void disableBreakpointsInputs() 346 | { 347 | EnableWindow(gBreakpointRemove, false); 348 | EnableWindow(gBreakpointTypeExecute, false); 349 | EnableWindow(gBreakpointTypeOpcode, false); 350 | EnableWindow(gBreakpointTypeRead, false); 351 | EnableWindow(gBreakpointTypeWrite, false); 352 | EnableWindow(gBreakpointName, false); 353 | EnableWindow(gBreakpointNameLabel, false); 354 | EnableWindow(gBreakpointValue, false); 355 | EnableWindow(gBreakpointValueLabel, false); 356 | populateBreakpointList(); 357 | } 358 | 359 | void showBreakpointsWindow() 360 | { 361 | ShowWindow(gBreakpointWindow, SW_SHOW); 362 | populateBreakpointList(); 363 | } 364 | 365 | void hideBreakpointsWindow() 366 | { 367 | ShowWindow(gBreakpointWindow, SW_HIDE); 368 | } 369 | 370 | void populateBreakpointList() 371 | { 372 | // Delete previous content 373 | SendMessage(gBreakpointList, LB_RESETCONTENT, 0, 0); 374 | 375 | char str[128]; 376 | int index = 0; 377 | int selectedIndex = 0; 378 | for(int i = 0; i < 32; i++) 379 | { 380 | if(!gBreakpoints[i].inUse) 381 | continue; 382 | char type; 383 | switch(gBreakpoints[i].type) 384 | { 385 | case 1: type = 'E'; break; 386 | case 2: type = 'O'; break; 387 | case 3: type = 'R'; break; 388 | case 4: type = 'W'; break; 389 | case 5: type = '?'; break; 390 | } 391 | snprintf(&str[0], 128, "%c: %.8LX %s", type, gBreakpoints[i].value, &gBreakpoints[i].name[0]); 392 | gBreakpointListIndices[index] = i; 393 | if(&gBreakpoints[i] == curBreakpoint) 394 | selectedIndex = index; 395 | SendMessage(gBreakpointList, LB_INSERTSTRING, index++, (LPARAM)&str[0]); 396 | } 397 | SendMessage(gBreakpointList, LB_SETCURSEL, selectedIndex, 0); 398 | } 399 | 400 | Breakpoint_t* getFreeBreakpoint() 401 | { 402 | for(int i = 0; i < 32; i++) 403 | { 404 | if(!gBreakpoints[i].inUse) 405 | return &gBreakpoints[i]; 406 | } 407 | return NULL; 408 | } 409 | 410 | void setBreakpointsWindow(Breakpoint_t* breakpoint) 411 | { 412 | curBreakpoint = breakpoint; 413 | 414 | EnableWindow(gBreakpointRemove, true); 415 | EnableWindow(gBreakpointTypeExecute, true); 416 | EnableWindow(gBreakpointTypeOpcode, true); 417 | EnableWindow(gBreakpointTypeRead, true); 418 | EnableWindow(gBreakpointTypeWrite, true); 419 | EnableWindow(gBreakpointName, true); 420 | EnableWindow(gBreakpointNameLabel, true); 421 | EnableWindow(gBreakpointValue, true); 422 | EnableWindow(gBreakpointValueLabel, true); 423 | 424 | if(breakpoint->type == 1) 425 | SendDlgItemMessage(gBreakpointWindow, ID_BREAKPOINT_EXECUTE, BM_SETCHECK, 1, 0); 426 | else 427 | SendDlgItemMessage(gBreakpointWindow, ID_BREAKPOINT_EXECUTE, BM_SETCHECK, 0, 0); 428 | if(breakpoint->type == 2) 429 | SendDlgItemMessage(gBreakpointWindow, ID_BREAKPOINT_OPCODE, BM_SETCHECK, 1, 0); 430 | else 431 | SendDlgItemMessage(gBreakpointWindow, ID_BREAKPOINT_OPCODE, BM_SETCHECK, 0, 0); 432 | if(breakpoint->type == 3) 433 | SendDlgItemMessage(gBreakpointWindow, ID_BREAKPOINT_READ, BM_SETCHECK, 1, 0); 434 | else 435 | SendDlgItemMessage(gBreakpointWindow, ID_BREAKPOINT_READ, BM_SETCHECK, 0, 0); 436 | if(breakpoint->type == 4) 437 | SendDlgItemMessage(gBreakpointWindow, ID_BREAKPOINT_WRITE, BM_SETCHECK, 1, 0); 438 | else 439 | SendDlgItemMessage(gBreakpointWindow, ID_BREAKPOINT_WRITE, BM_SETCHECK, 0, 0); 440 | 441 | if(breakpoint->name) 442 | SetWindowTextA(gBreakpointName, breakpoint->name); 443 | else 444 | SetWindowTextA(gBreakpointName, ""); 445 | char value[32]; 446 | snprintf(&value[0], 32, "%.LX", breakpoint->value); 447 | SetWindowTextA(gBreakpointValue, &value[0]); 448 | 449 | populateBreakpointList(); 450 | } 451 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 2, June 1991 3 | 4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc., 5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | Preamble 10 | 11 | The licenses for most software are designed to take away your 12 | freedom to share and change it. By contrast, the GNU General Public 13 | License is intended to guarantee your freedom to share and change free 14 | software--to make sure the software is free for all its users. This 15 | General Public License applies to most of the Free Software 16 | Foundation's software and to any other program whose authors commit to 17 | using it. (Some other Free Software Foundation software is covered by 18 | the GNU Lesser General Public License instead.) You can apply it to 19 | your programs, too. 20 | 21 | When we speak of free software, we are referring to freedom, not 22 | price. Our General Public Licenses are designed to make sure that you 23 | have the freedom to distribute copies of free software (and charge for 24 | this service if you wish), that you receive source code or can get it 25 | if you want it, that you can change the software or use pieces of it 26 | in new free programs; and that you know you can do these things. 27 | 28 | To protect your rights, we need to make restrictions that forbid 29 | anyone to deny you these rights or to ask you to surrender the rights. 30 | These restrictions translate to certain responsibilities for you if you 31 | distribute copies of the software, or if you modify it. 32 | 33 | For example, if you distribute copies of such a program, whether 34 | gratis or for a fee, you must give the recipients all the rights that 35 | you have. You must make sure that they, too, receive or can get the 36 | source code. And you must show them these terms so they know their 37 | rights. 38 | 39 | We protect your rights with two steps: (1) copyright the software, and 40 | (2) offer you this license which gives you legal permission to copy, 41 | distribute and/or modify the software. 42 | 43 | Also, for each author's protection and ours, we want to make certain 44 | that everyone understands that there is no warranty for this free 45 | software. If the software is modified by someone else and passed on, we 46 | want its recipients to know that what they have is not the original, so 47 | that any problems introduced by others will not reflect on the original 48 | authors' reputations. 49 | 50 | Finally, any free program is threatened constantly by software 51 | patents. We wish to avoid the danger that redistributors of a free 52 | program will individually obtain patent licenses, in effect making the 53 | program proprietary. To prevent this, we have made it clear that any 54 | patent must be licensed for everyone's free use or not licensed at all. 55 | 56 | The precise terms and conditions for copying, distribution and 57 | modification follow. 58 | 59 | GNU GENERAL PUBLIC LICENSE 60 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 61 | 62 | 0. This License applies to any program or other work which contains 63 | a notice placed by the copyright holder saying it may be distributed 64 | under the terms of this General Public License. The "Program", below, 65 | refers to any such program or work, and a "work based on the Program" 66 | means either the Program or any derivative work under copyright law: 67 | that is to say, a work containing the Program or a portion of it, 68 | either verbatim or with modifications and/or translated into another 69 | language. (Hereinafter, translation is included without limitation in 70 | the term "modification".) Each licensee is addressed as "you". 71 | 72 | Activities other than copying, distribution and modification are not 73 | covered by this License; they are outside its scope. The act of 74 | running the Program is not restricted, and the output from the Program 75 | is covered only if its contents constitute a work based on the 76 | Program (independent of having been made by running the Program). 77 | Whether that is true depends on what the Program does. 78 | 79 | 1. You may copy and distribute verbatim copies of the Program's 80 | source code as you receive it, in any medium, provided that you 81 | conspicuously and appropriately publish on each copy an appropriate 82 | copyright notice and disclaimer of warranty; keep intact all the 83 | notices that refer to this License and to the absence of any warranty; 84 | and give any other recipients of the Program a copy of this License 85 | along with the Program. 86 | 87 | You may charge a fee for the physical act of transferring a copy, and 88 | you may at your option offer warranty protection in exchange for a fee. 89 | 90 | 2. You may modify your copy or copies of the Program or any portion 91 | of it, thus forming a work based on the Program, and copy and 92 | distribute such modifications or work under the terms of Section 1 93 | above, provided that you also meet all of these conditions: 94 | 95 | a) You must cause the modified files to carry prominent notices 96 | stating that you changed the files and the date of any change. 97 | 98 | b) You must cause any work that you distribute or publish, that in 99 | whole or in part contains or is derived from the Program or any 100 | part thereof, to be licensed as a whole at no charge to all third 101 | parties under the terms of this License. 102 | 103 | c) If the modified program normally reads commands interactively 104 | when run, you must cause it, when started running for such 105 | interactive use in the most ordinary way, to print or display an 106 | announcement including an appropriate copyright notice and a 107 | notice that there is no warranty (or else, saying that you provide 108 | a warranty) and that users may redistribute the program under 109 | these conditions, and telling the user how to view a copy of this 110 | License. (Exception: if the Program itself is interactive but 111 | does not normally print such an announcement, your work based on 112 | the Program is not required to print an announcement.) 113 | 114 | These requirements apply to the modified work as a whole. If 115 | identifiable sections of that work are not derived from the Program, 116 | and can be reasonably considered independent and separate works in 117 | themselves, then this License, and its terms, do not apply to those 118 | sections when you distribute them as separate works. But when you 119 | distribute the same sections as part of a whole which is a work based 120 | on the Program, the distribution of the whole must be on the terms of 121 | this License, whose permissions for other licensees extend to the 122 | entire whole, and thus to each and every part regardless of who wrote it. 123 | 124 | Thus, it is not the intent of this section to claim rights or contest 125 | your rights to work written entirely by you; rather, the intent is to 126 | exercise the right to control the distribution of derivative or 127 | collective works based on the Program. 128 | 129 | In addition, mere aggregation of another work not based on the Program 130 | with the Program (or with a work based on the Program) on a volume of 131 | a storage or distribution medium does not bring the other work under 132 | the scope of this License. 133 | 134 | 3. You may copy and distribute the Program (or a work based on it, 135 | under Section 2) in object code or executable form under the terms of 136 | Sections 1 and 2 above provided that you also do one of the following: 137 | 138 | a) Accompany it with the complete corresponding machine-readable 139 | source code, which must be distributed under the terms of Sections 140 | 1 and 2 above on a medium customarily used for software interchange; or, 141 | 142 | b) Accompany it with a written offer, valid for at least three 143 | years, to give any third party, for a charge no more than your 144 | cost of physically performing source distribution, a complete 145 | machine-readable copy of the corresponding source code, to be 146 | distributed under the terms of Sections 1 and 2 above on a medium 147 | customarily used for software interchange; or, 148 | 149 | c) Accompany it with the information you received as to the offer 150 | to distribute corresponding source code. (This alternative is 151 | allowed only for noncommercial distribution and only if you 152 | received the program in object code or executable form with such 153 | an offer, in accord with Subsection b above.) 154 | 155 | The source code for a work means the preferred form of the work for 156 | making modifications to it. For an executable work, complete source 157 | code means all the source code for all modules it contains, plus any 158 | associated interface definition files, plus the scripts used to 159 | control compilation and installation of the executable. However, as a 160 | special exception, the source code distributed need not include 161 | anything that is normally distributed (in either source or binary 162 | form) with the major components (compiler, kernel, and so on) of the 163 | operating system on which the executable runs, unless that component 164 | itself accompanies the executable. 165 | 166 | If distribution of executable or object code is made by offering 167 | access to copy from a designated place, then offering equivalent 168 | access to copy the source code from the same place counts as 169 | distribution of the source code, even though third parties are not 170 | compelled to copy the source along with the object code. 171 | 172 | 4. You may not copy, modify, sublicense, or distribute the Program 173 | except as expressly provided under this License. Any attempt 174 | otherwise to copy, modify, sublicense or distribute the Program is 175 | void, and will automatically terminate your rights under this License. 176 | However, parties who have received copies, or rights, from you under 177 | this License will not have their licenses terminated so long as such 178 | parties remain in full compliance. 179 | 180 | 5. You are not required to accept this License, since you have not 181 | signed it. However, nothing else grants you permission to modify or 182 | distribute the Program or its derivative works. These actions are 183 | prohibited by law if you do not accept this License. Therefore, by 184 | modifying or distributing the Program (or any work based on the 185 | Program), you indicate your acceptance of this License to do so, and 186 | all its terms and conditions for copying, distributing or modifying 187 | the Program or works based on it. 188 | 189 | 6. Each time you redistribute the Program (or any work based on the 190 | Program), the recipient automatically receives a license from the 191 | original licensor to copy, distribute or modify the Program subject to 192 | these terms and conditions. You may not impose any further 193 | restrictions on the recipients' exercise of the rights granted herein. 194 | You are not responsible for enforcing compliance by third parties to 195 | this License. 196 | 197 | 7. If, as a consequence of a court judgment or allegation of patent 198 | infringement or for any other reason (not limited to patent issues), 199 | conditions are imposed on you (whether by court order, agreement or 200 | otherwise) that contradict the conditions of this License, they do not 201 | excuse you from the conditions of this License. If you cannot 202 | distribute so as to satisfy simultaneously your obligations under this 203 | License and any other pertinent obligations, then as a consequence you 204 | may not distribute the Program at all. For example, if a patent 205 | license would not permit royalty-free redistribution of the Program by 206 | all those who receive copies directly or indirectly through you, then 207 | the only way you could satisfy both it and this License would be to 208 | refrain entirely from distribution of the Program. 209 | 210 | If any portion of this section is held invalid or unenforceable under 211 | any particular circumstance, the balance of the section is intended to 212 | apply and the section as a whole is intended to apply in other 213 | circumstances. 214 | 215 | It is not the purpose of this section to induce you to infringe any 216 | patents or other property right claims or to contest validity of any 217 | such claims; this section has the sole purpose of protecting the 218 | integrity of the free software distribution system, which is 219 | implemented by public license practices. Many people have made 220 | generous contributions to the wide range of software distributed 221 | through that system in reliance on consistent application of that 222 | system; it is up to the author/donor to decide if he or she is willing 223 | to distribute software through any other system and a licensee cannot 224 | impose that choice. 225 | 226 | This section is intended to make thoroughly clear what is believed to 227 | be a consequence of the rest of this License. 228 | 229 | 8. If the distribution and/or use of the Program is restricted in 230 | certain countries either by patents or by copyrighted interfaces, the 231 | original copyright holder who places the Program under this License 232 | may add an explicit geographical distribution limitation excluding 233 | those countries, so that distribution is permitted only in or among 234 | countries not thus excluded. In such case, this License incorporates 235 | the limitation as if written in the body of this License. 236 | 237 | 9. The Free Software Foundation may publish revised and/or new versions 238 | of the General Public License from time to time. Such new versions will 239 | be similar in spirit to the present version, but may differ in detail to 240 | address new problems or concerns. 241 | 242 | Each version is given a distinguishing version number. If the Program 243 | specifies a version number of this License which applies to it and "any 244 | later version", you have the option of following the terms and conditions 245 | either of that version or of any later version published by the Free 246 | Software Foundation. If the Program does not specify a version number of 247 | this License, you may choose any version ever published by the Free Software 248 | Foundation. 249 | 250 | 10. If you wish to incorporate parts of the Program into other free 251 | programs whose distribution conditions are different, write to the author 252 | to ask for permission. For software which is copyrighted by the Free 253 | Software Foundation, write to the Free Software Foundation; we sometimes 254 | make exceptions for this. Our decision will be guided by the two goals 255 | of preserving the free status of all derivatives of our free software and 256 | of promoting the sharing and reuse of software generally. 257 | 258 | NO WARRANTY 259 | 260 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY 261 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN 262 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES 263 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED 264 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 265 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS 266 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE 267 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, 268 | REPAIR OR CORRECTION. 269 | 270 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 271 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR 272 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, 273 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING 274 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED 275 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY 276 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER 277 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE 278 | POSSIBILITY OF SUCH DAMAGES. 279 | 280 | END OF TERMS AND CONDITIONS 281 | 282 | How to Apply These Terms to Your New Programs 283 | 284 | If you develop a new program, and you want it to be of the greatest 285 | possible use to the public, the best way to achieve this is to make it 286 | free software which everyone can redistribute and change under these terms. 287 | 288 | To do so, attach the following notices to the program. It is safest 289 | to attach them to the start of each source file to most effectively 290 | convey the exclusion of warranty; and each file should have at least 291 | the "copyright" line and a pointer to where the full notice is found. 292 | 293 | 294 | Copyright (C) 295 | 296 | This program is free software; you can redistribute it and/or modify 297 | it under the terms of the GNU General Public License as published by 298 | the Free Software Foundation; either version 2 of the License, or 299 | (at your option) any later version. 300 | 301 | This program is distributed in the hope that it will be useful, 302 | but WITHOUT ANY WARRANTY; without even the implied warranty of 303 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 304 | GNU General Public License for more details. 305 | 306 | You should have received a copy of the GNU General Public License along 307 | with this program; if not, write to the Free Software Foundation, Inc., 308 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 309 | 310 | Also add information on how to contact you by electronic and paper mail. 311 | 312 | If the program is interactive, make it output a short notice like this 313 | when it starts in an interactive mode: 314 | 315 | Gnomovision version 69, Copyright (C) year name of author 316 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 317 | This is free software, and you are welcome to redistribute it 318 | under certain conditions; type `show c' for details. 319 | 320 | The hypothetical commands `show w' and `show c' should show the appropriate 321 | parts of the General Public License. Of course, the commands you use may 322 | be called something other than `show w' and `show c'; they could even be 323 | mouse-clicks or menu items--whatever suits your program. 324 | 325 | You should also get your employer (if you work as a programmer) or your 326 | school, if any, to sign a "copyright disclaimer" for the program, if 327 | necessary. Here is a sample; alter the names: 328 | 329 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program 330 | `Gnomovision' (which makes passes at compilers) written by James Hacker. 331 | 332 | , 1 April 1989 333 | Ty Coon, President of Vice 334 | 335 | This General Public License does not permit incorporating your program into 336 | proprietary programs. If your program is a subroutine library, you may 337 | consider it more useful to permit linking proprietary applications with the 338 | library. If this is what you want to do, use the GNU Lesser General 339 | Public License instead of this License. 340 | -------------------------------------------------------------------------------- /src/gui.c: -------------------------------------------------------------------------------- 1 | // 2 | // User interface code 3 | // 4 | 5 | #include "patch.h" 6 | 7 | #define ID_WINDOW_UPDATE_TIMER 1001 8 | #define ID_THREAD_LIST_BOX 2000 9 | #define ID_MEMORY_LIST_BOX 2001 10 | #define ID_STACK_LIST_BOX 2002 11 | #define ID_DISASSEMBLY_LIST_BOX 2003 12 | #define ID_MEMORY_SCROLLBAR 3001 13 | #define ID_STACK_SCROLLBAR 3002 14 | #define ID_DISASSEMBLY_SCROLLBAR 3003 15 | #define ID_BUTTON_DUMP_STACK 9000 16 | #define ID_BUTTON_DUMP_CODE 9001 17 | #define ID_BUTTON_DUMP_LOCAL 9002 18 | #define ID_BUTTON_HALT 9003 19 | #define ID_BUTTON_STEP 9004 20 | #define ID_BUTTON_BREAKPOINTS 9005 21 | 22 | HMODULE gDllHModule; 23 | HWND gDebuggerWindow; 24 | ATOM gHWndClassAtom; 25 | HFONT gFont; 26 | 27 | bool initialised = false; 28 | 29 | HWND gGUIThreadCount; 30 | HWND gGUITextArea; 31 | 32 | // Buttons 33 | HWND gDumpStackButton; 34 | HWND gDumpCodeButton; 35 | HWND gDumpLocalButton; 36 | HWND gHaltButton; 37 | HWND gStepButton; 38 | HWND gBreakpointsButton; 39 | 40 | // Disassembly 41 | HWND gDisassemblyList; 42 | HWND gDisassemblyScrollbar; 43 | HWND gLocalMemoryList; 44 | HWND gLocalMemoryScrollbar; 45 | HWND gStackList; 46 | HWND gStackScrollbar; 47 | 48 | // Thread list 49 | HWND gThreadListBox; 50 | VMThread_t curThreadCopy; // Copy of the thread to prevent redraw of unchanged fields (can cause flickering otherwise) 51 | VMThread_t* curThreadPtr; // Pointer to the actual thread being displayed 52 | VMThread_t* threadList[256]; // Threads as show in the thread list 53 | int gThreadListCount = 0; // Number of threads in the list 54 | 55 | // Program name 56 | HWND gProgramLabel; 57 | 58 | struct ThreadList; 59 | typedef struct ThreadList 60 | { 61 | VMThread_t* thread; 62 | uint32_t threadId; 63 | struct ThreadList* next; 64 | struct ThreadList* prev; 65 | } ThreadList_t; 66 | 67 | ThreadList_t vmThreads; 68 | ThreadList_t* lastThread; 69 | Disasm_t* disassembly; 70 | 71 | void freeThreadEntry(ThreadList_t* entry) 72 | { 73 | // Remove from list 74 | if(entry->next) 75 | entry->next->prev = entry->prev; 76 | if(entry->prev) 77 | entry->prev->next = entry->next; 78 | if(entry == lastThread) 79 | lastThread = entry->prev; 80 | free(entry); 81 | } 82 | 83 | ThreadList_t* addThreadEntry(VMThread_t* t) 84 | { 85 | ThreadList_t* newEntry = (ThreadList_t*)malloc(sizeof(ThreadList_t)); 86 | lastThread->next = newEntry; 87 | newEntry->prev = lastThread; 88 | newEntry->next = NULL; 89 | newEntry->thread = t; 90 | newEntry->threadId = t->threadId; 91 | return newEntry; 92 | } 93 | 94 | void updateThreadLists() 95 | { 96 | if(!*gVMThread) return; 97 | 98 | // First time updating? 99 | if(vmThreads.thread == NULL) 100 | { 101 | vmThreads.thread = *gVMThread; 102 | vmThreads.threadId = vmThreads.thread->threadId; 103 | vmThreads.next = NULL; 104 | vmThreads.prev = NULL; 105 | lastThread = &vmThreads; 106 | } 107 | 108 | ThreadList_t* l; 109 | VMThread_t* t; 110 | 111 | // Check that no threads were deleted 112 | l = &vmThreads; 113 | while(l) 114 | { 115 | bool found = false; 116 | t = *gVMThread; 117 | while(t) 118 | { 119 | if(l->thread == t && l->threadId == t->threadId) 120 | { 121 | found = true; 122 | break; 123 | } 124 | t = t->nextThread; 125 | } 126 | ThreadList_t* n = l->next; 127 | if(!found) 128 | { 129 | // This entry was deleted. 130 | freeThreadEntry(l); 131 | } 132 | l = n; 133 | } 134 | 135 | // Check for new threads 136 | t = *gVMThread; 137 | while(t) 138 | { 139 | bool found = false; 140 | l = &vmThreads; 141 | ThreadList_t* entry; 142 | while(l) 143 | { 144 | if(l->thread == t && l->threadId == t->threadId) 145 | { 146 | entry = l; 147 | found = true; 148 | break; 149 | } 150 | l = l->next; 151 | } 152 | VMThread_t* n = t->nextThread; 153 | if(!found) 154 | { 155 | // This entry is new. 156 | l = addThreadEntry(t); 157 | } 158 | // Disassemble any new programs that may have appeared 159 | //disassemblePrograms(l); 160 | t = n; 161 | } 162 | } 163 | 164 | struct VMThreadLabels 165 | { 166 | HWND programIdLabel; 167 | HWND programIdValue; 168 | HWND threadIdLabel; 169 | HWND threadIdValue; 170 | HWND nextThreadLabel; 171 | HWND nextThreadValue; 172 | HWND flagsLabel; 173 | HWND flagsValue; 174 | HWND stackPointerLabel; 175 | HWND stackPointerValue; 176 | HWND instructionPointerLabel; 177 | HWND instructionPointerValue; 178 | HWND programCounterLabel; 179 | HWND programCounterValue; 180 | HWND memPtrLabel; 181 | HWND memPtrValue; 182 | HWND stackSizeLabel; 183 | HWND stackSizeValue; 184 | HWND stackMemConfigLabel; 185 | HWND stackMemConfigValue; 186 | HWND stackLabel; 187 | HWND stackValue; 188 | HWND codeSpaceSizeLabel; 189 | HWND codeSpaceSizeValue; 190 | HWND codeSpaceMemConfigLabel; 191 | HWND codeSpaceMemConfigValue; 192 | HWND codeSpaceLabel; 193 | HWND codeSpaceValue; 194 | HWND programListLabel; 195 | HWND programListValue; 196 | HWND programCountLabel; 197 | HWND programCountValue; 198 | HWND codeSpaceTopLabel; 199 | HWND codeSpaceTopValue; 200 | HWND localMemSizeLabel; 201 | HWND localMemSizeValue; 202 | HWND localMemConfigLabel; 203 | HWND localMemConfigValue; 204 | HWND localMemLabel; 205 | HWND localMemValue; 206 | HWND unknownStructLabel; 207 | HWND unknownStructValue; 208 | HWND field_0x54Label; 209 | HWND field_0x54Value; 210 | HWND field_0x58Label; 211 | HWND field_0x58Value; 212 | HWND field_0x5cLabel; 213 | HWND field_0x5cValue; 214 | HWND field_0x60Label; 215 | HWND field_0x60Value; 216 | }; 217 | struct VMThreadLabels vmInfo; 218 | 219 | BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) 220 | { 221 | switch(ul_reason_for_call) 222 | { 223 | case DLL_PROCESS_ATTACH: 224 | case DLL_THREAD_ATTACH: 225 | gDllHModule = hModule; 226 | createDebugWindow(); 227 | break; 228 | case DLL_THREAD_DETACH: 229 | case DLL_PROCESS_DETACH: 230 | shutdownDebugger(); 231 | break; 232 | } 233 | return true; 234 | } 235 | 236 | uint8_t memoryViewBuffer[0x100]; 237 | off_t memoryOffset; 238 | uint32_t prevMemorySize = -1; 239 | void updateMemoryList(VMThread_t* thread) 240 | { 241 | int size = thread->localMemSize / 16; 242 | if(size > 0x10) 243 | size = 0x10; 244 | 245 | // No local memory 246 | if(size == 0) 247 | SendMessage(gLocalMemoryList, LB_RESETCONTENT, 0, 0); 248 | 249 | SCROLLINFO s; 250 | s.cbSize = sizeof(SCROLLINFO); 251 | s.fMask = SIF_POS; 252 | GetScrollInfo(gLocalMemoryScrollbar, SB_CTL, &s); 253 | off_t newOffset = s.nPos * 16; 254 | 255 | uint8_t* ptr = thread->localMem + newOffset; 256 | 257 | // Memory size changed 258 | if(thread->localMemSize != prevMemorySize) 259 | { 260 | prevMemorySize = thread->localMemSize; 261 | s.fMask = SIF_PAGE | SIF_RANGE; 262 | s.nMin = 0; 263 | s.nMax = (prevMemorySize/16) - 1; 264 | s.nPage = 16; 265 | s.nPos = 0; 266 | s.nTrackPos = 0; 267 | SetScrollInfo(gLocalMemoryScrollbar, SB_CTL, &s, true); 268 | } 269 | // Memory has not changed, no need to update. 270 | else if(size == 0 || (newOffset == memoryOffset && memcmp(ptr, &memoryViewBuffer[0], size*16) == 0)) 271 | return; 272 | 273 | memoryOffset = newOffset; 274 | 275 | char memStr[64]; 276 | 277 | SendMessage(gLocalMemoryList, LB_RESETCONTENT, 0, 0); 278 | memcpy(&memoryViewBuffer[0], ptr, size*16); 279 | 280 | for(int i = 0; i < size; i++) 281 | { 282 | uint8_t* ptr = &memoryViewBuffer[i*16]; 283 | sprintf( 284 | &memStr[0], 285 | "%.8LX: %.2X%.2X%.2X%.2X %.2X%.2X%.2X%.2X %.2X%.2X%.2X%.2X %.2X%.2X%.2X%.2X", 286 | memoryOffset+(i*16), 287 | ptr[0], ptr[1], ptr[2], ptr[3], 288 | ptr[4], ptr[5], ptr[6], ptr[7], 289 | ptr[8], ptr[9], ptr[10], ptr[11], 290 | ptr[12], ptr[13], ptr[14], ptr[15] 291 | ); 292 | SendMessage(gLocalMemoryList, LB_INSERTSTRING, i, (WPARAM)&memStr[0]); 293 | } 294 | } 295 | 296 | uint32_t prevStackSize = -1; 297 | void updateStackList(VMThread_t* thread) 298 | { 299 | SendMessage(gStackList, LB_RESETCONTENT, 0, 0); 300 | 301 | SCROLLINFO s; 302 | s.cbSize = sizeof(SCROLLINFO); 303 | s.fMask = SIF_POS; 304 | GetScrollInfo(gStackScrollbar, SB_CTL, &s); 305 | 306 | // Set scrollbar size 307 | if(thread->stackPointer != prevStackSize) 308 | { 309 | int diff = thread->stackPointer - prevStackSize; 310 | if(!s.nPos || diff + s.nPos < 0) 311 | s.nPos = 0; 312 | else 313 | s.nPos += diff; 314 | s.fMask = SIF_PAGE | SIF_RANGE | SIF_POS; 315 | s.nMin = 0; 316 | s.nMax = thread->stackPointer; 317 | s.nPage = 34; 318 | s.nTrackPos = 0; 319 | SetScrollInfo(gStackScrollbar, SB_CTL, &s, true); 320 | prevStackSize = thread->stackPointer; 321 | } 322 | 323 | // Don't attempt to add any stack elements if there are none 324 | if(thread->stackSize == 0 || thread->stackPointer == 0) 325 | return; 326 | 327 | uint32_t stackPointer = thread->stackPointer - 1; 328 | 329 | stackPointer += s.nPos; 330 | 331 | char memStr[32]; 332 | for(int i = 0; i < 34; i++) 333 | { 334 | sprintf( 335 | &memStr[0], 336 | "%.8LX: %.8LX", 337 | stackPointer, 338 | thread->stack[stackPointer] 339 | ); 340 | SendMessage(gStackList, LB_INSERTSTRING, i, (WPARAM)&memStr[0]); 341 | if(stackPointer == 0) 342 | break; 343 | stackPointer--; 344 | } 345 | } 346 | 347 | VMProgramList_t* getCurrentProgram(VMThread_t* thread) 348 | { 349 | VMProgramList_t* p = thread->programList; 350 | while(p) 351 | { 352 | if(thread->programCounter >= p->location && 353 | thread->programCounter < p->location + p->size) 354 | return p; 355 | p = p->prevProgram; 356 | } 357 | return NULL; 358 | } 359 | 360 | DisasmLine_t* findCurrentLine(VMThread_t* thread, Disasm_t* disasm) 361 | { 362 | uint32_t ppos = thread->programCounter; 363 | DisasmLine_t* start = disasm->disasm; 364 | DisasmLine_t* cur = disasm->disasm; 365 | int count = 0; 366 | while(cur) 367 | { 368 | if(cur->location == ppos) 369 | break; 370 | count++; 371 | if(count > 7) 372 | start = start->next; 373 | cur = cur->next; 374 | } 375 | return start; 376 | } 377 | 378 | void updateDisassembly(VMThread_t* curThreadPtr) 379 | { 380 | VMProgramList_t* p = getCurrentProgram(curThreadPtr); 381 | SendMessage(gDisassemblyList, LB_RESETCONTENT, 0, 0); 382 | if(p == NULL) 383 | { 384 | return; 385 | } 386 | if(!disassembly || disassembly->program != p) 387 | { 388 | if(disassembly) 389 | freeDisassemblies(disassembly); 390 | disassembly = disassembleProgram(curThreadPtr, p); 391 | } 392 | 393 | uint32_t ppos = curThreadPtr->programCounter; 394 | DisasmLine_t* line = findCurrentLine(curThreadPtr, disassembly); 395 | int highlight = 0; 396 | for(int i = 0; i < 16; i++) 397 | { 398 | if(!line) break; 399 | SendMessage(gDisassemblyList, LB_INSERTSTRING, i, (WPARAM)line->str); 400 | if(line->location == ppos) 401 | highlight = i + 1; 402 | line = line->next; 403 | } 404 | SendMessage(gDisassemblyList, LB_SETCURSEL, highlight, 0); 405 | } 406 | 407 | VMThread_t* prevSelectedThread = NULL; 408 | void updateWindow() 409 | { 410 | //updateThreadLists(); 411 | if(*gVMThread) 412 | { 413 | bool mustUpdate = false; 414 | int oldCount = gThreadListCount; 415 | gThreadListCount = 0; 416 | VMThread_t* thread = *gVMThread; 417 | 418 | // Get list of threads 419 | while(thread) 420 | { 421 | // If this entry had changed, we must redraw 422 | if(threadList[gThreadListCount] != thread) 423 | mustUpdate = true; 424 | threadList[gThreadListCount] = thread; 425 | gThreadListCount++; 426 | thread = thread->nextThread; 427 | } 428 | // If the total count has changed, we must redraw 429 | mustUpdate = mustUpdate || oldCount != gThreadListCount || prevSelectedThread != curThreadPtr; 430 | prevSelectedThread = curThreadPtr; 431 | 432 | // Re-draw the list if anything has changed 433 | if(mustUpdate) 434 | { 435 | int selectedThread = -1; 436 | 437 | // Delete previous content 438 | SendMessage(gThreadListBox, LB_RESETCONTENT, 0, 0); 439 | 440 | // Create new list 441 | for(int i = 0; i < gThreadListCount; i++) 442 | { 443 | char listText[64]; 444 | sprintf(&listText[0], "Thread %d", threadList[i]->threadId); 445 | SendMessage(gThreadListBox, LB_INSERTSTRING, i, (LPARAM)&listText[0]); 446 | 447 | // Get selected thread list index 448 | if(threadList[i] == curThreadPtr) 449 | selectedThread = i; 450 | } 451 | 452 | // If the current thread was not found, it must be deleted. Reset to the global thread. 453 | if(selectedThread == -1) 454 | { 455 | curThreadPtr = *gVMThread; 456 | SendMessage(gThreadListBox, LB_SETCURSEL, 0, 0); 457 | } 458 | // Otherwise, highlight the current thread 459 | else 460 | SendMessage(gThreadListBox, LB_SETCURSEL, selectedThread, 0); 461 | } 462 | } 463 | else 464 | curThreadPtr = NULL; 465 | 466 | // Update fields 467 | if(curThreadPtr) 468 | { 469 | updateVMInfo(curThreadPtr); 470 | updateMemoryList(curThreadPtr); 471 | updateStackList(curThreadPtr); 472 | updateDisassembly(curThreadPtr); 473 | } 474 | } 475 | 476 | bool dumpStack() 477 | { 478 | FILE* dumpFile = fopen("stack.bin", "wb"); 479 | if(!dumpFile) 480 | return false; 481 | 482 | fwrite(curThreadPtr->stack, 4, curThreadPtr->stackSize, dumpFile); 483 | fclose(dumpFile); 484 | return true; 485 | } 486 | 487 | bool dumpCode() 488 | { 489 | FILE* dumpFile = fopen("code.bin", "wb"); 490 | if(!dumpFile) 491 | return false; 492 | 493 | fwrite(curThreadPtr->codeSpace, 1, curThreadPtr->codeSpaceSize, dumpFile); 494 | fclose(dumpFile); 495 | return true; 496 | } 497 | 498 | bool dumpLocal() 499 | { 500 | FILE* dumpFile = fopen("local.bin", "wb"); 501 | if(!dumpFile) 502 | return false; 503 | 504 | fwrite(curThreadPtr->localMem, 1, curThreadPtr->localMemSize, dumpFile); 505 | fclose(dumpFile); 506 | return true; 507 | } 508 | 509 | void doHaltExecution(int stopped) 510 | { 511 | gHaltExecution = stopped; 512 | SetWindowTextA(gHaltButton, stopped ? "Run" : "Halt"); 513 | } 514 | 515 | LRESULT WINAPI DLLWindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) 516 | { 517 | VMThread_t* myThread; 518 | switch(msg) 519 | { 520 | case WM_DESTROY: 521 | PostQuitMessage(0); 522 | break; 523 | 524 | case WM_TIMER: 525 | if(wParam == ID_WINDOW_UPDATE_TIMER) 526 | { 527 | updateWindow(); 528 | } 529 | 530 | case WM_CREATE: 531 | break; 532 | 533 | case WM_COMMAND: 534 | switch(LOWORD(wParam)) 535 | { 536 | case ID_BUTTON_DUMP_STACK: 537 | if(dumpStack()) 538 | MessageBoxA(NULL, "Stack was dumped to file", "Dump", 0); 539 | else 540 | MessageBoxA(NULL, "Failed to dump stack", "Dump", 0); 541 | break; 542 | 543 | case ID_BUTTON_DUMP_CODE: 544 | if(dumpCode()) 545 | MessageBoxA(NULL, "Code was dumped to file", "Dump", 0); 546 | else 547 | MessageBoxA(NULL, "Failed to dump code", "Dump", 0); 548 | break; 549 | 550 | case ID_BUTTON_DUMP_LOCAL: 551 | if(dumpLocal()) 552 | MessageBoxA(NULL, "Local memory was dumped to file", "Dump", 0); 553 | else 554 | MessageBoxA(NULL, "Failed to dump local memory", "Dump", 0); 555 | break; 556 | 557 | case ID_BUTTON_HALT: 558 | doHaltExecution(gHaltExecution ^ 1); 559 | break; 560 | 561 | case ID_BUTTON_STEP: 562 | if(!gHaltExecution) 563 | doHaltExecution(1); 564 | gStepThread = curThreadPtr->threadId; 565 | gStepExecution = 1; 566 | break; 567 | 568 | case ID_BUTTON_BREAKPOINTS: 569 | showBreakpointsWindow(); 570 | break; 571 | 572 | case ID_THREAD_LIST_BOX: 573 | switch(HIWORD(wParam)) 574 | { 575 | case LBN_SELCHANGE: 576 | { 577 | int index = SendMessage(gThreadListBox, LB_GETCARETINDEX, 0, 0); 578 | curThreadPtr = threadList[index]; 579 | if(curThreadPtr) 580 | updateWindow(); 581 | break; 582 | } 583 | } 584 | break; 585 | } 586 | break; 587 | 588 | case WM_VSCROLL: 589 | { 590 | SCROLLINFO si; 591 | si.cbSize = sizeof(si); 592 | si.fMask = SIF_ALL; 593 | GetScrollInfo((HWND)lParam, SB_CTL, &si); 594 | 595 | // Save the position for comparison later on. 596 | int yPos = si.nPos; 597 | switch (LOWORD(wParam)) 598 | { 599 | // User clicked the top arrow. 600 | case SB_LINEUP: 601 | si.nPos -= 1; 602 | break; 603 | 604 | // User clicked the bottom arrow. 605 | case SB_LINEDOWN: 606 | si.nPos += 1; 607 | break; 608 | 609 | // User clicked the scroll bar shaft above the scroll box. 610 | case SB_PAGEUP: 611 | si.nPos -= si.nPage; 612 | break; 613 | 614 | // User clicked the scroll bar shaft below the scroll box. 615 | case SB_PAGEDOWN: 616 | si.nPos += si.nPage; 617 | break; 618 | 619 | // User dragged the scroll box. 620 | case SB_THUMBTRACK: 621 | si.nPos = si.nTrackPos; 622 | break; 623 | 624 | default: 625 | break; 626 | } 627 | 628 | // Set the position and then retrieve it. Due to adjustments 629 | // by Windows it may not be the same as the value set. 630 | si.fMask = SIF_POS; 631 | SetScrollInfo((HWND)lParam, SB_CTL, &si, TRUE); 632 | GetScrollInfo((HWND)lParam, SB_CTL, &si); 633 | 634 | // If the position has changed, scroll window and update it. 635 | if(si.nPos != yPos) 636 | { 637 | 638 | } 639 | break; 640 | } 641 | 642 | default: 643 | return DefWindowProc(hwnd, msg, wParam, lParam); 644 | } 645 | 646 | return 0; 647 | } 648 | 649 | void createValueLabel(int x, int* y, HWND* label, HWND* value, char* text) 650 | { 651 | *label = CreateWindowA( 652 | "static", text, 653 | WS_CHILD | WS_VISIBLE, 654 | x, *y, 200, 16, 655 | gDebuggerWindow, (HMENU)1, NULL, NULL 656 | ); 657 | *value = CreateWindowA( 658 | "static", "?", 659 | WS_CHILD | WS_VISIBLE, 660 | x+200, *y, 70, 16, 661 | gDebuggerWindow, (HMENU)1, NULL, NULL 662 | ); 663 | if(!*label || !*value) 664 | fatalError(text); 665 | SendMessage(*label, WM_SETFONT, (WPARAM)gFont, true); 666 | SendMessage(*value, WM_SETFONT, (WPARAM)gFont, true); 667 | *y += 16; 668 | } 669 | 670 | void updateValue(HWND hwnd, uint32_t value) 671 | { 672 | char str[32]; 673 | sprintf(&str[0], "%.8LX", value); 674 | SetWindowTextA(hwnd, &str[0]); 675 | } 676 | 677 | void updateVMInfo(VMThread_t* thread) 678 | { 679 | if(curThreadCopy.programId != thread->programId) 680 | updateValue(vmInfo.programIdValue, (uint32_t)thread->programId); 681 | if(curThreadCopy.threadId != thread->threadId) 682 | updateValue(vmInfo.threadIdValue, (uint32_t)thread->threadId); 683 | if(curThreadCopy.nextThread != thread->nextThread) 684 | updateValue(vmInfo.nextThreadValue, (uint32_t)thread->nextThread); 685 | if(curThreadCopy.flags != thread->flags) 686 | updateValue(vmInfo.flagsValue, (uint32_t)thread->flags); 687 | if(curThreadCopy.stackPointer != thread->stackPointer) 688 | updateValue(vmInfo.stackPointerValue, (uint32_t)thread->stackPointer); 689 | if(curThreadCopy.instructionPointer != thread->instructionPointer) 690 | updateValue(vmInfo.instructionPointerValue, (uint32_t)thread->instructionPointer); 691 | if(curThreadCopy.programCounter != thread->programCounter) 692 | updateValue(vmInfo.programCounterValue, (uint32_t)thread->programCounter); 693 | if(curThreadCopy.memPtr != thread->memPtr) 694 | updateValue(vmInfo.memPtrValue, (uint32_t)thread->memPtr); 695 | if(curThreadCopy.stackSize != thread->stackSize) 696 | updateValue(vmInfo.stackSizeValue, (uint32_t)thread->stackSize); 697 | if(curThreadCopy.stackMemConfig != thread->stackMemConfig) 698 | updateValue(vmInfo.stackMemConfigValue, (uint32_t)thread->stackMemConfig); 699 | if(curThreadCopy.stack != thread->stack) 700 | updateValue(vmInfo.stackValue, (uint32_t)thread->stack); 701 | if(curThreadCopy.codeSpaceSize != thread->codeSpaceSize) 702 | updateValue(vmInfo.codeSpaceSizeValue, (uint32_t)thread->codeSpaceSize); 703 | if(curThreadCopy.codeSpaceMemConfig != thread->codeSpaceMemConfig) 704 | updateValue(vmInfo.codeSpaceMemConfigValue, (uint32_t)thread->codeSpaceMemConfig); 705 | if(curThreadCopy.codeSpace != thread->codeSpace) 706 | updateValue(vmInfo.codeSpaceValue, (uint32_t)thread->codeSpace); 707 | if(curThreadCopy.programList != thread->programList) 708 | updateValue(vmInfo.programListValue, (uint32_t)thread->programList); 709 | if(curThreadCopy.programCount != thread->programCount) 710 | updateValue(vmInfo.programCountValue, (uint32_t)thread->programCount); 711 | if(curThreadCopy.codeSpaceTop != thread->codeSpaceTop) 712 | updateValue(vmInfo.codeSpaceTopValue, (uint32_t)thread->codeSpaceTop); 713 | if(curThreadCopy.localMemSize != thread->localMemSize) 714 | updateValue(vmInfo.localMemSizeValue, (uint32_t)thread->localMemSize); 715 | if(curThreadCopy.localMemConfig != thread->localMemConfig) 716 | updateValue(vmInfo.localMemConfigValue, (uint32_t)thread->localMemConfig); 717 | if(curThreadCopy.localMem != thread->localMem) 718 | updateValue(vmInfo.localMemValue, (uint32_t)thread->localMem); 719 | if(curThreadCopy.unknownStruct != thread->unknownStruct) 720 | updateValue(vmInfo.unknownStructValue, (uint32_t)thread->unknownStruct); 721 | if(curThreadCopy.field_0x54 != thread->field_0x54) 722 | updateValue(vmInfo.field_0x54Value, (uint32_t)thread->field_0x54); 723 | if(curThreadCopy.field_0x58 != thread->field_0x58) 724 | updateValue(vmInfo.field_0x58Value, (uint32_t)thread->field_0x58); 725 | if(curThreadCopy.field_0x5c != thread->field_0x5c) 726 | updateValue(vmInfo.field_0x5cValue, (uint32_t)thread->field_0x5c); 727 | if(curThreadCopy.field_0x60 != thread->field_0x60) 728 | updateValue(vmInfo.field_0x60Value, (uint32_t)thread->field_0x60); 729 | 730 | // Find program name 731 | char* programName = NULL; 732 | VMProgramList_t* program = thread->programList; 733 | while(program) 734 | { 735 | if(program->location <= thread->instructionPointer && 736 | program->location + program->size >= thread->instructionPointer) 737 | { 738 | programName = program->filename; 739 | break; 740 | } 741 | program = program->prevProgram; 742 | } 743 | char pStr[128]; 744 | snprintf(&pStr[0], 128, "Program: %s", programName ? programName : "?"); 745 | SetWindowTextA(gProgramLabel, &pStr[0]); 746 | 747 | // Copy the current state of the thread 748 | memcpy(&curThreadCopy, thread, sizeof(VMThread_t)); 749 | } 750 | 751 | HWND makeButton(char* title, HWND wnd, int x, int y, int width, int height, int id) 752 | { 753 | HWND button = CreateWindow( 754 | "BUTTON", title, 755 | WS_TABSTOP | WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON, 756 | x, y, 757 | width, height, 758 | wnd, 759 | (HMENU)id, 760 | gDllHModule, NULL 761 | ); 762 | SendMessage(button, WM_SETFONT, (WPARAM)gFont, true); 763 | return button; 764 | } 765 | 766 | bool createDebugWindow() 767 | { 768 | if(initialised) 769 | return true; 770 | 771 | memset(&curThreadCopy, 0xFF, sizeof(VMThread_t)); 772 | 773 | WNDCLASSEXA wclass; 774 | wclass.cbSize = sizeof(WNDCLASSEXA); 775 | wclass.style = CS_OWNDC; 776 | wclass.lpfnWndProc = DLLWindowProc; 777 | wclass.cbClsExtra = 0; 778 | wclass.cbWndExtra = 0; 779 | wclass.hInstance = gDllHModule; 780 | wclass.hIcon = LoadIcon(NULL, IDI_APPLICATION); 781 | wclass.hCursor = LoadCursor(NULL, IDC_ARROW); 782 | wclass.hbrBackground = (HBRUSH)COLOR_APPWORKSPACE; 783 | wclass.lpszMenuName = NULL; 784 | wclass.lpszClassName = "classPatchDebugger"; 785 | wclass.hIconSm = LoadIcon(NULL, IDI_APPLICATION); 786 | gHWndClassAtom = RegisterClassExA(&wclass); 787 | if(!gHWndClassAtom) 788 | { 789 | fatalError("RegisterClassExA"); 790 | return false; 791 | } 792 | 793 | gDebuggerWindow = CreateWindowExA( 794 | 0, 795 | (LPCSTR)gHWndClassAtom, 796 | "Debugger", 797 | WS_OVERLAPPEDWINDOW, 798 | CW_USEDEFAULT, CW_USEDEFAULT, 799 | 1000, 600, 800 | NULL, NULL, 801 | gDllHModule, NULL 802 | ); 803 | if(!gDebuggerWindow) 804 | { 805 | fatalError("CreateWindowExA"); 806 | return false; 807 | } 808 | 809 | gFont = CreateFontA( 810 | 16, 0, 811 | 0, 0, FW_REGULAR, 812 | false, false, false, 813 | ANSI_CHARSET, 814 | OUT_TT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, 815 | FIXED_PITCH | FF_MODERN, NULL 816 | ); 817 | SendMessage(gDebuggerWindow, WM_SETFONT, (WPARAM)gFont, true); 818 | 819 | 820 | // 821 | // Create thread info fields 822 | // 823 | int y = 10; 824 | createValueLabel(120, &y, &vmInfo.programIdLabel, &vmInfo.programIdValue, "programId"); 825 | createValueLabel(120, &y, &vmInfo.threadIdLabel, &vmInfo.threadIdValue, "threadId"); 826 | createValueLabel(120, &y, &vmInfo.nextThreadLabel, &vmInfo.nextThreadValue, "nextThread"); 827 | createValueLabel(120, &y, &vmInfo.flagsLabel, &vmInfo.flagsValue, "flags"); 828 | createValueLabel(120, &y, &vmInfo.stackPointerLabel, &vmInfo.stackPointerValue, "stackPointer"); 829 | createValueLabel(120, &y, &vmInfo.instructionPointerLabel, &vmInfo.instructionPointerValue, "instructionPointer"); 830 | createValueLabel(120, &y, &vmInfo.programCounterLabel, &vmInfo.programCounterValue, "programCounter"); 831 | createValueLabel(120, &y, &vmInfo.memPtrLabel, &vmInfo.memPtrValue, "memPtr"); 832 | createValueLabel(120, &y, &vmInfo.stackSizeLabel, &vmInfo.stackSizeValue, "stackSize"); 833 | createValueLabel(120, &y, &vmInfo.stackMemConfigLabel, &vmInfo.stackMemConfigValue, "stackMemConfig"); 834 | createValueLabel(120, &y, &vmInfo.stackLabel, &vmInfo.stackValue, "stack"); 835 | createValueLabel(120, &y, &vmInfo.codeSpaceSizeLabel, &vmInfo.codeSpaceSizeValue, "codeSpaceSize"); 836 | createValueLabel(120, &y, &vmInfo.codeSpaceMemConfigLabel, &vmInfo.codeSpaceMemConfigValue, "codeSpaceMemConfig"); 837 | createValueLabel(120, &y, &vmInfo.codeSpaceLabel, &vmInfo.codeSpaceValue, "codeSpace"); 838 | createValueLabel(120, &y, &vmInfo.programListLabel, &vmInfo.programListValue, "programList"); 839 | createValueLabel(120, &y, &vmInfo.programCountLabel, &vmInfo.programCountValue, "programCount"); 840 | createValueLabel(120, &y, &vmInfo.codeSpaceTopLabel, &vmInfo.codeSpaceTopValue, "codeSpaceTop"); 841 | createValueLabel(120, &y, &vmInfo.localMemSizeLabel, &vmInfo.localMemSizeValue, "localMemSize"); 842 | createValueLabel(120, &y, &vmInfo.localMemConfigLabel, &vmInfo.localMemConfigValue, "localMemConfig"); 843 | createValueLabel(120, &y, &vmInfo.localMemLabel, &vmInfo.localMemValue, "localMem"); 844 | createValueLabel(120, &y, &vmInfo.unknownStructLabel, &vmInfo.unknownStructValue, "unknownStruct"); 845 | createValueLabel(120, &y, &vmInfo.field_0x54Label, &vmInfo.field_0x54Value, "field_0x54"); 846 | createValueLabel(120, &y, &vmInfo.field_0x58Label, &vmInfo.field_0x58Value, "field_0x58"); 847 | createValueLabel(120, &y, &vmInfo.field_0x5cLabel, &vmInfo.field_0x5cValue, "field_0x5c"); 848 | createValueLabel(120, &y, &vmInfo.field_0x60Label, &vmInfo.field_0x60Value, "field_0x60"); 849 | 850 | gProgramLabel = CreateWindowA( 851 | "static", "Program: ?", 852 | WS_CHILD | WS_VISIBLE, 853 | 120, y, 270, 16, 854 | gDebuggerWindow, (HMENU)1, NULL, NULL 855 | ); 856 | SendMessage(gProgramLabel, WM_SETFONT, (WPARAM)gFont, true); 857 | 858 | // 859 | // Create buttons 860 | // 861 | int btnY = 310; 862 | gDumpStackButton = makeButton("Dump Stack", gDebuggerWindow, 10, btnY, 100, 30, ID_BUTTON_DUMP_STACK); 863 | btnY += 40; 864 | gDumpLocalButton = makeButton("Dump Code", gDebuggerWindow, 10, btnY, 100, 30, ID_BUTTON_DUMP_CODE); 865 | btnY += 40; 866 | gDumpLocalButton = makeButton("Dump Local", gDebuggerWindow, 10, btnY, 100, 30, ID_BUTTON_DUMP_LOCAL); 867 | btnY += 40; 868 | gHaltButton = makeButton(gHaltExecution ? "Run" : "Halt", gDebuggerWindow, 10, btnY, 100, 30, ID_BUTTON_HALT); 869 | btnY += 40; 870 | gStepButton = makeButton("Step", gDebuggerWindow, 10, btnY, 100, 30, ID_BUTTON_STEP); 871 | btnY += 40; 872 | gBreakpointsButton = makeButton("Breakpoints", gDebuggerWindow, 10, btnY, 100, 30, ID_BUTTON_BREAKPOINTS); 873 | btnY += 40; 874 | 875 | // 876 | // Create thread list 877 | // 878 | gThreadListBox = CreateWindowEx( 879 | WS_EX_CLIENTEDGE, 880 | "LISTBOX", NULL, 881 | WS_VISIBLE | WS_CHILD | LBS_STANDARD | LBS_NOTIFY, 882 | 10, 10, 883 | 100, 300, 884 | gDebuggerWindow, 885 | (HMENU)ID_THREAD_LIST_BOX, 886 | gDllHModule, NULL 887 | ); 888 | SendMessage(gThreadListBox, WM_SETFONT, (WPARAM)gFont, true); 889 | 890 | // Memory view 891 | gLocalMemoryList = CreateWindowEx( 892 | WS_EX_CLIENTEDGE, 893 | "LISTBOX", NULL, 894 | WS_VISIBLE | WS_CHILD | LBS_STANDARD | LBS_NOTIFY | WS_VSCROLL, 895 | 400, 298, 896 | 380, 262, 897 | gDebuggerWindow, 898 | (HMENU)ID_MEMORY_LIST_BOX, 899 | gDllHModule, NULL 900 | ); 901 | SendMessage(gLocalMemoryList, WM_SETFONT, (WPARAM)gFont, true); 902 | gLocalMemoryScrollbar = CreateWindow( 903 | "SCROLLBAR", NULL, 904 | WS_VISIBLE | WS_CHILD | SBS_VERT, 905 | 400+380, 298, 906 | 18, 262, 907 | gDebuggerWindow, 908 | (HMENU)ID_MEMORY_SCROLLBAR, 909 | gDllHModule, NULL 910 | ); 911 | 912 | // Stack view 913 | gStackList = CreateWindowEx( 914 | WS_EX_CLIENTEDGE, 915 | "LISTBOX", NULL, 916 | WS_VISIBLE | WS_CHILD | LBS_STANDARD | LBS_NOTIFY | WS_VSCROLL, 917 | 803, 10, 918 | 150, 550, 919 | gDebuggerWindow, 920 | (HMENU)ID_STACK_LIST_BOX, 921 | gDllHModule, NULL 922 | ); 923 | SendMessage(gStackList, WM_SETFONT, (WPARAM)gFont, true); 924 | gStackScrollbar = CreateWindow( 925 | "SCROLLBAR", NULL, 926 | WS_VISIBLE | WS_CHILD | SBS_VERT, 927 | 803+150, 10, 928 | 18, 550, 929 | gDebuggerWindow, 930 | (HMENU)ID_STACK_SCROLLBAR, 931 | gDllHModule, NULL 932 | ); 933 | 934 | // Disassembly view 935 | gDisassemblyList = CreateWindowEx( 936 | WS_EX_CLIENTEDGE, 937 | "LISTBOX", NULL, 938 | WS_VISIBLE | WS_CHILD | LBS_STANDARD | LBS_NOTIFY | WS_VSCROLL, 939 | 400, 10, 940 | 380, 262, 941 | gDebuggerWindow, 942 | (HMENU)ID_DISASSEMBLY_LIST_BOX, 943 | gDllHModule, NULL 944 | ); 945 | SendMessage(gDisassemblyList, WM_SETFONT, (WPARAM)gFont, true); 946 | gDisassemblyScrollbar = CreateWindow( 947 | "SCROLLBAR", NULL, 948 | WS_VISIBLE | WS_CHILD | SBS_VERT, 949 | 400+380, 10, 950 | 18, 262, 951 | gDebuggerWindow, 952 | (HMENU)ID_DISASSEMBLY_SCROLLBAR, 953 | gDllHModule, NULL 954 | ); 955 | 956 | createBreakpointsWindow(); 957 | 958 | // 959 | // Show window 960 | // 961 | ShowWindow(gDebuggerWindow, SW_SHOW); 962 | UpdateWindow(gDebuggerWindow); 963 | 964 | // A timer to regularily look for state updates 965 | SetTimer(gDebuggerWindow, ID_WINDOW_UPDATE_TIMER, 100, NULL); 966 | 967 | initialised = true; 968 | } 969 | 970 | void shutdownDebugger() 971 | { 972 | DestroyWindow(gDebuggerWindow); 973 | UnregisterClassA((LPCSTR)gHWndClassAtom, gDllHModule); 974 | } 975 | 976 | void fatalError(char* error) 977 | { 978 | char errBuf[1024]; 979 | DWORD lastError = GetLastError(); 980 | FormatMessageA( 981 | FORMAT_MESSAGE_FROM_SYSTEM, 982 | NULL, 983 | lastError, 984 | MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), 985 | &errBuf[0], 986 | 1024, 987 | NULL 988 | ); 989 | MessageBox(NULL, errBuf, error, 0); 990 | ExitProcess(1); 991 | } 992 | -------------------------------------------------------------------------------- /src/disasm_blank.c: -------------------------------------------------------------------------------- 1 | // 2 | // Blank instructions 3 | // 4 | 5 | #include "patch.h" 6 | 7 | BGIOpcode_t blankInstructions[256] = { 8 | // 0x00 ---- 9 | { 10 | .mnemonic = NULL, 11 | .numOperands = 0, 12 | .operands = {0,0,0,0} 13 | }, 14 | // 0x01 ---- 15 | { 16 | .mnemonic = NULL, 17 | .numOperands = 0, 18 | .operands = {0,0,0,0} 19 | }, 20 | // 0x02 ---- 21 | { 22 | .mnemonic = NULL, 23 | .numOperands = 0, 24 | .operands = {0,0,0,0} 25 | }, 26 | // 0x03 ---- 27 | { 28 | .mnemonic = NULL, 29 | .numOperands = 0, 30 | .operands = {0,0,0,0} 31 | }, 32 | // 0x04 ---- 33 | { 34 | .mnemonic = NULL, 35 | .numOperands = 0, 36 | .operands = {0,0,0,0} 37 | }, 38 | // 0x05 ---- 39 | { 40 | .mnemonic = NULL, 41 | .numOperands = 0, 42 | .operands = {0,0,0,0} 43 | }, 44 | // 0x06 ---- 45 | { 46 | .mnemonic = NULL, 47 | .numOperands = 0, 48 | .operands = {0,0,0,0} 49 | }, 50 | // 0x07 ----- 51 | { 52 | .mnemonic = NULL, 53 | .numOperands = 0, 54 | .operands = {0,0,0,0} 55 | }, 56 | // 0x08 ---- 57 | { 58 | .mnemonic = NULL, 59 | .numOperands = 0, 60 | .operands = {0,0,0,0} 61 | }, 62 | // 0x09 ---- 63 | { 64 | .mnemonic = NULL, 65 | .numOperands = 0, 66 | .operands = {0,0,0,0} 67 | }, 68 | // 0x0A ---- 69 | { 70 | .mnemonic = NULL, 71 | .numOperands = 0, 72 | .operands = {0,0,0,0} 73 | }, 74 | // 0x0B ---- 75 | { 76 | .mnemonic = NULL, 77 | .numOperands = 0, 78 | .operands = {0,0,0,0} 79 | }, 80 | // 0x0C ---- 81 | { 82 | .mnemonic = NULL, 83 | .numOperands = 0, 84 | .operands = {0,0,0,0} 85 | }, 86 | // 0x0D ----- 87 | { 88 | .mnemonic = NULL, 89 | .numOperands = 0, 90 | .operands = {0,0,0,0} 91 | }, 92 | // 0x0E ----- 93 | { 94 | .mnemonic = NULL, 95 | .numOperands = 0, 96 | .operands = {0,0,0,0} 97 | }, 98 | // 0x0F ----- 99 | { 100 | .mnemonic = NULL, 101 | .numOperands = 0, 102 | .operands = {0,0,0,0} 103 | }, 104 | // 0x10 ---- 105 | { 106 | .mnemonic = NULL, 107 | .numOperands = 0, 108 | .operands = {0,0,0,0} 109 | }, 110 | // 0x11 ---- 111 | { 112 | .mnemonic = NULL, 113 | .numOperands = 0, 114 | .operands = {0,0,0,0} 115 | }, 116 | // 0x12 ---- 117 | { 118 | .mnemonic = NULL, 119 | .numOperands = 0, 120 | .operands = {0,0,0,0} 121 | }, 122 | // 0x13 ---- 123 | { 124 | .mnemonic = NULL, 125 | .numOperands = 0, 126 | .operands = {0,0,0,0} 127 | }, 128 | // 0x14 ---- 129 | { 130 | .mnemonic = NULL, 131 | .numOperands = 0, 132 | .operands = {0,0,0,0} 133 | }, 134 | // 0x15 ---- 135 | { 136 | .mnemonic = NULL, 137 | .numOperands = 0, 138 | .operands = {0,0,0,0} 139 | }, 140 | // 0x16 ---- 141 | { 142 | .mnemonic = NULL, 143 | .numOperands = 0, 144 | .operands = {0,0,0,0} 145 | }, 146 | // 0x17 ----- 147 | { 148 | .mnemonic = NULL, 149 | .numOperands = 0, 150 | .operands = {0,0,0,0} 151 | }, 152 | // 0x18 ---- 153 | { 154 | .mnemonic = NULL, 155 | .numOperands = 0, 156 | .operands = {0,0,0,0} 157 | }, 158 | // 0x19 ---- 159 | { 160 | .mnemonic = NULL, 161 | .numOperands = 0, 162 | .operands = {0,0,0,0} 163 | }, 164 | // 0x1A ---- 165 | { 166 | .mnemonic = NULL, 167 | .numOperands = 0, 168 | .operands = {0,0,0,0} 169 | }, 170 | // 0x1B ---- 171 | { 172 | .mnemonic = NULL, 173 | .numOperands = 0, 174 | .operands = {0,0,0,0} 175 | }, 176 | // 0x1C ---- 177 | { 178 | .mnemonic = NULL, 179 | .numOperands = 0, 180 | .operands = {0,0,0,0} 181 | }, 182 | // 0x1D ----- 183 | { 184 | .mnemonic = NULL, 185 | .numOperands = 0, 186 | .operands = {0,0,0,0} 187 | }, 188 | // 0x1E ----- 189 | { 190 | .mnemonic = NULL, 191 | .numOperands = 0, 192 | .operands = {0,0,0,0} 193 | }, 194 | // 0x1F ----- 195 | { 196 | .mnemonic = NULL, 197 | .numOperands = 0, 198 | .operands = {0,0,0,0} 199 | }, 200 | // 0x20 ---- 201 | { 202 | .mnemonic = NULL, 203 | .numOperands = 0, 204 | .operands = {0,0,0,0} 205 | }, 206 | // 0x21 ---- 207 | { 208 | .mnemonic = NULL, 209 | .numOperands = 0, 210 | .operands = {0,0,0,0} 211 | }, 212 | // 0x22 ---- 213 | { 214 | .mnemonic = NULL, 215 | .numOperands = 0, 216 | .operands = {0,0,0,0} 217 | }, 218 | // 0x23 ---- 219 | { 220 | .mnemonic = NULL, 221 | .numOperands = 0, 222 | .operands = {0,0,0,0} 223 | }, 224 | // 0x24 ---- 225 | { 226 | .mnemonic = NULL, 227 | .numOperands = 0, 228 | .operands = {0,0,0,0} 229 | }, 230 | // 0x25 ---- 231 | { 232 | .mnemonic = NULL, 233 | .numOperands = 0, 234 | .operands = {0,0,0,0} 235 | }, 236 | // 0x26 ---- 237 | { 238 | .mnemonic = NULL, 239 | .numOperands = 0, 240 | .operands = {0,0,0,0} 241 | }, 242 | // 0x27 ----- 243 | { 244 | .mnemonic = NULL, 245 | .numOperands = 0, 246 | .operands = {0,0,0,0} 247 | }, 248 | // 0x28 ---- 249 | { 250 | .mnemonic = NULL, 251 | .numOperands = 0, 252 | .operands = {0,0,0,0} 253 | }, 254 | // 0x29 ---- 255 | { 256 | .mnemonic = NULL, 257 | .numOperands = 0, 258 | .operands = {0,0,0,0} 259 | }, 260 | // 0x2A ---- 261 | { 262 | .mnemonic = NULL, 263 | .numOperands = 0, 264 | .operands = {0,0,0,0} 265 | }, 266 | // 0x2B ---- 267 | { 268 | .mnemonic = NULL, 269 | .numOperands = 0, 270 | .operands = {0,0,0,0} 271 | }, 272 | // 0x2C ---- 273 | { 274 | .mnemonic = NULL, 275 | .numOperands = 0, 276 | .operands = {0,0,0,0} 277 | }, 278 | // 0x2D ----- 279 | { 280 | .mnemonic = NULL, 281 | .numOperands = 0, 282 | .operands = {0,0,0,0} 283 | }, 284 | // 0x2E ----- 285 | { 286 | .mnemonic = NULL, 287 | .numOperands = 0, 288 | .operands = {0,0,0,0} 289 | }, 290 | // 0x2F ----- 291 | { 292 | .mnemonic = NULL, 293 | .numOperands = 0, 294 | .operands = {0,0,0,0} 295 | }, 296 | // 0x30 ---- 297 | { 298 | .mnemonic = NULL, 299 | .numOperands = 0, 300 | .operands = {0,0,0,0} 301 | }, 302 | // 0x31 ---- 303 | { 304 | .mnemonic = NULL, 305 | .numOperands = 0, 306 | .operands = {0,0,0,0} 307 | }, 308 | // 0x32 ---- 309 | { 310 | .mnemonic = NULL, 311 | .numOperands = 0, 312 | .operands = {0,0,0,0} 313 | }, 314 | // 0x33 ---- 315 | { 316 | .mnemonic = NULL, 317 | .numOperands = 0, 318 | .operands = {0,0,0,0} 319 | }, 320 | // 0x34 ---- 321 | { 322 | .mnemonic = NULL, 323 | .numOperands = 0, 324 | .operands = {0,0,0,0} 325 | }, 326 | // 0x35 ---- 327 | { 328 | .mnemonic = NULL, 329 | .numOperands = 0, 330 | .operands = {0,0,0,0} 331 | }, 332 | // 0x36 ---- 333 | { 334 | .mnemonic = NULL, 335 | .numOperands = 0, 336 | .operands = {0,0,0,0} 337 | }, 338 | // 0x37 ----- 339 | { 340 | .mnemonic = NULL, 341 | .numOperands = 0, 342 | .operands = {0,0,0,0} 343 | }, 344 | // 0x38 ---- 345 | { 346 | .mnemonic = NULL, 347 | .numOperands = 0, 348 | .operands = {0,0,0,0} 349 | }, 350 | // 0x39 ---- 351 | { 352 | .mnemonic = NULL, 353 | .numOperands = 0, 354 | .operands = {0,0,0,0} 355 | }, 356 | // 0x3A ---- 357 | { 358 | .mnemonic = NULL, 359 | .numOperands = 0, 360 | .operands = {0,0,0,0} 361 | }, 362 | // 0x3B ---- 363 | { 364 | .mnemonic = NULL, 365 | .numOperands = 0, 366 | .operands = {0,0,0,0} 367 | }, 368 | // 0x3C ---- 369 | { 370 | .mnemonic = NULL, 371 | .numOperands = 0, 372 | .operands = {0,0,0,0} 373 | }, 374 | // 0x3D ----- 375 | { 376 | .mnemonic = NULL, 377 | .numOperands = 0, 378 | .operands = {0,0,0,0} 379 | }, 380 | // 0x3E ----- 381 | { 382 | .mnemonic = NULL, 383 | .numOperands = 0, 384 | .operands = {0,0,0,0} 385 | }, 386 | // 0x3F ----- 387 | { 388 | .mnemonic = NULL, 389 | .numOperands = 0, 390 | .operands = {0,0,0,0} 391 | }, 392 | // 0x40 ---- 393 | { 394 | .mnemonic = NULL, 395 | .numOperands = 0, 396 | .operands = {0,0,0,0} 397 | }, 398 | // 0x41 ---- 399 | { 400 | .mnemonic = NULL, 401 | .numOperands = 0, 402 | .operands = {0,0,0,0} 403 | }, 404 | // 0x42 ---- 405 | { 406 | .mnemonic = NULL, 407 | .numOperands = 0, 408 | .operands = {0,0,0,0} 409 | }, 410 | // 0x43 ---- 411 | { 412 | .mnemonic = NULL, 413 | .numOperands = 0, 414 | .operands = {0,0,0,0} 415 | }, 416 | // 0x44 ---- 417 | { 418 | .mnemonic = NULL, 419 | .numOperands = 0, 420 | .operands = {0,0,0,0} 421 | }, 422 | // 0x45 ---- 423 | { 424 | .mnemonic = NULL, 425 | .numOperands = 0, 426 | .operands = {0,0,0,0} 427 | }, 428 | // 0x46 ---- 429 | { 430 | .mnemonic = NULL, 431 | .numOperands = 0, 432 | .operands = {0,0,0,0} 433 | }, 434 | // 0x47 ----- 435 | { 436 | .mnemonic = NULL, 437 | .numOperands = 0, 438 | .operands = {0,0,0,0} 439 | }, 440 | // 0x48 ---- 441 | { 442 | .mnemonic = NULL, 443 | .numOperands = 0, 444 | .operands = {0,0,0,0} 445 | }, 446 | // 0x49 ---- 447 | { 448 | .mnemonic = NULL, 449 | .numOperands = 0, 450 | .operands = {0,0,0,0} 451 | }, 452 | // 0x4A ---- 453 | { 454 | .mnemonic = NULL, 455 | .numOperands = 0, 456 | .operands = {0,0,0,0} 457 | }, 458 | // 0x4B ---- 459 | { 460 | .mnemonic = NULL, 461 | .numOperands = 0, 462 | .operands = {0,0,0,0} 463 | }, 464 | // 0x4C ---- 465 | { 466 | .mnemonic = NULL, 467 | .numOperands = 0, 468 | .operands = {0,0,0,0} 469 | }, 470 | // 0x4D ----- 471 | { 472 | .mnemonic = NULL, 473 | .numOperands = 0, 474 | .operands = {0,0,0,0} 475 | }, 476 | // 0x4E ----- 477 | { 478 | .mnemonic = NULL, 479 | .numOperands = 0, 480 | .operands = {0,0,0,0} 481 | }, 482 | // 0x4F ----- 483 | { 484 | .mnemonic = NULL, 485 | .numOperands = 0, 486 | .operands = {0,0,0,0} 487 | }, 488 | // 0x50 ---- 489 | { 490 | .mnemonic = NULL, 491 | .numOperands = 0, 492 | .operands = {0,0,0,0} 493 | }, 494 | // 0x51 ---- 495 | { 496 | .mnemonic = NULL, 497 | .numOperands = 0, 498 | .operands = {0,0,0,0} 499 | }, 500 | // 0x52 ---- 501 | { 502 | .mnemonic = NULL, 503 | .numOperands = 0, 504 | .operands = {0,0,0,0} 505 | }, 506 | // 0x53 ---- 507 | { 508 | .mnemonic = NULL, 509 | .numOperands = 0, 510 | .operands = {0,0,0,0} 511 | }, 512 | // 0x54 ---- 513 | { 514 | .mnemonic = NULL, 515 | .numOperands = 0, 516 | .operands = {0,0,0,0} 517 | }, 518 | // 0x55 ---- 519 | { 520 | .mnemonic = NULL, 521 | .numOperands = 0, 522 | .operands = {0,0,0,0} 523 | }, 524 | // 0x56 ---- 525 | { 526 | .mnemonic = NULL, 527 | .numOperands = 0, 528 | .operands = {0,0,0,0} 529 | }, 530 | // 0x57 ----- 531 | { 532 | .mnemonic = NULL, 533 | .numOperands = 0, 534 | .operands = {0,0,0,0} 535 | }, 536 | // 0x58 ---- 537 | { 538 | .mnemonic = NULL, 539 | .numOperands = 0, 540 | .operands = {0,0,0,0} 541 | }, 542 | // 0x59 ---- 543 | { 544 | .mnemonic = NULL, 545 | .numOperands = 0, 546 | .operands = {0,0,0,0} 547 | }, 548 | // 0x5A ---- 549 | { 550 | .mnemonic = NULL, 551 | .numOperands = 0, 552 | .operands = {0,0,0,0} 553 | }, 554 | // 0x5B ---- 555 | { 556 | .mnemonic = NULL, 557 | .numOperands = 0, 558 | .operands = {0,0,0,0} 559 | }, 560 | // 0x5C ---- 561 | { 562 | .mnemonic = NULL, 563 | .numOperands = 0, 564 | .operands = {0,0,0,0} 565 | }, 566 | // 0x5D ----- 567 | { 568 | .mnemonic = NULL, 569 | .numOperands = 0, 570 | .operands = {0,0,0,0} 571 | }, 572 | // 0x5E ----- 573 | { 574 | .mnemonic = NULL, 575 | .numOperands = 0, 576 | .operands = {0,0,0,0} 577 | }, 578 | // 0x5F ----- 579 | { 580 | .mnemonic = NULL, 581 | .numOperands = 0, 582 | .operands = {0,0,0,0} 583 | }, 584 | // 0x60 ---- 585 | { 586 | .mnemonic = NULL, 587 | .numOperands = 0, 588 | .operands = {0,0,0,0} 589 | }, 590 | // 0x61 ---- 591 | { 592 | .mnemonic = NULL, 593 | .numOperands = 0, 594 | .operands = {0,0,0,0} 595 | }, 596 | // 0x62 ---- 597 | { 598 | .mnemonic = NULL, 599 | .numOperands = 0, 600 | .operands = {0,0,0,0} 601 | }, 602 | // 0x63 ---- 603 | { 604 | .mnemonic = NULL, 605 | .numOperands = 0, 606 | .operands = {0,0,0,0} 607 | }, 608 | // 0x64 ---- 609 | { 610 | .mnemonic = NULL, 611 | .numOperands = 0, 612 | .operands = {0,0,0,0} 613 | }, 614 | // 0x65 ---- 615 | { 616 | .mnemonic = NULL, 617 | .numOperands = 0, 618 | .operands = {0,0,0,0} 619 | }, 620 | // 0x66 ---- 621 | { 622 | .mnemonic = NULL, 623 | .numOperands = 0, 624 | .operands = {0,0,0,0} 625 | }, 626 | // 0x67 ----- 627 | { 628 | .mnemonic = NULL, 629 | .numOperands = 0, 630 | .operands = {0,0,0,0} 631 | }, 632 | // 0x68 ---- 633 | { 634 | .mnemonic = NULL, 635 | .numOperands = 0, 636 | .operands = {0,0,0,0} 637 | }, 638 | // 0x69 ---- 639 | { 640 | .mnemonic = NULL, 641 | .numOperands = 0, 642 | .operands = {0,0,0,0} 643 | }, 644 | // 0x6A ---- 645 | { 646 | .mnemonic = NULL, 647 | .numOperands = 0, 648 | .operands = {0,0,0,0} 649 | }, 650 | // 0x6B ---- 651 | { 652 | .mnemonic = NULL, 653 | .numOperands = 0, 654 | .operands = {0,0,0,0} 655 | }, 656 | // 0x6C ---- 657 | { 658 | .mnemonic = NULL, 659 | .numOperands = 0, 660 | .operands = {0,0,0,0} 661 | }, 662 | // 0x6D ----- 663 | { 664 | .mnemonic = NULL, 665 | .numOperands = 0, 666 | .operands = {0,0,0,0} 667 | }, 668 | // 0x6E ----- 669 | { 670 | .mnemonic = NULL, 671 | .numOperands = 0, 672 | .operands = {0,0,0,0} 673 | }, 674 | // 0x6F ----- 675 | { 676 | .mnemonic = NULL, 677 | .numOperands = 0, 678 | .operands = {0,0,0,0} 679 | }, 680 | // 0x70 ---- 681 | { 682 | .mnemonic = NULL, 683 | .numOperands = 0, 684 | .operands = {0,0,0,0} 685 | }, 686 | // 0x71 ---- 687 | { 688 | .mnemonic = NULL, 689 | .numOperands = 0, 690 | .operands = {0,0,0,0} 691 | }, 692 | // 0x72 ---- 693 | { 694 | .mnemonic = NULL, 695 | .numOperands = 0, 696 | .operands = {0,0,0,0} 697 | }, 698 | // 0x73 ---- 699 | { 700 | .mnemonic = NULL, 701 | .numOperands = 0, 702 | .operands = {0,0,0,0} 703 | }, 704 | // 0x74 ---- 705 | { 706 | .mnemonic = NULL, 707 | .numOperands = 0, 708 | .operands = {0,0,0,0} 709 | }, 710 | // 0x75 ---- 711 | { 712 | .mnemonic = NULL, 713 | .numOperands = 0, 714 | .operands = {0,0,0,0} 715 | }, 716 | // 0x76 ---- 717 | { 718 | .mnemonic = NULL, 719 | .numOperands = 0, 720 | .operands = {0,0,0,0} 721 | }, 722 | // 0x77 ----- 723 | { 724 | .mnemonic = NULL, 725 | .numOperands = 0, 726 | .operands = {0,0,0,0} 727 | }, 728 | // 0x78 ---- 729 | { 730 | .mnemonic = NULL, 731 | .numOperands = 0, 732 | .operands = {0,0,0,0} 733 | }, 734 | // 0x79 ---- 735 | { 736 | .mnemonic = NULL, 737 | .numOperands = 0, 738 | .operands = {0,0,0,0} 739 | }, 740 | // 0x7A ---- 741 | { 742 | .mnemonic = NULL, 743 | .numOperands = 0, 744 | .operands = {0,0,0,0} 745 | }, 746 | // 0x7B ---- 747 | { 748 | .mnemonic = NULL, 749 | .numOperands = 0, 750 | .operands = {0,0,0,0} 751 | }, 752 | // 0x7C ---- 753 | { 754 | .mnemonic = NULL, 755 | .numOperands = 0, 756 | .operands = {0,0,0,0} 757 | }, 758 | // 0x7D ----- 759 | { 760 | .mnemonic = NULL, 761 | .numOperands = 0, 762 | .operands = {0,0,0,0} 763 | }, 764 | // 0x7E ----- 765 | { 766 | .mnemonic = NULL, 767 | .numOperands = 0, 768 | .operands = {0,0,0,0} 769 | }, 770 | // 0x7F ----- 771 | { 772 | .mnemonic = NULL, 773 | .numOperands = 0, 774 | .operands = {0,0,0,0} 775 | }, 776 | // 0x80 ---- 777 | { 778 | .mnemonic = NULL, 779 | .numOperands = 0, 780 | .operands = {0,0,0,0} 781 | }, 782 | // 0x81 ---- 783 | { 784 | .mnemonic = NULL, 785 | .numOperands = 0, 786 | .operands = {0,0,0,0} 787 | }, 788 | // 0x82 ---- 789 | { 790 | .mnemonic = NULL, 791 | .numOperands = 0, 792 | .operands = {0,0,0,0} 793 | }, 794 | // 0x83 ---- 795 | { 796 | .mnemonic = NULL, 797 | .numOperands = 0, 798 | .operands = {0,0,0,0} 799 | }, 800 | // 0x84 ---- 801 | { 802 | .mnemonic = NULL, 803 | .numOperands = 0, 804 | .operands = {0,0,0,0} 805 | }, 806 | // 0x85 ---- 807 | { 808 | .mnemonic = NULL, 809 | .numOperands = 0, 810 | .operands = {0,0,0,0} 811 | }, 812 | // 0x86 ---- 813 | { 814 | .mnemonic = NULL, 815 | .numOperands = 0, 816 | .operands = {0,0,0,0} 817 | }, 818 | // 0x87 ----- 819 | { 820 | .mnemonic = NULL, 821 | .numOperands = 0, 822 | .operands = {0,0,0,0} 823 | }, 824 | // 0x88 ---- 825 | { 826 | .mnemonic = NULL, 827 | .numOperands = 0, 828 | .operands = {0,0,0,0} 829 | }, 830 | // 0x89 ---- 831 | { 832 | .mnemonic = NULL, 833 | .numOperands = 0, 834 | .operands = {0,0,0,0} 835 | }, 836 | // 0x8A ---- 837 | { 838 | .mnemonic = NULL, 839 | .numOperands = 0, 840 | .operands = {0,0,0,0} 841 | }, 842 | // 0x8B ---- 843 | { 844 | .mnemonic = NULL, 845 | .numOperands = 0, 846 | .operands = {0,0,0,0} 847 | }, 848 | // 0x8C ---- 849 | { 850 | .mnemonic = NULL, 851 | .numOperands = 0, 852 | .operands = {0,0,0,0} 853 | }, 854 | // 0x8D ----- 855 | { 856 | .mnemonic = NULL, 857 | .numOperands = 0, 858 | .operands = {0,0,0,0} 859 | }, 860 | // 0x8E ----- 861 | { 862 | .mnemonic = NULL, 863 | .numOperands = 0, 864 | .operands = {0,0,0,0} 865 | }, 866 | // 0x8F ----- 867 | { 868 | .mnemonic = NULL, 869 | .numOperands = 0, 870 | .operands = {0,0,0,0} 871 | }, 872 | // 0x90 ---- 873 | { 874 | .mnemonic = NULL, 875 | .numOperands = 0, 876 | .operands = {0,0,0,0} 877 | }, 878 | // 0x91 ---- 879 | { 880 | .mnemonic = NULL, 881 | .numOperands = 0, 882 | .operands = {0,0,0,0} 883 | }, 884 | // 0x92 ---- 885 | { 886 | .mnemonic = NULL, 887 | .numOperands = 0, 888 | .operands = {0,0,0,0} 889 | }, 890 | // 0x93 ---- 891 | { 892 | .mnemonic = NULL, 893 | .numOperands = 0, 894 | .operands = {0,0,0,0} 895 | }, 896 | // 0x94 ---- 897 | { 898 | .mnemonic = NULL, 899 | .numOperands = 0, 900 | .operands = {0,0,0,0} 901 | }, 902 | // 0x95 ---- 903 | { 904 | .mnemonic = NULL, 905 | .numOperands = 0, 906 | .operands = {0,0,0,0} 907 | }, 908 | // 0x96 ---- 909 | { 910 | .mnemonic = NULL, 911 | .numOperands = 0, 912 | .operands = {0,0,0,0} 913 | }, 914 | // 0x97 ----- 915 | { 916 | .mnemonic = NULL, 917 | .numOperands = 0, 918 | .operands = {0,0,0,0} 919 | }, 920 | // 0x98 ---- 921 | { 922 | .mnemonic = NULL, 923 | .numOperands = 0, 924 | .operands = {0,0,0,0} 925 | }, 926 | // 0x99 ---- 927 | { 928 | .mnemonic = NULL, 929 | .numOperands = 0, 930 | .operands = {0,0,0,0} 931 | }, 932 | // 0x9A ---- 933 | { 934 | .mnemonic = NULL, 935 | .numOperands = 0, 936 | .operands = {0,0,0,0} 937 | }, 938 | // 0x9B ---- 939 | { 940 | .mnemonic = NULL, 941 | .numOperands = 0, 942 | .operands = {0,0,0,0} 943 | }, 944 | // 0x9C ---- 945 | { 946 | .mnemonic = NULL, 947 | .numOperands = 0, 948 | .operands = {0,0,0,0} 949 | }, 950 | // 0x9D ----- 951 | { 952 | .mnemonic = NULL, 953 | .numOperands = 0, 954 | .operands = {0,0,0,0} 955 | }, 956 | // 0x9E ----- 957 | { 958 | .mnemonic = NULL, 959 | .numOperands = 0, 960 | .operands = {0,0,0,0} 961 | }, 962 | // 0x9F ----- 963 | { 964 | .mnemonic = NULL, 965 | .numOperands = 0, 966 | .operands = {0,0,0,0} 967 | }, 968 | // 0xA0 ---- 969 | { 970 | .mnemonic = NULL, 971 | .numOperands = 0, 972 | .operands = {0,0,0,0} 973 | }, 974 | // 0xA1 ---- 975 | { 976 | .mnemonic = NULL, 977 | .numOperands = 0, 978 | .operands = {0,0,0,0} 979 | }, 980 | // 0xA2 ---- 981 | { 982 | .mnemonic = NULL, 983 | .numOperands = 0, 984 | .operands = {0,0,0,0} 985 | }, 986 | // 0xA3 ---- 987 | { 988 | .mnemonic = NULL, 989 | .numOperands = 0, 990 | .operands = {0,0,0,0} 991 | }, 992 | // 0xA4 ---- 993 | { 994 | .mnemonic = NULL, 995 | .numOperands = 0, 996 | .operands = {0,0,0,0} 997 | }, 998 | // 0xA5 ---- 999 | { 1000 | .mnemonic = NULL, 1001 | .numOperands = 0, 1002 | .operands = {0,0,0,0} 1003 | }, 1004 | // 0xA6 ---- 1005 | { 1006 | .mnemonic = NULL, 1007 | .numOperands = 0, 1008 | .operands = {0,0,0,0} 1009 | }, 1010 | // 0xA7 ----- 1011 | { 1012 | .mnemonic = NULL, 1013 | .numOperands = 0, 1014 | .operands = {0,0,0,0} 1015 | }, 1016 | // 0xA8 ---- 1017 | { 1018 | .mnemonic = NULL, 1019 | .numOperands = 0, 1020 | .operands = {0,0,0,0} 1021 | }, 1022 | // 0xA9 ---- 1023 | { 1024 | .mnemonic = NULL, 1025 | .numOperands = 0, 1026 | .operands = {0,0,0,0} 1027 | }, 1028 | // 0xAA ---- 1029 | { 1030 | .mnemonic = NULL, 1031 | .numOperands = 0, 1032 | .operands = {0,0,0,0} 1033 | }, 1034 | // 0xAB ---- 1035 | { 1036 | .mnemonic = NULL, 1037 | .numOperands = 0, 1038 | .operands = {0,0,0,0} 1039 | }, 1040 | // 0xAC ---- 1041 | { 1042 | .mnemonic = NULL, 1043 | .numOperands = 0, 1044 | .operands = {0,0,0,0} 1045 | }, 1046 | // 0xAD ----- 1047 | { 1048 | .mnemonic = NULL, 1049 | .numOperands = 0, 1050 | .operands = {0,0,0,0} 1051 | }, 1052 | // 0xAE ----- 1053 | { 1054 | .mnemonic = NULL, 1055 | .numOperands = 0, 1056 | .operands = {0,0,0,0} 1057 | }, 1058 | // 0xAF ----- 1059 | { 1060 | .mnemonic = NULL, 1061 | .numOperands = 0, 1062 | .operands = {0,0,0,0} 1063 | }, 1064 | // 0xB0 ---- 1065 | { 1066 | .mnemonic = NULL, 1067 | .numOperands = 0, 1068 | .operands = {0,0,0,0} 1069 | }, 1070 | // 0xB1 ---- 1071 | { 1072 | .mnemonic = NULL, 1073 | .numOperands = 0, 1074 | .operands = {0,0,0,0} 1075 | }, 1076 | // 0xB2 ---- 1077 | { 1078 | .mnemonic = NULL, 1079 | .numOperands = 0, 1080 | .operands = {0,0,0,0} 1081 | }, 1082 | // 0xB3 ---- 1083 | { 1084 | .mnemonic = NULL, 1085 | .numOperands = 0, 1086 | .operands = {0,0,0,0} 1087 | }, 1088 | // 0xB4 ---- 1089 | { 1090 | .mnemonic = NULL, 1091 | .numOperands = 0, 1092 | .operands = {0,0,0,0} 1093 | }, 1094 | // 0xB5 ---- 1095 | { 1096 | .mnemonic = NULL, 1097 | .numOperands = 0, 1098 | .operands = {0,0,0,0} 1099 | }, 1100 | // 0xB6 ---- 1101 | { 1102 | .mnemonic = NULL, 1103 | .numOperands = 0, 1104 | .operands = {0,0,0,0} 1105 | }, 1106 | // 0xB7 ----- 1107 | { 1108 | .mnemonic = NULL, 1109 | .numOperands = 0, 1110 | .operands = {0,0,0,0} 1111 | }, 1112 | // 0xB8 ---- 1113 | { 1114 | .mnemonic = NULL, 1115 | .numOperands = 0, 1116 | .operands = {0,0,0,0} 1117 | }, 1118 | // 0xB9 ---- 1119 | { 1120 | .mnemonic = NULL, 1121 | .numOperands = 0, 1122 | .operands = {0,0,0,0} 1123 | }, 1124 | // 0xBA ---- 1125 | { 1126 | .mnemonic = NULL, 1127 | .numOperands = 0, 1128 | .operands = {0,0,0,0} 1129 | }, 1130 | // 0xBB ---- 1131 | { 1132 | .mnemonic = NULL, 1133 | .numOperands = 0, 1134 | .operands = {0,0,0,0} 1135 | }, 1136 | // 0xBC ---- 1137 | { 1138 | .mnemonic = NULL, 1139 | .numOperands = 0, 1140 | .operands = {0,0,0,0} 1141 | }, 1142 | // 0xBD ----- 1143 | { 1144 | .mnemonic = NULL, 1145 | .numOperands = 0, 1146 | .operands = {0,0,0,0} 1147 | }, 1148 | // 0xBE ----- 1149 | { 1150 | .mnemonic = NULL, 1151 | .numOperands = 0, 1152 | .operands = {0,0,0,0} 1153 | }, 1154 | // 0xBF ----- 1155 | { 1156 | .mnemonic = NULL, 1157 | .numOperands = 0, 1158 | .operands = {0,0,0,0} 1159 | }, 1160 | // 0xC0 ---- 1161 | { 1162 | .mnemonic = NULL, 1163 | .numOperands = 0, 1164 | .operands = {0,0,0,0} 1165 | }, 1166 | // 0xC1 ---- 1167 | { 1168 | .mnemonic = NULL, 1169 | .numOperands = 0, 1170 | .operands = {0,0,0,0} 1171 | }, 1172 | // 0xC2 ---- 1173 | { 1174 | .mnemonic = NULL, 1175 | .numOperands = 0, 1176 | .operands = {0,0,0,0} 1177 | }, 1178 | // 0xC3 ---- 1179 | { 1180 | .mnemonic = NULL, 1181 | .numOperands = 0, 1182 | .operands = {0,0,0,0} 1183 | }, 1184 | // 0xC4 ---- 1185 | { 1186 | .mnemonic = NULL, 1187 | .numOperands = 0, 1188 | .operands = {0,0,0,0} 1189 | }, 1190 | // 0xC5 ---- 1191 | { 1192 | .mnemonic = NULL, 1193 | .numOperands = 0, 1194 | .operands = {0,0,0,0} 1195 | }, 1196 | // 0xC6 ---- 1197 | { 1198 | .mnemonic = NULL, 1199 | .numOperands = 0, 1200 | .operands = {0,0,0,0} 1201 | }, 1202 | // 0xC7 ----- 1203 | { 1204 | .mnemonic = NULL, 1205 | .numOperands = 0, 1206 | .operands = {0,0,0,0} 1207 | }, 1208 | // 0xC8 ---- 1209 | { 1210 | .mnemonic = NULL, 1211 | .numOperands = 0, 1212 | .operands = {0,0,0,0} 1213 | }, 1214 | // 0xC9 ---- 1215 | { 1216 | .mnemonic = NULL, 1217 | .numOperands = 0, 1218 | .operands = {0,0,0,0} 1219 | }, 1220 | // 0xCA ---- 1221 | { 1222 | .mnemonic = NULL, 1223 | .numOperands = 0, 1224 | .operands = {0,0,0,0} 1225 | }, 1226 | // 0xCB ---- 1227 | { 1228 | .mnemonic = NULL, 1229 | .numOperands = 0, 1230 | .operands = {0,0,0,0} 1231 | }, 1232 | // 0xCC ---- 1233 | { 1234 | .mnemonic = NULL, 1235 | .numOperands = 0, 1236 | .operands = {0,0,0,0} 1237 | }, 1238 | // 0xCD ----- 1239 | { 1240 | .mnemonic = NULL, 1241 | .numOperands = 0, 1242 | .operands = {0,0,0,0} 1243 | }, 1244 | // 0xCE ----- 1245 | { 1246 | .mnemonic = NULL, 1247 | .numOperands = 0, 1248 | .operands = {0,0,0,0} 1249 | }, 1250 | // 0xCF ----- 1251 | { 1252 | .mnemonic = NULL, 1253 | .numOperands = 0, 1254 | .operands = {0,0,0,0} 1255 | }, 1256 | // 0xD0 ---- 1257 | { 1258 | .mnemonic = NULL, 1259 | .numOperands = 0, 1260 | .operands = {0,0,0,0} 1261 | }, 1262 | // 0xD1 ---- 1263 | { 1264 | .mnemonic = NULL, 1265 | .numOperands = 0, 1266 | .operands = {0,0,0,0} 1267 | }, 1268 | // 0xD2 ---- 1269 | { 1270 | .mnemonic = NULL, 1271 | .numOperands = 0, 1272 | .operands = {0,0,0,0} 1273 | }, 1274 | // 0xD3 ---- 1275 | { 1276 | .mnemonic = NULL, 1277 | .numOperands = 0, 1278 | .operands = {0,0,0,0} 1279 | }, 1280 | // 0xD4 ---- 1281 | { 1282 | .mnemonic = NULL, 1283 | .numOperands = 0, 1284 | .operands = {0,0,0,0} 1285 | }, 1286 | // 0xD5 ---- 1287 | { 1288 | .mnemonic = NULL, 1289 | .numOperands = 0, 1290 | .operands = {0,0,0,0} 1291 | }, 1292 | // 0xD6 ---- 1293 | { 1294 | .mnemonic = NULL, 1295 | .numOperands = 0, 1296 | .operands = {0,0,0,0} 1297 | }, 1298 | // 0xD7 ----- 1299 | { 1300 | .mnemonic = NULL, 1301 | .numOperands = 0, 1302 | .operands = {0,0,0,0} 1303 | }, 1304 | // 0xD8 ---- 1305 | { 1306 | .mnemonic = NULL, 1307 | .numOperands = 0, 1308 | .operands = {0,0,0,0} 1309 | }, 1310 | // 0xD9 ---- 1311 | { 1312 | .mnemonic = NULL, 1313 | .numOperands = 0, 1314 | .operands = {0,0,0,0} 1315 | }, 1316 | // 0xDA ---- 1317 | { 1318 | .mnemonic = NULL, 1319 | .numOperands = 0, 1320 | .operands = {0,0,0,0} 1321 | }, 1322 | // 0xDB ---- 1323 | { 1324 | .mnemonic = NULL, 1325 | .numOperands = 0, 1326 | .operands = {0,0,0,0} 1327 | }, 1328 | // 0xDC ---- 1329 | { 1330 | .mnemonic = NULL, 1331 | .numOperands = 0, 1332 | .operands = {0,0,0,0} 1333 | }, 1334 | // 0xDD ----- 1335 | { 1336 | .mnemonic = NULL, 1337 | .numOperands = 0, 1338 | .operands = {0,0,0,0} 1339 | }, 1340 | // 0xDE ----- 1341 | { 1342 | .mnemonic = NULL, 1343 | .numOperands = 0, 1344 | .operands = {0,0,0,0} 1345 | }, 1346 | // 0xDF ----- 1347 | { 1348 | .mnemonic = NULL, 1349 | .numOperands = 0, 1350 | .operands = {0,0,0,0} 1351 | }, 1352 | // 0xE0 ---- 1353 | { 1354 | .mnemonic = NULL, 1355 | .numOperands = 0, 1356 | .operands = {0,0,0,0} 1357 | }, 1358 | // 0xE1 ---- 1359 | { 1360 | .mnemonic = NULL, 1361 | .numOperands = 0, 1362 | .operands = {0,0,0,0} 1363 | }, 1364 | // 0xE2 ---- 1365 | { 1366 | .mnemonic = NULL, 1367 | .numOperands = 0, 1368 | .operands = {0,0,0,0} 1369 | }, 1370 | // 0xE3 ---- 1371 | { 1372 | .mnemonic = NULL, 1373 | .numOperands = 0, 1374 | .operands = {0,0,0,0} 1375 | }, 1376 | // 0xE4 ---- 1377 | { 1378 | .mnemonic = NULL, 1379 | .numOperands = 0, 1380 | .operands = {0,0,0,0} 1381 | }, 1382 | // 0xE5 ---- 1383 | { 1384 | .mnemonic = NULL, 1385 | .numOperands = 0, 1386 | .operands = {0,0,0,0} 1387 | }, 1388 | // 0xE6 ---- 1389 | { 1390 | .mnemonic = NULL, 1391 | .numOperands = 0, 1392 | .operands = {0,0,0,0} 1393 | }, 1394 | // 0xE7 ----- 1395 | { 1396 | .mnemonic = NULL, 1397 | .numOperands = 0, 1398 | .operands = {0,0,0,0} 1399 | }, 1400 | // 0xE8 ---- 1401 | { 1402 | .mnemonic = NULL, 1403 | .numOperands = 0, 1404 | .operands = {0,0,0,0} 1405 | }, 1406 | // 0xE9 ---- 1407 | { 1408 | .mnemonic = NULL, 1409 | .numOperands = 0, 1410 | .operands = {0,0,0,0} 1411 | }, 1412 | // 0xEA ---- 1413 | { 1414 | .mnemonic = NULL, 1415 | .numOperands = 0, 1416 | .operands = {0,0,0,0} 1417 | }, 1418 | // 0xEB ---- 1419 | { 1420 | .mnemonic = NULL, 1421 | .numOperands = 0, 1422 | .operands = {0,0,0,0} 1423 | }, 1424 | // 0xEC ---- 1425 | { 1426 | .mnemonic = NULL, 1427 | .numOperands = 0, 1428 | .operands = {0,0,0,0} 1429 | }, 1430 | // 0xED ----- 1431 | { 1432 | .mnemonic = NULL, 1433 | .numOperands = 0, 1434 | .operands = {0,0,0,0} 1435 | }, 1436 | // 0xEE ----- 1437 | { 1438 | .mnemonic = NULL, 1439 | .numOperands = 0, 1440 | .operands = {0,0,0,0} 1441 | }, 1442 | // 0xEF ----- 1443 | { 1444 | .mnemonic = NULL, 1445 | .numOperands = 0, 1446 | .operands = {0,0,0,0} 1447 | }, 1448 | // 0xF0 ---- 1449 | { 1450 | .mnemonic = NULL, 1451 | .numOperands = 0, 1452 | .operands = {0,0,0,0} 1453 | }, 1454 | // 0xF1 ---- 1455 | { 1456 | .mnemonic = NULL, 1457 | .numOperands = 0, 1458 | .operands = {0,0,0,0} 1459 | }, 1460 | // 0xF2 ---- 1461 | { 1462 | .mnemonic = NULL, 1463 | .numOperands = 0, 1464 | .operands = {0,0,0,0} 1465 | }, 1466 | // 0xF3 ---- 1467 | { 1468 | .mnemonic = NULL, 1469 | .numOperands = 0, 1470 | .operands = {0,0,0,0} 1471 | }, 1472 | // 0xF4 ---- 1473 | { 1474 | .mnemonic = NULL, 1475 | .numOperands = 0, 1476 | .operands = {0,0,0,0} 1477 | }, 1478 | // 0xF5 ---- 1479 | { 1480 | .mnemonic = NULL, 1481 | .numOperands = 0, 1482 | .operands = {0,0,0,0} 1483 | }, 1484 | // 0xF6 ---- 1485 | { 1486 | .mnemonic = NULL, 1487 | .numOperands = 0, 1488 | .operands = {0,0,0,0} 1489 | }, 1490 | // 0xF7 ----- 1491 | { 1492 | .mnemonic = NULL, 1493 | .numOperands = 0, 1494 | .operands = {0,0,0,0} 1495 | }, 1496 | // 0xF8 ---- 1497 | { 1498 | .mnemonic = NULL, 1499 | .numOperands = 0, 1500 | .operands = {0,0,0,0} 1501 | }, 1502 | // 0xF9 ---- 1503 | { 1504 | .mnemonic = NULL, 1505 | .numOperands = 0, 1506 | .operands = {0,0,0,0} 1507 | }, 1508 | // 0xFA ---- 1509 | { 1510 | .mnemonic = NULL, 1511 | .numOperands = 0, 1512 | .operands = {0,0,0,0} 1513 | }, 1514 | // 0xFB ---- 1515 | { 1516 | .mnemonic = NULL, 1517 | .numOperands = 0, 1518 | .operands = {0,0,0,0} 1519 | }, 1520 | // 0xFC ---- 1521 | { 1522 | .mnemonic = NULL, 1523 | .numOperands = 0, 1524 | .operands = {0,0,0,0} 1525 | }, 1526 | // 0xFD ----- 1527 | { 1528 | .mnemonic = NULL, 1529 | .numOperands = 0, 1530 | .operands = {0,0,0,0} 1531 | }, 1532 | // 0xFE ----- 1533 | { 1534 | .mnemonic = NULL, 1535 | .numOperands = 0, 1536 | .operands = {0,0,0,0} 1537 | }, 1538 | // 0xFF ----- 1539 | { 1540 | .mnemonic = NULL, 1541 | .numOperands = 0, 1542 | .operands = {0,0,0,0} 1543 | } 1544 | }; 1545 | -------------------------------------------------------------------------------- /src/disasm_sys0.c: -------------------------------------------------------------------------------- 1 | // 2 | // System instructions 3 | // 4 | 5 | #include "patch.h" 6 | 7 | BGIOpcode_t sys0Instructions[256] = 8 | { 9 | // 0x00 ---- 10 | { 11 | .mnemonic = "srand", 12 | .numOperands = 0, 13 | .operands = {0,0,0,0} 14 | }, 15 | // 0x01 ---- 16 | { 17 | .mnemonic = NULL, 18 | .numOperands = 0, 19 | .operands = {0,0,0,0} 20 | }, 21 | // 0x02 ---- 22 | { 23 | .mnemonic = NULL, 24 | .numOperands = 0, 25 | .operands = {0,0,0,0} 26 | }, 27 | // 0x03 ---- 28 | { 29 | .mnemonic = NULL, 30 | .numOperands = 0, 31 | .operands = {0,0,0,0} 32 | }, 33 | // 0x04 ---- 34 | { 35 | .mnemonic = NULL, 36 | .numOperands = 0, 37 | .operands = {0,0,0,0} 38 | }, 39 | // 0x05 ---- 40 | { 41 | .mnemonic = NULL, 42 | .numOperands = 0, 43 | .operands = {0,0,0,0} 44 | }, 45 | // 0x06 ---- 46 | { 47 | .mnemonic = NULL, 48 | .numOperands = 0, 49 | .operands = {0,0,0,0} 50 | }, 51 | // 0x07 ----- 52 | { 53 | .mnemonic = NULL, 54 | .numOperands = 0, 55 | .operands = {0,0,0,0} 56 | }, 57 | // 0x08 ---- 58 | { 59 | .mnemonic = NULL, 60 | .numOperands = 0, 61 | .operands = {0,0,0,0} 62 | }, 63 | // 0x09 ---- 64 | { 65 | .mnemonic = NULL, 66 | .numOperands = 0, 67 | .operands = {0,0,0,0} 68 | }, 69 | // 0x0A ---- 70 | { 71 | .mnemonic = NULL, 72 | .numOperands = 0, 73 | .operands = {0,0,0,0} 74 | }, 75 | // 0x0B ---- 76 | { 77 | .mnemonic = NULL, 78 | .numOperands = 0, 79 | .operands = {0,0,0,0} 80 | }, 81 | // 0x0C ---- 82 | { 83 | .mnemonic = NULL, 84 | .numOperands = 0, 85 | .operands = {0,0,0,0} 86 | }, 87 | // 0x0D ----- 88 | { 89 | .mnemonic = NULL, 90 | .numOperands = 0, 91 | .operands = {0,0,0,0} 92 | }, 93 | // 0x0E ----- 94 | { 95 | .mnemonic = NULL, 96 | .numOperands = 0, 97 | .operands = {0,0,0,0} 98 | }, 99 | // 0x0F ----- 100 | { 101 | .mnemonic = NULL, 102 | .numOperands = 0, 103 | .operands = {0,0,0,0} 104 | }, 105 | // 0x10 ---- 106 | { 107 | .mnemonic = NULL, 108 | .numOperands = 0, 109 | .operands = {0,0,0,0} 110 | }, 111 | // 0x11 ---- 112 | { 113 | .mnemonic = NULL, 114 | .numOperands = 0, 115 | .operands = {0,0,0,0} 116 | }, 117 | // 0x12 ---- 118 | { 119 | .mnemonic = NULL, 120 | .numOperands = 0, 121 | .operands = {0,0,0,0} 122 | }, 123 | // 0x13 ---- 124 | { 125 | .mnemonic = NULL, 126 | .numOperands = 0, 127 | .operands = {0,0,0,0} 128 | }, 129 | // 0x14 ---- 130 | { 131 | .mnemonic = NULL, 132 | .numOperands = 0, 133 | .operands = {0,0,0,0} 134 | }, 135 | // 0x15 ---- 136 | { 137 | .mnemonic = NULL, 138 | .numOperands = 0, 139 | .operands = {0,0,0,0} 140 | }, 141 | // 0x16 ---- 142 | { 143 | .mnemonic = NULL, 144 | .numOperands = 0, 145 | .operands = {0,0,0,0} 146 | }, 147 | // 0x17 ----- 148 | { 149 | .mnemonic = NULL, 150 | .numOperands = 0, 151 | .operands = {0,0,0,0} 152 | }, 153 | // 0x18 ---- 154 | { 155 | .mnemonic = NULL, 156 | .numOperands = 0, 157 | .operands = {0,0,0,0} 158 | }, 159 | // 0x19 ---- 160 | { 161 | .mnemonic = NULL, 162 | .numOperands = 0, 163 | .operands = {0,0,0,0} 164 | }, 165 | // 0x1A ---- 166 | { 167 | .mnemonic = NULL, 168 | .numOperands = 0, 169 | .operands = {0,0,0,0} 170 | }, 171 | // 0x1B ---- 172 | { 173 | .mnemonic = NULL, 174 | .numOperands = 0, 175 | .operands = {0,0,0,0} 176 | }, 177 | // 0x1C ---- 178 | { 179 | .mnemonic = NULL, 180 | .numOperands = 0, 181 | .operands = {0,0,0,0} 182 | }, 183 | // 0x1D ----- 184 | { 185 | .mnemonic = NULL, 186 | .numOperands = 0, 187 | .operands = {0,0,0,0} 188 | }, 189 | // 0x1E ----- 190 | { 191 | .mnemonic = NULL, 192 | .numOperands = 0, 193 | .operands = {0,0,0,0} 194 | }, 195 | // 0x1F ----- 196 | { 197 | .mnemonic = NULL, 198 | .numOperands = 0, 199 | .operands = {0,0,0,0} 200 | }, 201 | // 0x20 ---- 202 | { 203 | .mnemonic = NULL, 204 | .numOperands = 0, 205 | .operands = {0,0,0,0} 206 | }, 207 | // 0x21 ---- 208 | { 209 | .mnemonic = NULL, 210 | .numOperands = 0, 211 | .operands = {0,0,0,0} 212 | }, 213 | // 0x22 ---- 214 | { 215 | .mnemonic = NULL, 216 | .numOperands = 0, 217 | .operands = {0,0,0,0} 218 | }, 219 | // 0x23 ---- 220 | { 221 | .mnemonic = NULL, 222 | .numOperands = 0, 223 | .operands = {0,0,0,0} 224 | }, 225 | // 0x24 ---- 226 | { 227 | .mnemonic = NULL, 228 | .numOperands = 0, 229 | .operands = {0,0,0,0} 230 | }, 231 | // 0x25 ---- 232 | { 233 | .mnemonic = NULL, 234 | .numOperands = 0, 235 | .operands = {0,0,0,0} 236 | }, 237 | // 0x26 ---- 238 | { 239 | .mnemonic = NULL, 240 | .numOperands = 0, 241 | .operands = {0,0,0,0} 242 | }, 243 | // 0x27 ----- 244 | { 245 | .mnemonic = NULL, 246 | .numOperands = 0, 247 | .operands = {0,0,0,0} 248 | }, 249 | // 0x28 ---- 250 | { 251 | .mnemonic = NULL, 252 | .numOperands = 0, 253 | .operands = {0,0,0,0} 254 | }, 255 | // 0x29 ---- 256 | { 257 | .mnemonic = NULL, 258 | .numOperands = 0, 259 | .operands = {0,0,0,0} 260 | }, 261 | // 0x2A ---- 262 | { 263 | .mnemonic = NULL, 264 | .numOperands = 0, 265 | .operands = {0,0,0,0} 266 | }, 267 | // 0x2B ---- 268 | { 269 | .mnemonic = NULL, 270 | .numOperands = 0, 271 | .operands = {0,0,0,0} 272 | }, 273 | // 0x2C ---- 274 | { 275 | .mnemonic = NULL, 276 | .numOperands = 0, 277 | .operands = {0,0,0,0} 278 | }, 279 | // 0x2D ----- 280 | { 281 | .mnemonic = NULL, 282 | .numOperands = 0, 283 | .operands = {0,0,0,0} 284 | }, 285 | // 0x2E ----- 286 | { 287 | .mnemonic = NULL, 288 | .numOperands = 0, 289 | .operands = {0,0,0,0} 290 | }, 291 | // 0x2F ----- 292 | { 293 | .mnemonic = NULL, 294 | .numOperands = 0, 295 | .operands = {0,0,0,0} 296 | }, 297 | // 0x30 ---- 298 | { 299 | .mnemonic = NULL, 300 | .numOperands = 0, 301 | .operands = {0,0,0,0} 302 | }, 303 | // 0x31 ---- 304 | { 305 | .mnemonic = NULL, 306 | .numOperands = 0, 307 | .operands = {0,0,0,0} 308 | }, 309 | // 0x32 ---- 310 | { 311 | .mnemonic = NULL, 312 | .numOperands = 0, 313 | .operands = {0,0,0,0} 314 | }, 315 | // 0x33 ---- 316 | { 317 | .mnemonic = NULL, 318 | .numOperands = 0, 319 | .operands = {0,0,0,0} 320 | }, 321 | // 0x34 ---- 322 | { 323 | .mnemonic = NULL, 324 | .numOperands = 0, 325 | .operands = {0,0,0,0} 326 | }, 327 | // 0x35 ---- 328 | { 329 | .mnemonic = NULL, 330 | .numOperands = 0, 331 | .operands = {0,0,0,0} 332 | }, 333 | // 0x36 ---- 334 | { 335 | .mnemonic = NULL, 336 | .numOperands = 0, 337 | .operands = {0,0,0,0} 338 | }, 339 | // 0x37 ----- 340 | { 341 | .mnemonic = NULL, 342 | .numOperands = 0, 343 | .operands = {0,0,0,0} 344 | }, 345 | // 0x38 ---- 346 | { 347 | .mnemonic = NULL, 348 | .numOperands = 0, 349 | .operands = {0,0,0,0} 350 | }, 351 | // 0x39 ---- 352 | { 353 | .mnemonic = NULL, 354 | .numOperands = 0, 355 | .operands = {0,0,0,0} 356 | }, 357 | // 0x3A ---- 358 | { 359 | .mnemonic = NULL, 360 | .numOperands = 0, 361 | .operands = {0,0,0,0} 362 | }, 363 | // 0x3B ---- 364 | { 365 | .mnemonic = NULL, 366 | .numOperands = 0, 367 | .operands = {0,0,0,0} 368 | }, 369 | // 0x3C ---- 370 | { 371 | .mnemonic = NULL, 372 | .numOperands = 0, 373 | .operands = {0,0,0,0} 374 | }, 375 | // 0x3D ----- 376 | { 377 | .mnemonic = NULL, 378 | .numOperands = 0, 379 | .operands = {0,0,0,0} 380 | }, 381 | // 0x3E ----- 382 | { 383 | .mnemonic = NULL, 384 | .numOperands = 0, 385 | .operands = {0,0,0,0} 386 | }, 387 | // 0x3F ----- 388 | { 389 | .mnemonic = NULL, 390 | .numOperands = 0, 391 | .operands = {0,0,0,0} 392 | }, 393 | // 0x40 ---- 394 | { 395 | .mnemonic = NULL, 396 | .numOperands = 0, 397 | .operands = {0,0,0,0} 398 | }, 399 | // 0x41 ---- 400 | { 401 | .mnemonic = NULL, 402 | .numOperands = 0, 403 | .operands = {0,0,0,0} 404 | }, 405 | // 0x42 ---- 406 | { 407 | .mnemonic = NULL, 408 | .numOperands = 0, 409 | .operands = {0,0,0,0} 410 | }, 411 | // 0x43 ---- 412 | { 413 | .mnemonic = NULL, 414 | .numOperands = 0, 415 | .operands = {0,0,0,0} 416 | }, 417 | // 0x44 ---- 418 | { 419 | .mnemonic = NULL, 420 | .numOperands = 0, 421 | .operands = {0,0,0,0} 422 | }, 423 | // 0x45 ---- 424 | { 425 | .mnemonic = NULL, 426 | .numOperands = 0, 427 | .operands = {0,0,0,0} 428 | }, 429 | // 0x46 ---- 430 | { 431 | .mnemonic = NULL, 432 | .numOperands = 0, 433 | .operands = {0,0,0,0} 434 | }, 435 | // 0x47 ----- 436 | { 437 | .mnemonic = NULL, 438 | .numOperands = 0, 439 | .operands = {0,0,0,0} 440 | }, 441 | // 0x48 ---- 442 | { 443 | .mnemonic = NULL, 444 | .numOperands = 0, 445 | .operands = {0,0,0,0} 446 | }, 447 | // 0x49 ---- 448 | { 449 | .mnemonic = NULL, 450 | .numOperands = 0, 451 | .operands = {0,0,0,0} 452 | }, 453 | // 0x4A ---- 454 | { 455 | .mnemonic = NULL, 456 | .numOperands = 0, 457 | .operands = {0,0,0,0} 458 | }, 459 | // 0x4B ---- 460 | { 461 | .mnemonic = NULL, 462 | .numOperands = 0, 463 | .operands = {0,0,0,0} 464 | }, 465 | // 0x4C ---- 466 | { 467 | .mnemonic = NULL, 468 | .numOperands = 0, 469 | .operands = {0,0,0,0} 470 | }, 471 | // 0x4D ----- 472 | { 473 | .mnemonic = NULL, 474 | .numOperands = 0, 475 | .operands = {0,0,0,0} 476 | }, 477 | // 0x4E ----- 478 | { 479 | .mnemonic = NULL, 480 | .numOperands = 0, 481 | .operands = {0,0,0,0} 482 | }, 483 | // 0x4F ----- 484 | { 485 | .mnemonic = NULL, 486 | .numOperands = 0, 487 | .operands = {0,0,0,0} 488 | }, 489 | // 0x50 ---- 490 | { 491 | .mnemonic = NULL, 492 | .numOperands = 0, 493 | .operands = {0,0,0,0} 494 | }, 495 | // 0x51 ---- 496 | { 497 | .mnemonic = NULL, 498 | .numOperands = 0, 499 | .operands = {0,0,0,0} 500 | }, 501 | // 0x52 ---- 502 | { 503 | .mnemonic = NULL, 504 | .numOperands = 0, 505 | .operands = {0,0,0,0} 506 | }, 507 | // 0x53 ---- 508 | { 509 | .mnemonic = NULL, 510 | .numOperands = 0, 511 | .operands = {0,0,0,0} 512 | }, 513 | // 0x54 ---- 514 | { 515 | .mnemonic = NULL, 516 | .numOperands = 0, 517 | .operands = {0,0,0,0} 518 | }, 519 | // 0x55 ---- 520 | { 521 | .mnemonic = NULL, 522 | .numOperands = 0, 523 | .operands = {0,0,0,0} 524 | }, 525 | // 0x56 ---- 526 | { 527 | .mnemonic = NULL, 528 | .numOperands = 0, 529 | .operands = {0,0,0,0} 530 | }, 531 | // 0x57 ----- 532 | { 533 | .mnemonic = NULL, 534 | .numOperands = 0, 535 | .operands = {0,0,0,0} 536 | }, 537 | // 0x58 ---- 538 | { 539 | .mnemonic = "settimer?", 540 | .numOperands = 0, 541 | .operands = {0,0,0,0} 542 | }, 543 | // 0x59 ---- 544 | { 545 | .mnemonic = NULL, 546 | .numOperands = 0, 547 | .operands = {0,0,0,0} 548 | }, 549 | // 0x5A ---- 550 | { 551 | .mnemonic = NULL, 552 | .numOperands = 0, 553 | .operands = {0,0,0,0} 554 | }, 555 | // 0x5B ---- 556 | { 557 | .mnemonic = NULL, 558 | .numOperands = 0, 559 | .operands = {0,0,0,0} 560 | }, 561 | // 0x5C ---- 562 | { 563 | .mnemonic = NULL, 564 | .numOperands = 0, 565 | .operands = {0,0,0,0} 566 | }, 567 | // 0x5D ----- 568 | { 569 | .mnemonic = NULL, 570 | .numOperands = 0, 571 | .operands = {0,0,0,0} 572 | }, 573 | // 0x5E ----- 574 | { 575 | .mnemonic = NULL, 576 | .numOperands = 0, 577 | .operands = {0,0,0,0} 578 | }, 579 | // 0x5F ----- 580 | { 581 | .mnemonic = NULL, 582 | .numOperands = 0, 583 | .operands = {0,0,0,0} 584 | }, 585 | // 0x60 ---- 586 | { 587 | .mnemonic = NULL, 588 | .numOperands = 0, 589 | .operands = {0,0,0,0} 590 | }, 591 | // 0x61 ---- 592 | { 593 | .mnemonic = NULL, 594 | .numOperands = 0, 595 | .operands = {0,0,0,0} 596 | }, 597 | // 0x62 ---- 598 | { 599 | .mnemonic = NULL, 600 | .numOperands = 0, 601 | .operands = {0,0,0,0} 602 | }, 603 | // 0x63 ---- 604 | { 605 | .mnemonic = NULL, 606 | .numOperands = 0, 607 | .operands = {0,0,0,0} 608 | }, 609 | // 0x64 ---- 610 | { 611 | .mnemonic = NULL, 612 | .numOperands = 0, 613 | .operands = {0,0,0,0} 614 | }, 615 | // 0x65 ---- 616 | { 617 | .mnemonic = NULL, 618 | .numOperands = 0, 619 | .operands = {0,0,0,0} 620 | }, 621 | // 0x66 ---- 622 | { 623 | .mnemonic = NULL, 624 | .numOperands = 0, 625 | .operands = {0,0,0,0} 626 | }, 627 | // 0x67 ----- 628 | { 629 | .mnemonic = NULL, 630 | .numOperands = 0, 631 | .operands = {0,0,0,0} 632 | }, 633 | // 0x68 ---- 634 | { 635 | .mnemonic = "capturecloseevent?", // PTR_DAT_0048e39c = &DAT_004c058c 636 | .numOperands = 0, 637 | .operands = {0,0,0,0} 638 | }, 639 | // 0x69 ---- 640 | { 641 | .mnemonic = NULL, 642 | .numOperands = 0, 643 | .operands = {0,0,0,0} 644 | }, 645 | // 0x6A ---- 646 | { 647 | .mnemonic = NULL, 648 | .numOperands = 0, 649 | .operands = {0,0,0,0} 650 | }, 651 | // 0x6B ---- 652 | { 653 | .mnemonic = NULL, 654 | .numOperands = 0, 655 | .operands = {0,0,0,0} 656 | }, 657 | // 0x6C ---- 658 | { 659 | .mnemonic = NULL, 660 | .numOperands = 0, 661 | .operands = {0,0,0,0} 662 | }, 663 | // 0x6D ----- 664 | { 665 | .mnemonic = NULL, 666 | .numOperands = 0, 667 | .operands = {0,0,0,0} 668 | }, 669 | // 0x6E ----- 670 | { 671 | .mnemonic = NULL, 672 | .numOperands = 0, 673 | .operands = {0,0,0,0} 674 | }, 675 | // 0x6F ----- 676 | { 677 | .mnemonic = NULL, 678 | .numOperands = 0, 679 | .operands = {0,0,0,0} 680 | }, 681 | // 0x70 ---- 682 | { 683 | .mnemonic = "allocglobalmem", // Allocates memory into gGlobalMem 684 | .numOperands = 0, 685 | .operands = {0,0,0,0} 686 | }, 687 | // 0x71 ---- 688 | { 689 | .mnemonic = NULL, 690 | .numOperands = 0, 691 | .operands = {0,0,0,0} 692 | }, 693 | // 0x72 ---- 694 | { 695 | .mnemonic = NULL, 696 | .numOperands = 0, 697 | .operands = {0,0,0,0} 698 | }, 699 | // 0x73 ---- 700 | { 701 | .mnemonic = NULL, 702 | .numOperands = 0, 703 | .operands = {0,0,0,0} 704 | }, 705 | // 0x74 ---- 706 | { 707 | .mnemonic = NULL, 708 | .numOperands = 0, 709 | .operands = {0,0,0,0} 710 | }, 711 | // 0x75 ---- 712 | { 713 | .mnemonic = NULL, 714 | .numOperands = 0, 715 | .operands = {0,0,0,0} 716 | }, 717 | // 0x76 ---- 718 | { 719 | .mnemonic = NULL, 720 | .numOperands = 0, 721 | .operands = {0,0,0,0} 722 | }, 723 | // 0x77 ----- 724 | { 725 | .mnemonic = NULL, 726 | .numOperands = 0, 727 | .operands = {0,0,0,0} 728 | }, 729 | // 0x78 ---- 730 | { 731 | .mnemonic = NULL, 732 | .numOperands = 0, 733 | .operands = {0,0,0,0} 734 | }, 735 | // 0x79 ---- 736 | { 737 | .mnemonic = NULL, 738 | .numOperands = 0, 739 | .operands = {0,0,0,0} 740 | }, 741 | // 0x7A ---- 742 | { 743 | .mnemonic = NULL, 744 | .numOperands = 0, 745 | .operands = {0,0,0,0} 746 | }, 747 | // 0x7B ---- 748 | { 749 | .mnemonic = NULL, 750 | .numOperands = 0, 751 | .operands = {0,0,0,0} 752 | }, 753 | // 0x7C ---- 754 | { 755 | .mnemonic = NULL, 756 | .numOperands = 0, 757 | .operands = {0,0,0,0} 758 | }, 759 | // 0x7D ----- 760 | { 761 | .mnemonic = NULL, 762 | .numOperands = 0, 763 | .operands = {0,0,0,0} 764 | }, 765 | // 0x7E ----- 766 | { 767 | .mnemonic = NULL, 768 | .numOperands = 0, 769 | .operands = {0,0,0,0} 770 | }, 771 | // 0x7F ----- 772 | { 773 | .mnemonic = NULL, 774 | .numOperands = 0, 775 | .operands = {0,0,0,0} 776 | }, 777 | // 0x80 ---- 778 | { 779 | .mnemonic = NULL, 780 | .numOperands = 0, 781 | .operands = {0,0,0,0} 782 | }, 783 | // 0x81 ---- 784 | { 785 | .mnemonic = NULL, 786 | .numOperands = 0, 787 | .operands = {0,0,0,0} 788 | }, 789 | // 0x82 ---- 790 | { 791 | .mnemonic = NULL, 792 | .numOperands = 0, 793 | .operands = {0,0,0,0} 794 | }, 795 | // 0x83 ---- 796 | { 797 | .mnemonic = NULL, 798 | .numOperands = 0, 799 | .operands = {0,0,0,0} 800 | }, 801 | // 0x84 ---- 802 | { 803 | .mnemonic = NULL, 804 | .numOperands = 0, 805 | .operands = {0,0,0,0} 806 | }, 807 | // 0x85 ---- 808 | { 809 | .mnemonic = NULL, 810 | .numOperands = 0, 811 | .operands = {0,0,0,0} 812 | }, 813 | // 0x86 ---- 814 | { 815 | .mnemonic = NULL, 816 | .numOperands = 0, 817 | .operands = {0,0,0,0} 818 | }, 819 | // 0x87 ----- 820 | { 821 | .mnemonic = NULL, 822 | .numOperands = 0, 823 | .operands = {0,0,0,0} 824 | }, 825 | // 0x88 ---- 826 | { 827 | .mnemonic = NULL, 828 | .numOperands = 0, 829 | .operands = {0,0,0,0} 830 | }, 831 | // 0x89 ---- 832 | { 833 | .mnemonic = NULL, 834 | .numOperands = 0, 835 | .operands = {0,0,0,0} 836 | }, 837 | // 0x8A ---- 838 | { 839 | .mnemonic = NULL, 840 | .numOperands = 0, 841 | .operands = {0,0,0,0} 842 | }, 843 | // 0x8B ---- 844 | { 845 | .mnemonic = NULL, 846 | .numOperands = 0, 847 | .operands = {0,0,0,0} 848 | }, 849 | // 0x8C ---- 850 | { 851 | .mnemonic = NULL, 852 | .numOperands = 0, 853 | .operands = {0,0,0,0} 854 | }, 855 | // 0x8D ----- 856 | { 857 | .mnemonic = NULL, 858 | .numOperands = 0, 859 | .operands = {0,0,0,0} 860 | }, 861 | // 0x8E ----- 862 | { 863 | .mnemonic = NULL, 864 | .numOperands = 0, 865 | .operands = {0,0,0,0} 866 | }, 867 | // 0x8F ----- 868 | { 869 | .mnemonic = NULL, 870 | .numOperands = 0, 871 | .operands = {0,0,0,0} 872 | }, 873 | // 0x90 ---- 874 | { 875 | .mnemonic = NULL, 876 | .numOperands = 0, 877 | .operands = {0,0,0,0} 878 | }, 879 | // 0x91 ---- 880 | { 881 | .mnemonic = NULL, 882 | .numOperands = 0, 883 | .operands = {0,0,0,0} 884 | }, 885 | // 0x92 ---- 886 | { 887 | .mnemonic = NULL, 888 | .numOperands = 0, 889 | .operands = {0,0,0,0} 890 | }, 891 | // 0x93 ---- 892 | { 893 | .mnemonic = NULL, 894 | .numOperands = 0, 895 | .operands = {0,0,0,0} 896 | }, 897 | // 0x94 ---- 898 | { 899 | .mnemonic = NULL, 900 | .numOperands = 0, 901 | .operands = {0,0,0,0} 902 | }, 903 | // 0x95 ---- 904 | { 905 | .mnemonic = NULL, 906 | .numOperands = 0, 907 | .operands = {0,0,0,0} 908 | }, 909 | // 0x96 ---- 910 | { 911 | .mnemonic = NULL, 912 | .numOperands = 0, 913 | .operands = {0,0,0,0} 914 | }, 915 | // 0x97 ----- 916 | { 917 | .mnemonic = NULL, 918 | .numOperands = 0, 919 | .operands = {0,0,0,0} 920 | }, 921 | // 0x98 ---- 922 | { 923 | .mnemonic = NULL, 924 | .numOperands = 0, 925 | .operands = {0,0,0,0} 926 | }, 927 | // 0x99 ---- 928 | { 929 | .mnemonic = NULL, 930 | .numOperands = 0, 931 | .operands = {0,0,0,0} 932 | }, 933 | // 0x9A ---- 934 | { 935 | .mnemonic = NULL, 936 | .numOperands = 0, 937 | .operands = {0,0,0,0} 938 | }, 939 | // 0x9B ---- 940 | { 941 | .mnemonic = NULL, 942 | .numOperands = 0, 943 | .operands = {0,0,0,0} 944 | }, 945 | // 0x9C ---- 946 | { 947 | .mnemonic = NULL, 948 | .numOperands = 0, 949 | .operands = {0,0,0,0} 950 | }, 951 | // 0x9D ----- 952 | { 953 | .mnemonic = NULL, 954 | .numOperands = 0, 955 | .operands = {0,0,0,0} 956 | }, 957 | // 0x9E ----- 958 | { 959 | .mnemonic = NULL, 960 | .numOperands = 0, 961 | .operands = {0,0,0,0} 962 | }, 963 | // 0x9F ----- 964 | { 965 | .mnemonic = NULL, 966 | .numOperands = 0, 967 | .operands = {0,0,0,0} 968 | }, 969 | // 0xA0 ---- 970 | { 971 | .mnemonic = NULL, 972 | .numOperands = 0, 973 | .operands = {0,0,0,0} 974 | }, 975 | // 0xA1 ---- 976 | { 977 | .mnemonic = NULL, 978 | .numOperands = 0, 979 | .operands = {0,0,0,0} 980 | }, 981 | // 0xA2 ---- 982 | { 983 | .mnemonic = NULL, 984 | .numOperands = 0, 985 | .operands = {0,0,0,0} 986 | }, 987 | // 0xA3 ---- 988 | { 989 | .mnemonic = NULL, 990 | .numOperands = 0, 991 | .operands = {0,0,0,0} 992 | }, 993 | // 0xA4 ---- 994 | { 995 | .mnemonic = NULL, 996 | .numOperands = 0, 997 | .operands = {0,0,0,0} 998 | }, 999 | // 0xA5 ---- 1000 | { 1001 | .mnemonic = NULL, 1002 | .numOperands = 0, 1003 | .operands = {0,0,0,0} 1004 | }, 1005 | // 0xA6 ---- 1006 | { 1007 | .mnemonic = NULL, 1008 | .numOperands = 0, 1009 | .operands = {0,0,0,0} 1010 | }, 1011 | // 0xA7 ----- 1012 | { 1013 | .mnemonic = NULL, 1014 | .numOperands = 0, 1015 | .operands = {0,0,0,0} 1016 | }, 1017 | // 0xA8 ---- 1018 | { 1019 | .mnemonic = NULL, 1020 | .numOperands = 0, 1021 | .operands = {0,0,0,0} 1022 | }, 1023 | // 0xA9 ---- 1024 | { 1025 | .mnemonic = NULL, 1026 | .numOperands = 0, 1027 | .operands = {0,0,0,0} 1028 | }, 1029 | // 0xAA ---- 1030 | { 1031 | .mnemonic = NULL, 1032 | .numOperands = 0, 1033 | .operands = {0,0,0,0} 1034 | }, 1035 | // 0xAB ---- 1036 | { 1037 | .mnemonic = NULL, 1038 | .numOperands = 0, 1039 | .operands = {0,0,0,0} 1040 | }, 1041 | // 0xAC ---- 1042 | { 1043 | .mnemonic = NULL, 1044 | .numOperands = 0, 1045 | .operands = {0,0,0,0} 1046 | }, 1047 | // 0xAD ----- 1048 | { 1049 | .mnemonic = NULL, 1050 | .numOperands = 0, 1051 | .operands = {0,0,0,0} 1052 | }, 1053 | // 0xAE ----- 1054 | { 1055 | .mnemonic = NULL, 1056 | .numOperands = 0, 1057 | .operands = {0,0,0,0} 1058 | }, 1059 | // 0xAF ----- 1060 | { 1061 | .mnemonic = NULL, 1062 | .numOperands = 0, 1063 | .operands = {0,0,0,0} 1064 | }, 1065 | // 0xB0 ---- 1066 | { 1067 | .mnemonic = NULL, 1068 | .numOperands = 0, 1069 | .operands = {0,0,0,0} 1070 | }, 1071 | // 0xB1 ---- 1072 | { 1073 | .mnemonic = NULL, 1074 | .numOperands = 0, 1075 | .operands = {0,0,0,0} 1076 | }, 1077 | // 0xB2 ---- 1078 | { 1079 | .mnemonic = NULL, 1080 | .numOperands = 0, 1081 | .operands = {0,0,0,0} 1082 | }, 1083 | // 0xB3 ---- 1084 | { 1085 | .mnemonic = NULL, 1086 | .numOperands = 0, 1087 | .operands = {0,0,0,0} 1088 | }, 1089 | // 0xB4 ---- 1090 | { 1091 | .mnemonic = NULL, 1092 | .numOperands = 0, 1093 | .operands = {0,0,0,0} 1094 | }, 1095 | // 0xB5 ---- 1096 | { 1097 | .mnemonic = NULL, 1098 | .numOperands = 0, 1099 | .operands = {0,0,0,0} 1100 | }, 1101 | // 0xB6 ---- 1102 | { 1103 | .mnemonic = NULL, 1104 | .numOperands = 0, 1105 | .operands = {0,0,0,0} 1106 | }, 1107 | // 0xB7 ----- 1108 | { 1109 | .mnemonic = NULL, 1110 | .numOperands = 0, 1111 | .operands = {0,0,0,0} 1112 | }, 1113 | // 0xB8 ---- 1114 | { 1115 | .mnemonic = NULL, 1116 | .numOperands = 0, 1117 | .operands = {0,0,0,0} 1118 | }, 1119 | // 0xB9 ---- 1120 | { 1121 | .mnemonic = NULL, 1122 | .numOperands = 0, 1123 | .operands = {0,0,0,0} 1124 | }, 1125 | // 0xBA ---- 1126 | { 1127 | .mnemonic = NULL, 1128 | .numOperands = 0, 1129 | .operands = {0,0,0,0} 1130 | }, 1131 | // 0xBB ---- 1132 | { 1133 | .mnemonic = NULL, 1134 | .numOperands = 0, 1135 | .operands = {0,0,0,0} 1136 | }, 1137 | // 0xBC ---- 1138 | { 1139 | .mnemonic = NULL, 1140 | .numOperands = 0, 1141 | .operands = {0,0,0,0} 1142 | }, 1143 | // 0xBD ----- 1144 | { 1145 | .mnemonic = NULL, 1146 | .numOperands = 0, 1147 | .operands = {0,0,0,0} 1148 | }, 1149 | // 0xBE ----- 1150 | { 1151 | .mnemonic = NULL, 1152 | .numOperands = 0, 1153 | .operands = {0,0,0,0} 1154 | }, 1155 | // 0xBF ----- 1156 | { 1157 | .mnemonic = NULL, 1158 | .numOperands = 0, 1159 | .operands = {0,0,0,0} 1160 | }, 1161 | // 0xC0 ---- 1162 | { 1163 | .mnemonic = NULL, 1164 | .numOperands = 0, 1165 | .operands = {0,0,0,0} 1166 | }, 1167 | // 0xC1 ---- 1168 | { 1169 | .mnemonic = NULL, 1170 | .numOperands = 0, 1171 | .operands = {0,0,0,0} 1172 | }, 1173 | // 0xC2 ---- 1174 | { 1175 | .mnemonic = NULL, 1176 | .numOperands = 0, 1177 | .operands = {0,0,0,0} 1178 | }, 1179 | // 0xC3 ---- 1180 | { 1181 | .mnemonic = NULL, 1182 | .numOperands = 0, 1183 | .operands = {0,0,0,0} 1184 | }, 1185 | // 0xC4 ---- 1186 | { 1187 | .mnemonic = NULL, 1188 | .numOperands = 0, 1189 | .operands = {0,0,0,0} 1190 | }, 1191 | // 0xC5 ---- 1192 | { 1193 | .mnemonic = NULL, 1194 | .numOperands = 0, 1195 | .operands = {0,0,0,0} 1196 | }, 1197 | // 0xC6 ---- 1198 | { 1199 | .mnemonic = NULL, 1200 | .numOperands = 0, 1201 | .operands = {0,0,0,0} 1202 | }, 1203 | // 0xC7 ----- 1204 | { 1205 | .mnemonic = NULL, 1206 | .numOperands = 0, 1207 | .operands = {0,0,0,0} 1208 | }, 1209 | // 0xC8 ---- 1210 | { 1211 | .mnemonic = NULL, 1212 | .numOperands = 0, 1213 | .operands = {0,0,0,0} 1214 | }, 1215 | // 0xC9 ---- 1216 | { 1217 | .mnemonic = NULL, 1218 | .numOperands = 0, 1219 | .operands = {0,0,0,0} 1220 | }, 1221 | // 0xCA ---- 1222 | { 1223 | .mnemonic = NULL, 1224 | .numOperands = 0, 1225 | .operands = {0,0,0,0} 1226 | }, 1227 | // 0xCB ---- 1228 | { 1229 | .mnemonic = NULL, 1230 | .numOperands = 0, 1231 | .operands = {0,0,0,0} 1232 | }, 1233 | // 0xCC ---- 1234 | { 1235 | .mnemonic = NULL, 1236 | .numOperands = 0, 1237 | .operands = {0,0,0,0} 1238 | }, 1239 | // 0xCD ----- 1240 | { 1241 | .mnemonic = NULL, 1242 | .numOperands = 0, 1243 | .operands = {0,0,0,0} 1244 | }, 1245 | // 0xCE ----- 1246 | { 1247 | .mnemonic = NULL, 1248 | .numOperands = 0, 1249 | .operands = {0,0,0,0} 1250 | }, 1251 | // 0xCF ----- 1252 | { 1253 | .mnemonic = NULL, 1254 | .numOperands = 0, 1255 | .operands = {0,0,0,0} 1256 | }, 1257 | // 0xD0 ---- 1258 | { 1259 | .mnemonic = NULL, 1260 | .numOperands = 0, 1261 | .operands = {0,0,0,0} 1262 | }, 1263 | // 0xD1 ---- 1264 | { 1265 | .mnemonic = NULL, 1266 | .numOperands = 0, 1267 | .operands = {0,0,0,0} 1268 | }, 1269 | // 0xD2 ---- 1270 | { 1271 | .mnemonic = NULL, 1272 | .numOperands = 0, 1273 | .operands = {0,0,0,0} 1274 | }, 1275 | // 0xD3 ---- 1276 | { 1277 | .mnemonic = NULL, 1278 | .numOperands = 0, 1279 | .operands = {0,0,0,0} 1280 | }, 1281 | // 0xD4 ---- 1282 | { 1283 | .mnemonic = NULL, 1284 | .numOperands = 0, 1285 | .operands = {0,0,0,0} 1286 | }, 1287 | // 0xD5 ---- 1288 | { 1289 | .mnemonic = NULL, 1290 | .numOperands = 0, 1291 | .operands = {0,0,0,0} 1292 | }, 1293 | // 0xD6 ---- 1294 | { 1295 | .mnemonic = NULL, 1296 | .numOperands = 0, 1297 | .operands = {0,0,0,0} 1298 | }, 1299 | // 0xD7 ----- 1300 | { 1301 | .mnemonic = NULL, 1302 | .numOperands = 0, 1303 | .operands = {0,0,0,0} 1304 | }, 1305 | // 0xD8 ---- 1306 | { 1307 | .mnemonic = NULL, 1308 | .numOperands = 0, 1309 | .operands = {0,0,0,0} 1310 | }, 1311 | // 0xD9 ---- 1312 | { 1313 | .mnemonic = NULL, 1314 | .numOperands = 0, 1315 | .operands = {0,0,0,0} 1316 | }, 1317 | // 0xDA ---- 1318 | { 1319 | .mnemonic = NULL, 1320 | .numOperands = 0, 1321 | .operands = {0,0,0,0} 1322 | }, 1323 | // 0xDB ---- 1324 | { 1325 | .mnemonic = NULL, 1326 | .numOperands = 0, 1327 | .operands = {0,0,0,0} 1328 | }, 1329 | // 0xDC ---- 1330 | { 1331 | .mnemonic = NULL, 1332 | .numOperands = 0, 1333 | .operands = {0,0,0,0} 1334 | }, 1335 | // 0xDD ----- 1336 | { 1337 | .mnemonic = NULL, 1338 | .numOperands = 0, 1339 | .operands = {0,0,0,0} 1340 | }, 1341 | // 0xDE ----- 1342 | { 1343 | .mnemonic = NULL, 1344 | .numOperands = 0, 1345 | .operands = {0,0,0,0} 1346 | }, 1347 | // 0xDF ----- 1348 | { 1349 | .mnemonic = NULL, 1350 | .numOperands = 0, 1351 | .operands = {0,0,0,0} 1352 | }, 1353 | // 0xE0 ---- 1354 | { 1355 | .mnemonic = NULL, 1356 | .numOperands = 0, 1357 | .operands = {0,0,0,0} 1358 | }, 1359 | // 0xE1 ---- 1360 | { 1361 | .mnemonic = NULL, 1362 | .numOperands = 0, 1363 | .operands = {0,0,0,0} 1364 | }, 1365 | // 0xE2 ---- 1366 | { 1367 | .mnemonic = NULL, 1368 | .numOperands = 0, 1369 | .operands = {0,0,0,0} 1370 | }, 1371 | // 0xE3 ---- 1372 | { 1373 | .mnemonic = NULL, 1374 | .numOperands = 0, 1375 | .operands = {0,0,0,0} 1376 | }, 1377 | // 0xE4 ---- 1378 | { 1379 | .mnemonic = NULL, 1380 | .numOperands = 0, 1381 | .operands = {0,0,0,0} 1382 | }, 1383 | // 0xE5 ---- 1384 | { 1385 | .mnemonic = NULL, 1386 | .numOperands = 0, 1387 | .operands = {0,0,0,0} 1388 | }, 1389 | // 0xE6 ---- 1390 | { 1391 | .mnemonic = NULL, 1392 | .numOperands = 0, 1393 | .operands = {0,0,0,0} 1394 | }, 1395 | // 0xE7 ----- 1396 | { 1397 | .mnemonic = NULL, 1398 | .numOperands = 0, 1399 | .operands = {0,0,0,0} 1400 | }, 1401 | // 0xE8 ---- 1402 | { 1403 | .mnemonic = NULL, 1404 | .numOperands = 0, 1405 | .operands = {0,0,0,0} 1406 | }, 1407 | // 0xE9 ---- 1408 | { 1409 | .mnemonic = NULL, 1410 | .numOperands = 0, 1411 | .operands = {0,0,0,0} 1412 | }, 1413 | // 0xEA ---- 1414 | { 1415 | .mnemonic = NULL, 1416 | .numOperands = 0, 1417 | .operands = {0,0,0,0} 1418 | }, 1419 | // 0xEB ---- 1420 | { 1421 | .mnemonic = NULL, 1422 | .numOperands = 0, 1423 | .operands = {0,0,0,0} 1424 | }, 1425 | // 0xEC ---- 1426 | { 1427 | .mnemonic = NULL, 1428 | .numOperands = 0, 1429 | .operands = {0,0,0,0} 1430 | }, 1431 | // 0xED ----- 1432 | { 1433 | .mnemonic = NULL, 1434 | .numOperands = 0, 1435 | .operands = {0,0,0,0} 1436 | }, 1437 | // 0xEE ----- 1438 | { 1439 | .mnemonic = NULL, 1440 | .numOperands = 0, 1441 | .operands = {0,0,0,0} 1442 | }, 1443 | // 0xEF ----- 1444 | { 1445 | .mnemonic = NULL, 1446 | .numOperands = 0, 1447 | .operands = {0,0,0,0} 1448 | }, 1449 | // 0xF0 ---- 1450 | { 1451 | .mnemonic = NULL, 1452 | .numOperands = 0, 1453 | .operands = {0,0,0,0} 1454 | }, 1455 | // 0xF1 ---- 1456 | { 1457 | .mnemonic = NULL, 1458 | .numOperands = 0, 1459 | .operands = {0,0,0,0} 1460 | }, 1461 | // 0xF2 ---- 1462 | { 1463 | .mnemonic = NULL, 1464 | .numOperands = 0, 1465 | .operands = {0,0,0,0} 1466 | }, 1467 | // 0xF3 ---- 1468 | { 1469 | .mnemonic = NULL, 1470 | .numOperands = 0, 1471 | .operands = {0,0,0,0} 1472 | }, 1473 | // 0xF4 ---- 1474 | { 1475 | .mnemonic = NULL, 1476 | .numOperands = 0, 1477 | .operands = {0,0,0,0} 1478 | }, 1479 | // 0xF5 ---- 1480 | { 1481 | .mnemonic = NULL, 1482 | .numOperands = 0, 1483 | .operands = {0,0,0,0} 1484 | }, 1485 | // 0xF6 ---- 1486 | { 1487 | .mnemonic = NULL, 1488 | .numOperands = 0, 1489 | .operands = {0,0,0,0} 1490 | }, 1491 | // 0xF7 ----- 1492 | { 1493 | .mnemonic = NULL, 1494 | .numOperands = 0, 1495 | .operands = {0,0,0,0} 1496 | }, 1497 | // 0xF8 ---- 1498 | { 1499 | .mnemonic = NULL, 1500 | .numOperands = 0, 1501 | .operands = {0,0,0,0} 1502 | }, 1503 | // 0xF9 ---- 1504 | { 1505 | .mnemonic = NULL, 1506 | .numOperands = 0, 1507 | .operands = {0,0,0,0} 1508 | }, 1509 | // 0xFA ---- 1510 | { 1511 | .mnemonic = NULL, 1512 | .numOperands = 0, 1513 | .operands = {0,0,0,0} 1514 | }, 1515 | // 0xFB ---- 1516 | { 1517 | .mnemonic = NULL, 1518 | .numOperands = 0, 1519 | .operands = {0,0,0,0} 1520 | }, 1521 | // 0xFC ---- 1522 | { 1523 | .mnemonic = NULL, 1524 | .numOperands = 0, 1525 | .operands = {0,0,0,0} 1526 | }, 1527 | // 0xFD ----- 1528 | { 1529 | .mnemonic = "islauncher", 1530 | .numOperands = 0, 1531 | .operands = {0,0,0,0} 1532 | }, 1533 | // 0xFE ----- 1534 | { 1535 | .mnemonic = NULL, 1536 | .numOperands = 0, 1537 | .operands = {0,0,0,0} 1538 | }, 1539 | // 0xFF ----- 1540 | { 1541 | .mnemonic = NULL, 1542 | .numOperands = 0, 1543 | .operands = {0,0,0,0} 1544 | } 1545 | }; 1546 | -------------------------------------------------------------------------------- /src/op_basic.c: -------------------------------------------------------------------------------- 1 | // 2 | // Basic opcode re-implementations 3 | // 4 | 5 | #include "bgi.h" 6 | #include "patch.h" 7 | #include "debug.h" 8 | 9 | // ----------------------------------------------------------------------------- 10 | // Mnemonic: push8 11 | // Opcode: 0x00 12 | // Stack in: 0 13 | // Stack out: 1 14 | // Bytes: 2 15 | // ----------------------------------------------------------------------------- 16 | int op_push8(VMThread_t* thread) 17 | { 18 | BGI_PushStack(thread, BGI_ReadCode8(thread)); 19 | return 0; 20 | } 21 | 22 | // ----------------------------------------------------------------------------- 23 | // Mnemonic: push16 24 | // Opcode: 0x01 25 | // Stack in: 0 26 | // Stack out: 1 27 | // Bytes: 3 28 | // ----------------------------------------------------------------------------- 29 | int op_push16(VMThread_t* thread) 30 | { 31 | BGI_PushStack(thread, BGI_ReadCode16(thread)); 32 | return 0; 33 | } 34 | 35 | // ----------------------------------------------------------------------------- 36 | // Mnemonic: push32 37 | // Opcode: 0x02 38 | // Stack in: 0 39 | // Stack out: 1 40 | // Bytes: 5 41 | // ----------------------------------------------------------------------------- 42 | int op_push32(VMThread_t* thread) 43 | { 44 | BGI_PushStack(thread, BGI_ReadCode32(thread)); 45 | return 0; 46 | } 47 | 48 | // ----------------------------------------------------------------------------- 49 | // Mnemonic: memptr 50 | // Opcode: 0x04 51 | // Stack in: 0 52 | // Stack out: 1 53 | // Bytes: 3 54 | // ----------------------------------------------------------------------------- 55 | int op_memptr(VMThread_t* thread) 56 | { 57 | uint16_t offset = BGI_ReadCode16(thread); 58 | uint32_t memPtr = BGI_GetMemPointer(thread); 59 | BGI_PushStack(thread, (memPtr - offset) | BGI_MEMORY_OFFSET); 60 | return 0; 61 | } 62 | 63 | // ----------------------------------------------------------------------------- 64 | // Mnemonic: codeptr 65 | // Opcode: 0x05 66 | // Stack in: 0 67 | // Stack out: 1 68 | // Bytes: 3 69 | // ----------------------------------------------------------------------------- 70 | int op_codeptr(VMThread_t* thread) 71 | { 72 | uint16_t offset = BGI_ReadCode16(thread); 73 | uint32_t ip = BGI_GetInstructionPointer(thread); 74 | BGI_PushStack(thread, (ip + offset) | BGI_CODE_OFFSET); 75 | return 0; 76 | } 77 | 78 | // ----------------------------------------------------------------------------- 79 | // Mnemonic: codeoffset 80 | // Opcode: 0x06 81 | // Stack in: 0 82 | // Stack out: 1 83 | // Bytes: 3 84 | // ----------------------------------------------------------------------------- 85 | int op_codeoffset(VMThread_t* thread) 86 | { 87 | int16_t offset = BGI_ReadCode16(thread); 88 | uint32_t ip = BGI_GetInstructionPointer(thread); 89 | BGI_PushStack(thread, ip + offset); 90 | return 0; 91 | } 92 | 93 | // ----------------------------------------------------------------------------- 94 | // Mnemonic: readmem 95 | // Opcode: 0x08 96 | // Stack in: 1 97 | // Stack out: 1 98 | // Bytes: 2 99 | // ----------------------------------------------------------------------------- 100 | int op_readmem(VMThread_t* thread) 101 | { 102 | uint8_t* ptr = BGI_PopAndResolveAddress(thread); 103 | int intSize = BGI_ReadCode8(thread); 104 | 105 | if(intSize == 0) 106 | BGI_PushStack(thread, *ptr); 107 | else if(intSize == 1) 108 | BGI_PushStack(thread, *(uint16_t*)ptr); 109 | else if(intSize == 2) 110 | BGI_PushStack(thread, *(uint32_t*)ptr); 111 | else 112 | BGI_PushStack(thread, (uint32_t)thread); // ??? 113 | 114 | return 0; 115 | } 116 | 117 | // ----------------------------------------------------------------------------- 118 | // Mnemonic: writecopy 119 | // Opcode: 0x09 120 | // Stack in: 2 121 | // Stack out: 1 122 | // Bytes: 1 123 | // ----------------------------------------------------------------------------- 124 | int op_writecopy(VMThread_t* thread) 125 | { 126 | uint32_t data = BGI_PopStack(thread); 127 | uint8_t* ptr = BGI_PopAndResolveAddress(thread); 128 | int intSize = BGI_ReadCode8(thread); 129 | 130 | // Write to mem 131 | BGI_WriteIntToMemory(ptr, intSize, data); 132 | 133 | // Push data back onto the stack 134 | BGI_PushStack(thread, data); 135 | 136 | return 0; 137 | } 138 | 139 | // ----------------------------------------------------------------------------- 140 | // Mnemonic: write 141 | // Opcode: 0x0A 142 | // Stack in: 2 143 | // Stack out: 0 144 | // Bytes: 1 145 | // ----------------------------------------------------------------------------- 146 | int op_write(VMThread_t* thread) 147 | { 148 | uint8_t* ptr = BGI_PopAndResolveAddress(thread); 149 | uint32_t data = BGI_PopStack(thread); 150 | int intSize = BGI_ReadCode8(thread); 151 | 152 | // Write to mem 153 | BGI_WriteIntToMemory(ptr, intSize, data); 154 | 155 | return 0; 156 | } 157 | 158 | // ----------------------------------------------------------------------------- 159 | // Mnemonic: copystack 160 | // Opcode: 0x0C 161 | // Stack in: 1+? 162 | // Stack out: 0 163 | // Bytes: 2 164 | // ----------------------------------------------------------------------------- 165 | int op_copystack(VMThread_t* thread) 166 | { 167 | int intSize = BGI_ReadCode8(thread); 168 | int count = BGI_ReadCode8(thread); 169 | 170 | // Pop all the values 171 | uint32_t values[256]; 172 | for(int i = 0; i < count; i++) 173 | values[i] = BGI_PopStack(thread); 174 | 175 | // Write all the values to memory in reverse order 176 | uint8_t* dst = BGI_PopAndResolveAddress(thread); 177 | for(int i = count-1; i >= 0; i--) 178 | { 179 | BGI_WriteIntToMemory(dst, intSize, values[i]); 180 | dst += 1 << intSize; 181 | } 182 | 183 | return 0; 184 | } 185 | 186 | // ----------------------------------------------------------------------------- 187 | // Mnemonic: memptr 188 | // Opcode: 0x10 189 | // Stack in: 0 190 | // Stack out: 1 191 | // Bytes: 0 192 | // ----------------------------------------------------------------------------- 193 | int op_memptr2(VMThread_t* thread) 194 | { 195 | BGI_PushStack(thread, BGI_GetMemPointer(thread)); 196 | return 0; 197 | } 198 | 199 | // ----------------------------------------------------------------------------- 200 | // Mnemonic: storememptr 201 | // Opcode: 0x11 202 | // Stack in: 1 203 | // Stack out: 0 204 | // Bytes: 0 205 | // ----------------------------------------------------------------------------- 206 | int op_storememptr(VMThread_t* thread) 207 | { 208 | uint32_t newPtr = BGI_PopStack(thread); 209 | if(newPtr >= BGI_GetLocalMemSize(thread)) 210 | { 211 | MessageBox(NULL, "Out of bounds memptr", "Error", 0); 212 | ExitProcess(1); 213 | } 214 | BGI_SetMemPointer(thread, newPtr); 215 | return 0; 216 | } 217 | 218 | // ----------------------------------------------------------------------------- 219 | // Mnemonic: jmp 220 | // Opcode: 0x14 221 | // Stack in: 1 222 | // Stack out: 0 223 | // Bytes: 0 224 | // ----------------------------------------------------------------------------- 225 | int __cdecl op_jmp(VMThread_t* thread) 226 | { 227 | BGI_SetInstructionPointer(thread, BGI_PopStack(thread)); 228 | return 0; 229 | } 230 | 231 | // ----------------------------------------------------------------------------- 232 | // Mnemonic: [jnz, jz, jg, jge, jle, jl, ja] 233 | // Opcode: 0x15 234 | // Stack in: 2 235 | // Stack out: 0 236 | // Bytes: 1 237 | // ----------------------------------------------------------------------------- 238 | int op_cjmp(VMThread_t* thread) 239 | { 240 | uint8_t op = BGI_ReadCode8(thread); 241 | uint32_t dest = BGI_PopStack(thread); 242 | int32_t value = BGI_PopStack(thread); 243 | bool res = true; 244 | switch(op) 245 | { 246 | case 0: 247 | res = value != 0; 248 | break; 249 | case 1: 250 | res = value == 0; 251 | break; 252 | case 2: 253 | res = value > 0; 254 | break; 255 | case 3: 256 | res = value >= 0; 257 | break; 258 | case 4: 259 | res = value <= 0; 260 | break; 261 | case 5: 262 | res = value < 0; 263 | break; 264 | default: 265 | res = true; 266 | } 267 | if(res) 268 | { 269 | if(dest >= BGI_GetCodeSpaceSize(thread)) 270 | { 271 | printf("Error: Jump destination is outside code space\n"); 272 | haltExecution(thread); 273 | return 0; 274 | } 275 | BGI_SetInstructionPointer(thread, dest); 276 | } 277 | return 0; 278 | } 279 | 280 | // ----------------------------------------------------------------------------- 281 | // Mnemonic: call 282 | // Opcode: 0x16 283 | // Stack in: 1 284 | // Stack out: 0 285 | // Bytes: 0 286 | // ----------------------------------------------------------------------------- 287 | int op_call(VMThread_t* thread) 288 | { 289 | uint32_t ptr = BGI_GetMemPointer(thread); 290 | uint32_t size = BGI_GetLocalMemSize(thread); 291 | if(size <= ptr + 4) 292 | { 293 | // Out of memory (Tho the engine says スタック領域が不足しています) 294 | printf("Error: Out of memory\n"); 295 | haltExecution(thread); 296 | return 0; 297 | } 298 | 299 | uint32_t returnPtr = BGI_GetInstructionPointer(thread) + 1; 300 | BGI_WriteReturnAddr(thread, returnPtr); 301 | 302 | return op_jmp(thread); 303 | } 304 | 305 | // ----------------------------------------------------------------------------- 306 | // Mnemonic: ret 307 | // Opcode: 0x17 308 | // Stack in: 0 309 | // Stack out: 0 310 | // Bytes: 0 311 | // ----------------------------------------------------------------------------- 312 | int op_ret(VMThread_t* thread) 313 | { 314 | uint32_t memPtr = BGI_GetMemPointer(thread); 315 | if(memPtr != 0) 316 | { 317 | BGI_SetInstructionPointer(thread, BGI_ReadReturnAddr(thread)); 318 | return 0; 319 | } 320 | return 4; 321 | } 322 | 323 | // ----------------------------------------------------------------------------- 324 | // Mnemonic: add 325 | // Opcode: 0x20 326 | // Stack in: 2 327 | // Stack out: 1 328 | // Bytes: 0 329 | // ----------------------------------------------------------------------------- 330 | int op_add(VMThread_t* thread) 331 | { 332 | uint32_t right = BGI_PopStack(thread); 333 | uint32_t left = BGI_PopStack(thread); 334 | BGI_PushStack(thread, left + right); 335 | return 0; 336 | } 337 | 338 | // ----------------------------------------------------------------------------- 339 | // Mnemonic: sub 340 | // Opcode: 0x21 341 | // Stack in: 2 342 | // Stack out: 1 343 | // Bytes: 0 344 | // ----------------------------------------------------------------------------- 345 | int op_sub(VMThread_t* thread) 346 | { 347 | uint32_t right = BGI_PopStack(thread); 348 | uint32_t left = BGI_PopStack(thread); 349 | BGI_PushStack(thread, left - right); 350 | return 0; 351 | } 352 | 353 | // ----------------------------------------------------------------------------- 354 | // Mnemonic: mul 355 | // Opcode: 0x22 356 | // Stack in: 2 357 | // Stack out: 1 358 | // Bytes: 0 359 | // ----------------------------------------------------------------------------- 360 | int op_mul(VMThread_t* thread) 361 | { 362 | uint32_t right = BGI_PopStack(thread); 363 | uint32_t left = BGI_PopStack(thread); 364 | BGI_PushStack(thread, left * right); 365 | return 0; 366 | } 367 | 368 | // ----------------------------------------------------------------------------- 369 | // Mnemonic: div 370 | // Opcode: 0x23 371 | // Stack in: 2 372 | // Stack out: 1 373 | // Bytes: 0 374 | // ----------------------------------------------------------------------------- 375 | int op_div(VMThread_t* thread) 376 | { 377 | int32_t right = BGI_PopStack(thread); 378 | int32_t left = BGI_PopStack(thread); 379 | if(right == 0) 380 | BGI_PushStack(thread, -1); 381 | else 382 | BGI_PushStack(thread, left / right); 383 | return 0; 384 | } 385 | 386 | // ----------------------------------------------------------------------------- 387 | // Mnemonic: mod 388 | // Opcode: 0x24 389 | // Stack in: 2 390 | // Stack out: 1 391 | // Bytes: 0 392 | // ----------------------------------------------------------------------------- 393 | int op_mod(VMThread_t* thread) 394 | { 395 | int32_t right = BGI_PopStack(thread); 396 | int32_t left = BGI_PopStack(thread); 397 | if(right == 0) 398 | BGI_PushStack(thread, -1); 399 | else 400 | BGI_PushStack(thread, left % right); 401 | return 0; 402 | } 403 | 404 | // ----------------------------------------------------------------------------- 405 | // Mnemonic: and 406 | // Opcode: 0x25 407 | // Stack in: 2 408 | // Stack out: 1 409 | // Bytes: 0 410 | // ----------------------------------------------------------------------------- 411 | int op_and(VMThread_t* thread) 412 | { 413 | uint32_t right = BGI_PopStack(thread); 414 | uint32_t left = BGI_PopStack(thread); 415 | BGI_PushStack(thread, left & right); 416 | return 0; 417 | } 418 | 419 | // ----------------------------------------------------------------------------- 420 | // Mnemonic: or 421 | // Opcode: 0x26 422 | // Stack in: 2 423 | // Stack out: 1 424 | // Bytes: 0 425 | // ----------------------------------------------------------------------------- 426 | int op_or(VMThread_t* thread) 427 | { 428 | uint32_t right = BGI_PopStack(thread); 429 | uint32_t left = BGI_PopStack(thread); 430 | BGI_PushStack(thread, left | right); 431 | return 0; 432 | } 433 | 434 | // ----------------------------------------------------------------------------- 435 | // Mnemonic: xor 436 | // Opcode: 0x27 437 | // Stack in: 2 438 | // Stack out: 1 439 | // Bytes: 0 440 | // ----------------------------------------------------------------------------- 441 | int op_xor(VMThread_t* thread) 442 | { 443 | uint32_t right = BGI_PopStack(thread); 444 | uint32_t left = BGI_PopStack(thread); 445 | BGI_PushStack(thread, left ^ right); 446 | return 0; 447 | } 448 | 449 | // ----------------------------------------------------------------------------- 450 | // Mnemonic: not 451 | // Opcode: 0x28 452 | // Stack in: 1 453 | // Stack out: 1 454 | // Bytes: 0 455 | // ----------------------------------------------------------------------------- 456 | int op_not(VMThread_t* thread) 457 | { 458 | uint32_t value = BGI_PopStack(thread); 459 | BGI_PushStack(thread, ~value); 460 | return 0; 461 | } 462 | 463 | // ----------------------------------------------------------------------------- 464 | // Mnemonic: shl 465 | // Opcode: 0x29 466 | // Stack in: 2 467 | // Stack out: 1 468 | // Bytes: 0 469 | // ----------------------------------------------------------------------------- 470 | int op_shl(VMThread_t* thread) 471 | { 472 | uint32_t right = BGI_PopStack(thread); 473 | uint32_t left = BGI_PopStack(thread); 474 | BGI_PushStack(thread, left << (right & 0x1F)); 475 | return 0; 476 | } 477 | 478 | // ----------------------------------------------------------------------------- 479 | // Mnemonic: shr 480 | // Opcode: 0x2A 481 | // Stack in: 2 482 | // Stack out: 1 483 | // Bytes: 0 484 | // ----------------------------------------------------------------------------- 485 | int op_shr(VMThread_t* thread) 486 | { 487 | uint32_t right = BGI_PopStack(thread); 488 | uint32_t left = BGI_PopStack(thread); 489 | BGI_PushStack(thread, left >> (right & 0x1F)); 490 | return 0; 491 | } 492 | 493 | // ----------------------------------------------------------------------------- 494 | // Mnemonic: sar 495 | // Opcode: 0x2B 496 | // Stack in: 2 497 | // Stack out: 1 498 | // Bytes: 0 499 | // ----------------------------------------------------------------------------- 500 | int op_sar(VMThread_t* thread) 501 | { 502 | int32_t right = BGI_PopStack(thread); 503 | int32_t left = BGI_PopStack(thread); 504 | BGI_PushStack(thread, left >> (right & 0x1F)); 505 | return 0; 506 | } 507 | 508 | // ----------------------------------------------------------------------------- 509 | // Mnemonic: eq 510 | // Opcode: 0x30 511 | // Stack in: 2 512 | // Stack out: 1 513 | // Bytes: 0 514 | // ----------------------------------------------------------------------------- 515 | int op_eq(VMThread_t* thread) 516 | { 517 | uint32_t right = BGI_PopStack(thread); 518 | uint32_t left = BGI_PopStack(thread); 519 | BGI_PushStack(thread, left == right); 520 | return 0; 521 | } 522 | 523 | // ----------------------------------------------------------------------------- 524 | // Mnemonic: neq 525 | // Opcode: 0x31 526 | // Stack in: 2 527 | // Stack out: 1 528 | // Bytes: 0 529 | // ----------------------------------------------------------------------------- 530 | int op_neq(VMThread_t* thread) 531 | { 532 | uint32_t right = BGI_PopStack(thread); 533 | uint32_t left = BGI_PopStack(thread); 534 | BGI_PushStack(thread, left != right); 535 | return 0; 536 | } 537 | 538 | // ----------------------------------------------------------------------------- 539 | // Mnemonic: leq 540 | // Opcode: 0x32 541 | // Stack in: 2 542 | // Stack out: 1 543 | // Bytes: 0 544 | // ----------------------------------------------------------------------------- 545 | int op_leq(VMThread_t* thread) 546 | { 547 | int32_t right = BGI_PopStack(thread); 548 | int32_t left = BGI_PopStack(thread); 549 | BGI_PushStack(thread, left <= right); 550 | return 0; 551 | } 552 | 553 | // ----------------------------------------------------------------------------- 554 | // Mnemonic: geq 555 | // Opcode: 0x33 556 | // Stack in: 2 557 | // Stack out: 1 558 | // Bytes: 0 559 | // ----------------------------------------------------------------------------- 560 | int op_geq(VMThread_t* thread) 561 | { 562 | int32_t right = BGI_PopStack(thread); 563 | int32_t left = BGI_PopStack(thread); 564 | BGI_PushStack(thread, left >= right); 565 | return 0; 566 | } 567 | 568 | // ----------------------------------------------------------------------------- 569 | // Mnemonic: le 570 | // Opcode: 0x34 571 | // Stack in: 2 572 | // Stack out: 1 573 | // Bytes: 0 574 | // ----------------------------------------------------------------------------- 575 | int op_le(VMThread_t* thread) 576 | { 577 | int32_t right = BGI_PopStack(thread); 578 | int32_t left = BGI_PopStack(thread); 579 | BGI_PushStack(thread, left < right); 580 | return 0; 581 | } 582 | 583 | // ----------------------------------------------------------------------------- 584 | // Mnemonic: ge 585 | // Opcode: 0x35 586 | // Stack in: 2 587 | // Stack out: 1 588 | // Bytes: 0 589 | // ----------------------------------------------------------------------------- 590 | int op_ge(VMThread_t* thread) 591 | { 592 | int32_t right = BGI_PopStack(thread); 593 | int32_t left = BGI_PopStack(thread); 594 | BGI_PushStack(thread, left > right); 595 | return 0; 596 | } 597 | 598 | // ----------------------------------------------------------------------------- 599 | // Mnemonic: dnotzero 600 | // Opcode: 0x38 601 | // Stack in: 2 602 | // Stack out: 1 603 | // Bytes: 0 604 | // ----------------------------------------------------------------------------- 605 | int op_dnotzero(VMThread_t* thread) 606 | { 607 | uint32_t right = BGI_PopStack(thread); 608 | uint32_t left = BGI_PopStack(thread); 609 | 610 | if(left || right) 611 | BGI_PushStack(thread, 1); 612 | else 613 | BGI_PushStack(thread, 0); 614 | return 0; 615 | } 616 | 617 | // ----------------------------------------------------------------------------- 618 | // Mnemonic: dnotzero2 619 | // Opcode: 0x39 620 | // Stack in: 2 621 | // Stack out: 1 622 | // Bytes: 0 623 | // ----------------------------------------------------------------------------- 624 | int op_dnotzero2(VMThread_t* thread) 625 | { 626 | uint32_t right = BGI_PopStack(thread); 627 | uint32_t left = BGI_PopStack(thread); 628 | 629 | if(left && right) 630 | BGI_PushStack(thread, 1); 631 | else 632 | BGI_PushStack(thread, 0); 633 | return 0; 634 | } 635 | 636 | // ----------------------------------------------------------------------------- 637 | // Mnemonic: iszero 638 | // Opcode: 0x3A 639 | // Stack in: 1 640 | // Stack out: 1 641 | // Bytes: 0 642 | // ----------------------------------------------------------------------------- 643 | int op_iszero(VMThread_t* thread) 644 | { 645 | BGI_PushStack(thread, BGI_PopStack(thread) == 0); 646 | return 0; 647 | } 648 | 649 | // ----------------------------------------------------------------------------- 650 | // Mnemonic: ternary 651 | // Opcode: 0x40 652 | // Stack in: 3 653 | // Stack out: 1 654 | // Bytes: 0 655 | // ----------------------------------------------------------------------------- 656 | int op_ternary(VMThread_t* thread) 657 | { 658 | uint32_t falseVal = BGI_PopStack(thread); 659 | uint32_t trueVal = BGI_PopStack(thread); 660 | uint32_t compare = BGI_PopStack(thread); 661 | 662 | if(compare) 663 | BGI_PushStack(thread, trueVal); 664 | else 665 | BGI_PushStack(thread, falseVal); 666 | 667 | return 0; 668 | } 669 | 670 | // ----------------------------------------------------------------------------- 671 | // Mnemonic: muldiv 672 | // Opcode: 0x42 673 | // Stack in: 3 674 | // Stack out: 1 675 | // Bytes: 0 676 | // ----------------------------------------------------------------------------- 677 | int op_muldiv(VMThread_t* thread) 678 | { 679 | int32_t divisor = BGI_PopStack(thread); 680 | int32_t multiplier = BGI_PopStack(thread); 681 | int32_t multiplicand = BGI_PopStack(thread); 682 | 683 | int64_t tmp = (int64_t)multiplicand * (int64_t)multiplier; 684 | if(divisor == 0) 685 | BGI_PushStack(thread, -1); 686 | else 687 | BGI_PushStack(thread, (int32_t)(tmp / (int64_t)divisor)); 688 | 689 | return 0; 690 | } 691 | 692 | // ----------------------------------------------------------------------------- 693 | // Mnemonic: sin 694 | // Opcode: 0x48 695 | // Stack in: 1 696 | // Stack out: 1 697 | // Bytes: 0 698 | // ----------------------------------------------------------------------------- 699 | int op_sin(VMThread_t* thread) 700 | { 701 | int32_t angle = BGI_PopStack(thread); 702 | 703 | double tmp = sin((double)angle * ((M_PI / 180.0l) / 65536.0l)); 704 | 705 | BGI_PushStack(thread, (int32_t)(tmp * 65536.0l)); 706 | 707 | return 0; 708 | } 709 | 710 | // ----------------------------------------------------------------------------- 711 | // Mnemonic: cos 712 | // Opcode: 0x49 713 | // Stack in: 1 714 | // Stack out: 1 715 | // Bytes: 0 716 | // ----------------------------------------------------------------------------- 717 | int op_cos(VMThread_t* thread) 718 | { 719 | int32_t angle = BGI_PopStack(thread); 720 | 721 | double tmp = cos((double)angle * ((M_PI / 180.0l) / 65536.0l)); 722 | 723 | BGI_PushStack(thread, (int32_t)(tmp * 65536.0l)); 724 | 725 | return 0; 726 | } 727 | 728 | // ----------------------------------------------------------------------------- 729 | // Mnemonic: memcpy 730 | // Opcode: 0x60 731 | // Stack in: 3 732 | // Stack out: 0 733 | // Bytes: 0 734 | // ----------------------------------------------------------------------------- 735 | int op_memcpy(VMThread_t* thread) 736 | { 737 | uint32_t size = BGI_PopStack(thread); 738 | uint8_t* src = BGI_PopAndResolveAddress(thread); 739 | uint8_t* dst = BGI_PopAndResolveAddress(thread); 740 | 741 | memcpy(dst, src, size); 742 | 743 | return 0; 744 | } 745 | 746 | // ----------------------------------------------------------------------------- 747 | // Mnemonic: memclr 748 | // Opcode: 0x61 749 | // Stack in: 2 750 | // Stack out: 0 751 | // Bytes: 0 752 | // ----------------------------------------------------------------------------- 753 | int op_memclr(VMThread_t* thread) 754 | { 755 | uint32_t size = BGI_PopStack(thread); 756 | uint8_t* ptr = BGI_PopAndResolveAddress(thread); 757 | 758 | memset(ptr, 0, size); 759 | 760 | return 0; 761 | } 762 | 763 | // ----------------------------------------------------------------------------- 764 | // Mnemonic: memset 765 | // Opcode: 0x62 766 | // Stack in: 3 767 | // Stack out: 0 768 | // Bytes: 0 769 | // ----------------------------------------------------------------------------- 770 | int op_memset(VMThread_t* thread) 771 | { 772 | uint32_t val = BGI_PopStack(thread); 773 | uint32_t size = BGI_PopStack(thread); 774 | uint8_t* ptr = BGI_PopAndResolveAddress(thread); 775 | 776 | memset(ptr, (uint8_t)val, size); 777 | 778 | return 0; 779 | } 780 | 781 | // ----------------------------------------------------------------------------- 782 | // Mnemonic: memcmp 783 | // Opcode: 0x63 784 | // Stack in: 3 785 | // Stack out: 1 786 | // Bytes: 0 787 | // ----------------------------------------------------------------------------- 788 | int op_memcmp(VMThread_t* thread) 789 | { 790 | uint32_t size = BGI_PopStack(thread); 791 | uint8_t* src = BGI_PopAndResolveAddress(thread); 792 | uint8_t* dst = BGI_PopAndResolveAddress(thread); 793 | 794 | if(memcmp(dst, src, size) == 0) 795 | BGI_PushStack(thread, 1); 796 | else 797 | BGI_PushStack(thread, 0); 798 | 799 | return 0; 800 | } 801 | 802 | // ----------------------------------------------------------------------------- 803 | // Mnemonic: strreplace 804 | // Opcode: 0x67 805 | // Stack in: 4 806 | // Stack out: 1 807 | // Bytes: 0 808 | // ----------------------------------------------------------------------------- 809 | // TODO: Find some code that uses this opcode... I have no idea what I'm looking for. 810 | /* 811 | bool BGI_IsDoubleByteSJIS(char c) 812 | { 813 | if((c < 0x80 || c > 0x9F) && c < 0xE0) 814 | return false; 815 | return true; 816 | } 817 | 818 | int BGI_CopySJISChar(uint32_t* dst, char* src) 819 | { 820 | if(BGI_IsDoubleByteSJIS(*src)) 821 | { 822 | *dst = *(uint16_t*)src & 0xFFFF; 823 | return 1; 824 | } 825 | *dst = *src & 0xFF; 826 | return 0; 827 | } 828 | 829 | int BGI_Strunkonwn(char* a, char* search) 830 | { 831 | int searchLen = strlen(search); 832 | uint32_t* buf = (char*)malloc(searchLen * sizeof(uint32_t)); 833 | 834 | char* ptr = search; 835 | 836 | int len = 0; 837 | char c = *ptr; 838 | while(c) 839 | { 840 | if(BGI_CopySJISChar(buf++, ptr++)) 841 | ptr++; 842 | len++; 843 | } 844 | char* aPtr = a; 845 | c = *aPtr; 846 | while(c) 847 | { 848 | 849 | } 850 | } 851 | 852 | uint8_t* BGI_Strreplace(char* a, char* b, char* search, char* d) 853 | { 854 | int searchLen = strlen(search); 855 | int dLen = strlen(d); 856 | 857 | int len = BGI_Strunkonwn(b, search); 858 | } 859 | */ 860 | 861 | int op_strreplace(VMThread_t* thread) 862 | { 863 | uint8_t* d = BGI_PopAndResolveAddress(thread); 864 | uint8_t* c = BGI_PopAndResolveAddress(thread); 865 | uint8_t* b = BGI_PopAndResolveAddress(thread); 866 | uint8_t* a = BGI_PopAndResolveAddress(thread); 867 | 868 | printf("op_strreplace: a: %.8X, b: %.8X, c: %.8X, d: %.8X\n", a, b, c, d); 869 | 870 | //uint8_t* res = BGI_Strreplace(a, b, c, d); 871 | 872 | return 0; 873 | } 874 | 875 | // ----------------------------------------------------------------------------- 876 | // Mnemonic: strlen 877 | // Opcode: 0x68 878 | // Stack in: 1 879 | // Stack out: 1 880 | // Bytes: 0 881 | // ----------------------------------------------------------------------------- 882 | 883 | int op_strlen(VMThread_t* thread) 884 | { 885 | uint8_t* str = BGI_PopAndResolveAddress(thread); 886 | 887 | BGI_PushStack(thread, strlen(str)); 888 | return 0; 889 | } 890 | 891 | // ----------------------------------------------------------------------------- 892 | // Mnemonic: streq 893 | // Opcode: 0x69 894 | // Stack in: 2 895 | // Stack out: 1 896 | // Bytes: 0 897 | // ----------------------------------------------------------------------------- 898 | int op_streq(VMThread_t* thread) 899 | { 900 | uint8_t* strA = BGI_PopAndResolveAddress(thread); 901 | uint8_t* strB = BGI_PopAndResolveAddress(thread); 902 | 903 | BGI_PushStack(thread, strcmp(strA, strB) == 0); 904 | return 0; 905 | } 906 | 907 | // ----------------------------------------------------------------------------- 908 | // Mnemonic: strcpu 909 | // Opcode: 0x6A 910 | // Stack in: 2 911 | // Stack out: 0 912 | // Bytes: 0 913 | // ----------------------------------------------------------------------------- 914 | int op_strcpy(VMThread_t* thread) 915 | { 916 | uint8_t* right = BGI_PopAndResolveAddress(thread); 917 | uint8_t* left = BGI_PopAndResolveAddress(thread); 918 | 919 | strcpy(left, right); 920 | 921 | return 0; 922 | } 923 | 924 | // ----------------------------------------------------------------------------- 925 | // Mnemonic: strconcat 926 | // Opcode: 0x6B 927 | // Stack in: 3 928 | // Stack out: 0 929 | // Bytes: 0 930 | // ----------------------------------------------------------------------------- 931 | int op_strconcat(VMThread_t* thread) 932 | { 933 | uint8_t* right = BGI_PopAndResolveAddress(thread); 934 | uint8_t* left = BGI_PopAndResolveAddress(thread); 935 | uint8_t* dst = BGI_PopAndResolveAddress(thread); 936 | 937 | sprintf(dst, "%s%s", left, right); 938 | 939 | //Debug_PrintfSJIS(L"strconcat", dst); 940 | 941 | return 0; 942 | } 943 | 944 | // ----------------------------------------------------------------------------- 945 | // Mnemonic: getchar 946 | // Opcode: 0x6C 947 | // Stack in: 1 948 | // Stack out: 3 949 | // Bytes: 0 950 | // ----------------------------------------------------------------------------- 951 | int op_getchar(VMThread_t* thread) 952 | { 953 | uint8_t* ptr = BGI_PopAndResolveAddress(thread); 954 | bool isTwoByte = 0; 955 | uint16_t c = SjisGetChar(ptr, &isTwoByte); 956 | BGI_PushStack(thread, c); 957 | BGI_PushStack(thread, isTwoByte); 958 | BGI_PushStack(thread, BGI_IsDelimiter(c)); 959 | //printf("getchar: Char: %.4X, Two-byte: %c, Delimiter: %c\n", c, isTwoByte ? 'Y' : 'N', BGI_IsDelimiter(c) ? 'Y' : 'N'); 960 | return 0; 961 | } 962 | 963 | // ----------------------------------------------------------------------------- 964 | // Mnemonic: tolower 965 | // Opcode: 0x6D 966 | // Stack in: 1 967 | // Stack out: 0 968 | // Bytes: 0 969 | // ----------------------------------------------------------------------------- 970 | int op_tolower(VMThread_t* thread) 971 | { 972 | uint8_t* ptr = BGI_PopAndResolveAddress(thread); 973 | BGI_StrToLowerCase(ptr); 974 | } 975 | 976 | // ----------------------------------------------------------------------------- 977 | // Mnemonic: sprintf 978 | // Opcode: 0x6F 979 | // Stack in: 2+ 980 | // Stack out: 0 981 | // Bytes: 0 982 | // ----------------------------------------------------------------------------- 983 | int op_sprintf(VMThread_t* thread) 984 | { 985 | uint8_t* fmt = BGI_PopAndResolveAddress(thread); 986 | uint8_t* dst = BGI_PopAndResolveAddress(thread); 987 | BGI_Sprintf(dst, fmt, thread); 988 | } 989 | 990 | // ----------------------------------------------------------------------------- 991 | // Mnemonic: addmemboundary 992 | // Opcode: 0x75 993 | // Stack in: 3 994 | // Stack out: 0 995 | // Bytes: 0 996 | // ----------------------------------------------------------------------------- 997 | int op_addmemboundary(VMThread_t* thread) 998 | { 999 | // TODO: Finish the functionality of this opcode 1000 | 1001 | uint8_t* name = BGI_PopAndResolveAddress(thread); 1002 | uint32_t size = BGI_PopStack(thread); 1003 | uint32_t start = BGI_PopStack(thread); 1004 | 1005 | //Debug_PrintfSJIS(L"addmemboundary: ", name); 1006 | //wprintf(L"size: %.8X, start: %.8X\n", size, start); 1007 | 1008 | BGI_PushStack(thread, 1); 1009 | return 0; 1010 | } 1011 | 1012 | // ----------------------------------------------------------------------------- 1013 | // Mnemonic: sys 1014 | // Opcode: 0x80 1015 | // Stack in: ? 1016 | // Stack out: ? 1017 | // Bytes: 1+? 1018 | // ----------------------------------------------------------------------------- 1019 | int op_sys0(VMThread_t* thread) 1020 | { 1021 | uint8_t sysOpcode = BGI_ReadCode8(thread); 1022 | if(sys0Jumptable[sysOpcode] == NULL) 1023 | { 1024 | uint8_t opcode = thread->codeSpace[thread->instructionPointer]; 1025 | printf("Undefined sys0 opcode: 0x%.2X (%d) at address %.8LX\n", sysOpcode, sysOpcode, thread->instructionPointer); 1026 | 1027 | return gSys0Jumptable[sysOpcode](thread); 1028 | //thread->instructionPointer -= 2; 1029 | //thread->programCounter -= 2; 1030 | //haltExecution(thread); 1031 | //return 0; 1032 | } 1033 | return sys0Jumptable[sysOpcode](thread); 1034 | } 1035 | --------------------------------------------------------------------------------