Path: blob/main/RSDKv4/Object.cpp
817 views
#include "RetroEngine.hpp"12// Native Objects3int nativeEntityPos;45int activeEntityList[NATIVEENTITY_COUNT];6byte objectRemoveFlag[NATIVEENTITY_COUNT];7NativeEntity objectEntityBank[NATIVEENTITY_COUNT];8int nativeEntityCount = 0;910int nativeEntityCountBackup = 0;11int backupEntityList[NATIVEENTITY_COUNT];12NativeEntity objectEntityBackup[NATIVEENTITY_COUNT];1314int nativeEntityCountBackupS = 0;15int backupEntityListS[NATIVEENTITY_COUNT];16NativeEntity objectEntityBackupS[NATIVEENTITY_COUNT];1718// Game Objects19int objectEntityPos = 0;20int curObjectType = 0;21Entity objectEntityList[ENTITY_COUNT * 2]; //"regular" list & "storage" list22int processObjectFlag[ENTITY_COUNT];23TypeGroupList objectTypeGroupList[TYPEGROUP_COUNT];2425char typeNames[OBJECT_COUNT][0x40];2627int OBJECT_BORDER_X1 = 0x80;28int OBJECT_BORDER_X2 = SCREEN_XSIZE + 0x80;29int OBJECT_BORDER_X3 = 0x20;30int OBJECT_BORDER_X4 = SCREEN_XSIZE + 0x20;3132const int OBJECT_BORDER_Y1 = 0x100;33const int OBJECT_BORDER_Y2 = SCREEN_YSIZE + 0x100;34const int OBJECT_BORDER_Y3 = 0x80;35const int OBJECT_BORDER_Y4 = SCREEN_YSIZE + 0x80;3637int playerListPos = 0;3839void ProcessStartupObjects()40{41scriptFrameCount = 0;42ClearAnimationData();43scriptEng.arrayPosition[8] = TEMPENTITY_START;44OBJECT_BORDER_X1 = 0x80;45OBJECT_BORDER_X3 = 0x20;46OBJECT_BORDER_X2 = SCREEN_XSIZE + 0x80;47OBJECT_BORDER_X4 = SCREEN_XSIZE + 0x20;48Entity *entity = &objectEntityList[TEMPENTITY_START];49// Dunno what this is meant for, but it's here in the original code so...50objectEntityList[TEMPENTITY_START + 1].type = objectEntityList[0].type;5152memset(foreachStack, -1, sizeof(foreachStack));53memset(jumpTableStack, 0, sizeof(jumpTableStack));5455for (int i = 0; i < OBJECT_COUNT; ++i) {56ObjectScript *scriptInfo = &objectScriptList[i];57objectEntityPos = TEMPENTITY_START;58curObjectType = i;59scriptInfo->frameListOffset = scriptFrameCount;60scriptInfo->spriteSheetID = 0;61entity->type = i;6263if (scriptCode[scriptInfo->eventStartup.scriptCodePtr] > 0)64ProcessScript(scriptInfo->eventStartup.scriptCodePtr, scriptInfo->eventStartup.jumpTablePtr, EVENT_SETUP);65scriptInfo->frameCount = scriptFrameCount - scriptInfo->frameListOffset;66}67entity->type = 0;68curObjectType = 0;69}7071void ProcessObjects()72{73for (int i = 0; i < DRAWLAYER_COUNT; ++i) drawListEntries[i].listSize = 0;7475for (objectEntityPos = 0; objectEntityPos < ENTITY_COUNT; ++objectEntityPos) {76processObjectFlag[objectEntityPos] = false;77int x = 0, y = 0;78Entity *entity = &objectEntityList[objectEntityPos];79x = entity->xpos >> 16;80y = entity->ypos >> 16;8182switch (entity->priority) {83case PRIORITY_BOUNDS:84processObjectFlag[objectEntityPos] = x > xScrollOffset - OBJECT_BORDER_X1 && x < xScrollOffset + OBJECT_BORDER_X285&& y > yScrollOffset - OBJECT_BORDER_Y1 && y < yScrollOffset + OBJECT_BORDER_Y2;86break;8788case PRIORITY_ACTIVE:89case PRIORITY_ALWAYS:90case PRIORITY_ACTIVE_SMALL: processObjectFlag[objectEntityPos] = true; break;9192case PRIORITY_XBOUNDS:93processObjectFlag[objectEntityPos] = x > xScrollOffset - OBJECT_BORDER_X1 && x < OBJECT_BORDER_X2 + xScrollOffset;94break;9596case PRIORITY_XBOUNDS_DESTROY:97processObjectFlag[objectEntityPos] = x > xScrollOffset - OBJECT_BORDER_X1 && x < xScrollOffset + OBJECT_BORDER_X2;98if (!processObjectFlag[objectEntityPos]) {99processObjectFlag[objectEntityPos] = false;100entity->type = OBJ_TYPE_BLANKOBJECT;101}102break;103104case PRIORITY_INACTIVE: processObjectFlag[objectEntityPos] = false; break;105case PRIORITY_BOUNDS_SMALL:106processObjectFlag[objectEntityPos] = x > xScrollOffset - OBJECT_BORDER_X3 && x < OBJECT_BORDER_X4 + xScrollOffset107&& y > yScrollOffset - OBJECT_BORDER_Y3 && y < yScrollOffset + OBJECT_BORDER_Y4;108break;109110default: break;111}112113if (processObjectFlag[objectEntityPos] && entity->type > OBJ_TYPE_BLANKOBJECT) {114ObjectScript *scriptInfo = &objectScriptList[entity->type];115if (scriptCode[scriptInfo->eventUpdate.scriptCodePtr] > 0)116ProcessScript(scriptInfo->eventUpdate.scriptCodePtr, scriptInfo->eventUpdate.jumpTablePtr, EVENT_MAIN);117118if (entity->drawOrder < DRAWLAYER_COUNT)119drawListEntries[entity->drawOrder].entityRefs[drawListEntries[entity->drawOrder].listSize++] = objectEntityPos;120}121}122123for (int i = 0; i < TYPEGROUP_COUNT; ++i) objectTypeGroupList[i].listSize = 0;124125for (objectEntityPos = 0; objectEntityPos < ENTITY_COUNT; ++objectEntityPos) {126Entity *entity = &objectEntityList[objectEntityPos];127if (processObjectFlag[objectEntityPos] && entity->objectInteractions) {128// Custom Group129if (entity->groupID >= OBJECT_COUNT) {130TypeGroupList *listCustom = &objectTypeGroupList[objectEntityList[objectEntityPos].groupID];131listCustom->entityRefs[listCustom->listSize++] = objectEntityPos;132}133134// Type-Specific list135TypeGroupList *listType = &objectTypeGroupList[objectEntityList[objectEntityPos].type];136listType->entityRefs[listType->listSize++] = objectEntityPos;137138// All Entities list139TypeGroupList *listAll = &objectTypeGroupList[GROUP_ALL];140listAll->entityRefs[listAll->listSize++] = objectEntityPos;141}142}143}144void ProcessPausedObjects()145{146for (int i = 0; i < DRAWLAYER_COUNT; ++i) drawListEntries[i].listSize = 0;147148for (objectEntityPos = 0; objectEntityPos < ENTITY_COUNT; ++objectEntityPos) {149Entity *entity = &objectEntityList[objectEntityPos];150151if (entity->priority == PRIORITY_ALWAYS && entity->type > OBJ_TYPE_BLANKOBJECT) {152ObjectScript *scriptInfo = &objectScriptList[entity->type];153if (scriptCode[scriptInfo->eventUpdate.scriptCodePtr] > 0)154ProcessScript(scriptInfo->eventUpdate.scriptCodePtr, scriptInfo->eventUpdate.jumpTablePtr, EVENT_MAIN);155156if (entity->drawOrder < DRAWLAYER_COUNT && entity->drawOrder >= 0)157drawListEntries[entity->drawOrder].entityRefs[drawListEntries[entity->drawOrder].listSize++] = objectEntityPos;158}159}160}161void ProcessFrozenObjects()162{163for (int i = 0; i < DRAWLAYER_COUNT; ++i) drawListEntries[i].listSize = 0;164165for (objectEntityPos = 0; objectEntityPos < ENTITY_COUNT; ++objectEntityPos) {166processObjectFlag[objectEntityPos] = false;167int x = 0, y = 0;168Entity *entity = &objectEntityList[objectEntityPos];169x = entity->xpos >> 16;170y = entity->ypos >> 16;171172switch (entity->priority) {173case PRIORITY_BOUNDS:174processObjectFlag[objectEntityPos] = x > xScrollOffset - OBJECT_BORDER_X1 && x < xScrollOffset + OBJECT_BORDER_X2175&& y > yScrollOffset - OBJECT_BORDER_Y1 && y < yScrollOffset + OBJECT_BORDER_Y2;176break;177178case PRIORITY_ACTIVE:179case PRIORITY_ALWAYS:180case PRIORITY_ACTIVE_SMALL: processObjectFlag[objectEntityPos] = true; break;181182case PRIORITY_XBOUNDS:183processObjectFlag[objectEntityPos] = x > xScrollOffset - OBJECT_BORDER_X1 && x < OBJECT_BORDER_X2 + xScrollOffset;184break;185186case PRIORITY_XBOUNDS_DESTROY:187processObjectFlag[objectEntityPos] = x > xScrollOffset - OBJECT_BORDER_X1 && x < xScrollOffset + OBJECT_BORDER_X2;188if (!processObjectFlag[objectEntityPos]) {189processObjectFlag[objectEntityPos] = false;190entity->type = OBJ_TYPE_BLANKOBJECT;191}192break;193194case PRIORITY_INACTIVE: processObjectFlag[objectEntityPos] = false; break;195196case PRIORITY_BOUNDS_SMALL:197processObjectFlag[objectEntityPos] = x > xScrollOffset - OBJECT_BORDER_X3 && x < OBJECT_BORDER_X4 + xScrollOffset198&& y > yScrollOffset - OBJECT_BORDER_Y3 && y < yScrollOffset + OBJECT_BORDER_Y4;199break;200201default: break;202}203204if (processObjectFlag[objectEntityPos] && entity->type > OBJ_TYPE_BLANKOBJECT) {205ObjectScript *scriptInfo = &objectScriptList[entity->type];206if (scriptCode[scriptInfo->eventUpdate.scriptCodePtr] > 0 && entity->priority == PRIORITY_ALWAYS)207ProcessScript(scriptInfo->eventUpdate.scriptCodePtr, scriptInfo->eventUpdate.jumpTablePtr, EVENT_MAIN);208209if (entity->drawOrder < DRAWLAYER_COUNT && entity->drawOrder >= 0)210drawListEntries[entity->drawOrder].entityRefs[drawListEntries[entity->drawOrder].listSize++] = objectEntityPos;211}212}213214for (int i = 0; i < TYPEGROUP_COUNT; ++i) objectTypeGroupList[i].listSize = 0;215216for (objectEntityPos = 0; objectEntityPos < ENTITY_COUNT; ++objectEntityPos) {217Entity *entity = &objectEntityList[objectEntityPos];218if (processObjectFlag[objectEntityPos] && entity->objectInteractions) {219// Custom Group220if (entity->groupID >= OBJECT_COUNT) {221TypeGroupList *listCustom = &objectTypeGroupList[objectEntityList[objectEntityPos].groupID];222listCustom->entityRefs[listCustom->listSize++] = objectEntityPos;223}224// Type-Specific list225TypeGroupList *listType = &objectTypeGroupList[objectEntityList[objectEntityPos].type];226listType->entityRefs[listType->listSize++] = objectEntityPos;227228// All Entities list229TypeGroupList *listAll = &objectTypeGroupList[GROUP_ALL];230listAll->entityRefs[listAll->listSize++] = objectEntityPos;231}232}233}234#if !RETRO_REV00235void Process2PObjects()236{237for (int i = 0; i < DRAWLAYER_COUNT; ++i) drawListEntries[i].listSize = 0;238239int boundX1 = -(0x200 << 16);240int boundX2 = (0x200 << 16);241int boundX3 = -(0x180 << 16);242int boundX4 = (0x180 << 16);243244int boundY1 = -(0x180 << 16);245int boundY2 = (0x180 << 16);246int boundY3 = -(0x100 << 16);247int boundY4 = (0x100 << 16);248249for (objectEntityPos = 0; objectEntityPos < ENTITY_COUNT; ++objectEntityPos) {250processObjectFlag[objectEntityPos] = false;251int x = 0, y = 0;252253Entity *entity = &objectEntityList[objectEntityPos];254x = entity->xpos;255y = entity->ypos;256257// Set these here, they could (and prolly are) updated after objects258Entity *entityP1 = &objectEntityList[0];259int XPosP1 = entityP1->xpos;260int YPosP1 = entityP1->ypos;261Entity *entityP2 = &objectEntityList[1];262int XPosP2 = entityP2->xpos;263int YPosP2 = entityP2->ypos;264265switch (entity->priority) {266case PRIORITY_BOUNDS:267processObjectFlag[objectEntityPos] = x > XPosP1 + boundX1 && x < XPosP1 + boundX2 && y > YPosP1 + boundY1 && y < YPosP1 + boundY2;268if (!processObjectFlag[objectEntityPos]) {269processObjectFlag[objectEntityPos] = x > XPosP2 + boundX1 && x < XPosP2 + boundX2 && y > YPosP2 + boundY1 && y < YPosP2 + boundY2;270}271break;272273case PRIORITY_ACTIVE:274case PRIORITY_ALWAYS:275case PRIORITY_ACTIVE_SMALL: processObjectFlag[objectEntityPos] = true; break;276277case PRIORITY_XBOUNDS:278processObjectFlag[objectEntityPos] = x > XPosP1 + boundX1 && x < XPosP1 + boundX2;279if (!processObjectFlag[objectEntityPos]) {280processObjectFlag[objectEntityPos] = x > XPosP2 + boundX1 && x < XPosP2 + boundX2;281}282break;283284case PRIORITY_XBOUNDS_DESTROY:285processObjectFlag[objectEntityPos] = x > XPosP1 + boundX1 && x < XPosP1 + boundX2;286if (!processObjectFlag[objectEntityPos]) {287processObjectFlag[objectEntityPos] = x > XPosP2 + boundX1 && x < XPosP2 + boundX2;288}289290if (!processObjectFlag[objectEntityPos])291entity->type = OBJ_TYPE_BLANKOBJECT;292break;293294case PRIORITY_INACTIVE: processObjectFlag[objectEntityPos] = false; break;295case PRIORITY_BOUNDS_SMALL:296processObjectFlag[objectEntityPos] = x > XPosP1 + boundX3 && x < XPosP1 + boundX4 && y > YPosP1 + boundY3 && y < YPosP1 + boundY4;297if (!processObjectFlag[objectEntityPos]) {298processObjectFlag[objectEntityPos] = x > XPosP2 + boundX3 && x < XPosP2 + boundX4 && y > YPosP2 + boundY3 && y < YPosP2 + boundY4;299}300break;301302default: break;303}304305if (processObjectFlag[objectEntityPos] && entity->type > OBJ_TYPE_BLANKOBJECT) {306ObjectScript *scriptInfo = &objectScriptList[entity->type];307if (scriptCode[scriptInfo->eventUpdate.scriptCodePtr] > 0)308ProcessScript(scriptInfo->eventUpdate.scriptCodePtr, scriptInfo->eventUpdate.jumpTablePtr, EVENT_MAIN);309310if (entity->drawOrder < DRAWLAYER_COUNT && entity->drawOrder >= 0)311drawListEntries[entity->drawOrder].entityRefs[drawListEntries[entity->drawOrder].listSize++] = objectEntityPos;312}313}314315for (int i = 0; i < TYPEGROUP_COUNT; ++i) objectTypeGroupList[i].listSize = 0;316317for (objectEntityPos = 0; objectEntityPos < ENTITY_COUNT; ++objectEntityPos) {318Entity *entity = &objectEntityList[objectEntityPos];319if (processObjectFlag[objectEntityPos] && entity->objectInteractions) {320// Custom Group321if (entity->groupID >= OBJECT_COUNT) {322TypeGroupList *listCustom = &objectTypeGroupList[objectEntityList[objectEntityPos].groupID];323listCustom->entityRefs[listCustom->listSize++] = objectEntityPos;324}325// Type-Specific list326TypeGroupList *listType = &objectTypeGroupList[objectEntityList[objectEntityPos].type];327listType->entityRefs[listType->listSize++] = objectEntityPos;328329// All Entities list330TypeGroupList *listAll = &objectTypeGroupList[GROUP_ALL];331listAll->entityRefs[listAll->listSize++] = objectEntityPos;332}333}334}335#endif336337void SetObjectTypeName(const char *objectName, int objectID)338{339int objPos = 0;340int typePos = 0;341while (objectName[objPos]) {342if (objectName[objPos] != ' ')343typeNames[objectID][typePos++] = objectName[objPos];344++objPos;345}346typeNames[objectID][typePos] = 0;347PrintLog("Set Object (%d) name to: %s", objectID, objectName);348}349350void ProcessObjectControl(Entity *entity)351{352if (entity->controlMode == 0) {353entity->up = keyDown.up;354entity->down = keyDown.down;355if (!keyDown.left || !keyDown.right) {356entity->left = keyDown.left;357entity->right = keyDown.right;358}359else {360entity->left = false;361entity->right = false;362}363entity->jumpHold = keyDown.C || keyDown.B || keyDown.A;364entity->jumpPress = keyPress.C || keyPress.B || keyPress.A;365}366}367368void InitNativeObjectSystem()369{370InitLocalizedStrings();371372nativeEntityCount = 0;373memset(activeEntityList, 0, sizeof(activeEntityList));374memset(objectRemoveFlag, 0, sizeof(objectRemoveFlag));375memset(objectEntityBank, 0, sizeof(objectEntityBank));376377nativeEntityCountBackup = 0;378memset(backupEntityList, 0, sizeof(backupEntityList));379memset(objectEntityBackup, 0, sizeof(objectEntityBackup));380381nativeEntityCountBackupS = 0;382memset(backupEntityListS, 0, sizeof(backupEntityListS));383memset(objectEntityBackupS, 0, sizeof(objectEntityBackupS));384385ReadSaveRAMData();386387SaveGame *saveGame = (SaveGame *)saveRAM;388if (!saveGame->saveInitialized) {389saveGame->saveInitialized = true;390saveGame->musVolume = MAX_VOLUME;391saveGame->sfxVolume = MAX_VOLUME;392saveGame->spindashEnabled = true;393saveGame->boxRegion = 0;394saveGame->vDPadSize = 64;395saveGame->vDPadOpacity = 160;396saveGame->vDPadX_Move = 56;397saveGame->vDPadY_Move = 184;398saveGame->vDPadX_Jump = -56;399saveGame->vDPadY_Jump = 188;400saveGame->tailsUnlocked = Engine.gameType != GAME_SONIC1;401saveGame->knuxUnlocked = Engine.gameType != GAME_SONIC1;402saveGame->unlockedActs = 0;403WriteSaveRAMData();404}405#if !RETRO_USE_ORIGINAL_CODE406else if (Engine.gameType == GAME_SONIC2) {407// ensure tails and knuckles are unlocked in sonic 2408// they weren't automatically unlocked in older versions of the decomp409saveGame->tailsUnlocked = true;410saveGame->knuxUnlocked = true;411WriteSaveRAMData();412}413#endif414saveGame->musVolume = bgmVolume;415saveGame->sfxVolume = sfxVolume;416417if (!saveGame->musVolume)418musicEnabled = false;419420if (!saveGame->vDPadX_Move) {421saveGame->vDPadX_Move = 60;422saveGame->vDPadY_Move = 176;423saveGame->vDPadX_Jump = -56;424saveGame->vDPadY_Jump = 180;425}426427Engine.globalBoxRegion = saveGame->boxRegion;428SetGameVolumes(saveGame->musVolume, saveGame->sfxVolume);429#if !RETRO_USE_ORIGINAL_CODE430if (skipStartMenu) {431CREATE_ENTITY(RetroGameLoop);432if (Engine.gameDeviceType == RETRO_MOBILE)433CREATE_ENTITY(VirtualDPad);434}435else436#endif437CREATE_ENTITY(SegaSplash);438}439NativeEntity *CreateNativeObject(void (*create)(void *objPtr), void (*main)(void *objPtr))440{441if (!nativeEntityCount) {442memset(objectEntityBank, 0, sizeof(objectEntityBank));443NativeEntity *entity = &objectEntityBank[0];444entity->eventCreate = create;445entity->eventMain = main;446activeEntityList[0] = 0;447nativeEntityCount++;448if (entity->eventCreate)449entity->eventCreate(entity);450return entity;451}452else if (nativeEntityCount >= NATIVEENTITY_COUNT) {453// TODO, probably never454return NULL;455}456else {457int slot = 0;458for (; slot < NATIVEENTITY_COUNT; ++slot) {459if (!objectEntityBank[slot].eventMain)460break;461}462NativeEntity *entity = &objectEntityBank[slot];463memset(entity, 0, sizeof(NativeEntity));464entity->slotID = slot;465entity->objectID = nativeEntityCount;466entity->eventCreate = create;467entity->eventMain = main;468activeEntityList[nativeEntityCount++] = slot;469if (entity->eventCreate)470entity->eventCreate(entity);471return entity;472}473}474void RemoveNativeObject(NativeEntityBase *entity)475{476#if !RETRO_USE_ORIGINAL_CODE477if (!entity)478return;479memmove(&activeEntityList[entity->objectID], &activeEntityList[entity->objectID + 1], sizeof(int) * (NATIVEENTITY_COUNT - (entity->objectID + 2)));480--nativeEntityCount;481for (int i = entity->slotID; objectEntityBank[i].eventMain; ++i) objectEntityBank[i].objectID--;482#else483// this actually behaves COMPLETELY improperly, duplicating the deleted one instead484// the above code is my attempt to make a proper version485if (nativeEntityCount <= 0) {486objectRemoveFlag[entity->slotID] = true;487}488else {489memset(objectRemoveFlag, 0, nativeEntityCount);490int slotStore = 0;491objectRemoveFlag[entity->slotID] = true;492int s = 0;493do {494if (!objectRemoveFlag[s]) {495if (s != slotStore) {496int store = activeEntityList[s];497objectRemoveFlag[slotStore] = false;498activeEntityList[slotStore] = store;499}500++slotStore;501}502++s;503} while (s != nativeEntityCount);504nativeEntityCount = s - 1;505}506#endif507}508void ResetNativeObject(NativeEntityBase *obj, void (*create)(void *objPtr), void (*main)(void *objPtr))509{510int slotID = obj->slotID;511int objID = obj->objectID;512memset(&objectEntityBank[slotID], 0, sizeof(NativeEntity));513obj->slotID = slotID;514obj->eventMain = main;515obj->eventCreate = create;516obj->objectID = objID;517if (create)518create(obj);519}520void ProcessNativeObjects()521{522ResetRenderStates();523for (nativeEntityPos = 0; nativeEntityPos < nativeEntityCount; ++nativeEntityPos) {524NativeEntity *entity = &objectEntityBank[activeEntityList[nativeEntityPos]];525entity->eventMain(entity);526}527RenderScene();528}529530void RestoreNativeObjects()531{532memcpy(activeEntityList, backupEntityList, sizeof(activeEntityList));533memcpy(objectEntityBank, objectEntityBackup, sizeof(objectEntityBank));534nativeEntityCount = nativeEntityCountBackup;535536CREATE_ENTITY(FadeScreen)->state = FADESCREEN_STATE_MENUFADEIN;537}538539void RestoreNativeObjectsNoFade()540{541memcpy(activeEntityList, backupEntityList, sizeof(activeEntityList));542memcpy(objectEntityBank, objectEntityBackup, sizeof(objectEntityBank));543nativeEntityCount = nativeEntityCountBackup;544}545void RestoreNativeObjectsSettings()546{547memcpy(activeEntityList, backupEntityListS, sizeof(activeEntityList));548memcpy(objectEntityBank, objectEntityBackupS, sizeof(objectEntityBank));549nativeEntityCount = nativeEntityCountBackupS;550}551552553