Path: blob/master/RSDKv5/RSDK/Scene/Scene.cpp
1163 views
#include "RSDK/Core/RetroEngine.hpp"12using namespace RSDK;34#if RETRO_REV0U5#include "Legacy/SceneLegacy.cpp"6#endif78uint8 RSDK::tilesetPixels[TILESET_SIZE * 4];910ScanlineInfo *RSDK::scanlines = NULL;11TileLayer RSDK::tileLayers[LAYER_COUNT];12CollisionMask RSDK::collisionMasks[CPATH_COUNT][TILE_COUNT * 4];13TileInfo RSDK::tileInfo[CPATH_COUNT][TILE_COUNT * 4];1415#if RETRO_REV0216bool32 RSDK::forceHardReset = false;17#endif18char RSDK::currentSceneFolder[0x10];19char RSDK::currentSceneID[0x10];2021SceneInfo RSDK::sceneInfo;2223void RSDK::LoadSceneFolder()24{25#if RETRO_PLATFORM == RETRO_ANDROID26ShowLoadingIcon();27#endif2829#if RETRO_USE_MOD_LOADER30// run this before the game actually unloads all the objects & scene assets31RunModCallbacks(MODCB_ONSTAGEUNLOAD, NULL);32#endif3334sceneInfo.timeCounter = 0;35sceneInfo.minutes = 0;36sceneInfo.seconds = 0;37sceneInfo.milliseconds = 0;3839// clear draw groups40for (int32 i = 0; i < DRAWGROUP_COUNT; ++i) {41drawGroups[i].entityCount = 0;42drawGroups[i].layerCount = 0;43}4445// Clear Type groups46for (int32 i = 0; i < TYPEGROUP_COUNT; ++i) {47typeGroups[i].entryCount = 0;48}4950#if RETRO_REV0251// Unload debug values52ClearViewableVariables();5354// "unload" tint table55tintLookupTable = NULL;56#endif5758// Unload TileLayers59for (int32 l = 0; l < LAYER_COUNT; ++l) {60MEM_ZERO(tileLayers[l]);61for (int32 c = 0; c < CAMERA_COUNT; ++c) tileLayers[l].drawGroup[c] = -1;62}6364SceneListInfo *list = &sceneInfo.listCategory[sceneInfo.activeCategory];65#if RETRO_REV0266if (strcmp(currentSceneFolder, sceneInfo.listData[sceneInfo.listPos].folder) == 0 && !forceHardReset) {67// Reload68DefragmentAndGarbageCollectStorage(DATASET_STG);69sceneInfo.filter = sceneInfo.listData[sceneInfo.listPos].filter;70PrintLog(PRINT_NORMAL, "Reloading Scene \"%s - %s\" with filter %d", list->name, sceneInfo.listData[sceneInfo.listPos].name,71sceneInfo.listData[sceneInfo.listPos].filter);7273#if RETRO_USE_MOD_LOADER74// reload object hooks75for (int32 h = 0; h < (int32)objectHookList.size(); ++h) {76for (int32 i = 0; i < objectClassCount; ++i) {77if (HASH_MATCH_MD5(objectClassList[i].hash, objectHookList[h].hash)) {78if (objectHookList[h].staticVars && objectClassList[i].staticVars)79*objectHookList[h].staticVars = *objectClassList[i].staticVars;80break;81}82}83}84#endif8586return;87}88#endif8990#if !RETRO_REV0291if (strcmp(currentSceneFolder, sceneInfo.listData[sceneInfo.listPos].folder) == 0) {92// Reload93DefragmentAndGarbageCollectStorage(DATASET_STG);94PrintLog(PRINT_NORMAL, "Reloading Scene \"%s - %s\"", list->name, sceneInfo.listData[sceneInfo.listPos].name);9596#if RETRO_USE_MOD_LOADER97// reload object hooks98for (int32 h = 0; h < (int32)objectHookList.size(); ++h) {99for (int32 i = 0; i < objectClassCount; ++i) {100if (HASH_MATCH_MD5(objectClassList[i].hash, objectHookList[h].hash)) {101if (objectHookList[h].staticVars && objectClassList[i].staticVars)102*objectHookList[h].staticVars = *objectClassList[i].staticVars;103break;104}105}106}107#endif108return;109}110#endif111112// Unload stage 3DScenes & models113Clear3DScenes();114115// Unload stage sprite animations116ClearSpriteAnimations();117118// Unload stage surfaces119ClearGfxSurfaces();120121// Unload stage sfx & audio channels122ClearStageSfx();123124// Unload stage objects125ClearStageObjects();126127// Clear draw groups128for (int32 l = 0; l < DRAWGROUP_COUNT; ++l) {129MEM_ZERO(drawGroups[l]);130drawGroups[l].sorted = false;131}132133// Clear stage storage134DefragmentAndGarbageCollectStorage(DATASET_STG);135DefragmentAndGarbageCollectStorage(DATASET_SFX);136137for (int32 s = 0; s < SCREEN_COUNT; ++s) {138screens[s].position.x = 0;139screens[s].position.y = 0;140}141142SceneListEntry *sceneEntry = &sceneInfo.listData[sceneInfo.listPos];143strcpy(currentSceneFolder, sceneEntry->folder);144145#if RETRO_REV02146forceHardReset = false;147sceneInfo.filter = sceneEntry->filter;148PrintLog(PRINT_NORMAL, "Loading Scene \"%s - %s\" with filter %d", list->name, sceneEntry->name, sceneEntry->filter);149#endif150151#if !RETRO_REV02152PrintLog(PRINT_NORMAL, "Loading Scene \"%s - %s\"", list->name, sceneEntry->name);153#endif154155char fullFilePath[0x40];156157// Load TileConfig158sprintf_s(fullFilePath, sizeof(fullFilePath), "Data/Stages/%s/TileConfig.bin", currentSceneFolder);159LoadTileConfig(fullFilePath);160161// Load StageConfig162sprintf_s(fullFilePath, sizeof(fullFilePath), "Data/Stages/%s/StageConfig.bin", currentSceneFolder);163164FileInfo info;165InitFileInfo(&info);166if (LoadFile(&info, fullFilePath, FMODE_RB)) {167uint32 sig = ReadInt32(&info, false);168169if (sig != RSDK_SIGNATURE_CFG) {170CloseFile(&info);171return;172}173174sceneInfo.useGlobalObjects = ReadInt8(&info);175sceneInfo.classCount = 0;176177if (sceneInfo.useGlobalObjects) {178for (int32 o = 0; o < globalObjectCount; ++o) stageObjectIDs[o] = globalObjectIDs[o];179sceneInfo.classCount = globalObjectCount;180}181else {182for (int32 o = 0; o < TYPE_DEFAULT_COUNT; ++o) stageObjectIDs[o] = globalObjectIDs[o];183184sceneInfo.classCount = TYPE_DEFAULT_COUNT;185}186187uint8 objectCount = ReadInt8(&info);188for (int32 o = 0; o < objectCount; ++o) {189ReadString(&info, textBuffer);190191RETRO_HASH_MD5(hash);192GEN_HASH_MD5_BUFFER(textBuffer, hash);193194stageObjectIDs[sceneInfo.classCount] = 0;195for (int32 id = 0; id < objectClassCount; ++id) {196if (HASH_MATCH_MD5(hash, objectClassList[id].hash)) {197stageObjectIDs[sceneInfo.classCount] = id;198sceneInfo.classCount++;199}200}201}202203for (int32 o = 0; o < sceneInfo.classCount; ++o) {204ObjectClass *objClass = &objectClassList[stageObjectIDs[o]];205if (objClass->staticVars && !*objClass->staticVars) {206AllocateStorage((void **)objClass->staticVars, objClass->staticClassSize, DATASET_STG, true);207208#if RETRO_REV0U209if (objClass->staticLoad)210objClass->staticLoad(*objClass->staticVars);211else212LoadStaticVariables((uint8 *)*objClass->staticVars, objClass->hash, sizeof(Object));213214#else215LoadStaticVariables((uint8 *)*objClass->staticVars, objClass->hash, sizeof(Object));216#endif217218#if RETRO_USE_MOD_LOADER219// even though the static load event is rev0U only, this point in the engine is "static loading"220RunModCallbacks(MODCB_ONSTATICLOAD, (void *)objClass);221#endif222223#if RETRO_USE_MOD_LOADER224for (ModInfo &mod : modList) {225if (mod.staticVars.find(objClass->hash) != mod.staticVars.end()) {226auto sVars = mod.staticVars.at(objClass->hash);227RegisterStaticVariables((void **)sVars.staticVars, sVars.name.c_str(), sVars.size);228}229}230#endif231232(*objClass->staticVars)->classID = o;233if (o >= TYPE_DEFAULT_COUNT)234(*objClass->staticVars)->active = ACTIVE_NORMAL;235}236}237238for (int32 p = 0; p < PALETTE_BANK_COUNT; ++p) {239activeStageRows[p] = ReadInt16(&info);240241for (int32 r = 0; r < 0x10; ++r) {242if ((activeStageRows[p] >> r & 1)) {243for (int32 c = 0; c < 0x10; ++c) {244uint8 red = ReadInt8(&info);245uint8 green = ReadInt8(&info);246uint8 blue = ReadInt8(&info);247stagePalette[p][(r << 4) + c] = rgb32To16_B[blue] | rgb32To16_G[green] | rgb32To16_R[red];248}249}250else {251for (int32 c = 0; c < 0x10; ++c) stagePalette[p][(r << 4) + c] = 0;252}253}254}255256uint8 sfxCount = ReadInt8(&info);257char sfxPath[0x100];258for (int32 i = 0; i < sfxCount; ++i) {259ReadString(&info, sfxPath);260uint8 maxConcurrentPlays = ReadInt8(&info);261LoadSfx(sfxPath, maxConcurrentPlays, SCOPE_STAGE);262}263264CloseFile(&info);265}266267sprintf_s(fullFilePath, sizeof(fullFilePath), "Data/Stages/%s/16x16Tiles.gif", currentSceneFolder);268LoadStageGIF(fullFilePath);269270#if RETRO_USE_MOD_LOADER271for (int32 h = 0; h < (int32)objectHookList.size(); ++h) {272for (int32 i = 0; i < objectClassCount; ++i) {273if (HASH_MATCH_MD5(objectClassList[i].hash, objectHookList[h].hash)) {274if (objectHookList[h].staticVars && objectClassList[i].staticVars)275*objectHookList[h].staticVars = *objectClassList[i].staticVars;276break;277}278}279}280#endif281}282void RSDK::LoadSceneAssets()283{284#if RETRO_PLATFORM == RETRO_ANDROID285ShowLoadingIcon();286#endif287288memset(objectEntityList, 0, ENTITY_COUNT * sizeof(EntityBase));289290SceneListEntry *sceneEntry = &sceneInfo.listData[sceneInfo.listPos];291char fullFilePath[0x40];292sprintf_s(fullFilePath, sizeof(fullFilePath), "Data/Stages/%s/Scene%s.bin", currentSceneFolder, sceneEntry->id);293294dataStorage[DATASET_TMP].usedStorage = 0;295296for (int32 s = 0; s < SCREEN_COUNT; ++s) screens[s].waterDrawPos = screens[s].size.y;297298if (screens[0].size.y > 0)299memset(gfxLineBuffer, 0, screens[0].size.y * sizeof(uint8));300301memset(tileLayers, 0, LAYER_COUNT * sizeof(TileLayer));302303// Reload palette304for (int32 b = 0; b < 8; ++b) {305for (int32 r = 0; r < 0x10; ++r) {306if ((activeGlobalRows[b] >> r & 1)) {307for (int32 c = 0; c < 0x10; ++c) fullPalette[b][(r << 4) + c] = globalPalette[b][(r << 4) + c];308}309310if ((activeStageRows[b] >> r & 1)) {311for (int32 c = 0; c < 0x10; ++c) fullPalette[b][(r << 4) + c] = stagePalette[b][(r << 4) + c];312}313}314}315316FileInfo info;317InitFileInfo(&info);318if (LoadFile(&info, fullFilePath, FMODE_RB)) {319uint32 sig = ReadInt32(&info, false);320321if (sig != RSDK_SIGNATURE_SCN) {322CloseFile(&info);323return;324}325326// Editor Metadata327328// I'm leaving this section here so that the "format" can be documented, since the official code is 3 lines and just skips it lol329330/*331uint8 unknown1 = ReadInt8(&info); // usually 3, sometimes 4, LRZ1 (old) is 2332333uint8 b = ReadInt8(&info);334uint8 g = ReadInt8(&info);335uint8 r = ReadInt8(&info);336uint8 a = ReadInt8(&info);337color backgroundColor1 = (a << 24) | (r << 16) | (g << 8) | (b << 0);338339b = ReadInt8(&info);340g = ReadInt8(&info);341r = ReadInt8(&info);342a = ReadInt8(&info);343color backgroundColor2 = (a << 24) | (r << 16) | (g << 8) | (b << 0);344345uint8 unknown2 = ReadInt8(&info); // always 1 afaik346uint8 unknown3 = ReadInt8(&info); // always 1 afaik347uint8 unknown4 = ReadInt8(&info); // always 4 afaik348uint8 unknown5 = ReadInt8(&info); // always 0 afaik349uint8 unknown6 = ReadInt8(&info); // always 1 afaik350uint8 unknown7 = ReadInt8(&info); // always 4 afaik351uint8 unknown8 = ReadInt8(&info); // always 0 afaik352353char stampName[0x20];354ReadString(&info, stampName);355356uint8 unknown9 = ReadInt8(&info); // usually 3, 4, or 5357*/358359// Skip over Metadata, since we won't be using it at all in-game360Seek_Cur(&info, 0x10);361uint8 strLen = ReadInt8(&info);362Seek_Cur(&info, strLen + 1);363364// Tile Layers365uint8 layerCount = ReadInt8(&info);366for (int32 l = 0; l < layerCount; ++l) {367TileLayer *layer = &tileLayers[l];368369// Tests in RetroED & comparing images of the RSDKv5 editor we have puts this as the most likely use for this (otherwise unused) variable370bool32 visibleInEditor = ReadInt8(&info) != 0;371(void)visibleInEditor; // unused372373ReadString(&info, textBuffer);374GEN_HASH_MD5_BUFFER(textBuffer, layer->name);375376layer->type = ReadInt8(&info);377layer->drawGroup[0] = ReadInt8(&info);378for (int32 s = 1; s < CAMERA_COUNT; ++s) layer->drawGroup[s] = layer->drawGroup[0];379380layer->xsize = ReadInt16(&info);381int32 shift = 1;382int32 shift2 = 1;383int32 val = 0;384do {385shift = shift2;386val = 1 << shift2++;387} while (val < layer->xsize);388layer->widthShift = shift;389390layer->ysize = ReadInt16(&info);391shift = 1;392shift2 = 1;393val = 0;394do {395shift = shift2;396val = 1 << shift2++;397} while (val < layer->ysize);398layer->heightShift = shift;399400layer->parallaxFactor = ReadInt16(&info);401layer->scrollSpeed = ReadInt16(&info) << 8;402layer->scrollPos = 0;403404layer->layout = NULL;405if (layer->xsize || layer->ysize) {406AllocateStorage((void **)&layer->layout, sizeof(uint16) * (1UL << layer->widthShift) * (1UL << layer->heightShift), DATASET_STG, true);407memset(layer->layout, 0xFF, sizeof(uint16) * (1UL << layer->widthShift) * (1UL << layer->heightShift));408}409410int32 size = layer->xsize;411if (size <= layer->ysize)412size = layer->ysize;413AllocateStorage((void **)&layer->lineScroll, TILE_SIZE * size, DATASET_STG, true);414415layer->scrollInfoCount = ReadInt16(&info);416for (int32 s = 0; s < layer->scrollInfoCount; ++s) {417layer->scrollInfo[s].parallaxFactor = ReadInt16(&info);418layer->scrollInfo[s].scrollSpeed = ReadInt16(&info) << 8;419layer->scrollInfo[s].scrollPos = 0;420layer->scrollInfo[s].tilePos = 0;421layer->scrollInfo[s].deform = ReadInt8(&info);422423// this isn't used anywhere in-engine, and is never set in the files. so as you might expect, no one knows what it is for!424layer->scrollInfo[s].unknown = ReadInt8(&info);425}426427uint8 *scrollIndexes = NULL;428ReadCompressed(&info, (uint8 **)&scrollIndexes);429memcpy(layer->lineScroll, scrollIndexes, TILE_SIZE * size * sizeof(uint8));430#if !RETRO_USE_ORIGINAL_CODE431RemoveStorageEntry((void **)&scrollIndexes);432#endif433scrollIndexes = NULL;434435uint8 *tileLayout = NULL;436ReadCompressed(&info, (uint8 **)&tileLayout);437438int32 id = 0;439for (int32 y = 0; y < layer->ysize; ++y) {440for (int32 x = 0; x < layer->xsize; ++x) {441layer->layout[x + (y << layer->widthShift)] = (tileLayout[id + 1] << 8) + tileLayout[id + 0];442id += 2;443}444}445446#if !RETRO_USE_ORIGINAL_CODE447RemoveStorageEntry((void **)&tileLayout);448#endif449tileLayout = NULL;450}451452// Objects453uint8 objectCount = ReadInt8(&info);454editableVarList = NULL;455AllocateStorage((void **)&editableVarList, sizeof(EditableVarInfo) * EDITABLEVAR_COUNT, DATASET_TMP, false);456457#if RETRO_REV02458EntityBase *tempEntityList = NULL;459AllocateStorage((void **)&tempEntityList, SCENEENTITY_COUNT * sizeof(EntityBase), DATASET_TMP, true);460#endif461462for (int32 i = 0; i < objectCount; ++i) {463RETRO_HASH_MD5(objHash);464objHash[0] = ReadInt32(&info, false);465objHash[1] = ReadInt32(&info, false);466objHash[2] = ReadInt32(&info, false);467objHash[3] = ReadInt32(&info, false);468469int32 classID = 0;470for (int32 o = 0; o < sceneInfo.classCount; ++o) {471if (HASH_MATCH_MD5(objHash, objectClassList[stageObjectIDs[o]].hash)) {472classID = o;473break;474}475}476477#if !RETRO_USE_ORIGINAL_CODE478if (!classID && i >= TYPE_DEFAULT_COUNT)479PrintLog(PRINT_NORMAL, "Object Class %d is unimplemented!", i);480#endif481482ObjectClass *objectClass = &objectClassList[stageObjectIDs[classID]];483484uint8 varCount = ReadInt8(&info);485EditableVarInfo *varList = NULL;486AllocateStorage((void **)&varList, sizeof(EditableVarInfo) * varCount, DATASET_TMP, false);487editableVarCount = 0;488if (classID) {489#if RETRO_REV02490SetEditableVar(VAR_UINT8, "filter", classID, offsetof(Entity, filter));491#endif492493#if RETRO_USE_MOD_LOADER494currentObjectID = classID;495#endif496497if (objectClass->serialize)498objectClass->serialize();499}500501for (int32 e = 1; e < varCount; ++e) {502RETRO_HASH_MD5(varHash);503varHash[0] = ReadInt32(&info, false);504varHash[1] = ReadInt32(&info, false);505varHash[2] = ReadInt32(&info, false);506varHash[3] = ReadInt32(&info, false);507508int32 varID = 0;509MEM_ZERO(varList[e]);510for (int32 v = 0; v < editableVarCount; ++v) {511if (HASH_MATCH_MD5(varHash, editableVarList[v].hash)) {512varID = v;513HASH_COPY_MD5(varList[e].hash, editableVarList[v].hash);514varList[e].offset = editableVarList[v].offset;515varList[e].active = true;516break;517}518}519520editableVarList[varID].type = varList[e].type = ReadInt8(&info);521}522523uint16 entityCount = ReadInt16(&info);524for (int32 e = 0; e < entityCount; ++e) {525uint16 slotID = ReadInt16(&info);526527EntityBase *entity = NULL;528529#if RETRO_REV02530if (slotID < SCENEENTITY_COUNT)531entity = &objectEntityList[slotID + RESERVE_ENTITY_COUNT];532else533entity = &tempEntityList[slotID - SCENEENTITY_COUNT];534#else535entity = &objectEntityList[slotID + RESERVE_ENTITY_COUNT];536#endif537538entity->classID = classID;539#if RETRO_REV02540entity->filter = 0xFF;541#endif542entity->position.x = ReadInt32(&info, false);543entity->position.y = ReadInt32(&info, false);544545uint8 *entityBuffer = (uint8 *)entity;546547uint8 tempBuffer[0x10];548for (int32 v = 1; v < varCount; ++v) {549switch (varList[v].type) {550case VAR_UINT8:551case VAR_INT8:552if (varList[v].active)553ReadBytes(&info, &entityBuffer[varList[v].offset], sizeof(int8));554else555ReadBytes(&info, tempBuffer, sizeof(int8));556break;557558case VAR_UINT16:559case VAR_INT16:560if (varList[v].active)561#if !RETRO_USE_ORIGINAL_CODE562*(int16 *)&entityBuffer[varList[v].offset] = ReadInt16(&info);563#else564// This only works as intended on little-endian CPUs.565ReadBytes(&info, &entityBuffer[varList[v].offset], sizeof(int16));566#endif567else568ReadBytes(&info, tempBuffer, sizeof(int16));569break;570571case VAR_UINT32:572case VAR_INT32:573if (varList[v].active)574#if !RETRO_USE_ORIGINAL_CODE575*(int32 *)&entityBuffer[varList[v].offset] = ReadInt32(&info, false);576#else577// This only works as intended on little-endian CPUs.578ReadBytes(&info, &entityBuffer[varList[v].offset], sizeof(int32));579#endif580else581ReadBytes(&info, tempBuffer, sizeof(int32));582break;583584// not entirely sure on specifics here, should always be sizeof(int32) but it having a unique type implies it isn't always585case VAR_ENUM:586if (varList[v].active)587#if !RETRO_USE_ORIGINAL_CODE588*(int32 *)&entityBuffer[varList[v].offset] = ReadInt32(&info, false);589#else590// This only works as intended on little-endian CPUs.591ReadBytes(&info, &entityBuffer[varList[v].offset], sizeof(int32));592#endif593else594ReadBytes(&info, tempBuffer, sizeof(int32));595break;596597case VAR_BOOL:598if (varList[v].active)599#if !RETRO_USE_ORIGINAL_CODE600*(bool32 *)&entityBuffer[varList[v].offset] = (bool32)ReadInt32(&info, false);601#else602// This only works as intended on little-endian CPUs.603ReadBytes(&info, &entityBuffer[varList[v].offset], sizeof(bool32));604#endif605else606ReadBytes(&info, tempBuffer, sizeof(bool32));607break;608609case VAR_STRING:610if (varList[v].active) {611String *string = (String *)&entityBuffer[varList[v].offset];612uint16 len = ReadInt16(&info);613614InitString(string, "", len);615for (string->length = 0; string->length < len; ++string->length) string->chars[string->length] = ReadInt16(&info);616}617else {618Seek_Cur(&info, ReadInt16(&info) * sizeof(uint16));619}620break;621622case VAR_VECTOR2:623if (varList[v].active) {624#if !RETRO_USE_ORIGINAL_CODE625*(int32 *)&entityBuffer[varList[v].offset] = ReadInt32(&info, false);626*(int32 *)&entityBuffer[varList[v].offset + sizeof(int32)] = ReadInt32(&info, false);627#else628// This only works as intended on little-endian CPUs.629ReadBytes(&info, &entityBuffer[varList[v].offset], sizeof(int32));630ReadBytes(&info, &entityBuffer[varList[v].offset + sizeof(int32)], sizeof(int32));631#endif632}633else {634ReadBytes(&info, tempBuffer, sizeof(int32)); // x635ReadBytes(&info, tempBuffer, sizeof(int32)); // y636}637break;638639// Never used in mania so we don't know for sure, but it's our best guess!640case VAR_FLOAT:641if (varList[v].active)642#if !RETRO_USE_ORIGINAL_CODE643*(float *)&entityBuffer[varList[v].offset] = ReadSingle(&info);644#else645// This only works as intended on little-endian CPUs.646ReadBytes(&info, &entityBuffer[varList[v].offset], sizeof(float));647#endif648else649ReadBytes(&info, tempBuffer, sizeof(float));650break;651652case VAR_COLOR:653if (varList[v].active)654#if !RETRO_USE_ORIGINAL_CODE655*(color *)&entityBuffer[varList[v].offset] = ReadInt32(&info, false);656#else657// This only works as intended on little-endian CPUs.658ReadBytes(&info, &entityBuffer[varList[v].offset], sizeof(color));659#endif660else661ReadBytes(&info, tempBuffer, sizeof(color));662break;663}664}665}666667#if !RETRO_USE_ORIGINAL_CODE668RemoveStorageEntry((void **)&varList);669varList = NULL;670#endif671}672673#if RETRO_REV02674// handle filter and stuff675EntityBase *entity = &objectEntityList[RESERVE_ENTITY_COUNT];676int32 activeSlot = RESERVE_ENTITY_COUNT;677for (int32 i = RESERVE_ENTITY_COUNT; i < SCENEENTITY_COUNT + RESERVE_ENTITY_COUNT; ++i) {678if (sceneInfo.filter & entity->filter) {679if (i != activeSlot) {680memcpy(&objectEntityList[activeSlot], entity, sizeof(EntityBase));681memset(entity, 0, sizeof(EntityBase));682}683684++activeSlot;685}686else {687memset(entity, 0, sizeof(EntityBase));688}689690entity++;691}692693for (int32 i = 0; i < SCENEENTITY_COUNT; ++i) {694if (sceneInfo.filter & tempEntityList[i].filter)695memcpy(&objectEntityList[activeSlot++], &tempEntityList[i], sizeof(EntityBase));696697if (activeSlot >= SCENEENTITY_COUNT + RESERVE_ENTITY_COUNT)698break;699}700701#if !RETRO_USE_ORIGINAL_CODE702RemoveStorageEntry((void **)&tempEntityList);703#endif704tempEntityList = NULL;705#endif706707#if !RETRO_USE_ORIGINAL_CODE708RemoveStorageEntry((void **)&editableVarList);709#endif710editableVarList = NULL;711712CloseFile(&info);713}714#if RETRO_USE_MOD_LOADER715LoadGameXML(true); // override the stage palette *somewhere* idfk716#endif717}718void RSDK::LoadTileConfig(char *filepath)719{720FileInfo info;721InitFileInfo(&info);722723if (LoadFile(&info, filepath, FMODE_RB)) {724uint32 sig = ReadInt32(&info, false);725if (sig != RSDK_SIGNATURE_TIL) {726CloseFile(&info);727return;728}729730uint8 *buffer = NULL;731ReadCompressed(&info, &buffer);732733int32 bufPos = 0;734for (int32 p = 0; p < CPATH_COUNT; ++p) {735// No Flip/Stored in file736for (int32 t = 0; t < TILE_COUNT; ++t) {737uint8 maskHeights[0x10];738uint8 maskActive[0x10];739740memcpy(maskHeights, buffer + bufPos, TILE_SIZE * sizeof(uint8));741bufPos += TILE_SIZE;742memcpy(maskActive, buffer + bufPos, TILE_SIZE * sizeof(uint8));743bufPos += TILE_SIZE;744745bool32 yFlip = buffer[bufPos++];746tileInfo[p][t].floorAngle = buffer[bufPos++];747tileInfo[p][t].lWallAngle = buffer[bufPos++];748tileInfo[p][t].rWallAngle = buffer[bufPos++];749tileInfo[p][t].roofAngle = buffer[bufPos++];750tileInfo[p][t].flag = buffer[bufPos++];751752if (yFlip) {753for (int32 c = 0; c < TILE_SIZE; c++) {754if (maskActive[c]) {755collisionMasks[p][t].floorMasks[c] = 0x00;756collisionMasks[p][t].roofMasks[c] = maskHeights[c];757}758else {759collisionMasks[p][t].floorMasks[c] = 0xFF;760collisionMasks[p][t].roofMasks[c] = 0xFF;761}762}763764// LWall rotations765for (int32 c = 0; c < TILE_SIZE; ++c) {766int32 h = 0;767while (true) {768if (h == TILE_SIZE) {769collisionMasks[p][t].lWallMasks[c] = 0xFF;770break;771}772773uint8 m = collisionMasks[p][t].roofMasks[h];774if (m != 0xFF && c <= m) {775collisionMasks[p][t].lWallMasks[c] = h;776break;777}778else {779++h;780if (h <= -1)781break;782}783}784}785786// RWall rotations787for (int32 c = 0; c < TILE_SIZE; ++c) {788int32 h = TILE_SIZE - 1;789while (true) {790if (h == -1) {791collisionMasks[p][t].rWallMasks[c] = 0xFF;792break;793}794795uint8 m = collisionMasks[p][t].roofMasks[h];796if (m != 0xFF && c <= m) {797collisionMasks[p][t].rWallMasks[c] = h;798break;799}800else {801--h;802if (h >= TILE_SIZE)803break;804}805}806}807}808else // Regular Tile809{810// Collision heights811for (int32 c = 0; c < TILE_SIZE; ++c) {812if (maskActive[c]) {813collisionMasks[p][t].floorMasks[c] = maskHeights[c];814collisionMasks[p][t].roofMasks[c] = 0x0F;815}816else {817collisionMasks[p][t].floorMasks[c] = 0xFF;818collisionMasks[p][t].roofMasks[c] = 0xFF;819}820}821822// LWall rotations823for (int32 c = 0; c < TILE_SIZE; ++c) {824int32 h = 0;825while (true) {826if (h == TILE_SIZE) {827collisionMasks[p][t].lWallMasks[c] = 0xFF;828break;829}830831uint8 m = collisionMasks[p][t].floorMasks[h];832if (m != 0xFF && c >= m) {833collisionMasks[p][t].lWallMasks[c] = h;834break;835}836else {837++h;838if (h <= -1)839break;840}841}842}843844// RWall rotations845for (int32 c = 0; c < TILE_SIZE; ++c) {846int32 h = TILE_SIZE - 1;847while (true) {848if (h == -1) {849collisionMasks[p][t].rWallMasks[c] = 0xFF;850break;851}852853uint8 m = collisionMasks[p][t].floorMasks[h];854if (m != 0xFF && c >= m) {855collisionMasks[p][t].rWallMasks[c] = h;856break;857}858else {859--h;860if (h >= TILE_SIZE)861break;862}863}864}865}866}867868// FlipX869for (int32 t = 0; t < TILE_COUNT; ++t) {870int32 off = (FLIP_X * TILE_COUNT);871tileInfo[p][t + off].flag = tileInfo[p][t].flag;872tileInfo[p][t + off].floorAngle = -tileInfo[p][t].floorAngle;873tileInfo[p][t + off].lWallAngle = -tileInfo[p][t].rWallAngle;874tileInfo[p][t + off].roofAngle = -tileInfo[p][t].roofAngle;875tileInfo[p][t + off].rWallAngle = -tileInfo[p][t].lWallAngle;876877for (int32 c = 0; c < TILE_SIZE; ++c) {878int32 h = collisionMasks[p][t].lWallMasks[c];879if (h == 0xFF)880collisionMasks[p][t + off].rWallMasks[c] = 0xFF;881else882collisionMasks[p][t + off].rWallMasks[c] = 0xF - h;883884h = collisionMasks[p][t].rWallMasks[c];885if (h == 0xFF)886collisionMasks[p][t + off].lWallMasks[c] = 0xFF;887else888collisionMasks[p][t + off].lWallMasks[c] = 0xF - h;889890collisionMasks[p][t + off].floorMasks[c] = collisionMasks[p][t].floorMasks[0xF - c];891collisionMasks[p][t + off].roofMasks[c] = collisionMasks[p][t].roofMasks[0xF - c];892}893}894895// FlipY896for (int32 t = 0; t < TILE_COUNT; ++t) {897int32 off = (FLIP_Y * TILE_COUNT);898tileInfo[p][t + off].flag = tileInfo[p][t].flag;899tileInfo[p][t + off].floorAngle = -0x80 - tileInfo[p][t].roofAngle;900tileInfo[p][t + off].lWallAngle = -0x80 - tileInfo[p][t].lWallAngle;901tileInfo[p][t + off].roofAngle = -0x80 - tileInfo[p][t].floorAngle;902tileInfo[p][t + off].rWallAngle = -0x80 - tileInfo[p][t].rWallAngle;903904for (int32 c = 0; c < TILE_SIZE; ++c) {905int32 h = collisionMasks[p][t].roofMasks[c];906if (h == 0xFF)907collisionMasks[p][t + off].floorMasks[c] = 0xFF;908else909collisionMasks[p][t + off].floorMasks[c] = 0xF - h;910911h = collisionMasks[p][t].floorMasks[c];912if (h == 0xFF)913collisionMasks[p][t + off].roofMasks[c] = 0xFF;914else915collisionMasks[p][t + off].roofMasks[c] = 0xF - h;916917collisionMasks[p][t + off].lWallMasks[c] = collisionMasks[p][t].lWallMasks[0xF - c];918collisionMasks[p][t + off].rWallMasks[c] = collisionMasks[p][t].rWallMasks[0xF - c];919}920}921922// FlipXY923for (int32 t = 0; t < TILE_COUNT; ++t) {924int32 off = (FLIP_XY * TILE_COUNT);925int32 offY = (FLIP_Y * TILE_COUNT);926tileInfo[p][t + off].flag = tileInfo[p][t + offY].flag;927tileInfo[p][t + off].floorAngle = -tileInfo[p][t + offY].floorAngle;928tileInfo[p][t + off].lWallAngle = -tileInfo[p][t + offY].rWallAngle;929tileInfo[p][t + off].roofAngle = -tileInfo[p][t + offY].roofAngle;930tileInfo[p][t + off].rWallAngle = -tileInfo[p][t + offY].lWallAngle;931932for (int32 c = 0; c < TILE_SIZE; ++c) {933int32 h = collisionMasks[p][t + offY].lWallMasks[c];934if (h == 0xFF)935collisionMasks[p][t + off].rWallMasks[c] = 0xFF;936else937collisionMasks[p][t + off].rWallMasks[c] = 0xF - h;938939h = collisionMasks[p][t + offY].rWallMasks[c];940if (h == 0xFF)941collisionMasks[p][t + off].lWallMasks[c] = 0xFF;942else943collisionMasks[p][t + off].lWallMasks[c] = 0xF - h;944945collisionMasks[p][t + off].floorMasks[c] = collisionMasks[p][t + offY].floorMasks[0xF - c];946collisionMasks[p][t + off].roofMasks[c] = collisionMasks[p][t + offY].roofMasks[0xF - c];947}948}949}950951#if !RETRO_USE_ORIGINAL_CODE952RemoveStorageEntry((void **)&buffer);953buffer = NULL;954#endif955CloseFile(&info);956}957}958void RSDK::LoadStageGIF(char *filepath)959{960ImageGIF tileset;961962if (tileset.Load(filepath, true) && tileset.width == TILE_SIZE && tileset.height <= TILE_COUNT * TILE_SIZE) {963tileset.pixels = tilesetPixels;964tileset.Load(NULL, false);965966for (int32 r = 0; r < 0x10; ++r) {967// only overwrite inactive rows968if (!(activeStageRows[0] >> r & 1) && !(activeGlobalRows[0] >> r & 1)) {969for (int32 c = 0; c < 0x10; ++c) {970uint8 red = (tileset.palette[(r << 4) + c] >> 0x10);971uint8 green = (tileset.palette[(r << 4) + c] >> 0x08);972uint8 blue = (tileset.palette[(r << 4) + c] >> 0x00);973fullPalette[0][(r << 4) + c] = rgb32To16_B[blue] | rgb32To16_G[green] | rgb32To16_R[red];974}975}976}977978// Flip X979uint8 *srcPixels = tilesetPixels;980uint8 *dstPixels = &tilesetPixels[(FLIP_X * TILESET_SIZE) + (TILE_SIZE - 1)];981for (int32 t = 0; t < 0x400 * TILE_SIZE; ++t) {982for (int32 r = 0; r < TILE_SIZE; ++r) {983*dstPixels-- = *srcPixels++;984}985986dstPixels += (TILE_SIZE * 2);987}988989// Flip Y990srcPixels = tilesetPixels;991for (int32 t = 0; t < 0x400; ++t) {992dstPixels = &tilesetPixels[(FLIP_Y * TILESET_SIZE) + (t * TILE_DATASIZE) + (TILE_DATASIZE - TILE_SIZE)];993for (int32 y = 0; y < TILE_SIZE; ++y) {994for (int32 x = 0; x < TILE_SIZE; ++x) {995*dstPixels++ = *srcPixels++;996}997998dstPixels -= (TILE_SIZE * 2);999}1000}10011002// Flip XY1003srcPixels = &tilesetPixels[(FLIP_Y * TILESET_SIZE)];1004dstPixels = &tilesetPixels[(FLIP_XY * TILESET_SIZE) + (TILE_SIZE - 1)];1005for (int32 t = 0; t < 0x400 * TILE_SIZE; ++t) {1006for (int32 r = 0; r < TILE_SIZE; ++r) {1007*dstPixels-- = *srcPixels++;1008}10091010dstPixels += (TILE_SIZE * 2);1011}10121013#if RETRO_USE_ORIGINAL_CODE1014tileset.palette = NULL;1015tileset.decoder = NULL;1016#endif1017tileset.pixels = NULL;1018}1019}10201021void RSDK::ProcessParallaxAutoScroll()1022{1023for (int32 l = 0; l < LAYER_COUNT; ++l) {1024TileLayer *layer = &tileLayers[l];10251026if (layer->layout) {1027layer->scrollPos += layer->scrollSpeed;10281029for (int32 s = 0; s < layer->scrollInfoCount; ++s) layer->scrollInfo[s].scrollPos += layer->scrollInfo[s].scrollSpeed;1030}1031}1032}1033void RSDK::ProcessParallax(TileLayer *layer)1034{1035if (!layer->xsize || !layer->ysize)1036return;10371038int32 pixelWidth = TILE_SIZE * layer->xsize;1039int32 pixelHeight = TILE_SIZE * layer->ysize;1040ScanlineInfo *scanline = scanlines;1041ScrollInfo *scrollInfo = layer->scrollInfo;10421043switch (layer->type) {1044default: break;10451046case LAYER_HSCROLL: {1047for (int32 i = 0; i < layer->scrollInfoCount; ++i) {1048scrollInfo->tilePos = scrollInfo->scrollPos + (currentScreen->position.x * scrollInfo->parallaxFactor << 8);10491050int16 tilePos = FROM_FIXED(scrollInfo->tilePos) % pixelWidth;1051if (tilePos < 0)1052tilePos += pixelWidth;1053scrollInfo->tilePos = TO_FIXED(tilePos);10541055++scrollInfo;1056}10571058int16 scrollPos =1059FROM_FIXED((int32)((layer->scrollPos + (layer->parallaxFactor * currentScreen->position.y << 8)) & 0xFFFF0000)) % pixelHeight;1060if (scrollPos < 0)1061scrollPos += pixelHeight;10621063uint8 *lineScrollPtr = &layer->lineScroll[scrollPos];10641065// Above water1066int32 *deformationData = &layer->deformationData[(scrollPos + (uint16)layer->deformationOffset) & 0x1FF];1067for (int32 i = 0; i < currentScreen->waterDrawPos; ++i) {1068scanline->position.x = layer->scrollInfo[*lineScrollPtr].tilePos;1069if (layer->scrollInfo[*lineScrollPtr].deform)1070scanline->position.x += TO_FIXED(*deformationData);10711072scanline->position.y = TO_FIXED(scrollPos++);10731074deformationData++;1075if (scrollPos == pixelHeight) {1076lineScrollPtr = layer->lineScroll;1077scrollPos = 0;1078}1079else {1080++lineScrollPtr;1081}1082scanline++;1083}10841085// Under water1086deformationData = &layer->deformationDataW[(scrollPos + (uint16)layer->deformationOffsetW) & 0x1FF];1087for (int32 i = currentScreen->waterDrawPos; i < currentScreen->size.y; ++i) {1088scanline->position.x = layer->scrollInfo[*lineScrollPtr].tilePos;1089if (layer->scrollInfo[*lineScrollPtr].deform)1090scanline->position.x += TO_FIXED(*deformationData);10911092scanline->position.y = TO_FIXED(scrollPos++);10931094deformationData++;1095if (scrollPos == pixelHeight) {1096lineScrollPtr = layer->lineScroll;1097scrollPos = 0;1098}1099else {1100++lineScrollPtr;1101}1102scanline++;1103}1104break;1105}11061107case LAYER_VSCROLL: {1108for (int32 i = 0; i < layer->scrollInfoCount; ++i) {1109scrollInfo->tilePos = scrollInfo->scrollPos + (currentScreen->position.y * scrollInfo->parallaxFactor << 8);1110scrollInfo->tilePos = TO_FIXED(FROM_FIXED(scrollInfo->tilePos) % pixelHeight);11111112++scrollInfo;1113}11141115int16 scrollPos =1116FROM_FIXED((int32)((layer->scrollPos + (layer->parallaxFactor * currentScreen->position.x << 8)) & 0xFFFF0000)) % pixelWidth;1117if (scrollPos < 0)1118scrollPos += pixelWidth;11191120uint8 *lineScrollPtr = &layer->lineScroll[scrollPos];11211122// Above water1123for (int32 i = 0; i < currentScreen->size.x; ++i) {1124scanline->position.x = TO_FIXED(scrollPos++);1125scanline->position.y = layer->scrollInfo[*lineScrollPtr].tilePos;11261127if (scrollPos == pixelWidth) {1128lineScrollPtr = layer->lineScroll;1129scrollPos = 0;1130}1131else {1132++lineScrollPtr;1133}11341135scanline++;1136}1137break;1138}11391140case LAYER_ROTOZOOM: {1141int16 scrollPosX =1142FROM_FIXED((int32)((layer->scrollPos + (layer->parallaxFactor * currentScreen->position.x << 8)) & 0xFFFF0000)) % pixelWidth;1143if (scrollPosX < 0)1144scrollPosX += pixelWidth;11451146int16 scrollPosY =1147FROM_FIXED((int32)((layer->scrollPos + (layer->parallaxFactor * currentScreen->position.y << 8)) & 0xFFFF0000)) % pixelHeight;1148if (scrollPosY < 0)1149scrollPosY += pixelHeight;11501151for (int32 i = 0; i < currentScreen->size.y; ++i) {1152scanline->position.x = TO_FIXED(scrollPosX);1153scanline->position.y = TO_FIXED(scrollPosY++);1154scanline->deform.x = TO_FIXED(1);1155scanline->deform.y = TO_FIXED(0);11561157scanline++;1158}1159break;1160}11611162case LAYER_BASIC: {1163for (int32 i = 0; i < layer->scrollInfoCount; ++i) {1164scrollInfo->tilePos = scrollInfo->scrollPos + (currentScreen->position.x * scrollInfo->parallaxFactor << 8);11651166int16 tilePos = FROM_FIXED(scrollInfo->tilePos) % pixelWidth;1167if (tilePos < 0)1168tilePos += pixelWidth;1169scrollInfo->tilePos = TO_FIXED(tilePos);11701171++scrollInfo;1172}11731174int16 scrollPos =1175FROM_FIXED((int32)((layer->scrollPos + (layer->parallaxFactor * currentScreen->position.y << 8)) & 0xFFFF0000)) % pixelHeight;1176if (scrollPos < 0)1177scrollPos += pixelHeight;11781179uint8 *lineScrollPtr = &layer->lineScroll[scrollPos];11801181// Above water1182for (int32 i = 0; i < currentScreen->waterDrawPos; ++i) {1183scanline->position.x = layer->scrollInfo[*lineScrollPtr].tilePos;1184scanline->position.y = TO_FIXED(scrollPos++);11851186if (scrollPos == pixelHeight) {1187lineScrollPtr = layer->lineScroll;1188scrollPos = 0;1189}1190else {1191++lineScrollPtr;1192}1193scanline++;1194}11951196// Under water1197for (int32 i = currentScreen->waterDrawPos; i < currentScreen->size.y; ++i) {1198scanline->position.x = layer->scrollInfo[*lineScrollPtr].tilePos;1199scanline->position.y = TO_FIXED(scrollPos++);12001201if (scrollPos == pixelHeight) {1202lineScrollPtr = layer->lineScroll;1203scrollPos = 0;1204}1205else {1206++lineScrollPtr;1207}12081209scanline++;1210}1211break;1212}1213}1214}12151216void RSDK::ProcessSceneTimer()1217{1218if (sceneInfo.timeEnabled) {1219sceneInfo.timeCounter += 100;12201221if (sceneInfo.timeCounter >= 6000) {1222sceneInfo.timeCounter -= 6025;12231224if (++sceneInfo.seconds >= 60) {1225sceneInfo.seconds = 0;12261227if (++sceneInfo.minutes >= 60)1228sceneInfo.minutes = 0;1229}1230}12311232sceneInfo.milliseconds = sceneInfo.timeCounter / 60; // 60 == refreshRate1233}1234}12351236void RSDK::SetScene(const char *categoryName, const char *sceneName)1237{1238RETRO_HASH_MD5(catHash);1239GEN_HASH_MD5(categoryName, catHash);12401241RETRO_HASH_MD5(scnHash);1242GEN_HASH_MD5(sceneName, scnHash);12431244for (int32 i = 0; i < sceneInfo.categoryCount; ++i) {1245if (HASH_MATCH_MD5(sceneInfo.listCategory[i].hash, catHash)) {1246sceneInfo.activeCategory = i;1247sceneInfo.listPos = sceneInfo.listCategory[i].sceneOffsetStart;12481249for (int32 s = 0; s < sceneInfo.listCategory[i].sceneCount; ++s) {1250if (HASH_MATCH_MD5(sceneInfo.listData[sceneInfo.listCategory[i].sceneOffsetStart + s].hash, scnHash)) {1251sceneInfo.listPos = sceneInfo.listCategory[i].sceneOffsetStart + s;1252break;1253}1254}12551256break;1257}1258}1259}12601261void RSDK::CopyTileLayer(uint16 dstLayerID, int32 dstStartX, int32 dstStartY, uint16 srcLayerID, int32 srcStartX, int32 srcStartY, int32 countX,1262int32 countY)1263{1264if (dstLayerID < LAYER_COUNT && srcLayerID < LAYER_COUNT) {1265TileLayer *dstLayer = &tileLayers[dstLayerID];1266TileLayer *srcLayer = &tileLayers[srcLayerID];12671268if (dstStartX >= 0 && dstStartX < dstLayer->xsize && dstStartY >= 0 && dstStartY < dstLayer->ysize) {1269if (srcStartX >= 0 && srcStartX < srcLayer->xsize && srcStartY >= 0 && srcStartY < srcLayer->ysize) {1270if (dstStartX + countX > dstLayer->xsize)1271countX = dstLayer->xsize - dstStartX;12721273if (dstStartY + countY > dstLayer->ysize)1274countY = dstLayer->ysize - dstStartY;12751276if (srcStartX + countX > srcLayer->xsize)1277countX = srcLayer->xsize - srcStartX;12781279if (srcStartY + countY > srcLayer->ysize)1280countY = srcLayer->ysize - srcStartY;12811282for (int32 y = 0; y < countY; ++y) {1283for (int32 x = 0; x < countX; ++x) {1284uint16 tile = srcLayer->layout[(x + srcStartX) + ((y + srcStartY) << srcLayer->widthShift)];1285dstLayer->layout[(x + dstStartX) + ((y + dstStartY) << dstLayer->widthShift)] = tile;1286}1287}1288}1289}1290}1291}12921293void RSDK::DrawLayerHScroll(TileLayer *layer)1294{1295if (!layer->xsize || !layer->ysize)1296return;12971298int32 lineTileCount = (currentScreen->pitch >> 4) - 1;1299uint8 *lineBuffer = &gfxLineBuffer[currentScreen->clipBound_Y1];1300ScanlineInfo *scanline = &scanlines[currentScreen->clipBound_Y1];1301uint16 *frameBuffer = ¤tScreen->frameBuffer[currentScreen->pitch * currentScreen->clipBound_Y1];13021303for (int32 cy = currentScreen->clipBound_Y1; cy < currentScreen->clipBound_Y2; ++cy) {1304int32 x = scanline->position.x;1305int32 y = scanline->position.y;1306int32 tileX = FROM_FIXED(x);1307uint16 *activePalette = fullPalette[*lineBuffer++];13081309if (tileX >= TILE_SIZE * layer->xsize)1310x = TO_FIXED(tileX - TILE_SIZE * layer->xsize);1311else if (tileX < 0)1312x = TO_FIXED(tileX + TILE_SIZE * layer->xsize);13131314int32 tileRemain = TILE_SIZE - (FROM_FIXED(x) & 0xF);1315int32 sheetX = FROM_FIXED(x) & 0xF;1316int32 sheetY = TILE_SIZE * (FROM_FIXED(y) & 0xF);1317int32 lineRemain = currentScreen->pitch;13181319int32 tx = x >> 20;1320uint16 *layout = &layer->layout[tx + ((y >> 20) << layer->widthShift)];1321lineRemain -= tileRemain;13221323if (*layout >= 0xFFFF) {1324frameBuffer += tileRemain;1325}1326else {1327uint8 *pixels = &tilesetPixels[TILE_DATASIZE * (*layout & 0xFFF) + sheetY + sheetX];1328for (int32 x = 0; x < tileRemain; ++x) {1329if (*pixels)1330*frameBuffer = activePalette[*pixels];1331++pixels;1332++frameBuffer;1333}1334}13351336for (int32 l = 0; l < lineTileCount; ++l) {1337++layout;13381339if (++tx == layer->xsize) {1340tx = 0;1341layout -= layer->xsize;1342}13431344if (*layout < 0xFFFF) {1345uint8 *pixels = &tilesetPixels[TILE_DATASIZE * (*layout & 0xFFF) + sheetY];13461347uint8 index = *pixels;1348if (index)1349*frameBuffer = activePalette[index];13501351index = pixels[1];1352if (index)1353frameBuffer[1] = activePalette[index];13541355index = pixels[2];1356if (index)1357frameBuffer[2] = activePalette[index];13581359index = pixels[3];1360if (index)1361frameBuffer[3] = activePalette[index];13621363index = pixels[4];1364if (index)1365frameBuffer[4] = activePalette[index];13661367index = pixels[5];1368if (index)1369frameBuffer[5] = activePalette[index];13701371index = pixels[6];1372if (index)1373frameBuffer[6] = activePalette[index];13741375index = pixels[7];1376if (index)1377frameBuffer[7] = activePalette[index];13781379index = pixels[8];1380if (index)1381frameBuffer[8] = activePalette[index];13821383index = pixels[9];1384if (index)1385frameBuffer[9] = activePalette[index];13861387index = pixels[10];1388if (index)1389frameBuffer[10] = activePalette[index];13901391index = pixels[11];1392if (index)1393frameBuffer[11] = activePalette[index];13941395index = pixels[12];1396if (index)1397frameBuffer[12] = activePalette[index];13981399index = pixels[13];1400if (index)1401frameBuffer[13] = activePalette[index];14021403index = pixels[14];1404if (index)1405frameBuffer[14] = activePalette[index];14061407index = pixels[15];1408if (index)1409frameBuffer[15] = activePalette[index];1410}14111412frameBuffer += TILE_SIZE;1413lineRemain -= TILE_SIZE;1414}14151416while (lineRemain > 0) {1417++layout;14181419if (++tx == layer->xsize) {1420tx = 0;1421layout -= layer->xsize;1422}14231424tileRemain = lineRemain >= TILE_SIZE ? TILE_SIZE : lineRemain;14251426if (*layout >= 0xFFFF) {1427frameBuffer += tileRemain;1428}1429else {1430uint8 *pixels = &tilesetPixels[TILE_DATASIZE * (*layout & 0xFFF) + sheetY];1431for (int32 x = 0; x < tileRemain; ++x) {1432if (*pixels)1433*frameBuffer = activePalette[*pixels];1434++pixels;1435++frameBuffer;1436}1437}14381439lineRemain -= TILE_SIZE;1440}14411442++scanline;1443}1444}1445void RSDK::DrawLayerVScroll(TileLayer *layer)1446{1447if (!layer->xsize || !layer->ysize)1448return;14491450int32 lineTileCount = (currentScreen->size.y >> 4) - 1;1451uint16 *frameBuffer = ¤tScreen->frameBuffer[currentScreen->clipBound_X1];1452ScanlineInfo *scanline = &scanlines[currentScreen->clipBound_X1];1453uint16 *activePalette = fullPalette[gfxLineBuffer[0]];14541455for (int32 cx = currentScreen->clipBound_X1; cx < currentScreen->clipBound_X2; ++cx) {1456int32 x = scanline->position.x;1457int32 y = scanline->position.y;1458int32 ty = FROM_FIXED(y);14591460if (ty >= TILE_SIZE * layer->ysize)1461y -= TO_FIXED(TILE_SIZE * layer->ysize);1462else if (ty < 0)1463y += TO_FIXED(TILE_SIZE * layer->ysize);14641465int32 tileRemain = TILE_SIZE - (FROM_FIXED(y) & 0xF);1466int32 sheetX = FROM_FIXED(x) & 0xF;1467int32 sheetY = FROM_FIXED(y) & 0xF;1468int32 lineRemain = currentScreen->size.y;14691470uint16 *layout = &layer->layout[(x >> 20) + ((y >> 20) << layer->widthShift)];1471lineRemain -= tileRemain;14721473if (*layout >= 0xFFFF) {1474frameBuffer += currentScreen->pitch * tileRemain;1475}1476else {1477uint8 *pixels = &tilesetPixels[TILE_SIZE * (sheetY + TILE_SIZE * (*layout & 0xFFF)) + sheetX];1478for (int32 y = 0; y < tileRemain; ++y) {1479if (*pixels)1480*frameBuffer = activePalette[*pixels];1481pixels += TILE_SIZE;1482frameBuffer += currentScreen->pitch;1483}1484}14851486ty = y >> 20;1487for (int32 l = 0; l < lineTileCount; ++l) {1488layout += layer->xsize;14891490if (++ty == layer->ysize) {1491ty = 0;1492layout -= layer->ysize << layer->widthShift;1493}14941495if (*layout >= 0xFFFF) {1496frameBuffer += TILE_SIZE * currentScreen->pitch;1497}1498else {1499uint8 *pixels = &tilesetPixels[TILE_DATASIZE * (*layout & 0xFFF) + sheetX];15001501if (*pixels)1502*frameBuffer = activePalette[*pixels];15031504if (pixels[0x10])1505frameBuffer[currentScreen->pitch * 1] = activePalette[pixels[0x10]];15061507if (pixels[0x20])1508frameBuffer[currentScreen->pitch * 2] = activePalette[pixels[0x20]];15091510if (pixels[0x30])1511frameBuffer[currentScreen->pitch * 3] = activePalette[pixels[0x30]];15121513if (pixels[0x40])1514frameBuffer[currentScreen->pitch * 4] = activePalette[pixels[0x40]];15151516if (pixels[0x50])1517frameBuffer[currentScreen->pitch * 5] = activePalette[pixels[0x50]];15181519if (pixels[0x60])1520frameBuffer[currentScreen->pitch * 6] = activePalette[pixels[0x60]];15211522if (pixels[0x70])1523frameBuffer[currentScreen->pitch * 7] = activePalette[pixels[0x70]];15241525if (pixels[0x80])1526frameBuffer[currentScreen->pitch * 8] = activePalette[pixels[0x80]];15271528if (pixels[0x90])1529frameBuffer[currentScreen->pitch * 9] = activePalette[pixels[0x90]];15301531if (pixels[0xA0])1532frameBuffer[currentScreen->pitch * 10] = activePalette[pixels[0xA0]];15331534if (pixels[0xB0])1535frameBuffer[currentScreen->pitch * 11] = activePalette[pixels[0xB0]];15361537if (pixels[0xC0])1538frameBuffer[currentScreen->pitch * 12] = activePalette[pixels[0xC0]];15391540if (pixels[0xD0])1541frameBuffer[currentScreen->pitch * 13] = activePalette[pixels[0xD0]];15421543if (pixels[0xE0])1544frameBuffer[currentScreen->pitch * 14] = activePalette[pixels[0xE0]];15451546if (pixels[0xF0])1547frameBuffer[currentScreen->pitch * 15] = activePalette[pixels[0xF0]];15481549frameBuffer += currentScreen->pitch * TILE_SIZE;1550}15511552lineRemain -= TILE_SIZE;1553}15541555while (lineRemain > 0) {1556layout += layer->xsize;15571558if (++ty == layer->ysize) {1559ty = 0;1560layout -= layer->ysize << layer->widthShift;1561}15621563tileRemain = lineRemain >= TILE_SIZE ? TILE_SIZE : lineRemain;1564if (*layout >= 0xFFFF) {1565frameBuffer += currentScreen->pitch * sheetY;1566}1567else {1568uint8 *pixels = &tilesetPixels[TILE_DATASIZE * (*layout & 0xFFF) + sheetX];1569for (int32 y = 0; y < tileRemain; ++y) {1570if (*pixels)1571*frameBuffer = activePalette[*pixels];15721573pixels += TILE_SIZE;1574frameBuffer += currentScreen->pitch;1575}1576}15771578lineRemain -= TILE_SIZE;1579}15801581frameBuffer -= currentScreen->pitch * currentScreen->size.y;15821583++scanline;1584++frameBuffer;1585}1586}1587void RSDK::DrawLayerRotozoom(TileLayer *layer)1588{1589if (!layer->xsize || !layer->ysize)1590return;15911592uint16 *layout = layer->layout;1593uint8 *lineBuffer = &gfxLineBuffer[currentScreen->clipBound_Y1];1594ScanlineInfo *scanline = &scanlines[currentScreen->clipBound_Y1];1595uint16 *frameBuffer = ¤tScreen->frameBuffer[currentScreen->clipBound_X1 + currentScreen->clipBound_Y1 * currentScreen->pitch];15961597int32 width = (TILE_SIZE << layer->widthShift) - 1;1598int32 height = (TILE_SIZE << layer->heightShift) - 1;1599int32 lineSize = currentScreen->clipBound_X2 - currentScreen->clipBound_X1;16001601for (int32 cy = currentScreen->clipBound_Y1; cy < currentScreen->clipBound_Y2; ++cy) {1602int32 posX = scanline->position.x;1603int32 posY = scanline->position.y;16041605uint16 *activePalette = fullPalette[*lineBuffer];1606++lineBuffer;1607int32 fbOffset = currentScreen->pitch - lineSize;16081609for (int32 cx = 0; cx < lineSize; ++cx) {1610int32 tx = posX >> 20;1611int32 ty = posY >> 20;1612int32 x = FROM_FIXED(posX) & 0xF;1613int32 y = FROM_FIXED(posY) & 0xF;16141615uint16 tile = layout[((width >> 4) & tx) + (((height >> 4) & ty) << layer->widthShift)] & 0xFFF;1616uint8 idx = tilesetPixels[TILE_SIZE * (y + TILE_SIZE * tile) + x];16171618if (idx)1619*frameBuffer = activePalette[idx];16201621posX += scanline->deform.x;1622posY += scanline->deform.y;1623++frameBuffer;1624}16251626frameBuffer += fbOffset;1627++scanline;1628}1629}1630void RSDK::DrawLayerBasic(TileLayer *layer)1631{1632if (!layer->xsize || !layer->ysize)1633return;16341635if (currentScreen->clipBound_X1 >= currentScreen->clipBound_X2 || currentScreen->clipBound_Y1 >= currentScreen->clipBound_Y2)1636return;16371638uint16 *activePalette = fullPalette[0];1639if (currentScreen->clipBound_X1 < currentScreen->clipBound_X2 && currentScreen->clipBound_Y1 < currentScreen->clipBound_Y2) {1640int32 lineSize = (currentScreen->clipBound_X2 - currentScreen->clipBound_X1) >> 4;16411642ScanlineInfo *scanline = &scanlines[currentScreen->clipBound_Y1];16431644int32 tx = (currentScreen->clipBound_X1 + FROM_FIXED(scanline->position.x)) >> 4;1645int32 ty = FROM_FIXED(scanline->position.y) >> 4;1646int32 sheetY = FROM_FIXED(scanline->position.y) & 0xF;1647int32 sheetX = (currentScreen->clipBound_X1 + FROM_FIXED(scanline->position.x)) & 0xF;1648int32 tileRemainX = TILE_SIZE - sheetX;1649int32 tileRemainY = TILE_SIZE - sheetY;16501651uint16 *frameBuffer = ¤tScreen->frameBuffer[currentScreen->clipBound_X1 + currentScreen->clipBound_Y1 * currentScreen->pitch];1652uint16 *layout = &layer->layout[tx + (ty << layer->widthShift)];16531654// Remaining pixels on top1655{1656if (*layout == 0xFFFF) {1657frameBuffer += TILE_SIZE - sheetX;1658}1659else {1660uint8 *pixels = &tilesetPixels[TILE_DATASIZE * (*layout & 0xFFF) + TILE_SIZE * sheetY + sheetX];16611662for (int32 y = 0; y < tileRemainY; ++y) {1663for (int32 x = 0; x < tileRemainX; ++x) {1664if (*pixels)1665*frameBuffer = activePalette[*pixels];1666++pixels;1667++frameBuffer;1668}16691670pixels += sheetX;1671frameBuffer += currentScreen->pitch - tileRemainX;1672}16731674frameBuffer += tileRemainX - currentScreen->pitch * tileRemainY;1675}16761677++layout;1678if (++tx == layer->xsize) {1679tx = 0;1680layout -= layer->xsize;1681}16821683for (int32 x = 0; x < lineSize; ++x) {1684if (*layout == 0xFFFF) {1685frameBuffer += TILE_SIZE;1686}1687else {1688uint8 *pixels = &tilesetPixels[TILE_DATASIZE * (*layout & 0xFFF) + TILE_SIZE * sheetY];1689for (int32 y = 0; y < tileRemainY; ++y) {1690uint8 index = *pixels;1691if (index)1692*frameBuffer = activePalette[index];16931694index = pixels[1];1695if (index)1696frameBuffer[1] = activePalette[index];16971698index = pixels[2];1699if (index)1700frameBuffer[2] = activePalette[index];17011702index = pixels[3];1703if (index)1704frameBuffer[3] = activePalette[index];17051706index = pixels[4];1707if (index)1708frameBuffer[4] = activePalette[index];17091710index = pixels[5];1711if (index)1712frameBuffer[5] = activePalette[index];17131714index = pixels[6];1715if (index)1716frameBuffer[6] = activePalette[index];17171718index = pixels[7];1719if (index)1720frameBuffer[7] = activePalette[index];17211722index = pixels[8];1723if (index)1724frameBuffer[8] = activePalette[index];17251726index = pixels[9];1727if (index)1728frameBuffer[9] = activePalette[index];17291730index = pixels[10];1731if (index)1732frameBuffer[10] = activePalette[index];17331734index = pixels[11];1735if (index)1736frameBuffer[11] = activePalette[index];17371738index = pixels[12];1739if (index)1740frameBuffer[12] = activePalette[index];17411742index = pixels[13];1743if (index)1744frameBuffer[13] = activePalette[index];17451746index = pixels[14];1747if (index)1748frameBuffer[14] = activePalette[index];17491750index = pixels[15];1751if (index)1752frameBuffer[15] = activePalette[index];17531754frameBuffer += currentScreen->pitch;1755pixels += TILE_SIZE;1756}17571758frameBuffer += TILE_SIZE - currentScreen->pitch * tileRemainY;1759}17601761++layout;1762if (++tx == layer->xsize) {1763tx = 0;1764layout -= layer->xsize;1765}1766}17671768if (*layout == 0xFFFF) {1769frameBuffer += currentScreen->pitch * tileRemainY;1770}1771else {1772uint8 *pixels = &tilesetPixels[TILE_DATASIZE * (*layout & 0xFFF) + TILE_SIZE * sheetY];17731774for (int32 y = 0; y < tileRemainY; ++y) {1775for (int32 x = 0; x < sheetX; ++x) {1776if (*pixels)1777*frameBuffer = activePalette[*pixels];1778++pixels;1779++frameBuffer;1780}17811782pixels += tileRemainX;1783frameBuffer += currentScreen->pitch - sheetX;1784}1785}1786}17871788// We've drawn a single line of pixels, increase our variables1789frameBuffer += sheetX + -TILE_SIZE * lineSize - TILE_SIZE;1790scanline += tileRemainY;1791if (++ty == layer->ysize)1792ty = 0;17931794// Draw the bulk of the tiles1795int32 lineTileCount = ((currentScreen->clipBound_Y2 - currentScreen->clipBound_Y1) >> 4) - 1;1796for (int32 l = 0; l < lineTileCount; ++l) {1797sheetX = (currentScreen->clipBound_X1 + FROM_FIXED(scanline->position.x)) & 0xF;1798tx = (currentScreen->clipBound_X1 + FROM_FIXED(scanline->position.x)) >> 4;1799tileRemainX = TILE_SIZE - sheetX;1800layout = &layer->layout[tx + (ty << layer->widthShift)];18011802// Draw any stray pixels on the left1803if (*layout == 0xFFFF) {1804frameBuffer += tileRemainX;1805}1806else {1807uint8 *pixels = &tilesetPixels[TILE_DATASIZE * (*layout & 0xFFF) + sheetX];18081809for (int32 y = 0; y < TILE_SIZE; ++y) {1810for (int32 x = 0; x < tileRemainX; ++x) {1811if (*pixels)1812*frameBuffer = activePalette[*pixels];1813++pixels;1814++frameBuffer;1815}18161817pixels += sheetX;1818frameBuffer += currentScreen->pitch - tileRemainX;1819}18201821frameBuffer += tileRemainX - TILE_SIZE * currentScreen->pitch;1822}1823++layout;1824if (++tx == layer->xsize) {1825tx = 0;1826layout -= layer->xsize;1827}18281829// Draw the bulk of the tiles on this line1830for (int32 x = 0; x < lineSize; ++x) {1831if (*layout == 0xFFFF) {1832frameBuffer += TILE_SIZE;1833}1834else {1835uint8 *pixels = &tilesetPixels[TILE_DATASIZE * (*layout & 0xFFF)];18361837for (int32 y = 0; y < TILE_SIZE; ++y) {1838uint8 index = *pixels;1839if (index)1840*frameBuffer = activePalette[index];18411842index = pixels[1];1843if (index)1844frameBuffer[1] = activePalette[index];18451846index = pixels[2];1847if (index)1848frameBuffer[2] = activePalette[index];18491850index = pixels[3];1851if (index)1852frameBuffer[3] = activePalette[index];18531854index = pixels[4];1855if (index)1856frameBuffer[4] = activePalette[index];18571858index = pixels[5];1859if (index)1860frameBuffer[5] = activePalette[index];18611862index = pixels[6];1863if (index)1864frameBuffer[6] = activePalette[index];18651866index = pixels[7];1867if (index)1868frameBuffer[7] = activePalette[index];18691870index = pixels[8];1871if (index)1872frameBuffer[8] = activePalette[index];18731874index = pixels[9];1875if (index)1876frameBuffer[9] = activePalette[index];18771878index = pixels[10];1879if (index)1880frameBuffer[10] = activePalette[index];18811882index = pixels[11];1883if (index)1884frameBuffer[11] = activePalette[index];18851886index = pixels[12];1887if (index)1888frameBuffer[12] = activePalette[index];18891890index = pixels[13];1891if (index)1892frameBuffer[13] = activePalette[index];18931894index = pixels[14];1895if (index)1896frameBuffer[14] = activePalette[index];18971898index = pixels[15];1899if (index)1900frameBuffer[15] = activePalette[index];19011902pixels += TILE_SIZE;1903frameBuffer += currentScreen->pitch;1904}19051906frameBuffer -= TILE_SIZE * currentScreen->pitch;1907frameBuffer += TILE_SIZE;1908}19091910++layout;1911if (++tx == layer->xsize) {1912tx = 0;1913layout -= layer->xsize;1914}1915}19161917// Draw any stray pixels on the right1918if (*layout == 0xFFFF) {1919frameBuffer += TILE_SIZE * currentScreen->pitch;1920}1921else {1922uint8 *pixels = &tilesetPixels[TILE_DATASIZE * (*layout & 0xFFF)];19231924for (int32 y = 0; y < TILE_SIZE; ++y) {1925for (int32 x = 0; x < sheetX; ++x) {1926if (*pixels)1927*frameBuffer = activePalette[*pixels];1928++pixels;1929++frameBuffer;1930}19311932pixels += tileRemainX;1933frameBuffer += currentScreen->pitch - sheetX;1934}1935}1936++layout;1937if (++tx == layer->xsize) {1938tx = 0;1939layout -= layer->xsize;1940}19411942// We've drawn a single line, increase our variables1943scanline += TILE_SIZE;1944frameBuffer += sheetX + -TILE_SIZE * lineSize - TILE_SIZE;1945if (++ty == layer->ysize)1946ty = 0;1947}19481949// Remaining pixels on bottom1950{1951tx = (currentScreen->clipBound_X1 + FROM_FIXED(scanline->position.x)) >> 4;1952sheetX = (currentScreen->clipBound_X1 + FROM_FIXED(scanline->position.x)) & 0xF;1953tileRemainX = TILE_SIZE - sheetX;1954layout = &layer->layout[tx + (ty << layer->widthShift)];19551956if (*layout != 0xFFFF) {1957frameBuffer += tileRemainX;1958}1959else {1960uint8 *pixels = &tilesetPixels[TILE_DATASIZE * (*layout & 0xFFF) + sheetX];19611962for (int32 y = 0; y < sheetY; ++y) {1963for (int32 x = 0; x < tileRemainX; ++x) {1964if (*pixels)1965*frameBuffer = activePalette[*pixels];1966++pixels;1967++frameBuffer;1968}19691970pixels += sheetX;1971frameBuffer += currentScreen->pitch - tileRemainX;1972}19731974frameBuffer += tileRemainX - currentScreen->pitch * sheetY;1975}1976++layout;1977if (++tx == layer->xsize) {1978tx = 0;1979layout -= layer->xsize;1980}19811982for (int32 x = 0; x < lineSize; ++x) {1983if (*layout == 0xFFFF) {1984frameBuffer += TILE_SIZE;1985}1986else {1987uint8 *pixels = &tilesetPixels[TILE_DATASIZE * (*layout & 0xFFF)];1988for (int32 y = 0; y < sheetY; ++y) {1989uint8 index = *pixels;1990if (index)1991*frameBuffer = activePalette[index];19921993index = pixels[1];1994if (index)1995frameBuffer[1] = activePalette[index];19961997index = pixels[2];1998if (index)1999frameBuffer[2] = activePalette[index];20002001index = pixels[3];2002if (index)2003frameBuffer[3] = activePalette[index];20042005index = pixels[4];2006if (index)2007frameBuffer[4] = activePalette[index];20082009index = pixels[5];2010if (index)2011frameBuffer[5] = activePalette[index];20122013index = pixels[6];2014if (index)2015frameBuffer[6] = activePalette[index];20162017index = pixels[7];2018if (index)2019frameBuffer[7] = activePalette[index];20202021index = pixels[8];2022if (index)2023frameBuffer[8] = activePalette[index];20242025index = pixels[9];2026if (index)2027frameBuffer[9] = activePalette[index];20282029index = pixels[10];2030if (index)2031frameBuffer[10] = activePalette[index];20322033index = pixels[11];2034if (index)2035frameBuffer[11] = activePalette[index];20362037index = pixels[12];2038if (index)2039frameBuffer[12] = activePalette[index];20402041index = pixels[13];2042if (index)2043frameBuffer[13] = activePalette[index];20442045index = pixels[14];2046if (index)2047frameBuffer[14] = activePalette[index];20482049index = pixels[15];2050if (index)2051frameBuffer[15] = activePalette[index];20522053pixels += TILE_SIZE;2054frameBuffer += currentScreen->pitch;2055}20562057frameBuffer += TILE_SIZE - currentScreen->pitch * sheetY;2058}20592060++layout;2061if (++tx == layer->xsize) {2062tx = 0;2063layout -= layer->xsize;2064}2065}20662067if (*layout != 0xFFFF) {2068uint8 *pixels = &tilesetPixels[256 * (*layout & 0xFFF)];20692070for (int32 y = 0; y < sheetY; ++y) {2071for (int32 x = 0; x < sheetX; ++x) {2072if (*pixels)2073*frameBuffer = activePalette[*pixels];2074++pixels;2075++frameBuffer;2076}20772078pixels += tileRemainX;2079}20802081frameBuffer += currentScreen->pitch - sheetX;2082}2083}2084}2085}208620872088