mirror of
https://github.com/nunuhara/xsystem4.git
synced 2026-10-08 14:58:14 +03:00
Refactor sact_graphics.c
Split the code from sact_graphics.c into sprite.c and hll/SACT2.c. sprite.c contains an index-independent sprite/scene interface, whereas hll/SACT2.c handles the indexing of sprites. This is to better support the StoatSpriteEngine.MultiSprite_* functions, which use a different indexing system.
This commit is contained in:
+4
-45
@@ -18,54 +18,13 @@
|
||||
#define SYSTEM4_SACT_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <SDL.h>
|
||||
#include <GL/glew.h>
|
||||
#include "queue.h"
|
||||
#include "gfx/gfx.h"
|
||||
#include "gfx/types.h"
|
||||
|
||||
struct string;
|
||||
struct page;
|
||||
union vm_value;
|
||||
|
||||
struct sact_sprite {
|
||||
TAILQ_ENTRY(sact_sprite) entry;
|
||||
struct texture texture;
|
||||
SDL_Color color;
|
||||
Rectangle rect;
|
||||
struct {
|
||||
struct string *str;
|
||||
struct texture texture;
|
||||
Point home;
|
||||
Point pos;
|
||||
int char_space;
|
||||
int line_space;
|
||||
} text;
|
||||
int z;
|
||||
bool show;
|
||||
int no;
|
||||
int cg_no;
|
||||
};
|
||||
|
||||
extern bool sact_dirty;
|
||||
|
||||
static inline void sprite_dirty(struct sact_sprite *sp)
|
||||
{
|
||||
if (sp && sp->show)
|
||||
sact_dirty = true;
|
||||
}
|
||||
#include "sprite.h"
|
||||
|
||||
struct sact_sprite *sact_get_sprite(int sp);
|
||||
struct sact_sprite *sact_get_sprite_dirty(int sp);
|
||||
struct texture *sact_get_texture(int sp_no);
|
||||
struct texture *sact_get_texture_dirty(int sp_no);
|
||||
|
||||
void sact_render_scene(void);
|
||||
|
||||
void sact_ModuleFini(void);
|
||||
int sact_Init(void *_, int cg_cache_size);
|
||||
int sact_SetWP(int cg_no);
|
||||
int sact_SetWP_Color(int r, int g, int b);
|
||||
#define sact_SetWP sprite_set_wp
|
||||
#define sact_SetWP_Color sprite_set_wp_color
|
||||
int sact_GetScreenWidth(void);
|
||||
int sact_GetScreenHeight(void);
|
||||
int sact_GetMainSurfaceNumber(void);
|
||||
@@ -74,7 +33,7 @@ int sact_Effect(int type, int time, int key);
|
||||
int sact_SP_GetUnuseNum(int min);
|
||||
int sact_SP_Count(void);
|
||||
int sact_SP_Enum(struct page **array);
|
||||
int sact_SP_GetMaxZ(void);
|
||||
#define sact_SP_GetMaxZ sprite_get_max_z
|
||||
int sact_SP_SetCG(int sp, int cg);
|
||||
int sact_SP_Create(int sp, int width, int height, int r, int g, int b, int a);
|
||||
int sact_SP_CreatePixelOnly(int sp, int width, int height);
|
||||
|
||||
@@ -0,0 +1,109 @@
|
||||
/* Copyright (C) 2019 Nunuhara Cabbage <nunuhara@haniwa.technology>
|
||||
*
|
||||
* 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 <http://gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef SYSTEM4_SPRITE_H
|
||||
#define SYSTEM4_SPRITE_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <SDL.h>
|
||||
#include "queue.h"
|
||||
#include "gfx/gfx.h"
|
||||
|
||||
struct string;
|
||||
struct page;
|
||||
union vm_value;
|
||||
|
||||
struct sact_sprite {
|
||||
TAILQ_ENTRY(sact_sprite) entry;
|
||||
struct texture texture;
|
||||
SDL_Color color;
|
||||
Rectangle rect;
|
||||
struct {
|
||||
struct string *str;
|
||||
struct texture texture;
|
||||
Point home;
|
||||
Point pos;
|
||||
int char_space;
|
||||
int line_space;
|
||||
} text;
|
||||
int z;
|
||||
bool show;
|
||||
int no;
|
||||
int cg_no;
|
||||
};
|
||||
|
||||
extern bool sact_dirty;
|
||||
|
||||
static inline void sprite_dirty(struct sact_sprite *sp)
|
||||
{
|
||||
if (sp && sp->show)
|
||||
sact_dirty = true;
|
||||
}
|
||||
|
||||
static inline void scene_dirty(void)
|
||||
{
|
||||
sact_dirty = true;
|
||||
}
|
||||
|
||||
|
||||
void sprite_register(struct sact_sprite *sp);
|
||||
void sprite_unregister(struct sact_sprite *sp);
|
||||
void sprite_free(struct sact_sprite *sp);
|
||||
void sprite_render_scene(void);
|
||||
void sprite_flip(void);
|
||||
struct texture *sprite_get_texture(struct sact_sprite *sp);
|
||||
int sprite_set_wp(int cg_no);
|
||||
int sprite_set_wp_color(int r, int g, int b);
|
||||
int sprite_set_cg(struct sact_sprite *sp, int cg_no);
|
||||
void sprite_init(struct sact_sprite *sp, int w, int h, int r, int g, int b, int a);
|
||||
int sprite_get_max_z(void);
|
||||
void sprite_set_pos(struct sact_sprite *sp, int x, int y);
|
||||
void sprite_set_x(struct sact_sprite *sp, int x);
|
||||
void sprite_set_y(struct sact_sprite *sp, int y);
|
||||
void sprite_set_z(struct sact_sprite *sp, int z);
|
||||
int sprite_get_blend_rate(struct sact_sprite *sp);
|
||||
void sprite_set_blend_rate(struct sact_sprite *sp, int rate);
|
||||
void sprite_set_show(struct sact_sprite *sp, bool show);
|
||||
int sprite_set_draw_method(struct sact_sprite *sp, int method);
|
||||
int sprite_get_draw_method(struct sact_sprite *sp);
|
||||
int sprite_exists_alpha(struct sact_sprite *sp);
|
||||
static inline int sprite_get_pos_x(struct sact_sprite *sp) { return sp->rect.x; }
|
||||
static inline int sprite_get_pos_y(struct sact_sprite *sp) { return sp->rect.y; }
|
||||
static inline int sprite_get_width(struct sact_sprite *sp) { return sp->rect.w; }
|
||||
static inline int sprite_get_height(struct sact_sprite *sp) { return sp->rect.h; }
|
||||
static inline int sprite_get_z(struct sact_sprite *sp) { return sp->z; }
|
||||
static inline int sprite_get_show(struct sact_sprite *sp) { return sp->show; }
|
||||
void sprite_set_text_home(struct sact_sprite *sp, int x, int y);
|
||||
void sprite_set_text_line_space(struct sact_sprite *sp, int px);
|
||||
void sprite_set_text_char_space(struct sact_sprite *sp, int px);
|
||||
void sprite_set_text_pos(struct sact_sprite *sp, int x, int y);
|
||||
void sprite_text_draw(struct sact_sprite *sp, struct string *text, struct text_metrics *tm);
|
||||
void sprite_text_clear(struct sact_sprite *sp);
|
||||
void sprite_text_home(struct sact_sprite *sp, int size);
|
||||
void sprite_text_new_line(struct sact_sprite *sp, int size);
|
||||
void sprite_text_copy(struct sact_sprite *dsp, struct sact_sprite *ssp);
|
||||
static inline int sprite_get_text_home_x(struct sact_sprite *sp) { return sp->text.home.x; }
|
||||
static inline int sprite_get_text_home_y(struct sact_sprite *sp) { return sp->text.home.y; }
|
||||
static inline int sprite_get_text_char_space(struct sact_sprite *sp) { return sp->text.char_space; }
|
||||
static inline int sprite_get_text_pos_x(struct sact_sprite *sp) { return sp->text.pos.x; }
|
||||
static inline int sprite_get_text_pos_y(struct sact_sprite *sp) { return sp->text.pos.y; }
|
||||
static inline int sprite_get_text_line_space(struct sact_sprite *sp) { return sp->text.line_space; }
|
||||
bool sprite_is_point_in(struct sact_sprite *sp, int x, int y);
|
||||
bool sprite_is_point_in_rect(struct sact_sprite *sp, int x, int y);
|
||||
int sprite_get_amap_value(struct sact_sprite *sp, int x, int y);
|
||||
void sprite_get_pixel_value(struct sact_sprite *sp, int x, int y, int *r, int *g, int *b);
|
||||
|
||||
#endif /* SYSTEM4_SPRITE_H */
|
||||
+1
-1
@@ -105,7 +105,7 @@ int sact_Effect(int type, possibly_unused int time, possibly_unused int key)
|
||||
// get old & new scene textures
|
||||
Texture old, new;
|
||||
gfx_copy_main_surface(&old);
|
||||
sact_render_scene();
|
||||
sprite_render_scene();
|
||||
gfx_copy_main_surface(&new);
|
||||
|
||||
effect_callback effect = effects[type];
|
||||
|
||||
+16
-2
@@ -19,8 +19,22 @@
|
||||
#include "gfx/types.h"
|
||||
#include "system4/string.h"
|
||||
|
||||
#define STEX(sp_no) sact_get_texture(sp_no)
|
||||
#define DTEX(sp_no) sact_get_texture_dirty(sp_no)
|
||||
// Get texture for source sprite
|
||||
static struct texture *STEX(int sp_no)
|
||||
{
|
||||
struct sact_sprite *sp = sact_get_sprite(sp_no);
|
||||
if (!sp) return NULL;
|
||||
return sprite_get_texture(sp);
|
||||
}
|
||||
|
||||
// Get texture for destination sprite
|
||||
static struct texture *DTEX(int sp_no)
|
||||
{
|
||||
struct sact_sprite *sp = sact_get_sprite(sp_no);
|
||||
if (!sp) return NULL;
|
||||
sprite_dirty(sp);
|
||||
return sprite_get_texture(sp);
|
||||
}
|
||||
|
||||
static void DrawGraph_Copy(int dst, int dx, int dy, int src, int sx, int sy, int w, int h)
|
||||
{
|
||||
|
||||
+578
-51
@@ -29,13 +29,537 @@
|
||||
#include "queue.h"
|
||||
#include "gfx/gfx.h"
|
||||
#include "sact.h"
|
||||
#include "vm/page.h"
|
||||
#include "xsystem4.h"
|
||||
|
||||
static struct sact_sprite *sact_create_sprite(int sp_no, int width, int height, int r, int g, int b, int a);
|
||||
|
||||
static struct sact_sprite **sprites = NULL;
|
||||
static int nr_sprites = 0;
|
||||
|
||||
// NOTE: Used externally by DrawGraph and SengokuRanceFont
|
||||
struct sact_sprite *sact_get_sprite(int sp)
|
||||
{
|
||||
if (sp < -1 || sp >= nr_sprites)
|
||||
return NULL;
|
||||
return sprites[sp];
|
||||
}
|
||||
|
||||
static struct sact_sprite *sact_alloc_sprite(int sp)
|
||||
{
|
||||
sprites[sp] = xcalloc(1, sizeof(struct sact_sprite));
|
||||
sprites[sp]->no = sp;
|
||||
sprite_dirty(sprites[sp]);
|
||||
return sprites[sp];
|
||||
}
|
||||
|
||||
static void sact_free_sprite(struct sact_sprite *sp)
|
||||
{
|
||||
if (sprites[sp->no] == NULL)
|
||||
VM_ERROR("Double free of sact_sprite");
|
||||
sprites[sp->no] = NULL;
|
||||
sprite_free(sp);
|
||||
}
|
||||
|
||||
static void realloc_sprite_table(int n)
|
||||
{
|
||||
int old_nr_sprites = nr_sprites;
|
||||
nr_sprites = n;
|
||||
|
||||
struct sact_sprite **tmp = xrealloc(sprites-1, sizeof(struct sact_sprite*) * (nr_sprites+1));
|
||||
sprites = tmp + 1;
|
||||
|
||||
memset(sprites + old_nr_sprites, 0, sizeof(struct sact_sprite*) * (nr_sprites - old_nr_sprites));
|
||||
}
|
||||
|
||||
int sact_Init(possibly_unused void *_, possibly_unused int cg_cache_size)
|
||||
{
|
||||
// already initialized
|
||||
if (sprites)
|
||||
return 1;
|
||||
|
||||
gfx_init();
|
||||
gfx_font_init();
|
||||
audio_init();
|
||||
|
||||
nr_sprites = 256;
|
||||
sprites = xmalloc(sizeof(struct sact_sprite*) * 257);
|
||||
memset(sprites, 0, sizeof(struct sact_sprite*) * 257);
|
||||
|
||||
// create sprite for main_surface
|
||||
Texture *t = gfx_main_surface();
|
||||
struct sact_sprite *sp = sact_create_sprite(0, t->w, t->h, 0, 0, 0, 255);
|
||||
sp->texture = *t; // XXX: textures normally shouldn't be copied like this...
|
||||
|
||||
sprites++;
|
||||
return 1;
|
||||
}
|
||||
|
||||
void sact_ModuleFini(void)
|
||||
{
|
||||
for (int i = 0; i < nr_sprites; i++) {
|
||||
if (sprites[i]) {
|
||||
sact_free_sprite(sprites[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//int SACT2_Error(struct string *err);
|
||||
//int SACT2_WP_GetSP(int sp);
|
||||
//int SACT2_WP_SetSP(int sp);
|
||||
|
||||
int sact_GetScreenWidth(void)
|
||||
{
|
||||
return config.view_width;
|
||||
}
|
||||
|
||||
int sact_GetScreenHeight(void)
|
||||
{
|
||||
return config.view_height;
|
||||
}
|
||||
|
||||
int sact_GetMainSurfaceNumber(void)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
int sact_Update(void)
|
||||
{
|
||||
handle_events();
|
||||
if (sact_dirty) {
|
||||
sprite_render_scene();
|
||||
sprite_flip();
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
HLL_WARN_UNIMPLEMENTED(1, int, SACT2, EffectSetMask, int cg);
|
||||
//int SACT2_EffectSetMaskSP(int sp);
|
||||
HLL_WARN_UNIMPLEMENTED( , void, SACT2, QuakeScreen, int amp_x, int amp_y, int time, int key);
|
||||
//void SACT2_QUAKE_SET_CROSS(int amp_x, int amp_y);
|
||||
//void SACT2_QUAKE_SET_ROTATION(int amp, int cycle);
|
||||
|
||||
int sact_SP_GetUnuseNum(int min)
|
||||
{
|
||||
for (int i = min; i < nr_sprites; i++) {
|
||||
if (!sprites[i])
|
||||
return i;
|
||||
}
|
||||
|
||||
int n = max(min, nr_sprites);
|
||||
realloc_sprite_table(n + 256);
|
||||
return n;
|
||||
}
|
||||
|
||||
int sact_SP_Count(void)
|
||||
{
|
||||
int count = 0;
|
||||
for (int i = 0; i < nr_sprites; i++) {
|
||||
if (sprites[i])
|
||||
count++;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
int sact_SP_Enum(struct page **array)
|
||||
{
|
||||
int count = 0;
|
||||
int size = (*array)->nr_vars;
|
||||
for (int i = 0; i < nr_sprites && count < size; i++) {
|
||||
if (sprites[i]) {
|
||||
(*array)->values[count++].i = i;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
int sact_SP_SetCG(int sp_no, int cg_no)
|
||||
{
|
||||
struct sact_sprite *sp = sact_get_sprite(sp_no);
|
||||
if (!sp)
|
||||
sact_SP_Create(sp_no, 1, 1, 0, 0, 0, 255);
|
||||
if (!(sp = sact_get_sprite(sp_no))) {
|
||||
WARNING("Failed to create sprite");
|
||||
return 0;
|
||||
}
|
||||
return sprite_set_cg(sp, cg_no);
|
||||
}
|
||||
|
||||
//int SACT2_SP_SetCGFromFile(int sp, struct string *filename);
|
||||
//int SACT2_SP_SaveCG(int sp, struct string *filename);
|
||||
|
||||
static struct sact_sprite *sact_create_sprite(int sp_no, int width, int height, int r, int g, int b, int a)
|
||||
{
|
||||
struct sact_sprite *sp;
|
||||
if (sp_no < 0)
|
||||
VM_ERROR("Invalid sprite number: %d", sp_no);
|
||||
if (sp_no >= nr_sprites) {
|
||||
realloc_sprite_table(sp_no+256);
|
||||
}
|
||||
if (!(sp = sact_get_sprite(sp_no)))
|
||||
sp = sact_alloc_sprite(sp_no);
|
||||
|
||||
sprite_init(sp, width, height, r, g, b, a);
|
||||
return sp;
|
||||
}
|
||||
|
||||
int sact_SP_Create(int sp_no, int width, int height, int r, int g, int b, int a)
|
||||
{
|
||||
sact_create_sprite(sp_no, width, height, r, g, b, a);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int sact_SP_CreatePixelOnly(int sp_no, int width, int height)
|
||||
{
|
||||
sact_create_sprite(sp_no, width, height, 0, 0, 0, -1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
//int SACT2_SP_CreateCustom(int sp);
|
||||
|
||||
int sact_SP_Delete(int sp_no)
|
||||
{
|
||||
struct sact_sprite *sp = sact_get_sprite(sp_no);
|
||||
if (!sp) return 0;
|
||||
sact_free_sprite(sp);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int sact_SP_SetPos(int sp_no, int x, int y)
|
||||
{
|
||||
struct sact_sprite *sp = sact_get_sprite(sp_no);
|
||||
if (!sp) return 1;
|
||||
sprite_set_pos(sp, x, y);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int sact_SP_SetX(int sp_no, int x)
|
||||
{
|
||||
struct sact_sprite *sp = sact_get_sprite(sp_no);
|
||||
if (!sp) return 0;
|
||||
sprite_set_x(sp, x);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int sact_SP_SetY(int sp_no, int y)
|
||||
{
|
||||
struct sact_sprite *sp = sact_get_sprite(sp_no);
|
||||
if (!sp) return 0;
|
||||
sprite_set_y(sp, y);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int sact_SP_SetZ(int sp_no, int z)
|
||||
{
|
||||
struct sact_sprite *sp = sact_get_sprite(sp_no);
|
||||
if (!sp) return 0;
|
||||
sprite_set_z(sp, z);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int sact_SP_GetBlendRate(int sp_no)
|
||||
{
|
||||
struct sact_sprite *sp = sact_get_sprite(sp_no);
|
||||
if (!sp) return 0;
|
||||
return sprite_get_blend_rate(sp);
|
||||
}
|
||||
|
||||
int sact_SP_SetBlendRate(int sp_no, int rate)
|
||||
{
|
||||
struct sact_sprite *sp = sact_get_sprite(sp_no);
|
||||
if (!sp) return 0;
|
||||
sprite_set_blend_rate(sp, rate);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int sact_SP_SetShow(int sp_no, bool show)
|
||||
{
|
||||
struct sact_sprite *sp = sact_get_sprite(sp_no);
|
||||
if (!sp) return 0;
|
||||
sprite_set_show(sp, show);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int sact_SP_SetDrawMethod(int sp_no, int method)
|
||||
{
|
||||
struct sact_sprite *sp = sact_get_sprite(sp_no);
|
||||
if (!sp) return 0;
|
||||
return sprite_set_draw_method(sp, method);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int sact_SP_GetDrawMethod(int sp_no)
|
||||
{
|
||||
struct sact_sprite *sp = sact_get_sprite(sp_no);
|
||||
if (!sp) return DRAW_METHOD_NORMAL;
|
||||
return sprite_get_draw_method(sp);
|
||||
}
|
||||
|
||||
int sact_SP_IsUsing(int sp_no)
|
||||
{
|
||||
return sact_get_sprite(sp_no) != NULL;
|
||||
}
|
||||
|
||||
int sact_SP_ExistsAlpha(int sp_no)
|
||||
{
|
||||
struct sact_sprite *sp = sact_get_sprite(sp_no);
|
||||
if (!sp) return 0;
|
||||
return sprite_exists_alpha(sp);
|
||||
}
|
||||
|
||||
int sact_SP_GetPosX(int sp_no)
|
||||
{
|
||||
struct sact_sprite *sp = sact_get_sprite(sp_no);
|
||||
if (!sp) return 0;
|
||||
return sprite_get_pos_x(sp);
|
||||
}
|
||||
|
||||
int sact_SP_GetPosY(int sp_no)
|
||||
{
|
||||
struct sact_sprite *sp = sact_get_sprite(sp_no);
|
||||
if (!sp) return 0;
|
||||
return sprite_get_pos_y(sp);
|
||||
}
|
||||
|
||||
int sact_SP_GetWidth(int sp_no)
|
||||
{
|
||||
struct sact_sprite *sp = sact_get_sprite(sp_no);
|
||||
if (!sp) return 0;
|
||||
return sprite_get_width(sp);
|
||||
}
|
||||
|
||||
int sact_SP_GetHeight(int sp_no)
|
||||
{
|
||||
struct sact_sprite *sp = sact_get_sprite(sp_no);
|
||||
if (!sp) return 0;
|
||||
return sprite_get_height(sp);
|
||||
}
|
||||
|
||||
int sact_SP_GetZ(int sp_no)
|
||||
{
|
||||
struct sact_sprite *sp = sact_get_sprite(sp_no);
|
||||
if (!sp) return 0;
|
||||
return sprite_get_z(sp);
|
||||
}
|
||||
|
||||
int sact_SP_GetShow(int sp_no)
|
||||
{
|
||||
struct sact_sprite *sp = sact_get_sprite(sp_no);
|
||||
if (!sp) return 0;
|
||||
return sprite_get_show(sp);
|
||||
}
|
||||
|
||||
int sact_SP_SetTextHome(int sp_no, int x, int y)
|
||||
{
|
||||
struct sact_sprite *sp = sact_get_sprite(sp_no);
|
||||
if (!sp) return 0;
|
||||
sprite_set_text_home(sp, x, y);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int sact_SP_SetTextLineSpace(int sp_no, int px)
|
||||
{
|
||||
struct sact_sprite *sp = sact_get_sprite(sp_no);
|
||||
if (!sp) return 1;
|
||||
sprite_set_text_line_space(sp, px);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int sact_SP_SetTextCharSpace(int sp_no, int px)
|
||||
{
|
||||
struct sact_sprite *sp = sact_get_sprite(sp_no);
|
||||
if (!sp) return 1;
|
||||
sprite_set_text_char_space(sp, px);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int sact_SP_SetTextPos(int sp_no, int x, int y)
|
||||
{
|
||||
struct sact_sprite *sp = sact_get_sprite(sp_no);
|
||||
if (!sp) return 0;
|
||||
sprite_set_text_pos(sp, x, y);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void init_text_metrics(struct text_metrics *tm, union vm_value *_tm)
|
||||
{
|
||||
*tm = (struct text_metrics) {
|
||||
.color = {
|
||||
.r = _tm[0].i,
|
||||
.g = _tm[1].i,
|
||||
.b = _tm[2].i,
|
||||
.a = 255
|
||||
},
|
||||
.outline_color = {
|
||||
.r = _tm[10].i,
|
||||
.g = _tm[11].i,
|
||||
.b = _tm[12].i,
|
||||
.a = 255
|
||||
},
|
||||
.size = _tm[3].i,
|
||||
.weight = _tm[4].i,
|
||||
.face = _tm[5].i,
|
||||
.outline_left = _tm[6].i,
|
||||
.outline_up = _tm[7].i,
|
||||
.outline_right = _tm[8].i,
|
||||
.outline_down = _tm[9].i,
|
||||
};
|
||||
}
|
||||
|
||||
int _sact_SP_TextDraw(int sp_no, struct string *text, struct text_metrics *tm)
|
||||
{
|
||||
struct sact_sprite *sp = sact_get_sprite(sp_no);
|
||||
if (!sp) return 0;
|
||||
sprite_text_draw(sp, text, tm);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int sact_SP_TextDraw(int sp_no, struct string *text, struct page *_tm)
|
||||
{
|
||||
struct text_metrics tm;
|
||||
init_text_metrics(&tm, _tm->values);
|
||||
_sact_SP_TextDraw(sp_no, text, &tm);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int sact_SP_TextClear(int sp_no)
|
||||
{
|
||||
struct sact_sprite *sp = sact_get_sprite(sp_no);
|
||||
if (!sp) return 0;
|
||||
sprite_text_clear(sp);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int sact_SP_TextHome(int sp_no, int size)
|
||||
{
|
||||
struct sact_sprite *sp = sact_get_sprite(sp_no);
|
||||
if (!sp) return 0;
|
||||
sprite_text_home(sp, size);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int sact_SP_TextNewLine(int sp_no, int size)
|
||||
{
|
||||
struct sact_sprite *sp = sact_get_sprite(sp_no);
|
||||
if (!sp) return 0;
|
||||
sprite_text_new_line(sp, size);
|
||||
return 1;
|
||||
}
|
||||
|
||||
//int SACT2_SP_TextBackSpace(int sp_no);
|
||||
|
||||
int sact_SP_TextCopy(int dno, int sno)
|
||||
{
|
||||
struct sact_sprite *dsp = sact_get_sprite(dno);
|
||||
struct sact_sprite *ssp = sact_get_sprite(sno);
|
||||
if (!ssp)
|
||||
return 0;
|
||||
if (!dsp) {
|
||||
sact_SP_Create(dno, 1, 1, 0, 0, 0, 0);
|
||||
if (!(dsp = sact_get_sprite(dno))) {
|
||||
WARNING("Failed to create sprite");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
sprite_text_copy(dsp, ssp);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int sact_SP_GetTextHomeX(int sp_no)
|
||||
{
|
||||
struct sact_sprite *sp = sact_get_sprite(sp_no);
|
||||
if (!sp) return 0;
|
||||
return sprite_get_text_home_x(sp);
|
||||
}
|
||||
|
||||
int sact_SP_GetTextHomeY(int sp_no)
|
||||
{
|
||||
struct sact_sprite *sp = sact_get_sprite(sp_no);
|
||||
if (!sp) return 0;
|
||||
return sprite_get_text_home_y(sp);
|
||||
}
|
||||
|
||||
int sact_SP_GetTextCharSpace(int sp_no)
|
||||
{
|
||||
struct sact_sprite *sp = sact_get_sprite(sp_no);
|
||||
if (!sp) return 0;
|
||||
return sprite_get_text_char_space(sp);
|
||||
}
|
||||
|
||||
int sact_SP_GetTextPosX(int sp_no)
|
||||
{
|
||||
struct sact_sprite *sp = sact_get_sprite(sp_no);
|
||||
if (!sp) return 0;
|
||||
return sprite_get_text_pos_x(sp);
|
||||
}
|
||||
|
||||
int sact_SP_GetTextPosY(int sp_no)
|
||||
{
|
||||
struct sact_sprite *sp = sact_get_sprite(sp_no);
|
||||
if (!sp) return 0;
|
||||
return sprite_get_text_pos_y(sp);
|
||||
}
|
||||
|
||||
int sact_SP_GetTextLineSpace(int sp_no)
|
||||
{
|
||||
struct sact_sprite *sp = sact_get_sprite(sp_no);
|
||||
if (!sp) return 0;
|
||||
return sprite_get_text_line_space(sp);
|
||||
}
|
||||
|
||||
int sact_SP_IsPtIn(int sp_no, int x, int y)
|
||||
{
|
||||
struct sact_sprite *sp = sact_get_sprite(sp_no);
|
||||
if (!sp) return 0;
|
||||
return sprite_is_point_in(sp, x, y);
|
||||
}
|
||||
|
||||
int sact_SP_IsPtInRect(int sp_no, int x, int y)
|
||||
{
|
||||
struct sact_sprite *sp = sact_get_sprite(sp_no);
|
||||
if (!sp) return 0;
|
||||
return sprite_is_point_in_rect(sp, x, y);
|
||||
}
|
||||
|
||||
int sact_CG_GetMetrics(int cg_no, struct page **page)
|
||||
{
|
||||
union vm_value *cgm = (*page)->values;
|
||||
struct cg_metrics metrics;
|
||||
if (!cg_get_metrics(ald[ALDFILE_CG], cg_no - 1, &metrics))
|
||||
return 0;
|
||||
cgm[0].i = metrics.w;
|
||||
cgm[1].i = metrics.h;
|
||||
cgm[2].i = metrics.bpp;
|
||||
cgm[3].i = metrics.has_pixel;
|
||||
cgm[4].i = metrics.has_alpha;
|
||||
cgm[5].i = metrics.pixel_pitch;
|
||||
cgm[6].i = metrics.alpha_pitch;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int sact_SP_GetAMapValue(int sp_no, int x, int y)
|
||||
{
|
||||
struct sact_sprite *sp = sact_get_sprite(sp_no);
|
||||
if (!sp) return 0;
|
||||
return sprite_get_amap_value(sp, x, y);
|
||||
}
|
||||
|
||||
int sact_SP_GetPixelValue(int sp_no, int x, int y, int *r, int *g, int *b)
|
||||
{
|
||||
struct sact_sprite *sp = sact_get_sprite(sp_no);
|
||||
if (!sp) return 0;
|
||||
sprite_get_pixel_value(sp, x, y, r, g, b);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int sact_GAME_MSG_GetNumOf(void)
|
||||
{
|
||||
return ain->nr_messages;
|
||||
}
|
||||
|
||||
//void SACT2_GAME_MSG_Get(int index, struct string **text);
|
||||
|
||||
static void sact_IntToZenkaku(struct string **s, int value, int figures, int zero_pad)
|
||||
{
|
||||
int i;
|
||||
@@ -56,6 +580,8 @@ static void sact_IntToHankaku(struct string **s, int value, int figures, int zer
|
||||
string_append_cstr(s, buf, i);
|
||||
}
|
||||
|
||||
//int SACT2_StringPopFront(struct string **dst, struct string **src);
|
||||
|
||||
static int sact_Mouse_GetPos(int *x, int *y)
|
||||
{
|
||||
handle_events();
|
||||
@@ -90,6 +616,9 @@ static int sact_Joypad_IsKeyDown(int num, int key)
|
||||
return 0; // TODO
|
||||
}
|
||||
|
||||
//int SACT2_Joypad_GetNumof(void);
|
||||
HLL_WARN_UNIMPLEMENTED( , void, SACT2, JoypadQuake_Set, int num, int type, int magnitude);
|
||||
|
||||
static bool sact_Joypad_GetAnalogStickStatus(int num, int type, float *degree, float *power)
|
||||
{
|
||||
//hll_unimplemented_warning(SACT2, Joypad_GetAnalogStickStatus);
|
||||
@@ -125,6 +654,17 @@ static int sact_CG_IsExist(int cg_no)
|
||||
return ald[ALDFILE_CG] && archive_exists(ald[ALDFILE_CG], cg_no - 1);
|
||||
}
|
||||
|
||||
//int SACT2_CSV_Load(struct string *filename);
|
||||
//int SACT2_CSV_Save(void);
|
||||
//int SACT2_CSV_SaveAs(struct string *filename);
|
||||
//int SACT2_CSV_CountLines(void);
|
||||
//int SACT2_CSV_CountColumns(void);
|
||||
//void SACT2_CSV_Get(struct string **s, int line, int column);
|
||||
//int SACT2_CSV_Set(int line, int column, struct string *data);
|
||||
//int SACT2_CSV_GetInt(int line, int column);
|
||||
//void SACT2_CSV_SetInt(int line, int column, int data);
|
||||
//void SACT2_CSV_Realloc(int lines, int columns);
|
||||
|
||||
static int sact_Music_IsExist(int n)
|
||||
{
|
||||
return bgm_exists(n - 1);
|
||||
@@ -155,11 +695,27 @@ static int sact_Music_IsPlay(int ch)
|
||||
return bgm_is_playing(ch);
|
||||
}
|
||||
|
||||
HLL_WARN_UNIMPLEMENTED(1, int, SACT2, Music_SetLoopCount, int ch, int count);
|
||||
HLL_WARN_UNIMPLEMENTED(1, int, SACT2, Music_GetLoopCount, int ch);
|
||||
//int SACT2_Music_SetLoopStartPos(int ch, int pos);
|
||||
//int SACT2_Music_SetLoopEndPos(int ch, int pos);
|
||||
|
||||
static int sact_Music_Fade(int ch, int time, int volume, int stop)
|
||||
{
|
||||
return bgm_fade(ch, time, volume, stop);
|
||||
}
|
||||
|
||||
HLL_WARN_UNIMPLEMENTED(1, int, SACT2, Music_StopFade, int ch);
|
||||
HLL_WARN_UNIMPLEMENTED(0, int, SACT2, Music_IsFade, int ch);
|
||||
HLL_WARN_UNIMPLEMENTED(1, int, SACT2, Music_Pause, int ch);
|
||||
HLL_WARN_UNIMPLEMENTED(1, int, SACT2, Music_Restart, int ch);
|
||||
HLL_WARN_UNIMPLEMENTED(1, int, SACT2, Music_IsPause, int ch);
|
||||
HLL_WARN_UNIMPLEMENTED(1, int, SACT2, Music_GetPos, int ch);
|
||||
HLL_WARN_UNIMPLEMENTED(1, int, SACT2, Music_GetLength, int ch);
|
||||
HLL_WARN_UNIMPLEMENTED(1, int, SACT2, Music_GetSamplePos, int ch);
|
||||
HLL_WARN_UNIMPLEMENTED(1, int, SACT2, Music_GetSampleLength, int ch);
|
||||
HLL_WARN_UNIMPLEMENTED(1, int, SACT2, Music_Seek, int ch, int pos);
|
||||
|
||||
static int sact_Sound_IsExist(int n)
|
||||
{
|
||||
return wav_exists(n - 1);
|
||||
@@ -195,21 +751,34 @@ static int sact_Sound_IsPlay(int ch)
|
||||
return wav_is_playing(ch);
|
||||
}
|
||||
|
||||
//int SACT2_Sound_SetLoopCount(int ch, int count);
|
||||
//int SACT2_Sound_GetLoopCount(int ch);
|
||||
|
||||
static int sact_Sound_Fade(int ch, int time, int volume, int stop)
|
||||
{
|
||||
return wav_fade(ch, time, volume, stop);
|
||||
}
|
||||
|
||||
//int SACT2_Sound_StopFade(int ch);
|
||||
//int SACT2_Sound_IsFade(int ch);
|
||||
//int SACT2_Sound_GetPos(int ch);
|
||||
//int SACT2_Sound_GetLength(int ch);
|
||||
|
||||
static int sact_Sound_ReverseLR(int ch)
|
||||
{
|
||||
return wav_reverse_LR(ch);
|
||||
}
|
||||
|
||||
//int SACT2_Sound_GetVolume(int ch);
|
||||
|
||||
static int sact_Sound_GetTimeLength(int ch)
|
||||
{
|
||||
return wav_get_time_length(ch);
|
||||
}
|
||||
|
||||
//int SACT2_Sound_GetGroupNum(int ch);
|
||||
//bool SACT2_Sound_PrepareFromFile(int ch, struct string *filename);
|
||||
|
||||
static void sact_System_GetDate(int *year, int *month, int *mday, int *wday)
|
||||
{
|
||||
time_t t = time(NULL);
|
||||
@@ -234,61 +803,19 @@ static void sact_System_GetTime(int *hour, int *min, int *sec, int *ms)
|
||||
*ms = ts.tv_nsec / 1000000;
|
||||
}
|
||||
|
||||
//void SACT2_CG_RotateRGB(int dst, int dx, int dy, int w, int h, int rotate_type);
|
||||
|
||||
static void sact_CG_BlendAMapBin(int dst, int dx, int dy, int src, int sx, int sy, int w, int h, int border)
|
||||
{
|
||||
gfx_copy_use_amap_border(sact_get_texture_dirty(dst), dx, dy, sact_get_texture(src), sx, sy, w, h, border);
|
||||
struct sact_sprite *dsp = sact_get_sprite(dst);
|
||||
struct sact_sprite *ssp = sact_get_sprite(src);
|
||||
if (!dsp) return;
|
||||
struct texture *dtx = sprite_get_texture(dsp);
|
||||
struct texture *stx = ssp ? sprite_get_texture(ssp) : NULL;
|
||||
gfx_copy_use_amap_border(dtx, dx, dy, stx, sx, sy, w, h, border);
|
||||
sprite_dirty(dsp);
|
||||
}
|
||||
|
||||
//int SACT2_Error(struct string *err);
|
||||
//int SACT2_WP_GetSP(int sp);
|
||||
//int SACT2_WP_SetSP(int sp);
|
||||
HLL_WARN_UNIMPLEMENTED(1, int, SACT2, EffectSetMask, int cg);
|
||||
//int SACT2_EffectSetMaskSP(int sp);
|
||||
HLL_WARN_UNIMPLEMENTED( , void, SACT2, QuakeScreen, int amp_x, int amp_y, int time, int key);
|
||||
//void SACT2_QUAKE_SET_CROSS(int amp_x, int amp_y);
|
||||
//void SACT2_QUAKE_SET_ROTATION(int amp, int cycle);
|
||||
//int SACT2_SP_SetCGFromFile(int sp, struct string *filename);
|
||||
//int SACT2_SP_SaveCG(int sp, struct string *filename);
|
||||
//int SACT2_SP_CreateCustom(int sp);
|
||||
//int SACT2_SP_TextBackSpace(int sp_no);
|
||||
//void SACT2_GAME_MSG_Get(int index, struct string **text);
|
||||
//int SACT2_StringPopFront(struct string **dst, struct string **src);
|
||||
//int SACT2_Joypad_GetNumof(void);
|
||||
HLL_WARN_UNIMPLEMENTED( , void, SACT2, JoypadQuake_Set, int num, int type, int magnitude);
|
||||
//int SACT2_CSV_Load(struct string *filename);
|
||||
//int SACT2_CSV_Save(void);
|
||||
//int SACT2_CSV_SaveAs(struct string *filename);
|
||||
//int SACT2_CSV_CountLines(void);
|
||||
//int SACT2_CSV_CountColumns(void);
|
||||
//void SACT2_CSV_Get(struct string **s, int line, int column);
|
||||
//int SACT2_CSV_Set(int line, int column, struct string *data);
|
||||
//int SACT2_CSV_GetInt(int line, int column);
|
||||
//void SACT2_CSV_SetInt(int line, int column, int data);
|
||||
//void SACT2_CSV_Realloc(int lines, int columns);
|
||||
HLL_WARN_UNIMPLEMENTED(1, int, SACT2, Music_SetLoopCount, int ch, int count);
|
||||
HLL_WARN_UNIMPLEMENTED(1, int, SACT2, Music_GetLoopCount, int ch);
|
||||
//int SACT2_Music_SetLoopStartPos(int ch, int pos);
|
||||
//int SACT2_Music_SetLoopEndPos(int ch, int pos);
|
||||
HLL_WARN_UNIMPLEMENTED(1, int, SACT2, Music_StopFade, int ch);
|
||||
HLL_WARN_UNIMPLEMENTED(0, int, SACT2, Music_IsFade, int ch);
|
||||
HLL_WARN_UNIMPLEMENTED(1, int, SACT2, Music_Pause, int ch);
|
||||
HLL_WARN_UNIMPLEMENTED(1, int, SACT2, Music_Restart, int ch);
|
||||
HLL_WARN_UNIMPLEMENTED(1, int, SACT2, Music_IsPause, int ch);
|
||||
HLL_WARN_UNIMPLEMENTED(1, int, SACT2, Music_GetPos, int ch);
|
||||
HLL_WARN_UNIMPLEMENTED(1, int, SACT2, Music_GetLength, int ch);
|
||||
HLL_WARN_UNIMPLEMENTED(1, int, SACT2, Music_GetSamplePos, int ch);
|
||||
HLL_WARN_UNIMPLEMENTED(1, int, SACT2, Music_GetSampleLength, int ch);
|
||||
HLL_WARN_UNIMPLEMENTED(1, int, SACT2, Music_Seek, int ch, int pos);
|
||||
//int SACT2_Sound_SetLoopCount(int ch, int count);
|
||||
//int SACT2_Sound_GetLoopCount(int ch);
|
||||
//int SACT2_Sound_StopFade(int ch);
|
||||
//int SACT2_Sound_IsFade(int ch);
|
||||
//int SACT2_Sound_GetPos(int ch);
|
||||
//int SACT2_Sound_GetLength(int ch);
|
||||
//int SACT2_Sound_GetVolume(int ch);
|
||||
//int SACT2_Sound_GetGroupNum(int ch);
|
||||
//bool SACT2_Sound_PrepareFromFile(int ch, struct string *filename);
|
||||
//void SACT2_CG_RotateRGB(int dst, int dx, int dy, int w, int h, int rotate_type);
|
||||
//void SACT2_Debug_Pause(void);
|
||||
//void SACT2_Debug_GetFuncStack(struct string **s, int nest);
|
||||
HLL_WARN_UNIMPLEMENTED(0, int, SACT2, SP_SetBrightness, int sp_no, int brightness);
|
||||
|
||||
+1
-1
@@ -10,8 +10,8 @@ xsystem4 = ['audio.c',
|
||||
'input.c',
|
||||
'page.c',
|
||||
'resume.c',
|
||||
'sact_graphics.c',
|
||||
'savedata.c',
|
||||
'sprite.c',
|
||||
'system4.c',
|
||||
'text.c',
|
||||
'video.c',
|
||||
|
||||
@@ -1,713 +0,0 @@
|
||||
/* Copyright (C) 2019 Nunuhara Cabbage <nunuhara@haniwa.technology>
|
||||
*
|
||||
* 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 <http://gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "system4.h"
|
||||
#include "system4/ald.h"
|
||||
#include "system4/cg.h"
|
||||
#include "system4/string.h"
|
||||
#include "system4/utfsjis.h"
|
||||
|
||||
#include "audio.h"
|
||||
#include "input.h"
|
||||
#include "gfx/gfx.h"
|
||||
#include "sact.h"
|
||||
#include "vm.h"
|
||||
#include "vm/page.h"
|
||||
#include "xsystem4.h"
|
||||
|
||||
static struct sact_sprite *create_sprite(int sp_no, int width, int height, int r, int g, int b, int a);
|
||||
|
||||
bool sact_dirty = true;
|
||||
|
||||
static struct sact_sprite **sprites = NULL;
|
||||
static int nr_sprites = 0;
|
||||
|
||||
// wallpaper
|
||||
static struct sact_sprite wp;
|
||||
|
||||
TAILQ_HEAD(listhead, sact_sprite) sprite_list =
|
||||
TAILQ_HEAD_INITIALIZER(sprite_list);
|
||||
|
||||
static void sprite_register(struct sact_sprite *sp)
|
||||
{
|
||||
struct sact_sprite *p;
|
||||
TAILQ_FOREACH(p, &sprite_list, entry) {
|
||||
if (p->z > sp->z) {
|
||||
TAILQ_INSERT_BEFORE(p, sp, entry);
|
||||
return;
|
||||
}
|
||||
}
|
||||
TAILQ_INSERT_TAIL(&sprite_list, sp, entry);
|
||||
}
|
||||
|
||||
static void sprite_unregister(struct sact_sprite *sp)
|
||||
{
|
||||
TAILQ_REMOVE(&sprite_list, sp, entry);
|
||||
}
|
||||
|
||||
struct sact_sprite *sact_get_sprite(int sp)
|
||||
{
|
||||
if (sp < -1 || sp >= nr_sprites)
|
||||
return NULL;
|
||||
return sprites[sp];
|
||||
}
|
||||
|
||||
struct sact_sprite *sact_get_sprite_dirty(int sp)
|
||||
{
|
||||
if (sp < -1 || sp >= nr_sprites)
|
||||
return NULL;
|
||||
sprite_dirty(sprites[sp]);
|
||||
return sprites[sp];
|
||||
}
|
||||
|
||||
struct texture *sact_get_texture(int sp_no)
|
||||
{
|
||||
struct sact_sprite *sp = sact_get_sprite(sp_no);
|
||||
if (!sp)
|
||||
return NULL;
|
||||
if (!sp->texture.handle) {
|
||||
gfx_init_texture_with_color(&sp->texture, sp->rect.w, sp->rect.h, sp->color);
|
||||
}
|
||||
return &sp->texture;
|
||||
}
|
||||
|
||||
struct texture *sact_get_texture_dirty(int sp_no)
|
||||
{
|
||||
struct sact_sprite *sp = sact_get_sprite_dirty(sp_no);
|
||||
if (!sp)
|
||||
return NULL;
|
||||
if (!sp->texture.handle) {
|
||||
gfx_init_texture_with_color(&sp->texture, sp->rect.w, sp->rect.h, sp->color);
|
||||
}
|
||||
return &sp->texture;
|
||||
|
||||
}
|
||||
|
||||
static struct sact_sprite *alloc_sprite(int sp)
|
||||
{
|
||||
sprites[sp] = xcalloc(1, sizeof(struct sact_sprite));
|
||||
sprites[sp]->no = sp;
|
||||
sprite_dirty(sprites[sp]);
|
||||
return sprites[sp];
|
||||
}
|
||||
|
||||
static void free_sprite(struct sact_sprite *sp)
|
||||
{
|
||||
if (sprites[sp->no] == NULL)
|
||||
VM_ERROR("Double free of sact_sprite");
|
||||
if (sp->show)
|
||||
sprite_unregister(sp);
|
||||
sprites[sp->no] = NULL;
|
||||
gfx_delete_texture(&sp->texture);
|
||||
gfx_delete_texture(&sp->text.texture);
|
||||
free(sp);
|
||||
}
|
||||
|
||||
static void realloc_sprite_table(int n)
|
||||
{
|
||||
int old_nr_sprites = nr_sprites;
|
||||
nr_sprites = n;
|
||||
|
||||
struct sact_sprite **tmp = xrealloc(sprites-1, sizeof(struct sact_sprite*) * (nr_sprites+1));
|
||||
sprites = tmp + 1;
|
||||
|
||||
memset(sprites + old_nr_sprites, 0, sizeof(struct sact_sprite*) * (nr_sprites - old_nr_sprites));
|
||||
}
|
||||
|
||||
int sact_Init(possibly_unused void *_, possibly_unused int cg_cache_size)
|
||||
{
|
||||
// already initialized
|
||||
if (sprites)
|
||||
return 1;
|
||||
|
||||
gfx_init();
|
||||
gfx_font_init();
|
||||
audio_init();
|
||||
|
||||
nr_sprites = 256;
|
||||
sprites = xmalloc(sizeof(struct sact_sprite*) * 257);
|
||||
memset(sprites, 0, sizeof(struct sact_sprite*) * 257);
|
||||
|
||||
// create sprite for main_surface
|
||||
Texture *t = gfx_main_surface();
|
||||
struct sact_sprite *sp = create_sprite(0, t->w, t->h, 0, 0, 0, 255);
|
||||
sp->texture = *t; // XXX: textures normally shouldn't be copied like this...
|
||||
|
||||
sprites++;
|
||||
return 1;
|
||||
}
|
||||
|
||||
void sact_ModuleFini(void)
|
||||
{
|
||||
for (int i = 0; i < nr_sprites; i++) {
|
||||
if (sprites[i]) {
|
||||
free_sprite(sprites[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int sact_SetWP(int cg_no)
|
||||
{
|
||||
if (!cg_no) {
|
||||
gfx_delete_texture(&wp.texture);
|
||||
return 1;
|
||||
}
|
||||
|
||||
struct cg *cg = cg_load(ald[ALDFILE_CG], cg_no - 1);
|
||||
if (!cg)
|
||||
return 0;
|
||||
|
||||
gfx_delete_texture(&wp.texture);
|
||||
gfx_init_texture_with_cg(&wp.texture, cg);
|
||||
cg_free(cg);
|
||||
sact_dirty = true;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int sact_SetWP_Color(int r, int g, int b)
|
||||
{
|
||||
gfx_set_clear_color(r, g, b, 255);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int sact_GetScreenWidth(void)
|
||||
{
|
||||
return config.view_width;
|
||||
}
|
||||
|
||||
int sact_GetScreenHeight(void)
|
||||
{
|
||||
return config.view_height;
|
||||
}
|
||||
|
||||
int sact_GetMainSurfaceNumber(void)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
void sact_render_scene(void)
|
||||
{
|
||||
gfx_clear();
|
||||
if (wp.texture.handle) {
|
||||
Rectangle r = RECT(0, 0, wp.texture.w, wp.texture.h);
|
||||
gfx_render_texture(&wp.texture, &r);
|
||||
}
|
||||
struct sact_sprite *p;
|
||||
TAILQ_FOREACH(p, &sprite_list, entry) {
|
||||
if (!p->texture.handle) {
|
||||
gfx_init_texture_with_color(&p->texture, p->rect.w, p->rect.h, p->color);
|
||||
}
|
||||
gfx_render_texture(&p->texture, &p->rect);
|
||||
if (p->text.texture.handle) {
|
||||
gfx_render_texture(&p->text.texture, &p->rect);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int sact_Update(void)
|
||||
{
|
||||
handle_events();
|
||||
if (sact_dirty) {
|
||||
sact_render_scene();
|
||||
gfx_swap();
|
||||
sact_dirty = false;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int sact_SP_GetUnuseNum(int min)
|
||||
{
|
||||
for (int i = min; i < nr_sprites; i++) {
|
||||
if (!sprites[i])
|
||||
return i;
|
||||
}
|
||||
|
||||
int n = max(min, nr_sprites);
|
||||
realloc_sprite_table(n + 256);
|
||||
return n;
|
||||
}
|
||||
|
||||
int sact_SP_Count(void)
|
||||
{
|
||||
int count = 0;
|
||||
for (int i = 0; i < nr_sprites; i++) {
|
||||
if (sprites[i])
|
||||
count++;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
int sact_SP_Enum(struct page **array)
|
||||
{
|
||||
int count = 0;
|
||||
int size = (*array)->nr_vars;
|
||||
for (int i = 0; i < nr_sprites && count < size; i++) {
|
||||
if (sprites[i]) {
|
||||
(*array)->values[count++].i = i;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
int sact_SP_GetMaxZ(void)
|
||||
{
|
||||
if (TAILQ_EMPTY(&sprite_list))
|
||||
return 0;
|
||||
return TAILQ_LAST(&sprite_list, listhead)->z;
|
||||
}
|
||||
|
||||
int sact_SP_SetCG(int sp_no, int cg_no)
|
||||
{
|
||||
struct sact_sprite *sp = sact_get_sprite_dirty(sp_no);
|
||||
if (!sp)
|
||||
sact_SP_Create(sp_no, 1, 1, 0, 0, 0, 255);
|
||||
if (!(sp = sact_get_sprite(sp_no))) {
|
||||
WARNING("Failed to create sprite");
|
||||
return 0;
|
||||
}
|
||||
struct cg *cg = cg_load(ald[ALDFILE_CG], cg_no - 1);
|
||||
if (!cg)
|
||||
return 0;
|
||||
gfx_init_texture_with_cg(&sp->texture, cg);
|
||||
sp->rect.w = cg->metrics.w;
|
||||
sp->rect.h = cg->metrics.h;
|
||||
sp->cg_no = cg_no;
|
||||
cg_free(cg);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static struct sact_sprite *create_sprite(int sp_no, int width, int height, int r, int g, int b, int a)
|
||||
{
|
||||
struct sact_sprite *sp;
|
||||
if (sp_no < 0)
|
||||
VM_ERROR("Invalid sprite number: %d", sp_no);
|
||||
if (sp_no >= nr_sprites) {
|
||||
realloc_sprite_table(sp_no+256);
|
||||
}
|
||||
if (!(sp = sact_get_sprite_dirty(sp_no)))
|
||||
sp = alloc_sprite(sp_no);
|
||||
sp->color = (SDL_Color) { .r = r, .g = g, .b = b, .a = (a >= 0 ? a : 255) };
|
||||
sp->rect.w = width;
|
||||
sp->rect.h = height;
|
||||
if (!sp->show) {
|
||||
sp->show = true;
|
||||
sprite_register(sp);
|
||||
}
|
||||
gfx_delete_texture(&sp->texture);
|
||||
return sp;
|
||||
}
|
||||
|
||||
int sact_SP_Create(int sp_no, int width, int height, int r, int g, int b, int a)
|
||||
{
|
||||
create_sprite(sp_no, width, height, r, g, b, a);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int sact_SP_CreatePixelOnly(int sp_no, int width, int height)
|
||||
{
|
||||
create_sprite(sp_no, width, height, 0, 0, 0, -1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int sact_SP_Delete(int sp_no)
|
||||
{
|
||||
struct sact_sprite *sp = sact_get_sprite(sp_no);
|
||||
if (!sp) return 0;
|
||||
free_sprite(sp);
|
||||
sact_dirty = true;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int sact_SP_SetPos(int sp_no, int x, int y)
|
||||
{
|
||||
struct sact_sprite *sp = sact_get_sprite_dirty(sp_no);
|
||||
if (!sp) return 1;
|
||||
sp->rect.x = x;
|
||||
sp->rect.y = y;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int sact_SP_SetX(int sp_no, int x)
|
||||
{
|
||||
struct sact_sprite *sp = sact_get_sprite_dirty(sp_no);
|
||||
if (!sp) return 0;
|
||||
sp->rect.x = x;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int sact_SP_SetY(int sp_no, int y)
|
||||
{
|
||||
struct sact_sprite *sp = sact_get_sprite_dirty(sp_no);
|
||||
if (!sp) return 0;
|
||||
sp->rect.y = y;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int sact_SP_SetZ(int sp_no, int z)
|
||||
{
|
||||
struct sact_sprite *sp = sact_get_sprite_dirty(sp_no);
|
||||
if (!sp) return 0;
|
||||
sp->z = z;
|
||||
if (sp->show) {
|
||||
sprite_unregister(sp);
|
||||
sprite_register(sp);
|
||||
}
|
||||
return 1;
|
||||
|
||||
}
|
||||
|
||||
int sact_SP_GetBlendRate(int sp_no)
|
||||
{
|
||||
struct texture *t = sact_get_texture(sp_no);
|
||||
return t ? t->alpha_mod : 0;
|
||||
}
|
||||
|
||||
int sact_SP_SetBlendRate(int sp_no, int rate)
|
||||
{
|
||||
struct texture *t = sact_get_texture_dirty(sp_no);
|
||||
if (!t) return 0;
|
||||
t->alpha_mod = max(0, min(255, rate));
|
||||
return 1;
|
||||
}
|
||||
|
||||
int sact_SP_SetShow(int sp_no, bool show)
|
||||
{
|
||||
struct sact_sprite *sp = sact_get_sprite(sp_no);
|
||||
if (!sp) return 0;
|
||||
if (show == sp->show)
|
||||
return 1;
|
||||
sp->show = show;
|
||||
sprite_dirty(sp);
|
||||
if (show)
|
||||
sprite_register(sp);
|
||||
else
|
||||
sprite_unregister(sp);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int sact_SP_SetDrawMethod(int sp_no, int method)
|
||||
{
|
||||
struct texture *t = sact_get_texture_dirty(sp_no);
|
||||
if (!t) return 0;
|
||||
if (method < 0 || method >= NR_DRAW_METHODS) {
|
||||
WARNING("unknown draw method: %d", method);
|
||||
return 0;
|
||||
}
|
||||
t->draw_method = method;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int sact_SP_GetDrawMethod(int sp_no)
|
||||
{
|
||||
struct texture *t = sact_get_texture(sp_no);
|
||||
if (!t) return DRAW_METHOD_NORMAL;
|
||||
return t->draw_method;
|
||||
}
|
||||
|
||||
int sact_SP_IsUsing(int sp_no)
|
||||
{
|
||||
return sact_get_sprite(sp_no) != NULL;
|
||||
}
|
||||
|
||||
int sact_SP_ExistsAlpha(int sp_no)
|
||||
{
|
||||
struct sact_sprite *sp = sact_get_sprite(sp_no);
|
||||
if (!sp) return 0;
|
||||
return sp->texture.has_alpha;
|
||||
}
|
||||
|
||||
int sact_SP_GetPosX(int sp_no)
|
||||
{
|
||||
struct sact_sprite *sp = sact_get_sprite(sp_no);
|
||||
if (!sp) return 0;
|
||||
return sp->rect.x;
|
||||
}
|
||||
|
||||
int sact_SP_GetPosY(int sp_no)
|
||||
{
|
||||
struct sact_sprite *sp = sact_get_sprite(sp_no);
|
||||
if (!sp) return 0;
|
||||
return sp->rect.y;
|
||||
}
|
||||
|
||||
int sact_SP_GetWidth(int sp_no)
|
||||
{
|
||||
struct sact_sprite *sp = sact_get_sprite(sp_no);
|
||||
if (!sp) return 0;
|
||||
return sp->rect.w;
|
||||
}
|
||||
|
||||
int sact_SP_GetHeight(int sp_no)
|
||||
{
|
||||
struct sact_sprite *sp = sact_get_sprite(sp_no);
|
||||
if (!sp) return 0;
|
||||
return sp->rect.h;
|
||||
}
|
||||
|
||||
int sact_SP_GetZ(int sp_no)
|
||||
{
|
||||
struct sact_sprite *sp = sact_get_sprite(sp_no);
|
||||
if (!sp) return 0;
|
||||
return sp->z;
|
||||
}
|
||||
|
||||
int sact_SP_GetShow(int sp_no)
|
||||
{
|
||||
struct sact_sprite *sp = sact_get_sprite(sp_no);
|
||||
if (!sp) return 0;
|
||||
return sp->show;
|
||||
}
|
||||
|
||||
int sact_SP_SetTextHome(int sp_no, int x, int y)
|
||||
{
|
||||
struct sact_sprite *sp = sact_get_sprite_dirty(sp_no);
|
||||
if (!sp) return 0;
|
||||
sp->text.home = (Point) { .x = x, .y = y };
|
||||
return 1;
|
||||
}
|
||||
|
||||
int sact_SP_SetTextLineSpace(int sp_no, int px)
|
||||
{
|
||||
struct sact_sprite *sp = sact_get_sprite_dirty(sp_no);
|
||||
if (!sp) return 1;
|
||||
sp->text.line_space = px;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int sact_SP_SetTextCharSpace(int sp_no, int px)
|
||||
{
|
||||
struct sact_sprite *sp = sact_get_sprite_dirty(sp_no);
|
||||
if (!sp) return 1;
|
||||
sp->text.char_space = px;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int sact_SP_SetTextPos(int sp_no, int x, int y)
|
||||
{
|
||||
struct sact_sprite *sp = sact_get_sprite_dirty(sp_no);
|
||||
if (!sp) return 0;
|
||||
sp->text.pos = (Point) { .x = x, .y = y };
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void init_text_metrics(struct text_metrics *tm, union vm_value *_tm)
|
||||
{
|
||||
*tm = (struct text_metrics) {
|
||||
.color = {
|
||||
.r = _tm[0].i,
|
||||
.g = _tm[1].i,
|
||||
.b = _tm[2].i,
|
||||
.a = 255
|
||||
},
|
||||
.outline_color = {
|
||||
.r = _tm[10].i,
|
||||
.g = _tm[11].i,
|
||||
.b = _tm[12].i,
|
||||
.a = 255
|
||||
},
|
||||
.size = _tm[3].i,
|
||||
.weight = _tm[4].i,
|
||||
.face = _tm[5].i,
|
||||
.outline_left = _tm[6].i,
|
||||
.outline_up = _tm[7].i,
|
||||
.outline_right = _tm[8].i,
|
||||
.outline_down = _tm[9].i,
|
||||
};
|
||||
}
|
||||
|
||||
int _sact_SP_TextDraw(int sp_no, struct string *text, struct text_metrics *tm)
|
||||
{
|
||||
struct sact_sprite *sp = sact_get_sprite_dirty(sp_no);
|
||||
if (!sp) return 0;
|
||||
|
||||
if (!sp->text.texture.handle) {
|
||||
SDL_Color c;
|
||||
if (tm->outline_left || tm->outline_right || tm->outline_up || tm->outline_down)
|
||||
c = tm->outline_color;
|
||||
else
|
||||
c = tm->color;
|
||||
c.a = 0;
|
||||
gfx_init_texture_with_color(&sp->text.texture, sp->rect.w, sp->rect.h, c);
|
||||
}
|
||||
|
||||
sp->text.pos.x += gfx_render_text(&sp->text.texture, sp->text.pos, text->text, tm, sp->text.char_space);
|
||||
return 1;
|
||||
|
||||
}
|
||||
|
||||
int sact_SP_TextDraw(int sp_no, struct string *text, struct page *_tm)
|
||||
{
|
||||
struct text_metrics tm;
|
||||
init_text_metrics(&tm, _tm->values);
|
||||
_sact_SP_TextDraw(sp_no, text, &tm);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void clear_text(struct sact_sprite *sp)
|
||||
{
|
||||
gfx_delete_texture(&sp->text.texture);
|
||||
}
|
||||
|
||||
int sact_SP_TextClear(int sp_no)
|
||||
{
|
||||
struct sact_sprite *sp = sact_get_sprite_dirty(sp_no);
|
||||
if (!sp) return 0;
|
||||
clear_text(sp);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int sact_SP_TextHome(int sp_no, possibly_unused int size)
|
||||
{
|
||||
struct sact_sprite *sp = sact_get_sprite_dirty(sp_no);
|
||||
if (!sp) return 0;
|
||||
// FIXME: do something with nTextSize
|
||||
sp->text.pos = sp->text.home;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int sact_SP_TextNewLine(int sp_no, int size)
|
||||
{
|
||||
struct sact_sprite *sp = sact_get_sprite_dirty(sp_no);
|
||||
if (!sp) return 0;
|
||||
sp->text.pos = POINT(sp->text.home.x, sp->text.pos.y + size + sp->text.line_space);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int sact_SP_TextCopy(int dno, int sno)
|
||||
{
|
||||
struct sact_sprite *dsp = sact_get_sprite_dirty(dno);
|
||||
struct sact_sprite *ssp = sact_get_sprite(sno);
|
||||
if (!ssp)
|
||||
return 0;
|
||||
if (!dsp) {
|
||||
sact_SP_Create(dno, 1, 1, 0, 0, 0, 0);
|
||||
if (!(dsp = sact_get_sprite(dno))) {
|
||||
WARNING("Failed to create sprite");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
clear_text(dsp);
|
||||
if (ssp->text.texture.handle) {
|
||||
SDL_Color c = { 0, 0, 0, 0 };
|
||||
gfx_init_texture_with_color(&dsp->text.texture, dsp->rect.w, dsp->rect.h, c);
|
||||
gfx_copy(&dsp->text.texture, 0, 0, &ssp->text.texture, 0, 0, ssp->text.texture.w, ssp->text.texture.h);
|
||||
gfx_copy_amap(&dsp->text.texture, 0, 0, &ssp->text.texture, 0, 0, ssp->text.texture.w, ssp->text.texture.h);
|
||||
}
|
||||
dsp->text.home = ssp->text.home;
|
||||
dsp->text.pos = ssp->text.pos;
|
||||
dsp->text.char_space = ssp->text.char_space;
|
||||
dsp->text.line_space = ssp->text.line_space;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int sact_SP_GetTextHomeX(int sp_no)
|
||||
{
|
||||
struct sact_sprite *sp = sact_get_sprite(sp_no);
|
||||
if (!sp) return 0;
|
||||
return sp->text.home.x;
|
||||
}
|
||||
|
||||
int sact_SP_GetTextHomeY(int sp_no)
|
||||
{
|
||||
struct sact_sprite *sp = sact_get_sprite(sp_no);
|
||||
if (!sp) return 0;
|
||||
return sp->text.home.y;
|
||||
}
|
||||
|
||||
int sact_SP_GetTextCharSpace(int sp_no)
|
||||
{
|
||||
struct sact_sprite *sp = sact_get_sprite(sp_no);
|
||||
if (!sp) return 0;
|
||||
return sp->text.char_space;
|
||||
}
|
||||
|
||||
int sact_SP_GetTextPosX(int sp_no)
|
||||
{
|
||||
struct sact_sprite *sp = sact_get_sprite(sp_no);
|
||||
if (!sp) return 0;
|
||||
return sp->text.pos.x;
|
||||
}
|
||||
|
||||
int sact_SP_GetTextPosY(int sp_no)
|
||||
{
|
||||
struct sact_sprite *sp = sact_get_sprite(sp_no);
|
||||
if (!sp) return 0;
|
||||
return sp->text.pos.y;
|
||||
}
|
||||
|
||||
int sact_SP_GetTextLineSpace(int sp_no)
|
||||
{
|
||||
struct sact_sprite *sp = sact_get_sprite(sp_no);
|
||||
if (!sp) return 0;
|
||||
return sp->text.line_space;
|
||||
}
|
||||
|
||||
int sact_SP_IsPtIn(int sp_no, int x, int y)
|
||||
{
|
||||
Point p = POINT(x, y);
|
||||
struct sact_sprite *sp = sact_get_sprite(sp_no);
|
||||
|
||||
if (!sp || !SDL_PointInRect(&p, &sp->rect))
|
||||
return 0;
|
||||
|
||||
Texture *t = sact_get_texture(sp_no);
|
||||
SDL_Color c = gfx_get_pixel(t, x - sp->rect.x, y - sp->rect.y);
|
||||
return !!c.a;
|
||||
}
|
||||
|
||||
int sact_SP_IsPtInRect(int sp_no, int x, int y)
|
||||
{
|
||||
struct sact_sprite *sp = sact_get_sprite(sp_no);
|
||||
Point p = { .x = x, .y = y };
|
||||
if (!sp) return 0;
|
||||
return !!SDL_PointInRect(&p, &sp->rect);
|
||||
}
|
||||
|
||||
int sact_CG_GetMetrics(int cg_no, struct page **page)
|
||||
{
|
||||
union vm_value *cgm = (*page)->values;
|
||||
struct cg_metrics metrics;
|
||||
if (!cg_get_metrics(ald[ALDFILE_CG], cg_no - 1, &metrics))
|
||||
return 0;
|
||||
cgm[0].i = metrics.w;
|
||||
cgm[1].i = metrics.h;
|
||||
cgm[2].i = metrics.bpp;
|
||||
cgm[3].i = metrics.has_pixel;
|
||||
cgm[4].i = metrics.has_alpha;
|
||||
cgm[5].i = metrics.pixel_pitch;
|
||||
cgm[6].i = metrics.alpha_pitch;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int sact_SP_GetAMapValue(int sp_no, int x, int y)
|
||||
{
|
||||
Texture *t = sact_get_texture(sp_no);
|
||||
SDL_Color c = gfx_get_pixel(t, x, y);
|
||||
return c.a;
|
||||
}
|
||||
|
||||
int sact_SP_GetPixelValue(int sp_no, int x, int y, int *r, int *g, int *b)
|
||||
{
|
||||
Texture *t = sact_get_texture(sp_no);
|
||||
SDL_Color c = gfx_get_pixel(t, x, y);
|
||||
*r = c.r;
|
||||
*g = c.g;
|
||||
*b = c.b;
|
||||
return 1;
|
||||
}
|
||||
+338
@@ -0,0 +1,338 @@
|
||||
/* Copyright (C) 2019 Nunuhara Cabbage <nunuhara@haniwa.technology>
|
||||
*
|
||||
* 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 <http://gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "system4.h"
|
||||
#include "system4/ald.h"
|
||||
#include "system4/cg.h"
|
||||
#include "system4/string.h"
|
||||
#include "system4/utfsjis.h"
|
||||
|
||||
#include "audio.h"
|
||||
#include "input.h"
|
||||
#include "gfx/gfx.h"
|
||||
#include "sprite.h"
|
||||
#include "vm.h"
|
||||
#include "vm/page.h"
|
||||
#include "xsystem4.h"
|
||||
|
||||
bool sact_dirty = true;
|
||||
|
||||
static struct sact_sprite wp;
|
||||
|
||||
TAILQ_HEAD(listhead, sact_sprite) sprite_list =
|
||||
TAILQ_HEAD_INITIALIZER(sprite_list);
|
||||
|
||||
void sprite_register(struct sact_sprite *sp)
|
||||
{
|
||||
struct sact_sprite *p;
|
||||
TAILQ_FOREACH(p, &sprite_list, entry) {
|
||||
if (p->z > sp->z) {
|
||||
TAILQ_INSERT_BEFORE(p, sp, entry);
|
||||
return;
|
||||
}
|
||||
}
|
||||
TAILQ_INSERT_TAIL(&sprite_list, sp, entry);
|
||||
if (sp->show)
|
||||
scene_dirty();
|
||||
}
|
||||
|
||||
void sprite_unregister(struct sact_sprite *sp)
|
||||
{
|
||||
TAILQ_REMOVE(&sprite_list, sp, entry);
|
||||
if (sp->show)
|
||||
scene_dirty();
|
||||
}
|
||||
|
||||
void sprite_free(struct sact_sprite *sp)
|
||||
{
|
||||
if (sp->show)
|
||||
sprite_unregister(sp);
|
||||
gfx_delete_texture(&sp->texture);
|
||||
gfx_delete_texture(&sp->text.texture);
|
||||
free(sp);
|
||||
}
|
||||
|
||||
void sprite_render_scene(void)
|
||||
{
|
||||
gfx_clear();
|
||||
if (wp.texture.handle) {
|
||||
Rectangle r = RECT(0, 0, wp.texture.w, wp.texture.h);
|
||||
gfx_render_texture(&wp.texture, &r);
|
||||
}
|
||||
struct sact_sprite *p;
|
||||
TAILQ_FOREACH(p, &sprite_list, entry) {
|
||||
if (!p->texture.handle) {
|
||||
gfx_init_texture_with_color(&p->texture, p->rect.w, p->rect.h, p->color);
|
||||
}
|
||||
gfx_render_texture(&p->texture, &p->rect);
|
||||
if (p->text.texture.handle) {
|
||||
gfx_render_texture(&p->text.texture, &p->rect);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void sprite_flip(void)
|
||||
{
|
||||
gfx_swap();
|
||||
sact_dirty = false;
|
||||
}
|
||||
|
||||
struct texture *sprite_get_texture(struct sact_sprite *sp)
|
||||
{
|
||||
if (!sp->texture.handle) {
|
||||
gfx_init_texture_with_color(&sp->texture, sp->rect.w, sp->rect.h, sp->color);
|
||||
}
|
||||
return &sp->texture;
|
||||
}
|
||||
|
||||
int sprite_set_wp(int cg_no)
|
||||
{
|
||||
if (!cg_no) {
|
||||
gfx_delete_texture(&wp.texture);
|
||||
return 1;
|
||||
}
|
||||
|
||||
struct cg *cg = cg_load(ald[ALDFILE_CG], cg_no - 1);
|
||||
if (!cg)
|
||||
return 0;
|
||||
|
||||
gfx_delete_texture(&wp.texture);
|
||||
gfx_init_texture_with_cg(&wp.texture, cg);
|
||||
cg_free(cg);
|
||||
scene_dirty();
|
||||
return 1;
|
||||
}
|
||||
|
||||
int sprite_set_wp_color(int r, int g, int b)
|
||||
{
|
||||
gfx_set_clear_color(r, g, b, 255);
|
||||
scene_dirty();
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
int sprite_set_cg(struct sact_sprite *sp, int cg_no)
|
||||
{
|
||||
struct cg *cg = cg_load(ald[ALDFILE_CG], cg_no - 1);
|
||||
if (!cg)
|
||||
return 0;
|
||||
gfx_init_texture_with_cg(&sp->texture, cg);
|
||||
sp->rect.w = cg->metrics.w;
|
||||
sp->rect.h = cg->metrics.h;
|
||||
sp->cg_no = cg_no;
|
||||
cg_free(cg);
|
||||
sprite_dirty(sp);
|
||||
return 1;
|
||||
}
|
||||
|
||||
void sprite_init(struct sact_sprite *sp, int w, int h, int r, int g, int b, int a)
|
||||
{
|
||||
sp->color = (SDL_Color) { .r = r, .g = g, .b = b, .a = (a >= 0 ? a : 255) };
|
||||
sp->rect.w = w;
|
||||
sp->rect.h = h;
|
||||
if (!sp->show) {
|
||||
sp->show = true;
|
||||
sprite_register(sp);
|
||||
}
|
||||
gfx_delete_texture(&sp->texture);
|
||||
sprite_dirty(sp);
|
||||
}
|
||||
|
||||
int sprite_get_max_z(void)
|
||||
{
|
||||
if (TAILQ_EMPTY(&sprite_list))
|
||||
return 0;
|
||||
return TAILQ_LAST(&sprite_list, listhead)->z;
|
||||
}
|
||||
|
||||
void sprite_set_pos(struct sact_sprite *sp, int x, int y)
|
||||
{
|
||||
sp->rect.x = x;
|
||||
sp->rect.y = y;
|
||||
sprite_dirty(sp);
|
||||
}
|
||||
|
||||
void sprite_set_x(struct sact_sprite *sp, int x)
|
||||
{
|
||||
sp->rect.x = x;
|
||||
sprite_dirty(sp);
|
||||
}
|
||||
|
||||
void sprite_set_y(struct sact_sprite *sp, int y)
|
||||
{
|
||||
sp->rect.y = y;
|
||||
sprite_dirty(sp);
|
||||
}
|
||||
|
||||
void sprite_set_z(struct sact_sprite *sp, int z)
|
||||
{
|
||||
sp->z = z;
|
||||
if (sp->show) {
|
||||
sprite_unregister(sp);
|
||||
sprite_register(sp);
|
||||
}
|
||||
}
|
||||
|
||||
int sprite_get_blend_rate(struct sact_sprite *sp)
|
||||
{
|
||||
return sprite_get_texture(sp)->alpha_mod;
|
||||
}
|
||||
|
||||
void sprite_set_blend_rate(struct sact_sprite *sp, int rate)
|
||||
{
|
||||
sprite_get_texture(sp)->alpha_mod = max(0, min(255, rate));
|
||||
sprite_dirty(sp);
|
||||
}
|
||||
|
||||
void sprite_set_show(struct sact_sprite *sp, bool show)
|
||||
{
|
||||
if (show == sp->show)
|
||||
return;
|
||||
sp->show = show;
|
||||
sprite_dirty(sp);
|
||||
if (show)
|
||||
sprite_register(sp);
|
||||
else
|
||||
sprite_unregister(sp);
|
||||
}
|
||||
|
||||
int sprite_set_draw_method(struct sact_sprite *sp, int method)
|
||||
{
|
||||
if (method < 0 || method >= NR_DRAW_METHODS) {
|
||||
WARNING("unknown draw method: %d", method);
|
||||
return 0;
|
||||
}
|
||||
sprite_get_texture(sp)->draw_method = method;
|
||||
sprite_dirty(sp);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int sprite_get_draw_method(struct sact_sprite *sp)
|
||||
{
|
||||
return sprite_get_texture(sp)->draw_method;
|
||||
}
|
||||
|
||||
int sprite_exists_alpha(struct sact_sprite *sp)
|
||||
{
|
||||
return sp->texture.has_alpha;
|
||||
}
|
||||
|
||||
void sprite_set_text_home(struct sact_sprite *sp, int x, int y)
|
||||
{
|
||||
sp->text.home = (Point) { .x = x, .y = y };
|
||||
sprite_dirty(sp);
|
||||
}
|
||||
|
||||
void sprite_set_text_line_space(struct sact_sprite *sp, int px)
|
||||
{
|
||||
sp->text.line_space = px;
|
||||
sprite_dirty(sp);
|
||||
}
|
||||
|
||||
void sprite_set_text_char_space(struct sact_sprite *sp, int px)
|
||||
{
|
||||
sp->text.char_space = px;
|
||||
sprite_dirty(sp);
|
||||
}
|
||||
|
||||
void sprite_set_text_pos(struct sact_sprite *sp, int x, int y)
|
||||
{
|
||||
sp->text.pos = (Point) { .x = x, .y = y };
|
||||
sprite_dirty(sp);
|
||||
}
|
||||
|
||||
void sprite_text_draw(struct sact_sprite *sp, struct string *text, struct text_metrics *tm)
|
||||
{
|
||||
if (!sp->text.texture.handle) {
|
||||
SDL_Color c;
|
||||
if (tm->outline_left || tm->outline_right || tm->outline_up || tm->outline_down)
|
||||
c = tm->outline_color;
|
||||
else
|
||||
c = tm->color;
|
||||
c.a = 0;
|
||||
gfx_init_texture_with_color(&sp->text.texture, sp->rect.w, sp->rect.h, c);
|
||||
}
|
||||
|
||||
sp->text.pos.x += gfx_render_text(&sp->text.texture, sp->text.pos, text->text, tm, sp->text.char_space);
|
||||
sprite_dirty(sp);
|
||||
}
|
||||
|
||||
void sprite_text_clear(struct sact_sprite *sp)
|
||||
{
|
||||
gfx_delete_texture(&sp->text.texture);
|
||||
sprite_dirty(sp);
|
||||
}
|
||||
|
||||
void sprite_text_home(struct sact_sprite *sp, possibly_unused int size)
|
||||
{
|
||||
// FIXME: do something with nTextSize
|
||||
sp->text.pos = sp->text.home;
|
||||
sprite_dirty(sp);
|
||||
}
|
||||
|
||||
void sprite_text_new_line(struct sact_sprite *sp, int size)
|
||||
{
|
||||
sp->text.pos = POINT(sp->text.home.x, sp->text.pos.y + size + sp->text.line_space);
|
||||
sprite_dirty(sp);
|
||||
}
|
||||
|
||||
void sprite_text_copy(struct sact_sprite *dsp, struct sact_sprite *ssp)
|
||||
{
|
||||
sprite_text_clear(dsp);
|
||||
if (ssp->text.texture.handle) {
|
||||
SDL_Color c = { 0, 0, 0, 0 };
|
||||
gfx_init_texture_with_color(&dsp->text.texture, dsp->rect.w, dsp->rect.h, c);
|
||||
gfx_copy(&dsp->text.texture, 0, 0, &ssp->text.texture, 0, 0, ssp->text.texture.w, ssp->text.texture.h);
|
||||
gfx_copy_amap(&dsp->text.texture, 0, 0, &ssp->text.texture, 0, 0, ssp->text.texture.w, ssp->text.texture.h);
|
||||
}
|
||||
dsp->text.home = ssp->text.home;
|
||||
dsp->text.pos = ssp->text.pos;
|
||||
dsp->text.char_space = ssp->text.char_space;
|
||||
dsp->text.line_space = ssp->text.line_space;
|
||||
sprite_dirty(dsp);
|
||||
}
|
||||
|
||||
bool sprite_is_point_in_rect(struct sact_sprite *sp, int x, int y)
|
||||
{
|
||||
Point p = POINT(x, y);
|
||||
return !!SDL_PointInRect(&p, &sp->rect);
|
||||
}
|
||||
|
||||
bool sprite_is_point_in(struct sact_sprite *sp, int x, int y)
|
||||
{
|
||||
if (!sprite_is_point_in_rect(sp, x, y))
|
||||
return 0;
|
||||
|
||||
// check alpha
|
||||
struct texture *t = sprite_get_texture(sp);
|
||||
SDL_Color c = gfx_get_pixel(t, x - sp->rect.x, y - sp->rect.y);
|
||||
return !!c.a;
|
||||
}
|
||||
|
||||
int sprite_get_amap_value(struct sact_sprite *sp, int x, int y)
|
||||
{
|
||||
return gfx_get_pixel(sprite_get_texture(sp), x, y).a;
|
||||
}
|
||||
|
||||
void sprite_get_pixel_value(struct sact_sprite *sp, int x, int y, int *r, int *g, int *b)
|
||||
{
|
||||
SDL_Color c = gfx_get_pixel(sprite_get_texture(sp), x, y);
|
||||
*r = c.r;
|
||||
*g = c.g;
|
||||
*b = c.b;
|
||||
}
|
||||
+1
-1
Submodule subprojects/libsys4 updated: 9c1b705830...db29ca8714
Reference in New Issue
Block a user