Path: blob/master/RSDKv5/RSDK/Graphics/Legacy/DrawingLegacy.cpp
1163 views
12#include "v3/DrawingLegacyv3.cpp"3#include "v4/DrawingLegacyv4.cpp"45int32 RSDK::Legacy::SCREEN_XSIZE = 424;6int32 RSDK::Legacy::SCREEN_CENTERX = 424 / 2;78RSDK::Legacy::DrawListEntry RSDK::Legacy::drawListEntries[LEGACY_DRAWLAYER_COUNT];910int32 RSDK::Legacy::gfxDataPosition;11RSDK::Legacy::GFXSurface RSDK::Legacy::gfxSurface[LEGACY_SURFACE_COUNT];12uint8 RSDK::Legacy::graphicData[LEGACY_GFXDATA_SIZE];1314uint16 RSDK::Legacy::blendLookupTable[0x20 * 0x100];15uint16 RSDK::Legacy::subtractLookupTable[0x20 * 0x100];16uint16 RSDK::Legacy::tintLookupTable[0x10000];1718void RSDK::Legacy::GenerateBlendLookupTable()19{20for (int32 y = 0; y < 0x100; y++) {21for (int32 x = 0; x < 0x20; x++) {22blendLookupTable[x + (0x20 * y)] = y * x >> 8;23subtractLookupTable[x + (0x20 * y)] = y * (0x1F - x) >> 8;24}25}2627for (int32 i = 0; i < 0x10000; i++) {28int32 tintValue = ((i & 0x1F) + ((i & 0x7E0) >> 6) + ((i & 0xF800) >> 11)) / 3 + 6;29tintLookupTable[i] = 0x841 * MIN(tintValue, 0x1F);30}31}3233void RSDK::Legacy::ClearScreen(uint8 index)34{35uint16 color = activePalette[index];36uint16 *framebuffer = currentScreen->frameBuffer;3738int32 cnt = GFX_LINESIZE * SCREEN_YSIZE;39while (cnt--) {40*framebuffer = color;41++framebuffer;42}43}4445void RSDK::Legacy::DrawHLineScrollLayer(int32 layerID)46{47TileLayer *layer = &stageLayouts[activeTileLayers[layerID]];48if (!layer->xsize || !layer->ysize)49return;5051int32 screenwidth16 = (GFX_LINESIZE >> 4) - 1;52int32 layerwidth = layer->xsize;53int32 layerheight = layer->ysize;54bool32 aboveMidPoint = layerID >= tLayerMidPoint;5556uint8 *lineScroll;57int32 *deformationData;58int32 *deformationDataW;5960int32 yscrollOffset = 0;61if (activeTileLayers[layerID]) { // BG Layer62int32 yScroll = yScrollOffset * layer->parallaxFactor >> 8;63int32 fullheight = layerheight << 7;64layer->scrollPos += layer->scrollSpeed;65if (layer->scrollPos > fullheight << 16)66layer->scrollPos -= fullheight << 16;67yscrollOffset = (yScroll + (layer->scrollPos >> 16)) % fullheight;68layerheight = fullheight >> 7;69lineScroll = layer->lineScroll;70deformationData = &bgDeformationData2[(uint8)(yscrollOffset + layer->deformationOffset)];71deformationDataW = &bgDeformationData3[(uint8)(yscrollOffset + waterDrawPos + layer->deformationOffsetW)];72}73else { // FG Layer74lastXSize = layer->xsize;75yscrollOffset = yScrollOffset;76lineScroll = layer->lineScroll;77for (int32 i = 0; i < LEGACY_PARALLAX_COUNT; ++i) hParallax.linePos[i] = xScrollOffset;78deformationData = &bgDeformationData0[(uint8)(yscrollOffset + layer->deformationOffset)];79deformationDataW = &bgDeformationData1[(uint8)(yscrollOffset + waterDrawPos + layer->deformationOffsetW)];80}8182if (layer->type == LAYER_HSCROLL) {83if (lastXSize != layerwidth) {84int32 fullLayerwidth = layerwidth << 7;85for (int32 i = 0; i < hParallax.entryCount; ++i) {86hParallax.linePos[i] = xScrollOffset * hParallax.parallaxFactor[i] >> 8;87if (hParallax.scrollPos[i] > fullLayerwidth << 16)88hParallax.scrollPos[i] -= fullLayerwidth << 16;89if (hParallax.scrollPos[i] < 0)90hParallax.scrollPos[i] += fullLayerwidth << 16;91hParallax.linePos[i] += hParallax.scrollPos[i] >> 16;92hParallax.linePos[i] %= fullLayerwidth;93}94}95int32 w = -1;96if (activeTileLayers[layerID])97w = layerwidth;98lastXSize = w;99}100101uint16 *frameBuffer = currentScreen->frameBuffer;102uint8 *lineBuffer = gfxLineBuffer;103int32 tileYPos = yscrollOffset % (layerheight << 7);104if (tileYPos < 0)105tileYPos += layerheight << 7;106uint8 *scrollIndex = &lineScroll[tileYPos];107int32 tileY16 = tileYPos & 0xF;108int32 chunkY = tileYPos >> 7;109int32 tileY = (tileYPos & 0x7F) >> 4;110111// Draw Above Water (if applicable)112int32 drawableLines[2] = { waterDrawPos, SCREEN_YSIZE - waterDrawPos };113for (int32 i = 0; i < 2; ++i) {114while (drawableLines[i]--) {115activePalette = fullPalette[*lineBuffer];116lineBuffer++;117118int32 chunkX = hParallax.linePos[*scrollIndex];119if (i == 0) {120if (hParallax.deform[*scrollIndex])121chunkX += *deformationData;122++deformationData;123}124else {125if (hParallax.deform[*scrollIndex])126chunkX += *deformationDataW;127++deformationDataW;128}129++scrollIndex;130131int32 fullLayerwidth = layerwidth << 7;132if (chunkX < 0)133chunkX += fullLayerwidth;134if (chunkX >= fullLayerwidth)135chunkX -= fullLayerwidth;136137int32 chunkXPos = chunkX >> 7;138int32 tilePxXPos = chunkX & 0xF;139int32 tileXPxRemain = TILE_SIZE - tilePxXPos;140int32 chunk = (layer->tiles[(chunkX >> 7) + (chunkY << 8)] << 6) + ((chunkX & 0x7F) >> 4) + 8 * tileY;141int32 tileOffsetY = TILE_SIZE * tileY16;142int32 tileOffsetYFlipX = TILE_SIZE * tileY16 + 0xF;143int32 tileOffsetYFlipY = TILE_SIZE * (0xF - tileY16);144int32 tileOffsetYFlipXY = TILE_SIZE * (0xF - tileY16) + 0xF;145int32 lineRemain = GFX_LINESIZE;146147uint8 *pixels = NULL;148int32 tilePxLineCnt = tileXPxRemain;149150// Draw the first tile to the left151if (tiles128x128.visualPlane[chunk] == (uint8)aboveMidPoint) {152lineRemain -= tilePxLineCnt;153switch (tiles128x128.direction[chunk]) {154case FLIP_NONE:155pixels = &tilesetGFXData[tileOffsetY + tiles128x128.gfxDataPos[chunk] + tilePxXPos];156while (tilePxLineCnt--) {157if (*pixels > 0)158*frameBuffer = activePalette[*pixels];159++frameBuffer;160++pixels;161}162break;163164case FLIP_X:165166pixels = &tilesetGFXData[tileOffsetYFlipX + tiles128x128.gfxDataPos[chunk] - tilePxXPos];167while (tilePxLineCnt--) {168if (*pixels > 0)169*frameBuffer = activePalette[*pixels];170++frameBuffer;171--pixels;172}173break;174175case FLIP_Y:176pixels = &tilesetGFXData[tileOffsetYFlipY + tiles128x128.gfxDataPos[chunk] + tilePxXPos];177while (tilePxLineCnt--) {178if (*pixels > 0)179*frameBuffer = activePalette[*pixels];180++frameBuffer;181++pixels;182}183break;184185case FLIP_XY:186pixels = &tilesetGFXData[tileOffsetYFlipXY + tiles128x128.gfxDataPos[chunk] - tilePxXPos];187while (tilePxLineCnt--) {188if (*pixels > 0)189*frameBuffer = activePalette[*pixels];190++frameBuffer;191--pixels;192}193break;194195default: break;196}197}198else {199frameBuffer += tilePxLineCnt;200lineRemain -= tilePxLineCnt;201}202203// Draw the bulk of the tiles204int32 chunkTileX = ((chunkX & 0x7F) >> 4) + 1;205int32 tilesPerLine = screenwidth16;206while (tilesPerLine--) {207if (chunkTileX < 8) {208++chunk;209}210else {211if (++chunkXPos == layerwidth)212chunkXPos = 0;213214chunkTileX = 0;215chunk = (layer->tiles[chunkXPos + (chunkY << 8)] << 6) + 8 * tileY;216}217lineRemain -= TILE_SIZE;218219// Loop Unrolling (faster but messier code)220if (tiles128x128.visualPlane[chunk] == (uint8)aboveMidPoint) {221switch (tiles128x128.direction[chunk]) {222case FLIP_NONE:223pixels = &tilesetGFXData[tiles128x128.gfxDataPos[chunk] + tileOffsetY];224if (*pixels > 0)225*frameBuffer = activePalette[*pixels];226++frameBuffer;227++pixels;228229if (*pixels > 0)230*frameBuffer = activePalette[*pixels];231++frameBuffer;232++pixels;233234if (*pixels > 0)235*frameBuffer = activePalette[*pixels];236++frameBuffer;237++pixels;238239if (*pixels > 0)240*frameBuffer = activePalette[*pixels];241++frameBuffer;242++pixels;243244if (*pixels > 0)245*frameBuffer = activePalette[*pixels];246++frameBuffer;247++pixels;248249if (*pixels > 0)250*frameBuffer = activePalette[*pixels];251++frameBuffer;252++pixels;253254if (*pixels > 0)255*frameBuffer = activePalette[*pixels];256++frameBuffer;257++pixels;258259if (*pixels > 0)260*frameBuffer = activePalette[*pixels];261++frameBuffer;262++pixels;263264if (*pixels > 0)265*frameBuffer = activePalette[*pixels];266++frameBuffer;267++pixels;268269if (*pixels > 0)270*frameBuffer = activePalette[*pixels];271++frameBuffer;272++pixels;273274if (*pixels > 0)275*frameBuffer = activePalette[*pixels];276++frameBuffer;277++pixels;278279if (*pixels > 0)280*frameBuffer = activePalette[*pixels];281++frameBuffer;282++pixels;283284if (*pixels > 0)285*frameBuffer = activePalette[*pixels];286++frameBuffer;287++pixels;288289if (*pixels > 0)290*frameBuffer = activePalette[*pixels];291++frameBuffer;292++pixels;293294if (*pixels > 0)295*frameBuffer = activePalette[*pixels];296++frameBuffer;297++pixels;298299if (*pixels > 0)300*frameBuffer = activePalette[*pixels];301++frameBuffer;302break;303304case FLIP_X:305pixels = &tilesetGFXData[tiles128x128.gfxDataPos[chunk] + tileOffsetYFlipX];306if (*pixels > 0)307*frameBuffer = activePalette[*pixels];308++frameBuffer;309--pixels;310311if (*pixels > 0)312*frameBuffer = activePalette[*pixels];313++frameBuffer;314--pixels;315316if (*pixels > 0)317*frameBuffer = activePalette[*pixels];318++frameBuffer;319--pixels;320321if (*pixels > 0)322*frameBuffer = activePalette[*pixels];323++frameBuffer;324--pixels;325326if (*pixels > 0)327*frameBuffer = activePalette[*pixels];328++frameBuffer;329--pixels;330331if (*pixels > 0)332*frameBuffer = activePalette[*pixels];333++frameBuffer;334--pixels;335336if (*pixels > 0)337*frameBuffer = activePalette[*pixels];338++frameBuffer;339--pixels;340341if (*pixels > 0)342*frameBuffer = activePalette[*pixels];343++frameBuffer;344--pixels;345346if (*pixels > 0)347*frameBuffer = activePalette[*pixels];348++frameBuffer;349--pixels;350351if (*pixels > 0)352*frameBuffer = activePalette[*pixels];353++frameBuffer;354--pixels;355356if (*pixels > 0)357*frameBuffer = activePalette[*pixels];358++frameBuffer;359--pixels;360361if (*pixels > 0)362*frameBuffer = activePalette[*pixels];363++frameBuffer;364--pixels;365366if (*pixels > 0)367*frameBuffer = activePalette[*pixels];368++frameBuffer;369--pixels;370371if (*pixels > 0)372*frameBuffer = activePalette[*pixels];373++frameBuffer;374--pixels;375376if (*pixels > 0)377*frameBuffer = activePalette[*pixels];378++frameBuffer;379--pixels;380381if (*pixels > 0)382*frameBuffer = activePalette[*pixels];383++frameBuffer;384break;385386case FLIP_Y:387pixels = &tilesetGFXData[tiles128x128.gfxDataPos[chunk] + tileOffsetYFlipY];388if (*pixels > 0)389*frameBuffer = activePalette[*pixels];390++frameBuffer;391++pixels;392393if (*pixels > 0)394*frameBuffer = activePalette[*pixels];395++frameBuffer;396++pixels;397398if (*pixels > 0)399*frameBuffer = activePalette[*pixels];400++frameBuffer;401++pixels;402403if (*pixels > 0)404*frameBuffer = activePalette[*pixels];405++frameBuffer;406++pixels;407408if (*pixels > 0)409*frameBuffer = activePalette[*pixels];410++frameBuffer;411++pixels;412413if (*pixels > 0)414*frameBuffer = activePalette[*pixels];415++frameBuffer;416++pixels;417418if (*pixels > 0)419*frameBuffer = activePalette[*pixels];420++frameBuffer;421++pixels;422423if (*pixels > 0)424*frameBuffer = activePalette[*pixels];425++frameBuffer;426++pixels;427428if (*pixels > 0)429*frameBuffer = activePalette[*pixels];430++frameBuffer;431++pixels;432433if (*pixels > 0)434*frameBuffer = activePalette[*pixels];435++frameBuffer;436++pixels;437438if (*pixels > 0)439*frameBuffer = activePalette[*pixels];440++frameBuffer;441++pixels;442443if (*pixels > 0)444*frameBuffer = activePalette[*pixels];445++frameBuffer;446++pixels;447448if (*pixels > 0)449*frameBuffer = activePalette[*pixels];450++frameBuffer;451++pixels;452453if (*pixels > 0)454*frameBuffer = activePalette[*pixels];455++frameBuffer;456++pixels;457458if (*pixels > 0)459*frameBuffer = activePalette[*pixels];460++frameBuffer;461++pixels;462463if (*pixels > 0)464*frameBuffer = activePalette[*pixels];465++frameBuffer;466break;467468case FLIP_XY:469pixels = &tilesetGFXData[tiles128x128.gfxDataPos[chunk] + tileOffsetYFlipXY];470if (*pixels > 0)471*frameBuffer = activePalette[*pixels];472++frameBuffer;473--pixels;474475if (*pixels > 0)476*frameBuffer = activePalette[*pixels];477++frameBuffer;478--pixels;479480if (*pixels > 0)481*frameBuffer = activePalette[*pixels];482++frameBuffer;483--pixels;484485if (*pixels > 0)486*frameBuffer = activePalette[*pixels];487++frameBuffer;488--pixels;489490if (*pixels > 0)491*frameBuffer = activePalette[*pixels];492++frameBuffer;493--pixels;494495if (*pixels > 0)496*frameBuffer = activePalette[*pixels];497++frameBuffer;498--pixels;499500if (*pixels > 0)501*frameBuffer = activePalette[*pixels];502++frameBuffer;503--pixels;504505if (*pixels > 0)506*frameBuffer = activePalette[*pixels];507++frameBuffer;508--pixels;509510if (*pixels > 0)511*frameBuffer = activePalette[*pixels];512++frameBuffer;513--pixels;514515if (*pixels > 0)516*frameBuffer = activePalette[*pixels];517++frameBuffer;518--pixels;519520if (*pixels > 0)521*frameBuffer = activePalette[*pixels];522++frameBuffer;523--pixels;524525if (*pixels > 0)526*frameBuffer = activePalette[*pixels];527++frameBuffer;528--pixels;529530if (*pixels > 0)531*frameBuffer = activePalette[*pixels];532++frameBuffer;533--pixels;534535if (*pixels > 0)536*frameBuffer = activePalette[*pixels];537++frameBuffer;538--pixels;539540if (*pixels > 0)541*frameBuffer = activePalette[*pixels];542++frameBuffer;543--pixels;544545if (*pixels > 0)546*frameBuffer = activePalette[*pixels];547++frameBuffer;548break;549}550}551else {552frameBuffer += TILE_SIZE;553}554++chunkTileX;555}556557// Draw any remaining tiles558while (lineRemain > 0) {559if (chunkTileX++ < 8) {560++chunk;561}562else {563chunkTileX = 0;564if (++chunkXPos == layerwidth)565chunkXPos = 0;566567chunk = (layer->tiles[chunkXPos + (chunkY << 8)] << 6) + 8 * tileY;568}569570tilePxLineCnt = lineRemain >= TILE_SIZE ? TILE_SIZE : lineRemain;571lineRemain -= tilePxLineCnt;572if (tiles128x128.visualPlane[chunk] == (uint8)aboveMidPoint) {573switch (tiles128x128.direction[chunk]) {574case FLIP_NONE:575pixels = &tilesetGFXData[tiles128x128.gfxDataPos[chunk] + tileOffsetY];576while (tilePxLineCnt--) {577if (*pixels > 0)578*frameBuffer = activePalette[*pixels];579++frameBuffer;580++pixels;581}582break;583584case FLIP_X:585pixels = &tilesetGFXData[tiles128x128.gfxDataPos[chunk] + tileOffsetYFlipX];586while (tilePxLineCnt--) {587if (*pixels > 0)588*frameBuffer = activePalette[*pixels];589++frameBuffer;590--pixels;591}592break;593594case FLIP_Y:595pixels = &tilesetGFXData[tiles128x128.gfxDataPos[chunk] + tileOffsetYFlipY];596while (tilePxLineCnt--) {597if (*pixels > 0)598*frameBuffer = activePalette[*pixels];599++frameBuffer;600++pixels;601}602break;603604case FLIP_XY:605pixels = &tilesetGFXData[tiles128x128.gfxDataPos[chunk] + tileOffsetYFlipXY];606while (tilePxLineCnt--) {607if (*pixels > 0)608*frameBuffer = activePalette[*pixels];609++frameBuffer;610--pixels;611}612break;613614default: break;615}616}617else {618frameBuffer += tilePxLineCnt;619}620}621622if (++tileY16 >= TILE_SIZE) {623tileY16 = 0;624++tileY;625}626627if (tileY >= 8) {628if (++chunkY == layerheight) {629chunkY = 0;630scrollIndex -= 0x80 * layerheight;631}632tileY = 0;633}634}635}636}637void RSDK::Legacy::DrawVLineScrollLayer(int32 layerID)638{639TileLayer *layer = &stageLayouts[activeTileLayers[layerID]];640if (!layer->xsize || !layer->ysize)641return;642643int32 layerwidth = layer->xsize;644int32 layerheight = layer->ysize;645bool aboveMidPoint = layerID >= tLayerMidPoint;646647uint8 *lineScroll;648int32 *deformationData;649650int32 xscrollOffset = 0;651if (activeTileLayers[layerID]) { // BG Layer652int32 xScroll = xScrollOffset * layer->parallaxFactor >> 8;653int32 fullLayerwidth = layerwidth << 7;654layer->scrollPos += layer->scrollSpeed;655if (layer->scrollPos > fullLayerwidth << 16)656layer->scrollPos -= fullLayerwidth << 16;657xscrollOffset = (xScroll + (layer->scrollPos >> 16)) % fullLayerwidth;658layerwidth = fullLayerwidth >> 7;659lineScroll = layer->lineScroll;660deformationData = &bgDeformationData2[(uint8)(xscrollOffset + layer->deformationOffset)];661}662else { // FG Layer663lastYSize = layer->ysize;664xscrollOffset = xScrollOffset;665lineScroll = layer->lineScroll;666vParallax.linePos[0] = yScrollOffset;667vParallax.deform[0] = true;668deformationData = &bgDeformationData0[(uint8)(xScrollOffset + layer->deformationOffset)];669}670671if (layer->type == LAYER_VSCROLL) {672if (lastYSize != layerheight) {673int32 fullLayerheight = layerheight << 7;674for (int32 i = 0; i < vParallax.entryCount; ++i) {675vParallax.linePos[i] = yScrollOffset * vParallax.parallaxFactor[i] >> 8;676677vParallax.scrollPos[i] += vParallax.scrollPos[i] << 16;678if (vParallax.scrollPos[i] > fullLayerheight << 16)679vParallax.scrollPos[i] -= fullLayerheight << 16;680681vParallax.linePos[i] += vParallax.scrollPos[i] >> 16;682vParallax.linePos[i] %= fullLayerheight;683}684layerheight = fullLayerheight >> 7;685}686lastYSize = layerheight;687}688689uint16 *frameBuffer = currentScreen->frameBuffer;690activePalette = fullPalette[gfxLineBuffer[0]];691int32 tileXPos = xscrollOffset % (layerheight << 7);692if (tileXPos < 0)693tileXPos += layerheight << 7;694uint8 *scrollIndex = &lineScroll[tileXPos];695int32 chunkX = tileXPos >> 7;696int32 tileX16 = tileXPos & 0xF;697int32 tileX = (tileXPos & 0x7F) >> 4;698699// Draw Above Water (if applicable)700int32 drawableLines = SCREEN_XSIZE;701while (drawableLines--) {702int32 chunkY = vParallax.linePos[*scrollIndex];703if (vParallax.deform[*scrollIndex])704chunkY += *deformationData;705++deformationData;706++scrollIndex;707708int32 fullLayerHeight = layerheight << 7;709if (chunkY < 0)710chunkY += fullLayerHeight;711if (chunkY >= fullLayerHeight)712chunkY -= fullLayerHeight;713714int32 chunkYPos = chunkY >> 7;715int32 tileY = chunkY & 0xF;716int32 tileYPxRemain = TILE_SIZE - tileY;717int32 chunk = (layer->tiles[chunkX + (chunkY >> 7 << 8)] << 6) + tileX + 8 * ((chunkY & 0x7F) >> 4);718int32 tileOffsetXFlipX = 0xF - tileX16;719int32 tileOffsetXFlipY = tileX16 + SCREEN_YSIZE;720int32 tileOffsetXFlipXY = 0xFF - tileX16;721int32 lineRemain = SCREEN_YSIZE;722723uint8 *pixels = NULL;724int32 tilePxLineCnt = tileYPxRemain;725726// Draw the first tile to the left727if (tiles128x128.visualPlane[chunk] == (uint8)aboveMidPoint) {728lineRemain -= tilePxLineCnt;729switch (tiles128x128.direction[chunk]) {730case FLIP_NONE:731pixels = &tilesetGFXData[TILE_SIZE * tileY + tileX16 + tiles128x128.gfxDataPos[chunk]];732while (tilePxLineCnt--) {733if (*pixels > 0)734*frameBuffer = activePalette[*pixels];735frameBuffer += GFX_LINESIZE;736pixels += TILE_SIZE;737}738break;739740case FLIP_X:741pixels = &tilesetGFXData[TILE_SIZE * tileY + tileOffsetXFlipX + tiles128x128.gfxDataPos[chunk]];742while (tilePxLineCnt--) {743if (*pixels > 0)744*frameBuffer = activePalette[*pixels];745frameBuffer += GFX_LINESIZE;746pixels += TILE_SIZE;747}748break;749750case FLIP_Y:751pixels = &tilesetGFXData[tileOffsetXFlipY + tiles128x128.gfxDataPos[chunk] - TILE_SIZE * tileY];752while (tilePxLineCnt--) {753if (*pixels > 0)754*frameBuffer = activePalette[*pixels];755frameBuffer += GFX_LINESIZE;756pixels -= TILE_SIZE;757}758break;759760case FLIP_XY:761pixels = &tilesetGFXData[tileOffsetXFlipXY + tiles128x128.gfxDataPos[chunk] - TILE_SIZE * tileY];762while (tilePxLineCnt--) {763if (*pixels > 0)764*frameBuffer = activePalette[*pixels];765frameBuffer += GFX_LINESIZE;766pixels -= TILE_SIZE;767}768break;769770default: break;771}772}773else {774frameBuffer += GFX_LINESIZE * tileYPxRemain;775lineRemain -= tilePxLineCnt;776}777778// Draw the bulk of the tiles779int32 chunkTileY = ((chunkY & 0x7F) >> 4) + 1;780int32 tilesPerLine = (SCREEN_YSIZE >> 4) - 1;781782while (tilesPerLine--) {783if (chunkTileY < 8) {784chunk += 8;785}786else {787if (++chunkYPos == layerheight)788chunkYPos = 0;789790chunkTileY = 0;791chunk = (layer->tiles[chunkX + (chunkYPos << 8)] << 6) + tileX;792}793lineRemain -= TILE_SIZE;794795// Loop Unrolling (faster but messier code)796if (tiles128x128.visualPlane[chunk] == (uint8)aboveMidPoint) {797switch (tiles128x128.direction[chunk]) {798case FLIP_NONE:799pixels = &tilesetGFXData[tiles128x128.gfxDataPos[chunk] + tileX16];800if (*pixels > 0)801*frameBuffer = activePalette[*pixels];802frameBuffer += GFX_LINESIZE;803pixels += TILE_SIZE;804805if (*pixels > 0)806*frameBuffer = activePalette[*pixels];807frameBuffer += GFX_LINESIZE;808pixels += TILE_SIZE;809810if (*pixels > 0)811*frameBuffer = activePalette[*pixels];812frameBuffer += GFX_LINESIZE;813pixels += TILE_SIZE;814815if (*pixels > 0)816*frameBuffer = activePalette[*pixels];817frameBuffer += GFX_LINESIZE;818pixels += TILE_SIZE;819820if (*pixels > 0)821*frameBuffer = activePalette[*pixels];822frameBuffer += GFX_LINESIZE;823pixels += TILE_SIZE;824825if (*pixels > 0)826*frameBuffer = activePalette[*pixels];827frameBuffer += GFX_LINESIZE;828pixels += TILE_SIZE;829830if (*pixels > 0)831*frameBuffer = activePalette[*pixels];832frameBuffer += GFX_LINESIZE;833pixels += TILE_SIZE;834835if (*pixels > 0)836*frameBuffer = activePalette[*pixels];837frameBuffer += GFX_LINESIZE;838pixels += TILE_SIZE;839840if (*pixels > 0)841*frameBuffer = activePalette[*pixels];842frameBuffer += GFX_LINESIZE;843pixels += TILE_SIZE;844845if (*pixels > 0)846*frameBuffer = activePalette[*pixels];847frameBuffer += GFX_LINESIZE;848pixels += TILE_SIZE;849850if (*pixels > 0)851*frameBuffer = activePalette[*pixels];852frameBuffer += GFX_LINESIZE;853pixels += TILE_SIZE;854855if (*pixels > 0)856*frameBuffer = activePalette[*pixels];857frameBuffer += GFX_LINESIZE;858pixels += TILE_SIZE;859860if (*pixels > 0)861*frameBuffer = activePalette[*pixels];862frameBuffer += GFX_LINESIZE;863pixels += TILE_SIZE;864865if (*pixels > 0)866*frameBuffer = activePalette[*pixels];867frameBuffer += GFX_LINESIZE;868pixels += TILE_SIZE;869870if (*pixels > 0)871*frameBuffer = activePalette[*pixels];872frameBuffer += GFX_LINESIZE;873pixels += TILE_SIZE;874875if (*pixels > 0)876*frameBuffer = activePalette[*pixels];877frameBuffer += GFX_LINESIZE;878break;879880case FLIP_X:881pixels = &tilesetGFXData[tiles128x128.gfxDataPos[chunk] + tileOffsetXFlipX];882if (*pixels > 0)883*frameBuffer = activePalette[*pixels];884frameBuffer += GFX_LINESIZE;885pixels += TILE_SIZE;886887if (*pixels > 0)888*frameBuffer = activePalette[*pixels];889frameBuffer += GFX_LINESIZE;890pixels += TILE_SIZE;891892if (*pixels > 0)893*frameBuffer = activePalette[*pixels];894frameBuffer += GFX_LINESIZE;895pixels += TILE_SIZE;896897if (*pixels > 0)898*frameBuffer = activePalette[*pixels];899frameBuffer += GFX_LINESIZE;900pixels += TILE_SIZE;901902if (*pixels > 0)903*frameBuffer = activePalette[*pixels];904frameBuffer += GFX_LINESIZE;905pixels += TILE_SIZE;906907if (*pixels > 0)908*frameBuffer = activePalette[*pixels];909frameBuffer += GFX_LINESIZE;910pixels += TILE_SIZE;911912if (*pixels > 0)913*frameBuffer = activePalette[*pixels];914frameBuffer += GFX_LINESIZE;915pixels += TILE_SIZE;916917if (*pixels > 0)918*frameBuffer = activePalette[*pixels];919frameBuffer += GFX_LINESIZE;920pixels += TILE_SIZE;921922if (*pixels > 0)923*frameBuffer = activePalette[*pixels];924frameBuffer += GFX_LINESIZE;925pixels += TILE_SIZE;926927if (*pixels > 0)928*frameBuffer = activePalette[*pixels];929frameBuffer += GFX_LINESIZE;930pixels += TILE_SIZE;931932if (*pixels > 0)933*frameBuffer = activePalette[*pixels];934frameBuffer += GFX_LINESIZE;935pixels += TILE_SIZE;936937if (*pixels > 0)938*frameBuffer = activePalette[*pixels];939frameBuffer += GFX_LINESIZE;940pixels += TILE_SIZE;941942if (*pixels > 0)943*frameBuffer = activePalette[*pixels];944frameBuffer += GFX_LINESIZE;945pixels += TILE_SIZE;946947if (*pixels > 0)948*frameBuffer = activePalette[*pixels];949frameBuffer += GFX_LINESIZE;950pixels += TILE_SIZE;951952if (*pixels > 0)953*frameBuffer = activePalette[*pixels];954frameBuffer += GFX_LINESIZE;955pixels += TILE_SIZE;956957if (*pixels > 0)958*frameBuffer = activePalette[*pixels];959frameBuffer += GFX_LINESIZE;960break;961962case FLIP_Y:963pixels = &tilesetGFXData[tiles128x128.gfxDataPos[chunk] + tileOffsetXFlipY];964if (*pixels > 0)965*frameBuffer = activePalette[*pixels];966frameBuffer += GFX_LINESIZE;967pixels -= TILE_SIZE;968969if (*pixels > 0)970*frameBuffer = activePalette[*pixels];971frameBuffer += GFX_LINESIZE;972pixels -= TILE_SIZE;973974if (*pixels > 0)975*frameBuffer = activePalette[*pixels];976frameBuffer += GFX_LINESIZE;977pixels -= TILE_SIZE;978979if (*pixels > 0)980*frameBuffer = activePalette[*pixels];981frameBuffer += GFX_LINESIZE;982pixels -= TILE_SIZE;983984if (*pixels > 0)985*frameBuffer = activePalette[*pixels];986frameBuffer += GFX_LINESIZE;987pixels -= TILE_SIZE;988989if (*pixels > 0)990*frameBuffer = activePalette[*pixels];991frameBuffer += GFX_LINESIZE;992pixels -= TILE_SIZE;993994if (*pixels > 0)995*frameBuffer = activePalette[*pixels];996frameBuffer += GFX_LINESIZE;997pixels -= TILE_SIZE;998999if (*pixels > 0)1000*frameBuffer = activePalette[*pixels];1001frameBuffer += GFX_LINESIZE;1002pixels -= TILE_SIZE;10031004if (*pixels > 0)1005*frameBuffer = activePalette[*pixels];1006frameBuffer += GFX_LINESIZE;1007pixels -= TILE_SIZE;10081009if (*pixels > 0)1010*frameBuffer = activePalette[*pixels];1011frameBuffer += GFX_LINESIZE;1012pixels -= TILE_SIZE;10131014if (*pixels > 0)1015*frameBuffer = activePalette[*pixels];1016frameBuffer += GFX_LINESIZE;1017pixels -= TILE_SIZE;10181019if (*pixels > 0)1020*frameBuffer = activePalette[*pixels];1021frameBuffer += GFX_LINESIZE;1022pixels -= TILE_SIZE;10231024if (*pixels > 0)1025*frameBuffer = activePalette[*pixels];1026frameBuffer += GFX_LINESIZE;1027pixels -= TILE_SIZE;10281029if (*pixels > 0)1030*frameBuffer = activePalette[*pixels];1031frameBuffer += GFX_LINESIZE;1032pixels -= TILE_SIZE;10331034if (*pixels > 0)1035*frameBuffer = activePalette[*pixels];1036frameBuffer += GFX_LINESIZE;1037pixels -= TILE_SIZE;10381039if (*pixels > 0)1040*frameBuffer = activePalette[*pixels];1041frameBuffer += GFX_LINESIZE;1042break;10431044case FLIP_XY:1045pixels = &tilesetGFXData[tiles128x128.gfxDataPos[chunk] + tileOffsetXFlipXY];1046if (*pixels > 0)1047*frameBuffer = activePalette[*pixels];1048frameBuffer += GFX_LINESIZE;1049pixels -= TILE_SIZE;10501051if (*pixels > 0)1052*frameBuffer = activePalette[*pixels];1053frameBuffer += GFX_LINESIZE;1054pixels -= TILE_SIZE;10551056if (*pixels > 0)1057*frameBuffer = activePalette[*pixels];1058frameBuffer += GFX_LINESIZE;1059pixels -= TILE_SIZE;10601061if (*pixels > 0)1062*frameBuffer = activePalette[*pixels];1063frameBuffer += GFX_LINESIZE;1064pixels -= TILE_SIZE;10651066if (*pixels > 0)1067*frameBuffer = activePalette[*pixels];1068frameBuffer += GFX_LINESIZE;1069pixels -= TILE_SIZE;10701071if (*pixels > 0)1072*frameBuffer = activePalette[*pixels];1073frameBuffer += GFX_LINESIZE;1074pixels -= TILE_SIZE;10751076if (*pixels > 0)1077*frameBuffer = activePalette[*pixels];1078frameBuffer += GFX_LINESIZE;1079pixels -= TILE_SIZE;10801081if (*pixels > 0)1082*frameBuffer = activePalette[*pixels];1083frameBuffer += GFX_LINESIZE;1084pixels -= TILE_SIZE;10851086if (*pixels > 0)1087*frameBuffer = activePalette[*pixels];1088frameBuffer += GFX_LINESIZE;1089pixels -= TILE_SIZE;10901091if (*pixels > 0)1092*frameBuffer = activePalette[*pixels];1093frameBuffer += GFX_LINESIZE;1094pixels -= TILE_SIZE;10951096if (*pixels > 0)1097*frameBuffer = activePalette[*pixels];1098frameBuffer += GFX_LINESIZE;1099pixels -= TILE_SIZE;11001101if (*pixels > 0)1102*frameBuffer = activePalette[*pixels];1103frameBuffer += GFX_LINESIZE;1104pixels -= TILE_SIZE;11051106if (*pixels > 0)1107*frameBuffer = activePalette[*pixels];1108frameBuffer += GFX_LINESIZE;1109pixels -= TILE_SIZE;11101111if (*pixels > 0)1112*frameBuffer = activePalette[*pixels];1113frameBuffer += GFX_LINESIZE;1114pixels -= TILE_SIZE;11151116if (*pixels > 0)1117*frameBuffer = activePalette[*pixels];1118frameBuffer += GFX_LINESIZE;1119pixels -= TILE_SIZE;11201121if (*pixels > 0)1122*frameBuffer = activePalette[*pixels];1123frameBuffer += GFX_LINESIZE;1124break;1125}1126}1127else {1128frameBuffer += GFX_LINESIZE * TILE_SIZE;1129}1130++chunkTileY;1131}11321133// Draw any remaining tiles1134while (lineRemain > 0) {1135if (chunkTileY < 8) {1136chunk += 8;1137}1138else {1139if (++chunkYPos == layerheight)1140chunkYPos = 0;11411142chunkTileY = 0;1143chunk = (layer->tiles[chunkX + (chunkYPos << 8)] << 6) + tileX;1144}11451146tilePxLineCnt = lineRemain >= TILE_SIZE ? TILE_SIZE : lineRemain;1147lineRemain -= tilePxLineCnt;11481149if (tiles128x128.visualPlane[chunk] == (uint8)aboveMidPoint) {1150switch (tiles128x128.direction[chunk]) {1151case FLIP_NONE:1152pixels = &tilesetGFXData[tiles128x128.gfxDataPos[chunk] + tileX16];1153while (tilePxLineCnt--) {1154if (*pixels > 0)1155*frameBuffer = activePalette[*pixels];1156frameBuffer += GFX_LINESIZE;1157pixels += TILE_SIZE;1158}1159break;11601161case FLIP_X:1162pixels = &tilesetGFXData[tiles128x128.gfxDataPos[chunk] + tileOffsetXFlipX];1163while (tilePxLineCnt--) {1164if (*pixels > 0)1165*frameBuffer = activePalette[*pixels];1166frameBuffer += GFX_LINESIZE;1167pixels += TILE_SIZE;1168}1169break;11701171case FLIP_Y:1172pixels = &tilesetGFXData[tiles128x128.gfxDataPos[chunk] + tileOffsetXFlipY];1173while (tilePxLineCnt--) {1174if (*pixels > 0)1175*frameBuffer = activePalette[*pixels];1176frameBuffer += GFX_LINESIZE;1177pixels -= TILE_SIZE;1178}1179break;11801181case FLIP_XY:1182pixels = &tilesetGFXData[tiles128x128.gfxDataPos[chunk] + tileOffsetXFlipXY];1183while (tilePxLineCnt--) {1184if (*pixels > 0)1185*frameBuffer = activePalette[*pixels];1186frameBuffer += GFX_LINESIZE;1187pixels -= TILE_SIZE;1188}1189break;11901191default: break;1192}1193}1194else {1195frameBuffer += GFX_LINESIZE * tilePxLineCnt;1196}1197chunkTileY++;1198}11991200if (++tileX16 >= TILE_SIZE) {1201tileX16 = 0;1202++tileX;1203}12041205if (tileX >= 8) {1206if (++chunkX == layerwidth) {1207chunkX = 0;1208scrollIndex -= 0x80 * layerwidth;1209}1210tileX = 0;1211}12121213frameBuffer -= GFX_FBUFFERMINUSONE;1214}1215}1216void RSDK::Legacy::Draw3DFloorLayer(int32 layerID)1217{1218TileLayer *layer = &stageLayouts[activeTileLayers[layerID]];1219if (!layer->xsize || !layer->ysize)1220return;12211222int32 layerWidth = layer->xsize << 7;1223int32 layerHeight = layer->ysize << 7;1224int32 layerYPos = layer->ypos;1225int32 layerZPos = layer->zpos;1226int32 sinValue = sinM7LookupTable[layer->angle];1227int32 cosValue = cosM7LookupTable[layer->angle];1228uint8 *lineBuffer = &gfxLineBuffer[(SCREEN_YSIZE / 2) + 12];1229uint16 *frameBuffer = ¤tScreen->frameBuffer[((SCREEN_YSIZE / 2) + 12) * GFX_LINESIZE];1230int32 layerXPos = layer->xpos >> 4;1231int32 ZBuffer = layerZPos >> 4;12321233for (int32 i = 4; i < 112; ++i) {1234if (!(i & 1)) {1235activePalette = fullPalette[*lineBuffer];1236lineBuffer++;1237}1238int32 XBuffer = layerYPos / (i << 9) * -cosValue >> 8;1239int32 YBuffer = sinValue * (layerYPos / (i << 9)) >> 8;1240int32 XPos = layerXPos + (3 * sinValue * (layerYPos / (i << 9)) >> 2) - XBuffer * SCREEN_CENTERX;1241int32 YPos = ZBuffer + (3 * cosValue * (layerYPos / (i << 9)) >> 2) - YBuffer * SCREEN_CENTERX;1242int32 lineBuffer = 0;1243while (lineBuffer < GFX_LINESIZE) {1244int32 tileX = XPos >> 12;1245int32 tileY = YPos >> 12;1246if (tileX > -1 && tileX < layerWidth && tileY > -1 && tileY < layerHeight) {1247int32 chunk = tile3DFloorBuffer[(YPos >> 16 << 8) + (XPos >> 16)];1248uint8 *pixels = &tilesetGFXData[tiles128x128.gfxDataPos[chunk]];1249switch (tiles128x128.direction[chunk]) {1250case FLIP_NONE: pixels += TILE_SIZE * (tileY & 0xF) + (tileX & 0xF); break;1251case FLIP_X: pixels += TILE_SIZE * (tileY & 0xF) + 15 - (tileX & 0xF); break;1252case FLIP_Y: pixels += (tileX & 0xF) + SCREEN_YSIZE - TILE_SIZE * (tileY & 0xF); break;1253case FLIP_XY: pixels += 15 - (tileX & 0xF) + SCREEN_YSIZE - TILE_SIZE * (tileY & 0xF); break;1254default: break;1255}12561257if (*pixels > 0)1258*frameBuffer = activePalette[*pixels];1259}1260++frameBuffer;1261++lineBuffer;12621263XPos += XBuffer;1264YPos += YBuffer;1265}1266}1267}1268void RSDK::Legacy::Draw3DSkyLayer(int32 layerID)1269{1270TileLayer *layer = &stageLayouts[activeTileLayers[layerID]];1271if (!layer->xsize || !layer->ysize)1272return;12731274int32 layerWidth = layer->xsize << 7;1275int32 layerHeight = layer->ysize << 7;1276int32 layerYPos = layer->ypos;1277int32 sinValue = sinM7LookupTable[layer->angle & 0x1FF];1278int32 cosValue = cosM7LookupTable[layer->angle & 0x1FF];1279uint16 *frameBuffer = ¤tScreen->frameBuffer[((SCREEN_YSIZE / 2) + 12) * GFX_LINESIZE];1280uint8 *lineBuffer = &gfxLineBuffer[((SCREEN_YSIZE / 2) + 12)];1281int32 layerXPos = layer->xpos >> 4;1282int32 layerZPos = layer->zpos >> 4;1283for (int32 i = TILE_SIZE / 2; i < SCREEN_YSIZE - TILE_SIZE; ++i) {1284if (!(i & 1)) {1285activePalette = fullPalette[*lineBuffer];1286lineBuffer++;1287}12881289int32 xBuffer = layerYPos / (i << 8) * -cosValue >> 9;1290int32 yBuffer = sinValue * (layerYPos / (i << 8)) >> 9;1291int32 XPos = layerXPos + (3 * sinValue * (layerYPos / (i << 8)) >> 2) - xBuffer * GFX_LINESIZE;1292int32 YPos = layerZPos + (3 * cosValue * (layerYPos / (i << 8)) >> 2) - yBuffer * GFX_LINESIZE;1293int32 lineBuffer = 0;12941295while (lineBuffer < GFX_LINESIZE * 2) {1296int32 tileX = XPos >> 12;1297int32 tileY = YPos >> 12;1298if (tileX > -1 && tileX < layerWidth && tileY > -1 && tileY < layerHeight) {1299int32 chunk = tile3DFloorBuffer[(YPos >> 16 << 8) + (XPos >> 16)];1300uint8 *pixels = &tilesetGFXData[tiles128x128.gfxDataPos[chunk]];13011302switch (tiles128x128.direction[chunk]) {1303case FLIP_NONE: pixels += TILE_SIZE * (tileY & 0xF) + (tileX & 0xF); break;1304case FLIP_X: pixels += TILE_SIZE * (tileY & 0xF) + 0xF - (tileX & 0xF); break;1305case FLIP_Y: pixels += (tileX & 0xF) + SCREEN_YSIZE - TILE_SIZE * (tileY & 0xF); break;1306case FLIP_XY: pixels += 0xF - (tileX & 0xF) + SCREEN_YSIZE - TILE_SIZE * (tileY & 0xF); break;1307default: break;1308}13091310if (*pixels > 0)1311*frameBuffer = activePalette[*pixels];1312}13131314if (lineBuffer & 1)1315++frameBuffer;13161317lineBuffer++;1318XPos += xBuffer;1319YPos += yBuffer;1320}13211322if (!(i & 1))1323frameBuffer -= GFX_LINESIZE;1324}1325}13261327void RSDK::Legacy::DrawRectangle(int32 XPos, int32 YPos, int32 width, int32 height, int32 R, int32 G, int32 B, int32 A)1328{1329if (A > 0xFF)1330A = 0xFF;13311332if (width + XPos > GFX_LINESIZE)1333width = GFX_LINESIZE - XPos;1334if (XPos < 0) {1335width += XPos;1336XPos = 0;1337}13381339if (height + YPos > SCREEN_YSIZE)1340height = SCREEN_YSIZE - YPos;1341if (YPos < 0) {1342height += YPos;1343YPos = 0;1344}13451346if (width <= 0 || height <= 0 || A <= 0)1347return;13481349int32 pitch = GFX_LINESIZE - width;1350uint16 *frameBufferPtr = ¤tScreen->frameBuffer[XPos + GFX_LINESIZE * YPos];1351uint16 clr = PACK_RGB888(R, G, B);13521353if (A == 0xFF) {1354int32 h = height;1355while (h--) {1356int32 w = width;1357while (w--) {1358*frameBufferPtr = clr;1359++frameBufferPtr;1360}1361frameBufferPtr += pitch;1362}1363}1364else {1365uint16 *fbufferBlend = &blendLookupTable[0x20 * (0xFF - A)];1366uint16 *pixelBlend = &blendLookupTable[0x20 * A];13671368int32 h = height;1369while (h--) {1370int32 w = width;1371while (w--) {1372int32 R = (fbufferBlend[(*frameBufferPtr & 0xF800) >> 11] + pixelBlend[(clr & 0xF800) >> 11]) << 11;1373int32 G = (fbufferBlend[(*frameBufferPtr & 0x7E0) >> 6] + pixelBlend[(clr & 0x7E0) >> 6]) << 6;1374int32 B = fbufferBlend[*frameBufferPtr & 0x1F] + pixelBlend[clr & 0x1F];13751376*frameBufferPtr = R | G | B;1377++frameBufferPtr;1378}1379frameBufferPtr += pitch;1380}1381}1382}13831384void RSDK::Legacy::DrawTintRectangle(int32 XPos, int32 YPos, int32 width, int32 height)1385{1386if (width + XPos > GFX_LINESIZE)1387width = GFX_LINESIZE - XPos;1388if (XPos < 0) {1389width += XPos;1390XPos = 0;1391}13921393if (height + YPos > SCREEN_YSIZE)1394height = SCREEN_YSIZE - YPos;1395if (YPos < 0) {1396height += YPos;1397YPos = 0;1398}1399if (width < 0 || height < 0)1400return;1401int32 yOffset = GFX_LINESIZE - width;1402for (uint16 *frameBufferPtr = ¤tScreen->frameBuffer[XPos + GFX_LINESIZE * YPos];; frameBufferPtr += yOffset) {1403height--;1404if (height < 0)1405break;1406int32 w = width;1407while (w--) {1408*frameBufferPtr = tintLookupTable[*frameBufferPtr];1409++frameBufferPtr;1410}1411}1412}1413void RSDK::Legacy::DrawScaledTintMask(int32 direction, int32 XPos, int32 YPos, int32 pivotX, int32 pivotY, int32 scaleX, int32 scaleY, int32 width,1414int32 height, int32 sprX, int32 sprY, int32 sheetID)1415{1416int32 roundedYPos = 0;1417int32 roundedXPos = 0;1418int32 truescaleX = 4 * scaleX;1419int32 truescaleY = 4 * scaleY;1420int32 widthM1 = width - 1;1421int32 trueXPos = XPos - (truescaleX * pivotX >> 11);1422int32 trueYPos = YPos - (truescaleY * pivotY >> 11);1423width = truescaleX * width >> 11;1424height = truescaleY * height >> 11;1425int32 finalscaleX = (int32)(float)((float)(2048.0 / (float)truescaleX) * 2048.0);1426int32 finalscaleY = (int32)(float)((float)(2048.0 / (float)truescaleY) * 2048.0);14271428if (width + trueXPos > GFX_LINESIZE) {1429width = GFX_LINESIZE - trueXPos;1430}14311432if (direction) {1433if (trueXPos < 0) {1434widthM1 -= trueXPos * -finalscaleX >> 11;1435roundedXPos = (uint16)trueXPos * -(int16)finalscaleX & 0x7FF;1436width += trueXPos;1437trueXPos = 0;1438}1439}1440else if (trueXPos < 0) {1441sprX += trueXPos * -finalscaleX >> 11;1442roundedXPos = (uint16)trueXPos * -(int16)finalscaleX & 0x7FF;1443width += trueXPos;1444trueXPos = 0;1445}14461447if (height + trueYPos > SCREEN_YSIZE) {1448height = SCREEN_YSIZE - trueYPos;1449}1450if (trueYPos < 0) {1451sprY += trueYPos * -finalscaleY >> 11;1452roundedYPos = (uint16)trueYPos * -(int16)finalscaleY & 0x7FF;1453height += trueYPos;1454trueYPos = 0;1455}14561457if (width <= 0 || height <= 0)1458return;14591460GFXSurface *surface = &gfxSurface[sheetID];1461int32 pitch = GFX_LINESIZE - width;1462int32 gfxwidth = surface->width;1463// uint8 *lineBuffer = &gfxLineBuffer[trueYPos];1464uint8 *gfxData = &graphicData[sprX + surface->width * sprY + surface->dataPosition];1465uint16 *frameBufferPtr = ¤tScreen->frameBuffer[trueXPos + GFX_LINESIZE * trueYPos];1466if (direction == FLIP_X) {1467uint8 *gfxDataPtr = &gfxData[widthM1];1468int32 gfxPitch = 0;1469while (height--) {1470int32 roundXPos = roundedXPos;1471int32 w = width;1472while (w--) {1473if (*gfxDataPtr > 0)1474*frameBufferPtr = tintLookupTable[*frameBufferPtr];1475int32 offsetX = finalscaleX + roundXPos;1476gfxDataPtr -= offsetX >> 11;1477gfxPitch += offsetX >> 11;1478roundXPos = offsetX & 0x7FF;1479++frameBufferPtr;1480}1481frameBufferPtr += pitch;1482int32 offsetY = finalscaleY + roundedYPos;1483gfxDataPtr += gfxPitch + (offsetY >> 11) * gfxwidth;1484roundedYPos = offsetY & 0x7FF;1485gfxPitch = 0;1486}1487}1488else {1489int32 gfxPitch = 0;1490int32 h = height;1491while (h--) {1492int32 roundXPos = roundedXPos;1493int32 w = width;1494while (w--) {1495if (*gfxData > 0)1496*frameBufferPtr = tintLookupTable[*frameBufferPtr];1497int32 offsetX = finalscaleX + roundXPos;1498gfxData += offsetX >> 11;1499gfxPitch += offsetX >> 11;1500roundXPos = offsetX & 0x7FF;1501++frameBufferPtr;1502}1503frameBufferPtr += pitch;1504int32 offsetY = finalscaleY + roundedYPos;1505gfxData += (offsetY >> 11) * gfxwidth - gfxPitch;1506roundedYPos = offsetY & 0x7FF;1507gfxPitch = 0;1508}1509}1510}15111512void RSDK::Legacy::DrawSprite(int32 XPos, int32 YPos, int32 width, int32 height, int32 sprX, int32 sprY, int32 sheetID)1513{1514if (width + XPos > GFX_LINESIZE)1515width = GFX_LINESIZE - XPos;1516if (XPos < 0) {1517sprX -= XPos;1518width += XPos;1519XPos = 0;1520}1521if (height + YPos > SCREEN_YSIZE)1522height = SCREEN_YSIZE - YPos;1523if (YPos < 0) {1524sprY -= YPos;1525height += YPos;1526YPos = 0;1527}1528if (width <= 0 || height <= 0)1529return;15301531GFXSurface *surface = &gfxSurface[sheetID];1532int32 pitch = GFX_LINESIZE - width;1533int32 gfxPitch = surface->width - width;1534uint8 *lineBuffer = &gfxLineBuffer[YPos];1535uint8 *pixels = &graphicData[sprX + surface->width * sprY + surface->dataPosition];1536uint16 *frameBuffer = ¤tScreen->frameBuffer[XPos + GFX_LINESIZE * YPos];15371538while (height--) {1539activePalette = fullPalette[*lineBuffer];1540lineBuffer++;15411542int32 w = width;1543while (w--) {1544if (*pixels > 0)1545*frameBuffer = activePalette[*pixels];1546++pixels;1547++frameBuffer;1548}15491550frameBuffer += pitch;1551pixels += gfxPitch;1552}1553}15541555void RSDK::Legacy::DrawSpriteFlipped(int32 XPos, int32 YPos, int32 width, int32 height, int32 sprX, int32 sprY, int32 direction, int32 sheetID)1556{1557int32 widthFlip = width;1558int32 heightFlip = height;15591560if (width + XPos > GFX_LINESIZE) {1561width = GFX_LINESIZE - XPos;1562}1563if (XPos < 0) {1564sprX -= XPos;1565width += XPos;1566widthFlip += XPos + XPos;1567XPos = 0;1568}1569if (height + YPos > SCREEN_YSIZE) {1570height = SCREEN_YSIZE - YPos;1571}1572if (YPos < 0) {1573sprY -= YPos;1574height += YPos;1575heightFlip += YPos + YPos;1576YPos = 0;1577}1578if (width <= 0 || height <= 0)1579return;15801581GFXSurface *surface = &gfxSurface[sheetID];1582int32 pitch;1583int32 gfxPitch;1584uint8 *lineBuffer;1585uint8 *pixels;1586uint16 *frameBuffer;1587switch (direction) {1588case FLIP_NONE:1589pitch = GFX_LINESIZE - width;1590gfxPitch = surface->width - width;1591lineBuffer = &gfxLineBuffer[YPos];1592pixels = &graphicData[sprX + surface->width * sprY + surface->dataPosition];1593frameBuffer = ¤tScreen->frameBuffer[XPos + GFX_LINESIZE * YPos];15941595while (height--) {1596activePalette = fullPalette[*lineBuffer];1597lineBuffer++;15981599int32 w = width;1600while (w--) {1601if (*pixels > 0)1602*frameBuffer = activePalette[*pixels];1603++pixels;1604++frameBuffer;1605}16061607frameBuffer += pitch;1608pixels += gfxPitch;1609}1610break;16111612case FLIP_X:1613pitch = GFX_LINESIZE - width;1614gfxPitch = width + surface->width;1615lineBuffer = &gfxLineBuffer[YPos];1616pixels = &graphicData[widthFlip - 1 + sprX + surface->width * sprY + surface->dataPosition];1617frameBuffer = ¤tScreen->frameBuffer[XPos + GFX_LINESIZE * YPos];1618while (height--) {1619activePalette = fullPalette[*lineBuffer];16201621lineBuffer++;1622int32 w = width;1623while (w--) {1624if (*pixels > 0)1625*frameBuffer = activePalette[*pixels];1626--pixels;1627++frameBuffer;1628}16291630frameBuffer += pitch;1631pixels += gfxPitch;1632}1633break;16341635case FLIP_Y:1636pitch = GFX_LINESIZE - width;1637gfxPitch = width + surface->width;1638lineBuffer = &gfxLineBuffer[YPos];1639pixels = &graphicData[sprX + surface->width * (sprY + heightFlip - 1) + surface->dataPosition];1640frameBuffer = ¤tScreen->frameBuffer[XPos + GFX_LINESIZE * YPos];1641while (height--) {1642activePalette = fullPalette[*lineBuffer];1643lineBuffer++;16441645int32 w = width;1646while (w--) {1647if (*pixels > 0)1648*frameBuffer = activePalette[*pixels];1649++pixels;1650++frameBuffer;1651}16521653frameBuffer += pitch;1654pixels -= gfxPitch;1655}1656break;16571658case FLIP_XY:1659pitch = GFX_LINESIZE - width;1660gfxPitch = surface->width - width;1661lineBuffer = &gfxLineBuffer[YPos];1662pixels = &graphicData[widthFlip - 1 + sprX + surface->width * (sprY + heightFlip - 1) + surface->dataPosition];1663frameBuffer = ¤tScreen->frameBuffer[XPos + GFX_LINESIZE * YPos];1664while (height--) {1665activePalette = fullPalette[*lineBuffer];1666lineBuffer++;16671668int32 w = width;1669while (w--) {1670if (*pixels > 0)1671*frameBuffer = activePalette[*pixels];1672--pixels;1673++frameBuffer;1674}16751676frameBuffer += pitch;1677pixels -= gfxPitch;1678}1679break;16801681default: break;1682}1683}1684void RSDK::Legacy::DrawSpriteScaled(int32 direction, int32 XPos, int32 YPos, int32 pivotX, int32 pivotY, int32 scaleX, int32 scaleY, int32 width,1685int32 height, int32 sprX, int32 sprY, int32 sheetID)1686{1687int32 roundedYPos = 0;1688int32 roundedXPos = 0;1689int32 truescaleX = 4 * scaleX;1690int32 truescaleY = 4 * scaleY;1691int32 widthM1 = width - 1;1692int32 trueXPos = XPos - (truescaleX * pivotX >> 11);1693int32 trueYPos = YPos - (truescaleY * pivotY >> 11);1694width = truescaleX * width >> 11;1695height = truescaleY * height >> 11;1696int32 finalscaleX = (int32)(float)((float)(2048.0 / (float)truescaleX) * 2048.0);1697int32 finalscaleY = (int32)(float)((float)(2048.0 / (float)truescaleY) * 2048.0);1698if (width + trueXPos > GFX_LINESIZE) {1699width = GFX_LINESIZE - trueXPos;1700}17011702if (direction) {1703if (trueXPos < 0) {1704widthM1 -= trueXPos * -finalscaleX >> 11;1705roundedXPos = (uint16)trueXPos * -(int16)finalscaleX & 0x7FF;1706width += trueXPos;1707trueXPos = 0;1708}1709}1710else if (trueXPos < 0) {1711sprX += trueXPos * -finalscaleX >> 11;1712roundedXPos = (uint16)trueXPos * -(int16)finalscaleX & 0x7FF;1713width += trueXPos;1714trueXPos = 0;1715}17161717if (height + trueYPos > SCREEN_YSIZE) {1718height = SCREEN_YSIZE - trueYPos;1719}1720if (trueYPos < 0) {1721sprY += trueYPos * -finalscaleY >> 11;1722roundedYPos = (uint16)trueYPos * -(int16)finalscaleY & 0x7FF;1723height += trueYPos;1724trueYPos = 0;1725}17261727if (width <= 0 || height <= 0)1728return;17291730GFXSurface *surface = &gfxSurface[sheetID];1731int32 pitch = GFX_LINESIZE - width;1732int32 gfxwidth = surface->width;1733uint8 *lineBuffer = &gfxLineBuffer[trueYPos];1734uint8 *pixels = &graphicData[sprX + surface->width * sprY + surface->dataPosition];1735uint16 *frameBuffer = ¤tScreen->frameBuffer[trueXPos + GFX_LINESIZE * trueYPos];17361737if (direction == FLIP_X) {1738uint8 *pixelsPtr = &pixels[widthM1];1739int32 gfxPitch = 0;17401741while (height--) {1742activePalette = fullPalette[*lineBuffer];1743lineBuffer++;17441745int32 roundXPos = roundedXPos;1746int32 w = width;1747while (w--) {1748if (*pixelsPtr > 0)1749*frameBuffer = activePalette[*pixelsPtr];1750int32 offsetX = finalscaleX + roundXPos;1751pixelsPtr -= offsetX >> 11;1752gfxPitch += offsetX >> 11;1753roundXPos = offsetX & 0x7FF;1754++frameBuffer;1755}17561757frameBuffer += pitch;1758int32 offsetY = finalscaleY + roundedYPos;1759pixelsPtr += gfxPitch + (offsetY >> 11) * gfxwidth;1760roundedYPos = offsetY & 0x7FF;1761gfxPitch = 0;1762}1763}1764else {1765int32 gfxPitch = 0;1766int32 h = height;1767while (h--) {1768activePalette = fullPalette[*lineBuffer];1769lineBuffer++;17701771int32 roundXPos = roundedXPos;1772int32 w = width;1773while (w--) {1774if (*pixels > 0)1775*frameBuffer = activePalette[*pixels];1776int32 offsetX = finalscaleX + roundXPos;1777pixels += offsetX >> 11;1778gfxPitch += offsetX >> 11;1779roundXPos = offsetX & 0x7FF;1780++frameBuffer;1781}17821783frameBuffer += pitch;1784int32 offsetY = finalscaleY + roundedYPos;1785pixels += (offsetY >> 11) * gfxwidth - gfxPitch;1786roundedYPos = offsetY & 0x7FF;1787gfxPitch = 0;1788}1789}1790}1791void RSDK::Legacy::DrawSpriteRotated(int32 direction, int32 XPos, int32 YPos, int32 pivotX, int32 pivotY, int32 sprX, int32 sprY, int32 width,1792int32 height, int32 rotation, int32 sheetID)1793{1794int32 sprXPos = (pivotX + sprX) << 9;1795int32 sprYPos = (pivotY + sprY) << 9;1796int32 fullwidth = width + sprX;1797int32 fullheight = height + sprY;1798int32 angle = rotation & 0x1FF;1799if (angle < 0)1800angle += 0x200;1801if (angle)1802angle = 0x200 - angle;1803int32 sine = sin512LookupTable[angle];1804int32 cosine = cos512LookupTable[angle];1805int32 xPositions[4];1806int32 yPositions[4];18071808if (direction == FLIP_X) {1809xPositions[0] = XPos + ((sine * (-pivotY - 2) + cosine * (pivotX + 2)) >> 9);1810yPositions[0] = YPos + ((cosine * (-pivotY - 2) - sine * (pivotX + 2)) >> 9);1811xPositions[1] = XPos + ((sine * (-pivotY - 2) + cosine * (pivotX - width - 2)) >> 9);1812yPositions[1] = YPos + ((cosine * (-pivotY - 2) - sine * (pivotX - width - 2)) >> 9);1813xPositions[2] = XPos + ((sine * (height - pivotY + 2) + cosine * (pivotX + 2)) >> 9);1814yPositions[2] = YPos + ((cosine * (height - pivotY + 2) - sine * (pivotX + 2)) >> 9);1815int32 a = pivotX - width - 2;1816int32 b = height - pivotY + 2;1817xPositions[3] = XPos + ((sine * b + cosine * a) >> 9);1818yPositions[3] = YPos + ((cosine * b - sine * a) >> 9);1819}1820else {1821xPositions[0] = XPos + ((sine * (-pivotY - 2) + cosine * (-pivotX - 2)) >> 9);1822yPositions[0] = YPos + ((cosine * (-pivotY - 2) - sine * (-pivotX - 2)) >> 9);1823xPositions[1] = XPos + ((sine * (-pivotY - 2) + cosine * (width - pivotX + 2)) >> 9);1824yPositions[1] = YPos + ((cosine * (-pivotY - 2) - sine * (width - pivotX + 2)) >> 9);1825xPositions[2] = XPos + ((sine * (height - pivotY + 2) + cosine * (-pivotX - 2)) >> 9);1826yPositions[2] = YPos + ((cosine * (height - pivotY + 2) - sine * (-pivotX - 2)) >> 9);1827int32 a = width - pivotX + 2;1828int32 b = height - pivotY + 2;1829xPositions[3] = XPos + ((sine * b + cosine * a) >> 9);1830yPositions[3] = YPos + ((cosine * b - sine * a) >> 9);1831}18321833int32 left = GFX_LINESIZE;1834for (int32 i = 0; i < 4; ++i) {1835if (xPositions[i] < left)1836left = xPositions[i];1837}1838if (left < 0)1839left = 0;18401841int32 right = 0;1842for (int32 i = 0; i < 4; ++i) {1843if (xPositions[i] > right)1844right = xPositions[i];1845}1846if (right > GFX_LINESIZE)1847right = GFX_LINESIZE;1848int32 maxX = right - left;18491850int32 top = SCREEN_YSIZE;1851for (int32 i = 0; i < 4; ++i) {1852if (yPositions[i] < top)1853top = yPositions[i];1854}1855if (top < 0)1856top = 0;18571858int32 bottom = 0;1859for (int32 i = 0; i < 4; ++i) {1860if (yPositions[i] > bottom)1861bottom = yPositions[i];1862}1863if (bottom > SCREEN_YSIZE)1864bottom = SCREEN_YSIZE;1865int32 maxY = bottom - top;18661867if (maxX <= 0 || maxY <= 0)1868return;18691870GFXSurface *surface = &gfxSurface[sheetID];1871int32 pitch = GFX_LINESIZE - maxX;1872int32 lineSize = surface->widthShift;1873uint16 *frameBuffer = ¤tScreen->frameBuffer[left + GFX_LINESIZE * top];1874uint8 *lineBuffer = &gfxLineBuffer[top];1875int32 startX = left - XPos;1876int32 startY = top - YPos;1877int32 shiftPivot = (sprX << 9) - 1;1878int32 shiftheight = (sprY << 9) - 1;1879fullwidth <<= 9;1880fullheight <<= 9;1881uint8 *pixels = &graphicData[surface->dataPosition];1882if (cosine < 0 || sine < 0)1883sprYPos += sine + cosine;18841885if (direction == FLIP_X) {1886int32 drawX = sprXPos - (cosine * startX - sine * startY) - 0x100;1887int32 drawY = cosine * startY + sprYPos + sine * startX;1888while (maxY--) {1889activePalette = fullPalette[*lineBuffer];1890lineBuffer++;18911892int32 finalX = drawX;1893int32 finalY = drawY;1894int32 w = maxX;1895while (w--) {1896if (finalX > shiftPivot && finalX < fullwidth && finalY > shiftheight && finalY < fullheight) {1897uint8 index = pixels[(finalY >> 9 << lineSize) + (finalX >> 9)];1898if (index > 0)1899*frameBuffer = activePalette[index];1900}1901++frameBuffer;1902finalX -= cosine;1903finalY += sine;1904}19051906drawX += sine;1907drawY += cosine;1908frameBuffer += pitch;1909}1910}1911else {1912int32 drawX = sprXPos + cosine * startX - sine * startY;1913int32 drawY = cosine * startY + sprYPos + sine * startX;1914while (maxY--) {1915activePalette = fullPalette[*lineBuffer];1916lineBuffer++;19171918int32 finalX = drawX;1919int32 finalY = drawY;1920int32 w = maxX;1921while (w--) {1922if (finalX > shiftPivot && finalX < fullwidth && finalY > shiftheight && finalY < fullheight) {1923uint8 index = pixels[(finalY >> 9 << lineSize) + (finalX >> 9)];1924if (index > 0)1925*frameBuffer = activePalette[index];1926}1927++frameBuffer;1928finalX += cosine;1929finalY += sine;1930}19311932drawX -= sine;1933drawY += cosine;1934frameBuffer += pitch;1935}1936}1937}19381939void RSDK::Legacy::DrawSpriteRotozoom(int32 direction, int32 XPos, int32 YPos, int32 pivotX, int32 pivotY, int32 sprX, int32 sprY, int32 width,1940int32 height, int32 rotation, int32 scale, int32 sheetID)1941{1942if (scale == 0)1943return;19441945int32 sprXPos = (pivotX + sprX) << 9;1946int32 sprYPos = (pivotY + sprY) << 9;1947int32 fullwidth = width + sprX;1948int32 fullheight = height + sprY;1949int32 angle = rotation & 0x1FF;1950if (angle < 0)1951angle += 0x200;1952if (angle)1953angle = 0x200 - angle;1954int32 sine = scale * sin512LookupTable[angle] >> 9;1955int32 cosine = scale * cos512LookupTable[angle] >> 9;1956int32 xPositions[4];1957int32 yPositions[4];19581959if (direction == FLIP_X) {1960xPositions[0] = XPos + ((sine * (-pivotY - 2) + cosine * (pivotX + 2)) >> 9);1961yPositions[0] = YPos + ((cosine * (-pivotY - 2) - sine * (pivotX + 2)) >> 9);1962xPositions[1] = XPos + ((sine * (-pivotY - 2) + cosine * (pivotX - width - 2)) >> 9);1963yPositions[1] = YPos + ((cosine * (-pivotY - 2) - sine * (pivotX - width - 2)) >> 9);1964xPositions[2] = XPos + ((sine * (height - pivotY + 2) + cosine * (pivotX + 2)) >> 9);1965yPositions[2] = YPos + ((cosine * (height - pivotY + 2) - sine * (pivotX + 2)) >> 9);1966int32 a = pivotX - width - 2;1967int32 b = height - pivotY + 2;1968xPositions[3] = XPos + ((sine * b + cosine * a) >> 9);1969yPositions[3] = YPos + ((cosine * b - sine * a) >> 9);1970}1971else {1972xPositions[0] = XPos + ((sine * (-pivotY - 2) + cosine * (-pivotX - 2)) >> 9);1973yPositions[0] = YPos + ((cosine * (-pivotY - 2) - sine * (-pivotX - 2)) >> 9);1974xPositions[1] = XPos + ((sine * (-pivotY - 2) + cosine * (width - pivotX + 2)) >> 9);1975yPositions[1] = YPos + ((cosine * (-pivotY - 2) - sine * (width - pivotX + 2)) >> 9);1976xPositions[2] = XPos + ((sine * (height - pivotY + 2) + cosine * (-pivotX - 2)) >> 9);1977yPositions[2] = YPos + ((cosine * (height - pivotY + 2) - sine * (-pivotX - 2)) >> 9);1978int32 a = width - pivotX + 2;1979int32 b = height - pivotY + 2;1980xPositions[3] = XPos + ((sine * b + cosine * a) >> 9);1981yPositions[3] = YPos + ((cosine * b - sine * a) >> 9);1982}1983int32 truescale = (int32)(float)((float)(512.0 / (float)scale) * 512.0);1984sine = truescale * sin512LookupTable[angle] >> 9;1985cosine = truescale * cos512LookupTable[angle] >> 9;19861987int32 left = GFX_LINESIZE;1988for (int32 i = 0; i < 4; ++i) {1989if (xPositions[i] < left)1990left = xPositions[i];1991}1992if (left < 0)1993left = 0;19941995int32 right = 0;1996for (int32 i = 0; i < 4; ++i) {1997if (xPositions[i] > right)1998right = xPositions[i];1999}2000if (right > GFX_LINESIZE)2001right = GFX_LINESIZE;2002int32 maxX = right - left;20032004int32 top = SCREEN_YSIZE;2005for (int32 i = 0; i < 4; ++i) {2006if (yPositions[i] < top)2007top = yPositions[i];2008}2009if (top < 0)2010top = 0;20112012int32 bottom = 0;2013for (int32 i = 0; i < 4; ++i) {2014if (yPositions[i] > bottom)2015bottom = yPositions[i];2016}2017if (bottom > SCREEN_YSIZE)2018bottom = SCREEN_YSIZE;2019int32 maxY = bottom - top;20202021if (maxX <= 0 || maxY <= 0)2022return;20232024GFXSurface *surface = &gfxSurface[sheetID];2025int32 pitch = GFX_LINESIZE - maxX;2026int32 lineSize = surface->widthShift;2027uint16 *frameBuffer = ¤tScreen->frameBuffer[left + GFX_LINESIZE * top];2028uint8 *lineBuffer = &gfxLineBuffer[top];2029int32 startX = left - XPos;2030int32 startY = top - YPos;2031int32 shiftPivot = (sprX << 9) - 1;2032int32 shiftheight = (sprY << 9) - 1;2033fullwidth <<= 9;2034fullheight <<= 9;2035uint8 *pixels = &graphicData[surface->dataPosition];2036if (cosine < 0 || sine < 0)2037sprYPos += sine + cosine;20382039if (direction == FLIP_X) {2040int32 drawX = sprXPos - (cosine * startX - sine * startY) - (truescale >> 1);2041int32 drawY = cosine * startY + sprYPos + sine * startX;2042while (maxY--) {2043activePalette = fullPalette[*lineBuffer];2044lineBuffer++;20452046int32 finalX = drawX;2047int32 finalY = drawY;2048int32 w = maxX;2049while (w--) {2050if (finalX > shiftPivot && finalX < fullwidth && finalY > shiftheight && finalY < fullheight) {2051uint8 index = pixels[(finalY >> 9 << lineSize) + (finalX >> 9)];2052if (index > 0)2053*frameBuffer = activePalette[index];2054}20552056++frameBuffer;2057finalX -= cosine;2058finalY += sine;2059}20602061drawX += sine;2062drawY += cosine;2063frameBuffer += pitch;2064}2065}2066else {2067int32 drawX = sprXPos + cosine * startX - sine * startY;2068int32 drawY = cosine * startY + sprYPos + sine * startX;2069while (maxY--) {2070activePalette = fullPalette[*lineBuffer];2071lineBuffer++;20722073int32 finalX = drawX;2074int32 finalY = drawY;2075int32 w = maxX;2076while (w--) {2077if (finalX > shiftPivot && finalX < fullwidth && finalY > shiftheight && finalY < fullheight) {2078uint8 index = pixels[(finalY >> 9 << lineSize) + (finalX >> 9)];2079if (index > 0)2080*frameBuffer = activePalette[index];2081}20822083++frameBuffer;2084finalX += cosine;2085finalY += sine;2086}20872088drawX -= sine;2089drawY += cosine;2090frameBuffer += pitch;2091}2092}2093}20942095void RSDK::Legacy::DrawBlendedSprite(int32 XPos, int32 YPos, int32 width, int32 height, int32 sprX, int32 sprY, int32 sheetID)2096{2097if (width + XPos > GFX_LINESIZE)2098width = GFX_LINESIZE - XPos;2099if (XPos < 0) {2100sprX -= XPos;2101width += XPos;2102XPos = 0;2103}2104if (height + YPos > SCREEN_YSIZE)2105height = SCREEN_YSIZE - YPos;2106if (YPos < 0) {2107sprY -= YPos;2108height += YPos;2109YPos = 0;2110}2111if (width <= 0 || height <= 0)2112return;21132114GFXSurface *surface = &gfxSurface[sheetID];2115int32 pitch = GFX_LINESIZE - width;2116int32 gfxPitch = surface->width - width;2117uint8 *lineBuffer = &gfxLineBuffer[YPos];2118uint8 *pixels = &graphicData[sprX + surface->width * sprY + surface->dataPosition];2119uint16 *frameBuffer = ¤tScreen->frameBuffer[XPos + GFX_LINESIZE * YPos];21202121while (height--) {2122activePalette = fullPalette[*lineBuffer];2123lineBuffer++;21242125int32 w = width;2126while (w--) {2127if (*pixels > 0)2128*frameBuffer = ((activePalette[*pixels] & 0xF7DE) >> 1) + ((*frameBuffer & 0xF7DE) >> 1);2129++pixels;2130++frameBuffer;2131}21322133frameBuffer += pitch;2134pixels += gfxPitch;2135}2136}2137void RSDK::Legacy::DrawAlphaBlendedSprite(int32 XPos, int32 YPos, int32 width, int32 height, int32 sprX, int32 sprY, int32 alpha, int32 sheetID)2138{2139if (alpha > 0xFF)2140alpha = 0xFF;21412142if (width + XPos > GFX_LINESIZE)2143width = GFX_LINESIZE - XPos;2144if (XPos < 0) {2145sprX -= XPos;2146width += XPos;2147XPos = 0;2148}2149if (height + YPos > SCREEN_YSIZE)2150height = SCREEN_YSIZE - YPos;2151if (YPos < 0) {2152sprY -= YPos;2153height += YPos;2154YPos = 0;2155}2156if (width <= 0 || height <= 0 || alpha <= 0)2157return;21582159GFXSurface *surface = &gfxSurface[sheetID];2160int32 pitch = GFX_LINESIZE - width;2161int32 gfxPitch = surface->width - width;2162uint8 *lineBuffer = &gfxLineBuffer[YPos];2163uint8 *pixels = &graphicData[sprX + surface->width * sprY + surface->dataPosition];2164uint16 *frameBuffer = ¤tScreen->frameBuffer[XPos + GFX_LINESIZE * YPos];2165if (alpha == 0xFF) {2166while (height--) {2167activePalette = fullPalette[*lineBuffer];2168lineBuffer++;21692170int32 w = width;2171while (w--) {2172if (*pixels > 0)2173*frameBuffer = activePalette[*pixels];2174++pixels;2175++frameBuffer;2176}21772178frameBuffer += pitch;2179pixels += gfxPitch;2180}2181}2182else {2183uint16 *fbufferBlend = &blendLookupTable[0x20 * (0xFF - alpha)];2184uint16 *pixelBlend = &blendLookupTable[0x20 * alpha];21852186while (height--) {2187activePalette = fullPalette[*lineBuffer];2188lineBuffer++;21892190int32 w = width;2191while (w--) {2192if (*pixels > 0) {2193uint16 color = activePalette[*pixels];21942195int32 R = (fbufferBlend[(*frameBuffer & 0xF800) >> 11] + pixelBlend[(color & 0xF800) >> 11]) << 11;2196int32 G = (fbufferBlend[(*frameBuffer & 0x7E0) >> 6] + pixelBlend[(color & 0x7E0) >> 6]) << 6;2197int32 B = fbufferBlend[*frameBuffer & 0x1F] + pixelBlend[color & 0x1F];21982199*frameBuffer = R | G | B;2200}2201++pixels;2202++frameBuffer;2203}22042205frameBuffer += pitch;2206pixels += gfxPitch;2207}2208}2209}2210void RSDK::Legacy::DrawAdditiveBlendedSprite(int32 XPos, int32 YPos, int32 width, int32 height, int32 sprX, int32 sprY, int32 alpha, int32 sheetID)2211{2212if (alpha > 0xFF)2213alpha = 0xFF;22142215if (width + XPos > GFX_LINESIZE)2216width = GFX_LINESIZE - XPos;22172218if (XPos < 0) {2219sprX -= XPos;2220width += XPos;2221XPos = 0;2222}22232224if (height + YPos > SCREEN_YSIZE)2225height = SCREEN_YSIZE - YPos;22262227if (YPos < 0) {2228sprY -= YPos;2229height += YPos;2230YPos = 0;2231}22322233if (width <= 0 || height <= 0 || alpha <= 0)2234return;22352236uint16 *blendTablePtr = &blendLookupTable[0x20 * alpha];2237GFXSurface *surface = &gfxSurface[sheetID];2238int32 pitch = GFX_LINESIZE - width;2239int32 gfxPitch = surface->width - width;2240uint8 *lineBuffer = &gfxLineBuffer[YPos];2241uint8 *pixels = &graphicData[sprX + surface->width * sprY + surface->dataPosition];2242uint16 *frameBuffer = ¤tScreen->frameBuffer[XPos + GFX_LINESIZE * YPos];22432244while (height--) {2245activePalette = fullPalette[*lineBuffer];2246lineBuffer++;22472248int32 w = width;2249while (w--) {2250if (*pixels > 0) {2251uint16 color = activePalette[*pixels];22522253int32 R = MIN((blendTablePtr[(color & 0xF800) >> 11] << 11) + (*frameBuffer & 0xF800), 0xF800);2254int32 G = MIN((blendTablePtr[(color & 0x7E0) >> 6] << 6) + (*frameBuffer & 0x7E0), 0x7E0);2255int32 B = MIN(blendTablePtr[color & 0x1F] + (*frameBuffer & 0x1F), 0x1F);22562257*frameBuffer = R | G | B;2258}22592260++pixels;2261++frameBuffer;2262}22632264frameBuffer += pitch;2265pixels += gfxPitch;2266}2267}2268void RSDK::Legacy::DrawSubtractiveBlendedSprite(int32 XPos, int32 YPos, int32 width, int32 height, int32 sprX, int32 sprY, int32 alpha, int32 sheetID)2269{2270if (alpha > 0xFF)2271alpha = 0xFF;22722273if (width + XPos > GFX_LINESIZE)2274width = GFX_LINESIZE - XPos;2275if (XPos < 0) {2276sprX -= XPos;2277width += XPos;2278XPos = 0;2279}2280if (height + YPos > SCREEN_YSIZE)2281height = SCREEN_YSIZE - YPos;2282if (YPos < 0) {2283sprY -= YPos;2284height += YPos;2285YPos = 0;2286}2287if (width <= 0 || height <= 0 || alpha <= 0)2288return;22892290uint16 *subBlendTable = &subtractLookupTable[0x20 * alpha];2291GFXSurface *surface = &gfxSurface[sheetID];2292int32 pitch = GFX_LINESIZE - width;2293int32 gfxPitch = surface->width - width;2294uint8 *lineBuffer = &gfxLineBuffer[YPos];2295uint8 *pixels = &graphicData[sprX + surface->width * sprY + surface->dataPosition];2296uint16 *frameBuffer = ¤tScreen->frameBuffer[XPos + GFX_LINESIZE * YPos];22972298while (height--) {2299activePalette = fullPalette[*lineBuffer];2300lineBuffer++;23012302int32 w = width;2303while (w--) {2304if (*pixels > 0) {2305uint16 color = activePalette[*pixels];23062307int32 R = MAX((*frameBuffer & 0xF800) - (subBlendTable[(color & 0xF800) >> 11] << 11), 0);2308int32 G = MAX((*frameBuffer & 0x7E0) - (subBlendTable[(color & 0x7E0) >> 6] << 6), 0);2309int32 B = MAX((*frameBuffer & 0x1F) - subBlendTable[color & 0x1F], 0);23102311*frameBuffer = R | G | B;2312}2313++pixels;2314++frameBuffer;2315}2316frameBuffer += pitch;2317pixels += gfxPitch;2318}2319}23202321void RSDK::Legacy::DrawFace(void *v, uint32 color)2322{2323Vertex *verts = (Vertex *)v;2324int32 alpha = (color & 0x7F000000) >> 23;2325if (alpha < 1)2326return;23272328if (alpha > 0xFF)2329alpha = 0xFF;23302331if (verts[0].x < 0 && verts[1].x < 0 && verts[2].x < 0 && verts[3].x < 0)2332return;23332334if (verts[0].x > GFX_LINESIZE && verts[1].x > GFX_LINESIZE && verts[2].x > GFX_LINESIZE && verts[3].x > GFX_LINESIZE)2335return;23362337if (verts[0].y < 0 && verts[1].y < 0 && verts[2].y < 0 && verts[3].y < 0)2338return;23392340if (verts[0].y > SCREEN_YSIZE && verts[1].y > SCREEN_YSIZE && verts[2].y > SCREEN_YSIZE && verts[3].y > SCREEN_YSIZE)2341return;23422343if (verts[0].x == verts[1].x && verts[1].x == verts[2].x && verts[2].x == verts[3].x)2344return;23452346if (verts[0].y == verts[1].y && verts[1].y == verts[2].y && verts[2].y == verts[3].y)2347return;23482349int32 vertexA = 0;2350int32 vertexB = 1;2351int32 vertexC = 2;2352int32 vertexD = 3;2353if (verts[1].y < verts[0].y) {2354vertexA = 1;2355vertexB = 0;2356}2357if (verts[2].y < verts[vertexA].y) {2358int32 temp = vertexA;2359vertexA = 2;2360vertexC = temp;2361}2362if (verts[3].y < verts[vertexA].y) {2363int32 temp = vertexA;2364vertexA = 3;2365vertexD = temp;2366}2367if (verts[vertexC].y < verts[vertexB].y) {2368int32 temp = vertexB;2369vertexB = vertexC;2370vertexC = temp;2371}2372if (verts[vertexD].y < verts[vertexB].y) {2373int32 temp = vertexB;2374vertexB = vertexD;2375vertexD = temp;2376}2377if (verts[vertexD].y < verts[vertexC].y) {2378int32 temp = vertexC;2379vertexC = vertexD;2380vertexD = temp;2381}23822383int32 faceTop = verts[vertexA].y;2384int32 faceBottom = verts[vertexD].y;2385if (faceTop < 0)2386faceTop = 0;2387if (faceBottom > SCREEN_YSIZE)2388faceBottom = SCREEN_YSIZE;2389for (int32 i = faceTop; i < faceBottom; ++i) {2390faceLineStart[i] = 100000;2391faceLineEnd[i] = -100000;2392}23932394ProcessScanEdge(&verts[vertexA], &verts[vertexB]);2395ProcessScanEdge(&verts[vertexA], &verts[vertexC]);2396ProcessScanEdge(&verts[vertexA], &verts[vertexD]);2397ProcessScanEdge(&verts[vertexB], &verts[vertexC]);2398ProcessScanEdge(&verts[vertexC], &verts[vertexD]);2399ProcessScanEdge(&verts[vertexB], &verts[vertexD]);24002401uint16 color16 = PACK_RGB888(((color >> 16) & 0xFF), ((color >> 8) & 0xFF), ((color >> 0) & 0xFF));2402uint16 *frameBuffer = ¤tScreen->frameBuffer[GFX_LINESIZE * faceTop];24032404if (alpha == 0xFF) {2405while (faceTop < faceBottom) {2406int32 startX = faceLineStart[faceTop];2407int32 endX = faceLineEnd[faceTop];2408if (startX >= GFX_LINESIZE || endX <= 0) {2409frameBuffer += GFX_LINESIZE;2410}2411else {2412if (startX < 0)2413startX = 0;2414if (endX > GFX_LINESIZE_MINUSONE)2415endX = GFX_LINESIZE_MINUSONE;2416uint16 *frameBufferPtr = &frameBuffer[startX];2417frameBuffer += GFX_LINESIZE;2418int32 vertexwidth = endX - startX + 1;2419while (vertexwidth--) {2420*frameBufferPtr = color16;2421++frameBufferPtr;2422}2423}2424++faceTop;2425}2426}2427else {2428uint16 *fbufferBlend = &blendLookupTable[0x20 * (0xFF - alpha)];2429uint16 *pixelBlend = &blendLookupTable[0x20 * alpha];24302431while (faceTop < faceBottom) {2432int32 startX = faceLineStart[faceTop];2433int32 endX = faceLineEnd[faceTop];2434if (startX >= GFX_LINESIZE || endX <= 0) {2435frameBuffer += GFX_LINESIZE;2436}2437else {2438if (startX < 0)2439startX = 0;2440if (endX > GFX_LINESIZE_MINUSONE)2441endX = GFX_LINESIZE_MINUSONE;2442uint16 *framebufferPtr = &frameBuffer[startX];2443frameBuffer += GFX_LINESIZE;2444int32 vertexwidth = endX - startX + 1;2445while (vertexwidth--) {2446int32 R = (fbufferBlend[(*framebufferPtr & 0xF800) >> 11] + pixelBlend[(color16 & 0xF800) >> 11]) << 11;2447int32 G = (fbufferBlend[(*framebufferPtr & 0x7E0) >> 6] + pixelBlend[(color16 & 0x7E0) >> 6]) << 6;2448int32 B = fbufferBlend[*framebufferPtr & 0x1F] + pixelBlend[color16 & 0x1F];24492450*framebufferPtr = R | G | B;2451++framebufferPtr;2452}2453}2454++faceTop;2455}2456}2457}2458void RSDK::Legacy::DrawTexturedFace(void *v, uint8 sheetID)2459{2460Vertex *verts = (Vertex *)v;24612462if (verts[0].x < 0 && verts[1].x < 0 && verts[2].x < 0 && verts[3].x < 0)2463return;2464if (verts[0].x > GFX_LINESIZE && verts[1].x > GFX_LINESIZE && verts[2].x > GFX_LINESIZE && verts[3].x > GFX_LINESIZE)2465return;2466if (verts[0].y < 0 && verts[1].y < 0 && verts[2].y < 0 && verts[3].y < 0)2467return;2468if (verts[0].y > SCREEN_YSIZE && verts[1].y > SCREEN_YSIZE && verts[2].y > SCREEN_YSIZE && verts[3].y > SCREEN_YSIZE)2469return;2470if (verts[0].x == verts[1].x && verts[1].x == verts[2].x && verts[2].x == verts[3].x)2471return;2472if (verts[0].y == verts[1].y && verts[1].y == verts[2].y && verts[2].y == verts[3].y)2473return;24742475int32 vertexA = 0;2476int32 vertexB = 1;2477int32 vertexC = 2;2478int32 vertexD = 3;2479if (verts[1].y < verts[0].y) {2480vertexA = 1;2481vertexB = 0;2482}2483if (verts[2].y < verts[vertexA].y) {2484int32 temp = vertexA;2485vertexA = 2;2486vertexC = temp;2487}2488if (verts[3].y < verts[vertexA].y) {2489int32 temp = vertexA;2490vertexA = 3;2491vertexD = temp;2492}2493if (verts[vertexC].y < verts[vertexB].y) {2494int32 temp = vertexB;2495vertexB = vertexC;2496vertexC = temp;2497}2498if (verts[vertexD].y < verts[vertexB].y) {2499int32 temp = vertexB;2500vertexB = vertexD;2501vertexD = temp;2502}2503if (verts[vertexD].y < verts[vertexC].y) {2504int32 temp = vertexC;2505vertexC = vertexD;2506vertexD = temp;2507}25082509int32 faceTop = verts[vertexA].y;2510int32 faceBottom = verts[vertexD].y;2511if (faceTop < 0)2512faceTop = 0;2513if (faceBottom > SCREEN_YSIZE)2514faceBottom = SCREEN_YSIZE;2515for (int32 i = faceTop; i < faceBottom; ++i) {2516faceLineStart[i] = 100000;2517faceLineEnd[i] = -100000;2518}25192520ProcessScanEdgeUV(&verts[vertexA], &verts[vertexB]);2521ProcessScanEdgeUV(&verts[vertexA], &verts[vertexC]);2522ProcessScanEdgeUV(&verts[vertexA], &verts[vertexD]);2523ProcessScanEdgeUV(&verts[vertexB], &verts[vertexC]);2524ProcessScanEdgeUV(&verts[vertexC], &verts[vertexD]);2525ProcessScanEdgeUV(&verts[vertexB], &verts[vertexD]);25262527uint16 *frameBuffer = ¤tScreen->frameBuffer[GFX_LINESIZE * faceTop];2528uint8 *pixels = &graphicData[gfxSurface[sheetID].dataPosition];2529int32 shiftwidth = gfxSurface[sheetID].widthShift;2530uint8 *lineBuffer = &gfxLineBuffer[faceTop];25312532while (faceTop < faceBottom) {2533activePalette = fullPalette[*lineBuffer];2534lineBuffer++;25352536int32 startX = faceLineStart[faceTop];2537int32 endX = faceLineEnd[faceTop];2538int32 UPos = faceLineStartU[faceTop];2539int32 VPos = faceLineStartV[faceTop];2540if (startX >= GFX_LINESIZE || endX <= 0) {2541frameBuffer += GFX_LINESIZE;2542}2543else {2544int32 posDifference = endX - startX;2545int32 bufferedUPos = 0;2546int32 bufferedVPos = 0;2547if (endX == startX) {2548bufferedUPos = 0;2549bufferedVPos = 0;2550}2551else {2552bufferedUPos = (faceLineEndU[faceTop] - UPos) / posDifference;2553bufferedVPos = (faceLineEndV[faceTop] - VPos) / posDifference;2554}2555if (endX > GFX_LINESIZE_MINUSONE)2556posDifference = GFX_LINESIZE_MINUSONE - startX;2557if (startX < 0) {2558posDifference += startX;2559UPos -= startX * bufferedUPos;2560VPos -= startX * bufferedVPos;2561startX = 0;2562}25632564uint16 *framebufferPtr = &frameBuffer[startX];2565frameBuffer += GFX_LINESIZE;25662567int32 counter = posDifference + 1;2568while (counter--) {2569if (UPos < 0)2570UPos = 0;2571if (VPos < 0)2572VPos = 0;2573uint16 index = pixels[(VPos >> 16 << shiftwidth) + (UPos >> 16)];2574if (index > 0)2575*framebufferPtr = activePalette[index];2576framebufferPtr++;2577UPos += bufferedUPos;2578VPos += bufferedVPos;2579}2580}2581++faceTop;2582}2583}25842585void RSDK::Legacy::v4::DrawObjectAnimation(void *objScr, void *ent, int32 XPos, int32 YPos)2586{2587ObjectScript *objectScript = (ObjectScript *)objScr;2588Entity *entity = (Entity *)ent;2589SpriteAnimation *sprAnim = &animationList[objectScript->animFile->aniListOffset + entity->animation];2590SpriteFrame *frame = &animFrames[sprAnim->frameListOffset + entity->frame];2591int32 rotation = 0;25922593switch (sprAnim->rotationStyle) {2594case ROTSTYLE_NONE:2595switch (entity->direction) {2596case FLIP_NONE:2597DrawSpriteFlipped(frame->pivotX + XPos, frame->pivotY + YPos, frame->width, frame->height, frame->sprX, frame->sprY, FLIP_NONE,2598frame->sheetID);2599break;26002601case FLIP_X:2602DrawSpriteFlipped(XPos - frame->width - frame->pivotX, frame->pivotY + YPos, frame->width, frame->height, frame->sprX,2603frame->sprY, FLIP_X, frame->sheetID);2604break;2605case FLIP_Y:26062607DrawSpriteFlipped(frame->pivotX + XPos, YPos - frame->height - frame->pivotY, frame->width, frame->height, frame->sprX,2608frame->sprY, FLIP_Y, frame->sheetID);2609break;26102611case FLIP_XY:2612DrawSpriteFlipped(XPos - frame->width - frame->pivotX, YPos - frame->height - frame->pivotY, frame->width, frame->height,2613frame->sprX, frame->sprY, FLIP_XY, frame->sheetID);2614break;26152616default: break;2617}2618break;26192620case ROTSTYLE_FULL:2621DrawSpriteRotated(entity->direction, XPos, YPos, -frame->pivotX, -frame->pivotY, frame->sprX, frame->sprY, frame->width, frame->height,2622entity->rotation, frame->sheetID);2623break;26242625case ROTSTYLE_45DEG:2626if (entity->rotation >= 0x100)2627DrawSpriteRotated(entity->direction, XPos, YPos, -frame->pivotX, -frame->pivotY, frame->sprX, frame->sprY, frame->width,2628frame->height, 0x200 - ((0x214 - entity->rotation) >> 6 << 6), frame->sheetID);2629else2630DrawSpriteRotated(entity->direction, XPos, YPos, -frame->pivotX, -frame->pivotY, frame->sprX, frame->sprY, frame->width,2631frame->height, (entity->rotation + 20) >> 6 << 6, frame->sheetID);2632break;26332634case ROTSTYLE_STATICFRAMES: {2635if (entity->rotation >= 0x100)2636rotation = 8 - ((532 - entity->rotation) >> 6);2637else2638rotation = (entity->rotation + 20) >> 6;2639int32 frameID = entity->frame;2640switch (rotation) {2641case 0: // 0 deg2642case 8: // 360 deg2643rotation = 0x00;2644break;26452646case 1: // 45 deg2647frameID += sprAnim->frameCount;2648if (entity->direction)2649rotation = 0;2650else2651rotation = 0x80;2652break;26532654case 2: // 90 deg2655rotation = 0x80;2656break;26572658case 3: // 135 deg2659frameID += sprAnim->frameCount;2660if (entity->direction)2661rotation = 0x80;2662else2663rotation = 0x100;2664break;26652666case 4: // 180 deg2667rotation = 0x100;2668break;26692670case 5: // 225 deg2671frameID += sprAnim->frameCount;2672if (entity->direction)2673rotation = 0x100;2674else2675rotation = 384;2676break;26772678case 6: // 270 deg2679rotation = 384;2680break;26812682case 7: // 315 deg2683frameID += sprAnim->frameCount;2684if (entity->direction)2685rotation = 384;2686else2687rotation = 0;2688break;26892690default: break;2691}26922693frame = &animFrames[sprAnim->frameListOffset + frameID];2694DrawSpriteRotated(entity->direction, XPos, YPos, -frame->pivotX, -frame->pivotY, frame->sprX, frame->sprY, frame->width, frame->height,2695rotation, frame->sheetID);2696break;2697}26982699default: break;2700}2701}27022703void RSDK::Legacy::v4::DrawFadedFace(void *v, uint32 color, uint32 fogColor, int32 alpha)2704{2705Vertex *verts = (Vertex *)v;2706if (alpha > 0xFF)2707alpha = 0xFF;27082709if (alpha < 1)2710return;27112712if (verts[0].x < 0 && verts[1].x < 0 && verts[2].x < 0 && verts[3].x < 0)2713return;27142715if (verts[0].x > GFX_LINESIZE && verts[1].x > GFX_LINESIZE && verts[2].x > GFX_LINESIZE && verts[3].x > GFX_LINESIZE)2716return;27172718if (verts[0].y < 0 && verts[1].y < 0 && verts[2].y < 0 && verts[3].y < 0)2719return;27202721if (verts[0].y > SCREEN_YSIZE && verts[1].y > SCREEN_YSIZE && verts[2].y > SCREEN_YSIZE && verts[3].y > SCREEN_YSIZE)2722return;27232724if (verts[0].x == verts[1].x && verts[1].x == verts[2].x && verts[2].x == verts[3].x)2725return;27262727if (verts[0].y == verts[1].y && verts[1].y == verts[2].y && verts[2].y == verts[3].y)2728return;27292730int32 vertexA = 0;2731int32 vertexB = 1;2732int32 vertexC = 2;2733int32 vertexD = 3;2734if (verts[1].y < verts[0].y) {2735vertexA = 1;2736vertexB = 0;2737}2738if (verts[2].y < verts[vertexA].y) {2739int32 temp = vertexA;2740vertexA = 2;2741vertexC = temp;2742}2743if (verts[3].y < verts[vertexA].y) {2744int32 temp = vertexA;2745vertexA = 3;2746vertexD = temp;2747}2748if (verts[vertexC].y < verts[vertexB].y) {2749int32 temp = vertexB;2750vertexB = vertexC;2751vertexC = temp;2752}2753if (verts[vertexD].y < verts[vertexB].y) {2754int32 temp = vertexB;2755vertexB = vertexD;2756vertexD = temp;2757}2758if (verts[vertexD].y < verts[vertexC].y) {2759int32 temp = vertexC;2760vertexC = vertexD;2761vertexD = temp;2762}27632764int32 faceTop = verts[vertexA].y;2765int32 faceBottom = verts[vertexD].y;2766if (faceTop < 0)2767faceTop = 0;2768if (faceBottom > SCREEN_YSIZE)2769faceBottom = SCREEN_YSIZE;2770for (int32 i = faceTop; i < faceBottom; ++i) {2771faceLineStart[i] = 100000;2772faceLineEnd[i] = -100000;2773}27742775ProcessScanEdge(&verts[vertexA], &verts[vertexB]);2776ProcessScanEdge(&verts[vertexA], &verts[vertexC]);2777ProcessScanEdge(&verts[vertexA], &verts[vertexD]);2778ProcessScanEdge(&verts[vertexB], &verts[vertexC]);2779ProcessScanEdge(&verts[vertexC], &verts[vertexD]);2780ProcessScanEdge(&verts[vertexB], &verts[vertexD]);27812782uint16 color16 = PACK_RGB888(((color >> 16) & 0xFF), ((color >> 8) & 0xFF), ((color >> 0) & 0xFF));2783uint16 fogColor16 = PACK_RGB888(((fogColor >> 16) & 0xFF), ((fogColor >> 8) & 0xFF), ((fogColor >> 0) & 0xFF));27842785uint16 *frameBuffer = ¤tScreen->frameBuffer[GFX_LINESIZE * faceTop];2786uint16 *fbufferBlend = &blendLookupTable[0x20 * (0xFF - alpha)];2787uint16 *pixelBlend = &blendLookupTable[0x20 * alpha];27882789while (faceTop < faceBottom) {2790int32 startX = faceLineStart[faceTop];2791int32 endX = faceLineEnd[faceTop];2792if (startX >= GFX_LINESIZE || endX <= 0) {2793frameBuffer += GFX_LINESIZE;2794}2795else {2796if (startX < 0)2797startX = 0;2798if (endX > GFX_LINESIZE_MINUSONE)2799endX = GFX_LINESIZE_MINUSONE;28002801uint16 *frameBufferPtr = &frameBuffer[startX];2802frameBuffer += GFX_LINESIZE;2803int32 vertexwidth = endX - startX + 1;2804while (vertexwidth--) {2805int32 R = (fbufferBlend[(fogColor16 & 0xF800) >> 11] + pixelBlend[(color16 & 0xF800) >> 11]) << 11;2806int32 G = (fbufferBlend[(fogColor16 & 0x7E0) >> 6] + pixelBlend[(color16 & 0x7E0) >> 6]) << 6;2807int32 B = fbufferBlend[fogColor16 & 0x1F] + pixelBlend[color16 & 0x1F];28082809*frameBufferPtr = R | G | B;2810++frameBufferPtr;2811}2812}28132814++faceTop;2815}2816}2817void RSDK::Legacy::v4::DrawTexturedFaceBlended(void *v, uint8 sheetID)2818{2819Vertex *verts = (Vertex *)v;2820if (verts[0].x < 0 && verts[1].x < 0 && verts[2].x < 0 && verts[3].x < 0)2821return;28222823if (verts[0].x > GFX_LINESIZE && verts[1].x > GFX_LINESIZE && verts[2].x > GFX_LINESIZE && verts[3].x > GFX_LINESIZE)2824return;28252826if (verts[0].y < 0 && verts[1].y < 0 && verts[2].y < 0 && verts[3].y < 0)2827return;28282829if (verts[0].y > SCREEN_YSIZE && verts[1].y > SCREEN_YSIZE && verts[2].y > SCREEN_YSIZE && verts[3].y > SCREEN_YSIZE)2830return;28312832if (verts[0].x == verts[1].x && verts[1].x == verts[2].x && verts[2].x == verts[3].x)2833return;28342835if (verts[0].y == verts[1].y && verts[1].y == verts[2].y && verts[2].y == verts[3].y)2836return;28372838int32 vertexA = 0;2839int32 vertexB = 1;2840int32 vertexC = 2;2841int32 vertexD = 3;2842if (verts[1].y < verts[0].y) {2843vertexA = 1;2844vertexB = 0;2845}2846if (verts[2].y < verts[vertexA].y) {2847int32 temp = vertexA;2848vertexA = 2;2849vertexC = temp;2850}2851if (verts[3].y < verts[vertexA].y) {2852int32 temp = vertexA;2853vertexA = 3;2854vertexD = temp;2855}2856if (verts[vertexC].y < verts[vertexB].y) {2857int32 temp = vertexB;2858vertexB = vertexC;2859vertexC = temp;2860}2861if (verts[vertexD].y < verts[vertexB].y) {2862int32 temp = vertexB;2863vertexB = vertexD;2864vertexD = temp;2865}2866if (verts[vertexD].y < verts[vertexC].y) {2867int32 temp = vertexC;2868vertexC = vertexD;2869vertexD = temp;2870}28712872int32 faceTop = verts[vertexA].y;2873int32 faceBottom = verts[vertexD].y;2874if (faceTop < 0)2875faceTop = 0;2876if (faceBottom > SCREEN_YSIZE)2877faceBottom = SCREEN_YSIZE;2878for (int32 i = faceTop; i < faceBottom; ++i) {2879faceLineStart[i] = 100000;2880faceLineEnd[i] = -100000;2881}28822883ProcessScanEdgeUV(&verts[vertexA], &verts[vertexB]);2884ProcessScanEdgeUV(&verts[vertexA], &verts[vertexC]);2885ProcessScanEdgeUV(&verts[vertexA], &verts[vertexD]);2886ProcessScanEdgeUV(&verts[vertexB], &verts[vertexC]);2887ProcessScanEdgeUV(&verts[vertexC], &verts[vertexD]);2888ProcessScanEdgeUV(&verts[vertexB], &verts[vertexD]);28892890uint16 *frameBuffer = ¤tScreen->frameBuffer[GFX_LINESIZE * faceTop];2891uint8 *pixels = &graphicData[gfxSurface[sheetID].dataPosition];2892int32 shiftwidth = gfxSurface[sheetID].widthShift;2893uint8 *lineBuffer = &gfxLineBuffer[faceTop];2894while (faceTop < faceBottom) {2895activePalette = fullPalette[*lineBuffer];2896lineBuffer++;28972898int32 startX = faceLineStart[faceTop];2899int32 endX = faceLineEnd[faceTop];2900int32 UPos = faceLineStartU[faceTop];2901int32 VPos = faceLineStartV[faceTop];29022903if (startX >= GFX_LINESIZE || endX <= 0) {2904frameBuffer += GFX_LINESIZE;2905}2906else {2907int32 posDifference = endX - startX;2908int32 bufferedUPos = 0;2909int32 bufferedVPos = 0;2910if (endX == startX) {2911bufferedUPos = 0;2912bufferedVPos = 0;2913}2914else {2915bufferedUPos = (faceLineEndU[faceTop] - UPos) / posDifference;2916bufferedVPos = (faceLineEndV[faceTop] - VPos) / posDifference;2917}29182919if (endX > GFX_LINESIZE_MINUSONE)2920posDifference = GFX_LINESIZE_MINUSONE - startX;29212922if (startX < 0) {2923posDifference += startX;2924UPos -= startX * bufferedUPos;2925VPos -= startX * bufferedVPos;2926startX = 0;2927}29282929uint16 *framebufferPtr = &frameBuffer[startX];2930frameBuffer += GFX_LINESIZE;2931int32 counter = posDifference;2932while (counter--) {2933if (UPos < 0)2934UPos = 0;2935if (VPos < 0)2936VPos = 0;2937uint16 index = pixels[(VPos >> 16 << shiftwidth) + (UPos >> 16)];2938if (index > 0)2939*framebufferPtr = ((activePalette[index] & 0xF7BC) >> 1) + ((*framebufferPtr & 0xF7BC) >> 1);2940framebufferPtr++;2941UPos += bufferedUPos;2942VPos += bufferedVPos;2943}2944}2945++faceTop;2946}2947}29482949void RSDK::Legacy::v3::DrawObjectAnimation(void *objScr, void *ent, int32 XPos, int32 YPos)2950{2951ObjectScript *objectScript = (ObjectScript *)objScr;2952Entity *entity = (Entity *)ent;2953SpriteAnimation *sprAnim = &animationList[objectScript->animFile->aniListOffset + entity->animation];2954SpriteFrame *frame = &animFrames[sprAnim->frameListOffset + entity->frame];2955int32 rotation = 0;29562957switch (sprAnim->rotationStyle) {2958case ROTSTYLE_NONE:2959switch (entity->direction) {2960case FLIP_NONE:2961DrawSpriteFlipped(frame->pivotX + XPos, frame->pivotY + YPos, frame->width, frame->height, frame->sprX, frame->sprY, FLIP_NONE,2962frame->sheetID);2963break;29642965case FLIP_X:2966DrawSpriteFlipped(XPos - frame->width - frame->pivotX, frame->pivotY + YPos, frame->width, frame->height, frame->sprX,2967frame->sprY, FLIP_X, frame->sheetID);2968break;2969case FLIP_Y:29702971DrawSpriteFlipped(frame->pivotX + XPos, YPos - frame->height - frame->pivotY, frame->width, frame->height, frame->sprX,2972frame->sprY, FLIP_Y, frame->sheetID);2973break;29742975case FLIP_XY:2976DrawSpriteFlipped(XPos - frame->width - frame->pivotX, YPos - frame->height - frame->pivotY, frame->width, frame->height,2977frame->sprX, frame->sprY, FLIP_XY, frame->sheetID);2978break;29792980default: break;2981}2982break;29832984case ROTSTYLE_FULL:2985DrawSpriteRotated(entity->direction, XPos, YPos, -frame->pivotX, -frame->pivotY, frame->sprX, frame->sprY, frame->width, frame->height,2986entity->rotation, frame->sheetID);2987break;29882989case ROTSTYLE_45DEG:2990if (entity->rotation >= 0x100)2991DrawSpriteRotated(entity->direction, XPos, YPos, -frame->pivotX, -frame->pivotY, frame->sprX, frame->sprY, frame->width,2992frame->height, 0x200 - ((0x214 - entity->rotation) >> 6 << 6), frame->sheetID);2993else2994DrawSpriteRotated(entity->direction, XPos, YPos, -frame->pivotX, -frame->pivotY, frame->sprX, frame->sprY, frame->width,2995frame->height, (entity->rotation + 20) >> 6 << 6, frame->sheetID);2996break;29972998case ROTSTYLE_STATICFRAMES: {2999if (entity->rotation >= 0x100)3000rotation = 8 - ((532 - entity->rotation) >> 6);3001else3002rotation = (entity->rotation + 20) >> 6;3003int32 frameID = entity->frame;3004switch (rotation) {3005case 0: // 0 deg3006case 8: // 360 deg3007rotation = 0x00;3008break;30093010case 1: // 45 deg3011frameID += sprAnim->frameCount;3012if (entity->direction)3013rotation = 0;3014else3015rotation = 0x80;3016break;30173018case 2: // 90 deg3019rotation = 0x80;3020break;30213022case 3: // 135 deg3023frameID += sprAnim->frameCount;3024if (entity->direction)3025rotation = 0x80;3026else3027rotation = 0x100;3028break;30293030case 4: // 180 deg3031rotation = 0x100;3032break;30333034case 5: // 225 deg3035frameID += sprAnim->frameCount;3036if (entity->direction)3037rotation = 0x100;3038else3039rotation = 384;3040break;30413042case 6: // 270 deg3043rotation = 384;3044break;30453046case 7: // 315 deg3047frameID += sprAnim->frameCount;3048if (entity->direction)3049rotation = 384;3050else3051rotation = 0;3052break;30533054default: break;3055}30563057frame = &animFrames[sprAnim->frameListOffset + frameID];3058DrawSpriteRotated(entity->direction, XPos, YPos, -frame->pivotX, -frame->pivotY, frame->sprX, frame->sprY, frame->width, frame->height,3059rotation, frame->sheetID);3060break;3061}30623063default: break;3064}3065}30663067void RSDK::Legacy::DrawTextMenuEntry(void *menu, int32 rowID, int32 XPos, int32 YPos, int32 textHighlight)3068{3069TextMenu *tMenu = (TextMenu *)menu;3070int32 id = tMenu->entryStart[rowID];3071for (int32 i = 0; i < tMenu->entrySize[rowID]; ++i) {3072DrawSprite(XPos + (i << 3) - (((tMenu->entrySize[rowID] % 2) & (tMenu->alignment == 2)) * 4), YPos, 8, 8, ((tMenu->textData[id] & 0xF) << 3),3073((tMenu->textData[id] >> 4) << 3) + textHighlight, textMenuSurfaceNo);3074id++;3075}3076}3077void RSDK::Legacy::DrawStageTextEntry(void *menu, int32 rowID, int32 XPos, int32 YPos, int32 textHighlight)3078{3079TextMenu *tMenu = (TextMenu *)menu;3080int32 id = tMenu->entryStart[rowID];3081for (int32 i = 0; i < tMenu->entrySize[rowID]; ++i) {3082if (i == tMenu->entrySize[rowID] - 1) {3083DrawSprite(XPos + (i << 3), YPos, 8, 8, ((tMenu->textData[id] & 0xF) << 3), ((tMenu->textData[id] >> 4) << 3), textMenuSurfaceNo);3084}3085else {3086DrawSprite(XPos + (i << 3), YPos, 8, 8, ((tMenu->textData[id] & 0xF) << 3), ((tMenu->textData[id] >> 4) << 3) + textHighlight,3087textMenuSurfaceNo);3088}3089id++;3090}3091}3092void RSDK::Legacy::DrawBlendedTextMenuEntry(void *menu, int32 rowID, int32 XPos, int32 YPos, int32 textHighlight)3093{3094TextMenu *tMenu = (TextMenu *)menu;3095int32 id = tMenu->entryStart[rowID];3096for (int32 i = 0; i < tMenu->entrySize[rowID]; ++i) {3097DrawBlendedSprite(XPos + (i << 3), YPos, 8, 8, ((tMenu->textData[id] & 0xF) << 3), ((tMenu->textData[id] >> 4) << 3) + textHighlight,3098textMenuSurfaceNo);3099id++;3100}3101}3102void RSDK::Legacy::DrawTextMenu(void *menu, int32 XPos, int32 YPos)3103{3104TextMenu *tMenu = (TextMenu *)menu;3105int32 cnt = 0;31063107if (tMenu->visibleRowCount > 0) {3108cnt = (int32)(tMenu->visibleRowCount + tMenu->visibleRowOffset);3109}3110else {3111tMenu->visibleRowOffset = 0;3112cnt = (int32)tMenu->rowCount;3113}31143115if (tMenu->selectionCount == 3) {3116tMenu->selection2 = -1;3117for (int32 i = 0; i < tMenu->selection1 + 1; ++i) {3118if (tMenu->entryHighlight[i]) {3119tMenu->selection2 = i;3120}3121}3122}31233124switch (tMenu->alignment) {3125case 0:3126for (int32 i = (int32)tMenu->visibleRowOffset; i < cnt; ++i) {3127switch (tMenu->selectionCount) {3128case 1:3129if (i == tMenu->selection1)3130DrawTextMenuEntry(tMenu, i, XPos, YPos, 128);3131else3132DrawTextMenuEntry(tMenu, i, XPos, YPos, 0);3133break;31343135case 2:3136if (i == tMenu->selection1 || i == tMenu->selection2)3137DrawTextMenuEntry(tMenu, i, XPos, YPos, 128);3138else3139DrawTextMenuEntry(tMenu, i, XPos, YPos, 0);3140break;31413142case 3:3143if (i == tMenu->selection1)3144DrawTextMenuEntry(tMenu, i, XPos, YPos, 128);3145else3146DrawTextMenuEntry(tMenu, i, XPos, YPos, 0);31473148if (i == tMenu->selection2 && i != tMenu->selection1)3149DrawStageTextEntry(tMenu, i, XPos, YPos, 128);3150break;3151}3152YPos += 8;3153}3154break;31553156case 1:3157for (int32 i = (int32)tMenu->visibleRowOffset; i < cnt; ++i) {3158int32 entryX = XPos - (tMenu->entrySize[i] << 3);3159switch (tMenu->selectionCount) {3160case 1:3161if (i == tMenu->selection1)3162DrawTextMenuEntry(tMenu, i, entryX, YPos, 128);3163else3164DrawTextMenuEntry(tMenu, i, entryX, YPos, 0);3165break;31663167case 2:3168if (i == tMenu->selection1 || i == tMenu->selection2)3169DrawTextMenuEntry(tMenu, i, entryX, YPos, 128);3170else3171DrawTextMenuEntry(tMenu, i, entryX, YPos, 0);3172break;31733174case 3:3175if (i == tMenu->selection1)3176DrawTextMenuEntry(tMenu, i, entryX, YPos, 128);3177else3178DrawTextMenuEntry(tMenu, i, entryX, YPos, 0);31793180if (i == tMenu->selection2 && i != tMenu->selection1)3181DrawStageTextEntry(tMenu, i, entryX, YPos, 128);3182break;3183}3184YPos += 8;3185}3186break;31873188case 2:3189for (int32 i = (int32)tMenu->visibleRowOffset; i < cnt; ++i) {3190int32 entryX = XPos - (tMenu->entrySize[i] >> 1 << 3);3191switch (tMenu->selectionCount) {3192case 1:3193if (i == tMenu->selection1)3194DrawTextMenuEntry(tMenu, i, entryX, YPos, 128);3195else3196DrawTextMenuEntry(tMenu, i, entryX, YPos, 0);3197break;3198case 2:3199if (i == tMenu->selection1 || i == tMenu->selection2)3200DrawTextMenuEntry(tMenu, i, entryX, YPos, 128);3201else3202DrawTextMenuEntry(tMenu, i, entryX, YPos, 0);3203break;3204case 3:3205if (i == tMenu->selection1)3206DrawTextMenuEntry(tMenu, i, entryX, YPos, 128);3207else3208DrawTextMenuEntry(tMenu, i, entryX, YPos, 0);32093210if (i == tMenu->selection2 && i != tMenu->selection1)3211DrawStageTextEntry(tMenu, i, entryX, YPos, 128);3212break;3213}3214YPos += 8;3215}3216break;32173218default: break;3219}3220}322132223223