megadrive: add segacd support

This commit is contained in:
barbudreadmon committed 2026-11-04 08:22:12 +01:00
1 parent 097d45ab3a
commit 8d19a50878
32 files changed
+2810 -30

No files matched your search

+1 -1
View File
@@ -160,7 +160,7 @@ depobj = burn.o burn_bitmap.o burn_gun.o burn_led.o burn_shift.o burn_memory.o
\
toa_bcu2.o toa_extratext.o toa_gp9001.o toa_palette.o toaplan1.o toaplan.o \
\
megadrive.o stm95.o \
megadrive.o segacd.o stm95.o \
\
pce.o pce_cd.o \
\
@@ -704,6 +704,7 @@ rm %(Filename).exe</Command>
<ClCompile Include="..\..\src\burn\snd\timeplt_snd.cpp" />
<ClCompile Include="..\..\src\burn\drv\megadrive\d_megadrive.cpp" />
<ClCompile Include="..\..\src\burn\drv\megadrive\megadrive.cpp" />
<ClCompile Include="..\..\src\burn\drv\megadrive\segacd.cpp" />
<ClCompile Include="..\..\src\burn\drv\megadrive\stm95.cpp" />
<ClCompile Include="..\..\src\burn\drv\midway\dcs2k.cpp" />
<ClCompile Include="..\..\src\burn\drv\midway\d_kinst.cpp" />
@@ -3018,6 +3018,9 @@
<ClCompile Include="..\..\src\burn\snd\timeplt_snd.cpp">
<Filter>burn\snd</Filter>
</ClCompile>
<ClCompile Include="..\..\src\burn\drv\megadrive\segacd.cpp">
<Filter>Burn\drv\megadrive</Filter>
</ClCompile>
<ClCompile Include="..\..\src\burn\drv\megadrive\stm95.cpp">
<Filter>Burn\drv\megadrive</Filter>
</ClCompile>
@@ -655,6 +655,7 @@ del %(Filename).exe</Command>
<ClCompile Include="..\..\src\burn\snd\timeplt_snd.cpp" />
<ClCompile Include="..\..\src\burn\drv\megadrive\d_megadrive.cpp" />
<ClCompile Include="..\..\src\burn\drv\megadrive\megadrive.cpp" />
<ClCompile Include="..\..\src\burn\drv\megadrive\segacd.cpp" />
<ClCompile Include="..\..\src\burn\drv\megadrive\stm95.cpp" />
<ClCompile Include="..\..\src\burn\drv\midway\dcs2k.cpp" />
<ClCompile Include="..\..\src\burn\drv\midway\d_kinst.cpp" />
@@ -2059,6 +2059,9 @@
<ClCompile Include="..\..\src\burn\snd\timeplt_snd.cpp">
<Filter>burn\snd</Filter>
</ClCompile>
<ClCompile Include="..\..\src\burn\drv\megadrive\segacd.cpp">
<Filter>burn\drv\megadrive</Filter>
</ClCompile>
<ClCompile Include="..\..\src\burn\drv\megadrive\stm95.cpp">
<Filter>burn\drv\megadrive</Filter>
</ClCompile>
@@ -655,6 +655,7 @@ del %(Filename).exe</Command>
<ClCompile Include="..\..\src\burn\snd\timeplt_snd.cpp" />
<ClCompile Include="..\..\src\burn\drv\megadrive\d_megadrive.cpp" />
<ClCompile Include="..\..\src\burn\drv\megadrive\megadrive.cpp" />
<ClCompile Include="..\..\src\burn\drv\megadrive\segacd.cpp" />
<ClCompile Include="..\..\src\burn\drv\megadrive\stm95.cpp" />
<ClCompile Include="..\..\src\burn\drv\midway\dcs2k.cpp" />
<ClCompile Include="..\..\src\burn\drv\midway\d_kinst.cpp" />
@@ -2059,6 +2059,9 @@
<ClCompile Include="..\..\src\burn\snd\timeplt_snd.cpp">
<Filter>burn\snd</Filter>
</ClCompile>
<ClCompile Include="..\..\src\burn\drv\megadrive\segacd.cpp">
<Filter>burn\drv\megadrive</Filter>
</ClCompile>
<ClCompile Include="..\..\src\burn\drv\megadrive\stm95.cpp">
<Filter>burn\drv\megadrive</Filter>
</ClCompile>
@@ -655,6 +655,7 @@ del %(Filename).exe</Command>
<ClCompile Include="..\..\src\burn\snd\timeplt_snd.cpp" />
<ClCompile Include="..\..\src\burn\drv\megadrive\d_megadrive.cpp" />
<ClCompile Include="..\..\src\burn\drv\megadrive\megadrive.cpp" />
<ClCompile Include="..\..\src\burn\drv\megadrive\segacd.cpp" />
<ClCompile Include="..\..\src\burn\drv\megadrive\stm95.cpp" />
<ClCompile Include="..\..\src\burn\drv\midway\dcs2k.cpp" />
<ClCompile Include="..\..\src\burn\drv\midway\d_kinst.cpp" />
@@ -2059,6 +2059,9 @@
<ClCompile Include="..\..\src\burn\snd\timeplt_snd.cpp">
<Filter>burn\snd</Filter>
</ClCompile>
<ClCompile Include="..\..\src\burn\drv\megadrive\segacd.cpp">
<Filter>burn\drv\megadrive</Filter>
</ClCompile>
<ClCompile Include="..\..\src\burn\drv\megadrive\stm95.cpp">
<Filter>burn\drv\megadrive</Filter>
</ClCompile>
@@ -348,6 +348,7 @@
<ClCompile Include="..\..\src\burn\drv\megadrive\d_mdarcbl.cpp" />
<ClCompile Include="..\..\src\burn\drv\megadrive\d_megadrive.cpp" />
<ClCompile Include="..\..\src\burn\drv\megadrive\megadrive.cpp" />
<ClCompile Include="..\..\src\burn\drv\megadrive\segacd.cpp" />
<ClCompile Include="..\..\src\burn\drv\megadrive\stm95.cpp" />
<ClCompile Include="..\..\src\burn\drv\midway\d_kinst.cpp" />
<ClCompile Include="..\..\src\burn\drv\midway\d_tunit.cpp" />
@@ -952,6 +952,9 @@
<ClCompile Include="..\..\src\burn\drv\megadrive\megadrive.cpp">
<Filter>burn\drv\megadrive</Filter>
</ClCompile>
<ClCompile Include="..\..\src\burn\drv\megadrive\segacd.cpp">
<Filter>burn\drv\megadrive</Filter>
</ClCompile>
<ClCompile Include="..\..\src\burn\drv\megadrive\stm95.cpp">
<Filter>burn\drv\megadrive</Filter>
</ClCompile>
+1
View File
@@ -746,6 +746,7 @@ int BurnComputeSHA1(const UINT8 *buffer, int buffer_size, char *hash_str);
#define HARDWARE_SEGA_GAME_GEAR (HARDWARE_PREFIX_SEGA_GAME_GEAR)
#define HARDWARE_SEGA_MEGADRIVE (HARDWARE_PREFIX_SEGA_MEGADRIVE)
#define HARDWARE_SEGA_MEGACD (HARDWARE_PREFIX_SEGA_MEGADRIVE | 0x00010000)
#define HARDWARE_SEGA_SG1000 (HARDWARE_PREFIX_SEGA_SG1000)
#define HARDWARE_SEGA_SG1000_RAMEXP_A (0x1000)
+41
View File
@@ -483,6 +483,47 @@ INT32 MegadriveGetZipName(char** pszName, UINT32 i)
return 0;
}
// Sega CD / Mega-CD system (bios), the disc image is selected separately
static struct BurnDIPInfo SegaCDDIPList[] = {
DIP_OFFSET(0x19)
{0x00, 0xff, 0xff, 0x00, NULL },
{0x01, 0xff, 0xff, 0x03, NULL },
{0, 0xfd, 0, 4, "Bios" },
{0x00, 0x01, 0x03, 0x00, "Auto (disc region)" },
{0x00, 0x01, 0x03, 0x01, "Sega CD (USA, v1.10)" },
{0x00, 0x01, 0x03, 0x02, "Mega-CD (Europe, v1.00)" },
{0x00, 0x01, 0x03, 0x03, "Mega-CD (Japan, v1.00P)" },
{0, 0xfe, 0, 4, "32-Col Mode Draw" },
{0x01, 0x01, 0x03, 0x00, "No Change" },
{0x01, 0x01, 0x03, 0x01, "Center" },
{0x01, 0x01, 0x03, 0x02, "Inner Zoom" },
{0x01, 0x01, 0x03, 0x03, "Resize Screen/Window" },
};
STDDIPINFO(SegaCD)
static struct BurnRomInfo md_segacdRomDesc[] = {
{ "Sega CD BIOS (USA, v1.10).bin", 0x020000, 0xc6d10268, BRF_PRG | BRF_ESS },
{ "Mega-CD BIOS (Europe, v1.00).bin", 0x020000, 0x529ac15a, BRF_PRG | BRF_ESS | BRF_OPT },
{ "Mega-CD BIOS (Japan, v1.00P).bin", 0x020000, 0x9d2da8f2, BRF_PRG | BRF_ESS | BRF_OPT },
};
STD_ROM_PICK(md_segacd)
STD_ROM_FN(md_segacd)
struct BurnDriver BurnDrvmd_segacd = {
"md_segacd", NULL, NULL, NULL, "1992",
"Sega CD / Mega-CD System\0", "System - media selected separately", "Sega", "Sega CD / Mega-CD",
NULL, NULL, NULL, NULL,
BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGACD, GBF_BIOS, 0,
MegadriveGetZipName, md_segacdRomInfo, md_segacdRomName, NULL, NULL, NULL, NULL, MegadriveInputInfo, SegaCDDIPInfo,
MegadriveInitSegaCD, MegadriveExit, MegadriveFrame, MegadriveDraw, MegadriveScan,
&bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3
};
// 16 Ton (Japan, SegaNet)
static struct BurnRomInfo md_16tonRomDesc[] = {
{ "16 Ton (Japan, SegaNet)(1991)(Sega).bin", 0x040000, 0x537f04b6, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 },
+137 -8
View File
@@ -33,6 +33,7 @@
#include "m68000_debug.h"
#include "i2ceeprom.h" // i2c eeprom for MD
#include "burn_gun.h" // menacer, justifier
#include "segacd.h"
UINT8 MegadriveUnmappedRom = 0xff;
@@ -67,7 +68,7 @@ static INT32 SekCyclesDoneFrameF() { return ( (SekCycleCnt - SekCycleCntDELTA) -
#define SekCyclesBurn(c) { SekCycleCnt += c; }
#define SekEndRun(after) { SekCycleCnt -= m68k_ICount - (after); m68k_ICount = after; }
static void SekRunM68k(INT32 cyc)
static void SekRunM68kSlice(INT32 cyc)
{
INT32 cyc_do;
@@ -81,6 +82,24 @@ static void SekRunM68k(INT32 cyc)
m68k_ICount = 0;
}
// Sega CD: the sub cpu catches up with the main cpu in small slices
#define SEGACD_SLICE 122
static void SekRunM68k(INT32 cyc)
{
if (SegaCDMode) {
while (cyc > 0) {
INT32 slice = (cyc > SEGACD_SLICE) ? SEGACD_SLICE : cyc;
SekRunM68kSlice(slice);
SegaCDRunSub(SekCyclesDoneFrame());
cyc -= slice;
}
return;
}
SekRunM68kSlice(cyc);
}
static UINT64 z80_cycle_cnt;
static INT32 Z80HasBus = 0;
static INT32 MegadriveZ80Reset = 0;
@@ -275,6 +294,12 @@ static INT32 dma_xfers = 0; // vdp dma
static INT32 BlankedLine = 0;
static INT32 interlacemode2 = 0;
// VSRAM writes done once the next line's display has started, kept out of that line (Puggsy FMV)
static INT32 vsram_late_count = 0;
static UINT8 vsram_late_idx[0x40];
static UINT16 vsram_late_val[0x40];
static void VSRAMLateWrite(INT32 idx);
static UINT8 Hardware;
static UINT8 bNoDebug = 0;
static INT32 bForce3Button = 0;
@@ -293,6 +318,12 @@ static UINT8 __fastcall MegadriveReadByte(UINT32 address);
static void MegadriveCheckHardware()
{
if (SegaCDMode) {
Hardware = SegaCDGetHardware();
bprintf(PRINT_IMPORTANT, _T("Emulating %s Mega CD / Sega CD\n"), ((Hardware & 0xc0) == 0xc0) ? _T("Europe PAL") : ((Hardware & 0x80) ? _T("USA NTSC") : _T("Japan NTSC")));
return;
}
Hardware = MegadriveDIP[0] & 0xe0;
if (MegadriveDIP[0] & 0x01) {
// Auto Detect Region and SECAM
@@ -752,6 +783,11 @@ static void DmaSlow(INT32 len)
if ((source & 0xe00000) == 0xe00000) { // RAM
pd = (UINT16 *)(Ram68K + (source & 0xfffe));
pdend = (UINT16 *)(Ram68K + 0x10000);
} else if (SegaCDMode && source < 0x400000) { // Sega CD: bios, prg-ram window, word ram
fromrom = 1;
source &= ~1;
// dma from word ram responds with a one-access delay
if ((source & 0x3c0000) == 0x200000) source -= 2;
} else if( source < RomSize) { // ROM
if (papriummode || psolarmode) fromrom = 1;
fromrom = 1;
@@ -762,7 +798,7 @@ static void DmaSlow(INT32 len)
} else return; // Invalid source address
// overflow protection, might break something..
if (len > pdend - pd) {
if (pd && len > pdend - pd) {
len = pdend - pd;
//bprintf(0, _T("DmaSlow() overflow(!).\n"));
}
@@ -852,7 +888,12 @@ static void DmaSlow(INT32 len)
a |= RamVReg->addr_u << 16;
for(; len; len--)
{
VideoWrite128(a, BURN_ENDIAN_SWAP_INT16(*pd++));
if (pd == NULL) {
VideoWrite128(a, SekReadWord(source));
source += 2;
} else {
VideoWrite128(a, BURN_ENDIAN_SWAP_INT16(*pd++));
}
// AutoIncrement
a = (a + inc) & 0x1ffff;
}
@@ -860,6 +901,7 @@ static void DmaSlow(INT32 len)
break;
}
// remember addr
RamVReg->addr = (UINT16)a;
UpdateDMARegs();
@@ -1057,6 +1099,32 @@ struct h_ { UINT16 hres; UINT8 hint; UINT8 start; UINT8 end; };
static const h_ hints[2] = { {256, 0x85, 0x94, 0xe9}, {320, 0xa5, 0xb7, 0xe5} };
static void VSRAMLateWrite(INT32 idx)
{
INT32 cyc = SekCyclesLine();
if (cyc < 400 || cyc >= 512) return;
const UINT8 *hc = (RamVReg->reg[12] & 1) ? hcounts_40 : hcounts_32;
if (hc[cyc] >= 0x80) return; // display of the next line not started yet
for (INT32 i = 0; i < vsram_late_count; i++)
if (vsram_late_idx[i] == idx) return;
vsram_late_idx[vsram_late_count] = idx;
vsram_late_val[vsram_late_count] = RamSVid[idx];
vsram_late_count++;
}
// exchanges the late values with the ones they replaced
static void VSRAMLateSwap()
{
for (INT32 i = 0; i < vsram_late_count; i++) {
UINT16 t = RamSVid[vsram_late_idx[i]];
RamSVid[vsram_late_idx[i]] = vsram_late_val[i];
vsram_late_val[i] = t;
}
}
static UINT16 __fastcall MegadriveVideoReadWord(UINT32 sekAddress)
{
if (sekAddress > 0xC0001F)
@@ -1179,6 +1247,8 @@ static void __fastcall MegadriveVideoWriteWord(UINT32 sekAddress, UINT16 wordVal
CalcCol((RamVReg->addr >> 1) & 0x003f, wordValue);
break;
case 5:
// limited to Sega CD for safety, but should be valid for regular MD games too
if (SegaCDMode) VSRAMLateWrite((RamVReg->addr >> 1) & 0x003f);
RamSVid[(RamVReg->addr >> 1) & 0x003f] = BURN_ENDIAN_SWAP_INT16(wordValue & 0x7ff);
break;
case 0x81: {
@@ -1603,6 +1673,10 @@ static INT32 MegadriveResetDo()
m68k_megadrive_sr_checkint_mode(1);
SekClose();
if (SegaCDMode) {
SegaCDReset();
}
ZetOpen(0);
ZetReset();
ZetClose();
@@ -1622,6 +1696,10 @@ static INT32 MegadriveResetDo()
MegadriveCheckHardware();
if (SegaCDMode) {
SegaCDSetPAL(Hardware & 0x40);
}
if (last_hardware != Hardware) {
bprintf(0, _T("** Megadrive Region/Hardware change, %dhz\n"), (Hardware & 0x40) ? 50 : 60);
if (Hardware & 0x40) {
@@ -1707,6 +1785,7 @@ static INT32 MegadriveResetDo()
RamVReg->rendstatus = 0;
bMegadriveRecalcPalette = 1;
interlacemode2 = 0;
vsram_late_count = 0;
SekCyclesReset();
z80CyclesReset();
@@ -1731,7 +1810,13 @@ static INT32 __fastcall MegadriveIrqCallback(INT32 irq)
case 4: RamVReg->pending_ints = 0x00; break;
case 6: RamVReg->pending_ints &= ~0x20; break;
}
SekSetIRQLine(0, CPU_IRQSTATUS_NONE);
// a pending h-int stays asserted once the v-int is acknowledged (SoulStar demo)
// limited to Sega CD for safety, but should be valid for regular MD games too
if (SegaCDMode && irq == 6 && (RamVReg->pending_ints & 0x10) && (RamVReg->reg[0] & 0x10)) {
SekSetIRQLine(4, CPU_IRQSTATUS_ACK);
} else {
SekSetIRQLine(0, CPU_IRQSTATUS_NONE);
}
return M68K_INT_ACK_AUTOVECTOR;
}
@@ -3825,6 +3910,14 @@ INT32 MegadriveInitColocodx()
return rc;
}
INT32 MegadriveInitSegaCD()
{
SegaCDMode = 1;
SegaCDMainCycles = SekCyclesDoneFrameF;
return MegadriveInit();
}
INT32 MegadriveInit()
{
BurnAllocMemIndex();
@@ -3835,8 +3928,14 @@ INT32 MegadriveInit()
memset(RomMain, MegadriveUnmappedRom, MAX_CARTRIDGE_SIZE);
MegadriveLoadRoms(0);
if (MegadriveLoadRoms(1)) return 1;
if (SegaCDMode) {
if (SegaCDLoadBios(RomMain)) return 1;
RomNum = 1;
RomSize = 0x20000;
} else {
MegadriveLoadRoms(0);
if (MegadriveLoadRoms(1)) return 1;
}
{
SekInit(0, 0x68000); // Allocate 68000
@@ -3905,8 +4004,12 @@ INT32 MegadriveInit()
SN76496SetBuffered(SekCyclesDoneFrameF, OSC_NTSC / 7);
SN76496SetRoute(0, 0.50, BURN_SND_ROUTE_BOTH);
MegadriveSetupSRAM();
SetupCustomCartridgeMappers();
if (SegaCDMode) {
if (SegaCDInit(RomMain)) return 1;
} else {
MegadriveSetupSRAM();
SetupCustomCartridgeMappers();
}
if (MegadriveCallback) MegadriveCallback();
@@ -3960,6 +4063,10 @@ INT32 MegadriveExit()
sot4wmode = 0;
}
if (SegaCDMode) {
SegaCDExit();
}
if (has_gun != 0) {
BurnGunExit();
@@ -5520,6 +5627,10 @@ INT32 MegadriveFrame()
SekCyclesNewFrame(); // for sound sync
ZetNewFrame();
if (SegaCDMode) {
SegaCDNewFrame();
}
SekOpen(0);
ZetOpen(0);
@@ -5666,6 +5777,8 @@ INT32 MegadriveFrame()
}
// decide if we draw this line
INT32 vsram_late = vsram_late_count;
if (vsram_late) VSRAMLateSwap();
if ((!(RamVReg->reg[1]&8) && y<=224) || ((RamVReg->reg[1]&8) && y<240)) {
if (interlacemode2) {
RamVReg->field = 0;
@@ -5678,6 +5791,10 @@ INT32 MegadriveFrame()
PicoLine(y);
}
}
if (vsram_late) {
VSRAMLateSwap();
vsram_late_count = 0;
}
z80CyclesSync();
@@ -5710,6 +5827,10 @@ INT32 MegadriveFrame()
#endif
}
if (SegaCDMode) {
SegaCDEndFrame(SekCyclesDoneFrame());
}
if (pBurnDraw) MegadriveDraw();
if (pBurnSoundOut) {
@@ -5727,6 +5848,10 @@ INT32 MegadriveFrame()
vx_render(pBurnSoundOut, nBurnSoundLen);
}
if (SegaCDMode) {
SegaCDSoundUpdate(pBurnSoundOut, nBurnSoundLen);
}
SekClose();
ZetClose();
@@ -5801,6 +5926,10 @@ INT32 MegadriveScan(INT32 nAction, INT32 *pnMin)
md_eeprom_stm95_scan(nAction);
}
if (SegaCDMode) {
SegaCDScan(nAction, pnMin);
}
if (nAction & ACB_WRITE && (BurnDrvGetHardwareCode() & 0xff) == HARDWARE_SEGA_MEGADRIVE_PCB_SSF2) {
for (INT32 i = 0; i < 7; i++) {
Ssf2BankWriteByte(0xa130f3 + (i*2), RamMisc->MapperBank[i+1]);
+1
View File
@@ -36,6 +36,7 @@ INT32 MegadriveInitPaprium();
INT32 MegadriveInitPsolar();
INT32 MegadriveInitSot4w();
INT32 MegadriveInitColocodx();
INT32 MegadriveInitSegaCD();
INT32 MegadriveExit();
INT32 MegadriveFrame();
+1
View File
@@ -7,6 +7,7 @@
group_desc = 'Sega Mega Drive drivers'
group_srcs = [
'megadrive.cpp',
'segacd.cpp',
'stm95.cpp',
]
drivers = {
File diff suppressed because it is too large. Load diff
+27
View File
@@ -0,0 +1,27 @@
#pragma once
#ifndef SEGACD_H
#define SEGACD_H
extern INT32 SegaCDMode;
extern INT32 (*SegaCDMainCycles)(); // main cpu cycles done in the current frame
// bios / region
INT32 SegaCDLoadBios(UINT8 *dest);
UINT8 SegaCDGetHardware();
// main cpu (cpu #0) must be initialised and closed when calling these
INT32 SegaCDInit(UINT8 *bios);
void SegaCDExit();
void SegaCDReset();
void SegaCDSetPAL(INT32 pal);
// frame handling, called with cpu #0 closed
void SegaCDNewFrame();
// called with cpu #0 open
void SegaCDRunSub(INT32 main_cycles);
void SegaCDEndFrame(INT32 main_cycles);
void SegaCDSoundUpdate(INT16 *output, INT32 samples);
INT32 SegaCDScan(INT32 nAction, INT32 *pnMin);
#endif
+151 -1
View File
@@ -2,9 +2,11 @@
#include "cdlist.h"
#include "neocdlist.h"
#include "pcecdlist.h"
#include "segacdlist.h"
#include "cd_img.h"
#include "neocdlist_games.h"
#include "pcecdlist_games.h"
#include "segacdlist_games.h"
static NGCDGAME* pNeoGame;
@@ -268,6 +270,25 @@ static INT32 IsGamesExpress(CDImage* pImage, const CDImageTrack* pTrack, UINT8*
return nCrc == 0xd7b47c06 || nCrc == 0x86aec522 || nCrc == 0xc8d1b5ef || nCrc == 0x0bdbde64;
}
// Sega CD / Mega-CD disc header: system id at 0x000, titles at 0x120 (domestic) / 0x150 (overseas), region at 0x1f0
static INT32 IsSegaCDHeader(const UINT8* pSector, INT32 nSize)
{
return nSize >= 0x200 && (!memcmp(pSector, "SEGADISCSYSTEM", 14) || !memcmp(pSector, "SEGABOOTDISC", 12));
}
static void SegaCDHeaderText(TCHAR* pszDest, UINT32 nDest, const UINT8* pText, INT32 nLength)
{
UINT32 n = 0;
for (INT32 i = 0; i < nLength && n + 1 < nDest; i++) {
UINT8 c = pText[i];
if (c < 0x20 || c > 0x7e) c = ' ';
if (c == ' ' && (n == 0 || pszDest[n - 1] == _T(' '))) continue;
pszDest[n++] = (TCHAR)c;
}
while (n && pszDest[n - 1] == _T(' ')) n--;
pszDest[n] = 0;
}
static INT32 IdentifyPlatform(CDImage* pImage, CDListResult* pResult)
{
static const UINT8 pPceMagic[32] = {
@@ -293,6 +314,18 @@ static INT32 IdentifyPlatform(CDImage* pImage, CDListResult* pResult)
return 0;
INT32 nSize = 0;
if (ReadSector(pImage, pTrack->nIndex1LBA, sector, &nSize) && IsSegaCDHeader(sector, nSize)) {
pResult->nPlatform = CDLIST_PLATFORM_SEGACD;
pResult->nSource = CDLIST_SOURCE_MAGIC;
pResult->nConfidence = CDLIST_CONFIDENCE_EXACT;
SegaCDHeaderText(pResult->Metadata.szTitle, CDLIST_TEXT_SIZE, sector + 0x150, 0x30);
if (!pResult->Metadata.szTitle[0])
SegaCDHeaderText(pResult->Metadata.szTitle, CDLIST_TEXT_SIZE, sector + 0x120, 0x30);
SegaCDHeaderText(pResult->Metadata.szRegion, 64, sector + 0x1f0, 0x10);
CopyText(pResult->Metadata.szRequirement, CDLIST_TEXT_SIZE, _T("Sega CD / Mega-CD BIOS"));
CopyText(pResult->Metadata.szDescriptor, CDLIST_TEXT_SIZE, _T("Sega CD disc system header"));
return 1;
}
if (ReadSector(pImage, pTrack->nIndex1LBA, sector, &nSize) && nSize >= 32 && !memcmp(sector, pPceMagic, sizeof(pPceMagic))) {
pResult->nPlatform = CDLIST_PLATFORM_PCECD;
pResult->nSource = CDLIST_SOURCE_MAGIC;
@@ -320,6 +353,18 @@ static INT32 IdentifyPlatform(CDImage* pImage, CDListResult* pResult)
return 0;
}
static const sega_cd_game* FindSegaCDGame(const TCHAR* pszSha1)
{
if (!pszSha1 || !pszSha1[0])
return NULL;
for (UINT32 i = 0; i < sizeof(segacd_games) / sizeof(segacd_games[0]); i++) {
if (segacd_games[i].sha1[0] && !_tcscmp(segacd_games[i].sha1, pszSha1))
return &segacd_games[i];
}
return NULL;
}
static void FillNeoMetadata(CDListResult* pResult)
{
NGCDGAME* pGame = GetNeoGeoCDInfo(pResult->nNeoID);
@@ -391,6 +436,17 @@ INT32 CDListIdentifyEx(const TCHAR* pszPath, CDListResult* pResult, UINT32 nFlag
break;
}
}
if (pResult->nPlatform == CDLIST_PLATFORM_SEGACD) {
const sega_cd_game* pGame = FindSegaCDGame(pResult->szTOCSha1);
if (pGame) {
CopyText(pResult->Metadata.szTitle, CDLIST_TEXT_SIZE, pGame->name);
CopyText(pResult->Metadata.szName, CDLIST_TEXT_SIZE, pGame->id);
CopyText(pResult->Metadata.szYear, 32, pGame->year);
CopyText(pResult->Metadata.szCompany, CDLIST_TEXT_SIZE, pGame->company);
pResult->nSource = CDLIST_SOURCE_GAMEDB;
}
}
}
CDImageClose(pImage);
return pResult->nPlatform != CDLIST_PLATFORM_UNKNOWN;
@@ -598,6 +654,98 @@ void PceCDInfo_Exit()
}
#endif
#ifdef BUILD_MEGADRIVE
static CDListMetadata SegaCdInfo;
static INT32 nSegaCdInfoValid = 0;
static INT32 IsSegaCD()
{
return (BurnDrvGetHardwareCode() & HARDWARE_PUBLIC_MASK) == HARDWARE_SEGA_MEGACD;
}
INT32 SegaCDInfo_Init()
{
SegaCDInfo_Exit();
if (!IsSegaCD() || !CDEmuImage[0]) {
return 0;
}
// the short name comes from the image file name, so that each image gets its own saves
TCHAR szFile[CDLIST_TEXT_SIZE];
const TCHAR* pszBase = _tcsrchr(CDEmuImage, _T('\\'));
pszBase = pszBase ? pszBase + 1 : CDEmuImage;
const TCHAR* pszSlash = _tcsrchr(pszBase, _T('/'));
if (pszSlash) {
pszBase = pszSlash + 1;
}
CopyText(szFile, CDLIST_TEXT_SIZE, pszBase);
TCHAR* pszDot = _tcsrchr(szFile, _T('.'));
if (pszDot) {
*pszDot = _T('\0');
}
INT32 nLen = 0;
for (INT32 i = 0; szFile[i] && nLen < 32; i++) {
TCHAR c = _totlower(szFile[i]);
if (c == _T('-') || c == _T('(') || c == _T('[')) break;
if ((c >= _T('a') && c <= _T('z')) || (c >= _T('0') && c <= _T('9'))) {
SegaCdInfo.szName[nLen++] = c;
}
}
SegaCdInfo.szName[nLen] = _T('\0');
if (nLen == 0) {
_tcscpy(SegaCdInfo.szName, _T("unknown"));
}
const sega_cd_game* pGame = FindSegaCDGame(ANSIToTCHAR((char*)CDEmuImageTOCSHA1, NULL, 0));
if (pGame) {
bprintf(0, _T("segacdlist_games db: found entry %s\n"), pGame->id);
CopyText(SegaCdInfo.szTitle, CDLIST_TEXT_SIZE, pGame->name);
CopyText(SegaCdInfo.szName, CDLIST_TEXT_SIZE, pGame->id);
CopyText(SegaCdInfo.szYear, 32, pGame->year);
CopyText(SegaCdInfo.szCompany, CDLIST_TEXT_SIZE, pGame->company);
} else {
CDListResult Result;
if (CDListIdentifyEx(CDEmuImage, &Result, CDLIST_IDENTIFY_FAST, NULL, NULL, NULL) && Result.nPlatform == CDLIST_PLATFORM_SEGACD && Result.Metadata.szTitle[0]) {
CopyText(SegaCdInfo.szTitle, CDLIST_TEXT_SIZE, Result.Metadata.szTitle);
} else {
CopyText(SegaCdInfo.szTitle, CDLIST_TEXT_SIZE, szFile);
}
}
nSegaCdInfoValid = 1;
bprintf(PRINT_NORMAL, _T(" Title: %s\n" ), SegaCdInfo.szTitle);
bprintf(PRINT_NORMAL, _T(" Shortname: %s\n"), SegaCdInfo.szName);
if (SegaCdInfo.szYear[0]) bprintf(PRINT_NORMAL, _T(" Year: %s\n" ), SegaCdInfo.szYear);
if (SegaCdInfo.szCompany[0]) bprintf(PRINT_NORMAL, _T(" Company: %s\n"), SegaCdInfo.szCompany);
return nSegaCdInfoValid;
}
TCHAR* SegaCDInfo_Text(INT32 nText)
{
if (!IsSegaCD() || !nSegaCdInfoValid) {
return NULL;
}
switch (nText) {
case DRV_FULLNAME: return SegaCdInfo.szTitle;
case DRV_NAME: return SegaCdInfo.szName;
case DRV_MANUFACTURER: return SegaCdInfo.szCompany[0] ? SegaCdInfo.szCompany : NULL;
case DRV_DATE: return SegaCdInfo.szYear[0] ? SegaCdInfo.szYear : NULL;
}
return NULL;
}
void SegaCDInfo_Exit()
{
memset(&SegaCdInfo, 0, sizeof(SegaCdInfo));
nSegaCdInfoValid = 0;
}
#endif
TCHAR* CDInfo_Text(INT32 nText)
{
static TCHAR szNone[] = _T("NOGAME");
@@ -608,6 +756,8 @@ TCHAR* CDInfo_Text(INT32 nText)
return NeoCDInfo_Text(nText);
case CDGAME_PCE:
return PceCDInfo_Text(nText);
case CDGAME_SEGACD:
return SegaCDInfo_Text(nText);
default:
return szNone;
}
@@ -617,7 +767,7 @@ TCHAR *CDInfo_GamePrefix()
{
static TCHAR buffer[128];
TCHAR g_sys_prefixes[3][20] = { _T("none_"), _T("ngcd_"), _T("pcecd_") };
TCHAR g_sys_prefixes[4][20] = { _T("none_"), _T("ngcd_"), _T("pcecd_"), _T("segacd_") };
const INT32 g_type = CDGameType();
_stprintf(buffer, _T("%s%s"), g_sys_prefixes[g_type], CDInfo_Text(DRV_NAME));
+7 -2
View File
@@ -11,7 +11,8 @@
enum {
CDGAME_NONE = 0, // not a CD game
CDGAME_NEOGEO, // Neo Geo CD
CDGAME_PCE // PC Engine CD
CDGAME_PCE, // PC Engine CD
CDGAME_SEGACD // Sega CD / Mega-CD
};
static inline INT32 CDGameType()
@@ -23,6 +24,9 @@ static inline INT32 CDGameType()
if (nHardware == HARDWARE_PCENGINE_PCE_CD) {
return CDGAME_PCE;
}
if (nHardware == HARDWARE_SEGA_MEGACD) {
return CDGAME_SEGACD;
}
return CDGAME_NONE;
}
@@ -38,7 +42,8 @@ enum CDListPlatform {
CDLIST_PLATFORM_UNKNOWN = 0,
CDLIST_PLATFORM_NEOCD,
CDLIST_PLATFORM_PCECD,
CDLIST_PLATFORM_PCFX
CDLIST_PLATFORM_PCFX,
CDLIST_PLATFORM_SEGACD
};
enum CDListSource {
+6 -2
View File
@@ -177,6 +177,7 @@ INT32 write_datfile(INT32 bType, FILE* fDat)
}
if ((((BurnDrvGetHardwareCode() & HARDWARE_PUBLIC_MASK) == HARDWARE_SEGA_MEGADRIVE)
|| ((BurnDrvGetHardwareCode() & HARDWARE_PUBLIC_MASK) == HARDWARE_SEGA_MEGACD)
|| ((BurnDrvGetHardwareCode() & HARDWARE_PUBLIC_MASK) == HARDWARE_PCENGINE_PCENGINE)
|| ((BurnDrvGetHardwareCode() & HARDWARE_PUBLIC_MASK) == HARDWARE_PCENGINE_PCE_CD)
|| ((BurnDrvGetHardwareCode() & HARDWARE_PUBLIC_MASK) == HARDWARE_PCENGINE_TG16)
@@ -198,7 +199,7 @@ INT32 write_datfile(INT32 bType, FILE* fDat)
continue;
}
if (((BurnDrvGetHardwareCode() & HARDWARE_PUBLIC_MASK) != HARDWARE_SEGA_MEGADRIVE) && (bType == DAT_MEGADRIVE_ONLY)) {
if (((BurnDrvGetHardwareCode() & HARDWARE_PUBLIC_MASK) != HARDWARE_SEGA_MEGADRIVE) && ((BurnDrvGetHardwareCode() & HARDWARE_PUBLIC_MASK) != HARDWARE_SEGA_MEGACD) && (bType == DAT_MEGADRIVE_ONLY)) {
continue;
}
@@ -345,6 +346,7 @@ INT32 write_datfile(INT32 bType, FILE* fDat)
}
remove_driver_leader(HARDWARE_SEGA_MEGADRIVE, 3, 1)
remove_driver_leader(HARDWARE_SEGA_MEGACD, 3, 1)
remove_driver_leader(HARDWARE_PCENGINE_TG16, 3, 1)
remove_driver_leader(HARDWARE_COLECO, 3, 1)
remove_driver_leader(HARDWARE_SEGA_SG1000, 5, 1)
@@ -696,6 +698,7 @@ INT32 write_datfile(INT32 bType, FILE* fDat)
}
if ((((BurnDrvGetHardwareCode() & HARDWARE_PUBLIC_MASK) == HARDWARE_SEGA_MEGADRIVE)
|| ((BurnDrvGetHardwareCode() & HARDWARE_PUBLIC_MASK) == HARDWARE_SEGA_MEGACD)
|| ((BurnDrvGetHardwareCode() & HARDWARE_PUBLIC_MASK) == HARDWARE_PCENGINE_PCENGINE)
|| ((BurnDrvGetHardwareCode() & HARDWARE_PUBLIC_MASK) == HARDWARE_PCENGINE_PCE_CD)
|| ((BurnDrvGetHardwareCode() & HARDWARE_PUBLIC_MASK) == HARDWARE_PCENGINE_TG16)
@@ -717,7 +720,7 @@ INT32 write_datfile(INT32 bType, FILE* fDat)
continue;
}
if (((BurnDrvGetHardwareCode() & HARDWARE_PUBLIC_MASK) != HARDWARE_SEGA_MEGADRIVE) && (bType == DAT_MEGADRIVE_ONLY)) {
if (((BurnDrvGetHardwareCode() & HARDWARE_PUBLIC_MASK) != HARDWARE_SEGA_MEGADRIVE) && ((BurnDrvGetHardwareCode() & HARDWARE_PUBLIC_MASK) != HARDWARE_SEGA_MEGACD) && (bType == DAT_MEGADRIVE_ONLY)) {
continue;
}
@@ -797,6 +800,7 @@ INT32 write_datfile(INT32 bType, FILE* fDat)
#endif
remove_driver_leader(HARDWARE_SEGA_MEGADRIVE, 3, 0)
remove_driver_leader(HARDWARE_SEGA_MEGACD, 3, 0)
remove_driver_leader(HARDWARE_PCENGINE_TG16, 3, 0)
remove_driver_leader(HARDWARE_COLECO, 3, 0)
remove_driver_leader(HARDWARE_SEGA_SG1000, 5, 0)
+4 -2
View File
@@ -59,7 +59,8 @@ UINT8 *lua_hotkeys[] = {
#define HW_NEOGEO ( ((BurnDrvGetHardwareCode() & HARDWARE_PUBLIC_MASK) == HARDWARE_SNK_NEOGEO) || ((BurnDrvGetHardwareCode() & HARDWARE_PUBLIC_MASK) == HARDWARE_SNK_NEOCD) )
#define HW_NES ( ((BurnDrvGetHardwareCode() & HARDWARE_PUBLIC_MASK) == HARDWARE_NES) || ((BurnDrvGetHardwareCode() & HARDWARE_PUBLIC_MASK) == HARDWARE_FDS) )
#define HW_MISC ( (! HW_NEOGEO) && (! HW_NES) && ((BurnDrvGetHardwareCode() & HARDWARE_PUBLIC_MASK) != HARDWARE_SEGA_MEGADRIVE) )
#define HW_MEGADRIVE ( ((BurnDrvGetHardwareCode() & HARDWARE_PUBLIC_MASK) == HARDWARE_SEGA_MEGADRIVE) || ((BurnDrvGetHardwareCode() & HARDWARE_PUBLIC_MASK) == HARDWARE_SEGA_MEGACD) )
#define HW_MISC ( (! HW_NEOGEO) && (! HW_NES) && (! HW_MEGADRIVE) )
#define SETS_VS ( (BurnDrvGetGenreFlags() & GBF_VSFIGHT) && ((BurnDrvGetFamilyFlags() & FBF_SF) || (BurnDrvGetFamilyFlags() & FBF_DSTLK) || (BurnDrvGetFamilyFlags() &FBF_PWRINST) || HW_NEOGEO) )
#ifdef BUILD_MACOS
@@ -1102,7 +1103,7 @@ static void GameInpInitMacros()
nMacroCount++;
pgi++;
}
if ((BurnDrvGetHardwareCode() & HARDWARE_PUBLIC_MASK) == HARDWARE_SEGA_MEGADRIVE) {
if (HW_MEGADRIVE) {
pgi->nInput = GIT_MACRO_AUTO;
pgi->nType = BIT_DIGITAL;
pgi->Macro.nMode = 0;
@@ -2179,6 +2180,7 @@ tIniStruct gamehw_cfg[] = {
{_T("MegaDrive hardware"), _T("config/presets/megadrive.ini"), true, { HARDWARE_SEGA_MEGADRIVE, 0 }, "\t\t\t<item list=\"megadriv\" name=\"" },
{_T("PCE/SGX hardware"), _T("config/presets/pce.ini"), true, { HARDWARE_PCENGINE_PCENGINE, HARDWARE_PCENGINE_SGX, 0 }, "\t\t\t<item list=\"pce\" name=\"" },
{_T("PCE CD hardware"), _T("config/presets/pcecd.ini"), true, { HARDWARE_PCENGINE_PCE_CD, 0 }, "\t\t\t<item list=\"pce_cd\" name=\"" },
{_T("Sega CD hardware"), _T("config/presets/megadrive.ini"), true, { HARDWARE_SEGA_MEGACD, 0 }, "\t\t\t<item list=\"segacd\" name=\"" },
{_T("TG16 hardware"), _T("config/presets/pce.ini"), true, { HARDWARE_PCENGINE_TG16, 0 }, "\t\t\t<item list=\"tg16\" name=\"" },
{_T("MSX1 hardware"), _T("config/presets/msx.ini"), false, { HARDWARE_MSX, 0 }, "\t\t\t<item list=\"msx1_cart\" name=\"" },
{_T("Coleco hardware"), _T("config/presets/coleco.ini"), true, { HARDWARE_COLECO, 0 }, "\t\t\t<item list=\"coleco\" name=\"" },
+6 -1
View File
@@ -2,6 +2,7 @@
#include "burner.h"
#include "neocdlist.h"
#include "pcecdlist.h"
#include "segacdlist.h"
int bDrvOkay = 0; // 1 if the Driver has been initted okay, and it's okay to use the BurnDrv functions
char szAppRomPaths[DIRS_MAX][MAX_PATH] = { { "/usr/local/share/roms/" }, { "roms/" }, };
@@ -86,7 +87,7 @@ int DrvInit(int nDrvNum, bool bRestore)
nBurnDrvActive = nDrvNum; // Set the driver number
INT32 nHardware = BurnDrvGetHardwareCode() & HARDWARE_PUBLIC_MASK;
if (nHardware == HARDWARE_SNK_NEOCD || nHardware == HARDWARE_PCENGINE_PCE_CD) {
if (nHardware == HARDWARE_SNK_NEOCD || nHardware == HARDWARE_PCENGINE_PCE_CD || nHardware == HARDWARE_SEGA_MEGACD) {
if (CDEmuInit()) {
printf("CD emu failed\n");
return 1;
@@ -98,6 +99,10 @@ int DrvInit(int nDrvNum, bool bRestore)
NeoCDZRateChange();
} else if (nHardware == HARDWARE_PCENGINE_PCE_CD) {
PceCDInfo_Init();
} else if (nHardware == HARDWARE_SEGA_MEGACD) {
SegaCDInfo_Init();
NeoCDZRateChange();
}
}
+16
View File
@@ -0,0 +1,16 @@
#ifndef SEGACDLIST_H_
#define SEGACDLIST_H_
#include "cdlist.h"
#ifdef BUILD_MEGADRIVE
INT32 SegaCDInfo_Init();
TCHAR* SegaCDInfo_Text(INT32 nText);
void SegaCDInfo_Exit();
#else
static inline INT32 SegaCDInfo_Init() { return 0; }
static inline TCHAR* SegaCDInfo_Text(INT32) { return NULL; }
static inline void SegaCDInfo_Exit() { }
#endif
#endif
+21
View File
@@ -0,0 +1,21 @@
// sega cd / mega-cd game detection via SHA1 of toc (toc-hash, printed in the log as "TOC Hash")
// discs not listed here fall back to the disc header title and a short name made from the file name
struct sega_cd_game {
TCHAR *sha1;
TCHAR *name;
TCHAR *id;
TCHAR *year;
TCHAR *company;
};
static sega_cd_game segacd_games[] = {
{ _T("1ba98761123bc815d3b4eecd072438b54e9dbd01"), _T("Dune (USA)"), _T("dune"), _T("1993"), _T("Virgin Games / Cryo") },
{ _T("4c77e0b81a72aeb763c80dfa168a7700f39ab21f"), _T("Keio Flying Squadron (USA)"), _T("keiofs"), _T("1994"), _T("JVC / Victor Entertainment") },
{ _T("cfea7696b9280bef7f82bb693435e86fd6c7c5f3"), _T("Lunar: The Silver Star (USA)"), _T("lunar"), _T("1993"), _T("Working Designs / Game Arts") },
{ _T("ce0b4c6cf602cc471451e8a451792112bc4e40e1"), _T("Lunar: Eternal Blue (USA)"), _T("lunar2"), _T("1994"), _T("Working Designs / Game Arts") },
{ _T("f321fffaf0e8c3bcd42af118918cf0a73e83f806"), _T("Mortal Kombat Kanzenban (Japan)"), _T("mkkanzen"), _T("1994"), _T("Acclaim / Probe Software") },
{ _T("2d252bd6afc1ef76db0769505a7bcdd4cec77cec"), _T("Puggsy (USA)"), _T("puggsy"), _T("1994"), _T("Psygnosis") },
{ _T("7c391316df9cb6b22d1537393ce711a94f036130"), _T("Sol-Feace (Europe)"), _T("solfeace"), _T("1992"), _T("Wolf Team") },
{ _T("46eff97ebe56033ede2a27492541b3e597023fd8"), _T("SoulStar + Battlecorps (Europe) (Demo)"), _T("soulstbcdemo"), _T("1994"), _T("Core Design") },
};
+4
View File
@@ -246,6 +246,10 @@ static INT32 CDLibraryPlatformEnabled(INT32 nPlatform)
#ifdef BUILD_PCE
if (nPlatform == CDLIST_PLATFORM_PCECD)
return 1;
#endif
#ifdef BUILD_MEGADRIVE
if (nPlatform == CDLIST_PLATFORM_SEGACD)
return 1;
#endif
return 0;
}
+6 -2
View File
@@ -2,6 +2,7 @@
#include "burner.h"
#include "neocdlist.h"
#include "pcecdlist.h"
#include "segacdlist.h"
int bDrvOkay = 0; // 1 if the Driver has been initted okay, and it's okay to use the BurnDrv functions
@@ -173,7 +174,7 @@ static void NeoCDZRateChange()
{
if (nAudSampleRate[nAudSelect] != 44100) {
nNeoCDZnAudSampleRateSave = nAudSampleRate[nAudSelect];
bprintf(PRINT_IMPORTANT, _T("Switching sound rate to 44100hz (from %dhz) as required by NeoGeo & PCE CD\n"), nNeoCDZnAudSampleRateSave);
bprintf(PRINT_IMPORTANT, _T("Switching sound rate to 44100hz (from %dhz) as required by NeoGeo, PCE & Sega CD\n"), nNeoCDZnAudSampleRateSave);
nAudSampleRate[nAudSelect] = 44100; // force 44100hz for CDDA
}
}
@@ -200,7 +201,7 @@ int DrvInit(int nDrvNum, bool bRestore)
}
INT32 nHardware = BurnDrvGetHardwareCode() & HARDWARE_PUBLIC_MASK;
if (nHardware == HARDWARE_SNK_NEOCD || nHardware == HARDWARE_PCENGINE_PCE_CD) {
if (nHardware == HARDWARE_SNK_NEOCD || nHardware == HARDWARE_PCENGINE_PCE_CD || nHardware == HARDWARE_SEGA_MEGACD) {
if (CDEmuInit()) {
FBAPopupAddText(PUF_TEXT_DEFAULT, MAKEINTRESOURCE(IDS_ERR_CDEMU_INI_FAIL));
FBAPopupDisplay(PUF_TYPE_ERROR);
@@ -215,6 +216,9 @@ int DrvInit(int nDrvNum, bool bRestore)
} else if (nHardware == HARDWARE_PCENGINE_PCE_CD) {
PceCDInfo_Init();
NeoCDZRateChange();
} else if (nHardware == HARDWARE_SEGA_MEGACD) {
SegaCDInfo_Init();
NeoCDZRateChange();
}
}
+28 -9
View File
@@ -8,7 +8,7 @@ TCHAR szNeoCDCoverDir[MAX_PATH] = _T("support/cdcovers/");
TCHAR szNeoCDPreviewDir[MAX_PATH] = _T("support/cdpreviews/");
TCHAR szNeoCDGamesDir[MAX_PATH] = _T("cdiso/");
#if defined(BUILD_NEOGEO) || defined(BUILD_PCE)
#if defined(BUILD_NEOGEO) || defined(BUILD_PCE) || defined(BUILD_MEGADRIVE)
struct PNGRESOLUTION { INT32 nWidth; INT32 nHeight; };
@@ -243,7 +243,7 @@ static void LoadEntryPreview(const CDLibraryEntry* pEntry, INT32 nSide, void** p
const TCHAR* pszName = GetPreviewName(pEntry);
TCHAR szPath[MAX_PATH];
TCHAR tszName[MAX_PATH];
_stprintf(tszName, _T("%s%s"), (pEntry->nPlatform == CDLIST_PLATFORM_PCECD) ? _T("pcecd_") : _T("ngcd_"), pszName);
_stprintf(tszName, _T("%s%s"), (pEntry->nPlatform == CDLIST_PLATFORM_PCECD) ? _T("pcecd_") : ((pEntry->nPlatform == CDLIST_PLATFORM_SEGACD) ? _T("segacd_") : _T("ngcd_")), pszName);
if (!nSide) {
BuildPreviewPath(szPath, MAX_PATH, szNeoCDCoverDir, tszName);
@@ -308,6 +308,8 @@ static const TCHAR* PlatformText(INT32 nPlatform)
return _T("Neo Geo CD");
if (nPlatform == CDLIST_PLATFORM_PCECD)
return _T("PCE CD");
if (nPlatform == CDLIST_PLATFORM_SEGACD)
return _T("Sega CD");
return _T("Unknown");
}
@@ -606,6 +608,20 @@ static void ShowZoom(INT32 nSide)
nZoomPngSize = 0;
}
static INT32 PlatformAvailable(INT32 nPlatform)
{
#ifdef BUILD_NEOGEO
if (nPlatform == CDLIST_PLATFORM_NEOCD) return 1;
#endif
#ifdef BUILD_PCE
if (nPlatform == CDLIST_PLATFORM_PCECD) return 1;
#endif
#ifdef BUILD_MEGADRIVE
if (nPlatform == CDLIST_PLATFORM_SEGACD) return 1;
#endif
return 0;
}
static bool SelectForPlay()
{
const CDLibraryEntry* pEntry = GetLibraryEntry(nSelectedItem);
@@ -613,13 +629,7 @@ static bool SelectForPlay()
MessageBox(hNeoCDWnd, _T("Select a CD image first."), _T(APP_TITLE), MB_OK | MB_ICONWARNING);
return false;
}
#if !defined(BUILD_NEOGEO)
if (pEntry->nPlatform != CDLIST_PLATFORM_PCECD) {
#elif !defined(BUILD_PCE)
if (pEntry->nPlatform != CDLIST_PLATFORM_NEOCD) {
#else
if (pEntry->nPlatform != CDLIST_PLATFORM_NEOCD && pEntry->nPlatform != CDLIST_PLATFORM_PCECD) {
#endif
if (!PlatformAvailable(pEntry->nPlatform)) {
MessageBox(hNeoCDWnd, _T("The required CD driver is unavailable in this build."), _T(APP_TITLE), MB_OK | MB_ICONERROR);
return false;
}
@@ -629,6 +639,12 @@ static bool SelectForPlay()
return false;
}
#endif
#ifdef BUILD_MEGADRIVE
if (pEntry->nPlatform == CDLIST_PLATFORM_SEGACD && BurnDrvGetIndex((char*)"md_segacd") < 0) {
MessageBox(hNeoCDWnd, _T("The Sega CD driver is unavailable."), _T(APP_TITLE), MB_OK | MB_ICONERROR);
return false;
}
#endif
#ifdef BUILD_PCE
if (pEntry->nPlatform == CDLIST_PLATFORM_PCECD && BurnDrvGetIndex((char*)"pce_scdsys") < 0) {
MessageBox(hNeoCDWnd, _T("The PCE CD driver is unavailable."), _T(APP_TITLE), MB_OK | MB_ICONERROR);
@@ -709,6 +725,9 @@ static INT_PTR CALLBACK NeoCDList_WndProc(HWND hDlg, UINT nMessage, WPARAM wPara
#endif
#ifdef BUILD_PCE
if (nPlatform == CDLIST_PLATFORM_PCECD) BurnerLoadDriver(_T("pce_scdsys"));
#endif
#ifdef BUILD_MEGADRIVE
if (nPlatform == CDLIST_PLATFORM_SEGACD) BurnerLoadDriver(_T("md_segacd"));
#endif
return TRUE;
}
+22
View File
@@ -1,6 +1,7 @@
// Screen Window
#include "burner.h"
#include "pcecdlist.h"
#include "segacdlist.h"
#include <process.h>
#include <shlobj.h>
@@ -22,6 +23,17 @@ static void SetPCECDTitle()
}
#endif
#ifdef BUILD_MEGADRIVE
static void SetSegaCDTitle()
{
TCHAR szText[1024] = _T("");
TCHAR* pszTitle = SegaCDInfo_Text(DRV_FULLNAME);
_sntprintf(szText, _countof(szText), _T(APP_TITLE) _T(" v%.20s") _T(SEPERATOR_1) _T("%s") _T(SEPERATOR_1) _T("%s"), szAppBurnVer, BurnDrvGetText(DRV_FULLNAME), pszTitle ? pszTitle : FBALoadStringEx(hAppInst, IDS_UNIDENTIFIED_CD, true));
szText[_countof(szText) - 1] = _T('\0');
SetWindowText(hScrnWnd, szText);
}
#endif
#ifdef BUILD_NEOGEO
static void SetNeoCDTitle(TCHAR* pszTitle)
{
@@ -1100,6 +1112,7 @@ static t_hw_Struct scrn_gamehw_cfg[] = {
{ "neogeo", { HARDWARE_SNK_NEOGEO, HARDWARE_SNK_MVS, HARDWARE_SNK_DEDICATED_PCB, 0 } },
{ "neogeocd", { HARDWARE_SNK_NEOCD, 0 } },
{ "pcecd", { HARDWARE_PCENGINE_PCE_CD, 0 } },
{ "segacd", { HARDWARE_SEGA_MEGACD, 0 } },
{ "arcade", { ~0, 0 } }, // default, if not found above
{ "\0", { 0 } } // end
};
@@ -1608,6 +1621,9 @@ INT32 BurnerQuickLoad(const INT32 nMode, const TCHAR* pszSelect)
case CDLIST_PLATFORM_PCECD:
pszDrvName = _T("pce_scdsys");
break;
case CDLIST_PLATFORM_SEGACD:
pszDrvName = _T("md_segacd");
break;
default:
FBAPopupAddText(PUF_TEXT_DEFAULT, MAKEINTRESOURCE(IDS_ERR_CD_IMAGE_IDENTIFY), pszSelect);
FBAPopupDisplay(PUF_TYPE_ERROR);
@@ -4727,6 +4743,12 @@ int ScrnTitle()
return 0;
}
#endif
#ifdef BUILD_MEGADRIVE
if ((BurnDrvGetHardwareCode() & HARDWARE_PUBLIC_MASK) == HARDWARE_SEGA_MEGACD) {
SetSegaCDTitle();
return 0;
}
#endif
} else {
_stprintf(szText, _T(APP_TITLE) _T( " v%.20s") _T(SEPERATOR_1) _T("[%s]"), szAppBurnVer, FBALoadStringEx(hAppInst, IDS_SCRN_NOGAME, true));
+1 -1
View File
@@ -2056,7 +2056,7 @@ void LoadDrvIcons()
// By hardwares
if (bIconsByHardwares) {
if ((nCode & HARDWARE_PUBLIC_MASK) == HARDWARE_SEGA_MEGADRIVE) {
if ((nCode & HARDWARE_PUBLIC_MASK) == HARDWARE_SEGA_MEGADRIVE || (nCode & HARDWARE_PUBLIC_MASK) == HARDWARE_SEGA_MEGACD) {
hDrvIcon[nDrvIndex] = pIconsCache[nDrvCount + ICON_MEGADRIVE]; continue;
}
else
+12
View File
@@ -1756,6 +1756,18 @@ static UINT8* cdimgReadTOC(INT32 track)
return TOCEntry;
}
if (track & CDEmuTOC_TRACKEND) {
track = bcd(track & 0xff);
if (track >= cdimgTOC->FirstTrack && track <= cdimgTOC->LastTrack) {
TOCEntry[0] = cdimgTOC->TrackData[track - 1].EndAddress[1];
TOCEntry[1] = cdimgTOC->TrackData[track - 1].EndAddress[2];
TOCEntry[2] = cdimgTOC->TrackData[track - 1].EndAddress[3];
TOCEntry[3] = cdimgTOC->TrackData[track - 1].Control >> 4;
}
return TOCEntry;
}
track = bcd(track);
if (track >= cdimgTOC->FirstTrack && track <= cdimgTOC->LastTrack) {
TOCEntry[0] = cdimgTOC->TrackData[track - 1].Address[1];
+2 -1
View File
@@ -5,7 +5,8 @@
// CD emulation module
enum CDEmuStatusValue { idle = 0, reading, playing, paused, seeking, fastforward, fastreverse };
enum CDEmuReadTOCFlags { CDEmuTOC_FIRSTLAST = 0x1000, CDEmuTOC_LASTMSF, CDEmuTOC_FIRSTINDEX, CDEmuTOC_ENDOFDISC };
// CDEmuTOC_TRACKEND is or'ed with a bcd track number: msf where the track ends (start of the next track's pregap)
enum CDEmuReadTOCFlags { CDEmuTOC_FIRSTLAST = 0x1000, CDEmuTOC_LASTMSF, CDEmuTOC_FIRSTINDEX, CDEmuTOC_ENDOFDISC, CDEmuTOC_TRACKEND = 0x2000 };
extern TCHAR CDEmuImage[MAX_PATH];
extern UINT8 CDEmuImageTOCSHA1[MAX_PATH];