mirror of
https://github.com/libretro/neocd_libretro.git
synced 2025-03-02 12:56:18 +00:00
Added support for MAME variant of the BIOS
Added support for the Universe BIOS CHD bugfixes
This commit is contained in:
parent
e4b6e99d34
commit
348e88f33a
52
README.md
52
README.md
@ -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
|
||||
|
@ -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"
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
|
108
src/libretro.cpp
108
src/libretro.cpp
@ -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;
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user