void do_keypad() { int bVert = !options.rotate && (BurnDrvGetFlags() & BDF_ORIENTATION_VERTICAL); FBA_KEYPAD[0] = 0; FBA_KEYPAD[1] = 0; FBA_KEYPAD[2] = 0; FBA_KEYPAD[3] = 0; ServiceRequest = 0; P1P2Start = 0; sdl_input_read(false); for (int it = 0; it < autofire_count; it++) { if (autofire_state[it].state == 0 && (keypc & autofire_state[it].keypc)) { autofire_state[it].state = 1; } if (autofire_state[it].state != 0 && !(keypc & autofire_state[it].keypc)) { autofire_state[it].state = 0; } } sdl_input_read(true); // process redefinable keypresses if (keypad & KEYPAD_UP) FBA_KEYPAD[0] |= bVert ? KEYPAD_LEFT : KEYPAD_UP; if (keypad & KEYPAD_DOWN) FBA_KEYPAD[0] |= bVert ? KEYPAD_RIGHT : KEYPAD_DOWN; if (keypad & KEYPAD_LEFT) FBA_KEYPAD[0] |= bVert ? KEYPAD_DOWN : KEYPAD_LEFT; if (keypad & KEYPAD_RIGHT) FBA_KEYPAD[0] |= bVert ? KEYPAD_UP : KEYPAD_RIGHT; if (keypad & KEYPAD_COIN) FBA_KEYPAD[0] |= KEYPAD_COIN; if (keypad & KEYPAD_START) FBA_KEYPAD[0] |= KEYPAD_START; if (keypad & KEYPAD_FIRE1) FBA_KEYPAD[0] |= KEYPAD_FIRE1; // A if (keypad & KEYPAD_FIRE2) FBA_KEYPAD[0] |= KEYPAD_FIRE2; // B if (keypad & KEYPAD_FIRE3) FBA_KEYPAD[0] |= KEYPAD_FIRE3; // X if (keypad & KEYPAD_FIRE4) FBA_KEYPAD[0] |= KEYPAD_FIRE4; // Y if (keypad & KEYPAD_FIRE5) FBA_KEYPAD[0] |= KEYPAD_FIRE5; // L if (keypad & KEYPAD_FIRE6) FBA_KEYPAD[0] |= KEYPAD_FIRE6; // R // process non-redefinable keypresses if (keypc & BUTTON_QT) { GameLooping = false; keypc = keypad = 0; } if (keypc & BUTTON_MENU) { keypc = keypad = 0; SndPause(1); gui_Run(); SndPause(0); } if (keypc & BUTTON_PAUSE) { bPauseOn = !bPauseOn; SndPause(bPauseOn); keypc &= ~BUTTON_PAUSE; } if(!bPauseOn) { // savestate fails inside pause if (keypc & BUTTON_QSAVE) { StatedSave(nSavestateSlot); keypc &= ~BUTTON_QSAVE; } if (keypc & BUTTON_QLOAD) { StatedLoad(nSavestateSlot); keypc &= ~BUTTON_QLOAD; bPauseOn = 0; } } if ((keypc & BUTTON_SL) && (keypc & BUTTON_SR)) { if (keypc & BUTTON_Y) { ChangeFrameskip(); keypc &= ~BUTTON_Y; } else if (keypc & BUTTON_B && !bPauseOn) { StatedSave(nSavestateSlot); keypc &= ~BUTTON_B; } else if (keypc & BUTTON_A && !bPauseOn) { StatedLoad(nSavestateSlot); keypc &= ~BUTTON_A; bPauseOn = 0; } else if (keypc & BUTTON_START) { keypc = keypad = 0; SndPause(1); gui_Run(); SndPause(0); } else if (keypc & BUTTON_SELECT) ServiceRequest = 1; } else if ((keypc & BUTTON_START) && (keypc & BUTTON_SELECT)) P1P2Start = 1; }
int main() { static char load_filename[512]; char *romname = NULL; float audioStart; // this is a float to count the half sample per frame needed ho have precise timing u32 audioTarget, audioEnd; srvInit(); aptInit(); hidInit(); APT_CheckNew3DS(&isN3DS); if(isN3DS) osSetSpeedupEnable(true); get_config_path(); sprintf(savename, "%s/Handy3ds.cfg", config_base_path); // using savename char buffer to save memory do_config(savename); handy_3ds_video_init(); sprintf(bios_path_and_name, "%s/%s", config_bios_path, "lynxboot.img"); // Call filebrowser if(gui_LoadFile(load_filename)!= -1) { romname = (char *)&load_filename; do { hidScanInput(); } while (hidKeysHeld()); } else { handy_3ds_quit(); } // Primary initalise of Handy - should be called AFTER _Init() but BEFORE handy_3ds_video_setup() handy_3ds_core_init(romname); // Initialise Handy 3ds video handy_3ds_video_setup(1, 0, 0, 32, LynxScale, 0, 0); // Initialise Handy 3ds audio printf("\nInitialising 3DS Audio... "); gAudioEnabled = handy_3ds_audio_init(); printf("[DONE]\n"); // Setup of Handy Core video handy_3ds_video_reinit(32); printf("Starting Lynx Emulation...\n"); bool touched = false; audioStart = gAudioBufferPointer; // both should be 0 at this point // initialize timers u64 tickcurr, syncticknext,synctickres; u64 fpsticknext,fpstickres; int frameSyncPeriod; if(isN3DS) frameSyncPeriod = 1; else frameSyncPeriod = 12; fpstickres= TICKS_PER_SEC; synctickres = TICKS_PER_FRAME * frameSyncPeriod; // on o3ds the sync is every 12 frame, i.e. 5 times every sec tickcurr=svcGetSystemTick(); fpsticknext = tickcurr + fpstickres; syncticknext = tickcurr + synctickres; int fpscnt = 0, synccnt = 0; gThrottleMaxPercentage = isN3DS?100:50; // !! TO DO: check if 50 is the best value. while(!emulation) { // Initialise Handy button events int OldKeyMask, KeyMask = mpLynx->GetButtonData(); OldKeyMask = KeyMask; // Getting events for keyboard and/or joypad handling hidScanInput(); if (hidKeysHeld() & KEY_TOUCH) { touched = true; } else { if (touched) { handy_3ds_audio_pause(); gui_Run(); KeyMask = 0; touched = false; // audioStart = gAudioBufferPointer; do { hidScanInput(); } while (hidKeysHeld()); gThrottleMaxPercentage = isN3DS?100:50; // !! Loading a savestate overrides this value, so we force it again exiting menu fpscnt = 0; synccnt = 0; tickcurr=svcGetSystemTick(); fpsticknext = tickcurr + fpstickres; syncticknext = tickcurr + synctickres; } else { touched = false; } } KeyMask = handy_3ds_on_key_down(hidKeysHeld(), KeyMask); // Check if there are handling events and then update the Handy button events. if (OldKeyMask != KeyMask) mpLynx->SetButtonData(KeyMask); // Update TimerCount gTimerCount++; while( handy_3ds_update() ) { //!! hidScanInput(); u32 held = hidKeysHeld(); if (held & KEY_SELECT) { // handy_3ds_video_quit(); // handy_3ds_audio_quit(); // exit(EXIT_SUCCESS); //break; touched = true; // enter menu } //!! if(!gSystemHalt) { if (!handy_3ds_audio_getstate()) { audioStart=0.0; // reset counter gAudioBufferPointer = 0; // reset buffer. really not needed since we set it to 0 in handy_3ds_audio_pause(). } // increase sound samples counter - 367,5 samples per frame at 60 fps audioEnd = (int)(audioStart + 367.5) % HANDY_AUDIO_BUFFER_SIZE; // filling 1 half of the buffer, roughly enough for slow frames on o3DS without risk of buffer head to reach the tail during the 10 frames before resync. audioTarget = (int)(audioStart + HANDY_AUDIO_BUFFER_SIZE/2.1) % HANDY_AUDIO_BUFFER_SIZE; if (audioTarget>audioStart) while (gAudioBufferPointer<audioTarget) mpLynx->Update(); else while ((gAudioBufferPointer>audioStart)||(gAudioBufferPointer<audioTarget)) mpLynx->Update(); if(Handy_cfg_Throttle && Handy_cfg_Sound && gAudioEnabled) { if (handy_3ds_audio_getstate()) handy_3ds_audio_callback(audioStart, (int)(audioTarget-audioStart)); else handy_3ds_audio_start(22050, audioStart); } audioStart = audioEnd; } else { printf("gSystemHalt : %ld\n", gSystemHalt); gTimerCount++; } system_checkPolls(); } // Timing fpscnt++; synccnt++; if (Handy_cfg_Throttle) { if (synccnt==frameSyncPeriod){ svcSleepThread((syncticknext - svcGetSystemTick()) / TICKS_PER_NSEC); } } tickcurr=svcGetSystemTick(); if (tickcurr >= syncticknext) { syncticknext += synctickres; synccnt = 0; } if (tickcurr >= fpsticknext) { fpsticknext += fpstickres; fps_counter = fpscnt; fpscnt = 0; } } // while(!emulation) osSetSpeedupEnable(true); return 0; }