- get rid of PC Filesystem spooling micro-freezes on slow hard drives

This commit is contained in:
InspirationByte 2022-01-19 23:35:52 +03:00
parent 662bf3a049
commit ca9f797df0
7 changed files with 218 additions and 216 deletions

View File

@ -524,8 +524,6 @@ void SetPleaseWait(char *buffer)
ResetCityType();
#else
ResetCityType();
PsyX_EndScene();
#endif // PSX

View File

@ -406,12 +406,7 @@ void LoadGameLevel(void)
sector = citylumps[GameLevel][CITYLUMP_DATA1].x / CDSECTOR_SIZE;
nsectors = citylumps[GameLevel][CITYLUMP_DATA1].y / CDSECTOR_SIZE;
#ifdef PSX
loadsectors((char*)_primTab1, sector, nsectors);
#else
extern char g_CurrentLevelFileName[64];
loadsectorsPC(g_CurrentLevelFileName, (char*)_primTab1, sector, nsectors);
#endif // PSX
sector += nsectors;
@ -428,12 +423,8 @@ void LoadGameLevel(void)
malloc_lump = D_MALLOC(nsectors * CDSECTOR_SIZE);
D_MALLOC_END();
#ifdef PSX
loadsectors(malloc_lump, sector, nsectors);
#else
extern char g_CurrentLevelFileName[64];
loadsectorsPC(g_CurrentLevelFileName, malloc_lump, sector, nsectors);
#endif // PSX
sector += nsectors;
// CITYLUMP_DATA2 - in-memory lump

View File

@ -406,7 +406,7 @@ void ControlMap(void)
region_to_unpack = region_x + region_z * regions_across;
if (current_region == -1)
UnpackRegion(region_to_unpack, region_x & 1U | (region_z & 1U) * 2); // is that ever valid for 'target_barrel_region'?
UnpackRegion(region_to_unpack, region_x & 1U | (region_z & 1U) * 2);
current_region = region_to_unpack;

View File

@ -118,10 +118,7 @@ SPOOLQ spooldata[48];
#if USE_PC_FILESYSTEM
#define SIMPLE_SPOOL
extern int gContentOverride;
extern char g_CurrentLevelFileName[64];
#endif
#if defined(_DEBUG) || defined(PSX)
@ -357,7 +354,7 @@ void RequestSpool(int type, int data, int offset, int loadsize, char *address, s
next->type = type;
next->data = data;
next->sector = (SpoolLumpOffset / 2048) + offset;
next->sector = (SpoolLumpOffset / CDSECTOR_SIZE) + offset;
next->nsectors = loadsize;
next->addr = address;
next->func = func;
@ -744,7 +741,6 @@ void CheckLoadAreaData(int cellx, int cellz)
else if (/*spoolptr->super_region == 0xFF ||*/ nAreas == 0)
return;
// [A] Rev 1.1 patch
#define BOUNDARY_MIN 15
#define BOUNDARY_MAX 17
@ -806,14 +802,14 @@ void ClearRegion(int target_region)
ushort *cell_ptrs_s;
int loop;
loop = 1024;
cell_ptrs_s = cell_ptrs + target_region * 1024;
pvsptr = (int *)PVS_Buffers[target_region];
do {
for (loop = 0; loop < 1024; loop++)
{
*cell_ptrs_s++ = 0xffff;
*pvsptr++ = 0;
} while (--loop != 0);
}
ClearMem(PVS_Buffers[target_region]-4, pvsSize[target_region]);
@ -1016,7 +1012,7 @@ void ready_cb_textures(unsigned char intr, unsigned char *result)
{
CdGetSector(target_address, SECTOR_SIZE);
target_address += 2048;
target_address += CDSECTOR_SIZE;
sectors_this_chunk--;
current_sector++;
sectors_to_read--;
@ -1067,7 +1063,7 @@ void ready_cb_regions(unsigned char intr, unsigned char *result)
{
CdGetSector(target_address, SECTOR_SIZE);
target_address += 2048;
target_address += CDSECTOR_SIZE;
sectors_this_chunk--;
current_sector++;
sectors_to_read--;
@ -1182,7 +1178,7 @@ void ready_cb_misc(unsigned char intr, unsigned char *result)
{
CdGetSector(target_address, SECTOR_SIZE);
target_address += 2048;
target_address += CDSECTOR_SIZE;
sectors_to_read--;
current_sector++;
@ -1403,149 +1399,159 @@ void GotRegion(void)
}
}
// [D] [T]
void UpdateSpool(void)
{
#if USE_PC_FILESYSTEM && defined(SIMPLE_SPOOL)
if(strlen(g_CurrentLevelFileName) > 0)
{
FILE* fp = fopen(g_CurrentLevelFileName, "rb");
#if defined(SIMPLE_SPOOL)
extern char g_CurrentLevelFileName[64];
extern char* g_CurrentLevelSpoolData;
if (!fp)
{
#if !defined(__EMSCRIPTEN__)
char errPrint[1024];
sprintf(errPrint, "Cannot open '%s'\n", g_CurrentLevelFileName);
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "ERROR", errPrint, NULL);
#endif
return;
int UpdateSpoolPC(void)
{
if (g_CurrentLevelFileName[0] == 0)
return 0;
// read entire spool data
if (g_CurrentLevelSpoolData == NULL)
{
int SpoolLumpSize;
SpoolLumpSize = 16 * 1024 * 1024; // allocate 16 MB of RAM for spoolable data
g_CurrentLevelSpoolData = (char*)malloc(16 * 1024 * 1024);
loadsectors(g_CurrentLevelSpoolData, SpoolLumpOffset / CDSECTOR_SIZE, SpoolLumpSize);
}
for (; spoolpos_reading < spoolcounter; spoolpos_reading++)
{
char* spoolDataPtr;
SPOOLQ* current;
current = &spooldata[spoolpos_reading];
#define SPL_READ(dest, nsectors) \
{ \
int readSize = (nsectors)*CDSECTOR_SIZE; \
memcpy(dest, spoolDataPtr, readSize); \
spoolDataPtr += readSize; \
}
for (; spoolpos_reading < spoolcounter; spoolpos_reading++)
{
SPOOLQ* current = &spooldata[spoolpos_reading];
#ifdef _DEBUG
char* nameType;
switch (current->type)
{
case 0: // regions
nameType = "REGION";
break;
case 1: // textures
nameType = "TPAGE";
break;
case 2: // sbk
nameType = "SBK";
break;
case 3: // misc
nameType = "MISC";
break;
}
char* nameType;
switch (current->type)
{
case 0: // regions
nameType = "REGION";
break;
case 1: // textures
nameType = "TPAGE";
break;
case 2: // sbk
nameType = "SBK";
break;
case 3: // misc
nameType = "MISC";
break;
}
SPOOL_WARNING("spool type=%s cb=%d sec=%d cnt=%d id=%d\n", nameType, current->func ? 1 : 0, current->sector, current->nsectors, spoolpos_reading);
SPOOL_WARNING("spool type=%s cb=%d sec=%d cnt=%d id=%d\n", nameType, current->func ? 1 : 0, current->sector, current->nsectors, spoolpos_reading);
#endif // _DEBUG
// seek to required sector
fseek(fp, current->sector * 2048, SEEK_SET);
// seek to required sector
spoolDataPtr = g_CurrentLevelSpoolData - SpoolLumpOffset + current->sector * CDSECTOR_SIZE;
switch (current->type)
switch (current->type)
{
case 0: // regions
case 3: // misc
SPL_READ(current->addr, current->nsectors);
if (current->func)
current->func();
break;
case 1: // textures
// read cluts
nTPchunks = 0;
SPL_READ(current->addr + CDSECTOR_SIZE * 2 * 4, 1);
SendTPage();
nTPchunks++;
// read tpage (4 sectors 4 times = 16)
for (int i = 0; i < 4; i++)
{
case 0: // regions
fread(current->addr, 2048, current->nsectors, fp);
if (current->func)
current->func();
break;
case 1: // textures
// read cluts
nTPchunks = 0;
fread(current->addr + 0x4000, 2048, 1, fp);
SPL_READ(current->addr + (loadbank_write & 1U) * 256 * 32, 4);
SendTPage();
nTPchunks++;
// read tpage (4 sectors 4 times = 16)
for (int i = 0; i < 4; i++)
{
fread(current->addr + (loadbank_write & 1U) * 256 * 32, 2048, 4, fp);
SendTPage();
nTPchunks++;
}
break;
case 2: // sbk
// nothing to do with this
break;
case 3: // misc
fread(current->addr, 2048, current->nsectors, fp);
if (current->func)
current->func();
break;
}
break;
default:
break;
}
spoolcounter = 0;
spoolpos_reading = 0;
spoolactive = 0;
fclose(fp);
return;
#undef SPL_READ
}
spoolcounter = 0;
spoolpos_reading = 0;
spoolactive = 0;
return 1;
}
#endif
// [D] [T]
void UpdateSpool(void)
{
CdlLOC pos;
SPOOLQ* current;
SPOOLQ *current = &spooldata[spoolpos_reading];
#if defined(SIMPLE_SPOOL)
if (UpdateSpoolPC())
return;
#endif
if (!XAPrepared())
if (XAPrepared())
return;
current = &spooldata[spoolpos_reading];
target_address = current->addr;
if (current->type == 0) // SPOOLTYPE_REGIONS
{
target_address = current->addr;
sectors_this_chunk = current->nsectors;
sectors_to_read = spool_regioninfo[spool_regionpos].nsectors;
if (current->type == 0) // SPOOLTYPE_REGIONS
{
sectors_this_chunk = current->nsectors;
sectors_to_read = spool_regioninfo[spool_regionpos].nsectors;
CdDataCallback(data_cb_regions);
CdReadyCallback(ready_cb_regions);
}
else if (current->type == 1) // SPOOLTYPE_TEXTURES
{
nTPchunks_reading = 0;
nTPchunks_writing = 0;
sectors_to_read = 17;
ntpages = tsetcounter;
sectors_this_chunk = 1;
CdDataCallback(data_cb_textures);
CdReadyCallback(ready_cb_textures);
target_address += 0x4000;
}
else if (current->type == 3) // SPOOLTYPE_MISC
{
sectors_to_read = (current->nsectors);
CdDataCallback(data_cb_misc);
CdReadyCallback(ready_cb_misc);
}
current_sector = current->sector;
endchunk = 0;
switch_spooltype = 0;
// run sector reading
CdIntToPos(current_sector, &pos);
CdControlF(CdlReadS, (u_char*)&pos);
CdDataCallback(data_cb_regions);
CdReadyCallback(ready_cb_regions);
}
else if (current->type == 1) // SPOOLTYPE_TEXTURES
{
nTPchunks_reading = 0;
nTPchunks_writing = 0;
sectors_to_read = 17;
ntpages = tsetcounter;
sectors_this_chunk = 1;
CdDataCallback(data_cb_textures);
CdReadyCallback(ready_cb_textures);
target_address += 0x4000;
}
else if (current->type == 3) // SPOOLTYPE_MISC
{
sectors_to_read = (current->nsectors);
CdDataCallback(data_cb_misc);
CdReadyCallback(ready_cb_misc);
}
current_sector = current->sector;
endchunk = 0;
switch_spooltype = 0;
// run sector reading
CdIntToPos(current_sector, &pos);
CdControlF(CdlReadS, (u_char*)&pos);
}
// [D] [T]
@ -1616,14 +1622,16 @@ int RoadMapRegions[4];
// [D] [T]
void UnpackRegion(int region_to_unpack, int target_barrel_region)
{
if (loading_region[target_barrel_region] == -1)
if (loading_region[target_barrel_region] != -1)
{
if (LoadRegionData(region_to_unpack, target_barrel_region))
spool_regioncounter++;
regions_unpacked[target_barrel_region] = region_to_unpack;
RoadMapRegions[target_barrel_region] = region_to_unpack;
return;
}
if (LoadRegionData(region_to_unpack, target_barrel_region))
spool_regioncounter++;
regions_unpacked[target_barrel_region] = region_to_unpack;
RoadMapRegions[target_barrel_region] = region_to_unpack;
}
@ -1710,7 +1718,7 @@ void CleanModelSpooled(void)
}
// memcpy
while (loadaddr < (int*)(specLoadBuffer + 2048))
while (loadaddr < (int*)(specLoadBuffer + CDSECTOR_SIZE))
*modelMemory++ = *loadaddr++;
mem = (int*)((int)gCarCleanModelPtr[4] + gCarCleanModelPtr[4]->poly_block); // [A] pls check, might be invalid
@ -1759,7 +1767,7 @@ void DamagedModelSpooled(void)
}
// memcpy
while (loadaddr < (int*)(specLoadBuffer + 2048))
while (loadaddr < (int*)(specLoadBuffer + CDSECTOR_SIZE))
*modelMemory++ = *loadaddr++;
mem = (int*)((int)gCarDamModelPtr[4] + gCarDamModelPtr[4]->poly_block); // [A] pls check, might be invalid
@ -1771,7 +1779,7 @@ void DamagedModelSpooled(void)
{
// [A] vertices
LoadCarModelFromFile((char*)gCarDamModelPtr[4], MissionHeader->residentModels[4], CAR_MODEL_DAMAGED);
}
}
#endif
specBlocksToLoad = 0;
@ -1806,7 +1814,7 @@ void LowModelSpooled(void)
}
// memcpy
while (loadaddr < (int*)(specLoadBuffer + 2048))
while (loadaddr < (int*)(specLoadBuffer + CDSECTOR_SIZE))
*modelMemory++ = *loadaddr++;
mem = (int*)((int)gCarLowModelPtr[4] + gCarLowModelPtr[4]->poly_block); // [A] pls check, might be invalid
@ -1850,7 +1858,7 @@ void CleanSpooled(void)
int size_2 = ((int *)specmallocptr)[1];
int size_3 = ((int *)specmallocptr)[2];
lastCleanBlock = size_1 + 2048 + 11;
lastCleanBlock = size_1 + CDSECTOR_SIZE + 11;
lastCleanBlock >>= 11;
firstDamBlock = size_1 + 12;
@ -1859,17 +1867,17 @@ void CleanSpooled(void)
firstLowBlock = size_1 + size_2 + 12;
firstLowBlock >>= 11;
int lastDamBlock = size_1 + size_2 + 2048 + 11;
int lastDamBlock = size_1 + size_2 + CDSECTOR_SIZE + 11;
lastDamBlock >>= 11;
lengthDamBlock = lastDamBlock - firstDamBlock;
damOffset = size_1 - (firstDamBlock * 2048 - 12);
damOffset = size_1 - (firstDamBlock * CDSECTOR_SIZE - 12);
int lastLowBlock = size_1 + size_2 + size_3 + 2048 + 11;
int lastLowBlock = size_1 + size_2 + size_3 + CDSECTOR_SIZE + 11;
lastLowBlock >>= 11;
lengthLowBlock = lastLowBlock - firstLowBlock;
lowOffset = size_1 + size_2 - (firstLowBlock * 2048 - 12);
lowOffset = size_1 + size_2 - (firstLowBlock * CDSECTOR_SIZE - 12);
}
model = (MODEL *)(specmallocptr + 12);
@ -2030,7 +2038,7 @@ void SpecialStartNextBlock(void)
specialState++;
}
fileSector = 0x1400 + (citystart[GameLevel] - SpoolLumpOffset / 2048) + (specspooldata[2]-1) * 42;
fileSector = 0x1400 + (citystart[GameLevel] - SpoolLumpOffset / CDSECTOR_SIZE) + (specspooldata[2]-1) * 42;
switch (specialState)
{
@ -2052,12 +2060,12 @@ void SpecialStartNextBlock(void)
case 5:
spoolFunc = CleanSpooled;
fileSector += (41 - specBlocksToLoad);
loadaddr = specmallocptr + (7 - specBlocksToLoad) * 2048;
loadaddr = specmallocptr + (7 - specBlocksToLoad) * CDSECTOR_SIZE;
break;
case 6:
spoolFunc = LowSpooled;
fileSector += ((firstLowBlock + lengthLowBlock) - specBlocksToLoad) + 34;
loadaddr = specmallocptr + (lengthLowBlock - specBlocksToLoad) * 2048;
loadaddr = specmallocptr + (lengthLowBlock - specBlocksToLoad) * CDSECTOR_SIZE;
break;
case 7:
spoolFunc = CleanModelSpooled;

View File

@ -170,6 +170,7 @@ XYPAIR citylumps[8][4];
#ifndef PSX
int gContentOverride = 1; // use unpacked filesystem?
char g_CurrentLevelFileName[64];
char* g_CurrentLevelSpoolData = NULL;
#endif // !PSX
// TODO: to game vars
@ -373,7 +374,7 @@ int LoadfileSeg(char* name, char* addr, int offset, int loadsize)
int remainingOffset;
int sector;
u_char result[8];
char sectorbuffer[2048];
char sectorbuffer[CDSECTOR_SIZE];
CdlLOC pos;
sprintf(namebuffer, "\\%s%s;1", gDataFolder, name);
@ -395,7 +396,7 @@ int LoadfileSeg(char* name, char* addr, int offset, int loadsize)
remainingBytes = loadsize;
// seek to the sector
sector = offset / 2048 + CdPosToInt(&currentfileinfo.pos);
sector = offset / CDSECTOR_SIZE + CdPosToInt(&currentfileinfo.pos);
// start reading sectors from CD
while(remainingBytes > 0)
@ -405,7 +406,7 @@ int LoadfileSeg(char* name, char* addr, int offset, int loadsize)
// if we don't have offset or we have more than 2048 bytes
// - we can read into buffer directly (which is faster)
if (remainingBytes >= 2048 && remainingOffset == 0)
if (remainingBytes >= CDSECTOR_SIZE && remainingOffset == 0)
sectorPtr = addr;
else
sectorPtr = sectorbuffer;
@ -428,7 +429,7 @@ int LoadfileSeg(char* name, char* addr, int offset, int loadsize)
// copy bytes
while (remainingBytes > 0 &&
readPtr - sectorbuffer < 2048) // don't leave boundary
readPtr - sectorbuffer < CDSECTOR_SIZE) // don't leave boundary
{
*addr++ = *readPtr++;
remainingBytes--;
@ -438,8 +439,8 @@ int LoadfileSeg(char* name, char* addr, int offset, int loadsize)
}
else
{
addr += 2048;
remainingBytes -= 2048;
addr += CDSECTOR_SIZE;
remainingBytes -= CDSECTOR_SIZE;
}
// go to next sector
@ -499,7 +500,7 @@ void sector_ready(u_char intr, u_char* result)
// read sector data
CdGetSector(current_address, SECTOR_SIZE);
current_address += 2048;
current_address += CDSECTOR_SIZE;
current_sector++;
sectors_left--;
@ -528,6 +529,44 @@ void sector_ready(u_char intr, u_char* result)
}
}
#if USE_PC_FILESYSTEM
// It has to be this way
int loadsectorsPC(char* addr, int sector, int nsectors)
{
char namebuffer[64];
strcpy(namebuffer, g_CurrentLevelFileName);
FS_FixPathSlashes(namebuffer);
FILE* fp = fopen(namebuffer, "rb");
if (fp)
{
// constrain nsectors to the maximum that can be read from the file
int maxSectors;
fseek(fp, 0, SEEK_END);
maxSectors = (ftell(fp) - (sector * CDSECTOR_SIZE)) / CDSECTOR_SIZE;
nsectors = MIN(nsectors, maxSectors);
fseek(fp, sector * CDSECTOR_SIZE, SEEK_SET);
fread(addr, CDSECTOR_SIZE, nsectors, fp);
fclose(fp);
ShowLoading();
return 1;
}
#ifndef __EMSCRIPTEN__
char errPrint[512];
sprintf(errPrint, "loadsectorsPC: failed to open '%s'\n", namebuffer);
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "ERROR", errPrint, NULL);
#endif // !__EMSCRIPTEN__
return 0;
}
#endif // USE_PC_FILESYSTEM
// [D] [T]
void loadsectors(char* addr, int sector, int nsectors)
{
@ -537,6 +576,11 @@ void loadsectors(char* addr, int sector, int nsectors)
if (nsectors == 0)
return;
#if USE_PC_FILESYSTEM
if (loadsectorsPC(addr, sector, nsectors))
return;
#endif
load_complete = 0;
endread = 0;
@ -561,39 +605,6 @@ void loadsectors(char* addr, int sector, int nsectors)
ShowLoading();
}
#if USE_PC_FILESYSTEM
// It has to be this way
void loadsectorsPC(char* filename, char* addr, int sector, int nsectors)
{
char namebuffer[64];
strcpy(namebuffer, filename);
FS_FixPathSlashes(namebuffer);
FILE* fp = fopen(namebuffer, "rb");
if (fp)
{
fseek(fp, sector * CDSECTOR_SIZE, SEEK_SET);
fread(addr, CDSECTOR_SIZE, nsectors, fp);
fclose(fp);
ShowLoading();
return;
}
#if USE_CD_FILESYSTEM
// try using CD
loadsectors(addr, sector, nsectors);
#elif !defined(__EMSCRIPTEN__)
char errPrint[512];
sprintf(errPrint, "loadsectorsPC: failed to open '%s'\n", namebuffer);
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "ERROR", errPrint, NULL);
#endif // USE_CD_FILESYSTEM
}
#endif // USE_PC_FILESYSTEM
// [D] [T]
void EnableDisplay(void)
{
@ -854,6 +865,11 @@ void ResetCityType(void)
{
lasttype = (CITYTYPE)-1;
lastcity = -1;
#ifndef PSX
free(g_CurrentLevelSpoolData);
g_CurrentLevelSpoolData = NULL;
#endif // PSX
}
// [A]
@ -872,6 +888,8 @@ void SetCityType(CITYTYPE type)
if (type == lasttype && GameLevel == lastcity)
return;
ResetCityType();
lastcity = GameLevel;
lasttype = type;
@ -903,11 +921,11 @@ void SetCityType(CITYTYPE type)
// store level name as it's required by loadsectorsPC
strcpy(g_CurrentLevelFileName, filename);
// spool position is forced to 0
citystart[GameLevel] = 0;
// skip LUMP type (37) and size, it's already hardcoded
fseek(levFp, 8, SEEK_CUR);
fread(citylumps[GameLevel], 1, sizeof(citylumps[GameLevel]), levFp);
fclose(levFp);
@ -963,7 +981,7 @@ void SetCityType(CITYTYPE type)
for (i = 0; i < 4; i++)
{
citylumps[GameLevel][i].x = data[0] + sector * 2048;
citylumps[GameLevel][i].x = data[0] + sector * CDSECTOR_SIZE;
citylumps[GameLevel][i].y = data[1];
data += 2;

View File

@ -136,11 +136,7 @@ extern int LoadfileSeg(char *name, char *addr, int offset, int loadsize); // 0x0
extern void ReportMode(int on); // 0x0007F8B8
#ifdef PSX
extern void loadsectors(char *addr, int sector, int nsectors); // 0x0007F904
#else
extern void loadsectorsPC(char* filename, char *addr, int sector, int nsectors);
#endif // PSX
extern void EnableDisplay(); // 0x0007F984
extern void DisableDisplay(); // 0x0007F9F0

View File

@ -484,11 +484,7 @@ void LoadPermanentTPages(int *sector)
for (i = 0; i < nperms; i++)
nsectors += (permlist[i].y + 2047) / CDSECTOR_SIZE;
#ifdef PSX
loadsectors(tpagebuffer, *sector, nsectors);
#else
loadsectorsPC(g_CurrentLevelFileName, tpagebuffer, *sector, nsectors);
#endif // PSX
*sector += nsectors;
@ -532,12 +528,7 @@ void LoadPermanentTPages(int *sector)
for (i = 0; i < nspecpages; i++)
nsectors += (speclist[i].y + 2047) / CDSECTOR_SIZE;
#ifdef PSX
loadsectors(tpagebuffer, *sector, nsectors);
#else
loadsectorsPC(g_CurrentLevelFileName, tpagebuffer, *sector, nsectors);
#endif // PSX
*sector += nsectors;