From 511d99563d26ada77f38e55d552308d71986cd4b Mon Sep 17 00:00:00 2001 From: Zack Buhman Date: Fri, 2 Feb 2024 18:37:19 +0800 Subject: [PATCH] maple_bus_commands: zero-sized structs should be zero sized From the GCC manual. > GCC permits a C structure to have no members: struct empty { }; > The structure has size zero. In C++, empty structures are part of the > language. G++ treats empty structures as if they had a single member of type > char. I was not aware of the different behavior in C++. This fixes every maple example--most were broken for multiple reasons, including this one. This also enables SH4 caching. This includes linking code/data into the P1 area (previously this was not the case). The maple examples (which indeed involve much use of DMA) require much work to successfully work with the operand and copyback caches. The vibration example currently is the most complete, though I should consider more on how I want to structure maple response operand cache invalidation more generally. --- client.py | 17 ++- common.mk | 3 +- example/clipping.cpp | 13 +- example/clipping2.cpp | 14 ++- example/clipping_textured.cpp | 13 +- example/cube.cpp | 7 +- example/example.mk | 8 +- example/font_bitmap.cpp | 7 +- example/font_outline.cpp | 7 +- example/font_outline_punch_through.cpp | 7 +- example/heart.cpp | 6 +- example/icosphere.cpp | 7 +- example/macaw.cpp | 6 +- example/macaw_cube.cpp | 7 +- example/macaw_cube_render_to_texture.cpp | 7 +- example/macaw_multipass.cpp | 6 +- example/macaw_twiddle.cpp | 7 +- example/maple_analog.cpp | 15 ++- example/maple_controller.cpp | 15 +-- example/maple_device_request.cpp | 22 ++-- example/maple_vibrator.cpp | 77 ++++++++---- example/maple_wink.cpp | 14 +-- example/modifier_volume.cpp | 6 +- example/modifier_volume_with_two_volumes.cpp | 18 +-- example/sprite.cpp | 7 +- example/suzanne_profile.cpp | 6 +- example/translucency.cpp | 6 +- example/viewing_system.cpp | 6 +- example/wiffle_attenuation.cpp | 7 +- geometry/border.hpp | 55 ++++++--- geometry/border.obj | 50 +++++--- geometry/plane.hpp | 14 +-- maple/maple.cpp | 78 ++++++++---- maple/maple.hpp | 28 +++-- maple/maple_bus_commands.hpp | 123 +++++++++++-------- maple/maple_impl.hpp | 11 +- regs/gen/maple_bus_commands.py | 24 ++-- systembus_bits.hpp | 31 +++++ 38 files changed, 472 insertions(+), 283 deletions(-) diff --git a/client.py b/client.py index 656a2eb..2708406 100644 --- a/client.py +++ b/client.py @@ -8,10 +8,10 @@ dest = 0xac02_0000 ret = [] -def sync(ser, b, wait=1): +def sync(ser, b, wait=0.5): l = [] for i, c in enumerate(b): - if i % 32 == 0: + if i % 32 == 0 and i != 0: print(i, end=' ') sys.stdout.flush() ser.write(bytes([c])) @@ -60,15 +60,18 @@ def do(ser, b): _ = ser.read(ser.in_waiting) ret = sync(ser, b'DATA') - print(ret) + #print(ret) size = len(b) args = struct.pack("(command_buf, receive_buf, - data_fields); - maple::dma_start(command_buf); + const uint32_t size = maple::init_host_command_all_ports(command_buf, receive_buf, + data_fields); + maple::dma_start(command_buf, size); using command_response_type = struct maple::command_response; for (uint8_t port = 0; port < 4; port++) { @@ -310,9 +310,12 @@ void main() ta_polygon_converter_transfer(ta_parameter_buf, parameter.offset); ta_wait_opaque_list(); core_start_render(frame_ix, num_frames); + core_wait_end_of_render_video(); + + while (!spg_status::vsync(holly.SPG_STATUS)); + core_flip(frame_ix, num_frames); + while (spg_status::vsync(holly.SPG_STATUS)); - v_sync_in(); - core_wait_end_of_render_video(frame_ix, num_frames); frame_ix += 1; theta += (2.f * pi) / 720.f; } diff --git a/example/clipping2.cpp b/example/clipping2.cpp index 0460c3c..0ea6ad6 100644 --- a/example/clipping2.cpp +++ b/example/clipping2.cpp @@ -17,7 +17,6 @@ #include "holly/background.hpp" #include "holly/texture_memory_alloc.hpp" #include "memorymap.hpp" -#include "sh7091/serial.hpp" #include "geometry/triangle.hpp" #include "geometry/circle.hpp" @@ -46,9 +45,9 @@ void do_get_condition(uint32_t * command_buf, .function_type = std::byteswap(function_type::controller) }; - maple::init_host_command_all_ports(command_buf, receive_buf, - data_fields); - maple::dma_start(command_buf); + const uint32_t size = maple::init_host_command_all_ports(command_buf, receive_buf, + data_fields); + maple::dma_start(command_buf, size); using command_response_type = struct maple::command_response; for (uint8_t port = 0; port < 4; port++) { @@ -286,9 +285,12 @@ void main() ta_polygon_converter_transfer(ta_parameter_buf, parameter.offset); ta_wait_opaque_list(); core_start_render(frame_ix, num_frames); + core_wait_end_of_render_video(); + + while (!spg_status::vsync(holly.SPG_STATUS)); + core_flip(frame_ix, num_frames); + while (spg_status::vsync(holly.SPG_STATUS)); - v_sync_in(); - core_wait_end_of_render_video(frame_ix, num_frames); frame_ix += 1; } } diff --git a/example/clipping_textured.cpp b/example/clipping_textured.cpp index 260b3c0..4a123b4 100644 --- a/example/clipping_textured.cpp +++ b/example/clipping_textured.cpp @@ -49,9 +49,9 @@ void do_get_condition(uint32_t * command_buf, .function_type = std::byteswap(function_type::controller) }; - maple::init_host_command_all_ports(command_buf, receive_buf, - data_fields); - maple::dma_start(command_buf); + const uint32_t size = maple::init_host_command_all_ports(command_buf, receive_buf, + data_fields); + maple::dma_start(command_buf, size); using command_response_type = struct maple::command_response; for (uint8_t port = 0; port < 4; port++) { @@ -326,9 +326,12 @@ void main() ta_polygon_converter_transfer(ta_parameter_buf, parameter.offset); ta_wait_opaque_list(); core_start_render(frame_ix, num_frames); + core_wait_end_of_render_video(); + + while (!spg_status::vsync(holly.SPG_STATUS)); + core_flip(frame_ix, num_frames); + while (spg_status::vsync(holly.SPG_STATUS)); - v_sync_in(); - core_wait_end_of_render_video(frame_ix, num_frames); frame_ix += 1; } } diff --git a/example/cube.cpp b/example/cube.cpp index 70b998c..a4f17bf 100644 --- a/example/cube.cpp +++ b/example/cube.cpp @@ -205,9 +205,12 @@ void main() ta_polygon_converter_transfer(ta_parameter_buf, parameter.offset); ta_wait_opaque_list(); core_start_render(frame_ix, num_frames); + core_wait_end_of_render_video(); + + while (!spg_status::vsync(holly.SPG_STATUS)); + core_flip(frame_ix, num_frames); + while (spg_status::vsync(holly.SPG_STATUS)); - v_sync_in(); - core_wait_end_of_render_video(frame_ix, num_frames); theta += half_degree; frame_ix += 1; } diff --git a/example/example.mk b/example/example.mk index 70e325b..2047d46 100644 --- a/example/example.mk +++ b/example/example.mk @@ -257,7 +257,7 @@ example/clipping_textured.elf: $(START_OBJ) $(CLIPPING_TEXTURED_OBJ) MAPLE_DEVICE_REQUEST_OBJ = \ example/maple_device_request.o \ vga.o \ - serial.o \ + sh7091/serial.o \ maple/maple.o example/maple_device_request.elf: LDSCRIPT = $(LIB)/alt.lds @@ -276,7 +276,7 @@ MAPLE_WINK_OBJ = \ example/maple_wink.o \ vga.o \ rgb.o \ - serial.o \ + sh7091/serial.o \ maple/maple.o \ wink.data.o @@ -287,7 +287,7 @@ MAPLE_VIBRATOR_OBJ = \ example/maple_vibrator.o \ vga.o \ rgb.o \ - serial.o \ + sh7091/serial.o \ maple/maple.o example/maple_vibrator.elf: LDSCRIPT = $(LIB)/alt.lds @@ -314,7 +314,7 @@ example/serial_transfer.elf: $(START_OBJ) $(SERIAL_TRANSFER_OBJ) INTERRUPT_OBJ = \ example/interrupt.o \ - serial.o + sh7091/serial.o example/interrupt.elf: LDSCRIPT = $(LIB)/alt.lds example/interrupt.elf: $(START_OBJ) $(INTERRUPT_OBJ) diff --git a/example/font_bitmap.cpp b/example/font_bitmap.cpp index 560b885..38cfa9e 100644 --- a/example/font_bitmap.cpp +++ b/example/font_bitmap.cpp @@ -272,10 +272,11 @@ void main() ta_wait_opaque_list(); core_start_render(frame_ix, num_frames); + core_wait_end_of_render_video(); - v_sync_out(); - v_sync_in(); - core_wait_end_of_render_video(frame_ix, num_frames); + while (!spg_status::vsync(holly.SPG_STATUS)); + core_flip(frame_ix, num_frames); + while (spg_status::vsync(holly.SPG_STATUS)); frame_ix++; } diff --git a/example/font_outline.cpp b/example/font_outline.cpp index d367e84..672a2de 100644 --- a/example/font_outline.cpp +++ b/example/font_outline.cpp @@ -296,10 +296,11 @@ void main() ta_wait_translucent_list(); core_start_render(frame_ix, num_frames); + core_wait_end_of_render_video(); - v_sync_out(); - v_sync_in(); - core_wait_end_of_render_video(frame_ix, num_frames); + while (!spg_status::vsync(holly.SPG_STATUS)); + core_flip(frame_ix, num_frames); + while (spg_status::vsync(holly.SPG_STATUS)); frame_ix++; } diff --git a/example/font_outline_punch_through.cpp b/example/font_outline_punch_through.cpp index 78c9ade..27c49ff 100644 --- a/example/font_outline_punch_through.cpp +++ b/example/font_outline_punch_through.cpp @@ -302,10 +302,11 @@ void main() ta_wait_punch_through_list(); core_start_render(frame_ix, num_frames); + core_wait_end_of_render_video(); - v_sync_out(); - v_sync_in(); - core_wait_end_of_render_video(frame_ix, num_frames); + while (!spg_status::vsync(holly.SPG_STATUS)); + core_flip(frame_ix, num_frames); + while (spg_status::vsync(holly.SPG_STATUS)); frame_ix++; } diff --git a/example/heart.cpp b/example/heart.cpp index 97a55af..538efcb 100644 --- a/example/heart.cpp +++ b/example/heart.cpp @@ -322,9 +322,11 @@ void main() ta_wait_opaque_list(); core_start_render(frame_ix, num_frames); + core_wait_end_of_render_video(); - v_sync_in(); - core_wait_end_of_render_video(frame_ix, num_frames); + while (!spg_status::vsync(holly.SPG_STATUS)); + core_flip(frame_ix, num_frames); + while (spg_status::vsync(holly.SPG_STATUS)); constexpr float half_degree = 0.01745329f / 2; theta += half_degree; diff --git a/example/icosphere.cpp b/example/icosphere.cpp index 50135d1..8a56f4b 100644 --- a/example/icosphere.cpp +++ b/example/icosphere.cpp @@ -300,9 +300,12 @@ void main() ta_polygon_converter_transfer(ta_parameter_buf, parameter.offset); ta_wait_opaque_list(); core_start_render(frame_ix, num_frames); + core_wait_end_of_render_video(); + + while (!spg_status::vsync(holly.SPG_STATUS)); + core_flip(frame_ix, num_frames); + while (spg_status::vsync(holly.SPG_STATUS)); - v_sync_out(); - core_wait_end_of_render_video(frame_ix, num_frames); theta += half_degree; frame_ix += 1; } diff --git a/example/macaw.cpp b/example/macaw.cpp index aca90d8..bcb8417 100644 --- a/example/macaw.cpp +++ b/example/macaw.cpp @@ -177,9 +177,11 @@ void main() ta_wait_opaque_list(); core_start_render(frame_ix, num_frames); + core_wait_end_of_render_video(); - v_sync_in(); - core_wait_end_of_render_video(frame_ix, num_frames); + while (!spg_status::vsync(holly.SPG_STATUS)); + core_flip(frame_ix, num_frames); + while (spg_status::vsync(holly.SPG_STATUS)); theta += half_degree; frame_ix += 1; diff --git a/example/macaw_cube.cpp b/example/macaw_cube.cpp index 5e4a2c3..700d3de 100644 --- a/example/macaw_cube.cpp +++ b/example/macaw_cube.cpp @@ -211,9 +211,12 @@ void main() ta_polygon_converter_transfer(ta_parameter_buf, parameter.offset); ta_wait_opaque_list(); core_start_render(frame_ix, num_frames); + core_wait_end_of_render_video(); + + while (!spg_status::vsync(holly.SPG_STATUS)); + core_flip(frame_ix, num_frames); + while (spg_status::vsync(holly.SPG_STATUS)); - v_sync_in(); - core_wait_end_of_render_video(frame_ix, num_frames); theta += half_degree; frame_ix += 1; } diff --git a/example/macaw_cube_render_to_texture.cpp b/example/macaw_cube_render_to_texture.cpp index 1a04a38..144067c 100644 --- a/example/macaw_cube_render_to_texture.cpp +++ b/example/macaw_cube_render_to_texture.cpp @@ -287,8 +287,11 @@ void main() 640, // linestride 0x00096000, // framesize frame_ix, num_frames); - v_sync_in(); - core_wait_end_of_render_video(frame_ix, num_frames); + core_wait_end_of_render_video(); + + while (!spg_status::vsync(holly.SPG_STATUS)); + core_flip(frame_ix, num_frames); + while (spg_status::vsync(holly.SPG_STATUS)); theta += half_degree; frame_ix += 1; diff --git a/example/macaw_multipass.cpp b/example/macaw_multipass.cpp index df2fcd8..356922f 100644 --- a/example/macaw_multipass.cpp +++ b/example/macaw_multipass.cpp @@ -175,9 +175,11 @@ void main() ta_wait_translucent_list(); core_start_render(frame_ix, num_frames); + core_wait_end_of_render_video(); - v_sync_in(); - core_wait_end_of_render_video(frame_ix, num_frames); + while (!spg_status::vsync(holly.SPG_STATUS)); + core_flip(frame_ix, num_frames); + while (spg_status::vsync(holly.SPG_STATUS)); theta += half_degree; frame_ix += 1; diff --git a/example/macaw_twiddle.cpp b/example/macaw_twiddle.cpp index 1caf7e2..b30fdda 100644 --- a/example/macaw_twiddle.cpp +++ b/example/macaw_twiddle.cpp @@ -181,10 +181,11 @@ void main() ta_wait_opaque_list(); core_start_render(frame_ix, num_frames); + core_wait_end_of_render_video(); - v_sync_out(); - v_sync_in(); - core_wait_end_of_render_video(frame_ix, num_frames); + while (!spg_status::vsync(holly.SPG_STATUS)); + core_flip(frame_ix, num_frames); + while (spg_status::vsync(holly.SPG_STATUS)); theta += half_degree; frame_ix += 1; diff --git a/example/maple_analog.cpp b/example/maple_analog.cpp index 1db8500..b9ed9e0 100644 --- a/example/maple_analog.cpp +++ b/example/maple_analog.cpp @@ -44,9 +44,9 @@ void do_get_condition(uint32_t * command_buf, .function_type = std::byteswap(function_type::controller) }; - maple::init_host_command_all_ports(command_buf, receive_buf, - data_fields); - maple::dma_start(command_buf); + const uint32_t size = maple::init_host_command_all_ports(command_buf, receive_buf, + data_fields); + maple::dma_start(command_buf, size); using command_response_type = struct maple::command_response; for (uint8_t port = 0; port < 4; port++) { @@ -67,7 +67,7 @@ void do_get_condition(uint32_t * command_buf, void transform(ta_parameter_writer& parameter, const vec3 * vertices, - const face_vn& face, + const face_vtn& face, const vec4& color, const vec3& position, const float scale @@ -227,9 +227,12 @@ void main() ta_polygon_converter_transfer(ta_parameter_buf, parameter.offset); ta_wait_opaque_list(); core_start_render(frame_ix, num_frames); + core_wait_end_of_render_video(); + + while (!spg_status::vsync(holly.SPG_STATUS)); + core_flip(frame_ix, num_frames); + while (spg_status::vsync(holly.SPG_STATUS)); - v_sync_out(); - core_wait_end_of_render_video(frame_ix, num_frames); frame_ix += 1; } } diff --git a/example/maple_controller.cpp b/example/maple_controller.cpp index 0e2652d..c9e7183 100644 --- a/example/maple_controller.cpp +++ b/example/maple_controller.cpp @@ -42,11 +42,11 @@ void do_get_condition(uint32_t port) return; } - maple::init_get_condition(command_buf, receive_buf, - destination_port, - destination_ap, - std::byteswap(function_type::controller)); - maple::dma_start(command_buf); + const uint32_t size = maple::init_get_condition(command_buf, receive_buf, + destination_port, + destination_ap, + std::byteswap(function_type::controller)); + maple::dma_start(command_buf, size); using response_type = data_transfer; using command_response_type = struct maple::command_response; @@ -74,8 +74,8 @@ void do_device_request() using command_type = device_request; using response_type = device_status; - maple::init_host_command_all_ports(command_buf, receive_buf); - maple::dma_start(command_buf); + const uint32_t size = maple::init_host_command_all_ports(command_buf, receive_buf); + maple::dma_start(command_buf, size * 10); using command_response_type = struct maple::command_response; auto response = reinterpret_cast(receive_buf); @@ -97,6 +97,7 @@ void do_device_request() void main() { command_buf = align_32byte(_command_buf); + command_buf = reinterpret_cast(reinterpret_cast(command_buf) | 0xa000'0000); receive_buf = align_32byte(_receive_buf); // flycast needs this in HLE mode, or else it won't start the vcount diff --git a/example/maple_device_request.cpp b/example/maple_device_request.cpp index 7af9004..1ee10d4 100644 --- a/example/maple_device_request.cpp +++ b/example/maple_device_request.cpp @@ -1,32 +1,30 @@ #include "align.hpp" #include "maple/maple.hpp" +#include "maple/maple_impl.hpp" #include "maple/maple_bus_commands.hpp" -#include "serial.hpp" +#include "sh7091/serial.hpp" -constexpr uint32_t command_data_size = (sizeof (device_request::data_fields)); -constexpr uint32_t response_data_size = (sizeof (device_status::data_fields)); - -constexpr uint32_t host_command_size = (sizeof (struct maple::host_command)); -constexpr uint32_t command_response_size = align_32byte((sizeof (struct maple::command_response))); - -uint32_t _command_buf[host_command_size * 4 + 32] = {0}; -uint32_t _receive_buf[command_response_size * 4 + 32] = {0}; +uint32_t _command_buf[1024 / 4 + 32] = {0}; +uint32_t _receive_buf[1024 / 4 + 32] = {0}; void main() { uint32_t * command_buf = align_32byte(_command_buf); uint32_t * receive_buf = align_32byte(_receive_buf); - maple::init_host_command_all_ports(command_buf, receive_buf, - device_request::command_code, command_data_size, response_data_size); + using command_type = device_request; + using response_type = device_status; - maple::dma_start(command_buf); + uint32_t size = maple::init_host_command_all_ports(command_buf, receive_buf); + maple::dma_start(command_buf, size); uint8_t * buf = reinterpret_cast(receive_buf); for (uint8_t port = 0; port < 4; port++) { serial::string("port "); serial::integer(port); + + constexpr uint32_t command_response_size = (sizeof (maple::command_response)); for (uint32_t i = 0; i < command_response_size; i++) { serial::integer(buf[port * command_response_size + i]); } diff --git a/example/maple_vibrator.cpp b/example/maple_vibrator.cpp index b4d5d8b..cce6a41 100644 --- a/example/maple_vibrator.cpp +++ b/example/maple_vibrator.cpp @@ -4,13 +4,11 @@ #include "align.hpp" #include "maple/maple.hpp" +#include "maple/maple_impl.hpp" #include "maple/maple_bus_bits.hpp" #include "maple/maple_bus_commands.hpp" #include "maple/maple_bus_ft8.hpp" -#include "serial.hpp" - -uint32_t _command_buf[1024 / 4 + 32] = {0}; -uint32_t _receive_buf[1024 / 4 + 32] = {0}; +#include "sh7091/serial.hpp" static uint32_t * command_buf; static uint32_t * receive_buf; @@ -56,12 +54,23 @@ void do_lm_request(uint8_t port, uint8_t lm) fields.function_type = std::byteswap(function_type::vibration); fields.pt = std::byteswap(1 << 24); - maple::dma_start(command_buf); + serial::string("dma start\n"); + const uint32_t size = (reinterpret_cast(&host_command[1]) - reinterpret_cast(&host_command[0])); + maple::dma_start(command_buf, size * 2); + + using response_type = data_transfer; + using command_response_type = struct maple::command_response; + for (uint32_t i = 0; i < (sizeof (command_response_type)) / 32; i++) { + asm volatile ("ocbp @%0" + : // output + : "r" (reinterpret_cast(&receive_buf[(32 * i) / 4])) // input + ); + } + + auto response = reinterpret_cast(receive_buf); - using response_type = struct maple::command_response>; - auto response = reinterpret_cast(receive_buf); auto& bus_data = response->bus_data; - if (bus_data.command_code != data_transfer::command_code) { + if (bus_data.command_code != response_type::command_code) { serial::string("lm did not reply to vibration get_media_info: "); serial::integer(lm); return; @@ -99,15 +108,15 @@ void do_lm_request(uint8_t port, uint8_t lm) set condition */ { - using data_field_type = set_condition::data_fields; + using command_type = set_condition; maple::init_host_command(command_buf, receive_buf, destination_port, - destination_ap, set_condition::command_code, (sizeof (data_field_type)), + destination_ap, command_type::command_code, (sizeof (command_type::data_fields)), true); - using command_type = struct maple::host_command; - auto host_command = reinterpret_cast(command_buf); + using host_command_type = struct maple::host_command; + auto host_command = reinterpret_cast(command_buf); auto& fields = host_command->bus_data.data_fields; fields.function_type = std::byteswap(function_type::vibration); fields.write_in_data.ctrl = 0x11; @@ -115,11 +124,18 @@ void do_lm_request(uint8_t port, uint8_t lm) fields.write_in_data.freq = 0x27; fields.write_in_data.inc = 0x00; - maple::dma_start(command_buf); + const uint32_t size = (reinterpret_cast(&host_command[1]) - reinterpret_cast(&host_command[0])); + maple::dma_start(command_buf, size); - using response_type = struct maple::command_response; - auto response = reinterpret_cast(receive_buf); - auto& bus_data = response->bus_data; + using command_response_type = struct maple::command_response; + for (uint32_t i = 0; i < (sizeof (command_response_type)) / 32; i++) { + asm volatile ("ocbp @%0" + : // output + : "r" (reinterpret_cast(&receive_buf[(32 * i) / 4])) // input + ); + } + auto command_response = reinterpret_cast(receive_buf); + auto& bus_data = command_response->bus_data; if (bus_data.command_code != device_reply::command_code) { serial::string("lm did not reply to vibration set_condition: "); @@ -148,20 +164,23 @@ void do_lm_requests(uint8_t port, uint8_t lm) void do_device_request() { - using response_type = struct maple::command_response; - constexpr uint32_t response_size = align_32byte(sizeof (response_type)); + using command_type = device_request; + using response_type = device_status; - maple::init_host_command_all_ports(command_buf, receive_buf, - device_request::command_code, - (sizeof (device_request::data_fields)), // command_data_size - (sizeof (device_status::data_fields))); // response_data_size - maple::dma_start(command_buf); + const uint32_t size = maple::init_host_command_all_ports(command_buf, receive_buf); + maple::dma_start(command_buf, size); + using command_response_type = struct maple::command_response; + for (uint32_t i = 0; i < ((sizeof (command_response_type)) * 4) / 32; i++) { + asm volatile ("ocbp @%0" + : // output + : "r" (reinterpret_cast(&receive_buf[(32 * i) / 4])) // input + ); + } + auto response = reinterpret_cast(receive_buf); for (uint8_t port = 0; port < 4; port++) { - auto response = reinterpret_cast(&receive_buf[response_size * port / 4]); - - auto& bus_data = response->bus_data; - auto& data_fields = response->bus_data.data_fields; + auto& bus_data = response[port].bus_data; + auto& data_fields = response[port].bus_data.data_fields; if (bus_data.command_code != device_status::command_code) { // the controller is disconnected } else { @@ -177,7 +196,11 @@ void do_device_request() void main() { + uint32_t _command_buf[1024 / 4 + 32]; + uint32_t _receive_buf[1024 / 4 + 32]; + command_buf = align_32byte(_command_buf); + command_buf = reinterpret_cast(reinterpret_cast(command_buf) | 0xa000'0000); receive_buf = align_32byte(_receive_buf); vga(); diff --git a/example/maple_wink.cpp b/example/maple_wink.cpp index ee4f7d7..500f5ab 100644 --- a/example/maple_wink.cpp +++ b/example/maple_wink.cpp @@ -4,7 +4,7 @@ #include "maple/maple_bus_bits.hpp" #include "vga.hpp" #include "align.hpp" -#include "serial.hpp" +#include "sh7091/serial.hpp" extern uint32_t _binary_wink_data_start __asm("_binary_wink_data_start"); @@ -40,12 +40,12 @@ void main() uint32_t * command_buf = align_32byte(_command_buf); uint32_t * receive_buf = align_32byte(_receive_buf); - maple::init_block_write(command_buf, receive_buf, - host_instruction::port_select::a, - ap::de::expansion_device | ap::port_select::a | ap::lm_bus::_0, - wink_buf, - wink_size); - maple::dma_start(command_buf); + const uint32_t size = maple::init_block_write(command_buf, receive_buf, + host_instruction::port_select::a, + ap::de::expansion_device | ap::port_select::a | ap::lm_bus::_0, + wink_buf, + wink_size); + maple::dma_start(command_buf, size); for (int i = 0; i < 1; i++) { serial::integer(receive_buf[i]); diff --git a/example/modifier_volume.cpp b/example/modifier_volume.cpp index 43ddf97..5173ad4 100644 --- a/example/modifier_volume.cpp +++ b/example/modifier_volume.cpp @@ -261,9 +261,11 @@ void main() ta_wait_opaque_modifier_volume_list(); core_start_render(frame_ix, num_frames); + core_wait_end_of_render_video(); - v_sync_in(); - core_wait_end_of_render_video(frame_ix, num_frames); + while (!spg_status::vsync(holly.SPG_STATUS)); + core_flip(frame_ix, num_frames); + while (spg_status::vsync(holly.SPG_STATUS)); constexpr float half_degree = 0.01745329f / 2; theta += half_degree; diff --git a/example/modifier_volume_with_two_volumes.cpp b/example/modifier_volume_with_two_volumes.cpp index 6fc16b3..233bbd5 100644 --- a/example/modifier_volume_with_two_volumes.cpp +++ b/example/modifier_volume_with_two_volumes.cpp @@ -5,7 +5,7 @@ #include "vga.hpp" #include "holly/texture_memory_alloc.hpp" -#include "holly.hpp" +#include "holly/holly.hpp" #include "holly/core.hpp" #include "holly/core_bits.hpp" #include "holly/ta_fifo_polygon_converter.hpp" @@ -45,9 +45,9 @@ void do_get_condition(uint32_t * command_buf, .function_type = std::byteswap(function_type::controller) }; - maple::init_host_command_all_ports(command_buf, receive_buf, - data_fields); - maple::dma_start(command_buf); + const uint32_t size = maple::init_host_command_all_ports(command_buf, receive_buf, + data_fields); + maple::dma_start(command_buf, size); using command_response_type = struct maple::command_response; for (uint8_t port = 0; port < 4; port++) { @@ -164,7 +164,7 @@ uint32_t argb8888(const vec4& color) void transform_polygon(ta_parameter_writer& parameter, const vec3 * vertices, const vec2 * texture, - const face& face, + const face_vtn& face, const float scale, const vec4& color0, const vec4& color1, @@ -238,7 +238,7 @@ void transform_polygon(ta_parameter_writer& parameter, void transform_modifier_volume(ta_parameter_writer& parameter, const vec3 * vertices, - const face * faces, + const face_vtn * faces, const uint32_t num_faces, const float scale) { @@ -442,9 +442,11 @@ void main() ta_wait_opaque_modifier_volume_list(); core_start_render(frame_ix, num_frames); + core_wait_end_of_render_video(); - v_sync_in(); - core_wait_end_of_render_video(frame_ix, num_frames); + while (!spg_status::vsync(holly.SPG_STATUS)); + core_flip(frame_ix, num_frames); + while (spg_status::vsync(holly.SPG_STATUS)); frame_ix += 1; } diff --git a/example/sprite.cpp b/example/sprite.cpp index 7a1f70d..124d30f 100644 --- a/example/sprite.cpp +++ b/example/sprite.cpp @@ -109,9 +109,12 @@ void main() ta_wait_opaque_list(); core_start_render(frame_ix, num_frames); + core_wait_end_of_render_video(); + + while (!spg_status::vsync(holly.SPG_STATUS)); + core_flip(frame_ix, num_frames); + while (spg_status::vsync(holly.SPG_STATUS)); - v_sync_in(); - core_wait_end_of_render_video(frame_ix, num_frames); frame_ix += 1; } } diff --git a/example/suzanne_profile.cpp b/example/suzanne_profile.cpp index 5d3c4f9..5b27fe7 100644 --- a/example/suzanne_profile.cpp +++ b/example/suzanne_profile.cpp @@ -391,11 +391,9 @@ void main() core_wait_end_of_render_video(); t_render_end = sh7091.TMU.TCNT0; - while (!spg_status::vsync(holly.SPG_STATUS)) { - } + while (!spg_status::vsync(holly.SPG_STATUS)); core_flip(frame_ix, num_frames); - while (spg_status::vsync(holly.SPG_STATUS)) { - } + while (spg_status::vsync(holly.SPG_STATUS)); theta += half_degree * 0.5; frame_ix += 1; diff --git a/example/translucency.cpp b/example/translucency.cpp index 914e0e3..9c147a2 100644 --- a/example/translucency.cpp +++ b/example/translucency.cpp @@ -201,9 +201,11 @@ void main() ta_wait_translucent_list(); core_start_render(frame_ix, num_frames); + core_wait_end_of_render_video(); - v_sync_in(); - core_wait_end_of_render_video(frame_ix, num_frames); + while (!spg_status::vsync(holly.SPG_STATUS)); + core_flip(frame_ix, num_frames); + while (spg_status::vsync(holly.SPG_STATUS)); theta += half_degree; frame_ix += 1; diff --git a/example/viewing_system.cpp b/example/viewing_system.cpp index d4aa1f0..3f86995 100644 --- a/example/viewing_system.cpp +++ b/example/viewing_system.cpp @@ -213,9 +213,11 @@ void main() ta_wait_opaque_list(); core_start_render(frame_ix, num_frames); + core_wait_end_of_render_video(); - v_sync_out(); - core_wait_end_of_render_video(frame_ix, num_frames); + while (!spg_status::vsync(holly.SPG_STATUS)); + core_flip(frame_ix, num_frames); + while (spg_status::vsync(holly.SPG_STATUS)); frame_ix += 1; delta += pi * 2 / 360; diff --git a/example/wiffle_attenuation.cpp b/example/wiffle_attenuation.cpp index fd71083..c1a8f16 100644 --- a/example/wiffle_attenuation.cpp +++ b/example/wiffle_attenuation.cpp @@ -311,9 +311,12 @@ void main() ta_polygon_converter_transfer(ta_parameter_buf, parameter.offset); ta_wait_opaque_list(); core_start_render(frame_ix, num_frames); + core_wait_end_of_render_video(); + + while (!spg_status::vsync(holly.SPG_STATUS)); + core_flip(frame_ix, num_frames); + while (spg_status::vsync(holly.SPG_STATUS)); - v_sync_out(); - core_wait_end_of_render_video(frame_ix, num_frames); theta += half_degree; frame_ix += 1; } diff --git a/geometry/border.hpp b/geometry/border.hpp index 62d8230..b779b9d 100644 --- a/geometry/border.hpp +++ b/geometry/border.hpp @@ -4,39 +4,54 @@ namespace border { constexpr vec3 vertices[] = { - { -1.000000f, 0.000000f, 1.000000f }, - { 1.000000f, 0.000000f, 1.000000f }, + { -1.000000f, -0.000000f, 1.000000f }, + { 1.000000f, -0.000000f, 1.000000f }, { -1.000000f, 0.000000f, -1.000000f }, { 1.000000f, 0.000000f, -1.000000f }, - { 0.950000f, 0.000000f, 1.000000f }, + { 0.950000f, -0.000000f, 1.000000f }, { 0.950000f, 0.000000f, -1.000000f }, - { 0.950000f, 0.000000f, 0.950000f }, + { 0.950000f, -0.000000f, 0.950000f }, { 0.950000f, 0.000000f, -0.950000f }, { -0.950000f, 0.000000f, -1.000000f }, - { -0.950000f, 0.000000f, 1.000000f }, - { -0.950000f, 0.000000f, 0.950000f }, + { -0.950000f, -0.000000f, 1.000000f }, + { -0.950000f, -0.000000f, 0.950000f }, { -0.950000f, 0.000000f, -0.950000f }, }; + constexpr vec2 texture[] = { + { 0.000100f, 0.974905f }, + { 0.025095f, 0.025096f }, + { 0.025095f, 0.974905f }, + { 0.999900f, 0.974905f }, + { 0.974905f, 0.025095f }, + { 0.999900f, 0.025095f }, + { 0.000100f, 0.025096f }, + { 0.974905f, 0.974905f }, + { 0.000100f, 0.999900f }, + { 0.999900f, 0.000100f }, + { 0.000100f, 0.000101f }, + { 0.999900f, 0.999900f }, + }; + constexpr vec3 normals[] = { { -0.000000f, 1.000000f, -0.000000f }, }; - constexpr face_vn faces[] = { - {{ 5, 0}, {11, 0}, { 7, 0}}, - {{ 4, 0}, {10, 0}, { 9, 0}}, - {{ 5, 0}, { 8, 0}, {11, 0}}, - {{ 4, 0}, { 6, 0}, {10, 0}}, - {{ 7, 0}, { 3, 0}, { 5, 0}}, - {{ 0, 0}, {10, 0}, {11, 0}}, - {{11, 0}, { 2, 0}, { 0, 0}}, - {{ 1, 0}, { 6, 0}, { 4, 0}}, - {{ 7, 0}, { 6, 0}, { 3, 0}}, - {{ 0, 0}, { 9, 0}, {10, 0}}, - {{11, 0}, { 8, 0}, { 2, 0}}, - {{ 1, 0}, { 3, 0}, { 6, 0}}, + constexpr face_vtn faces[] = { + {{ 5, 0, 0}, {11, 1, 0}, { 7, 2, 0}}, + {{ 4, 3, 0}, {10, 4, 0}, { 9, 5, 0}}, + {{ 5, 0, 0}, { 8, 6, 0}, {11, 1, 0}}, + {{ 4, 3, 0}, { 6, 7, 0}, {10, 4, 0}}, + {{ 7, 2, 0}, { 3, 8, 0}, { 5, 0, 0}}, + {{ 0, 9, 0}, {10, 4, 0}, {11, 1, 0}}, + {{11, 1, 0}, { 2, 10, 0}, { 0, 9, 0}}, + {{ 1, 11, 0}, { 6, 7, 0}, { 4, 3, 0}}, + {{ 7, 2, 0}, { 6, 7, 0}, { 3, 8, 0}}, + {{ 0, 9, 0}, { 9, 5, 0}, {10, 4, 0}}, + {{11, 1, 0}, { 8, 6, 0}, { 2, 10, 0}}, + {{ 1, 11, 0}, { 3, 8, 0}, { 6, 7, 0}}, }; - constexpr uint32_t num_faces = (sizeof (faces)) / (sizeof (face_vn)); + constexpr uint32_t num_faces = (sizeof (faces)) / (sizeof (face_vtn)); } diff --git a/geometry/border.obj b/geometry/border.obj index 213a27d..b2c9f65 100644 --- a/geometry/border.obj +++ b/geometry/border.obj @@ -1,29 +1,41 @@ -# Blender 3.3.6 +# Blender 3.3.8 # www.blender.org o Border -v -1.000000 0.000000 1.000000 -v 1.000000 0.000000 1.000000 +v -1.000000 -0.000000 1.000000 +v 1.000000 -0.000000 1.000000 v -1.000000 0.000000 -1.000000 v 1.000000 0.000000 -1.000000 -v 0.950000 0.000000 1.000000 +v 0.950000 -0.000000 1.000000 v 0.950000 0.000000 -1.000000 -v 0.950000 0.000000 0.950000 +v 0.950000 -0.000000 0.950000 v 0.950000 0.000000 -0.950000 v -0.950000 0.000000 -1.000000 -v -0.950000 0.000000 1.000000 -v -0.950000 0.000000 0.950000 +v -0.950000 -0.000000 1.000000 +v -0.950000 -0.000000 0.950000 v -0.950000 0.000000 -0.950000 vn -0.0000 1.0000 -0.0000 +vt 0.999900 0.000100 +vt 0.999900 0.999900 +vt 0.000100 0.000101 +vt 0.000100 0.999900 +vt 0.999900 0.974905 +vt 0.000100 0.974905 +vt 0.974905 0.974905 +vt 0.025095 0.974905 +vt 0.000100 0.025096 +vt 0.999900 0.025095 +vt 0.974905 0.025095 +vt 0.025095 0.025096 s 0 -f 6//1 12//1 8//1 -f 5//1 11//1 10//1 -f 6//1 9//1 12//1 -f 5//1 7//1 11//1 -f 8//1 4//1 6//1 -f 1//1 11//1 12//1 -f 12//1 3//1 1//1 -f 2//1 7//1 5//1 -f 8//1 7//1 4//1 -f 1//1 10//1 11//1 -f 12//1 9//1 3//1 -f 2//1 4//1 7//1 +f 6/6/1 12/12/1 8/8/1 +f 5/5/1 11/11/1 10/10/1 +f 6/6/1 9/9/1 12/12/1 +f 5/5/1 7/7/1 11/11/1 +f 8/8/1 4/4/1 6/6/1 +f 1/1/1 11/11/1 12/12/1 +f 12/12/1 3/3/1 1/1/1 +f 2/2/1 7/7/1 5/5/1 +f 8/8/1 7/7/1 4/4/1 +f 1/1/1 10/10/1 11/11/1 +f 12/12/1 9/9/1 3/3/1 +f 2/2/1 4/4/1 7/7/1 diff --git a/geometry/plane.hpp b/geometry/plane.hpp index 79af336..f4f8000 100644 --- a/geometry/plane.hpp +++ b/geometry/plane.hpp @@ -9,23 +9,23 @@ namespace plane { { -1.000000f, 0.000000f, -1.000000f }, { 1.000000f, 0.000000f, -1.000000f }, }; - + constexpr vec2 texture[] = { { 1.000000f, 0.000000f }, { 0.000000f, 1.000000f }, { 0.000000f, 0.000000f }, { 1.000000f, 1.000000f }, }; - + constexpr vec3 normals[] = { { -0.000000f, 1.000000f, -0.000000f }, }; - - constexpr face faces[] = { + + constexpr face_vtn faces[] = { {{1, 0, 0}, {2, 1, 0}, {0, 2, 0}}, {{1, 0, 0}, {3, 3, 0}, {2, 1, 0}}, }; - - constexpr uint32_t num_faces = (sizeof (faces)) / (sizeof (face)); - + + constexpr uint32_t num_faces = (sizeof (faces)) / (sizeof (face_vtn)); + } diff --git a/maple/maple.cpp b/maple/maple.cpp index a16b9af..ee693ad 100644 --- a/maple/maple.cpp +++ b/maple/maple.cpp @@ -26,7 +26,7 @@ void init_host_command(uint32_t * command_buf, uint32_t * receive_buf, host_command->host_instruction = (end_flag ? host_instruction::end_flag : 0) | (destination_port & host_instruction::port_select::bit_mask) // host_instruction::port_select::a - | host_instruction::transfer_length((data_size / 4)); + | host_instruction::transfer_length((data_size / 4)); host_command->receive_data_storage_address = receive_data_storage_address::address(reinterpret_cast(receive_buf)); @@ -37,45 +37,52 @@ void init_host_command(uint32_t * command_buf, uint32_t * receive_buf, host_command->bus_data.data_size = data_size / 4; } -void init_device_request(uint32_t * buf, uint32_t * receive_buf, - uint32_t destination_port, - uint8_t destination_ap) +uint32_t init_device_request(uint32_t * command_buf, uint32_t * receive_buf, + uint32_t destination_port, + uint8_t destination_ap) { - init_host_command(buf, receive_buf, + init_host_command(command_buf, receive_buf, destination_port, destination_ap, device_request::command_code, (sizeof (struct device_request::data_fields)), true); + + auto host_command = reinterpret_cast *>(command_buf); + + return (reinterpret_cast(&host_command[1]) - reinterpret_cast(&host_command[0])); } -void init_get_condition(uint32_t * buf, uint32_t * receive_buf, - uint32_t destination_port, - uint8_t destination_ap, - uint32_t function_type) +uint32_t init_get_condition(uint32_t * command_buf, uint32_t * receive_buf, + uint32_t destination_port, + uint8_t destination_ap, + uint32_t function_type) { - init_host_command(buf, receive_buf, + init_host_command(command_buf, receive_buf, destination_port, destination_ap, get_condition::command_code, (sizeof (struct get_condition::data_fields)), true); - auto host_command = reinterpret_cast *>(buf); + auto host_command = reinterpret_cast *>(command_buf); auto& fields = host_command->bus_data.data_fields; // controller function type fields.function_type = function_type; + + return (reinterpret_cast(&host_command[1]) - reinterpret_cast(&host_command[0])); } -void init_block_write(uint32_t * command_buf, uint32_t * receive_buf, - uint32_t destination_port, - uint8_t destination_ap, - uint32_t * data, - uint32_t data_size) +uint32_t init_block_write(uint32_t * command_buf, uint32_t * receive_buf, + uint32_t destination_port, + uint8_t destination_ap, + uint32_t * data, + uint32_t data_size) { + using command_type = block_write; init_host_command(command_buf, receive_buf, destination_port, - destination_ap, block_write::command_code, (sizeof (struct block_write::data_fields)) + data_size, + destination_ap, command_type::command_code, (sizeof (struct command_type::data_fields)) + data_size, true); - auto host_command = reinterpret_cast> *>(command_buf); + auto host_command = reinterpret_cast *>(command_buf); auto& fields = host_command->bus_data.data_fields; // BW LCD function type @@ -93,12 +100,24 @@ void init_block_write(uint32_t * command_buf, uint32_t * receive_buf, for (uint32_t i = 0; i < (data_size / 4); i++) { fields.written_data[i] = data[i]; } + + return (reinterpret_cast(&host_command[1]) - reinterpret_cast(&host_command[0])) + + data_size; } -void dma_start(uint32_t * command_buf) +void dma_start(const uint32_t * command_buf, const uint32_t size) { using namespace dmac; + for (uint32_t i = 0; i < align_32byte(size) / 32; i++) { + asm volatile ("ocbwb @%0" + : // output + : "r" (reinterpret_cast(&command_buf[(32 * i) / 4])) // input + ); + } + + //command_buf = reinterpret_cast(reinterpret_cast(command_buf) | 0xa000'0000); + sh7091.DMAC.DMAOR = dmaor::ddt::on_demand_data_transfer_mode /* on-demand data transfer mode */ | dmaor::pr::ch2_ch0_ch1_ch3 /* priority mode; CH2 > CH0 > CH1 > CH3 */ | dmaor::dme::operation_enabled_on_all_channels; /* DMAC master enable */ @@ -108,29 +127,42 @@ void dma_start(uint32_t * command_buf) // disable maple-DMA maple_if.MDEN = mden::dma_enable::abort; - while (mdst::start_status::status(maple_if.MDST) != 0); // 20nsec * 0xc350 = 1ms constexpr uint32_t one_msec = 0xc350; maple_if.MSYS = msys::time_out_counter(one_msec) - | msys::sending_rate::_2M; + | msys::sending_rate::_2M; // top address: the first/lowest address // bottom address: the last/highest address maple_if.MDAPRO = mdapro::security_code - | mdapro::top_address(0x00) - | mdapro::bottom_address(0x7f); + | mdapro::top_address(0x40) + | mdapro::bottom_address(0x7f); maple_if.MDTSEL = mdtsel::trigger_select::software_initiation; maple_if.MDSTAR = mdstar::table_address(reinterpret_cast(command_buf)); + system.ISTERR = 0xffff'ffff; + maple_if.MDEN = mden::dma_enable::enable; maple_if.MDST = mdst::start_status::start; // wait for completion //while (mdst::start_status::status(maple_if.MDST) != 0); + /* + uint32_t last_isterr = 0xffff'ffff; + uint32_t isterr = 0; + while ((system.ISTNRM & ISTNRM__END_OF_DMA_MAPLE_DMA) == 0) { + isterr = system.ISTERR; + if (isterr != last_isterr) { + serial::string("maple dma isterr: "); + serial::integer(isterr); + last_isterr = isterr; + } + } + */ while ((system.ISTNRM & ISTNRM__END_OF_DMA_MAPLE_DMA) == 0); system.ISTNRM = ISTNRM__END_OF_DMA_MAPLE_DMA; } diff --git a/maple/maple.hpp b/maple/maple.hpp index dc2b8ea..fbd2366 100644 --- a/maple/maple.hpp +++ b/maple/maple.hpp @@ -18,6 +18,8 @@ struct host_command { T data_fields; } bus_data; }; +static_assert((sizeof (host_command)) == 12); +static_assert((sizeof (host_command[4])) == 48); template struct command_response { @@ -37,21 +39,21 @@ void init_host_command(uint32_t * buf, uint32_t * receive_buf, uint8_t destination_ap, uint8_t command_code, uint8_t data_size, bool end_flag); -void init_device_request(uint32_t * buf, uint32_t * receive_buf, - uint32_t destination_port, - uint8_t destination_ap); +uint32_t init_device_request(uint32_t * buf, uint32_t * receive_buf, + uint32_t destination_port, + uint8_t destination_ap); -void init_get_condition(uint32_t * buf, uint32_t * receive_buf, - uint32_t destination_port, - uint8_t destination_ap, - uint32_t function_type); +uint32_t init_get_condition(uint32_t * buf, uint32_t * receive_buf, + uint32_t destination_port, + uint8_t destination_ap, + uint32_t function_type); -void init_block_write(uint32_t * buf, uint32_t * receive_buf, - uint32_t destination_port, - uint8_t destination_ap, - uint32_t * data, - uint32_t data_size); +uint32_t init_block_write(uint32_t * buf, uint32_t * receive_buf, + uint32_t destination_port, + uint8_t destination_ap, + uint32_t * data, + uint32_t data_size); -void dma_start(uint32_t * command_buf); +void dma_start(const uint32_t * command_buf, const uint32_t size); } diff --git a/maple/maple_bus_commands.hpp b/maple/maple_bus_commands.hpp index 856663a..7a6c704 100644 --- a/maple/maple_bus_commands.hpp +++ b/maple/maple_bus_commands.hpp @@ -10,39 +10,47 @@ struct device_id { static_assert((sizeof (struct device_id)) == 16); struct device_request { static constexpr uint32_t command_code = 0x1; - + struct data_fields { + uint8_t _empty[0]; }; }; +static_assert((sizeof (struct device_request::data_fields)) == 0); struct all_status_request { static constexpr uint32_t command_code = 0x2; - + struct data_fields { + uint8_t _empty[0]; }; }; +static_assert((sizeof (struct all_status_request::data_fields)) == 0); struct device_reset { static constexpr uint32_t command_code = 0x3; - + struct data_fields { + uint8_t _empty[0]; }; }; +static_assert((sizeof (struct device_reset::data_fields)) == 0); struct device_kill { static constexpr uint32_t command_code = 0x4; - + struct data_fields { + uint8_t _empty[0]; }; }; +static_assert((sizeof (struct device_kill::data_fields)) == 0); struct device_status { static constexpr uint32_t command_code = 0x5; - + struct data_fields { struct device_id device_id; uint8_t destination_code; @@ -52,15 +60,15 @@ struct device_status { uint16_t low_consumption_standby_current; uint16_t maximum_current_consumption; }; - - static_assert((sizeof (struct data_fields)) == 112); + }; +static_assert((sizeof (struct device_status::data_fields)) == 112); +template struct device_all_status { static constexpr uint32_t command_code = 0x6; - - template + struct data_fields { struct device_id device_id; uint8_t destination_code; @@ -71,18 +79,21 @@ struct device_all_status { uint16_t maximum_current_consumption; T free_device_status; }; - - static_assert((sizeof (struct data_fields)) == 112); + }; +static_assert((sizeof (struct device_all_status::data_fields)) == 112); struct device_reply { static constexpr uint32_t command_code = 0x7; - + struct data_fields { + uint8_t _empty[0]; }; }; +static_assert((sizeof (struct device_reply::data_fields)) == 0); + template struct data_transfer { static constexpr uint32_t command_code = 0x8; @@ -91,50 +102,52 @@ struct data_transfer { uint32_t function_type; T data; }; + }; + static_assert((sizeof (struct data_transfer::data_fields)) == 4); struct get_condition { static constexpr uint32_t command_code = 0x9; - + struct data_fields { uint32_t function_type; }; - - static_assert((sizeof (struct data_fields)) == 4); + }; +static_assert((sizeof (struct get_condition::data_fields)) == 4); struct get_media_info { static constexpr uint32_t command_code = 0xa; - + struct data_fields { uint32_t function_type; uint32_t pt; }; - - static_assert((sizeof (struct data_fields)) == 8); + }; +static_assert((sizeof (struct get_media_info::data_fields)) == 8); struct block_read { static constexpr uint32_t command_code = 0xb; - + struct data_fields { uint32_t function_type; uint8_t pt; uint8_t phase; uint16_t block_no; }; - - static_assert((sizeof (struct data_fields)) == 8); + }; +static_assert((sizeof (struct block_read::data_fields)) == 8); +template struct block_write { static constexpr uint32_t command_code = 0xc; - - template + struct data_fields { uint32_t function_type; uint8_t pt; @@ -142,118 +155,124 @@ struct block_write { uint16_t block_no; T written_data; }; - - static_assert((sizeof (struct data_fields)) == 8); + }; +static_assert((sizeof (struct block_write::data_fields)) == 8); struct get_last_error { static constexpr uint32_t command_code = 0xd; - + struct data_fields { uint32_t function_type; uint8_t pt; uint8_t phase; uint16_t block_no; }; - - static_assert((sizeof (struct data_fields)) == 8); + }; +static_assert((sizeof (struct get_last_error::data_fields)) == 8); +template struct set_condition { static constexpr uint32_t command_code = 0xe; - - template + struct data_fields { uint32_t function_type; T write_in_data; }; - - static_assert((sizeof (struct data_fields)) == 4); + }; +static_assert((sizeof (struct set_condition::data_fields)) == 4); +template struct ft4_control { static constexpr uint32_t command_code = 0xf; - - template + struct data_fields { uint32_t function_type; T ft4_data; }; - - static_assert((sizeof (struct data_fields)) == 4); + }; +static_assert((sizeof (struct ft4_control::data_fields)) == 4); +template struct ar_control { static constexpr uint32_t command_code = 0x10; - - template + struct data_fields { uint32_t function_type; T data; }; - - static_assert((sizeof (struct data_fields)) == 4); + }; +static_assert((sizeof (struct ar_control::data_fields)) == 4); struct function_type_unknown { static constexpr uint32_t command_code = 0xfe; - + struct data_fields { + uint8_t _empty[0]; }; }; +static_assert((sizeof (struct function_type_unknown::data_fields)) == 0); struct command_unknown { static constexpr uint32_t command_code = 0xfd; - + struct data_fields { + uint8_t _empty[0]; }; }; +static_assert((sizeof (struct command_unknown::data_fields)) == 0); struct transmit_again { static constexpr uint32_t command_code = 0xfc; - + struct data_fields { + uint8_t _empty[0]; }; }; +static_assert((sizeof (struct transmit_again::data_fields)) == 0); struct file_error { static constexpr uint32_t command_code = 0xfb; - + struct data_fields { uint32_t function_error_code; }; - - static_assert((sizeof (struct data_fields)) == 4); + }; +static_assert((sizeof (struct file_error::data_fields)) == 4); struct lcd_error { static constexpr uint32_t command_code = 0xfa; - + struct data_fields { uint32_t function_error_code; }; - - static_assert((sizeof (struct data_fields)) == 4); + }; +static_assert((sizeof (struct lcd_error::data_fields)) == 4); struct ar_error { static constexpr uint32_t command_code = 0xf9; - + struct data_fields { uint32_t function_error_code; }; - - static_assert((sizeof (struct data_fields)) == 4); + }; +static_assert((sizeof (struct ar_error::data_fields)) == 4); diff --git a/maple/maple_impl.hpp b/maple/maple_impl.hpp index 2e3069d..5349d0e 100644 --- a/maple/maple_impl.hpp +++ b/maple/maple_impl.hpp @@ -9,8 +9,8 @@ namespace maple { template -void init_host_command_all_ports(uint32_t * command_buf, uint32_t * receive_buf, - const typename C::data_fields& data_fields) +uint32_t init_host_command_all_ports(uint32_t * command_buf, uint32_t * receive_buf, + const typename C::data_fields& data_fields) { using command_type = maple::host_command; using response_type = maple::command_response; @@ -41,13 +41,16 @@ void init_host_command_all_ports(uint32_t * command_buf, uint32_t * receive_buf, ap::de::device | ap::port_select::d, C::command_code, (sizeof (typename C::data_fields)), true); // end_flag host_command[3].bus_data.data_fields = data_fields; + + return reinterpret_cast(&host_command[4]) - reinterpret_cast(&host_command[0]); } template -void init_host_command_all_ports(uint32_t * command_buf, uint32_t * receive_buf) +uint32_t init_host_command_all_ports(uint32_t * command_buf, uint32_t * receive_buf) { using command_type = maple::host_command; using response_type = maple::command_response; + //static_assert((sizeof (command_type)) == 12); auto host_command = reinterpret_cast(command_buf); auto response_command = reinterpret_cast(receive_buf); @@ -71,6 +74,8 @@ void init_host_command_all_ports(uint32_t * command_buf, uint32_t * receive_buf) host_instruction::port_select::d, // destination_port ap::de::device | ap::port_select::d, C::command_code, (sizeof (typename C::data_fields)), true); // end_flag + + return reinterpret_cast(&host_command[1]) - reinterpret_cast(&host_command[0]); } } diff --git a/regs/gen/maple_bus_commands.py b/regs/gen/maple_bus_commands.py index 86ab98a..cd00841 100644 --- a/regs/gen/maple_bus_commands.py +++ b/regs/gen/maple_bus_commands.py @@ -14,6 +14,11 @@ class CommandNamespace: def command_namespace(namespace: CommandNamespace, data_fields: list[tuple[str, tuple[int, str]]]): + length, variable = namespace.data_size + if variable is not None: + assert variable.lower() == "n" + yield "template " + yield f"struct {namespace.name} {{" yield f"static constexpr uint32_t command_code = {hex(namespace.command_code)};" yield "" @@ -21,14 +26,9 @@ def command_namespace(namespace: CommandNamespace, if namespace.data_size == (0, None): assert data_fields == [] yield "struct data_fields {" + yield "uint8_t _empty[0];" yield "};" else: - length, variable = namespace.data_size - - if variable is not None: - assert variable.lower() == "n" - yield "template " - yield "struct data_fields {" for field_name, field_size in data_fields: @@ -51,13 +51,13 @@ def command_namespace(namespace: CommandNamespace, yield "" - if variable is not None: - assert variable == "n" - yield f"static_assert((sizeof (struct data_fields)) == {length});" - else: - yield f"static_assert((sizeof (struct data_fields)) == {length});" - yield "};" + if variable is not None: + assert variable == "n" + yield f"static_assert((sizeof (struct {namespace.name}::data_fields)) == {length});" + else: + yield f"static_assert((sizeof (struct {namespace.name}::data_fields)) == {length});" + yield "" def parse_data_size(data_size, base, multiple) -> tuple[int, str]: diff --git a/systembus_bits.hpp b/systembus_bits.hpp index f93ebcb..8d42927 100644 --- a/systembus_bits.hpp +++ b/systembus_bits.hpp @@ -26,3 +26,34 @@ #define ISTNRM__END_OF_RENDER_TSP (1 << 2) #define ISTNRM__END_OF_RENDER_ISP (1 << 1) #define ISTNRM__END_OF_RENDER_VIDEO (1 << 0) + +#define ISTERR__SH4__IF_ACCESS_INHIBITED_AREA (1 << 31) +#define ISTERR__DDT__IF_SORT_DMA_COMMAND_ERROR (1 << 28) +#define ISTERR__G2__TIME_OUT_IN_CPU_ACCESS (1 << 27) +#define ISTERR__G2__DEV_DMA_TIME_OUT (1 << 26) +#define ISTERR__G2__EXT_DMA2_TIME_OUT (1 << 25) +#define ISTERR__G2__EXT_DMA1_TIME_OUT (1 << 24) +#define ISTERR__G2__AICA_DMA_TIME_OUT (1 << 23) +#define ISTERR__G2__DEV_DMA_OVER_RUN (1 << 22) +#define ISTERR__G2__EXT_DMA2_OVER_RUN (1 << 21) +#define ISTERR__G2__EXT_DMA1_OVER_RUN (1 << 20) +#define ISTERR__G2__AICA_DMA_OVER_RUN (1 << 19) +#define ISTERR__G2__DEV_DMA_ILLEGAL_ADDRESS_SET (1 << 18) +#define ISTERR__G2__EXT_DMA2_ILLEGAL_ADDRESS_SET (1 << 17) +#define ISTERR__G2__EXT_DMA1_ILLEGAL_ADDRESS_SET (1 << 16) +#define ISTERR__G2__AICA_DMA_ILLEGAL_ADDRESS_SET (1 << 15) +#define ISTERR__G1__ROM_FLASH_ACCESS_AT_GD_DMA (1 << 14) +#define ISTERR__G1__GD_DMA_OVER_RUN (1 << 13) +#define ISTERR__G1__ILLEGAL_ADDRESS_SET (1 << 12) +#define ISTERR__MAPLE__ILLEGAL_COMMAND (1 << 11) +#define ISTERR__MAPLE__WRITE_FIFO_OVER_FLOW (1 << 10) +#define ISTERR__MAPLE__DMA_OVER_RUN (1 << 9) +#define ISTERR__MAPLE__ILLEGAL_ADDRESS_SET (1 << 8) +#define ISTERR__PVRIF__DMA_OVER_RUN (1 << 7) +#define ISTERR__PVRIF__ILLEGAL_ADDRESS_SET (1 << 6) +#define ISTERR__TA__FIFO_OVERFLOW (1 << 5) +#define ISTERR__TA__ILLEGAL_PARAMETER (1 << 4) +#define ISTERR__TA__OBJECT_LIST_POINTER_OVERFLOW (1 << 3) +#define ISTERR__TA__ISP_TSP_PARAMETER_OVERFLOW (1 << 2) +#define ISTERR__RENDER__HAZARD_PROCESSING_OF_STRIP_BUFFER (1 << 1) +#define ISTERR__RENDER__ISP_OUT_OF_CACHE (1 << 0)