From 10d17d3c988efe935d9e260cddfcf29f86095b76 Mon Sep 17 00:00:00 2001 From: Zack Buhman Date: Tue, 27 Feb 2024 00:28:39 +0800 Subject: [PATCH] example: add gdrom_iso9660 This combines my iso9660 parsing code, with all of the prior gdrom packet interface / command code. The example, on real Dreamcast hardware, displays the first 2048 bytes [1] of every file in the root directory on the serial console. [1] or the size of the file, whichever is smaller --- common.mk | 6 + example/example.mk | 7 + example/gdrom_iso9660.cpp | 213 +++++++++++++++++++++ example/gdrom_test.cpp | 13 +- gdrom/command_packet_format_byte_order.hpp | 10 +- gdrom/gdrom.hpp | 15 +- gdrom/toc.hpp | 89 +++++++++ iso9660/byte_position.py | 9 +- iso9660/directory_record.hpp | 51 ++--- iso9660/primary_volume_descriptor.hpp | 139 +++++++------- iso9660/uint_le_be.hpp | 1 - regs/gdrom.csv | 6 +- regs/gdrom.ods | Bin 16136 -> 16152 bytes regs/gen/gdrom.py | 9 + sh7091/serial.cpp | 8 + sh7091/serial.hpp | 2 + 16 files changed, 462 insertions(+), 116 deletions(-) create mode 100644 example/gdrom_iso9660.cpp create mode 100644 gdrom/toc.hpp diff --git a/common.mk b/common.mk index 2aaf69b..20f52e6 100644 --- a/common.mk +++ b/common.mk @@ -160,12 +160,18 @@ sh7091/sh7091.hpp: regs/sh7091.csv regs/gen/sh7091.py sh7091/sh7091_bits.hpp: regs/sh7091_bits.csv regs/gen/core_bits.py python regs/gen/core_bits.py $< > $@ +gdrom/gdrom.hpp: regs/gdrom.csv regs/gen/gdrom.py + python regs/gen/gdrom.py $< gdrom > $@ + gdrom/gdrom_bits.hpp: regs/gdrom_bits.csv regs/gen/core_bits.py python regs/gen/core_bits.py $< gdrom > $@ gdrom/command_packet_format.hpp: regs/gdrom_command_packet_format.csv regs/gen/gdrom_command_packet_format.py regs/gen/generic_sparse_struct.py python regs/gen/gdrom_command_packet_format.py $< gdrom_command_packet_format > $@ +iso9660/%.hpp: iso9660/%.csv iso9660/byte_position.py + python iso9660/byte_position.py $< > $@ + clean: find -P \ -regextype posix-egrep \ diff --git a/example/example.mk b/example/example.mk index e77505e..847933c 100644 --- a/example/example.mk +++ b/example/example.mk @@ -357,3 +357,10 @@ GDROM_TEST_OBJ = \ example/gdrom_test.elf: LDSCRIPT = $(LIB)/alt.lds example/gdrom_test.elf: $(START_OBJ) $(GDROM_TEST_OBJ) + +GDROM_ISO9660_OBJ = \ + example/gdrom_iso9660.o \ + sh7091/serial.o + +example/gdrom_iso9660.elf: LDSCRIPT = $(LIB)/alt.lds +example/gdrom_iso9660.elf: $(START_OBJ) $(GDROM_ISO9660_OBJ) diff --git a/example/gdrom_iso9660.cpp b/example/gdrom_iso9660.cpp new file mode 100644 index 0000000..ec2264e --- /dev/null +++ b/example/gdrom_iso9660.cpp @@ -0,0 +1,213 @@ +#include + +#include "memorymap.hpp" +#include "systembus.hpp" +#include "sh7091/serial.hpp" +#include "gdrom/gdrom.hpp" +#include "gdrom/gdrom_bits.hpp" +#include "gdrom/command_packet_format.hpp" +#include "gdrom/toc.hpp" + +#include "iso9660/primary_volume_descriptor.hpp" +#include "iso9660/directory_record.hpp" + +void pio_data(const uint8_t * data) +{ + while ((gdrom::status::bsy(gdrom_if.status) | gdrom::status::drq(gdrom_if.status)) != 0); + + gdrom_if.features = gdrom::features::dma::disable; + gdrom_if.drive_select = gdrom::drive_select::drive_select + | gdrom::drive_select::lun(0); + + gdrom_if.command = gdrom::command::code::packet_command; + while (gdrom::status::drq(gdrom_if.status) == 0); + + const uint16_t * buf = reinterpret_cast(&data[0]); + for (int i = 0; i < 6; i++) { + gdrom_if.data = buf[i]; + } + + while (gdrom::status::bsy(gdrom_if.status) != 0); +} + +void read_data(uint16_t * buf, const uint32_t length) +{ + serial::string("read_data drq interrupt_reason: "); + serial::integer(gdrom::status::drq(gdrom_if.status), ' '); + serial::integer(gdrom_if.interrupt_reason); + for (uint32_t i = 0; i < (length / 2); i++) { + buf[i] = gdrom_if.data; + } +} + +uint32_t toc__get_data_track_fad() +{ + auto packet = gdrom_command_packet_format::get_toc(0, // single-density + 0x0198 // maximum toc length + ); + serial::string("get_toc\n"); + pio_data(packet._data()); + + serial::string("byte_count: "); + serial::integer(gdrom_if.byte_count()); + uint16_t buf[gdrom_if.byte_count() / 2]; + read_data(buf, gdrom_if.byte_count()); + + serial::string("status: "); + serial::integer(gdrom_if.status); + + auto toc = reinterpret_cast(buf); + for (int i = 0; i < 99; i++) { + if (toc->track[i].fad() == 0xffffff) + break; + serial::string("track "); + serial::integer(i); + serial::integer(toc->track[i].fad()); + } + + // assume track 1 is the correct track + return toc->track[1].fad(); +} + +uint32_t cd_read(uint16_t * buf, + const uint32_t starting_address, + const uint32_t transfer_length) +{ + const uint8_t data_select = 0b0010; // data + const uint8_t expected_data_type = 0b100; // XA mode 2 form 1 + const uint8_t parameter_type = 0b0; // FAD specified + const uint8_t data = (data_select << 4) | (expected_data_type << 1) | (parameter_type << 0); + + auto packet = gdrom_command_packet_format::cd_read(data, + starting_address, + transfer_length); + + auto arst = packet._data(); + serial::string("cd_read\n"); + serial::string("starting_address: "); + serial::integer(starting_address); + pio_data(packet._data()); + + uint32_t length = 0; + while ((gdrom::status::drq(gdrom_if.status)) != 0) { + const uint32_t byte_count = gdrom_if.byte_count(); + length += byte_count; + read_data(buf, byte_count); + } + serial::string("status: "); + serial::integer(gdrom_if.status); + + serial::string("read length: "); + serial::integer(length); + return length; +} + +void main() +{ + // gdrom unlock undocumented register + g1_if.GDUNLOCK = 0x1fffff; + + // Without this read from system_boot_rom, the read value of + // gdrom_if.status is always 0xff + for(uint32_t i = 0; i < 0x200000 / 4; i++) { + (void)system_boot_rom[i]; + } + + const uint32_t fad = toc__get_data_track_fad(); + serial::character('\n'); + + const uint32_t primary_volume_descriptor = fad + 16; + uint16_t buf[2048 / 2]; + const uint32_t length0 = cd_read(buf, + primary_volume_descriptor, + 1 // one sector; 2048 bytes + ); + serial::character('\n'); + + auto pvd = reinterpret_cast(&buf[0]); + auto root_dr = reinterpret_cast(&pvd->directory_record_for_root_directory[0]); + + serial::string("primary volume descriptor:\n"); + serial::string(" standard_identifier: "); + serial::string(pvd->standard_identifier, 5); + serial::character('\n'); + serial::string(" root directory record:\n"); + serial::string(" location of extent: "); + serial::integer(root_dr->location_of_extent.get()); + serial::string(" data length: "); + serial::integer(root_dr->data_length.get()); + + serial::character('\n'); + + /* + for (int i = 0; i < 2048; i++) { + serial::hexlify(buf8[i]); + serial::character(' '); + if ((i % 16) == 15) + serial::character('\n'); + } + */ + serial::character('\n'); + + const uint32_t root_directory_extent = root_dr->location_of_extent.get(); + const uint32_t length1 = cd_read(buf, + root_directory_extent + 150, // 150? + 1 // one sector; 2048 bytes + ); + serial::character('\n'); + + auto buf8 = reinterpret_cast(buf); + uint32_t offset = 0; + while (true) { + serial::string("directory entry offset: "); + serial::integer(offset); + + auto dr = reinterpret_cast(&buf8[offset]); + if (dr->length_of_directory_record == 0) + break; + + serial::string(" length_of_directory_record: "); + serial::integer(dr->length_of_directory_record); + serial::string(" length_of_file_identifier: "); + serial::integer(dr->length_of_file_identifier); + serial::string(" file_identifier: "); + serial::string(dr->file_identifier, dr->length_of_file_identifier); + serial::character('\n'); + + if (dr->file_flags == 0) { + serial::string(" location_of_extent: "); + serial::integer(dr->location_of_extent.get()); + serial::string(" data_length: "); + serial::integer(dr->data_length.get()); + + if (dr->file_identifier[0] != '1') { + const uint32_t extent = dr->location_of_extent.get(); + + uint16_t buf2[2048 / 2]; + const uint32_t length1 = cd_read(buf2, + extent + 150, // 150? + 1 // one sector; 2048 bytes + ); + + auto file = reinterpret_cast(&buf2[0]); + serial::string("---begin file content---\n"); + serial::string(file, dr->data_length.get()); + serial::string("---end file content---\n"); + } + } + + offset += dr->length_of_directory_record; + } + + serial::integer(offset); + + while (1); +} + +/* + for (int i = 0; i < 12; i++) { + serial::hexlify(arst[i]); + serial::character(' '); + } + serial::character('\n'); +*/ diff --git a/example/gdrom_test.cpp b/example/gdrom_test.cpp index c691d9a..26dc028 100644 --- a/example/gdrom_test.cpp +++ b/example/gdrom_test.cpp @@ -1,8 +1,9 @@ -#include "gdrom/gdrom.hpp" -#include "gdrom/gdrom_bits.hpp" +#include + #include "memorymap.hpp" #include "systembus.hpp" - +#include "gdrom/gdrom.hpp" +#include "gdrom/gdrom_bits.hpp" #include "sh7091/serial.hpp" void test_unit() @@ -172,7 +173,7 @@ void get_toc() 41 00 2f 7c (lead-out information) */ -void cd_read() +void cd_read2() { // CD-ROM XA mode 2 form 1 @@ -182,7 +183,7 @@ void cd_read() const uint8_t data[12] = { - 0x31, // CD_READ + 0x31, // CD_READ2 (data_select << 4) | (expected_data_type << 1) | (parameter_type << 0), 0x00, // starting address (msb) @@ -238,7 +239,7 @@ void main() req_mode(); get_toc(); - cd_read(); + cd_read2(); while (1); } diff --git a/gdrom/command_packet_format_byte_order.hpp b/gdrom/command_packet_format_byte_order.hpp index 54439ff..e57c83a 100644 --- a/gdrom/command_packet_format_byte_order.hpp +++ b/gdrom/command_packet_format_byte_order.hpp @@ -7,15 +7,15 @@ namespace gdrom_command_packet_format { template <> constexpr void byte_order<2>(uint8_t * buf, const uint32_t n) { - buf[0] = n >> 8; - buf[1] = n >> 0; + buf[0] = (n >> 8) & 0xff; + buf[1] = (n >> 0) & 0xff; } template <> constexpr void byte_order<3>(uint8_t * buf, const uint32_t n) { - buf[0] = n >> 16; - buf[1] = n >> 8; - buf[1] = n >> 0; + buf[0] = (n >> 16) & 0xff; + buf[1] = (n >> 8) & 0xff; + buf[2] = (n >> 0) & 0xff; } } diff --git a/gdrom/gdrom.hpp b/gdrom/gdrom.hpp index e2e2841..7d4292d 100644 --- a/gdrom/gdrom.hpp +++ b/gdrom/gdrom.hpp @@ -22,11 +22,11 @@ struct gdrom_if_reg { reg8 sector_count; }; const reg8 _pad4[3]; - reg8 sector_number; + const reg8 sector_number; const reg8 _pad5[3]; - reg8 byte_control_low; + reg8 byte_count_low; const reg8 _pad6[3]; - reg8 byte_control_high; + reg8 byte_count_high; const reg8 _pad7[3]; reg8 drive_select; const reg8 _pad8[3]; @@ -34,6 +34,11 @@ struct gdrom_if_reg { const reg8 status; reg8 command; }; + + uint16_t byte_count() const + { + return (byte_count_high << 8) | (byte_count_low << 0); + } }; static_assert((offsetof (struct gdrom_if_reg, alternate_status)) == 24); @@ -44,8 +49,8 @@ static_assert((offsetof (struct gdrom_if_reg, features)) == 132); static_assert((offsetof (struct gdrom_if_reg, interrupt_reason)) == 136); static_assert((offsetof (struct gdrom_if_reg, sector_count)) == 136); static_assert((offsetof (struct gdrom_if_reg, sector_number)) == 140); -static_assert((offsetof (struct gdrom_if_reg, byte_control_low)) == 144); -static_assert((offsetof (struct gdrom_if_reg, byte_control_high)) == 148); +static_assert((offsetof (struct gdrom_if_reg, byte_count_low)) == 144); +static_assert((offsetof (struct gdrom_if_reg, byte_count_high)) == 148); static_assert((offsetof (struct gdrom_if_reg, drive_select)) == 152); static_assert((offsetof (struct gdrom_if_reg, status)) == 156); static_assert((offsetof (struct gdrom_if_reg, command)) == 156); diff --git a/gdrom/toc.hpp b/gdrom/toc.hpp new file mode 100644 index 0000000..03bd346 --- /dev/null +++ b/gdrom/toc.hpp @@ -0,0 +1,89 @@ +#include + +namespace gdrom_toc { + +struct track { + const uint8_t _control_adr; + const uint8_t _fad[3]; + + uint32_t fad() const + { + return (_fad[0] << 16) | (_fad[1] << 8) | (_fad[2] << 0); + } + + uint8_t control() const + { + return (_control_adr >> 4) & 0xf; + } + + uint8_t adr() const + { + return (_control_adr >> 0) & 0xf; + } +}; +static_assert((sizeof (track)) == 4); + +struct start_track { + const uint8_t _control_adr; + const uint8_t start_track_number; + const uint8_t _zero[2]; + + uint8_t control() const + { + return (_control_adr >> 4) & 0xf; + } + + uint8_t adr() const + { + return (_control_adr >> 0) & 0xf; + } +}; +static_assert((sizeof (start_track)) == 4); + +struct end_track { + const uint8_t _control_adr; + const uint8_t end_track_number; + const uint8_t _zero[2]; + + uint8_t control() const + { + return (_control_adr >> 4) & 0xf; + } + + uint8_t adr() const + { + return (_control_adr >> 0) & 0xf; + } +}; +static_assert((sizeof (end_track)) == 4); + +struct lead_out { + const uint8_t _control_adr; + const uint8_t _fad[3]; + + uint32_t fad() const + { + return (_fad[0] << 16) | (_fad[1] << 8) | (_fad[2] << 0); + } + + uint8_t control() const + { + return (_control_adr >> 4) & 0xf; + } + + uint8_t adr() const + { + return (_control_adr >> 0) & 0xf; + } +}; +static_assert((sizeof (lead_out)) == 4); + +struct toc { + struct track track[99]; + struct start_track start_track; + struct end_track end_track; + struct lead_out lead_out; +}; +static_assert((sizeof (toc)) == 408); + +} diff --git a/iso9660/byte_position.py b/iso9660/byte_position.py index 61fef12..8e7110b 100644 --- a/iso9660/byte_position.py +++ b/iso9660/byte_position.py @@ -1,6 +1,6 @@ import sys from dataclasses import dataclass -from os.path import splitext +from os import path from csv_input import read_input from generate import renderer @@ -89,6 +89,8 @@ def header(): yield "" def render_fields(input_name, fields): + yield "namespace iso9660 {" + yield f"struct {input_name} {{" for field in fields: field_size = (field.end - field.start) + 1 @@ -108,9 +110,12 @@ def render_fields(input_name, fields): for field in fields: yield f"static_assert((offsetof (struct {input_name}, {field.name})) == {field.start - 1});" + yield "}" # namespace + if __name__ == "__main__": input_file = sys.argv[1] - input_name, _ = splitext(input_file) + input_name0, _ = path.splitext(input_file) + _, input_name = path.split(input_name0) rows = read_input(input_file) fields = list(parse(rows)) render, out = renderer() diff --git a/iso9660/directory_record.hpp b/iso9660/directory_record.hpp index 63f2c7e..5b1d5c4 100644 --- a/iso9660/directory_record.hpp +++ b/iso9660/directory_record.hpp @@ -5,28 +5,29 @@ #include "uint_le_be.hpp" -struct directory_record { - const uint8_t length_of_directory_record; - const uint8_t extended_attribute_record_length; - const uint32_le_be location_of_extent; - const uint32_le_be data_length; - const uint8_t recording_date_and_time[7]; - const uint8_t file_flags; - const uint8_t file_unit_size; - const uint8_t interleave_gap_size; - const uint16_le_be volume_sequence_number; - const uint8_t length_of_file_identifier; - const uint8_t file_identifier[]; -}; - -static_assert((offsetof (struct directory_record, length_of_directory_ecord)) == 0); -static_assert((offsetof (struct directory_record, extended_attribute_record_length)) == 1); -static_assert((offsetof (struct directory_record, location_of_extent)) == 2); -static_assert((offsetof (struct directory_record, data_length)) == 10); -static_assert((offsetof (struct directory_record, recording_date_and_time)) == 18); -static_assert((offsetof (struct directory_record, file_flags)) == 25); -static_assert((offsetof (struct directory_record, file_unit_size)) == 26); -static_assert((offsetof (struct directory_record, interleave_gap_size)) == 27); -static_assert((offsetof (struct directory_record, volume_sequence_number)) == 28); -static_assert((offsetof (struct directory_record, length_of_file_identifier)) == 32); -static_assert((offsetof (struct directory_record, file_identifier)) == 33); +namespace iso9660 { + struct directory_record { + const uint8_t length_of_directory_record; + const uint8_t extended_attribute_record_length; + const uint32_le_be location_of_extent; + const uint32_le_be data_length; + const uint8_t recording_date_and_time[7]; + const uint8_t file_flags; + const uint8_t file_unit_size; + const uint8_t interleave_gap_size; + const uint16_le_be volume_sequence_number; + const uint8_t length_of_file_identifier; + const uint8_t file_identifier[]; + }; + static_assert((offsetof (struct directory_record, length_of_directory_record)) == 0); + static_assert((offsetof (struct directory_record, extended_attribute_record_length)) == 1); + static_assert((offsetof (struct directory_record, location_of_extent)) == 2); + static_assert((offsetof (struct directory_record, data_length)) == 10); + static_assert((offsetof (struct directory_record, recording_date_and_time)) == 18); + static_assert((offsetof (struct directory_record, file_flags)) == 25); + static_assert((offsetof (struct directory_record, file_unit_size)) == 26); + static_assert((offsetof (struct directory_record, interleave_gap_size)) == 27); + static_assert((offsetof (struct directory_record, volume_sequence_number)) == 28); + static_assert((offsetof (struct directory_record, length_of_file_identifier)) == 32); + static_assert((offsetof (struct directory_record, file_identifier)) == 33); +} diff --git a/iso9660/primary_volume_descriptor.hpp b/iso9660/primary_volume_descriptor.hpp index 6aa75d6..674d7e7 100644 --- a/iso9660/primary_volume_descriptor.hpp +++ b/iso9660/primary_volume_descriptor.hpp @@ -5,72 +5,73 @@ #include "uint_le_be.hpp" -struct primary_volume_descriptor { - const uint8_t volume_descriptor_type; - const uint8_t standard_identifier[5]; - const uint8_t volume_descriptor_version; - const uint8_t _res1; - const uint8_t system_identifier[32]; - const uint8_t volume_identifier[32]; - const uint8_t _res2[8]; - const uint32_le_be volume_space_size; - const uint8_t _res3[32]; - const uint16_le_be volume_set_size; - const uint16_le_be volume_sequence_number; - const uint16_le_be logical_block_size; - const uint32_le_be path_table_size; - const uint16_le_be location_of_occurrence_of_type_l_path_table; - const uint16_le_be location_of_optional_occurence_of_type_l_path_table; - const uint16_le_be location_of_occurence_of_type_m_path_table; - const uint16_le_be location_of_optional_occurence_of_type_m_path_table; - const uint8_t directory_record_for_root_directory[34]; - const uint8_t volume_set_identifier[128]; - const uint8_t publisher_identifier[128]; - const uint8_t data_preparer_identifier[128]; - const uint8_t application_identifier[128]; - const uint8_t copyright_file_identifier[37]; - const uint8_t abstract_file_identifier[37]; - const uint8_t bibliographic_file_identifier[37]; - const uint8_t volume_creation_date_and_time[17]; - const uint8_t volume_modification_date_and_time[17]; - const uint8_t volume_expiration_date_and_time[17]; - const uint8_t volume_effective_date_and_time[17]; - const uint8_t file_structure_version; - const uint8_t _res4; - const uint8_t application_use[512]; - const uint8_t _res5[653]; -}; - -static_assert((offsetof (struct primary_volume_descriptor, volume_descriptor_type)) == 0); -static_assert((offsetof (struct primary_volume_descriptor, standard_identifier)) == 1); -static_assert((offsetof (struct primary_volume_descriptor, volume_descriptor_version)) == 6); -static_assert((offsetof (struct primary_volume_descriptor, _res1)) == 7); -static_assert((offsetof (struct primary_volume_descriptor, system_identifier)) == 8); -static_assert((offsetof (struct primary_volume_descriptor, volume_identifier)) == 40); -static_assert((offsetof (struct primary_volume_descriptor, _res2)) == 72); -static_assert((offsetof (struct primary_volume_descriptor, volume_space_size)) == 80); -static_assert((offsetof (struct primary_volume_descriptor, _res3)) == 88); -static_assert((offsetof (struct primary_volume_descriptor, volume_set_size)) == 120); -static_assert((offsetof (struct primary_volume_descriptor, volume_sequence_number)) == 124); -static_assert((offsetof (struct primary_volume_descriptor, logical_block_size)) == 128); -static_assert((offsetof (struct primary_volume_descriptor, path_table_size)) == 132); -static_assert((offsetof (struct primary_volume_descriptor, location_of_occurrence_of_type_l_path_table)) == 140); -static_assert((offsetof (struct primary_volume_descriptor, location_of_optional_occurence_of_type_l_path_table)) == 144); -static_assert((offsetof (struct primary_volume_descriptor, location_of_occurence_of_type_m_path_table)) == 148); -static_assert((offsetof (struct primary_volume_descriptor, location_of_optional_occurence_of_type_m_path_table)) == 152); -static_assert((offsetof (struct primary_volume_descriptor, directory_record_for_root_directory)) == 156); -static_assert((offsetof (struct primary_volume_descriptor, volume_set_identifier)) == 190); -static_assert((offsetof (struct primary_volume_descriptor, publisher_identifier)) == 318); -static_assert((offsetof (struct primary_volume_descriptor, data_preparer_identifier)) == 446); -static_assert((offsetof (struct primary_volume_descriptor, application_identifier)) == 574); -static_assert((offsetof (struct primary_volume_descriptor, copyright_file_identifier)) == 702); -static_assert((offsetof (struct primary_volume_descriptor, abstract_file_identifier)) == 739); -static_assert((offsetof (struct primary_volume_descriptor, bibliographic_file_identifier)) == 776); -static_assert((offsetof (struct primary_volume_descriptor, volume_creation_date_and_time)) == 813); -static_assert((offsetof (struct primary_volume_descriptor, volume_modification_date_and_time)) == 830); -static_assert((offsetof (struct primary_volume_descriptor, volume_expiration_date_and_time)) == 847); -static_assert((offsetof (struct primary_volume_descriptor, volume_effective_date_and_time)) == 864); -static_assert((offsetof (struct primary_volume_descriptor, file_structure_version)) == 881); -static_assert((offsetof (struct primary_volume_descriptor, _res4)) == 882); -static_assert((offsetof (struct primary_volume_descriptor, application_use)) == 883); -static_assert((offsetof (struct primary_volume_descriptor, _res5)) == 1395); +namespace iso9660 { + struct primary_volume_descriptor { + const uint8_t volume_descriptor_type; + const uint8_t standard_identifier[5]; + const uint8_t volume_descriptor_version; + const uint8_t _res1; + const uint8_t system_identifier[32]; + const uint8_t volume_identifier[32]; + const uint8_t _res2[8]; + const uint32_le_be volume_space_size; + const uint8_t _res3[32]; + const uint16_le_be volume_set_size; + const uint16_le_be volume_sequence_number; + const uint16_le_be logical_block_size; + const uint32_le_be path_table_size; + const uint16_le_be location_of_occurrence_of_type_l_path_table; + const uint16_le_be location_of_optional_occurence_of_type_l_path_table; + const uint16_le_be location_of_occurence_of_type_m_path_table; + const uint16_le_be location_of_optional_occurence_of_type_m_path_table; + const uint8_t directory_record_for_root_directory[34]; + const uint8_t volume_set_identifier[128]; + const uint8_t publisher_identifier[128]; + const uint8_t data_preparer_identifier[128]; + const uint8_t application_identifier[128]; + const uint8_t copyright_file_identifier[37]; + const uint8_t abstract_file_identifier[37]; + const uint8_t bibliographic_file_identifier[37]; + const uint8_t volume_creation_date_and_time[17]; + const uint8_t volume_modification_date_and_time[17]; + const uint8_t volume_expiration_date_and_time[17]; + const uint8_t volume_effective_date_and_time[17]; + const uint8_t file_structure_version; + const uint8_t _res4; + const uint8_t application_use[512]; + const uint8_t _res5[653]; + }; + static_assert((offsetof (struct primary_volume_descriptor, volume_descriptor_type)) == 0); + static_assert((offsetof (struct primary_volume_descriptor, standard_identifier)) == 1); + static_assert((offsetof (struct primary_volume_descriptor, volume_descriptor_version)) == 6); + static_assert((offsetof (struct primary_volume_descriptor, _res1)) == 7); + static_assert((offsetof (struct primary_volume_descriptor, system_identifier)) == 8); + static_assert((offsetof (struct primary_volume_descriptor, volume_identifier)) == 40); + static_assert((offsetof (struct primary_volume_descriptor, _res2)) == 72); + static_assert((offsetof (struct primary_volume_descriptor, volume_space_size)) == 80); + static_assert((offsetof (struct primary_volume_descriptor, _res3)) == 88); + static_assert((offsetof (struct primary_volume_descriptor, volume_set_size)) == 120); + static_assert((offsetof (struct primary_volume_descriptor, volume_sequence_number)) == 124); + static_assert((offsetof (struct primary_volume_descriptor, logical_block_size)) == 128); + static_assert((offsetof (struct primary_volume_descriptor, path_table_size)) == 132); + static_assert((offsetof (struct primary_volume_descriptor, location_of_occurrence_of_type_l_path_table)) == 140); + static_assert((offsetof (struct primary_volume_descriptor, location_of_optional_occurence_of_type_l_path_table)) == 144); + static_assert((offsetof (struct primary_volume_descriptor, location_of_occurence_of_type_m_path_table)) == 148); + static_assert((offsetof (struct primary_volume_descriptor, location_of_optional_occurence_of_type_m_path_table)) == 152); + static_assert((offsetof (struct primary_volume_descriptor, directory_record_for_root_directory)) == 156); + static_assert((offsetof (struct primary_volume_descriptor, volume_set_identifier)) == 190); + static_assert((offsetof (struct primary_volume_descriptor, publisher_identifier)) == 318); + static_assert((offsetof (struct primary_volume_descriptor, data_preparer_identifier)) == 446); + static_assert((offsetof (struct primary_volume_descriptor, application_identifier)) == 574); + static_assert((offsetof (struct primary_volume_descriptor, copyright_file_identifier)) == 702); + static_assert((offsetof (struct primary_volume_descriptor, abstract_file_identifier)) == 739); + static_assert((offsetof (struct primary_volume_descriptor, bibliographic_file_identifier)) == 776); + static_assert((offsetof (struct primary_volume_descriptor, volume_creation_date_and_time)) == 813); + static_assert((offsetof (struct primary_volume_descriptor, volume_modification_date_and_time)) == 830); + static_assert((offsetof (struct primary_volume_descriptor, volume_expiration_date_and_time)) == 847); + static_assert((offsetof (struct primary_volume_descriptor, volume_effective_date_and_time)) == 864); + static_assert((offsetof (struct primary_volume_descriptor, file_structure_version)) == 881); + static_assert((offsetof (struct primary_volume_descriptor, _res4)) == 882); + static_assert((offsetof (struct primary_volume_descriptor, application_use)) == 883); + static_assert((offsetof (struct primary_volume_descriptor, _res5)) == 1395); +} diff --git a/iso9660/uint_le_be.hpp b/iso9660/uint_le_be.hpp index 1e6ded3..5fcf80d 100644 --- a/iso9660/uint_le_be.hpp +++ b/iso9660/uint_le_be.hpp @@ -2,7 +2,6 @@ #include #include -#include template struct uint_le_be { diff --git a/regs/gdrom.csv b/regs/gdrom.csv index cc834f3..636fa7e 100644 --- a/regs/gdrom.csv +++ b/regs/gdrom.csv @@ -6,9 +6,9 @@ "0084","1","features","W", "0088","1","interrupt_reason","R", "0088","1","sector_count","W", -"008C","1","sector_number","RW", -"0090","1","byte_control_low","RW", -"0094","1","byte_control_high","RW", +"008C","1","sector_number","R", +"0090","1","byte_count_low","RW", +"0094","1","byte_count_high","RW", "0098","1","drive_select","RW", "009C","1","status","R", "009C","1","command","W", diff --git a/regs/gdrom.ods b/regs/gdrom.ods index 434c1e19697f7e20a0267f66a2c8ac2e171a925d..f6f6647d64a7a21aa87ae897ed0f9193c9bf5a8d 100644 GIT binary patch delta 5468 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 0) { + character(*s++); + len--; + } +} + void hexlify(const uint8_t n) { constexpr uint32_t length = 2; diff --git a/sh7091/serial.hpp b/sh7091/serial.hpp index 27a9ad8..9450830 100644 --- a/sh7091/serial.hpp +++ b/sh7091/serial.hpp @@ -6,6 +6,8 @@ void character(const char c); void string(const char * s); +void string(const uint8_t * s, uint32_t len); + void hexlify(const uint8_t n); template