Use physfs in raylib
This commit is contained in:
parent
973ad9e285
commit
1095afb510
@ -29,13 +29,14 @@ case $(uname) in
|
|||||||
if [ ! -d "linux" ]; then
|
if [ ! -d "linux" ]; then
|
||||||
mkdir linux
|
mkdir linux
|
||||||
cp -r $ROOT/vendor/raylib/linux/libraylib*.so* linux
|
cp -r $ROOT/vendor/raylib/linux/libraylib*.so* linux
|
||||||
|
cp -r libs/physfs/libphysfs.so* linux
|
||||||
fi
|
fi
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
# Build the game.
|
# Build the game.
|
||||||
echo "Building game$DLL_EXT"
|
echo "Building game$DLL_EXT"
|
||||||
odin build game -extra-linker-flags:"$EXTRA_LINKER_FLAGS" -define:RAYLIB_SHARED=true -define:TRACY_ENABLE=true -collection:libs=./libs -collection:common=./common -collection:game=./game -build-mode:dll -out:game_tmp$DLL_EXT -strict-style -vet -debug -o:speed
|
odin build game -extra-linker-flags:"$EXTRA_LINKER_FLAGS" -define:RAYLIB_SHARED=true -define:PHYSFS_SHARED=true -define:TRACY_ENABLE=true -collection:libs=./libs -collection:common=./common -collection:game=./game -build-mode:dll -out:game_tmp$DLL_EXT -strict-style -vet -debug -o:speed
|
||||||
|
|
||||||
# Need to use a temp file on Linux because it first writes an empty `game.so`, which the game will load before it is actually fully written.
|
# Need to use a temp file on Linux because it first writes an empty `game.so`, which the game will load before it is actually fully written.
|
||||||
mv game_tmp$DLL_EXT game$DLL_EXT
|
mv game_tmp$DLL_EXT game$DLL_EXT
|
||||||
|
139
game/fs.odin
Normal file
139
game/fs.odin
Normal file
@ -0,0 +1,139 @@
|
|||||||
|
package game
|
||||||
|
|
||||||
|
import "base:runtime"
|
||||||
|
import "core:c"
|
||||||
|
import "core:log"
|
||||||
|
import "core:strings"
|
||||||
|
import "libs:physfs"
|
||||||
|
import rl "vendor:raylib"
|
||||||
|
|
||||||
|
@(private = "file")
|
||||||
|
_ctx: runtime.Context
|
||||||
|
|
||||||
|
init_physfs :: proc(args: []string) {
|
||||||
|
_ctx = context
|
||||||
|
|
||||||
|
physfs.init(strings.clone_to_cstring(args[0], context.temp_allocator))
|
||||||
|
physfs.setSaneConfig("serega", "gutter-runner", "zip", 0, 1)
|
||||||
|
|
||||||
|
rl.SetLoadFileDataCallback(raylib_load_file_data_physfs)
|
||||||
|
rl.SetSaveFileDataCallback(raylib_save_file_data_physfs)
|
||||||
|
rl.SetLoadFileTextCallback(raylib_load_file_text_physfs)
|
||||||
|
rl.SetSaveFileTextCallback(raylib_save_file_text_physfs)
|
||||||
|
}
|
||||||
|
|
||||||
|
deinit_physfs :: proc() {
|
||||||
|
rl.SetLoadFileDataCallback(nil)
|
||||||
|
rl.SetSaveFileDataCallback(nil)
|
||||||
|
rl.SetLoadFileTextCallback(nil)
|
||||||
|
rl.SetSaveFileTextCallback(nil)
|
||||||
|
|
||||||
|
physfs.deinit()
|
||||||
|
}
|
||||||
|
|
||||||
|
@(private = "file")
|
||||||
|
raylib_load_file_data_physfs :: proc "c" (file_name: cstring, bytes_read: ^c.int) -> [^]u8 {
|
||||||
|
context = _ctx
|
||||||
|
|
||||||
|
bytes_read^ = 0
|
||||||
|
if physfs.exists(file_name) == 0 {
|
||||||
|
log.warnf("PHYSFS: Tried to load unexisting file '%s'", file_name)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Open up the file.
|
||||||
|
handle := physfs.openRead(file_name)
|
||||||
|
if handle == nil {
|
||||||
|
trace_physfs_error(file_name)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
defer physfs.close(handle)
|
||||||
|
|
||||||
|
// Check to see how large the file is.
|
||||||
|
size := physfs.fileLength(handle)
|
||||||
|
if (size == -1) {
|
||||||
|
log.warnf("PHYSFS: Cannot determine size of file '%s'", file_name)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close safely when it's empty.
|
||||||
|
if (size == 0) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read the file, return if it's empty.
|
||||||
|
buffer := rl.MemAlloc(u32(size))
|
||||||
|
read := physfs.readBytes(handle, buffer, u64(size))
|
||||||
|
if read < 0 {
|
||||||
|
rl.MemFree(buffer)
|
||||||
|
trace_physfs_error(file_name)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
bytes_read^ = i32(read)
|
||||||
|
return cast([^]u8)buffer
|
||||||
|
}
|
||||||
|
|
||||||
|
@(private = "file")
|
||||||
|
raylib_save_file_data_physfs :: proc "c" (
|
||||||
|
file_name: cstring,
|
||||||
|
data: rawptr,
|
||||||
|
bytes_to_write: c.int,
|
||||||
|
) -> bool {
|
||||||
|
context = _ctx
|
||||||
|
// Protect against empty writes.
|
||||||
|
if bytes_to_write <= 0 {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Open the file.
|
||||||
|
handle := physfs.openWrite(file_name)
|
||||||
|
if handle == nil {
|
||||||
|
trace_physfs_error(file_name)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
defer physfs.close(handle)
|
||||||
|
|
||||||
|
// Write the data to the file handle.
|
||||||
|
if (physfs.writeBytes(handle, data, u64(bytes_to_write)) < 0) {
|
||||||
|
trace_physfs_error(file_name)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
@(private = "file")
|
||||||
|
raylib_load_file_text_physfs :: proc "c" (fileName: cstring) -> [^]u8 {
|
||||||
|
bytesRead: i32
|
||||||
|
data := raylib_load_file_data_physfs(fileName, &bytesRead)
|
||||||
|
if bytesRead == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
defer rl.MemFree(data)
|
||||||
|
|
||||||
|
// Copy the data, and append a null terminator.
|
||||||
|
text := cast([^]u8)rl.MemAlloc(u32(bytesRead + 1))
|
||||||
|
for i := i32(0); i < bytesRead; i += 1 {
|
||||||
|
text[i] = data[i]
|
||||||
|
}
|
||||||
|
text[bytesRead] = 0
|
||||||
|
|
||||||
|
return text
|
||||||
|
}
|
||||||
|
|
||||||
|
@(private = "file")
|
||||||
|
raylib_save_file_text_physfs :: proc "c" (fileName: cstring, text: cstring) -> bool {
|
||||||
|
return raylib_save_file_data_physfs(fileName, cast(rawptr)text, i32(runtime.cstring_len(text)))
|
||||||
|
}
|
||||||
|
|
||||||
|
@(private = "file")
|
||||||
|
trace_physfs_error :: proc(detail: cstring) {
|
||||||
|
errorCode := physfs.getLastErrorCode()
|
||||||
|
if errorCode == .OK {
|
||||||
|
log.warnf("PHYSFS: %s", detail)
|
||||||
|
} else {
|
||||||
|
errorMessage := physfs.getErrorByCode(errorCode)
|
||||||
|
log.warnf("PHYSFS: %s (%s)", errorMessage, detail)
|
||||||
|
}
|
||||||
|
}
|
@ -1022,9 +1022,11 @@ game_update :: proc() -> bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@(export)
|
@(export)
|
||||||
game_init_window :: proc() {
|
game_init_window :: proc(args: []string) {
|
||||||
tracy.SetThreadName("Main")
|
tracy.SetThreadName("Main")
|
||||||
|
|
||||||
|
init_physfs(args)
|
||||||
|
|
||||||
rl.SetConfigFlags({.WINDOW_RESIZABLE, .VSYNC_HINT})
|
rl.SetConfigFlags({.WINDOW_RESIZABLE, .VSYNC_HINT})
|
||||||
rl.InitWindow(1280, 720, "Odin + Raylib + Hot Reload template!")
|
rl.InitWindow(1280, 720, "Odin + Raylib + Hot Reload template!")
|
||||||
rl.SetExitKey(.KEY_NULL)
|
rl.SetExitKey(.KEY_NULL)
|
||||||
@ -1056,6 +1058,8 @@ game_shutdown :: proc() {
|
|||||||
@(export)
|
@(export)
|
||||||
game_shutdown_window :: proc() {
|
game_shutdown_window :: proc() {
|
||||||
rl.CloseWindow()
|
rl.CloseWindow()
|
||||||
|
|
||||||
|
deinit_physfs()
|
||||||
}
|
}
|
||||||
|
|
||||||
@(export)
|
@(export)
|
||||||
|
2
libs/physfs/.gitignore
vendored
2
libs/physfs/.gitignore
vendored
@ -1,3 +1,3 @@
|
|||||||
*.a
|
*.a
|
||||||
*.so
|
*.so*
|
||||||
build
|
build
|
||||||
|
@ -5,4 +5,4 @@ build_physfs: configure_cmake
|
|||||||
libphysfs.a: build_physfs
|
libphysfs.a: build_physfs
|
||||||
cp ./build/libphysfs.a .
|
cp ./build/libphysfs.a .
|
||||||
libphysfs.so: build_physfs
|
libphysfs.so: build_physfs
|
||||||
cp ./build/libphysfs.so .
|
cp ./build/libphysfs.so* .
|
||||||
|
@ -2,18 +2,24 @@ package physfs
|
|||||||
|
|
||||||
import "core:c"
|
import "core:c"
|
||||||
|
|
||||||
|
PHYSFS_SHARED :: #config(PHYSFS_SHARED, false)
|
||||||
|
|
||||||
when ODIN_OS == .Linux || ODIN_OS == .Darwin {
|
when ODIN_OS == .Linux || ODIN_OS == .Darwin {
|
||||||
foreign import lib "libphysfs.a"
|
when PHYSFS_SHARED {
|
||||||
|
foreign import lib "libphysfs.so"
|
||||||
|
} else {
|
||||||
|
foreign import lib "libphysfs.a"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@(default_calling_convention="c", link_prefix="PHYSFS_")
|
@(default_calling_convention = "c", link_prefix = "PHYSFS_")
|
||||||
foreign lib {
|
foreign lib {
|
||||||
init :: proc(argv0: cstring) -> c.int ---
|
init :: proc(argv0: cstring) -> c.int ---
|
||||||
isInit :: proc() -> c.int ---
|
isInit :: proc() -> c.int ---
|
||||||
deinit :: proc() -> c.int ---
|
deinit :: proc() -> c.int ---
|
||||||
supportedArchiveTypes :: proc() -> [^]^ArchiveInfo ---
|
supportedArchiveTypes :: proc() -> [^]^ArchiveInfo ---
|
||||||
freeList :: proc(listVar: rawptr) ---
|
freeList :: proc(listVar: rawptr) ---
|
||||||
|
|
||||||
getLastError :: proc() -> cstring ---
|
getLastError :: proc() -> cstring ---
|
||||||
getDirSeparator :: proc() -> cstring ---
|
getDirSeparator :: proc() -> cstring ---
|
||||||
permitSymbolicLinks :: proc(allow: c.int) ---
|
permitSymbolicLinks :: proc(allow: c.int) ---
|
||||||
@ -26,10 +32,10 @@ foreign lib {
|
|||||||
removeFromSearchPath :: proc(oldDir: cstring) -> c.int ---
|
removeFromSearchPath :: proc(oldDir: cstring) -> c.int ---
|
||||||
getSearchPath :: proc() -> [^]cstring ---
|
getSearchPath :: proc() -> [^]cstring ---
|
||||||
setSaneConfig :: proc(organization, appName, archiveExt: cstring, includedCdRoms, archivesFirst: c.int) -> c.int ---
|
setSaneConfig :: proc(organization, appName, archiveExt: cstring, includedCdRoms, archivesFirst: c.int) -> c.int ---
|
||||||
|
|
||||||
mkdir :: proc(dirName: cstring) -> c.int ---
|
mkdir :: proc(dirName: cstring) -> c.int ---
|
||||||
delete :: proc(filename: cstring) -> c.int ---
|
delete :: proc(filename: cstring) -> c.int ---
|
||||||
|
|
||||||
getRealDir :: proc(filename: cstring) -> cstring ---
|
getRealDir :: proc(filename: cstring) -> cstring ---
|
||||||
getPrefDir :: proc(org, app: cstring) -> cstring ---
|
getPrefDir :: proc(org, app: cstring) -> cstring ---
|
||||||
enumerateFiles :: proc(dir: cstring) -> [^]cstring ---
|
enumerateFiles :: proc(dir: cstring) -> [^]cstring ---
|
||||||
@ -41,11 +47,11 @@ foreign lib {
|
|||||||
getLastErrorCode :: proc() -> ErrorCode ---
|
getLastErrorCode :: proc() -> ErrorCode ---
|
||||||
getErrorByCode :: proc(code: ErrorCode) -> cstring ---
|
getErrorByCode :: proc(code: ErrorCode) -> cstring ---
|
||||||
setErrorCode :: proc(code: ErrorCode) ---
|
setErrorCode :: proc(code: ErrorCode) ---
|
||||||
|
|
||||||
openWrite :: proc(filename: cstring) -> ^File ---
|
openWrite :: proc(filename: cstring) -> ^File ---
|
||||||
openAppend :: proc(filename: cstring) -> ^File ---
|
openAppend :: proc(filename: cstring) -> ^File ---
|
||||||
openRead :: proc(filename: cstring) -> ^File ---
|
openRead :: proc(filename: cstring) -> ^File ---
|
||||||
|
|
||||||
close :: proc(handle: ^File) -> c.int ---
|
close :: proc(handle: ^File) -> c.int ---
|
||||||
read :: proc(handle: ^File, buffer: rawptr, objSize, objCount: uint32) -> sint64 ---
|
read :: proc(handle: ^File, buffer: rawptr, objSize, objCount: uint32) -> sint64 ---
|
||||||
write :: proc(handle: ^File, buffer: rawptr, objSize, objCount: uint32) -> sint64 ---
|
write :: proc(handle: ^File, buffer: rawptr, objSize, objCount: uint32) -> sint64 ---
|
||||||
@ -58,26 +64,26 @@ foreign lib {
|
|||||||
flush :: proc(handle: ^File) -> c.int ---
|
flush :: proc(handle: ^File) -> c.int ---
|
||||||
readBytes :: proc(handle: ^File, buffer: rawptr, len: uint64) -> sint64 ---
|
readBytes :: proc(handle: ^File, buffer: rawptr, len: uint64) -> sint64 ---
|
||||||
writeBytes :: proc(handle: ^File, buffer: rawptr, len: uint64) -> sint64 ---
|
writeBytes :: proc(handle: ^File, buffer: rawptr, len: uint64) -> sint64 ---
|
||||||
|
|
||||||
registerArchiver :: proc(archiver: ^Archiver) -> c.int ---
|
registerArchiver :: proc(archiver: ^Archiver) -> c.int ---
|
||||||
deregisterArchiver :: proc(ext: cstring) -> c.int ---
|
deregisterArchiver :: proc(ext: cstring) -> c.int ---
|
||||||
|
|
||||||
setRoot :: proc(archive, subdir: cstring) -> c.int ---
|
setRoot :: proc(archive, subdir: cstring) -> c.int ---
|
||||||
setAllocator :: proc(allocator: ^Allocator) -> c.int ---
|
setAllocator :: proc(allocator: ^Allocator) -> c.int ---
|
||||||
getAllocator :: proc() -> ^Allocator ---
|
getAllocator :: proc() -> ^Allocator ---
|
||||||
|
|
||||||
mount :: proc(newDir, mountPoint: cstring, appendToPath: c.int) -> c.int ---
|
mount :: proc(newDir, mountPoint: cstring, appendToPath: c.int) -> c.int ---
|
||||||
unmount :: proc(oldDir: cstring) -> c.int ---
|
unmount :: proc(oldDir: cstring) -> c.int ---
|
||||||
mountIo :: proc(io: ^Io, newdir, mountPoint: cstring, appendToPath: c.int) -> c.int ---
|
mountIo :: proc(io: ^Io, newdir, mountPoint: cstring, appendToPath: c.int) -> c.int ---
|
||||||
mountMemory :: proc(buf: rawptr, len: uint64, del: proc "c"(rawptr), newDir, mountPoint: cstring, appendToPath: c.int) -> c.int ---
|
mountMemory :: proc(buf: rawptr, len: uint64, del: proc "c" (_: rawptr), newDir, mountPoint: cstring, appendToPath: c.int) -> c.int ---
|
||||||
mountHandle :: proc(file: ^File, newDir, mountPoint: cstring, appendToPath: c.int) -> c.int ---
|
mountHandle :: proc(file: ^File, newDir, mountPoint: cstring, appendToPath: c.int) -> c.int ---
|
||||||
|
|
||||||
getMountPoint :: proc(dir: cstring) -> cstring ---
|
getMountPoint :: proc(dir: cstring) -> cstring ---
|
||||||
getCdRomDirsCallback :: proc(c: StringCallback, d: rawptr) ---
|
getCdRomDirsCallback :: proc(c: StringCallback, d: rawptr) ---
|
||||||
getSearchPathCallback :: proc(c: StringCallback, d: rawptr) ---
|
getSearchPathCallback :: proc(c: StringCallback, d: rawptr) ---
|
||||||
enumerateFilesCallback :: proc(dir: cstring, c: EnumFilesCallback, d: rawptr) ---
|
enumerateFilesCallback :: proc(dir: cstring, c: EnumFilesCallback, d: rawptr) ---
|
||||||
enumerate :: proc(dir: cstring, callback: EnumerateCallback, d: rawptr) -> c.int ---
|
enumerate :: proc(dir: cstring, callback: EnumerateCallback, d: rawptr) -> c.int ---
|
||||||
|
|
||||||
swapSLE16 :: proc(val: sint16) -> sint16 ---
|
swapSLE16 :: proc(val: sint16) -> sint16 ---
|
||||||
swapULE16 :: proc(val: uint16) -> uint16 ---
|
swapULE16 :: proc(val: uint16) -> uint16 ---
|
||||||
swapLE32 :: proc(val: sint32) -> sint32 ---
|
swapLE32 :: proc(val: sint32) -> sint32 ---
|
||||||
@ -124,7 +130,7 @@ foreign lib {
|
|||||||
utf8FromLatin1 :: proc(src, dst: cstring, len: uint64) ---
|
utf8FromLatin1 :: proc(src, dst: cstring, len: uint64) ---
|
||||||
utf8FromUtf16 :: proc(src: ^uint16, dst: cstring, len: uint64) ---
|
utf8FromUtf16 :: proc(src: ^uint16, dst: cstring, len: uint64) ---
|
||||||
utf8ToUtf16 :: proc(src: cstring, dst: ^uint16, len: uint64) ---
|
utf8ToUtf16 :: proc(src: cstring, dst: ^uint16, len: uint64) ---
|
||||||
|
|
||||||
caseFold :: proc(from: uint32, to: ^uint32) -> c.int ---
|
caseFold :: proc(from: uint32, to: ^uint32) -> c.int ---
|
||||||
utf8stricmp :: proc(str1, str2: cstring) -> c.int ---
|
utf8stricmp :: proc(str1, str2: cstring) -> c.int ---
|
||||||
utf16stricmp :: proc(str1, str2: cstring) -> c.int ---
|
utf16stricmp :: proc(str1, str2: cstring) -> c.int ---
|
||||||
|
@ -40,7 +40,7 @@ copy_dll :: proc(to: string) -> bool {
|
|||||||
|
|
||||||
Game_API :: struct {
|
Game_API :: struct {
|
||||||
lib: dynlib.Library,
|
lib: dynlib.Library,
|
||||||
init_window: proc(),
|
init_window: proc(args: []string),
|
||||||
init: proc(),
|
init: proc(),
|
||||||
update: proc() -> bool,
|
update: proc() -> bool,
|
||||||
shutdown: proc(),
|
shutdown: proc(),
|
||||||
@ -136,7 +136,7 @@ main :: proc() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
game_api_version += 1
|
game_api_version += 1
|
||||||
game_api.init_window()
|
game_api.init_window(os.args)
|
||||||
game_api.init()
|
game_api.init()
|
||||||
|
|
||||||
old_game_apis := make([dynamic]Game_API, default_allocator)
|
old_game_apis := make([dynamic]Game_API, default_allocator)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user