Skip to content

Commit

Permalink
feat: add -read-file-utf8 option
Browse files Browse the repository at this point in the history
  • Loading branch information
kg68k committed Mar 8, 2024
1 parent f99490d commit 8ff4c8d
Show file tree
Hide file tree
Showing 12 changed files with 446 additions and 192 deletions.
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
# run68x 2.0.0 (2024-03-09)

* ファイル読み込み時のエンコーディング変換を追加(`-read-file-utf8`)。
* `DOS _BUS_ERR`を実装した。
* `ADDX -(Ay),-(Ax)``SUBX -(Ay),-(Ax)`命令を実装した。


# run68x 1.4.0 (2024-03-01)

新機能
Expand Down
17 changes: 17 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ run68の改造版です。
* `-f` ... ファンクションコールトレース
* `-tr <adr>` ... MPU命令トラップ
* `-d` ... 簡易デバッガ起動
* `-read-file-utf8` ... ファイル読み込み時にUTF-8からシフトJISに変換


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


### ファイル読み込み時のエンコーディング変換

実験的な機能です。

`-read-file-utf8`オプションを指定すると、読み込みモードで開いたファイルから内容を
読み込むときに、エンコーディングをUTF-8からシフトJISに変換します。

すべてのファイル読み込みに適用されるため、UTF-8以外で記述されたファイルや
バイナリファイルでは正しく内容を読み取ることができなくなります。

読み書きモードで開いたファイルや、新規作成したファイルは変換されません。
また、ファイルの書き込み時には変換されません。

現在の実装では、変換に失敗した場合は変換せずに続行します。


## Build
Windows (Visual Studio 2022、x64)、WSL上のUbuntu 22.04でのみ確認しています。
なにか問題があれば報告してください。
Expand Down
105 changes: 103 additions & 2 deletions src/dos_file.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,19 @@
#include "mem.h"
#include "run68.h"

static Long readFile(FILEINFO* finfop, char* buffer, ULong length) {
if (!finfop->onmemory.buffer)
return HOST_READ_FILE_OR_TTY(finfop, buffer, length);

ULong rest = (ULong)(finfop->onmemory.length - finfop->onmemory.position);
ULong len = (rest < length) ? rest : length;

memcpy(buffer, finfop->onmemory.buffer + finfop->onmemory.position, len);
finfop->onmemory.position += len;

return len;
}

// DOS _READ
Long Read(UWord fileno, ULong buffer, ULong length) {
// Human68k v3.02ではファイルのエラー検査より先にバイト数が0か調べている
Expand All @@ -40,7 +53,7 @@ Long Read(UWord fileno, ULong buffer, ULong length) {
if (!GetWritableMemoryRangeSuper(buffer, length, &mem))
throwBusErrorOnWrite(buffer); // バッファアドレスが不正

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

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

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

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

static Long seekOnmemoryFile(FILEINFO* finfop, Long offset, FileSeekMode mode) {
Long base = (mode == SEEKMODE_SET) ? 0
: (mode == SEEKMODE_CUR) ? finfop->onmemory.position
: finfop->onmemory.length;
Long pos = base + offset;

if (pos < 0 || pos > finfop->onmemory.length) return DOSE_CANTSEEK;

finfop->onmemory.position = pos;
return pos;
}

// DOS _SEEK (0xff42)
Long Seek(UWord fileno, Long offset, UWord mode) {
if (fileno >= FILE_MAX) return DOSE_MFILE;

FILEINFO* finfop = &finfo[fileno];
if (!finfop->is_opened) return DOSE_BADF;

if (mode > SEEKMODE_END) return DOSE_ILGPARM;

return finfop->onmemory.buffer ? seekOnmemoryFile(finfop, offset, mode)
: HOST_SEEK_FILE(finfop, offset, mode);
}

// Human68kにおける2バイト文字の1バイト目の文字コードか
// Shift_JIS-2004 ... 0x81~0x9f、0xe0~0xfc
// Human68kの実際の動作 ... 0x80~0x9f、0xe0~0xff
Expand Down Expand Up @@ -139,3 +177,66 @@ Long Maketmp(ULong path, UWord atr) {
// 加算できたらファイル作成を再試行する
}
}

static OnmemoryFileData defaultOnmemoryFileData(void) {
return (OnmemoryFileData){NULL, 0, 0};
}

// finfoを初期化する。
void ClearFinfo(int fileno) {
FILEINFO* f = &finfo[fileno];

f->host = (HostFileInfoMember){0};
f->is_opened = false;
f->mode = OPENMODE_READ;
f->nest = 0;
f->onmemory = defaultOnmemoryFileData();
}

// オープンしたファイルの情報をfinfoに書き込む。
FILEINFO* SetFinfo(int fileno, HostFileInfoMember hostfile, FileOpenMode mode,
unsigned int nest) {
FILEINFO* f = &finfo[fileno];

f->host = hostfile;
f->is_opened = true;
f->mode = mode;
f->nest = nest_cnt;
f->onmemory = defaultOnmemoryFileData();

return f;
}

void FreeOnmemoryFile(FILEINFO* finfop) {
if (!finfop->onmemory.buffer) return;

free(finfop->onmemory.buffer);
finfop->onmemory.buffer = NULL;
}

void ReadOnmemoryFile(FILEINFO* finfop, FileOpenMode openMode) {
if (openMode != OPENMODE_READ || !settings.readFileUtf8) return;

Long fileSize = HOST_SEEK_FILE(finfop, 0, SEEKMODE_END);
HOST_SEEK_FILE(finfop, 0, SEEKMODE_SET);
if (fileSize < 0) return;

char* u8buf = malloc(fileSize);
if (!u8buf) return;

Long readSize = (Long)HOST_READ_FILE_OR_TTY(finfop, u8buf, fileSize);
HOST_SEEK_FILE(finfop, 0, SEEKMODE_SET);
if (readSize != fileSize) {
free(u8buf);
return;
}

size_t sjSize;
char* sjbuf = HOST_UTF8_TO_SJIS(u8buf, readSize, &sjSize);
free(u8buf);
if (!sjbuf) return;

finfop->onmemory.buffer = sjbuf;
finfop->onmemory.length = sjSize;
finfop->onmemory.position = 0;
}
8 changes: 7 additions & 1 deletion src/dos_file.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// run68x - Human68k CUI Emulator based on run68
// Copyright (C) 2023 TcbnErik
// Copyright (C) 2024 TcbnErik
//
// 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
Expand All @@ -21,6 +21,12 @@
#include "run68.h"

Long Read(UWord fileno, ULong buffer, ULong length);
Long Seek(UWord fileno, Long offset, UWord mode);
Long Maketmp(ULong path, UWord atr);
void ClearFinfo(int fileno);
FILEINFO* SetFinfo(Long fileno, HostFileInfoMember hostfile, FileOpenMode mode,
unsigned int nest);
void FreeOnmemoryFile(FILEINFO* finfop);
void ReadOnmemoryFile(FILEINFO* finfop, FileOpenMode openMode);

#endif
Loading

0 comments on commit 8ff4c8d

Please sign in to comment.