236 lines
4.4 KiB
C++
236 lines
4.4 KiB
C++
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <inttypes.h>
|
|
|
|
#include "../../file_io.h"
|
|
#include "../../user_io.h"
|
|
#include "../../spi.h"
|
|
#include "../../hardware.h"
|
|
#include "pcecd.h"
|
|
|
|
|
|
static int /*loaded = 0, unloaded = 0,*/ need_reset=0;
|
|
static uint8_t has_command = 0;
|
|
|
|
void pcecd_poll()
|
|
{
|
|
static uint32_t poll_timer = 0;
|
|
static uint8_t last_req = 0;
|
|
static uint8_t adj = 0;
|
|
|
|
if (!poll_timer || CheckTimer(poll_timer))
|
|
{
|
|
poll_timer = GetTimer(13 + (!adj ? 1 : 0));
|
|
if (++adj >= 3) adj = 0;
|
|
|
|
if (pcecdd.has_status) {
|
|
uint16_t s;
|
|
pcecdd.GetStatus((uint8_t*)&s);
|
|
|
|
spi_uio_cmd_cont(UIO_CD_SET);
|
|
spi_w(s);
|
|
spi_w(0);
|
|
DisableIO();
|
|
|
|
pcecdd.has_status = 0;
|
|
|
|
printf("\x1b[32mPCECD: Send status = %02X, message = %02X\n\x1b[0m", s&0xFF, s >> 8);
|
|
}
|
|
else if (pcecdd.data_req) {
|
|
spi_uio_cmd_cont(UIO_CD_SET);
|
|
spi_w(0);
|
|
spi_w(1);
|
|
DisableIO();
|
|
|
|
pcecdd.data_req = false;
|
|
|
|
printf("\x1b[32mPCECD: Data request for MODESELECT6\n\x1b[0m");
|
|
}
|
|
|
|
pcecdd.Update();
|
|
}
|
|
|
|
|
|
uint8_t req = spi_uio_cmd_cont(UIO_CD_GET);
|
|
if (req != last_req)
|
|
{
|
|
last_req = req;
|
|
|
|
uint16_t data_in[6];
|
|
uint16_t data_mode;
|
|
data_in[0] = spi_w(0);
|
|
data_in[1] = spi_w(0);
|
|
data_in[2] = spi_w(0);
|
|
data_in[3] = spi_w(0);
|
|
data_in[4] = spi_w(0);
|
|
data_in[5] = spi_w(0);
|
|
data_mode = spi_w(0);
|
|
DisableIO();
|
|
|
|
|
|
switch (data_mode & 0xFF)
|
|
{
|
|
case 0:
|
|
pcecdd.SetCommand((uint8_t*)data_in);
|
|
pcecdd.CommandExec();
|
|
has_command = 1;
|
|
break;
|
|
|
|
case 1:
|
|
//TODO: process data
|
|
pcecdd.SendStatus(0, 0);
|
|
printf("\x1b[32mPCECD: Command MODESELECT6, received data\n\x1b[0m");
|
|
break;
|
|
|
|
default:
|
|
pcecdd.can_read_next = true;
|
|
break;
|
|
}
|
|
|
|
|
|
//printf("\x1b[32mMCD: Get command, command = %04X%04X%04X, has_command = %u\n\x1b[0m", data_in[2], data_in[1], data_in[0], has_command);
|
|
}
|
|
else
|
|
DisableIO();
|
|
|
|
if (need_reset) {
|
|
need_reset = 0;
|
|
pcecdd.Reset();
|
|
printf("\x1b[32mPCECD: Reset\n\x1b[0m");
|
|
}
|
|
|
|
}
|
|
|
|
void pcecd_reset() {
|
|
need_reset = 1;
|
|
}
|
|
|
|
static void notify_mount(int load)
|
|
{
|
|
spi_uio_cmd16(UIO_SET_SDINFO, load);
|
|
spi_uio_cmd8(UIO_SET_SDSTAT, 1);
|
|
|
|
if (!load)
|
|
{
|
|
user_io_8bit_set_status(UIO_STATUS_RESET, UIO_STATUS_RESET);
|
|
usleep(100000);
|
|
user_io_8bit_set_status(0, UIO_STATUS_RESET);
|
|
}
|
|
}
|
|
|
|
int pcecd_using_cd()
|
|
{
|
|
return pcecdd.loaded;
|
|
}
|
|
|
|
static char buf[1024];
|
|
static char us_sig[] =
|
|
{ 0x72, 0xA2, 0xC2, 0x04, 0x12, 0xF6, 0xB6, 0xA6,
|
|
0x04, 0xA2, 0x36, 0xA6, 0xC6, 0x2E, 0x4E, 0xF6,
|
|
0x76, 0x96, 0xC6, 0xCE, 0x34, 0x32, 0x2E, 0x26,
|
|
0x74, 0x00 };
|
|
|
|
static int load_bios(char *name)
|
|
{
|
|
uint32_t size = FileLoad(name, 0, 0);
|
|
if (!size) return 0;
|
|
|
|
if (size < 262144)
|
|
{
|
|
//not official bios
|
|
return user_io_file_tx(name, 0);
|
|
}
|
|
|
|
fileTYPE f;
|
|
if (!FileOpen(&f, name)) return 0;
|
|
|
|
uint32_t start = size & 0x3FF;
|
|
size = 262144;
|
|
|
|
FileSeek(&f, start+size-26, SEEK_SET);
|
|
memset(buf, 0, sizeof(buf));
|
|
FileReadAdv(&f, buf, 26);
|
|
int swap = !memcmp(buf, us_sig, sizeof(us_sig));
|
|
|
|
user_io_set_index(0);
|
|
user_io_set_download(1);
|
|
FileSeek(&f, start, SEEK_SET);
|
|
|
|
while (size)
|
|
{
|
|
uint16_t chunk = (size > sizeof(buf)) ? sizeof(buf) : size;
|
|
size -= chunk;
|
|
|
|
FileReadAdv(&f, buf, chunk);
|
|
if (swap)
|
|
{
|
|
for (uint32_t i = 0; i < chunk; i++)
|
|
{
|
|
unsigned char c = buf[i];
|
|
buf[i] = ((c & 1) << 7) | ((c & 2) << 5) | ((c & 4) << 3) | ((c & 8) << 1) | ((c & 16) >> 1) | ((c & 32) >> 3) | ((c & 64) >> 5) | ((c & 128) >> 7);
|
|
}
|
|
}
|
|
user_io_file_tx_write((uint8_t*)buf, chunk);
|
|
}
|
|
|
|
user_io_set_download(0);
|
|
|
|
return 1;
|
|
}
|
|
|
|
void pcecd_set_image(int num, const char *filename)
|
|
{
|
|
(void)num;
|
|
|
|
pcecdd.Unload();
|
|
pcecdd.state = PCECD_STATE_NODISC;
|
|
|
|
if (strlen(filename)) {
|
|
static char path[1024];
|
|
|
|
if (pcecdd.Load(filename) > 0) {
|
|
pcecdd.state = pcecdd.loaded ? PCECD_STATE_IDLE : PCECD_STATE_NODISC;
|
|
pcecdd.latency = 10;
|
|
pcecdd.SendData = pcecd_send_data;
|
|
|
|
// load CD BIOS
|
|
strcpy(buf, filename);
|
|
char *p = strrchr(buf, '/');
|
|
int loaded = 0;
|
|
if (p)
|
|
{
|
|
p++;
|
|
strcpy(p, "cd_bios.rom");
|
|
loaded = load_bios(buf);
|
|
}
|
|
|
|
if (!loaded)
|
|
{
|
|
sprintf(path, "%s/cd_bios.rom", user_io_get_core_path());
|
|
load_bios(path);
|
|
}
|
|
notify_mount(1);
|
|
}
|
|
else {
|
|
notify_mount(0);
|
|
pcecdd.state = PCECD_STATE_NODISC;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
pcecdd.Unload();
|
|
notify_mount(0);
|
|
pcecdd.state = PCECD_STATE_NODISC;
|
|
}
|
|
}
|
|
|
|
int pcecd_send_data(uint8_t* buf, int len, uint8_t index) {
|
|
user_io_set_index(index);
|
|
user_io_set_download(1);
|
|
user_io_file_tx_write(buf, len);
|
|
user_io_set_download(0);
|
|
return 1;
|
|
}
|