diff --git a/common.mk b/common.mk index 03ad6bd..13ac848 100644 --- a/common.mk +++ b/common.mk @@ -60,7 +60,8 @@ sine.pcm: common.mk /=./pcm/PRELUDE.PCM \ /=./pcm/CLOCKTOW.PCM \ /=./pcm/ELEC.PCM \ - /=./pcm/ECCLESIA.PCM + /=./pcm/ECCLESIA.PCM \ + /=jvm.bin clean: find -P \ diff --git a/crc_main.c b/crc_main.c new file mode 100644 index 0000000..5313273 --- /dev/null +++ b/crc_main.c @@ -0,0 +1,73 @@ +#include +#include +#include +#include +#include +#include + +#include "crc32.c" + +int read_file(const char * filename, uint8_t ** buf, uint32_t * size_out) +{ + FILE * file = fopen(filename, "rb"); + if (file == NULL) { + fprintf(stderr, "fopen(\"%s\", \"rb\"): %s\n", filename, strerror(errno)); + return -1; + } + + int ret; + ret = fseek(file, 0L, SEEK_END); + if (ret < 0) { + fprintf(stderr, "fseek(SEEK_END)"); + return -1; + } + + long offset = ftell(file); + if (offset < 0) { + fprintf(stderr, "ftell"); + return -1; + } + size_t size = offset; + + ret = fseek(file, 0L, SEEK_SET); + if (ret < 0) { + fprintf(stderr, "fseek(SEEK_SET)"); + return -1; + } + + fprintf(stderr, "read_file: %s size %ld\n", filename, size); + *buf = (uint8_t *)malloc(size); + size_t fread_size = fread(*buf, 1, size, file); + if (fread_size != size) { + fprintf(stderr, "fread `%s` short read: %" PRIu64 " ; expected: %" PRIu64 "\n", filename, fread_size, size); + return -1; + } + + ret = fclose(file); + if (ret < 0) { + fprintf(stderr, "fclose"); + return -1; + } + + *size_out = size; + + return 0; +} + +int main(int argc, char * argv[]) +{ + assert(argc == 2); + + uint8_t * buf; + uint32_t size; + int ret = read_file(argv[1], &buf, &size); + assert(ret == 0); + + printf("size: %08x\n", size); + int chunks = size / 2048; + printf("crc:\n"); + for (int i = 0; i < chunks; i++) { + uint32_t crc = crc32(&buf[i * 2048], 2048); + printf("0x%08x\n", crc); + } +} diff --git a/example/gdrom_jvm_boot.cpp b/example/gdrom_jvm_boot.cpp index ac335b6..aa5763a 100644 --- a/example/gdrom_jvm_boot.cpp +++ b/example/gdrom_jvm_boot.cpp @@ -7,10 +7,15 @@ #include "gdrom/gdrom_bits.hpp" #include "gdrom/command_packet_format.hpp" #include "gdrom/toc.hpp" +#include "holly/video_output.hpp" #include "iso9660/primary_volume_descriptor.hpp" #include "iso9660/directory_record.hpp" +#include "crc32.h" + +typedef void (*main_ptr_t)(void); + void pio_data(const uint8_t * data) { while ((gdrom::status::bsy(gdrom_if.status) | gdrom::status::drq(gdrom_if.status)) != 0); @@ -32,9 +37,9 @@ void pio_data(const uint8_t * data) 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); + //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; } @@ -110,6 +115,72 @@ bool dr_is_self_or_parent(const iso9660::directory_record * dr) #define FILE_FLAGS__DIRECTORY 2 +bool is_jvm_bin(const uint8_t * file_identifier, int length_of_file_identifier) +{ + static const uint8_t * jvm_bin = (const uint8_t *)"JVM.BIN;1"; + int jvm_bin_length = 9; + if (length_of_file_identifier != jvm_bin_length) + return false; + + for (int i = 0; i < jvm_bin_length; i++) { + if (file_identifier[i] != jvm_bin[i]) + return false; + } + return true; +} + +static inline int min(int a, int b) +{ + return a < b ? a : b; +} + +static bool jvm_load_complete; +static int __data_length; +constexpr int load_address = 0xac010000; + +void load_jvm_bin(const iso9660::directory_record * dr) +{ + serial::string("load jvm bin:\n"); + //__attribute__((aligned(4))) static uint16_t file_buf16[16384 / 2]; + //uint32_t * file_buf32 = reinterpret_cast(file_buf16); + uint16_t * load_buf = reinterpret_cast(load_address); + int offset = 0; + + int extent = dr->location_of_extent.get(); + int data_length = dr->data_length.get(); + serial::integer(extent); + + int transfers = 0; + while (data_length > 0) { + int transfer_size = min(data_length, 2048); + int sectors = transfer_size >> 11; // divide by 2048 + if (sectors == 0) + sectors = 1; + + cd_read(&load_buf[offset], + extent + 150, // 150? + sectors // one sector + ); + + offset += transfer_size / (sizeof (load_buf[0])); + + extent += sectors; + data_length -= sectors * 2048; + transfers += 1; + } + + serial::string("\njvm load complete\n"); + jvm_load_complete = true; + serial::integer(extent); + + serial::string("size: "); + serial::integer(dr->data_length.get()); + __data_length = dr->data_length.get(); + + serial::string("transfers: "); + serial::integer(transfers); +} + void walk_directory_record(const iso9660::directory_record * dr) { if (dr_is_self_or_parent(dr)) @@ -124,6 +195,12 @@ void walk_directory_record(const iso9660::directory_record * dr) serial::string(" file_identifier: "); serial::string(dr->file_identifier, dr->length_of_file_identifier); serial::character('\n'); + + if ((dr->file_flags & FILE_FLAGS__DIRECTORY) == 0) { + if (is_jvm_bin(dr->file_identifier, dr->length_of_file_identifier)) { + load_jvm_bin(dr); + } + } } void walk_directory(uint16_t * buf, int extent, int num_extents) @@ -154,14 +231,14 @@ void walk_directory(uint16_t * buf, int extent, int num_extents) void main() { - //serial::init(0); + 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++) { + for (uint32_t i = 0; i < 0x200000 / 4; i++) { (void)system_boot_rom[i]; } @@ -195,7 +272,24 @@ void main() const int data_length = root_dr->data_length.get(); const int num_extents = data_length >> 11; // division by 2048 + jvm_load_complete = false; walk_directory(buf, extent, num_extents); + serial::integer(jvm_load_complete); + if (jvm_load_complete) { + main_ptr_t jvm_main = reinterpret_cast(load_address); + uint8_t * load_buf = reinterpret_cast(load_address); + + serial::string("crc32: "); + int chunks = __data_length / 2048; + for (int i = 0; i < chunks; i++) { + uint32_t crc = crc32(&((uint8_t *)load_address)[i * 2048], 2048); + serial::integer(crc); + } + + serial::string("jvm jump\n"); + jvm_main(); + serial::string("jvm return\n"); + } while (1); } diff --git a/holly/video_output.cpp b/holly/video_output.cpp index 4abaa72..3737b23 100644 --- a/holly/video_output.cpp +++ b/holly/video_output.cpp @@ -38,7 +38,7 @@ void set_framebuffer_resolution(const uint32_t x_size, const uint32_t y_size) void set_mode(const struct mode& mode) { holly.FB_R_CTRL = mode.fb_r_ctrl - | fb_r_ctrl::fb_depth::_0565_rgb_16bit + | fb_r_ctrl::fb_depth::_565_rgb_16bit | fb_r_ctrl::fb_enable; holly.SPG_LOAD = mode.spg_load; diff --git a/ip.mk b/ip.mk index c8559a0..5a4d802 100644 --- a/ip.mk +++ b/ip.mk @@ -22,7 +22,8 @@ SERIAL_LOAD_OBJ = \ GDROM_JVM_BOOT_OBJ = \ example/gdrom_jvm_boot.o \ - sh7091/serial.o + sh7091/serial.o \ + crc32.o %.o: %.obj $(OBJCOPY) -g \ @@ -34,3 +35,6 @@ serial_load_ip.elf: $(IP_OBJ) $(SERIAL_LOAD_OBJ) gdrom_jvm_boot_ip.elf: $(IP_OBJ) $(GDROM_JVM_BOOT_OBJ) $(LD) --orphan-handling=error --print-memory-usage -T $(LIB)/ip.lds $^ -o $@ + +gdrom-jvm-boot-ip-bin: gdrom_jvm_boot_ip.bin + cp $< ip.bin