Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pre-Sort Mode #81

Merged
merged 13 commits into from
Jan 26, 2025
10 changes: 5 additions & 5 deletions Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,14 +47,14 @@ sudo apt install libgtk-3-dev
- Modifier Volumes.
- Implemented: Inclusion volumes and shadow bit over opaque and transparent geometry.
- Missing: Exclusion volumes.
- "Region Array Data Configuration" (written by the CPU directly to VRAM) are completely ignored.
- Z Clear bit.
- Flush Accumulate?
- Pre sort mode.
- Missing: Translucent MV in pre-sort mode.
- Region Array Data Configuration are mostly ignored.
- Z Clear bit.
- Flush Accumulate? (Secondary accumulate buffer)
- Multipass rendering.
- Fog LUT Mode 2.
- User Tile Clip, only the simplest version is supported.
- Bump mapping.
- Z-Write bit, especially for translucent polygons.
- Secondary accumulate buffer (very low priority, not sure if many games use this feature).
- Mipmaps for palette textures?
- Sort-DMA?
Expand Down
124 changes: 84 additions & 40 deletions src/debug_ui.zig
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,26 @@ fn display(self: anytype) void {
}
}

const Green: [4]f32 = .{ 0.51, 0.71, 0.212, 1.0 };
const Red: [4]f32 = .{ 0.973, 0.443, 0.408, 1.0 };

fn inline_bool(value: bool, comptime fmt: []const u8) void {
inline_colored(value, fmt, .{});
}

fn inline_colored(value: bool, comptime fmt: []const u8, args: anytype) void {
zgui.sameLine(.{});
colored(value, fmt, args);
}

fn colored(value: bool, comptime fmt: []const u8, args: anytype) void {
zgui.textColored(if (value) Green else Red, fmt, args);
}

fn text_highlighted(b: bool, comptime fmt: []const u8, args: anytype) void {
zgui.textColored(if (b) .{ 1.0, 1.0, 1.0, 1.0 } else .{ 1.0, 1.0, 1.0, 0.5 }, fmt, args);
}

pub fn init(d: *Deecy) !@This() {
var self = @This(){
._allocator = d._allocator,
Expand Down Expand Up @@ -163,10 +183,6 @@ fn reset_hover(self: *@This()) void {
}
}

fn text_highlighted(b: bool, comptime fmt: []const u8, args: anytype) void {
zgui.textColored(if (b) .{ 1.0, 1.0, 1.0, 1.0 } else .{ 1.0, 1.0, 1.0, 0.5 }, fmt, args);
}

fn compare_blocks(_: void, a: BasicBlock, b: BasicBlock) std.math.Order {
return std.math.order(a.time_spent, b.time_spent);
}
Expand Down Expand Up @@ -220,7 +236,7 @@ pub fn draw(self: *@This(), d: *Deecy) !void {
var addr = (if (pc >= 0x0C000000) std.math.clamp(pc, 0x0C000000 + range / 2, 0x0D000000 - range) else std.math.clamp(pc, 0x00000000 + range / 2, 0x02000000 - range)) - range / 2;
const end_addr = addr + range;
while (addr < end_addr) {
const disassembly = try sh4_disassembly.disassemble(.{ .value = dc.cpu.read16(@intCast(addr)) }, self._allocator);
const disassembly = try sh4_disassembly.disassemble(.{ .value = dc.cpu.read(u16, @intCast(addr)) }, self._allocator);
zgui.text("[{X:0>8}] {s} {s}", .{ addr, if (addr == pc) ">" else " ", disassembly });
addr += 2;
}
Expand Down Expand Up @@ -357,7 +373,7 @@ pub fn draw(self: *@This(), d: *Deecy) !void {
});
for (0..block.len) |i| {
const addr: u32 = block.start_addr + @as(u32, @intCast(2 * i));
const instr = dc.cpu.read16(addr);
const instr = dc.cpu.read(u16, addr);
const op = sh4.sh4_instructions.Opcodes[sh4.sh4_instructions.JumpTable[instr]];
zgui.text("{s} {X:0>6}: {s}", .{ if (op.use_fallback()) "!" else " ", addr, try sh4_disassembly.disassemble(@bitCast(instr), dc._allocator) });
}
Expand Down Expand Up @@ -462,9 +478,9 @@ pub fn draw(self: *@This(), d: *Deecy) !void {
const mask: u32 = @as(u32, 1) << @intCast(6 + i);
const interrupt_enabled = (dc.aica.debug_read_reg(u32, .SCIEB) & mask) != 0;
if (interrupt_enabled) {
zgui.textColored(.{ 0.0, 1.0, 0.0, 1.0 }, "!", .{});
zgui.textColored(Green, "!", .{});
} else {
zgui.textColored(.{ 1.0, 0.0, 0.0, 1.0 }, ".", .{});
zgui.textColored(Red, ".", .{});
}
zgui.sameLine(.{});
zgui.text("Timer " ++ number ++ ": Prescale: {X:0>1} - Value: {X:0>2}", .{ timer.prescale, timer.value });
Expand Down Expand Up @@ -495,11 +511,10 @@ pub fn draw(self: *@This(), d: *Deecy) !void {
_ = zgui.checkbox("Mute (Debug)", .{ .v = &dc.aica.channel_states[i].debug.mute });
const start_addr = channel.sample_address();

zgui.textColored(if (channel.play_control.key_on_bit) .{ 0.0, 1.0, 0.0, 1.0 } else .{ 1.0, 0.0, 0.0, 1.0 }, "KeyOn: {s: >3}", .{if (channel.play_control.key_on_bit) "Yes" else "No"});
zgui.sameLine(.{});
inline_colored(channel.play_control.key_on_bit, "KeyOn: {s: >3}", .{if (channel.play_control.key_on_bit) "Yes" else "No"});
zgui.text(" - {s} - ", .{@tagName(channel.play_control.sample_format)});
zgui.sameLine(.{});
zgui.textColored(if (channel.play_control.sample_loop) .{ 0.0, 1.0, 0.0, 1.0 } else .{ 1.0, 0.0, 0.0, 1.0 }, "Loop: {s: >3}", .{if (channel.play_control.sample_loop) "Yes" else "No"});
colored(channel.play_control.sample_loop, "Loop: {s: >3}", .{if (channel.play_control.sample_loop) "Yes" else "No"});
zgui.text("Addr: {X: >6} - Loop: {X:0>4} - {X:0>4}", .{
start_addr,
channel.loop_start,
Expand All @@ -508,22 +523,19 @@ pub fn draw(self: *@This(), d: *Deecy) !void {
zgui.text("FNS: {X:0>3} - Oct: {X:0>2}", .{ channel.sample_pitch_rate.fns, channel.sample_pitch_rate.oct });
zgui.text("DIPAN: {X:0>2} - DISDL: {X:0>1}", .{ channel.direct_pan_vol_send.pan, channel.direct_pan_vol_send.volume });
zgui.text("DSP Vol: {X:0>1} - DSP Chan: {X:0>1}", .{ channel.dps_channel_send.level, channel.dps_channel_send.channel });
zgui.textColored(if (state.playing) .{ 0.0, 1.0, 0.0, 1.0 } else .{ 1.0, 0.0, 0.0, 1.0 }, "{s: >7}", .{if (state.playing) "Playing" else "Stopped"});
zgui.sameLine(.{});
inline_colored(state.playing, "{s: >7}", .{if (state.playing) "Playing" else "Stopped"});
zgui.text("PlayPos: {X: >6} - ", .{state.play_position});
zgui.sameLine(.{});
zgui.textColored(if (state.loop_end_flag) .{ 0.0, 1.0, 0.0, 1.0 } else .{ 1.0, 0.0, 0.0, 1.0 }, "LoodEnd: {s: >3}", .{if (state.loop_end_flag) "Yes" else "No"});
inline_colored(state.loop_end_flag, "LoodEnd: {s: >3}", .{if (state.loop_end_flag) "Yes" else "No"});
const effective_rate = AICAModule.AICAChannelState.compute_effective_rate(channel, switch (state.amp_env_state) {
.Attack => channel.amp_env_1.attack_rate,
.Decay => channel.amp_env_1.decay_rate,
.Sustain => channel.amp_env_1.sustain_rate,
.Release => channel.amp_env_2.release_rate,
});
zgui.textColored(if (!channel.env_settings.voff) .{ 0.0, 1.0, 0.0, 1.0 } else .{ 1.0, 0.0, 0.0, 1.0 }, "AmpEnv ", .{});
zgui.sameLine(.{});
inline_colored(!channel.env_settings.voff, "AmpEnv ", .{});
zgui.text("{s: >7} - level: {X: >4} - rate: {X: >2}", .{ @tagName(state.amp_env_state), state.amp_env_level, effective_rate });
zgui.textColored(if (!channel.env_settings.lpoff) .{ 0.0, 1.0, 0.0, 1.0 } else .{ 1.0, 0.0, 0.0, 1.0 }, "FilEnv ", .{});
zgui.sameLine(.{});
inline_colored(!channel.env_settings.lpoff, "FilEnv ", .{});
zgui.text("{s: >7} - level: {X: >4}", .{ @tagName(state.filter_env_state), state.filter_env_level });
zgui.text("ALFOS {X: >1} ALFOWS {X: >1} PLFOS {X: >1} PLFOWS {X: >1} F {X: >2} R {any}", .{
channel.lfo_control.amplitude_modulation_depth,
Expand Down Expand Up @@ -602,22 +614,22 @@ pub fn draw(self: *@This(), d: *Deecy) !void {
while (addr < end_addr) {
zgui.text("[{X:0>8}] {X:0>2} {X:0>2} {X:0>2} {X:0>2} {X:0>2} {X:0>2} {X:0>2} {X:0>2} {c}{c}{c}{c}{c}{c}{c}{c}", .{
addr,
dc.cpu.read8(@intCast(addr)),
dc.cpu.read8(@intCast(addr + 1)),
dc.cpu.read8(@intCast(addr + 2)),
dc.cpu.read8(@intCast(addr + 3)),
dc.cpu.read8(@intCast(addr + 4)),
dc.cpu.read8(@intCast(addr + 5)),
dc.cpu.read8(@intCast(addr + 6)),
dc.cpu.read8(@intCast(addr + 7)),
printable_ascii(dc.cpu.read8(@intCast(addr))),
printable_ascii(dc.cpu.read8(@intCast(addr + 1))),
printable_ascii(dc.cpu.read8(@intCast(addr + 2))),
printable_ascii(dc.cpu.read8(@intCast(addr + 3))),
printable_ascii(dc.cpu.read8(@intCast(addr + 4))),
printable_ascii(dc.cpu.read8(@intCast(addr + 5))),
printable_ascii(dc.cpu.read8(@intCast(addr + 6))),
printable_ascii(dc.cpu.read8(@intCast(addr + 7))),
dc.cpu.read(u8, @intCast(addr)),
dc.cpu.read(u8, @intCast(addr + 1)),
dc.cpu.read(u8, @intCast(addr + 2)),
dc.cpu.read(u8, @intCast(addr + 3)),
dc.cpu.read(u8, @intCast(addr + 4)),
dc.cpu.read(u8, @intCast(addr + 5)),
dc.cpu.read(u8, @intCast(addr + 6)),
dc.cpu.read(u8, @intCast(addr + 7)),
printable_ascii(dc.cpu.read(u8, @intCast(addr))),
printable_ascii(dc.cpu.read(u8, @intCast(addr + 1))),
printable_ascii(dc.cpu.read(u8, @intCast(addr + 2))),
printable_ascii(dc.cpu.read(u8, @intCast(addr + 3))),
printable_ascii(dc.cpu.read(u8, @intCast(addr + 4))),
printable_ascii(dc.cpu.read(u8, @intCast(addr + 5))),
printable_ascii(dc.cpu.read(u8, @intCast(addr + 6))),
printable_ascii(dc.cpu.read(u8, @intCast(addr + 7))),
});
addr += 8;
}
Expand Down Expand Up @@ -677,6 +689,38 @@ pub fn draw(self: *@This(), d: *Deecy) !void {
zgui.text("FB_R_SOF2: 0x{X:0>8}", .{FB_R_SOF2});
zgui.text("FB_R_SIZE: 0x{X:0>8} - {any}", .{ @as(u32, @bitCast(FB_R_SIZE)), FB_R_SIZE });
zgui.text("VO_CONTROL: {any}", .{VO_CONTROL});
if (zgui.collapsingHeader("FPU_PARAM_CFG", .{ .default_open = true }))
display(dc.gpu._get_register(Holly.FPU_PARAM_CFG, .FPU_PARAM_CFG).*);
if (zgui.collapsingHeader("TA_ALLOC_CTRL", .{ .default_open = true }))
display(dc.gpu._get_register(Holly.TA_ALLOC_CTRL, .TA_ALLOC_CTRL).*);

if (zgui.collapsingHeader("Region Array", .{ .frame_padding = true })) {
zgui.indent(.{});
defer zgui.unindent(.{});
const region_base = dc.gpu.read_register(u32, .REGION_BASE);
zgui.text("REGION_BASE: 0x{X:0>8}", .{region_base});
const static = struct {
var view_all: bool = false;
};
_ = zgui.checkbox("View All", .{ .v = &static.view_all });
var region = dc.gpu.get_region_array_data_config(0);
var idx: usize = 1;
while (idx < 512) : (idx += 1) {
zgui.text("[{d:<3}] {d:<2} {d:<2}", .{ idx, region.settings.tile_x_position, region.settings.tile_y_position });
inline_bool(region.settings.flush_accumulate, "Flush-Accumulate ");
inline_bool(region.settings.z_clear, "Z-Clear ");
inline_bool(region.settings.pre_sort, "Pre-Sort ");
inline_bool(region.settings.last_region, "Last-Region ");
zgui.text(" ", .{});
inline_colored(!region.opaque_list_pointer.empty, "{X:<8} ", .{region.opaque_list_pointer.pointer_to_object_list});
inline_colored(!region.opaque_modifier_volume_pointer.empty, "{X:<8} ", .{region.opaque_modifier_volume_pointer.pointer_to_object_list});
inline_colored(!region.translucent_list_pointer.empty, "{X:<8} ", .{region.translucent_list_pointer.pointer_to_object_list});
inline_colored(!region.translucent_modifier_volume_pointer.empty, "{X:<8} ", .{region.translucent_modifier_volume_pointer.pointer_to_object_list});
inline_colored(!region.punch_through_list_pointer.empty, "{X:<8} ", .{region.punch_through_list_pointer.pointer_to_object_list});
if (!static.view_all and region.settings.last_region) break;
region = dc.gpu.get_region_array_data_config(idx);
}
}

var buffer: [256]u8 = .{0} ** 256;

Expand Down Expand Up @@ -806,15 +850,15 @@ pub fn draw(self: *@This(), d: *Deecy) !void {
if (addr >= 0x04800000 - bytes_per_pixels) break;
switch (static.format & 0b111) {
0x0, 0x3 => { // 0555 KRGB 16 bits
const color: Color16 = .{ .value = dc.cpu.read16(addr) };
const color: Color16 = .{ .value = dc.cpu.read(u16, addr) };
self.pixels[4 * i + 0] = @as(u8, @intCast(color.argb1555.r)) << 3;
self.pixels[4 * i + 1] = @as(u8, @intCast(color.argb1555.g)) << 3;
self.pixels[4 * i + 2] = @as(u8, @intCast(color.argb1555.b)) << 3;
self.pixels[4 * i + 3] = 255; // FIXME: Not really.
i += 1;
},
0x1 => { // 565 RGB 16 bit
const color: Color16 = .{ .value = dc.cpu.read16(addr) };
const color: Color16 = .{ .value = dc.cpu.read(u16, addr) };
self.pixels[4 * i + 0] = @as(u8, @intCast(color.rgb565.r)) << 3;
self.pixels[4 * i + 1] = @as(u8, @intCast(color.rgb565.g)) << 2;
self.pixels[4 * i + 2] = @as(u8, @intCast(color.rgb565.b)) << 3;
Expand All @@ -823,10 +867,10 @@ pub fn draw(self: *@This(), d: *Deecy) !void {
},
// ARGB 32-Bits
0x6 => {
self.pixels[4 * i + 0] = dc.cpu.read8(@intCast(addr + 3));
self.pixels[4 * i + 1] = dc.cpu.read8(@intCast(addr + 2));
self.pixels[4 * i + 2] = dc.cpu.read8(@intCast(addr + 1));
self.pixels[4 * i + 3] = dc.cpu.read8(@intCast(addr + 0));
self.pixels[4 * i + 0] = dc.cpu.read(u8, @intCast(addr + 3));
self.pixels[4 * i + 1] = dc.cpu.read(u8, @intCast(addr + 2));
self.pixels[4 * i + 2] = dc.cpu.read(u8, @intCast(addr + 1));
self.pixels[4 * i + 3] = dc.cpu.read(u8, @intCast(addr + 0));
i += 1;
},
else => {
Expand Down
5 changes: 3 additions & 2 deletions src/deecy_ui.zig
Original file line number Diff line number Diff line change
Expand Up @@ -146,13 +146,14 @@ pub fn upload_vmu_texture(self: *@This(), controller: u8, index: u8) void {
}

pub fn draw_vmus(self: *@This(), editable: bool) void {
if (!editable and !self.deecy.config.display_vmus) return;
if ((editable and self.deecy.config.display_debug_ui) or (!editable and !self.deecy.config.display_vmus)) return;

zgui.setNextWindowSize(.{ .w = 4 * 48, .h = 2 * 4 * 32, .cond = .first_use_ever });
zgui.setNextWindowPos(.{ .x = 32, .y = 32, .cond = .first_use_ever });

zgui.pushStyleVar2f(.{ .idx = .window_padding, .v = .{ 0.0, 0.0 } });

if (zgui.begin("VMUs", .{ .flags = .{ .no_resize = !editable, .no_move = !editable, .no_title_bar = !editable, .no_mouse_inputs = !editable, .no_nav_inputs = !editable, .no_nav_focus = !editable, .no_background = !editable } })) {
if (zgui.begin("VMUs", .{ .flags = .{ .no_resize = !editable, .no_move = !editable, .no_title_bar = !editable, .no_mouse_inputs = !editable, .no_nav_inputs = !editable, .no_nav_focus = !editable, .no_background = !editable, .no_docking = true } })) {
const win_width = zgui.getWindowSize()[0];
for (0..self.vmu_displays.len) |controller| {
for (0..2) |index| {
Expand Down
Loading
Loading