Skip to content

Commit 8ff4c8d

Browse files
committed
feat: add -read-file-utf8 option
1 parent f99490d commit 8ff4c8d

File tree

12 files changed

+446
-192
lines changed

12 files changed

+446
-192
lines changed

CHANGELOG.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,10 @@
1+
# run68x 2.0.0 (2024-03-09)
2+
3+
* ファイル読み込み時のエンコーディング変換を追加(`-read-file-utf8`)。
4+
* `DOS _BUS_ERR`を実装した。
5+
* `ADDX -(Ay),-(Ax)``SUBX -(Ay),-(Ax)`命令を実装した。
6+
7+
18
# run68x 1.4.0 (2024-03-01)
29

310
新機能

README.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ run68の改造版です。
1313
* `-f` ... ファンクションコールトレース
1414
* `-tr <adr>` ... MPU命令トラップ
1515
* `-d` ... 簡易デバッガ起動
16+
* `-read-file-utf8` ... ファイル読み込み時にUTF-8からシフトJISに変換
1617

1718

1819
### run68.ini
@@ -44,6 +45,22 @@ run68の改造版です。
4445
容量を超える部分は(メインメモリが見えるのではなく)バスエラーになります。
4546

4647

48+
### ファイル読み込み時のエンコーディング変換
49+
50+
実験的な機能です。
51+
52+
`-read-file-utf8`オプションを指定すると、読み込みモードで開いたファイルから内容を
53+
読み込むときに、エンコーディングをUTF-8からシフトJISに変換します。
54+
55+
すべてのファイル読み込みに適用されるため、UTF-8以外で記述されたファイルや
56+
バイナリファイルでは正しく内容を読み取ることができなくなります。
57+
58+
読み書きモードで開いたファイルや、新規作成したファイルは変換されません。
59+
また、ファイルの書き込み時には変換されません。
60+
61+
現在の実装では、変換に失敗した場合は変換せずに続行します。
62+
63+
4764
## Build
4865
Windows (Visual Studio 2022、x64)、WSL上のUbuntu 22.04でのみ確認しています。
4966
なにか問題があれば報告してください。

src/dos_file.c

Lines changed: 103 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,19 @@
2525
#include "mem.h"
2626
#include "run68.h"
2727

28+
static Long readFile(FILEINFO* finfop, char* buffer, ULong length) {
29+
if (!finfop->onmemory.buffer)
30+
return HOST_READ_FILE_OR_TTY(finfop, buffer, length);
31+
32+
ULong rest = (ULong)(finfop->onmemory.length - finfop->onmemory.position);
33+
ULong len = (rest < length) ? rest : length;
34+
35+
memcpy(buffer, finfop->onmemory.buffer + finfop->onmemory.position, len);
36+
finfop->onmemory.position += len;
37+
38+
return len;
39+
}
40+
2841
// DOS _READ
2942
Long Read(UWord fileno, ULong buffer, ULong length) {
3043
// Human68k v3.02ではファイルのエラー検査より先にバイト数が0か調べている
@@ -40,7 +53,7 @@ Long Read(UWord fileno, ULong buffer, ULong length) {
4053
if (!GetWritableMemoryRangeSuper(buffer, length, &mem))
4154
throwBusErrorOnWrite(buffer); // バッファアドレスが不正
4255

43-
Long result = HOST_READ_FILE_OR_TTY(finfop, mem.bufptr, mem.length);
56+
Long result = readFile(finfop, mem.bufptr, mem.length);
4457
if (result <= 0) return result;
4558
if (length == mem.length) return result; // バッファが全域有効なら完了
4659

@@ -55,7 +68,7 @@ Long Read(UWord fileno, ULong buffer, ULong length) {
5568

5669
// 試しに追加で1バイト読み込んでみる
5770
char dummy;
58-
Long result2 = HOST_READ_FILE_OR_TTY(finfop, &dummy, 1);
71+
Long result2 = readFile(finfop, &dummy, 1);
5972
if (result2 < 0) return result2;
6073

6174
// ファイル末尾に達していたら、最初の読み込みでちょうど終わっていた
@@ -65,6 +78,31 @@ Long Read(UWord fileno, ULong buffer, ULong length) {
6578
throwBusErrorOnWrite(buffer + mem.length);
6679
}
6780

81+
static Long seekOnmemoryFile(FILEINFO* finfop, Long offset, FileSeekMode mode) {
82+
Long base = (mode == SEEKMODE_SET) ? 0
83+
: (mode == SEEKMODE_CUR) ? finfop->onmemory.position
84+
: finfop->onmemory.length;
85+
Long pos = base + offset;
86+
87+
if (pos < 0 || pos > finfop->onmemory.length) return DOSE_CANTSEEK;
88+
89+
finfop->onmemory.position = pos;
90+
return pos;
91+
}
92+
93+
// DOS _SEEK (0xff42)
94+
Long Seek(UWord fileno, Long offset, UWord mode) {
95+
if (fileno >= FILE_MAX) return DOSE_MFILE;
96+
97+
FILEINFO* finfop = &finfo[fileno];
98+
if (!finfop->is_opened) return DOSE_BADF;
99+
100+
if (mode > SEEKMODE_END) return DOSE_ILGPARM;
101+
102+
return finfop->onmemory.buffer ? seekOnmemoryFile(finfop, offset, mode)
103+
: HOST_SEEK_FILE(finfop, offset, mode);
104+
}
105+
68106
// Human68kにおける2バイト文字の1バイト目の文字コードか
69107
// Shift_JIS-2004 ... 0x81~0x9f、0xe0~0xfc
70108
// Human68kの実際の動作 ... 0x80~0x9f、0xe0~0xff
@@ -139,3 +177,66 @@ Long Maketmp(ULong path, UWord atr) {
139177
// 加算できたらファイル作成を再試行する
140178
}
141179
}
180+
181+
static OnmemoryFileData defaultOnmemoryFileData(void) {
182+
return (OnmemoryFileData){NULL, 0, 0};
183+
}
184+
185+
// finfoを初期化する。
186+
void ClearFinfo(int fileno) {
187+
FILEINFO* f = &finfo[fileno];
188+
189+
f->host = (HostFileInfoMember){0};
190+
f->is_opened = false;
191+
f->mode = OPENMODE_READ;
192+
f->nest = 0;
193+
f->onmemory = defaultOnmemoryFileData();
194+
}
195+
196+
// オープンしたファイルの情報をfinfoに書き込む。
197+
FILEINFO* SetFinfo(int fileno, HostFileInfoMember hostfile, FileOpenMode mode,
198+
unsigned int nest) {
199+
FILEINFO* f = &finfo[fileno];
200+
201+
f->host = hostfile;
202+
f->is_opened = true;
203+
f->mode = mode;
204+
f->nest = nest_cnt;
205+
f->onmemory = defaultOnmemoryFileData();
206+
207+
return f;
208+
}
209+
210+
void FreeOnmemoryFile(FILEINFO* finfop) {
211+
if (!finfop->onmemory.buffer) return;
212+
213+
free(finfop->onmemory.buffer);
214+
finfop->onmemory.buffer = NULL;
215+
}
216+
217+
void ReadOnmemoryFile(FILEINFO* finfop, FileOpenMode openMode) {
218+
if (openMode != OPENMODE_READ || !settings.readFileUtf8) return;
219+
220+
Long fileSize = HOST_SEEK_FILE(finfop, 0, SEEKMODE_END);
221+
HOST_SEEK_FILE(finfop, 0, SEEKMODE_SET);
222+
if (fileSize < 0) return;
223+
224+
char* u8buf = malloc(fileSize);
225+
if (!u8buf) return;
226+
227+
Long readSize = (Long)HOST_READ_FILE_OR_TTY(finfop, u8buf, fileSize);
228+
HOST_SEEK_FILE(finfop, 0, SEEKMODE_SET);
229+
if (readSize != fileSize) {
230+
free(u8buf);
231+
return;
232+
}
233+
234+
size_t sjSize;
235+
char* sjbuf = HOST_UTF8_TO_SJIS(u8buf, readSize, &sjSize);
236+
free(u8buf);
237+
if (!sjbuf) return;
238+
239+
finfop->onmemory.buffer = sjbuf;
240+
finfop->onmemory.length = sjSize;
241+
finfop->onmemory.position = 0;
242+
}

src/dos_file.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// run68x - Human68k CUI Emulator based on run68
2-
// Copyright (C) 2023 TcbnErik
2+
// Copyright (C) 2024 TcbnErik
33
//
44
// This program is free software; you can redistribute it and /or modify
55
// it under the terms of the GNU General Public License as published by
@@ -21,6 +21,12 @@
2121
#include "run68.h"
2222

2323
Long Read(UWord fileno, ULong buffer, ULong length);
24+
Long Seek(UWord fileno, Long offset, UWord mode);
2425
Long Maketmp(ULong path, UWord atr);
26+
void ClearFinfo(int fileno);
27+
FILEINFO* SetFinfo(Long fileno, HostFileInfoMember hostfile, FileOpenMode mode,
28+
unsigned int nest);
29+
void FreeOnmemoryFile(FILEINFO* finfop);
30+
void ReadOnmemoryFile(FILEINFO* finfop, FileOpenMode openMode);
2531

2632
#endif

0 commit comments

Comments
 (0)