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.
This commit is contained in:
Zack Buhman 2024-02-02 18:37:19 +08:00
parent a71ac1c4b1
commit 511d99563d
38 changed files with 472 additions and 283 deletions

View File

@ -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("<II", size, dest)
print("dargs", args)
#print("dargs", args)
ret = sync(ser, args)
print(ret)
#print(ret)
if ret != b'data\n':
print(".", end=' ')
sys.stdout.flush()
sync(ser, b'prime', wait=0)
do(ser, b)
print("\nDATA")
ret = symmetric(ser, b)
print(ret[-5:])
if ret[:-5] != b:
@ -97,4 +100,6 @@ with open(sys.argv[1], 'rb') as f:
with serial.Serial('/dev/ttyUSB0', 120192, timeout=1) as ser:
#console(ser)
print("waiting: ", end=' ')
sys.stdout.flush()
do(ser, b)

View File

@ -2,7 +2,7 @@ MAKEFILE_PATH := $(abspath $(lastword $(MAKEFILE_LIST)))
DIR := $(dir $(MAKEFILE_PATH))
LIB ?= .
OPT ?= -O2
OPT ?= -Og
DEBUG ?= -g -gdwarf-4
GENERATED ?=
@ -85,6 +85,7 @@ START_OBJ = \
%.bin: %.elf
$(OBJCOPY) -O binary $< $@
du -b $@
ip.elf: $(IP_OBJ)
$(LD) --orphan-handling=error --print-memory-usage -T $(LIB)/ip.lds $^ -o $@

View File

@ -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_type, response_type>(command_buf, receive_buf,
const uint32_t size = maple::init_host_command_all_ports<command_type, response_type>(command_buf, receive_buf,
data_fields);
maple::dma_start(command_buf);
maple::dma_start(command_buf, size);
using command_response_type = struct maple::command_response<response_type::data_fields>;
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;
}

View File

@ -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_type, response_type>(command_buf, receive_buf,
const uint32_t size = maple::init_host_command_all_ports<command_type, response_type>(command_buf, receive_buf,
data_fields);
maple::dma_start(command_buf);
maple::dma_start(command_buf, size);
using command_response_type = struct maple::command_response<response_type::data_fields>;
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;
}
}

View File

@ -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_type, response_type>(command_buf, receive_buf,
const uint32_t size = maple::init_host_command_all_ports<command_type, response_type>(command_buf, receive_buf,
data_fields);
maple::dma_start(command_buf);
maple::dma_start(command_buf, size);
using command_response_type = struct maple::command_response<response_type::data_fields>;
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;
}
}

View File

@ -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;
}

View File

@ -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)

View File

@ -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++;
}

View File

@ -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++;
}

View File

@ -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++;
}

View File

@ -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;

View File

@ -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;
}

View File

@ -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;

View File

@ -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;
}

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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_type, response_type>(command_buf, receive_buf,
const uint32_t size = maple::init_host_command_all_ports<command_type, response_type>(command_buf, receive_buf,
data_fields);
maple::dma_start(command_buf);
maple::dma_start(command_buf, size);
using command_response_type = struct maple::command_response<response_type::data_fields>;
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;
}
}

View File

@ -42,11 +42,11 @@ void do_get_condition(uint32_t port)
return;
}
maple::init_get_condition(command_buf, receive_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);
maple::dma_start(command_buf, size);
using response_type = data_transfer<ft0::data_transfer::data_format>;
using command_response_type = struct maple::command_response<response_type::data_fields>;
@ -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_type, response_type>(command_buf, receive_buf);
maple::dma_start(command_buf);
const uint32_t size = maple::init_host_command_all_ports<command_type, response_type>(command_buf, receive_buf);
maple::dma_start(command_buf, size * 10);
using command_response_type = struct maple::command_response<response_type::data_fields>;
auto response = reinterpret_cast<command_response_type *>(receive_buf);
@ -97,6 +97,7 @@ void do_device_request()
void main()
{
command_buf = align_32byte(_command_buf);
command_buf = reinterpret_cast<uint32_t *>(reinterpret_cast<uint32_t>(command_buf) | 0xa000'0000);
receive_buf = align_32byte(_receive_buf);
// flycast needs this in HLE mode, or else it won't start the vcount

View File

@ -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<device_request::data_fields>));
constexpr uint32_t command_response_size = align_32byte((sizeof (struct maple::command_response<device_status::data_fields>)));
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_type, response_type>(command_buf, receive_buf);
maple::dma_start(command_buf, size);
uint8_t * buf = reinterpret_cast<uint8_t *>(receive_buf);
for (uint8_t port = 0; port < 4; port++) {
serial::string("port ");
serial::integer<uint8_t>(port);
constexpr uint32_t command_response_size = (sizeof (maple::command_response<response_type::data_fields>));
for (uint32_t i = 0; i < command_response_size; i++) {
serial::integer<uint8_t>(buf[port * command_response_size + i]);
}

View File

@ -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<uint32_t>(&host_command[1]) - reinterpret_cast<uint32_t>(&host_command[0]));
maple::dma_start(command_buf, size * 2);
using response_type = data_transfer<ft8::data_transfer::data_format>;
using command_response_type = struct maple::command_response<response_type::data_fields>;
for (uint32_t i = 0; i < (sizeof (command_response_type)) / 32; i++) {
asm volatile ("ocbp @%0"
: // output
: "r" (reinterpret_cast<uint32_t>(&receive_buf[(32 * i) / 4])) // input
);
}
auto response = reinterpret_cast<command_response_type *>(receive_buf);
using response_type = struct maple::command_response<data_transfer::data_fields<struct ft8::data_transfer::data_format>>;
auto response = reinterpret_cast<response_type *>(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<uint8_t>(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<ft8::set_condition::data_format>;
using command_type = set_condition<ft8::set_condition::data_format>;
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<data_field_type>;
auto host_command = reinterpret_cast<command_type *>(command_buf);
using host_command_type = struct maple::host_command<command_type::data_fields>;
auto host_command = reinterpret_cast<host_command_type *>(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<uint32_t>(&host_command[1]) - reinterpret_cast<uint32_t>(&host_command[0]));
maple::dma_start(command_buf, size);
using response_type = struct maple::command_response<device_reply::data_fields>;
auto response = reinterpret_cast<response_type *>(receive_buf);
auto& bus_data = response->bus_data;
using command_response_type = struct maple::command_response<device_reply::data_fields>;
for (uint32_t i = 0; i < (sizeof (command_response_type)) / 32; i++) {
asm volatile ("ocbp @%0"
: // output
: "r" (reinterpret_cast<uint32_t>(&receive_buf[(32 * i) / 4])) // input
);
}
auto command_response = reinterpret_cast<command_response_type *>(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<device_status::data_fields>;
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_type, response_type>(command_buf, receive_buf);
maple::dma_start(command_buf, size);
using command_response_type = struct maple::command_response<response_type::data_fields>;
for (uint32_t i = 0; i < ((sizeof (command_response_type)) * 4) / 32; i++) {
asm volatile ("ocbp @%0"
: // output
: "r" (reinterpret_cast<uint32_t>(&receive_buf[(32 * i) / 4])) // input
);
}
auto response = reinterpret_cast<command_response_type *>(receive_buf);
for (uint8_t port = 0; port < 4; port++) {
auto response = reinterpret_cast<response_type *>(&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<uint32_t *>(reinterpret_cast<uint32_t>(command_buf) | 0xa000'0000);
receive_buf = align_32byte(_receive_buf);
vga();

View File

@ -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,
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);
maple::dma_start(command_buf, size);
for (int i = 0; i < 1; i++) {
serial::integer<uint32_t>(receive_buf[i]);

View File

@ -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;

View File

@ -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_type, response_type>(command_buf, receive_buf,
const uint32_t size = maple::init_host_command_all_ports<command_type, response_type>(command_buf, receive_buf,
data_fields);
maple::dma_start(command_buf);
maple::dma_start(command_buf, size);
using command_response_type = struct maple::command_response<response_type::data_fields>;
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;
}

View File

@ -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;
}
}

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;
}

View File

@ -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));
}

View File

@ -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

View File

@ -21,11 +21,11 @@ namespace plane {
{ -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));
}

View File

@ -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 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<struct host_command<uint8_t[0]> *>(command_buf);
return (reinterpret_cast<uint32_t>(&host_command[1]) - reinterpret_cast<uint32_t>(&host_command[0]));
}
void init_get_condition(uint32_t * buf, uint32_t * receive_buf,
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<struct host_command<get_condition::data_fields> *>(buf);
auto host_command = reinterpret_cast<struct host_command<get_condition::data_fields> *>(command_buf);
auto& fields = host_command->bus_data.data_fields;
// controller function type
fields.function_type = function_type;
return (reinterpret_cast<uint32_t>(&host_command[1]) - reinterpret_cast<uint32_t>(&host_command[0]));
}
void init_block_write(uint32_t * command_buf, uint32_t * receive_buf,
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<uint32_t[0]>;
init_host_command(command_buf, receive_buf,
destination_port,
destination_ap, block_write::command_code, (sizeof (struct block_write::data_fields<uint8_t[0]>)) + data_size,
destination_ap, command_type::command_code, (sizeof (struct command_type::data_fields)) + data_size,
true);
auto host_command = reinterpret_cast<struct host_command<block_write::data_fields<uint32_t[0]>> *>(command_buf);
auto host_command = reinterpret_cast<struct host_command<command_type::data_fields> *>(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<uint32_t>(&host_command[1]) - reinterpret_cast<uint32_t>(&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<uint32_t>(&command_buf[(32 * i) / 4])) // input
);
}
//command_buf = reinterpret_cast<uint32_t *>(reinterpret_cast<uint32_t>(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,7 +127,6 @@ 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
@ -119,18 +137,32 @@ void dma_start(uint32_t * command_buf)
// top address: the first/lowest address
// bottom address: the last/highest address
maple_if.MDAPRO = mdapro::security_code
| mdapro::top_address(0x00)
| mdapro::top_address(0x40)
| mdapro::bottom_address(0x7f);
maple_if.MDTSEL = mdtsel::trigger_select::software_initiation;
maple_if.MDSTAR = mdstar::table_address(reinterpret_cast<uint32_t>(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<uint32_t>(isterr);
last_isterr = isterr;
}
}
*/
while ((system.ISTNRM & ISTNRM__END_OF_DMA_MAPLE_DMA) == 0);
system.ISTNRM = ISTNRM__END_OF_DMA_MAPLE_DMA;
}

View File

@ -18,6 +18,8 @@ struct host_command {
T data_fields;
} bus_data;
};
static_assert((sizeof (host_command<uint8_t[0]>)) == 12);
static_assert((sizeof (host_command<uint8_t[0]>[4])) == 48);
template <typename T>
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 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 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 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);
}

View File

@ -12,33 +12,41 @@ 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;
@ -53,14 +61,14 @@ struct device_status {
uint16_t maximum_current_consumption;
};
static_assert((sizeof (struct data_fields)) == 112);
};
static_assert((sizeof (struct device_status::data_fields)) == 112);
template <typename T>
struct device_all_status {
static constexpr uint32_t command_code = 0x6;
template <typename T>
struct data_fields {
struct device_id device_id;
uint8_t destination_code;
@ -72,17 +80,20 @@ struct device_all_status {
T free_device_status;
};
static_assert((sizeof (struct data_fields<char[0]>)) == 112);
};
static_assert((sizeof (struct device_all_status<uint8_t[0]>::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 <typename T>
struct data_transfer {
static constexpr uint32_t command_code = 0x8;
@ -91,7 +102,9 @@ struct data_transfer {
uint32_t function_type;
T data;
};
};
static_assert((sizeof (struct data_transfer<uint8_t[0]>::data_fields)) == 4);
struct get_condition {
@ -101,9 +114,9 @@ struct get_condition {
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;
@ -113,9 +126,9 @@ struct get_media_info {
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;
@ -127,14 +140,14 @@ struct block_read {
uint16_t block_no;
};
static_assert((sizeof (struct data_fields)) == 8);
};
static_assert((sizeof (struct block_read::data_fields)) == 8);
template <typename T>
struct block_write {
static constexpr uint32_t command_code = 0xc;
template <typename T>
struct data_fields {
uint32_t function_type;
uint8_t pt;
@ -143,9 +156,9 @@ struct block_write {
T written_data;
};
static_assert((sizeof (struct data_fields<char[0]>)) == 8);
};
static_assert((sizeof (struct block_write<uint8_t[0]>::data_fields)) == 8);
struct get_last_error {
static constexpr uint32_t command_code = 0xd;
@ -157,72 +170,78 @@ struct get_last_error {
uint16_t block_no;
};
static_assert((sizeof (struct data_fields)) == 8);
};
static_assert((sizeof (struct get_last_error::data_fields)) == 8);
template <typename T>
struct set_condition {
static constexpr uint32_t command_code = 0xe;
template <typename T>
struct data_fields {
uint32_t function_type;
T write_in_data;
};
static_assert((sizeof (struct data_fields<char[0]>)) == 4);
};
static_assert((sizeof (struct set_condition<uint8_t[0]>::data_fields)) == 4);
template <typename T>
struct ft4_control {
static constexpr uint32_t command_code = 0xf;
template <typename T>
struct data_fields {
uint32_t function_type;
T ft4_data;
};
static_assert((sizeof (struct data_fields<char[0]>)) == 4);
};
static_assert((sizeof (struct ft4_control<uint8_t[0]>::data_fields)) == 4);
template <typename T>
struct ar_control {
static constexpr uint32_t command_code = 0x10;
template <typename T>
struct data_fields {
uint32_t function_type;
T data;
};
static_assert((sizeof (struct data_fields<char[0]>)) == 4);
};
static_assert((sizeof (struct ar_control<uint8_t[0]>::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;
@ -231,9 +250,9 @@ struct file_error {
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;
@ -242,9 +261,9 @@ struct lcd_error {
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;
@ -253,7 +272,7 @@ struct ar_error {
uint32_t function_error_code;
};
static_assert((sizeof (struct data_fields)) == 4);
};
static_assert((sizeof (struct ar_error::data_fields)) == 4);

View File

@ -9,7 +9,7 @@
namespace maple {
template <typename C, typename R>
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,
const typename C::data_fields& data_fields)
{
using command_type = maple::host_command<typename C::data_fields>;
@ -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<uint32_t>(&host_command[4]) - reinterpret_cast<uint32_t>(&host_command[0]);
}
template <typename C, typename R>
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<typename C::data_fields>;
using response_type = maple::command_response<typename R::data_fields>;
//static_assert((sizeof (command_type)) == 12);
auto host_command = reinterpret_cast<command_type *>(command_buf);
auto response_command = reinterpret_cast<response_type *>(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<uint32_t>(&host_command[1]) - reinterpret_cast<uint32_t>(&host_command[0]);
}
}

View File

@ -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 <typename T>"
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 <typename T>"
yield "struct data_fields {"
for field_name, field_size in data_fields:
@ -51,13 +51,13 @@ def command_namespace(namespace: CommandNamespace,
yield ""
yield "};"
if variable is not None:
assert variable == "n"
yield f"static_assert((sizeof (struct data_fields<char[0]>)) == {length});"
yield f"static_assert((sizeof (struct {namespace.name}<uint8_t[0]>::data_fields)) == {length});"
else:
yield f"static_assert((sizeof (struct data_fields)) == {length});"
yield f"static_assert((sizeof (struct {namespace.name}::data_fields)) == {length});"
yield "};"
yield ""
def parse_data_size(data_size, base, multiple) -> tuple[int, str]:

View File

@ -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)