Merge pull request #718 from TheRealQuantam/tracefix4
Non-SDL/Qt Windows Trace Logging Optimizations
This commit is contained in:
commit
db8fd407ab
323
src/asm.cpp
323
src/asm.cpp
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
#include "utils/xstring.h"
|
#include "utils/xstring.h"
|
||||||
|
#include "utils/StringBuilder.h"
|
||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
#include "asm.h"
|
#include "asm.h"
|
||||||
#include "x6502.h"
|
#include "x6502.h"
|
||||||
|
@ -256,8 +257,11 @@ int Assemble(unsigned char *output, int addr, char *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.
|
///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 *Disassemble(int addr, uint8 *opcode) {
|
char *Disassemble(int addr, uint8 *opcode) {
|
||||||
static char str[64]={0},chr[5]={0};
|
static char str[64]={0};
|
||||||
|
const char *chr;
|
||||||
|
char indReg;
|
||||||
uint16 tmp,tmp2;
|
uint16 tmp,tmp2;
|
||||||
|
StringBuilder sb(str);
|
||||||
|
|
||||||
//these may be replaced later with passed-in values to make a lighter-weight disassembly mode that may not query the referenced values
|
//these may be replaced later with passed-in values to make a lighter-weight disassembly mode that may not query the referenced values
|
||||||
#define RX (X.X)
|
#define RX (X.X)
|
||||||
|
@ -286,7 +290,7 @@ char *Disassemble(int addr, uint8 *opcode) {
|
||||||
|
|
||||||
#ifdef BRK_3BYTE_HACK
|
#ifdef BRK_3BYTE_HACK
|
||||||
case 0x00:
|
case 0x00:
|
||||||
snprintf(str, sizeof(str), "BRK %02X %02X", opcode[1], opcode[2]);
|
sb << "BRK " << sb_hex(opcode[1], 2) << ' ' << sb_hex(opcode[2], 2);
|
||||||
break;
|
break;
|
||||||
#else
|
#else
|
||||||
case 0x00: strcpy(str,"BRK"); break;
|
case 0x00: strcpy(str,"BRK"); break;
|
||||||
|
@ -323,207 +327,228 @@ char *Disassemble(int addr, uint8 *opcode) {
|
||||||
case 0xF8: strcpy(str,"SED"); break;
|
case 0xF8: strcpy(str,"SED"); break;
|
||||||
|
|
||||||
//(Indirect,X)
|
//(Indirect,X)
|
||||||
case 0x01: strcpy(chr,"ORA"); goto _indirectx;
|
case 0x01: chr = "ORA"; goto _indirectx;
|
||||||
case 0x21: strcpy(chr,"AND"); goto _indirectx;
|
case 0x21: chr = "AND"; goto _indirectx;
|
||||||
case 0x41: strcpy(chr,"EOR"); goto _indirectx;
|
case 0x41: chr = "EOR"; goto _indirectx;
|
||||||
case 0x61: strcpy(chr,"ADC"); goto _indirectx;
|
case 0x61: chr = "ADC"; goto _indirectx;
|
||||||
case 0x81: strcpy(chr,"STA"); goto _indirectx;
|
case 0x81: chr = "STA"; goto _indirectx;
|
||||||
case 0xA1: strcpy(chr,"LDA"); goto _indirectx;
|
case 0xA1: chr = "LDA"; goto _indirectx;
|
||||||
case 0xC1: strcpy(chr,"CMP"); goto _indirectx;
|
case 0xC1: chr = "CMP"; goto _indirectx;
|
||||||
case 0xE1: strcpy(chr,"SBC"); goto _indirectx;
|
case 0xE1: chr = "SBC"; goto _indirectx;
|
||||||
_indirectx:
|
_indirectx:
|
||||||
indirectX(tmp);
|
indirectX(tmp);
|
||||||
snprintf(str, sizeof(str), "%s ($%02X,X) @ $%04X = #$%02X", chr,opcode[1],tmp,GetMem(tmp));
|
indReg = 'X';
|
||||||
|
|
||||||
|
_indirect:
|
||||||
|
sb << chr << " (" << sb_addr(opcode[1], 2) << ',' << indReg << ") @ " << sb_addr(tmp) << " = " << sb_lit(GetMem(tmp));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
//Zero Page
|
//Zero Page
|
||||||
case 0x05: strcpy(chr,"ORA"); goto _zeropage;
|
case 0x05: chr = "ORA"; goto _zeropage;
|
||||||
case 0x06: strcpy(chr,"ASL"); goto _zeropage;
|
case 0x06: chr = "ASL"; goto _zeropage;
|
||||||
case 0x24: strcpy(chr,"BIT"); goto _zeropage;
|
case 0x24: chr = "BIT"; goto _zeropage;
|
||||||
case 0x25: strcpy(chr,"AND"); goto _zeropage;
|
case 0x25: chr = "AND"; goto _zeropage;
|
||||||
case 0x26: strcpy(chr,"ROL"); goto _zeropage;
|
case 0x26: chr = "ROL"; goto _zeropage;
|
||||||
case 0x45: strcpy(chr,"EOR"); goto _zeropage;
|
case 0x45: chr = "EOR"; goto _zeropage;
|
||||||
case 0x46: strcpy(chr,"LSR"); goto _zeropage;
|
case 0x46: chr = "LSR"; goto _zeropage;
|
||||||
case 0x65: strcpy(chr,"ADC"); goto _zeropage;
|
case 0x65: chr = "ADC"; goto _zeropage;
|
||||||
case 0x66: strcpy(chr,"ROR"); goto _zeropage;
|
case 0x66: chr = "ROR"; goto _zeropage;
|
||||||
case 0x84: strcpy(chr,"STY"); goto _zeropage;
|
case 0x84: chr = "STY"; goto _zeropage;
|
||||||
case 0x85: strcpy(chr,"STA"); goto _zeropage;
|
case 0x85: chr = "STA"; goto _zeropage;
|
||||||
case 0x86: strcpy(chr,"STX"); goto _zeropage;
|
case 0x86: chr = "STX"; goto _zeropage;
|
||||||
case 0xA4: strcpy(chr,"LDY"); goto _zeropage;
|
case 0xA4: chr = "LDY"; goto _zeropage;
|
||||||
case 0xA5: strcpy(chr,"LDA"); goto _zeropage;
|
case 0xA5: chr = "LDA"; goto _zeropage;
|
||||||
case 0xA6: strcpy(chr,"LDX"); goto _zeropage;
|
case 0xA6: chr = "LDX"; goto _zeropage;
|
||||||
case 0xC4: strcpy(chr,"CPY"); goto _zeropage;
|
case 0xC4: chr = "CPY"; goto _zeropage;
|
||||||
case 0xC5: strcpy(chr,"CMP"); goto _zeropage;
|
case 0xC5: chr = "CMP"; goto _zeropage;
|
||||||
case 0xC6: strcpy(chr,"DEC"); goto _zeropage;
|
case 0xC6: chr = "DEC"; goto _zeropage;
|
||||||
case 0xE4: strcpy(chr,"CPX"); goto _zeropage;
|
case 0xE4: chr = "CPX"; goto _zeropage;
|
||||||
case 0xE5: strcpy(chr,"SBC"); goto _zeropage;
|
case 0xE5: chr = "SBC"; goto _zeropage;
|
||||||
case 0xE6: strcpy(chr,"INC"); goto _zeropage;
|
case 0xE6: chr = "INC"; goto _zeropage;
|
||||||
_zeropage:
|
_zeropage:
|
||||||
// ################################## Start of SP CODE ###########################
|
// ################################## Start of SP CODE ###########################
|
||||||
// Change width to %04X // don't!
|
// Change width to %04X // don't!
|
||||||
snprintf(str, sizeof(str), "%s $%02X = #$%02X", chr,opcode[1],GetMem(opcode[1]));
|
sb << chr << ' ' << sb_addr(opcode[1], 2) << " = " << sb_lit(GetMem(opcode[1]));
|
||||||
// ################################## End of SP CODE ###########################
|
// ################################## End of SP CODE ###########################
|
||||||
break;
|
break;
|
||||||
|
|
||||||
//#Immediate
|
//#Immediate
|
||||||
case 0x09: strcpy(chr,"ORA"); goto _immediate;
|
case 0x09: chr = "ORA"; goto _immediate;
|
||||||
case 0x29: strcpy(chr,"AND"); goto _immediate;
|
case 0x29: chr = "AND"; goto _immediate;
|
||||||
case 0x49: strcpy(chr,"EOR"); goto _immediate;
|
case 0x49: chr = "EOR"; goto _immediate;
|
||||||
case 0x69: strcpy(chr,"ADC"); goto _immediate;
|
case 0x69: chr = "ADC"; goto _immediate;
|
||||||
//case 0x89: strcpy(chr,"STA"); goto _immediate; //baka, no STA #imm!!
|
//case 0x89: chr = "STA"; goto _immediate; //baka, no STA #imm!!
|
||||||
case 0xA0: strcpy(chr,"LDY"); goto _immediate;
|
case 0xA0: chr = "LDY"; goto _immediate;
|
||||||
case 0xA2: strcpy(chr,"LDX"); goto _immediate;
|
case 0xA2: chr = "LDX"; goto _immediate;
|
||||||
case 0xA9: strcpy(chr,"LDA"); goto _immediate;
|
case 0xA9: chr = "LDA"; goto _immediate;
|
||||||
case 0xC0: strcpy(chr,"CPY"); goto _immediate;
|
case 0xC0: chr = "CPY"; goto _immediate;
|
||||||
case 0xC9: strcpy(chr,"CMP"); goto _immediate;
|
case 0xC9: chr = "CMP"; goto _immediate;
|
||||||
case 0xE0: strcpy(chr,"CPX"); goto _immediate;
|
case 0xE0: chr = "CPX"; goto _immediate;
|
||||||
case 0xE9: strcpy(chr,"SBC"); goto _immediate;
|
case 0xE9: chr = "SBC"; goto _immediate;
|
||||||
_immediate:
|
_immediate:
|
||||||
snprintf(str, sizeof(str), "%s #$%02X", chr,opcode[1]);
|
sb << chr << ' ' << sb_lit(opcode[1]);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
//Absolute
|
//Absolute
|
||||||
case 0x0D: strcpy(chr,"ORA"); goto _absolute;
|
case 0x0D: chr = "ORA"; goto _absolute;
|
||||||
case 0x0E: strcpy(chr,"ASL"); goto _absolute;
|
case 0x0E: chr = "ASL"; goto _absolute;
|
||||||
case 0x2C: strcpy(chr,"BIT"); goto _absolute;
|
case 0x2C: chr = "BIT"; goto _absolute;
|
||||||
case 0x2D: strcpy(chr,"AND"); goto _absolute;
|
case 0x2D: chr = "AND"; goto _absolute;
|
||||||
case 0x2E: strcpy(chr,"ROL"); goto _absolute;
|
case 0x2E: chr = "ROL"; goto _absolute;
|
||||||
case 0x4D: strcpy(chr,"EOR"); goto _absolute;
|
case 0x4D: chr = "EOR"; goto _absolute;
|
||||||
case 0x4E: strcpy(chr,"LSR"); goto _absolute;
|
case 0x4E: chr = "LSR"; goto _absolute;
|
||||||
case 0x6D: strcpy(chr,"ADC"); goto _absolute;
|
case 0x6D: chr = "ADC"; goto _absolute;
|
||||||
case 0x6E: strcpy(chr,"ROR"); goto _absolute;
|
case 0x6E: chr = "ROR"; goto _absolute;
|
||||||
case 0x8C: strcpy(chr,"STY"); goto _absolute;
|
case 0x8C: chr = "STY"; goto _absolute;
|
||||||
case 0x8D: strcpy(chr,"STA"); goto _absolute;
|
case 0x8D: chr = "STA"; goto _absolute;
|
||||||
case 0x8E: strcpy(chr,"STX"); goto _absolute;
|
case 0x8E: chr = "STX"; goto _absolute;
|
||||||
case 0xAC: strcpy(chr,"LDY"); goto _absolute;
|
case 0xAC: chr = "LDY"; goto _absolute;
|
||||||
case 0xAD: strcpy(chr,"LDA"); goto _absolute;
|
case 0xAD: chr = "LDA"; goto _absolute;
|
||||||
case 0xAE: strcpy(chr,"LDX"); goto _absolute;
|
case 0xAE: chr = "LDX"; goto _absolute;
|
||||||
case 0xCC: strcpy(chr,"CPY"); goto _absolute;
|
case 0xCC: chr = "CPY"; goto _absolute;
|
||||||
case 0xCD: strcpy(chr,"CMP"); goto _absolute;
|
case 0xCD: chr = "CMP"; goto _absolute;
|
||||||
case 0xCE: strcpy(chr,"DEC"); goto _absolute;
|
case 0xCE: chr = "DEC"; goto _absolute;
|
||||||
case 0xEC: strcpy(chr,"CPX"); goto _absolute;
|
case 0xEC: chr = "CPX"; goto _absolute;
|
||||||
case 0xED: strcpy(chr,"SBC"); goto _absolute;
|
case 0xED: chr = "SBC"; goto _absolute;
|
||||||
case 0xEE: strcpy(chr,"INC"); goto _absolute;
|
case 0xEE: chr = "INC"; goto _absolute;
|
||||||
_absolute:
|
_absolute:
|
||||||
absolute(tmp);
|
absolute(tmp);
|
||||||
snprintf(str, sizeof(str), "%s $%04X = #$%02X", chr,tmp,GetMem(tmp));
|
|
||||||
|
sb << chr << ' ' << sb_addr(tmp) << " = " << sb_lit(GetMem(tmp));
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
//branches
|
//branches
|
||||||
case 0x10: strcpy(chr,"BPL"); goto _branch;
|
case 0x10: chr = "BPL"; goto _branch;
|
||||||
case 0x30: strcpy(chr,"BMI"); goto _branch;
|
case 0x30: chr = "BMI"; goto _branch;
|
||||||
case 0x50: strcpy(chr,"BVC"); goto _branch;
|
case 0x50: chr = "BVC"; goto _branch;
|
||||||
case 0x70: strcpy(chr,"BVS"); goto _branch;
|
case 0x70: chr = "BVS"; goto _branch;
|
||||||
case 0x90: strcpy(chr,"BCC"); goto _branch;
|
case 0x90: chr = "BCC"; goto _branch;
|
||||||
case 0xB0: strcpy(chr,"BCS"); goto _branch;
|
case 0xB0: chr = "BCS"; goto _branch;
|
||||||
case 0xD0: strcpy(chr,"BNE"); goto _branch;
|
case 0xD0: chr = "BNE"; goto _branch;
|
||||||
case 0xF0: strcpy(chr,"BEQ"); goto _branch;
|
case 0xF0: chr = "BEQ"; goto _branch;
|
||||||
_branch:
|
_branch:
|
||||||
relative(tmp);
|
relative(tmp);
|
||||||
snprintf(str, sizeof(str), "%s $%04X", chr,tmp);
|
|
||||||
|
sb << chr << ' ' << sb_addr(tmp);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
//(Indirect),Y
|
//(Indirect),Y
|
||||||
case 0x11: strcpy(chr,"ORA"); goto _indirecty;
|
case 0x11: chr = "ORA"; goto _indirecty;
|
||||||
case 0x31: strcpy(chr,"AND"); goto _indirecty;
|
case 0x31: chr = "AND"; goto _indirecty;
|
||||||
case 0x51: strcpy(chr,"EOR"); goto _indirecty;
|
case 0x51: chr = "EOR"; goto _indirecty;
|
||||||
case 0x71: strcpy(chr,"ADC"); goto _indirecty;
|
case 0x71: chr = "ADC"; goto _indirecty;
|
||||||
case 0x91: strcpy(chr,"STA"); goto _indirecty;
|
case 0x91: chr = "STA"; goto _indirecty;
|
||||||
case 0xB1: strcpy(chr,"LDA"); goto _indirecty;
|
case 0xB1: chr = "LDA"; goto _indirecty;
|
||||||
case 0xD1: strcpy(chr,"CMP"); goto _indirecty;
|
case 0xD1: chr = "CMP"; goto _indirecty;
|
||||||
case 0xF1: strcpy(chr,"SBC"); goto _indirecty;
|
case 0xF1: chr = "SBC"; goto _indirecty;
|
||||||
_indirecty:
|
_indirecty:
|
||||||
indirectY(tmp);
|
indirectY(tmp);
|
||||||
snprintf(str, sizeof(str), "%s ($%02X),Y @ $%04X = #$%02X", chr,opcode[1],tmp,GetMem(tmp));
|
indReg = 'Y';
|
||||||
break;
|
|
||||||
|
goto _indirect;
|
||||||
|
|
||||||
//Zero Page,X
|
//Zero Page,X
|
||||||
case 0x15: strcpy(chr,"ORA"); goto _zeropagex;
|
case 0x15: chr = "ORA"; goto _zeropagex;
|
||||||
case 0x16: strcpy(chr,"ASL"); goto _zeropagex;
|
case 0x16: chr = "ASL"; goto _zeropagex;
|
||||||
case 0x35: strcpy(chr,"AND"); goto _zeropagex;
|
case 0x35: chr = "AND"; goto _zeropagex;
|
||||||
case 0x36: strcpy(chr,"ROL"); goto _zeropagex;
|
case 0x36: chr = "ROL"; goto _zeropagex;
|
||||||
case 0x55: strcpy(chr,"EOR"); goto _zeropagex;
|
case 0x55: chr = "EOR"; goto _zeropagex;
|
||||||
case 0x56: strcpy(chr,"LSR"); goto _zeropagex;
|
case 0x56: chr = "LSR"; goto _zeropagex;
|
||||||
case 0x75: strcpy(chr,"ADC"); goto _zeropagex;
|
case 0x75: chr = "ADC"; goto _zeropagex;
|
||||||
case 0x76: strcpy(chr,"ROR"); goto _zeropagex;
|
case 0x76: chr = "ROR"; goto _zeropagex;
|
||||||
case 0x94: strcpy(chr,"STY"); goto _zeropagex;
|
case 0x94: chr = "STY"; goto _zeropagex;
|
||||||
case 0x95: strcpy(chr,"STA"); goto _zeropagex;
|
case 0x95: chr = "STA"; goto _zeropagex;
|
||||||
case 0xB4: strcpy(chr,"LDY"); goto _zeropagex;
|
case 0xB4: chr = "LDY"; goto _zeropagex;
|
||||||
case 0xB5: strcpy(chr,"LDA"); goto _zeropagex;
|
case 0xB5: chr = "LDA"; goto _zeropagex;
|
||||||
case 0xD5: strcpy(chr,"CMP"); goto _zeropagex;
|
case 0xD5: chr = "CMP"; goto _zeropagex;
|
||||||
case 0xD6: strcpy(chr,"DEC"); goto _zeropagex;
|
case 0xD6: chr = "DEC"; goto _zeropagex;
|
||||||
case 0xF5: strcpy(chr,"SBC"); goto _zeropagex;
|
case 0xF5: chr = "SBC"; goto _zeropagex;
|
||||||
case 0xF6: strcpy(chr,"INC"); goto _zeropagex;
|
case 0xF6: chr = "INC"; goto _zeropagex;
|
||||||
_zeropagex:
|
_zeropagex:
|
||||||
zpIndex(tmp,RX);
|
zpIndex(tmp, RX);
|
||||||
|
indReg = 'X';
|
||||||
|
|
||||||
|
_indexed:
|
||||||
// ################################## Start of SP CODE ###########################
|
// ################################## Start of SP CODE ###########################
|
||||||
// Change width to %04X // don't!
|
// Change width to %04X // don't!
|
||||||
snprintf(str, sizeof(str), "%s $%02X,X @ $%04X = #$%02X", chr,opcode[1],tmp,GetMem(tmp));
|
sb << chr << ' ' << sb_addr(opcode[1], 2) << ',' << indReg << " @ " << sb_addr(tmp) << " = " << sb_lit(GetMem(tmp));
|
||||||
// ################################## End of SP CODE ###########################
|
// ################################## End of SP CODE ###########################
|
||||||
break;
|
break;
|
||||||
|
|
||||||
//Absolute,Y
|
//Absolute,Y
|
||||||
case 0x19: strcpy(chr,"ORA"); goto _absolutey;
|
case 0x19: chr = "ORA"; goto _absolutey;
|
||||||
case 0x39: strcpy(chr,"AND"); goto _absolutey;
|
case 0x39: chr = "AND"; goto _absolutey;
|
||||||
case 0x59: strcpy(chr,"EOR"); goto _absolutey;
|
case 0x59: chr = "EOR"; goto _absolutey;
|
||||||
case 0x79: strcpy(chr,"ADC"); goto _absolutey;
|
case 0x79: chr = "ADC"; goto _absolutey;
|
||||||
case 0x99: strcpy(chr,"STA"); goto _absolutey;
|
case 0x99: chr = "STA"; goto _absolutey;
|
||||||
case 0xB9: strcpy(chr,"LDA"); goto _absolutey;
|
case 0xB9: chr = "LDA"; goto _absolutey;
|
||||||
case 0xBE: strcpy(chr,"LDX"); goto _absolutey;
|
case 0xBE: chr = "LDX"; goto _absolutey;
|
||||||
case 0xD9: strcpy(chr,"CMP"); goto _absolutey;
|
case 0xD9: chr = "CMP"; goto _absolutey;
|
||||||
case 0xF9: strcpy(chr,"SBC"); goto _absolutey;
|
case 0xF9: chr = "SBC"; goto _absolutey;
|
||||||
_absolutey:
|
_absolutey:
|
||||||
absolute(tmp);
|
absolute(tmp);
|
||||||
tmp2=(tmp+RY);
|
tmp2 = (tmp + RY);
|
||||||
snprintf(str, sizeof(str), "%s $%04X,Y @ $%04X = #$%02X", chr,tmp,tmp2,GetMem(tmp2));
|
indReg = 'Y';
|
||||||
|
|
||||||
|
_absindexed:
|
||||||
|
sb << chr << ' ' << sb_addr(tmp) << ',' << indReg << " @ " << sb_addr(tmp2) << " = " << sb_lit(GetMem(tmp2));
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
//Absolute,X
|
//Absolute,X
|
||||||
case 0x1D: strcpy(chr,"ORA"); goto _absolutex;
|
case 0x1D: chr = "ORA"; goto _absolutex;
|
||||||
case 0x1E: strcpy(chr,"ASL"); goto _absolutex;
|
case 0x1E: chr = "ASL"; goto _absolutex;
|
||||||
case 0x3D: strcpy(chr,"AND"); goto _absolutex;
|
case 0x3D: chr = "AND"; goto _absolutex;
|
||||||
case 0x3E: strcpy(chr,"ROL"); goto _absolutex;
|
case 0x3E: chr = "ROL"; goto _absolutex;
|
||||||
case 0x5D: strcpy(chr,"EOR"); goto _absolutex;
|
case 0x5D: chr = "EOR"; goto _absolutex;
|
||||||
case 0x5E: strcpy(chr,"LSR"); goto _absolutex;
|
case 0x5E: chr = "LSR"; goto _absolutex;
|
||||||
case 0x7D: strcpy(chr,"ADC"); goto _absolutex;
|
case 0x7D: chr = "ADC"; goto _absolutex;
|
||||||
case 0x7E: strcpy(chr,"ROR"); goto _absolutex;
|
case 0x7E: chr = "ROR"; goto _absolutex;
|
||||||
case 0x9D: strcpy(chr,"STA"); goto _absolutex;
|
case 0x9D: chr = "STA"; goto _absolutex;
|
||||||
case 0xBC: strcpy(chr,"LDY"); goto _absolutex;
|
case 0xBC: chr = "LDY"; goto _absolutex;
|
||||||
case 0xBD: strcpy(chr,"LDA"); goto _absolutex;
|
case 0xBD: chr = "LDA"; goto _absolutex;
|
||||||
case 0xDD: strcpy(chr,"CMP"); goto _absolutex;
|
case 0xDD: chr = "CMP"; goto _absolutex;
|
||||||
case 0xDE: strcpy(chr,"DEC"); goto _absolutex;
|
case 0xDE: chr = "DEC"; goto _absolutex;
|
||||||
case 0xFD: strcpy(chr,"SBC"); goto _absolutex;
|
case 0xFD: chr = "SBC"; goto _absolutex;
|
||||||
case 0xFE: strcpy(chr,"INC"); goto _absolutex;
|
case 0xFE: chr = "INC"; goto _absolutex;
|
||||||
_absolutex:
|
_absolutex:
|
||||||
absolute(tmp);
|
absolute(tmp);
|
||||||
tmp2=(tmp+RX);
|
tmp2 = (tmp + RX);
|
||||||
snprintf(str, sizeof(str), "%s $%04X,X @ $%04X = #$%02X", chr,tmp,tmp2,GetMem(tmp2));
|
indReg = 'X';
|
||||||
break;
|
|
||||||
|
goto _absindexed;
|
||||||
|
|
||||||
//jumps
|
//jumps
|
||||||
case 0x20: strcpy(chr,"JSR"); goto _jump;
|
case 0x20: chr = "JSR"; goto _jump;
|
||||||
case 0x4C: strcpy(chr,"JMP"); goto _jump;
|
case 0x4C: chr = "JMP"; goto _jump;
|
||||||
case 0x6C: absolute(tmp); snprintf(str, sizeof(str), "JMP ($%04X) = $%04X", tmp,GetMem(tmp)|GetMem(tmp+1)<<8); break;
|
|
||||||
_jump:
|
_jump:
|
||||||
absolute(tmp);
|
absolute(tmp);
|
||||||
snprintf(str, sizeof(str), "%s $%04X", chr,tmp);
|
|
||||||
|
sb << chr << ' ' << sb_addr(tmp);
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0x6C:
|
||||||
|
absolute(tmp);
|
||||||
|
|
||||||
|
sb << "JMP (" << sb_addr(tmp);
|
||||||
|
sb << ") = " << sb_addr(GetMem(tmp) | GetMem(tmp + 1) << 8);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
//Zero Page,Y
|
//Zero Page,Y
|
||||||
case 0x96: strcpy(chr,"STX"); goto _zeropagey;
|
case 0x96: chr = "STX"; goto _zeropagey;
|
||||||
case 0xB6: strcpy(chr,"LDX"); goto _zeropagey;
|
case 0xB6: chr = "LDX"; goto _zeropagey;
|
||||||
_zeropagey:
|
_zeropagey:
|
||||||
zpIndex(tmp,RY);
|
zpIndex(tmp, RY);
|
||||||
// ################################## Start of SP CODE ###########################
|
indReg = 'Y';
|
||||||
// Change width to %04X // don't!
|
|
||||||
snprintf(str, sizeof(str), "%s $%02X,Y @ $%04X = #$%02X", chr,opcode[1],tmp,GetMem(tmp));
|
goto _indexed;
|
||||||
// ################################## End of SP CODE ###########################
|
|
||||||
break;
|
|
||||||
|
|
||||||
//UNDEFINED
|
//UNDEFINED
|
||||||
default: strcpy(str,"ERROR"); break;
|
default: strcpy(str, "ERROR"); break;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,7 +25,7 @@
|
||||||
|
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#include <Qt/TraceFileWriter.h>
|
#include "../win/TraceFileWriter.h"
|
||||||
#else
|
#else
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
|
|
@ -125,7 +125,7 @@ public:
|
||||||
|
|
||||||
// Add a line to the buffer and write it out when the buffer is filled
|
// Add a line to the buffer and write it out when the buffer is filled
|
||||||
// Under most failure cirumstances the line is added to the buffer
|
// Under most failure cirumstances the line is added to the buffer
|
||||||
bool writeLine(const char *line)
|
bool writeLine(const char *line, bool addEol = true)
|
||||||
{
|
{
|
||||||
if (!isOpen)
|
if (!isOpen)
|
||||||
{
|
{
|
||||||
|
@ -138,6 +138,7 @@ public:
|
||||||
size_t eolSize = strlen(eol);
|
size_t eolSize = strlen(eol);
|
||||||
char *buff = buffers[buffIdx];
|
char *buff = buffers[buffIdx];
|
||||||
size_t lineLen = strlen(line);
|
size_t lineLen = strlen(line);
|
||||||
|
size_t copyLen = lineLen + (addEol ? eolSize : 0);
|
||||||
if (buffOffs + lineLen + eolSize > BuffSize)
|
if (buffOffs + lineLen + eolSize > BuffSize)
|
||||||
{
|
{
|
||||||
// Buffer is full. This shouldn't ever happen.
|
// Buffer is full. This shouldn't ever happen.
|
||||||
|
@ -146,6 +147,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy(buff + buffOffs, line, lineLen);
|
memcpy(buff + buffOffs, line, lineLen);
|
||||||
|
if (addEol)
|
||||||
memcpy(buff + buffOffs + lineLen, eol, eolSize);
|
memcpy(buff + buffOffs + lineLen, eol, eolSize);
|
||||||
buffOffs += lineLen + eolSize;
|
buffOffs += lineLen + eolSize;
|
||||||
|
|
||||||
|
@ -202,7 +204,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
typedef BOOL (*SetFileInformationByHandlePtr)(
|
typedef BOOL (WINAPI *SetFileInformationByHandlePtr)(
|
||||||
HANDLE hFile,
|
HANDLE hFile,
|
||||||
FILE_INFO_BY_HANDLE_CLASS FileInformationClass,
|
FILE_INFO_BY_HANDLE_CLASS FileInformationClass,
|
||||||
LPVOID lpFileInformation,
|
LPVOID lpFileInformation,
|
|
@ -27,10 +27,12 @@
|
||||||
#include "../../debug.h"
|
#include "../../debug.h"
|
||||||
#include "../../debugsymboltable.h"
|
#include "../../debugsymboltable.h"
|
||||||
#include "../../conddebug.h"
|
#include "../../conddebug.h"
|
||||||
|
#include "utils/StringBuilder.h"
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
#include <cstdlib>
|
||||||
|
|
||||||
int GetNesFileAddress(int A);
|
int GetNesFileAddress(int A);
|
||||||
|
|
||||||
|
@ -103,8 +105,14 @@ MemoryMappedRegister RegNames[] = {
|
||||||
{"$4017", "JOY2_FRAME"}
|
{"$4017", "JOY2_FRAME"}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const char minRegFirstDigit = '2', maxRegFirstDigit = '4';
|
||||||
|
|
||||||
int RegNameCount = sizeof(RegNames)/sizeof(MemoryMappedRegister);
|
int RegNameCount = sizeof(RegNames)/sizeof(MemoryMappedRegister);
|
||||||
|
|
||||||
|
auto cmpRegNames = [](const void *a, const void *b) {
|
||||||
|
return std::strncmp(((const MemoryMappedRegister *)a)->offset + 1, ((const MemoryMappedRegister *)b)->offset + 1, 4);
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parses a line from a NL file.
|
* Parses a line from a NL file.
|
||||||
* @param line The line to parse
|
* @param line The line to parse
|
||||||
|
@ -603,20 +611,39 @@ void replaceNames(Name* list, char* str, std::vector<uint16>* addressesLog)
|
||||||
list = list->next;
|
list = list->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < RegNameCount; i++) {
|
if (symbRegNames) {
|
||||||
if (!symbRegNames) break;
|
StringBuilder sb(buff);
|
||||||
// copypaste, because Name* is too complex to abstract
|
|
||||||
*buff = 0;
|
|
||||||
src = str;
|
|
||||||
|
|
||||||
while (pos = strstr(src, RegNames[i].offset)) {
|
pos = src = str;
|
||||||
*pos = 0;
|
while (pos = std::strchr(pos, '$'))
|
||||||
strcat(buff, src);
|
{
|
||||||
strcat(buff, RegNames[i].name);
|
char first = pos[1];
|
||||||
src = pos + 5;
|
if (first < minRegFirstDigit || first > maxRegFirstDigit)
|
||||||
|
{
|
||||||
|
pos += 1;
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
if (*buff) {
|
|
||||||
strcat(buff, src);
|
MemoryMappedRegister key = { pos, "" };
|
||||||
|
const MemoryMappedRegister *reg = (const MemoryMappedRegister *)std::bsearch(&key, RegNames, RegNameCount, sizeof(MemoryMappedRegister), cmpRegNames);
|
||||||
|
if (reg != nullptr)
|
||||||
|
{
|
||||||
|
*pos = '\0';
|
||||||
|
sb << src << reg->name;
|
||||||
|
|
||||||
|
pos += 5;
|
||||||
|
src = pos;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
pos += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If no registers were found then the string is unmodified and no copies are necessary
|
||||||
|
if (src != str)
|
||||||
|
{
|
||||||
|
if (*src)
|
||||||
|
sb << src;
|
||||||
|
|
||||||
strcpy(str, buff);
|
strcpy(str, buff);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,8 +32,10 @@
|
||||||
#include "cdlogger.h"
|
#include "cdlogger.h"
|
||||||
#include "tracer.h"
|
#include "tracer.h"
|
||||||
#include "memview.h"
|
#include "memview.h"
|
||||||
|
#include "TraceFileWriter.h"
|
||||||
#include "main.h" //for GetRomName()
|
#include "main.h" //for GetRomName()
|
||||||
#include "utils/xstring.h"
|
#include "utils/xstring.h"
|
||||||
|
#include "utils/StringBuilder.h"
|
||||||
|
|
||||||
//Used to determine the current hotkey mapping for the pause key in order to display on the dialog
|
//Used to determine the current hotkey mapping for the pause key in order to display on the dialog
|
||||||
#include "mapinput.h"
|
#include "mapinput.h"
|
||||||
|
@ -132,7 +134,7 @@ bool log_old_emu_paused = true; // thanks to this flag the window only updates
|
||||||
extern bool JustFrameAdvanced;
|
extern bool JustFrameAdvanced;
|
||||||
extern int currFrameCounter;
|
extern int currFrameCounter;
|
||||||
|
|
||||||
FILE *LOG_FP;
|
TraceFileWriter fileWriter;
|
||||||
|
|
||||||
char trace_str[35000] = {0};
|
char trace_str[35000] = {0};
|
||||||
WNDPROC IDC_TRACER_LOG_oldWndProc = 0;
|
WNDPROC IDC_TRACER_LOG_oldWndProc = 0;
|
||||||
|
@ -686,14 +688,13 @@ void BeginLoggingSequence(void)
|
||||||
{
|
{
|
||||||
if(logfilename == NULL) ShowLogDirDialog();
|
if(logfilename == NULL) ShowLogDirDialog();
|
||||||
if (!logfilename) return;
|
if (!logfilename) return;
|
||||||
LOG_FP = fopen(logfilename,"w");
|
if (!fileWriter.open(logfilename, false))
|
||||||
if (LOG_FP == NULL)
|
|
||||||
{
|
{
|
||||||
sprintf(trace_str, "Error Opening File %s", logfilename);
|
sprintf(trace_str, "Error Opening File %s", logfilename);
|
||||||
MessageBox(hTracer, trace_str, "File Error", MB_OK);
|
MessageBox(hTracer, trace_str, "File Error", MB_OK);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
fprintf(LOG_FP,FCEU_NAME_AND_VERSION" - Trace Log File\n"); //mbg merge 7/19/06 changed string
|
fileWriter.writeLine(FCEU_NAME_AND_VERSION" - Trace Log File");
|
||||||
} else
|
} else
|
||||||
{
|
{
|
||||||
ClearTraceLogBuf();
|
ClearTraceLogBuf();
|
||||||
|
@ -734,8 +735,8 @@ void BeginLoggingSequence(void)
|
||||||
|
|
||||||
void FCEUD_FlushTrace()
|
void FCEUD_FlushTrace()
|
||||||
{
|
{
|
||||||
if(LOG_FP)
|
if(fileWriter.getOpen())
|
||||||
fflush(LOG_FP);
|
fileWriter.flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
//todo: really speed this up
|
//todo: really speed this up
|
||||||
|
@ -745,8 +746,8 @@ void FCEUD_TraceInstruction(uint8 *opcode, int size)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
unsigned int addr = X.PC;
|
unsigned int addr = X.PC;
|
||||||
uint8 tmp;
|
|
||||||
static int unloggedlines;
|
static int unloggedlines;
|
||||||
|
StringBuilder dataSb(str_data), dasmSb(str_disassembly), resSb(str_result);
|
||||||
|
|
||||||
// if instruction executed from the RAM, skip this, log all instead
|
// if instruction executed from the RAM, skip this, log all instead
|
||||||
// TODO: loops folding mame-lyke style
|
// TODO: loops folding mame-lyke style
|
||||||
|
@ -760,7 +761,7 @@ void FCEUD_TraceInstruction(uint8 *opcode, int size)
|
||||||
olddatacount = datacount;
|
olddatacount = datacount;
|
||||||
if(unloggedlines > 0)
|
if(unloggedlines > 0)
|
||||||
{
|
{
|
||||||
sprintf(str_result, "(%d lines skipped)", unloggedlines);
|
resSb << '(' << sb_dec(unloggedlines) << " lines skipped)";
|
||||||
OutputLogLine(str_result);
|
OutputLogLine(str_result);
|
||||||
unloggedlines = 0;
|
unloggedlines = 0;
|
||||||
}
|
}
|
||||||
|
@ -778,20 +779,22 @@ void FCEUD_TraceInstruction(uint8 *opcode, int size)
|
||||||
|
|
||||||
if ((addr + size) > 0xFFFF)
|
if ((addr + size) > 0xFFFF)
|
||||||
{
|
{
|
||||||
sprintf(str_data, "%02X ", opcode[0]);
|
dataSb << sb_hex(opcode[0], 2) << " ";
|
||||||
sprintf(str_disassembly, "OVERFLOW");
|
dasmSb << "OVERFLOW";
|
||||||
} else
|
} else
|
||||||
{
|
{
|
||||||
char* a = 0;
|
char* a = 0;
|
||||||
switch (size)
|
switch (size)
|
||||||
{
|
{
|
||||||
case 0:
|
case 0:
|
||||||
sprintf(str_data, "%02X ", opcode[0]);
|
dataSb << sb_hex(opcode[0], 2) << " ";
|
||||||
sprintf(str_disassembly,"UNDEFINED");
|
dasmSb << "UNDEFINED";
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
{
|
{
|
||||||
sprintf(str_data, "%02X ", opcode[0]);
|
StringBuilder decSb(str_decoration);
|
||||||
|
|
||||||
|
dataSb << sb_hex(opcode[0], 2) << " ";
|
||||||
a = Disassemble(addr + 1, opcode);
|
a = Disassemble(addr + 1, opcode);
|
||||||
// special case: an RTS opcode
|
// special case: an RTS opcode
|
||||||
if (opcode[0] == 0x60)
|
if (opcode[0] == 0x60)
|
||||||
|
@ -802,18 +805,18 @@ void FCEUD_TraceInstruction(uint8 *opcode, int size)
|
||||||
{
|
{
|
||||||
// this was a JSR instruction - take the subroutine address from it
|
// this was a JSR instruction - take the subroutine address from it
|
||||||
unsigned int call_addr = GetMem(caller_addr + 1) + (GetMem(caller_addr + 2) << 8);
|
unsigned int call_addr = GetMem(caller_addr + 1) + (GetMem(caller_addr + 2) << 8);
|
||||||
sprintf(str_decoration, " (from $%04X)", call_addr);
|
decSb << " (from " << sb_addr(call_addr) << ')';
|
||||||
strcat(a, str_decoration);
|
strcat(a, str_decoration);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 2:
|
case 2:
|
||||||
sprintf(str_data, "%02X %02X ", opcode[0],opcode[1]);
|
dataSb << sb_hex(opcode[0], 2) << ' ' << sb_hex(opcode[1], 2) << " ";
|
||||||
a = Disassemble(addr + 2, opcode);
|
a = Disassemble(addr + 2, opcode);
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
sprintf(str_data, "%02X %02X %02X ", opcode[0],opcode[1],opcode[2]);
|
dataSb << sb_hex(opcode[0], 2) << ' ' << sb_hex(opcode[1], 2) << ' ' << sb_hex(opcode[2], 2) << " ";
|
||||||
a = Disassemble(addr + 3, opcode);
|
a = Disassemble(addr + 3, opcode);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -822,6 +825,8 @@ void FCEUD_TraceInstruction(uint8 *opcode, int size)
|
||||||
{
|
{
|
||||||
if (logging_options & LOG_SYMBOLIC)
|
if (logging_options & LOG_SYMBOLIC)
|
||||||
{
|
{
|
||||||
|
StringBuilder decSb(str_decoration);
|
||||||
|
|
||||||
loadNameFiles();
|
loadNameFiles();
|
||||||
tempAddressesLog.resize(0);
|
tempAddressesLog.resize(0);
|
||||||
// Insert Name and Comment lines if needed
|
// Insert Name and Comment lines if needed
|
||||||
|
@ -830,24 +835,22 @@ void FCEUD_TraceInstruction(uint8 *opcode, int size)
|
||||||
{
|
{
|
||||||
if (node->name)
|
if (node->name)
|
||||||
{
|
{
|
||||||
strcpy(str_decoration, node->name);
|
decSb << node->name << ':';
|
||||||
strcat(str_decoration, ":");
|
|
||||||
tempAddressesLog.push_back(addr);
|
tempAddressesLog.push_back(addr);
|
||||||
OutputLogLine(str_decoration, &tempAddressesLog);
|
OutputLogLine(str_decoration, &tempAddressesLog);
|
||||||
}
|
}
|
||||||
if (node->comment)
|
if (node->comment)
|
||||||
{
|
{
|
||||||
// make a copy
|
// make a copy
|
||||||
strcpy(str_decoration_comment, node->comment);
|
StringBuilder cmtSb(str_decoration_comment);
|
||||||
strcat(str_decoration_comment, "\r\n");
|
cmtSb << node->comment << "\r\n";
|
||||||
tracer_decoration_comment = str_decoration_comment;
|
tracer_decoration_comment = str_decoration_comment;
|
||||||
// divide the str_decoration_comment into strings (Comment1, Comment2, ...)
|
// divide the str_decoration_comment into strings (Comment1, Comment2, ...)
|
||||||
char* tracer_decoration_comment_end_pos = strstr(tracer_decoration_comment, "\r\n");
|
char* tracer_decoration_comment_end_pos = strstr(tracer_decoration_comment, "\r\n");
|
||||||
while (tracer_decoration_comment_end_pos)
|
while (tracer_decoration_comment_end_pos)
|
||||||
{
|
{
|
||||||
tracer_decoration_comment_end_pos[0] = 0; // set \0 instead of \r
|
tracer_decoration_comment_end_pos[0] = 0; // set \0 instead of \r
|
||||||
strcpy(str_decoration, "; ");
|
decSb << "; " << tracer_decoration_comment;
|
||||||
strcat(str_decoration, tracer_decoration_comment);
|
|
||||||
OutputLogLine(str_decoration, &tempAddressesLog);
|
OutputLogLine(str_decoration, &tempAddressesLog);
|
||||||
tracer_decoration_comment_end_pos += 2;
|
tracer_decoration_comment_end_pos += 2;
|
||||||
tracer_decoration_comment = tracer_decoration_comment_end_pos;
|
tracer_decoration_comment = tracer_decoration_comment_end_pos;
|
||||||
|
@ -860,8 +863,7 @@ void FCEUD_TraceInstruction(uint8 *opcode, int size)
|
||||||
for(int i=0;i<ARRAY_SIZE(pageNames);i++)
|
for(int i=0;i<ARRAY_SIZE(pageNames);i++)
|
||||||
replaceNames(pageNames[i], a, &tempAddressesLog);
|
replaceNames(pageNames[i], a, &tempAddressesLog);
|
||||||
}
|
}
|
||||||
strncpy(str_disassembly, a, LOG_DISASSEMBLY_MAX_LEN);
|
dasmSb.appendStr(a, LOG_DISASSEMBLY_MAX_LEN);
|
||||||
str_disassembly[LOG_DISASSEMBLY_MAX_LEN - 1] = 0;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -870,23 +872,19 @@ void FCEUD_TraceInstruction(uint8 *opcode, int size)
|
||||||
// special case: an RTS opcode
|
// special case: an RTS opcode
|
||||||
// add "----------" to emphasize the end of subroutine
|
// add "----------" to emphasize the end of subroutine
|
||||||
static const char* emphasize = " -------------------------------------------------------------------------------------------------------------------------";
|
static const char* emphasize = " -------------------------------------------------------------------------------------------------------------------------";
|
||||||
strncat(str_disassembly, emphasize, LOG_DISASSEMBLY_MAX_LEN - strlen(str_disassembly) - 1);
|
dasmSb.appendStr(emphasize, LOG_DISASSEMBLY_MAX_LEN);
|
||||||
}
|
}
|
||||||
// stretch the disassembly string out if we have to output other stuff.
|
// 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))
|
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)
|
for (int i = dasmSb.size(); i < (LOG_DISASSEMBLY_MAX_LEN - 1); ++i)
|
||||||
str_disassembly[i] = ' ';
|
dasmSb << ' ';
|
||||||
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
|
// 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)
|
if (logging_options & LOG_FRAMES_COUNT)
|
||||||
{
|
{
|
||||||
sprintf(str_result, "f%-6u ", currFrameCounter);
|
resSb << 'f' << sb_dec((unsigned)currFrameCounter, -6) << ' ';
|
||||||
} else
|
|
||||||
{
|
|
||||||
str_result[0] = 0;
|
|
||||||
}
|
}
|
||||||
if (logging_options & LOG_CYCLES_COUNT)
|
if (logging_options & LOG_CYCLES_COUNT)
|
||||||
{
|
{
|
||||||
|
@ -896,77 +894,74 @@ void FCEUD_TraceInstruction(uint8 *opcode, int size)
|
||||||
ResetDebugStatisticsCounters();
|
ResetDebugStatisticsCounters();
|
||||||
counter_value = 0;
|
counter_value = 0;
|
||||||
}
|
}
|
||||||
sprintf(str_temp, "c%-11llu ", counter_value);
|
resSb << 'c' << sb_dec((uint64_t)counter_value, -11) << ' ';
|
||||||
strcat(str_result, str_temp);
|
|
||||||
}
|
}
|
||||||
if (logging_options & LOG_INSTRUCTIONS_COUNT)
|
if (logging_options & LOG_INSTRUCTIONS_COUNT)
|
||||||
{
|
{
|
||||||
sprintf(str_temp, "i%-11llu ", total_instructions);
|
resSb << 'i' << sb_dec(total_instructions, -11) << ' ';
|
||||||
strcat(str_result, str_temp);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (logging_options & LOG_REGISTERS)
|
if (logging_options & LOG_REGISTERS)
|
||||||
{
|
{
|
||||||
sprintf(str_axystate,"A:%02X X:%02X Y:%02X S:%02X ",(X.A),(X.X),(X.Y),(X.S));
|
StringBuilder sb(str_axystate);
|
||||||
|
sb << "A:" << sb_hex(X.A, 2) << " X:" << sb_hex(X.X, 2) << " Y:" << sb_hex(X.Y, 2) << " S:" << sb_hex(X.S, 2) << ' ';
|
||||||
}
|
}
|
||||||
|
|
||||||
if (logging_options & LOG_PROCESSOR_STATUS)
|
if (logging_options & LOG_PROCESSOR_STATUS)
|
||||||
{
|
{
|
||||||
tmp = X.P^0xFF;
|
char *s = str_procstatus;
|
||||||
sprintf(str_procstatus,"P:%c%c%c%c%c%c%c%c ",
|
*(s++) = X.P & 0x80 ? 'N' : 'n';
|
||||||
'N'|(tmp&0x80)>>2,
|
*(s++) = X.P & 0x40 ? 'V' : 'v';
|
||||||
'V'|(tmp&0x40)>>1,
|
*(s++) = X.P & 0x20 ? 'U' : 'u';
|
||||||
'U'|(tmp&0x20),
|
*(s++) = X.P & 0x10 ? 'B' : 'b';
|
||||||
'B'|(tmp&0x10)<<1,
|
*(s++) = X.P & 0x08 ? 'D' : 'd';
|
||||||
'D'|(tmp&0x08)<<2,
|
*(s++) = X.P & 0x04 ? 'I' : 'i';
|
||||||
'I'|(tmp&0x04)<<3,
|
*(s++) = X.P & 0x02 ? 'Z' : 'z';
|
||||||
'Z'|(tmp&0x02)<<4,
|
*(s++) = X.P & 0x01 ? 'C' : 'c';
|
||||||
'C'|(tmp&0x01)<<5
|
*(s++) = ' ';
|
||||||
);
|
*(s++) = '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
if (logging_options & LOG_TO_THE_LEFT)
|
if (logging_options & LOG_TO_THE_LEFT)
|
||||||
{
|
{
|
||||||
if (logging_options & LOG_REGISTERS)
|
if (logging_options & LOG_REGISTERS)
|
||||||
strcat(str_result, str_axystate);
|
resSb << str_axystate;
|
||||||
if (logging_options & LOG_PROCESSOR_STATUS)
|
if (logging_options & LOG_PROCESSOR_STATUS)
|
||||||
strcat(str_result, str_procstatus);
|
resSb << str_procstatus;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (logging_options & LOG_CODE_TABBING)
|
if (logging_options & LOG_CODE_TABBING)
|
||||||
{
|
{
|
||||||
// add spaces at the beginning of the line according to stack pointer
|
// add spaces at the beginning of the line according to stack pointer
|
||||||
int spaces = (0xFF - X.S) & LOG_TABS_MASK;
|
int spaces = (0xFF - X.S) & LOG_TABS_MASK;
|
||||||
for (int i = 0; i < spaces; i++)
|
std::memset(str_tabs, ' ', spaces);
|
||||||
str_tabs[i] = ' ';
|
|
||||||
str_tabs[spaces] = 0;
|
str_tabs[spaces] = 0;
|
||||||
strcat(str_result, str_tabs);
|
resSb << str_tabs;
|
||||||
} else if (logging_options & LOG_TO_THE_LEFT)
|
} else if (logging_options & LOG_TO_THE_LEFT)
|
||||||
{
|
{
|
||||||
strcat(str_result, " ");
|
resSb << ' ';
|
||||||
}
|
}
|
||||||
|
|
||||||
if (logging_options & LOG_BANK_NUMBER)
|
if (logging_options & LOG_BANK_NUMBER)
|
||||||
{
|
{
|
||||||
if (addr >= 0x8000)
|
if (addr >= 0x8000)
|
||||||
sprintf(str_address, "$%02X:%04X: ", getBank(addr), addr);
|
resSb << sb_addr(getBank(addr), 2) << ':' << sb_hex(addr, 4);
|
||||||
else
|
else
|
||||||
sprintf(str_address, " $%04X: ", addr);
|
resSb << " " << sb_addr(addr);
|
||||||
} else
|
} else
|
||||||
{
|
{
|
||||||
sprintf(str_address, "$%04X: ", addr);
|
resSb << sb_addr(addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
strcat(str_result, str_address);
|
resSb << ": " << str_data;
|
||||||
strcat(str_result, str_data);
|
resSb << str_disassembly;
|
||||||
strcat(str_result, str_disassembly);
|
|
||||||
|
|
||||||
if (!(logging_options & LOG_TO_THE_LEFT))
|
if (!(logging_options & LOG_TO_THE_LEFT))
|
||||||
{
|
{
|
||||||
if (logging_options & LOG_REGISTERS)
|
if (logging_options & LOG_REGISTERS)
|
||||||
strcat(str_result, str_axystate);
|
resSb << str_axystate;
|
||||||
if (logging_options & LOG_PROCESSOR_STATUS)
|
if (logging_options & LOG_PROCESSOR_STATUS)
|
||||||
strcat(str_result, str_procstatus);
|
resSb << str_procstatus;
|
||||||
}
|
}
|
||||||
|
|
||||||
OutputLogLine(str_result, &tempAddressesLog);
|
OutputLogLine(str_result, &tempAddressesLog);
|
||||||
|
@ -978,9 +973,7 @@ void OutputLogLine(const char *str, std::vector<uint16>* addressesLog, bool add_
|
||||||
{
|
{
|
||||||
if (logtofile)
|
if (logtofile)
|
||||||
{
|
{
|
||||||
fputs(str, LOG_FP);
|
fileWriter.writeLine(str, add_newline);
|
||||||
if (add_newline)
|
|
||||||
fputs("\n", LOG_FP);
|
|
||||||
} else
|
} else
|
||||||
{
|
{
|
||||||
if (add_newline)
|
if (add_newline)
|
||||||
|
@ -1025,7 +1018,7 @@ void EndLoggingSequence()
|
||||||
{
|
{
|
||||||
if (logtofile)
|
if (logtofile)
|
||||||
{
|
{
|
||||||
fclose(LOG_FP);
|
fileWriter.close();
|
||||||
} else
|
} else
|
||||||
{
|
{
|
||||||
strcpy(str_result, "Logging finished.");
|
strcpy(str_result, "Logging finished.");
|
||||||
|
|
|
@ -59,6 +59,57 @@ public:
|
||||||
return appendInt<Radix>(intInfo.x, intInfo.minLen, intInfo.leadChar, intInfo.upperCase);
|
return appendInt<Radix>(intInfo.x, intInfo.minLen, intInfo.leadChar, intInfo.upperCase);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Append an array of characters that may or may not be null-terminated
|
||||||
|
StringBuilder &appendSubstr(const char *str, size_t maxLen)
|
||||||
|
{
|
||||||
|
size_t len = std::strlen(str),
|
||||||
|
copyLen = len <= maxLen ? len : maxLen;
|
||||||
|
|
||||||
|
std::memcpy(end, str, copyLen);
|
||||||
|
end += len;
|
||||||
|
*end = '\0';
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Substitute for strncpy/strncat
|
||||||
|
// maxLen is the TOTAL size, including what's already built
|
||||||
|
// If alwaysAppendNull the last character will always be null
|
||||||
|
StringBuilder &appendStr(const char *str, size_t maxLen, bool alwaysAddNull = true)
|
||||||
|
{
|
||||||
|
size_t len = std::strlen(str),
|
||||||
|
curLen = size(),
|
||||||
|
lenLeft = maxLen - curLen;
|
||||||
|
|
||||||
|
if (len < lenLeft)
|
||||||
|
{
|
||||||
|
std::memcpy(end, str, len + 1);
|
||||||
|
end += len;
|
||||||
|
}
|
||||||
|
else if (!alwaysAddNull)
|
||||||
|
{
|
||||||
|
// strncpy/strncat case: no terminating null
|
||||||
|
std::memcpy(end, str, lenLeft);
|
||||||
|
end += lenLeft;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// strncpy_s/strncat_s case: always null-terminate
|
||||||
|
if (lenLeft != 0)
|
||||||
|
{
|
||||||
|
size_t copyLen = lenLeft - 1;
|
||||||
|
std::memcpy(end, str, copyLen);
|
||||||
|
|
||||||
|
end += copyLen;
|
||||||
|
*end = '\0';
|
||||||
|
}
|
||||||
|
else
|
||||||
|
end[-1] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
inline StringBuilder &operator <<(nullptr_t)
|
inline StringBuilder &operator <<(nullptr_t)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue