確かに、標準のbload命令では、2GB以上のオフセットは指定できないっぽいですね。
しかし、2GB以上ものサイズのファイルなんて、何に使うんですか?
まずはそんなに大きなファイルを使うことをやめる方向で考えていった方が良いと思います。
まあ、DVDのisoとかだと4GBを超えることもありますし……。
どうしてもというのなら、Win32APIを直接使う必要がありそうです。
というわけで、モジュール化。
#module
#uselib "kernel32.dll"
#cfunc CreateFile "CreateFileA" int, int, int, int, int, int, int
#func SetFilePointer "SetFilePointer" int, int, int, int
#func ReadFile "ReadFile" int, int, int, int, int
#func CloseHandle "CloseHandle" int
#const GENERIC_READ 0x80000000
#const OPEN_EXISTING 0x00000003
#const FILE_ATTRIBUTE_NORMAL 0x00000080
#const INVALID_HANDLE_VALUE 0xFFFFFFFF
#const FILE_BEGIN 0x00000000
#deffunc bloadex str _filename, var buf, int size, int _dist, int _distH
filename = _filename
hFile = CreateFile(varptr(filename), GENERIC_READ, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0)
if hFile ! INVALID_HANDLE_VALUE {
dist = _dist
distH = _distH
readsize = 0
SetFilePointer hFile, dist, varptr(distH), FILE_BEGIN
ReadFile hFile, varptr(buf), size, varptr(readsize), 0
CloseHandle hFile
ret = readsize
} else {
ret = 0
}
return ret
#global
; 以下サンプル。
; ダイアログでファイルを指定して、ためしにオフセット2GBで1KB読み込んでみる。
; さらにオフセット4GBで1KB読み込んでみる。
; さらにさらにオフセット6GBで1KB読み込んでみる。
; オフセットよりもサイズが小さければ、戻り値( = 読み込んだバイト数)が0になる。
dialog "*", 16
if stat = 1 {
mes refstr+"から読み込んでみます。"
sdim buf1, 1024
bloadex refstr, buf1, 1024, 0x80000000, 0
; 第一パラメータ: ロードするファイル名
; 第二パラメータ: ロード先変数名
; かならずsdimで領域を確保しておくこと。
; 第三パラメータ: ロードするサイズ
; sdimで確保したサイズより大きくしないこと。
; 第四パラメータ: オフセットの下位ダブルワード
; 0x80000000 = 2ギガバイト。
; 0xFFFFFFFF = 4ギガバイト-1バイト。
; 第五パラメータ: オフセットの上位ダブルワード
; 0x00000001 = プラス4ギガバイト。
; 0x00000002 = プラス8ギガバイト。以下同様。
; 戻り値: 実際にロードしたサイズ
; bloadと違ってstrsizeには返らないので注意。
mes "オフセット2GBとして変数buf1に"+stat+"byte読み込みました。"
sdim buf2, 1024
bloadex refstr, buf2, 1024, 0, 0x00000001
mes "オフセット4GBとして変数buf2に"+stat+"byte読み込みました。"
sdim buf3, 1024
bloadex refstr, buf3, 1024, 0x80000000, 0x00000001
mes "オフセット6GBとして変数buf3に"+stat+"byte読み込みました。"
}
手元のisoファイル(5GB超)とバイナリエディタで確認してみましたが、きちんと動作しているようです。