diff --git a/include/reign.h b/include/reign.h index a454b17..c7cdb86 100644 --- a/include/reign.h +++ b/include/reign.h @@ -18,9 +18,11 @@ #define SYSTEM4_REIGN_H #define RE_MAX_INSTANCES 32 +#define RE_NR_BACK_CGS 16 #include +#include "gfx/gfx.h" #include "plugin.h" enum RE_motion_state { @@ -40,6 +42,17 @@ struct RE_camera { float pitch, roll, yaw; // in degrees }; +struct RE_back_cg { + struct texture texture; + struct string *name; + int no; + float blend_rate; + float x; + float y; + float mag; + bool show; +}; + struct RE_plugin { struct draw_plugin plugin; int sprite; @@ -49,6 +62,8 @@ struct RE_plugin { struct RE_camera camera; mat4 proj_transform; + struct RE_back_cg back_cg[RE_NR_BACK_CGS]; + // Settings. int render_mode; int shadow_mode; @@ -116,6 +131,9 @@ bool RE_motion_set_frame(struct motion *motion, float frame); bool RE_motion_set_frame_range(struct motion *motion, float begin, float end); bool RE_motion_set_loop_frame_range(struct motion *motion, float begin, float end); +bool RE_back_cg_set(struct RE_back_cg *bcg, int no); +bool RE_back_cg_set_name(struct RE_back_cg *bcg, struct string *name, struct archive *aar); + void RE_render(struct sact_sprite *sp); void RE_debug_print(struct sact_sprite *sp, int indent); diff --git a/src/3d/debug.c b/src/3d/debug.c new file mode 100644 index 0000000..5c636c7 --- /dev/null +++ b/src/3d/debug.c @@ -0,0 +1,96 @@ +/* Copyright (C) 2022 kichikuou + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ + +#include "system4/string.h" + +#include "3d_internal.h" +#include "reign.h" +#include "sprite.h" +#include "xsystem4.h" + +static void print_motion(const char *name, struct motion *m, int indent) +{ + const char *state; + switch (m->state) { + case RE_MOTION_STATE_STOP: state = "STOP"; break; + case RE_MOTION_STATE_NOLOOP: state = "NOLOOP"; break; + case RE_MOTION_STATE_LOOP: state = "LOOP"; break; + default: state = "?"; break; + } + indent_printf(indent, "%s = {name=\"%s\", state=%s, frame=%f},\n", + name, m->name, state, m->current_frame); +} + +static void print_instance(struct RE_instance *inst, int index, int indent) +{ + if (!inst || !inst->model) + return; + indent_printf(indent, "instance[%d] = {\n", index); + indent++; + + indent_printf(indent, "path = \"%s\",\n", inst->model->path); + indent_printf(indent, "type = %d,\n", inst->type); + indent_printf(indent, "draw = %d,\n", inst->draw); + indent_printf(indent, "pos = {x=%f, y=%f, z=%f},\n", inst->pos[0], inst->pos[1], inst->pos[2]); + indent_printf(indent, "vec = {x=%f, y=%f, z=%f},\n", inst->vec[0], inst->vec[1], inst->vec[2]); + indent_printf(indent, "scale = {x=%f, y=%f, z=%f},\n", inst->scale[0], inst->scale[1], inst->scale[2]); + if (inst->motion) + print_motion("motion", inst->motion, indent); + if (inst->next_motion) + print_motion("next_motion", inst->next_motion, indent); + indent_printf(indent, "fps = %f,\n", inst->fps); + if (inst->motion_blend) + indent_printf(indent, "motion_blend_rate = %f,\n", inst->motion_blend_rate); + + indent--; + indent_printf(indent, "},\n"); +} + +static void print_back_cg(struct RE_back_cg *bcg, int index, int indent) +{ + if (!bcg->name && !bcg->no) + return; + indent_printf(indent, "backCG[%d] = {\n", index); + indent++; + + if (bcg->no) + indent_printf(indent, "no = %d,\n", bcg->no); + if (bcg->name) + indent_printf(indent, "name = \"%s\",\n", bcg->name ? bcg->name->text : ""); + indent_printf(indent, "pos = {x=%f, y=%f},\n", bcg->x, bcg->y); + indent_printf(indent, "blend_rate = %f,\n", bcg->blend_rate); + indent_printf(indent, "mag = %f,\n", bcg->mag); + indent_printf(indent, "show = %d,\n", bcg->show); + + indent--; + indent_printf(indent, "},\n"); +} + +void RE_debug_print(struct sact_sprite *sp, int indent) +{ + struct RE_plugin *p = (struct RE_plugin *)sp->plugin; + + indent_printf(indent, "name = \"%s\",\n", p->plugin.name); + indent_printf(indent, "camera = {x=%f, y=%f, z=%f, pitch=%f, roll=%f, yaw=%f},\n", + p->camera.pos[0], p->camera.pos[1], p->camera.pos[2], + p->camera.pitch, p->camera.roll, p->camera.yaw); + + for (int i = 0; i < RE_MAX_INSTANCES; i++) + print_instance(p->instances[i], i, indent); + + for (int i = 0; i < RE_NR_BACK_CGS; i++) + print_back_cg(&p->back_cg[i], i, indent); +} diff --git a/src/3d/reign.c b/src/3d/reign.c index a9314ad..8e50930 100644 --- a/src/3d/reign.c +++ b/src/3d/reign.c @@ -22,8 +22,11 @@ #include "system4.h" #include "system4/aar.h" +#include "system4/cg.h" +#include "system4/string.h" #include "3d_internal.h" +#include "asset_manager.h" #include "reign.h" #include "sact.h" #include "xsystem4.h" @@ -67,6 +70,19 @@ static void free_instance(struct RE_instance *instance) free(instance); } +static void RE_back_cg_init(struct RE_back_cg *bcg) +{ + bcg->blend_rate = 1.0; + bcg->mag = 1.0; +} + +static void RE_back_cg_destroy(struct RE_back_cg *bcg) +{ + gfx_delete_texture(&bcg->texture); + if (bcg->name) + free_string(bcg->name); +} + struct RE_plugin *RE_plugin_new(void) { char *aar_path = gamedir_path("Data/ReignData.red"); @@ -86,6 +102,8 @@ struct RE_plugin *RE_plugin_new(void) plugin->plugin.update = RE_render; plugin->plugin.debug_print = RE_debug_print; plugin->aar = aar; + for (int i = 0; i < RE_NR_BACK_CGS; i++) + RE_back_cg_init(&plugin->back_cg[i]); return plugin; } @@ -98,6 +116,8 @@ void RE_plugin_free(struct RE_plugin *plugin) archive_free(plugin->aar); if (plugin->renderer) RE_renderer_free(plugin->renderer); + for (int i = 0; i < RE_NR_BACK_CGS; i++) + RE_back_cg_destroy(&plugin->back_cg[i]); free(plugin); } @@ -240,50 +260,52 @@ bool RE_motion_set_loop_frame_range(struct motion *motion, float begin, float en return true; } -static void print_motion(const char *name, struct motion *m, int indent) +bool RE_back_cg_set(struct RE_back_cg *bcg, int no) { - const char *state; - switch (m->state) { - case RE_MOTION_STATE_STOP: state = "STOP"; break; - case RE_MOTION_STATE_NOLOOP: state = "NOLOOP"; break; - case RE_MOTION_STATE_LOOP: state = "LOOP"; break; - default: state = "?"; break; + if (!bcg) + return false; + if (bcg->name) { + free_string(bcg->name); + bcg->name = NULL; } - indent_printf(indent, "%s = {name=\"%s\", state=%s, frame=%f},\n", - name, m->name, state, m->current_frame); + bcg->no = no; + gfx_delete_texture(&bcg->texture); + + struct cg *cg = asset_cg_load(no); + if (!cg) { + WARNING("cannot load back CG: %d", no); + return false; + } + gfx_init_texture_with_cg(&bcg->texture, cg); + cg_free(cg); + return true; } -void RE_debug_print(struct sact_sprite *sp, int indent) +bool RE_back_cg_set_name(struct RE_back_cg *bcg, struct string *name, struct archive *aar) { - struct RE_plugin *p = (struct RE_plugin *)sp->plugin; + if (!bcg) + return false; + if (bcg->name) + free_string(bcg->name); + bcg->name = string_ref(name); + bcg->no = 0; + gfx_delete_texture(&bcg->texture); - indent_printf(indent, "name = \"%s\",\n", p->plugin.name); - indent_printf(indent, "camera = {x=%f, y=%f, z=%f, pitch=%f, roll=%f, yaw=%f},\n", - p->camera.pos[0], p->camera.pos[1], p->camera.pos[2], - p->camera.pitch, p->camera.roll, p->camera.yaw); - - for (int i = 0; i < RE_MAX_INSTANCES; i++) { - struct RE_instance *inst = p->instances[i]; - if (!inst || !inst->model) - continue; - indent_printf(indent, "instance[%d] = {\n", i); - indent++; - - indent_printf(indent, "path = \"%s\",\n", inst->model->path); - indent_printf(indent, "type = %d,\n", inst->type); - indent_printf(indent, "draw = %d,\n", inst->draw); - indent_printf(indent, "pos = {x=%f, y=%f, z=%f},\n", inst->pos[0], inst->pos[1], inst->pos[2]); - indent_printf(indent, "vec = {x=%f, y=%f, z=%f},\n", inst->vec[0], inst->vec[1], inst->vec[2]); - indent_printf(indent, "scale = {x=%f, y=%f, z=%f},\n", inst->scale[0], inst->scale[1], inst->scale[2]); - if (inst->motion) - print_motion("motion", inst->motion, indent); - if (inst->next_motion) - print_motion("next_motion", inst->next_motion, indent); - indent_printf(indent, "fps = %f,\n", inst->fps); - if (inst->motion_blend) - indent_printf(indent, "motion_blend_rate = %f,\n", inst->motion_blend_rate); - - indent--; - indent_printf(indent, "},\n"); + char *cg_path = xmalloc(name->size + 5); + sprintf(cg_path, "%s.bmp", name->text); + struct archive_data *dfile = archive_get_by_name(aar, cg_path); + free(cg_path); + if (!dfile) { + WARNING("cannot load back CG %s", name->text); + return false; } + struct cg *cg = cg_load_data(dfile); + archive_free_data(dfile); + if (!cg) { + WARNING("cg_load_data failed: %s", name->text); + return false; + } + gfx_init_texture_with_cg(&bcg->texture, cg); + cg_free(cg); + return true; } diff --git a/src/3d/renderer.c b/src/3d/renderer.c index 06468cf..98eb327 100644 --- a/src/3d/renderer.c +++ b/src/3d/renderer.c @@ -190,6 +190,15 @@ static void render_instance(struct RE_instance *inst, struct RE_renderer *r, mat glUseProgram(0); } +static void render_back_cg(struct texture *dst, struct RE_back_cg *bcg, struct RE_renderer *r) +{ + if (!bcg->texture.handle) + return; + int sw = bcg->texture.w; + int sh = bcg->texture.h; + gfx_copy_stretch_blend(dst, bcg->x, bcg->y, sw * bcg->mag, sh * bcg->mag, &bcg->texture, 0, 0, sw, sh, bcg->blend_rate * 255); +} + void RE_render(struct sact_sprite *sp) { uint32_t timestamp = SDL_GetTicks(); @@ -211,6 +220,13 @@ void RE_render(struct sact_sprite *sp) ERROR("Incomplete framebuffer"); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + // Draw background CGs. + glDisable(GL_DEPTH_TEST); + for (int i = 0; i < RE_NR_BACK_CGS; i++) + render_back_cg(texture, &plugin->back_cg[i], r); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo); + glEnable(GL_DEPTH_TEST); glEnable(GL_CULL_FACE); diff --git a/src/hll/ReignEngine.c b/src/hll/ReignEngine.c index c1fb376..dbd1225 100644 --- a/src/hll/ReignEngine.c +++ b/src/hll/ReignEngine.c @@ -54,6 +54,14 @@ static struct motion *get_next_motion(unsigned plugin, unsigned instance) return inst ? inst->next_motion : NULL; } +static struct RE_back_cg *get_back_cg(unsigned plugin, unsigned num) +{ + struct RE_plugin *p = get_plugin(plugin); + if (!p || num >= RE_NR_BACK_CGS) + return NULL; + return &p->back_cg[num]; +} + static int ReignEngine_CreatePlugin(void) { for (int i = 0; i < RE_MAX_PLUGINS; i++) { @@ -965,21 +973,107 @@ static bool ReignEngine_SetPostEffectFilterCr(int plugin, float cr) return true; } -//bool ReignEngine_GetBackCGName(int plugin, int num, struct string **pICGName); -//int ReignEngine_GetBackCGNum(int plugin, int num); -//float ReignEngine_GetBackCGBlendRate(int plugin, int num); -//float ReignEngine_GetBackCGDestPosX(int plugin, int num); -//float ReignEngine_GetBackCGDestPosY(int plugin, int num); -//float ReignEngine_GetBackCGMag(int plugin, int num); +static bool ReignEngine_GetBackCGName(int plugin, int num, struct string **cg_name) +{ + struct RE_back_cg* bcg = get_back_cg(plugin, num); + if (!bcg) + return false; + if (*cg_name) + free_string(*cg_name); + *cg_name = string_ref(bcg->name ? bcg->name : &EMPTY_STRING); + return true; +} + +static int ReignEngine_GetBackCGNum(int plugin, int num) +{ + struct RE_back_cg* bcg = get_back_cg(plugin, num); + return bcg ? bcg->no : 0; +} + +static float ReignEngine_GetBackCGBlendRate(int plugin, int num) +{ + struct RE_back_cg* bcg = get_back_cg(plugin, num); + return bcg ? bcg->blend_rate : 0.0; +} + +static float ReignEngine_GetBackCGDestPosX(int plugin, int num) +{ + struct RE_back_cg* bcg = get_back_cg(plugin, num); + return bcg ? bcg->x : 0.0; +} + +static float ReignEngine_GetBackCGDestPosY(int plugin, int num) +{ + struct RE_back_cg* bcg = get_back_cg(plugin, num); + return bcg ? bcg->y : 0.0; +} + +static float ReignEngine_GetBackCGMag(int plugin, int num) +{ + struct RE_back_cg* bcg = get_back_cg(plugin, num); + return bcg ? bcg->mag : 0.0; +} + //float ReignEngine_GetBackCGQuakeMag(int plugin, int num); -//bool ReignEngine_GetBackCGShow(int plugin, int num); -HLL_WARN_UNIMPLEMENTED(true, bool, ReignEngine, SetBackCGName, int plugin, int num, struct string *pICGName /* e.g. "Data\Texture\cg29501" */); -//bool ReignEngine_SetBackCGNum(int plugin, int num, int nCGNum); -HLL_WARN_UNIMPLEMENTED(false, bool, ReignEngine, SetBackCGBlendRate, int plugin, int num, float blend_rate); -HLL_WARN_UNIMPLEMENTED(true, bool, ReignEngine, SetBackCGDestPos, int plugin, int num, float fX, float fY); -//bool ReignEngine_SetBackCGMag(int plugin, int num, float fMag); + +static bool ReignEngine_GetBackCGShow(int plugin, int num) +{ + struct RE_back_cg* bcg = get_back_cg(plugin, num); + return bcg ? bcg->show : false; +} + +static bool ReignEngine_SetBackCGName(int plugin, int num, struct string *cg_name) +{ + struct RE_plugin *p = get_plugin(plugin); + if (!p) + return false; + return RE_back_cg_set_name(get_back_cg(plugin, num), cg_name, p->aar); +} + +static bool ReignEngine_SetBackCGNum(int plugin, int num, int cg_num) +{ + return RE_back_cg_set(get_back_cg(plugin, num), cg_num); +} + +static bool ReignEngine_SetBackCGBlendRate(int plugin, int num, float blend_rate) +{ + struct RE_back_cg* bcg = get_back_cg(plugin, num); + if (!bcg) + return false; + bcg->blend_rate = blend_rate; + return true; +} + +static bool ReignEngine_SetBackCGDestPos(int plugin, int num, float x, float y) +{ + struct RE_back_cg* bcg = get_back_cg(plugin, num); + if (!bcg) + return false; + bcg->x = x; + bcg->y = y; + return true; +} + +static bool ReignEngine_SetBackCGMag(int plugin, int num, float mag) +{ + struct RE_back_cg* bcg = get_back_cg(plugin, num); + if (!bcg) + return false; + bcg->mag = mag; + return true; +} + //bool ReignEngine_SetBackCGQuakeMag(int plugin, int num, float fQuakeMag); -HLL_WARN_UNIMPLEMENTED(true, bool, ReignEngine, SetBackCGShow, int plugin, int num, bool bShow); + +static bool ReignEngine_SetBackCGShow(int plugin, int num, bool show) +{ + struct RE_back_cg* bcg = get_back_cg(plugin, num); + if (!bcg) + return false; + bcg->show = show; + return true; +} + //float ReignEngine_GetGlareBrightnessParam(int plugin, int index); HLL_WARN_UNIMPLEMENTED(false, bool, ReignEngine, SetGlareBrightnessParam, int plugin, int index, float param); //float ReignEngine_GetSSAOParam(int plugin, int type); @@ -1313,19 +1407,19 @@ HLL_LIBRARY(ReignEngine, HLL_EXPORT(SetPostEffectFilterY, ReignEngine_SetPostEffectFilterY), HLL_EXPORT(SetPostEffectFilterCb, ReignEngine_SetPostEffectFilterCb), HLL_EXPORT(SetPostEffectFilterCr, ReignEngine_SetPostEffectFilterCr), - HLL_TODO_EXPORT(GetBackCGName, ReignEngine_GetBackCGName), - HLL_TODO_EXPORT(GetBackCGNum, ReignEngine_GetBackCGNum), - HLL_TODO_EXPORT(GetBackCGBlendRate, ReignEngine_GetBackCGBlendRate), - HLL_TODO_EXPORT(GetBackCGDestPosX, ReignEngine_GetBackCGDestPosX), - HLL_TODO_EXPORT(GetBackCGDestPosY, ReignEngine_GetBackCGDestPosY), - HLL_TODO_EXPORT(GetBackCGMag, ReignEngine_GetBackCGMag), + HLL_EXPORT(GetBackCGName, ReignEngine_GetBackCGName), + HLL_EXPORT(GetBackCGNum, ReignEngine_GetBackCGNum), + HLL_EXPORT(GetBackCGBlendRate, ReignEngine_GetBackCGBlendRate), + HLL_EXPORT(GetBackCGDestPosX, ReignEngine_GetBackCGDestPosX), + HLL_EXPORT(GetBackCGDestPosY, ReignEngine_GetBackCGDestPosY), + HLL_EXPORT(GetBackCGMag, ReignEngine_GetBackCGMag), HLL_TODO_EXPORT(GetBackCGQuakeMag, ReignEngine_GetBackCGQuakeMag), - HLL_TODO_EXPORT(GetBackCGShow, ReignEngine_GetBackCGShow), + HLL_EXPORT(GetBackCGShow, ReignEngine_GetBackCGShow), HLL_EXPORT(SetBackCGName, ReignEngine_SetBackCGName), - HLL_TODO_EXPORT(SetBackCGNum, ReignEngine_SetBackCGNum), + HLL_EXPORT(SetBackCGNum, ReignEngine_SetBackCGNum), HLL_EXPORT(SetBackCGBlendRate, ReignEngine_SetBackCGBlendRate), HLL_EXPORT(SetBackCGDestPos, ReignEngine_SetBackCGDestPos), - HLL_TODO_EXPORT(SetBackCGMag, ReignEngine_SetBackCGMag), + HLL_EXPORT(SetBackCGMag, ReignEngine_SetBackCGMag), HLL_TODO_EXPORT(SetBackCGQuakeMag, ReignEngine_SetBackCGQuakeMag), HLL_EXPORT(SetBackCGShow, ReignEngine_SetBackCGShow), HLL_TODO_EXPORT(GetGlareBrightnessParam, ReignEngine_GetGlareBrightnessParam), diff --git a/src/meson.build b/src/meson.build index 6f63698..fd4aecd 100644 --- a/src/meson.build +++ b/src/meson.build @@ -31,6 +31,7 @@ xsystem4 = [version_h, 'video.c', 'vm.c', + '3d/debug.c', '3d/model.c', '3d/parser.c', '3d/reign.c',