static void* nes_thread_proc(void *param) { NES *nes = (NES*)param; int totalpclk, nmi, irq; while (!nes->thread_exit) { //++ for run/pause ++// if (!nes->isrunning) { nes->ispaused = 1; nes->ppu.vdev->dequeue(nes->ppu.vctxt, NULL, NULL); nes->ppu.vdev->enqueue(nes->ppu.vctxt); continue; } //-- for run/pause --// //++ for replay playing ++// if (!replay_progress(&(nes->replay)) && nes->request_reset == 0) { nes->ppu.vdev->dequeue(nes->ppu.vctxt, NULL, NULL); nes->ppu.vdev->enqueue(nes->ppu.vctxt); continue; } //-- for replay playing --// //++ for nes reset ++// if (nes->request_reset == 1) { nes->request_reset = 0; nes_do_reset(nes); } //-- for nes reset --// //++ run cpu & apu & ppu do { cpu_run_pclk(&(nes->cpu)); // run cpu ppu_run_pclk(&(nes->ppu)); // run ppu apu_run_pclk(&(nes->apu)); // run apu //+ for cpu nmi & irq nmi = nes->ppu.pinvbl; irq = !(nes->apu.regs[0x0015] & 0xC0); cpu_nmi(&(nes->cpu), nmi); cpu_irq(&(nes->cpu), irq); //- for cpu nmi & irq } while (nes->ppu.pclk_frame != NES_HTOTAL * 241 + 2); // at frame clk (241, 2) the frame buffer will be enqueued //-- run cpu & apu & ppu // run joypad for turbo key function joypad_run(&(nes->pad)); } return NULL; }
void gb_run() { #ifdef PROFILE prof_enter(PF_GB_RUN); #endif //if (rom_get_loaded()){ if (g_regs.LCDC&0x80){ // LCDC 起動時 g_regs.LY=(g_regs.LY+1)%154; g_regs.STAT&=0xF8; if (g_regs.LYC==g_regs.LY){ g_regs.STAT|=4; if (g_regs.STAT&0x40) cpu_irq(INT_LCDC); } if (g_regs.LY==0){ renderer_refresh(); if (now_frame>=skip){ //pgFillvram(0); render_screen(vframe); now_frame=0; } else now_frame++; lcd_clear_win_count(); // skip=skip_buf; } if (g_regs.LY>=144){ // VBlank 期間中 g_regs.STAT|=1; if (g_regs.LY==144){ cpu_exec(72); cpu_irq(INT_VBLANK); if (g_regs.STAT&0x10) cpu_irq(INT_LCDC); cpu_exec(456-80); } else if (g_regs.LY==153){ cpu_exec(80); g_regs.LY=0; cpu_exec(456-80); // 前のラインのかなり早目から0になるようだ。 g_regs.LY=153; } else cpu_exec(456); } else{ // VBlank 期間外 g_regs.STAT|=2; if (g_regs.STAT&0x20) cpu_irq(INT_LCDC); cpu_exec(80); // state=2 g_regs.STAT|=3; cpu_exec(169); // state=3 if (dma_executing){ // HBlank DMA if (b_dma_first){ dma_dest_bank=vram_bank; if (dma_src<0x4000) dma_src_bank=get_rom(); else if (dma_src<0x8000) dma_src_bank=mbc_get_rom(); else if (dma_src>=0xA000&&dma_src<0xC000) dma_src_bank=mbc_get_sram()-0xA000; else if (dma_src>=0xC000&&dma_src<0xD000) dma_src_bank=ram-0xC000; else if (dma_src>=0xD000&&dma_src<0xE000) dma_src_bank=ram_bank-0xD000; else dma_src_bank=NULL; b_dma_first=false; } memcpy(dma_dest_bank+(dma_dest&0x1ff0),dma_src_bank+dma_src,16); // fprintf(cpu_file,"%03d : dma exec %04X -> %04X rest %d\n",g_regs.LY,cpu_dma_src,cpu_dma_dest,cpu_dma_rest); dma_src+=16; dma_src&=0xfff0; dma_dest+=16; dma_dest&=0xfff0; dma_rest--; if (!dma_rest) dma_executing=false; // cpu_total_clock+=207*(cpu_speed?2:1); // cpu_sys_clock+=207*(cpu_speed?2:1); // cpu_div_clock+=207*(cpu_speed?2:1); // g_regs.STAT|=3; if (now_frame>=skip && !sgb_mask) lcd_render(vframe,g_regs.LY); g_regs.STAT&=0xfc; cpu_exec(207); // state=3 } else{ /* if (lcd_get_sprite_count()){ if (lcd_get_sprite_count()>=10){ cpu_exec(129); if ((g_regs.STAT&0x08)) cpu_irq(INT_LCDC); g_regs.STAT&=0xfc; if (now_frame>=skip) lcd_render(vframe,g_regs.LY); cpu_exec(78); // state=0 } else{ cpu_exec(129*lcd_get_sprite_count()/10); if ((g_regs.STAT&0x08)) cpu_irq(INT_LCDC); g_regs.STAT&=0xfc; if (now_frame>=skip) lcd_render(vframe,g_regs.LY); cpu_exec(207-(129*lcd_get_sprite_count()/10)); // state=0 } } else{ */ g_regs.STAT&=0xfc; if (now_frame>=skip && !sgb_mask) lcd_render(vframe,g_regs.LY); if ((g_regs.STAT&0x08)) cpu_irq(INT_LCDC); cpu_exec(207); // state=0 // } } } } else{ // LCDC 停止時 g_regs.LY=0; // g_regs.LY=(g_regs.LY+1)%154; re_render++; if (re_render>=154){ gb_fill_vframe(0xff); renderer_refresh(); if (now_frame>=skip){ //pgFillvram(0); render_screen(vframe); now_frame=0; } else now_frame++; lcd_clear_win_count(); re_render=0; } g_regs.STAT&=0xF8; cpu_exec(456); } //} #ifdef PROFILE prof_out(); #endif }
int gb_run() { int cmd = 0; if (rom_get_loaded()){ if (g_regs.LCDC&0x80){ // LCDC 起動時 g_regs.LY=(g_regs.LY+1)%154; g_regs.STAT&=0xF8; if (g_regs.LYC==g_regs.LY){ g_regs.STAT|=4; if (g_regs.STAT&0x40) cpu_irq(INT_LCDC); } if (g_regs.LY==0){ // renderer_refresh(); cmd |= 1; /* if (gbSkip){ render_screen(vframe); // now_frame=0; } else now_frame++;*/ lcd_clear_win_count(); // skip=skip_buf; } if (g_regs.LY>=144){ // VBlank 期間中 g_regs.STAT|=1; if (g_regs.LY==144){ cpu_exec(72); cpu_irq(INT_VBLANK); if (g_regs.STAT&0x10) cpu_irq(INT_LCDC); cpu_exec(456-80); } else if (g_regs.LY==153){ cpu_exec(80); g_regs.LY=0; cpu_exec(456-80); // 前のラインのかなり早目から0になるようだ。 g_regs.LY=153; } else cpu_exec(456); } else{ // VBlank 期間外 g_regs.STAT|=2; if (g_regs.STAT&0x20) cpu_irq(INT_LCDC); cpu_exec(80); // state=2 g_regs.STAT|=3; cpu_exec(169); // state=3 if (dma_executing){ // HBlank DMA if (b_dma_first){ dma_dest_bank=vram_bank; if (dma_src<0x4000) dma_src_bank=get_rom(); else if (dma_src<0x8000) dma_src_bank=mbc_get_rom(); else if (dma_src>=0xA000&&dma_src<0xC000) dma_src_bank=mbc_get_sram()-0xA000; else if (dma_src>=0xC000&&dma_src<0xD000) dma_src_bank=ram-0xC000; else if (dma_src>=0xD000&&dma_src<0xE000) dma_src_bank=ram_bank-0xD000; else dma_src_bank=NULL; b_dma_first=false; } memcpy(dma_dest_bank+(dma_dest&0x1ff0),dma_src_bank+dma_src,16); // fprintf(cpu_file,"%03d : dma exec %04X -> %04X rest %d\n",g_regs.LY,cpu_dma_src,cpu_dma_dest,cpu_dma_rest); dma_src+=16; dma_src&=0xfff0; dma_dest+=16; dma_dest&=0xfff0; dma_rest--; if (!dma_rest) dma_executing=false; // cpu_total_clock+=207*(cpu_speed?2:1); // cpu_sys_clock+=207*(cpu_speed?2:1); // cpu_div_clock+=207*(cpu_speed?2:1); // g_regs.STAT|=3; if (!gbSkip && !sgb_mask) lcd_render(vframe,g_regs.LY); g_regs.STAT&=0xfc; cpu_exec(207); // state=3 } else{ /* if (lcd_get_sprite_count()){ if (lcd_get_sprite_count()>=10){ cpu_exec(129); if ((g_regs.STAT&0x08)) cpu_irq(INT_LCDC); g_regs.STAT&=0xfc; if (now_frame>=skip) lcd_render(vframe,g_regs.LY); cpu_exec(78); // state=0 } else{ cpu_exec(129*lcd_get_sprite_count()/10); if ((g_regs.STAT&0x08)) cpu_irq(INT_LCDC); g_regs.STAT&=0xfc; if (now_frame>=skip) lcd_render(vframe,g_regs.LY); cpu_exec(207-(129*lcd_get_sprite_count()/10)); // state=0 } } else{ */ g_regs.STAT&=0xfc; if (!gbSkip && !sgb_mask) lcd_render(vframe,g_regs.LY); if ((g_regs.STAT&0x08)) cpu_irq(INT_LCDC); cpu_exec(207); // state=0 // } } } } else{ // LCDC 停止時 g_regs.LY=0; // g_regs.LY=(g_regs.LY+1)%154; re_render++; if (re_render>=154) { // memset(vframe,0xff,(160+16)*144*2); if (!gbSkip) memset(vframe, 0xff, VFRAME_SIZE); // renderer_refresh(); cmd |= 1; /* if (!gbSkip) { // render_screen(vframe); now_frame=0; } else now_frame++;*/ lcd_clear_win_count(); re_render=0; } g_regs.STAT&=0xF8; cpu_exec(456); } // if (!menuConfig.sound.perfectSynchro) // sound_update_gb(line); } return cmd; }
int sc_main(int, char **) { MBWrapper cpu("MBWrapper"); Memory inst_ram("inst_ram", INST_RAM_SIZE); // Memory data_ram("data_ram", SRAM_SIZE); Bus bus("bus"); TIMER timer("timer", sc_core::sc_time(20, sc_core::SC_NS)); Vga vga("vga"); Intc intc("intc"); Gpio gpio("gpio"); sc_core::sc_signal<bool> timer_irq("timer_irq"); sc_core::sc_signal<bool> vga_irq("vga_irq"); sc_core::sc_signal<bool> cpu_irq("cpu_irq"); // Load the program in RAM soclib::common::Loader::register_loader("elf", soclib::common::elf_load); try { soclib::common::Loader loader("../software/cross/a.out"); loader.load(inst_ram.storage, 0, SOFT_SIZE); for (int i = 0; i < SOFT_SIZE / 4; i++) { inst_ram.storage[i] = uint32_be_to_machine(inst_ram.storage[i]); } } catch (soclib::exception::RunTimeError e) { std::cerr << "unable to load ELF file in memory:" << std::endl; std::cerr << e.what() << std::endl; abort(); } // initiators cpu.socket.bind(bus.target); vga.initiator(bus.target); // targets // bus.initiator(data_ram.target); bus.initiator(inst_ram.target); bus.initiator(vga.target); bus.initiator(timer.target); bus.initiator(gpio.target); bus.initiator(intc.target); // interrupts vga.irq(vga_irq); timer.irq(timer_irq); intc.in0(vga_irq); intc.in1(timer_irq); intc.out(cpu_irq); cpu.irq(cpu_irq); // port start addr size bus.map(inst_ram.target, INST_RAM_BASEADDR, INST_RAM_SIZE); // bus.map(data_ram.target, SRAM_BASEADDR, SRAM_SIZE); bus.map(vga.target, VGA_BASEADDR, VGA_SIZE); bus.map(gpio.target, GPIO_BASEADDR, GPIO_SIZE); bus.map(timer.target, TIMER_BASEADDR, TIMER_SIZE); bus.map(intc.target, INTC_BASEADDR, INTC_SIZE); // start the simulation sc_core::sc_start(); return 0; }