Merge NeoGeo support code.
This commit is contained in:
1
Makefile
1
Makefile
@@ -31,6 +31,7 @@ CPP_SRC = $(wildcard *.cpp) \
|
||||
$(wildcard ./support/st/*.cpp) \
|
||||
$(wildcard ./support/x86/*.cpp) \
|
||||
$(wildcard ./support/snes/*.cpp) \
|
||||
$(wildcard ./support/neogeo/*.cpp) \
|
||||
lib/lodepng/lodepng.cpp
|
||||
|
||||
IMG = $(wildcard *.png)
|
||||
|
||||
@@ -78,6 +78,8 @@
|
||||
<ClCompile Include="support\minimig\minimig_config.cpp" />
|
||||
<ClCompile Include="support\minimig\minimig_fdd.cpp" />
|
||||
<ClCompile Include="support\minimig\minimig_hdd.cpp" />
|
||||
<ClCompile Include="support\neogeo\graphics.cpp" />
|
||||
<ClCompile Include="support\neogeo\loader.cpp" />
|
||||
<ClCompile Include="support\sharpmz\sharpmz.cpp" />
|
||||
<ClCompile Include="support\snes\snes.cpp" />
|
||||
<ClCompile Include="support\st\st_ikbd.cpp" />
|
||||
@@ -128,6 +130,8 @@
|
||||
<ClInclude Include="support\minimig\minimig_fdd.h" />
|
||||
<ClInclude Include="support\minimig\minimig_hdd.h" />
|
||||
<ClInclude Include="support\minimig\minimig_hdd_internal.h" />
|
||||
<ClInclude Include="support\neogeo\graphics.h" />
|
||||
<ClInclude Include="support\neogeo\loader.h" />
|
||||
<ClInclude Include="support\sharpmz\sharpmz.h" />
|
||||
<ClInclude Include="support\snes\snes.h" />
|
||||
<ClInclude Include="support\st\st_ikbd.h" />
|
||||
|
||||
@@ -142,6 +142,12 @@
|
||||
<ClCompile Include="video.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="support\neogeo\graphics.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="support\neogeo\loader.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="battery.h">
|
||||
@@ -288,5 +294,11 @@
|
||||
<ClInclude Include="lib\imlib2\Imlib2.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="support\neogeo\graphics.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="support\neogeo\loader.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
38
menu.cpp
38
menu.cpp
@@ -1574,10 +1574,25 @@ void HandleUI(void)
|
||||
|
||||
case MENU_8BIT_MAIN_FILE_SELECTED:
|
||||
printf("File selected: %s\n", SelectedPath);
|
||||
user_io_store_filename(SelectedPath);
|
||||
user_io_file_tx(SelectedPath, user_io_ext_idx(SelectedPath, fs_pFileExt) << 6 | ioctl_index, opensave);
|
||||
if(user_io_use_cheats()) cheats_init(SelectedPath, user_io_get_file_crc());
|
||||
menustate = MENU_NONE1;
|
||||
if (is_neogeo_core())
|
||||
{
|
||||
if (!neogeo_romset_tx(SelectedPath))
|
||||
{
|
||||
OsdSetTitle("Message", 0);
|
||||
OsdEnable(0); // do not disable keyboard
|
||||
menu_timer = GetTimer(2000);
|
||||
menustate = MENU_INFO;
|
||||
} else {
|
||||
menustate = MENU_NONE1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
user_io_store_filename(SelectedPath);
|
||||
user_io_file_tx(SelectedPath, user_io_ext_idx(SelectedPath, fs_pFileExt) << 6 | ioctl_index, opensave);
|
||||
if (user_io_use_cheats()) cheats_init(SelectedPath, user_io_get_file_crc());
|
||||
menustate = MENU_NONE1;
|
||||
}
|
||||
break;
|
||||
|
||||
case MENU_8BIT_MAIN_IMAGE_SELECTED:
|
||||
@@ -1591,6 +1606,21 @@ void HandleUI(void)
|
||||
user_io_set_index(user_io_ext_idx(SelectedPath, fs_pFileExt) << 6 | (menusub + 1));
|
||||
user_io_file_mount(SelectedPath, drive_num);
|
||||
}
|
||||
|
||||
if (is_neogeo_core())
|
||||
{
|
||||
// ElectronAsh.
|
||||
strcpy(SelectedPath + strlen(SelectedPath) - 3, "CUE");
|
||||
printf("Checking for presence of CUE file %s\n", SelectedPath);
|
||||
if (user_io_file_mount(SelectedPath, 1))
|
||||
{
|
||||
printf("CUE file found and mounted.\n");
|
||||
parse_cue_file();
|
||||
char str[2] = "";
|
||||
neogeo_romset_tx(str);
|
||||
}
|
||||
}
|
||||
|
||||
menustate = SelectedPath[0] ? MENU_NONE1 : MENU_8BIT_MAIN1;
|
||||
break;
|
||||
|
||||
|
||||
@@ -19,3 +19,6 @@
|
||||
|
||||
// SNES support
|
||||
#include "support/snes/snes.h"
|
||||
|
||||
// NeoGeo support
|
||||
#include "support/neogeo/loader.h"
|
||||
79
support/neogeo/graphics.cpp
Normal file
79
support/neogeo/graphics.cpp
Normal file
@@ -0,0 +1,79 @@
|
||||
// Moves bytes around so that the fix graphics are stored in a way that
|
||||
// takes advantage of the SDRAM 16-bit bus
|
||||
// Part of Neogeo_MiSTer
|
||||
// (C) 2019 Sean 'furrtek' Gonsalves
|
||||
|
||||
#include "graphics.h"
|
||||
#include "../../spi.h"
|
||||
|
||||
void spr_convert(uint8_t* buf_in, uint8_t* buf_out, unsigned int size)
|
||||
{
|
||||
/*
|
||||
In C ROMs, a word provides two bitplanes for an 8-pixel wide line
|
||||
They're used in pairs to provide 32 bits at once (all four bitplanes)
|
||||
For one sprite tile, bytes are used like this: ([...] represents one 8-pixel wide line)
|
||||
Even ROM Odd ROM
|
||||
[ 40 41 ][ 00 01 ] [ 42 43 ][ 02 03 ]
|
||||
[ 44 45 ][ 04 05 ] [ 46 47 ][ 06 07 ]
|
||||
[ 48 49 ][ 08 09 ] [ 4A 4B ][ 0A 0B ]
|
||||
[ 4C 4D ][ 0C 0D ] [ 4E 4F ][ 0E 0F ]
|
||||
[ 50 51 ][ 10 11 ] [ 52 53 ][ 12 13 ]
|
||||
... ...
|
||||
The data read for a given tile line (16 pixels) is always the same, only the rendering order of the pixels can change
|
||||
To take advantage of the SDRAM burst read feature, the data can be loaded so that all 16 pixels of a tile
|
||||
line can be read sequentially: () are 16-bit words, [] is the 4-word burst read
|
||||
[(40 41) (00 01) (42 43) (02 03)]
|
||||
[(44 45) (04 05) (46 47) (06 07)]...
|
||||
Word interleaving is done on the FPGA side to mix the two C ROMs data (even/odd)
|
||||
|
||||
In: FEDCBA9876 54321 0
|
||||
Out: FEDCBA9876 15432 0
|
||||
*/
|
||||
for (unsigned int i = 0; i < size; i++)
|
||||
buf_out[i] = buf_in[(i & 0xFFC0) | (i & 1) | ((i >> 1) & 0x1E) | (((i & 2) ^ 2) << 4)];
|
||||
|
||||
/*
|
||||
0 <- 20
|
||||
1 <- 21
|
||||
2 <- 00
|
||||
3 <- 01
|
||||
4 <- 22
|
||||
5 <- 23
|
||||
6 <- 02
|
||||
7 <- 03
|
||||
...
|
||||
|
||||
00 -> 02
|
||||
01 -> 03
|
||||
02 -> 06
|
||||
03 -> 07
|
||||
...
|
||||
*/
|
||||
}
|
||||
|
||||
void fix_convert(uint8_t* buf_in, uint8_t* buf_out, unsigned int size)
|
||||
{
|
||||
/*
|
||||
In S ROMs, a byte provides two pixels
|
||||
For one fix tile, bytes are used like this: ([...] represents a pair of pixels)
|
||||
[10][18][00][08]
|
||||
[11][19][01][09]
|
||||
[12][1A][02][0A]
|
||||
[13][1B][03][0B]
|
||||
[14][1C][04][0C]
|
||||
[15][1D][05][0D]
|
||||
[16][1E][06][0E]
|
||||
[17][1F][07][0F]
|
||||
The data read for a given tile line (8 pixels) is always the same
|
||||
To take advantage of the SDRAM burst read feature, the data can be loaded so that all 8 pixels of a tile
|
||||
line can be read sequentially: () are 16-bit words, [] is the 2-word burst read
|
||||
[(10 18) (00 08)]
|
||||
[(11 19) (01 09)]...
|
||||
|
||||
In: FEDCBA9876543210
|
||||
Out: FEDCBA9876510432
|
||||
*/
|
||||
for (unsigned int i = 0; i < size; i++)
|
||||
buf_out[i] = buf_in[(i & 0xFFE0) | ((i >> 2) & 7) | ((i & 1) << 3) | (((i & 2) << 3) ^ 0x10)];
|
||||
}
|
||||
|
||||
4
support/neogeo/graphics.h
Normal file
4
support/neogeo/graphics.h
Normal file
@@ -0,0 +1,4 @@
|
||||
#include "../../file_io.h"
|
||||
|
||||
void spr_convert(uint8_t* buf_in, uint8_t* buf_out, unsigned int size);
|
||||
void fix_convert(uint8_t* buf_in, uint8_t* buf_out, unsigned int size);
|
||||
361
support/neogeo/loader.cpp
Normal file
361
support/neogeo/loader.cpp
Normal file
@@ -0,0 +1,361 @@
|
||||
// Part of Neogeo_MiSTer
|
||||
// (C) 2019 Sean 'furrtek' Gonsalves
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/stat.h>
|
||||
#include <time.h> // clock_gettime, CLOCK_REALTIME
|
||||
#include "graphics.h"
|
||||
#include "loader.h"
|
||||
#include "../../sxmlc.h"
|
||||
#include "../../user_io.h"
|
||||
#include "../../osd.h"
|
||||
|
||||
bool checked_ok;
|
||||
|
||||
void neogeo_osd_progress(const char* name, unsigned int progress) {
|
||||
char progress_buf[30 + 1];
|
||||
|
||||
// OSD width - width of white bar on the left - max width of file name = 32 - 2 - 11 - 1 = 18
|
||||
progress = (progress * 18) >> 8;
|
||||
if (progress >= 18) progress = 18;
|
||||
|
||||
// ##############################
|
||||
// NNNNNNNNNNN-PPPPPPPPPPPPPPPPPP
|
||||
memset(progress_buf, ' ', 30);
|
||||
memcpy(progress_buf, name, strlen(name));
|
||||
for (unsigned int i = 0; i < progress; i++)
|
||||
progress_buf[12 + i] = '#';
|
||||
progress_buf[30] = 0;
|
||||
|
||||
OsdWrite(OsdGetSize() - 1, progress_buf, 0);
|
||||
}
|
||||
|
||||
int neogeo_file_tx(const char* romset, const char* name, unsigned char neo_file_type, unsigned char index, unsigned long offset, unsigned long size)
|
||||
{
|
||||
fileTYPE f = {};
|
||||
uint8_t buf[4096]; // Same in user_io_file_tx
|
||||
uint8_t buf_out[4096];
|
||||
static char name_buf[256];
|
||||
unsigned long bytes2send = size;
|
||||
struct timespec ts1, ts2; // DEBUG PROFILING
|
||||
long us_acc = 0; // DEBUG PROFILING
|
||||
|
||||
if (!bytes2send) return 0;
|
||||
|
||||
strcpy(name_buf, "/media/fat/NeoGeo/");
|
||||
if (strlen(romset)) {
|
||||
strcat(name_buf, romset);
|
||||
strcat(name_buf, "/");
|
||||
}
|
||||
strcat(name_buf, name);
|
||||
|
||||
if (!FileOpen(&f, name_buf, 0)) return 0;
|
||||
|
||||
FileSeek(&f, offset, SEEK_SET);
|
||||
|
||||
printf("Loading %s (offset %lu, size %lu, type %u) with index 0x%02X\n", name, offset, bytes2send, neo_file_type, index);
|
||||
|
||||
// Put pairs of bitplanes in the correct order for the core
|
||||
if (neo_file_type == NEO_FILE_SPR) index ^= 1;
|
||||
// set index byte
|
||||
user_io_set_index(index);
|
||||
|
||||
// prepare transmission of new file
|
||||
EnableFpga();
|
||||
spi8(UIO_FILE_TX);
|
||||
spi8(0xff);
|
||||
DisableFpga();
|
||||
|
||||
while (bytes2send)
|
||||
{
|
||||
uint16_t chunk = (bytes2send > sizeof(buf)) ? sizeof(buf) : bytes2send;
|
||||
|
||||
FileReadAdv(&f, buf, chunk);
|
||||
|
||||
EnableFpga();
|
||||
spi8(UIO_FILE_TX_DAT);
|
||||
|
||||
if (neo_file_type == NEO_FILE_RAW) {
|
||||
spi_write(buf, chunk, 1);
|
||||
} else if (neo_file_type == NEO_FILE_8BIT) {
|
||||
spi_write(buf, chunk, 0);
|
||||
} else {
|
||||
|
||||
if (neo_file_type == NEO_FILE_FIX)
|
||||
fix_convert(buf, buf_out, sizeof(buf_out));
|
||||
else if (neo_file_type == NEO_FILE_SPR)
|
||||
spr_convert(buf, buf_out, sizeof(buf_out));
|
||||
|
||||
clock_gettime(CLOCK_REALTIME, &ts1); // DEBUG PROFILING
|
||||
spi_write(buf_out, chunk, 1);
|
||||
clock_gettime(CLOCK_REALTIME, &ts2); // DEBUG PROFILING
|
||||
|
||||
if (ts2.tv_nsec < ts1.tv_nsec) { // DEBUG PROFILING
|
||||
ts2.tv_nsec += 1000000000;
|
||||
ts2.tv_sec--;
|
||||
}
|
||||
|
||||
us_acc += ((ts2.tv_nsec - ts1.tv_nsec) / 1000); // DEBUG PROFILING
|
||||
}
|
||||
|
||||
DisableFpga();
|
||||
|
||||
neogeo_osd_progress(name, 256 - ((bytes2send << 8) / size));
|
||||
bytes2send -= chunk;
|
||||
}
|
||||
|
||||
// DEBUG PROFILING
|
||||
printf("Gfx spi_write us total: %09ld\n", us_acc);
|
||||
// mslug all C ROMs:
|
||||
// spr_convert: 37680*4 = 150720us = 0.150s
|
||||
// spi_write: 2300766*4 = 9203064us = 9.2s !
|
||||
|
||||
FileClose(&f);
|
||||
|
||||
// signal end of transmission
|
||||
EnableFpga();
|
||||
spi8(UIO_FILE_TX);
|
||||
spi8(0x00);
|
||||
DisableFpga();
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int xml_check_files(XMLEvent evt, const XMLNode* node, SXML_CHAR* text, const int n, SAX_Data* sd)
|
||||
{
|
||||
const char* romset = (const char*)sd->user;
|
||||
static int in_correct_romset = 0;
|
||||
static char full_path[256];
|
||||
|
||||
switch (evt)
|
||||
{
|
||||
case XML_EVENT_START_NODE:
|
||||
if (!strcasecmp(node->tag, "romset")) {
|
||||
if (!strcasecmp(node->attributes[0].value, romset)) {
|
||||
printf("Romset %s found !\n", romset);
|
||||
in_correct_romset = 1;
|
||||
}
|
||||
else {
|
||||
in_correct_romset = 0;
|
||||
}
|
||||
}
|
||||
if (in_correct_romset) {
|
||||
if (!strcasecmp(node->tag, "file")) {
|
||||
for (int i = 0; i < node->n_attributes; i++) {
|
||||
if (!strcasecmp(node->attributes[i].name, "name")) {
|
||||
struct stat64 st;
|
||||
sprintf(full_path, "%s/neogeo/%s/%s", getRootDir(), romset, node->attributes[i].value);
|
||||
if (!stat64(full_path, &st)) {
|
||||
printf("Found %s\n", full_path);
|
||||
break;
|
||||
}
|
||||
else {
|
||||
printf("Missing %s\n", full_path);
|
||||
sprintf(full_path, "Missing %s !", node->attributes[i].value);
|
||||
OsdWrite(OsdGetSize() - 1, full_path, 0);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case XML_EVENT_END_NODE:
|
||||
if (in_correct_romset) {
|
||||
if (!strcasecmp(node->tag, "romset")) {
|
||||
checked_ok = true;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (!strcasecmp(node->tag, "romsets")) {
|
||||
printf("Couldn't find romset %s\n", romset);
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
|
||||
case XML_EVENT_ERROR:
|
||||
printf("XML parse: %s: ERROR %d\n", text, n);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static int xml_load_files(XMLEvent evt, const XMLNode* node, SXML_CHAR* text, const int n, SAX_Data* sd)
|
||||
{
|
||||
const char* romset = (const char*)sd->user;
|
||||
static char file_name[16 + 1] { "" };
|
||||
static int in_correct_romset = 0;
|
||||
static int in_file = 0;
|
||||
static unsigned char file_index = 0;
|
||||
static char file_type = 0;
|
||||
static unsigned long int file_offset = 0, file_size = 0;
|
||||
static unsigned char hw_type = 0, use_pcm = 0;
|
||||
|
||||
switch (evt)
|
||||
{
|
||||
case XML_EVENT_START_NODE:
|
||||
if (!strcasecmp(node->tag, "romset")) {
|
||||
for (int i = 0; i < node->n_attributes; i++) {
|
||||
if (!strcasecmp(node->attributes[i].name, "name")) {
|
||||
if (!strcasecmp(node->attributes[i].value, romset)) {
|
||||
printf("Romset %s found !\n", romset);
|
||||
in_correct_romset = 1;
|
||||
} else {
|
||||
in_correct_romset = 0;
|
||||
}
|
||||
} else if (!strcasecmp(node->attributes[i].name, "hw")) {
|
||||
hw_type = atoi(node->attributes[i].value);
|
||||
} else if (!strcasecmp(node->attributes[i].name, "pcm")) {
|
||||
use_pcm = atoi(node->attributes[i].value);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (in_correct_romset) {
|
||||
if (!strcasecmp(node->tag, "file")) {
|
||||
for (int i = 0; i < node->n_attributes; i++) {
|
||||
if (!strcasecmp(node->attributes[i].name, "name"))
|
||||
strncpy(file_name, node->attributes[i].value, 16);
|
||||
|
||||
if (!strcasecmp(node->attributes[i].name, "type")) {
|
||||
file_type = *node->attributes[i].value;
|
||||
if (file_type == 'S')
|
||||
file_type = NEO_FILE_FIX;
|
||||
else if (file_type == 'C')
|
||||
file_type = NEO_FILE_SPR;
|
||||
else if (file_type == 'M')
|
||||
file_type = NEO_FILE_8BIT;
|
||||
else
|
||||
file_type = NEO_FILE_RAW;
|
||||
}
|
||||
|
||||
if (!strcasecmp(node->attributes[i].name, "index"))
|
||||
file_index = atoi(node->attributes[i].value);
|
||||
|
||||
if (!strcasecmp(node->attributes[i].name, "offset"))
|
||||
file_offset = strtol(node->attributes[i].value, NULL, 0);
|
||||
|
||||
if (!strcasecmp(node->attributes[i].name, "size"))
|
||||
file_size = strtol(node->attributes[i].value, NULL, 0);
|
||||
}
|
||||
in_file = 1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case XML_EVENT_END_NODE:
|
||||
if (in_correct_romset) {
|
||||
if (!strcasecmp(node->tag, "romset")) {
|
||||
printf("Setting cart hardware type to %u\n", hw_type);
|
||||
user_io_8bit_set_status(((uint32_t)hw_type & 3) << 24, 0x03000000);
|
||||
printf("Setting cart to%s use the PCM chip\n", use_pcm ? "" : " not");
|
||||
user_io_8bit_set_status(((uint32_t)use_pcm & 1) << 26, 0x04000000);
|
||||
return 0;
|
||||
} else if (!strcasecmp(node->tag, "file")) {
|
||||
if (in_file)
|
||||
neogeo_file_tx(romset, file_name, file_type, file_index, file_offset, file_size);
|
||||
in_file = 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case XML_EVENT_ERROR:
|
||||
printf("XML parse: %s: ERROR %d\n", text, n);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int neogeo_romset_tx(char* name) {
|
||||
char romset[8 + 1];
|
||||
int system_type;
|
||||
static char full_path[1024];
|
||||
|
||||
memset(romset, 0, sizeof(romset));
|
||||
|
||||
system_type = (user_io_8bit_set_status(0, 0) >> 1) & 3;
|
||||
printf("System type: %u\n", system_type);
|
||||
|
||||
user_io_8bit_set_status(1, 1); // Maintain reset
|
||||
|
||||
// Look for the romset's file list in romsets.xml
|
||||
if (!(system_type & 2)) {
|
||||
// Get romset name from path (which should point to a .p1 or .ep1 file)
|
||||
char *p = strrchr(name, '/');
|
||||
if (!p) return 0;
|
||||
*p = 0;
|
||||
p = strrchr(name, '/');
|
||||
if (!p) return 0;
|
||||
strncpy(romset, p + 1, strlen(p + 1));
|
||||
|
||||
sprintf(full_path, "%s/neogeo/romsets.xml", getRootDir());
|
||||
SAX_Callbacks sax;
|
||||
SAX_Callbacks_init(&sax);
|
||||
|
||||
checked_ok = false;
|
||||
sax.all_event = xml_check_files;
|
||||
XMLDoc_parse_file_SAX(full_path, &sax, romset);
|
||||
if (!checked_ok) return 0;
|
||||
|
||||
sax.all_event = xml_load_files;
|
||||
XMLDoc_parse_file_SAX(full_path, &sax, romset);
|
||||
}
|
||||
|
||||
// Load system ROMs
|
||||
if (strcmp(romset, "debug")) {
|
||||
// Not loading the special 'debug' romset
|
||||
struct stat64 st;
|
||||
if (!(system_type & 2)) {
|
||||
sprintf(full_path, "%s/neogeo/uni-bios.rom", getRootDir());
|
||||
if (!stat64(full_path, &st)) {
|
||||
// Autoload Unibios for cart systems if present
|
||||
neogeo_file_tx("", "uni-bios.rom", NEO_FILE_RAW, 0, 0, 0x20000);
|
||||
} else {
|
||||
// Otherwise load normal system roms
|
||||
if (system_type == 0)
|
||||
neogeo_file_tx("", "neo-epo.sp1", NEO_FILE_RAW, 0, 0, 0x20000);
|
||||
else
|
||||
neogeo_file_tx("", "sp-s2.sp1", NEO_FILE_RAW, 0, 0, 0x20000);
|
||||
}
|
||||
} else if (system_type == 2) {
|
||||
// NeoGeo CD
|
||||
neogeo_file_tx("", "top-sp1.bin", NEO_FILE_RAW, 0, 0, 0x80000);
|
||||
} else {
|
||||
// NeoGeo CDZ
|
||||
neogeo_file_tx("", "neocd.bin", NEO_FILE_RAW, 0, 0, 0x80000);
|
||||
}
|
||||
}
|
||||
|
||||
if (!(system_type & 2))
|
||||
neogeo_file_tx("", "sfix.sfix", NEO_FILE_FIX, 2, 0, 0x10000);
|
||||
neogeo_file_tx("", "000-lo.lo", NEO_FILE_8BIT, 1, 0, 0x10000);
|
||||
|
||||
if (!strcmp(romset, "kof95")) {
|
||||
printf("Enabled sprite gfx gap hack for kof95\n");
|
||||
user_io_8bit_set_status(0x10000000, 0x30000000);
|
||||
} else if (!strcmp(romset, "whp")) {
|
||||
printf("Enabled sprite gfx gap hack for whp\n");
|
||||
user_io_8bit_set_status(0x20000000, 0x30000000);
|
||||
} else if (!strcmp(romset, "kizuna")) {
|
||||
printf("Enabled sprite gfx gap hack for kizuna\n");
|
||||
user_io_8bit_set_status(0x30000000, 0x30000000);
|
||||
} else
|
||||
user_io_8bit_set_status(0x00000000, 0x30000000);
|
||||
|
||||
if (!(system_type & 2))
|
||||
FileGenerateSavePath(name, (char*)full_path);
|
||||
else
|
||||
FileGenerateSavePath("ngcd", (char*)full_path);
|
||||
user_io_file_mount((char*)full_path, 2, 1);
|
||||
|
||||
user_io_8bit_set_status(0, 1); // Release reset
|
||||
|
||||
return 1;
|
||||
}
|
||||
9
support/neogeo/loader.h
Normal file
9
support/neogeo/loader.h
Normal file
@@ -0,0 +1,9 @@
|
||||
#include "../../file_io.h"
|
||||
|
||||
#define NEO_FILE_RAW 0
|
||||
#define NEO_FILE_8BIT 1
|
||||
#define NEO_FILE_FIX 2
|
||||
#define NEO_FILE_SPR 3
|
||||
|
||||
extern bool checked_ok;
|
||||
int neogeo_romset_tx(char* name);
|
||||
486
user_io.cpp
486
user_io.cpp
@@ -69,6 +69,63 @@ static bool caps_status = 0;
|
||||
static bool num_status = 0;
|
||||
static bool scrl_status = 0;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
bool track_active;
|
||||
bool pregap_present;
|
||||
uint8_t pre_m; // Actual "PREGAP".
|
||||
uint8_t pre_s;
|
||||
uint8_t pre_f;
|
||||
bool ind0_present;
|
||||
uint8_t ind0_m; // "Pregap" INDEX 00
|
||||
uint8_t ind0_s;
|
||||
uint8_t ind0_f;
|
||||
uint8_t ind1_m; // "Track Start" INDEX 01
|
||||
uint8_t ind1_s;
|
||||
uint8_t ind1_f;
|
||||
uint8_t type; // 0==AUDIO. 4==DATA.
|
||||
int bytes_per_sec;
|
||||
} cd_track_t;
|
||||
|
||||
// Track 1-99, so entry zero is unused / ignored.
|
||||
cd_track_t cd_trackinfo[100];
|
||||
|
||||
uint8_t cd_first_track;
|
||||
uint8_t cd_last_track;
|
||||
|
||||
static inline uint32_t msf_to_lba(uint8_t m, uint8_t s, uint8_t f)
|
||||
{
|
||||
return (m*60*75) + (s*75) + f;
|
||||
}
|
||||
|
||||
uint32_t dec_2_bcd(uint32_t a)
|
||||
{
|
||||
uint32_t result = 0;
|
||||
int shift = 0;
|
||||
|
||||
while (a != 0)
|
||||
{
|
||||
result |= (a % 10) << shift;
|
||||
a /= 10;
|
||||
shift += 4;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
uint32_t bcd_2_dec(uint32_t a)
|
||||
{
|
||||
uint32_t result = 0;
|
||||
uint32_t scale = 1;
|
||||
|
||||
while (a != 0)
|
||||
{
|
||||
result += (a & 0x0f) * scale;
|
||||
a >>= 4;
|
||||
scale *= 10;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static char last_filename[1024] = {};
|
||||
void user_io_store_filename(char *filename)
|
||||
{
|
||||
@@ -189,14 +246,25 @@ char is_snes_core()
|
||||
return (is_snes_type == 1);
|
||||
}
|
||||
|
||||
static int is_cpc_type = 0;
|
||||
char is_cpc_core()
|
||||
{
|
||||
return !strcasecmp(core_name, "amstrad");
|
||||
if (!is_cpc_type) is_cpc_type = strcasecmp(core_name, "amstrad") ? 2 : 1;
|
||||
return (is_cpc_type == 1);
|
||||
}
|
||||
|
||||
static int is_zx81_type = 0;
|
||||
char is_zx81_core()
|
||||
{
|
||||
return !strcasecmp(core_name, "zx81");
|
||||
if (!is_zx81_type) is_zx81_type = strcasecmp(core_name, "zx81") ? 2 : 1;
|
||||
return (is_zx81_type == 1);
|
||||
}
|
||||
|
||||
static int is_neogeo_type = 0;
|
||||
char is_neogeo_core()
|
||||
{
|
||||
if (!is_neogeo_type) is_neogeo_type = strcasecmp(core_name, "neogeo") ? 2 : 1;
|
||||
return (is_neogeo_type == 1);
|
||||
}
|
||||
|
||||
static int is_no_type = 0;
|
||||
@@ -215,6 +283,9 @@ static void user_io_read_core_name()
|
||||
is_x86_type = 0;
|
||||
is_no_type = 0;
|
||||
is_snes_type = 0;
|
||||
is_cpc_type = 0;
|
||||
is_zx81_type = 0;
|
||||
is_neogeo_type = 0;
|
||||
core_name[0] = 0;
|
||||
|
||||
// get core name
|
||||
@@ -822,10 +893,11 @@ void user_io_sd_set_config(void)
|
||||
}
|
||||
|
||||
// read 8+32 bit sd card status word from FPGA
|
||||
uint16_t user_io_sd_get_status(uint32_t *lba)
|
||||
uint16_t user_io_sd_get_status(uint32_t *lba, uint16_t *req_type)
|
||||
{
|
||||
uint32_t s;
|
||||
uint16_t c;
|
||||
uint16_t req = 0;
|
||||
|
||||
spi_uio_cmd_cont(UIO_GET_SDSTAT);
|
||||
if (io_ver)
|
||||
@@ -833,6 +905,7 @@ uint16_t user_io_sd_get_status(uint32_t *lba)
|
||||
c = spi_w(0);
|
||||
s = spi_w(0);
|
||||
s = (s & 0xFFFF) | (((uint32_t)spi_w(0))<<16);
|
||||
req = spi_w(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -842,12 +915,16 @@ uint16_t user_io_sd_get_status(uint32_t *lba)
|
||||
s = (s << 8) | spi_in();
|
||||
s = (s << 8) | spi_in();
|
||||
s = (s << 8) | spi_in();
|
||||
req = spi_in();
|
||||
}
|
||||
DisableIO();
|
||||
|
||||
if (lba)
|
||||
*lba = s;
|
||||
|
||||
if (req)
|
||||
*req_type = req;
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
@@ -1609,6 +1686,225 @@ static int coldreset_req = 0;
|
||||
|
||||
static uint32_t res_timer = 0;
|
||||
|
||||
uint8_t cd_lba_to_track(uint32_t req_lba) {
|
||||
uint8_t track=1;
|
||||
for (track=1; track<=cd_last_track; track++) {
|
||||
uint32_t toc_lba = msf_to_lba(cd_trackinfo[track].ind1_m, cd_trackinfo[track].ind1_s, cd_trackinfo[track].ind1_f); // Convert track MSF to LBA.
|
||||
//printf("TOC Track LBA: %08d\n", toc_lba);
|
||||
if (req_lba > toc_lba) continue; // See if the TOC LBA is > the requested LBA.
|
||||
else break;
|
||||
}
|
||||
return track-1; // The start LBA of the PREVIOUS track checked was lower than our requested LBA.
|
||||
}
|
||||
|
||||
int cue_pt = 0;
|
||||
char cue_getch()
|
||||
{
|
||||
static uint8_t buf[512];
|
||||
if (!(cue_pt & 0x1ff)) FileReadSec(&sd_image[1], buf);
|
||||
if (cue_pt >= sd_image[1].size) return 0;
|
||||
return buf[(cue_pt++) & 0x1ff];
|
||||
}
|
||||
|
||||
char cue_readline(char *buffer)
|
||||
{
|
||||
char my_char = 0;
|
||||
bool ret = 0;
|
||||
int char_count = 0;
|
||||
|
||||
for (int i=0; i<1024; i++) {
|
||||
ret = ( my_char = cue_getch() );
|
||||
if (my_char!=0x20) { // Ditch the spaces.
|
||||
buffer[char_count] = my_char;
|
||||
if (ret==0 || my_char==0x0A) {
|
||||
buffer[char_count+1] = 0x00; // Null terminator.
|
||||
break;
|
||||
}
|
||||
else char_count++;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void parse_cue_file(void)
|
||||
{
|
||||
int i_num, i_min, i_sec, i_frame, bytes_per_sec = 0;
|
||||
|
||||
// Clear the trackinfo before starting.
|
||||
for (int i=0;i<=99;i++)
|
||||
{
|
||||
cd_trackinfo[i].track_active = 0;
|
||||
cd_trackinfo[i].pregap_present = 0;
|
||||
cd_trackinfo[i].pre_m = 0;
|
||||
cd_trackinfo[i].pre_s = 0;
|
||||
cd_trackinfo[i].pre_f = 0;
|
||||
cd_trackinfo[i].ind0_present = 0;
|
||||
cd_trackinfo[i].ind0_m = 0;
|
||||
cd_trackinfo[i].ind0_s = 0;
|
||||
cd_trackinfo[i].ind0_f = 0;
|
||||
cd_trackinfo[i].ind1_m = 0;
|
||||
cd_trackinfo[i].ind1_s = 0;
|
||||
cd_trackinfo[i].ind1_f = 0;
|
||||
cd_trackinfo[i].type = 0;
|
||||
cd_trackinfo[i].bytes_per_sec = 0;
|
||||
}
|
||||
|
||||
size_t i_tracks = 0;
|
||||
char str[1024];
|
||||
char type[5];
|
||||
|
||||
cue_pt = 0; // Set cue file index to zero.
|
||||
|
||||
int track_num = 0;
|
||||
bool first_track_done = 0;
|
||||
|
||||
// Note: strncmp==0 means a MATCH! Because reasons.
|
||||
|
||||
while( i_tracks < 99 )
|
||||
{
|
||||
if ( !cue_readline(str) ) break; // Read in a whole line from the CUE file (until the end of the file).
|
||||
|
||||
if ( strncmp(str, "TRACK", 5)==0 ) { // Is this a track?
|
||||
sscanf( str, "%*5s%2u%5s%*1s%4u", &track_num, type, &bytes_per_sec);
|
||||
if (!first_track_done) {
|
||||
first_track_done = 1;
|
||||
cd_first_track = track_num;
|
||||
}
|
||||
}
|
||||
|
||||
if ( strncmp(str, "PREGAP", 6)==0 )
|
||||
{
|
||||
sscanf( str, "%*6s%2u:%2u:%2u", &i_min, &i_sec, &i_frame );
|
||||
cd_trackinfo[track_num].pregap_present = 1;
|
||||
cd_trackinfo[track_num].pre_m = i_min;
|
||||
cd_trackinfo[track_num].pre_s = i_sec;
|
||||
cd_trackinfo[track_num].pre_f = i_frame;
|
||||
}
|
||||
|
||||
if ( strncmp(str, "INDEX", 5)==0 ) // Is this an Index?
|
||||
{
|
||||
sscanf( str, "%*5s%2u%2u:%2u:%2u", &i_num, &i_min, &i_sec, &i_frame );
|
||||
|
||||
cd_trackinfo[track_num].track_active = 1;
|
||||
if ( strcmp(type, "AUDIO")==0 ) {
|
||||
cd_trackinfo[track_num].type = 0;
|
||||
bytes_per_sec = 2352; // Audio tracks assume 2352 bytes per sector, so it's not listed in the CUE file.
|
||||
}
|
||||
else if ( strcmp(type, "MODE1")==0 ) {
|
||||
cd_trackinfo[track_num].type = 4;
|
||||
}
|
||||
cd_trackinfo[track_num].bytes_per_sec = bytes_per_sec;
|
||||
|
||||
/*
|
||||
if (i_num==0) { // "Pregap" index, sort of.
|
||||
printf("Track:%02d Pregap:%d M:%02d S:%02d F:%02d Type:%s TOCtype:%d BPS:%04d\n", track_num, cd_trackinfo[track_num].pregap_present, i_min, i_sec, i_frame, type, cd_trackinfo[track_num].type, bytes_per_sec);
|
||||
cd_trackinfo[track_num].ind0_m = i_min;
|
||||
cd_trackinfo[track_num].ind0_s = i_sec;
|
||||
cd_trackinfo[track_num].ind0_f = i_frame;
|
||||
}
|
||||
*/
|
||||
|
||||
if (i_num==1) { // "Track Start" index.
|
||||
printf("Track:%02d Pregap:%d M:%02d S:%02d F:%02d Type:%s TOCtype:%d BPS:%04d\n", track_num, cd_trackinfo[track_num].pregap_present, i_min, i_sec, i_frame, type, cd_trackinfo[track_num].type, bytes_per_sec);
|
||||
cd_trackinfo[track_num].ind1_m = i_min;
|
||||
cd_trackinfo[track_num].ind1_s = i_sec;
|
||||
cd_trackinfo[track_num].ind1_f = i_frame;
|
||||
}
|
||||
}
|
||||
i_tracks++;
|
||||
}
|
||||
cd_last_track = track_num;
|
||||
}
|
||||
|
||||
void cd_generate_toc(uint16_t req_type, uint8_t *buffer)
|
||||
{
|
||||
uint8_t m,s,f;
|
||||
uint32_t lba;
|
||||
|
||||
switch ( (req_type&0xFF00)>>8 ) {
|
||||
case 0xD0: { // Request First Track and Last Track (BCD).
|
||||
//buffer[0] = 0x01; // Rondo - First track (BCD).
|
||||
//buffer[1] = 0x22; // Rondo - Last track (BCD).
|
||||
buffer[0] = dec_2_bcd( cd_first_track );
|
||||
buffer[1] = dec_2_bcd( cd_last_track );
|
||||
buffer[2] = 0x00; // Padding.
|
||||
buffer[3] = 0x00; // Padding.
|
||||
printf("Core requesting CD TOC0. First Track:%02X. Last Track:%02X (BCD)\n", buffer[0], buffer[1]);
|
||||
}; break;
|
||||
|
||||
case 0xD1: { // Request Total Disk Size (MSF, in BCD).
|
||||
//buffer[0] = 0x49; // Rondo - Minutes = 0x49 (73).
|
||||
//buffer[1] = 0x09; // Rondo - Seconds = 0x09 (9).
|
||||
//buffer[2] = 0x12; // Rondo - Frames = 0x12 (18).
|
||||
|
||||
// ADD the PREGAP (if present).
|
||||
/*
|
||||
if (buffer[3]==4 && cd_trackinfo[track].pregap_present) {
|
||||
m = cd_trackinfo[cd_last_track].ind1_m + cd_trackinfo[cd_last_track].pre_m;
|
||||
s = cd_trackinfo[cd_last_track].ind1_s + cd_trackinfo[cd_last_track].pre_s;
|
||||
f = cd_trackinfo[cd_last_track].ind1_f + cd_trackinfo[cd_last_track].pre_f;
|
||||
// Not sure if audio tracks need the 2-second lead-in offset added? ElectronAsh.
|
||||
uint32_t lba = msf_to_lba(m, s, f); // Convert to LBA, so we can add the 2-second lead-in.
|
||||
//lba += 2*75; // Standard lead-in is 2 seconds (75 sectors per second, so 150).
|
||||
// Convert back from LBA to MSF...
|
||||
m = lba / (60 * 75);
|
||||
lba -= m * (60 * 75);
|
||||
s = lba / 75;
|
||||
f = lba % 75;
|
||||
|
||||
buffer[0] = dec_2_bcd( m );
|
||||
buffer[1] = dec_2_bcd( s );
|
||||
buffer[2] = dec_2_bcd( f );
|
||||
}
|
||||
else
|
||||
{*/
|
||||
buffer[0] = dec_2_bcd( cd_trackinfo[cd_last_track].ind1_m );
|
||||
buffer[1] = dec_2_bcd( cd_trackinfo[cd_last_track].ind1_s );
|
||||
buffer[2] = dec_2_bcd( cd_trackinfo[cd_last_track].ind1_f );
|
||||
//}
|
||||
buffer[3] = 0x00; // Padding.
|
||||
|
||||
printf("Core requesting CD TOC1. Total Disk Size:M:%02X S:%02X F:%02X (BCD)\n", buffer[0], buffer[1], buffer[2]);
|
||||
}; break;
|
||||
|
||||
case 0xD2: { // Request Track Info (Start MSF in BCD, and track type).
|
||||
uint8_t track = bcd_2_dec(req_type&0xFF); // Track number from req_type upper byte is in BCD!
|
||||
|
||||
// If a DATA track, check for a pregap, and ADD it (if present).
|
||||
if (cd_trackinfo[track].type==4 && cd_trackinfo[track].pregap_present) {
|
||||
m = cd_trackinfo[track].ind1_m + cd_trackinfo[track].pre_m;
|
||||
s = cd_trackinfo[track].ind1_s + cd_trackinfo[track].pre_s;
|
||||
f = cd_trackinfo[track].ind1_f + cd_trackinfo[track].pre_f;
|
||||
|
||||
lba = msf_to_lba(m, s, f); // Convert to LBA, so we can add the 2-second lead-in.
|
||||
lba += 2*75; // Standard lead-in is 2 seconds (75 sectors per second, so 150).
|
||||
|
||||
// Convert back from LBA to MSF...
|
||||
m = lba / (60 * 75);
|
||||
lba -= m * (60 * 75);
|
||||
s = lba / 75;
|
||||
f = lba % 75;
|
||||
|
||||
buffer[0] = dec_2_bcd( m );
|
||||
buffer[1] = dec_2_bcd( s );
|
||||
buffer[2] = dec_2_bcd( f );
|
||||
}
|
||||
else
|
||||
{
|
||||
buffer[0] = dec_2_bcd( cd_trackinfo[track].ind1_m );
|
||||
buffer[1] = dec_2_bcd( cd_trackinfo[track].ind1_s );
|
||||
buffer[2] = dec_2_bcd( cd_trackinfo[track].ind1_f );
|
||||
}
|
||||
buffer[3] = cd_trackinfo[track].type;
|
||||
|
||||
printf("Core requesting CD TOC2. Track:%02d. M:%02X S:%02X F:%02X (BCD). Type:", track, buffer[0], buffer[1], buffer[2]);
|
||||
if (buffer[3]==0x00) printf("AUDIO\n");
|
||||
else if (buffer[3]==0x04) printf("DATA\n");
|
||||
else printf("UNKNOWN!\n");
|
||||
}; break;
|
||||
}
|
||||
}
|
||||
|
||||
void user_io_poll()
|
||||
{
|
||||
if ((core_type != CORE_TYPE_MINIMIG2) &&
|
||||
@@ -1772,7 +2068,8 @@ void user_io_poll()
|
||||
{
|
||||
static uint8_t buffer[4][512];
|
||||
uint32_t lba;
|
||||
uint16_t c = user_io_sd_get_status(&lba);
|
||||
uint16_t req_type = 0;
|
||||
uint16_t c = user_io_sd_get_status(&lba, &req_type);
|
||||
//if(c&3) printf("user_io_sd_get_status: cmd=%02x, lba=%08x\n", c, lba);
|
||||
|
||||
// valid sd commands start with "5x" to avoid problems with
|
||||
@@ -1861,18 +2158,111 @@ void user_io_poll()
|
||||
//printf("SD RD %d on %d, WIDE=%d\n", lba, disk, fio_size);
|
||||
|
||||
int done = 0;
|
||||
|
||||
if (buffer_lba[disk] != lba)
|
||||
if (is_neogeo_core())
|
||||
{
|
||||
uint32_t offset = 0;
|
||||
|
||||
if (sd_image[disk].size)
|
||||
{
|
||||
diskled_on();
|
||||
if (FileSeekLBA(&sd_image[disk], lba))
|
||||
printf("req_type: 0x%04X ", req_type);
|
||||
switch ((req_type & 0xFF00) >> 8)
|
||||
{
|
||||
if (FileReadSec(&sd_image[disk], buffer[disk]))
|
||||
case 0xD0:case 0xD1:case 0xD2:
|
||||
{
|
||||
cd_generate_toc(req_type, buffer[disk]);
|
||||
done = 1;
|
||||
};
|
||||
break;
|
||||
|
||||
case 0x48:
|
||||
{
|
||||
// Added this, Neo CD always requests by MSF (furrtek)
|
||||
if ((req_type & 0xFF) == 0x01)
|
||||
{
|
||||
done = 1;
|
||||
printf("Neo CD requested raw lba value (MSF): 0x%08X\n", lba);
|
||||
uint8_t m = bcd_2_dec((lba & 0xFF0000) >> 16);
|
||||
uint8_t s = bcd_2_dec((lba & 0xFF00) >> 8);
|
||||
uint8_t f = bcd_2_dec((lba & 0xFF) >> 0);
|
||||
lba = msf_to_lba(m, s, f);
|
||||
lba -= (2 * 75); // Remove 2 second pregap
|
||||
}
|
||||
|
||||
uint8_t track = cd_lba_to_track(lba);
|
||||
uint16_t bps = cd_trackinfo[track].bytes_per_sec;
|
||||
uint32_t pregap = 0;
|
||||
|
||||
if (cd_trackinfo[track].pregap_present)
|
||||
{
|
||||
pregap = msf_to_lba(cd_trackinfo[track].pre_m, cd_trackinfo[track].pre_s, cd_trackinfo[track].pre_f);
|
||||
}
|
||||
|
||||
if (bps == 2352) offset = 16 + ((lba - pregap) * 2352); // Rondo etc.
|
||||
else if (bps == 2048) offset = ((lba - pregap) * 2048); // Homebrew, etc.
|
||||
else printf("Data track %02d has unhandled bytes-per-sec of %d !\n", track, bps);
|
||||
|
||||
if (FileSeek(&sd_image[disk], offset, SEEK_SET))
|
||||
{
|
||||
if (FileReadAdv(&sd_image[disk], buffer[disk], 2048)) done = 1;
|
||||
}
|
||||
printf("Core requesting 2048-byte CD sector, from LBA: 0x%08X TRACK: %02d BPS: %04d OFFSET: 0x%08X \n", lba, track, bps, offset);
|
||||
};
|
||||
break;
|
||||
|
||||
case 0x52:
|
||||
{
|
||||
switch (req_type & 0xFF)
|
||||
{
|
||||
// "lba" holds the LBA. Dun do nothing. (no conversion needed).
|
||||
case 0x00:
|
||||
break;
|
||||
|
||||
// "lba" holds the MSF (BCD). Convert to LBA.
|
||||
case 0x01:
|
||||
{
|
||||
uint8_t m = bcd_2_dec((lba & 0xFF0000) >> 16);
|
||||
uint8_t s = bcd_2_dec((lba & 0xFF00) >> 8);
|
||||
uint8_t f = bcd_2_dec((lba & 0xFF) >> 0);
|
||||
lba = msf_to_lba(m, s, f);
|
||||
};
|
||||
break;
|
||||
|
||||
// "lba" holds the TRACK number (BCD?). Grab the track start MSF from the TOC, then convert to LBA.
|
||||
case 0x02:
|
||||
{
|
||||
uint8_t track = bcd_2_dec(lba);
|
||||
lba = msf_to_lba(cd_trackinfo[track].ind1_m, cd_trackinfo[track].ind1_s, cd_trackinfo[track].ind1_f);
|
||||
};
|
||||
break;
|
||||
}
|
||||
|
||||
uint8_t track = cd_lba_to_track(lba);
|
||||
|
||||
if (cd_trackinfo[track].type != 0x00)
|
||||
{
|
||||
printf("Error: Core is trying to play back non-audio track as CDDA!\n");
|
||||
memset(buffer[disk], 0, sizeof(buffer[disk]));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (FileSeek(&sd_image[disk], (lba - 525) * 2352, SEEK_SET))
|
||||
{
|
||||
if (FileReadAdv(&sd_image[disk], buffer[disk], 2352)) done = 1;
|
||||
}
|
||||
}
|
||||
printf("Core requesting a raw 2352-byte CD sector, from LBA: 0x%08X TRACK: %02d\n", lba, track);
|
||||
};
|
||||
break;
|
||||
|
||||
default:
|
||||
{
|
||||
if (FileSeekLBA(&sd_image[disk], lba))
|
||||
{
|
||||
if (FileReadSec(&sd_image[disk], buffer[disk])) done = 1;
|
||||
}
|
||||
printf("Core requesting a 512-byte SD / VHD sector, from LBA: 0x%08X\n", lba);
|
||||
};
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1880,37 +2270,66 @@ void user_io_poll()
|
||||
//Give an empty block.
|
||||
if (!done) memset(buffer[disk], 0, sizeof(buffer[disk]));
|
||||
buffer_lba[disk] = lba;
|
||||
}
|
||||
|
||||
if(buffer_lba[disk] == lba)
|
||||
{
|
||||
//hexdump(buffer, 32, 0);
|
||||
|
||||
// data is now stored in buffer. send it to fpga
|
||||
spi_uio_cmd_cont(UIO_SECTOR_RD);
|
||||
spi_block_write(buffer[disk], fio_size);
|
||||
if ((req_type & 0xF000) == 0xD000) spi_write(buffer[disk], 4, fio_size); // TOC. (4 bytes, including padding).
|
||||
else if ((req_type & 0xFF00) == 0x4800) spi_write(buffer[disk], 2048, fio_size); // 2048-byte CD sector.
|
||||
else if ((req_type & 0xFF00) == 0x5200) spi_write(buffer[disk], 2352, fio_size); // 2352-byte CD sector.
|
||||
else spi_write(buffer[disk], 512, fio_size); // Standard 512-byte SD / VHD sector.
|
||||
DisableIO();
|
||||
}
|
||||
|
||||
// just load the next sector now, so it may be prefetched
|
||||
// for the next request already
|
||||
done = 0;
|
||||
if (sd_image[disk].size)
|
||||
else
|
||||
{
|
||||
diskled_on();
|
||||
if (FileSeekLBA(&sd_image[disk], lba + 1))
|
||||
if (buffer_lba[disk] != lba)
|
||||
{
|
||||
if (FileReadSec(&sd_image[disk], buffer[disk]))
|
||||
if (sd_image[disk].size)
|
||||
{
|
||||
done = 1;
|
||||
diskled_on();
|
||||
if (FileSeekLBA(&sd_image[disk], lba))
|
||||
{
|
||||
if (FileReadSec(&sd_image[disk], buffer[disk]))
|
||||
{
|
||||
done = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Even after error we have to provide the block to the core
|
||||
//Give an empty block.
|
||||
if (!done) memset(buffer[disk], 0, sizeof(buffer[disk]));
|
||||
buffer_lba[disk] = lba;
|
||||
}
|
||||
|
||||
if (buffer_lba[disk] == lba)
|
||||
{
|
||||
//hexdump(buffer, 32, 0);
|
||||
|
||||
// data is now stored in buffer. send it to fpga
|
||||
spi_uio_cmd_cont(UIO_SECTOR_RD);
|
||||
spi_block_write(buffer[disk], fio_size);
|
||||
DisableIO();
|
||||
}
|
||||
|
||||
// just load the next sector now, so it may be prefetched
|
||||
// for the next request already
|
||||
done = 0;
|
||||
if (sd_image[disk].size)
|
||||
{
|
||||
diskled_on();
|
||||
if (FileSeekLBA(&sd_image[disk], lba + 1))
|
||||
{
|
||||
if (FileReadSec(&sd_image[disk], buffer[disk]))
|
||||
{
|
||||
done = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if(done) buffer_lba[disk] = lba + 1;
|
||||
if (done) buffer_lba[disk] = lba + 1;
|
||||
|
||||
if (sd_image[disk].type == 2)
|
||||
{
|
||||
buffer_lba[disk] = -1;
|
||||
if (sd_image[disk].type == 2)
|
||||
{
|
||||
buffer_lba[disk] = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1997,6 +2416,13 @@ void user_io_poll()
|
||||
}
|
||||
}
|
||||
|
||||
if (is_neogeo_core() && (!rtc_timer || CheckTimer(rtc_timer)))
|
||||
{
|
||||
// Update once per minute should be enough
|
||||
rtc_timer = GetTimer(60000);
|
||||
send_rtc(1);
|
||||
}
|
||||
|
||||
if (core_type == CORE_TYPE_ARCHIE) archie_poll();
|
||||
if (core_type == CORE_TYPE_SHARPMZ) sharpmz_poll();
|
||||
|
||||
|
||||
20
user_io.h
20
user_io.h
@@ -182,9 +182,6 @@ typedef struct {
|
||||
|
||||
void user_io_init(const char *path);
|
||||
unsigned char user_io_core_type();
|
||||
char is_minimig();
|
||||
char is_archie();
|
||||
char is_sharpmz();
|
||||
void user_io_poll();
|
||||
char user_io_menu_button();
|
||||
char user_io_user_button();
|
||||
@@ -198,9 +195,6 @@ int user_io_file_mount(char *name, unsigned char index = 0, char pre = 0);
|
||||
char user_io_serial_status(serial_status_t *, uint8_t);
|
||||
char *user_io_get_core_name();
|
||||
const char *user_io_get_core_name_ex();
|
||||
char is_menu_core();
|
||||
char is_x86_core();
|
||||
char is_snes_core();
|
||||
char has_menu();
|
||||
|
||||
const char *get_image_name(int i);
|
||||
@@ -236,8 +230,6 @@ void user_io_rtc_reset();
|
||||
const char* get_rbf_dir();
|
||||
const char* get_rbf_name();
|
||||
|
||||
#define HomeDir (is_minimig() ? "Amiga" : is_archie() ? "Archie" : is_menu_core() ? "Scripts" : user_io_get_core_name())
|
||||
|
||||
int GetUARTMode();
|
||||
int GetMidiLinkMode();
|
||||
void SetMidiLinkMode(int mode);
|
||||
@@ -252,4 +244,16 @@ void diskled_on();
|
||||
#define DISKLED_ON diskled_on()
|
||||
#define DISKLED_OFF void()
|
||||
|
||||
void parse_cue_file(void);
|
||||
|
||||
char is_minimig();
|
||||
char is_archie();
|
||||
char is_sharpmz();
|
||||
char is_menu_core();
|
||||
char is_x86_core();
|
||||
char is_snes_core();
|
||||
char is_neogeo_core();
|
||||
|
||||
#define HomeDir (is_minimig() ? "Amiga" : is_archie() ? "Archie" : is_menu_core() ? "Scripts" : user_io_get_core_name())
|
||||
|
||||
#endif // USER_IO_H
|
||||
|
||||
Reference in New Issue
Block a user