example: add gdrom_jvm_boot
This commit is contained in:
parent
63b4a9b108
commit
0c70ce02ec
7
alt.lds
7
alt.lds
@ -1,8 +1,11 @@
|
||||
OUTPUT_FORMAT("elf32-shl", "elf32-shl", "elf32-shl")
|
||||
MEMORY
|
||||
{
|
||||
p1ram : ORIGIN = 0x8c020000, LENGTH = 0xfe0000
|
||||
p2ram : ORIGIN = 0xac020000, LENGTH = 0xfe0000
|
||||
p1ram : ORIGIN = 0xac080000, LENGTH = 0xfe0000
|
||||
p2ram : ORIGIN = 0xac080000, LENGTH = 0xfe0000
|
||||
}
|
||||
__stack_reservation = 0x1000;
|
||||
|
||||
INCLUDE "common.lds"
|
||||
|
||||
__stack_end = ORIGIN(p1ram) + LENGTH(p1ram) - 0x4000;
|
||||
|
@ -437,6 +437,14 @@ GDROM_ISO9660_OBJ = \
|
||||
example/gdrom_iso9660.elf: LDSCRIPT = $(LIB)/main.lds
|
||||
example/gdrom_iso9660.elf: $(START_OBJ) $(GDROM_ISO9660_OBJ)
|
||||
|
||||
GDROM_JVM_BOOT_OBJ = \
|
||||
example/gdrom_jvm_boot.o \
|
||||
sh7091/serial.o
|
||||
|
||||
example/gdrom_jvm_boot.elf: LDSCRIPT = $(LIB)/alt.lds
|
||||
example/gdrom_jvm_boot.elf: $(START_OBJ) $(GDROM_JVM_BOOT_OBJ)
|
||||
|
||||
|
||||
AICA_OBJ = \
|
||||
example/aica.o \
|
||||
sh7091/serial.o \
|
||||
|
201
example/gdrom_jvm_boot.cpp
Normal file
201
example/gdrom_jvm_boot.cpp
Normal file
@ -0,0 +1,201 @@
|
||||
#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);
|
||||
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;
|
||||
}
|
||||
|
||||
bool dr_is_self_or_parent(const iso9660::directory_record * dr)
|
||||
{
|
||||
if (dr->length_of_file_identifier != 1)
|
||||
return false;
|
||||
uint8_t c = dr->file_identifier[0];
|
||||
return c == 0 || c == 1;
|
||||
}
|
||||
|
||||
#define FILE_FLAGS__DIRECTORY 2
|
||||
|
||||
void walk_directory_record(const iso9660::directory_record * dr)
|
||||
{
|
||||
if (dr_is_self_or_parent(dr))
|
||||
return;
|
||||
|
||||
if ((dr->file_flags & FILE_FLAGS__DIRECTORY) == 0) {
|
||||
serial::string(" [regular file] ");
|
||||
} else {
|
||||
serial::string(" [directory] ");
|
||||
}
|
||||
|
||||
serial::string(" file_identifier: ");
|
||||
serial::string(dr->file_identifier, dr->length_of_file_identifier);
|
||||
serial::character('\n');
|
||||
}
|
||||
|
||||
void walk_directory(uint16_t * buf, int extent, int num_extents)
|
||||
{
|
||||
auto buf8 = reinterpret_cast<const uint8_t *>(buf);
|
||||
|
||||
while (num_extents > 0) {
|
||||
cd_read(buf,
|
||||
extent + 150, // 150?
|
||||
1 // one sector
|
||||
);
|
||||
|
||||
int offset = 0;
|
||||
|
||||
while (true) {
|
||||
auto dr = reinterpret_cast<const iso9660::directory_record *>(&buf8[offset]);
|
||||
if (dr->length_of_directory_record == 0)
|
||||
break;
|
||||
|
||||
walk_directory_record(dr);
|
||||
|
||||
offset += dr->length_of_directory_record;
|
||||
}
|
||||
num_extents -= 1;
|
||||
extent += 1;
|
||||
}
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
//serial::init(0);
|
||||
|
||||
// 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];
|
||||
cd_read(buf,
|
||||
primary_volume_descriptor,
|
||||
1 // one sector
|
||||
);
|
||||
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');
|
||||
|
||||
const int extent = root_dr->location_of_extent.get();
|
||||
const int data_length = root_dr->data_length.get();
|
||||
const int num_extents = data_length >> 11; // division by 2048
|
||||
|
||||
walk_directory(buf, extent, num_extents);
|
||||
|
||||
while (1);
|
||||
}
|
15
ip.mk
15
ip.mk
@ -10,20 +10,27 @@ IP_OBJ = \
|
||||
sg_are02.o \
|
||||
sg_are03.o \
|
||||
sg_are04.o \
|
||||
$(START_OBJ) \
|
||||
$(START_OBJ)
|
||||
|
||||
SERIAL_LOAD_OBJ = \
|
||||
example/serial_transfer.o \
|
||||
sh7091/serial.o \
|
||||
serial_load.o \
|
||||
maple/maple.o \
|
||||
font/portfolio_6x8/portfolio_6x8.data.o \
|
||||
crc32.o
|
||||
#sg_ini.o \
|
||||
#aip.o
|
||||
|
||||
GDROM_JVM_BOOT_OBJ = \
|
||||
example/gdrom_jvm_boot.o \
|
||||
sh7091/serial.o
|
||||
|
||||
%.o: %.obj
|
||||
$(OBJCOPY) -g \
|
||||
--rename-section IP=.text.$* \
|
||||
$< $@
|
||||
|
||||
ip.elf: $(IP_OBJ)
|
||||
serial_load_ip.elf: $(IP_OBJ) $(SERIAL_LOAD_OBJ)
|
||||
$(LD) --orphan-handling=error --print-memory-usage -T $(LIB)/ip.lds $^ -o $@
|
||||
|
||||
gdrom_jvm_boot_ip.elf: $(IP_OBJ) $(GDROM_JVM_BOOT_OBJ)
|
||||
$(LD) --orphan-handling=error --print-memory-usage -T $(LIB)/ip.lds $^ -o $@
|
||||
|
17
tools/ftdi_transfer_alt.sh
Normal file
17
tools/ftdi_transfer_alt.sh
Normal file
@ -0,0 +1,17 @@
|
||||
#!/bin/sh
|
||||
|
||||
SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
|
||||
|
||||
filename="$1"
|
||||
|
||||
if [ -z "$filename" ]; then
|
||||
echo "usage: ./$0 [filename]"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
set -ex
|
||||
|
||||
${SCRIPT_DIR}/ftdi_transfer \
|
||||
write 0xac080000 "$filename" \
|
||||
jump 0xac080000 \
|
||||
console
|
Loading…
x
Reference in New Issue
Block a user