[goalc] add a build system (#704)

* add first attempt at build system

* fix stupid bug

* try again
This commit is contained in:
water111 2021-07-15 21:37:15 -04:00 committed by GitHub
parent 77667d9185
commit ef011f4fe8
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
33 changed files with 2208 additions and 72 deletions

View file

@ -72,7 +72,8 @@ Interpreter::Interpreter() {
{"string-ref", &Interpreter::eval_string_ref},
{"string-length", &Interpreter::eval_string_length},
{"string-append", &Interpreter::eval_string_append},
{"ash", &Interpreter::eval_ash}};
{"ash", &Interpreter::eval_ash},
{"symbol->string", &Interpreter::eval_symbol_to_string}};
string_to_type = {{"empty-list", ObjectType::EMPTY_LIST},
{"integer", ObjectType::INTEGER},
@ -90,6 +91,17 @@ Interpreter::Interpreter() {
load_goos_library();
}
/*!
* Add a user defined special form. The given function will be called with unevaluated arguments.
* Lookup from these forms occurs after special/builtin, but before any env lookups.
*/
void Interpreter::register_form(
const std::string& name,
const std::function<
Object(const Object&, Arguments&, const std::shared_ptr<EnvironmentObject>&)>& form) {
m_custom_forms[name] = form;
}
Interpreter::~Interpreter() {
// There are some circular references that prevent shared_ptrs from cleaning up if we
// don't do this.
@ -191,6 +203,19 @@ bool Interpreter::get_global_variable_by_name(const std::string& name, Object* d
return false;
}
/*!
* Sets the variable to the value. Overwrites an existing value, or creates a new global.
*/
void Interpreter::set_global_variable_by_name(const std::string& name, const Object& value) {
auto sym = SymbolObject::make_new(reader.symbolTable, name).as_symbol();
global_environment.as_env()->vars[sym] = value;
}
void Interpreter::set_global_variable_to_symbol(const std::string& name, const std::string& value) {
auto sym = SymbolObject::make_new(reader.symbolTable, value);
set_global_variable_by_name(name, sym);
}
/*!
* Get arguments being passed to a form. Don't evaluate them. There are two modes, "varargs" and
* "not varargs". With varargs enabled, any number of unnamed and named arguments can be given.
@ -525,6 +550,13 @@ Object Interpreter::eval_pair(const Object& obj, const std::shared_ptr<Environme
return ((*this).*(kv_b->second))(obj, args, env);
}
// try custom forms next
auto kv_u = m_custom_forms.find(head_sym->name);
if (kv_u != m_custom_forms.end()) {
Arguments args = get_args(obj, rest, make_varargs());
return (kv_u->second)(obj, args, env);
}
// try macros next
Object macro_obj;
if (try_symbol_lookup(head, env, &macro_obj) && macro_obj.is_macro()) {
@ -1586,10 +1618,17 @@ Object Interpreter::eval_ash(const Object& form,
if (sa >= 0 && sa < 64) {
return Object::make_integer(val << sa);
} else if (sa > -64) {
return Object::make_integer(val >> sa);
return Object::make_integer(val >> -sa);
} else {
throw_eval_error(form, fmt::format("Shift amount {} is out of range", sa));
return EmptyListObject::make_new();
}
}
Object Interpreter::eval_symbol_to_string(const Object& form,
Arguments& args,
const std::shared_ptr<EnvironmentObject>&) {
vararg_check(form, args, {ObjectType::SYMBOL}, {});
return StringObject::make_new(args.unnamed.at(0).as_symbol()->name);
}
} // namespace goos

View file

@ -19,6 +19,8 @@ class Interpreter {
void throw_eval_error(const Object& o, const std::string& err);
Object eval_with_rewind(const Object& obj, const std::shared_ptr<EnvironmentObject>& env);
bool get_global_variable_by_name(const std::string& name, Object* dest);
void set_global_variable_by_name(const std::string& name, const Object& value);
void set_global_variable_to_symbol(const std::string& name, const std::string& value);
Object eval(Object obj, const std::shared_ptr<EnvironmentObject>& env);
Object intern(const std::string& name);
void disable_printfs();
@ -36,6 +38,12 @@ class Interpreter {
const std::shared_ptr<EnvironmentObject>& env);
bool truthy(const Object& o);
void register_form(
const std::string& name,
const std::function<
Object(const Object&, Arguments&, const std::shared_ptr<EnvironmentObject>&)>& form);
void eval_args(Arguments* args, const std::shared_ptr<EnvironmentObject>& env);
Reader reader;
Object global_environment;
Object goal_env;
@ -59,7 +67,6 @@ class Interpreter {
const std::unordered_map<std::string, std::pair<bool, std::optional<ObjectType>>>& named);
Object eval_pair(const Object& o, const std::shared_ptr<EnvironmentObject>& env);
void eval_args(Arguments* args, const std::shared_ptr<EnvironmentObject>& env);
ArgumentSpec parse_arg_spec(const Object& form, Object& rest);
Object quasiquote_helper(const Object& form, const std::shared_ptr<EnvironmentObject>& env);
@ -198,6 +205,9 @@ class Interpreter {
Object eval_ash(const Object& form,
Arguments& args,
const std::shared_ptr<EnvironmentObject>& env);
Object eval_symbol_to_string(const Object& form,
Arguments& args,
const std::shared_ptr<EnvironmentObject>& env);
// specials
Object eval_define(const Object& form,
@ -239,6 +249,11 @@ class Interpreter {
Arguments& args,
const std::shared_ptr<EnvironmentObject>& env)>
builtin_forms;
std::unordered_map<
std::string,
std::function<Object(const Object&, Arguments&, const std::shared_ptr<EnvironmentObject>&)>>
m_custom_forms;
std::unordered_map<std::string,
Object (Interpreter::*)(const Object& form,
const Object& rest,

View file

@ -580,6 +580,7 @@ std::string ObjectFileDB::process_tpages() {
if (tpage_dir_count == 0) {
lg::warn("Did not find tpage-dir.");
return {};
}
lg::info("Processed {} / {} textures {:.2f}% in {:.2f} ms", success, total,
@ -612,6 +613,9 @@ std::string ObjectFileDB::process_game_text_files() {
lg::info("Processed {} text files ({} strings, {} characters) in {:.2f} ms", file_count,
string_count, char_count, timer.getMs());
if (text_by_language_by_id.empty()) {
return {};
}
return write_game_text(text_by_language_by_id);
}

View file

@ -55,7 +55,7 @@
"hexdump_code": false,
"hexdump_data": false,
// dump raw obj files
"dump_objs": false,
"dump_objs": true,
// print control flow graph
"print_cfgs": false,

View file

@ -100,18 +100,24 @@ int main(int argc, char** argv) {
if (config.process_game_text) {
auto result = db.process_game_text_files();
if (!result.empty()) {
file_util::write_text_file(file_util::get_file_path({"assets", "game_text.txt"}), result);
}
}
if (config.process_tpages) {
auto result = db.process_tpages();
if (!result.empty()) {
file_util::write_text_file(file_util::get_file_path({"assets", "tpage-dir.txt"}), result);
}
}
if (config.process_game_count) {
auto result = db.process_game_count_file();
if (!result.empty()) {
file_util::write_text_file(file_util::get_file_path({"assets", "game_count.txt"}), result);
}
}
lg::info("Disassembly has completed successfully.");
return 0;

View file

@ -54,7 +54,7 @@ void Loop(std::function<bool()> f) {
// exit if display window was closed
if (glfwWindowShouldClose(Display::display)) {
// Display::KillDisplay(Display::display);
MasterExit = 1;
MasterExit = 2;
}
}
}

295
goal_src/dgos/engine.gd Normal file
View file

@ -0,0 +1,295 @@
("ENGINE.CGO"
("types-h.o" "types-h")
("vu1-macros.o" "vu1-macros")
;; the "math" section
("math.o" "math")
("vector-h.o" "vector-h")
("gravity-h.o" "gravity-h")
("bounding-box-h.o" "bounding-box-h")
("matrix-h.o" "matrix-h")
("quaternion-h.o" "quaternion-h")
("euler-h.o" "euler-h")
("transform-h.o" "transform-h")
("geometry-h.o" "geometry-h")
("trigonometry-h.o" "trigonometry-h")
("transformq-h.o" "transformq-h")
("bounding-box.o" "bounding-box")
("matrix.o" "matrix")
("transform.o" "transform")
("quaternion.o" "quaternion")
("euler.o" "euler")
("geometry.o" "geometry")
("trigonometry.o" "trigonometry")
("gsound-h.o" "gsound-h")
("timer-h.o" "timer-h")
("timer.o" "timer")
("vif-h.o" "vif-h")
("dma-h.o" "dma-h")
("video-h.o" "video-h")
("vu1-user-h.o" "vu1-user-h")
("dma.o" "dma")
("dma-buffer.o" "dma-buffer")
("dma-bucket.o" "dma-bucket")
("dma-disasm.o" "dma-disasm")
("pad.o" "pad")
("gs.o" "gs")
("display-h.o" "display-h")
("vector.o" "vector")
("file-io.o" "file-io")
("loader-h.o" "loader-h")
("texture-h.o" "texture-h")
("level-h.o" "level-h")
("math-camera-h.o" "math-camera-h")
("math-camera.o" "math-camera")
("font-h.o" "font-h")
("decomp-h.o" "decomp-h")
("display.o" "display")
("connect.o" "connect")
("text-h.o" "text-h")
("settings-h.o" "settings-h")
("capture.o" "capture")
("memory-usage-h.o" "memory-usage-h")
("texture.o" "texture")
("main-h.o" "main-h")
("mspace-h.o" "mspace-h")
("drawable-h.o" "drawable-h")
("drawable-group-h.o" "drawable-group-h")
("drawable-inline-array-h.o" "drawable-inline-array-h")
("draw-node-h.o" "draw-node-h")
("drawable-tree-h.o" "drawable-tree-h")
("drawable-actor-h.o" "drawable-actor-h")
("drawable-ambient-h.o" "drawable-ambient-h")
("game-task-h.o" "game-task-h")
("hint-control-h.o" "hint-control-h")
("generic-h.o" "generic-h")
("lights-h.o" "lights-h")
("ocean-h.o" "ocean-h")
("ocean-trans-tables.o" "ocean-trans-tables")
("ocean-tables.o" "ocean-tables")
("ocean-frames.o" "ocean-frames")
("sky-h.o" "sky-h")
("mood-h.o" "mood-h")
("time-of-day-h.o" "time-of-day-h")
("art-h.o" "art-h")
("generic-vu1-h.o" "generic-vu1-h")
("merc-h.o" "merc-h")
("generic-merc-h.o" "generic-merc-h")
("generic-tie-h.o" "generic-tie-h")
("generic-work-h.o" "generic-work-h")
("shadow-cpu-h.o" "shadow-cpu-h")
("shadow-vu1-h.o" "shadow-vu1-h")
("memcard-h.o" "memcard-h")
("game-info-h.o" "game-info-h")
("wind-h.o" "wind-h")
("prototype-h.o" "prototype-h")
("joint-h.o" "joint-h")
("bones-h.o" "bones-h")
("engines.o" "engines")
("res-h.o" "res-h")
("res.o" "res")
("lights.o" "lights")
("dynamics-h.o" "dynamics-h")
("surface-h.o" "surface-h")
("pat-h.o" "pat-h")
("fact-h.o" "fact-h")
("aligner-h.o" "aligner-h")
("game-h.o" "game-h")
("generic-obs-h.o" "generic-obs-h")
("pov-camera-h.o" "pov-camera-h")
("sync-info-h.o" "sync-info-h")
("smush-control-h.o" "smush-control-h")
("trajectory-h.o" "trajectory-h")
("debug-h.o" "debug-h")
("joint-mod-h.o" "joint-mod-h")
("collide-func-h.o" "collide-func-h")
("collide-mesh-h.o" "collide-mesh-h")
("collide-shape-h.o" "collide-shape-h")
("collide-target-h.o" "collide-target-h")
("collide-touch-h.o" "collide-touch-h")
("collide-edge-grab-h.o" "collide-edge-grab-h")
("process-drawable-h.o" "process-drawable-h")
("effect-control-h.o" "effect-control-h")
("collide-frag-h.o" "collide-frag-h")
("projectiles-h.o" "projectiles-h")
("target-h.o" "target-h")
("depth-cue-h.o" "depth-cue-h")
("stats-h.o" "stats-h")
("bsp-h.o" "bsp-h")
("collide-cache-h.o" "collide-cache-h")
("collide-h.o" "collide-h")
("shrubbery-h.o" "shrubbery-h")
("tie-h.o" "tie-h")
("tfrag-h.o" "tfrag-h")
("background-h.o" "background-h")
("subdivide-h.o" "subdivide-h")
("entity-h.o" "entity-h")
("sprite-h.o" "sprite-h")
("shadow-h.o" "shadow-h")
("eye-h.o" "eye-h")
("sparticle-launcher-h.o" "sparticle-launcher-h")
("sparticle-h.o" "sparticle-h")
("actor-link-h.o" "actor-link-h")
("camera-h.o" "camera-h")
("cam-debug-h.o" "cam-debug-h")
("cam-interface-h.o" "cam-interface-h")
("cam-update-h.o" "cam-update-h")
("assert-h.o" "assert-h")
("hud-h.o" "hud-h")
("progress-h.o" "progress-h")
("rpc-h.o" "rpc-h")
("path-h.o" "path-h")
("navigate-h.o" "navigate-h")
("load-dgo.o" "load-dgo")
("ramdisk.o" "ramdisk")
("gsound.o" "gsound")
("transformq.o" "transformq")
("collide-func.o" "collide-func")
("joint.o" "joint")
("cylinder.o" "cylinder")
("wind.o" "wind")
("bsp.o" "bsp")
("subdivide.o" "subdivide")
("sprite.o" "sprite")
("sprite-distort.o" "sprite-distort")
("debug-sphere.o" "debug-sphere")
("debug.o" "debug")
("merc-vu1.o" "merc-vu1")
("merc-blend-shape.o" "merc-blend-shape")
("merc.o" "merc")
("ripple.o" "ripple")
("bones.o" "bones")
("generic-vu0.o" "generic-vu0")
("generic.o" "generic")
("generic-vu1.o" "generic-vu1")
("generic-effect.o" "generic-effect")
("generic-merc.o" "generic-merc")
("generic-tie.o" "generic-tie")
("shadow-cpu.o" "shadow-cpu")
("shadow-vu1.o" "shadow-vu1")
("depth-cue.o" "depth-cue")
("font.o" "font")
("decomp.o" "decomp")
("background.o" "background")
("draw-node.o" "draw-node")
("shrubbery.o" "shrubbery")
("shrub-work.o" "shrub-work")
("tfrag-near.o" "tfrag-near")
("tfrag.o" "tfrag")
("tfrag-methods.o" "tfrag-methods")
("tfrag-work.o" "tfrag-work")
("tie.o" "tie")
("tie-near.o" "tie-near")
("tie-work.o" "tie-work")
("tie-methods.o" "tie-methods")
("sync-info.o" "sync-info")
("trajectory.o" "trajectory")
("sparticle-launcher.o" "sparticle-launcher")
("sparticle.o" "sparticle")
("entity-table.o" "entity-table")
("loader.o" "loader")
("task-control-h.o" "task-control-h")
("game-info.o" "game-info")
("game-save.o" "game-save")
("settings.o" "settings")
("mood-tables.o" "mood-tables")
("mood.o" "mood")
("weather-part.o" "weather-part")
("time-of-day.o" "time-of-day")
("sky-utils.o" "sky-utils")
("sky.o" "sky")
("sky-tng.o" "sky-tng")
("load-boundary-h.o" "load-boundary-h")
("load-boundary.o" "load-boundary")
("load-boundary-data.o" "load-boundary-data")
("level-info.o" "level-info")
("level.o" "level")
("text.o" "text")
("collide-probe.o" "collide-probe")
("collide-frag.o" "collide-frag")
("collide-mesh.o" "collide-mesh")
("collide-touch.o" "collide-touch")
("collide-edge-grab.o" "collide-edge-grab")
("collide-shape.o" "collide-shape")
("collide-shape-rider.o" "collide-shape-rider")
("collide.o" "collide")
("collide-planes.o" "collide-planes")
("merc-death.o" "merc-death")
("water-h.o" "water-h")
("camera.o" "camera")
("cam-interface.o" "cam-interface")
("cam-master.o" "cam-master")
("cam-states.o" "cam-states")
("cam-states-dbg.o" "cam-states-dbg")
("cam-combiner.o" "cam-combiner")
("cam-update.o" "cam-update")
("vol-h.o" "vol-h")
("cam-layout.o" "cam-layout")
("cam-debug.o" "cam-debug")
("cam-start.o" "cam-start")
("process-drawable.o" "process-drawable")
("hint-control.o" "hint-control")
("ambient.o" "ambient")
("assert.o" "assert")
("generic-obs.o" "generic-obs")
("target-util.o" "target-util")
("target-part.o" "target-part")
("collide-reaction-target.o" "collide-reaction-target")
("logic-target.o" "logic-target")
("sidekick.o" "sidekick")
("voicebox.o" "voicebox")
("target-handler.o" "target-handler")
("target.o" "target")
("target2.o" "target2")
("target-death.o" "target-death")
("menu.o" "menu")
("drawable.o" "drawable")
("drawable-group.o" "drawable-group")
("drawable-inline-array.o" "drawable-inline-array")
("drawable-tree.o" "drawable-tree")
("prototype.o" "prototype")
("main-collide.o" "main-collide")
("video.o" "video")
("main.o" "main")
("collide-cache.o" "collide-cache")
("relocate.o" "relocate")
("memory-usage.o" "memory-usage")
("entity.o" "entity")
("path.o" "path")
("vol.o" "vol")
("navigate.o" "navigate")
("aligner.o" "aligner")
("effect-control.o" "effect-control")
("water.o" "water")
("collectables-part.o" "collectables-part")
("collectables.o" "collectables")
("task-control.o" "task-control")
("process-taskable.o" "process-taskable")
("pov-camera.o" "pov-camera")
("powerups.o" "powerups")
("crates.o" "crates")
("hud.o" "hud")
("hud-classes.o" "hud-classes")
("progress-static.o" "progress-static")
("progress-part.o" "progress-part")
("progress-draw.o" "progress-draw")
("progress.o" "progress")
("credits.o" "credits")
("projectiles.o" "projectiles")
("ocean.o" "ocean")
("ocean-vu0.o" "ocean-vu0")
("ocean-texture.o" "ocean-texture")
("ocean-mid.o" "ocean-mid")
("ocean-transition.o" "ocean-transition")
("ocean-near.o" "ocean-near")
("shadow.o" "shadow")
("eye.o" "eye")
("glist-h.o" "glist-h")
("glist.o" "glist")
("anim-tester.o" "anim-tester")
("viewer.o" "viewer")
("part-tester.o" "part-tester")
("default-menu.o" "default-menu")
)

330
goal_src/dgos/game.gd Normal file
View file

@ -0,0 +1,330 @@
("GAME.CGO"
("types-h.o" "types-h")
("vu1-macros.o" "vu1-macros")
("math.o" "math")
("vector-h.o" "vector-h")
("gravity-h.o" "gravity-h")
("bounding-box-h.o" "bounding-box-h")
("matrix-h.o" "matrix-h")
("quaternion-h.o" "quaternion-h")
("euler-h.o" "euler-h")
("transform-h.o" "transform-h")
("geometry-h.o" "geometry-h")
("trigonometry-h.o" "trigonometry-h")
("transformq-h.o" "transformq-h")
("bounding-box.o" "bounding-box")
("matrix.o" "matrix")
("transform.o" "transform")
("quaternion.o" "quaternion")
("euler.o" "euler")
("geometry.o" "geometry")
("trigonometry.o" "trigonometry")
("gsound-h.o" "gsound-h")
("timer-h.o" "timer-h")
("timer.o" "timer")
("vif-h.o" "vif-h")
("dma-h.o" "dma-h")
("video-h.o" "video-h")
("vu1-user-h.o" "vu1-user-h")
("dma.o" "dma")
("dma-buffer.o" "dma-buffer")
("dma-bucket.o" "dma-bucket")
("dma-disasm.o" "dma-disasm")
("pad.o" "pad")
("gs.o" "gs")
("display-h.o" "display-h")
("vector.o" "vector")
("file-io.o" "file-io")
("loader-h.o" "loader-h")
("texture-h.o" "texture-h")
("level-h.o" "level-h")
("math-camera-h.o" "math-camera-h")
("math-camera.o" "math-camera")
("font-h.o" "font-h")
("decomp-h.o" "decomp-h")
("display.o" "display")
("connect.o" "connect")
("text-h.o" "text-h")
("settings-h.o" "settings-h")
("capture.o" "capture")
("memory-usage-h.o" "memory-usage-h")
("texture.o" "texture")
("main-h.o" "main-h")
("mspace-h.o" "mspace-h")
("drawable-h.o" "drawable-h")
("drawable-group-h.o" "drawable-group-h")
("drawable-inline-array-h.o" "drawable-inline-array-h")
("draw-node-h.o" "draw-node-h")
("drawable-tree-h.o" "drawable-tree-h")
("drawable-actor-h.o" "drawable-actor-h")
("drawable-ambient-h.o" "drawable-ambient-h")
("game-task-h.o" "game-task-h")
("hint-control-h.o" "hint-control-h")
("generic-h.o" "generic-h")
("lights-h.o" "lights-h")
("ocean-h.o" "ocean-h")
("ocean-trans-tables.o" "ocean-trans-tables")
("ocean-tables.o" "ocean-tables")
("ocean-frames.o" "ocean-frames")
("sky-h.o" "sky-h")
("mood-h.o" "mood-h")
("time-of-day-h.o" "time-of-day-h")
("art-h.o" "art-h")
("generic-vu1-h.o" "generic-vu1-h")
("merc-h.o" "merc-h")
("generic-merc-h.o" "generic-merc-h")
("generic-tie-h.o" "generic-tie-h")
("generic-work-h.o" "generic-work-h")
("shadow-cpu-h.o" "shadow-cpu-h")
("shadow-vu1-h.o" "shadow-vu1-h")
("memcard-h.o" "memcard-h")
("game-info-h.o" "game-info-h")
("wind-h.o" "wind-h")
("prototype-h.o" "prototype-h")
("joint-h.o" "joint-h")
("bones-h.o" "bones-h")
("engines.o" "engines")
("res-h.o" "res-h")
("res.o" "res")
("lights.o" "lights")
("dynamics-h.o" "dynamics-h")
("surface-h.o" "surface-h")
("pat-h.o" "pat-h")
("fact-h.o" "fact-h")
("aligner-h.o" "aligner-h")
("game-h.o" "game-h")
("generic-obs-h.o" "generic-obs-h")
("pov-camera-h.o" "pov-camera-h")
("sync-info-h.o" "sync-info-h")
("smush-control-h.o" "smush-control-h")
("trajectory-h.o" "trajectory-h")
("debug-h.o" "debug-h")
("joint-mod-h.o" "joint-mod-h")
("collide-func-h.o" "collide-func-h")
("collide-mesh-h.o" "collide-mesh-h")
("collide-shape-h.o" "collide-shape-h")
("collide-target-h.o" "collide-target-h")
("collide-touch-h.o" "collide-touch-h")
("collide-edge-grab-h.o" "collide-edge-grab-h")
("process-drawable-h.o" "process-drawable-h")
("effect-control-h.o" "effect-control-h")
("collide-frag-h.o" "collide-frag-h")
("projectiles-h.o" "projectiles-h")
("target-h.o" "target-h")
("depth-cue-h.o" "depth-cue-h")
("stats-h.o" "stats-h")
("bsp-h.o" "bsp-h")
("collide-cache-h.o" "collide-cache-h")
("collide-h.o" "collide-h")
("shrubbery-h.o" "shrubbery-h")
("tie-h.o" "tie-h")
("tfrag-h.o" "tfrag-h")
("background-h.o" "background-h")
("subdivide-h.o" "subdivide-h")
("entity-h.o" "entity-h")
("sprite-h.o" "sprite-h")
("shadow-h.o" "shadow-h")
("eye-h.o" "eye-h")
("sparticle-launcher-h.o" "sparticle-launcher-h")
("sparticle-h.o" "sparticle-h")
("actor-link-h.o" "actor-link-h")
("camera-h.o" "camera-h")
("cam-debug-h.o" "cam-debug-h")
("cam-interface-h.o" "cam-interface-h")
("cam-update-h.o" "cam-update-h")
("assert-h.o" "assert-h")
("hud-h.o" "hud-h")
("progress-h.o" "progress-h")
("rpc-h.o" "rpc-h")
("path-h.o" "path-h")
("navigate-h.o" "navigate-h")
("load-dgo.o" "load-dgo")
("ramdisk.o" "ramdisk")
("gsound.o" "gsound")
("transformq.o" "transformq")
("collide-func.o" "collide-func")
("joint.o" "joint")
("cylinder.o" "cylinder")
("wind.o" "wind")
("bsp.o" "bsp")
("subdivide.o" "subdivide")
("sprite.o" "sprite")
("sprite-distort.o" "sprite-distort")
("debug-sphere.o" "debug-sphere")
("debug.o" "debug")
("merc-vu1.o" "merc-vu1")
("merc-blend-shape.o" "merc-blend-shape")
("merc.o" "merc")
("ripple.o" "ripple")
("bones.o" "bones")
("generic-vu0.o" "generic-vu0")
("generic.o" "generic")
("generic-vu1.o" "generic-vu1")
("generic-effect.o" "generic-effect")
("generic-merc.o" "generic-merc")
("generic-tie.o" "generic-tie")
("shadow-cpu.o" "shadow-cpu")
("shadow-vu1.o" "shadow-vu1")
("depth-cue.o" "depth-cue")
("font.o" "font")
("decomp.o" "decomp")
("background.o" "background")
("draw-node.o" "draw-node")
("shrubbery.o" "shrubbery")
("shrub-work.o" "shrub-work")
("tfrag-near.o" "tfrag-near")
("tfrag.o" "tfrag")
("tfrag-methods.o" "tfrag-methods")
("tfrag-work.o" "tfrag-work")
("tie.o" "tie")
("tie-near.o" "tie-near")
("tie-work.o" "tie-work")
("tie-methods.o" "tie-methods")
("sync-info.o" "sync-info")
("trajectory.o" "trajectory")
("sparticle-launcher.o" "sparticle-launcher")
("sparticle.o" "sparticle")
("entity-table.o" "entity-table")
("loader.o" "loader")
("task-control-h.o" "task-control-h")
("game-info.o" "game-info")
("game-save.o" "game-save")
("settings.o" "settings")
("mood-tables.o" "mood-tables")
("mood.o" "mood")
("weather-part.o" "weather-part")
("time-of-day.o" "time-of-day")
("sky-utils.o" "sky-utils")
("sky.o" "sky")
("sky-tng.o" "sky-tng")
("load-boundary-h.o" "load-boundary-h")
("load-boundary.o" "load-boundary")
("load-boundary-data.o" "load-boundary-data")
("level-info.o" "level-info")
("level.o" "level")
("text.o" "text")
("collide-probe.o" "collide-probe")
("collide-frag.o" "collide-frag")
("collide-mesh.o" "collide-mesh")
("collide-touch.o" "collide-touch")
("collide-edge-grab.o" "collide-edge-grab")
("collide-shape.o" "collide-shape")
("collide-shape-rider.o" "collide-shape-rider")
("collide.o" "collide")
("collide-planes.o" "collide-planes")
("merc-death.o" "merc-death")
("water-h.o" "water-h")
("camera.o" "camera")
("cam-interface.o" "cam-interface")
("cam-master.o" "cam-master")
("cam-states.o" "cam-states")
("cam-states-dbg.o" "cam-states-dbg")
("cam-combiner.o" "cam-combiner")
("cam-update.o" "cam-update")
("vol-h.o" "vol-h")
("cam-layout.o" "cam-layout")
("cam-debug.o" "cam-debug")
("cam-start.o" "cam-start")
("process-drawable.o" "process-drawable")
("hint-control.o" "hint-control")
("ambient.o" "ambient")
("assert.o" "assert")
("generic-obs.o" "generic-obs")
("target-util.o" "target-util")
("target-part.o" "target-part")
("collide-reaction-target.o" "collide-reaction-target")
("logic-target.o" "logic-target")
("sidekick.o" "sidekick")
("voicebox.o" "voicebox")
("target-handler.o" "target-handler")
("target.o" "target")
("target2.o" "target2")
("target-death.o" "target-death")
("menu.o" "menu")
("drawable.o" "drawable")
("drawable-group.o" "drawable-group")
("drawable-inline-array.o" "drawable-inline-array")
("drawable-tree.o" "drawable-tree")
("prototype.o" "prototype")
("main-collide.o" "main-collide")
("video.o" "video")
("main.o" "main")
("collide-cache.o" "collide-cache")
("relocate.o" "relocate")
("memory-usage.o" "memory-usage")
("entity.o" "entity")
("path.o" "path")
("vol.o" "vol")
("navigate.o" "navigate")
("aligner.o" "aligner")
("effect-control.o" "effect-control")
("water.o" "water")
("collectables-part.o" "collectables-part")
("collectables.o" "collectables")
("task-control.o" "task-control")
("process-taskable.o" "process-taskable")
("pov-camera.o" "pov-camera")
("powerups.o" "powerups")
("crates.o" "crates")
("hud.o" "hud")
("hud-classes.o" "hud-classes")
("progress-static.o" "progress-static")
("progress-part.o" "progress-part")
("progress-draw.o" "progress-draw")
("progress.o" "progress")
("credits.o" "credits")
("projectiles.o" "projectiles")
("ocean.o" "ocean")
("ocean-vu0.o" "ocean-vu0")
("ocean-texture.o" "ocean-texture")
("ocean-mid.o" "ocean-mid")
("ocean-transition.o" "ocean-transition")
("ocean-near.o" "ocean-near")
("shadow.o" "shadow")
("eye.o" "eye")
("glist-h.o" "glist-h")
("glist.o" "glist")
("anim-tester.o" "anim-tester")
("viewer.o" "viewer")
("part-tester.o" "part-tester")
("default-menu.o" "default-menu")
("dir-tpages.go" "dir-tpages")
("tpage-463.go" "tpage-463")
("tpage-2.go" "tpage-2")
("tpage-880.go" "tpage-880")
("tpage-256.go" "tpage-256")
("tpage-1278.go" "tpage-1278")
("texture-upload.o" "texture-upload")
("tpage-1032.go" "tpage-1032")
("tpage-62.go" "tpage-62")
("tpage-1532.go" "tpage-1532")
("fuel-cell-ag.go" "fuel-cell")
("money-ag.go" "money")
("buzzer-ag.go" "buzzer")
("ecovalve-ag-ART-GAME.go" "ecovalve")
("crate-ag.go" "crate")
("speaker-ag.go" "speaker")
("fuelcell-naked-ag.go" "fuelcell-naked")
("eichar-ag.go" "eichar")
("sidekick-ag.go" "sidekick")
("deathcam-ag.go" "deathcam")
("game-cnt.go" "game-cnt")
("rigid-body-h.o" "rigid-body-h")
("water-anim.o" "water-anim")
("dark-eco-pool.o" "dark-eco-pool")
("rigid-body.o" "rigid-body")
("nav-enemy-h.o" "nav-enemy-h")
("nav-enemy.o" "nav-enemy")
("baseplat.o" "baseplat")
("basebutton.o" "basebutton")
("tippy.o" "tippy")
("joint-exploder.o" "joint-exploder")
("babak.o" "babak")
("sharkey.o" "sharkey")
("orb-cache.o" "orb-cache")
("plat.o" "plat")
("plat-button.o" "plat-button")
("plat-eco.o" "plat-eco")
("ropebridge.o" "ropebridge")
("ticky.o" "ticky")
)

10
goal_src/dgos/kernel.gd Normal file
View file

@ -0,0 +1,10 @@
("KERNEL.CGO"
("gcommon.o" "gcommon")
("gstring-h.o" "gstring-h")
("gkernel-h.o" "gkernel-h")
("gkernel.o" "gkernel")
("pskernel.o" "pskernel")
("gstring.o" "gstring")
("dgo-h.o" "dgo-h")
("gstate.o" "gstate")
)

57
goal_src/dgos/vi1.gd Normal file
View file

@ -0,0 +1,57 @@
("VI1.DGO"
("villagep-obs.o" "villagep-obs")
("oracle.o" "oracle")
("farmer.o" "farmer")
("explorer.o" "explorer")
("assistant.o" "assistant")
("sage.o" "sage")
("yakow.o" "yakow")
("village-obs-VI1.o" "village-obs")
("fishermans-boat.o" "fishermans-boat")
("village1-part.o" "village1-part")
("village1-part2.o" "village1-part2")
("sequence-a-village1.o" "sequence-a-village1")
("tpage-398.go" "tpage-398")
("tpage-400.go" "tpage-400")
("tpage-399.go" "tpage-399")
("tpage-401.go" "tpage-401")
("tpage-1470.go" "tpage-1470")
("assistant-ag.go" "assistant")
("evilplant-ag.go" "evilplant")
("explorer-ag.go" "explorer")
("farmer-ag.go" "farmer")
("fishermans-boat-ag.go" "fishermans-boat")
("hutlamp-ag.go" "hutlamp")
("mayorgears-ag.go" "mayorgears")
("medres-beach-ag.go" "medres-beach")
("medres-beach1-ag.go" "medres-beach1")
("medres-beach2-ag.go" "medres-beach2")
("medres-beach3-ag.go" "medres-beach3")
("medres-jungle-ag.go" "medres-jungle")
("medres-jungle1-ag.go" "medres-jungle1")
("medres-jungle2-ag.go" "medres-jungle2")
("medres-misty-ag.go" "medres-misty")
("medres-training-ag.go" "medres-training")
("medres-village11-ag.go" "medres-village11")
("medres-village12-ag.go" "medres-village12")
("medres-village13-ag.go" "medres-village13")
("oracle-ag-VI1.go" "oracle")
("orb-cache-top-ag-VI1.go" "orb-cache-top")
("reflector-middle-ag.go" "reflector-middle")
("revcycle-ag.go" "revcycle")
("revcycleprop-ag.go" "revcycleprop")
("ropebridge-32-ag.go" "ropebridge-32")
("sage-ag.go" "sage")
("sagesail-ag.go" "sagesail")
("sharkey-ag-VI1.go" "sharkey")
("villa-starfish-ag.go" "villa-starfish")
("village-cam-ag-VI1.go" "village-cam")
("village1cam-ag.go" "village1cam")
("warp-gate-switch-ag-VI1-VI3.go" "warp-gate-switch")
("warpgate-ag.go" "warpgate")
("water-anim-village1-ag.go" "water-anim-village1")
("windmill-sail-ag.go" "windmill-sail")
("windspinner-ag.go" "windspinner")
("yakow-ag.go" "yakow")
("village1-vis.go" "village1-vis")
)

View file

@ -189,6 +189,8 @@
(s3-1 s2-1 (-> *temp-string* data) load-status heap 0)
)
)
(format 0 "loaded text ~A~%" *common-text*)
(format 0 "~A~%" (lookup-text! *common-text* (game-text-id continue-without-saving) #f))
)
(if (<= (the-as int (-> curr-text value)) 0)
(set! (-> curr-text value) (the-as object #f))
@ -196,6 +198,7 @@
)
(set! v0-2 0)
(label cfg-27)
v0-2
)

626
goal_src/game.gp Normal file
View file

@ -0,0 +1,626 @@
;;-*-Lisp-*-
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Jak 1 Project File
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; This file sets up the OpenGOAL build system for Jak 1.
;;;;;;;;;;;;;;;;;;;;;;;
;; Build system macros
;;;;;;;;;;;;;;;;;;;;;;;
;; use defmacro to define goos macros.
(define defmacro defsmacro)
(define defun desfun)
(defun gc-file->o-file (filename)
"Get the name of the object file for the given GOAL (*.gc) source file."
(string-append "out/obj/" (stem filename) ".o")
)
(defmacro goal-src (src-file &rest deps)
"Add a GOAL source file with the given dependencies"
`(defstep :in ,(string-append "goal_src/" src-file)
;; use goal compiler
:tool 'goalc
;; will output the obj file
:out '(,(gc-file->o-file src-file))
;; dependencies are the obj files
:dep '(,@(apply gc-file->o-file deps))
)
)
(defun make-src-sequence-elt (current previous prefix)
"Helper for goal-src-sequence"
`(defstep :in ,(string-append "goal_src/" prefix current)
:tool 'goalc
:out '(,(gc-file->o-file current))
:dep '(#|"iso/KERNEL.CGO"|#
,(gc-file->o-file previous))
)
)
(defmacro goal-src-sequence (prefix &key (deps '()) &rest sequence)
"Add a sequence of GOAL files (each depending on the previous) in the given directory,
with all depending on the given deps."
(let* ((first-thing `(goal-src ,(string-append prefix (first sequence)) ,@deps))
(result (cons first-thing '()))
(iter result))
(let ((prev (first sequence))
(in-iter (rest sequence)))
(while (not (null? in-iter))
;; (fmt #t "{} dep on {}\n" (first in-iter) prev)
(let ((next (make-src-sequence-elt (first in-iter) prev prefix)))
(set-cdr! iter (cons next '()))
(set! iter (cdr iter))
)
(set! prev (car in-iter))
(set! in-iter (cdr in-iter))
)
)
`(begin ,@result)
)
)
(defmacro cgo (output-name desc-file-name &rest objs)
"Add a CGO with the given output name (in out/iso) and input name (in goal_src/dgos)"
`(defstep :in ,(string-append "goal_src/dgos/" desc-file-name)
:tool 'dgo
:out '(,(string-append "out/iso/" output-name))
)
)
(defun tpage-name (id)
(fmt #f "tpage-{}.go" id)
)
(defmacro copy-texture (tpage-id)
`(defstep :in ,(string-append "decompiler_out/raw_obj/" (tpage-name tpage-id))
:tool 'copy
:out '(,(string-append "out/obj/" (tpage-name tpage-id)))
)
)
(defmacro copy-textures (&rest ids)
`(begin
,@(apply (lambda (x) `(copy-texture ,x)) ids)
)
)
(defmacro copy-go (name)
`(defstep :in ,(string-append "decompiler_out/raw_obj/" name ".go")
:tool 'copy
:out '(,(string-append "out/obj/" name ".go"))
)
)
(defmacro copy-gos (&rest gos)
`(begin
,@(apply (lambda (x) `(copy-go ,x)) gos)
)
)
(defmacro group (name &rest stuff)
`(defstep :in ""
:tool 'group
:out '(,(string-append "GROUP:" name))
:dep '(,@stuff))
)
;;;;;;;;;;;;;;;;;;;;;;
;; CGO's
;;;;;;;;;;;;;;;;;;;;;;
(cgo "KERNEL.CGO" "kernel.gd")
(cgo "ENGINE.CGO" "engine.gd")
(cgo "GAME.CGO" "game.gd")
;;;;;;;;;;;;;;;;;
;; GOAL Kernel
;;;;;;;;;;;;;;;;;
;; These are set up with proper dependencies
(goal-src "kernel/gcommon.gc")
(goal-src "kernel/gstring-h.gc")
(goal-src "kernel/gkernel-h.gc"
"gcommon"
"gstring-h")
(goal-src "kernel/gkernel.gc"
"gkernel-h")
(goal-src "kernel/pskernel.gc"
"gcommon"
"gkernel-h")
(goal-src "kernel/gstring.gc"
"gcommon"
"gstring-h")
(goal-src "kernel/dgo-h.gc")
(goal-src "kernel/gstate.gc"
"gkernel")
;;;;;;;;;;;;;;;;;;;;;;;;
;; Weird special things
;;;;;;;;;;;;;;;;;;;;;;;;
;; The tpage directory
(defstep :in "assets/tpage-dir.txt"
:tool 'tpage-dir
:out '("out/obj/dir-tpages.go")
)
;; the count file.
(defstep :in "assets/game_count.txt"
:tool 'game-cnt
:out '("out/obj/game-cnt.go")
)
;;;;;;;;;;;;;;;;;;;;;
;; Textures (Common)
;;;;;;;;;;;;;;;;;;;;;
(copy-textures 463 2 880 256 1278 1032 62 1532)
;;;;;;;;;;;;;;;;;;;;;
;; Art (Common)
;;;;;;;;;;;;;;;;;;;;;
(copy-gos
"fuel-cell-ag"
"money-ag"
"buzzer-ag"
"ecovalve-ag-ART-GAME"
"crate-ag"
"speaker-ag"
"fuelcell-naked-ag"
"eichar-ag"
"sidekick-ag"
"deathcam-ag"
)
;;;;;;;;;;;;;;;;;;;;;
;; Text
;;;;;;;;;;;;;;;;;;;;;
(defstep :in "assets/game_text.txt"
:tool 'text
:out '("out/iso/0COMMON.TXT"
"out/iso/1COMMON.TXT"
"out/iso/2COMMON.TXT"
"out/iso/3COMMON.TXT"
"out/iso/4COMMON.TXT"
"out/iso/5COMMON.TXT"
"out/iso/6COMMON.TXT")
)
;;;;;;;;;;;;;;;;;;;;;
;; ISO Group
;;;;;;;;;;;;;;;;;;;;;
;; the iso group is a group of files required to boot.
(group "iso"
"out/iso/0COMMON.TXT"
"out/iso/KERNEL.CGO"
"out/iso/GAME.CGO"
"out/iso/VI1.DGO"
)
;;;;;;;;;;;;;;;;;;;;;
;; Village 1
;;;;;;;;;;;;;;;;;;;;;
;; the definition for the DGO file.
(cgo "VI1.DGO"
"vi1.gd"
)
;; the code
(goal-src-sequence
"levels/"
:deps ;; no idea what these depend on, make it depend on the whole engine
("out/obj/default-menu.o")
"village_common/villagep-obs.gc"
"village_common/oracle.gc"
"village1/farmer.gc"
"village1/explorer.gc"
"village1/assistant.gc"
"village1/sage.gc"
"village1/yakow.gc"
"village1/village-obs-VI1.gc"
"village1/fishermans-boat.gc"
"village1/village1-part.gc"
"village1/village1-part2.gc"
"village1/sequence-a-village1.gc"
)
;; the textures
(copy-textures 398 400 399 401 1470)
;; the art
(copy-gos
"assistant-ag"
"evilplant-ag"
"explorer-ag"
"farmer-ag"
"fishermans-boat-ag"
"hutlamp-ag"
"mayorgears-ag"
"medres-beach-ag"
"medres-beach1-ag"
"medres-beach2-ag"
"medres-beach3-ag"
"medres-jungle-ag"
"medres-jungle1-ag"
"medres-jungle2-ag"
"medres-misty-ag"
"medres-training-ag"
"medres-village11-ag"
"medres-village12-ag"
"medres-village13-ag"
"oracle-ag-VI1"
"orb-cache-top-ag-VI1"
"reflector-middle-ag"
"revcycle-ag"
"revcycleprop-ag"
"ropebridge-32-ag"
"sage-ag"
"sagesail-ag"
"sharkey-ag-VI1"
"villa-starfish-ag"
"village-cam-ag-VI1"
"village1cam-ag"
"warp-gate-switch-ag-VI1-VI3"
"warpgate-ag"
"water-anim-village1-ag"
"windmill-sail-ag"
"windspinner-ag"
"yakow-ag"
"village1-vis"
)
;;;;;;;;;;;;;;;;;;;;;
;; Game Engine Code
;;;;;;;;;;;;;;;;;;;;;
;; We don't know the actual dependencies, but the build
;; order is a possibly ordering, and the goal-src-sequence
;; will force these to always build in this order.
(goal-src-sequence
;; prefix
"engine/"
:deps
("out/obj/gcommon.o"
"out/obj/gstate.o"
"out/obj/gstring.o"
"out/obj/gkernel.o"
)
;; sources
"util/types-h.gc"
"ps2/vu1-macros.gc"
"math/math.gc"
"math/vector-h.gc"
"physics/gravity-h.gc"
"geometry/bounding-box-h.gc"
"math/matrix-h.gc"
"math/quaternion-h.gc"
"math/euler-h.gc"
"math/transform-h.gc"
"geometry/geometry-h.gc"
"math/trigonometry-h.gc"
"math/transformq-h.gc"
"geometry/bounding-box.gc"
"math/matrix.gc"
"math/transform.gc"
"math/quaternion.gc"
"math/euler.gc"
"geometry/geometry.gc"
"math/trigonometry.gc"
"sound/gsound-h.gc"
"ps2/timer-h.gc"
"ps2/timer.gc"
"ps2/vif-h.gc"
"dma/dma-h.gc"
"gfx/hw/video-h.gc"
"gfx/hw/vu1-user-h.gc"
"dma/dma.gc"
"dma/dma-buffer.gc"
"dma/dma-bucket.gc"
"dma/dma-disasm.gc"
"ps2/pad.gc"
"gfx/hw/gs.gc"
"gfx/hw/display-h.gc"
"math/vector.gc"
"load/file-io.gc"
"load/loader-h.gc"
"gfx/texture-h.gc"
"level/level-h.gc"
"camera/math-camera-h.gc"
"camera/math-camera.gc"
"gfx/font-h.gc"
"gfx/decomp-h.gc"
"gfx/hw/display.gc"
"engine/connect.gc"
"ui/text-h.gc"
"game/settings-h.gc"
"gfx/capture.gc"
"debug/memory-usage-h.gc"
"gfx/texture.gc"
"game/main-h.gc"
"anim/mspace-h.gc"
"draw/drawable-h.gc"
"draw/drawable-group-h.gc"
"draw/drawable-inline-array-h.gc"
"draw/draw-node-h.gc"
"draw/drawable-tree-h.gc"
"draw/drawable-actor-h.gc"
"draw/drawable-ambient-h.gc"
"game/task/game-task-h.gc"
"game/task/hint-control-h.gc"
"gfx/generic/generic-h.gc"
"gfx/lights-h.gc"
"gfx/ocean/ocean-h.gc"
"gfx/ocean/ocean-trans-tables.gc"
"gfx/ocean/ocean-tables.gc"
"gfx/ocean/ocean-frames.gc"
"gfx/sky/sky-h.gc"
"gfx/mood-h.gc"
"gfx/time-of-day-h.gc"
"data/art-h.gc"
"gfx/generic/generic-vu1-h.gc"
"gfx/merc/merc-h.gc"
"gfx/merc/generic-merc-h.gc"
"gfx/tie/generic-tie-h.gc"
"gfx/generic/generic-work-h.gc"
"gfx/shadow/shadow-cpu-h.gc"
"gfx/shadow/shadow-vu1-h.gc"
"ps2/memcard-h.gc"
"game/game-info-h.gc"
"gfx/wind-h.gc"
"gfx/tie/prototype-h.gc"
"anim/joint-h.gc"
"anim/bones-h.gc"
"engine/engines.gc"
"data/res-h.gc"
"data/res.gc"
"gfx/lights.gc"
"physics/dynamics-h.gc"
"target/surface-h.gc"
"target/pat-h.gc"
"game/fact-h.gc"
"anim/aligner-h.gc"
"game/game-h.gc"
"game/generic-obs-h.gc"
"camera/pov-camera-h.gc"
"util/sync-info-h.gc"
"util/smush-control-h.gc"
"physics/trajectory-h.gc"
"debug/debug-h.gc"
"target/joint-mod-h.gc"
"collide/collide-func-h.gc"
"collide/collide-mesh-h.gc"
"collide/collide-shape-h.gc"
"collide/collide-target-h.gc"
"collide/collide-touch-h.gc"
"collide/collide-edge-grab-h.gc"
"draw/process-drawable-h.gc"
"game/effect-control-h.gc"
"collide/collide-frag-h.gc"
"game/projectiles-h.gc"
"target/target-h.gc"
"gfx/depth-cue-h.gc"
"debug/stats-h.gc"
"gfx/vis/bsp-h.gc"
"collide/collide-cache-h.gc"
"collide/collide-h.gc"
"gfx/shrub/shrubbery-h.gc"
"gfx/tie/tie-h.gc"
"gfx/tfrag/tfrag-h.gc"
"gfx/background-h.gc"
"gfx/tfrag/subdivide-h.gc"
"entity/entity-h.gc"
"gfx/sprite/sprite-h.gc"
"gfx/shadow/shadow-h.gc"
"gfx/eye-h.gc"
"sparticle/sparticle-launcher-h.gc"
"sparticle/sparticle-h.gc"
"entity/actor-link-h.gc"
"camera/camera-h.gc"
"camera/cam-debug-h.gc"
"camera/cam-interface-h.gc"
"camera/cam-update-h.gc"
"debug/assert-h.gc"
"ui/hud-h.gc"
"ui/progress-h.gc"
"ps2/rpc-h.gc"
"nav/path-h.gc"
"nav/navigate-h.gc"
"load/load-dgo.gc"
"load/ramdisk.gc"
"sound/gsound.gc"
"math/transformq.gc"
"collide/collide-func.gc"
"anim/joint.gc"
"geometry/cylinder.gc"
"gfx/wind.gc"
"gfx/vis/bsp.gc"
"gfx/tfrag/subdivide.gc"
"gfx/sprite/sprite.gc"
"gfx/sprite/sprite-distort.gc"
"debug/debug-sphere.gc"
"debug/debug.gc"
"gfx/merc/merc-vu1.gc"
"gfx/merc/merc-blend-shape.gc"
"gfx/merc/merc.gc"
"gfx/ripple.gc"
"anim/bones.gc"
"gfx/generic/generic-vu0.gc"
"gfx/generic/generic.gc"
"gfx/generic/generic-vu1.gc"
"gfx/generic/generic-effect.gc"
"gfx/generic/generic-merc.gc"
"gfx/generic/generic-tie.gc"
"gfx/shadow/shadow-cpu.gc"
"gfx/shadow/shadow-vu1.gc"
"gfx/depth-cue.gc"
"gfx/font.gc"
"load/decomp.gc"
"gfx/background.gc"
"draw/draw-node.gc"
"gfx/shrub/shrubbery.gc"
"gfx/shrub/shrub-work.gc"
"gfx/tfrag/tfrag-near.gc"
"gfx/tfrag/tfrag.gc"
"gfx/tfrag/tfrag-methods.gc"
"gfx/tfrag/tfrag-work.gc"
"gfx/tie/tie.gc"
"gfx/tie/tie-near.gc"
"gfx/tie/tie-work.gc"
"gfx/tie/tie-methods.gc"
"util/sync-info.gc"
"physics/trajectory.gc"
"sparticle/sparticle-launcher.gc"
"sparticle/sparticle.gc"
"entity/entity-table.gc"
"load/loader.gc"
"game/task/task-control-h.gc"
"game/game-info.gc"
"game/game-save.gc"
"game/settings.gc"
"ambient/mood-tables.gc"
"ambient/mood.gc"
"ambient/weather-part.gc"
"gfx/time-of-day.gc"
"gfx/sky/sky-utils.gc"
"gfx/sky/sky.gc"
"gfx/sky/sky-tng.gc"
"level/load-boundary-h.gc"
"level/load-boundary.gc"
"level/load-boundary-data.gc"
"level/level-info.gc"
"level/level.gc"
"ui/text.gc"
"collide/collide-probe.gc"
"collide/collide-frag.gc"
"collide/collide-mesh.gc"
"collide/collide-touch.gc"
"collide/collide-edge-grab.gc"
"collide/collide-shape.gc"
"collide/collide-shape-rider.gc"
"collide/collide.gc"
"collide/collide-planes.gc"
"gfx/merc/merc-death.gc"
"gfx/water/water-h.gc"
"camera/camera.gc"
"camera/cam-interface.gc"
"camera/cam-master.gc"
"camera/cam-states.gc"
"camera/cam-states-dbg.gc"
"camera/cam-combiner.gc"
"camera/cam-update.gc"
"geometry/vol-h.gc"
"camera/cam-layout.gc"
"camera/cam-debug.gc"
"camera/cam-start.gc"
"draw/process-drawable.gc"
"game/task/hint-control.gc"
"ambient/ambient.gc"
"debug/assert.gc"
"game/generic-obs.gc"
"target/target-util.gc"
"target/target-part.gc"
"collide/collide-reaction-target.gc"
"target/logic-target.gc"
"target/sidekick.gc"
"game/voicebox.gc"
"target/target-handler.gc"
"target/target.gc"
"target/target2.gc"
"target/target-death.gc"
"debug/menu.gc"
"draw/drawable.gc"
"draw/drawable-group.gc"
"draw/drawable-inline-array.gc"
"draw/drawable-tree.gc"
"gfx/tie/prototype.gc"
"collide/main-collide.gc"
"game/video.gc"
"game/main.gc"
"collide/collide-cache.gc"
"entity/relocate.gc"
"debug/memory-usage.gc"
"entity/entity.gc"
"nav/path.gc"
"geometry/vol.gc"
"nav/navigate.gc"
"anim/aligner.gc"
"game/effect-control.gc"
"gfx/water/water.gc"
"game/collectables-part.gc"
"game/collectables.gc"
"game/task/task-control.gc"
"game/task/process-taskable.gc"
"camera/pov-camera.gc"
"game/powerups.gc"
"game/crates.gc"
"ui/hud.gc"
"ui/hud-classes.gc"
"ui/progress/progress-static.gc"
"ui/progress/progress-part.gc"
"ui/progress/progress-draw.gc"
"ui/progress/progress.gc"
"ui/credits.gc"
"game/projectiles.gc"
"gfx/ocean/ocean.gc"
"gfx/ocean/ocean-vu0.gc"
"gfx/ocean/ocean-texture.gc"
"gfx/ocean/ocean-mid.gc"
"gfx/ocean/ocean-transition.gc"
"gfx/ocean/ocean-near.gc"
"gfx/shadow/shadow.gc"
"gfx/eye.gc"
"util/glist-h.gc"
"util/glist.gc"
"debug/anim-tester.gc"
"debug/viewer.gc"
"debug/part-tester.gc"
"debug/default-menu.gc"
)
(goal-src-sequence
"levels/common/"
:deps ("out/obj/default-menu.o")
"texture-upload.gc"
"rigid-body-h.gc"
"water-anim.gc"
"dark-eco-pool.gc"
"rigid-body.gc"
"nav-enemy-h.gc"
"nav-enemy.gc"
"baseplat.gc"
"basebutton.gc"
"tippy.gc"
"joint-exploder.gc"
"babak.gc"
"sharkey.gc"
"orb-cache.gc"
"plat.gc"
"plat-button.gc"
"plat-eco.gc"
"ropebridge.gc"
"ticky.gc"
)

View file

@ -625,3 +625,33 @@
(defmacro fake-asm (asm-name &rest args)
`(defmacro ,asm-name (,@args) `(none))
)
;;;;;;;;;;;;;;;;;;;;;;;;;
;; Build System
;;;;;;;;;;;;;;;;;;;;;;;;;
(defmacro makeo (object-name &rest flags)
"Make the given object. Can use a string, or not."
`(make ,(string-append
"out/obj/"
(if (string? object-name) object-name (symbol->string object-name))
".o"
)
,@flags)
)
(defmacro make-cgo (file)
`(make ,(string-append "out/iso/" file ".CGO"))
)
(defmacro make-dgo (file)
`(make ,(string-append "out/iso/" file ".DGO"))
)
(defmacro make-group (name &key (verbose #f) &key (force #f))
`(make ,(string-append "GROUP:" name) :verbose ,verbose :force ,force)
)
;; load the default project
(load-project "goal_src/game.gp")

View file

@ -34,6 +34,9 @@ add_library(compiler
debugger/DebugInfo.cpp
listener/Listener.cpp
listener/MemoryMap.cpp
make/MakeSystem.cpp
make/Tool.cpp
make/Tools.cpp
regalloc/IRegister.cpp
regalloc/Allocator.cpp
regalloc/allocate.cpp

View file

@ -1,11 +1,12 @@
#include "Compiler.h"
#include "common/link_types.h"
#include "IR.h"
#include "goalc/regalloc/allocate.h"
#include "third-party/fmt/core.h"
#include "CompilerException.h"
#include <chrono>
#include <thread>
#include "CompilerException.h"
#include "IR.h"
#include "common/link_types.h"
#include "goalc/make/Tools.h"
#include "goalc/regalloc/allocate.h"
#include "third-party/fmt/core.h"
using namespace goos;
@ -16,7 +17,10 @@ Compiler::Compiler(std::unique_ptr<ReplWrapper> repl)
m_global_env = std::make_unique<GlobalEnv>();
m_none = std::make_unique<None>(m_ts.make_typespec("none"));
// compile GOAL library
// let the build system run us
m_make.add_tool(std::make_shared<CompilerTool>(this));
// load GOAL library
Object library_code = m_goos.reader.read_from_file({"goal_src", "goal-lib.gc"});
compile_object_file("goal-lib", library_code, false);
@ -410,3 +414,7 @@ void Compiler::typecheck_reg_type_allow_false(const goos::Object& form,
}
typecheck(form, expected, coerce_to_reg_type(actual->type()), error_message);
}
bool Compiler::knows_object_file(const std::string& name) {
return m_debugger.knows_object(name);
}

View file

@ -2,19 +2,22 @@
#include <functional>
#include <optional>
#include "common/type_system/TypeSystem.h"
#include "Env.h"
#include "goalc/listener/Listener.h"
#include "third-party/fmt/color.h"
#include "third-party/fmt/core.h"
#include "common/goos/Interpreter.h"
#include "common/goos/ReplUtils.h"
#include "common/type_system/TypeSystem.h"
#include "goalc/compiler/CompilerException.h"
#include "goalc/compiler/CompilerSettings.h"
#include "goalc/compiler/Env.h"
#include "goalc/compiler/IR.h"
#include "goalc/compiler/SymbolInfo.h"
#include "goalc/debugger/Debugger.h"
#include "goalc/emitter/Register.h"
#include "CompilerSettings.h"
#include "third-party/fmt/core.h"
#include "third-party/fmt/color.h"
#include "CompilerException.h"
#include "goalc/compiler/SymbolInfo.h"
#include "common/goos/ReplUtils.h"
#include "goalc/listener/Listener.h"
#include "goalc/make/MakeSystem.h"
enum MathMode { MATH_INT, MATH_BINT, MATH_FLOAT, MATH_INVALID };
@ -56,8 +59,26 @@ class Compiler {
void repl_coloring(std::string const& str,
Replxx::colors_t& colors,
std::vector<std::pair<std::string, Replxx::Color>> const& user_data);
bool knows_object_file(const std::string& name);
private:
TypeSystem m_ts;
std::unique_ptr<GlobalEnv> m_global_env = nullptr;
std::unique_ptr<None> m_none = nullptr;
bool m_want_exit = false;
bool m_want_reload = false;
listener::Listener m_listener;
Debugger m_debugger;
goos::Interpreter m_goos;
std::unordered_map<std::string, TypeSpec> m_symbol_types;
std::unordered_map<std::shared_ptr<goos::SymbolObject>, goos::Object> m_global_constants;
std::unordered_map<std::shared_ptr<goos::SymbolObject>, LambdaVal*> m_inlineable_functions;
CompilerSettings m_settings;
bool m_throw_on_define_extern_redefinition = false;
SymbolInfoMap m_symbol_info;
std::unique_ptr<ReplWrapper> m_repl;
MakeSystem m_make;
std::set<std::string> lookup_symbol_infos_starting_with(const std::string& prefix) const;
std::vector<SymbolInfo>* lookup_exact_name_info(const std::string& name) const;
bool get_true_or_false(const goos::Object& form, const goos::Object& boolean);
@ -223,22 +244,6 @@ class Compiler {
std::string make_symbol_info_description(const SymbolInfo& info);
TypeSystem m_ts;
std::unique_ptr<GlobalEnv> m_global_env = nullptr;
std::unique_ptr<None> m_none = nullptr;
bool m_want_exit = false;
bool m_want_reload = false;
listener::Listener m_listener;
Debugger m_debugger;
goos::Interpreter m_goos;
std::unordered_map<std::string, TypeSpec> m_symbol_types;
std::unordered_map<std::shared_ptr<goos::SymbolObject>, goos::Object> m_global_constants;
std::unordered_map<std::shared_ptr<goos::SymbolObject>, LambdaVal*> m_inlineable_functions;
CompilerSettings m_settings;
bool m_throw_on_define_extern_redefinition = false;
SymbolInfoMap m_symbol_info;
std::unique_ptr<ReplWrapper> m_repl;
MathMode get_math_mode(const TypeSpec& ts);
bool is_number(const TypeSpec& ts);
bool is_float(const TypeSpec& ts);
@ -492,6 +497,8 @@ class Compiler {
Val* compile_add_macro_to_autocomplete(const goos::Object& form,
const goos::Object& rest,
Env* env);
Val* compile_load_project(const goos::Object& form, const goos::Object& rest, Env* env);
Val* compile_make(const goos::Object& form, const goos::Object& rest, Env* env);
// ControlFlow
Condition compile_condition(const goos::Object& condition, Env* env, bool invert);

View file

@ -128,6 +128,8 @@ const std::unordered_map<
{"get-info", &Compiler::compile_get_info},
{"autocomplete", &Compiler::compile_autocomplete},
{"add-macro-to-autocomplete", &Compiler::compile_add_macro_to_autocomplete},
{"load-project", &Compiler::compile_load_project},
{"make", &Compiler::compile_make},
// CONDITIONAL COMPILATION
{"#cond", &Compiler::compile_gscond},

View file

@ -4,18 +4,19 @@
*/
#include <filesystem>
#include "goalc/compiler/Compiler.h"
#include "goalc/compiler/IR.h"
#include "common/util/Timer.h"
#include "common/util/DgoWriter.h"
#include "common/util/FileUtil.h"
#include "goalc/data_compiler/game_text.h"
#include "goalc/data_compiler/game_count.h"
#include "goalc/data_compiler/dir_tpages.h"
#include "common/goos/ReplUtils.h"
#include <regex>
#include <stack>
#include "common/goos/ReplUtils.h"
#include "common/util/DgoWriter.h"
#include "common/util/FileUtil.h"
#include "common/util/Timer.h"
#include "goalc/compiler/Compiler.h"
#include "goalc/compiler/IR.h"
#include "goalc/data_compiler/dir_tpages.h"
#include "goalc/data_compiler/game_count.h"
#include "goalc/data_compiler/game_text.h"
/*!
* Exit the compiler. Disconnects the listener and tells the target to reset itself.
* Will actually exit the next time the REPL runs.
@ -90,6 +91,7 @@ Val* Compiler::compile_asm_file(const goos::Object& form, const goos::Object& re
bool write = false;
bool no_code = false;
bool disassemble = false;
bool no_time_prints = false;
std::vector<std::pair<std::string, double>> timing;
Timer total_timer;
@ -120,6 +122,8 @@ Val* Compiler::compile_asm_file(const goos::Object& form, const goos::Object& re
} else if (setting == ":disassemble") {
disassemble = true;
last_was_disasm = true;
} else if (setting == ":no-time-prints") {
no_time_prints = true;
} else {
throw_compiler_error(form, "The option {} was not recognized for asm-file.", setting);
}
@ -208,7 +212,7 @@ Val* Compiler::compile_asm_file(const goos::Object& form, const goos::Object& re
printf("\n");
} else {
auto total_time = total_timer.getMs();
if (total_time > 10.0 && color) {
if (total_time > 10.0 && color && !no_time_prints) {
fmt::print("[ASM-FILE] {} took {:.2f} ms\n", obj_file_name, total_time);
}
}
@ -575,3 +579,29 @@ std::vector<SymbolInfo>* Compiler::lookup_exact_name_info(const std::string& nam
return nullptr;
}
}
Val* Compiler::compile_load_project(const goos::Object& form, const goos::Object& rest, Env*) {
auto args = get_va(form, rest);
va_check(form, args, {goos::ObjectType::STRING}, {});
m_make.load_project_file(args.unnamed.at(0).as_string()->data);
return get_none();
}
Val* Compiler::compile_make(const goos::Object& form, const goos::Object& rest, Env*) {
auto args = get_va(form, rest);
va_check(form, args, {goos::ObjectType::STRING},
{{"force", {false, {goos::ObjectType::SYMBOL}}},
{"verbose", {false, {goos::ObjectType::SYMBOL}}}});
bool force = false;
if (args.has_named("force")) {
force = get_true_or_false(form, args.get_named("force"));
}
bool verbose = false;
if (args.has_named("verbose")) {
verbose = get_true_or_false(form, args.get_named("verbose"));
}
m_make.make(args.unnamed.at(0).as_string()->data, force, verbose);
return get_none();
}

View file

@ -8,8 +8,6 @@
void compile_dir_tpages(const std::string& filename) {
std::vector<int> lengths;
printf("[Build tpage dir] %s\n", filename.c_str());
goos::Reader reader;
auto code = reader.read_from_file({filename});
std::string err;

View file

@ -6,7 +6,6 @@
#include "game_count.h"
void compile_game_count(const std::string& filename) {
printf("[Build Game Count] %s\n", filename.c_str());
struct Count {
int buzzer;
int money;

View file

@ -4,15 +4,15 @@
* Uses xdbg functions to debug an OpenGOAL target.
*/
#include "goalc/emitter/Register.h"
#include "common/util/assert.h"
#include "Debugger.h"
#include "common/util/Timer.h"
#include "common/goal_constants.h"
#include "common/symbols.h"
#include "third-party/fmt/core.h"
#include "common/util/Timer.h"
#include "common/util/assert.h"
#include "goalc/debugger/disassemble.h"
#include "goalc/emitter/Register.h"
#include "goalc/listener/Listener.h"
#include "third-party/fmt/core.h"
/*!
* Is the target halted? If we don't know or aren't connected, returns false.
@ -752,3 +752,7 @@ DebugInfo& Debugger::get_debug_info_for_object(const std::string& object_name) {
return m_debug_info.insert(std::make_pair(object_name, DebugInfo(object_name))).first->second;
}
bool Debugger::knows_object(const std::string& object_name) const {
return m_debug_info.find(object_name) != m_debug_info.end();
}

View file

@ -6,16 +6,16 @@
#pragma once
#include <unordered_map>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <cstring>
#include <mutex>
#include <queue>
#include <thread>
#include <unordered_map>
#include "DebugInfo.h"
#include "common/common_types.h"
#include "common/cross_os_debug/xdbg.h"
#include "goalc/listener/MemoryMap.h"
#include "DebugInfo.h"
#include <cstring>
namespace listener {
class Listener;
@ -92,6 +92,7 @@ class Debugger {
InstructionPointerInfo get_rip_info(u64 x86_rip);
DebugInfo& get_debug_info_for_object(const std::string& object_name);
bool knows_object(const std::string& object_name) const;
const InstructionPointerInfo& get_cached_break_info() { return m_break_info; }
std::string get_info_about_addr(u32 addr);
Disassembly disassemble_at_rip(const InstructionPointerInfo& info);

View file

@ -48,7 +48,7 @@ int main(int argc, char** argv) {
// Init REPL
// the compiler may throw an exception if it fails to load its standard library.
try {
std::unique_ptr<Compiler> compiler = std::make_unique<Compiler>();
std::unique_ptr<Compiler> compiler;
if (argument.empty()) {
ReplStatus status = ReplStatus::WANT_RELOAD;
while (status == ReplStatus::WANT_RELOAD) {
@ -59,6 +59,7 @@ int main(int argc, char** argv) {
}
}
} else {
compiler = std::make_unique<Compiler>();
compiler->run_front_end_on_string(argument);
}
} catch (std::exception& e) {

328
goalc/make/MakeSystem.cpp Normal file
View file

@ -0,0 +1,328 @@
#include <filesystem>
#include "MakeSystem.h"
#include "third-party/fmt/color.h"
#include "third-party/fmt/core.h"
#include "common/goos/ParseHelpers.h"
#include "common/util/Timer.h"
#include "goalc/make/Tools.h"
std::string MakeStep::print() const {
std::string result = fmt::format("Tool {} with input \"{}\" and deps:\n ", tool, input);
for (auto& dep : deps) {
result += dep;
result += '\n';
result += ' ';
}
result.pop_back();
result += fmt::format("will produce outputs:\n ");
for (auto& o : outputs) {
result += o;
result += '\n';
result += ' ';
}
result.pop_back();
return result;
}
MakeSystem::MakeSystem() {
m_goos.register_form("defstep", [=](const goos::Object& obj, goos::Arguments& args,
const std::shared_ptr<goos::EnvironmentObject>& env) {
return handle_defstep(obj, args, env);
});
m_goos.register_form("basename", [=](const goos::Object& obj, goos::Arguments& args,
const std::shared_ptr<goos::EnvironmentObject>& env) {
return handle_basename(obj, args, env);
});
m_goos.register_form("stem", [=](const goos::Object& obj, goos::Arguments& args,
const std::shared_ptr<goos::EnvironmentObject>& env) {
return handle_stem(obj, args, env);
});
m_goos.set_global_variable_to_symbol("ASSETS", "#t");
add_tool<DgoTool>();
add_tool<TpageDirTool>();
add_tool<CopyTool>();
add_tool<GameCntTool>();
add_tool<TextTool>();
add_tool<GroupTool>();
}
/*!
* Load a project file, clearing any project info previously loaded.
*/
void MakeSystem::load_project_file(const std::string& file_path) {
Timer timer;
// clear the previous project
clear_project();
// read the file
auto data = m_goos.reader.read_from_file({file_path});
// interpret it, which will call various handlers.
m_goos.eval(data, m_goos.global_environment.as_env());
}
goos::Object MakeSystem::handle_defstep(const goos::Object& form,
goos::Arguments& args,
const std::shared_ptr<goos::EnvironmentObject>& env) {
m_goos.eval_args(&args, env);
va_check(form, args, {},
{{"out", {true, {goos::ObjectType::PAIR}}},
{"tool", {true, {goos::ObjectType::SYMBOL}}},
{"in", {false, {goos::ObjectType::STRING}}},
{"dep", {false, {}}}});
auto step = std::make_shared<MakeStep>();
goos::for_each_in_list(args.get_named("out"), [&](const goos::Object& obj) {
step->outputs.push_back(obj.as_string()->data);
});
step->tool = args.get_named("tool").as_symbol()->name;
if (m_tools.find(step->tool) == m_tools.end()) {
throw std::runtime_error(fmt::format("The tool {} is unknown.", step->tool));
}
if (args.has_named("in")) {
step->input = args.get_named("in").as_string()->data;
}
if (args.has_named("dep")) {
goos::for_each_in_list(args.get_named("dep"), [&](const goos::Object& obj) {
step->deps.push_back(obj.as_string()->data);
});
}
for (auto& output : step->outputs) {
auto existing = m_output_to_step.find(output);
if (existing != m_output_to_step.end()) {
throw std::runtime_error(fmt::format("There are multiple ways to make output {}:\n{}\n{}\n",
output, step->print(), existing->second->print()));
}
m_output_to_step.insert({output, step});
}
return goos::EmptyListObject::make_new();
}
/*!
* Fully clear the state of the project.
*
*/
void MakeSystem::clear_project() {
m_output_to_step.clear();
}
void MakeSystem::va_check(
const goos::Object& form,
const goos::Arguments& args,
const std::vector<std::optional<goos::ObjectType>>& unnamed,
const std::unordered_map<std::string, std::pair<bool, std::optional<goos::ObjectType>>>&
named) {
std::string err;
if (!goos::va_check(args, unnamed, named, &err)) {
m_goos.throw_eval_error(form, err);
}
}
goos::Object MakeSystem::handle_basename(const goos::Object& form,
goos::Arguments& args,
const std::shared_ptr<goos::EnvironmentObject>& env) {
m_goos.eval_args(&args, env);
va_check(form, args, {goos::ObjectType::STRING}, {});
std::filesystem::path input(args.unnamed.at(0).as_string()->data);
return goos::StringObject::make_new(input.filename().u8string());
}
goos::Object MakeSystem::handle_stem(const goos::Object& form,
goos::Arguments& args,
const std::shared_ptr<goos::EnvironmentObject>& env) {
m_goos.eval_args(&args, env);
va_check(form, args, {goos::ObjectType::STRING}, {});
std::filesystem::path input(args.unnamed.at(0).as_string()->data);
return goos::StringObject::make_new(input.stem().u8string());
}
void MakeSystem::get_dependencies(const std::string& master_target,
const std::string& output,
std::vector<std::string>* result,
std::unordered_set<std::string>* result_set) const {
if (result_set->find(output) != result_set->end()) {
return;
}
const auto& rule_it = m_output_to_step.find(output);
if (rule_it == m_output_to_step.end()) {
throw std::runtime_error(
fmt::format("No rule to make {}, required for {}\n", output, master_target));
}
// what deps do we need?
for (auto& dep : rule_it->second->deps) {
get_dependencies(master_target, dep, result, result_set);
}
const auto& rule = rule_it->second;
for (auto& dep : m_tools.at(rule->tool)
->get_additional_dependencies({rule->input, rule->deps, rule->outputs})) {
get_dependencies(master_target, dep, result, result_set);
}
result->push_back(output);
for (auto& op : rule->outputs) {
result_set->insert(op);
}
}
std::vector<std::string> MakeSystem::get_dependencies(const std::string& target) const {
Timer timer;
std::vector<std::string> result;
std::unordered_set<std::string> added_deps;
get_dependencies(target, target, &result, &added_deps);
fmt::print("Successfully found all {} dependencies for target in {:.3f}s\n", result.size(),
timer.getSeconds());
return result;
}
void MakeSystem::add_tool(std::shared_ptr<Tool> tool) {
auto& name = tool->name();
assert(m_tools.find(name) == m_tools.end());
m_tools[name] = tool;
}
std::vector<std::string> MakeSystem::filter_dependencies(const std::vector<std::string>& all_deps) {
Timer timer;
std::vector<std::string> result;
std::unordered_set<std::string> stale_deps;
std::unordered_set<std::string> compiler_sym_needed;
for (auto& to_make : all_deps) {
auto& rule = m_output_to_step.at(to_make);
auto& tool = m_tools.at(rule->tool);
bool added = false;
if (tool->needs_run({rule->input, rule->deps, rule->outputs})) {
result.push_back(to_make);
stale_deps.insert(to_make);
added = true;
}
if (!added) {
// check transitive dependencies
for (auto& dep : rule->deps) {
if (stale_deps.find(dep) != stale_deps.end()) {
result.push_back(to_make);
stale_deps.insert(to_make);
added = true;
break;
}
}
}
if (!added) {
// check transitive dependencies
for (auto& dep :
tool->get_additional_dependencies({rule->input, rule->deps, rule->outputs})) {
if (stale_deps.find(dep) != stale_deps.end()) {
result.push_back(to_make);
stale_deps.insert(to_make);
added = true;
break;
}
}
}
}
fmt::print("Found that {} of {} targets do need rebuilding in {:.3f}s\n", result.size(),
all_deps.size(), timer.getSeconds());
return result;
}
namespace {
void print_input(const std::string& in, char end) {
if (in.length() > 70) {
fmt::print("{}...{}", in.substr(0, 70 - 3), end);
} else {
fmt::print("{}{}{}", in, std::string(70 - in.length(), ' '), end);
}
}
} // namespace
bool MakeSystem::make(const std::string& target, bool force, bool verbose) {
auto deps = get_dependencies(target);
// fmt::print("All deps:\n");
// for (auto& dep : deps) {
// fmt::print("{}\n", dep);
// }
if (!force) {
deps = filter_dependencies(deps);
}
// fmt::print("Filt deps:\n");
// for (auto& dep : filtered_deps) {
// fmt::print("{}\n", dep);
// }
Timer make_timer;
fmt::print("Building {} targets...\n", deps.size());
int i = 0;
for (auto& to_make : deps) {
Timer step_timer;
auto& rule = m_output_to_step.at(to_make);
auto& tool = m_tools.at(rule->tool);
int percent = (100.0 * (1 + (i++)) / (deps.size())) + 0.5;
if (verbose) {
fmt::print("[{:3d}%] [{:8s}] {}\n", percent, tool->name(), rule->input);
} else {
fmt::print("[{:3d}%] [{:8s}] ", percent, tool->name());
print_input(rule->input, '\r');
}
bool success = false;
try {
success = tool->run({rule->input, rule->deps, rule->outputs});
} catch (std::exception& e) {
fmt::print("\n");
fmt::print("Error: {}\n", e.what());
}
if (!success) {
fmt::print("Build failed on {}.\n", rule->input);
throw std::runtime_error("Build failed.");
return false;
}
if (verbose) {
if (step_timer.getSeconds() > 0.05) {
fmt::print(fg(fmt::color::yellow), " {:.3f}\n", step_timer.getSeconds());
} else {
fmt::print(" {:.3f}\n", step_timer.getSeconds());
}
} else {
if (step_timer.getSeconds() > 0.05) {
fmt::print("[{:3d}%] [{:8s}] ", percent, tool->name());
fmt::print(fg(fmt::color::yellow), "{:.3f} ", step_timer.getSeconds());
print_input(rule->input, '\n');
} else {
fmt::print("[{:3d}%] [{:8s}] {:.3f} ", percent, tool->name(), step_timer.getSeconds());
print_input(rule->input, '\r');
}
}
}
fmt::print("\nSuccessfully built all {} targets in {:.3f}s\n", deps.size(),
make_timer.getSeconds());
return true;
}

61
goalc/make/MakeSystem.h Normal file
View file

@ -0,0 +1,61 @@
#pragma once
#include "common/goos/Interpreter.h"
#include "goalc/make/Tool.h"
struct MakeStep {
std::string input;
std::vector<std::string> deps, outputs;
std::string tool;
std::string print() const;
};
class MakeSystem {
public:
MakeSystem();
void load_project_file(const std::string& file_path);
goos::Object handle_defstep(const goos::Object& obj,
goos::Arguments& args,
const std::shared_ptr<goos::EnvironmentObject>& env);
goos::Object handle_basename(const goos::Object& obj,
goos::Arguments& args,
const std::shared_ptr<goos::EnvironmentObject>& env);
goos::Object handle_stem(const goos::Object& obj,
goos::Arguments&,
const std::shared_ptr<goos::EnvironmentObject>& env);
std::vector<std::string> get_dependencies(const std::string& target) const;
std::vector<std::string> filter_dependencies(const std::vector<std::string>& all_deps);
bool make(const std::string& target, bool force, bool verbose);
void add_tool(std::shared_ptr<Tool> tool);
template <typename T>
void add_tool() {
add_tool(std::make_shared<T>());
}
void clear_project();
private:
void va_check(const goos::Object& form,
const goos::Arguments& args,
const std::vector<std::optional<goos::ObjectType>>& unnamed,
const std::unordered_map<std::string,
std::pair<bool, std::optional<goos::ObjectType>>>& named);
void get_dependencies(const std::string& master_target,
const std::string& output,
std::vector<std::string>* result_order,
std::unordered_set<std::string>* result_set) const;
goos::Interpreter m_goos;
std::unordered_map<std::string, std::shared_ptr<MakeStep>> m_output_to_step;
std::unordered_map<std::string, std::shared_ptr<Tool>> m_tools;
};

59
goalc/make/Tool.cpp Normal file
View file

@ -0,0 +1,59 @@
#include <chrono>
#include <filesystem>
#include "third-party/fmt/core.h"
#include "Tool.h"
#include "common/util/FileUtil.h"
Tool::Tool(const std::string& name) : m_name(name) {}
bool Tool::needs_run(const ToolInput& task) {
// for this to return false, all outputs need to be newer than all inputs.
auto in_file = std::filesystem::path(file_util::get_file_path({task.input}));
if (!std::filesystem::exists(in_file)) {
throw std::runtime_error(fmt::format("Input file {} does not exist.", task.input));
}
auto newest_input = std::filesystem::last_write_time(in_file);
for (auto& dep : task.deps) {
auto dep_path = std::filesystem::path(file_util::get_file_path({dep}));
if (std::filesystem::exists(dep_path)) {
auto dep_time = std::filesystem::last_write_time(dep_path);
if (dep_time > newest_input) {
newest_input = dep_time;
}
} else {
return true; // don't have a dep.
}
}
for (auto& dep : get_additional_dependencies(task)) {
auto dep_path = std::filesystem::path(file_util::get_file_path({dep}));
if (std::filesystem::exists(dep_path)) {
auto dep_time = std::filesystem::last_write_time(dep_path);
if (dep_time > newest_input) {
newest_input = dep_time;
}
} else {
return true; // don't have a dep.
}
}
for (auto& out : task.output) {
auto out_path = std::filesystem::path(file_util::get_file_path({out}));
if (std::filesystem::exists(out_path)) {
auto out_time = std::filesystem::last_write_time(out_path);
if (out_time < newest_input) {
return true;
}
} else {
return true; // don't have a dep.
}
}
return false;
}

25
goalc/make/Tool.h Normal file
View file

@ -0,0 +1,25 @@
#pragma once
#include <optional>
#include <string>
#include <vector>
struct ToolInput {
std::string& input; // the input file
std::vector<std::string>& deps; // explicit dependencies
std::vector<std::string>& output; // produced output files.
};
class Tool {
public:
Tool(const std::string& name);
virtual bool run(const ToolInput& task) = 0;
virtual std::vector<std::string> get_additional_dependencies(const ToolInput&) { return {}; }
virtual bool needs_run(const ToolInput& task);
virtual ~Tool() = default;
const std::string& name() const { return m_name; }
private:
std::string m_name;
};

121
goalc/make/Tools.cpp Normal file
View file

@ -0,0 +1,121 @@
#include "Tools.h"
#include <filesystem>
#include "goalc/compiler/Compiler.h"
#include "common/goos/ParseHelpers.h"
#include "common/util/DgoWriter.h"
#include "common/util/FileUtil.h"
#include "third-party/fmt/core.h"
#include "goalc/data_compiler/dir_tpages.h"
#include "goalc/data_compiler/game_count.h"
#include "goalc/data_compiler/game_text.h"
CompilerTool::CompilerTool(Compiler* compiler) : Tool("goalc"), m_compiler(compiler) {}
bool CompilerTool::needs_run(const ToolInput& task) {
if (!m_compiler->knows_object_file(std::filesystem::path(task.input).stem().u8string())) {
return true;
}
return Tool::needs_run(task);
}
bool CompilerTool::run(const ToolInput& task) {
// todo check inputs
try {
m_compiler->run_front_end_on_string(
fmt::format("(asm-file \"{}\" :no-time-prints :color :write)", task.input));
} catch (std::exception& e) {
fmt::print("Compilation failed: {}\n", e.what());
return false;
}
return true;
}
namespace {
DgoDescription parse_desc_file(const std::string& filename, goos::Reader& reader) {
auto dgo_desc = reader.read_from_file({filename}).as_pair()->cdr;
if (goos::list_length(dgo_desc) != 1) {
throw std::runtime_error("Invalid DGO description - got too many lists");
}
auto dgo = dgo_desc.as_pair()->car;
DgoDescription desc;
auto first = dgo.as_pair()->car;
desc.dgo_name = first.as_string()->data;
auto dgo_rest = dgo.as_pair()->cdr;
for_each_in_list(dgo_rest, [&](const goos::Object& entry) {
goos::Arguments e_arg;
std::string err;
if (!goos::get_va(entry, &err, &e_arg)) {
throw std::runtime_error(fmt::format("Invalid DGO description: {}\n", err));
}
if (!goos::va_check(e_arg, {goos::ObjectType::STRING, goos::ObjectType::STRING}, {}, &err)) {
throw std::runtime_error(fmt::format("Invalid DGO description: {}\n", err));
}
DgoDescription::DgoEntry o;
o.file_name = e_arg.unnamed.at(0).as_string()->data;
o.name_in_dgo = e_arg.unnamed.at(1).as_string()->data;
desc.entries.push_back(o);
});
return desc;
}
} // namespace
DgoTool::DgoTool() : Tool("dgo") {}
bool DgoTool::run(const ToolInput& task) {
auto desc = parse_desc_file(task.input, m_reader);
build_dgo(desc);
return true;
}
std::vector<std::string> DgoTool::get_additional_dependencies(const ToolInput& task) {
std::vector<std::string> result;
auto desc = parse_desc_file(task.input, m_reader);
for (auto& x : desc.entries) {
result.push_back(fmt::format("out/obj/{}", x.file_name));
}
return result;
}
TpageDirTool::TpageDirTool() : Tool("tpage-dir") {}
bool TpageDirTool::run(const ToolInput& task) {
compile_dir_tpages(task.input);
return true;
}
CopyTool::CopyTool() : Tool("copy") {}
bool CopyTool::run(const ToolInput& task) {
for (auto& out : task.output) {
std::filesystem::copy(std::filesystem::path(file_util::get_file_path({task.input})),
std::filesystem::path(file_util::get_file_path({out})),
std::filesystem::copy_options::overwrite_existing);
}
return true;
}
GameCntTool::GameCntTool() : Tool("game-cnt") {}
bool GameCntTool::run(const ToolInput& task) {
compile_game_count(task.input);
return true;
}
TextTool::TextTool() : Tool("text") {}
bool TextTool::run(const ToolInput& task) {
compile_game_text(task.input);
return true;
}
GroupTool::GroupTool() : Tool("group") {}
bool GroupTool::run(const ToolInput&) {
return true;
}

57
goalc/make/Tools.h Normal file
View file

@ -0,0 +1,57 @@
#pragma once
#include "goalc/make/Tool.h"
#include "common/goos/Reader.h"
class Compiler;
class CompilerTool : public Tool {
public:
CompilerTool(Compiler* compiler);
bool run(const ToolInput& task) override;
bool needs_run(const ToolInput& task) override;
private:
Compiler* m_compiler = nullptr;
};
class DgoTool : public Tool {
public:
DgoTool();
bool run(const ToolInput& task) override;
std::vector<std::string> get_additional_dependencies(const ToolInput&) override;
private:
goos::Reader m_reader;
};
class TpageDirTool : public Tool {
public:
TpageDirTool();
bool run(const ToolInput& task) override;
};
class CopyTool : public Tool {
public:
CopyTool();
bool run(const ToolInput& task) override;
};
class GameCntTool : public Tool {
public:
GameCntTool();
bool run(const ToolInput& task) override;
};
class TextTool : public Tool {
public:
TextTool();
bool run(const ToolInput& task) override;
};
class GroupTool : public Tool {
public:
GroupTool();
bool run(const ToolInput& task) override;
};

View file

@ -99,6 +99,8 @@
;; set up indentation for GOAL keywords
(put 'with-pp 'common-lisp-indent-function 0)
(put 'while 'common-lisp-indent-function 1)
(put 'goal-src 'common-lisp-indent-function 1)
(put 'engine-src 'common-lisp-indent-function 1)
(put 'rlet 'common-lisp-indent-function 1)
(put 'until 'common-lisp-indent-function 1)
(put 'countdown 'common-lisp-indent-function 1)

View file

@ -47,15 +47,12 @@ echo " ================ Running offline decompiler tests..."
echo " ================ Decompiling..."
../scripts/shell/decomp.sh
echo " ================ Building assets..."
../scripts/shell/gc.sh -cmd \(build-data\)
echo " ================ Building project..."
../scripts/shell/gc.sh -cmd \(make-group\ \"iso\"\)
echo " ================ Checking assets..."
../scripts/shell/check.sh
echo " ================ Building game..."
../scripts/shell/gc.sh -cmd \(build-game\)
echo " ================ Booting game..."
../scripts/shell/boot_game.sh

View file

@ -115,6 +115,10 @@ std::vector<std::string> get_test_pass_string(const std::string& name, int count
}
} // namespace
TEST_F(WithGameTests, MakeSystem) {
compiler.run_front_end_on_string("(make \"out/iso/ENGINE.CGO\")");
}
TEST_F(WithGameTests, ReturnConstant) {
runner.run_static_test(env, testCategory, "defun-return-constant.static.gc", {"12\n"});
}

View file

@ -1319,3 +1319,17 @@ TEST(GoosBuiltins, Error) {
Interpreter i;
EXPECT_ANY_THROW(e(i, "(error \"hi\")"));
}
TEST(GoosBuiltins, Ash) {
Interpreter i;
EXPECT_EQ(e(i, "(ash 3 2)"), "12");
EXPECT_EQ(e(i, "(ash 3 -1)"), "1");
}
TEST(GoosBuiltins, StringUtils) {
Interpreter i;
EXPECT_EQ(e(i, "(string-ref \"test\" 2)"), "#\\s");
EXPECT_EQ(e(i, "(string-length \"test\")"), "4");
EXPECT_EQ(e(i, "(string-append \"hello\" \" \" \"world\")"), "\"hello world\"");
EXPECT_EQ(e(i, "(symbol->string 'test)"), "\"test\"");
}