dreamcast2: add maple headers

This commit is contained in:
Zack Buhman 2025-09-03 14:12:06 -05:00
parent 1f8010ef89
commit 8ef2d20749
17 changed files with 1199 additions and 0 deletions

View File

@ -0,0 +1,38 @@
#pragma once
#include <cstdint>
namespace maple {
struct protocol_header {
uint8_t command_code;
uint8_t destination_ap;
uint8_t source_ap;
uint8_t data_size;
};
template <typename T>
struct host_command {
uint32_t host_instruction; // interpreted by the Maple DMA controller
uint32_t receive_data_address; // interpreted by the Maple DMA controller
protocol_header header;
T data;
};
static_assert((sizeof (host_command<uint8_t[0]>)) == 12);
static_assert((sizeof (host_command<uint8_t[0]>[4])) == 48);
constexpr inline uint32_t align(uint32_t mem)
{
return (mem + 31) & ~31;
}
template <typename T>
struct host_response {
protocol_header header;
T data;
uint8_t _pad[align((sizeof (protocol_header)) + (sizeof (T))) - ((sizeof (protocol_header)) + (sizeof (T)))];
};
static_assert((sizeof (host_response<uint8_t[0]>)) == 32);
}

View File

@ -0,0 +1,90 @@
#pragma once
#include <cstdint>
namespace maple {
namespace mdstar {
constexpr inline uint32_t table_address(uint32_t num) { return (num & 0xfffffe0) << 0; }
}
namespace mdtsel {
namespace trigger_select {
constexpr uint32_t software_initiation = 0 << 0;
constexpr uint32_t v_blank_initiation = 1 << 0;
constexpr uint32_t bit_mask = 0x1 << 0;
}
}
namespace mden {
namespace dma_enable {
constexpr uint32_t abort = 0 << 0;
constexpr uint32_t enable = 1 << 0;
constexpr inline uint32_t status(uint32_t reg) { return (reg >> 0) & 0x1; }
constexpr uint32_t bit_mask = 0x1 << 0;
}
}
namespace mdst {
namespace start_status {
constexpr inline uint32_t status(uint32_t reg) { return (reg >> 0) & 0x1; }
constexpr uint32_t start = 1 << 0;
constexpr uint32_t bit_mask = 0x1 << 0;
}
}
namespace msys {
constexpr inline uint32_t time_out_counter(uint32_t num) { return (num & 0xffff) << 16; }
constexpr uint32_t single_hard_trigger = 1 << 12;
namespace sending_rate {
constexpr uint32_t _2M = 0 << 8;
constexpr uint32_t _1M = 1 << 8;
constexpr uint32_t bit_mask = 0x3 << 8;
}
constexpr inline uint32_t delay_time(uint32_t num) { return (num & 0xf) << 0; }
}
namespace mst {
constexpr inline uint32_t move_status(uint32_t reg) { return (reg >> 31) & 0x1; }
constexpr inline uint32_t internal_frame_monitor(uint32_t reg) { return (reg >> 24) & 0x7; }
constexpr inline uint32_t internal_state_monitor(uint32_t reg) { return (reg >> 16) & 0x3f; }
constexpr inline uint32_t line_monitor(uint32_t reg) { return (reg >> 0) & 0xff; }
}
namespace mshtcl {
constexpr uint32_t hard_dma_clear = 1 << 0;
}
namespace mdapro {
constexpr uint32_t security_code = 0x6155 << 16;
constexpr inline uint32_t top_address(uint32_t num) { return (num & 0x7f) << 8; }
constexpr inline uint32_t bottom_address(uint32_t num) { return (num & 0x7f) << 0; }
}
namespace mmsel {
namespace msb_selection {
constexpr uint32_t bit7 = 0 << 0;
constexpr uint32_t bit31 = 1 << 0;
constexpr uint32_t bit_mask = 0x1 << 0;
}
}
namespace mtxdad {
constexpr inline uint32_t txd_address_counter(uint32_t reg) { return (reg >> 0) & 0x1fffffff; }
}
namespace mrxdad {
constexpr inline uint32_t rxd_address_counter(uint32_t reg) { return (reg >> 0) & 0x1fffffff; }
}
namespace mrxdbd {
constexpr inline uint32_t rxd_base_address(uint32_t reg) { return (reg >> 0) & 0x1fffffff; }
}
}

View File

@ -0,0 +1,79 @@
#pragma once
#include <cstdint>
namespace maple {
namespace host_instruction {
constexpr uint32_t end_flag = 1 << 31;
namespace port_select {
constexpr uint32_t a = 0 << 16;
constexpr uint32_t b = 1 << 16;
constexpr uint32_t c = 2 << 16;
constexpr uint32_t d = 3 << 16;
constexpr uint32_t bit_mask = 0x3 << 16;
}
namespace pattern {
constexpr uint32_t normal = 0b000 << 8;
constexpr uint32_t light_gun_mode = 0b010 << 8;
constexpr uint32_t reset = 0b011 << 8;
constexpr uint32_t return_from_light_gun_mode = 0b100 << 8;
constexpr uint32_t nop = 0b111 << 8;
constexpr uint32_t bit_mask = 0x7 << 8;
}
constexpr inline uint32_t transfer_length(uint32_t num) { return (num & 0xff) << 0; }
}
namespace receive_data_storage_address {
constexpr inline uint32_t address(uint32_t num) { return (num & 0x1fffffff) << 0; }
}
namespace ap {
namespace port_select {
constexpr uint32_t a = 0b00 << 6;
constexpr uint32_t b = 0b01 << 6;
constexpr uint32_t c = 0b10 << 6;
constexpr uint32_t d = 0b11 << 6;
constexpr uint32_t bit_mask = 0x3 << 6;
}
namespace de {
constexpr uint32_t device = 1 << 5;
constexpr uint32_t expansion_device = 0 << 5;
constexpr uint32_t port = 0 << 5;
constexpr uint32_t bit_mask = 0x1 << 5;
}
namespace lm_bus {
constexpr uint32_t _4 = 0b10000 << 0;
constexpr uint32_t _3 = 0b01000 << 0;
constexpr uint32_t _2 = 0b00100 << 0;
constexpr uint32_t _1 = 0b00010 << 0;
constexpr uint32_t _0 = 0b00001 << 0;
constexpr uint32_t bit_mask = 0x1f << 0;
}
}
namespace function_type {
constexpr uint32_t camera = 1 << 11;
constexpr uint32_t exchange_media = 1 << 10;
constexpr uint32_t pointing = 1 << 9;
constexpr uint32_t vibration = 1 << 8;
constexpr uint32_t light_gun = 1 << 7;
constexpr uint32_t keyboard = 1 << 6;
constexpr uint32_t ar_gun = 1 << 5;
constexpr uint32_t audio_input = 1 << 4;
constexpr uint32_t timer = 1 << 3;
constexpr uint32_t bw_lcd = 1 << 2;
constexpr uint32_t storage = 1 << 1;
constexpr uint32_t controller = 1 << 0;
}
}

View File

@ -0,0 +1,260 @@
#pragma once
#include <cstdint>
namespace maple {
struct device_id {
uint32_t ft;
uint32_t fd[3];
};
static_assert((sizeof (struct device_id)) == 16);
struct device_request {
static constexpr uint32_t command_code = 0x1;
struct data_fields {
uint8_t _empty[0];
};
};
static_assert((sizeof (struct device_request::data_fields)) == 0);
struct all_status_request {
static constexpr uint32_t command_code = 0x2;
struct data_fields {
uint8_t _empty[0];
};
};
static_assert((sizeof (struct all_status_request::data_fields)) == 0);
struct device_reset {
static constexpr uint32_t command_code = 0x3;
struct data_fields {
uint8_t _empty[0];
};
};
static_assert((sizeof (struct device_reset::data_fields)) == 0);
struct device_kill {
static constexpr uint32_t command_code = 0x4;
struct data_fields {
uint8_t _empty[0];
};
};
static_assert((sizeof (struct device_kill::data_fields)) == 0);
struct device_status {
static constexpr uint32_t command_code = 0x5;
struct data_fields {
struct device_id device_id;
uint8_t destination_code;
uint8_t connection_direction;
uint8_t product_name[30];
uint8_t license[60];
uint16_t low_consumption_standby_current;
uint16_t maximum_current_consumption;
};
};
static_assert((sizeof (struct device_status::data_fields)) == 112);
template <typename T>
struct device_all_status {
static constexpr uint32_t command_code = 0x6;
struct data_fields {
struct device_id device_id;
uint8_t destination_code;
uint8_t connection_direction;
uint8_t product_name[30];
uint8_t license[60];
uint16_t low_consumption_standby_current;
uint16_t maximum_current_consumption;
T free_device_status;
};
};
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;
struct data_fields {
uint32_t function_type;
T data;
};
};
static_assert((sizeof (struct data_transfer<uint8_t[0]>::data_fields)) == 4);
struct get_condition {
static constexpr uint32_t command_code = 0x9;
struct data_fields {
uint32_t function_type;
};
};
static_assert((sizeof (struct get_condition::data_fields)) == 4);
struct get_media_info {
static constexpr uint32_t command_code = 0xa;
struct data_fields {
uint32_t function_type;
uint32_t pt;
};
};
static_assert((sizeof (struct get_media_info::data_fields)) == 8);
struct block_read {
static constexpr uint32_t command_code = 0xb;
struct data_fields {
uint32_t function_type;
uint8_t pt;
uint8_t phase;
uint16_t block_number;
};
};
static_assert((sizeof (struct block_read::data_fields)) == 8);
template <typename T>
struct block_write {
static constexpr uint32_t command_code = 0xc;
struct data_fields {
uint32_t function_type;
uint8_t pt;
uint8_t phase;
uint16_t block_number;
T written_data;
};
};
static_assert((sizeof (struct block_write<uint8_t[0]>::data_fields)) == 8);
struct get_last_error {
static constexpr uint32_t command_code = 0xd;
struct data_fields {
uint32_t function_type;
uint8_t pt;
uint8_t phase;
uint16_t block_number;
};
};
static_assert((sizeof (struct get_last_error::data_fields)) == 8);
template <typename T>
struct set_condition {
static constexpr uint32_t command_code = 0xe;
struct data_fields {
uint32_t function_type;
T write_in_data;
};
};
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;
struct data_fields {
uint32_t function_type;
T ft4_data;
};
};
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;
struct data_fields {
uint32_t function_type;
T data;
};
};
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;
struct data_fields {
uint32_t function_error_code;
};
};
static_assert((sizeof (struct file_error::data_fields)) == 4);
struct lcd_error {
static constexpr uint32_t command_code = 0xfa;
struct data_fields {
uint32_t function_error_code;
};
};
static_assert((sizeof (struct lcd_error::data_fields)) == 4);
struct ar_error {
static constexpr uint32_t command_code = 0xf9;
struct data_fields {
uint32_t function_error_code;
};
};
static_assert((sizeof (struct ar_error::data_fields)) == 4);
}

View File

@ -0,0 +1,67 @@
#pragma once
#include <cstdint>
namespace maple::ft0 {
namespace data_transfer {
namespace digital_button {
constexpr uint32_t ra() { return 0b1 << 7; }
constexpr uint32_t ra(uint32_t reg) { return (reg >> 7) & 0b1; }
constexpr uint32_t la() { return 0b1 << 6; }
constexpr uint32_t la(uint32_t reg) { return (reg >> 6) & 0b1; }
constexpr uint32_t da() { return 0b1 << 5; }
constexpr uint32_t da(uint32_t reg) { return (reg >> 5) & 0b1; }
constexpr uint32_t ua() { return 0b1 << 4; }
constexpr uint32_t ua(uint32_t reg) { return (reg >> 4) & 0b1; }
constexpr uint32_t start() { return 0b1 << 3; }
constexpr uint32_t start(uint32_t reg) { return (reg >> 3) & 0b1; }
constexpr uint32_t a() { return 0b1 << 2; }
constexpr uint32_t a(uint32_t reg) { return (reg >> 2) & 0b1; }
constexpr uint32_t b() { return 0b1 << 1; }
constexpr uint32_t b(uint32_t reg) { return (reg >> 1) & 0b1; }
constexpr uint32_t c() { return 0b1 << 0; }
constexpr uint32_t c(uint32_t reg) { return (reg >> 0) & 0b1; }
constexpr uint32_t rb() { return 0b1 << 15; }
constexpr uint32_t rb(uint32_t reg) { return (reg >> 15) & 0b1; }
constexpr uint32_t lb() { return 0b1 << 14; }
constexpr uint32_t lb(uint32_t reg) { return (reg >> 14) & 0b1; }
constexpr uint32_t db() { return 0b1 << 13; }
constexpr uint32_t db(uint32_t reg) { return (reg >> 13) & 0b1; }
constexpr uint32_t ub() { return 0b1 << 12; }
constexpr uint32_t ub(uint32_t reg) { return (reg >> 12) & 0b1; }
constexpr uint32_t d() { return 0b1 << 11; }
constexpr uint32_t d(uint32_t reg) { return (reg >> 11) & 0b1; }
constexpr uint32_t x() { return 0b1 << 10; }
constexpr uint32_t x(uint32_t reg) { return (reg >> 10) & 0b1; }
constexpr uint32_t y() { return 0b1 << 9; }
constexpr uint32_t y(uint32_t reg) { return (reg >> 9) & 0b1; }
constexpr uint32_t z() { return 0b1 << 8; }
constexpr uint32_t z(uint32_t reg) { return (reg >> 8) & 0b1; }
}
struct data_format {
uint16_t digital_button;
uint8_t analog_coordinate_axis[6];
};
static_assert((sizeof (struct data_format)) % 4 == 0);
static_assert((sizeof (struct data_format)) == 8);
}
}

View File

@ -0,0 +1,82 @@
#pragma once
#include <cstdint>
namespace maple::ft6 {
namespace data_transfer {
namespace modifier_key {
constexpr uint32_t s2() { return 0b1 << 7; }
constexpr uint32_t s2(uint32_t reg) { return (reg >> 7) & 0b1; }
constexpr uint32_t right_alt() { return 0b1 << 6; }
constexpr uint32_t right_alt(uint32_t reg) { return (reg >> 6) & 0b1; }
constexpr uint32_t right_shift() { return 0b1 << 5; }
constexpr uint32_t right_shift(uint32_t reg) { return (reg >> 5) & 0b1; }
constexpr uint32_t right_control() { return 0b1 << 4; }
constexpr uint32_t right_control(uint32_t reg) { return (reg >> 4) & 0b1; }
constexpr uint32_t left_gui() { return 0b1 << 3; }
constexpr uint32_t left_gui(uint32_t reg) { return (reg >> 3) & 0b1; }
constexpr uint32_t left_alt() { return 0b1 << 2; }
constexpr uint32_t left_alt(uint32_t reg) { return (reg >> 2) & 0b1; }
constexpr uint32_t left_shift() { return 0b1 << 1; }
constexpr uint32_t left_shift(uint32_t reg) { return (reg >> 1) & 0b1; }
constexpr uint32_t left_control() { return 0b1 << 0; }
constexpr uint32_t left_control(uint32_t reg) { return (reg >> 0) & 0b1; }
}
namespace led_state {
constexpr uint32_t shift() { return 0b1 << 7; }
constexpr uint32_t shift(uint32_t reg) { return (reg >> 7) & 0b1; }
constexpr uint32_t power() { return 0b1 << 6; }
constexpr uint32_t power(uint32_t reg) { return (reg >> 6) & 0b1; }
constexpr uint32_t kana() { return 0b1 << 5; }
constexpr uint32_t kana(uint32_t reg) { return (reg >> 5) & 0b1; }
constexpr uint32_t reserved0() { return 0b1 << 4; }
constexpr uint32_t reserved0(uint32_t reg) { return (reg >> 4) & 0b1; }
constexpr uint32_t reserved1() { return 0b1 << 3; }
constexpr uint32_t reserved1(uint32_t reg) { return (reg >> 3) & 0b1; }
constexpr uint32_t scroll_lock() { return 0b1 << 2; }
constexpr uint32_t scroll_lock(uint32_t reg) { return (reg >> 2) & 0b1; }
constexpr uint32_t caps_lock() { return 0b1 << 1; }
constexpr uint32_t caps_lock(uint32_t reg) { return (reg >> 1) & 0b1; }
constexpr uint32_t num_lock() { return 0b1 << 0; }
constexpr uint32_t num_lock(uint32_t reg) { return (reg >> 0) & 0b1; }
}
struct data_format {
uint8_t modifier_key;
uint8_t led_state;
uint8_t scan_code_array[6];
};
static_assert((sizeof (struct data_format)) % 4 == 0);
static_assert((sizeof (struct data_format)) == 8);
}
namespace set_condition {
struct data_format {
uint8_t led_setting;
uint8_t w1_reserved;
uint8_t w2_reserved;
uint8_t w3_reserved;
};
static_assert((sizeof (struct data_format)) % 4 == 0);
static_assert((sizeof (struct data_format)) == 4);
}
}

View File

@ -0,0 +1,151 @@
#pragma once
#include <cstdint>
namespace maple::ft6::scan_code {
constexpr uint32_t no_operation = 0x0;
constexpr uint32_t rollover_error = 0x1;
constexpr uint32_t post_fail = 0x2;
constexpr uint32_t undefined_error = 0x3;
constexpr uint32_t a_A = 0x4;
constexpr uint32_t b_B = 0x5;
constexpr uint32_t c_C = 0x6;
constexpr uint32_t d_D = 0x7;
constexpr uint32_t e_E = 0x8;
constexpr uint32_t f_F = 0x9;
constexpr uint32_t g_G = 0xa;
constexpr uint32_t h_H = 0xb;
constexpr uint32_t i_I = 0xc;
constexpr uint32_t j_J = 0xd;
constexpr uint32_t k_K = 0xe;
constexpr uint32_t l_L = 0xf;
constexpr uint32_t m_M = 0x10;
constexpr uint32_t n_N = 0x11;
constexpr uint32_t o_O = 0x12;
constexpr uint32_t p_P = 0x13;
constexpr uint32_t q_Q = 0x14;
constexpr uint32_t r_R = 0x15;
constexpr uint32_t s_S = 0x16;
constexpr uint32_t t_T = 0x17;
constexpr uint32_t u_U = 0x18;
constexpr uint32_t v_V = 0x19;
constexpr uint32_t w_W = 0x1a;
constexpr uint32_t x_X = 0x1b;
constexpr uint32_t y_Y = 0x1c;
constexpr uint32_t z_Z = 0x1d;
constexpr uint32_t _1_exclam = 0x1e;
constexpr uint32_t _2_at = 0x1f;
constexpr uint32_t _3_numbersign = 0x20;
constexpr uint32_t _4_dollar = 0x21;
constexpr uint32_t _5_percent = 0x22;
constexpr uint32_t _6_asciicircum = 0x23;
constexpr uint32_t _7_ampersand = 0x24;
constexpr uint32_t _8_asterisk = 0x25;
constexpr uint32_t _9_parenleft = 0x26;
constexpr uint32_t _0_parenright = 0x27;
constexpr uint32_t _return = 0x28;
constexpr uint32_t esc = 0x29;
constexpr uint32_t backspace = 0x2a;
constexpr uint32_t tab = 0x2b;
constexpr uint32_t spacebar = 0x2c;
constexpr uint32_t minus_underscore = 0x2d;
constexpr uint32_t equal_plus = 0x2e;
constexpr uint32_t bracketleft_braceleft = 0x2f;
constexpr uint32_t bracketright_braceright = 0x30;
constexpr uint32_t backslash_bar = 0x31;
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;
constexpr uint32_t comma_less = 0x36;
constexpr uint32_t period_greater = 0x37;
constexpr uint32_t slash_question = 0x38;
constexpr uint32_t caps_lock = 0x39;
constexpr uint32_t F1 = 0x3a;
constexpr uint32_t F2 = 0x3b;
constexpr uint32_t F3 = 0x3c;
constexpr uint32_t F4 = 0x3d;
constexpr uint32_t F5 = 0x3e;
constexpr uint32_t F6 = 0x3f;
constexpr uint32_t F7 = 0x40;
constexpr uint32_t F8 = 0x41;
constexpr uint32_t F9 = 0x42;
constexpr uint32_t F10 = 0x43;
constexpr uint32_t F11 = 0x44;
constexpr uint32_t F12 = 0x45;
constexpr uint32_t print_screen = 0x46;
constexpr uint32_t scroll_lock = 0x47;
constexpr uint32_t pause = 0x48;
constexpr uint32_t insert = 0x49;
constexpr uint32_t home = 0x4a;
constexpr uint32_t page_up = 0x4b;
constexpr uint32_t _delete = 0x4c;
constexpr uint32_t end = 0x4d;
constexpr uint32_t page_down = 0x4e;
constexpr uint32_t right_arrow = 0x4f;
constexpr uint32_t left_arrow = 0x50;
constexpr uint32_t down_arrow = 0x51;
constexpr uint32_t up_arrow = 0x52;
constexpr uint32_t last_printable = 0x38;
static 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] = { '/', '?' },
};
}

View File

@ -43,3 +43,23 @@ systembus/systembus.hpp: regs/systembus/systembus.csv regs/render_block_regs.py
systembus/systembus_bits.hpp: regs/systembus/systembus_bits.csv regs/render_bits.py systembus/systembus_bits.hpp: regs/systembus/systembus_bits.csv regs/render_bits.py
python regs/render_bits.py $< systembus > $@ python regs/render_bits.py $< systembus > $@
# MAPLE
maple/maple_bits.hpp: regs/maple/maple_bits.csv regs/render_bits.py
python regs/render_bits.py $< maple > $@
maple/maple_bus_bits.hpp: regs/maple/maple_bus_bits.csv regs/render_bits.py
python regs/render_bits.py $< maple > $@
maple/maple_bus_commands.hpp: regs/maple/maple_bus_commands.csv regs/render_maple_bus_commands.py
python regs/render_maple_bus_commands.py $< > $@
maple/maple_bus_ft0.hpp: regs/maple/maple_bus_ft0.csv regs/render_maple_data_format.py
python regs/render_maple_data_format.py $< > $@
maple/maple_bus_ft6.hpp: regs/maple/maple_bus_ft6.csv regs/render_maple_data_format.py
python regs/render_maple_data_format.py $< > $@
maple/maple_bus_ft6_scan_code.hpp: regs/maple/maple_bus_ft6_scan_code.csv regs/render_maple_scan_code.py
python regs/render_maple_scan_code.py $< > $@

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,184 @@
from dataclasses import dataclass
from typing import Union
import sys
from csv_input import read_input
from generate import renderer
@dataclass
class CommandNamespace:
name: str
issuing_right: set[str]
command_code: int
data_size: int
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 ""
if namespace.data_size == (0, None):
assert data_fields == []
yield "struct data_fields {"
yield "uint8_t _empty[0];"
yield "};"
else:
yield "struct data_fields {"
for field_name, field_size in data_fields:
const, var = field_size
if var is None:
if const in {1, 2, 4}:
bits = const * 8
yield f"uint{bits}_t {field_name};"
elif field_name == "device_id":
yield f"struct device_id {field_name};"
else:
yield f"uint8_t {field_name}[{const}];"
elif const == 0:
assert var == "n"
yield f"T {field_name};"
else:
yield f"uint8_t {field_name}[{const} + {var.upper()}];"
yield "};"
yield ""
yield "};"
if variable is not None:
assert variable == "n"
yield f"static_assert((sizeof (struct {namespace.name}<uint8_t[0]>::data_fields)) == {length});"
else:
yield f"static_assert((sizeof (struct {namespace.name}::data_fields)) == {length});"
yield ""
def parse_data_size(data_size, base, multiple) -> tuple[int, str]:
def parse_term(s):
try:
return int(s, base) * multiple
except ValueError:
div = s.split("/")
if len(div) == 1:
# this must be a variable
assert multiple == 1, s
a, = div
return a
elif len(div) == 2:
# this must be a variable divided by a number
a, b = div
b = int(b, 10)
assert b == multiple
return a
else:
assert False, div
_terms = data_size.split("+")
terms = tuple(parse_term(term) for term in _terms)
if len(terms) == 1:
term, = terms
if type(term) == str:
return (0, term)
elif type(term) == int:
return (term, None)
else:
assert False, (_terms, terms)
elif len(terms) == 2:
assert type(terms[0]) == int
assert type(terms[1]) == str
return terms
else:
assert False, (_terms, terms)
def new_aggregator():
last_name = None
namespace = None
data_fields = []
all_names = set()
def process_row(row):
nonlocal last_name
nonlocal namespace
nonlocal data_fields
if row["name"] == "":
assert all(v == "" for v in row.values()), row
return
if row["name"] != last_name:
if namespace is not None:
yield namespace, data_fields
else:
assert data_fields == []
assert row["name"] != ""
last_name = row["name"]
issuing_right = set(row["issuing_right"].split(", "))
assert all(s in {"host", "peripheral"} for s in issuing_right), row
assert issuing_right != set(), issuing_right
data_size = parse_data_size(row["data_size"], 16, 4)
namespace = CommandNamespace(
name = row["name"],
issuing_right = issuing_right,
command_code = int(row["command_code"], 16),
data_size = data_size,
)
data_fields = []
# fall through
assert last_name is None or row["name"] == last_name, (row["name"], last_name)
if row["data_field"] != "":
assert row["data_field_size"] != ""
data_fields.append((
row["data_field"],
parse_data_size(row["data_field_size"], 10, 1)
))
def terminate():
nonlocal namespace
nonlocal data_fields
if namespace is not None:
yield namespace, data_fields
def process(rows):
for row in rows:
yield from process_row(row)
yield from terminate()
return process
def headers():
yield "#pragma once"
yield ""
yield "#include <cstdint>"
yield ""
def namespace():
yield "namespace maple {"
yield ""
yield "struct device_id {"
yield "uint32_t ft;"
yield "uint32_t fd[3];"
yield "};"
yield "static_assert((sizeof (struct device_id)) == 16);"
yield ""
for namespace, data_fields in process(rows):
yield from command_namespace(namespace, data_fields)
yield ""
yield "}"
input_file = sys.argv[1]
rows = read_input(input_file)
process = new_aggregator()
render, out = renderer()
render(headers())
render(namespace())
sys.stdout.write(out.getvalue())

View File

@ -0,0 +1,163 @@
import sys
import re
from dataclasses import dataclass
from collections import defaultdict
from csv_input import read_input_headerless
from generate import renderer
@dataclass
class Bit:
name: str
length: int
position: int
@dataclass
class Field:
name: str
bits: list[str]
@dataclass
class Format:
name: str
fields: list[Field]
field_order: list[str]
size: int
def parse_bits(bits: list[str]):
bit_order = [7, 6, 5, 4, 3, 2, 1, 0]
by_name = defaultdict(list)
for bit_ix, bit in zip(bit_order, bits):
if bit == '':
continue
by_name[bit].append(bit_ix)
for name, indicies in by_name.items():
yield Bit(name=name,
length=len(indicies),
position=min(indicies),
)
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 parse_data_format(ix, rows):
if ix >= len(rows):
return None
while rows[ix][0] == "":
ix += 1
if ix >= len(rows):
return None
format_name, *header = rows[ix]
ix += 1
assert format_name != ""
assert header == ["7", "6", "5", "4", "3", "2", "1", "0"]
fields = defaultdict(list)
field_order = list()
size = 0
while ix < len(rows) and rows[ix][0] != "":
field_name, *_bits = rows[ix]
ix += 1
excess_bits = [b for b in _bits[8:] if b != ""]
assert excess_bits == []
bits = [b for b in _bits[:8]]
assert len(bits) == 8, bits
fields[field_name].append(Field(field_name,
list(parse_bits(bits))))
_, variable = parse_format_name(field_name)
if not variable:
size += 1
if field_name not in field_order:
field_order.append(field_name)
return ix, Format(format_name, dict(fields), field_order, size)
def parse(rows):
ix = 0
formats = []
while True:
ix_format = parse_data_format(ix, rows)
if ix_format is None:
break
ix, format = ix_format
formats.append(format)
assert len(formats) > 0
return formats
def render_format(format):
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):
continue
yield f"namespace {field_name} {{"
for ix, field in enumerate(subfields):
bit_offset = 8 * ix
for bit in field.bits:
name = bit.name.lower()
pos = bit_offset + bit.position
mask = bin(2 ** bit.length - 1)
yield f"constexpr uint32_t {name}() {{ return {mask} << {pos}; }}"
yield f"constexpr uint32_t {name}(uint32_t reg) {{ return (reg >> {pos}) & {mask}; }}"
yield ""
yield "}"
yield ""
yield f"struct data_format {{"
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) in {3, 6}:
yield f"uint8_t {field_name}[{len(subfields)}];"
elif len(subfields) == 16:
# bleh: hacky
yield f"uint16_t {field_name}[8];"
elif len(subfields) == 4:
yield f"uint32_t {field_name};"
else:
assert False, (len(subfields), field_name)
yield "};"
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):
yield "#pragma once"
yield ""
yield "#include <cstdint>"
yield ""
yield f"namespace maple::{name} {{"
for format in formats:
yield from render_format(format)
yield ""
yield "}"
if __name__ == "__main__":
rows = read_input_headerless(sys.argv[1])
name = sys.argv[1].split('.')[0].split('_')[-1]
assert len(name) == 3 or len(name) == 4
formats = parse(rows)
render, out = renderer()
render(render_formats(name, formats))
print(out.getvalue())

View File

@ -0,0 +1,65 @@
import sys
import string
from csv_input import read_input
from generate import renderer
def render_row(row):
usage = row['usage']
code = int(row['code'], 16)
yield f"constexpr uint32_t {usage} = {hex(code)};"
def render_rows(rows):
for row in rows:
yield from render_row(row)
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 f"constexpr uint32_t last_printable = {hex(last_printable)};"
yield ""
yield f"static 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 "};"
def render_all(rows):
yield "namespace maple::ft6::scan_code {"
yield from render_rows(rows)
yield from render_scancode_code_point(rows)
yield "}"
def header():
yield "#pragma once"
yield ""
yield "#include <cstdint>"
yield ""
if __name__ == "__main__":
rows = read_input(sys.argv[1])
render, out = renderer()
render(header())
render(render_all(rows))
print(out.getvalue())