void wait_for_input(void) { printf("\n\nPress Start.\n\n"); fflush(stdout); while(aptMainLoop()) { u32 kDown; hidScanInput(); kDown = hidKeysDown(); if (kDown & KEY_START) break; if (kDown & KEY_SELECT) exit(0); #if 0 select_pressed = true; #endif retro_sleep(1); } }
void MCPHookClose() { if (mcp_hook_fd < 0) return; //close down wupserver, return control to mcp IOSUHAX_Close(); //wait for mcp to return retro_sleep(1000); IOS_Close(mcp_hook_fd); mcp_hook_fd = -1; }
static void emscripten_mainloop(void) { unsigned sleep_ms = 0; int ret = runloop_iterate(&sleep_ms); if (ret == 1 && sleep_ms > 0) retro_sleep(sleep_ms); runloop_ctl(RUNLOOP_CTL_DATA_ITERATE, NULL); if (ret != -1) return; main_exit(NULL); exit(0); }
static void emscripten_mainloop(void) { unsigned sleep_ms = 0; int ret = runloop_iterate(&sleep_ms); if (ret == 1 && sleep_ms > 0) retro_sleep(sleep_ms); task_queue_ctl(TASK_QUEUE_CTL_CHECK, NULL); if (ret != -1) return; main_exit(NULL); exit(0); }
static void threaded_worker(void *userdata) { (void)userdata; for (;;) { retro_task_t *task = NULL; if (!worker_continue) break; /* should we keep running until all tasks finished? */ slock_lock(running_lock); /* Get first task to run */ task = tasks_running.front; if (task == NULL) { scond_wait(worker_cond, running_lock); slock_unlock(running_lock); continue; } slock_unlock(running_lock); task->handler(task); slock_lock(running_lock); task_queue_remove(&tasks_running, task); slock_unlock(running_lock); /* Update queue */ if (!task->finished) { /* Re-add task to running queue */ retro_task_threaded_push_running(task); } else { /* Add task to finished queue */ slock_lock(finished_lock); task_queue_put(&tasks_finished, task); slock_unlock(finished_lock); } #if 0 retro_sleep(10); #endif } slock_unlock(running_lock); }
/** * main_entry: * * Main function of RetroArch. * * If HAVE_MAIN is not defined, will contain main loop and will not * be exited from until we exit the program. Otherwise, will * just do initialization. * * Returns: varies per platform. **/ int rarch_main(int argc, char *argv[], void *data) { void *args = (void*)data; #ifndef HAVE_MAIN int ret = 0; #endif rarch_ctl(RARCH_CTL_PREINIT, NULL); frontend_driver_init_first(args); rarch_ctl(RARCH_CTL_INIT, NULL); if (frontend_driver_is_inited()) { content_ctx_info_t info; info.argc = argc; info.argv = argv; info.args = args; info.environ_get = frontend_driver_environment_get_ptr(); if (!task_push_content_load_default( NULL, NULL, &info, CORE_TYPE_PLAIN, CONTENT_MODE_LOAD_FROM_CLI, NULL, NULL)) return 0; } ui_companion_driver_init_first(); #ifndef HAVE_MAIN do { unsigned sleep_ms = 0; ret = runloop_iterate(&sleep_ms); if (ret == 1 && sleep_ms > 0) retro_sleep(sleep_ms); task_queue_ctl(TASK_QUEUE_CTL_CHECK, NULL); }while(ret != -1); main_exit(args); #endif return 0; }
/** * task_http_iterate_transfer: * * Resumes HTTP transfer update. * * Returns: 0 when finished, -1 when we should continue * with the transfer on the next frame. **/ static int task_http_iterate_transfer(retro_task_t *task) { http_handle_t *http = (http_handle_t*)task->state; size_t pos = 0, tot = 0; /* FIXME: This wouldn't be needed if we could wait for a timeout */ if (task_queue_is_threaded()) retro_sleep(1); if (!net_http_update(http->handle, &pos, &tot)) { task_set_progress(task, (tot == 0) ? -1 : (signed)(pos * 100 / tot)); return -1; } return 0; }
bool retro_load_game(const struct retro_game_info* game) { init_descriptors(); check_variables(); uint8_t bios_data[256]; char bios_path[PATH_MAX_LENGTH]; char* system_dir; if(environ_cb(RETRO_ENVIRONMENT_GET_SYSTEM_DIRECTORY, &system_dir) && system_dir) strncpy(bios_path, system_dir, sizeof(bios_path)); else if (game->path) strncpy(bios_path, game->path, sizeof(bios_path)); else strncpy(bios_path, ".", sizeof(bios_path)); #if defined(_WIN32) char slash = '\\'; #else char slash = '/'; #endif char* tmp = strrchr(bios_path, slash); if(!tmp) tmp = strrchr(bios_path, '\0'); *tmp++ = slash; strcpy(tmp, "gbbios.gb"); retro_sleep(10); fflush(stdout); gbemu_printf("romd info\n"); gbemu_printf("path : %s\n", game->path); gbemu_printf("size : %u\n", game->size); fflush(stdout); gbemu_printf("loading bios from : %s\n", bios_path); FILE* fp = fopen(bios_path, "rb"); if(fp) { fread(bios_data, 1, sizeof(bios_data), fp); fclose(fp); } else gbemu_printf("bios not found !\n"); gbemu_load_game(game->data, game->size, fp? bios_data: NULL); return true; }
void gbemu_wait_for_input(void) { if(!poll_cb || !input_cb) return; printf("press START\n"); fflush(stdout); do { retro_sleep(50); poll_cb(); if(input_cb(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_SELECT)) exit(0); } while(!input_cb(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_START)); }
int MCPHookOpen() { //take over mcp thread mcp_hook_fd = IOS_Open("/dev/mcp", 0); if (mcp_hook_fd < 0) return -1; IOS_IoctlAsync(mcp_hook_fd, 0x62, (void *)0, 0, (void *)0, 0, someFunc, (void *)0); //let wupserver start up retro_sleep(1000); if (IOSUHAX_Open("/dev/mcp") < 0) { IOS_Close(mcp_hook_fd); mcp_hook_fd = -1; return -1; } return 0; }
/** * runloop_iterate: * * Run Libretro core in RetroArch for one frame. * * Returns: 0 on success, 1 if we have to wait until button input in order * to wake up the loop, -1 if we forcibly quit out of the RetroArch iteration loop. **/ int runloop_iterate(unsigned *sleep_ms) { unsigned i; event_cmd_state_t cmd; event_cmd_state_t *cmd_ptr = &cmd; retro_time_t current, target, to_sleep_ms; static retro_usec_t frame_time_last = 0; static retro_time_t frame_limit_minimum_time = 0.0; static retro_time_t frame_limit_last_time = 0.0; static retro_input_t last_input = 0; settings_t *settings = config_get_ptr(); global_t *global = global_get_ptr(); rarch_system_info_t *system = NULL; cmd.state[1] = last_input; cmd.state[0] = input_keys_pressed(); last_input = cmd.state[0]; runloop_ctl(RUNLOOP_CTL_SYSTEM_INFO_GET, &system); if (runloop_ctl(RUNLOOP_CTL_IS_FRAME_TIME_LAST, NULL)) { frame_time_last = 0; runloop_ctl(RUNLOOP_CTL_UNSET_FRAME_TIME_LAST, NULL); } if (runloop_ctl(RUNLOOP_CTL_SHOULD_SET_FRAME_LIMIT, NULL)) { struct retro_system_av_info *av_info = video_viewport_get_system_av_info(); float fastforward_ratio = (settings->fastforward_ratio == 0.0f) ? 1.0f : settings->fastforward_ratio; frame_limit_last_time = retro_get_time_usec(); frame_limit_minimum_time = (retro_time_t)roundf(1000000.0f / (av_info->timing.fps * fastforward_ratio)); runloop_ctl(RUNLOOP_CTL_UNSET_FRAME_LIMIT, NULL); } if (input_driver_ctl(RARCH_INPUT_CTL_IS_FLUSHING_INPUT, NULL)) { input_driver_ctl(RARCH_INPUT_CTL_UNSET_FLUSHING_INPUT, NULL); if (cmd.state[0]) { cmd.state[0] = 0; /* If core was paused before entering menu, evoke * pause toggle to wake it up. */ if (runloop_ctl(RUNLOOP_CTL_IS_PAUSED, NULL)) BIT64_SET(cmd.state[0], RARCH_PAUSE_TOGGLE); input_driver_ctl(RARCH_INPUT_CTL_SET_FLUSHING_INPUT, NULL); } } if (system->frame_time.callback) { /* Updates frame timing if frame timing callback is in use by the core. * Limits frame time if fast forward ratio throttle is enabled. */ bool is_slowmotion; retro_time_t current = retro_get_time_usec(); retro_time_t delta = current - frame_time_last; bool is_locked_fps = (runloop_ctl(RUNLOOP_CTL_IS_PAUSED, NULL) || input_driver_ctl(RARCH_INPUT_CTL_IS_NONBLOCK_STATE, NULL)) | !!recording_driver_get_data_ptr(); runloop_ctl(RUNLOOP_CTL_IS_SLOWMOTION, &is_slowmotion); if (!frame_time_last || is_locked_fps) delta = system->frame_time.reference; if (!is_locked_fps && is_slowmotion) delta /= settings->slowmotion_ratio; frame_time_last = current; if (is_locked_fps) frame_time_last = 0; system->frame_time.callback(delta); } cmd.state[2] = cmd.state[0] & ~cmd.state[1]; /* trigger */ if (runloop_cmd_triggered(cmd_ptr, RARCH_OVERLAY_NEXT)) event_command(EVENT_CMD_OVERLAY_NEXT); if (runloop_cmd_triggered(cmd_ptr, RARCH_FULLSCREEN_TOGGLE_KEY)) { bool fullscreen_toggled = !runloop_ctl(RUNLOOP_CTL_IS_PAUSED, NULL); #ifdef HAVE_MENU fullscreen_toggled = fullscreen_toggled || menu_driver_ctl(RARCH_MENU_CTL_IS_ALIVE, NULL); #endif if (fullscreen_toggled) event_command(EVENT_CMD_FULLSCREEN_TOGGLE); } if (runloop_cmd_triggered(cmd_ptr, RARCH_GRAB_MOUSE_TOGGLE)) event_command(EVENT_CMD_GRAB_MOUSE_TOGGLE); #ifdef HAVE_MENU if (runloop_cmd_menu_press(cmd_ptr) || (global->inited.core.type == CORE_TYPE_DUMMY)) { if (menu_driver_ctl(RARCH_MENU_CTL_IS_ALIVE, NULL)) { if (global->inited.main && (global->inited.core.type != CORE_TYPE_DUMMY)) rarch_ctl(RARCH_CTL_MENU_RUNNING_FINISHED, NULL); } else rarch_ctl(RARCH_CTL_MENU_RUNNING, NULL); } #endif #ifdef HAVE_OVERLAY runloop_iterate_linefeed_overlay(settings); #endif if (runloop_iterate_time_to_exit(runloop_cmd_press(cmd_ptr, RARCH_QUIT_KEY)) != 1) { frame_limit_last_time = 0.0; return -1; } #ifdef HAVE_MENU if (menu_driver_ctl(RARCH_MENU_CTL_IS_ALIVE, NULL)) { bool focused = runloop_ctl(RUNLOOP_CTL_CHECK_FOCUS, NULL) && !ui_companion_is_on_foreground(); bool is_idle = runloop_ctl(RUNLOOP_CTL_IS_IDLE, NULL); if (menu_driver_iterate((enum menu_action)menu_input_frame_retropad(cmd.state[0], cmd.state[2])) == -1) rarch_ctl(RARCH_CTL_MENU_RUNNING_FINISHED, NULL); if (focused || !is_idle) menu_driver_ctl(RARCH_MENU_CTL_RENDER, NULL); if (!focused || is_idle) { *sleep_ms = 10; return 1; } goto end; } #endif if (!runloop_ctl(RUNLOOP_CTL_CHECK_STATE, &cmd)) { /* RetroArch has been paused. */ retro_ctx.poll_cb(); *sleep_ms = 10; return 1; } #if defined(HAVE_THREADS) lock_autosave(); #endif #ifdef HAVE_NETPLAY netplay_driver_ctl(RARCH_NETPLAY_CTL_PRE_FRAME, NULL); #endif if (bsv_movie_ctl(BSV_MOVIE_CTL_IS_INITED, NULL)) bsv_movie_ctl(BSV_MOVIE_CTL_SET_FRAME_START, NULL); if (system->camera_callback.caps) driver_camera_poll(); /* Update binds for analog dpad modes. */ for (i = 0; i < settings->input.max_users; i++) { if (!settings->input.analog_dpad_mode[i]) continue; input_push_analog_dpad(settings->input.binds[i], settings->input.analog_dpad_mode[i]); input_push_analog_dpad(settings->input.autoconf_binds[i], settings->input.analog_dpad_mode[i]); } if ((settings->video.frame_delay > 0) && !input_driver_ctl(RARCH_INPUT_CTL_IS_NONBLOCK_STATE, NULL)) retro_sleep(settings->video.frame_delay); /* Run libretro for one frame. */ core.retro_run(); #ifdef HAVE_CHEEVOS /* Test the achievements. */ cheevos_test(); #endif for (i = 0; i < settings->input.max_users; i++) { if (!settings->input.analog_dpad_mode[i]) continue; input_pop_analog_dpad(settings->input.binds[i]); input_pop_analog_dpad(settings->input.autoconf_binds[i]); } if (bsv_movie_ctl(BSV_MOVIE_CTL_IS_INITED, NULL)) bsv_movie_ctl(BSV_MOVIE_CTL_SET_FRAME_END, NULL); #ifdef HAVE_NETPLAY netplay_driver_ctl(RARCH_NETPLAY_CTL_POST_FRAME, NULL); #endif #if defined(HAVE_THREADS) unlock_autosave(); #endif #ifdef HAVE_MENU end: #endif if (!settings->fastforward_ratio) return 0; current = retro_get_time_usec(); target = frame_limit_last_time + frame_limit_minimum_time; to_sleep_ms = (target - current) / 1000; if (to_sleep_ms > 0) { *sleep_ms = (unsigned)to_sleep_ms; /* Combat jitter a bit. */ frame_limit_last_time += frame_limit_minimum_time; return 1; } frame_limit_last_time = retro_get_time_usec(); return 0; }
/** * runloop_iterate: * * Run Libretro core in RetroArch for one frame. * * Returns: 0 on success, 1 if we have to wait until * button input in order to wake up the loop, * -1 if we forcibly quit out of the RetroArch iteration loop. **/ int runloop_iterate(unsigned *sleep_ms) { unsigned i; event_cmd_state_t cmd; retro_time_t current, target, to_sleep_ms; static retro_input_t last_input = {0}; event_cmd_state_t *cmd_ptr = &cmd; static retro_time_t frame_limit_minimum_time = 0.0; static retro_time_t frame_limit_last_time = 0.0; settings_t *settings = config_get_ptr(); cmd.state[1] = last_input; cmd.state[0] = input_keys_pressed(); last_input = cmd.state[0]; runloop_ctl(RUNLOOP_CTL_UNSET_FRAME_TIME_LAST, NULL); if (runloop_ctl(RUNLOOP_CTL_SHOULD_SET_FRAME_LIMIT, NULL)) { struct retro_system_av_info *av_info = video_viewport_get_system_av_info(); float fastforward_ratio = (settings->fastforward_ratio == 0.0f) ? 1.0f : settings->fastforward_ratio; frame_limit_last_time = cpu_features_get_time_usec(); frame_limit_minimum_time = (retro_time_t)roundf(1000000.0f / (av_info->timing.fps * fastforward_ratio)); runloop_ctl(RUNLOOP_CTL_UNSET_FRAME_LIMIT, NULL); } if (input_driver_is_flushing_input()) { input_driver_unset_flushing_input(); if (cmd.state[0].state) { cmd.state[0].state = 0; /* If core was paused before entering menu, evoke * pause toggle to wake it up. */ if (runloop_ctl(RUNLOOP_CTL_IS_PAUSED, NULL)) BIT64_SET(cmd.state[0].state, RARCH_PAUSE_TOGGLE); input_driver_set_flushing_input(); } } if (runloop_frame_time.callback) { /* Updates frame timing if frame timing callback is in use by the core. * Limits frame time if fast forward ratio throttle is enabled. */ retro_time_t current = cpu_features_get_time_usec(); retro_time_t delta = current - runloop_frame_time_last; bool is_locked_fps = (runloop_ctl(RUNLOOP_CTL_IS_PAUSED, NULL) || input_driver_is_nonblock_state()) | !!recording_driver_get_data_ptr(); if (!runloop_frame_time_last || is_locked_fps) delta = runloop_frame_time.reference; if (!is_locked_fps && runloop_ctl(RUNLOOP_CTL_IS_SLOWMOTION, NULL)) delta /= settings->slowmotion_ratio; runloop_frame_time_last = current; if (is_locked_fps) runloop_frame_time_last = 0; runloop_frame_time.callback(delta); } cmd.state[2].state = cmd.state[0].state & ~cmd.state[1].state; /* trigger */ if (runloop_cmd_triggered(cmd_ptr, RARCH_OVERLAY_NEXT)) command_event(CMD_EVENT_OVERLAY_NEXT, NULL); if (runloop_cmd_triggered(cmd_ptr, RARCH_FULLSCREEN_TOGGLE_KEY)) { bool fullscreen_toggled = !runloop_ctl(RUNLOOP_CTL_IS_PAUSED, NULL); #ifdef HAVE_MENU fullscreen_toggled = fullscreen_toggled || menu_driver_ctl(RARCH_MENU_CTL_IS_ALIVE, NULL); #endif if (fullscreen_toggled) command_event(CMD_EVENT_FULLSCREEN_TOGGLE, NULL); } if (runloop_cmd_triggered(cmd_ptr, RARCH_GRAB_MOUSE_TOGGLE)) command_event(CMD_EVENT_GRAB_MOUSE_TOGGLE, NULL); #ifdef HAVE_MENU if (runloop_cmd_menu_press(cmd_ptr) || rarch_ctl(RARCH_CTL_IS_DUMMY_CORE, NULL)) { if (menu_driver_ctl(RARCH_MENU_CTL_IS_ALIVE, NULL)) { if (rarch_ctl(RARCH_CTL_IS_INITED, NULL) && !rarch_ctl(RARCH_CTL_IS_DUMMY_CORE, NULL)) rarch_ctl(RARCH_CTL_MENU_RUNNING_FINISHED, NULL); } else rarch_ctl(RARCH_CTL_MENU_RUNNING, NULL); } #endif #ifdef HAVE_OVERLAY runloop_iterate_linefeed_overlay(settings); #endif if (runloop_iterate_time_to_exit( runloop_cmd_press(cmd_ptr, RARCH_QUIT_KEY)) != 1) { frame_limit_last_time = 0.0; return -1; } #ifdef HAVE_MENU if (menu_driver_ctl(RARCH_MENU_CTL_IS_ALIVE, NULL)) { int ret = runloop_iterate_menu((enum menu_action) menu_input_frame_retropad(cmd.state[0], cmd.state[2]), sleep_ms); if (ret == -1) goto end; return ret; } #endif if (!runloop_check_state(&cmd, &runloop_shader_dir)) { /* RetroArch has been paused. */ core_poll(); *sleep_ms = 10; return 1; } #if defined(HAVE_THREADS) autosave_lock(); #endif #ifdef HAVE_NETPLAY netplay_driver_ctl(RARCH_NETPLAY_CTL_PRE_FRAME, NULL); #endif if (bsv_movie_ctl(BSV_MOVIE_CTL_IS_INITED, NULL)) bsv_movie_ctl(BSV_MOVIE_CTL_SET_FRAME_START, NULL); camera_driver_ctl(RARCH_CAMERA_CTL_POLL, NULL); /* Update binds for analog dpad modes. */ for (i = 0; i < settings->input.max_users; i++) { if (!settings->input.analog_dpad_mode[i]) continue; input_push_analog_dpad(settings->input.binds[i], settings->input.analog_dpad_mode[i]); input_push_analog_dpad(settings->input.autoconf_binds[i], settings->input.analog_dpad_mode[i]); } if ((settings->video.frame_delay > 0) && !input_driver_is_nonblock_state()) retro_sleep(settings->video.frame_delay); core_run(); #ifdef HAVE_CHEEVOS cheevos_test(); #endif for (i = 0; i < settings->input.max_users; i++) { if (!settings->input.analog_dpad_mode[i]) continue; input_pop_analog_dpad(settings->input.binds[i]); input_pop_analog_dpad(settings->input.autoconf_binds[i]); } if (bsv_movie_ctl(BSV_MOVIE_CTL_IS_INITED, NULL)) bsv_movie_ctl(BSV_MOVIE_CTL_SET_FRAME_END, NULL); #ifdef HAVE_NETPLAY netplay_driver_ctl(RARCH_NETPLAY_CTL_POST_FRAME, NULL); #endif #if defined(HAVE_THREADS) autosave_unlock(); #endif if (!settings->fastforward_ratio) return 0; #ifdef HAVE_MENU end: #endif current = cpu_features_get_time_usec(); target = frame_limit_last_time + frame_limit_minimum_time; to_sleep_ms = (target - current) / 1000; if (to_sleep_ms > 0) { *sleep_ms = (unsigned)to_sleep_ms; /* Combat jitter a bit. */ frame_limit_last_time += frame_limit_minimum_time; return 1; } frame_limit_last_time = cpu_features_get_time_usec(); return 0; }
int main(int argc, char **argv) { #else int __entry_menu(int argc, char **argv) { InitFunctionPointers(); #endif #if 1 setup_os_exceptions(); #else InstallExceptionHandler(); #endif socket_lib_init(); #if defined(PC_DEVELOPMENT_IP_ADDRESS) && defined(PC_DEVELOPMENT_TCP_PORT) log_init(PC_DEVELOPMENT_IP_ADDRESS, PC_DEVELOPMENT_TCP_PORT); #endif devoptab_list[STD_OUT] = &dotab_stdout; devoptab_list[STD_ERR] = &dotab_stdout; memoryInitialize(); mount_sd_fat("sd"); VPADInit(); verbosity_enable(); DEBUG_VAR(argc); DEBUG_STR(argv[0]); DEBUG_STR(argv[1]); #if 0 int argc_ = 2; // char* argv_[] = {WIIU_SD_PATH "retroarch/retroarch.elf", WIIU_SD_PATH "rom.nes", NULL}; char* argv_[] = {WIIU_SD_PATH "retroarch/retroarch.elf", WIIU_SD_PATH "rom.sfc", NULL}; rarch_main(argc_, argv_, NULL); #else rarch_main(argc, argv, NULL); #endif // int frames = 0; do { unsigned sleep_ms = 0; int ret = runloop_iterate(&sleep_ms); if (ret == 1 && sleep_ms > 0) retro_sleep(sleep_ms); task_queue_ctl(TASK_QUEUE_CTL_WAIT, NULL); if (ret == -1) break; }while(1); // }while(frames++ < 300); main_exit(NULL); unmount_sd_fat("sd"); memoryRelease(); fflush(stdout); fflush(stderr); #if defined(PC_DEVELOPMENT_IP_ADDRESS) && defined(PC_DEVELOPMENT_TCP_PORT) log_deinit(); #endif return 0; }
/** * rarch_main_iterate: * * Run Libretro core in RetroArch for one frame. * * Returns: 0 on success, 1 if we have to wait until button input in order * to wake up the loop, -1 if we forcibly quit out of the RetroArch iteration loop. **/ int rarch_main_iterate(unsigned *sleep_ms) { int ret; unsigned i; retro_input_t trigger_input; event_cmd_state_t cmd; retro_time_t current, target, to_sleep_ms; static retro_input_t last_input = 0; driver_t *driver = driver_get_ptr(); settings_t *settings = config_get_ptr(); global_t *global = global_get_ptr(); retro_input_t input = input_keys_pressed(driver, settings, global); rarch_system_info_t *system = rarch_system_info_get_ptr(); retro_input_t old_input = last_input; last_input = input; if (driver->flushing_input) { driver->flushing_input = false; if (input) { input = 0; /* If core was paused before entering menu, evoke * pause toggle to wake it up. */ if (main_is_paused) BIT64_SET(input, RARCH_PAUSE_TOGGLE); driver->flushing_input = true; } } trigger_input = input & ~old_input; rarch_main_cmd_get_state(driver, settings, &cmd, input, old_input, trigger_input); if (system->frame_time.callback) { /* Updates frame timing if frame timing callback is in use by the core. * Limits frame time if fast forward ratio throttle is enabled. */ retro_time_t current = retro_get_time_usec(); retro_time_t delta = current - system->frame_time_last; bool is_locked_fps = (main_is_paused || driver->nonblock_state) | !!driver->recording_data; if (!system->frame_time_last || is_locked_fps) delta = system->frame_time.reference; if (!is_locked_fps && main_is_slowmotion) delta /= settings->slowmotion_ratio; system->frame_time_last = current; if (is_locked_fps) system->frame_time_last = 0; system->frame_time.callback(delta); } if (cmd.overlay_next_pressed) event_command(EVENT_CMD_OVERLAY_NEXT); if (!main_is_paused || menu_driver_alive()) { if (cmd.fullscreen_toggle) event_command(EVENT_CMD_FULLSCREEN_TOGGLE); } if (cmd.grab_mouse_pressed) event_command(EVENT_CMD_GRAB_MOUSE_TOGGLE); #ifdef HAVE_MENU if (cmd.menu_pressed || (global->inited.core.type == CORE_TYPE_DUMMY)) { if (menu_driver_alive()) { if (global->inited.main && (global->inited.core.type != CORE_TYPE_DUMMY)) rarch_ctl(RARCH_ACTION_STATE_MENU_RUNNING_FINISHED, NULL); } else rarch_ctl(RARCH_ACTION_STATE_MENU_RUNNING, NULL); } #endif #ifdef HAVE_OVERLAY rarch_main_iterate_linefeed_overlay(driver, settings); #endif ret = rarch_main_iterate_time_to_exit(&cmd); if (ret != 1) return -1; #ifdef HAVE_MENU if (menu_driver_alive()) { if (menu_driver_iterate((enum menu_action)menu_input_frame(input, trigger_input)) == -1) rarch_ctl(RARCH_ACTION_STATE_MENU_RUNNING_FINISHED, NULL); if (!input && settings->menu.pause_libretro) return 1; goto end; } #endif if (!rarch_main_ctl(RARCH_MAIN_CTL_CHECK_STATE, &cmd)) { /* RetroArch has been paused. */ driver->retro_ctx.poll_cb(); *sleep_ms = 10; return 1; } #if defined(HAVE_THREADS) lock_autosave(); #endif #ifdef HAVE_NETPLAY if (driver->netplay_data) netplay_pre_frame((netplay_t*)driver->netplay_data); #endif if (global->bsv.movie) bsv_movie_set_frame_start(global->bsv.movie); if (system->camera_callback.caps) driver_camera_poll(); /* Update binds for analog dpad modes. */ for (i = 0; i < settings->input.max_users; i++) { if (!settings->input.analog_dpad_mode[i]) continue; input_push_analog_dpad(settings->input.binds[i], settings->input.analog_dpad_mode[i]); input_push_analog_dpad(settings->input.autoconf_binds[i], settings->input.analog_dpad_mode[i]); } if ((settings->video.frame_delay > 0) && !driver->nonblock_state) retro_sleep(settings->video.frame_delay); /* Run libretro for one frame. */ core.retro_run(); #ifdef HAVE_CHEEVOS /* Test the achievements. */ cheevos_test(); #endif for (i = 0; i < settings->input.max_users; i++) { if (!settings->input.analog_dpad_mode[i]) continue; input_pop_analog_dpad(settings->input.binds[i]); input_pop_analog_dpad(settings->input.autoconf_binds[i]); } if (global->bsv.movie) bsv_movie_set_frame_end(global->bsv.movie); #ifdef HAVE_NETPLAY if (driver->netplay_data) netplay_post_frame((netplay_t*)driver->netplay_data); #endif #if defined(HAVE_THREADS) unlock_autosave(); #endif #ifdef HAVE_MENU end: #endif if (!settings->fastforward_ratio) return 0; current = retro_get_time_usec(); target = frame_limit_last_time + frame_limit_minimum_time; to_sleep_ms = (target - current) / 1000; if (to_sleep_ms > 0) { *sleep_ms = (unsigned)to_sleep_ms; /* Combat jitter a bit. */ frame_limit_last_time += frame_limit_minimum_time; return 1; } frame_limit_last_time = retro_get_time_usec(); return 0; }
static void dsound_thread(void *data) { DWORD write_ptr; dsound_t *ds = (dsound_t*)data; SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL); get_positions(ds, NULL, &write_ptr); write_ptr = (write_ptr + ds->buffer_size / 2) % ds->buffer_size; while (ds->thread_alive) { struct audio_lock region; DWORD read_ptr, avail, fifo_avail; get_positions(ds, &read_ptr, NULL); avail = write_avail(read_ptr, write_ptr, ds->buffer_size); EnterCriticalSection(&ds->crit); fifo_avail = fifo_read_avail(ds->buffer); LeaveCriticalSection(&ds->crit); if (avail < CHUNK_SIZE || ((fifo_avail < CHUNK_SIZE) && (avail < ds->buffer_size / 2))) { /* No space to write, or we don't have data in our fifo, * but we can wait some time before it underruns ... */ /* We could opt for using the notification interface, * but it is not guaranteed to work, so use high * priority sleeping patterns. */ retro_sleep(1); continue; } if (!grab_region(ds, write_ptr, ®ion)) { ds->thread_alive = false; SetEvent(ds->event); break; } if (fifo_avail < CHUNK_SIZE) { /* Got space to write, but nothing in FIFO (underrun), * fill block with silence. */ memset(region.chunk1, 0, region.size1); memset(region.chunk2, 0, region.size2); release_region(ds, ®ion); write_ptr = (write_ptr + region.size1 + region.size2) % ds->buffer_size; } else { /* All is good. Pull from it and notify FIFO. */ EnterCriticalSection(&ds->crit); if (region.chunk1) fifo_read(ds->buffer, region.chunk1, region.size1); if (region.chunk2) fifo_read(ds->buffer, region.chunk2, region.size2); LeaveCriticalSection(&ds->crit); release_region(ds, ®ion); write_ptr = (write_ptr + region.size1 + region.size2) % ds->buffer_size; SetEvent(ds->event); } } ExitThread(0); }
/** * main_entry: * * Main function of RetroArch. * * If HAVE_MAIN is not defined, will contain main loop and will not * be exited from until we exit the program. Otherwise, will * just do initialization. * * Returns: varies per platform. **/ int rarch_main(int argc, char *argv[], void *data) { void *args = (void*)data; int ret = 0; settings_t *settings = NULL; rarch_ctl(RARCH_CTL_PREINIT, NULL); frontend_driver_init_first(args); rarch_ctl(RARCH_CTL_INIT, NULL); #ifdef HAVE_THREADS async_jobs = async_job_new(); #endif if (frontend_driver_is_inited()) { ret = main_load_content(argc, argv, args, frontend_driver_environment_get_ptr()); if (!ret) return ret; } event_cmd_ctl(EVENT_CMD_HISTORY_INIT, NULL); settings = config_get_ptr(); if (settings->history_list_enable) { char *fullpath = NULL; rarch_system_info_t *system = NULL; runloop_ctl(RUNLOOP_CTL_SYSTEM_INFO_GET, &system); runloop_ctl(RUNLOOP_CTL_GET_CONTENT_PATH, &fullpath); if (content_ctl(CONTENT_CTL_IS_INITED, NULL) || system->no_content) history_playlist_push( g_defaults.history, fullpath, settings->libretro, system ? &system->info : NULL); } ui_companion_driver_init_first(); #ifndef HAVE_MAIN do { unsigned sleep_ms = 0; ret = runloop_iterate(&sleep_ms); if (ret == 1 && sleep_ms > 0) retro_sleep(sleep_ms); runloop_ctl(RUNLOOP_CTL_DATA_ITERATE, NULL); }while(ret != -1); main_exit(args); #endif #ifdef HAVE_THREADS async_job_free(async_jobs); async_jobs = NULL; #endif return 0; }
/** * runloop_iterate: * * Run Libretro core in RetroArch for one frame. * * Returns: 0 on success, 1 if we have to wait until * button input in order to wake up the loop, * -1 if we forcibly quit out of the RetroArch iteration loop. **/ int runloop_iterate(unsigned *sleep_ms) { unsigned i; retro_time_t current, target, to_sleep_ms; static uint64_t last_input = 0; enum runloop_state runloop_status = RUNLOOP_STATE_NONE; static retro_time_t frame_limit_minimum_time = 0.0; static retro_time_t frame_limit_last_time = 0.0; settings_t *settings = config_get_ptr(); uint64_t current_input = menu_driver_ctl(RARCH_MENU_CTL_IS_ALIVE, NULL) ? input_menu_keys_pressed() : input_keys_pressed(); uint64_t old_input = last_input; last_input = current_input; if (runloop_frame_time_last_enable) { runloop_frame_time_last = 0; runloop_frame_time_last_enable = false; } if (runloop_set_frame_limit) { struct retro_system_av_info *av_info = video_viewport_get_system_av_info(); float fastforward_ratio = (settings->fastforward_ratio == 0.0f) ? 1.0f : settings->fastforward_ratio; frame_limit_last_time = cpu_features_get_time_usec(); frame_limit_minimum_time = (retro_time_t)roundf(1000000.0f / (av_info->timing.fps * fastforward_ratio)); runloop_set_frame_limit = false; } if (runloop_frame_time.callback) { /* Updates frame timing if frame timing callback is in use by the core. * Limits frame time if fast forward ratio throttle is enabled. */ retro_time_t current = cpu_features_get_time_usec(); retro_time_t delta = current - runloop_frame_time_last; bool is_locked_fps = (runloop_paused || input_driver_is_nonblock_state()) | !!recording_driver_get_data_ptr(); if (!runloop_frame_time_last || is_locked_fps) delta = runloop_frame_time.reference; if (!is_locked_fps && runloop_slowmotion) delta /= settings->slowmotion_ratio; runloop_frame_time_last = current; if (is_locked_fps) runloop_frame_time_last = 0; runloop_frame_time.callback(delta); } runloop_status = runloop_check_state(settings, current_input, old_input, sleep_ms); switch (runloop_status) { case RUNLOOP_STATE_QUIT: frame_limit_last_time = 0.0; command_event(CMD_EVENT_QUIT, NULL); return -1; case RUNLOOP_STATE_SLEEP: case RUNLOOP_STATE_END: case RUNLOOP_STATE_MENU_ITERATE: core_poll(); #ifdef HAVE_NETWORKING /* FIXME: This is an ugly way to tell Netplay this... */ netplay_driver_ctl(RARCH_NETPLAY_CTL_PAUSE, NULL); #endif if (runloop_status == RUNLOOP_STATE_SLEEP) *sleep_ms = 10; if (runloop_status == RUNLOOP_STATE_END) goto end; if (runloop_status == RUNLOOP_STATE_MENU_ITERATE) return 0; return 1; case RUNLOOP_STATE_ITERATE: case RUNLOOP_STATE_NONE: default: break; } autosave_lock(); if (bsv_movie_ctl(BSV_MOVIE_CTL_IS_INITED, NULL)) bsv_movie_ctl(BSV_MOVIE_CTL_SET_FRAME_START, NULL); camera_driver_ctl(RARCH_CAMERA_CTL_POLL, NULL); /* Update binds for analog dpad modes. */ for (i = 0; i < settings->input.max_users; i++) { if (!settings->input.analog_dpad_mode[i]) continue; input_push_analog_dpad(settings->input.binds[i], settings->input.analog_dpad_mode[i]); input_push_analog_dpad(settings->input.autoconf_binds[i], settings->input.analog_dpad_mode[i]); } if ((settings->video.frame_delay > 0) && !input_driver_is_nonblock_state()) retro_sleep(settings->video.frame_delay); core_run(); #ifdef HAVE_CHEEVOS cheevos_test(); #endif for (i = 0; i < settings->input.max_users; i++) { if (!settings->input.analog_dpad_mode[i]) continue; input_pop_analog_dpad(settings->input.binds[i]); input_pop_analog_dpad(settings->input.autoconf_binds[i]); } if (bsv_movie_ctl(BSV_MOVIE_CTL_IS_INITED, NULL)) bsv_movie_ctl(BSV_MOVIE_CTL_SET_FRAME_END, NULL); autosave_unlock(); if (!settings->fastforward_ratio) return 0; end: current = cpu_features_get_time_usec(); target = frame_limit_last_time + frame_limit_minimum_time; to_sleep_ms = (target - current) / 1000; if (to_sleep_ms > 0) { *sleep_ms = (unsigned)to_sleep_ms; /* Combat jitter a bit. */ frame_limit_last_time += frame_limit_minimum_time; return 1; } frame_limit_last_time = cpu_features_get_time_usec(); return 0; }
int main(int argc, char **argv) { #if 1 setup_os_exceptions(); #else InstallExceptionHandler(); #endif ProcUIInit(&SaveCallback); socket_lib_init(); #if defined(PC_DEVELOPMENT_IP_ADDRESS) && defined(PC_DEVELOPMENT_TCP_PORT) log_init(PC_DEVELOPMENT_IP_ADDRESS, PC_DEVELOPMENT_TCP_PORT); devoptab_list[STD_OUT] = &dotab_stdout; devoptab_list[STD_ERR] = &dotab_stdout; #endif #ifndef IS_SALAMANDER VPADInit(); WPADEnableURCC(true); WPADEnableWiiRemote(true); KPADInit(); #endif verbosity_enable(); printf("starting\n"); fflush(stdout); DEBUG_VAR(ARGV_PTR); if(ARGV_PTR && ((u32)ARGV_PTR < 0x01000000)) { struct { u32 magic; u32 argc; char * argv[3]; }*param = ARGV_PTR; if(param->magic == ARGV_MAGIC) { argc = param->argc; argv = param->argv; } ARGV_PTR = NULL; } DEBUG_VAR(argc); DEBUG_STR(argv[0]); DEBUG_STR(argv[1]); fflush(stdout); #ifdef IS_SALAMANDER int salamander_main(int, char **); salamander_main(argc, argv); #else #if 1 #if 0 int argc_ = 2; // char* argv_[] = {WIIU_SD_PATH "retroarch/retroarch.elf", WIIU_SD_PATH "rom.nes", NULL}; char *argv_[] = {WIIU_SD_PATH "retroarch/retroarch.elf", WIIU_SD_PATH "rom.sfc", NULL}; rarch_main(argc_, argv_, NULL); #else rarch_main(argc, argv, NULL); #endif do { unsigned sleep_ms = 0; int ret = runloop_iterate(&sleep_ms); if (ret == 1 && sleep_ms > 0) retro_sleep(sleep_ms); task_queue_ctl(TASK_QUEUE_CTL_WAIT, NULL); if (ret == -1) break; } while (1); main_exit(NULL); #endif #endif fflush(stdout); fflush(stderr); ProcUIShutdown(); #if defined(PC_DEVELOPMENT_IP_ADDRESS) && defined(PC_DEVELOPMENT_TCP_PORT) log_deinit(); #endif /* returning non 0 here can prevent loading a different rpx/elf in the HBL environment */ return 0; }
void gbemu_cpu_run(int cycles) { gbemu_cpu_t CPU = GB.CPU; CPU.cycles = 0; GB.APU.cycles = 0; GB.APU.write_pos = gbemu_sound_buffer; int cycles_last = 0; static int h_cycles = 0; next_instruction: gbemu_ppu_draw(CPU.cycles); gbemu_apu_run(CPU.cycles); CPU.timer.ticks += CPU.cycles - cycles_last; while (CPU.timer.ticks_last < CPU.timer.ticks) { CPU.timer.ticks_last++; if (!(CPU.timer.ticks_last & 0x3F)) GB.DIV++; if (GB.TAC.active) { /* 0: 0xFF * 1: 0x03 * 2: 0x0F * 3: 0x3F */ static const uint8_t timer_masks[4] = {0xFF, 0x03, 0x0F, 0x3F}; if (!(CPU.timer.ticks_last & timer_masks[GB.TAC.clock_select])) { GB.TIMA++; if (!GB.TIMA) { GB.TIMA = GB.TMA; GB.IF.timer = 1; } } } } if (CPU.cycles > cycles) goto cpu_exit; h_cycles += CPU.cycles - cycles_last; cycles_last = CPU.cycles; if (h_cycles > GB_LINE_TICK_COUNT) { h_cycles -= GB_LINE_TICK_COUNT; GB.LY++; if (GB.LY >= GB_V_COUNT) { GB.LY = 0; goto cpu_exit; } } if (GB.LCDC.LCD_enable) { if (GB.LY == GB.LYC) { if(!GB.LCD_STAT.LCY_eq_LY_flag) { GB.LCD_STAT.LCY_eq_LY_flag = 1; if(GB.LCD_STAT.LCY_eq_LY_IE) GB.IF.LCD_stat = 1; } } else GB.LCD_STAT.LCY_eq_LY_flag = 0; if (GB.LY < 144) { if (h_cycles > (80 + 20)) { if(GB.LCD_STAT.mode_flag != GB_LCD_STAT_MODE0_HBLANK) { GB.LCD_STAT.mode_flag = GB_LCD_STAT_MODE0_HBLANK; if(GB.LCD_STAT.HBlank_IE) GB.IF.LCD_stat = 1; } } else if (h_cycles > 20) { if(GB.LCD_STAT.mode_flag != GB_LCD_STAT_MODE3_OAM_VRAM_busy) GB.LCD_STAT.mode_flag = GB_LCD_STAT_MODE3_OAM_VRAM_busy; } else { if (GB.LCD_STAT.mode_flag != GB_LCD_STAT_MODE2_OAM_busy) { GB.LCD_STAT.mode_flag = GB_LCD_STAT_MODE2_OAM_busy; if(GB.LCD_STAT.OAM_IE) GB.IF.LCD_stat = 1; } } } else if (GB.LCD_STAT.mode_flag != GB_LCD_STAT_MODE1_VBLANK) { GB.LCD_STAT.mode_flag = GB_LCD_STAT_MODE1_VBLANK; GB.IF.Vblank = 1; if(GB.LCD_STAT.VBlank_IE) GB.IF.LCD_stat = 1; } } // if((GB.LCD_STAT.VBlank_IE && (GB.LCD_STAT.mode_flag == GB_LCD_STAT_MODE1_VBLANK)) || // (GB.LCD_STAT.HBlank_IE && (GB.LCD_STAT.mode_flag == GB_LCD_STAT_MODE0_HBLANK)) || // (GB.LCD_STAT.OAM_IE && (GB.LCD_STAT.mode_flag == GB_LCD_STAT_MODE2_OAM_busy)) || // (GB.LCD_STAT.LCY_eq_LY_IE && GB.LCD_STAT.LCY_eq_LY_flag)) // GB.IF.LCD_stat = 1; if(CPU.HALT) { if (GB.IF.Vblank || GB.IF.LCD_stat || GB.IF.timer || GB.IF.serial || GB.IF.joypad ) CPU_disable_halt(); else { CPU_cycles_inc(); goto next_instruction; } } if (CPU.IME) { if ((GB.IF.Vblank && GB.IE.Vblank) && GB.LCDC.LCD_enable) { CPU.IME = 0; GB.IF.Vblank = 0; CPU_INT(0x40); } else if (GB.IF.LCD_stat && GB.IE.LCD_stat) { CPU.IME = 0; GB.IF.LCD_stat = 0; CPU_INT(0x48); } else if (GB.IF.timer && GB.IE.timer) { CPU.IME = 0; GB.IF.timer = 0; CPU_INT(0x50); } else if (GB.IF.serial && GB.IE.serial) { CPU.IME = 0; GB.IF.serial = 0; CPU_INT(0x58); } else if (GB.IF.joypad && GB.IE.joypad) { CPU.IME = 0; GB.IF.joypad = 0; CPU_INT(0x60); } } //#define DISASM #define SKIP_COUNT 0x12000 //#define SKIP_COUNT 0xEEE9 // #define SKIP_COUNT 0x00049B4C //#define SKIP_COUNT 0xFFFFFFFF //#define SKIP_COUNT 0x00000000 static int total_exec = 0; #ifdef DISASM static bool force_disasm = false; #endif next_instruction_nocheck: #ifdef DISASM // if(CPU.PC == 0xC2B5) // if (CPU.PC >= 0x4000) // force_disasm = true; if (total_exec > SKIP_COUNT) { force_disasm = true; printf("0x%08X: ", total_exec); } if (force_disasm) { gbemu_disasm_current(&CPU, true); fflush(stdout); } #endif total_exec++; // if(GB.MEMORY[0xFF44] == 0x94) // fflush(stdout); // if ((CPU.AF == 0x810b)) // fflush(stdout); // if ((CPU.PC == 0xDEF8)) // fflush(stdout); // if ((CPU.PC == 0xC4C2) && (CPU.A == 0xF1)) // fflush(stdout); #ifdef USE_BIOS if(CPU.PC == 0x100) memcpy(GB.MEMORY, GB.BIOS, 0x100); #endif switch (GB_READ_PC()) { // NOP // case 0x7F: // case 0x40: // case 0x49: // case 0x52: // case 0x5B: // case 0x64: // case 0x6D: case 0x00: CPU_NOP(); case 0x08: CPU_LD_addr16_SP(); case 0x10: CPU_STOP(); case 0x18: CPU_JR(CPU_COND_ALWAYS); case 0x20: CPU_JR(CPU_COND_NZ); case 0x28: CPU_JR(CPU_COND_Z); case 0x30: CPU_JR(CPU_COND_NC); case 0x38: CPU_JR(CPU_COND_C); case 0x01: CPU_LD_rr_imm16(REG_BC); case 0x11: CPU_LD_rr_imm16(REG_DE); case 0x21: CPU_LD_rr_imm16(REG_HL); case 0x31: CPU_LD_rr_imm16(REG_SP); case 0x09: CPU_ADD_rr_rr(REG_HL, REG_BC); case 0x19: CPU_ADD_rr_rr(REG_HL, REG_DE); case 0x29: CPU_ADD_rr_rr(REG_HL, REG_HL); case 0x39: CPU_ADD_rr_rr(REG_HL, REG_SP); case 0x02: CPU_LD_raddr_r(REG_BC, REG_A); case 0x0A: CPU_LD_r_raddr(REG_A, REG_BC); case 0x12: CPU_LD_raddr_r(REG_DE, REG_A); case 0x1A: CPU_LD_r_raddr(REG_A, REG_DE); case 0x22: CPU_LD_raddr_r(REG_HL++, REG_A); case 0x2A: CPU_LD_r_raddr(REG_A, REG_HL++); case 0x32: CPU_LD_raddr_r(REG_HL--, REG_A); case 0x3A: CPU_LD_r_raddr(REG_A, REG_HL--); case 0x03: CPU_INC_rr(REG_BC); case 0x0B: CPU_DEC_rr(REG_BC); case 0x13: CPU_INC_rr(REG_DE); case 0x1B: CPU_DEC_rr(REG_DE); case 0x23: CPU_INC_rr(REG_HL); case 0x2B: CPU_DEC_rr(REG_HL); case 0x33: CPU_INC_rr(REG_SP); case 0x3B: CPU_DEC_rr(REG_SP); case 0x04: CPU_INC_r(REG_B); case 0x0C: CPU_INC_r(REG_C); case 0x14: CPU_INC_r(REG_D); case 0x1C: CPU_INC_r(REG_E); case 0x24: CPU_INC_r(REG_H); case 0x2C: CPU_INC_r(REG_L); case 0x34: CPU_INC_raddr(REG_HL); case 0x3C: CPU_INC_r(REG_A); case 0x05: CPU_DEC_r(REG_B); case 0x0D: CPU_DEC_r(REG_C); case 0x15: CPU_DEC_r(REG_D); case 0x1D: CPU_DEC_r(REG_E); case 0x25: CPU_DEC_r(REG_H); case 0x2D: CPU_DEC_r(REG_L); case 0x35: CPU_DEC_raddr(REG_HL); case 0x3D: CPU_DEC_r(REG_A); case 0x06: CPU_LD_r_imm8(REG_B); case 0x0E: CPU_LD_r_imm8(REG_C); case 0x16: CPU_LD_r_imm8(REG_D); case 0x1E: CPU_LD_r_imm8(REG_E); case 0x26: CPU_LD_r_imm8(REG_H); case 0x2E: CPU_LD_r_imm8(REG_L); case 0x36: CPU_LD_raddr_imm8(REG_HL); case 0x3E: CPU_LD_r_imm8(REG_A); case 0x07: CPU_RLCA(); case 0x0F: CPU_RRCA(); case 0x17: CPU_RLA(); case 0x1F: CPU_RRA(); case 0x27: CPU_DAA(); case 0x2F: CPU_CPL(); case 0x37: CPU_SCF(); case 0x3F: CPU_CCF(); // LD r1, r2 case 0x40: CPU_LD_r0_r1(CPU.B, CPU.B); case 0x41: CPU_LD_r0_r1(CPU.B, CPU.C); case 0x42: CPU_LD_r0_r1(CPU.B, CPU.D); case 0x43: CPU_LD_r0_r1(CPU.B, CPU.E); case 0x44: CPU_LD_r0_r1(CPU.B, CPU.H); case 0x45: CPU_LD_r0_r1(CPU.B, CPU.L); case 0x46: CPU_LD_r_raddr(CPU.B, CPU.HL); case 0x47: CPU_LD_r0_r1(CPU.B, CPU.A); case 0x48: CPU_LD_r0_r1(CPU.C, CPU.B); case 0x49: CPU_LD_r0_r1(CPU.C, CPU.C); case 0x4A: CPU_LD_r0_r1(CPU.C, CPU.D); case 0x4B: CPU_LD_r0_r1(CPU.C, CPU.E); case 0x4C: CPU_LD_r0_r1(CPU.C, CPU.H); case 0x4D: CPU_LD_r0_r1(CPU.C, CPU.L); case 0x4E: CPU_LD_r_raddr(CPU.C, CPU.HL); case 0x4F: CPU_LD_r0_r1(CPU.C, CPU.A); case 0x50: CPU_LD_r0_r1(CPU.D, CPU.B); case 0x51: CPU_LD_r0_r1(CPU.D, CPU.C); case 0x52: CPU_LD_r0_r1(CPU.D, CPU.D); case 0x53: CPU_LD_r0_r1(CPU.D, CPU.E); case 0x54: CPU_LD_r0_r1(CPU.D, CPU.H); case 0x55: CPU_LD_r0_r1(CPU.D, CPU.L); case 0x56: CPU_LD_r_raddr(CPU.D, CPU.HL); case 0x57: CPU_LD_r0_r1(CPU.D, CPU.A); case 0x58: CPU_LD_r0_r1(CPU.E, CPU.B); case 0x59: CPU_LD_r0_r1(CPU.E, CPU.C); case 0x5A: CPU_LD_r0_r1(CPU.E, CPU.D); case 0x5B: CPU_LD_r0_r1(CPU.E, CPU.E); case 0x5C: CPU_LD_r0_r1(CPU.E, CPU.H); case 0x5D: CPU_LD_r0_r1(CPU.E, CPU.L); case 0x5E: CPU_LD_r_raddr(CPU.E, CPU.HL); case 0x5F: CPU_LD_r0_r1(CPU.E, CPU.A); case 0x60: CPU_LD_r0_r1(CPU.H, CPU.B); case 0x61: CPU_LD_r0_r1(CPU.H, CPU.C); case 0x62: CPU_LD_r0_r1(CPU.H, CPU.D); case 0x63: CPU_LD_r0_r1(CPU.H, CPU.E); case 0x64: CPU_LD_r0_r1(CPU.H, CPU.H); case 0x65: CPU_LD_r0_r1(CPU.H, CPU.L); case 0x66: CPU_LD_r_raddr(CPU.H, CPU.HL); case 0x67: CPU_LD_r0_r1(CPU.H, CPU.A); case 0x68: CPU_LD_r0_r1(CPU.L, CPU.B); case 0x69: CPU_LD_r0_r1(CPU.L, CPU.C); case 0x6A: CPU_LD_r0_r1(CPU.L, CPU.D); case 0x6B: CPU_LD_r0_r1(CPU.L, CPU.E); case 0x6C: CPU_LD_r0_r1(CPU.L, CPU.H); case 0x6D: CPU_LD_r0_r1(CPU.L, CPU.L); case 0x6E: CPU_LD_r_raddr(CPU.L, CPU.HL); case 0x6F: CPU_LD_r0_r1(CPU.L, CPU.A); case 0x70: CPU_LD_raddr_r(CPU.HL, CPU.B); case 0x71: CPU_LD_raddr_r(CPU.HL, CPU.C); case 0x72: CPU_LD_raddr_r(CPU.HL, CPU.D); case 0x73: CPU_LD_raddr_r(CPU.HL, CPU.E); case 0x74: CPU_LD_raddr_r(CPU.HL, CPU.H); case 0x75: CPU_LD_raddr_r(CPU.HL, CPU.L); case 0x76: CPU_HALT(); case 0x77: CPU_LD_raddr_r(CPU.HL, CPU.A); case 0x78: CPU_LD_r0_r1(CPU.A, CPU.B); case 0x79: CPU_LD_r0_r1(CPU.A, CPU.C); case 0x7A: CPU_LD_r0_r1(CPU.A, CPU.D); case 0x7B: CPU_LD_r0_r1(CPU.A, CPU.E); case 0x7C: CPU_LD_r0_r1(CPU.A, CPU.H); case 0x7D: CPU_LD_r0_r1(CPU.A, CPU.L); case 0x7E: CPU_LD_r_raddr(CPU.A, CPU.HL); case 0x7F: CPU_LD_r0_r1(CPU.A, CPU.A); /* ALU */ case 0x80: CPU_ADD_r_r(REG_A, REG_B); case 0x81: CPU_ADD_r_r(REG_A, REG_C); case 0x82: CPU_ADD_r_r(REG_A, REG_D); case 0x83: CPU_ADD_r_r(REG_A, REG_E); case 0x84: CPU_ADD_r_r(REG_A, REG_H); case 0x85: CPU_ADD_r_r(REG_A, REG_L); case 0x86: CPU_ADD_r_raddr(REG_A, REG_HL); case 0x87: CPU_ADD_r_r(REG_A, REG_A); case 0x88: CPU_ADC_r_r(REG_A, REG_B); case 0x89: CPU_ADC_r_r(REG_A, REG_C); case 0x8A: CPU_ADC_r_r(REG_A, REG_D); case 0x8B: CPU_ADC_r_r(REG_A, REG_E); case 0x8C: CPU_ADC_r_r(REG_A, REG_H); case 0x8D: CPU_ADC_r_r(REG_A, REG_L); case 0x8E: CPU_ADC_r_raddr(REG_A, REG_HL); case 0x8F: CPU_ADC_r_r(REG_A, REG_A); case 0x90: CPU_SUB_r_r(REG_A, REG_B); case 0x91: CPU_SUB_r_r(REG_A, REG_C); case 0x92: CPU_SUB_r_r(REG_A, REG_D); case 0x93: CPU_SUB_r_r(REG_A, REG_E); case 0x94: CPU_SUB_r_r(REG_A, REG_H); case 0x95: CPU_SUB_r_r(REG_A, REG_L); case 0x96: CPU_SUB_r_raddr(REG_A, REG_HL); case 0x97: CPU_SUB_r_r(REG_A, REG_A); case 0x98: CPU_SBC_r_r(REG_A, REG_B); case 0x99: CPU_SBC_r_r(REG_A, REG_C); case 0x9A: CPU_SBC_r_r(REG_A, REG_D); case 0x9B: CPU_SBC_r_r(REG_A, REG_E); case 0x9C: CPU_SBC_r_r(REG_A, REG_H); case 0x9D: CPU_SBC_r_r(REG_A, REG_L); case 0x9E: CPU_SBC_r_raddr(REG_A, REG_HL); case 0x9F: CPU_SBC_r_r(REG_A, REG_A); case 0xA0: CPU_AND_A_r(REG_B); case 0xA1: CPU_AND_A_r(REG_C); case 0xA2: CPU_AND_A_r(REG_D); case 0xA3: CPU_AND_A_r(REG_E); case 0xA4: CPU_AND_A_r(REG_H); case 0xA5: CPU_AND_A_r(REG_L); case 0xA6: CPU_AND_A_raddr(REG_HL); case 0xA7: CPU_AND_A_r(REG_A); case 0xA8: CPU_XOR_A_r(REG_B); case 0xA9: CPU_XOR_A_r(REG_C); case 0xAA: CPU_XOR_A_r(REG_D); case 0xAB: CPU_XOR_A_r(REG_E); case 0xAC: CPU_XOR_A_r(REG_H); case 0xAD: CPU_XOR_A_r(REG_L); case 0xAE: CPU_XOR_A_raddr(REG_HL); case 0xAF: CPU_XOR_A_r(REG_A); case 0xB0: CPU_OR_A_r(REG_B); case 0xB1: CPU_OR_A_r(REG_C); case 0xB2: CPU_OR_A_r(REG_D); case 0xB3: CPU_OR_A_r(REG_E); case 0xB4: CPU_OR_A_r(REG_H); case 0xB5: CPU_OR_A_r(REG_L); case 0xB6: CPU_OR_A_raddr(REG_HL); case 0xB7: CPU_OR_A_r(REG_A); case 0xB8: CPU_CP_A_r(REG_B); case 0xB9: CPU_CP_A_r(REG_C); case 0xBA: CPU_CP_A_r(REG_D); case 0xBB: CPU_CP_A_r(REG_E); case 0xBC: CPU_CP_A_r(REG_H); case 0xBD: CPU_CP_A_r(REG_L); case 0xBE: CPU_CP_A_raddr(REG_HL); case 0xBF: CPU_CP_A_r(REG_A); /*******/ case 0xC0: CPU_RET_cc(CPU_COND_NZ); case 0xC8: CPU_RET_cc(CPU_COND_Z); case 0xD0: CPU_RET_cc(CPU_COND_NC); case 0xD8: CPU_RET_cc(CPU_COND_C); case 0xE0: CPU_LD_addr8_r(REG_A); case 0xF0: CPU_LD_r_addr8(REG_A); case 0xE8: CPU_ADD_SP_off8(); case 0xF8: CPU_LD_HL_SP_off8(); // POP (rr) case 0xC1: CPU_POP_BC(); case 0xD1: CPU_POP_DE(); case 0xE1: CPU_POP_HL(); case 0xF1: CPU_POP_AF(); case 0xC9: CPU_RET(); case 0xD9: CPU_RETI(); case 0xE9: CPU_JP_HL(); case 0xC2: CPU_JP(CPU_COND_NZ); case 0xD2: CPU_JP(CPU_COND_NC); case 0xCA: CPU_JP(CPU_COND_Z); case 0xDA: CPU_JP(CPU_COND_C); case 0xC3: CPU_JP(CPU_COND_ALWAYS); case 0xF3: CPU_DI(); case 0xFB: CPU_EI(); case 0xC4: CPU_CALL(CPU_COND_NZ); case 0xCC: CPU_CALL(CPU_COND_Z); case 0xD4: CPU_CALL(CPU_COND_NC); case 0xDC: CPU_CALL(CPU_COND_C); case 0xCD: CPU_CALL(CPU_COND_ALWAYS); // PUSH (rr) case 0xC5: CPU_PUSH_BC(); case 0xD5: CPU_PUSH_DE(); case 0xE5: CPU_PUSH_HL(); case 0xF5: CPU_PUSH_AF(); case 0xC6: CPU_ADD_r_imm8(REG_A); case 0xCE: // 0x0210 0xC674 0xDEF8 // if(REG_PC == 0xDEF9) // fflush(stdout); CPU_ADC_r_imm8(REG_A); case 0xD6: CPU_SUB_r_imm8(REG_A); case 0xDE: CPU_SBC_r_imm8(REG_A); case 0xE6: CPU_AND_A_imm8(); case 0xEE: CPU_XOR_A_imm8(); case 0xF6: CPU_OR_A_imm8(); case 0xFE: CPU_CP_A_imm8(); case 0xFA: { uint16_t addr = GB_READ_U8(CPU.PC++); addr |= GB_READ_U8(CPU.PC++) << 8; CPU.A = GB_READ_U8(addr); CPU.cycles += 4; CPU_exec_next(); } case 0xEA: CPU_LD_addr16_A(); // LD A,(C) case 0xF2: CPU.A = GB_READ_U8(CPU.C | 0xFF00); CPU.cycles += 2; CPU_exec_next(); // LD (C), A case 0xE2: GB_WRITE_U8((CPU.C | 0xFF00), CPU.A); CPU.cycles += 2; CPU_exec_next(); // LD SP, HL case 0xF9: CPU.SP = CPU.HL; CPU.cycles += 2; CPU_exec_next(); case 0xC7: CPU_RST(0x00); case 0xD7: CPU_RST(0x10); case 0xE7: CPU_RST(0x20); case 0xF7: CPU_RST(0x30); case 0xCF: CPU_RST(0x08); case 0xDF: CPU_RST(0x18); case 0xEF: CPU_RST(0x28); case 0xFF: CPU_RST(0x38); case 0xCB: { switch (GB_READ_PC()) { case 0x00: CPU_RLC(REG_B); case 0x01: CPU_RLC(REG_C); case 0x02: CPU_RLC(REG_D); case 0x03: CPU_RLC(REG_E); case 0x04: CPU_RLC(REG_H); case 0x05: CPU_RLC(REG_L); case 0x06: CPU_RLC_HL(); case 0x07: CPU_RLC(REG_A); case 0x08: CPU_RRC(REG_B); case 0x09: CPU_RRC(REG_C); case 0x0A: CPU_RRC(REG_D); case 0x0B: CPU_RRC(REG_E); case 0x0C: CPU_RRC(REG_H); case 0x0D: CPU_RRC(REG_L); case 0x0E: CPU_RRC_HL(); case 0x0F: CPU_RRC(REG_A); case 0x10: CPU_RL(REG_B); case 0x11: CPU_RL(REG_C); case 0x12: CPU_RL(REG_D); case 0x13: CPU_RL(REG_E); case 0x14: CPU_RL(REG_H); case 0x15: CPU_RL(REG_L); case 0x16: CPU_RL_HL(); case 0x17: CPU_RL(REG_A); case 0x18: CPU_RR(REG_B); case 0x19: CPU_RR(REG_C); case 0x1A: CPU_RR(REG_D); case 0x1B: CPU_RR(REG_E); case 0x1C: CPU_RR(REG_H); case 0x1D: CPU_RR(REG_L); case 0x1E: CPU_RR_HL(); case 0x1F: CPU_RR(REG_A); case 0x20: CPU_SLA(REG_B); case 0x21: CPU_SLA(REG_C); case 0x22: CPU_SLA(REG_D); case 0x23: CPU_SLA(REG_E); case 0x24: CPU_SLA(REG_H); case 0x25: CPU_SLA(REG_L); case 0x26: CPU_SLA_HL(); case 0x27: CPU_SLA(REG_A); case 0x28: CPU_SRA(REG_B); case 0x29: CPU_SRA(REG_C); case 0x2A: CPU_SRA(REG_D); case 0x2B: CPU_SRA(REG_E); case 0x2C: CPU_SRA(REG_H); case 0x2D: CPU_SRA(REG_L); case 0x2E: CPU_SRA_HL(); case 0x2F: CPU_SRA(REG_A); case 0x30: CPU_SWAP(REG_B); case 0x31: CPU_SWAP(REG_C); case 0x32: CPU_SWAP(REG_D); case 0x33: CPU_SWAP(REG_E); case 0x34: CPU_SWAP(REG_H); case 0x35: CPU_SWAP(REG_L); case 0x36: CPU_SWAP_HL(); case 0x37: CPU_SWAP(REG_A); case 0x38: CPU_SRL(REG_B); case 0x39: CPU_SRL(REG_C); case 0x3A: CPU_SRL(REG_D); case 0x3B: CPU_SRL(REG_E); case 0x3C: CPU_SRL(REG_H); case 0x3D: CPU_SRL(REG_L); case 0x3E: CPU_SRL_HL(); case 0x3F: CPU_SRL(REG_A); case 0x40: CPU_BIT(0, REG_B); case 0x41: CPU_BIT(0, REG_C); case 0x42: CPU_BIT(0, REG_D); case 0x43: CPU_BIT(0, REG_E); case 0x44: CPU_BIT(0, REG_H); case 0x45: CPU_BIT(0, REG_L); case 0x46: CPU_BIT_HL(0); case 0x47: CPU_BIT(0, REG_A); case 0x48: CPU_BIT(1, REG_B); case 0x49: CPU_BIT(1, REG_C); case 0x4A: CPU_BIT(1, REG_D); case 0x4B: CPU_BIT(1, REG_E); case 0x4C: CPU_BIT(1, REG_H); case 0x4D: CPU_BIT(1, REG_L); case 0x4E: CPU_BIT_HL(1); case 0x4F: CPU_BIT(1, REG_A); case 0x50: CPU_BIT(2, REG_B); case 0x51: CPU_BIT(2, REG_C); case 0x52: CPU_BIT(2, REG_D); case 0x53: CPU_BIT(2, REG_E); case 0x54: CPU_BIT(2, REG_H); case 0x55: CPU_BIT(2, REG_L); case 0x56: CPU_BIT_HL(2); case 0x57: CPU_BIT(2, REG_A); case 0x58: CPU_BIT(3, REG_B); case 0x59: CPU_BIT(3, REG_C); case 0x5A: CPU_BIT(3, REG_D); case 0x5B: CPU_BIT(3, REG_E); case 0x5C: CPU_BIT(3, REG_H); case 0x5D: CPU_BIT(3, REG_L); case 0x5E: CPU_BIT_HL(3); case 0x5F: CPU_BIT(3, REG_A); case 0x60: CPU_BIT(4, REG_B); case 0x61: CPU_BIT(4, REG_C); case 0x62: CPU_BIT(4, REG_D); case 0x63: CPU_BIT(4, REG_E); case 0x64: CPU_BIT(4, REG_H); case 0x65: CPU_BIT(4, REG_L); case 0x66: CPU_BIT_HL(4); case 0x67: CPU_BIT(4, REG_A); case 0x68: CPU_BIT(5, REG_B); case 0x69: CPU_BIT(5, REG_C); case 0x6A: CPU_BIT(5, REG_D); case 0x6B: CPU_BIT(5, REG_E); case 0x6C: CPU_BIT(5, REG_H); case 0x6D: CPU_BIT(5, REG_L); case 0x6E: CPU_BIT_HL(5); case 0x6F: CPU_BIT(5, REG_A); case 0x70: CPU_BIT(6, REG_B); case 0x71: CPU_BIT(6, REG_C); case 0x72: CPU_BIT(6, REG_D); case 0x73: CPU_BIT(6, REG_E); case 0x74: CPU_BIT(6, REG_H); case 0x75: CPU_BIT(6, REG_L); case 0x76: CPU_BIT_HL(6); case 0x77: CPU_BIT(6, REG_A); case 0x78: CPU_BIT(7, REG_B); case 0x79: CPU_BIT(7, REG_C); case 0x7A: CPU_BIT(7, REG_D); case 0x7B: CPU_BIT(7, REG_E); case 0x7C: CPU_BIT(7, REG_H); case 0x7D: CPU_BIT(7, REG_L); case 0x7E: CPU_BIT_HL(7); case 0x7F: CPU_BIT(7, REG_A); case 0x80: CPU_RES(0, REG_B); case 0x81: CPU_RES(0, REG_C); case 0x82: CPU_RES(0, REG_D); case 0x83: CPU_RES(0, REG_E); case 0x84: CPU_RES(0, REG_H); case 0x85: CPU_RES(0, REG_L); case 0x86: CPU_RES_HL(0); case 0x87: CPU_RES(0, REG_A); case 0x88: CPU_RES(1, REG_B); case 0x89: CPU_RES(1, REG_C); case 0x8A: CPU_RES(1, REG_D); case 0x8B: CPU_RES(1, REG_E); case 0x8C: CPU_RES(1, REG_H); case 0x8D: CPU_RES(1, REG_L); case 0x8E: CPU_RES_HL(1); case 0x8F: CPU_RES(1, REG_A); case 0x90: CPU_RES(2, REG_B); case 0x91: CPU_RES(2, REG_C); case 0x92: CPU_RES(2, REG_D); case 0x93: CPU_RES(2, REG_E); case 0x94: CPU_RES(2, REG_H); case 0x95: CPU_RES(2, REG_L); case 0x96: CPU_RES_HL(2); case 0x97: CPU_RES(2, REG_A); case 0x98: CPU_RES(3, REG_B); case 0x99: CPU_RES(3, REG_C); case 0x9A: CPU_RES(3, REG_D); case 0x9B: CPU_RES(3, REG_E); case 0x9C: CPU_RES(3, REG_H); case 0x9D: CPU_RES(3, REG_L); case 0x9E: CPU_RES_HL(3); case 0x9F: CPU_RES(3, REG_A); case 0xA0: CPU_RES(4, REG_B); case 0xA1: CPU_RES(4, REG_C); case 0xA2: CPU_RES(4, REG_D); case 0xA3: CPU_RES(4, REG_E); case 0xA4: CPU_RES(4, REG_H); case 0xA5: CPU_RES(4, REG_L); case 0xA6: CPU_RES_HL(4); case 0xA7: CPU_RES(4, REG_A); case 0xA8: CPU_RES(5, REG_B); case 0xA9: CPU_RES(5, REG_C); case 0xAA: CPU_RES(5, REG_D); case 0xAB: CPU_RES(5, REG_E); case 0xAC: CPU_RES(5, REG_H); case 0xAD: CPU_RES(5, REG_L); case 0xAE: CPU_RES_HL(5); case 0xAF: CPU_RES(5, REG_A); case 0xB0: CPU_RES(6, REG_B); case 0xB1: CPU_RES(6, REG_C); case 0xB2: CPU_RES(6, REG_D); case 0xB3: CPU_RES(6, REG_E); case 0xB4: CPU_RES(6, REG_H); case 0xB5: CPU_RES(6, REG_L); case 0xB6: CPU_RES_HL(6); case 0xB7: CPU_RES(6, REG_A); case 0xB8: CPU_RES(7, REG_B); case 0xB9: CPU_RES(7, REG_C); case 0xBA: CPU_RES(7, REG_D); case 0xBB: CPU_RES(7, REG_E); case 0xBC: CPU_RES(7, REG_H); case 0xBD: CPU_RES(7, REG_L); case 0xBE: CPU_RES_HL(7); case 0xBF: CPU_RES(7, REG_A); case 0xC0: CPU_SET(0, REG_B); case 0xC1: CPU_SET(0, REG_C); case 0xC2: CPU_SET(0, REG_D); case 0xC3: CPU_SET(0, REG_E); case 0xC4: CPU_SET(0, REG_H); case 0xC5: CPU_SET(0, REG_L); case 0xC6: CPU_SET_HL(0); case 0xC7: CPU_SET(0, REG_A); case 0xC8: CPU_SET(1, REG_B); case 0xC9: CPU_SET(1, REG_C); case 0xCA: CPU_SET(1, REG_D); case 0xCB: CPU_SET(1, REG_E); case 0xCC: CPU_SET(1, REG_H); case 0xCD: CPU_SET(1, REG_L); case 0xCE: CPU_SET_HL(1); case 0xCF: CPU_SET(1, REG_A); case 0xD0: CPU_SET(2, REG_B); case 0xD1: CPU_SET(2, REG_C); case 0xD2: CPU_SET(2, REG_D); case 0xD3: CPU_SET(2, REG_E); case 0xD4: CPU_SET(2, REG_H); case 0xD5: CPU_SET(2, REG_L); case 0xD6: CPU_SET_HL(2); case 0xD7: CPU_SET(2, REG_A); case 0xD8: CPU_SET(3, REG_B); case 0xD9: CPU_SET(3, REG_C); case 0xDA: CPU_SET(3, REG_D); case 0xDB: CPU_SET(3, REG_E); case 0xDC: CPU_SET(3, REG_H); case 0xDD: CPU_SET(3, REG_L); case 0xDE: CPU_SET_HL(3); case 0xDF: CPU_SET(3, REG_A); case 0xE0: CPU_SET(4, REG_B); case 0xE1: CPU_SET(4, REG_C); case 0xE2: CPU_SET(4, REG_D); case 0xE3: CPU_SET(4, REG_E); case 0xE4: CPU_SET(4, REG_H); case 0xE5: CPU_SET(4, REG_L); case 0xE6: CPU_SET_HL(4); case 0xE7: CPU_SET(4, REG_A); case 0xE8: CPU_SET(5, REG_B); case 0xE9: CPU_SET(5, REG_C); case 0xEA: CPU_SET(5, REG_D); case 0xEB: CPU_SET(5, REG_E); case 0xEC: CPU_SET(5, REG_H); case 0xED: CPU_SET(5, REG_L); case 0xEE: CPU_SET_HL(5); case 0xEF: CPU_SET(5, REG_A); case 0xF0: CPU_SET(6, REG_B); case 0xF1: CPU_SET(6, REG_C); case 0xF2: CPU_SET(6, REG_D); case 0xF3: CPU_SET(6, REG_E); case 0xF4: CPU_SET(6, REG_H); case 0xF5: CPU_SET(6, REG_L); case 0xF6: CPU_SET_HL(6); case 0xF7: CPU_SET(6, REG_A); case 0xF8: CPU_SET(7, REG_B); case 0xF9: CPU_SET(7, REG_C); case 0xFA: CPU_SET(7, REG_D); case 0xFB: CPU_SET(7, REG_E); case 0xFC: CPU_SET(7, REG_H); case 0xFD: CPU_SET(7, REG_L); case 0xFE: CPU_SET_HL(7); case 0xFF: CPU_SET(7, REG_A); default: gbemu_printf("(0xCB)"); goto unknown_opcode; } } case 0xD3: case 0xE3: case 0xE4: case 0xF4: case 0xDB: case 0xEB: case 0xEC: case 0xFC: case 0xDD: case 0xED: case 0xFD: invalid_opcode: { extern retro_environment_t environ_cb; retro_sleep(10); printf("invalid opcode : 0x%02X\n",GB_READ_U8(CPU.PC - 1)); fflush(stdout); // DEBUG_BREAK(); if (environ_cb) environ_cb(RETRO_ENVIRONMENT_SHUTDOWN, NULL); #ifdef PERF_TEST extern struct retro_perf_callback perf_cb; perf_cb.perf_log(); #endif // return; exit(0); } break; default: unknown_opcode: { extern retro_environment_t environ_cb; retro_sleep(10); printf("unknown opcode : 0x%02X\n", GB_READ_U8(CPU.PC - 1)); fflush(stdout); // DEBUG_BREAK(); if (environ_cb) environ_cb(RETRO_ENVIRONMENT_SHUTDOWN, NULL); #ifdef PERF_TEST extern struct retro_perf_callback perf_cb; perf_cb.perf_log(); #endif // return; exit(0); } break; } cpu_exit: GB.CPU = CPU; return; }
static void get_binds(config_file_t *conf, config_file_t *auto_conf, int player, int joypad) { int i, timeout_cnt; const input_device_driver_t *driver = input_joypad_init_driver(g_driver, NULL); const char *joypad_name; int16_t initial_axes[MAX_AXES] = {0}; struct poll_data old_poll = {{0}}; struct poll_data new_poll = {{0}}; int last_axis = -1; bool block_axis = false; int timeout_ticks = g_timeout * 100; if (!driver) { fprintf(stderr, "Cannot find any valid input driver.\n"); exit(1); } if (!driver->query_pad(joypad)) { fprintf(stderr, "Couldn't open joystick #%d.\n", joypad); exit(1); } fprintf(stderr, "Found joypad driver: %s\n", driver->ident); joypad_name = input_joypad_name(driver, joypad); fprintf(stderr, "Using joypad: %s\n", joypad_name ? joypad_name : "Unknown"); if (joypad_name && auto_conf) { config_set_string(auto_conf, "input_device", joypad_name); config_set_string(auto_conf, "input_driver", driver->ident); } poll_joypad(driver, joypad, &old_poll); fprintf(stderr, "\nJoypads tend to have stale state after opened.\nPress some buttons and move some axes around to make sure joypad state is completely neutral before proceeding.\nWhen done, press Enter ... "); getchar(); poll_joypad(driver, joypad, &old_poll); for (i = 0; i < MAX_AXES; i++) { int16_t initial = input_joypad_axis_raw(driver, joypad, i); if (abs(initial) < 20000) initial = 0; /* Certain joypads (such as XBox360 controller on Linux) * has a default negative axis for shoulder triggers, * which makes configuration very awkward. * * If default negative, we can't trigger on the negative axis, * and similar with defaulted positive axes. */ if (initial) fprintf(stderr, "Axis %d is defaulted to %s axis value of %d.\n", i, initial > 0 ? "positive" : "negative", initial); initial_axes[i] = initial; } for (i = 0; i < MAX_BUTTONS; i++) { if (old_poll.buttons[i]) fprintf(stderr, "Button %d was initially pressed. This indicates broken initial state.\n", i); } fprintf(stderr, "Configuring binds for player #%d on joypad #%d.\n\n", player + 1, joypad); for (i = 0, timeout_cnt = 0; input_config_bind_map[i].valid; i++, timeout_cnt = 0) { unsigned meta_level; unsigned player_index; int j; if (i == RARCH_TURBO_ENABLE) continue; meta_level = input_config_bind_map[i].meta; if (meta_level > g_meta_level) continue; fprintf(stderr, "%s\n", input_config_bind_map[i].desc); player_index = input_config_bind_map[i].meta ? 0 : player; for (;;) { old_poll = new_poll; /* To avoid pegging CPU. * Ideally use an event-based joypad scheme, * but it adds far more complexity, so, meh. */ retro_sleep(10); if (timeout_ticks) { timeout_cnt++; if (timeout_cnt >= timeout_ticks) { fprintf(stderr, "\tTimed out ...\n"); break; } } poll_joypad(driver, joypad, &new_poll); for (j = 0; j < MAX_BUTTONS; j++) { if (new_poll.buttons[j] && !old_poll.buttons[j]) { char key[64] = {0}; fprintf(stderr, "\tJoybutton pressed: %d\n", j); snprintf(key, sizeof(key), "%s_%s_btn", input_config_get_prefix(player_index, input_config_bind_map[i].meta), input_config_bind_map[i].base); config_set_int(conf, key, j); if (auto_conf) { snprintf(key, sizeof(key), "input_%s_btn", input_config_bind_map[i].base); config_set_int(auto_conf, key, j); } goto out; } } for (j = 0; j < MAX_AXES; j++) { int16_t value; bool same_axis; bool require_negative; bool require_positive; if (new_poll.axes[j] == old_poll.axes[j]) continue; value = new_poll.axes[j]; same_axis = last_axis == j; require_negative = initial_axes[j] > 0; require_positive = initial_axes[j] < 0; /* Block the axis config until we're sure * axes have returned to their neutral state. */ if (same_axis) { if (abs(value) < 10000 || (require_positive && value < 0) || (require_negative && value > 0)) block_axis = false; } /* If axes are in their neutral state, * we can't allow it. */ if (require_negative && value >= 0) continue; if (require_positive && value <= 0) continue; if (block_axis) continue; if (abs(value) > 20000) { char buf[8] = {0}; char key[64] = {0}; last_axis = j; fprintf(stderr, "\tJoyaxis moved: Axis %d, Value %d\n", j, value); snprintf(buf, sizeof(buf), value > 0 ? "+%d" : "-%d", j); snprintf(key, sizeof(key), "%s_%s_axis", input_config_get_prefix(player_index, input_config_bind_map[i].meta), input_config_bind_map[i].base); config_set_string(conf, key, buf); if (auto_conf) { snprintf(key, sizeof(key), "input_%s_axis", input_config_bind_map[i].base); config_set_string(auto_conf, key, buf); } block_axis = true; goto out; } } for (j = 0; j < MAX_HATS; j++) { const char *quark = NULL; uint16_t value = new_poll.hats[j]; uint16_t old_value = old_poll.hats[j]; if ((value & HAT_UP_MASK) && !(old_value & HAT_UP_MASK)) quark = "up"; else if ((value & HAT_LEFT_MASK) && !(old_value & HAT_LEFT_MASK)) quark = "left"; else if ((value & HAT_RIGHT_MASK) && !(old_value & HAT_RIGHT_MASK)) quark = "right"; else if ((value & HAT_DOWN_MASK) && !(old_value & HAT_DOWN_MASK)) quark = "down"; if (quark) { char buf[16] = {0}; char key[64] = {0}; fprintf(stderr, "\tJoyhat moved: Hat %d, direction %s\n", j, quark); snprintf(buf, sizeof(buf), "h%d%s", j, quark); snprintf(key, sizeof(key), "%s_%s_btn", input_config_get_prefix(player_index, input_config_bind_map[i].meta), input_config_bind_map[i].base); config_set_string(conf, key, buf); if (auto_conf) { snprintf(key, sizeof(key), "input_%s_btn", input_config_bind_map[i].base); config_set_string(auto_conf, key, buf); } goto out; } } } out: old_poll = new_poll; } }
static int network_interface_up(struct sockaddr_in *target, int index, const char *ip_address, unsigned udp_port, int *s) { (void)index; #if defined(VITA) if (sceNetShowNetstat() == PSP2_NET_ERROR_ENOTINIT) { SceNetInitParam initparam; net_memory = malloc(NET_INIT_SIZE); initparam.memory = net_memory; initparam.size = NET_INIT_SIZE; initparam.flags = 0; sceNetInit(&initparam); } *s = sceNetSocket("RA_netlogger", PSP2_NET_AF_INET, PSP2_NET_SOCK_DGRAM, 0); target->sin_family = PSP2_NET_AF_INET; target->sin_port = sceNetHtons(udp_port); sceNetInetPton(PSP2_NET_AF_INET, ip_address, &target->sin_addr); #else #if defined(__CELLOS_LV2__) && !defined(__PSL1GHT__) int ret = 0; int state, timeout_count = 10; ret = cellNetCtlInit(); if (ret < 0) return -1; for (;;) { ret = cellNetCtlGetState(&state); if (ret < 0) return -1; if (state == CELL_NET_CTL_STATE_IPObtained) break; retro_sleep(500); timeout_count--; if (index && timeout_count < 0) return 0; } #elif defined(GEKKO) char t[16]; if (if_config(t, NULL, NULL, TRUE) < 0) ret = -1; #endif if (ret < 0) return -1; *s = socket(AF_INET, SOCK_DGRAM, 0); target->sin_family = AF_INET; target->sin_port = htons(udp_port); #ifdef GEKKO target->sin_len = 8; #endif inet_pton(AF_INET, ip_address, &target->sin_addr); #endif return 0; }
/** * network_init: * * Platform specific socket library initialization. * * Returns: true (1) if successful, otherwise false (0). **/ bool network_init(void) { #ifdef _WIN32 WSADATA wsaData; #endif static bool inited = false; if (inited) return true; #if defined(_WIN32) if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) { network_deinit(); return false; } #elif defined(__CELLOS_LV2__) && !defined(__PSL1GHT__) int timeout_count = 10; cellSysmoduleLoadModule(CELL_SYSMODULE_NET); sys_net_initialize_network(); if (cellNetCtlInit() < 0) return false; for (;;) { int state; if (cellNetCtlGetState(&state) < 0) return false; if (state == CELL_NET_CTL_STATE_IPObtained) break; retro_sleep(500); timeout_count--; if (timeout_count < 0) return 0; } #elif defined(VITA) SceNetInitParam initparam; if (sceNetShowNetstat() == SCE_NET_ERROR_ENOTINIT) { _net_compat_net_memory = malloc(COMPAT_NET_INIT_SIZE); initparam.memory = _net_compat_net_memory; initparam.size = COMPAT_NET_INIT_SIZE; initparam.flags = 0; sceNetInit(&initparam); sceNetCtlInit(); } retro_epoll_fd = sceNetEpollCreate("epoll", 0); #elif defined(GEKKO) char t[16]; if (if_config(t, NULL, NULL, TRUE, 10) < 0) return false; #elif defined(WIIU) socket_lib_init(); #elif defined(_3DS) _net_compat_net_memory = (u32*)memalign(SOC_ALIGN, SOC_BUFFERSIZE); if (_net_compat_net_memory == NULL) return false; Result ret = socInit(_net_compat_net_memory, SOC_BUFFERSIZE);//WIFI init if (ret != 0) return false; #else signal(SIGPIPE, SIG_IGN); /* Do not like SIGPIPE killing our app. */ #endif inited = true; return true; }
virtual void delayMillis(uint msecs) { if(!retroCheckThread(msecs)) retro_sleep(msecs); }