//run 1 NES frame with FF/REW control void play() { static int framecount=0; static int fcount = 0; int forward = 0; int backward = 0; do_cheat(); global_playcount++; if(global_playcount > 6) global_playcount = 0; if(nifi_stat) __emuflags &= ~(FASTFORWARD | REWIND); //when nifi enabled, disable the fastforward & rewind. forward = __emuflags & FASTFORWARD; backward = __emuflags & REWIND; if(backward) { // for rolling back... a nice function? swiWaitForVBlank(); framecount++; if(framecount>2) { framecount-=3; if(firstsave!=lastsave) { lastsave--; if(lastsave<0) lastsave=maxsaves-1; loadstate(freemem_start+SAVESTATESIZE*lastsave); EMU_Run(); } } } else { if(__emuflags & SOFTRENDER) { if(!(forward) && (fcount >= debuginfo[6] && fcount - debuginfo[6] < 10) ) // disable VBlank to speed up emulation. swiWaitForVBlank(); } else { if(!(forward)) { if(__emuflags & PALSYNC) { if(__emuflags & (SOFTRENDER | PALTIMING)) __emuflags ^= PALSYNC; if(REG_VCOUNT < 190) { swiWaitForVBlank(); } } else { if((!(__emuflags & ALLPIXEL)) || (all_pix_start != 0)) swiWaitForVBlank(); } } } if(!(__emuflags & PALTIMING && global_playcount == 6)) { EMU_Run(); //run a frame framecount++; if(framecount>8) { //save state every 9th frame framecount-=9; savestate(freemem_start+SAVESTATESIZE*lastsave); lastsave++; if(lastsave>=maxsaves) lastsave=0; if(lastsave==firstsave) { firstsave++; if(firstsave>=maxsaves) firstsave=0; } } } else { if((__emuflags & PALTIMING) && (__emuflags & ALLPIXEL) && !(__emuflags & SOFTRENDER)) swiWaitForVBlank(); } } if(__emuflags & SOFTRENDER) { __emuflags &= ~AUTOSRAM; __rendercount++; if(SOFT_FRAMESKIP <= 1 ||__rendercount == 1) { if(__emuflags & ALLPIXEL) render_sub(); render_all(); } if(!(forward) && __rendercount >= SOFT_FRAMESKIP) __rendercount = 0; if((forward) && __rendercount > 16) __rendercount = 0; } else if(__emuflags & ALLPIXEL) { render_sub(); } fcount++; if(fcount > 59) fcount = 0; __emuflags &= ~(FASTFORWARD | REWIND); }
/* The key event handler. */ int handle_keystroke_event(nbstate *state, GR_EVENT_KEYSTROKE *ev) { /* If the event is a "key up" event and the key is either the left or * right cursor key, cancel bat movement in that direction. Otherwise * we don't care about the event. */ if(ev->type == GR_EVENT_TYPE_KEY_UP) { switch(ev->ch) { case MWKEY_LEFT: state->flags.left = 0; break; case MWKEY_RIGHT: state->flags.right = 0; break; default: /* Ignore the event. */ break; } return 0; /* Normal return. */ } /* If we get to here, it's a "key down" event. Perform various * different actions depending on which key was pressed: */ switch(ev->ch) { case ' ': /* The space bar is the "action" key: */ action_pressed(state); break; case MWKEY_F1: /* F1 is the "pause" key: */ state->flags.paused ^= 1; /* Set the pause flag. */ break; case MWKEY_F2: /* F2 is the "suicide" key: */ lost_ball(state); /* Throw away the current ball. */ break; #ifdef DEBUG_POWERS /* If DEBUG_POWERS is defined in nbreaker.h, keys F3-F8 are * used to trigger the power ups and power downs without * needing to catch a falling power box. */ case MWKEY_F3: /* WideBat */ activate_widebat(state); break; case MWKEY_F4: /* SlowMotion */ activate_slowmotion(state); break; case MWKEY_F5: /* StickyBat */ activate_stickybat(state); break; case MWKEY_F6: /* PowerBall */ activate_powerball(state); break; case MWKEY_F7: /* NarrowBat */ activate_narrowbat(state); break; case MWKEY_F8: /* FastMotion */ activate_fastmotion(state); break; #endif case MWKEY_LEFT: /* The left cursor key: */ /* Set the "moving left" flag and cancel the * "moving right" one. */ state->flags.left = 1; state->flags.right = 0; break; case MWKEY_RIGHT: /* The right cursor key: */ /* Set the "moving right" flag and cancel the * "moving left" one. */ state->flags.left = 0; state->flags.right = 1; break; #ifdef NB_DEBUG /* If NB_DEBUG is set in nbreaker.h, dump the game state when * F10 is pressed. */ case MWKEY_F10: dump_state(state); break; #endif /* If the escape key is pressed, return 1 which means "exit * the game". */ case MWKEY_ESCAPE: return 1; /* Feed all other key presses to the cheat recogniser engine: */ default: do_cheat(state, ev->ch); break; } return 0; /* Normal return. */ }