Applied the first batch of upstream commits.
This commit is contained in:
@@ -9,7 +9,7 @@
|
||||
* Implementation of the CD-ROM drive with SCSI(-like)
|
||||
* commands, for both ATAPI and SCSI usage.
|
||||
*
|
||||
* Version: @(#)cdrom.c 1.0.5 2018/03/16
|
||||
* Version: @(#)cdrom.c 1.0.6 2018/03/17
|
||||
*
|
||||
* Authors: Fred N. van Kempen, <decwiz@yahoo.com>
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
@@ -909,12 +909,6 @@ static void cdrom_unit_attention(uint8_t id)
|
||||
cdrom_log("CD-ROM %i: UNIT ATTENTION\n", id);
|
||||
}
|
||||
|
||||
static void cdrom_bus_master_error(uint8_t id)
|
||||
{
|
||||
cdrom_sense_key = cdrom_asc = cdrom_ascq = 0;
|
||||
cdrom_cmd_error(id);
|
||||
}
|
||||
|
||||
static void cdrom_not_ready(uint8_t id)
|
||||
{
|
||||
cdrom_sense_key = SENSE_NOT_READY;
|
||||
@@ -2745,21 +2739,22 @@ int cdrom_read_from_ide_dma(uint8_t channel)
|
||||
return 0;
|
||||
|
||||
if (ide_bus_master_write) {
|
||||
if (ide_bus_master_write(channel >> 1, cdbufferb, cdrom[id].packet_len)) {
|
||||
cdrom_bus_master_error(id);
|
||||
cdrom_phase_callback(id);
|
||||
if (ide_bus_master_write(channel >> 1, cdbufferb, cdrom[id].packet_len))
|
||||
return 0;
|
||||
} else
|
||||
else
|
||||
return 1;
|
||||
} else {
|
||||
cdrom_bus_master_error(id);
|
||||
cdrom_phase_callback(id);
|
||||
} else
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void cdrom_irq_raise(uint8_t id)
|
||||
{
|
||||
if (cdrom_drives[id].bus_type < CDROM_BUS_SCSI)
|
||||
ide_irq_raise(&(ide_drives[cdrom_drives[id].ide_channel]));
|
||||
}
|
||||
|
||||
int cdrom_read_from_scsi_dma(uint8_t scsi_id, uint8_t scsi_lun)
|
||||
{
|
||||
uint8_t id = scsi_cdrom_drives[scsi_id][scsi_lun];
|
||||
@@ -2793,40 +2788,34 @@ int cdrom_read_from_dma(uint8_t id)
|
||||
cdrom_log("CD-ROM %i: ATAPI Input data length: %i\n", id, cdrom[id].packet_len);
|
||||
|
||||
ret = cdrom_phase_data_out(id);
|
||||
if (!ret) {
|
||||
cdrom_phase_callback(id);
|
||||
return 0;
|
||||
} else
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
if (ret || (cdrom_drives[id].bus_type == CDROM_BUS_SCSI)) {
|
||||
cdrom_buf_free(id);
|
||||
cdrom[id].packet_status = CDROM_PHASE_COMPLETE;
|
||||
cdrom[id].status = READY_STAT;
|
||||
cdrom[id].phase = 3;
|
||||
ui_sb_update_icon(SB_CDROM | id, 0);
|
||||
cdrom_irq_raise(id);
|
||||
if (ret)
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
} else
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cdrom_write_to_ide_dma(uint8_t channel)
|
||||
{
|
||||
uint8_t id = atapi_cdrom_drives[channel];
|
||||
|
||||
if (id > CDROM_NUM) {
|
||||
cdrom_log("CD-ROM %i: Drive not found\n", id);
|
||||
if (id > CDROM_NUM)
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (ide_bus_master_read) {
|
||||
if (ide_bus_master_read(channel >> 1, cdbufferb, cdrom[id].packet_len)) {
|
||||
cdrom_log("CD-ROM %i: ATAPI DMA error\n", id);
|
||||
cdrom_bus_master_error(id);
|
||||
cdrom_phase_callback(id);
|
||||
if (ide_bus_master_read(channel >> 1, cdbufferb, cdrom[id].packet_len))
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
cdrom_log("CD-ROM %i: ATAPI DMA success\n", id);
|
||||
else
|
||||
return 1;
|
||||
}
|
||||
} else {
|
||||
cdrom_log("CD-ROM %i: No bus master\n", id);
|
||||
cdrom_bus_master_error(id);
|
||||
cdrom_phase_callback(id);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -2857,16 +2846,19 @@ int cdrom_write_to_dma(uint8_t id)
|
||||
} else
|
||||
ret = cdrom_write_to_ide_dma(cdrom_drives[id].ide_channel);
|
||||
|
||||
if (!ret)
|
||||
if (ret || (cdrom_drives[id].bus_type == CDROM_BUS_SCSI)) {
|
||||
cdrom_buf_free(id);
|
||||
cdrom[id].packet_status = CDROM_PHASE_COMPLETE;
|
||||
cdrom[id].status = READY_STAT;
|
||||
cdrom[id].phase = 3;
|
||||
ui_sb_update_icon(SB_CDROM | id, 0);
|
||||
cdrom_irq_raise(id);
|
||||
if (ret)
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
} else
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void cdrom_irq_raise(uint8_t id)
|
||||
{
|
||||
if (cdrom_drives[id].bus_type < CDROM_BUS_SCSI)
|
||||
ide_irq_raise(&(ide_drives[cdrom_drives[id].ide_channel]));
|
||||
}
|
||||
|
||||
/* If the result is 1, issue an IRQ, otherwise not. */
|
||||
@@ -2902,12 +2894,6 @@ void cdrom_phase_callback(uint8_t id)
|
||||
case CDROM_PHASE_DATA_OUT_DMA:
|
||||
cdrom_log("CD-ROM %i: CDROM_PHASE_DATA_OUT_DMA\n", id);
|
||||
cdrom_read_from_dma(id);
|
||||
cdrom_buf_free(id);
|
||||
cdrom[id].packet_status = CDROM_PHASE_COMPLETE;
|
||||
cdrom[id].status = READY_STAT;
|
||||
cdrom[id].phase = 3;
|
||||
ui_sb_update_icon(SB_CDROM | id, 0);
|
||||
cdrom_irq_raise(id);
|
||||
return;
|
||||
case CDROM_PHASE_DATA_IN:
|
||||
cdrom_log("CD-ROM %i: CDROM_PHASE_DATA_IN\n", id);
|
||||
@@ -2918,12 +2904,6 @@ void cdrom_phase_callback(uint8_t id)
|
||||
case CDROM_PHASE_DATA_IN_DMA:
|
||||
cdrom_log("CD-ROM %i: CDROM_PHASE_DATA_IN_DMA\n", id);
|
||||
cdrom_write_to_dma(id);
|
||||
cdrom_buf_free(id);
|
||||
cdrom[id].packet_status = CDROM_PHASE_COMPLETE;
|
||||
cdrom[id].status = READY_STAT;
|
||||
cdrom[id].phase = 3;
|
||||
ui_sb_update_icon(SB_CDROM | id, 0);
|
||||
cdrom_irq_raise(id);
|
||||
return;
|
||||
case CDROM_PHASE_ERROR:
|
||||
cdrom_log("CD-ROM %i: CDROM_PHASE_ERROR\n", id);
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*
|
||||
* Definitions for the CDROM module..
|
||||
*
|
||||
* Version: @(#)cdrom.h 1.0.4 2018/03/08
|
||||
* Version: @(#)cdrom.h 1.0.5 2018/03/17
|
||||
*
|
||||
* Authors: Fred N. van Kempen, <decwiz@yahoo.com>
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
@@ -172,6 +172,8 @@ typedef struct {
|
||||
int block_descriptor_len;
|
||||
|
||||
int init_length;
|
||||
|
||||
int16_t cd_buffer[BUF_SIZE];
|
||||
} cdrom_t;
|
||||
|
||||
typedef struct {
|
||||
@@ -211,7 +213,6 @@ typedef struct {
|
||||
int cd_state;
|
||||
uint32_t cd_pos;
|
||||
uint32_t cd_end;
|
||||
int16_t cd_buffer[BUF_SIZE];
|
||||
int cd_buflen;
|
||||
} cdrom_image_t;
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*
|
||||
* CD-ROM image support.
|
||||
*
|
||||
* Version: @(#)cdrom_image.cpp 1.0.3 2018/02/22
|
||||
* Version: @(#)cdrom_image.cpp 1.0.4 2018/03/17
|
||||
*
|
||||
* Authors: Fred N. van Kempen, <decwiz@yahoo.com>
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
@@ -112,9 +112,9 @@ void image_audio_callback(uint8_t id, int16_t *output, int len)
|
||||
{
|
||||
if (cdrom[id].seek_pos < cdrom_image[id].cd_end)
|
||||
{
|
||||
if (!cdimg[id]->ReadSector((unsigned char*)&cdrom_image[id].cd_buffer[cdrom_image[id].cd_buflen], true, cdrom[id].seek_pos))
|
||||
if (!cdimg[id]->ReadSector((unsigned char*)&cdrom[id].cd_buffer[cdrom_image[id].cd_buflen], true, cdrom[id].seek_pos))
|
||||
{
|
||||
memset(&cdrom_image[id].cd_buffer[cdrom_image[id].cd_buflen], 0, (BUF_SIZE - cdrom_image[id].cd_buflen) * 2);
|
||||
memset(&cdrom[id].cd_buffer[cdrom_image[id].cd_buflen], 0, (BUF_SIZE - cdrom_image[id].cd_buflen) * 2);
|
||||
cdrom_image[id].cd_state = CD_STOPPED;
|
||||
cdrom_image[id].cd_buflen = len;
|
||||
}
|
||||
@@ -126,13 +126,13 @@ void image_audio_callback(uint8_t id, int16_t *output, int len)
|
||||
}
|
||||
else
|
||||
{
|
||||
memset(&cdrom_image[id].cd_buffer[cdrom_image[id].cd_buflen], 0, (BUF_SIZE - cdrom_image[id].cd_buflen) * 2);
|
||||
memset(&cdrom[id].cd_buffer[cdrom_image[id].cd_buflen], 0, (BUF_SIZE - cdrom_image[id].cd_buflen) * 2);
|
||||
cdrom_image[id].cd_state = CD_STOPPED;
|
||||
cdrom_image[id].cd_buflen = len;
|
||||
}
|
||||
}
|
||||
memcpy(output, cdrom_image[id].cd_buffer, len * 2);
|
||||
memmove(cdrom_image[id].cd_buffer, &cdrom_image[id].cd_buffer[len], (BUF_SIZE - len) * 2);
|
||||
memcpy(output, cdrom[id].cd_buffer, len * 2);
|
||||
memmove(cdrom[id].cd_buffer, &cdrom[id].cd_buffer[len], (BUF_SIZE - len) * 2);
|
||||
cdrom_image[id].cd_buflen -= len;
|
||||
}
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
* Implementation of the IDE emulation for hard disks and ATAPI
|
||||
* CD-ROM devices.
|
||||
*
|
||||
* Version: @(#)hdc_ide.c 1.0.9 2018/03/16
|
||||
* Version: @(#)hdc_ide.c 1.0.10 2018/03/17
|
||||
*
|
||||
* Authors: Miran Grca, <mgrca8@gmail.com>
|
||||
* Sarah Walker, <tommowalker@tommowalker.co.uk>
|
||||
@@ -110,6 +110,14 @@
|
||||
#define WIN_SET_FEATURES 0xEF
|
||||
#define WIN_READ_NATIVE_MAX 0xF8
|
||||
|
||||
#define FEATURE_SET_TRANSFER_MODE 0x03
|
||||
#define FEATURE_ENABLE_IRQ_OVERLAPPED 0x5d
|
||||
#define FEATURE_ENABLE_IRQ_SERVICE 0x5e
|
||||
#define FEATURE_DISABLE_REVERT 0x66
|
||||
#define FEATURE_ENABLE_REVERT 0xcc
|
||||
#define FEATURE_DISABLE_IRQ_OVERLAPPED 0xdd
|
||||
#define FEATURE_DISABLE_IRQ_SERVICE 0xde
|
||||
|
||||
enum
|
||||
{
|
||||
IDE_NONE = 0,
|
||||
@@ -417,11 +425,13 @@ static void ide_identify(IDE *ide)
|
||||
|
||||
if (ide->buffer[49] & (1 << 8))
|
||||
{
|
||||
ide->buffer[52] = 2 << 8; /*DMA timing mode*/
|
||||
ide->buffer[51] = 120;
|
||||
ide->buffer[52] = 120; /*DMA timing mode*/
|
||||
ide->buffer[53] |= 6;
|
||||
|
||||
ide->buffer[62] = 7;
|
||||
ide->buffer[63] = 7;
|
||||
ide->buffer[64] = 3; /*PIO Modes 3 & 4*/
|
||||
ide->buffer[88] = 7;
|
||||
if (ide->mdma_mode != -1)
|
||||
{
|
||||
@@ -431,7 +441,10 @@ static void ide_identify(IDE *ide)
|
||||
ide->buffer[88] |= d;
|
||||
else if ((ide->mdma_mode & 0x300) == 0x100)
|
||||
ide->buffer[63] |= d;
|
||||
else
|
||||
else if ((ide->mdma_mode & 0x300) == 0x400) {
|
||||
if ((ide->mdma_mode & 0xff) >= 3)
|
||||
ide->buffer[64] |= d;
|
||||
} else
|
||||
ide->buffer[62] |= d;
|
||||
ide_log(" IDENTIFY DMA Mode: %04X, %04X\n", ide->buffer[62], ide->buffer[63]);
|
||||
}
|
||||
@@ -472,10 +485,12 @@ static void ide_atapi_identify(IDE *ide)
|
||||
if (PCI && (ide->board < 2) && (cdrom_drives[cdrom_id].bus_type == CDROM_BUS_ATAPI_PIO_AND_DMA))
|
||||
{
|
||||
ide->buffer[49] |= 0x100; /* DMA supported */
|
||||
ide->buffer[52] = 2 << 8; /*DMA timing mode*/
|
||||
ide->buffer[51] = 120;
|
||||
ide->buffer[52] = 120; /*DMA timing mode*/
|
||||
ide->buffer[53] = 7;
|
||||
ide->buffer[62] = 7;
|
||||
ide->buffer[63] = 7;
|
||||
ide->buffer[64] = 3; /*PIO Modes 3 & 4*/
|
||||
ide->buffer[88] = 7;
|
||||
if (ide->mdma_mode != -1)
|
||||
{
|
||||
@@ -485,12 +500,16 @@ static void ide_atapi_identify(IDE *ide)
|
||||
ide->buffer[88] |= d;
|
||||
else if ((ide->mdma_mode & 0x300) == 0x100)
|
||||
ide->buffer[63] |= d;
|
||||
else
|
||||
else if ((ide->mdma_mode & 0x300) == 0x400) {
|
||||
if ((ide->mdma_mode & 0xff) >= 3)
|
||||
ide->buffer[64] |= d;
|
||||
} else
|
||||
ide->buffer[62] |= d;
|
||||
ide_log("PIDENTIFY DMA Mode: %04X, %04X\n", ide->buffer[62], ide->buffer[63]);
|
||||
}
|
||||
ide->buffer[65] = 0xb4;
|
||||
ide->buffer[66] = 0xb4;
|
||||
ide->buffer[65] = 120;
|
||||
ide->buffer[66] = 120;
|
||||
ide->buffer[67] = 120;
|
||||
ide->buffer[71] = 30;
|
||||
ide->buffer[72] = 30;
|
||||
ide->buffer[80] = 0x1e; /*ATA-1 to ATA-4 supported*/
|
||||
@@ -526,26 +545,42 @@ static void ide_atapi_zip_identify(IDE *ide)
|
||||
if (PCI && (ide->board < 2) && (zip_drives[zip_id].bus_type == ZIP_BUS_ATAPI_PIO_AND_DMA))
|
||||
{
|
||||
ide->buffer[49] |= 0x100; /* DMA supported */
|
||||
ide->buffer[52] = 0 << 8; /*DMA timing mode*/
|
||||
ide->buffer[53] = 6;
|
||||
ide->buffer[63] = 3;
|
||||
ide->buffer[88] = 7;
|
||||
if (ide->mdma_mode != -1)
|
||||
if (zip_drives[zip_id].is_250) {
|
||||
ide->buffer[52] = 0 << 8; /*DMA timing mode*/
|
||||
ide->buffer[53] = 6;
|
||||
ide->buffer[63] = 3;
|
||||
ide->buffer[88] = 7;
|
||||
ide->buffer[64] = 0x0001; /*PIO Mode 3*/
|
||||
ide->buffer[65] = 0x96;
|
||||
ide->buffer[66] = 0x96;
|
||||
ide->buffer[67] = 0xb4;
|
||||
ide->buffer[68] = 0xb4;
|
||||
ide->buffer[80] = 0x30; /*Supported ATA versions : ATA/ATAPI-4 ATA/ATAPI-5*/
|
||||
ide->buffer[81] = 0x15; /*Maximum ATA revision supported : ATA/ATAPI-5 T13 1321D revision 1*/
|
||||
} else {
|
||||
ide->buffer[51] = 120;
|
||||
ide->buffer[52] = 120;
|
||||
ide->buffer[53] = 2; /*Words 64-70 are valid*/
|
||||
ide->buffer[63] = 0x0003; /*Multi-word DMA 0 & 1*/
|
||||
ide->buffer[64] = 0x0001; /*PIO Mode 3*/
|
||||
ide->buffer[65] = 120;
|
||||
ide->buffer[66] = 120;
|
||||
ide->buffer[67] = 120;
|
||||
}
|
||||
|
||||
if (ide->mdma_mode != -1)
|
||||
{
|
||||
d = (ide->mdma_mode & 0xff);
|
||||
d <<= 8;
|
||||
if ((ide->mdma_mode & 0x300) == 0x200)
|
||||
ide->buffer[88] |= d;
|
||||
else
|
||||
else if ((ide->mdma_mode & 0x300) == 0x400) {
|
||||
if ((ide->mdma_mode & 0xff) >= 3)
|
||||
ide->buffer[64] |= d;
|
||||
} else
|
||||
ide->buffer[63] |= d;
|
||||
ide_log("PIDENTIFY DMA Mode: %04X, %04X\n", ide->buffer[62], ide->buffer[63]);
|
||||
}
|
||||
ide->buffer[65] = 0x96;
|
||||
ide->buffer[66] = 0x96;
|
||||
ide->buffer[67] = 0xb4;
|
||||
ide->buffer[68] = 0xb4;
|
||||
ide->buffer[80] = 0x30; /*Supported ATA versions : ATA/ATAPI-4 ATA/ATAPI-5*/
|
||||
ide->buffer[81] = 0x15; /*Maximum ATA revision supported : ATA/ATAPI-5 T13 1321D revision 1*/
|
||||
}
|
||||
}
|
||||
|
||||
@@ -651,14 +686,25 @@ static int ide_set_features(IDE *ide)
|
||||
if (ide_drive_is_zip(ide)) {
|
||||
bus = zip_drives[atapi_zip_drives[ide->channel]].bus_type;
|
||||
dma = (bus == ZIP_BUS_ATAPI_PIO_AND_DMA);
|
||||
max_pio = 0;
|
||||
if (!PCI || !dma || (ide->board >= 2))
|
||||
max_pio = 0;
|
||||
else
|
||||
max_pio = 3;
|
||||
max_mdma = 1;
|
||||
} else if (ide_drive_is_cdrom(ide)) {
|
||||
bus = cdrom_drives[atapi_cdrom_drives[ide->channel]].bus_type;
|
||||
dma = (bus == CDROM_BUS_ATAPI_PIO_AND_DMA);
|
||||
if (!PCI || !dma || (ide->board >= 2))
|
||||
max_pio = 0;
|
||||
else
|
||||
max_pio = 4;
|
||||
} else {
|
||||
bus = hdd[ide->hdd_num].bus;
|
||||
dma = (bus == HDD_BUS_IDE_PIO_AND_DMA);
|
||||
if (!PCI || !dma || (ide->board >= 2))
|
||||
max_pio = 0;
|
||||
else
|
||||
max_pio = 2;
|
||||
}
|
||||
|
||||
ide_log("Features code %02X\n", features);
|
||||
@@ -667,7 +713,7 @@ static int ide_set_features(IDE *ide)
|
||||
|
||||
switch(features)
|
||||
{
|
||||
case 0x03: /* Set transfer mode. */
|
||||
case FEATURE_SET_TRANSFER_MODE: /* Set transfer mode. */
|
||||
ide_log("Transfer mode %02X\n", features_data >> 3);
|
||||
|
||||
mode = (features_data >> 3);
|
||||
@@ -680,7 +726,7 @@ static int ide_set_features(IDE *ide)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
ide->mdma_mode = -1;
|
||||
ide->mdma_mode = (1 << submode) | 0x400;
|
||||
ide_log("IDE %02X: Setting DPIO mode: %02X, %08X\n", ide->channel, submode, ide->mdma_mode);
|
||||
break;
|
||||
|
||||
@@ -724,8 +770,17 @@ static int ide_set_features(IDE *ide)
|
||||
return 0;
|
||||
}
|
||||
|
||||
case 0x66: /* Disable reverting to power on defaults. */
|
||||
case 0xCC: /* Enable reverting to power on defaults. */
|
||||
case FEATURE_ENABLE_IRQ_OVERLAPPED:
|
||||
case FEATURE_ENABLE_IRQ_SERVICE:
|
||||
case FEATURE_DISABLE_IRQ_OVERLAPPED:
|
||||
case FEATURE_DISABLE_IRQ_SERVICE:
|
||||
if (!PCI || !dma || (ide->board >= 2))
|
||||
return 0;
|
||||
else
|
||||
return 1;
|
||||
|
||||
case FEATURE_DISABLE_REVERT: /* Disable reverting to power on defaults. */
|
||||
case FEATURE_ENABLE_REVERT: /* Enable reverting to power on defaults. */
|
||||
return 1;
|
||||
|
||||
default:
|
||||
@@ -1573,6 +1628,20 @@ uint32_t ide_read_data(int ide_board, int length)
|
||||
IDE *ide = &ide_drives[cur_ide[ide_board]];
|
||||
uint32_t temp;
|
||||
|
||||
if (!ide->buffer) {
|
||||
switch (length)
|
||||
{
|
||||
case 1:
|
||||
return 0xff;
|
||||
case 2:
|
||||
return 0xffff;
|
||||
case 4:
|
||||
return 0xffffffff;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t *idebufferb = (uint8_t *) ide->buffer;
|
||||
uint16_t *idebufferw = ide->buffer;
|
||||
uint32_t *idebufferl = (uint32_t *) ide->buffer;
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
* Implementation of the Iomega ZIP drive with SCSI(-like)
|
||||
* commands, for both ATAPI and SCSI usage.
|
||||
*
|
||||
* Version: @(#)zip.c 1.0.4 2018/03/08
|
||||
* Version: @(#)zip.c 1.0.5 2018/03/17
|
||||
*
|
||||
* Authors: Fred N. van Kempen, <decwiz@yahoo.com>
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
@@ -89,7 +89,7 @@ uint8_t scsi_zip_drives[16][8] = { { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0
|
||||
|
||||
|
||||
/* Table of all SCSI commands and their flags, needed for the new disc change / not ready handler. */
|
||||
uint8_t zip_command_flags[0x100] =
|
||||
static const uint8_t zip_command_flags[0x100] =
|
||||
{
|
||||
IMPLEMENTED | CHECK_READY | NONDATA, /* 0x00 */
|
||||
IMPLEMENTED | ALLOW_UA | NONDATA | SCSI_ONLY, /* 0x01 */
|
||||
@@ -1107,12 +1107,6 @@ static void zip_unit_attention(uint8_t id)
|
||||
zip_set_callback(id);
|
||||
zip_log("ZIP %i: UNIT ATTENTION\n", id);
|
||||
}
|
||||
|
||||
static void zip_bus_master_error(uint8_t id)
|
||||
{
|
||||
zip_sense_key = zip_asc = zip_ascq = 0;
|
||||
zip_cmd_error(id);
|
||||
}
|
||||
|
||||
static void zip_not_ready(uint8_t id)
|
||||
{
|
||||
@@ -2243,16 +2237,10 @@ int zip_read_from_ide_dma(uint8_t channel)
|
||||
if (id > ZIP_NUM)
|
||||
return 0;
|
||||
|
||||
if (ide_bus_master_write) {
|
||||
if (ide_bus_master_write(channel >> 1, zipbufferb, zip[id].packet_len)) {
|
||||
zip_bus_master_error(id);
|
||||
if (ide_bus_master_write) {
|
||||
if (ide_bus_master_write(channel >> 1, zipbufferb, zip[id].packet_len))
|
||||
return 0;
|
||||
return 0;
|
||||
else
|
||||
return 1;
|
||||
} else {
|
||||
zip_bus_master_error(id);
|
||||
zip_phase_callback(id);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -2271,6 +2259,12 @@ int zip_read_from_scsi_dma(uint8_t scsi_id, uint8_t scsi_lun)
|
||||
memcpy(zipbufferb, SCSIDevices[scsi_id][scsi_lun].CmdBuffer, *BufLen);
|
||||
return 1;
|
||||
}
|
||||
|
||||
void zip_irq_raise(uint8_t id)
|
||||
{
|
||||
if (zip_drives[id].bus_type < ZIP_BUS_SCSI)
|
||||
ide_irq_raise(&(ide_drives[zip_drives[id].ide_channel]));
|
||||
}
|
||||
|
||||
int zip_read_from_dma(uint8_t id)
|
||||
{
|
||||
@@ -2296,11 +2290,19 @@ int zip_read_from_dma(uint8_t id)
|
||||
zip_log("ZIP %i: ATAPI Input data length: %i\n", id, in_data_length);
|
||||
}
|
||||
|
||||
ret = zip_phase_data_out(id);
|
||||
if (!ret) {
|
||||
zip_phase_callback(id);
|
||||
return 0;
|
||||
} else
|
||||
ret = zip_phase_data_out(id);
|
||||
|
||||
if (ret || (zip_drives[id].bus_type == ZIP_BUS_SCSI)) {
|
||||
zip_buf_free(id);
|
||||
zip[id].packet_status = ZIP_PHASE_COMPLETE;
|
||||
zip[id].status = READY_STAT;
|
||||
zip[id].phase = 3;
|
||||
ui_sb_update_icon(SB_ZIP | id, 0);
|
||||
zip_irq_raise(id);
|
||||
if (ret)
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -2315,21 +2317,10 @@ int zip_write_to_ide_dma(uint8_t channel)
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (ide_bus_master_read) {
|
||||
if (ide_bus_master_read(channel >> 1, zipbufferb, zip[id].packet_len)) {
|
||||
zip_log("ZIP %i: ATAPI DMA error\n", id);
|
||||
zip_bus_master_error(id);
|
||||
if (ide_bus_master_read) {
|
||||
if (ide_bus_master_read(channel >> 1, zipbufferb, zip[id].packet_len))
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
return 0;
|
||||
else
|
||||
return 1;
|
||||
}
|
||||
} else {
|
||||
zip_log("ZIP %i: No bus master\n", id);
|
||||
zip_bus_master_error(id);
|
||||
zip_phase_callback(id);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -2360,16 +2351,20 @@ int zip_write_to_dma(uint8_t id)
|
||||
ret = zip_write_to_scsi_dma(zip_drives[id].scsi_device_id, zip_drives[id].scsi_device_lun);
|
||||
} else
|
||||
ret = zip_write_to_ide_dma(zip_drives[id].ide_channel);
|
||||
|
||||
if (!ret)
|
||||
|
||||
if (ret || (zip_drives[id].bus_type == ZIP_BUS_SCSI)) {
|
||||
zip_buf_free(id);
|
||||
zip[id].packet_status = ZIP_PHASE_COMPLETE;
|
||||
zip[id].status = READY_STAT;
|
||||
zip[id].phase = 3;
|
||||
ui_sb_update_icon(SB_ZIP | id, 0);
|
||||
zip_irq_raise(id);
|
||||
if (ret)
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void zip_irq_raise(uint8_t id)
|
||||
{
|
||||
if (zip_drives[id].bus_type < ZIP_BUS_SCSI)
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -2405,12 +2400,6 @@ void zip_phase_callback(uint8_t id)
|
||||
return;
|
||||
case ZIP_PHASE_DATA_OUT_DMA:
|
||||
zip_log("ZIP %i: ZIP_PHASE_DATA_OUT_DMA\n", id);
|
||||
zip_read_from_dma(id);
|
||||
zip_buf_free(id);
|
||||
zip[id].packet_status = ZIP_PHASE_COMPLETE;
|
||||
zip[id].status = READY_STAT;
|
||||
zip[id].phase = 3;
|
||||
ui_sb_update_icon(SB_ZIP | id, 0);
|
||||
zip_read_from_dma(id);
|
||||
return;
|
||||
case ZIP_PHASE_DATA_IN:
|
||||
@@ -2421,12 +2410,6 @@ void zip_phase_callback(uint8_t id)
|
||||
return;
|
||||
case ZIP_PHASE_DATA_IN_DMA:
|
||||
zip_log("ZIP %i: ZIP_PHASE_DATA_IN_DMA\n", id);
|
||||
zip_write_to_dma(id);
|
||||
zip_buf_free(id);
|
||||
zip[id].packet_status = ZIP_PHASE_COMPLETE;
|
||||
zip[id].status = READY_STAT;
|
||||
zip[id].phase = 3;
|
||||
ui_sb_update_icon(SB_ZIP | id, 0);
|
||||
zip_write_to_dma(id);
|
||||
return;
|
||||
case ZIP_PHASE_ERROR:
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*
|
||||
* Memory handling and MMU.
|
||||
*
|
||||
* Version: @(#)mem.c 1.0.6 2018/03/16
|
||||
* Version: @(#)mem.c 1.0.7 2018/03/17
|
||||
*
|
||||
* Authors: Fred N. van Kempen, <decwiz@yahoo.com>
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
@@ -1750,6 +1750,8 @@ mem_reset_page_blocks(void)
|
||||
void
|
||||
mem_reset_page_blocks(void)
|
||||
{
|
||||
int c;
|
||||
|
||||
if (pages == NULL) return;
|
||||
|
||||
for (c = 0; c < ((mem_size * 1024) >> 12); c++) {
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*
|
||||
* Implementation of the AudioPCI sound device.
|
||||
*
|
||||
* Version: @(#)snd_audiopci.c 1.0.4 2018/03/15
|
||||
* Version: @(#)snd_audiopci.c 1.0.5 2018/03/17
|
||||
*
|
||||
* Authors: Fred N. van Kempen, <decwiz@yahoo.com>
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
@@ -41,6 +41,7 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
#include <math.h>
|
||||
#define HAVE_STDARG_H
|
||||
#include "../emu.h"
|
||||
#include "../device.h"
|
||||
@@ -53,6 +54,12 @@
|
||||
#include "snd_audiopci.h"
|
||||
|
||||
|
||||
#define N 16
|
||||
|
||||
#define ES1371_NCoef 91
|
||||
|
||||
static float low_fir_es1371_coef[ES1371_NCoef];
|
||||
|
||||
typedef struct {
|
||||
uint8_t pci_command, pci_serr;
|
||||
|
||||
@@ -93,6 +100,9 @@ typedef struct {
|
||||
int16_t buffer_l[64], buffer_r[64];
|
||||
int buffer_pos, buffer_pos_end;
|
||||
|
||||
int filtered_l[32], filtered_r[32];
|
||||
int f_pos;
|
||||
|
||||
int16_t out_l, out_r;
|
||||
|
||||
int32_t vol_l, vol_r;
|
||||
@@ -528,6 +538,7 @@ static void es1371_outl(uint16_t port, uint32_t val, void *p)
|
||||
case 0x71:
|
||||
es1371->dac[0].vf = (es1371->dac[0].vf & ~0x1f8000) | ((val & 0xfc00) << 5);
|
||||
es1371->dac[0].ac = (es1371->dac[0].ac & ~0x7f8000) | ((val & 0x00ff) << 15);
|
||||
es1371->dac[0].f_pos = 0;
|
||||
break;
|
||||
case 0x72:
|
||||
es1371->dac[0].ac = (es1371->dac[0].ac & ~0x7fff) | (val & 0x7fff);
|
||||
@@ -539,6 +550,7 @@ static void es1371_outl(uint16_t port, uint32_t val, void *p)
|
||||
case 0x75:
|
||||
es1371->dac[1].vf = (es1371->dac[1].vf & ~0x1f8000) | ((val & 0xfc00) << 5);
|
||||
es1371->dac[1].ac = (es1371->dac[1].ac & ~0x7f8000) | ((val & 0x00ff) << 15);
|
||||
es1371->dac[1].f_pos = 0;
|
||||
break;
|
||||
case 0x76:
|
||||
es1371->dac[1].ac = (es1371->dac[1].ac & ~0x7fff) | (val & 0x7fff);
|
||||
@@ -1034,15 +1046,60 @@ static void es1371_fetch(es1371_t *es1371, int dac_nr)
|
||||
}
|
||||
}
|
||||
|
||||
static void es1371_next_sample(es1371_t *es1371, int dac_nr)
|
||||
static inline float low_fir_es1371(int dac_nr, int i, float NewSample)
|
||||
{
|
||||
static float x[2][2][128]; //input samples
|
||||
static int x_pos[2] = {0, 0};
|
||||
float out = 0.0;
|
||||
int read_pos;
|
||||
int n_coef;
|
||||
int pos = x_pos[dac_nr];
|
||||
|
||||
x[dac_nr][i][pos] = NewSample;
|
||||
|
||||
/*Since only 1/16th of input samples are non-zero, only filter those that
|
||||
are valid.*/
|
||||
read_pos = (pos + 15) & (127 & ~15);
|
||||
n_coef = (16 - pos) & 15;
|
||||
|
||||
while (n_coef < ES1371_NCoef)
|
||||
{
|
||||
out += low_fir_es1371_coef[n_coef] * x[dac_nr][i][read_pos];
|
||||
read_pos = (read_pos + 16) & (127 & ~15);
|
||||
n_coef += 16;
|
||||
}
|
||||
|
||||
if (i == 1)
|
||||
{
|
||||
x_pos[dac_nr] = (x_pos[dac_nr] + 1) & 127;
|
||||
if (x_pos[dac_nr] > 127)
|
||||
x_pos[dac_nr] = 0;
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
static void es1371_next_sample_filtered(es1371_t *es1371, int dac_nr, int out_idx)
|
||||
{
|
||||
int out_l, out_r;
|
||||
int c;
|
||||
|
||||
if ((es1371->dac[dac_nr].buffer_pos - es1371->dac[dac_nr].buffer_pos_end) >= 0)
|
||||
{
|
||||
es1371_fetch(es1371, dac_nr);
|
||||
}
|
||||
|
||||
es1371->dac[dac_nr].out_l = es1371->dac[dac_nr].buffer_l[es1371->dac[dac_nr].buffer_pos & 63];
|
||||
es1371->dac[dac_nr].out_r = es1371->dac[dac_nr].buffer_r[es1371->dac[dac_nr].buffer_pos & 63];
|
||||
out_l = es1371->dac[dac_nr].buffer_l[es1371->dac[dac_nr].buffer_pos & 63];
|
||||
out_r = es1371->dac[dac_nr].buffer_r[es1371->dac[dac_nr].buffer_pos & 63];
|
||||
|
||||
es1371->dac[dac_nr].filtered_l[out_idx] = (int)low_fir_es1371(dac_nr, 0, (float)out_l);
|
||||
es1371->dac[dac_nr].filtered_r[out_idx] = (int)low_fir_es1371(dac_nr, 1, (float)out_r);
|
||||
for (c = 1; c < 16; c++)
|
||||
{
|
||||
es1371->dac[dac_nr].filtered_l[out_idx+c] = (int)low_fir_es1371(dac_nr, 0, 0);
|
||||
es1371->dac[dac_nr].filtered_r[out_idx+c] = (int)low_fir_es1371(dac_nr, 1, 0);
|
||||
}
|
||||
|
||||
// audiopci_log("Use %02x %04x %04x\n", es1371->dac[dac_nr].buffer_pos & 63, es1371->dac[dac_nr].out_l, es1371->dac[dac_nr].out_r);
|
||||
|
||||
es1371->dac[dac_nr].buffer_pos++;
|
||||
@@ -1050,20 +1107,64 @@ static void es1371_next_sample(es1371_t *es1371, int dac_nr)
|
||||
}
|
||||
|
||||
//static FILE *es1371_f;//,*es1371_f2;
|
||||
|
||||
static void es1371_update(es1371_t *es1371)
|
||||
{
|
||||
int32_t l, r;
|
||||
|
||||
l = (es1371->dac[0].out_l * es1371->dac[0].vol_l) >> 12;
|
||||
l += ((es1371->dac[1].out_l * es1371->dac[1].vol_l) >> 12);
|
||||
r = (es1371->dac[0].out_r * es1371->dac[0].vol_r) >> 12;
|
||||
r += ((es1371->dac[1].out_r * es1371->dac[1].vol_r) >> 12);
|
||||
|
||||
l >>= 1;
|
||||
r >>= 1;
|
||||
|
||||
l = (l * es1371->master_vol_l) >> 15;
|
||||
r = (r * es1371->master_vol_r) >> 15;
|
||||
|
||||
if (l < -32768)
|
||||
l = -32768;
|
||||
else if (l > 32767)
|
||||
l = 32767;
|
||||
if (r < -32768)
|
||||
r = -32768;
|
||||
else if (r > 32767)
|
||||
r = 32767;
|
||||
|
||||
for (; es1371->pos < sound_pos_global; es1371->pos++)
|
||||
{
|
||||
es1371->buffer[es1371->pos*2] = l;
|
||||
es1371->buffer[es1371->pos*2 + 1] = r;
|
||||
}
|
||||
}
|
||||
|
||||
static void es1371_poll(void *p)
|
||||
{
|
||||
es1371_t *es1371 = (es1371_t *)p;
|
||||
|
||||
es1371->dac[1].time += es1371->dac[1].latch;
|
||||
|
||||
es1371_update(es1371);
|
||||
|
||||
if (es1371->int_ctrl & INT_DAC1_EN)
|
||||
{
|
||||
int frac = es1371->dac[0].ac & 0x7fff;
|
||||
int idx = es1371->dac[0].ac >> 15;
|
||||
int samp1_l = es1371->dac[0].filtered_l[idx];
|
||||
int samp1_r = es1371->dac[0].filtered_r[idx];
|
||||
int samp2_l = es1371->dac[0].filtered_l[(idx + 1) & 31];
|
||||
int samp2_r = es1371->dac[0].filtered_r[(idx + 1) & 31];
|
||||
|
||||
es1371->dac[0].out_l = ((samp1_l * (0x8000 - frac)) + (samp2_l * frac)) >> 15;
|
||||
es1371->dac[0].out_r = ((samp1_r * (0x8000 - frac)) + (samp2_r * frac)) >> 15;
|
||||
// audiopci_log("1Samp %i %i %08x\n", es1371->dac[0].curr_samp_ct, es1371->dac[0].samp_ct, es1371->dac[0].ac);
|
||||
es1371->dac[0].ac += es1371->dac[0].vf;
|
||||
if (es1371->dac[0].ac & (~0 << (15+4)))
|
||||
es1371->dac[0].ac += es1371->dac[0].vf;
|
||||
es1371->dac[0].ac &= ((32 << 15) - 1);
|
||||
if ((es1371->dac[0].ac >> (15+4)) != es1371->dac[0].f_pos)
|
||||
{
|
||||
es1371->dac[0].ac &= ~(~0 << (15+4));
|
||||
es1371_next_sample(es1371, 0);
|
||||
es1371_next_sample_filtered(es1371, 0, es1371->dac[0].f_pos ? 16 : 0);
|
||||
es1371->dac[0].f_pos = (es1371->dac[0].f_pos + 1) & 1;
|
||||
|
||||
es1371->dac[0].curr_samp_ct++;
|
||||
if (es1371->dac[0].curr_samp_ct == es1371->dac[0].samp_ct)
|
||||
@@ -1081,51 +1182,35 @@ static void es1371_poll(void *p)
|
||||
|
||||
if (es1371->int_ctrl & INT_DAC2_EN)
|
||||
{
|
||||
int frac = es1371->dac[1].ac & 0x7fff;
|
||||
int idx = es1371->dac[1].ac >> 15;
|
||||
int samp1_l = es1371->dac[1].filtered_l[idx];
|
||||
int samp1_r = es1371->dac[1].filtered_r[idx];
|
||||
int samp2_l = es1371->dac[1].filtered_l[(idx + 1) & 31];
|
||||
int samp2_r = es1371->dac[1].filtered_r[(idx + 1) & 31];
|
||||
|
||||
es1371->dac[1].out_l = ((samp1_l * (0x8000 - frac)) + (samp2_l * frac)) >> 15;
|
||||
es1371->dac[1].out_r = ((samp1_r * (0x8000 - frac)) + (samp2_r * frac)) >> 15;
|
||||
// audiopci_log("2Samp %i %i %08x\n", es1371->dac[1].curr_samp_ct, es1371->dac[1].samp_ct, es1371->dac[1].ac);
|
||||
es1371->dac[1].ac += es1371->dac[1].vf;
|
||||
if (es1371->dac[1].ac & (~0 << (15+4)))
|
||||
es1371->dac[1].ac &= ((32 << 15) - 1);
|
||||
if ((es1371->dac[1].ac >> (15+4)) != es1371->dac[1].f_pos)
|
||||
{
|
||||
es1371->dac[1].ac &= ~(~0 << (15+4));
|
||||
es1371_next_sample(es1371, 1);
|
||||
es1371_next_sample_filtered(es1371, 1, es1371->dac[1].f_pos ? 16 : 0);
|
||||
es1371->dac[1].f_pos = (es1371->dac[1].f_pos + 1) & 1;
|
||||
|
||||
es1371->dac[1].curr_samp_ct++;
|
||||
if (es1371->dac[1].curr_samp_ct > es1371->dac[1].samp_ct)
|
||||
{
|
||||
es1371->dac[1].curr_samp_ct = 0;
|
||||
// es1371->dac[1].curr_samp_ct = 0;
|
||||
// audiopci_log("DAC2 IRQ\n");
|
||||
es1371->int_status |= INT_STATUS_DAC2;
|
||||
es1371_update_irqs(es1371);
|
||||
}
|
||||
if (es1371->dac[1].curr_samp_ct > es1371->dac[1].samp_ct)
|
||||
es1371->dac[1].curr_samp_ct = 0;
|
||||
}
|
||||
}
|
||||
|
||||
for (; es1371->pos < sound_pos_global; es1371->pos++)
|
||||
{
|
||||
int32_t l, r;
|
||||
|
||||
l = (es1371->dac[0].out_l * es1371->dac[0].vol_l) >> 12;
|
||||
l += ((es1371->dac[1].out_l * es1371->dac[1].vol_l) >> 12);
|
||||
r = (es1371->dac[0].out_r * es1371->dac[0].vol_r) >> 12;
|
||||
r += ((es1371->dac[1].out_r * es1371->dac[1].vol_r) >> 12);
|
||||
|
||||
l >>= 1;
|
||||
r >>= 1;
|
||||
|
||||
l = (l * es1371->master_vol_l) >> 15;
|
||||
r = (r * es1371->master_vol_r) >> 15;
|
||||
|
||||
if (l < -32768)
|
||||
l = -32768;
|
||||
else if (l > 32767)
|
||||
l = 32767;
|
||||
if (r < -32768)
|
||||
r = -32768;
|
||||
else if (r > 32767)
|
||||
r = 32767;
|
||||
|
||||
es1371->buffer[es1371->pos*2] = l;
|
||||
es1371->buffer[es1371->pos*2 + 1] = r;
|
||||
}
|
||||
}
|
||||
|
||||
static void es1371_get_buffer(int32_t *buffer, int len, void *p)
|
||||
@@ -1133,12 +1218,48 @@ static void es1371_get_buffer(int32_t *buffer, int len, void *p)
|
||||
es1371_t *es1371 = (es1371_t *)p;
|
||||
int c;
|
||||
|
||||
es1371_update(es1371);
|
||||
|
||||
for (c = 0; c < len * 2; c++)
|
||||
buffer[c] += (es1371->buffer[c] / 2);
|
||||
|
||||
es1371->pos = 0;
|
||||
}
|
||||
|
||||
static inline double sinc(double x)
|
||||
{
|
||||
return sin(M_PI * x) / (M_PI * x);
|
||||
}
|
||||
|
||||
static void generate_es1371_filter()
|
||||
{
|
||||
/*Cutoff frequency = 1 / 32*/
|
||||
float fC = 1.0 / 32.0;
|
||||
float gain;
|
||||
int n;
|
||||
|
||||
for (n = 0; n < ES1371_NCoef; n++)
|
||||
{
|
||||
/*Blackman window*/
|
||||
double w = 0.42 - (0.5 * cos((2.0*n*M_PI)/(double)(ES1371_NCoef-1))) + (0.08 * cos((4.0*n*M_PI)/(double)(ES1371_NCoef-1)));
|
||||
/*Sinc filter*/
|
||||
double h = sinc(2.0 * fC * ((double)n - ((double)(ES1371_NCoef-1) / 2.0)));
|
||||
|
||||
/*Create windowed-sinc filter*/
|
||||
low_fir_es1371_coef[n] = w * h;
|
||||
}
|
||||
|
||||
low_fir_es1371_coef[(ES1371_NCoef - 1) / 2] = 1.0;
|
||||
|
||||
gain = 0.0;
|
||||
for (n = 0; n < ES1371_NCoef; n++)
|
||||
gain += low_fir_es1371_coef[n] / (float)N;
|
||||
|
||||
/*Normalise filter, to produce unity gain*/
|
||||
for (n = 0; n < ES1371_NCoef; n++)
|
||||
low_fir_es1371_coef[n] /= gain;
|
||||
}
|
||||
|
||||
static void *es1371_init(const device_t *info)
|
||||
{
|
||||
es1371_t *es1371 = malloc(sizeof(es1371_t));
|
||||
@@ -1149,6 +1270,8 @@ static void *es1371_init(const device_t *info)
|
||||
es1371->card = pci_add_card(PCI_ADD_NORMAL, es1371_pci_read, es1371_pci_write, es1371);
|
||||
|
||||
timer_add(es1371_poll, &es1371->dac[1].time, TIMER_ALWAYS_ENABLED, es1371);
|
||||
|
||||
generate_es1371_filter();
|
||||
|
||||
return es1371;
|
||||
}
|
||||
@@ -1166,6 +1289,54 @@ static void es1371_speed_changed(void *p)
|
||||
|
||||
es1371->dac[1].latch = (int)((double)TIMER_USEC * (1000000.0 / 48000.0));
|
||||
}
|
||||
|
||||
void es1371_add_status_info_dac(es1371_t *es1371, char *s, int max_len, int dac_nr)
|
||||
{
|
||||
int ena = dac_nr ? INT_DAC2_EN : INT_DAC1_EN;
|
||||
char *dac_name = dac_nr ? "DAC2 (Wave)" : "DAC1 (MIDI)";
|
||||
char temps[128];
|
||||
|
||||
if (es1371->int_ctrl & ena)
|
||||
{
|
||||
int format = dac_nr ? ((es1371->si_cr >> 2) & 3) : (es1371->si_cr & 3);
|
||||
double freq = 48000.0 * ((double)es1371->dac[dac_nr].vf / (32768.0 * 16.0));
|
||||
|
||||
switch (format)
|
||||
{
|
||||
case FORMAT_MONO_8:
|
||||
snprintf(temps, 128, "%s format : 8-bit mono\n", dac_name);
|
||||
break;
|
||||
case FORMAT_STEREO_8:
|
||||
snprintf(temps, 128, "%s format : 8-bit stereo\n", dac_name);
|
||||
break;
|
||||
case FORMAT_MONO_16:
|
||||
snprintf(temps, 128, "%s format : 16-bit mono\n", dac_name);
|
||||
break;
|
||||
case FORMAT_STEREO_16:
|
||||
snprintf(temps, 128, "%s format : 16-bit stereo\n", dac_name);
|
||||
break;
|
||||
}
|
||||
|
||||
strncat(s, temps, max_len);
|
||||
max_len -= strlen(temps);
|
||||
|
||||
snprintf(temps, 128, "Playback frequency : %i Hz\n", (int)freq);
|
||||
strncat(s, temps, max_len);
|
||||
}
|
||||
else
|
||||
{
|
||||
snprintf(temps, max_len, "%s stopped\n", dac_name);
|
||||
strncat(s, temps, max_len);
|
||||
}
|
||||
}
|
||||
|
||||
void es1371_add_status_info(char *s, int max_len, void *p)
|
||||
{
|
||||
es1371_t *es1371 = (es1371_t *)p;
|
||||
|
||||
es1371_add_status_info_dac(es1371, s, max_len, 0);
|
||||
es1371_add_status_info_dac(es1371, s, max_len, 1);
|
||||
}
|
||||
|
||||
const device_t es1371_device =
|
||||
{
|
||||
@@ -1178,6 +1349,6 @@ const device_t es1371_device =
|
||||
NULL,
|
||||
es1371_speed_changed,
|
||||
NULL,
|
||||
NULL,
|
||||
es1371_add_status_info,
|
||||
NULL
|
||||
};
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*
|
||||
* ATI 18800 emulation (VGA Edge-16)
|
||||
*
|
||||
* Version: @(#)vid_ati18800.c 1.0.3 2018/03/15
|
||||
* Version: @(#)vid_ati18800.c 1.0.4 2018/03/17
|
||||
*
|
||||
* Authors: Fred N. van Kempen, <decwiz@yahoo.com>
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
@@ -51,6 +51,7 @@
|
||||
#include "vid_ati18800.h"
|
||||
#include "vid_ati_eeprom.h"
|
||||
#include "vid_svga.h"
|
||||
#include "vid_svga_render.h"
|
||||
|
||||
|
||||
#define BIOS_ROM_PATH_WONDER L"roms/video/ati/ati18800/vga_wonder_v3-1.02.bin"
|
||||
@@ -169,6 +170,39 @@ static uint8_t ati18800_in(uint16_t addr, void *p)
|
||||
case 0x3D5:
|
||||
temp = svga->crtc[svga->crtcreg];
|
||||
break;
|
||||
case 0x3DA:
|
||||
svga->attrff = 0;
|
||||
svga->attrff = 0;
|
||||
svga->cgastat &= ~0x30;
|
||||
/* copy color diagnostic info from the overscan color register */
|
||||
switch (svga->attrregs[0x12] & 0x30)
|
||||
{
|
||||
case 0x00: /* P0 and P2 */
|
||||
if (svga->attrregs[0x11] & 0x01)
|
||||
svga->cgastat |= 0x10;
|
||||
if (svga->attrregs[0x11] & 0x04)
|
||||
svga->cgastat |= 0x20;
|
||||
break;
|
||||
case 0x10: /* P4 and P5 */
|
||||
if (svga->attrregs[0x11] & 0x10)
|
||||
svga->cgastat |= 0x10;
|
||||
if (svga->attrregs[0x11] & 0x20)
|
||||
svga->cgastat |= 0x20;
|
||||
break;
|
||||
case 0x20: /* P1 and P3 */
|
||||
if (svga->attrregs[0x11] & 0x02)
|
||||
svga->cgastat |= 0x10;
|
||||
if (svga->attrregs[0x11] & 0x08)
|
||||
svga->cgastat |= 0x20;
|
||||
break;
|
||||
case 0x30: /* P6 and P7 */
|
||||
if (svga->attrregs[0x11] & 0x40)
|
||||
svga->cgastat |= 0x10;
|
||||
if (svga->attrregs[0x11] & 0x80)
|
||||
svga->cgastat |= 0x20;
|
||||
break;
|
||||
}
|
||||
return svga->cgastat;
|
||||
default:
|
||||
temp = svga_in(addr, svga);
|
||||
break;
|
||||
@@ -179,6 +213,28 @@ static uint8_t ati18800_in(uint16_t addr, void *p)
|
||||
return temp;
|
||||
}
|
||||
|
||||
static void ati18800_recalctimings(svga_t *svga)
|
||||
{
|
||||
ati18800_t *ati18800 = (ati18800_t *)svga->p;
|
||||
|
||||
if(svga->crtc[0x17] & 4)
|
||||
{
|
||||
svga->vtotal <<= 1;
|
||||
svga->dispend <<= 1;
|
||||
svga->vsyncstart <<= 1;
|
||||
svga->split <<= 1;
|
||||
svga->vblankstart <<= 1;
|
||||
}
|
||||
|
||||
if (!svga->scrblank && (ati18800->regs[0xb0] & 0x20)) /*Extended 256 colour modes*/
|
||||
{
|
||||
svga->render = svga_render_8bpp_highres;
|
||||
svga->bpp = 8;
|
||||
svga->rowoffset <<= 1;
|
||||
svga->ma <<= 1;
|
||||
}
|
||||
}
|
||||
|
||||
static void *ati18800_init(const device_t *info)
|
||||
{
|
||||
ati18800_t *ati18800 = malloc(sizeof(ati18800_t));
|
||||
@@ -198,7 +254,7 @@ static void *ati18800_init(const device_t *info)
|
||||
};
|
||||
|
||||
svga_init(&ati18800->svga, ati18800, 1 << 19, /*512kb*/
|
||||
NULL,
|
||||
ati18800_recalctimings,
|
||||
ati18800_in, ati18800_out,
|
||||
NULL,
|
||||
NULL);
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*
|
||||
* ATI 28800 emulation (VGA Charger and Korean VGA)
|
||||
*
|
||||
* Version: @(#)vid_ati28800.c 1.0.6 2018/03/15
|
||||
* Version: @(#)vid_ati28800.c 1.0.7 2018/03/17
|
||||
*
|
||||
* Authors: Fred N. van Kempen, <decwiz@yahoo.com>
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
@@ -268,6 +268,39 @@ static uint8_t ati28800_in(uint16_t addr, void *p)
|
||||
case 0x3D5:
|
||||
temp = svga->crtc[svga->crtcreg];
|
||||
break;
|
||||
case 0x3DA:
|
||||
svga->attrff = 0;
|
||||
svga->attrff = 0;
|
||||
svga->cgastat &= ~0x30;
|
||||
/* copy color diagnostic info from the overscan color register */
|
||||
switch (svga->attrregs[0x12] & 0x30)
|
||||
{
|
||||
case 0x00: /* P0 and P2 */
|
||||
if (svga->attrregs[0x11] & 0x01)
|
||||
svga->cgastat |= 0x10;
|
||||
if (svga->attrregs[0x11] & 0x04)
|
||||
svga->cgastat |= 0x20;
|
||||
break;
|
||||
case 0x10: /* P4 and P5 */
|
||||
if (svga->attrregs[0x11] & 0x10)
|
||||
svga->cgastat |= 0x10;
|
||||
if (svga->attrregs[0x11] & 0x20)
|
||||
svga->cgastat |= 0x20;
|
||||
break;
|
||||
case 0x20: /* P1 and P3 */
|
||||
if (svga->attrregs[0x11] & 0x02)
|
||||
svga->cgastat |= 0x10;
|
||||
if (svga->attrregs[0x11] & 0x08)
|
||||
svga->cgastat |= 0x20;
|
||||
break;
|
||||
case 0x30: /* P6 and P7 */
|
||||
if (svga->attrregs[0x11] & 0x40)
|
||||
svga->cgastat |= 0x10;
|
||||
if (svga->attrregs[0x11] & 0x80)
|
||||
svga->cgastat |= 0x20;
|
||||
break;
|
||||
}
|
||||
return svga->cgastat;
|
||||
default:
|
||||
temp = svga_in(addr, svga);
|
||||
break;
|
||||
@@ -295,7 +328,7 @@ static uint8_t ati28800k_in(uint16_t addr, void *p)
|
||||
switch(get_korean_font_kind >> 8)
|
||||
{
|
||||
case 4: /* ROM font */
|
||||
temp = fontdatksc5601[get_korean_font_base][get_korean_font_index++];
|
||||
temp = fontdatksc5601[get_korean_font_base].chr[get_korean_font_index++];
|
||||
break;
|
||||
case 2: /* User defined font - TODO : Should be implemented later */
|
||||
temp = 0;
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*
|
||||
* ATi Mach64 graphics card emulation.
|
||||
*
|
||||
* Version: @(#)vid_ati_mach64.c 1.0.6 2018/03/15
|
||||
* Version: @(#)vid_ati_mach64.c 1.0.7 2018/03/17
|
||||
*
|
||||
* Authors: Fred N. van Kempen, <decwiz@yahoo.com>
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
@@ -194,6 +194,7 @@ typedef struct mach64_t
|
||||
|
||||
uint32_t linear_base, old_linear_base;
|
||||
uint32_t io_base;
|
||||
int draw_pixel;
|
||||
|
||||
struct
|
||||
{
|
||||
@@ -310,6 +311,7 @@ enum
|
||||
{
|
||||
SRC_PATT_EN = 1,
|
||||
SRC_PATT_ROT_EN = 2,
|
||||
SRC_BYTE_ALIGN = 3,
|
||||
SRC_LINEAR_EN = 4
|
||||
};
|
||||
|
||||
@@ -449,6 +451,39 @@ uint8_t mach64_in(uint16_t addr, void *p)
|
||||
if (svga->crtcreg > 0x18)
|
||||
return 0xff;
|
||||
return svga->crtc[svga->crtcreg];
|
||||
case 0x3DA:
|
||||
svga->attrff = 0;
|
||||
svga->attrff = 0;
|
||||
svga->cgastat &= ~0x30;
|
||||
/* copy color diagnostic info from the overscan color register */
|
||||
switch (svga->attrregs[0x12] & 0x30)
|
||||
{
|
||||
case 0x00: /* P0 and P2 */
|
||||
if (svga->attrregs[0x11] & 0x01)
|
||||
svga->cgastat |= 0x10;
|
||||
if (svga->attrregs[0x11] & 0x04)
|
||||
svga->cgastat |= 0x20;
|
||||
break;
|
||||
case 0x10: /* P4 and P5 */
|
||||
if (svga->attrregs[0x11] & 0x10)
|
||||
svga->cgastat |= 0x10;
|
||||
if (svga->attrregs[0x11] & 0x20)
|
||||
svga->cgastat |= 0x20;
|
||||
break;
|
||||
case 0x20: /* P1 and P3 */
|
||||
if (svga->attrregs[0x11] & 0x02)
|
||||
svga->cgastat |= 0x10;
|
||||
if (svga->attrregs[0x11] & 0x08)
|
||||
svga->cgastat |= 0x20;
|
||||
break;
|
||||
case 0x30: /* P6 and P7 */
|
||||
if (svga->attrregs[0x11] & 0x40)
|
||||
svga->cgastat |= 0x10;
|
||||
if (svga->attrregs[0x11] & 0x80)
|
||||
svga->cgastat |= 0x20;
|
||||
break;
|
||||
}
|
||||
return svga->cgastat;
|
||||
}
|
||||
return svga_in(addr, svga);
|
||||
}
|
||||
@@ -476,36 +511,41 @@ void mach64_recalctimings(svga_t *svga)
|
||||
svga->render = mach64->ramdac.render;
|
||||
switch ((mach64->crtc_gen_cntl >> 8) & 7)
|
||||
{
|
||||
case 1:
|
||||
case 1:
|
||||
mach64->draw_pixel = 4;
|
||||
if (mach64->type != MACH64_GX)
|
||||
svga->render = svga_render_4bpp_highres;
|
||||
svga->render = svga_render_4bpp_highres;
|
||||
svga->hdisp *= 8;
|
||||
break;
|
||||
case 2:
|
||||
case 2:
|
||||
mach64->draw_pixel = 8;
|
||||
if (mach64->type != MACH64_GX)
|
||||
svga->render = svga_render_8bpp_highres;
|
||||
svga->render = svga_render_8bpp_highres;
|
||||
svga->hdisp *= 8;
|
||||
svga->rowoffset /= 2;
|
||||
break;
|
||||
case 3:
|
||||
case 3:
|
||||
mach64->draw_pixel = 16;
|
||||
if (mach64->type != MACH64_GX)
|
||||
svga->render = svga_render_15bpp_highres;
|
||||
svga->render = svga_render_15bpp_highres;
|
||||
svga->hdisp *= 8;
|
||||
break;
|
||||
case 4:
|
||||
case 4:
|
||||
mach64->draw_pixel = 16;
|
||||
if (mach64->type != MACH64_GX)
|
||||
svga->render = svga_render_16bpp_highres;
|
||||
svga->render = svga_render_16bpp_highres;
|
||||
svga->hdisp *= 8;
|
||||
break;
|
||||
case 5:
|
||||
case 5:
|
||||
if (mach64->type != MACH64_GX)
|
||||
svga->render = svga_render_24bpp_highres;
|
||||
svga->render = svga_render_24bpp_highres;
|
||||
svga->hdisp *= 8;
|
||||
svga->rowoffset = (svga->rowoffset * 3) / 2;
|
||||
break;
|
||||
case 6:
|
||||
case 6:
|
||||
mach64->draw_pixel = 32;
|
||||
if (mach64->type != MACH64_GX)
|
||||
svga->render = svga_render_32bpp_highres;
|
||||
svga->render = svga_render_32bpp_highres;
|
||||
svga->hdisp *= 8;
|
||||
svga->rowoffset *= 2;
|
||||
break;
|
||||
@@ -663,11 +703,7 @@ static void mach64_accel_write_fifo(mach64_t *mach64, uint32_t addr, uint8_t val
|
||||
(addr & 0x3ff) == 0x113) && !(val & 0x80))
|
||||
{
|
||||
mach64_start_fill(mach64);
|
||||
#ifdef MACH64_DEBUG
|
||||
pclog("%i %i %i %i %i %08x\n", (mach64->dst_height_width & 0x7ff), (mach64->dst_height_width & 0x7ff0000),
|
||||
((mach64->dp_src & 7) != SRC_HOST), (((mach64->dp_src >> 8) & 7) != SRC_HOST),
|
||||
(((mach64->dp_src >> 16) & 3) != MONO_SRC_HOST), mach64->dp_src);
|
||||
#endif
|
||||
|
||||
if ((mach64->dst_height_width & 0x7ff) && (mach64->dst_height_width & 0x7ff0000) &&
|
||||
((mach64->dp_src & 7) != SRC_HOST) && (((mach64->dp_src >> 8) & 7) != SRC_HOST) &&
|
||||
(((mach64->dp_src >> 16) & 3) != MONO_SRC_HOST))
|
||||
@@ -971,7 +1007,7 @@ void mach64_cursor_dump(mach64_t *mach64)
|
||||
void mach64_start_fill(mach64_t *mach64)
|
||||
{
|
||||
int x, y;
|
||||
|
||||
|
||||
mach64->accel.dst_x = 0;
|
||||
mach64->accel.dst_y = 0;
|
||||
mach64->accel.dst_x_start = (mach64->dst_y_x >> 16) & 0xfff;
|
||||
@@ -980,19 +1016,26 @@ void mach64_start_fill(mach64_t *mach64)
|
||||
mach64->accel.dst_width = (mach64->dst_height_width >> 16) & 0x1fff;
|
||||
mach64->accel.dst_height = mach64->dst_height_width & 0x1fff;
|
||||
|
||||
/*
|
||||
if ((((mach64->dp_src >> 16) & 7) == MONO_SRC_BLITSRC))
|
||||
{
|
||||
pclog("Byte Align set=%02x\n", mach64->dp_pix_width & DP_BYTE_PIX_ORDER);
|
||||
}
|
||||
*/
|
||||
|
||||
if (((mach64->dp_src >> 16) & 7) == MONO_SRC_BLITSRC)
|
||||
{
|
||||
if (mach64->accel.dst_width & 7)
|
||||
if (mach64->accel.dst_width & 7)
|
||||
mach64->accel.dst_width = (mach64->accel.dst_width & ~7) + 8;
|
||||
}
|
||||
|
||||
mach64->accel.x_count = mach64->accel.dst_width;
|
||||
mach64->accel.x_count = mach64->accel.dst_width;
|
||||
|
||||
mach64->accel.src_x = 0;
|
||||
mach64->accel.src_x = 0;
|
||||
mach64->accel.src_y = 0;
|
||||
mach64->accel.src_x_start = (mach64->src_y_x >> 16) & 0xfff;
|
||||
mach64->accel.src_y_start = mach64->src_y_x & 0xfff;
|
||||
if (mach64->src_cntl & SRC_LINEAR_EN)
|
||||
if (mach64->src_cntl & (SRC_LINEAR_EN|SRC_BYTE_ALIGN))
|
||||
mach64->accel.src_x_count = 0x7ffffff; /*Essentially infinite*/
|
||||
else
|
||||
mach64->accel.src_x_count = (mach64->src_height1_width1 >> 16) & 0x7fff;
|
||||
@@ -1002,36 +1045,27 @@ void mach64_start_fill(mach64_t *mach64)
|
||||
mach64->accel.src_y_count = mach64->src_height1_width1 & 0x1fff;
|
||||
|
||||
mach64->accel.src_width1 = (mach64->src_height1_width1 >> 16) & 0x7fff;
|
||||
mach64->accel.src_height1 = mach64->src_height1_width1 & 0x1fff;
|
||||
mach64->accel.src_height1 = mach64->src_height1_width1 & 0x1fff;
|
||||
mach64->accel.src_width2 = (mach64->src_height2_width2 >> 16) & 0x7fff;
|
||||
mach64->accel.src_height2 = mach64->src_height2_width2 & 0x1fff;
|
||||
mach64->accel.src_height2 = mach64->src_height2_width2 & 0x1fff;
|
||||
|
||||
#ifdef MACH64_DEBUG
|
||||
pclog("src %i %i %i %i %08X %08X\n", mach64->accel.src_x_count,
|
||||
mach64->accel.src_y_count,
|
||||
mach64->accel.src_width1,
|
||||
mach64->accel.src_height1,
|
||||
mach64->src_height1_width1,
|
||||
mach64->src_height2_width2);
|
||||
#endif
|
||||
|
||||
mach64->accel.src_pitch = (mach64->src_off_pitch >> 22) * 8;
|
||||
mach64->accel.src_offset = (mach64->src_off_pitch & 0xfffff) * 8;
|
||||
mach64->accel.src_offset = (mach64->src_off_pitch & 0xfffff) * 8;
|
||||
|
||||
mach64->accel.dst_pitch = (mach64->dst_off_pitch >> 22) * 8;
|
||||
mach64->accel.dst_offset = (mach64->dst_off_pitch & 0xfffff) * 8;
|
||||
|
||||
|
||||
mach64->accel.mix_fg = (mach64->dp_mix >> 16) & 0x1f;
|
||||
mach64->accel.mix_bg = mach64->dp_mix & 0x1f;
|
||||
|
||||
|
||||
mach64->accel.source_bg = mach64->dp_src & 7;
|
||||
mach64->accel.source_fg = (mach64->dp_src >> 8) & 7;
|
||||
mach64->accel.source_mix = (mach64->dp_src >> 16) & 7;
|
||||
|
||||
|
||||
mach64->accel.dst_pix_width = mach64->dp_pix_width & 7;
|
||||
mach64->accel.src_pix_width = (mach64->dp_pix_width >> 8) & 7;
|
||||
mach64->accel.host_pix_width = (mach64->dp_pix_width >> 16) & 7;
|
||||
|
||||
|
||||
mach64->accel.dst_size = mach64_width[mach64->accel.dst_pix_width];
|
||||
mach64->accel.src_size = mach64_width[mach64->accel.src_pix_width];
|
||||
mach64->accel.host_size = mach64_width[mach64->accel.host_pix_width];
|
||||
@@ -1040,18 +1074,17 @@ void mach64_start_fill(mach64_t *mach64)
|
||||
mach64->accel.src_offset <<= 3;
|
||||
else
|
||||
mach64->accel.src_offset >>= mach64->accel.src_size;
|
||||
|
||||
|
||||
if (mach64->accel.dst_size == WIDTH_1BIT)
|
||||
mach64->accel.dst_offset <<= 3;
|
||||
else
|
||||
mach64->accel.dst_offset >>= mach64->accel.dst_size;
|
||||
|
||||
|
||||
mach64->accel.xinc = (mach64->dst_cntl & DST_X_DIR) ? 1 : -1;
|
||||
mach64->accel.yinc = (mach64->dst_cntl & DST_Y_DIR) ? 1 : -1;
|
||||
|
||||
mach64->accel.yinc = (mach64->dst_cntl & DST_Y_DIR) ? 1 : -1;
|
||||
|
||||
mach64->accel.source_host = ((mach64->dp_src & 7) == SRC_HOST) || (((mach64->dp_src >> 8) & 7) == SRC_HOST);
|
||||
|
||||
|
||||
|
||||
for (y = 0; y < 8; y++)
|
||||
{
|
||||
for (x = 0; x < 8; x++)
|
||||
@@ -1060,36 +1093,30 @@ void mach64_start_fill(mach64_t *mach64)
|
||||
mach64->accel.pattern[y][x] = (temp >> (x + ((y & 3) * 8))) & 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
mach64->accel.sc_left = mach64->sc_left_right & 0x1fff;
|
||||
mach64->accel.sc_right = (mach64->sc_left_right >> 16) & 0x1fff;
|
||||
mach64->accel.sc_top = mach64->sc_top_bottom & 0x7fff;
|
||||
mach64->accel.sc_bottom = (mach64->sc_top_bottom >> 16) & 0x7fff;
|
||||
|
||||
/* mach64->accel.sc_left *= mach64_inc[mach64->accel.dst_pix_width];
|
||||
mach64->accel.sc_right *= mach64_inc[mach64->accel.dst_pix_width];*/
|
||||
|
||||
mach64->accel.dp_frgd_clr = mach64->dp_frgd_clr;
|
||||
mach64->accel.dp_bkgd_clr = mach64->dp_bkgd_clr;
|
||||
mach64->accel.dp_bkgd_clr = mach64->dp_bkgd_clr;
|
||||
|
||||
mach64->accel.clr_cmp_clr = mach64->clr_cmp_clr & mach64->clr_cmp_mask;
|
||||
mach64->accel.clr_cmp_mask = mach64->clr_cmp_mask;
|
||||
mach64->accel.clr_cmp_fn = mach64->clr_cmp_cntl & 7;
|
||||
mach64->accel.clr_cmp_src = mach64->clr_cmp_cntl & (1 << 24);
|
||||
|
||||
|
||||
mach64->accel.poly_draw = 0;
|
||||
|
||||
|
||||
mach64->accel.busy = 1;
|
||||
#ifdef MACH64_DEBUG
|
||||
pclog("mach64_start_fill : dst %i, %i src %i, %i size %i, %i src pitch %i offset %X dst pitch %i offset %X scissor %i %i %i %i src_fg %i mix %02X %02X\n", mach64->accel.dst_x_start, mach64->accel.dst_y_start, mach64->accel.src_x_start, mach64->accel.src_y_start, mach64->accel.dst_width, mach64->accel.dst_height, mach64->accel.src_pitch, mach64->accel.src_offset, mach64->accel.dst_pitch, mach64->accel.dst_offset, mach64->accel.sc_left, mach64->accel.sc_right, mach64->accel.sc_top, mach64->accel.sc_bottom, mach64->accel.source_fg, mach64->accel.mix_fg, mach64->accel.mix_bg);
|
||||
#endif
|
||||
mach64->accel.op = OP_RECT;
|
||||
}
|
||||
|
||||
void mach64_start_line(mach64_t *mach64)
|
||||
{
|
||||
int x, y;
|
||||
|
||||
|
||||
mach64->accel.dst_x = (mach64->dst_y_x >> 16) & 0xfff;
|
||||
mach64->accel.dst_y = mach64->dst_y_x & 0xfff;
|
||||
|
||||
@@ -1101,37 +1128,34 @@ void mach64_start_line(mach64_t *mach64)
|
||||
|
||||
mach64->accel.dst_pitch = (mach64->dst_off_pitch >> 22) * 8;
|
||||
mach64->accel.dst_offset = (mach64->dst_off_pitch & 0xfffff) * 8;
|
||||
|
||||
|
||||
mach64->accel.mix_fg = (mach64->dp_mix >> 16) & 0x1f;
|
||||
mach64->accel.mix_bg = mach64->dp_mix & 0x1f;
|
||||
|
||||
|
||||
mach64->accel.source_bg = mach64->dp_src & 7;
|
||||
mach64->accel.source_fg = (mach64->dp_src >> 8) & 7;
|
||||
mach64->accel.source_mix = (mach64->dp_src >> 16) & 7;
|
||||
|
||||
|
||||
mach64->accel.dst_pix_width = mach64->dp_pix_width & 7;
|
||||
mach64->accel.src_pix_width = (mach64->dp_pix_width >> 8) & 7;
|
||||
mach64->accel.host_pix_width = (mach64->dp_pix_width >> 16) & 7;
|
||||
|
||||
|
||||
mach64->accel.dst_size = mach64_width[mach64->accel.dst_pix_width];
|
||||
mach64->accel.src_size = mach64_width[mach64->accel.src_pix_width];
|
||||
mach64->accel.host_size = mach64_width[mach64->accel.host_pix_width];
|
||||
|
||||
|
||||
if (mach64->accel.src_size == WIDTH_1BIT)
|
||||
mach64->accel.src_offset <<= 3;
|
||||
else
|
||||
mach64->accel.src_offset >>= mach64->accel.src_size;
|
||||
|
||||
|
||||
if (mach64->accel.dst_size == WIDTH_1BIT)
|
||||
mach64->accel.dst_offset <<= 3;
|
||||
else
|
||||
mach64->accel.dst_offset >>= mach64->accel.dst_size;
|
||||
|
||||
/* mach64->accel.src_pitch *= mach64_inc[mach64->accel.src_pix_width];
|
||||
mach64->accel.dst_pitch *= mach64_inc[mach64->accel.dst_pix_width];*/
|
||||
|
||||
mach64->accel.source_host = ((mach64->dp_src & 7) == SRC_HOST) || (((mach64->dp_src >> 8) & 7) == SRC_HOST);
|
||||
|
||||
|
||||
for (y = 0; y < 8; y++)
|
||||
{
|
||||
for (x = 0; x < 8; x++)
|
||||
@@ -1140,41 +1164,43 @@ void mach64_start_line(mach64_t *mach64)
|
||||
mach64->accel.pattern[y][x] = (temp >> (x + ((y & 3) * 8))) & 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
mach64->accel.sc_left = mach64->sc_left_right & 0x1fff;
|
||||
mach64->accel.sc_right = (mach64->sc_left_right >> 16) & 0x1fff;
|
||||
mach64->accel.sc_top = mach64->sc_top_bottom & 0x7fff;
|
||||
mach64->accel.sc_bottom = (mach64->sc_top_bottom >> 16) & 0x7fff;
|
||||
|
||||
|
||||
mach64->accel.dp_frgd_clr = mach64->dp_frgd_clr;
|
||||
mach64->accel.dp_bkgd_clr = mach64->dp_bkgd_clr;
|
||||
|
||||
mach64->accel.dp_bkgd_clr = mach64->dp_bkgd_clr;
|
||||
|
||||
mach64->accel.x_count = mach64->dst_bres_lnth & 0x7fff;
|
||||
mach64->accel.err = (mach64->dst_bres_err & 0x3ffff) | ((mach64->dst_bres_err & 0x40000) ? 0xfffc0000 : 0);
|
||||
|
||||
|
||||
mach64->accel.clr_cmp_clr = mach64->clr_cmp_clr & mach64->clr_cmp_mask;
|
||||
mach64->accel.clr_cmp_mask = mach64->clr_cmp_mask;
|
||||
mach64->accel.clr_cmp_fn = mach64->clr_cmp_cntl & 7;
|
||||
mach64->accel.clr_cmp_src = mach64->clr_cmp_cntl & (1 << 24);
|
||||
|
||||
mach64->accel.busy = 1;
|
||||
#ifdef MACH64_DEBUG
|
||||
pclog("mach64_start_line\n");
|
||||
#endif
|
||||
mach64->accel.op = OP_LINE;
|
||||
}
|
||||
|
||||
#define READ(addr, dat, width) if (width == 0) dat = svga->vram[((addr)) & mach64->vram_mask]; \
|
||||
else if (width == 1) dat = *(uint16_t *)&svga->vram[((addr) << 1) & mach64->vram_mask]; \
|
||||
else if (width == 2) dat = *(uint32_t *)&svga->vram[((addr) << 2) & mach64->vram_mask]; \
|
||||
else if (mach64->dp_pix_width & DP_BYTE_PIX_ORDER) dat = (svga->vram[((addr) >> 3) & mach64->vram_mask] >> ((addr) & 7)) & 1; \
|
||||
else dat = (svga->vram[((addr) >> 3) & mach64->vram_mask] >> (7 - ((addr) & 7))) & 1;
|
||||
#define READ(addr, dat, width) if (width == 0) dat = svga->vram[((addr)) & mach64->vram_mask]; \
|
||||
else if (width == 1) dat = *(uint16_t *)&svga->vram[((addr) << 1) & mach64->vram_mask]; \
|
||||
else if (width == 2) dat = *(uint32_t *)&svga->vram[((addr) << 2) & mach64->vram_mask]; \
|
||||
else \
|
||||
{ \
|
||||
if (mach64->dp_pix_width & DP_BYTE_PIX_ORDER) \
|
||||
dat = (svga->vram[((addr) >> 3) & mach64->vram_mask] >> (((addr) & 7))) & 1; \
|
||||
else \
|
||||
dat = (svga->vram[((addr) >> 3) & mach64->vram_mask] >> (7 - ((addr) & 7))) & 1; \
|
||||
}
|
||||
|
||||
#define MIX switch (mix ? mach64->accel.mix_fg : mach64->accel.mix_bg) \
|
||||
{ \
|
||||
case 0x0: dest_dat = ~dest_dat; break; \
|
||||
case 0x1: dest_dat = 0; break; \
|
||||
case 0x2: dest_dat = 0xffffffff; break; \
|
||||
case 0x2: dest_dat = ~0; break; \
|
||||
case 0x3: dest_dat = dest_dat; break; \
|
||||
case 0x4: dest_dat = ~src_dat; break; \
|
||||
case 0x5: dest_dat = src_dat ^ dest_dat; break; \
|
||||
@@ -1207,17 +1233,10 @@ void mach64_start_line(mach64_t *mach64)
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
if (dest_dat & 1) { \
|
||||
if (mach64->dp_pix_width & DP_BYTE_PIX_ORDER) \
|
||||
svga->vram[((addr) >> 3) & mach64->vram_mask] |= 1 << ((addr) & 7); \
|
||||
else \
|
||||
svga->vram[((addr) >> 3) & mach64->vram_mask] |= 1 << (7 - ((addr) & 7)); \
|
||||
} else { \
|
||||
if (mach64->dp_pix_width & DP_BYTE_PIX_ORDER) \
|
||||
svga->vram[((addr) >> 3) & mach64->vram_mask] &= ~(1 << ((addr) & 7)); \
|
||||
else \
|
||||
svga->vram[((addr) >> 3) & mach64->vram_mask] &= ~(1 << (7 - ((addr) & 7)));\
|
||||
} \
|
||||
if (dest_dat & 1) \
|
||||
svga->vram[((addr) >> 3) & mach64->vram_mask] |= 1 << (((addr) & 7)); \
|
||||
else \
|
||||
svga->vram[((addr) >> 3) & mach64->vram_mask] &= ~(1 << (((addr) & 7))); \
|
||||
svga->changedvram[(((addr) >> 3) & mach64->vram_mask) >> 12] = changeframecount; \
|
||||
}
|
||||
|
||||
@@ -1225,7 +1244,7 @@ void mach64_blit(uint32_t cpu_dat, int count, mach64_t *mach64)
|
||||
{
|
||||
svga_t *svga = &mach64->svga;
|
||||
int cmp_clr = 0;
|
||||
|
||||
|
||||
if (!mach64->accel.busy)
|
||||
{
|
||||
#ifdef MACH64_DEBUG
|
||||
@@ -1245,7 +1264,7 @@ void mach64_blit(uint32_t cpu_dat, int count, mach64_t *mach64)
|
||||
int dst_y = (mach64->accel.dst_y + mach64->accel.dst_y_start) & 0xfff;
|
||||
int src_x;
|
||||
int src_y = (mach64->accel.src_y + mach64->accel.src_y_start) & 0xfff;
|
||||
|
||||
|
||||
if (mach64->src_cntl & SRC_LINEAR_EN)
|
||||
src_x = mach64->accel.src_x;
|
||||
else
|
||||
@@ -1293,20 +1312,17 @@ void mach64_blit(uint32_t cpu_dat, int count, mach64_t *mach64)
|
||||
mix = 1;
|
||||
break;
|
||||
case MONO_SRC_BLITSRC:
|
||||
if (mach64->src_cntl & SRC_LINEAR_EN)
|
||||
{
|
||||
READ(mach64->accel.src_offset + src_x, mix, WIDTH_1BIT);
|
||||
}
|
||||
else
|
||||
{
|
||||
READ(mach64->accel.src_offset + (src_y * mach64->accel.src_pitch) + src_x, mix, WIDTH_1BIT);
|
||||
}
|
||||
if (mach64->src_cntl & SRC_LINEAR_EN) {
|
||||
READ(mach64->accel.src_offset + src_x, mix, WIDTH_1BIT);
|
||||
} else {
|
||||
READ(mach64->accel.src_offset + (src_y * mach64->accel.src_pitch) + src_x, mix, WIDTH_1BIT);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (dst_x >= mach64->accel.sc_left && dst_x <= mach64->accel.sc_right &&
|
||||
dst_y >= mach64->accel.sc_top && dst_y <= mach64->accel.sc_bottom)
|
||||
{
|
||||
{
|
||||
switch (mix ? mach64->accel.source_fg : mach64->accel.source_bg)
|
||||
{
|
||||
case SRC_HOST:
|
||||
@@ -1348,20 +1364,20 @@ void mach64_blit(uint32_t cpu_dat, int count, mach64_t *mach64)
|
||||
cmp_clr = (((mach64->accel.clr_cmp_src) ? src_dat : dest_dat) & mach64->accel.clr_cmp_mask) == mach64->accel.clr_cmp_clr;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
if (!cmp_clr)
|
||||
MIX
|
||||
|
||||
WRITE(mach64->accel.dst_offset + (dst_y * mach64->accel.dst_pitch) + dst_x, mach64->accel.dst_size);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (mach64->dst_cntl & DST_24_ROT_EN)
|
||||
{
|
||||
mach64->accel.dp_frgd_clr = ((mach64->accel.dp_frgd_clr >> 8) & 0xffff) | (mach64->accel.dp_frgd_clr << 16);
|
||||
mach64->accel.dp_bkgd_clr = ((mach64->accel.dp_bkgd_clr >> 8) & 0xffff) | (mach64->accel.dp_bkgd_clr << 16);
|
||||
}
|
||||
|
||||
|
||||
mach64->accel.src_x += mach64->accel.xinc;
|
||||
mach64->accel.dst_x += mach64->accel.xinc;
|
||||
if (!(mach64->src_cntl & SRC_LINEAR_EN))
|
||||
@@ -1379,9 +1395,9 @@ void mach64_blit(uint32_t cpu_dat, int count, mach64_t *mach64)
|
||||
mach64->accel.src_x_count = mach64->accel.src_width1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
mach64->accel.x_count--;
|
||||
|
||||
|
||||
if (mach64->accel.x_count <= 0)
|
||||
{
|
||||
mach64->accel.x_count = mach64->accel.dst_width;
|
||||
@@ -1393,7 +1409,7 @@ void mach64_blit(uint32_t cpu_dat, int count, mach64_t *mach64)
|
||||
if (!(mach64->src_cntl & SRC_LINEAR_EN))
|
||||
{
|
||||
mach64->accel.src_x = 0;
|
||||
mach64->accel.src_y += mach64->accel.yinc;
|
||||
mach64->accel.src_y += mach64->accel.yinc;
|
||||
mach64->accel.src_y_count--;
|
||||
if (mach64->accel.src_y_count <= 0)
|
||||
{
|
||||
@@ -1411,13 +1427,10 @@ void mach64_blit(uint32_t cpu_dat, int count, mach64_t *mach64)
|
||||
mach64->accel.poly_draw = 0;
|
||||
|
||||
mach64->accel.dst_height--;
|
||||
|
||||
|
||||
if (mach64->accel.dst_height <= 0)
|
||||
{
|
||||
/*Blit finished*/
|
||||
#ifdef MACH64_DEBUG
|
||||
pclog("mach64 blit finished\n");
|
||||
#endif
|
||||
mach64->accel.busy = 0;
|
||||
if (mach64->dst_cntl & DST_X_TILE)
|
||||
mach64->dst_y_x = (mach64->dst_y_x & 0xfff) | ((mach64->dst_y_x + (mach64->accel.dst_width << 16)) & 0xfff0000);
|
||||
@@ -1437,7 +1450,7 @@ void mach64_blit(uint32_t cpu_dat, int count, mach64_t *mach64)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case OP_LINE:
|
||||
@@ -1447,7 +1460,7 @@ void mach64_blit(uint32_t cpu_dat, int count, mach64_t *mach64)
|
||||
uint32_t host_dat = 0;
|
||||
int mix = 0;
|
||||
int draw_pixel = !(mach64->dst_cntl & DST_POLYGON_EN);
|
||||
|
||||
|
||||
if (mach64->accel.source_host)
|
||||
{
|
||||
host_dat = cpu_dat;
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
* Emulation of select Cirrus Logic cards (CL-GD 5428,
|
||||
* CL-GD 5429, 5430, 5434 and 5436 are supported).
|
||||
*
|
||||
* Version: @(#)vid_cl54xx.c 1.0.8 2018/03/15
|
||||
* Version: @(#)vid_cl54xx.c 1.0.9 2018/03/17
|
||||
*
|
||||
* Authors: Fred N. van Kempen, <decwiz@yahoo.com>
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
@@ -60,8 +60,8 @@
|
||||
|
||||
|
||||
#define BIOS_GD5424_PATH L"roms/video/cirruslogic/cl5424.bin"
|
||||
#define BIOS_GD5428_ISA_PATH L"roms/video/cirruslogic/5428.bin"
|
||||
#define BIOS_GD5428_VLB_PATH L"roms/video/cirruslogic/diamond speedstar pro vlb (cirrus logic 5428)_V3.04.bin"
|
||||
#define BIOS_GD5426_PATH L"roms/video/cirruslogic/diamond speedstar pro vlb v3.04.bin"
|
||||
#define BIOS_GD5428_PATH L"roms/video/cirruslogic/vlbusjapan.bin"
|
||||
#define BIOS_GD5429_PATH L"roms/video/cirruslogic/5429.vbi"
|
||||
#define BIOS_GD5430_VLB_PATH L"roms/video/cirruslogic/diamondvlbus.bin"
|
||||
#define BIOS_GD5430_PCI_PATH L"roms/video/cirruslogic/pci.bin"
|
||||
@@ -69,6 +69,7 @@
|
||||
#define BIOS_GD5436_PATH L"roms/video/cirruslogic/5436.vbi"
|
||||
|
||||
#define CIRRUS_ID_CLGD5424 0x94
|
||||
#define CIRRUS_ID_CLGD5426 0x90
|
||||
#define CIRRUS_ID_CLGD5428 0x98
|
||||
#define CIRRUS_ID_CLGD5429 0x9c
|
||||
#define CIRRUS_ID_CLGD5430 0xa0
|
||||
@@ -97,9 +98,13 @@
|
||||
#define CIRRUS_BUSTYPE_VLBSLOW 0x30
|
||||
#define CIRRUS_BUSTYPE_ISA 0x38
|
||||
#define CIRRUS_MMIO_ENABLE 0x04
|
||||
#define CIRRUS_MMIO_USE_PCIADDR 0x40 // 0xb8000 if cleared.
|
||||
#define CIRRUS_MMIO_USE_PCIADDR 0x40 /* 0xb8000 if cleared. */
|
||||
#define CIRRUS_MEMSIZEEXT_DOUBLE 0x80
|
||||
|
||||
/* control 0x0b */
|
||||
#define CIRRUS_BANKING_DUAL 0x01
|
||||
#define CIRRUS_BANKING_GRANULARITY_16K 0x20 /* set:16k, clear:4k */
|
||||
|
||||
/* control 0x30 */
|
||||
#define CIRRUS_BLTMODE_BACKWARDS 0x01
|
||||
#define CIRRUS_BLTMODE_MEMSYSDEST 0x02
|
||||
@@ -113,7 +118,14 @@
|
||||
#define CIRRUS_BLTMODE_PIXELWIDTH24 0x20
|
||||
#define CIRRUS_BLTMODE_PIXELWIDTH32 0x30
|
||||
|
||||
// control 0x33
|
||||
/* control 0x31 */
|
||||
#define CIRRUS_BLT_BUSY 0x01
|
||||
#define CIRRUS_BLT_START 0x02
|
||||
#define CIRRUS_BLT_RESET 0x04
|
||||
#define CIRRUS_BLT_FIFOUSED 0x10
|
||||
#define CIRRUS_BLT_AUTOSTART 0x80
|
||||
|
||||
/* control 0x33 */
|
||||
#define CIRRUS_BLTMODEEXT_SOLIDFILL 0x04
|
||||
#define CIRRUS_BLTMODEEXT_COLOREXPINV 0x02
|
||||
#define CIRRUS_BLTMODEEXT_DWORDGRANULARITY 0x01
|
||||
@@ -139,22 +151,22 @@ typedef struct gd54xx_t
|
||||
uint32_t vram_mask;
|
||||
|
||||
uint8_t vclk_n[4];
|
||||
uint8_t vclk_d[4];
|
||||
uint8_t vclk_d[4];
|
||||
uint32_t bank[2];
|
||||
|
||||
struct {
|
||||
uint8_t state;
|
||||
int ctrl;
|
||||
} ramdac;
|
||||
|
||||
} ramdac;
|
||||
|
||||
struct {
|
||||
uint32_t fg_col, bg_col;
|
||||
uint16_t width, height;
|
||||
uint16_t dst_pitch, src_pitch;
|
||||
uint16_t dst_pitch, src_pitch;
|
||||
uint32_t dst_addr, src_addr;
|
||||
uint8_t mask, mode, rop;
|
||||
uint8_t modeext;
|
||||
uint8_t bltstart;
|
||||
uint8_t status;
|
||||
uint16_t trans_col, trans_mask;
|
||||
|
||||
uint32_t dst_addr_backup, src_addr_backup;
|
||||
@@ -167,15 +179,15 @@ typedef struct gd54xx_t
|
||||
uint16_t pixel_cnt;
|
||||
uint16_t scan_cnt;
|
||||
} blt;
|
||||
|
||||
int pci, vlb;
|
||||
|
||||
|
||||
int pci, vlb;
|
||||
|
||||
uint8_t pci_regs[256];
|
||||
uint8_t int_line;
|
||||
int card;
|
||||
|
||||
|
||||
uint32_t lfb_base;
|
||||
|
||||
|
||||
int mmio_vram_overlap;
|
||||
} gd54xx_t;
|
||||
|
||||
@@ -219,7 +231,7 @@ gd54xx_out(uint16_t addr, uint8_t val, void *p)
|
||||
if (svga->seqaddr > 5) {
|
||||
svga->seqregs[svga->seqaddr & 0x1f] = val;
|
||||
switch (svga->seqaddr & 0x1f) {
|
||||
case 6: /* cirrus unlock extensions */
|
||||
case 6:
|
||||
val &= 0x17;
|
||||
if (val == 0x12)
|
||||
svga->seqregs[6] = 0x12;
|
||||
@@ -234,17 +246,25 @@ gd54xx_out(uint16_t addr, uint8_t val, void *p)
|
||||
break;
|
||||
case 0x10: case 0x30: case 0x50: case 0x70:
|
||||
case 0x90: case 0xb0: case 0xd0: case 0xf0:
|
||||
svga->hwcursor.x = (val << 3) | ((svga->seqaddr >> 5) & 7);
|
||||
svga->hwcursor.x = (val << 3) | (svga->seqaddr >> 5);
|
||||
break;
|
||||
case 0x11: case 0x31: case 0x51: case 0x71:
|
||||
case 0x91: case 0xb1: case 0xd1: case 0xf1:
|
||||
svga->hwcursor.y = (val << 3) | ((svga->seqaddr >> 5) & 7);
|
||||
svga->hwcursor.y = (val << 3) | (svga->seqaddr >> 5);
|
||||
break;
|
||||
case 0x12:
|
||||
svga->hwcursor.ena = val & 1;
|
||||
svga->hwcursor.ena = val & CIRRUS_CURSOR_SHOW;
|
||||
svga->hwcursor.xsize = svga->hwcursor.ysize = (val & CIRRUS_CURSOR_LARGE) ? 64 : 32;
|
||||
if (val & CIRRUS_CURSOR_LARGE)
|
||||
svga->hwcursor.addr = (((gd54xx->vram_size<<20)-0x4000) + ((svga->seqregs[0x13] & 0x3c) * 256));
|
||||
else
|
||||
svga->hwcursor.addr = (((gd54xx->vram_size<<20)-0x4000) + ((svga->seqregs[0x13] & 0x3f) * 256));
|
||||
break;
|
||||
case 0x13:
|
||||
svga->hwcursor.addr = (((gd54xx->vram_size<<20)-0x4000) + ((val & 0x3f) * 256));
|
||||
if (svga->seqregs[0x12] & CIRRUS_CURSOR_LARGE)
|
||||
svga->hwcursor.addr = (((gd54xx->vram_size<<20)-0x4000) + ((val & 0x3c) * 256));
|
||||
else
|
||||
svga->hwcursor.addr = (((gd54xx->vram_size<<20)-0x4000) + ((val & 0x3f) * 256));
|
||||
break;
|
||||
case 0x07:
|
||||
svga->set_reset_disabled = svga->seqregs[7] & 1;
|
||||
@@ -414,8 +434,7 @@ gd54xx_out(uint16_t addr, uint8_t val, void *p)
|
||||
if ((svga->crtcreg == 7) && (svga->crtc[0x11] & 0x80))
|
||||
val = (svga->crtc[7] & ~0x10) | (val & 0x10);
|
||||
old = svga->crtc[svga->crtcreg];
|
||||
if ((svga->crtcreg != 0x27) && (svga->crtcreg != 0x28))
|
||||
svga->crtc[svga->crtcreg] = val;
|
||||
svga->crtc[svga->crtcreg] = val;
|
||||
|
||||
if (old != val) {
|
||||
if (svga->crtcreg < 0xe || svga->crtcreg > 0x10) {
|
||||
@@ -441,18 +460,31 @@ gd54xx_in(uint16_t addr, void *p)
|
||||
addr ^= 0x60;
|
||||
|
||||
switch (addr) {
|
||||
case 0x3c4:
|
||||
if ((svga->seqregs[6] & 0x17) == 0x12)
|
||||
{
|
||||
temp = svga->seqaddr;
|
||||
if ((temp & 0x1e) == 0x10)
|
||||
{
|
||||
if (temp & 1)
|
||||
temp = ((svga->hwcursor.y & 7) << 5) | 0x11;
|
||||
else
|
||||
temp = ((svga->hwcursor.x & 7) << 5) | 0x10;
|
||||
}
|
||||
return temp;
|
||||
}
|
||||
return svga->seqaddr;
|
||||
|
||||
case 0x3c5:
|
||||
if (svga->seqaddr > 5) {
|
||||
switch (svga->seqaddr) {
|
||||
case 6:
|
||||
return ((svga->seqregs[6] & 0x17) == 0x12) ? 0x12 : 0x0f;
|
||||
return ((svga->seqregs[6] & 0x17) == 0x12) ? 0x12 : 0x0f;
|
||||
case 0x0b: case 0x0c: case 0x0d: case 0x0e:
|
||||
return gd54xx->vclk_n[svga->seqaddr-0x0b];
|
||||
case 0x0f:
|
||||
return svga->seqregs[0x0f];
|
||||
case 0x17:
|
||||
temp = svga->gdcreg[0x17] & ~(7 << 3);
|
||||
if (svga->crtc[0x27] < CIRRUS_ID_CLGD5430) {
|
||||
if (svga->crtc[0x27] <= CIRRUS_ID_CLGD5429) {
|
||||
if (gd54xx->vlb)
|
||||
temp |= (CL_GD5429_SYSTEM_BUS_VESA << 3);
|
||||
else
|
||||
@@ -468,8 +500,6 @@ gd54xx_in(uint16_t addr, void *p)
|
||||
return temp;
|
||||
case 0x1b: case 0x1c: case 0x1d: case 0x1e:
|
||||
return gd54xx->vclk_d[svga->seqaddr-0x1b];
|
||||
case 0x1f:
|
||||
return svga->seqregs[0x1f];
|
||||
}
|
||||
return svga->seqregs[svga->seqaddr & 0x3f];
|
||||
}
|
||||
@@ -493,7 +523,7 @@ gd54xx_in(uint16_t addr, void *p)
|
||||
case 0x24: /*Attribute controller toggle readback (R)*/
|
||||
return svga->attrff << 7;
|
||||
case 0x26: /*Attribute controller index readback (R)*/
|
||||
return svga->attraddr & 0x3f;
|
||||
return svga->attraddr & 0x3f;
|
||||
case 0x27: /*ID*/
|
||||
return svga->crtc[0x27]; /*GD542x/GD543x*/
|
||||
case 0x28: /*Class ID*/
|
||||
@@ -512,13 +542,13 @@ gd54xx_recalc_banking(gd54xx_t *gd54xx)
|
||||
{
|
||||
svga_t *svga = &gd54xx->svga;
|
||||
|
||||
if (svga->gdcreg[0xb] & 0x20)
|
||||
if (svga->gdcreg[0x0b] & CIRRUS_BANKING_GRANULARITY_16K)
|
||||
gd54xx->bank[0] = svga->gdcreg[0x09] << 14;
|
||||
else
|
||||
gd54xx->bank[0] = svga->gdcreg[0x09] << 12;
|
||||
|
||||
if (svga->gdcreg[0xb] & 0x01) {
|
||||
if (svga->gdcreg[0xb] & 0x20)
|
||||
if (svga->gdcreg[0x0b] & CIRRUS_BANKING_DUAL) {
|
||||
if (svga->gdcreg[0x0b] & CIRRUS_BANKING_GRANULARITY_16K)
|
||||
gd54xx->bank[1] = svga->gdcreg[0x0a] << 14;
|
||||
else
|
||||
gd54xx->bank[1] = svga->gdcreg[0x0a] << 12;
|
||||
@@ -543,7 +573,7 @@ gd543x_recalc_mapping(gd54xx_t *gd54xx)
|
||||
|
||||
if (!(svga->seqregs[7] & 0xf0)) {
|
||||
mem_mapping_disable(&gd54xx->linear_mapping);
|
||||
switch (svga->gdcreg[6] & 0x0C) {
|
||||
switch (svga->gdcreg[6] & 0x0c) {
|
||||
case 0x0: /*128k at A0000*/
|
||||
mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x20000);
|
||||
svga->banked_mask = 0xffff;
|
||||
@@ -554,12 +584,10 @@ gd543x_recalc_mapping(gd54xx_t *gd54xx)
|
||||
break;
|
||||
case 0x8: /*32k at B0000*/
|
||||
mem_mapping_set_addr(&svga->mapping, 0xb0000, 0x08000);
|
||||
mem_mapping_disable(&gd54xx->mmio_mapping);
|
||||
svga->banked_mask = 0x7fff;
|
||||
break;
|
||||
case 0xC: /*32k at B8000*/
|
||||
mem_mapping_set_addr(&svga->mapping, 0xb8000, 0x08000);
|
||||
mem_mapping_disable(&gd54xx->mmio_mapping);
|
||||
svga->banked_mask = 0x7fff;
|
||||
gd54xx->mmio_vram_overlap = 1;
|
||||
break;
|
||||
@@ -572,7 +600,7 @@ gd543x_recalc_mapping(gd54xx_t *gd54xx)
|
||||
uint32_t base, size;
|
||||
|
||||
if (svga->crtc[0x27] <= CIRRUS_ID_CLGD5429 || (!gd54xx->pci && !gd54xx->vlb)) {
|
||||
if (svga->gdcreg[0xb] & 0x20) {
|
||||
if (svga->gdcreg[0x0b] & CIRRUS_BANKING_GRANULARITY_16K) {
|
||||
base = (svga->seqregs[7] & 0xf0) << 16;
|
||||
size = 1 * 1024 * 1024;
|
||||
} else {
|
||||
@@ -597,7 +625,7 @@ gd543x_recalc_mapping(gd54xx_t *gd54xx)
|
||||
mem_mapping_set_addr(&gd54xx->linear_mapping, base, size);
|
||||
svga->linear_base = base;
|
||||
if (svga->seqregs[0x17] & CIRRUS_MMIO_ENABLE) {
|
||||
if (svga->seqregs[0x17] & 0x40) {
|
||||
if (svga->seqregs[0x17] & CIRRUS_MMIO_USE_PCIADDR) {
|
||||
if (size >= (4 * 1024 * 1024))
|
||||
mem_mapping_disable(&gd54xx->mmio_mapping); /* MMIO is handled in the linear read/write functions */
|
||||
else {
|
||||
@@ -622,45 +650,85 @@ gd54xx_recalctimings(svga_t *svga)
|
||||
|
||||
svga->interlace = (svga->crtc[0x1a] & 0x01);
|
||||
|
||||
if (svga->seqregs[7] & 0x01) {
|
||||
svga->render = svga_render_8bpp_highres;
|
||||
svga->bpp = 8;
|
||||
} else if (svga->gdcreg[5] & 0x40) {
|
||||
svga->render = svga_render_8bpp_lowres;
|
||||
svga->bpp = 8;
|
||||
}
|
||||
|
||||
svga->ma_latch |= ((svga->crtc[0x1b] & 0x01) << 16) | ((svga->crtc[0x1b] & 0xc) << 15);
|
||||
|
||||
if (gd54xx->ramdac.ctrl & 0x80) {
|
||||
if (gd54xx->ramdac.ctrl & 0x40) {
|
||||
switch (gd54xx->ramdac.ctrl & 0xf) {
|
||||
case 0x0:
|
||||
svga->render = svga_render_15bpp_highres;
|
||||
svga->bpp = 15;
|
||||
break;
|
||||
case 0x1:
|
||||
svga->render = svga_render_16bpp_highres;
|
||||
svga->bpp = 16;
|
||||
break;
|
||||
case 0x5:
|
||||
if ((svga->crtc[0x27] >= CIRRUS_ID_CLGD5434) && (svga->seqregs[7] & 8)) {
|
||||
svga->render = svga_render_32bpp_highres;
|
||||
svga->bpp = 32;
|
||||
if (svga->crtc[0x27] < CIRRUS_ID_CLGD5436)
|
||||
svga->rowoffset *= 2;
|
||||
} else {
|
||||
svga->render = svga_render_24bpp_highres;
|
||||
svga->bpp = 24;
|
||||
}
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
svga->render = svga_render_15bpp_highres;
|
||||
svga->bpp = 15;
|
||||
if (svga->seqregs[7] & CIRRUS_SR7_BPP_SVGA)
|
||||
{
|
||||
svga->bpp = 8;
|
||||
svga->render = svga_render_8bpp_highres;
|
||||
}
|
||||
else if (svga->gdcreg[5] & 0x40)
|
||||
{
|
||||
svga->bpp = 8;
|
||||
svga->render = svga_render_8bpp_lowres;
|
||||
}
|
||||
}
|
||||
|
||||
if (gd54xx->ramdac.ctrl & 0x80)
|
||||
{
|
||||
if (gd54xx->ramdac.ctrl & 0x40)
|
||||
{
|
||||
switch (gd54xx->ramdac.ctrl & 0xf)
|
||||
{
|
||||
case 0:
|
||||
svga->bpp = 15;
|
||||
svga->render = svga_render_15bpp_highres;
|
||||
break;
|
||||
|
||||
case 1:
|
||||
svga->bpp = 16;
|
||||
svga->render = svga_render_16bpp_highres;
|
||||
break;
|
||||
|
||||
case 5:
|
||||
if ((svga->crtc[0x27] >= CIRRUS_ID_CLGD5434) && (svga->seqregs[7] & CIRRUS_SR7_BPP_32))
|
||||
{
|
||||
svga->bpp = 32;
|
||||
svga->render = svga_render_32bpp_highres;
|
||||
if (svga->crtc[0x27] < CIRRUS_ID_CLGD5436)
|
||||
svga->rowoffset *= 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
svga->bpp = 24;
|
||||
svga->render = svga_render_24bpp_highres;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xf:
|
||||
switch (svga->seqregs[7] & CIRRUS_SR7_BPP_MASK)
|
||||
{
|
||||
case CIRRUS_SR7_BPP_32:
|
||||
svga->bpp = 32;
|
||||
svga->render = svga_render_32bpp_highres;
|
||||
svga->rowoffset *= 2;
|
||||
break;
|
||||
|
||||
case CIRRUS_SR7_BPP_24:
|
||||
svga->bpp = 24;
|
||||
svga->render = svga_render_24bpp_highres;
|
||||
break;
|
||||
|
||||
case CIRRUS_SR7_BPP_16:
|
||||
case CIRRUS_SR7_BPP_16_DOUBLEVCLK:
|
||||
svga->bpp = 16;
|
||||
svga->render = svga_render_16bpp_highres;
|
||||
break;
|
||||
|
||||
case CIRRUS_SR7_BPP_8:
|
||||
svga->bpp = 8;
|
||||
svga->render = svga_render_8bpp_highres;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
svga->bpp = 15;
|
||||
svga->render = svga_render_15bpp_highres;
|
||||
}
|
||||
}
|
||||
|
||||
clocksel = (svga->miscout >> 2) & 3;
|
||||
|
||||
if (!gd54xx->vclk_n[clocksel] || !gd54xx->vclk_d[clocksel])
|
||||
@@ -676,7 +744,7 @@ gd54xx_recalctimings(svga_t *svga)
|
||||
freq /= 2.0;
|
||||
break;
|
||||
case 4:
|
||||
if (svga->crtc[0x27] < CIRRUS_ID_CLGD5436)
|
||||
if (svga->crtc[0x27] <= CIRRUS_ID_CLGD5434)
|
||||
freq /= 3.0;
|
||||
break;
|
||||
}
|
||||
@@ -687,46 +755,51 @@ gd54xx_recalctimings(svga_t *svga)
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
gd54xx_hwcursor_draw(svga_t *svga, int displine)
|
||||
static
|
||||
void gd54xx_hwcursor_draw(svga_t *svga, int displine)
|
||||
{
|
||||
int x;
|
||||
uint8_t dat[2];
|
||||
int xx;
|
||||
int offset = svga->hwcursor_latch.x - svga->hwcursor_latch.xoff;
|
||||
int largecur = (svga->seqregs[0x12] & CIRRUS_CURSOR_LARGE);
|
||||
int cursize = (largecur) ? 64 : 32;
|
||||
int y_add = (enable_overscan && !suppress_overscan) ? 16 : 0;
|
||||
int x_add = (enable_overscan && !suppress_overscan) ? 8 : 0;
|
||||
|
||||
if (svga->interlace && svga->hwcursor_oddeven)
|
||||
svga->hwcursor_latch.addr += 4;
|
||||
|
||||
for (x = 0; x < cursize; x += 8) {
|
||||
dat[0] = svga->vram[svga->hwcursor_latch.addr];
|
||||
dat[1] = svga->vram[svga->hwcursor_latch.addr + 0x80];
|
||||
for (xx = 0; xx < 8; xx++) {
|
||||
if (offset >= svga->hwcursor_latch.x) {
|
||||
if (dat[1] & 0x80)
|
||||
((uint32_t *)buffer32->line[displine + y_add])[offset + cursize + x_add] = 0;
|
||||
if (dat[0] & 0x80)
|
||||
((uint32_t *)buffer32->line[displine + y_add])[offset + cursize + x_add] ^= 0xffffff;
|
||||
}
|
||||
int x;
|
||||
uint8_t dat[2];
|
||||
int xx;
|
||||
int offset = svga->hwcursor_latch.x - svga->hwcursor_latch.xoff;
|
||||
int y_add = (enable_overscan && !suppress_overscan) ? 16 : 0;
|
||||
int x_add = (enable_overscan && !suppress_overscan) ? 8 : 0;
|
||||
int pitch = (svga->hwcursor.xsize == 64) ? 16 : 4;
|
||||
|
||||
if (svga->interlace && svga->hwcursor_oddeven)
|
||||
svga->hwcursor_latch.addr += pitch;
|
||||
|
||||
for (x = 0; x < svga->hwcursor.xsize; x += 8) {
|
||||
dat[0] = svga->vram[svga->hwcursor_latch.addr];
|
||||
if (svga->hwcursor.xsize == 64)
|
||||
dat[1] = svga->vram[svga->hwcursor_latch.addr + 0x08];
|
||||
else
|
||||
dat[1] = svga->vram[svga->hwcursor_latch.addr + 0x80];
|
||||
for (xx = 0; xx < 8; xx++) {
|
||||
if (offset >= svga->hwcursor_latch.x) {
|
||||
if (dat[1] & 0x80)
|
||||
((uint32_t *)buffer32->line[displine + y_add])[offset + 32 + x_add] = 0;
|
||||
if (dat[0] & 0x80)
|
||||
((uint32_t *)buffer32->line[displine + y_add])[offset + 32 + x_add] ^= 0xffffff;
|
||||
}
|
||||
|
||||
offset++;
|
||||
dat[0] <<= 1;
|
||||
dat[1] <<= 1;
|
||||
offset++;
|
||||
dat[0] <<= 1;
|
||||
dat[1] <<= 1;
|
||||
}
|
||||
svga->hwcursor_latch.addr++;
|
||||
}
|
||||
svga->hwcursor_latch.addr++;
|
||||
}
|
||||
|
||||
if (svga->interlace && !svga->hwcursor_oddeven)
|
||||
svga->hwcursor_latch.addr += 4;
|
||||
|
||||
if (svga->hwcursor.xsize == 64)
|
||||
svga->hwcursor_latch.addr += 8;
|
||||
|
||||
if (svga->interlace && !svga->hwcursor_oddeven)
|
||||
svga->hwcursor_latch.addr += pitch;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
gd5428_copy_pixel(gd54xx_t *gd54xx, svga_t *svga, uint8_t src, uint8_t dst)
|
||||
gd54xx_memsrc_rop(gd54xx_t *gd54xx, svga_t *svga, uint8_t src, uint8_t dst)
|
||||
{
|
||||
uint8_t res = src;
|
||||
svga->changedvram[(gd54xx->blt.dst_addr_backup & svga->vram_mask) >> 12] = changeframecount;
|
||||
@@ -771,7 +844,7 @@ gd54xx_blit_dword(gd54xx_t *gd54xx, svga_t *svga)
|
||||
for (x=0;x<32;x+=8) {
|
||||
pixel = ((gd54xx->blt.sys_buf & (0xff << x)) >> x);
|
||||
if(gd54xx->blt.pixel_cnt <= gd54xx->blt.width)
|
||||
gd5428_copy_pixel(gd54xx, svga, pixel, svga->vram[gd54xx->blt.dst_addr_backup & svga->vram_mask]);
|
||||
gd54xx_memsrc_rop(gd54xx, svga, pixel, svga->vram[gd54xx->blt.dst_addr_backup & svga->vram_mask]);
|
||||
gd54xx->blt.dst_addr_backup++;
|
||||
gd54xx->blt.pixel_cnt++;
|
||||
}
|
||||
@@ -1143,7 +1216,7 @@ gd54xx_readb_linear(uint32_t addr, void *p)
|
||||
}
|
||||
|
||||
if ((addr & 0x003fff00) == 0x003fff00) {
|
||||
if ((svga->seqregs[0x17] & CIRRUS_MMIO_ENABLE) && (svga->seqregs[0x17] & 0x40))
|
||||
if ((svga->seqregs[0x17] & CIRRUS_MMIO_ENABLE) && (svga->seqregs[0x17] & CIRRUS_MMIO_USE_PCIADDR))
|
||||
return gd543x_mmio_read(addr & 0x000000ff, gd54xx);
|
||||
}
|
||||
|
||||
@@ -1163,7 +1236,7 @@ gd54xx_readw_linear(uint32_t addr, void *p)
|
||||
addr &= 0x003fffff; /* 4 MB mask */
|
||||
|
||||
if ((addr & 0x003fff00) == 0x003fff00) {
|
||||
if ((svga->seqregs[0x17] & CIRRUS_MMIO_ENABLE) && (svga->seqregs[0x17] & 0x40)) {
|
||||
if ((svga->seqregs[0x17] & CIRRUS_MMIO_ENABLE) && (svga->seqregs[0x17] & CIRRUS_MMIO_USE_PCIADDR)) {
|
||||
if (ap == 2)
|
||||
addr ^= 0x00000002;
|
||||
|
||||
@@ -1219,7 +1292,7 @@ gd54xx_readl_linear(uint32_t addr, void *p)
|
||||
addr &= 0x003fffff; /* 4 MB mask */
|
||||
|
||||
if ((addr & 0x003fff00) == 0x003fff00) {
|
||||
if ((svga->seqregs[0x17] & CIRRUS_MMIO_ENABLE) && (svga->seqregs[0x17] & 0x40)) {
|
||||
if ((svga->seqregs[0x17] & CIRRUS_MMIO_ENABLE) && (svga->seqregs[0x17] & CIRRUS_MMIO_USE_PCIADDR)) {
|
||||
temp = gd543x_mmio_readl(addr & 0x000000ff, gd54xx);
|
||||
|
||||
switch(ap) {
|
||||
@@ -1306,7 +1379,7 @@ gd54xx_writeb_linear(uint32_t addr, uint8_t val, void *p)
|
||||
}
|
||||
|
||||
if ((addr & 0x003fff00) == 0x003fff00) {
|
||||
if ((svga->seqregs[0x17] & CIRRUS_MMIO_ENABLE) && (svga->seqregs[0x17] & 0x40))
|
||||
if ((svga->seqregs[0x17] & CIRRUS_MMIO_ENABLE) && (svga->seqregs[0x17] & CIRRUS_MMIO_USE_PCIADDR))
|
||||
gd543x_mmio_write(addr & 0x000000ff, val, gd54xx);
|
||||
}
|
||||
|
||||
@@ -1340,7 +1413,7 @@ gd54xx_writew_linear(uint32_t addr, uint16_t val, void *p)
|
||||
uint16_t temp;
|
||||
|
||||
if ((addr & 0x003fff00) == 0x003fff00) {
|
||||
if ((svga->seqregs[0x17] & CIRRUS_MMIO_ENABLE) && (svga->seqregs[0x17] & 0x40)) {
|
||||
if ((svga->seqregs[0x17] & CIRRUS_MMIO_ENABLE) && (svga->seqregs[0x17] & CIRRUS_MMIO_USE_PCIADDR)) {
|
||||
switch(ap) {
|
||||
case 0:
|
||||
default:
|
||||
@@ -1414,7 +1487,7 @@ gd54xx_writel_linear(uint32_t addr, uint32_t val, void *p)
|
||||
uint32_t temp;
|
||||
|
||||
if ((addr & 0x003fff00) == 0x003fff00) {
|
||||
if ((svga->seqregs[0x17] & CIRRUS_MMIO_ENABLE) && (svga->seqregs[0x17] & 0x40)) {
|
||||
if ((svga->seqregs[0x17] & CIRRUS_MMIO_ENABLE) && (svga->seqregs[0x17] & CIRRUS_MMIO_USE_PCIADDR)) {
|
||||
switch(ap) {
|
||||
case 0:
|
||||
default:
|
||||
@@ -1540,7 +1613,7 @@ gd54xx_readl(uint32_t addr, void *p)
|
||||
static int
|
||||
gd543x_do_mmio(svga_t *svga, uint32_t addr)
|
||||
{
|
||||
if (svga->seqregs[0x17] & 0x40)
|
||||
if (svga->seqregs[0x17] & CIRRUS_MMIO_USE_PCIADDR)
|
||||
return 1;
|
||||
else
|
||||
return ((addr & ~0xff) == 0xb8000);
|
||||
@@ -1640,7 +1713,7 @@ gd543x_mmio_write(uint32_t addr, uint8_t val, void *p)
|
||||
else
|
||||
gd54xx->blt.dst_addr &= 0x1fffff;
|
||||
|
||||
if ((svga->crtc[0x27] >= CIRRUS_ID_CLGD5436) && (gd54xx->blt.bltstart & 0x80)) {
|
||||
if ((svga->crtc[0x27] == CIRRUS_ID_CLGD5436) && (gd54xx->blt.status & CIRRUS_BLT_AUTOSTART)) {
|
||||
if (gd54xx->blt.mode == CIRRUS_BLTMODE_MEMSYSSRC) {
|
||||
gd54xx->blt.sys_tx = 1;
|
||||
gd54xx->blt.sys_cnt = 0;
|
||||
@@ -1679,7 +1752,7 @@ gd543x_mmio_write(uint32_t addr, uint8_t val, void *p)
|
||||
break;
|
||||
|
||||
case 0x1b:
|
||||
if (svga->crtc[0x27] >= CIRRUS_ID_CLGD5436)
|
||||
if (svga->crtc[0x27] == CIRRUS_ID_CLGD5436)
|
||||
gd54xx->blt.modeext = val;
|
||||
break;
|
||||
|
||||
@@ -1700,8 +1773,8 @@ gd543x_mmio_write(uint32_t addr, uint8_t val, void *p)
|
||||
break;
|
||||
|
||||
case 0x40:
|
||||
gd54xx->blt.bltstart = val;
|
||||
if (gd54xx->blt.bltstart & 0x02) {
|
||||
gd54xx->blt.status = val;
|
||||
if (gd54xx->blt.status & CIRRUS_BLT_START) {
|
||||
if (gd54xx->blt.mode == CIRRUS_BLTMODE_MEMSYSSRC) {
|
||||
gd54xx->blt.sys_tx = 1;
|
||||
gd54xx->blt.sys_cnt = 0;
|
||||
@@ -1819,20 +1892,8 @@ gd54xx_start_blit(uint32_t cpu_dat, int count, gd54xx_t *gd54xx, svga_t *svga)
|
||||
blt_mask *= 2;
|
||||
break;
|
||||
case CIRRUS_BLTMODE_PIXELWIDTH24:
|
||||
if (svga->crtc[0x27] >= CIRRUS_ID_CLGD5436)
|
||||
{
|
||||
x_max = 24;
|
||||
if (gd54xx->blt.mode & CIRRUS_BLTMODE_PATTERNCOPY)
|
||||
{
|
||||
blt_mask = (gd54xx->blt.mask & 0x1f);
|
||||
blt_mask /= 3;
|
||||
}
|
||||
else
|
||||
{
|
||||
blt_mask = gd54xx->blt.mask & 7;
|
||||
blt_mask *= 3;
|
||||
}
|
||||
}
|
||||
blt_mask = (gd54xx->blt.mask & 0x1f);
|
||||
x_max = 24;
|
||||
break;
|
||||
case CIRRUS_BLTMODE_PIXELWIDTH32:
|
||||
blt_mask = gd54xx->blt.mask & 7;
|
||||
@@ -1873,7 +1934,7 @@ gd54xx_start_blit(uint32_t cpu_dat, int count, gd54xx_t *gd54xx, svga_t *svga)
|
||||
}
|
||||
else
|
||||
{
|
||||
mem_mapping_set_handler(&gd54xx->linear_mapping, svga_read_linear, svga_readw_linear, svga_readl_linear, gd54xx_writeb_linear, gd54xx_writew_linear, gd54xx_writel_linear);
|
||||
mem_mapping_set_handler(&gd54xx->linear_mapping, svga_readb_linear, svga_readw_linear, svga_readl_linear, gd54xx_writeb_linear, gd54xx_writew_linear, gd54xx_writel_linear);
|
||||
mem_mapping_set_p(&gd54xx->linear_mapping, svga);
|
||||
}
|
||||
gd543x_recalc_mapping(gd54xx);
|
||||
@@ -1912,19 +1973,16 @@ gd54xx_start_blit(uint32_t cpu_dat, int count, gd54xx_t *gd54xx, svga_t *svga)
|
||||
}
|
||||
break;
|
||||
case CIRRUS_BLTMODE_PIXELWIDTH24:
|
||||
if (svga->crtc[0x27] >= CIRRUS_ID_CLGD5436)
|
||||
if ((gd54xx->blt.x_count % 3) == 2)
|
||||
src = mask ? (gd54xx->blt.fg_col >> 16) : (gd54xx->blt.bg_col >> 16);
|
||||
else if ((gd54xx->blt.x_count % 3) == 1)
|
||||
src = mask ? (gd54xx->blt.fg_col >> 8) : (gd54xx->blt.bg_col >> 8);
|
||||
else
|
||||
src = mask ? gd54xx->blt.fg_col : gd54xx->blt.bg_col;
|
||||
if ((gd54xx->blt.x_count % 3) == 2)
|
||||
{
|
||||
if ((gd54xx->blt.x_count % 3) == 2)
|
||||
src = mask ? (gd54xx->blt.fg_col >> 16) : (gd54xx->blt.bg_col >> 16);
|
||||
else if ((gd54xx->blt.x_count % 3) == 1)
|
||||
src = mask ? (gd54xx->blt.fg_col >> 8) : (gd54xx->blt.bg_col >> 8);
|
||||
else
|
||||
src = mask ? gd54xx->blt.fg_col : gd54xx->blt.bg_col;
|
||||
if ((gd54xx->blt.x_count % 3) == 2)
|
||||
{
|
||||
cpu_dat <<= 1;
|
||||
count--;
|
||||
}
|
||||
cpu_dat <<= 1;
|
||||
count--;
|
||||
}
|
||||
break;
|
||||
case CIRRUS_BLTMODE_PIXELWIDTH32:
|
||||
@@ -1961,9 +2019,7 @@ gd54xx_start_blit(uint32_t cpu_dat, int count, gd54xx_t *gd54xx, svga_t *svga)
|
||||
src = svga->vram[(gd54xx->blt.src_addr & (svga->vram_mask & ~3)) + (gd54xx->blt.y_count << 4) + (gd54xx->blt.x_count & 15)];
|
||||
break;
|
||||
case CIRRUS_BLTMODE_PIXELWIDTH24:
|
||||
pclog("Pattern copy\n");
|
||||
if (svga->crtc[0x27] >= CIRRUS_ID_CLGD5436)
|
||||
src = svga->vram[(gd54xx->blt.src_addr & (svga->vram_mask & ~3)) + (gd54xx->blt.y_count << 5) + (gd54xx->blt.x_count % 24)];
|
||||
src = svga->vram[(gd54xx->blt.src_addr & (svga->vram_mask & ~3)) + (gd54xx->blt.y_count << 5) + (gd54xx->blt.x_count % 24)];
|
||||
break;
|
||||
case CIRRUS_BLTMODE_PIXELWIDTH32:
|
||||
src = svga->vram[(gd54xx->blt.src_addr & (svga->vram_mask & ~3)) + (gd54xx->blt.y_count << 5) + (gd54xx->blt.x_count & 31)];
|
||||
@@ -1986,20 +2042,19 @@ gd54xx_start_blit(uint32_t cpu_dat, int count, gd54xx_t *gd54xx, svga_t *svga)
|
||||
src = mask ? gd54xx->blt.fg_col : gd54xx->blt.bg_col;
|
||||
break;
|
||||
case CIRRUS_BLTMODE_PIXELWIDTH24:
|
||||
if (svga->crtc[0x27] >= CIRRUS_ID_CLGD5436)
|
||||
{
|
||||
mask = svga->vram[gd54xx->blt.src_addr & svga->vram_mask] & (0x80 >> (gd54xx->blt.x_count / 3));
|
||||
if ((gd54xx->blt.dst_addr % 3) == 2)
|
||||
src = mask ? (gd54xx->blt.fg_col >> 16) : (gd54xx->blt.bg_col >> 16);
|
||||
else if ((gd54xx->blt.dst_addr % 3) == 1)
|
||||
src = mask ? (gd54xx->blt.fg_col >> 8) : (gd54xx->blt.bg_col >> 8);
|
||||
else
|
||||
src = mask ? gd54xx->blt.fg_col : gd54xx->blt.bg_col;
|
||||
}
|
||||
mask = svga->vram[gd54xx->blt.src_addr & svga->vram_mask] & (0x80 >> (gd54xx->blt.x_count / 3));
|
||||
if ((gd54xx->blt.dst_addr % 3) == 2)
|
||||
src = mask ? (gd54xx->blt.fg_col >> 16) : (gd54xx->blt.bg_col >> 16);
|
||||
else if ((gd54xx->blt.dst_addr % 3) == 1)
|
||||
src = mask ? (gd54xx->blt.fg_col >> 8) : (gd54xx->blt.bg_col >> 8);
|
||||
else
|
||||
src = mask ? gd54xx->blt.fg_col : gd54xx->blt.bg_col;
|
||||
break;
|
||||
case CIRRUS_BLTMODE_PIXELWIDTH32:
|
||||
mask = svga->vram[gd54xx->blt.src_addr & svga->vram_mask] & (0x80 >> (gd54xx->blt.x_count >> 2));
|
||||
if ((gd54xx->blt.dst_addr & 3) == 2)
|
||||
if ((gd54xx->blt.dst_addr & 3) == 3)
|
||||
src = mask ? (gd54xx->blt.fg_col >> 24) : (gd54xx->blt.bg_col >> 24);
|
||||
else if ((gd54xx->blt.dst_addr & 3) == 2)
|
||||
src = mask ? (gd54xx->blt.fg_col >> 16) : (gd54xx->blt.bg_col >> 16);
|
||||
else if ((gd54xx->blt.dst_addr & 3) == 1)
|
||||
src = mask ? (gd54xx->blt.fg_col >> 8) : (gd54xx->blt.bg_col >> 8);
|
||||
@@ -2059,7 +2114,7 @@ gd54xx_start_blit(uint32_t cpu_dat, int count, gd54xx_t *gd54xx, svga_t *svga)
|
||||
src = mask ? gd54xx->blt.fg_col : gd54xx->blt.bg_col;
|
||||
break;
|
||||
case CIRRUS_BLTMODE_PIXELWIDTH24:
|
||||
if (svga->crtc[0x27] >= CIRRUS_ID_CLGD5436)
|
||||
if (svga->crtc[0x27] == CIRRUS_ID_CLGD5436)
|
||||
{
|
||||
mask = svga->vram[(gd54xx->blt.src_addr & svga->vram_mask & ~7) | gd54xx->blt.y_count] & (0x80 >> (gd54xx->blt.x_count / 3));
|
||||
if ((gd54xx->blt.dst_addr % 3) == 2)
|
||||
@@ -2126,7 +2181,9 @@ gd54xx_start_blit(uint32_t cpu_dat, int count, gd54xx_t *gd54xx, svga_t *svga)
|
||||
gd54xx->blt.dst_addr += ((gd54xx->blt.mode & CIRRUS_BLTMODE_BACKWARDS) ? -1 : 1);
|
||||
|
||||
gd54xx->blt.x_count++;
|
||||
if (gd54xx->blt.x_count == x_max) {
|
||||
|
||||
if (gd54xx->blt.x_count == x_max)
|
||||
{
|
||||
gd54xx->blt.x_count = 0;
|
||||
if ((gd54xx->blt.mode & (CIRRUS_BLTMODE_PATTERNCOPY|CIRRUS_BLTMODE_COLOREXPAND)) == CIRRUS_BLTMODE_COLOREXPAND)
|
||||
gd54xx->blt.src_addr++;
|
||||
@@ -2166,7 +2223,7 @@ gd54xx_start_blit(uint32_t cpu_dat, int count, gd54xx_t *gd54xx, svga_t *svga)
|
||||
}
|
||||
else
|
||||
{
|
||||
mem_mapping_set_handler(&gd54xx->linear_mapping, svga_read_linear, svga_readw_linear, svga_readl_linear, gd54xx_writeb_linear, gd54xx_writew_linear, gd54xx_writel_linear);
|
||||
mem_mapping_set_handler(&gd54xx->linear_mapping, svga_readb_linear, svga_readw_linear, svga_readl_linear, gd54xx_writeb_linear, gd54xx_writew_linear, gd54xx_writel_linear);
|
||||
mem_mapping_set_p(&gd54xx->linear_mapping, svga);
|
||||
}
|
||||
gd543x_recalc_mapping(gd54xx);
|
||||
@@ -2192,16 +2249,10 @@ cl_pci_read(int func, int addr, void *p)
|
||||
case 0x01: return 0x10;
|
||||
|
||||
case 0x02:
|
||||
switch (svga->crtc[0x27]) {
|
||||
case CIRRUS_ID_CLGD5430:
|
||||
return 0xa0;
|
||||
case CIRRUS_ID_CLGD5434:
|
||||
return 0xa8;
|
||||
case CIRRUS_ID_CLGD5436:
|
||||
return 0xac;
|
||||
}
|
||||
return 0xff;
|
||||
return svga->crtc[0x27];
|
||||
|
||||
case 0x03: return 0x00;
|
||||
|
||||
case PCI_REG_COMMAND:
|
||||
return gd54xx->pci_regs[PCI_REG_COMMAND]; /*Respond to IO and memory accesses*/
|
||||
|
||||
@@ -2218,10 +2269,10 @@ cl_pci_read(int func, int addr, void *p)
|
||||
case 0x12: return 0x00;
|
||||
case 0x13: return gd54xx->lfb_base >> 24;
|
||||
|
||||
case 0x30: return (gd54xx->has_bios) ? (gd54xx->pci_regs[0x30] & 0x01) : 0x00; /*BIOS ROM address*/
|
||||
case 0x30: return (gd54xx->pci_regs[0x30] & 0x01); /*BIOS ROM address*/
|
||||
case 0x31: return 0x00;
|
||||
case 0x32: return (gd54xx->has_bios) ? gd54xx->pci_regs[0x32] : 0x00;
|
||||
case 0x33: return (gd54xx->has_bios) ? gd54xx->pci_regs[0x33] : 0x00;
|
||||
case 0x32: return gd54xx->pci_regs[0x32];
|
||||
case 0x33: return gd54xx->pci_regs[0x33];
|
||||
|
||||
case 0x3c: return gd54xx->int_line;
|
||||
case 0x3d: return PCI_INTA;
|
||||
@@ -2250,8 +2301,6 @@ cl_pci_write(int func, int addr, uint8_t val, void *p)
|
||||
break;
|
||||
|
||||
case 0x30: case 0x32: case 0x33:
|
||||
if (!(gd54xx->has_bios))
|
||||
return;
|
||||
gd54xx->pci_regs[addr] = val;
|
||||
if (gd54xx->pci_regs[0x30] & 0x01) {
|
||||
uint32_t addr = (gd54xx->pci_regs[0x32] << 16) | (gd54xx->pci_regs[0x33] << 24);
|
||||
@@ -2272,21 +2321,20 @@ gd54xx_init(const device_t *info)
|
||||
{
|
||||
gd54xx_t *gd54xx = malloc(sizeof(gd54xx_t));
|
||||
svga_t *svga = &gd54xx->svga;
|
||||
int id = info->local & 0x7FFF;
|
||||
int id = info->local;
|
||||
wchar_t *romfn = NULL;
|
||||
memset(gd54xx, 0, sizeof(gd54xx_t));
|
||||
|
||||
gd54xx->has_bios = !(info->local & 0x8000);
|
||||
|
||||
gd54xx->pci = !!(info->flags & DEVICE_PCI);
|
||||
gd54xx->vlb = !!(info->flags & DEVICE_VLB);
|
||||
|
||||
switch (id) {
|
||||
case CIRRUS_ID_CLGD5426:
|
||||
romfn = BIOS_GD5426_PATH;
|
||||
break;
|
||||
|
||||
case CIRRUS_ID_CLGD5428:
|
||||
if (gd54xx->vlb)
|
||||
romfn = BIOS_GD5428_VLB_PATH;
|
||||
else
|
||||
romfn = BIOS_GD5428_ISA_PATH;
|
||||
romfn = BIOS_GD5428_PATH;
|
||||
break;
|
||||
|
||||
case CIRRUS_ID_CLGD5429:
|
||||
@@ -2312,7 +2360,6 @@ gd54xx_init(const device_t *info)
|
||||
gd54xx->vram_size = device_get_config_int("memory");
|
||||
gd54xx->vram_mask = (gd54xx->vram_size << 20) - 1;
|
||||
|
||||
if (gd54xx->has_bios)
|
||||
rom_init(&gd54xx->bios_rom, romfn, 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL);
|
||||
|
||||
svga_init(&gd54xx->svga, gd54xx, gd54xx->vram_size << 20,
|
||||
@@ -2327,23 +2374,6 @@ gd54xx_init(const device_t *info)
|
||||
|
||||
io_sethandler(0x03c0, 0x0020, gd54xx_in, NULL, NULL, gd54xx_out, NULL, NULL, gd54xx);
|
||||
|
||||
svga->decode_mask = (4 << 20) - 1;
|
||||
|
||||
switch (gd54xx->vram_size) {
|
||||
case 1: /*1MB*/
|
||||
svga->vram_mask = (1 << 20) - 1;
|
||||
svga->vram_max = 1 << 20;
|
||||
break;
|
||||
case 2: /*2MB*/
|
||||
svga->vram_mask = (2 << 20) - 1;
|
||||
svga->vram_max = 2 << 20;
|
||||
break;
|
||||
case 4: /*4MB*/
|
||||
svga->vram_mask = (4 << 20) - 1;
|
||||
svga->vram_max = 4 << 20;
|
||||
break;
|
||||
}
|
||||
|
||||
svga->hwcursor.yoff = 32;
|
||||
svga->hwcursor.xoff = 0;
|
||||
|
||||
@@ -2354,10 +2384,10 @@ gd54xx_init(const device_t *info)
|
||||
|
||||
gd54xx->bank[1] = 0x8000;
|
||||
|
||||
if ((info->flags & DEVICE_PCI) && id >= CIRRUS_ID_CLGD5430)
|
||||
if (gd54xx->pci && id >= CIRRUS_ID_CLGD5430)
|
||||
pci_add_card(PCI_ADD_VIDEO, cl_pci_read, cl_pci_write, gd54xx);
|
||||
|
||||
gd54xx->pci_regs[0x04] = 7;
|
||||
gd54xx->pci_regs[PCI_REG_COMMAND] = 7;
|
||||
|
||||
gd54xx->pci_regs[0x30] = 0x00;
|
||||
gd54xx->pci_regs[0x32] = 0x0c;
|
||||
@@ -2369,19 +2399,17 @@ gd54xx_init(const device_t *info)
|
||||
}
|
||||
|
||||
static int
|
||||
gd5428_isa_available(void)
|
||||
gd5426_available(void)
|
||||
{
|
||||
return rom_present(BIOS_GD5428_ISA_PATH);
|
||||
return rom_present(BIOS_GD5426_PATH);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
gd5428_vlb_available(void)
|
||||
gd5428_available(void)
|
||||
{
|
||||
return rom_present(BIOS_GD5428_VLB_PATH);
|
||||
return rom_present(BIOS_GD5428_PATH);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
gd5429_available(void)
|
||||
{
|
||||
@@ -2505,6 +2533,21 @@ static const device_config_t gd5434_config[] =
|
||||
};
|
||||
|
||||
|
||||
const device_t gd5426_vlb_device =
|
||||
{
|
||||
"Cirrus Logic GD5426 (VLB)",
|
||||
DEVICE_VLB,
|
||||
CIRRUS_ID_CLGD5426,
|
||||
gd54xx_init,
|
||||
gd54xx_close,
|
||||
NULL,
|
||||
gd5426_available,
|
||||
gd54xx_speed_changed,
|
||||
gd54xx_force_redraw,
|
||||
gd54xx_add_status_info,
|
||||
gd5428_config
|
||||
};
|
||||
|
||||
const device_t gd5428_isa_device =
|
||||
{
|
||||
"Cirrus Logic GD5428 (ISA)",
|
||||
@@ -2513,7 +2556,7 @@ const device_t gd5428_isa_device =
|
||||
gd54xx_init,
|
||||
gd54xx_close,
|
||||
NULL,
|
||||
gd5428_isa_available,
|
||||
gd5428_available,
|
||||
gd54xx_speed_changed,
|
||||
gd54xx_force_redraw,
|
||||
gd54xx_add_status_info,
|
||||
@@ -2528,7 +2571,7 @@ const device_t gd5428_vlb_device =
|
||||
gd54xx_init,
|
||||
gd54xx_close,
|
||||
NULL,
|
||||
gd5428_vlb_available,
|
||||
gd5428_available,
|
||||
gd54xx_speed_changed,
|
||||
gd54xx_force_redraw,
|
||||
gd54xx_add_status_info,
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*
|
||||
* Definitions for the CLGD5428 driver.
|
||||
*
|
||||
* Version: @(#)vid_cl54xx.h 1.0.4 2018/03/15
|
||||
* Version: @(#)vid_cl54xx.h 1.0.5 2018/03/17
|
||||
*
|
||||
* Authors: Fred N. van Kempen, <decwiz@yahoo.com>
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
@@ -40,6 +40,7 @@
|
||||
# define VIDEO_CL54XX_H
|
||||
|
||||
|
||||
extern const device_t gd5426_vlb_device;
|
||||
extern const device_t gd5428_isa_device;
|
||||
extern const device_t gd5428_vlb_device;
|
||||
extern const device_t gd5429_isa_device;
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
* This is intended to be used by another SVGA driver,
|
||||
* and not as a card in it's own right.
|
||||
*
|
||||
* Version: @(#)vid_svga.c 1.0.6 2018/03/12
|
||||
* Version: @(#)vid_svga.c 1.0.7 2018/03/17
|
||||
*
|
||||
* Authors: Fred N. van Kempen, <decwiz@yahoo.com>
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
@@ -314,44 +314,11 @@ uint8_t svga_in(uint16_t addr, void *p)
|
||||
case 0x3DA:
|
||||
svga->attrff = 0;
|
||||
|
||||
#if 0
|
||||
/* old diagnostic code */
|
||||
if (svga->cgastat & 0x01)
|
||||
svga->cgastat &= ~0x30;
|
||||
else
|
||||
svga->cgastat ^= 0x30;
|
||||
return svga->cgastat;
|
||||
#endif
|
||||
svga->cgastat &= ~0x30;
|
||||
/* copy color diagnostic info from the overscan color register */
|
||||
switch (svga->attrregs[0x12] & 0x30)
|
||||
{
|
||||
case 0x00: /* P0 and P2 */
|
||||
if (svga->attrregs[0x11] & 0x01)
|
||||
svga->cgastat |= 0x10;
|
||||
if (svga->attrregs[0x11] & 0x04)
|
||||
svga->cgastat |= 0x20;
|
||||
break;
|
||||
case 0x10: /* P4 and P5 */
|
||||
if (svga->attrregs[0x11] & 0x10)
|
||||
svga->cgastat |= 0x10;
|
||||
if (svga->attrregs[0x11] & 0x20)
|
||||
svga->cgastat |= 0x20;
|
||||
break;
|
||||
case 0x20: /* P1 and P3 */
|
||||
if (svga->attrregs[0x11] & 0x02)
|
||||
svga->cgastat |= 0x10;
|
||||
if (svga->attrregs[0x11] & 0x08)
|
||||
svga->cgastat |= 0x20;
|
||||
break;
|
||||
case 0x30: /* P6 and P7 */
|
||||
if (svga->attrregs[0x11] & 0x40)
|
||||
svga->cgastat |= 0x10;
|
||||
if (svga->attrregs[0x11] & 0x80)
|
||||
svga->cgastat |= 0x20;
|
||||
break;
|
||||
}
|
||||
return svga->cgastat;
|
||||
}
|
||||
return 0xFF;
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*
|
||||
* SVGA renderers.
|
||||
*
|
||||
* Version: @(#)vid_svga_render.c 1.0.6 2018/03/14
|
||||
* Version: @(#)vid_svga_render.c 1.0.7 2018/03/17
|
||||
*
|
||||
* Authors: Fred N. van Kempen, <decwiz@yahoo.com>
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
@@ -330,7 +330,7 @@ void svga_render_text_80_ksc5601(svga_t *svga)
|
||||
dat = svga->vram[charaddr + (svga->sc << 2)];
|
||||
if(x + xinc < svga->hdisp && (chr & nextchr & 0x80))
|
||||
{
|
||||
dat = fontdatksc5601[((chr & 0x7F) << 7) | (nextchr & 0x7F)][svga->sc];
|
||||
dat = fontdatksc5601[((chr & 0x7F) << 7) | (nextchr & 0x7F)].chr[svga->sc];
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -377,7 +377,7 @@ void svga_render_text_80_ksc5601(svga_t *svga)
|
||||
}
|
||||
}
|
||||
|
||||
dat = fontdatksc5601[((chr & 0x7F) << 7) | (nextchr & 0x7F)][svga->sc + 16];
|
||||
dat = fontdatksc5601[((chr & 0x7F) << 7) | (nextchr & 0x7F)].chr[svga->sc + 16];
|
||||
if (svga->seqregs[1] & 1)
|
||||
{
|
||||
for (xx = 0; xx < 8; xx++)
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*
|
||||
* Define all known video cards.
|
||||
*
|
||||
* Version: @(#)vid_table.c 1.0.9 2018/03/15
|
||||
* Version: @(#)vid_table.c 1.0.10 2018/03/17
|
||||
*
|
||||
* Authors: Fred N. van Kempen, <decwiz@yahoo.com>
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
@@ -163,7 +163,7 @@ video_cards[] = {
|
||||
{"[VLB] Cardex Tseng ET4000/w32p", "et4000w32p_vlb", &et4000w32p_cardex_vlb_device, VID_ET4000W32_CARDEX_VLB, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_BUS, 4, 4, 4, 10, 10, 10}},
|
||||
{"[VLB] Cirrus Logic GD5429", "cl_gd5429_vlb", &gd5429_vlb_device, VID_CL_GD5429_VLB, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_BUS, 4, 4, 8, 10, 10, 20}},
|
||||
{"[VLB] Cirrus Logic GD5434", "cl_gd5434_vlb", &gd5434_vlb_device, VID_CL_GD5434_VLB, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_BUS, 4, 4, 8, 10, 10, 20}},
|
||||
{"[VLB] Diamond SpeedStar PRO (CL GD5428)", "cl_gd5428_vlb", &gd5428_vlb_device, VID_CL_GD5428_VLB, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_BUS, 4, 4, 8, 10, 10, 20}},
|
||||
{"[VLB] Diamond SpeedStar PRO (CL-GD5426)", "cl_gd5426_vlb", &gd5426_vlb_device, VID_CL_GD5426_VLB, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_BUS, 4, 4, 8, 10, 10, 20}},
|
||||
{"[VLB] Diamond SpeedStar PRO SE (CL GD5430)", "cl_gd5430_vlb", &gd5430_vlb_device, VID_CL_GD5430_VLB, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_BUS, 4, 4, 8, 10, 10, 20}},
|
||||
#if defined(DEV_BRANCH) && defined(USE_STEALTH32)
|
||||
{"[VLB] Diamond Stealth 32 (Tseng ET4000/w32p)", "stealth32_vlb", &et4000w32p_vlb_device, VID_ET4000W32_VLB, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_BUS, 4, 4, 4, 10, 10, 10}},
|
||||
@@ -220,6 +220,11 @@ video_reset(int card)
|
||||
if ((card == VID_NONE) || \
|
||||
(card == VID_INTERNAL) || machines[machine].fixed_vidcard) return;
|
||||
|
||||
if (fontdatksc5601 != NULL) {
|
||||
free(fontdatksc5601);
|
||||
fontdatksc5601 = NULL;
|
||||
}
|
||||
|
||||
/* Initialize the video card. */
|
||||
device_add(video_cards[video_old_to_new(card)].device);
|
||||
|
||||
|
||||
@@ -40,7 +40,7 @@
|
||||
* W = 3 bus clocks
|
||||
* L = 4 bus clocks
|
||||
*
|
||||
* Version: @(#)video.c 1.0.5 2018/03/15
|
||||
* Version: @(#)video.c 1.0.6 2018/03/17
|
||||
*
|
||||
* Authors: Fred N. van Kempen, <decwiz@yahoo.com>
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
@@ -101,7 +101,7 @@ uint8_t fontdat[2048][8]; /* IBM CGA font */
|
||||
uint8_t fontdatm[2048][16]; /* IBM MDA font */
|
||||
uint8_t fontdatw[512][32]; /* Wyse700 font */
|
||||
uint8_t fontdat8x12[256][16]; /* MDSI Genius font */
|
||||
uint8_t fontdatksc5601[16384][32]; /* Korean KSC-5601 font */
|
||||
dbcs_font_t *fontdatksc5601; /* Korean KSC-5601 font */
|
||||
uint32_t pal_lookup[256];
|
||||
int xsize = 1,
|
||||
ysize = 1;
|
||||
@@ -679,6 +679,11 @@ video_close(void)
|
||||
|
||||
destroy_bitmap(buffer);
|
||||
destroy_bitmap(buffer32);
|
||||
|
||||
if (fontdatksc5601 != NULL) {
|
||||
free(fontdatksc5601);
|
||||
fontdatksc5601 = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -775,9 +780,12 @@ loadfont(wchar_t *s, int format)
|
||||
break;
|
||||
|
||||
case 6: /* Korean KSC-5601 */
|
||||
if (fontdatksc5601 == NULL)
|
||||
fontdatksc5601 = malloc(16384 * sizeof(dbcs_font_t));
|
||||
|
||||
for (c=0;c<16384;c++) {
|
||||
for (d=0;d<32;d++)
|
||||
fontdatksc5601[c][d]=getc(f);
|
||||
fontdatksc5601[c].chr[d]=getc(f);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*
|
||||
* Definitions for the video controller module.
|
||||
*
|
||||
* Version: @(#)video.h 1.0.6 2018/03/15
|
||||
* Version: @(#)video.h 1.0.8 2018/03/17
|
||||
*
|
||||
* Authors: Fred N. van Kempen, <decwiz@yahoo.com>
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
@@ -94,11 +94,12 @@ enum {
|
||||
VID_MACH64VT2, /* ATI Mach64 VT2 */
|
||||
VID_CL_GD5424_ISA, /* Cirrus Logic GD5424 ISA */
|
||||
VID_CL_GD5424_VLB, /* Cirrus Logic GD5424 VLB */
|
||||
VID_CL_GD5426_VLB, /* Diamond SpeedStar PRO (Cirrus Logic GD5426) VLB */
|
||||
VID_CL_GD5428_ISA, /* Cirrus Logic GD5428 ISA */
|
||||
VID_CL_GD5428_VLB, /* Diamond SpeedStar PRO (Cirrus Logic GD5428) VLB */
|
||||
VID_CL_GD5428_VLB, /* Cirrus Logic GD5428 VLB */
|
||||
VID_CL_GD5429_ISA, /* Cirrus Logic GD5429 ISA */
|
||||
VID_CL_GD5429_VLB, /* Cirrus Logic GD5429 VLB */
|
||||
VID_CL_GD5430_VLB, /* Diamond SpeedStar PRO SE (Cirrus Logic GD5430) PCI */
|
||||
VID_CL_GD5430_VLB, /* Diamond SpeedStar PRO SE (Cirrus Logic GD5430) VLB */
|
||||
VID_CL_GD5430_PCI, /* Cirrus Logic GD5430 PCI */
|
||||
VID_CL_GD5434_ISA, /* Cirrus Logic GD5434 ISA */
|
||||
VID_CL_GD5434_VLB, /* Cirrus Logic GD5434 VLB */
|
||||
@@ -163,6 +164,10 @@ typedef struct {
|
||||
uint8_t r, g, b;
|
||||
} rgb_t;
|
||||
|
||||
typedef struct {
|
||||
uint8_t chr[32];
|
||||
} dbcs_font_t;
|
||||
|
||||
typedef rgb_t PALETTE[256];
|
||||
|
||||
|
||||
@@ -183,7 +188,7 @@ extern int video_fullscreen,
|
||||
extern int fullchange;
|
||||
extern uint8_t fontdat[2048][8];
|
||||
extern uint8_t fontdatm[2048][16];
|
||||
extern uint8_t fontdatksc5601[16384][32];
|
||||
extern dbcs_font_t *fontdatksc5601;
|
||||
extern uint32_t *video_6to8,
|
||||
*video_15to32,
|
||||
*video_16to32;
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
#
|
||||
# Makefile for Windows systems using the MinGW32 environment.
|
||||
#
|
||||
# Version: @(#)Makefile.mingw 1.0.13 2018/03/14
|
||||
# Version: @(#)Makefile.mingw 1.0.14 2018/03/17
|
||||
#
|
||||
# Author: Fred N. van Kempen, <decwiz@yahoo.com>
|
||||
#
|
||||
@@ -95,6 +95,9 @@ endif
|
||||
ifndef RDP
|
||||
RDP := n
|
||||
endif
|
||||
ifndef PNG
|
||||
PNG := n
|
||||
endif
|
||||
ifndef DEV_BUILD
|
||||
DEV_BUILD := n
|
||||
endif
|
||||
@@ -347,10 +350,11 @@ endif
|
||||
|
||||
ifneq ($(WX), n)
|
||||
OPTS += -DUSE_WX $(WX_FLAGS)
|
||||
LIBS += $(WX_LIBS) -lz -lm
|
||||
LIBS += $(WX_LIBS) -lm
|
||||
UIOBJ := wx_main.o wx_ui.o wx_stbar.o wx_render.o
|
||||
else
|
||||
UIOBJ := win_ui.o win_ddraw.o win_d3d.o win_png.o \
|
||||
UIOBJ := win_ui.o \
|
||||
win_ddraw.o win_d3d.o \
|
||||
win_dialog.o win_about.o win_status.o win_stbar.o \
|
||||
win_settings.o win_devconf.o win_snd_gain.o \
|
||||
win_new_floppy.o win_jsconf.o
|
||||
@@ -383,7 +387,7 @@ RFLAGS += -DUSE_VNC
|
||||
endif
|
||||
VNCLIB += -lvncserver
|
||||
VNCOBJ := vnc.o vnc_keymap.o
|
||||
LIBS += $(VNCLIB) -lws2_32 -lz
|
||||
LIBS += $(VNCLIB) -lws2_32
|
||||
endif
|
||||
|
||||
ifeq ($(RDP), y)
|
||||
@@ -398,6 +402,12 @@ RDPOBJ := rdp.o
|
||||
LIBS += $(RDPLIB)
|
||||
endif
|
||||
|
||||
ifeq ($(PNG), y)
|
||||
OPTS += -DUSE_PNG
|
||||
RFLAGS += -DUSE_PNG
|
||||
LIBS += -lpng -lz
|
||||
endif
|
||||
|
||||
# Options for the DEV branch.
|
||||
ifeq ($(DEV_BRANCH), y)
|
||||
OPTS += -DDEV_BRANCH
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*
|
||||
* Platform main support module for Windows.
|
||||
*
|
||||
* Version: @(#)win.c 1.0.7 2018/03/10
|
||||
* Version: @(#)win.c 1.0.8 2018/03/17
|
||||
*
|
||||
* Authors: Fred N. van Kempen, <decwiz@yahoo.com>
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
@@ -833,32 +833,27 @@ take_screenshot(void)
|
||||
|
||||
wcscat(path, L"\\");
|
||||
|
||||
wcsftime(fn, 128, L"%Y%m%d_%H%M%S.png", info);
|
||||
wcscat(path, fn);
|
||||
|
||||
switch(vid_api) {
|
||||
#ifdef USE_WX
|
||||
case 0:
|
||||
case 1:
|
||||
wcsftime(fn, 128, L"%Y%m%d_%H%M%S.png", info);
|
||||
wcscat(path, fn);
|
||||
wx_screenshot(path);
|
||||
break;
|
||||
#else
|
||||
case 0: /* ddraw */
|
||||
wcsftime(fn, 128, L"%Y%m%d_%H%M%S.bmp", info);
|
||||
wcscat(path, fn);
|
||||
ddraw_take_screenshot(path);
|
||||
break;
|
||||
|
||||
case 1: /* d3d9 */
|
||||
wcsftime(fn, 128, L"%Y%m%d_%H%M%S.png", info);
|
||||
wcscat(path, fn);
|
||||
d3d_take_screenshot(path);
|
||||
break;
|
||||
#endif
|
||||
|
||||
#ifdef USE_VNC
|
||||
case 2: /* vnc */
|
||||
wcsftime(fn, 128, L"%Y%m%d_%H%M%S.png", info);
|
||||
wcscat(path, fn);
|
||||
vnc_take_screenshot(path);
|
||||
break;
|
||||
#endif
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
* Implementation of the CD-ROM host drive IOCTL interface for
|
||||
* Windows using SCSI Passthrough Direct.
|
||||
*
|
||||
* Version: @(#)cdrom_ioctl.c 1.0.4 2018/03/08
|
||||
* Version: @(#)cdrom_ioctl.c 1.0.5 2018/03/17
|
||||
*
|
||||
* Authors: Fred N. van Kempen, <decwiz@yahoo.com>
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
@@ -118,9 +118,9 @@ void ioctl_audio_callback(uint8_t id, int16_t *output, int len)
|
||||
in.DiskOffset.HighPart = 0;
|
||||
in.SectorCount = 1;
|
||||
in.TrackMode = CDDA;
|
||||
if (!DeviceIoControl(cdrom_ioctl_windows[id].hIOCTL, IOCTL_CDROM_RAW_READ, &in, sizeof(in), &(cdrom_ioctl[id].cd_buffer[cdrom_ioctl[id].cd_buflen]), 2352, &count, NULL))
|
||||
if (!DeviceIoControl(cdrom_ioctl_windows[id].hIOCTL, IOCTL_CDROM_RAW_READ, &in, sizeof(in), &(cdrom[id].cd_buffer[cdrom_ioctl[id].cd_buflen]), 2352, &count, NULL))
|
||||
{
|
||||
memset(&(cdrom_ioctl[id].cd_buffer[cdrom_ioctl[id].cd_buflen]), 0, (BUF_SIZE - cdrom_ioctl[id].cd_buflen) * 2);
|
||||
memset(&(cdrom[id].cd_buffer[cdrom_ioctl[id].cd_buflen]), 0, (BUF_SIZE - cdrom_ioctl[id].cd_buflen) * 2);
|
||||
cdrom_ioctl_windows[id].is_playing = 0;
|
||||
ioctl_close(id);
|
||||
cdrom_ioctl[id].cd_state = CD_STOPPED;
|
||||
@@ -134,15 +134,15 @@ void ioctl_audio_callback(uint8_t id, int16_t *output, int len)
|
||||
}
|
||||
else
|
||||
{
|
||||
memset(&(cdrom_ioctl[id].cd_buffer[cdrom_ioctl[id].cd_buflen]), 0, (BUF_SIZE - cdrom_ioctl[id].cd_buflen) * 2);
|
||||
memset(&(cdrom[id].cd_buffer[cdrom_ioctl[id].cd_buflen]), 0, (BUF_SIZE - cdrom_ioctl[id].cd_buflen) * 2);
|
||||
cdrom_ioctl_windows[id].is_playing = 0;
|
||||
ioctl_close(id);
|
||||
cdrom_ioctl[id].cd_state = CD_STOPPED;
|
||||
cdrom_ioctl[id].cd_buflen = len;
|
||||
}
|
||||
}
|
||||
memcpy(output, cdrom_ioctl[id].cd_buffer, len * 2);
|
||||
memcpy(&cdrom_ioctl[id].cd_buffer[0], &(cdrom_ioctl[id].cd_buffer[len]), (BUF_SIZE - len) * 2);
|
||||
memcpy(output, cdrom[id].cd_buffer, len * 2);
|
||||
memcpy(&cdrom[id].cd_buffer[0], &(cdrom[id].cd_buffer[len]), (BUF_SIZE - len) * 2);
|
||||
cdrom_ioctl[id].cd_buflen -= len;
|
||||
}
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
* NOTES: This code should be re-merged into a single init() with a
|
||||
* 'fullscreen' argument, indicating FS mode is requested.
|
||||
*
|
||||
* Version: @(#)win_ddraw.cpp 1.0.2 2018/03/07
|
||||
* Version: @(#)win_ddraw.cpp 1.0.3 2018/03/17
|
||||
*
|
||||
* Authors: Fred N. van Kempen, <decwiz@yahoo.com>
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
@@ -44,6 +44,10 @@
|
||||
#include <ddraw.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#ifdef USE_LIBPNG
|
||||
# define PNG_DEBUG 0
|
||||
# include <png.h>
|
||||
#endif
|
||||
#include "../emu.h"
|
||||
#include "../device.h"
|
||||
#include "../video/video.h"
|
||||
@@ -51,7 +55,6 @@
|
||||
#include "../ui.h"
|
||||
#include "win.h"
|
||||
#include "win_ddraw.h"
|
||||
#include "win_png.h"
|
||||
|
||||
|
||||
static LPDIRECTDRAW lpdd = NULL;
|
||||
@@ -65,6 +68,10 @@ static HWND ddraw_hwnd;
|
||||
static HBITMAP hbitmap;
|
||||
static int ddraw_w, ddraw_h,
|
||||
xs, ys, ys2;
|
||||
#ifdef USE_LIBPNG
|
||||
static png_structp png_ptr;
|
||||
static png_infop png_info_ptr;
|
||||
#endif
|
||||
|
||||
|
||||
static void
|
||||
@@ -88,6 +95,159 @@ CopySurface(IDirectDrawSurface4 *pDDSurface)
|
||||
}
|
||||
|
||||
|
||||
#ifdef USE_LIBPNG
|
||||
static void
|
||||
bgra_to_rgb(png_bytep *b_rgb, uint8_t *bgra, int width, int height)
|
||||
{
|
||||
int i, j;
|
||||
uint8_t *r, *b;
|
||||
|
||||
for (i = 0; i < height; i++) {
|
||||
for (j = 0; j < width; j++) {
|
||||
r = &b_rgb[(height - 1) - i][j * 3];
|
||||
b = &bgra[((i * width) + j) * 4];
|
||||
r[0] = b[2];
|
||||
r[1] = b[1];
|
||||
r[2] = b[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
SavePNG(wchar_t *szFilename, HBITMAP hBitmap)
|
||||
{
|
||||
static WCHAR szMessage[512];
|
||||
BITMAPFILEHEADER bmpFileHeader;
|
||||
BITMAPINFO bmpInfo;
|
||||
HDC hdc;
|
||||
LPVOID pBuf = NULL;
|
||||
LPVOID pBuf2 = NULL;
|
||||
png_bytep *b_rgb = NULL;
|
||||
FILE *fp;
|
||||
int i;
|
||||
|
||||
/* Create file. */
|
||||
fp = plat_fopen(szFilename, (wchar_t *) L"wb");
|
||||
if (fp == NULL) {
|
||||
pclog("[SavePNG] File %ls could not be opened for writing", szFilename);
|
||||
_swprintf(szMessage, plat_get_string(IDS_2088), szFilename);
|
||||
ui_msgbox(MBX_ERROR, szMessage);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Initialize PNG stuff. */
|
||||
png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING,
|
||||
NULL, NULL, NULL);
|
||||
if (png_ptr == NULL) {
|
||||
fclose(fp);
|
||||
pclog("[SavePNG] png_create_write_struct failed");
|
||||
_swprintf(szMessage, plat_get_string(IDS_2088), szFilename);
|
||||
ui_msgbox(MBX_ERROR, szMessage);
|
||||
return;
|
||||
}
|
||||
|
||||
png_info_ptr = png_create_info_struct(png_ptr);
|
||||
if (png_info_ptr == NULL) {
|
||||
fclose(fp);
|
||||
pclog("[SavePNG] png_create_info_struct failed");
|
||||
_swprintf(szMessage, plat_get_string(IDS_2088), szFilename);
|
||||
ui_msgbox(MBX_ERROR, szMessage);
|
||||
return;
|
||||
}
|
||||
|
||||
png_init_io(png_ptr, fp);
|
||||
|
||||
hdc = GetDC(NULL);
|
||||
|
||||
ZeroMemory(&bmpInfo, sizeof(BITMAPINFO));
|
||||
bmpInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
|
||||
|
||||
GetDIBits(hdc, hBitmap, 0, 0, NULL, &bmpInfo, DIB_RGB_COLORS);
|
||||
if (bmpInfo.bmiHeader.biSizeImage <= 0)
|
||||
bmpInfo.bmiHeader.biSizeImage =
|
||||
bmpInfo.bmiHeader.biWidth*abs(bmpInfo.bmiHeader.biHeight)*(bmpInfo.bmiHeader.biBitCount+7)/8;
|
||||
|
||||
if ((pBuf = malloc(bmpInfo.bmiHeader.biSizeImage)) == NULL) {
|
||||
fclose(fp);
|
||||
pclog("[SavePNG] Unable to Allocate Bitmap Memory");
|
||||
_swprintf(szMessage, plat_get_string(IDS_2088), szFilename);
|
||||
ui_msgbox(MBX_ERROR, szMessage);
|
||||
return;
|
||||
}
|
||||
|
||||
if (ys2 <= 250) {
|
||||
bmpInfo.bmiHeader.biSizeImage <<= 1;
|
||||
|
||||
if ((pBuf2 = malloc(bmpInfo.bmiHeader.biSizeImage)) == NULL) {
|
||||
fclose(fp);
|
||||
free(pBuf);
|
||||
pclog("[SavePNG] Unable to Allocate Secondary Bitmap Memory");
|
||||
_swprintf(szMessage, plat_get_string(IDS_2088), szFilename);
|
||||
ui_msgbox(MBX_ERROR, szMessage);
|
||||
return;
|
||||
}
|
||||
|
||||
bmpInfo.bmiHeader.biHeight <<= 1;
|
||||
}
|
||||
|
||||
#if 0
|
||||
pclog("save png w=%i h=%i\n",
|
||||
bmpInfo.bmiHeader.biWidth, bmpInfo.bmiHeader.biHeight);
|
||||
#endif
|
||||
|
||||
bmpInfo.bmiHeader.biCompression = BI_RGB;
|
||||
|
||||
GetDIBits(hdc, hBitmap, 0,
|
||||
bmpInfo.bmiHeader.biHeight, pBuf, &bmpInfo, DIB_RGB_COLORS);
|
||||
|
||||
png_set_IHDR(png_ptr, png_info_ptr,
|
||||
bmpInfo.bmiHeader.biWidth, bmpInfo.bmiHeader.biHeight,
|
||||
8, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE,
|
||||
PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
|
||||
|
||||
b_rgb = (png_bytep *)malloc(sizeof(png_bytep)*bmpInfo.bmiHeader.biHeight));
|
||||
if (b_rgb == NULL) {
|
||||
fclose(fp);
|
||||
free(pBuf);
|
||||
free(pBuf2);
|
||||
pclog("[SavePNG] Unable to Allocate RGB Bitmap Memory");
|
||||
_swprintf(szMessage, plat_get_string(IDS_2088), szFilename);
|
||||
ui_msgbox(MBX_ERROR, szMessage);
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < bmpInfo.bmiHeader.biHeight; i++)
|
||||
b_rgb[i] = (png_byte *)malloc(png_get_rowbytes(png_ptr, info_ptr));
|
||||
|
||||
if (pBuf2) {
|
||||
DoubleLines((uint8_t *)pBuf2, (uint8_t *)pBuf);
|
||||
bgra_to_rgb(b_rgb, (uint8_t *)pBuf2,
|
||||
bmpInfo.bmiHeader.biWidth, bmpInfo.bmiHeader.biHeight);
|
||||
} else
|
||||
bgra_to_rgb(b_rgb, (uint8_t *)pBuf,
|
||||
bmpInfo.bmiHeader.biWidth, bmpInfo.bmiHeader.biHeight);
|
||||
|
||||
png_write_info(png_ptr, png_info_ptr);
|
||||
|
||||
png_write_image(png_ptr, b_rgb);
|
||||
|
||||
png_write_end(png_ptr, NULL);
|
||||
|
||||
/* Clean up. */
|
||||
if (hdc) ReleaseDC(NULL,hdc);
|
||||
|
||||
for (i = 0; i < bmpInfo.bmiHeader.biHeight; i++)
|
||||
if (b_rgb[i]) free(b_rgb[i]);
|
||||
|
||||
if (b_rgb) free(b_rgb);
|
||||
|
||||
if (pBuf) free(pBuf);
|
||||
if (pBuf2) free(pBuf2);
|
||||
|
||||
if (fp != NULL) fclose(fp);
|
||||
}
|
||||
#else
|
||||
static void
|
||||
DoubleLines(uint8_t *dst, uint8_t *src)
|
||||
{
|
||||
@@ -101,7 +261,7 @@ DoubleLines(uint8_t *dst, uint8_t *src)
|
||||
|
||||
|
||||
static void
|
||||
SaveBitmap(wchar_t *szFilename, HBITMAP hBitmap)
|
||||
SaveBMP(wchar_t *szFilename, HBITMAP hBitmap)
|
||||
{
|
||||
static WCHAR szMessage[512];
|
||||
BITMAPFILEHEADER bmpFileHeader;
|
||||
@@ -170,6 +330,7 @@ SaveBitmap(wchar_t *szFilename, HBITMAP hBitmap)
|
||||
|
||||
if (fp) fclose(fp);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
static void
|
||||
@@ -442,7 +603,11 @@ ddraw_take_screenshot(wchar_t *fn)
|
||||
|
||||
CopySurface(lpdds_back2);
|
||||
|
||||
SaveBitmap(fn, hbitmap);
|
||||
#ifdef USE_LIBPNG
|
||||
SavePNG(fn, hbitmap);
|
||||
#else
|
||||
SaveBMP(fn, hbitmap);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,538 +0,0 @@
|
||||
/*
|
||||
* VARCem Virtual ARchaeological Computer EMulator.
|
||||
* An emulator of (mostly) x86-based PC systems and devices,
|
||||
* using the ISA,EISA,VLB,MCA and PCI system buses, roughly
|
||||
* spanning the era between 1981 and 1995.
|
||||
*
|
||||
* This file is part of the VARCem Project.
|
||||
*
|
||||
* Simple PNG image file format handler.
|
||||
*
|
||||
* Adapted for use with VARCem. Writing of (very basic) PNG
|
||||
* image files, mostly intended to be used for creating
|
||||
* screenshots. We only support sRGB format (3-byte pixel
|
||||
* data) with a color depth of 8 bits per sample- so, 24bpp.
|
||||
*
|
||||
* NOTES: This is a stripped-down version of my full library for PNG
|
||||
* image file format support. All the 'reading' code has been
|
||||
* removed, and some other stuff we don't need here.
|
||||
*
|
||||
* TODO: Compression is currently not supported, until I figure out
|
||||
* how ZLIB works so I can interface with it here.
|
||||
*
|
||||
* Version: @(#)win_png.c 1.0.2 2018/03/08
|
||||
*
|
||||
* Author: Fred N. van Kempen, <decwiz@yahoo.com>
|
||||
*
|
||||
* Copyright 2017,2018 Fred N. van Kempen.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with
|
||||
* or without modification, are permitted provided that the
|
||||
* following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the entire
|
||||
* above notice, this list of conditions and the following
|
||||
* disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the
|
||||
* following disclaimer in the documentation and/or other
|
||||
* materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names
|
||||
* of its contributors may be used to endorse or promote
|
||||
* products derived from this software without specific
|
||||
* prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "../emu.h"
|
||||
#include "../plat.h"
|
||||
#include "win_png.h"
|
||||
|
||||
|
||||
#ifdef CRC_DYNAMIC
|
||||
static uint32_t crc_table[256];
|
||||
static int crc_tblok = 0;
|
||||
|
||||
|
||||
/* Pre-calculate the CRC table. */
|
||||
static void
|
||||
crc_create(void)
|
||||
{
|
||||
uint32_t crc;
|
||||
int i, k;
|
||||
|
||||
for (i=0; i<256; i++) {
|
||||
crc = (uint32_t)i;
|
||||
for (k=0; k<8; k++) {
|
||||
if (crc & 1)
|
||||
crc = 0xedb88320UL ^ (crc >> 1);
|
||||
else
|
||||
crc >>= 1;
|
||||
}
|
||||
crc_table[i] = crc;
|
||||
}
|
||||
|
||||
crc_tblok = 1;
|
||||
}
|
||||
|
||||
|
||||
#else
|
||||
static uint32_t crc_table[256] = {
|
||||
0x00000000, 0x77073096, 0xee0e612c, 0x990951ba,
|
||||
0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,
|
||||
0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
|
||||
0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,
|
||||
0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
|
||||
0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
|
||||
0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec,
|
||||
0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,
|
||||
0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
|
||||
0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
|
||||
0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940,
|
||||
0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
|
||||
0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116,
|
||||
0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,
|
||||
0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
|
||||
0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,
|
||||
0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a,
|
||||
0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
|
||||
0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818,
|
||||
0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
|
||||
0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
|
||||
0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,
|
||||
0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c,
|
||||
0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
|
||||
0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
|
||||
0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb,
|
||||
0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
|
||||
0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,
|
||||
0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086,
|
||||
0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
|
||||
0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4,
|
||||
0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,
|
||||
0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
|
||||
0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683,
|
||||
0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
|
||||
0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
|
||||
0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe,
|
||||
0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7,
|
||||
0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
|
||||
0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
|
||||
0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252,
|
||||
0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
|
||||
0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60,
|
||||
0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,
|
||||
0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
|
||||
0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,
|
||||
0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04,
|
||||
0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
|
||||
0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a,
|
||||
0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
|
||||
0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
|
||||
0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21,
|
||||
0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e,
|
||||
0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
|
||||
0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
|
||||
0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,
|
||||
0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
|
||||
0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db,
|
||||
0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0,
|
||||
0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
|
||||
0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6,
|
||||
0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf,
|
||||
0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
|
||||
0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
/* Standard Network CRC32. */
|
||||
static uint32_t
|
||||
crc_upd(uint32_t crc, uint8_t *bufp, int buflen)
|
||||
{
|
||||
int i;
|
||||
|
||||
#ifdef CRC_DYNAMIC
|
||||
if (! crc_tblok)
|
||||
crc_create();
|
||||
#endif
|
||||
|
||||
for (i=0; i<buflen; i++)
|
||||
crc = crc_table[(crc ^ *bufp++) & 0xff] ^ (crc >> 8);
|
||||
|
||||
return(crc);
|
||||
}
|
||||
|
||||
|
||||
static uint32_t
|
||||
crc_init(void)
|
||||
{
|
||||
return(0xffffffffUL);
|
||||
}
|
||||
|
||||
|
||||
static uint32_t
|
||||
crc_finish(uint32_t crc)
|
||||
{
|
||||
return(crc ^ 0xffffffffUL);
|
||||
}
|
||||
|
||||
|
||||
/* Perform CRC over the compressed data. */
|
||||
static uint32_t
|
||||
png_dcrc(uint32_t state, const uint8_t *bufp, uint32_t buflen)
|
||||
{
|
||||
uint16_t s1, s2;
|
||||
uint32_t i;
|
||||
|
||||
s1 = (uint16_t)(state & 0xffff);
|
||||
s2 = (uint16_t)(state >> 16);
|
||||
|
||||
for (i=0; i<buflen; i++) {
|
||||
s1 = ((uint32_t)s1 + bufp[i]) % 65521;
|
||||
s2 = ((uint32_t)s2 + s1) % 65521;
|
||||
}
|
||||
|
||||
return((uint32_t)s2 << 16 | s1);
|
||||
}
|
||||
|
||||
|
||||
/* Finish the PNG file by writing the IEND record. */
|
||||
static int
|
||||
png_wriend(png_t *png)
|
||||
{
|
||||
uint8_t buff[12];
|
||||
int i = 0;
|
||||
|
||||
/* Create the IEND chunk. */
|
||||
png_putlong(&buff[i], 0, &i);
|
||||
memcpy(&buff[i], "IEND", 4); i += 4;
|
||||
png_putlong(&buff[i], 0xae426082, &i);
|
||||
if (fwrite(buff, 1, sizeof(buff), png->fp) != sizeof(buff)) {
|
||||
pclog("PNG(%ls): could not write trailer chunk!\n", png->name);
|
||||
return(-1);
|
||||
}
|
||||
|
||||
/* All is good! */
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
/* Write an IDAT chunk header to the file. */
|
||||
static uint32_t
|
||||
png_wridat(png_t *png, uint32_t pixels)
|
||||
{
|
||||
uint8_t buff[10];
|
||||
uint32_t cnt;
|
||||
int i, fluff;
|
||||
|
||||
/*
|
||||
* We must know the size of the chunk we are about to write,
|
||||
* and that is not straightforward. If compression is enabled,
|
||||
* we won't know until we're done with the chunk, so we would
|
||||
* have to just write a dummy, and then go back afterwards and
|
||||
* fix up the chunk size.
|
||||
*
|
||||
* Without compression, we could do the same, or we can do some
|
||||
* calculations on how much data we expect to generate, and use
|
||||
* that. For now, we'll go with the latter option.
|
||||
*/
|
||||
cnt = png->lwidth; /* bytes per scanline */
|
||||
cnt += 1; /* filter type per line */
|
||||
cnt *= (pixels/png->width); /* number of full lines */
|
||||
cnt += (pixels%png->width); /* number of pixels */
|
||||
|
||||
/*
|
||||
* We now have the total number of pixel bytes to write.
|
||||
*
|
||||
* All that is left is adding the expected overhead (since we
|
||||
* are dealing with fixed-size blocks and their headers) and
|
||||
* that should give us the grand total..
|
||||
*/
|
||||
i = (cnt / DEFL_MAX_BLKSZ); /* number of full blocks */
|
||||
if ((cnt % DEFL_MAX_BLKSZ) != 0) i++; /* incomplete block */
|
||||
cnt += (i * 5); /* block header is 5 bytes */
|
||||
|
||||
/*
|
||||
* We are not using compression, so we must account for
|
||||
* the extra data we insert to fake that. Below you will
|
||||
* see the two DEFLATE bytes (this makes it look like a
|
||||
* real deflate stream.) Upon closing, we also add the
|
||||
* four compressed-data CRC bytes, so, a total of 6.
|
||||
*/
|
||||
fluff = 6;
|
||||
|
||||
i = 0;
|
||||
png_putlong(&buff[i], cnt+fluff, &i); /* IDAT chunk */
|
||||
memcpy(&buff[i], "IDAT", 4); i += 4;
|
||||
buff[i++] = 0x08; /* deflate data: zlib */
|
||||
buff[i++] = 0x1d; /* zlib method number */
|
||||
if (fwrite(buff, 1, i, png->fp) != i) {
|
||||
pclog("PNG(%ls): unable to write IDAT header!\n", png->name);
|
||||
png_close(png);
|
||||
return(-1);
|
||||
}
|
||||
|
||||
/* Initialize IDAT CRC. */
|
||||
png->crc = crc_upd(png->crc, &buff[4], i-4);
|
||||
|
||||
/* Initialize for writing data. */
|
||||
png->bufcnt = 0; /* no data in buffer */
|
||||
|
||||
return(cnt);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* API: Write (more) data to the PNG file.
|
||||
*
|
||||
* To keep things semi-simple, we generate a single IDAT
|
||||
* chunk for each write. So, if the application calls us
|
||||
* with the entire image, we have one IDAT. If it calls
|
||||
* us multiple times (for example, once per scanline), we
|
||||
* get one IDAT per scanline.
|
||||
*/
|
||||
int
|
||||
png_write(png_t *png, uint8_t *bitmap, uint32_t pixels)
|
||||
{
|
||||
uint8_t buff[10];
|
||||
uint32_t cnt, n;
|
||||
uint16_t s;
|
||||
int i;
|
||||
|
||||
/* Do they want to close up? */
|
||||
if (bitmap == NULL && pixels == 0) {
|
||||
i = png_wriend(png);
|
||||
return(i);
|
||||
}
|
||||
|
||||
if (png->line >= png->height) {
|
||||
pclog("PNG(%ls): cannot write %u pixels!\n", png->name, pixels);
|
||||
png_close(png);
|
||||
return(-1);
|
||||
}
|
||||
|
||||
/* Start a new IDAT chunk. */
|
||||
cnt = png_wridat(png, pixels);
|
||||
|
||||
/* Loop, writing all pixels to the file. */
|
||||
while (cnt > 0) {
|
||||
if (png->bufcnt == 0) {
|
||||
/*
|
||||
* Initialize a new block header.
|
||||
*
|
||||
* Bit0: LastBlock
|
||||
* Bits[2:1]: compression type (00=stored)
|
||||
* Len: block size (MSB)
|
||||
* Nlen: block size, negated (MSB)
|
||||
*/
|
||||
s = (cnt < DEFL_MAX_BLKSZ) ? cnt : DEFL_MAX_BLKSZ;
|
||||
i = 0;
|
||||
buff[i++] = (cnt <= DEFL_MAX_BLKSZ) ? 1:0;
|
||||
buff[i++] = ((s >> 8) & 0xff);
|
||||
buff[i++] = (s & 0xff);
|
||||
buff[i++] = ((s >> 8) ^ 0xff);
|
||||
buff[i++] = (s ^ 0xff);
|
||||
if (fwrite(buff, 1, i, png->fp) != i) {
|
||||
pclog("PNG(%ls): block header write failed!\n",
|
||||
png->name);
|
||||
png_close(png);
|
||||
return(-1);
|
||||
}
|
||||
png->crc = crc_upd(png->crc, buff, i);
|
||||
cnt -= i;
|
||||
}
|
||||
|
||||
if (png->col == 0) {
|
||||
/* Beginning of line, write filter method. */
|
||||
buff[0] = 0x00;
|
||||
if (fwrite(buff, 1, 1, png->fp) != 1) {
|
||||
pclog("PNG(%ls): cannot write filter?!\n", png->name);
|
||||
png_close(png);
|
||||
return(-1);
|
||||
}
|
||||
png->crc = crc_upd(png->crc, buff, 1);
|
||||
png->dcrc = png_dcrc(png->dcrc, buff, 1);
|
||||
png->bufcnt++;
|
||||
cnt--;
|
||||
}
|
||||
|
||||
/* See how many pixels we can write for this scanline. */
|
||||
n = cnt;
|
||||
if ((uint32_t)(png->lwidth - png->col) < n)
|
||||
n = (png->lwidth - png->col);
|
||||
if ((DEFL_MAX_BLKSZ - png->bufcnt) < n)
|
||||
n = (DEFL_MAX_BLKSZ - png->bufcnt);
|
||||
|
||||
/* Write the pixel data for this block. */
|
||||
if (fwrite(bitmap, 1, n, png->fp) != n) {
|
||||
pclog("PNG(%ls): cannot write pixeldata?!\n", png->name);
|
||||
png_close(png);
|
||||
return(-1);
|
||||
}
|
||||
|
||||
/* Update the CRCs for these pixels. */
|
||||
png->crc = crc_upd(png->crc, bitmap, n);
|
||||
png->dcrc = png_dcrc(png->dcrc, bitmap, n);
|
||||
|
||||
/* Update stats. */
|
||||
bitmap += n;
|
||||
png->bufcnt += n;
|
||||
if (png->bufcnt == DEFL_MAX_BLKSZ)
|
||||
png->bufcnt = 0;
|
||||
cnt -= n;
|
||||
|
||||
png->col += n;
|
||||
if (png->col == png->lwidth) {
|
||||
png->col = 0;
|
||||
if (++png->line == png->height) {
|
||||
if (cnt > 0) {
|
||||
pclog("PNG(%ls): done, more data?!\n",
|
||||
png->name);
|
||||
png_close(png);
|
||||
return(-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Write the CRCs. */
|
||||
i = 0;
|
||||
png_putlong(buff, png->dcrc, &i);
|
||||
png->crc = crc_finish(crc_upd(png->crc, buff, i));
|
||||
png_putlong(&buff[i], png->crc, &i);
|
||||
if (fwrite(buff, 1, i, png->fp) != i) {
|
||||
pclog("PNG(%ls): cannot write IDAT trailer?!\n", png->name);
|
||||
png_close(png);
|
||||
return(-1);
|
||||
}
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
/* Write an unsigned long 32bit value in MSB. */
|
||||
void
|
||||
png_putlong(uint8_t *ptr, uint32_t val, int *off)
|
||||
{
|
||||
*ptr++ = (val >> 24) & 0xff;
|
||||
*ptr++ = (val >> 16) & 0xff;
|
||||
*ptr++ = (val >> 8) & 0xff;
|
||||
*ptr = val & 0xff;
|
||||
|
||||
if (off != NULL)
|
||||
*off += sizeof(uint32_t);
|
||||
}
|
||||
|
||||
|
||||
/* API: Close the current PNG file. */
|
||||
void
|
||||
png_close(png_t *png)
|
||||
{
|
||||
if (png->fp != NULL) {
|
||||
fflush(png->fp);
|
||||
(void)fclose(png->fp);
|
||||
|
||||
free(png);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* API: Create a new PNG file. */
|
||||
png_t *
|
||||
png_create(wchar_t *fn, int width, int height, int bpp)
|
||||
{
|
||||
uint8_t buff[33];
|
||||
uint32_t crc;
|
||||
png_t *png;
|
||||
int i;
|
||||
|
||||
/* Make sure we can do this. */
|
||||
if ((bpp != 24) ||
|
||||
(width<=0 || width >= 65536) ||
|
||||
(height<=0 || height >= 65536)) {
|
||||
pclog("PNG(%ls): invalid image parameters!\n", fn);
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
/* Allocate the control block. */
|
||||
png = (png_t *)malloc(sizeof(png_t));
|
||||
if (png == NULL) {
|
||||
pclog("PNG(%ls): out of memory!\n", fn);
|
||||
return(NULL);
|
||||
}
|
||||
memset(png, 0x00, sizeof(png_t));
|
||||
png->name = fn;
|
||||
png->width = width; /* width, in pixels */
|
||||
png->height = height; /* height, in pixels */
|
||||
png->bpp = bpp; /* total bits per pixel */
|
||||
png->ctype = PNG_COLOR_TYPE; /* 02 - sRBG */
|
||||
png->cdepth = (bpp/3); /* bits per color sample */
|
||||
png->pwidth = (bpp/8); /* bytes per pixel */
|
||||
png->lwidth = (png->pwidth*width); /* line width in bytes */
|
||||
png->crc = crc_init(); /* initialize data CRC */
|
||||
png->dcrc = 1; /* compressed-data CRC */
|
||||
|
||||
/* Create the data file. */
|
||||
if ((png->fp = plat_fopen(fn, L"wb")) == NULL) {
|
||||
pclog("PNG(%ls): unable to create file!\n", fn);
|
||||
png_close(png);
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
/* Write out the basic header chunks. */
|
||||
i = 0;
|
||||
buff[i++] = 0x89; /* standard PNG header */
|
||||
memcpy(&buff[i], "PNG", 3); i += 3;
|
||||
buff[i++] = 0x0d; buff[i++] = 0x0a;
|
||||
buff[i++] = 0x1a; buff[i++] = 0x0a;
|
||||
|
||||
png_putlong(&buff[i], 13, &i); /* IHDR chunk */
|
||||
memcpy(&buff[i], "IHDR", 4); i += 4;
|
||||
png_putlong(&buff[i], png->width, &i); /* width */
|
||||
png_putlong(&buff[i], png->height, &i); /* height */
|
||||
buff[i++] = png->cdepth; /* color depth (per color) */
|
||||
buff[i++] = png->ctype; /* color type (2=RGB) */
|
||||
buff[i++] = PNG_COMPRESSION_TYPE; /* compression (0=deflate) */
|
||||
buff[i++] = PNG_FILTER_TYPE; /* filter (0=adaptive) */
|
||||
buff[i++] = PNG_INTERLACE_MODE; /* interlace (0=none) */
|
||||
crc = crc_finish(crc_upd(crc_init(), &buff[12], 17));
|
||||
png_putlong(&buff[i], crc, &i);
|
||||
if (fwrite(buff, 1, i, png->fp) != i) {
|
||||
pclog("PNG(%ls): unable to write PNG header!\n", fn);
|
||||
png_close(png);
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
i = 4;
|
||||
memcpy(&buff[i], "tEXt", 4); i += 4;
|
||||
memcpy(&buff[i], "Software", 8); i+= 8;
|
||||
buff[i++] = 0x00;
|
||||
memcpy(&buff[i], "VARCem PNGlib", 12); i+= 12;
|
||||
png_putlong(buff, i-8, NULL);
|
||||
crc = crc_finish(crc_upd(crc_init(), &buff[4], i-4));
|
||||
png_putlong(&buff[i], crc, &i);
|
||||
if (fwrite(buff, 1, i, png->fp) != i) {
|
||||
pclog("PNG(%ls): unable to write chunk header!\n", fn);
|
||||
png_close(png);
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
return(png);
|
||||
}
|
||||
@@ -1,96 +0,0 @@
|
||||
/*
|
||||
* VARCem Virtual ARchaeological Computer EMulator.
|
||||
* An emulator of (mostly) x86-based PC systems and devices,
|
||||
* using the ISA,EISA,VLB,MCA and PCI system buses, roughly
|
||||
* spanning the era between 1981 and 1995.
|
||||
*
|
||||
* This file is part of the VARCem Project.
|
||||
*
|
||||
* Definitions for the Simple PNG image file format handler.
|
||||
*
|
||||
* Version: @(#)win_png.h 1.0.1 2018/02/14
|
||||
*
|
||||
* Author: Fred N. van Kempen, <decwiz@yahoo.com>
|
||||
*
|
||||
* Copyright 2017,2018 Fred N. van Kempen.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with
|
||||
* or without modification, are permitted provided that the
|
||||
* following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the entire
|
||||
* above notice, this list of conditions and the following
|
||||
* disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the
|
||||
* following disclaimer in the documentation and/or other
|
||||
* materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names
|
||||
* of its contributors may be used to endorse or promote
|
||||
* products derived from this software without specific
|
||||
* prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#ifndef WIN_PNG_H
|
||||
# define WIN_PNG_H
|
||||
|
||||
|
||||
/* PNG defintions, as per the specification. */
|
||||
#define PNG_COLOR_TYPE 0x02 /* 3-sample sRGB */
|
||||
#define PNG_COMPRESSION_TYPE 0x00 /* deflate compression */
|
||||
#define PNG_FILTER_TYPE 0x00 /* no filtering */
|
||||
#define PNG_INTERLACE_MODE 0x00 /* no interlacing */
|
||||
|
||||
/* DEFLATE definition, as per RFC1950/1 specification. */
|
||||
#define DEFL_MAX_BLKSZ 65535 /* DEFLATE max block size */
|
||||
|
||||
|
||||
typedef struct {
|
||||
wchar_t *name; /* name of datafile */
|
||||
FILE *fp;
|
||||
|
||||
uint16_t width, /* configured with in pixels */
|
||||
height; /* configured with in pixels */
|
||||
uint8_t bpp, /* configured bits per pixel */
|
||||
ctype; /* configured color type */
|
||||
|
||||
uint16_t col, /* current column */
|
||||
line, /* current scanline */
|
||||
lwidth; /* line width in bytes */
|
||||
uint8_t cdepth, /* color depth in bits */
|
||||
pwidth; /* bytes per pixel */
|
||||
uint32_t crc; /* idat chunk crc */
|
||||
uint32_t dcrc; /* deflate data crc */
|
||||
|
||||
uint32_t bufcnt; /* #bytes in block */
|
||||
} png_t;
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
extern void png_putlong(uint8_t *ptr, uint32_t val, int *off);
|
||||
extern void png_close(png_t *png);
|
||||
extern png_t *png_create(wchar_t *fn, int width, int height, int bpp);
|
||||
extern int png_write(png_t *png, uint8_t *bitmap, uint32_t pixels);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#endif /*WIN_PNG_H*/
|
||||
Reference in New Issue
Block a user