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
2942Long 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+ }
0 commit comments