mirror of
https://github.com/MiSTer-devel/Main_MiSTer.git
synced 2026-04-12 03:04:02 +00:00
Saturn: initial support. (#612)
This commit is contained in:
8
cd.h
8
cd.h
@@ -39,7 +39,15 @@ typedef struct
|
||||
uint8_t f;
|
||||
} msf_t;
|
||||
|
||||
#define BCD(v) ((uint8_t)((((v)/10) << 4) | ((v)%10)))
|
||||
|
||||
typedef int (*SendDataFunc) (uint8_t* buf, int len, uint8_t index);
|
||||
|
||||
inline int FindIndexInTOC(toc_t* toc, int lba)
|
||||
{
|
||||
int index = 0;
|
||||
while ((toc->tracks[index].end <= lba) && (index < toc->last)) index++;
|
||||
return index;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
7
menu.cpp
7
menu.cpp
@@ -2156,6 +2156,7 @@ void HandleUI(void)
|
||||
}
|
||||
|
||||
if (is_pce() && !bit) pcecd_reset();
|
||||
if (is_saturn() && !bit) saturn_reset();
|
||||
|
||||
user_io_status_set(opt, 1, ex);
|
||||
user_io_status_set(opt, 0, ex);
|
||||
@@ -2278,6 +2279,10 @@ void HandleUI(void)
|
||||
psx_mount_cd(user_io_ext_idx(selPath, fs_pFileExt) << 6 | (menusub + 1), ioctl_index, selPath);
|
||||
cheats_init(selPath, 0);
|
||||
}
|
||||
else if (is_saturn())
|
||||
{
|
||||
saturn_set_image(ioctl_index, selPath);
|
||||
}
|
||||
else
|
||||
{
|
||||
user_io_set_index(user_io_ext_idx(selPath, fs_pFileExt) << 6 | (menusub + 1));
|
||||
@@ -4800,7 +4805,7 @@ void HandleUI(void)
|
||||
char type = flist_SelectedItem()->de.d_type;
|
||||
memcpy(name, flist_SelectedItem()->de.d_name, sizeof(name));
|
||||
|
||||
if ((fs_Options & SCANO_UMOUNT) && (is_megacd() || is_pce() || (is_psx() && !(fs_Options & SCANO_SAVES))) && type == DT_DIR && strcmp(flist_SelectedItem()->de.d_name, ".."))
|
||||
if ((fs_Options & SCANO_UMOUNT) && (is_megacd() || is_pce() || (is_psx() && !(fs_Options & SCANO_SAVES)) || is_saturn()) && type == DT_DIR && strcmp(flist_SelectedItem()->de.d_name, ".."))
|
||||
{
|
||||
int len = strlen(selPath);
|
||||
strcat(selPath, "/");
|
||||
|
||||
1
osd.cpp
1
osd.cpp
@@ -671,6 +671,7 @@ void OsdUpdate()
|
||||
DisableOsd();
|
||||
if (is_megacd()) mcd_poll();
|
||||
if (is_pce()) pcecd_poll();
|
||||
if (is_saturn()) saturn_poll();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -40,3 +40,6 @@
|
||||
|
||||
// UEF support
|
||||
#include "support/uef/uef_reader.h"
|
||||
|
||||
// Saturn support
|
||||
#include "support/saturn/saturn.h"
|
||||
|
||||
231
support/saturn/saturn.cpp
Normal file
231
support/saturn/saturn.cpp
Normal file
@@ -0,0 +1,231 @@
|
||||
#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 "../../menu.h"
|
||||
#include "../../cheats.h"
|
||||
#include "saturn.h"
|
||||
|
||||
static int need_reset = 0;
|
||||
uint32_t frame_cnt = 0;
|
||||
|
||||
static uint32_t CalcTimerOffset(uint8_t speed) {
|
||||
static uint8_t adj = 0x1;
|
||||
|
||||
uint32_t offs;
|
||||
if (speed == 2) {
|
||||
offs = 6 + ((adj & 0x03) != 0x00 ? 1 : 0); //6.6
|
||||
adj <<= 1;
|
||||
if (adj >= 0x08) adj = 0x01;
|
||||
}
|
||||
else if (speed == 1) {
|
||||
offs = 13 + ((adj & 0x01) != 0x00 ? 1 : 0); //13.3
|
||||
adj <<= 1;
|
||||
if (adj >= 0x08) adj = 0x01;
|
||||
}
|
||||
else {
|
||||
offs = 16 + ((adj & 0x03) != 0x00 ? 1 : 0); //16.7
|
||||
adj <<= 1;
|
||||
if (adj >= 0x08) adj = 0x01;
|
||||
}
|
||||
return offs;
|
||||
}
|
||||
|
||||
void saturn_poll()
|
||||
{
|
||||
static unsigned long poll_timer = 0;
|
||||
static uint8_t last_req = 255;
|
||||
|
||||
if (!poll_timer || CheckTimer(poll_timer))
|
||||
{
|
||||
poll_timer = GetTimer(0);
|
||||
|
||||
uint16_t data_in[6];
|
||||
uint8_t req = spi_uio_cmd_cont(UIO_CD_GET);
|
||||
if (req != last_req)
|
||||
{
|
||||
last_req = req;
|
||||
|
||||
for (int i = 0; i < 6; i++) data_in[i] = spi_w(0);
|
||||
DisableIO();
|
||||
|
||||
satcdd.SetCommand((uint8_t*)data_in);
|
||||
satcdd.CommandExec();
|
||||
}
|
||||
else
|
||||
DisableIO();
|
||||
|
||||
uint8_t time_mode;
|
||||
satcdd.Process(&time_mode);
|
||||
|
||||
poll_timer += CalcTimerOffset(time_mode);
|
||||
|
||||
uint16_t* s = (uint16_t*)satcdd.GetStatus();
|
||||
spi_uio_cmd_cont(UIO_CD_SET);
|
||||
for (int i = 0; i < 6; i++) spi_w(s[i]);
|
||||
DisableIO();
|
||||
|
||||
satcdd.Update();
|
||||
|
||||
frame_cnt++;
|
||||
}
|
||||
}
|
||||
|
||||
static char buf[1024];
|
||||
static void saturn_mount_save(const char *filename)
|
||||
{
|
||||
/*user_io_set_index(SAVE_IO_INDEX);
|
||||
user_io_set_download(1);
|
||||
if (strlen(filename))
|
||||
{
|
||||
FileGenerateSavePath(filename, buf);
|
||||
user_io_file_mount(buf, 0, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
user_io_file_mount("");
|
||||
}
|
||||
user_io_set_download(0);*/
|
||||
}
|
||||
|
||||
static int saturn_load_rom(const char *basename, const char *name, int sub_index)
|
||||
{
|
||||
strcpy(buf, basename);
|
||||
char *p = strrchr(buf, '/');
|
||||
if (p)
|
||||
{
|
||||
p++;
|
||||
strcpy(p, name);
|
||||
if (user_io_file_tx(buf, sub_index << 6)) return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
void saturn_set_image(int num, const char *filename)
|
||||
{
|
||||
static char last_dir[1024] = {};
|
||||
|
||||
(void)num;
|
||||
|
||||
satcdd.Unload();
|
||||
satcdd.state = Open;
|
||||
|
||||
int same_game = *filename && *last_dir && !strncmp(last_dir, filename, strlen(last_dir));
|
||||
strcpy(last_dir, filename);
|
||||
char *p = strrchr(last_dir, '/');
|
||||
if (p) *p = 0;
|
||||
|
||||
int loaded = 1;
|
||||
if (!same_game)
|
||||
{
|
||||
saturn_mount_save("");
|
||||
|
||||
user_io_status_set("[0]", 1);
|
||||
user_io_status_set("[0]", 0);
|
||||
saturn_reset();
|
||||
|
||||
loaded = 0;
|
||||
strcpy(buf, last_dir);
|
||||
char *p = strrchr(buf, '/');
|
||||
if (p)
|
||||
{
|
||||
strcpy(p + 1, "cd_bios.rom");
|
||||
loaded = user_io_file_tx(buf);
|
||||
}
|
||||
|
||||
if (!loaded)
|
||||
{
|
||||
sprintf(buf, "%s/boot.rom", HomeDir());
|
||||
loaded = user_io_file_tx(buf);
|
||||
}
|
||||
|
||||
if (!loaded) Info("CD BIOS not found!", 4000);
|
||||
}
|
||||
|
||||
if (strlen(filename))
|
||||
{
|
||||
if (satcdd.Load(filename) > 0)
|
||||
{
|
||||
satcdd.state = satcdd.loaded ? Stop : Open;
|
||||
satcdd.SendData = saturn_send_data;
|
||||
|
||||
if (!same_game)
|
||||
{
|
||||
saturn_load_rom(filename, "cd_bios.rom", 0);
|
||||
//saturn_load_rom(filename, "cart.rom", 1);
|
||||
saturn_mount_save(filename);
|
||||
//cheats_init(filename, 0);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
satcdd.state = Open;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void saturn_reset() {
|
||||
need_reset = 1;
|
||||
}
|
||||
|
||||
int saturn_send_data(uint8_t* buf, int len, uint8_t index) {
|
||||
// set index byte
|
||||
user_io_set_index(index);
|
||||
|
||||
user_io_set_download(1);
|
||||
user_io_file_tx_data(buf, len);
|
||||
user_io_set_download(0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static char int_blank[] = {
|
||||
0x42, 0x61, 0x63, 0x6B, 0x55, 0x70, 0x52, 0x61, 0x6D, 0x20, 0x46, 0x6F, 0x72, 0x6D, 0x61, 0x74,
|
||||
0x42, 0x61, 0x63, 0x6B, 0x55, 0x70, 0x52, 0x61, 0x6D, 0x20, 0x46, 0x6F, 0x72, 0x6D, 0x61, 0x74,
|
||||
0x42, 0x61, 0x63, 0x6B, 0x55, 0x70, 0x52, 0x61, 0x6D, 0x20, 0x46, 0x6F, 0x72, 0x6D, 0x61, 0x74,
|
||||
0x42, 0x61, 0x63, 0x6B, 0x55, 0x70, 0x52, 0x61, 0x6D, 0x20, 0x46, 0x6F, 0x72, 0x6D, 0x61, 0x74,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
};
|
||||
|
||||
void saturn_fill_blanksave(uint8_t *buffer, uint32_t lba)
|
||||
{
|
||||
if (lba == 0)
|
||||
{
|
||||
memcpy(buffer, int_blank, 512);
|
||||
}
|
||||
else
|
||||
{
|
||||
memset(buffer, 0, 512);
|
||||
}
|
||||
}
|
||||
96
support/saturn/saturn.h
Normal file
96
support/saturn/saturn.h
Normal file
@@ -0,0 +1,96 @@
|
||||
#ifndef SATURN_H
|
||||
#define SATURN_H
|
||||
|
||||
#include "../../cd.h"
|
||||
|
||||
// CDD command
|
||||
#define SATURN_COMM_NOP 0x00
|
||||
#define SATURN_COMM_SEEK_RING 0x02
|
||||
#define SATURN_COMM_TOC 0x03
|
||||
#define SATURN_COMM_STOP 0x04
|
||||
#define SATURN_COMM_READ 0x06
|
||||
#define SATURN_COMM_PAUSE 0x08
|
||||
#define SATURN_COMM_SEEK 0x09
|
||||
#define SATURN_COMM_FW_SCAN 0x0A
|
||||
#define SATURN_COMM_RW_SCAN 0x0B
|
||||
|
||||
// CDD status
|
||||
#define SATURN_STAT_NOP 0x00
|
||||
#define SATURN_STAT_TOC 0x06
|
||||
#define SATURN_STAT_STOP 0x12
|
||||
#define SATURN_STAT_SEEK 0x22
|
||||
#define SATURN_STAT_AUDIO 0x34
|
||||
#define SATURN_STAT_DATA 0x36
|
||||
#define SATURN_STAT_IDLE 0x46
|
||||
#define SATURN_STAT_OPEN 0x80
|
||||
#define SATURN_STAT_NODISK 0x83
|
||||
#define SATURN_STAT_SEEK_RING 0xB2
|
||||
#define SATURN_STAT_SEEK_RING2 0xB6
|
||||
|
||||
typedef enum {
|
||||
Idle,
|
||||
Open,
|
||||
ReadTOC,
|
||||
Read,
|
||||
Play,
|
||||
Pause,
|
||||
Stop,
|
||||
Seek,
|
||||
SeekRead,
|
||||
SeekRing
|
||||
} satstate_t;
|
||||
|
||||
class satcdd_t
|
||||
{
|
||||
public:
|
||||
int loaded;
|
||||
satstate_t state;
|
||||
int speed;
|
||||
SendDataFunc SendData;
|
||||
|
||||
satcdd_t();
|
||||
int Load(const char *filename);
|
||||
void Unload();
|
||||
void Reset();
|
||||
void Process(uint8_t* time_mode);
|
||||
void Update();
|
||||
void CommandExec();
|
||||
uint8_t* GetStatus();
|
||||
int SetCommand(uint8_t* data);
|
||||
|
||||
private:
|
||||
toc_t toc;
|
||||
int lba;
|
||||
int index;
|
||||
int seek_lba;
|
||||
uint16_t sectorSize;
|
||||
int toc_pos;
|
||||
satstate_t next_state;
|
||||
uint8_t stat[12];
|
||||
uint8_t comm[12];
|
||||
uint8_t cd_buf[4096 + 2];
|
||||
int audioLength;
|
||||
int audioFirst;
|
||||
|
||||
int LoadCUE(const char* filename);
|
||||
void LBAToMSF(int lba, msf_t* msf);
|
||||
int GetFAD(uint8_t* cmd);
|
||||
void SetChecksum(uint8_t* stat);
|
||||
void ReadData(uint8_t *buf);
|
||||
int ReadCDDA(uint8_t *buf);
|
||||
void MakeSecureRingData(uint8_t *buf);
|
||||
int DataSectorSend(uint8_t* header, int speed);
|
||||
int AudioSectorSend();
|
||||
int RingDataSend(uint8_t* header, int speed);
|
||||
};
|
||||
|
||||
extern satcdd_t satcdd;
|
||||
extern uint32_t frame_cnt;
|
||||
|
||||
void saturn_poll();
|
||||
void saturn_set_image(int num, const char *filename);
|
||||
void saturn_reset();
|
||||
void saturn_fill_blanksave(uint8_t *buffer, uint32_t lba);
|
||||
int saturn_send_data(uint8_t* buf, int len, uint8_t index);
|
||||
|
||||
#endif
|
||||
965
support/saturn/saturncdd.cpp
Normal file
965
support/saturn/saturncdd.cpp
Normal file
@@ -0,0 +1,965 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <inttypes.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "saturn.h"
|
||||
#include "../chd/mister_chd.h"
|
||||
|
||||
#define CD_DATA_IO_INDEX 4
|
||||
|
||||
satcdd_t satcdd;
|
||||
|
||||
satcdd_t::satcdd_t() {
|
||||
loaded = 0;
|
||||
state = Open,
|
||||
index = 0;
|
||||
lba = 0;
|
||||
seek_lba = 0;
|
||||
speed = 0;
|
||||
audioLength = 0;
|
||||
audioFirst = 0;
|
||||
//chd_hunkbuf = NULL;
|
||||
//chd_hunknum = -1;
|
||||
SendData = NULL;
|
||||
|
||||
stat[0] = SATURN_STAT_OPEN;
|
||||
stat[1] = 0x00;
|
||||
stat[2] = 0x00;
|
||||
stat[3] = 0x00;
|
||||
stat[4] = 0x00;
|
||||
stat[5] = 0x00;
|
||||
stat[6] = 0x00;
|
||||
stat[7] = 0x00;
|
||||
stat[8] = 0x00;
|
||||
stat[9] = 0x00;
|
||||
stat[11] = 0x00;
|
||||
SetChecksum(stat);
|
||||
}
|
||||
|
||||
static int sgets(char *out, int sz, char **in)
|
||||
{
|
||||
*out = 0;
|
||||
do
|
||||
{
|
||||
char *instr = *in;
|
||||
int cnt = 0;
|
||||
|
||||
while (*instr && *instr != 10)
|
||||
{
|
||||
if (*instr == 13)
|
||||
{
|
||||
instr++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (cnt < sz - 1)
|
||||
{
|
||||
out[cnt++] = *instr;
|
||||
out[cnt] = 0;
|
||||
}
|
||||
|
||||
instr++;
|
||||
}
|
||||
|
||||
if (*instr == 10) instr++;
|
||||
*in = instr;
|
||||
} while (!*out && **in);
|
||||
|
||||
return *out;
|
||||
}
|
||||
|
||||
int satcdd_t::LoadCUE(const char* filename) {
|
||||
static char fname[1024 + 10];
|
||||
static char line[128];
|
||||
char *ptr, *lptr;
|
||||
static char toc[100 * 1024];
|
||||
|
||||
strcpy(fname, filename);
|
||||
|
||||
memset(toc, 0, sizeof(toc));
|
||||
if (!FileLoad(fname, toc, sizeof(toc) - 1)) return 1;
|
||||
|
||||
printf("\x1b[32mSaturn: Open CUE: %s\n\x1b[0m", fname);
|
||||
|
||||
int mm, ss, bb, pregap = 0;
|
||||
|
||||
char *buf = toc;
|
||||
while (sgets(line, sizeof(line), &buf))
|
||||
{
|
||||
lptr = line;
|
||||
while (*lptr == 0x20) lptr++;
|
||||
|
||||
/* decode FILE commands */
|
||||
if (!(memcmp(lptr, "FILE", 4)))
|
||||
{
|
||||
ptr = fname + strlen(fname) - 1;
|
||||
while ((ptr - fname) && (*ptr != '/') && (*ptr != '\\')) ptr--;
|
||||
if (ptr - fname) ptr++;
|
||||
|
||||
lptr += 4;
|
||||
while (*lptr == 0x20) lptr++;
|
||||
|
||||
if (*lptr == '\"')
|
||||
{
|
||||
lptr++;
|
||||
while ((*lptr != '\"') && (lptr <= (line + 128)) && (ptr < (fname + 1023)))
|
||||
*ptr++ = *lptr++;
|
||||
}
|
||||
else
|
||||
{
|
||||
while ((*lptr != 0x20) && (lptr <= (line + 128)) && (ptr < (fname + 1023)))
|
||||
*ptr++ = *lptr++;
|
||||
}
|
||||
*ptr = 0;
|
||||
|
||||
if (!FileOpen(&this->toc.tracks[this->toc.last].f, fname)) return -1;
|
||||
|
||||
printf("\x1b[32mSaturn: Open track file: %s\n\x1b[0m", fname);
|
||||
|
||||
pregap = 0;
|
||||
|
||||
this->toc.tracks[this->toc.last].offset = 0;
|
||||
|
||||
if (!strstr(lptr, "BINARY") && !strstr(lptr, "MOTOROLA") && !strstr(lptr, "WAVE"))
|
||||
{
|
||||
FileClose(&this->toc.tracks[this->toc.last].f);
|
||||
printf("\x1b[32mSaturn: unsupported file: %s\n\x1b[0m", fname);
|
||||
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* decode TRACK commands */
|
||||
else if ((sscanf(lptr, "TRACK %02d %*s", &bb)) || (sscanf(lptr, "TRACK %d %*s", &bb)))
|
||||
{
|
||||
if (bb != (this->toc.last + 1))
|
||||
{
|
||||
FileClose(&this->toc.tracks[this->toc.last].f);
|
||||
printf("\x1b[32mSaturn: missing tracks: %s\n\x1b[0m", fname);
|
||||
break;
|
||||
}
|
||||
|
||||
if (strstr(lptr, "MODE1/2048"))
|
||||
{
|
||||
this->sectorSize = 2048;
|
||||
this->toc.tracks[this->toc.last].type = 1;
|
||||
}
|
||||
else if (strstr(lptr, "MODE1/2352"))
|
||||
{
|
||||
this->sectorSize = 2352;
|
||||
this->toc.tracks[this->toc.last].type = 1;
|
||||
|
||||
//FileSeek(&this->toc.tracks[0].f, 0x10, SEEK_SET);
|
||||
}
|
||||
else if (strstr(lptr, "MODE2/2352"))
|
||||
{
|
||||
this->sectorSize = 2352;
|
||||
this->toc.tracks[this->toc.last].type = 2;
|
||||
|
||||
//FileSeek(&this->toc.tracks[0].f, 0x10, SEEK_SET);
|
||||
}
|
||||
|
||||
if (!this->toc.last)
|
||||
{
|
||||
/*if (strstr(lptr, "MODE1/2048"))
|
||||
{
|
||||
this->sectorSize = 2048;
|
||||
this->toc.tracks[0].type = 1;
|
||||
}
|
||||
else if (strstr(lptr, "MODE1/2352") || strstr(lptr, "MODE2/2352"))
|
||||
{
|
||||
this->sectorSize = 2352;
|
||||
this->toc.tracks[0].type = 1;
|
||||
|
||||
FileSeek(&this->toc.tracks[0].f, 0x10, SEEK_SET);
|
||||
}
|
||||
|
||||
if (this->sectorSize)
|
||||
{
|
||||
this->toc.tracks[0].type = 1;
|
||||
|
||||
FileReadAdv(&this->toc.tracks[0].f, header, 0x210);
|
||||
FileSeek(&this->toc.tracks[0].f, 0, SEEK_SET);
|
||||
}*/
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!this->toc.tracks[this->toc.last].f.opened())
|
||||
{
|
||||
this->toc.tracks[this->toc.last - 1].end = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* decode PREGAP commands */
|
||||
else if (sscanf(lptr, "PREGAP %02d:%02d:%02d", &mm, &ss, &bb) == 3)
|
||||
{
|
||||
pregap += bb + ss * 75 + mm * 60 * 75;
|
||||
}
|
||||
|
||||
/* decode INDEX commands */
|
||||
else if ((sscanf(lptr, "INDEX 00 %02d:%02d:%02d", &mm, &ss, &bb) == 3) ||
|
||||
(sscanf(lptr, "INDEX 0 %02d:%02d:%02d", &mm, &ss, &bb) == 3))
|
||||
{
|
||||
if (this->toc.last && !this->toc.tracks[this->toc.last - 1].end)
|
||||
{
|
||||
this->toc.tracks[this->toc.last - 1].end = bb + ss * 75 + mm * 60 * 75 + pregap;
|
||||
}
|
||||
}
|
||||
else if ((sscanf(lptr, "INDEX 01 %02d:%02d:%02d", &mm, &ss, &bb) == 3) ||
|
||||
(sscanf(lptr, "INDEX 1 %02d:%02d:%02d", &mm, &ss, &bb) == 3))
|
||||
{
|
||||
this->toc.tracks[this->toc.last].offset += pregap * 2352;
|
||||
|
||||
if (!this->toc.tracks[this->toc.last].f.opened())
|
||||
{
|
||||
FileOpen(&this->toc.tracks[this->toc.last].f, fname);
|
||||
this->toc.tracks[this->toc.last].start = bb + ss * 75 + mm * 60 * 75 + pregap;
|
||||
if (this->toc.last && !this->toc.tracks[this->toc.last - 1].end)
|
||||
{
|
||||
this->toc.tracks[this->toc.last - 1].end = this->toc.tracks[this->toc.last].start;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
FileSeek(&this->toc.tracks[this->toc.last].f, 0, SEEK_SET);
|
||||
|
||||
this->toc.tracks[this->toc.last].start = this->toc.end + pregap;
|
||||
this->toc.tracks[this->toc.last].offset += this->toc.end * 2352;
|
||||
|
||||
int sectorSize = 2352;
|
||||
if (this->toc.tracks[this->toc.last].type) sectorSize = this->sectorSize;
|
||||
this->toc.tracks[this->toc.last].end = this->toc.tracks[this->toc.last].start + ((this->toc.tracks[this->toc.last].f.size + sectorSize - 1) / sectorSize);
|
||||
|
||||
this->toc.tracks[this->toc.last].start += (bb + ss * 75 + mm * 60 * 75);
|
||||
this->toc.end = this->toc.tracks[this->toc.last].end;
|
||||
}
|
||||
|
||||
printf("\x1b[32mSaturn: Track = %u, start = %u, end = %u, offset = %u, type = %u\n\x1b[0m", this->toc.last, this->toc.tracks[this->toc.last].start, this->toc.tracks[this->toc.last].end, this->toc.tracks[this->toc.last].offset, this->toc.tracks[this->toc.last].type);
|
||||
|
||||
this->toc.last++;
|
||||
if (this->toc.last == 99) break;
|
||||
}
|
||||
}
|
||||
|
||||
if (this->toc.last && !this->toc.tracks[this->toc.last - 1].end)
|
||||
{
|
||||
this->toc.end += pregap;
|
||||
this->toc.tracks[this->toc.last - 1].end = this->toc.end;
|
||||
}
|
||||
|
||||
FileClose(&this->toc.tracks[this->toc.last].f);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int satcdd_t::Load(const char *filename)
|
||||
{
|
||||
//static char header[32];
|
||||
//fileTYPE *fd_img;
|
||||
|
||||
Unload();
|
||||
|
||||
const char *ext = filename + strlen(filename) - 4;
|
||||
if (!strncasecmp(".cue", ext, 4))
|
||||
{
|
||||
if (LoadCUE(filename)) {
|
||||
return (-1);
|
||||
}
|
||||
}
|
||||
/*else if (!strncasecmp(".chd", ext, 4)) {
|
||||
chd_error err = mister_load_chd(filename, &this->toc);
|
||||
if (err != CHDERR_NONE)
|
||||
{
|
||||
printf("ERROR %s\n", chd_error_string(err));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (this->chd_hunkbuf)
|
||||
{
|
||||
free(this->chd_hunkbuf);
|
||||
}
|
||||
|
||||
this->chd_hunkbuf = (uint8_t *)malloc(CD_FRAME_SIZE * CD_FRAMES_PER_HUNK);
|
||||
this->chd_hunknum = -1;
|
||||
}*/
|
||||
else {
|
||||
return (-1);
|
||||
|
||||
}
|
||||
|
||||
/*if (this->toc.chd_f)
|
||||
{
|
||||
mister_chd_read_sector(this->toc.chd_f, 0, 0, 0, 0x10, (uint8_t *)header, this->chd_hunkbuf, &this->chd_hunknum);
|
||||
}
|
||||
else {
|
||||
fd_img = &this->toc.tracks[0].f;
|
||||
|
||||
FileSeek(fd_img, 0, SEEK_SET);
|
||||
FileReadAdv(fd_img, header, 0x10);
|
||||
}*/
|
||||
|
||||
/*if (!memcmp("SEGADISCSYSTEM", header, 14))
|
||||
{
|
||||
this->sectorSize = 2048;
|
||||
}
|
||||
else
|
||||
{
|
||||
this->sectorSize = 2352;
|
||||
}*/
|
||||
|
||||
printf("\x1b[32mSaturn: Sector size = %u, Track 0 end = %u\n\x1b[0m", this->sectorSize, this->toc.tracks[0].end);
|
||||
|
||||
if (this->toc.last)
|
||||
{
|
||||
this->toc.tracks[this->toc.last].start = this->toc.end;
|
||||
this->loaded = 1;
|
||||
|
||||
printf("\x1b[32mSaturn: CD mounted, last track = %u\n\x1b[0m", this->toc.last);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void satcdd_t::Unload()
|
||||
{
|
||||
if (this->loaded)
|
||||
{
|
||||
/*if (this->toc.chd_f)
|
||||
{
|
||||
chd_close(this->toc.chd_f);
|
||||
}
|
||||
|
||||
if (this->chd_hunkbuf)
|
||||
{
|
||||
free(this->chd_hunkbuf);
|
||||
this->chd_hunkbuf = NULL;
|
||||
}*/
|
||||
|
||||
for (int i = 0; i < this->toc.last; i++)
|
||||
{
|
||||
if (this->toc.tracks[i].f.opened())
|
||||
{
|
||||
FileClose(&this->toc.tracks[i].f);
|
||||
}
|
||||
}
|
||||
|
||||
this->loaded = 0;
|
||||
}
|
||||
|
||||
memset(&this->toc, 0x00, sizeof(this->toc));
|
||||
this->sectorSize = 0;
|
||||
}
|
||||
|
||||
|
||||
void satcdd_t::Reset() {
|
||||
state = Open,
|
||||
index = 0;
|
||||
lba = 0;
|
||||
seek_lba = 0;
|
||||
speed = 0;
|
||||
audioLength = 0;
|
||||
audioFirst = 0;
|
||||
//chd_audio_read_lba = 0;
|
||||
|
||||
stat[0] = SATURN_STAT_OPEN;
|
||||
stat[1] = 0x00;
|
||||
stat[2] = 0x00;
|
||||
stat[3] = 0x00;
|
||||
stat[4] = 0x00;
|
||||
stat[5] = 0x00;
|
||||
stat[6] = 0x00;
|
||||
stat[7] = 0x00;
|
||||
stat[8] = 0x00;
|
||||
stat[9] = 0x00;
|
||||
stat[11] = 0x00;
|
||||
SetChecksum(stat);
|
||||
}
|
||||
|
||||
void satcdd_t::Process(uint8_t* time_mode) {
|
||||
msf_t amsf = { 0,2,0 };
|
||||
msf_t msf = { 0,2,0 };
|
||||
uint8_t idx = 0;
|
||||
uint8_t q = this->lba < this->toc.end && this->toc.tracks[this->index].type ? 0x40 : 0x00;
|
||||
static int seek_time = 8;
|
||||
|
||||
this->next_state = this->state;
|
||||
switch (this->state)
|
||||
{
|
||||
case Idle:
|
||||
this->lba++;
|
||||
if (this->lba > this->seek_lba + 5) this->lba = this->seek_lba;
|
||||
|
||||
LBAToMSF(this->lba + 150, &amsf);
|
||||
LBAToMSF(this->lba - this->toc.tracks[this->index].start + 150, &msf);
|
||||
|
||||
stat[0] = SATURN_STAT_IDLE;
|
||||
stat[1] = q | 0x01;
|
||||
stat[2] = this->lba < this->toc.end ? BCD(this->index + 1) : 0xAA;
|
||||
stat[3] = this->lba < this->toc.end ? 0x00 : 0x01;
|
||||
stat[4] = BCD(msf.m);
|
||||
stat[5] = BCD(msf.s);
|
||||
stat[6] = BCD(msf.f);
|
||||
stat[7] = 0x04;
|
||||
stat[8] = BCD(amsf.m);
|
||||
stat[9] = BCD(amsf.s);
|
||||
stat[10] = BCD(amsf.f);
|
||||
break;
|
||||
|
||||
case Open:
|
||||
stat[0] = SATURN_STAT_OPEN;
|
||||
stat[1] = 0x41;
|
||||
stat[2] = 0x01;
|
||||
stat[3] = 0x01;
|
||||
stat[4] = 0x00;
|
||||
stat[5] = 0x00;
|
||||
stat[6] = 0x00;
|
||||
stat[7] = 0x06;
|
||||
stat[8] = 0x00;
|
||||
stat[9] = 0x00;
|
||||
stat[10] = 0x00;
|
||||
break;
|
||||
|
||||
case ReadTOC:
|
||||
if (toc_pos < 0x100)
|
||||
{
|
||||
int lba_ = this->toc.tracks[toc_pos & 0xFF].start + 150;
|
||||
LBAToMSF(lba_, &msf);
|
||||
idx = BCD(toc_pos + 1);
|
||||
q = this->toc.tracks[toc_pos & 0xFF].type ? 0x40 : 0x00;
|
||||
|
||||
toc_pos++;
|
||||
if (toc_pos >= this->toc.last) toc_pos = 0x100;
|
||||
}
|
||||
else {
|
||||
if (toc_pos == 0x100) {//track A0
|
||||
msf.m = 1;
|
||||
msf.s = 0;
|
||||
msf.f = 0;
|
||||
idx = 0xA0;
|
||||
q = this->toc.tracks[0].type ? 0x40 : 0x00;
|
||||
}
|
||||
else if (toc_pos == 0x101) {//track A1
|
||||
msf.m = this->toc.last;
|
||||
msf.s = 0;
|
||||
msf.f = 0;
|
||||
idx = 0xA1;
|
||||
q = this->toc.tracks[this->toc.last - 1].type ? 0x40 : 0x00;
|
||||
}
|
||||
else if (toc_pos == 0x102) {//track A2
|
||||
int lba_ = this->toc.end + 150;
|
||||
LBAToMSF(lba_, &msf);
|
||||
idx = 0xA2;
|
||||
q = 0x00;
|
||||
|
||||
this->next_state = Idle;
|
||||
}
|
||||
toc_pos++;
|
||||
}
|
||||
|
||||
stat[0] = SATURN_STAT_TOC;
|
||||
stat[1] = q | 0x01;
|
||||
stat[2] = 0x00;
|
||||
stat[3] = idx;
|
||||
stat[4] = 0x00;
|
||||
stat[5] = 0x00;
|
||||
stat[6] = 0x00;
|
||||
stat[7] = 0x06;
|
||||
stat[8] = BCD(msf.m);
|
||||
stat[9] = BCD(msf.s);
|
||||
stat[10] = BCD(msf.f);
|
||||
|
||||
printf("\x1b[32mSaturn: ");
|
||||
printf("Process read TOC: index = %02X, msf = %02X:%02X:%02X, q = %02X", idx, BCD(msf.m), BCD(msf.s), BCD(msf.f), q);
|
||||
printf(" (%u)\n\x1b[0m", frame_cnt);
|
||||
break;
|
||||
|
||||
case Read:
|
||||
LBAToMSF(this->lba + 150, &amsf);
|
||||
LBAToMSF(this->lba - this->toc.tracks[this->index].start + 150, &msf);
|
||||
|
||||
stat[0] = SATURN_STAT_DATA;
|
||||
stat[1] = q | 0x01;
|
||||
stat[2] = this->lba < this->toc.end ? BCD(this->index + 1) : 0xAA;
|
||||
stat[3] = this->lba < 0 ? 0x00 : 0x01;
|
||||
stat[4] = BCD(msf.m);
|
||||
stat[5] = BCD(msf.s);
|
||||
stat[6] = BCD(msf.f);
|
||||
stat[7] = 0x04;
|
||||
stat[8] = BCD(amsf.m);
|
||||
stat[9] = BCD(amsf.s);
|
||||
stat[10] = BCD(amsf.f);
|
||||
|
||||
printf("\x1b[32mSaturn: ");
|
||||
printf("Process read data, fad = %i, msf = %02X:%02X:%02X, q = %02X", this->lba + 150, BCD(msf.m), BCD(msf.s), BCD(msf.f), q);
|
||||
printf(" (%u)\n\x1b[0m", frame_cnt);
|
||||
break;
|
||||
|
||||
case Play:
|
||||
break;
|
||||
|
||||
case Pause:
|
||||
stat[0] = SATURN_STAT_IDLE;
|
||||
stat[1] = 0x41;
|
||||
stat[2] = 0x01;
|
||||
stat[3] = 0x01;
|
||||
stat[4] = 0x00;
|
||||
stat[5] = 0x00;
|
||||
stat[6] = 0x00;
|
||||
stat[7] = 0x06;
|
||||
stat[8] = 0x00;
|
||||
stat[9] = 0x00;
|
||||
stat[10] = 0x00;
|
||||
|
||||
this->next_state = Idle;
|
||||
break;
|
||||
|
||||
case Stop:
|
||||
stat[0] = SATURN_STAT_STOP;
|
||||
stat[1] = 0x41;
|
||||
stat[2] = 0x01;
|
||||
stat[3] = 0x01;
|
||||
stat[4] = 0x00;
|
||||
stat[5] = 0x00;
|
||||
stat[6] = 0x00;
|
||||
stat[7] = 0x06;
|
||||
stat[8] = 0x00;
|
||||
stat[9] = 0x00;
|
||||
stat[10] = 0x00;
|
||||
break;
|
||||
|
||||
case Seek:
|
||||
case SeekRead:
|
||||
LBAToMSF(this->seek_lba + 150, &amsf);
|
||||
LBAToMSF(this->seek_lba - this->toc.tracks[this->index].start + 150, &msf);
|
||||
|
||||
stat[0] = SATURN_STAT_SEEK;
|
||||
stat[1] = q | 0x01;
|
||||
stat[2] = this->seek_lba < this->toc.end ? BCD(this->index + 1) : 0xAA;
|
||||
stat[3] = this->seek_lba < this->toc.end ? 0x00 : 0x01;
|
||||
stat[4] = BCD(msf.m);
|
||||
stat[5] = BCD(msf.s);
|
||||
stat[6] = BCD(msf.f);
|
||||
stat[7] = 0x06;
|
||||
stat[8] = BCD(amsf.m);
|
||||
stat[9] = BCD(amsf.s);
|
||||
stat[10] = BCD(amsf.f);
|
||||
|
||||
if (this->seek_lba == this->lba) {
|
||||
if (seek_time) seek_time--;
|
||||
else {
|
||||
this->next_state = this->state == SeekRead ? Read : Idle;
|
||||
seek_time = 2;
|
||||
}
|
||||
}
|
||||
|
||||
//printf("\x1b[32mSaturn: ");
|
||||
//printf("Process seek, fad = %i, amsf = %02X:%02X:%02X, msf = %02X:%02X:%02X, q = %02X", this->seek_lba + 150, BCD(amsf.m), BCD(amsf.s), BCD(amsf.f), BCD(msf.m), BCD(msf.s), BCD(msf.f), q | 0x01);
|
||||
//printf(" (%u)\n\x1b[0m", frame_cnt);
|
||||
break;
|
||||
|
||||
case SeekRing:
|
||||
int fad = this->lba + 150;
|
||||
|
||||
stat[0] = SATURN_STAT_SEEK_RING2;
|
||||
stat[1] = 0x48;
|
||||
stat[2] = 0x5A;
|
||||
stat[3] = fad>>16;
|
||||
stat[4] = fad>>8;
|
||||
stat[5] = fad>>0;
|
||||
stat[6] = 0x09;
|
||||
stat[7] = 0x09;
|
||||
stat[8] = 0x09;
|
||||
stat[9] = 0x09;
|
||||
stat[10] = 0x00;
|
||||
|
||||
//printf("\x1b[32mSaturn: ");
|
||||
//printf("Process seek ring, fad = %i", fad);
|
||||
//printf(" (%u)\n\x1b[0m", frame_cnt);
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
SetChecksum(stat);
|
||||
|
||||
if (this->next_state == Idle || this->next_state == Pause || this->next_state == Stop) *time_mode = 0;
|
||||
else *time_mode = this->speed;
|
||||
}
|
||||
|
||||
void satcdd_t::Update() {
|
||||
msf_t msf = { 0,2,0 };
|
||||
|
||||
switch (this->state)
|
||||
{
|
||||
case Idle:
|
||||
case Open:
|
||||
case ReadTOC:
|
||||
break;
|
||||
|
||||
case Read:
|
||||
LBAToMSF(this->lba + 150, &msf);
|
||||
|
||||
if (lba >= this->toc.end)
|
||||
{
|
||||
// CD-ROM Security Ring Data (Mode 2)
|
||||
uint8_t header[12];
|
||||
header[0] = BCD(msf.m);
|
||||
header[1] = BCD(msf.s);
|
||||
header[2] = BCD(msf.f);
|
||||
header[3] = 0x02;
|
||||
header[4] = 0x00;
|
||||
header[5] = 0x00;
|
||||
header[6] = 0x28;
|
||||
header[7] = 0x00;
|
||||
header[8] = 0x00;
|
||||
header[9] = 0x00;
|
||||
header[10] = 0x28;
|
||||
header[11] = 0x00;
|
||||
|
||||
RingDataSend(header, this->speed);
|
||||
|
||||
//printf("\x1b[32mSaturn: ");
|
||||
//printf("Read ring data, fad = %i, msf = %02X:%02X:%02X", this->lba + 150, BCD(msf.m), BCD(msf.s), BCD(msf.f));
|
||||
//printf(" (%u)\n\x1b[0m", frame_cnt);
|
||||
}
|
||||
else if (this->toc.tracks[this->index].type)
|
||||
{
|
||||
// CD-ROM Data (Mode 1/2)
|
||||
uint8_t header[4];
|
||||
|
||||
if (this->sectorSize == 2048 || this->lba < 0) {
|
||||
header[0] = BCD(msf.m);
|
||||
header[1] = BCD(msf.s);
|
||||
header[2] = BCD(msf.f);
|
||||
header[3] = 0x01;
|
||||
DataSectorSend(header, this->speed);
|
||||
}
|
||||
else {
|
||||
DataSectorSend(0, this->speed);
|
||||
}
|
||||
|
||||
if (this->toc.tracks[this->index].type == 2) {
|
||||
printf("\x1b[32mSaturn: ");
|
||||
printf("Update read data, track = %i, lba = %i, msf = %u:%u:%u, mode = 2", this->index + 1, this->lba + 150, msf.m, msf.s, msf.f);
|
||||
printf(" (%u)\n\x1b[0m", frame_cnt);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (this->lba >= this->toc.tracks[this->index].start)
|
||||
{
|
||||
//this->isData = 0x00;
|
||||
}
|
||||
AudioSectorSend();
|
||||
}
|
||||
|
||||
//printf("\x1b[32mSaturn: ");
|
||||
//printf("Update read data, lba = %i, msf = %u:%u:%u", this->lba, msf.m, msf.s, msf.f);
|
||||
//printf(" (%u)\n\x1b[0m", frame_cnt);
|
||||
|
||||
this->lba++;
|
||||
this->seek_lba++;
|
||||
this->index = FindIndexInTOC(&this->toc, this->lba);
|
||||
//this->chd_audio_read_lba++;
|
||||
|
||||
break;
|
||||
|
||||
case Play:
|
||||
case Pause:
|
||||
case Stop:
|
||||
break;
|
||||
|
||||
case Seek:
|
||||
case SeekRead:
|
||||
if (this->seek_lba != this->lba) this->seek_lba++;
|
||||
this->index = FindIndexInTOC(&this->toc, this->seek_lba);
|
||||
break;
|
||||
|
||||
case SeekRing:
|
||||
break;
|
||||
}
|
||||
|
||||
this->state = this->next_state;
|
||||
}
|
||||
|
||||
void satcdd_t::CommandExec() {
|
||||
int fad = GetFAD(comm);
|
||||
|
||||
//int last_lba = this->lba;
|
||||
|
||||
switch (comm[0]) {
|
||||
case SATURN_COMM_NOP:
|
||||
|
||||
//printf("\x1b[32mSaturn: ");
|
||||
//printf("Command Nop, status = %02X", status);
|
||||
//printf(" (%u)\n\x1b[0m", frame_cnt);
|
||||
break;
|
||||
|
||||
case SATURN_COMM_SEEK_RING:
|
||||
this->lba = this->seek_lba = fad - 150;
|
||||
this->index = FindIndexInTOC(&this->toc, this->lba);
|
||||
this->state = SeekRing;
|
||||
this->speed = comm[10] == 1 ? 1 : 2;
|
||||
|
||||
printf("\x1b[32mSaturn: ");
|
||||
printf("Command Seek Security Ring: FAD = %u, track = %u", fad, this->index + 1);
|
||||
printf(" (%u)\n\x1b[0m", frame_cnt);
|
||||
break;
|
||||
|
||||
case SATURN_COMM_TOC:
|
||||
this->toc_pos = 0;
|
||||
this->state = ReadTOC;
|
||||
this->speed = comm[10] == 1 ? 1 : 2;
|
||||
|
||||
printf("\x1b[32mSaturn: ");
|
||||
printf("Command TOC Read");
|
||||
printf(" (%u)\n\x1b[0m", frame_cnt);
|
||||
break;
|
||||
|
||||
case SATURN_COMM_STOP:
|
||||
this->state = Stop;
|
||||
|
||||
printf("\x1b[32mSaturn: ");
|
||||
printf("Command Stop");
|
||||
//printf(", last FAD = %u", last_lba + 150);
|
||||
printf(" (%u)\n\x1b[0m", frame_cnt);
|
||||
break;
|
||||
|
||||
case SATURN_COMM_READ:
|
||||
this->lba = fad - 150 - 4;
|
||||
this->seek_lba = fad - 150 - 4 - 2;
|
||||
this->index = FindIndexInTOC(&this->toc, this->lba);
|
||||
//if (this->toc.tracks[this->index].type) {
|
||||
// this->lba -= 4;
|
||||
// this->seek_lba -= 4;
|
||||
//}
|
||||
this->state = SeekRead;
|
||||
this->speed = comm[10] == 1 ? 1 : 2;
|
||||
|
||||
this->audioFirst = 1;
|
||||
|
||||
printf("\x1b[32mSaturn: ");
|
||||
printf("Command Read Data: FAD = %u, track = %u, speed = %u", fad, this->index + 1, this->speed);
|
||||
//printf(", last FAD = %u", last_lba+150);
|
||||
printf(" (%u)\n\x1b[0m", frame_cnt);
|
||||
break;
|
||||
|
||||
case SATURN_COMM_PAUSE:
|
||||
this->state = Pause;
|
||||
|
||||
printf("\x1b[32mSaturn: ");
|
||||
printf("Command Pause");
|
||||
//printf(", last FAD = %u", last_lba + 150);
|
||||
printf(" (%u)\n\x1b[0m", frame_cnt);
|
||||
break;
|
||||
|
||||
case SATURN_COMM_SEEK:
|
||||
this->lba = fad - 150;
|
||||
this->seek_lba = fad - 150;
|
||||
this->index = FindIndexInTOC(&this->toc, this->lba);
|
||||
//if (this->toc.tracks[this->index].type) {
|
||||
// this->lba -= 4;
|
||||
// this->seek_lba -= 4;
|
||||
//}
|
||||
this->state = Seek;
|
||||
this->speed = comm[10] == 1 ? 1 : 2;
|
||||
|
||||
printf("\x1b[32mSaturn: ");
|
||||
printf("Command Seek: FAD = %u, track = %u, speed = %u", fad, this->index + 1, this->speed);
|
||||
//printf(", command = %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X", comm[0], comm[1], comm[2], comm[3], comm[4], comm[5], comm[6], comm[7], comm[8], comm[9], comm[10], comm[11]);
|
||||
printf(" (%u)\n\x1b[0m", frame_cnt);
|
||||
break;
|
||||
|
||||
default:
|
||||
printf("\x1b[32mSaturn: ");
|
||||
printf("Command undefined, command = %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X", comm[0], comm[1], comm[2], comm[3], comm[4], comm[5], comm[6], comm[7], comm[8], comm[9], comm[10], comm[11]);
|
||||
printf(" (%u)\n\x1b[0m", frame_cnt);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void satcdd_t::SetChecksum(uint8_t* stat) {
|
||||
uint8_t sum = 0;
|
||||
for (int i = 0; i < 11; i++) sum += stat[i];
|
||||
stat[11] = ~sum;
|
||||
}
|
||||
|
||||
void satcdd_t::LBAToMSF(int lba, msf_t* msf) {
|
||||
msf->m = (lba / 75) / 60;
|
||||
msf->s = (lba / 75) % 60;
|
||||
msf->f = (lba % 75);
|
||||
}
|
||||
|
||||
int satcdd_t::GetFAD(uint8_t* cmd) {
|
||||
int fad = 0;
|
||||
fad |= cmd[3] << 0;
|
||||
fad |= cmd[2] << 8;
|
||||
fad |= cmd[1] << 16;
|
||||
return fad;
|
||||
}
|
||||
|
||||
uint8_t* satcdd_t::GetStatus() {
|
||||
return this->stat;
|
||||
}
|
||||
|
||||
int satcdd_t::SetCommand(uint8_t* data) {
|
||||
memcpy(this->comm, data, 12);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void satcdd_t::MakeSecureRingData(uint8_t *buf) {
|
||||
int i, j;
|
||||
uint16_t lfsr = 1;
|
||||
uint8_t a;
|
||||
for (i = 12; i < 2348; i++)
|
||||
{
|
||||
a = (i & 1) ? 0x59 : 0xa8;
|
||||
for (j = 0; j < 8; j++)
|
||||
{
|
||||
a ^= (lfsr & 1);
|
||||
a = (a >> 1) | (a << (7));
|
||||
|
||||
uint16_t x = (lfsr >> 1) ^ lfsr;
|
||||
lfsr |= x << 15;
|
||||
lfsr >>= 1;
|
||||
}
|
||||
buf[i] = a;
|
||||
}
|
||||
}
|
||||
|
||||
void satcdd_t::ReadData(uint8_t *buf)
|
||||
{
|
||||
if (this->toc.tracks[this->index].type && (this->lba >= 0))
|
||||
{
|
||||
|
||||
/*if (this->toc.chd_f)
|
||||
{
|
||||
int read_offset = 0;
|
||||
if (this->sectorSize != 2048)
|
||||
{
|
||||
read_offset += 16;
|
||||
}
|
||||
|
||||
mister_chd_read_sector(this->toc.chd_f, this->lba + this->toc.tracks[this->index].offset, 0, read_offset, 2048, buf, this->chd_hunkbuf, &this->chd_hunknum);
|
||||
}
|
||||
else*/ {
|
||||
if (this->sectorSize == 2048)
|
||||
{
|
||||
FileSeek(&this->toc.tracks[this->index].f, this->lba * 2048, SEEK_SET);
|
||||
FileReadAdv(&this->toc.tracks[this->index].f, buf, 2048);
|
||||
}
|
||||
else {
|
||||
FileSeek(&this->toc.tracks[this->index].f, this->lba * 2352, SEEK_SET);
|
||||
FileReadAdv(&this->toc.tracks[this->index].f, buf, 2352);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int satcdd_t::ReadCDDA(uint8_t *buf)
|
||||
{
|
||||
this->audioLength = 2352;
|
||||
if (this->audioFirst) this->audioLength += 4096 - 2352;
|
||||
|
||||
//printf("\x1b[32mMCD: AUDIO LENGTH %d LBA: %d INDEX: %d START: %d END %d\n\x1b[0m", this->audioLength, this->lba, this->index, this->toc.tracks[this->index].start, this->toc.tracks[this->index].end);
|
||||
//
|
||||
|
||||
/*if (this->isData)
|
||||
{
|
||||
return this->audioLength;
|
||||
}*/
|
||||
|
||||
int offs = 0;
|
||||
/*if (this->toc.chd_f)
|
||||
{
|
||||
for (int i = 0; i < this->audioLength / 2352; i++)
|
||||
{
|
||||
mister_chd_read_sector(this->toc.chd_f, this->chd_audio_read_lba + this->toc.tracks[this->index].offset, 2352 * i, 0, 2352, buf, this->chd_hunkbuf, &this->chd_hunknum);
|
||||
}
|
||||
|
||||
//CHD audio requires byteswap. There's probably a better way to do this...
|
||||
|
||||
for (int swapidx = 0; swapidx < this->audioLength; swapidx += 2)
|
||||
{
|
||||
uint8_t temp = buf[swapidx];
|
||||
buf[swapidx] = buf[swapidx + 1];
|
||||
buf[swapidx + 1] = temp;
|
||||
}
|
||||
|
||||
if ((this->audioLength / 2352) > 1)
|
||||
{
|
||||
this->chd_audio_read_lba++;
|
||||
}
|
||||
|
||||
}
|
||||
else*/ if (this->toc.tracks[this->index].f.opened()) {
|
||||
offs = (this->lba * 2352) - this->toc.tracks[this->index].offset;
|
||||
if (!this->audioFirst) offs += 4096 - 2352;
|
||||
FileSeek(&this->toc.tracks[this->index].f, offs, SEEK_SET);
|
||||
FileReadAdv(&this->toc.tracks[this->index].f, buf, this->audioLength);
|
||||
}
|
||||
|
||||
/*printf("\x1b[32mSaturn: ");
|
||||
printf("Read CD DA sector: Length = %u, First = %u, offset = %u", this->audioLength, this->audioFirst, offs);
|
||||
printf(" (%u)\n\x1b[0m", frame_cnt);*/
|
||||
|
||||
this->audioFirst = 0;
|
||||
|
||||
return this->audioLength;
|
||||
}
|
||||
|
||||
int satcdd_t::DataSectorSend(uint8_t* header, int speed)
|
||||
{
|
||||
int len = 2352;
|
||||
uint8_t* data_ptr = cd_buf + 2;
|
||||
|
||||
if (header) {
|
||||
memcpy(data_ptr + 12 , header, 4);
|
||||
ReadData(data_ptr + 16);
|
||||
}
|
||||
else {
|
||||
ReadData(data_ptr);
|
||||
}
|
||||
cd_buf[0] = cd_buf[1] = (speed == 2 ? 0x01 : 0x00);
|
||||
|
||||
if (SendData)
|
||||
return SendData(cd_buf, len + 2, CD_DATA_IO_INDEX /*| (!header ? 2 : 0) | (speed == 2 ? 1 : 0)*/);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int satcdd_t::AudioSectorSend()
|
||||
{
|
||||
int len = 2352;
|
||||
uint8_t* data_ptr = cd_buf + 2;
|
||||
|
||||
len = ReadCDDA(data_ptr);
|
||||
cd_buf[0] = cd_buf[1] = 0x02;
|
||||
|
||||
if (SendData)
|
||||
return SendData(cd_buf, len + 2, CD_DATA_IO_INDEX /*| (!header ? 2 : 0) | (speed == 2 ? 1 : 0)*/);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int satcdd_t::RingDataSend(uint8_t* header, int speed)
|
||||
{
|
||||
uint8_t* data_ptr = cd_buf + 2;
|
||||
|
||||
if (header) {
|
||||
MakeSecureRingData(data_ptr);
|
||||
memcpy(data_ptr + 12, header, 12);
|
||||
memset(data_ptr + 2348, 0, 4);
|
||||
}
|
||||
cd_buf[0] = cd_buf[1] = (!header ? 2 : 0) | (speed == 2 ? 1 : 0);
|
||||
|
||||
if (SendData)
|
||||
return SendData(cd_buf, 2352 + 2, CD_DATA_IO_INDEX);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
16
user_io.cpp
16
user_io.cpp
@@ -287,6 +287,14 @@ char is_electron()
|
||||
return (is_electron_type == 1);
|
||||
}
|
||||
|
||||
static int is_saturn_type = 0;
|
||||
char is_saturn()
|
||||
{
|
||||
if (!is_saturn_type) is_saturn_type = strcasecmp(core_name, "Saturn") ? 2 : 1;
|
||||
return (is_saturn_type == 1);
|
||||
}
|
||||
|
||||
|
||||
static int is_no_type = 0;
|
||||
static int disable_osd = 0;
|
||||
char has_menu()
|
||||
@@ -2691,7 +2699,8 @@ void user_io_send_buttons(char force)
|
||||
{
|
||||
if (is_minimig()) minimig_reset();
|
||||
if (is_megacd()) mcd_reset();
|
||||
if (is_pce()) pcecd_reset();
|
||||
if (is_pce()) pcecd_reset();
|
||||
if (is_saturn()) saturn_reset();
|
||||
if (is_x86()) x86_init();
|
||||
ResetUART();
|
||||
}
|
||||
@@ -3013,6 +3022,10 @@ void user_io_poll()
|
||||
{
|
||||
psx_fill_blanksave(buffer[disk], lba, blks);
|
||||
}
|
||||
else if (is_saturn())
|
||||
{
|
||||
saturn_fill_blanksave(buffer[disk], lba);
|
||||
}
|
||||
else
|
||||
{
|
||||
memset(buffer[disk], -1, sizeof(buffer[disk]));
|
||||
@@ -3349,6 +3362,7 @@ void user_io_poll()
|
||||
|
||||
if (is_megacd()) mcd_poll();
|
||||
if (is_pce()) pcecd_poll();
|
||||
if (is_saturn()) saturn_poll();
|
||||
process_ss(0);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user