00001
00025 #include "redraw.h"
00026 #include "sdlengine.h"
00027 #include "lbaengine.h"
00028 #include "interface.h"
00029 #include "images.h"
00030 #include "grid.h"
00031 #include "scene.h"
00032 #include "actor.h"
00033 #include "hqrdepack.h"
00034 #include "resources.h"
00035 #include "menu.h"
00036
00037 #ifdef GAMEMOD
00038 #include "debug.scene.h"
00039 #endif
00040
00041
00042 typedef struct RedrawStruct
00043 {
00044 unsigned short int left;
00045 unsigned short int top;
00046 unsigned short int right;
00047 unsigned short int bottom;
00048 } RedrawStruct;
00049
00050 RedrawStruct currentRedrawList[300];
00051 RedrawStruct nextRedrawList[300];
00052
00053 typedef struct DrawListStruct
00054 {
00055 short int posValue;
00056 unsigned short int index;
00057 unsigned short int X;
00058 unsigned short int Y;
00059 unsigned short int Z;
00060 unsigned short int field_A;
00061 unsigned short int field_C;
00062 unsigned short int field_E;
00063 unsigned short int field_10;
00064 } DrawListStruct;
00065
00067 DrawListStruct drawList[150];
00068
00070 int currNumOfRedrawBox;
00072 int numOfRedrawBox;
00073
00079 void add_redraw_current_area(int left, int top, int right, int bottom)
00080 {
00081 int area;
00082 int i = 0;
00083 int leftValue;
00084 int rightValue;
00085 int topValue;
00086 int bottomValue;
00087
00088 area = (right - left) * (bottom - top);
00089
00090 while (i < numOfRedrawBox)
00091 {
00092 if (currentRedrawList[i].left >= left)
00093 leftValue = left;
00094 else
00095 leftValue = currentRedrawList[i].left;
00096
00097 if (currentRedrawList[i].right <= right)
00098 rightValue = right;
00099 else
00100 rightValue = currentRedrawList[i].right;
00101
00102 if (currentRedrawList[i].top >= top)
00103 topValue = top;
00104 else
00105 topValue = currentRedrawList[i].top;
00106
00107 if (currentRedrawList[i].bottom <= bottom)
00108 bottomValue = bottom;
00109 else
00110 bottomValue = currentRedrawList[i].bottom;
00111
00112 if ((rightValue - leftValue) * (bottomValue - topValue) < ((currentRedrawList[i].bottom - currentRedrawList[i].top) * (currentRedrawList[i].right - currentRedrawList[i].left) + area))
00113 {
00114 currentRedrawList[i].left = leftValue;
00115 currentRedrawList[i].top = topValue;
00116 currentRedrawList[i].right = rightValue;
00117 currentRedrawList[i].bottom = bottomValue;
00118
00119 if(currentRedrawList[i].bottom >= SCREEN_WIDTH)
00120 currentRedrawList[i].bottom = SCREEN_TEXTLIMIT_BOTTOM;
00121 return;
00122 }
00123
00124 i++;
00125 };
00126
00127 currentRedrawList[i].left = left;
00128 currentRedrawList[i].top = top;
00129 currentRedrawList[i].right = right;
00130 currentRedrawList[i].bottom = bottom;
00131
00132 if(currentRedrawList[i].bottom >= SCREEN_WIDTH)
00133 currentRedrawList[i].bottom = SCREEN_TEXTLIMIT_BOTTOM;
00134
00135 numOfRedrawBox++;
00136 }
00137
00143 void add_redraw_area(int left, int top, int right, int bottom)
00144 {
00145 if (left < 0)
00146 left = 0;
00147 if (top < 0)
00148 top = 0;
00149 if (right >= SCREEN_WIDTH)
00150 right = SCREEN_TEXTLIMIT_RIGHT;
00151 if (bottom >= SCREEN_HEIGHT)
00152 bottom = SCREEN_TEXTLIMIT_BOTTOM;
00153
00154 if (left > right || top > bottom)
00155 return;
00156
00157 nextRedrawList[currNumOfRedrawBox].left = left;
00158 nextRedrawList[currNumOfRedrawBox].top = top;
00159 nextRedrawList[currNumOfRedrawBox].right = right;
00160 nextRedrawList[currNumOfRedrawBox].bottom = bottom;
00161
00162 currNumOfRedrawBox++;
00163
00164 add_redraw_current_area(left, top, right, bottom);
00165 }
00166
00168 void move_next_areas()
00169 {
00170 int i;
00171
00172 numOfRedrawBox = 0;
00173
00174 for (i = 0; i < currNumOfRedrawBox; i++)
00175 {
00176 add_redraw_current_area(nextRedrawList[i].left, nextRedrawList[i].top, nextRedrawList[i].right, nextRedrawList[i].bottom);
00177 }
00178 }
00179
00183 void flip_redraw_areas()
00184 {
00185 int i;
00186
00187 for (i = 0; i < numOfRedrawBox; i++)
00188 {
00189 copy_block_phys(currentRedrawList[i].left, currentRedrawList[i].top, currentRedrawList[i].right, currentRedrawList[i].bottom);
00190 }
00191
00192 numOfRedrawBox = 0;
00193
00194 for (i = 0; i < currNumOfRedrawBox; i++)
00195 {
00196 add_redraw_current_area(nextRedrawList[i].left, nextRedrawList[i].top, nextRedrawList[i].right, nextRedrawList[i].bottom);
00197 }
00198 }
00199
00201 void blit_background_areas()
00202 {
00203 int i;
00204 RedrawStruct* currentArea;
00205 currentArea = currentRedrawList;
00206
00207 for (i = 0; i < numOfRedrawBox; i++)
00208 {
00209 blit_box(currentArea->left, currentArea->top, currentArea->right, currentArea->bottom, (char *) workVideoBuffer, currentArea->left, currentArea->top, (char *) frontVideoBuffer);
00210 currentArea++;
00211 }
00212 }
00213
00217 void sort_drawing_list(DrawListStruct *list, int listSize)
00218 {
00219 int i;
00220 int j;
00221
00222 DrawListStruct tempStruct;
00223
00224 for(i=0;i<listSize-1;i++)
00225 {
00226 for(j=0;j<listSize-1-i;j++)
00227 {
00228 if(list[j+1].posValue<list[j].posValue)
00229 {
00230 memcpy(&tempStruct,&list[j+1],sizeof(DrawListStruct));
00231 memcpy(&list[j+1],&list[j],sizeof(DrawListStruct));
00232 memcpy(&list[j],&tempStruct,sizeof(DrawListStruct));
00233 }
00234 }
00235 }
00236 }
00237
00240 int process_actors_drawlist(int bgRedraw)
00241 {
00242 int tmpVal;
00243 int modelActorPos;
00244 int spriteActorPos;
00245 int shadowActorPos;
00246 int drawListPos;
00247 ActorStruct *localActor;
00248
00249 modelActorPos = 0;
00250 drawListPos = 0;
00251 spriteActorPos = modelActorPos + 0x1000;
00252 shadowActorPos = modelActorPos + 0x0C00;
00253
00254
00255 for(modelActorPos=0; modelActorPos < sceneNumActors; modelActorPos++, spriteActorPos++, shadowActorPos++)
00256 {
00257 localActor = &sceneActors[modelActorPos];
00258 localActor->dinamicFlags.bIsVisible = 0;
00259
00260 if((useCellingGrid==-1) || localActor->Y <= (*(short int*)(cellingGridIdx*24 + (char *)sceneZones+8)))
00261 {
00262
00263 if(localActor->staticFlags.bIsBackgrounded && bgRedraw==0)
00264 {
00265
00266 project_position_on_screen(localActor->X - cameraX, localActor->Y - cameraY, localActor->Z - cameraZ);
00267
00268
00269 if(projPosX > -50 && projPosX < 680 && projPosY > -30 && projPosY < 580)
00270 {
00271 localActor->dinamicFlags.bIsVisible = 1;
00272 }
00273 }
00274 else
00275 {
00276
00277 if(localActor->entity != -1 && !(localActor->staticFlags.bIsHidden))
00278 {
00279
00280 project_position_on_screen(localActor->X - cameraX, localActor->Y - cameraY, localActor->Z - cameraZ);
00281
00282 if (((localActor->staticFlags.bUsesClipping) && projPosX > -112 && projPosX < 752 && projPosY > -50 && projPosY < 651) ||
00283 ((!(localActor->staticFlags.bUsesClipping)) && projPosX > -50 && projPosX < 680 && projPosY > -30 && projPosY < 580))
00284 {
00285 tmpVal = localActor->Z + localActor->X - cameraX - cameraZ;
00286
00287
00288 if(localActor->standOn != -1)
00289 {
00290 tmpVal = sceneActors[localActor->standOn].X - cameraX + sceneActors[localActor->standOn].Z - cameraZ + 2;
00291 }
00292
00293
00294 if(localActor->staticFlags.bIsSpriteActor)
00295 {
00296 drawList[drawListPos].index = spriteActorPos;
00297 if(localActor->staticFlags.bUsesClipping)
00298 {
00299 tmpVal = localActor->lastX - cameraX + localActor->lastZ - cameraZ;
00300 }
00301 }
00302 else
00303 {
00304 drawList[drawListPos].index = modelActorPos;
00305 }
00306
00307 drawList[drawListPos].posValue = tmpVal;
00308
00309 drawListPos++;
00310
00311
00312 if(cfgfile.ShadowMode!=0 && !(localActor->staticFlags.bDoesntCastShadow))
00313 {
00314 if(localActor->standOn != -1)
00315 {
00316 shadowX = localActor->X;
00317 shadowY = localActor->Y-1;
00318 shadowZ = localActor->Z;
00319 }
00320 else
00321 {
00322
00323 }
00324
00325 tmpVal--;
00326 drawList[drawListPos].posValue = tmpVal;
00327 drawList[drawListPos].index = 0xC00;
00328 drawList[drawListPos].X = shadowX;
00329 drawList[drawListPos].Y = shadowY;
00330 drawList[drawListPos].Z = shadowZ;
00331 drawList[drawListPos].field_A = 2;
00332 drawListPos++;
00333 }
00334 }
00335 }
00336 }
00337 }
00338 }
00339 return drawListPos;
00340 }
00341
00346 void process_drawing(int numDrawingList)
00347 {
00348 int drawListPos = 0;
00349
00350
00351 if(numDrawingList > 0)
00352 {
00353 unsigned int flags;
00354 int actorIdx;
00355 ActorStruct *localActor;
00356
00357 do
00358 {
00359 actorIdx = drawList[drawListPos].index & 0x3FF;
00360 localActor = &sceneActors[actorIdx];
00361 flags = ((unsigned int) drawList[drawListPos].index) & 0xFC00;
00362
00363
00364 if (flags < 0xC00)
00365 {
00366
00367 }
00368
00369 else if(flags == 0xC00)
00370 {
00371
00372 }
00373
00374 else if(flags < 0x1000)
00375 {
00376
00377 }
00378
00379 else if(flags == 0x1000)
00380 {
00381 int spriteWidth, spriteHeight;
00382
00383 unsigned char *spritePtr = spriteTable[localActor->entity];
00384
00385
00386 project_position_on_screen(localActor->X - cameraX, localActor->Y - cameraY, localActor->Z - cameraZ);
00387
00388 get_sprite_size(0, &spriteWidth, &spriteHeight, spritePtr);
00389
00390
00391 renderLeft = projPosX + *(short int *) (spriteBoundingBoxPtr + localActor->entity * 16);
00392 renderTop = projPosY + *(short int *) (spriteBoundingBoxPtr + localActor->entity * 16 + 2);
00393 renderRight = renderLeft + spriteWidth;
00394 renderBottom = renderTop + spriteHeight;
00395
00396 if(localActor->staticFlags.bUsesClipping)
00397 {
00398 set_clip(projPosXScreen + localActor->info0, projPosYScreen + localActor->info1, projPosXScreen + localActor->info2, projPosYScreen + localActor->info3);
00399 }
00400 else
00401 {
00402 set_clip(renderLeft, renderTop, renderRight, renderBottom);
00403 }
00404
00405 if (textWindowLeft <= textWindowRight && textWindowTop <= textWindowBottom)
00406 {
00407 draw_sprite(0, renderLeft, renderTop, spritePtr);
00408
00409 localActor->dinamicFlags.bIsVisible = 1;
00410
00411 if(localActor->staticFlags.bUsesClipping)
00412 {
00413 draw_over_sprite_actor((localActor->lastX+0x100)>> 9,localActor->lastY >> 8,(localActor->lastZ+0x100) >> 9);
00414 }
00415 else
00416 {
00417 int tempX, tempZ, tempY;
00418
00419 tempX = (localActor->X + localActor->boudingBox.X.topRight +0x100) >> 9;
00420 tempZ = localActor->Y >> 8;
00421 if (localActor->field_3 & 0x7F)
00422 tempZ++;
00423 tempY = (localActor->Z + localActor->boudingBox.Z.topRight +0x100) >> 9;
00424
00425 draw_over_sprite_actor(tempX, tempZ, tempY);
00426 }
00427
00428 add_redraw_area(textWindowLeft, textWindowTop,textWindowRight, textWindowBottom);
00429
00430
00431
00432 }
00433 }
00434
00435 else if(flags == 0x1800)
00436 {
00437
00438 }
00439
00440 reset_clip();
00441 drawListPos++;
00442 }while(drawListPos < numDrawingList);
00443 }
00444 }
00445
00448 void redraw_engine_actions(int bgRedraw)
00449 {
00450 short int tmpProjPosX;
00451 short int tmpProjPosY;
00452 int numDrawingList;
00453
00454 tmpProjPosX = projPosXScreen;
00455 tmpProjPosY = projPosYScreen;
00456
00457 reset_clip();
00458
00459 if(bgRedraw)
00460 {
00461 freeze_time();
00462 if(needChangeScene!=-1 && needChangeScene!=-2)
00463 fade_out(paletteRGBA);
00464 clear_screen();
00465 redraw_grid();
00466
00467 copy_screen(frontVideoBuffer,workVideoBuffer);
00468 if(needChangeScene!=-1 && needChangeScene!=-2)
00469 fade_in(paletteRGBA);
00470 }
00471 else
00472 {
00473 blit_background_areas();
00474 }
00475
00476
00477 numDrawingList = process_actors_drawlist(bgRedraw);
00478
00479 sort_drawing_list(drawList,numDrawingList);
00480
00481 currNumOfRedrawBox = 0;
00482 process_drawing(numDrawingList);
00483
00484 #ifdef GAMEMOD
00485 display_zones(skipIntro);
00486 #endif
00487
00488
00489
00490 if(needChangeScene==-2)
00491 cross_fade(frontVideoBuffer, paletteRGBA);
00492
00493 if(bgRedraw)
00494 {
00495 flip();
00496 move_next_areas();
00497 }
00498 else
00499 {
00500 flip_redraw_areas();
00501 }
00502 }