From b804589f8125044d6b184720e7cf3efe55a3ace8 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 25 Jul 2020 22:47:46 +0200 Subject: [PATCH] - implemented a proper cache for Blood's SEQs. Messing around in the file system cache should be a no-go, so now it's no longer done. This also allows reenabling the byte swapping needed for Big Endian. --- source/blood/src/actor.cpp | 16 +++--- source/blood/src/ai.cpp | 2 +- source/blood/src/aiunicult.cpp | 64 ++++++++++++++---------- source/blood/src/blood.cpp | 4 -- source/blood/src/blood.h | 1 - source/blood/src/callback.cpp | 4 +- source/blood/src/nnexts.cpp | 7 ++- source/blood/src/player.cpp | 2 +- source/blood/src/resource.cpp | 38 -------------- source/blood/src/seq.cpp | 90 ++++++++++++++++++++++++++-------- source/blood/src/seq.h | 5 +- 11 files changed, 126 insertions(+), 107 deletions(-) diff --git a/source/blood/src/actor.cpp b/source/blood/src/actor.cpp index 7a3c8b0b8..206b5c72b 100644 --- a/source/blood/src/actor.cpp +++ b/source/blood/src/actor.cpp @@ -2498,8 +2498,8 @@ void actInit(bool bSaveLoad) { case kThingBloodChunks: { SEQINST *pInst = GetInstance(3, pSprite->extra); if (pInst && pInst->at13) { - DICTNODE *hSeq = gSysRes.Lookup(pInst->at8, "SEQ"); - if (!hSeq) break; + auto seq = getSequence(pInst->at8); + if (!seq) break; seqSpawn(pInst->at8, 3, pSprite->extra); } break; @@ -2577,7 +2577,7 @@ void actInit(bool bSaveLoad) { } - if (gSysRes.Lookup(seqStartId, "SEQ")) seqSpawn(seqStartId, 3, pSprite->extra); + if (getSequence(seqStartId)) seqSpawn(seqStartId, 3, pSprite->extra); } aiInit(); } @@ -2966,7 +2966,7 @@ void actKillDude(int nKillerSprite, spritetype *pSprite, DAMAGE_TYPE damageType, playGenDudeSound(pSprite, kGenDudeSndTransforming); int seqId = pXSprite->data2 + kGenDudeSeqTransform; - if (gSysRes.Lookup(seqId, "SEQ")) seqSpawn(seqId, 3, nXSprite, -1); + if (getSequence(seqId)) seqSpawn(seqId, 3, nXSprite, -1); else { seqKill(3, nXSprite); spritetype* pEffect = gFX.fxSpawn((FX_ID)52, pSprite->sectnum, pSprite->x, pSprite->y, pSprite->z, pSprite->ang); @@ -3152,7 +3152,7 @@ void actKillDude(int nKillerSprite, spritetype *pSprite, DAMAGE_TYPE damageType, break; } - if (!gSysRes.Lookup(getDudeInfo(nType+kDudeBase)->seqStartID + nSeq, "SEQ")) + if (!getSequence(getDudeInfo(nType+kDudeBase)->seqStartID + nSeq)) { seqKill(3, nXSprite); gKillMgr.AddKill(pSprite); @@ -3227,7 +3227,7 @@ void actKillDude(int nKillerSprite, spritetype *pSprite, DAMAGE_TYPE damageType, if (pExtra->availDeaths[kDmgBurn] == 3) seqSpawn((15 + Random(2)) + pXSprite->data2, 3, nXSprite, dudeToGib); else if (pExtra->availDeaths[kDmgBurn] == 2) seqSpawn(16 + pXSprite->data2, 3, nXSprite, dudeToGib); else if (pExtra->availDeaths[kDmgBurn] == 1) seqSpawn(15 + pXSprite->data2, 3, nXSprite, dudeToGib); - else if (gSysRes.Lookup(pXSprite->data2 + nSeq, "SEQ"))seqSpawn(nSeq + pXSprite->data2, 3, nXSprite, dudeToGib); + else if (getSequence(pXSprite->data2 + nSeq))seqSpawn(nSeq + pXSprite->data2, 3, nXSprite, dudeToGib); else seqSpawn(1 + pXSprite->data2, 3, nXSprite, dudeToGib); } else { @@ -5344,7 +5344,7 @@ void actExplodeSprite(spritetype *pSprite) } #endif - if (gSysRes.Lookup(nSeq, "SEQ")) + if (getSequence(nSeq)) seqSpawn(nSeq, 3, nXSprite, -1); sfxPlay3DSound(pSprite, nSnd, -1, 0); @@ -6110,7 +6110,7 @@ spritetype *actSpawnDude(spritetype *pSource, short nType, int a3, int a4) pSprite2->clipdist = getDudeInfo(nDude+kDudeBase)->clipdist; pXSprite2->health = getDudeInfo(nDude+kDudeBase)->startHealth<<4; pXSprite2->respawn = 1; - if (gSysRes.Lookup(getDudeInfo(nDude+kDudeBase)->seqStartID, "SEQ")) + if (getSequence(getDudeInfo(nDude+kDudeBase)->seqStartID)) seqSpawn(getDudeInfo(nDude+kDudeBase)->seqStartID, 3, pSprite2->extra, -1); #ifdef NOONE_EXTENSIONS diff --git a/source/blood/src/ai.cpp b/source/blood/src/ai.cpp index 35552bc8c..d9abaceee 100644 --- a/source/blood/src/ai.cpp +++ b/source/blood/src/ai.cpp @@ -94,7 +94,7 @@ void aiNewState(spritetype *pSprite, XSPRITE *pXSprite, AISTATE *pAIState) if (pAIState->seqId >= 0) { seqStartId += pAIState->seqId; - if (gSysRes.Lookup(seqStartId, "SEQ")) + if (getSequence(seqStartId)) seqSpawn(seqStartId, 3, pSprite->extra, pAIState->funcId); } diff --git a/source/blood/src/aiunicult.cpp b/source/blood/src/aiunicult.cpp index 45a308b83..60c211d83 100644 --- a/source/blood/src/aiunicult.cpp +++ b/source/blood/src/aiunicult.cpp @@ -1110,7 +1110,7 @@ void aiGenDudeNewState(spritetype* pSprite, AISTATE* pAIState) { pXSprite->stateTimer = pAIState->stateTicks; pXSprite->aiState = pAIState; int stateSeq = pXSprite->data2 + pAIState->seqId; - if (pAIState->seqId >= 0 && gSysRes.Lookup(stateSeq, "SEQ")) { + if (pAIState->seqId >= 0 && getSequence(stateSeq)) { seqSpawn(stateSeq, 3, pSprite->extra, pAIState->funcId); } @@ -1460,10 +1460,13 @@ void scaleDamage(XSPRITE* pXSprite) { //viewSetSystemMessage("0: %d, 1: %d, 2: %d, 3: %d, 4: %d, 5: %d, 6: %d", dc[0], dc[1], dc[2], dc[3], dc[4], dc[5], dc[6]); } -int getDispersionModifier(spritetype* pSprite, int minDisp, int maxDisp) { +int getDispersionModifier(spritetype* pSprite, int minDisp, int maxDisp) +{ // the faster fire rate, the less frames = more dispersion - Seq* pSeq = NULL; DICTNODE* hSeq = gSysRes.Lookup(xsprite[pSprite->extra].data2 + 6, "SEQ"); int disp = 1; - if (hSeq != NULL && (pSeq = (Seq*)gSysRes.Load(hSeq)) != NULL) { + Seq* pSeq = getSequence(xsprite[pSprite->extra].data2 + 6); + int disp = 1; + if (pSeq != nullptr) + { int nFrames = pSeq->nFrames; int ticks = pSeq->at8; int shots = 0; for (int i = 0; i <= pSeq->nFrames; i++) { if (pSeq->frames[i].at5_5) shots++; @@ -1487,9 +1490,8 @@ int getRangeAttackDist(spritetype* pSprite, int minDist, int maxDist) { if (yrepeat > 0) { if (seqId >= 0) { - Seq* pSeq = NULL; DICTNODE* hSeq = gSysRes.Lookup(seqId, "SEQ"); - if (hSeq) { - pSeq = (Seq*)gSysRes.Load(hSeq); + Seq* pSeq = getSequence(seqId); + if (pSeq) { picnum = seqGetTile(&pSeq->frames[0]); } } @@ -1974,7 +1976,7 @@ bool genDudePrepare(spritetype* pSprite, int propId) { } pExtra->canAttack = false; - if (pExtra->curWeapon > 0 && gSysRes.Lookup(pXSprite->data2 + kGenDudeSeqAttackNormalL, "SEQ")) + if (pExtra->curWeapon > 0 && getSequence(pXSprite->data2 + kGenDudeSeqAttackNormalL)) pExtra->canAttack = true; pExtra->weaponType = kGenDudeWeaponNone; @@ -2033,45 +2035,54 @@ bool genDudePrepare(spritetype* pSprite, int propId) { case kGenDudeSeqAttackNormalL: case kGenDudeSeqAttackThrow: case kGenDudeSeqAttackPunch: - if (!gSysRes.Lookup(i, "SEQ")) { + { + Seq* pSeq = getSequence(i); + if (!pSeq) + { pXSprite->data2 = getDudeInfo(pSprite->type)->seqStartID; viewSetSystemMessage("No SEQ animation id %d found for custom dude #%d!", i, pSprite->index); viewSetSystemMessage("SEQ base id: %d", seqStartId); - } else if ((i - seqStartId) == kGenDudeSeqAttackPunch) { + } + else if ((i - seqStartId) == kGenDudeSeqAttackPunch) + { pExtra->forcePunch = true; // required for those who don't have fire trigger in punch seq and for default animation - Seq* pSeq = NULL; DICTNODE* hSeq = gSysRes.Lookup(i, "SEQ"); - pSeq = (Seq*)gSysRes.Load(hSeq); for (int i = 0; i < pSeq->nFrames; i++) { if (!pSeq->frames[i].at5_5) continue; pExtra->forcePunch = false; break; - } + } } break; + } case kGenDudeSeqDeathExplode: - pExtra->availDeaths[kDmgExplode] = (bool)gSysRes.Lookup(i, "SEQ"); + pExtra->availDeaths[kDmgExplode] = !!getSequence(i); break; case kGenDudeSeqBurning: - pExtra->canBurn = gSysRes.Lookup(i, "SEQ"); + pExtra->canBurn = !!getSequence(i); break; case kGenDudeSeqElectocuted: - pExtra->canElectrocute = gSysRes.Lookup(i, "SEQ"); + pExtra->canElectrocute = !!getSequence(i); break; case kGenDudeSeqRecoil: - pExtra->canRecoil = gSysRes.Lookup(i, "SEQ"); + pExtra->canRecoil = !!getSequence(i); break; case kGenDudeSeqMoveL: { bool oldStatus = pExtra->canWalk; - pExtra->canWalk = gSysRes.Lookup(i, "SEQ"); + pExtra->canWalk = !!getSequence(i); if (oldStatus != pExtra->canWalk) { - if (!spriRangeIsFine(pXSprite->target)) { + if (!spriRangeIsFine(pXSprite->target)) + { if (spriteIsUnderwater(pSprite, false)) aiGenDudeNewState(pSprite, &genDudeIdleW); else aiGenDudeNewState(pSprite, &genDudeIdleL); - } else if (pExtra->canWalk) { + } + else if (pExtra->canWalk) + { if (spriteIsUnderwater(pSprite, false)) aiGenDudeNewState(pSprite, &genDudeChaseW); else if (inDuck(pXSprite->aiState)) aiGenDudeNewState(pSprite, &genDudeChaseD); else aiGenDudeNewState(pSprite, &genDudeChaseL); - } else { + } + else + { if (spriteIsUnderwater(pSprite, false)) aiGenDudeNewState(pSprite, &genDudeChaseNoWalkW); else if (inDuck(pXSprite->aiState)) aiGenDudeNewState(pSprite, &genDudeChaseNoWalkD); else aiGenDudeNewState(pSprite, &genDudeChaseNoWalkL); @@ -2080,12 +2091,13 @@ bool genDudePrepare(spritetype* pSprite, int propId) { break; } case kGenDudeSeqAttackNormalDW: - pExtra->canDuck = (gSysRes.Lookup(i, "SEQ") && gSysRes.Lookup(seqStartId + 14, "SEQ")); - pExtra->canSwim = (gSysRes.Lookup(i, "SEQ") && gSysRes.Lookup(seqStartId + 13, "SEQ") - && gSysRes.Lookup(seqStartId + 17, "SEQ")); + pExtra->canDuck = (getSequence(i) && getSequence(seqStartId + 14)); + pExtra->canSwim = (getSequence(i) && getSequence(seqStartId + 13) + && getSequence(seqStartId + 17)); break; case kGenDudeSeqDeathBurn1: { - bool seq15 = gSysRes.Lookup(i, "SEQ"); bool seq16 = gSysRes.Lookup(seqStartId + 16, "SEQ"); + bool seq15 = getSequence(i); + bool seq16 = getSequence(seqStartId + 16); if (seq15 && seq16) pExtra->availDeaths[kDmgBurn] = 3; else if (seq16) pExtra->availDeaths[kDmgBurn] = 2; else if (seq15) pExtra->availDeaths[kDmgBurn] = 1; @@ -2103,7 +2115,7 @@ bool genDudePrepare(spritetype* pSprite, int propId) { case kGenDudeSeqReserved6: case kGenDudeSeqReserved7: case kGenDudeSeqReserved8: - /*if (gSysRes.Lookup(i, "SEQ")) { + /*if (getSequence(i)) { viewSetSystemMessage("Found reserved SEQ animation (%d) for custom dude #%d!", i, pSprite->index); viewSetSystemMessage("Using reserved animation is not recommended."); viewSetSystemMessage("SEQ base id: %d", seqStartId); diff --git a/source/blood/src/blood.cpp b/source/blood/src/blood.cpp index 801bbd333..6bcef018b 100644 --- a/source/blood/src/blood.cpp +++ b/source/blood/src/blood.cpp @@ -1782,10 +1782,6 @@ bool VanillaMode() { return gDemo.m_bLegacy && gDemo.at1; } -bool fileExistsRFF(int id, const char *ext) { - return gSysRes.Lookup(id, ext); -} - int sndTryPlaySpecialMusic(int nMusic) { if (Mus_Play(nullptr, quoteMgr.GetQuote(nMusic), true)) diff --git a/source/blood/src/blood.h b/source/blood/src/blood.h index 97878d64d..c1383a9a2 100644 --- a/source/blood/src/blood.h +++ b/source/blood/src/blood.h @@ -132,7 +132,6 @@ void ProcessFrame(void); void ScanINIFiles(void); bool DemoRecordStatus(void); bool VanillaMode(void); -bool fileExistsRFF(int id, const char* ext); int sndTryPlaySpecialMusic(int nMusic); void sndPlaySpecialMusicOrNothing(int nMusic); diff --git a/source/blood/src/callback.cpp b/source/blood/src/callback.cpp index 96f8e692d..cea99e69d 100644 --- a/source/blood/src/callback.cpp +++ b/source/blood/src/callback.cpp @@ -275,7 +275,7 @@ void Respawn(int nSprite) // 9 switch (pSprite->type) { default: pSprite->clipdist = getDudeInfo(nType + kDudeBase)->clipdist; - if (gSysRes.Lookup(getDudeInfo(nType + kDudeBase)->seqStartID, "SEQ")) + if (getSequence(getDudeInfo(nType + kDudeBase)->seqStartID)) seqSpawn(getDudeInfo(nType + kDudeBase)->seqStartID, 3, pSprite->extra, -1); break; case kDudeModernCustom: @@ -285,7 +285,7 @@ void Respawn(int nSprite) // 9 #else pSprite->clipdist = getDudeInfo(nType + kDudeBase)->clipdist; pXSprite->health = getDudeInfo(nType + kDudeBase)->startHealth << 4; - if (gSysRes.Lookup(getDudeInfo(nType + kDudeBase)->seqStartID, "SEQ")) + if (getSequence(getDudeInfo(nType + kDudeBase)->seqStartID)) seqSpawn(getDudeInfo(nType + kDudeBase)->seqStartID, 3, pSprite->extra, -1); #endif aiInitSprite(pSprite); diff --git a/source/blood/src/nnexts.cpp b/source/blood/src/nnexts.cpp index 7c6372f8f..8b38ff244 100644 --- a/source/blood/src/nnexts.cpp +++ b/source/blood/src/nnexts.cpp @@ -948,10 +948,9 @@ int getSpriteMassBySize(spritetype* pSprite) { short massDiv = 30; short addMul = 2; short subMul = 2; if (seqId >= 0) { - DICTNODE* hSeq = gSysRes.Lookup(seqId, "SEQ"); - if (hSeq) + auto pSeq = getSequence(seqId); + if (pSeq) { - pSeq = (Seq*)gSysRes.Load(hSeq); picnum = seqGetTile(&pSeq->frames[0]); } else picnum = pSprite->picnum; @@ -2326,7 +2325,7 @@ void useSpriteDamager(XSPRITE* pXSource, spritetype* pSprite) { void useSeqSpawnerGen(XSPRITE* pXSource, int objType, int index) { - if (pXSource->data2 > 0 && !gSysRes.Lookup(pXSource->data2, "SEQ")) { + if (pXSource->data2 > 0 && !getSequence(pXSource->data2)) { consoleSysMsg("Missing sequence #%d", pXSource->data2); return; } diff --git a/source/blood/src/player.cpp b/source/blood/src/player.cpp index 38d25d4d7..802864a00 100644 --- a/source/blood/src/player.cpp +++ b/source/blood/src/player.cpp @@ -2121,7 +2121,7 @@ int playerDamageSprite(int nSource, PLAYER *pPlayer, DAMAGE_TYPE nDamageType, in FragPlayer(pPlayer, nSource); trTriggerSprite(nSprite, pXSprite, kCmdOff); } - dassert(gSysRes.Lookup(pDudeInfo->seqStartID + nDeathSeqID, "SEQ") != NULL); + dassert(getSequence(pDudeInfo->seqStartID + nDeathSeqID) != NULL); seqSpawn(pDudeInfo->seqStartID+nDeathSeqID, 3, nXSprite, nKneelingPlayer); return nDamage; } diff --git a/source/blood/src/resource.cpp b/source/blood/src/resource.cpp index a897a3554..23e7cab56 100644 --- a/source/blood/src/resource.cpp +++ b/source/blood/src/resource.cpp @@ -73,44 +73,6 @@ void ByteSwapQAV(void *p) } } -void ByteSwapSEQ(void *p) -{ - Seq *pSeq = (Seq*)p; - pSeq->version = B_LITTLE16(pSeq->version); - pSeq->nFrames = B_LITTLE16(pSeq->nFrames); - pSeq->at8 = B_LITTLE16(pSeq->at8); - pSeq->ata = B_LITTLE16(pSeq->ata); - pSeq->atc = B_LITTLE32(pSeq->atc); - for (int i = 0; i < pSeq->nFrames; i++) - { - SEQFRAME *pFrame = &pSeq->frames[i]; - BitReader bitReader((char *)pFrame, sizeof(SEQFRAME)); - SEQFRAME swapFrame; - swapFrame.tile = bitReader.readUnsigned(12); - swapFrame.at1_4 = bitReader.readBit(); - swapFrame.at1_5 = bitReader.readBit(); - swapFrame.at1_6 = bitReader.readBit(); - swapFrame.at1_7 = bitReader.readBit(); - swapFrame.at2_0 = bitReader.readUnsigned(8); - swapFrame.at3_0 = bitReader.readUnsigned(8); - swapFrame.at4_0 = bitReader.readSigned(8); - swapFrame.at5_0 = bitReader.readUnsigned(5); - swapFrame.at5_5 = bitReader.readBit(); - swapFrame.at5_6 = bitReader.readBit(); - swapFrame.at5_7 = bitReader.readBit(); - swapFrame.at6_0 = bitReader.readBit(); - swapFrame.at6_1 = bitReader.readBit(); - swapFrame.at6_2 = bitReader.readBit(); - swapFrame.at6_3 = bitReader.readBit(); - swapFrame.at6_4 = bitReader.readBit(); - swapFrame.tile2 = bitReader.readUnsigned(4); - swapFrame.soundRange = bitReader.readUnsigned(4); - swapFrame.surfaceSound = bitReader.readBit(); - swapFrame.reserved = bitReader.readUnsigned(2); - *pFrame = swapFrame; - } -} - void ByteSwapSFX(void *p) { SFX *pSFX = (SFX*)p; diff --git a/source/blood/src/seq.cpp b/source/blood/src/seq.cpp index a354b0af7..b9b19e726 100644 --- a/source/blood/src/seq.cpp +++ b/source/blood/src/seq.cpp @@ -79,11 +79,8 @@ void Seq::Precache(void) void seqPrecacheId(int id) { - DICTNODE *hSeq = gSysRes.Lookup(id, "SEQ"); - if (!hSeq) - return; - Seq *pSeq = (Seq*)gSysRes.Load(hSeq); - pSeq->Precache(); + auto pSeq = getSequence(id); + if (pSeq) pSeq->Precache(); } SEQINST siWall[kMaxXWalls]; @@ -371,9 +368,7 @@ SEQINST * GetInstance(int a1, int a2) void UnlockInstance(SEQINST *pInst) { dassert(pInst != NULL); - dassert(pInst->hSeq != NULL); dassert(pInst->pSequence != NULL); - pInst->hSeq = NULL; pInst->pSequence = NULL; pInst->at13 = 0; } @@ -383,14 +378,14 @@ void seqSpawn(int a1, int a2, int a3, int a4) SEQINST *pInst = GetInstance(a2, a3); if (!pInst) return; - DICTNODE *hSeq = gSysRes.Lookup(a1, "SEQ"); - if (!hSeq) + auto pSeq = getSequence(a1); + if (!pSeq) ThrowError("Missing sequence #%d", a1); int i = activeCount; if (pInst->at13) { - if (hSeq == pInst->hSeq) + if (pSeq == pInst->pSequence) return; UnlockInstance(pInst); for (i = 0; i < activeCount; i++) @@ -400,7 +395,6 @@ void seqSpawn(int a1, int a2, int a3, int a4) } dassert(i < activeCount); } - Seq *pSeq = (Seq*)gSysRes.Load(hSeq); if (memcmp(pSeq->signature, "SEQ\x1a", 4) != 0) ThrowError("Invalid sequence %d", a1); if ((pSeq->version & 0xff00) != 0x300) @@ -411,7 +405,6 @@ void seqSpawn(int a1, int a2, int a3, int a4) pSeq->frames[i].tile2 = 0; } pInst->at13 = 1; - pInst->hSeq = hSeq; pInst->pSequence = pSeq; pInst->at8 = a1; pInst->atc = a4; @@ -557,21 +550,16 @@ void SeqLoadSave::Load(void) Read(&activeCount, sizeof(activeCount)); for (int i = 0; i < kMaxXWalls; i++) { - siWall[i].hSeq = NULL; - siMasked[i].hSeq = NULL; siWall[i].pSequence = NULL; siMasked[i].pSequence = NULL; } for (int i = 0; i < kMaxXSectors; i++) { - siCeiling[i].hSeq = NULL; - siFloor[i].hSeq = NULL; siCeiling[i].pSequence = NULL; siFloor[i].pSequence = NULL; } for (int i = 0; i < kMaxXSprites; i++) { - siSprite[i].hSeq = NULL; siSprite[i].pSequence = NULL; } for (int i = 0; i < activeCount; i++) @@ -580,17 +568,15 @@ void SeqLoadSave::Load(void) if (pInst->at13) { int nSeq = pInst->at8; - DICTNODE *hSeq = gSysRes.Lookup(nSeq, "SEQ"); - if (!hSeq) { + auto pSeq = getSequence(nSeq); + if (!pSeq) { ThrowError("Missing sequence #%d", nSeq); continue; } - Seq *pSeq = (Seq*)gSysRes.Load(hSeq); if (memcmp(pSeq->signature, "SEQ\x1a", 4) != 0) ThrowError("Invalid sequence %d", nSeq); if ((pSeq->version & 0xff00) != 0x300) ThrowError("Sequence %d is obsolete version", nSeq); - pInst->hSeq = hSeq; pInst->pSequence = pSeq; } } @@ -614,4 +600,66 @@ void SeqLoadSaveConstruct(void) myLoadSave = new SeqLoadSave(); } + +static void ByteSwapSEQ(Seq* pSeq) +{ + pSeq->version = B_LITTLE16(pSeq->version); + pSeq->nFrames = B_LITTLE16(pSeq->nFrames); + pSeq->at8 = B_LITTLE16(pSeq->at8); + pSeq->ata = B_LITTLE16(pSeq->ata); + pSeq->atc = B_LITTLE32(pSeq->atc); + for (int i = 0; i < pSeq->nFrames; i++) + { + SEQFRAME* pFrame = &pSeq->frames[i]; + BitReader bitReader((char*)pFrame, sizeof(SEQFRAME)); + SEQFRAME swapFrame; + swapFrame.tile = bitReader.readUnsigned(12); + swapFrame.at1_4 = bitReader.readBit(); + swapFrame.at1_5 = bitReader.readBit(); + swapFrame.at1_6 = bitReader.readBit(); + swapFrame.at1_7 = bitReader.readBit(); + swapFrame.at2_0 = bitReader.readUnsigned(8); + swapFrame.at3_0 = bitReader.readUnsigned(8); + swapFrame.at4_0 = bitReader.readSigned(8); + swapFrame.at5_0 = bitReader.readUnsigned(5); + swapFrame.at5_5 = bitReader.readBit(); + swapFrame.at5_6 = bitReader.readBit(); + swapFrame.at5_7 = bitReader.readBit(); + swapFrame.at6_0 = bitReader.readBit(); + swapFrame.at6_1 = bitReader.readBit(); + swapFrame.at6_2 = bitReader.readBit(); + swapFrame.at6_3 = bitReader.readBit(); + swapFrame.at6_4 = bitReader.readBit(); + swapFrame.tile2 = bitReader.readUnsigned(4); + swapFrame.soundRange = bitReader.readUnsigned(4); + swapFrame.surfaceSound = bitReader.readBit(); + swapFrame.reserved = bitReader.readUnsigned(2); + *pFrame = swapFrame; + } +} + + +// This is to eliminate a huge design issue in NBlood that was apparently copied verbatim from the DOS-Version. +// Sequences were cached in the resource and directly returned from there in writable form, with byte swapping directly performed in the cache on Big Endian systems. +// To avoid such unsafe operations this caches the read data separately in static memory that's guaranteed not to be touched by the file system. +FMemArena seqcache; +static TMap sequences; +Seq* getSequence(int res_id) +{ + auto p = sequences.CheckKey(res_id); + if (p != nullptr) return *p; + + int index = fileSystem.FindResource(res_id, "SEQ"); + if (index < 0) + { + return nullptr; + } + auto fr = fileSystem.OpenFileReader(index); + auto seqdata = (Seq*)seqcache.Alloc(fr.GetLength()); + fr.Read(seqdata, fr.GetLength()); + sequences.Insert(res_id, seqdata); + ByteSwapSEQ(seqdata); + return seqdata; +} + END_BLD_NS diff --git a/source/blood/src/seq.h b/source/blood/src/seq.h index 34029271b..52c333a8c 100644 --- a/source/blood/src/seq.h +++ b/source/blood/src/seq.h @@ -24,6 +24,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. BEGIN_BLD_NS + struct SEQFRAME { unsigned int tile : 12; unsigned int at1_4 : 1; // transparent @@ -68,7 +69,6 @@ struct ACTIVE struct SEQINST { - DICTNODE *hSeq; Seq *pSequence; int at8; int atc; @@ -94,4 +94,7 @@ int seqGetStatus(int a1, int a2); int seqGetID(int a1, int a2); void seqProcess(int a1); +Seq* getSequence(int res_id); + + END_BLD_NS