Exemple #1
0
/*
 * 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;
    }
}
Exemple #2
0
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();
		}
	}
}
Exemple #3
0
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
}
Exemple #4
0
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++;
    }
}
Exemple #5
0
	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;
		}
	}