it compiles

This commit is contained in:
Demur Rumed 2025-07-19 06:11:44 +00:00
commit 899d0d5356
6 changed files with 12730 additions and 58 deletions

View file

@ -229,6 +229,13 @@ add_custom_target(
DEPENDS ZAPD
)
add_custom_target(
CompileLogic
COMMAND ${Python3_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/soh/compile_logic.py ${CMAKE_CURRENT_SOURCE_DIR}/soh/soh/Enhancements/randomizer/logic.s ${CMAKE_CURRENT_SOURCE_DIR}/soh/soh/Enhancements/randomizer/location_access/generated.cpp
BYPRODUCTS ${CMAKE_CURRENT_SOURCE_DIR}/soh/soh/Enhancements/randomizer/location_access/generated.cpp
)
if(CMAKE_SYSTEM_NAME MATCHES "Linux")
find_package(ImageMagick COMPONENTS convert)
if (ImageMagick_FOUND)

View file

@ -2,8 +2,8 @@
from sys import argv
if len(argv) < 1:
print("expects input file")
if len(argv) < 2:
print("expects input file & output file")
exit()
class RR:
@ -72,9 +72,14 @@ class RR:
output(", ".join(map(self.to_cpp, ast[1:])))
output(")")
elif f in binOP:
output("(")
output(binOP[f].join(map(self.to_cpp, ast[1:])))
output(")")
if f == "==" and isinstance(ast[1], str) and ast[1].startswith("RSK_"):
output(f"{self.to_cpp(ast[1])}.Is({self.to_cpp(ast[2])})")
elif f == "!=" and isinstance(ast[1], str) and ast[1].startswith("RSK_"):
output(f"{self.to_cpp(ast[1])}.IsNot({self.to_cpp(ast[2])})")
else:
output("(")
output(binOP[f].join(map(self.to_cpp, ast[1:])))
output(")")
elif f == "not":
output("!")
output(self.to_cpp(ast[1]))
@ -87,23 +92,27 @@ class RR:
output(self.to_cpp(ast[3]))
output(")")
elif f.startswith("RSK_"):
output(f"ctx->GetOption(f{f})")
output(f"ctx->GetOption({f})")
if f in ("RSK_BIG_POE_COUNT", "RSK_TRIFORCE_HUNT_PIECES_REQUIRED"):
output(".Get()")
elif f.startswith("RT_"):
output(f"ctx->GetTrickOption(f{f})")
output(f"(bool)ctx->GetTrickOption({f})")
elif f == "IsDungeonVanilla":
output(f"ctx->GetDungeon(f{self.to_cpp(ast[1])})->IsVanilla()")
output(f"ctx->GetDungeon({self.to_cpp(ast[1])})->IsVanilla()")
elif f == "IsDungeonMQ":
output(f"ctx->GetDungeon(f{self.to_cpp(ast[1])})->IsMQ()")
output(f"ctx->GetDungeon({self.to_cpp(ast[1])})->IsMQ()")
elif f == "IsTrialSkipped":
output(f"ctx->GetTrial(f{self.to_cpp(ast[1])})->IsSkipped()")
output(f"ctx->GetTrial({self.to_cpp(ast[1])})->IsSkipped()")
elif f == "TriforcePiecesCollected":
output("gSaveContext.ship.quest.data.randomizer.triforcePiecesCollected")
elif f.startswith("HasProjectileAge"):
output(f.replace("HasProjectileAge", "HasProjectileAge::"))
output(f)
elif f in RANDO:
output(f"Rando::{f}")
elif f == "Here":
output(f"Here({self.name}, []{{return {self.to_cpp(ast[1])};}})")
elif f in ("MQSpiritSharedStatueRoom", "MQSpiritSharedBrokenWallRoom"):
output(f"{f}({self.to_cpp(ast[1])}, []{{return {self.to_cpp(ast[2])};}})")
elif f != "--":
if len(ast) != 1:
print("expected atom, got tree", ast)
@ -141,19 +150,17 @@ RANDO = {
}
FUNC = {
"MQSpiritSharedStatueRoom",
"MQSpiritSharedBrokenWallRoom",
"CanPlantBean",
"BothAges",
"ChildCanAccess",
"AdultCanAccess",
"HasAccessTo",
"CanBuyCheck",
}
logicFUNC = {
"BlueFire",
"CanBreakMudWalls",
"CanBuyCheck",
"HasItem",
"HasBossSoul",
"HasFireSource",
@ -225,7 +232,15 @@ RRs = []
active_rr = None
buf = ""
open_count = close_count = 0
for line in open(argv[1]):
mode = None
for line in open(argv[1], "r", encoding="ascii"):
line = line.strip()
if line == "::":
mode = None if mode == line else line
continue
if mode == "::":
RRs.append(line)
continue
if line.startswith("def "):
if open_count != close_count:
print("error parsing", line)
@ -236,7 +251,7 @@ for line in open(argv[1]):
open_count = close_count = 0
continue
if active_rr and not active_rr.ui_name:
active_rr.ui_name = line.strip()
active_rr.ui_name = line
continue
if not active_rr or line.startswith("--"):
continue
@ -245,12 +260,12 @@ for line in open(argv[1]):
buf += line
if open_count != close_count:
continue
if buf and buf.isspace(): continue
if not buf or buf.isspace():
continue
try:
thing, code = buf.split(None, 1)
code = code.strip()
except:
print("failed to parse line", buf)
print("failed to parse line", repr(buf))
continue
if thing.startswith("RR_"):
active_rr.exits.append((thing, code))
@ -265,7 +280,11 @@ for line in open(argv[1]):
result = []
output = result.append
for rr in RRs:
output(f"areaTable[{rr.name}] = Region(\"{rr.ui_name}\", {rr.scene}, {'true' if rr.timepass else 'false'}, {{','.join(rr.areas)}}, {{")
if isinstance(rr, str):
output(rr)
output("\n")
continue
output(f"areaTable[{rr.name}] = Region(\"{rr.ui_name}\", {rr.scene}, {'true' if rr.timepass else 'false'}, {{{','.join(rr.areas)}}}, {{")
if rr.events:
output("\n")
for name, code in rr.events:
@ -284,4 +303,6 @@ for rr in RRs:
output(f"\tEntrance({name}, []{{return {rr.gen(code)};}}),\n")
output("});\n")
print("".join(result))
source = "".join(result)
with open(argv[2], "w", encoding="ascii") as f:
f.write(source)

View file

@ -784,6 +784,7 @@ void RegionTable_Init() {
// locations which appear in both MQ and Vanilla dungeons don't get set in both areas.
areaTable.fill(Region("Invalid Region", SCENE_ID_MAX, {}, {}, {}));
#if 0
// clang-format off
areaTable[RR_ROOT] = Region("Root", SCENE_ID_MAX, TIME_DOESNT_PASS, {RA_LINKS_POCKET}, {
//Events
@ -856,43 +857,9 @@ void RegionTable_Init() {
});
// clang-format on
#endif
// Overworld
RegionTable_Init_KokiriForest();
RegionTable_Init_LostWoods();
RegionTable_Init_SacredForestMeadow();
RegionTable_Init_HyruleField();
RegionTable_Init_LakeHylia();
RegionTable_Init_LonLonRanch();
RegionTable_Init_Market();
RegionTable_Init_TempleOfTime();
RegionTable_Init_CastleGrounds();
RegionTable_Init_Kakariko();
RegionTable_Init_Graveyard();
RegionTable_Init_DeathMountainTrail();
RegionTable_Init_GoronCity();
RegionTable_Init_DeathMountainCrater();
RegionTable_Init_ZoraRiver();
RegionTable_Init_ZorasDomain();
RegionTable_Init_ZorasFountain();
RegionTable_Init_GerudoValley();
RegionTable_Init_GerudoFortress();
RegionTable_Init_ThievesHideout();
RegionTable_Init_HauntedWasteland();
RegionTable_Init_DesertColossus();
// Dungeons
RegionTable_Init_DekuTree();
RegionTable_Init_DodongosCavern();
RegionTable_Init_JabuJabusBelly();
RegionTable_Init_ForestTemple();
RegionTable_Init_FireTemple();
RegionTable_Init_WaterTemple();
RegionTable_Init_SpiritTemple();
RegionTable_Init_ShadowTemple();
RegionTable_Init_BottomOfTheWell();
RegionTable_Init_IceCavern();
RegionTable_Init_GerudoTrainingGround();
RegionTable_Init_GanonsCastle();
RegionTable_Init_Generated();
// Set parent regions
for (uint32_t i = RR_ROOT; i <= RR_GANONS_CASTLE; i++) {

View file

@ -245,6 +245,9 @@ Region* RegionTable(const RandomizerRegion regionKey);
std::vector<Rando::Entrance*> GetShuffleableEntrances(Rando::EntranceType type, bool onlyPrimary = true);
Rando::Entrance* GetEntrance(RandomizerRegion source, RandomizerRegion destination);
void RegionTable_Init_Generated();
#if 0
// Overworld
void RegionTable_Init_KokiriForest();
void RegionTable_Init_LostWoods();
@ -280,4 +283,5 @@ void RegionTable_Init_BottomOfTheWell();
void RegionTable_Init_IceCavern();
void RegionTable_Init_ThievesHideout();
void RegionTable_Init_GerudoTrainingGround();
void RegionTable_Init_GanonsCastle();
void RegionTable_Init_GanonsCastle();
#endif

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff