Skip to content

Instantly share code, notes, and snippets.

@zakki
Last active November 1, 2025 07:03
Show Gist options
  • Select an option

  • Save zakki/36ce9d822f7ee7af1924ceebeb9f7830 to your computer and use it in GitHub Desktop.

Select an option

Save zakki/36ce9d822f7ee7af1924ceebeb9f7830 to your computer and use it in GitHub Desktop.
Fix HSP 3.7 file I/O
diff --git i/hspproj/hsp3/filepack.cpp w/hspproj/hsp3/filepack.cpp
index c03bc83..1f4beba 100644
--- i/hspproj/hsp3/filepack.cpp
+++ w/hspproj/hsp3/filepack.cpp
@@ -244,22 +244,24 @@ int FilePack::pack_fgetc(FILE* ptr)
int FilePack::pack_flength(char* name)
{
+ HFPOBJ* obj;
+ obj = SearchFileObject(name);
+ if (obj) return (int)obj->size;
- HFPOBJ* obj;
- obj = SearchFileObject(name);
- if (obj) return (int)obj->size;
+ int size = hsp3_flength(name);
+ if (size>=0) return size;
- int size = hsp3_flength(name);
- if (size>=0) return size;
-
- FILE* ff = pack_fopen(name);
- if (ff != NULL) {
- if (memfile_active) { // メモリストリーム時
- return memfile.size;
- }
- pack_fclose(ff);
- }
- return -1;
+ FILE* ff = pack_fopen(name);
+ if (ff != NULL) {
+ if (memfile_active) { // メモリストリーム時
+ return memfile.size;
+ }
+ fseek(ff, 0, SEEK_END);
+ size = (int)ftell(ff);
+ pack_fclose(ff);
+ return size;
+ }
+ return -1;
}
diff --git i/hspproj/hsp3/hsp3utfcnv.cpp w/hspproj/hsp3/hsp3utfcnv.cpp
index 023102b..d62dcbc 100644
--- i/hspproj/hsp3/hsp3utfcnv.cpp
+++ w/hspproj/hsp3/hsp3utfcnv.cpp
@@ -264,6 +264,14 @@ FILE *hsp3_fopen(char*name, int offset)
}
#endif
+#ifdef HSPIOS
+ {
+ char* path = gb_filepath(name);
+ printf("Load %s", path);
+ hsp3_fp = fopen(path, "rb");
+ return hsp3_fp;
+ }
+#endif
// Linux
hsp3_fp = fopen(name, "rb");
#ifdef HSPDEBUG
@@ -350,10 +358,11 @@ void hsp3_fclose(FILE* ptr)
int hsp3_flength(char* name)
{
#ifdef HSPIOS
- {
- int length = gb_existdata( name );
- return length;
- }
+ {
+ int length = gb_existdata( name );
+ if (length >= 0)
+ return length;
+ }
#endif
#ifdef HSPNDK
//
// File Pack manager 2
// Copyright 2022- ONION software/onitama
//
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <cctype>
#ifdef HSPWIN
#include <direct.h>
#include "windows.h"
#endif
#if defined(HSPLINUX) || defined(HSPNDK) || defined(HSPIOS)
#include<unistd.h>
#define _getcwd getcwd
#endif
#include "hsp3config.h"
#include "supio.h"
#include "filepack.h"
#include "hsp3crypt.h"
#define _MALLOC malloc
#define _FREE free
#define WELCOMEMSG "DPM2 Manager 1.0"
#define DPMFILEEXT ".dpm"
#define DPMENCODE_DEFVAL 0
/*------------------------------------------------------------*/
/*
UTF8 Util
*/
/*------------------------------------------------------------*/
void FilePack::StrCase(char* str)
{
// strをすべて小文字に(utf8/sjis対応版)
// ('\'を'/'にも変換)
//
unsigned char* p;
unsigned char a1;
p = (unsigned char*)str;
while (1) {
a1 = *p; if (a1 == 0) break;
if (a1 == '\\') a1 = '/';
*p = tolower(a1);
p+=StrCopyLetter((char *)p,NULL); // 検索位置を移動
}
}
void FilePack::StrSplit(char *target, char *fpath, char *filename)
{
// targetをパスとファイル名に分離(utf8/sjis対応版)
//
unsigned char *p;
unsigned char *div;
unsigned char a1;
unsigned char *dst;
int i;
int diff;
fpath[0] = 0;
filename[0] = 0;
p = (unsigned char*)target;
div = p;
while (1) {
a1 = *p; if (a1 == 0) break;
if (a1 == '\\') {
div = p;
}
if (a1 == '/') {
div = p;
}
p += StrCopyLetter((char*)p, NULL); // 検索位置を移動
}
i = 0;
p = (unsigned char*)target;
if (div != p) {
dst = (unsigned char*)fpath;
while (1) {
if (p>div) break;
a1 = *p; if (a1 == 0) break;
diff = StrCopyLetter((char*)p, (char *)dst); // 1文字コピー
p += diff; // 検索位置を移動
dst += diff; // 検索位置を移動
i++;
if ( i>= HFP_NAME_MAX ) break;
}
*dst++ = 0;
}
i = 0;
dst = (unsigned char*)filename;
while (1) {
a1 = *p; if (a1 == 0) break;
diff = StrCopyLetter((char*)p, (char*)dst); // 1文字コピー
p += diff; // 検索位置を移動
dst += diff; // 検索位置を移動
i++;
if (i >= HFP_NAME_MAX) break;
}
*dst++ = 0;
}
/*------------------------------------------------------------*/
/*
constructor
*/
/*------------------------------------------------------------*/
FilePack::FilePack()
{
// 初期化
//
int i;
for(i=0;i<HFP_MAX;i++) {
buf[i] = NULL;
hsp3crypt[i] = NULL;
}
memfile_enable = true;
memfile_active = false;
Reset();
}
FilePack::~FilePack()
{
// すべて破棄
//
Reset();
}
/*------------------------------------------------------------*/
/*
interface (File Service)
*/
/*------------------------------------------------------------*/
void FilePack::pack_memenable(bool sw)
{
memfile_enable = sw;
}
FILE* FilePack::pack_fopen(char* name, int offset)
{
HFPHED* hed;
HFPOBJ* obj;
FILE* ff;
int ofs;
int encode;
filebase = HFP_FILEBASE_NORMAL;
encode = 0;
int i;
i = *(int*)name;
memfile_active = false;
fopen_crypt = 0;
if ((i == 0x3a4d454d) || (i == 0x3a6d656d)) { // 'MEM:'をチェックする
if (memfile_enable == false) {
return NULL;
}
if (memfile.pt == NULL) {
return NULL;
}
memfile_active = true;
filebase = HFP_FILEBASE_MEMFILE;
return (FILE *)name;
}
obj = SearchFileObject(name);
if (obj == NULL) {
filebase = HFP_FILEBASE_NORMAL;
return hsp3_fopen(name,offset);
}
if (offset < 0) return NULL;
hed = GetCurrentHeader();
ofs = hed->filetable + (int)obj->offset;
ofs += offset;
if (curnum == exedpm_slot) {
filebase = HFP_FILEBASE_PACKEXE;
ofs += exedpm_offset;
}
else {
filebase = HFP_FILEBASE_PACKDPM;
}
HSP3Crypt* cm = GetCurrentCryptManager();
ff = hsp3_fopen(cm->GetBasePath(), ofs);
if (ff == NULL) return NULL;
fopen_crypt = obj->crypt;
if (obj->crypt) {
char pathname[HFP_PATH_MAX + 1];
strcpy(pathname, GetFolderName(obj));
strcat(pathname, GetFileName(obj));
int enc_crypt = cm->GetCRC32(pathname, strlen(pathname)); // ファイルパスを暗号キーにする
enc_crypt = cm->GetSalt(enc_crypt);
if (enc_crypt == 0) enc_crypt = 1;
int size = (int)obj->size;
if (enc_crypt != obj->crypt) {
return NULL;
}
cm->DataSet(NULL, size, obj->crypt);
cm->SetOffset(offset);
}
return ff;
}
int FilePack::GetCurrentDPMOffset(void)
{
if (curnum == exedpm_slot) {
return exedpm_offset;
}
return 0;
}
void FilePack::pack_fclose(FILE* ptr)
{
if (memfile_active) {
memfile.pt = NULL;
memfile_active = false;
return;
}
hsp3_fclose(ptr);
}
int FilePack::pack_fgetc(FILE* ptr)
{
int i = 0;
int res = pack_fread(ptr,&i,1);
if (res <= 0) return -1;
return i;
}
int FilePack::pack_flength(char* name)
{
HFPOBJ* obj;
obj = SearchFileObject(name);
if (obj) return (int)obj->size;
int size = hsp3_flength(name);
if (size>=0) return size;
FILE* ff = pack_fopen(name);
if (ff != NULL) {
if (memfile_active) { // メモリストリーム時
return memfile.size;
}
fseek(ff, 0, SEEK_END);
size = (int)ftell(ff);
pack_fclose(ff);
return size;
}
return -1;
}
int FilePack::pack_fread(FILE* ptr, void* mem, int size)
{
int len;
if (ptr == NULL) return -1;
if (memfile_active) {
len = size;
if ((memfile.cur + size) >= memfile.size) len = memfile.size - memfile.cur;
if (len > 0) {
memcpy(mem, memfile.pt + memfile.cur, len);
memfile.cur += len;
}
return len;
}
len = (int)hsp3_fread(ptr, mem, size);
if (filebase == HFP_FILEBASE_NORMAL) {
return len;
}
if (fopen_crypt) {
int i;
unsigned char* p = (unsigned char*)mem;
HSP3Crypt* cm = GetCurrentCryptManager();
for (i = 0; i < len; i++) {
*p = cm->Decrypt(*p);
p++;
}
}
return len;
}
int FilePack::pack_fbase(char* name)
{
FILE* ff = pack_fopen(name);
if (ff == NULL) return -1;
pack_fclose(ff);
return filebase;
}
void FilePack::pack_memfile(void* mem, int size)
{
memfile.pt = (char*)mem;
memfile.cur = 0;
memfile.size = size;
}
void FilePack::pack_getinfstr(char* inf)
{
HFPHED* hed = GetPackHeader(0);
if (hed == NULL) {
*inf = 0;
return;
}
int ofs = 0;
HSP3Crypt* cm = hsp3crypt[0];
if (exedpm_slot == 0) {
ofs = exedpm_offset;
}
sprintf(inf, "%s,%d", cm->GetBasePath(), ofs );
}
/*------------------------------------------------------------*/
/*
interface (read)
*/
/*------------------------------------------------------------*/
void FilePack::Reset( void )
{
int i;
for (i = 0; i < HFP_MAX; i++) {
DeleteSlot(i);
}
curnum = 0;
wrtbuf = NULL;
errbuf = NULL;
wrtstr = NULL;
exedpm_slot = -1;
exedpm_offset = 0;
filebase = 0;
}
void FilePack::DeleteSlot(int slot)
{
int i = slot;
if ((i<0)||(i>=HFP_MAX)) {
return;
}
if (buf[i] != NULL) {
_FREE(buf[i]);
buf[i] = NULL;
}
if (hsp3crypt[i] != NULL) {
delete hsp3crypt[i];
hsp3crypt[i] = NULL;
}
}
int FilePack::GetEmptySlot(void)
{
int i;
for (i = 0; i < HFP_MAX; i++) {
if (buf[i] == NULL) return i;
}
return -1;
}
void FilePack::PrepareRead(int slot, int value)
{
// hsp3cryptを準備する
//
char pwtmp[128];
sprintf(pwtmp, "HSP3Encode:%d", value);
//Print(pwtmp);
DeleteSlot(slot);
hsp3crypt[slot] = new HSP3Crypt();
hsp3crypt[slot]->SetPassword(pwtmp);
}
int FilePack::LoadPackFile( char *fname, int encode, int dpmoffset, int slot)
{
FILE *ff;
HFPHED testhed;
HFPHED *p;
int i;
int hedsize;
char dpmname[HFP_PATH_MAX + 1];
//Print(WELCOMEMSG);
curnum = slot;
if (curnum < 0) {
curnum = GetEmptySlot();
}
if (curnum < 0) return -1;
*dpmname = 0;
#ifdef HSPWIN
if (dpmoffset == 0) {
bool addcurrent = true;
char a1 = *fname;
// fnameがフルパスの場合はパスを補完しない
if ((a1 == 0x5c) || (a1 == '/')) addcurrent = false;
if ((a1 != 0)&&(fname[1]==':')) addcurrent = false;
if (addcurrent) {
_getcwd(dpmname, HFP_PATH_MAX);
strcat(dpmname, "/");
}
}
#endif
strcat(dpmname, fname);
//strcat(dpmname, DPMFILEEXT);
dpmname[HFP_PATH_MAX] = 0;
ff = hsp3_fopen(dpmname, dpmoffset);
if (ff==NULL) return -2;
hsp3_fread(ff, &testhed, sizeof(HFPHED));
hsp3_fclose(ff);
if (dpmoffset > 0) {
exedpm_slot = curnum;
exedpm_offset = dpmoffset;
}
hedsize = testhed.filetable;
if (hedsize < sizeof(HFPHED)) return -2;
p = (HFPHED *)_MALLOC( hedsize );
ff=hsp3_fopen(dpmname, dpmoffset);
if (ff == NULL) {
_FREE(p);
return -2;
}
hsp3_fread( ff, p, hedsize );
hsp3_fclose(ff);
if (( p->h1 != HFP_MAGIC1 )||( p->h2 != HFP_MAGIC2 )||
( p->h3 != HFP_MAGIC3 )||( p->h4 != HFP_MAGIC4 )) {
_FREE( p );
return -3;
}
PrepareRead(curnum, p->seed + encode);
buf[curnum] = p;
HSP3Crypt* cm = GetCurrentCryptManager();
if (encode>0) {
if (p->salt != cm->GetSalt(encode + p->seed)) {
return -4;
}
}
cm->SetBasePath(dpmname);
HFPOBJ* obj;
obj = GetCurrentObjectHeader();
for (i = 0; i < p->max_file; i++) {
obj->slot = curnum;
obj++;
}
return 0;
}
/*------------------------------------------------------------*/
/*
interface (info)
*/
/*------------------------------------------------------------*/
int FilePack::GetPackSlot( void )
{
return curnum;
}
HFPHED *FilePack::GetPackHeader( int slot )
{
if (( slot < 0 )||( slot >= HFP_MAX)) return NULL;
return buf[slot];
}
HFPHED* FilePack::GetCurrentHeader(void)
{
return GetPackHeader(curnum);
}
HFPOBJ* FilePack::GetCurrentObjectHeader(void)
{
HFPHED *hed = GetCurrentHeader();
HFPOBJ* obj = (HFPOBJ*)(hed + 1);
return obj;
}
HSP3Crypt *FilePack::GetCurrentCryptManager(void)
{
return (hsp3crypt[curnum]);
}
int FilePack::GetFileNum( HFPHED *hed )
{
return hed->max_file;
}
char *FilePack::GetPackName( HFPHED *hed )
{
char *strbase;
strbase = ((char *)hed) + hed->strtable;
return strbase + hed->myname;
}
HFPOBJ* FilePack::GetFileObject(HFPHED* hed, int id)
{
HFPOBJ* obj;
if ((id < 0) || (id >= hed->max_file)) return NULL;
obj = (HFPOBJ*)(hed + 1);
return &obj[id];
}
char* FilePack::GetString(HFPHED* hed, int ptr)
{
HFPHED* p = hed;
if (p == NULL) return NULL;
char* strbase = ((char*)p) + p->strtable;
return strbase + ptr;
}
char* FilePack::GetFileName(HFPOBJ* obj)
{
HFPHED* p = GetPackHeader(curnum);
return GetString(p, obj->name);
}
char* FilePack::GetFolderName(HFPOBJ* obj)
{
HFPHED* p = GetPackHeader(curnum);
if (obj->folder == 0) return "";
return GetString(p, obj->folder);
}
int FilePack::GetFileSize(char* name)
{
HFPOBJ* obj;
obj = SearchFileObject(name);
if (obj != NULL) {
return (int)obj->size;
}
return -1;
}
HFPOBJ *FilePack::SearchFileObject( HFPHED *hed, char *name )
{
// ファイル情報を検索する
//
int i;
HFPOBJ *obj;
char fname[HFP_PATH_MAX + 1];
char fname_utf8[HFP_PATH_MAX + 1];
char foldername[HFP_PATH_MAX + 1];
char foldername_utf8[HFP_PATH_MAX + 1];
if (hed == NULL) return NULL;
StrSplit(name, foldername, fname); // Split Path and File Name
StrCase(fname);
StrCase(foldername);
// UTF8に変換する
hsp3_to_utf8(fname_utf8, fname, HFP_PATH_MAX);
hsp3_to_utf8(foldername_utf8, foldername, HFP_PATH_MAX);
obj = (HFPOBJ *)(hed+1);
for(i=0;i<hed->max_file;i++) {
bool fchk = true;
if (obj->folder != 0) {
if (strcmp(foldername_utf8, GetFolderName(obj)) != 0) fchk = false;
}
else {
if (*foldername != 0) fchk = false;
}
if (fchk) {
if (strcmp(fname_utf8, GetFileName(obj)) == 0) return obj;
}
obj++;
}
return NULL;
}
HFPOBJ* FilePack::SearchFileObject(char* name)
{
int i;
HFPOBJ* obj;
int baknum = GetPackSlot();
for (i = 0; i < HFP_MAX; i++) {
HFPHED* hed = buf[i];
if (hed) {
SetCurrentSlot(i);
obj = SearchFileObject(hed, name);
if (obj != NULL) {
return obj;
}
}
}
SetCurrentSlot(baknum);
return NULL;
}
int FilePack::pack_fread(char* name, void* mem, int size, int seekofs)
{
FILE *pt = pack_fopen(name, seekofs);
if (pt == NULL) {
return hsp3_rawload(name, mem, size, seekofs);
}
int len = pack_fread(pt, mem, size);
pack_fclose(pt);
return len;
}
/*------------------------------------------------------------*/
/*
interface (stream)
*/
/*------------------------------------------------------------*/
DpmFile::DpmFile()
{
filebase = -1;
_file = NULL;
filepack = NULL;
}
DpmFile::~DpmFile()
{
close();
}
bool DpmFile::open(FilePack* pack, char* fname)
{
HFPHED* hed;
HFPOBJ* obj;
FILE* ff;
int ofs, ofs2;
filepack = pack;
if (filepack == NULL) return false;
cur = 0;
size = 0;
_file = NULL;
endflag = false;
baseoffset = 0;
fopen_crypt = 0;
obj = filepack->SearchFileObject(fname);
if (obj == NULL) {
ff = hsp3_fopen(fname, 0);
if (ff == NULL) {
return false;
}
_file = ff;
filebase = HFP_FILEBASE_NORMAL;
return true;
}
hed = filepack->GetCurrentHeader();
ofs = hed->filetable + (int)obj->offset;
ofs2 = filepack->GetCurrentDPMOffset();
baseoffset = ofs + ofs2;
if (ofs2>0) {
filebase = HFP_FILEBASE_PACKEXE;
}
else {
filebase = HFP_FILEBASE_PACKDPM;
}
crypt = filepack->GetCurrentCryptManager();
ff = hsp3_fopen(crypt->GetBasePath(), baseoffset );
if (ff == NULL) {
filebase = -1;
return false;
}
fopen_crypt = obj->crypt;
size = (int)obj->size;
if (obj->crypt) {
char pathname[HFP_PATH_MAX + 1];
strcpy(pathname, filepack->GetFolderName(obj));
strcat(pathname, filepack->GetFileName(obj));
int enc_crypt = crypt->GetCRC32(pathname, strlen(pathname)); // ファイルパスを暗号キーにする
enc_crypt = crypt->GetSalt(enc_crypt);
if (enc_crypt == 0) enc_crypt = 1;
if (enc_crypt != obj->crypt) {
filebase = -1;
return false;
}
crypt->DataSet(NULL, size, obj->crypt);
crypt->SetOffset(0);
}
_file = ff;
return true;
}
void DpmFile::close(void)
{
if (filepack == NULL) return;
if (_file) {
hsp3_fclose(_file);
_file = NULL;
}
filebase = -1;
filepack = NULL;
endflag = true;
}
size_t DpmFile::read(void* mem, size_t sz, size_t count)
{
int readsize = (int)(sz * count);
int len;
if ((filepack == NULL)||(_file == NULL)) return -1;
len = (int)hsp3_fread(_file, mem, readsize);
if ( len <= 0 ) {
len = 0;
endflag = true;
}
if (filebase == HFP_FILEBASE_NORMAL) {
cur += len;
return (size_t)(len/sz);
}
if (fopen_crypt) {
int i;
unsigned char* p = (unsigned char*)mem;
crypt->DataSet(NULL, size, fopen_crypt);
crypt->SetOffset(cur);
for (i = 0; i < len; i++) {
*p = crypt->Decrypt(*p);
p++;
}
}
cur += len;
if (cur >= size) {
endflag = true;
cur = size;
}
return (size_t)(len/sz);
}
char* DpmFile::readLine(char* str, int num)
{
if ((filepack == NULL) || (_file == NULL)) return NULL;
/*
if (filebase == HFP_FILEBASE_NORMAL) {
char *res = fgets(str, num, _file);
Alertf("Read ok[%s]",res);
if (res) {
cur += strlen(str);
} else {
endflag = true;
}
return res;
}
*/
if (fopen_crypt) {
crypt->DataSet(NULL, size, fopen_crypt);
crypt->SetOffset(cur);
}
int i = num-1;
char* p = str;
int a1=0;
if ((p == NULL)||(num<1)) return NULL;
while (1) {
if (i <= 0) break;
if (size>0) {
if ( cur>=size ) break;
}
int res = hsp3_fread(_file, &a1, 1);
if ( res <= 0 ) {
endflag = true;
break;
}
cur++;
i--;
if (fopen_crypt) {
a1 = crypt->Decrypt(a1);
}
*p++ = (char)a1;
if (a1 == 10) {
break;
}
}
*p = 0;
return str;
}
bool DpmFile::rewind(void)
{
if ((filepack == NULL) || (_file == NULL)) return false;
//if (filebase == HFP_FILEBASE_NORMAL) {
// ::rewind(_file);
// return true;
//}
seek(0, SEEK_SET);
return true;
}
bool DpmFile::seek(int offset, int origin)
{
if ((filepack == NULL) || (_file == NULL)) return false;
//if (filebase == HFP_FILEBASE_NORMAL) {
//Alertf("SEEK:%d", offset);
//return hsp3_fseek(_file, offset, origin) == 0;
//}
int newpos;
switch (origin) {
case SEEK_CUR:
newpos = cur;
break;
case SEEK_END:
newpos = size;
break;
default:
newpos = 0;
break;
}
cur = newpos + offset;
if (cur < 0) {
cur = 0;
}
if (size > 0) {
if (cur >= size) {
cur = size;
endflag = true;
}
}
if (filebase == HFP_FILEBASE_NORMAL) {
return hsp3_fseek(_file, cur, SEEK_SET) == 0;
}
hsp3_fseek(_file, baseoffset+cur, SEEK_SET);
return true;
}
bool DpmFile::eof(void)
{
if ((filepack == NULL) || (_file == NULL)) return true;
if (filebase == HFP_FILEBASE_NORMAL) {
//int res = feof(_file);
//Alertf("eof %d",res);
//if (res) return true;
//return ((size_t)position()) >= length();
return endflag;
}
if (cur>=size) return true;
return false;
}
int DpmFile::position(void)
{
if ((filepack == NULL) || (_file == NULL)) return -1;
//if (filebase == HFP_FILEBASE_NORMAL) {
// return ftell(_file);
//}
return cur;
}
size_t DpmFile::length(void)
{
if ((filepack == NULL) || (_file == NULL)) return -1;
if (filebase == HFP_FILEBASE_NORMAL) {
if ( size == 0 ) {
}
return (size_t)size;
}
return (size_t)size;
}
//
// hsp3utfcnv.cpp functions
//
#include "hsp3config.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char* hsp3ext_getdir(int id);
#ifdef HSPWIN
#include <windows.h>
#include <tchar.h>
#endif
#include <ctype.h>
#ifdef HSPIOS
#include "iOSBridge.h"
#include "../hsp3dish/ios/appengine.h"
#endif
#ifdef HSPNDK
#include "../hsp3dish/hgio.h"
#include "../appengine.h"
#include "../javafunc.h"
#endif
#include "hsp3utfcnv.h"
#ifdef HSPWIN
#include "hsp3config.h"
#include "supio.h"
#include "hsp3ext.h"
//
// 変換用のテンポラリ
//
#define HSP3CNV_DEFSIZE 0x8000
static char* hsp3cnv_tmp = NULL;
static int hsp3cnv_tmpsize = 0;
static void hsp3cnv_cleartmp(void)
{
if (hsp3cnv_tmp) {
free(hsp3cnv_tmp);
hsp3cnv_tmp = NULL;
}
hsp3cnv_tmpsize = 0;
}
static char* hsp3cnv_gettmp(int size)
{
int newsize = size + 1;
if (newsize < HSP3CNV_DEFSIZE) {
newsize = HSP3CNV_DEFSIZE;
}
if (newsize > hsp3cnv_tmpsize) {
hsp3cnv_cleartmp();
hsp3cnv_tmpsize = newsize;
hsp3cnv_tmp = (char *)malloc(hsp3cnv_tmpsize);
}
return hsp3cnv_tmp;
}
//
// API用の文字エンコードへ変換
//
#ifdef HSPUTF8
HSPAPICHAR *chartoapichar( const char *orig,HSPAPICHAR **pphac)
{
int reslen;
wchar_t *resw;
if (orig == 0) {
*pphac = 0;
return 0;
}
reslen = MultiByteToWideChar(CP_UTF8,0,orig,-1,(LPWSTR)NULL,0);
resw = (wchar_t*)calloc(reslen+1,sizeof(wchar_t));
MultiByteToWideChar(CP_UTF8,0,orig,-1,resw,reslen);
*pphac = resw;
return resw;
}
void freehac(HSPAPICHAR **pphac)
{
free(*pphac);
*pphac = 0;
}
HSPCHAR *apichartohspchar( const HSPAPICHAR *orig,HSPCHAR **pphc)
{
int plen;
HSPCHAR *p = 0;
if (orig == 0) {
*pphc = 0;
return 0;
}
plen=WideCharToMultiByte(CP_UTF8,NULL,orig,-1,NULL,0,NULL,NULL);
p = (HSPCHAR *)calloc(plen+1,sizeof(HSPCHAR*));
WideCharToMultiByte(CP_UTF8,NULL,orig,-1,p,plen,NULL,NULL);
*pphc = p;
return p;
}
void freehc(HSPCHAR **pphc)
{
free(*pphc);
*pphc = 0;
}
HSPAPICHAR *ansichartoapichar(const char *orig, HSPAPICHAR **pphac)
{
int reslen;
wchar_t *resw;
if (orig == 0) {
*pphac = 0;
return 0;
}
reslen = MultiByteToWideChar(CP_ACP, 0, orig, -1, (LPWSTR)NULL, 0);
resw = (wchar_t*)calloc(reslen + 1, sizeof(wchar_t));
MultiByteToWideChar(CP_ACP, 0, orig, -1, resw, reslen);
*pphac = resw;
return resw;
}
char *apichartoansichar(const HSPAPICHAR *orig, char **ppac)
{
int plen;
HSPCHAR *p = 0;
if (orig == 0) {
*ppac = 0;
return 0;
}
plen = WideCharToMultiByte(CP_ACP, NULL, orig, -1, NULL, 0, NULL, NULL);
p = (char *)calloc(plen + 1, sizeof(char*));
WideCharToMultiByte(CP_ACP,NULL, orig, -1, p, plen, NULL, NULL);
*ppac = p;
return p;
}
void freeac(char **ppac)
{
free(*ppac);
*ppac = 0;
}
#else
HSPAPICHAR *chartoapichar( const char *orig,HSPAPICHAR **pphac)
{
*pphac = (HSPAPICHAR*)orig;
return (HSPAPICHAR*)orig;
}
void freehac(HSPAPICHAR **pphac)
{
*pphac = 0;
return;
}
HSPCHAR *apichartohspchar( const HSPAPICHAR *orig,HSPCHAR **pphc)
{
*pphc = (HSPAPICHAR*)orig;
return (HSPCHAR*)orig;
}
void freehc(HSPCHAR **pphc)
{
*pphc = 0;
return;
}
HSPAPICHAR *ansichartoapichar(const char *orig, HSPAPICHAR **pphac)
{
*pphac = (HSPAPICHAR*)orig;
return (HSPAPICHAR*)orig;
}
char *apichartoansichar(const HSPAPICHAR *orig, char **ppc)
{
*ppc = (char*)orig;
return (char*)orig;
}
void freeac(char **ppc)
{
*ppc = 0;
return;
}
#endif
#endif
//
// basic File I/O support
//
FILE *hsp3_fopen(char*name, int offset)
{
FILE* hsp3_fp = NULL;
#ifdef HSPWIN
#ifdef HSPUTF8
HSPAPICHAR* hactmp1;
#endif
#ifdef HSPUTF8
// Windows UTF
hsp3_fp = _wfopen(chartoapichar(name, &hactmp1), L"rb");
freehac(&hactmp1);
#else
// Windows SJIS
hsp3_fp = fopen(name, "rb");
#endif
// Read HSPTV resource
#ifdef HSPDEBUG
if (hsp3_fp == NULL) {
// hsptvフォルダを検索する
char fn[2048];
TCHAR fporg[_MAX_PATH];
TCHAR fporg_tmp[_MAX_PATH];
char* resp8;
GetModuleFileName(NULL, fporg, _MAX_PATH);
getpathW(fporg, fporg_tmp, 32);
apichartohspchar(fporg_tmp, &resp8);
strcpy(fn, resp8);
CutLastChr(fn, '\\');
freehc(&resp8);
strcat(fn, "\\hsptv\\");
if ((strlen(name) + strlen(fn)) < 2047) {
strcat(fn, name);
#ifdef HSPUTF8
// Windows UTF
hsp3_fp = _wfopen(chartoapichar(fn, &hactmp1), L"rb");
#else
// Windows SJIS
hsp3_fp = fopen(fn, "rb");
#endif
}
}
#endif
#else
#ifdef HSPNDK
{
char *fname = name;
if ( *name == '*' ) {
fname = hgio_getstorage(name+1);
}
hsp3_fp = hgio_android_fopen(fname,offset);
if (hsp3_fp == NULL) return NULL;
return hsp3_fp;
}
#endif
#ifdef HSPIOS
{
char* path = gb_filepath(name);
printf("Load %s", path);
hsp3_fp = fopen(path, "rb");
return hsp3_fp;
}
#endif
// Linux
hsp3_fp = fopen(name, "rb");
#ifdef HSPDEBUG
if (hsp3_fp == NULL) {
// hsptvフォルダを検索する
char fn[2048];
strcpy(fn, hsp3ext_getdir(5)); // tv folder
strcat(fn, name);
hsp3_fp = fopen(fn, "rb");
}
#endif
#endif
if (hsp3_fp == NULL) return NULL;
if (offset > 0) {
fseek(hsp3_fp, offset, SEEK_SET);
}
return hsp3_fp;
}
FILE* hsp3_fopenwrite(char* fname8, int offset)
{
FILE* hsp3_fp = NULL;
#ifdef HSPWIN
#ifdef HSPUTF8
// Windows UTF
HSPAPICHAR* fnamew = 0;
if (offset < 0) {
hsp3_fp = _tfopen(chartoapichar(fname8, &fnamew), TEXT("wb"));
}
else {
hsp3_fp = _tfopen(chartoapichar(fname8, &fnamew), TEXT("r+b"));
}
freehac(&fnamew);
#else
// Windows SJIS
if (offset < 0) {
hsp3_fp = fopen(fname8, "w+b");
}
else {
hsp3_fp = fopen(fname8, "r+b");
if (hsp3_fp == NULL) return NULL;
fseek(hsp3_fp, offset, SEEK_SET);
}
#endif
#else
char *fname;
fname = fname8;
#ifdef HSPNDK
if ( *fname != '/' ) {
fname = hgio_getstorage(fname8);
}
#endif
// Linux
if (offset < 0) {
hsp3_fp = fopen(fname, "w+b");
}
else {
hsp3_fp = fopen(fname, "r+b");
if (hsp3_fp == NULL) return NULL;
fseek(hsp3_fp, offset, SEEK_SET);
}
#endif
return hsp3_fp;
}
void hsp3_fclose(FILE* ptr)
{
#ifdef HSPNDK
{
return hgio_android_fclose(ptr);
}
#endif
fclose(ptr);
}
int hsp3_flength(char* name)
{
#ifdef HSPIOS
{
int length = gb_existdata( name );
if (length >= 0)
return length;
}
#endif
#ifdef HSPNDK
{
int length = hgio_file_exist( name );
if ( length>=0 ) return length;
char *fname = name;
if ( *fname != '/' ) {
fname = hgio_getstorage(name);
}
FILE* fp = fopen(fname, "rb");
if (fp) {
fseek(fp, 0, SEEK_END);
int length = (int)ftell(fp);
fclose(fp);
return length;
}
}
#endif
FILE* hsp3_fp = hsp3_fopen(name, 0);
if (hsp3_fp ==NULL) {
return -1;
}
fseek(hsp3_fp, 0, SEEK_END);
int length = (int)ftell(hsp3_fp); // normal file size
hsp3_fclose(hsp3_fp);
return length;
}
int hsp3_fread( FILE* ptr, void *mem, int size )
{
if (ptr == NULL) return -1;
if (mem == NULL) return -1;
if (size <= 0) return 0;
#ifdef HSPNDK
{
return hgio_android_fread(ptr,mem,size);
}
#endif
int len = (int)fread(mem, 1, size, ptr);
return len;
}
int hsp3_fseek(FILE* ptr, int offset, int whence)
{
if (ptr == NULL) return -1;
#ifdef HSPNDK
{
return hgio_android_seek(ptr,offset,whence);
}
#endif
return fseek(ptr,offset,whence);
}
int hsp3_binsave( char *fname8, void *mem, int msize, int seekofs )
{
FILE* hsp3_fp = hsp3_fopenwrite( fname8, seekofs );
if (hsp3_fp == NULL) return -1;
int flen = (int)fwrite( mem, 1, msize, hsp3_fp);
#ifdef HSPNDK
fclose(hsp3_fp);
return flen;
#endif
hsp3_fclose(hsp3_fp);
#ifdef HSPWIN
_fcloseall();
#endif
return flen;
}
int hsp3_rawload(char* name, void* mem, int size, int seekofs)
{
#ifdef HSPNDK
char *fname = name;
if ( *fname != '/' ) {
fname = hgio_getstorage(name);
}
FILE* fp = fopen(fname, "rb");
if (fp==NULL) return -1;
if (seekofs > 0) {
fseek(fp, seekofs, SEEK_SET);
}
int len = (int)fread(mem, 1, size, fp);
fclose(fp);
return len;
#endif
return -1;
}
//
// UTF Conversion Service (Windows Only)
//
#ifdef HSPWIN
int hsp3_to_utf16(void* out, char* in, int bufsize)
{
// hspchar->UTF16 に変換
//
#ifdef HSPUTF8
return MultiByteToWideChar(CP_UTF8, 0, in, -1, (LPWSTR)out, bufsize);
#else
return MultiByteToWideChar(CP_ACP, 0, in, -1, (LPWSTR)out, bufsize);
#endif
}
int utf16_to_hsp3(char* out, void* in, int bufsize)
{
// UTF16->hspchar に変換
//
#ifdef HSPUTF8
return WideCharToMultiByte(CP_UTF8, 0, (LPCWSTR)in, -1, (LPSTR)out, bufsize, NULL, NULL);
#else
return WideCharToMultiByte(CP_ACP, 0, (LPCWSTR)in, -1, (LPSTR)out, bufsize, NULL, NULL);
#endif
}
#endif
int hsp3_to_utf8(void* out, char* in, int bufsize)
{
// hspchar->UTF8 に変換
//
#ifdef HSPWIN
#ifdef HSPUTF8
strncpy((char*)out, in, bufsize);
return -1;
#else
int reslen = MultiByteToWideChar(CP_ACP, 0, in, -1, (LPWSTR)NULL, 0);
char* tmpbuf = hsp3cnv_gettmp(reslen);
MultiByteToWideChar(CP_ACP, 0, in, -1, (LPWSTR)tmpbuf, hsp3cnv_tmpsize);
return WideCharToMultiByte(CP_UTF8, 0, (LPWSTR)tmpbuf, -1, (LPSTR)out, bufsize, NULL, NULL);
#endif
#else
strncpy((char*)out, in, bufsize);
return -1;
#endif
}
int utf8_to_hsp3(void* out, char* in, int bufsize)
{
// UTF8->hspchar に変換
//
#ifdef HSPWIN
#ifdef HSPUTF8
strncpy((char*)out, in, bufsize);
return -1;
#else
int reslen = MultiByteToWideChar(CP_UTF8, 0, in, -1, (LPWSTR)NULL, 0);
char* tmpbuf = hsp3cnv_gettmp(reslen);
MultiByteToWideChar(CP_UTF8, 0, in, -1, (LPWSTR)tmpbuf, hsp3cnv_tmpsize);
return WideCharToMultiByte(CP_ACP, 0, (LPCWSTR)tmpbuf, -1, (LPSTR)out, bufsize, NULL, NULL);
#endif
#else
strncpy((char*)out, in, bufsize);
return -1;
#endif
}
int StrCopyLetter(char* source, char* dest)
{
// 1文字をコピー(utf8/sjis対応版)
// (移動したbyte数を返します)
//
unsigned char a1;
unsigned char* p = (unsigned char*)source;
unsigned char* dst = (unsigned char*)dest;
int i = 1;
a1 = *p;
#ifdef HSPUTF8
if (a1 >= 128) { // 多バイト文字チェック
if (a1 >= 192) i++;
if (a1 >= 224) i++;
if (a1 >= 240) i++;
if (a1 >= 248) i++;
if (a1 >= 252) i++;
}
#else
if (a1 >= 129) {
if ((a1 <= 159) || (a1 >= 224)) i++;
}
#endif
if (dst) {
int j = 0;
while (1) {
if (j >= i) break;
*dst = *p;
dst++;
p++;
j++;
}
}
return i;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment