diff --git a/game/graphics/display.h b/game/graphics/display.h index 1a456e07fd..ff9893603f 100644 --- a/game/graphics/display.h +++ b/game/graphics/display.h @@ -31,6 +31,8 @@ class GfxDisplay { virtual std::shared_ptr get_input_manager() const = 0; virtual void render() = 0; + virtual void init_splash() = 0; + virtual void draw_splash(int fb_w, int fb_h) = 0; void set_imgui_visible(bool visible) { m_imgui_visible = visible; diff --git a/game/graphics/gfx.cpp b/game/graphics/gfx.cpp index e9e5fdfd43..8f2e82ec01 100644 --- a/game/graphics/gfx.cpp +++ b/game/graphics/gfx.cpp @@ -28,6 +28,7 @@ namespace Gfx { std::function vsync_callback; GfxGlobalSettings g_global_settings; game_settings::DebugSettings g_debug_settings; +SplashScreen g_splash; const GfxRendererModule* GetRenderer(GfxPipeline pipeline) { switch (pipeline) { diff --git a/game/graphics/gfx.h b/game/graphics/gfx.h index 0a32416728..ca89495cc9 100644 --- a/game/graphics/gfx.h +++ b/game/graphics/gfx.h @@ -6,8 +6,10 @@ */ #include +#include #include #include +#include #include "common/common_types.h" #include "common/util/FileUtil.h" @@ -130,4 +132,12 @@ void CollisionRendererSetMask(GfxGlobalSettings::CollisionRendererMode mode, s64 void CollisionRendererClearMask(GfxGlobalSettings::CollisionRendererMode mode, s64 mask_id); void CollisionRendererSetMode(GfxGlobalSettings::CollisionRendererMode mode); +struct SplashScreen { + std::vector data; + int width = 0; + int height = 0; + std::atomic ready{false}; +}; +extern SplashScreen g_splash; + } // namespace Gfx diff --git a/game/graphics/opengl_renderer/shaders/splash.frag b/game/graphics/opengl_renderer/shaders/splash.frag new file mode 100644 index 0000000000..61bdb1e6ef --- /dev/null +++ b/game/graphics/opengl_renderer/shaders/splash.frag @@ -0,0 +1,7 @@ +#version 410 core +in vec2 frag_uv; +out vec4 out_color; +uniform sampler2D splash_tex; +void main() { + out_color = texture(splash_tex, frag_uv); +} \ No newline at end of file diff --git a/game/graphics/opengl_renderer/shaders/splash.vert b/game/graphics/opengl_renderer/shaders/splash.vert new file mode 100644 index 0000000000..d25c1f3e0a --- /dev/null +++ b/game/graphics/opengl_renderer/shaders/splash.vert @@ -0,0 +1,17 @@ +#version 410 core +out vec2 frag_uv; +uniform vec2 u_res; +uniform vec2 u_tex; + +void main() { + vec2 pos = vec2(float(gl_VertexID & 1) * 2.0 - 1.0, float(gl_VertexID >> 1) * 2.0 - 1.0); + frag_uv = vec2(pos.x * 0.5 + 0.5, 0.5 - pos.y * 0.5); + + float tex_aspect = u_tex.x / u_tex.y; + float fb_aspect = u_res.x / u_res.y; + vec2 scale = (fb_aspect > tex_aspect) + ? vec2(tex_aspect / fb_aspect, 1.0) + : vec2(1.0, fb_aspect / tex_aspect); + + gl_Position = vec4(pos * scale, 0.0, 1.0); +} \ No newline at end of file diff --git a/game/graphics/pipelines/opengl.cpp b/game/graphics/pipelines/opengl.cpp index a8b149737c..7fe03403d4 100644 --- a/game/graphics/pipelines/opengl.cpp +++ b/game/graphics/pipelines/opengl.cpp @@ -344,7 +344,103 @@ GLDisplay::GLDisplay(SDL_Window* window, SDL_GLContext gl_context, bool is_main) })); } +void GLDisplay::init_splash() { + if (m_splash_program) + return; + if (!Gfx::g_splash.ready.load()) + return; + + auto shader_folder = "game/graphics/opengl_renderer/shaders"; + auto vert_src = + file_util::read_text_file(file_util::get_file_path({shader_folder, "splash.vert"})); + auto frag_src = + file_util::read_text_file(file_util::get_file_path({shader_folder, "splash.frag"})); + + constexpr int len = 1024; + GLint compile_ok; + char err[len]; + + auto compile_shader = [](GLenum type, const char* src, GLint& compile_ok, char* err) -> GLuint { + GLuint s = glCreateShader(type); + glShaderSource(s, 1, &src, nullptr); + glCompileShader(s); + glGetShaderiv(s, GL_COMPILE_STATUS, &compile_ok); + if (!compile_ok) { + glGetShaderInfoLog(s, len, nullptr, err); + lg::error("splash shader compile failed: {}\n", err); + glDeleteShader(s); + return 0; + } + return s; + }; + + GLuint vs = compile_shader(GL_VERTEX_SHADER, vert_src.c_str(), compile_ok, err); + GLuint fs = compile_shader(GL_FRAGMENT_SHADER, frag_src.c_str(), compile_ok, err); + if (!vs || !fs) { + glDeleteShader(vs); + glDeleteShader(fs); + return; + } + + m_splash_program = glCreateProgram(); + glAttachShader(m_splash_program, vs); + glAttachShader(m_splash_program, fs); + glLinkProgram(m_splash_program); + glDeleteShader(vs); + glDeleteShader(fs); + + glGetProgramiv(m_splash_program, GL_LINK_STATUS, &compile_ok); + if (!compile_ok) { + glGetProgramInfoLog(m_splash_program, len, nullptr, err); + lg::error("Failed to link splash shader:\n{}", err); + glDeleteProgram(m_splash_program); + m_splash_program = 0; + return; + } + + if (!Gfx::g_splash.data.empty()) { + glGenTextures(1, &m_splash_texture); + glBindTexture(GL_TEXTURE_2D, m_splash_texture); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, Gfx::g_splash.width, Gfx::g_splash.height, 0, GL_RGBA, + GL_UNSIGNED_BYTE, Gfx::g_splash.data.data()); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glBindTexture(GL_TEXTURE_2D, 0); + Gfx::g_splash.data.clear(); + Gfx::g_splash.data.shrink_to_fit(); + } + + glGenVertexArrays(1, &m_splash_vao); +} + +void GLDisplay::draw_splash(int fb_w, int fb_h) { + if (!m_splash_program || !m_splash_texture) + return; + glBindFramebuffer(GL_FRAMEBUFFER, 0); + glClearColor(0.f, 0.f, 0.f, 1.f); + glClear(GL_COLOR_BUFFER_BIT); + glViewport(0, 0, fb_w, fb_h); + glDisable(GL_DEPTH_TEST); + glDisable(GL_BLEND); + glUseProgram(m_splash_program); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, m_splash_texture); + glUniform1i(glGetUniformLocation(m_splash_program, "splash_tex"), 0); + glUniform2f(glGetUniformLocation(m_splash_program, "u_res"), fb_w, fb_h); + glUniform2f(glGetUniformLocation(m_splash_program, "u_tex"), Gfx::g_splash.width, + Gfx::g_splash.height); + glBindVertexArray(m_splash_vao); + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + glBindVertexArray(0); +} + GLDisplay::~GLDisplay() { + if (m_splash_texture) + glDeleteTextures(1, &m_splash_texture); + if (m_splash_program) + glDeleteProgram(m_splash_program); + if (m_splash_vao) + glDeleteVertexArrays(1, &m_splash_vao); // Cleanup ImGUI ImGuiIO& io = ImGui::GetIO(); io.IniFilename = nullptr; @@ -551,6 +647,16 @@ void GLDisplay::render() { // set the size of the visible/playable portion of the game in the window get_display_manager()->set_game_size(Gfx::g_global_settings.lbox_w, Gfx::g_global_settings.lbox_h); + + // draw splash screen on startup if requested + if (SplashScreen && DiskBoot && !m_splash_program) { + init_splash(); + } + if (SplashScreen && Gfx::g_splash.ready.load() && + SplashTimer.getSeconds() < SPLASH_SCREEN_TIME) { + draw_splash(fbuf_w, fbuf_h); + } + render_game_frame( game_res_w, game_res_h, fbuf_w, fbuf_h, Gfx::g_global_settings.lbox_w, Gfx::g_global_settings.lbox_h, Gfx::g_global_settings.msaa_samples, diff --git a/game/graphics/pipelines/opengl.h b/game/graphics/pipelines/opengl.h index 70ee513693..76c1c00cc1 100644 --- a/game/graphics/pipelines/opengl.h +++ b/game/graphics/pipelines/opengl.h @@ -56,6 +56,13 @@ class GLDisplay : public GfxDisplay { int width = 0; int height = 0; } m_pending_size; + + // splash screen + GLuint m_splash_texture = 0; + GLuint m_splash_program = 0; + GLuint m_splash_vao = 0; + void init_splash(); + void draw_splash(int fb_w, int fb_h); }; extern const GfxRendererModule gRendererOpenGL; diff --git a/game/kernel/common/kboot.cpp b/game/kernel/common/kboot.cpp index 433c6fb303..effa17b0c7 100644 --- a/game/kernel/common/kboot.cpp +++ b/game/kernel/common/kboot.cpp @@ -11,6 +11,10 @@ u32 DiskBoot; // Set to 1 to enable debug heap u32 MasterDebug; +// added in pc port for splash screen +Timer SplashTimer; +u32 SplashScreen; + // Set to 1 to load debug code u32 DebugSegment; @@ -31,6 +35,7 @@ void kboot_init_globals_common() { MasterDebug = 1; DebugSegment = 1; MasterUseKernel = 1; + SplashScreen = 1; strcpy(DebugBootLevel, "#f"); // no specified level strcpy(DebugBootMessage, "play"); // play mode, the default retail mode memset(&masterConfig, 0, sizeof(MasterConfig)); diff --git a/game/kernel/common/kboot.h b/game/kernel/common/kboot.h index 56ee7ddbda..1fbbac2b15 100644 --- a/game/kernel/common/kboot.h +++ b/game/kernel/common/kboot.h @@ -1,11 +1,14 @@ #pragma once #include "common/common_types.h" +#include "common/util/Timer.h" #define GAME_TERRITORY_SCEA 0 // sony america #define GAME_TERRITORY_SCEE 1 // sony europe #define GAME_TERRITORY_SCEI 2 // sony inc. (japan) #define GAME_TERRITORY_SCEK 3 // sony korea +#define SPLASH_SCREEN_TIME 3.f // how long to display the splash screen for + enum class RuntimeExitStatus { RUNNING = 0, RESTART_RUNTIME = 1, @@ -41,6 +44,10 @@ extern char DebugBootMessage[64]; // Added in PC port, option to run listener functions without the kernel for debugging extern u32 MasterUseKernel; +// Added in PC port for splash screen +extern Timer SplashTimer; +extern u32 SplashScreen; + struct MasterConfig { u16 language; //! GOAL language 0 u16 aspect; //! SCE_ASPECT 2 diff --git a/game/kernel/common/kmachine.cpp b/game/kernel/common/kmachine.cpp index 0b4296102f..c6027ddb08 100644 --- a/game/kernel/common/kmachine.cpp +++ b/game/kernel/common/kmachine.cpp @@ -19,6 +19,7 @@ #include "game/kernel/common/kprint.h" #include "game/kernel/common/kscheme.h" #include "game/mips2c/mips2c_table.h" +#include "game/runtime.h" #include "game/sce/libcdvd_ee.h" #include "game/sce/libpad.h" #include "game/sce/libscf.h" @@ -70,9 +71,54 @@ void InitCD() { /*! * Initialize the GS and display the splash screen. - * Not yet implemented. TODO */ -void InitVideo() {} +void InitVideo() { + if (!SplashScreen) { + lg::info("InitVideo: skipping splash!\n"); + return; + } + std::map lang_to_splash_map{ + {SCE_JAPANESE_LANGUAGE, "JAP"}, {SCE_ENGLISH_LANGUAGE, "USA"}, + {SCE_FRENCH_LANGUAGE, "FRE"}, {SCE_SPANISH_LANGUAGE, "SPA"}, + {SCE_GERMAN_LANGUAGE, "GER"}, {SCE_ITALIAN_LANGUAGE, "ITA"}, + {SCE_PORTUGUESE_LANGUAGE, "POR"}, {SCE_KOREAN_LANGUAGE, "KOR"}, + }; + auto lang = ee::sceScfGetLanguage(); + auto filename = "SCREEN1." + lang_to_splash_map.at(lang); + auto path = file_util::get_jak_project_dir() / "out" / game_version_names[g_game_version] / + "iso" / filename; + if (lang != SCE_ENGLISH_LANGUAGE && !fs::exists(path)) { + lg::warn("InitVideo: file {} not found, falling back to english...\n", filename); + path = file_util::get_jak_project_dir() / "out" / game_version_names[g_game_version] / "iso" / + "SCREEN1.USA"; + } + if (!fs::exists(path)) { + lg::warn("InitVideo: splash screen not found!\n"); + return; + } + auto data = file_util::read_binary_file(path); + // width is always 512, height is sometimes different (e.g. demo screens), so we infer from file + // size + constexpr int kWidth = 512; + if (data.size() % (kWidth * 4) != 0) { + lg::error("InitVideo: splash size {} not divisible by stride {}", data.size(), kWidth * 4); + return; + } + int kHeight = data.size() / (kWidth * 4); + if ((int)data.size() != kWidth * kHeight * 4) { + lg::error("InitVideo: unexpected size {}, expected {} for splash screen", data.size(), + kWidth * kHeight * 4); + return; + } + Gfx::g_splash.data = std::move(data); + Gfx::g_splash.width = kWidth; + Gfx::g_splash.height = kHeight; + Gfx::g_splash.ready.store(true); + SplashTimer.start(); + while (SplashTimer.getSeconds() < SPLASH_SCREEN_TIME) { + std::this_thread::sleep_for(std::chrono::milliseconds(50)); + } +} /*! * Flush caches. Does all the memory, regardless of what you specify diff --git a/game/kernel/jak1/kmachine.cpp b/game/kernel/jak1/kmachine.cpp index dfac2eec4b..459a215622 100644 --- a/game/kernel/jak1/kmachine.cpp +++ b/game/kernel/jak1/kmachine.cpp @@ -114,6 +114,12 @@ void InitParms(int argc, const char* const* argv) { masterConfig.disable_sound = true; } + // added in pc port to skip the splash screen + if (arg == "-nosplash") { + Msg(6, "dkernel: skipping splash screen\n"); + SplashScreen = false; + } + // GOAL Settings // ---------------------------- @@ -137,6 +143,8 @@ void InitParms(int argc, const char* const* argv) { Msg(6, "dkernel: debug mode\n"); MasterDebug = 1; DebugSegment = 1; + // disable splash in debug + SplashScreen = 0; } // the "debug-mem" mode is used to set up GOAL in debug mode, but not to load debug-segments diff --git a/game/kernel/jak2/kmachine.cpp b/game/kernel/jak2/kmachine.cpp index 97af545e98..258472f8dd 100644 --- a/game/kernel/jak2/kmachine.cpp +++ b/game/kernel/jak2/kmachine.cpp @@ -138,6 +138,8 @@ void InitParms(int argc, const char* const* argv) { Msg(6, "dkernel: debug mode\n"); MasterDebug = 1; DebugSegment = 1; + // disable splash in debug + SplashScreen = 0; } // the "debug-mem" mode is used to set up GOAL in debug mode, but not to load debug-segments @@ -184,6 +186,12 @@ void InitParms(int argc, const char* const* argv) { Msg(6, "dkernel: no sound mode\n"); masterConfig.disable_sound = true; } + + // added in pc port to skip the splash screen + if (arg == "-nosplash") { + Msg(6, "dkernel: skipping splash screen\n"); + SplashScreen = false; + } } } diff --git a/game/kernel/jak3/kmachine.cpp b/game/kernel/jak3/kmachine.cpp index 63bb767807..dcb4481a89 100644 --- a/game/kernel/jak3/kmachine.cpp +++ b/game/kernel/jak3/kmachine.cpp @@ -128,6 +128,8 @@ void InitParms(int argc, const char* const* argv) { Msg(6, "dkernel: debug mode\n"); MasterDebug = 1; DebugSegment = 1; + // disable splash in debug + SplashScreen = 0; } // the "debug-mem" mode is used to set up GOAL in debug mode, but not to load debug-segments @@ -187,6 +189,12 @@ void InitParms(int argc, const char* const* argv) { Msg(6, "dkernel: no sound mode\n"); masterConfig.disable_sound = true; } + + // added in pc port to skip the splash screen + if (arg == "-nosplash") { + Msg(6, "dkernel: skipping splash screen\n"); + SplashScreen = false; + } } } diff --git a/game/sce/libscf.cpp b/game/sce/libscf.cpp index fa3771050d..2c3bf45f3d 100644 --- a/game/sce/libscf.cpp +++ b/game/sce/libscf.cpp @@ -1,11 +1,15 @@ #include "libscf.h" +#include +#include #include #ifdef _WIN32 // clang-format off #include #include +#elif __linux__ +#include // clang-format on #endif @@ -42,6 +46,40 @@ int sceScfGetLanguage() { } } else if (curLangMain == LANG_DUTCH) { return SCE_DUTCH_LANGUAGE; + } else if (curLangMain == LANG_KOREAN) { + return SCE_KOREAN_LANGUAGE; + } +#elif __linux__ + const char* lang = std::getenv("LANG"); + if (!lang) + return SCE_ENGLISH_LANGUAGE; + + if (!std::strncmp(lang, "ja", 2)) { + return SCE_JAPANESE_LANGUAGE; + } + if (!std::strncmp(lang, "en", 2)) { + return SCE_ENGLISH_LANGUAGE; + } + if (!std::strncmp(lang, "fr", 2)) { + return SCE_FRENCH_LANGUAGE; + } + if (!std::strncmp(lang, "es", 2)) { + return SCE_SPANISH_LANGUAGE; + } + if (!std::strncmp(lang, "de", 2)) { + return SCE_GERMAN_LANGUAGE; + } + if (!std::strncmp(lang, "it", 2)) { + return SCE_ITALIAN_LANGUAGE; + } + if (!std::strncmp(lang, "pt", 2)) { + return SCE_PORTUGUESE_LANGUAGE; + } + if (!std::strncmp(lang, "nl", 2)) { + return SCE_DUTCH_LANGUAGE; + } + if (!std::strncmp(lang, "ko", 2)) { + return SCE_KOREAN_LANGUAGE; } #endif return SCE_ENGLISH_LANGUAGE; diff --git a/game/sce/libscf.h b/game/sce/libscf.h index 8f3ea56d92..25ca1a4d96 100644 --- a/game/sce/libscf.h +++ b/game/sce/libscf.h @@ -10,6 +10,8 @@ #define SCE_ITALIAN_LANGUAGE 5 #define SCE_DUTCH_LANGUAGE 6 #define SCE_PORTUGUESE_LANGUAGE 7 +// added +#define SCE_KOREAN_LANGUAGE 8 #define SCE_ASPECT_43 0 #define SCE_ASPECT_FULL 1 diff --git a/goal_src/jak1/game.gp b/goal_src/jak1/game.gp index 1a8d191da5..f74ab13e24 100644 --- a/goal_src/jak1/game.gp +++ b/goal_src/jak1/game.gp @@ -90,6 +90,7 @@ (define *all-mus* '()) (define *all-sbk* '()) (define *all-vag* '()) +(define *all-screens* '()) (define *all-gc* '()) ;;;;;;;;;;;;;;;;;;;;;;; @@ -255,6 +256,9 @@ (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))) +(defmacro copy-screen-files (&rest files) + `(begin ,@(apply (lambda (x) `(set! *all-screens* (cons (copy-iso-file "SCREEN1" "DRIVERS/" (string-append "." ,x)) *all-screens*))) files))) + (defmacro group (name &rest stuff) `(defstep :in "" :tool 'group @@ -331,11 +335,6 @@ :tool 'copy :out '("$OUT/iso/SAVEGAME.ICO")) -;; the loading screen file -(defstep :in "$ISO/DRIVERS/SCREEN1.USA" - :tool 'copy - :out '("$OUT/iso/SCREEN1.USA")) - ;;;;;;;;;;;;;;;;;;;;; ;; Textures (Common) ;;;;;;;;;;;;;;;;;;;;; @@ -2054,6 +2053,8 @@ (copy-vag-files "ENG" "FRE" "GER" "ITA" "SPA" "JAP") +(copy-screen-files "EUR" "FRE" "GER" "ITA" "SPA" "JAP" "USA") + ;;;;;;;;;;;;;;;;;;;;; ;; ISO Group ;;;;;;;;;;;;;;;;;;;;; @@ -2069,6 +2070,7 @@ ,@(reverse *all-sbk*) ,@(reverse *all-mus*) ,@(reverse *all-vag*) + ,@(reverse *all-screens*) ,@(reverse *all-cgos*)) ) diff --git a/goal_src/jak2/game.gp b/goal_src/jak2/game.gp index ea5d48754c..7af246a2fb 100644 --- a/goal_src/jak2/game.gp +++ b/goal_src/jak2/game.gp @@ -57,6 +57,7 @@ (define *all-mus* '()) (define *all-sbk* '()) (define *all-vag* '()) +(define *all-screens* '()) (define *all-gc* '()) (define *file-entry-map* (make-string-hash-table)) @@ -382,6 +383,12 @@ "DANGER11" "DIG" "FOREST" "FORTRESS" "MOUNTAIN" "PALCAB" "RACE" "RUINS" "SEWER" "STRIP" "TOMB" "TWEAKVAL") +;;;;;;;;;;;;;;;;;;;;; +;; Splash Screens +;;;;;;;;;;;;;;;;;;;;; + +(copy-screen-files "DEE" "DEJ" "DEM" "EUR" "FRE" "GER" "ITA" "JAP" "KOR" "SPA" "USA") + ;;;;;;;;;;;;;;;;;;;;; ;; Text ;;;;;;;;;;;;;;;;;;;;; @@ -425,6 +432,7 @@ ,@(reverse *all-sbk*) ,@(reverse *all-mus*) ,@(reverse *all-vag*) + ,@(reverse *all-screens*) ,@(reverse *all-cgos*)) ) diff --git a/goal_src/jak2/lib/project-lib.gp b/goal_src/jak2/lib/project-lib.gp index 6fcef076c9..cd90d23fd9 100644 --- a/goal_src/jak2/lib/project-lib.gp +++ b/goal_src/jak2/lib/project-lib.gp @@ -182,6 +182,9 @@ (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))) +(defmacro copy-screen-files (&rest files) + `(begin ,@(apply (lambda (x) `(set! *all-screens* (cons (copy-iso-file "SCREEN1" "DRIVERS/" (string-append "." ,x)) *all-screens*))) files))) + (defun reverse-list (list) (let ((new-list '()) (curr-elt list)) diff --git a/goal_src/jak3/game.gp b/goal_src/jak3/game.gp index e2535dd8cc..23ac6c734c 100644 --- a/goal_src/jak3/game.gp +++ b/goal_src/jak3/game.gp @@ -57,6 +57,7 @@ (define *all-mus* '()) (define *all-sbk* '()) (define *all-vag* '()) +(define *all-screens* '()) (define *all-gc* '()) (define *file-entry-map* (make-string-hash-table)) @@ -501,6 +502,13 @@ (defstep :in "$ISO/RES/TWEAKVAL.MUS" :tool 'copy :out '("$OUT/iso/TWEAKVAL.MUS")) + +;;;;;;;;;;;;;;;;;;;;; +;; Splash Screens +;;;;;;;;;;;;;;;;;;;;; + +(copy-screen-files "DEE" "DEJ" "DEM" "EUR" "FRE" "GER" "ITA" "JAP" "KOR" "POR" "SPA" "USA") + ;;;;;;;;;;;;;;;;;;;;; ;; Text ;;;;;;;;;;;;;;;;;;;;; @@ -543,6 +551,7 @@ ,@(reverse *all-str*) ,@(reverse *all-sbk*) ,@(reverse *all-vag*) + ,@(reverse *all-screens*) ,@(reverse *all-cgos*)) ) diff --git a/goal_src/jak3/lib/project-lib.gp b/goal_src/jak3/lib/project-lib.gp index ab53a8d2b0..6776f22bed 100644 --- a/goal_src/jak3/lib/project-lib.gp +++ b/goal_src/jak3/lib/project-lib.gp @@ -159,6 +159,9 @@ (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))) +(defmacro copy-screen-files (&rest files) + `(begin ,@(apply (lambda (x) `(set! *all-screens* (cons (copy-iso-file "SCREEN1" "RES/" (string-append "." ,x)) *all-screens*))) files))) + (defun reverse-list (list) (let ((new-list '()) (curr-elt list))