gpgx: multidisk? dunno

This commit is contained in:
nattthebear 2017-07-17 18:49:16 -04:00
parent e61f7d7876
commit c31ebe176d
10 changed files with 1078 additions and 1002 deletions

View File

@ -554,7 +554,7 @@ namespace BizHawk.Client.Common
switch (game.System) switch (game.System)
{ {
case "GEN": case "GEN":
var genesis = new GPGX(nextComm, null, disc, GetCoreSettings<GPGX>(), GetCoreSyncSettings<GPGX>()); var genesis = new GPGX(nextComm, null, new[] { disc }, GetCoreSettings<GPGX>(), GetCoreSyncSettings<GPGX>());
nextEmulator = genesis; nextEmulator = genesis;
break; break;
case "SAT": case "SAT":

View File

@ -7,20 +7,42 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx
{ {
public IEmulatorServiceProvider ServiceProvider { get; private set; } public IEmulatorServiceProvider ServiceProvider { get; private set; }
public ControllerDefinition ControllerDefinition { get; private set; } public ControllerDefinition ControllerDefinition { get; private set; }
// TODO: use render and rendersound // TODO: use render and rendersound
public void FrameAdvance(IController controller, bool render, bool rendersound = true) public void FrameAdvance(IController controller, bool render, bool rendersound = true)
{ {
if (controller.IsPressed("Reset")) if (controller.IsPressed("Reset"))
Core.gpgx_reset(false); Core.gpgx_reset(false);
if (controller.IsPressed("Power")) if (controller.IsPressed("Power"))
Core.gpgx_reset(true); Core.gpgx_reset(true);
if (_cds != null)
// this shouldn't be needed, as nothing has changed {
// if (!Core.gpgx_get_control(input, inputsize)) var prev = controller.IsPressed("Previous Disk");
// throw new Exception("gpgx_get_control() failed!"); var next = controller.IsPressed("Next Disk");
int newDisk = _discIndex;
if (prev && !_prevDiskPressed)
newDisk--;
if (next && !_nextDiskPressed)
newDisk++;
if (newDisk < -1)
newDisk = -1;
if (newDisk >= _cds.Length)
newDisk = _cds.Length - 1;
if (newDisk != _discIndex)
{
_discIndex = newDisk;
Core.gpgx_swap_disc(_discIndex == -1 ? null : GetCDDataStruct(_cds[_discIndex]));
Console.WriteLine("IMMA CHANGING MAH DISKS");
}
}
// this shouldn't be needed, as nothing has changed
// if (!Core.gpgx_get_control(input, inputsize))
// throw new Exception("gpgx_get_control() failed!");
ControlConverter.ScreenWidth = vwidth; ControlConverter.ScreenWidth = vwidth;
ControlConverter.ScreenHeight = vheight; ControlConverter.ScreenHeight = vheight;
ControlConverter.Convert(controller, input); ControlConverter.Convert(controller, input);
@ -39,7 +61,7 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx
if (IsLagFrame) if (IsLagFrame)
LagCount++; LagCount++;
if (CD != null) if (_cds != null)
DriveLightOn = _drivelight; DriveLightOn = _drivelight;
} }
@ -70,8 +92,9 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx
{ {
if (_elf != null) if (_elf != null)
_elf.Dispose(); _elf.Dispose();
if (CD != null) if (_cds != null)
CD.Dispose(); foreach (var cd in _cds)
cd.Dispose();
_disposed = true; _disposed = true;
} }
} }

View File

@ -36,6 +36,9 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx
Frame = reader.ReadInt32(); Frame = reader.ReadInt32();
LagCount = reader.ReadInt32(); LagCount = reader.ReadInt32();
IsLagFrame = reader.ReadBoolean(); IsLagFrame = reader.ReadBoolean();
_discIndex = reader.ReadInt32();
_prevDiskPressed = reader.ReadBoolean();
_nextDiskPressed = reader.ReadBoolean();
// any managed pointers that we sent to the core need to be resent now! // any managed pointers that we sent to the core need to be resent now!
Core.gpgx_set_input_callback(InputCallback); Core.gpgx_set_input_callback(InputCallback);
RefreshMemCallbacks(); RefreshMemCallbacks();
@ -51,6 +54,9 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx
writer.Write(Frame); writer.Write(Frame);
writer.Write(LagCount); writer.Write(LagCount);
writer.Write(IsLagFrame); writer.Write(IsLagFrame);
writer.Write(_discIndex);
writer.Write(_prevDiskPressed);
writer.Write(_nextDiskPressed);
} }
public byte[] SaveStateBinary() public byte[] SaveStateBinary()

View File

@ -7,6 +7,8 @@ using BizHawk.Emulation.Common;
using BizHawk.Emulation.Cores.Waterbox; using BizHawk.Emulation.Cores.Waterbox;
using BizHawk.Common; using BizHawk.Common;
using BizHawk.Emulation.DiscSystem; using BizHawk.Emulation.DiscSystem;
using System.Collections.Generic;
using System.Linq;
namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx
{ {
@ -27,7 +29,7 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx
{ {
} }
public GPGX(CoreComm comm, byte[] rom, DiscSystem.Disc CD, object settings, object syncSettings) public GPGX(CoreComm comm, byte[] rom, IEnumerable<Disc> cds, object settings, object syncSettings)
{ {
ServiceProvider = new BasicServiceProvider(this); ServiceProvider = new BasicServiceProvider(this);
// this can influence some things internally (autodetect romtype, etc) // this can influence some things internally (autodetect romtype, etc)
@ -64,12 +66,14 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx
LoadCallback = new LibGPGX.load_archive_cb(load_archive); LoadCallback = new LibGPGX.load_archive_cb(load_archive);
this.romfile = rom; this.romfile = rom;
this.CD = CD;
if (CD != null) if (cds != null)
{ {
this.DiscSectorReader = new DiscSystem.DiscSectorReader(CD); _cds = cds.ToArray();
_cdReaders = cds.Select(c => new DiscSectorReader(c)).ToArray();
cd_callback_handle = new LibGPGX.cd_read_cb(CDRead); cd_callback_handle = new LibGPGX.cd_read_cb(CDRead);
Core.gpgx_set_cdd_callback(cd_callback_handle); Core.gpgx_set_cdd_callback(cd_callback_handle);
DriveLightEnabled = true;
} }
LibGPGX.INPUT_SYSTEM system_a = LibGPGX.INPUT_SYSTEM.SYSTEM_NONE; LibGPGX.INPUT_SYSTEM system_a = LibGPGX.INPUT_SYSTEM.SYSTEM_NONE;
@ -139,9 +143,6 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx
InputCallback = new LibGPGX.input_cb(input_callback); InputCallback = new LibGPGX.input_cb(input_callback);
Core.gpgx_set_input_callback(InputCallback); Core.gpgx_set_input_callback(InputCallback);
if (CD != null)
DriveLightEnabled = true;
// process the non-init settings now // process the non-init settings now
PutSettings(_settings); PutSettings(_settings);
@ -159,8 +160,12 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx
private LibGPGX Core; private LibGPGX Core;
private PeRunner _elf; private PeRunner _elf;
DiscSystem.Disc CD; private Disc[] _cds;
DiscSystem.DiscSectorReader DiscSectorReader; private int _discIndex;
private DiscSectorReader[] _cdReaders;
private bool _prevDiskPressed;
private bool _nextDiskPressed;
byte[] romfile; byte[] romfile;
private bool _disposed = false; private bool _disposed = false;
@ -217,12 +222,12 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx
} }
else else
{ {
if (CD == null) if (_cds == null)
{ {
Console.WriteLine("Couldn't satisfy firmware request {0} because none was provided.", filename); Console.WriteLine("Couldn't satisfy firmware request {0} because none was provided.", filename);
return 0; return 0;
} }
srcdata = GetCDData(CD); srcdata = GetCDData(_cds[0]);
if (srcdata.Length != maxsize) if (srcdata.Length != maxsize)
{ {
Console.WriteLine("Couldn't satisfy firmware request {0} because of struct size.", filename); Console.WriteLine("Couldn't satisfy firmware request {0} because of struct size.", filename);
@ -283,36 +288,38 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx
void CDRead(int lba, IntPtr dest, bool audio) void CDRead(int lba, IntPtr dest, bool audio)
{ {
if (audio) if ((uint)_discIndex < _cds.Length)
{ {
byte[] data = new byte[2352]; if (audio)
if (lba < CD.Session1.LeadoutLBA)
{ {
DiscSectorReader.ReadLBA_2352(lba, data, 0); byte[] data = new byte[2352];
if (lba < _cds[_discIndex].Session1.LeadoutLBA)
{
_cdReaders[_discIndex].ReadLBA_2352(lba, data, 0);
}
else
{
// audio seems to read slightly past the end of disks; probably innoculous
// just send back 0s.
// Console.WriteLine("!!{0} >= {1}", lba, CD.LBACount);
}
Marshal.Copy(data, 0, dest, 2352);
} }
else else
{ {
// audio seems to read slightly past the end of disks; probably innoculous byte[] data = new byte[2048];
// just send back 0s. _cdReaders[_discIndex].ReadLBA_2048(lba, data, 0);
// Console.WriteLine("!!{0} >= {1}", lba, CD.LBACount); Marshal.Copy(data, 0, dest, 2048);
_drivelight = true;
} }
Marshal.Copy(data, 0, dest, 2352);
}
else
{
byte[] data = new byte[2048];
DiscSectorReader.ReadLBA_2048(lba, data, 0);
Marshal.Copy(data, 0, dest, 2048);
_drivelight = true;
} }
} }
LibGPGX.cd_read_cb cd_callback_handle; LibGPGX.cd_read_cb cd_callback_handle;
public static unsafe byte[] GetCDData(Disc cd) public static LibGPGX.CDData GetCDDataStruct(Disc cd)
{ {
LibGPGX.CDData ret = new LibGPGX.CDData(); var ret = new LibGPGX.CDData();
int size = Marshal.SizeOf(ret);
var ses = cd.Session1; var ses = cd.Session1;
int ntrack = ses.InformationTrackCount; int ntrack = ses.InformationTrackCount;
@ -338,6 +345,13 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx
} }
} }
return ret;
}
public static unsafe byte[] GetCDData(Disc cd)
{
var ret = GetCDDataStruct(cd);
int size = Marshal.SizeOf(ret);
byte[] retdata = new byte[size]; byte[] retdata = new byte[size];
fixed (byte* p = &retdata[0]) fixed (byte* p = &retdata[0])
@ -360,7 +374,7 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx
if (!Core.gpgx_get_control(input, inputsize)) if (!Core.gpgx_get_control(input, inputsize))
throw new Exception("gpgx_get_control() failed"); throw new Exception("gpgx_get_control() failed");
ControlConverter = new GPGXControlConverter(input); ControlConverter = new GPGXControlConverter(input, _cds != null);
ControllerDefinition = ControlConverter.ControllerDef; ControllerDefinition = ControlConverter.ControllerDef;
} }
@ -369,7 +383,7 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx
return (LibGPGX.INPUT_DEVICE[])input.dev.Clone(); return (LibGPGX.INPUT_DEVICE[])input.dev.Clone();
} }
public bool IsMegaCD { get { return CD != null; } } public bool IsMegaCD { get { return _cds != null; } }
public class VDPView : IMonitor public class VDPView : IMonitor
{ {

View File

@ -175,7 +175,7 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx
}); });
} }
public GPGXControlConverter(LibGPGX.InputData input) public GPGXControlConverter(LibGPGX.InputData input, bool cdButtons)
{ {
Console.WriteLine("Genesis Controller report:"); Console.WriteLine("Genesis Controller report:");
foreach (var e in input.system) foreach (var e in input.system)
@ -189,6 +189,11 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx
ControllerDef.BoolButtons.Add("Power"); ControllerDef.BoolButtons.Add("Power");
ControllerDef.BoolButtons.Add("Reset"); ControllerDef.BoolButtons.Add("Reset");
if (cdButtons)
{
ControllerDef.BoolButtons.Add("Previous Disk");
ControllerDef.BoolButtons.Add("Next Disk");
}
for (int i = 0; i < LibGPGX.MAX_DEVICES; i++) for (int i = 0; i < LibGPGX.MAX_DEVICES; i++)
{ {

View File

@ -49,7 +49,7 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx
public uint BackdropColor; public uint BackdropColor;
} }
[BizImport(CallingConvention.Cdecl, Compatibility=true)] [BizImport(CallingConvention.Cdecl, Compatibility = true)]
public abstract bool gpgx_init(string feromextension, load_archive_cb feload_archive_cb, bool sixbutton, INPUT_SYSTEM system_a, INPUT_SYSTEM system_b, Region region, [In]InitSettings settings); public abstract bool gpgx_init(string feromextension, load_archive_cb feload_archive_cb, bool sixbutton, INPUT_SYSTEM system_a, INPUT_SYSTEM system_b, Region region, [In]InitSettings settings);
[BizImport(CallingConvention.Cdecl)] [BizImport(CallingConvention.Cdecl)]
@ -84,34 +84,34 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx
public enum INPUT_SYSTEM : byte public enum INPUT_SYSTEM : byte
{ {
SYSTEM_NONE = 0, // unconnected port SYSTEM_NONE = 0, // unconnected port
SYSTEM_MD_GAMEPAD = 1, // single 3-buttons or 6-buttons Control Pad SYSTEM_MD_GAMEPAD = 1, // single 3-buttons or 6-buttons Control Pad
SYSTEM_MOUSE = 2, // Sega Mouse SYSTEM_MOUSE = 2, // Sega Mouse
SYSTEM_MENACER = 3, // Sega Menacer -- port B only SYSTEM_MENACER = 3, // Sega Menacer -- port B only
SYSTEM_JUSTIFIER = 4, // Konami Justifiers -- port B only SYSTEM_JUSTIFIER = 4, // Konami Justifiers -- port B only
SYSTEM_XE_A1P = 5, // XE-A1P analog controller -- port A only SYSTEM_XE_A1P = 5, // XE-A1P analog controller -- port A only
SYSTEM_ACTIVATOR = 6, // Sega Activator SYSTEM_ACTIVATOR = 6, // Sega Activator
SYSTEM_MS_GAMEPAD = 7, // single 2-buttons Control Pad -- Master System SYSTEM_MS_GAMEPAD = 7, // single 2-buttons Control Pad -- Master System
SYSTEM_LIGHTPHASER = 8, // Sega Light Phaser -- Master System SYSTEM_LIGHTPHASER = 8, // Sega Light Phaser -- Master System
SYSTEM_PADDLE = 9, // Sega Paddle Control -- Master System SYSTEM_PADDLE = 9, // Sega Paddle Control -- Master System
SYSTEM_SPORTSPAD = 10, // Sega Sports Pad -- Master System SYSTEM_SPORTSPAD = 10, // Sega Sports Pad -- Master System
SYSTEM_TEAMPLAYER = 11, // Multi Tap -- Sega TeamPlayer SYSTEM_TEAMPLAYER = 11, // Multi Tap -- Sega TeamPlayer
SYSTEM_WAYPLAY = 12, // Multi Tap -- EA 4-Way Play -- use both ports SYSTEM_WAYPLAY = 12, // Multi Tap -- EA 4-Way Play -- use both ports
}; };
public enum INPUT_DEVICE : byte public enum INPUT_DEVICE : byte
{ {
DEVICE_NONE = 0xff, // unconnected device = fixed ID for Team Player) DEVICE_NONE = 0xff, // unconnected device = fixed ID for Team Player)
DEVICE_PAD3B = 0x00, // 3-buttons Control Pad = fixed ID for Team Player) DEVICE_PAD3B = 0x00, // 3-buttons Control Pad = fixed ID for Team Player)
DEVICE_PAD6B = 0x01, // 6-buttons Control Pad = fixed ID for Team Player) DEVICE_PAD6B = 0x01, // 6-buttons Control Pad = fixed ID for Team Player)
DEVICE_PAD2B = 0x02, // 2-buttons Control Pad DEVICE_PAD2B = 0x02, // 2-buttons Control Pad
DEVICE_MOUSE = 0x03, // Sega Mouse DEVICE_MOUSE = 0x03, // Sega Mouse
DEVICE_LIGHTGUN = 0x04, // Sega Light Phaser, Menacer or Konami Justifiers DEVICE_LIGHTGUN = 0x04, // Sega Light Phaser, Menacer or Konami Justifiers
DEVICE_PADDLE = 0x05, // Sega Paddle Control DEVICE_PADDLE = 0x05, // Sega Paddle Control
DEVICE_SPORTSPAD = 0x06,// Sega Sports Pad DEVICE_SPORTSPAD = 0x06,// Sega Sports Pad
DEVICE_PICO = 0x07, // PICO tablet DEVICE_PICO = 0x07, // PICO tablet
DEVICE_TEREBI = 0x08, // Terebi Oekaki tablet DEVICE_TEREBI = 0x08, // Terebi Oekaki tablet
DEVICE_XE_A1P = 0x09, // XE-A1P analog controller DEVICE_XE_A1P = 0x09, // XE-A1P analog controller
DEVICE_ACTIVATOR = 0x0a,// Activator DEVICE_ACTIVATOR = 0x0a,// Activator
}; };
@ -151,8 +151,6 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx
[BizImport(CallingConvention.Cdecl)] [BizImport(CallingConvention.Cdecl)]
public abstract void gpgx_set_cd_callback(CDCallback cd); public abstract void gpgx_set_cd_callback(CDCallback cd);
/// <summary> /// <summary>
/// not every flag is valid for every device! /// not every flag is valid for every device!
/// </summary> /// </summary>
@ -277,6 +275,9 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx
[BizImport(CallingConvention.Cdecl)] [BizImport(CallingConvention.Cdecl)]
public abstract void gpgx_set_cdd_callback(cd_read_cb cddcb); public abstract void gpgx_set_cdd_callback(cd_read_cb cddcb);
[BizImport(CallingConvention.Cdecl, Compatibility = true)]
public abstract void gpgx_swap_disc(CDData toc);
[StructLayout(LayoutKind.Sequential)] [StructLayout(LayoutKind.Sequential)]
public struct VDPNameTable public struct VDPNameTable
{ {

Binary file not shown.

View File

@ -192,6 +192,14 @@ GPGX_EX void gpgx_advance(void)
nsamples = audio_update(soundbuffer); nsamples = audio_update(soundbuffer);
} }
GPGX_EX void gpgx_swap_disc(const toc_t* toc)
{
if (system_hw == SYSTEM_MCD)
{
cdd_hotswap(toc);
}
}
typedef struct typedef struct
{ {
uint32 width; // in cells uint32 width; // in cells

File diff suppressed because it is too large Load Diff

View File

@ -1,106 +1,110 @@
/*************************************************************************************** /***************************************************************************************
* Genesis Plus * Genesis Plus
* CD drive processor & CD-DA fader * CD drive processor & CD-DA fader
* *
* Copyright (C) 2012-2013 Eke-Eke (Genesis Plus GX) * Copyright (C) 2012-2013 Eke-Eke (Genesis Plus GX)
* *
* Redistribution and use of this code or any derivative works are permitted * Redistribution and use of this code or any derivative works are permitted
* provided that the following conditions are met: * provided that the following conditions are met:
* *
* - Redistributions may not be sold, nor may they be used in a commercial * - Redistributions may not be sold, nor may they be used in a commercial
* product or activity. * product or activity.
* *
* - Redistributions that are modified from the original source must include the * - Redistributions that are modified from the original source must include the
* complete source code, including the source code for all components used by a * complete source code, including the source code for all components used by a
* binary built from the modified sources. However, as a special exception, the * binary built from the modified sources. However, as a special exception, the
* source code distributed need not include anything that is normally distributed * source code distributed need not include anything that is normally distributed
* (in either source or binary form) with the major components (compiler, kernel, * (in either source or binary form) with the major components (compiler, kernel,
* and so on) of the operating system on which the executable runs, unless that * and so on) of the operating system on which the executable runs, unless that
* component itself accompanies the executable. * component itself accompanies the executable.
* *
* - Redistributions must reproduce the above copyright notice, this list of * - Redistributions must reproduce the above copyright notice, this list of
* conditions and the following disclaimer in the documentation and/or other * conditions and the following disclaimer in the documentation and/or other
* materials provided with the distribution. * materials provided with the distribution.
* *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE. * POSSIBILITY OF SUCH DAMAGE.
* *
****************************************************************************************/ ****************************************************************************************/
#ifndef _HW_CDD_ #ifndef _HW_CDD_
#define _HW_CDD_ #define _HW_CDD_
#include "blip_buf.h" #include "blip_buf.h"
#ifdef USE_LIBTREMOR #ifdef USE_LIBTREMOR
#include "tremor/ivorbisfile.h" #include "tremor/ivorbisfile.h"
#endif #endif
#define cdd scd.cdd_hw #define cdd scd.cdd_hw
/* CDD status */ /* CDD status */
#define NO_DISC 0x00 #define NO_DISC 0x00
#define CD_PLAY 0x01 #define CD_PLAY 0x01
#define CD_SEEK 0x02 #define CD_SEEK 0x02
#define CD_SCAN 0x03 #define CD_SCAN 0x03
#define CD_READY 0x04 #define CD_READY 0x04
#define CD_OPEN 0x05 /* similar to 0x0E ? */ #define CD_OPEN 0x05 /* similar to 0x0E ? */
#define CD_STOP 0x09 #define CD_STOP 0x09
#define CD_END 0x0C #define CD_END 0x0C
/* CD blocks scanning speed */ /* CD blocks scanning speed */
#define CD_SCAN_SPEED 30 #define CD_SCAN_SPEED 30
#define CD_MAX_TRACKS 100 #define CD_MAX_TRACKS 100
/* CD track */ /* CD track */
typedef struct typedef struct
{ {
int start; int start;
int end; int end;
} track_t; } track_t;
/* CD TOC */ /* CD TOC */
typedef struct typedef struct
{ {
int end; int end;
int last; int last;
track_t tracks[CD_MAX_TRACKS]; track_t tracks[CD_MAX_TRACKS];
} toc_t; } toc_t;
/* CDD hardware */ /* CDD hardware */
typedef struct typedef struct
{ {
uint32 cycles; uint32 cycles;
uint32 latency; uint32 latency;
int loaded; int loaded;
int index; int index;
int lba; int lba;
int scanOffset; int scanOffset;
int volume; int volume;
int sampleOffset; int sampleOffset;
int sampleLba; int sampleLba;
uint8 status; uint8 status;
toc_t toc; toc_t toc;
int16 audio[2]; int16 audio[2];
} cdd_t; } cdd_t;
/* Function prototypes */ /* Function prototypes */
extern void cdd_init(blip_t* left, blip_t* right); extern void cdd_init(blip_t* left, blip_t* right);
extern void cdd_reset(void); extern void cdd_reset(void);
extern int cdd_load(const char *key, char *header); extern int cdd_load(const char *key, char *header);
extern void cdd_unload(void); extern void cdd_unload(void);
extern void cdd_read_data(uint8 *dst); extern void cdd_read_data(uint8 *dst);
extern void cdd_read_audio(unsigned int samples); extern void cdd_read_audio(unsigned int samples);
extern void cdd_update(void); extern void cdd_update(void);
extern void cdd_process(void); extern void cdd_process(void);
#endif // switch disks after emulation was started
// pass NULL to open tray
void cdd_hotswap(const toc_t *toc);
#endif