Add support for BIN/CUE images. Patch from bit, BIN/CUE handling from DOSBox.

This commit is contained in:
SarahW 2017-05-29 13:56:19 +01:00
commit a2f44b8ea7
21 changed files with 1363 additions and 423 deletions

View file

@ -16,7 +16,7 @@ pcem_LDADD = $(allegro_LIBS) -lopenal
pcem_SOURCES = 386.c 386_dynarec.c 386_dynarec_ops.c 808x.c acer386sx.c ali1429.c allegro-gui.c \
allegro-gui-config-sel.c allegro-gui-configure.c allegro-gui-deviceconfig.c allegro-gui-hdconf.c allegro-joystick.c allegro-keyboard.c allegro-main.c \
allegro-midi.c allegro-mouse.c allegro-video.c amstrad.c cdrom-ioctl-linux.c cdrom-iso.c cdrom-null.c \
allegro-midi.c allegro-mouse.c allegro-video.c amstrad.c cdrom-ioctl-linux.c cdrom-image.c cdrom-null.c \
codegen.c codegen_ops.c codegen_timing_486.c codegen_timing_686.c codegen_timing_pentium.c codegen_timing_winchip.c compaq.c config.c cpu.c \
dac.c dells200.c device.c disc.c disc_fdi.c disc_img.c disc_sector.c dma.c fdc.c fdc37c665.c fdd.c fdi2raw.c gameport.c \
hdd.c hdd_esdi.c headland.c i430lx.c i430fx.c i430vx.c ide.c intel.c intel_flash.c io.c jim.c joystick_ch_flightstick_pro.c joystick_standard.c joystick_sw_pad.c \
@ -32,7 +32,7 @@ vid_icd2061.c vid_ics2595.c vid_incolor.c vid_mda.c vid_olivetti_m24.c vid_oti06
vid_pc1512.c vid_pc1640.c vid_pcjr.c vid_ps1_svga.c vid_s3.c vid_s3_virge.c vid_sdac_ramdac.c \
vid_stg_ramdac.c vid_svga.c vid_svga_render.c vid_tandy.c vid_tandysl.c vid_tgui9440.c \
vid_tkd8001_ramdac.c vid_tvga.c vid_unk_ramdac.c vid_vga.c vid_voodoo.c video.c wd76c10.c vid_wy700.c \
x86seg.c x87.c xtide.c sound_dbopl.cc sound_resid.cc dosbox/dbopl.cpp \
x86seg.c x87.c xtide.c sound_dbopl.cc sound_resid.cc dosbox/cdrom_image.cpp dosbox/dbopl.cpp \
dosbox/vid_cga_comp.c resid-fp/convolve.cc resid-fp/convolve-sse.cc resid-fp/envelope.cc \
resid-fp/extfilt.cc resid-fp/filter.cc resid-fp/pot.cc resid-fp/sid.cc \
resid-fp/voice.cc resid-fp/wave6581_PS_.cc resid-fp/wave6581_PST.cc \

View file

@ -5,7 +5,7 @@ CFLAGS = -O3 -fomit-frame-pointer -msse2 -m32
LDFLAGS = -m32
OBJ = 386.o 386_dynarec.o 386_dynarec_ops.o 808x.o acer386sx.o ali1429.o allegro-gui.o \
allegro-gui-configure.o allegro-gui-config-sel.o allegro-gui-deviceconfig.o allegro-gui-hdconf.o allegro-joystick.o allegro-keyboard.o allegro-main.o \
allegro-midi.o allegro-mouse.o allegro-video.o amstrad.o cdrom-ioctl-linux.o cdrom-iso.o cdrom-null.o \
allegro-midi.o allegro-mouse.o allegro-video.o amstrad.o cdrom-ioctl-linux.o cdrom-image.o cdrom-null.o \
codegen.o codegen_ops.o codegen_timing_486.o codegen_timing_686.o codegen_timing_pentium.o codegen_timing_winchip.o codegen_x86.c compaq.o config.o cpu.o \
dac.o dells200.o device.o disc.o disc_fdi.o disc_img.o disc_sector.o dma.o fdc.o fdc37c665.o fdd.o fdi2raw.o gameport.o \
hdd.o hdd_esdi.o headland.o i430lx.o i430fx.o i430vx.o ide.o intel.o intel_flash.o io.o jim.o joystick_ch_flightstick_pro.o joystick_standard.o joystick_sw_pad.o \
@ -22,7 +22,7 @@ vid_pc1512.o vid_pc1640.o vid_pcjr.o vid_ps1_svga.o vid_s3.o vid_s3_virge.o vid_
vid_stg_ramdac.o vid_svga.o vid_svga_render.o vid_tandy.o vid_tandysl.o vid_tgui9440.o \
vid_tkd8001_ramdac.o vid_tvga.o vid_unk_ramdac.o vid_vga.o vid_wy700.o vid_voodoo.o video.o wd76c10.o \
x86seg.o x87.o xtide.o sound_dbopl.o sound_resid.o
DBOBJ = dbopl.o vid_cga_comp.o
DBOBJ = cdrom_image.o dbopl.o vid_cga_comp.o
SIDOBJ = convolve.o convolve-sse.o envelope.o extfilt.o filter.o pot.o sid.o voice.o wave6581__ST.o wave6581_P_T.o wave6581_PS_.o wave6581_PST.o wave8580__ST.o wave8580_P_T.o wave8580_PS_.o wave8580_PST.o wave.o

View file

@ -4,7 +4,7 @@ CC = gcc
CFLAGS = -O3 -fomit-frame-pointer -msse2 -m64
OBJ = 386.o 386_dynarec.o 386_dynarec_ops.o 808x.o acer386sx.o ali1429.o allegro-gui.o \
allegro-gui-configure.o allegro-gui-config-sel.o allegro-gui-deviceconfig.o allegro-gui-hdconf.o allegro-joystick.o allegro-keyboard.o allegro-main.o \
allegro-midi.o allegro-mouse.o allegro-video.o amstrad.o cdrom-ioctl-linux.o cdrom-iso.o cdrom-null.o \
allegro-midi.o allegro-mouse.o allegro-video.o amstrad.o cdrom-ioctl-linux.o cdrom-image.o cdrom-null.o \
codegen.o codegen_ops.o codegen_timing_486.o codegen_timing_686.o codegen_timing_pentium.o codegen_timing_winchip.o codegen_x86-64.c compaq.o config.o cpu.o \
dac.o dells200.o device.o disc.o disc_fdi.o disc_img.o disc_sector.o dma.o fdc.o fdc37c665.o fdd.o fdi2raw.o gameport.o \
hdd.o hdd_esdi.o headland.o i430lx.o i430fx.o i430vx.o ide.o intel.o intel_flash.o io.o jim.o joystick_ch_flightstick_pro.o joystick_standard.o joystick_sw_pad.o \
@ -21,7 +21,7 @@ vid_pc1512.o vid_pc1640.o vid_pcjr.o vid_ps1_svga.o vid_s3.o vid_s3_virge.o vid_
vid_stg_ramdac.o vid_svga.o vid_svga_render.o vid_tandy.o vid_tandysl.o vid_tgui9440.o \
vid_tkd8001_ramdac.o vid_tvga.o vid_unk_ramdac.o vid_vga.o vid_voodoo.o vid_wy700.o video.o wd76c10.o \
x86seg.o x87.o xtide.o sound_dbopl.o sound_resid.o
DBOBJ = dbopl.o vid_cga_comp.o
DBOBJ = cdrom_image.o dbopl.o vid_cga_comp.o
SIDOBJ = convolve.o convolve-sse.o envelope.o extfilt.o filter.o pot.o sid.o voice.o wave6581__ST.o wave6581_P_T.o wave6581_PS_.o wave6581_PST.o wave8580__ST.o wave8580_P_T.o wave8580_PS_.o wave8580_PST.o wave.o

View file

@ -3,7 +3,7 @@ CPP = g++.exe
CC = gcc.exe
WINDRES = windres.exe
CFLAGS = -O3 -march=i686 -fomit-frame-pointer -msse2 -mstackrealign -Wall -Werror -fno-strict-aliasing
OBJ = 386.o 386_dynarec.o 386_dynarec_ops.o 808x.o acer386sx.o ali1429.o amstrad.o cdrom-ioctl.o cdrom-iso.o \
OBJ = 386.o 386_dynarec.o 386_dynarec_ops.o 808x.o acer386sx.o ali1429.o amstrad.o cdrom-ioctl.o cdrom-image.o \
codegen.o codegen_ops.o codegen_timing_486.o codegen_timing_686.o codegen_timing_pentium.o codegen_timing_winchip.o codegen_x86.o compaq.o config.o cpu.o dac.o \
dells200.o device.o disc.o disc_fdi.o disc_img.o disc_sector.o dma.o fdc.o fdc37c665.o fdd.o fdi2raw.o gameport.o hdd.o hdd_esdi.o headland.o i430lx.o i430fx.o \
i430vx.o ide.o intel.o intel_flash.o io.o jim.o joystick_ch_flightstick_pro.o joystick_standard.o joystick_sw_pad.o joystick_tm_fcs.o keyboard.o keyboard_amstrad.o keyboard_at.o \
@ -21,7 +21,7 @@ OBJ = 386.o 386_dynarec.o 386_dynarec_ops.o 808x.o acer386sx.o ali1429.o amstrad
vid_vga.o vid_voodoo.o vid_wy700.o video.o wd76c10.o win.o win-config.o win-config_sel.o win-d3d.o win-d3d-fs.o win-ddraw.o \
win-ddraw-fs.o win-deviceconfig.o win-hdconf.o win-joystick.o win-joystickconfig.o win-keyboard.o win-midi.o win-mouse.o \
win-status.o win-video.o x86seg.o x87.o xtide.o pc.res
DBOBJ = dbopl.o vid_cga_comp.o
DBOBJ = cdrom_image.o dbopl.o vid_cga_comp.o
SIDOBJ = convolve.o convolve-sse.o envelope.o extfilt.o filter.o pot.o sid.o voice.o wave6581__ST.o wave6581_P_T.o wave6581_PS_.o wave6581_PST.o wave8580__ST.o wave8580_P_T.o wave8580_PS_.o wave8580_PST.o wave.o

View file

@ -3,7 +3,7 @@ CPP = g++.exe
CC = gcc.exe
WINDRES = windres.exe
CFLAGS = -O3 -fomit-frame-pointer -msse2 -Wall -Werror -fno-strict-aliasing
OBJ = 386.o 386_dynarec.o 386_dynarec_ops.o 808x.o acer386sx.o ali1429.o amstrad.o cdrom-ioctl.o cdrom-iso.o \
OBJ = 386.o 386_dynarec.o 386_dynarec_ops.o 808x.o acer386sx.o ali1429.o amstrad.o cdrom-ioctl.o cdrom-image.o \
codegen.o codegen_ops.o codegen_timing_486.o codegen_timing_686.o codegen_timing_pentium.o codegen_timing_winchip.o codegen_x86-64.o compaq.o config.o cpu.o dac.o \
dells200.o device.o disc.o disc_fdi.o disc_img.o disc_sector.o dma.o fdc.o fdc37c665.o fdd.o fdi2raw.o gameport.o hdd.o hdd_esdi.o headland.o i430lx.o i430fx.o \
i430vx.o ide.o intel.o intel_flash.o io.o jim.o joystick_ch_flightstick_pro.o joystick_standard.o joystick_sw_pad.o joystick_tm_fcs.o keyboard.o keyboard_amstrad.o keyboard_at.o \
@ -21,7 +21,7 @@ OBJ = 386.o 386_dynarec.o 386_dynarec_ops.o 808x.o acer386sx.o ali1429.o amstrad
vid_vga.o vid_voodoo.o vid_wy700.o video.o wd76c10.o win.o win-config.o win-config_sel.o win-d3d.o win-d3d-fs.o win-ddraw.o \
win-ddraw-fs.o win-deviceconfig.o win-hdconf.o win-joystick.o win-joystickconfig.o win-keyboard.o win-midi.o win-mouse.o \
win-status.o win-video.o x86seg.o x87.o xtide.o pc.res
DBOBJ = dbopl.o vid_cga_comp.o
DBOBJ = cdrom_image.o dbopl.o vid_cga_comp.o
SIDOBJ = convolve.o convolve-sse.o envelope.o extfilt.o filter.o pot.o sid.o voice.o wave6581__ST.o wave6581_P_T.o wave6581_PS_.o wave6581_PST.o wave8580__ST.o wave8580_P_T.o wave8580_PS_.o wave8580_PST.o wave.o

View file

@ -5,7 +5,7 @@
#include "disc.h"
#include "ide.h"
#include "cdrom-ioctl.h"
#include "cdrom-iso.h"
#include "cdrom-image.h"
#include "cdrom-null.h"
void warning(const char *format, ...)
@ -128,7 +128,7 @@ static void cdrom_update()
case -1:
cdrom_menu[1].flags = D_SELECTED;
break;
case CDROM_ISO:
case CDROM_IMAGE:
cdrom_menu[3].flags = D_SELECTED;
break;
default:
@ -200,14 +200,14 @@ static int cdrom_dev()
return D_O_K;
}
static int cdrom_iso()
static int cdrom_image()
{
char fn[260];
int ret;
int xsize = SCREEN_W - 32, ysize = SCREEN_H - 64;
strcpy(fn, iso_path);
ret = file_select_ex("Please choose an ISO image", fn, "ISO", 260, xsize, ysize);
strcpy(fn, image_path);
ret = file_select_ex("Please choose an image image", fn, "ISO;CUE", 260, xsize, ysize);
if (ret)
{
if (!cdrom_enabled)
@ -220,8 +220,8 @@ static int cdrom_iso()
atapi->exit();
}
cdrom_drive = CDROM_ISO;
iso_open(fn);
cdrom_drive = CDROM_IMAGE;
image_open(fn);
if (!cdrom_enabled)
{
cdrom_enabled = 1;
@ -238,7 +238,7 @@ static MENU cdrom_menu[] =
{"&Disabled", cdrom_disabled, NULL, 0, NULL},
{"&Empty", cdrom_empty, NULL, 0, NULL},
{"/dev/cdrom", cdrom_dev, NULL, 0, NULL},
{"&ISO image...", cdrom_iso, NULL, 0, NULL},
{"&Image...", cdrom_image, NULL, 0, NULL},
{NULL,NULL,NULL,0,NULL}
};

551
src/cdrom-image.cc Normal file
View file

@ -0,0 +1,551 @@
#include <stdlib.h>
#include "cdrom-image.h"
#include "dosbox/cdrom.h"
extern "C"
{
#include "ibm.h"
#include "ide.h"
int cdrom_drive;
int old_cdrom_drive;
}
char image_path[1024];
static int image_changed = 0;
extern ATAPI image_atapi;
CDROM_Interface_Image *cdrom = NULL;
#define MSFtoLBA(m,s,f) (((((m*60)+s)*75)+f))
static uint32_t cdrom_capacity = 0;
enum
{
CD_STOPPED = 0,
CD_PLAYING,
CD_PAUSED
};
static int image_cd_state = CD_STOPPED;
static uint32_t image_cd_pos = 0, image_cd_end = 0;
#define BUF_SIZE 32768
static int16_t cd_buffer[BUF_SIZE];
static int cd_buflen = 0;
void image_audio_callback(int16_t *output, int len)
{
if (image_cd_state != CD_PLAYING)
return;
while (cd_buflen < len)
{
if (image_cd_pos < image_cd_end)
{
// pclog("Read to %i\n", cd_buflen);
if (!cdrom->ReadSector((unsigned char *)&cd_buffer[cd_buflen], true, image_cd_pos - 150))
{
// pclog("DeviceIoControl returned false\n");
memset(&cd_buffer[cd_buflen], 0, (BUF_SIZE - cd_buflen) * 2);
image_cd_state = CD_STOPPED;
cd_buflen = len;
}
else
{
// pclog("DeviceIoControl returned true\n");
image_cd_pos++;
cd_buflen += (RAW_SECTOR_SIZE / 2);
}
}
else
{
memset(&cd_buffer[cd_buflen], 0, (BUF_SIZE - cd_buflen) * 2);
image_cd_state = CD_STOPPED;
cd_buflen = len;
}
}
memcpy(output, cd_buffer, len * 2);
memmove(cd_buffer, &cd_buffer[len], (BUF_SIZE - len) * 2);
cd_buflen -= len;
}
void image_audio_stop()
{
image_cd_state = CD_STOPPED;
}
static int image_is_track_audio(uint32_t pos, int ismsf)
{
if (!cdrom) return 0;
if (ismsf)
{
int m = (pos >> 16) & 0xff;
int s = (pos >> 8) & 0xff;
int f = pos & 0xff;
pos = MSF_TO_FRAMES(m, s, f);
}
unsigned char attr;
TMSF tmsf;
int number;
cdrom->GetAudioTrackInfo(cdrom->GetTrack(pos), number, tmsf, attr);
return attr == AUDIO_TRACK;
}
static void image_playaudio(uint32_t pos, uint32_t len, int ismsf)
{
if (!cdrom) return;
int number;
unsigned char attr;
TMSF tmsf;
cdrom->GetAudioTrackInfo(cdrom->GetTrack(pos), number, tmsf, attr);
if (attr == DATA_TRACK)
{
pclog("Can't play data track\n");
image_cd_pos = 0;
image_cd_state = CD_STOPPED;
return;
}
pclog("Play audio - %08X %08X %i\n", pos, len, ismsf);
if (ismsf)
{
int m, s, f;
m = (pos >> 16) & 0xff;
s = (pos >> 8) & 0xff;
f = pos & 0xff;
pos = MSFtoLBA(m, s, f);
m = (len >> 16) & 0xff;
s = (len >> 8) & 0xff;
f = len & 0xff;
len = MSFtoLBA(m, s, f);
pclog("MSF - pos = %08X len = %08X\n", pos, len);
}
else
len += pos;
image_cd_pos = pos;// + 150;
image_cd_end = len;// + 150;
image_cd_state = CD_PLAYING;
if (image_cd_pos < 150)
image_cd_pos = 150;
cd_buflen = 0;
pclog("Audio start %08X %08X %i %i %i\n", image_cd_pos, image_cd_end, image_cd_state, cd_buflen, len);
}
static void image_pause(void)
{
if (!cdrom) return;
if (image_cd_state == CD_PLAYING)
image_cd_state = CD_PAUSED;
}
static void image_resume(void)
{
if (!cdrom) return;
if (image_cd_state == CD_PAUSED)
image_cd_state = CD_PLAYING;
}
static void image_stop(void)
{
if (!cdrom) return;
image_cd_state = CD_STOPPED;
}
static void image_seek(uint32_t pos)
{
if (!cdrom) return;
image_cd_pos = pos;
image_cd_state = CD_STOPPED;
}
static int image_ready(void)
{
if (!cdrom)
return 0;
if (strlen(image_path) == 0)
return 0;
if (image_changed)
image_changed = 0;
return 1;
}
static int image_get_last_block(unsigned char starttrack, int msf, int maxlen, int single)
{
int c;
uint32_t lb=0;
if (!cdrom) return 0;
int first_track;
int last_track;
int number;
unsigned char attr;
TMSF tmsf;
cdrom->GetAudioTracks(first_track, last_track, tmsf);
for (c = 0; c <= last_track; c++)
{
uint32_t address;
cdrom->GetAudioTrackInfo(c+1, number, tmsf, attr);
address = MSFtoLBA(tmsf.min, tmsf.sec, tmsf.fr) - 150;
if (address > lb)
lb = address;
}
return lb;
}
static int image_medium_changed(void)
{
if (!cdrom)
return 0;
if (strlen(image_path) == 0)
return 0;
if (old_cdrom_drive != cdrom_drive)
{
old_cdrom_drive = cdrom_drive;
return 1;
}
if (image_changed)
{
image_changed = 0;
return 1;
}
return 0;
}
static uint8_t image_getcurrentsubchannel(uint8_t *b, int msf)
{
if (!cdrom) return 0;
uint8_t ret;
int pos=0;
uint32_t cdpos = image_cd_pos;
if (cdpos >= 150) cdpos -= 150;
TMSF relPos, absPos;
unsigned char attr, track, index;
cdrom->GetAudioSub(cdpos, attr, track, index, relPos, absPos);
if (image_cd_state == CD_PLAYING)
ret = 0x11;
else if (image_cd_state == CD_PAUSED)
ret = 0x12;
else
ret = 0x13;
b[pos++] = attr;
b[pos++] = track;
b[pos++] = index;
if (msf)
{
uint32_t dat = MSFtoLBA(absPos.min, absPos.sec, absPos.fr);
b[pos + 3] = (uint8_t)(dat % 75); dat /= 75;
b[pos + 2] = (uint8_t)(dat % 60); dat /= 60;
b[pos + 1] = (uint8_t)dat;
b[pos] = 0;
pos += 4;
dat = MSFtoLBA(relPos.min, relPos.sec, relPos.fr);
b[pos + 3] = (uint8_t)(dat % 75); dat /= 75;
b[pos + 2] = (uint8_t)(dat % 60); dat /= 60;
b[pos + 1] = (uint8_t)dat;
b[pos] = 0;
pos += 4;
}
else
{
uint32_t dat = MSFtoLBA(absPos.min, absPos.sec, absPos.fr);
b[pos++] = (dat >> 24) & 0xff;
b[pos++] = (dat >> 16) & 0xff;
b[pos++] = (dat >> 8) & 0xff;
b[pos++] = dat & 0xff;
dat = MSFtoLBA(relPos.min, relPos.sec, relPos.fr);
b[pos++] = (dat >> 24) & 0xff;
b[pos++] = (dat >> 16) & 0xff;
b[pos++] = (dat >> 8) & 0xff;
b[pos++] = dat & 0xff;
}
return ret;
}
static void image_eject(void)
{
}
static void image_load(void)
{
}
static int image_readsector(uint8_t *b, int sector)
{
if (!cdrom) return -1;
return !cdrom->ReadSector(b, false, sector);
}
static void image_readsector_raw(uint8_t *b, int sector)
{
if (!cdrom) return;
cdrom->ReadSector(b, true, sector);
}
static int image_readtoc(unsigned char *b, unsigned char starttrack, int msf, int maxlen, int single)
{
if (!cdrom) return 0;
int len=4;
int c,d;
uint32_t temp;
int first_track;
int last_track;
int number;
unsigned char attr;
TMSF tmsf;
cdrom->GetAudioTracks(first_track, last_track, tmsf);
b[2] = first_track;
b[3] = last_track;
d = 0;
for (c = 0; c <= last_track; c++)
{
cdrom->GetAudioTrackInfo(c+1, number, tmsf, attr);
if (number >= starttrack)
{
d=c;
break;
}
}
cdrom->GetAudioTrackInfo(c+1, number, tmsf, attr);
b[2] = number;
for (c = d; c <= last_track; c++)
{
if ((len + 8) > maxlen)
break;
cdrom->GetAudioTrackInfo(c+1, number, tmsf, attr);
// pclog("Len %i max %i Track %02X - %02X %02X %02i:%02i:%02i %08X\n",len,maxlen,toc[c].cdte_track,toc[c].cdte_adr,toc[c].cdte_ctrl,toc[c].cdte_addr.msf.minute, toc[c].cdte_addr.msf.second, toc[c].cdte_addr.msf.frame,MSFtoLBA(toc[c].cdte_addr.msf.minute, toc[c].cdte_addr.msf.second, toc[c].cdte_addr.msf.frame));
b[len++] = 0; /* reserved */
b[len++] = attr;
b[len++] = number; /* track number */
b[len++] = 0; /* reserved */
if (msf)
{
b[len++] = 0;
b[len++] = tmsf.min;
b[len++] = tmsf.sec;
b[len++] = tmsf.fr;
}
else
{
temp = MSFtoLBA(tmsf.min, tmsf.sec, tmsf.fr) - 150;
b[len++] = temp >> 24;
b[len++] = temp >> 16;
b[len++] = temp >> 8;
b[len++] = temp;
}
if (single)
break;
}
b[0] = (uint8_t)(((len-2) >> 8) & 0xff);
b[1] = (uint8_t)((len-2) & 0xff);
/*
pclog("Table of Contents:\n");
pclog("First track - %02X\n", first_track);
pclog("Last track - %02X\n", last_track);
for (c = 0; c <= last_track; c++)
{
cdrom->GetAudioTrackInfo(c+1, number, tmsf, attr);
pclog("Track %02X - number %02X control %02X adr %02X address %02X %02X %02X %02X\n", c, number, attr, 0, 0, tmsf.min, tmsf.sec, tmsf.fr);
}
for (c = 0;c <= last_track; c++) {
cdrom->GetAudioTrackInfo(c+1, number, tmsf, attr);
pclog("Track %02X - number %02X control %02X adr %02X address %06X\n", c, number, attr, 0, MSF_TO_FRAMES(tmsf.min, tmsf.sec, tmsf.fr));
}
*/
return len;
}
static int image_readtoc_session(unsigned char *b, int msf, int maxlen)
{
if (!cdrom) return 0;
int len = 4;
int number;
TMSF tmsf;
unsigned char attr;
cdrom->GetAudioTrackInfo(1, number, tmsf, attr);
// pclog("Read TOC session - %i %02X %02X %i %i %02X %02X %02X\n",0, 0, 0,1,1,attr,0,number);
b[2] = 1;
b[3] = 1;
b[len++] = 0; /* reserved */
b[len++] = attr;
b[len++] = number; /* track number */
b[len++] = 0; /* reserved */
if (msf)
{
b[len++] = 0;
b[len++] = tmsf.min;
b[len++] = tmsf.sec;
b[len++] = tmsf.fr;
}
else
{
uint32_t temp = MSFtoLBA(tmsf.min, tmsf.sec, tmsf.fr) - 150;
b[len++] = temp >> 24;
b[len++] = temp >> 16;
b[len++] = temp >> 8;
b[len++] = temp;
}
return len;
}
static int image_readtoc_raw(unsigned char *b, int maxlen)
{
if (!cdrom) return 0;
int track;
int len = 4;
int first_track;
int last_track;
int number;
unsigned char attr;
TMSF tmsf;
cdrom->GetAudioTracks(first_track, last_track, tmsf);
b[2] = first_track;
b[3] = last_track;
for (track = first_track; track <= last_track; track++)
{
if ((len + 11) > maxlen)
{
pclog("image_readtocraw: This iteration would fill the buffer beyond the bounds, aborting...\n");
return len;
}
cdrom->GetAudioTrackInfo(track, number, tmsf, attr);
// pclog("read_toc: Track %02X - number %02X control %02X adr %02X address %02X %02X %02X %02X\n", track, toc[track].cdte_track, toc[track].cdte_ctrl, toc[track].cdte_adr, 0, toc[track].cdte_addr.msf.minute, toc[track].cdte_addr.msf.second, toc[track].cdte_addr.msf.frame);
b[len++] = track;
b[len++]= attr;
b[len++]=0;
b[len++]=0;
b[len++]=0;
b[len++]=0;
b[len++]=0;
b[len++]=0;
b[len++] = tmsf.min;
b[len++] = tmsf.sec;
b[len++] = tmsf.fr;
}
return len;
}
static uint32_t image_size()
{
return cdrom_capacity;
}
static int image_status()
{
if (!cdrom) return CD_STATUS_EMPTY;
if (cdrom->HasAudioTracks())
{
switch(image_cd_state)
{
case CD_PLAYING:
return CD_STATUS_PLAYING;
case CD_PAUSED:
return CD_STATUS_PAUSED;
case CD_STOPPED:
default:
return CD_STATUS_STOPPED;
}
}
return CD_STATUS_DATA_ONLY;
}
void image_reset()
{
}
void image_close(void)
{
image_cd_state = CD_STOPPED;
if (cdrom)
{
delete cdrom;
cdrom = NULL;
}
// memset(image_path, 0, 1024);
}
int image_open(char *fn)
{
if (strcmp(fn, image_path) != 0)
image_changed = 1;
/* Make sure image_changed stays when changing from an image to another image. */
if (cdrom_drive != CDROM_IMAGE)
image_changed = 1;
/* strcpy fails on OSX if both parameters are pointing to the same address */
if (image_path != fn)
strcpy(image_path, fn);
cdrom = new CDROM_Interface_Image();
if (!cdrom->SetDevice(fn, false))
{
image_close();
return 1;
}
image_cd_state = CD_STOPPED;
image_cd_pos = 0;
cd_buflen = 0;
cdrom_capacity = image_get_last_block(0, 0, 4096, 0) + 1;
atapi = &image_atapi;
return 0;
}
static void image_exit(void)
{
}
ATAPI image_atapi=
{
image_ready,
image_medium_changed,
image_readtoc,
image_readtoc_session,
image_readtoc_raw,
image_getcurrentsubchannel,
image_readsector,
image_readsector_raw,
image_playaudio,
image_seek,
image_load,
image_eject,
image_pause,
image_resume,
image_size,
image_status,
image_is_track_audio,
image_stop,
image_exit
};

23
src/cdrom-image.h Normal file
View file

@ -0,0 +1,23 @@
#ifndef CDROM_ISO_H
#define CDROM_ISO_H
#include <stdint.h>
extern char image_path[1024];
#ifdef __cplusplus
extern "C" {
#endif
int image_open(char *fn);
void image_reset();
void image_close();
void image_audio_callback(int16_t *output, int len);
void image_audio_stop();
#ifdef __cplusplus
}
#endif
#endif /* ! CDROM_ISO_H */

View file

@ -58,10 +58,7 @@ void ioctl_audio_callback(int16_t *output, int len)
// return;
// pclog("Audio callback %08X %08X %i %i %i %04X %i\n", ioctl_cd_pos, ioctl_cd_end, ioctl_cd_state, cd_buflen, len, cd_buffer[4], GetTickCount());
if (ioctl_cd_state != CD_PLAYING)
{
memset(output, 0, len * 2);
return;
}
while (cd_buflen < len)
{
if (ioctl_cd_pos < ioctl_cd_end)

View file

@ -1,356 +0,0 @@
/*ISO CD-ROM support*/
#include "ibm.h"
#include "ide.h"
#include "cdrom-iso.h"
#include <sys/stat.h>
static ATAPI iso_atapi;
static uint32_t last_block = 0;
static uint64_t image_size = 0;
static int iso_inited = 0;
char iso_path[1024];
void iso_close(void);
static FILE *iso_image = NULL;
static int iso_changed = 0;
void iso_audio_callback(int16_t *output, int len)
{
memset(output, 0, len * 2);
return;
}
void iso_audio_stop()
{
pclog("iso_audio_stop stub\n");
}
static void iso_playaudio(uint32_t pos, uint32_t len, int ismsf)
{
pclog("iso_playaudio stub\n");
return;
}
static void iso_pause(void)
{
pclog("iso_pause stub\n");
return;
}
static void iso_resume(void)
{
pclog("iso_resume stub\n");
return;
}
static void iso_stop(void)
{
pclog("iso_stop stub\n");
return;
}
static void iso_seek(uint32_t pos)
{
pclog("iso_seek stub\n");
return;
}
static int iso_ready(void)
{
if (strlen(iso_path) == 0)
return 0;
if (old_cdrom_drive != cdrom_drive)
return 1;
iso_changed = 0;
return 1;
}
/* Always return 0, because there is no way to change the ISO without unmounting and remounting it. */
static int iso_medium_changed(void)
{
iso_changed = 0;
return 0;
}
static uint8_t iso_getcurrentsubchannel(uint8_t *b, int msf)
{
pclog("iso_getcurrentsubchannel stub\n");
return 0;
}
static void iso_eject(void)
{
pclog("iso_eject stub\n");
}
static void iso_load(void)
{
pclog("iso_load stub\n");
}
static int iso_readsector(uint8_t *b, int sector)
{
if (!cdrom_drive)
return -1;
fseek(iso_image,sector*2048,SEEK_SET);
fread(b,2048,1,iso_image);
return 0;
}
static void lba_to_msf(uint8_t *buf, int lba)
{
lba += 150;
buf[0] = (lba / 75) / 60;
buf[1] = (lba / 75) % 60;
buf[2] = lba % 75;
}
static void iso_readsector_raw(uint8_t *b, int sector)
{
if (!cdrom_drive) return;
fseek(iso_image, sector*2048, SEEK_SET);
fread(b+16, 2048, 1, iso_image);
/* sync bytes */
b[0] = 0;
memset(b + 1, 0xff, 10);
b[11] = 0;
b += 12;
lba_to_msf(b, sector);
b[3] = 1; /* mode 1 data */
b += 4;
b += 2048;
memset(b, 0, 288);
}
static int iso_readtoc(unsigned char *buf, unsigned char start_track, int msf, int maxlen, int single)
{
uint8_t *q;
int len;
if (start_track > 1 && start_track != 0xaa)
return -1;
q = buf + 2;
*q++ = 1; /* first session */
*q++ = 1; /* last session */
if (start_track <= 1)
{
*q++ = 0; /* reserved */
*q++ = 0x14; /* ADR, control */
*q++ = 1; /* track number */
*q++ = 0; /* reserved */
if (msf)
{
*q++ = 0; /* reserved */
lba_to_msf(q, 0);
q += 3;
}
else
{
/* sector 0 */
*q++ = 0;
*q++ = 0;
*q++ = 0;
*q++ = 0;
}
}
/* lead out track */
*q++ = 0; /* reserved */
*q++ = 0x16; /* ADR, control */
*q++ = 0xaa; /* track number */
*q++ = 0; /* reserved */
last_block = image_size >> 11;
if (msf)
{
*q++ = 0; /* reserved */
lba_to_msf(q, last_block);
q += 3;
}
else
{
*q++ = last_block >> 24;
*q++ = last_block >> 16;
*q++ = last_block >> 8;
*q++ = last_block;
}
len = q - buf;
buf[0] = (uint8_t)(((len-2) >> 8) & 0xff);
buf[1] = (uint8_t)((len-2) & 0xff);
return len;
}
static int iso_readtoc_session(unsigned char *buf, int msf, int maxlen)
{
uint8_t *q;
q = buf + 2;
*q++ = 1; /* first session */
*q++ = 1; /* last session */
*q++ = 1; /* session number */
*q++ = 0x14; /* data track */
*q++ = 0; /* track number */
*q++ = 0xa0; /* lead-in */
*q++ = 0; /* min */
*q++ = 0; /* sec */
*q++ = 0; /* frame */
*q++ = 0;
return 12;
}
static int iso_readtoc_raw(unsigned char *buf, int maxlen)
{
uint8_t *q;
int len;
q = buf + 2;
*q++ = 1; /* first session */
*q++ = 1; /* last session */
*q++ = 1; /* session number */
*q++ = 0x14; /* data track */
*q++ = 0; /* track number */
*q++ = 0xa0; /* lead-in */
*q++ = 0; /* min */
*q++ = 0; /* sec */
*q++ = 0; /* frame */
*q++ = 0;
*q++ = 1; /* first track */
*q++ = 0x00; /* disk type */
*q++ = 0x00;
*q++ = 1; /* session number */
*q++ = 0x14; /* data track */
*q++ = 0; /* track number */
*q++ = 0xa1;
*q++ = 0; /* min */
*q++ = 0; /* sec */
*q++ = 0; /* frame */
*q++ = 0;
*q++ = 1; /* last track */
*q++ = 0x00;
*q++ = 0x00;
*q++ = 1; /* session number */
*q++ = 0x14; /* data track */
*q++ = 0; /* track number */
*q++ = 0xa2; /* lead-out */
*q++ = 0; /* min */
*q++ = 0; /* sec */
*q++ = 0; /* frame */
last_block = image_size >> 11;
/* this is raw, must be msf */
*q++ = 0; /* reserved */
lba_to_msf(q, last_block);
q += 3;
*q++ = 1; /* session number */
*q++ = 0x14; /* ADR, control */
*q++ = 0; /* track number */
*q++ = 1; /* point */
*q++ = 0; /* min */
*q++ = 0; /* sec */
*q++ = 0; /* frame */
/* same here */
*q++ = 0;
*q++ = 0;
*q++ = 0;
*q++ = 0;
len = q - buf;
buf[0] = (uint8_t)(((len-2) >> 8) & 0xff);
buf[1] = (uint8_t)((len-2) & 0xff);
return len;
}
static uint32_t iso_size()
{
unsigned char b[4096];
atapi->readtoc(b, 0, 0, 4096, 0);
return last_block;
}
static int iso_status()
{
if (!(iso_ready()) && (cdrom_drive != 200))
return CD_STATUS_EMPTY;
return CD_STATUS_DATA_ONLY;
}
void iso_reset()
{
}
int iso_open(char *fn)
{
struct stat st;
if (iso_image)
fclose(iso_image);
if (strcmp(fn, iso_path) != 0)
iso_changed = 1;
/* Make sure iso_changed stays when changing from ISO to another ISO. */
if (cdrom_drive != CDROM_ISO)
iso_changed = 1;
strcpy(iso_path, fn);
iso_image = fopen(iso_path, "rb");
atapi = &iso_atapi;
stat(iso_path, &st);
image_size = st.st_size;
return 0;
}
void iso_close(void)
{
if (iso_image)
{
fclose(iso_image);
iso_image = NULL;
}
memset(iso_path, 0, 1024);
}
static void iso_exit(void)
{
iso_inited = 0;
}
static int iso_is_track_audio(uint32_t pos, int ismsf)
{
return 0;
}
static ATAPI iso_atapi =
{
iso_ready,
iso_medium_changed,
iso_readtoc,
iso_readtoc_session,
iso_readtoc_raw,
iso_getcurrentsubchannel,
iso_readsector,
iso_readsector_raw,
iso_playaudio,
iso_seek,
iso_load,
iso_eject,
iso_pause,
iso_resume,
iso_size,
iso_status,
iso_is_track_audio,
iso_stop,
iso_exit
};

View file

@ -1,13 +0,0 @@
#ifndef CDROM_ISO_H
#define CDROM_ISO_H
/* this header file lists the functions provided by
various platform specific cdrom-ioctl files */
extern char iso_path[1024];
extern int iso_open(char *fn);
extern void iso_reset();
extern void iso_close();
#endif /* ! CDROM_ISO_H */

172
src/dosbox/cdrom.h Normal file
View file

@ -0,0 +1,172 @@
/*
* Copyright (C) 2002-2015 The DOSBox Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/* Modified for use with PCem by bit */
#ifndef __CDROM_INTERFACE__
#define __CDROM_INTERFACE__
#include <string.h>
#include <string>
#include <iostream>
#include <vector>
#include <fstream>
#include <sstream>
//#include "dosbox.h"
//#include "mem.h"
//#include "mixer.h"
//#include "SDL.h"
//#include "SDL_thread.h"
#include <stdint.h>
typedef signed int Bits;
typedef unsigned int Bitu;
typedef int8_t Bit8s;
typedef uint8_t Bit8u;
typedef int16_t Bit16s;
typedef uint16_t Bit16u;
typedef int32_t Bit32s;
typedef uint32_t Bit32u;
typedef size_t PhysPt;
#define RAW_SECTOR_SIZE 2352
#define COOKED_SECTOR_SIZE 2048
#define DATA_TRACK 0x14
#define AUDIO_TRACK 0x10
#define CD_FPS 75
#define FRAMES_TO_MSF(f, M,S,F) { \
int value = f; \
*(F) = value%CD_FPS; \
value /= CD_FPS; \
*(S) = value%60; \
value /= 60; \
*(M) = value; \
}
#define MSF_TO_FRAMES(M, S, F) ((M)*60*CD_FPS+(S)*CD_FPS+(F))
typedef struct SMSF {
unsigned char min;
unsigned char sec;
unsigned char fr;
} TMSF;
typedef struct SCtrl {
Bit8u out[4]; // output channel
Bit8u vol[4]; // channel volume
} TCtrl;
extern int CDROM_GetMountType(char* path, int force);
class CDROM_Interface
{
public:
// CDROM_Interface (void);
virtual ~CDROM_Interface (void) {};
virtual bool SetDevice (char* path, int forceCD) = 0;
virtual bool GetUPC (unsigned char& attr, char* upc) = 0;
virtual bool GetAudioTracks (int& stTrack, int& end, TMSF& leadOut) = 0;
virtual bool GetAudioTrackInfo (int track, int& number, TMSF& start, unsigned char& attr) = 0;
virtual bool GetAudioSub (int sector, unsigned char& attr, unsigned char& track, unsigned char& index, TMSF& relPos, TMSF& absPos) = 0;
virtual bool GetMediaTrayStatus (bool& mediaPresent, bool& mediaChanged, bool& trayOpen) = 0;
virtual bool ReadSectors (PhysPt buffer, bool raw, unsigned long sector, unsigned long num) = 0;
virtual bool LoadUnloadMedia (bool unload) = 0;
virtual void InitNewMedia (void) {};
};
class CDROM_Interface_Image : public CDROM_Interface
{
private:
class TrackFile {
public:
virtual bool read(Bit8u *buffer, int seek, int count) = 0;
virtual int getLength() = 0;
virtual ~TrackFile() { };
};
class BinaryFile : public TrackFile {
public:
BinaryFile(const char *filename, bool &error);
~BinaryFile();
bool read(Bit8u *buffer, int seek, int count);
int getLength();
private:
BinaryFile();
std::ifstream *file;
};
struct Track {
int number;
int track_number;
int attr;
int start;
int length;
int skip;
int sectorSize;
bool mode2;
TrackFile *file;
};
public:
CDROM_Interface_Image ();
virtual ~CDROM_Interface_Image (void);
void InitNewMedia (void);
bool SetDevice (char* path, int forceCD);
bool GetUPC (unsigned char& attr, char* upc);
bool GetAudioTracks (int& stTrack, int& end, TMSF& leadOut);
bool GetAudioTrackInfo (int track, int& number, TMSF& start, unsigned char& attr);
bool GetAudioSub (int sector, unsigned char& attr, unsigned char& track, unsigned char& index, TMSF& relPos, TMSF& absPos);
bool GetMediaTrayStatus (bool& mediaPresent, bool& mediaChanged, bool& trayOpen);
bool ReadSectors (PhysPt buffer, bool raw, unsigned long sector, unsigned long num);
bool LoadUnloadMedia (bool unload);
bool ReadSector (Bit8u *buffer, bool raw, unsigned long sector);
bool HasDataTrack (void);
bool HasAudioTracks (void);
int GetTrack (int sector);
private:
// player
static void CDAudioCallBack(Bitu len);
void ClearTracks();
bool LoadIsoFile(char *filename);
bool CanReadPVD(TrackFile *file, int sectorSize, bool mode2);
// cue sheet processing
bool LoadCueSheet(char *cuefile);
bool GetRealFileName(std::string& filename, std::string& pathname);
bool GetCueKeyword(std::string &keyword, std::istream &in);
bool GetCueFrame(int &frames, std::istream &in);
bool GetCueString(std::string &str, std::istream &in);
bool AddTrack(Track &curr, int &shift, int prestart, int &totalPregap, int currPregap);
std::vector<Track> tracks;
typedef std::vector<Track>::iterator track_it;
std::string mcn;
};
#endif /* __CDROM_INTERFACE__ */

546
src/dosbox/cdrom_image.cpp Normal file
View file

@ -0,0 +1,546 @@
/*
* Copyright (C) 2002-2015 The DOSBox Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/* Modified for use with PCem by bit */
#include <cctype>
#include <cmath>
#include <cstdio>
#include <fstream>
#include <iostream>
#include <limits>
#include <limits.h> //GCC 2.95
#include <sstream>
#include <vector>
#include <sys/stat.h>
#include "cdrom.h"
#if !defined(WIN32)
#include <libgen.h>
#else
#include <string.h>
#endif
using namespace std;
#define MAX_LINE_LENGTH 512
#define MAX_FILENAME_LENGTH 256
#define CROSS_LEN 512
#define safe_strncpy(a,b,n) do { strncpy((a),(b),(n)-1); (a)[(n)-1] = 0; } while (0)
CDROM_Interface_Image::BinaryFile::BinaryFile(const char *filename, bool &error)
{
file = new ifstream(filename, ios::in | ios::binary);
error = (file == NULL) || (file->fail());
}
CDROM_Interface_Image::BinaryFile::~BinaryFile()
{
delete file;
}
bool CDROM_Interface_Image::BinaryFile::read(Bit8u *buffer, int seek, int count)
{
file->seekg(seek, ios::beg);
file->read((char*)buffer, count);
return !(file->fail());
}
int CDROM_Interface_Image::BinaryFile::getLength()
{
file->seekg(0, ios::end);
int length = (int)file->tellg();
if (file->fail()) return -1;
return length;
}
CDROM_Interface_Image::CDROM_Interface_Image()
{
}
CDROM_Interface_Image::~CDROM_Interface_Image()
{
ClearTracks();
}
void CDROM_Interface_Image::InitNewMedia()
{
}
bool CDROM_Interface_Image::SetDevice(char* path, int forceCD)
{
if (LoadCueSheet(path)) return true;
if (LoadIsoFile(path)) return true;
// print error message on dosbox console
//printf("Could not load image file: %s\n", path);
return false;
}
bool CDROM_Interface_Image::GetUPC(unsigned char& attr, char* upc)
{
attr = 0;
strcpy(upc, this->mcn.c_str());
return true;
}
bool CDROM_Interface_Image::GetAudioTracks(int& stTrack, int& end, TMSF& leadOut)
{
stTrack = 1;
end = (int)(tracks.size() - 1);
FRAMES_TO_MSF(tracks[tracks.size() - 1].start + 150, &leadOut.min, &leadOut.sec, &leadOut.fr);
return true;
}
bool CDROM_Interface_Image::GetAudioTrackInfo(int track, int& track_number, TMSF& start, unsigned char& attr)
{
if (track < 1 || track > (int)tracks.size()) return false;
FRAMES_TO_MSF(tracks[track - 1].start + 150, &start.min, &start.sec, &start.fr);
track_number = tracks[track - 1].track_number;
attr = tracks[track - 1].attr;
return true;
}
bool CDROM_Interface_Image::GetAudioSub(int sector, unsigned char& attr, unsigned char& track, unsigned char& index, TMSF& relPos, TMSF& absPos)
{
int cur_track = GetTrack(sector);
if (cur_track < 1) return false;
track = (unsigned char)cur_track;
attr = tracks[track - 1].attr;
index = 1;
FRAMES_TO_MSF(sector + 150, &absPos.min, &absPos.sec, &absPos.fr);
FRAMES_TO_MSF(sector - tracks[track - 1].start + 150, &relPos.min, &relPos.sec, &relPos.fr);
return true;
}
bool CDROM_Interface_Image::GetMediaTrayStatus(bool& mediaPresent, bool& mediaChanged, bool& trayOpen)
{
mediaPresent = true;
mediaChanged = false;
trayOpen = false;
return true;
}
bool CDROM_Interface_Image::ReadSectors(PhysPt buffer, bool raw, unsigned long sector, unsigned long num)
{
int sectorSize = raw ? RAW_SECTOR_SIZE : COOKED_SECTOR_SIZE;
Bitu buflen = num * sectorSize;
Bit8u* buf = new Bit8u[buflen];
bool success = true; //Gobliiins reads 0 sectors
for(unsigned long i = 0; i < num; i++) {
success = ReadSector(&buf[i * sectorSize], raw, sector + i);
if (!success) break;
}
memcpy((void*)buffer, buf, buflen);
delete[] buf;
return success;
}
bool CDROM_Interface_Image::LoadUnloadMedia(bool unload)
{
return true;
}
int CDROM_Interface_Image::GetTrack(int sector)
{
vector<Track>::iterator i = tracks.begin();
vector<Track>::iterator end = tracks.end() - 1;
while(i != end) {
Track &curr = *i;
Track &next = *(i + 1);
if (curr.start <= sector && sector < next.start) return curr.number;
i++;
}
return -1;
}
bool CDROM_Interface_Image::ReadSector(Bit8u *buffer, bool raw, unsigned long sector)
{
int track = GetTrack(sector) - 1;
if (track < 0) return false;
int seek = tracks[track].skip + (sector - tracks[track].start) * tracks[track].sectorSize;
int length = (raw ? RAW_SECTOR_SIZE : COOKED_SECTOR_SIZE);
if (tracks[track].sectorSize != RAW_SECTOR_SIZE && raw) return false;
if (tracks[track].sectorSize == RAW_SECTOR_SIZE && !tracks[track].mode2 && !raw) seek += 16;
if (tracks[track].mode2 && !raw) seek += 24;
return tracks[track].file->read(buffer, seek, length);
}
bool CDROM_Interface_Image::LoadIsoFile(char* filename)
{
tracks.clear();
// data track
Track track = {0, 0, 0, 0, 0, 0, 0, false, NULL};
bool error;
track.file = new BinaryFile(filename, error);
if (error) {
delete track.file;
return false;
}
track.number = 1;
track.track_number = 1;
track.attr = DATA_TRACK;//data
// try to detect iso type
if (CanReadPVD(track.file, COOKED_SECTOR_SIZE, false)) {
track.sectorSize = COOKED_SECTOR_SIZE;
track.mode2 = false;
} else if (CanReadPVD(track.file, RAW_SECTOR_SIZE, false)) {
track.sectorSize = RAW_SECTOR_SIZE;
track.mode2 = false;
} else if (CanReadPVD(track.file, 2336, true)) {
track.sectorSize = 2336;
track.mode2 = true;
} else if (CanReadPVD(track.file, RAW_SECTOR_SIZE, true)) {
track.sectorSize = RAW_SECTOR_SIZE;
track.mode2 = true;
} else return false;
track.length = track.file->getLength() / track.sectorSize;
tracks.push_back(track);
// leadout track
track.number = 2;
track.track_number = 0xAA;
track.attr = 0;
track.start = track.length;
track.length = 0;
track.file = NULL;
tracks.push_back(track);
return true;
}
bool CDROM_Interface_Image::CanReadPVD(TrackFile *file, int sectorSize, bool mode2)
{
Bit8u pvd[COOKED_SECTOR_SIZE];
int seek = 16 * sectorSize; // first vd is located at sector 16
if (sectorSize == RAW_SECTOR_SIZE && !mode2) seek += 16;
if (mode2) seek += 24;
file->read(pvd, seek, COOKED_SECTOR_SIZE);
// pvd[0] = descriptor type, pvd[1..5] = standard identifier, pvd[6] = iso version (+8 for High Sierra)
return ((pvd[0] == 1 && !strncmp((char*)(&pvd[1]), "CD001", 5) && pvd[6] == 1) ||
(pvd[8] == 1 && !strncmp((char*)(&pvd[9]), "CDROM", 5) && pvd[14] == 1));
}
#if defined(WIN32)
static string dirname(char * file) {
char * sep = strrchr(file, '\\');
if (sep == NULL)
sep = strrchr(file, '/');
if (sep == NULL)
return "";
else {
int len = (int)(sep - file);
char tmp[MAX_FILENAME_LENGTH];
safe_strncpy(tmp, file, len+1);
return tmp;
}
}
#endif
bool CDROM_Interface_Image::LoadCueSheet(char *cuefile)
{
Track track = {0, 0, 0, 0, 0, 0, 0, false, NULL};
tracks.clear();
int shift = 0;
int currPregap = 0;
int totalPregap = 0;
int prestart = 0;
bool success;
bool canAddTrack = false;
char tmp[MAX_FILENAME_LENGTH]; // dirname can change its argument
safe_strncpy(tmp, cuefile, MAX_FILENAME_LENGTH);
string pathname(dirname(tmp));
ifstream in;
in.open(cuefile, ios::in);
if (in.fail()) return false;
while(!in.eof()) {
// get next line
char buf[MAX_LINE_LENGTH];
in.getline(buf, MAX_LINE_LENGTH);
if (in.fail() && !in.eof()) return false; // probably a binary file
istringstream line(buf);
string command;
GetCueKeyword(command, line);
if (command == "TRACK") {
if (canAddTrack) success = AddTrack(track, shift, prestart, totalPregap, currPregap);
else success = true;
track.start = 0;
track.skip = 0;
currPregap = 0;
prestart = 0;
line >> track.number;
track.track_number = track.number;
string type;
GetCueKeyword(type, line);
if (type == "AUDIO") {
track.sectorSize = RAW_SECTOR_SIZE;
track.attr = AUDIO_TRACK;
track.mode2 = false;
} else if (type == "MODE1/2048") {
track.sectorSize = COOKED_SECTOR_SIZE;
track.attr = DATA_TRACK;
track.mode2 = false;
} else if (type == "MODE1/2352") {
track.sectorSize = RAW_SECTOR_SIZE;
track.attr = DATA_TRACK;
track.mode2 = false;
} else if (type == "MODE2/2336") {
track.sectorSize = 2336;
track.attr = DATA_TRACK;
track.mode2 = true;
} else if (type == "MODE2/2352") {
track.sectorSize = RAW_SECTOR_SIZE;
track.attr = DATA_TRACK;
track.mode2 = true;
} else success = false;
canAddTrack = true;
}
else if (command == "INDEX") {
int index;
line >> index;
int frame;
success = GetCueFrame(frame, line);
if (index == 1) track.start = frame;
else if (index == 0) prestart = frame;
// ignore other indices
}
else if (command == "FILE") {
if (canAddTrack) success = AddTrack(track, shift, prestart, totalPregap, currPregap);
else success = true;
canAddTrack = false;
string filename;
GetCueString(filename, line);
GetRealFileName(filename, pathname);
string type;
GetCueKeyword(type, line);
track.file = NULL;
bool error = true;
if (type == "BINARY") {
track.file = new BinaryFile(filename.c_str(), error);
}
if (error) {
delete track.file;
success = false;
}
}
else if (command == "PREGAP") success = GetCueFrame(currPregap, line);
else if (command == "CATALOG") success = GetCueString(mcn, line);
// ignored commands
else if (command == "CDTEXTFILE" || command == "FLAGS" || command == "ISRC"
|| command == "PERFORMER" || command == "POSTGAP" || command == "REM"
|| command == "SONGWRITER" || command == "TITLE" || command == "") success = true;
// failure
else success = false;
if (!success) return false;
}
// add last track
if (!AddTrack(track, shift, prestart, totalPregap, currPregap)) return false;
// add leadout track
track.number++;
track.track_number = 0xAA;
track.attr = 0;//sync with load iso
track.start = 0;
track.length = 0;
track.file = NULL;
if(!AddTrack(track, shift, 0, totalPregap, 0)) return false;
return true;
}
bool CDROM_Interface_Image::AddTrack(Track &curr, int &shift, int prestart, int &totalPregap, int currPregap)
{
// frames between index 0(prestart) and 1(curr.start) must be skipped
int skip;
if (prestart > 0) {
if (prestart > curr.start) return false;
skip = curr.start - prestart;
} else skip = 0;
// first track (track number must be 1)
if (tracks.empty()) {
if (curr.number != 1) return false;
curr.skip = skip * curr.sectorSize;
curr.start += currPregap;
totalPregap = currPregap;
tracks.push_back(curr);
return true;
}
Track &prev = *(tracks.end() - 1);
// current track consumes data from the same file as the previous
if (prev.file == curr.file) {
curr.start += shift;
prev.length = curr.start + totalPregap - prev.start - skip;
curr.skip += prev.skip + prev.length * prev.sectorSize + skip * curr.sectorSize;
totalPregap += currPregap;
curr.start += totalPregap;
// current track uses a different file as the previous track
} else {
int tmp = prev.file->getLength() - prev.skip;
prev.length = tmp / prev.sectorSize;
if (tmp % prev.sectorSize != 0) prev.length++; // padding
curr.start += prev.start + prev.length + currPregap;
curr.skip = skip * curr.sectorSize;
shift += prev.start + prev.length;
totalPregap = currPregap;
}
// error checks
if (curr.number <= 1) return false;
if (prev.number + 1 != curr.number) return false;
if (curr.start < prev.start + prev.length) return false;
if (curr.length < 0) return false;
tracks.push_back(curr);
return true;
}
bool CDROM_Interface_Image::HasDataTrack(void)
{
//Data track has attribute 0x14
for(track_it it = tracks.begin(); it != tracks.end(); it++) {
if ((*it).attr == DATA_TRACK) return true;
}
return false;
}
bool CDROM_Interface_Image::HasAudioTracks(void)
{
for(track_it it = tracks.begin(); it != tracks.end(); it++) {
if ((*it).attr == AUDIO_TRACK) return true;
}
return false;
}
bool CDROM_Interface_Image::GetRealFileName(string &filename, string &pathname)
{
// check if file exists
struct stat test;
if (stat(filename.c_str(), &test) == 0) return true;
// check if file with path relative to cue file exists
string tmpstr(pathname + "/" + filename);
if (stat(tmpstr.c_str(), &test) == 0) {
filename = tmpstr;
return true;
}
#if defined (WIN32) || defined(OS2)
//Nothing
#else
//Consider the possibility that the filename has a windows directory seperator (inside the CUE file)
//which is common for some commercial rereleases of DOS games using DOSBox
string copy = filename;
size_t l = copy.size();
for (size_t i = 0; i < l;i++) {
if(copy[i] == '\\') copy[i] = '/';
}
if (stat(copy.c_str(), &test) == 0) {
filename = copy;
return true;
}
tmpstr = pathname + "/" + copy;
if (stat(tmpstr.c_str(), &test) == 0) {
filename = tmpstr;
return true;
}
#endif
return false;
}
bool CDROM_Interface_Image::GetCueKeyword(string &keyword, istream &in)
{
in >> keyword;
for(Bitu i = 0; i < keyword.size(); i++) keyword[i] = toupper(keyword[i]);
return true;
}
bool CDROM_Interface_Image::GetCueFrame(int &frames, istream &in)
{
string msf;
in >> msf;
int min, sec, fr;
bool success = sscanf(msf.c_str(), "%d:%d:%d", &min, &sec, &fr) == 3;
frames = MSF_TO_FRAMES(min, sec, fr);
return success;
}
bool CDROM_Interface_Image::GetCueString(string &str, istream &in)
{
int pos = (int)in.tellg();
in >> str;
if (str[0] == '\"') {
if (str[str.size() - 1] == '\"') {
str.assign(str, 1, str.size() - 2);
} else {
in.seekg(pos, ios::beg);
char buffer[MAX_FILENAME_LENGTH];
in.getline(buffer, MAX_FILENAME_LENGTH, '\"'); // skip
in.getline(buffer, MAX_FILENAME_LENGTH, '\"');
str = buffer;
}
}
return true;
}
void CDROM_Interface_Image::ClearTracks()
{
vector<Track>::iterator i = tracks.begin();
vector<Track>::iterator end = tracks.end();
TrackFile* last = NULL;
while(i != end) {
Track &curr = *i;
if (curr.file != last) {
delete curr.file;
last = curr.file;
}
i++;
}
tracks.clear();
}

View file

@ -167,7 +167,7 @@ struct
#define cycles cpu_state._cycles
uint32_t cpu_cur_status;
extern uint32_t cpu_cur_status;
#define CPU_STATUS_USE32 (1 << 0)
#define CPU_STATUS_STACK32 (1 << 1)

View file

@ -2415,7 +2415,7 @@ static void atapicommand(int ide_board)
}
if ((cdrom_drive < 1) || (cdrom_drive == CDROM_ISO) || (cd_status <= CD_STATUS_DATA_ONLY) ||
if ((cdrom_drive < 1) || (cd_status <= CD_STATUS_DATA_ONLY) ||
!atapi->is_track_audio(pos, (idebufferb[0] == GPCMD_PLAY_AUDIO_MSF) ? 1 : 0))
{
ide->atastat = READY_STAT | ERR_STAT; /*CHECK CONDITION*/

View file

@ -56,6 +56,6 @@ extern int cdrom_channel;
uint32_t atapi_get_cd_channel(int channel);
uint32_t atapi_get_cd_volume(int channel);
#define CDROM_ISO 200
#define CDROM_IMAGE 200
#endif //__IDE__

View file

@ -6,7 +6,7 @@
#include "ali1429.h"
#include "cdrom-ioctl.h"
#include "cdrom-iso.h"
#include "cdrom-image.h"
#include "disc.h"
#include "disc_img.h"
#include "mem.h"
@ -281,13 +281,13 @@ void initpc(int argc, char *argv[])
else
#endif
{
if (cdrom_drive == CDROM_ISO)
if (cdrom_drive == CDROM_IMAGE)
{
FILE *ff = fopen(iso_path, "rb");
FILE *ff = fopen(image_path, "rb");
if (ff)
{
fclose(ff);
iso_open(iso_path);
image_open(image_path);
}
else
{
@ -318,9 +318,9 @@ void initpc(int argc, char *argv[])
else
#endif
{
if (cdrom_drive == CDROM_ISO)
if (cdrom_drive == CDROM_IMAGE)
{
iso_reset();
image_reset();
}
else
{
@ -398,15 +398,31 @@ void resetpchard()
// output=3;
image_close();
#if __unix
if (cdrom_drive == -1)
cdrom_null_reset();
else
#endif
{
if (cdrom_drive == CDROM_ISO)
if (cdrom_drive == CDROM_IMAGE)
{
iso_reset();
FILE *ff = fopen(image_path, "rb");
if (ff)
{
fclose(ff);
image_open(image_path);
}
else
{
#if __unix
cdrom_drive = -1;
cdrom_null_open(cdrom_drive);
#else
cdrom_drive = 0;
ioctl_set_drive(cdrom_drive);
#endif
}
}
else
{
@ -655,8 +671,8 @@ void loadconfig(char *fn)
cdrom_channel = config_get_int(CFG_MACHINE, NULL, "cdrom_channel", 2);
p = (char *)config_get_string(CFG_MACHINE, NULL, "cdrom_path", "");
if (p) strcpy(iso_path, p);
else strcpy(iso_path, "");
if (p) strcpy(image_path, p);
else strcpy(image_path, "");
hdc[0].spt = config_get_int(CFG_MACHINE, NULL, "hdc_sectors", 0);
hdc[0].hpc = config_get_int(CFG_MACHINE, NULL, "hdc_heads", 0);
@ -764,7 +780,7 @@ void saveconfig(char *fn)
config_set_int(CFG_MACHINE, NULL, "cdrom_drive", cdrom_drive);
config_set_int(CFG_MACHINE, NULL, "cdrom_enabled", cdrom_enabled);
config_set_int(CFG_MACHINE, NULL, "cdrom_channel", cdrom_channel);
config_set_string(CFG_MACHINE, NULL, "cdrom_path", iso_path);
config_set_string(CFG_MACHINE, NULL, "cdrom_path", image_path);
config_set_int(CFG_MACHINE, NULL, "hdc_sectors", hdc[0].spt);
config_set_int(CFG_MACHINE, NULL, "hdc_heads", hdc[0].hpc);

View file

@ -31,7 +31,7 @@ BEGIN
BEGIN
MENUITEM "&Disabled", IDM_CDROM_DISABLED
MENUITEM "&Empty",IDM_CDROM_EMPTY
MENUITEM "&ISO...",IDM_CDROM_ISO
MENUITEM "&Image...",IDM_CDROM_IMAGE
END
POPUP "&Video"
BEGIN

View file

@ -24,7 +24,7 @@
#define IDM_CDROM_EMPTY 40100
#define IDM_CDROM_REAL 40100
#define IDM_CDROM_DISABLED 40200
#define IDM_CDROM_ISO 40201
#define IDM_CDROM_IMAGE 40201
#define IDC_COMBO1 1000
#define IDC_COMBOVID 1001

View file

@ -4,6 +4,7 @@
#include "device.h"
#include "cdrom-ioctl.h"
#include "cdrom-image.h"
#include "ide.h"
#include "filters.h"
@ -134,7 +135,9 @@ static void sound_cd_thread(void *param)
int c;
thread_wait_event(sound_cd_event, -1);
memset(cd_buffer, 0, CD_BUFLEN*2 * 2);
ioctl_audio_callback(cd_buffer, CD_BUFLEN*2);
image_audio_callback(cd_buffer, CD_BUFLEN*2);
if (soundon)
{
int32_t atapi_vol_l = atapi_get_cd_volume(0);
@ -259,4 +262,5 @@ void sound_reset()
sound_set_cd_volume(65535, 65535);
ioctl_audio_stop();
image_audio_stop();
}

View file

@ -15,7 +15,7 @@
#include <stdlib.h>
#include "ibm.h"
#include "cdrom-ioctl.h"
#include "cdrom-iso.h"
#include "cdrom-image.h"
#include "config.h"
#include "cpu.h"
#include "device.h"
@ -632,8 +632,8 @@ int WINAPI WinMain (HINSTANCE hThisInstance,
CheckMenuItem(menu, IDM_CDROM_DISABLED, MF_CHECKED);
else
{
if (cdrom_drive == CDROM_ISO)
CheckMenuItem(menu, IDM_CDROM_ISO, MF_CHECKED);
if (cdrom_drive == CDROM_IMAGE)
CheckMenuItem(menu, IDM_CDROM_IMAGE, MF_CHECKED);
else
CheckMenuItem(menu, IDM_CDROM_REAL + cdrom_drive, MF_CHECKED);
}
@ -885,8 +885,8 @@ void atapi_close(void)
{
switch (cdrom_drive)
{
case CDROM_ISO:
iso_close();
case CDROM_IMAGE:
image_close();
break;
default:
ioctl_close();
@ -898,7 +898,7 @@ LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM
{
HMENU hmenu;
RECT rect;
char temp_iso_path[1024];
char temp_image_path[1024];
int new_cdrom_drive;
// pclog("Message %i %08X\n",message,message);
switch (message)
@ -1067,7 +1067,7 @@ LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM
ioctl_set_drive(0);
CheckMenuItem(hmenu, IDM_CDROM_REAL + cdrom_drive, MF_UNCHECKED);
CheckMenuItem(hmenu, IDM_CDROM_DISABLED, MF_CHECKED);
CheckMenuItem(hmenu, IDM_CDROM_ISO, MF_UNCHECKED);
CheckMenuItem(hmenu, IDM_CDROM_IMAGE, MF_UNCHECKED);
old_cdrom_drive = cdrom_drive;
cdrom_drive=0;
CheckMenuItem(hmenu, IDM_CDROM_EMPTY, MF_UNCHECKED);
@ -1103,7 +1103,7 @@ LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM
}
CheckMenuItem(hmenu, IDM_CDROM_REAL + cdrom_drive, MF_UNCHECKED);
CheckMenuItem(hmenu, IDM_CDROM_DISABLED, MF_UNCHECKED);
CheckMenuItem(hmenu, IDM_CDROM_ISO, MF_UNCHECKED);
CheckMenuItem(hmenu, IDM_CDROM_IMAGE, MF_UNCHECKED);
old_cdrom_drive = cdrom_drive;
cdrom_drive=0;
CheckMenuItem(hmenu, IDM_CDROM_EMPTY, MF_CHECKED);
@ -1119,8 +1119,8 @@ LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM
}
break;
case IDM_CDROM_ISO:
if (!getfile(hwnd,"CD-ROM image (*.ISO)\0*.ISO\0All files (*.*)\0*.*\0",iso_path))
case IDM_CDROM_IMAGE:
if (!getfile(hwnd,"CD-ROM image (*.ISO;*.CUE)\0*.ISO;*.CUE\0All files (*.*)\0*.*\0",image_path))
{
if (!cdrom_enabled)
{
@ -1128,15 +1128,15 @@ LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM
break;
}
old_cdrom_drive = cdrom_drive;
strcpy(temp_iso_path, openfilestring);
if ((strcmp(iso_path, temp_iso_path) == 0) && (cdrom_drive == CDROM_ISO) && cdrom_enabled)
strcpy(temp_image_path, openfilestring);
if ((strcmp(image_path, temp_image_path) == 0) && (cdrom_drive == CDROM_IMAGE) && cdrom_enabled)
{
/* Switching from ISO to the same ISO. Do nothing. */
break;
}
atapi->exit();
atapi_close();
iso_open(temp_iso_path);
image_open(temp_image_path);
if (cdrom_enabled)
{
/* Signal disc change to the emulated machine. */
@ -1144,9 +1144,9 @@ LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM
}
CheckMenuItem(hmenu, IDM_CDROM_REAL + cdrom_drive, MF_UNCHECKED);
CheckMenuItem(hmenu, IDM_CDROM_DISABLED, MF_UNCHECKED);
CheckMenuItem(hmenu, IDM_CDROM_ISO, MF_UNCHECKED);
cdrom_drive = CDROM_ISO;
CheckMenuItem(hmenu, IDM_CDROM_ISO, MF_CHECKED);
CheckMenuItem(hmenu, IDM_CDROM_IMAGE, MF_UNCHECKED);
cdrom_drive = CDROM_IMAGE;
CheckMenuItem(hmenu, IDM_CDROM_IMAGE, MF_CHECKED);
saveconfig(NULL);
if (!cdrom_enabled)
{
@ -1185,7 +1185,7 @@ LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM
}
CheckMenuItem(hmenu, IDM_CDROM_REAL + cdrom_drive, MF_UNCHECKED);
CheckMenuItem(hmenu, IDM_CDROM_DISABLED, MF_UNCHECKED);
CheckMenuItem(hmenu, IDM_CDROM_ISO, MF_UNCHECKED);
CheckMenuItem(hmenu, IDM_CDROM_IMAGE, MF_UNCHECKED);
cdrom_drive = new_cdrom_drive;
CheckMenuItem(hmenu, IDM_CDROM_REAL + cdrom_drive, MF_CHECKED);
saveconfig(NULL);