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
This commit is contained in:
parent
c45cb293f0
commit
10d17d3c98
@ -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
|
sh7091/sh7091_bits.hpp: regs/sh7091_bits.csv regs/gen/core_bits.py
|
||||||
python 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
|
gdrom/gdrom_bits.hpp: regs/gdrom_bits.csv regs/gen/core_bits.py
|
||||||
python regs/gen/core_bits.py $< gdrom > $@
|
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
|
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 > $@
|
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:
|
clean:
|
||||||
find -P \
|
find -P \
|
||||||
-regextype posix-egrep \
|
-regextype posix-egrep \
|
||||||
|
@ -357,3 +357,10 @@ GDROM_TEST_OBJ = \
|
|||||||
|
|
||||||
example/gdrom_test.elf: LDSCRIPT = $(LIB)/alt.lds
|
example/gdrom_test.elf: LDSCRIPT = $(LIB)/alt.lds
|
||||||
example/gdrom_test.elf: $(START_OBJ) $(GDROM_TEST_OBJ)
|
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)
|
||||||
|
213
example/gdrom_iso9660.cpp
Normal file
213
example/gdrom_iso9660.cpp
Normal file
@ -0,0 +1,213 @@
|
|||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
#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<const uint16_t *>(&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<uint8_t>(gdrom::status::drq(gdrom_if.status), ' ');
|
||||||
|
serial::integer<uint8_t>(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<uint16_t>(gdrom_if.byte_count());
|
||||||
|
uint16_t buf[gdrom_if.byte_count() / 2];
|
||||||
|
read_data(buf, gdrom_if.byte_count());
|
||||||
|
|
||||||
|
serial::string("status: ");
|
||||||
|
serial::integer<uint8_t>(gdrom_if.status);
|
||||||
|
|
||||||
|
auto toc = reinterpret_cast<const struct gdrom_toc::toc *>(buf);
|
||||||
|
for (int i = 0; i < 99; i++) {
|
||||||
|
if (toc->track[i].fad() == 0xffffff)
|
||||||
|
break;
|
||||||
|
serial::string("track ");
|
||||||
|
serial::integer<uint8_t>(i);
|
||||||
|
serial::integer<uint32_t>(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<uint32_t>(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<uint8_t>(gdrom_if.status);
|
||||||
|
|
||||||
|
serial::string("read length: ");
|
||||||
|
serial::integer<uint32_t>(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<const iso9660::primary_volume_descriptor *>(&buf[0]);
|
||||||
|
auto root_dr = reinterpret_cast<const iso9660::directory_record *>(&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<uint32_t>(root_dr->location_of_extent.get());
|
||||||
|
serial::string(" data length: ");
|
||||||
|
serial::integer<uint32_t>(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<const uint8_t *>(buf);
|
||||||
|
uint32_t offset = 0;
|
||||||
|
while (true) {
|
||||||
|
serial::string("directory entry offset: ");
|
||||||
|
serial::integer<uint32_t>(offset);
|
||||||
|
|
||||||
|
auto dr = reinterpret_cast<const iso9660::directory_record *>(&buf8[offset]);
|
||||||
|
if (dr->length_of_directory_record == 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
serial::string(" length_of_directory_record: ");
|
||||||
|
serial::integer<uint8_t>(dr->length_of_directory_record);
|
||||||
|
serial::string(" length_of_file_identifier: ");
|
||||||
|
serial::integer<uint8_t>(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<uint32_t>(dr->location_of_extent.get());
|
||||||
|
serial::string(" data_length: ");
|
||||||
|
serial::integer<uint32_t>(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<const uint8_t *>(&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<uint32_t>(offset);
|
||||||
|
|
||||||
|
while (1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
for (int i = 0; i < 12; i++) {
|
||||||
|
serial::hexlify(arst[i]);
|
||||||
|
serial::character(' ');
|
||||||
|
}
|
||||||
|
serial::character('\n');
|
||||||
|
*/
|
@ -1,8 +1,9 @@
|
|||||||
#include "gdrom/gdrom.hpp"
|
#include <cstdint>
|
||||||
#include "gdrom/gdrom_bits.hpp"
|
|
||||||
#include "memorymap.hpp"
|
#include "memorymap.hpp"
|
||||||
#include "systembus.hpp"
|
#include "systembus.hpp"
|
||||||
|
#include "gdrom/gdrom.hpp"
|
||||||
|
#include "gdrom/gdrom_bits.hpp"
|
||||||
#include "sh7091/serial.hpp"
|
#include "sh7091/serial.hpp"
|
||||||
|
|
||||||
void test_unit()
|
void test_unit()
|
||||||
@ -172,7 +173,7 @@ void get_toc()
|
|||||||
41 00 2f 7c (lead-out information)
|
41 00 2f 7c (lead-out information)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void cd_read()
|
void cd_read2()
|
||||||
{
|
{
|
||||||
// CD-ROM XA mode 2 form 1
|
// CD-ROM XA mode 2 form 1
|
||||||
|
|
||||||
@ -182,7 +183,7 @@ void cd_read()
|
|||||||
|
|
||||||
|
|
||||||
const uint8_t data[12] = {
|
const uint8_t data[12] = {
|
||||||
0x31, // CD_READ
|
0x31, // CD_READ2
|
||||||
(data_select << 4) | (expected_data_type << 1) | (parameter_type << 0),
|
(data_select << 4) | (expected_data_type << 1) | (parameter_type << 0),
|
||||||
|
|
||||||
0x00, // starting address (msb)
|
0x00, // starting address (msb)
|
||||||
@ -238,7 +239,7 @@ void main()
|
|||||||
req_mode();
|
req_mode();
|
||||||
get_toc();
|
get_toc();
|
||||||
|
|
||||||
cd_read();
|
cd_read2();
|
||||||
|
|
||||||
while (1);
|
while (1);
|
||||||
}
|
}
|
||||||
|
@ -7,15 +7,15 @@ namespace gdrom_command_packet_format {
|
|||||||
template <>
|
template <>
|
||||||
constexpr void byte_order<2>(uint8_t * buf, const uint32_t n)
|
constexpr void byte_order<2>(uint8_t * buf, const uint32_t n)
|
||||||
{
|
{
|
||||||
buf[0] = n >> 8;
|
buf[0] = (n >> 8) & 0xff;
|
||||||
buf[1] = n >> 0;
|
buf[1] = (n >> 0) & 0xff;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
constexpr void byte_order<3>(uint8_t * buf, const uint32_t n)
|
constexpr void byte_order<3>(uint8_t * buf, const uint32_t n)
|
||||||
{
|
{
|
||||||
buf[0] = n >> 16;
|
buf[0] = (n >> 16) & 0xff;
|
||||||
buf[1] = n >> 8;
|
buf[1] = (n >> 8) & 0xff;
|
||||||
buf[1] = n >> 0;
|
buf[2] = (n >> 0) & 0xff;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -22,11 +22,11 @@ struct gdrom_if_reg {
|
|||||||
reg8 sector_count;
|
reg8 sector_count;
|
||||||
};
|
};
|
||||||
const reg8 _pad4[3];
|
const reg8 _pad4[3];
|
||||||
reg8 sector_number;
|
const reg8 sector_number;
|
||||||
const reg8 _pad5[3];
|
const reg8 _pad5[3];
|
||||||
reg8 byte_control_low;
|
reg8 byte_count_low;
|
||||||
const reg8 _pad6[3];
|
const reg8 _pad6[3];
|
||||||
reg8 byte_control_high;
|
reg8 byte_count_high;
|
||||||
const reg8 _pad7[3];
|
const reg8 _pad7[3];
|
||||||
reg8 drive_select;
|
reg8 drive_select;
|
||||||
const reg8 _pad8[3];
|
const reg8 _pad8[3];
|
||||||
@ -34,6 +34,11 @@ struct gdrom_if_reg {
|
|||||||
const reg8 status;
|
const reg8 status;
|
||||||
reg8 command;
|
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);
|
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, interrupt_reason)) == 136);
|
||||||
static_assert((offsetof (struct gdrom_if_reg, sector_count)) == 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, sector_number)) == 140);
|
||||||
static_assert((offsetof (struct gdrom_if_reg, byte_control_low)) == 144);
|
static_assert((offsetof (struct gdrom_if_reg, byte_count_low)) == 144);
|
||||||
static_assert((offsetof (struct gdrom_if_reg, byte_control_high)) == 148);
|
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, drive_select)) == 152);
|
||||||
static_assert((offsetof (struct gdrom_if_reg, status)) == 156);
|
static_assert((offsetof (struct gdrom_if_reg, status)) == 156);
|
||||||
static_assert((offsetof (struct gdrom_if_reg, command)) == 156);
|
static_assert((offsetof (struct gdrom_if_reg, command)) == 156);
|
||||||
|
89
gdrom/toc.hpp
Normal file
89
gdrom/toc.hpp
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
}
|
@ -1,6 +1,6 @@
|
|||||||
import sys
|
import sys
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
from os.path import splitext
|
from os import path
|
||||||
|
|
||||||
from csv_input import read_input
|
from csv_input import read_input
|
||||||
from generate import renderer
|
from generate import renderer
|
||||||
@ -89,6 +89,8 @@ def header():
|
|||||||
yield ""
|
yield ""
|
||||||
|
|
||||||
def render_fields(input_name, fields):
|
def render_fields(input_name, fields):
|
||||||
|
yield "namespace iso9660 {"
|
||||||
|
|
||||||
yield f"struct {input_name} {{"
|
yield f"struct {input_name} {{"
|
||||||
for field in fields:
|
for field in fields:
|
||||||
field_size = (field.end - field.start) + 1
|
field_size = (field.end - field.start) + 1
|
||||||
@ -108,9 +110,12 @@ def render_fields(input_name, fields):
|
|||||||
for field in fields:
|
for field in fields:
|
||||||
yield f"static_assert((offsetof (struct {input_name}, {field.name})) == {field.start - 1});"
|
yield f"static_assert((offsetof (struct {input_name}, {field.name})) == {field.start - 1});"
|
||||||
|
|
||||||
|
yield "}" # namespace
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
input_file = sys.argv[1]
|
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)
|
rows = read_input(input_file)
|
||||||
fields = list(parse(rows))
|
fields = list(parse(rows))
|
||||||
render, out = renderer()
|
render, out = renderer()
|
||||||
|
@ -5,28 +5,29 @@
|
|||||||
|
|
||||||
#include "uint_le_be.hpp"
|
#include "uint_le_be.hpp"
|
||||||
|
|
||||||
struct directory_record {
|
namespace iso9660 {
|
||||||
const uint8_t length_of_directory_record;
|
struct directory_record {
|
||||||
const uint8_t extended_attribute_record_length;
|
const uint8_t length_of_directory_record;
|
||||||
const uint32_le_be location_of_extent;
|
const uint8_t extended_attribute_record_length;
|
||||||
const uint32_le_be data_length;
|
const uint32_le_be location_of_extent;
|
||||||
const uint8_t recording_date_and_time[7];
|
const uint32_le_be data_length;
|
||||||
const uint8_t file_flags;
|
const uint8_t recording_date_and_time[7];
|
||||||
const uint8_t file_unit_size;
|
const uint8_t file_flags;
|
||||||
const uint8_t interleave_gap_size;
|
const uint8_t file_unit_size;
|
||||||
const uint16_le_be volume_sequence_number;
|
const uint8_t interleave_gap_size;
|
||||||
const uint8_t length_of_file_identifier;
|
const uint16_le_be volume_sequence_number;
|
||||||
const uint8_t file_identifier[];
|
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, length_of_directory_record)) == 0);
|
||||||
static_assert((offsetof (struct directory_record, extended_attribute_record_length)) == 1);
|
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, location_of_extent)) == 2);
|
||||||
static_assert((offsetof (struct directory_record, data_length)) == 10);
|
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, recording_date_and_time)) == 18);
|
||||||
static_assert((offsetof (struct directory_record, file_flags)) == 25);
|
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, file_unit_size)) == 26);
|
||||||
static_assert((offsetof (struct directory_record, interleave_gap_size)) == 27);
|
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, volume_sequence_number)) == 28);
|
||||||
static_assert((offsetof (struct directory_record, length_of_file_identifier)) == 32);
|
static_assert((offsetof (struct directory_record, length_of_file_identifier)) == 32);
|
||||||
static_assert((offsetof (struct directory_record, file_identifier)) == 33);
|
static_assert((offsetof (struct directory_record, file_identifier)) == 33);
|
||||||
|
}
|
||||||
|
@ -5,72 +5,73 @@
|
|||||||
|
|
||||||
#include "uint_le_be.hpp"
|
#include "uint_le_be.hpp"
|
||||||
|
|
||||||
struct primary_volume_descriptor {
|
namespace iso9660 {
|
||||||
const uint8_t volume_descriptor_type;
|
struct primary_volume_descriptor {
|
||||||
const uint8_t standard_identifier[5];
|
const uint8_t volume_descriptor_type;
|
||||||
const uint8_t volume_descriptor_version;
|
const uint8_t standard_identifier[5];
|
||||||
const uint8_t _res1;
|
const uint8_t volume_descriptor_version;
|
||||||
const uint8_t system_identifier[32];
|
const uint8_t _res1;
|
||||||
const uint8_t volume_identifier[32];
|
const uint8_t system_identifier[32];
|
||||||
const uint8_t _res2[8];
|
const uint8_t volume_identifier[32];
|
||||||
const uint32_le_be volume_space_size;
|
const uint8_t _res2[8];
|
||||||
const uint8_t _res3[32];
|
const uint32_le_be volume_space_size;
|
||||||
const uint16_le_be volume_set_size;
|
const uint8_t _res3[32];
|
||||||
const uint16_le_be volume_sequence_number;
|
const uint16_le_be volume_set_size;
|
||||||
const uint16_le_be logical_block_size;
|
const uint16_le_be volume_sequence_number;
|
||||||
const uint32_le_be path_table_size;
|
const uint16_le_be logical_block_size;
|
||||||
const uint16_le_be location_of_occurrence_of_type_l_path_table;
|
const uint32_le_be path_table_size;
|
||||||
const uint16_le_be location_of_optional_occurence_of_type_l_path_table;
|
const uint16_le_be location_of_occurrence_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_l_path_table;
|
||||||
const uint16_le_be location_of_optional_occurence_of_type_m_path_table;
|
const uint16_le_be location_of_occurence_of_type_m_path_table;
|
||||||
const uint8_t directory_record_for_root_directory[34];
|
const uint16_le_be location_of_optional_occurence_of_type_m_path_table;
|
||||||
const uint8_t volume_set_identifier[128];
|
const uint8_t directory_record_for_root_directory[34];
|
||||||
const uint8_t publisher_identifier[128];
|
const uint8_t volume_set_identifier[128];
|
||||||
const uint8_t data_preparer_identifier[128];
|
const uint8_t publisher_identifier[128];
|
||||||
const uint8_t application_identifier[128];
|
const uint8_t data_preparer_identifier[128];
|
||||||
const uint8_t copyright_file_identifier[37];
|
const uint8_t application_identifier[128];
|
||||||
const uint8_t abstract_file_identifier[37];
|
const uint8_t copyright_file_identifier[37];
|
||||||
const uint8_t bibliographic_file_identifier[37];
|
const uint8_t abstract_file_identifier[37];
|
||||||
const uint8_t volume_creation_date_and_time[17];
|
const uint8_t bibliographic_file_identifier[37];
|
||||||
const uint8_t volume_modification_date_and_time[17];
|
const uint8_t volume_creation_date_and_time[17];
|
||||||
const uint8_t volume_expiration_date_and_time[17];
|
const uint8_t volume_modification_date_and_time[17];
|
||||||
const uint8_t volume_effective_date_and_time[17];
|
const uint8_t volume_expiration_date_and_time[17];
|
||||||
const uint8_t file_structure_version;
|
const uint8_t volume_effective_date_and_time[17];
|
||||||
const uint8_t _res4;
|
const uint8_t file_structure_version;
|
||||||
const uint8_t application_use[512];
|
const uint8_t _res4;
|
||||||
const uint8_t _res5[653];
|
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, volume_descriptor_type)) == 0);
|
||||||
static_assert((offsetof (struct primary_volume_descriptor, standard_identifier)) == 1);
|
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, volume_descriptor_version)) == 6);
|
||||||
static_assert((offsetof (struct primary_volume_descriptor, _res1)) == 7);
|
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, system_identifier)) == 8);
|
||||||
static_assert((offsetof (struct primary_volume_descriptor, volume_identifier)) == 40);
|
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, _res2)) == 72);
|
||||||
static_assert((offsetof (struct primary_volume_descriptor, volume_space_size)) == 80);
|
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, _res3)) == 88);
|
||||||
static_assert((offsetof (struct primary_volume_descriptor, volume_set_size)) == 120);
|
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, volume_sequence_number)) == 124);
|
||||||
static_assert((offsetof (struct primary_volume_descriptor, logical_block_size)) == 128);
|
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, 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_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_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_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, 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, directory_record_for_root_directory)) == 156);
|
||||||
static_assert((offsetof (struct primary_volume_descriptor, volume_set_identifier)) == 190);
|
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, publisher_identifier)) == 318);
|
||||||
static_assert((offsetof (struct primary_volume_descriptor, data_preparer_identifier)) == 446);
|
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, application_identifier)) == 574);
|
||||||
static_assert((offsetof (struct primary_volume_descriptor, copyright_file_identifier)) == 702);
|
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, abstract_file_identifier)) == 739);
|
||||||
static_assert((offsetof (struct primary_volume_descriptor, bibliographic_file_identifier)) == 776);
|
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_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_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_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, volume_effective_date_and_time)) == 864);
|
||||||
static_assert((offsetof (struct primary_volume_descriptor, file_structure_version)) == 881);
|
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, _res4)) == 882);
|
||||||
static_assert((offsetof (struct primary_volume_descriptor, application_use)) == 883);
|
static_assert((offsetof (struct primary_volume_descriptor, application_use)) == 883);
|
||||||
static_assert((offsetof (struct primary_volume_descriptor, _res5)) == 1395);
|
static_assert((offsetof (struct primary_volume_descriptor, _res5)) == 1395);
|
||||||
|
}
|
||||||
|
@ -2,7 +2,6 @@
|
|||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <bit>
|
#include <bit>
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct uint_le_be {
|
struct uint_le_be {
|
||||||
|
@ -6,9 +6,9 @@
|
|||||||
"0084","1","features","W",
|
"0084","1","features","W",
|
||||||
"0088","1","interrupt_reason","R",
|
"0088","1","interrupt_reason","R",
|
||||||
"0088","1","sector_count","W",
|
"0088","1","sector_count","W",
|
||||||
"008C","1","sector_number","RW",
|
"008C","1","sector_number","R",
|
||||||
"0090","1","byte_control_low","RW",
|
"0090","1","byte_count_low","RW",
|
||||||
"0094","1","byte_control_high","RW",
|
"0094","1","byte_count_high","RW",
|
||||||
"0098","1","drive_select","RW",
|
"0098","1","drive_select","RW",
|
||||||
"009C","1","status","R",
|
"009C","1","status","R",
|
||||||
"009C","1","command","W",
|
"009C","1","command","W",
|
||||||
|
|
BIN
regs/gdrom.ods
BIN
regs/gdrom.ods
Binary file not shown.
@ -40,6 +40,12 @@ def group_by_address(rows):
|
|||||||
|
|
||||||
return list(sorted(_groups.items(), key=lambda kv: kv[0]))
|
return list(sorted(_groups.items(), key=lambda kv: kv[0]))
|
||||||
|
|
||||||
|
def byte_count():
|
||||||
|
yield "uint16_t byte_count() const"
|
||||||
|
yield "{"
|
||||||
|
yield "return (byte_count_high << 8) | (byte_count_low << 0);"
|
||||||
|
yield "}"
|
||||||
|
|
||||||
def render_groups(groups):
|
def render_groups(groups):
|
||||||
next_address = 0
|
next_address = 0
|
||||||
reserved_num = 0
|
reserved_num = 0
|
||||||
@ -67,6 +73,9 @@ def render_groups(groups):
|
|||||||
|
|
||||||
next_address = address + group[0].size
|
next_address = address + group[0].size
|
||||||
|
|
||||||
|
yield ""
|
||||||
|
yield from byte_count()
|
||||||
|
|
||||||
yield "};"
|
yield "};"
|
||||||
|
|
||||||
|
|
||||||
|
@ -47,6 +47,14 @@ void string(const char * s)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void string(const uint8_t * s, uint32_t len)
|
||||||
|
{
|
||||||
|
while (len > 0) {
|
||||||
|
character(*s++);
|
||||||
|
len--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void hexlify(const uint8_t n)
|
void hexlify(const uint8_t n)
|
||||||
{
|
{
|
||||||
constexpr uint32_t length = 2;
|
constexpr uint32_t length = 2;
|
||||||
|
@ -6,6 +6,8 @@ void character(const char c);
|
|||||||
|
|
||||||
void string(const char * s);
|
void string(const char * s);
|
||||||
|
|
||||||
|
void string(const uint8_t * s, uint32_t len);
|
||||||
|
|
||||||
void hexlify(const uint8_t n);
|
void hexlify(const uint8_t n);
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user