diff options
| author | Xander Swan <[hidden email]> | 2026-01-07 23:12:22 -0500 |
|---|---|---|
| committer | Xander Swan <[hidden email]> | 2026-01-07 23:12:22 -0500 |
| commit | 0988ab832bfc7a1b1c851125b6172cf68c6d9cb9 (patch) | |
| tree | 460bc2d9f0bce463af273d6b2b2c20faa880ac29 /tools/compile_assets/aseprite/unmarshal.odin | |
| parent | ade0dc4d257d053b7064184f193f8168c496e308 (diff) | |
doesn't compile but i'm commiting anywya
Diffstat (limited to 'tools/compile_assets/aseprite/unmarshal.odin')
| -rw-r--r-- | tools/compile_assets/aseprite/unmarshal.odin | 444 |
1 files changed, 444 insertions, 0 deletions
diff --git a/tools/compile_assets/aseprite/unmarshal.odin b/tools/compile_assets/aseprite/unmarshal.odin new file mode 100644 index 0000000..5e5295c --- /dev/null +++ b/tools/compile_assets/aseprite/unmarshal.odin @@ -0,0 +1,444 @@ +package aseprite_file_handler + +import "base:runtime" +import "base:intrinsics" +import "core:io" +import "core:os" +import "core:log" +import "core:bytes" +import "core:bufio" +import "core:mem/virtual" + + +unmarshal_from_bytes_buff :: proc(doc: ^Document, r: ^bytes.Reader, alloc: runtime.Allocator = {}) -> (err: Unmarshal_Error) { + rr, ok := io.to_reader(bytes.reader_to_stream(r)) + if !ok { + return .Unable_Make_Reader + } + return unmarshal(doc, rr, alloc) +} + +unmarshal_from_bufio :: proc(doc: ^Document, r: ^bufio.Reader, alloc: runtime.Allocator = {}) -> (err: Unmarshal_Error) { + rr, ok := io.to_reader(bufio.reader_to_stream(r)) + if !ok { + return .Unable_Make_Reader + } + return unmarshal(doc, rr, alloc) +} + +unmarshal_from_filename :: proc(doc: ^Document, name: string, alloc: runtime.Allocator = {}) -> (err: Unmarshal_Error) { + fd, fd_err := os.open(name, os.O_RDONLY, 0) + if fd_err != nil { + log.error("Unable to read because of:", fd_err) + return fd_err + } + defer os.close(fd) + return unmarshal(doc, fd, alloc) +} + +unmarshal_from_handle :: proc(doc: ^Document, h: os.Handle, alloc: runtime.Allocator = {}) -> (err: Unmarshal_Error) { + rr, ok := io.to_reader(os.stream_from_handle(h)) + if !ok { + return .Unable_Make_Reader + } + return unmarshal(doc, rr, alloc) +} + +unmarshal_from_slice :: proc(doc: ^Document, b: []byte, alloc: runtime.Allocator = {}) -> (err: Unmarshal_Error) { + r: bytes.Reader + bytes.reader_init(&r, b[:]) + return unmarshal(doc, &r, alloc) +} + +unmarshal :: proc{ + unmarshal_from_bytes_buff, unmarshal_from_slice, unmarshal_from_handle, + unmarshal_from_filename, unmarshal_from_bufio, unmarshal_from_reader, +} + +unmarshal_from_reader :: proc(doc: ^Document, r: io.Reader, alloc: runtime.Allocator = {}) -> (err: Unmarshal_Error) { + tr: int + defer { + if err != nil { + log.errorf("Failed to unmarshal at %v (%X) cause of %v", tr, tr, err) + } + } + + temp_alloc := alloc + if alloc == {} { + if doc.arena.curr_block == nil || doc.arena.total_reserved == 0 { + virtual.arena_init_growing(&doc.arena) or_return + } + temp_alloc = virtual.arena_allocator(&doc.arena) + } + context.allocator = temp_alloc + + icc_warn: bool + rt := &tr + + doc.header = read_file_header(r, rt) or_return + frames := doc.header.frames + color_depth := doc.header.color_depth + doc.frames = make([]Frame, int(frames)) or_return + flags := doc.header.flags + + for &frame in doc.frames { + fh: Frame_Header + //frame_size := read_dword(r, rt) or_return + read_dword(r, rt) or_return + frame_magic := read_word(r, rt) or_return + if frame_magic != FRAME_MAGIC_NUM { + return .Bad_Frame_Magic_Number + } + + fh.old_num_of_chunks = read_word(r, rt) or_return + fh.duration = read_word(r, rt) or_return + if fh.duration == 0 { + fh.duration = doc.header.speed + } + + read_skip(r, 2, rt) or_return + fh.num_of_chunks = read_dword(r, rt) or_return + + chunks := int(fh.num_of_chunks) + if chunks == 0 { + chunks = int(fh.old_num_of_chunks) + } + + frame.header = fh + frame.chunks = make([]Chunk, chunks) or_return + + for &chunk in frame.chunks { + c_size := int(read_dword(r, rt) or_return) + c_type := cast(Chunk_Types)read_word(r, rt) or_return + + switch c_type { + case .old_palette_256: chunk = read_old_palette_256(r, rt) or_return + case .old_palette_64: chunk = read_old_palette_64(r, rt) or_return + case .layer: chunk = read_layer(r, rt, (.Has_UUID in flags)) or_return + case .cel: chunk = read_cel(r, rt, int(color_depth), c_size) or_return + case .cel_extra: chunk = read_cel_extra(r, rt) or_return + case .color_profile: chunk = read_color_profile(r, rt, &icc_warn) or_return + case .external_files: chunk = read_external_files(r, rt) or_return + case .mask: chunk = read_mask(r, rt) or_return + case .path: chunk = read_path() + case .tags: chunk = read_tags(r, rt) or_return + case .palette: chunk = read_palette(r, rt) or_return + case .user_data: chunk = read_user_data(r, rt) or_return + case .slice: chunk = read_slice(r, rt) or_return + case .tileset: chunk = read_tileset(r, rt) or_return + + case .none: fallthrough + case: + log.error("Invalid Chunk Type", c_type) + return .Invalid_Chunk_Type + } + } + } + return +} + + +unmarshal_chunks :: proc{ unmarshal_multi_chunks, unmarshal_single_chunk } + + +unmarshal_multi_chunks :: proc(r: io.Reader, buf: ^[dynamic]Chunk, chunks: Chunk_Set, alloc := context.allocator) -> (err: Unmarshal_Error) { + context.allocator = alloc + icc_warn: bool + tr: int + defer { + if err != nil { + log.error("Failed to unmarshal at", tr, "cause of", err) + } + } + rt := &tr + + file_header := read_file_header(r, rt) or_return + frames := file_header.frames + color_depth := int(file_header.color_depth) + flags := file_header.flags + + for _ in 0..<frames { + read_dword(r, rt) or_return + frame_magic := read_word(r, rt) or_return + if frame_magic != FRAME_MAGIC_NUM { + return .Bad_Frame_Magic_Number + } + old_num_of_chunks := read_word(r, rt) or_return + read_skip(r, 4, rt) or_return + num_of_chunks := int(read_dword(r, rt) or_return) + + if num_of_chunks == 0 { + num_of_chunks = int(old_num_of_chunks) + } + + for _ in 0..<num_of_chunks { + c_size := int(read_dword(r, rt) or_return) - 6 + c_type := cast(Chunk_Types)read_word(r, rt) or_return + + chunk: Chunk + switch c_type { + case .old_palette_256: + if .old_palette_256 in chunks { + chunk = read_old_palette_256(r, rt) or_return + } else { + read_skip(r, c_size, rt) or_return + } + + case .old_palette_64: + if .old_palette_64 in chunks { + chunk = read_old_palette_64(r, rt) or_return + } else { + read_skip(r, c_size, rt) or_return + } + + case .layer: + if .layer in chunks { + chunk = read_layer(r, rt, (.Has_UUID in flags)) or_return + } else { + read_skip(r, c_size, rt) or_return + } + + case .cel: + if .cel in chunks { + chunk = read_cel(r, rt, color_depth, c_size+6) or_return + } else { + read_skip(r, c_size, rt) or_return + } + + case .cel_extra: + if .cel_extra in chunks { + chunk = read_cel_extra(r, rt) or_return + } else { + read_skip(r, c_size, rt) or_return + } + + case .color_profile: + if .color_profile in chunks { + chunk = read_color_profile(r, rt, &icc_warn) or_return + } else { + read_skip(r, c_size, rt) or_return + } + + case .external_files: + if .external_files in chunks { + chunk = read_external_files(r, rt) or_return + } else { + read_skip(r, c_size, rt) or_return + } + + case .mask: + if .mask in chunks { + chunk = read_mask(r, rt) or_return + } else { + read_skip(r, c_size, rt) or_return + } + + case .path: + if .path in chunks { + chunk = read_path() + } else { + read_skip(r, c_size, rt) or_return + } + + case .tags: + if .tags in chunks { + chunk = read_tags(r, rt) or_return + } else { + read_skip(r, c_size, rt) or_return + } + + case .palette: + if .palette in chunks { + chunk = read_palette(r, rt) or_return + } else { + read_skip(r, c_size, rt) or_return + } + + case .user_data: + if .user_data in chunks { + chunk = read_user_data(r, rt) or_return + } else { + read_skip(r, c_size, rt) or_return + } + + case .slice: + if .slice in chunks { + chunk = read_slice(r, rt) or_return + } else { + read_skip(r, c_size, rt) or_return + } + + case .tileset: + if .tileset in chunks { + chunk = read_tileset(r, rt) or_return + } else { + read_skip(r, c_size, rt) or_return + } + + case .none: fallthrough + case: + log.error("Invalid Chunk Type", c_type) + return .Invalid_Chunk_Type + } + + if chunk != nil { + append(buf, chunk) or_return + } + } + } + return +} + + +unmarshal_single_chunk :: proc ( + r: io.Reader, buf: ^[dynamic]$T, alloc := context.allocator +) -> (err: Unmarshal_Error) where intrinsics.type_is_variant_of(Chunk, T) { + + context.allocator = alloc + icc_warn: bool + + tr: int + defer { + if err != nil { + log.error("Failed to unmarshal at", tr, "cause of", err) + } + } + rt := &tr + + file_header := read_file_header(r, rt) or_return + + frames := file_header.frames + color_depth := file_header.color_depth + _ = color_depth + flags := file_header.flags + + for _ in 0..<frames { + read_dword(r, rt) or_return + frame_magic := read_word(r, rt) or_return + if frame_magic != FRAME_MAGIC_NUM { + return .Bad_Frame_Magic_Number + } + + old_num_of_chunks := read_word(r, rt) or_return + read_skip(r, 4, rt) or_return + num_of_chunks := int(read_dword(r, rt) or_return) + + if num_of_chunks == 0 { + num_of_chunks = int(old_num_of_chunks) + } + + for _ in 0..<num_of_chunks { + c_size := int(read_dword(r, rt) or_return) - 6 + c_type := cast(Chunk_Types)read_word(r, rt) or_return + + // TODO: This is too dirty for my likeing. Make a proc group for it all. + switch c_type { + case .old_palette_256: + when T == Old_Palette_256_Chunk { + append(buf, read_old_palette_256(r, rt) or_return) or_return + } else { + read_skip(r, c_size, rt) or_return + } + + case .old_palette_64: + when T == Old_Palette_64_Chunk { + append(buf, read_old_palette_64(r, rt) or_return) or_return + } else { + read_skip(r, c_size, rt) or_return + } + + case .layer: + when T == Layer_Chunk { + append(buf, read_layer(r, rt, (.Has_UUID in flags)) or_return) or_return + } else { + read_skip(r, c_size, rt) or_return + } + + case .cel: + when T == Cel_Chunk { + append(buf, read_cel(r, rt, int(color_depth), c_size+6) or_return) or_return + } else { + read_skip(r, c_size, rt) or_return + } + + case .cel_extra: + when T == Cel_Extra_Chunk { + append(buf, read_cel_extra(r, rt) or_return) or_return + } else { + read_skip(r, c_size, rt) or_return + } + + case .color_profile: + when T == Color_Profile_Chunk { + append(buf, read_color_profile(r, rt, &icc_warn) or_return) or_return + } else { + read_skip(r, c_size, rt) or_return + } + + case .external_files: + when T == External_Files_Chunk { + append(buf, read_external_files(r, rt) or_return) or_return + } else { + read_skip(r, c_size, rt) or_return + } + + case .mask: + when T == Mask_Chunk { + append(buf, read_mask(r, rt) or_return) or_return + } else { + read_skip(r, c_size, rt) or_return + } + + case .path: + when T == Path_Chunk { + append(buf, read_path()) or_return + } else { + read_skip(r, c_size, rt) or_return + } + + case .tags: + when T == Tags_Chunk { + append(buf, read_tags(r, rt) or_return) or_return + } else { + read_skip(r, c_size, rt) or_return + } + + case .palette: + when T == Palette_Chunk { + append(buf, read_palette(r, rt) or_return) or_return + } else { + read_skip(r, c_size, rt) or_return + } + + case .user_data: + when T == User_Data_Chunk { + append(buf, read_user_data(r, rt) or_return) or_return + } else { + read_skip(r, c_size, rt) or_return + } + + case .slice: + when T == Slice_Chunk { + append(buf, read_slice(r, rt) or_return) or_return + } else { + read_skip(r, c_size, rt) or_return + } + + case .tileset: + when T == Tileset_Chunk { + append(buf, read_tileset(r, rt) or_return) or_return + } else { + read_skip(r, c_size, rt) or_return + } + + case .none: fallthrough + case: + log.error("Invalid Chunk Type", c_type) + return .Invalid_Chunk_Type + } + } + } + + return +} + |
