Skip to content

Commit

Permalink
Add op_list_as_array
Browse files Browse the repository at this point in the history
  • Loading branch information
alexbatalov committed Sep 2, 2023
1 parent bb35139 commit 4276727
Show file tree
Hide file tree
Showing 5 changed files with 74 additions and 31 deletions.
20 changes: 20 additions & 0 deletions src/sfall_arrays.cc
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include <vector>

#include "interpreter.h"
#include "sfall_lists.h"

namespace fallout {

Expand Down Expand Up @@ -647,6 +648,25 @@ ProgramValue ScanArray(ArrayId arrayId, const ProgramValue& val, Program* progra
return arr->ScanArray(val, program);
}

ArrayId ListAsArray(int type)
{
std::vector<Object*> objects;
sfall_lists_fill(type, objects);

int count = static_cast<int>(objects.size());
ArrayId arrayId = CreateTempArray(count, 0);
auto arr = get_array_by_id(arrayId);

// A little bit ugly and likely inefficient.
for (int index = 0; index < count; index++) {
arr->SetArray(ProgramValue { index },
ArrayElement { ProgramValue { objects[index] }, nullptr },
false);
}

return arrayId;
}

ArrayId StringSplit(const char* str, const char* split)
{
size_t splitLen = strlen(split);
Expand Down
1 change: 1 addition & 0 deletions src/sfall_arrays.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ void ResizeArray(ArrayId arrayId, int newLen);
void DeleteAllTempArrays();
int StackArray(const ProgramValue& key, const ProgramValue& val, Program* program);
ProgramValue ScanArray(ArrayId arrayId, const ProgramValue& val, Program* program);
ArrayId ListAsArray(int type);

ArrayId StringSplit(const char* str, const char* split);

Expand Down
72 changes: 41 additions & 31 deletions src/sfall_lists.cc
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
#include "sfall_lists.h"

#include <unordered_map>
#include <vector>

#include "object.h"
#include "scripts.h"
Expand Down Expand Up @@ -66,17 +65,50 @@ int sfallListsCreate(int listType)
int listId = _state->nextListId++;
List& list = _state->lists[listId];

if (listType == LIST_TILES) {
sfall_lists_fill(listType, list.objects);

return listId;
}

Object* sfallListsGetNext(int listId)
{
auto it = _state->lists.find(listId);
if (it != _state->lists.end()) {
List& list = it->second;
if (list.pos < list.objects.size()) {
return list.objects[list.pos++];
}
}

return nullptr;
}

void sfallListsDestroy(int listId)
{
auto it = _state->lists.find(listId);
if (it != _state->lists.end()) {
_state->lists.erase(it);
}
}

void sfall_lists_fill(int type, std::vector<Object*>& objects)
{
if (type == LIST_TILES) {
// For unknown reason this list type is not implemented in Sfall.
} else if (listType == LIST_SPATIAL) {
return;
}

objects.reserve(100);

if (type == LIST_SPATIAL) {
for (int elevation = 0; elevation < ELEVATION_COUNT; elevation++) {
Script* script = scriptGetFirstSpatialScript(elevation);
while (script != nullptr) {
Object* obj = script->owner;
if (obj == nullptr) {
obj = scriptGetSelf(script->program);
}
list.objects.push_back(obj);
objects.push_back(obj);
script = scriptGetNextSpatialScript();
}
}
Expand All @@ -89,46 +121,24 @@ int sfallListsCreate(int listType)
//
// As a small optimization |LIST_ALL| is handled separately since there
// is no need to check object type.
if (listType == LIST_ALL) {
if (type == LIST_ALL) {
Object* obj = objectFindFirst();
while (obj != nullptr) {
list.objects.push_back(obj);
objects.push_back(obj);
obj = objectFindNext();
}
} else {
Object* obj = objectFindFirst();
while (obj != nullptr) {
int objectType = PID_TYPE(obj->pid);
if (objectType < kObjectTypeToListTypeSize && kObjectTypeToListType[objectType] == listType) {
list.objects.push_back(obj);
if (objectType < kObjectTypeToListTypeSize
&& kObjectTypeToListType[objectType] == type) {
objects.push_back(obj);
}
obj = objectFindNext();
}
}
}

return listId;
}

Object* sfallListsGetNext(int listId)
{
auto it = _state->lists.find(listId);
if (it != _state->lists.end()) {
List& list = it->second;
if (list.pos < list.objects.size()) {
return list.objects[list.pos++];
}
}

return nullptr;
}

void sfallListsDestroy(int listId)
{
auto it = _state->lists.find(listId);
if (it != _state->lists.end()) {
_state->lists.erase(it);
}
}

} // namespace fallout
3 changes: 3 additions & 0 deletions src/sfall_lists.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
#ifndef FALLOUT_SFALL_LISTS_H_
#define FALLOUT_SFALL_LISTS_H_

#include <vector>

#include "obj_types.h"

namespace fallout {
Expand All @@ -22,6 +24,7 @@ void sfallListsExit();
int sfallListsCreate(int listType);
Object* sfallListsGetNext(int listId);
void sfallListsDestroy(int listId);
void sfall_lists_fill(int type, std::vector<Object*>& objects);

} // namespace fallout

Expand Down
9 changes: 9 additions & 0 deletions src/sfall_opcodes.cc
Original file line number Diff line number Diff line change
Expand Up @@ -556,6 +556,14 @@ static void op_force_encounter_with_flags(Program* program)
wmForceEncounter(map, flags);
}

// list_as_array
static void op_list_as_array(Program* program)
{
int type = programStackPopInteger(program);
int arrayId = ListAsArray(type);
programStackPushInteger(program, arrayId);
}

// atoi
static void opParseInt(Program* program)
{
Expand Down Expand Up @@ -953,6 +961,7 @@ void sfallOpcodesInit()
interpreterRegisterOpcode(0x8233, opTempArray);
interpreterRegisterOpcode(0x8234, opFixArray);
interpreterRegisterOpcode(0x8235, opStringSplit);
interpreterRegisterOpcode(0x8236, op_list_as_array);
interpreterRegisterOpcode(0x8237, opParseInt);
interpreterRegisterOpcode(0x8238, op_atof);
interpreterRegisterOpcode(0x8239, opScanArray);
Expand Down

0 comments on commit 4276727

Please sign in to comment.