mirror of
https://github.com/open-goal/jak-project
synced 2026-07-09 23:01:56 -04:00
jak2: significantly reduce the verbosity of the game.gp file (#2103)
This commit is contained in:
@@ -9,8 +9,10 @@
|
||||
|
||||
#include "ParseHelpers.h"
|
||||
|
||||
#include "common/goos/Printer.h"
|
||||
#include "common/log/log.h"
|
||||
#include "common/util/FileUtil.h"
|
||||
#include "common/util/string_util.h"
|
||||
#include "common/util/unicode_util.h"
|
||||
|
||||
#include "third-party/fmt/core.h"
|
||||
@@ -53,6 +55,7 @@ Interpreter::Interpreter(const std::string& username) {
|
||||
{"begin", &Interpreter::eval_begin},
|
||||
{"exit", &Interpreter::eval_exit},
|
||||
{"read", &Interpreter::eval_read},
|
||||
{"read-data-file", &Interpreter::eval_read_data_file},
|
||||
{"read-file", &Interpreter::eval_read_file},
|
||||
{"print", &Interpreter::eval_print},
|
||||
{"inspect", &Interpreter::eval_inspect},
|
||||
@@ -82,6 +85,9 @@ Interpreter::Interpreter(const std::string& username) {
|
||||
{"string-ref", &Interpreter::eval_string_ref},
|
||||
{"string-length", &Interpreter::eval_string_length},
|
||||
{"string-append", &Interpreter::eval_string_append},
|
||||
{"string-starts-with?", &Interpreter::eval_string_starts_with},
|
||||
{"string-ends-with?", &Interpreter::eval_string_ends_with},
|
||||
{"string-split", &Interpreter::eval_string_split},
|
||||
{"ash", &Interpreter::eval_ash},
|
||||
{"symbol->string", &Interpreter::eval_symbol_to_string},
|
||||
{"string->symbol", &Interpreter::eval_string_to_symbol},
|
||||
@@ -1002,6 +1008,23 @@ Object Interpreter::eval_read(const Object& form,
|
||||
return Object::make_empty_list();
|
||||
}
|
||||
|
||||
/*!
|
||||
* Reads list data from a file, returns the pair. Not a lot of safety here!
|
||||
*/
|
||||
Object Interpreter::eval_read_data_file(const Object& form,
|
||||
Arguments& args,
|
||||
const std::shared_ptr<EnvironmentObject>& env) {
|
||||
(void)env;
|
||||
vararg_check(form, args, {ObjectType::STRING}, {});
|
||||
|
||||
try {
|
||||
return reader.read_from_file({args.unnamed.at(0).as_string()->data}).as_pair()->cdr;
|
||||
} catch (std::runtime_error& e) {
|
||||
throw_eval_error(form, std::string("reader error inside of read-file:\n") + e.what());
|
||||
}
|
||||
return Object::make_empty_list();
|
||||
}
|
||||
|
||||
/*!
|
||||
* Open and run the Reader on a text file.
|
||||
*/
|
||||
@@ -1648,6 +1671,45 @@ Object Interpreter::eval_string_append(const Object& form,
|
||||
return StringObject::make_new(result);
|
||||
}
|
||||
|
||||
Object Interpreter::eval_string_starts_with(const Object& form,
|
||||
Arguments& args,
|
||||
const std::shared_ptr<EnvironmentObject>& env) {
|
||||
(void)env;
|
||||
vararg_check(form, args, {ObjectType::STRING, ObjectType::STRING}, {});
|
||||
auto& str = args.unnamed.at(0).as_string()->data;
|
||||
auto& suffix = args.unnamed.at(1).as_string()->data;
|
||||
|
||||
if (str_util::starts_with(str, suffix)) {
|
||||
return SymbolObject::make_new(reader.symbolTable, "#t");
|
||||
}
|
||||
return SymbolObject::make_new(reader.symbolTable, "#f");
|
||||
}
|
||||
|
||||
Object Interpreter::eval_string_ends_with(const Object& form,
|
||||
Arguments& args,
|
||||
const std::shared_ptr<EnvironmentObject>& env) {
|
||||
(void)env;
|
||||
vararg_check(form, args, {ObjectType::STRING, ObjectType::STRING}, {});
|
||||
auto& str = args.unnamed.at(0).as_string()->data;
|
||||
auto& suffix = args.unnamed.at(1).as_string()->data;
|
||||
|
||||
if (str_util::ends_with(str, suffix)) {
|
||||
return SymbolObject::make_new(reader.symbolTable, "#t");
|
||||
}
|
||||
return SymbolObject::make_new(reader.symbolTable, "#f");
|
||||
}
|
||||
|
||||
Object Interpreter::eval_string_split(const Object& form,
|
||||
Arguments& args,
|
||||
const std::shared_ptr<EnvironmentObject>& env) {
|
||||
(void)env;
|
||||
vararg_check(form, args, {ObjectType::STRING, ObjectType::STRING}, {});
|
||||
auto& str = args.unnamed.at(0).as_string()->data;
|
||||
auto& delim = args.unnamed.at(1).as_string()->data;
|
||||
|
||||
return pretty_print::build_list(str_util::split(str, delim.at(0)));
|
||||
}
|
||||
|
||||
Object Interpreter::eval_ash(const Object& form,
|
||||
Arguments& args,
|
||||
const std::shared_ptr<EnvironmentObject>& env) {
|
||||
|
||||
@@ -116,6 +116,9 @@ class Interpreter {
|
||||
Object eval_read(const Object& form,
|
||||
Arguments& args,
|
||||
const std::shared_ptr<EnvironmentObject>& env);
|
||||
Object eval_read_data_file(const Object& form,
|
||||
Arguments& args,
|
||||
const std::shared_ptr<EnvironmentObject>& env);
|
||||
Object eval_read_file(const Object& form,
|
||||
Arguments& args,
|
||||
const std::shared_ptr<EnvironmentObject>& env);
|
||||
@@ -197,6 +200,15 @@ class Interpreter {
|
||||
Object eval_string_append(const Object& form,
|
||||
Arguments& args,
|
||||
const std::shared_ptr<EnvironmentObject>& env);
|
||||
Object eval_string_starts_with(const Object& form,
|
||||
Arguments& args,
|
||||
const std::shared_ptr<EnvironmentObject>& env);
|
||||
Object eval_string_ends_with(const Object& form,
|
||||
Arguments& args,
|
||||
const std::shared_ptr<EnvironmentObject>& env);
|
||||
Object eval_string_split(const Object& form,
|
||||
Arguments& args,
|
||||
const std::shared_ptr<EnvironmentObject>& env);
|
||||
Object eval_ash(const Object& form,
|
||||
Arguments& args,
|
||||
const std::shared_ptr<EnvironmentObject>& env);
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
|
||||
#include "FileUtil.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstdio> /* defines FILENAME_MAX */
|
||||
#include <cstdlib>
|
||||
#include <fstream>
|
||||
@@ -338,6 +339,29 @@ std::string base_name_no_ext(const std::string& filename) {
|
||||
;
|
||||
}
|
||||
|
||||
std::string split_path_at(const fs::path& path, const std::vector<std::string>& folders) {
|
||||
std::string split_str = "";
|
||||
for (const auto& folder : folders) {
|
||||
#ifdef _WIN32
|
||||
split_str += folder + "\\";
|
||||
#else
|
||||
split_str += folder + "/";
|
||||
#endif
|
||||
}
|
||||
const auto& path_str = path.u8string();
|
||||
return path_str.substr(path_str.find(split_str) + split_str.length());
|
||||
}
|
||||
|
||||
std::string convert_to_unix_path_separators(const std::string& path) {
|
||||
#ifdef _WIN32
|
||||
std::string copy = path;
|
||||
std::replace(copy.begin(), copy.end(), '\\', '/');
|
||||
return copy;
|
||||
#else
|
||||
return path;
|
||||
#endif
|
||||
}
|
||||
|
||||
void ISONameFromAnimationName(char* dst, const char* src) {
|
||||
// The Animation Name is a bunch of words separated by dashes
|
||||
|
||||
|
||||
@@ -53,6 +53,8 @@ std::string combine_path(const std::string& parent, const std::string& child);
|
||||
bool file_exists(const std::string& path);
|
||||
std::string base_name(const std::string& filename);
|
||||
std::string base_name_no_ext(const std::string& filename);
|
||||
std::string split_path_at(const fs::path& path, const std::vector<std::string>& folders);
|
||||
std::string convert_to_unix_path_separators(const std::string& path);
|
||||
void MakeISOName(char* dst, const char* src);
|
||||
void ISONameFromAnimationName(char* dst, const char* src);
|
||||
void assert_file_exists(const char* path, const char* error_message);
|
||||
|
||||
@@ -13,15 +13,12 @@ bool contains(const std::string& s, const std::string& substr) {
|
||||
}
|
||||
|
||||
bool starts_with(const std::string& s, const std::string& prefix) {
|
||||
return s.rfind(prefix) == 0;
|
||||
return s.size() >= prefix.size() && 0 == s.compare(0, prefix.size(), prefix);
|
||||
}
|
||||
|
||||
bool ends_with(const std::string& s, const std::string& suffix) {
|
||||
if (s.length() >= suffix.length()) {
|
||||
return !s.compare(s.length() - suffix.length(), suffix.length(), suffix);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
return s.size() >= suffix.size() &&
|
||||
0 == s.compare(s.size() - suffix.size(), suffix.size(), suffix);
|
||||
}
|
||||
|
||||
std::string ltrim(const std::string& s) {
|
||||
|
||||
@@ -232,7 +232,6 @@
|
||||
("game-task.o" "game-task")
|
||||
("game-save.o" "game-save")
|
||||
("settings.o" "settings")
|
||||
("pckernel.o" "pckernel") ;; added
|
||||
("mood-tables.o" "mood-tables")
|
||||
("mood-tables2.o" "mood-tables2")
|
||||
("mood.o" "mood")
|
||||
@@ -326,6 +325,7 @@
|
||||
("prototype.o" "prototype")
|
||||
("main-collide.o" "main-collide")
|
||||
("video.o" "video")
|
||||
("pckernel.o" "pckernel") ;; added
|
||||
("main.o" "main")
|
||||
("collide-cache.o" "collide-cache")
|
||||
("collide-debug.o" "collide-debug")
|
||||
|
||||
@@ -29,8 +29,8 @@
|
||||
("dma-buffer.o" "dma-buffer")
|
||||
("dma-bucket.o" "dma-bucket")
|
||||
("dma-disasm.o" "dma-disasm")
|
||||
("pckernel-h.o" "pckernel-h") ;; added
|
||||
("pad.o" "pad")
|
||||
("pckernel-h.o" "pckernel-h") ;; added
|
||||
("gs.o" "gs")
|
||||
("display-h.o" "display-h")
|
||||
("geometry.o" "geometry")
|
||||
@@ -326,6 +326,7 @@
|
||||
("prototype.o" "prototype")
|
||||
("main-collide.o" "main-collide")
|
||||
("video.o" "video")
|
||||
("pckernel.o" "pckernel") ;; added
|
||||
("main.o" "main")
|
||||
("collide-cache.o" "collide-cache")
|
||||
("collide-debug.o" "collide-debug")
|
||||
|
||||
+175
-4451
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,199 @@
|
||||
;;-*-Lisp-*-
|
||||
|
||||
;; TODO extract most of this into a common lib that isn't so game dependent
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; Build system macros
|
||||
;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
(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"
|
||||
`(let ((output-file ,(gc-file->o-file src-file)))
|
||||
(set! *all-gc* (cons output-file *all-gc*))
|
||||
(defstep :in ,(string-append "goal_src/jak2/" src-file)
|
||||
;; use goal compiler
|
||||
:tool 'goalc
|
||||
;; will output the obj file
|
||||
:out (list output-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"
|
||||
`(let ((output-file ,(gc-file->o-file current)))
|
||||
(set! *all-gc* (cons output-file *all-gc*))
|
||||
(defstep :in ,(string-append "goal_src/jak2/" prefix current)
|
||||
:tool 'goalc
|
||||
:out (list output-file)
|
||||
:dep '(,(gc-file->o-file previous))
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
;; TODO - deps should probably just treated as a proper list to refactor duplication
|
||||
(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)
|
||||
)
|
||||
)
|
||||
|
||||
(defun cgo (output-name desc-file-name)
|
||||
"Add a CGO with the given output name (in $OUT/iso) and input name (in goal_src/jak2/dgos)"
|
||||
(let ((out-name (string-append "$OUT/iso/" output-name)))
|
||||
(defstep :in (string-append "goal_src/jak2/dgos/" desc-file-name)
|
||||
:tool 'dgo
|
||||
:out `(,out-name)
|
||||
)
|
||||
(set! *all-cgos* (cons out-name *all-cgos*))
|
||||
)
|
||||
)
|
||||
|
||||
(defun tpage-name (id)
|
||||
"Get the name of the tpage obj file with the given id"
|
||||
(fmt #f "tpage-{}.go" id)
|
||||
)
|
||||
|
||||
(defmacro copy-texture (tpage-id)
|
||||
"Copy a texture from the game, using the given tpage ID"
|
||||
(let* ((path (string-append "$DECOMP/raw_obj/" (tpage-name tpage-id))))
|
||||
`(defstep :in ,path
|
||||
: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)
|
||||
(let* ((path (string-append "$DECOMP/raw_obj/" name ".go")))
|
||||
`(defstep :in ,path
|
||||
: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))
|
||||
)
|
||||
|
||||
(defun group-list (name stuff)
|
||||
(defstep :in ""
|
||||
:tool 'group
|
||||
:out `(,(string-append "GROUP:" name))
|
||||
:dep stuff)
|
||||
)
|
||||
|
||||
|
||||
(defun copy-iso-file (name subdir ext)
|
||||
(let* ((path (string-append "$ISO/" subdir name ext))
|
||||
(out-name (string-append "$OUT/iso/" name ext)))
|
||||
(defstep :in path
|
||||
:tool 'copy
|
||||
:out `(,out-name))
|
||||
out-name))
|
||||
|
||||
(defmacro copy-strs (&rest strs)
|
||||
`(begin ,@(apply (lambda (x) `(set! *all-str* (cons (copy-iso-file ,x "STR/" ".STR") *all-str*))) strs)))
|
||||
|
||||
(defmacro copy-sbk-files (&rest files)
|
||||
`(begin ,@(apply (lambda (x) `(set! *all-sbk* (cons (copy-iso-file ,x "SBK/" ".SBK") *all-sbk*))) files)))
|
||||
|
||||
(defmacro copy-mus-files (&rest files)
|
||||
`(begin ,@(apply (lambda (x) `(set! *all-mus* (cons (copy-iso-file ,x "MUS/" ".MUS") *all-mus*))) files)))
|
||||
|
||||
(defmacro copy-vag-files (&rest files)
|
||||
`(begin ,@(apply (lambda (x) `(set! *all-vag* (cons (copy-iso-file "VAGWAD" "VAG/" (string-append "." ,x)) *all-vag*))) files)))
|
||||
|
||||
(defun reverse-list (list)
|
||||
(let ((new-list '())
|
||||
(curr-elt list))
|
||||
(while (not (null? curr-elt))
|
||||
(set! new-list (cons (car curr-elt) new-list))
|
||||
(set! curr-elt (cdr curr-elt)))
|
||||
new-list))
|
||||
|
||||
(defmacro cgo-file (dgo-file-name deps)
|
||||
;; First read in the DGO file, it has pretty much everything we need
|
||||
(let ((dgo-data (car (read-data-file (string-append "goal_src/jak2/dgos/" dgo-file-name)))))
|
||||
;; Get the name of the DGO
|
||||
(let ((dgo-name (car dgo-data))
|
||||
(files (cdr dgo-data))
|
||||
(gsrc-seq-args '())
|
||||
(textures '())
|
||||
(gos '()))
|
||||
;; create the dgo step
|
||||
(cgo dgo-name dgo-file-name)
|
||||
;; Now we iterate through the list of files, skipping ones we've already processed
|
||||
;; and creating steps for the ones that are new!
|
||||
(while (not (null? files))
|
||||
(let ((file-name (car (car files)))
|
||||
(obj-name (car (cdr (car files)))))
|
||||
;; Check to see if we've already handled this file
|
||||
(when (not (car (hash-table-try-ref *file-entry-map* file-name)))
|
||||
;; Depending on the type of file, generate the appropriate steps
|
||||
(cond
|
||||
((string-ends-with? file-name ".o")
|
||||
;; build up a list of all gsrc files needing to be compiled
|
||||
(let ((gsrc-path (get-gsrc-path obj-name)))
|
||||
(set! gsrc-seq-args (cons gsrc-path gsrc-seq-args))))
|
||||
((string-starts-with? obj-name "tpage-")
|
||||
;; copy textures
|
||||
(let ((tpage-id (car (cdr (string-split obj-name "-")))))
|
||||
(set! textures (cons tpage-id textures))))
|
||||
((string-ends-with? file-name ".go")
|
||||
;; copy art files
|
||||
(set! gos (cons (stem file-name) gos))))
|
||||
;; Update the map so this file isn't processed again
|
||||
(hash-table-set! *file-entry-map* file-name #f)))
|
||||
(set! files (cdr files)))
|
||||
;; TODO - need an `append`!, reverse lists by re-cons'ing them for now
|
||||
(set! gsrc-seq-args (reverse-list gsrc-seq-args))
|
||||
(set! textures (reverse-list textures))
|
||||
(set! gos (reverse-list gos))
|
||||
`(begin
|
||||
;; macros can't return nothing, so these macros assume they will be given a non-empty list
|
||||
(when (not (null? '(,@gsrc-seq-args)))
|
||||
(goal-src-sequence "" :deps ,deps ,@gsrc-seq-args))
|
||||
(when (not (null? '(,@textures)))
|
||||
(copy-textures ,@textures))
|
||||
(when (not (null? '(,@gos)))
|
||||
(copy-gos ,@gos)))
|
||||
)
|
||||
))
|
||||
@@ -4,6 +4,7 @@
|
||||
#include "common/log/log.h"
|
||||
#include "common/util/FileUtil.h"
|
||||
#include "common/util/Timer.h"
|
||||
#include "common/util/string_util.h"
|
||||
|
||||
#include "goalc/make/Tools.h"
|
||||
|
||||
@@ -53,6 +54,11 @@ MakeSystem::MakeSystem(const std::string& username) : m_goos(username) {
|
||||
return handle_stem(obj, args, env);
|
||||
});
|
||||
|
||||
m_goos.register_form("get-gsrc-path", [=](const goos::Object& obj, goos::Arguments& args,
|
||||
const std::shared_ptr<goos::EnvironmentObject>& env) {
|
||||
return handle_get_gsrc_path(obj, args, env);
|
||||
});
|
||||
|
||||
m_goos.register_form("map-path!", [=](const goos::Object& obj, goos::Arguments& args,
|
||||
const std::shared_ptr<goos::EnvironmentObject>& env) {
|
||||
return handle_map_path(obj, args, env);
|
||||
@@ -64,6 +70,12 @@ MakeSystem::MakeSystem(const std::string& username) : m_goos(username) {
|
||||
return handle_set_output_prefix(obj, args, env);
|
||||
});
|
||||
|
||||
m_goos.register_form("set-gsrc-folder!",
|
||||
[=](const goos::Object& obj, goos::Arguments& args,
|
||||
const std::shared_ptr<goos::EnvironmentObject>& env) {
|
||||
return handle_set_gsrc_folder(obj, args, env);
|
||||
});
|
||||
|
||||
m_goos.set_global_variable_to_symbol("ASSETS", "#t");
|
||||
|
||||
set_constant("*iso-data*", file_util::get_file_path({"iso_data"}));
|
||||
@@ -193,6 +205,39 @@ goos::Object MakeSystem::handle_stem(const goos::Object& form,
|
||||
return goos::StringObject::make_new(input.stem().u8string());
|
||||
}
|
||||
|
||||
goos::Object MakeSystem::handle_get_gsrc_path(const goos::Object& form,
|
||||
goos::Arguments& args,
|
||||
const std::shared_ptr<goos::EnvironmentObject>& env) {
|
||||
if (m_gsrc_folder.empty()) {
|
||||
throw std::runtime_error("`set-gsrc-folder!` was not called before a `get-src-path`");
|
||||
}
|
||||
m_goos.eval_args(&args, env);
|
||||
va_check(form, args, {goos::ObjectType::STRING}, {});
|
||||
|
||||
const auto& file_name = args.unnamed.at(0).as_string()->data;
|
||||
|
||||
// Keep things fast by scanning the gsrc directory _once_ on the first call
|
||||
if (m_gsrc_files.empty()) {
|
||||
auto folder = file_util::get_file_path(m_gsrc_folder);
|
||||
auto src_files = file_util::find_files_recursively(folder, std::regex(".*\\.gc"));
|
||||
|
||||
for (const auto& path : src_files) {
|
||||
auto name = file_util::base_name_no_ext(path.u8string());
|
||||
auto gsrc_path =
|
||||
file_util::convert_to_unix_path_separators(file_util::split_path_at(path, m_gsrc_folder));
|
||||
// TODO - this is only "safe" because the current OpenGOAL system requires globally unique
|
||||
// file names
|
||||
m_gsrc_files.emplace(name, gsrc_path);
|
||||
}
|
||||
}
|
||||
|
||||
if (m_gsrc_files.count(file_name) != 0) {
|
||||
return goos::StringObject::make_new(m_gsrc_files.at(file_name));
|
||||
} else {
|
||||
return goos::SymbolObject::make_new(m_goos.reader.symbolTable, "#f");
|
||||
}
|
||||
}
|
||||
|
||||
goos::Object MakeSystem::handle_map_path(const goos::Object& form,
|
||||
goos::Arguments& args,
|
||||
const std::shared_ptr<goos::EnvironmentObject>& env) {
|
||||
@@ -217,10 +262,23 @@ goos::Object MakeSystem::handle_set_output_prefix(
|
||||
return goos::Object::make_empty_list();
|
||||
}
|
||||
|
||||
goos::Object MakeSystem::handle_set_gsrc_folder(
|
||||
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}, {});
|
||||
|
||||
const auto& folder = args.unnamed.at(0).as_string()->data;
|
||||
m_gsrc_folder = str_util::split(folder, '/');
|
||||
return goos::Object::make_empty_list();
|
||||
}
|
||||
|
||||
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 {
|
||||
// fmt::print(output + "\n");
|
||||
if (result_set->find(output) != result_set->end()) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -30,6 +30,10 @@ class MakeSystem {
|
||||
goos::Arguments&,
|
||||
const std::shared_ptr<goos::EnvironmentObject>& env);
|
||||
|
||||
goos::Object handle_get_gsrc_path(const goos::Object& obj,
|
||||
goos::Arguments&,
|
||||
const std::shared_ptr<goos::EnvironmentObject>& env);
|
||||
|
||||
goos::Object handle_map_path(const goos::Object& obj,
|
||||
goos::Arguments& args,
|
||||
const std::shared_ptr<goos::EnvironmentObject>& env);
|
||||
@@ -38,6 +42,10 @@ class MakeSystem {
|
||||
goos::Arguments& args,
|
||||
const std::shared_ptr<goos::EnvironmentObject>& env);
|
||||
|
||||
goos::Object handle_set_gsrc_folder(const goos::Object& obj,
|
||||
goos::Arguments& args,
|
||||
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);
|
||||
|
||||
@@ -76,4 +84,6 @@ class MakeSystem {
|
||||
std::unordered_map<std::string, std::shared_ptr<MakeStep>> m_output_to_step;
|
||||
std::unordered_map<std::string, std::shared_ptr<Tool>> m_tools;
|
||||
PathMap m_path_map;
|
||||
std::vector<std::string> m_gsrc_folder;
|
||||
std::map<std::string, std::string> m_gsrc_files = {};
|
||||
};
|
||||
|
||||
@@ -1,115 +0,0 @@
|
||||
# Generates a file with all `game.gp` code taking the `*.gd` files as input
|
||||
|
||||
# example - python .\scripts\gsrc\skeleton_creation\generate_dgo_project_code.py --game jak2
|
||||
|
||||
import argparse
|
||||
import glob
|
||||
from pathlib import Path
|
||||
import json
|
||||
import os
|
||||
|
||||
# TODO - this is duplication code, but i don't feel like dealing with python's module system right now, its out of `utils.py`
|
||||
|
||||
jak1_files = None
|
||||
jak2_files = None
|
||||
|
||||
with open('./goal_src/jak1/build/all_objs.json', 'r') as f:
|
||||
jak1_files = json.load(f)
|
||||
with open('./goal_src/jak2/build/all_objs.json', 'r') as f:
|
||||
jak2_files = json.load(f)
|
||||
|
||||
def get_file_list(game_name):
|
||||
if game_name == "jak1":
|
||||
return jak1_files
|
||||
else:
|
||||
return jak2_files
|
||||
|
||||
def get_project_path_from_filename(game_name, file_name):
|
||||
file_list = get_file_list(game_name)
|
||||
src_path = ""
|
||||
for f in file_list:
|
||||
if f[2] != 3:
|
||||
continue
|
||||
if f[0] == file_name:
|
||||
src_path = f[4]
|
||||
break
|
||||
path = "./goal_src/{}/{}/{}.gc".format(game_name, src_path, file_name)
|
||||
if not os.path.exists(path):
|
||||
print("{} couldn't find in /goal_src/{}!".format(file_name, game_name))
|
||||
exit(1)
|
||||
return "{}/{}.gc".format(src_path, file_name)
|
||||
|
||||
|
||||
parser = argparse.ArgumentParser("generate_dgo_project_code")
|
||||
parser.add_argument("--game", help="The name of the game", type=str)
|
||||
# TODO - it isn't really established what this should actually be, for example, at the time of writing
|
||||
# jak 2's other DGOs depend on a `los-control` file which is a random file near the end (but not quite) in GAME.CGO
|
||||
#
|
||||
# Until a proper system is figured out, this is basically a best-guess so there's no point trying to be accurate at this stage
|
||||
parser.add_argument("--dep", help="Arbitrary file to make all the DGOs depend upon", type=str)
|
||||
args = parser.parse_args()
|
||||
|
||||
dgos_to_skip = ["common.gd", "engine.gd", "game.gd", "vi1.gd", "kernel.gd", "cta.gd", "lwidea.gd", "cwi.gd", "pri.gd"]
|
||||
output = []
|
||||
file_locations = None
|
||||
|
||||
for name in glob.glob('./goal_src/{}/dgos/*.gd'.format(args.game)):
|
||||
skip_it = False
|
||||
for to_skip in dgos_to_skip:
|
||||
if to_skip in name:
|
||||
skip_it = True
|
||||
break
|
||||
if skip_it:
|
||||
continue
|
||||
# read the file
|
||||
dgo_name = Path(name).stem.upper()
|
||||
# first print a comment header
|
||||
output.append(";;;;;;;;;;;;;;;;;;;;;\n")
|
||||
output.append(";; {}\n".format(dgo_name))
|
||||
output.append(";;;;;;;;;;;;;;;;;;;;;\n")
|
||||
output.append("\n")
|
||||
# print cgo call
|
||||
output.append("(cgo \"{}.DGO\" \"{}.gd\")\n".format(dgo_name, dgo_name.lower()))
|
||||
output.append("\n")
|
||||
|
||||
object_paths = []
|
||||
texture_ids = []
|
||||
# anything that ends with .go
|
||||
copy_names = []
|
||||
|
||||
with open(name, "r") as f:
|
||||
dgo_lines = f.readlines()[1:] # skip the first line, dont care about it
|
||||
for line in dgo_lines:
|
||||
# gross parsing, as usual without a nice data format
|
||||
cleaned_line = line.strip().replace("\"", "").replace("(", "").replace(")", "")
|
||||
if cleaned_line == "":
|
||||
continue
|
||||
object_name = cleaned_line.split(" ")[0]
|
||||
object_name_no_ext = object_name.split(".")[0]
|
||||
if ".o" in object_name:
|
||||
object_paths.append(get_project_path_from_filename(args.game, object_name_no_ext))
|
||||
elif ".go" in object_name:
|
||||
# tpages are different
|
||||
if "tpage" in object_name:
|
||||
texture_ids.append(object_name_no_ext.split("-")[1])
|
||||
else:
|
||||
copy_names.append(object_name_no_ext)
|
||||
|
||||
# Construct the rest of the file
|
||||
if len(object_paths) > 0:
|
||||
output.append("(goal-src-sequence\n \"\"\n :deps (\"$OUT/obj/{}.o\")\n".format(args.dep))
|
||||
for path in object_paths:
|
||||
output.append(" \"{}\"\n".format(path))
|
||||
output.append(" )\n\n")
|
||||
|
||||
if len(texture_ids) > 0:
|
||||
output.append("(copy-textures {})\n\n".format(" ".join(texture_ids)))
|
||||
|
||||
if len(copy_names) > 0:
|
||||
output.append("(copy-gos\n")
|
||||
for name in copy_names:
|
||||
output.append(" \"{}\"\n".format(name))
|
||||
output.append(" )\n\n")
|
||||
|
||||
with open('dgo-proj-code.gp', 'w') as out_file:
|
||||
out_file.writelines(output)
|
||||
Reference in New Issue
Block a user