diff --git a/CMakeLists.txt b/CMakeLists.txt index 9def34b1..3c92c9b4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -47,12 +47,16 @@ endif() add_compile_definitions( $<$:WIN> $<$:DEBUG> - LITTLE_ENDIAN ) if (CMAKE_SIZEOF_VOID_P EQUAL 4) add_compile_definitions( $<$:IN_80386> + # IN_80386 implies LITTLE_ENDIAN + ) +else() + add_compile_definitions( + LITTLE_ENDIAN ) endif() diff --git a/inc/tagman.h b/inc/tagman.h index 30045c68..19327f79 100644 --- a/inc/tagman.h +++ b/inc/tagman.h @@ -44,6 +44,10 @@ const long ksidInvalid = -1; // negative SIDs imply an invalid TAG const long sidNil = 0; const long ksidUseCrf = 0; // chunk is in ptag->pcrf +PCRF RefToPcrf(ulong ref); +ulong PcrfToRef(PCRF pcrf); +void ReleasePpoPcrfRef(ulong* ref); + typedef struct TAG *PTAG; struct TAG { @@ -54,7 +58,8 @@ struct TAG #endif // DEBUG long sid; // Source ID (or ksidUseCrf) - PCRF pcrf; // File to look in for this chunk if sid is ksidUseCrf + //PCRF pcrf; // File to look in for this chunk if sid is ksidUseCrf + ulong pcrfRef; // An 8-byte pointer cannot be stored here, so use a ulong reference instead. CTG ctg; // CTG of chunk CNO cno; // CNO of chunk }; diff --git a/src/engine/actredit.cpp b/src/engine/actredit.cpp index 7dfd3b7f..0034b81e 100644 --- a/src/engine/actredit.cpp +++ b/src/engine/actredit.cpp @@ -758,7 +758,7 @@ bool ACTR::FPaste(long nfrm, SCEN *pscen) { return fFalse; } - if (pcrf != _tagTmpl.pcrf) + if (pcrf != RefToPcrf(_tagTmpl.pcrfRef)) { // Need to save this actor's tagTmpl in this movie because it came from another movie @@ -839,7 +839,7 @@ bool ACTR::FPaste(long nfrm, SCEN *pscen) if (aevsnd.tag.sid != ksidUseCrf) continue; // Save tag (this may be a new movie) - if (!aevsnd.tag.pcrf->Pcfl()->FFind(aevsnd.tag.ctg, aevsnd.tag.cno)) + if (!RefToPcrf(aevsnd.tag.pcrfRef)->Pcfl()->FFind(aevsnd.tag.ctg, aevsnd.tag.cno)) { PushErc(ercSocNoSndOnPaste); _RemoveAev(iaev); diff --git a/src/engine/modl.cpp b/src/engine/modl.cpp index 8ca22b7e..13f6408c 100644 --- a/src/engine/modl.cpp +++ b/src/engine/modl.cpp @@ -9,6 +9,7 @@ Review Status: REVIEWED - any changes to this file must be reviewed! ***************************************************************************/ +#include #include "soc.h" ASSERTNAME @@ -80,6 +81,40 @@ bool MODL::FReadModl(PCRF pcrf, CTG ctg, CNO cno, PBLCK pblck, PBACO *ppbaco, lo return fTrue; } +// Portable version of br_face for reading from files. +// Original comes from BRender model.h. +// br_material* material has been replaced with a ulong. +#pragma pack(4) +typedef struct BRF_IO +{ + br_uint_16 vertices[3]; /* Vertices around face */ + br_uint_16 edges[3]; /* Edges around face */ + ulong material; /* Face material (or NULL) */ + br_uint_16 smoothing; /* Controls if shared edges are smooth */ + br_uint_8 flags; /* Bits 0,1 and 2 denote internal edges */ + br_uint_8 _pad0; + br_fvector3 n; /* Plane equation of face */ + br_scalar d; +} BRF_IO; +#pragma pack() + +void BRF_IoToNative(BRF* dst, const BRF_IO* src, size_t count) +{ + for (size_t f = 0; f < count; f++) + { + for (int i = 0; i < 3; i++) + dst[f].vertices[i] = src[f].vertices[i]; + for (int i = 0; i < 3; i++) + dst[f].edges[i] = src[f].edges[i]; + dst[f].material = pvNil; + dst[f].smoothing = src[f].smoothing; + dst[f].flags = src[f].flags; + dst[f]._pad0 = src[f]._pad0; + dst[f].n = src[f].n; + dst[f].d = src[f].d; + } +} + /*************************************************************************** Reads a MODL from a BLCK ***************************************************************************/ @@ -109,9 +144,13 @@ bool MODL::_FInit(PBLCK pblck) SwapBytesBom(&modlf, kbomModlf); Assert(kboCur == modlf.bo, "bad MODL!"); + printf("size of MODLF == %d\n", (int)size(MODLF)); + printf("size of BRV == %d\n", (int)size(BRV)); + printf("size of BRF == %d\n", (int)size(BRF_IO)); + // Allocate space for the BMDL, array of vertices, and array of faces cbrgbrv = LwMul(modlf.cver, size(BRV)); - cbrgbrf = LwMul(modlf.cfac, size(BRF)); + cbrgbrf = LwMul(modlf.cfac, size(BRF_IO)); if (modlf.rRadius == rZero) { @@ -123,8 +162,16 @@ bool MODL::_FInit(PBLCK pblck) CopyPb(&pmodlThis, _pbmdl->identifier, size(PMODL)); if (!pblck->FReadRgb(_pbmdl->vertices, cbrgbrv, size(MODLF))) return fFalse; - if (!pblck->FReadRgb(_pbmdl->faces, cbrgbrf, size(MODLF) + cbrgbrv)) + BRF_IO* faces_io = new BRF_IO[modlf.cfac]; + if (!pblck->FReadRgb(faces_io, cbrgbrf, size(MODLF) + cbrgbrv)) + { + delete[] faces_io; return fFalse; + } + + BRF_IoToNative(_pbmdl->faces, faces_io, modlf.cfac); + + delete[] faces_io; BrModelAdd(_pbmdl); @@ -160,18 +207,25 @@ bool MODL::_FInit(PBLCK pblck) SwapBytesBom(pbrv, kbomBrv); } } - if (!pblck->FReadRgb(_pbmdl->prepared_faces, cbrgbrf, size(MODLF) + cbrgbrv)) + BRF_IO* prepared_faces_io = new BRF_IO[modlf.cfac]; + if (!pblck->FReadRgb(prepared_faces_io, cbrgbrf, size(MODLF) + cbrgbrv)) { + delete[] prepared_faces_io; return fFalse; } if (kboOther == modlf.bo) { - for (ibrf = 0, pbrf = _pbmdl->prepared_faces; ibrf < modlf.cfac; ibrf++, pbrf++) + BRF_IO* pbrf; + for (ibrf = 0, pbrf = prepared_faces_io; ibrf < modlf.cfac; ibrf++, pbrf++) { SwapBytesBom(pbrf, kbomBrf); } } + BRF_IoToNative(_pbmdl->prepared_faces, prepared_faces_io, modlf.cfac); + + delete[] prepared_faces_io; + _pbmdl->flags = BR_MODF_PREPREPARED; _pbmdl->nprepared_vertices = (ushort)modlf.cver; _pbmdl->nprepared_faces = (ushort)modlf.cfac; diff --git a/src/engine/movie.cpp b/src/engine/movie.cpp index c3a4fd56..38c94f96 100644 --- a/src/engine/movie.cpp +++ b/src/engine/movie.cpp @@ -6135,7 +6135,7 @@ void MVU::SetTagTool(PTAG ptag) // Make sure the new tag has been opened, if it's a "ksidUseCrf" tag if (ptag->sid == ksidUseCrf) { - AssertPo(ptag->pcrf, 0); + AssertPo(RefToPcrf(ptag->pcrfRef), 0); } #endif diff --git a/src/engine/scene.cpp b/src/engine/scene.cpp index 95dc1407..707c8526 100644 --- a/src/engine/scene.cpp +++ b/src/engine/scene.cpp @@ -7201,7 +7201,7 @@ void ReleasePpsse(PSSE *ppsse) for (itagc = 0; itagc < psse->ctagc; itagc++) { - if (psse->Ptag(itagc)->pcrf != pvNil) + if (psse->Ptag(itagc)->pcrfRef != pvNil) TAGM::CloseTag(psse->Ptag(itagc)); } @@ -7234,14 +7234,14 @@ PSSE SSE::PsseDupFromGg(PGG pgg, long iv, bool fDupTags) { if (psse->Ptag(itagc)->sid == ksidUseCrf) { - AssertPo(psse->Ptag(itagc)->pcrf, 0); + AssertPo(RefToPcrf(psse->Ptag(itagc)->pcrfRef), 0); TAGM::DupTag(psse->Ptag(itagc)); } } else { // Clear the crf on read, since the caller isn't having us dupe the tag - psse->Ptag(itagc)->pcrf = pvNil; + psse->Ptag(itagc)->pcrfRef = pvNil; } } diff --git a/src/engine/tagman.cpp b/src/engine/tagman.cpp index d1fd5df1..210a729e 100644 --- a/src/engine/tagman.cpp +++ b/src/engine/tagman.cpp @@ -38,9 +38,51 @@ short names. ***************************************************************************/ +#include #include "soc.h" ASSERTNAME +ulong g_nextPcrfRef = 1; // FIXME: handle/prevent overflow and generally make this more robust +// These two maps form a bidirectional map of refs and their corresponding PCRF's. +static std::map g_refToPcrfMap; +static std::map g_pcrfToRefMap; + +PCRF RefToPcrf(ulong ref) +{ + if (ref == 0) + return pvNil; + return g_refToPcrfMap[ref]; +} + +ulong PcrfToRef(PCRF pcrf) +{ + if (pcrf == pvNil) + return 0; + if (g_pcrfToRefMap.find(pcrf) == g_pcrfToRefMap.end()) + { + g_pcrfToRefMap[pcrf] = g_nextPcrfRef; + ++g_nextPcrfRef; + } + + return g_pcrfToRefMap[pcrf]; +} + +void ReleasePpoPcrfRef(ulong* ref) +{ + if (*ref != 0) + { + PCRF pcrf = g_refToPcrfMap[*ref]; + if (pcrf->CactRef() <= 1) + { + // PCRF will be deleted, remove it from the bimap. + g_pcrfToRefMap.erase(pcrf); + g_refToPcrfMap.erase(*ref); + } + ReleasePpo(&pcrf); + *ref = 0; + } +} + RTCLASS(TAGM) const BOM kbomSid = 0xc0000000; @@ -779,14 +821,14 @@ bool TAGM::FBuildChildTag(PTAG ptagPar, CHID chid, CTG ctgChild, PTAG ptagChild) if (ksidUseCrf == ptagPar->sid) { - AssertPo(ptagPar->pcrf, 0); - if (!ptagPar->pcrf->Pcfl()->FGetKidChidCtg(ptagPar->ctg, ptagPar->cno, chid, ctgChild, &kid)) + AssertPo(RefToPcrf(ptagPar->pcrfRef), 0); + if (!RefToPcrf(ptagPar->pcrfRef)->Pcfl()->FGetKidChidCtg(ptagPar->ctg, ptagPar->cno, chid, ctgChild, &kid)) { return fFalse; // child chunk not found } ptagChild->sid = ksidUseCrf; - ptagChild->pcrf = ptagPar->pcrf; - ptagPar->pcrf->AddRef(); + ptagChild->pcrfRef = ptagPar->pcrfRef; + RefToPcrf(ptagPar->pcrfRef)->AddRef(); ptagChild->ctg = kid.cki.ctg; ptagChild->cno = kid.cki.cno; return fTrue; @@ -890,8 +932,8 @@ PBACO TAGM::PbacoFetch(PTAG ptag, PFNRPO pfnrpo, bool fUseCD) { // Tag knows pcrf, so just read from there. Nothing we can do if // it's not there. - AssertPo(ptag->pcrf, 0); - return ptag->pcrf->PbacoFetch(ptag->ctg, ptag->cno, pfnrpo); + AssertPo(RefToPcrf(ptag->pcrfRef), 0); + return RefToPcrf(ptag->pcrfRef)->PbacoFetch(ptag->ctg, ptag->cno, pfnrpo); } // fTrue parameter ensures that _PcrmSourceGet won't hit the CD @@ -990,12 +1032,12 @@ bool TAGM::FOpenTag(PTAG ptag, PCRF pcrfDest, PCFL pcflSrc) { if (!pcflSrc->FCopy(ptag->ctg, ptag->cno, pcrfDest->Pcfl(), &cnoDest)) { - ptag->pcrf = pvNil; + ptag->pcrfRef = pvNil; return fFalse; // copy failed } ptag->cno = cnoDest; } - ptag->pcrf = pcrfDest; + ptag->pcrfRef = PcrfToRef(pcrfDest); pcrfDest->AddRef(); return fTrue; } @@ -1015,9 +1057,9 @@ bool TAGM::FSaveTag(PTAG ptag, PCRF pcrf, bool fRedirect) if (ptag->sid != ksidUseCrf) return fTrue; - AssertPo(ptag->pcrf, 0); + AssertPo(RefToPcrf(ptag->pcrfRef), 0); - if (!ptag->pcrf->Pcfl()->FCopy(ptag->ctg, ptag->cno, pcrf->Pcfl(), &cnoDest)) + if (!RefToPcrf(ptag->pcrfRef)->Pcfl()->FCopy(ptag->ctg, ptag->cno, pcrf->Pcfl(), &cnoDest)) { return fFalse; // copy failed } @@ -1025,8 +1067,8 @@ bool TAGM::FSaveTag(PTAG ptag, PCRF pcrf, bool fRedirect) if (fRedirect) { pcrf->AddRef(); - ReleasePpo(&ptag->pcrf); - ptag->pcrf = pcrf; + ReleasePpoPcrfRef(&ptag->pcrfRef); + ptag->pcrfRef = PcrfToRef(pcrf); ptag->cno = cnoDest; } @@ -1044,8 +1086,8 @@ void TAGM::DupTag(PTAG ptag) if (ptag->sid == ksidUseCrf) { - AssertPo(ptag->pcrf, 0); - ptag->pcrf->AddRef(); + AssertPo(RefToPcrf(ptag->pcrfRef), 0); + RefToPcrf(ptag->pcrfRef)->AddRef(); } } @@ -1061,8 +1103,8 @@ void TAGM::CloseTag(PTAG ptag) if (ptag->sid == ksidUseCrf) { - AssertPo(ptag->pcrf, 0); - ReleasePpo(&ptag->pcrf); + AssertPo(RefToPcrf(ptag->pcrfRef), 0); + ReleasePpoPcrfRef(&ptag->pcrfRef); } } @@ -1091,9 +1133,9 @@ ulong TAGM::FcmpCompareTags(PTAG ptag1, PTAG ptag2) // If both sids are ksidUseCrf, compare CRFs if (ptag1->sid == ksidUseCrf) // implies ptag2->sid == ksidUseCrf { - if (ptag1->pcrf < ptag2->pcrf) + if (ptag1->pcrfRef < ptag2->pcrfRef) return fcmpLt; - if (ptag1->pcrf > ptag2->pcrf) + if (ptag1->pcrfRef > ptag2->pcrfRef) return fcmpGt; } return fcmpEq; @@ -1151,8 +1193,8 @@ void TAG::MarkMem(void) { if (sid == ksidUseCrf) { - AssertPo(pcrf, 0); - MarkMemObj(pcrf); + AssertPo(RefToPcrf(pcrfRef), 0); + MarkMemObj(RefToPcrf(pcrfRef)); } } #endif // DEBUG diff --git a/src/studio/browser.cpp b/src/studio/browser.cpp index 3c9e6ee3..3b6f0de4 100644 --- a/src/studio/browser.cpp +++ b/src/studio/browser.cpp @@ -1964,7 +1964,7 @@ bool BRWN::FCmdOk(PCMD pcmd) PMVU pmvu; pmvu = (PMVU)(_pstdio->Pmvie()->PddgGet(0)); tag.sid = ksidInvalid; - tag.pcrf = pvNil; + tag.pcrfRef = pvNil; pmvu->SetTagTool(&tag); // No need to close tag with ksidInvalid } @@ -2057,7 +2057,7 @@ bool BRWM::_FUpdateLists(void) if (!pcfl->FGetCkiCtg(kctgMsnd, icki, &cki)) goto LNext; tag.sid = ksidUseCrf; // Non-CD-loaded content - tag.pcrf = _pcrf; + tag.pcrfRef = PcrfToRef(_pcrf); tag.ctg = kctgMsnd; tag.cno = cki.cno; @@ -2141,7 +2141,7 @@ bool BRWM::_FAddThd(STN *pstn, CKI *pcki) ; thd.tag.sid = ksidUseCrf; - thd.tag.pcrf = _pcrf; + thd.tag.pcrfRef = PcrfToRef(_pcrf); thd.tag.ctg = pcki->ctg; thd.tag.cno = pcki->cno; thd.cno = cnoNil; // unused @@ -2175,7 +2175,7 @@ void BRWM::_ProcessSelection(void) _GetThumFromIthum(_ithumSelect, &thumSelect, &sid); tag.sid = sid; - tag.pcrf = (ksidUseCrf == sid) ? _pcrf : pvNil; + tag.pcrfRef = (ksidUseCrf == sid) ? PcrfToRef(_pcrf) : pvNil; tag.ctg = kctgMsnd; tag.cno = (CNO)thumSelect; @@ -2367,7 +2367,7 @@ bool BRWM::FCmdDel(PCMD pcmd) // Delete the midi or wave child chunk from the msnd // Invalidate the sound tag.sid = ksidUseCrf; // Non-CD-loaded content - tag.pcrf = _pcrf; + tag.pcrfRef = PcrfToRef(_pcrf); tag.ctg = kctgMsnd; _GetThumFromIthum(_ithumSelect, &tag.cno, &sid); diff --git a/src/studio/esl.cpp b/src/studio/esl.cpp index 27fd89d8..506ef07b 100644 --- a/src/studio/esl.cpp +++ b/src/studio/esl.cpp @@ -485,7 +485,7 @@ bool ESLT::FCmdSetFont(PCMD pcmd) TAG tagTdfNew; tagTdfNew.sid = pcmd->rglw[1]; - tagTdfNew.pcrf = pvNil; + tagTdfNew.pcrfRef = pvNil; tagTdfNew.ctg = kctgTdf; tagTdfNew.cno = pcmd->rglw[0]; @@ -530,7 +530,7 @@ bool ESLT::FCmdSetColor(PCMD pcmd) TAG tagTdfNew; tagTdfNew.sid = pcmd->rglw[1]; - tagTdfNew.pcrf = pvNil; + tagTdfNew.pcrfRef = pvNil; tagTdfNew.ctg = kctgMtrl; tagTdfNew.cno = pcmd->rglw[0]; diff --git a/src/studio/stdiobrw.cpp b/src/studio/stdiobrw.cpp index ba06357d..37d326c7 100644 --- a/src/studio/stdiobrw.cpp +++ b/src/studio/stdiobrw.cpp @@ -425,7 +425,7 @@ void BRWB::_ApplySelection(long thumSelect, long sid) PMVU pmvu; tag.sid = sid; - tag.pcrf = pvNil; + tag.pcrfRef = pvNil; tag.ctg = kctgBkgd; tag.cno = (CNO)thumSelect; @@ -472,7 +472,7 @@ void BRWP::_ApplySelection(long thumSelect, long sid) AssertPo(pmvu, 0); tag.sid = sid; - tag.pcrf = pvNil; + tag.pcrfRef = pvNil; tag.ctg = kctgTmpl; tag.cno = (CNO)thumSelect; @@ -550,7 +550,7 @@ void BRWM::_ApplySelection(long thumSelect, long sid) tag.cno = (CNO)thumSelect; tag.sid = sid; if (ksidUseCrf != sid) - tag.pcrf = pvNil; + tag.pcrfRef = pvNil; else { if (!_pstdio->Pmvie()->FEnsureAutosave(&_pcrf))