maple: send a 'device request' command
On an emulator, the receive buffer is filled with the correct/expected data for 'device status'. I found this experiment useful: - it revealed a bug in my register struct generator code (the maple_if-related registers were not at the correct offsets) - it validates my understanding about endianness-swapping between the maple bus and the SH4
This commit is contained in:
parent
3f30c96dcd
commit
f1a32d0719
27
Makefile
27
Makefile
@ -1 +1,28 @@
|
|||||||
|
all: main.elf
|
||||||
|
|
||||||
include common.mk
|
include common.mk
|
||||||
|
|
||||||
|
MAIN_OBJ = \
|
||||||
|
start.o \
|
||||||
|
main.o \
|
||||||
|
load.o \
|
||||||
|
cache.o \
|
||||||
|
vga.o \
|
||||||
|
rgb.o \
|
||||||
|
holly/background.o \
|
||||||
|
holly/region_array.o \
|
||||||
|
holly/ta_fifo_polygon_converter.o \
|
||||||
|
holly/core.o \
|
||||||
|
maple.o \
|
||||||
|
scene.o \
|
||||||
|
macaw.data.o \
|
||||||
|
$(LIBGCC)
|
||||||
|
|
||||||
|
serial.elf: start.o serial_main.o load.o cache.o
|
||||||
|
$(LD) $(LDFLAGS) -T $(LIB)/alt.lds $^ -o $@
|
||||||
|
|
||||||
|
main.elf: $(MAIN_OBJ)
|
||||||
|
$(LD) $(LDFLAGS) -T $(LIB)/main.lds $^ -o $@
|
||||||
|
|
||||||
|
test.elf: $(MAIN_OBJ)
|
||||||
|
$(LD) $(LDFLAGS) -T $(LIB)/alt.lds $^ -o $@
|
||||||
|
33
common.mk
33
common.mk
@ -7,13 +7,14 @@ AARCH = --isa=sh4 --little
|
|||||||
AFLAGS = --fatal-warnings
|
AFLAGS = --fatal-warnings
|
||||||
|
|
||||||
CARCH = -m4-single-only -ml
|
CARCH = -m4-single-only -ml
|
||||||
CFLAGS += -falign-functions=4 -ffunction-sections -fdata-sections -fshort-enums -ffreestanding -nostdlib -Wno-error=narrowing
|
CFLAGS += -falign-functions=4 -ffunction-sections -fdata-sections -fshort-enums -ffreestanding -nostdlib
|
||||||
CFLAGS += -Wall -Werror -Wfatal-errors -Wno-error=unused-variable
|
CFLAGS += -Wall -Werror -Wfatal-errors
|
||||||
|
CFLAGS += -Wno-error=narrowing -Wno-error=unused-variable
|
||||||
CFLAGS += -mfsca -funsafe-math-optimizations
|
CFLAGS += -mfsca -funsafe-math-optimizations
|
||||||
DEPFLAGS = -MMD -E
|
DEPFLAGS = -MMD -E
|
||||||
# --print-gc-sections
|
# --print-gc-sections
|
||||||
LDFLAGS = --gc-sections --no-warn-rwx-segment --print-memory-usage --entry=_start --orphan-handling=error
|
LDFLAGS = --gc-sections --no-warn-rwx-segment --print-memory-usage --entry=_start --orphan-handling=error
|
||||||
CXXFLAGS = -std=c++20 -fno-exceptions -fno-non-call-exceptions -fno-rtti -fno-threadsafe-statics
|
CXXFLAGS = -std=c++23 -fno-exceptions -fno-non-call-exceptions -fno-rtti -fno-threadsafe-statics
|
||||||
|
|
||||||
TARGET = sh4-none-elf-
|
TARGET = sh4-none-elf-
|
||||||
CC = $(TARGET)gcc
|
CC = $(TARGET)gcc
|
||||||
@ -47,23 +48,6 @@ IP_OBJ = \
|
|||||||
sg/sg_ini.o \
|
sg/sg_ini.o \
|
||||||
sg/aip.o
|
sg/aip.o
|
||||||
|
|
||||||
MAIN_OBJ = \
|
|
||||||
start.o \
|
|
||||||
main.o \
|
|
||||||
load.o \
|
|
||||||
cache.o \
|
|
||||||
vga.o \
|
|
||||||
rgb.o \
|
|
||||||
holly/background.o \
|
|
||||||
holly/region_array.o \
|
|
||||||
holly/ta_fifo_polygon_converter.o \
|
|
||||||
holly/core.o \
|
|
||||||
scene.o \
|
|
||||||
macaw.data.o \
|
|
||||||
$(LIBGCC)
|
|
||||||
|
|
||||||
all: main.cdi
|
|
||||||
|
|
||||||
%.bin.o: %.bin
|
%.bin.o: %.bin
|
||||||
$(BUILD_BINARY_O)
|
$(BUILD_BINARY_O)
|
||||||
|
|
||||||
@ -87,15 +71,6 @@ all: main.cdi
|
|||||||
%.o: %.cpp %.cpp.d
|
%.o: %.cpp %.cpp.d
|
||||||
$(CXX) $(CARCH) $(CFLAGS) $(CXXFLAGS) $(OPT) $(DEBUG) -c $< -o $@
|
$(CXX) $(CARCH) $(CFLAGS) $(CXXFLAGS) $(OPT) $(DEBUG) -c $< -o $@
|
||||||
|
|
||||||
serial.elf: start.o serial_main.o load.o cache.o
|
|
||||||
$(LD) $(LDFLAGS) -T $(LIB)/alt.lds $^ -o $@
|
|
||||||
|
|
||||||
main.elf: $(MAIN_OBJ)
|
|
||||||
$(LD) $(LDFLAGS) -T $(LIB)/main.lds $^ -o $@
|
|
||||||
|
|
||||||
test.elf: $(MAIN_OBJ)
|
|
||||||
$(LD) $(LDFLAGS) -T $(LIB)/alt.lds $^ -o $@
|
|
||||||
|
|
||||||
%.bin: %.elf
|
%.bin: %.elf
|
||||||
$(OBJCOPY) -O binary $< $@
|
$(OBJCOPY) -O binary $< $@
|
||||||
|
|
||||||
|
31
main.cpp
31
main.cpp
@ -9,6 +9,8 @@
|
|||||||
#include "holly/core_bits.h"
|
#include "holly/core_bits.h"
|
||||||
#include "holly/ta_fifo_polygon_converter.h"
|
#include "holly/ta_fifo_polygon_converter.h"
|
||||||
#include "systembus.h"
|
#include "systembus.h"
|
||||||
|
#include "maple.h"
|
||||||
|
#include "maple_bits.h"
|
||||||
|
|
||||||
#include "holly/texture_memory_alloc.h"
|
#include "holly/texture_memory_alloc.h"
|
||||||
|
|
||||||
@ -16,6 +18,7 @@
|
|||||||
#include "load.h"
|
#include "load.h"
|
||||||
#include "vga.h"
|
#include "vga.h"
|
||||||
#include "rgb.h"
|
#include "rgb.h"
|
||||||
|
#include "string.h"
|
||||||
#include "scene.h"
|
#include "scene.h"
|
||||||
|
|
||||||
#include "macaw.h"
|
#include "macaw.h"
|
||||||
@ -64,6 +67,32 @@ uint32_t * align_32byte(uint32_t * mem)
|
|||||||
return reinterpret_cast<uint32_t *>(((reinterpret_cast<uint32_t>(_scene) + 31) & ~31));
|
return reinterpret_cast<uint32_t *>(((reinterpret_cast<uint32_t>(_scene) + 31) & ~31));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void serial_int(const uint32_t n)
|
||||||
|
{
|
||||||
|
char num_buf[9];
|
||||||
|
string::hex<char>(num_buf, 8, n);
|
||||||
|
num_buf[8] = 0;
|
||||||
|
serial_string("0x");
|
||||||
|
serial_string(num_buf);
|
||||||
|
serial_string("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void maple_test()
|
||||||
|
{
|
||||||
|
uint32_t _command_buf[(32 + 32) / 4];
|
||||||
|
uint32_t _receive_address[(32 + 32) / 4];
|
||||||
|
uint32_t * command_buf = align_32byte(_command_buf);
|
||||||
|
uint32_t * receive_address = align_32byte(_receive_address);
|
||||||
|
|
||||||
|
serial_int(mdstar::table_address(reinterpret_cast<uint32_t>(command_buf)));
|
||||||
|
maple_init_host_command(command_buf, receive_address);
|
||||||
|
maple_dma_start(command_buf);
|
||||||
|
|
||||||
|
for (int i = 0; i < 32; i++) {
|
||||||
|
serial_int(receive_address[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
extern "C"
|
extern "C"
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
@ -82,6 +111,8 @@ void main()
|
|||||||
|
|
||||||
v_sync_in();
|
v_sync_in();
|
||||||
|
|
||||||
|
maple_test();
|
||||||
|
|
||||||
volatile uint16_t * framebuffer = reinterpret_cast<volatile uint16_t *>(&texture_memory[0]);
|
volatile uint16_t * framebuffer = reinterpret_cast<volatile uint16_t *>(&texture_memory[0]);
|
||||||
for (int y = 0; y < 480; y++) {
|
for (int y = 0; y < 480; y++) {
|
||||||
for (int x = 0; x < 640; x++) {
|
for (int x = 0; x < 640; x++) {
|
||||||
|
42
maple.cpp
42
maple.cpp
@ -1,11 +1,22 @@
|
|||||||
|
#include <cstdint>
|
||||||
|
#include <bit>
|
||||||
|
|
||||||
|
#include "sh7091.h"
|
||||||
|
#include "sh7091_bits.h"
|
||||||
|
#include "systembus.h"
|
||||||
|
#include "systembus_bits.h"
|
||||||
|
#include "maple_bits.h"
|
||||||
|
|
||||||
|
#include "maple.h"
|
||||||
|
|
||||||
#define AP__PO__A (0b00 << 6)
|
#define AP__PO__A (0b00 << 6)
|
||||||
#define AP__PO__B (0b01 << 6)
|
#define AP__PO__B (0b01 << 6)
|
||||||
#define AP__PO__C (0b10 << 6)
|
#define AP__PO__C (0b10 << 6)
|
||||||
#define AP__PO__D (0b11 << 6)
|
#define AP__PO__D (0b11 << 6)
|
||||||
|
|
||||||
#define AP__DE__DEVICE = (1 << 5)
|
#define AP__DE__DEVICE (1 << 5)
|
||||||
#define AP__DE__EXPANSION_DEVICE = (0 << 5)
|
#define AP__DE__EXPANSION_DEVICE (0 << 5)
|
||||||
#define AP__DE__PORT = (0 << 5)
|
#define AP__DE__PORT (0 << 5)
|
||||||
|
|
||||||
#define AP__LM(reg) ((reg) & 0b11111)
|
#define AP__LM(reg) ((reg) & 0b11111)
|
||||||
|
|
||||||
@ -26,9 +37,9 @@ struct maple_host_command {
|
|||||||
uint32_t protocol_data[N];
|
uint32_t protocol_data[N];
|
||||||
};
|
};
|
||||||
|
|
||||||
void maple_host_command(uint32_t * buf, uint32_t * receive_address)
|
void maple_init_host_command(uint32_t * buf, uint32_t * receive_address)
|
||||||
{
|
{
|
||||||
auto command = reinterpet_cast<maple_host_command<1> *>(buf);
|
auto command = reinterpret_cast<maple_host_command<1> *>(buf);
|
||||||
|
|
||||||
command->host_instruction = HOST_INSTRUCTION__END_FLAG
|
command->host_instruction = HOST_INSTRUCTION__END_FLAG
|
||||||
| HOST_INSTRUCTION__PORT_SELECT__A
|
| HOST_INSTRUCTION__PORT_SELECT__A
|
||||||
@ -40,10 +51,11 @@ void maple_host_command(uint32_t * buf, uint32_t * receive_address)
|
|||||||
uint32_t destination_ap = AP__DE__DEVICE | AP__PO__A;
|
uint32_t destination_ap = AP__DE__DEVICE | AP__PO__A;
|
||||||
uint32_t source_ap = AP__PO__A;
|
uint32_t source_ap = AP__PO__A;
|
||||||
uint32_t data_size = 0;
|
uint32_t data_size = 0;
|
||||||
command->protocol_data[0] = (command_code << 24)
|
// maple bus is big endian
|
||||||
|
command->protocol_data[0] = std::byteswap( (command_code << 24)
|
||||||
| (destination_ap << 16)
|
| (destination_ap << 16)
|
||||||
| (source_ap << 8)
|
| (source_ap << 8)
|
||||||
| (data_size << 0);
|
| (data_size << 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
void maple_dma_start(uint32_t * command_buf)
|
void maple_dma_start(uint32_t * command_buf)
|
||||||
@ -56,28 +68,28 @@ void maple_dma_start(uint32_t * command_buf)
|
|||||||
system.ISTNRM = ISTNRM__END_OF_DMA_MAPLE_DMA;
|
system.ISTNRM = ISTNRM__END_OF_DMA_MAPLE_DMA;
|
||||||
|
|
||||||
// disable maple-DMA
|
// disable maple-DMA
|
||||||
system.MDEN = mden::dma_enable::abort;
|
maple_if.MDEN = mden::dma_enable::abort;
|
||||||
|
|
||||||
volatile uint32_t _dummy = system.MDST;
|
volatile uint32_t _dummy = maple_if.MDST;
|
||||||
(void)_dummy;
|
(void)_dummy;
|
||||||
|
|
||||||
// 20nsec * 0xc350 = 1ms
|
// 20nsec * 0xc350 = 1ms
|
||||||
constexpr uint32_t one_msec = 0xc350;
|
constexpr uint32_t one_msec = 0xc350;
|
||||||
system.MSYS = msys::time_out_counter(one_msec)
|
maple_if.MSYS = msys::time_out_counter(one_msec)
|
||||||
| msys::sending_rate::_2M;
|
| msys::sending_rate::_2M;
|
||||||
|
|
||||||
system.MDTSEL = mdtsel::trigger_select::software_initiation;
|
maple_if.MDTSEL = mdtsel::trigger_select::software_initiation;
|
||||||
|
|
||||||
/* top address: the first/lowest address
|
/* top address: the first/lowest address
|
||||||
bottom address: the last/highest address */
|
bottom address: the last/highest address */
|
||||||
system.MDAPRO = mdapro::security_code
|
maple_if.MDAPRO = mdapro::security_code
|
||||||
| mdapro::top_address(0x00)
|
| mdapro::top_address(0x00)
|
||||||
| mdapro::bottom_address(0x7f);
|
| mdapro::bottom_address(0x7f);
|
||||||
|
|
||||||
system.MDSTAR = mdstar::table_address(command_buf);
|
maple_if.MDSTAR = mdstar::table_address(reinterpret_cast<uint32_t>(command_buf));
|
||||||
|
|
||||||
system.MDEN = mden::dma_enable::enable;
|
maple_if.MDEN = mden::dma_enable::enable;
|
||||||
system.MDST = mdst::start_status::start;
|
maple_if.MDST = mdst::start_status::start;
|
||||||
|
|
||||||
// wait for completion
|
// wait for completion
|
||||||
while ((system.ISTNRM & ISTNRM__END_OF_DMA_MAPLE_DMA) == 0);
|
while ((system.ISTNRM & ISTNRM__END_OF_DMA_MAPLE_DMA) == 0);
|
||||||
|
80
maple.h
80
maple.h
@ -1,78 +1,6 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
|
||||||
#include "float_uint32.h"
|
void maple_init_host_command(uint32_t * buf, uint32_t * receive_address);
|
||||||
|
void maple_dma_start(uint32_t * command_buf);
|
||||||
namespace mdstar {
|
|
||||||
constexpr 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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace mden {
|
|
||||||
namespace dma_enable {
|
|
||||||
constexpr uint32_t abort = 0 << 0;
|
|
||||||
constexpr uint32_t enable = 1 << 0;
|
|
||||||
constexpr uint32_t status(uint32_t reg) { return (reg >> 0) & 0x1; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace mdst {
|
|
||||||
namespace start_status {
|
|
||||||
constexpr uint32_t status(uint32_t reg) { return (reg >> 0) & 0x1; }
|
|
||||||
constexpr uint32_t start = 1 << 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace msys {
|
|
||||||
constexpr 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 delay_time(uint32_t num) { return (num & 0xf) << 0; }
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace mst {
|
|
||||||
constexpr uint32_t move_status(uint32_t reg) { return (reg >> 31) & 0x1; }
|
|
||||||
constexpr uint32_t internal_frame_monitor(uint32_t reg) { return (reg >> 24) & 0x7; }
|
|
||||||
constexpr uint32_t internal_state_monitor(uint32_t reg) { return (reg >> 16) & 0x3f; }
|
|
||||||
constexpr 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 uint32_t top_address(uint32_t num) { return (num & 0x7f) << 8; }
|
|
||||||
constexpr 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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace mtxdad {
|
|
||||||
constexpr uint32_t txd_address_counter(uint32_t reg) { return (reg >> 0) & 0x1fffffff; }
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace mrxdad {
|
|
||||||
constexpr uint32_t rxd_address_counter(uint32_t reg) { return (reg >> 0) & 0x1fffffff; }
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace mrxdbd {
|
|
||||||
constexpr uint32_t rxd_base_address(uint32_t reg) { return (reg >> 0) & 0x1fffffff; }
|
|
||||||
}
|
|
||||||
|
|
||||||
|
78
maple_bits.h
Normal file
78
maple_bits.h
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
#include "holly/float_uint32.h"
|
||||||
|
|
||||||
|
namespace mdstar {
|
||||||
|
constexpr 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace mden {
|
||||||
|
namespace dma_enable {
|
||||||
|
constexpr uint32_t abort = 0 << 0;
|
||||||
|
constexpr uint32_t enable = 1 << 0;
|
||||||
|
constexpr uint32_t status(uint32_t reg) { return (reg >> 0) & 0x1; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace mdst {
|
||||||
|
namespace start_status {
|
||||||
|
constexpr uint32_t status(uint32_t reg) { return (reg >> 0) & 0x1; }
|
||||||
|
constexpr uint32_t start = 1 << 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace msys {
|
||||||
|
constexpr 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 delay_time(uint32_t num) { return (num & 0xf) << 0; }
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace mst {
|
||||||
|
constexpr uint32_t move_status(uint32_t reg) { return (reg >> 31) & 0x1; }
|
||||||
|
constexpr uint32_t internal_frame_monitor(uint32_t reg) { return (reg >> 24) & 0x7; }
|
||||||
|
constexpr uint32_t internal_state_monitor(uint32_t reg) { return (reg >> 16) & 0x3f; }
|
||||||
|
constexpr 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 uint32_t top_address(uint32_t num) { return (num & 0x7f) << 8; }
|
||||||
|
constexpr 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace mtxdad {
|
||||||
|
constexpr uint32_t txd_address_counter(uint32_t reg) { return (reg >> 0) & 0x1fffffff; }
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace mrxdad {
|
||||||
|
constexpr uint32_t rxd_address_counter(uint32_t reg) { return (reg >> 0) & 0x1fffffff; }
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace mrxdbd {
|
||||||
|
constexpr uint32_t rxd_base_address(uint32_t reg) { return (reg >> 0) & 0x1fffffff; }
|
||||||
|
}
|
||||||
|
|
@ -4,7 +4,7 @@ def should_autonewline(line):
|
|||||||
return (
|
return (
|
||||||
"static_assert" not in line
|
"static_assert" not in line
|
||||||
and "extern" not in line
|
and "extern" not in line
|
||||||
and line.split()[1] != '=' # hacky; meh
|
and (len(line.split()) < 2 or line.split()[1] != '=') # hacky; meh
|
||||||
)
|
)
|
||||||
|
|
||||||
def _render(out, lines):
|
def _render(out, lines):
|
||||||
|
@ -51,8 +51,7 @@ def new_writer():
|
|||||||
if last_block is not None:
|
if last_block is not None:
|
||||||
yield "};"
|
yield "};"
|
||||||
for address, name in stack:
|
for address, name in stack:
|
||||||
relative_address = address - first_address
|
yield f"static_assert((offsetof (struct {last_block.lower()}_reg, {name})) == {hex(address)});"
|
||||||
yield f"static_assert((offsetof (struct {last_block.lower()}_reg, {name})) == {hex(relative_address)});"
|
|
||||||
yield ""
|
yield ""
|
||||||
stack = []
|
stack = []
|
||||||
|
|
||||||
@ -76,8 +75,8 @@ def new_writer():
|
|||||||
|
|
||||||
if block != last_block:
|
if block != last_block:
|
||||||
yield from terminate()
|
yield from terminate()
|
||||||
first_address = address
|
first_address = 0 # hmm...
|
||||||
last_address = address
|
last_address = 0
|
||||||
size_total = 0
|
size_total = 0
|
||||||
reserved_num = 0
|
reserved_num = 0
|
||||||
yield f"struct {block.lower()}_reg {{"
|
yield f"struct {block.lower()}_reg {{"
|
||||||
|
@ -14,7 +14,7 @@ def blocks(rows):
|
|||||||
blocks.append(block)
|
blocks.append(block)
|
||||||
|
|
||||||
for block in blocks:
|
for block in blocks:
|
||||||
yield f'extern struct {block.lower()}_reg {block} __asm("{block}");'
|
yield f'extern struct {block.lower()}_reg {block.lower()} __asm("{block.lower()}");'
|
||||||
|
|
||||||
input_file = sys.argv[1]
|
input_file = sys.argv[1]
|
||||||
rows = read_input(input_file)
|
rows = read_input(input_file)
|
||||||
|
21
string.h
Normal file
21
string.h
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
namespace string {
|
||||||
|
template <typename T>
|
||||||
|
inline void hex(T * c, uint32_t len, uint32_t n)
|
||||||
|
{
|
||||||
|
while (len > 0) {
|
||||||
|
uint32_t nib = n & 0xf;
|
||||||
|
n = n >> 4;
|
||||||
|
if (nib > 9) {
|
||||||
|
nib += (97 - 10);
|
||||||
|
} else {
|
||||||
|
nib += (48 - 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
c[--len] = nib;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
84
systembus.h
84
systembus.h
@ -88,81 +88,83 @@ static_assert((offsetof (struct system_reg, G2DTNRM)) == 0x150);
|
|||||||
static_assert((offsetof (struct system_reg, G2DTEXT)) == 0x154);
|
static_assert((offsetof (struct system_reg, G2DTEXT)) == 0x154);
|
||||||
|
|
||||||
struct maple_if_reg {
|
struct maple_if_reg {
|
||||||
|
reg8 _pad0[4];
|
||||||
reg32 MDSTAR; /* Maple-DMA command table address */
|
reg32 MDSTAR; /* Maple-DMA command table address */
|
||||||
reg8 _pad0[8];
|
reg8 _pad1[8];
|
||||||
reg32 MDTSEL; /* Maple-DMA trigger select */
|
reg32 MDTSEL; /* Maple-DMA trigger select */
|
||||||
reg32 MDEN; /* Maple-DMA enable */
|
reg32 MDEN; /* Maple-DMA enable */
|
||||||
reg32 MDST; /* Maple-DMA start */
|
reg32 MDST; /* Maple-DMA start */
|
||||||
reg8 _pad1[100];
|
reg8 _pad2[100];
|
||||||
reg32 MSYS; /* Maple system control */
|
reg32 MSYS; /* Maple system control */
|
||||||
reg32 MST; /* Maple status */
|
reg32 MST; /* Maple status */
|
||||||
reg32 MSHTCL; /* Maple-DMA hard trigger clear */
|
reg32 MSHTCL; /* Maple-DMA hard trigger clear */
|
||||||
reg32 MDAPRO; /* Maple-DMA address range */
|
reg32 MDAPRO; /* Maple-DMA address range */
|
||||||
reg8 _pad2[88];
|
reg8 _pad3[88];
|
||||||
reg32 MMSEL; /* Maple MSP selection */
|
reg32 MMSEL; /* Maple MSP selection */
|
||||||
reg8 _pad3[8];
|
reg8 _pad4[8];
|
||||||
reg32 MTXDAD; /* Maple TXD address counter */
|
reg32 MTXDAD; /* Maple TXD address counter */
|
||||||
reg32 MRXDAD; /* Maple RXD address counter */
|
reg32 MRXDAD; /* Maple RXD address counter */
|
||||||
reg32 MRXDBD; /* Maple RXD address base */
|
reg32 MRXDBD; /* Maple RXD address base */
|
||||||
};
|
};
|
||||||
|
|
||||||
static_assert((offsetof (struct maple_if_reg, MDSTAR)) == 0x0);
|
static_assert((offsetof (struct maple_if_reg, MDSTAR)) == 0x4);
|
||||||
static_assert((offsetof (struct maple_if_reg, MDTSEL)) == 0xc);
|
static_assert((offsetof (struct maple_if_reg, MDTSEL)) == 0x10);
|
||||||
static_assert((offsetof (struct maple_if_reg, MDEN)) == 0x10);
|
static_assert((offsetof (struct maple_if_reg, MDEN)) == 0x14);
|
||||||
static_assert((offsetof (struct maple_if_reg, MDST)) == 0x14);
|
static_assert((offsetof (struct maple_if_reg, MDST)) == 0x18);
|
||||||
static_assert((offsetof (struct maple_if_reg, MSYS)) == 0x7c);
|
static_assert((offsetof (struct maple_if_reg, MSYS)) == 0x80);
|
||||||
static_assert((offsetof (struct maple_if_reg, MST)) == 0x80);
|
static_assert((offsetof (struct maple_if_reg, MST)) == 0x84);
|
||||||
static_assert((offsetof (struct maple_if_reg, MSHTCL)) == 0x84);
|
static_assert((offsetof (struct maple_if_reg, MSHTCL)) == 0x88);
|
||||||
static_assert((offsetof (struct maple_if_reg, MDAPRO)) == 0x88);
|
static_assert((offsetof (struct maple_if_reg, MDAPRO)) == 0x8c);
|
||||||
static_assert((offsetof (struct maple_if_reg, MMSEL)) == 0xe4);
|
static_assert((offsetof (struct maple_if_reg, MMSEL)) == 0xe8);
|
||||||
static_assert((offsetof (struct maple_if_reg, MTXDAD)) == 0xf0);
|
static_assert((offsetof (struct maple_if_reg, MTXDAD)) == 0xf4);
|
||||||
static_assert((offsetof (struct maple_if_reg, MRXDAD)) == 0xf4);
|
static_assert((offsetof (struct maple_if_reg, MRXDAD)) == 0xf8);
|
||||||
static_assert((offsetof (struct maple_if_reg, MRXDBD)) == 0xf8);
|
static_assert((offsetof (struct maple_if_reg, MRXDBD)) == 0xfc);
|
||||||
|
|
||||||
struct g1_if_reg {
|
struct g1_if_reg {
|
||||||
|
reg8 _pad0[4];
|
||||||
reg32 GDSTAR; /* GD-DMA start address */
|
reg32 GDSTAR; /* GD-DMA start address */
|
||||||
reg32 GDLEN; /* GD-DMA length */
|
reg32 GDLEN; /* GD-DMA length */
|
||||||
reg32 GDDIR; /* GD-DMA direction */
|
reg32 GDDIR; /* GD-DMA direction */
|
||||||
reg8 _pad0[4];
|
reg8 _pad1[4];
|
||||||
reg32 GDEN; /* GD-DMA enable */
|
reg32 GDEN; /* GD-DMA enable */
|
||||||
reg32 GDST; /* GD-DMA start */
|
reg32 GDST; /* GD-DMA start */
|
||||||
reg8 _pad1[100];
|
reg8 _pad2[100];
|
||||||
reg32 G1RRC; /* System ROM read access timing */
|
reg32 G1RRC; /* System ROM read access timing */
|
||||||
reg32 G1RWC; /* System ROM write access timing */
|
reg32 G1RWC; /* System ROM write access timing */
|
||||||
reg32 G1FRC; /* Flash ROM read access timing */
|
reg32 G1FRC; /* Flash ROM read access timing */
|
||||||
reg32 G1FWC; /* Flash ROM write access timing */
|
reg32 G1FWC; /* Flash ROM write access timing */
|
||||||
reg32 G1CRC; /* GD PIO read access timing */
|
reg32 G1CRC; /* GD PIO read access timing */
|
||||||
reg32 G1CWC; /* GD PIO write access timing */
|
reg32 G1CWC; /* GD PIO write access timing */
|
||||||
reg8 _pad2[8];
|
reg8 _pad3[8];
|
||||||
reg32 G1GDRC; /* GD-DMA read access timing */
|
reg32 G1GDRC; /* GD-DMA read access timing */
|
||||||
reg32 G1GDWC; /* GD-DMA write access timing */
|
reg32 G1GDWC; /* GD-DMA write access timing */
|
||||||
reg8 _pad3[8];
|
reg8 _pad4[8];
|
||||||
reg32 G1SYSM; /* System mode */
|
reg32 G1SYSM; /* System mode */
|
||||||
reg32 G1CRDYC; /* G1IORDY signal control */
|
reg32 G1CRDYC; /* G1IORDY signal control */
|
||||||
reg32 GDAPRO; /* GD-DMA address range */
|
reg32 GDAPRO; /* GD-DMA address range */
|
||||||
reg8 _pad4[56];
|
reg8 _pad5[56];
|
||||||
reg32 GDSTARD; /* GD-DMA address count (on Root Bus) */
|
reg32 GDSTARD; /* GD-DMA address count (on Root Bus) */
|
||||||
reg32 GDLEND; /* GD-DMA transfer counter */
|
reg32 GDLEND; /* GD-DMA transfer counter */
|
||||||
};
|
};
|
||||||
|
|
||||||
static_assert((offsetof (struct g1_if_reg, GDSTAR)) == 0x0);
|
static_assert((offsetof (struct g1_if_reg, GDSTAR)) == 0x4);
|
||||||
static_assert((offsetof (struct g1_if_reg, GDLEN)) == 0x4);
|
static_assert((offsetof (struct g1_if_reg, GDLEN)) == 0x8);
|
||||||
static_assert((offsetof (struct g1_if_reg, GDDIR)) == 0x8);
|
static_assert((offsetof (struct g1_if_reg, GDDIR)) == 0xc);
|
||||||
static_assert((offsetof (struct g1_if_reg, GDEN)) == 0x10);
|
static_assert((offsetof (struct g1_if_reg, GDEN)) == 0x14);
|
||||||
static_assert((offsetof (struct g1_if_reg, GDST)) == 0x14);
|
static_assert((offsetof (struct g1_if_reg, GDST)) == 0x18);
|
||||||
static_assert((offsetof (struct g1_if_reg, G1RRC)) == 0x7c);
|
static_assert((offsetof (struct g1_if_reg, G1RRC)) == 0x80);
|
||||||
static_assert((offsetof (struct g1_if_reg, G1RWC)) == 0x80);
|
static_assert((offsetof (struct g1_if_reg, G1RWC)) == 0x84);
|
||||||
static_assert((offsetof (struct g1_if_reg, G1FRC)) == 0x84);
|
static_assert((offsetof (struct g1_if_reg, G1FRC)) == 0x88);
|
||||||
static_assert((offsetof (struct g1_if_reg, G1FWC)) == 0x88);
|
static_assert((offsetof (struct g1_if_reg, G1FWC)) == 0x8c);
|
||||||
static_assert((offsetof (struct g1_if_reg, G1CRC)) == 0x8c);
|
static_assert((offsetof (struct g1_if_reg, G1CRC)) == 0x90);
|
||||||
static_assert((offsetof (struct g1_if_reg, G1CWC)) == 0x90);
|
static_assert((offsetof (struct g1_if_reg, G1CWC)) == 0x94);
|
||||||
static_assert((offsetof (struct g1_if_reg, G1GDRC)) == 0x9c);
|
static_assert((offsetof (struct g1_if_reg, G1GDRC)) == 0xa0);
|
||||||
static_assert((offsetof (struct g1_if_reg, G1GDWC)) == 0xa0);
|
static_assert((offsetof (struct g1_if_reg, G1GDWC)) == 0xa4);
|
||||||
static_assert((offsetof (struct g1_if_reg, G1SYSM)) == 0xac);
|
static_assert((offsetof (struct g1_if_reg, G1SYSM)) == 0xb0);
|
||||||
static_assert((offsetof (struct g1_if_reg, G1CRDYC)) == 0xb0);
|
static_assert((offsetof (struct g1_if_reg, G1CRDYC)) == 0xb4);
|
||||||
static_assert((offsetof (struct g1_if_reg, GDAPRO)) == 0xb4);
|
static_assert((offsetof (struct g1_if_reg, GDAPRO)) == 0xb8);
|
||||||
static_assert((offsetof (struct g1_if_reg, GDSTARD)) == 0xf0);
|
static_assert((offsetof (struct g1_if_reg, GDSTARD)) == 0xf4);
|
||||||
static_assert((offsetof (struct g1_if_reg, GDLEND)) == 0xf4);
|
static_assert((offsetof (struct g1_if_reg, GDLEND)) == 0xf8);
|
||||||
|
|
||||||
struct g2_if_reg {
|
struct g2_if_reg {
|
||||||
reg32 ADSTAG; /* ACIA:G2-DMA G2 start address */
|
reg32 ADSTAG; /* ACIA:G2-DMA G2 start address */
|
||||||
@ -302,11 +304,7 @@ static_assert((offsetof (struct pvr_if_reg, PDSTARD)) == 0xf4);
|
|||||||
static_assert((offsetof (struct pvr_if_reg, PDLEND)) == 0xf8);
|
static_assert((offsetof (struct pvr_if_reg, PDLEND)) == 0xf8);
|
||||||
|
|
||||||
extern struct system_reg system __asm("system");
|
extern struct system_reg system __asm("system");
|
||||||
|
|
||||||
extern struct maple_if_reg maple_if __asm("maple_if");
|
extern struct maple_if_reg maple_if __asm("maple_if");
|
||||||
|
|
||||||
extern struct g1_if_reg g1_if __asm("g1_if");
|
extern struct g1_if_reg g1_if __asm("g1_if");
|
||||||
|
|
||||||
extern struct g2_if_reg g2_if __asm("g2_if");
|
extern struct g2_if_reg g2_if __asm("g2_if");
|
||||||
|
|
||||||
extern struct pvr_if_reg pvr_if __asm("pvr_if");
|
extern struct pvr_if_reg pvr_if __asm("pvr_if");
|
||||||
|
Loading…
x
Reference in New Issue
Block a user