From f1a32d071904abed9467e275169d8441ff506695 Mon Sep 17 00:00:00 2001 From: Zack Buhman Date: Sat, 9 Dec 2023 01:31:34 +0800 Subject: [PATCH] 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 --- Makefile | 27 ++++++++++++++ common.mk | 33 +++-------------- main.cpp | 31 ++++++++++++++++ maple.cpp | 50 ++++++++++++++++---------- maple.h | 80 +++-------------------------------------- maple_bits.h | 78 ++++++++++++++++++++++++++++++++++++++++ regs/gen/generate.py | 2 +- regs/gen/sh7091.py | 7 ++-- regs/gen/systembus.py | 2 +- string.h | 21 +++++++++++ systembus.h | 84 +++++++++++++++++++++---------------------- 11 files changed, 242 insertions(+), 173 deletions(-) create mode 100644 maple_bits.h create mode 100644 string.h diff --git a/Makefile b/Makefile index 31ea6a8..20c0f6e 100644 --- a/Makefile +++ b/Makefile @@ -1 +1,28 @@ +all: main.elf + 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 $@ diff --git a/common.mk b/common.mk index e9fdd4c..72be8e3 100644 --- a/common.mk +++ b/common.mk @@ -7,13 +7,14 @@ AARCH = --isa=sh4 --little AFLAGS = --fatal-warnings CARCH = -m4-single-only -ml -CFLAGS += -falign-functions=4 -ffunction-sections -fdata-sections -fshort-enums -ffreestanding -nostdlib -Wno-error=narrowing -CFLAGS += -Wall -Werror -Wfatal-errors -Wno-error=unused-variable +CFLAGS += -falign-functions=4 -ffunction-sections -fdata-sections -fshort-enums -ffreestanding -nostdlib +CFLAGS += -Wall -Werror -Wfatal-errors +CFLAGS += -Wno-error=narrowing -Wno-error=unused-variable CFLAGS += -mfsca -funsafe-math-optimizations DEPFLAGS = -MMD -E # --print-gc-sections 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- CC = $(TARGET)gcc @@ -47,23 +48,6 @@ IP_OBJ = \ sg/sg_ini.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 $(BUILD_BINARY_O) @@ -87,15 +71,6 @@ all: main.cdi %.o: %.cpp %.cpp.d $(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 $(OBJCOPY) -O binary $< $@ diff --git a/main.cpp b/main.cpp index 391da41..800f457 100644 --- a/main.cpp +++ b/main.cpp @@ -9,6 +9,8 @@ #include "holly/core_bits.h" #include "holly/ta_fifo_polygon_converter.h" #include "systembus.h" +#include "maple.h" +#include "maple_bits.h" #include "holly/texture_memory_alloc.h" @@ -16,6 +18,7 @@ #include "load.h" #include "vga.h" #include "rgb.h" +#include "string.h" #include "scene.h" #include "macaw.h" @@ -64,6 +67,32 @@ uint32_t * align_32byte(uint32_t * mem) return reinterpret_cast(((reinterpret_cast(_scene) + 31) & ~31)); } +void serial_int(const uint32_t n) +{ + char num_buf[9]; + string::hex(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(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" void main() { @@ -82,6 +111,8 @@ void main() v_sync_in(); + maple_test(); + volatile uint16_t * framebuffer = reinterpret_cast(&texture_memory[0]); for (int y = 0; y < 480; y++) { for (int x = 0; x < 640; x++) { diff --git a/maple.cpp b/maple.cpp index 24c7600..a8cb9c6 100644 --- a/maple.cpp +++ b/maple.cpp @@ -1,11 +1,22 @@ +#include +#include + +#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__B (0b01 << 6) #define AP__PO__C (0b10 << 6) #define AP__PO__D (0b11 << 6) -#define AP__DE__DEVICE = (1 << 5) -#define AP__DE__EXPANSION_DEVICE = (0 << 5) -#define AP__DE__PORT = (0 << 5) +#define AP__DE__DEVICE (1 << 5) +#define AP__DE__EXPANSION_DEVICE (0 << 5) +#define AP__DE__PORT (0 << 5) #define AP__LM(reg) ((reg) & 0b11111) @@ -26,9 +37,9 @@ struct maple_host_command { 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 *>(buf); + auto command = reinterpret_cast *>(buf); command->host_instruction = HOST_INSTRUCTION__END_FLAG | 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 source_ap = AP__PO__A; uint32_t data_size = 0; - command->protocol_data[0] = (command_code << 24) - | (destination_ap << 16) - | (source_ap << 8) - | (data_size << 0); + // maple bus is big endian + command->protocol_data[0] = std::byteswap( (command_code << 24) + | (destination_ap << 16) + | (source_ap << 8) + | (data_size << 0)); } 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; // 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; // 20nsec * 0xc350 = 1ms 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; - system.MDTSEL = mdtsel::trigger_select::software_initiation; + maple_if.MDTSEL = mdtsel::trigger_select::software_initiation; /* top address: the first/lowest address bottom address: the last/highest address */ - system.MDAPRO = mdapro::security_code - | mdapro::top_address(0x00) - | mdapro::bottom_address(0x7f); + maple_if.MDAPRO = mdapro::security_code + | mdapro::top_address(0x00) + | mdapro::bottom_address(0x7f); - system.MDSTAR = mdstar::table_address(command_buf); + maple_if.MDSTAR = mdstar::table_address(reinterpret_cast(command_buf)); - system.MDEN = mden::dma_enable::enable; - system.MDST = mdst::start_status::start; + maple_if.MDEN = mden::dma_enable::enable; + maple_if.MDST = mdst::start_status::start; // wait for completion while ((system.ISTNRM & ISTNRM__END_OF_DMA_MAPLE_DMA) == 0); diff --git a/maple.h b/maple.h index 2a528cf..a0cd7d4 100644 --- a/maple.h +++ b/maple.h @@ -1,78 +1,6 @@ +#pragma once + #include -#include "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; } -} - +void maple_init_host_command(uint32_t * buf, uint32_t * receive_address); +void maple_dma_start(uint32_t * command_buf); diff --git a/maple_bits.h b/maple_bits.h new file mode 100644 index 0000000..9343e3d --- /dev/null +++ b/maple_bits.h @@ -0,0 +1,78 @@ +#include + +#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; } +} + diff --git a/regs/gen/generate.py b/regs/gen/generate.py index cf56c82..5686039 100644 --- a/regs/gen/generate.py +++ b/regs/gen/generate.py @@ -4,7 +4,7 @@ def should_autonewline(line): return ( "static_assert" 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): diff --git a/regs/gen/sh7091.py b/regs/gen/sh7091.py index d24390b..c416f61 100644 --- a/regs/gen/sh7091.py +++ b/regs/gen/sh7091.py @@ -51,8 +51,7 @@ def new_writer(): if last_block is not None: yield "};" for address, name in stack: - relative_address = address - first_address - yield f"static_assert((offsetof (struct {last_block.lower()}_reg, {name})) == {hex(relative_address)});" + yield f"static_assert((offsetof (struct {last_block.lower()}_reg, {name})) == {hex(address)});" yield "" stack = [] @@ -76,8 +75,8 @@ def new_writer(): if block != last_block: yield from terminate() - first_address = address - last_address = address + first_address = 0 # hmm... + last_address = 0 size_total = 0 reserved_num = 0 yield f"struct {block.lower()}_reg {{" diff --git a/regs/gen/systembus.py b/regs/gen/systembus.py index a1d1c6e..2487077 100644 --- a/regs/gen/systembus.py +++ b/regs/gen/systembus.py @@ -14,7 +14,7 @@ def blocks(rows): blocks.append(block) 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] rows = read_input(input_file) diff --git a/string.h b/string.h new file mode 100644 index 0000000..8365d74 --- /dev/null +++ b/string.h @@ -0,0 +1,21 @@ +#pragma once + +#include + +namespace string { + template + 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; + } + } +} diff --git a/systembus.h b/systembus.h index 4aad7ae..7f30197 100644 --- a/systembus.h +++ b/systembus.h @@ -88,81 +88,83 @@ static_assert((offsetof (struct system_reg, G2DTNRM)) == 0x150); static_assert((offsetof (struct system_reg, G2DTEXT)) == 0x154); struct maple_if_reg { + reg8 _pad0[4]; reg32 MDSTAR; /* Maple-DMA command table address */ - reg8 _pad0[8]; + reg8 _pad1[8]; reg32 MDTSEL; /* Maple-DMA trigger select */ reg32 MDEN; /* Maple-DMA enable */ reg32 MDST; /* Maple-DMA start */ - reg8 _pad1[100]; + reg8 _pad2[100]; reg32 MSYS; /* Maple system control */ reg32 MST; /* Maple status */ reg32 MSHTCL; /* Maple-DMA hard trigger clear */ reg32 MDAPRO; /* Maple-DMA address range */ - reg8 _pad2[88]; + reg8 _pad3[88]; reg32 MMSEL; /* Maple MSP selection */ - reg8 _pad3[8]; + reg8 _pad4[8]; reg32 MTXDAD; /* Maple TXD address counter */ reg32 MRXDAD; /* Maple RXD address counter */ reg32 MRXDBD; /* Maple RXD address base */ }; -static_assert((offsetof (struct maple_if_reg, MDSTAR)) == 0x0); -static_assert((offsetof (struct maple_if_reg, MDTSEL)) == 0xc); -static_assert((offsetof (struct maple_if_reg, MDEN)) == 0x10); -static_assert((offsetof (struct maple_if_reg, MDST)) == 0x14); -static_assert((offsetof (struct maple_if_reg, MSYS)) == 0x7c); -static_assert((offsetof (struct maple_if_reg, MST)) == 0x80); -static_assert((offsetof (struct maple_if_reg, MSHTCL)) == 0x84); -static_assert((offsetof (struct maple_if_reg, MDAPRO)) == 0x88); -static_assert((offsetof (struct maple_if_reg, MMSEL)) == 0xe4); -static_assert((offsetof (struct maple_if_reg, MTXDAD)) == 0xf0); -static_assert((offsetof (struct maple_if_reg, MRXDAD)) == 0xf4); -static_assert((offsetof (struct maple_if_reg, MRXDBD)) == 0xf8); +static_assert((offsetof (struct maple_if_reg, MDSTAR)) == 0x4); +static_assert((offsetof (struct maple_if_reg, MDTSEL)) == 0x10); +static_assert((offsetof (struct maple_if_reg, MDEN)) == 0x14); +static_assert((offsetof (struct maple_if_reg, MDST)) == 0x18); +static_assert((offsetof (struct maple_if_reg, MSYS)) == 0x80); +static_assert((offsetof (struct maple_if_reg, MST)) == 0x84); +static_assert((offsetof (struct maple_if_reg, MSHTCL)) == 0x88); +static_assert((offsetof (struct maple_if_reg, MDAPRO)) == 0x8c); +static_assert((offsetof (struct maple_if_reg, MMSEL)) == 0xe8); +static_assert((offsetof (struct maple_if_reg, MTXDAD)) == 0xf4); +static_assert((offsetof (struct maple_if_reg, MRXDAD)) == 0xf8); +static_assert((offsetof (struct maple_if_reg, MRXDBD)) == 0xfc); struct g1_if_reg { + reg8 _pad0[4]; reg32 GDSTAR; /* GD-DMA start address */ reg32 GDLEN; /* GD-DMA length */ reg32 GDDIR; /* GD-DMA direction */ - reg8 _pad0[4]; + reg8 _pad1[4]; reg32 GDEN; /* GD-DMA enable */ reg32 GDST; /* GD-DMA start */ - reg8 _pad1[100]; + reg8 _pad2[100]; reg32 G1RRC; /* System ROM read access timing */ reg32 G1RWC; /* System ROM write access timing */ reg32 G1FRC; /* Flash ROM read access timing */ reg32 G1FWC; /* Flash ROM write access timing */ reg32 G1CRC; /* GD PIO read access timing */ reg32 G1CWC; /* GD PIO write access timing */ - reg8 _pad2[8]; + reg8 _pad3[8]; reg32 G1GDRC; /* GD-DMA read access timing */ reg32 G1GDWC; /* GD-DMA write access timing */ - reg8 _pad3[8]; + reg8 _pad4[8]; reg32 G1SYSM; /* System mode */ reg32 G1CRDYC; /* G1IORDY signal control */ reg32 GDAPRO; /* GD-DMA address range */ - reg8 _pad4[56]; + reg8 _pad5[56]; reg32 GDSTARD; /* GD-DMA address count (on Root Bus) */ reg32 GDLEND; /* GD-DMA transfer counter */ }; -static_assert((offsetof (struct g1_if_reg, GDSTAR)) == 0x0); -static_assert((offsetof (struct g1_if_reg, GDLEN)) == 0x4); -static_assert((offsetof (struct g1_if_reg, GDDIR)) == 0x8); -static_assert((offsetof (struct g1_if_reg, GDEN)) == 0x10); -static_assert((offsetof (struct g1_if_reg, GDST)) == 0x14); -static_assert((offsetof (struct g1_if_reg, G1RRC)) == 0x7c); -static_assert((offsetof (struct g1_if_reg, G1RWC)) == 0x80); -static_assert((offsetof (struct g1_if_reg, G1FRC)) == 0x84); -static_assert((offsetof (struct g1_if_reg, G1FWC)) == 0x88); -static_assert((offsetof (struct g1_if_reg, G1CRC)) == 0x8c); -static_assert((offsetof (struct g1_if_reg, G1CWC)) == 0x90); -static_assert((offsetof (struct g1_if_reg, G1GDRC)) == 0x9c); -static_assert((offsetof (struct g1_if_reg, G1GDWC)) == 0xa0); -static_assert((offsetof (struct g1_if_reg, G1SYSM)) == 0xac); -static_assert((offsetof (struct g1_if_reg, G1CRDYC)) == 0xb0); -static_assert((offsetof (struct g1_if_reg, GDAPRO)) == 0xb4); -static_assert((offsetof (struct g1_if_reg, GDSTARD)) == 0xf0); -static_assert((offsetof (struct g1_if_reg, GDLEND)) == 0xf4); +static_assert((offsetof (struct g1_if_reg, GDSTAR)) == 0x4); +static_assert((offsetof (struct g1_if_reg, GDLEN)) == 0x8); +static_assert((offsetof (struct g1_if_reg, GDDIR)) == 0xc); +static_assert((offsetof (struct g1_if_reg, GDEN)) == 0x14); +static_assert((offsetof (struct g1_if_reg, GDST)) == 0x18); +static_assert((offsetof (struct g1_if_reg, G1RRC)) == 0x80); +static_assert((offsetof (struct g1_if_reg, G1RWC)) == 0x84); +static_assert((offsetof (struct g1_if_reg, G1FRC)) == 0x88); +static_assert((offsetof (struct g1_if_reg, G1FWC)) == 0x8c); +static_assert((offsetof (struct g1_if_reg, G1CRC)) == 0x90); +static_assert((offsetof (struct g1_if_reg, G1CWC)) == 0x94); +static_assert((offsetof (struct g1_if_reg, G1GDRC)) == 0xa0); +static_assert((offsetof (struct g1_if_reg, G1GDWC)) == 0xa4); +static_assert((offsetof (struct g1_if_reg, G1SYSM)) == 0xb0); +static_assert((offsetof (struct g1_if_reg, G1CRDYC)) == 0xb4); +static_assert((offsetof (struct g1_if_reg, GDAPRO)) == 0xb8); +static_assert((offsetof (struct g1_if_reg, GDSTARD)) == 0xf4); +static_assert((offsetof (struct g1_if_reg, GDLEND)) == 0xf8); struct g2_if_reg { 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); extern struct system_reg system __asm("system"); - extern struct maple_if_reg maple_if __asm("maple_if"); - extern struct g1_if_reg g1_if __asm("g1_if"); - extern struct g2_if_reg g2_if __asm("g2_if"); - extern struct pvr_if_reg pvr_if __asm("pvr_if");