#ifdef SUPERMODEL_DEBUGGER #include "Supermodel.h" #include "ConsoleDebugger.h" #include "CPUDebug.h" #include "Label.h" #include #include namespace Debugger { CSupermodelDebugger::CSupermodelDebugger(::CModel3 *model3, ::CInputs *inputs, ::CLogger *logger) : CConsoleDebugger(), m_model3(model3), m_inputs(inputs), m_logger(logger) { AddCPU(new CPPCDebug()); #ifdef SUPERMODEL_SOUND AddCPU(new C68KDebug()); #endif } void CSupermodelDebugger::WaitCommand(CCPUDebug *cpu) { m_inputs->GetInputSystem()->UngrabMouse(); CConsoleDebugger::WaitCommand(cpu); m_inputs->GetInputSystem()->GrabMouse(); } bool CSupermodelDebugger::ProcessToken(const char *token, const char *cmd) { // TODO - load/saving emu state not supported //if (CheckToken(token, "les", "loademustate")) // loademustate FILENAME //{ // // Parse arguments // token = strtok(NULL, " "); // if (token == NULL) // { // puts("Missing filename."); // return false; // } // if (LoadModel3State(token)) // printf("Emulator state successfully loaded from <%s>\n", token); // else // printf("Unable to load emulator state from <%s>\n", token); // return false; //} //else if (CheckToken(token, "ses", "savestate")) // saveemustate FILENAME //{ // // Parse arguments // token = strtok(NULL, " "); // if (token == NULL) // { // puts("Missing filename."); // return false; // } // if (SaveModel3State(token)) // printf("Emulator state successfully saved to <%s>\n", token); // else // printf("Unable to save emulator state to <%s>\n", token); // return false; //} if (CheckToken(token, "lip", "listinputs")) // listinputs { ListInputs(); return false; } else if (CheckToken(token, "pip", "printinput")) // printinput NAME { // Parse arguments token = strtok(NULL, " "); if (token == NULL) { puts("Mising input name."); return false; } ::CInput *input = (*m_inputs)[token]; if (input == NULL) { printf("No input with id or label '%s'.\n", token); return false; } if (!InputIsValid(input)) { printf("Input '%s' is not valid for current game.\n", token); return false; } if (!input->IsVirtual()) { char mapTrunc[41]; Truncate(mapTrunc, 40, input->GetMapping()); printf("Input %s (%s) [%s] = %04X (%d)\n", input->id, input->label, mapTrunc, input->value, input->value); } else printf("Input %s (%s) = %04X (%d)\n", input->id, input->label, input->value, input->value); return false; } else if (CheckToken(token, "sip", "setinput")) // setinput NAME MAPPING { // Parse arguments token = strtok(NULL, " "); if (token == NULL) { puts("Mising input name."); return false; } ::CInput *input = (*m_inputs)[token]; if (input == NULL) { printf("No input with id or label '%s'.\n", token); return false; } if (!InputIsValid(input)) { printf("Input '%s' is not valid for current game.\n", token); return false; } token = strtok(NULL, " "); if (token == NULL) { puts("Missing mapping to set."); return false; } input->SetMapping(token); printf("Set input %s (%s) to [%s]\n", input->id, input->label, input->GetMapping()); return false; } else if (CheckToken(token, "cip", "configinput")) // configinput NAME { //// Parse arguments // TODO //token = strtok(NULL, " "); //if (token == NULL) //{ // puts("Missing mode (a)ll, (s)et single, (a)ppend single or (r)eset single"); // return false; //} //if (CheckToken("a", "all")) //{ // //m_inputs->ConfigureInputs(); //} return false; } else return CConsoleDebugger::ProcessToken(token, cmd); } bool CSupermodelDebugger::InputIsValid(::CInput *input) { return input->IsUIInput() || (input->gameFlags & m_model3->GetGameInfo()->inputFlags); } void CSupermodelDebugger::ListInputs() { puts("Inputs:"); if (m_inputs->Count() == 0) puts(" None"); // Get maximum id, label and mapping widths size_t idAndLabelWidth = 0; size_t mappingWidth = 0; for (unsigned i = 0; i < m_inputs->Count(); i++) { ::CInput *input = (*m_inputs)[i]; if (!InputIsValid(input)) continue; idAndLabelWidth = max(idAndLabelWidth, strlen(input->id) + strlen(input->label) + 3); if (!input->IsVirtual()) mappingWidth = max(mappingWidth, strlen(input->GetMapping())); } mappingWidth = min(mappingWidth, 20); // Print labels, mappings and values for each input const char *groupLabel = NULL; char idAndLabel[255]; char mapping[21]; for (unsigned i = 0; i < m_inputs->Count(); i++) { ::CInput *input = (*m_inputs)[i]; if (!InputIsValid(input)) continue; if (groupLabel == NULL || stricmp(groupLabel, input->GetInputGroup()) != 0) { groupLabel = input->GetInputGroup(); printf(" %s:\n", groupLabel); } sprintf(idAndLabel, "%s (%s)", input->id, input->label); printf(" %-*s", (int)idAndLabelWidth, idAndLabel); if (!input->IsVirtual()) Truncate(mapping, 20, input->GetMapping()); else mapping[0] = '\0'; printf(" %-*s %04X (%d)\n", (int)mappingWidth, mapping, input->value, input->value); } } void CSupermodelDebugger::Attached() { CConsoleDebugger::Attached(); char fileName[25]; sprintf(fileName, "Debug/%s.ds", m_model3->GetGameInfo()->id); LoadState(fileName); } void CSupermodelDebugger::Detaching() { char fileName[25]; sprintf(fileName, "Debug/%s.ds", m_model3->GetGameInfo()->id); SaveState(fileName); CConsoleDebugger::Detaching(); } bool CSupermodelDebugger::LoadModel3State(const char *fileName) { // Open file and find header CBlockFile state; if (state.Load(fileName) != OKAY) return false; if (state.FindBlock("Debugger Model3 State") != OKAY) { state.Close(); return false; } // Check version in header matches unsigned version; state.Read(&version, sizeof(version)); if (version != MODEL3_STATEFILE_VERSION) { state.Close(); return false; } // Load Model3 state m_model3->LoadState(&state); state.Close(); // Reset debugger Reset(); return true; } bool CSupermodelDebugger::SaveModel3State(const char *fileName) { // Create file with header CBlockFile state; if (state.Create(fileName, "Debugger Model3 State", __FILE__) != OKAY) return false; // Write out version in header unsigned version = MODEL3_STATEFILE_VERSION; state.Write(&version, sizeof(version)); // Save Model3 state m_model3->SaveState(&state); state.Close(); return true; } void CSupermodelDebugger::DebugLog(const char *fmt, va_list vl) { // Use the supplied logger, if any if (m_logger != NULL) m_logger->DebugLog(fmt, vl); else CConsoleDebugger::DebugLog(fmt, vl); } void CSupermodelDebugger::InfoLog(const char *fmt, va_list vl) { // Use the supplied logger, if any if (m_logger != NULL) m_logger->InfoLog(fmt, vl); else CConsoleDebugger::InfoLog(fmt, vl); } void CSupermodelDebugger::ErrorLog(const char *fmt, va_list vl) { // Use the supplied logger, if any if (m_logger != NULL) m_logger->ErrorLog(fmt, vl); else CConsoleDebugger::ErrorLog(fmt, vl); } } #endif // SUPERMODEL_DEBUGGER