trace logger hack

This commit is contained in:
cyneprepou4uk 2021-10-19 01:26:51 +03:00
parent afd65c12f3
commit 469e8f8dde
6 changed files with 509 additions and 229 deletions

View File

@ -527,3 +527,199 @@ char *Disassemble(int addr, uint8 *opcode) {
return str;
}
///disassembles the opcodes in the buffer assuming the provided address. Uses GetMem() and 6502 current registers to query referenced values. returns a static string buffer.
char *bzk_Disassemble(int addr, uint8 *opcode) {
static char str[64] = {0};
uint16 tmp;
switch (opcode[0]) {
//Zero Page
case 0x05: goto _zeropage; //ORA
case 0x06: goto _zeropage; //ASL
case 0x24: goto _zeropage; //BIT
case 0x25: goto _zeropage; //AND
case 0x26: goto _zeropage; //ROL
case 0x45: goto _zeropage; //EOR
case 0x46: goto _zeropage; //LSR
case 0x65: goto _zeropage; //ADC
case 0x66: goto _zeropage; //ROR
case 0x84: goto _zeropage; //STY
case 0x85: goto _zeropage; //STA
case 0x86: goto _zeropage; //STX
case 0xA4: goto _zeropage; //LDY
case 0xA5: goto _zeropage; //LDA
case 0xA6: goto _zeropage; //LDX
case 0xC4: goto _zeropage; //CPY
case 0xC5: goto _zeropage; //CMP
case 0xC6: goto _zeropage; //DEC
case 0xE4: goto _zeropage; //CPX
case 0xE5: goto _zeropage; //SBC
case 0xE6: goto _zeropage; //INC
_zeropage:
tmp = opcode[1];
sprintf(str, "%u|%u", bzk_GetNesFileAddress(tmp), bzk_getBank(tmp));
break;
//Zero Page,X
case 0x15: goto _zeropagex; //ORA
case 0x16: goto _zeropagex; //ASL
case 0x35: goto _zeropagex; //AND
case 0x36: goto _zeropagex; //ROL
case 0x55: goto _zeropagex; //EOR
case 0x56: goto _zeropagex; //LSR
case 0x75: goto _zeropagex; //ADC
case 0x76: goto _zeropagex; //ROR
case 0x94: goto _zeropagex; //STY
case 0x95: goto _zeropagex; //STA
case 0xB4: goto _zeropagex; //LDY
case 0xB5: goto _zeropagex; //LDA
case 0xD5: goto _zeropagex; //CMP
case 0xD6: goto _zeropagex; //DEC
case 0xF5: goto _zeropagex; //SBC
case 0xF6: goto _zeropagex; //INC
_zeropagex:
tmp = (opcode[1] + X.X) & 0xFF;
sprintf(str, "%u|%u", bzk_GetNesFileAddress(tmp), bzk_getBank(tmp));
break;
//Zero Page,Y
case 0x96: goto _zeropagey; //STX
case 0xB6: goto _zeropagey; //LDX
_zeropagey:
tmp = (opcode[1] + X.Y) & 0xFF;
sprintf(str, "%u|%u", bzk_GetNesFileAddress(tmp), bzk_getBank(tmp));
break;
//Absolute
case 0x0D: goto _absolute; //ORA
case 0x0E: goto _absolute; //ASL
case 0x2C: goto _absolute; //BIT
case 0x2D: goto _absolute; //AND
case 0x2E: goto _absolute; //ROL
case 0x4D: goto _absolute; //EOR
case 0x4E: goto _absolute; //LSR
case 0x6D: goto _absolute; //ADC
case 0x6E: goto _absolute; //ROR
case 0x8C: goto _absolute; //STY
case 0x8D: goto _absolute; //STA
case 0x8E: goto _absolute; //STX
case 0xAC: goto _absolute; //LDY
case 0xAD: goto _absolute; //LDA
case 0xAE: goto _absolute; //LDX
case 0xCC: goto _absolute; //CPY
case 0xCD: goto _absolute; //CMP
case 0xCE: goto _absolute; //DEC
case 0xEC: goto _absolute; //CPX
case 0xED: goto _absolute; //SBC
case 0xEE: goto _absolute; //INC
_absolute:
tmp = opcode[1] | opcode[2] << 8;
sprintf(str, "%u|%u", bzk_GetNesFileAddress(tmp), bzk_getBank(tmp));
break;
//Absolute,X
case 0x1D: goto _absolutex; //ORA
case 0x1E: goto _absolutex; //ASL
case 0x3D: goto _absolutex; //AND
case 0x3E: goto _absolutex; //ROL
case 0x5D: goto _absolutex; //EOR
case 0x5E: goto _absolutex; //LSR
case 0x7D: goto _absolutex; //ADC
case 0x7E: goto _absolutex; //ROR
case 0x9D: goto _absolutex; //STA
case 0xBC: goto _absolutex; //LDY
case 0xBD: goto _absolutex; //LDA
case 0xDD: goto _absolutex; //CMP
case 0xDE: goto _absolutex; //DEC
case 0xFD: goto _absolutex; //SBC
case 0xFE: goto _absolutex; //INC
_absolutex:
tmp = (opcode[1] | opcode[2] << 8) + X.X;
sprintf(str, "%u|%u", bzk_GetNesFileAddress(tmp), bzk_getBank(tmp));
break;
//Absolute,Y
case 0x19: goto _absolutey; //ORA
case 0x39: goto _absolutey; //AND
case 0x59: goto _absolutey; //EOR
case 0x79: goto _absolutey; //ADC
case 0x99: goto _absolutey; //STA
case 0xB9: goto _absolutey; //LDA
case 0xBE: goto _absolutey; //LDX
case 0xD9: goto _absolutey; //CMP
case 0xF9: goto _absolutey; //SBC
_absolutey:
tmp = (opcode[1] | opcode[2] << 8) + X.Y;
sprintf(str, "%u|%u", bzk_GetNesFileAddress(tmp), bzk_getBank(tmp));
break;
//branches
case 0x10: goto _branch; //BPL
case 0x30: goto _branch; //BMI
case 0x50: goto _branch; //BVC
case 0x70: goto _branch; //BVS
case 0x90: goto _branch; //BCC
case 0xB0: goto _branch; //BCS
case 0xD0: goto _branch; //BNE
case 0xF0: goto _branch; //BEQ
_branch:
tmp = addr + opcode[1] + 0x02;
if (opcode[1] >= 0x80) tmp -= 0x100;
sprintf(str, "%u|%u", bzk_GetNesFileAddress(tmp), bzk_getBank(tmp));
break;
//(Indirect,X)
case 0x01: goto _indirectx; //ORA
case 0x21: goto _indirectx; //AND
case 0x41: goto _indirectx; //EOR
case 0x61: goto _indirectx; //ADC
case 0x81: goto _indirectx; //STA
case 0xA1: goto _indirectx; //LDA
case 0xC1: goto _indirectx; //CMP
case 0xE1: goto _indirectx; //SBC
_indirectx:
tmp = (opcode[1] + X.X) & 0xFF;
tmp = GetMem((tmp)) | (GetMem(((tmp) + 1) & 0xFF)) << 8;
sprintf(str, "%u|%u", bzk_GetNesFileAddress(tmp), bzk_getBank(tmp));
break;
//(Indirect),Y
case 0x11: goto _indirecty; //ORA
case 0x31: goto _indirecty; //AND
case 0x51: goto _indirecty; //EOR
case 0x71: goto _indirecty; //ADC
case 0x91: goto _indirecty; //STA
case 0xB1: goto _indirecty; //LDA
case 0xD1: goto _indirecty; //CMP
case 0xF1: goto _indirecty; //SBC
_indirecty:
tmp = (GetMem(opcode[1]) | (GetMem((opcode[1] + 1) & 0xFF)) << 8) + X.Y;
sprintf(str, "%u|%u", bzk_GetNesFileAddress(tmp), bzk_getBank(tmp));
break;
//absolute jumps
case 0x20: goto _jump; //JSR
case 0x4C: goto _jump; //JMP
_jump:
tmp = opcode[1] | opcode[2] << 8;
sprintf(str, "%u|%u", bzk_GetNesFileAddress(tmp), bzk_getBank(tmp));
break;
//indirect jump
case 0x6C: //JMP
tmp = opcode[1] | opcode[2] << 8;
tmp = GetMem(tmp) | GetMem(tmp + 1) << 8;
sprintf(str, "%u|%u", bzk_GetNesFileAddress(tmp), bzk_getBank(tmp));
break;
//for all other other opcodes, which are immediate and 1-byte instructions
default:
strcpy(str, "?|?");
break;
}
return str;
}

View File

@ -1,2 +1,3 @@
int Assemble(unsigned char *output, int addr, char *str);
char *Disassemble(int addr, uint8 *opcode);
char *bzk_Disassemble(int addr, uint8 *opcode);

View File

@ -265,6 +265,11 @@ int getBank(int offs)
return addr != -1 ? addr / (1<<debuggerPageSize) : -1; //formerly, dividing by 0x4000
}
int bzk_getBank(int offs)
{
return bzk_GetNesFileAddress(offs) / 0x2000;
}
int GetNesFileAddress(int A){
int result;
if((A < 0x6000) || (A > 0xFFFF))return -1;
@ -273,6 +278,11 @@ int GetNesFileAddress(int A){
else return result+16; //16 bytes for the header remember
}
int bzk_GetNesFileAddress(int A){
if (A >= 0x6000) return &Page[A>>11][A]-PRGptr[0]; //for 6000-FFFF
return A + 0x80000; //for 0000-5FFF
}
int GetRomAddress(int A){
int i;
uint8 *p = GetNesPRGPointer(A-=16);

View File

@ -64,7 +64,9 @@ extern watchpointinfo watchpoint[65]; //64 watchpoints, + 1 reserved for step ov
extern unsigned int debuggerPageSize;
int getBank(int offs);
int bzk_getBank(int offs);
int GetNesFileAddress(int A);
int bzk_GetNesFileAddress(int A);
int GetPRGAddress(int A);
int GetRomAddress(int A);
//int GetEditHex(HWND hwndDlg, int id);

View File

@ -109,7 +109,9 @@ int log_optn_intlst[LOG_OPTION_SIZE] = {3000000, 1000000, 300000, 100000, 30000
char *log_optn_strlst[LOG_OPTION_SIZE] = {"3 000 000", "1 000 000", "300 000", "100 000", "30 000", "10 000", "3000", "1000", "300", "100"};
int log_lines_option = 5; // 10000 lines by default
char *logfilename = 0;
int oldcodecount, olddatacount;
char bzk_filename[2100] = {0};
char bzk_newfilename[2100] = { 0 };
// int oldcodecount, olddatacount;
SCROLLINFO tracesi;
@ -121,6 +123,9 @@ int tracelogbufusedsize = 0;
char str_axystate[LOG_AXYSTATE_MAX_LEN] = {0}, str_procstatus[LOG_PROCSTATUS_MAX_LEN] = {0};
char str_tabs[LOG_TABS_MASK+1] = {0}, str_address[LOG_ADDRESS_MAX_LEN] = {0}, str_data[LOG_DATA_MAX_LEN] = {0}, str_disassembly[LOG_DISASSEMBLY_MAX_LEN] = {0};
char str_result[LOG_LINE_MAX_LEN] = {0};
char bzk_string[200] = {0};
int bzk_writes_counter = 0;
int bzk_files_counter = 0;
char str_temp[LOG_LINE_MAX_LEN] = {0};
char str_decoration[NL_MAX_MULTILINE_COMMENT_LEN + 10] = {0};
char str_decoration_comment[NL_MAX_MULTILINE_COMMENT_LEN + 10] = {0};
@ -419,9 +424,9 @@ INT_PTR CALLBACK TracerCallB(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lPar
SendDlgItemMessage(hwndDlg, IDC_TRACER_LOG_SIZE, CB_INSERTSTRING, -1, (LPARAM)(LPSTR)log_optn_strlst[i]);
}
SendDlgItemMessage(hwndDlg, IDC_TRACER_LOG_SIZE, CB_SETCURSEL, (WPARAM)log_lines_option, 0);
strcpy(trace_str, "Welcome to the Trace Logger.");
strcpy(trace_str, "1 - delete all .log files, 2 - start logging, 3 - launch BZK script, 4 - stop logging before exit.");
SetDlgItemText(hwndDlg, IDC_TRACER_LOG, trace_str);
logtofile = 0;
logtofile = 1;
CheckDlgButton(hwndDlg, IDC_CHECK_LOG_REGISTERS, (logging_options & LOG_REGISTERS) ? BST_CHECKED : BST_UNCHECKED);
CheckDlgButton(hwndDlg, IDC_CHECK_LOG_PROCESSOR_STATUS, (logging_options & LOG_PROCESSOR_STATUS) ? BST_CHECKED : BST_UNCHECKED);
@ -532,7 +537,7 @@ INT_PTR CALLBACK TracerCallB(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lPar
EnableTracerMenuItems();
break;
case IDC_RADIO_LOG_LAST:
logtofile = 0;
logtofile = 1;
EnableTracerMenuItems();
break;
case IDC_RADIO_LOG_TO_FILE:
@ -685,15 +690,47 @@ void BeginLoggingSequence(void)
if (logtofile)
{
if(logfilename == NULL) ShowLogDirDialog();
if (!logfilename) return;
LOG_FP = fopen(logfilename,"w");
//if (!logfilename) return;
// I've tried to make a "for" loop, but that doesn't work for some reason
//for (int k = 99999; k == -1; k--) {
// sprintf(bzk_filename, "z%05d_fceux.log", k);
// LOG_FP = fopen(bzk_filename, "r");
// if (LOG_FP != NULL) {
// fclose(LOG_FP);
// bzk_files_counter = k + 1;
// break;
// }
//}
//so fuck it, I'm sticking with what's actually working
int k = 99999;
while (true) {
sprintf(bzk_filename, "z%05d_fceux.log", k);
LOG_FP = fopen(bzk_filename, "r");
if (LOG_FP != NULL) {
fclose(LOG_FP);
bzk_files_counter = k + 1;
break;
}
k--;
if (k == -1) {
bzk_files_counter = 0;
break;
}
}
if (bzk_files_counter >= 100000) bzk_files_counter = 0;
sprintf(bzk_filename, "z%05d.log", bzk_files_counter);
LOG_FP = fopen(bzk_filename, "w");
if (LOG_FP == NULL)
{
sprintf(trace_str, "Error Opening File %s", logfilename);
sprintf(trace_str, "Error Opening File %s", bzk_filename);
MessageBox(hTracer, trace_str, "File Error", MB_OK);
return;
}
fprintf(LOG_FP,FCEU_NAME_AND_VERSION" - Trace Log File\n"); //mbg merge 7/19/06 changed string
// fprintf(LOG_FP,FCEU_NAME_AND_VERSION" - Trace Log File\n"); //mbg merge 7/19/06 changed string
} else
{
ClearTraceLogBuf();
@ -724,8 +761,8 @@ void BeginLoggingSequence(void)
tracelogbufpos = tracelogbufusedsize = 0;
}
oldcodecount = codecount;
olddatacount = datacount;
// oldcodecount = codecount;
// olddatacount = datacount;
logging=1;
SetDlgItemText(hTracer, IDC_BTN_START_STOP_LOGGING,"Stop Logging");
@ -739,232 +776,258 @@ void FCEUD_TraceInstruction(uint8 *opcode, int size)
return;
unsigned int addr = X.PC;
uint8 tmp;
static int unloggedlines;
// uint8 tmp;
// static int unloggedlines;
// if instruction executed from the RAM, skip this, log all instead
// TODO: loops folding mame-lyke style
if (GetPRGAddress(addr) != -1)
{
if(((logging_options & LOG_NEW_INSTRUCTIONS) && (oldcodecount != codecount)) ||
((logging_options & LOG_NEW_DATA) && (olddatacount != datacount)))
{
//something new was logged
oldcodecount = codecount;
olddatacount = datacount;
if(unloggedlines > 0)
{
sprintf(str_result, "(%d lines skipped)", unloggedlines);
OutputLogLine(str_result);
unloggedlines = 0;
}
} else
{
if((logging_options & LOG_NEW_INSTRUCTIONS) ||
(logging_options & LOG_NEW_DATA))
{
if(FCEUI_GetLoggingCD())
unloggedlines++;
return;
}
}
}
// // if instruction executed from the RAM, skip this, log all instead
// // TODO: loops folding mame-lyke style
// if (GetPRGAddress(addr) != -1)
// {
// if(((logging_options & LOG_NEW_INSTRUCTIONS) && (oldcodecount != codecount)) ||
// ((logging_options & LOG_NEW_DATA) && (olddatacount != datacount)))
// {
// //something new was logged
// oldcodecount = codecount;
// olddatacount = datacount;
// if(unloggedlines > 0)
// {
// sprintf(str_result, "(%d lines skipped)", unloggedlines);
// OutputLogLine(str_result);
// unloggedlines = 0;
// }
// } else
// {
// if((logging_options & LOG_NEW_INSTRUCTIONS) ||
// (logging_options & LOG_NEW_DATA))
// {
// if(FCEUI_GetLoggingCD())
// unloggedlines++;
// return;
// }
// }
// }
//
// if ((addr + size) > 0xFFFF)
// {
// sprintf(str_data, "%02X ", opcode[0]);
// sprintf(str_disassembly, "OVERFLOW");
// } else
// {
// char* a = 0;
// switch (size)
// {
// case 0:
// sprintf(str_data, "%02X ", opcode[0]);
// sprintf(str_disassembly,"UNDEFINED");
// break;
// case 1:
// {
// sprintf(str_data, "%02X ", opcode[0]);
// a = Disassemble(addr + 1, opcode);
// // special case: an RTS opcode
// if (opcode[0] == 0x60)
// {
// // add the beginning address of the subroutine that we exit from
// unsigned int caller_addr = GetMem(((X.S) + 1)|0x0100) + (GetMem(((X.S) + 2)|0x0100) << 8) - 0x2;
// if (GetMem(caller_addr) == 0x20)
// {
// // this was a JSR instruction - take the subroutine address from it
// unsigned int call_addr = GetMem(caller_addr + 1) + (GetMem(caller_addr + 2) << 8);
// sprintf(str_decoration, " (from $%04X)", call_addr);
// strcat(a, str_decoration);
// }
// }
// break;
// }
// case 2:
// sprintf(str_data, "%02X %02X ", opcode[0],opcode[1]);
// a = Disassemble(addr + 2, opcode);
// break;
// case 3:
// sprintf(str_data, "%02X %02X %02X ", opcode[0],opcode[1],opcode[2]);
// a = Disassemble(addr + 3, opcode);
// break;
// }
//
// if (a)
// {
// if (logging_options & LOG_SYMBOLIC)
// {
// loadNameFiles();
// tempAddressesLog.resize(0);
// // Insert Name and Comment lines if needed
// Name* node = findNode(getNamesPointerForAddress(addr), addr);
// if (node)
// {
// if (node->name)
// {
// strcpy(str_decoration, node->name);
// strcat(str_decoration, ":");
// tempAddressesLog.push_back(addr);
// OutputLogLine(str_decoration, &tempAddressesLog);
// }
// if (node->comment)
// {
// // make a copy
// strcpy(str_decoration_comment, node->comment);
// strcat(str_decoration_comment, "\r\n");
// tracer_decoration_comment = str_decoration_comment;
// // divide the str_decoration_comment into strings (Comment1, Comment2, ...)
// char* tracer_decoration_comment_end_pos = strstr(tracer_decoration_comment, "\r\n");
// while (tracer_decoration_comment_end_pos)
// {
// tracer_decoration_comment_end_pos[0] = 0; // set \0 instead of \r
// strcpy(str_decoration, "; ");
// strcat(str_decoration, tracer_decoration_comment);
// OutputLogLine(str_decoration, &tempAddressesLog);
// tracer_decoration_comment_end_pos += 2;
// tracer_decoration_comment = tracer_decoration_comment_end_pos;
// tracer_decoration_comment_end_pos = strstr(tracer_decoration_comment_end_pos, "\r\n");
// }
// }
// }
//
// replaceNames(ramBankNames, a, &tempAddressesLog);
// for(int i=0;i<ARRAY_SIZE(pageNames);i++)
// replaceNames(pageNames[i], a, &tempAddressesLog);
// }
// strncpy(str_disassembly, a, LOG_DISASSEMBLY_MAX_LEN);
// str_disassembly[LOG_DISASSEMBLY_MAX_LEN - 1] = 0;
// }
// }
//
// if (size == 1 && GetMem(addr) == 0x60)
// {
// // special case: an RTS opcode
// // add "----------" to emphasize the end of subroutine
// static const char* emphasize = " -------------------------------------------------------------------------------------------------------------------------";
// strncat(str_disassembly, emphasize, LOG_DISASSEMBLY_MAX_LEN - strlen(str_disassembly) - 1);
// }
// // stretch the disassembly string out if we have to output other stuff.
// if ((logging_options & (LOG_REGISTERS|LOG_PROCESSOR_STATUS)) && !(logging_options & LOG_TO_THE_LEFT))
// {
// for (int i = strlen(str_disassembly); i < (LOG_DISASSEMBLY_MAX_LEN - 1); ++i)
// str_disassembly[i] = ' ';
// str_disassembly[LOG_DISASSEMBLY_MAX_LEN - 1] = 0;
// }
//
// // Start filling the str_temp line: Frame count, Cycles count, Instructions count, AXYS state, Processor status, Tabs, Address, Data, Disassembly
// if (logging_options & LOG_FRAMES_COUNT)
// {
// sprintf(str_result, "f%-6u ", currFrameCounter);
// } else
// {
// str_result[0] = 0;
// }
// if (logging_options & LOG_CYCLES_COUNT)
// {
// int64 counter_value = timestampbase + (uint64)timestamp - total_cycles_base;
// if (counter_value < 0) // sanity check
// {
// ResetDebugStatisticsCounters();
// counter_value = 0;
// }
// sprintf(str_temp, "c%-11llu ", counter_value);
// strcat(str_result, str_temp);
// }
// if (logging_options & LOG_INSTRUCTIONS_COUNT)
// {
// sprintf(str_temp, "i%-11llu ", total_instructions);
// strcat(str_result, str_temp);
// }
//
// if (logging_options & LOG_REGISTERS)
// {
// sprintf(str_axystate,"A:%02X X:%02X Y:%02X S:%02X ",(X.A),(X.X),(X.Y),(X.S));
// }
//
// if (logging_options & LOG_PROCESSOR_STATUS)
// {
// tmp = X.P^0xFF;
// sprintf(str_procstatus,"P:%c%c%c%c%c%c%c%c ",
// 'N'|(tmp&0x80)>>2,
// 'V'|(tmp&0x40)>>1,
// 'U'|(tmp&0x20),
// 'B'|(tmp&0x10)<<1,
// 'D'|(tmp&0x08)<<2,
// 'I'|(tmp&0x04)<<3,
// 'Z'|(tmp&0x02)<<4,
// 'C'|(tmp&0x01)<<5
// );
// }
// if (logging_options & LOG_TO_THE_LEFT)
// {
// if (logging_options & LOG_REGISTERS)
// strcat(str_result, str_axystate);
// if (logging_options & LOG_PROCESSOR_STATUS)
// strcat(str_result, str_procstatus);
// }
//
// if (logging_options & LOG_CODE_TABBING)
// {
// // add spaces at the beginning of the line according to stack pointer
// int spaces = (0xFF - X.S) & LOG_TABS_MASK;
// for (int i = 0; i < spaces; i++)
// str_tabs[i] = ' ';
// str_tabs[spaces] = 0;
// strcat(str_result, str_tabs);
// } else if (logging_options & LOG_TO_THE_LEFT)
// {
// strcat(str_result, " ");
// }
//
// if (logging_options & LOG_BANK_NUMBER)
// {
// if (addr >= 0x8000)
// sprintf(str_address, "$%02X:%04X: ", getBank(addr), addr);
// else
// sprintf(str_address, " $%04X: ", addr);
// } else
// {
// sprintf(str_address, "$%04X: ", addr);
// }
//
// strcat(str_result, str_address);
// strcat(str_result, str_data);
// strcat(str_result, str_disassembly);
//
// if (!(logging_options & LOG_TO_THE_LEFT))
// {
// if (logging_options & LOG_REGISTERS)
// strcat(str_result, str_axystate);
// if (logging_options & LOG_PROCESSOR_STATUS)
// strcat(str_result, str_procstatus);
// }
//
// OutputLogLine(str_result, &tempAddressesLog);
if ((addr + size) > 0xFFFF)
{
sprintf(str_data, "%02X ", opcode[0]);
sprintf(str_disassembly, "OVERFLOW");
} else
{
char* a = 0;
switch (size)
{
case 0:
sprintf(str_data, "%02X ", opcode[0]);
sprintf(str_disassembly,"UNDEFINED");
break;
case 1:
{
sprintf(str_data, "%02X ", opcode[0]);
a = Disassemble(addr + 1, opcode);
// special case: an RTS opcode
if (opcode[0] == 0x60)
{
// add the beginning address of the subroutine that we exit from
unsigned int caller_addr = GetMem(((X.S) + 1)|0x0100) + (GetMem(((X.S) + 2)|0x0100) << 8) - 0x2;
if (GetMem(caller_addr) == 0x20)
{
// this was a JSR instruction - take the subroutine address from it
unsigned int call_addr = GetMem(caller_addr + 1) + (GetMem(caller_addr + 2) << 8);
sprintf(str_decoration, " (from $%04X)", call_addr);
strcat(a, str_decoration);
}
}
break;
}
case 2:
sprintf(str_data, "%02X %02X ", opcode[0],opcode[1]);
a = Disassemble(addr + 2, opcode);
break;
case 3:
sprintf(str_data, "%02X %02X %02X ", opcode[0],opcode[1],opcode[2]);
a = Disassemble(addr + 3, opcode);
break;
}
if (a)
{
if (logging_options & LOG_SYMBOLIC)
{
loadNameFiles();
tempAddressesLog.resize(0);
// Insert Name and Comment lines if needed
Name* node = findNode(getNamesPointerForAddress(addr), addr);
if (node)
{
if (node->name)
{
strcpy(str_decoration, node->name);
strcat(str_decoration, ":");
tempAddressesLog.push_back(addr);
OutputLogLine(str_decoration, &tempAddressesLog);
}
if (node->comment)
{
// make a copy
strcpy(str_decoration_comment, node->comment);
strcat(str_decoration_comment, "\r\n");
tracer_decoration_comment = str_decoration_comment;
// divide the str_decoration_comment into strings (Comment1, Comment2, ...)
char* tracer_decoration_comment_end_pos = strstr(tracer_decoration_comment, "\r\n");
while (tracer_decoration_comment_end_pos)
{
tracer_decoration_comment_end_pos[0] = 0; // set \0 instead of \r
strcpy(str_decoration, "; ");
strcat(str_decoration, tracer_decoration_comment);
OutputLogLine(str_decoration, &tempAddressesLog);
tracer_decoration_comment_end_pos += 2;
tracer_decoration_comment = tracer_decoration_comment_end_pos;
tracer_decoration_comment_end_pos = strstr(tracer_decoration_comment_end_pos, "\r\n");
}
}
}
replaceNames(ramBankNames, a, &tempAddressesLog);
for(int i=0;i<ARRAY_SIZE(pageNames);i++)
replaceNames(pageNames[i], a, &tempAddressesLog);
}
strncpy(str_disassembly, a, LOG_DISASSEMBLY_MAX_LEN);
str_disassembly[LOG_DISASSEMBLY_MAX_LEN - 1] = 0;
}
}
if (size == 1 && GetMem(addr) == 0x60)
{
// special case: an RTS opcode
// add "----------" to emphasize the end of subroutine
static const char* emphasize = " -------------------------------------------------------------------------------------------------------------------------";
strncat(str_disassembly, emphasize, LOG_DISASSEMBLY_MAX_LEN - strlen(str_disassembly) - 1);
}
// stretch the disassembly string out if we have to output other stuff.
if ((logging_options & (LOG_REGISTERS|LOG_PROCESSOR_STATUS)) && !(logging_options & LOG_TO_THE_LEFT))
{
for (int i = strlen(str_disassembly); i < (LOG_DISASSEMBLY_MAX_LEN - 1); ++i)
str_disassembly[i] = ' ';
str_disassembly[LOG_DISASSEMBLY_MAX_LEN - 1] = 0;
}
//sprintf(str_address, "%X ", GetNesFileAddress(addr));
//sprintf(str_axystate, "%X %X %X %X %X ", X.A, X.X, X.Y, X.S, X.P);
//sprintf(bzk_string, "%X %X %X %X %X %X %X %X %X %X \n", addr, bzk_GetNesFileAddress(addr), bzk_getBank(0x8000), bzk_getBank(0xA000), bzk_getBank(0xC000), bzk_getBank(0xE000), X.A, X.X, X.Y, X.P);
//sprintf(bzk_string, "%u|%u|%u|%u|%u|%u|%u|%u|%s|\n", bzk_GetNesFileAddress(addr), bzk_getBank(0x8000), bzk_getBank(0xA000), bzk_getBank(0xC000), bzk_getBank(0xE000), X.A, X.X, X.Y, bzk_Disassemble(opcode));
sprintf(bzk_string, "%u|%u|%u|%u|%u|%s|\n", bzk_GetNesFileAddress(addr), bzk_getBank(addr), X.A, X.X, X.Y, bzk_Disassemble(addr, opcode));
// Start filling the str_temp line: Frame count, Cycles count, Instructions count, AXYS state, Processor status, Tabs, Address, Data, Disassembly
if (logging_options & LOG_FRAMES_COUNT)
{
sprintf(str_result, "f%-6u ", currFrameCounter);
} else
{
str_result[0] = 0;
}
if (logging_options & LOG_CYCLES_COUNT)
{
int64 counter_value = timestampbase + (uint64)timestamp - total_cycles_base;
if (counter_value < 0) // sanity check
{
ResetDebugStatisticsCounters();
counter_value = 0;
}
sprintf(str_temp, "c%-11llu ", counter_value);
strcat(str_result, str_temp);
}
if (logging_options & LOG_INSTRUCTIONS_COUNT)
{
sprintf(str_temp, "i%-11llu ", total_instructions);
strcat(str_result, str_temp);
}
if (logging_options & LOG_REGISTERS)
{
sprintf(str_axystate,"A:%02X X:%02X Y:%02X S:%02X ",(X.A),(X.X),(X.Y),(X.S));
}
if (logging_options & LOG_PROCESSOR_STATUS)
{
tmp = X.P^0xFF;
sprintf(str_procstatus,"P:%c%c%c%c%c%c%c%c ",
'N'|(tmp&0x80)>>2,
'V'|(tmp&0x40)>>1,
'U'|(tmp&0x20),
'B'|(tmp&0x10)<<1,
'D'|(tmp&0x08)<<2,
'I'|(tmp&0x04)<<3,
'Z'|(tmp&0x02)<<4,
'C'|(tmp&0x01)<<5
);
}
fputs(bzk_string, LOG_FP);
bzk_writes_counter++;
if (logging_options & LOG_TO_THE_LEFT)
if (bzk_writes_counter == 4999999)
{
if (logging_options & LOG_REGISTERS)
strcat(str_result, str_axystate);
if (logging_options & LOG_PROCESSOR_STATUS)
strcat(str_result, str_procstatus);
bzk_writes_counter = 0;
fflush(LOG_FP);
fclose(LOG_FP);
sprintf(bzk_newfilename, "z%05d_fceux.log", bzk_files_counter);
remove(bzk_newfilename); //delete file if exists
rename(bzk_filename, bzk_newfilename);
bzk_files_counter++;
if (bzk_files_counter >= 100000) bzk_files_counter = 0;
sprintf(bzk_filename, "z%05d.log", bzk_files_counter);
LOG_FP = fopen(bzk_filename, "w");
}
if (logging_options & LOG_CODE_TABBING)
{
// add spaces at the beginning of the line according to stack pointer
int spaces = (0xFF - X.S) & LOG_TABS_MASK;
for (int i = 0; i < spaces; i++)
str_tabs[i] = ' ';
str_tabs[spaces] = 0;
strcat(str_result, str_tabs);
} else if (logging_options & LOG_TO_THE_LEFT)
{
strcat(str_result, " ");
}
if (logging_options & LOG_BANK_NUMBER)
{
if (addr >= 0x8000)
sprintf(str_address, "$%02X:%04X: ", getBank(addr), addr);
else
sprintf(str_address, " $%04X: ", addr);
} else
{
sprintf(str_address, "$%04X: ", addr);
}
strcat(str_result, str_address);
strcat(str_result, str_data);
strcat(str_result, str_disassembly);
if (!(logging_options & LOG_TO_THE_LEFT))
{
if (logging_options & LOG_REGISTERS)
strcat(str_result, str_axystate);
if (logging_options & LOG_PROCESSOR_STATUS)
strcat(str_result, str_procstatus);
}
OutputLogLine(str_result, &tempAddressesLog);
return;
}
@ -1020,7 +1083,15 @@ void EndLoggingSequence()
{
if (logtofile)
{
fflush(LOG_FP);
fclose(LOG_FP);
sprintf(bzk_newfilename, "z%05d", bzk_files_counter);
strcat(bzk_newfilename, "_fceux.log");
rename(bzk_filename, bzk_newfilename);
bzk_files_counter++;
bzk_writes_counter = 0;
} else
{
strcpy(str_result, "Logging finished.");

View File

@ -30,7 +30,7 @@
#define LOG_AXYSTATE_MAX_LEN 21
#define LOG_PROCSTATUS_MAX_LEN 12
#define LOG_TABS_MASK 31
#define LOG_ADDRESS_MAX_LEN 13
#define LOG_ADDRESS_MAX_LEN 50
#define LOG_DATA_MAX_LEN 11
#define LOG_DISASSEMBLY_MAX_LEN 46