3261 lines
75 KiB
C
3261 lines
75 KiB
C
/*
|
|
* OpenTyrian: A modern cross-platform port of Tyrian
|
|
* Copyright (C) 2007-2009 The OpenTyrian Development Team
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License
|
|
* as published by the Free Software Foundation; either version 2
|
|
* of the License, or (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
*/
|
|
#include "backgrnd.h"
|
|
#include "config.h"
|
|
#include "file.h"
|
|
#include "fonthand.h"
|
|
#include "game_menu.h"
|
|
#include "joystick.h"
|
|
#include "keyboard.h"
|
|
#include "loudness.h"
|
|
#include "mainint.h"
|
|
#include "mouse.h"
|
|
#include "musmast.h"
|
|
#include "network.h"
|
|
#include "nortsong.h"
|
|
#include "nortvars.h"
|
|
#include "params.h"
|
|
#include "pcxmast.h"
|
|
#include "picload.h"
|
|
#include "player.h"
|
|
#include "shots.h"
|
|
#include "sprite.h"
|
|
#include "tyrian2.h"
|
|
#include "varz.h"
|
|
#include "vga256d.h"
|
|
#include "video.h"
|
|
|
|
#include <assert.h>
|
|
|
|
/*** Structs ***/
|
|
struct cube_struct
|
|
{
|
|
char title[81];
|
|
char header[13];
|
|
int face_sprite;
|
|
char text[90][36];
|
|
int last_line;
|
|
};
|
|
|
|
/*** Globals ***/
|
|
static int joystick_config = 0; // which joystick is being configured in menu
|
|
|
|
static JE_word yLoc;
|
|
static JE_shortint yChg;
|
|
static int newPal, curPal, oldPal;
|
|
static JE_boolean quikSave;
|
|
static JE_byte oldMenu;
|
|
static JE_boolean backFromHelp;
|
|
static JE_integer lastDirection;
|
|
static JE_boolean firstMenu9, paletteChanged;
|
|
static JE_MenuChoiceType menuChoices;
|
|
static JE_integer col, colC;
|
|
static JE_byte lastCurSel;
|
|
static JE_integer curMenu;
|
|
static JE_byte curSel[MENU_MAX]; /* [1..maxmenu] */
|
|
static JE_byte curItemType, curItem, cursor;
|
|
static JE_boolean leftPower, rightPower, rightPowerAfford;
|
|
static JE_byte currentCube;
|
|
static JE_boolean keyboardUsed;
|
|
|
|
static JE_byte planetAni, planetAniWait;
|
|
static JE_byte currentDotNum, currentDotWait;
|
|
static JE_real navX, navY, newNavX, newNavY;
|
|
static JE_integer tempNavX, tempNavY;
|
|
static JE_byte planetDots[5]; /* [1..5] */
|
|
static JE_integer planetDotX[5][10], planetDotY[5][10]; /* [1..5, 1..10] */
|
|
static PlayerItems old_items[2]; // TODO: should not be global if possible
|
|
|
|
static struct cube_struct cube[4];
|
|
|
|
static const JE_MenuChoiceType menuChoicesDefault = { 7, 9, 8, 0, 0, 13, (SAVE_FILES_NUM / 2) + 2, 0, 0, 6, 4, 6, 7, 5 };
|
|
static const JE_byte menuEsc[MENU_MAX] = { 0, 1, 1, 1, 2, 3, 3, 1, 8, 0, 0, 11, 3, 0 };
|
|
static const JE_byte itemAvailMap[7] = { 1, 2, 3, 9, 4, 6, 7 };
|
|
static const JE_word planetX[21] = { 200, 150, 240, 300, 270, 280, 320, 260, 220, 150, 160, 210, 80, 240, 220, 180, 310, 330, 150, 240, 200 };
|
|
static const JE_word planetY[21] = { 40, 90, 90, 80, 170, 30, 50, 130, 120, 150, 220, 200, 80, 50, 160, 10, 55, 55, 90, 90, 40 };
|
|
static const uint cube_line_chars = sizeof(*cube->text) - 1;
|
|
static const uint cube_line_width = 150;
|
|
|
|
|
|
/*** Functions ***/
|
|
static uint *playeritem_map( PlayerItems *items, uint i )
|
|
{
|
|
uint * const map[] = { &items->ship, &items->weapon[FRONT_WEAPON].id, &items->weapon[REAR_WEAPON].id, &items->shield, &items->generator, &items->sidekick[LEFT_SIDEKICK], &items->sidekick[RIGHT_SIDEKICK] };
|
|
assert(i < COUNTOF(map));
|
|
return map[i];
|
|
}
|
|
|
|
|
|
JE_longint JE_cashLeft( void )
|
|
{
|
|
JE_longint tempL = player[0].cash;
|
|
JE_word itemNum = *playeritem_map(&player[0].items, curSel[1] - 2);
|
|
|
|
tempL -= JE_getCost(curSel[1], itemNum);
|
|
|
|
tempW = 0;
|
|
|
|
switch (curSel[1])
|
|
{
|
|
case 3:
|
|
case 4:
|
|
for (uint i = 1; i < player[0].items.weapon[curSel[1]-3].power; ++i)
|
|
{
|
|
tempW += weaponPort[itemNum].cost * i;
|
|
tempL -= tempW;
|
|
}
|
|
break;
|
|
}
|
|
|
|
return tempL;
|
|
}
|
|
|
|
void JE_itemScreen( void )
|
|
{
|
|
bool quit = false;
|
|
|
|
/* SYN: Okay, here's the menu numbers. All are reindexed by -1 from the original code.
|
|
0: full game menu
|
|
1: upgrade ship main
|
|
2: full game options
|
|
3: play next level
|
|
4: upgrade ship submenus
|
|
5: keyboard settings
|
|
6: load/save menu
|
|
7: data cube menu
|
|
8: read data cube
|
|
9: 2 player arcade game menu
|
|
10: 1 player arcade game menu
|
|
11: network game options
|
|
12: joystick settings
|
|
13: super tyrian
|
|
*/
|
|
|
|
free_sprite2s(&shapes6);
|
|
JE_loadCompShapes(&shapes6, '1'); // item sprites
|
|
|
|
load_cubes();
|
|
|
|
VGAScreen = VGAScreenSeg;
|
|
|
|
memcpy(menuChoices, menuChoicesDefault, sizeof(menuChoices));
|
|
|
|
play_song(songBuy);
|
|
|
|
JE_loadPic(VGAScreen, 1, false);
|
|
|
|
curPal = 1;
|
|
newPal = 0;
|
|
|
|
JE_showVGA();
|
|
|
|
set_palette(colors, 0, 255);
|
|
|
|
col = 1;
|
|
gameLoaded = false;
|
|
curItemType = 1;
|
|
cursor = 1;
|
|
curItem = 0;
|
|
|
|
for (unsigned int i = 0; i < COUNTOF(curSel); ++i)
|
|
curSel[i] = 2;
|
|
|
|
curMenu = 0;
|
|
|
|
int temp_weapon_power[7]; // assumes there'll never be more than 6 weapons to choose from, 7th is "Done"
|
|
|
|
/* JE: (* Check for where Pitems and Select match up - if no match then add to the itemavail list *) */
|
|
for (int i = 0; i < 7; i++)
|
|
{
|
|
int item = *playeritem_map(&player[0].last_items, i);
|
|
|
|
int slot = 0;
|
|
|
|
for ( ; slot < itemAvailMax[itemAvailMap[i]-1]; ++slot)
|
|
{
|
|
if (itemAvail[itemAvailMap[i]-1][slot] == item)
|
|
break;
|
|
}
|
|
|
|
if (slot == itemAvailMax[itemAvailMap[i]-1])
|
|
{
|
|
itemAvail[itemAvailMap[i]-1][slot] = item;
|
|
itemAvailMax[itemAvailMap[i]-1]++;
|
|
}
|
|
}
|
|
|
|
memcpy(VGAScreen2->pixels, VGAScreen->pixels, VGAScreen2->pitch * VGAScreen2->h);
|
|
|
|
keyboardUsed = false;
|
|
firstMenu9 = false;
|
|
backFromHelp = false;
|
|
|
|
/* JE: Sort items in merchant inventory */
|
|
for (int x = 0; x < 9; x++)
|
|
{
|
|
if (itemAvailMax[x] > 1)
|
|
{
|
|
for (temp = 0; temp < itemAvailMax[x] - 1; temp++)
|
|
{
|
|
for (temp2 = temp; temp2 < itemAvailMax[x]; temp2++)
|
|
{
|
|
if (itemAvail[x][temp] == 0 || (itemAvail[x][temp] > itemAvail[x][temp2] && itemAvail[x][temp2] != 0))
|
|
{
|
|
temp3 = itemAvail[x][temp];
|
|
itemAvail[x][temp] = itemAvail[x][temp2];
|
|
itemAvail[x][temp2] = temp3;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
do
|
|
{
|
|
quit = false;
|
|
|
|
JE_getShipInfo();
|
|
|
|
/* JE: If curMenu==1 and twoPlayerMode is on, then force move to menu 10 */
|
|
if (curMenu == 0)
|
|
{
|
|
if (twoPlayerMode)
|
|
curMenu = 9;
|
|
|
|
if (isNetworkGame || onePlayerAction)
|
|
curMenu = 10;
|
|
|
|
if (superTyrian)
|
|
curMenu = 13;
|
|
}
|
|
|
|
paletteChanged = false;
|
|
|
|
leftPower = false;
|
|
rightPower = false;
|
|
|
|
/* SYN: note reindexing... "firstMenu9" refers to Menu 8 here :( */
|
|
if (curMenu != 8 || firstMenu9)
|
|
{
|
|
memcpy(VGAScreen->pixels, VGAScreen2->pixels, VGAScreen->pitch * VGAScreen->h);
|
|
}
|
|
|
|
defaultBrightness = -3;
|
|
|
|
if (curMenu == 1 && (curSel[curMenu] == 3 || curSel[curMenu] == 4))
|
|
{
|
|
// reset temp_weapon_power[] every time we select upgrading front or back
|
|
const uint item = player[0].items.weapon[curSel[1] - 3].id,
|
|
item_power = player[0].items.weapon[curSel[1] - 3].power,
|
|
i = curSel[1] - 2; // 1 or 2 (front or rear)
|
|
|
|
// set power level of owned weapon
|
|
for (int slot = 0; slot < itemAvailMax[itemAvailMap[i]-1]; ++slot)
|
|
{
|
|
if (itemAvail[itemAvailMap[i]-1][slot] == item)
|
|
temp_weapon_power[slot] = item_power;
|
|
else
|
|
temp_weapon_power[slot] = 1;
|
|
}
|
|
|
|
// set power level for "Done"
|
|
temp_weapon_power[itemAvailMax[itemAvailMap[i]-1]] = item_power;
|
|
}
|
|
|
|
/* play next level menu */
|
|
if (curMenu == 3)
|
|
{
|
|
planetAni = 0;
|
|
keyboardUsed = false;
|
|
currentDotNum = 0;
|
|
currentDotWait = 8;
|
|
planetAniWait = 3;
|
|
JE_updateNavScreen();
|
|
}
|
|
|
|
/* Draw menu title for everything but upgrade ship submenus */
|
|
if (curMenu != 4)
|
|
{
|
|
JE_drawMenuHeader();
|
|
}
|
|
|
|
/* Draw menu choices for simple menus */
|
|
if ((curMenu >= 0 && curMenu <= 3) || (curMenu >= 9 && curMenu <= 11) || curMenu == 13)
|
|
{
|
|
JE_drawMenuChoices();
|
|
}
|
|
|
|
/* Data cube icons */
|
|
if (curMenu == 0)
|
|
{
|
|
for (int i = 1; i <= cubeMax; i++)
|
|
{
|
|
blit_sprite_dark(VGAScreen, 190 + i * 18 + 2, 37 + 1, OPTION_SHAPES, 34, false);
|
|
blit_sprite(VGAScreen, 190 + i * 18, 37, OPTION_SHAPES, 34); // data cube
|
|
}
|
|
}
|
|
|
|
/* load/save menu */
|
|
if (curMenu == 6)
|
|
{
|
|
int min, max;
|
|
|
|
if (twoPlayerMode)
|
|
{
|
|
min = 13;
|
|
max = 24;
|
|
}
|
|
else
|
|
{
|
|
min = 2;
|
|
max = 12;
|
|
}
|
|
|
|
for (int x = min; x <= max; x++)
|
|
{
|
|
/* Highlight if current selection */
|
|
temp2 = (x - min + 2 == curSel[curMenu]) ? 15 : 28;
|
|
|
|
/* Write save game slot */
|
|
if (x == max)
|
|
strcpy(tempStr, miscText[6-1]);
|
|
else if (saveFiles[x-2].level == 0)
|
|
strcpy(tempStr, miscText[3-1]);
|
|
else
|
|
strcpy(tempStr, saveFiles[x-2].name);
|
|
|
|
int tempY = 38 + (x - min)*11;
|
|
|
|
JE_textShade(VGAScreen, 163, tempY, tempStr, temp2 / 16, temp2 % 16 - 8, DARKEN);
|
|
|
|
/* If selected with keyboard, move mouse pointer to match? Or something. */
|
|
if (x - min + 2 == curSel[curMenu])
|
|
{
|
|
if (keyboardUsed)
|
|
set_mouse_position(305, 38 + (x - min) * 11);
|
|
}
|
|
|
|
if (x < max) /* x == max isn't a save slot */
|
|
{
|
|
/* Highlight if current selection */
|
|
temp2 = (x - min + 2 == curSel[curMenu]) ? 252 : 250;
|
|
|
|
if (saveFiles[x-2].level == 0)
|
|
{
|
|
strcpy(tempStr, "-----"); /* Empty save slot */
|
|
}
|
|
else
|
|
{
|
|
char buf[20];
|
|
|
|
strcpy(tempStr, saveFiles[x-2].levelName);
|
|
|
|
snprintf(buf, sizeof buf, "%s%d", miscTextB[1-1], saveFiles[x-2].episode);
|
|
JE_textShade(VGAScreen, 297, tempY, buf, temp2 / 16, temp2 % 16 - 8, DARKEN);
|
|
}
|
|
|
|
JE_textShade(VGAScreen, 245, tempY, tempStr, temp2 / 16, temp2 % 16 - 8, DARKEN);
|
|
}
|
|
|
|
JE_drawMenuHeader();
|
|
}
|
|
}
|
|
|
|
/* keyboard settings menu */
|
|
if (curMenu == 5)
|
|
{
|
|
for (int x = 2; x <= 12; x++)
|
|
{
|
|
if (x == curSel[curMenu])
|
|
{
|
|
temp2 = 15;
|
|
if (keyboardUsed)
|
|
set_mouse_position(305, 38 + (x - 2) * 12);
|
|
}
|
|
else
|
|
{
|
|
temp2 = 28;
|
|
}
|
|
|
|
if( x == 12 )
|
|
{
|
|
char *touchscreenControlNames[] = { "Ship follows touch", "Joystick + buttons", "Both" };
|
|
JE_textShade(VGAScreen, 166, 38 + (x - 2)*12, "Touch mode", temp2 / 16, temp2 % 16 - 8, DARKEN);
|
|
JE_textShade(VGAScreen, 230, 38 + (x - 2)*12, touchscreenControlNames[touchscreenControlMode], temp2 / 16, temp2 % 16 - 8, DARKEN);
|
|
}
|
|
else
|
|
JE_textShade(VGAScreen, 166, 38 + (x - 2)*12, menuInt[curMenu + 1][x-1], temp2 / 16, temp2 % 16 - 8, DARKEN);
|
|
|
|
if (x < 10) /* 10 = reset to defaults, 11 = done */
|
|
{
|
|
temp2 = (x == curSel[curMenu]) ? 252 : 250;
|
|
JE_textShade(VGAScreen, 230, 38 + (x - 2)*12, SDL_GetKeyName(keySettings[x-2]), temp2 / 16, temp2 % 16 - 8, DARKEN);
|
|
}
|
|
}
|
|
|
|
menuChoices[5] = 12;
|
|
}
|
|
|
|
/* Joystick settings menu */
|
|
if (curMenu == 12)
|
|
{
|
|
const char *menu_item[] =
|
|
{
|
|
"JOYSTICK",
|
|
"ANALOG AXES",
|
|
" SENSITIVITY",
|
|
" THRESHOLD",
|
|
menuInt[6][1],
|
|
menuInt[6][4],
|
|
menuInt[6][2],
|
|
menuInt[6][3],
|
|
menuInt[6][5],
|
|
menuInt[6][6],
|
|
menuInt[6][7],
|
|
menuInt[6][8],
|
|
"MENU",
|
|
"PAUSE",
|
|
menuInt[6][9],
|
|
menuInt[6][10]
|
|
};
|
|
|
|
for (uint i = 0; i < COUNTOF(menu_item); i++)
|
|
{
|
|
int temp = (i == curSel[curMenu] - 2u) ? 15 : 28;
|
|
|
|
JE_textShade(VGAScreen, 166, 38 + i * 8, menu_item[i], temp / 16, temp % 16 - 8, DARKEN);
|
|
|
|
temp = (i == curSel[curMenu] - 2u) ? 252 : 250;
|
|
|
|
char value[30] = "";
|
|
if (joysticks == 0 && i < 14) // no joysticks, everything disabled
|
|
{
|
|
sprintf(value, "-");
|
|
}
|
|
else if (i == 0) // joystick number
|
|
{
|
|
sprintf(value, "%d", joystick_config + 1);
|
|
}
|
|
else if (i == 1) // joystick is analog
|
|
{
|
|
sprintf(value, "%s", joystick[joystick_config].analog ? "TRUE" : "FALSE");
|
|
}
|
|
else if (i < 4) // joystick analog settings
|
|
{
|
|
if (!joystick[joystick_config].analog)
|
|
temp -= 3;
|
|
sprintf(value, "%d", i == 2 ? joystick[joystick_config].sensitivity : joystick[joystick_config].threshold);
|
|
}
|
|
else if (i < 14) // assignments
|
|
{
|
|
joystick_assignments_to_string(value, sizeof(value), joystick[joystick_config].assignment[i - 4]);
|
|
}
|
|
|
|
JE_textShade(VGAScreen, 236, 38 + i * 8, value, temp / 16, temp % 16 - 8, DARKEN);
|
|
}
|
|
|
|
menuChoices[curMenu] = COUNTOF(menu_item) + 1;
|
|
}
|
|
|
|
/* Upgrade weapon submenus, with weapon sim */
|
|
if (curMenu == 4)
|
|
{
|
|
/* Move cursor until we hit either "Done" or a weapon the player can afford */
|
|
while (curSel[4] < menuChoices[4] && JE_getCost(curSel[1], itemAvail[itemAvailMap[curSel[1]-2]-1][curSel[4]-2]) > player[0].cash)
|
|
{
|
|
curSel[4] += lastDirection;
|
|
if (curSel[4] < 2)
|
|
curSel[4] = menuChoices[4];
|
|
else if (curSel[4] > menuChoices[4])
|
|
curSel[4] = 2;
|
|
}
|
|
|
|
if (curSel[4] == menuChoices[4])
|
|
{
|
|
/* If cursor on "Done", use previous weapon */
|
|
*playeritem_map(&player[0].items, curSel[1] - 2) = *playeritem_map(&old_items[0], curSel[1] - 2);
|
|
}
|
|
else
|
|
{
|
|
/* Otherwise display the selected weapon */
|
|
*playeritem_map(&player[0].items, curSel[1] - 2) = itemAvail[itemAvailMap[curSel[1]-2]-1][curSel[4]-2];
|
|
}
|
|
|
|
/* Get power level info for front and rear weapons */
|
|
if ((curSel[1] == 3 && curSel[4] < menuChoices[4]) || (curSel[1] == 4 && curSel[4] < menuChoices[4]-1))
|
|
{
|
|
const uint port = curSel[1] - 3, // 0 or 1 (front or back)
|
|
item_level = player[0].items.weapon[port].power;
|
|
|
|
// calculate upgradeCost
|
|
JE_getCost(curSel[1], itemAvail[itemAvailMap[curSel[1]-2]-1][curSel[5]-2]);
|
|
|
|
leftPower = item_level > 1; // can downgrade
|
|
rightPower = item_level < 11; // can upgrade
|
|
|
|
if (rightPower)
|
|
rightPowerAfford = JE_cashLeft() >= upgradeCost; // can afford upgrade
|
|
}
|
|
else
|
|
{
|
|
/* Nothing else can be upgraded / downgraded */
|
|
leftPower = false;
|
|
rightPower = false;
|
|
}
|
|
|
|
/* submenu title e.g., "Left Sidekick" */
|
|
JE_dString(VGAScreen, 74 + JE_fontCenter(menuInt[2][curSel[1]-1], FONT_SHAPES), 10, menuInt[2][curSel[1]-1], FONT_SHAPES);
|
|
|
|
/* Iterate through all submenu options */
|
|
for (tempW = 1; tempW < menuChoices[curMenu]; tempW++)
|
|
{
|
|
int tempY = 40 + (tempW-1) * 26; /* Calculate y position */
|
|
uint temp_cost;
|
|
|
|
/* Is this a item or None/DONE? */
|
|
if (tempW < menuChoices[4] - 1)
|
|
{
|
|
/* Get base cost for choice */
|
|
temp_cost = JE_getCost(curSel[1], itemAvail[itemAvailMap[curSel[1]-2]-1][tempW-1]);
|
|
}
|
|
else
|
|
{
|
|
/* "None" is free :) */
|
|
temp_cost = 0;
|
|
}
|
|
|
|
int afford_shade = (temp_cost > player[0].cash) ? 4 : 0; // can player afford current weapon at all
|
|
|
|
temp = itemAvail[itemAvailMap[curSel[1]-2]-1][tempW-1]; /* Item ID */
|
|
switch (curSel[1]-1)
|
|
{
|
|
case 1: /* ship */
|
|
if (temp > 90)
|
|
{
|
|
snprintf(tempStr, sizeof(tempStr), "Custom Ship %d", temp - 90);
|
|
} else {
|
|
strcpy(tempStr, ships[temp].name);
|
|
}
|
|
break;
|
|
case 2: /* front and rear weapon */
|
|
case 3:
|
|
strcpy(tempStr, weaponPort[temp].name);
|
|
break;
|
|
case 4: /* shields */
|
|
strcpy(tempStr, shields[temp].name);
|
|
break;
|
|
case 5: /* generator */
|
|
strcpy(tempStr, powerSys[temp].name);
|
|
break;
|
|
case 6: /* sidekicks */
|
|
case 7:
|
|
strcpy(tempStr, options[temp].name);
|
|
break;
|
|
}
|
|
if (tempW == curSel[curMenu]-1)
|
|
{
|
|
if (keyboardUsed)
|
|
{
|
|
set_mouse_position(305, tempY + 10);
|
|
}
|
|
temp2 = 15;
|
|
} else {
|
|
temp2 = 28;
|
|
}
|
|
|
|
JE_getShipInfo();
|
|
|
|
/* item-owned marker */
|
|
if (temp == *playeritem_map(&old_items[0], curSel[1] - 2) && temp != 0 && tempW != menuChoices[curMenu]-1)
|
|
{
|
|
fill_rectangle_xy(VGAScreen, 160, tempY+7, 300, tempY+11, 227);
|
|
blit_sprite2(VGAScreen, 298, tempY+2, shapes6, 247);
|
|
}
|
|
|
|
/* Draw DONE */
|
|
if (tempW == menuChoices[curMenu]-1)
|
|
{
|
|
strcpy(tempStr, miscText[13]);
|
|
}
|
|
JE_textShade(VGAScreen, 185, tempY, tempStr, temp2 / 16, temp2 % 16 - 8 - afford_shade, DARKEN);
|
|
|
|
/* Draw icon if not DONE. NOTE: None is a normal item with a blank icon. */
|
|
if (tempW < menuChoices[curMenu]-1)
|
|
{
|
|
JE_drawItem(curSel[1]-1, temp, 160, tempY-4);
|
|
}
|
|
|
|
/* Make selected text brigther */
|
|
temp2 = (tempW == curSel[curMenu]-1) ? 15 : 28;
|
|
|
|
/* Draw Cost: if it's not the DONE option */
|
|
if (tempW != menuChoices[curMenu]-1)
|
|
{
|
|
char buf[20];
|
|
|
|
snprintf(buf, sizeof buf, "Cost: %d", temp_cost);
|
|
JE_textShade(VGAScreen, 187, tempY+10, buf, temp2 / 16, temp2 % 16 - 8 - afford_shade, DARKEN);
|
|
}
|
|
}
|
|
} /* /weapon upgrade */
|
|
|
|
/* Draw current money and shield/armor bars, when appropriate */
|
|
/* YKS: Ouch */
|
|
if (((curMenu <= 2 || curMenu == 5 || curMenu == 6 || curMenu >= 10) && !twoPlayerMode) || (curMenu == 4 && (curSel[1] >= 1 && curSel[1] <= 6)))
|
|
{
|
|
if (curMenu != 4)
|
|
{
|
|
char buf[20];
|
|
|
|
snprintf(buf, sizeof buf, "%lu", player[0].cash);
|
|
JE_textShade(VGAScreen, 65, 173, buf, 1, 6, DARKEN);
|
|
}
|
|
JE_barDrawShadow(VGAScreen, 42, 152, 3, 14, player[0].armor, 2, 13);
|
|
JE_barDrawShadow(VGAScreen, 104, 152, 2, 14, shields[player[0].items.shield].mpwr * 2, 2, 13);
|
|
}
|
|
|
|
/* Draw crap on the left side of the screen, i.e. two player scores, ship graphic, etc. */
|
|
if (((curMenu >= 0 && curMenu <= 2) || curMenu == 5 || curMenu == 6 || curMenu >= 9) || (curMenu == 4 && (curSel[1] == 2 || curSel[1] == 5)))
|
|
{
|
|
if (twoPlayerMode)
|
|
{
|
|
char buf[50];
|
|
|
|
for (uint i = 0; i < 2; ++i)
|
|
{
|
|
snprintf(buf, sizeof(buf), "%s %lu", miscText[40 + i], player[i].cash);
|
|
JE_textShade(VGAScreen, 25, 50 + 10 * i, buf, 15, 0, FULL_SHADE);
|
|
}
|
|
}
|
|
else if (superArcadeMode != SA_NONE || superTyrian)
|
|
{
|
|
helpBoxColor = 15;
|
|
helpBoxBrightness = 4;
|
|
if (!superTyrian)
|
|
JE_helpBox(VGAScreen, 35, 25, superShips[superArcadeMode], 18);
|
|
else
|
|
JE_helpBox(VGAScreen, 35, 25, superShips[SA+3], 18);
|
|
helpBoxBrightness = 1;
|
|
|
|
JE_textShade(VGAScreen, 25, 50, superShips[SA+1], 15, 0, FULL_SHADE);
|
|
JE_helpBox(VGAScreen, 25, 60, weaponPort[player[0].items.weapon[FRONT_WEAPON].id].name, 22);
|
|
JE_textShade(VGAScreen, 25, 120, superShips[SA+2], 15, 0, FULL_SHADE);
|
|
JE_helpBox(VGAScreen, 25, 130, special[player[0].items.special].name, 22);
|
|
}
|
|
else
|
|
{
|
|
draw_ship_illustration();
|
|
}
|
|
}
|
|
|
|
/* Changing the volume? */
|
|
if ((curMenu == 2) || (curMenu == 11))
|
|
{
|
|
JE_barDrawShadow(VGAScreen, 225, 70, 1, music_disabled ? 12 : 16, tyrMusicVolume / 12, 3, 13);
|
|
JE_barDrawShadow(VGAScreen, 225, 86, 1, samples_disabled ? 12 : 16, fxVolume / 12, 3, 13);
|
|
}
|
|
|
|
/* 7 is data cubes menu, 8 is reading a data cube, "firstmenu9" refers to menu 8 because of reindexing */
|
|
if (curMenu == 7 || ( curMenu == 8 && (firstMenu9 || backFromHelp) ) )
|
|
{
|
|
firstMenu9 = false;
|
|
menuChoices[7] = cubeMax + 2;
|
|
fill_rectangle_xy(VGAScreen, 1, 1, 145, 170, 0);
|
|
|
|
blit_sprite(VGAScreenSeg, 1, 1, OPTION_SHAPES, 20); /* Portrait area background */
|
|
|
|
if (curMenu == 7)
|
|
{
|
|
if (cubeMax == 0)
|
|
{
|
|
JE_helpBox(VGAScreen, 166, 80, miscText[16 - 1], 30);
|
|
tempW = 160;
|
|
temp2 = 252;
|
|
}
|
|
else
|
|
{
|
|
for (int x = 1; x <= cubeMax; x++)
|
|
{
|
|
JE_drawCube(VGAScreenSeg, 166, 38 + (x - 1) * 28, 13, 0);
|
|
if (x + 1 == curSel[curMenu])
|
|
{
|
|
if (keyboardUsed)
|
|
set_mouse_position(305, 38 + (x - 1) * 28 + 6);
|
|
temp2 = 252;
|
|
}
|
|
else
|
|
{
|
|
temp2 = 250;
|
|
}
|
|
|
|
helpBoxColor = temp2 / 16;
|
|
helpBoxBrightness = (temp2 % 16) - 8;
|
|
helpBoxShadeType = DARKEN;
|
|
JE_helpBox(VGAScreen, 192, 44 + (x - 1) * 28, cube[x - 1].title, 24);
|
|
}
|
|
int x = cubeMax + 1;
|
|
if (x + 1 == curSel[curMenu])
|
|
{
|
|
if (keyboardUsed)
|
|
set_mouse_position(305, 38 + (x - 1) * 28 + 6);
|
|
temp2 = 252;
|
|
}
|
|
else
|
|
{
|
|
temp2 = 250;
|
|
}
|
|
tempW = 44 + (x - 1) * 28;
|
|
}
|
|
|
|
JE_textShade(VGAScreen, 172, tempW, miscText[6 - 1], temp2 / 16, (temp2 % 16) - 8, DARKEN);
|
|
}
|
|
|
|
if (curSel[7] < menuChoices[7])
|
|
{
|
|
const int face_sprite = cube[curSel[7] - 2].face_sprite;
|
|
|
|
if (face_sprite != -1)
|
|
{
|
|
const int face_x = 77 - (sprite(FACE_SHAPES, face_sprite)->width / 2),
|
|
face_y = 92 - (sprite(FACE_SHAPES, face_sprite)->height / 2);
|
|
|
|
blit_sprite(VGAScreenSeg, face_x, face_y, FACE_SHAPES, face_sprite); // datacube face
|
|
|
|
// modify pallete for face
|
|
paletteChanged = true;
|
|
temp2 = facepal[face_sprite];
|
|
newPal = 0;
|
|
|
|
for (temp = 1; temp <= 255 - (3 * 16); temp++)
|
|
colors[temp] = palettes[temp2][temp];
|
|
}
|
|
}
|
|
}
|
|
|
|
/* 2 player input devices */
|
|
if (curMenu == 9)
|
|
{
|
|
for (uint i = 0; i < COUNTOF(inputDevice); i++)
|
|
{
|
|
if (inputDevice[i] > 2 + joysticks)
|
|
inputDevice[i] = inputDevice[i == 0 ? 1 : 0] == 1 ? 2 : 1;
|
|
|
|
char temp[64];
|
|
if (joysticks > 1 && inputDevice[i] > 2)
|
|
sprintf(temp, "%s %d", inputDevices[2], inputDevice[i] - 2);
|
|
else
|
|
sprintf(temp, "%s", inputDevices[inputDevice[i] - 1]);
|
|
JE_dString(VGAScreen, 186, 38 + 2 * (i + 1) * 16, temp, SMALL_FONT_SHAPES);
|
|
}
|
|
}
|
|
|
|
/* JE: { - Step VI - Help text for current cursor location } */
|
|
|
|
flash = false;
|
|
|
|
/* JE: {Reset player weapons} */
|
|
memset(shotMultiPos, 0, sizeof(shotMultiPos));
|
|
|
|
JE_drawScore();
|
|
|
|
JE_drawMainMenuHelpText();
|
|
|
|
if (newPal > 0) /* can't reindex this :( */
|
|
{
|
|
curPal = newPal;
|
|
memcpy(colors, palettes[newPal - 1], sizeof(colors));
|
|
set_palette(palettes[newPal - 1], 0, 255);
|
|
newPal = 0;
|
|
}
|
|
|
|
/* datacube title under face */
|
|
if ( ( (curMenu == 7) || (curMenu == 8) ) && (curSel[7] < menuChoices[7]) )
|
|
JE_textShade (VGAScreen, 75 - JE_textWidth(cube[curSel[7] - 2].header, TINY_FONT) / 2, 173, cube[curSel[7] - 2].header, 14, 3, DARKEN);
|
|
|
|
/* SYN: Everything above was just drawing the screen. In the rest of it, we process
|
|
any user input (and do a few other things) */
|
|
|
|
/* SYN: Let's start by getting fresh events from SDL */
|
|
service_SDL_events(true);
|
|
|
|
if (constantPlay)
|
|
{
|
|
mainLevel = mapSection[mapPNum-1];
|
|
jumpSection = true;
|
|
}
|
|
else
|
|
{
|
|
do
|
|
{
|
|
/* Inner loop -- this handles animations on menus that need them and handles
|
|
some keyboard events. Events it can't handle end the loop and fall through
|
|
to the main keyboard handler below.
|
|
|
|
Also, I think all timing is handled in here. Somehow. */
|
|
|
|
NETWORK_KEEP_ALIVE();
|
|
|
|
mouseCursor = 0;
|
|
|
|
col += colC;
|
|
if (col < -2 || col > 6)
|
|
{
|
|
colC = (-1 * colC);
|
|
}
|
|
|
|
// data cube reading
|
|
if (curMenu == 8)
|
|
{
|
|
if (mouseX > 164 && mouseX < 299 && mouseY > 47 && mouseY < 153)
|
|
{
|
|
if (mouseY > 100)
|
|
mouseCursor = 2;
|
|
else
|
|
mouseCursor = 1;
|
|
}
|
|
|
|
fill_rectangle_xy(VGAScreen, 160, 49, 310, 158, 228);
|
|
if (yLoc + yChg < 0)
|
|
{
|
|
yChg = 0;
|
|
yLoc = 0;
|
|
}
|
|
|
|
yLoc += yChg;
|
|
temp = yLoc / 12;
|
|
temp2 = yLoc % 12;
|
|
tempW = 38 + 12 - temp2;
|
|
temp3 = cube[curSel[7] - 2].last_line;
|
|
|
|
for (int x = temp + 1; x <= temp + 10; x++)
|
|
{
|
|
if (x <= temp3)
|
|
{
|
|
JE_outTextAndDarken(VGAScreen, 161, tempW, cube[curSel[7] - 2].text[x-1], 14, 3, TINY_FONT);
|
|
tempW += 12;
|
|
}
|
|
}
|
|
|
|
fill_rectangle_xy(VGAScreen, 160, 39, 310, 48, 228);
|
|
fill_rectangle_xy(VGAScreen, 160, 157, 310, 166, 228);
|
|
|
|
int percent_read = (cube[currentCube].last_line <= 9)
|
|
? 100
|
|
: (yLoc * 100) / ((cube[currentCube].last_line - 9) * 12);
|
|
|
|
char buf[20];
|
|
snprintf(buf, sizeof(buf), "%s %d%%", miscText[11], percent_read);
|
|
JE_outTextAndDarken(VGAScreen, 176, 160, buf, 14, 1, TINY_FONT);
|
|
|
|
JE_dString(VGAScreen, 260, 160, miscText[12], SMALL_FONT_SHAPES);
|
|
|
|
if (temp2 == 0)
|
|
yChg = 0;
|
|
|
|
JE_mouseStart();
|
|
|
|
JE_showVGA();
|
|
|
|
if (backFromHelp)
|
|
{
|
|
fade_palette(colors, 10, 0, 255);
|
|
backFromHelp = false;
|
|
}
|
|
JE_mouseReplace();
|
|
|
|
setjasondelay(1);
|
|
}
|
|
else
|
|
{
|
|
/* current menu is not 8 (read data cube) */
|
|
|
|
if (curMenu == 3)
|
|
{
|
|
JE_updateNavScreen();
|
|
JE_drawMainMenuHelpText();
|
|
JE_drawMenuHeader();
|
|
JE_drawMenuChoices();
|
|
if (extraGame)
|
|
JE_dString(VGAScreen, 170, 140, miscText[68 - 1], FONT_SHAPES);
|
|
}
|
|
|
|
if (curMenu == 7 && curSel[7] < menuChoices[7])
|
|
{
|
|
/* Draw flashy cube */
|
|
blit_sprite_hv_blend(VGAScreenSeg, 166, 38 + (curSel[7] - 2) * 28, OPTION_SHAPES, 25, 13, col);
|
|
}
|
|
|
|
/* IF (curmenu = 5) AND (cursel [2] IN [3, 4, 6, 7, 8]) */
|
|
if (curMenu == 4 && ( curSel[1] == 3 || curSel[1] == 4 || ( curSel[1] >= 6 && curSel[1] <= 8) ) )
|
|
{
|
|
setjasondelay(3);
|
|
JE_weaponSimUpdate();
|
|
JE_drawScore();
|
|
service_SDL_events(false);
|
|
|
|
if (newPal > 0)
|
|
{
|
|
curPal = newPal;
|
|
set_palette(palettes[newPal - 1], 0, 255);
|
|
newPal = 0;
|
|
}
|
|
|
|
JE_mouseStart();
|
|
|
|
if (paletteChanged)
|
|
{
|
|
set_palette(colors, 0, 255);
|
|
paletteChanged = false;
|
|
}
|
|
|
|
JE_showVGA(); /* SYN: This is where it updates the screen for the weapon sim */
|
|
|
|
if (backFromHelp)
|
|
{
|
|
fade_palette(colors, 10, 0, 255);
|
|
backFromHelp = false;
|
|
}
|
|
|
|
JE_mouseReplace();
|
|
|
|
} else { /* current menu is anything but weapon sim or datacube */
|
|
|
|
setjasondelay(2);
|
|
|
|
JE_drawScore();
|
|
//JE_waitRetrace(); didn't do anything anyway?
|
|
|
|
if (newPal > 0)
|
|
{
|
|
curPal = newPal;
|
|
set_palette(palettes[newPal - 1], 0, 255);
|
|
newPal = 0;
|
|
}
|
|
|
|
JE_mouseStart();
|
|
|
|
if (paletteChanged)
|
|
{
|
|
set_palette(colors, 0, 255);
|
|
paletteChanged = false;
|
|
}
|
|
|
|
JE_showVGA(); /* SYN: This is the where the screen updates for most menus */
|
|
|
|
JE_mouseReplace();
|
|
|
|
if (backFromHelp)
|
|
{
|
|
fade_palette(colors, 10, 0, 255);
|
|
backFromHelp = false;
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
wait_delay();
|
|
|
|
push_joysticks_as_keyboard();
|
|
service_SDL_events(false);
|
|
mouseButton = JE_mousePosition(&mouseX, &mouseY);
|
|
inputDetected = newkey || mouseButton > 0;
|
|
|
|
if (curMenu != 6)
|
|
{
|
|
if (keysactive[SDLK_s] && (keysactive[SDLK_LALT] || keysactive[SDLK_RALT]) )
|
|
{
|
|
if (curMenu == 8 || curMenu == 7)
|
|
{
|
|
curMenu = 0;
|
|
}
|
|
quikSave = true;
|
|
oldMenu = curMenu;
|
|
curMenu = 6;
|
|
performSave = true;
|
|
newPal = 1;
|
|
oldPal = curPal;
|
|
}
|
|
if (keysactive[SDLK_l] && (keysactive[SDLK_LALT] || keysactive[SDLK_RALT]) )
|
|
{
|
|
if (curMenu == 8 || curMenu == 7)
|
|
{
|
|
curMenu = 0;
|
|
}
|
|
quikSave = true;
|
|
oldMenu = curMenu;
|
|
curMenu = 6;
|
|
performSave = false;
|
|
newPal = 1;
|
|
oldPal = curPal;
|
|
}
|
|
}
|
|
|
|
if (curMenu == 8)
|
|
{
|
|
if (mouseButton > 0 && mouseCursor >= 1)
|
|
{
|
|
inputDetected = false;
|
|
if (mouseCursor == 1)
|
|
{
|
|
yChg = -1;
|
|
} else {
|
|
yChg = 1;
|
|
}
|
|
}
|
|
|
|
if (keysactive[SDLK_PAGEUP])
|
|
{
|
|
yChg = -2;
|
|
inputDetected = false;
|
|
}
|
|
if (keysactive[SDLK_PAGEDOWN])
|
|
{
|
|
yChg = 2;
|
|
inputDetected = false;
|
|
}
|
|
|
|
bool joystick_up = false, joystick_down = false;
|
|
for (int j = 0; j < joysticks; j++)
|
|
{
|
|
joystick_up |= joystick[j].direction[0];
|
|
joystick_down |= joystick[j].direction[2];
|
|
}
|
|
|
|
if (keysactive[SDLK_UP] || keysactive[SDLK_LCTRL] || joystick_up)
|
|
{
|
|
yChg = -1;
|
|
inputDetected = false;
|
|
}
|
|
|
|
if (keysactive[SDLK_DOWN] || keysactive[SDLK_LALT] || joystick_down)
|
|
{
|
|
yChg = 1;
|
|
inputDetected = false;
|
|
}
|
|
|
|
if (yChg < 0 && yLoc == 0)
|
|
{
|
|
yChg = 0;
|
|
}
|
|
if (yChg > 0 && (yLoc / 12) > cube[currentCube].last_line - 10)
|
|
{
|
|
yChg = 0;
|
|
}
|
|
}
|
|
|
|
} while (!inputDetected);
|
|
}
|
|
|
|
keyboardUsed = false;
|
|
|
|
/* The rest of this just grabs input events, handles them, then proceeds on. */
|
|
|
|
if (mouseButton > 0)
|
|
{
|
|
lastDirection = 1;
|
|
|
|
mouseButton = JE_mousePosition(&mouseX, &mouseY);
|
|
|
|
if (curMenu == 7 && cubeMax == 0)
|
|
{
|
|
curMenu = 0;
|
|
JE_playSampleNum(S_SPRING);
|
|
newPal = 1;
|
|
JE_wipeKey();
|
|
}
|
|
|
|
if (curMenu == 8)
|
|
{
|
|
if ((mouseX > 258) && (mouseX < 290) && (mouseY > 159) && (mouseY < 171))
|
|
{
|
|
curMenu = 7;
|
|
JE_playSampleNum(S_SPRING);
|
|
}
|
|
}
|
|
|
|
if (curMenu == 2 || curMenu == 11)
|
|
{
|
|
if ((mouseX >= (225 - 4)) && (mouseY >= 70) && (mouseY <= 82))
|
|
{
|
|
if (music_disabled)
|
|
{
|
|
music_disabled = false;
|
|
restart_song();
|
|
}
|
|
|
|
curSel[2] = 4;
|
|
|
|
tyrMusicVolume = (mouseX - (225 - 4)) / 4 * 12;
|
|
if (tyrMusicVolume > 255)
|
|
tyrMusicVolume = 255;
|
|
}
|
|
|
|
if ((mouseX >= (225 - 4)) && (mouseY >= 86) && (mouseY <= 98))
|
|
{
|
|
samples_disabled = false;
|
|
|
|
curSel[2] = 5;
|
|
|
|
fxVolume = (mouseX - (225 - 4)) / 4 * 12;
|
|
if (fxVolume > 255)
|
|
fxVolume = 255;
|
|
}
|
|
|
|
JE_calcFXVol();
|
|
|
|
set_volume(tyrMusicVolume, fxVolume);
|
|
|
|
JE_playSampleNum(S_CURSOR);
|
|
}
|
|
|
|
if ((mouseY > 20) && (mouseX > 170) && (mouseX < 308) && (curMenu != 8))
|
|
{
|
|
const JE_byte mouseSelectionY[MENU_MAX] = { 16, 16, 16, 16, 26, 12, 11, 28, 0, 16, 16, 16, 8, 16 };
|
|
|
|
int selection = (mouseY - 38) / mouseSelectionY[curMenu]+2;
|
|
|
|
if (curMenu == 9)
|
|
{
|
|
if (selection > 5)
|
|
selection--;
|
|
if (selection > 3)
|
|
selection--;
|
|
}
|
|
|
|
if (curMenu == 0)
|
|
{
|
|
if (selection > 7)
|
|
selection = 7;
|
|
}
|
|
|
|
// is play next level screen?
|
|
if (curMenu == 3)
|
|
{
|
|
if (selection == menuChoices[curMenu] + 1)
|
|
selection = menuChoices[curMenu];
|
|
}
|
|
|
|
if (selection <= menuChoices[curMenu])
|
|
{
|
|
if ((curMenu == 4) && (selection == menuChoices[4]))
|
|
{
|
|
player[0].cash = JE_cashLeft();
|
|
curMenu = 1;
|
|
JE_playSampleNum(S_ITEM);
|
|
}
|
|
else
|
|
{
|
|
JE_playSampleNum(S_CLICK);
|
|
if (curSel[curMenu] == selection)
|
|
{
|
|
JE_menuFunction(curSel[curMenu]);
|
|
}
|
|
else
|
|
{
|
|
if ((curMenu == 4) && (JE_getCost(curSel[1], itemAvail[itemAvailMap[curSel[2]-1]][selection-2]) > player[0].cash))
|
|
{
|
|
JE_playSampleNum(S_CLINK);
|
|
}
|
|
else
|
|
{
|
|
if (curSel[1] == 4)
|
|
player[0].weapon_mode = 1;
|
|
|
|
curSel[curMenu] = selection;
|
|
}
|
|
|
|
// in front or rear weapon upgrade screen?
|
|
if ((curMenu == 4) && ((curSel[1] == 3) || (curSel[1] == 4)))
|
|
player[0].items.weapon[curSel[1]-3].power = temp_weapon_power[curSel[4]-2];
|
|
}
|
|
}
|
|
}
|
|
|
|
wait_noinput(false, true, false);
|
|
}
|
|
|
|
if ((curMenu == 4) && ((curSel[1] == 3) || (curSel[1] == 4)))
|
|
{
|
|
if ((mouseX >= 23) && (mouseX <= 36) && (mouseY >= 149) && (mouseY <= 168))
|
|
{
|
|
JE_playSampleNum(S_CURSOR);
|
|
switch (curSel[1])
|
|
{
|
|
case 3:
|
|
case 4:
|
|
if (leftPower)
|
|
player[0].items.weapon[curSel[1]-3].power = --temp_weapon_power[curSel[4]-2];
|
|
else
|
|
JE_playSampleNum(S_CLINK);
|
|
|
|
break;
|
|
}
|
|
wait_noinput(false, true, false);
|
|
}
|
|
|
|
if ((mouseX >= 119) && (mouseX <= 131) && (mouseY >= 149) && (mouseY <= 168))
|
|
{
|
|
JE_playSampleNum(S_CURSOR);
|
|
switch (curSel[1])
|
|
{
|
|
case 3:
|
|
case 4:
|
|
if (rightPower && rightPowerAfford)
|
|
player[0].items.weapon[curSel[1]-3].power = ++temp_weapon_power[curSel[4]-2];
|
|
else
|
|
JE_playSampleNum(S_CLINK);
|
|
|
|
break;
|
|
}
|
|
wait_noinput(false, true, false);
|
|
}
|
|
}
|
|
}
|
|
else if (newkey)
|
|
{
|
|
switch (lastkey_sym)
|
|
{
|
|
case SDLK_SLASH:
|
|
// if in rear weapon upgrade screen
|
|
if ( (curMenu == 4) && (curSel[1] == 4))
|
|
{
|
|
// cycle weapon modes
|
|
if (++player[0].weapon_mode > weaponPort[player[0].items.weapon[REAR_WEAPON].id].opnum)
|
|
player[0].weapon_mode = 1;
|
|
}
|
|
break;
|
|
|
|
case SDLK_SPACE:
|
|
case SDLK_RETURN:
|
|
keyboardUsed = true;
|
|
|
|
// if front or rear weapon, update "Done" power level
|
|
if (curMenu == 4 && (curSel[1] == 3 || curSel[1] == 4))
|
|
temp_weapon_power[itemAvailMax[itemAvailMap[curSel[1]-2]-1]] = player[0].items.weapon[curSel[1]-3].power;
|
|
|
|
JE_menuFunction(curSel[curMenu]);
|
|
break;
|
|
|
|
case SDLK_ESCAPE:
|
|
keyboardUsed = true;
|
|
|
|
JE_playSampleNum(S_SPRING);
|
|
if ( (curMenu == 6) && quikSave)
|
|
{
|
|
curMenu = oldMenu;
|
|
newPal = oldPal;
|
|
}
|
|
else if (menuEsc[curMenu] == 0)
|
|
{
|
|
if (JE_quitRequest())
|
|
{
|
|
gameLoaded = true;
|
|
mainLevel = 0;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (curMenu == 4) // leaving upgrade menu without buying
|
|
{
|
|
player[0].items = old_items[0];
|
|
curSel[4] = lastCurSel;
|
|
player[0].cash = JE_cashLeft();
|
|
}
|
|
|
|
if (curMenu != 8) // not data cube
|
|
newPal = 1;
|
|
|
|
curMenu = menuEsc[curMenu] - 1;
|
|
}
|
|
break;
|
|
|
|
case SDLK_F1:
|
|
if (!isNetworkGame)
|
|
{
|
|
JE_helpSystem(2);
|
|
fade_black(10);
|
|
|
|
play_song(songBuy);
|
|
|
|
JE_loadPic(VGAScreen, 1, false);
|
|
newPal = 1;
|
|
|
|
switch (curMenu)
|
|
{
|
|
case 3:
|
|
newPal = 18;
|
|
break;
|
|
case 7:
|
|
case 8:
|
|
break;
|
|
}
|
|
|
|
memcpy(VGAScreen2->pixels, VGAScreen->pixels, VGAScreen2->pitch * VGAScreen2->h);
|
|
|
|
curPal = newPal;
|
|
memcpy(colors, palettes[newPal-1], sizeof(colors));
|
|
JE_showVGA();
|
|
newPal = 0;
|
|
backFromHelp = true;
|
|
}
|
|
break;
|
|
|
|
case SDLK_UP:
|
|
case SDLK_LCTRL:
|
|
keyboardUsed = true;
|
|
lastDirection = -1;
|
|
|
|
if (curMenu != 8) // not data cube
|
|
JE_playSampleNum(S_CURSOR);
|
|
|
|
curSel[curMenu]--;
|
|
if (curSel[curMenu] < 2)
|
|
curSel[curMenu] = menuChoices[curMenu];
|
|
|
|
// if in front or rear weapon upgrade screen
|
|
if (curMenu == 4 && (curSel[1] == 3 || curSel[1] == 4))
|
|
{
|
|
player[0].items.weapon[curSel[1]-3].power = temp_weapon_power[curSel[4]-2];
|
|
if (curSel[curMenu] == 4)
|
|
player[0].weapon_mode = 1;
|
|
}
|
|
|
|
// if joystick config, skip disabled items when digital
|
|
if (curMenu == 12 && joysticks > 0 && !joystick[joystick_config].analog && curSel[curMenu] == 5)
|
|
curSel[curMenu] = 3;
|
|
|
|
break;
|
|
|
|
case SDLK_DOWN:
|
|
case SDLK_LALT:
|
|
keyboardUsed = true;
|
|
lastDirection = 1;
|
|
|
|
if (curMenu != 8) // not data cube
|
|
JE_playSampleNum(S_CURSOR);
|
|
|
|
curSel[curMenu]++;
|
|
if (curSel[curMenu] > menuChoices[curMenu])
|
|
curSel[curMenu] = 2;
|
|
|
|
// if in front or rear weapon upgrade screen
|
|
if (curMenu == 4 && (curSel[1] == 3 || curSel[1] == 4))
|
|
{
|
|
player[0].items.weapon[curSel[1]-3].power = temp_weapon_power[curSel[4]-2];
|
|
if (curSel[curMenu] == 4)
|
|
player[0].weapon_mode = 1;
|
|
}
|
|
|
|
// if in joystick config, skip disabled items when digital
|
|
if (curMenu == 12 && joysticks > 0 && !joystick[joystick_config].analog && curSel[curMenu] == 4)
|
|
curSel[curMenu] = 6;
|
|
|
|
break;
|
|
|
|
case SDLK_HOME:
|
|
if (curMenu == 8) // data cube
|
|
yLoc = 0;
|
|
break;
|
|
|
|
case SDLK_END:
|
|
if (curMenu == 8) // data cube
|
|
yLoc = (cube[currentCube].last_line - 9) * 12;
|
|
break;
|
|
|
|
case SDLK_LEFT:
|
|
if (curMenu == 12) // joystick settings menu
|
|
{
|
|
if (joysticks > 0)
|
|
{
|
|
switch (curSel[curMenu])
|
|
{
|
|
case 2:
|
|
if (joystick_config == 0)
|
|
joystick_config = joysticks;
|
|
joystick_config--;
|
|
break;
|
|
case 3:
|
|
joystick[joystick_config].analog = !joystick[joystick_config].analog;
|
|
break;
|
|
case 4:
|
|
if (joystick[joystick_config].sensitivity == 0)
|
|
joystick[joystick_config].sensitivity = 10;
|
|
else
|
|
joystick[joystick_config].sensitivity--;
|
|
break;
|
|
case 5:
|
|
if (joystick[joystick_config].threshold == 0)
|
|
joystick[joystick_config].threshold = 10;
|
|
else
|
|
joystick[joystick_config].threshold--;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (curMenu == 9)
|
|
{
|
|
switch (curSel[curMenu])
|
|
{
|
|
case 3:
|
|
case 4:
|
|
JE_playSampleNum(S_CURSOR);
|
|
|
|
int temp = curSel[curMenu] - 3;
|
|
do {
|
|
if (joysticks == 0)
|
|
{
|
|
inputDevice[temp == 0 ? 1 : 0] = inputDevice[temp]; // swap controllers
|
|
}
|
|
if (inputDevice[temp] <= 1)
|
|
{
|
|
inputDevice[temp] = 2 + joysticks;
|
|
} else {
|
|
inputDevice[temp]--;
|
|
}
|
|
} while (inputDevice[temp] == inputDevice[temp == 0 ? 1 : 0]);
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (curMenu == 2 || curMenu == 4 || curMenu == 11)
|
|
{
|
|
JE_playSampleNum(S_CURSOR);
|
|
}
|
|
|
|
switch (curMenu)
|
|
{
|
|
case 2:
|
|
case 11:
|
|
switch (curSel[curMenu])
|
|
{
|
|
case 4:
|
|
JE_changeVolume(&tyrMusicVolume, -12, &fxVolume, 0);
|
|
if (music_disabled)
|
|
{
|
|
music_disabled = false;
|
|
restart_song();
|
|
}
|
|
break;
|
|
case 5:
|
|
JE_changeVolume(&tyrMusicVolume, 0, &fxVolume, -12);
|
|
samples_disabled = false;
|
|
break;
|
|
}
|
|
break;
|
|
case 4:
|
|
switch (curSel[1])
|
|
{
|
|
case 3:
|
|
case 4:
|
|
if (leftPower)
|
|
player[0].items.weapon[curSel[1]-3].power = --temp_weapon_power[curSel[4]-2];
|
|
else
|
|
JE_playSampleNum(S_CLINK);
|
|
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case SDLK_RIGHT:
|
|
if (curMenu == 12) // joystick settings menu
|
|
{
|
|
if (joysticks > 0)
|
|
{
|
|
switch (curSel[curMenu])
|
|
{
|
|
case 2:
|
|
joystick_config++;
|
|
joystick_config %= joysticks;
|
|
break;
|
|
case 3:
|
|
joystick[joystick_config].analog = !joystick[joystick_config].analog;
|
|
break;
|
|
case 4:
|
|
joystick[joystick_config].sensitivity++;
|
|
joystick[joystick_config].sensitivity %= 11;
|
|
break;
|
|
case 5:
|
|
joystick[joystick_config].threshold++;
|
|
joystick[joystick_config].threshold %= 11;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (curMenu == 9)
|
|
{
|
|
switch (curSel[curMenu])
|
|
{
|
|
case 3:
|
|
case 4:
|
|
JE_playSampleNum(S_CURSOR);
|
|
|
|
int temp = curSel[curMenu] - 3;
|
|
do {
|
|
if (joysticks == 0)
|
|
{
|
|
inputDevice[temp == 0 ? 1 : 0] = inputDevice[temp]; // swap controllers
|
|
}
|
|
if (inputDevice[temp] >= 2 + joysticks)
|
|
{
|
|
inputDevice[temp] = 1;
|
|
} else {
|
|
inputDevice[temp]++;
|
|
}
|
|
} while (inputDevice[temp] == inputDevice[temp == 0 ? 1 : 0]);
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (curMenu == 2 || curMenu == 4 || curMenu == 11)
|
|
{
|
|
JE_playSampleNum(S_CURSOR);
|
|
}
|
|
|
|
switch (curMenu)
|
|
{
|
|
case 2:
|
|
case 11:
|
|
switch (curSel[curMenu])
|
|
{
|
|
case 4:
|
|
JE_changeVolume(&tyrMusicVolume, 12, &fxVolume, 0);
|
|
if (music_disabled)
|
|
{
|
|
music_disabled = false;
|
|
restart_song();
|
|
}
|
|
break;
|
|
case 5:
|
|
JE_changeVolume(&tyrMusicVolume, 0, &fxVolume, 12);
|
|
samples_disabled = false;
|
|
break;
|
|
}
|
|
break;
|
|
case 4:
|
|
switch (curSel[1])
|
|
{
|
|
case 3:
|
|
case 4:
|
|
if (rightPower && rightPowerAfford)
|
|
player[0].items.weapon[curSel[1]-3].power = ++temp_weapon_power[curSel[4]-2];
|
|
else
|
|
JE_playSampleNum(S_CLINK);
|
|
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
} while (!(quit || gameLoaded || jumpSection));
|
|
|
|
#ifdef WITH_NETWORK
|
|
if (!quit && isNetworkGame)
|
|
{
|
|
JE_barShade(VGAScreen, 3, 3, 316, 196);
|
|
JE_barShade(VGAScreen, 1, 1, 318, 198);
|
|
JE_dString(VGAScreen, 10, 160, "Waiting for other player.", SMALL_FONT_SHAPES);
|
|
|
|
network_prepare(PACKET_WAITING);
|
|
network_send(4); // PACKET_WAITING
|
|
|
|
while (true)
|
|
{
|
|
service_SDL_events(false);
|
|
JE_showVGA();
|
|
|
|
if (packet_in[0] && SDLNet_Read16(&packet_in[0]->data[0]) == PACKET_WAITING)
|
|
{
|
|
network_update();
|
|
break;
|
|
}
|
|
|
|
network_update();
|
|
network_check();
|
|
|
|
SDL_Delay(16);
|
|
}
|
|
|
|
network_state_reset();
|
|
}
|
|
|
|
if (isNetworkGame)
|
|
{
|
|
while (!network_is_sync())
|
|
{
|
|
service_SDL_events(false);
|
|
JE_showVGA();
|
|
|
|
network_check();
|
|
SDL_Delay(16);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
if (gameLoaded)
|
|
fade_black(10);
|
|
}
|
|
|
|
void draw_ship_illustration( void )
|
|
{
|
|
// full of evil hardcoding
|
|
|
|
// ship
|
|
{
|
|
assert(player[0].items.ship > 0);
|
|
|
|
const int sprite_id = (player[0].items.ship < COUNTOF(ships)) // shipedit ships get a default
|
|
? ships[player[0].items.ship].bigshipgraphic - 1
|
|
: 31;
|
|
|
|
const int ship_x[6] = { 31, 0, 0, 0, 35, 31 },
|
|
ship_y[6] = { 36, 0, 0, 0, 33, 35 };
|
|
|
|
const int x = ship_x[sprite_id - 27],
|
|
y = ship_y[sprite_id - 27];
|
|
|
|
blit_sprite(VGAScreenSeg, x, y, OPTION_SHAPES, sprite_id);
|
|
}
|
|
|
|
// generator
|
|
{
|
|
assert(player[0].items.generator > 0 && player[0].items.generator < 7);
|
|
|
|
const int sprite_id = (player[0].items.generator == 1) // generator 1 and generator 2 have the same sprite
|
|
? player[0].items.generator + 15
|
|
: player[0].items.generator + 14;
|
|
|
|
const int generator_x[5] = { 62, 64, 67, 66, 63 },
|
|
generator_y[5] = { 84, 85, 86, 84, 97 };
|
|
const int x = generator_x[sprite_id - 16],
|
|
y = generator_y[sprite_id - 16];
|
|
|
|
blit_sprite(VGAScreenSeg, x, y, WEAPON_SHAPES, sprite_id);
|
|
}
|
|
|
|
const int weapon_sprites[43] =
|
|
{
|
|
-1, 0, 1, 2, 3, 4, 5, 6, 7, 8,
|
|
9, 10, 11, 21, 5, 13, -1, 14, 15, 0,
|
|
14, 9, 8, 2, 15, 0, 13, 0, 8, 8,
|
|
11, 1, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
0, 2, 1
|
|
};
|
|
|
|
// front weapon
|
|
if (player[0].items.weapon[FRONT_WEAPON].id > 0)
|
|
{
|
|
const int front_weapon_xy_list[43] =
|
|
{
|
|
-1, 4, 9, 3, 8, 2, 5, 10, 1, -1,
|
|
-1, -1, -1, 7, 8, -1, -1, 0, -1, 4,
|
|
0, -1, -1, 3, -1, 4, -1, 4, -1, -1,
|
|
-1, 9, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
0, 3, 9
|
|
};
|
|
|
|
const int front_weapon_x[12] = { 59, 66, 66, 54, 61, 51, 58, 51, 61, 52, 53, 58 };
|
|
const int front_weapon_y[12] = { 38, 53, 41, 36, 48, 35, 41, 35, 53, 41, 39, 31 };
|
|
const int x = front_weapon_x[front_weapon_xy_list[player[0].items.weapon[FRONT_WEAPON].id]],
|
|
y = front_weapon_y[front_weapon_xy_list[player[0].items.weapon[FRONT_WEAPON].id]];
|
|
|
|
blit_sprite(VGAScreenSeg, x, y, WEAPON_SHAPES, weapon_sprites[player[0].items.weapon[FRONT_WEAPON].id]); // ship illustration: front weapon
|
|
}
|
|
|
|
// rear weapon
|
|
if (player[0].items.weapon[REAR_WEAPON].id > 0)
|
|
{
|
|
const int rear_weapon_xy_list[43] =
|
|
{
|
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, 0,
|
|
1, 2, 3, -1, 4, 5, -1, -1, 6, -1,
|
|
-1, 1, 0, -1, 6, -1, 5, -1, 0, 0,
|
|
3, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
0, -1, -1
|
|
};
|
|
|
|
const int rear_weapon_x[7] = { 41, 27, 49, 43, 51, 39, 41 };
|
|
const int rear_weapon_y[7] = { 92, 92, 113, 102, 97, 96, 76 };
|
|
const int x = rear_weapon_x[rear_weapon_xy_list[player[0].items.weapon[REAR_WEAPON].id]],
|
|
y = rear_weapon_y[rear_weapon_xy_list[player[0].items.weapon[REAR_WEAPON].id]];
|
|
|
|
blit_sprite(VGAScreenSeg, x, y, WEAPON_SHAPES, weapon_sprites[player[0].items.weapon[REAR_WEAPON].id]);
|
|
}
|
|
|
|
// sidekicks
|
|
JE_drawItem(6, player[0].items.sidekick[LEFT_SIDEKICK], 3, 84);
|
|
JE_drawItem(7, player[0].items.sidekick[RIGHT_SIDEKICK], 129, 84);
|
|
|
|
// shield
|
|
blit_sprite_hv(VGAScreenSeg, 28, 23, OPTION_SHAPES, 26, 15, shields[player[0].items.shield].mpwr - 10);
|
|
}
|
|
|
|
void load_cubes( void )
|
|
{
|
|
for (int cube_slot = 0; cube_slot < cubeMax; ++cube_slot)
|
|
{
|
|
memset(cube[cube_slot].text, 0, sizeof(cube->text));
|
|
|
|
load_cube(cube_slot, cubeList[cube_slot]);
|
|
}
|
|
}
|
|
|
|
bool load_cube( int cube_slot, int cube_index )
|
|
{
|
|
FILE *f = dir_fopen_die(data_dir(), cube_file, "rb");
|
|
|
|
char buf[256];
|
|
|
|
// seek to the cube
|
|
while (cube_index > 0)
|
|
{
|
|
read_encrypted_pascal_string(buf, sizeof(buf), f);
|
|
if (buf[0] == '*')
|
|
--cube_index;
|
|
|
|
if (feof(f))
|
|
{
|
|
fclose(f);
|
|
|
|
return false;
|
|
}
|
|
}
|
|
|
|
str_pop_int(&buf[4], &cube[cube_slot].face_sprite);
|
|
--cube[cube_slot].face_sprite;
|
|
|
|
read_encrypted_pascal_string(cube[cube_slot].title, sizeof(cube[cube_slot].title), f);
|
|
read_encrypted_pascal_string(cube[cube_slot].header, sizeof(cube[cube_slot].header), f);
|
|
|
|
uint line = 0, line_chars = 0, line_width = 0;
|
|
|
|
// for each line of decrypted text, split the line into words
|
|
// and add them individually to the lines of wrapped text
|
|
for (; ; )
|
|
{
|
|
read_encrypted_pascal_string(buf, sizeof(buf), f);
|
|
|
|
// end of data
|
|
if (feof(f) || buf[0] == '*')
|
|
break;
|
|
|
|
// new paragraph
|
|
if (strlen(buf) == 0)
|
|
{
|
|
if (line_chars == 0)
|
|
line += 4; // subsequent new paragaphs indicate 4-line break
|
|
else
|
|
++line;
|
|
line_chars = 0;
|
|
line_width = 0;
|
|
|
|
continue;
|
|
}
|
|
|
|
uint word_start = 0;
|
|
for (uint i = 0; ; ++i)
|
|
{
|
|
bool end_of_line = (buf[i] == '\0'),
|
|
end_of_word = end_of_line || (buf[i] == ' ');
|
|
|
|
if (end_of_word)
|
|
{
|
|
buf[i] = '\0';
|
|
|
|
char *word = &buf[word_start];
|
|
word_start = i + 1;
|
|
|
|
uint word_chars = strlen(word),
|
|
word_width = JE_textWidth(word, TINY_FONT);
|
|
|
|
// word won't fit; no can do
|
|
if (word_chars > cube_line_chars || word_width > cube_line_width)
|
|
break;
|
|
|
|
bool prepend_space = true;
|
|
|
|
line_chars += word_chars + (prepend_space ? 1 : 0);
|
|
line_width += word_width + (prepend_space ? 6 : 0);
|
|
|
|
// word won't fit on current line; use next
|
|
if (line_chars > cube_line_chars || line_width > cube_line_width)
|
|
{
|
|
++line;
|
|
line_chars = word_chars;
|
|
line_width = word_width;
|
|
|
|
prepend_space = false;
|
|
}
|
|
|
|
// append word
|
|
if (line < COUNTOF(cube->text))
|
|
{
|
|
if (prepend_space)
|
|
strcat(cube[cube_slot].text[line], " ");
|
|
strcat(cube[cube_slot].text[line], word);
|
|
|
|
// track last line with text
|
|
cube[cube_slot].last_line = line + 1;
|
|
}
|
|
}
|
|
|
|
if (end_of_line)
|
|
break;
|
|
}
|
|
}
|
|
|
|
fclose(f);
|
|
|
|
return true;
|
|
}
|
|
|
|
void JE_drawItem( JE_byte itemType, JE_word itemNum, JE_word x, JE_word y )
|
|
{
|
|
JE_word tempW = 0;
|
|
|
|
if (itemNum > 0)
|
|
{
|
|
switch (itemType)
|
|
{
|
|
case 2:
|
|
case 3:
|
|
tempW = weaponPort[itemNum].itemgraphic;
|
|
break;
|
|
case 5:
|
|
tempW = powerSys[itemNum].itemgraphic;
|
|
break;
|
|
case 6:
|
|
case 7:
|
|
tempW = options[itemNum].itemgraphic;
|
|
break;
|
|
case 4:
|
|
tempW = shields[itemNum].itemgraphic;
|
|
break;
|
|
}
|
|
|
|
if (itemType == 1)
|
|
{
|
|
if (itemNum > 90)
|
|
{
|
|
shipGrPtr = &shapes9;
|
|
shipGr = JE_SGr(itemNum - 90, &shipGrPtr);
|
|
blit_sprite2x2(VGAScreen, x, y, *shipGrPtr, shipGr);
|
|
}
|
|
else
|
|
{
|
|
blit_sprite2x2(VGAScreen, x, y, shapes9, ships[itemNum].shipgraphic);
|
|
}
|
|
}
|
|
else if (tempW > 0)
|
|
{
|
|
blit_sprite2x2(VGAScreen, x, y, shapes6, tempW);
|
|
}
|
|
}
|
|
}
|
|
|
|
void JE_drawMenuHeader( void )
|
|
{
|
|
switch (curMenu)
|
|
{
|
|
case 8:
|
|
strcpy(tempStr, cube[curSel[7]-2].header);
|
|
break;
|
|
case 7:
|
|
strcpy(tempStr, menuInt[1][1]);
|
|
break;
|
|
case 6:
|
|
strcpy(tempStr, menuInt[3][performSave + 1]);
|
|
break;
|
|
default:
|
|
strcpy(tempStr, menuInt[curMenu + 1][0]);
|
|
break;
|
|
}
|
|
JE_dString(VGAScreen, 74 + JE_fontCenter(tempStr, FONT_SHAPES), 10, tempStr, FONT_SHAPES);
|
|
}
|
|
|
|
void JE_drawMenuChoices( void )
|
|
{
|
|
JE_byte x;
|
|
char *str;
|
|
|
|
for (x = 2; x <= menuChoices[curMenu]; x++)
|
|
{
|
|
int tempY = 38 + (x-1) * 16;
|
|
|
|
if (curMenu == 0)
|
|
{
|
|
if (x == 7)
|
|
{
|
|
tempY += 16;
|
|
}
|
|
}
|
|
|
|
if (curMenu == 9)
|
|
{
|
|
if (x > 3)
|
|
{
|
|
tempY += 16;
|
|
}
|
|
if (x > 4)
|
|
{
|
|
tempY += 16;
|
|
}
|
|
}
|
|
|
|
if (!(curMenu == 3 && x == menuChoices[curMenu]))
|
|
{
|
|
tempY -= 16;
|
|
}
|
|
|
|
str = malloc(strlen(menuInt[curMenu + 1][x-1])+2);
|
|
if (curSel[curMenu] == x)
|
|
{
|
|
str[0] = '~';
|
|
strcpy(str+1, menuInt[curMenu + 1][x-1]);
|
|
} else {
|
|
strcpy(str, menuInt[curMenu + 1][x-1]);
|
|
}
|
|
JE_dString(VGAScreen, 166, tempY, str, SMALL_FONT_SHAPES);
|
|
free(str);
|
|
|
|
if (keyboardUsed && curSel[curMenu] == x)
|
|
{
|
|
set_mouse_position(305, tempY + 6);
|
|
}
|
|
}
|
|
}
|
|
|
|
void JE_updateNavScreen( void )
|
|
{
|
|
JE_byte x;
|
|
|
|
/* minor issues: */
|
|
/* TODO: The scroll to the new planet is too fast, I think */
|
|
/* TODO: The starting coordinates for the scrolling effect may be wrong, the
|
|
yellowish planet below Tyrian isn't visible for as many frames as in the
|
|
original. */
|
|
|
|
tempNavX = roundf(navX);
|
|
tempNavY = roundf(navY);
|
|
fill_rectangle_xy(VGAScreen, 19, 16, 135, 169, 2);
|
|
JE_drawNavLines(true);
|
|
JE_drawNavLines(false);
|
|
JE_drawDots();
|
|
|
|
for (x = 0; x < 11; x++)
|
|
JE_drawPlanet(x);
|
|
|
|
for (x = 0; x < menuChoices[3]-1; x++)
|
|
{
|
|
if (mapPlanet[x] > 11)
|
|
JE_drawPlanet(mapPlanet[x] - 1);
|
|
}
|
|
|
|
if (mapOrigin > 11)
|
|
JE_drawPlanet(mapOrigin - 1);
|
|
|
|
blit_sprite(VGAScreenSeg, 0, 0, OPTION_SHAPES, 28); // navigation screen interface
|
|
|
|
if (curSel[3] < menuChoices[3])
|
|
{
|
|
const unsigned int origin_x_offset = sprite(PLANET_SHAPES, PGR[mapOrigin-1]-1)->width / 2,
|
|
origin_y_offset = sprite(PLANET_SHAPES, PGR[mapOrigin-1]-1)->height / 2,
|
|
dest_x_offset = sprite(PLANET_SHAPES, PGR[mapPlanet[curSel[3]-2] - 1]-1)->width / 2,
|
|
dest_y_offset = sprite(PLANET_SHAPES, PGR[mapPlanet[curSel[3]-2] - 1]-1)->height / 2;
|
|
|
|
newNavX = (planetX[mapOrigin-1] - origin_x_offset
|
|
+ planetX[mapPlanet[curSel[3]-2] - 1] - dest_x_offset) / 2.0f;
|
|
newNavY = (planetY[mapOrigin-1] - origin_y_offset
|
|
+ planetY[mapPlanet[curSel[3]-2] - 1] - dest_y_offset) / 2.0f;
|
|
}
|
|
|
|
navX = navX + (newNavX - navX) / 2.0f;
|
|
navY = navY + (newNavY - navY) / 2.0f;
|
|
|
|
if (abs(newNavX - navX) < 1)
|
|
navX = newNavX;
|
|
if (abs(newNavY - navY) < 1)
|
|
navY = newNavY;
|
|
|
|
fill_rectangle_xy(VGAScreen, 314, 0, 319, 199, 230);
|
|
|
|
if (planetAniWait > 0)
|
|
{
|
|
planetAniWait--;
|
|
}
|
|
else
|
|
{
|
|
planetAni++;
|
|
if (planetAni > 14)
|
|
planetAni = 0;
|
|
planetAniWait = 3;
|
|
}
|
|
|
|
if (currentDotWait > 0)
|
|
{
|
|
currentDotWait--;
|
|
}
|
|
else
|
|
{
|
|
if (currentDotNum < planetDots[curSel[3]-2])
|
|
currentDotNum++;
|
|
currentDotWait = 5;
|
|
}
|
|
}
|
|
|
|
void JE_drawLines( SDL_Surface *surface, JE_boolean dark )
|
|
{
|
|
JE_byte x, y;
|
|
JE_integer tempX, tempY;
|
|
JE_integer tempX2, tempY2;
|
|
JE_word tempW, tempW2;
|
|
|
|
tempX2 = -10;
|
|
tempY2 = 0;
|
|
|
|
tempW = 0;
|
|
for (x = 0; x < 20; x++)
|
|
{
|
|
tempW += 15;
|
|
tempX = tempW - tempX2;
|
|
|
|
if (tempX > 18 && tempX < 135)
|
|
{
|
|
if (dark)
|
|
{
|
|
JE_rectangle(surface, tempX + 1, 0, tempX + 1, 199, 32+3);
|
|
} else {
|
|
JE_rectangle(surface, tempX, 0, tempX, 199, 32+5);
|
|
}
|
|
}
|
|
}
|
|
|
|
tempW = 0;
|
|
for (y = 0; y < 20; y++)
|
|
{
|
|
tempW += 15;
|
|
tempY = tempW - tempY2;
|
|
|
|
if (tempY > 15 && tempY < 169)
|
|
{
|
|
if (dark)
|
|
{
|
|
JE_rectangle(surface, 0, tempY + 1, 319, tempY + 1, 32+3);
|
|
} else {
|
|
JE_rectangle(surface, 0, tempY, 319, tempY, 32+5);
|
|
}
|
|
|
|
tempW2 = 0;
|
|
|
|
for (x = 0; x < 20; x++)
|
|
{
|
|
tempW2 += 15;
|
|
tempX = tempW2 - tempX2;
|
|
if (tempX > 18 && tempX < 135)
|
|
{
|
|
JE_pix3(surface, tempX, tempY, 32+6);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/* SYN: This was originally PROC drawlines... yes, there were two different procs called
|
|
drawlines in different scopes in the same file. Dammit, Jason, why do you do this to me? */
|
|
|
|
void JE_drawNavLines( JE_boolean dark )
|
|
{
|
|
JE_byte x, y;
|
|
JE_integer tempX, tempY;
|
|
JE_integer tempX2, tempY2;
|
|
JE_word tempW, tempW2;
|
|
|
|
tempX2 = tempNavX >> 1;
|
|
tempY2 = tempNavY >> 1;
|
|
|
|
tempW = 0;
|
|
for (x = 1; x <= 20; x++)
|
|
{
|
|
tempW += 15;
|
|
tempX = tempW - tempX2;
|
|
|
|
if (tempX > 18 && tempX < 135)
|
|
{
|
|
if (dark)
|
|
JE_rectangle(VGAScreen, tempX + 1, 16, tempX + 1, 169, 1);
|
|
else
|
|
JE_rectangle(VGAScreen, tempX, 16, tempX, 169, 5);
|
|
}
|
|
}
|
|
|
|
tempW = 0;
|
|
for (y = 1; y <= 20; y++)
|
|
{
|
|
tempW += 15;
|
|
tempY = tempW - tempY2;
|
|
|
|
if (tempY > 15 && tempY < 169)
|
|
{
|
|
if (dark)
|
|
JE_rectangle(VGAScreen, 19, tempY + 1, 135, tempY + 1, 1);
|
|
else
|
|
JE_rectangle(VGAScreen, 8, tempY, 160, tempY, 5);
|
|
|
|
tempW2 = 0;
|
|
|
|
for (x = 0; x < 20; x++)
|
|
{
|
|
tempW2 += 15;
|
|
tempX = tempW2 - tempX2;
|
|
if (tempX > 18 && tempX < 135)
|
|
JE_pix3(VGAScreen, tempX, tempY, 7);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void JE_drawDots( void )
|
|
{
|
|
JE_byte x, y;
|
|
JE_integer tempX, tempY;
|
|
|
|
for (x = 0; x < mapPNum; x++)
|
|
{
|
|
for (y = 0; y < planetDots[x]; y++)
|
|
{
|
|
tempX = planetDotX[x][y] - tempNavX + 66 - 2;
|
|
tempY = planetDotY[x][y] - tempNavY + 85 - 2;
|
|
if (tempX > 0 && tempX < 140 && tempY > 0 && tempY < 168)
|
|
blit_sprite(VGAScreenSeg, tempX, tempY, OPTION_SHAPES, (x == curSel[3]-2 && y < currentDotNum) ? 30 : 29); // navigation dots
|
|
}
|
|
}
|
|
}
|
|
|
|
void JE_drawPlanet( JE_byte planetNum )
|
|
{
|
|
JE_integer tempZ = PGR[planetNum]-1,
|
|
tempX = planetX[planetNum] + 66 - tempNavX - sprite(PLANET_SHAPES, tempZ)->width / 2,
|
|
tempY = planetY[planetNum] + 85 - tempNavY - sprite(PLANET_SHAPES, tempZ)->height / 2;
|
|
|
|
if (tempX > -7 && tempX + sprite(PLANET_SHAPES, tempZ)->width < 170 && tempY > 0 && tempY < 160)
|
|
{
|
|
if (PAni[planetNum])
|
|
tempZ += planetAni;
|
|
|
|
blit_sprite_dark(VGAScreenSeg, tempX + 3, tempY + 3, PLANET_SHAPES, tempZ, false);
|
|
blit_sprite(VGAScreenSeg, tempX, tempY, PLANET_SHAPES, tempZ); // planets
|
|
}
|
|
}
|
|
|
|
void JE_scaleBitmap( SDL_Surface *dst_bitmap, const SDL_Surface *src_bitmap, int x1, int y1, int x2, int y2 )
|
|
{
|
|
/* This function scales one screen and writes the result to another.
|
|
* The only code that calls it is the code run when you select 'ship
|
|
* specs' from the main menu.
|
|
*
|
|
* Originally this used fixed point math. I haven't seen that in ages :).
|
|
* But we're well past the point of needing that.*/
|
|
|
|
assert(src_bitmap != NULL && dst_bitmap != NULL);
|
|
assert(x1 >= 0 && y1 >= 0 && x2 < src_bitmap->pitch && y2 < src_bitmap->h);
|
|
|
|
int w = x2 - x1 + 1,
|
|
h = y2 - y1 + 1;
|
|
float base_skip_w = src_bitmap->pitch / (float)w,
|
|
base_skip_h = src_bitmap->h / (float)h;
|
|
float cumulative_skip_w, cumulative_skip_h;
|
|
|
|
|
|
//Okay, it's time to loop through and add bits of A to a rectangle in B
|
|
Uint8 *dst = dst_bitmap->pixels; /* 8-bit specific */
|
|
const Uint8 *src, *src_w; /* 8-bit specific */
|
|
|
|
dst += y1 * dst_bitmap->pitch + x1;
|
|
cumulative_skip_h = 0;
|
|
|
|
for (int i = 0; i < h; i++)
|
|
{
|
|
//this sets src to the beginning of our desired line
|
|
src = src_w = (Uint8 *)(src_bitmap->pixels) + (src_bitmap->w * ((unsigned int)cumulative_skip_h));
|
|
cumulative_skip_h += base_skip_h;
|
|
cumulative_skip_w = 0;
|
|
|
|
for (int j = 0; j < w; j++)
|
|
{
|
|
//copy and move pointers
|
|
*dst = *src;
|
|
dst++;
|
|
|
|
cumulative_skip_w += base_skip_w;
|
|
src = src_w + ((unsigned int)cumulative_skip_w); //value is floored
|
|
}
|
|
|
|
dst += dst_bitmap->pitch - w;
|
|
}
|
|
}
|
|
|
|
void JE_initWeaponView( void )
|
|
{
|
|
fill_rectangle_xy(VGAScreen, 8, 8, 144, 177, 0);
|
|
|
|
player[0].sidekick[LEFT_SIDEKICK].x = 72 - 15;
|
|
player[0].sidekick[LEFT_SIDEKICK].y = 120;
|
|
player[0].sidekick[RIGHT_SIDEKICK].x = 72 + 15;
|
|
player[0].sidekick[RIGHT_SIDEKICK].y = 120;
|
|
|
|
player[0].x = 72;
|
|
player[0].y = 110;
|
|
player[0].delta_x_shot_move = 0;
|
|
player[0].delta_y_shot_move = 0;
|
|
player[0].last_x_explosion_follow = 72;
|
|
player[0].last_y_explosion_follow = 110;
|
|
power = 500;
|
|
lastPower = 500;
|
|
|
|
memset(shotAvail, 0, sizeof(shotAvail));
|
|
|
|
memset(shotRepeat, 1, sizeof(shotRepeat));
|
|
memset(shotMultiPos, 0, sizeof(shotMultiPos));
|
|
|
|
initialize_starfield();
|
|
}
|
|
|
|
void JE_computeDots( void )
|
|
{
|
|
JE_integer tempX, tempY;
|
|
JE_longint distX, distY;
|
|
JE_byte x, y;
|
|
|
|
for (x = 0; x < mapPNum; x++)
|
|
{
|
|
distX = (int)(planetX[mapPlanet[x]-1]) - (int)(planetX[mapOrigin-1]);
|
|
distY = (int)(planetY[mapPlanet[x]-1]) - (int)(planetY[mapOrigin-1]);
|
|
tempX = abs(distX) + abs(distY);
|
|
|
|
if (tempX != 0)
|
|
{
|
|
planetDots[x] = roundf(sqrtf(sqrtf((distX * distX) + (distY * distY)))) - 1;
|
|
} else {
|
|
planetDots[x] = 0;
|
|
}
|
|
|
|
if (planetDots[x] > 10)
|
|
{
|
|
planetDots[x] = 10;
|
|
}
|
|
|
|
for (y = 0; y < planetDots[x]; y++)
|
|
{
|
|
tempX = JE_partWay(planetX[mapOrigin-1], planetX[mapPlanet[x]-1], planetDots[x], y);
|
|
tempY = JE_partWay(planetY[mapOrigin-1], planetY[mapPlanet[x]-1], planetDots[x], y);
|
|
/* ??? Why does it use temp? =P */
|
|
planetDotX[x][y] = tempX;
|
|
planetDotY[x][y] = tempY;
|
|
}
|
|
}
|
|
}
|
|
|
|
JE_integer JE_partWay( JE_integer start, JE_integer finish, JE_byte dots, JE_byte dist )
|
|
{
|
|
return (finish - start) / (dots + 2) * (dist + 1) + start;
|
|
}
|
|
|
|
void JE_doShipSpecs( void )
|
|
{
|
|
/* This function is called whenever you select 'ship specs' in the
|
|
* game menu. It draws the nice green tech screen and scales it onto
|
|
* the main window. To do this we need two temp buffers, so we're going
|
|
* to use VGAScreen and game_screen for the purpose (making things more
|
|
* complex than they would be if we just malloc'd, but faster)
|
|
*
|
|
* Originally the whole system was pretty oddly designed. So I changed it.
|
|
* Currently drawFunkyScreen creates the image, scaleInPicture draws it,
|
|
* and doFunkyScreen ties everything together. Before it was more like
|
|
* an oddly designed, unreusable, global sharing hierarchy. */
|
|
|
|
//create the image we want
|
|
wait_noinput(true, true, true);
|
|
JE_drawShipSpecs(game_screen, VGAScreen2);
|
|
|
|
//reset VGAScreen2, which we clobbered
|
|
JE_loadPic(VGAScreen2, 1, false);
|
|
|
|
//draw it
|
|
JE_playSampleNum(16);
|
|
JE_scaleInPicture(VGAScreen, game_screen);
|
|
wait_input(true, true, true);
|
|
}
|
|
|
|
void JE_drawMainMenuHelpText( void )
|
|
{
|
|
char tempStr[67];
|
|
JE_byte temp;
|
|
|
|
temp = curSel[curMenu] - 2;
|
|
if (curMenu == 12) // joystick settings menu help
|
|
{
|
|
int help[16] = { 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 24, 11 };
|
|
memcpy(tempStr, mainMenuHelp[help[curSel[curMenu] - 2]], sizeof(tempStr));
|
|
}
|
|
else if (curMenu < 3 || curMenu == 9 || curMenu > 10)
|
|
{
|
|
memcpy(tempStr, mainMenuHelp[(menuHelp[curMenu][temp])-1], sizeof(tempStr));
|
|
}
|
|
else if (curMenu == 5 && curSel[5] == 10)
|
|
{
|
|
memcpy(tempStr, mainMenuHelp[25-1], sizeof(tempStr));
|
|
}
|
|
else if (leftPower || rightPower)
|
|
{
|
|
memcpy(tempStr, mainMenuHelp[24-1], sizeof(tempStr));
|
|
}
|
|
else if ( (temp == menuChoices[curMenu] - 1) || ( (curMenu == 7) && (cubeMax == 0) ) )
|
|
{
|
|
memcpy(tempStr, mainMenuHelp[12-1], sizeof(tempStr));
|
|
}
|
|
else
|
|
{
|
|
memcpy(tempStr, mainMenuHelp[17 + curMenu - 3], sizeof(tempStr));
|
|
}
|
|
|
|
JE_textShade(VGAScreen, 10, 187, tempStr, 14, 1, DARKEN);
|
|
}
|
|
|
|
JE_boolean JE_quitRequest( void )
|
|
{
|
|
bool quit_selected = true, done = false;
|
|
|
|
JE_clearKeyboard();
|
|
JE_wipeKey();
|
|
wait_noinput(true, true, true);
|
|
|
|
JE_barShade(VGAScreen, 65, 55, 255, 155);
|
|
|
|
while (!done)
|
|
{
|
|
Uint8 col = 8;
|
|
int colC = 1;
|
|
|
|
do
|
|
{
|
|
service_SDL_events(true);
|
|
setjasondelay(4);
|
|
|
|
blit_sprite(VGAScreen, 50, 50, OPTION_SHAPES, 35); // message box
|
|
JE_textShade(VGAScreen, 70, 60, miscText[28], 0, 5, FULL_SHADE);
|
|
JE_helpBox(VGAScreen, 70, 90, miscText[30], 30);
|
|
|
|
col += colC;
|
|
if (col > 8 || col < 2)
|
|
colC = -colC;
|
|
|
|
int temp_x, temp_c;
|
|
|
|
temp_x = 54 + 45 - (JE_textWidth(miscText[9], FONT_SHAPES) / 2);
|
|
temp_c = quit_selected ? col - 12 : -5;
|
|
|
|
JE_outTextAdjust(VGAScreen, temp_x, 128, miscText[9], 15, temp_c, FONT_SHAPES, true);
|
|
|
|
temp_x = 149 + 45 - (JE_textWidth(miscText[10], FONT_SHAPES) / 2);
|
|
temp_c = !quit_selected ? col - 12 : -5;
|
|
|
|
JE_outTextAdjust(VGAScreen, temp_x, 128, miscText[10], 15, temp_c, FONT_SHAPES, true);
|
|
|
|
if (has_mouse)
|
|
{
|
|
JE_mouseStart();
|
|
JE_showVGA();
|
|
JE_mouseReplace();
|
|
}
|
|
else
|
|
{
|
|
JE_showVGA();
|
|
}
|
|
|
|
wait_delay();
|
|
|
|
push_joysticks_as_keyboard();
|
|
service_SDL_events(false);
|
|
|
|
} while (!newkey && !mousedown);
|
|
|
|
if (mousedown)
|
|
{
|
|
if (lastmouse_y > 123 && lastmouse_y < 149)
|
|
{
|
|
if (lastmouse_x > 56 && lastmouse_x < 142)
|
|
{
|
|
quit_selected = true;
|
|
done = true;
|
|
}
|
|
else if (lastmouse_x > 151 && lastmouse_x < 237)
|
|
{
|
|
quit_selected = false;
|
|
done = true;
|
|
}
|
|
}
|
|
mousedown = false;
|
|
}
|
|
else if (newkey)
|
|
{
|
|
switch (lastkey_sym)
|
|
{
|
|
case SDLK_LEFT:
|
|
case SDLK_RIGHT:
|
|
case SDLK_TAB:
|
|
quit_selected = !quit_selected;
|
|
JE_playSampleNum(S_CURSOR);
|
|
break;
|
|
case SDLK_RETURN:
|
|
case SDLK_SPACE:
|
|
done = true;
|
|
break;
|
|
case SDLK_ESCAPE:
|
|
quit_selected = false;
|
|
done = true;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
JE_playSampleNum(quit_selected ? S_SPRING : S_CLICK);
|
|
|
|
#ifdef WITH_NETWORK
|
|
if (isNetworkGame && quit_selected)
|
|
{
|
|
network_prepare(PACKET_QUIT);
|
|
network_send(4); // PACKET QUIT
|
|
|
|
network_tyrian_halt(0, true);
|
|
}
|
|
#endif
|
|
|
|
return quit_selected;
|
|
}
|
|
|
|
void JE_genItemMenu( JE_byte itemNum )
|
|
{
|
|
menuChoices[4] = itemAvailMax[itemAvailMap[itemNum - 2] - 1] + 2;
|
|
|
|
temp3 = 2;
|
|
temp2 = *playeritem_map(&player[0].items, itemNum - 2);
|
|
|
|
strcpy(menuInt[5][0], menuInt[2][itemNum - 1]);
|
|
|
|
for (tempW = 0; tempW < itemAvailMax[itemAvailMap[itemNum - 2] - 1]; tempW++)
|
|
{
|
|
temp = itemAvail[itemAvailMap[itemNum - 2] - 1][tempW];
|
|
switch (itemNum)
|
|
{
|
|
case 2:
|
|
strcpy(tempStr, ships[temp].name);
|
|
break;
|
|
case 3:
|
|
case 4:
|
|
strcpy(tempStr, weaponPort[temp].name);
|
|
break;
|
|
case 5:
|
|
strcpy(tempStr, shields[temp].name);
|
|
break;
|
|
case 6:
|
|
strcpy(tempStr, powerSys[temp].name);
|
|
break;
|
|
case 7:
|
|
case 8:
|
|
strcpy(tempStr, options[temp].name);
|
|
break;
|
|
}
|
|
if (temp == temp2)
|
|
{
|
|
temp3 = tempW + 2;
|
|
}
|
|
strcpy(menuInt[5][tempW], tempStr);
|
|
}
|
|
|
|
strcpy(menuInt[5][tempW], miscText[13]);
|
|
|
|
curSel[4] = temp3;
|
|
}
|
|
|
|
void JE_scaleInPicture( SDL_Surface *dst, const SDL_Surface *src )
|
|
{
|
|
for (int i = 2; i <= 160; i += 2)
|
|
{
|
|
if (JE_anyButton()) { break; }
|
|
|
|
JE_scaleBitmap(dst, src, 160 - i, 0, 160 + i - 1, 100 + roundf(i * 0.625f) - 1);
|
|
JE_showVGA();
|
|
|
|
SDL_Delay(1);
|
|
}
|
|
}
|
|
|
|
|
|
void JE_drawScore( void )
|
|
{
|
|
char cl[24];
|
|
if (curMenu == 4)
|
|
{
|
|
sprintf(cl, "%d", JE_cashLeft());
|
|
JE_textShade(VGAScreen, 65, 173, cl, 1, 6, DARKEN);
|
|
}
|
|
}
|
|
|
|
void JE_menuFunction( JE_byte select )
|
|
{
|
|
JE_byte x;
|
|
JE_word curSelect;
|
|
|
|
col = 0;
|
|
colC = -1;
|
|
JE_playSampleNum(S_CLICK);
|
|
|
|
curSelect = curSel[curMenu];
|
|
|
|
switch (curMenu)
|
|
{
|
|
case 0: //root menu
|
|
switch (select)
|
|
{
|
|
case 2: //cubes
|
|
curMenu = 7;
|
|
curSel[7] = 2;
|
|
break;
|
|
case 3: //shipspecs
|
|
JE_doShipSpecs();
|
|
break;
|
|
case 4://upgradeship
|
|
curMenu = 1;
|
|
break;
|
|
case 5: //options
|
|
curMenu = 2;
|
|
break;
|
|
case 6: //nextlevel
|
|
curMenu = 3;
|
|
newPal = 18;
|
|
JE_computeDots();
|
|
navX = planetX[mapOrigin - 1];
|
|
navY = planetY[mapOrigin - 1];
|
|
newNavX = navX;
|
|
newNavY = navY;
|
|
menuChoices[3] = mapPNum + 2;
|
|
curSel[3] = 2;
|
|
strcpy(menuInt[4][0], "Next Level");
|
|
for (x = 0; x < mapPNum; x++)
|
|
{
|
|
temp = mapPlanet[x];
|
|
strcpy(menuInt[4][x + 1], pName[temp - 1]);
|
|
}
|
|
strcpy(menuInt[4][x + 1], miscText[5]);
|
|
break;
|
|
case 7: //quit
|
|
if (JE_quitRequest())
|
|
{
|
|
gameLoaded = true;
|
|
mainLevel = 0;
|
|
}
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case 1: //upgradeship
|
|
if (select == 9) //done
|
|
{
|
|
curMenu = 0;
|
|
}
|
|
else // selected item to upgrade
|
|
{
|
|
old_items[0] = player[0].items;
|
|
|
|
lastDirection = 1;
|
|
JE_genItemMenu(select);
|
|
JE_initWeaponView();
|
|
curMenu = 4;
|
|
lastCurSel = curSel[4];
|
|
player[0].cash = player[0].cash * 2 - JE_cashLeft();
|
|
}
|
|
break;
|
|
|
|
case 2: //options
|
|
switch (select)
|
|
{
|
|
case 2:
|
|
curMenu = 6;
|
|
performSave = false;
|
|
quikSave = false;
|
|
break;
|
|
case 3:
|
|
curMenu = 6;
|
|
performSave = true;
|
|
quikSave = false;
|
|
break;
|
|
case 6:
|
|
curMenu = 12;
|
|
break;
|
|
case 7:
|
|
curMenu = 5;
|
|
break;
|
|
case 8:
|
|
curMenu = 0;
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case 3: //nextlevel
|
|
if (select == menuChoices[3]) //exit
|
|
{
|
|
curMenu = 0;
|
|
newPal = 1;
|
|
} else {
|
|
mainLevel = mapSection[curSelect - 2];
|
|
jumpSection = true;
|
|
}
|
|
break;
|
|
|
|
case 4: //buying
|
|
if (curSel[4] < menuChoices[4])
|
|
{
|
|
// select done
|
|
curSel[4] = menuChoices[4];
|
|
}
|
|
else // if done is selected
|
|
{
|
|
JE_playSampleNum(S_ITEM);
|
|
|
|
player[0].cash = JE_cashLeft();
|
|
curMenu = 1;
|
|
}
|
|
break;
|
|
|
|
case 5: /* keyboard settings */
|
|
if (curSelect == 12) /* Touchscreen mode */
|
|
{
|
|
touchscreenControlMode = touchscreenControlMode + 1;
|
|
if(touchscreenControlMode >= TOUCHSCREEN_CONTROL_LAST)
|
|
touchscreenControlMode = TOUCHSCREEN_CONTROL_FINGER;
|
|
JE_saveConfiguration();
|
|
}
|
|
else if (curSelect == 10) /* reset to defaults */
|
|
{
|
|
memcpy(keySettings, defaultKeySettings, sizeof(keySettings));
|
|
}
|
|
else if (curSelect == 11) /* done */
|
|
{
|
|
if (isNetworkGame || onePlayerAction)
|
|
{
|
|
curMenu = 11;
|
|
} else {
|
|
curMenu = 2;
|
|
}
|
|
}
|
|
else /* change key */
|
|
{
|
|
temp2 = 254;
|
|
int tempY = 38 + (curSelect - 2) * 12;
|
|
JE_textShade(VGAScreen, 236, tempY, SDL_GetKeyName(keySettings[curSelect-2]), (temp2 / 16), (temp2 % 16) - 8, DARKEN);
|
|
JE_showVGA();
|
|
|
|
wait_noinput(true, true, true);
|
|
|
|
col = 248;
|
|
colC = 1;
|
|
|
|
do {
|
|
setjasondelay(1);
|
|
|
|
col += colC;
|
|
if (col < 243 || col > 248)
|
|
{
|
|
colC *= -1;
|
|
}
|
|
JE_rectangle(VGAScreen, 230, tempY - 2, 300, tempY + 7, col);
|
|
|
|
poll_joysticks();
|
|
service_SDL_events(true);
|
|
|
|
JE_showVGA();
|
|
|
|
wait_delay();
|
|
} while (!newkey && !mousedown && !joydown);
|
|
|
|
if (newkey)
|
|
{
|
|
// already used? then swap
|
|
for (uint i = 0; i < COUNTOF(keySettings); ++i)
|
|
{
|
|
if (keySettings[i] == lastkey_sym)
|
|
{
|
|
keySettings[i] = keySettings[curSelect-2];
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (lastkey_sym != SDLK_ESCAPE && // reserved for menu
|
|
lastkey_sym != SDLK_F11 && // reserved for gamma
|
|
lastkey_sym != SDLK_p) // reserved for pause
|
|
{
|
|
JE_playSampleNum(S_CLICK);
|
|
keySettings[curSelect-2] = lastkey_sym;
|
|
++curSelect;
|
|
}
|
|
|
|
JE_wipeKey();
|
|
}
|
|
}
|
|
break;
|
|
|
|
case 6: //save
|
|
if (curSelect == 13)
|
|
{
|
|
if (quikSave)
|
|
{
|
|
curMenu = oldMenu;
|
|
newPal = oldPal;
|
|
} else {
|
|
curMenu = 2;
|
|
}
|
|
} else {
|
|
if (twoPlayerMode)
|
|
{
|
|
temp = 11;
|
|
} else {
|
|
temp = 0;
|
|
}
|
|
JE_operation(curSelect - 1 + temp);
|
|
if (quikSave)
|
|
{
|
|
curMenu = oldMenu;
|
|
newPal = oldPal;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case 7: //cubes
|
|
if (curSelect == menuChoices[curMenu])
|
|
{
|
|
curMenu = 0;
|
|
newPal = 1;
|
|
} else {
|
|
if (cubeMax > 0)
|
|
{
|
|
firstMenu9 = true;
|
|
curMenu = 8;
|
|
yLoc = 0;
|
|
yChg = 0;
|
|
currentCube = curSel[7] - 2;
|
|
} else {
|
|
curMenu = 0;
|
|
newPal = 1;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case 8: //cubes 2
|
|
curMenu = 7;
|
|
break;
|
|
|
|
case 9: //2player
|
|
switch (curSel[curMenu])
|
|
{
|
|
case 2:
|
|
mainLevel = mapSection[mapPNum-1];
|
|
jumpSection = true;
|
|
break;
|
|
case 3:
|
|
case 4:
|
|
JE_playSampleNum(S_CURSOR);
|
|
|
|
int temp = curSel[curMenu] - 3;
|
|
do {
|
|
if (joysticks == 0)
|
|
{
|
|
inputDevice[temp == 0 ? 1 : 0] = inputDevice[temp]; // swap controllers
|
|
}
|
|
if (inputDevice[temp] >= 2 + joysticks)
|
|
{
|
|
inputDevice[temp] = 1;
|
|
} else {
|
|
inputDevice[temp]++;
|
|
}
|
|
} while (inputDevice[temp] == inputDevice[temp == 0 ? 1 : 0]);
|
|
break;
|
|
case 5:
|
|
curMenu = 2;
|
|
break;
|
|
case 6:
|
|
if (JE_quitRequest())
|
|
{
|
|
gameLoaded = true;
|
|
mainLevel = 0;
|
|
}
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case 10: //arcade
|
|
switch (curSel[curMenu])
|
|
{
|
|
case 2:
|
|
mainLevel = mapSection[mapPNum-1];
|
|
jumpSection = true;
|
|
break;
|
|
case 3:
|
|
curMenu = 2;
|
|
break;
|
|
case 4:
|
|
if (JE_quitRequest())
|
|
{
|
|
gameLoaded = true;
|
|
mainLevel = 0;
|
|
}
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case 11: //dunno, possibly online multiplayer
|
|
switch (select)
|
|
{
|
|
case 2:
|
|
curMenu = 12;
|
|
break;
|
|
case 3:
|
|
curMenu = 5;
|
|
break;
|
|
case 6:
|
|
curMenu = 10;
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case 12: //joy
|
|
if (joysticks == 0 && select != 17)
|
|
break;
|
|
|
|
switch (select)
|
|
{
|
|
case 2:
|
|
joystick_config++;
|
|
joystick_config %= joysticks;
|
|
break;
|
|
case 3:
|
|
joystick[joystick_config].analog = !joystick[joystick_config].analog;
|
|
break;
|
|
case 4:
|
|
if (joystick[joystick_config].analog)
|
|
{
|
|
joystick[joystick_config].sensitivity++;
|
|
joystick[joystick_config].sensitivity %= 11;
|
|
}
|
|
break;
|
|
case 5:
|
|
if (joystick[joystick_config].analog)
|
|
{
|
|
joystick[joystick_config].threshold++;
|
|
joystick[joystick_config].threshold %= 11;
|
|
}
|
|
break;
|
|
case 16:
|
|
reset_joystick_assignments(joystick_config);
|
|
break;
|
|
case 17:
|
|
if (isNetworkGame || onePlayerAction)
|
|
{
|
|
curMenu = 11;
|
|
} else {
|
|
curMenu = 2;
|
|
}
|
|
break;
|
|
default:
|
|
if (joysticks == 0)
|
|
break;
|
|
|
|
// int temp = 254;
|
|
// JE_textShade(VGAScreen, 236, 38 + i * 8, value, temp / 16, temp % 16 - 8, DARKEN);
|
|
|
|
JE_rectangle(VGAScreen, 235, 21 + select * 8, 310, 30 + select * 8, 248);
|
|
|
|
Joystick_assignment temp;
|
|
if (detect_joystick_assignment(joystick_config, &temp))
|
|
{
|
|
// if the detected assignment was already set, unset it
|
|
for (uint i = 0; i < COUNTOF(*joystick->assignment); i++)
|
|
{
|
|
if (joystick_assignment_cmp(&temp, &joystick[joystick_config].assignment[select - 6][i]))
|
|
{
|
|
joystick[joystick_config].assignment[select - 6][i].type = NONE;
|
|
goto joystick_assign_done;
|
|
}
|
|
}
|
|
|
|
// if there is an empty assignment, set it
|
|
for (uint i = 0; i < COUNTOF(*joystick->assignment); i++)
|
|
{
|
|
if (joystick[joystick_config].assignment[select - 6][i].type == NONE)
|
|
{
|
|
joystick[joystick_config].assignment[select - 6][i] = temp;
|
|
goto joystick_assign_done;
|
|
}
|
|
}
|
|
|
|
// if no assignments are empty, shift them all forward and set the last one
|
|
for (uint i = 0; i < COUNTOF(*joystick->assignment); i++)
|
|
{
|
|
if (i == COUNTOF(*joystick->assignment) - 1)
|
|
joystick[joystick_config].assignment[select - 6][i] = temp;
|
|
else
|
|
joystick[joystick_config].assignment[select - 6][i] = joystick[joystick_config].assignment[select - 6][i + 1];
|
|
}
|
|
|
|
joystick_assign_done:
|
|
curSelect++;
|
|
|
|
poll_joysticks();
|
|
}
|
|
}
|
|
break;
|
|
|
|
case 13: //engage
|
|
switch (curSel[curMenu])
|
|
{
|
|
case 2:
|
|
mainLevel = mapSection[mapPNum-1];
|
|
jumpSection = true;
|
|
break;
|
|
case 3:
|
|
JE_doShipSpecs();
|
|
break;
|
|
case 4:
|
|
curMenu = 2;
|
|
break;
|
|
case 5:
|
|
if (JE_quitRequest())
|
|
{
|
|
if (isNetworkGame)
|
|
{
|
|
JE_tyrianHalt(0);
|
|
}
|
|
gameLoaded = true;
|
|
mainLevel = 0;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
|
|
old_items[0] = player[0].items;
|
|
}
|
|
|
|
void JE_drawShipSpecs( SDL_Surface * screen, SDL_Surface * temp_screen )
|
|
{
|
|
/* In this function we create our ship description image.
|
|
*
|
|
* We use a temp screen for convenience. Bad design maybe (Jason!),
|
|
* but it'll be okay (and the alternative is malloc/a large stack) */
|
|
|
|
int temp_x = 0, temp_y = 0, temp_index;
|
|
Uint8 *src, *dst;
|
|
|
|
|
|
//first, draw the text and other assorted flavoring.
|
|
JE_clr256(screen);
|
|
JE_drawLines(screen, true);
|
|
JE_drawLines(screen, false);
|
|
JE_rectangle(screen, 0, 0, 319, 199, 37);
|
|
JE_rectangle(screen, 1, 1, 318, 198, 35);
|
|
|
|
verticalHeight = 9;
|
|
JE_outText(screen, 10, 2, ships[player[0].items.ship].name, 12, 3);
|
|
JE_helpBox(screen, 100, 20, shipInfo[player[0].items.ship-1][0], 40);
|
|
JE_helpBox(screen, 100, 100, shipInfo[player[0].items.ship-1][1], 40);
|
|
verticalHeight = 7;
|
|
|
|
JE_outText(screen, JE_fontCenter(miscText[4], TINY_FONT), 190, miscText[4], 12, 2);
|
|
|
|
|
|
//now draw the green ship over that.
|
|
//This hardcoded stuff is for positioning our little ship graphic
|
|
if (player[0].items.ship > 90)
|
|
{
|
|
temp_index = 32;
|
|
}
|
|
else if (player[0].items.ship > 0)
|
|
{
|
|
temp_index = ships[player[0].items.ship].bigshipgraphic;
|
|
}
|
|
else
|
|
{
|
|
temp_index = ships[old_items[0].ship].bigshipgraphic;
|
|
}
|
|
|
|
switch (temp_index)
|
|
{
|
|
case 32:
|
|
temp_x = 35;
|
|
temp_y = 33;
|
|
break;
|
|
case 28:
|
|
temp_x = 31;
|
|
temp_y = 36;
|
|
break;
|
|
case 33:
|
|
temp_x = 31;
|
|
temp_y = 35;
|
|
break;
|
|
default:
|
|
assert(0);
|
|
}
|
|
temp_x -= 30;
|
|
|
|
|
|
//draw the ship into our temp buffer.
|
|
JE_clr256(temp_screen);
|
|
blit_sprite(temp_screen, temp_x, temp_y, OPTION_SHAPES, temp_index - 1); // ship illustration
|
|
|
|
/* But wait! Our ship is fully colored, not green!
|
|
* With a little work we could get the sprite dimensions and greenify
|
|
* the area it resides in. For now, let's just greenify the (almost
|
|
* entirely) black screen.
|
|
|
|
* We can't work in place. In fact we'll need to overlay the result
|
|
* To avoid our temp screen dependence this has been rewritten to
|
|
* only write one line at a time.*/
|
|
dst = screen->pixels;
|
|
src = temp_screen->pixels;
|
|
for (int y = 0; y < screen->h; y++)
|
|
{
|
|
for (int x = 0; x < screen->pitch; x++)
|
|
{
|
|
int avg = 0;
|
|
if (y > 0)
|
|
avg += *(src - screen->pitch) & 0x0f;
|
|
if (y < screen->h - 1)
|
|
avg += *(src + screen->pitch) & 0x0f;
|
|
if (x > 0)
|
|
avg += *(src - 1) & 0x0f;
|
|
if (x < screen->pitch - 1)
|
|
avg += *(src + 1) & 0x0f;
|
|
avg /= 4;
|
|
|
|
if ((*src & 0x0f) > avg)
|
|
{
|
|
*dst = (*src & 0x0f) | 0xc0;
|
|
//} else {
|
|
// *dst = 0;
|
|
}
|
|
|
|
src++;
|
|
dst++;
|
|
}
|
|
}
|
|
}
|
|
|
|
void JE_weaponSimUpdate( void )
|
|
{
|
|
char buf[32];
|
|
|
|
JE_weaponViewFrame();
|
|
|
|
if ( (curSel[1] == 3 && curSel[4] < menuChoices[4]) || (curSel[1] == 4 && curSel[4] < menuChoices[4] - 1) )
|
|
{
|
|
if (leftPower)
|
|
{
|
|
sprintf(buf, "%d", downgradeCost);
|
|
JE_outText(VGAScreen, 26, 137, buf, 1, 4);
|
|
}
|
|
else
|
|
{
|
|
blit_sprite(VGAScreenSeg, 24, 149, OPTION_SHAPES, 13); // downgrade disabled
|
|
}
|
|
|
|
if (rightPower)
|
|
{
|
|
if (!rightPowerAfford)
|
|
{
|
|
sprintf(buf, "%d", upgradeCost);
|
|
JE_outText(VGAScreen, 108, 137, buf, 7, 4);
|
|
blit_sprite(VGAScreenSeg, 119, 149, OPTION_SHAPES, 14); // upgrade disabled
|
|
}
|
|
else
|
|
{
|
|
sprintf(buf, "%d", upgradeCost);
|
|
JE_outText(VGAScreen, 108, 137, buf, 1, 4);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
blit_sprite(VGAScreenSeg, 119, 149, OPTION_SHAPES, 14); // upgrade disabled
|
|
}
|
|
|
|
temp = player[0].items.weapon[curSel[1]-3].power;
|
|
|
|
for (int x = 1; x <= temp; x++)
|
|
{
|
|
fill_rectangle_xy(VGAScreen, 39 + x * 6, 151, 39 + x * 6 + 4, 151, 251);
|
|
JE_pix(VGAScreen, 39 + x * 6, 151, 252);
|
|
fill_rectangle_xy(VGAScreen, 39 + x * 6, 152, 39 + x * 6 + 4, 164, 250);
|
|
fill_rectangle_xy(VGAScreen, 39 + x * 6, 165, 39 + x * 6 + 4, 165, 249);
|
|
}
|
|
|
|
sprintf(buf, "POWER: %d", temp);
|
|
JE_outText(VGAScreen, 58, 137, buf, 15, 4);
|
|
}
|
|
else
|
|
{
|
|
leftPower = false;
|
|
rightPower = false;
|
|
blit_sprite(VGAScreenSeg, 20, 146, OPTION_SHAPES, 17); // hide power level interface
|
|
}
|
|
|
|
JE_drawItem(1, player[0].items.ship, player[0].x - 5, player[0].y - 7);
|
|
}
|
|
|
|
void JE_weaponViewFrame( void )
|
|
{
|
|
fill_rectangle_xy(VGAScreen, 8, 8, 143, 182, 0);
|
|
|
|
/* JE: (* Port Configuration Display *)
|
|
(* drawportconfigbuttons;*/
|
|
|
|
update_and_draw_starfield(VGAScreen, 1);
|
|
|
|
mouseX = player[0].x;
|
|
mouseY = player[0].y;
|
|
|
|
// create shots in weapon simulator
|
|
for (uint i = 0; i < 2; ++i)
|
|
{
|
|
if (shotRepeat[i] > 0)
|
|
{
|
|
--shotRepeat[i];
|
|
}
|
|
else
|
|
{
|
|
const uint item = player[0].items.weapon[i].id,
|
|
item_power = player[0].items.weapon[i].power - 1,
|
|
item_mode = (i == REAR_WEAPON) ? player[0].weapon_mode - 1 : 0;
|
|
|
|
b = player_shot_create(item, i, player[0].x, player[0].y, mouseX, mouseY, weaponPort[item].op[item_mode][item_power], 1);
|
|
}
|
|
}
|
|
|
|
if (options[player[0].items.sidekick[LEFT_SIDEKICK]].wport > 0)
|
|
{
|
|
if (shotRepeat[SHOT_LEFT_SIDEKICK] > 0)
|
|
{
|
|
--shotRepeat[SHOT_LEFT_SIDEKICK];
|
|
}
|
|
else
|
|
{
|
|
const uint item = player[0].items.sidekick[LEFT_SIDEKICK];
|
|
const int x = player[0].sidekick[LEFT_SIDEKICK].x,
|
|
y = player[0].sidekick[LEFT_SIDEKICK].y;
|
|
|
|
b = player_shot_create(options[item].wport, SHOT_LEFT_SIDEKICK, x, y, mouseX, mouseY, options[item].wpnum, 1);
|
|
}
|
|
}
|
|
|
|
if (options[player[0].items.sidekick[RIGHT_SIDEKICK]].tr == 2)
|
|
{
|
|
player[0].sidekick[RIGHT_SIDEKICK].x = player[0].x;
|
|
player[0].sidekick[RIGHT_SIDEKICK].y = MAX(10, player[0].y - 20);
|
|
}
|
|
else
|
|
{
|
|
player[0].sidekick[RIGHT_SIDEKICK].x = 72 + 15;
|
|
player[0].sidekick[RIGHT_SIDEKICK].y = 120;
|
|
}
|
|
|
|
if (options[player[0].items.sidekick[RIGHT_SIDEKICK]].wport > 0)
|
|
{
|
|
if (shotRepeat[SHOT_RIGHT_SIDEKICK] > 0)
|
|
{
|
|
--shotRepeat[SHOT_RIGHT_SIDEKICK];
|
|
}
|
|
else
|
|
{
|
|
const uint item = player[0].items.sidekick[RIGHT_SIDEKICK];
|
|
const int x = player[0].sidekick[RIGHT_SIDEKICK].x,
|
|
y = player[0].sidekick[RIGHT_SIDEKICK].y;
|
|
|
|
b = player_shot_create(options[item].wport, SHOT_RIGHT_SIDEKICK, x, y, mouseX, mouseY, options[item].wpnum, 1);
|
|
}
|
|
}
|
|
|
|
simulate_player_shots();
|
|
|
|
blit_sprite(VGAScreenSeg, 0, 0, OPTION_SHAPES, 12); // upgrade interface
|
|
|
|
|
|
/*========================Power Bar=========================*/
|
|
|
|
power += powerAdd;
|
|
if (power > 900)
|
|
power = 900;
|
|
|
|
temp = power / 10;
|
|
|
|
for (temp = 147 - temp; temp <= 146; temp++)
|
|
{
|
|
temp2 = 113 + (146 - temp) / 9 + 2;
|
|
temp3 = (temp + 1) % 6;
|
|
if (temp3 == 1)
|
|
temp2 += 3;
|
|
else if (temp3 != 0)
|
|
temp2 += 2;
|
|
|
|
JE_pix(VGAScreen, 141, temp, temp2 - 3);
|
|
JE_pix(VGAScreen, 142, temp, temp2 - 3);
|
|
JE_pix(VGAScreen, 143, temp, temp2 - 2);
|
|
JE_pix(VGAScreen, 144, temp, temp2 - 1);
|
|
fill_rectangle_xy(VGAScreen, 145, temp, 149, temp, temp2);
|
|
|
|
if (temp2 - 3 < 112)
|
|
temp2++;
|
|
}
|
|
|
|
temp = 147 - (power / 10);
|
|
temp2 = 113 + (146 - temp) / 9 + 4;
|
|
|
|
JE_pix(VGAScreen, 141, temp - 1, temp2 - 1);
|
|
JE_pix(VGAScreen, 142, temp - 1, temp2 - 1);
|
|
JE_pix(VGAScreen, 143, temp - 1, temp2 - 1);
|
|
JE_pix(VGAScreen, 144, temp - 1, temp2 - 1);
|
|
|
|
fill_rectangle_xy(VGAScreen, 145, temp-1, 149, temp-1, temp2);
|
|
|
|
lastPower = temp;
|
|
|
|
//JE_waitFrameCount(); TODO: didn't do anything?
|
|
}
|
|
|