////////////////////////// // FITD - Free in the Dark ////////////////////////// // 22 septembre 2003 14:25 // seg002 #include "common.h" #include "hybrid.h" #include "anim2d.h" #include #ifndef AITD_UE4 #include "bgfxGlue.h" #include #endif #include #include extern "C" { extern char homePath[512]; } FILE* Open(const char* filename, const char* mode) { std::filesystem::path path = std::filesystem::path(homePath) / filename; return fopen(path.string().c_str(), mode); } int AntiRebond; int* currentCVarTable = NULL; int getCVarsIdx(enumCVars searchedType) // TODO: optimize by reversing the table.... { for(int i=0;i=0) { if(currentActorEntryPtr->indexInWorld == -1) break; currentActorEntryPtr--; currentActorEntry--; } if(currentActorEntry==-1) // no space, we will have to overwrite the last actor ! { currentActorEntry = NUM_MAX_OBJECT-1; currentActorEntryPtr = &ListObjets[NUM_MAX_OBJECT-1]; } actorIdx = currentActorEntry; var_2 = 1; currentProcessedActorPtr = &ListObjets[actorIdx]; currentLifeActorPtr = &ListObjets[actorIdx]; currentProcessedActorIdx = actorIdx; currentLifeActorIdx = actorIdx; currentProcessedActorPtr->indexInWorld = objIdx; currentProcessedActorPtr->life = -1; currentProcessedActorPtr->bodyNum = -1; currentProcessedActorPtr->objectType = 0; currentProcessedActorPtr->trackMode = -1; currentProcessedActorPtr->room = -1; currentProcessedActorPtr->lifeMode = -1; currentProcessedActorPtr->ANIM = -1; } processLife(foundLife, true); if(var_2) { currentProcessedActorPtr->indexInWorld = -1; } currentProcessedActorPtr = currentActorPtr; currentProcessedActorIdx = currentActorIdx; currentLifeActorIdx = currentActorLifeIdx; currentLifeActorPtr = currentActorLifePtr; if(currentActorLifeNum != -1) { currentLifeNum = currentActorLifeNum; currentLifePtr = HQR_Get(listLife,currentLifeNum) + lifeOffset * 2; } } void InitCopyBox(char* var0, char* var1) { screenSm1 = var0; screenSm2 = var0; screenSm3 = var1; screenSm4 = var1; screenSm5 = var1; } void allocTextes(void) { int currentIndex; u8* currentPosInTextes; int textCounter; int stringIndex; u8* stringPtr; int textLength; tabTextes = (textEntryStruct*)malloc(NUM_MAX_TEXT_ENTRY * sizeof(textEntryStruct)); // 2000 = 250 * 8 ASSERT_PTR(tabTextes); if(!tabTextes) { fatalError(1,"TabTextes"); } // setup languageNameString { for (int i=0; i= '0' && currentIndex <= '9') // parse string number { stringIndex = stringIndex * 10 + currentIndex - 48; } if(currentIndex == ':') // start of string { stringPtr = currentPosInTextes; do { currentPosInTextes ++; }while((unsigned char)*(currentPosInTextes-1) >= ' '); // detect the end of the string *(currentPosInTextes-1) = 0; // add the end of string tabTextes[textCounter].index = stringIndex; tabTextes[textCounter].textPtr = stringPtr; tabTextes[textCounter].width = ExtGetSizeFont(stringPtr); textCounter++; } if(currentIndex == 26) { return; } } } } void OpenProgram(void) { //time_t ltime; FILE* fHandle; setupScreen(); //setupInterrupt(); //setupInterrupt2(); //setupInterrupt3(); //setupVideoMode(); // time( <ime ); // srand(ltime); if(!initMusicDriver()) { musicConfigured = 0; musicEnabled = 0; } // TODO: reverse sound init code aux = (char*)malloc(65068); if(!aux) { fatalError(1,"Aux"); } aux2 = (char*)malloc(65068); if(!aux2) { fatalError(1,"Aux2"); } InitCopyBox(aux2,logicalScreen); /* InitCopyPlot(aux2); InitSpecialCopyPoly(aux2); */ BufferAnim.resize(NB_BUFFER_ANIM); switch(g_gameId) { case AITD3: PtrFont = CheckLoadMallocPak("ITD_RESS", 1); break; case JACK: case AITD2: PtrFont = CheckLoadMallocPak("ITD_RESS", 1); break; case AITD1: PtrFont = CheckLoadMallocPak("ITD_RESS", 5); break; case TIMEGATE: PtrFont = CheckLoadMallocPak("ITD_RESS", 2); break; default: assert(0); } SetFont(PtrFont, 14); if(g_gameId == AITD1) { SetFontSpace(2,0); } else { SetFontSpace(2,1); } switch(g_gameId) { case JACK: case AITD2: case AITD3: { PtrCadre = CheckLoadMallocPak("ITD_RESS",0); break; } case AITD1: { PtrCadre = CheckLoadMallocPak("ITD_RESS",4); break; } } PtrPrioritySample = loadFromItd("PRIORITY.ITD"); // read cvars definitions { fHandle = Open("DEFINES.ITD", "rb"); if (!fHandle) { fatalError(0, "DEFINES.ITD"); } for (int i = 0; i < CVars.size(); i++) { s16 cvarValue = 0; fread(&cvarValue, 2, 1, fHandle); CVars[i] = READ_BE_S16(&cvarValue); } fclose(fHandle); } allocTextes(); // if(musicConfigured) { listMus = HQR_InitRessource("LISTMUS",110000,40); } char sampleFileName[256] = ""; if (g_gameId == TIMEGATE) { strcpy(sampleFileName, "SAMPLES"); } else { strcpy(sampleFileName, "LISTSAMP"); } listSamp = HQR_InitRessource(sampleFileName,64000,30); HQ_Memory = HQR_Init(10000,50); } void freeAll(void) { /* HQR_Free(hqrUnk); HQR_Free(listSamp); HQR_Free(listMus); free(languageData); free(tabTextes); free(priority); free(aitdBoxGfx); free(fontData); free(bufferAnim); if(aux != aux3) { free(aux); } free(aux2);*/ //TODO: implement all the code that restore the interrupts & all } textEntryStruct* getTextFromIdx(int index) { int currentIndex; for(currentIndex = 0; currentIndex < NUM_MAX_TEXT_ENTRY; currentIndex++) { if(tabTextes[currentIndex].index == index) { return(&tabTextes[currentIndex]); } } return(NULL); } void AffRect(int x1, int y1, int x2, int y2, char color) // fast recode. No RE { int width = x2 - x1 + 1; int height = y2 - y1 + 1; char* dest = logicalScreen + y1*320 + x1; char* dest2 = (char*)uiLayer.data() + y1*320 + x1; int i; int j; for(i=0;i ptrpage; int currentTextIdx; int maxStringWidth; u8* textPtr; SetFont(PtrFont, color); maxStringWidth = endx - startx + 4; int textIndexMalloc = HQ_Malloc(HQ_Memory,getPakSize(languageNameString.c_str(),index)+300); textPtr = (u8*)HQ_PtrMalloc(HQ_Memory, textIndexMalloc); if(!LoadPak( languageNameString.c_str(), index, (char*)textPtr)) { fatalError(1, languageNameString.c_str() ); } ptrpage.fill(nullptr); ptrpage[0] = textPtr; // LastSample = -1; // LastPriority = -1; while(!quit) { u8* ptrt; int currentTextY; FastCopyScreen(aux,logicalScreen); process_events(); SetClip(startx,top,endx,bottom); uiLayer.fill(0); ptrt = ptrpage[page]; currentTextY = top; lastPageReached = false; while(currentTextY <= bottom - 16) { int line_type = 1; int var_1BA = 0; int currentStringWidth; int currentTextX; regularTextEntryStruct* currentText = textTable; int numWordInLine = 0; int interWordSpace = 0; while (true) { while (*ptrt == '#') { //char* var_1BE = var_1C2; ptrt++; switch (*(ptrt++)) { case 'P': // page change { if (currentTextY > top) // Hu ? goto pageChange; break; } case 'T': // tab { currentText->textPtr = tabString; currentText->width = ExtGetSizeFont(currentText->textPtr) + 3; var_1BA += currentText->width; numWordInLine++; currentText++; break; } case 'C': // center { line_type &= ~1; line_type |= 8; break; } case 'G': // print number { currentTextIdx = 0; while (*ptrt >= '0' && *ptrt <= '9') { currentTextIdx = (currentTextIdx * 10 + *ptrt - 48); ptrt++; } if (LoadPak("ITD_RESS", 9, aux2)) { assert(0); // when is this used? /* var_C = printTextSub3(currentTextIdx,aux2); var_A = printTextSub4(currentTextIdx,aux2); if(currentTextY + var_A > bottom) { var_1C2 = var_1BE; goto pageChange; } else { printTextSub5((((right-left)/2)+left)-var_C, currentTextY, currentTextIdx, aux2); currentTextY = var_A; }*/ } break; } } } currentText->textPtr = ptrt; do { var_1C3 = *((unsigned char*)ptrt++); } while (var_1C3 > ' '); // go to the end of the string *(ptrt - 1) = 0; // add end of string marker to cut the word currentStringWidth = ExtGetSizeFont(currentText->textPtr) + 3; if (currentStringWidth > maxStringWidth) { quit = 1; break; } if (var_1BA + currentStringWidth > maxStringWidth) { ptrt = currentText->textPtr; break; } currentText->width = currentStringWidth; var_1BA += currentStringWidth; numWordInLine++; currentText++; // eval the character that caused the 'end of word' state if (var_1C3 == 26) { line_type &= ~1; line_type |= 4; lastPageReached = true; break; } if (((var_1C3 == 13) || (var_1C3 == 0)) && (*ptrt < ' ')) { ++ptrt; if (*ptrt == 0xD) { ptrt += 2; line_type &= ~1; line_type |= 2; break; } if (*ptrt == '#') { line_type &= ~1; break; } } } if(line_type & 1) // stretch words on line { interWordSpace = (maxStringWidth - var_1BA) / (numWordInLine-1); } currentText = textTable; if (line_type & 8) // center { currentTextX = startx + ((maxStringWidth - var_1BA) / 2); } else { currentTextX = startx; } for (int i = 0; i < numWordInLine; i++) { PrintFont(currentTextX, currentTextY, logicalScreen, currentText->textPtr); currentTextX += currentText->width + interWordSpace; // add inter word space currentText++; } currentTextIdx = 0; if (line_type & 2) // font size { currentTextY += 8; } currentTextY += 16; if (lastPageReached) break; } pageChange: if(lastPageReached) { *(ptrt-1) = 0x1A; // rewrite End Of Text } else { ptrpage[page+1] = ptrt; } if(demoMode == 0) { if(page>0) { AffSpfI(startx-19,185,12,PtrCadre); } if(!lastPageReached) { AffSpfI(endx+4,185,11,PtrCadre); } } if(demoMode == 2) { if(page>0) { AffSpfI(startx-3,191,13,PtrCadre); } if(!lastPageReached) { AffSpfI(endx-10,191,14,PtrCadre); } } if(firstpage) { if(demoMode!=1) { osystem_CopyBlockPhys((unsigned char*)logicalScreen,0,0,320,200); FadeInPhys(16,0); } else { if(turnPageFlag) { turnPageForward(); } else { osystem_CopyBlockPhys((unsigned char*)logicalScreen,0,0,320,200); } } firstpage = 0; } else { if(turnPageFlag) { if(previousPage 0) { previousPage = page; page--; if (demoMode == 2) { playSound(CVars[getCVarsIdx(SAMPLE_PAGE)]); LastSample = -1; LastPriority = -1; } break; } } } } else // Demo mode: pages automatically flips { unsigned int var_6; startChrono(&var_6); do { process_events(); if(evalChrono(&var_6) > 300) { break; } }while(!key && !Click); if(key || Click) { quit = 1; } if(!lastPageReached) { page++; playSound(CVars[getCVarsIdx(SAMPLE_PAGE)]); LastSample = -1; } else { quit = 1; demoMode = 0; } } } HQ_Free_Malloc(HQ_Memory, textIndexMalloc); return(demoMode); } extern "C" { extern char homePath[512]; } void LoadWorld(void) { u8* pObjectData; u8* pObjectDataBackup; unsigned long int objectDataSize; FILE* fHandle; int i; int choosePersoBackup; char objectPath[512]; strcpy(objectPath, homePath); strcat(objectPath, "OBJETS.ITD"); fHandle = fopen(objectPath,"rb"); if (!fHandle) { fatalError(0, "OBJETS.ITD"); } fseek(fHandle,0,SEEK_END); objectDataSize = ftell(fHandle); fseek(fHandle,0,SEEK_SET); pObjectDataBackup = pObjectData = (u8*)malloc(objectDataSize); ASSERT(pObjectData); fread(pObjectData,objectDataSize,1,fHandle); fclose(fHandle); maxObjects = READ_LE_U16(pObjectData); pObjectData+=2; ListWorldObjets.resize(maxObjects); for(i=0;i= JACK) { ListWorldObjets[i].mark = READ_LE_U16(pObjectData); pObjectData+=2; } ListWorldObjets[i].flags |= 0x20; } free(pObjectDataBackup); vars = (s16*)loadFromItd("VARS.ITD"); varSize = fileSize; if(g_gameId == AITD1) { choosePersoBackup = CVars[getCVarsIdx(CHOOSE_PERSO)]; // backup hero selection } char definestPath[512]; strcpy(definestPath, homePath); strcat(definestPath, "DEFINES.ITD"); fHandle = fopen(definestPath,"rb"); if(!fHandle) { fatalError(0,"DEFINES.ITD"); } /////////////////////////////////////////////// { fread(&CVars[0], CVars.size(), 2, fHandle); fclose(fHandle); for(i=0;i< CVars.size();i++) { CVars[i] = ((CVars[i]&0xFF)<<8) | ((CVars[i]&0xFF00)>>8); } } ////////////////////////////////////////////// if(g_gameId == AITD1) { CVars[getCVarsIdx(CHOOSE_PERSO)] = choosePersoBackup; } listLife = HQR_InitRessource("LISTLIFE", 65000, 100); listTrack = HQR_InitRessource("LISTTRAK", 20000, 100); if (g_gameId >= JACK) { HQ_Hybrides = HQR_InitRessource("LISTHYB", 20000, 10); // TODO: recheck size for other games } // TODO: missing dos memory check here if(g_gameId == AITD1) { HQ_Bodys = HQR_InitRessource(listBodySelect[CVars[getCVarsIdx(CHOOSE_PERSO)]], 37000, 50); // was calculated from free mem size HQ_Anims = HQR_InitRessource(listAnimSelect[CVars[getCVarsIdx(CHOOSE_PERSO)]], 30000, 80); // was calculated from free mem size } else { HQ_Bodys = HQR_InitRessource("LISTBODY", 37000, 50); // was calculated from free mem size HQ_Anims = HQR_InitRessource("LISTANIM",30000, 80); // was calculated from free mem size HQ_Matrices = HQR_InitRessource("LISTMAT",64000,5); } for(i=0;i= JACK) { copyPalette(aux+64000,currentGamePalette); if(g_gameId == AITD3) { for (int i = 0; i < 16; i++) { currentGamePalette[i][0] = defaultPaletteAITD3[i * 3 + 0]; currentGamePalette[i][1] = defaultPaletteAITD3[i * 3 + 1]; currentGamePalette[i][2] = defaultPaletteAITD3[i * 3 + 2]; } } else { for (int i = 0; i < 16; i++) { currentGamePalette[i][0] = defaultPalette[i * 3 + 0]; currentGamePalette[i][1] = defaultPalette[i * 3 + 1]; currentGamePalette[i][2] = defaultPalette[i * 3 + 2]; } } convertPaletteIfRequired(currentGamePalette); osystem_setPalette(¤tGamePalette); } } struct sMaskStruct { u16 x1; u16 y1; u16 x2; u16 y2; u16 deltaX; u16 deltaY; std::array mask; }; std::vector> g_maskBuffers; void loadMask(int cameraIdx) { if (g_gameId == TIMEGATE) return; char name[16]; sprintf(name, "MASK%02d", g_currentFloor); if(g_MaskPtr) { free(g_MaskPtr); } g_MaskPtr = (unsigned char*)loadPak(name,cameraIdx); g_maskBuffers.clear(); g_maskBuffers.resize(cameraDataTable[NumCamera]->numViewedRooms); for(int i=0; inumViewedRooms; i++) { cameraViewedRoomStruct* pRoomView = &cameraDataTable[NumCamera]->viewedRoomTable[i]; unsigned char* pViewedRoomMask = g_MaskPtr + READ_LE_U32(g_MaskPtr + i*4); g_maskBuffers[i].reserve(pRoomView->masks.size()); for(int j=0; jmasks.size(); j++) { sMaskStruct* pDestMask = &g_maskBuffers[i].emplace_back(); unsigned char* pMaskData = pViewedRoomMask + READ_LE_U32(pViewedRoomMask + j*4); pDestMask->mask.fill(0); pDestMask->x1 = READ_LE_U16(pMaskData); pMaskData += 2; pDestMask->y1 = READ_LE_U16(pMaskData); pMaskData += 2; pDestMask->x2 = READ_LE_U16(pMaskData); pMaskData += 2; pDestMask->y2 = READ_LE_U16(pMaskData); pMaskData += 2; pDestMask->deltaX = READ_LE_U16(pMaskData); pMaskData += 2; pDestMask->deltaY = READ_LE_U16(pMaskData); pMaskData += 2; assert(pDestMask->deltaX == pDestMask->x2 - pDestMask->x1 + 1); assert(pDestMask->deltaY == pDestMask->y2 - pDestMask->y1 + 1); for(int k=0; kdeltaY; k++) { u16 uNumEntryForLine = READ_LE_U16(pMaskData); pMaskData += 2; unsigned char* pSourceBuffer = (unsigned char*)aux; int offset = pDestMask->x1 + pDestMask->y1 * 320 + k * 320; for(int l=0; lmask[offset] = 0xFF; offset++; } } } osystem_createMask(pDestMask->mask, i, j, pDestMask->x1, pDestMask->y1, pDestMask->x2, pDestMask->y2); } } } void fillpoly(s16 * datas, int n, unsigned char c); extern unsigned char* polyBackBuffer; void createAITD1Mask() { for(int viewedRoomIdx=0; viewedRoomIdxnumViewedRooms; viewedRoomIdx++) { cameraViewedRoomStruct* pcameraViewedRoomData = &cameraDataTable[NumCamera]->viewedRoomTable[viewedRoomIdx]; char* data2 = room_PtrCamera[NumCamera] + pcameraViewedRoomData->offsetToMask; char* data = data2; data+=2; int numMask = *(s16*)(data2); for(int maskIdx=0;maskIdxmask.fill(0); polyBackBuffer = pDestMask->mask.data(); int numMaskZone = READ_LE_U16(data); char* src = data2 + READ_LE_U16(data+2); int minX = 319; int maxX = 0; int minY = 199; int maxY = 0; /*if(isBgOverlayRequired( actorPtr->zv.ZVX1 / 10, actorPtr->zv.ZVX2 / 10, actorPtr->zv.ZVZ1 / 10, actorPtr->zv.ZVZ2 / 10, data+4, *(s16*)(data) ))*/ { int numMaskPoly = READ_LE_U16(src); src += 2; for(int maskPolyIdx=0;maskPolyIdx(minX, verticeX); minY = std::min(minY, verticeY); maxX = std::max(maxX, verticeX); maxY = std::max(maxY, verticeY); } src+=numPoints*4; //drawBgOverlaySub2(param); } // blitOverlay(src); polyBackBuffer = nullptr; } osystem_createMask(pDestMask->mask, viewedRoomIdx, maskIdx, minX-1, minY-1, maxX+1, maxY+1); int numOverlay = READ_LE_U16(data); data+=2; data+=((numOverlay*4)+1)*2; } /* unsigned char* pViewedRoomMask = g_MaskPtr + READ_LE_U32(g_MaskPtr + i*4); for(int j=0; jnumMask; j++) { unsigned char* pMaskData = pViewedRoomMask + READ_LE_U32(pViewedRoomMask + j*4); maskStruct* pDestMask = &g_maskBuffers[i][j]; memset(pDestMask->mask, 0, 320*200); pDestMask->x1 = READ_LE_U16(pMaskData); pMaskData += 2; pDestMask->y1 = READ_LE_U16(pMaskData); pMaskData += 2; pDestMask->x2 = READ_LE_U16(pMaskData); pMaskData += 2; pDestMask->y2 = READ_LE_U16(pMaskData); pMaskData += 2; pDestMask->deltaX = READ_LE_U16(pMaskData); pMaskData += 2; pDestMask->deltaY = READ_LE_U16(pMaskData); pMaskData += 2; assert(pDestMask->deltaX == pDestMask->x2 - pDestMask->x1 + 1); assert(pDestMask->deltaY == pDestMask->y2 - pDestMask->y1 + 1); for(int k=0; kdeltaY; k++) { u16 uNumEntryForLine = READ_LE_U16(pMaskData); pMaskData += 2; unsigned char* pDestBuffer = pDestMask->mask; unsigned char* pSourceBuffer = (unsigned char*)aux; int offset = pDestMask->x1 + pDestMask->y1 * 320 + k * 320; for(int l=0; lmask, i, j, (unsigned char*)aux, pDestMask->x1, pDestMask->y1, pDestMask->x2, pDestMask->y2); }*/ } polyBackBuffer = NULL; } void SetAngleCamera(int x, int y, int z) { transformX = x&0x3FF; if(transformX) { transformXCos = cosTable[transformX]; transformXSin = cosTable[(transformX+0x100)&0x3FF]; transformUseX = true; } else { transformUseX = false; } transformY = y&0x3FF; if(transformY) { transformYCos = cosTable[transformY]; transformYSin = cosTable[(transformY+0x100)&0x3FF]; transformUseY = true; } else { transformUseY = false; } transformZ = z&0x3FF; if(transformZ) { transformZCos = cosTable[transformZ]; transformZSin = cosTable[(transformZ+0x100)&0x3FF]; transformUseZ = true; } else { transformUseZ = false; } } void SetPosCamera(int x, int y, int z) { translateX = x; translateY = y; translateZ = z; } void SetProjection(int centerX, int centerY, int x, int y, int z) { cameraCenterX = centerX; cameraCenterY = centerY; cameraPerspective = x; cameraFovX = y; cameraFovY = z; } int isInViewList(int value) { char* ptr = currentCameraVisibilityList; int var; while((var=*(ptr++))!=-1) { if(value == var) { return(1); } } return(0); } // setup visibility list void InitViewedRoomList() { u32 i; int j; int var_10; char* dataTabPos = currentCameraVisibilityList; *dataTabPos = -1; // visibility list: add linked rooms for(i=0;inumViewedRooms;j++) { if(!isInViewList(cameraDataTable[NumCamera]->viewedRoomTable[j].viewedRoomIdx)) { *(dataTabPos++) = (char)cameraDataTable[NumCamera]->viewedRoomTable[j].viewedRoomIdx; *(dataTabPos) = -1; } } } void DeleteObjet(int index) // remove actor { tObject *actorPtr = &ListObjets[index]; if(actorPtr->indexInWorld == -2) // flow { actorPtr->indexInWorld = -1; if(actorPtr->ANIM == 4 ) { CVars[getCVarsIdx(FOG_FLAG)] = 0; } HQ_Free_Malloc(HQ_Memory,actorPtr->frame); } else { if(actorPtr->indexInWorld >= 0) { tWorldObject* objectPtr = &ListWorldObjets[actorPtr->indexInWorld]; objectPtr->objIndex = -1; actorPtr->indexInWorld = -1; objectPtr->body = actorPtr->bodyNum; objectPtr->anim = actorPtr->ANIM; objectPtr->frame = actorPtr->frame; objectPtr->animType = actorPtr->animType; objectPtr->animInfo = actorPtr->animInfo; objectPtr->flags = actorPtr->objectType & ~AF_BOXIFY; objectPtr->flags |= AF_SPECIAL * actorPtr->dynFlags; // ugly hack, need rewrite objectPtr->life = actorPtr->life; objectPtr->lifeMode = actorPtr->lifeMode; objectPtr->trackMode = actorPtr->trackMode; if(objectPtr->trackMode) { objectPtr->trackNumber = actorPtr->trackNumber; objectPtr->positionInTrack = actorPtr->positionInTrack; if(g_gameId != AITD1) { objectPtr->mark = actorPtr->MARK; } } objectPtr->x = actorPtr->roomX + actorPtr->stepX; objectPtr->y = actorPtr->roomY + actorPtr->stepY; objectPtr->z = actorPtr->roomZ + actorPtr->stepZ; objectPtr->alpha = actorPtr->alpha; objectPtr->beta = actorPtr->beta; objectPtr->gamma = actorPtr->gamma; objectPtr->stage = actorPtr->stage; objectPtr->room = actorPtr->room; FlagGenereAffList = 1; } } } bool pointRotateEnable = true; int pointRotateCosX; int pointRotateSinX; int pointRotateCosY; int pointRotateSinY; int pointRotateCosZ; int pointRotateSinZ; void setupPointRotate(int alpha, int beta, int gamma) { pointRotateEnable = true; pointRotateCosX = cosTable[alpha&0x3FF]; pointRotateSinX = cosTable[((alpha&0x3FF) + 0x100) & 0x3FF]; pointRotateCosY = cosTable[beta&0x3FF]; pointRotateSinY = cosTable[((beta&0x3FF) + 0x100) & 0x3FF]; pointRotateCosZ = cosTable[gamma&0x3FF]; pointRotateSinZ = cosTable[((gamma&0x3FF) + 0x100) & 0x3FF]; } void pointRotate(int x, int y, int z, int* destX, int* destY, int* destZ) { if(pointRotateEnable) { { int tempX = x; int tempY = y; x = ((((tempX * pointRotateSinZ) - ( tempY * pointRotateCosZ)))>>16)<<1; y = ((((tempX * pointRotateCosZ) + ( tempY * pointRotateSinZ)))>>16)<<1; } { int tempX = x; int tempZ = z; x = ((((tempX * pointRotateSinY) - (tempZ * pointRotateCosY)))>>16)<<1; z = ((((tempX * pointRotateCosY) + (tempZ * pointRotateSinY)))>>16)<<1; } { int tempY = y; int tempZ = z; y = ((((tempY * pointRotateSinX ) - (tempZ * pointRotateCosX)))>>16)<<1; z = ((((tempY * pointRotateCosX ) + (tempZ * pointRotateSinX)))>>16)<<1; } *destX = x; *destY = y; *destZ = z; } } void CopyZV(ZVStruct* source, ZVStruct* dest) { memcpy(dest,source,sizeof(ZVStruct)); } void RefreshAux2(void) { FastCopyScreen(aux,aux2); //TODO: implementer la suite } void InitDeplacement(int trackMode, int trackNumber) { currentProcessedActorPtr->trackMode = trackMode; switch(trackMode) { case 2: { currentProcessedActorPtr->trackNumber = trackNumber; currentProcessedActorPtr->MARK = -1; break; } case 3: { currentProcessedActorPtr->trackNumber = trackNumber; currentProcessedActorPtr->positionInTrack = 0; currentProcessedActorPtr->MARK = -1; break; } } } s16 ObjSalleRel = 0; int IsInCamera(int roomNumber) { int numZone = cameraDataTable[NumCamera]->numViewedRooms; for(int i=0;iviewedRoomTable[i].viewedRoomIdx == roomNumber) { ObjSalleRel = i; return(1); } } ObjSalleRel = -1; return 0; } int IsInCamRectTestAITD2(int X, int Z) // TODO: not 100% exact { // if(changeCameraSub1(X,X,Z,Z,&cameraDataTable[currentCamera]->cameraZoneDefTable[cameraVisibilityVar])) return 1; return 0; } void updateAllActorAndObjectsAITD2() { for (int i = 0; i < NUM_MAX_OBJECT; i++) { tObject* pObject = &ListObjets[i]; if (pObject->indexInWorld == -1) { continue; } pObject->lifeMode &= ~4; if (pObject->stage == g_currentFloor) { switch (pObject->lifeMode) { case 0: // OFF break; case 1: // STAGE continue; case 2: // ROOM if (pObject->room == currentRoom) { continue; } break; case 3: // CAMERA if (isInViewList(pObject->room)) { continue; } break; default: break; } if (pObject->bodyNum != -1) { if (IsInCamera(pObject->room)) { if (IsInCamRectTestAITD2(pObject->roomX + pObject->stepX, pObject->roomZ + pObject->stepZ)) { pObject->lifeMode |= 4; continue; } } } } DeleteObjet(i); } for (int i = 0; i < maxObjects; i++) { tWorldObject* currentObject = &ListWorldObjets[i]; if (currentObject->objIndex != -1) { if (currentWorldTarget == i) { currentCameraTargetActor = currentObject->objIndex; } continue; } if (currentObject->stage != g_currentFloor) continue; bool isOk = false; switch (currentObject->lifeMode & 3) { case 0: // OFF isOk = false; break; case 1: // STAGE isOk = true; break; case 3: // CAMERA if (!isInViewList(currentObject->room)) { isOk = false; } else { isOk = true; } break; case 2: // ROOM if (currentObject->room != currentRoom) { isOk = false; } else { isOk = true; } break; } if (!isOk) { if ((currentObject->body == -1) || (!IsInCamera(currentObject->room)) || (!IsInCamRectTestAITD2(currentObject->x, currentObject->z))) { continue; } else { currentObject->lifeMode |= 4; } } currentObject->objIndex = InitObjet(currentObject->body, currentObject->typeZV, currentObject->foundName, currentObject->flags & ~AF_SPECIAL, currentObject->x, currentObject->y, currentObject->z, currentObject->stage, currentObject->room, currentObject->alpha, currentObject->beta, currentObject->gamma, currentObject->anim, currentObject->frame, currentObject->animType, currentObject->animInfo); if (currentObject->objIndex != -1) { currentProcessedActorPtr = &ListObjets[currentObject->objIndex]; currentProcessedActorIdx = currentObject->objIndex; if (currentWorldTarget == i) { currentCameraTargetActor = currentProcessedActorIdx; } currentProcessedActorPtr->dynFlags = (currentObject->flags & 0x20) / 0x20; // recheck currentProcessedActorPtr->life = currentObject->life; currentProcessedActorPtr->lifeMode = currentObject->lifeMode; currentProcessedActorPtr->indexInWorld = i; InitDeplacement(currentObject->trackMode, currentObject->trackNumber); currentProcessedActorPtr->positionInTrack = currentObject->positionInTrack; if (g_gameId != AITD1) { currentProcessedActorPtr->MARK = currentObject->mark; } FlagGenereAffList = 1; } } //FlagGenereActiveList = true; } void GenereActiveList() { if(g_gameId > JACK) { updateAllActorAndObjectsAITD2(); return; } for(int i=0;iindexInWorld == -1) continue; if(currentActor->stage == g_currentFloor) { if(currentActor->life != -1) { switch(currentActor->lifeMode) { case 0: // STAGE continue; case 1: // ROOM if(currentActor->room == currentRoom) { continue; } break; case 2: // CAMERA if(isInViewList(currentActor->room)) { continue; } break; default: { break; } } } else { if(isInViewList(currentActor->room)) { continue; } } } DeleteObjet(i); } for(int i=0;iobjIndex != -1) { if(currentWorldTarget == i) { currentCameraTargetActor = currentObject->objIndex; } continue; } if (currentObject->stage != g_currentFloor) { continue; } if (currentObject->life != -1) { switch (currentObject->lifeMode) { case -1: continue; case 0: // Stage break; case 1: // Room if (currentObject->room != currentRoom) { continue; } break; case 2: // Camera if (!isInViewList(currentObject->room)) { continue; } break; } } else { if (!isInViewList(currentObject->room)) { continue; } } currentObject->objIndex = InitObjet( currentObject->body, currentObject->typeZV, currentObject->foundName, currentObject->flags & ~AF_SPECIAL, currentObject->x, currentObject->y, currentObject->z, currentObject->stage, currentObject->room, currentObject->alpha, currentObject->beta, currentObject->gamma, currentObject->anim, currentObject->frame, currentObject->animType, currentObject->animInfo); if(currentObject->objIndex != -1) { currentProcessedActorPtr = &ListObjets[currentObject->objIndex]; currentProcessedActorIdx = currentObject->objIndex; if(currentWorldTarget == i) { currentCameraTargetActor = currentProcessedActorIdx; } currentProcessedActorPtr->dynFlags = (currentObject->flags & 0x20) / 0x20; // recheck currentProcessedActorPtr->life = currentObject->life; currentProcessedActorPtr->lifeMode = currentObject->lifeMode; currentProcessedActorPtr->indexInWorld = i; InitDeplacement(currentObject->trackMode, currentObject->trackNumber); currentProcessedActorPtr->positionInTrack = currentObject->positionInTrack; FlagGenereAffList = 1; } } // FlagGenereActiveList = 0; //TODO: object update } int checkActorInRoom(int room) { int i; for(i=0;inumViewedRooms;i++) { if(cameraDataTable[NumCamera]->viewedRoomTable[i].viewedRoomIdx == room) { return(1); } } return(0); } void GenereAffList() { NbAffObjets = 0; for(int i=0;i< ListObjets.size();i++) { tObject* actorPtr = &ListObjets[i]; if(actorPtr->indexInWorld != -1 && actorPtr->bodyNum != -1) { if(checkActorInRoom(actorPtr->room)) { Index[NbAffObjets] = i; if(!(actorPtr->objectType & (AF_SPECIAL & AF_ANIMATED))) { actorPtr->objectType |= AF_BOXIFY; // FlagRefreshAux2 = 1; } NbAffObjets++; } } } } void InitView() { int x; int y; int z; SaveTimerAnim(); resetAnim2D(); NumCamera = NewNumCamera; assert(NewNumCamera < roomDataTable[currentRoom].numCameraInRoom); loadCamera(roomDataTable[currentRoom].cameraIdxTable[NewNumCamera]); if(g_gameId >= JACK) { loadMask(roomDataTable[currentRoom].cameraIdxTable[NewNumCamera]); } else { createAITD1Mask(); } cameraBackgroundChanged = true; if (g_gameId >= JACK) { load2dAnims(roomDataTable[currentRoom].cameraIdxTable[NewNumCamera]); } cameraDataStruct* pCamera = cameraDataTable[NumCamera]; SetAngleCamera(pCamera->alpha,pCamera->beta,pCamera->gamma); #ifdef FITD_DEBUGGER if(debuggerVar_topCamera) SetAngleCamera(0x100,0,0); #endif x = (pCamera->x - roomDataTable[currentRoom].worldX)*10; y = (roomDataTable[currentRoom].worldY - pCamera->y)*10; z = (roomDataTable[currentRoom].worldZ - pCamera->z)*10; #ifdef FITD_DEBUGGER if(debuggerVar_topCamera) { if(currentCameraTargetActor != -1) { x = ListObjets[currentCameraTargetActor].worldX + ListObjets[currentCameraTargetActor].stepX; y = debufferVar_topCameraZoom; z = ListObjets[currentCameraTargetActor].worldZ + ListObjets[currentCameraTargetActor].stepZ; } } #endif SetPosCamera(x,y,z); // setup camera position SetProjection(160,100,pCamera->focal1,pCamera->focal2,pCamera->focal3); // setup projection #ifdef FITD_DEBUGGER if(debuggerVar_topCamera) SetProjection(160,100,1000,100,100); #endif InitViewedRoomList(); GenereActiveList(); GenereAffList(); // TriListObjet(); RefreshAux2(); /* InitScreenCoors(); */ if(FlagInitView==2) { flagRedraw = 2; } else { if(flagRedraw!=2) { flagRedraw = 1; } } FlagInitView = 0; RestoreTimerAnim(); for (int i = 0; i < currentCameraZoneList[NumCamera]->hybrids.size(); i++) { startAnim2d(i); } } s16 GiveDistance2D(int x1, int z1, int x2, int z2) { //int axBackup = x1; x1 -= x2; if((s16)x1 < 0) { x1 = -(s16)x1; } z1 -= z2; if((s16)z1 < 0) { z1 = -(s16)z1; } if((x1+z1)> 0xFFFF) { return(0x7D00); } else { return(x1+z1); } } void InitRealValue(s16 startValue, s16 endValue, s16 time, RealValue* realValue) { realValue->startValue = startValue; realValue->endValue = endValue; realValue->numSteps = time; realValue->memoTicks = timer; } s16 updateActorRotation(RealValue* rotatePtr) { int timeDif; int angleDif; if(!rotatePtr->numSteps) return(rotatePtr->endValue); timeDif = timer - rotatePtr->memoTicks; if(timeDif>rotatePtr->numSteps) { rotatePtr->numSteps = 0; return(rotatePtr->endValue); } angleDif = (rotatePtr->endValue&0x3FF) - (rotatePtr->startValue&0x3FF); if(angleDif<=0x200) { if(angleDif>=-0x200) { int angle = (rotatePtr->endValue&0x3FF) - (rotatePtr->startValue&0x3FF); return (rotatePtr->startValue&0x3FF) + (angle*timeDif)/rotatePtr->numSteps; } else { s16 angle = ((rotatePtr->endValue&0x3FF)+0x400) - ((rotatePtr->startValue&0x3FF)); return (((rotatePtr->startValue&0x3FF)) + ((angle*timeDif)/rotatePtr->numSteps)); } } else { int angle = (rotatePtr->endValue&0x3FF) - ((rotatePtr->startValue&0x3FF)+0x400); return ((angle*timeDif)/rotatePtr->numSteps) + ((rotatePtr->startValue&0x3FF)); } } void removeFromBGIncrust(int actorIdx) { tObject* actorPtr = &ListObjets[actorIdx]; actorPtr->objectType &= ~AF_BOXIFY; // FlagRefreshAux2 = 1; BBox3D1 = actorPtr->screenXMin; if(BBox3D1 > -1) { BBox3D2 = actorPtr->screenYMin; BBox3D3 = actorPtr->screenXMax; BBox3D4 = actorPtr->screenYMax; //deleteSubSub(); } } int findObjectInInventory(int objIdx) { for(int i=0;iobjIndex; if(actorIdx != -1) { actorPtr = &ListObjets[actorIdx]; actorPtr->room = -1; actorPtr->stage = -1; // FlagGenereActiveList = 1; if(actorPtr->objectType & AF_BOXIFY) { removeFromBGIncrust(actorIdx); } } objPtr->room = -1; objPtr->stage = -1; DeleteInventoryObjet(objIdx); } #ifdef FITD_DEBUGGER void line(int x1, int y1, int x2, int y2, char c); void drawProjectedLine(s32 x1s, s32 y1s, s32 z1s, s32 x2s, s32 y2s, s32 z2s,int c) { float x1 = (float)x1s; float x2 = (float)x2s; float y1 = (float)y1s; float y2 = (float)y2s; float z1 = (float)z1s; float z2 = (float)z2s; float transformedX1; float transformedX2; float transformedY1; float transformedY2; x1 -= translateX; x2 -= translateX; #if !defined(AITD_UE4) y1 -= translateY; y2 -= translateY; #endif z1 -= translateZ; z2 -= translateZ; #if defined(AITD_UE4) osystem_draw3dLine(x1, y1, z1, x2, y2, z2, c); #else transformPoint(&x1,&y1,&z1); transformPoint(&x2,&y2,&z2); z1 += cameraPerspective; z2 += cameraPerspective; transformedX1 = ((x1 * cameraFovX) / (float)z1) + cameraCenterX; transformedX2 = ((x2 * cameraFovX) / (float)z2) + cameraCenterX; transformedY1 = ((y1 * cameraFovY) / (float)z1) + cameraCenterY; transformedY2 = ((y2 * cameraFovY) / (float)z2) + cameraCenterY; if(z1>0 && z2>0) osystem_draw3dLine(transformedX1,transformedY1,z1,transformedX2,transformedY2,z2,c); #endif } void drawZv(const ZVStruct& localZv) { // bottom drawProjectedLine(localZv.ZVX1, localZv.ZVY2, localZv.ZVZ1, localZv.ZVX1, localZv.ZVY2, localZv.ZVZ2, 10); drawProjectedLine(localZv.ZVX1, localZv.ZVY2, localZv.ZVZ2, localZv.ZVX2, localZv.ZVY2, localZv.ZVZ2, 10); drawProjectedLine(localZv.ZVX2, localZv.ZVY2, localZv.ZVZ2, localZv.ZVX2, localZv.ZVY2, localZv.ZVZ1, 10); drawProjectedLine(localZv.ZVX2, localZv.ZVY2, localZv.ZVZ1, localZv.ZVX1, localZv.ZVY2, localZv.ZVZ1, 10); // top drawProjectedLine(localZv.ZVX1, localZv.ZVY1, localZv.ZVZ1, localZv.ZVX1, localZv.ZVY1, localZv.ZVZ2, 10); drawProjectedLine(localZv.ZVX1, localZv.ZVY1, localZv.ZVZ2, localZv.ZVX2, localZv.ZVY1, localZv.ZVZ2, 10); drawProjectedLine(localZv.ZVX2, localZv.ZVY1, localZv.ZVZ2, localZv.ZVX2, localZv.ZVY1, localZv.ZVZ1, 10); drawProjectedLine(localZv.ZVX2, localZv.ZVY1, localZv.ZVZ1, localZv.ZVX1, localZv.ZVY1, localZv.ZVZ1, 10); drawProjectedLine(localZv.ZVX1, localZv.ZVY2, localZv.ZVZ1, localZv.ZVX1, localZv.ZVY1, localZv.ZVZ1, 10); drawProjectedLine(localZv.ZVX1, localZv.ZVY2, localZv.ZVZ2, localZv.ZVX1, localZv.ZVY1, localZv.ZVZ2, 10); drawProjectedLine(localZv.ZVX2, localZv.ZVY2, localZv.ZVZ2, localZv.ZVX2, localZv.ZVY1, localZv.ZVZ2, 10); drawProjectedLine(localZv.ZVX2, localZv.ZVY2, localZv.ZVZ1, localZv.ZVX2, localZv.ZVY1, localZv.ZVZ1, 10); } void drawZv(tObject* actorPtr) { ZVStruct localZv; if( actorPtr->room != ListObjets[currentCameraTargetActor].room ) { if (ListObjets[currentCameraTargetActor].room == -1) { return; } AdjustZV(&localZv, actorPtr->room, ListObjets[currentCameraTargetActor].room); } else { CopyZV(&actorPtr->zv,&localZv); } drawZv(localZv); } void drawConverZone(cameraZoneEntryStruct* zonePtr) { int i; for(i=0;inumPoints-1;i++) { drawProjectedLine(zonePtr->pointTable[i].x*10,0,zonePtr->pointTable[i].y*10,zonePtr->pointTable[i+1].x*10,0,zonePtr->pointTable[i+1].y*10,20); } // loop first and last i = zonePtr->numPoints-1; drawProjectedLine(zonePtr->pointTable[0].x*10,0,zonePtr->pointTable[0].y*10,zonePtr->pointTable[i].x*10,0,zonePtr->pointTable[i].y*10,20); } void drawConverZones() { int i; for(i=0;inumViewedRooms;j++) { int k; if(cameraDataTable[i]->viewedRoomTable[j].viewedRoomIdx == currentRoom) { for(k=0;kviewedRoomTable[j].coverZones.size();k++) { drawConverZone(&cameraDataTable[i]->viewedRoomTable[j].coverZones[k]); } } } } } void drawAAQuad(s32 X1, s32 X2, s32 Z1, s32 Z2) { drawProjectedLine(X1, 0, Z1, X1, 0, Z2, 20); drawProjectedLine(X1, 0, Z2, X2, 0, Z2, 20); drawProjectedLine(X2, 0, Z2, X2, 0, Z1, 20); drawProjectedLine(X2, 0, Z1, X1, 0, Z1, 20); } void drawMaskZone(cameraMaskStruct* maskZonePtr) { for(int i=0; inumTestRect; i++) { drawAAQuad(maskZonePtr->rectTests[i].zoneX1*10, maskZonePtr->rectTests[i].zoneX2*10, maskZonePtr->rectTests[i].zoneZ1*10, maskZonePtr->rectTests[i].zoneZ2*10); } } void drawMaskZones() { { cameraDataStruct* pCamera = cameraDataTable[NumCamera]; for(int j=0;jnumViewedRooms;j++) { int k; //if(cameraDataTable[i]->viewedRoomTable[j].viewedRoomIdx == currentDisplayedRoom) { for(k=0;kviewedRoomTable[j].masks.size();k++) { drawMaskZone(&pCamera->viewedRoomTable[j].masks[k]); } } } } } #define DEPTH_THRESHOLD 1000 void drawProjectedQuad(float x1,float x2, float x3, float x4, float y1,float y2, float y3, float y4, float z1,float z2, float z3, float z4, int color, int transprency) { float transformedX1; float transformedX2; float transformedX3; float transformedX4; float transformedY1; float transformedY2; float transformedY3; float transformedY4; x1 -= translateX; x2 -= translateX; x3 -= translateX; x4 -= translateX; y1 -= translateY; y2 -= translateY; y3 -= translateY; y4 -= translateY; z1 -= translateZ; z2 -= translateZ; z3 -= translateZ; z4 -= translateZ; transformPoint(&x1,&y1,&z1); transformPoint(&x2,&y2,&z2); transformPoint(&x3,&y3,&z3); transformPoint(&x4,&y4,&z4); z1 += cameraPerspective; z2 += cameraPerspective; z3 += cameraPerspective; z4 += cameraPerspective; transformedX1 = ((x1 * cameraFovX) / (float)z1) + cameraCenterX; transformedX2 = ((x2 * cameraFovX) / (float)z2) + cameraCenterX; transformedX3 = ((x3 * cameraFovX) / (float)z3) + cameraCenterX; transformedX4 = ((x4 * cameraFovX) / (float)z4) + cameraCenterX; transformedY1 = ((y1 * cameraFovY) / (float)z1) + cameraCenterY; transformedY2 = ((y2 * cameraFovY) / (float)z2) + cameraCenterY; transformedY3 = ((y3 * cameraFovY) / (float)z3) + cameraCenterY; transformedY4 = ((y4 * cameraFovY) / (float)z4) + cameraCenterY; if(z1>DEPTH_THRESHOLD && z2>DEPTH_THRESHOLD && z3>DEPTH_THRESHOLD && z4>DEPTH_THRESHOLD) { osystem_draw3dQuad(transformedX1,transformedY1,z1, transformedX2,transformedY2,z2, transformedX3,transformedY3,z3, transformedX4,transformedY4,z4, color, transprency); } //osystem_draw3dQuad(x1,y1,z1, x2,y2,z2, x3,y3,z3, x4,y4,z4, color); } void drawProjectedBox(int x1,int x2,int y1,int y2,int z1,int z2, int color, int transprency) { //bottom drawProjectedQuad((float)x1,(float)x1,(float)x2,(float)x2,(float)y1,(float)y1,(float)y1,(float)y1,(float)z1,(float)z2,(float)z2,(float)z1,color,transprency); //top drawProjectedQuad((float)x1,(float)x1,(float)x2,(float)x2,(float)y2,(float)y2,(float)y2,(float)y2,(float)z1,(float)z2,(float)z2,(float)z1,color,transprency); //left drawProjectedQuad((float)x1,(float)x1,(float)x1,(float)x1,(float)y1,(float)y2,(float)y2,(float)y1,(float)z1,(float)z1,(float)z2,(float)z2,color,transprency); //right drawProjectedQuad((float)x2,(float)x2,(float)x2,(float)x2,(float)y1,(float)y2,(float)y2,(float)y1,(float)z1,(float)z1,(float)z2,(float)z2,color,transprency); //front drawProjectedQuad((float)x1,(float)x2,(float)x2,(float)x1,(float)y1,(float)y1,(float)y2,(float)y2,(float)z1,(float)z1,(float)z1,(float)z1,color,transprency); //back drawProjectedQuad((float)x1,(float)x2,(float)x2,(float)x1,(float)y1,(float)y1,(float)y2,(float)y2,(float)z2,(float)z2,(float)z2,(float)z2,color,transprency); } void drawRoomZv(ZVStruct* zoneData, int color, int transparency) { ZVStruct cameraZv = {-100,100,-100,100,-100,100}; cameraZv.ZVX1 += translateX; cameraZv.ZVX2 += translateX; cameraZv.ZVY1 += translateY; cameraZv.ZVY2 += translateY; cameraZv.ZVZ1 += translateZ; cameraZv.ZVZ2 += translateZ; if(CubeIntersect(&cameraZv,zoneData)) { return; } drawProjectedBox(zoneData->ZVX1,zoneData->ZVX2,zoneData->ZVY1,zoneData->ZVY2,zoneData->ZVZ1,zoneData->ZVZ2,color,transparency); } void drawRoomZvLine(ZVStruct* zoneData, int color) { ZVStruct cameraZv = {-100,100,-100,100,-100,100}; cameraZv.ZVX1 += translateX; cameraZv.ZVX2 += translateX; cameraZv.ZVY1 += translateY; cameraZv.ZVY2 += translateY; cameraZv.ZVZ1 += translateZ; cameraZv.ZVZ2 += translateZ; if(CubeIntersect(&cameraZv,zoneData)) { return; } drawProjectedLine(zoneData->ZVX1,zoneData->ZVY1,zoneData->ZVZ1,zoneData->ZVX1,zoneData->ZVY1,zoneData->ZVZ2,color); drawProjectedLine(zoneData->ZVX1,zoneData->ZVY1,zoneData->ZVZ2,zoneData->ZVX2,zoneData->ZVY1,zoneData->ZVZ2,color); drawProjectedLine(zoneData->ZVX2,zoneData->ZVY1,zoneData->ZVZ2,zoneData->ZVX2,zoneData->ZVY1,zoneData->ZVZ1,color); drawProjectedLine(zoneData->ZVX2,zoneData->ZVY1,zoneData->ZVZ1,zoneData->ZVX1,zoneData->ZVY1,zoneData->ZVZ1,color); drawProjectedLine(zoneData->ZVX1,zoneData->ZVY2,zoneData->ZVZ1,zoneData->ZVX1,zoneData->ZVY2,zoneData->ZVZ2,color); drawProjectedLine(zoneData->ZVX1,zoneData->ZVY2,zoneData->ZVZ2,zoneData->ZVX2,zoneData->ZVY2,zoneData->ZVZ2,color); drawProjectedLine(zoneData->ZVX2,zoneData->ZVY2,zoneData->ZVZ2,zoneData->ZVX2,zoneData->ZVY2,zoneData->ZVZ1,color); drawProjectedLine(zoneData->ZVX2,zoneData->ZVY2,zoneData->ZVZ1,zoneData->ZVX1,zoneData->ZVY2,zoneData->ZVZ1,color); drawProjectedLine(zoneData->ZVX1,zoneData->ZVY1,zoneData->ZVZ1,zoneData->ZVX1,zoneData->ZVY2,zoneData->ZVZ1,color); drawProjectedLine(zoneData->ZVX1,zoneData->ZVY1,zoneData->ZVZ2,zoneData->ZVX1,zoneData->ZVY2,zoneData->ZVZ2,color); drawProjectedLine(zoneData->ZVX2,zoneData->ZVY1,zoneData->ZVZ2,zoneData->ZVX2,zoneData->ZVY2,zoneData->ZVZ2,color); drawProjectedLine(zoneData->ZVX2,zoneData->ZVY1,zoneData->ZVZ1,zoneData->ZVX2,zoneData->ZVY2,zoneData->ZVZ1,color); } void drawZone(char* zoneData,int color) { int x1; int x2; int y1; int y2; int z1; int z2; int type; ZVStruct tempZv; ZVStruct cameraZv = {-100,100,-100,100,-100,100}; type = *(s16*)(zoneData+0xE); x1 = *( s16*)(zoneData+0x0); x2 = *( s16*)(zoneData+0x2); y1 = *( s16*)(zoneData+0x4); y2 = *( s16*)(zoneData+0x6); z1 = *( s16*)(zoneData+0x8); z2 = *( s16*)(zoneData+0xA); cameraZv.ZVX1 += translateX; cameraZv.ZVX2 += translateX; cameraZv.ZVY1 += translateY; cameraZv.ZVY2 += translateY; cameraZv.ZVZ1 += translateZ; cameraZv.ZVZ2 += translateZ; tempZv.ZVX1 = READ_LE_S16(zoneData+0x00); tempZv.ZVX2 = READ_LE_S16(zoneData+0x02); tempZv.ZVY1 = READ_LE_S16(zoneData+0x04); tempZv.ZVY2 = READ_LE_S16(zoneData+0x06); tempZv.ZVZ1 = READ_LE_S16(zoneData+0x08); tempZv.ZVZ2 = READ_LE_S16(zoneData+0x0A); if(CubeIntersect(&cameraZv,&tempZv)) { return; } drawProjectedBox(x1,x2,y1,y2,z1,z2,type,255); } void drawOverlayZone(char* zoneData,int color) { int x1; int x2; int y1; int y2; int z1; int z2; x1 = *( s16*)(zoneData+0x0) * 10; z1 = *( s16*)(zoneData+0x2) * 10; x2 = *( s16*)(zoneData+0x4) * 10; z2 = *( s16*)(zoneData+0x6) * 10; y1=0; y2=0; drawProjectedBox(x1,x2,y1,y2,z1,z2,color,255); } void drawSceZone(int roomNumber) { u32 i; ZVStruct dataLocal; for(i=0;i= zoneX1 && Z1 >= zoneZ1 && X2 <= zoneX2 && Z2 <= zoneZ2) { return(1); } data+=0x8; } return(0); } void drawBgOverlay(tObject* actorPtr) { char* data; char* data2; int numOverlayZone; actorPtr->screenXMin = BBox3D1; actorPtr->screenYMin = BBox3D2; actorPtr->screenXMax = BBox3D3; actorPtr->screenYMax = BBox3D4; //if(actorPtr->trackMode != 1) // return; SetClip(BBox3D1, BBox3D2, BBox3D3, BBox3D4); cameraDataStruct* pCamera = cameraDataTable[NumCamera]; // look for the correct room data of that camera cameraViewedRoomStruct* pcameraViewedRoomData = NULL; int relativeCameraIndex = -1; for(int i=0; inumViewedRooms; i++) { if(pCamera->viewedRoomTable[i].viewedRoomIdx == actorPtr->room) { pcameraViewedRoomData = &pCamera->viewedRoomTable[i]; relativeCameraIndex = i; break; } } if(pcameraViewedRoomData == NULL) return; if(g_gameId == AITD1) { data2 = room_PtrCamera[NumCamera] + pcameraViewedRoomData->offsetToMask; data = data2; data+=2; numOverlayZone = *(s16*)(data2); for(int i=0;izv.ZVX1 / 10, actorPtr->zv.ZVX2 / 10, actorPtr->zv.ZVZ1 / 10, actorPtr->zv.ZVZ2 / 10, data+4, *(s16*)(data) )) { osystem_setClip(clipLeft, clipTop, clipRight, clipBottom); osystem_drawMask(relativeCameraIndex, i); osystem_clearClip(); /* int j; numOverlay = *(s16*)src; src += 2; for(j=0;jmasks.size();i++) { cameraMaskStruct* pMaskZones = &pcameraViewedRoomData->masks[i]; for(int j=0; jnumTestRect; j++) { rectTestStruct* pRect = &pMaskZones->rectTests[j]; int actorX1 = actorPtr->zv.ZVX1 / 10; int actorX2 = actorPtr->zv.ZVX2 / 10; int actorZ1 = actorPtr->zv.ZVZ1 / 10; int actorZ2 = actorPtr->zv.ZVZ2 / 10; if(actorX1 >= pRect->zoneX1 && actorZ1 >= pRect->zoneZ1 && actorX2 <= pRect->zoneX2 && actorZ2 <= pRect->zoneZ2) { osystem_setClip(clipLeft, clipTop, clipRight, clipBottom); osystem_drawMask(relativeCameraIndex, i); osystem_clearClip(); break; } } } } SetClip(0,0,319,199); } void AffSpecialObjet(int actorIdx) // draw flow { //actorStruct* actorPtr = &actorTable[actorIdx]; //char* data = printTextSub2(hqrUnk, actorPtr->FRAME); // TODO: finish } void getHotPoint(int hotPointIdx, sBody* bodyPtr, point3dStruct* hotPoint) { hotPoint->x = 0; hotPoint->y = 0; hotPoint->z = 0; if(bodyPtr->m_flags &2) { ASSERT(hotPointIdx < bodyPtr->m_groups.size()); if(hotPointIdx < bodyPtr->m_groups.size()) { auto& group = bodyPtr->m_groups[hotPointIdx]; int pointIdx = group.m_baseVertices; // first point *hotPoint = pointBuffer[pointIdx]; } } } void AllRedraw(int flagFlip) { uiLayer.fill(0); //if(flagFlip == 2) { if(cameraBackgroundChanged) { osystem_CopyBlockPhys((unsigned char*)aux,0,0,320,200); cameraBackgroundChanged = false; } } if(flagFlip== 0) { //ClsAuxLog(); } else { NbPhysBoxs = 0; FastCopyScreen(aux2,logicalScreen); } SetClip(0,0,319,199); NbLogBoxs = 0; for(int i=0;iid, 0, 0, PtrAnim2D); // TODO: Clipping stuff osystem_CopyBlockPhys((unsigned char*)logicalScreen, 0, 0, 320, 200); } else { tObject* actorPtr = &ListObjets[currentDrawActor]; // this is commented out to draw actors backed into the background //if(actorPtr->_flags & (AF_ANIMATED + AF_DRAWABLE + AF_SPECIAL)) { actorPtr->objectType &= ~AF_DRAWABLE; if (actorPtr->objectType & AF_SPECIAL) { AffSpecialObjet(currentDrawActor); } else { if (actorPtr->objectType & AF_OBJ_2D) { sHybrid* pHybrid = HQR_Get(HQ_Hybrides, actorPtr->ANIM); s16 numHybrid = pHybrid->animations[actorPtr->bodyNum].anims[actorPtr->frame].id; AffHyb(numHybrid, 0, 0, pHybrid); // TODO: bounding volume } else { sBody* bodyPtr = HQR_Get(HQ_Bodys, actorPtr->bodyNum); if (HQ_Load) { // initAnimInBody(actorPtr->FRAME, HQR_Get(listAnim, actorPtr->ANIM), bodyPtr); } AffObjet(actorPtr->worldX + actorPtr->stepX, actorPtr->worldY + actorPtr->stepY, actorPtr->worldZ + actorPtr->stepZ, actorPtr->alpha, actorPtr->beta, actorPtr->gamma, bodyPtr); if (actorPtr->animActionType != 0) { if (actorPtr->hotPointID != -1) { getHotPoint(actorPtr->hotPointID, bodyPtr, &actorPtr->hotPoint); } } } } if (BBox3D1 < 0) BBox3D1 = 0; if (BBox3D3 > 319) BBox3D3 = 319; if (BBox3D2 < 0) BBox3D2 = 0; if (BBox3D4 > 199) BBox3D4 = 199; if (BBox3D1 <= 319 && BBox3D2 <= 199 && BBox3D3 >= 0 && BBox3D4 >= 0) // is the character on screen ? { if (g_gameId == AITD1) { if (actorPtr->indexInWorld == CVars[getCVarsIdx(LIGHT_OBJECT)]) { lightX = (BBox3D3 + BBox3D1) / 2; lightY = (BBox3D4 + BBox3D2) / 2; } } #ifdef FITD_DEBUGGER if (backgroundMode == backgroundModeEnum_2D) #endif { //if(g_gameId == AITD1) drawBgOverlay(actorPtr); } //addToRedrawBox(); } else { actorPtr->screenYMax = -1; actorPtr->screenXMax = -1; actorPtr->screenYMin = -1; actorPtr->screenXMin = -1; } } } } #ifdef FITD_DEBUGGER { if (backgroundMode == backgroundModeEnum_3D) { for (int i = 0; i < NUM_MAX_OBJECT; i++) { tObject* actorPtr = &ListObjets[i]; if (actorPtr->indexInWorld != -1) { drawZv(actorPtr); } } } ///////////////////////////////////// for (int i = 0; i < getNumberOfRoom(); i++) { if (hardColDisplayMode != displayNone) { drawHardCol(i); } if (sceColDisplayMode != displayNone) { drawSceZone(i); } } //drawConverZones(); //drawMaskZones(); } #endif if(drawTextOverlay()) { //addToRedrawBox(); } if(!lightOff) { if(flagFlip) { if(flagFlip==2 || lightVar2) { //makeBlackPalette(); osystem_flip(NULL); FadeInPhys(0x10,0); lightVar2 = 0; } else { //osystem_flip(NULL); } } else { //mainDrawSub1(); } } else { } // osystem_stopFrame(); // osystem_flip(NULL); flagRedraw = 0; } void walkStep(int angle1, int angle2, int angle3) { Rotate(angle3,angle1,angle2,&animMoveZ,&animMoveX); } void addActorToBgInscrust(int actorIdx) { ListObjets[actorIdx].objectType |= AF_BOXIFY + AF_DRAWABLE; ListObjets[actorIdx].objectType &= ~AF_ANIMATED; //FlagRefreshAux2 = 1; } int CubeIntersect(ZVStruct* zvPtr1,ZVStruct* zvPtr2) { if(zvPtr1->ZVX1 >= zvPtr2->ZVX2) return 0; if(zvPtr2->ZVX1 >= zvPtr1->ZVX2) return 0; if(zvPtr1->ZVY1 >= zvPtr2->ZVY2) return 0; if(zvPtr2->ZVY1 >= zvPtr1->ZVY2) return 0; if(zvPtr1->ZVZ1 >= zvPtr2->ZVZ2) return 0; if(zvPtr2->ZVZ1 >= zvPtr1->ZVZ2) return 0; return 1; } void AdjustZV(ZVStruct* zvPtr, int startRoom, int destRoom) { unsigned int Xdif = 10*(roomDataTable[destRoom].worldX - roomDataTable[startRoom].worldX); unsigned int Ydif = 10*(roomDataTable[destRoom].worldY - roomDataTable[startRoom].worldY); unsigned int Zdif = 10*(roomDataTable[destRoom].worldZ - roomDataTable[startRoom].worldZ); zvPtr->ZVX1 -= Xdif; zvPtr->ZVX2 -= Xdif; zvPtr->ZVY1 += Ydif; zvPtr->ZVY2 += Ydif; zvPtr->ZVZ1 += Zdif; zvPtr->ZVZ2 += Zdif; } int CheckObjectCol(int actorIdx, ZVStruct* zvPtr) { int currentCollisionSlot = 0; int actorRoom = ListObjets[actorIdx].room; for(int i=0;i<3;i++) { currentProcessedActorPtr->COL[i] = -1; } for(int i=0;iindexInWorld == -1) continue; if (i == actorIdx) continue; ZVStruct* currentActorZv = ¤tActor->zv; if (currentActor->room != actorRoom) { ZVStruct localZv; CopyZV(zvPtr, &localZv); AdjustZV(&localZv, actorRoom, currentActor->room); if (CubeIntersect(&localZv, currentActorZv)) { currentProcessedActorPtr->COL[currentCollisionSlot++] = i; if (currentCollisionSlot == 3) return(3); } } else { if (CubeIntersect(zvPtr, currentActorZv)) { currentProcessedActorPtr->COL[currentCollisionSlot++] = i; if (currentCollisionSlot == 3) return(3); } } } return(currentCollisionSlot); } void take(int objIdx) { tWorldObject* objPtr = &ListWorldObjets[objIdx]; if(numObjInInventoryTable[currentInventory] == 0) { inventoryTable[currentInventory][0] = objIdx; } else { int i; for(i=numObjInInventoryTable[currentInventory];i>0;i--) { inventoryTable[currentInventory][i+1] = inventoryTable[currentInventory][i]; } inventoryTable[currentInventory][1] = objIdx; } numObjInInventoryTable[currentInventory]++; action = 0x800; executeFoundLife(objIdx); if(objPtr->objIndex != -1) { DeleteObjet(objPtr->objIndex); } objPtr->foundFlag &= 0xBFFF; objPtr->foundFlag |= 0x8000; objPtr->room = -1; objPtr->stage = -1; } void Glisser(int flag) { switch(flag) { case 1: case 2: { hardColStepZ = 0; break; } case 4: case 8: { hardColStepX = 0; break; } default: { break; } } } void GereCollision(ZVStruct* oldZv, ZVStruct* animatedZv, ZVStruct* fixZv) { s32 oldpos = 0; s32 oldtype; s32 halfX; s32 halfZ; s32 pos; s32 type; if(oldZv->ZVX2 > fixZv->ZVX1) { if(fixZv->ZVX2 <= oldZv->ZVX1) { oldpos = 8; // right } else { oldpos = 0; // center } } else { oldpos = 4; // left } if(oldZv->ZVZ2 > fixZv->ZVZ1) { if(oldZv->ZVZ1 >= fixZv->ZVZ2) { oldpos |= 2; } else { oldpos |= 0; // center } } else { oldpos |= 1; } if( (oldpos == 5) || (oldpos == 9) || (oldpos == 6) || (oldpos == 10) ) { oldtype = 2; // corner } else { if(oldpos == 0) { oldtype = 0; hardColStepZ = 0; hardColStepX = 0; return; } else { oldtype = 1; // corner } } halfX = (animatedZv->ZVX1 + animatedZv->ZVX2) / 2; halfZ = (animatedZv->ZVZ1 + animatedZv->ZVZ2) / 2; if(fixZv->ZVX1 > halfX) { pos = 4; // left } else { if(fixZv->ZVX2 < halfX) { pos = 0; // center } else { pos = 8; // right } } if(fixZv->ZVZ1 > halfZ) { pos |= 1; // up } else { if(fixZv->ZVZ2 < halfZ) { pos |= 0; // center } else { pos |= 2; // bellow } } if( (pos == 5) || (pos == 9) || (pos == 6) || (pos == 10) ) { type = 2; // corner } else { if(pos == 0) { type = 0; // center } else { type = 1; // border } } if(oldtype == 1) // border { Glisser(oldpos); } else { if ((type == 1) && (pos & oldpos)) { Glisser(pos); } else { if ((pos == oldpos) || (pos+oldpos == 15)) { int Xmod = abs(animatedZv->ZVX1 - oldZv->ZVX1); // recheck int Zmod = abs(animatedZv->ZVZ1 - oldZv->ZVZ1); if (Xmod > Zmod) { hardColStepZ = 0; } else { hardColStepX = 0; } } else { if ((type == 0) || ((type == 1) && ((pos & oldpos) == 0))) { hardColStepZ = 0; hardColStepX = 0; } else { Glisser(oldpos & pos); } } } } } int AsmCheckListCol(ZVStruct* zvPtr, roomDataStruct* pRoomData) { u16 i; int hardColVar = 0; hardColStruct* pCurrentEntry = pRoomData->hardColTable.data(); #ifdef FITD_DEBUGGER if(debuggerVar_noHardClip) return 0; #endif for(i=0;inumHardCol;i++) { if(((pCurrentEntry->zv.ZVX1) < (zvPtr->ZVX2)) && ((zvPtr->ZVX1) < (pCurrentEntry->zv.ZVX2))) { if(((pCurrentEntry->zv.ZVY1) < (zvPtr->ZVY2)) && ((zvPtr->ZVY1) < (pCurrentEntry->zv.ZVY2))) { if(((pCurrentEntry->zv.ZVZ1) < (zvPtr->ZVZ2)) && ((zvPtr->ZVZ1) < (pCurrentEntry->zv.ZVZ2))) { ASSERT(hardColVar < 10); hardColTable[hardColVar++] = pCurrentEntry; } } } pCurrentEntry++; } return hardColVar; } void menuWaitVSync() { } int testCrossProduct(int x1, int z1, int x2, int z2, int x3, int z3, int x4, int z4) { int returnFlag = 0; int xAB = x1 - x2; int yCD = z3 - z4; int xCD = x3 - x4; int yAB = z1 - z2; int xAC = x1 - x3; int yAC = z1 - z3; int DotProduct = (xAB * yCD) - (xCD * yAC); if(DotProduct) { int Dda = xAC*yCD - xCD*yAC; int Dmu = -xAB*yAC + xAC*yAB; if(DotProduct<0) { DotProduct = -DotProduct; Dda = -Dda; Dmu = -Dmu; } if(Dda >= 0 && Dmu >= 0 && DotProduct >= Dda && DotProduct >= Dmu) returnFlag = 1; } return(returnFlag); } int isInPoly(int x1, int x2, int z1, int z2, cameraViewedRoomStruct* pCameraZoneDef) { int xMid = (x1+x2)/2; int zMid = (z1+z2)/2; int i; for(i=0;icoverZones.size();i++) { int j; int flag = 0; for(j=0;jcoverZones[i].numPoints;j++) { int zoneX1; int zoneZ1; int zoneX2; int zoneZ2; zoneX1= pCameraZoneDef->coverZones[i].pointTable[j].x; zoneZ1= pCameraZoneDef->coverZones[i].pointTable[j].y; zoneX2= pCameraZoneDef->coverZones[i].pointTable[j+1].x; zoneZ2= pCameraZoneDef->coverZones[i].pointTable[j+1].y; if(testCrossProduct(xMid,zMid,xMid-10000,zMid,zoneX1,zoneZ1,zoneX2,zoneZ2)) { flag |= 1; } if(testCrossProduct(xMid,zMid,xMid+10000,zMid,zoneX1,zoneZ1,zoneX2,zoneZ2)) { flag |= 2; } } if(flag == 3) { return(1); } } return(0); } int findBestCamera(void) { int foundAngle = 32000; int foundCamera = -1; tObject* actorPtr = &ListObjets[currentCameraTargetActor]; int x1 = actorPtr->zv.ZVX1/10; int x2 = actorPtr->zv.ZVX2/10; int z1 = actorPtr->zv.ZVZ1/10; int z2 = actorPtr->zv.ZVZ2/10; int i; for(i=0;ibeta + (((cameraDataTable[i]->beta)+0x200)&0x3FF); if(newAngle <0 ) { newAngle = -newAngle; } if(newAngle < foundAngle) { foundAngle = newAngle; foundCamera = i; } } } return(foundCamera); } void GereSwitchCamera(void) { int localCurrentCam = NumCamera; int newCamera; if(NumCamera!=-1) { if (currentCameraTargetActor == -1) { // TODO: Happens at the start of AITD3, likely a bug return; } tObject* actorPtr; int zvx1; int zvx2; int zvz1; int zvz2; actorPtr = &ListObjets[currentCameraTargetActor]; zvx1 = actorPtr->zv.ZVX1/10; zvx2 = actorPtr->zv.ZVX2/10; zvz1 = actorPtr->zv.ZVZ1/10; zvz2 = actorPtr->zv.ZVZ2/10; if(isInPoly(zvx1,zvx2,zvz1,zvz2,currentCameraZoneList[NumCamera])) // is still in current camera zone ? { return; } } #ifdef FITD_DEBUGGER //printf("Exited current camera cover zone...\n"); #endif newCamera = findBestCamera(); // find new camera if(newCamera!=-1) { localCurrentCam = newCamera; } if(NumCamera != localCurrentCam) { NewNumCamera = localCurrentCam; FlagInitView = 1; } #ifdef FITD_DEBUGGER /* if(newCamera == -1) { printf("No new camera found...\n"); }*/ #endif } bool isPointInZV(int x, int y, int z, ZVStruct* pZV) { if(pZV->ZVX1 <= x && pZV->ZVX2 >= x) { if(pZV->ZVY1 <= y && pZV->ZVY2 >= y) { if(pZV->ZVZ1 <= z && pZV->ZVZ2 >= z) { return(true); } } } return false; } sceZoneStruct* processActor2Sub(int x, int y, int z, roomDataStruct* pRoomData) { u32 i; sceZoneStruct* pCurrentZone; pCurrentZone = pRoomData->sceZoneTable.data(); for(i=0;inumSceZone;i++) { if(pCurrentZone->zv.ZVX1 <= x && pCurrentZone->zv.ZVX2 >= x) { if(pCurrentZone->zv.ZVY1 <= y && pCurrentZone->zv.ZVY2 >= y) { if(pCurrentZone->zv.ZVZ1 <= z && pCurrentZone->zv.ZVZ2 >= z) { return(pCurrentZone); } } } pCurrentZone++; } return(NULL); } void GereDec() { bool onceMore = false; bool flagFloorChange = false; int zoneIdx = 0; do { onceMore = false; roomDataStruct* pRoomData = &roomDataTable[currentProcessedActorPtr->room]; for(u32 i=0;inumSceZone;i++) { sceZoneStruct* pCurrentZone = &pRoomData->sceZoneTable[i]; if(isPointInZV( currentProcessedActorPtr->roomX + currentProcessedActorPtr->stepX, currentProcessedActorPtr->roomY + currentProcessedActorPtr->stepY, currentProcessedActorPtr->roomZ + currentProcessedActorPtr->stepZ, &pCurrentZone->zv)) { switch(pCurrentZone->type) { case 0: { int oldRoom = currentProcessedActorPtr->room; currentProcessedActorPtr->room = (short)pCurrentZone->parameter; int x = (roomDataTable[currentProcessedActorPtr->room].worldX - roomDataTable[oldRoom].worldX) * 10; int y = (roomDataTable[currentProcessedActorPtr->room].worldY - roomDataTable[oldRoom].worldY) * 10; int z = (roomDataTable[currentProcessedActorPtr->room].worldZ - roomDataTable[oldRoom].worldZ) * 10; currentProcessedActorPtr->roomX -= x; currentProcessedActorPtr->roomY += y; currentProcessedActorPtr->roomZ += z; currentProcessedActorPtr->zv.ZVX1 -= x; currentProcessedActorPtr->zv.ZVX2 -= x; currentProcessedActorPtr->zv.ZVY1 += y; currentProcessedActorPtr->zv.ZVY2 += y; currentProcessedActorPtr->zv.ZVZ1 += z; currentProcessedActorPtr->zv.ZVZ2 += z; onceMore = true; if(currentProcessedActorIdx == currentCameraTargetActor) { FlagChangeSalle = 1; NewNumSalle = (short)pCurrentZone->parameter; if (g_gameId > AITD1) { ChangeSalle(NewNumSalle); // Hack: this wasn't in the original game, but is required here, or else we would use the current camera index in the new room and potentially go out of bound InitView(); } } else { FlagGenereAffList = 1; } startChrono(¤tProcessedActorPtr->ROOM_CHRONO); break; } case 8: { assert(g_gameId != AITD1); if(g_gameId != AITD1) { currentProcessedActorPtr->hardMat = (short)pCurrentZone->parameter; } break; } case 9: // Scenar { if((g_gameId == AITD1) || !flagFloorChange) { currentProcessedActorPtr->HARD_DEC = (short)pCurrentZone->parameter; } break; } case 10: // stage { int life = ListWorldObjets[currentProcessedActorPtr->indexInWorld].floorLife; if(life==-1) return; currentProcessedActorPtr->life = life; currentProcessedActorPtr->HARD_DEC = (short)pCurrentZone->parameter; flagFloorChange = true; break; } } if(g_gameId == AITD1) // AITD1 stops at the first zone return; } if(onceMore) break; } }while(onceMore); } int checkLineProjectionWithActors( int actorIdx, int X, int Y, int Z, int beta, int room, int param ) { ZVStruct localZv; int foundFlag = -2; int tempX; int tempZ; localZv.ZVX1 = X - param; localZv.ZVX2 = X + param; localZv.ZVY1 = Y - param; localZv.ZVY2 = Y + param; localZv.ZVZ1 = Z - param; localZv.ZVZ2 = Z + param; walkStep(param * 2, 0, beta); while(foundFlag == -2) { localZv.ZVX1 += animMoveX; localZv.ZVX2 += animMoveX; localZv.ZVZ1 += animMoveZ; localZv.ZVZ2 += animMoveZ; tempX = X; tempZ = Z; X += animMoveX; Z += animMoveZ; if(X > 20000 || X < -20000 || Z > 20000 || Z < -20000) { foundFlag = -1; break; } if(AsmCheckListCol(&localZv, &roomDataTable[room]) <= 0) { foundFlag = -1; } else { for(int i=0;iindexInWorld != -1 && i != actorIdx && !(currentActorPtr->objectType & AF_SPECIAL)) { ZVStruct* zvPtr = ¤tActorPtr->zv; if(room != currentActorPtr->room) { ZVStruct localZv2; CopyZV(&localZv, &localZv2); AdjustZV(&localZv2, room, currentActorPtr->room); if(!CubeIntersect(&localZv2,zvPtr)) { currentActorPtr++; continue; } } else { if(!CubeIntersect(&localZv,zvPtr)) { currentActorPtr++; continue; } } foundFlag = i; break; } } } } animMoveX = tempX; animMoveY = Y; animMoveZ = tempZ; return(foundFlag); } void PutAtObjet(int objIdx, int objIdxToPutAt) { tWorldObject* objPtr = &ListWorldObjets[objIdx]; tWorldObject* objPtrToPutAt = &ListWorldObjets[objIdxToPutAt]; if(objPtrToPutAt->objIndex != -1) { tObject* actorToPutAtPtr = &ListObjets[objPtrToPutAt->objIndex]; DeleteInventoryObjet(objIdx); if(objPtr->objIndex == -1) { objPtr->x = actorToPutAtPtr->roomX; objPtr->y = actorToPutAtPtr->roomY; objPtr->z = actorToPutAtPtr->roomZ; objPtr->room = actorToPutAtPtr->room; objPtr->stage = actorToPutAtPtr->stage; objPtr->alpha = actorToPutAtPtr->alpha; objPtr->beta = actorToPutAtPtr->beta; objPtr->gamma = actorToPutAtPtr->gamma; objPtr->foundFlag |= 0x4000; objPtr->flags |= 0x80; // FlagGenereActiveList = 1; // FlagRefreshAux2 = 1; } else { currentProcessedActorPtr->roomX = actorToPutAtPtr->roomX; currentProcessedActorPtr->roomY = actorToPutAtPtr->roomY; currentProcessedActorPtr->roomZ = actorToPutAtPtr->roomZ; currentProcessedActorPtr->room = actorToPutAtPtr->room; currentProcessedActorPtr->stage = actorToPutAtPtr->stage; currentProcessedActorPtr->alpha = actorToPutAtPtr->alpha; currentProcessedActorPtr->beta = actorToPutAtPtr->beta; currentProcessedActorPtr->gamma = actorToPutAtPtr->gamma; ListWorldObjets[currentProcessedActorPtr->indexInWorld].foundFlag |= 0x4000; ListWorldObjets[currentProcessedActorPtr->indexInWorld].flags |= 0x80; // FlagGenereActiveList = 1; // FlagRefreshAux2 = 1; } } else { DeleteInventoryObjet(objIdx); if(objPtr->objIndex == -1) { objPtr->x = objPtrToPutAt->x; objPtr->y = objPtrToPutAt->y; objPtr->z = objPtrToPutAt->z; objPtr->room = objPtrToPutAt->room; objPtr->stage = objPtrToPutAt->stage; objPtr->alpha = objPtrToPutAt->alpha; objPtr->beta = objPtrToPutAt->beta; objPtr->gamma = objPtrToPutAt->gamma; objPtr->foundFlag |= 0x4000; objPtr->flags |= 0x80; // FlagGenereActiveList = 1; // FlagRefreshAux2 = 1; } else { currentProcessedActorPtr->roomX = objPtrToPutAt->x; currentProcessedActorPtr->roomY = objPtrToPutAt->y; currentProcessedActorPtr->roomZ = objPtrToPutAt->z; currentProcessedActorPtr->room = objPtrToPutAt->room; currentProcessedActorPtr->stage = objPtrToPutAt->stage; currentProcessedActorPtr->alpha = objPtrToPutAt->alpha; currentProcessedActorPtr->beta = objPtrToPutAt->beta; currentProcessedActorPtr->gamma = objPtrToPutAt->gamma; ListWorldObjets[currentProcessedActorPtr->indexInWorld].foundFlag |= 0x4000; ListWorldObjets[currentProcessedActorPtr->indexInWorld].flags |= 0x80; // FlagGenereActiveList = 1; // FlagRefreshAux2 = 1; } } } void throwStoppedAt(int x, int z) { int x2; int y2; int z2; int foundPosition; int step; ZVStruct zvCopy; ZVStruct zvLocal; sBody* bodyPtr = HQR_Get(HQ_Bodys,currentProcessedActorPtr->bodyNum); GiveZVObjet(bodyPtr,&zvLocal); x2 = x; y2 = (currentProcessedActorPtr->roomY/2000)*2000; z2 = z; foundPosition = 0; step = 0; while(!foundPosition) { walkStep(0,-step,currentProcessedActorPtr->beta+0x200); CopyZV(&zvLocal,&zvCopy); x2 = x + animMoveX; z2 = z + animMoveZ; zvCopy.ZVX1 += x2; zvCopy.ZVX2 += x2; zvCopy.ZVY1 += y2; zvCopy.ZVY2 += y2; zvCopy.ZVZ1 += z2; zvCopy.ZVZ2 += z2; if(!AsmCheckListCol(&zvCopy,&roomDataTable[currentProcessedActorPtr->room])) { foundPosition = 1; } if(foundPosition) { if(y2<-500) { zvCopy.ZVY1 += 100; // is the object reachable ? (100 is Carnby height. If hard col at Y + 100, carnby can't reach that spot) zvCopy.ZVY2 += 100; if(!AsmCheckListCol(&zvCopy,&roomDataTable[currentProcessedActorPtr->room])) { y2 += 2000; foundPosition = 0; } else { zvCopy.ZVY1 -= 100; zvCopy.ZVY2 -= 100; } } } else { step+=100; } } currentProcessedActorPtr->worldX = x2; currentProcessedActorPtr->roomX = x2; currentProcessedActorPtr->worldY = y2; currentProcessedActorPtr->roomY = y2; currentProcessedActorPtr->worldZ = z2; currentProcessedActorPtr->roomZ = z2; currentProcessedActorPtr->stepX = 0; currentProcessedActorPtr->stepZ = 0; currentProcessedActorPtr->animActionType = 0; currentProcessedActorPtr->speed = 0; currentProcessedActorPtr->gamma = 0; GiveZVObjet(bodyPtr,¤tProcessedActorPtr->zv); currentProcessedActorPtr->zv.ZVX1 += x2; currentProcessedActorPtr->zv.ZVX2 += x2; currentProcessedActorPtr->zv.ZVY1 += y2; currentProcessedActorPtr->zv.ZVY2 += y2; currentProcessedActorPtr->zv.ZVZ1 += z2; currentProcessedActorPtr->zv.ZVZ2 += z2; ListWorldObjets[currentProcessedActorPtr->indexInWorld].foundFlag |= 0x4000; ListWorldObjets[currentProcessedActorPtr->indexInWorld].foundFlag &= 0xEFFF; addActorToBgInscrust(currentProcessedActorIdx); } void startGame(int startupFloor, int startupRoom, int allowSystemMenu) { LoadWorld(); initVars(); LoadEtage(startupFloor); NumCamera = -1; ChangeSalle(startupRoom); NewNumCamera = 0; FlagInitView = 2; InitView(); PlayWorld(allowSystemMenu, 1); /*freeScene(); fadeOut(8,0);*/ } int parseAllSaves(int arg) { return(0); // TODO : make real implementation } void detectGame(void) { if(fileExists("LISTBOD2.PAK")) { g_gameId = AITD1; CVars.resize(45); currentCVarTable = AITD1KnownCVars; printf("Detected Alone in the Dark\n"); #ifndef AITD_UE4 SDL_SetWindowTitle(gWindowBGFX, "Alone in the Dark"); #endif return; } if(fileExists("PERE.PAK")) { g_gameId = JACK; CVars.resize(70); currentCVarTable = AITD2KnownCVars; printf("Detected Jack in the Dark\n"); #ifndef AITD_UE4 SDL_SetWindowTitle(gWindowBGFX, "Jack in the Dark"); #endif return; } if(fileExists("MER.PAK")) { g_gameId = AITD2; CVars.resize(70); currentCVarTable = AITD2KnownCVars; printf("Detected Alone in the Dark 2\n"); #ifndef AITD_UE4 SDL_SetWindowTitle(gWindowBGFX, "Alone in the Dark 2"); #endif return; } if(fileExists("AN1.PAK")) { g_gameId = AITD3; CVars.resize(70); currentCVarTable = AITD2KnownCVars; printf("Detected Alone in the Dark 3\n"); #ifndef AITD_UE4 SDL_SetWindowTitle(gWindowBGFX, "Alone in the Dark 3"); #endif return; } if(fileExists("PURSUIT.PAK")) { g_gameId = TIMEGATE; CVars.resize(100); // TODO: figure this currentCVarTable = AITD2KnownCVars; // TODO: figure this printf("Detected Time Gate\n"); #ifndef AITD_UE4 SDL_SetWindowTitle(gWindowBGFX, "Time Gate"); #endif return; } printf("FATAL: Game detection failed...\n"); assert(0); } extern "C" { int FitdMain(int argc, char* argv[]); void setCurrentContext(void); } int FitdMain(int argc, char* argv[]) { #ifndef AITD_UE4 initBgfxGlue(argc, argv); #endif osystem_startOfFrame(); // int protectionToBeDone = 1; OpenProgram(); paletteFill(currentGamePalette,0,0,0); loadPalette(); switch(g_gameId) { case AITD1: startAITD1(); break; case JACK: startJACK(); break; case AITD2: startAITD2(); break; case AITD3: startAITD3(); break; case TIMEGATE: startGame(0, 5, 1); break; default: assert(0); break; } return(0); } int drawTextOverlay(void) { int var_14 = 0; int var_10 = 183; messageStruct* currentMessage; BBox3D4 = 199; BBox3D1 = 319; BBox3D3 = 0; currentMessage = messageTable; if(lightOff==0) { int i; for(i=0;i<5;i++) { if(currentMessage->string) { int width = currentMessage->string->width; int X = 160 - width/2; int Y = X + width; if(XBBox3D3) { BBox3D3 = Y; } if((currentMessage->time++)>55) { currentMessage->string = NULL; } else { if(currentMessage->time<26) { SetFont(PtrFont,16); } else { SetFont(PtrFont,16+(currentMessage->time-26)/2); } PrintFont(X,var_10+1,logicalScreen,currentMessage->string->textPtr); } var_10 -= 16; var_14 = 1; } currentMessage++; } } else { } BBox3D2 = var_10; return(var_14); } void makeMessage(int messageIdx) { textEntryStruct* messagePtr; messagePtr = getTextFromIdx(messageIdx); if(messagePtr) { int i; for(i=0;i<5;i++) { if(messageTable[i].string == messagePtr) { messageTable[i].time = 0; return; } } for(i=0;i<5;i++) { if(messageTable[i].string == NULL) { messageTable[i].string = messagePtr; messageTable[i].time = 0; return; } } } } void hit(int animNumber,int arg_2,int arg_4,int arg_6,int hitForce,int arg_A) { if(InitAnim(animNumber, 0, arg_A)) { currentProcessedActorPtr->animActionANIM = animNumber; currentProcessedActorPtr->animActionFRAME = arg_2; currentProcessedActorPtr->animActionType = 1; currentProcessedActorPtr->animActionParam = arg_6; currentProcessedActorPtr->hotPointID = arg_4; currentProcessedActorPtr->hitForce = hitForce; } } void SetClip(int left, int top, int right, int bottom) { clipLeft = left; clipTop = top; clipRight = right; clipBottom = bottom; } extern "C" { void Sound_Quit(void); } void cleanupAndExit(void) { Sound_Quit(); HQR_Free(listMus); HQR_Free(listSamp); HQR_Free(HQ_Memory); HQR_Free(listLife); HQR_Free(listTrack); HQR_Free(HQ_Bodys); HQR_Free(HQ_Anims); /* free(tabTextes); free(aux); free(aux2); free(bufferAnim); free(screen); */ destroyMusicDriver(); exit(0); }