diff --git a/base.mk b/base.mk index 1008f47..82f8536 100644 --- a/base.mk +++ b/base.mk @@ -2,10 +2,11 @@ DEBUG = -g -gdwarf-4 AFLAGS += --fatal-warnings -CFLAGS += -falign-functions=4 -ffunction-sections -fdata-sections -fshort-enums -ffreestanding -nostdlib +CFLAGS += -falign-functions=4 -ffunction-sections -fdata-sections -fshort-enums -ffreestanding -nostdlib -fno-builtin -finline-stringops CFLAGS += -Wall -Werror -Wfatal-errors CFLAGS += -Wno-array-bounds #CFLAGS += -Wno-error=narrowing -Wno-error=unused-variable -Wno-error=array-bounds= +CFLAGS += -Wno-error=maybe-uninitialized CXXFLAGS += -fno-exceptions -fno-non-call-exceptions -fno-rtti -fno-threadsafe-statics diff --git a/common.mk b/common.mk index 696f83f..b5fd50c 100644 --- a/common.mk +++ b/common.mk @@ -2,7 +2,7 @@ MAKEFILE_PATH := $(abspath $(lastword $(MAKEFILE_LIST))) DIR := $(dir $(MAKEFILE_PATH)) LIB ?= . -OPT ?= -O2 +OPT ?= -Os GENERATED ?= AARCH = --isa=sh4 --little diff --git a/example/clipping.cpp b/example/clipping.cpp index 8179988..1aa8cfb 100644 --- a/example/clipping.cpp +++ b/example/clipping.cpp @@ -46,7 +46,7 @@ void do_get_condition(uint32_t * command_buf, const uint32_t command_size = maple::init_host_command_all_ports(command_buf, receive_buf, data_fields); - using host_response_type = struct maple::command_response; + using host_response_type = struct maple::host_response; auto host_response = reinterpret_cast(receive_buf); maple::dma_start(command_buf, command_size, diff --git a/example/clipping2.cpp b/example/clipping2.cpp index f4b4389..8ef15aa 100644 --- a/example/clipping2.cpp +++ b/example/clipping2.cpp @@ -47,9 +47,8 @@ void do_get_condition(uint32_t * command_buf, .function_type = std::byteswap(function_type::controller) }; - const uint32_t command_size = maple::init_host_command_all_ports(command_buf, receive_buf, - data_fields); - using host_response_type = struct maple::command_response; + const uint32_t command_size = maple::init_host_command_all_ports(command_buf, receive_buf, data_fields); + using host_response_type = struct maple::host_response; auto host_response = reinterpret_cast(receive_buf); maple::dma_start(command_buf, command_size, receive_buf, maple::sizeof_command(host_response)); diff --git a/example/clipping_textured.cpp b/example/clipping_textured.cpp index 2a62628..1559b4d 100644 --- a/example/clipping_textured.cpp +++ b/example/clipping_textured.cpp @@ -51,14 +51,14 @@ void do_get_condition(uint32_t * command_buf, const uint32_t command_size = maple::init_host_command_all_ports(command_buf, receive_buf, data_fields); - using host_response_type = struct maple::command_response; + using host_response_type = struct maple::host_response; auto host_response = reinterpret_cast(receive_buf); maple::dma_start(command_buf, command_size, receive_buf, maple::sizeof_command(host_response)); - using command_response_type = struct maple::command_response; + using host_response_type = struct maple::host_response; for (uint8_t port = 0; port < 4; port++) { - auto response = reinterpret_cast(receive_buf); + auto response = reinterpret_cast(receive_buf); auto& bus_data = response[port].bus_data; if (bus_data.command_code != response_type::command_code) { return; diff --git a/example/maple_analog.cpp b/example/maple_analog.cpp index 030e904..98c6701 100644 --- a/example/maple_analog.cpp +++ b/example/maple_analog.cpp @@ -46,7 +46,7 @@ void do_get_condition(uint32_t * command_buf, const uint32_t command_size = maple::init_host_command_all_ports(command_buf, receive_buf, data_fields); - using host_response_type = struct maple::command_response; + using host_response_type = struct maple::host_response; auto host_response = reinterpret_cast(receive_buf); maple::dma_start(command_buf, command_size, diff --git a/example/maple_controller.cpp b/example/maple_controller.cpp index 78f277f..68b58df 100644 --- a/example/maple_controller.cpp +++ b/example/maple_controller.cpp @@ -5,114 +5,162 @@ #include "holly/core_bits.hpp" #include "holly/holly.hpp" #include "maple/maple.hpp" -#include "maple/maple_impl.hpp" +#include "maple/maple_port.hpp" #include "maple/maple_bus_bits.hpp" #include "maple/maple_bus_commands.hpp" #include "maple/maple_bus_ft0.hpp" +#include "maple/maple_host_command_writer.hpp" #include "sh7091/serial.hpp" -uint32_t _command_buf[(1024 + 32) / 4]; -uint32_t _receive_buf[(1024 + 32) / 4]; +#include "systembus.hpp" -static uint32_t * command_buf; -static uint32_t * receive_buf; - -void do_get_condition(uint32_t port) +void do_get_condition() { - uint32_t destination_port; - uint32_t destination_ap; + uint32_t send_buf[1024] __attribute__((aligned(32))); + uint32_t recv_buf[1024] __attribute__((aligned(32))); - switch (port) { - case 0: - destination_port = host_instruction::port_select::a; - destination_ap = ap::de::device | ap::port_select::a; - break; - case 1: - destination_port = host_instruction::port_select::b; - destination_ap = ap::de::device | ap::port_select::b; - break; - case 2: - destination_port = host_instruction::port_select::c; - destination_ap = ap::de::device | ap::port_select::c; - break; - case 3: - destination_port = host_instruction::port_select::d; - destination_ap = ap::de::device | ap::port_select::d; - break; - default: - return; - } - - const uint32_t command_size = maple::init_get_condition(command_buf, receive_buf, - destination_port, - destination_ap, - std::byteswap(function_type::controller)); + auto writer = maple::host_command_writer(send_buf, recv_buf); + using command_type = get_condition; using response_type = data_transfer; - using command_response_type = struct maple::command_response; - auto host_response = reinterpret_cast(receive_buf); - maple::dma_start(command_buf, command_size, - receive_buf, maple::sizeof_command(host_response)); + 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("device did not reply to get_condition: "); + //serial::integer(port); + } else if ((data_fields.function_type & std::byteswap(function_type::controller)) != 0) { + bool a = ft0::data_transfer::digital_button::a(data_fields.data.digital_button); + if (a == 0) { + serial::string("port "); + serial::integer(port); + serial::string(" `a` press "); + serial::integer(a); + } + } + } +} + +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))); + + auto writer = maple::host_command_writer(send_buf, recv_buf); + + uint32_t host_port_select = host_instruction_port_select(port); + uint32_t destination_ap = ap_port_select(port) | ap::de::expansion_device | lm; + + using command_type = device_request; + using response_type = device_status; + + 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; - if (bus_data.command_code != response_type::command_code) { - return; - } auto& data_fields = bus_data.data_fields; - if ((data_fields.function_type & std::byteswap(function_type::controller)) == 0) { - return; + if (bus_data.command_code != device_status::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::integer(std::byteswap(data_fields.device_id.ft)); + serial::string(" fd[0]: "); + serial::integer(std::byteswap(data_fields.device_id.fd[0])); + serial::string(" fd[1]: "); + serial::integer(std::byteswap(data_fields.device_id.fd[1])); + serial::string(" fd[2]: "); + serial::integer(std::byteswap(data_fields.device_id.fd[2])); + serial::string(" source_ap.lm_bus: "); + serial::integer(bus_data.source_ap & ap::lm_bus::bit_mask); } +} - bool a = ft0::data_transfer::digital_button::a(data_fields.data.digital_button); - if (a == 0) { - serial::string("port "); - serial::integer(port); - serial::string(" `a` press "); - serial::integer(a); - } +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; - const uint32_t command_size = maple::init_host_command_all_ports(command_buf, receive_buf); - using host_response_type = struct maple::command_response; - auto host_response = reinterpret_cast(receive_buf); + auto [host_command, host_response] + = writer.append_command_all_ports(); - maple::dma_start(command_buf, command_size, - receive_buf, maple::sizeof_command(host_response)); + 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 = host_response[port].bus_data.data_fields; + auto& data_fields = bus_data.data_fields; if (bus_data.command_code != device_status::command_code) { - // the controller is disconnected + serial::string("port: "); + serial::integer(port); + serial::string(" disconnected\n"); } else { - if ((data_fields.device_id.ft & std::byteswap(function_type::controller)) != 0) { - //serial::string("is controller: "); - //serial::integer(port); - do_get_condition(port); - } + serial::string("port: "); + serial::integer(port); + serial::string(" ft: "); + serial::integer(std::byteswap(data_fields.device_id.ft)); + serial::string(" fd[0]: "); + serial::integer(std::byteswap(data_fields.device_id.fd[0])); + serial::string(" fd[1]: "); + serial::integer(std::byteswap(data_fields.device_id.fd[1])); + serial::string(" fd[2]: "); + serial::integer(std::byteswap(data_fields.device_id.fd[2])); + 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() { - 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 // counter. video_output::set_mode_vga(); + do_device_request(); + while (1) { while (!spg_status::vsync(holly.SPG_STATUS)); while (spg_status::vsync(holly.SPG_STATUS)); - do_device_request(); + + do_get_condition(); }; } diff --git a/example/maple_device_request.cpp b/example/maple_device_request.cpp index 9781b9c..7857d68 100644 --- a/example/maple_device_request.cpp +++ b/example/maple_device_request.cpp @@ -18,7 +18,7 @@ void main() uint32_t command_size = maple::init_host_command_all_ports(command_buf, receive_buf); - constexpr uint32_t host_response_size = (sizeof (maple::command_response)); + constexpr uint32_t host_response_size = (sizeof (maple::host_response)); maple::dma_start(command_buf, command_size, receive_buf, host_response_size); diff --git a/example/maple_vibrator.cpp b/example/maple_vibrator.cpp index c86f8f9..9ae5fbb 100644 --- a/example/maple_vibrator.cpp +++ b/example/maple_vibrator.cpp @@ -47,16 +47,17 @@ void do_lm_request(uint8_t port, uint8_t lm) maple::init_host_command(command_buf, receive_buf, destination_port, destination_ap, get_media_info::command_code, (sizeof (struct get_media_info::data_fields)), - true); + true); // end_flag - using host_command_type = struct maple::host_command; + using command_type = get_media_info; + 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.pt = std::byteswap(1 << 24); using response_type = data_transfer; - using host_response_type = struct maple::command_response; + using host_response_type = struct maple::host_response; auto host_response = reinterpret_cast(receive_buf); serial::string("dma start\n"); @@ -118,7 +119,7 @@ void do_lm_request(uint8_t port, uint8_t lm) fields.write_in_data.freq = 0x27; fields.write_in_data.inc = 0x00; - using host_response_type = struct maple::command_response; + using host_response_type = struct maple::host_response; auto host_response = reinterpret_cast(receive_buf); maple::dma_start(command_buf, maple::sizeof_command(host_command), receive_buf, maple::sizeof_command(host_response)); @@ -154,11 +155,11 @@ void do_device_request() { using command_type = device_request; using response_type = device_status; - using host_response_type = struct maple::command_response; + using host_response_type = struct maple::host_response; auto host_response = reinterpret_cast(receive_buf); const uint32_t command_size = maple::init_host_command_all_ports(command_buf, receive_buf); maple::dma_start(command_buf, command_size, - receive_buf, maple::sizeof_command(host_response)); + receive_buf, maple::sizeof_command(host_response) * 4); for (uint8_t port = 0; port < 4; port++) { auto& bus_data = host_response[port].bus_data; @@ -193,5 +194,6 @@ void main() while (spg_status::vsync(holly.SPG_STATUS)); } do_device_request(); + break; }; } diff --git a/example/maple_wink.cpp b/example/maple_wink.cpp index 9b9fe29..675641e 100644 --- a/example/maple_wink.cpp +++ b/example/maple_wink.cpp @@ -42,12 +42,12 @@ void main() uint32_t * receive_buf = align_32byte(_receive_buf); const uint32_t command_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, + host_instruction::port_select::b, + ap::de::expansion_device | ap::port_select::b | ap::lm_bus::_0, wink_buf, wink_size); using response_type = device_reply; - using host_response_type = struct maple::command_response; + using host_response_type = struct maple::host_response; auto host_response = reinterpret_cast(receive_buf); maple::dma_start(command_buf, command_size, receive_buf, maple::sizeof_command(host_response)); @@ -56,6 +56,4 @@ void main() serial::integer(host_response->bus_data.destination_ap); serial::integer(host_response->bus_data.source_ap); serial::integer(host_response->bus_data.data_size); - - while(1); } diff --git a/example/modifier_volume_with_two_volumes.cpp b/example/modifier_volume_with_two_volumes.cpp index e881bed..d07fd56 100644 --- a/example/modifier_volume_with_two_volumes.cpp +++ b/example/modifier_volume_with_two_volumes.cpp @@ -47,7 +47,7 @@ void do_get_condition(uint32_t * command_buf, const uint32_t command_size = maple::init_host_command_all_ports(command_buf, receive_buf, data_fields); - using host_response_type = struct maple::command_response; + using host_response_type = struct maple::host_response; auto host_response = reinterpret_cast(receive_buf); maple::dma_start(command_buf, command_size, diff --git a/example/texture_filtering_maple.cpp b/example/texture_filtering_maple.cpp index 31ac0cf..5af8327 100644 --- a/example/texture_filtering_maple.cpp +++ b/example/texture_filtering_maple.cpp @@ -244,7 +244,7 @@ void do_get_condition(uint32_t * command_buf, const uint32_t command_size = maple::init_host_command_all_ports(command_buf, receive_buf, data_fields); - using host_response_type = struct maple::command_response; + using host_response_type = struct maple::host_response; auto host_response = reinterpret_cast(receive_buf); maple::dma_start(command_buf, command_size, diff --git a/maple/maple.cpp b/maple/maple.cpp index 3ee4494..79e72b1 100644 --- a/maple/maple.cpp +++ b/maple/maple.cpp @@ -15,6 +15,7 @@ namespace maple { +/* void init_host_command(uint32_t * command_buf, uint32_t * receive_buf, uint32_t destination_port, uint8_t destination_ap, uint8_t command_code, uint8_t data_size, @@ -104,6 +105,7 @@ uint32_t init_block_write(uint32_t * command_buf, uint32_t * receive_buf, return (reinterpret_cast(&host_command[1]) - reinterpret_cast(&host_command[0])) + data_size; } +*/ static inline void _dma_start(const uint32_t * command_buf) { diff --git a/maple/maple.hpp b/maple/maple.hpp index 2ae140e..eaa5188 100644 --- a/maple/maple.hpp +++ b/maple/maple.hpp @@ -22,7 +22,7 @@ static_assert((sizeof (host_command)) == 12); static_assert((sizeof (host_command[4])) == 48); template -struct command_response { +struct host_response { struct bus_data { uint8_t command_code; uint8_t destination_ap; @@ -32,7 +32,7 @@ struct command_response { } bus_data; uint8_t _pad[align_32byte((sizeof (bus_data))) - (sizeof (bus_data))]; }; -static_assert((sizeof (command_response)) == align_32byte((sizeof (command_response)))); +static_assert((sizeof (host_response)) == align_32byte((sizeof (host_response)))); void init_host_command(uint32_t * buf, uint32_t * receive_buf, uint32_t destination_port, diff --git a/maple/maple_bus_ft6_key_scan_codes.hpp b/maple/maple_bus_ft6_key_scan_codes.hpp index 43f2067..70df769 100644 --- a/maple/maple_bus_ft6_key_scan_codes.hpp +++ b/maple/maple_bus_ft6_key_scan_codes.hpp @@ -1,7 +1,9 @@ +#pragma once + #include namespace ft6 { - namespace scan_codes { + namespace scan_code { constexpr uint32_t no_operation = 0x0; constexpr uint32_t rollover_error = 0x1; constexpr uint32_t post_fail = 0x2; @@ -52,7 +54,7 @@ namespace ft6 { constexpr uint32_t bracketleft_braceleft = 0x2f; constexpr uint32_t bracketright_braceright = 0x30; constexpr uint32_t backslash_bar = 0x31; - constexpr uint32_t _unknown_ = 0x32; + constexpr uint32_t iso_numbersign_tilde = 0x32; constexpr uint32_t semicolon_colon = 0x33; constexpr uint32_t apostrophe_quotedbl = 0x34; constexpr uint32_t grave_asciitilde = 0x35; @@ -87,4 +89,69 @@ namespace ft6 { constexpr uint32_t up_arrow = 0x52; } } +namespace ft6 { + namespace scan_code { + constexpr uint32_t last_printable = 0x38; + + const uint8_t code_point[last_printable + 1][2] = { + [scan_code::no_operation] = { 0, 0 }, + [scan_code::rollover_error] = { 0, 0 }, + [scan_code::post_fail] = { 0, 0 }, + [scan_code::undefined_error] = { 0, 0 }, + [scan_code::a_A] = { 'a', 'A' }, + [scan_code::b_B] = { 'b', 'B' }, + [scan_code::c_C] = { 'c', 'C' }, + [scan_code::d_D] = { 'd', 'D' }, + [scan_code::e_E] = { 'e', 'E' }, + [scan_code::f_F] = { 'f', 'F' }, + [scan_code::g_G] = { 'g', 'G' }, + [scan_code::h_H] = { 'h', 'H' }, + [scan_code::i_I] = { 'i', 'I' }, + [scan_code::j_J] = { 'j', 'J' }, + [scan_code::k_K] = { 'k', 'K' }, + [scan_code::l_L] = { 'l', 'L' }, + [scan_code::m_M] = { 'm', 'M' }, + [scan_code::n_N] = { 'n', 'N' }, + [scan_code::o_O] = { 'o', 'O' }, + [scan_code::p_P] = { 'p', 'P' }, + [scan_code::q_Q] = { 'q', 'Q' }, + [scan_code::r_R] = { 'r', 'R' }, + [scan_code::s_S] = { 's', 'S' }, + [scan_code::t_T] = { 't', 'T' }, + [scan_code::u_U] = { 'u', 'U' }, + [scan_code::v_V] = { 'v', 'V' }, + [scan_code::w_W] = { 'w', 'W' }, + [scan_code::x_X] = { 'x', 'X' }, + [scan_code::y_Y] = { 'y', 'Y' }, + [scan_code::z_Z] = { 'z', 'Z' }, + [scan_code::_1_exclam] = { '1', '!' }, + [scan_code::_2_at] = { '2', '@' }, + [scan_code::_3_numbersign] = { '3', '#' }, + [scan_code::_4_dollar] = { '4', '$' }, + [scan_code::_5_percent] = { '5', '%' }, + [scan_code::_6_asciicircum] = { '6', '^' }, + [scan_code::_7_ampersand] = { '7', '&' }, + [scan_code::_8_asterisk] = { '8', '*' }, + [scan_code::_9_parenleft] = { '9', '(' }, + [scan_code::_0_parenright] = { '0', ')' }, + [scan_code::_return] = { 0, 0 }, + [scan_code::esc] = { 0, 0 }, + [scan_code::backspace] = { 0, 0 }, + [scan_code::tab] = { 0, 0 }, + [scan_code::spacebar] = { 0, 0 }, + [scan_code::minus_underscore] = { '-', '_' }, + [scan_code::equal_plus] = { '=', '+' }, + [scan_code::bracketleft_braceleft] = { '[', '{' }, + [scan_code::bracketright_braceright] = { ']', '}' }, + [scan_code::backslash_bar] = { '\\', '|' }, + [scan_code::iso_numbersign_tilde] = { '#', '~' }, + [scan_code::semicolon_colon] = { ';', ':' }, + [scan_code::apostrophe_quotedbl] = { '\'', '"' }, + [scan_code::grave_asciitilde] = { '\'', '~' }, + [scan_code::comma_less] = { ',', '<' }, + [scan_code::period_greater] = { '.', '>' }, + [scan_code::slash_question] = { '/', '?' }, + }; + } +} diff --git a/maple/maple_host_command_writer.hpp b/maple/maple_host_command_writer.hpp new file mode 100644 index 0000000..d45fa98 --- /dev/null +++ b/maple/maple_host_command_writer.hpp @@ -0,0 +1,72 @@ +#pragma once + +#include +#include + +#include "maple/maple.hpp" +#include "maple/maple_bus_commands.hpp" +#include "maple/maple_bus_bits.hpp" + +namespace maple { + +struct host_command_writer { + uint32_t * const send_buf; + uint32_t * const recv_buf; + uint32_t send_offset; + uint32_t recv_offset; + + constexpr host_command_writer(uint32_t * const send_buf, + uint32_t * const recv_buf) + : send_buf(send_buf), recv_buf(recv_buf), send_offset(0), recv_offset(0) + { } + + template + constexpr inline std::tuple *, + maple::host_response *> + append_command(uint32_t host_port_select, + uint32_t destination_ap, + bool end_flag) + { + using command_type = maple::host_command; + using response_type = maple::host_response; + constexpr uint32_t data_size = (sizeof (typename C::data_fields)) + data_fields_trailing; + + static_assert((sizeof (command_type)) % 4 == 0); + static_assert((sizeof (response_type)) % 4 == 0); + static_assert(data_size % 4 == 0); + + auto host_command = reinterpret_cast(&send_buf[send_offset / 4]); + auto host_response = reinterpret_cast(&recv_buf[recv_offset / 4]); + + host_command->host_instruction = (end_flag ? host_instruction::end_flag : 0) + | (host_port_select & host_instruction::port_select::bit_mask) + | host_instruction::transfer_length(data_size / 4); + + host_command->receive_data_storage_address = receive_data_storage_address::address(reinterpret_cast(host_response)); + + host_command->bus_data.command_code = C::command_code; + host_command->bus_data.destination_ap = destination_ap; + + host_command->bus_data.source_ap = destination_ap & ap::port_select::bit_mask; + host_command->bus_data.data_size = data_size / 4; + + send_offset += (sizeof (command_type)) + data_fields_trailing; + recv_offset += (sizeof (response_type)); + + return {host_command, host_response}; + } + + template + constexpr inline std::tuple *, + maple::host_response *> + append_command_all_ports() + { + auto ret = append_command(host_instruction::port_select::a, ap::de::device | ap::port_select::a, false); + append_command(host_instruction::port_select::b, ap::de::device | ap::port_select::b, false); + append_command(host_instruction::port_select::c, ap::de::device | ap::port_select::c, false); + append_command(host_instruction::port_select::d, ap::de::device | ap::port_select::d, true); + return ret; + } +}; + +} diff --git a/maple/maple_impl.hpp b/maple/maple_impl.hpp deleted file mode 100644 index 5349d0e..0000000 --- a/maple/maple_impl.hpp +++ /dev/null @@ -1,81 +0,0 @@ -#pragma once - -#include - -#include "maple/maple.hpp" -#include "maple/maple_bus_commands.hpp" -#include "maple/maple_bus_bits.hpp" - -namespace maple { - -template -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; - - auto host_command = reinterpret_cast(command_buf); - auto response_command = reinterpret_cast(receive_buf); - - init_host_command((uint32_t*)&host_command[0], (uint32_t*)&response_command[0], - host_instruction::port_select::a, // destination_port - ap::de::device | ap::port_select::a, C::command_code, (sizeof (typename C::data_fields)), - false); // end_flag - host_command[0].bus_data.data_fields = data_fields; - - init_host_command((uint32_t*)&host_command[1], (uint32_t*)&response_command[1], - host_instruction::port_select::b, // destination_port - ap::de::device | ap::port_select::b, C::command_code, (sizeof (typename C::data_fields)), - false); // end_flag - host_command[1].bus_data.data_fields = data_fields; - - init_host_command((uint32_t*)&host_command[2], (uint32_t*)&response_command[2], - host_instruction::port_select::c, // destination_port - ap::de::device | ap::port_select::c, C::command_code, (sizeof (typename C::data_fields)), - false); // end_flag - host_command[2].bus_data.data_fields = data_fields; - - init_host_command((uint32_t*)&host_command[3], (uint32_t*)&response_command[3], - 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 - host_command[3].bus_data.data_fields = data_fields; - - return reinterpret_cast(&host_command[4]) - reinterpret_cast(&host_command[0]); -} - -template -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); - - init_host_command((uint32_t*)&host_command[0], (uint32_t*)&response_command[0], - host_instruction::port_select::a, // destination_port - ap::de::device | ap::port_select::a, C::command_code, (sizeof (typename C::data_fields)), - false); // end_flag - - init_host_command((uint32_t*)&host_command[1], (uint32_t*)&response_command[1], - host_instruction::port_select::b, // destination_port - ap::de::device | ap::port_select::b, C::command_code, (sizeof (typename C::data_fields)), - false); // end_flag - - init_host_command((uint32_t*)&host_command[2], (uint32_t*)&response_command[2], - host_instruction::port_select::c, // destination_port - ap::de::device | ap::port_select::c, C::command_code, (sizeof (typename C::data_fields)), - false); // end_flag - - init_host_command((uint32_t*)&host_command[3], (uint32_t*)&response_command[3], - 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/maple/maple_port.hpp b/maple/maple_port.hpp new file mode 100644 index 0000000..dfe2246 --- /dev/null +++ b/maple/maple_port.hpp @@ -0,0 +1,25 @@ +#pragma once + +#include "maple_bus_bits.hpp" + +constexpr inline uint32_t ap_port_select(const uint32_t port) +{ + switch (port) { + default: [[fallthrough]]; + case 0: return ap::port_select::a; + case 1: return ap::port_select::b; + case 2: return ap::port_select::c; + case 3: return ap::port_select::d; + } +} + +constexpr inline uint32_t host_instruction_port_select(const uint32_t port) +{ + switch (port) { + default: [[fallthrough]]; + case 0: return host_instruction::port_select::a; + case 1: return host_instruction::port_select::b; + case 2: return host_instruction::port_select::c; + case 3: return host_instruction::port_select::d; + } +} diff --git a/regs/gen/maple_data_format.py b/regs/gen/maple_data_format.py index 49a519c..da86a23 100644 --- a/regs/gen/maple_data_format.py +++ b/regs/gen/maple_data_format.py @@ -121,7 +121,7 @@ def render_format(format): def render_formats(name, formats): yield "#pragma once" - + yield "" yield f"namespace {name} {{" for format in formats: yield from render_format(format) diff --git a/regs/gen/maple_key_scan_codes.py b/regs/gen/maple_key_scan_codes.py index 36738de..175be51 100644 --- a/regs/gen/maple_key_scan_codes.py +++ b/regs/gen/maple_key_scan_codes.py @@ -1,4 +1,5 @@ import sys +import string from csv_input import read_input from generate import renderer @@ -9,17 +10,59 @@ def render_row(row): yield f"constexpr uint32_t {usage} = {hex(code)};" def render_rows(rows): - yield "#include " - yield "" yield "namespace ft6 {" - yield "namespace scan_codes {" + yield "namespace scan_code {" for row in rows: yield from render_row(row) yield "}" yield "}" +def code_point(s): + if not s.strip(): + return '0' + elif len(s) == 1: + assert s in string.printable + if s == '\\': + return "'\\\\'" + elif s.strip() == "'": + return "'\\''" + else: + return f"'{s}'" + else: + assert False, s + +last_printable = 0x38 + +def render_normal_shift(row): + usage = row['usage'] + normal = code_point(row['normal']) + shift = code_point(row['shift']) + yield f"[scan_code::{usage}] = {{ {normal}, {shift} }}," + +def render_scancode_code_point(rows): + yield "namespace ft6 {" + yield "namespace scan_code {" + yield f"constexpr uint32_t last_printable = {hex(last_printable)};" + yield "" + yield f"const uint8_t code_point[last_printable + 1][2] = {{" + for i, row in enumerate(rows): + yield from render_normal_shift(row) + if i == last_printable: + break + yield "};" + yield "}" + yield "}" + +def header(): + yield "#pragma once" + yield "" + yield "#include " + yield "" + if __name__ == "__main__": rows = read_input(sys.argv[1]) render, out = renderer() + render(header()) render(render_rows(rows)) + render(render_scancode_code_point(rows)) print(out.getvalue()) diff --git a/regs/maple_bus_ft6_key_scan_codes.csv b/regs/maple_bus_ft6_key_scan_codes.csv index e31bc99..5b8e460 100644 --- a/regs/maple_bus_ft6_key_scan_codes.csv +++ b/regs/maple_bus_ft6_key_scan_codes.csv @@ -1,84 +1,84 @@ -"code","usage", -"0x00","no_operation", -"0x01","rollover_error", -"0x02","post_fail", -"0x03","undefined_error", -"0x04","a_A", -"0x05","b_B", -"0x06","c_C", -"0x07","d_D", -"0x08","e_E", -"0x09","f_F", -"0x0a","g_G", -"0x0b","h_H", -"0x0c","i_I", -"0x0d","j_J", -"0x0e","k_K", -"0x0f","l_L", -"0x10","m_M", -"0x11","n_N", -"0x12","o_O", -"0x13","p_P", -"0x14","q_Q", -"0x15","r_R", -"0x16","s_S", -"0x17","t_T", -"0x18","u_U", -"0x19","v_V", -"0x1a","w_W", -"0x1b","x_X", -"0x1c","y_Y", -"0x1d","z_Z", -"0x1e","_1_exclam", -"0x1f","_2_at", -"0x20","_3_numbersign", -"0x21","_4_dollar", -"0x22","_5_percent", -"0x23","_6_asciicircum", -"0x24","_7_ampersand", -"0x25","_8_asterisk", -"0x26","_9_parenleft", -"0x27","_0_parenright", -"0x28","_return", -"0x29","esc", -"0x2a","backspace", -"0x2b","tab", -"0x2c","spacebar", -"0x2d","minus_underscore", -"0x2e","equal_plus","underscore carot" -"0x2f","bracketleft_braceleft","at" -"0x30","bracketright_braceright","braceleft" -"0x31","backslash_bar", -"0x32","_unknown_", -"0x33","semicolon_colon", -"0x34","apostrophe_quotedbl", -"0x35","grave_asciitilde", -"0x36","comma_less", -"0x37","period_greater", -"0x38","slash_question", -"0x39","caps_lock", -"0x3a","F1", -"0x3b","F2", -"0x3c","F3", -"0x3d","F4", -"0x3e","F5", -"0x3f","F6", -"0x40","F7", -"0x41","F8", -"0x42","F9", -"0x43","F10", -"0x44","F11", -"0x45","F12", -"0x46","print_screen", -"0x47","scroll_lock", -"0x48","pause", -"0x49","insert", -"0x4a","home", -"0x4b","page_up", -"0x4c","_delete", -"0x4d","end", -"0x4e","page_down", -"0x4f","right_arrow", -"0x50","left_arrow", -"0x51","down_arrow", -"0x52","up_arrow", +"code","usage","normal","shift" +"0x00","no_operation",, +"0x01","rollover_error",, +"0x02","post_fail",, +"0x03","undefined_error",, +"0x04","a_A","a","A" +"0x05","b_B","b","B" +"0x06","c_C","c","C" +"0x07","d_D","d","D" +"0x08","e_E","e","E" +"0x09","f_F","f","F" +"0x0a","g_G","g","G" +"0x0b","h_H","h","H" +"0x0c","i_I","i","I" +"0x0d","j_J","j","J" +"0x0e","k_K","k","K" +"0x0f","l_L","l","L" +"0x10","m_M","m","M" +"0x11","n_N","n","N" +"0x12","o_O","o","O" +"0x13","p_P","p","P" +"0x14","q_Q","q","Q" +"0x15","r_R","r","R" +"0x16","s_S","s","S" +"0x17","t_T","t","T" +"0x18","u_U","u","U" +"0x19","v_V","v","V" +"0x1a","w_W","w","W" +"0x1b","x_X","x","X" +"0x1c","y_Y","y","Y" +"0x1d","z_Z","z","Z" +"0x1e","_1_exclam",1,"!" +"0x1f","_2_at",2,"@" +"0x20","_3_numbersign",3,"#" +"0x21","_4_dollar",4,"$" +"0x22","_5_percent",5,"%" +"0x23","_6_asciicircum",6,"^" +"0x24","_7_ampersand",7,"&" +"0x25","_8_asterisk",8,"*" +"0x26","_9_parenleft",9,"(" +"0x27","_0_parenright",0,")" +"0x28","_return",, +"0x29","esc",, +"0x2a","backspace",, +"0x2b","tab",, +"0x2c","spacebar",, +"0x2d","minus_underscore","-","_" +"0x2e","equal_plus","=","+" +"0x2f","bracketleft_braceleft","[","{" +"0x30","bracketright_braceright","]","}" +"0x31","backslash_bar","\","|" +"0x32","iso_numbersign_tilde","#","~" +"0x33","semicolon_colon",";",":" +"0x34","apostrophe_quotedbl","'","""" +"0x35","grave_asciitilde","'","~" +"0x36","comma_less",",","<" +"0x37","period_greater",".",">" +"0x38","slash_question","/","?" +"0x39","caps_lock",, +"0x3a","F1",, +"0x3b","F2",, +"0x3c","F3",, +"0x3d","F4",, +"0x3e","F5",, +"0x3f","F6",, +"0x40","F7",, +"0x41","F8",, +"0x42","F9",, +"0x43","F10",, +"0x44","F11",, +"0x45","F12",, +"0x46","print_screen",, +"0x47","scroll_lock",, +"0x48","pause",, +"0x49","insert",, +"0x4a","home",, +"0x4b","page_up",, +"0x4c","_delete",, +"0x4d","end",, +"0x4e","page_down",, +"0x4f","right_arrow",, +"0x50","left_arrow",, +"0x51","down_arrow",, +"0x52","up_arrow",, diff --git a/regs/maple_bus_ft6_key_scan_codes.ods b/regs/maple_bus_ft6_key_scan_codes.ods index 6d4333d..f5f6d3e 100644 Binary files a/regs/maple_bus_ft6_key_scan_codes.ods and b/regs/maple_bus_ft6_key_scan_codes.ods differ diff --git a/sh7091/serial.hpp b/sh7091/serial.hpp index 070621c..2a87c12 100644 --- a/sh7091/serial.hpp +++ b/sh7091/serial.hpp @@ -1,3 +1,5 @@ +#pragma once + #include "string.hpp" namespace serial { diff --git a/text_editor/keyboard.cpp b/text_editor/keyboard.cpp index bfe45e2..f7a7406 100644 --- a/text_editor/keyboard.cpp +++ b/text_editor/keyboard.cpp @@ -21,7 +21,7 @@ void keyboard_do_get_condition(uint32_t * command_buf, }; const uint32_t command_size = maple::init_host_command_all_ports(command_buf, receive_buf, data_fields); - using host_response_type = struct maple::command_response; + using host_response_type = struct maple::host_response; auto host_response = reinterpret_cast(receive_buf); maple::dma_start(command_buf, command_size, @@ -68,12 +68,21 @@ void keyboard_debug(ft6::data_transfer::data_format * keyboards, uint32_t frame_ } } +static inline bool is_shifted(const uint8_t modifier_key) +{ + return + (ft6::data_transfer::modifier_key::right_shift() & modifier_key) || + (ft6::data_transfer::modifier_key::left_shift() & modifier_key); +} + void keyboard_update(ft6::data_transfer::data_format * keyboards, uint32_t frame_ix, gap_buffer& gb) { uint32_t this_frame = (frame_ix + 0) & 1; uint32_t next_frame = (frame_ix + 1) & 1; for (int i = 0; i < 6; i++) { - if (i < 5 && keyboards[this_frame].scan_code_array[i + 1] != ft6::scan_codes::no_operation) + if (keyboards[this_frame].scan_code_array[i] == ft6::scan_code::no_operation) + break; + if (i < 5 && keyboards[this_frame].scan_code_array[i + 1] != ft6::scan_code::no_operation) continue; bool make = true; for (int j = 0; j < 6; j++) { @@ -85,63 +94,25 @@ void keyboard_update(ft6::data_transfer::data_format * keyboards, uint32_t frame if (make) { // make uint8_t scan_code = keyboards[this_frame].scan_code_array[i]; + if (scan_code <= ft6::scan_code::last_printable) { + bool shifted = is_shifted(keyboards[this_frame].modifier_key); + char_type code_point = ft6::scan_code::code_point[scan_code][shifted]; + if (code_point != 0) { + gap_append(gb, code_point); + continue; + } + } switch (scan_code) { - case ft6::scan_codes::a_A: [[fallthrough]]; - case ft6::scan_codes::b_B: [[fallthrough]]; - case ft6::scan_codes::c_C: [[fallthrough]]; - case ft6::scan_codes::d_D: [[fallthrough]]; - case ft6::scan_codes::e_E: [[fallthrough]]; - case ft6::scan_codes::f_F: [[fallthrough]]; - case ft6::scan_codes::g_G: [[fallthrough]]; - case ft6::scan_codes::h_H: [[fallthrough]]; - case ft6::scan_codes::i_I: [[fallthrough]]; - case ft6::scan_codes::j_J: [[fallthrough]]; - case ft6::scan_codes::k_K: [[fallthrough]]; - case ft6::scan_codes::l_L: [[fallthrough]]; - case ft6::scan_codes::m_M: [[fallthrough]]; - case ft6::scan_codes::n_N: [[fallthrough]]; - case ft6::scan_codes::o_O: [[fallthrough]]; - case ft6::scan_codes::p_P: [[fallthrough]]; - case ft6::scan_codes::q_Q: [[fallthrough]]; - case ft6::scan_codes::r_R: [[fallthrough]]; - case ft6::scan_codes::s_S: [[fallthrough]]; - case ft6::scan_codes::t_T: [[fallthrough]]; - case ft6::scan_codes::u_U: [[fallthrough]]; - case ft6::scan_codes::v_V: [[fallthrough]]; - case ft6::scan_codes::w_W: [[fallthrough]]; - case ft6::scan_codes::x_X: [[fallthrough]]; - case ft6::scan_codes::y_Y: [[fallthrough]]; - case ft6::scan_codes::z_Z: - { - char_type code_point = (scan_code - ft6::scan_codes::a_A) + 'a'; - gap_append(gb, code_point); - } - break; - case ft6::scan_codes::_1_exclam: [[fallthrough]]; - case ft6::scan_codes::_2_at: [[fallthrough]]; - case ft6::scan_codes::_3_numbersign: [[fallthrough]]; - case ft6::scan_codes::_4_dollar: [[fallthrough]]; - case ft6::scan_codes::_5_percent: [[fallthrough]]; - case ft6::scan_codes::_6_asciicircum: [[fallthrough]]; - case ft6::scan_codes::_7_ampersand: [[fallthrough]]; - case ft6::scan_codes::_8_asterisk: [[fallthrough]]; - case ft6::scan_codes::_9_parenleft: - { - char_type code_point = (scan_code - ft6::scan_codes::_1_exclam) + '1'; - gap_append(gb, code_point); - } - break; - case ft6::scan_codes::_0_parenright: gap_append(gb, '0'); break; - case ft6::scan_codes::_return: gap_append(gb, '\n'); break; - case ft6::scan_codes::backspace: gap_pop(gb); break; - case ft6::scan_codes::spacebar: gap_append(gb, ' '); break; + case ft6::scan_code::_return: gap_append(gb, '\n'); break; + case ft6::scan_code::backspace: gap_pop(gb); break; + case ft6::scan_code::spacebar: gap_append(gb, ' '); break; - case ft6::scan_codes::left_arrow: gap_cursor_pos(gb, -1); break; - case ft6::scan_codes::right_arrow: gap_cursor_pos(gb, 1); break; - case ft6::scan_codes::up_arrow: gap_cursor_pos_line(gb, -1); break; - case ft6::scan_codes::down_arrow: gap_cursor_pos_line(gb, 1); break; - default: - break; + case ft6::scan_code::left_arrow: gap_cursor_pos(gb, -1); break; + case ft6::scan_code::right_arrow: gap_cursor_pos(gb, 1); break; + case ft6::scan_code::up_arrow: gap_cursor_pos_line(gb, -1); break; + case ft6::scan_code::down_arrow: gap_cursor_pos_line(gb, 1); break; + default: + break; } } } diff --git a/text_editor/text_editor.cpp b/text_editor/text_editor.cpp index da9fd9c..e1830b6 100644 --- a/text_editor/text_editor.cpp +++ b/text_editor/text_editor.cpp @@ -80,13 +80,13 @@ void main() constexpr uint32_t ta_alloc = ta_alloc_ctrl::pt_opb::no_list | ta_alloc_ctrl::tm_opb::no_list - //| ta_alloc_ctrl::t_opb::_16x4byte + | ta_alloc_ctrl::t_opb::_16x4byte | ta_alloc_ctrl::om_opb::no_list | ta_alloc_ctrl::o_opb::_16x4byte; constexpr struct opb_size opb_size = { .opaque = 16 * 4 , .opaque_modifier = 0 - //, .translucent = 16 * 4 + , .translucent = 16 * 4 , .translucent_modifier = 0 , .punch_through = 0 };