NeoGeo CD: add support for bin/cue and ccd/img/sub (trurip). remove support for mode1-2048 (.iso + .wav). new cdimage support is better, faster, no pauses when cd audio starts, works with savestates(git diff .)
This commit is contained in:
parent
6d3031d56d
commit
3fb85cb996
|
@ -22,7 +22,7 @@ depobj += about.o bzip.o choose_monitor.o cona.o debugger.o drv.o d3dkmt_sync.o
|
|||
\
|
||||
2xpm.o 2xsai.o ddt3x.o epx.o hq2xs.o hq2xs_16.o xbr.o \
|
||||
\
|
||||
aud_dsound3.o aud_xaudio2.o cd_isowav.o cdsound.o ddraw_core.o dinput_core.o directx9_core.o dsound_core.o \
|
||||
aud_dsound3.o aud_xaudio2.o cd_img.o ddraw_core.o dinput_core.o directx9_core.o dsound_core.o \
|
||||
inp_dinput.o prf_performance_counter.o vid_d3d.o vid_ddraw.o vid_ddrawfx.o vid_directx9.o vid_directx_support.o
|
||||
|
||||
ifdef INCLUDE_7Z_SUPPORT
|
||||
|
|
|
@ -1,16 +1,10 @@
|
|||
// NeoGeo CD-WIP - Jan 25, 2019
|
||||
// NeoGeo CD-WIP - Jan 25, 2019 - present
|
||||
|
||||
// mit .bin/.cue & .ccd/.img (trurip) unterstutzung (feb.4.2019)
|
||||
// todo:
|
||||
// burner/win32/neocdsel.cpp needs updated to support mode1/2352
|
||||
// ssrpg bugs in sfx-audio in cutscene after starting game
|
||||
|
||||
// neogeocd: states WIP "the 3rd attempt."
|
||||
// working restrictions AKA at least it no longer crashes :)
|
||||
// game must be fully loaded in order to use them.
|
||||
//
|
||||
// TODO: (in order to remove restrictions)
|
||||
// state-able iso-library
|
||||
// state-able wav-player
|
||||
// Advanced-TODO:
|
||||
// stream wav instead of telling directX/SDL to play WAVfile.
|
||||
// this will fix neo-cdplayer in bios, get rid of platform-specific stuff, etc..
|
||||
// Note: this text will self-destruct upon completion / end of WIP. -dink
|
||||
|
||||
/*
|
||||
* FB Alpha Neo Geo module
|
||||
|
@ -79,6 +73,8 @@
|
|||
#include "bitswap.h"
|
||||
#include "neocdlist.h"
|
||||
|
||||
static INT32 isowav_mode = 0;
|
||||
|
||||
// #undef USE_SPEEDHACKS
|
||||
|
||||
// #define LOG_IRQ
|
||||
|
@ -280,7 +276,7 @@ static INT32 nNeoControlConfig;
|
|||
static INT32 nNeoSystemType;
|
||||
static bool bZ80BIOS;
|
||||
|
||||
static INT32 /*nNeoCDCyclesIRQ = 0,*/ nNeoCDCyclesIRQPeriod = 0;
|
||||
static INT32 nNeoCDCyclesIRQ = 0, nNeoCDCyclesIRQPeriod = 0;
|
||||
|
||||
#ifdef BUILD_A68K
|
||||
static bool bUseAsm68KCoreOldValue = false;
|
||||
|
@ -1555,6 +1551,7 @@ INT32 NeoScan(INT32 nAction, INT32* pnMin)
|
|||
|
||||
SCAN_VAR(nNeoCDMode);
|
||||
SCAN_VAR(nff0002);
|
||||
CDEmuScan(nAction, pnMin);
|
||||
}
|
||||
|
||||
if (nAction & ACB_WRITE) {
|
||||
|
@ -2512,11 +2509,17 @@ static void LC8951UpdateHeader()
|
|||
} else {
|
||||
|
||||
// HEAD registers have header
|
||||
|
||||
LC8951RegistersR[4] = ((NeoCDSectorMin / 10) << 4) | (NeoCDSectorMin % 10); // HEAD0
|
||||
LC8951RegistersR[5] = ((NeoCDSectorSec / 10) << 4) | (NeoCDSectorSec % 10); // HEAD1
|
||||
LC8951RegistersR[6] = ((NeoCDSectorFrm / 10) << 4) | (NeoCDSectorFrm % 10); // HEAD2
|
||||
LC8951RegistersR[7] = 1; // HEAD3
|
||||
if (isowav_mode) {
|
||||
LC8951RegistersR[4] = ((NeoCDSectorMin / 10) << 4) | (NeoCDSectorMin % 10); // HEAD0
|
||||
LC8951RegistersR[5] = ((NeoCDSectorSec / 10) << 4) | (NeoCDSectorSec % 10); // HEAD1
|
||||
LC8951RegistersR[6] = ((NeoCDSectorFrm / 10) << 4) | (NeoCDSectorFrm % 10); // HEAD2
|
||||
LC8951RegistersR[7] = 1; // HEAD3
|
||||
} else {
|
||||
LC8951RegistersR[4] = NeoCDSectorData[12]; // HEAD0
|
||||
LC8951RegistersR[5] = NeoCDSectorData[13]; // HEAD1
|
||||
LC8951RegistersR[6] = NeoCDSectorData[14]; // HEAD2
|
||||
LC8951RegistersR[7] = NeoCDSectorData[15]; // HEAD3
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2535,8 +2538,12 @@ static char* LC8951InitTransfer()
|
|||
return NULL;
|
||||
}
|
||||
|
||||
return NeoCDSectorData + ((LC8951RegistersW[5] << 8) | LC8951RegistersW[4]);
|
||||
}
|
||||
if (isowav_mode) {
|
||||
return NeoCDSectorData + ((LC8951RegistersW[5] << 8) | LC8951RegistersW[4]);
|
||||
} else {
|
||||
return NeoCDSectorData + 12 + ((LC8951RegistersW[5] << 8) | LC8951RegistersW[4]);
|
||||
}
|
||||
}
|
||||
|
||||
static void LC8951EndTransfer()
|
||||
{
|
||||
|
@ -2556,21 +2563,21 @@ static void LC8951EndTransfer()
|
|||
|
||||
static void LC8951Reset()
|
||||
{
|
||||
memset(NeoCDSectorData, 0, sizeof(NeoCDSectorData));
|
||||
|
||||
memset(LC8951RegistersR, 0, sizeof(LC8951RegistersR));
|
||||
memset(LC8951RegistersW, 0, sizeof(LC8951RegistersW));
|
||||
LC8951RegistersR[0x04] = 0x01; // head0
|
||||
|
||||
bNeoCDLoadSector = false;
|
||||
|
||||
LC8951RegistersR[0x01] = 0xFF;
|
||||
LC8951RegistersR[0x0F] = 0x80;
|
||||
|
||||
memset(NeoCDSectorData, 0, sizeof(NeoCDSectorData));
|
||||
LC8951UpdateHeader();
|
||||
}
|
||||
|
||||
// for NeoGeo CD (WAV playback)
|
||||
void wav_exit();
|
||||
void wav_pause(bool bResume);
|
||||
//void wav_exit();
|
||||
//void wav_pause(bool bResume);
|
||||
|
||||
static void NeoCDProcessCommand()
|
||||
{
|
||||
|
@ -2598,16 +2605,29 @@ static void NeoCDProcessCommand()
|
|||
case 0: {
|
||||
UINT8* ChannelData = CDEmuReadQChannel();
|
||||
|
||||
NeoCDCommsStatusFIFO[2] = ChannelData[1] / 10;
|
||||
NeoCDCommsStatusFIFO[3] = ChannelData[1] % 10;
|
||||
if (isowav_mode) {
|
||||
NeoCDCommsStatusFIFO[2] = ChannelData[1] / 10;
|
||||
NeoCDCommsStatusFIFO[3] = ChannelData[1] % 10;
|
||||
|
||||
NeoCDCommsStatusFIFO[4] = ChannelData[2] / 10;
|
||||
NeoCDCommsStatusFIFO[5] = ChannelData[2] % 10;
|
||||
NeoCDCommsStatusFIFO[4] = ChannelData[2] / 10;
|
||||
NeoCDCommsStatusFIFO[5] = ChannelData[2] % 10;
|
||||
|
||||
NeoCDCommsStatusFIFO[6] = ChannelData[3] / 10;
|
||||
NeoCDCommsStatusFIFO[7] = ChannelData[3] % 10;
|
||||
|
||||
NeoCDCommsStatusFIFO[8] = ChannelData[7];
|
||||
NeoCDCommsStatusFIFO[6] = ChannelData[3] / 10;
|
||||
NeoCDCommsStatusFIFO[7] = ChannelData[3] % 10;
|
||||
|
||||
NeoCDCommsStatusFIFO[8] = ChannelData[7];
|
||||
} else {
|
||||
NeoCDCommsStatusFIFO[2] = ChannelData[1] >> 4;
|
||||
NeoCDCommsStatusFIFO[3] = ChannelData[1] & 0x0F;
|
||||
|
||||
NeoCDCommsStatusFIFO[4] = ChannelData[2] >> 4;
|
||||
NeoCDCommsStatusFIFO[5] = ChannelData[2] & 0x0F;
|
||||
|
||||
NeoCDCommsStatusFIFO[6] = ChannelData[3] >> 4;
|
||||
NeoCDCommsStatusFIFO[7] = ChannelData[3] & 0x0F;
|
||||
|
||||
NeoCDCommsStatusFIFO[8] = ChannelData[7];
|
||||
}
|
||||
|
||||
// bprintf(PRINT_ERROR, _T(" %02i %02i:%02i:%02i %02i:%02i:%02i %02i\n"), ChannelData[0], ChannelData[1], ChannelData[2], ChannelData[3], ChannelData[4], ChannelData[5], ChannelData[6], ChannelData[7]);
|
||||
|
||||
|
@ -2616,16 +2636,29 @@ static void NeoCDProcessCommand()
|
|||
case 1: {
|
||||
UINT8* ChannelData = CDEmuReadQChannel();
|
||||
|
||||
NeoCDCommsStatusFIFO[2] = ChannelData[4] / 10;
|
||||
NeoCDCommsStatusFIFO[3] = ChannelData[4] % 10;
|
||||
if (isowav_mode) {
|
||||
NeoCDCommsStatusFIFO[2] = ChannelData[4] / 10;
|
||||
NeoCDCommsStatusFIFO[3] = ChannelData[4] % 10;
|
||||
|
||||
NeoCDCommsStatusFIFO[4] = ChannelData[5] / 10;
|
||||
NeoCDCommsStatusFIFO[5] = ChannelData[5] % 10;
|
||||
NeoCDCommsStatusFIFO[4] = ChannelData[5] / 10;
|
||||
NeoCDCommsStatusFIFO[5] = ChannelData[5] % 10;
|
||||
|
||||
NeoCDCommsStatusFIFO[6] = ChannelData[6] / 10;
|
||||
NeoCDCommsStatusFIFO[7] = ChannelData[6] % 10;
|
||||
NeoCDCommsStatusFIFO[6] = ChannelData[6] / 10;
|
||||
NeoCDCommsStatusFIFO[7] = ChannelData[6] % 10;
|
||||
|
||||
NeoCDCommsStatusFIFO[8] = ChannelData[7];
|
||||
NeoCDCommsStatusFIFO[8] = ChannelData[7];
|
||||
} else {
|
||||
NeoCDCommsStatusFIFO[2] = ChannelData[4] >> 4;
|
||||
NeoCDCommsStatusFIFO[3] = ChannelData[4] & 0x0F;
|
||||
|
||||
NeoCDCommsStatusFIFO[4] = ChannelData[5] >> 4;
|
||||
NeoCDCommsStatusFIFO[5] = ChannelData[5] & 0x0F;
|
||||
|
||||
NeoCDCommsStatusFIFO[6] = ChannelData[6] >> 4;
|
||||
NeoCDCommsStatusFIFO[7] = ChannelData[6] & 0x0F;
|
||||
|
||||
NeoCDCommsStatusFIFO[8] = ChannelData[7];
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
@ -2633,59 +2666,99 @@ static void NeoCDProcessCommand()
|
|||
|
||||
UINT8* ChannelData = CDEmuReadQChannel();
|
||||
|
||||
NeoCDCommsStatusFIFO[2] = ChannelData[0] / 10;
|
||||
NeoCDCommsStatusFIFO[3] = ChannelData[0] % 10;
|
||||
if (isowav_mode) {
|
||||
NeoCDCommsStatusFIFO[2] = ChannelData[0] / 10;
|
||||
NeoCDCommsStatusFIFO[3] = ChannelData[0] % 10;
|
||||
|
||||
NeoCDCommsStatusFIFO[8] = ChannelData[7];
|
||||
} else {
|
||||
NeoCDCommsStatusFIFO[2] = ChannelData[0] >> 4;
|
||||
NeoCDCommsStatusFIFO[3] = ChannelData[0] & 0x0F;
|
||||
|
||||
NeoCDCommsStatusFIFO[8] = ChannelData[7];
|
||||
NeoCDCommsStatusFIFO[8] = ChannelData[7];
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case 3: {
|
||||
UINT8* TOCEntry = CDEmuReadTOC(-2);
|
||||
|
||||
NeoCDCommsStatusFIFO[2] = TOCEntry[0] / 10;
|
||||
NeoCDCommsStatusFIFO[3] = TOCEntry[0] % 10;
|
||||
if (isowav_mode) {
|
||||
NeoCDCommsStatusFIFO[2] = TOCEntry[0] / 10;
|
||||
NeoCDCommsStatusFIFO[3] = TOCEntry[0] % 10;
|
||||
|
||||
NeoCDCommsStatusFIFO[4] = TOCEntry[1] / 10;
|
||||
NeoCDCommsStatusFIFO[5] = TOCEntry[1] % 10;
|
||||
NeoCDCommsStatusFIFO[4] = TOCEntry[1] / 10;
|
||||
NeoCDCommsStatusFIFO[5] = TOCEntry[1] % 10;
|
||||
|
||||
NeoCDCommsStatusFIFO[6] = TOCEntry[2] / 10;
|
||||
NeoCDCommsStatusFIFO[7] = TOCEntry[2] % 10;
|
||||
NeoCDCommsStatusFIFO[6] = TOCEntry[2] / 10;
|
||||
NeoCDCommsStatusFIFO[7] = TOCEntry[2] % 10;
|
||||
} else {
|
||||
NeoCDCommsStatusFIFO[2] = TOCEntry[0] >> 4;
|
||||
NeoCDCommsStatusFIFO[3] = TOCEntry[0] & 0x0F;
|
||||
|
||||
NeoCDCommsStatusFIFO[4] = TOCEntry[1] >> 4;
|
||||
NeoCDCommsStatusFIFO[5] = TOCEntry[1] & 0x0F;
|
||||
|
||||
NeoCDCommsStatusFIFO[6] = TOCEntry[2] >> 4;
|
||||
NeoCDCommsStatusFIFO[7] = TOCEntry[2] & 0x0F;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case 4: {
|
||||
UINT8* TOCEntry = CDEmuReadTOC(-1);
|
||||
|
||||
NeoCDCommsStatusFIFO[2] = TOCEntry[0] / 10;
|
||||
NeoCDCommsStatusFIFO[3] = TOCEntry[0] % 10;
|
||||
if (isowav_mode) {
|
||||
NeoCDCommsStatusFIFO[2] = TOCEntry[0] / 10;
|
||||
NeoCDCommsStatusFIFO[3] = TOCEntry[0] % 10;
|
||||
|
||||
NeoCDCommsStatusFIFO[4] = TOCEntry[1] / 10;
|
||||
NeoCDCommsStatusFIFO[5] = TOCEntry[1] % 10;
|
||||
NeoCDCommsStatusFIFO[4] = TOCEntry[1] / 10;
|
||||
NeoCDCommsStatusFIFO[5] = TOCEntry[1] % 10;
|
||||
} else {
|
||||
NeoCDCommsStatusFIFO[2] = TOCEntry[0] > 4;
|
||||
NeoCDCommsStatusFIFO[3] = TOCEntry[0] & 0x0F;
|
||||
|
||||
NeoCDCommsStatusFIFO[4] = TOCEntry[1] >> 4;
|
||||
NeoCDCommsStatusFIFO[5] = TOCEntry[1] & 0x0F;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case 5: {
|
||||
NeoCDTrack = NeoCDCommsCommandFIFO[4] * 10 + NeoCDCommsCommandFIFO[5];
|
||||
NeoCDTrack = (NeoCDCommsCommandFIFO[4] << 4) | NeoCDCommsCommandFIFO[5];
|
||||
|
||||
UINT8* TOCEntry = CDEmuReadTOC(NeoCDTrack);
|
||||
|
||||
NeoCDCommsStatusFIFO[2] = TOCEntry[0] / 10;
|
||||
NeoCDCommsStatusFIFO[3] = TOCEntry[0] % 10;
|
||||
if (isowav_mode) {
|
||||
NeoCDCommsStatusFIFO[2] = TOCEntry[0] / 10;
|
||||
NeoCDCommsStatusFIFO[3] = TOCEntry[0] % 10;
|
||||
|
||||
NeoCDCommsStatusFIFO[4] = TOCEntry[1] / 10;
|
||||
NeoCDCommsStatusFIFO[5] = TOCEntry[1] % 10;
|
||||
NeoCDCommsStatusFIFO[4] = TOCEntry[1] / 10;
|
||||
NeoCDCommsStatusFIFO[5] = TOCEntry[1] % 10;
|
||||
|
||||
NeoCDCommsStatusFIFO[6] = TOCEntry[2] / 10;
|
||||
NeoCDCommsStatusFIFO[7] = TOCEntry[2] % 10;
|
||||
NeoCDCommsStatusFIFO[6] = TOCEntry[2] / 10;
|
||||
NeoCDCommsStatusFIFO[7] = TOCEntry[2] % 10;
|
||||
} else {
|
||||
NeoCDCommsStatusFIFO[2] = TOCEntry[0] >> 4;
|
||||
NeoCDCommsStatusFIFO[3] = TOCEntry[0] & 0x0F;
|
||||
|
||||
NeoCDCommsStatusFIFO[4] = TOCEntry[1] >> 4;
|
||||
NeoCDCommsStatusFIFO[5] = TOCEntry[1] & 0x0F;
|
||||
|
||||
NeoCDCommsStatusFIFO[6] = TOCEntry[2] >> 4;
|
||||
NeoCDCommsStatusFIFO[7] = TOCEntry[2] & 0x0F;
|
||||
}
|
||||
|
||||
// bit 3 of the 1st minutes digit indicates a data track
|
||||
if (TOCEntry[3] & 4) {
|
||||
NeoCDCommsStatusFIFO[6] |= 8;
|
||||
}
|
||||
|
||||
NeoCDCommsStatusFIFO[8] = NeoCDTrack % 10;
|
||||
if (isowav_mode) {
|
||||
NeoCDCommsStatusFIFO[8] = NeoCDTrack % 10;
|
||||
} else {
|
||||
NeoCDCommsStatusFIFO[8] = NeoCDTrack & 0x0F;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
@ -2703,7 +2776,7 @@ static void NeoCDProcessCommand()
|
|||
|
||||
// must be 02, 0E, 0F, or 05
|
||||
NeoCDCommsStatusFIFO[2] = 0;
|
||||
NeoCDCommsStatusFIFO[3] = 5;
|
||||
NeoCDCommsStatusFIFO[3] = (isowav_mode) ? 5 : NeoCDAssyStatus;
|
||||
|
||||
NeoCDCommsStatusFIFO[4] = 0;
|
||||
NeoCDCommsStatusFIFO[5] = 0;
|
||||
|
@ -2730,7 +2803,8 @@ static void NeoCDProcessCommand()
|
|||
NeoCDSectorLBA += NeoCDCommsCommandFIFO[6] * (10 );
|
||||
NeoCDSectorLBA += NeoCDCommsCommandFIFO[7] * ( 1 );
|
||||
|
||||
NeoCDSectorLBA -= CD_FRAMES_PREGAP;
|
||||
if (isowav_mode)
|
||||
NeoCDSectorLBA -= CD_FRAMES_PREGAP;
|
||||
|
||||
CDEmuStartRead();
|
||||
// LC8951RegistersR[1] |= 0x20;
|
||||
|
@ -2740,7 +2814,11 @@ static void NeoCDProcessCommand()
|
|||
bprintf(PRINT_ERROR, _T("*** Switching CD mode to audio while in CD-ROM mode!(PC: 0x%06X)\n"), SekGetPC(-1));
|
||||
}
|
||||
|
||||
CDEmuPlay((NeoCDCommsCommandFIFO[2] * 10) + NeoCDCommsCommandFIFO[3], (NeoCDCommsCommandFIFO[4] * 10) + NeoCDCommsCommandFIFO[5], (NeoCDCommsCommandFIFO[6] * 10) + NeoCDCommsCommandFIFO[7]);
|
||||
if (isowav_mode) {
|
||||
CDEmuPlay((NeoCDCommsCommandFIFO[2] * 10) + NeoCDCommsCommandFIFO[3], (NeoCDCommsCommandFIFO[4] * 10) + NeoCDCommsCommandFIFO[5], (NeoCDCommsCommandFIFO[6] * 10) + NeoCDCommsCommandFIFO[7]);
|
||||
} else {
|
||||
CDEmuPlay((NeoCDCommsCommandFIFO[2] * 16) + NeoCDCommsCommandFIFO[3], (NeoCDCommsCommandFIFO[4] * 16) + NeoCDCommsCommandFIFO[5], (NeoCDCommsCommandFIFO[6] * 16) + NeoCDCommsCommandFIFO[7]);
|
||||
}
|
||||
}
|
||||
|
||||
NeoCDAssyStatus = 1;
|
||||
|
@ -2763,14 +2841,14 @@ static void NeoCDProcessCommand()
|
|||
NeoCDAssyStatus = 4;
|
||||
bNeoCDLoadSector = false;
|
||||
CDEmuPause();
|
||||
wav_pause(0);
|
||||
//if (isowav_mode) wav_pause(0);
|
||||
break;
|
||||
case 7:
|
||||
// bprintf(PRINT_ERROR, _T(" CD comms received command %i\n"), NeoCDCommsCommandFIFO[0]);
|
||||
NeoCDAssyStatus = 1;
|
||||
bNeoCDLoadSector = true;
|
||||
CDEmuResume();
|
||||
wav_pause(1);
|
||||
//if (isowav_mode) wav_pause(1);
|
||||
break;
|
||||
|
||||
case 8:
|
||||
|
@ -3137,7 +3215,11 @@ void NeoCDReadSector()
|
|||
|
||||
// if (LC8951RegistersW[10] & 0x80) {
|
||||
NeoCDSectorLBA++;
|
||||
NeoCDSectorLBA = CDEmuLoadSector(NeoCDSectorLBA, NeoCDSectorData + 4) - 1;
|
||||
if (isowav_mode) {
|
||||
NeoCDSectorLBA = CDEmuLoadSector(NeoCDSectorLBA, NeoCDSectorData + 4) - 1;
|
||||
} else {
|
||||
NeoCDSectorLBA = CDEmuLoadSector(NeoCDSectorLBA, NeoCDSectorData) - 1;
|
||||
}
|
||||
// }
|
||||
|
||||
if (LC8951RegistersW[10] & 0x80) {
|
||||
|
@ -3148,18 +3230,18 @@ void NeoCDReadSector()
|
|||
LC8951RegistersR[14] = 0x10; // STAT2
|
||||
LC8951RegistersR[15] = 0; // STAT3
|
||||
|
||||
// bprintf(PRINT_IMPORTANT, _T(" Sector %08i (%02i:%02i:%02i) read\n"), NeoCDSectorLBA, NeoCDSectorMin, NeoCDSectorSec, NeoCDSectorFrm);
|
||||
//bprintf(PRINT_IMPORTANT, _T(" Sector %08i (%02i:%02i:%02i) read\n"), NeoCDSectorLBA, NeoCDSectorMin, NeoCDSectorSec, NeoCDSectorFrm);
|
||||
|
||||
INT32 sectoffs = (isowav_mode) ? 0 : 12;
|
||||
|
||||
if (NeoCDSectorData[sectoffs + 4 + 64] == 'g' && !strncmp(NeoCDSectorData + sectoffs + 4, "Copyright by SNK", 16)) {
|
||||
//bprintf(0, _T("\n simulated CDZ protection error\n"));
|
||||
//bprintf(PRINT_ERROR, _T(" %.70hs\n"), NeoCDSectorData + sectoffs + 4);
|
||||
|
||||
#if 1
|
||||
if (NeoCDSectorData[4 + 64] == 'g' && !strncmp(NeoCDSectorData + 4, "Copyright by SNK", 16)) {
|
||||
// printf(PRINT_ERROR, _T(" simulated CDZ protection error\n"));
|
||||
// bprintf(PRINT_ERROR, _T(" %.70hs\n"), NeoCDSectorData + 4);
|
||||
|
||||
NeoCDSectorData[4 + 64] = 'f';
|
||||
NeoCDSectorData[sectoffs + 4 + 64] = 'f';
|
||||
|
||||
// LC8951RegistersR[12] = 0x00; // STAT0
|
||||
}
|
||||
#endif
|
||||
|
||||
nIRQAcknowledge &= ~0x20;
|
||||
NeoCDIRQUpdate(0);
|
||||
|
@ -3241,7 +3323,7 @@ void __fastcall neogeoWriteByteCDROM(UINT32 sekAddress, UINT8 byteValue)
|
|||
// bprintf(PRINT_NORMAL, _T(" - Neo Geo CD: 0x%06X -> 0x%02X (PC: 0x%06X)\n"), sekAddress, byteValue, SekGetPC(-1));
|
||||
|
||||
switch (sekAddress & 0xFFFF) {
|
||||
case 0x000E:
|
||||
//case 0x000E:
|
||||
case 0x000F:
|
||||
NeoCDIRQUpdate(byteValue);
|
||||
break;
|
||||
|
@ -3397,15 +3479,18 @@ void __fastcall neogeoWriteWordCDROM(UINT32 sekAddress, UINT16 wordValue)
|
|||
switch (sekAddress & 0xFFFE) {
|
||||
case 0x0002:
|
||||
// bprintf(PRINT_IMPORTANT, _T(" - NGCD Interrupt mask -> 0x%04X (PC: 0x%06X)\n"), wordValue, SekGetPC(-1));
|
||||
nff0002 = wordValue;
|
||||
if ((wordValue & 0x0500) && !(nff0002 & 0x0500))
|
||||
nNeoCDCyclesIRQ = nNeoCDCyclesIRQPeriod;
|
||||
|
||||
nff0002 = wordValue;
|
||||
|
||||
// LC8951RegistersR[1] |= 0x20;
|
||||
|
||||
if (nff0002 & 0x0500)
|
||||
/* if (nff0002 & 0x0500)
|
||||
nNeoCDCyclesIRQPeriod = (INT32)(12000000.0 * nBurnCPUSpeedAdjust / (256.0 * 75.0));
|
||||
else
|
||||
nNeoCDCyclesIRQPeriod = (INT32)(12000000.0 * nBurnCPUSpeedAdjust / (256.0 * 75.0));
|
||||
|
||||
*/
|
||||
break;
|
||||
|
||||
case 0x000E:
|
||||
|
@ -3413,6 +3498,11 @@ void __fastcall neogeoWriteWordCDROM(UINT32 sekAddress, UINT16 wordValue)
|
|||
break;
|
||||
|
||||
// DMA controller
|
||||
case 0x0060:
|
||||
if (wordValue & 0x40) {
|
||||
NeoCDDoDMA();
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x0064:
|
||||
NeoCDDMAAddress1 &= 0x0000FFFF;
|
||||
|
@ -3542,12 +3632,8 @@ void __fastcall neogeoWriteByteTransfer(UINT32 sekAddress, UINT8 byteValue)
|
|||
YM2610ADPCMAROM[nNeoActiveSlot][nADPCMTransferBank + ((sekAddress & 0x0FFFFF) >> 1)] = byteValue;
|
||||
break;
|
||||
case 4: // Z80
|
||||
if (ZetGetBUSREQLine() == 0) {
|
||||
YM2610ADPCMAROM[nNeoActiveSlot][nADPCMTransferBank + ((sekAddress & 0x0FFFFF) >> 1)] = byteValue;
|
||||
} else {
|
||||
if ((sekAddress & 0xfffff) >= 0x20000) break;
|
||||
NeoZ80ROMActive[(sekAddress & 0x1FFFF) >> 1] = byteValue;
|
||||
}
|
||||
if ((sekAddress & 0xfffff) >= 0x20000) break;
|
||||
NeoZ80ROMActive[(sekAddress & 0x1FFFF) >> 1] = byteValue;
|
||||
break;
|
||||
case 5: // Text
|
||||
NeoTextRAM[(sekAddress & 0x3FFFF) >> 1] = byteValue;
|
||||
|
@ -3610,9 +3696,6 @@ UINT8 __fastcall neogeoCDReadByte68KProgram(UINT32 sekAddress)
|
|||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// for NeoGeo CD (WAV playback)
|
||||
void wav_exit();
|
||||
|
||||
static INT32 neogeoReset()
|
||||
{
|
||||
if (nNeoSystemType & NEO_SYS_CART) {
|
||||
|
@ -3681,7 +3764,7 @@ static INT32 neogeoReset()
|
|||
bprintf(PRINT_IMPORTANT, _T(" - Emulating Neo CD system.\n"));
|
||||
|
||||
// exit WAV object if needed
|
||||
wav_exit();
|
||||
//if (isowav_mode) wav_exit();
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -4448,18 +4531,16 @@ static void NeoStandardInputs(INT32 nBank)
|
|||
}
|
||||
}
|
||||
|
||||
#if 1
|
||||
#if 0
|
||||
#define NeoSekRun SekRun
|
||||
#else
|
||||
static INT32 NeoSekRun(const INT32 nCycles)
|
||||
{
|
||||
INT32 nCyclesExecutedTotal = 0, nOldCyclesSegment = nCyclesSegment;
|
||||
|
||||
if (!(nNeoSystemType & NEO_SYS_CD) || !(nff0002 & 0x0050))
|
||||
if (!(nNeoSystemType & NEO_SYS_CD) /*|| !(nff0002 & 0x0050)*/ )
|
||||
return SekRun(nCycles);
|
||||
|
||||
//bprintf(PRINT_NORMAL, _T("***\n"));
|
||||
|
||||
while (nCyclesExecutedTotal < nCycles) {
|
||||
|
||||
INT32 nCyclesExecuted;
|
||||
|
@ -4467,24 +4548,20 @@ static INT32 NeoSekRun(const INT32 nCycles)
|
|||
if (nNeoCDCyclesIRQ <= 0) {
|
||||
nNeoCDCyclesIRQ += nNeoCDCyclesIRQPeriod;
|
||||
|
||||
// Trigger CD mechanism communication interrupt
|
||||
//bprintf(PRINT_NORMAL, _T(" DECI status %i\n"), (LC8951RegistersR[1] & 0x20) >> 5);
|
||||
if ((nff0002 & 0x0500) /*&& (LC8951RegistersR[1] & 0x20)*/ )
|
||||
NeoCDReadSector();
|
||||
|
||||
// Trigger CD mechanism communication interrupt
|
||||
//bprintf(PRINT_NORMAL, _T(" DECI status %i\n"), (LC8951RegistersR[1] & 0x20) >> 5);
|
||||
nIRQAcknowledge &= ~0x10;
|
||||
NeoCDIRQUpdate(0);
|
||||
|
||||
if ((nff0002 & 0x0500) && (LC8951RegistersR[1] & 0x20))
|
||||
NeoCDReadSector();
|
||||
}
|
||||
|
||||
nCyclesSegment = (nNeoCDCyclesIRQ < (nCycles - nCyclesExecutedTotal)) ? nNeoCDCyclesIRQ : (nCycles - nCyclesExecutedTotal);
|
||||
nCyclesExecuted = SekRun(nCyclesSegment);
|
||||
|
||||
//bprintf(PRINT_NORMAL, _T("%010i %010i %010i %010i\n"), nCycles, nCyclesExecutedTotal, nCyclesExecuted, nNeoCDCyclesIRQ);
|
||||
|
||||
nCyclesExecutedTotal += nCyclesExecuted;
|
||||
nNeoCDCyclesIRQ -= nCyclesExecuted;
|
||||
|
||||
}
|
||||
|
||||
nCyclesSegment = nOldCyclesSegment;
|
||||
|
@ -4663,6 +4740,8 @@ INT32 NeoFrame()
|
|||
// uPD499A ticks per second (same as 68K clock)
|
||||
uPD499ASetTicks((INT64)12000000 * nBurnCPUSpeedAdjust / 256);
|
||||
|
||||
nNeoCDCyclesIRQPeriod = (int)(12000000.0 * nBurnCPUSpeedAdjust / (256.0 * 150.0));
|
||||
|
||||
nPrevBurnCPUSpeedAdjust = nBurnCPUSpeedAdjust;
|
||||
}
|
||||
|
||||
|
@ -4706,12 +4785,14 @@ INT32 NeoFrame()
|
|||
// Run 68000
|
||||
|
||||
|
||||
if ((nNeoSystemType & NEO_SYS_CD) && (nff0002 & 0x0050)) {
|
||||
nIRQAcknowledge &= ~0x10;
|
||||
NeoCDIRQUpdate(0);
|
||||
if (isowav_mode) {
|
||||
if ((nNeoSystemType & NEO_SYS_CD) && (nff0002 & 0x0050)) {
|
||||
nIRQAcknowledge &= ~0x10;
|
||||
NeoCDIRQUpdate(0);
|
||||
|
||||
if (nff0002 & 0x0500) {
|
||||
NeoCDReadSector();
|
||||
if (nff0002 & 0x0500) {
|
||||
NeoCDReadSector();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4981,7 +5062,8 @@ INT32 NeoFrame()
|
|||
}
|
||||
|
||||
if (pBurnSoundOut) {
|
||||
CDEmuGetSoundBuffer(pBurnSoundOut, nBurnSoundLen);
|
||||
if (!(LC8951RegistersW[10] & 4))
|
||||
CDEmuGetSoundBuffer(pBurnSoundOut, nBurnSoundLen);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -1,9 +1,6 @@
|
|||
// Run module
|
||||
#include "burner.h"
|
||||
|
||||
// for NeoGeo CD (WAV playback)
|
||||
void wav_pause(bool bResume);
|
||||
|
||||
int bRunPause = 0;
|
||||
int bAltPause = 0;
|
||||
|
||||
|
@ -674,9 +671,6 @@ int RunMessageLoop()
|
|||
}
|
||||
}
|
||||
} else {
|
||||
|
||||
bRunPause ? wav_pause(false) : wav_pause(true);
|
||||
|
||||
// No messages are waiting
|
||||
SplashDestroy(0);
|
||||
RunIdle();
|
||||
|
|
|
@ -1023,7 +1023,7 @@ static void OnCommand(HWND /*hDlg*/, int id, HWND /*hwndCtl*/, UINT codeNotify)
|
|||
nCDEmuSelect = 0;
|
||||
TCHAR szFilter[100];
|
||||
_stprintf(szFilter, _T("%s"), FBALoadStringEx(hAppInst, IDS_CD_SELECT_FILTER, true));
|
||||
memcpy(szFilter + _tcslen(szFilter), _T(" (*.iso,*.cue)\0*.iso;*.cue\0\0"), 28 * sizeof(TCHAR));
|
||||
memcpy(szFilter + _tcslen(szFilter), _T(" (*.ccd,*.cue)\0*.ccd;*.cue\0\0"), 28 * sizeof(TCHAR));
|
||||
TCHAR szTitle[100];
|
||||
_stprintf(szTitle, _T("%s"), FBALoadStringEx(hAppInst, IDS_CD_SELECT_IMAGE_TITLE, true));
|
||||
if (UseDialogs() && !bDrvOkay) {
|
||||
|
|
|
@ -51,13 +51,8 @@ static struct AudOut *pAudOut[]=
|
|||
|
||||
static InterfaceInfo AudInfo = { NULL, NULL, NULL };
|
||||
|
||||
// for NeoGeo CD (WAV playback)
|
||||
void wav_pause(bool bResume);
|
||||
|
||||
INT32 AudBlankSound()
|
||||
{
|
||||
wav_pause(false); // pause / stop if needed
|
||||
|
||||
if (!bAudOkay || nAudActive >= AUD_LEN) {
|
||||
return 1;
|
||||
}
|
||||
|
@ -67,8 +62,6 @@ INT32 AudBlankSound()
|
|||
// This function checks the Sound loop, and if necessary gets some more sound
|
||||
INT32 AudSoundCheck()
|
||||
{
|
||||
if(!bRunPause) wav_pause(true); // resume, if needed
|
||||
|
||||
if (!bAudOkay || nAudActive >= AUD_LEN) {
|
||||
return 1;
|
||||
}
|
||||
|
@ -109,7 +102,6 @@ INT32 AudSoundPlay()
|
|||
INT32 nRet = pAudOut[nAudActive]->SoundPlay();
|
||||
if (!nRet) {
|
||||
bAudPlaying = true;
|
||||
if (bCDEmuOkay) wav_pause(true);
|
||||
}
|
||||
|
||||
return nRet;
|
||||
|
@ -122,8 +114,7 @@ INT32 AudSoundStop()
|
|||
}
|
||||
|
||||
bAudPlaying = false;
|
||||
if (bCDEmuOkay) wav_pause(false);
|
||||
|
||||
|
||||
return pAudOut[nAudActive]->SoundStop();
|
||||
}
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@ CDEmuStatusValue CDEmuStatus;
|
|||
static InterfaceInfo CDEmuInfo = { NULL, NULL, NULL };
|
||||
|
||||
#if defined BUILD_WIN32
|
||||
extern struct CDEmuDo isowavDo;
|
||||
extern struct CDEmuDo cdimgDo;
|
||||
#elif defined BUILD_SDL
|
||||
// CD emulation module
|
||||
#elif defined (_XBOX)
|
||||
|
@ -19,7 +19,7 @@ static InterfaceInfo CDEmuInfo = { NULL, NULL, NULL };
|
|||
static struct CDEmuDo* pCDEmuDo[] =
|
||||
{
|
||||
#if defined BUILD_WIN32
|
||||
&isowavDo,
|
||||
&cdimgDo,
|
||||
#elif defined BUILD_SDL
|
||||
// CD emulation module
|
||||
#elif defined (_XBOX)
|
||||
|
@ -117,6 +117,15 @@ INT32 CDEmuGetSoundBuffer(INT16* buffer, INT32 samples)
|
|||
return pCDEmuDo[nCDEmuSelect]->CDEmuGetSoundBuffer(buffer, samples);
|
||||
}
|
||||
|
||||
INT32 CDEmuScan(INT32 nAction, INT32 *pnMin)
|
||||
{
|
||||
if (!bCDEmuOkay || nCDEmuSelect >= CDEMU_LEN) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
return pCDEmuDo[nCDEmuSelect]->CDEmuScan(nAction, pnMin);
|
||||
}
|
||||
|
||||
InterfaceInfo* CDEmuGetInfo()
|
||||
{
|
||||
if (IntInfoInit(&CDEmuInfo)) {
|
||||
|
|
|
@ -16,6 +16,7 @@ INT32 CDEmuLoadSector(INT32 LBA, char* pBuffer);
|
|||
UINT8* CDEmuReadTOC(INT32 track);
|
||||
UINT8* CDEmuReadQChannel();
|
||||
INT32 CDEmuGetSoundBuffer(INT16* buffer, INT32 samples);
|
||||
INT32 CDEmuScan(INT32 nAction, INT32 *pnMin);
|
||||
|
||||
static inline CDEmuStatusValue CDEmuGetStatus()
|
||||
{
|
||||
|
|
|
@ -0,0 +1,866 @@
|
|||
// FBAlpha cd-img, TruRip .ccd/.sub/.img support by Jan Klaassen
|
||||
// .bin/.cue re-work by dink
|
||||
|
||||
#include "burner.h"
|
||||
#include "io.h"
|
||||
|
||||
const int MAXIMUM_NUMBER_TRACKS = 100;
|
||||
|
||||
const int CD_FRAMES_MINUTE = 60 * 75;
|
||||
const int CD_FRAMES_SECOND = 75;
|
||||
|
||||
const int CD_TYPE_NONE = 1 << 0;
|
||||
const int CD_TYPE_BINCUE = 1 << 1;
|
||||
const int CD_TYPE_CCD = 1 << 2;
|
||||
|
||||
static int cd_pregap;
|
||||
|
||||
struct MSF { UINT8 M; UINT8 S; UINT8 F; };
|
||||
struct MSFAddress { UINT8 Control; MSF MSF; };
|
||||
|
||||
struct cdimgTRACK_DATA { UINT8 Control; UINT8 TrackNumber; UINT8 Address[4]; UINT8 EndAddress[4]; };
|
||||
struct cdimgCDROM_TOC { UINT8 FirstTrack; UINT8 LastTrack; UINT8 ImageType; TCHAR Image[MAX_PATH]; cdimgTRACK_DATA TrackData[MAXIMUM_NUMBER_TRACKS]; };
|
||||
|
||||
static cdimgCDROM_TOC* cdimgTOC;
|
||||
|
||||
static FILE* cdimgFile = NULL;
|
||||
static int cdimgFileSize = 0;
|
||||
static int cdimgTrack = 0;
|
||||
static int cdimgLBA = 0;
|
||||
|
||||
static int cdimgSamples = 0;
|
||||
|
||||
// identical to the format used in clonecd .sub files, can use memcpy
|
||||
struct QData { UINT8 Control; char track; char index; MSF MSFrel; char unused; MSF MSFabs; unsigned short CRC; };
|
||||
|
||||
static QData* QChannel = NULL;
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
const int cdimgOUT_SIZE = 2352;
|
||||
static int cdimgOutputbufferSize = 0;
|
||||
|
||||
static short* cdimgOutputbuffer = NULL;
|
||||
|
||||
static int cdimgOutputPosition;
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
TCHAR* GetIsoPath()
|
||||
{
|
||||
if (cdimgTOC) {
|
||||
return cdimgTOC->Image;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static UINT8 bcd(const UINT8 v)
|
||||
{
|
||||
return ((v >> 4) * 10) + (v & 0x0F);
|
||||
}
|
||||
|
||||
static UINT8 tobcd(const UINT8 v)
|
||||
{
|
||||
return ((v / 10) << 4) | (v % 10);
|
||||
}
|
||||
|
||||
static const UINT8* cdimgLBAToMSF(int LBA)
|
||||
{
|
||||
static UINT8 address[4];
|
||||
|
||||
address[0] = 0;
|
||||
address[1] = tobcd(LBA / CD_FRAMES_MINUTE);
|
||||
address[2] = tobcd(LBA % CD_FRAMES_MINUTE / CD_FRAMES_SECOND);
|
||||
address[3] = tobcd(LBA % CD_FRAMES_SECOND);
|
||||
|
||||
return address;
|
||||
}
|
||||
|
||||
static int cdimgMSFToLBA(const UINT8* address)
|
||||
{
|
||||
int LBA;
|
||||
|
||||
LBA = bcd(address[3]);
|
||||
LBA += bcd(address[2]) * CD_FRAMES_SECOND;
|
||||
LBA += bcd(address[1]) * CD_FRAMES_MINUTE;
|
||||
|
||||
return LBA;
|
||||
}
|
||||
|
||||
static const UINT8* dinkLBAToMSF(const int LBA) // not BCD version
|
||||
{
|
||||
static UINT8 address[4];
|
||||
|
||||
address[0] = 0;
|
||||
address[1] = LBA / CD_FRAMES_MINUTE;
|
||||
address[2] = LBA % CD_FRAMES_MINUTE / CD_FRAMES_SECOND;
|
||||
address[3] = LBA % CD_FRAMES_SECOND;
|
||||
|
||||
return address;
|
||||
}
|
||||
|
||||
static int dinkMSFToLBA(const UINT8* address)
|
||||
{
|
||||
int LBA;
|
||||
|
||||
LBA = address[3];
|
||||
LBA += address[2] * CD_FRAMES_SECOND;
|
||||
LBA += address[1] * CD_FRAMES_MINUTE;
|
||||
|
||||
return LBA;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
static void cdimgExitStream()
|
||||
{
|
||||
free(cdimgOutputbuffer);
|
||||
cdimgOutputbuffer = NULL;
|
||||
}
|
||||
|
||||
static int cdimgInitStream()
|
||||
{
|
||||
cdimgExitStream();
|
||||
|
||||
cdimgOutputbuffer = (short*)malloc(cdimgOUT_SIZE * 2 * sizeof(short));
|
||||
if (cdimgOutputbuffer == NULL)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cdimgSkip(FILE* h, int samples)
|
||||
{
|
||||
fseek(h, samples * 4, SEEK_CUR);
|
||||
|
||||
return samples * 4;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
static void cdimgPrintImageInfo()
|
||||
{
|
||||
bprintf(0, _T("Image file: %s\n"), cdimgTOC->Image);
|
||||
|
||||
bprintf(0, _T(" CD image TOC - "));
|
||||
if (cdimgTOC->ImageType == CD_TYPE_CCD)
|
||||
bprintf(0, _T("TruRip (.CCD/.SUB/.IMG) format\n"));
|
||||
if (cdimgTOC->ImageType == CD_TYPE_BINCUE)
|
||||
bprintf(0, _T("Disk At Once (.BIN/.CUE) format\n"));
|
||||
|
||||
for (INT32 trk = cdimgTOC->FirstTrack - 1; trk <= cdimgTOC->LastTrack; trk++) {
|
||||
const UINT8* addressUNBCD = dinkLBAToMSF(cdimgMSFToLBA(cdimgTOC->TrackData[trk].Address));
|
||||
|
||||
if (trk != cdimgTOC->LastTrack) {
|
||||
bprintf(0, _T("Track %02d: %02d:%02d:%02d\n"), trk + 1, addressUNBCD[1], addressUNBCD[2], addressUNBCD[3]);
|
||||
} else {
|
||||
bprintf(0, _T(" total running time %02i:%02i:%02i\n"), addressUNBCD[1], addressUNBCD[2], addressUNBCD[3]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// parse .sub file and build a TOC based in Q sub channel data
|
||||
static int cdimgParseSubFile()
|
||||
{
|
||||
TCHAR filename_sub[MAX_PATH];
|
||||
int length = 0;
|
||||
QData* Q = 0;
|
||||
int Qsize = 0;
|
||||
FILE* h;
|
||||
int track = 1;
|
||||
|
||||
cdimgTOC->ImageType = CD_TYPE_CCD;
|
||||
cdimgTOC->FirstTrack = 1;
|
||||
|
||||
_tcscpy(filename_sub, CDEmuImage);
|
||||
length = _tcslen(filename_sub);
|
||||
|
||||
if (length <= 4 ||
|
||||
(_tcscmp(_T(".ccd"), filename_sub + length - 4) &&
|
||||
_tcscmp(_T(".img"), filename_sub + length - 4) &&
|
||||
_tcscmp(_T(".sub"), filename_sub + length - 4)))
|
||||
{
|
||||
dprintf(_T("*** Bad image: %s\n"), filename_sub);
|
||||
return 1;
|
||||
}
|
||||
|
||||
_tcscpy(cdimgTOC->Image, CDEmuImage);
|
||||
_tcscpy(cdimgTOC->Image + length - 4, _T(".img"));
|
||||
//bprintf(0, _T("Image file: %s\n"),cdimgTOC->Image);
|
||||
if (_waccess(cdimgTOC->Image, 4) == -1)
|
||||
{
|
||||
dprintf(_T("*** Bad image: %s\n"), cdimgTOC->Image);
|
||||
return 1;
|
||||
}
|
||||
|
||||
_tcscpy(filename_sub + length - 4, _T(".sub"));
|
||||
//bprintf(0, _T("filename_sub: %s\n"),filename_sub);
|
||||
h = _wfopen(filename_sub, _T("rb"));
|
||||
if (h == 0)
|
||||
{
|
||||
dprintf(_T("*** Bad image: %s\n"), filename_sub);
|
||||
return 1;
|
||||
}
|
||||
|
||||
fseek(h, 0, SEEK_END);
|
||||
|
||||
INT32 subQidx = 0;
|
||||
INT32 subQsize = ftell(h);
|
||||
UINT8 *subQdata = (UINT8*)malloc(subQsize);
|
||||
memset(subQdata, 0, subQsize);
|
||||
|
||||
//bprintf(0, _T("raw .sub data size: %d\n"), subQsize);
|
||||
fseek(h, 0, SEEK_SET);
|
||||
fread(subQdata, subQsize, 1, h);
|
||||
fclose(h);
|
||||
|
||||
Qsize = (subQsize + 95) / 96 * sizeof(QData);
|
||||
Q = QChannel = (QData*)malloc(Qsize);
|
||||
memset(Q, 0, Qsize);
|
||||
|
||||
INT32 track_linear = 1;
|
||||
|
||||
while (1)
|
||||
{
|
||||
subQidx += 12;
|
||||
if (subQidx >= subQsize) break;
|
||||
memcpy(Q, &subQdata[subQidx], 12);
|
||||
subQidx += 12;
|
||||
subQidx += 6*12;
|
||||
|
||||
if (Q->index && (Q->Control & 1) && (cdimgTOC->TrackData[bcd(Q->track) - 1].TrackNumber == 0))
|
||||
{
|
||||
// new track
|
||||
track = bcd(Q->track);
|
||||
|
||||
if (track == track_linear) {
|
||||
//dprintf(_T(" - Track %i found starting at %02X:%02X:%02X\n"), track, Q->MSFabs.M, Q->MSFabs.S, Q->MSFabs.F);
|
||||
//bprintf(0, _T(" contrl: %X track %X(%d) indx %X\n"),Q->Control,Q->track,track,Q->index);
|
||||
|
||||
cdimgTOC->TrackData[track - 1].Control = Q->Control; // >> 4;
|
||||
cdimgTOC->TrackData[track - 1].TrackNumber = Q->track;
|
||||
cdimgTOC->TrackData[track - 1].Address[1] = Q->MSFabs.M;
|
||||
cdimgTOC->TrackData[track - 1].Address[2] = Q->MSFabs.S;
|
||||
cdimgTOC->TrackData[track - 1].Address[3] = Q->MSFabs.F;
|
||||
track_linear++;
|
||||
} else {
|
||||
//bprintf(0, _T("skipped weird track: %X (%X)\n"), track, Q->track);
|
||||
}
|
||||
}
|
||||
|
||||
Q++;
|
||||
}
|
||||
|
||||
cdimgTOC->LastTrack = track;
|
||||
|
||||
free(subQdata);
|
||||
|
||||
cd_pregap = QChannel[0].MSFabs.F + QChannel[0].MSFabs.S * CD_FRAMES_SECOND + QChannel[0].MSFabs.M * CD_FRAMES_MINUTE;
|
||||
//bprintf(0, _T("pregap lba: %d MSF: %d:%d:%d\n"), cd_pregap, QChannel[0].MSFabs.M, QChannel[0].MSFabs.S, QChannel[0].MSFabs.F);
|
||||
|
||||
{ // Make a fake last-track w/total image size (for bounds checking)
|
||||
h = _wfopen(cdimgTOC->Image, _T("rb"));
|
||||
if (h)
|
||||
{
|
||||
fseek(h, 0, SEEK_END);
|
||||
const UINT8* address = cdimgLBAToMSF((ftell(h) + 2351) / 2352);
|
||||
fclose(h);
|
||||
|
||||
cdimgTOC->TrackData[cdimgTOC->LastTrack].Address[1] = address[1];
|
||||
cdimgTOC->TrackData[cdimgTOC->LastTrack].Address[2] = address[2];
|
||||
cdimgTOC->TrackData[cdimgTOC->LastTrack].Address[3] = address[3];
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cdimgParseCueFile()
|
||||
{
|
||||
TCHAR szLine[1024];
|
||||
TCHAR szFile[1024];
|
||||
TCHAR* s;
|
||||
TCHAR* t;
|
||||
FILE* h;
|
||||
int track = 1;
|
||||
int length;
|
||||
|
||||
cdimgTOC->ImageType = CD_TYPE_BINCUE;
|
||||
cdimgTOC->FirstTrack = 1;
|
||||
cdimgTOC->LastTrack = 1;
|
||||
|
||||
cdimgTOC->TrackData[0].Address[1] = 0;
|
||||
cdimgTOC->TrackData[0].Address[2] = 2;
|
||||
cdimgTOC->TrackData[0].Address[3] = 0;
|
||||
|
||||
cd_pregap = 150; // default for bin/cue?
|
||||
|
||||
// derive .bin name from .cue filename (it gets the actual name from the .cue, below)
|
||||
length = _tcslen(CDEmuImage);
|
||||
_tcscpy(cdimgTOC->Image, CDEmuImage);
|
||||
_tcscpy(cdimgTOC->Image + length - 4, _T(".bin"));
|
||||
//bprintf(0, _T("Image file: %s\n"),cdimgTOC->Image);
|
||||
|
||||
h = _tfopen(CDEmuImage, _T("rt"));
|
||||
if (h == NULL) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
while (1) {
|
||||
if (_fgetts(szLine, sizeof(szLine), h) == NULL) {
|
||||
break;
|
||||
}
|
||||
|
||||
length = _tcslen(szLine);
|
||||
// get rid of the linefeed at the end
|
||||
while (length && (szLine[length - 1] == _T('\r') || szLine[length - 1] == _T('\n'))) {
|
||||
szLine[length - 1] = 0;
|
||||
length--;
|
||||
}
|
||||
|
||||
s = szLine;
|
||||
|
||||
// file info
|
||||
if ((t = LabelCheck(s, _T("FILE"))) != 0) {
|
||||
s = t;
|
||||
|
||||
TCHAR* szQuote;
|
||||
|
||||
// read filename
|
||||
QuoteRead(&szQuote, NULL, s);
|
||||
|
||||
_sntprintf(szFile, ExtractFilename(CDEmuImage) - CDEmuImage, _T("%s"), CDEmuImage);
|
||||
_sntprintf(szFile + (ExtractFilename(CDEmuImage) - CDEmuImage), 1024 - (ExtractFilename(CDEmuImage) - CDEmuImage), _T("/%s"), szQuote);
|
||||
|
||||
if (track == 1) {
|
||||
//bprintf(0, _T("Image file (from .CUE): %s\n"), szFile);
|
||||
_tcscpy(cdimgTOC->Image, szFile);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
// track info
|
||||
if ((t = LabelCheck(s, _T("TRACK"))) != 0) {
|
||||
s = t;
|
||||
|
||||
// track number
|
||||
track = _tcstol(s, &t, 10);
|
||||
|
||||
if (track < 1 || track > MAXIMUM_NUMBER_TRACKS) {
|
||||
fclose(h);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (track < cdimgTOC->FirstTrack) {
|
||||
cdimgTOC->FirstTrack = track;
|
||||
}
|
||||
if (track > cdimgTOC->LastTrack) {
|
||||
cdimgTOC->LastTrack = track;
|
||||
}
|
||||
cdimgTOC->TrackData[track - 1].TrackNumber = tobcd(track);
|
||||
|
||||
s = t;
|
||||
|
||||
// type of track
|
||||
|
||||
if ((t = LabelCheck(s, _T("MODE1/2352"))) != 0) {
|
||||
cdimgTOC->TrackData[track - 1].Control = 0x41;
|
||||
//bprintf(0, _T(".cue: Track #%d, data.\n"), track);
|
||||
continue;
|
||||
}
|
||||
if ((t = LabelCheck(s, _T("AUDIO"))) != 0) {
|
||||
cdimgTOC->TrackData[track - 1].Control = 0x01;
|
||||
//bprintf(0, _T(".cue: Track #%d, AUDIO.\n"), track);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
fclose(h);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// PREGAP (not handled)
|
||||
if ((t = LabelCheck(s, _T("PREGAP"))) != 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// TRACK Index
|
||||
if ((t = LabelCheck(s, _T("INDEX 01"))) != 0) {
|
||||
s = t;
|
||||
|
||||
int M, S, F;
|
||||
|
||||
// index M
|
||||
M = _tcstol(s, &t, 10);
|
||||
s = t + 1;
|
||||
// index S
|
||||
S = _tcstol(s, &t, 10);
|
||||
s = t + 1;
|
||||
// index F
|
||||
F = _tcstol(s, &t, 10);
|
||||
|
||||
if (M < 0 || M > 100 || S < 0 || S > 59 || F < 0 || F > 74) {
|
||||
bprintf(0, _T("Bad M:S:F!\n"));
|
||||
fclose(h);
|
||||
return 1;
|
||||
}
|
||||
|
||||
const UINT8 address[] = { 0, (UINT8)M, (UINT8)S, (UINT8)F };
|
||||
const UINT8* newaddress = cdimgLBAToMSF(dinkMSFToLBA(address) + cd_pregap);
|
||||
//const UINT8* newaddressUNBCD = dinkLBAToMSF(dinkMSFToLBA(address) + cd_pregap);
|
||||
//bprintf(0, _T("Track MSF: %02d:%02d:%02d "), newaddressUNBCD[1], newaddressUNBCD[2], newaddressUNBCD[3]);
|
||||
|
||||
cdimgTOC->TrackData[track - 1].Address[1] = newaddress[1];
|
||||
cdimgTOC->TrackData[track - 1].Address[2] = newaddress[2];
|
||||
cdimgTOC->TrackData[track - 1].Address[3] = newaddress[3];
|
||||
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
fclose(h);
|
||||
|
||||
{
|
||||
h = _wfopen(cdimgTOC->Image, _T("rb"));
|
||||
if (h)
|
||||
{
|
||||
fseek(h, 0, SEEK_END);
|
||||
const UINT8* address = cdimgLBAToMSF((ftell(h) + 2351) / 2352);
|
||||
fclose(h);
|
||||
|
||||
cdimgTOC->TrackData[cdimgTOC->LastTrack].Address[1] = address[1];
|
||||
cdimgTOC->TrackData[cdimgTOC->LastTrack].Address[2] = address[2];
|
||||
cdimgTOC->TrackData[cdimgTOC->LastTrack].Address[3] = address[3];
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
static int cdimgExit()
|
||||
{
|
||||
cdimgExitStream();
|
||||
|
||||
if (cdimgFile)
|
||||
fclose(cdimgFile);
|
||||
cdimgFile = NULL;
|
||||
|
||||
cdimgFileSize = 0;
|
||||
cdimgTrack = 0;
|
||||
cdimgLBA = 0;
|
||||
|
||||
if (cdimgTOC)
|
||||
free(cdimgTOC);
|
||||
cdimgTOC = NULL;
|
||||
|
||||
free(QChannel);
|
||||
QChannel = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cdimgInit()
|
||||
{
|
||||
cdimgTOC = (cdimgCDROM_TOC*)malloc(sizeof(cdimgCDROM_TOC));
|
||||
if (cdimgTOC == NULL)
|
||||
return 1;
|
||||
|
||||
memset(cdimgTOC, 0, sizeof(cdimgCDROM_TOC));
|
||||
|
||||
cdimgTOC->ImageType = CD_TYPE_NONE;
|
||||
|
||||
TCHAR* filename = ExtractFilename(CDEmuImage);
|
||||
|
||||
if (_tcslen(filename) < 4)
|
||||
return 1;
|
||||
|
||||
if (_tcscmp(_T(".cue"), filename + _tcslen(filename) - 4) == 0)
|
||||
{
|
||||
if (cdimgParseCueFile())
|
||||
{
|
||||
dprintf(_T("*** Couldn't parse .cue file\n"));
|
||||
cdimgExit();
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
} else
|
||||
if (_tcscmp(_T(".ccd"), filename + _tcslen(filename) - 4) == 0)
|
||||
{
|
||||
if (cdimgParseSubFile())
|
||||
{
|
||||
dprintf(_T("*** Couldn't parse .sub file\n"));
|
||||
cdimgExit();
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
dprintf(_T("*** Couldn't find .img / .bin file\n"));
|
||||
cdimgExit();
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
cdimgPrintImageInfo();
|
||||
|
||||
CDEmuStatus = idle;
|
||||
|
||||
cdimgInitStream();
|
||||
|
||||
{
|
||||
char buf[2048];
|
||||
FILE* h = _wfopen(cdimgTOC->Image, _T("rb")); cdimgLBA++;
|
||||
|
||||
if (h)
|
||||
{
|
||||
if (fseek(h, 16 * 2352 + 16, SEEK_SET) == 0)
|
||||
{
|
||||
if (fread(buf, 1, 2048, h) == 2048)
|
||||
{
|
||||
if (strncmp("CD001", buf + 1, 5) == 0)
|
||||
{
|
||||
buf[48] = 0;
|
||||
/* BurnDrvFindMedium(buf + 40); */
|
||||
}
|
||||
else
|
||||
dprintf(_T("*** Bad CD!\n"));
|
||||
}
|
||||
}
|
||||
|
||||
fclose(h);
|
||||
}
|
||||
|
||||
//CDEmuPrintCDName();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void cdimgCloseFile()
|
||||
{
|
||||
if (cdimgFile)
|
||||
{
|
||||
fclose(cdimgFile);
|
||||
cdimgFile = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static int cdimgStop()
|
||||
{
|
||||
cdimgCloseFile();
|
||||
CDEmuStatus = idle;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cdimgFindTrack(int LBA)
|
||||
{
|
||||
int trk = 0;
|
||||
for (trk = cdimgTOC->FirstTrack - 1; trk < cdimgTOC->LastTrack; trk++)
|
||||
if (LBA < cdimgMSFToLBA(cdimgTOC->TrackData[trk + 1].Address))
|
||||
break;
|
||||
return trk;
|
||||
}
|
||||
|
||||
static int cdimgPlayLBA(int LBA)
|
||||
{
|
||||
cdimgStop();
|
||||
|
||||
if (QChannel != NULL) { // .CCD dump w/.SUB
|
||||
if (QChannel[LBA].Control & 0x40)
|
||||
return 1;
|
||||
} else { // .BIN/.CUE dump
|
||||
if (cdimgTOC->TrackData[cdimgFindTrack(LBA)].Control & 0x40)
|
||||
return 1;
|
||||
}
|
||||
|
||||
cdimgLBA = LBA;
|
||||
|
||||
cdimgTrack = cdimgFindTrack(cdimgLBA);
|
||||
|
||||
if (cdimgTrack >= cdimgTOC->LastTrack)
|
||||
return 1;
|
||||
|
||||
bprintf(PRINT_IMPORTANT, _T(" playing track %2i\n"), cdimgTrack + 1);
|
||||
|
||||
cdimgFile = _wfopen(cdimgTOC->Image, _T("rb"));
|
||||
if (cdimgFile == NULL)
|
||||
return 1;
|
||||
|
||||
// advance if we're not starting at the beginning of a CD
|
||||
if (cdimgLBA > cd_pregap)
|
||||
cdimgSkip(cdimgFile, (cdimgLBA - cd_pregap) * (44100 / CD_FRAMES_SECOND));
|
||||
|
||||
// fill the input buffer
|
||||
if ((cdimgOutputbufferSize = fread(cdimgOutputbuffer, 4, cdimgOUT_SIZE, cdimgFile)) <= 0)
|
||||
return 1;
|
||||
|
||||
cdimgOutputPosition = 0;
|
||||
|
||||
cdimgSamples = 0;
|
||||
|
||||
cdimgLBA = cdimgMSFToLBA(cdimgTOC->TrackData[cdimgTrack].Address);
|
||||
CDEmuStatus = playing;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cdimgPlay(UINT8 M, UINT8 S, UINT8 F)
|
||||
{
|
||||
const UINT8 address[] = { 0, M, S, F };
|
||||
|
||||
dprintf(_T(" play %02i:%02i:%02i\n"), M, S, F);
|
||||
|
||||
return cdimgPlayLBA(cdimgMSFToLBA(address));
|
||||
}
|
||||
|
||||
static int cdimgLoadSector(int LBA, char* pBuffer)
|
||||
{
|
||||
//dprintf(_T(" read LBA %i\n"), LBA);
|
||||
if (CDEmuStatus == playing) return 0; // this might cause problems? - dink
|
||||
|
||||
if (LBA != cdimgLBA)
|
||||
{
|
||||
if (cdimgFile == NULL)
|
||||
{
|
||||
cdimgStop();
|
||||
|
||||
cdimgFile = _wfopen(cdimgTOC->Image, _T("rb"));
|
||||
if (cdimgFile == NULL)
|
||||
return 0;
|
||||
}
|
||||
|
||||
//bprintf(PRINT_IMPORTANT, _T(" loading data at LBA %08u 0x%08X\n"), (LBA - cdimgMSFToLBA(cdimgTOC->TrackData[cdimgTrack].Address)) * 2352, LBA * 2352);
|
||||
|
||||
if (fseek(cdimgFile, (LBA - cd_pregap) * 2352, SEEK_SET))
|
||||
{
|
||||
dprintf(_T("*** couldn't seek (LBA %08u)\n"), LBA);
|
||||
|
||||
//cdimgStop(); // stopping here will break ssrpg
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
CDEmuStatus = reading;
|
||||
}
|
||||
|
||||
//dprintf(_T(" reading LBA %08i 0x%08X"), LBA, ftell(cdimgFile));
|
||||
|
||||
cdimgLBA = cdimgMSFToLBA(cdimgTOC->TrackData[0].Address) + (ftell(cdimgFile) + 2351) / 2352 - cd_pregap;
|
||||
|
||||
bool status = (fread(pBuffer, 1, 2352, cdimgFile) <= 0);
|
||||
|
||||
if (status)
|
||||
{
|
||||
dprintf(_T("*** couldn't read from file\n"));
|
||||
|
||||
cdimgStop();
|
||||
|
||||
return 0;
|
||||
}
|
||||
// dprintf(_T(" [ %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X ]\n"), pBuffer[0], pBuffer[1], pBuffer[2], pBuffer[3], pBuffer[4], pBuffer[5], pBuffer[6], pBuffer[7], pBuffer[8], pBuffer[9], pBuffer[10], pBuffer[11], pBuffer[12], pBuffer[13], pBuffer[14], pBuffer[15]);
|
||||
|
||||
cdimgLBA++;
|
||||
|
||||
return cdimgLBA;
|
||||
}
|
||||
|
||||
static UINT8* cdimgReadTOC(int track)
|
||||
{
|
||||
static UINT8 TOCEntry[4];
|
||||
|
||||
if (track == -1)
|
||||
{
|
||||
TOCEntry[0] = tobcd(cdimgTOC->FirstTrack - 1);
|
||||
TOCEntry[1] = tobcd(cdimgTOC->LastTrack);
|
||||
TOCEntry[2] = 0;
|
||||
TOCEntry[3] = 0;
|
||||
|
||||
return TOCEntry;
|
||||
}
|
||||
if (track == -2)
|
||||
{
|
||||
TOCEntry[0] = cdimgTOC->TrackData[cdimgTOC->LastTrack].Address[1];
|
||||
TOCEntry[1] = cdimgTOC->TrackData[cdimgTOC->LastTrack].Address[2];
|
||||
TOCEntry[2] = cdimgTOC->TrackData[cdimgTOC->LastTrack].Address[3];
|
||||
|
||||
TOCEntry[3] = 0;
|
||||
|
||||
return TOCEntry;
|
||||
}
|
||||
|
||||
track = bcd(track);
|
||||
if (track >= cdimgTOC->FirstTrack - 1 && track <= cdimgTOC->LastTrack)
|
||||
{
|
||||
TOCEntry[0] = cdimgTOC->TrackData[track - 1].Address[1];
|
||||
TOCEntry[1] = cdimgTOC->TrackData[track - 1].Address[2];
|
||||
TOCEntry[2] = cdimgTOC->TrackData[track - 1].Address[3];
|
||||
TOCEntry[3] = cdimgTOC->TrackData[track - 1].Control >> 4;
|
||||
}
|
||||
|
||||
// dprintf(_T(" track %02i - %02x:%02x:%02x\n"), track, TOCEntry[0], TOCEntry[1], TOCEntry[2]);
|
||||
|
||||
return TOCEntry;
|
||||
}
|
||||
|
||||
static UINT8* cdimgReadQChannel()
|
||||
{
|
||||
// Q channel format
|
||||
// byte 0: 41 = data, 1 = cdda ( flags described at https://en.wikipedia.org/wiki/Compact_Disc_subcode )
|
||||
// track, index, M rel, S rel, F rel, M to start, S to start, F to start, 0, CRC, CRC
|
||||
// if index is 0, MSF rel counts down to next track
|
||||
|
||||
static UINT8 QChannelData[8];
|
||||
|
||||
switch (CDEmuStatus)
|
||||
{
|
||||
case reading:
|
||||
case playing:
|
||||
{
|
||||
if (QChannel != NULL) { // .CCD/.SUB
|
||||
QChannelData[0] = QChannel[cdimgLBA].track;
|
||||
|
||||
QChannelData[1] = QChannel[cdimgLBA].MSFrel.M;
|
||||
QChannelData[2] = QChannel[cdimgLBA].MSFrel.S;
|
||||
QChannelData[3] = QChannel[cdimgLBA].MSFrel.F;
|
||||
|
||||
QChannelData[4] = QChannel[cdimgLBA].MSFrel.M;
|
||||
QChannelData[5] = QChannel[cdimgLBA].MSFrel.S;
|
||||
QChannelData[6] = QChannel[cdimgLBA].MSFrel.F;
|
||||
|
||||
QChannelData[7] = QChannel[cdimgLBA].Control;
|
||||
} else { // .BIN/.ISO
|
||||
const UINT8* AddressAbs = cdimgLBAToMSF(cdimgLBA);
|
||||
const UINT8* AddressRel = cdimgLBAToMSF(cdimgLBA - cdimgMSFToLBA(cdimgTOC->TrackData[cdimgTrack].Address));
|
||||
|
||||
QChannelData[0] = cdimgTOC->TrackData[cdimgTrack].TrackNumber;
|
||||
|
||||
QChannelData[1] = AddressAbs[1];
|
||||
QChannelData[2] = AddressAbs[2];
|
||||
QChannelData[3] = AddressAbs[3];
|
||||
|
||||
QChannelData[4] = AddressRel[1];
|
||||
QChannelData[5] = AddressRel[2];
|
||||
QChannelData[6] = AddressRel[3];
|
||||
|
||||
QChannelData[7] = cdimgTOC->TrackData[cdimgTrack].Control;
|
||||
}
|
||||
|
||||
// dprintf(_T(" Q %02x %02x %02x:%02x:%02x %02x:%02x:%02x\n"), QChannel[cdimgLBA].track, QChannel[cdimgLBA].index, QChannel[cdimgLBA].MSFrel.M, QChannel[cdimgLBA].MSFrel.S, QChannel[cdimgLBA].MSFrel.F, QChannel[cdimgLBA].MSFabs.M, QChannel[cdimgLBA].MSFabs.S, QChannel[cdimgLBA].MSFabs.F);
|
||||
|
||||
break;
|
||||
}
|
||||
case paused:
|
||||
break;
|
||||
|
||||
default:
|
||||
memset(QChannelData, 0, sizeof(QChannelData));
|
||||
}
|
||||
|
||||
return QChannelData;
|
||||
}
|
||||
|
||||
static int cdimgGetSoundBuffer(short* buffer, int samples)
|
||||
{
|
||||
|
||||
#define CLIP(A) ((A) < -0x8000 ? -0x8000 : (A) > 0x7fff ? 0x7fff : (A))
|
||||
|
||||
if (CDEmuStatus != playing) {
|
||||
memset(cdimgOutputbuffer, 0x00, cdimgOUT_SIZE * 2 * sizeof(short));
|
||||
return 0;
|
||||
}
|
||||
|
||||
cdimgSamples += samples;
|
||||
while (cdimgSamples > (44100 / CD_FRAMES_SECOND))
|
||||
{
|
||||
cdimgSamples -= (44100 / CD_FRAMES_SECOND);
|
||||
cdimgLBA++;
|
||||
|
||||
/* if (cdimgFile == NULL) // play next track? bad idea. -dink
|
||||
if (cdimgLBA >= cdimgMSFToLBA(cdimgTOC->TrackData[cdimgTrack + 1].Address))
|
||||
cdimgPlayLBA(cdimgLBA); */
|
||||
}
|
||||
|
||||
if (cdimgFile == NULL) { // restart play if fileptr lost
|
||||
bprintf(0, _T("CDDA file pointer lost, re-starting!\n"));
|
||||
if (cdimgLBA < cdimgMSFToLBA(cdimgTOC->TrackData[cdimgTrack + 1].Address))
|
||||
cdimgPlayLBA(cdimgLBA);
|
||||
}
|
||||
|
||||
if (cdimgFile == NULL) { // restart failed (really?) - time to give up.
|
||||
cdimgStop();
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((cdimgOutputPosition + samples) >= cdimgOutputbufferSize)
|
||||
{
|
||||
short* src = cdimgOutputbuffer + cdimgOutputPosition * 2;
|
||||
short* dst = buffer;
|
||||
|
||||
for (int i = (cdimgOutputbufferSize - cdimgOutputPosition) * 2 - 1; i > 0; )
|
||||
{
|
||||
dst[i] = CLIP((src[i]) + dst[i]); i--;
|
||||
dst[i] = CLIP((src[i]) + dst[i]); i--;
|
||||
}
|
||||
|
||||
buffer += (cdimgOutputbufferSize - cdimgOutputPosition) * 2;
|
||||
samples -= (cdimgOutputbufferSize - cdimgOutputPosition);
|
||||
|
||||
cdimgOutputPosition = 0;
|
||||
cdimgLBA++;
|
||||
if ((cdimgOutputbufferSize = fread(cdimgOutputbuffer, 4, cdimgOUT_SIZE, cdimgFile)) <= 0)
|
||||
cdimgStop();
|
||||
|
||||
if (cdimgLBA >= cdimgMSFToLBA(cdimgTOC->TrackData[cdimgTrack + 1 /* next track */].Address)) {
|
||||
bprintf(0, _T("End of audio track %d reached!! stopping.\n"), cdimgTrack + 1);
|
||||
cdimgStop();
|
||||
}
|
||||
}
|
||||
|
||||
if ((cdimgOutputPosition + samples) < cdimgOutputbufferSize)
|
||||
{
|
||||
short* src = cdimgOutputbuffer + cdimgOutputPosition * 2;
|
||||
short* dst = buffer;
|
||||
|
||||
for (int i = samples * 2 - 1; i > 0; )
|
||||
{
|
||||
dst[i] = CLIP((src[i]) + dst[i]); i--;
|
||||
dst[i] = CLIP((src[i]) + dst[i]); i--;
|
||||
}
|
||||
|
||||
cdimgOutputPosition += samples;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
#undef CLIP
|
||||
|
||||
}
|
||||
|
||||
static INT32 cdimgScan(INT32 nAction, INT32 *pnMin)
|
||||
{
|
||||
if (nAction & ACB_VOLATILE) {
|
||||
SCAN_VAR(CDEmuStatus);
|
||||
SCAN_VAR(cdimgTrack);
|
||||
SCAN_VAR(cdimgLBA);
|
||||
}
|
||||
|
||||
if (nAction & ACB_WRITE) {
|
||||
cdimgCloseFile();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cdimgGetSettings(InterfaceInfo* pInfo)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct CDEmuDo cdimgDo = { cdimgExit, cdimgInit, cdimgStop, cdimgPlay, cdimgLoadSector, cdimgReadTOC, cdimgReadQChannel, cdimgGetSoundBuffer, cdimgScan, cdimgGetSettings, _T("raw image CD emulation") };
|
|
@ -62,9 +62,10 @@ struct CDEmuDo {
|
|||
INT32 (*CDEmuStop)();
|
||||
INT32 (*CDEmuPlay)(UINT8 M, UINT8 S, UINT8 F);
|
||||
INT32 (*CDEmuLoadSector)(INT32 LBA, char* pBuffer);
|
||||
UINT8* (*CDEmuReadTOC)(INT32 track);
|
||||
UINT8* (*CDEmuReadQChannel)();
|
||||
UINT8* (*CDEmuReadTOC)(INT32 track);
|
||||
UINT8* (*CDEmuReadQChannel)();
|
||||
INT32 (*CDEmuGetSoundBuffer)(INT16* buffer, INT32 samples);
|
||||
INT32 (*CDEmuScan)(INT32 nAction, INT32 *pnMin);
|
||||
// Get plugin info
|
||||
INT32 (*GetPluginSettings)(InterfaceInfo* pInfo);
|
||||
const TCHAR* szModuleName;
|
||||
|
|
Loading…
Reference in New Issue