Fork the vendored engine into the playable replica
Engine changes vs the vendored upstream (full ledger in docs/upstream-patches.md): - Assets: replace the encrypted FILE000N.GLB archives with a catalog of pre-decrypted loose files (data/INDEX); GLB_SlotItems() drives mission-pack / registered-version detection; payloads never run the GLB cipher at runtime. - Platform: Linux/SDL2/ALSA only; Android, MSVC/MinGW, macOS packaging, bundled Windows SDL2 SDKs and the ENDOOM exit screen are gone; EXIT_Error now prints before exiting. - Rendering: decouple presentation from simulation -- sim stays at the original 70/3 Hz, frames render interpolated at display rate (player, map scroll, enemies, shots, bonuses, anims, shadows); menus keep 70 Hz pacing; vsync with a delay-guard fallback. - QoL: borderless window mode (Video/borderless), no menu cursor snapping onto default buttons. Fix four regressions from the render split: - Shield bars never redrew: RAP_ThinkStats latches g_oldshield each sim step before RAP_DisplayStats' dirty check could fire. Bars now draw unconditionally per rendered frame; g_oldsuper deleted, g_oldshield kept as sim-side damage-detection state only. - Dying ships despawned without exploding: the render loop never called ANIMS_DisplayHigh(); most air-death explosions register HIGH_AIR. Restored between the player and enemy shots, as upstream orders it. - Laser turret broke: reusing doneflag as a draw marker (it is hit/retire game state, and the turret retire path never frees its shot) hid the beam on hitting ticks and leaked one SHOTS pool slot per fire until no weapon could shoot. S_LINE tracers now carry an age counter: one Think pass, every render of their birth step, purged at the top of the next Think. - Muzzle flash was cleared per rendered frame, making it invisible at display refresh rates; now cleared once per simulation step.
This commit is contained in:
1 parent
f7c9b7a02d
commit
214789fe87
667 files changed
+1490
-279572
No files matched your search
+29
-6
@@ -253,6 +253,8 @@ ANIMS_StartAnim(
|
||||
cur->x = x - lib->xoff;
|
||||
cur->y = y - lib->yoff;
|
||||
cur->groundflag = lib->groundflag;
|
||||
cur->dx = cur->pdx = cur->x;
|
||||
cur->dy = cur->pdy = cur->y;
|
||||
}
|
||||
|
||||
/***************************************************************************
|
||||
@@ -275,6 +277,8 @@ ANIMS_StartGAnim(
|
||||
cur->x = x;
|
||||
cur->y = y;
|
||||
cur->groundflag = 0;
|
||||
cur->dx = cur->pdx = cur->x;
|
||||
cur->dy = cur->pdy = cur->y;
|
||||
}
|
||||
|
||||
/***************************************************************************
|
||||
@@ -301,6 +305,8 @@ ANIMS_StartEAnim(
|
||||
cur->x = x - lib->xoff;
|
||||
cur->y = y - lib->yoff;
|
||||
cur->groundflag = HIGH_AIR;
|
||||
cur->dx = cur->pdx = cur->x;
|
||||
cur->dy = cur->pdy = cur->y;
|
||||
}
|
||||
|
||||
/***************************************************************************
|
||||
@@ -325,6 +331,8 @@ ANIMS_StartAAnim(
|
||||
cur->x = x - lib->xoff;
|
||||
cur->y = y - lib->yoff;
|
||||
cur->groundflag = HIGH_AIR;
|
||||
cur->dx = cur->pdx = cur->x;
|
||||
cur->dy = cur->pdy = cur->y;
|
||||
}
|
||||
|
||||
/***************************************************************************
|
||||
@@ -342,6 +350,9 @@ ANIMS_Think(
|
||||
{
|
||||
lib = cur->lib;
|
||||
|
||||
cur->pdx = cur->dx;
|
||||
cur->pdy = cur->dy;
|
||||
|
||||
if (cur->curframe >= lib->numframes)
|
||||
{
|
||||
cur = ANIMS_Remove(cur);
|
||||
@@ -403,18 +414,22 @@ ANIMS_DisplayGround(
|
||||
{
|
||||
ANIMS *cur;
|
||||
char *pic;
|
||||
int idx, idy;
|
||||
|
||||
for (cur = first_anims.next; &last_anims != cur; cur = cur->next)
|
||||
{
|
||||
if (cur->groundflag)
|
||||
continue;
|
||||
|
||||
idx = GFX_InterpCoord(cur->dx, cur->pdx);
|
||||
idy = GFX_InterpCoord(cur->dy, cur->pdy);
|
||||
|
||||
pic = (char*)GLB_GetItem(cur->item);
|
||||
|
||||
if (cur->lib->transparent)
|
||||
GFX_ShadeShape(LIGHT, pic, cur->dx, cur->dy);
|
||||
GFX_ShadeShape(LIGHT, pic, idx, idy);
|
||||
else
|
||||
GFX_PutSprite(pic, cur->dx, cur->dy);
|
||||
GFX_PutSprite(pic, idx, idy);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -428,19 +443,23 @@ ANIMS_DisplaySky(
|
||||
{
|
||||
ANIMS *cur;
|
||||
char *pic;
|
||||
int idx, idy;
|
||||
|
||||
for (cur = first_anims.next; &last_anims != cur; cur = cur->next)
|
||||
{
|
||||
if (cur->groundflag != MID_AIR)
|
||||
continue;
|
||||
|
||||
idx = GFX_InterpCoord(cur->dx, cur->pdx);
|
||||
idy = GFX_InterpCoord(cur->dy, cur->pdy);
|
||||
|
||||
pic = (char*)GLB_GetItem(cur->item);
|
||||
|
||||
if (cur->lib->transparent)
|
||||
GFX_ShadeShape(LIGHT, pic, cur->dx, cur->dy);
|
||||
GFX_ShadeShape(LIGHT, pic, idx, idy);
|
||||
|
||||
else
|
||||
GFX_PutSprite(pic, cur->dx, cur->dy);
|
||||
GFX_PutSprite(pic, idx, idy);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -454,17 +473,21 @@ ANIMS_DisplayHigh(
|
||||
{
|
||||
ANIMS *cur;
|
||||
char *pic;
|
||||
int idx, idy;
|
||||
|
||||
for (cur = first_anims.next; &last_anims != cur; cur = cur->next)
|
||||
{
|
||||
if (cur->groundflag != HIGH_AIR)
|
||||
continue;
|
||||
|
||||
idx = GFX_InterpCoord(cur->dx, cur->pdx);
|
||||
idy = GFX_InterpCoord(cur->dy, cur->pdy);
|
||||
|
||||
pic = (char*)GLB_GetItem(cur->item);
|
||||
|
||||
if (cur->lib->transparent)
|
||||
GFX_ShadeShape(LIGHT, pic, cur->dx, cur->dy);
|
||||
GFX_ShadeShape(LIGHT, pic, idx, idy);
|
||||
else
|
||||
GFX_PutSprite(pic, cur->dx, cur->dy);
|
||||
GFX_PutSprite(pic, idx, idy);
|
||||
}
|
||||
}
|
||||
@@ -35,6 +35,8 @@ typedef struct ANIMS_S
|
||||
int item;
|
||||
int dx;
|
||||
int dy;
|
||||
int pdx; // PREV SIM DX (INTERP)
|
||||
int pdy; // PREV SIM DY (INTERP)
|
||||
int x;
|
||||
int y;
|
||||
int curframe;
|
||||
|
||||
+23
-3
@@ -162,6 +162,15 @@ BONUS_Add(
|
||||
cur->x = MAP_LEFT + x;
|
||||
cur->y = y;
|
||||
cur->pos = wrand() % 16;
|
||||
|
||||
cur->bx = cur->x - (BONUS_WIDTH / 2) + xpos[cur->pos];
|
||||
cur->by = cur->y - (BONUS_HEIGHT / 2) + ypos[cur->pos];
|
||||
cur->gx = cur->x - (glow_lx>>1) + xpos[cur->pos];
|
||||
cur->gy = cur->y - (glow_ly>>1) + ypos[cur->pos];
|
||||
cur->pbx = cur->bx;
|
||||
cur->pby = cur->by;
|
||||
cur->pgx = cur->gx;
|
||||
cur->pgy = cur->gy;
|
||||
}
|
||||
|
||||
/***************************************************************************
|
||||
@@ -183,6 +192,11 @@ BONUS_Think(
|
||||
|
||||
for (cur = first_bonus.next; &last_bonus != cur; cur = cur->next)
|
||||
{
|
||||
cur->pbx = cur->bx;
|
||||
cur->pby = cur->by;
|
||||
cur->pgx = cur->gx;
|
||||
cur->pgy = cur->gy;
|
||||
|
||||
cur->item = cur->lib->item + cur->curframe;
|
||||
|
||||
cur->bx = cur->x - (BONUS_WIDTH / 2) + xpos[cur->pos];
|
||||
@@ -264,16 +278,22 @@ BONUS_Display(
|
||||
)
|
||||
{
|
||||
BONUS *cur;
|
||||
int ibx, iby, igx, igy;
|
||||
|
||||
for (cur = first_bonus.next; &last_bonus != cur; cur = cur->next)
|
||||
{
|
||||
ibx = GFX_InterpCoord(cur->bx, cur->pbx);
|
||||
iby = GFX_InterpCoord(cur->by, cur->pby);
|
||||
igx = GFX_InterpCoord(cur->gx, cur->pgx);
|
||||
igy = GFX_InterpCoord(cur->gy, cur->pgy);
|
||||
|
||||
if (!cur->dflag)
|
||||
{
|
||||
GFX_PutSprite((char*)GLB_GetItem(cur->item), cur->bx, cur->by);
|
||||
GFX_ShadeShape(LIGHT, (char*)GLB_GetItem(glow[cur->curglow]), cur->gx, cur->gy);
|
||||
GFX_PutSprite((char*)GLB_GetItem(cur->item), ibx, iby);
|
||||
GFX_ShadeShape(LIGHT, (char*)GLB_GetItem(glow[cur->curglow]), igx, igy);
|
||||
}
|
||||
else
|
||||
GFX_PutSprite((char*)GLB_GetItem(FILE10f_N$_PIC), cur->bx, cur->by);
|
||||
GFX_PutSprite((char*)GLB_GetItem(FILE10f_N$_PIC), ibx, iby);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,6 +21,10 @@ typedef struct BONUS_S
|
||||
int by; // BONUS Y POSITION
|
||||
int gx; // GLOW X POSITION
|
||||
int gy; // GLOW Y POSITION
|
||||
int pbx; // PREV SIM BX (INTERP)
|
||||
int pby; // PREV SIM BY (INTERP)
|
||||
int pgx; // PREV SIM GX (INTERP)
|
||||
int pgy; // PREV SIM GY (INTERP)
|
||||
int pos; // POS IN CIRCLE
|
||||
int dflag; // DONEFLAG
|
||||
int countdown; // COUNTDOWN TO REMOVE
|
||||
|
||||
+9
-1
@@ -1,9 +1,17 @@
|
||||
#pragma once
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
static inline void EXIT_Error(const char *a1, ...)
|
||||
{
|
||||
exit(0);
|
||||
va_list args;
|
||||
|
||||
va_start(args, a1);
|
||||
vfprintf(stderr, a1, args);
|
||||
va_end(args);
|
||||
fputc('\n', stderr);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
static inline void EXIT_Clean(void)
|
||||
|
||||
+16
-5
@@ -713,6 +713,10 @@ void ENEMY_Think(
|
||||
{
|
||||
curlib = sprite->lib;
|
||||
|
||||
sprite->px = sprite->x;
|
||||
sprite->py = sprite->y;
|
||||
sprite->eframe ^= 1;
|
||||
|
||||
if (LE_LONG(curlib->num_frames) > 1)
|
||||
{
|
||||
sprite->item = LE_LONG(curlib->item) + sprite->curframe;
|
||||
@@ -1177,12 +1181,17 @@ ENEMY_DisplayGround(
|
||||
)
|
||||
{
|
||||
SPRITE_SHIP *spt;
|
||||
int ix, iy;
|
||||
|
||||
for (spt = first_enemy.next; &last_enemy != spt; spt = spt->next)
|
||||
{
|
||||
if (!spt->groundflag)
|
||||
continue;
|
||||
GFX_PutSprite((char*)GLB_GetItem(spt->item), spt->x, spt->y);
|
||||
|
||||
ix = GFX_InterpCoord(spt->x, spt->px);
|
||||
iy = GFX_InterpCoord(spt->y, spt->py);
|
||||
|
||||
GFX_PutSprite((char*)GLB_GetItem(spt->item), ix, iy);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1195,6 +1204,7 @@ ENEMY_DisplaySky(
|
||||
)
|
||||
{
|
||||
int i;
|
||||
int ix, iy;
|
||||
SPRITE_SHIP *spt;
|
||||
|
||||
for (spt = first_enemy.next; &last_enemy != spt; spt = spt->next)
|
||||
@@ -1202,14 +1212,15 @@ ENEMY_DisplaySky(
|
||||
if (spt->groundflag)
|
||||
continue;
|
||||
|
||||
GFX_PutSprite((char*)GLB_GetItem(spt->item), spt->x, spt->y);
|
||||
ix = GFX_InterpCoord(spt->x, spt->px);
|
||||
iy = GFX_InterpCoord(spt->y, spt->py);
|
||||
|
||||
GFX_PutSprite((char*)GLB_GetItem(spt->item), ix, iy);
|
||||
|
||||
for (i = 0; i < LE_LONG(spt->lib->numengs); i++)
|
||||
{
|
||||
FLAME_Up(spt->x + LE_SHORT(spt->lib->engx[i]), spt->y + LE_SHORT(spt->lib->engy[i]), LE_SHORT(spt->lib->englx[i]), spt->eframe);
|
||||
FLAME_Up(ix + LE_SHORT(spt->lib->engx[i]), iy + LE_SHORT(spt->lib->engy[i]), LE_SHORT(spt->lib->englx[i]), spt->eframe);
|
||||
}
|
||||
|
||||
spt->eframe ^= 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -77,6 +77,8 @@ typedef struct SPRITE_SHIP_S
|
||||
int sy; // START Y
|
||||
int x; // CENTER X POS;
|
||||
int y; // Y POS
|
||||
int px; // PREV SIM CENTER X (INTERP)
|
||||
int py; // PREV SIM Y POS (INTERP)
|
||||
int x2; // WIDTH
|
||||
int y2; // HEIGHT
|
||||
int width; // WIDTH
|
||||
|
||||
+17
-6
@@ -372,6 +372,11 @@ ESHOT_Shoot(
|
||||
InitMobj(&cur->move);
|
||||
MoveSobj(&cur->move, 1);
|
||||
|
||||
cur->x = cur->move.x;
|
||||
cur->y = cur->move.y;
|
||||
cur->px = cur->x;
|
||||
cur->py = cur->y;
|
||||
|
||||
if (cur->move.x < 0 || cur->move.x >= 320)
|
||||
cur->move.done = 1;
|
||||
|
||||
@@ -399,6 +404,9 @@ ESHOT_Think(
|
||||
{
|
||||
lib = shot->lib;
|
||||
|
||||
shot->px = shot->x;
|
||||
shot->py = shot->y;
|
||||
|
||||
shot->pic = lib->pic[shot->curframe];
|
||||
|
||||
shot->curframe++;
|
||||
@@ -512,17 +520,20 @@ ESHOT_Display(
|
||||
)
|
||||
{
|
||||
ESHOT *shot;
|
||||
int loop, y;
|
||||
int loop, y, ix, iy;
|
||||
GFX_PIC *h;
|
||||
|
||||
for (shot = first_eshot.next; shot !=&last_eshot; shot = shot->next)
|
||||
{
|
||||
ix = GFX_InterpCoord(shot->x, shot->px);
|
||||
iy = GFX_InterpCoord(shot->y, shot->py);
|
||||
|
||||
if (shot->type == ES_LASER)
|
||||
{
|
||||
for (loop = shot->y; loop < shot->move.y2; loop += 3)
|
||||
GFX_PutSprite(shot->pic, shot->x, loop);
|
||||
for (loop = iy; loop < shot->move.y2; loop += 3)
|
||||
GFX_PutSprite(shot->pic, ix, loop);
|
||||
|
||||
GFX_PutSprite(elaspow[shot->curframe - 1], shot->x, shot->y);
|
||||
GFX_PutSprite(elaspow[shot->curframe - 1], ix, iy);
|
||||
|
||||
h = (GFX_PIC*)lashit[shot->curframe - 1];
|
||||
|
||||
@@ -530,10 +541,10 @@ ESHOT_Display(
|
||||
|
||||
if (y > 0 && y < 200)
|
||||
{
|
||||
GFX_PutSprite((char*)h, shot->x - (LE_LONG(h->width) >> 2), y);
|
||||
GFX_PutSprite((char*)h, ix - (LE_LONG(h->width) >> 2), y);
|
||||
}
|
||||
}
|
||||
else
|
||||
GFX_PutSprite(shot->pic, shot->x, shot->y);
|
||||
GFX_PutSprite(shot->pic, ix, iy);
|
||||
}
|
||||
}
|
||||
@@ -36,6 +36,8 @@ typedef struct ESHOT_S
|
||||
int curframe; // CURRENT ANIM FRAME
|
||||
int x; // CUR SHOT CENTER X
|
||||
int y; // CUR SHOT CENTER Y
|
||||
int px; // PREV SIM X (INTERP)
|
||||
int py; // PREV SIM Y (INTERP)
|
||||
MOVEOBJ move; // MOVE STUFF
|
||||
int doneflag; // SHOT DONE = TRUE
|
||||
ESHOT_LIB *lib; // POINTER TO LIB
|
||||
|
||||
@@ -112,6 +112,38 @@ GFX_GetFrameCount(
|
||||
return framecount;
|
||||
}
|
||||
|
||||
/***************************************************************************
|
||||
GFX_SetInterp () - Sets the interpolation fraction (num/den, 0 <= num <=
|
||||
den) used by GFX_InterpCoord() for this rendered frame.
|
||||
***************************************************************************/
|
||||
static int gfx_interp_num = 1, gfx_interp_den = 1;
|
||||
|
||||
void
|
||||
GFX_SetInterp(
|
||||
int num, // INPUT : interpolated fraction numerator
|
||||
int den // INPUT : interpolated fraction denominator
|
||||
)
|
||||
{
|
||||
if (den > 0 && num >= 0)
|
||||
{
|
||||
gfx_interp_num = num;
|
||||
gfx_interp_den = den;
|
||||
}
|
||||
}
|
||||
|
||||
/***************************************************************************
|
||||
GFX_InterpCoord () - Interpolates between previous and current simulation
|
||||
position: prev + (cur - prev) * num/den.
|
||||
***************************************************************************/
|
||||
int
|
||||
GFX_InterpCoord(
|
||||
int cur, // INPUT : current sim position
|
||||
int prev // INPUT : previous sim position
|
||||
)
|
||||
{
|
||||
return prev + (int)(((long long)(cur - prev) * gfx_interp_num) / gfx_interp_den);
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
GFX_ClipLines ()
|
||||
*************************************************************************/
|
||||
|
||||
@@ -81,6 +81,8 @@ void GFX_UpdateTimer(void);
|
||||
void GFX_InitSystem(void);
|
||||
void GFX_InitVideo(char *curpal);
|
||||
int GFX_GetFrameCount(void);
|
||||
void GFX_SetInterp(int num, int den);
|
||||
int GFX_InterpCoord(int cur, int prev);
|
||||
int GFX_ClipLines(char **image, int *x, int *y, int *lx, int *ly);
|
||||
void GFX_SetPalette(char *curpal, int startpal);
|
||||
void GFX_FadeOut(int red, int green, int blue, int speed);
|
||||
|
||||
+136
-199
@@ -5,6 +5,7 @@
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/stat.h>
|
||||
#include "common.h"
|
||||
#include "glbapi.h"
|
||||
#include "vmemapi.h"
|
||||
@@ -31,13 +32,10 @@ char* strupr(char* s)
|
||||
#define PATH_MAX MAX_PATH
|
||||
#endif // _MSC_VER
|
||||
|
||||
#define _SCOTTGAME
|
||||
|
||||
static const char* serial = "32768GLB";
|
||||
static char exePath[PATH_MAX];
|
||||
static int num_glbs;
|
||||
static KEYFILE g_key;
|
||||
static char prefix[5] = "FILE";
|
||||
static bool fVmem = 0;
|
||||
|
||||
/*
|
||||
@@ -55,11 +53,8 @@ typedef struct
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char filepath[PATH_MAX];
|
||||
ITEMINFO* item;
|
||||
int items;
|
||||
FILE *handle;
|
||||
const char *permissions;
|
||||
}FILEDESC;
|
||||
|
||||
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
|
||||
@@ -153,207 +148,155 @@ GLB_DeCrypt(
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------
|
||||
GLB_FindFile() - Finds a file, opens it, and stores it's path
|
||||
Data catalog: INDEX maps asset ids to files in category dirs
|
||||
(music/, sprites/, ... — see tools/glbextract.py). Ids are engine
|
||||
handles, (archive slot << 16) | item index, sorted ascending.
|
||||
------------------------------------------------------------------------*/
|
||||
static FILE*
|
||||
GLB_FindFile(
|
||||
int return_on_failure, // INPUT : Don't bomb if file not open
|
||||
int filenum, // INPUT : file number
|
||||
const char *permissions // INPUT : file access permissions
|
||||
)
|
||||
typedef struct
|
||||
{
|
||||
const char* routine = "GLB_FindFile";
|
||||
char filename[PATH_MAX];
|
||||
char filenamelc[PATH_MAX];
|
||||
FILE *handle;
|
||||
FILEDESC* fd;
|
||||
|
||||
/*
|
||||
* Scott, the ASSERT function is a macro that will be compiled-out when
|
||||
* not debugging ( DEBUG not defined ), otherwise it calls EXIT_Assert
|
||||
* if the expression is false ( which bails out of your program and displays
|
||||
* the expression, file & line number of the assertion ). This is a standard
|
||||
* way of checking variables for correct boundries during development, and
|
||||
* makes it easy to remove extra logic for doing so by recompiling without
|
||||
* DEBUG defined.
|
||||
*/
|
||||
ASSERT(filenum >= 0 && filenum < MAX_GLB_FILES);
|
||||
|
||||
/*
|
||||
* create a file name and attempt to open it local first, then if it
|
||||
* fails use the exe path and try again.
|
||||
*/
|
||||
sprintf(filenamelc, "%s%04u.glb", "file", filenum);
|
||||
if (!access(filenamelc, 0))
|
||||
strcpy(filename, filenamelc);
|
||||
else
|
||||
sprintf(filename, "%s%04u.GLB", prefix, filenum);
|
||||
|
||||
if ((handle = fopen(filename, permissions)) == NULL)
|
||||
{
|
||||
sprintf(filenamelc, "%s%s%04u.glb", exePath, "file", filenum);
|
||||
if (!access(filenamelc, 0))
|
||||
strcpy(filename, filenamelc);
|
||||
else
|
||||
sprintf(filename, "%s%s%04u.GLB", exePath, prefix, filenum);
|
||||
|
||||
if ((handle = fopen(filename, permissions)) == NULL)
|
||||
{
|
||||
if (return_on_failure)
|
||||
return NULL;
|
||||
uint32_t id;
|
||||
uint32_t size;
|
||||
char path[64];
|
||||
}CATENTRY;
|
||||
|
||||
sprintf(filename, "%s%04u.GLB", prefix, filenum);
|
||||
EXIT_Error("GLB_FindFile: %s, Error #%d,%s",
|
||||
filename, errno, strerror(errno));
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Keep file handle
|
||||
*/
|
||||
fd = &filedesc[filenum];
|
||||
|
||||
strcpy(fd->filepath, filename);
|
||||
fd->permissions = permissions;
|
||||
fd->handle = handle;
|
||||
|
||||
return handle;
|
||||
}
|
||||
static CATENTRY* catalog;
|
||||
static int catalog_n;
|
||||
static char dataRoot[PATH_MAX]; // "" when INDEX sits in the cwd
|
||||
|
||||
/*------------------------------------------------------------------------
|
||||
GLB_OpenFile() - Opens & Caches file handle
|
||||
------------------------------------------------------------------------*/
|
||||
static FILE*
|
||||
GLB_OpenFile(
|
||||
int return_on_failure, // INPUT : Don't bomb if file not open
|
||||
int filenum, // INPUT : file number
|
||||
const char *permissions // INPUT : file access permissions
|
||||
)
|
||||
{
|
||||
FILEDESC* fd;
|
||||
|
||||
ASSERT(filenum >= 0 && filenum < MAX_GLB_FILES);
|
||||
|
||||
fd = &filedesc[filenum];
|
||||
|
||||
if (fd->handle == 0)
|
||||
return GLB_FindFile(return_on_failure, filenum, permissions);
|
||||
else if (fd->permissions != permissions)
|
||||
{
|
||||
fclose(fd->handle);
|
||||
|
||||
if ((fd->handle = fopen(fd->filepath, permissions)) == NULL)
|
||||
{
|
||||
if (return_on_failure)
|
||||
return NULL;
|
||||
|
||||
EXIT_Error("GLB_OpenFile: %s, Error #%d,%s",
|
||||
fd->filepath, errno, strerror(errno));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
fseek(fd->handle, 0L, SEEK_SET);
|
||||
}
|
||||
|
||||
return fd->handle;
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------
|
||||
GLB_CloseFiles() - Closes all cached files.
|
||||
GLB_LoadCatalog() - Parses INDEX (current directory first, then
|
||||
exePath). Missing INDEX leaves the catalog empty; every slot then
|
||||
reports zero items, which callers treat as "no data".
|
||||
------------------------------------------------------------------------*/
|
||||
static void
|
||||
GLB_CloseFiles(
|
||||
GLB_LoadCatalog(
|
||||
void
|
||||
)
|
||||
{
|
||||
int j;
|
||||
char path[PATH_MAX];
|
||||
FILE *handle;
|
||||
|
||||
for (j = 0; j < MAX_GLB_FILES; j++)
|
||||
if (catalog != NULL)
|
||||
return;
|
||||
|
||||
strcpy(dataRoot, "");
|
||||
|
||||
handle = fopen("INDEX", "rb");
|
||||
if (handle == NULL)
|
||||
{
|
||||
if (filedesc[j].handle)
|
||||
{
|
||||
fclose(filedesc[j].handle);
|
||||
filedesc[j].handle = 0;
|
||||
}
|
||||
strcpy(dataRoot, exePath);
|
||||
sprintf(path, "%sINDEX", exePath);
|
||||
handle = fopen(path, "rb");
|
||||
}
|
||||
if (handle == NULL)
|
||||
return;
|
||||
|
||||
while (true)
|
||||
{
|
||||
CATENTRY ce;
|
||||
|
||||
if (fscanf(handle, "%x %u %63s", &ce.id, &ce.size, ce.path) != 3)
|
||||
break;
|
||||
|
||||
catalog = (CATENTRY*)realloc(catalog, (catalog_n + 1) * sizeof(CATENTRY));
|
||||
if (catalog == NULL)
|
||||
EXIT_Error("GLB_LoadCatalog: memory");
|
||||
|
||||
catalog[catalog_n++] = ce;
|
||||
}
|
||||
|
||||
fclose(handle);
|
||||
}
|
||||
|
||||
/***************************************************************************
|
||||
GLB_SlotItems() - Returns number of catalog items in one archive slot
|
||||
***************************************************************************/
|
||||
int
|
||||
GLB_SlotItems(
|
||||
int filenum // INPUT : archive slot number
|
||||
)
|
||||
{
|
||||
int i;
|
||||
int count;
|
||||
|
||||
GLB_LoadCatalog();
|
||||
|
||||
count = 0;
|
||||
for (i = 0; i < catalog_n; i++)
|
||||
{
|
||||
if (catalog[i].id >> 16 == (uint32_t)filenum)
|
||||
count++;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------
|
||||
GLB_NumItems() - Returns number of items in a .GLB file
|
||||
GLB_CatFind() - Binary search of the catalog by asset id.
|
||||
------------------------------------------------------------------------*/
|
||||
static int
|
||||
GLB_NumItems(
|
||||
int filenum
|
||||
static CATENTRY*
|
||||
GLB_CatFind(
|
||||
uint32_t id
|
||||
)
|
||||
{
|
||||
KEYFILE key;
|
||||
FILE *handle;
|
||||
int lo;
|
||||
int hi;
|
||||
|
||||
ASSERT(filenum >= 0 && filenum < num_glbs);
|
||||
lo = 0;
|
||||
hi = catalog_n - 1;
|
||||
|
||||
handle = GLB_OpenFile(1, filenum, "rb");
|
||||
|
||||
if (handle == NULL)
|
||||
return 0;
|
||||
|
||||
fseek(handle, 0L, SEEK_SET);
|
||||
|
||||
if (!fread(&key, sizeof(KEYFILE), 1, handle))
|
||||
while (lo <= hi)
|
||||
{
|
||||
EXIT_Error("GLB_NumItems: Read failed!");
|
||||
int mid = (lo + hi) / 2;
|
||||
|
||||
if (catalog[mid].id == id)
|
||||
return &catalog[mid];
|
||||
else if (catalog[mid].id < id)
|
||||
lo = mid + 1;
|
||||
else
|
||||
hi = mid - 1;
|
||||
}
|
||||
|
||||
#ifdef _SCOTTGAME
|
||||
GLB_DeCrypt(serial, (uint8_t*)&key, sizeof(KEYFILE));
|
||||
#endif
|
||||
|
||||
return ((int)LE_ULONG(key.offset));
|
||||
EXIT_Error("GLB_CatFind: id %x not in catalog", id);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------------------
|
||||
GLB_LoadIDT() Loads a item descriptor table from a GLB file.
|
||||
GLB_FillSlot() - Fills one slot's item descriptors from the catalog.
|
||||
Extracted payloads are stored pre-decrypted, so no item stays flagged
|
||||
ITF_ENCODED.
|
||||
--------------------------------------------------------------------------*/
|
||||
static void
|
||||
GLB_LoadIDT(
|
||||
FILEDESC* fd // INPUT: file to load
|
||||
GLB_FillSlot(
|
||||
FILEDESC* fd, // INPUT: slot descriptor to fill
|
||||
int filenum // INPUT : archive slot number
|
||||
)
|
||||
{
|
||||
FILE *handle;
|
||||
int j;
|
||||
int k;
|
||||
int n;
|
||||
KEYFILE key[10];
|
||||
ITEMINFO* ii;
|
||||
int i;
|
||||
int n;
|
||||
|
||||
handle = fd->handle;
|
||||
n = 0;
|
||||
ii = fd->item;
|
||||
|
||||
fseek(handle, sizeof(KEYFILE), SEEK_SET);
|
||||
|
||||
for (j = 0; j < fd->items; )
|
||||
for (i = 0; i < catalog_n && n < fd->items; i++)
|
||||
{
|
||||
k = fd->items - j;
|
||||
|
||||
if (k > ASIZE(key))
|
||||
k = ASIZE(key);
|
||||
CATENTRY* ce = &catalog[i];
|
||||
const char* base;
|
||||
|
||||
fread(key, sizeof(KEYFILE), k, handle);
|
||||
|
||||
for (n = 0; n < k; n++)
|
||||
{
|
||||
#ifdef _SCOTTGAME
|
||||
GLB_DeCrypt(serial, (void*)&key[n], sizeof(KEYFILE));
|
||||
#endif
|
||||
if (LE_ULONG(key[n].opt) == GLB_ENCODED)
|
||||
ii->flags |= ITF_ENCODED;
|
||||
if (ce->id >> 16 != (uint32_t)filenum)
|
||||
continue;
|
||||
|
||||
ii->size = LE_ULONG(key[n].filesize);
|
||||
ii->offset = LE_ULONG(key[n].offset);
|
||||
memcpy(ii->name, key[n].name, sizeof(ii->name));
|
||||
ii++;
|
||||
}
|
||||
j += k;
|
||||
base = strrchr(ce->path, '/');
|
||||
base = (base != NULL) ? base + 1 : ce->path;
|
||||
|
||||
if (strlen(base) >= sizeof(ii->name))
|
||||
EXIT_Error("GLB_FillSlot: item name too long: %s", base);
|
||||
|
||||
strcpy(ii->name, base);
|
||||
ii->size = ce->size;
|
||||
ii++;
|
||||
n++;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -396,39 +339,32 @@ GLB_InitSystem(
|
||||
num_glbs = innum;
|
||||
ASSERT(num_glbs >= 1 && num_glbs <= MAX_GLB_FILES);
|
||||
|
||||
if (iprefix)
|
||||
{
|
||||
ASSERT(strlen(iprefix) < sizeof(prefix) - 1);
|
||||
|
||||
strcpy(prefix, iprefix);
|
||||
strupr(prefix);
|
||||
}
|
||||
(void)iprefix; // archive-name prefixes are obsolete with the catalog
|
||||
memset(filedesc, 0, sizeof(filedesc));
|
||||
|
||||
/*
|
||||
* Next, read in header of each file and allocate cache
|
||||
* Parse the catalog, then set up one descriptor per non-empty slot
|
||||
*/
|
||||
GLB_LoadCatalog();
|
||||
|
||||
opened = 0;
|
||||
for (filenum = 0; filenum < num_glbs; filenum++)
|
||||
{
|
||||
fd = &filedesc[filenum];
|
||||
|
||||
if ((num = GLB_NumItems(filenum)) != 0)
|
||||
|
||||
if ((num = GLB_SlotItems(filenum)) != 0)
|
||||
{
|
||||
fd->items = num;
|
||||
|
||||
|
||||
/*
|
||||
* Note: calloc zeros out all memory that it allocates
|
||||
*/
|
||||
fd->item = (ITEMINFO*)calloc(num, sizeof(ITEMINFO));
|
||||
|
||||
|
||||
if (fd->item == NULL)
|
||||
EXIT_Error("GLB_NumItems: memory ( init )");
|
||||
|
||||
/*
|
||||
* Load Item Descriptor Table for file
|
||||
*/
|
||||
GLB_LoadIDT(fd);
|
||||
EXIT_Error("GLB_InitSystem: memory ( init )");
|
||||
|
||||
GLB_FillSlot(fd, filenum);
|
||||
opened++;
|
||||
}
|
||||
}
|
||||
@@ -446,14 +382,13 @@ GLB_Load(
|
||||
int itemnum // INPUT: item in file number
|
||||
)
|
||||
{
|
||||
FILE *handle;
|
||||
ITEMINFO* ii;
|
||||
char path[PATH_MAX];
|
||||
FILE *f;
|
||||
|
||||
ASSERT(filenum >= 0 && filenum < num_glbs);
|
||||
|
||||
handle = filedesc[filenum].handle;
|
||||
|
||||
if (handle == 0)
|
||||
if (filedesc[filenum].item == NULL)
|
||||
return 0;
|
||||
|
||||
ASSERT(itemnum < (WORD)filedesc[filenum].items);
|
||||
@@ -467,14 +402,16 @@ GLB_Load(
|
||||
memcpy(inmem, ii->vm_mem.obj, ii->size);
|
||||
else
|
||||
{
|
||||
fseek(handle, ii->offset, SEEK_SET);
|
||||
fread(inmem, ii->size, 1, handle);
|
||||
#ifdef _SCOTTGAME
|
||||
if (ii->flags & ITF_ENCODED)
|
||||
{
|
||||
GLB_DeCrypt(serial, inmem, ii->size);
|
||||
}
|
||||
#endif
|
||||
CATENTRY* ce = GLB_CatFind(((uint32_t)filenum << 16) | (uint32_t)itemnum);
|
||||
char path[PATH_MAX];
|
||||
|
||||
sprintf(path, "%s%s", dataRoot, ce->path);
|
||||
|
||||
f = fopen(path, "rb");
|
||||
if (f == NULL || fread(inmem, ii->size, 1, f) != 1)
|
||||
EXIT_Error("GLB_Load: read failed on %s", path);
|
||||
|
||||
fclose(f);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -23,6 +23,7 @@ typedef struct
|
||||
|
||||
void GLB_UseVM(void);
|
||||
int GLB_InitSystem(const char *exepath, int innum, const char *iprefix);
|
||||
int GLB_SlotItems(int filenum);
|
||||
char *GLB_LockItem(int handle);
|
||||
void GLB_UnlockItem(int handle);
|
||||
char *GLB_GetItem(int handle);
|
||||
|
||||
@@ -1,86 +0,0 @@
|
||||
//
|
||||
// Copyright(C) 2005-2014 Simon Howard
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
// DESCRIPTION:
|
||||
// Exit text-mode ENDOOM screen.
|
||||
//
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "rap.h"
|
||||
#include "i_lastscr.h"
|
||||
#include "textscreen.h"
|
||||
#include "i_video.h"
|
||||
#include "joyapi.h"
|
||||
#include "kbdapi.h"
|
||||
#include "ptrapi.h"
|
||||
#include "imsapi.h"
|
||||
|
||||
#define LASTSCR_W 80
|
||||
#define LASTSCR_H 25
|
||||
|
||||
|
||||
//
|
||||
// Displays the text mode ending screen after the game quits
|
||||
//
|
||||
void I_LASTSCR(char* mem)
|
||||
{
|
||||
unsigned char* screendata;
|
||||
int y;
|
||||
int indent;
|
||||
|
||||
TXT_Fullscreen(txt_fullscreen);
|
||||
|
||||
// Set up text mode screen
|
||||
|
||||
TXT_Init();
|
||||
|
||||
TXT_SetWindowTitle("Raptor");
|
||||
// SDL2-TODO I_InitWindowTitle();
|
||||
// SDL2-TODO I_InitWindowIcon();
|
||||
|
||||
// Write the data to the screen memory
|
||||
|
||||
screendata = TXT_GetScreenData();
|
||||
|
||||
indent = (LASTSCR_W - TXT_SCREEN_W) / 2;
|
||||
|
||||
for (y = 0; y < TXT_SCREEN_H; ++y)
|
||||
{
|
||||
memcpy(screendata + (y * TXT_SCREEN_W * 2),
|
||||
mem + (y * LASTSCR_W + indent) * 2,
|
||||
TXT_SCREEN_W * 2);
|
||||
}
|
||||
|
||||
// Wait for a keypress
|
||||
|
||||
IMS_StartAck();
|
||||
I_Settextmode(true);
|
||||
|
||||
while (true)
|
||||
{
|
||||
TXT_UpdateScreen();
|
||||
I_GetEvent();
|
||||
|
||||
if (joy_ack || kbd_ack || mouse_b1_ack || mouse_b2_ack || mouse_b3_ack)
|
||||
break;
|
||||
|
||||
TXT_Sleep(0);
|
||||
}
|
||||
|
||||
// Shut down text mode screen
|
||||
|
||||
TXT_Shutdown();
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
void I_LASTSCR(char* mem);
|
||||
+89
-13
@@ -84,6 +84,10 @@ static bool initialized = false;
|
||||
static bool nomouse = false;
|
||||
int usemouse = 1;
|
||||
|
||||
// Set when the SDL renderer was created with present-vs-sync.
|
||||
|
||||
static int vsync_active = 0;
|
||||
|
||||
// Save screenshots in PNG format.
|
||||
|
||||
// int png_screenshots = 0;
|
||||
@@ -118,6 +122,11 @@ static int max_scaling_buffer_pixels = 16000000;
|
||||
// int fullscreen = true;
|
||||
int fullscreen; //Defined in VIDEO_LoadPrefs to read config from setup.ini
|
||||
|
||||
|
||||
// Borderless window: cover the desktop without decorations (compositor-
|
||||
// friendly, instant alt-tab). Read from Video/borderless in SETUP.INI.
|
||||
|
||||
int borderless = 0;
|
||||
int txt_fullscreen;
|
||||
|
||||
// Aspect ratio correction mode
|
||||
@@ -208,6 +217,7 @@ void VIDEO_LoadPrefs(void)
|
||||
fullscreen = INI_GetPreferenceLong("Video", "fullscreen", 0);
|
||||
aspect_ratio_correct = INI_GetPreferenceLong("Video", "aspect_ratio_correct", 1);
|
||||
txt_fullscreen = INI_GetPreferenceLong("Video", "txt_fullscreen", 0);
|
||||
borderless = INI_GetPreferenceLong("Video", "borderless", 0);
|
||||
}
|
||||
|
||||
static bool MouseShouldBeGrabbed()
|
||||
@@ -386,6 +396,8 @@ static bool ToggleFullScreenKeyShortcut(SDL_Keysym *sym)
|
||||
sym->scancode == SDL_SCANCODE_KP_ENTER) && (sym->mod & flags) != 0;
|
||||
}
|
||||
|
||||
static void I_GetWindowPosition(int *x, int *y, int w, int h);
|
||||
|
||||
static void I_ToggleFullScreen(void)
|
||||
{
|
||||
unsigned int flags = 0;
|
||||
@@ -398,6 +410,38 @@ static void I_ToggleFullScreen(void)
|
||||
return;
|
||||
}
|
||||
|
||||
if (borderless)
|
||||
{
|
||||
// Cycle between the borderless desktop window and a normal
|
||||
// decorated window.
|
||||
int x, y, w, h;
|
||||
|
||||
fullscreen = !fullscreen;
|
||||
|
||||
SDL_SetWindowBordered(screen, (SDL_bool) !fullscreen);
|
||||
|
||||
if (fullscreen)
|
||||
{
|
||||
SDL_DisplayMode borderless_mode;
|
||||
|
||||
SDL_SetWindowPosition(screen, 0, 0);
|
||||
|
||||
if (SDL_GetDesktopDisplayMode(video_display, &borderless_mode) == 0)
|
||||
{
|
||||
SDL_SetWindowSize(screen, borderless_mode.w, borderless_mode.h);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
AdjustWindowSize();
|
||||
I_GetWindowPosition(&x, &y, window_width, window_height);
|
||||
SDL_SetWindowSize(screen, window_width, window_height);
|
||||
SDL_SetWindowPosition(screen, x, y);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
fullscreen = !fullscreen;
|
||||
|
||||
if (fullscreen)
|
||||
@@ -740,7 +784,8 @@ void I_FinishUpdate (void)
|
||||
// When the window is resized (we're not in fullscreen mode),
|
||||
// save the new window size.
|
||||
flags = SDL_GetWindowFlags(screen);
|
||||
if ((flags & SDL_WINDOW_FULLSCREEN_DESKTOP) == 0)
|
||||
if ((flags & SDL_WINDOW_FULLSCREEN_DESKTOP) == 0 &&
|
||||
!(borderless && fullscreen))
|
||||
{
|
||||
SDL_GetWindowSize(screen, &window_width, &window_height);
|
||||
|
||||
@@ -1233,19 +1278,32 @@ static void SetVideoMode(void)
|
||||
window_flags |= SDL_WINDOW_FULLSCREEN;
|
||||
}
|
||||
}
|
||||
|
||||
// Running without window decorations is potentially useful if you're
|
||||
// playing in three window mode and want to line up three game windows
|
||||
// next to each other on a single desktop.
|
||||
// Deliberately not documented because I'm not sure how useful this is yet.
|
||||
#if 0
|
||||
if (M_ParmExists("-borderless"))
|
||||
else if (borderless)
|
||||
{
|
||||
// Cover the current desktop without decorations: no mode switch,
|
||||
// the desktop resolution is used as-is.
|
||||
SDL_DisplayMode borderless_mode;
|
||||
|
||||
if (SDL_GetDesktopDisplayMode(video_display, &borderless_mode) == 0)
|
||||
{
|
||||
w = borderless_mode.w;
|
||||
h = borderless_mode.h;
|
||||
}
|
||||
|
||||
window_flags |= SDL_WINDOW_BORDERLESS;
|
||||
}
|
||||
#endif
|
||||
|
||||
I_GetWindowPosition(&x, &y, w, h);
|
||||
|
||||
if (borderless)
|
||||
{
|
||||
// A borderless desktop window sits at the origin.
|
||||
x = 0;
|
||||
y = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
I_GetWindowPosition(&x, &y, w, h);
|
||||
}
|
||||
|
||||
// Create window and renderer contexts. We set the window title
|
||||
// later anyway and leave the window position "undefined". If
|
||||
@@ -1280,10 +1338,11 @@ static void SetVideoMode(void)
|
||||
video_display, SDL_GetError());
|
||||
}
|
||||
|
||||
// Turn on vsync if we aren't in a -timedemo
|
||||
if (/*!singletics && */mode.refresh_rate > 0)
|
||||
// Turn on vsync: the game loop paces simulation on a wall-clock
|
||||
// accumulator, presentation is throttled by the display.
|
||||
if (mode.refresh_rate > 0)
|
||||
{
|
||||
// renderer_flags |= SDL_RENDERER_PRESENTVSYNC;
|
||||
renderer_flags |= SDL_RENDERER_PRESENTVSYNC;
|
||||
}
|
||||
|
||||
if (force_software_renderer)
|
||||
@@ -1324,6 +1383,15 @@ static void SetVideoMode(void)
|
||||
EXIT_Error("Error creating renderer for screen window: %s",
|
||||
SDL_GetError());
|
||||
}
|
||||
|
||||
// Remember whether the created renderer actually vsyncs; the game loop
|
||||
// uses this to decide between vsync pacing and its own delay guard.
|
||||
{
|
||||
SDL_RendererInfo rinfo;
|
||||
|
||||
vsync_active = (SDL_GetRendererInfo(renderer, &rinfo) == 0 &&
|
||||
(rinfo.flags & SDL_RENDERER_PRESENTVSYNC) != 0);
|
||||
}
|
||||
|
||||
// Important: Set the "logical size" of the rendering context. At the same
|
||||
// time this also defines the aspect ratio that is preserved while scaling
|
||||
@@ -1581,6 +1649,14 @@ void I_SetMousePos(int x, int y)
|
||||
SDL_WarpMouseInWindow(screen, x, y);
|
||||
}
|
||||
|
||||
/***************************************************************************
|
||||
I_VsyncActive () - TRUE when the renderer presents with vsync
|
||||
***************************************************************************/
|
||||
int I_VsyncActive(void)
|
||||
{
|
||||
return vsync_active;
|
||||
}
|
||||
|
||||
void closewindow(void)
|
||||
{
|
||||
SDL_DestroyWindow(screen);
|
||||
|
||||
@@ -52,4 +52,5 @@ void I_SetGrabMouseCallback(grabmouse_callback_t func);
|
||||
void VIDEO_LoadPrefs(void);
|
||||
void closewindow(void);
|
||||
bool I_GetNeedResize(bool setonlypos);
|
||||
int I_VsyncActive(void);
|
||||
void I_Settextmode(bool flag);
|
||||
@@ -977,36 +977,6 @@ RAP_InitLoadSave(
|
||||
EXIT_Error("Couldn't find home directory");
|
||||
}
|
||||
|
||||
#if __ANDROID__
|
||||
for(int i = 0; i < 2; i++)
|
||||
{
|
||||
char src[PATH_MAX];
|
||||
char srclc[PATH_MAX];
|
||||
char dst[PATH_MAX];
|
||||
sprintf(src,"FILE%04u.GLB", i);
|
||||
sprintf(srclc, "file%04u.glb", i);
|
||||
sprintf(dst, "%sFILE%04u.GLB", cdpath, i);
|
||||
if (!RAP_CheckFileInPath(src) && !RAP_CheckFileInPath(srclc))
|
||||
{
|
||||
SDL_RWops *readsrc = SDL_RWFromFile(src, "rb");
|
||||
if(readsrc)
|
||||
{
|
||||
Sint64 size = SDL_RWsize(readsrc);
|
||||
char *buffer = (char*)malloc(size);
|
||||
SDL_RWread(readsrc, buffer, sizeof(char), size);
|
||||
SDL_RWops *writedst = SDL_RWFromFile(dst, "wb");
|
||||
if(writedst)
|
||||
{
|
||||
SDL_RWwrite(writedst, buffer, sizeof(char), size);
|
||||
SDL_RWclose(writedst);
|
||||
}
|
||||
SDL_RWclose(readsrc);
|
||||
free(buffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif //__ANDROID__
|
||||
|
||||
return cdpath;
|
||||
#else
|
||||
memset(cdpath, 0, sizeof(cdpath));
|
||||
|
||||
+15
-4
@@ -595,10 +595,23 @@ OBJS_DisplayStats(
|
||||
}
|
||||
else
|
||||
{
|
||||
static int dpos_gl = -1;
|
||||
int new_step = (dpos_gl != gl_cnt);
|
||||
|
||||
// The sweep advances once per simulation step, not once per
|
||||
// rendered frame.
|
||||
|
||||
if (new_step)
|
||||
dpos_gl = gl_cnt;
|
||||
|
||||
GFX_VLine(dpos + 110, MAP_BOTTOM + 8, 3, 68);
|
||||
GFX_VLine(209 - dpos, MAP_BOTTOM + 8, 3, 68);
|
||||
dpos++;
|
||||
dpos %= 50;
|
||||
|
||||
if (new_step)
|
||||
{
|
||||
dpos++;
|
||||
dpos %= 50;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -692,8 +705,6 @@ OBJS_Add(
|
||||
if (type >= S_LAST_OBJECT)
|
||||
return OBJ_ERROR;
|
||||
|
||||
g_oldsuper = -1;
|
||||
g_oldshield = -1;
|
||||
|
||||
lib = &obj_lib[type];
|
||||
|
||||
|
||||
+172
-122
@@ -1,6 +1,7 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <limits.h>
|
||||
#include "SDL.h"
|
||||
#include "common.h"
|
||||
#include "glbapi.h"
|
||||
@@ -30,7 +31,6 @@
|
||||
#include "flame.h"
|
||||
#include "input.h"
|
||||
#include "joyapi.h"
|
||||
#include "i_lastscr.h"
|
||||
#include "fileids.h"
|
||||
#include "entypes.h"
|
||||
|
||||
@@ -109,8 +109,10 @@ int player_cx = PLAYERINITX;
|
||||
int player_cy = PLAYERINITY;
|
||||
int playerbasepic = 3;
|
||||
int startfadeflag;
|
||||
int g_oldsuper = -1;
|
||||
int g_oldshield = -1;
|
||||
// Shield level latched by RAP_ThinkStats at the end of each simulation step;
|
||||
// used there to detect fresh damage. This is NOT a display dirty flag --
|
||||
// RAP_DisplayStats redraws the shield bars unconditionally every frame.
|
||||
static int g_oldshield = -1;
|
||||
int startendwave = -1;
|
||||
int gl_cnt;
|
||||
int g_flash = 0;
|
||||
@@ -119,6 +121,16 @@ int end_wave;
|
||||
int playerpic = 4;
|
||||
int g_mapleft;
|
||||
|
||||
// Interpolated player center, recomputed once per rendered frame and
|
||||
// consumed by draw code that cannot reach the Do_Game() locals.
|
||||
|
||||
int g_ipcx, g_ipcy;
|
||||
static int pp_x, pp_y, pp_cx, pp_cy;
|
||||
|
||||
// Simulation tick: 3/70 s written in units of 1/70000 s.
|
||||
|
||||
#define RAP_SIM_STEP 3000
|
||||
|
||||
int fadecnt;
|
||||
|
||||
#define ROTPAL_START 240
|
||||
@@ -209,8 +221,6 @@ ShutDown(
|
||||
int errcode
|
||||
)
|
||||
{
|
||||
char* mem;
|
||||
|
||||
if (!errcode && !godmode)
|
||||
WIN_Order();
|
||||
|
||||
@@ -220,13 +230,7 @@ ShutDown(
|
||||
//PTR_End();
|
||||
//KBD_End();
|
||||
|
||||
if (reg_flag)
|
||||
mem = GLB_GetItem(FILE002_LASTSCR2_TXT); //Get ANSI Screen Fullversion from GLB to char*
|
||||
else
|
||||
mem = GLB_GetItem(FILE001_LASTSCR1_TXT); //Get ANSI Screen Shareware from GLB to char*
|
||||
|
||||
closewindow(); //Close Main Window
|
||||
I_LASTSCR(mem); //Call to display ANSI Screen
|
||||
GLB_FreeAll();
|
||||
IPT_CloJoy(); //Close Joystick
|
||||
SWD_End();
|
||||
@@ -497,38 +501,28 @@ RAP_DisplayShieldLevel(
|
||||
}
|
||||
|
||||
/***************************************************************************
|
||||
RAP_DisplayStats() -
|
||||
RAP_ThinkStats () - Simulation-side half of the status logic: death
|
||||
sequence, wave-exit control and low-shield warnings.
|
||||
Split from RAP_DisplayStats so state changes stay
|
||||
locked to simulation steps while drawing runs at the
|
||||
presentation rate.
|
||||
***************************************************************************/
|
||||
static int stats_damage = -1;
|
||||
static int stats_blinkflag = 1;
|
||||
|
||||
void
|
||||
RAP_DisplayStats(
|
||||
RAP_ThinkStats(
|
||||
void
|
||||
)
|
||||
{
|
||||
char temp[24];
|
||||
int super, shield, loop, x, y;
|
||||
char* pic;
|
||||
GFX_PIC *h;
|
||||
static int damage = -1;
|
||||
static int blinkflag = 1;
|
||||
|
||||
// == DISPLAY SUPER SHIELD ========================
|
||||
super = OBJS_GetAmt(S_SUPER_SHIELD);
|
||||
if (g_oldsuper != super)
|
||||
{
|
||||
RAP_DisplayShieldLevel(MAP_LEFT - 8, super);
|
||||
g_oldsuper = super;
|
||||
}
|
||||
|
||||
// == DISPLAY NORM SHIELD ========================
|
||||
shield = OBJS_GetAmt(S_ENERGY);
|
||||
if (g_oldshield != shield)
|
||||
{
|
||||
RAP_DisplayShieldLevel(MAP_RIGHT + 4, shield);
|
||||
}
|
||||
|
||||
if (shield <= 0 && !godmode)
|
||||
{
|
||||
// BLOW UP SHIP IF ! IN GOD MODE ===================
|
||||
// == BLOW UP SHIP IF ! IN GOD MODE ===================
|
||||
|
||||
ANIMS_StartAnim(A_MED_AIR_EXPLO, playerx + (wrand()%32), playery + (wrand()%32));
|
||||
ANIMS_StartAnim(A_SMALL_AIR_EXPLO, playerx + (wrand()%32), playery + (wrand()%32));
|
||||
@@ -565,7 +559,7 @@ RAP_DisplayStats(
|
||||
}
|
||||
}
|
||||
|
||||
// IF END OF WAVE FLY SHIP OFF SCREEN ===================
|
||||
// == IF END OF WAVE FLY SHIP OFF SCREEN ===================
|
||||
|
||||
if (startendwave != -1 && shield > 0)
|
||||
{
|
||||
@@ -592,17 +586,17 @@ RAP_DisplayStats(
|
||||
{
|
||||
if (!(gl_cnt % 8))
|
||||
{
|
||||
blinkflag ^= 1;
|
||||
stats_blinkflag ^= 1;
|
||||
|
||||
if (blinkflag)
|
||||
if (stats_blinkflag)
|
||||
{
|
||||
if (damage)
|
||||
if (stats_damage)
|
||||
{
|
||||
damage--;
|
||||
stats_damage--;
|
||||
|
||||
if ((haptic) && (control == 2))
|
||||
{
|
||||
IPT_CalJoyRumbleHigh();
|
||||
IPT_CalJoyRumbleHigh();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -613,30 +607,57 @@ RAP_DisplayStats(
|
||||
if (OBJS_LoseObj())
|
||||
{
|
||||
SND_Patch(FX_CRASH, 127);
|
||||
damage = 2;
|
||||
stats_damage = 2;
|
||||
}
|
||||
}
|
||||
|
||||
if (blinkflag)
|
||||
{
|
||||
if (damage)
|
||||
{
|
||||
pic = GLB_GetItem(FILE111_WEPDEST_PIC);
|
||||
h = (GFX_PIC*)pic;
|
||||
GFX_PutSprite(pic, (320 - LE_LONG(h->width)) >> 1, MAP_BOTTOM - 9);
|
||||
}
|
||||
|
||||
if (startendwave == -1)
|
||||
SND_Patch(FX_WARNING, 127);
|
||||
|
||||
pic = GLB_GetItem(FILE110_SHLDLOW_PIC);
|
||||
h = (GFX_PIC*)pic;
|
||||
GFX_PutSprite(pic, (320 - LE_LONG(h->width)) >> 1, MAP_BOTTOM);
|
||||
}
|
||||
if (stats_blinkflag && startendwave == -1)
|
||||
SND_Patch(FX_WARNING, 127);
|
||||
}
|
||||
|
||||
g_oldshield = shield;
|
||||
|
||||
}
|
||||
|
||||
/***************************************************************************
|
||||
RAP_DisplayStats() -
|
||||
***************************************************************************/
|
||||
void
|
||||
RAP_DisplayStats(
|
||||
void
|
||||
)
|
||||
{
|
||||
char temp[24];
|
||||
int shield, loop, x, y;
|
||||
char* pic;
|
||||
GFX_PIC *h;
|
||||
|
||||
// == DISPLAY SUPER SHIELD ========================
|
||||
// Both bars are redrawn on every rendered frame. They were once cached
|
||||
// behind g_oldsuper/g_oldshield change checks, but RAP_ThinkStats now
|
||||
// re-latches g_oldshield once per simulation step -- before this draw
|
||||
// code ever runs -- so the checks could never fire again and the bars
|
||||
// froze. Drawing is idempotent and cheap; the bars write straight into
|
||||
// displayscreen outside the blitted map area, so this also restores
|
||||
// them after menus or fades clear the sides.
|
||||
RAP_DisplayShieldLevel(MAP_LEFT - 8, OBJS_GetAmt(S_SUPER_SHIELD));
|
||||
|
||||
// == DISPLAY NORM SHIELD ========================
|
||||
shield = OBJS_GetAmt(S_ENERGY);
|
||||
RAP_DisplayShieldLevel(MAP_RIGHT + 4, shield);
|
||||
|
||||
if (shield <= SHIELD_LOW && !godmode && stats_blinkflag)
|
||||
{
|
||||
if (stats_damage)
|
||||
{
|
||||
pic = GLB_GetItem(FILE111_WEPDEST_PIC);
|
||||
h = (GFX_PIC*)pic;
|
||||
GFX_PutSprite(pic, (320 - LE_LONG(h->width)) >> 1, MAP_BOTTOM - 9);
|
||||
}
|
||||
|
||||
pic = GLB_GetItem(FILE110_SHLDLOW_PIC);
|
||||
h = (GFX_PIC*)pic;
|
||||
GFX_PutSprite(pic, (320 - LE_LONG(h->width)) >> 1, MAP_BOTTOM);
|
||||
}
|
||||
OBJS_DisplayStats();
|
||||
|
||||
sprintf(temp, "%08u", plr.score);
|
||||
@@ -809,7 +830,7 @@ Do_Game(
|
||||
void
|
||||
)
|
||||
{
|
||||
int b2_flag, b3_flag, init_flag, rval, start_score, local_cnt;
|
||||
int b2_flag, b3_flag, init_flag, rval, start_score;
|
||||
b2_flag = 0;
|
||||
b3_flag = 0;
|
||||
init_flag = 1;
|
||||
@@ -852,11 +873,9 @@ Do_Game(
|
||||
memset(displaybuffer, 0, 64000);
|
||||
memset(displayscreen, 0, 64000);
|
||||
|
||||
local_cnt = GFX_GetFrameCount();
|
||||
Uint32 sim_next = SDL_GetTicks() * 70; // due time of next sim step
|
||||
|
||||
g_flash = 0;
|
||||
g_oldsuper = -1;
|
||||
g_oldshield = -1;
|
||||
startendwave = -1;
|
||||
|
||||
if (demo_flag == DEMO_RECORD)
|
||||
@@ -871,6 +890,11 @@ Do_Game(
|
||||
do
|
||||
{
|
||||
num_shadows = num_gshadows = 0;
|
||||
|
||||
pp_x = playerx;
|
||||
pp_y = playery;
|
||||
pp_cx = player_cx;
|
||||
pp_cy = player_cy;
|
||||
|
||||
#ifdef __ANDROID__
|
||||
if (!I_GetNeedResize(true))
|
||||
@@ -886,8 +910,6 @@ Do_Game(
|
||||
HELP_Win("OVERVW06_TXT");
|
||||
memset(displayscreen, 0, 64000);
|
||||
IPT_Start();
|
||||
g_oldsuper = -1;
|
||||
g_oldshield = -1;
|
||||
RAP_ClearSides();
|
||||
RAP_DisplayStats();
|
||||
SWD_SetClearFlag(1);
|
||||
@@ -908,8 +930,6 @@ Do_Game(
|
||||
SWD_SetClearFlag(0);
|
||||
RAP_ClearSides();
|
||||
WIN_Pause();
|
||||
g_oldsuper = -1;
|
||||
g_oldshield = -1;
|
||||
RAP_ClearSides();
|
||||
RAP_DisplayStats();
|
||||
SWD_SetClearFlag(1);
|
||||
@@ -1046,6 +1066,8 @@ Do_Game(
|
||||
|
||||
gl_cnt++;
|
||||
|
||||
TILE_Scroll();
|
||||
|
||||
TILE_Think();
|
||||
ENEMY_Think();
|
||||
ESHOT_Think();
|
||||
@@ -1057,27 +1079,10 @@ Do_Game(
|
||||
if (draw_player)
|
||||
SHADOW_Add(curship[playerpic + g_flash], playerx, playery);
|
||||
|
||||
TILE_Display();
|
||||
SHADOW_DisplayGround();
|
||||
ENEMY_DisplayGround();
|
||||
SHADOW_DisplaySky();
|
||||
ANIMS_DisplayGround();
|
||||
SHADOW_Snapshot();
|
||||
|
||||
ENEMY_DisplaySky();
|
||||
SHOTS_Display();
|
||||
BONUS_Display();
|
||||
ANIMS_DisplaySky();
|
||||
|
||||
if (draw_player)
|
||||
{
|
||||
FLAME_Down(player_cx - o_engine[playerpic] - 3, player_cy + 15, 4, gl_cnt % 2);
|
||||
FLAME_Down(player_cx + o_engine[playerpic] - 2, player_cy + 15, 4, gl_cnt % 2);
|
||||
GFX_PutSprite((char*)GLB_GetItem(curship[playerpic + g_flash]), playerx, playery);
|
||||
g_flash = 0;
|
||||
}
|
||||
|
||||
ANIMS_DisplayHigh();
|
||||
ESHOT_Display();
|
||||
// == FADE / PALETTE SIMULATION =====================================
|
||||
// (advanced once per simulation step; was interleaved with drawing)
|
||||
|
||||
if (fadeflag)
|
||||
{
|
||||
@@ -1087,8 +1092,6 @@ Do_Game(
|
||||
g_mapleft = MAP_LEFT;
|
||||
GFX_SetPalette(gpal, 0);
|
||||
fadeflag = 0;
|
||||
g_oldsuper = -1;
|
||||
g_oldshield = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1106,18 +1109,7 @@ Do_Game(
|
||||
RAP_PaletteStuff();
|
||||
}
|
||||
|
||||
RAP_DisplayStats();
|
||||
|
||||
while (GFX_GetFrameCount() - local_cnt < 3)
|
||||
{
|
||||
}
|
||||
|
||||
local_cnt = GFX_GetFrameCount();
|
||||
|
||||
if (fadeflag)
|
||||
TILE_ShakeScreen();
|
||||
else
|
||||
TILE_DisplayScreen();
|
||||
RAP_ThinkStats();
|
||||
|
||||
if (startfadeflag)
|
||||
{
|
||||
@@ -1147,6 +1139,85 @@ Do_Game(
|
||||
GFX_FadeIn(gpal, 64);
|
||||
}
|
||||
|
||||
// == PRESENTATION ==================================================
|
||||
// Redraw interpolated frames until the next simulation step is due.
|
||||
// When running behind (a blocking menu ate wall time), skip renders
|
||||
// and let the simulation catch up -- the old tick-wait loop did the
|
||||
// same because the frame counter kept counting during menus.
|
||||
|
||||
if (SDL_GetTicks() * 70 - sim_next >= RAP_SIM_STEP)
|
||||
{
|
||||
sim_next += RAP_SIM_STEP;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
Uint32 now = SDL_GetTicks() * 70;
|
||||
Uint32 pend;
|
||||
|
||||
if (now - sim_next >= RAP_SIM_STEP)
|
||||
break;
|
||||
|
||||
pend = sim_next - now; // time until the next sim step
|
||||
|
||||
GFX_SetInterp(RAP_SIM_STEP - pend, RAP_SIM_STEP);
|
||||
I_GetEvent();
|
||||
|
||||
g_ipcx = GFX_InterpCoord(player_cx, pp_cx);
|
||||
g_ipcy = GFX_InterpCoord(player_cy, pp_cy);
|
||||
|
||||
TILE_Display();
|
||||
SHADOW_DisplayGround();
|
||||
ENEMY_DisplayGround();
|
||||
SHADOW_DisplaySky();
|
||||
ANIMS_DisplayGround();
|
||||
|
||||
ENEMY_DisplaySky();
|
||||
SHOTS_Display();
|
||||
BONUS_Display();
|
||||
ANIMS_DisplaySky();
|
||||
|
||||
if (draw_player)
|
||||
{
|
||||
int ipx = GFX_InterpCoord(playerx, pp_x);
|
||||
int ipy = GFX_InterpCoord(playery, pp_y);
|
||||
|
||||
FLAME_Down(g_ipcx - o_engine[playerpic] - 3, g_ipcy + 15, 4, gl_cnt % 2);
|
||||
FLAME_Down(g_ipcx + o_engine[playerpic] - 2, g_ipcy + 15, 4, gl_cnt % 2);
|
||||
GFX_PutSprite((char*)GLB_GetItem(curship[playerpic + g_flash]), ipx, ipy);
|
||||
}
|
||||
|
||||
// Above-player layer (most air explosions register as
|
||||
// HIGH_AIR); upstream draws it between the player and
|
||||
// enemy shots -- dropping it made dying ships despawn
|
||||
// without their explosion anims.
|
||||
ANIMS_DisplayHigh();
|
||||
ESHOT_Display();
|
||||
|
||||
RAP_DisplayStats();
|
||||
|
||||
if (fadeflag)
|
||||
TILE_ShakeScreen();
|
||||
else
|
||||
TILE_DisplayScreen();
|
||||
|
||||
if (!I_VsyncActive())
|
||||
{
|
||||
now = SDL_GetTicks() * 70;
|
||||
if (sim_next - now > 280)
|
||||
SDL_Delay(1);
|
||||
}
|
||||
}
|
||||
|
||||
sim_next += RAP_SIM_STEP;
|
||||
}
|
||||
|
||||
// Muzzle-flash ship pic lasts exactly one simulation step, matching
|
||||
// the original tick loop. Clearing it per rendered frame (inside the
|
||||
// interpolation loop) made the flash vanish at display refresh rates.
|
||||
g_flash = 0;
|
||||
|
||||
if (KBD_Key(SC_X) && KBD_Key(SC_ALT))
|
||||
{
|
||||
RAP_ClearSides();
|
||||
@@ -1154,8 +1225,6 @@ Do_Game(
|
||||
IPT_End();
|
||||
WIN_AskExit();
|
||||
IPT_Start();
|
||||
g_oldsuper = -1;
|
||||
g_oldshield = -1;
|
||||
RAP_ClearSides();
|
||||
RAP_DisplayStats();
|
||||
SWD_SetClearFlag(1);
|
||||
@@ -1196,8 +1265,6 @@ Do_Game(
|
||||
#endif //__ANDROID__
|
||||
|
||||
IPT_Start();
|
||||
g_oldsuper = -1;
|
||||
g_oldshield = -1;
|
||||
RAP_ClearSides();
|
||||
RAP_DisplayStats();
|
||||
SWD_SetClearFlag(1);
|
||||
@@ -1320,27 +1387,13 @@ main(
|
||||
printf("GOD mode enabled\n");
|
||||
|
||||
cur_diff = 0;
|
||||
|
||||
if (!access("FILE0001.GLB", 0) ||
|
||||
!access("file0001.glb", 0) ||
|
||||
RAP_CheckFileInPath("FILE0001.GLB") ||
|
||||
RAP_CheckFileInPath("file0001.glb"))
|
||||
if (GLB_SlotItems(1) > 0)
|
||||
gameflag[0] = 1;
|
||||
|
||||
if (!access("FILE0002.GLB", 0) ||
|
||||
!access("file0002.glb", 0) ||
|
||||
RAP_CheckFileInPath("FILE0002.GLB") ||
|
||||
RAP_CheckFileInPath("file0002.glb"))
|
||||
if (GLB_SlotItems(2) > 0)
|
||||
gameflag[1] = 1;
|
||||
|
||||
if ((!access("FILE0003.GLB", 0) && !access("FILE0004.GLB", 0)) ||
|
||||
(!access("file0003.glb", 0) && !access("file0004.glb", 0)) ||
|
||||
(!access("FILE0003.GLB", 0) && !access("file0004.glb", 0)) ||
|
||||
(!access("file0003.glb", 0) && !access("FILE0004.GLB", 0)) ||
|
||||
(RAP_CheckFileInPath("FILE0003.GLB") && RAP_CheckFileInPath("FILE0004.GLB")) ||
|
||||
(RAP_CheckFileInPath("file0003.glb") && RAP_CheckFileInPath("file0004.glb")) ||
|
||||
(RAP_CheckFileInPath("FILE0003.GLB") && RAP_CheckFileInPath("file0004.glb")) ||
|
||||
(RAP_CheckFileInPath("file0003.glb") && RAP_CheckFileInPath("FILE0004.GLB")))
|
||||
if (GLB_SlotItems(3) > 0 && GLB_SlotItems(4) > 0)
|
||||
{
|
||||
gameflag[2] = 1;
|
||||
gameflag[3] = 1;
|
||||
@@ -1356,10 +1409,7 @@ main(
|
||||
if (gameflag[loop])
|
||||
numfiles++;
|
||||
}
|
||||
|
||||
if ((access("FILE0000.GLB", 0) && !RAP_CheckFileInPath("FILE0000.GLB")) &&
|
||||
(access("file0000.glb", 0) && !RAP_CheckFileInPath("file0000.glb")) ||
|
||||
!numfiles)
|
||||
if (GLB_SlotItems(0) == 0 || !numfiles)
|
||||
{
|
||||
printf("All game data files NOT FOUND cannot proceed !!\n");
|
||||
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR,
|
||||
|
||||
+1
-1
@@ -43,8 +43,8 @@ extern int player_cx, player_cy;
|
||||
extern int startfadeflag;
|
||||
extern int startendwave;
|
||||
extern int gl_cnt;
|
||||
extern int g_oldsuper, g_oldshield;
|
||||
extern int playerx, playery;
|
||||
extern int g_ipcx, g_ipcy;
|
||||
extern char gdmodestr[];
|
||||
extern int playerbasepic;
|
||||
|
||||
|
||||
+36
-16
@@ -23,6 +23,26 @@ SHADOW shads[MAX_SHADOWS];
|
||||
SHADOW gshads[MAX_GSHADOWS];
|
||||
int num_shadows, num_gshadows;
|
||||
|
||||
static SHADOW prev_shads[MAX_SHADOWS];
|
||||
static SHADOW prev_gshads[MAX_GSHADOWS];
|
||||
static int prev_num_shadows, prev_num_gshadows;
|
||||
|
||||
/***************************************************************************
|
||||
SHADOW_Snapshot () - Latches this simulation step's shadows as previous
|
||||
positions for interpolated display
|
||||
***************************************************************************/
|
||||
void
|
||||
SHADOW_Snapshot(
|
||||
void
|
||||
)
|
||||
{
|
||||
memcpy(prev_shads, shads, sizeof(shads));
|
||||
memcpy(prev_gshads, gshads, sizeof(gshads));
|
||||
|
||||
prev_num_shadows = num_shadows;
|
||||
prev_num_gshadows = num_gshadows;
|
||||
}
|
||||
|
||||
#define MAXZ 1280;
|
||||
|
||||
/***************************************************************************
|
||||
@@ -194,20 +214,20 @@ SHADOW_DisplaySky(
|
||||
)
|
||||
{
|
||||
char *pic;
|
||||
SHADOW *cur;
|
||||
cur = shads;
|
||||
int i;
|
||||
int ix, iy;
|
||||
|
||||
if (opt_detail < 1)
|
||||
return;
|
||||
|
||||
while (--num_shadows != -1)
|
||||
for (i = 0; i < num_shadows; i++)
|
||||
{
|
||||
pic = GLB_GetItem(cur->item);
|
||||
SHADOW_Draw(pic, cur->x, cur->y);
|
||||
cur++;
|
||||
ix = (i < prev_num_shadows) ? GFX_InterpCoord(shads[i].x, prev_shads[i].x) : shads[i].x;
|
||||
iy = (i < prev_num_shadows) ? GFX_InterpCoord(shads[i].y, prev_shads[i].y) : shads[i].y;
|
||||
|
||||
pic = GLB_GetItem(shads[i].item);
|
||||
SHADOW_Draw(pic, ix, iy);
|
||||
}
|
||||
|
||||
num_shadows = 0;
|
||||
}
|
||||
|
||||
/***************************************************************************
|
||||
@@ -219,18 +239,18 @@ SHADOW_DisplayGround(
|
||||
)
|
||||
{
|
||||
char *pic;
|
||||
SHADOW *cur;
|
||||
cur = gshads;
|
||||
int i;
|
||||
int ix, iy;
|
||||
|
||||
if (opt_detail < 1)
|
||||
return;
|
||||
|
||||
while (--num_gshadows != -1)
|
||||
for (i = 0; i < num_gshadows; i++)
|
||||
{
|
||||
pic = GLB_GetItem(cur->item);
|
||||
GFX_ShadeShape(DARK, (char*)pic, cur->x, cur->y);
|
||||
cur++;
|
||||
ix = (i < prev_num_gshadows) ? GFX_InterpCoord(gshads[i].x, prev_gshads[i].x) : gshads[i].x;
|
||||
iy = (i < prev_num_gshadows) ? GFX_InterpCoord(gshads[i].y, prev_gshads[i].y) : gshads[i].y;
|
||||
|
||||
pic = GLB_GetItem(gshads[i].item);
|
||||
GFX_ShadeShape(DARK, (char*)pic, ix, iy);
|
||||
}
|
||||
|
||||
num_gshadows = 0;
|
||||
}
|
||||
@@ -8,4 +8,5 @@ void SHADOW_MakeShades(void);
|
||||
void SHADOW_GAdd(int item, int x, int y);
|
||||
void SHADOW_Add(int item, int x, int y);
|
||||
void SHADOW_DisplayGround();
|
||||
void SHADOW_Snapshot(void);
|
||||
void SHADOW_DisplaySky();
|
||||
+36
-14
@@ -779,6 +779,7 @@ SHOTS_PlayerShoot(
|
||||
cur->speed = lib->speed;
|
||||
cur->x = player_cx;
|
||||
cur->y = player_cy;
|
||||
cur->age = 0;
|
||||
cur->move.x = (wrand() % enemy->width) + enemy->move.x - 1;
|
||||
cur->move.y = (wrand() % enemy->height) + enemy->move.y - 1;
|
||||
cur->move.x2 = player_cx;
|
||||
@@ -1019,7 +1020,23 @@ SHOTS_Think(
|
||||
for (shot = first_shots.next; &last_shots != shot; shot = shot->next)
|
||||
{
|
||||
lib = shot->lib;
|
||||
|
||||
|
||||
// S_LINE tracers (laser turret) live exactly one simulation step:
|
||||
// created during this iteration's input phase, they get ONE Think
|
||||
// pass (position + damage) and are drawn by every render of this
|
||||
// step, then purged here at the top of the NEXT Think. Upstream
|
||||
// removed them inside the display pass, which no longer owns state.
|
||||
// doneflag must NOT be used: it is hit/retire game state, and the
|
||||
// turret's retire path never frees the shot, so reusing it leaked
|
||||
// one pool slot per fire until SHOTS_Get() serviced no weapon.
|
||||
if (lib->beam == S_LINE && ++shot->age > 1)
|
||||
{
|
||||
shot = SHOTS_Remove(shot);
|
||||
continue;
|
||||
}
|
||||
|
||||
shot->px = shot->x;
|
||||
shot->py = shot->y;
|
||||
switch (lib->beam)
|
||||
{
|
||||
default:
|
||||
@@ -1046,6 +1063,8 @@ SHOTS_Think(
|
||||
shot->pic = lib->pic[shot->curframe];
|
||||
shot->x = shot->move.x - lib->hlx;
|
||||
shot->y = shot->move.y;
|
||||
shot->cnt++;
|
||||
shot->cnt = shot->cnt % 4;
|
||||
|
||||
for (enemy = first_enemy.next; &last_enemy != enemy; enemy = enemy->next)
|
||||
{
|
||||
@@ -1257,12 +1276,15 @@ SHOTS_Display(
|
||||
void
|
||||
)
|
||||
{
|
||||
int loop, x, y;
|
||||
int loop, x, y, ix, iy;
|
||||
SHOTS *shot;
|
||||
GFX_PIC *h;
|
||||
|
||||
for (shot = first_shots.next; shot != &last_shots; shot = shot->next)
|
||||
{
|
||||
ix = GFX_InterpCoord(shot->x, shot->px);
|
||||
iy = GFX_InterpCoord(shot->y, shot->py);
|
||||
|
||||
switch (shot->lib->beam)
|
||||
{
|
||||
default:
|
||||
@@ -1270,37 +1292,37 @@ SHOTS_Display(
|
||||
break;
|
||||
|
||||
case S_SHOOT:
|
||||
GFX_PutSprite(shot->pic, shot->x, shot->y);
|
||||
GFX_PutSprite(shot->pic, ix, iy);
|
||||
break;
|
||||
|
||||
case S_LINE:
|
||||
GFX_Line(player_cx + 1, player_cy, shot->move.x, shot->move.y, 69);
|
||||
GFX_Line(player_cx - 1, player_cy, shot->move.x, shot->move.y, 69);
|
||||
GFX_Line(player_cx, player_cy, shot->move.x, shot->move.y, 64);
|
||||
shot = SHOTS_Remove(shot);
|
||||
// Exists only during its birth step (purged by SHOTS_Think),
|
||||
// so every rendered frame of that step draws the beam -- on a
|
||||
// hitting tick too, which the old doneflag guard hid.
|
||||
GFX_Line(g_ipcx + 1, g_ipcy, shot->move.x, shot->move.y, 69);
|
||||
GFX_Line(g_ipcx - 1, g_ipcy, shot->move.x, shot->move.y, 69);
|
||||
GFX_Line(g_ipcx, g_ipcy, shot->move.x, shot->move.y, 64);
|
||||
break;
|
||||
|
||||
case S_BEAM:
|
||||
for (loop = shot->move.y2; loop < shot->y; loop += 3)
|
||||
for (loop = shot->move.y2; loop < iy; loop += 3)
|
||||
{
|
||||
GFX_PutSprite(shot->pic, shot->x, loop);
|
||||
GFX_PutSprite(shot->pic, ix, loop);
|
||||
}
|
||||
|
||||
if (shot->lib->type == S_DEATH_RAY)
|
||||
GFX_PutSprite(detpow[shot->cnt], shot->x - 4, shot->y);
|
||||
GFX_PutSprite(detpow[shot->cnt], ix - 4, iy);
|
||||
else
|
||||
GFX_PutSprite(laspow[shot->cnt], shot->x, shot->y);
|
||||
GFX_PutSprite(laspow[shot->cnt], ix, iy);
|
||||
|
||||
h = (GFX_PIC*)lashit[shot->cnt];
|
||||
|
||||
x = shot->x - (LE_LONG(h->width) >> 2);
|
||||
x = ix - (LE_LONG(h->width) >> 2);
|
||||
y = shot->move.y2 - 8;
|
||||
|
||||
if (y > 0)
|
||||
GFX_PutSprite((char*)h, x, y);
|
||||
|
||||
shot->cnt++;
|
||||
shot->cnt = shot->cnt % 4;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -56,6 +56,8 @@ typedef struct SHOTS_S
|
||||
char *pic; // pointer to cur frame pic
|
||||
int x; // cur shot center x
|
||||
int y; // cur shot center y
|
||||
int px; // prev sim x (interp)
|
||||
int py; // prev sim y (interp)
|
||||
MOVEOBJ move; // MOVE stuff
|
||||
int speed; // cur speed
|
||||
int curframe; // current anim frame
|
||||
@@ -65,6 +67,7 @@ typedef struct SHOTS_S
|
||||
int starty; // PLAYER Y OFFSET;
|
||||
SHOT_LIB *lib;
|
||||
int cnt;
|
||||
int age; // sim steps survived (S_LINE purge in SHOTS_Think)
|
||||
}SHOTS;
|
||||
|
||||
extern char *lashit[4];
|
||||
|
||||
@@ -265,7 +265,6 @@ STORE_Enter(
|
||||
GFX_DisplayUpdate();
|
||||
GFX_FadeIn(palette, 16);
|
||||
|
||||
SWD_SetFieldPtr(window, STOR_VEXIT);
|
||||
PTR_DrawCursor(1);
|
||||
|
||||
OBJS_GetNum();
|
||||
|
||||
@@ -1877,69 +1877,6 @@ SWD_ShowAllWindows(
|
||||
return 1;
|
||||
}
|
||||
|
||||
/***************************************************************************
|
||||
SWD_SetWindowPtr() - Sets Pointer to center of active field
|
||||
***************************************************************************/
|
||||
void
|
||||
SWD_SetWindowPtr(
|
||||
int handle // INPUT : number/handle of window
|
||||
)
|
||||
{
|
||||
SWIN *curwin;
|
||||
SFIELD *curfld;
|
||||
curwin = g_wins[handle].win;
|
||||
|
||||
if (!ptractive || handle == -1)
|
||||
return;
|
||||
|
||||
if (active_field == -1 || !LE_LONG(curwin->numflds))
|
||||
{
|
||||
if (!g_wins[handle].flag || curwin == NULL)
|
||||
return;
|
||||
|
||||
PTR_SetPos(LE_LONG(curwin->x) + (LE_LONG(curwin->lx)>>1), LE_LONG(curwin->y) + (LE_LONG(curwin->ly)>>1));
|
||||
}
|
||||
else
|
||||
{
|
||||
curfld = (SFIELD*)((char*)curwin + LE_LONG(curwin->fldofs));
|
||||
curfld += active_field;
|
||||
|
||||
PTR_SetPos(LE_LONG(curfld->x) + (LE_LONG(curfld->lx)>>1), LE_LONG(curfld->y) + (LE_LONG(curfld->ly)>>1));
|
||||
}
|
||||
}
|
||||
|
||||
/***************************************************************************
|
||||
SWD_SetFieldPtr () - Sets Pointer on a field
|
||||
***************************************************************************/
|
||||
void
|
||||
SWD_SetFieldPtr(
|
||||
int handle, // INPUT : number/handle of window
|
||||
int field // INPUT : field
|
||||
)
|
||||
{
|
||||
SWIN *curwin;
|
||||
SFIELD *curfld;
|
||||
curwin = g_wins[handle].win;
|
||||
|
||||
if (!ptractive || handle == -1)
|
||||
return;
|
||||
|
||||
if (field == -1 || !LE_LONG(curwin->numflds))
|
||||
{
|
||||
if (!g_wins[handle].flag || curwin == NULL)
|
||||
return;
|
||||
|
||||
PTR_SetPos(LE_LONG(curwin->x) + (LE_LONG(curwin->lx)>>1), LE_LONG(curwin->y) + (LE_LONG(curwin->ly)>>1));
|
||||
}
|
||||
else
|
||||
{
|
||||
curfld = (SFIELD*)((char*)curwin + LE_LONG(curwin->fldofs));
|
||||
curfld += field;
|
||||
|
||||
PTR_SetPos(LE_LONG(curfld->x) + (LE_LONG(curfld->lx)>>1), LE_LONG(curfld->y) + (LE_LONG(curfld->ly)>>1));
|
||||
}
|
||||
}
|
||||
|
||||
/***************************************************************************
|
||||
SWD_SetActiveWindow() - Sets the current working window
|
||||
***************************************************************************/
|
||||
|
||||
@@ -222,7 +222,6 @@ void SWD_Dialog(SWD_DLG *swd_dlg);
|
||||
SWIN* SWD_ReformatFieldData(SWIN *header, int handle);
|
||||
int SWD_InitMasterWindow(int handle);
|
||||
int SWD_ShowAllWindows(void);
|
||||
void SWD_SetWindowPtr(int handle);
|
||||
void SWD_SetFieldSelect(int handle, int field_id, int opt);
|
||||
void SWD_SetFieldItem(int handle, int field_id, int item);
|
||||
int SWD_SetFieldText(int handle, int field_id, const char *in_text);
|
||||
@@ -231,7 +230,6 @@ int SWD_InitWindow(int handle);
|
||||
void SWD_SetActiveField(int handle, int field_id);
|
||||
int SWD_GetFieldXYL(int handle, int field_id, int* x, int* y, int* lx, int* ly);
|
||||
void SWD_SetWinDrawFunc(int handle, void (*infunc)(SWD_DLG*));
|
||||
void SWD_SetFieldPtr(int handle, int field);
|
||||
int SWD_GetFieldText(int handle, int field_id, char *out_text);
|
||||
int SWD_GetFieldItem(int handle, int field_id);
|
||||
void SWD_SetClearFlag(int inflag);
|
||||
+26
-1
@@ -46,6 +46,13 @@ int startflat[4];
|
||||
int tilepos;
|
||||
int tileyoff;
|
||||
|
||||
// Unwrapped scroll counters for interpolation. The raw tileyoff wraps by
|
||||
// MAP_BLOCKSIZE while the on-screen tile grid stays positionally continuous
|
||||
// (the wrap and the row shift cancel), so the visual offset must be derived
|
||||
// from a counter that never wraps.
|
||||
|
||||
static int vscroll, vscroll_prev;
|
||||
|
||||
TILESPOT tspots[MAX_STILES];
|
||||
TILESPOT *lastspot;
|
||||
int spark_delay;
|
||||
@@ -423,20 +430,35 @@ TILE_Display(
|
||||
{
|
||||
char *pic;
|
||||
TILESPOT *ts;
|
||||
int oy;
|
||||
|
||||
oy = GFX_InterpCoord(vscroll, vscroll_prev) - vscroll;
|
||||
|
||||
ts = tspots;
|
||||
|
||||
do
|
||||
{
|
||||
pic = GLB_GetItem(ts->item);
|
||||
pic += 20;
|
||||
TILE_Put(pic, ts->x, ts->y);
|
||||
TILE_Put(pic, ts->x, ts->y + oy);
|
||||
|
||||
if (ts == lastspot)
|
||||
break;
|
||||
|
||||
ts++;
|
||||
} while (1);
|
||||
}
|
||||
|
||||
/***************************************************************************
|
||||
TILE_Scroll () - Advances the map scroll one simulation step
|
||||
(moved out of TILE_Display for decoupled rendering)
|
||||
***************************************************************************/
|
||||
void
|
||||
TILE_Scroll(
|
||||
void
|
||||
)
|
||||
{
|
||||
vscroll_prev = vscroll;
|
||||
|
||||
tileyoff++;
|
||||
|
||||
@@ -459,6 +481,9 @@ TILE_Display(
|
||||
last_tile = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (scroll_flag)
|
||||
vscroll++;
|
||||
}
|
||||
|
||||
/***************************************************************************
|
||||
|
||||
@@ -28,6 +28,7 @@ typedef struct TDELAY_S
|
||||
void TILE_Init(void);
|
||||
void TILE_Think(void);
|
||||
void TILE_Display(void);
|
||||
void TILE_Scroll(void);
|
||||
int TILE_IsHit(int damage, int x, int y);
|
||||
int TILE_Bomb(int damage, int x, int y);
|
||||
void TILE_Explode(TILESPOT *ts, int delay);
|
||||
|
||||
@@ -212,7 +212,6 @@ WIN_Opts(
|
||||
|
||||
opt_window = SWD_InitWindow(FILE13f_OPTS_SWD);
|
||||
|
||||
SWD_SetWindowPtr(opt_window);
|
||||
SWD_SetFieldText(opt_window, OPTS_DETAIL, detail[curd]);
|
||||
SWD_SetWinDrawFunc(opt_window, WIN_OptDraw);
|
||||
|
||||
@@ -564,7 +563,6 @@ WIN_AskBool(
|
||||
int rval;
|
||||
int dchold;
|
||||
int ask_window;
|
||||
int px, py, lx, ly;
|
||||
SWD_DLG dlg;
|
||||
|
||||
rval = 0;
|
||||
@@ -583,9 +581,6 @@ WIN_AskBool(
|
||||
|
||||
PTR_DrawCursor(1);
|
||||
|
||||
SWD_GetFieldXYL(ask_window, ASK_YES, &px, &py, &lx, &ly);
|
||||
PTR_SetPos(px + (lx >> 1), py + (ly >> 1));
|
||||
|
||||
SWD_SetActiveField(ask_window, ASK_YES);
|
||||
|
||||
while (1)
|
||||
@@ -698,7 +693,6 @@ WIN_AskDiff(
|
||||
{
|
||||
SWD_DLG dlg;
|
||||
int rval, ask_window;
|
||||
int px, py, lx, ly;
|
||||
|
||||
rval = -1;
|
||||
|
||||
@@ -709,9 +703,6 @@ WIN_AskDiff(
|
||||
SWD_ShowAllWindows();
|
||||
GFX_DisplayUpdate();
|
||||
|
||||
SWD_GetFieldXYL(ask_window, OKREG_MED, &px, &py, &lx, &ly);
|
||||
PTR_SetPos(px + (lx >> 1), py + (ly >> 1));
|
||||
|
||||
while (1)
|
||||
{
|
||||
SWD_Dialog(&dlg);
|
||||
@@ -798,7 +789,6 @@ WIN_Register(
|
||||
|
||||
GFX_FadeIn(palette, 16);
|
||||
|
||||
SWD_SetFieldPtr(window, REG_VIEWID);
|
||||
PTR_DrawCursor(1);
|
||||
|
||||
#ifdef __ANDROID__
|
||||
@@ -1086,7 +1076,6 @@ WIN_Hangar(
|
||||
char temp[44];
|
||||
SWD_DLG dlg;
|
||||
int opt, oldopt, pos, kflag, local_cnt, pic_cnt, window;
|
||||
int x, y, lx, ly;
|
||||
int poslookup[4] = {
|
||||
HANG_MISSION,
|
||||
HANG_SUPPLIES,
|
||||
@@ -1143,7 +1132,6 @@ WIN_Hangar(
|
||||
|
||||
hangto = HANGTOMISSION;
|
||||
|
||||
SWD_SetWindowPtr(window);
|
||||
PTR_DrawCursor(1);
|
||||
|
||||
while (1)
|
||||
@@ -1277,8 +1265,6 @@ WIN_Hangar(
|
||||
if (opt != oldopt)
|
||||
{
|
||||
oldopt = opt;
|
||||
SWD_GetFieldXYL(window, opt, &x, &y, &lx, &ly);
|
||||
PTR_SetPos(x + (lx>>1), y + (ly>>1));
|
||||
oldopt = -1;
|
||||
dlg.sfield = opt;
|
||||
dlg.viewactive = 1;
|
||||
@@ -1465,7 +1451,6 @@ WIN_ShipComp(
|
||||
SWD_DLG dlg;
|
||||
int rval, secret1, secret2, secret3, secret, cz1, cz2;
|
||||
int window;
|
||||
int px, py, lx, ly;
|
||||
|
||||
rval = 1;
|
||||
secret1 = 0;
|
||||
@@ -1495,8 +1480,6 @@ WIN_ShipComp(
|
||||
GLB_LockItem(FILE12a_LIGHTON_PIC);
|
||||
GLB_LockItem(FILE12b_LIGHTOFF_PIC);
|
||||
|
||||
SWD_GetFieldXYL(window, COMP_AUTO, &px, &py, &lx, &ly);
|
||||
PTR_SetPos(px + (lx >> 1), py + (ly >> 1));
|
||||
SWD_SetActiveField(window, COMP_AUTO);
|
||||
|
||||
SWD_SetFieldItem(window, COMP_LITE1, FILE12b_LIGHTOFF_PIC);
|
||||
@@ -1520,7 +1503,6 @@ WIN_ShipComp(
|
||||
|
||||
GFX_FadeIn(palette, 16);
|
||||
|
||||
SWD_SetWindowPtr(window);
|
||||
PTR_DrawCursor(1);
|
||||
|
||||
while (1)
|
||||
@@ -2105,7 +2087,6 @@ WIN_MainMenu(
|
||||
|
||||
SND_CacheIFX();
|
||||
|
||||
SWD_SetWindowPtr(window);
|
||||
PTR_DrawCursor(1);
|
||||
ltable[0] = 0;
|
||||
|
||||
|
||||
Reference in new issue
Block a user