Skip to content

Commit 9f92291

Browse files
committed
feat: init sarc + (clim + darc dumping)
* horizon/fmt: init sarc and clim * tools/Archive: init Sarc and Darc dumping * tools/Layout: init Image
1 parent 2f3e78e commit 9f92291

28 files changed

Lines changed: 919 additions & 63 deletions

File tree

README.md

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ You can (and are encouraged) to look at the `tools` directory as it is a good ex
112112
- 🟢 Smdh (tools/Smdh): Make / Dump
113113
- 🟢 3dsx (tools/3dsx): Make / Dump
114114
- 🟢 Pica (tools/Pica): Assemble / Disassemble
115-
- 🟢 Assemble: Only **Z**itrus**P**ica**Sh**aders are implemented as an output format.
115+
- 🟢 Assemble: Only **Z**itrus**P**ica**Sh**ader's are implemented as an output format.
116116
- 🟢 Disassemble: Outputs **Z**itrus**P**ica**A**sse**m**bly. Either RAW instructions, ZPSH's or DVL's (.shbin) can be disassembled.
117117
- 🟢 Firm (tools/Firm): Make / Info / Dump
118118
- 🟢 Make: Confirmed to build (and boot!) Luma3DS from source, however needs more testing as the firm is not 1:1.
@@ -124,9 +124,13 @@ You can (and are encouraged) to look at the `tools` directory as it is a good ex
124124
- 🟡 Yaz0 (Compress/Yaz): Decompression
125125
- 🟡 LZ10 (Compress/Lz10): Decompression
126126
- 🟡 LZ11 (Compress/Lz11): Decompression
127-
- 🟡 Archives:
128-
- 🟡 Darc (Archive/Darc): List
129-
- 🔴 Sarc
127+
- 🟡 Archives (tools/Archive):
128+
- 🟡 Darc (Archive/Darc): List / Dump
129+
- 🟡 Sarc (Archive/Sarc): List
130+
- 🟡 Layouts (tools/Layout):
131+
- 🟡 Image (Layout/Image): Dump
132+
- 🔴 Layout
133+
- 🔴 Animation
130134
- 🔴 Cro0 / Crr0
131135
- 🔴 Cia
132136

src/compress.zig

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
pub const etc = @import("compress/etc.zig");
2+
13
pub const lz = @import("compress/lz.zig");
24
pub const yaz = @import("compress/yaz.zig");
35
pub const lz10 = @import("compress/lz10.zig");

src/compress/etc.zig

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
//! Ericsson Texture Compression Decoder
2+
//!
3+
//!
4+
//! TODO: Move this into its own library
5+
6+
pub const pixels_per_block = 4;
7+
8+
/// All fields should be read as big endian.
9+
pub const Pkm = extern struct {
10+
pub const Format = enum(u16) {
11+
etc1_rgb,
12+
etc2_rgb,
13+
etc2_rgba_old,
14+
etc2_rgba,
15+
etc2_rgba1,
16+
etc2_r,
17+
etc2_rg,
18+
etc2_r_signed,
19+
etc2_rg_signed,
20+
_,
21+
};
22+
23+
pub const magic_value = "PKM ";
24+
25+
magic: [magic_value.len]u8 = magic_value.*,
26+
/// "10" for ETC1, "20" for ETC2
27+
version: [2]u8 = "10".*,
28+
format: Format,
29+
width: u16,
30+
height: u16,
31+
real_width: u16,
32+
real_height: u16,
33+
};

src/compress/lz10.zig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
//! LZ11 decompressor and (TODO) compressor.
1+
//! LZ10 decompressor and (TODO) compressor.
22
//!
33
//! LZ-like compression format where the maximum match offset is `4096` and length `18`.
44
//!

src/hardware/pica.zig

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,42 @@ pub const morton = struct {
102102

103103
return values;
104104
}
105+
106+
pub const Strategy = enum { tile, untile };
107+
108+
pub fn convert(comptime T: type, comptime strategy: Strategy, comptime tile_size: usize, width: usize, dst_pixels: []T, src_pixels: []const T) void {
109+
std.debug.assert(dst_pixels.len == src_pixels.len);
110+
const max_tile_subindex = (tile_size * tile_size);
111+
const SubindexInt = std.math.IntFittingRange(0, max_tile_subindex - 1);
112+
113+
const height = @divExact(src_pixels.len, width);
114+
const width_tiles = @divExact(width, tile_size);
115+
const height_tiles = @divExact(height, tile_size);
116+
117+
var i: u16 = 0;
118+
for (0..height_tiles) |y_tile| {
119+
const y_start = y_tile * tile_size;
120+
121+
for (0..width_tiles) |x_tile| {
122+
const x_start = x_tile * tile_size;
123+
124+
for (0..max_tile_subindex) |tile| {
125+
const x, const y = toDimensions(SubindexInt, 2, @intCast(tile));
126+
127+
const linear_index = i;
128+
const morton_index = (y_start + y) * width + x_start + x;
129+
130+
const src_pixel, const dst_pixel = switch (strategy) {
131+
.tile => .{ &src_pixels[morton_index], &dst_pixels[linear_index] },
132+
.untile => .{ &src_pixels[linear_index], &dst_pixels[morton_index] },
133+
};
134+
135+
dst_pixel.* = src_pixel.*;
136+
i += 1;
137+
}
138+
}
139+
}
140+
}
105141
};
106142

107143
pub const Screen = enum(u1) {
@@ -547,6 +583,16 @@ pub const TextureUnitFormat = enum(u4) {
547583
a4,
548584
etc1,
549585
etc1a4,
586+
587+
pub fn scale(format: TextureUnitFormat, size: usize) usize {
588+
return switch (format) {
589+
.abgr8888 => size << 2,
590+
.bgr888 => size * 3,
591+
.rgba5551, .rgb565, .rgba4444, .ia88, .hilo88 => size << 1,
592+
.i8, .a8, .ia44, .etc1a4 => size,
593+
.i4, .a4, .etc1 => size >> 1,
594+
};
595+
}
550596
};
551597

552598
pub const TextureUnitTexture2Coordinates = enum(u1) {

src/horizon/fmt.zig

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ pub const ncch = @import("fmt/ncch.zig");
2626
pub const dvl = @import("fmt/dvl.zig");
2727

2828
pub const archive = @import("fmt/archive.zig");
29+
pub const layout = @import("fmt/layout.zig");
2930
pub const audio = @import("fmt/audio.zig");
3031
pub const cro0 = @import("fmt/cro0.zig");
3132

@@ -38,6 +39,7 @@ comptime {
3839
_ = dvl;
3940

4041
_ = archive;
42+
_ = layout;
4143
_ = audio;
4244
_ = cro0;
4345
}

src/horizon/fmt/archive.zig

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,7 @@
11
pub const darc = @import("archive/darc.zig");
2+
pub const sarc = @import("archive/sarc.zig");
3+
4+
comptime {
5+
_ = darc;
6+
_ = sarc;
7+
}

src/horizon/fmt/archive/darc.zig

Lines changed: 34 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -67,14 +67,45 @@ pub const TableEntry = extern struct {
6767
attributes: Attributes,
6868
info: Info,
6969

70-
pub fn name(entry: TableEntry, table: []const u16) []const u16 {
70+
pub fn name(entry: TableEntry, table: []const u16) [:0]const u16 {
7171
return std.mem.span(@as([*:0]const u16, @ptrCast(table))[@divExact(entry.attributes.name_offset, 2)..]);
7272
}
7373
};
7474

7575
pub const View = struct {
76-
pub const File = enum(u32) { _ };
77-
pub const Directory = enum(u32) { root = 0, _ };
76+
pub const Directory = enum(u32) {
77+
root = 0,
78+
_,
79+
80+
pub fn name(directory: Directory, view: View) [:0]const u16 {
81+
return view.entries[@intFromEnum(directory)].name(view.name_table);
82+
}
83+
};
84+
85+
pub const File = enum(u32) {
86+
pub const Stat = struct {
87+
/// Offset of file data starting from `data_offset`.
88+
offset: u32,
89+
/// Size of the file in bytes.
90+
size: u32,
91+
};
92+
93+
_,
94+
95+
pub fn name(file: File, view: View) [:0]const u16 {
96+
return view.entries[@intFromEnum(file)].name(view.name_table);
97+
}
98+
99+
pub fn stat(file: File, view: View) Stat {
100+
const file_meta = view.entries[@intFromEnum(file)];
101+
102+
return .{
103+
.offset = file_meta.info.file.offset,
104+
.size = file_meta.info.file.size,
105+
};
106+
}
107+
};
108+
78109
pub const Entry = struct {
79110
pub const Handle = enum(u32) { _ };
80111

0 commit comments

Comments
 (0)