From be8f06e4860e5be5a5359dd842f0da14e3a99422 Mon Sep 17 00:00:00 2001 From: Zack Buhman Date: Tue, 21 May 2024 19:09:48 -0500 Subject: [PATCH] example: add maple_storage example --- example/clipping.cpp | 2 +- example/clipping2.cpp | 2 +- example/clipping_textured.cpp | 2 +- example/example.mk | 9 + example/maple_analog.cpp | 2 +- example/maple_controller.cpp | 2 +- example/maple_storage.cpp | 220 +++++++++++++++++++ example/modifier_volume_with_two_volumes.cpp | 2 +- example/texture_filtering_maple.cpp | 2 +- headers.mk | 3 + maple/maple_bus_commands.hpp | 6 +- maple/maple_bus_ft0.hpp | 1 + maple/maple_bus_ft1.hpp | 35 +++ regs/gen/maple_data_format.py | 39 +++- regs/maple_bus_commands.csv | 6 +- regs/maple_bus_commands.ods | Bin 17298 -> 17310 bytes regs/maple_bus_ft1.csv | 32 +++ regs/maple_bus_ft1.ods | Bin 0 -> 18921 bytes sh7091/serial.cpp | 13 ++ sh7091/serial.hpp | 4 + text_editor/keyboard.cpp | 2 +- 21 files changed, 362 insertions(+), 22 deletions(-) create mode 100644 example/maple_storage.cpp create mode 100644 maple/maple_bus_ft1.hpp create mode 100644 regs/maple_bus_ft1.csv create mode 100644 regs/maple_bus_ft1.ods diff --git a/example/clipping.cpp b/example/clipping.cpp index 1aa8cfb..7b23f46 100644 --- a/example/clipping.cpp +++ b/example/clipping.cpp @@ -58,7 +58,7 @@ void do_get_condition(uint32_t * command_buf, return; } auto& data_fields = bus_data.data_fields; - if ((data_fields.function_type & std::byteswap(function_type::controller)) == 0) { + if ((std::byteswap(data_fields.function_type) & function_type::controller) == 0) { return; } diff --git a/example/clipping2.cpp b/example/clipping2.cpp index 8ef15aa..12b09bd 100644 --- a/example/clipping2.cpp +++ b/example/clipping2.cpp @@ -59,7 +59,7 @@ void do_get_condition(uint32_t * command_buf, return; } auto& data_fields = bus_data.data_fields; - if ((data_fields.function_type & std::byteswap(function_type::controller)) == 0) { + if ((std::byteswap(data_fields.function_type) & function_type::controller) == 0) { return; } diff --git a/example/clipping_textured.cpp b/example/clipping_textured.cpp index 1559b4d..f1e8d1c 100644 --- a/example/clipping_textured.cpp +++ b/example/clipping_textured.cpp @@ -64,7 +64,7 @@ void do_get_condition(uint32_t * command_buf, return; } auto& data_fields = bus_data.data_fields; - if ((data_fields.function_type & std::byteswap(function_type::controller)) == 0) { + if ((std::byteswap(data_fields.function_type) & function_type::controller) == 0) { return; } diff --git a/example/example.mk b/example/example.mk index 9877d0b..1a30778 100644 --- a/example/example.mk +++ b/example/example.mk @@ -286,6 +286,15 @@ MAPLE_CONTROLLER_OBJ = \ example/maple_controller.elf: LDSCRIPT = $(LIB)/main.lds example/maple_controller.elf: $(START_OBJ) $(MAPLE_CONTROLLER_OBJ) +MAPLE_STORAGE_OBJ = \ + example/maple_storage.o \ + holly/video_output.o \ + sh7091/serial.o \ + maple/maple.o + +example/maple_storage.elf: LDSCRIPT = $(LIB)/main.lds +example/maple_storage.elf: $(START_OBJ) $(MAPLE_STORAGE_OBJ) + MAPLE_WINK_OBJ = \ example/maple_wink.o \ holly/video_output.o \ diff --git a/example/maple_analog.cpp b/example/maple_analog.cpp index 98c6701..ac8d926 100644 --- a/example/maple_analog.cpp +++ b/example/maple_analog.cpp @@ -58,7 +58,7 @@ void do_get_condition(uint32_t * command_buf, return; } auto& data_fields = bus_data.data_fields; - if ((data_fields.function_type & std::byteswap(function_type::controller)) == 0) { + if ((std::byteswap(data_fields.function_type) & function_type::controller) == 0) { return; } diff --git a/example/maple_controller.cpp b/example/maple_controller.cpp index 8602cc1..3dd21e0 100644 --- a/example/maple_controller.cpp +++ b/example/maple_controller.cpp @@ -39,7 +39,7 @@ void do_get_condition() if (bus_data.command_code != response_type::command_code) { //serial::string("device did not reply to get_condition: "); //serial::integer(port); - } else if ((data_fields.function_type & std::byteswap(function_type::controller)) != 0) { + } else if ((std::byteswap(data_fields.function_type) & function_type::controller) != 0) { bool a = ft0::data_transfer::digital_button::a(data_fields.data.digital_button); if (a == 0) { serial::string("port "); diff --git a/example/maple_storage.cpp b/example/maple_storage.cpp new file mode 100644 index 0000000..3fbb4d3 --- /dev/null +++ b/example/maple_storage.cpp @@ -0,0 +1,220 @@ +#include + +#include "align.hpp" +#include "holly/video_output.hpp" +#include "holly/core_bits.hpp" +#include "holly/holly.hpp" +#include "maple/maple.hpp" +#include "maple/maple_port.hpp" +#include "maple/maple_bus_bits.hpp" +#include "maple/maple_bus_commands.hpp" +#include "maple/maple_bus_ft1.hpp" +#include "maple/maple_host_command_writer.hpp" +#include "sh7091/serial.hpp" + +#include "systembus.hpp" + +void do_lm_request(uint8_t port, uint8_t lm) +{ + uint32_t send_buf[1024] __attribute__((aligned(32))); + uint32_t recv_buf[1024] __attribute__((aligned(32))); + + const uint32_t host_port_select = host_instruction_port_select(port); + const uint32_t destination_ap = ap_port_select(port) | ap::de::expansion_device | lm; + + { + using command_type = device_request; + using response_type = device_status; + + auto writer = maple::host_command_writer(send_buf, recv_buf); + + auto [host_command, host_response] + = writer.append_command(host_port_select, + destination_ap, + true); // end_flag + + maple::dma_start(send_buf, writer.send_offset, + recv_buf, writer.recv_offset); + + auto& bus_data = host_response->bus_data; + auto& data_fields = bus_data.data_fields; + if (bus_data.command_code != response_type::command_code) { + serial::string("lm did not reply: "); + serial::integer(port, ' '); + serial::integer(lm); + } else { + serial::string(" lm: "); + serial::integer(lm); + serial::string(" ft: "); + serial::hexlify(&data_fields.device_id.ft, 4); + serial::string(" fd[0]: "); + serial::hexlify(&data_fields.device_id.fd[0], 4); + serial::string(" fd[1]: "); + serial::hexlify(&data_fields.device_id.fd[1], 4); + serial::string(" fd[2]: "); + serial::hexlify(&data_fields.device_id.fd[2], 4); + serial::string(" source_ap.lm_bus: "); + serial::integer(bus_data.source_ap & ap::lm_bus::bit_mask); + } + + if ((std::byteswap(data_fields.device_id.ft) & function_type::storage) == 0) { + return; + } + } + + { + using command_type = get_media_info; + using response_type = data_transfer; + + auto writer = maple::host_command_writer(send_buf, recv_buf); + + auto [host_command, host_response] + = writer.append_command(host_port_select, + destination_ap, + true); // end_flag + host_command->bus_data.data_fields.function_type = std::byteswap(function_type::storage); + host_command->bus_data.data_fields.pt = 0; + + maple::dma_start(send_buf, writer.send_offset, + recv_buf, writer.recv_offset); + + auto& bus_data = host_response->bus_data; + auto& data_fields = bus_data.data_fields; + auto& data = data_fields.data; + + if (bus_data.command_code != response_type::command_code) { + serial::string("lm did not reply: "); + serial::integer(port, ' '); + serial::integer(lm); + } else { + serial::string(" total_size: "); + serial::integer(data.total_size); + serial::string(" partition_number: "); + serial::integer(data.partition_number); + serial::string(" system_area_block_number: "); + serial::integer(data.system_area_block_number); + serial::string(" fat_area_block_number: "); + serial::integer(data.fat_area_block_number); + serial::string(" number_of_fat_area_blocks: "); + serial::integer(data.number_of_fat_area_blocks); + serial::string(" file_information_block_number: "); + serial::integer(data.file_information_block_number); + serial::string(" number_of_file_information_blocks: "); + serial::integer(data.number_of_file_information_blocks); + serial::string(" volume_icon: "); + serial::integer(data.volume_icon); + serial::string(" save_area_block_number: "); + serial::integer(data.save_area_block_number); + serial::string(" number_of_save_area_blocks: "); + serial::integer(data.number_of_save_area_blocks); + serial::string(" reserved_for_execution_file: "); + serial::integer(data.reserved_for_execution_file); + } + } + + { + using command_type = block_read; + using response_type = data_transfer>; + + auto writer = maple::host_command_writer(send_buf, recv_buf); + + auto [host_command, host_response] + = writer.append_command(host_port_select, + destination_ap, + true); // end_flag + host_command->bus_data.data_fields.function_type = std::byteswap(function_type::storage); + host_command->bus_data.data_fields.pt = 0; + host_command->bus_data.data_fields.phase = 0; + host_command->bus_data.data_fields.block_number = std::byteswap(0xff); + + maple::dma_start(send_buf, writer.send_offset, + recv_buf, writer.recv_offset); + + auto& bus_data = host_response->bus_data; + auto& data_fields = bus_data.data_fields; + auto& data = data_fields.data; + serial::integer(std::byteswap(host_command->bus_data.data_fields.block_number)); + if (bus_data.command_code != response_type::command_code) { + serial::string("lm did not reply block_read: "); + serial::integer(port, ' '); + serial::integer(lm, ' '); + serial::integer(bus_data.command_code); + auto error = reinterpret_cast(&data_fields); + serial::hexlify(&error->function_error_code, 4); + } else { + for (int i = 0; i < 512; i++) { + serial::hexlify(data.block_data[i]); + serial::character(' '); + if (i % 16 == 15) { + serial::character('\n'); + } + } + } + } +} + +void do_lm_requests(uint8_t port, uint8_t lm) +{ + if (lm & ap::lm_bus::_0) + do_lm_request(port, lm & ap::lm_bus::_0); + if (lm & ap::lm_bus::_1) + do_lm_request(port, lm & ap::lm_bus::_1); + if (lm & ap::lm_bus::_2) + do_lm_request(port, lm & ap::lm_bus::_2); + if (lm & ap::lm_bus::_3) + do_lm_request(port, lm & ap::lm_bus::_3); + if (lm & ap::lm_bus::_4) + do_lm_request(port, lm & ap::lm_bus::_4); +} + +void do_device_request() +{ + uint32_t send_buf[1024] __attribute__((aligned(32))); + uint32_t recv_buf[1024] __attribute__((aligned(32))); + + auto writer = maple::host_command_writer(send_buf, recv_buf); + + using command_type = device_request; + using response_type = device_status; + + auto [host_command, host_response] + = writer.append_command_all_ports(); + + maple::dma_start(send_buf, writer.send_offset, + recv_buf, writer.recv_offset); + + for (uint8_t port = 0; port < 4; port++) { + auto& bus_data = host_response[port].bus_data; + auto& data_fields = bus_data.data_fields; + if (bus_data.command_code != response_type::command_code) { + serial::string("port: "); + serial::integer(port); + serial::string(" disconnected\n"); + } else { + serial::string("port: "); + serial::integer(port); + serial::string(" ft: "); + serial::hexlify(&data_fields.device_id.ft, 4); + serial::string(" fd[0]: "); + serial::hexlify(&data_fields.device_id.fd[0], 4); + serial::string(" fd[1]: "); + serial::hexlify(&data_fields.device_id.fd[1], 4); + serial::string(" fd[2]: "); + serial::hexlify(&data_fields.device_id.fd[2], 4); + serial::string(" source_ap.lm_bus: "); + serial::integer(bus_data.source_ap & ap::lm_bus::bit_mask); + + do_lm_requests(port, + bus_data.source_ap & ap::lm_bus::bit_mask); + } + } +} + +void main() +{ + // flycast needs this in HLE mode, or else it won't start the vcount + // counter. + video_output::set_mode_vga(); + + do_device_request(); +} diff --git a/example/modifier_volume_with_two_volumes.cpp b/example/modifier_volume_with_two_volumes.cpp index d07fd56..9b5d438 100644 --- a/example/modifier_volume_with_two_volumes.cpp +++ b/example/modifier_volume_with_two_volumes.cpp @@ -59,7 +59,7 @@ void do_get_condition(uint32_t * command_buf, return; } auto& data_fields = bus_data.data_fields; - if ((data_fields.function_type & std::byteswap(function_type::controller)) == 0) { + if ((std::byteswap(data_fields.function_type) & function_type::controller) == 0) { return; } diff --git a/example/texture_filtering_maple.cpp b/example/texture_filtering_maple.cpp index 5af8327..1684c59 100644 --- a/example/texture_filtering_maple.cpp +++ b/example/texture_filtering_maple.cpp @@ -258,7 +258,7 @@ void do_get_condition(uint32_t * command_buf, return; } auto& data_fields = bus_data.data_fields; - if ((data_fields.function_type & std::byteswap(function_type::controller)) == 0) { + if ((std::byteswap(data_fields.function_type) & function_type::controller) == 0) { return; } diff --git a/headers.mk b/headers.mk index 8c8b254..4217714 100644 --- a/headers.mk +++ b/headers.mk @@ -50,6 +50,9 @@ maple/maple_bus_bits.hpp: regs/maple_bus_bits.csv regs/gen/core_bits.py maple/maple_bus_ft0.hpp: regs/maple_bus_ft0.csv regs/gen/maple_data_format.py python regs/gen/maple_data_format.py $< > $@ +maple/maple_bus_ft1.hpp: regs/maple_bus_ft1.csv regs/gen/maple_data_format.py + python regs/gen/maple_data_format.py $< > $@ + maple/maple_bus_ft6.hpp: regs/maple_bus_ft6.csv regs/gen/maple_data_format.py python regs/gen/maple_data_format.py $< > $@ diff --git a/maple/maple_bus_commands.hpp b/maple/maple_bus_commands.hpp index 7a6c704..b76ec22 100644 --- a/maple/maple_bus_commands.hpp +++ b/maple/maple_bus_commands.hpp @@ -137,7 +137,7 @@ struct block_read { uint32_t function_type; uint8_t pt; uint8_t phase; - uint16_t block_no; + uint16_t block_number; }; }; @@ -152,7 +152,7 @@ struct block_write { uint32_t function_type; uint8_t pt; uint8_t phase; - uint16_t block_no; + uint16_t block_number; T written_data; }; @@ -167,7 +167,7 @@ struct get_last_error { uint32_t function_type; uint8_t pt; uint8_t phase; - uint16_t block_no; + uint16_t block_number; }; }; diff --git a/maple/maple_bus_ft0.hpp b/maple/maple_bus_ft0.hpp index aa835a1..999ab82 100644 --- a/maple/maple_bus_ft0.hpp +++ b/maple/maple_bus_ft0.hpp @@ -1,4 +1,5 @@ #pragma once + namespace ft0 { namespace data_transfer { namespace digital_button { diff --git a/maple/maple_bus_ft1.hpp b/maple/maple_bus_ft1.hpp new file mode 100644 index 0000000..4a7151b --- /dev/null +++ b/maple/maple_bus_ft1.hpp @@ -0,0 +1,35 @@ +#pragma once + +namespace ft1 { + namespace get_media_info_data_transfer { + struct data_format { + uint16_t total_size; + uint16_t partition_number; + uint16_t system_area_block_number; + uint16_t fat_area_block_number; + uint16_t number_of_fat_area_blocks; + uint16_t file_information_block_number; + uint16_t number_of_file_information_blocks; + uint16_t volume_icon; + uint16_t save_area_block_number; + uint16_t number_of_save_area_blocks; + uint32_t reserved_for_execution_file; + }; + static_assert((sizeof (struct data_format)) % 4 == 0); + static_assert((sizeof (struct data_format)) == 24); + } + + namespace block_read_data_transfer { + template + struct data_format { + uint8_t pt; + uint8_t phase; + uint16_t block_number; + uint8_t block_data[n]; + }; + static_assert((sizeof (struct data_format<0>)) % 4 == 0); + static_assert((sizeof (struct data_format<0>)) == 4); + } + +} + diff --git a/regs/gen/maple_data_format.py b/regs/gen/maple_data_format.py index da86a23..31b7fc2 100644 --- a/regs/gen/maple_data_format.py +++ b/regs/gen/maple_data_format.py @@ -1,4 +1,5 @@ import sys +import re from dataclasses import dataclass from collections import defaultdict @@ -80,8 +81,17 @@ def parse(rows): assert len(formats) > 0 return formats +def parse_format_name(name): + if '<' in name: + head, middle, tail = re.split('[<>]', name) + assert tail == "", name + return head, middle + else: + return name, None + def render_format(format): - yield f"namespace {format.name} {{" + format_name, variable = parse_format_name(format.name) + yield f"namespace {format_name} {{" for field_name in format.field_order: subfields = format.fields[field_name] if not any(field.bits != [] for field in subfields): @@ -100,23 +110,36 @@ def render_format(format): yield "}" yield "" + if variable is not None: + yield f"template " yield f"struct data_format {{" - for field_name in format.field_order: - subfields = format.fields[field_name] - if len(subfields) == 1: + for _field_name in format.field_order: + field_name, variable = parse_format_name(_field_name) + subfields = format.fields[_field_name] + if variable is not None: + assert len(subfields) == 1 + yield f"uint8_t {field_name}[{variable}];" + elif len(subfields) == 1: field, = subfields yield f"uint8_t {field_name};" elif len(subfields) == 2: yield f"uint16_t {field_name};" - elif len(subfields) == 6: - yield f"uint8_t {field_name}[6];" + elif len(subfields) in {3, 6}: + yield f"uint8_t {field_name}[{len(subfields)}];" + elif len(subfields) == 4: + yield f"uint32_t {field_name};" else: assert False, (len(subfields), field_name) yield "};" - assert format.size % 4 == 0, format.size - yield f"static_assert((sizeof (struct data_format)) == {format.size});" + format_name, variable = parse_format_name(format.name) + if variable is not None: + yield f"static_assert((sizeof (struct data_format<0>)) % 4 == 0);" + yield f"static_assert((sizeof (struct data_format<0>)) == {format.size - 1});" + else: + yield f"static_assert((sizeof (struct data_format)) % 4 == 0);" + yield f"static_assert((sizeof (struct data_format)) == {format.size});" yield "}" def render_formats(name, formats): diff --git a/regs/maple_bus_commands.csv b/regs/maple_bus_commands.csv index a065431..d31f6a9 100644 --- a/regs/maple_bus_commands.csv +++ b/regs/maple_bus_commands.csv @@ -37,18 +37,18 @@ "block_read","host","0x0b","0x02","function_type",4 "block_read",,,,"pt",1 "block_read",,,,"phase",1 -"block_read",,,,"block_no",2 +"block_read",,,,"block_number",2 ,,,,, "block_write","host","0x0c","0x02+n/4","function_type",4 "block_write",,,,"pt",1 "block_write",,,,"phase",1 -"block_write",,,,"block_no",2 +"block_write",,,,"block_number",2 "block_write",,,,"written_data","n" ,,,,, "get_last_error","host","0x0d","0x02","function_type",4 "get_last_error",,,,"pt",1 "get_last_error",,,,"phase",1 -"get_last_error",,,,"block_no",2 +"get_last_error",,,,"block_number",2 ,,,,, "set_condition","host","0x0e","0x01+n/4","function_type",4 "set_condition",,,,"write_in_data","n" diff --git a/regs/maple_bus_commands.ods b/regs/maple_bus_commands.ods index 1b56cf8674b2cb88901396ab6446d91b8e43dd6b..ed58d40f7fa0577ebc720a474594dfb99f6ee134 100644 GIT binary patch delta 6713 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 JBozA%{tv8>Rh9q% diff --git a/regs/maple_bus_ft1.csv b/regs/maple_bus_ft1.csv new file mode 100644 index 0000000..1bf81a1 --- /dev/null +++ b/regs/maple_bus_ft1.csv @@ -0,0 +1,32 @@ +"get_media_info_data_transfer",7,6,5,4,3,2,1,0 +"total_size",,,,,,,, +"total_size",,,,,,,, +"partition_number",,,,,,,, +"partition_number",,,,,,,, +"system_area_block_number",,,,,,,, +"system_area_block_number",,,,,,,, +"fat_area_block_number",,,,,,,, +"fat_area_block_number",,,,,,,, +"number_of_fat_area_blocks",,,,,,,, +"number_of_fat_area_blocks",,,,,,,, +"file_information_block_number",,,,,,,, +"file_information_block_number",,,,,,,, +"number_of_file_information_blocks",,,,,,,, +"number_of_file_information_blocks",,,,,,,, +"volume_icon",,,,,,,, +"volume_icon",,,,,,,, +"save_area_block_number",,,,,,,, +"save_area_block_number",,,,,,,, +"number_of_save_area_blocks",,,,,,,, +"number_of_save_area_blocks",,,,,,,, +"reserved_for_execution_file",,,,,,,, +"reserved_for_execution_file",,,,,,,, +"reserved_for_execution_file",,,,,,,, +"reserved_for_execution_file",,,,,,,, +,,,,,,,, +"block_read_data_transfer",7,6,5,4,3,2,1,0 +"pt",,,,,,,, +"phase",,,,,,,, +"block_number",,,,,,,, +"block_number",,,,,,,, +"block_data",,,,,,,, diff --git a/regs/maple_bus_ft1.ods b/regs/maple_bus_ft1.ods new file mode 100644 index 0000000000000000000000000000000000000000..e574186a6a7e07e0c7ed56988f06e2fe1db221df GIT binary patch literal 18921 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 L6(s), len); +} + template void integer(const T n, const char end, const uint32_t length) { diff --git a/sh7091/serial.hpp b/sh7091/serial.hpp index 2a87c12..80027cd 100644 --- a/sh7091/serial.hpp +++ b/sh7091/serial.hpp @@ -14,6 +14,10 @@ void string(const uint8_t * s, uint32_t len); void hexlify(const uint8_t n); +void hexlify(const uint8_t * s, uint32_t len); + +void hexlify(const uint32_t * s, uint32_t len); + using hex = string::hex_type; using dec = string::dec_type; diff --git a/text_editor/keyboard.cpp b/text_editor/keyboard.cpp index 7ceb190..3d846c2 100644 --- a/text_editor/keyboard.cpp +++ b/text_editor/keyboard.cpp @@ -32,7 +32,7 @@ void keyboard_do_get_condition(ft6::data_transfer::data_format& data) if (bus_data.command_code != response_type::command_code) { continue; } - if ((data_fields.function_type & std::byteswap(function_type::keyboard)) == 0) { + if ((std::byteswap(data_fields.function_type) & function_type::keyboard) == 0) { continue; }