146 lines
3.2 KiB
Go
146 lines
3.2 KiB
Go
package parser
|
|
|
|
import (
|
|
"encoding/binary"
|
|
"eq2emu/internal/common"
|
|
"unsafe"
|
|
)
|
|
|
|
type ParseContext struct {
|
|
data []byte
|
|
offset int
|
|
version uint32
|
|
flags uint64
|
|
vars map[string]any
|
|
arrayStack []int
|
|
}
|
|
|
|
func NewContext(data []byte, version uint32, flags uint64) *ParseContext {
|
|
return &ParseContext{
|
|
data: data,
|
|
version: version,
|
|
flags: flags,
|
|
vars: make(map[string]any),
|
|
}
|
|
}
|
|
|
|
func (ctx *ParseContext) readUint8() uint8 {
|
|
val := ctx.data[ctx.offset]
|
|
ctx.offset++
|
|
return val
|
|
}
|
|
|
|
func (ctx *ParseContext) readUint16() uint16 {
|
|
val := binary.LittleEndian.Uint16(ctx.data[ctx.offset:])
|
|
ctx.offset += 2
|
|
return val
|
|
}
|
|
|
|
func (ctx *ParseContext) readUint32() uint32 {
|
|
val := binary.LittleEndian.Uint32(ctx.data[ctx.offset:])
|
|
ctx.offset += 4
|
|
return val
|
|
}
|
|
|
|
func (ctx *ParseContext) readOversizedUint8(threshold int) uint8 {
|
|
if ctx.data[ctx.offset] == byte(threshold) {
|
|
ctx.offset++
|
|
return ctx.readUint8()
|
|
}
|
|
return ctx.readUint8()
|
|
}
|
|
|
|
func (ctx *ParseContext) readOversizedUint16(threshold int) uint16 {
|
|
if ctx.data[ctx.offset] == byte(threshold) {
|
|
ctx.offset++
|
|
return ctx.readUint16()
|
|
}
|
|
return uint16(ctx.readUint8())
|
|
}
|
|
|
|
func (ctx *ParseContext) readString8() string {
|
|
length := ctx.readUint8()
|
|
str := string(ctx.data[ctx.offset : ctx.offset+int(length)])
|
|
ctx.offset += int(length)
|
|
return str
|
|
}
|
|
|
|
func (ctx *ParseContext) readString16() string {
|
|
length := ctx.readUint16()
|
|
str := string(ctx.data[ctx.offset : ctx.offset+int(length)])
|
|
ctx.offset += int(length)
|
|
return str
|
|
}
|
|
|
|
func (ctx *ParseContext) readEQ2String8() common.EQ2String8 {
|
|
size := ctx.readUint8()
|
|
data := string(ctx.data[ctx.offset : ctx.offset+int(size)])
|
|
ctx.offset += int(size)
|
|
return common.EQ2String8{
|
|
Size: size,
|
|
Data: data,
|
|
}
|
|
}
|
|
|
|
func (ctx *ParseContext) readEQ2String16() common.EQ2String16 {
|
|
size := ctx.readUint16()
|
|
data := string(ctx.data[ctx.offset : ctx.offset+int(size)])
|
|
ctx.offset += int(size)
|
|
return common.EQ2String16{
|
|
Size: size,
|
|
Data: data,
|
|
}
|
|
}
|
|
|
|
func (ctx *ParseContext) readEQ2String32() common.EQ2String32 {
|
|
size := ctx.readUint32()
|
|
data := string(ctx.data[ctx.offset : ctx.offset+int(size)])
|
|
ctx.offset += int(size)
|
|
return common.EQ2String32{
|
|
Size: size,
|
|
Data: data,
|
|
}
|
|
}
|
|
|
|
func (ctx *ParseContext) readEQ2Color() common.EQ2Color {
|
|
return common.EQ2Color{
|
|
Red: ctx.readUint8(),
|
|
Green: ctx.readUint8(),
|
|
Blue: ctx.readUint8(),
|
|
}
|
|
}
|
|
|
|
func (ctx *ParseContext) readEQ2Equipment() common.EQ2EquipmentItem {
|
|
return common.EQ2EquipmentItem{
|
|
Type: ctx.readUint16(),
|
|
Color: ctx.readEQ2Color(),
|
|
Highlight: ctx.readEQ2Color(),
|
|
}
|
|
}
|
|
|
|
func (ctx *ParseContext) readBytes(count int) []byte {
|
|
val := make([]byte, count)
|
|
copy(val, ctx.data[ctx.offset:ctx.offset+count])
|
|
ctx.offset += count
|
|
return val
|
|
}
|
|
|
|
func (ctx *ParseContext) readFloat32() float32 {
|
|
val := ctx.readUint32()
|
|
return *(*float32)(unsafe.Pointer(&val))
|
|
}
|
|
|
|
func (ctx *ParseContext) setVar(name string, value any) {
|
|
ctx.vars[name] = value
|
|
}
|
|
|
|
func (ctx *ParseContext) pushArrayIndex(index int) {
|
|
ctx.arrayStack = append(ctx.arrayStack, index)
|
|
}
|
|
|
|
func (ctx *ParseContext) popArrayIndex() {
|
|
if len(ctx.arrayStack) > 0 {
|
|
ctx.arrayStack = ctx.arrayStack[:len(ctx.arrayStack)-1]
|
|
}
|
|
}
|