void cpu_instr_callback() { static char buff[100]; static unsigned int pc; if (verbose) { pc = m68k_get_reg(NULL, M68K_REG_PC); m68k_disassemble(buff, pc, M68K_CPU_TYPE_68000); printf("E %03x: %s\n", pc, buff); #if 0 /* Dump all regs */ printf(" D0 D1 D2 D3 D4 D5 D6 D7\n"); printf(" %08x %08x %08x %08x %08x %08x %08x %08x\n" , m68k_get_reg(0, M68K_REG_D0) , m68k_get_reg(0, M68K_REG_D1) , m68k_get_reg(0, M68K_REG_D2) , m68k_get_reg(0, M68K_REG_D3) , m68k_get_reg(0, M68K_REG_D4) , m68k_get_reg(0, M68K_REG_D5) , m68k_get_reg(0, M68K_REG_D6) , m68k_get_reg(0, M68K_REG_D7)); printf(" A0 A1 A2 A3 A4 A5 A6 A7\n"); printf(" %08x %08x %08x %08x %08x %08x %08x %08x\n" , m68k_get_reg(0, M68K_REG_A0) , m68k_get_reg(0, M68K_REG_A1) , m68k_get_reg(0, M68K_REG_A2) , m68k_get_reg(0, M68K_REG_A3) , m68k_get_reg(0, M68K_REG_A4) , m68k_get_reg(0, M68K_REG_A5) , m68k_get_reg(0, M68K_REG_A6) , m68k_get_reg(0, M68K_REG_A7)); #endif fflush(stdout); } }
static int CreateDisassFile(TCHAR* filename, unsigned int start, unsigned int end, int nCPU) { unsigned int size; unsigned int pc = start; FILE* fp = _tfopen(filename, _T("wt")); if (fp == NULL) { return 1; } // Print the disassembly while (pc <= end) { char buf[100] = ""; unsigned int j; if (pc > 0x00FFFFFE) { break; } // Get the mnemonic size = m68k_disassemble(buf, pc, nCPU); // Print the address _ftprintf(fp, _T("%06x "), pc); // Print the word values if (nCPU == M68K_CPU_TYPE_68000) { for (j = 10; j > size; j -= 2) { _ftprintf(fp, _T(" ")); } for (j = 0; j < size; j += 2) { _ftprintf(fp, _T("%04x "), SekFetchWord(pc + j)); } } else { if (size > 20) { for (j = 0; j < 18; j += 2) { _ftprintf(fp, _T("%04x "), SekFetchWord(pc + j)); } _ftprintf(fp, _T("... ")); } else { for (j = 20; j > size; j -= 2) { _ftprintf(fp, _T(" ")); } for (j = 0; j < size; j += 2) { _ftprintf(fp, _T("%04x "), SekFetchWord(pc + j)); } } } // Print the instruction _ftprintf(fp, _T("%hs\n"), buf); pc += size; } fclose(fp); return 0; }
void gentrace(void) { return; if (TRACE_COUNT > 0 || VDP.vcounter() == 33) { uint32_t pc = m68k_get_reg(NULL, M68K_REG_PC); char buf[2048]; int oplen = m68k_disassemble(buf, pc, M68K_CPU_TYPE_68000); fprintf(stdout, "%06x\t%s\t\t[HC=%x]\n", pc, buf, VDP.hcounter()); --TRACE_COUNT; } }
bool soakTestOpWordDecoding(void) { const char* previousDescription = 0; uint opWord; printf("Attempting to decode lengths for all opwords...\n"); for (opWord = 0; opWord < 0x10000; ++opWord) { InstructionLength instructionLength; bool success; uint16_t instructionBuffer[16] = { 0 }; uint musashiInstructionLength; char musashiDisassembledInstruction[256]; instructionBuffer[0] = opWord; success = decodeInstructionLengthFromInstructionWords(instructionBuffer, sizeof instructionBuffer / sizeof instructionBuffer[0], &instructionLength); if (!success) { printf("Error: decoding failed for instruction %04x\n", opWord); return false; } writeInstructionBufferToMusashiMemory(instructionBuffer, sizeof instructionBuffer / sizeof instructionBuffer[0]); musashiInstructionLength = m68k_disassemble(musashiDisassembledInstruction, 0, M68K_CPU_TYPE_68040); if (diffAgainstMusashi(instructionLength.totalWords, musashiInstructionLength, opWord)) { printf("Error: instruction length decoding mismatch for opword %04x -\n", opWord); printf("M68060InstructionLengthDecoder claims instruction %s, %d bytes\n", instructionLength.description, instructionLength.totalWords * 2); printf("Musashi disassembler claims instruction %s, %d bytes\n",musashiDisassembledInstruction, musashiInstructionLength); return false; } if (previousDescription != instructionLength.description) { printf("%04x: %s\n", opWord, instructionLength.description); previousDescription = instructionLength.description; } } return true; }
static unsigned int TraceBack(unsigned int nStartAddress, unsigned int nTotalInstructions, int nCPU) { unsigned int pc = nStartAddress; unsigned int trace = nTotalInstructions; if (nStartAddress == 0 || nTotalInstructions == 0) { return 0; } // If there's no valid instruction at the start adress, increase it while (m68k_is_valid_instruction(SekFetchWord(pc), nCPU) == 0 && (pc - nStartAddress) < ((nCPU == M68K_CPU_TYPE_68000) ? 10 : 30) - 2) { pc += 2; } do { trace_size = 0; trace_pc = pc; // Trace back a few extra instructions to ensure we'll return a valid code path trace_max = trace + 4; TraceBackDo(pc, 0, nCPU); pc -= 2; } while (trace_size == 0 && pc >= nStartAddress); pc = trace_pc; // If we've traced back more instructions than needed, skip the extra ones while (trace_size > trace) { char buf[100] = ""; pc += m68k_disassemble(buf, pc, nCPU); trace++; } // If we can't trace back at all, simply decrease the address if (trace_size == 0) { return nTotalInstructions * 2 < nStartAddress ? nStartAddress - nTotalInstructions * 2 : 0; } return pc; }
static void TraceBackDo(unsigned int start_pc, unsigned int trace_level, int cpu_type) { unsigned int pc; unsigned int trace; // Go over all possible instruction sizes (the longest 68020 instruction is 30 bytes) for (unsigned int size = (cpu_type == M68K_CPU_TYPE_68000) ? 10 : 30; size != 0 ; size -= 2) { pc = start_pc; trace = trace_level; // Make sure we don't go past the start of memory if (size > pc) { break; } // Check if there is a valid instruction at the current address if (m68k_is_valid_instruction(SekFetchWord(pc - size), cpu_type) != 0) { char buf[100] = ""; // Check if the instruction at the current address has the right size if (m68k_disassemble(buf, pc - size, cpu_type) == size) { pc -= size; trace++; // Update best result if (trace_size < trace) { trace_size = trace; trace_pc = pc; } // Recurse until we've traced back enough instructions if (trace < trace_max) { TraceBackDo(pc, trace, cpu_type); } } } } }
void Dasm(uint32_t offset, uint32_t qt) { #ifdef CPU_DEBUG // back up a few instructions... //offset -= 100; static char buffer[2048];//, mem[64]; int pc = offset, oldpc; uint32_t i; for(i=0; i<qt; i++) { /* oldpc = pc; for(int j=0; j<64; j++) mem[j^0x01] = jaguar_byte_read(pc + j); pc += Dasm68000((char *)mem, buffer, 0); WriteLog("%08X: %s\n", oldpc, buffer);//*/ oldpc = pc; pc += m68k_disassemble(buffer, pc, 0);//M68K_CPU_TYPE_68000); // WriteLog("%08X: %s\n", oldpc, buffer);//*/ printf("%08X: %s\n", oldpc, buffer);//*/ } #endif }
void M68KDasmBrowserWindow::RefreshContents(void) { char string[1024];//, buf[64]; QString s; char buffer[2048]; int pc = memBase, oldpc; for(uint32_t i=0; i<32; i++) { oldpc = pc; pc += m68k_disassemble(buffer, pc, 0); // WriteLog("%06X: %s\n", oldpc, buffer); sprintf(string, "%06X: %s<br>", oldpc, buffer); buffer[0] = 0; // Clear string char singleCharString[2] = { 0, 0 }; for(int j=0; j<strlen(string); j++) { if (string[j] == 32) strcat(buffer, " "); else { singleCharString[0] = string[j]; strcat(buffer, singleCharString); } } // s += QString(string); s += QString(buffer); } text->clear(); text->setText(s); }
int m68k_disasm_pc(char* outputBuffer, int outputBufferSize, int pc, int* instCount) { int i, end; // we make sure we have some head room as we sprintf directly into the buffer outputbuffer const char* outputBufferEnd = outputBuffer + outputBufferSize - 32; if (outputBuffer > outputBufferEnd) { printf("M68KDebugger:: outputBuffer needs to be at least 32 bytes and bigger\n"); return 0; } for (i = 0, end = *instCount; i < end; ++i) { int textSize = 0; int inst_size; char instructionText[256]; memset(instructionText, 0, sizeof(instructionText)); inst_size = m68k_disassemble(instructionText, pc, M68K_CPU_TYPE_68040); textSize = sprintf(outputBuffer, "%08x %s\n", pc, instructionText); outputBuffer += textSize; if (outputBuffer >= outputBufferEnd) { *instCount = i; return 1; } pc += inst_size; } return 0; }
// ----------------------------------------------------------------------------------- // �����Τᤤ��롼�� // ----------------------------------------------------------------------------------- void WinX68k_Exec(void) { if(!(Memory_ReadD(0xed0008)==ram_size)){ Memory_WriteB(0xe8e00d, 0x31); // SRAM write permission Memory_WriteD(0xed0008, ram_size); // Define RAM amount } //char *test = NULL; int clk_total, clkdiv, usedclk, hsync, clk_next, clk_count, clk_line=0; int KeyIntCnt = 0, MouseIntCnt = 0; DWORD t_start = timeGetTime(), t_end; if ( Config.FrameRate == 0) Config.FrameRate = 7; if ( Config.FrameRate != 7 ) { DispFrame = (DispFrame+1)%Config.FrameRate; } else { // Auto Frame Skip if ( FrameSkipQueue ) { if ( FrameSkipCount>15 ) { FrameSkipCount = 0; FrameSkipQueue++; DispFrame = 0; } else { FrameSkipCount++; FrameSkipQueue--; DispFrame = 1; } } else { FrameSkipCount = 0; DispFrame = 0; } } vline = 0; clk_count = -ICount; clk_total = (CRTC_Regs[0x29] & 0x10) ? VSYNC_HIGH : VSYNC_NORM; clk_total = (clk_total*clockmhz)/10; clkdiv = clockmhz; /*if (Config.XVIMode == 1) { clk_total = (clk_total*16)/10; clkdiv = 16; } else if (Config.XVIMode == 2) { clk_total = (clk_total*24)/10; clkdiv = 24; } else { clkdiv = 10; }*/ if(clkdiv != old_clkdiv || ram_size != old_ram_size){ printf("CPU Clock: %d%s\n",clkdiv,"MHz"); printf("RAM Size: %ld%s\n",ram_size/1000000,"MB"); old_clkdiv = clkdiv; old_ram_size = ram_size; } ICount += clk_total; clk_next = (clk_total/VLINE_TOTAL); hsync = 1; do { int m, n = (ICount>CLOCK_SLICE)?CLOCK_SLICE:ICount; //C68K.ICount = m68000_ICountBk = 0; // ������ȯ������Ϳ���Ƥ����ʤ��ȥ����CARAT�� if ( hsync ) { hsync = 0; clk_line = 0; MFP_Int(0); if ( (vline>=CRTC_VSTART)&&(vline<CRTC_VEND) ) VLINE = ((vline-CRTC_VSTART)*CRTC_VStep)/2; else VLINE = (DWORD)-1; if ( (!(MFP[MFP_AER]&0x40))&&(vline==CRTC_IntLine) ) MFP_Int(1); if ( MFP[MFP_AER]&0x10 ) { if ( vline==CRTC_VSTART ) MFP_Int(9); } else { if ( CRTC_VEND>=VLINE_TOTAL ) { if ( (long)vline==(CRTC_VEND-VLINE_TOTAL) ) MFP_Int(9); // ���������ƥ�����Ȥ���TOTAL<VEND�� } else { if ( (long)vline==(VLINE_TOTAL-1) ) MFP_Int(9); // ���쥤�������饤�ޡ��ϥ���Ǥʤ��ȥ��ᡩ } } } #ifdef WIN68DEBUG if (traceflag/*&&fdctrace*/) { FILE *fp; static DWORD oldpc; int i; char buf[200]; fp=fopen("_trace68.txt", "a"); for (i=0; i<HSYNC_CLK; i++) { m68k_disassemble(buf, C68k_Get_Reg(&C68K, C68K_PC)); // if (MEM[0xa84c0]) /**test=1; */tracing=1000; // if (regs.pc==0x9d2a) tracing=5000; // if ((regs.pc>=0x2000)&&((regs.pc<=0x8e0e0))) tracing=50000; // if (regs.pc<0x10000) tracing=1; // if ( (regs.pc&1) ) // fp=fopen("_trace68.txt", "a"); // if ( (regs.pc==0x7176) /*&& (Memory_ReadW(oldpc)==0xff1a)*/ ) tracing=100; // if ( (/*((regs.pc>=0x27000) && (regs.pc<=0x29000))||*/((regs.pc>=0x27000) && (regs.pc<=0x29000))) && (oldpc!=regs.pc)) if (/*fdctrace&&*/(oldpc != C68k_Get_Reg(&C68K, C68K_PC))) { // //tracing--; fprintf(fp, "D0:%08X D1:%08X D2:%08X D3:%08X D4:%08X D5:%08X D6:%08X D7:%08X CR:%04X\n", C68K.D[0], C68K.D[1], C68K.D[2], C68K.D[3], C68K.D[4], C68K.D[5], C68K.D[6], C68K.D[7], 0/* xxx �Ȥꤢ����0 C68K.ccr */); fprintf(fp, "A0:%08X A1:%08X A2:%08X A3:%08X A4:%08X A5:%08X A6:%08X A7:%08X SR:%04X\n", C68K.A[0], C68K.A[1], C68K.A[2], C68K.A[3], C68K.A[4], C68K.A[5], C68K.A[6], C68K.A[7], C68k_Get_Reg(&C68K, C68K_SR) >> 8/* regs.sr_high*/); fprintf(fp, "<%04X> (%08X ->) %08X : %s\n", Memory_ReadW(C68k_Get_Reg(&C68K, C68K_PC)), oldpc, C68k_Get_Reg(&C68K, C68K_PC), buf); } #ifdef CYCLONE oldpc = m68000_get_reg(M68K_PC); // * C68KICount = 1; m68000_execute(1); #else oldpc = C68k_Get_Reg(&C68K, C68K_PC); //C68K.ICount = 1; //C68k_Exec(&C68K, C68K.ICount); C68k_Exec(&C68K, 1); #endif } fclose(fp); usedclk = clk_line = HSYNC_CLK; clk_count = clk_next; } else #endif { //C68K.ICount = n; #ifdef CYCLONE m68000_execute(n); #else C68k_Exec(&C68K, n); #endif m = (n-m68000_ICountBk); //m = (n-C68K.ICount-m68000_ICountBk); // clockspeed progress ClkUsed += m*10; usedclk = ClkUsed/clkdiv; clk_line += usedclk; ClkUsed -= usedclk*clkdiv; ICount -= m; clk_count += m; //C68K.ICount = m68000_ICountBk = 0; } MFP_Timer(usedclk); RTC_Timer(usedclk); DMA_Exec(0); DMA_Exec(1); DMA_Exec(2); if ( clk_count>=clk_next ) { //OPM_RomeoOut(Config.BufferSize*5); //MIDI_DelayOut((Config.MIDIAutoDelay)?(Config.BufferSize*5):Config.MIDIDelay); MFP_TimerA(); if ( (MFP[MFP_AER]&0x40)&&(vline==CRTC_IntLine) ) MFP_Int(1); if ( (!DispFrame)&&(vline>=CRTC_VSTART)&&(vline<CRTC_VEND) ) { if ( CRTC_VStep==1 ) { // HighReso 256dot��2���ɤߡ� if ( vline%2 ) WinDraw_DrawLine(); } else if ( CRTC_VStep==4 ) { // LowReso 512dot WinDraw_DrawLine(); // 1��������2�������ʥ����졼���� VLINE++; WinDraw_DrawLine(); } else { // High 512dot / Low 256dot WinDraw_DrawLine(); } } ADPCM_PreUpdate(clk_line); OPM_Timer(clk_line); MIDI_Timer(clk_line); #ifndef NO_MERCURY Mcry_PreUpdate(clk_line); #endif KeyIntCnt++; if ( KeyIntCnt>(VLINE_TOTAL/4) ) { KeyIntCnt = 0; Keyboard_Int(); } MouseIntCnt++; if ( MouseIntCnt>(VLINE_TOTAL/8) ) { MouseIntCnt = 0; SCC_IntCheck(); } DSound_Send0(clk_line); vline++; clk_next = (clk_total*(vline+1))/VLINE_TOTAL; hsync = 1; } } while ( vline<VLINE_TOTAL );
static void CreateDisass(HWND hWindow, unsigned int nAddress, int nCPU) { int nPageSize = bLargeWindow ? 16 : 12; TCHAR szBuffer[16384] = _T(""); TCHAR* pszBuf = szBuffer; unsigned int pc, nSize; pc = nAddress; // RTF header and initial settings pszBuf += _stprintf(pszBuf, _T("{\\rtf1\\ansi\\ansicpg1252\\deff0{\\fonttbl(\\f0\\fmodern\\charset0\\fprq0 Courier New;)}{\\colortbl\\red0\\green0\\blue0;\\red96\\green96\\blue96;\\red255\\green0\\blue0;\\red255\\green96\\blue96;\\red224\\green224\\blue224;}\\deflang1033\\horzdoc\\pard\\plain\\f0")); if (bLargeWindow) { if (nCPU == M68K_CPU_TYPE_68000) { // Tabstops 5555 4444 3333 2222 1111 Mnemonic pszBuf += _stprintf(pszBuf, _T("\\tx1050\\tx1513\\tx1976\\tx2429\\tx2892\\tx3450")); } else { // Tabstops 6666 5555 4444 3333 2222 1111 Mnemonic pszBuf += _stprintf(pszBuf, _T("\\tx1050\\tx1435\\tx1820\\tx2205\\tx2590\\tx2975\\tx3450")); } // Indentation pszBuf += _stprintf(pszBuf, _T("\\fi-4665\\li4665 ")); } else { // Tabstops pszBuf += _stprintf(pszBuf, _T("\\tx735")); } // Print the disassembly for (int i = 0; i < nPageSize; i++) { char buf[100] = ""; unsigned int j; unsigned int nCol; if (pc > 0x00FFFFFE) { do { nDisassAddress[i++] = 0x00FFFFFE; } while (i < nPageSize); break; } nDisassAddress[i] = pc; // Get the mnemonic nSize = m68k_disassemble(buf, pc, nCPU); // Display the instruction at the current PC in red nCol = (pc == SekDbgGetRegister(SEK_REG_PC)) ? 2 : 0; // Print the address pszBuf += _stprintf(pszBuf, _T("\\fs%i\\cf%i %06x\t"), bLargeWindow ? 24 : 16, nCol, pc); if (bLargeWindow) { // Print the word values if (nCPU == M68K_CPU_TYPE_68000) { // Print a filler pszBuf += _stprintf(pszBuf, _T("\\fs16\\cf4 ")); for (j = 10; j > nSize; j -= 2) { pszBuf += _stprintf(pszBuf, _T(" -- \t")); } // Print the words that make up the instruction pszBuf += _stprintf(pszBuf, _T("\\cf%i "), nCol + 1); for (j = 0; j < nSize; j += 2) { pszBuf += _stprintf(pszBuf, _T("%04x\t"), SekFetchWord(pc + j)); } } else { if (nSize > 12) { // There's not enough room for all words, so print the first 5 words that make up the instruction pszBuf += _stprintf(pszBuf, _T("\\fs13\\cf%i "), nCol + 1); for (j = 0; j < 10; j += 2) { pszBuf += _stprintf(pszBuf, _T("%04x\t"), SekFetchWord(pc + j)); } // Print an ellipsis pszBuf += _stprintf(pszBuf, _T("... \t")); } else { // Print a filler pszBuf += _stprintf(pszBuf, _T("\\fs13\\cf4 ")); for (j = 12; j > nSize; j -= 2) { pszBuf += _stprintf(pszBuf, _T(" -- \t")); } // Print the words that make up the instruction pszBuf += _stprintf(pszBuf, _T("\\cf%i "), nCol + 1); for (j = 0; j < nSize; j += 2) { pszBuf += _stprintf(pszBuf, _T("%04x\t"), SekFetchWord(pc + j)); } } } } // Colour Invalid instructions gray if (nCol == 0) { if (m68k_is_valid_instruction(SekFetchWord(pc), nCPU) == 0) { nCol++; } } // Print the instruction pszBuf += _stprintf(pszBuf, _T("\\fs%i\\cf%i %hs\\par"), bLargeWindow ? 24 : 16, nCol, buf); pc += nSize; } pszBuf += _stprintf(pszBuf, _T("}\0")); // Send the new data to the RichEdit control SendMessage(hWindow, WM_SETTEXT, (WPARAM)0, (LPARAM)szBuffer); #if 0 FILE* fp = _tfopen(_T("disass.rtf"), _T("wb")); if (fp) { fwrite(szBuffer, 1, _tcslen(szBuffer), fp); fclose(fp); } #endif }
int main(int argc, const char *argv[]) { ez::ezOptionParser opt; opt.overview = "GenEmu -- Sega Genesis Emulator"; opt.syntax = "genemu [OPTIONS] rom"; opt.add("",0,0,0,"Display usage instructions.", "-h", "--help"); opt.add("",0,-1,',',"Apply Game Genie codes [format=ABCD-EFGH]", "--gamegenie", "--gg"); opt.add("",0,1,0,"Force console type [accepted values: PAL or NTSC]", "--mode", "--type"); opt.add("",0,-1,',',"Make screenshots on the specified frames and exit", "--screenshots"); opt.add("",0,1,0,"Load from saved state", "--load"); opt.parse(argc, argv); if (opt.isSet("-h")) { std::string usage; opt.getUsage(usage, 120); std::cout << usage; return 0; } std::vector<std::string*> args; if (opt.firstArgs.size() >= 2) { strcpy(romname, opt.firstArgs[1]->c_str()); } else if (opt.lastArgs.size() >= 1) strcpy(romname, opt.lastArgs[0]->c_str()); else { std::cerr << "ERROR: no ROM specified\n"; return 2; } int romsize; if (strstr(romname, ".smd")) romsize = load_smd(romname); else romsize = load_bin(romname); mem_init(romsize); #if 0 uint16_t checksum = 0; for (int i=0;i<(romsize-512)/2;i++) checksum += m68k_read_memory_16(512+i*2); assert(checksum == m68k_read_memory_16(0x18e)); #endif #if 1 char buf[256]; int pc = 0; strcpy(buf, argv[1]); strcat(buf, ".asm"); FILE *f = fopen(buf, "w"); while (pc < romsize) { int oplen = m68k_disassemble(buf, pc, M68K_CPU_TYPE_68000); fprintf(f, "%06x\t%s\n", pc, buf); pc += oplen; } fclose(f); #endif if (opt.isSet("--mode")) { std::string mode; opt.get("--mode")->getString(mode); if (mode == "PAL") { VERSION_PAL = 1; std::cerr << "Forced mode: PAL\n"; } else if (mode == "NTSC") { VERSION_PAL = 0; std::cerr << "Forced mode: NTSC\n"; } else { std::cerr << "ERROR: invalid mode: " << mode << std::endl; return 2; } } std::vector<int> ss_frames; int ss_idx = 0; hw_init(YM2612_FREQ, VERSION_PAL ? 50 : 60); if (!opt.isSet("--screenshots")) { hw_enable_video(true); hw_enable_audio(true); gfx_enable(true); } else { opt.get("--screenshots")->getInts(ss_frames); } CPU_M68K.init(); CPU_Z80.init(); MASTER_CLOCK = 0; CPU_M68K.reset(); VDP.reset(); if (opt.isSet("--load")) { std::string sn; opt.get("--load")->getString(sn); loadstate(sn.c_str()); } while (hw_poll()) { if (ss_idx < ss_frames.size() && framecounter == ss_frames[ss_idx]) { gfx_enable(true); } int numscanlines = VDP.num_scanlines(); uint8_t *screen; int pitch; hw_beginframe(&screen, &pitch); int16_t *audio; int nsamples; hw_beginaudio(&audio, &nsamples); int audio_index = 0; int audio_step = (nsamples << 16) / numscanlines; for (int sl=0;sl<numscanlines;++sl) { CPU_M68K.run(MASTER_CLOCK + VDP_CYCLES_PER_LINE); CPU_Z80 .run(MASTER_CLOCK + VDP_CYCLES_PER_LINE); vdp_scanline(screen); screen += pitch; int prev_index = audio_index; audio_index += audio_step; YM2612Update(audio + ((prev_index+0x8000)>>16)*2, (audio_index-prev_index+0x8000)>>16); MASTER_CLOCK += VDP_CYCLES_PER_LINE; } hw_endaudio(); hw_endframe(); if (framecounter == 100 && opt.isSet("--gamegenie")) { std::vector<std::string> codes; opt.get("--gamegenie")->getStrings(codes); for (int i=0;i<codes.size();++i) mem_apply_gamegenie(codes[i].c_str()); } if (ss_idx < ss_frames.size() && framecounter == ss_frames[ss_idx]) { static char ssname[2048]; sprintf(ssname, "%s.%d.%s.bmp", romname, framecounter, (VERSION_PAL ? "PAL" : "NTSC")); std::cerr << "Saving screenshot " << ssname << std::endl; hw_save_screenshot(ssname); sprintf(ssname, "%s.%d.%s.gs", romname, framecounter, (VERSION_PAL ? "PAL" : "NTSC")); savestate(ssname); ++ss_idx; if (ss_idx == ss_frames.size()) break; } ++framecounter; state_poll(); } #if 0 checksum = 0; for (int i=0;i<(romsize-512)/2;i++) checksum += m68k_read_memory_16(512+i*2); assert(checksum == m68k_read_memory_16(0x18e)); #endif #if 0 { char buf[256]; int pc = 0xffffee00; FILE *f = fopen(buf, "w"); while (pc <= 0xffffef00) { int oplen = m68k_disassemble(buf, pc, M68K_CPU_TYPE_68000); fprintf(stdout, "%06x\t%s\n", pc, buf); pc += oplen; } fclose(f); } #endif return 0; }