////////////////////////// // FITD - Free in the Dark ////////////////////////// // 22 septembre 2003 14:25 // seg002 #include "common.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 input5; 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 = &objectTable[NUM_MAX_OBJECT-1]; } actorIdx = currentActorEntry; var_2 = 1; currentProcessedActorPtr = &objectTable[actorIdx]; currentLifeActorPtr = &objectTable[actorIdx]; currentProcessedActorIdx = actorIdx; currentLifeActorIdx = actorIdx; currentProcessedActorPtr->indexInWorld = objIdx; currentProcessedActorPtr->life = -1; currentProcessedActorPtr->bodyNum = -1; currentProcessedActorPtr->_flags = 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); for (int i = 0; i < NB_BUFFER_ANIM; i++) { BufferAnim[i].resize(SIZE_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; 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); 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); // TODO: missing dos memory check here if(g_gameId == AITD1) { listBody = HQR_InitRessource(listBodySelect[CVars[getCVarsIdx(CHOOSE_PERSO)]],37000, 50); // was calculated from free mem size listAnim = HQR_InitRessource(listAnimSelect[CVars[getCVarsIdx(CHOOSE_PERSO)]],30000, 80); // was calculated from free mem size } else { listBody = HQR_InitRessource("LISTBODY",37000, 50); // was calculated from free mem size listAnim = HQR_InitRessource("LISTANIM",30000, 80); // was calculated from free mem size listMatrix = 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 maskStruct { u16 x1; u16 y1; u16 x2; u16 y2; u16 deltaX; u16 deltaY; std::array mask; }; std::vector> g_maskBuffers; void loadMask(int cameraIdx) { g_maskBuffers.clear(); 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); for(int i=0; inumViewedRooms; i++) { cameraViewedRoomStruct* pRoomView = &cameraDataTable[NumCamera]->viewedRoomTable[i]; 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]; 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 setupCameraProjection(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 setupCameraSub1() { 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 = &objectTable[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->_flags & ~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; actorTurnedToObj = 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 zvRotSub(int X, int Y, int Z, int alpha, int beta, int gamma) { if( alpha || beta || gamma ) { setupPointRotate(alpha,beta,gamma); pointRotate(X, Y, Z, &animMoveX,&animMoveY,&animMoveZ); } else { animMoveX = X; animMoveY = Y; animMoveZ = Z; } } void getZvRot(char* bodyPtr, ZVStruct* zvPtr, int alpha, int beta, int gamma) { int X1 = 32000; int Y1 = 32000; int Z1 = 32000; int X2 = -32000; int Y2 = -32000; int Z2 = -32000; int i; int tempX; int tempY; int tempZ; GiveZVObjet(bodyPtr, zvPtr); for(i=0;i<8;i++) { switch(i) { case 0: { tempX = zvPtr->ZVX1; tempY = zvPtr->ZVY1; tempZ = zvPtr->ZVZ1; break; } case 1: { tempZ = zvPtr->ZVZ2; break; } case 2: { tempX = zvPtr->ZVX2; break; } case 3: { tempZ = zvPtr->ZVZ1; break; } case 4: { tempY = zvPtr->ZVY2; break; } case 5: { tempX = zvPtr->ZVX1; break; } case 6: { tempZ = zvPtr->ZVZ2; break; } case 7: { tempX = zvPtr->ZVX2; break; } } zvRotSub(tempX, tempY, tempZ, alpha, beta, gamma); if(animMoveXX2) X2 = animMoveX; if(animMoveYY2) Y2 = animMoveY; if(animMoveZZ2) Z2 = animMoveZ; } zvPtr->ZVX1 = X1; zvPtr->ZVX2 = X2; zvPtr->ZVY1 = Y1; zvPtr->ZVY2 = Y2; zvPtr->ZVZ1 = Z1; zvPtr->ZVZ2 = Z2; } void copyZv(ZVStruct* source, ZVStruct* dest) { memcpy(dest,source,sizeof(ZVStruct)); } void setupCameraSub4(void) { FastCopyScreen(aux,aux2); //TODO: implementer la suite } void setMoveMode(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 cameraVisibilityVar = 0; int IsInCamera(int roomNumber) { int numZone = cameraDataTable[NumCamera]->numViewedRooms; for(int i=0;iviewedRoomTable[i].viewedRoomIdx == roomNumber) { cameraVisibilityVar = i; return(1); } } cameraVisibilityVar = -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; } int updateActorAitd2Only(int actorIdx) { tObject *currentActor = &objectTable[actorIdx]; if(g_gameId == AITD1) { return 0; } if(currentActor->bodyNum != -1) { if(IsInCamera(currentActor->room)) { if(IsInCamRectTestAITD2(currentActor->roomX + currentActor->stepX, currentActor->roomZ + currentActor->stepZ)) { currentActor->lifeMode |= 4; return 1; } } } return 0; } void updateAllActorAndObjectsAITD2() { for(int i=0;iindexInWorld == -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: //assert(0); break; } if(updateActorAitd2Only(i)) { pObject->lifeMode |= 4; continue; } } DeleteObjet(i); } for(int i=0;iobjIndex != -1) { if(currentWorldTarget == i) { currentCameraTargetActor = currentObject->objIndex; } } else { if(currentObject->stage == g_currentFloor) { if(currentObject->life != -1) { if(currentObject->lifeMode != -1) { int actorIdx; int di; switch(currentObject->lifeMode&3) { case 0: { di = 0; break; } case 1: { di = 1; break; } case 2: { if(currentObject->room != currentRoom) { di = 0; } else { di = 1; } break; } case 3: { if(!isInViewList(currentObject->room)) { di = 0; } else { di = 1; } break; } } if(!di) { if(currentObject->body != -1) { if(IsInCamera(currentObject->room)) { if(IsInCamRectTestAITD2(currentObject->x,currentObject->z)) { currentObject->lifeMode |= 4; } else { continue; } } else { continue; } } else { continue; } } //int var_C = currentObject->flags & 0xFFDF; //int var_E = currentObject->field_2; //int var_A = currentObject->anim; addObject: actorIdx = copyObjectToActor( currentObject->body, currentObject->typeZV, currentObject->foundName, currentObject->flags & 0xFFDF, currentObject->x, currentObject->y, currentObject->z, currentObject->stage, currentObject->room, currentObject->alpha, currentObject->beta, currentObject->gamma, currentObject->anim, currentObject->frame, currentObject->animType, currentObject->animInfo); currentObject->objIndex = actorIdx; if(actorIdx != -1) { currentProcessedActorPtr = &objectTable[actorIdx]; currentProcessedActorIdx = actorIdx; if(currentWorldTarget == i) { currentCameraTargetActor = currentProcessedActorIdx; } currentProcessedActorPtr->dynFlags = (currentObject->flags & 0x20) / 0x20; // recheck currentProcessedActorPtr->life = currentObject->life; currentProcessedActorPtr->lifeMode = currentObject->lifeMode; currentProcessedActorPtr->indexInWorld = i; setMoveMode(currentObject->trackMode, currentObject->trackNumber); currentProcessedActorPtr->positionInTrack = currentObject->positionInTrack; if(g_gameId != AITD1) { currentProcessedActorPtr->MARK = currentObject->mark; } actorTurnedToObj = 1; } } } else { if(isInViewList(currentObject->room)) goto addObject; } } } } // objModifFlag1 = 0; //TODO: object update } void updateAllActorAndObjects() { int i; tObject *currentActor = objectTable; tWorldObject* currentObject; if(g_gameId > JACK) { updateAllActorAndObjectsAITD2(); return; } for(i=0;iindexInWorld != -1) { if(currentActor->stage == g_currentFloor) { if(currentActor->life != -1) { switch(currentActor->lifeMode) { case 0: { break; } case 1: { if(currentActor->room != currentRoom) { DeleteObjet(i); } break; } case 2: { if(!isInViewList(currentActor->room)) { DeleteObjet(i); } break; } default: { DeleteObjet(i); break; } } } else { if(!isInViewList(currentActor->room)) { DeleteObjet(i); } } } else { DeleteObjet(i); } } currentActor++; } currentObject = &ListWorldObjets[0]; for(i=0;iobjIndex != -1) { if(currentWorldTarget == i) { currentCameraTargetActor = currentObject->objIndex; } } else { if(currentObject->stage == g_currentFloor) { if(currentObject->life != -1) { if(currentObject->lifeMode != -1) { int actorIdx; switch(currentObject->lifeMode) { case 1: { if(currentObject->room != currentRoom) { currentObject++; continue; } break; } case 2: { if(!isInViewList(currentObject->room)) { currentObject++; continue; } break; } } //int var_C = currentObject->flags & 0xFFDF; //int var_E = currentObject->field_2; //int var_A = currentObject->anim; addObject: actorIdx = copyObjectToActor( currentObject->body, currentObject->typeZV, currentObject->foundName, currentObject->flags & 0xFFDF, currentObject->x, currentObject->y, currentObject->z, currentObject->stage, currentObject->room, currentObject->alpha, currentObject->beta, currentObject->gamma, currentObject->anim, currentObject->frame, currentObject->animType, currentObject->animInfo); currentObject->objIndex = actorIdx; if(actorIdx != -1) { currentProcessedActorPtr = &objectTable[actorIdx]; currentProcessedActorIdx = actorIdx; if(currentWorldTarget == i) { currentCameraTargetActor = currentProcessedActorIdx; } currentProcessedActorPtr->dynFlags = (currentObject->flags & 0x20) / 0x20; // recheck currentProcessedActorPtr->life = currentObject->life; currentProcessedActorPtr->lifeMode = currentObject->lifeMode; currentProcessedActorPtr->indexInWorld = i; setMoveMode(currentObject->trackMode, currentObject->trackNumber); currentProcessedActorPtr->positionInTrack = currentObject->positionInTrack; actorTurnedToObj = 1; } } } else { if(isInViewList(currentObject->room)) goto addObject; } } } currentObject++; } // 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 createActorList() { int i; tObject* actorPtr; numActorInList = 0; actorPtr = objectTable; for(i=0;iindexInWorld != -1 && actorPtr->bodyNum != -1) { if(checkActorInRoom(actorPtr->room)) { sortedActorTable[numActorInList] = i; if(!(actorPtr->_flags & (AF_SPECIAL & AF_ANIMATED))) { actorPtr->_flags |= AF_BOXIFY; // FlagRefreshAux2 = 1; } numActorInList++; } } actorPtr++; } } void InitView() { int x; int y; int z; cameraDataStruct* pCamera; SaveTimerAnim(); 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; 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 = objectTable[currentCameraTargetActor].worldX + objectTable[currentCameraTargetActor].stepX; y = debufferVar_topCameraZoom; z = objectTable[currentCameraTargetActor].worldZ + objectTable[currentCameraTargetActor].stepZ; } } #endif SetPosCamera(x,y,z); // setup camera position setupCameraProjection(160,100,pCamera->focal1,pCamera->focal2,pCamera->focal3); // setup focale #ifdef FITD_DEBUGGER if(debuggerVar_topCamera) setupCameraProjection(160,100,1000,100,100); // setup focale #endif setupCameraSub1(); updateAllActorAndObjects(); createActorList(); // setupCameraSub3(); setupCameraSub4(); /* setupCameraSub5(); */ if(FlagInitView==2) { flagRedraw = 2; } else { if(flagRedraw!=2) { flagRedraw = 1; } } FlagInitView = 0; RestoreTimerAnim(); } 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 = &objectTable[actorIdx]; actorPtr->_flags &= ~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 = &objectTable[actorIdx]; actorPtr->room = -1; actorPtr->stage = -1; // FlagGenereActiveList = 1; if(actorPtr->_flags & 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(tObject* actorPtr) { ZVStruct localZv; if( actorPtr->room != objectTable[currentCameraTargetActor].room ) { getZvRelativePosition(&localZv, actorPtr->room, objectTable[currentCameraTargetActor].room); } else { copyZv(&actorPtr->zv,&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 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].numCoverZones;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].numMask;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(checkZvCollision(&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(checkZvCollision(&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(checkZvCollision(&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;jnumMask;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 mainDrawSub2(int actorIdx) // draw flow { //actorStruct* actorPtr = &actorTable[actorIdx]; //char* data = printTextSub2(hqrUnk, actorPtr->FRAME); // TODO: finish } void getHotPoint(int hotPointIdx, char* bodyPtr, point3dStruct* hotPoint) { s16 flag; flag = *(s16*)bodyPtr; bodyPtr += 2; if(flag&2) { s16 offset; bodyPtr += 12; offset = *(s16*)bodyPtr; bodyPtr+=2; bodyPtr+=offset; offset = *(s16*)bodyPtr; // num points bodyPtr+=2; bodyPtr+=offset*6; // skip point buffer offset = *(s16*)bodyPtr; // num bones bodyPtr+=2; bodyPtr+=offset*2; // skip bone buffer ASSERT(hotPointIdx < offset); if(hotPointIdx < offset) { int pointIdx; s16* source; if(flag&INFO_OPTIMISE) { bodyPtr+=hotPointIdx*0x18; } else { bodyPtr+=hotPointIdx*16; } pointIdx = *(s16*)(bodyPtr+4); // first point //ASSERT(pointIdx > 0 && pointIdx < 1200); source = (s16*)(((char*)pointBuffer) + pointIdx); hotPoint->x = source[0]; hotPoint->y = source[1]; hotPoint->z = source[2]; } else { hotPoint->x = 0; hotPoint->y = 0; hotPoint->z = 0; } } else { hotPoint->x = 0; hotPoint->y = 0; hotPoint->z = 0; } } void mainDraw(int flagFlip) { int i; //if(flagFlip == 2) { if(cameraBackgroundChanged) { osystem_CopyBlockPhys((unsigned char*)aux,0,0,320,200); cameraBackgroundChanged = false; } } if(flagFlip== 0) { //restoreDirtyRects(); } else { genVar5 = 0; FastCopyScreen(aux2,logicalScreen); } //osystem_drawBackground(); SetClip(0,0,319,199); genVar6 = 0; #ifdef FITD_DEBUGGER if(backgroundMode == backgroundModeEnum_3D) { for(i=0;i_flags & (AF_ANIMATED + AF_DRAWABLE + AF_SPECIAL)) { actorPtr->_flags &= ~AF_DRAWABLE; if(actorPtr->_flags & AF_SPECIAL) { mainDrawSub2(currentDrawActor); } else { char* bodyPtr = HQR_Get(listBody,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); } } ///////////////////////////////////// DEBUG #ifdef FITD_DEBUGGER // if(debuggerVar_drawModelZv) { if(backgroundMode == backgroundModeEnum_3D) { drawZv(actorPtr); } } #endif ///////////////////////////////////// } 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; } } } osystem_stopModelRender(); 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) { objectTable[actorIdx]._flags |= AF_BOXIFY + AF_DRAWABLE; objectTable[actorIdx]._flags &= ~AF_ANIMATED; //FlagRefreshAux2 = 1; } int checkZvCollision(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 getZvRelativePosition(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 checkObjectCollisions(int actorIdx, ZVStruct* zvPtr) { int currentCollisionSlot = 0; tObject* currentActor = objectTable; int actorRoom = objectTable[actorIdx].room; for(int i=0;i<3;i++) { currentProcessedActorPtr->COL[i] = -1; } for(int i=0;iindexInWorld != -1 && i!=actorIdx) { ZVStruct* currentActorZv = ¤tActor->zv; if(currentActor->room != actorRoom) { ZVStruct localZv; copyZv(zvPtr,&localZv); getZvRelativePosition(&localZv,actorRoom,currentActor->room); if(checkZvCollision(&localZv,currentActorZv)) { currentProcessedActorPtr->COL[currentCollisionSlot++] = i; if(currentCollisionSlot == 3) return(3); } } else { if(checkZvCollision(zvPtr,currentActorZv)) { currentProcessedActorPtr->COL[currentCollisionSlot++] = i; if(currentCollisionSlot == 3) return(3); } } } currentActor++; } return(currentCollisionSlot); } void cleanClip() { for(int x=clipLeft; x0;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 foundObject(int objIdx, int param) { tWorldObject* objPtr; int var_C = 0; int var_6 = 1; int i; int var_A = 15000; int var_8 = -200; if(objIdx < 0) return; if(param == 2) { printf("foundObject with param == 2\n"); } objPtr = &ListWorldObjets[objIdx]; if( param != 0 && (objPtr->foundFlag & 0xC000)) { return; } if(objPtr->trackNumber) { if(timer - objPtr->trackNumber < 300) // prevent from reopening the window every frame return; } objPtr->trackNumber = 0; SaveTimerAnim(); // setupShaking(1000); // probably to remove the shaking when in foundObject screen int weight = 0; for(i=0;ipositionInTrack + weight > CVars[getCVarsIdx(MAX_WEIGHT_LOADABLE)] || numObjInInventoryTable[currentInventory] +1 == 30) { var_6 = 3; } currentFoundBodyIdx = objPtr->foundBody; currentFoundBody = HQR_Get(listBody,currentFoundBodyIdx); setupCameraProjection(160,100,128,300,298); statusVar1 = 0; memset(frontBuffer, 0, 320*200); FastCopyScreen(frontBuffer,logicalScreen); AffBigCadre(160,100,240,120); drawFoundObect(var_6, objPtr->foundName, var_A); osystem_flip(NULL); input5 = 1; while(!var_C) { osystem_CopyBlockPhys((unsigned char*)logicalScreen,0,0,320,200); process_events(); osystem_drawBackground(); localKey = key; localJoyD = JoyD; localClick = Click; if(!input5) { if(localKey == 1) { if(var_6 != 2) { var_6 = 0; } var_C = 1; } if(var_6 != 2) { if(localJoyD&4) { var_6 = 0; } if(localJoyD&8) { var_6 = 1; } } if(localKey == 28 || localClick !=0) { while(key) { process_events(); } var_C = 1; } } else { if(!localKey && !localJoyD && !localClick) input5 = 0; } statusVar1 -= 8; var_A += var_8; // zoom / dezoom if(var_A> 8000) // zoom management var_8 = -var_8; if(var_A< 25000) var_8 = -var_8; drawFoundObect(var_6,objPtr->foundName,var_A); // menuWaitVSync(); } RestoreTimerAnim(); if(var_6 == 1) { take(objIdx); } else { objPtr->trackNumber = timer; } while(key && Click) { process_events(); } localJoyD = 0; localKey = 0; localClick = 0; // if(mainLoopVar1 != 0) { //setupShaking(-600); } FlagInitView = 1; } void hardColSuB1Sub1(int flag) { switch(flag) { case 1: case 2: { hardColStepZ = 0; break; } case 4: case 8: { hardColStepX = 0; break; } default: { break; } } } void handleCollision(ZVStruct* startZv, ZVStruct* zvPtr2, ZVStruct* zvPtr3) { s32 flag = 0; s32 var_8; s32 halfX; s32 halfZ; s32 var_A; s32 var_6; if(startZv->ZVX2 > zvPtr3->ZVX1) { if(zvPtr3->ZVX2 <= startZv->ZVX1) { flag = 8; } } else { flag = 4; } if(startZv->ZVZ2 > zvPtr3->ZVZ1) { if(startZv->ZVZ1 >= zvPtr3->ZVZ2) { flag |= 2; } } else { flag |= 1; } if( flag == 5 || flag == 9 || flag == 6 || flag == 10 ) { var_8 = 2; } else { if(!flag) { var_8 = 0; hardColStepZ = 0; hardColStepX = 0; return; } else { var_8 = 1; } } halfX = (zvPtr2->ZVX1 + zvPtr2->ZVX2) / 2; halfZ = (zvPtr2->ZVZ1 + zvPtr2->ZVZ2) / 2; if(zvPtr3->ZVX1 > halfX) { var_A = 4; } else { if(zvPtr3->ZVX2 < halfX) { var_A = 0; } else { var_A = 8; } } if(zvPtr3->ZVZ1 > halfZ) { var_A |= 1; } else { if(zvPtr3->ZVZ2 < halfZ) { var_A |= 0; // once again, not that much usefull } else { var_A |= 2; } } if( var_A == 5 || var_A == 9 || var_A == 6 || var_A == 10 ) { var_6 = 2; } else { if(!var_A) { var_6 = 0; } else { var_6 = 1; } } if(var_8 == 1) { hardColSuB1Sub1(flag); return; } if(var_6 == 1 && (var_A & flag)) { hardColSuB1Sub1(var_A); return; } if(var_A == flag || flag == 15) { int Xmod = abs(zvPtr2->ZVX1 - startZv->ZVX1); // recheck int Zmod = abs(zvPtr2->ZVZ1 - startZv->ZVZ1); if(Xmod > Zmod) { hardColStepZ = 0; } else { hardColStepX = 0; } } else { if(!var_6 || (var_6 == 1 && !(var_A & flag))) { hardColStepZ = 0; hardColStepX = 0; } else { hardColSuB1Sub1(flag&var_A); } } } 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;inumCoverZones;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 = &objectTable[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 checkIfCameraChangeIsRequired(void) { int localCurrentCam = NumCamera; int newCamera; if(NumCamera!=-1) { tObject* actorPtr; int zvx1; int zvx2; int zvz1; int zvz2; actorPtr = &objectTable[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 processActor2() { 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 x; int y; int z; int oldRoom = currentProcessedActorPtr->room; currentProcessedActorPtr->room = (short)pCurrentZone->parameter; x = (roomDataTable[currentProcessedActorPtr->room].worldX - roomDataTable[oldRoom].worldX) * 10; y = (roomDataTable[currentProcessedActorPtr->room].worldY - roomDataTable[oldRoom].worldY) * 10; 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) { needChangeRoom = 1; newRoom = (short)pCurrentZone->parameter; if(g_gameId > AITD1) ChangeSalle(newRoom); } else { actorTurnedToObj = 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; 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 { tObject* currentActorPtr = objectTable; int i; for(i=0;iindexInWorld != -1 && i != actorIdx && !(currentActorPtr->_flags & AF_SPECIAL)) { ZVStruct* zvPtr = ¤tActorPtr->zv; if(room != currentActorPtr->room) { ZVStruct localZv2; copyZv(&localZv, &localZv2); getZvRelativePosition(&localZv2, room, currentActorPtr->room); if(!checkZvCollision(&localZv2,zvPtr)) { currentActorPtr++; continue; } } else { if(!checkZvCollision(&localZv,zvPtr)) { currentActorPtr++; continue; } } foundFlag = i; break; } currentActorPtr++; } } } 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 = &objectTable[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; u8* bodyPtr; bodyPtr = (u8*)HQR_Get(listBody,currentProcessedActorPtr->bodyNum); GiveZVObjet((char*)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((char*)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 configureHqrHero(hqrEntryStruct* hqrPtr, const char* name) { strcpy(hqrPtr->string," "); strncpy(hqrPtr->string,name,8); } 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(listBody); HQR_Free(listAnim); /* free(tabTextes); free(aux); free(aux2); free(bufferAnim); free(screen); */ destroyMusicDriver(); exit(0); }