bool MemDebuggerPrompt::DoRSearch(uint32 byte_count, uint8 *the_bytes) { const uint64 zemod = SizeCache[CurASpace]; const uint32 start_a = (ASpacePos[CurASpace] - 1) % zemod; uint32 a = start_a; bool found = FALSE; uint8 *bbuffer = (uint8 *)calloc(1, byte_count); LockGameMutex(1); do { ASpace->GetAddressSpaceBytes(ASpace->name, a, byte_count + 1, bbuffer); bool match = TRUE; for(uint32 i = 1; i <= byte_count; i++) { if(((bbuffer[i] - bbuffer[i - 1]) & 0xFF) != the_bytes[i - 1]) { match = FALSE; break; } } if(match) { found = TRUE; ASpacePos[CurASpace] = (a + 1) % zemod; break; } a = (a + 1) % zemod; } while(a != start_a); LockGameMutex(0); free(bbuffer); return(found); }
bool MemDebuggerPrompt::DoBSSearch(uint32 byte_count, uint8 *thebytes) { const uint64 zemod = SizeCache[CurASpace]; const uint32 start_a = ASpacePos[CurASpace] % zemod; uint32 a = start_a; bool found = FALSE; uint8 *bbuffer = (uint8 *)calloc(1, byte_count); LockGameMutex(1); do { ASpace->GetAddressSpaceBytes(ASpace->name, a, byte_count, bbuffer); if(!memcmp(bbuffer, thebytes, byte_count)) { ASpacePos[CurASpace] = a; found = TRUE; break; } a = (a + 1) % zemod; } while(a != start_a); LockGameMutex(0); free(bbuffer); return(found); }
// Call this function from either thread. void MemDebugger_SetActive(bool newia) { if(CurGame->Debugger) { LockGameMutex(1); IsActive = newia; if(!newia) { InEditMode = FALSE; LowNib = FALSE; } LockGameMutex(0); } }
void DebuggerFudge(void) { LockGameMutex(0); int MeowCowHowFlown = VTBackBuffer; MDFND_Update((uint32 *)VTBuffer[VTBackBuffer], NULL, 0); VTBackBuffer = MeowCowHowFlown; if(sound_active) WriteSoundSilence(10); else SDL_Delay(10); LockGameMutex(1); }
// Call this function from either thread. void GfxDebugger_SetActive(bool newia) { if(CurGame->Debugger && CurGame->Debugger->SetGraphicsDecode) { LockGameMutex(1); IsActive = newia; if(IsActive && !LayerCount) { LayerCount = 0; int clen; const char *lnp = CurGame->LayerNames; while((clen = strlen(lnp))) { LayerNames[LayerCount] = lnp; LayerCount++; lnp += clen + 1; } } if(!IsActive) { if(gd_surface) { delete gd_surface; gd_surface = NULL; } } else if(IsActive) { if(!gd_surface) gd_surface = new MDFN_Surface(NULL, 128, 128, 128 * 3, MDFN_PixelFormat(MDFN_COLORSPACE_RGB, 0, 8, 16, 24)); } RedoSGD(); LockGameMutex(0); } }
static void ParseSTDIOCommand(char *buf) { char *arguments[8]; int which_argument = 0; size_t blen = strlen(buf); bool InQuote = 0; char *InBegin = NULL; char last_char = 0; memset(arguments, 0, sizeof(arguments)); for(size_t x = 0; x <= blen; x++) { if((buf[x] == ' ' || buf[x] == 0) && last_char != '\\' && !InQuote && InBegin) { buf[x] = 0; unescape_string(InBegin); arguments[which_argument] = InBegin; which_argument++; if(which_argument == 8) { break; } InBegin = NULL; } else if(buf[x] != ' ' && buf[x] != '\t' && buf[x] != '"' && last_char != '\\' && !InQuote && !InBegin) { InBegin = &buf[x]; } else if(buf[x] == '"' && last_char != '\\') { if(InBegin) { buf[x] = 0; unescape_string(InBegin); arguments[which_argument] = InBegin; which_argument++; if(which_argument == 8) { break; } InQuote = 0; InBegin = NULL; } else { InQuote = TRUE; InBegin = &buf[x + 1]; } } last_char = buf[x]; } int numargs = which_argument; // numargs count includes the command. Misleading, yes! bool success = 0; bool suppress_success = 0; if(numargs) { if(!strcasecmp(arguments[0], "exit")) { MainRequestExit(); suppress_success = TRUE; } else if(!strcasecmp(arguments[0], "sync_video")) { success = MT_FromRemote_VideoSync(); } else if(!strcasecmp(arguments[0], "sync_sound")) { success = MT_FromRemote_SoundSync(); } else if(!strcasecmp(arguments[0], "get_setting")) { if(numargs == 2) { std::string sval; LockGameMutex(TRUE); sval = MDFN_GetSettingS(arguments[1]); success = TRUE; LockGameMutex(FALSE); Remote_SendCommand("return", 2, "success", sval.c_str()); return; } else puts("Invalid number of arguments"); } else if(!strcasecmp(arguments[0], "set_setting")) { if(numargs == 3) { LockGameMutex(TRUE); success = MDFNI_SetSetting(arguments[1], arguments[2]); LockGameMutex(FALSE); } else puts("Invalid number of arguments"); } else if(!strcasecmp(arguments[0], "get_known_fileexts")) { uint32 count = 0; char count_string[64]; // TODO: Move to core for(unsigned int i = 0; i < MDFNSystems.size(); i++) { const FileExtensionSpecStruct *FileExtensions = MDFNSystems[i]->FileExtensions; if(FileExtensions) while(FileExtensions->extension) { count++; FileExtensions++; } } trio_snprintf(count_string, 64, "%u", count); Remote_SendCommand("result_count", 1, count_string); for(unsigned int i = 0; i < MDFNSystems.size(); i++) { const FileExtensionSpecStruct *FileExtensions = MDFNSystems[i]->FileExtensions; if(FileExtensions) while(FileExtensions->extension) { Remote_SendCommand("result", 3, MDFNSystems[i]->shortname, FileExtensions->extension, FileExtensions->description); FileExtensions++; } } success = TRUE; } else { puts("Unknown command!"); } } if(!suppress_success) { if(success) { Remote_SendCommand("return", 1, "success"); } else { Remote_SendCommand("return", 1, "failure"); } } //printf("%s %s %s %s %s %s\n", arguments[0], arguments[1], arguments[2], arguments[3], arguments[4], arguments[5]); }
// Call this function from the main thread void GfxDebugger_Draw(MDFN_Surface *surface, const MDFN_Rect *rect, const MDFN_Rect *screen_rect) { if(!IsActive) return; const MDFN_PixelFormat pf_cache = surface->format; uint32 *src_pixels; uint32 * pixels = surface->pixels; uint32 pitch32 = surface->pitchinpix; bool ism; LockGameMutex(1); ism = InSteppingMode; if(ism) { RedoSGD(TRUE); } if(gd_surface->format.Rshift != surface->format.Rshift || gd_surface->format.Gshift != surface->format.Gshift || gd_surface->format.Bshift != surface->format.Bshift || gd_surface->format.Ashift != surface->format.Ashift || gd_surface->format.colorspace != surface->format.colorspace) { //puts("Convert Meow"); gd_surface->SetFormat(surface->format, TRUE); } src_pixels = gd_surface->pixels; if(!src_pixels) { LockGameMutex(0); return; } for(unsigned int y = 0; y < 128; y++) { uint32 *row = pixels + ((rect->w - 256) / 2) + y * pitch32 * 2; for(unsigned int x = 0; x < 128; x++) { //printf("%d %d %d\n", y, x, pixels); row[x*2] = row[x*2 + 1] = row[pitch32 + x*2] = row[pitch32 + x*2 + 1] = src_pixels[x + y * 128 * 3]; //row[x] = MK_COLOR_A(0, 0, 0, 0xc0); //row[x] = MK_COLOR_A(0x00, 0x00, 0x00, 0x7F); } } // Draw layer name { for(unsigned int y = 256; y < 256 + 18; y++) for(unsigned int x = 0; x < rect->w; x++) { pixels[y * pitch32 + x] = MK_COLOR_A(0x00, 0x00, 0x00, 0xC0); } char buf[256]; if(ism) trio_snprintf(buf, 256, "%s, PBN: %d, Scroll: %d, Instant", LayerNames[CurLayer], LayerPBN[CurLayer], LayerScroll[CurLayer]); else trio_snprintf(buf, 256, "%s, PBN: %d, Scroll: %d, Line: %d", LayerNames[CurLayer], LayerPBN[CurLayer], LayerScroll[CurLayer], LayerScanline[CurLayer]); DrawTextTransShadow(pixels + 256 * pitch32, surface->pitchinpix << 2, rect->w, (UTF8*)buf, MK_COLOR_A(0xF0, 0xF0, 0xF0, 0xFF), MK_COLOR_A(0, 0, 0, 0xFF), 1, FALSE); } int mousex, mousey; SDL_GetMouseState(&mousex, &mousey); int vx, vy; vx = (mousex - screen_rect->x) * rect->w / screen_rect->w - ((rect->w - 256) / 2); vy = (mousey - screen_rect->y) * rect->h / screen_rect->h; vx /= 2; vy /= 2; if(vx < 128 && vy < 128 && vx >= 0 && vy >= 0) { if(src_pixels[vx + vy * 128 * 3] & (0xFF << surface->format.Ashift)) { for(unsigned int y = 278; y < 278 + 18; y++) for(unsigned int x = 0; x < rect->w; x++) { pixels[y * pitch32 + x] = MK_COLOR_A(0x00, 0x00, 0x00, 0xC0); } char buf[256]; trio_snprintf(buf, 256, "Tile: %08x, Address: %08x", src_pixels[128 + vx + vy * 128 * 3], src_pixels[256 + vx + vy * 128 * 3]); DrawTextTransShadow(pixels + 278 * pitch32, surface->pitchinpix << 2, rect->w, (UTF8*)buf, MK_COLOR_A(0xF0, 0xF0, 0xF0, 0xFF), MK_COLOR_A(0, 0, 0, 0xFF), 1, FALSE); } } LockGameMutex(0); }
// Call this from the main thread int GfxDebugger_Event(const SDL_Event *event) { switch(event->type) { case SDL_KEYDOWN: switch(event->key.keysym.sym) { default: break; case SDLK_MINUS: LockGameMutex(1); if(LayerScanline[CurLayer]) { LayerScanline[CurLayer]--; RedoSGD(); } LockGameMutex(0); break; case SDLK_EQUALS: LockGameMutex(1); LayerScanline[CurLayer]++; RedoSGD(); LockGameMutex(0); break; case SDLK_UP: LockGameMutex(1); if(LayerScroll[CurLayer]) { LayerScroll[CurLayer]--; RedoSGD(); } LockGameMutex(0); break; case SDLK_PAGEUP: LockGameMutex(1); LayerScroll[CurLayer] -= 8; if(LayerScroll[CurLayer] < 0) LayerScroll[CurLayer] = 0; RedoSGD(); LockGameMutex(0); break; case SDLK_PAGEDOWN: LockGameMutex(1); LayerScroll[CurLayer] += 8; RedoSGD(); LockGameMutex(0); break; case SDLK_DOWN: LockGameMutex(1); LayerScroll[CurLayer]++; RedoSGD(); LockGameMutex(0); break; case SDLK_LEFT: LockGameMutex(1); CurLayer = (CurLayer - 1); if(CurLayer < 0) CurLayer = LayerCount - 1; RedoSGD(); LockGameMutex(0); break; case SDLK_RIGHT: LockGameMutex(1); CurLayer = (CurLayer + 1) % LayerCount; RedoSGD(); LockGameMutex(0); break; case SDLK_COMMA: LockGameMutex(1); if(LayerPBN[CurLayer] >= 0) LayerPBN[CurLayer]--; RedoSGD(); LockGameMutex(0); break; case SDLK_PERIOD: LockGameMutex(1); LayerPBN[CurLayer]++; RedoSGD(); LockGameMutex(0); break; } break; } return(1); }
int GameLoop(void *arg) { while(GameThreadRun) { int16 *sound; int32 ssize; int fskip; /* If we requested a new video mode, wait until it's set before calling the emulation code again. */ while(NeedVideoChange) { if(!GameThreadRun) return(1); // Might happen if video initialization failed SDL_Delay(1); } do { if(InFrameAdvance && !NeedFrameAdvance) { SDL_Delay(10); } } while(InFrameAdvance && !NeedFrameAdvance); fskip = ThrottleCheckFS(); if(pending_snapshot || pending_save_state || pending_save_movie || NeedFrameAdvance) fskip = 0; NeedFrameAdvance = 0; if(NoWaiting) fskip = 1; VTLineWidths[VTBackBuffer][0].w = ~0; int ThisBackBuffer = VTBackBuffer; LockGameMutex(1); { EmulateSpecStruct espec; memset(&espec, 0, sizeof(EmulateSpecStruct)); espec.pixels = (uint32 *)VTBuffer[VTBackBuffer]; espec.LineWidths = (MDFN_Rect *)VTLineWidths[VTBackBuffer]; espec.SoundBuf = &sound; espec.SoundBufSize = &ssize; espec.skip = fskip; espec.soundmultiplier = CurGameSpeed; espec.NeedRewind = DNeedRewind; MDFNI_Emulate(&espec); //(uint32 *)VTBuffer[VTBackBuffer], (MDFN_Rect *)VTLineWidths[VTBackBuffer], &sound, &ssize, fskip, CurGameSpeed); } LockGameMutex(0); FPS_IncVirtual(); if(!fskip) FPS_IncDrawn(); do { GameThread_HandleEvents(); VTBackBuffer = ThisBackBuffer; MDFND_Update(fskip ? NULL : (uint32 *)VTBuffer[ThisBackBuffer], sound, ssize); if((InFrameAdvance && !NeedFrameAdvance) || GameLoopPaused) { if(!ssize) ThrottleCheckFS(); else for(int x = 0; x < CurGame->soundchan * ssize; x++) sound[x] = 0; } } while(((InFrameAdvance && !NeedFrameAdvance) || GameLoopPaused) && GameThreadRun); } return(1); }
// Call this from the main thread int MemDebugger_Event(const SDL_Event *event) { if(!InPrompt && myprompt) { delete myprompt; myprompt = NULL; } unsigned int keysym = event->key.keysym.sym; switch(event->type) { case SDL_KEYDOWN: if(event->key.keysym.mod & KMOD_ALT) break; if(InPrompt) { myprompt->Event(event); } else if(InEditMode && InTextArea && keysym != SDLK_TAB && keysym != SDLK_INSERT && keysym != SDLK_UP && keysym != SDLK_DOWN && keysym != SDLK_LEFT && keysym != SDLK_RIGHT && (event->key.keysym.unicode >= 0x20)) { uint8 to_write[16]; int to_write_len; size_t ibl, obl, obl_start; char *inbuf, *outbuf; ibl = 2; obl_start = obl = 16; inbuf = (char *)&event->key.keysym.unicode; outbuf = (char*)to_write; size_t result = iconv(ict_utf16_to_game, (ICONV_CONST char **)&inbuf, &ibl, &outbuf, &obl); if(result != (size_t)-1) { to_write_len = 16 - obl; LockGameMutex(1); ASpace->PutAddressSpaceBytes(ASpace->name, ASpacePos[CurASpace], to_write_len, 1, TRUE, to_write); LockGameMutex(0); LowNib = 0; ChangePos(to_write_len); } } else if(InEditMode && ((event->key.keysym.sym >= SDLK_0 && event->key.keysym.sym <= SDLK_9) || (event->key.keysym.sym >= SDLK_a && event->key.keysym.sym <= SDLK_f))) { uint8 tc = 0; uint8 meowbyte = 0; if(event->key.keysym.sym >= SDLK_0 && event->key.keysym.sym <= SDLK_9) tc = 0x0 + event->key.keysym.sym - SDLK_0; else if(event->key.keysym.sym >= SDLK_a && event->key.keysym.sym <= SDLK_f) tc = 0xA + event->key.keysym.sym - SDLK_a; LockGameMutex(1); ASpace->GetAddressSpaceBytes(ASpace->name, ASpacePos[CurASpace], 1, &meowbyte); meowbyte &= 0xF << ((LowNib) * 4); meowbyte |= tc << ((!LowNib) * 4); ASpace->PutAddressSpaceBytes(ASpace->name, ASpacePos[CurASpace], 1, 1, TRUE, &meowbyte); LockGameMutex(0); LowNib = !LowNib; if(!LowNib) ChangePos(1); } else switch(event->key.keysym.sym) { default: break; case SDLK_MINUS: Debugger_ModOpacity(-8); break; case SDLK_EQUALS: Debugger_ModOpacity(8); break; case SDLK_TAB: InTextArea = !InTextArea; LowNib = FALSE; break; case SDLK_d: InPrompt = DumpMem; myprompt = new MemDebuggerPrompt("Dump Memory(start end filename)", ""); break; case SDLK_l: InPrompt = LoadMem; myprompt = new MemDebuggerPrompt("Load Memory(start end filename)", ""); break; case SDLK_s: if(SizeCache[CurASpace] > (1 << 24)) { error_string = trio_aprintf("Address space is too large to search!"); error_time = SDL_GetTicks(); } else { InPrompt = ByteStringSearch; myprompt = new MemDebuggerPrompt("Byte String Search", BSS_String); } break; case SDLK_r: if(SizeCache[CurASpace] > (1 << 24)) { error_string = trio_aprintf("Address space is too large to search!"); error_time = SDL_GetTicks(); } else { InPrompt = RelSearch; myprompt = new MemDebuggerPrompt("Byte String Relative/Delta Search", RS_String); } break; case SDLK_c: InPrompt = SetCharset; myprompt = new MemDebuggerPrompt("Charset", GameCode); break; case SDLK_t: if(ASpace->TotalBits > 24) { error_string = trio_aprintf("Address space is too large to search!"); error_time = SDL_GetTicks(); } else { InPrompt = TextSearch; myprompt = new MemDebuggerPrompt("Text Search", TS_String); } break; case SDLK_g: if(event->key.keysym.mod & KMOD_SHIFT) { InPrompt = GotoDD; myprompt = new MemDebuggerPrompt("Goto Address(DD)", ""); } else { InPrompt = Goto; myprompt = new MemDebuggerPrompt("Goto Address", ""); } break; case SDLK_INSERT: InEditMode = !InEditMode; LowNib = FALSE; break; case SDLK_END: ASpacePos[CurASpace] = (SizeCache[CurASpace] - 128) % SizeCache[CurASpace]; LowNib = FALSE; break; case SDLK_HOME: ASpacePos[CurASpace] = 0; LowNib = FALSE; break; case SDLK_PAGEUP: ChangePos(-16 * 16); break; case SDLK_PAGEDOWN: ChangePos(16 * 16); break; case SDLK_UP: ChangePos(-16); break; case SDLK_DOWN: ChangePos(16); break; case SDLK_LEFT: ChangePos(-1); break; case SDLK_RIGHT: ChangePos(1); break; case SDLK_COMMA: if(CurASpace) CurASpace--; else CurASpace = AddressSpaces->size() - 1; ASpace = &(*AddressSpaces)[CurASpace]; LowNib = FALSE; break; case SDLK_PERIOD: CurASpace = (CurASpace + 1) % AddressSpaces->size(); ASpace = &(*AddressSpaces)[CurASpace]; LowNib = FALSE; break; case SDLK_b: //InMarkMode = !InMarkMode; //if(InMarkMode) // MarkModeBegin = ASpacePos[CurASpace]; DoCrazy(); break; case SDLK_e: if(InMarkMode) { FILE *fp = fopen("markers.txt", "ab"); fprintf(fp, "%08x %08x\n", MarkModeBegin, ASpacePos[CurASpace]); fclose(fp); InMarkMode = FALSE; } break; } break; } return(1); }
static void DoCrazy(void) { LockGameMutex(1); uint32 start = ASpacePos[CurASpace]; uint32 A = ASpacePos[CurASpace]; for(;;) { uint8 zebyte; ASpace->GetAddressSpaceBytes(ASpace->name, A, 1, &zebyte); // Simple control codes if(zebyte < 0x20) { switch(zebyte) { default: printf("UNKNOWN GAHGAHGAH: %02x\n", zebyte); return; case 0x00: goto GetOut; // Crazy escape case 0x05: goto GetOut; // Pause+close text box // Print numbers, 3 arguments case 0x06: case 0x07: case 0x08: A += 3; break; // Transfer control, 4 arguments case 0x12: A += 4; break; case 0x0C: break; // Clear text box case 0x0D: break; // New line case 0x0F: goto GetOut; // Pause+close text box case 0x10: break; // Prompt for button to continue case 0x11: goto GetOut; // Binary selection magic case 0x14: A += 1; break; // Set draw speed, 1 argument case 0x17: A += 1; break; // Delay, 1 argument } } else if(zebyte <= 0x7F) // ASCII { } else if(zebyte < 0xEB) // 2-byte SJIS { A += 1; } else { printf("UNKNOWN GAHGAHGAH: %02x\n", zebyte); return; } A++; } GetOut: ASpacePos[CurASpace] = A; printf("%08x\n", A); FILE *fp = fopen("markers.txt", "ab"); fprintf(fp, "%08x %08x\n", start, ASpacePos[CurASpace]); fclose(fp); LockGameMutex(0); }
// Call this function from the main thread void MemDebugger_Draw(MDFN_Surface *surface, const MDFN_Rect *rect, const MDFN_Rect *screen_rect) { if(!IsActive) return; const MDFN_PixelFormat pf_cache = surface->format; uint32 *pixels = surface->pixels; uint32 pitch32 = surface->pitchinpix; const uint64 zemod = SizeCache[CurASpace]; LockGameMutex(1); DrawTextTrans(pixels, surface->pitchinpix << 2, rect->w, (UTF8*)ASpace->long_name, MK_COLOR_A(0x20, 0xFF, 0x20, 0xFF), 1, 1); pixels += 10 * pitch32; uint32 A; uint32 Ameow; // A meow for a cat if(ASpacePos[CurASpace] < 128) A = (SizeCache[CurASpace] - 128 + ASpacePos[CurASpace]) % SizeCache[CurASpace]; else A = ASpacePos[CurASpace] - 128; Ameow = A &~ 0xF; int numrows = zemod / 16; if(numrows > 16) numrows = 16; else if(numrows < 4) numrows = 4; for(int y = 0; y < numrows; y++) { uint8 byte_buffer[16]; char abuf[32]; Ameow %= zemod; ASpace->GetAddressSpaceBytes(ASpace->name, Ameow, 16, byte_buffer); if(zemod <= (1 << 16)) trio_snprintf(abuf, 32, "%04X:", Ameow); else if(zemod <= (1 << 24)) trio_snprintf(abuf, 32, "%06X:", Ameow); else trio_snprintf(abuf, 32, "%08X:", Ameow); uint32 alen; uint32 addr_color = MK_COLOR_A(0xA0, 0xA0, 0xFF, 0xFF); if(Ameow == (ASpacePos[CurASpace] & ~0xF)) addr_color = MK_COLOR_A(0x80, 0xB0, 0xFF, 0xFF); alen = DrawTextTrans(pixels, surface->pitchinpix << 2, rect->w, (UTF8*)abuf, addr_color, 0, 1); alen += 3; for(int x = 0; x < 16; x++) { uint32 bcolor = MK_COLOR_A(0xFF, 0xFF, 0xFF, 0xFF); uint32 acolor = MK_COLOR_A(0xA0, 0xA0, 0xA0, 0xFF); char quickbuf[16]; uint32 test_match_pos; uint8 ascii_str[2]; ascii_str[1] = 0; ascii_str[0] = byte_buffer[x]; if(ascii_str[0] < 0x20 || ascii_str[0] >= 128) ascii_str[0] = '.'; trio_snprintf(quickbuf, 16, "%02X", byte_buffer[x]); test_match_pos = ASpacePos[CurASpace] % zemod; if(InMarkMode) { if(MarkModeBegin < test_match_pos && Ameow < test_match_pos && Ameow >= MarkModeBegin) { if(InTextArea) { acolor = MK_COLOR_A(0xFF, 0x00, 0x00, 0xFF); bcolor = MK_COLOR_A(0xFF, 0x80, 0x80, 0xFF); } else { acolor = MK_COLOR_A(0xFF, 0x80, 0x80, 0xFF); bcolor = MK_COLOR_A(0xFF, 0x00, 0x00, 0xFF); } } } if(Ameow == test_match_pos) { if(InEditMode) if(SDL_GetTicks() & 0x80) { int pix_offset = alen; if(InTextArea) pix_offset += 16 * 12 + x * 5; else pix_offset += (LowNib ? 5 : 0) + x * 12; DrawTextTrans(pixels + pix_offset, surface->pitchinpix << 2, rect->w, (UTF8*)"▉", MK_COLOR_A(0xFF, 0xFF, 0xFF, 0xFF), 0, 1); } if(InTextArea) { acolor = MK_COLOR_A(0xFF, 0x00, 0x00, 0xFF); bcolor = MK_COLOR_A(0xFF, 0x80, 0x80, 0xFF); } else { acolor = MK_COLOR_A(0xFF, 0x80, 0x80, 0xFF); bcolor = MK_COLOR_A(0xFF, 0x00, 0x00, 0xFF); } } // hex display DrawTextTrans(pixels + alen + x * 12, surface->pitchinpix << 2, rect->w, (UTF8*)quickbuf, bcolor, 0, 1); // ASCII display DrawTextTrans(pixels + alen + 16 * 12 + x * 5, surface->pitchinpix << 2, rect->w, (UTF8 *)ascii_str, acolor, 0, 1); Ameow++; } pixels += 9 * pitch32; } { char cpstr[32]; uint32 curpos = ASpacePos[CurASpace]; uint8 zebytes[4]; uint32 tmpval; curpos %= zemod; ASpace->GetAddressSpaceBytes(ASpace->name, curpos, 4, zebytes); pixels += 8 + 5 * pitch32; if(zemod <= (1 << 16)) trio_snprintf(cpstr, 32, "%04X", curpos); else if(zemod <= (1 << 24)) trio_snprintf(cpstr, 32, "%06X", curpos); else trio_snprintf(cpstr, 32, "%08X", curpos); uint32 cpplen; uint32 cplen; cpplen = DrawTextTrans(pixels, surface->pitchinpix << 2, rect->w, (UTF8*)"Cursor position: ", MK_COLOR_A(0xa0, 0xa0, 0xFF, 0xFF), 0, 1); cplen = DrawTextTrans(pixels + cpplen, surface->pitchinpix << 2, rect->w, (UTF8*)cpstr , MK_COLOR_A(0xFF, 0xFF, 0xFF, 0xFF), 0, 1); if(GoGoPowerDD[CurASpace]) { char ggddstr[32]; if(zemod <= (1 << 16)) trio_snprintf(ggddstr, 32, "%04X", curpos - GoGoPowerDD[CurASpace]); else if(zemod <= (1 << 24)) trio_snprintf(ggddstr, 32, "%06X", curpos - GoGoPowerDD[CurASpace]); else trio_snprintf(ggddstr, 32, "%08X", curpos - GoGoPowerDD[CurASpace]); DrawTextTrans(pixels + cpplen + cplen + 8, surface->pitchinpix << 2, rect->w, (UTF8*)ggddstr, MK_COLOR_A(0xFF, 0x80, 0x80, 0xFF), 0, 1); } pixels += 5 + 10 * pitch32; tmpval = zebytes[0]; trio_snprintf(cpstr, 32, "%02x(%u, %d)", tmpval, (uint8)tmpval, (int8)tmpval); cpplen = DrawTextTrans(pixels, surface->pitchinpix << 2, rect->w, (UTF8*)"1-byte value: ", MK_COLOR_A(0xA0, 0xA0, 0xFF, 0xFF), 0, 1); DrawTextTrans(pixels + cpplen, surface->pitchinpix << 2, rect->w, (UTF8*)cpstr , MK_COLOR_A(0xFF, 0xFF, 0xFF, 0xFF), 0, 1); pixels += 10 * pitch32; if(ASpace->IsWave && SizeCache[CurASpace] <= 128 && ASpace->WaveBits <= 6) { const int32 wf_size = SizeCache[CurASpace]; uint8 waveform[wf_size]; const int32 pcm_max = (1 << ASpace->WaveBits) - 1; DrawTextTrans(pixels - 5, surface->pitchinpix << 2, rect->w, (UTF8 *)"Full waveform:", MK_COLOR_A(0xA0, 0xA0, 0xFF, 0xFF), 0, 1); pixels += 9 * pitch32; MDFN_DrawRectangleFill(pixels, surface->pitchinpix, 0, 0, MK_COLOR_A(0xA0,0xA0,0xA0,0xFF), MK_COLOR_A(0,0,0,0xFF), 2 + wf_size * 2 + 2, 2 + (pcm_max + 1) + 2); ASpace->GetAddressSpaceBytes(ASpace->name, 0, wf_size, waveform); for(int i = 0; i < wf_size; i++) { int32 delta; int32 current; int32 previous; current = waveform[i]; previous = waveform[(i + wf_size - 1) % wf_size]; delta = current - previous; for(int y = previous; y != current; y += delta / abs(delta)) pixels[2 + i * 2 + 0 + (2 + (pcm_max - y)) * surface->pitchinpix] = MK_COLOR_A(0x00,0xA0,0x00,0xFF); pixels[2 + i * 2 + 0 + (2 + (pcm_max - current)) * surface->pitchinpix] = MK_COLOR_A(0x00,0xA0,0x00,0xFF); pixels[2 + i * 2 + 1 + (2 + (pcm_max - current)) * surface->pitchinpix] = MK_COLOR_A(0x00,0xA0,0x00,0xFF); } } else { tmpval = zebytes[0] | (zebytes[1] << 8); trio_snprintf(cpstr, 32, "%04x(%u, %d)", tmpval, (uint16)tmpval, (int16)tmpval); cpplen = DrawTextTrans(pixels, surface->pitchinpix << 2, rect->w, (UTF8*)"2-byte value(LSB): ", MK_COLOR_A(0xA0, 0xA0, 0xFF, 0xFF), 0, 1); DrawTextTrans(pixels + cpplen, surface->pitchinpix << 2, rect->w, (UTF8*)cpstr , MK_COLOR_A(0xFF, 0xFF, 0xFF, 0xFF), 0, 1); pixels += 10 * pitch32; tmpval = zebytes[0] | (zebytes[1] << 8) | (zebytes[2] << 16) | (zebytes[3] << 24); trio_snprintf(cpstr, 32, "%08x(%u, %d)", tmpval, (uint32)tmpval, (int32)tmpval); cpplen = DrawTextTrans(pixels, surface->pitchinpix << 2, rect->w, (UTF8*)"4-byte value(LSB): ", MK_COLOR_A(0xA0, 0xA0, 0xFF, 0xFF), 0, 1); DrawTextTrans(pixels + cpplen, surface->pitchinpix << 2, rect->w, (UTF8*)cpstr , MK_COLOR_A(0xFF, 0xFF, 0xFF, 0xFF), 0, 1); pixels += 10 * pitch32; tmpval = zebytes[1] | (zebytes[0] << 8); trio_snprintf(cpstr, 32, "%04x(%u, %d)", tmpval, (uint16)tmpval, (int16)tmpval); cpplen = DrawTextTrans(pixels, surface->pitchinpix << 2, rect->w, (UTF8*)"2-byte value(MSB): ", MK_COLOR_A(0xA0, 0xA0, 0xFF, 0xFF), 0, 1); DrawTextTrans(pixels + cpplen, surface->pitchinpix << 2, rect->w, (UTF8*)cpstr , MK_COLOR_A(0xFF, 0xFF, 0xFF, 0xFF), 0, 1); pixels += 10 * pitch32; tmpval = zebytes[3] | (zebytes[2] << 8) | (zebytes[1] << 16) | (zebytes[0] << 24); trio_snprintf(cpstr, 32, "%08x(%u, %d)", tmpval, (uint32)tmpval, (int32)tmpval); cpplen = DrawTextTrans(pixels, surface->pitchinpix << 2, rect->w, (UTF8*)"4-byte value(MSB): ", MK_COLOR_A(0xA0, 0xA0, 0xFF, 0xFF), 0, 1); DrawTextTrans(pixels + cpplen, surface->pitchinpix << 2, rect->w, (UTF8*)cpstr , MK_COLOR_A(0xFF, 0xFF, 0xFF, 0xFF), 0, 1); trio_snprintf(cpstr, 32, "%s text: ", GameCode); cpplen = DrawTextTrans(pixels + 10 * pitch32, surface->pitchinpix << 2, rect->w, (UTF8*)cpstr, MK_COLOR_A(0xA0, 0xA0, 0xFF, 0xFF), 0, MDFN_FONT_5x7); { char rawbuf[64]; char textbuf[256]; ASpace->GetAddressSpaceBytes(ASpace->name, curpos, 64, (uint8*)rawbuf); size_t ibl, obl, obl_start; char *inbuf, *outbuf; ibl = 64; obl_start = obl = 255; // Hehe, ugly maximum estimation! inbuf = rawbuf; outbuf = textbuf; iconv(ict_to_utf8, (ICONV_CONST char **)&inbuf, &ibl, &outbuf, &obl); textbuf[obl_start - obl] = 0; DrawTextTrans(pixels + 8 * pitch32 + cpplen, surface->pitchinpix << 2, rect->w - cpplen - 13, (UTF8*)textbuf, MK_COLOR_A(0xFF, 0xFF, 0xFF, 0xFF), 0, MDFN_FONT_9x18_18x18); } } } LockGameMutex(0); if(InPrompt) myprompt->Draw(surface, rect); else if(myprompt) { delete myprompt; myprompt = NULL; } if(error_string) { if(SDL_GetTicks() >= (error_time + 4000)) { free(error_string); error_string = NULL; } else { DrawTextTrans((uint32*)surface->pixels + (rect->h - 7) * pitch32, surface->pitchinpix << 2, rect->w, (UTF8*)error_string, MK_COLOR_A(0xFF, 0x00, 0x00, 0xFF), 1, 1); } } }
void MemDebuggerPrompt::TheEnd(const std::string &pstring) { if(error_string) { free(error_string); error_string = NULL; } if(InPrompt == Goto || InPrompt == GotoDD) { unsigned long NewAddie; if(trio_sscanf(pstring.c_str(), "%08lx", &NewAddie) == 1) { ASpacePos[CurASpace] = NewAddie; LowNib = FALSE; if(InPrompt == GotoDD) GoGoPowerDD[CurASpace] = NewAddie; } } else if(InPrompt == SetCharset) { if(ICV_Init(pstring.c_str())) { LockGameMutex(1); MDFNI_SetSetting(std::string(std::string(CurGame->shortname) + "." + std::string("debugger.memcharenc")).c_str(), pstring.c_str()); LockGameMutex(0); } } else if(InPrompt == DumpMem) { uint32 A1, A2, tmpsize; char fname[256]; bool acceptable = FALSE; if(trio_sscanf(pstring.c_str(), "%08x %08x %255[^\r\n]", &A1, &A2, fname) == 3) acceptable = TRUE; else if(trio_sscanf(pstring.c_str(), "%08x +%08x %255[^\r\n]", &A1, &tmpsize, fname) == 3) { acceptable = TRUE; A2 = A1 + tmpsize - 1; } if(acceptable) { FILE *fp = fopen(fname, "wb"); if(fp) { uint8 write_buffer[256]; uint64 a = A1; //printf("%08x %08x\n", A1, A2); LockGameMutex(1); while(a <= A2) { size_t to_write; to_write = A2 - a + 1; if(to_write > 256) to_write = 256; ASpace->GetAddressSpaceBytes(ASpace->name, a, to_write, write_buffer); if(fwrite(write_buffer, 1, to_write, fp) != to_write) { error_string = trio_aprintf("File write error: %m", errno); error_time = SDL_GetTicks(); break; } a += to_write; } LockGameMutex(0); fclose(fp); } else { error_string = trio_aprintf("File open error: %m", errno); error_time = SDL_GetTicks(); } } } else if(InPrompt == LoadMem) { uint32 A1, A2, tmpsize; char fname[256]; bool acceptable = FALSE; if(trio_sscanf(pstring.c_str(), "%08x %08x %255[^\r\n]", &A1, &A2, fname) == 3) acceptable = TRUE; else if(trio_sscanf(pstring.c_str(), "%08x +%08x %255[^\r\n]", &A1, &tmpsize, fname) == 3) { acceptable = TRUE; A2 = A1 + tmpsize - 1; } if(acceptable) { FILE *fp = fopen(fname, "rb"); if(fp) { LockGameMutex(1); uint8 read_buffer[256]; uint64 a = A1; while(a <= A2) { size_t to_read; size_t read_len; to_read = A2 - a + 1; if(to_read > 256) to_read = 256; read_len = fread(read_buffer, 1, to_read, fp); if(read_len > 0) ASpace->PutAddressSpaceBytes(ASpace->name, a, read_len, 1, TRUE, read_buffer); a += read_len; if(read_len != to_read) { if(ferror(fp)) { error_string = trio_aprintf("File read error: %m", errno); error_time = SDL_GetTicks(); } else if(feof(fp)) { error_string = trio_aprintf("Warning: unexpected EOF(short by %08x byte(s))", A2 - a + 1); error_time = SDL_GetTicks(); } break; } } LockGameMutex(0); fclose(fp); } else { error_string = trio_aprintf("File open error: %m", errno); error_time = SDL_GetTicks(); } } } else if(InPrompt == TextSearch) { uint8 *thebytes; uint32 bcount; TS_String = pstring; char *inbuf, *outbuf; char *utf8_string; size_t ibl, obl, obl_start; size_t result; utf8_string = strdup(pstring.c_str()); ibl = strlen(utf8_string); obl_start = obl = (ibl + 1) * 8; // Hehe, ugly maximum estimation! thebytes = (uint8 *)calloc(1, obl_start); inbuf = utf8_string; outbuf = (char*)thebytes; result = iconv(ict, (ICONV_CONST char **)&inbuf, &ibl, &outbuf, &obl); if(result == (size_t)-1) { error_string = trio_aprintf("iconv() error: %m", errno); error_time = SDL_GetTicks(); InPrompt = None; free(utf8_string); free(thebytes); return; } bcount = obl_start - obl; free(utf8_string); if(!DoBSSearch(bcount, thebytes)) { error_string = trio_aprintf("String not found."); error_time = SDL_GetTicks(); InPrompt = None; } free(thebytes); } else if(InPrompt == ByteStringSearch) { size_t byte_count; uint8 *the_bytes; BSS_String = pstring; if(!(the_bytes = TextToBS(pstring.c_str(), &byte_count))) return; if(!DoBSSearch(byte_count, the_bytes)) { free(the_bytes); error_string = trio_aprintf("Bytestring \"%s\" not found.", pstring.c_str()); error_time = SDL_GetTicks(); InPrompt = None; return; } free(the_bytes); } else if(InPrompt == RelSearch) { size_t byte_count; uint8 *the_bytes; RS_String = pstring; if(!(the_bytes = TextToBS(pstring.c_str(), &byte_count))) return; if(!DoRSearch(byte_count, the_bytes)) { free(the_bytes); error_string = trio_aprintf("Bytestring \"%s\" not found.", pstring.c_str()); error_time = SDL_GetTicks(); InPrompt = None; return; } free(the_bytes); } InPrompt = None; }