Implement StoatSpriteEngine.CharSprite functions

With the exception of the Rebuild, Save and Load functions.

Used in 僕だけの保健室
This commit is contained in:
Nunuhara Cabbage
2021-05-06 20:58:10 -07:00
parent 058eee03e5
commit 28ca3d01e2
5 changed files with 299 additions and 13 deletions
+242
View File
@@ -0,0 +1,242 @@
/* 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 <assert.h>
#include "system4.h"
#include "system4/string.h"
#include "system4/utfsjis.h"
#include "vm/heap.h"
#include "vm/page.h"
#include "sprite.h"
#include "CharSpriteManager.h"
/*
* NOTE: This is not a library on it's own, but rather part of
* StoatSpriteEngine/ChipmunkSpriteEngine.
*/
struct charsprite {
struct sact_sprite sp;
// NOTE: even though we only render a single character, we need to store an
// arbitrary string because CharSprite_GetChar returns it.
struct string *ch;
struct text_metrics tm;
};
static struct {
unsigned size;
struct charsprite **sprites;
unsigned nr_free;
int *free;
} chars = {0};
static void grow_chars(unsigned new_size) {
assert(new_size > chars.size);
chars.sprites = xrealloc_array(chars.sprites, chars.size, new_size, sizeof(struct charsprite*));
chars.free = xrealloc_array(chars.free, chars.size, new_size, sizeof(int));
for (unsigned i = chars.size; i < new_size; i++) {
chars.free[chars.nr_free++] = i;
}
chars.size = new_size;
}
static int get_handle(void)
{
if (!chars.nr_free) {
grow_chars(chars.size ? chars.size*2 : 256);
}
return chars.free[--chars.nr_free];
}
static bool handle_valid(int handle)
{
return handle >= 0 && (unsigned)handle < chars.size && chars.sprites[handle];
}
static void check_handle(int handle)
{
if (!handle_valid(handle))
VM_ERROR("Invalid CharSprite handle: %d", handle);
}
static struct charsprite *charsprite_get(int handle)
{
check_handle(handle);
return chars.sprites[handle];
}
static bool charsprite_allocated(struct charsprite *cs)
{
return cs->ch != NULL;
}
int CharSpriteManager_CreateHandle(void)
{
int handle = get_handle();
assert(!chars.sprites[handle]);
chars.sprites[handle] = xcalloc(1, sizeof(struct charsprite));
return handle;
}
bool CharSpriteManager_ReleaseHandle(int handle)
{
if (!handle_valid(handle))
return false;
sprite_free(&chars.sprites[handle]->sp);
if (chars.sprites[handle]->ch) {
free_string(chars.sprites[handle]->ch);
}
free(chars.sprites[handle]);
chars.sprites[handle] = NULL;
chars.free[chars.nr_free++] = handle;
return true;
}
void CharSpriteManager_Clear(void)
{
for (unsigned i = 0; i < chars.size; i++) {
CharSpriteManager_ReleaseHandle(i);
}
}
//static void CharSpriteManager_Rebuild(void);
//static bool CharSpriteManager_Save(struct page **iarray);
//static bool CharSpriteManager_Load(struct page **iarray);
void CharSprite_Release(int handle)
{
struct charsprite *sp = charsprite_get(handle);
sprite_free(&sp->sp);
}
static void CASColor_to_SDL_Color(SDL_Color *color, int page_no)
{
struct page *page = heap_get_page(page_no);
assert(page);
assert(page->nr_vars == 4);
color->r = page->values[0].i;
color->g = page->values[1].i;
color->b = page->values[2].i;
color->a = page->values[3].i;
}
static void CASCharSpriteProperty_to_text_metrics(struct text_metrics *tm, struct page *page)
{
assert(page);
assert(page->nr_vars == 6);
tm->face = page->values[0].i;
tm->size = page->values[1].i;
CASColor_to_SDL_Color(&tm->color, page->values[2].i);
//tm->weight = page->values[3].f;
tm->weight = FW_NORMAL;
tm->outline_left = page->values[4].f;
tm->outline_up = tm->outline_left;
tm->outline_right = tm->outline_left;
tm->outline_down = tm->outline_left;
CASColor_to_SDL_Color(&tm->outline_color, page->values[5].i);
}
static int extract_sjis_char(char *src, char *dst)
{
if (SJIS_2BYTE(*src)) {
dst[0] = src[0];
dst[1] = src[1];
dst[2] = '\0';
return 2;
}
dst[0] = src[0];
dst[1] = '\0';
return 1;
}
void CharSprite_SetChar(int handle, struct string **s, struct page **property)
{
struct charsprite *sp = charsprite_get(handle);
CASCharSpriteProperty_to_text_metrics(&sp->tm, *property);
if (charsprite_allocated(sp)) {
sprite_free(&sp->sp);
}
if (sp->ch) {
free_string(sp->ch);
sp->ch = NULL;
}
if (!(*s)->size) {
return;
}
sp->ch = string_ref(*s);
char ch[3];
extract_sjis_char((*s)->text, ch);
int w = sp->tm.size;
int h = sp->tm.size;
if (isascii(ch[0]))
w /= 2;
sprite_init(&sp->sp, w, h, 0, 0, 0, 0);
sprite_get_texture(&sp->sp); // XXX: force initialization of texture
gfx_render_text(&sp->sp.texture, (Point) { .x=0, .y = 0 }, ch, &sp->tm, 0);
sprite_dirty(&sp->sp);
}
void CharSprite_SetPos(int handle, int x, int y)
{
struct charsprite *sp = charsprite_get(handle);
sprite_set_pos(&sp->sp, x, y);
}
void CharSprite_SetZ(int handle, int z)
{
struct charsprite *sp = charsprite_get(handle);
sprite_set_z(&sp->sp, z);
}
void CharSprite_SetAlphaRate(int handle, int rate)
{
struct charsprite *sp = charsprite_get(handle);
sprite_set_blend_rate(&sp->sp, rate);
}
void CharSprite_SetShow(int handle, bool show)
{
struct charsprite *sp = charsprite_get(handle);
sprite_set_show(&sp->sp, show);
}
void CharSprite_GetChar(int handle, struct string **ch)
{
struct charsprite *sp = charsprite_get(handle);
if (*ch)
free_string(*ch);
if (sp->ch)
*ch = string_ref(sp->ch);
else
*ch = string_ref(&EMPTY_STRING);
}
int CharSprite_GetAlphaRate(int handle)
{
struct charsprite *sp = charsprite_get(handle);
return sprite_get_blend_rate(&sp->sp);
}
+40
View File
@@ -0,0 +1,40 @@
/* 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_HLL_CHARSPRITE_MANAGER_H
#define SYSTEM4_HLL_CHARSPRITE_MANAGER_H
#include <stdbool.h>
struct page;
struct string;
int CharSpriteManager_CreateHandle(void);
bool CharSpriteManager_ReleaseHandle(int handle);
void CharSpriteManager_Clear(void);
void CharSpriteManager_Rebuild(void);
bool CharSpriteManager_Save(struct page **iarray);
bool CharSpriteManager_Load(struct page **iarray);
void CharSprite_Release(int nHandle);
void CharSprite_SetChar(int handle, struct string **s, struct page **property);
void CharSprite_SetPos(int handle, int x, int y);
void CharSprite_SetZ(int handle, int z);
void CharSprite_SetAlphaRate(int handle, int rate);
void CharSprite_SetShow(int handle, bool show);
void CharSprite_GetChar(int handle, struct string **ch);
int CharSprite_GetAlphaRate(int handle);
#endif /* SYSTEM4_HLL_CHARSPRITE_MANAGER_H */
+15 -13
View File
@@ -35,6 +35,7 @@
#include "xsystem4.h"
#include "sact.h"
#include "AnteaterADVEngine.h"
#include "CharSpriteManager.h"
HLL_WARN_UNIMPLEMENTED( , void, StoatSpriteEngine, JoypadQuake_Set, int num, int type, int magnitude);
HLL_WARN_UNIMPLEMENTED(1, int, StoatSpriteEngine, Music_SetLoopCount, int ch, int count);
@@ -553,19 +554,6 @@ HLL_WARN_UNIMPLEMENTED(0, bool, StoatSpriteEngine, SYSTEM_GetInvalidateFrameSkip
//void StoatSpriteEngine_ADVSceneKeeper_Clear(void);
//bool StoatSpriteEngine_ADVSceneKeeper_Save(ref array@int pIVMArray);
//bool StoatSpriteEngine_ADVSceneKeeper_Load(ref array@int pIVMArray);
//void StoatSpriteEngine_ADVLogList_Clear(void);
//void StoatSpriteEngine_ADVLogList_AddText(ref string pIText);
//void StoatSpriteEngine_ADVLogList_AddNewLine(void);
//void StoatSpriteEngine_ADVLogList_AddNewPage(void);
//void StoatSpriteEngine_ADVLogList_AddVoice(int nVoiceNumber);
//void StoatSpriteEngine_ADVLogList_SetEnable(bool bEnable);
//bool StoatSpriteEngine_ADVLogList_IsEnable(void);
//int StoatSpriteEngine_ADVLogList_GetNumofADVLog(void);
//int StoatSpriteEngine_ADVLogList_GetNumofADVLogText(int nADVLog);
//void StoatSpriteEngine_ADVLogList_GetADVLogText(int nADVLog, int nText, ref string pIText);
//int StoatSpriteEngine_ADVLogList_GetADVLogVoice(int nADVLog);
//bool StoatSpriteEngine_ADVLogList_Save(ref array@int pIVMArray);
//bool StoatSpriteEngine_ADVLogList_Load(ref array@int pIVMArray);
HLL_LIBRARY(StoatSpriteEngine,
HLL_EXPORT(_ModuleFini, StoatSpriteEngine_ModuleFini),
@@ -765,6 +753,20 @@ HLL_LIBRARY(StoatSpriteEngine,
HLL_EXPORT(MultiSprite_Rebuild, StoatSpriteEngine_MultiSprite_Rebuild),
HLL_EXPORT(MultiSprite_Encode, StoatSpriteEngine_MultiSprite_Encode),
HLL_EXPORT(MultiSprite_Decode, StoatSpriteEngine_MultiSprite_Decode),
HLL_EXPORT(CharSpriteManager_CreateHandle, CharSpriteManager_CreateHandle),
HLL_EXPORT(CharSpriteManager_ReleaseHandle, CharSpriteManager_ReleaseHandle),
HLL_EXPORT(CharSpriteManager_Clear, CharSpriteManager_Clear),
HLL_TODO_EXPORT(CharSpriteManager_Rebuild, CharSpriteManager_Rebuild),
HLL_TODO_EXPORT(CharSpriteManager_Save, CharSpriteManager_Save),
HLL_TODO_EXPORT(CharSpriteManager_Load, CharSpriteManager_Load),
HLL_EXPORT(CharSprite_Release, CharSprite_Release),
HLL_EXPORT(CharSprite_SetChar, CharSprite_SetChar),
HLL_EXPORT(CharSprite_SetPos, CharSprite_SetPos),
HLL_EXPORT(CharSprite_SetZ, CharSprite_SetZ),
HLL_EXPORT(CharSprite_SetAlphaRate, CharSprite_SetAlphaRate),
HLL_EXPORT(CharSprite_SetShow, CharSprite_SetShow),
HLL_EXPORT(CharSprite_GetChar, CharSprite_GetChar),
HLL_EXPORT(CharSprite_GetAlphaRate, CharSprite_GetAlphaRate),
HLL_EXPORT(SYSTEM_IsResetOnce, StoatSpriteEngine_SYSTEM_IsResetOnce),
HLL_EXPORT(SYSTEM_SetConfigOverFrameRateSleep, StoatSpriteEngine_SYSTEM_SetConfigOverFrameRateSleep),
HLL_EXPORT(SYSTEM_GetConfigOverFrameRateSleep, StoatSpriteEngine_SYSTEM_GetConfigOverFrameRateSleep),
+1
View File
@@ -26,6 +26,7 @@ xsystem4 = ['audio.c',
'hll/AnteaterADVEngine.c',
'hll/BanMisc.c',
'hll/Bitarray.c',
'hll/CharSpriteManager.c',
'hll/Confirm.c',
'hll/Confirm2.c',
'hll/CrayfishLogViewer.c',
+1
View File
@@ -69,6 +69,7 @@ void sprite_free(struct sact_sprite *sp)
sprite_unregister(sp);
gfx_delete_texture(&sp->texture);
gfx_delete_texture(&sp->text.texture);
memset(sp, 0, sizeof(struct sact_sprite));
}
void sprite_render_scene(void)