Add more functions

This commit is contained in:
JupiterRider 2023-06-04 11:24:25 +02:00
parent fb93c7c94b
commit 349288d189
2 changed files with 165 additions and 10 deletions

View file

@ -15,6 +15,28 @@ import (
rl "github.com/gen2brain/raylib-go/raylib" rl "github.com/gen2brain/raylib-go/raylib"
) )
// LoadDataFromResource - Load raw data from rres resource chunk
//
// NOTE: Chunk data must be provided uncompressed/unencrypted
func LoadDataFromResource(chunk ResourceChunk) []byte {
cchunk := *(*C.rresResourceChunk)(unsafe.Pointer(&chunk))
var csize C.uint
ret := C.LoadDataFromResource(cchunk, &csize)
defer C.free(ret)
v := C.GoBytes(ret, C.int(csize))
return v
}
// UnpackResourceChunk - Unpack resource chunk data (decompres/decrypt data)
//
// NOTE: Function return 0 on success or other value on failure
func UnpackResourceChunk(chunk *ResourceChunk) ErrorType {
cchunk := (*C.rresResourceChunk)(unsafe.Pointer(chunk))
ret := C.UnpackResourceChunk(cchunk)
v := ErrorType(ret)
return v
}
func LoadImageFromResource(chunk ResourceChunk) rl.Image { func LoadImageFromResource(chunk ResourceChunk) rl.Image {
cchunk := *(*C.rresResourceChunk)(unsafe.Pointer(&chunk)) cchunk := *(*C.rresResourceChunk)(unsafe.Pointer(&chunk))
ret := C.LoadImageFromResource(cchunk) ret := C.LoadImageFromResource(cchunk)

View file

@ -1,10 +1,18 @@
package rres package rres
// #define RRES_IMPLEMENTATION /*
// #include <rres.h> #define RRES_IMPLEMENTATION
// #include <stdlib.h> #include <rres.h>
#include <stdlib.h>
#include <string.h>
rresResourceChunkInfo GetResourceChunkInfoFromArray(rresResourceChunkInfo *infos, int index)
{
return infos[index];
}
*/
import "C" import "C"
import ( import (
"hash/crc32"
"unsafe" "unsafe"
) )
@ -51,7 +59,12 @@ type ResourceChunk struct {
// NOTE: It supports multiple resource chunks // NOTE: It supports multiple resource chunks
type ResourceMulti struct { type ResourceMulti struct {
Count uint32 // Resource chunks count Count uint32 // Resource chunks count
Chunks *ResourceChunk // Resource chunks chunks *ResourceChunk // Resource chunks
}
// Chunks - Resource chunks
func (r *ResourceMulti) Chunks() []ResourceChunk {
return unsafe.Slice(r.chunks, r.Count)
} }
// DirEntry - CDIR: rres central directory entry // DirEntry - CDIR: rres central directory entry
@ -60,7 +73,15 @@ type DirEntry struct {
Offset uint32 // Resource global offset in file Offset uint32 // Resource global offset in file
Reserved uint32 // reserved Reserved uint32 // reserved
FileNameSize uint32 // Resource fileName size (NULL terminator and 4-byte alignment padding considered) FileNameSize uint32 // Resource fileName size (NULL terminator and 4-byte alignment padding considered)
FileName [MaxFilenameSize]int8 // Resource original fileName (NULL terminated and padded to 4-byte alignment) fileName [MaxFilenameSize]int8 // Resource original fileName (NULL terminated and padded to 4-byte alignment)
}
// FileName - Resource original fileName
func (d *DirEntry) FileName() string {
cpointer := (*C.char)(unsafe.Pointer(&d.fileName[0]))
clength := C.int(d.FileNameSize)
fileName := C.GoStringN(cpointer, clength)
return fileName
} }
// CentralDir - CDIR: rres central directory // CentralDir - CDIR: rres central directory
@ -68,7 +89,12 @@ type DirEntry struct {
// NOTE: This data conforms the ResourceChunkData // NOTE: This data conforms the ResourceChunkData
type CentralDir struct { type CentralDir struct {
Count uint32 // Central directory entries count Count uint32 // Central directory entries count
Entries *DirEntry // Central directory entries entries *DirEntry // Central directory entries
}
// Entries - Central directory entries
func (c *CentralDir) Entries() []DirEntry {
return unsafe.Slice(c.entries, c.Count)
} }
// FontGlyphInfo - FNTG: rres font glyphs info (32 bytes) // FontGlyphInfo - FNTG: rres font glyphs info (32 bytes)
@ -326,8 +352,8 @@ func LoadResourceChunk(fileName string, rresId int32) ResourceChunk {
} }
// UnloadResourceChunk - Unload resource chunk from memory // UnloadResourceChunk - Unload resource chunk from memory
func UnloadResourceChunk(chunk ResourceChunk) { func UnloadResourceChunk(chunk *ResourceChunk) {
cchunk := *(*C.rresResourceChunk)(unsafe.Pointer(&chunk)) cchunk := *(*C.rresResourceChunk)(unsafe.Pointer(chunk))
C.rresUnloadResourceChunk(cchunk) C.rresUnloadResourceChunk(cchunk)
} }
@ -341,11 +367,48 @@ func LoadResourceMulti(fileName string, rresId int32) ResourceMulti {
} }
// UnloadResourceMulti - Unload resource from memory (multiple resource chunks) // UnloadResourceMulti - Unload resource from memory (multiple resource chunks)
func UnloadResourceMulti(multi ResourceMulti) { func UnloadResourceMulti(multi *ResourceMulti) {
cmulti := *(*C.rresResourceMulti)(unsafe.Pointer(&multi)) cmulti := *(*C.rresResourceMulti)(unsafe.Pointer(multi))
C.rresUnloadResourceMulti(cmulti) C.rresUnloadResourceMulti(cmulti)
} }
// LoadResourceChunkInfo - Load resource chunk info for provided id
func LoadResourceChunkInfo(fileName string, rresId int32) ResourceChunkInfo {
cfileName := C.CString(fileName)
defer C.free(unsafe.Pointer(cfileName))
ret := C.rresLoadResourceChunkInfo(cfileName, C.int(rresId))
v := *(*ResourceChunkInfo)(unsafe.Pointer(&ret))
return v
}
// LoadResourceChunkInfoAll - Load all resource chunks info
func LoadResourceChunkInfoAll(fileName string) []ResourceChunkInfo {
// Convert the fileName into a CString and releases the memory afterwards
cfileName := C.CString(fileName)
defer C.free(unsafe.Pointer(cfileName))
// The length of the resulted array is saved in the chunkCount variable
var chunkCount C.uint
cinfos := C.rresLoadResourceChunkInfoAll(cfileName, &chunkCount)
// The C array can be released afterwards, because the values are stored in a golang slice
defer C.free(unsafe.Pointer(cinfos))
// Iterate over the C array and store the values in a golang slice
infos := make([]ResourceChunkInfo, chunkCount)
for i := 0; i < int(chunkCount); i++ {
// Get the C value from the C array
ret := C.GetResourceChunkInfoFromArray(cinfos, C.int(i))
// Convert the C value into a golang value
v := *(*ResourceChunkInfo)(unsafe.Pointer(&ret))
// Save the golang value in the golang slice
infos[i] = v
}
return infos
}
// LoadCentralDirectory - Load central directory resource chunk from file
func LoadCentralDirectory(fileName string) CentralDir { func LoadCentralDirectory(fileName string) CentralDir {
cfileName := C.CString(fileName) cfileName := C.CString(fileName)
defer C.free(unsafe.Pointer(cfileName)) defer C.free(unsafe.Pointer(cfileName))
@ -354,6 +417,42 @@ func LoadCentralDirectory(fileName string) CentralDir {
return v return v
} }
// UnloadCentralDirectory - Unload central directory resource chunk
func UnloadCentralDirectory(dir *CentralDir) {
cdir := *(*C.rresCentralDir)(unsafe.Pointer(dir))
C.rresUnloadCentralDirectory(cdir)
}
// GetDataType - Get ResourceDataType from FourCC code
func GetDataType(fourCC [4]byte) ResourceDataType {
value := string(fourCC[:])
switch value {
case "NULL":
return DataNull
case "RAWD":
return DataRaw
case "TEXT":
return DataText
case "IMGE":
return DataImage
case "WAVE":
return DataWave
case "VRTX":
return DataVertex
case "FNTG":
return DataFontGlyphs
case "LINK":
return DataLink
case "CDIR":
return DataDirectory
default:
return 0
}
}
// GetResourceId - Get resource id for a provided filename
//
// NOTE: It requires CDIR available in the file (it's optinal by design)
func GetResourceId(dir CentralDir, fileName string) int32 { func GetResourceId(dir CentralDir, fileName string) int32 {
cfileName := C.CString(fileName) cfileName := C.CString(fileName)
defer C.free(unsafe.Pointer(cfileName)) defer C.free(unsafe.Pointer(cfileName))
@ -362,3 +461,37 @@ func GetResourceId(dir CentralDir, fileName string) int32 {
v := int32(ret) v := int32(ret)
return v return v
} }
// ComputeCRC32 - Compute CRC32 hash
//
// NOTE: CRC32 is used as rres id, generated from original filename
func ComputeCRC32(data []byte) uint32 {
return crc32.ChecksumIEEE(data)
}
// SetCipherPassword - Set password to be used on data decryption
//
// NOTE: The cipher password is kept as an internal pointer to provided string, it's up to the user to manage that sensible data properly
//
// Password should be to allocate and set before loading an encrypted resource and it should be cleaned/wiped after the encrypted resource has been loaded
//
// You can use the WipeCipherPassword function to clear the password
func SetCipherPassword(pass string) {
cpass := C.CString(pass)
C.rresSetCipherPassword(cpass)
}
// GetCipherPassword - Get password to be used on data decryption
func GetCipherPassword() string {
cpass := C.rresGetCipherPassword()
return C.GoString(cpass)
}
// WipeCipherPassword - Clears the password from the C memory using explicit_bzero
//
// This is an approach but no guarantee
func WipeCipherPassword() {
cpass := C.rresGetCipherPassword()
C.explicit_bzero(unsafe.Pointer(cpass), C.strlen(cpass))
C.free(unsafe.Pointer(cpass))
}