Added support for MAME variant of the BIOS

Added support for the Universe BIOS
CHD bugfixes
This commit is contained in:
Fabrice Martinez 2019-06-10 03:40:30 +02:00
parent e4b6e99d34
commit 348e88f33a
5 changed files with 118 additions and 105 deletions

View File

@ -1,3 +1,4 @@
# NeoCD-Libretro
## Introduction
@ -37,40 +38,40 @@ Copy `neocd_libretro.info` to folder `RetroArch/info`
To function NeoCD need a BIOS from a Front Loading, Top Loading or CDZ machine. The BIOS files should be installed in a `neocd` folder under RetroArch's system folder.
The hashes are given to help you verify the files have not been tampered with, the emulator doesn't verify them.
> **📓 Note:** The hashes are given to help you verify the files have not been tampered with, the emulator doesn't verify them.
The needed files are:
#### Zoom ROM
|Description | Filename | SHA1 |
|------------|-----------|------------------------------------------|
| Y Zoom ROM | ng-lo.rom | 2b1c719531dac9bb503f22644e6e4236b91e7cfc |
> **📓 Note:** Need one in the following table
|Description | Filename | SHA1 |
|-------------------|-----------|------------------------------------------|
| Y Zoom ROM | ng-lo.rom | 2b1c719531dac9bb503f22644e6e4236b91e7cfc |
| Y Zoom ROM (MAME) | 000-lo.lo | 5992277debadeb64d1c1c64b0a92d9293eaf7e4a |
#### BIOS
> **📓 Note:** You need at least one in the following table. If several BIOSes are available, it will be possible to choose which to run in the Core Options Menu.
The files will be automatically byte swapped if needed.
| Description | Filename | SHA1 |
|----------------------------|--------------|------------------------------------------|
| Front Loader BIOS | neocd_f.rom | a5f4a7a627b3083c979f6ebe1fabc5d2df6d083b |
| Front Loader BIOS (SMKDAN) | neocd_sf.rom | c99c44a43bded1bff4570b30b74975601bd3f94e |
| Top Loader BIOS | neocd_t.rom | cc92b54a18a8bff6e595aabe8e5c360ba9e62eb5 |
| Top Loader BIOS (SMKDAN) | neocd_st.rom | d463b3a322b9674f9e227a21e43898019ce0e642 |
| CDZ BIOS | neocd_z.rom | b0f1c4fa8d4492a04431805f6537138b842b549f |
| CDZ BIOS (SMKDAN) | neocd_sz.rom | 41ca1c031b844a46387be783ac862c76e65afbb3 |
| Description | Filename | Byte Swapped SHA1 |
|----------------------------|--------------|------------------------------------------|
| Front Loader BIOS | neocd_f.rom | 53bc1f283cdf00fa2efbb79f2e36d4c8038d743a |
| Front Loader BIOS (SMKDAN) | neocd_sf.rom | 4a94719ee5d0e3f2b981498f70efc1b8f1cef325 |
| Top Loader BIOS | neocd_t.rom | 235f4d1d74364415910f73c10ae5482d90b4274f |
| Top Loader BIOS (SMKDAN) | neocd_st.rom | 19729b51bdab60c42aafef6e20ea9234c7eb8410 |
| CDZ BIOS | neocd_z.rom | 7bb26d1e5d1e930515219cb18bcde5b7b23e2eda |
| CDZ BIOS (SMKDAN) | neocd_sz.rom | 6a947457031dd3a702a296862446d7485aa89dbb |
| Description | Filename | SHA1 |
|----------------------------|----------------|------------------------------------------|
| Front Loader BIOS | neocd_f.rom | a5f4a7a627b3083c979f6ebe1fabc5d2df6d083b |
| Front Loader BIOS (SMKDAN) | neocd_sf.rom | c99c44a43bded1bff4570b30b74975601bd3f94e |
| Top Loader BIOS | neocd_t.rom | cc92b54a18a8bff6e595aabe8e5c360ba9e62eb5 |
| Top Loader BIOS (SMKDAN) | neocd_st.rom | d463b3a322b9674f9e227a21e43898019ce0e642 |
| CDZ BIOS | neocd_z.rom | b0f1c4fa8d4492a04431805f6537138b842b549f |
| CDZ BIOS (SMKDAN) | neocd_sz.rom | 41ca1c031b844a46387be783ac862c76e65afbb3 |
| Front Loader BIOS (MAME) | front-sp1.bin | 53bc1f283cdf00fa2efbb79f2e36d4c8038d743a |
| Top Loader BIOS (MAME) | top-sp1.bin | 235f4d1d74364415910f73c10ae5482d90b4274f |
| CDZ BIOS (MAME) | neocd.bin | 7bb26d1e5d1e930515219cb18bcde5b7b23e2eda |
| Universe 3.2 | uni-bioscd.rom | 5158b728e62b391fb69493743dcf7abbc62abc82 |
### CD Images
In the era of modern computers and portable devices, CD-ROMs are no longer convenient. Additionally I believe it is not possible to read the TOC of protected games without special drivers. As a result, NeoCD now exclusively run using CD-ROM images.
NeoCD accepts as input a cue sheet file (CUE) or a MAME CHD file. The image can be either of "single file" type (CUE, BIN) or "multiple files" type (CUE,ISO,[WAV/FLAC/OGG]).
NeoCD accepts as input a cue sheet file (CUE) or a MAME CHD file. CUE images can be either of "single file" type (CUE, BIN) or "multiple files" type (CUE,ISO,[WAV/FLAC/OGG]).
> **🎶 Supported audio formats are:** Wave (.wav), FLAC (.flac) or Ogg Vorbis (.ogg)
@ -90,6 +91,7 @@ NeoCD accepts as input a cue sheet file (CUE) or a MAME CHD file. The image can
* libFLAC
* libogg
* libvorbis
* zlib
* MSYS (Windows)
The project uses custom cmake finders in the folder `cmakescripts` to locate the libraries.
@ -106,8 +108,8 @@ The project uses custom cmake finders in the folder `cmakescripts` to locate the
## Tested platforms
* x64 / Windows / GCC 8.2
* x64 / Arch Linux / GCC 8.2
* x64 / Windows / GCC 9.1
* x64 / Arch Linux / GCC 9.1
* Raspberry Pi 3 / Arch Linux / GCC 8.2
## Known problems

View File

@ -10,7 +10,7 @@ license = "LGPLv3"
display_version = "2019"
supports_no_game = "false"
firmware_count = 7
firmware_count = 12
firmware0_desc = "Front Loader BIOS"
firmware0_path = "neocd/neocd_f.rom"
firmware0_opt = "true"
@ -31,4 +31,19 @@ firmware5_path = "neocd/neocd_sz.rom"
firmware5_opt = "true"
firmware6_desc = "Y-ZOOM ROM"
firmware6_path = "neocd/ng-lo.rom"
firmware6_opt = "false"
firmware6_opt = "true"
firmware7_desc = "Y-ZOOM ROM (MAME)"
firmware7_path = "neocd/000-lo.lo"
firmware7_opt = "true"
firmware8_desc = "Front Loader BIOS (MAME)"
firmware8_path = "neocd/front-sp1.bin"
firmware8_opt = "true"
firmware9_desc = "Top Loader BIOS (MAME)"
firmware9_path = "neocd/top-sp1.bin"
firmware9_opt = "true"
firmware10_desc = "CDZ BIOS (MAME)"
firmware10_path = "neocd/neocd.bin"
firmware10_opt = "true"
firmware11_desc = "Universe BIOS"
firmware11_path = "neocd/uni-bioscd.rom"
firmware11_opt = "true"

View File

@ -227,10 +227,13 @@ void Cdrom::readData(char* buffer)
uint32_t trackOffset = m_currentPosition - m_currentTrack->startSector;
if (m_file->isChd())
trackOffset *= 2352;
else if (m_currentTrack->trackType == CdromToc::TrackType::Mode1_2048)
trackOffset *= 2048;
if (m_currentTrack->trackType == CdromToc::TrackType::Mode1_2048)
{
if (m_file->isChd())
trackOffset *= 2352;
else
trackOffset *= 2048;
}
else if (m_currentTrack->trackType == CdromToc::TrackType::Mode1_2352)
trackOffset = (trackOffset * 2352) + 16;

View File

@ -432,6 +432,9 @@ bool CdromToc::loadChd(const std::string& filename)
// Current position on the CD
uint32_t cdPosition = 0;
// Used to fix some weird CHD behavior
bool previousWasData = true;
// Scan metadata
for(uint32_t idx = 0; idx < 99; ++idx)
{
@ -450,9 +453,6 @@ bool CdromToc::loadChd(const std::string& filename)
// Length of the postgap (index 2)
uint32_t postgapLength;
// True is pregap / postgap have associated data in the data file, otherwise they're just silence
bool gapsInDataFile = false;
// True if the metadata is in V2 format
bool v2Metadata = true;
@ -489,17 +489,12 @@ bool CdromToc::loadChd(const std::string& filename)
// Get pre / post gap length from metadata
pregapLength = std::stoul(match[5].str());
postgapLength = std::stoul(match[8].str());
// If PGTYPE starts with 'V' the pregap data is in the CHD
std::string pgType = match[6];
gapsInDataFile = !pgType.empty() && (pgType[0] == 'V');
}
else
{
// Old metadata don't have pre / post gap info so set it to zero
pregapLength = 0;
postgapLength = 0;
gapsInDataFile = false;
}
//Get the track number and length from metadata
@ -532,13 +527,16 @@ bool CdromToc::loadChd(const std::string& filename)
// Create the pregap entry (index 0)
if (pregapLength)
{
if (gapsInDataFile)
m_toc.push_back({ -1, { static_cast<uint8_t>(trackNumber), 0 }, TrackType::Silence, 0, cdPosition, 0, pregapLength });
// CHD WEIRDNESS: If the previous track was data don't move the chd position
if (!previousWasData)
{
m_toc.push_back({ 0, { static_cast<uint8_t>(trackNumber), 0 }, TrackType::AudioPCM, 0, cdPosition, static_cast<size_t>(chdPosition) * 2352, pregapLength });
chdPosition += pregapLength;
// Shorten the track accordingly
trackLength -= pregapLength;
}
else
m_toc.push_back({ -1, { static_cast<uint8_t>(trackNumber), 0 }, TrackType::Silence, 0, cdPosition, 0, pregapLength });
cdPosition += pregapLength;
}
@ -551,16 +549,11 @@ bool CdromToc::loadChd(const std::string& filename)
// Create the post gap entry (index 2)
if (postgapLength)
{
if (gapsInDataFile)
{
m_toc.push_back({ 0, { static_cast<uint8_t>(trackNumber), 2 }, TrackType::AudioPCM, 0, cdPosition, static_cast<size_t>(chdPosition) * 2352, postgapLength });
chdPosition += postgapLength;
}
else
m_toc.push_back({ -1, { static_cast<uint8_t>(trackNumber), 2 }, TrackType::Silence, 0, cdPosition, 0, postgapLength });
m_toc.push_back({ -1, { static_cast<uint8_t>(trackNumber), 2 }, TrackType::Silence, 0, cdPosition, 0, postgapLength });
cdPosition += postgapLength;
}
previousWasData = !(trackType == TrackType::AudioPCM);
}
m_totalSectors = cdPosition;

View File

@ -1,39 +1,40 @@
#include "neogeocd.h"
#include "timeprofiler.h"
#include <algorithm>
#include <cmath>
#include <cstdlib>
#include <cstring>
#include <fstream>
#include <initializer_list>
#include <vector>
class BiosListEntry
{
public:
BiosListEntry(const std::string& f, const std::string& d, NeoGeoCD::BiosType t) :
filename(f),
description(d),
type(t)
{ }
#include "neogeocd.h"
#include "timeprofiler.h"
std::string filename;
std::string description;
struct BiosListEntry
{
const char* filename;
const char* description;
NeoGeoCD::BiosType type;
bool isSMKDan;
bool isUniverse;
};
static const char* BIOS_F_FILENAME = "neocd_f.rom";
static const char* BIOS_F_DESCRIPTION = "Front Loader";
static const char* BIOS_SF_FILENAME = "neocd_sf.rom";
static const char* BIOS_SF_DESCRIPTION = "Front Loader (SMKDAN)";
static const char* BIOS_T_FILENAME = "neocd_t.rom";
static const char* BIOS_T_DESCRIPTION = "Top Loader";
static const char* BIOS_ST_FILENAME = "neocd_st.rom";
static const char* BIOS_ST_DESCRIPTION = "Top Loader (SMKDAN)";
static const char* BIOS_Z_FILENAME = "neocd_z.rom";
static const char* BIOS_Z_DESCRIPTION = "CDZ";
static const char* BIOS_SZ_FILENAME = "neocd_sz.rom";
static const char* BIOS_SZ_DESCRIPTION = "CDZ (SMKDAN)";
static const std::initializer_list<BiosListEntry> KNOWN_BIOSES{
{ "neocd_f.rom", "Front Loader", NeoGeoCD::FrontLoader, false, false },
{ "neocd_sf.rom", "Front Loader (SMKDAN)", NeoGeoCD::FrontLoader, true, false },
{ "front-sp1.bin", "Front Loader (MAME)", NeoGeoCD::FrontLoader, false, false },
{ "neocd_t.rom", "Top Loader", NeoGeoCD::TopLoader, false, false },
{ "neocd_st.rom", "Top Loader (SMKDAN)", NeoGeoCD::TopLoader, true, false },
{ "top-sp1.bin", "Top Loader (MAME)", NeoGeoCD::TopLoader, false, false },
{ "neocd_z.rom", "CDZ", NeoGeoCD::CDZ, false, false },
{ "neocd_sz.rom", "CDZ (SMKDAN)", NeoGeoCD::CDZ, true, false },
{ "neocd.bin", "CDZ (MAME)", NeoGeoCD::CDZ, false, false },
{ "uni-bioscd.rom", "Universe 3.2", NeoGeoCD::CDZ, false, true }
};
static const std::initializer_list<const char*> KNOWN_ZOOM_ROMS{
{ "ng-lo.rom" },
{ "000-lo.lo" }
};
static const char* REGION_VARIABLE = "neocd_region";
static const char* BIOS_VARIABLE = "neocd_bios";
@ -122,23 +123,11 @@ static void lookForBIOS()
{
biosList.clear();
if (fileExists(makeSystemPath(BIOS_F_FILENAME)))
biosList.emplace_back(BiosListEntry(BIOS_F_FILENAME, BIOS_F_DESCRIPTION, NeoGeoCD::FrontLoader));
if (fileExists(makeSystemPath(BIOS_SF_FILENAME)))
biosList.emplace_back(BiosListEntry(BIOS_SF_FILENAME, BIOS_SF_DESCRIPTION, NeoGeoCD::FrontLoader));
if (fileExists(makeSystemPath(BIOS_T_FILENAME)))
biosList.emplace_back(BiosListEntry(BIOS_T_FILENAME, BIOS_T_DESCRIPTION, NeoGeoCD::TopLoader));
if (fileExists(makeSystemPath(BIOS_ST_FILENAME)))
biosList.emplace_back(BiosListEntry(BIOS_ST_FILENAME, BIOS_ST_DESCRIPTION, NeoGeoCD::TopLoader));
if (fileExists(makeSystemPath(BIOS_Z_FILENAME)))
biosList.emplace_back(BiosListEntry(BIOS_Z_FILENAME, BIOS_Z_DESCRIPTION, NeoGeoCD::CDZ));
if (fileExists(makeSystemPath(BIOS_SZ_FILENAME)))
biosList.emplace_back(BiosListEntry(BIOS_SZ_FILENAME, BIOS_SZ_DESCRIPTION, NeoGeoCD::CDZ));
for(const BiosListEntry& entry : KNOWN_BIOSES)
{
if (fileExists(makeSystemPath(entry.filename)))
biosList.push_back(entry);
}
}
static bool loadYZoomROM()
@ -146,11 +135,17 @@ static bool loadYZoomROM()
std::ifstream file;
std::string filename;
filename = makeSystemPath("ng-lo.rom");
file.open(filename, std::ios::in | std::ios::binary);
for(const char* rom_name : KNOWN_ZOOM_ROMS)
{
filename = makeSystemPath(rom_name);
file.open(filename, std::ios::in | std::ios::binary);
if (file.is_open())
break;
}
if (!file.is_open())
{
LOG(LOG_ERROR, "Could not load Y Zoom ROM %s\n", filename.c_str());
LOG(LOG_ERROR, "Could not load Y Zoom ROM\n");
return false;
}
@ -158,7 +153,7 @@ static bool loadYZoomROM()
if (file.gcount() < Memory::YZOOMROM_SIZE)
{
LOG(LOG_ERROR, "ng-lo.rom should be exactly 65536 bytes!\n");
LOG(LOG_ERROR, "Y ZOOM ROM should be at least 65536 bytes!\n");
return false;
}
@ -195,12 +190,13 @@ static void disableSMKDANChecksum(uint32_t address)
static void patchBIOS()
{
bool isSMKDan = (biosList[biosIndex].filename == BIOS_SZ_FILENAME)
|| (biosList[biosIndex].filename == BIOS_SF_FILENAME)
|| (biosList[biosIndex].filename == BIOS_ST_FILENAME);
const BiosListEntry& entry = biosList[biosIndex];
if (neocd.biosType == NeoGeoCD::FrontLoader)
{
// Patch the CD Recognition
patchROM_16(0xC10B64, 0x4E71);
// Speed hacks to avoid busy looping
if (cdSpeedHack)
{
@ -211,11 +207,14 @@ static void patchBIOS()
}
// If SMKDan, disable the BIOS checksum
if (isSMKDan)
if (entry.isSMKDan)
disableSMKDANChecksum(0xC23EBE);
}
else if (neocd.biosType == NeoGeoCD::TopLoader)
{
// Patch the CD Recognition
patchROM_16(0xC10436, 0x4E71);
// Speed hacks to avoid busy looping
if (cdSpeedHack)
{
@ -226,12 +225,13 @@ static void patchBIOS()
}
// If SMKDan, disable the BIOS checksum
if (isSMKDan)
if (entry.isSMKDan)
disableSMKDANChecksum(0xC23FBE);
}
else if (neocd.biosType == NeoGeoCD::CDZ)
{
// Patch the CD Recognition (It's done in the CD-ROM firmware, can't emulate)
// Patch the CD Recognition
patchROM_16(0xC0EB82, 0x4E71);
patchROM_16(0xC0D280, 0x4E71);
// Speed hacks to avoid busy looping
@ -245,7 +245,7 @@ static void patchBIOS()
}
// If SMKDan, disable the BIOS checksum
if (isSMKDan)
if (entry.isSMKDan)
disableSMKDANChecksum(0xC62BF4);
}
}
@ -301,7 +301,7 @@ static int biosDescriptionToIndex(const char* description)
{
for (int result = 0; result < biosList.size(); ++result)
{
if (!strcmp(description, biosList[result].description.c_str()))
if (!strcmp(description, biosList[result].description))
return result;
}