Exemple #1
0
static void processButtonEvent(int eventType) {
	Action *action = NULL;
	EnumAction actionCode;
	
	if (context.idxActiveList != -1) {
		action = getListActions(&pkgSystem.lists[context.idxActiveList]);
		while (action && !isEventInAction(action,eventType,context.isPaused))
			action = getNextAction(action);
	}
	if (!action)
		action = getMatchingAction(eventType);

	if (action)
		takeAction(action, -1);
	if (context.returnPackage) {
		if (action) {
			actionCode = getActionCode(action);
			if (actionCode == VOLUME_UP || actionCode == VOLUME_DOWN || actionCode == VOLUME_NORMAL
				|| actionCode == SPEED_UP || actionCode == SPEED_DOWN || actionCode == SPEED_NORMAL
				|| actionCode == JUMP_TIME || actionCode == PLAY_PAUSE || actionCode == PAUSE)
					context.package = context.returnPackage; // reset what might have been set in getMatchingAction
		}
		context.returnPackage = NULL;
	}
}
void Gameplay::createActionMap(void)
{
    // read configuration...
    ButtonChannel* buttonChannel;

	float ascLvl = 2.0f;
	float descLvl = 5.0f;
    // create left channel
    buttonChannel = new ButtonChannel( iaLeft, ascLvl, descLvl );
    buttonChannel->setup( 0, getActionCode( _config, "iaLeft" ) );
    _actionChannels.insert( ActionChannelT( iaLeft, buttonChannel ) );

    // create right channel
    buttonChannel = new ButtonChannel( iaRight, ascLvl, descLvl );
    buttonChannel->setup( 0, getActionCode( _config, "iaRight" ) );
    _actionChannels.insert( ActionChannelT( iaRight, buttonChannel ) );

    // create forward channel
    buttonChannel = new ButtonChannel( iaForward, ascLvl, descLvl );
    buttonChannel->setup( 0, getActionCode( _config, "iaForward" ) );
    _actionChannels.insert( ActionChannelT( iaForward, buttonChannel ) );

    // create backward channel
    buttonChannel = new ButtonChannel( iaBackward, ascLvl, descLvl );
    buttonChannel->setup( 0, getActionCode( _config, "iaBackward" ) );
    _actionChannels.insert( ActionChannelT( iaBackward, buttonChannel ) );
    
    // create left-warp channel
    buttonChannel = new ButtonChannel( iaLeftWarp, ascLvl, descLvl );
    buttonChannel->setup( 0, getActionCode( _config, "iaLeftWarp" ) );
    _actionChannels.insert( ActionChannelT( iaLeftWarp, buttonChannel ) );

    // create right-warp channel
    buttonChannel = new ButtonChannel( iaRightWarp, ascLvl, descLvl );
    buttonChannel->setup( 0, getActionCode( _config, "iaRightWarp" ) );
    _actionChannels.insert( ActionChannelT( iaRightWarp, buttonChannel ) );

    // create left-rear riser channel
    buttonChannel = new ButtonChannel( iaLeftRearRiser, ascLvl, descLvl );
    buttonChannel->setup( 0, getActionCode( _config, "iaLeftRearRiser" ) );
    _actionChannels.insert( ActionChannelT( iaLeftRearRiser, buttonChannel ) );

    // create right-rear riser channel
    buttonChannel = new ButtonChannel( iaRightRearRiser, ascLvl, descLvl );
    buttonChannel->setup( 0, getActionCode( _config, "iaRightRearRiser" ) );
    _actionChannels.insert( ActionChannelT( iaRightRearRiser, buttonChannel ) );

    // create phase channel
    buttonChannel = new ButtonChannel( iaPhase, ascLvl, descLvl );
    buttonChannel->setup( 0, getActionCode( _config, "iaPhase" ) );
    _actionChannels.insert( ActionChannelT( iaPhase, buttonChannel ) );

    // create modifier channel
    buttonChannel = new ButtonChannel( iaModifier, ascLvl*0.7f, descLvl*0.7f );
    buttonChannel->setup( 0, getActionCode( _config, "iaModifier" ) );
    _actionChannels.insert( ActionChannelT( iaModifier, buttonChannel ) );
    
    // create camera mode 0 channel
    buttonChannel = new ButtonChannel( iaCameraMode0, ascLvl, descLvl );
    buttonChannel->setup( 0, getActionCode( _config, "iaCameraMode0" ) );
    _actionChannels.insert( ActionChannelT( iaCameraMode0, buttonChannel ) );

    // create camera mode 1 channel
    buttonChannel = new ButtonChannel( iaCameraMode1, ascLvl, descLvl );
    buttonChannel->setup( 0, getActionCode( _config, "iaCameraMode1" ) );
    _actionChannels.insert( ActionChannelT( iaCameraMode1, buttonChannel ) );

    // create camera mode 2 channel
    buttonChannel = new ButtonChannel( iaCameraMode2, ascLvl, descLvl );
    buttonChannel->setup( 0, getActionCode( _config, "iaCameraMode2" ) );
    _actionChannels.insert( ActionChannelT( iaCameraMode2, buttonChannel ) );

    // create WLO channel
    buttonChannel = new ButtonChannel( iaWLO, ascLvl, descLvl );
    buttonChannel->setup( 0, getActionCode( _config, "iaWLO" ) );
    _actionChannels.insert( ActionChannelT( iaWLO, buttonChannel ) );

    // create hook knife channel
    buttonChannel = new ButtonChannel( iaHook, ascLvl, descLvl );
    buttonChannel->setup( 0, getActionCode( _config, "iaHook" ) );
    _actionChannels.insert( ActionChannelT( iaHook, buttonChannel ) );

    // create flight time (+) channel
    buttonChannel = new ButtonChannel( iaAccelerateFlightTime, ascLvl, descLvl );
    buttonChannel->setup( 0, getActionCode( _config, "iaAccelerateFlightTime" ) );
    _actionChannels.insert( ActionChannelT( iaAccelerateFlightTime, buttonChannel ) );

    // create flight time (-) channel
    buttonChannel = new ButtonChannel( iaDecelerateFlightTime, ascLvl, descLvl );
    buttonChannel->setup( 0, getActionCode( _config, "iaDecelerateFlightTime" ) );
    _actionChannels.insert( ActionChannelT( iaDecelerateFlightTime, buttonChannel ) );

    // create altimeter mode channel
    buttonChannel = new ButtonChannel( iaAltimeterMode, ascLvl, descLvl );
    buttonChannel->setup( 0, getActionCode( _config, "iaAltimeterMode" ) );
    _actionChannels.insert( ActionChannelT( iaAltimeterMode, buttonChannel ) );

    // create warn. alt. (+) channel
    buttonChannel = new ButtonChannel( iaIncreaseWarningAltitude, ascLvl, descLvl );
    buttonChannel->setup( 0, getActionCode( _config, "iaIncreaseWarningAltitude" ) );
    _actionChannels.insert( ActionChannelT( iaIncreaseWarningAltitude, buttonChannel ) );

    // create warn. alt. (-) channel
    buttonChannel = new ButtonChannel( iaDecreaseWarningAltitude, ascLvl, descLvl );
    buttonChannel->setup( 0, getActionCode( _config, "iaDecreaseWarningAltitude" ) );
    _actionChannels.insert( ActionChannelT( iaDecreaseWarningAltitude, buttonChannel ) );

    // create HUD mode channel
    buttonChannel = new ButtonChannel( iaSwitchHUDMode, ascLvl, descLvl );
    buttonChannel->setup( 0, getActionCode( _config, "iaSwitchHUDMode" ) );
    _actionChannels.insert( ActionChannelT( iaSwitchHUDMode, buttonChannel ) );

    // create music volume (+) channel
    buttonChannel = new ButtonChannel( iaIncreaseMusicVolume, ascLvl, descLvl );
    buttonChannel->setup( 0, getActionCode( _config, "iaIncreaseMusicVolume" ) );
    _actionChannels.insert( ActionChannelT( iaIncreaseMusicVolume, buttonChannel ) );

    // create music volume (-) channel
    buttonChannel = new ButtonChannel( iaDecreaseMusicVolume, ascLvl, descLvl );
    buttonChannel->setup( 0, getActionCode( _config, "iaDecreaseMusicVolume" ) );
    _actionChannels.insert( ActionChannelT( iaDecreaseMusicVolume, buttonChannel ) );

    // cutaway
    buttonChannel = new ButtonChannel( iaCutAway, ascLvl, descLvl );
    buttonChannel->setup( 0, getActionCode( _config, "iaCutAway" ) );
    _actionChannels.insert( ActionChannelT( iaCutAway, buttonChannel ) );
	
    // pull reserve
    buttonChannel = new ButtonChannel( iaPullReserve, ascLvl, descLvl );
    buttonChannel->setup( 0, getActionCode( _config, "iaPullReserve" ) );
    _actionChannels.insert( ActionChannelT( iaPullReserve, buttonChannel ) );

    // create left reserve channel
    buttonChannel = new ButtonChannel( iaReserveLeft, ascLvl, descLvl );
    buttonChannel->setup( 0, getActionCode( _config, "iaReserveLeft" ) );
    _actionChannels.insert( ActionChannelT( iaReserveLeft, buttonChannel ) );

    // create right reserve channel
    buttonChannel = new ButtonChannel( iaReserveRight, ascLvl, descLvl );
    buttonChannel->setup( 0, getActionCode( _config, "iaReserveRight" ) );
    _actionChannels.insert( ActionChannelT( iaReserveRight, buttonChannel ) );

    // create left-warp reserve channel
    buttonChannel = new ButtonChannel( iaReserveLeftWarp, ascLvl, descLvl );
    buttonChannel->setup( 0, getActionCode( _config, "iaReserveLeftWarp" ) );
    _actionChannels.insert( ActionChannelT( iaReserveLeftWarp, buttonChannel ) );

    // create right-warp reserve channel
	buttonChannel = new ButtonChannel( iaReserveRightWarp, ascLvl, descLvl );
    buttonChannel->setup( 0, getActionCode( _config, "iaReserveRightWarp" ) );
    _actionChannels.insert( ActionChannelT( iaReserveRightWarp, buttonChannel ) );

    // create left rear riser reserve channel
    buttonChannel = new ButtonChannel( iaReserveLeftRearRiser, ascLvl, descLvl );
    buttonChannel->setup( 0, getActionCode( _config, "iaReserveLeftRearRiser" ) );
    _actionChannels.insert( ActionChannelT( iaReserveLeftRearRiser, buttonChannel ) );

    // create right rear riser reserve channel
	buttonChannel = new ButtonChannel( iaReserveRightRearRiser, ascLvl, descLvl );
    buttonChannel->setup( 0, getActionCode( _config, "iaReserveRightRearRiser" ) );
    _actionChannels.insert( ActionChannelT( iaReserveRightRearRiser, buttonChannel ) );

    // create rear break channel
    buttonChannel = new ButtonChannel( iaRearBrake, ascLvl, descLvl );
    buttonChannel->setup( 0, getActionCode( _config, "iaRearBrake" ) );
    _actionChannels.insert( ActionChannelT( iaRearBrake, buttonChannel ) );

    // create right channel
    buttonChannel = new ButtonChannel( iaRight, ascLvl, descLvl );
    buttonChannel->setup( 0, getActionCode( _config, "iaRight" ) );
    _actionChannels.insert( ActionChannelT( iaRight, buttonChannel ) );

	/// JOYSTICK CHANNELS

		// create left channel (joystick)
		_actionChannels.insert( ActionChannelT( iaLeftJoy, new JoystickChannel( iaLeftJoy ) ) );
		// create left channel (joystick)
		_actionChannels.insert( ActionChannelT( iaRightJoy, new JoystickChannel( iaRightJoy ) ) );
		// create backward channel (joystick)
		_actionChannels.insert( ActionChannelT( iaBackwardJoy, new JoystickChannel( iaBackwardJoy ) ) );
		// create cutaway channel (joystick)
		_actionChannels.insert( ActionChannelT( iaCutAwayJoy, new JoystickChannel( iaCutAwayJoy ) ) );

		//// cutaway (joystick)
		//buttonChannel = new ButtonChannel( iaCutAwayJoy, 1, 4 );
		//unsigned int JoyBt1 = 0;
		//buttonChannel->setup( 2, JoyBt1 );
		//_actionChannels.insert( ActionChannelT( iaCutAwayJoy, buttonChannel ) );
	

    // default channels : head left/right/up/down
    _actionChannels.insert( ActionChannelT( iaHeadLeft, new MouseChannel( iaHeadLeft ) ) );
    _actionChannels.insert( ActionChannelT( iaHeadRight, new MouseChannel( iaHeadRight ) ) );
    _actionChannels.insert( ActionChannelT( iaHeadUp, new MouseChannel( iaHeadUp ) ) );
    _actionChannels.insert( ActionChannelT( iaHeadDown, new MouseChannel( iaHeadDown ) ) );

    // default channels : zoom in and zoom out
    ButtonChannel* channel = new ButtonChannel( iaZoomIn, 2, 2 );
    channel->setup( 1, 0 );
    _actionChannels.insert( ActionChannelT( iaZoomIn, channel ) );
    channel = new ButtonChannel( iaZoomOut, 2, 2 );
    channel->setup( 1, 1 );
    _actionChannels.insert( ActionChannelT( iaZoomOut, channel ) );

    // default channels : camera mode 3
    _actionChannels.insert( ActionChannelT( iaCameraMode3, new ButtonChannel( iaCameraMode3 ) ) );

    // developer's channels
    #ifdef GAMEPLAY_DEVELOPER_EDITION
        _actionChannels.insert( ActionChannelT( iaGlobalDeceleration, new ButtonChannel( iaGlobalDeceleration ) ) );
        _actionChannels.insert( ActionChannelT( iaGlobalAcceleration, new ButtonChannel( iaGlobalAcceleration ) ) );
    #endif
}
Exemple #3
0
static void takeAction (Action *action, EnumAction actionCode) {
	unsigned int newTime, oldTime; 
	unsigned long longNewTime, longOldTime;
	int newIdxTimeframe, tempTime;
	CtnrFile *newFile;
	CtnrBlock *newBlock, *soundInsertBlock;
	int newIdxAction;
	EnumAction newActionCode;
	EnumBorderCrossing direction;
	signed long l;	
	int destination, aux, i, ret;
	int status;
	BOOL reposition = FALSE;
	BOOL isTooFar = FALSE;
	ListItem *list, *tempList;
	char filename[PATH_LENGTH];
	char *cursor, *cursor2;
	CtnrFile *replayFile;
		
	replayFile = NULL;
	list = NULL;
	oldTime = compressTime(Snd_A1800_GetCurrentTime(),context.package->timePrecision);
	newFile = 0;
	newTime = -1;
	newBlock = 0;
		
	if (actionCode == -1)
		actionCode = getActionCode(action);
	if (action) {
		aux = action->aux;
		destination = action->destination;
	}
		
	switch (actionCode) {
		case JUMP_LIST:
			stop();
			list = &context.package->lists[destination];
			context.idxActiveList = destination;
			switch (getListRotation(aux)) {
				case 0:
				    cursor = getCurrentList(list);
				    strcpy(filename,cursor);
					break;
				case 1:
				    strcpy(filename,getNextList(list,TRUE));
					break;
				case -1:
				    strcpy(filename,getPreviousList(list));
					break;
			}
			if (!filename[0]) { 
				// empty list
				insertSound(&pkgSystem.files[EMPTY_LIST_FILE_IDX],NULL,FALSE);
				// empty list of packages; redirect to current point in list of lists
				list = &context.package->lists[0];
				context.idxActiveList = 0;
			    cursor = getCurrentList(list);
			    strcpy(filename,cursor);
			} 
			if (list->listType == LIST_OF_PACKAGES) {
				// load package
				switch (filename[0]) {
					case SYS_PKG_CHAR:
						context.queuedPackageType = PKG_SYS;
						destination = replaceStack(filename+1,&pkgSystem);
						break;
					case APP_PKG_CHAR:
						context.queuedPackageType = PKG_APP;
						destination = replaceStack(filename+1,&pkgSystem);
						break;
					default:
						context.queuedPackageType = PKG_MSG;
						destination = replaceStack(filename,&pkgSystem);
						break;
				}
				context.queuedPackageNameIndex = destination;
			} else { // list->listType != LIST_OF_PACKAGES
				// play sound of subject
				newFile = getListFile(filename);
				newTime = 0;
				reposition = TRUE;
			}
			break;
		
		case JUMP_PACKAGE:
			if (aux == PKG_VARIABLE) {
				strcpy(filename,getCurrentList(&pkgSystem.lists[destination]));
				switch (filename[0]) {
					case SYS_PKG_CHAR:
						aux = PKG_SYS;
						destination = replaceStack(filename+1,&pkgSystem);
						break;
					case APP_PKG_CHAR:
						aux = PKG_APP;
						destination = replaceStack(filename+1,&pkgSystem);
						break;
					default:
						aux = PKG_MSG;
						destination = replaceStack(filename,&pkgSystem);
						break;
				}
			}
			context.queuedPackageType = aux;
			context.queuedPackageNameIndex = destination;
			break;  // sets up main loop to handle this, rather than building up a stack overflow

		case COPY:
			stop();
			tempList = &context.package->lists[destination];
			getListFilename(filename,destination,FALSE);
			cursor = getCurrentList(tempList);
			if (PRE_COPY_FILE_IDX)
				insertSound(&pkgSystem.files[PRE_COPY_FILE_IDX],NULL,TRUE);  
			ret = d2dCopy((const char *)filename,(const char *)cursor);
			if (ret == 0 && POST_COPY_FILE_IDX) 
				insertSound(&pkgSystem.files[POST_COPY_FILE_IDX],NULL,TRUE); 
//			newBlock = &context.package->blocks[aux];
//			newTime = newBlock->startTime;
//			reposition = TRUE;
			break;		

		case DELETE:
			stop();
			tempList = &context.package->lists[destination];
			getListFilename(filename,destination,TRUE);
			cursor = getCurrentList(tempList);			
			ret = findDeleteStringFromFile(LIST_PATH,filename,cursor,TRUE);
			tempList->currentFilePosition = -1; // forces next list action to reload
			if (ret != -1)
				ret = deletePackage(cursor);
			else
				logException(29,cursor,0);

			list = &context.package->lists[aux];
			context.idxActiveList = aux;
			newFile = getListFile(getCurrentList(list));
			newTime = 0;
			reposition = TRUE;

//			newBlock = &context.package->blocks[aux];
//			newTime = newBlock->startTime;
//			reposition = TRUE;
			break;
			
		case TRIM:
			stop();
			tempList = &context.package->lists[destination];
			cursor = getCurrentList(tempList);
			strcpy(filename,USER_PATH);
			strcat(filename,cursor);  //todo: address application packages
			strcat(filename,AUDIO_FILE_EXT);
			edit(filename);
			context.queuedPackageType = PKG_MSG;
			destination = replaceStack(cursor,context.package);
			context.queuedPackageNameIndex = destination;
			break;
			
		case SPEED_UP:
			adjustSpeed(SPEED_INCREMENT,TRUE);
			break;

		case SPEED_DOWN:
			adjustSpeed(-SPEED_INCREMENT,TRUE);
			break;

		case SPEED_NORMAL:
			adjustSpeed(NORMAL_SPEED,FALSE);
			break;

		case VOLUME_UP:
			adjustVolume(VOLUME_INCREMENT,TRUE,FALSE);
			break;

		case VOLUME_DOWN:
			adjustVolume(-VOLUME_INCREMENT,TRUE,FALSE);
			break;

		case VOLUME_NORMAL:
			adjustVolume(NORMAL_VOLUME,FALSE,FALSE);
			break;

		case LED_RED_ON:
			setLED(LED_RED,TRUE);
			break;	
			
		case LED_RED_OFF:
			setLED(LED_RED,FALSE);
			break;	

		case LED_GREEN_ON:
			setLED(LED_GREEN,TRUE);
			break;
			
		case LED_GREEN_OFF:	
			setLED(LED_GREEN,FALSE);
			break;

		case LED_ALL_ON:
			setLED(LED_ALL,TRUE);	
			break;	

		case LED_ALL_OFF:
			setLED(LED_ALL,TRUE);
			break;
			
		case USB_DEVICE_ON:
			setUSBDevice(TRUE);
			newBlock = &context.package->blocks[destination];
			newTime = newBlock->startTime;
			reposition = TRUE;
			break;	
					
		case USB_HOST_ON:
/*			stop();
			setUSBDevice(TRUE);
			newBlock = &context.package->blocks[destination];
			newTime = newBlock->startTime;
			reposition = TRUE;
*/			break;	
					
		case STOP:
			stop();
			enterOrExitAllBlocks(context.idxTimeframe,EXITING);
			break;

		case PLAY_PAUSE:
			status = SACM_Status();
			switch (status) {
				case 0:
//					if (context.package->pkg_type != PKG_SYS)
						markStartPlay(Snd_A1800_GetCurrentTime(),context.package->strHeapStack+context.package->idxName);
					if (context.idxActiveList == -1) {
						enterOrExitAllBlocks(context.idxTimeframe,ENTERING);
						i = getStartingBlockIdxFromTimeline(context.idxTimeframe);
						if (i != -1) 
							processStartBlock(i);
						play(context.file,getCurrentTimeframeStart());
					} else
						play(context.file,0);
					break;
				case C_SACM_RECORD:
				case C_SACM_PLAY:
					context.isPaused = TRUE;
					pause();
					break;
				case C_SACM_PAUSE:
					context.isPaused = FALSE;
					resume();	
					break;
				default:
					if (context.isPaused) {
						context.isPaused = FALSE;
						resume();	
					} else {
						context.isPaused = TRUE;
						pause();
					}		
					break;
			}
			break;
			
		case PAUSE:
			pause();
			context.isPaused = TRUE;
			break;
			
		case RECORD_TITLE: // deprecated
		case RECORD_MSG:
			stop();
/*			// Not currently allowing sound inserts before record commands since aux is used for recording from another headphone jack
			// Although the SPINS part of the headphone jack thing isn't currently working.
			if (action && hasSoundInsert(action)) {
				soundInsertBlock = &pkgSystem.blocks[getSoundInsertIdxFromAux(aux)];
				insertSound(getFileFromBlock(soundInsertBlock),soundInsertBlock,TRUE);
				wait(500);
			}
*/
			if(vCur_1 < V_MIN_RECORD_VOLTAGE) {
				refuse_lowvoltage(0);
				break;
			}
			
			cursor = getCurrentList(&pkgSystem.lists[context.package->idxMasterList]);
			do {
				strcpy(filename,USER_PATH);
				getPkgNumber(filename+strlen(USER_PATH),TRUE);
				strcat(filename,(const char *)CATEGORY_DELIM_STR);
				strcat(filename,cursor); // adds current listname to new recording name
				cursor2 = filename + strlen(filename);
				strcat(filename,AUDIO_FILE_EXT);
				ret = fileExists((LPSTR)filename); // this causes approx 1 sec delay!
			} while (ret);
			*cursor2 = 0; // remove extension
			strcpy(filename,filename+strlen(USER_PATH)); //remove path
			
			ret = createRecording(filename,aux,cursor);
			if (ret != -1) {
				destination = replaceStack(filename,context.package);
				context.queuedPackageNameIndex = destination;
				context.queuedPackageType = PKG_MSG;
			} else
				logException(28,"recording failed",RESET); //todo: add voice error msg?
			break;	

		case CALL_BLOCK:
			// TODO: handle error (return of -1) if stack is full
			stackPush(context.package,context.file,oldTime - getRewind(aux)); // times are compressed
			// this is designed to fall through
			
		case JUMP_BLOCK:
			newBlock = &context.package->blocks[destination];
			newTime = newBlock->startTime;
			reposition = TRUE;
			break;
	
		case RETURN:
			if (stackPop(&context.package,&newFile,&newTime))  // times are compressed 
				reposition = TRUE;
			break;

		case FWD:
			newActionCode = getStartEndCodeFromTimeframe(context.idxTimeframe,FORWARD_JUMPING, &newTime, &newIdxAction);
			switch (newActionCode) {
				case NOP:
				case PAUSE:
					break;
				case STOP:
					//rewind to give context before stopping
					newTime -= compressTime(BLOCK_END_LEADER,context.package->timePrecision);
					break;
				case JUMP_BLOCK:
					//follow this link
					newBlock = &context.package->blocks[context.package->actions[newIdxAction].destination];
					newTime = newBlock->startTime;
					break;
				case RETURN:
					stackPop(&context.package,&newFile,&newTime); //todo: double verify there was something on stack (shouldn't have gotten RETURN if not) 
					break;
				default:
					//no action needed
					break;
			}
			reposition = TRUE;
			break;
			
		case BACK:
			// test whether within the start leader to determine whether to go to last start or to previous start before that
			if ((oldTime - getCurrentTimeframeStart()) > compressTime(BLOCK_START_LEADER, context.package->timePrecision)) {
				// just move to start time of same timeframe 
				newTime = getCurrentTimeframeStart(); // must make sure we call the Start event 
			} else {
				newActionCode = getStartEndCodeFromTimeframe(context.idxTimeframe,BACKWARD_JUMPING, &newTime, &newIdxAction);
				switch (newActionCode) {
					case NOP:
					case PAUSE:
					case STOP:
						break;
					case JUMP_BLOCK:
						//follow this link
						newBlock = &context.package->blocks[context.package->actions[newIdxAction].destination];
						newTime = newBlock->startTime;
						break;  
					case RETURN:
						stackPop(&context.package,&newFile,&newTime); //todo: double verify there was something on stack (shouldn't have gotten RETURN if not) 
						break;
					default:
						//no action needed
						break;						
				}
			}
			reposition = TRUE;
			break;

		case JUMP_TIME:
			// skip forward/back from relative position
			// observe block boundary when they exist, but leap beyond them
			// todo:do not leap over newFile boundaries
			// if system package action, reset context to user package for this action
			if (context.returnPackage)
				context.package = context.returnPackage;
			if (context.package != &pkgSystem) {
				longOldTime = Snd_A1800_GetCurrentTime();
				l = (signed long)extractSignedTime(destination,context.package->timePrecision); // hoping this brings back an originally negative number
				longNewTime = longOldTime + l;
				if (l >= 0) 
					direction = FORWARD_JUMPING;
				else {
					direction = BACKWARD_JUMPING;
					if (abs(l) > longOldTime)
						longNewTime = 0;
				}
				newTime = compressTime(longNewTime,context.package->timePrecision);
	
				// check for interfering block events
				newIdxTimeframe = context.idxTimeframe;
				do {
					newActionCode = getStartEndCodeFromTimeframe(newIdxTimeframe,direction, &tempTime, &newIdxAction);
					if (direction == FORWARD_JUMPING) 
						isTooFar = blockTimeline[++newIdxTimeframe].time > newTime;
					else
						isTooFar = blockTimeline[--newIdxTimeframe].time < newTime;
				} while (!isTooFar && newActionCode == NOP);
				switch (newActionCode) {
					case JUMP_BLOCK:
						newBlock = &context.package->blocks[context.package->actions[newIdxAction].destination];
						newTime = newBlock->startTime;
						newFile = getFileFromBlock(newBlock);
						break;  
					case RETURN:
						stackPop(&context.package,&newFile,&newTime); //todo: double verify there was something on stack (shouldn't have gotten RETURN if not) 
						break;
					default:
						//no action needed
						break;
				}
				playActionSound(JUMP_TIME);
				reposition = TRUE;
			} // context is not system file
			break;
		case SLEEP:
			// call sleep function
			setOperationalMode((int)P_SLEEP); 
			break;
		case HALT:
			// call sleep function
			setOperationalMode((int)P_HALT); 
			break;
		case NOP:
			// no operation
			break;
		default:
			//nothing should default here
			logException(1,0,USB_MODE);
			break;
	}
		
	if (reposition) {
		//todo: am i catching every possible change in file?		
		if (newBlock && !newFile) 
			newFile = getFileFromBlock(newBlock);
		if (newFile && newFile != context.file) {
			enterOrExitAllBlocks(context.idxTimeframe,EXITING);
			context.file = newFile;
			if (!list)
				buildBlockTimelines(newFile);
			context.idxTimeframe = -1; // to signal it hasn't been set yet
			context.timeNextTimeframe = -1; // resets this -- necessary for lists that dont go to processTimelineJump
		}
		if (!list) {
			context.idxActiveList = -1;
			newIdxTimeframe = getIdxTimeline(newTime);
			if (newIdxTimeframe != context.idxTimeframe) 
				processTimelineJump(context.idxTimeframe, newIdxTimeframe);  // this resets context.idxTimeframe and context.timeNextTimeframe
		}
	}
	
	// now that context.idxTimeframe has been set for repositions, we can insert sounds
	if (action && hasSoundInsert(action)) {
		if (reposition) 
			stop();  // stop currently playing audio first or insertSound() will return to it
		if (actionCode == JUMP_TIME) {
			if (context.returnPackage)
				context.package = &pkgSystem;
			soundInsertBlock = &context.package->blocks[getSoundInsertIdxFromAux(aux)];
			insertSound(getFileFromBlock(soundInsertBlock),soundInsertBlock,TRUE);
		}
		else {
			soundInsertBlock = &context.package->blocks[getSoundInsertIdxFromAux(aux)];
			insertSound(getFileFromBlock(soundInsertBlock),soundInsertBlock,FALSE);
		}
	}
	// process start block action if landing on the start of a new block
	if (reposition && newBlock && newTime == newBlock->startTime)
		processStartBlock(newBlock - context.package->blocks);
	if (list) {
		soundInsertBlock = getStartInsert(list->actionStartEnd, list->idxFirstAction);
		if (soundInsertBlock)
			insertSound(getFileFromBlock(soundInsertBlock),soundInsertBlock,FALSE);
	}		
	if (actionCode == JUMP_TIME && context.returnPackage) {  // returning to user package after possibly inserting a system sound above
		context.package = context.returnPackage;
		context.returnPackage = NULL;
	}
	if (actionCode == SPEED_UP || actionCode == SPEED_DOWN) {
		context.isPaused = FALSE;
		resume();	
	}
	if (reposition)
		play(context.file,newTime); //todo: chg to seek if same file
	//todo: maybe for JUMP_BLOCK (not CALL_BLOCK) , allow offsets within a block (stored in first 13 bits of aux)
}