Merge pull request #157 from kichikuou/mamanyonyo

Mamanyonyo support
This commit is contained in:
Nunuhara Cabbage
2024-06-02 14:46:45 -07:00
committed by GitHub
35 changed files with 4546 additions and 100 deletions
+25
View File
@@ -149,6 +149,8 @@ target_sources(xsystem4 PRIVATE
src/hll/LoadCG.c
src/hll/MainEXFile.c
src/hll/MainSurface.c
src/hll/MamanyoDemo.c
src/hll/MamanyoSDemo.c
src/hll/MarmotModelEngine.c
src/hll/Math.c
src/hll/MapLoader.c
@@ -173,6 +175,29 @@ target_sources(xsystem4 PRIVATE
src/hll/SystemServiceEx.c
src/hll/Timer.c
src/hll/Toushin3Loader.c
src/hll/vmAnime.c
src/hll/vmArray.c
src/hll/vmCG.c
src/hll/vmChrLoader.c
src/hll/vmCursor.c
src/hll/vmDialog.c
src/hll/vmDrawGauge.c
src/hll/vmDrawMsg.c
src/hll/vmDrawNumber.c
src/hll/vmFile.c
src/hll/vmGraph.c
src/hll/vmGraphQuake.c
src/hll/vmKey.c
src/hll/vmMapLoader.c
src/hll/vmMsgLog.c
src/hll/vmMsgSkip.c
src/hll/vmMusic.c
src/hll/vmSound.c
src/hll/vmSprite.c
src/hll/vmString.c
src/hll/vmSurface.c
src/hll/vmSystem.c
src/hll/vmTimer.c
src/hll/VSFile.c
)
+1 -1
View File
@@ -15,7 +15,7 @@ issues, please let me know or open a pull request to update this table.
| Game | Status | Notes |
| ------------------------------------------------------- | ----------- | ----- |
| DALK外伝 | Unsupported | |
| ままにょにょ | Unsupported | |
| ままにょにょ | Supported | |
| 大番長 -Big Bang Age- | Supported | |
| Daibanchou -Big Bang Age- (EN) | Supported | |
| 魔女の贖罪 | Unknown | |
+10 -2
View File
@@ -17,14 +17,22 @@
#ifndef SYSTEM4_ID_POOL_H
#define SYSTEM4_ID_POOL_H
// A reasonable base value for pointer-based handles.
#define ID_POOL_HANDLE_BASE 0x100000
struct id_pool {
void **slots;
int nr_slots;
int base;
};
void id_pool_init(struct id_pool *pool);
void id_pool_release(struct id_pool *pool, int id);
void id_pool_init(struct id_pool *pool, int base);
void id_pool_delete(struct id_pool *pool);
void *id_pool_release(struct id_pool *pool, int id);
int id_pool_count(struct id_pool *pool);
int id_pool_get_unused(struct id_pool *pool);
int id_pool_get_first(struct id_pool *pool);
int id_pool_get_next(struct id_pool *pool, int id);
void *id_pool_get(struct id_pool *pool, int id);
void *id_pool_set(struct id_pool *pool, int id, void *data);
+5 -6
View File
@@ -43,8 +43,8 @@ void audio_init(void)
if (audio_initialized)
return;
id_pool_init(&wav);
id_pool_init(&bgm);
id_pool_init(&wav, 0);
id_pool_init(&bgm, 0);
for (int i = 0; i < NR_ANONYMOUS_CHANNELS; i++) {
anonymous_channels[i] = -1;
@@ -56,10 +56,10 @@ void audio_init(void)
void audio_reset(void)
{
for (int i = 0; i < wav.nr_slots; i++) {
for (int i = id_pool_get_first(&wav); i >= 0; i = id_pool_get_next(&wav, i)) {
wav_unprepare(i);
}
for (int i = 0; i < bgm.nr_slots; i++) {
for (int i = id_pool_get_first(&bgm); i >= 0; i = id_pool_get_next(&bgm, i)) {
bgm_unprepare(i);
}
for (int i = 0; i < NR_ANONYMOUS_CHANNELS; i++) {
@@ -136,11 +136,10 @@ int bgm_prepare(int id, int no) { return audio_prepare(&bgm, id, ASSET_BGM, no);
static int audio_unprepare(struct id_pool *pool, int id)
{
struct channel *ch = id_pool_get(pool, id);
struct channel *ch = id_pool_release(pool, id);
if (!ch)
return 0;
channel_close(ch);
id_pool_release(pool, id);
return 1;
}
+50
View File
@@ -343,6 +343,8 @@ extern struct static_library lib_KiwiSoundEngine;
extern struct static_library lib_LoadCG;
extern struct static_library lib_MainEXFile;
extern struct static_library lib_MainSurface;
extern struct static_library lib_MamanyoDemo;
extern struct static_library lib_MamanyoSDemo;
extern struct static_library lib_MarmotModelEngine;
extern struct static_library lib_Math;
extern struct static_library lib_MapLoader;
@@ -369,6 +371,29 @@ extern struct static_library lib_SystemServiceEx;
extern struct static_library lib_TapirEngine;
extern struct static_library lib_Timer;
extern struct static_library lib_Toushin3Loader;
extern struct static_library lib_vmAnime;
extern struct static_library lib_vmArray;
extern struct static_library lib_vmCG;
extern struct static_library lib_vmChrLoader;
extern struct static_library lib_vmCursor;
extern struct static_library lib_vmDialog;
extern struct static_library lib_vmDrawGauge;
extern struct static_library lib_vmDrawMsg;
extern struct static_library lib_vmDrawNumber;
extern struct static_library lib_vmFile;
extern struct static_library lib_vmGraph;
extern struct static_library lib_vmGraphQuake;
extern struct static_library lib_vmKey;
extern struct static_library lib_vmMapLoader;
extern struct static_library lib_vmMsgLog;
extern struct static_library lib_vmMsgSkip;
extern struct static_library lib_vmMusic;
extern struct static_library lib_vmSound;
extern struct static_library lib_vmSprite;
extern struct static_library lib_vmString;
extern struct static_library lib_vmSurface;
extern struct static_library lib_vmSystem;
extern struct static_library lib_vmTimer;
extern struct static_library lib_VSFile;
static struct static_library *static_libraries[] = {
@@ -414,6 +439,8 @@ static struct static_library *static_libraries[] = {
&lib_LoadCG,
&lib_MainEXFile,
&lib_MainSurface,
&lib_MamanyoDemo,
&lib_MamanyoSDemo,
&lib_MarmotModelEngine,
&lib_Math,
&lib_MapLoader,
@@ -440,6 +467,29 @@ static struct static_library *static_libraries[] = {
&lib_TapirEngine,
&lib_Timer,
&lib_Toushin3Loader,
&lib_vmAnime,
&lib_vmArray,
&lib_vmCG,
&lib_vmChrLoader,
&lib_vmCursor,
&lib_vmDialog,
&lib_vmDrawGauge,
&lib_vmDrawMsg,
&lib_vmDrawNumber,
&lib_vmFile,
&lib_vmGraph,
&lib_vmGraphQuake,
&lib_vmKey,
&lib_vmMapLoader,
&lib_vmMsgLog,
&lib_vmMsgSkip,
&lib_vmMusic,
&lib_vmSound,
&lib_vmSprite,
&lib_vmString,
&lib_vmSurface,
&lib_vmSystem,
&lib_vmTimer,
&lib_VSFile,
NULL
};
+167 -85
View File
@@ -28,10 +28,10 @@
#include "system4/little_endian.h"
#include "audio.h"
#include "hll.h"
#include "sact.h"
#include "xsystem4.h"
#include "hll.h"
#include "ChrLoader.h"
/*
* struct ChrHeader {
@@ -50,7 +50,8 @@
* };
*
* struct MineInfo {
* uint32_t unknown[6];
* uint32_t id;
* uint32_t unknown[5];
* uint32_t status[24];
* char name[32];
* };
@@ -64,12 +65,14 @@
* };
*
* struct EnmyInfo {
* uint32_t unknown[5];
* uint32_t id;
* uint32_t unknown[4];
* uint32_t status[17];
* char name[32];
* };
*/
static char *chr_directory;
static struct hash_table *chr_table; // Caches decrypted .chr file data
static bool is_enemy(uint8_t *data)
@@ -84,7 +87,7 @@ static uint8_t *chr_get(int id)
return slot->value;
char buf[32];
sprintf(buf, "CHR/%d.chr", id);
snprintf(buf, sizeof(buf), "%s/%d.chr", chr_directory, id);
char *path = gamedir_path(buf);
size_t size;
uint8_t *data = file_read(path, &size);
@@ -102,106 +105,51 @@ static uint8_t *chr_get(int id)
return data;
}
static bool ChrLoader_Init(void)
void chr_loader_init(const char *dir)
{
chr_directory = strdup(dir);
chr_table = ht_create(512);
return true;
}
static bool ChrLoader_LoadCG(int sprite, int x, int y, int id, int type)
bool chr_loader_exists(int id)
{
return chr_get(id) != NULL;
}
struct string *chr_loader_get_name(int id)
{
uint8_t *data = chr_get(id);
if (!data)
return false;
return NULL;
struct sact_sprite *sp = sact_get_sprite(sprite);
if (!sp)
return false;
int index = -1;
switch (type) {
case 0: // Unit
index = is_enemy(data) ? 0 : 1;
break;
case 1: // Attack
index = is_enemy(data) ? 1 : 2;
break;
case 2: // Damage
index = is_enemy(data) ? 2 : 3;
break;
case 3: // Face
index = is_enemy(data) ? -1 : 0;
break;
}
if (index < 0)
return false;
size_t offset = LittleEndian_getDW(data, 12 + index * 4);
size_t size = LittleEndian_getDW(data, (is_enemy(data) ? 24 : 28) + index * 4);
struct cg *cg = cg_load_buffer(data + offset, size);
if (!cg)
return false;
sprite_set_cg(sp, cg);
cg_free(cg);
return true;
uint32_t offset = LittleEndian_getDW(data, 8);
offset += is_enemy(data) ? 88 : 120;
return cstr_to_string((char *)data + offset);
}
static void chr_archive_free_data(struct archive_data *data) { /* no-op */ }
static struct archive_ops chr_archive_ops = {
.free_data = chr_archive_free_data
};
static struct archive chr_archive = { .mmapped = false, .ops = &chr_archive_ops };
static bool ChrLoader_LoadWavFile(int sound_channel, int id)
struct string *chr_loader_get_string(int id, int index)
{
uint8_t *data = chr_get(id);
if (!data)
return false;
if (!data || is_enemy(data) || (unsigned)index >= 48)
return NULL;
size_t offset = LittleEndian_getDW(data, is_enemy(data) ? 36 : 44);
size_t size = LittleEndian_getDW(data, is_enemy(data) ? 40 : 48);
struct archive_data *dfile = xcalloc(1, sizeof(struct archive_data));
dfile->size = size;
dfile->data = data + offset;
dfile->no = id;
dfile->archive = &chr_archive;
if (!wav_prepare_from_archive_data(sound_channel, dfile)) {
WARNING("ChrLoader.LoadWavFile %d failed", id);
return false;
}
return true;
}
static bool ChrLoader_LoadSentence(int id, int type, struct string **msg)
{
uint8_t *data = chr_get(id);
if (!data || is_enemy(data) || (unsigned)type >= 48)
return false;
uint32_t offset = LittleEndian_getDW(data, 52 + type * 4);
uint32_t offset = LittleEndian_getDW(data, 52 + index * 4);
if (!offset)
return false;
*msg = cstr_to_string((char *)data + offset);
return true;
return NULL;
return cstr_to_string((char *)data + offset);
}
static bool ChrLoader_GetName(int id, struct string **name)
int chr_loader_get_id(int id)
{
uint8_t *data = chr_get(id);
if (!data)
return false;
uint32_t offset = LittleEndian_getDW(data, 8);
offset += is_enemy(data) ? 88 : 120;
*name = cstr_to_string((char *)data + offset);
return true;
return LittleEndian_getDW(data, offset);
}
static int ChrLoader_GetStatus(int id, int type)
int chr_loader_get_status(int id, int type)
{
uint8_t *data = chr_get(id);
if (!data)
@@ -226,9 +174,143 @@ static int ChrLoader_GetStatus(int id, int type)
return LittleEndian_getDW(data, offset);
}
static bool ChrLoader_IsExist(int id)
int chr_loader_get_blob_handle(int id, int index)
{
return chr_get(id) != NULL;
if (!chr_get(id) || index < 0 || index > 4)
return 0;
return (id << 3) + index + 1;
}
void *chr_loader_get_blob(int blob_handle, size_t *size)
{
if (!blob_handle)
return NULL;
int id = blob_handle >> 3;
int index = (blob_handle & 7) - 1;
uint8_t *data = chr_get(id);
if (!data || index < 0 || index > 4)
return NULL;
size_t ofs_ofs;
size_t size_ofs;
if (is_enemy(data)) {
if (index == 4) {
ofs_ofs = 36;
size_ofs = 40;
} else {
ofs_ofs = 12 + index * 4;
size_ofs = 24 + index * 4;
}
} else {
if (index == 4) {
ofs_ofs = 44;
size_ofs = 48;
} else {
ofs_ofs = 12 + index * 4;
size_ofs = 28 + index * 4;
}
}
size_t offset = LittleEndian_getDW(data, ofs_ofs);
*size = LittleEndian_getDW(data, size_ofs);
return data + offset;
}
static void chr_archive_free_data(struct archive_data *data) { /* no-op */ }
static struct archive_ops chr_archive_ops = {
.free_data = chr_archive_free_data
};
static struct archive chr_archive = { .mmapped = false, .ops = &chr_archive_ops };
struct archive_data *chr_loader_get_blob_as_archive_data(int blob_handle)
{
size_t size;
uint8_t *data = chr_loader_get_blob(blob_handle, &size);
if (!data)
return NULL;
struct archive_data *dfile = xcalloc(1, sizeof(struct archive_data));
dfile->size = size;
dfile->data = data;
dfile->archive = &chr_archive;
return dfile;
}
static bool ChrLoader_Init(void)
{
chr_loader_init("CHR");
return true;
}
static bool ChrLoader_LoadCG(int sprite, int x, int y, int id, int type)
{
struct sact_sprite *sp = sact_get_sprite(sprite);
if (!sp)
return false;
uint8_t *data = chr_get(id);
if (!data)
return false;
int index = -1;
switch (type) {
case 0: // Unit
index = is_enemy(data) ? 0 : 1;
break;
case 1: // Attack
index = is_enemy(data) ? 1 : 2;
break;
case 2: // Damage
index = is_enemy(data) ? 2 : 3;
break;
case 3: // Face
index = is_enemy(data) ? -1 : 0;
break;
}
if (index < 0)
return false;
size_t size;
uint8_t *blob = chr_loader_get_blob(chr_loader_get_blob_handle(id, index), &size);
if (!blob)
return false;
struct cg *cg = cg_load_buffer(blob, size);
if (!cg)
return false;
sprite_set_cg(sp, cg);
cg_free(cg);
return true;
}
static bool ChrLoader_LoadWavFile(int sound_channel, int id)
{
int blob = chr_loader_get_blob_handle(id, 4);
struct archive_data *dfile = chr_loader_get_blob_as_archive_data(blob);
if (!dfile || !wav_prepare_from_archive_data(sound_channel, dfile)) {
WARNING("ChrLoader.LoadWavFile %d failed", id);
return false;
}
return true;
}
static bool ChrLoader_LoadSentence(int id, int type, struct string **msg)
{
struct string *s = chr_loader_get_string(id, type);
if (!s)
return false;
*msg = s;
return true;
}
static bool ChrLoader_GetName(int id, struct string **name)
{
struct string *s = chr_loader_get_name(id);
if (!s)
return false;
*name = s;
return true;
}
HLL_LIBRARY(ChrLoader,
@@ -237,6 +319,6 @@ HLL_LIBRARY(ChrLoader,
HLL_EXPORT(LoadWavFile, ChrLoader_LoadWavFile),
HLL_EXPORT(LoadSentence, ChrLoader_LoadSentence),
HLL_EXPORT(GetName, ChrLoader_GetName),
HLL_EXPORT(GetStatus, ChrLoader_GetStatus),
HLL_EXPORT(IsExist, ChrLoader_IsExist)
HLL_EXPORT(GetStatus, chr_loader_get_status),
HLL_EXPORT(IsExist, chr_loader_exists)
);
+35
View File
@@ -0,0 +1,35 @@
/* Copyright (C) 2024 kichikuou <KichikuouChrome@gmail.com>
*
* 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_CHRLOADER_H
#define SYSTEM4_HLL_CHRLOADER_H
#include <stddef.h>
struct archive_data;
struct string;
void chr_loader_init(const char *dir);
bool chr_loader_exists(int id);
struct string *chr_loader_get_name(int id);
struct string *chr_loader_get_string(int id, int index);
int chr_loader_get_id(int id);
int chr_loader_get_status(int id, int type);
int chr_loader_get_blob_handle(int id, int index);
void *chr_loader_get_blob(int blob_handle, size_t *size);
struct archive_data *chr_loader_get_blob_as_archive_data(int blob_handle);
#endif /* SYSTEM4_HLL_CHRLOADER_H */
+25
View File
@@ -0,0 +1,25 @@
/* Copyright (C) 2024 kichikuou <KichikuouChrome@gmail.com>
*
* 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 "hll.h"
HLL_WARN_UNIMPLEMENTED(1, int, MamanyoDemo, Init, void *imainsystem);
HLL_WARN_UNIMPLEMENTED(0, int, MamanyoDemo, Run, void);
HLL_LIBRARY(MamanyoDemo,
HLL_EXPORT(Init, MamanyoDemo_Init),
HLL_EXPORT(Run, MamanyoDemo_Run)
);
+27
View File
@@ -0,0 +1,27 @@
/* Copyright (C) 2024 kichikuou <KichikuouChrome@gmail.com>
*
* 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 "hll.h"
HLL_WARN_UNIMPLEMENTED(0, int, MamanyoSDemo, Init, void *imainsystem);
//int MamanyoSDemo_Run(void);
//int MamanyoSDemo_AddChara(int nNum);
HLL_LIBRARY(MamanyoSDemo,
HLL_EXPORT(Init, MamanyoSDemo_Init),
HLL_TODO_EXPORT(Run, MamanyoSDemo_Run),
HLL_TODO_EXPORT(AddChara, MamanyoSDemo_AddChara)
);
+151
View File
@@ -0,0 +1,151 @@
/* Copyright (C) 2024 kichikuou <KichikuouChrome@gmail.com>
*
* 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 <SDL.h>
#include "system4/cg.h"
#include "asset_manager.h"
#include "audio.h"
#include "gfx/gfx.h"
#include "hll.h"
#include "id_pool.h"
struct vm_anime {
int cg;
int length;
int type;
int interval;
Point pos;
int wave_channel;
};
static struct id_pool pool;
static void vmAnime_New(possibly_unused void *imainsystem)
{
if (pool.slots)
return; // already initialized
id_pool_init(&pool, ID_POOL_HANDLE_BASE);
}
static int vmAnime_EnumHandle(void)
{
return id_pool_count(&pool);
}
static int vmAnime_Open(int cg, int length, int type)
{
int no = id_pool_get_unused(&pool);
struct vm_anime *anime = xcalloc(1, sizeof(struct vm_anime));
id_pool_set(&pool, no, anime);
anime->cg = cg;
anime->length = length;
anime->type = type;
return no;
}
static void vmAnime_Close(int handle)
{
struct vm_anime *anime = id_pool_release(&pool, handle);
if (anime)
free(anime);
}
static int vmAnime_Release(void)
{
for (int i = id_pool_get_first(&pool); i >= 0; i = id_pool_get_next(&pool, i))
vmAnime_Close(i);
id_pool_delete(&pool);
return 1;
}
static void vmAnime_ModuleFini(void)
{
vmAnime_Release();
}
static void vmAnime_SetInterval(int handle, int interval)
{
struct vm_anime *anime = id_pool_get(&pool, handle);
if (!anime)
return;
anime->interval = interval;
}
static void vmAnime_SetPos(int handle, int x, int y)
{
struct vm_anime *anime = id_pool_get(&pool, handle);
if (!anime)
return;
anime->pos.x = x;
anime->pos.y = y;
}
static void vmAnime_SetWave(int handle, int channel)
{
struct vm_anime *anime = id_pool_get(&pool, handle);
if (!anime)
return;
anime->wave_channel = channel;
}
static void vmAnime_Draw(int handle, int return_)
{
struct vm_anime *anime = id_pool_get(&pool, handle);
if (!anime)
return;
if (anime->wave_channel) {
wav_stop(anime->wave_channel);
wav_play(anime->wave_channel);
}
Texture old;
gfx_copy_main_surface(&old);
Texture *dst = gfx_main_surface();
uint64_t start_time = SDL_GetTicks64();
for (int i = 0; i < anime->length; i++) {
struct cg *cg = asset_cg_load(anime->cg + i);
Texture src;
gfx_init_texture_with_cg(&src, cg);
gfx_copy(dst, 0, 0, &old, 0, 0, old.w, old.h);
gfx_blend_add_satur(dst, anime->pos.x, anime->pos.y, &src, 0, 0, src.w, src.h);
gfx_delete_texture(&src);
cg_free(cg);
gfx_swap();
SDL_Delay(start_time + (i + 1) * anime->interval - SDL_GetTicks64());
}
if (return_) {
gfx_copy(dst, 0, 0, &old, 0, 0, old.w, old.h);
gfx_swap();
}
gfx_delete_texture(&old);
}
HLL_LIBRARY(vmAnime,
HLL_EXPORT(_ModuleFini, vmAnime_ModuleFini),
HLL_EXPORT(New, vmAnime_New),
HLL_EXPORT(Release, vmAnime_Release),
HLL_EXPORT(EnumHandle, vmAnime_EnumHandle),
HLL_EXPORT(Open, vmAnime_Open),
HLL_EXPORT(Close, vmAnime_Close),
HLL_EXPORT(SetInterval, vmAnime_SetInterval),
HLL_EXPORT(SetPos, vmAnime_SetPos),
HLL_EXPORT(SetWave, vmAnime_SetWave),
HLL_EXPORT(Draw, vmAnime_Draw)
);
+746
View File
@@ -0,0 +1,746 @@
/* Copyright (C) 2024 kichikuou <KichikuouChrome@gmail.com>
*
* 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 <stdint.h>
#include "hll.h"
#include "vm/page.h"
static void check_array(struct page *array)
{
if (array->type != ARRAY_PAGE || array->a_type != AIN_ARRAY_INT || array->array.rank != 1)
VM_ERROR("Not a flat integer array");
}
//int vmArray_GetAdd(struct page *array, int index);
//int vmArray_GetSub(struct page *array, int index);
//int vmArray_GetMul(struct page *array, int index);
//int vmArray_GetDiv(struct page *array, int index);
//int vmArray_GetAnd(struct page *array, int index);
//int vmArray_GetOr(struct page *array, int index);
//int vmArray_GetXor(struct page *array, int index);
static void transform(struct page *array, int index, int (*func)(int, void *), void *data)
{
if (!array)
return;
check_array(array);
if (index >= 0) {
for (int i = index; i < array->nr_vars; i++) {
array->values[i].i = func(array->values[i].i, data);
}
} else {
for (int i = -index - 1; i >= 0; --i) {
array->values[i].i = func(array->values[i].i, data);
}
}
}
static inline int32_t clamp(int64_t val)
{
if (val > INT32_MAX)
return INT32_MAX;
if (val < INT32_MIN)
return INT32_MIN;
return val;
}
static int trans_add(int x, void *data)
{
int64_t y = *(int*)data;
return clamp(x + y);
}
static int trans_sub(int x, void *data)
{
int64_t y = *(int*)data;
return clamp(x - y);
}
static int trans_mul(int x, void *data)
{
int64_t y = *(int*)data;
return clamp(x * y);
}
static int trans_div(int x, void *data)
{
int64_t y = *(int*)data;
return clamp(x / y);
}
static int trans_and(int x, void *data)
{
int y = *(int*)data;
return x & y;
}
static int trans_or(int x, void *data)
{
int y = *(int*)data;
return x | y;
}
static int trans_xor(int x, void *data)
{
int y = *(int*)data;
return x ^ y;
}
static void vmArray_AddNum(struct page **array, int index, int num)
{
transform(*array, index, trans_add, &num);
}
static void vmArray_SubNum(struct page **array, int index, int num)
{
transform(*array, index, trans_sub, &num);
}
static void vmArray_MulNum(struct page **array, int index, int num)
{
transform(*array, index, trans_mul, &num);
}
static void vmArray_DivNum(struct page **array, int index, int num)
{
if (num != 0)
transform(*array, index, trans_div, &num);
}
static void vmArray_AndNum(struct page **array, int index, int num)
{
transform(*array, index, trans_and, &num);
}
static void vmArray_OrNum(struct page **array, int index, int num)
{
transform(*array, index, trans_or, &num);
}
static void vmArray_XorNum(struct page **array, int index, int num)
{
transform(*array, index, trans_xor, &num);
}
//void vmArray_MinNum(struct page **array, int index, int num);
//void vmArray_MaxNum(struct page **array, int index, int num);
struct vmarray_iter {
struct page *array;
int index;
};
static int trans_add_array(int x, void *data)
{
struct vmarray_iter *iter = data;
return clamp((int64_t)x + iter->array->values[iter->index++].i);
}
static int trans_sub_array(int x, void *data)
{
struct vmarray_iter *iter = data;
return clamp((int64_t)x - iter->array->values[iter->index++].i);
}
static int trans_mul_array(int x, void *data)
{
struct vmarray_iter *iter = data;
return clamp((int64_t)x * iter->array->values[iter->index++].i);
}
static int trans_div_array(int x, void *data)
{
struct vmarray_iter *iter = data;
int rhs = iter->array->values[iter->index++].i;
return rhs ? x / rhs : x;
}
static int trans_and_array(int x, void *data)
{
struct vmarray_iter *iter = data;
return x & iter->array->values[iter->index++].i;
}
static int trans_or_array(int x, void *data)
{
struct vmarray_iter *iter = data;
return x | iter->array->values[iter->index++].i;
}
static int trans_xor_array(int x, void *data)
{
struct vmarray_iter *iter = data;
return x ^ iter->array->values[iter->index++].i;
}
static void vmArray_AddArray(struct page **d_array, int index, struct page *s_array)
{
struct vmarray_iter iter = { s_array, 0 };
transform(*d_array, index, trans_add_array, &iter);
}
static void vmArray_SubArray(struct page **d_array, int index, struct page *s_array)
{
struct vmarray_iter iter = { s_array, 0 };
transform(*d_array, index, trans_sub_array, &iter);
}
static void vmArray_MulArray(struct page **d_array, int index, struct page *s_array)
{
struct vmarray_iter iter = { s_array, 0 };
transform(*d_array, index, trans_mul_array, &iter);
}
static void vmArray_DivArray(struct page **d_array, int index, struct page *s_array)
{
struct vmarray_iter iter = { s_array, 0 };
transform(*d_array, index, trans_div_array, &iter);
}
static void vmArray_AndArray(struct page **d_array, int index, struct page *s_array)
{
struct vmarray_iter iter = { s_array, 0 };
transform(*d_array, index, trans_and_array, &iter);
}
static void vmArray_OrArray(struct page **d_array, int index, struct page *s_array)
{
struct vmarray_iter iter = { s_array, 0 };
transform(*d_array, index, trans_or_array, &iter);
}
static void vmArray_XorArray(struct page **d_array, int index, struct page *s_array)
{
struct vmarray_iter iter = { s_array, 0 };
transform(*d_array, index, trans_xor_array, &iter);
}
//void vmArray_MinArray(struct page **d_array, int index, struct page *s_array);
//void vmArray_MaxArray(struct page **d_array, int index, struct page *s_array);
static bool pred_equal(int x, void *data)
{
int y = *(int*)data;
return x == y;
}
static bool pred_not_equal(int x, void *data)
{
int y = *(int*)data;
return x != y;
}
static bool pred_low(int x, void *data)
{
int y = *(int*)data;
return x <= y;
}
static bool pred_high(int x, void *data)
{
int y = *(int*)data;
return y <= x;
}
struct range {
int min;
int max;
};
static bool pred_in_range(int x, void *data)
{
struct range *r = data;
return r->min <= x && x <= r->max;
}
static int count_if(struct page *array, int index, bool (*pred)(int, void *), void *data)
{
if (!array)
return 0;
check_array(array);
int count = 0;
for (int i = index; i < array->nr_vars; i++) {
if (pred(array->values[i].i, data))
count++;
}
return count;
}
static int vmArray_EnumEquNum(struct page *array, int index, int num)
{
return count_if(array, index, pred_equal, &num);
}
static int vmArray_EnumNotNum(struct page *array, int index, int num)
{
return count_if(array, index, pred_not_equal, &num);
}
static int vmArray_EnumLowNum(struct page *array, int index, int num)
{
return count_if(array, index, pred_low, &num);
}
static int vmArray_EnumHighNum(struct page *array, int index, int num)
{
return count_if(array, index, pred_high, &num);
}
static int vmArray_EnumRangeNum(struct page *array, int index, int min, int max)
{
struct range r = { .min = min, .max = max };
return count_if(array, index, pred_in_range, &r);
}
static void replace(struct page *array, int index, int n, bool (*pred)(int, void *), void *data)
{
if (!array)
return;
check_array(array);
for (int i = index; i < array->nr_vars; i++) {
if (pred(array->values[i].i, data))
array->values[i].i = n;
}
}
static void vmArray_ChangeEquNum(struct page **array, int index, int num, int exg)
{
replace(*array, index, exg, pred_equal, &num);
}
static void vmArray_ChangeNotNum(struct page **array, int index, int num, int exg)
{
replace(*array, index, exg, pred_not_equal, &num);
}
static void vmArray_ChangeLowNum(struct page **array, int index, int num, int exg)
{
replace(*array, index, exg, pred_low, &num);
}
static void vmArray_ChangeHighNum(struct page **array, int index, int num, int exg)
{
replace(*array, index, exg, pred_high, &num);
}
static void vmArray_ChangeRangeNum(struct page **array, int index, int min, int max, int exg)
{
struct range r = { .min = min, .max = max };
replace(*array, index, exg, pred_in_range, &r);
}
static int find(struct page *array, int index, bool (*pred)(int, void *), void *data, int *out_index)
{
if (!array)
return 0;
check_array(array);
if (index >= 0) {
for (int i = index; i < array->nr_vars; i++) {
if (pred(array->values[i].i, data)) {
*out_index = i;
return 1;
}
}
} else {
for (int i = -index - 1; i >= 0; --i) {
if (pred(array->values[i].i, data)) {
*out_index = i;
return 1;
}
}
}
return 0;
}
static int vmArray_GrepEquNum(struct page *array, int index, int num, int *out_index)
{
return find(array, index, pred_equal, &num, out_index);
}
static int vmArray_GrepNotNum(struct page *array, int index, int num, int *out_index)
{
return find(array, index, pred_not_equal, &num, out_index);
}
static int vmArray_GrepLowNum(struct page *array, int index, int num, int *out_index)
{
return find(array, index, pred_low, &num, out_index);
}
static int vmArray_GrepHighNum(struct page *array, int index, int num, int *out_index)
{
return find(array, index, pred_high, &num, out_index);
}
static int vmArray_GrepRangeNum(struct page *array, int index, int min, int max, int *out_index)
{
struct range r = { .min = min, .max = max };
return find(array, index, pred_in_range, &r, out_index);
}
static int vmArray_GrepLowOrder(struct page *s_array, int index, struct page **d_array_, int *out_index)
{
struct page *d_array = *d_array_;
check_array(s_array);
check_array(d_array);
if (index < 0)
VM_ERROR("not implemented");
int min_index = -1, min_value;
for (int i = index; i < s_array->nr_vars; i++) {
if (d_array->values[i].i)
continue;
int val = s_array->values[i].i;
if (min_index < 0 || val < min_value) {
min_index = i;
min_value = val;
}
}
if (min_index < 0)
return 0;
*out_index = min_index;
d_array->values[min_index].i = 1;
return 1;
}
static int vmArray_GrepHighOrder(struct page *s_array, int index, struct page **d_array_, int *out_index)
{
struct page *d_array = *d_array_;
check_array(s_array);
check_array(d_array);
if (index < 0)
VM_ERROR("not implemented");
int max_index = -1, max_value;
for (int i = index; i < s_array->nr_vars; i++) {
if (d_array->values[i].i)
continue;
int val = s_array->values[i].i;
if (max_index < 0 || val > max_value) {
max_index = i;
max_value = val;
}
}
if (max_index < 0)
return 0;
*out_index = max_index;
d_array->values[max_index].i = 1;
return 1;
}
static void map_predicate(struct page *s_array, int index, bool (*pred)(int, void *), void *data, struct page *d_array)
{
if (!s_array || !d_array)
return;
check_array(s_array);
check_array(d_array);
if (index >= 0) {
for (int i = index; i < s_array->nr_vars; i++) {
d_array->values[i].i = pred(s_array->values[i].i, data) ? 1 : 0;
}
} else {
for (int i = -index - 1; i >= 0; --i) {
d_array->values[i].i = pred(s_array->values[i].i, data) ? 1 : 0;
}
}
}
static void vmArray_SetEquNum(struct page *s_array, int index, int num, struct page **d_array)
{
map_predicate(s_array, index, pred_equal, &num, *d_array);
}
static void vmArray_SetNotNum(struct page *s_array, int index, int num, struct page **d_array)
{
map_predicate(s_array, index, pred_not_equal, &num, *d_array);
}
static void vmArray_SetLowNum(struct page *s_array, int index, int num, struct page **d_array)
{
map_predicate(s_array, index, pred_low, &num, *d_array);
}
static void vmArray_SetHighNum(struct page *s_array, int index, int num, struct page **d_array)
{
map_predicate(s_array, index, pred_high, &num, *d_array);
}
static void vmArray_SetRangeNum(struct page *s_array, int index, int min, int max, struct page **d_array)
{
struct range r = { .min = min, .max = max };
map_predicate(s_array, index, pred_in_range, &r, *d_array);
}
//void vmArray_AndEquNum(struct page *pISVMArray, int index, int num, struct page **pIDVMArray);
//void vmArray_AndNotNum(struct page *pISVMArray, int index, int num, struct page **pIDVMArray);
//void vmArray_AndLowNum(struct page *pISVMArray, int index, int num, struct page **pIDVMArray);
//void vmArray_AndHighNum(struct page *pISVMArray, int index, int num, struct page **pIDVMArray);
//void vmArray_AndRangeNum(struct page *pISVMArray, int index, int nMin, int nMax, struct page **pIDVMArray);
static void set_if(struct page *s_array, int index, bool (*pred)(int, void *), void *data, struct page *d_array)
{
if (!s_array || !d_array)
return;
check_array(s_array);
check_array(d_array);
if (index >= 0) {
for (int i = index; i < s_array->nr_vars; i++) {
if (pred(s_array->values[i].i, data))
d_array->values[i].i = 1;
}
} else {
for (int i = -index - 1; i >= 0; --i) {
if (pred(s_array->values[i].i, data))
d_array->values[i].i = 1;
}
}
}
static void vmArray_OrEquNum(struct page *s_array, int index, int num, struct page **d_array)
{
set_if(s_array, index, pred_equal, &num, *d_array);
}
static void vmArray_OrNotNum(struct page *s_array, int index, int num, struct page **d_array)
{
set_if(s_array, index, pred_not_equal, &num, *d_array);
}
static void vmArray_OrLowNum(struct page *s_array, int index, int num, struct page **d_array)
{
set_if(s_array, index, pred_low, &num, *d_array);
}
static void vmArray_OrHighNum(struct page *s_array, int index, int num, struct page **d_array)
{
set_if(s_array, index, pred_high, &num, *d_array);
}
static void vmArray_OrRangeNum(struct page *s_array, int index, int min, int max, struct page **d_array)
{
struct range r = { .min = min, .max = max };
set_if(s_array, index, pred_in_range, &r, *d_array);
}
// Find num by visiting elements spirally around (x, y).
static int vmArray_AroundRect(struct page *array, int width, int height, int x, int y, int length, int num, int *out_x, int *out_y)
{
for (int dist = 1;; dist++) {
if (--length < 0)
return 0;
y--;
if (0 <= x && x < width && 0 <= y && y < height && array->values[y * width + x].i == num)
goto found;
for (int i = 0; i < dist; i++) {
if (--length < 0)
return 0;
x++;
y++;
if (0 <= x && x < width && 0 <= y && y < height && array->values[y * width + x].i == num)
goto found;
}
for (int i = 0; i < dist; i++) {
if (--length < 0)
return 0;
x--;
y++;
if (0 <= x && x < width && 0 <= y && y < height && array->values[y * width + x].i == num)
goto found;
}
for (int i = 0; i < dist; i++) {
if (--length < 0)
return 0;
x--;
y--;
if (0 <= x && x < width && 0 <= y && y < height && array->values[y * width + x].i == num)
goto found;
}
for (int i = 0; i < dist; i++) {
if (--length < 0)
return 0;
x++;
y--;
if (0 <= x && x < width && 0 <= y && y < height && array->values[y * width + x].i == num)
goto found;
}
}
found:
*out_x = x;
*out_y = y;
return 1;
}
//int vmArray_AroundHexa(struct page *array, int nWidth, int nHeight, int nX, int nY, int nLength, int num, int *pnRX, int *pnRY);
static int vmArray_PaintRect(struct page **array_, int width, int height, int x, int y, int length)
{
struct page *array = *array_;
check_array(array);
if (array->nr_vars < width * height || x >= width || y >= height || length < 0)
return 0;
int size = width * height;
for (int i = 0; i < size; i++) {
array->values[i].i = array->values[i].i < 0 ? -2 : -1;
}
int count = 0;
array->values[y * width + x].i = 0;
for (int dist = 0; dist < length; dist++) {
for (int i = 0; i < size; i++) {
if (array->values[i].i != dist)
continue;
if (i / width > 0 && array->values[i - width].i == -1) {
array->values[i - width].i = dist + 1;
count++;
}
if (i / width < height - 1 && array->values[i + width].i == -1) {
array->values[i + width].i = dist + 1;
count++;
}
if (i % width > 0 && array->values[i - 1].i == -1) {
array->values[i - 1].i = dist + 1;
count++;
}
if (i % width < width - 1 && array->values[i + 1].i == -1) {
array->values[i + 1].i = dist + 1;
count++;
}
}
}
return count;
}
//int vmArray_PaintHexa(struct page **pIVMArray, int nWidth, int nHeight, int nX, int nY, int nLength);
static int vmArray_CopyRectToRect(struct page **d_array_, int dw, int dh, int dx, int dy, struct page *s_array, int sw, int sh, int sx, int sy, int w, int h)
{
struct page *d_array = *d_array_;
check_array(s_array);
check_array(d_array);
if (s_array->nr_vars < sw * sh || d_array->nr_vars < dw * dh)
return 0;
for (int y = 0; y < h; y++) {
for (int x = 0; x < w; x++) {
if (dx + x < 0 || dx + x >= dw || dy + y < 0 || dy + y >= dh)
continue;
if (sx + x < 0 || sx + x >= sw || sy + y < 0 || sy + y >= sh)
continue;
d_array->values[(dy + y) * dw + dx + x] = s_array->values[(sy + y) * sw + sx + x];
}
}
return 1;
}
//int vmArray_CopyHexaToHexa(struct page **pIDVMArray, int nDWidth, int nDHeight, int nDx, int nDy, struct page *pISVMArray, int nSWidth, int nSHeight, int nSx, int nSy, int nCWidth, int nCHeight);
// Transpose s_array (as a 2D array of s_width * s_height) into d_array.
static int vmArray_ConvertRectSide(struct page **d_array_, struct page *s_array, int s_width, int s_height, int side)
{
struct page *d_array = *d_array_;
check_array(s_array);
check_array(d_array);
int w = side ? s_width : s_height;
int h = side ? s_height : s_width;
if (s_array->nr_vars < w * h || d_array->nr_vars < w * h)
return 0;
for (int y = 0; y < h; y++) {
for (int x = 0; x < w; x++) {
d_array->values[x * h + y] = s_array->values[y * w + x];
}
}
return 1;
}
HLL_LIBRARY(vmArray,
HLL_TODO_EXPORT(GetAdd, vmArray_GetAdd),
HLL_TODO_EXPORT(GetSub, vmArray_GetSub),
HLL_TODO_EXPORT(GetMul, vmArray_GetMul),
HLL_TODO_EXPORT(GetDiv, vmArray_GetDiv),
HLL_TODO_EXPORT(GetAnd, vmArray_GetAnd),
HLL_TODO_EXPORT(GetOr, vmArray_GetOr),
HLL_TODO_EXPORT(GetXor, vmArray_GetXor),
HLL_EXPORT(AddNum, vmArray_AddNum),
HLL_EXPORT(SubNum, vmArray_SubNum),
HLL_EXPORT(MulNum, vmArray_MulNum),
HLL_EXPORT(DivNum, vmArray_DivNum),
HLL_EXPORT(AndNum, vmArray_AndNum),
HLL_EXPORT(OrNum, vmArray_OrNum),
HLL_EXPORT(XorNum, vmArray_XorNum),
HLL_TODO_EXPORT(MinNum, vmArray_MinNum),
HLL_TODO_EXPORT(MaxNum, vmArray_MaxNum),
HLL_EXPORT(AddArray, vmArray_AddArray),
HLL_EXPORT(SubArray, vmArray_SubArray),
HLL_EXPORT(MulArray, vmArray_MulArray),
HLL_EXPORT(DivArray, vmArray_DivArray),
HLL_EXPORT(AndArray, vmArray_AndArray),
HLL_EXPORT(OrArray, vmArray_OrArray),
HLL_EXPORT(XorArray, vmArray_XorArray),
HLL_TODO_EXPORT(MinArray, vmArray_MinArray),
HLL_TODO_EXPORT(MaxArray, vmArray_MaxArray),
HLL_EXPORT(EnumEquNum, vmArray_EnumEquNum),
HLL_EXPORT(EnumNotNum, vmArray_EnumNotNum),
HLL_EXPORT(EnumLowNum, vmArray_EnumLowNum),
HLL_EXPORT(EnumHighNum, vmArray_EnumHighNum),
HLL_EXPORT(EnumRangeNum, vmArray_EnumRangeNum),
HLL_EXPORT(ChangeEquNum, vmArray_ChangeEquNum),
HLL_EXPORT(ChangeNotNum, vmArray_ChangeNotNum),
HLL_EXPORT(ChangeLowNum, vmArray_ChangeLowNum),
HLL_EXPORT(ChangeHighNum, vmArray_ChangeHighNum),
HLL_EXPORT(ChangeRangeNum, vmArray_ChangeRangeNum),
HLL_EXPORT(GrepEquNum, vmArray_GrepEquNum),
HLL_EXPORT(GrepNotNum, vmArray_GrepNotNum),
HLL_EXPORT(GrepLowNum, vmArray_GrepLowNum),
HLL_EXPORT(GrepHighNum, vmArray_GrepHighNum),
HLL_EXPORT(GrepRangeNum, vmArray_GrepRangeNum),
HLL_EXPORT(GrepLowOrder, vmArray_GrepLowOrder),
HLL_EXPORT(GrepHighOrder, vmArray_GrepHighOrder),
HLL_EXPORT(SetEquNum, vmArray_SetEquNum),
HLL_EXPORT(SetNotNum, vmArray_SetNotNum),
HLL_EXPORT(SetLowNum, vmArray_SetLowNum),
HLL_EXPORT(SetHighNum, vmArray_SetHighNum),
HLL_EXPORT(SetRangeNum, vmArray_SetRangeNum),
HLL_TODO_EXPORT(AndEquNum, vmArray_AndEquNum),
HLL_TODO_EXPORT(AndNotNum, vmArray_AndNotNum),
HLL_TODO_EXPORT(AndLowNum, vmArray_AndLowNum),
HLL_TODO_EXPORT(AndHighNum, vmArray_AndHighNum),
HLL_TODO_EXPORT(AndRangeNum, vmArray_AndRangeNum),
HLL_EXPORT(OrEquNum, vmArray_OrEquNum),
HLL_EXPORT(OrNotNum, vmArray_OrNotNum),
HLL_EXPORT(OrLowNum, vmArray_OrLowNum),
HLL_EXPORT(OrHighNum, vmArray_OrHighNum),
HLL_EXPORT(OrRangeNum, vmArray_OrRangeNum),
HLL_EXPORT(AroundRect, vmArray_AroundRect),
HLL_TODO_EXPORT(AroundHexa, vmArray_AroundHexa),
HLL_EXPORT(PaintRect, vmArray_PaintRect),
HLL_TODO_EXPORT(PaintHexa, vmArray_PaintHexa),
HLL_EXPORT(CopyRectToRect, vmArray_CopyRectToRect),
HLL_TODO_EXPORT(CopyHexaToHexa, vmArray_CopyHexaToHexa),
HLL_EXPORT(ConvertRectSide, vmArray_ConvertRectSide)
);
+85
View File
@@ -0,0 +1,85 @@
/* Copyright (C) 2024 kichikuou <KichikuouChrome@gmail.com>
*
* 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 "system4.h"
#include "system4/cg.h"
#include "asset_manager.h"
#include "gfx/gfx.h"
#include "hll.h"
#include "vmSurface.h"
HLL_QUIET_UNIMPLEMENTED( , void, vmCG, New, void);
//int vmCG_Release(void);
HLL_WARN_UNIMPLEMENTED( , void, vmCG, SetType, int type);
//int vmCG_EnumHandle(void);
static int vmCG_Exist(int num)
{
return asset_exists(ASSET_CG, num);
}
static int vmCG_Load(int num)
{
struct cg *cg = asset_cg_load(num);
if (!cg)
return 0;
struct vm_surface *sf = vm_surface_create(cg->metrics.w, cg->metrics.h);
gfx_init_texture_with_cg(&sf->texture, cg);
sf->has_pixel = cg->metrics.has_pixel;
sf->has_alpha = cg->metrics.has_alpha;
sf->cg_no = num;
cg_free(cg);
return sf->no;
}
static void vmCG_Unload(int surface)
{
vm_surface_delete(surface);
}
static int vmCG_Trans(int surface, int x, int y, int num)
{
struct vm_surface *sf = vm_surface_get(surface);
if (!sf)
return 0;
struct cg *cg = asset_cg_load(num);
if (!cg)
return 0;
Texture src;
gfx_init_texture_with_cg(&src, cg);
cg_free(cg);
if (sf->has_alpha)
gfx_copy_with_alpha_map(&sf->texture, x, y, &src, 0, 0, src.w, src.h);
else
gfx_blend_amap(&sf->texture, x, y, &src, 0, 0, src.w, src.h);
gfx_delete_texture(&src);
return 1;
}
HLL_LIBRARY(vmCG,
HLL_EXPORT(New, vmCG_New),
HLL_TODO_EXPORT(Release, vmCG_Release),
HLL_EXPORT(SetType, vmCG_SetType),
HLL_TODO_EXPORT(EnumHandle, vmCG_EnumHandle),
HLL_EXPORT(Exist, vmCG_Exist),
HLL_EXPORT(Load, vmCG_Load),
HLL_EXPORT(Unload, vmCG_Unload),
HLL_EXPORT(Trans, vmCG_Trans)
);
+89
View File
@@ -0,0 +1,89 @@
/* Copyright (C) 2024 kichikuou <KichikuouChrome@gmail.com>
*
* 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 <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "system4.h"
#include "system4/cg.h"
#include "system4/string.h"
#include "gfx/gfx.h"
#include "hll.h"
#include "ChrLoader.h"
#include "vmSurface.h"
#include "xsystem4.h"
static void vmChrLoader_Init(possibly_unused void *imainsystem, possibly_unused struct string *string)
{
chr_loader_init("Chr");
}
static int vmChrLoader_Exist(int id)
{
return chr_loader_exists(id) ? 1 : 0;
}
HLL_QUIET_UNIMPLEMENTED(, void, vmChrLoader, ReleaseMemory, int id, int index);
static struct string *vmChrLoader_GetMsg(int id, int index)
{
struct string *msg = chr_loader_get_string(id, index);
return msg ? msg : string_ref(&EMPTY_STRING);
}
static struct string *vmChrLoader_GetName(int id)
{
struct string *name = chr_loader_get_name(id);
return name ? name : string_ref(&EMPTY_STRING);
}
static int vmChrLoader_MemoryToSurface(int memory, int x, int y, int surface)
{
struct vm_surface *sf = vm_surface_get(surface);
if (!sf)
return 0;
size_t size;
void *data = chr_loader_get_blob(memory, &size);
if (!data)
return 0;
struct cg *cg = cg_load_buffer(data, size);
if (!cg)
return 0;
Texture tex;
gfx_init_texture_with_cg(&tex, cg);
cg_free(cg);
gfx_copy(&sf->texture, x, y, &tex, 0, 0, tex.w, tex.h);
gfx_delete_texture(&tex);
return 1;
}
HLL_LIBRARY(vmChrLoader,
HLL_EXPORT(Init, vmChrLoader_Init),
HLL_EXPORT(Exist, vmChrLoader_Exist),
HLL_EXPORT(GetID, chr_loader_get_id),
HLL_EXPORT(GetStatus, chr_loader_get_status),
HLL_EXPORT(GetMemory, chr_loader_get_blob_handle),
HLL_EXPORT(ReleaseMemory, vmChrLoader_ReleaseMemory),
HLL_EXPORT(GetMsg, vmChrLoader_GetMsg),
HLL_EXPORT(GetName, vmChrLoader_GetName),
HLL_EXPORT(MemoryToSurface, vmChrLoader_MemoryToSurface)
);
+43
View File
@@ -0,0 +1,43 @@
/* Copyright (C) 2024 kichikuou <KichikuouChrome@gmail.com>
*
* 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 "hll.h"
#include "input.h"
HLL_QUIET_UNIMPLEMENTED( , void, vmCursor, Init, void *imainsystem);
static void vmCursor_SetPos(int x, int y)
{
mouse_set_pos(x, y);
}
static int vmCursor_GetPos(int *x, int *y)
{
handle_events();
mouse_get_pos(x, y);
return mouse_focus && keyboard_focus;
}
//void vmCursor_SetShow(int nShow);
//int vmCursor_GetShow(void);
HLL_LIBRARY(vmCursor,
HLL_EXPORT(Init, vmCursor_Init),
HLL_EXPORT(SetPos, vmCursor_SetPos),
HLL_EXPORT(GetPos, vmCursor_GetPos),
HLL_TODO_EXPORT(SetShow, vmCursor_SetShow),
HLL_TODO_EXPORT(GetShow, vmCursor_GetShow)
);
+53
View File
@@ -0,0 +1,53 @@
/* Copyright (C) 2024 kichikuou <KichikuouChrome@gmail.com>
*
* 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 <SDL.h>
#include "system4/string.h"
#include "system4/utfsjis.h"
#include "hll.h"
HLL_QUIET_UNIMPLEMENTED( , void, vmDialog, Init, void *imainsystem);
static int vmDialog_MsgBox(struct string *t_string, struct string *string, int type, possibly_unused int default_button)
{
uint32_t flags = (type == 4) ? SDL_MESSAGEBOX_ERROR : 0;
char *title = sjis2utf(t_string->text, 0);
char *message = sjis2utf(string->text, 0);
SDL_ShowSimpleMessageBox(flags, title, message, NULL);
free(message);
free(title);
return 1;
}
//int vmDialog_InputNum(struct string *pITString, int nMin, int nMax, int *pnNum);
//int vmDialog_InputString(struct string *pITString, int nLength, struct string **pIString);
//int vmDialog_SelectNum(struct string *pITString, int nMin, int nMax, int *pnNum);
//int vmDialog_SelectString(struct string *pITString, struct page **pIVMArray, int nNum, struct string **pIString);
//int vmDialog_InputOpenFile(struct string *pITString, struct string **pIPString, struct string **pIString, struct string *pIDString, struct string *pIFString);
//int vmDialog_InputSaveFile(struct string *pITString, struct string **pIPString, struct string **pIString, struct string *pIDString, struct string *pIFString);
HLL_LIBRARY(vmDialog,
HLL_EXPORT(Init, vmDialog_Init),
HLL_EXPORT(MsgBox, vmDialog_MsgBox),
HLL_TODO_EXPORT(InputNum, vmDialog_InputNum),
HLL_TODO_EXPORT(InputString, vmDialog_InputString),
HLL_TODO_EXPORT(SelectNum, vmDialog_SelectNum),
HLL_TODO_EXPORT(SelectString, vmDialog_SelectString),
HLL_TODO_EXPORT(InputOpenFile, vmDialog_InputOpenFile),
HLL_TODO_EXPORT(InputSaveFile, vmDialog_InputSaveFile)
);
+119
View File
@@ -0,0 +1,119 @@
/* Copyright (C) 2024 kichikuou <KichikuouChrome@gmail.com>
*
* 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 "system4/cg.h"
#include "asset_manager.h"
#include "gfx/gfx.h"
#include "hll.h"
#include "id_pool.h"
#include "vmSurface.h"
struct vm_drawgauge {
struct texture tex;
int surface;
};
static struct id_pool pool;
static void vmDrawGauge_New(void)
{
if (pool.slots)
return; // already initialized
id_pool_init(&pool, ID_POOL_HANDLE_BASE);
}
static int vmDrawGauge_EnumHandle(void)
{
return id_pool_count(&pool);
}
static int vmDrawGauge_Open(int cg_no, int origin, int phase)
{
struct cg *cg = asset_cg_load(cg_no);
if (!cg)
return 0;
int w = cg->metrics.w;
int h = cg->metrics.h;
int handle = id_pool_get_unused(&pool);
struct vm_drawgauge *dg = xcalloc(1, sizeof(struct vm_drawgauge));
id_pool_set(&pool, handle, dg);
gfx_init_texture_with_cg(&dg->tex, cg);
cg_free(cg);
struct vm_surface *sf = vm_surface_create(w, h);
gfx_init_texture_blank(&sf->texture, w, h);
dg->surface = sf->no;
return handle;
}
static void vmDrawGauge_Close(int handle)
{
struct vm_drawgauge *dg = id_pool_release(&pool, handle);
if (!dg)
return;
gfx_delete_texture(&dg->tex);
vm_surface_delete(dg->surface);
free(dg);
}
static int vmDrawGauge_Release(void)
{
for (int i = id_pool_get_first(&pool); i >= 0; i = id_pool_get_next(&pool, i))
vmDrawGauge_Close(i);
id_pool_delete(&pool);
return 1;
}
static void vmDrawGauge_ModuleFini(void)
{
vmDrawGauge_Release();
}
static int vmDrawGauge_GetSurface(int handle)
{
struct vm_drawgauge *dg = id_pool_get(&pool, handle);
return dg ? dg->surface : 0;
}
static void vmDrawGauge_Draw(int handle, int now, int max)
{
struct vm_drawgauge *dg = id_pool_get(&pool, handle);
if (!dg)
return;
struct vm_surface *sf = vm_surface_get(dg->surface);
if (!sf)
return;
gfx_fill_with_alpha(&sf->texture, 0, 0, sf->texture.w, sf->texture.h, 255, 0, 255, 0);
int w = sf->texture.w * now / max;
gfx_copy_with_alpha_map(&sf->texture, 0, 0, &dg->tex, 0, 0, w, sf->texture.h);
}
HLL_LIBRARY(vmDrawGauge,
HLL_EXPORT(_ModuleFini, vmDrawGauge_ModuleFini),
HLL_EXPORT(New, vmDrawGauge_New),
HLL_EXPORT(Release, vmDrawGauge_Release),
HLL_EXPORT(EnumHandle, vmDrawGauge_EnumHandle),
HLL_EXPORT(Open, vmDrawGauge_Open),
HLL_EXPORT(Close, vmDrawGauge_Close),
HLL_EXPORT(GetSurface, vmDrawGauge_GetSurface),
HLL_EXPORT(Draw, vmDrawGauge_Draw)
);
+266
View File
@@ -0,0 +1,266 @@
/* Copyright (C) 2024 kichikuou <KichikuouChrome@gmail.com>
*
* 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 "system4.h"
#include "system4/string.h"
#include "gfx/font.h"
#include "hll.h"
#include "id_pool.h"
#include "vmSurface.h"
#include "xsystem4.h"
enum {
SURFACE_DROP_SHADOW,
SURFACE_BOLD,
SURFACE_TEXT,
NR_SURFACES
};
struct style {
struct text_style ts;
int drop_shadow;
SDL_Color drop_shadow_color;
int bold;
SDL_Color bold_color;
};
struct vm_drawmsg {
int w;
int h;
int surfaces[NR_SURFACES];
struct string *text;
Point pos;
Point initial_pos;
struct style style;
struct style initial_style;
};
static struct id_pool pool;
static void vmDrawMsg_New(possibly_unused void *imainsystem)
{
if (pool.slots)
return; // already initialized
gfx_font_init();
id_pool_init(&pool, ID_POOL_HANDLE_BASE);
}
static int vmDrawMsg_EnumHandle(void)
{
return id_pool_count(&pool);
}
static int vmDrawMsg_Open(int width, int height)
{
int no = id_pool_get_unused(&pool);
struct vm_drawmsg *dm = xcalloc(1, sizeof(struct vm_drawmsg));
id_pool_set(&pool, no, dm);
dm->w = width;
dm->h = height;
for (int i = 0; i < NR_SURFACES; i++) {
struct vm_surface *sf = vm_surface_create(width, height);
dm->surfaces[i] = sf->no;
gfx_init_texture_rgba(&sf->texture, sf->w, sf->h, COLOR(0, 0, 0, 0));
}
dm->text = string_dup(&EMPTY_STRING);
dm->initial_style.ts.face = FONT_GOTHIC;
dm->initial_style.ts.size = 24.0f;
dm->initial_style.ts.weight = FW_BOLD;
dm->initial_style.ts.color = COLOR(255, 255, 255, 255);
dm->initial_style.ts.scale_x = 1.0;
dm->initial_style.ts.space_scale_x = 1.0f;
dm->style = dm->initial_style;
return no;
}
static void vmDrawMsg_Close(int handle)
{
struct vm_drawmsg *dm = id_pool_release(&pool, handle);
if (!dm)
return;
free_string(dm->text);
for (int i = 0; i < NR_SURFACES; i++) {
vm_surface_delete(dm->surfaces[i]);
}
free(dm);
}
static int vmDrawMsg_Release(void)
{
for (int i = id_pool_get_first(&pool); i >= 0; i = id_pool_get_next(&pool, i))
vmDrawMsg_Close(i);
id_pool_delete(&pool);
return 1;
}
static void vmDrawMsg_ModuleFini(void)
{
vmDrawMsg_Release();
}
static int vmDrawMsg_GetNumofSurface(int handle)
{
struct vm_drawmsg *dm = id_pool_get(&pool, handle);
return dm ? NR_SURFACES : 0;
}
static int vmDrawMsg_GetSurface(int handle, int index)
{
struct vm_drawmsg *dm = id_pool_get(&pool, handle);
if (!dm || index < 0 || index >= NR_SURFACES)
return 0;
return dm->surfaces[index];
}
static int vmDrawMsg_AddMsg(int handle, struct string *s)
{
struct vm_drawmsg *dm = id_pool_get(&pool, handle);
if (!dm)
return 0;
string_append(&dm->text, s);
return 1;
}
static int vmDrawMsg_Draw(int handle)
{
struct vm_drawmsg *dm = id_pool_get(&pool, handle);
if (!dm)
return 0;
char *s = dm->text->text;
const int line_space = 2;
while (*s) {
int skiplen = 0, a1, a2, a3;
if (*s != '<') {
char *lb = strchr(s, '<');
if (lb) {
skiplen = lb - s;
*lb = '\0';
} else {
skiplen = strlen(s);
}
if (dm->style.drop_shadow) {
struct text_style ts = dm->style.ts;
ts.color = dm->style.drop_shadow_color;
struct vm_surface *sf = vm_surface_get(dm->surfaces[SURFACE_DROP_SHADOW]);
int x = dm->pos.x + dm->style.drop_shadow;
int y = dm->pos.y + dm->style.drop_shadow;
gfx_render_text(&sf->texture, x, y, s, &ts);
}
if (dm->style.bold) {
struct text_style ts = dm->style.ts;
ts.bold_width = dm->style.bold;
ts.color = dm->style.bold_color;
struct vm_surface *sf = vm_surface_get(dm->surfaces[SURFACE_BOLD]);
gfx_render_text(&sf->texture, dm->pos.x, dm->pos.y, s, &ts);
}
struct vm_surface *sf = vm_surface_get(dm->surfaces[SURFACE_TEXT]);
dm->pos.x += gfx_render_text(&sf->texture, dm->pos.x, dm->pos.y, s, &dm->style.ts);
if (lb)
*lb = '<';
} else if (sscanf(s, "<C%d,%d,%d>%n", &a1, &a2, &a3, &skiplen) == 3) {
dm->style.ts.color = COLOR(a1, a2, a3, 255);
} else if (sscanf(s, "<@C%d,%d,%d>%n", &a1, &a2, &a3, &skiplen) == 3) {
dm->initial_style.ts.color = dm->style.ts.color = COLOR(a1, a2, a3, 255);
} else if (!strncmp(s, "</C>", 4)) {
skiplen = 4;
dm->style.ts.color = dm->initial_style.ts.color;
} else if (sscanf(s, "<E%d>%n", &a1, &skiplen) == 1) {
dm->style.bold = a1;
} else if (sscanf(s, "<@E%d>%n", &a1, &skiplen) == 1) {
dm->initial_style.bold = dm->style.bold = a1;
} else if (sscanf(s, "<EC%d,%d,%d>%n", &a1, &a2, &a3, &skiplen) == 3) {
dm->style.bold_color = COLOR(a1, a2, a3, 255);
} else if (sscanf(s, "<@EC%d,%d,%d>%n", &a1, &a2, &a3, &skiplen) == 3) {
dm->initial_style.bold_color = dm->style.bold_color = COLOR(a1, a2, a3, 255);
} else if (sscanf(s, "<K%d>%n", &a1, &skiplen) == 1) {
dm->style.drop_shadow = a1;
} else if (sscanf(s, "<@K%d>%n", &a1, &skiplen) == 1) {
dm->initial_style.drop_shadow = dm->style.drop_shadow = a1;
} else if (sscanf(s, "<KC%d,%d,%d>%n", &a1, &a2, &a3, &skiplen) == 3) {
dm->style.drop_shadow_color = COLOR(a1, a2, a3, 255);
} else if (sscanf(s, "<@KC%d,%d,%d>%n", &a1, &a2, &a3, &skiplen) == 3) {
dm->initial_style.drop_shadow_color = dm->style.drop_shadow_color = COLOR(a1, a2, a3, 255);
} else if (sscanf(s, "<S%d>%n", &a1, &skiplen) == 1) {
dm->style.ts.size = a1;
} else if (sscanf(s, "<@S%d>%n", &a1, &skiplen) == 1) {
dm->initial_style.ts.size = dm->style.ts.size = a1;
} else if (sscanf(s, "<P%d,%d>%n", &a1, &a2, &skiplen) == 2) {
dm->pos = POINT(a1, a2);
} else if (sscanf(s, "<@P%d,%d>%n", &a1, &a2, &skiplen) == 2) {
dm->initial_pos = dm->pos = POINT(a1, a2);
} else if (!strncmp(s, "<WCR>", 5)) {
skiplen = 5;
dm->pos = dm->initial_pos;
for (int i = 0; i < NR_SURFACES; i++) {
struct vm_surface *dst = vm_surface_get(dm->surfaces[i]);
gfx_fill_amap(&dst->texture, 0, 0, dm->w, dm->h, 0);
}
} else if (!strncmp(s, "<CR>", 4)) {
skiplen = 4;
dm->pos = dm->initial_pos;
dm->style = dm->initial_style;
} else if (!strncmp(s, "<WA1>", 5)) {
// no-op?
skiplen = 5;
} else if (!strncmp(s, "<R>", 3)) {
skiplen = 3;
dm->pos.x = dm->initial_pos.x;
dm->pos.y += dm->style.ts.size + line_space;
} else {
char *rb = strchr(s, '>');
if (rb) {
WARNING("Unknown command %.*s", ++rb - s, s);
skiplen = rb - s;
} else {
WARNING("Unfinished command in message '%s'", dm->text->text);
break;
}
}
s += skiplen;
}
string_clear(dm->text);
return 0;
}
static int vmDrawMsg_RenewalRect(int handle, int *x, int *y, int *width, int *height)
{
struct vm_drawmsg *dm = id_pool_get(&pool, handle);
if (!dm)
return 0;
*x = 0;
*y = 0;
*width = dm->w;
*height = dm->h;
return 1;
}
HLL_LIBRARY(vmDrawMsg,
HLL_EXPORT(_ModuleFini, vmDrawMsg_ModuleFini),
HLL_EXPORT(New, vmDrawMsg_New),
HLL_EXPORT(Release, vmDrawMsg_Release),
HLL_EXPORT(EnumHandle, vmDrawMsg_EnumHandle),
HLL_EXPORT(Open, vmDrawMsg_Open),
HLL_EXPORT(Close, vmDrawMsg_Close),
HLL_EXPORT(GetNumofSurface, vmDrawMsg_GetNumofSurface),
HLL_EXPORT(GetSurface, vmDrawMsg_GetSurface),
HLL_EXPORT(AddMsg, vmDrawMsg_AddMsg),
HLL_EXPORT(Draw, vmDrawMsg_Draw),
HLL_EXPORT(RenewalRect, vmDrawMsg_RenewalRect)
);
+188
View File
@@ -0,0 +1,188 @@
/* Copyright (C) 2024 kichikuou <KichikuouChrome@gmail.com>
*
* 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 <stdio.h>
#include "system4.h"
#include "system4/cg.h"
#include "asset_manager.h"
#include "gfx/gfx.h"
#include "hll.h"
#include "id_pool.h"
#include "vmSurface.h"
enum {
ALIGN_LEFT = 0,
ZERO_PAD = 1,
ALIGN_RIGHT = 2,
ALIGN_CENTER = 4,
};
struct vm_drawnumber {
struct texture digits;
struct texture sign;
int surface;
int kind;
int figures;
int space;
};
static struct id_pool pool;
static void vmDrawNumber_New(void)
{
if (pool.slots)
return; // already initialized
id_pool_init(&pool, ID_POOL_HANDLE_BASE);
}
static int vmDrawNumber_EnumHandle(void)
{
return id_pool_count(&pool);
}
static int vmDrawNumber_Open(int cg_no, int kind, int figure, int space)
{
struct cg *cg = asset_cg_load(cg_no);
if (!cg)
return 0;
int width = cg->metrics.w / 10 * figure;
int height = cg->metrics.h;
int handle = id_pool_get_unused(&pool);
struct vm_drawnumber *dn = xcalloc(1, sizeof(struct vm_drawnumber));
id_pool_set(&pool, handle, dn);
gfx_init_texture_with_cg(&dn->digits, cg);
cg_free(cg);
struct vm_surface *sf = vm_surface_create(width, height);
gfx_init_texture_blank(&sf->texture, width, height);
dn->surface = sf->no;
dn->kind = kind;
dn->figures = figure;
dn->space = space;
return handle;
}
static void vmDrawNumber_Close(int handle)
{
struct vm_drawnumber *dn = id_pool_release(&pool, handle);
if (!dn)
return;
gfx_delete_texture(&dn->digits);
gfx_delete_texture(&dn->sign);
vm_surface_delete(dn->surface);
free(dn);
}
static int vmDrawNumber_Release(void)
{
for (int i = id_pool_get_first(&pool); i >= 0; i = id_pool_get_next(&pool, i))
vmDrawNumber_Close(i);
id_pool_delete(&pool);
return 1;
}
static void vmDrawNumber_ModuleFini(void)
{
vmDrawNumber_Release();
}
static int vmDrawNumber_GetSurface(int handle)
{
struct vm_drawnumber *dn = id_pool_get(&pool, handle);
return dn ? dn->surface : 0;
}
static void vmDrawNumber_Draw(int handle, int num)
{
struct vm_drawnumber *dn = id_pool_get(&pool, handle);
if (!dn)
return;
struct vm_surface *sf = vm_surface_get(dn->surface);
if (!sf)
return;
char buf[16];
if (dn->kind == ZERO_PAD) {
snprintf(buf, min(sizeof(buf), dn->figures + 1), "%0*d", dn->figures, num);
} else {
snprintf(buf, min(sizeof(buf), dn->figures + 1), "%d", num);
}
int dw = dn->digits.w / 10;
int w = dw * strlen(buf);
int h = dn->digits.h;
int left;
switch (dn->kind) {
case ALIGN_LEFT:
case ZERO_PAD:
left = 0;
break;
case ALIGN_RIGHT:
left = sf->texture.w - w;
break;
case ALIGN_CENTER:
left = (sf->texture.w - w) / 2;
break;
default:
WARNING("vmDrawNumber.Draw: unknown kind %d", dn->kind);
left = 0;
break;
}
gfx_fill_amap(&sf->texture, 0, 0, sf->texture.w, sf->texture.h, 0);
for (int i = 0; buf[i]; i++) {
switch (buf[i]) {
case '-':
gfx_copy_with_alpha_map(&sf->texture, left + i * dw, 0, &dn->sign, 0, 0, dw, h);
break;
default:
gfx_copy_with_alpha_map(&sf->texture, left + i * dw, 0, &dn->digits, (buf[i] - '0') * dw, 0, dw, h);
break;
}
}
}
int vmDrawNumber_SetSign(int handle, int cg_no)
{
struct vm_drawnumber *dn = id_pool_get(&pool, handle);
if (!dn)
return 0;
struct cg *cg = asset_cg_load(cg_no);
if (!cg)
return 0;
gfx_init_texture_with_cg(&dn->sign, cg);
cg_free(cg);
return 1;
}
HLL_LIBRARY(vmDrawNumber,
HLL_EXPORT(_ModuleFini, vmDrawNumber_ModuleFini),
HLL_EXPORT(New, vmDrawNumber_New),
HLL_EXPORT(Release, vmDrawNumber_Release),
HLL_EXPORT(EnumHandle, vmDrawNumber_EnumHandle),
HLL_EXPORT(Open, vmDrawNumber_Open),
HLL_EXPORT(Close, vmDrawNumber_Close),
HLL_EXPORT(GetSurface, vmDrawNumber_GetSurface),
HLL_EXPORT(Draw, vmDrawNumber_Draw),
HLL_EXPORT(SetSign, vmDrawNumber_SetSign)
);
+372
View File
@@ -0,0 +1,372 @@
/* Copyright (C) 2024 kichikuou <KichikuouChrome@gmail.com>
*
* 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 <errno.h>
#include <stdio.h>
#include <string.h>
#include "system4.h"
#include "system4/buffer.h"
#include "system4/file.h"
#include "system4/string.h"
#include "hll.h"
#include "id_pool.h"
#include "vm/heap.h"
#include "vm/page.h"
#include "xsystem4.h"
enum vm_file_mode {
VM_FILE_READ = 1,
VM_FILE_WRITE = 2
};
struct vm_file {
char *path;
FILE *fp;
struct buffer buf;
};
static struct id_pool pool;
static void read_page(struct vm_file *vf, struct page *page);
static void write_page(struct vm_file *vf, struct page *page);
static void read_value(struct vm_file *vf, union vm_value *v, enum ain_data_type type)
{
switch (type) {
case AIN_INT:
case AIN_BOOL:
case AIN_LONG_INT:
v->i = buffer_read_int32(&vf->buf);
break;
case AIN_FLOAT:
v->f = buffer_read_float(&vf->buf);
break;
case AIN_STRING:
variable_fini(*v, type);
v->i = heap_alloc_string(buffer_read_string(&vf->buf));
break;
case AIN_STRUCT:
case AIN_ARRAY_TYPE:
read_page(vf, heap_get_page(v->i));
break;
default:
VM_ERROR("Unsupported value type %d", type);
}
}
static void read_page(struct vm_file *vf, struct page *page)
{
switch (page->type) {
case STRUCT_PAGE:
{
struct ain_struct *s = &ain->structures[page->index];
for (int i = 0; i < s->nr_members; i++) {
read_value(vf, &page->values[i], s->members[i].type.data);
}
}
break;
case ARRAY_PAGE:
{
enum ain_data_type type = page->array.rank > 1 ? page->a_type : array_type(page->a_type);
for (int i = 0; i < page->nr_vars; i++) {
read_value(vf, &page->values[i], type);
}
}
break;
default:
VM_ERROR("Unsupported page type %d", page->type);
}
}
static void write_value(struct vm_file *vf, union vm_value v, enum ain_data_type type)
{
switch (type) {
case AIN_INT:
case AIN_BOOL:
buffer_write_int32(&vf->buf, v.i);
break;
case AIN_FLOAT:
buffer_write_float(&vf->buf, v.f);
break;
case AIN_STRING:
buffer_write_cstringz(&vf->buf, heap_get_string(v.i)->text);
break;
case AIN_STRUCT:
case AIN_ARRAY_TYPE:
write_page(vf, heap_get_page(v.i));
break;
default:
VM_ERROR("Unsupported value type %d", type);
}
}
static void write_page(struct vm_file *vf, struct page *page)
{
switch (page->type) {
case STRUCT_PAGE:
{
struct ain_struct *s = &ain->structures[page->index];
for (int i = 0; i < s->nr_members; i++) {
write_value(vf, page->values[i], s->members[i].type.data);
}
}
break;
case ARRAY_PAGE:
{
enum ain_data_type type = page->array.rank > 1 ? page->a_type : array_type(page->a_type);
for (int i = 0; i < page->nr_vars; i++) {
write_value(vf, page->values[i], type);
}
}
break;
default:
VM_ERROR("Unsupported page type %d", page->type);
}
}
static void vmFile_ModuleInit(void)
{
id_pool_init(&pool, ID_POOL_HANDLE_BASE);
}
static int vmFile_EnumHandle(void)
{
return id_pool_count(&pool);
}
static int vmFile_Open(struct string *string, int type)
{
struct vm_file *vf = xcalloc(1, sizeof(struct vm_file));
char *path = savedir_path(string->text);
vf->path = path;
if (type == VM_FILE_READ) {
size_t len;
uint8_t *data = file_read(path, &len);
if (!data) {
free(path);
free(vf);
return 0;
}
buffer_init(&vf->buf, data, len);
} else if (type == VM_FILE_WRITE) {
vf->fp = file_open_utf8(path, "wb");
if (!vf->fp) {
WARNING("Failed to open file '%s': %s", display_utf0(path), strerror(errno));
free(path);
free(vf);
return 0;
}
} else {
WARNING("Unknown mode in vmFile.Open: %d", type);
return 0;
}
int handle = id_pool_get_unused(&pool);
id_pool_set(&pool, handle, vf);
return handle;
}
static void vmFile_Close(int handle)
{
struct vm_file *vf = id_pool_release(&pool, handle);
if (!vf)
return;
if (vf->fp) { // write mode
if (fwrite(vf->buf.buf, vf->buf.index, 1, vf->fp) != 1) {
WARNING("%s: fwrite failed: %s", display_utf0(vf->path), strerror(errno));
}
fclose(vf->fp);
}
free(vf->buf.buf);
free(vf->path);
free(vf);
}
static void vmFile_ModuleFini(void)
{
for (int i = id_pool_get_first(&pool); i >= 0; i = id_pool_get_next(&pool, i))
vmFile_Close(i);
id_pool_delete(&pool);
}
static int vmFile_Encode(int handle, int seed, int rand)
{
struct vm_file *vf = id_pool_get(&pool, handle);
if (!vf)
return 0;
size_t len = vf->buf.index;
int32_t *buf = xmalloc(len + 8);
memcpy(buf + 2, vf->buf.buf, len);
free(vf->buf.buf);
vf->buf.buf = (uint8_t*)buf;
vf->buf.index += 8;
int32_t mask = rand ^ ((rand & 1) ? 0xdf3d1b79 : 0x3ddf791b);
int32_t checksum = 0;
buf[0] = mask;
len >>= 2;
for (int i = 0; i < len; i++) {
buf[i + 2] ^= mask;
mask = buf[i + 2] ^ seed;
checksum ^= mask;
if (i & 2)
mask ^= i * -3 ^ 0xf7fef7fe;
if (i & 4)
mask = mask << ((3 - i) & 0xf) | mask >> ((i - 3) & 0xf);
}
buf[1] = checksum;
return 1;
}
static int vmFile_Decode(int handle, int seed)
{
struct vm_file *vf = id_pool_get(&pool, handle);
if (!vf)
return 0;
int32_t mask = buffer_read_int32(&vf->buf);
int32_t checksum = buffer_read_int32(&vf->buf);
int32_t *buf = (int32_t*)buffer_strdata(&vf->buf);
int len = buffer_remaining(&vf->buf) >> 2;
int32_t sum = 0;
for (int i = 0; i < len; i++) {
buf[i] ^= mask;
mask ^= buf[i] ^ seed;
sum ^= mask;
if (i & 2)
mask ^= i * -3 ^ 0xf7fef7fe;
if (i & 4)
mask = mask << ((3 - i) & 0xf) | mask >> ((i - 3) & 0xf);
}
if (sum != checksum) {
WARNING("%s: checksum error", display_utf0(vf->path));
return 0;
}
return 1;
}
//int vmFile_ReadArrayChar(int handle, struct page **pIVMArray);
//int vmFile_ReadArrayShort(int handle, struct page **pIVMArray);
//int vmFile_ReadArrayInt(int handle, struct page **pIVMArray);
//int vmFile_ReadArrayFloat(int handle, struct page **pIVMArray);
//int vmFile_ReadArrayString(int handle, struct page **pIVMArray);
//int vmFile_ReadArrayStruct(int handle, struct page **pIVMArray);
static int vmFile_ReadStruct(int handle, struct page **_page)
{
struct vm_file *vf = id_pool_get(&pool, handle);
if (!vf)
return 0;
struct page *page = *_page;
if (page->type != STRUCT_PAGE) {
VM_ERROR("vmFile.ReadStruct of non-struct");
}
read_page(vf, page);
return 1;
}
//int vmFile_ReadGlobal(int handle, IMainSystem pIMainSystem);
//int vmFile_WriteArrayChar(int handle, struct page *pIVMArray);
//int vmFile_WriteArrayShort(int handle, struct page *pIVMArray);
//int vmFile_WriteArrayInt(int handle, struct page *pIVMArray);
//int vmFile_WriteArrayFloat(int handle, struct page *pIVMArray);
//int vmFile_WriteArrayString(int handle, struct page *pIVMArray);
//int vmFile_WriteArrayStruct(int handle, struct page *pIVMArray);
static int vmFile_WriteStruct(int handle, struct page *page)
{
struct vm_file *vf = id_pool_get(&pool, handle);
if (!vf)
return 0;
write_page(vf, page);
return 1;
}
//int vmFile_WriteGlobal(int handle, IMainSystem pIMainSystem);
//int vmFile_SeekChar(int handle, int nPos, int nAbsolute);
//int vmFile_SeekShort(int handle, int nPos, int nAbsolute);
//int vmFile_SeekInt(int handle, int nPos, int nAbsolute);
//int vmFile_SeekFloat(int handle, int nPos, int nAbsolute);
//int vmFile_SeekString(int handle, int nPos, int nAbsolute);
//int vmFile_SizeChar(int handle);
//int vmFile_SizeShort(int handle);
//int vmFile_SizeInt(int handle);
//int vmFile_SizeFloat(int handle);
//int vmFile_SizeString(int handle);
//int vmFile_Copy(struct string *pISString, struct string *pIDString);
static int vmFile_Delete(struct string *string)
{
char *path = savedir_path(string->text);
int r = !remove_utf8(path);
free(path);
return r;
}
//int vmFile_GetTime(struct string *pIString, struct page **pIVMStruct);
//int vmFile_Find(struct string *pIWildString, struct string **pIString, int *pnCount);
//int vmFile_MakeDirectory(struct string *pIString);
HLL_LIBRARY(vmFile,
HLL_EXPORT(_ModuleInit, vmFile_ModuleInit),
HLL_EXPORT(_ModuleFini, vmFile_ModuleFini),
HLL_EXPORT(EnumHandle, vmFile_EnumHandle),
HLL_EXPORT(Open, vmFile_Open),
HLL_EXPORT(Close, vmFile_Close),
HLL_EXPORT(Encode, vmFile_Encode),
HLL_EXPORT(Decode, vmFile_Decode),
HLL_TODO_EXPORT(ReadArrayChar, vmFile_ReadArrayChar),
HLL_TODO_EXPORT(ReadArrayShort, vmFile_ReadArrayShort),
HLL_TODO_EXPORT(ReadArrayInt, vmFile_ReadArrayInt),
HLL_TODO_EXPORT(ReadArrayFloat, vmFile_ReadArrayFloat),
HLL_TODO_EXPORT(ReadArrayString, vmFile_ReadArrayString),
HLL_TODO_EXPORT(ReadArrayStruct, vmFile_ReadArrayStruct),
HLL_EXPORT(ReadStruct, vmFile_ReadStruct),
HLL_TODO_EXPORT(ReadGlobal, vmFile_ReadGlobal),
HLL_TODO_EXPORT(WriteArrayChar, vmFile_WriteArrayChar),
HLL_TODO_EXPORT(WriteArrayShort, vmFile_WriteArrayShort),
HLL_TODO_EXPORT(WriteArrayInt, vmFile_WriteArrayInt),
HLL_TODO_EXPORT(WriteArrayFloat, vmFile_WriteArrayFloat),
HLL_TODO_EXPORT(WriteArrayString, vmFile_WriteArrayString),
HLL_TODO_EXPORT(WriteArrayStruct, vmFile_WriteArrayStruct),
HLL_EXPORT(WriteStruct, vmFile_WriteStruct),
HLL_TODO_EXPORT(WriteGlobal, vmFile_WriteGlobal),
HLL_TODO_EXPORT(SeekChar, vmFile_SeekChar),
HLL_TODO_EXPORT(SeekShort, vmFile_SeekShort),
HLL_TODO_EXPORT(SeekInt, vmFile_SeekInt),
HLL_TODO_EXPORT(SeekFloat, vmFile_SeekFloat),
HLL_TODO_EXPORT(SeekString, vmFile_SeekString),
HLL_TODO_EXPORT(SizeChar, vmFile_SizeChar),
HLL_TODO_EXPORT(SizeShort, vmFile_SizeShort),
HLL_TODO_EXPORT(SizeInt, vmFile_SizeInt),
HLL_TODO_EXPORT(SizeFloat, vmFile_SizeFloat),
HLL_TODO_EXPORT(SizeString, vmFile_SizeString),
HLL_TODO_EXPORT(Copy, vmFile_Copy),
HLL_EXPORT(Delete, vmFile_Delete),
HLL_TODO_EXPORT(GetTime, vmFile_GetTime),
HLL_TODO_EXPORT(Find, vmFile_Find),
HLL_TODO_EXPORT(MakeDirectory, vmFile_MakeDirectory)
);
+214
View File
@@ -0,0 +1,214 @@
/* Copyright (C) 2024 kichikuou <KichikuouChrome@gmail.com>
*
* 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 "gfx/gfx.h"
#include "vmSurface.h"
#include "hll.h"
HLL_QUIET_UNIMPLEMENTED( , void, vmGraph, Init, void *imainsystem);
//void vmGraph_SetUseCPUEx(int nUse);
static void vmGraph_Copy(int dst_surface, int dx, int dy, int src_surface, int sx, int sy, int width, int height)
{
struct vm_surface *dst = vm_surface_get(dst_surface);
struct vm_surface *src = vm_surface_get(src_surface);
if (!dst || !src)
return;
gfx_copy_with_alpha_map(&dst->texture, dx, dy, &src->texture, sx, sy, width, height);
}
static void vmGraph_CopyPixelMap(int dst_surface, int dx, int dy, int src_surface, int sx, int sy, int width, int height)
{
struct vm_surface *dst = vm_surface_get(dst_surface);
struct vm_surface *src = vm_surface_get(src_surface);
if (!dst || !src)
return;
gfx_copy(&dst->texture, dx, dy, &src->texture, sx, sy, width, height);
}
static void vmGraph_CopyAlphaMap(int dst_surface, int dx, int dy, int src_surface, int sx, int sy, int width, int height)
{
struct vm_surface *dst = vm_surface_get(dst_surface);
struct vm_surface *src = vm_surface_get(src_surface);
if (!dst || !src)
return;
gfx_copy_amap(&dst->texture, dx, dy, &src->texture, sx, sy, width, height);
}
//void vmGraph_CopyBright(int dst_surface, int dx, int dy, int src_surface, int sx, int sy, int width, int height, int nRate);
static void vmGraph_CopySprite(int dst_surface, int dx, int dy, int src_surface, int sx, int sy, int width, int height, int r, int g, int b)
{
struct vm_surface *dst = vm_surface_get(dst_surface);
struct vm_surface *src = vm_surface_get(src_surface);
if (!dst || !src)
return;
gfx_copy_sprite(&dst->texture, dx, dy, &src->texture, sx, sy, width, height, COLOR(r, g, b, 0));
}
//void vmGraph_Blend(int dst_surface, int dx, int dy, int src_surface, int sx, int sy, int width, int height, int alpha);
//void vmGraph_BlendSrcBright(int dst_surface, int dx, int dy, int src_surface, int sx, int sy, int width, int height, int alpha, int nRate);
//void vmGraph_BlendAddSatur(int dst_surface, int dx, int dy, int src_surface, int sx, int sy, int width, int height);
static void vmGraph_BlendAlphaMap(int dst_surface, int dx, int dy, int src_surface, int sx, int sy, int width, int height)
{
struct vm_surface *dst = vm_surface_get(dst_surface);
struct vm_surface *src = vm_surface_get(src_surface);
if (!dst || !src)
return;
gfx_blend_amap(&dst->texture, dx, dy, &src->texture, sx, sy, width, height);
}
//void vmGraph_BlendAlphaMapSrcOnly(int dst_surface, int dx, int dy, int src_surface, int sx, int sy, int width, int height);
//void vmGraph_BlendAlphaMapColor(int dst_surface, int dx, int dy, int src_surface, int sx, int sy, int width, int height, int r, int g, int b);
//void vmGraph_BlendAlphaMapColorAlpha(int dst_surface, int dx, int dy, int src_surface, int sx, int sy, int width, int height, int r, int g, int b, int alpha);
//void vmGraph_BlendAlphaMapAlpha(int dst_surface, int dx, int dy, int src_surface, int sx, int sy, int width, int height, int alpha);
//void vmGraph_BlendAlphaMapBright(int dst_surface, int dx, int dy, int src_surface, int sx, int sy, int width, int height, int nRate);
//void vmGraph_BlendAlphaMapAlphaSrcBright(int dst_surface, int dx, int dy, int src_surface, int sx, int sy, int width, int height, int alpha, int nRate);
//void vmGraph_BlendUseAMapColor(int dst_surface, int dx, int dy, int width, int height, int hAlphaSurface, int nAx, int nAy, int r, int g, int b, int alpha);
//void vmGraph_BlendScreen(int dst_surface, int dx, int dy, int src_surface, int sx, int sy, int width, int height);
//void vmGraph_BlendMultiply(int dst_surface, int dx, int dy, int src_surface, int sx, int sy, int width, int height);
//void vmGraph_BlendScreenAlpha(int dst_surface, int dx, int dy, int src_surface, int sx, int sy, int width, int height, int alpha);
static void vmGraph_Fill(int surface, int x, int y, int width, int height, int r, int g, int b, int alpha)
{
struct vm_surface *dst = vm_surface_get(surface);
if (!dst)
return;
gfx_fill_with_alpha(&dst->texture, x, y, width, height, r, g, b, alpha);
}
static void vmGraph_FillPixelMap(int surface, int x, int y, int width, int height, int r, int g, int b)
{
struct vm_surface *dst = vm_surface_get(surface);
if (!dst)
return;
gfx_fill(&dst->texture, x, y, width, height, r, g, b);
}
static void vmGraph_FillAlphaMap(int surface, int x, int y, int width, int height, int alpha)
{
struct vm_surface *dst = vm_surface_get(surface);
if (!dst)
return;
gfx_fill_amap(&dst->texture, x, y, width, height, alpha);
}
static void vmGraph_FillAlphaColor(int surface, int x, int y, int width, int height, int r, int g, int b, int rate)
{
struct vm_surface *dst = vm_surface_get(surface);
if (!dst)
return;
gfx_fill_alpha_color(&dst->texture, x, y, width, height, r, g, b, rate);
}
//void vmGraph_SaturDP_DPxSA(int dst_surface, int dx, int dy, int src_surface, int sx, int sy, int width, int height);
//void vmGraph_ScreenDA_DAxSA(int dst_surface, int dx, int dy, int src_surface, int sx, int sy, int width, int height);
static void vmGraph_AddDA_DAxSA(int dst_surface, int dx, int dy, int src_surface, int sx, int sy, int width, int height)
{
struct vm_surface *dst = vm_surface_get(dst_surface);
struct vm_surface *src = vm_surface_get(src_surface);
if (!dst || !src)
return;
gfx_add_da_daxsa(&dst->texture, dx, dy, &src->texture, sx, sy, width, height);
}
//void vmGraph_SubDA_DAxSA(int dst_surface, int dx, int dy, int src_surface, int sx, int sy, int width, int height);
//void vmGraph_BrightDestOnly(int surface, int x, int y, int width, int height, int nRate);
//void vmGraph_CopyTextureWrap(int dst_surface, int dx, int dy, int d_width, int d_height, int src_surface, int sx, int sy, int s_width, int s_height, int nU, int nV);
//void vmGraph_CopyTextureWrapAlpha(int dst_surface, int dx, int dy, int d_width, int d_height, int src_surface, int sx, int sy, int s_width, int s_height, int nU, int nV, int alpha);
static void vmGraph_CopyStretch(int surface, int dx, int dy, int d_width, int d_height, int src_surface, float sx, float sy, float s_width, float s_height)
{
struct vm_surface *dst = vm_surface_get(surface);
struct vm_surface *src = vm_surface_get(src_surface);
if (!dst || !src)
return;
// Use nearest neighbor interpolation to avoid magenta edges.
glBindTexture(GL_TEXTURE_2D, src->texture.handle);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glBindTexture(GL_TEXTURE_2D, 0);
gfx_copy_stretch(
&dst->texture, dx, dy, d_width, d_height,
&src->texture, sx, sy, s_width, s_height);
glBindTexture(GL_TEXTURE_2D, src->texture.handle);
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);
}
//void vmGraph_CopyStretchBlend(int surface, int dx, int dy, int d_width, int d_height, int src_surface, float sx, float sy, float s_width, float s_height, int alpha);
//void vmGraph_CopyStretchBlendAlphaMap(int surface, int dx, int dy, int d_width, int d_height, int src_surface, float sx, float sy, float s_width, float s_height);
HLL_WARN_UNIMPLEMENTED( , void, vmGraph, SetClickCancel, int click);
//int vmGraph_EffectCopy(int dx, int dy, int src_surface, int sx, int sy, int width, int height, int nEffect, int nTotalTime);
//int vmGraph_GetMainWidth(void);
//int vmGraph_GetMainHeight(void);
//int vmGraph_GetMainBpp(void);
void vmGraph_Update(int x, int y, int width, int height)
{
gfx_swap();
}
HLL_LIBRARY(vmGraph,
HLL_EXPORT(Init, vmGraph_Init),
HLL_TODO_EXPORT(SetUseCPUEx, vmGraph_SetUseCPUEx),
HLL_EXPORT(Copy, vmGraph_Copy),
HLL_EXPORT(CopyPixelMap, vmGraph_CopyPixelMap),
HLL_EXPORT(CopyAlphaMap, vmGraph_CopyAlphaMap),
HLL_TODO_EXPORT(CopyBright, vmGraph_CopyBright),
HLL_EXPORT(CopySprite, vmGraph_CopySprite),
HLL_TODO_EXPORT(Blend, vmGraph_Blend),
HLL_TODO_EXPORT(BlendSrcBright, vmGraph_BlendSrcBright),
HLL_TODO_EXPORT(BlendAddSatur, vmGraph_BlendAddSatur),
HLL_EXPORT(BlendAlphaMap, vmGraph_BlendAlphaMap),
HLL_TODO_EXPORT(BlendAlphaMapSrcOnly, vmGraph_BlendAlphaMapSrcOnly),
HLL_TODO_EXPORT(BlendAlphaMapColor, vmGraph_BlendAlphaMapColor),
HLL_TODO_EXPORT(BlendAlphaMapColorAlpha, vmGraph_BlendAlphaMapColorAlpha),
HLL_TODO_EXPORT(BlendAlphaMapAlpha, vmGraph_BlendAlphaMapAlpha),
HLL_TODO_EXPORT(BlendAlphaMapBright, vmGraph_BlendAlphaMapBright),
HLL_TODO_EXPORT(BlendAlphaMapAlphaSrcBright, vmGraph_BlendAlphaMapAlphaSrcBright),
HLL_TODO_EXPORT(BlendUseAMapColor, vmGraph_BlendUseAMapColor),
HLL_TODO_EXPORT(BlendScreen, vmGraph_BlendScreen),
HLL_TODO_EXPORT(BlendMultiply, vmGraph_BlendMultiply),
HLL_TODO_EXPORT(BlendScreenAlpha, vmGraph_BlendScreenAlpha),
HLL_EXPORT(Fill, vmGraph_Fill),
HLL_EXPORT(FillPixelMap, vmGraph_FillPixelMap),
HLL_EXPORT(FillAlphaMap, vmGraph_FillAlphaMap),
HLL_EXPORT(FillAlphaColor, vmGraph_FillAlphaColor),
HLL_TODO_EXPORT(SaturDP_DPxSA, vmGraph_SaturDP_DPxSA),
HLL_TODO_EXPORT(ScreenDA_DAxSA, vmGraph_ScreenDA_DAxSA),
HLL_EXPORT(AddDA_DAxSA, vmGraph_AddDA_DAxSA),
HLL_TODO_EXPORT(SubDA_DAxSA, vmGraph_SubDA_DAxSA),
HLL_TODO_EXPORT(BrightDestOnly, vmGraph_BrightDestOnly),
HLL_TODO_EXPORT(CopyTextureWrap, vmGraph_CopyTextureWrap),
HLL_TODO_EXPORT(CopyTextureWrapAlpha, vmGraph_CopyTextureWrapAlpha),
HLL_EXPORT(CopyStretch, vmGraph_CopyStretch),
HLL_TODO_EXPORT(CopyStretchBlend, vmGraph_CopyStretchBlend),
HLL_TODO_EXPORT(CopyStretchBlendAlphaMap, vmGraph_CopyStretchBlendAlphaMap),
HLL_EXPORT(SetClickCancel, vmGraph_SetClickCancel),
HLL_TODO_EXPORT(EffectCopy, vmGraph_EffectCopy),
HLL_EXPORT(GetMainSurface, vm_surface_get_main_surface),
HLL_TODO_EXPORT(GetMainWidth, vmGraph_GetMainWidth),
HLL_TODO_EXPORT(GetMainHeight, vmGraph_GetMainHeight),
HLL_TODO_EXPORT(GetMainBpp, vmGraph_GetMainBpp),
HLL_EXPORT(Update, vmGraph_Update)
);
+41
View File
@@ -0,0 +1,41 @@
/* Copyright (C) 2024 kichikuou <KichikuouChrome@gmail.com>
*
* 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 "hll.h"
HLL_WARN_UNIMPLEMENTED(, void, vmGraphQuake, SetMode, int mode);
//void vmGraphQuake_SetAmp(int nAmp);
HLL_WARN_UNIMPLEMENTED(, void, vmGraphQuake, SetAmpX, int amp_x);
HLL_WARN_UNIMPLEMENTED(, void, vmGraphQuake, SetAmpY, int amp_y);
//void vmGraphQuake_SetCycle(int nCycle);
//int vmGraphQuake_GetMode(void);
//int vmGraphQuake_GetAmp(void);
//int vmGraphQuake_GetAmpX(void);
//int vmGraphQuake_GetAmpY(void);
//int vmGraphQuake_GetCycle(void);
HLL_LIBRARY(vmGraphQuake,
HLL_EXPORT(SetMode, vmGraphQuake_SetMode),
HLL_TODO_EXPORT(SetAmp, vmGraphQuake_SetAmp),
HLL_EXPORT(SetAmpX, vmGraphQuake_SetAmpX),
HLL_EXPORT(SetAmpY, vmGraphQuake_SetAmpY),
HLL_TODO_EXPORT(SetCycle, vmGraphQuake_SetCycle),
HLL_TODO_EXPORT(GetMode, vmGraphQuake_GetMode),
HLL_TODO_EXPORT(GetAmp, vmGraphQuake_GetAmp),
HLL_TODO_EXPORT(GetAmpX, vmGraphQuake_GetAmpX),
HLL_TODO_EXPORT(GetAmpY, vmGraphQuake_GetAmpY),
HLL_TODO_EXPORT(GetCycle, vmGraphQuake_GetCycle)
);
+133
View File
@@ -0,0 +1,133 @@
/* Copyright (C) 2024 kichikuou <KichikuouChrome@gmail.com>
*
* 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 "hll.h"
#include "id_pool.h"
#include "input.h"
#include "vm.h"
#include "xsystem4.h"
#define MAXENT 32
struct vm_key {
int size;
int win[MAXENT];
int ret[MAXENT];
};
static struct id_pool pool;
static void handle_events_throttled(void)
{
// To prevent taking 100% CPU time in busy input loops,
// sleep 10ms every 30 input event checks.
static int count;
if (++count == 30) {
count = 0;
vm_sleep(10);
}
handle_events();
}
static void vmKey_Init(possibly_unused void *imainsystem)
{
if (pool.slots)
return; // already initialized
id_pool_init(&pool, ID_POOL_HANDLE_BASE);
}
static int vmKey_EnumHandle(void)
{
return id_pool_count(&pool);
}
static int vmKey_Open(void)
{
int no = id_pool_get_unused(&pool);
struct vm_key *vk = xcalloc(1, sizeof(struct vm_key));
id_pool_set(&pool, no, vk);
return no;
}
static void vmKey_Close(int handle)
{
struct vm_key *vk = id_pool_release(&pool, handle);
if (vk)
free(vk);
}
static void vmKey_ModuleFini(void)
{
for (int i = id_pool_get_first(&pool); i >= 0; i = id_pool_get_next(&pool, i))
vmKey_Close(i);
id_pool_delete(&pool);
}
static int vmKey_Set(int handle, int win_key, int ret_key)
{
struct vm_key *vk = id_pool_get(&pool, handle);
if (!vk)
return 0;
if (vk->size + 1 >= MAXENT)
VM_ERROR("too many keys");
vk->win[vk->size] = win_key;
vk->ret[vk->size] = ret_key;
vk->size++;
return 1;
}
static int vmKey_Get(int handle)
{
struct vm_key *vk = id_pool_get(&pool, handle);
if (!vk)
return 0;
handle_events_throttled();
int ret = 0;
for (int i = 0; i < vk->size; i++) {
if (key_is_down(vk->win[i])) {
ret |= vk->ret[i];
}
}
return ret;
}
static int vmKey_GetWheelCount(void)
{
int forward, back;
handle_events_throttled();
mouse_get_wheel(&forward, &back);
mouse_clear_wheel();
return back - forward;
}
//void vmKey_ClearBuffer(void);
HLL_LIBRARY(vmKey,
HLL_EXPORT(_ModuleFini, vmKey_ModuleFini),
HLL_EXPORT(Init, vmKey_Init),
HLL_EXPORT(EnumHandle, vmKey_EnumHandle),
HLL_EXPORT(Open, vmKey_Open),
HLL_EXPORT(Close, vmKey_Close),
HLL_EXPORT(Set, vmKey_Set),
HLL_EXPORT(Get, vmKey_Get),
HLL_EXPORT(GetWheelCount, vmKey_GetWheelCount),
HLL_TODO_EXPORT(ClearBuffer, vmKey_ClearBuffer)
);
+231
View File
@@ -0,0 +1,231 @@
/* Copyright (C) 2024 kichikuou <KichikuouChrome@gmail.com>
*
* 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 <stdio.h>
#include <stdlib.h>
#include "system4/file.h"
#include "system4/mt19937int.h"
#include "system4/little_endian.h"
#include "hll.h"
#include "xsystem4.h"
/*
* struct MapHeader {
* char magic[4]; // "Map\0"
* // the below are encrypted
* uint32_t width;
* uint32_t height;
* uint32_t cg_table_offset;
* uint32_t move_table_offset;
* uint32_t figure_table_offset;
* uint32_t info_table_offset;
* uint32_t map_no;
* };
*
* struct CGTable {
* uint32_t count;
* uint32_t cg[count];
* };
*
* struct MoveTable {
* bool movable[height][width];
* };
*
* struct FigureTable {
* uint32_t count;
* struct {
* uint8_t x;
* uint8_t y;
* uint16_t unit;
* } figures[count];
* };
*
* struct InfoTable {
* uint32_t item;
* uint32_t gold;
* uint32_t turn;
* uint32_t level;
* uint32_t unknown; // checksum?
* };
*/
static uint8_t *map_data;
static size_t map_size;
static char *mapfile_path(int map_no)
{
char buf[32];
sprintf(buf, "Map/%04d.map", map_no);
return gamedir_path(buf);
}
HLL_QUIET_UNIMPLEMENTED(, void, vmMapLoader,Init, void *imainsystem, struct string *string);
static int vmMapLoader_Exist(int map_no)
{
char *path = mapfile_path(map_no);
bool result = file_exists(path);
free(path);
return result;
}
static int vmMapLoader_New(int map_no)
{
if (map_data)
free(map_data);
char *path = mapfile_path(map_no);
map_data = file_read(path, &map_size);
if (!map_data) {
WARNING("Cannot read %s", path);
} else if (memcmp(map_data, "Map", 4)) {
WARNING("%s: Wrong magic bytes", path);
free(map_data);
map_data = NULL;
} else {
mt19937_xorcode(map_data + 4, map_size - 4, 12753);
}
free(path);
return !!map_data;
}
void vmMapLoader_Release(void)
{
if (map_data) {
free(map_data);
map_data = NULL;
}
}
static int vmMapLoader_GetWidth(void)
{
if (!map_data)
return -1;
return LittleEndian_getDW(map_data, 4);
}
static int vmMapLoader_GetHeight(void)
{
if (!map_data)
return -1;
return LittleEndian_getDW(map_data, 8);
}
static int vmMapLoader_GetBaseCG(int index)
{
if (!map_data)
return -1;
int nr_base_cg = LittleEndian_getDW(map_data, 32);
if (index < 0 || index >= nr_base_cg)
return -1;
return LittleEndian_getDW(map_data, 36 + index * 4);
}
static int vmMapLoader_GetNumofBaseCG(void)
{
if (!map_data)
return -1;
return LittleEndian_getDW(map_data, 32);
}
static int vmMapLoader_IsMove(int x, int y)
{
if (!map_data)
return -1;
int w = LittleEndian_getDW(map_data, 4);
int h = LittleEndian_getDW(map_data, 8);
if (x < 0 || x >= w || y < 0 || y > h)
return 0;
uint8_t *table = map_data + LittleEndian_getDW(map_data, 16);
return table[y * w + x];
}
static int vmMapLoader_GetFigure(int x, int y)
{
if (!map_data)
return 0;
int offset = LittleEndian_getDW(map_data, 20);
int num = LittleEndian_getDW(map_data, offset);
uint8_t *table = map_data + offset + 4;
for (int i = 0; i < num; i++) {
if (x == table[i * 4] && y == table[i * 4 + 1])
return LittleEndian_getW(table, i * 4 + 2);
}
return 0;
}
static int vmMapLoader_GetItemNum(void)
{
if (!map_data)
return -1;
int offset = LittleEndian_getDW(map_data, 24);
return LittleEndian_getDW(map_data, offset + 0);
}
static int vmMapLoader_GetGoldNum(void)
{
if (!map_data)
return -1;
int offset = LittleEndian_getDW(map_data, 24);
return LittleEndian_getDW(map_data, offset + 4);
}
static int vmMapLoader_GetTurnNum(void)
{
if (!map_data)
return -1;
int offset = LittleEndian_getDW(map_data, 24);
return LittleEndian_getDW(map_data, offset + 8);
}
static int vmMapLoader_GetLevel(void)
{
if (!map_data)
return -1;
int offset = LittleEndian_getDW(map_data, 24);
return LittleEndian_getDW(map_data, offset + 12);
}
static int vmMapLoader_GetID(void)
{
if (!map_data)
return -1;
return LittleEndian_getDW(map_data, 28);
}
HLL_LIBRARY(vmMapLoader,
HLL_EXPORT(Init, vmMapLoader_Init),
HLL_EXPORT(Exist, vmMapLoader_Exist),
HLL_EXPORT(New, vmMapLoader_New),
HLL_EXPORT(Release, vmMapLoader_Release),
HLL_EXPORT(GetWidth, vmMapLoader_GetWidth),
HLL_EXPORT(GetHeight, vmMapLoader_GetHeight),
HLL_EXPORT(GetBaseCG, vmMapLoader_GetBaseCG),
HLL_EXPORT(GetNumofBaseCG, vmMapLoader_GetNumofBaseCG),
HLL_EXPORT(IsMove, vmMapLoader_IsMove),
HLL_EXPORT(GetFigure, vmMapLoader_GetFigure),
HLL_EXPORT(GetItemNum, vmMapLoader_GetItemNum),
HLL_EXPORT(GetGoldNum, vmMapLoader_GetGoldNum),
HLL_EXPORT(GetTurnNum, vmMapLoader_GetTurnNum),
HLL_EXPORT(GetLevel, vmMapLoader_GetLevel),
HLL_EXPORT(GetID, vmMapLoader_GetID)
);
+108
View File
@@ -0,0 +1,108 @@
/* Copyright (C) 2024 kichikuou <KichikuouChrome@gmail.com>
*
* 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/ain.h"
#include "system4/string.h"
#include "hll.h"
#include "id_pool.h"
#include "vm.h"
#include "vm/page.h"
struct vm_msglog {
struct page *array; // backing store
int ptr;
};
static struct id_pool pool;
static void vmMsgLog_Init(possibly_unused void *imainsystem)
{
if (pool.slots)
return; // already initialized
id_pool_init(&pool, ID_POOL_HANDLE_BASE);
}
static int vmMsgLog_EnumHandle(void)
{
return id_pool_count(&pool);
}
static int vmMsgLog_Open(struct page **array)
{
int no = id_pool_get_unused(&pool);
struct vm_msglog *log = xcalloc(1, sizeof(struct vm_msglog));
id_pool_set(&pool, no, log);
log->array = *array;
log->ptr = 0;
return no;
}
static void vmMsgLog_Close(int handle)
{
struct vm_msglog *log = id_pool_release(&pool, handle);
if (log)
free(log);
}
static void vmMsgLog_ModuleFini(void)
{
for (int i = id_pool_get_first(&pool); i >= 0; i = id_pool_get_next(&pool, i))
vmMsgLog_Close(i);
id_pool_delete(&pool);
}
static int vmMsgLog_Set(int handle, int msg_num)
{
struct vm_msglog *log = id_pool_get(&pool, handle);
if (!log)
return 0;
if (--log->ptr < 0)
log->ptr = log->array->nr_vars - 1;
log->array->values[log->ptr].i = msg_num;
return 1;
}
static int vmMsgLog_Get(int handle, int index)
{
struct vm_msglog *log = id_pool_get(&pool, handle);
if (!log)
return -1;
int i = (index + log->ptr) % log->array->nr_vars;
return log->array->values[i].i;
}
static struct string *vmMsgLog_MsgNumToString(int msg_num)
{
if (msg_num < 0 || msg_num >= ain->nr_messages)
return string_ref(&EMPTY_STRING);
return string_ref(ain->messages[msg_num]);
}
HLL_LIBRARY(vmMsgLog,
HLL_EXPORT(_ModuleFini, vmMsgLog_ModuleFini),
HLL_EXPORT(Init, vmMsgLog_Init),
HLL_EXPORT(EnumHandle, vmMsgLog_EnumHandle),
HLL_EXPORT(Open, vmMsgLog_Open),
HLL_EXPORT(Close, vmMsgLog_Close),
HLL_EXPORT(Set, vmMsgLog_Set),
HLL_EXPORT(Get, vmMsgLog_Get),
HLL_EXPORT(MsgNumToString, vmMsgLog_MsgNumToString)
);
+39
View File
@@ -0,0 +1,39 @@
/* Copyright (C) 2024 kichikuou <KichikuouChrome@gmail.com>
*
* 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 "hll.h"
HLL_WARN_UNIMPLEMENTED(, void, vmMsgSkip, Init, void *imainsystem);
//int vmMsgSkip_EnumHandle(void);
//int vmMsgSkip_Open(struct string *pIString, int nOption);
//void vmMsgSkip_Close(int hMsgSkip);
//int vmMsgSkip_Query(int hMsgSkip, int nMsgNum);
//void vmMsgSkip_SetEnable(int nEnable);
HLL_QUIET_UNIMPLEMENTED(, void, vmMsgSkip, SetState, int state);
//int vmMsgSkip_GetEnable(void);
//int vmMsgSkip_GetState(void);
HLL_LIBRARY(vmMsgSkip,
HLL_EXPORT(Init, vmMsgSkip_Init),
HLL_TODO_EXPORT(EnumHandle, vmMsgSkip_EnumHandle),
HLL_TODO_EXPORT(Open, vmMsgSkip_Open),
HLL_TODO_EXPORT(Close, vmMsgSkip_Close),
HLL_TODO_EXPORT(Query, vmMsgSkip_Query),
HLL_TODO_EXPORT(SetEnable, vmMsgSkip_SetEnable),
HLL_EXPORT(SetState, vmMsgSkip_SetState),
HLL_TODO_EXPORT(GetEnable, vmMsgSkip_GetEnable),
HLL_TODO_EXPORT(GetState, vmMsgSkip_GetState)
);
+85
View File
@@ -0,0 +1,85 @@
/* Copyright (C) 2024 kichikuou <KichikuouChrome@gmail.com>
*
* 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 "system4.h"
#include "hll.h"
#include "audio.h"
static int max_channel;
static int *current;
static void vmMusic_Init(int max_channel_, possibly_unused void *imainsystem)
{
audio_init();
max_channel = max_channel_;
current = xcalloc(max_channel, sizeof(int));
}
static int vmMusic_Prepare(int channel, int track)
{
if (channel < 0 || channel >= max_channel)
return 0;
if (current[channel] == track)
return 1; // Keep playing current music.
int r = bgm_prepare(channel, track);
if (r)
current[channel] = track;
return r;
}
static int vmMusic_Play(int channel)
{
return bgm_play(channel);
}
static int vmMusic_Stop(int channel)
{
return bgm_stop(channel);
}
static int vmMusic_IsPlay(int channel)
{
return bgm_is_playing(channel);
}
//int vmMusic_SetLoop(int channel, int nLoop);
//int vmMusic_GetLoop(int channel);
static int vmMusic_Fade(int channel, int time, int volume, int stop)
{
return bgm_fade(channel, time, volume, stop);
}
//int vmMusic_StopFade(int channel);
//int vmMusic_IsFade(int channel);
//int vmMusic_GetPos(int channel);
//int vmMusic_GetLength(int channel);
HLL_LIBRARY(vmMusic,
HLL_EXPORT(Init, vmMusic_Init),
HLL_EXPORT(Prepare, vmMusic_Prepare),
HLL_EXPORT(Play, vmMusic_Play),
HLL_EXPORT(Stop, vmMusic_Stop),
HLL_EXPORT(IsPlay, vmMusic_IsPlay),
HLL_TODO_EXPORT(SetLoop, vmMusic_SetLoop),
HLL_TODO_EXPORT(GetLoop, vmMusic_GetLoop),
HLL_EXPORT(Fade, vmMusic_Fade),
HLL_TODO_EXPORT(StopFade, vmMusic_StopFade),
HLL_TODO_EXPORT(IsFade, vmMusic_IsFade),
HLL_TODO_EXPORT(GetPos, vmMusic_GetPos),
HLL_TODO_EXPORT(GetLength, vmMusic_GetLength)
);
+86
View File
@@ -0,0 +1,86 @@
/* Copyright (C) 2024 kichikuou <KichikuouChrome@gmail.com>
*
* 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 "audio.h"
#include "hll.h"
#include "ChrLoader.h"
static int ring_pos = 0;
static void vmSound_Init(possibly_unused void *imainsystem)
{
audio_init();
}
//void vmSound_Enable(int nEnable);
//void vmSound_SetType(int nType);
static int vmSound_Load(int channel, int num)
{
return wav_prepare(channel, num);
}
static int vmSound_LoadMemory(int channel, int memory)
{
struct archive_data *dfile = chr_loader_get_blob_as_archive_data(memory);
if (!dfile)
return 0;
return wav_prepare_from_archive_data(channel, dfile);
}
static void vmSound_Unload(int channel, possibly_unused int length)
{
wav_unprepare(channel);
}
static int vmSound_Play(int channel, possibly_unused int length)
{
wav_stop(channel);
return wav_play(channel);
}
static int vmSound_RingPlay(int channel, int ring)
{
channel += ring_pos++ % ring;
wav_stop(channel);
return wav_play(channel);
}
//int vmSound_Stop(int channel, int nLength);
//int vmSound_IsPlay(int channel, int nLength);
//void vmSound_Wait(int channel, int nLength);
//int vmSound_Fade(int channel, int nLength, int nTime, int nVolume, int nStopFlag);
//int vmSound_StopFade(int channel, int nLength);
//int vmSound_IsFade(int channel, int nLength);
//int vmSound_ReverseLR(int channel, int nLength);
HLL_LIBRARY(vmSound,
HLL_EXPORT(Init, vmSound_Init),
HLL_TODO_EXPORT(Enable, vmSound_Enable),
HLL_TODO_EXPORT(SetType, vmSound_SetType),
HLL_EXPORT(Load, vmSound_Load),
HLL_EXPORT(LoadMemory, vmSound_LoadMemory),
HLL_EXPORT(Unload, vmSound_Unload),
HLL_EXPORT(Play, vmSound_Play),
HLL_EXPORT(RingPlay, vmSound_RingPlay),
HLL_TODO_EXPORT(Stop, vmSound_Stop),
HLL_TODO_EXPORT(IsPlay, vmSound_IsPlay),
HLL_TODO_EXPORT(Wait, vmSound_Wait),
HLL_TODO_EXPORT(Fade, vmSound_Fade),
HLL_TODO_EXPORT(StopFade, vmSound_StopFade),
HLL_TODO_EXPORT(IsFade, vmSound_IsFade),
HLL_TODO_EXPORT(ReverseLR, vmSound_ReverseLR)
);
+628
View File
@@ -0,0 +1,628 @@
/* Copyright (C) 2024 kichikuou <KichikuouChrome@gmail.com>
*
* 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 <SDL.h>
#include "cJSON.h"
#include "effect.h"
#include "gfx/gfx.h"
#include "hll.h"
#include "id_pool.h"
#include "input.h"
#include "json.h"
#include "sact.h"
#include "scene.h"
#include "vm/page.h"
#include "vmSurface.h"
struct child_surface {
int surface;
int type;
Point pos;
};
struct animation {
int nr_frames;
int current_frame;
int total_frame_time;
int frame_times[];
};
struct vm_sprite {
struct sprite sp;
int surface;
int type;
Rectangle rect;
int current;
int id;
bool findable;
struct animation *anime;
struct id_pool children;
};
static struct id_pool pool;
static int default_layer = 200000;
static SDL_Rect dirty_rect;
static void check_array(struct page *array)
{
if (array->type != ARRAY_PAGE || array->a_type != AIN_ARRAY_INT || array->array.rank != 1)
VM_ERROR("Not a flat integer array");
}
static void vm_sprite_dirty(struct vm_sprite *sp)
{
scene_sprite_dirty(&sp->sp);
SDL_UnionRect(&dirty_rect, &sp->rect, &dirty_rect);
}
static void update_animation(void)
{
uint64_t now = SDL_GetTicks64();
for (int id = id_pool_get_first(&pool); id >= 0; id = id_pool_get_next(&pool, id)) {
struct vm_sprite *sp = id_pool_get(&pool, id);
if (!sp || !sp->anime)
continue;
int t = now % sp->anime->total_frame_time;
int frame;
for (frame = 0; t >= sp->anime->frame_times[frame]; frame++)
t -= sp->anime->frame_times[frame];
if (frame == sp->anime->current_frame)
continue;
sp->anime->current_frame = frame;
vm_sprite_dirty(sp);
}
}
static void render_surface(int surface, int type, int current, Rectangle *rect, Point *pos)
{
struct vm_surface *sf = vm_surface_get(surface);
Texture *src = &sf->texture;
Texture *dst = gfx_main_surface();
int sx = 0;
int sy = 0;
int dx = rect->x + (pos ? pos->x : 0);
int dy = rect->y + (pos ? pos->y : 0);
int w = pos ? src->w : rect->w;
int h = pos ? src->h : rect->h;
if (current) {
int col = sf->w / w;
sx = current % col * w;
sy = current / col * h;
}
switch (type) {
case 0:
gfx_copy(dst, dx, dy, src, sx, sy, w, h);
break;
case 1:
gfx_blend_amap(dst, dx, dy, src, sx, sy, w, h);
break;
case 2:
gfx_copy_sprite(dst, dx, dy, src, sx, sy, w, h, COLOR(255, 0, 255, 0));
break;
case 3:
gfx_blend_add_satur(dst, dx, dy, src, sx, sy, w, h);
break;
default:
WARNING("unknown vmSprite type %d", type);
break;
}
}
static void vm_sprite_render(struct sprite *_sp)
{
struct vm_sprite *sp = (struct vm_sprite*)_sp;
if (sp->current >= 0) {
int current = sp->current + (sp->anime ? sp->anime->current_frame : 0);
render_surface(sp->surface, sp->type, current, &sp->rect, NULL);
}
for (int id = id_pool_get_first(&sp->children); id >= 0; id = id_pool_get_next(&sp->children, id)) {
struct child_surface *child = id_pool_get(&sp->children, id);
if (!child)
continue;
render_surface(child->surface, child->type, 0, &sp->rect, &child->pos);
}
}
static cJSON *vm_sprite_to_json(struct sprite *_sp, bool verbose)
{
struct vm_sprite* sp = (struct vm_sprite*)_sp;
cJSON *ent, *sprite, *children;
ent = scene_sprite_to_json(_sp, verbose);
cJSON_AddItemToObjectCS(ent, "vmSprite", sprite = cJSON_CreateObject());
cJSON_AddNumberToObject(sprite, "surface", sp->surface);
struct vm_surface *sf = vm_surface_get(sp->surface);
if (sf && sf->cg_no) {
cJSON_AddNumberToObject(sprite, "cg_no", sf->cg_no);
}
cJSON_AddNumberToObject(sprite, "type", sp->type);
cJSON_AddItemToObjectCS(sprite, "rect", rectangle_to_json(&sp->rect, verbose));
cJSON_AddNumberToObject(sprite, "current", sp->current);
cJSON_AddItemToObjectCS(sprite, "children", children = cJSON_CreateArray());
for (int id = id_pool_get_first(&sp->children); id >= 0; id = id_pool_get_next(&sp->children, id)) {
struct child_surface *child = id_pool_get(&sp->children, id);
if (!child)
continue;
cJSON *c;
cJSON_AddItemToArray(children, c = cJSON_CreateObject());
cJSON_AddNumberToObject(c, "surface", child->surface);
cJSON_AddNumberToObject(c, "type", child->type);
cJSON_AddItemToObjectCS(c, "pos", point_to_json(&child->pos, verbose));
}
return ent;
}
static void vm_sprite_delete(struct vm_sprite *sp)
{
if (!sp)
return;
scene_unregister_sprite(&sp->sp);
for (int id = id_pool_get_first(&sp->children); id >= 0; id = id_pool_get_next(&sp->children, id)) {
struct child_surface *child = id_pool_get(&sp->children, id);
if (child)
free(child);
}
if (sp->anime)
free(sp->anime);
id_pool_delete(&sp->children);
free(sp);
}
static void vmSprite_New(possibly_unused void *imainsystem)
{
if (pool.slots)
return; // already initialized
id_pool_init(&pool, ID_POOL_HANDLE_BASE);
}
static int vmSprite_EnumHandle(void)
{
return id_pool_count(&pool);
}
static int vmSprite_Open(int surface, int type, int width, int height)
{
int no = id_pool_get_unused(&pool);
struct vm_sprite *sp = xcalloc(1, sizeof(struct vm_sprite));
id_pool_set(&pool, no, sp);
sp->sp.z = ++default_layer;
sp->sp.has_pixel = true;
sp->sp.hidden = true;
sp->sp.id = no;
sp->sp.render = vm_sprite_render;
sp->sp.to_json = vm_sprite_to_json;
sp->surface = surface;
sp->type = type;
sp->rect.w = width;
sp->rect.h = height;
sp->id = -1;
return no;
}
static int vmSprite_Reopen(int sprite, int surface, int type, int width, int height)
{
struct vm_sprite *sp = id_pool_get(&pool, sprite);
if (!sp)
return 0;
sp->surface = surface;
sp->type = type;
sp->rect.w = width;
sp->rect.h = height;
return sprite;
}
static void vmSprite_Close(int sprite)
{
vm_sprite_delete(id_pool_release(&pool, sprite));
}
static int vmSprite_Release(void)
{
for (int i = id_pool_get_first(&pool); i >= 0; i = id_pool_get_next(&pool, i))
vmSprite_Close(i);
id_pool_delete(&pool);
return 1;
}
static void vmSprite_ModuleFini(void)
{
vmSprite_Release();
}
static int vmSprite_SetLayer(int sprite, int layer)
{
struct vm_sprite *sp = id_pool_get(&pool, sprite);
if (!sp)
return 0;
scene_set_sprite_z(&sp->sp, layer);
return 1;
}
static void vmSprite_SetPos(int sprite, int x, int y)
{
struct vm_sprite *sp = id_pool_get(&pool, sprite);
if (sp) {
vm_sprite_dirty(sp);
sp->rect.x = x;
sp->rect.y = y;
vm_sprite_dirty(sp);
}
}
static int vmSprite_SetCurrent(int sprite, int current)
{
struct vm_sprite *sp = id_pool_get(&pool, sprite);
if (!sp)
return 0;
if (sp->current != current) {
sp->current = current;
vm_sprite_dirty(sp);
}
return 1;
}
static int vmSprite_SetCurrentArray1(struct page *array, int current)
{
if (!array)
return 0;
check_array(array);
for (int i = 0; i < array->nr_vars; i++) {
vmSprite_SetCurrent(array->values[i].i, current);
}
return 1;
}
static int vmSprite_SetCurrentArray2(struct page *sprite_array, struct page *current_array)
{
if (!sprite_array || !current_array)
return 0;
check_array(sprite_array);
check_array(current_array);
if (sprite_array->nr_vars != current_array->nr_vars)
return 0;
for (int i = 0; i < sprite_array->nr_vars; i++) {
vmSprite_SetCurrent(sprite_array->values[i].i, current_array->values[i].i);
}
return 1;
}
static int vmSprite_SetShow(int sprite, int show)
{
struct vm_sprite *sp = id_pool_get(&pool, sprite);
if (!sp)
return 0;
scene_set_sprite_show(&sp->sp, show);
vm_sprite_dirty(sp);
return 1;
}
static int vmSprite_SetShowArray1(struct page *array, int show)
{
if (!array)
return 0;
check_array(array);
for (int i = 0; i < array->nr_vars; i++) {
vmSprite_SetShow(array->values[i].i, show);
}
return 1;
}
static int vmSprite_SetShowArray2(struct page *sprite_array, struct page *show_array)
{
if (!sprite_array || !show_array)
return 0;
check_array(sprite_array);
check_array(show_array);
if (sprite_array->nr_vars != show_array->nr_vars)
return 0;
for (int i = 0; i < sprite_array->nr_vars; i++) {
vmSprite_SetShow(sprite_array->values[i].i, show_array->values[i].i);
}
return 1;
}
static void vmSprite_SetRenewal(int sprite)
{
struct vm_sprite *sp = id_pool_get(&pool, sprite);
if (!sp)
return;
vm_sprite_dirty(sp);
}
static void vmSprite_SetFind(int sprite, int find)
{
struct vm_sprite *sp = id_pool_get(&pool, sprite);
if (sp)
sp->findable = !!find;
}
static void vmSprite_SetID(int sprite, int id)
{
struct vm_sprite *sp = id_pool_get(&pool, sprite);
if (sp)
sp->id = id;
}
static int vmSprite_SetAnime(int sprite, int frame_s, int frame_e, struct page *array)
{
struct vm_sprite *sp = id_pool_get(&pool, sprite);
if (!sp)
return 0;
check_array(array);
if (sp->anime)
free(sp->anime);
int nr_frames = array->nr_vars;
struct animation *a = xmalloc(sizeof(struct animation) + nr_frames * sizeof(int));
a->nr_frames = nr_frames;
a->current_frame = 0;
a->total_frame_time = 0;
for (int i = 0; i < a->nr_frames; i++) {
a->total_frame_time += a->frame_times[i] = array->values[i].i;
}
sp->anime = a;
return 1;
}
static void vmSprite_ResetAnime(int sprite)
{
struct vm_sprite *sp = id_pool_get(&pool, sprite);
if (!sp)
return;
free(sp->anime);
sp->anime = NULL;
}
static int vmSprite_SetChildSurface(int sprite, int num, int surface, int type, int x, int y)
{
struct vm_sprite *sp = id_pool_get(&pool, sprite);
if (!sp)
return 0;
struct child_surface *child = id_pool_get(&sp->children, num);
if (!child) {
child = xcalloc(1, sizeof(struct child_surface));
id_pool_set(&sp->children, num, child);
}
child->surface = surface;
child->type = type;
child->pos.x = x;
child->pos.y = y;
return 1;
}
static int vmSprite_ResetChildSurface(int sprite, int num)
{
struct vm_sprite *sp = id_pool_get(&pool, sprite);
if (!sp)
return 0;
struct child_surface *child = id_pool_release(&sp->children, num);
if (child)
free(child);
return 1;
}
static void vmSprite_Draw(int update)
{
handle_events();
update_animation();
if (scene_is_dirty) {
scene_render();
if (update)
gfx_swap();
scene_is_dirty = false;
dirty_rect = RECT(0, 0, 0, 0);
}
}
static void vmSprite_DrawEffect(int effect, int time)
{
// XXX: This function should only apply the effect to `dirty_rect`, while
// sact_Effect applies the effect to the whole screen. In most cases it
// doesn't make a difference because (1) the effect is no-op for pixels
// where the old and new colors are the same (e.g. crossfade), or (2) the
// whole screen is dirty. In Mamanyonyo, the exception is
// EFFECT_ROTATE_OUT_CW, which must be applied to `dirty_rect` correctly.
if (effect != EFFECT_ROTATE_OUT_CW) {
sact_Effect(effect, time, 0);
return;
}
if (SDL_RectEmpty(&dirty_rect))
return;
uint64_t start = SDL_GetTicks64();
Texture *screen = gfx_main_surface();
Texture base, src;
gfx_init_texture_blank(&src, dirty_rect.w, dirty_rect.h);
gfx_copy(&src, 0, 0, screen, dirty_rect.x, dirty_rect.y, dirty_rect.w, dirty_rect.h);
scene_render();
gfx_copy_main_surface(&base);
uint64_t t = SDL_GetTicks64() - start;
float cx = dirty_rect.x + dirty_rect.w / 2.0f;
float cy = dirty_rect.y + dirty_rect.h / 2.0f;
while (t < time) {
float rate = (float)t / time;
gfx_clear();
gfx_copy(screen, 0, 0, &base, 0, 0, screen->w, screen->h);
gfx_copy_root_zoom2(screen, cx, cy, &src, src.w / 2.0f, src.h / 2.0f, rate * -360, 1.0f - rate);
gfx_swap();
uint64_t t2 = SDL_GetTicks64() - start;
if (t2 < t + 16) {
SDL_Delay(t + 16 - t2);
t += 16;
} else {
t = t2;
}
}
gfx_delete_texture(&base);
gfx_delete_texture(&src);
}
static int vmSprite_AddRect(int x, int y, int width, int height)
{
SDL_Rect r = RECT(x, y, width, height);
SDL_UnionRect(&dirty_rect, &r, &dirty_rect);
scene_dirty();
return 1;
}
//void vmSprite_SetSurface(int hSurface);
static int vmSprite_FindPos(int x, int y)
{
int found = 0;
int z = 0;
Point p = { .x = x, .y = y };
for (int id = id_pool_get_first(&pool); id >= 0; id = id_pool_get_next(&pool, id)) {
struct vm_sprite *sp = id_pool_get(&pool, id);
if (!sp || !sp->findable)
continue;
if (!SDL_PointInRect(&p, &sp->rect))
continue;
if (found && sp->sp.z < z)
continue;
found = id;
z = sp->sp.z;
}
return found;
}
//int vmSprite_FindSprite(int sprite);
static int vmSprite_GetSurface(int sprite)
{
struct vm_sprite *sp = id_pool_get(&pool, sprite);
return sp ? sp->surface : 0;
}
static int vmSprite_GetType(int sprite)
{
struct vm_sprite *sp = id_pool_get(&pool, sprite);
return sp ? sp->type : 0;
}
static int vmSprite_GetWidth(int sprite)
{
struct vm_sprite *sp = id_pool_get(&pool, sprite);
return sp ? sp->rect.w : 0;
}
static int vmSprite_GetHeight(int sprite)
{
struct vm_sprite *sp = id_pool_get(&pool, sprite);
return sp ? sp->rect.h : 0;
}
static int vmSprite_GetLayer(int sprite)
{
struct vm_sprite *sp = id_pool_get(&pool, sprite);
return sp ? sp->sp.z : 0;
}
static int vmSprite_GetX(int sprite)
{
struct vm_sprite *sp = id_pool_get(&pool, sprite);
return sp ? sp->rect.x : 0;
}
static int vmSprite_GetY(int sprite)
{
struct vm_sprite *sp = id_pool_get(&pool, sprite);
return sp ? sp->rect.y : 0;
}
static int vmSprite_GetCurrent(int sprite)
{
struct vm_sprite *sp = id_pool_get(&pool, sprite);
return sp ? sp->current : 0;
}
static int vmSprite_GetShow(int sprite)
{
struct vm_sprite *sp = id_pool_get(&pool, sprite);
return sp ? scene_get_sprite_show(&sp->sp) : 0;
}
//int vmSprite_GetRenewal(int sprite);
static int vmSprite_GetFind(int sprite)
{
struct vm_sprite *sp = id_pool_get(&pool, sprite);
return sp ? sp->findable : 0;
}
static int vmSprite_GetID(int sprite)
{
struct vm_sprite *sp = id_pool_get(&pool, sprite);
return sp ? sp->id : -1;
}
HLL_LIBRARY(vmSprite,
HLL_EXPORT(_ModuleFini, vmSprite_ModuleFini),
HLL_EXPORT(New, vmSprite_New),
HLL_EXPORT(Release, vmSprite_Release),
HLL_EXPORT(EnumHandle, vmSprite_EnumHandle),
HLL_EXPORT(Open, vmSprite_Open),
HLL_EXPORT(Reopen, vmSprite_Reopen),
HLL_EXPORT(Close, vmSprite_Close),
HLL_EXPORT(SetLayer, vmSprite_SetLayer),
HLL_EXPORT(SetPos, vmSprite_SetPos),
HLL_EXPORT(SetCurrent, vmSprite_SetCurrent),
HLL_EXPORT(SetCurrentArray1, vmSprite_SetCurrentArray1),
HLL_EXPORT(SetCurrentArray2, vmSprite_SetCurrentArray2),
HLL_EXPORT(SetShow, vmSprite_SetShow),
HLL_EXPORT(SetShowArray1, vmSprite_SetShowArray1),
HLL_EXPORT(SetShowArray2, vmSprite_SetShowArray2),
HLL_EXPORT(SetRenewal, vmSprite_SetRenewal),
HLL_EXPORT(SetFind, vmSprite_SetFind),
HLL_EXPORT(SetID, vmSprite_SetID),
HLL_EXPORT(SetAnime, vmSprite_SetAnime),
HLL_EXPORT(ResetAnime, vmSprite_ResetAnime),
HLL_EXPORT(SetChildSurface, vmSprite_SetChildSurface),
HLL_EXPORT(ResetChildSurface, vmSprite_ResetChildSurface),
HLL_EXPORT(Draw, vmSprite_Draw),
HLL_EXPORT(DrawEffect, vmSprite_DrawEffect),
HLL_EXPORT(AddRect, vmSprite_AddRect),
HLL_TODO_EXPORT(SetSurface, vmSprite_SetSurface),
HLL_EXPORT(FindPos, vmSprite_FindPos),
HLL_TODO_EXPORT(FindSprite, vmSprite_FindSprite),
HLL_EXPORT(GetSurface, vmSprite_GetSurface),
HLL_EXPORT(GetType, vmSprite_GetType),
HLL_EXPORT(GetWidth, vmSprite_GetWidth),
HLL_EXPORT(GetHeight, vmSprite_GetHeight),
HLL_EXPORT(GetLayer, vmSprite_GetLayer),
HLL_EXPORT(GetX, vmSprite_GetX),
HLL_EXPORT(GetY, vmSprite_GetY),
HLL_EXPORT(GetCurrent, vmSprite_GetCurrent),
HLL_EXPORT(GetShow, vmSprite_GetShow),
HLL_TODO_EXPORT(GetRenewal, vmSprite_GetRenewal),
HLL_EXPORT(GetFind, vmSprite_GetFind),
HLL_EXPORT(GetID, vmSprite_GetID)
);
+88
View File
@@ -0,0 +1,88 @@
/* Copyright (C) 2024 kichikuou <KichikuouChrome@gmail.com>
*
* 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 <stdio.h>
#include <string.h>
#include "system4/string.h"
#include "system4/utfsjis.h"
#include "hll.h"
static int vmString_GetLength(struct string *string)
{
return sjis_count_char(string->text);
}
static int vmString_GetLengthA(struct string *string)
{
return strlen(string->text);
}
static struct string *format_int(int v, int figures, bool zero_pad, bool zenkaku)
{
char buf[32];
int_to_cstr(buf, sizeof(buf), v, figures, zero_pad, zenkaku);
return cstr_to_string(buf);
}
static struct string *vmString_IntToString(int num)
{
return format_int(num, 0, false, true);
}
struct string *vmString_IntToStringA(int num)
{
return format_int(num, 0, false, false);
}
static struct string *vmString_IntToStringEx(int num, int figure, int zero)
{
return format_int(num, figure, zero, true);
}
static struct string *vmString_IntToStringExA(int num, int figure, int zero)
{
return format_int(num, figure, zero, false);
}
//int vmString_StringToInt(struct string *pIString);
//struct string *vmString_FloatToString(float fNum);
//struct string *vmString_FloatToStringA(float fNum);
//float vmString_StringToFloat(struct string *pIString);
//struct string *vmString_GetString(struct string *pIString, int nIndex, int nLength);
//struct string *vmString_CutTag(struct string *pIString);
//void vmString_TransLower(struct string **pIString);
//void vmString_TransUpper(struct string **pIString);
//void vmString_Convert(struct string **pIDString, struct string *pISString, struct string *pICString);
HLL_LIBRARY(vmString,
HLL_EXPORT(GetLength, vmString_GetLength),
HLL_EXPORT(GetLengthA, vmString_GetLengthA),
HLL_EXPORT(IntToString, vmString_IntToString),
HLL_EXPORT(IntToStringA, vmString_IntToStringA),
HLL_EXPORT(IntToStringEx, vmString_IntToStringEx),
HLL_EXPORT(IntToStringExA, vmString_IntToStringExA),
HLL_TODO_EXPORT(StringToInt, vmString_StringToInt),
HLL_TODO_EXPORT(FloatToString, vmString_FloatToString),
HLL_TODO_EXPORT(FloatToStringA, vmString_FloatToStringA),
HLL_TODO_EXPORT(StringToFloat, vmString_StringToFloat),
HLL_TODO_EXPORT(GetString, vmString_GetString),
HLL_TODO_EXPORT(CutTag, vmString_CutTag),
HLL_TODO_EXPORT(TransLower, vmString_TransLower),
HLL_TODO_EXPORT(TransUpper, vmString_TransUpper),
HLL_TODO_EXPORT(Convert, vmString_Convert)
);
+152
View File
@@ -0,0 +1,152 @@
/* Copyright (C) 2024 kichikuou <KichikuouChrome@gmail.com>
*
* 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 <assert.h>
#include "hll.h"
#include "id_pool.h"
#include "vmSurface.h"
static struct id_pool pool;
struct vm_surface *vm_surface_create(int width, int height)
{
int no = id_pool_get_unused(&pool);
struct vm_surface *sf = xcalloc(1, sizeof(struct vm_surface));
id_pool_set(&pool, no, sf);
sf->w = width;
sf->h = height;
sf->has_pixel = true;
sf->has_alpha = true;
sf->no = no;
return sf;
}
struct vm_surface *vm_surface_get(int no)
{
return id_pool_get(&pool, no);
}
void vm_surface_delete(int no)
{
struct vm_surface *sf = id_pool_release(&pool, no);
if (sf) {
gfx_delete_texture(&sf->texture);
free(sf);
}
}
int vm_surface_get_main_surface(void)
{
return ID_POOL_HANDLE_BASE;
}
static void vmSurface_New(void)
{
if (pool.slots)
return; // already initialized
gfx_init();
id_pool_init(&pool, ID_POOL_HANDLE_BASE);
// create main surface
Texture *t = gfx_main_surface();
struct vm_surface *sf = vm_surface_create(t->w, t->h);
sf->texture = *t; // XXX: textures normally shouldn't be copied like this...
assert(sf->no == ID_POOL_HANDLE_BASE);
}
static int vmSurface_Release(void)
{
for (int i = id_pool_get_first(&pool); i >= 0; i = id_pool_get_next(&pool, i))
vm_surface_delete(i);
id_pool_delete(&pool);
return 1;
}
static void vmSurface_ModuleFini(void)
{
vmSurface_Release();
}
static int vmSurface_EnumHandle(void)
{
return id_pool_count(&pool);
}
static int vmSurface_Create(int width, int height, possibly_unused int bpp)
{
struct vm_surface *sf = vm_surface_create(width, height);
gfx_init_texture_rgba(&sf->texture, sf->w, sf->h, (SDL_Color){0, 0, 0, 0});
return sf->no;
}
static int vmSurface_CreatePixelMap(int width, int height, possibly_unused int bpp)
{
struct vm_surface *sf = vm_surface_create(width, height);
gfx_init_texture_rgba(&sf->texture, sf->w, sf->h, (SDL_Color){0, 0, 0, 255});
sf->has_alpha = false;
return sf->no;
}
static int vmSurface_CreateAlphaMap(int width, int height)
{
struct vm_surface *sf = vm_surface_create(width, height);
gfx_init_texture_rgba(&sf->texture, sf->w, sf->h, (SDL_Color){0, 0, 0, 255});
sf->has_pixel = false;
return sf->no;
}
static int vmSurface_GetWidth(int surface)
{
struct vm_surface *sf = id_pool_get(&pool, surface);
return sf ? sf->w : 0;
}
static int vmSurface_GetHeight(int surface)
{
struct vm_surface *sf = id_pool_get(&pool, surface);
return sf ? sf->h : 0;
}
//int vmSurface_GetBpp(int surface);
static int vmSurface_ExistPixel(int surface)
{
struct vm_surface *sf = id_pool_get(&pool, surface);
return sf && sf->has_pixel;
}
static int vmSurface_ExistAlpha(int surface)
{
struct vm_surface *sf = id_pool_get(&pool, surface);
return sf && sf->has_alpha;
}
HLL_LIBRARY(vmSurface,
HLL_EXPORT(_ModuleFini, vmSurface_ModuleFini),
HLL_EXPORT(New, vmSurface_New),
HLL_EXPORT(Release, vmSurface_Release),
HLL_EXPORT(EnumHandle, vmSurface_EnumHandle),
HLL_EXPORT(Create, vmSurface_Create),
HLL_EXPORT(CreatePixelMap, vmSurface_CreatePixelMap),
HLL_EXPORT(CreateAlphaMap, vmSurface_CreateAlphaMap),
HLL_EXPORT(Delete, vm_surface_delete),
HLL_EXPORT(GetWidth, vmSurface_GetWidth),
HLL_EXPORT(GetHeight, vmSurface_GetHeight),
HLL_TODO_EXPORT(GetBpp, vmSurface_GetBpp),
HLL_EXPORT(ExistPixel, vmSurface_ExistPixel),
HLL_EXPORT(ExistAlpha, vmSurface_ExistAlpha)
);
+37
View File
@@ -0,0 +1,37 @@
/* Copyright (C) 2024 kichikuou <KichikuouChrome@gmail.com>
*
* 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_VMSURFACE_H
#define SYSTEM4_HLL_VMSURFACE_H
#include "gfx/gfx.h"
struct vm_surface {
struct texture texture;
int no;
int w;
int h;
bool has_pixel;
bool has_alpha;
int cg_no;
};
struct vm_surface *vm_surface_create(int width, int height);
struct vm_surface *vm_surface_get(int no);
void vm_surface_delete(int no);
int vm_surface_get_main_surface(void);
#endif /* SYSTEM4_HLL_VMSURFACE_H */
+69
View File
@@ -0,0 +1,69 @@
/* Copyright (C) 2024 kichikuou <KichikuouChrome@gmail.com>
*
* 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 <errno.h>
#include <string.h>
#include <time.h>
#include <SDL.h>
#include "system4/string.h"
#include "hll.h"
#include "vm/page.h"
HLL_QUIET_UNIMPLEMENTED( , void, vmSystem, Init, void *imainsystem);
void vmSystem_CurrentTime(struct page **page)
{
struct timespec ts;
if (clock_gettime(CLOCK_REALTIME, &ts) < 0) {
WARNING("clock_gettime failed: %s", strerror(errno));
return;
}
struct tm *tm = localtime(&ts.tv_sec);
if (!tm) {
WARNING("localtime failed: %s", strerror(errno));
return;
}
union vm_value *date = (*page)->values;
date[0].i = tm->tm_year + 1900;
date[1].i = tm->tm_mon + 1;
date[2].i = tm->tm_mday;
date[3].i = tm->tm_hour;
date[4].i = tm->tm_min;
date[5].i = tm->tm_sec;
date[6].i = tm->tm_wday;
}
//void vmSystem_Reset(void);
//void vmSystem_Shutdown(void);
static int vmSystem_OpenWeb(struct string *url)
{
return SDL_OpenURL(url->text) == 0;
}
HLL_WARN_UNIMPLEMENTED(0, int, vmSystem, AddURLMenu, struct string *title, struct string *url);
HLL_LIBRARY(vmSystem,
HLL_EXPORT(Init, vmSystem_Init),
HLL_EXPORT(CurrentTime, vmSystem_CurrentTime),
HLL_TODO_EXPORT(Reset, vmSystem_Reset),
HLL_TODO_EXPORT(Shutdown, vmSystem_Shutdown),
HLL_EXPORT(OpenWeb, vmSystem_OpenWeb),
HLL_EXPORT(AddURLMenu, vmSystem_AddURLMenu)
);
+103
View File
@@ -0,0 +1,103 @@
/* Copyright (C) 2024 kichikuou <KichikuouChrome@gmail.com>
*
* 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 <SDL.h>
#include "hll.h"
#include "id_pool.h"
struct vm_timer {
uint64_t origin;
};
static struct id_pool pool;
static void vmTimer_Init(possibly_unused void *imainsystem)
{
if (pool.slots)
return; // already initialized
id_pool_init(&pool, ID_POOL_HANDLE_BASE);
}
static int vmTimer_EnumHandle(void)
{
return id_pool_count(&pool);
}
static int vmTimer_Open(void)
{
int handle = id_pool_get_unused(&pool);
struct vm_timer *timer = xcalloc(1, sizeof(struct vm_timer));
id_pool_set(&pool, handle, timer);
return handle;
}
static void vmTimer_Close(int handle)
{
struct vm_timer *timer = id_pool_release(&pool, handle);
if (timer)
free(timer);
}
static void vmTimer_ModuleFini(void)
{
for (int i = id_pool_get_first(&pool); i >= 0; i = id_pool_get_next(&pool, i))
vmTimer_Close(i);
id_pool_delete(&pool);
}
static void vmTimer_Set(int handle, int time)
{
struct vm_timer *timer = id_pool_get(&pool, handle);
if (!timer)
return;
timer->origin = SDL_GetTicks64() - time;
}
static int vmTimer_Get(int handle)
{
struct vm_timer *timer = id_pool_get(&pool, handle);
if (!timer)
return 0;
return SDL_GetTicks64() - timer->origin;
}
static void vmTimer_Wait(int time)
{
SDL_Delay(time);
}
static void vmTimer_Pass(int handle, int time)
{
struct vm_timer *timer = id_pool_get(&pool, handle);
if (!timer)
return;
int ms = timer->origin + time - SDL_GetTicks64();
if (ms > 0)
SDL_Delay(ms);
}
HLL_LIBRARY(vmTimer,
HLL_EXPORT(_ModuleFini, vmTimer_ModuleFini),
HLL_EXPORT(Init, vmTimer_Init),
HLL_EXPORT(EnumHandle, vmTimer_EnumHandle),
HLL_EXPORT(Open, vmTimer_Open),
HLL_EXPORT(Close, vmTimer_Close),
HLL_EXPORT(Set, vmTimer_Set),
HLL_EXPORT(Get, vmTimer_Get),
HLL_EXPORT(Wait, vmTimer_Wait),
HLL_EXPORT(Pass, vmTimer_Pass)
);
+50 -6
View File
@@ -15,6 +15,7 @@
*/
#include <assert.h>
#include <stdlib.h>
#include "system4.h"
#include "id_pool.h"
@@ -26,10 +27,18 @@
#define ID_POOL_INIT_SLOTS 32
#define ID_POOL_ALLOC_HEADROOM 256
void id_pool_init(struct id_pool *pool)
void id_pool_init(struct id_pool *pool, int base)
{
pool->slots = xcalloc(ID_POOL_INIT_SLOTS, sizeof(void*));
pool->nr_slots = ID_POOL_INIT_SLOTS;
pool->base = base;
}
void id_pool_delete(struct id_pool *pool)
{
free(pool->slots);
pool->slots = NULL;
pool->nr_slots = 0;
}
static void id_pool_realloc(struct id_pool *pool, int new_size)
@@ -38,26 +47,60 @@ static void id_pool_realloc(struct id_pool *pool, int new_size)
pool->nr_slots = new_size;
}
void id_pool_release(struct id_pool *pool, int id)
void *id_pool_release(struct id_pool *pool, int id)
{
if (pool->slots[id])
pool->slots[id] = NULL;
id -= pool->base;
if (id < 0 || id >= pool->nr_slots)
return NULL;
void *data = pool->slots[id];
pool->slots[id] = NULL;
return data;
}
int id_pool_count(struct id_pool *pool)
{
int count = 0;
for (int i = 0; i < pool->nr_slots; i++) {
if (pool->slots[i])
count++;
}
return count;
}
int id_pool_get_unused(struct id_pool *pool)
{
for (int i = 0; i < pool->nr_slots; i++) {
if (!pool->slots[i])
return i;
return pool->base + i;
}
int id = pool->nr_slots;
id_pool_realloc(pool, id + ID_POOL_ALLOC_HEADROOM);
return id;
return pool->base + id;
}
int id_pool_get_first(struct id_pool *pool)
{
for (int i = 0; i < pool->nr_slots; i++) {
if (pool->slots[i])
return pool->base + i;
}
return -1;
}
int id_pool_get_next(struct id_pool *pool, int id)
{
id -= pool->base;
for (int i = id + 1; i < pool->nr_slots; i++) {
if (pool->slots[i])
return pool->base + i;
}
return -1;
}
void *id_pool_get(struct id_pool *pool, int id)
{
id -= pool->base;
if (id < 0 || id >= pool->nr_slots)
return NULL;
return pool->slots[id];
@@ -65,6 +108,7 @@ void *id_pool_get(struct id_pool *pool, int id)
void *id_pool_set(struct id_pool *pool, int id, void *data)
{
id -= pool->base;
assert(id >= 0);
if (id >= pool->nr_slots)
id_pool_realloc(pool, id + ID_POOL_ALLOC_HEADROOM);
+25
View File
@@ -103,6 +103,8 @@ xsystem4 = [version_h,
'hll/LoadCG.c',
'hll/MainEXFile.c',
'hll/MainSurface.c',
'hll/MamanyoDemo.c',
'hll/MamanyoSDemo.c',
'hll/MarmotModelEngine.c',
'hll/Math.c',
'hll/MapLoader.c',
@@ -127,6 +129,29 @@ xsystem4 = [version_h,
'hll/SystemServiceEx.c',
'hll/Timer.c',
'hll/Toushin3Loader.c',
'hll/vmAnime.c',
'hll/vmArray.c',
'hll/vmCG.c',
'hll/vmChrLoader.c',
'hll/vmCursor.c',
'hll/vmDialog.c',
'hll/vmDrawGauge.c',
'hll/vmDrawMsg.c',
'hll/vmDrawNumber.c',
'hll/vmFile.c',
'hll/vmGraph.c',
'hll/vmGraphQuake.c',
'hll/vmKey.c',
'hll/vmMapLoader.c',
'hll/vmMsgLog.c',
'hll/vmMsgSkip.c',
'hll/vmMusic.c',
'hll/vmSound.c',
'hll/vmSprite.c',
'hll/vmString.c',
'hll/vmSurface.c',
'hll/vmSystem.c',
'hll/vmTimer.c',
'hll/VSFile.c',
]