dreamcast2: add maple headers
This commit is contained in:
parent
1f8010ef89
commit
8ef2d20749
38
dreamcast2/maple/maple.hpp
Normal file
38
dreamcast2/maple/maple.hpp
Normal 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);
|
||||||
|
}
|
90
dreamcast2/maple/maple_bits.hpp
Normal file
90
dreamcast2/maple/maple_bits.hpp
Normal 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; }
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
79
dreamcast2/maple/maple_bus_bits.hpp
Normal file
79
dreamcast2/maple/maple_bus_bits.hpp
Normal 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
260
dreamcast2/maple/maple_bus_commands.hpp
Normal file
260
dreamcast2/maple/maple_bus_commands.hpp
Normal 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);
|
||||||
|
|
||||||
|
|
||||||
|
}
|
67
dreamcast2/maple/maple_bus_ft0.hpp
Normal file
67
dreamcast2/maple/maple_bus_ft0.hpp
Normal 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
82
dreamcast2/maple/maple_bus_ft6.hpp
Normal file
82
dreamcast2/maple/maple_bus_ft6.hpp
Normal 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
151
dreamcast2/maple/maple_bus_ft6_scan_code.hpp
Normal file
151
dreamcast2/maple/maple_bus_ft6_scan_code.hpp
Normal 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] = { '/', '?' },
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
@ -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 $< > $@
|
||||||
|
BIN
dreamcast2/regs/maple/bus_bits.ods
Normal file
BIN
dreamcast2/regs/maple/bus_bits.ods
Normal file
Binary file not shown.
BIN
dreamcast2/regs/maple/maple_bits.ods
Normal file
BIN
dreamcast2/regs/maple/maple_bits.ods
Normal file
Binary file not shown.
BIN
dreamcast2/regs/maple/maple_bus_commands.ods
Normal file
BIN
dreamcast2/regs/maple/maple_bus_commands.ods
Normal file
Binary file not shown.
BIN
dreamcast2/regs/maple/maple_bus_ft0.ods
Normal file
BIN
dreamcast2/regs/maple/maple_bus_ft0.ods
Normal file
Binary file not shown.
BIN
dreamcast2/regs/maple/maple_bus_ft6.ods
Normal file
BIN
dreamcast2/regs/maple/maple_bus_ft6.ods
Normal file
Binary file not shown.
BIN
dreamcast2/regs/maple/maple_bus_ft6_scan_code.ods
Normal file
BIN
dreamcast2/regs/maple/maple_bus_ft6_scan_code.ods
Normal file
Binary file not shown.
184
dreamcast2/regs/render_maple_bus_commands.py
Normal file
184
dreamcast2/regs/render_maple_bus_commands.py
Normal 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())
|
163
dreamcast2/regs/render_maple_data_format.py
Normal file
163
dreamcast2/regs/render_maple_data_format.py
Normal 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())
|
65
dreamcast2/regs/render_maple_scan_code.py
Normal file
65
dreamcast2/regs/render_maple_scan_code.py
Normal 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())
|
Loading…
x
Reference in New Issue
Block a user