diff --git a/common/goos/Interpreter.cpp b/common/goos/Interpreter.cpp index 990ff4fba..3941ee039 100644 --- a/common/goos/Interpreter.cpp +++ b/common/goos/Interpreter.cpp @@ -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&)>& 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_ptrsecond))(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, ¯o_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&) { + vararg_check(form, args, {ObjectType::SYMBOL}, {}); + return StringObject::make_new(args.unnamed.at(0).as_symbol()->name); +} } // namespace goos diff --git a/common/goos/Interpreter.h b/common/goos/Interpreter.h index db8225801..50fb75750 100644 --- a/common/goos/Interpreter.h +++ b/common/goos/Interpreter.h @@ -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& 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& env); Object intern(const std::string& name); void disable_printfs(); @@ -36,6 +38,12 @@ class Interpreter { const std::shared_ptr& env); bool truthy(const Object& o); + void register_form( + const std::string& name, + const std::function< + Object(const Object&, Arguments&, const std::shared_ptr&)>& form); + void eval_args(Arguments* args, const std::shared_ptr& env); + Reader reader; Object global_environment; Object goal_env; @@ -59,7 +67,6 @@ class Interpreter { const std::unordered_map>>& named); Object eval_pair(const Object& o, const std::shared_ptr& env); - void eval_args(Arguments* args, const std::shared_ptr& env); ArgumentSpec parse_arg_spec(const Object& form, Object& rest); Object quasiquote_helper(const Object& form, const std::shared_ptr& env); @@ -198,6 +205,9 @@ class Interpreter { Object eval_ash(const Object& form, Arguments& args, const std::shared_ptr& env); + Object eval_symbol_to_string(const Object& form, + Arguments& args, + const std::shared_ptr& env); // specials Object eval_define(const Object& form, @@ -239,6 +249,11 @@ class Interpreter { Arguments& args, const std::shared_ptr& env)> builtin_forms; + + std::unordered_map< + std::string, + std::function&)>> + m_custom_forms; std::unordered_map f) { // exit if display window was closed if (glfwWindowShouldClose(Display::display)) { // Display::KillDisplay(Display::display); - MasterExit = 1; + MasterExit = 2; } } } diff --git a/goal_src/dgos/engine.gd b/goal_src/dgos/engine.gd new file mode 100644 index 000000000..44d32facc --- /dev/null +++ b/goal_src/dgos/engine.gd @@ -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") + ) \ No newline at end of file diff --git a/goal_src/dgos/game.gd b/goal_src/dgos/game.gd new file mode 100644 index 000000000..331d94077 --- /dev/null +++ b/goal_src/dgos/game.gd @@ -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") + ) diff --git a/goal_src/dgos/kernel.gd b/goal_src/dgos/kernel.gd new file mode 100644 index 000000000..4df9a0e14 --- /dev/null +++ b/goal_src/dgos/kernel.gd @@ -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") + ) \ No newline at end of file diff --git a/goal_src/dgos/vi1.gd b/goal_src/dgos/vi1.gd new file mode 100644 index 000000000..150358c84 --- /dev/null +++ b/goal_src/dgos/vi1.gd @@ -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") + ) \ No newline at end of file diff --git a/goal_src/engine/ui/text.gc b/goal_src/engine/ui/text.gc index af762a8bf..9dde22be7 100644 --- a/goal_src/engine/ui/text.gc +++ b/goal_src/engine/ui/text.gc @@ -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 ) diff --git a/goal_src/game.gp b/goal_src/game.gp new file mode 100644 index 000000000..e2bced669 --- /dev/null +++ b/goal_src/game.gp @@ -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" + ) + + diff --git a/goal_src/goal-lib.gc b/goal_src/goal-lib.gc index 3c01a6d46..4f69000dc 100644 --- a/goal_src/goal-lib.gc +++ b/goal_src/goal-lib.gc @@ -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") diff --git a/goalc/CMakeLists.txt b/goalc/CMakeLists.txt index c5b6a9c00..02824890e 100644 --- a/goalc/CMakeLists.txt +++ b/goalc/CMakeLists.txt @@ -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 @@ -42,15 +45,15 @@ add_library(compiler target_link_libraries(compiler common Zydis) -if(WIN32) +if (WIN32) target_link_libraries(compiler mman) -endif() +endif () -if(UNIX) +if (UNIX) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O2") -elseif(WIN32) +elseif (WIN32) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /O2") -endif() +endif () add_executable(goalc main.cpp) target_link_libraries(goalc common Zydis compiler) diff --git a/goalc/compiler/Compiler.cpp b/goalc/compiler/Compiler.cpp index edc4c59f1..37f702d72 100644 --- a/goalc/compiler/Compiler.cpp +++ b/goalc/compiler/Compiler.cpp @@ -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 #include +#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 repl) m_global_env = std::make_unique(); m_none = std::make_unique(m_ts.make_typespec("none")); - // compile GOAL library + // let the build system run us + m_make.add_tool(std::make_shared(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); +} \ No newline at end of file diff --git a/goalc/compiler/Compiler.h b/goalc/compiler/Compiler.h index 56353295d..cc58e0079 100644 --- a/goalc/compiler/Compiler.h +++ b/goalc/compiler/Compiler.h @@ -2,19 +2,22 @@ #include #include -#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> const& user_data); + bool knows_object_file(const std::string& name); private: + TypeSystem m_ts; + std::unique_ptr m_global_env = nullptr; + std::unique_ptr 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 m_symbol_types; + std::unordered_map, goos::Object> m_global_constants; + std::unordered_map, LambdaVal*> m_inlineable_functions; + CompilerSettings m_settings; + bool m_throw_on_define_extern_redefinition = false; + SymbolInfoMap m_symbol_info; + std::unique_ptr m_repl; + MakeSystem m_make; + std::set lookup_symbol_infos_starting_with(const std::string& prefix) const; std::vector* 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 m_global_env = nullptr; - std::unique_ptr 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 m_symbol_types; - std::unordered_map, goos::Object> m_global_constants; - std::unordered_map, LambdaVal*> m_inlineable_functions; - CompilerSettings m_settings; - bool m_throw_on_define_extern_redefinition = false; - SymbolInfoMap m_symbol_info; - std::unique_ptr 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); diff --git a/goalc/compiler/compilation/Atoms.cpp b/goalc/compiler/compilation/Atoms.cpp index f1b03485e..611cc663b 100644 --- a/goalc/compiler/compilation/Atoms.cpp +++ b/goalc/compiler/compilation/Atoms.cpp @@ -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}, diff --git a/goalc/compiler/compilation/CompilerControl.cpp b/goalc/compiler/compilation/CompilerControl.cpp index 2a945be96..05deb0556 100644 --- a/goalc/compiler/compilation/CompilerControl.cpp +++ b/goalc/compiler/compilation/CompilerControl.cpp @@ -4,18 +4,19 @@ */ #include -#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 #include +#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> 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); } } @@ -574,4 +578,30 @@ std::vector* Compiler::lookup_exact_name_info(const std::string& nam } else { 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(); } \ No newline at end of file diff --git a/goalc/data_compiler/dir_tpages.cpp b/goalc/data_compiler/dir_tpages.cpp index 37dca4041..93b244980 100644 --- a/goalc/data_compiler/dir_tpages.cpp +++ b/goalc/data_compiler/dir_tpages.cpp @@ -8,8 +8,6 @@ void compile_dir_tpages(const std::string& filename) { std::vector lengths; - printf("[Build tpage dir] %s\n", filename.c_str()); - goos::Reader reader; auto code = reader.read_from_file({filename}); std::string err; diff --git a/goalc/data_compiler/game_count.cpp b/goalc/data_compiler/game_count.cpp index c15a5b17a..0edcf726b 100644 --- a/goalc/data_compiler/game_count.cpp +++ b/goalc/data_compiler/game_count.cpp @@ -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; diff --git a/goalc/debugger/Debugger.cpp b/goalc/debugger/Debugger.cpp index ffa1c982c..88f7520e5 100644 --- a/goalc/debugger/Debugger.cpp +++ b/goalc/debugger/Debugger.cpp @@ -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. @@ -751,4 +751,8 @@ 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(); } \ No newline at end of file diff --git a/goalc/debugger/Debugger.h b/goalc/debugger/Debugger.h index 50a7736e2..169b56ac3 100644 --- a/goalc/debugger/Debugger.h +++ b/goalc/debugger/Debugger.h @@ -6,16 +6,16 @@ #pragma once -#include -#include -#include #include +#include +#include #include +#include +#include +#include "DebugInfo.h" #include "common/common_types.h" #include "common/cross_os_debug/xdbg.h" #include "goalc/listener/MemoryMap.h" -#include "DebugInfo.h" -#include 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); diff --git a/goalc/main.cpp b/goalc/main.cpp index 3b0cee6e5..a0664d20f 100644 --- a/goalc/main.cpp +++ b/goalc/main.cpp @@ -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 = std::make_unique(); + std::unique_ptr 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->run_front_end_on_string(argument); } } catch (std::exception& e) { diff --git a/goalc/make/MakeSystem.cpp b/goalc/make/MakeSystem.cpp new file mode 100644 index 000000000..ac5c264d8 --- /dev/null +++ b/goalc/make/MakeSystem.cpp @@ -0,0 +1,328 @@ +#include + +#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& env) { + return handle_defstep(obj, args, env); + }); + + m_goos.register_form("basename", [=](const goos::Object& obj, goos::Arguments& args, + const std::shared_ptr& env) { + return handle_basename(obj, args, env); + }); + + m_goos.register_form("stem", [=](const goos::Object& obj, goos::Arguments& args, + const std::shared_ptr& env) { + return handle_stem(obj, args, env); + }); + + m_goos.set_global_variable_to_symbol("ASSETS", "#t"); + + add_tool(); + add_tool(); + add_tool(); + add_tool(); + add_tool(); + add_tool(); +} + +/*! + * 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& 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(); + + 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>& unnamed, + const std::unordered_map>>& + 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& 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& 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* result, + std::unordered_set* 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 MakeSystem::get_dependencies(const std::string& target) const { + Timer timer; + + std::vector result; + std::unordered_set 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) { + auto& name = tool->name(); + assert(m_tools.find(name) == m_tools.end()); + m_tools[name] = tool; +} + +std::vector MakeSystem::filter_dependencies(const std::vector& all_deps) { + Timer timer; + std::vector result; + std::unordered_set stale_deps; + + std::unordered_set 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; +} \ No newline at end of file diff --git a/goalc/make/MakeSystem.h b/goalc/make/MakeSystem.h new file mode 100644 index 000000000..2e53fc1c1 --- /dev/null +++ b/goalc/make/MakeSystem.h @@ -0,0 +1,61 @@ +#pragma once + +#include "common/goos/Interpreter.h" +#include "goalc/make/Tool.h" + +struct MakeStep { + std::string input; + std::vector 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& env); + + goos::Object handle_basename(const goos::Object& obj, + goos::Arguments& args, + const std::shared_ptr& env); + + goos::Object handle_stem(const goos::Object& obj, + goos::Arguments&, + const std::shared_ptr& env); + + std::vector get_dependencies(const std::string& target) const; + std::vector filter_dependencies(const std::vector& all_deps); + + bool make(const std::string& target, bool force, bool verbose); + + void add_tool(std::shared_ptr tool); + + template + void add_tool() { + add_tool(std::make_shared()); + } + + void clear_project(); + + private: + void va_check(const goos::Object& form, + const goos::Arguments& args, + const std::vector>& unnamed, + const std::unordered_map>>& named); + + void get_dependencies(const std::string& master_target, + const std::string& output, + std::vector* result_order, + std::unordered_set* result_set) const; + + goos::Interpreter m_goos; + + std::unordered_map> m_output_to_step; + std::unordered_map> m_tools; +}; diff --git a/goalc/make/Tool.cpp b/goalc/make/Tool.cpp new file mode 100644 index 000000000..e88189b74 --- /dev/null +++ b/goalc/make/Tool.cpp @@ -0,0 +1,59 @@ + +#include +#include + +#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; +} diff --git a/goalc/make/Tool.h b/goalc/make/Tool.h new file mode 100644 index 000000000..5f5844799 --- /dev/null +++ b/goalc/make/Tool.h @@ -0,0 +1,25 @@ +#pragma once + +#include +#include +#include + +struct ToolInput { + std::string& input; // the input file + std::vector& deps; // explicit dependencies + std::vector& output; // produced output files. +}; + +class Tool { + public: + Tool(const std::string& name); + virtual bool run(const ToolInput& task) = 0; + virtual std::vector 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; +}; \ No newline at end of file diff --git a/goalc/make/Tools.cpp b/goalc/make/Tools.cpp new file mode 100644 index 000000000..69f96fc57 --- /dev/null +++ b/goalc/make/Tools.cpp @@ -0,0 +1,121 @@ + + +#include "Tools.h" + +#include +#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 DgoTool::get_additional_dependencies(const ToolInput& task) { + std::vector 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; +} \ No newline at end of file diff --git a/goalc/make/Tools.h b/goalc/make/Tools.h new file mode 100644 index 000000000..17baec819 --- /dev/null +++ b/goalc/make/Tools.h @@ -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 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; +}; \ No newline at end of file diff --git a/scripts/emacs/goal-config.el b/scripts/emacs/goal-config.el index da7a12348..69f7fe3e5 100644 --- a/scripts/emacs/goal-config.el +++ b/scripts/emacs/goal-config.el @@ -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) diff --git a/scripts/shell/offline_test_git_branch.sh b/scripts/shell/offline_test_git_branch.sh index 605a568f9..325f2160b 100755 --- a/scripts/shell/offline_test_git_branch.sh +++ b/scripts/shell/offline_test_git_branch.sh @@ -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 diff --git a/test/goalc/test_with_game.cpp b/test/goalc/test_with_game.cpp index 09ccf0da3..aff11c645 100644 --- a/test/goalc/test_with_game.cpp +++ b/test/goalc/test_with_game.cpp @@ -115,6 +115,10 @@ std::vector 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"}); } diff --git a/test/test_goos.cpp b/test/test_goos.cpp index 4bbd2d547..5064ea4d7 100644 --- a/test/test_goos.cpp +++ b/test/test_goos.cpp @@ -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\""); +} \ No newline at end of file