example: add gdrom_test
This successfully reads the first 17 sectors of the first data track of a CD.
This commit is contained in:
parent
c851070604
commit
e4c2a047fa
28
example/dump_ram.cpp
Normal file
28
example/dump_ram.cpp
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
#include "memorymap.hpp"
|
||||||
|
|
||||||
|
#include "sh7091/serial.hpp"
|
||||||
|
|
||||||
|
void dump_ram(const volatile uint32_t * mem, const uint32_t len)
|
||||||
|
{
|
||||||
|
uint32_t sum = 0;
|
||||||
|
for (uint32_t i = 0; i < ; i++) {
|
||||||
|
uint8_t n = mem[i];
|
||||||
|
sum += n;
|
||||||
|
serial::hexlify(n);
|
||||||
|
if ((i & 0xf) == 0xf)
|
||||||
|
serial::character('\n');
|
||||||
|
}
|
||||||
|
serial::character('\n');
|
||||||
|
serial::integer<uint32_t>(sum);
|
||||||
|
}
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
// dump the first 64k of system memory
|
||||||
|
dump_ram(system_memory, 0x10000);
|
||||||
|
|
||||||
|
|
||||||
|
while (1);
|
||||||
|
}
|
@ -326,12 +326,18 @@ DUMP_OBJECT_LIST_OBJ = \
|
|||||||
holly/region_array.o \
|
holly/region_array.o \
|
||||||
holly/background.o \
|
holly/background.o \
|
||||||
holly/ta_fifo_polygon_converter.o \
|
holly/ta_fifo_polygon_converter.o \
|
||||||
sh7091/serial.o \
|
sh7091/serial.o
|
||||||
libm.o
|
|
||||||
|
|
||||||
example/dump_object_list.elf: LDSCRIPT = $(LIB)/alt.lds
|
example/dump_object_list.elf: LDSCRIPT = $(LIB)/alt.lds
|
||||||
example/dump_object_list.elf: $(START_OBJ) $(DUMP_OBJECT_LIST_OBJ)
|
example/dump_object_list.elf: $(START_OBJ) $(DUMP_OBJECT_LIST_OBJ)
|
||||||
|
|
||||||
|
DUMP_RAM_OBJ = \
|
||||||
|
example/dump_ram.o \
|
||||||
|
sh7091/serial.o
|
||||||
|
|
||||||
|
example/dump_ram.elf: LDSCRIPT = $(LIB)/alt.lds
|
||||||
|
example/dump_ram.elf: $(START_OBJ) $(DUMP_RAM_OBJ)
|
||||||
|
|
||||||
SOFTWARE_TA_OBJ = \
|
SOFTWARE_TA_OBJ = \
|
||||||
example/software_ta.o \
|
example/software_ta.o \
|
||||||
vga.o \
|
vga.o \
|
||||||
@ -344,3 +350,10 @@ SOFTWARE_TA_OBJ = \
|
|||||||
|
|
||||||
example/software_ta.elf: LDSCRIPT = $(LIB)/alt.lds
|
example/software_ta.elf: LDSCRIPT = $(LIB)/alt.lds
|
||||||
example/software_ta.elf: $(START_OBJ) $(SOFTWARE_TA_OBJ)
|
example/software_ta.elf: $(START_OBJ) $(SOFTWARE_TA_OBJ)
|
||||||
|
|
||||||
|
GDROM_TEST_OBJ = \
|
||||||
|
example/gdrom_test.o \
|
||||||
|
sh7091/serial.o
|
||||||
|
|
||||||
|
example/gdrom_test.elf: LDSCRIPT = $(LIB)/alt.lds
|
||||||
|
example/gdrom_test.elf: $(START_OBJ) $(GDROM_TEST_OBJ)
|
||||||
|
253
example/gdrom_test.cpp
Normal file
253
example/gdrom_test.cpp
Normal file
@ -0,0 +1,253 @@
|
|||||||
|
#include "gdrom.hpp"
|
||||||
|
#include "gdrom_bits.hpp"
|
||||||
|
#include "memorymap.hpp"
|
||||||
|
|
||||||
|
#include "sh7091/serial.hpp"
|
||||||
|
|
||||||
|
union data {
|
||||||
|
uint8_t u8[2];
|
||||||
|
uint16_t u16;
|
||||||
|
};
|
||||||
|
static_assert((sizeof (data)) == 2);
|
||||||
|
|
||||||
|
|
||||||
|
void test_unit()
|
||||||
|
{
|
||||||
|
serial::string("test_unit\n");
|
||||||
|
// wait for BSY == 0 && DRQ == 0
|
||||||
|
while ((gdrom_if.status & (gdrom::status::bsy | gdrom::status::drq)) != 0) {
|
||||||
|
serial::integer<uint8_t>(gdrom_if.status);
|
||||||
|
for (int i = 0; i < 1000000; i++) { asm volatile ("nop;"); }
|
||||||
|
};
|
||||||
|
serial::string("bsy | drq == 0\n");
|
||||||
|
|
||||||
|
gdrom_if.command = 0xa0; // packet command
|
||||||
|
while ((gdrom_if.status & gdrom::status::drq) == 0);
|
||||||
|
serial::string("drq != 0; CoD: ");
|
||||||
|
serial::integer<uint8_t>(gdrom_if.interrupt_reason & 1);
|
||||||
|
|
||||||
|
serial::string("bsy1: ");
|
||||||
|
serial::integer<uint8_t>(gdrom_if.status & gdrom::status::bsy);
|
||||||
|
for (int i = 0; i < 6; i++)
|
||||||
|
gdrom_if.data = 0;
|
||||||
|
serial::integer<uint8_t>(gdrom_if.status & gdrom::status::bsy);
|
||||||
|
|
||||||
|
while ((gdrom_if.status & (gdrom::status::bsy | gdrom::status::drq)) != 0);
|
||||||
|
serial::string("bsy2: ");
|
||||||
|
serial::integer<uint8_t>(gdrom_if.status);
|
||||||
|
serial::string("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void pio_data(const uint8_t * data)
|
||||||
|
{
|
||||||
|
while ((gdrom_if.status & (gdrom::status::bsy | gdrom::status::drq)) != 0);
|
||||||
|
serial::string("bsy | drq == 0\n");
|
||||||
|
|
||||||
|
gdrom_if.features = 0; // not DMA
|
||||||
|
gdrom_if.drive_select = 0b1010'0000; // LUN 0
|
||||||
|
|
||||||
|
gdrom_if.command = 0xa0; // packet command
|
||||||
|
// CoD
|
||||||
|
//serial::string("wait CoD\n");
|
||||||
|
while ((gdrom_if.interrupt_reason & 0b11) != gdrom::interrupt_reason::cod);
|
||||||
|
//serial::string("done CoD\n");
|
||||||
|
while ((gdrom_if.status & gdrom::status::drq) == 0);
|
||||||
|
serial::string("drq == 1\n");
|
||||||
|
|
||||||
|
const uint16_t * buf = reinterpret_cast<const uint16_t *>(&data[0]);
|
||||||
|
for (int i = 0; i < 6; i++) {
|
||||||
|
gdrom_if.data = buf[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
serial::string("status1: ");
|
||||||
|
serial::integer<uint8_t>(gdrom_if.status);
|
||||||
|
while ((gdrom_if.status & gdrom::status::bsy) != 0) {
|
||||||
|
serial::integer<uint8_t>(gdrom_if.status);
|
||||||
|
for (int i = 0; i < 10000000; i++) { asm volatile ("nop;"); }
|
||||||
|
};
|
||||||
|
serial::string("status2: ");
|
||||||
|
serial::integer<uint8_t>(gdrom_if.status);
|
||||||
|
|
||||||
|
serial::string("byte_control: ");
|
||||||
|
serial::integer<uint8_t>(gdrom_if.byte_control_high, ' ');
|
||||||
|
serial::integer<uint8_t>(gdrom_if.byte_control_low);
|
||||||
|
}
|
||||||
|
|
||||||
|
void read_data(uint32_t length)
|
||||||
|
{
|
||||||
|
uint16_t read[length / 2];
|
||||||
|
for (uint32_t i = 0; i < (length / 2); i++) {
|
||||||
|
read[i] = gdrom_if.data;
|
||||||
|
}
|
||||||
|
const uint8_t * read_buf = reinterpret_cast<const uint8_t *>(&read[0]);
|
||||||
|
for (uint32_t i = 0; i < length; i++) {
|
||||||
|
serial::hexlify(read_buf[i]);
|
||||||
|
serial::character(' ');
|
||||||
|
if ((i & 0xf) == 0xf)
|
||||||
|
serial::character('\n');
|
||||||
|
}
|
||||||
|
serial::character('\n');
|
||||||
|
serial::string("status: ");
|
||||||
|
serial::integer<uint8_t>(gdrom_if.status);
|
||||||
|
}
|
||||||
|
|
||||||
|
void req_stat()
|
||||||
|
{
|
||||||
|
const uint8_t data[12] = {
|
||||||
|
0x10, // req_stat
|
||||||
|
0x00,
|
||||||
|
0x00, // starting_address
|
||||||
|
0x00,
|
||||||
|
0x0a, // allocation_length
|
||||||
|
0x00,
|
||||||
|
|
||||||
|
0x00,
|
||||||
|
0x00,
|
||||||
|
0x00,
|
||||||
|
0x00,
|
||||||
|
0x00,
|
||||||
|
0x00,
|
||||||
|
};
|
||||||
|
|
||||||
|
serial::string("\nreq_stat\n");
|
||||||
|
pio_data(data);
|
||||||
|
read_data(0xa);
|
||||||
|
}
|
||||||
|
|
||||||
|
void req_mode()
|
||||||
|
{
|
||||||
|
const uint8_t data[12] = {
|
||||||
|
0x11, // req_mode
|
||||||
|
0x00,
|
||||||
|
0x00, // starting_address
|
||||||
|
0x00,
|
||||||
|
0x20, // allocation_length
|
||||||
|
0x00,
|
||||||
|
|
||||||
|
0x00,
|
||||||
|
0x00,
|
||||||
|
0x00,
|
||||||
|
0x00,
|
||||||
|
0x00,
|
||||||
|
0x00,
|
||||||
|
};
|
||||||
|
|
||||||
|
serial::string("\nreq_mode\n");
|
||||||
|
pio_data(data);
|
||||||
|
read_data(0x20);
|
||||||
|
}
|
||||||
|
|
||||||
|
void get_toc()
|
||||||
|
{
|
||||||
|
const uint8_t data[12] = {
|
||||||
|
0x14, // GET_TOC
|
||||||
|
(0 << 0), // single density
|
||||||
|
0x0,
|
||||||
|
0xff, // allocation length msb
|
||||||
|
0xff, // allocation length lsb
|
||||||
|
0x00, // 5
|
||||||
|
0x00, // 6
|
||||||
|
0x00, // 7
|
||||||
|
0x00, // 8
|
||||||
|
0x00, // 9
|
||||||
|
0x00, // 10
|
||||||
|
0x00, // 11
|
||||||
|
};
|
||||||
|
|
||||||
|
serial::string("\nget_toc\n");
|
||||||
|
pio_data(data);
|
||||||
|
const uint32_t length = (gdrom_if.byte_control_high << 8) | (gdrom_if.byte_control_low << 0);
|
||||||
|
// 102 entries ; 4 bytes per entry, 408 bytes (0x0198)
|
||||||
|
read_data(length);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* TOC:
|
||||||
|
01 00 00 96 (track 1 information)
|
||||||
|
- audio track
|
||||||
|
- FAD track start: 0x000096
|
||||||
|
|
||||||
|
41 00 2e 4c (track 2 information)
|
||||||
|
- data track
|
||||||
|
- FAD track start: 0x002e4c
|
||||||
|
|
||||||
|
01 01 00 00 (start track information)
|
||||||
|
01: first track is audio track
|
||||||
|
01: first track is track number 1
|
||||||
|
|
||||||
|
41 02 00 00 (end track information)
|
||||||
|
41: last track is data track
|
||||||
|
02: last track is track number 2
|
||||||
|
|
||||||
|
41 00 2f 7c (lead-out information)
|
||||||
|
*/
|
||||||
|
|
||||||
|
void cd_read()
|
||||||
|
{
|
||||||
|
// CD-ROM XA mode 2 form 1
|
||||||
|
|
||||||
|
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[12] = {
|
||||||
|
0x31, // CD_READ
|
||||||
|
(data_select << 4) | (expected_data_type << 1) | (parameter_type << 0),
|
||||||
|
|
||||||
|
0x00, // starting address (msb)
|
||||||
|
0x2e, //
|
||||||
|
0x4c, // starting address (lsb)
|
||||||
|
|
||||||
|
0x00, // 5
|
||||||
|
|
||||||
|
0x00, // transfer length (msb)
|
||||||
|
0x11, // transfer length (lsb)
|
||||||
|
|
||||||
|
0x00, // next address (msb)
|
||||||
|
0x2e, // 9
|
||||||
|
0x4c, // next address (lsb)
|
||||||
|
0x00, // 11
|
||||||
|
};
|
||||||
|
|
||||||
|
serial::string("\ncd_read\n");
|
||||||
|
pio_data(data);
|
||||||
|
|
||||||
|
uint32_t read = 0;
|
||||||
|
|
||||||
|
while ((gdrom_if.status & 0x08) != 0) {
|
||||||
|
serial::string("offset: ");
|
||||||
|
serial::integer<uint32_t>(read);
|
||||||
|
|
||||||
|
const uint32_t length = (gdrom_if.byte_control_high << 8) | (gdrom_if.byte_control_low << 0);
|
||||||
|
// 102 entries ; 4 bytes per entry, 408 bytes (0x0198)
|
||||||
|
read_data(length);
|
||||||
|
read += length;
|
||||||
|
|
||||||
|
serial::string("byte_control: ");
|
||||||
|
serial::integer<uint8_t>(gdrom_if.byte_control_high, ' ');
|
||||||
|
serial::integer<uint8_t>(gdrom_if.byte_control_low);
|
||||||
|
}
|
||||||
|
serial::string("read bytes: ");
|
||||||
|
serial::integer<uint32_t>(read);
|
||||||
|
}
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
// gdrom unlock undocumented register
|
||||||
|
*((volatile unsigned long *)0xa05f74e4) = 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];
|
||||||
|
}
|
||||||
|
|
||||||
|
test_unit();
|
||||||
|
req_stat();
|
||||||
|
req_mode();
|
||||||
|
get_toc();
|
||||||
|
|
||||||
|
cd_read();
|
||||||
|
|
||||||
|
while (1);
|
||||||
|
}
|
@ -210,6 +210,7 @@ void main()
|
|||||||
qq.c = rotate(q.c, theta);
|
qq.c = rotate(q.c, theta);
|
||||||
qq.d = rotate(q.d, theta);
|
qq.d = rotate(q.d, theta);
|
||||||
|
|
||||||
|
auto mem = reinterpret_cast<volatile texture_memory_alloc *>(texture_memory32);
|
||||||
if (hardware_ta) {
|
if (hardware_ta) {
|
||||||
ta_polygon_converter_init(opb_size.total(),
|
ta_polygon_converter_init(opb_size.total(),
|
||||||
ta_alloc,
|
ta_alloc,
|
||||||
@ -219,11 +220,10 @@ void main()
|
|||||||
ta_polygon_converter_transfer(ta_parameter_buf, ta_parameter_size);
|
ta_polygon_converter_transfer(ta_parameter_buf, ta_parameter_size);
|
||||||
ta_wait_opaque_list();
|
ta_wait_opaque_list();
|
||||||
} else {
|
} else {
|
||||||
auto mem = reinterpret_cast<volatile texture_memory_alloc *>(texture_memory32);
|
software_ta::object_pointer_blocks<8>(mem->object_list, qq);
|
||||||
|
software_ta::isp_tsp_parameters(mem->isp_tsp_parameters, qq);
|
||||||
software_ta::object_pointer_blocks<8>(&mem->object_list[0], qq);
|
|
||||||
software_ta::isp_tsp_parameters(&mem->isp_tsp_parameters[0], qq);
|
|
||||||
}
|
}
|
||||||
|
software_ta::opb_checkerboard_pattern<8>(mem->object_list);
|
||||||
|
|
||||||
core_start_render(frame_ix, num_frames);
|
core_start_render(frame_ix, num_frames);
|
||||||
core_wait_end_of_render_video();
|
core_wait_end_of_render_video();
|
||||||
|
@ -116,6 +116,21 @@ void object_pointer_blocks(volatile uint32_t * mem, const quad& quad)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <int N>
|
||||||
|
void opb_checkerboard_pattern(volatile uint32_t * mem)
|
||||||
|
{
|
||||||
|
auto block = reinterpret_cast<volatile object_pointer_block<N> *>(mem);
|
||||||
|
for (uint32_t y = 0; y < tile_height; y++) {
|
||||||
|
for (uint32_t x = 0; x < tile_width; x++) {
|
||||||
|
if (((x + (y & 1)) & 1) == 0) continue;
|
||||||
|
|
||||||
|
auto& opb = block[y * tile_width + x];
|
||||||
|
opb.pointer[0] = object_list_data::pointer_type::object_pointer_block_link
|
||||||
|
| object_list_data::object_pointer_block_link::end_of_list;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
struct __untextured_quad_vertex {
|
struct __untextured_quad_vertex {
|
||||||
float x;
|
float x;
|
||||||
float y;
|
float y;
|
||||||
|
43
gdrom_bits.hpp
Normal file
43
gdrom_bits.hpp
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
namespace gdrom {
|
||||||
|
|
||||||
|
namespace status {
|
||||||
|
|
||||||
|
constexpr uint8_t bsy = (1 << 7);
|
||||||
|
constexpr uint8_t drdy = (1 << 6);
|
||||||
|
constexpr uint8_t df = (1 << 5);
|
||||||
|
constexpr uint8_t dsc = (1 << 4);
|
||||||
|
constexpr uint8_t drq = (1 << 3);
|
||||||
|
constexpr uint8_t corr = (1 << 2);
|
||||||
|
constexpr uint8_t check = (1 << 0);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace interrupt_reason {
|
||||||
|
|
||||||
|
constexpr uint8_t io = (1 << 1);
|
||||||
|
constexpr uint8_t cod = (1 << 0);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace command {
|
||||||
|
|
||||||
|
constexpr uint8_t test_unit = 0x00;
|
||||||
|
constexpr uint8_t req_stat = 0x10;
|
||||||
|
constexpr uint8_t req_mode = 0x11;
|
||||||
|
constexpr uint8_t set_mode = 0x12;
|
||||||
|
constexpr uint8_t req_error = 0x13;
|
||||||
|
constexpr uint8_t get_toc = 0x14;
|
||||||
|
constexpr uint8_t req_ses = 0x15;
|
||||||
|
constexpr uint8_t cd_open = 0x16;
|
||||||
|
constexpr uint8_t cd_play = 0x20;
|
||||||
|
constexpr uint8_t cd_seek = 0x21;
|
||||||
|
constexpr uint8_t cd_scan = 0x22;
|
||||||
|
constexpr uint8_t cd_read = 0x30;
|
||||||
|
constexpr uint8_t cd_read2 = 0x31;
|
||||||
|
constexpr uint8_t get_scd = 0x40;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -47,6 +47,15 @@ void string(const char * s)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void hexlify(const uint8_t n)
|
||||||
|
{
|
||||||
|
constexpr uint32_t length = 2;
|
||||||
|
char num_buf[length];
|
||||||
|
string::hex<char>(num_buf, length, n);
|
||||||
|
character(num_buf[0]);
|
||||||
|
character(num_buf[1]);
|
||||||
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
void integer(const T n, const char end)
|
void integer(const T n, const char end)
|
||||||
{
|
{
|
||||||
|
@ -6,6 +6,8 @@ void character(const char c);
|
|||||||
|
|
||||||
void string(const char * s);
|
void string(const char * s);
|
||||||
|
|
||||||
|
void hexlify(const uint8_t n);
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
void integer(const T n, const char end);
|
void integer(const T n, const char end);
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user