void wait_delayorinput( JE_boolean keyboard, JE_boolean mouse, JE_boolean joystick ) { service_SDL_events(true); while (SDL_GetTicks() < target && !((keyboard && keydown) || (mouse && mousedown) || (joystick && joydown))) { SDL_Delay(SDL_GetTicks() - target > SDL_POLL_INTERVAL ? SDL_POLL_INTERVAL : SDL_GetTicks() - target); push_joysticks_as_keyboard(); service_SDL_events(false); } }
void wait_noinput( JE_boolean keyboard, JE_boolean mouse, JE_boolean joystick ) { service_SDL_events(false); while ((keyboard && keydown) || (mouse && mousedown) || (joystick && joydown)) { SDL_Delay(SDL_POLL_INTERVAL); poll_joysticks(); service_SDL_events(false); if (isNetworkGame) network_check(); } }
void JE_textMenuWait( JE_word *waitTime, JE_boolean doGamma ) { set_mouse_position(160, 100); do { JE_showVGA(); push_joysticks_as_keyboard(); service_SDL_events(true); inputDetected = newkey | mousedown; if (lastkey_sym == SDLK_SPACE) { lastkey_sym = SDLK_RETURN; } if (mousedown) { newkey = true; lastkey_sym = SDLK_RETURN; } if (mouseInstalled && input_grabbed) { if (abs(mouse_y - 100) > 10) { inputDetected = true; if (mouse_y - 100 < 0) { lastkey_sym = SDLK_UP; } else { lastkey_sym = SDLK_DOWN; } newkey = true; } if (abs(mouse_x - 160) > 10) { inputDetected = true; if (mouse_x - 160 < 0) { lastkey_sym = SDLK_LEFT; } else { lastkey_sym = SDLK_RIGHT; } newkey = true; } } NETWORK_KEEP_ALIVE(); SDL_Delay(16); if (*waitTime > 0) { (*waitTime)--; } } while (!(inputDetected || *waitTime == 1 || haltGame)); }
JE_word JE_mousePosition( JE_word *mouseX, JE_word *mouseY ) { service_SDL_events(false); *mouseX = mouse_x; *mouseY = mouse_y; return mousedown ? lastmouse_but : 0; }
void wait_noinput( JE_boolean keyboard, JE_boolean mouse, JE_boolean joystick ) { service_SDL_events(false); while ((keyboard && keydown) || (mouse && mousedown) || (joystick && joydown)) { JE_showVGA(); // Must update screen on Android to get new mouse events SDL_Delay(SDL_POLL_INTERVAL); poll_joysticks(); service_SDL_events(false); #ifdef WITH_NETWORK if (isNetworkGame) network_check(); #endif } }
void service_wait_delay( void ) { while (SDL_GetTicks() < target) { SDL_Delay(SDL_GetTicks() - target > SDL_POLL_INTERVAL ? SDL_POLL_INTERVAL : SDL_GetTicks() - target); service_SDL_events(false); } }
// something has gone wrong :( void network_tyrian_halt( unsigned int err, bool attempt_sync ) { #ifdef __BLACKBERRY__ quit = true; #else const char *err_msg[] = { "Quitting...", "Other player quit the game.", "Network connection was lost.", "Network connection failed.", "Network version mismatch.", "Network delay mismatch.", "Network player number conflict.", }; quit = true; if (err >= COUNTOF(err_msg)) err = 0; fade_black(10); VGAScreen = VGAScreenSeg; JE_loadPic(VGAScreen, 2, false); JE_dString(VGAScreen, JE_fontCenter(err_msg[err], SMALL_FONT_SHAPES), 140, err_msg[err], SMALL_FONT_SHAPES); JE_showVGA(); fade_palette(colors, 10, 0, 255); if (attempt_sync) { while (!network_is_sync() && network_is_alive()) { service_SDL_events(false); network_check(); SDL_Delay(16); } } if (err) { while (!JE_anyButton()) SDL_Delay(16); } fade_black(10); SDLNet_Quit(); JE_tyrianHalt(5); #endif }
void JE_playAnim( const char *animfile, uint8_t startingframe, uint8_t speed ) { uint32_t i; int pageNum; if (JE_loadAnim(animfile) != 0) { return; /* Failed to open or process file */ } /* Blank screen */ JE_clr256(VGAScreen); JE_showVGA(); /* re FileHeader.nRecords-1: It's -1 in the pascal too. * The final frame is a delta of the first, and we don't need that. * We could also, if we ever ended up needing to loop anis, check * the bools in the header to see if we should render the last * frame. But that's never going to be encessary :) */ for (i = startingframe; i < FileHeader.nRecords-1; i++) { /* Handle boring crap */ setjasondelay(speed); /* Load required frame. The loading function is smart enough to not re-load an already loaded frame */ pageNum = JE_findPage(i); if(pageNum == -1) { break; } if (JE_loadPage(pageNum) != 0) { break; } /* render frame. */ if (JE_renderFrame(i) != 0) { break; } JE_showVGA(); /* Return early if user presses a key */ service_SDL_events(true); if (newkey) { break; } /* Wait until we need the next frame */ NETWORK_KEEP_ALIVE(); wait_delay(); } JE_closeAnim(); }
// captures joystick input for configuring assignments // returns false if non-joystick input was detected // TODO: input from joystick other than the one being configured probably should not be ignored bool detect_joystick_assignment( int j, Joystick_assignment *assignment ) { // get initial joystick state to compare against to see if anything was pressed const int axes = SDL_JoystickNumAxes(joystick[j].handle); Sint16 *axis = malloc(axes * sizeof(*axis)); for (int i = 0; i < axes; i++) axis[i] = SDL_JoystickGetAxis(joystick[j].handle, i); const int buttons = SDL_JoystickNumButtons(joystick[j].handle); Uint8 *button = malloc(buttons * sizeof(*button)); for (int i = 0; i < buttons; i++) button[i] = SDL_JoystickGetButton(joystick[j].handle, i); const int hats = SDL_JoystickNumHats(joystick[j].handle); Uint8 *hat = malloc(hats * sizeof(*hat)); for (int i = 0; i < hats; i++) hat[i] = SDL_JoystickGetHat(joystick[j].handle, i); bool detected = false; do { setjasondelay(1); SDL_JoystickUpdate(); for (int i = 0; i < axes; ++i) { Sint16 temp = SDL_JoystickGetAxis(joystick[j].handle, i); if (abs(temp - axis[i]) > joystick_analog_max * 2 / 3) { assignment->type = AXIS; assignment->num = i; assignment->negative_axis = temp < axis[i]; detected = true; break; } } for (int i = 0; i < buttons; ++i) { Uint8 new_button = SDL_JoystickGetButton(joystick[j].handle, i), changed = button[i] ^ new_button; if (!changed) continue; if (new_button == 0) // button was released { button[i] = new_button; } else // button was pressed { assignment->type = BUTTON; assignment->num = i; detected = true; break; } } for (int i = 0; i < hats; ++i) { Uint8 new_hat = SDL_JoystickGetHat(joystick[j].handle, i), changed = hat[i] ^ new_hat; if (!changed) continue; if ((new_hat & changed) == SDL_HAT_CENTERED) // hat was centered { hat[i] = new_hat; } else { assignment->type = HAT; assignment->num = i; assignment->x_axis = changed & (SDL_HAT_LEFT | SDL_HAT_RIGHT); assignment->negative_axis = changed & (SDL_HAT_LEFT | SDL_HAT_UP); detected = true; } } service_SDL_events(true); JE_showVGA(); wait_delay(); } while (!detected && !newkey && !newmouse); free(axis); free(button); free(hat); return detected; }
JE_boolean JE_anyButton( void ) { poll_joysticks(); service_SDL_events(true); return newkey || mousedown || joydown; }
// attempt to punch through firewall by firing off UDP packets at the opponent // exchange game information int network_connect( void ) { #ifdef __BLACKBERRY__ #else SDLNet_ResolveHost(&ip, network_opponent_host, network_opponent_port); SDLNet_UDP_Bind(socket, 0, &ip); Uint16 episodes = 0, episodes_local = 0; assert(EPISODE_MAX <= 16); for (int i = EPISODE_MAX - 1; i >= 0; i--) { episodes <<= 1; episodes |= (episodeAvail[i] != 0); } episodes_local = episodes; assert(NET_PACKET_SIZE - 12 >= 20 + 1); if (strlen(network_player_name) > 20) network_player_name[20] = '\0'; connect_reset: network_prepare(PACKET_CONNECT); SDLNet_Write16(NET_VERSION, &packet_out_temp->data[4]); SDLNet_Write16(network_delay, &packet_out_temp->data[6]); SDLNet_Write16(episodes_local, &packet_out_temp->data[8]); SDLNet_Write16(thisPlayerNum, &packet_out_temp->data[10]); strcpy((char *)&packet_out_temp->data[12], network_player_name); network_send(12 + strlen(network_player_name) + 1); // PACKET_CONNECT // until opponent sends connect packet while (true) { push_joysticks_as_keyboard(); service_SDL_events(false); if (newkey && lastkey_sym == SDLK_ESCAPE) network_tyrian_halt(0, false); // never timeout last_in_tick = SDL_GetTicks(); if (packet_in[0] && SDLNet_Read16(&packet_in[0]->data[0]) == PACKET_CONNECT) break; network_update(); network_check(); SDL_Delay(16); } connect_again: if (SDLNet_Read16(&packet_in[0]->data[4]) != NET_VERSION) { fprintf(stderr, "error: network version did not match opponent's\n"); network_tyrian_halt(4, true); } if (SDLNet_Read16(&packet_in[0]->data[6]) != network_delay) { fprintf(stderr, "error: network delay did not match opponent's\n"); network_tyrian_halt(5, true); } if (SDLNet_Read16(&packet_in[0]->data[10]) == thisPlayerNum) { fprintf(stderr, "error: player number conflicts with opponent's\n"); network_tyrian_halt(6, true); } episodes = SDLNet_Read16(&packet_in[0]->data[8]); for (int i = 0; i < EPISODE_MAX; i++) { episodeAvail[i] &= (episodes & 1); episodes >>= 1; } network_opponent_name = malloc(packet_in[0]->len - 12 + 1); strcpy(network_opponent_name, (char *)&packet_in[0]->data[12]); network_update(); // until opponent has acknowledged while (!network_is_sync()) { service_SDL_events(false); // got a duplicate packet; process it again (but why?) if (packet_in[0] && SDLNet_Read16(&packet_in[0]->data[0]) == PACKET_CONNECT) goto connect_again; network_check(); // maybe opponent didn't get our packet if (SDL_GetTicks() - last_out_tick > NET_RETRY) goto connect_reset; SDL_Delay(16); } // send another packet since sometimes the network syncs without both connect packets exchanged // there should be a better way to handle this network_prepare(PACKET_CONNECT); SDLNet_Write16(NET_VERSION, &packet_out_temp->data[4]); SDLNet_Write16(network_delay, &packet_out_temp->data[6]); SDLNet_Write16(episodes_local, &packet_out_temp->data[8]); SDLNet_Write16(thisPlayerNum, &packet_out_temp->data[10]); strcpy((char *)&packet_out_temp->data[12], network_player_name); network_send(12 + strlen(network_player_name) + 1); // PACKET_CONNECT connected = true; #endif return 0; }
void JE_jukeboxGo( void ) { JE_boolean weirdMusic, weirdCurrent; JE_byte weirdSpeed = 0; char tempStr[64]; JE_byte lastSong; JE_byte tempVolume; JE_boolean youStopped, drawText, quit, fade; weirdMusic = false; weirdCurrent = true; drawText = true; fx = false; fxNum = 1; lastSong = currentJukeboxSong; JE_fadeBlack(10); SDL_FillRect(VGAScreenSeg, NULL, 0x0); JE_showVGA(); JE_updateColorsFast(vga_palette); //JE_fadeColor(10); JE_starlib_init(); quit = false; fade = false; repeatedFade = false; tempVolume = tyrMusicVolume; youStopped = false; JE_wipeKey(); do { tempScreenSeg = VGAScreenSeg; if (weirdMusic) { if (delaycount2() == 0) { setjasondelay2(weirdSpeed); if (weirdCurrent) { JE_setVol(tempVolume / 2, fxVolume); } else { JE_setVol(tempVolume, fxVolume); } weirdCurrent = !weirdCurrent; } } if (repeated && !repeatedFade) { fade = true; repeatedFade = true; } if ( ( (repeated && !fade) || !playing) && !youStopped) { currentJukeboxSong = ( mt_rand() % MUSIC_NUM ); JE_playNewSong(); } setdelay(1); push_joysticks_as_keyboard(); service_SDL_events(true); JE_starlib_main(); if (lastSong != currentJukeboxSong) { lastSong = currentJukeboxSong; JE_bar(50, 190, 250, 198, 0); } if (drawText) { tempScreenSeg = VGAScreenSeg; if (fx) { sprintf(tempStr, "%d %s", fxNum, soundTitle[fxNum - 1]); JE_bar(50, 190, 250, 198, 0); JE_outText(JE_fontCenter(tempStr, TINY_FONT), 190, tempStr, 1, 4); } else { sprintf(tempStr, "%d %s", currentJukeboxSong, musicTitle[currentJukeboxSong - 1]); JE_outText(JE_fontCenter(tempStr, TINY_FONT), 190, tempStr, 1, 4); } tempScreenSeg = VGAScreenSeg; JE_outText(JE_fontCenter("Press ESC to quit the jukebox.", TINY_FONT), 170, "Press ESC to quit the jukebox.", 1, 0); tempScreenSeg = VGAScreenSeg; JE_outText(JE_fontCenter("Arrow keys change the song being played.", TINY_FONT), 180, "Arrow keys change the song being played.", 1, 0); } JE_showVGA(); wait_delay(); if (fade) { if (volumeActive) { if (tempVolume > 5) { tempVolume -= 2; JE_setVol(tempVolume, fxVolume); } else { fade = false; } } else if (speed < 0xE000) { speed += 0x800; } else { speed = 0xE000; fade = false; } JE_resetTimerInt(); JE_setTimerInt(); } if (JE_mousePosition(&x, &y) > 0 || button[0]) { quit = true; JE_wipeKey(); } if (newkey) { JE_newSpeed(); switch (lastkey_sym) { case SDLK_ESCAPE: /* quit jukebox */ case SDLK_q: quit = true; break; case SDLK_r: /* restart song */ JE_jukebox_selectSong(1); break; case SDLK_n: /* toggle continuous play */ continuousPlay = !continuousPlay; break; case SDLK_v: volumeActive = !volumeActive; break; case SDLK_t: /* No idea what this is doing -- possibly resetting to default speed? */ speed = 0x4300; JE_resetTimerInt(); JE_setTimerInt(); break; case SDLK_f: fade = !fade; break; case SDLK_COMMA: /* dec sound effect */ fxNum = (fxNum - 1 < 1) ? SOUND_NUM + 9 : fxNum - 1; break; case SDLK_PERIOD: /* inc sound effect */ fxNum = (fxNum + 1 > SOUND_NUM + 9) ? 1 : fxNum + 1; break; case SDLK_SLASH: /* switch to sfx mode */ fx = !fx; break; case SDLK_SEMICOLON: JE_playSampleNum(fxNum); break; case SDLK_RETURN: currentJukeboxSong++; JE_playNewSong(); youStopped = false; break; case SDLK_s: JE_jukebox_selectSong(0); youStopped = true; break; case SDLK_w: if (!weirdMusic) { weirdMusic = true; weirdSpeed = 10; } else if (weirdSpeed > 1) { weirdSpeed--; } else { weirdMusic = false; if (!fade) { JE_setVol(tempVolume, fxVolume); } } break; case SDLK_SPACE: drawText = !drawText; if (!drawText) { JE_bar(30, 170, 270, 198, 0); } break; case SDLK_LEFT: case SDLK_UP: currentJukeboxSong--; JE_playNewSong(); youStopped = false; break; case SDLK_RIGHT: case SDLK_DOWN: currentJukeboxSong++; JE_playNewSong(); youStopped = false; break; default: break; } } } while (!quit); JE_updateColorsFast(black); //JE_fadeBlack(10); JE_setVol(255, fxVolume); }
void jukebox( void ) { bool trigger_quit = false, // true when user wants to quit quitting = false; bool hide_text = false; bool fade_looped_songs = true, fading_song = false; bool stopped = false; bool fx = false; int fx_num = 0; int palette_fade_steps = 15; int diff[256][3]; init_step_fade_palette(diff, vga_palette, 0, 255); JE_starlib_init(); int fade_volume = tyrMusicVolume; for (; ; ) { if (!stopped && !audio_disabled) { if (songlooped && fade_looped_songs) fading_song = true; if (fading_song) { if (fade_volume > 5) { fade_volume -= 2; } else { fade_volume = tyrMusicVolume; fading_song = false; } set_volume(fade_volume, fxVolume); } if (!playing || (songlooped && fade_looped_songs && !fading_song)) play_song(mt_rand() % MUSIC_NUM); } setdelay(1); SDL_FillRect(VGAScreenSeg, NULL, 0); // starlib input needs to be rewritten JE_starlib_main(); push_joysticks_as_keyboard(); service_SDL_events(true); if (!hide_text) { char buffer[60]; if (fx) snprintf(buffer, sizeof(buffer), "%d %s", fx_num + 1, soundTitle[fx_num]); else snprintf(buffer, sizeof(buffer), "%d %s", song_playing + 1, musicTitle[song_playing]); const int x = VGAScreen->w / 2; #ifdef ANDROID draw_font_hv(VGAScreen, x, 170, "Press the Back button to quit the jukebox.", small_font, centered, 1, 0); draw_font_hv(VGAScreen, x, 180, "Touch to change the song being played.", small_font, centered, 1, 0); #else draw_font_hv(VGAScreen, x, 170, "Press ESC to quit the jukebox.", small_font, centered, 1, 0); draw_font_hv(VGAScreen, x, 180, "Arrow keys change the song being played.", small_font, centered, 1, 0); #endif draw_font_hv(VGAScreen, x, 190, buffer, small_font, centered, 1, 4); } if (palette_fade_steps > 0) step_fade_palette(diff, palette_fade_steps--, 0, 255); JE_showVGA(); wait_delay(); #ifdef ANDROID if (mousedown) { wait_noinput(true, true, true); newkey = true; if (mouse_x < 160) lastkey_sym = SDLK_LEFT; else lastkey_sym = SDLK_RIGHT; } #else // quit on mouse click Uint16 x, y; if (JE_mousePosition(&x, &y) > 0) trigger_quit = true; #endif if (newkey) { switch (lastkey_sym) { case SDLK_ESCAPE: // quit jukebox case SDLK_q: trigger_quit = true; break; case SDLK_SPACE: hide_text = !hide_text; break; case SDLK_f: fading_song = !fading_song; break; case SDLK_n: fade_looped_songs = !fade_looped_songs; break; case SDLK_SLASH: // switch to sfx mode fx = !fx; break; case SDLK_COMMA: if (fx && --fx_num < 0) fx_num = SAMPLE_COUNT - 1; break; case SDLK_PERIOD: if (fx && ++fx_num >= SAMPLE_COUNT) fx_num = 0; break; case SDLK_SEMICOLON: if (fx) JE_playSampleNum(fx_num + 1); break; case SDLK_LEFT: case SDLK_UP: case SDLK_LCTRL: play_song((song_playing > 0 ? song_playing : MUSIC_NUM) - 1); stopped = false; break; case SDLK_RETURN: case SDLK_RIGHT: case SDLK_DOWN: case SDLK_LALT: play_song((song_playing + 1) % MUSIC_NUM); stopped = false; break; case SDLK_s: // stop song stop_song(); stopped = true; break; case SDLK_r: // restart song restart_song(); stopped = false; break; default: break; } } // user wants to quit, start fade-out if (trigger_quit && !quitting) { palette_fade_steps = 15; SDL_Color black = { 0, 0, 0 }; init_step_fade_solid(diff, black, 0, 255); quitting = true; } // if fade-out finished, we can finally quit if (quitting && palette_fade_steps == 0) break; } set_volume(tyrMusicVolume, fxVolume); }