void emu_run(uint32_t usec) { uint32_t tickCount = (EMU_TICKS_PER_SEC*1e-6) * usec; if(gEmu.irqPending) { irq6502(); gEmu.irqPending = 0; } exec6502(tickCount); }
//NES 帧周期循环 void NesFrameCycle(GContext *ctx) { int clocks; //CPU执行时间 //启动模拟器循环,检查VROM设置,若卡带为0,初始化VROM //if ( NesHeader.byVRomSize == 0) //设置VROM存储区位置。 //frame_cnt=0; nesruning=1; //while(nesruning) { //scanline: 0~19 VBANK 段,若PPU使能NMI,将产生NMI 中断 frame_cnt++;//帧计数器 SpriteHitFlag=FALSE; for(PPU_scanline=0; PPU_scanline<20; PPU_scanline++) { exec6502(CLOCKS_PER_SCANLINE); } //scanline: 20, PPU加载设置,执行一次空的扫描时间 exec6502(CLOCKS_PER_SCANLINE); //NesHBCycle(); //水平周期 PPU_scanline++; //20++ PPU_Reg.NES_R2 &= ~R2_SPR0_HIT; //scanline: 21~261 for(; PPU_scanline < SCAN_LINE_DISPALY_END_NUM; PPU_scanline++) { if((SpriteHitFlag == TRUE) && ((PPU_Reg.NES_R2 & R2_SPR0_HIT) == 0)) { clocks = sprite[0].x * CLOCKS_PER_SCANLINE / NES_DISP_WIDTH; exec6502(clocks); PPU_Reg.NES_R2 |= R2_SPR0_HIT; exec6502(CLOCKS_PER_SCANLINE - clocks); }else exec6502(CLOCKS_PER_SCANLINE); if(PPU_Reg.NES_R1 & (R1_BG_VISIBLE | R1_SPR_VISIBLE))//若为假,关闭显示 { if(SpriteHitFlag == FALSE) NES_GetSpr0HitFlag(PPU_scanline - SCAN_LINE_DISPALY_START_NUM);//查找Sprite #0 碰撞标志 } //if((frame_cnt%3)==0)//每2帧显示一次 { NES_RenderLine(PPU_scanline - SCAN_LINE_DISPALY_START_NUM, ctx);//水平同步与显示一行 } } //layer_mark_dirty(s_canvas_layer); //scanline: 262 完成一帧 exec6502(CLOCKS_PER_SCANLINE); PPU_Reg.NES_R2 |= R2_VBlank_Flag;//设置VBANK 标志 //若使能PPU VBANK中断,则设置VBANK if(PPU_Reg.NES_R0 & R0_VB_NMI_EN) { NMI_Flag = SET1;//完成一帧扫描,产生NMI中断 } //设置帧IRQ标志,同步计数器,APU等 //A mapper function in V-Sync 存储器切换垂直VBANK同步 //MapperVSync(); //读取控制器JoyPad状态,更新JoyPad控制器值 //NES_JoyPadUpdateValue(); //systick 中断读取按键值 } }
int main(int argc, char **argv) { int cycles_to_run; char *machine_code; // This will hold our "ASCII Object File" char debug_command[180]="init"; char *cmdptr; unsigned int dbg_addr; printf("6502 simulator front end for CS 2208a.\n\n"); // Did the user specify an object file on the command line? // If not... help them. if(argc < 3) { printf("Usage: %s [ASCII Object File name] [# cycles to simulate] {-d}\n",argv[0]); printf(" e.g.: %s test.obj 3000 -d\n\n",argv[0]); exit(-1); } // Read the object file into a string. machine_code = read_obj_file(argv[1]); // Fire up the system RAM initMem(); // Load the object file from the string into our simulated RAM, // starting at memory location 'code_location'. loadMem(machine_code,code_location); // We did something horribly underhanded in read_obj_file()... // we allocated memory with 'malloc' and then passed back a pointer. // But note that the onus is on us, the C programmer, to _remember_ // that we did that and free up the memory when it's no longer needed. // Not a big deal here, but imagine a bigger program where you're keeping // track of hundreds of mallocs and frees. Now you know why C programs // leak memory like the titanic. free(machine_code); // Initialize the 6502 init6502(); reset6502(); PC = code_location; // Make sure the program counter points to our code! // All set to run the simulator now! // Everything below is just fanciness to give you a rudimentry 6502 debugger // to help with your assignment. Without the fancyness, all we're really doing // is one call: // // exec6502(num_cycles); // Run in debug mode, if requested if( (argc > 3) && (!strcmp(argv[3],"-d"))) { printf("Running in DEBUG MODE.\n\nType '?' for help.\n"); // Debug loop while(strcmp(debug_command,"quit")) { //dumpMem(0x0021); // Check the value we stored to the zero page //dumpMem(0x01FF); // Peek at the top of the stack. Remember, the stack // is hard-coded to addresses $0100–$01FF. //dump6502reg(); // print registers to the screen printf("debug> "); if( (gets(debug_command))[0] != '\0'){ cmdptr = strtok(debug_command," "); switch(cmdptr[0]) { case 'p': if(cmdptr = strtok(NULL," ")) { sscanf(cmdptr, "%x", &dbg_addr); dumpMem((WORD)dbg_addr); } break; case 'r': dump6502reg(); break; case 's': exec6502(1); // Execute 1 command break; case '?': printf("\n\np [0xAddress] - print value at memory location\n"); printf("r - print register values\n"); printf("s - step through program\n"); printf("quit - exit\n\n"); break; default: (cmdptr[0] % 2) ? printf("Herp.\n") : printf("Derp.\n"); } } } } else { // Otherwise, run in regular mode. exec6502(atoi(argv[2])); } }