From 719c97c9e47706406234308e47a8c124efb8c62e Mon Sep 17 00:00:00 2001 From: Zack Buhman Date: Wed, 16 Jul 2025 14:38:19 -0500 Subject: [PATCH] add view transform, input, and grid primitive --- demo.mk | 4 +- src/demo/ballistics.cpp | 46 +++---- src/demo/ballistics.hpp | 38 ++++++ src/demo/demo.cpp | 157 ++---------------------- src/demo/graphics.cpp | 205 ++++++++++++++++++++++++++++++++ src/demo/graphics.hpp | 7 ++ src/demo/graphics_primitive.hpp | 56 +++++++++ src/demo/input.cpp | 116 ++++++++++++++++++ src/demo/input.hpp | 26 ++++ src/demo/scene.hpp | 11 ++ 10 files changed, 483 insertions(+), 183 deletions(-) create mode 100644 src/demo/ballistics.hpp create mode 100644 src/demo/graphics.hpp create mode 100644 src/demo/graphics_primitive.hpp create mode 100644 src/demo/input.cpp create mode 100755 src/demo/input.hpp create mode 100644 src/demo/scene.hpp diff --git a/demo.mk b/demo.mk index 9f17629..6a8ade8 100644 --- a/demo.mk +++ b/demo.mk @@ -10,7 +10,9 @@ DEMO_OBJ = \ $(LIB)/printf/printf.o \ $(LIB)/printf/unparse.o \ $(LIB)/printf/parse.o \ - src/demo/demo.o + src/demo/demo.o \ + src/demo/graphics.o \ + src/demo/input.o demo.elf: LDSCRIPT = $(LIB)/main.lds demo.elf: $(START_OBJ) $(DEMO_OBJ) $(LIBGCC) diff --git a/src/demo/ballistics.cpp b/src/demo/ballistics.cpp index aef6e97..895b978 100644 --- a/src/demo/ballistics.cpp +++ b/src/demo/ballistics.cpp @@ -1,46 +1,26 @@ #include "physics/particle.hpp" -namespace demo::ballistic { +#include "demo/ballistics.hpp" - enum struct projectile_type { - NONE, - PISTOL, - ARTILLERY, - FIREBALL, - LASER - }; +namespace demo { - struct projectile + void ballistics::init() { - physics::particle particle; - projectile_type type; - uint32_t start_time; - - void draw() - { - } - }; - - constexpr int max_projectiles = 32; - projectile projectiles[max_projectiles]; - projectile_type current_projectile_type; - - void init() - { - current_projectile_type = PISTOL; + current_projectile_type = projectile_type::PISTOL; for (int i = 0; i < max_projectiles; i++) { projectiles[i].type = projectile_type::NONE; } } - void fire() + void ballistics::fire() { projectile * projectile; - for (int i = 0; i < max_projectiles; i++) { + int i; + for (i = 0; i < max_projectiles; i++) { projectile = &projectiles[i]; - if (projectile->type == UNUSED) + if (projectile->type == projectile_type::NONE) break; } @@ -72,6 +52,8 @@ namespace demo::ballistic { projectile->particle.acceleration = vec3(0.0f, 0.0f, 0.0f); projectile->particle.damping = 0.99f; break; + default: + break; } projectile->particle.position = vec3(0.0f, 1.5f, 0.0f); @@ -80,20 +62,20 @@ namespace demo::ballistic { //projectile->particle.clear_accumulator(); FIXME } - void update() + void ballistics::update() { float duration = 1.0f / 60.0f; for (int i = 0; i < max_projectiles; i++) { projectile * projectile = &projectiles[i]; - if (projectile->type == projectile_type::UNUSED) + if (projectile->type == projectile_type::NONE) continue; - projectile->integrate(duration); + projectile->particle.integrate(duration); } } - void draw() + void ballistics::draw() { } } diff --git a/src/demo/ballistics.hpp b/src/demo/ballistics.hpp new file mode 100644 index 0000000..f453397 --- /dev/null +++ b/src/demo/ballistics.hpp @@ -0,0 +1,38 @@ +#pragma once + +#include +#include "demo/scene.hpp" +#include "physics/particle.hpp" + +namespace demo { + struct ballistics : scene { + + enum struct projectile_type { + NONE, + PISTOL, + ARTILLERY, + FIREBALL, + LASER + }; + + struct projectile + { + physics::particle particle; + projectile_type type; + uint32_t start_time; + + void draw() + { + } + }; + + constexpr static int max_projectiles = 32; + projectile projectiles[max_projectiles]; + projectile_type current_projectile_type; + + void init() override; + void fire() override; + void update() override; + void draw() override; + }; +}; diff --git a/src/demo/demo.cpp b/src/demo/demo.cpp index 65b941d..c6a4809 100644 --- a/src/demo/demo.cpp +++ b/src/demo/demo.cpp @@ -2,19 +2,8 @@ #include "interrupt.hpp" //#include "aica/aica.hpp" -#include "holly/holly.hpp" -#include "holly/ta_bits.hpp" -#include "holly/region_array.hpp" -#include "holly/background.hpp" -#include "holly/core_bits.hpp" -#include "holly/core.hpp" -#include "holly/framebuffer.hpp" -#include "holly/texture_memory_alloc9.hpp" -#include "holly/ta_fifo_texture_memory_transfer.hpp" -#include "holly/ta_fifo_polygon_converter.hpp" - -#include "ta_parameter_presets.hpp" - +#include "demo/graphics.hpp" +#include "demo/input.hpp" #include "printf/printf.h" void vbr100() @@ -29,48 +18,6 @@ void vbr400() interrupt_exception(); } -static volatile int ta_in_use = 0; -static volatile int core_in_use = 0; -static volatile int next_frame = 0; -static volatile int framebuffer_ix = 0; -static volatile int next_frame_ix = 0; - -static inline void graphics_interrupt(uint32_t istnrm) -{ - if (istnrm & istnrm::v_blank_in) { - system.ISTNRM = istnrm::v_blank_in; - - next_frame = 1; - holly.FB_R_SOF1 = texture_memory_alloc.framebuffer[next_frame_ix].start; - holly.FB_R_SOF2 = texture_memory_alloc.framebuffer[next_frame_ix].start; - } - - if (istnrm & istnrm::end_of_render_tsp) { - system.ISTNRM = istnrm::end_of_render_tsp - | istnrm::end_of_render_isp - | istnrm::end_of_render_video; - - next_frame_ix = framebuffer_ix; - framebuffer_ix += 1; - if (framebuffer_ix >= 3) framebuffer_ix = 0; - - core_in_use = 0; - } - - if (istnrm & istnrm::end_of_transferring_opaque_list) { - system.ISTNRM = istnrm::end_of_transferring_opaque_list; - - core_in_use = 1; - core_start_render2(texture_memory_alloc.region_array.start, - texture_memory_alloc.isp_tsp_parameters.start, - texture_memory_alloc.background[0].start, - texture_memory_alloc.framebuffer[framebuffer_ix].start, - framebuffer::framebuffer.px_width); - - ta_in_use = 0; - } -} - static bool inside_interrupt = false; void vbr600() @@ -91,7 +38,7 @@ void vbr600() serial::integer(system.ISTERR); } - graphics_interrupt(istnrm); + graphics::interrupt(istnrm); } else if (sh7091.CCN.EXPEVT == 0 && sh7091.CCN.INTEVT == 0x360) { // AICA //wait(); aica_sound.common.mcire = (1 << 6); // interrupt timer A @@ -106,110 +53,20 @@ void vbr600() inside_interrupt = false; } -void draw(ta_parameter_writer& writer) -{ - global_polygon_intensity(writer, {1.0, 0.0, 0.0}); - - quad_type_2(writer, - {10, 10, 1}, - {90, 10, 1}, - {90, 90, 1}, - {10, 90, 1}, - 1.0); - - writer.append() = - ta_global_parameter::end_of_list(para_control::para_type::end_of_list); -} - void main() { serial::init(0); - core_init(); - framebuffer::scaler_init(); - - // read - while (spg_status::vsync(holly.SPG_STATUS)); - while (!spg_status::vsync(holly.SPG_STATUS)); - - system.LMMODE0 = 1; // 32-bit address space - system.LMMODE1 = 1; // 32-bit address space - - int length = texture_memory_alloc.framebuffer[2].start; - ta_fifo_texture_memory_transfer::zeroize(&ta_fifo_texture_memory[0 / 4], - length, - 0x00c0bebc); - ta_fifo_texture_memory_transfer::zeroize(&ta_fifo_texture_memory[length / 4], - 720 * 480 * 2, - 0xc5f7c5f7); - - framebuffer::spg_set_mode_640x480_vga(); - framebuffer::init(640, 480, - texture_memory_alloc.framebuffer[0].start); - core_param_init(texture_memory_alloc.region_array.start, - texture_memory_alloc.isp_tsp_parameters.start, - texture_memory_alloc.background[0].start, - framebuffer::framebuffer.px_width); - - holly.SOFTRESET = softreset::pipeline_soft_reset - | softreset::ta_soft_reset; - holly.SOFTRESET = 0; - - uint32_t ta_alloc - = ta_alloc_ctrl::pt_opb::no_list - | ta_alloc_ctrl::tm_opb::no_list - | ta_alloc_ctrl::t_opb::no_list - | ta_alloc_ctrl::om_opb::no_list - | ta_alloc_ctrl::o_opb::_32x4byte; - - struct opb_size opb_size = { - .opaque = 32 * 4, - .opaque_modifier = 0, - .translucent = 0, - .translucent_modifier = 0, - .punch_through = 0 - }; - - - background_parameter2(texture_memory_alloc.background[0].start, - 0x110012); - - region_array_multipass(framebuffer::framebuffer.tile_width(), - framebuffer::framebuffer.tile_height(), - &opb_size, - 1, - texture_memory_alloc.region_array.start, - texture_memory_alloc.object_list.start); - - static uint8_t op_buf[1024 * 1024] __attribute__((aligned(32))); - ta_parameter_writer writer(op_buf, (sizeof (op_buf))); + input::init(); + graphics::init(); interrupt_init(); - system.IML6NRM = istnrm::end_of_render_tsp | istnrm::v_blank_in | istnrm::end_of_transferring_opaque_list; while (1) { - writer.offset = 0; - draw(writer); - - while (ta_in_use); - while (core_in_use); - ta_in_use = 1; - ta_polygon_converter_init2(texture_memory_alloc.isp_tsp_parameters.start, - texture_memory_alloc.isp_tsp_parameters.end, - texture_memory_alloc.object_list.start, - texture_memory_alloc.object_list.end, - opb_size.total(), - ta_alloc, - framebuffer::framebuffer.tile_width(), - framebuffer::framebuffer.tile_height()); - - ta_polygon_converter_writeback(writer.buf, writer.offset); - ta_polygon_converter_transfer(writer.buf, writer.offset); - - while (next_frame == 0); - next_frame = 0; + input::update(); + graphics::step(); } } diff --git a/src/demo/graphics.cpp b/src/demo/graphics.cpp index 8b13789..c97287b 100644 --- a/src/demo/graphics.cpp +++ b/src/demo/graphics.cpp @@ -1 +1,206 @@ +#include +#include "systembus.hpp" +#include "systembus_bits.hpp" + +#include "holly/holly.hpp" +#include "holly/ta_bits.hpp" +#include "holly/region_array.hpp" +#include "holly/background.hpp" +#include "holly/core_bits.hpp" +#include "holly/core.hpp" +#include "holly/framebuffer.hpp" +#include "holly/texture_memory_alloc9.hpp" +#include "holly/ta_fifo_texture_memory_transfer.hpp" +#include "holly/ta_fifo_polygon_converter.hpp" + +#include "ta_parameter_presets.hpp" + +#include "math/transform.hpp" + +#include "demo/graphics_primitive.hpp" +#include "demo/graphics.hpp" +#include "demo/ballistics.hpp" +#include "demo/input.hpp" + +#include "maple/maple_bus_bits.hpp" + +namespace graphics { + + static uint8_t op_buf[1024 * 1024] __attribute__((aligned(32))); + static ta_parameter_writer writer(op_buf, (sizeof (op_buf))); + + static volatile int ta_in_use = 0; + static volatile int core_in_use = 0; + static volatile int next_frame = 0; + static volatile int framebuffer_ix = 0; + static volatile int next_frame_ix = 0; + + constexpr uint32_t ta_alloc + = ta_alloc_ctrl::pt_opb::no_list + | ta_alloc_ctrl::tm_opb::no_list + | ta_alloc_ctrl::t_opb::no_list + | ta_alloc_ctrl::om_opb::no_list + | ta_alloc_ctrl::o_opb::_32x4byte; + + const opb_size opb_size = { + .opaque = 32 * 4, + .opaque_modifier = 0, + .translucent = 0, + .translucent_modifier = 0, + .punch_through = 0 + }; + + mat4x4 view_trans; + + void interrupt(uint32_t istnrm) + { + if (istnrm & istnrm::v_blank_in) { + system.ISTNRM = istnrm::v_blank_in; + + next_frame = 1; + holly.FB_R_SOF1 = texture_memory_alloc.framebuffer[next_frame_ix].start; + holly.FB_R_SOF2 = texture_memory_alloc.framebuffer[next_frame_ix].start; + } + + if (istnrm & istnrm::end_of_render_tsp) { + system.ISTNRM = istnrm::end_of_render_tsp + | istnrm::end_of_render_isp + | istnrm::end_of_render_video; + + next_frame_ix = framebuffer_ix; + framebuffer_ix += 1; + if (framebuffer_ix >= 3) framebuffer_ix = 0; + + core_in_use = 0; + } + + if (istnrm & istnrm::end_of_transferring_opaque_list) { + system.ISTNRM = istnrm::end_of_transferring_opaque_list; + + core_in_use = 1; + core_start_render2(texture_memory_alloc.region_array.start, + texture_memory_alloc.isp_tsp_parameters.start, + texture_memory_alloc.background[0].start, + texture_memory_alloc.framebuffer[framebuffer_ix].start, + framebuffer::framebuffer.px_width); + + ta_in_use = 0; + } + } + + void draw() + { + global_polygon_intensity(writer, {1.0, 0.0, 0.0}); + + quad_type_2(writer, + {10, 10, 1}, + {90, 10, 1}, + {90, 90, 1}, + {10, 90, 1}, + 1.0); + + draw_grid(writer, view_trans); + + writer.append() = + ta_global_parameter::end_of_list(para_control::para_type::end_of_list); + } + + void init() + { + core_init(); + framebuffer::scaler_init(); + + // read + while (spg_status::vsync(holly.SPG_STATUS)); + while (!spg_status::vsync(holly.SPG_STATUS)); + + system.LMMODE0 = 1; // 32-bit address space + system.LMMODE1 = 1; // 32-bit address space + + int length = texture_memory_alloc.framebuffer[2].start; + ta_fifo_texture_memory_transfer::zeroize(&ta_fifo_texture_memory[0 / 4], + length, + 0x00c0bebc); + ta_fifo_texture_memory_transfer::zeroize(&ta_fifo_texture_memory[length / 4], + 720 * 480 * 2, + 0xc5f7c5f7); + + framebuffer::spg_set_mode_640x480_vga(); + framebuffer::init(640, 480, + texture_memory_alloc.framebuffer[0].start); + core_param_init(texture_memory_alloc.region_array.start, + texture_memory_alloc.isp_tsp_parameters.start, + texture_memory_alloc.background[0].start, + framebuffer::framebuffer.px_width); + + holly.SOFTRESET = softreset::pipeline_soft_reset + | softreset::ta_soft_reset; + holly.SOFTRESET = 0; + + background_parameter2(texture_memory_alloc.background[0].start, + 0x110012); + + region_array_multipass(framebuffer::framebuffer.tile_width(), + framebuffer::framebuffer.tile_height(), + &opb_size, + 1, + texture_memory_alloc.region_array.start, + texture_memory_alloc.object_list.start); + + vec3 t = {framebuffer::framebuffer.px_width / 2.f, framebuffer::framebuffer.px_height / 2.f, 0}; + float s = framebuffer::framebuffer.px_height / 3.f; + + view_trans + = translate(t) + * scale(vec3(s, s, 1)) + * translate(vec3(0, 0, 10)) + * scale(vec3(-1, -1, 1)); + } + + void view_transform() + { + for (int port_ix = 0; port_ix < 4; port_ix++) { + auto& port = input::state.port[port_ix]; + if ((port.function_type & function_type::controller) != 0 && port.host_response_data_transfer_ft0 != nullptr) { + auto& bus_data = port.host_response_data_transfer_ft0->bus_data; + auto& data_fields = bus_data.data_fields; + if ((std::byteswap(data_fields.function_type) & function_type::controller) == 0) + continue; + + auto& data = data_fields.data; + + float dx = static_cast(data.analog_coordinate_axis[2] - 0x80) * 0.001; + float dy = static_cast(data.analog_coordinate_axis[3] - 0x80) * 0.001; + + view_trans = view_trans * rotate_x(dx) * rotate_y(dy); + } + } + } + + void step() + { + view_transform(); + + writer.offset = 0; + draw(); + + while (ta_in_use); + while (core_in_use); + ta_in_use = 1; + ta_polygon_converter_init2(texture_memory_alloc.isp_tsp_parameters.start, + texture_memory_alloc.isp_tsp_parameters.end, + texture_memory_alloc.object_list.start, + texture_memory_alloc.object_list.end, + opb_size.total(), + ta_alloc, + framebuffer::framebuffer.tile_width(), + framebuffer::framebuffer.tile_height()); + + ta_polygon_converter_writeback(writer.buf, writer.offset); + ta_polygon_converter_transfer(writer.buf, writer.offset); + + while (next_frame == 0); + next_frame = 0; + } +} diff --git a/src/demo/graphics.hpp b/src/demo/graphics.hpp new file mode 100644 index 0000000..43ac3e2 --- /dev/null +++ b/src/demo/graphics.hpp @@ -0,0 +1,7 @@ +#pragma once + +namespace graphics { + void interrupt(uint32_t istnrm); + void init(); + void step(); +}; diff --git a/src/demo/graphics_primitive.hpp b/src/demo/graphics_primitive.hpp new file mode 100644 index 0000000..875e2b8 --- /dev/null +++ b/src/demo/graphics_primitive.hpp @@ -0,0 +1,56 @@ +#include "ta_parameter_presets.hpp" +#include "math/math.hpp" + +#define _fsrra(n) (1.0f / (sqrt(n))) + +static inline void draw_line(ta_parameter_writer& writer, + const vec3& p1, + const vec3& p2, + const vec3& color) +{ + float dy = p2.y - p1.y; + float dx = p2.x - p1.x; + float d = _fsrra(dx * dx + dy * dy) * 0.5f; + float dy1 = dy * d; + float dx1 = dx * d; + + vec3 ap = { p1.x + dy1, p1.y + -dx1, p1.z }; + vec3 bp = { p1.x + -dy1, p1.y + dx1, p1.z }; + vec3 cp = { p2.x + -dy1, p2.y + dx1, p2.z }; + vec3 dp = { p2.x + dy1, p2.y + -dx1, p2.z }; + + const float intensity = 1.0f; + quad_type_2(writer, + ap, + bp, + cp, + dp, + intensity); +} + +static inline vec3 screen_transform(const vec3& v) +{ + return {v.x, v.y, _fsrra(v.z)}; +} + +static inline void draw_grid(ta_parameter_writer& writer, + const mat4x4& trans) +{ + const vec3 color = {0, 1, 0}; + global_polygon_intensity(writer, color); + + for (int i = 1; i < 10; i++) { + float x = (float)i * 0.1f - 0.5f; + + { + vec3 p1 = screen_transform(trans * vec3(x, 0.5, 0)); + vec3 p2 = screen_transform(trans * vec3(x, -0.5, 0)); + draw_line(writer, p1, p2, color); + } + { + vec3 p1 = screen_transform(trans * vec3(0.5, x, 0)); + vec3 p2 = screen_transform(trans * vec3(-0.5, x, 0)); + draw_line(writer, p1, p2, color); + } + } +} diff --git a/src/demo/input.cpp b/src/demo/input.cpp new file mode 100644 index 0000000..385cc96 --- /dev/null +++ b/src/demo/input.cpp @@ -0,0 +1,116 @@ +#include + +#include "maple/maple.hpp" +#include "maple/maple_port.hpp" +#include "maple/maple_bus_bits.hpp" +#include "maple/maple_bus_commands.hpp" +#include "maple/maple_bus_ft0.hpp" +#include "maple/maple_bus_ft9.hpp" +#include "maple/maple_host_command_writer.hpp" + +#include "sh7091/serial.hpp" + +#include "demo/input.hpp" + +namespace input { + +struct input_state state; + +template +static inline void do_get_condition_controller(maple::host_command_writer& writer, + const uint32_t port) +{ + using command_type = maple::get_condition; + using response_type = maple::data_transfer; + + uint32_t host_port_select = host_instruction_port_select(port); + uint32_t destination_ap = ap_port_select(port) | ap::de::device; + + auto [host_command, host_response] + = writer.template append_command(host_port_select, + destination_ap, + false); // end_flag + + host_command->bus_data.data_fields.function_type = std::byteswap(function_type::controller); + + state.port[port].host_response_data_transfer_ft0 = host_response; +} + +template +static inline void do_get_condition_pointing(maple::host_command_writer& writer, + const uint32_t port) +{ + using command_type = maple::get_condition; + using response_type = maple::data_transfer; + + uint32_t host_port_select = host_instruction_port_select(port); + uint32_t destination_ap = ap_port_select(port) | ap::de::device; + + auto [host_command, host_response] + = writer.template append_command(host_port_select, + destination_ap, + false); // end_flag + + host_command->bus_data.data_fields.function_type = std::byteswap(function_type::pointing); + + state.port[port].host_response_data_transfer_ft9 = host_response; +} + +template +static inline maple::host_response * do_device_request(maple::host_command_writer& writer) +{ + using command_type = maple::device_request; + using response_type = maple::device_status; + + auto [host_command, host_response] + = writer.template append_command_all_ports(); + + return host_response; +} + +void update() +{ + static uint8_t send_buf[1024] __attribute__((aligned(32))); + static uint8_t recv_buf[1024] __attribute__((aligned(32))); + + maple::host_command_writer writer(send_buf, recv_buf); + + for (uint8_t port_ix = 0; port_ix < 4; port_ix++) { + state.port[port_ix].function_type = state.port[port_ix].next_function_type; + + if (state.port[port_ix].function_type & function_type::controller) { + do_get_condition_controller(writer, port_ix); + } + + if (state.port[port_ix].function_type & function_type::pointing) { + do_get_condition_pointing(writer, port_ix); + } + } + + auto host_response_device_status = do_device_request(writer); + + // what?? + maple::dma_start(writer.send_buf, writer.send_offset, + writer.recv_buf, writer.recv_offset); + maple::dma_wait_complete(); + + for (uint8_t port_ix = 0; port_ix < 4; port_ix++) { + auto& bus_data = host_response_device_status[port_ix].bus_data; + auto& data_fields = bus_data.data_fields; + if (bus_data.command_code != maple::device_status::command_code) { + state.port[port_ix].function_type = 0; + state.port[port_ix].next_function_type = 0; + } else { + state.port[port_ix].next_function_type = std::byteswap(data_fields.device_id.ft); + } + } +} + +void init() +{ + for (uint8_t port = 0; port < 4; port++) { + state.port[port].function_type = 0; + } +} + +} diff --git a/src/demo/input.hpp b/src/demo/input.hpp new file mode 100755 index 0000000..bdc1a7f --- /dev/null +++ b/src/demo/input.hpp @@ -0,0 +1,26 @@ +#pragma once + +#include "maple/maple.hpp" +#include "maple/maple_bus_commands.hpp" +#include "maple/maple_bus_ft0.hpp" +#include "maple/maple_bus_ft9.hpp" + +namespace input { + +struct port_state { + uint32_t function_type; + uint32_t next_function_type; + maple::host_response::data_fields> * host_response_data_transfer_ft0; + maple::host_response::data_fields> * host_response_data_transfer_ft9; +}; + +struct input_state { + port_state port[4]; +}; + +extern input_state state; + +void update(); +void init(); + +} diff --git a/src/demo/scene.hpp b/src/demo/scene.hpp new file mode 100644 index 0000000..1531cdd --- /dev/null +++ b/src/demo/scene.hpp @@ -0,0 +1,11 @@ +#pragma once + +namespace demo { + + struct scene { + virtual void init() = 0; + virtual void fire() = 0; + virtual void update() = 0; + virtual void draw() = 0; + }; +};