- ported the final level's text screen and exported its text to the string table.

This commit is contained in:
Christoph Oelckers 2020-08-22 18:12:19 +02:00
parent 6f039164a3
commit 0843f5f04a
11 changed files with 248 additions and 325 deletions

View file

@ -103,7 +103,7 @@ void FireProcess(void)
{
DoFireFrame();
lastUpdate = totalclock;
tileInvalidate(2342, -1, -1);
TileFiles.InvalidateTile(2342);
}
}

View file

@ -497,7 +497,7 @@ void DoLensEffect(void)
for (int i = 0; i < kLensSize*kLensSize; i++, d++)
if (lensTable[i] >= 0)
*d = s[lensTable[i]];
tileInvalidate(4077, -1, -1);
TileFiles.InvalidateTile(4077);
}
void UpdateDacs(int nPalette, bool bNoTint)

View file

@ -930,20 +930,6 @@ inline double calcSinTableValue(double index)
return 16384. * sin(BANG2RAD * index);
}
// pal: pass -1 to invalidate all palettes for the tile, or >=0 for a particular palette
// how: pass -1 to invalidate all instances of the tile in texture memory, or a bitfield
// bit 0: opaque or masked (non-translucent) texture, using repeating
// bit 1: ignored
// bit 2: 33% translucence, using repeating
// bit 3: 67% translucence, using repeating
// bit 4: opaque or masked (non-translucent) texture, using clamping
// bit 5: ignored
// bit 6: 33% translucence, using clamping
// bit 7: 67% translucence, using clamping
// clamping is for sprites, repeating is for walls
void tileInvalidate(int tilenume, int32_t pal, int32_t how);
void PrecacheHardwareTextures(int nTile);
void Polymost_Startup();
@ -1027,10 +1013,8 @@ static FORCE_INLINE int tilehasmodelorvoxel(int const tilenume, int pal)
{
UNREFERENCED_PARAMETER(pal);
return
#ifdef USE_OPENGL
(videoGetRenderMode() >= REND_POLYMOST && mdinited && hw_models && tile2model[Ptile2tile(tilenume, pal)].modelid != -1) ||
#endif
(videoGetRenderMode() <= REND_POLYMOST && r_voxels && tiletovox[tilenume] != -1);
(mdinited && hw_models && tile2model[Ptile2tile(tilenume, pal)].modelid != -1) ||
(r_voxels && tiletovox[tilenume] != -1);
}
int32_t md_defineframe(int32_t modelid, const char *framename, int32_t tilenume,

View file

@ -476,11 +476,6 @@ inline rottile_t& RotTile(int tile)
}
inline void tileInvalidate(int tilenume, int32_t, int32_t)
{
TileFiles.InvalidateTile(tilenume);
}
int32_t animateoffs(int const tilenum, int fakevar);
inline FGameTexture* tileGetTexture(int tile, bool animate = false)

View file

@ -39,6 +39,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#include "sequence.h"
#include "v_draw.h"
#include "m_random.h"
#include "gstrings.h"
#include <string>
@ -116,13 +117,12 @@ void InitFonts()
fontdata.Insert('\'', tileGetTexture(3654));
fontdata.Insert('`', tileGetTexture(3654));
fontdata.Insert('.', tileGetTexture(3650));
fontdata.Insert(',', tileGetTexture(3551));
fontdata.Insert(',', tileGetTexture(3653));
fontdata.Insert('-', tileGetTexture(3656));
fontdata.Insert('?', tileGetTexture(3652));
fontdata.Insert(127, TexMan.FindGameTexture("TINYBLAK")); // this is only here to widen the color range of the font to produce a better translation.
GlyphSet::Iterator it(fontdata);
GlyphSet::Pair* pair;
while (it.NextPair(pair)) pair->Value->SetOffsetsNotForFont();
GlyphSet::Iterator it2(fontdata);
while (it2.NextPair(pair)) pair->Value->SetOffsetsNotForFont();
SmallFont2 = new ::FFont("SmallFont2", nullptr, "defsmallfont2", 0, 0, 0, -1, 4, false, false, false, &fontdata);
SmallFont2->SetKerning(1);
}
@ -369,7 +369,7 @@ void menu_DoPlasma()
v28[nSmokeOffset] = 175;
}
tileInvalidate(nPlasmaTile, -1, -1);
TileFiles.InvalidateTile(nPlasmaTile);
// flip between tile 4092 and 4093
if (nPlasmaTile == kTile4092) {
@ -1030,10 +1030,215 @@ public:
}
};
//---------------------------------------------------------------------------
//
// last level cinema
//
//---------------------------------------------------------------------------
class DLastLevelCinema : public DScreenJob
{
int var_24 = 16;
int var_28 = 12;
int ebp;
int nEndTime = 240;
int phase = 0;
int nextclock = 4;
unsigned int nStringTypeOn, nCharTypeOn;
int screencnt = 0;
TArray<FString> screentext;
public:
DLastLevelCinema() : DScreenJob(fadein | fadeout) {}
private:
void DoStatic(int a, int b)
{
auto pixels = TileFiles.tileMakeWritable(kTileLoboLaptop);
int v2 = 160 - a / 2;
int v4 = 81 - b / 2;
int var_18 = v2 + a;
int v5 = v4 + b;
auto pTile = (pixels + (200 * v2)) + v4;
TileFiles.InvalidateTile(kTileLoboLaptop);
while (v2 < var_18)
{
uint8_t* pStart = pTile;
pTile += 200;
int v7 = v4;
while (v7 < v5)
{
*pStart = RandomBit() * 16;
v7++;
pStart++;
}
v2++;
}
}
void Phase1()
{
if (var_24 >= 116)
{
if (var_28 < 192)
var_28 += 20;
}
else
{
var_24 += 20;
}
DoStatic(var_28, var_24);
}
bool InitPhase2()
{
FStringf label("TXT_EX_LASTLEVEL%d", screencnt + 1);
label = GStrings(label);
screentext = label.Split("\n");
if (screentext.Size() == 0) return false;
nStringTypeOn = 0;
nCharTypeOn = 0;
ebp = screentext.Size() * 4; // half height of the entire text
ebp = 81 - ebp; // offset from the screen's center.
auto tex = dynamic_cast<FRestorableTile*>(tileGetTexture(kTileLoboLaptop)->GetTexture()->GetImage());
if (tex) tex->Reload();
return true;
}
bool Phase3()
{
DoStatic(var_28, var_24);
if (var_28 > 20) {
var_28 -= 20;
return true;
}
if (var_24 > 20) {
var_24 -= 20;
return true;
}
return false;
}
void DisplayPhase2()
{
DrawTexture(twod, tileGetTexture(kTileLoboLaptop), 0, 0, DTA_FullscreenEx, FSMode_ScaleToFit43, TAG_DONE);
int yy = ebp;
for (int i = 0; i < nStringTypeOn; i++, yy += 8)
{
DrawText(twod, SmallFont2, CR_UNTRANSLATED, 70, yy, screentext[i], DTA_FullscreenScale, FSMode_ScaleToFit43, DTA_VirtualWidth, 320, DTA_VirtualHeight, 200, TAG_DONE);
}
DrawText(twod, SmallFont2, CR_UNTRANSLATED, 70, yy, screentext[nStringTypeOn], DTA_FullscreenScale, FSMode_ScaleToFit43, DTA_VirtualWidth, 320, DTA_VirtualHeight, 200, DTA_TextLen, nCharTypeOn, TAG_DONE);
}
int Frame(uint64_t clock, bool skiprequest) override
{
if (clock == 0)
{
PlayLocalSound(StaticSound[kSound75], 0, false, CHANF_UI);
phase = 1;
}
int totalclock = clock * 120 / 1'000'000'000;
switch (phase)
{
case 1:
if (totalclock >= nextclock)
{
Phase1();
nextclock += 4;
}
DrawTexture(twod, tileGetTexture(kTileLoboLaptop), 0, 0, DTA_FullscreenEx, FSMode_ScaleToFit43, TAG_DONE);
if (skiprequest || totalclock >= 240)
{
InitPhase2();
phase = 2;
skiprequest = 0;
}
break;
case 2:
if (totalclock >= nextclock)
{
if (screentext[nStringTypeOn][nCharTypeOn] != ' ')
PlayLocalSound(StaticSound[kSound71], 0, false, CHANF_UI);
nCharTypeOn++;
nextclock += 4;
if (screentext[nStringTypeOn][nCharTypeOn] == 0)
{
nCharTypeOn = 0;
nStringTypeOn++;
if (nStringTypeOn >= screentext.Size())
{
nextclock = (kTimerTicks * (screentext.Size() + 2)) + (int)totalclock;
phase = 3;
}
}
}
DisplayPhase2();
if (skiprequest)
{
nextclock = (kTimerTicks * (screentext.Size() + 2)) + (int)totalclock;
phase = 3;
}
break;
case 3:
DisplayPhase2();
if (totalclock >= nextclock || skiprequest)
{
PlayLocalSound(StaticSound[kSound75], 0, false, CHANF_UI);
phase = 4;
nextclock = totalclock + 240;
skiprequest = 0;
}
break;
case 4:
if (totalclock >= nextclock)
{
skiprequest |= !Phase3();
nextclock += 4;
}
if (skiprequest || totalclock >= 240)
{
// Go to the next text page.
if (screencnt != 2)
{
screencnt++;
nextclock = totalclock + 240;
skiprequest = 0;
phase = 1;
}
else return skiprequest ? -1 : 0;
}
}
return 1;
}
};
// temporary.
void RunCinemaScene(int num)
{
JobDesc job = { Create<DCinema>(num) };
num = -1;
JobDesc job = { num == -1? (DScreenJob*)Create<DLastLevelCinema>() : Create<DCinema>(num) };
RunScreenJob(&job, 1, [](bool) { gamestate = GS_LEVEL; });
SyncScreenJob();
}

View file

@ -228,32 +228,6 @@ const char *gString[] =
"LOBOTOMY SOFTWARE, INC.",
"3D ENGINE BY 3D REALMS",
"",
"LASTLEVEL",
"INCOMING MESSAGE",
"",
"OUR LATEST SCANS SHOW",
"THAT THE ALIEN CRAFT IS",
"POWERING UP, APPARENTLY",
"IN AN EFFORT TO LEAVE.",
"THE BAD NEWS IS THAT THEY",
"SEEM TO HAVE LEFT A DEVICE",
"BEHIND, AND ALL EVIDENCE",
"SAYS ITS GOING TO BLOW A",
"BIG HOLE IN OUR FINE PLANET.",
"A SQUAD IS TRYING TO DISMANTLE",
"IT RIGHT NOW, BUT NO LUCK SO",
"FAR, AND TIME IS RUNNING OUT.",
"",
"GET ABOARD THAT CRAFT NOW",
"BEFORE IT LEAVES, THEN FIND",
"AND SHOOT ALL THE ENERGY",
"TOWERS TO GAIN ACCESS TO THE",
"CONTROL ROOM. THERE YOU NEED TO",
"TAKE OUT THE CONTROL PANELS AND",
"THE CENTRAL POWER SOURCE. THIS",
"IS THE BIG ONE BUDDY, BEST OF",
"LUCK... FOR ALL OF US.",
"",
"",
"CREDITS",
"EXHUMED",
@ -2100,20 +2074,7 @@ void CopyTileToBitmap(short nSrcTile, short nDestTile, int xPos, int yPos)
pDestB = pDest;
}
tileInvalidate(nDestTile, -1, -1);
}
int CopyCharToBitmap(char nChar, int nTile, int xPos, int yPos)
{
if (nChar == ' ') {
return 4;
}
nChar = toupper(nChar);
int nFontTile = seq_GetSeqPicnum(kSeqFont2, 0, nChar - 32) + 102;
CopyTileToBitmap(nFontTile, nTile, xPos, yPos);
return tilesiz[nFontTile].x + 1;
TileFiles.InvalidateTile(nDestTile);
}
void EraseScreen(int nVal)
@ -2191,7 +2152,7 @@ void InitSpiritHead()
nHeadTimeStart = (int)totalclock;
memset(Worktile, TRANSPARENT_INDEX, WorktileSize);
tileInvalidate(kTileRamsesWorkTile, -1, -1);
TileFiles.InvalidateTile(kTileRamsesWorkTile);
nPixelsToShow = 0;
@ -2271,7 +2232,7 @@ int DoSpiritHead()
PlayerList[0].q16horiz = fix16_sadd(PlayerList[0].q16horiz, fix16_sdiv(fix16_ssub(nDestVertPan[0], PlayerList[0].q16horiz), fix16_from_int(4)));
tileInvalidate(kTileRamsesWorkTile, -1, -1);
TileFiles.InvalidateTile(kTileRamsesWorkTile);
if (nHeadStage < 2)
{

View file

@ -150,8 +150,6 @@ void DoPassword(int nPassword);
void InitSpiritHead();
int CopyCharToBitmap(char nChar, int nTile, int xPos, int yPos);
// TODO - relocate
void StatusMessage(int messageTime, const char *fmt, ...);

View file

@ -934,7 +934,7 @@ void DrawWeapons(int smooth)
if (nWeapon < -1) {
return;
}
PspTwoDSetter set;
PspTwoDSetter set; // this is the last one.
short var_34 = PlayerList[nLocalPlayer].field_3A;

View file

@ -70,19 +70,6 @@ short word_9AB5B = 0;
int keytimer = 0;
short nMenuKeys[] = { sc_N, sc_L, sc_M, sc_V, sc_Q, sc_None }; // select a menu item using the keys. 'N' for New Gane, 'V' for voume etc. 'M' picks Training for some reason...
void menu_ResetKeyTimer();
enum {
kMenuNewGame = 0,
kMenuLoadGame,
kMenuTraining,
kMenuVolume,
kMenuQuitGame,
kMenuMaxItems
};
void RunCinemaScene(int num);
@ -141,7 +128,7 @@ void DoEnergyTile()
}
}
tileInvalidate(kEnergy1, -1, -1);
TileFiles.InvalidateTile(kEnergy1);
if (nSmokeSparks)
{
@ -269,7 +256,7 @@ void DoEnergyTile()
energytile[val] = 175;
word_9AB5B = 1;
}
tileInvalidate(kEnergy2, -1, -1);
TileFiles.InvalidateTile(kEnergy2);
}
}
@ -361,32 +348,6 @@ void menu_GameSave(int nSaveSlot)
}
}
#define kMaxCinemaPals 16
const char *cinpalfname[kMaxCinemaPals] = {
"3454.pal",
"3452.pal",
"3449.pal",
"3445.pal",
"set.pal",
"3448.pal",
"3446.pal",
"hsc1.pal",
"2972.pal",
"2973.pal",
"2974.pal",
"2975.pal",
"2976.pal",
"heli.pal",
"2978.pal",
"terror.pal"
};
void CinemaFadeIn()
{
}
short nBeforeScene[] = { 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0 };
@ -394,7 +355,7 @@ void CheckBeforeScene(int nLevel)
{
if (nLevel == kMap20)
{
DoLastLevelCinema();
RunCinemaScene(-1);
return;
}
@ -483,209 +444,6 @@ uint8_t CheckForEscape()
return inputState.CheckAllInput();
}
void DoStatic(int a, int b)
{
RandomLong(); // nothing done with the result of this?
auto pixels = TileFiles.tileMakeWritable(kTileLoboLaptop);
int v2 = 160 - a / 2;
int v4 = 81 - b / 2;
int var_18 = v2 + a;
int v5 = v4 + b;
auto pTile = (pixels + (200 * v2)) + v4;
tileInvalidate(kTileLoboLaptop, -1, -1);
while (v2 < var_18)
{
uint8_t *pStart = pTile;
pTile += 200;
int v7 = v4;
while (v7 < v5)
{
*pStart = RandomBit() * 16;
v7++;
pStart++;
}
v2++;
}
tileInvalidate(kTileLoboLaptop, 0, 0);
overwritesprite(0, 0, kTileLoboLaptop, 0, 2, kPalNormal);
videoNextPage();
}
void DoLastLevelCinema()
{
FadeOut(0);
videoSetViewableArea(0, 0, xdim - 1, ydim - 1);
EraseScreen(-1);
RestorePalette();
int nString = FindGString("LASTLEVEL");
PlayLocalSound(StaticSound[kSound75], 0, false, CHANF_UI);
auto pixels = TileFiles.tileMakeWritable(kTileLoboLaptop);
// uh, what?
//memcpy((void*)waloff[kTileLoboLaptop], (void*)waloff[kTileLoboLaptop], tilesiz[kTileLoboLaptop].x * tilesiz[kTileLoboLaptop].y);
int var_24 = 16;
int var_28 = 12;
int nEndTime = (int)totalclock + 240;
while (inputState.keyBufferWaiting()) {
inputState.keyGetChar();
}
while (nEndTime > (int)totalclock)
{
HandleAsync();
if (var_24 >= 116)
{
if (var_28 < 192)
var_28 += 20;
}
else
{
var_24 += 20;
}
DoStatic(var_28, var_24);
// WaitVBL();
int time = (int)totalclock + 4;
while ((int)totalclock < time) {
HandleAsync();
}
}
// loc_3AD75
do
{
LABEL_11:
HandleAsync();
if (strlen(gString[nString]) == 0)
break;
int esi = nString;
while (strlen(gString[esi]) != 0)
esi++;
int ebp = esi;
ebp -= nString;
ebp <<= 2;
ebp = 81 - ebp;
int var_1C = esi - nString;
// loc_3ADD7
while (1)
{
HandleAsync();
if (strlen(gString[nString]) == 0)
break;
int xPos = 70;
const char *nChar = gString[nString];
nString++;
TileFiles.tileMakeWritable(kTileLoboLaptop);
while (*nChar)
{
HandleAsync();
if (*nChar != ' ') {
PlayLocalSound(StaticSound[kSound71], 0, false, CHANF_UI);
}
xPos += CopyCharToBitmap(*nChar, kTileLoboLaptop, xPos, ebp);
nChar++;
overwritesprite(0, 0, kTileLoboLaptop, 0, 2, kPalNormal);
videoNextPage();
// WaitVBL();
int time = (int)totalclock + 4;
while ((int)totalclock < time) {
HandleAsync();
}
if (CheckForEscape())
goto LABEL_28;
}
ebp += 8;
}
nString++;
inputState.ClearAllInput();
int v11 = (kTimerTicks * (var_1C + 2)) + (int)totalclock;
do
{
HandleAsync();
if (v11 <= (int)totalclock)
goto LABEL_11;
} while (!inputState.keyBufferWaiting());
}
while (inputState.keyGetChar() != 27);
LABEL_28:
PlayLocalSound(StaticSound[kSound75], 0, false, CHANF_UI);
nEndTime = (int)totalclock + 240;
while (nEndTime > (int)totalclock)
{
HandleAsync();
DoStatic(var_28, var_24);
// WaitVBL();
int time = (int)totalclock + 4;
while ((int)totalclock < time) {
HandleAsync();
}
if (var_28 > 20) {
var_28 -= 20;
continue;
}
if (var_24 > 20) {
var_24 -= 20;
continue;
}
break;
}
EraseScreen(-1);
tileLoad(kTileLoboLaptop);
FadeOut(0);
}
static SavegameHelper sgh("menu",
SA(nCinemaSeen),

View file

@ -60,11 +60,8 @@ void menu_DrawTheMap(int nLevel, int nLevelNew, int nLevelBest, std::function<vo
void DoEnergyTile();
void CinemaFadeIn();
void DoFailedFinalScene();
void DoLastLevelCinema();
void DoAfterCinemaScene(int nLevel);
void InitEnergyTile();

View file

@ -2132,4 +2132,29 @@ Level 28,TXT_EX_MAP28,,,,,,,,,,,,,,,,,,,,,,
Level 29,TXT_EX_MAP29,,,,,,,,,,,,,,,,,,,,,,
Level 30,TXT_EX_MAP30,,,,,,,,,,,,,,,,,,,,,,
Level 31,TXT_EX_MAP31,,,,,,,,,,,,,,,,,,,,,,
Level 32,TXT_EX_MAP32,,,,,,,,,,,,,,,,,,,,,,
Level 32,TXT_EX_MAP32,,,,,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,,,,,,
incoming Message,TXT_EX_LASTLEVEL1,,,,,,,,,,,,,,,,,,,,,,
"Our latest scans show
that the alien craft is
powering up, apparently
in an effort to leave.
The bad news is that they
seem to have left a device
behind, and all evidence
says its going to blow a
big hole in our fine planet.
A squad is trying to dismantle
it right now, but no luck so
far, and time is running out.
",TXT_EX_LASTLEVEL2,,,,,,,,,,,,,,,,,,,,,,
"Get aboard that craft now
before it leaves, then find
and shoot all the energy
towers to gain access to the
control room. There you need to
take out the control panels and
the central power source. This
is the big one buddy, best of
luck... For all of us.
",TXT_EX_LASTLEVEL3,,,,,,,,,,,,,,,,,,,,,,
1 default Identifier Remarks Filter eng enc ena enz eni ens enj enb enl ent enw cs de el eo es esm esn esg esc esa esd esv eso esr ess esf esl esy esz esb ese esh esi esu fi fr hu it jp ko nl pl pt ptg ro ru sr
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160