/* * Updates the screen. */ void graphics_update(context_t *ctx, int cycles) { // context->state starts in OAM. As soon as a certain // amount of cycles is reached, state transitions // to TRANSF, etc. if (!lcdc_display_enabled(&ctx->mem)) { // LCD is disabled. ctx->mem.io.LY = 144; ctx->gfx.state = VBLANK_WAIT; ctx->gfx.cycles = 0; return; } ctx->gfx.cycles += cycles; switch (ctx->gfx.state) { case OAM: oam(ctx); case OAM_WAIT: oam_wait(ctx); break; case TRANSF: transf(ctx); break; case HBLANK: hblank(ctx); case HBLANK_WAIT: hblank_wait(ctx); break; case VBLANK: vblank(ctx); case VBLANK_WAIT: vblank_wait(ctx); break; } }
void interruptStep(void) { if(interrupt.master && interrupt.enable && interrupt.flags) { unsigned char fire = interrupt.enable & interrupt.flags; if(fire & INTERRUPTS_VBLANK) { interrupt.flags &= ~INTERRUPTS_VBLANK; vblank(); } if(fire & INTERRUPTS_LCDSTAT) { interrupt.flags &= ~INTERRUPTS_LCDSTAT; lcdStat(); } if(fire & INTERRUPTS_TIMER) { interrupt.flags &= ~INTERRUPTS_TIMER; timer(); } if(fire & INTERRUPTS_SERIAL) { interrupt.flags &= ~INTERRUPTS_SERIAL; serial(); } if(fire & INTERRUPTS_JOYPAD) { interrupt.flags &= ~INTERRUPTS_JOYPAD; joypad(); } } }
void VGA::flip() { vblank(); #if VGA_USE_DOUBLE_BUFFER bufferNumber = 1 - bufferNumber; if (bufferNumber == 0) { vgaBuffer = _buffer1; activeBuffer = _buffer0; } else { vgaBuffer = _buffer0; activeBuffer = _buffer1; } #endif }
void NesMain(void) { unsigned char bgy = 0; const char palettebg[] = { 0x0f, 0x11, 0x21, 0x30, 0x0f, 0x11, 0x21, 0x30, 0x0f, 0x11, 0x21, 0x30, 0x0f, 0x11, 0x21, 0x30 }; const char palettespr[] = { 0x0f, 0x00, 0x10, 0x21, 0x0f, 0x0f, 0x10, 0x21, 0x0f, 0x09, 0x19, 0x21, 0x0f, 0x15, 0x27, 0x30 }; init_ppu(); set_palette((char *)palettebg, 0); set_palette((char *)palettespr, 1); set_background(0x21, 0xc9, "HELLO, WORLD!", 13); set_scroll(0, 0); set_ppu(0x08, 0x1e); while (1) { vblank(); bgy++; if (bgy == 240) { bgy == 0; } set_scroll(0, bgy); frame++; } }
void thread::on_task() { on_init_thread(); reset(); last_flip_time = get_system_time() - 1000000; scope_thread_t vblank(PURE_EXPR("VBlank Thread"s), [this]() { const u64 start_time = get_system_time(); vblank_count = 0; // TODO: exit condition while (!Emu.IsStopped()) { if (get_system_time() - start_time > vblank_count * 1000000 / 60) { vblank_count++; if (vblank_handler) { Emu.GetCallbackManager().Async([func = vblank_handler](PPUThread& ppu) { func(ppu, 1); }); } continue; } std::this_thread::sleep_for(1ms); // hack } }); // TODO: exit condition while (true) { CHECK_EMU_STATUS; be_t<u32> get = ctrl->get; be_t<u32> put = ctrl->put; if (put == get || !Emu.IsRunning()) { std::this_thread::sleep_for(std::chrono::milliseconds(1)); // hack continue; } const u32 cmd = ReadIO32(get); const u32 count = (cmd >> 18) & 0x7ff; if (cmd & CELL_GCM_METHOD_FLAG_JUMP) { u32 offs = cmd & 0x1fffffff; //LOG_WARNING(RSX, "rsx jump(0x%x) #addr=0x%x, cmd=0x%x, get=0x%x, put=0x%x", offs, m_ioAddress + get, cmd, get, put); ctrl->get = offs; continue; } if (cmd & CELL_GCM_METHOD_FLAG_CALL) { m_call_stack.push(get + 4); u32 offs = cmd & ~3; //LOG_WARNING(RSX, "rsx call(0x%x) #0x%x - 0x%x", offs, cmd, get); ctrl->get = offs; continue; } if (cmd == CELL_GCM_METHOD_FLAG_RETURN) { u32 get = m_call_stack.top(); m_call_stack.pop(); //LOG_WARNING(RSX, "rsx return(0x%x)", get); ctrl->get = get; continue; } if (cmd == 0) //nop { ctrl->get = get + 4; continue; } auto args = vm::ptr<u32>::make((u32)RSXIOMem.RealAddr(get + 4)); u32 first_cmd = (cmd & 0xffff) >> 2; if (cmd & 0x3) { LOG_WARNING(Log::RSX, "unaligned command: %s (0x%x from 0x%x)", get_method_name(first_cmd).c_str(), first_cmd, cmd & 0xffff); } for (u32 i = 0; i < count; i++) { u32 reg = cmd & CELL_GCM_METHOD_FLAG_NON_INCREMENT ? first_cmd : first_cmd + i; u32 value = args[i]; if (rpcs3::config.misc.log.rsx_logging.value()) { LOG_NOTICE(Log::RSX, "%s(0x%x) = 0x%x", get_method_name(reg).c_str(), reg, value); } method_registers[reg] = value; if (capture_current_frame) frame_debug.command_queue.push_back(std::make_pair(reg, value)); if (auto method = methods[reg]) method(this, value); } ctrl->get = get + (count + 1) * 4; } }