Merge pull request #5359 from 86Box/cdrom_changes

Assorted CD-ROM fixes
This commit is contained in:
Miran Grča
2025-03-17 00:45:07 +01:00
committed by GitHub
27 changed files with 1512 additions and 902 deletions

View File

@@ -23,8 +23,6 @@ endif()
add_executable(86Box
86box.c
config.c
log.c
random.c
timer.c
io.c
acpi.c
@@ -41,15 +39,11 @@ add_executable(86Box
pci.c
mca.c
usb.c
fifo.c
fifo8.c
device.c
nvr.c
nvr_at.c
nvr_ps2.c
machine_status.c
ini.c
cJSON.c
)
if(CMAKE_SYSTEM_NAME MATCHES "Linux")
@@ -106,7 +100,7 @@ if(INSTRUMENT)
endif()
target_link_libraries(86Box cpu chipset mch dev mem fdd game cdrom zip mo hdd
net print scsi sio snd vid voodoo plat ui)
net print scsi sio snd utils vid voodoo plat ui)
if(HAIKU)
target_link_libraries(86Box be)
@@ -256,7 +250,9 @@ add_subdirectory(printer)
add_subdirectory(sio)
add_subdirectory(scsi)
add_subdirectory(sound)
add_subdirectory(utils)
add_subdirectory(video)
if (APPLE)
add_subdirectory(mac)
endif()

File diff suppressed because it is too large Load Diff

View File

@@ -409,7 +409,7 @@ image_get_track_and_index(const cd_image_t *img, const uint32_t sector,
for (int i = 0; i < img->tracks_num; i++) {
track_t *ct = &(img->tracks[i]);
for (int j = 0; j < 3; j++) {
if ((ct->point >= 1) && (ct->point <= 99)) for (int j = 0; j < 3; j++) {
track_index_t *ci = &(ct->idx[j]);
if ((ci->type >= INDEX_ZERO) && (ci->length != 0ULL) &&
((sector + 150) >= ci->start) && ((sector + 150) <= (ci->start + ci->length - 1))) {

View File

@@ -1028,9 +1028,8 @@ ide_atapi_command_bus(ide_t *ide)
static void
ide_atapi_callback(ide_t *ide)
{
int out;
int ret = 0;
ide_bm_t *bm = ide_boards[ide->board]->bm;
static int ret = 0;
ide_bm_t *bm = ide_boards[ide->board]->bm;
#ifdef ENABLE_IDE_LOG
char *phases[7] = { "Idle", "Command", "Data in", "Data out", "Data in DMA", "Data out DMA",
"Complete" };
@@ -1056,14 +1055,17 @@ ide_atapi_callback(ide_t *ide)
switch (ide->sc->packet_status) {
default:
ret = 0;
break;
case PHASE_IDLE:
ret = 0;
ide->tf->pos = 0;
ide->tf->phase = 1;
ide->tf->atastat = READY_STAT | DRQ_STAT | (ide->tf->atastat & ERR_STAT);
break;
case PHASE_COMMAND:
ret = 1;
ide->tf->atastat = BUSY_STAT | (ide->tf->atastat & ERR_STAT);
if (ide->packet_command) {
ide->packet_command(ide->sc, ide->sc->atapi_cdb);
@@ -1073,6 +1075,7 @@ ide_atapi_callback(ide_t *ide)
break;
case PHASE_COMPLETE:
case PHASE_ERROR:
ret = 0;
ide->tf->atastat = READY_STAT;
if (ide->sc->packet_status == PHASE_ERROR)
ide->tf->atastat |= ERR_STAT;
@@ -1082,19 +1085,34 @@ ide_atapi_callback(ide_t *ide)
break;
case PHASE_DATA_IN:
case PHASE_DATA_OUT:
ret = 0;
ide->tf->atastat = READY_STAT | DRQ_STAT | (ide->tf->atastat & ERR_STAT);
ide->tf->phase = !(ide->sc->packet_status & 0x01) << 1;
ide_irq_raise(ide);
break;
case PHASE_DATA_IN_DMA:
case PHASE_DATA_OUT_DMA:
out = (ide->sc->packet_status & 0x01);
if (!IDE_ATAPI_IS_EARLY && !ide_boards[ide->board]->force_ata3 &&
(bm != NULL) && bm->dma) {
ret = bm->dma(ide->sc->temp_buffer, ide->sc->packet_len, out, bm->priv);
}
/* Else, DMA command without a bus master, ret = 0 (default). */
if (ide->sc->block_len == 0) {
ret = bm->dma(ide->sc->temp_buffer, ide->sc->packet_len, 0, bm->priv);
/* Underrun. */
if (ret == 1)
ret = 3;
} else {
ret = bm->dma(ide->sc->temp_buffer + ide->sc->buffer_pos -
ide->sc->block_len, ide->sc->block_len,
0, bm->priv);
if (ret == 1) {
if (ide->sc->sector_len == 0)
ret = 3;
else if (ide->read != NULL)
ide->read(ide->sc);
}
}
} else
ret = 0;
switch (ret) {
default:
@@ -1103,18 +1121,73 @@ ide_atapi_callback(ide_t *ide)
if (ide->bus_master_error)
ide->bus_master_error(ide->sc);
break;
case 1:
if (out && ide->phase_data_out)
(void) ide->phase_data_out(ide->sc);
else if (!out && ide->command_stop)
ide->command_stop(ide->sc);
case 2:
ide_atapi_command_bus(ide);
break;
case 3:
/* Reached EOT - terminate the command as there's nothing
more to transfer. */
ide->sc->packet_status = PHASE_COMPLETE;
ide->sc->callback = 0.0;
if ((ide->sc->packet_status == PHASE_COMPLETE) && (ide->sc->callback == 0.0))
if (ide->command_stop != NULL)
ide->command_stop(ide->sc);
fallthrough;
case 1:
if ((ide->sc->packet_status == PHASE_COMPLETE) &&
(ide->sc->callback == 0.0))
ide_atapi_callback(ide);
break;
}
break;
case PHASE_DATA_OUT_DMA:
if (!IDE_ATAPI_IS_EARLY && !ide_boards[ide->board]->force_ata3 &&
(bm != NULL) && bm->dma) {
if (ide->sc->block_len == 0) {
ret = bm->dma(ide->sc->temp_buffer, ide->sc->packet_len, 1, bm->priv);
/* Underrun. */
if (ret == 1)
ret = 3;
} else {
ret = bm->dma(ide->sc->temp_buffer + ide->sc->buffer_pos,
ide->sc->block_len, 1, bm->priv);
if (ret & 1) {
if (ide->write != NULL)
ide->write(ide->sc);
if ((ret == 1) && (ide->sc->sector_len == 0))
ret = 3;
}
}
} else
ret = 0;
switch (ret) {
default:
break;
case 0:
if (ide->bus_master_error)
ide->bus_master_error(ide->sc);
break;
case 2:
ide_atapi_command_bus(ide);
break;
case 3:
/* Reached EOT - terminate the command as there's nothing
more to transfer. */
ide->sc->packet_status = PHASE_COMPLETE;
ide->sc->callback = 0.0;
if (ide->phase_data_out != NULL)
(void) ide->phase_data_out(ide->sc);
fallthrough;
case 1:
if ((ide->sc->packet_status == PHASE_COMPLETE) &&
(ide->sc->callback == 0.0))
ide_atapi_callback(ide);
break;
}
break;
}
@@ -1128,28 +1201,36 @@ ide_atapi_pio_request(ide_t *ide, uint8_t out)
ide_irq_lower(ide);
ide->tf->atastat = BSY_STAT;
ide->tf->atastat = BSY_STAT;
if (ide->tf->pos >= dev->packet_len) {
ide_log("%i bytes %s, command done\n", ide->tf->pos, out ? "written" : "read");
ide->tf->pos = dev->request_pos = 0;
if (out && ide->phase_data_out)
ide->phase_data_out(dev);
else if (!out && ide->command_stop)
ide->command_stop(dev);
if ((ide->sc->packet_status == PHASE_COMPLETE) && (ide->sc->callback == 0.0))
ide_atapi_callback(ide);
if (dev->block_len == 0) {
if (out && (ide->phase_data_out != NULL))
ide->phase_data_out(dev);
else if (!out && (ide->command_stop != NULL))
ide->command_stop(dev);
if ((ide->sc->packet_status == PHASE_COMPLETE) && (ide->sc->callback == 0.0))
ide_atapi_callback(ide);
}
} else {
ide_log("%i bytes %s, %i bytes are still left\n", ide->tf->pos,
out ? "written" : "read", dev->packet_len - ide->tf->pos);
/* If less than (packet length) bytes are remaining, update packet length
accordingly. */
/*
If less than (packet length) bytes are remaining, update packet length
accordingly.
*/
if ((dev->packet_len - ide->tf->pos) < (dev->max_transfer_len)) {
dev->max_transfer_len = dev->packet_len - ide->tf->pos;
/* Also update the request length so the host knows how many bytes to transfer. */
/*
Also update the request length so the host knows how many bytes to
transfer.
*/
ide->tf->request_length = dev->max_transfer_len;
}
ide_log("CD-ROM %i: Packet length %i, request length %i\n", dev->id, dev->packet_len,
@@ -1157,12 +1238,40 @@ ide_atapi_pio_request(ide_t *ide, uint8_t out)
dev->packet_status = PHASE_DATA_IN | out;
ide->tf->atastat = BSY_STAT;
ide->tf->phase = 1;
ide_atapi_callback(ide);
ide_set_callback(ide, 0.0);
if (dev->block_len == 0) {
ide_atapi_callback(ide);
ide_set_callback(ide, 0.0);
}
dev->request_pos = 0;
dev->request_pos = 0;
}
if (dev->block_len != 0) {
if (out) {
if (ide->write != NULL)
ide->write(dev);
if (dev->sector_len == 0) {
ide->sc->packet_status = PHASE_COMPLETE;
ide->sc->callback = 0.0;
if (ide->phase_data_out != NULL)
(void) ide->phase_data_out(dev);
ide_atapi_callback(ide);
}
} else {
if (dev->sector_len == 0) {
if (ide->command_stop != NULL)
ide->command_stop(dev);
ide->sc->packet_status = PHASE_COMPLETE;
ide->sc->callback = 0.0;
ide_atapi_callback(ide);
} else if (ide->read != NULL)
ide->read(dev);
}
}
}
@@ -1179,16 +1288,19 @@ ide_atapi_packet_read(ide_t *ide)
bufferw = (uint16_t *) dev->temp_buffer;
/* Make sure we return a 0 and don't attempt to read from the buffer if
/*
Make sure we return a 0 and don't attempt to read from the buffer if
we're transferring bytes beyond it, which can happen when issuing media
access commands with an allocated length below minimum request length
(which is 1 sector = 2048 bytes). */
(which is 1 sector = 2048 bytes).
*/
ret = (ide->tf->pos < dev->packet_len) ? bufferw[ide->tf->pos >> 1] : 0;
ide->tf->pos += 2;
dev->request_pos += 2;
if ((dev->request_pos >= dev->max_transfer_len) || (ide->tf->pos >= dev->packet_len)) {
if ((dev->request_pos >= dev->max_transfer_len) ||
(ide->tf->pos >= dev->packet_len)) {
/* Time for a DRQ. */
ide_atapi_pio_request(ide, 0);
}
@@ -1221,7 +1333,8 @@ ide_atapi_packet_write(ide_t *ide, const uint16_t val)
dev->request_pos += 2;
if (dev->packet_status == PHASE_DATA_OUT) {
if ((dev->request_pos >= dev->max_transfer_len) || (ide->tf->pos >= dev->packet_len)) {
if ((dev->request_pos >= dev->max_transfer_len) ||
(ide->tf->pos >= dev->packet_len)) {
/* Time for a DRQ. */
ide_atapi_pio_request(ide, 1);
}
@@ -1287,7 +1400,7 @@ ide_writew(uint16_t addr, uint16_t val, void *priv)
ide = ide_drives[ch];
#if defined(ENABLE_IDE_LOG) && (ENABLE_IDE_LOG == 2)
ide_log("ide_writew(%04X, %04X, %08X)\n", addr, val, priv);
ide_log("[%04X:%08X] ide_writew(%04X, %04X, %08X)\n", CS, cpu_state.pc, addr, val, priv);
#endif
addr &= 0x7;
@@ -1321,7 +1434,7 @@ ide_writel(uint16_t addr, uint32_t val, void *priv)
ide = ide_drives[ch];
#if defined(ENABLE_IDE_LOG) && (ENABLE_IDE_LOG == 2)
ide_log("ide_writel(%04X, %08X, %08X)\n", addr, val, priv);
ide_log("[%04X:%08X] ide_writel(%04X, %08X, %08X)\n", CS, cpu_state.pc, addr, val, priv);
#endif
addr &= 0x7;
@@ -1371,9 +1484,9 @@ ide_write_devctl(UNUSED(uint16_t addr), uint8_t val, void *priv)
ide = ide_drives[ch];
ide_other = ide_drives[ch ^ 1];
ide_log("ide_write_devctl(%04X, %02X, %08X)\n", addr, val, priv);
ide_log("[%04X:%08X] ide_write_devctl(%04X, %02X, %08X)\n", CS, cpu_state.pc, addr, val, priv);
if ((ide->type == IDE_NONE) && (ide_other->type == IDE_NONE))
if ((addr & 0x0001) || ((ide->type == IDE_NONE) && (ide_other->type == IDE_NONE)))
return;
dev->diag = 0;
@@ -1481,7 +1594,7 @@ ide_writeb(uint16_t addr, uint8_t val, void *priv)
ide = ide_drives[ch];
ide_other = ide_drives[ch ^ 1];
ide_log("ide_writeb(%04X, %02X, %08X)\n", addr, val, priv);
ide_log("[%04X:%08X] ide_writeb(%04X, %02X, %08X)\n", CS, cpu_state.pc, addr, val, priv);
addr &= 0x7;
@@ -1831,7 +1944,7 @@ ide_read_data(ide_t *ide)
const uint16_t *idebufferw = ide->buffer;
uint16_t ret = 0x0000;
#if defined(ENABLE_IDE_LOG) && (ENABLE_IDE_LOG == 2)
#if defined(ENABLE_IDE_LOG) && (ENABLE_IDE_LOG == 3)
ide_log("ide_read_data(): ch = %i, board = %i, type = %i\n", ide->channel,
ide->board, ide->type);
#endif
@@ -2010,7 +2123,7 @@ ide_readb(uint16_t addr, void *priv)
break;
}
ide_log("ide_readb(%04X, %08X) = %02X\n", addr, priv, ret);
ide_log("[%04X:%08X] ide_readb(%04X, %08X) = %02X\n", CS, cpu_state.pc, addr, priv, ret);
return ret;
}
@@ -2022,12 +2135,14 @@ ide_read_alt_status(UNUSED(const uint16_t addr), void *priv)
const int ch = dev->cur_dev;
ide_t * ide = ide_drives[ch];
uint8_t ret = 0xff;
/* Per the Seagate ATA-3 specification:
Reading the alternate status does *NOT* clear the IRQ. */
const uint8_t ret = ide_status(ide, ide_drives[ch ^ 1], ch);
if (!(addr & 0x0001))
ret = ide_status(ide, ide_drives[ch ^ 1], ch);
ide_log("ide_read_alt_status(%04X, %08X) = %02X\n", addr, priv, ret);
ide_log("[%04X:%08X] ide_read_alt_status(%04X, %08X) = %02X\n", CS, cpu_state.pc, addr, priv, ret);
return ret;
}
@@ -2053,7 +2168,7 @@ ide_readw(uint16_t addr, void *priv)
}
#if defined(ENABLE_IDE_LOG) && (ENABLE_IDE_LOG == 2)
ide_log("ide_readw(%04X, %08X) = %04X\n", addr, priv, ret);
ide_log("[%04X:%08X] ide_readw(%04X, %08X) = %04X\n", CS, cpu_state.pc, addr, priv, ret);
#endif
return ret;
}
@@ -2084,7 +2199,7 @@ ide_readl(uint16_t addr, void *priv)
}
#if defined(ENABLE_IDE_LOG) && (ENABLE_IDE_LOG == 2)
ide_log("ide_readl(%04X, %08X) = %04X\n", addr, priv, ret);
ide_log("[%04X:%08X] ide_readl(%04X, %08X) = %04X\n", CS, cpu_state.pc, addr, priv, ret);
#endif
return ret;
}
@@ -2270,7 +2385,7 @@ ide_callback(void *priv)
ide->tf->atastat = DRQ_STAT | DRDY_STAT | DSC_STAT;
ide_set_callback(ide, 6.0 * IDE_TIME);
return;
} else if (ret == 1) {
} else if (ret & 1) {
/* DMA successful */
ide_log("IDE %i: DMA read successful\n", ide->channel);
@@ -2379,7 +2494,7 @@ ide_callback(void *priv)
ide->tf->atastat = DRQ_STAT | DRDY_STAT | DSC_STAT;
ide_set_callback(ide, 6.0 * IDE_TIME);
return;
} else if (ret == 1) {
} else if (ret & 1) {
/* DMA successful */
ret = hdd_image_write(ide->hdd_num, ide_get_sector(ide),
ide->sector_pos, ide->sector_buffer);
@@ -2637,7 +2752,7 @@ ide_handlers(uint8_t board, int set)
}
if (ide_boards[board]->base[1]) {
io_handler(set, ide_boards[board]->base[1], 1,
io_handler(set, ide_boards[board]->base[1], 2,
ide_read_alt_status, NULL, NULL,
ide_write_devctl, NULL, NULL,
ide_boards[board]);

View File

@@ -375,7 +375,7 @@ sff_bus_master_dma(uint8_t *data, int transfer_length, int out, void *priv)
} else if (dev->eot) {
sff_log("Regular EOT\n");
dev->status &= ~3;
return 1; /* We have regularly reached EOT - clear status and break. */
return 3; /* We have regularly reached EOT - clear status and break. */
} else {
/* We have more to transfer and there are blocks left, get next block. */
sff_bus_master_next_addr(dev);

View File

@@ -28,6 +28,7 @@
#define HAVE_STDARG_H
#include <86box/86box.h>
#include <86box/timer.h>
#include <86box/crc.h>
#include <86box/dma.h>
#include <86box/nvr.h>
#include <86box/random.h>
@@ -223,6 +224,7 @@ typedef struct d86f_t {
uint8_t *filebuf;
uint8_t *outbuf;
sector_t *last_side_sector[2];
uint16_t crc_table[256];
} d86f_t;
static const uint8_t encoded_fm[64] = {
@@ -247,7 +249,6 @@ static const uint8_t encoded_mfm[64] = {
};
static d86f_t *d86f[FDD_NUM];
static uint16_t CRCTable[256];
static fdc_t *d86f_fdc;
uint64_t poly = 0x42F0E1EBA9EA3693LL; /* ECMA normal */
@@ -276,28 +277,6 @@ d86f_log(const char *fmt, ...)
# define d86f_log(fmt, ...)
#endif
static void
setup_crc(uint16_t poly)
{
int c = 256;
int bc;
uint16_t temp;
while (c--) {
temp = c << 8;
bc = 8;
while (bc--) {
if (temp & 0x8000)
temp = (temp << 1) ^ poly;
else
temp <<= 1;
CRCTable[c] = temp;
}
}
}
void
d86f_destroy_linked_lists(int drive, int side)
{
@@ -1237,16 +1216,10 @@ decodefm(UNUSED(int drive), uint16_t dat)
return temp;
}
void
fdd_calccrc(uint8_t byte, crc_t *crc_var)
{
crc_var->word = (crc_var->word << 8) ^ CRCTable[(crc_var->word >> 8) ^ byte];
}
static void
d86f_calccrc(d86f_t *dev, uint8_t byte)
{
fdd_calccrc(byte, &(dev->calc_crc));
crc16_calc(dev->crc_table, byte, &(dev->calc_crc));
}
int
@@ -1274,7 +1247,9 @@ d86f_word_is_aligned(int drive, int side, uint32_t base_pos)
/* State 1: Find sector ID */
void
d86f_find_address_mark_fm(int drive, int side, find_t *find, uint16_t req_am, uint16_t other_am, uint16_t wrong_am, uint16_t ignore_other_am)
d86f_find_address_mark_fm(int drive, int side, find_t *find, uint16_t req_am,
uint16_t other_am, uint16_t wrong_am,
uint16_t ignore_other_am)
{
d86f_t *dev = d86f[drive];
@@ -1282,7 +1257,8 @@ d86f_find_address_mark_fm(int drive, int side, find_t *find, uint16_t req_am, ui
if (dev->last_word[side] == req_am) {
dev->calc_crc.word = 0xFFFF;
fdd_calccrc(decodefm(drive, dev->last_word[side]), &(dev->calc_crc));
crc16_calc(dev->crc_table, decodefm(drive, dev->last_word[side]),
&(dev->calc_crc));
find->sync_marks = find->bits_obtained =
find->bytes_obtained = 0;
find->sync_pos = 0xFFFFFFFF;
@@ -1302,7 +1278,8 @@ d86f_find_address_mark_fm(int drive, int side, find_t *find, uint16_t req_am, ui
if ((ignore_other_am & 2) && (dev->last_word[side] == other_am)) {
dev->calc_crc.word = 0xFFFF;
fdd_calccrc(decodefm(drive, dev->last_word[side]), &(dev->calc_crc));
crc16_calc(dev->crc_table, decodefm(drive, dev->last_word[side]),
&(dev->calc_crc));
find->sync_marks = find->bits_obtained = find->bytes_obtained = 0;
find->sync_pos = 0xFFFFFFFF;
if (ignore_other_am & 1) {
@@ -1378,7 +1355,8 @@ d86f_find_address_mark_mfm(int drive, int side, find_t *find, uint16_t req_am, u
if ((dev->last_word[side] == req_am) && (find->sync_marks >= 3)) {
if (d86f_word_is_aligned(drive, side, find->sync_pos)) {
dev->calc_crc.word = 0xCDB4;
fdd_calccrc(decodefm(drive, dev->last_word[side]), &(dev->calc_crc));
crc16_calc(dev->crc_table, decodefm(drive, dev->last_word[side]),
&(dev->calc_crc));
find->sync_marks = find->bits_obtained = find->bytes_obtained = 0;
find->sync_pos = 0xFFFFFFFF;
dev->preceding_bit[side] = dev->last_word[side] & 1;
@@ -1390,7 +1368,8 @@ d86f_find_address_mark_mfm(int drive, int side, find_t *find, uint16_t req_am, u
if ((ignore_other_am & 2) && (dev->last_word[side] == other_am) && (find->sync_marks >= 3)) {
if (d86f_word_is_aligned(drive, side, find->sync_pos)) {
dev->calc_crc.word = 0xCDB4;
fdd_calccrc(decodefm(drive, dev->last_word[side]), &(dev->calc_crc));
crc16_calc(dev->crc_table, decodefm(drive, dev->last_word[side]),
&(dev->calc_crc));
find->sync_marks = find->bits_obtained = find->bytes_obtained = 0;
find->sync_pos = 0xFFFFFFFF;
if (ignore_other_am & 1) {
@@ -1464,8 +1443,11 @@ d86f_read_sector_id(int drive, int side, int match)
if (dev->id_find.bytes_obtained < 4) {
dev->last_sector.byte_array[dev->id_find.bytes_obtained] =
decodefm(drive, dev->last_word[side]);
fdd_calccrc(dev->last_sector.byte_array[dev->id_find.bytes_obtained], &(dev->calc_crc));
} else if ((dev->id_find.bytes_obtained >= 4) && (dev->id_find.bytes_obtained < 6)) {
crc16_calc(dev->crc_table,
dev->last_sector.byte_array[dev->id_find.bytes_obtained],
&(dev->calc_crc));
} else if ((dev->id_find.bytes_obtained >= 4) &&
(dev->id_find.bytes_obtained < 6)) {
dev->track_crc.bytes[(dev->id_find.bytes_obtained & 1) ^ 1] =
decodefm(drive, dev->last_word[side]);
}
@@ -1643,7 +1625,7 @@ d86f_read_sector_data(int drive, int side)
}
}
}
fdd_calccrc(data, &(dev->calc_crc));
crc16_calc(dev->crc_table, data, &(dev->calc_crc));
} else if (dev->data_find.bytes_obtained < crc_pos)
dev->track_crc.bytes[(dev->data_find.bytes_obtained - sector_len) ^ 1] =
decodefm(drive, dev->last_word[side]);
@@ -1730,11 +1712,12 @@ d86f_write_sector_data(int drive, int side, int mfm, uint16_t am)
if (dev->data_find.bytes_obtained < sector_len) {
/* This is a data byte, so CRC it. */
if (!dev->data_find.bytes_obtained) {
fdd_calccrc(decodefm(drive, am), &(dev->calc_crc));
} else {
fdd_calccrc(dev->current_byte[side], &(dev->calc_crc));
}
if (!dev->data_find.bytes_obtained)
crc16_calc(dev->crc_table, decodefm(drive, am),
&(dev->calc_crc));
else
crc16_calc(dev->crc_table, dev->current_byte[side],
&(dev->calc_crc));
}
}
} else {
@@ -3861,8 +3844,6 @@ d86f_load(int drive, char *fn)
void
d86f_init(void)
{
setup_crc(0x1021);
for (uint8_t i = 0; i < FDD_NUM; i++)
d86f[i] = NULL;
}
@@ -3926,6 +3907,8 @@ d86f_setup(int drive)
dev->last_side_sector[0] = NULL;
dev->last_side_sector[1] = NULL;
crc16_setup(dev->crc_table, 0x1021);
/* Set the drive as active. */
d86f[drive] = dev;
}

View File

@@ -28,8 +28,9 @@
#define CD_STATUS_PLAYING 5
#define CD_STATUS_STOPPED 6
#define CD_STATUS_PLAYING_COMPLETED 7
#define CD_STATUS_HAS_AUDIO 4
#define CD_STATUS_MASK 7
#define CD_STATUS_HOLD 8
#define CD_STATUS_HAS_AUDIO 0xc
#define CD_STATUS_MASK 0xf
/* Medium changed flag. */
#define CD_STATUS_TRANSITION 0x40
@@ -50,8 +51,6 @@
#define CD_IMAGE_HISTORY 10
#define BUF_SIZE 32768
#define CDROM_IMAGE 200
/* This is so that if/when this is changed to something else,
@@ -63,6 +62,8 @@
#define RAW_SECTOR_SIZE 2352
#define COOKED_SECTOR_SIZE 2048
#define CD_BUF_SIZE (16 * RAW_SECTOR_SIZE)
#define DATA_TRACK 0x14
#define AUDIO_TRACK 0x10
@@ -105,9 +106,9 @@ enum {
#define CDV EMU_VERSION_EX
static const struct cdrom_drive_types_s {
const char vendor[9];
const char model[17];
const char revision[5];
const char * vendor;
const char * model;
const char * revision;
const char * internal_name;
const int bus_type;
/* SCSI standard for SCSI (or both) devices, early for IDE. */
@@ -298,9 +299,7 @@ typedef struct cdrom {
void * priv;
char image_path[1024];
char prev_image_path[1024];
char * image_history[CD_IMAGE_HISTORY];
char prev_image_path[1280];
uint32_t sound_on;
uint32_t cdrom_capacity;
@@ -310,18 +309,21 @@ typedef struct cdrom {
uint32_t type;
uint32_t sector_size;
int cd_buflen;
int audio_op;
int audio_muted_soft;
int sony_msf;
int real_speed;
int is_early;
int is_nec;
uint32_t inv_field;
int32_t cached_sector;
int32_t cd_buflen;
int32_t sony_msf;
int32_t real_speed;
int32_t is_early;
int32_t is_nec;
int32_t is_bcd;
int32_t cdrom_sector_size;
const cdrom_ops_t *ops;
char * image_history[CD_IMAGE_HISTORY];
void * local;
void * log;
@@ -330,24 +332,29 @@ typedef struct cdrom {
uint32_t (*get_volume)(void *p, int channel);
uint32_t (*get_channel)(void *p, int channel);
int16_t cd_buffer[BUF_SIZE];
int16_t cd_buffer[CD_BUF_SIZE];
uint8_t subch_buffer[96];
int cdrom_sector_size;
/* Needs some extra breathing space in case of overflows. */
uint8_t raw_buffer[2][4096];
uint8_t extra_buffer[296];
int32_t is_chinon;
int32_t is_pioneer;
int32_t is_plextor;
int32_t is_sony;
int32_t is_toshiba;
int32_t c2_first;
int32_t cur_buf;
/* Only used on Windows hosts for disc change notifications. */
uint8_t host_letter;
/* Needs some extra breathing space in case of overflows. */
uint8_t raw_buffer[4096];
uint8_t extra_buffer[296];
} cdrom_t;
extern cdrom_t cdrom[CDROM_NUM];
/* The addresses sent from the guest are absolute, ie. a LBA of 0 corresponds to a MSF of 00:00:00. Otherwise, the counter displayed by the guest is wrong:
there is a seeming 2 seconds in which audio plays but counter does not move, while a data track before audio jumps to 2 seconds before the actual start
of the audio while audio still plays. With an absolute conversion, the counter is fine. */
#define MSFtoLBA(m, s, f) ((((m * 60) + s) * 75) + f)
static __inline int
@@ -368,8 +375,6 @@ extern char *cdrom_get_revision(const int type);
extern int cdrom_get_scsi_std(const int type);
extern int cdrom_is_early(const int type);
extern int cdrom_is_generic(const int type);
extern int cdrom_has_date(const int type);
extern int cdrom_is_sony(const int type);
extern int cdrom_is_caddy(const int type);
extern int cdrom_get_speed(const int type);
extern int cdrom_get_inquiry_len(const int type);
@@ -386,6 +391,7 @@ extern void cdrom_set_type(const int model, const int type);
extern int cdrom_get_type(const int model);
extern int cdrom_lba_to_msf_accurate(const int lba);
extern void cdrom_interleave_subch(uint8_t *d, const uint8_t *s);
extern double cdrom_seek_time(const cdrom_t *dev);
extern void cdrom_stop(cdrom_t *dev);
extern void cdrom_seek(cdrom_t *dev, const uint32_t pos, const uint8_t vendor_type);
@@ -398,7 +404,7 @@ extern uint8_t cdrom_audio_track_search(cdrom_t *dev, const uint32_t pos
extern uint8_t cdrom_audio_track_search_pioneer(cdrom_t *dev, const uint32_t pos, const uint8_t playbit);
extern uint8_t cdrom_audio_play_pioneer(cdrom_t *dev, const uint32_t pos);
extern uint8_t cdrom_audio_play_toshiba(cdrom_t *dev, const uint32_t pos, const int type);
extern uint8_t cdrom_audio_scan(cdrom_t *dev, const uint32_t pos, const int type);
extern uint8_t cdrom_audio_scan(cdrom_t *dev, const uint32_t pos);
extern void cdrom_audio_pause_resume(cdrom_t *dev, const uint8_t resume);
extern uint8_t cdrom_get_current_status(const cdrom_t *dev);
@@ -426,6 +432,7 @@ extern int cdrom_read_dvd_structure(const cdrom_t *dev, const uint8_
uint8_t *buffer, uint32_t *info);
extern void cdrom_read_disc_information(const cdrom_t *dev, uint8_t *buffer);
extern int cdrom_read_track_information(cdrom_t *dev, const uint8_t *cdb, uint8_t *buffer);
extern uint8_t cdrom_get_current_mode(cdrom_t *dev);
extern void cdrom_set_empty(cdrom_t *dev);
extern void cdrom_update_status(cdrom_t *dev);
extern int cdrom_load(cdrom_t *dev, const char *fn, const int skip_insert);

34
src/include/86box/crc.h Normal file
View File

@@ -0,0 +1,34 @@
/*
* 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.
*
* Definitions for the CRC code.
*
* Authors: Miran Grca, <mgrca8@gmail.com>
*
* Copyright 2016-2025 Miran Grca.
*/
#ifndef EMU_CRC_H
#define EMU_CRC_H
#ifdef __cplusplus
extern "C" {
#endif
typedef union {
uint16_t word;
uint8_t bytes[2];
} crc_t;
extern void crc16_setup(uint16_t *crc_table, uint16_t poly);
extern void crc16_calc(uint16_t *crc_table, uint8_t byte, crc_t *crc_var);
#ifdef __cplusplus
}
#endif
#endif /*EMU_CRC_H*/

View File

@@ -8,15 +8,13 @@
*
* Definitions for the floppy drive emulation.
*
*
*
* Authors: Sarah Walker, <https://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com>
* Fred N. van Kempen, <decwiz@yahoo.com>
*
* Copyright 2008-2018 Sarah Walker.
* Copyright 2016-2018 Miran Grca.
* Copyright 2018 Fred N. van Kempen.
* Copyright 2008-2025 Sarah Walker.
* Copyright 2016-2025 Miran Grca.
* Copyright 2018-2025 Fred N. van Kempen.
*/
#ifndef EMU_FDD_H
#define EMU_FDD_H
@@ -129,13 +127,6 @@ extern int drive_empty[FDD_NUM];
#define SECTOR_FIRST -2
#define SECTOR_NEXT -1
typedef union {
uint16_t word;
uint8_t bytes[2];
} crc_t;
void fdd_calccrc(uint8_t byte, crc_t *crc_var);
typedef struct d86f_handler_t {
uint16_t (*disk_flags)(int drive);
uint16_t (*side_flags)(int drive);

View File

@@ -133,6 +133,8 @@ typedef struct ide_s {
uint8_t (*phase_data_out)(scsi_common_t *sc);
void (*command_stop)(scsi_common_t *sc);
void (*bus_master_error)(scsi_common_t *sc);
void (*read)(scsi_common_t *sc);
void (*write)(scsi_common_t *sc);
#else
void * get_max;
void * get_timings;

View File

@@ -138,55 +138,63 @@ typedef struct hdd_zone_t {
/* Define the virtual Hard Disk. */
typedef struct hard_disk_t {
uint8_t id;
uint8_t id;
union {
uint8_t channel; /* Needed for Settings to reduce the number of if's */
/* Needed for Settings to reduce the number of if's */
uint8_t channel;
uint8_t mfm_channel; /* Should rename and/or unionize */
uint8_t esdi_channel;
uint8_t xta_channel;
uint8_t ide_channel;
uint8_t scsi_id;
uint8_t mfm_channel;
uint8_t esdi_channel;
uint8_t xta_channel;
uint8_t ide_channel;
uint8_t scsi_id;
};
uint8_t bus_type;
uint8_t bus_mode; /* Bit 0 = PIO suported;
Bit 1 = DMA supportd. */
uint8_t wp; /* Disk has been mounted READ-ONLY */
uint8_t pad;
uint8_t pad0;
void *priv;
uint8_t bus_type;
uint8_t bus_mode; /* Bit 0 = PIO suported;
Bit 1 = DMA supportd. */
uint8_t wp; /* Disk has been mounted
READ-ONLY */
uint8_t pad;
uint8_t pad0;
char fn[1024]; /* Name of current image file */
char vhd_parent[1041]; /* Differential VHD parent file */
void * priv;
uint32_t seek_pos;
uint32_t seek_len;
uint32_t base;
uint32_t spt;
uint32_t hpc; /* Physical geometry parameters */
uint32_t tracks;
const char *model;
char fn[1024]; /* Name of current image file */
/* Differential VHD parent file */
char vhd_parent[1280];
hdd_zone_t zones[HDD_MAX_ZONES];
uint32_t num_zones;
hdd_cache_t cache;
uint32_t phy_cyl;
uint32_t phy_heads;
uint32_t rpm;
uint8_t max_multiple_block;
uint32_t seek_pos;
uint32_t seek_len;
uint32_t base;
uint32_t spt; /* Physical geometry parameters */
uint32_t hpc;
uint32_t tracks;
uint32_t speed_preset;
uint32_t cur_cylinder;
uint32_t cur_track;
uint32_t cur_addr;
uint32_t num_zones;
uint32_t phy_cyl;
uint32_t phy_heads;
uint32_t rpm;
uint32_t cur_cylinder;
uint32_t cur_track;
uint32_t cur_addr;
uint32_t vhd_blocksize;
uint32_t speed_preset;
uint32_t vhd_blocksize;
uint8_t max_multiple_block;
uint8_t pad1[3];
double avg_rotation_lat_usec;
double full_stroke_usec;
double head_switch_usec;
double cyl_switch_usec;
const char * model;
hdd_zone_t zones[HDD_MAX_ZONES];
hdd_cache_t cache;
double avg_rotation_lat_usec;
double full_stroke_usec;
double head_switch_usec;
double cyl_switch_usec;
} hard_disk_t;
extern hard_disk_t hdd[HDD_NUM];

View File

@@ -51,10 +51,10 @@ static const mo_type_t mo_types[KNOWN_MO_TYPES] = {
};
typedef struct mo_drive_type_t {
const char vendor[9];
const char model[16];
const char revision[5];
int8_t supported_media[KNOWN_MO_TYPES];
const char *vendor;
const char *model;
const char *revision;
int8_t supported_media[KNOWN_MO_TYPES];
} mo_drive_type_t;
#define KNOWN_MO_DRIVE_TYPES 22
@@ -161,6 +161,7 @@ typedef struct mo_t {
uint32_t sector_pos;
uint32_t sector_len;
uint32_t packet_len;
uint32_t block_len;
double callback;

View File

@@ -54,18 +54,24 @@ typedef struct scsi_cdrom_t {
int do_page_save;
int unit_attention;
int request_pos;
int old_len;
int media_status;
int wait;
int buffer_pos;
uint32_t sector_pos;
uint32_t sector_len;
uint32_t packet_len;
uint32_t block_len;
double callback;
int is_sony;
int use_cdb_9;
uint8_t (*ven_cmd)(void *sc, const uint8_t *cdb, int32_t *BufLen);
int use_cdb_9;
int was_cached;
int toc_cached;
int media_access;
uint8_t vendor_type;
uint8_t ven_cmd_is_data[256];
mode_sense_pages_t ms_drive_status_pages_saved;
@@ -74,8 +80,6 @@ typedef struct scsi_cdrom_t {
mode_sense_pages_t ms_pages_default;
mode_sense_pages_t ms_pages_changeable;
uint8_t (*ven_cmd)(void *sc, const uint8_t *cdb, int32_t *BufLen);
} scsi_cdrom_t;
#endif

View File

@@ -110,39 +110,40 @@
#define GPCMD_MECHANISM_STATUS 0xbd
#define GPCMD_READ_CD 0xbe
#define GPCMD_SEND_DVD_STRUCTURE 0xbf /* This is for writing only, irrelevant to 86Box. */
#define GPCMD_EJECT_CHINON 0xc0 /* Chinon Vendor Unique command */
#define GPCMD_AUDIO_TRACK_SEARCH_TOSHIBA 0xc0 /* Toshiba Vendor Unique command */
#define GPCMD_SET_ADDRESS_FORMAT_SONY 0xc0 /* Sony Vendor Unique command */
#define GPCMD_EJECT_CHINON 0xc0 /* Chinon Vendor Unique command */
#define GPCMD_MAGAZINE_EJECT_PIONEER 0xc0 /* Pioneer Vendor Unique command */
#define GPCMD_SET_ADDRESS_FORMAT_SONY 0xc0 /* Sony Vendor Unique command */
#define GPCMD_PLAY_AUDIO_TOSHIBA 0xc1 /* Toshiba Vendor Unique command */
#define GPCMD_READ_TOC_SONY 0xc1 /* Sony Vendor Unique command */
#define GPCMD_READ_TOC_PIONEER 0xc1 /* Pioneer Vendor Unique command */
#define GPCMD_READ_TOC_SONY 0xc1 /* Sony Vendor Unique command */
#define GPCMD_PAUSE_RESUME_ALT 0xc2
#define GPCMD_READ_SUBCHANNEL_MATSUSHITA 0xc2 /* Matsushita Vendor Unique command */
#define GPCMD_READ_SUBCODEQ_PIONEER 0xc2 /* Pioneer Vendor Unique command */
#define GPCMD_READ_SUBCHANNEL_SONY 0xc2 /* Sony Vendor Unique command */
#define GPCMD_STILL_TOSHIBA 0xc2 /* Toshiba Vendor Unique command */
#define GPCMD_READ_SUBCODEQ_PIONEER 0xc2 /* Pioneer Vendor Unique command */
#define GPCMD_READ_TOC_MATSUSHITA 0xc3 /* Matsushita Vendor Unique command */
#define GPCMD_READ_HEADER_SONY 0xc3 /* Sony Vendor Unique command */
#define GPCMD_SET_STOP_TIME_TOSHIBA 0xc3 /* Toshiba Vendor Unique command */
#define GPCMD_READ_HEADER_MATSUSHITA 0xc4 /* Matsushita Vendor Unique command */
#define GPCMD_PLAYBACK_STATUS_SONY 0xc4 /* Sony Vendor Unique command */
#define GPCMD_CADDY_EJECT_TOSHIBA 0xc4 /* Toshiba Vendor Unique command */
#define GPCMD_PLAYBACK_STATUS_SONY 0xc4 /* Sony Vendor Unique command */
#define GPCMD_READ_HEADER_MATSUSHITA 0xc4 /* Matsushita Vendor Unique command */
#define GPCMD_PAUSE_SONY 0xc5 /* Sony Vendor Unique command */
#define GPCMD_PLAY_AUDIO_MATSUSHITA 0xc5 /* Matsushita Vendor Unique command */
#define GPCMD_UNKNOWN_SCSI2_NEC 0xc5 /* NEC Vendor Unique Command */
#define GPCMD_STOP_CHINON 0xc6 /* Chinon Vendor Unique command */
#define GPCMD_PLAY_TRACK_SONY 0xc6 /* Sony Vendor Unique command */
#define GPCMD_READ_SUBCODEQ_PLAYING_STATUS_TOSHIBA 0xc6 /* Toshiba Vendor Unique command */
#define GPCMD_STOP_CHINON 0xc6 /* Chinon Vendor Unique command */
#define GPCMD_PLAY_AUDIO_MSF_MATSUSHITA 0xc7 /* Matsushita Vendor Unique command*/
#define GPCMD_PLAY_MSF_SONY 0xc7 /* Sony Vendor Unique command*/
#define GPCMD_READ_DISC_INFORMATION_TOSHIBA 0xc7 /* Toshiba Vendor Unique command */
#define GPCMD_PLAY_AUDIO_TRACK_INDEX_MATSUSHITA 0xc8 /* Matsushita Vendor Unique command */
#define GPCMD_PLAY_AUDIO_SONY 0xc8 /* Sony Vendor Unique command */
#define GPCMD_AUDIO_TRACK_SEARCH_PIONEER 0xc8 /* Pioneer Vendor Unique command */
#define GPCMD_PLAY_AUDIO_SONY 0xc8 /* Sony Vendor Unique command */
#define GPCMD_PLAY_AUDIO_TRACK_INDEX_MATSUSHITA 0xc8 /* Matsushita Vendor Unique command */
#define GPCMD_READ_CDROM_MODE_TOSHIBA 0xc8 /* Toshiba Vendor Unique command */
#define GPCMD_PLAY_AUDIO_PIONEER 0xc9 /* Pioneer Vendor Unique command */
#define GPCMD_PLAY_AUDIO_TRACK_RELATIVE_10_MATSUSHITA 0xc9 /* Matsushita Vendor Unique command */
#define GPCMD_PLAYBACK_CONTROL_SONY 0xc9 /* Sony Vendor Unique command */
#define GPCMD_PLAY_AUDIO_PIONEER 0xc9 /* Pioneer Vendor Unique command */
#define GPCMD_PAUSE_PIONEER 0xca /* Pioneer Vendor Unique command */
#define GPCMD_PAUSE_RESUME_MATSUSHITA 0xcb /* Matsushita Vendor Unique command */
#define GPCMD_STOP_PIONEER 0xcb /* Pioneer Vendor Unique command */
@@ -151,8 +152,8 @@
#define GPCMD_READ_CD_MSF_OLD 0xd5 /* Should be equivalent to 0xb9 */
#define GPCMD_AUDIO_TRACK_SEARCH_NEC 0xd8 /* NEC Vendor Unique command */
#define GPCMD_PLAY_AUDIO_NEC 0xd9 /* NEC Vendor Unique command */
#define GPCMD_STILL_NEC 0xda /* NEC Vendor Unique command */
#define GPCMD_SET_SPEED_ALT 0xda /* Should be equivalent to 0xbb */
#define GPCMD_STILL_NEC 0xda /* NEC Vendor Unique command */
#define GPCMD_SET_STOP_TIME_NEC 0xdb /* NEC Vendor Unique command */
#define GPCMD_CADDY_EJECT_NEC 0xdc /* NEC Vendor Unique command */
#define GPCMD_READ_SUBCODEQ_PLAYING_STATUS_NEC 0xdd /* NEC Vendor Unique command */
@@ -409,12 +410,13 @@ typedef struct scsi_common_s {
int do_page_save;
int unit_attention;
int request_pos;
int old_len;
int media_status;
int wait;
int buffer_pos;
uint32_t sector_pos;
uint32_t sector_len;
uint32_t packet_len;
uint32_t block_len;
double callback;

View File

@@ -53,6 +53,7 @@ typedef struct scsi_disk_t {
uint32_t sector_pos;
uint32_t sector_len;
uint32_t packet_len;
uint32_t block_len;
double callback;

View File

@@ -108,6 +108,7 @@ typedef struct zip_t {
uint32_t sector_pos;
uint32_t sector_len;
uint32_t packet_len;
uint32_t block_len;
double callback;

View File

@@ -43,9 +43,6 @@ typedef struct ioctl_t {
void *log;
int is_dvd;
int has_audio;
int32_t tracks_num;
uint8_t cur_toc[65536];
CDROM_READ_TOC_EX cur_read_toc_ex;
int blocks_num;
uint8_t cur_rti[65536];
HANDLE handle;
@@ -91,37 +88,50 @@ ioctl_open_handle(ioctl_t *ioctl)
ioctl_log(ioctl->log, "handle=%p, error=%x\n",
ioctl->handle, (unsigned int) GetLastError());
if (ioctl->handle != INVALID_HANDLE_VALUE) {
CDROM_SET_SPEED set_speed = { 0 };
set_speed.RequestType = CdromSetSpeed;
set_speed.ReadSpeed = 0xffff;
set_speed.WriteSpeed = 0xffff;
set_speed.RotationControl = CdromDefaultRotation;
(void) DeviceIoControl(ioctl->handle, IOCTL_CDROM_SET_SPEED,
&set_speed, sizeof(set_speed),
NULL, 0,
0, NULL);
}
return (ioctl->handle != INVALID_HANDLE_VALUE);
}
static int
ioctl_read_normal_toc(ioctl_t *ioctl, uint8_t *toc_buf)
ioctl_read_normal_toc(ioctl_t *ioctl, uint8_t *toc_buf, int32_t *tracks_num)
{
long size = 0;
PCDROM_TOC_FULL_TOC_DATA cur_full_toc = NULL;
long size = 0;
PCDROM_TOC_FULL_TOC_DATA cur_full_toc = NULL;
CDROM_READ_TOC_EX cur_read_toc_ex = { 0 };
ioctl->tracks_num = 0;
*tracks_num = 0;
memset(toc_buf, 0x00, 65536);
cur_full_toc = (PCDROM_TOC_FULL_TOC_DATA) calloc(1, 65536);
ioctl->cur_read_toc_ex.Format = CDROM_READ_TOC_EX_FORMAT_TOC;
ioctl_log(ioctl->log, "cur_read_toc_ex.Format = %i\n", ioctl->cur_read_toc_ex.Format);
ioctl->cur_read_toc_ex.Msf = 1;
ioctl->cur_read_toc_ex.SessionTrack = 1;
cur_read_toc_ex.Format = CDROM_READ_TOC_EX_FORMAT_TOC;
ioctl_log(ioctl->log, "cur_read_toc_ex.Format = %i\n", cur_read_toc_ex.Format);
cur_read_toc_ex.Msf = 1;
cur_read_toc_ex.SessionTrack = 1;
ioctl_open_handle(ioctl);
const int temp = DeviceIoControl(ioctl->handle, IOCTL_CDROM_READ_TOC_EX,
&ioctl->cur_read_toc_ex, 65535,
cur_full_toc, 65535,
&cur_read_toc_ex, sizeof(CDROM_READ_TOC_EX),
cur_full_toc, 65535,
(LPDWORD) &size, NULL);
ioctl_close_handle(ioctl);
ioctl_log(ioctl->log, "temp = %i\n", temp);
if (temp != 0) {
const int length = ((cur_full_toc->Length[0] << 8) | cur_full_toc->Length[1]) + 2;
memcpy(toc_buf, cur_full_toc, length);
ioctl->tracks_num = (length - 4) / 8;
*tracks_num = (length - 4) / 8;
}
free(cur_full_toc);
@@ -130,9 +140,9 @@ ioctl_read_normal_toc(ioctl_t *ioctl, uint8_t *toc_buf)
PCDROM_TOC toc = (PCDROM_TOC) toc_buf;
ioctl_log(ioctl->log, "%i tracks: %02X %02X %02X %02X\n",
ioctl->tracks_num, toc_buf[0], toc_buf[1], toc_buf[2], toc_buf[3]);
*tracks_num, toc_buf[0], toc_buf[1], toc_buf[2], toc_buf[3]);
for (int i = 0; i < ioctl->tracks_num; i++) {
for (int i = 0; i < *tracks_num; i++) {
const uint8_t *t = (const uint8_t *) &toc->TrackData[i];
ioctl_log(ioctl->log, "Track %03i: %02X %02X %02X %02X %02X %02X %02X %02X\n",
i, t[0], t[1], t[2], t[3], t[4], t[5], t[6], t[7]);
@@ -145,10 +155,12 @@ ioctl_read_normal_toc(ioctl_t *ioctl, uint8_t *toc_buf)
static void
ioctl_read_raw_toc(ioctl_t *ioctl)
{
PCDROM_TOC_FULL_TOC_DATA cur_full_toc = NULL;
long size = 0;
raw_track_info_t *rti = (raw_track_info_t *) ioctl->cur_rti;
uint8_t *buffer = (uint8_t *) calloc (1, 2052);
PCDROM_TOC_FULL_TOC_DATA cur_full_toc = NULL;
long size = 0;
raw_track_info_t *rti = (raw_track_info_t *) ioctl->cur_rti;
uint8_t *buffer = (uint8_t *) calloc (1, 2052);
int status = 0;
CDROM_READ_TOC_EX cur_read_toc_ex = { 0 };
ioctl->is_dvd = (ioctl_read_dvd_structure(ioctl, 0, 0, buffer, NULL) > 0);
free(buffer);
@@ -159,65 +171,75 @@ ioctl_read_raw_toc(ioctl_t *ioctl)
cur_full_toc = (PCDROM_TOC_FULL_TOC_DATA) calloc(1, 65536);
ioctl->cur_read_toc_ex.Format = CDROM_READ_TOC_EX_FORMAT_FULL_TOC;
ioctl_log(ioctl->log, "cur_read_toc_ex.Format = %i\n", ioctl->cur_read_toc_ex.Format);
ioctl->cur_read_toc_ex.Msf = 1;
ioctl->cur_read_toc_ex.SessionTrack = 1;
cur_read_toc_ex.Format = CDROM_READ_TOC_EX_FORMAT_FULL_TOC;
ioctl_log(ioctl->log, "cur_read_toc_ex.Format = %i\n", cur_read_toc_ex.Format);
cur_read_toc_ex.Msf = 1;
cur_read_toc_ex.SessionTrack = 1;
ioctl_open_handle(ioctl);
const int status = DeviceIoControl(ioctl->handle, IOCTL_CDROM_READ_TOC_EX,
&ioctl->cur_read_toc_ex, 65535,
cur_full_toc, 65535,
(LPDWORD) &size, NULL);
ioctl_close_handle(ioctl);
ioctl_log(ioctl->log, "status = %i\n", status);
if (!ioctl->is_dvd) {
status = DeviceIoControl(ioctl->handle, IOCTL_CDROM_READ_TOC_EX,
&cur_read_toc_ex, sizeof(CDROM_READ_TOC_EX),
cur_full_toc, 65535,
(LPDWORD) &size, NULL);
ioctl_log(ioctl->log, "status = %i\n", status);
}
if ((status == 0) && (ioctl->tracks_num >= 1)) {
if (status == 0) {
/*
This is needed because in some circumstances (eg. a DVD .MDS
mounted in Daemon Tools), reading the raw TOC fails but
reading the cooked TOC does not, so we have to construct the
raw TOC from the cooked TOC.
*/
const CDROM_TOC *toc = (const CDROM_TOC *) ioctl->cur_toc;
const TRACK_DATA *ct = &(toc->TrackData[ioctl->tracks_num - 1]);
uint8_t cur_toc[65536] = { 0 };
int32_t tracks_num = 0;
rti[0].adr_ctl = ((ct->Adr & 0xf) << 4) | (ct->Control & 0xf);
rti[0].point = 0xa0;
rti[0].pm = toc->FirstTrack;
const CDROM_TOC * toc = (const CDROM_TOC *) cur_toc;
rti[1].adr_ctl = rti[0].adr_ctl;
rti[1].point = 0xa1;
rti[1].pm = toc->LastTrack;
status = ioctl_read_normal_toc(ioctl, cur_toc, &tracks_num);
rti[2].adr_ctl = rti[0].adr_ctl;
rti[2].point = 0xa2;
rti[2].pm = ct->Address[1];
rti[2].ps = ct->Address[2];
rti[2].pf = ct->Address[3];
const TRACK_DATA *ct = &(toc->TrackData[tracks_num - 1]);
ioctl->blocks_num = 3;
if ((status > 0) && (tracks_num >= 1)) {
rti[0].adr_ctl = ((ct->Adr & 0xf) << 4) | (ct->Control & 0xf);
rti[0].point = 0xa0;
rti[0].pm = toc->FirstTrack;
for (int i = 0; i < (ioctl->tracks_num - 1); i++) {
raw_track_info_t *crt = &(rti[ioctl->blocks_num]);
rti[1].adr_ctl = rti[0].adr_ctl;
rti[1].point = 0xa1;
rti[1].pm = toc->LastTrack;
ct = &(toc->TrackData[i]);
rti[2].adr_ctl = rti[0].adr_ctl;
rti[2].point = 0xa2;
rti[2].pm = ct->Address[1];
rti[2].ps = ct->Address[2];
rti[2].pf = ct->Address[3];
crt->adr_ctl = ((ct->Adr & 0xf) << 4) | (ct->Control & 0xf);
crt->point = ct->TrackNumber;
crt->pm = ct->Address[1];
crt->ps = ct->Address[2];
crt->pf = ct->Address[3];
ioctl->blocks_num = 3;
ioctl->blocks_num++;
}
for (int i = 0; i < (tracks_num - 1); i++) {
raw_track_info_t *crt = &(rti[ioctl->blocks_num]);
ct = &(toc->TrackData[i]);
crt->adr_ctl = ((ct->Adr & 0xf) << 4) | (ct->Control & 0xf);
crt->point = ct->TrackNumber;
crt->pm = ct->Address[1];
crt->ps = ct->Address[2];
crt->pf = ct->Address[3];
ioctl->blocks_num++;
}
} else if (status > 0)
/* Announce that we've had a failure. */
status = 0;
} else if (status != 0) {
ioctl->blocks_num = (((cur_full_toc->Length[0] << 8) |
cur_full_toc->Length[1]) - 2) / 11;
memcpy(ioctl->cur_rti, cur_full_toc->Descriptors, ioctl->blocks_num * 11);
}
if (ioctl->blocks_num) for (int i = 0; i < ioctl->tracks_num; i++) {
if (ioctl->blocks_num) for (int i = 0; i < ioctl->blocks_num; i++) {
const raw_track_info_t *crt = &(rti[i]);
if ((crt->point >= 1) && (crt->point <= 99) && !(crt->adr_ctl & 0x04)) {
@@ -244,13 +266,6 @@ ioctl_read_raw_toc(ioctl_t *ioctl)
free(cur_full_toc);
}
static void
ioctl_read_toc(ioctl_t *ioctl)
{
(void) ioctl_read_normal_toc(ioctl, ioctl->cur_toc);
ioctl_read_raw_toc(ioctl);
}
static int
ioctl_get_track(const ioctl_t *ioctl, const uint32_t sector) {
raw_track_info_t *rti = (raw_track_info_t *) ioctl->cur_rti;
@@ -296,23 +311,28 @@ static int
ioctl_get_track_info(const void *local, const uint32_t track,
int end, track_info_t *ti)
{
const ioctl_t * ioctl = (const ioctl_t *) local;
const CDROM_TOC *toc = (const CDROM_TOC *) ioctl->cur_toc;
int ret = 1;
const ioctl_t * ioctl = (const ioctl_t *) local;
const raw_track_info_t *rti = (const raw_track_info_t *) ioctl->cur_rti;
int ret = 1;
int trk = -1;
if ((track < 1) || (track == 0xaa) || (track > (toc->LastTrack + 1))) {
if ((track >= 1) && (track < 99))
for (int i = 0; i < ioctl->blocks_num; i++)
if (rti[i].point == track) {
trk = i;
break;
}
if ((track == 0xaa) || (trk == -1)) {
ioctl_log(ioctl->log, "ioctl_get_track_info(%02i)\n", track);
ret = 0;
} else {
const TRACK_DATA * td = &toc->TrackData[track - 1];
ti->m = rti[trk].pm;
ti->s = rti[trk].ps;
ti->f = rti[trk].pf;
ti->m = td->Address[1];
ti->s = td->Address[2];
ti->f = td->Address[3];
ti->number = td->TrackNumber;
ti->attr = td->Control;
ti->attr |= ((td->Adr << 4) & 0xf0);
ti->number = rti[trk].point;
ti->attr = rti[trk].adr_ctl;
ioctl_log(ioctl->log, "ioctl_get_track_info(%02i): %02i:%02i:%02i, %02i, %02X\n",
track, ti->m, ti->s, ti->f, ti->number, ti->attr);
@@ -370,8 +390,6 @@ ioctl_read_sector(const void *local, uint8_t *buffer, uint32_t const sector)
int ret;
SCSI_PASS_THROUGH_DIRECT_BUF req;
ioctl_open_handle((ioctl_t *) ioctl);
if (ioctl->is_dvd) {
int track;
@@ -503,8 +521,6 @@ ioctl_read_sector(const void *local, uint8_t *buffer, uint32_t const sector)
for (int j = 7; j >= 0; j--)
buffer[2352 + (i * 8) + j] = ((buffer[sc_offs + i] >> (7 - j)) & 0x01) << 6;
ioctl_close_handle((ioctl_t *) ioctl);
return ret;
}
@@ -540,18 +556,15 @@ ioctl_get_track_type(const void *local, const uint32_t sector)
static uint32_t
ioctl_get_last_block(const void *local)
{
const ioctl_t *ioctl = (const ioctl_t *) local;
const CDROM_TOC *toc = (const CDROM_TOC *) ioctl->cur_toc;
const ioctl_t * ioctl = (const ioctl_t *) local;
raw_track_info_t *rti = (raw_track_info_t *) ioctl->cur_rti;
uint32_t lb = 0;
for (int c = 0; c <= toc->LastTrack; c++) {
const TRACK_DATA *td = &toc->TrackData[c];
const uint32_t address = MSFtoLBA(td->Address[1], td->Address[2],
td->Address[3]) - 150;
if (address > lb)
lb = address;
}
for (int i = (ioctl->blocks_num - 1); i >= 0; i--)
if (rti[i].point == 0xa2) {
lb = MSFtoLBA(rti[i].pm, rti[i].ps, rti[i].pf) - 151;
break;
}
ioctl_log(ioctl->log, "LBCapacity=%d\n", lb);
@@ -573,8 +586,6 @@ ioctl_read_dvd_structure(const void *local, const uint8_t layer, const uint8_t f
const int len = 2052;
SCSI_PASS_THROUGH_DIRECT_BUF req;
ioctl_open_handle((ioctl_t *) ioctl);
memset(&req, 0x00, sizeof(SCSI_PASS_THROUGH_DIRECT_BUF));
req.spt.Length = sizeof(SCSI_PASS_THROUGH_DIRECT);
req.spt.PathId = 0;
@@ -636,8 +647,6 @@ ioctl_read_dvd_structure(const void *local, const uint8_t layer, const uint8_t f
} else
ret = ret ? (req.spt.DataTransferLength >= len) : 0;
ioctl_close_handle((ioctl_t *) ioctl);
return ret;
}
@@ -670,8 +679,6 @@ ioctl_is_empty(const void *local)
unsigned long int unused = 0;
SCSI_PASS_THROUGH_DIRECT_BUF req;
ioctl_open_handle((ioctl_t *) ioctl);
memset(&req, 0x00, sizeof(SCSI_PASS_THROUGH_DIRECT_BUF));
req.spt.Length = sizeof(SCSI_PASS_THROUGH_DIRECT);
req.spt.PathId = 0;
@@ -731,8 +738,6 @@ ioctl_is_empty(const void *local)
} else
ret = 0;
ioctl_close_handle((ioctl_t *) ioctl);
return ret;
}
@@ -760,14 +765,13 @@ ioctl_load(const void *local)
{
const ioctl_t *ioctl = (const ioctl_t *) local;
if (ioctl_open_handle((ioctl_t *) ioctl)) {
long size;
DeviceIoControl(ioctl->handle, IOCTL_STORAGE_LOAD_MEDIA,
NULL, 0, NULL, 0,
(LPDWORD) &size, NULL);
ioctl_close_handle((ioctl_t *) ioctl);
if ((ioctl->handle != NULL) || ioctl_open_handle((ioctl_t *) ioctl)) {
long size = 0;
(void) DeviceIoControl(ioctl->handle, IOCTL_STORAGE_LOAD_MEDIA,
NULL, 0, NULL, 0,
(LPDWORD) &size, NULL);
ioctl_read_toc((ioctl_t *) ioctl);
ioctl_read_raw_toc((ioctl_t *) ioctl);
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -274,83 +274,89 @@ sound_cd_thread(UNUSED(void *param))
temp_buffer[0] = temp_buffer[1] = 0;
for (uint8_t i = 0; i < CDROM_NUM; i++) {
if ((cdrom[i].bus_type == CDROM_BUS_DISABLED) || (cdrom[i].cd_status == CD_STATUS_EMPTY))
/* Just in case the thread is in a loop when it gets terminated. */
if (!cdaudioon)
break;
if ((cdrom[i].bus_type == CDROM_BUS_DISABLED) ||
(cdrom[i].cd_status != CD_STATUS_PLAYING))
continue;
const uint32_t lba = cdrom[i].seek_pos;
const int r = cdrom_audio_callback(&(cdrom[i]), cd_buffer[i], CD_BUFLEN * 2);
if (!cdrom[i].sound_on || !r)
continue;
const int pre = cdrom_is_pre(&(cdrom[i]), lba);
const int ret = cdrom_audio_callback(&(cdrom[i]), cd_buffer[i],
CD_BUFLEN * 2);
if (cdrom[i].get_volume) {
audio_vol_l = cd_audio_volume_lut[cdrom[i].get_volume(cdrom[i].priv, 0)];
audio_vol_r = cd_audio_volume_lut[cdrom[i].get_volume(cdrom[i].priv, 1)];
} else {
audio_vol_l = cd_audio_volume_lut[255];
audio_vol_r = cd_audio_volume_lut[255];
}
if (cdrom[i].get_channel) {
channel_select[0] = (int) cdrom[i].get_channel(cdrom[i].priv, 0);
channel_select[1] = (int) cdrom[i].get_channel(cdrom[i].priv, 1);
} else {
channel_select[0] = 1;
channel_select[1] = 2;
}
for (int c = 0; c < CD_BUFLEN * 2; c += 2) {
/*Apply ATAPI channel select*/
cd_buffer_temp[0] = cd_buffer_temp[1] = 0.0;
if ((audio_vol_l != 0.0) && (channel_select[0] != 0)) {
if (channel_select[0] & 1)
cd_buffer_temp[0] += ((double) cd_buffer[i][c]); /* Channel 0 => Port 0 */
if (channel_select[0] & 2)
cd_buffer_temp[0] += ((double) cd_buffer[i][c + 1]); /* Channel 1 => Port 0 */
cd_buffer_temp[0] *= audio_vol_l; /* Multiply Port 0 by Port 0 volume */
if (pre)
cd_buffer_temp[0] = deemph_iir(0, cd_buffer_temp[0]); /* De-emphasize if necessary */
}
if ((audio_vol_r != 0.0) && (channel_select[1] != 0)) {
if (channel_select[1] & 1)
cd_buffer_temp[1] += ((double) cd_buffer[i][c]); /* Channel 0 => Port 1 */
if (channel_select[1] & 2)
cd_buffer_temp[1] += ((double) cd_buffer[i][c + 1]); /* Channel 1 => Port 1 */
cd_buffer_temp[1] *= audio_vol_r; /* Multiply Port 1 by Port 1 volume */
if (pre)
cd_buffer_temp[1] = deemph_iir(1, cd_buffer_temp[1]); /* De-emphasize if necessary */
}
/* Apply sound card CD volume and filters */
if (filter_cd_audio != NULL) {
filter_cd_audio(0, &(cd_buffer_temp[0]), filter_cd_audio_p);
filter_cd_audio(1, &(cd_buffer_temp[1]), filter_cd_audio_p);
}
if (sound_is_float) {
cd_out_buffer[c] += (float) (cd_buffer_temp[0] / 32768.0);
cd_out_buffer[c + 1] += (float) (cd_buffer_temp[1] / 32768.0);
if (ret) {
if (cdrom[i].get_volume) {
audio_vol_l = cd_audio_volume_lut[cdrom[i].get_volume(cdrom[i].priv, 0)];
audio_vol_r = cd_audio_volume_lut[cdrom[i].get_volume(cdrom[i].priv, 1)];
} else {
temp_buffer[0] += (int) trunc(cd_buffer_temp[0]);
temp_buffer[1] += (int) trunc(cd_buffer_temp[1]);
audio_vol_l = cd_audio_volume_lut[255];
audio_vol_r = cd_audio_volume_lut[255];
}
if (temp_buffer[0] > 32767)
temp_buffer[0] = 32767;
if (temp_buffer[0] < -32768)
temp_buffer[0] = -32768;
if (temp_buffer[1] > 32767)
temp_buffer[1] = 32767;
if (temp_buffer[1] < -32768)
temp_buffer[1] = -32768;
if (cdrom[i].get_channel) {
channel_select[0] = (int) cdrom[i].get_channel(cdrom[i].priv, 0);
channel_select[1] = (int) cdrom[i].get_channel(cdrom[i].priv, 1);
} else {
channel_select[0] = 1;
channel_select[1] = 2;
}
cd_out_buffer_int16[c] = (int16_t) temp_buffer[0];
cd_out_buffer_int16[c + 1] = (int16_t) temp_buffer[1];
// uint16_t *cddab = (uint16_t *) cdrom[i].raw_buffer;
for (int c = 0; c < CD_BUFLEN * 2; c += 2) {
/* Apply ATAPI channel select */
cd_buffer_temp[0] = cd_buffer_temp[1] = 0.0;
if ((audio_vol_l != 0.0) && (channel_select[0] != 0)) {
if (channel_select[0] & 1)
/* Channel 0 => Port 0 */
cd_buffer_temp[0] += ((double) cd_buffer[i][c]);
if (channel_select[0] & 2)
/* Channel 1 => Port 0 */
cd_buffer_temp[0] += ((double) cd_buffer[i][c + 1]);
/* Multiply Port 0 by Port 0 volume */
cd_buffer_temp[0] *= audio_vol_l;
}
if ((audio_vol_r != 0.0) && (channel_select[1] != 0)) {
if (channel_select[1] & 1)
/* Channel 0 => Port 1 */
cd_buffer_temp[1] += ((double) cd_buffer[i][c]);
if (channel_select[1] & 2)
/* Channel 1 => Port 1 */
cd_buffer_temp[1] += ((double) cd_buffer[i][c + 1]);
/* Multiply Port 1 by Port 1 volume */
cd_buffer_temp[1] *= audio_vol_r;
}
/* Apply sound card CD volume and filters */
if (filter_cd_audio != NULL) {
filter_cd_audio(0, &(cd_buffer_temp[0]),
filter_cd_audio_p);
filter_cd_audio(1, &(cd_buffer_temp[1]),
filter_cd_audio_p);
}
if (sound_is_float) {
cd_out_buffer[c] += (float) (cd_buffer_temp[0] / 32768.0);
cd_out_buffer[c + 1] += (float) (cd_buffer_temp[1] / 32768.0);
} else {
temp_buffer[0] = (int) trunc(cd_buffer_temp[0]);
temp_buffer[1] = (int) trunc(cd_buffer_temp[1]);
if (temp_buffer[0] > 32767)
temp_buffer[0] = 32767;
if (temp_buffer[0] < -32768)
temp_buffer[0] = -32768;
if (temp_buffer[1] > 32767)
temp_buffer[1] = 32767;
if (temp_buffer[1] < -32768)
temp_buffer[1] = -32768;
cd_out_buffer_int16[c] += (int16_t) temp_buffer[0];
cd_out_buffer_int16[c + 1] += (int16_t) temp_buffer[1];
}
}
}
}

26
src/utils/CMakeLists.txt Normal file
View File

@@ -0,0 +1,26 @@
#
# 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.
#
# CMake build script.
#
# Authors: David Hrdlička, <hrdlickadavid@outlook.com>
# Jasmine Iwanek, <jriwanek@gmail.com>
#
# Copyright 2020-2021 David Hrdlička.
# Copyright 2024 Jasmine Iwanek.
#
add_library(utils OBJECT
cJSON.c
crc.c
fifo.c
fifo8.c
ini.c
log.c
random.c
)

77
src/utils/crc.c Normal file
View File

@@ -0,0 +1,77 @@
/*
* 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.
*
* CRC implementation.
*
* Authors: Miran Grca, <mgrca8@gmail.com>
*
* Copyright 2016-2025 Miran Grca.
*/
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdarg.h>
#include <assert.h>
#include <wchar.h>
#define HAVE_STDARG_H
#include <86box/86box.h>
#include <86box/timer.h>
#include <86box/dma.h>
#include <86box/nvr.h>
#include <86box/random.h>
#include <86box/plat.h>
#include <86box/ui.h>
#include <86box/crc.h>
#ifdef ENABLE_CRC_LOG
int d86f_do_log = ENABLE_CRC_LOG;
static void
crc_log(const char *fmt, ...)
{
va_list ap;
if (crc_do_log) {
va_start(ap, fmt);
pclog_ex(fmt, ap);
va_end(ap);
}
}
#else
# define crc_log(fmt, ...)
#endif
void
crc16_setup(uint16_t *crc_table, uint16_t poly)
{
int c = 256;
int bc;
uint16_t temp;
while (c--) {
temp = c << 8;
bc = 8;
while (bc--) {
if (temp & 0x8000)
temp = (temp << 1) ^ poly;
else
temp <<= 1;
crc_table[c] = temp;
}
}
}
void
crc16_calc(uint16_t *crc_table, uint8_t byte, crc_t *crc_var)
{
crc_var->word = (crc_var->word << 8) ^
crc_table[(crc_var->word >> 8) ^ byte];
}