diff --git a/src/drivers/win/debugger.cpp b/src/drivers/win/debugger.cpp index cf633ab0..0aed2a2d 100644 --- a/src/drivers/win/debugger.cpp +++ b/src/drivers/win/debugger.cpp @@ -40,6 +40,7 @@ #include "richedit.h" #include "assembler.h" #include "patcher.h" +#include "dumper.h" // ################################## Start of SP CODE ########################### @@ -80,11 +81,11 @@ bool debuggerIDAFont = false; unsigned int IDAFontSize = 16; bool debuggerDisplayROMoffsets = false; -wchar_t* debug_wstr; -char* debug_cdl_str; -char* debug_str_decoration_comment; -char* debug_decoration_comment; -char* debug_decoration_comment_end_pos; +static wchar_t* debug_wstr; +static char* debug_cdl_str; +static char* debug_str_decoration_comment; +static char* debug_decoration_comment; +static char* debug_decoration_comment_end_pos; FINDTEXT newline; FINDTEXT num; @@ -561,198 +562,6 @@ void UpdateDisassembleView(HWND hWnd, UINT id, int lines, bool text = false) SendDlgItemMessage(hWnd, id, EM_SETEVENTMASK, 0, eventMask); } -/** -* Dumps disassembled ROM code between startAddr and endAddr (inclusive) to a file. -* endAddr is the address of the last INSTRUCTION. This funcion will grab the operands if present, -* and may spill over a bit in the process. -* 0x80000 - 0xFFFF should get you the loaded banks. However, it's most reliable when you dump one subroutine at a time -* or already have a lot of labels. -* -* For example, say you have 2C A9 10 60, and the A9 byte is supposed to be the start of a subroutine. If the disassembler -* comes across that 2C first, it will interpret the code as: - -* 2C A9 10 BIT $10A9 -* 60 RTS - -* Nonsense. - -* But if you have a named label -* on that A9 byte, the 2C (BIT) instruction will be INTERRUPTED, and it will show up like this: - -* 2C INTERRUPTED -* my_subroutine: -* A9 10 LDA #$10 -* 60 RTS -* -* There is a lot of reused logic between this and Disassemble. However, they're different enough that it would -* be more trouble than it's worth to combine them. -*/ -void Dump(FILE *fout, unsigned int startAddr, unsigned int endAddr) -{ - wchar_t chr[40] = { 0 }; - wchar_t debug_wbuf[2048] = { 0 }; - int size; - uint8 opcode[3]; - unsigned int instruction_addr; - unsigned int addr = startAddr; // Keeps track of which address to get the operands, etc. from - - if (symbDebugEnabled) - loadNameFiles(); - - unsigned int instructions_count = 0; - for (int addr = startAddr; addr <= endAddr;) - { - // PC pointer - if (addr > 0xFFFF) break; - - instruction_addr = addr; - - if (symbDebugEnabled) - { - // Insert name and comment lines if present - Name* node = findNode(getNamesPointerForAddress(addr), addr); - if (node) - { - if (node->name) - { - // Could probably ditch these swprintf's and just do fwprintf. - // Need to verify exactly how the various buffers are used. - swprintf(debug_wbuf, L"%S:\n", node->name); - fprintf(fout, "%ls", debug_wbuf); - } - if (node->comment) - { - // make a copy - strcpy(debug_str_decoration_comment, node->comment); - strcat(debug_str_decoration_comment, "\r\n"); - // divide the debug_str_decoration_comment into strings (Comment1, Comment2, ...) - debug_decoration_comment = debug_str_decoration_comment; - debug_decoration_comment_end_pos = strstr(debug_decoration_comment, "\r\n"); - while (debug_decoration_comment_end_pos) - { - debug_decoration_comment_end_pos[0] = 0; // set \0 instead of \r - debug_decoration_comment_end_pos[1] = 0; // set \0 instead of \n - swprintf(debug_wbuf, L"; %S\n", debug_decoration_comment); - fprintf(fout, "%ls", debug_wbuf); - - debug_decoration_comment_end_pos += 2; - debug_decoration_comment = debug_decoration_comment_end_pos; - debug_decoration_comment_end_pos = strstr(debug_decoration_comment_end_pos, "\r\n"); - } - } - } - } - - fprintf(fout, "%ls", L" "); - - if (addr >= 0x8000) - { - if (debuggerDisplayROMoffsets && GetNesFileAddress(addr) != -1) - { - swprintf(chr, L" %06X: ", GetNesFileAddress(addr)); - } - else - { - swprintf(chr, L"%02X:%04X: ", getBank(addr), addr); - } - } - else - { - swprintf(chr, L" :%04X: ", addr); - } - - // Add address - fprintf(fout, "%ls", chr); - - size = opsize[GetMem(addr)]; - if (size == 0) - { - swprintf(chr, L"%02X UNDEFINED", GetMem(addr++)); - fprintf(fout, "%ls", chr); - } - else - { - if ((addr + size) > 0xFFFF) - { - while (addr < 0xFFFF) - { - swprintf(chr, L"%02X OVERFLOW\n", GetMem(addr++)); - fprintf(fout, "%ls", chr); - } - break; - } - Name* node; - for (int j = 0; j < size; j++) - { - // Write the raw bytes of this instruction - swprintf(chr, L"%02X ", opcode[j] = GetMem(addr++)); - fprintf(fout, "%ls", chr); - if (j != size - 1 && (node = findNode(getNamesPointerForAddress(addr), addr))) - { - // We were treating this as an operand, but it's named! - // Probably want an instruction to start here instead. - printf("$%04X (%s) came up as an operand for instruction @ %04X\n", addr, node->name, addr - j - 1); - size = j + 1; - break; - } - } - while (size < 3) - { - fprintf(fout, "%ls", L" "); - size++; - } - if (node) - { - // TODO: Instead of this ominous and confusing message, could print ".byte $XX $YY..." - fprintf(fout, " INTERRUPTED"); - } - else - { - static char bufferForDisassemblyWithPlentyOfStuff[64 + NL_MAX_NAME_LEN * 10]; // "plenty" - char* _a = Disassemble(addr, opcode); - // This isn't a trace log, so we want to remove the data after the @ or =. - // There are lots of hardcoded sprintfs in Disassemble. This really is the easiest way. - char* traceInfoIndex = strstr(_a, "@"); - if (traceInfoIndex) - traceInfoIndex[-1] = 0; - traceInfoIndex = strstr(_a, "="); - if (traceInfoIndex) - traceInfoIndex[-1] = 0; - - strcpy(bufferForDisassemblyWithPlentyOfStuff, _a); - - if (symbDebugEnabled) - { // TODO: This will add in both the default name and custom name if you have inlineAddresses enabled. - if (symbRegNames) - replaceRegNames(bufferForDisassemblyWithPlentyOfStuff); - replaceNames(ramBankNames, bufferForDisassemblyWithPlentyOfStuff, NULL); - for (int p = 0; p +#include + +#include "types.h" +#include "resource.h" +#include "debugger.h" +#include "debuggersp.h" +#include "../../debug.h" +#include "asm.h" +#include "../../x6502.h" +#include "../../fceu.h" +#include "../../debug.h" +#include "../../nsf.h" +#include "../../ppu.h" +#include "../../cart.h" +#include "../../ines.h" +#include "../../asm.h" +#include "tracer.h" +#include "window.h" + +extern Name* ramBankNames; +extern Name* pageNames[32]; + +static char* debug_str_decoration_comment; +static char* debug_decoration_comment; +static char* debug_decoration_comment_end_pos; +static char filename[257]; + +/** +* Dumps disassembled ROM code between startAddr and endAddr (inclusive) to a file. +* endAddr is the address of the last INSTRUCTION. This funcion will grab the operands if present, +* and may spill over a bit in the process. +* 0x80000 - 0xFFFF should get you the loaded banks. However, it's most reliable when you dump one subroutine at a time +* or already have a lot of labels. +* +* For example, say you have 2C A9 10 60, and the A9 byte is supposed to be the start of a subroutine. If the disassembler +* comes across that 2C first, it will interpret the code as: + +* 2C A9 10 BIT $10A9 +* 60 RTS + +* Nonsense. + +* But if you have a named label +* on that A9 byte, the 2C (BIT) instruction will be INTERRUPTED, and it will show up like this: + +* 2C INTERRUPTED +* my_subroutine: +* A9 10 LDA #$10 +* 60 RTS +* +* There is a lot of reused logic between this and Disassemble. However, they're different enough that it would +* be more trouble than it's worth to combine them. +*/ +void Dump(FILE *fout, unsigned int startAddr, unsigned int endAddr) +{ + wchar_t chr[40] = { 0 }; + wchar_t debug_wbuf[2048] = { 0 }; + int size; + uint8 opcode[3]; + unsigned int instruction_addr; + unsigned int addr = startAddr; // Keeps track of which address to get the operands, etc. from + + if (symbDebugEnabled) + loadNameFiles(); + + unsigned int instructions_count = 0; + for (int addr = startAddr; addr <= endAddr;) + { + // PC pointer + if (addr > 0xFFFF) break; + + instruction_addr = addr; + + if (symbDebugEnabled) + { + // Insert name and comment lines if present + Name* node = findNode(getNamesPointerForAddress(addr), addr); + if (node) + { + if (node->name) + { + // Could probably ditch these swprintf's and just do fwprintf. + // Need to verify exactly how the various buffers are used. + swprintf(debug_wbuf, L"%S:\n", node->name); + fprintf(fout, "%ls", debug_wbuf); + } + if (node->comment) + { + // make a copy + strcpy(debug_str_decoration_comment, node->comment); + strcat(debug_str_decoration_comment, "\r\n"); + // divide the debug_str_decoration_comment into strings (Comment1, Comment2, ...) + debug_decoration_comment = debug_str_decoration_comment; + debug_decoration_comment_end_pos = strstr(debug_decoration_comment, "\r\n"); + while (debug_decoration_comment_end_pos) + { + debug_decoration_comment_end_pos[0] = 0; // set \0 instead of \r + debug_decoration_comment_end_pos[1] = 0; // set \0 instead of \n + swprintf(debug_wbuf, L"; %S\n", debug_decoration_comment); + fprintf(fout, "%ls", debug_wbuf); + + debug_decoration_comment_end_pos += 2; + debug_decoration_comment = debug_decoration_comment_end_pos; + debug_decoration_comment_end_pos = strstr(debug_decoration_comment_end_pos, "\r\n"); + } + } + } + } + + fprintf(fout, "%ls", L" "); + + if (addr >= 0x8000) + { + if (debuggerDisplayROMoffsets && GetNesFileAddress(addr) != -1) + { + swprintf(chr, L" %06X: ", GetNesFileAddress(addr)); + } + else + { + swprintf(chr, L"%02X:%04X: ", getBank(addr), addr); + } + } + else + { + swprintf(chr, L" :%04X: ", addr); + } + + // Add address + fprintf(fout, "%ls", chr); + + size = opsize[GetMem(addr)]; + if (size == 0) + { + swprintf(chr, L"%02X UNDEFINED", GetMem(addr++)); + fprintf(fout, "%ls", chr); + } + else + { + if ((addr + size) > 0xFFFF) + { + while (addr < 0xFFFF) + { + swprintf(chr, L"%02X OVERFLOW\n", GetMem(addr++)); + fprintf(fout, "%ls", chr); + } + break; + } + Name* node; + for (int j = 0; j < size; j++) + { + // Write the raw bytes of this instruction + swprintf(chr, L"%02X ", opcode[j] = GetMem(addr++)); + fprintf(fout, "%ls", chr); + if (j != size - 1 && (node = findNode(getNamesPointerForAddress(addr), addr))) + { + // We were treating this as an operand, but it's named! + // Probably want an instruction to start here instead. + printf("$%04X (%s) came up as an operand for instruction @ %04X\n", addr, node->name, addr - j - 1); + size = j + 1; + break; + } + } + while (size < 3) + { + fprintf(fout, "%ls", L" "); + size++; + } + if (node) + { + // TODO: Instead of this ominous and confusing message, could print ".byte $XX $YY..." + fprintf(fout, " INTERRUPTED"); + } + else + { + static char bufferForDisassemblyWithPlentyOfStuff[64 + NL_MAX_NAME_LEN * 10]; // "plenty" + char* _a = Disassemble(addr, opcode); + // This isn't a trace log, so we want to remove the data after the @ or =. + // There are lots of hardcoded sprintfs in Disassemble. This really is the easiest way. + char* traceInfoIndex = strstr(_a, "@"); + if (traceInfoIndex) + traceInfoIndex[-1] = 0; + traceInfoIndex = strstr(_a, "="); + if (traceInfoIndex) + traceInfoIndex[-1] = 0; + + strcpy(bufferForDisassemblyWithPlentyOfStuff, _a); + + if (symbDebugEnabled) + { // TODO: This will add in both the default name and custom name if you have inlineAddresses enabled. + if (symbRegNames) + replaceRegNames(bufferForDisassemblyWithPlentyOfStuff); + replaceNames(ramBankNames, bufferForDisassemblyWithPlentyOfStuff, NULL); + for (int p = 0; p + +BOOL CALLBACK DumperCallB(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam); diff --git a/src/drivers/win/window.cpp b/src/drivers/win/window.cpp index b36e74bc..cb4c78a3 100644 --- a/src/drivers/win/window.cpp +++ b/src/drivers/win/window.cpp @@ -3362,6 +3362,9 @@ bool inline (*GetIsLetterLegal(UINT id))(char letter) // Array Size, Init value in Symbolic Name in Debugger case IDC_EDIT_SYMBOLIC_ARRAY: case IDC_EDIT_SYMBOLIC_INIT: + // Address boxes in Debugger -> Tools menus + case ID_DUMPER_START_ADDR: case ID_DUMPER_END_ADDR: + // Address, Value, Compare, Known Value, Note equal, Greater than and Less than in Cheat case IDC_CHEAT_ADDR: case IDC_CHEAT_VAL: case IDC_CHEAT_COM: case IDC_CHEAT_VAL_KNOWN: case IDC_CHEAT_VAL_NE_BY: diff --git a/vc/vc14_fceux.vcxproj b/vc/vc14_fceux.vcxproj index cbd0c352..3bed0b09 100644 --- a/vc/vc14_fceux.vcxproj +++ b/vc/vc14_fceux.vcxproj @@ -577,6 +577,7 @@ xcopy /y /d "$(ProjectDir)\..\src\drivers\win\7z_64.dll" "$(OutDir)" + @@ -1038,6 +1039,7 @@ xcopy /y /d "$(ProjectDir)\..\src\drivers\win\7z_64.dll" "$(OutDir)" + diff --git a/vc/vc14_fceux.vcxproj.filters b/vc/vc14_fceux.vcxproj.filters index 2d1b4b79..a34827a6 100644 --- a/vc/vc14_fceux.vcxproj.filters +++ b/vc/vc14_fceux.vcxproj.filters @@ -1117,6 +1117,9 @@ drivers\win + + drivers\win + @@ -1632,6 +1635,9 @@ drivers\win + + drivers\win +