2017-05-30 03:38:38 +02:00
|
|
|
/*
|
|
|
|
|
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
|
|
|
|
* running old operating systems and software designed for IBM
|
|
|
|
|
* PC systems and compatibles from 1981 through fairly recent
|
|
|
|
|
* system designs based on the PCI bus.
|
|
|
|
|
*
|
|
|
|
|
* This file is part of the 86Box distribution.
|
|
|
|
|
*
|
2018-10-10 22:33:24 +02:00
|
|
|
* Generic CD-ROM drive core.
|
2017-05-30 03:38:38 +02:00
|
|
|
*
|
2018-10-17 05:29:48 +02:00
|
|
|
* Version: @(#)cdrom.c 1.0.2 2018/10/17
|
2017-05-30 03:38:38 +02:00
|
|
|
*
|
|
|
|
|
* Author: Miran Grca, <mgrca8@gmail.com>
|
2017-10-08 19:14:46 -04:00
|
|
|
*
|
2018-10-10 22:33:24 +02:00
|
|
|
* Copyright 2018 Miran Grca.
|
2017-05-30 03:38:38 +02:00
|
|
|
*/
|
2018-03-21 14:46:54 +01:00
|
|
|
#include <inttypes.h>
|
2018-05-21 19:04:05 +02:00
|
|
|
#include <stdarg.h>
|
2017-01-16 01:49:19 +01:00
|
|
|
#include <stdint.h>
|
2018-05-21 19:04:05 +02:00
|
|
|
#include <stdio.h>
|
2017-01-17 00:01:59 +01:00
|
|
|
#include <string.h>
|
2017-09-25 04:31:20 -04:00
|
|
|
#include <stdlib.h>
|
|
|
|
|
#include <wchar.h>
|
2017-12-10 19:36:41 +01:00
|
|
|
#define HAVE_STDARG_H
|
2017-09-04 01:52:29 -04:00
|
|
|
#include "../86box.h"
|
2018-10-17 05:29:48 +02:00
|
|
|
#include "../config.h"
|
2017-01-16 01:49:19 +01:00
|
|
|
#include "cdrom.h"
|
2017-10-08 05:04:38 +02:00
|
|
|
#include "cdrom_image.h"
|
2018-10-17 05:29:48 +02:00
|
|
|
#include "../plat.h"
|
2018-10-10 22:33:24 +02:00
|
|
|
#include "../sound/sound.h"
|
2017-09-04 01:52:29 -04:00
|
|
|
|
2017-01-16 01:49:19 +01:00
|
|
|
|
2018-04-25 23:51:13 +02:00
|
|
|
#define MIN_SEEK 2000
|
|
|
|
|
#define MAX_SEEK 333333
|
|
|
|
|
|
|
|
|
|
|
2018-10-17 05:29:48 +02:00
|
|
|
cdrom_t cdrom[CDROM_NUM];
|
|
|
|
|
|
2017-01-16 01:49:19 +01:00
|
|
|
|
2017-10-16 06:19:18 +02:00
|
|
|
#ifdef ENABLE_CDROM_LOG
|
2018-10-17 05:29:48 +02:00
|
|
|
int cdrom_do_log = ENABLE_CDROM_LOG;
|
2017-01-16 01:49:19 +01:00
|
|
|
|
2017-11-24 02:23:00 -05:00
|
|
|
|
2018-10-17 05:29:48 +02:00
|
|
|
void
|
|
|
|
|
cdrom_log(const char *fmt, ...)
|
2017-01-16 01:49:19 +01:00
|
|
|
{
|
2018-04-25 23:51:13 +02:00
|
|
|
va_list ap;
|
2017-12-05 23:35:35 +01:00
|
|
|
|
2018-04-25 23:51:13 +02:00
|
|
|
if (cdrom_do_log) {
|
2018-10-17 05:29:48 +02:00
|
|
|
va_start(ap, fmt);
|
|
|
|
|
pclog_ex(fmt, ap);
|
2018-04-25 23:51:13 +02:00
|
|
|
va_end(ap);
|
|
|
|
|
}
|
2017-01-16 01:49:19 +01:00
|
|
|
}
|
2018-10-17 05:29:48 +02:00
|
|
|
#else
|
|
|
|
|
#define cdrom_log(fmt, ...)
|
|
|
|
|
#endif
|
2017-01-16 01:49:19 +01:00
|
|
|
|
2017-11-24 02:23:00 -05:00
|
|
|
|
2018-04-25 23:51:13 +02:00
|
|
|
int
|
|
|
|
|
cdrom_lba_to_msf_accurate(int lba)
|
2017-01-16 01:49:19 +01:00
|
|
|
{
|
2018-10-17 05:29:48 +02:00
|
|
|
int pos;
|
2018-04-25 23:51:13 +02:00
|
|
|
int m, s, f;
|
|
|
|
|
|
2018-10-17 05:29:48 +02:00
|
|
|
pos = lba + 150;
|
|
|
|
|
f = pos % 75;
|
|
|
|
|
pos -= f;
|
|
|
|
|
pos /= 75;
|
|
|
|
|
s = pos % 60;
|
|
|
|
|
pos -= s;
|
|
|
|
|
pos /= 60;
|
|
|
|
|
m = pos;
|
2018-04-25 23:51:13 +02:00
|
|
|
|
|
|
|
|
return ((m << 16) | (s << 8) | f);
|
2017-01-16 01:49:19 +01:00
|
|
|
}
|
|
|
|
|
|
2018-04-25 23:51:13 +02:00
|
|
|
|
2018-10-17 05:29:48 +02:00
|
|
|
static double
|
|
|
|
|
cdrom_get_short_seek(cdrom_t *dev)
|
2018-04-25 23:51:13 +02:00
|
|
|
{
|
|
|
|
|
switch(dev->cur_speed) {
|
|
|
|
|
case 0:
|
|
|
|
|
fatal("CD-ROM %i: 0x speed\n", dev->id);
|
|
|
|
|
return 0.0;
|
|
|
|
|
case 1:
|
|
|
|
|
return 240.0;
|
|
|
|
|
case 2:
|
|
|
|
|
return 160.0;
|
|
|
|
|
case 3:
|
|
|
|
|
return 150.0;
|
|
|
|
|
case 4: case 5: case 6: case 7: case 8:
|
|
|
|
|
case 9: case 10: case 11:
|
|
|
|
|
return 112.0;
|
|
|
|
|
case 12: case 13: case 14: case 15:
|
|
|
|
|
return 75.0;
|
|
|
|
|
case 16: case 17: case 18: case 19:
|
|
|
|
|
return 58.0;
|
|
|
|
|
case 20: case 21: case 22: case 23:
|
|
|
|
|
case 40: case 41: case 42: case 43:
|
|
|
|
|
case 44: case 45: case 46: case 47:
|
|
|
|
|
case 48:
|
|
|
|
|
return 50.0;
|
|
|
|
|
default:
|
|
|
|
|
/* 24-32, 52+ */
|
|
|
|
|
return 45.0;
|
|
|
|
|
}
|
2018-03-17 20:32:20 +01:00
|
|
|
}
|
|
|
|
|
|
2018-03-21 14:46:54 +01:00
|
|
|
|
2018-10-17 05:29:48 +02:00
|
|
|
static double
|
|
|
|
|
cdrom_get_long_seek(cdrom_t *dev)
|
2018-04-25 23:51:13 +02:00
|
|
|
{
|
|
|
|
|
switch(dev->cur_speed) {
|
|
|
|
|
case 0:
|
|
|
|
|
fatal("CD-ROM %i: 0x speed\n", dev->id);
|
|
|
|
|
return 0.0;
|
|
|
|
|
case 1:
|
|
|
|
|
return 1446.0;
|
|
|
|
|
case 2:
|
|
|
|
|
return 1000.0;
|
|
|
|
|
case 3:
|
|
|
|
|
return 900.0;
|
|
|
|
|
case 4: case 5: case 6: case 7: case 8:
|
|
|
|
|
case 9: case 10: case 11:
|
|
|
|
|
return 675.0;
|
|
|
|
|
case 12: case 13: case 14: case 15:
|
|
|
|
|
return 400.0;
|
|
|
|
|
case 16: case 17: case 18: case 19:
|
|
|
|
|
return 350.0;
|
|
|
|
|
case 20: case 21: case 22: case 23:
|
|
|
|
|
case 40: case 41: case 42: case 43:
|
|
|
|
|
case 44: case 45: case 46: case 47:
|
|
|
|
|
case 48:
|
|
|
|
|
return 300.0;
|
|
|
|
|
default:
|
|
|
|
|
/* 24-32, 52+ */
|
|
|
|
|
return 270.0;
|
|
|
|
|
}
|
2018-03-17 20:32:20 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2018-10-10 22:33:24 +02:00
|
|
|
double
|
2018-10-17 05:29:48 +02:00
|
|
|
cdrom_seek_time(cdrom_t *dev)
|
2018-03-17 20:32:20 +01:00
|
|
|
{
|
2018-04-25 23:51:13 +02:00
|
|
|
uint32_t diff = dev->seek_diff;
|
|
|
|
|
double sd = (double) (MAX_SEEK - MIN_SEEK);
|
2018-03-17 20:32:20 +01:00
|
|
|
|
2018-04-25 23:51:13 +02:00
|
|
|
if (diff < MIN_SEEK)
|
|
|
|
|
return 0.0;
|
|
|
|
|
if (diff > MAX_SEEK)
|
|
|
|
|
diff = MAX_SEEK;
|
2018-03-17 20:32:20 +01:00
|
|
|
|
2018-04-25 23:51:13 +02:00
|
|
|
diff -= MIN_SEEK;
|
2018-03-17 20:32:20 +01:00
|
|
|
|
2018-04-25 23:51:13 +02:00
|
|
|
return cdrom_get_short_seek(dev) + ((cdrom_get_long_seek(dev) * ((double) diff)) / sd);
|
2018-03-17 20:32:20 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2018-10-10 22:33:24 +02:00
|
|
|
void
|
2018-10-17 05:29:48 +02:00
|
|
|
cdrom_seek(cdrom_t *dev, uint32_t pos)
|
2018-04-25 23:51:13 +02:00
|
|
|
{
|
2018-10-10 22:33:24 +02:00
|
|
|
/* cdrom_log("CD-ROM %i: Seek %08X\n", dev->id, pos); */
|
2018-10-11 10:34:12 +02:00
|
|
|
if (!dev)
|
|
|
|
|
return;
|
|
|
|
|
|
2018-10-10 22:33:24 +02:00
|
|
|
dev->seek_pos = pos;
|
2018-10-17 05:29:48 +02:00
|
|
|
if (dev->ops && dev->ops->stop)
|
|
|
|
|
dev->ops->stop(dev);
|
2017-01-16 01:49:19 +01:00
|
|
|
}
|
|
|
|
|
|
2018-03-17 20:32:20 +01:00
|
|
|
|
2018-10-10 22:33:24 +02:00
|
|
|
int
|
2018-10-17 05:29:48 +02:00
|
|
|
cdrom_playing_completed(cdrom_t *dev)
|
2018-04-25 23:51:13 +02:00
|
|
|
{
|
2018-10-10 22:33:24 +02:00
|
|
|
dev->prev_status = dev->cd_status;
|
2018-10-17 05:29:48 +02:00
|
|
|
|
|
|
|
|
if (dev->ops && dev->ops->status)
|
|
|
|
|
dev->cd_status = dev->ops->status(dev);
|
|
|
|
|
else {
|
|
|
|
|
dev->cd_status = CD_STATUS_EMPTY;
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2018-10-10 22:33:24 +02:00
|
|
|
if (((dev->prev_status == CD_STATUS_PLAYING) || (dev->prev_status == CD_STATUS_PAUSED)) &&
|
|
|
|
|
((dev->cd_status != CD_STATUS_PLAYING) && (dev->cd_status != CD_STATUS_PAUSED)))
|
|
|
|
|
return 1;
|
2018-10-17 05:29:48 +02:00
|
|
|
|
|
|
|
|
return 0;
|
2017-01-16 01:49:19 +01:00
|
|
|
}
|
|
|
|
|
|
2018-03-17 20:32:20 +01:00
|
|
|
|
2018-10-10 22:33:24 +02:00
|
|
|
/* Peform a master init on the entire module. */
|
|
|
|
|
void
|
|
|
|
|
cdrom_global_init(void)
|
2018-04-25 23:51:13 +02:00
|
|
|
{
|
2018-10-10 22:33:24 +02:00
|
|
|
/* Clear the global data. */
|
2018-10-17 05:29:48 +02:00
|
|
|
memset(cdrom, 0x00, sizeof(cdrom));
|
2017-01-16 01:49:19 +01:00
|
|
|
}
|
|
|
|
|
|
2018-03-17 20:32:20 +01:00
|
|
|
|
2018-04-25 23:51:13 +02:00
|
|
|
static void
|
2018-10-17 05:29:48 +02:00
|
|
|
cdrom_drive_reset(cdrom_t *dev)
|
2018-04-25 23:51:13 +02:00
|
|
|
{
|
2018-10-17 05:29:48 +02:00
|
|
|
dev->p = NULL;
|
|
|
|
|
dev->insert = NULL;
|
|
|
|
|
dev->close = NULL;
|
|
|
|
|
dev->get_volume = NULL;
|
|
|
|
|
dev->get_channel = NULL;
|
2017-01-16 01:49:19 +01:00
|
|
|
}
|
|
|
|
|
|
2018-03-17 20:32:20 +01:00
|
|
|
|
2018-10-10 22:33:24 +02:00
|
|
|
void
|
|
|
|
|
cdrom_hard_reset(void)
|
2018-04-25 23:51:13 +02:00
|
|
|
{
|
2018-10-17 05:29:48 +02:00
|
|
|
cdrom_t *dev;
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < CDROM_NUM; i++) {
|
|
|
|
|
dev = &cdrom[i];
|
|
|
|
|
if (dev->bus_type) {
|
|
|
|
|
cdrom_log("CDROM %i: hard_reset\n", i);
|
|
|
|
|
|
|
|
|
|
dev->id = i;
|
2018-03-17 20:32:20 +01:00
|
|
|
|
2018-10-17 05:29:48 +02:00
|
|
|
cdrom_drive_reset(dev);
|
2017-01-16 01:49:19 +01:00
|
|
|
|
2018-10-17 05:29:48 +02:00
|
|
|
switch(dev->bus_type) {
|
|
|
|
|
case CDROM_BUS_ATAPI:
|
|
|
|
|
case CDROM_BUS_SCSI:
|
|
|
|
|
scsi_cdrom_drive_reset(i);
|
|
|
|
|
break;
|
2018-04-25 23:51:13 +02:00
|
|
|
|
2018-10-17 05:29:48 +02:00
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
2018-04-25 23:51:13 +02:00
|
|
|
|
|
|
|
|
|
2018-10-17 05:29:48 +02:00
|
|
|
if (dev->host_drive == 200) {
|
|
|
|
|
cdrom_image_open(dev, dev->image_path);
|
|
|
|
|
cdrom_image_reset(dev);
|
|
|
|
|
}
|
2017-01-16 01:49:19 +01:00
|
|
|
}
|
2018-04-25 23:51:13 +02:00
|
|
|
}
|
2017-10-24 04:15:05 +02:00
|
|
|
|
2018-10-10 22:33:24 +02:00
|
|
|
sound_cd_thread_reset();
|
2017-01-16 01:49:19 +01:00
|
|
|
}
|
|
|
|
|
|
2018-04-25 23:51:13 +02:00
|
|
|
|
2018-10-10 22:33:24 +02:00
|
|
|
void
|
2018-10-17 05:29:48 +02:00
|
|
|
cdrom_close(void)
|
2018-01-06 22:47:41 +01:00
|
|
|
{
|
2018-10-17 05:29:48 +02:00
|
|
|
cdrom_t *dev;
|
|
|
|
|
int i;
|
2018-01-06 22:47:41 +01:00
|
|
|
|
2018-10-17 05:29:48 +02:00
|
|
|
for (i = 0; i < CDROM_NUM; i++) {
|
|
|
|
|
dev = &cdrom[i];
|
|
|
|
|
|
|
|
|
|
if (dev->ops && dev->ops->exit)
|
|
|
|
|
dev->ops->exit(dev);
|
|
|
|
|
|
|
|
|
|
dev->ops = NULL;
|
|
|
|
|
|
|
|
|
|
if (dev->close)
|
|
|
|
|
dev->close(dev->p);
|
|
|
|
|
|
|
|
|
|
cdrom_drive_reset(dev);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Signal disc change to the emulated machine. */
|
|
|
|
|
void
|
|
|
|
|
cdrom_insert(uint8_t id)
|
|
|
|
|
{
|
|
|
|
|
cdrom_t *dev = &cdrom[id];
|
|
|
|
|
|
|
|
|
|
if (dev->bus_type) {
|
|
|
|
|
if (dev->insert)
|
|
|
|
|
dev->insert(dev->p);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* The mechanics of ejecting a CD-ROM from a drive. */
|
|
|
|
|
void
|
|
|
|
|
cdrom_eject(uint8_t id)
|
|
|
|
|
{
|
|
|
|
|
cdrom_t *dev = &cdrom[id];
|
|
|
|
|
|
|
|
|
|
/* This entire block should be in cdrom.c/cdrom_eject(dev*) ... */
|
|
|
|
|
if (dev->host_drive == 0) {
|
|
|
|
|
/* Switch from empty to empty. Do nothing. */
|
2018-10-11 10:34:12 +02:00
|
|
|
return;
|
2018-10-17 05:29:48 +02:00
|
|
|
}
|
2018-10-11 10:34:12 +02:00
|
|
|
|
2018-10-17 05:29:48 +02:00
|
|
|
if (dev->prev_image_path) {
|
|
|
|
|
free(dev->prev_image_path);
|
|
|
|
|
dev->prev_image_path = NULL;
|
2018-10-10 22:33:24 +02:00
|
|
|
}
|
2018-10-11 10:34:12 +02:00
|
|
|
|
2018-10-17 05:29:48 +02:00
|
|
|
if (dev->host_drive == 200) {
|
|
|
|
|
dev->prev_image_path = (wchar_t *) malloc(1024);
|
|
|
|
|
wcscpy(dev->prev_image_path, dev->image_path);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
dev->prev_host_drive = dev->host_drive;
|
|
|
|
|
dev->host_drive = 0;
|
|
|
|
|
|
|
|
|
|
dev->ops->exit(dev);
|
|
|
|
|
dev->ops = NULL;
|
|
|
|
|
memset(dev->image_path, 0, sizeof(dev->image_path));
|
|
|
|
|
|
|
|
|
|
cdrom_insert(id);
|
|
|
|
|
|
|
|
|
|
plat_cdrom_ui_update(id, 0);
|
|
|
|
|
|
|
|
|
|
config_save();
|
2018-01-06 22:47:41 +01:00
|
|
|
}
|
|
|
|
|
|
2017-01-16 01:49:19 +01:00
|
|
|
|
2018-10-17 05:29:48 +02:00
|
|
|
/* The mechanics of re-loading a CD-ROM drive. */
|
2018-10-10 22:33:24 +02:00
|
|
|
void
|
2018-10-17 05:29:48 +02:00
|
|
|
cdrom_reload(uint8_t id)
|
2017-01-16 01:49:19 +01:00
|
|
|
{
|
2018-10-17 05:29:48 +02:00
|
|
|
cdrom_t *dev = &cdrom[id];
|
2017-01-16 01:49:19 +01:00
|
|
|
|
2018-10-17 05:29:48 +02:00
|
|
|
if ((dev->host_drive == dev->prev_host_drive) ||
|
|
|
|
|
(dev->prev_host_drive == 0) || (dev->host_drive != 0)) {
|
|
|
|
|
/* Switch from empty to empty. Do nothing. */
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (dev->ops && dev->ops->exit)
|
|
|
|
|
dev->ops->exit(dev);
|
|
|
|
|
dev->ops = NULL;
|
|
|
|
|
memset(dev->image_path, 0, sizeof(dev->image_path));
|
2017-01-18 21:51:03 +01:00
|
|
|
|
2018-10-17 05:29:48 +02:00
|
|
|
if (dev->prev_host_drive == 200) {
|
|
|
|
|
/* Reload a previous image. */
|
|
|
|
|
wcscpy(dev->image_path, dev->prev_image_path);
|
|
|
|
|
free(dev->prev_image_path);
|
|
|
|
|
dev->prev_image_path = NULL;
|
|
|
|
|
cdrom_image_open(dev, dev->image_path);
|
2017-01-16 01:49:19 +01:00
|
|
|
|
2018-10-17 05:29:48 +02:00
|
|
|
cdrom_insert(id);
|
|
|
|
|
|
|
|
|
|
if (wcslen(dev->image_path) == 0)
|
|
|
|
|
dev->host_drive = 0;
|
|
|
|
|
else
|
|
|
|
|
dev->host_drive = 200;
|
2018-04-25 23:51:13 +02:00
|
|
|
}
|
2018-10-17 05:29:48 +02:00
|
|
|
|
|
|
|
|
plat_cdrom_ui_update(id, 1);
|
|
|
|
|
|
|
|
|
|
config_save();
|
2018-04-25 23:51:13 +02:00
|
|
|
}
|