00001
00025 #include <stdio.h>
00026 #include <stdlib.h>
00027 #include <string.h>
00028
00029 #include "grid.h"
00030 #include "resources.h"
00031 #include "lbaengine.h"
00032 #include "scene.h"
00033 #include "sdlengine.h"
00034 #include "interface.h"
00035 #include "images.h"
00036 #include "actor.h"
00037
00039 #define GRID_SIZE_X 64
00040
00041 #define GRID_SIZE_Y 25
00042
00043 #define GRID_SIZE_Z GRID_SIZE_X
00044
00046 #define NUM_BRICKS 9000
00047
00049 #define CELLING_GRIDS_START_INDEX 120
00050
00052 unsigned char* brickTable[NUM_BRICKS];
00054 unsigned char* brickMaskTable[NUM_BRICKS];
00056 unsigned int brickSizeTable[NUM_BRICKS];
00058 unsigned char brickUsageTable[NUM_BRICKS];
00059
00061 unsigned char *currentGrid;
00063 unsigned char *currentBll;
00065 int numberOfBll;
00066
00068 struct BlockEntry
00069 {
00071 unsigned char blockIdx;
00073 unsigned char brickBlockIdx;
00074 };
00076 typedef struct BlockEntry blockMap[64][64][25];
00077
00079 typedef struct BrickEntry
00080 {
00082 short int x;
00084 short int y;
00086 short int z;
00088 short int posX;
00090 short int posY;
00092 short int index;
00094 unsigned char shape;
00096 unsigned char sound;
00097 } BrickEntry;
00098
00100 BrickEntry bricksDataBuffer[28][150];
00102 short int brickInfoBuffer[28];
00103
00105 int brickPixelPosX;
00107 int brickPixelPosY;
00108
00109
00110 void copy_grid_mask(int spriteNum, int x, int y, unsigned char *buffer)
00111 {
00112 unsigned char *ptr;
00113 int top;
00114 int bottom;
00115 int left;
00116 int right;
00117 unsigned char *outPtr;
00118 unsigned char *inPtr;
00119 int offset;
00120 int vc3;
00121
00122 int temp;
00123 int j;
00124
00125 int absX;
00126 int absY;
00127
00128 int vSize;
00129
00130 ptr = brickMaskTable[spriteNum];
00131
00132 left = x + *(ptr + 2);
00133 top = y + *(ptr + 3);
00134 right = *ptr + left - 1;
00135 bottom = *(ptr + 1) + top - 1;
00136
00137 if(left > textWindowRight || right < textWindowLeft || bottom < textWindowTop || top > textWindowBottom)
00138 return;
00139
00140 ptr += 4;
00141
00142 absX = left;
00143 absY = top;
00144
00145 vSize = (bottom - top)+1;
00146
00147 if(vSize <= 0)
00148 return;
00149
00150 offset = -((right - left) - SCREEN_WIDTH)-1;
00151
00152 right++;
00153 bottom++;
00154
00155
00156 if(absY < textWindowTop)
00157 {
00158 int numOfLineToRemove;
00159
00160 numOfLineToRemove = textWindowTop - absY;
00161
00162 vSize-=numOfLineToRemove;
00163 if(vSize <= 0)
00164 return;
00165
00166 absY += numOfLineToRemove;
00167
00168 do
00169 {
00170 int lineDataSize;
00171
00172 lineDataSize = *(ptr++);
00173 ptr+=lineDataSize;
00174 }while(--numOfLineToRemove);
00175 }
00176
00177
00178 if(absY + vSize - 1> textWindowBottom)
00179 {
00180 vSize = textWindowBottom - absY + 1;
00181 if(vSize <= 0)
00182 return;
00183 }
00184
00185 outPtr = frontVideoBuffer + screenLockupTable[absY] + left;
00186 inPtr = buffer + screenLockupTable[absY] + left;
00187
00188 do
00189 {
00190 vc3 = *(ptr++);
00191
00192 do
00193 {
00194 temp = *(ptr++);
00195 outPtr += temp;
00196 inPtr += temp;
00197
00198 absX += temp;
00199
00200 vc3--;
00201 if(!vc3)
00202 break;
00203
00204 temp = *(ptr++);
00205
00206 for(j=0;j<temp;j++)
00207 {
00208 if(absX>=textWindowLeft && absX<=textWindowRight)
00209 *outPtr = *inPtr;
00210
00211 absX++;
00212 outPtr++;
00213 inPtr++;
00214 }
00215 }while(--vc3);
00216
00217 absX = left;
00218
00219 outPtr += offset;
00220 inPtr += offset;
00221 }while(--vSize);
00222 }
00223
00224 void draw_over_sprite_actor(int X, int Y, int Z)
00225 {
00226 int CopyBlockPhysLeft;
00227 int CopyBlockPhysRight;
00228 int i;
00229 int j;
00230 BrickEntry *currBrickEntry;
00231
00232 CopyBlockPhysLeft = ((textWindowLeft + 24) / 24) - 1;
00233 CopyBlockPhysRight = (textWindowRight + 24) / 24;
00234
00235 for(j = CopyBlockPhysLeft; j <= CopyBlockPhysRight; j++)
00236 {
00237 for (i = 0; i < brickInfoBuffer[j]; i++)
00238 {
00239 currBrickEntry = &bricksDataBuffer[j][i];
00240
00241 if (currBrickEntry->posY + 38 > textWindowTop && currBrickEntry->posY <= textWindowBottom && currBrickEntry->y >= Y)
00242 {
00243 if ((currBrickEntry->x == X) && (currBrickEntry->z == Z))
00244 {
00245 copy_grid_mask(currBrickEntry->index, (j * 24) - 24, currBrickEntry->posY, workVideoBuffer);
00246 }
00247
00248 if ((currBrickEntry->x > X) || (currBrickEntry->z > Z))
00249 {
00250 copy_grid_mask(currBrickEntry->index, (j * 24) - 24, currBrickEntry->posY, workVideoBuffer);
00251 }
00252 }
00253 }
00254 }
00255 }
00256
00257
00258 int process_grid_mask(int var, unsigned char *buffer, unsigned char *ptr)
00259 {
00260 unsigned int *ptrSave = (unsigned int *)ptr;
00261 unsigned char *ptr2;
00262 unsigned char *esi;
00263 unsigned char *edi;
00264 unsigned char iteration, ch, numOfBlock, ah, bl, al, bh;
00265 int ebx;
00266
00267 ebx = *((unsigned int *)buffer);
00268 buffer+=4;
00269 *((unsigned int *)ptr) = ebx;
00270 ptr+=4;
00271
00272 bh = (ebx & 0x0000FF00) >> 8;
00273
00274 esi = (unsigned char *) buffer;
00275 edi = (unsigned char *) ptr;
00276
00277 iteration = 0;
00278 ch = 0;
00279
00280 do
00281 {
00282 numOfBlock = 0;
00283 ah = 0;
00284 ptr2 = edi;
00285
00286 edi++;
00287
00288 bl = *(esi++);
00289
00290 if (*(esi) & 0xC0)
00291 {
00292 *edi++ = 0;
00293 numOfBlock++;
00294 }
00295
00296 do
00297 {
00298 al = *esi++;
00299 iteration = al;
00300 iteration &= 0x3F;
00301 iteration++;
00302
00303 if (al & 0x80)
00304 {
00305 ah += iteration;
00306 esi++;
00307 }
00308 else if (al & 0x40)
00309 {
00310 ah += iteration;
00311 esi += iteration;
00312 }
00313 else
00314 {
00315 if (ah)
00316 {
00317 *edi++ = ah;
00318 numOfBlock++;
00319 ah = 0;
00320 }
00321 *(edi++) = iteration;
00322 numOfBlock++;
00323 }
00324 }while (--bl > 0);
00325
00326 if (ah)
00327 {
00328 *edi++ = ah;
00329 numOfBlock++;
00330
00331 ah = 0;
00332 }
00333
00334 *ptr2 = numOfBlock;
00335 }while (--bh > 0);
00336
00337 return ((int) ((unsigned char *) edi - (unsigned char *) ptrSave));
00338 }
00339
00340
00341 void create_grid_mask()
00342 {
00343 int b;
00344
00345 for(b=0; b<NUM_BRICKS; b++)
00346 {
00347 if(brickUsageTable[b])
00348 {
00349 if(brickMaskTable[b])
00350 free(brickMaskTable[b]);
00351 brickMaskTable[b] = (unsigned char*)malloc(brickSizeTable[b]);
00352 process_grid_mask(b, brickTable[b], brickMaskTable[b]);
00353 }
00354 }
00355 }
00356
00357 void get_sprite_size(int offset, int *width, int *height, unsigned char *spritePtr)
00358 {
00359 spritePtr += *((int *)(spritePtr + offset * 4));
00360
00361 *width = *spritePtr;
00362 *height = *(spritePtr + 1);
00363 }
00364
00368 int load_grid_bricks(int gridSize)
00369 {
00370 unsigned int firstBrick = 60000;
00371 unsigned int lastBrick = 0;
00372 unsigned char* ptrToBllBits;
00373 unsigned int i;
00374 unsigned int j;
00375 unsigned int currentBllEntryIdx = 0;
00376
00377 memset(brickTable, 0, sizeof(brickTable));
00378 memset(brickSizeTable, 0, sizeof(brickSizeTable));
00379 memset(brickUsageTable, 0, sizeof(brickUsageTable));
00380
00381
00382 ptrToBllBits = currentGrid + (gridSize - 32);
00383
00384
00385 for(i=1; i<256; i++)
00386 {
00387 unsigned char currentBitByte = *(ptrToBllBits + (i/8));
00388 unsigned char currentBitMask = 1 << (7-(i&7));
00389
00390 if(currentBitByte & currentBitMask)
00391 {
00392 unsigned int currentBllOffset = *((unsigned int *)(currentBll + currentBllEntryIdx));
00393 unsigned char* currentBllPtr = currentBll + currentBllOffset;
00394
00395 unsigned int bllSizeX = currentBllPtr[0];
00396 unsigned int bllSizeY = currentBllPtr[1];
00397 unsigned int bllSizeZ = currentBllPtr[2];
00398
00399 unsigned int bllSize = bllSizeX * bllSizeY * bllSizeZ;
00400
00401 unsigned char* bllDataPtr = currentBllPtr + 5;
00402
00403 for(j=0; j<bllSize; j++)
00404 {
00405 unsigned int brickIdx = *((short int*)(bllDataPtr));
00406
00407 if(brickIdx)
00408 {
00409 brickIdx--;
00410
00411 if (brickIdx <= firstBrick)
00412 firstBrick = brickIdx;
00413
00414 if (brickIdx > lastBrick)
00415 lastBrick = brickIdx;
00416
00417 brickUsageTable[brickIdx] = 1;
00418 }
00419 bllDataPtr += 4;
00420 }
00421 }
00422 currentBllEntryIdx += 4;
00423 }
00424
00425 for(i=firstBrick; i<=lastBrick; i++)
00426 {
00427 if(brickUsageTable[i])
00428 {
00429
00430 brickSizeTable[i] = hqr_entry_size(HQR_LBA_BRK_FILE,i);
00431 if(brickTable[i])
00432 free(brickTable[i]);
00433 brickTable[i] = (unsigned char*)malloc(brickSizeTable[i]);
00434 if(!brickTable[i])
00435 {
00436 printf("\nGRID WARNING: unable to allocate brick memory!!\n");
00437 return -1;
00438 }
00439 hqr_get_entry(brickTable[i], HQR_LBA_BRK_FILE, i);
00440 }
00441 }
00442
00443 return 1;
00444 }
00445
00449 void create_grid_column(unsigned char *gridEntry, unsigned char *dest)
00450 {
00451 int blockCount;
00452 int brickCount;
00453 int flag;
00454 int gridIdx;
00455 int i;
00456 unsigned short int *gridBuffer;
00457 unsigned short int *blockByffer;
00458
00459 brickCount = *(gridEntry++);
00460
00461 do
00462 {
00463 flag = *(gridEntry++);
00464
00465 blockCount = (flag & 0x3F) + 1;
00466
00467 gridBuffer = (unsigned short int *) gridEntry;
00468 blockByffer = (unsigned short int *) dest;
00469
00470 if (!(flag & 0xC0))
00471 {
00472 for (i = 0; i < blockCount; i++)
00473 *(blockByffer++) = 0;
00474 }
00475 else if (flag & 0x40)
00476 {
00477 for (i = 0; i < blockCount; i++)
00478 *(blockByffer++) = *(gridBuffer++);
00479 }
00480 else
00481 {
00482 gridIdx = *(gridBuffer++);
00483 for (i = 0; i < blockCount; i++)
00484 *(blockByffer++) = gridIdx;
00485 }
00486
00487 gridEntry = (unsigned char *) gridBuffer;
00488 dest = (unsigned char *) blockByffer;
00489
00490 }while (--brickCount);
00491 }
00492
00496 void create_celling_grid_column(unsigned char *gridEntry, unsigned char *dest)
00497 {
00498 int blockCount;
00499 int brickCount;
00500 int flag;
00501 int gridIdx;
00502 int i;
00503 unsigned short int *gridBuffer;
00504 unsigned short int *blockByffer;
00505
00506 brickCount = *(gridEntry++);
00507
00508 do
00509 {
00510 flag = *(gridEntry++);
00511
00512 blockCount = (flag & 0x3F) + 1;
00513
00514 gridBuffer = (unsigned short int *) gridEntry;
00515 blockByffer = (unsigned short int *) dest;
00516
00517 if (!(flag & 0xC0))
00518 {
00519 for (i = 0; i < blockCount; i++)
00520 blockByffer++;
00521 }
00522 else if (flag & 0x40)
00523 {
00524 for (i = 0; i < blockCount; i++)
00525 *(blockByffer++) = *(gridBuffer++);
00526 }
00527 else
00528 {
00529 gridIdx = *(gridBuffer++);
00530 for (i = 0; i < blockCount; i++)
00531 *(blockByffer++) = gridIdx;
00532 }
00533
00534 gridEntry = (unsigned char *) gridBuffer;
00535 dest = (unsigned char *) blockByffer;
00536
00537 }while (--brickCount);
00538 }
00539
00541 void create_grid_map()
00542 {
00543 int currOffset = 0;
00544 int blockOffset;
00545 int gridIdx;
00546 int x,z;
00547
00548 for(z=0; z<GRID_SIZE_Z; z++)
00549 {
00550 blockOffset = currOffset;
00551 gridIdx = z << 6;
00552
00553 for(x=0; x<GRID_SIZE_X; x++)
00554 {
00555 int gridOffset = *((unsigned short int *)(currentGrid + 2 * (x + gridIdx)));
00556 create_grid_column(currentGrid+gridOffset, blockBuffer + blockOffset);
00557 blockOffset += 50;
00558 }
00559 currOffset += 3200;
00560 }
00561 }
00562
00565 void create_celling_grid_map(unsigned char* gridPtr)
00566 {
00567 int currGridOffset=0;
00568 int currOffset=0;
00569 int blockOffset;
00570 int z,x;
00571 unsigned char* tempGridPtr;
00572
00573 for(z=0; z<GRID_SIZE_Z; z++)
00574 {
00575 blockOffset = currOffset;
00576 tempGridPtr = gridPtr+currGridOffset;
00577
00578 for(x=0; x<GRID_SIZE_X; x++)
00579 {
00580 int gridOffset = *((unsigned short int *)tempGridPtr); tempGridPtr+=2;
00581 create_celling_grid_column(gridPtr + gridOffset, blockBuffer + blockOffset);
00582 blockOffset += 50;
00583 }
00584 currGridOffset += 128;
00585 currOffset += 3200;
00586 }
00587 }
00588
00591 int init_grid(int index)
00592 {
00593 int gridSize;
00594 int bllSize;
00595 int brickSize;
00596
00597
00598 gridSize = hqr_entry_size(HQR_LBA_GRI_FILE,index);
00599 if(currentGrid)
00600 free(currentGrid);
00601 currentGrid = (unsigned char*)malloc(gridSize);
00602 if(!currentGrid)
00603 {
00604 printf("\nGRID WARNING: unable to allocate grid memory!!\n");
00605 return -1;
00606 }
00607 hqr_get_entry(currentGrid, HQR_LBA_GRI_FILE, index);
00608
00609
00610 bllSize = hqr_entry_size(HQR_LBA_BLL_FILE,index);
00611 if(currentBll)
00612 free(currentBll);
00613 currentBll = (unsigned char*)malloc(bllSize);
00614 if(!currentBll)
00615 {
00616 printf("\nGRID WARNING: unable to allocate layouts memory!!\n");
00617 return -1;
00618 }
00619 hqr_get_entry(currentBll, HQR_LBA_BLL_FILE, index);
00620
00621 brickSize = load_grid_bricks(gridSize);
00622
00623 create_grid_mask();
00624
00625 numberOfBll = (*((unsigned int *)currentBll) >> 2);
00626
00627 create_grid_map();
00628
00629 return 1;
00630 }
00631
00634 int init_celling_grid(int index)
00635 {
00636 int gridSize;
00637 unsigned char* gridPtr;
00638
00639
00640 gridSize = hqr_entry_size(HQR_LBA_GRI_FILE,index+CELLING_GRIDS_START_INDEX);
00641 gridPtr = (unsigned char*)malloc(gridSize);
00642 if(!gridPtr)
00643 {
00644 printf("\nCELLING GRID WARNING: unable to allocate grid memory!!\n");
00645 return -1;
00646 }
00647 hqr_get_entry(gridPtr, HQR_LBA_GRI_FILE, index+CELLING_GRIDS_START_INDEX);
00648
00649 create_celling_grid_map(gridPtr);
00650
00651 if(gridPtr)
00652 free(gridPtr);
00653
00654 reqBgRedraw=1;
00655
00656 return 0;
00657 }
00658
00659 void draw_brick(int index, int posX, int posY)
00660 {
00661 draw_brick_sprite(index, posX, posY, brickTable[index],0);
00662 }
00663
00664 void draw_sprite(int index, int posX, int posY, unsigned char *ptr)
00665 {
00666 draw_brick_sprite(index, posX, posY, ptr, 1);
00667 }
00668
00669
00670 void draw_brick_sprite(int index, int posX, int posY, unsigned char *ptr, int isSprite)
00671 {
00672
00673 int top;
00674 int bottom;
00675 int left;
00676 int right;
00677 unsigned char *outPtr;
00678 int offset;
00679 int c1;
00680 int c2;
00681 int vc3;
00682
00683 int temp;
00684 int iteration;
00685 int i;
00686
00687 int x;
00688 int y;
00689
00690 if(isSprite==1)
00691 ptr = ptr + *((unsigned int *)(ptr + index * 4));
00692
00693 left = posX + *(ptr + 2);
00694 top = posY + *(ptr + 3);
00695 right = *ptr + left - 1;
00696 bottom = *(ptr + 1) + top - 1;
00697
00698 ptr += 4;
00699
00700 x = left;
00701 y = top;
00702
00703
00704 {
00705 right++;
00706 bottom++;
00707
00708 outPtr = frontVideoBuffer + screenLockupTable[top] + left;
00709
00710 offset = -((right - left) - SCREEN_WIDTH);
00711
00712 for (c1 = 0; c1 < bottom - top; c1++)
00713 {
00714 vc3 = *(ptr++);
00715 for (c2 = 0; c2 < vc3; c2++)
00716 {
00717 temp = *(ptr++);
00718 iteration = temp & 0x3F;
00719 if (temp & 0xC0)
00720 {
00721 iteration++;
00722 if (!(temp & 0x40))
00723 {
00724 temp = *(ptr++);
00725 for (i = 0; i < iteration; i++)
00726 {
00727 if(x>=textWindowLeft && x<textWindowRight && y>=textWindowTop && y<textWindowBottom)
00728 frontVideoBuffer[y*SCREEN_WIDTH+x] = temp;
00729
00730 x++;
00731 outPtr++;
00732 }
00733 }
00734 else
00735 {
00736 for (i = 0; i < iteration; i++)
00737 {
00738 if(x>=textWindowLeft && x<textWindowRight && y>=textWindowTop && y<textWindowBottom)
00739 frontVideoBuffer[y*SCREEN_WIDTH+x] = *ptr;
00740
00741 x++;
00742 ptr++;
00743 outPtr++;
00744 }
00745 }
00746 }
00747 else
00748 {
00749 outPtr += iteration + 1;
00750 x+=iteration + 1;
00751 }
00752 }
00753 outPtr += offset;
00754 x = left;
00755 y++;
00756 }
00757 }
00758 }
00759
00763 unsigned char* get_block_library(int index)
00764 {
00765 int offset = *((unsigned int *)(currentBll + 4 * index));
00766 return (unsigned char *)(currentBll + offset);
00767 }
00768
00773 void get_brick_pos(int x, int y, int z)
00774 {
00775 brickPixelPosX = (x - z) * 24 + 288;
00776 brickPixelPosY = ((x + z)*12) - (y * 15) + 215;
00777 }
00778
00785 void draw_column_grid(int blockIdx, int brickBlockIdx, int x, int y, int z)
00786 {
00787 unsigned char *blockPtr;
00788 unsigned short int brickIdx;
00789 unsigned char brickShape;
00790 unsigned char brickSound;
00791 int brickBuffIdx;
00792 BrickEntry *currBrickEntry;
00793
00794 blockPtr = get_block_library(blockIdx) + 3 + brickBlockIdx * 4;
00795
00796 brickShape = *((unsigned char *)(blockPtr));
00797 brickSound = *((unsigned char *)(blockPtr+1));
00798 brickIdx = *((unsigned short int *)(blockPtr+2));
00799
00800 if (!brickIdx)
00801 return;
00802
00803 get_brick_pos(x - newCameraX, y - newCameraY, z - newCameraZ);
00804
00805
00806 if (brickPixelPosX < -24)
00807 return;
00808 if (brickPixelPosX >= SCREEN_WIDTH)
00809 return;
00810 if (brickPixelPosY < -38)
00811 return;
00812 if (brickPixelPosY >= SCREEN_HEIGHT)
00813 return;
00814
00815
00816 draw_brick(brickIdx-1, brickPixelPosX, brickPixelPosY);
00817
00818 brickBuffIdx = (brickPixelPosX + 24) / 24;
00819
00820 if (brickInfoBuffer[brickBuffIdx] >= 150)
00821 {
00822 printf("\nGRID WARNING: brick buffer exceeded! \n");
00823 return;
00824 }
00825
00826 currBrickEntry = &bricksDataBuffer[brickBuffIdx][brickInfoBuffer[brickBuffIdx]];
00827
00828 currBrickEntry->x = x;
00829 currBrickEntry->y = y;
00830 currBrickEntry->z = z;
00831 currBrickEntry->posX = brickPixelPosX;
00832 currBrickEntry->posY = brickPixelPosY;
00833 currBrickEntry->index = brickIdx - 1;
00834 currBrickEntry->shape = brickShape;
00835 currBrickEntry->sound = brickSound;
00836
00837 brickInfoBuffer[brickBuffIdx]++;
00838 }
00839
00841 void redraw_grid()
00842 {
00843 int i, x, y, z;
00844 unsigned char blockIdx;
00845 blockMap* map = (blockMap*)blockBuffer;
00846
00847 cameraX = newCameraX << 9;
00848 cameraY = newCameraY << 8;
00849 cameraZ = newCameraZ << 9;
00850
00851 project_position_on_screen(-cameraX, -cameraY, -cameraZ);
00852
00853 projPosXScreen = projPosX;
00854 projPosYScreen = projPosY;
00855
00856 for (i = 0; i < 28; i++)
00857 {
00858 brickInfoBuffer[i] = 0;
00859 }
00860
00861
00862
00863
00864
00865 for (z = 0; z < GRID_SIZE_Z; z++)
00866 {
00867 for (x = 0; x < GRID_SIZE_X; x++)
00868 {
00869 for (y = 0; y < GRID_SIZE_Y; y++)
00870 {
00871 blockIdx = (*map)[z][x][y].blockIdx;
00872 if(blockIdx)
00873 {
00874 draw_column_grid(blockIdx-1, (*map)[z][x][y].brickBlockIdx,x,y,z);
00875 }
00876 }
00877 }
00878 }
00879 }
00880
00881
00882
00883
00884
00885
00886
00887
00888
00889
00890
00891
00892
00893
00894
00895
00896
00897
00898
00899
00900
00901
00902
00903
00904
00905
00906
00907
00908
00909
00910
00911
00912
00913
00914
00915
00916
00917
00918
00919
00920
00921
00922
00923
00924
00925
00926
00927
00928