Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
93 changes: 83 additions & 10 deletions workspace/all/minarch/minarch.c
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,11 @@ static int DEVICE_PITCH = 0; // FIXED_PITCH;

GFX_Renderer renderer;

size_t max_state_size = 0;
uint8_t *base_state;
uint8_t *runahead_state;
int doRunAhead = 0;

///////////////////////////////////////

static struct Core {
Expand Down Expand Up @@ -2990,6 +2995,7 @@ static int setFastForward(int enable) {

static uint32_t buttons = 0; // RETRO_DEVICE_ID_JOYPAD_* buttons
static int ignore_menu = 0;
static int runahead_buttons = 0;
static void input_poll_callback(void) {
PAD_poll();

Expand Down Expand Up @@ -3108,15 +3114,22 @@ static void input_poll_callback(void) {
case BTN_DPAD_LEFT: btn = BTN_LEFT; break;
case BTN_DPAD_RIGHT: btn = BTN_RIGHT; break;
}

}
if (PAD_isPressed(btn) && (!mapping->mod || PAD_isPressed(BTN_MENU))) {
buttons |= 1 << mapping->retro;
if (mapping->mod) ignore_menu = 1;
}
if(PAD_anyJustPressed()) {
doRunAhead = 1;
}
runahead_buttons = buttons;
// && !PWR_ignoreSettingInput(btn, show_setting)
}

// if (buttons) LOG_info("buttons: %i\n", buttons);


}
static int16_t input_state_callback(unsigned port, unsigned device, unsigned index, unsigned id) {
if (port==0 && device==RETRO_DEVICE_JOYPAD && index==0) {
Expand Down Expand Up @@ -3201,6 +3214,7 @@ static bool set_rumble_state(unsigned port, enum retro_rumble_effect effect, uin
VIB_setStrength(strength);
return 1;
}

static bool environment_callback(unsigned cmd, void *data) { // copied from picoarch initially
// LOG_info("environment_callback: %i\n", cmd);

Expand Down Expand Up @@ -4411,9 +4425,12 @@ void applyCircleReveal(uint32_t **data, size_t pitch, unsigned width, unsigned h
*data = temp_buffer;
}



static void video_refresh_callback_main(const void *data, unsigned width, unsigned height, size_t pitch) {
// return;


Special_render();

// static int tmp_frameskip = 0;
Expand Down Expand Up @@ -4513,7 +4530,7 @@ static Uint32* rgbaData = NULL;
static size_t rgbaDataSize = 0;

static void video_refresh_callback(const void* data, unsigned width, unsigned height, size_t pitch) {

// I need to check quit here because sometimes quit is true but callback is still called by the core after and it still runs one more frame and it looks ugly :D
if(!quit) {
if (!rgbaData || rgbaDataSize != width * height) {
Expand Down Expand Up @@ -4602,7 +4619,8 @@ static size_t audio_sample_batch_callback(const int16_t *data, size_t frames) {
}
else return frames;
// return frames;
};
}


///////////////////////////////////////

Expand All @@ -4611,6 +4629,15 @@ void Core_getName(char* in_name, char* out_name) {
char* tmp = strrchr(out_name, '_');
tmp[0] = '\0';
}

void (*set_video_refresh_callback)(retro_video_refresh_t);
void (*set_audio_sample_callback)(retro_audio_sample_t);
void (*set_audio_sample_batch_callback)(retro_audio_sample_batch_t);
void (*set_input_state_callback)(retro_input_state_t);




void Core_open(const char* core_path, const char* tag_name) {
LOG_info("Core_open\n");
core.handle = dlopen(core_path, RTLD_LAZY);
Expand All @@ -4637,19 +4664,19 @@ void Core_open(const char* core_path, const char* tag_name) {
core.get_memory_size = dlsym(core.handle, "retro_get_memory_size");

void (*set_environment_callback)(retro_environment_t);
void (*set_video_refresh_callback)(retro_video_refresh_t);
void (*set_audio_sample_callback)(retro_audio_sample_t);
void (*set_audio_sample_batch_callback)(retro_audio_sample_batch_t);

void (*set_input_poll_callback)(retro_input_poll_t);
void (*set_input_state_callback)(retro_input_state_t);


set_environment_callback = dlsym(core.handle, "retro_set_environment");
set_video_refresh_callback = dlsym(core.handle, "retro_set_video_refresh");
set_audio_sample_callback = dlsym(core.handle, "retro_set_audio_sample");
set_audio_sample_batch_callback = dlsym(core.handle, "retro_set_audio_sample_batch");
set_input_poll_callback = dlsym(core.handle, "retro_set_input_poll");
set_input_state_callback = dlsym(core.handle, "retro_set_input_state");




struct retro_system_info info = {};
core.get_system_info(&info);

Expand Down Expand Up @@ -4682,6 +4709,7 @@ void Core_open(const char* core_path, const char* tag_name) {
set_audio_sample_batch_callback(audio_sample_batch_callback);
set_input_poll_callback(input_poll_callback);
set_input_state_callback(input_state_callback);

}
void Core_init(void) {
LOG_info("Core_init\n");
Expand Down Expand Up @@ -6770,6 +6798,20 @@ static void limitFF(void) {
}


int16_t dummy_buffer[4096];

static void fakeAudioCall(int16_t left, int16_t right) {}
size_t fakeBatchCall(const int16_t *data, size_t frames) {
memcpy(dummy_buffer, data, frames * sizeof(int16_t) * 2); // Stereo
return frames;
}
static void fakeVideoCall(const void *data, unsigned width, unsigned height, size_t pitch) {}
static int16_t fake_input_callback(unsigned port, unsigned device, unsigned index, unsigned id) {
int bit = 1 << id;
return (runahead_buttons & bit) ? 1 : 0;
}


int main(int argc , char* argv[]) {
LOG_info("MinArch\n");
pthread_t cpucheckthread;
Expand Down Expand Up @@ -6876,13 +6918,44 @@ int main(int argc , char* argv[]) {
// release config when all is loaded
Config_free();
LOG_info("total startup time %ims\n\n",SDL_GetTicks());

max_state_size = core.serialize_size();
base_state = malloc(max_state_size);
int runAheadFrames = 1; // How many frames to run ahead
while (!quit) {
GFX_startFrame();

core.run();
if(doRunAhead) {
retro_video_refresh_t saved_video = video_refresh_callback;
retro_audio_sample_t saved_audio = audio_sample_callback;
retro_audio_sample_batch_t saved_batch = audio_sample_batch_callback;
retro_input_state_t saved_input = input_state_callback;

core.serialize(base_state, max_state_size);

set_video_refresh_callback(fakeVideoCall);
set_audio_sample_callback(fakeAudioCall);
set_audio_sample_batch_callback(fakeBatchCall);
set_input_state_callback(fake_input_callback);

core.unserialize(base_state, max_state_size);

for (int i = 0; i < runAheadFrames; i++) {
core.run();
}

set_video_refresh_callback(saved_video);
set_audio_sample_callback(saved_audio);
set_audio_sample_batch_callback(saved_batch);
set_input_state_callback(saved_input);

core.unserialize(base_state, max_state_size);
doRunAhead = 0;
}
core.run(); // Visible frame, synced to real time via your FPS limiter

limitFF();
trackFPS();


if (has_pending_opt_change) {
has_pending_opt_change = 0;
Expand Down