Applied relevant upstream patches, including one that fixes the CL-GD.

Several small fixes here and there.
This commit is contained in:
waltje
2018-10-21 17:55:29 -04:00
parent 18917db2a7
commit b7a877bacc
11 changed files with 414 additions and 276 deletions

View File

@@ -135,6 +135,7 @@ device_add(const device_t *d)
{ {
wchar_t temp[1024]; wchar_t temp[1024];
void *priv = NULL; void *priv = NULL;
device_t *old;
int c; int c;
for (c = 0; c < DEVICE_MAX; c++) { for (c = 0; c < DEVICE_MAX; c++) {
@@ -164,6 +165,7 @@ device_add(const device_t *d)
INFO("DEVICE: device '%s' is unstable, user agreed!\n", d->name); INFO("DEVICE: device '%s' is unstable, user agreed!\n", d->name);
} }
old = device_current;
device_current = (device_t *)d; device_current = (device_t *)d;
devices[c] = (device_t *)d; devices[c] = (device_t *)d;
@@ -183,6 +185,7 @@ device_add(const device_t *d)
} }
device_priv[c] = priv; device_priv[c] = priv;
device_current = old;
return(priv); return(priv);
} }
@@ -204,8 +207,6 @@ device_add_ex(const device_t *d, void *priv)
if (c >= DEVICE_MAX) if (c >= DEVICE_MAX)
fatal("DEVICE: too many devices\n"); fatal("DEVICE: too many devices\n");
device_current = (device_t *)d;
devices[c] = (device_t *)d; devices[c] = (device_t *)d;
device_priv[c] = priv; device_priv[c] = priv;
} }

View File

@@ -8,7 +8,7 @@
* *
* Generic interface for CD-ROM/DVD/BD implementations. * Generic interface for CD-ROM/DVD/BD implementations.
* *
* Version: @(#)cdrom.c 1.0.24 2018/10/20 * Version: @(#)cdrom.c 1.0.25 2018/10/21
* *
* Authors: Fred N. van Kempen, <decwiz@yahoo.com> * Authors: Fred N. van Kempen, <decwiz@yahoo.com>
* Miran Grca, <mgrca8@gmail.com> * Miran Grca, <mgrca8@gmail.com>
@@ -271,7 +271,7 @@ cdrom_eject(uint8_t id)
} }
if (dev->host_drive == 200) { if (dev->host_drive == 200) {
dev->prev_image_path = (wchar_t *)mem_alloc(1024); dev->prev_image_path = (wchar_t *)mem_alloc(1024 * sizeof(wchar_t));
wcscpy(dev->prev_image_path, dev->image_path); wcscpy(dev->prev_image_path, dev->image_path);
} }

View File

@@ -8,7 +8,7 @@
* *
* CD-ROM image support. * CD-ROM image support.
* *
* Version: @(#)cdrom_image.cpp 1.0.17 2018/10/20 * Version: @(#)cdrom_image.cpp 1.0.19 2018/10/21
* *
* Authors: Fred N. van Kempen, <decwiz@yahoo.com> * Authors: Fred N. van Kempen, <decwiz@yahoo.com>
* Miran Grca, <mgrca8@gmail.com> * Miran Grca, <mgrca8@gmail.com>
@@ -133,7 +133,7 @@ enum {
static int cdrom_sector_size; static int cdrom_sector_size;
static uint8_t raw_buffer[2448]; static uint8_t raw_buffer[2856]; /* same size as sector_buffer_t */
static uint8_t extra_buffer[296]; static uint8_t extra_buffer[296];
@@ -467,9 +467,9 @@ read_sector_to_buffer(cdrom_t *dev, uint8_t *rbuf, uint32_t msf, uint32_t lba, i
bb += mode2 ? 12 : 4; bb += mode2 ? 12 : 4;
bb += len; bb += len;
if (mode2 && ((mode2 & 0x03) == 1)) if (mode2 && ((mode2 & 0x03) == 1))
memset(bb, 0, 280); memset(bb, 0, 88); /* 280 */
else if (!mode2) else if (!mode2)
memset(bb, 0, 288); memset(bb, 0, 96); /* 288 */
} }
@@ -730,13 +730,8 @@ image_readsector_raw(cdrom_t *dev, uint8_t *buffer, int sector, int is_msf,
if (!is_legal(dev->id, type, flags, audio, mode2)) if (!is_legal(dev->id, type, flags, audio, mode2))
return 0; return 0;
if ((type == 3) || ((type > 4) && (type != 8))) { if ((type > 5) && (type != 8)) {
if (type == 3) { DEBUG("CD-ROM %i: Attempting to read an unrecognized sector type from an image\n", dev->id);
DEBUG("CD-ROM %i: Attempting to read a Yellowbook Mode 2 data sector from an image\n", dev->id);
}
if (type > 4) {
DEBUG("CD-ROM %i: Attempting to read a XA Mode 2 Form 2 data sector from an image\n", dev->id);
}
return 0; return 0;
} else if (type == 1) { } else if (type == 1) {
if (!audio || dev->img_is_iso) { if (!audio || dev->img_is_iso) {
@@ -1107,6 +1102,7 @@ cdrom_image_open(cdrom_t *dev, const wchar_t *fn)
if (! img->SetDevice(temp, false)) { if (! img->SetDevice(temp, false)) {
image_close(dev); image_close(dev);
dev->ops = NULL; dev->ops = NULL;
dev->host_drive = 0;
return 1; return 1;
} }

View File

@@ -9,7 +9,7 @@
* Implementation of the Iomega ZIP drive with SCSI(-like) * Implementation of the Iomega ZIP drive with SCSI(-like)
* commands, for both ATAPI and SCSI usage. * commands, for both ATAPI and SCSI usage.
* *
* Version: @(#)zip.c 1.0.20 2018/10/20 * Version: @(#)zip.c 1.0.21 2018/10/21
* *
* Authors: Fred N. van Kempen, <decwiz@yahoo.com> * Authors: Fred N. van Kempen, <decwiz@yahoo.com>
* Miran Grca, <mgrca8@gmail.com> * Miran Grca, <mgrca8@gmail.com>
@@ -2760,15 +2760,15 @@ zip_identify(void *p, int ide_has_dma)
} }
static zip_t * static void
zip_drive_reset(int c) zip_drive_reset(int c)
{ {
scsi_device_t *sd; scsi_device_t *sd;
ide_t *id; ide_t *id;
if (!zip[c]) { if (!zip[c]) {
zip[c] = (zip_t *) malloc(sizeof(zip_t)); zip[c] = (zip_t *)mem_alloc(sizeof(zip_t));
memset(zip[c], 0, sizeof(zip_t)); memset(zip[c], 0x00, sizeof(zip_t));
} }
zip[c]->id = c; zip[c]->id = c;
@@ -2807,8 +2807,6 @@ zip_drive_reset(int c)
ide_atapi_attach(id); ide_atapi_attach(id);
} }
} }
return zip[c];
} }
@@ -2829,7 +2827,7 @@ zip_hard_reset(void)
if ((zip_drives[c].bus_type == ZIP_BUS_ATAPI) && (zip_drives[c].bus_id.ide_channel > 7)) if ((zip_drives[c].bus_type == ZIP_BUS_ATAPI) && (zip_drives[c].bus_id.ide_channel > 7))
continue; continue;
zip[c] = zip_drive_reset(c); zip_drive_reset(c);
zip[c]->id = c; zip[c]->id = c;
zip[c]->drv = &zip_drives[c]; zip[c]->drv = &zip_drives[c];

View File

@@ -40,6 +40,8 @@
* Logitech Mouse.exe 6.50 * Logitech Mouse.exe 6.50
* Microsoft Mouse.com 2.00 * Microsoft Mouse.com 2.00
* Microsoft Mouse.sys 3.00 * Microsoft Mouse.sys 3.00
* Microsoft Mouse.com 7.04
* Microsoft Mouse.com 8.21J
* Microsoft Windows 1.00 DR5 * Microsoft Windows 1.00 DR5
* Microsoft Windows 3.10.026 * Microsoft Windows 3.10.026
* Microsoft Windows NT 3.1 * Microsoft Windows NT 3.1
@@ -51,7 +53,7 @@
* Microsoft Windows NT 3.1 * Microsoft Windows NT 3.1
* Microsoft Windows 98 SE * Microsoft Windows 98 SE
* *
* Version: @(#)mouse_bus.c 1.1.1 2018/10/11 * Version: @(#)mouse_bus.c 1.1.2 2018/10/21
* *
* Authors: Fred N. van Kempen, <decwiz@yahoo.com> * Authors: Fred N. van Kempen, <decwiz@yahoo.com>
* Miran Grca, <mgrca8@gmail.com> * Miran Grca, <mgrca8@gmail.com>

View File

@@ -8,7 +8,7 @@
* *
* Definitions for the common AHA/BL code. * Definitions for the common AHA/BL code.
* *
* Version: @(#)scsi_x54x.h 1.0.5 2018/10/14 * Version: @(#)scsi_x54x.h 1.0.6 2018/10/21
* *
* Authors: Fred N. van Kempen, <decwiz@yahoo.com> * Authors: Fred N. van Kempen, <decwiz@yahoo.com>
* Miran Grca, <mgrca8@gmail.com> * Miran Grca, <mgrca8@gmail.com>
@@ -133,50 +133,10 @@
#define INTR_MBIF 0x01 /* MBI full */ #define INTR_MBIF 0x01 /* MBI full */
#pragma pack(push,1)
typedef struct {
uint8_t hi;
uint8_t mid;
uint8_t lo;
} addr24;
#pragma pack(pop)
#define ADDR_TO_U32(x) (((x).hi<<16)|((x).mid<<8)|((x).lo&0xFF)) #define ADDR_TO_U32(x) (((x).hi<<16)|((x).mid<<8)|((x).lo&0xFF))
#define U32_TO_ADDR(a,x) do {(a).hi=(x)>>16;(a).mid=(x)>>8;(a).lo=(x)&0xFF;}while(0) #define U32_TO_ADDR(a,x) do {(a).hi=(x)>>16;(a).mid=(x)>>8;(a).lo=(x)&0xFF;}while(0)
/* Structure for the INQUIRE_SETUP_INFORMATION reply. */
#pragma pack(push,1)
typedef struct {
uint8_t uOffset :4,
uTransferPeriod :3,
fSynchronous :1;
} ReplyInquireSetupInformationSynchronousValue;
#pragma pack(pop)
#pragma pack(push,1)
typedef struct {
uint8_t fSynchronousInitiationEnabled :1,
fParityCheckingEnabled :1,
uReserved1 :6;
uint8_t uBusTransferRate;
uint8_t uPreemptTimeOnBus;
uint8_t uTimeOffBus;
uint8_t cMailbox;
addr24 MailboxAddress;
ReplyInquireSetupInformationSynchronousValue SynchronousValuesId0To7[8];
uint8_t uDisconnectPermittedId0To7;
uint8_t VendorSpecificData[28];
} ReplyInquireSetupInformation;
#pragma pack(pop)
#pragma pack(push,1)
typedef struct {
uint8_t Count;
addr24 Address;
} MailboxInit_t;
#pragma pack(pop)
/* /*
* Mailbox Definitions. * Mailbox Definitions.
* *
@@ -193,31 +153,6 @@ typedef struct {
#define MBI_NOT_FOUND 0x03 #define MBI_NOT_FOUND 0x03
#define MBI_ERROR 0x04 #define MBI_ERROR 0x04
#pragma pack(push,1)
typedef struct {
uint8_t CmdStatus;
addr24 CCBPointer;
} Mailbox_t;
#pragma pack(pop)
#pragma pack(push,1)
typedef struct {
uint32_t CCBPointer;
union {
struct {
uint8_t Reserved[3];
uint8_t ActionCode;
} out;
struct {
uint8_t HostStatus;
uint8_t TargetStatus;
uint8_t Reserved;
uint8_t CompletionCode;
} in;
} u;
} Mailbox32_t;
#pragma pack(pop)
/* /*
* *
* CCB - SCSI Command Control Block * CCB - SCSI Command Control Block
@@ -265,13 +200,77 @@ typedef struct {
#define CCB_DUPLICATE_CCB 0x19 /* Duplicate CCB */ #define CCB_DUPLICATE_CCB 0x19 /* Duplicate CCB */
#define CCB_INVALID_CCB 0x1A /* Invalid CCB - bad parameter */ #define CCB_INVALID_CCB 0x1A /* Invalid CCB - bad parameter */
#define lba32_blk(p) ((uint32_t)(p->u.lba.lba0<<24) | (p->u.lba.lba1<<16) | \
(p->u.lba.lba2<<8) | p->u.lba.lba3)
/*
*
* Scatter/Gather Segment List Definitions
*
* Adapter limits
*/
#define MAX_SG_DESCRIPTORS 32 /* Always make the array 32 elements long, if less are used, that's not an issue. */
#pragma pack(push,1)
typedef struct {
uint8_t hi;
uint8_t mid;
uint8_t lo;
} addr24;
/* Structure for the INQUIRE_SETUP_INFORMATION reply. */
typedef struct {
uint8_t uOffset :4,
uTransferPeriod :3,
fSynchronous :1;
} ReplyInquireSetupInformationSynchronousValue;
typedef struct {
uint8_t fSynchronousInitiationEnabled :1,
fParityCheckingEnabled :1,
uReserved1 :6;
uint8_t uBusTransferRate;
uint8_t uPreemptTimeOnBus;
uint8_t uTimeOffBus;
uint8_t cMailbox;
addr24 MailboxAddress;
ReplyInquireSetupInformationSynchronousValue SynchronousValuesId0To7[8];
uint8_t uDisconnectPermittedId0To7;
uint8_t VendorSpecificData[28];
} ReplyInquireSetupInformation;
typedef struct {
uint8_t Count;
addr24 Address;
} MailboxInit_t;
typedef struct {
uint8_t CmdStatus;
addr24 CCBPointer;
} Mailbox_t;
typedef struct {
uint32_t CCBPointer;
union {
struct {
uint8_t Reserved[3];
uint8_t ActionCode;
} out;
struct {
uint8_t HostStatus;
uint8_t TargetStatus;
uint8_t Reserved;
uint8_t CompletionCode;
} in;
} u;
} Mailbox32_t;
/* Byte 15 Target Status /* Byte 15 Target Status
See scsi.h files for these statuses. See scsi.h files for these statuses.
Bytes 16 and 17 Reserved (must be 0) Bytes 16 and 17 Reserved (must be 0)
Bytes 18 through 18+n-1, where n=size of CDB Command Descriptor Block */ Bytes 18 through 18+n-1, where n=size of CDB Command Descriptor Block */
#pragma pack(push,1)
typedef struct { typedef struct {
uint8_t Opcode; uint8_t Opcode;
uint8_t Reserved1 :3, uint8_t Reserved1 :3,
@@ -293,9 +292,7 @@ typedef struct {
uint8_t Reserved3[6]; uint8_t Reserved3[6];
uint32_t SensePointer; uint32_t SensePointer;
} CCB32; } CCB32;
#pragma pack(pop)
#pragma pack(push,1)
typedef struct { typedef struct {
uint8_t Opcode; uint8_t Opcode;
uint8_t Lun :3, uint8_t Lun :3,
@@ -312,9 +309,7 @@ typedef struct {
uint8_t Reserved[2]; uint8_t Reserved[2];
uint8_t Cdb[12]; uint8_t Cdb[12];
} CCB; } CCB;
#pragma pack(pop)
#pragma pack(push,1)
typedef struct { typedef struct {
uint8_t Opcode; uint8_t Opcode;
uint8_t Pad1 :3, uint8_t Pad1 :3,
@@ -329,17 +324,13 @@ typedef struct {
uint8_t Pad4[2]; uint8_t Pad4[2];
uint8_t Cdb[12]; uint8_t Cdb[12];
} CCBC; } CCBC;
#pragma pack(pop)
#pragma pack(push,1)
typedef union { typedef union {
CCB32 new_fmt; CCB32 new_fmt;
CCB old_fmt; CCB old_fmt;
CCBC common; CCBC common;
} CCBU; } CCBU;
#pragma pack(pop)
#pragma pack(push,1)
typedef struct { typedef struct {
CCBU CmdBlock; CCBU CmdBlock;
uint8_t *RequestSenseBuffer; uint8_t *RequestSenseBuffer;
@@ -351,6 +342,38 @@ typedef struct {
TargetStatus, TargetStatus,
MailboxCompletionCode; MailboxCompletionCode;
} Req_t; } Req_t;
typedef struct {
uint8_t command;
uint8_t lun:3,
reserved:2,
id:3;
union {
struct {
uint16_t cyl;
uint8_t head;
uint8_t sec;
} chs;
struct {
uint8_t lba0; /* MSB */
uint8_t lba1;
uint8_t lba2;
uint8_t lba3; /* LSB */
} lba;
} u;
uint8_t secount;
addr24 dma_address;
} BIOSCMD;
typedef struct {
uint32_t Segment;
uint32_t SegmentPointer;
} SGE32;
typedef struct {
addr24 Segment;
addr24 SegmentPointer;
} SGE;
#pragma pack(pop) #pragma pack(pop)
typedef struct { typedef struct {
@@ -490,56 +513,6 @@ typedef struct {
} x54x_t; } x54x_t;
#pragma pack(push,1)
typedef struct
{
uint8_t command;
uint8_t lun:3,
reserved:2,
id:3;
union {
struct {
uint16_t cyl;
uint8_t head;
uint8_t sec;
} chs;
struct {
uint8_t lba0; /* MSB */
uint8_t lba1;
uint8_t lba2;
uint8_t lba3; /* LSB */
} lba;
} u;
uint8_t secount;
addr24 dma_address;
} BIOSCMD;
#pragma pack(pop)
#define lba32_blk(p) ((uint32_t)(p->u.lba.lba0<<24) | (p->u.lba.lba1<<16) | \
(p->u.lba.lba2<<8) | p->u.lba.lba3)
/*
*
* Scatter/Gather Segment List Definitions
*
* Adapter limits
*/
#define MAX_SG_DESCRIPTORS 32 /* Always make the array 32 elements long, if less are used, that's not an issue. */
#pragma pack(push,1)
typedef struct {
uint32_t Segment;
uint32_t SegmentPointer;
} SGE32;
#pragma pack(pop)
#pragma pack(push,1)
typedef struct {
addr24 Segment;
addr24 SegmentPointer;
} SGE;
#pragma pack(pop)
extern void x54x_reset_ctrl(x54x_t *dev, uint8_t Reset); extern void x54x_reset_ctrl(x54x_t *dev, uint8_t Reset);
extern void x54x_buf_alloc(scsi_device_t *sd, int length); extern void x54x_buf_alloc(scsi_device_t *sd, int length);
extern void x54x_buf_free(scsi_device_t *sd); extern void x54x_buf_free(scsi_device_t *sd);

View File

@@ -8,7 +8,7 @@
* *
* Brooktree Bt48x series true color RAMDAC emulation. * Brooktree Bt48x series true color RAMDAC emulation.
* *
* Version: @(#)vid_bt48x_ramdac.c 1.0.8 2018/10/06 * Version: @(#)vid_bt48x_ramdac.c 1.0.9 2018/10/21
* *
* Authors: Fred N. van Kempen, <decwiz@yahoo.com> * Authors: Fred N. van Kempen, <decwiz@yahoo.com>
* Miran Grca, <mgrca8@gmail.com> * Miran Grca, <mgrca8@gmail.com>
@@ -209,8 +209,10 @@ bt48x_ramdac_out(uint16_t addr, int rs2, int rs3, uint8_t val, bt48x_ramdac_t *d
indx = svga->dac_addr & 0x03ff; indx = svga->dac_addr & 0x03ff;
if ((dev->type >= BT485) && (svga->hwcursor.xsize == 64)) if ((dev->type >= BT485) && (svga->hwcursor.xsize == 64))
cd = (uint8_t *) dev->cursor64_data; cd = (uint8_t *) dev->cursor64_data;
else else {
indx &= 0xff;
cd = (uint8_t *) dev->cursor32_data; cd = (uint8_t *) dev->cursor32_data;
}
cd[indx] = val; cd[indx] = val;
svga->dac_addr++; svga->dac_addr++;
svga->dac_addr = (svga->dac_addr + 1) & da_mask; svga->dac_addr = (svga->dac_addr + 1) & da_mask;
@@ -351,8 +353,10 @@ bt48x_ramdac_in(uint16_t addr, int rs2, int rs3, bt48x_ramdac_t *dev, svga_t *sv
indx = (svga->dac_addr - 1) & da_mask; indx = (svga->dac_addr - 1) & da_mask;
if ((dev->type >= BT485) && (svga->hwcursor.xsize == 64)) if ((dev->type >= BT485) && (svga->hwcursor.xsize == 64))
cd = (uint8_t *) dev->cursor64_data; cd = (uint8_t *) dev->cursor64_data;
else else {
indx &= 0xff;
cd = (uint8_t *) dev->cursor32_data; cd = (uint8_t *) dev->cursor32_data;
}
temp = cd[indx]; temp = cd[indx];
svga->dac_addr = (svga->dac_addr + 1) & da_mask; svga->dac_addr = (svga->dac_addr + 1) & da_mask;

View File

@@ -9,7 +9,7 @@
* Emulation of select Cirrus Logic cards (CL-GD 5428, * Emulation of select Cirrus Logic cards (CL-GD 5428,
* CL-GD 5429, 5430, 5434 and 5436 are supported). * CL-GD 5429, 5430, 5434 and 5436 are supported).
* *
* Version: @(#)vid_cl54xx.c 1.0.21 2018/10/20 * Version: @(#)vid_cl54xx.c 1.0.22 2018/10/21
* *
* Authors: Fred N. van Kempen, <decwiz@yahoo.com> * Authors: Fred N. van Kempen, <decwiz@yahoo.com>
* Miran Grca, <mgrca8@gmail.com> * Miran Grca, <mgrca8@gmail.com>
@@ -1016,8 +1016,13 @@ gd54xx_write(uint32_t addr, uint8_t val, void *p)
{ {
gd54xx_t *gd54xx = (gd54xx_t *)p; gd54xx_t *gd54xx = (gd54xx_t *)p;
svga_t *svga = &gd54xx->svga; svga_t *svga = &gd54xx->svga;
if (gd54xx->blt.sys_tx) { if ((svga->seqregs[0x07] & 0x01) == 0) {
svga_write(addr, val, svga);
return;
}
if (gd54xx->blt.sys_tx) {
if (gd54xx->blt.mode == CIRRUS_BLTMODE_MEMSYSSRC) { if (gd54xx->blt.mode == CIRRUS_BLTMODE_MEMSYSSRC) {
gd54xx->blt.sys_buf &= ~(0xff << (gd54xx->blt.sys_cnt * 8)); gd54xx->blt.sys_buf &= ~(0xff << (gd54xx->blt.sys_cnt * 8));
gd54xx->blt.sys_buf |= (val << (gd54xx->blt.sys_cnt * 8)); gd54xx->blt.sys_buf |= (val << (gd54xx->blt.sys_cnt * 8));
@@ -1028,7 +1033,7 @@ gd54xx_write(uint32_t addr, uint8_t val, void *p)
} }
} }
return; return;
} }
addr &= svga->banked_mask; addr &= svga->banked_mask;
addr = (addr & 0x7fff) + gd54xx->bank[(addr >> 15) & 1]; addr = (addr & 0x7fff) + gd54xx->bank[(addr >> 15) & 1];
@@ -1043,13 +1048,17 @@ gd54xx_writew(uint32_t addr, uint16_t val, void *p)
gd54xx_t *gd54xx = (gd54xx_t *)p; gd54xx_t *gd54xx = (gd54xx_t *)p;
svga_t *svga = &gd54xx->svga; svga_t *svga = &gd54xx->svga;
if (gd54xx->blt.sys_tx) if ((svga->seqregs[0x07] & 0x01) == 0) {
{ svga_writew(addr, val, svga);
gd54xx_write(addr, val & 0xff, gd54xx); return;
gd54xx_write(addr+1, val >> 8, gd54xx); }
return;
} if (gd54xx->blt.sys_tx) {
gd54xx_write(addr, val, gd54xx);
gd54xx_write(addr+1, val >> 8, gd54xx);
return;
}
addr &= svga->banked_mask; addr &= svga->banked_mask;
addr = (addr & 0x7fff) + gd54xx->bank[(addr >> 15) & 1]; addr = (addr & 0x7fff) + gd54xx->bank[(addr >> 15) & 1];
@@ -1068,14 +1077,18 @@ gd54xx_writel(uint32_t addr, uint32_t val, void *p)
gd54xx_t *gd54xx = (gd54xx_t *)p; gd54xx_t *gd54xx = (gd54xx_t *)p;
svga_t *svga = &gd54xx->svga; svga_t *svga = &gd54xx->svga;
if (gd54xx->blt.sys_tx) if ((svga->seqregs[0x07] & 0x01) == 0) {
{ svga_writel(addr, val, svga);
gd54xx_write(addr, val & 0xff, gd54xx); return;
gd54xx_write(addr+1, val >> 8, gd54xx); }
gd54xx_write(addr+2, val >> 16, gd54xx);
gd54xx_write(addr+3, val >> 24, gd54xx); if (gd54xx->blt.sys_tx) {
return; gd54xx_write(addr, val, gd54xx);
} gd54xx_write(addr+1, val >> 8, gd54xx);
gd54xx_write(addr+2, val >> 16, gd54xx);
gd54xx_write(addr+3, val >> 24, gd54xx);
return;
}
addr &= svga->banked_mask; addr &= svga->banked_mask;
addr = (addr & 0x7fff) + gd54xx->bank[(addr >> 15) & 1]; addr = (addr & 0x7fff) + gd54xx->bank[(addr >> 15) & 1];
@@ -1532,8 +1545,13 @@ gd54xx_read(uint32_t addr, void *p)
{ {
gd54xx_t *gd54xx = (gd54xx_t *)p; gd54xx_t *gd54xx = (gd54xx_t *)p;
svga_t *svga = &gd54xx->svga; svga_t *svga = &gd54xx->svga;
if ((svga->seqregs[0x07] & 0x01) == 0)
return svga_read(addr, svga);
addr &= svga->banked_mask; addr &= svga->banked_mask;
addr = (addr & 0x7fff) + gd54xx->bank[(addr >> 15) & 1]; addr = (addr & 0x7fff) + gd54xx->bank[(addr >> 15) & 1];
return svga_read_linear(addr, svga); return svga_read_linear(addr, svga);
} }
@@ -1544,8 +1562,12 @@ gd54xx_readw(uint32_t addr, void *p)
gd54xx_t *gd54xx = (gd54xx_t *)p; gd54xx_t *gd54xx = (gd54xx_t *)p;
svga_t *svga = &gd54xx->svga; svga_t *svga = &gd54xx->svga;
if ((svga->seqregs[0x07] & 0x01) == 0)
return svga_readw(addr, svga);
addr &= svga->banked_mask; addr &= svga->banked_mask;
addr = (addr & 0x7fff) + gd54xx->bank[(addr >> 15) & 1]; addr = (addr & 0x7fff) + gd54xx->bank[(addr >> 15) & 1];
return svga_readw_linear(addr, svga); return svga_readw_linear(addr, svga);
} }
@@ -1556,8 +1578,12 @@ gd54xx_readl(uint32_t addr, void *p)
gd54xx_t *gd54xx = (gd54xx_t *)p; gd54xx_t *gd54xx = (gd54xx_t *)p;
svga_t *svga = &gd54xx->svga; svga_t *svga = &gd54xx->svga;
if ((svga->seqregs[0x07] & 0x01) == 0)
return svga_readl(addr, svga);
addr &= svga->banked_mask; addr &= svga->banked_mask;
addr = (addr & 0x7fff) + gd54xx->bank[(addr >> 15) & 1]; addr = (addr & 0x7fff) + gd54xx->bank[(addr >> 15) & 1];
return svga_readl_linear(addr, svga); return svga_readl_linear(addr, svga);
} }
@@ -1567,8 +1593,8 @@ gd543x_do_mmio(svga_t *svga, uint32_t addr)
{ {
if (svga->seqregs[0x17] & CIRRUS_MMIO_USE_PCIADDR) if (svga->seqregs[0x17] & CIRRUS_MMIO_USE_PCIADDR)
return 1; return 1;
else
return ((addr & ~0xff) == 0xb8000); return ((addr & ~0xff) == 0xb8000);
} }
@@ -1795,6 +1821,7 @@ gd543x_mmio_read(uint32_t addr, void *p)
} }
else if (gd54xx->mmio_vram_overlap) else if (gd54xx->mmio_vram_overlap)
return gd54xx_read(addr, gd54xx); return gd54xx_read(addr, gd54xx);
return 0xff; return 0xff;
} }
@@ -1809,6 +1836,7 @@ gd543x_mmio_readw(uint32_t addr, void *p)
return gd543x_mmio_read(addr, gd54xx) | (gd543x_mmio_read(addr+1, gd54xx) << 8); return gd543x_mmio_read(addr, gd54xx) | (gd543x_mmio_read(addr+1, gd54xx) << 8);
else if (gd54xx->mmio_vram_overlap) else if (gd54xx->mmio_vram_overlap)
return gd54xx_read(addr, gd54xx) | (gd54xx_read(addr+1, gd54xx) << 8); return gd54xx_read(addr, gd54xx) | (gd54xx_read(addr+1, gd54xx) << 8);
return 0xffff; return 0xffff;
} }
@@ -1823,6 +1851,7 @@ gd543x_mmio_readl(uint32_t addr, void *p)
return gd543x_mmio_read(addr, gd54xx) | (gd543x_mmio_read(addr+1, gd54xx) << 8) | (gd543x_mmio_read(addr+2, gd54xx) << 16) | (gd543x_mmio_read(addr+3, gd54xx) << 24); return gd543x_mmio_read(addr, gd54xx) | (gd543x_mmio_read(addr+1, gd54xx) << 8) | (gd543x_mmio_read(addr+2, gd54xx) << 16) | (gd543x_mmio_read(addr+3, gd54xx) << 24);
else if (gd54xx->mmio_vram_overlap) else if (gd54xx->mmio_vram_overlap)
return gd54xx_read(addr, gd54xx) | (gd54xx_read(addr+1, gd54xx) << 8) | (gd54xx_read(addr+2, gd54xx) << 16) | (gd54xx_read(addr+3, gd54xx) << 24); return gd54xx_read(addr, gd54xx) | (gd54xx_read(addr+1, gd54xx) << 8) | (gd54xx_read(addr+2, gd54xx) << 16) | (gd54xx_read(addr+3, gd54xx) << 24);
return 0xffffffff; return 0xffffffff;
} }

View File

@@ -11,7 +11,7 @@
* This is intended to be used by another SVGA driver, * This is intended to be used by another SVGA driver,
* and not as a card in it's own right. * and not as a card in it's own right.
* *
* Version: @(#)vid_svga.c 1.0.13 2018/10/07 * Version: @(#)vid_svga.c 1.0.14 2018/10/21
* *
* Authors: Fred N. van Kempen, <decwiz@yahoo.com> * Authors: Fred N. van Kempen, <decwiz@yahoo.com>
* Miran Grca, <mgrca8@gmail.com> * Miran Grca, <mgrca8@gmail.com>
@@ -875,15 +875,39 @@ void
svga_write_common(uint32_t addr, uint8_t val, uint8_t linear, void *p) svga_write_common(uint32_t addr, uint8_t val, uint8_t linear, void *p)
{ {
svga_t *svga = (svga_t *)p; svga_t *svga = (svga_t *)p;
int func_select, writemask2 = svga->writemask;
uint32_t write_mask, bit_mask, set_mask, val32 = (uint32_t) val; uint32_t write_mask, bit_mask, set_mask, val32 = (uint32_t) val;
int func_select, writemask2 = svga->writemask;
int memory_map_mode;
cycles -= video_timing_write_b; cycles -= video_timing_write_b;
if (!linear) { if (! linear) {
addr &= svga->banked_mask; memory_map_mode = (svga->gdcreg[6] >> 2) & 3;
addr += svga->write_bank; addr &= 0x1ffff;
switch (memory_map_mode) {
case 0:
break;
case 1:
if (addr >= 0x10000)
return;
addr += svga->write_bank;
break;
case 2:
addr -= 0x10000;
if (addr >= 0x8000)
return;
break;
default:
case 3:
addr -= 0x18000;
if (addr >= 0x8000)
return;
break;
}
} }
if (!(svga->gdcreg[6] & 1)) if (!(svga->gdcreg[6] & 1))
@@ -1008,14 +1032,38 @@ svga_read_common(uint32_t addr, uint8_t linear, void *p)
{ {
svga_t *svga = (svga_t *)p; svga_t *svga = (svga_t *)p;
uint32_t latch_addr = 0, ret; uint32_t latch_addr = 0, ret;
int readplane = svga->readplane; int memory_map_mode, readplane = svga->readplane;
uint8_t ret8;
cycles -= video_timing_read_b; cycles -= video_timing_read_b;
if (!linear) { if (! linear) {
addr &= svga->banked_mask; memory_map_mode = (svga->gdcreg[6] >> 2) & 3;
addr += svga->read_bank;
addr &= 0x1ffff;
switch(memory_map_mode) {
case 0:
break;
case 1:
if (addr >= 0x10000)
return 0xff;
addr += svga->read_bank;
break;
case 2:
addr -= 0x10000;
if (addr >= 0x8000)
return 0xff;
break;
default:
case 3:
addr -= 0x18000;
if (addr >= 0x8000)
return 0xff;
break;
}
latch_addr = (addr << 2) & svga->decode_mask; latch_addr = (addr << 2) & svga->decode_mask;
} }
@@ -1029,6 +1077,12 @@ svga_read_common(uint32_t addr, uint8_t linear, void *p)
readplane = (readplane & 2) | (addr & 1); readplane = (readplane & 2) | (addr & 1);
addr &= ~1; addr &= ~1;
addr <<= 2; addr <<= 2;
addr |= readplane;
addr &= svga->decode_mask;
if (addr >= svga->vram_max)
return 0xff;
addr &= svga->vram_mask;
return svga->vram[addr];
} else } else
addr <<= 2; addr <<= 2;
@@ -1058,16 +1112,15 @@ svga_read_common(uint32_t addr, uint8_t linear, void *p)
if (!(svga->gdcreg[5] & 8)) { if (!(svga->gdcreg[5] & 8)) {
/* read mode 0 */ /* read mode 0 */
return svga->vram[addr | readplane]; return (svga->latch >> (readplane * 8)) & 0xff;
} else {
/* read mode 1 */
ret = (svga->latch ^ mask16[svga->colourcompare & 0x0f]) & mask16[svga->colournocare & 0x0f];
ret8 = (ret & 0xff);
ret8 |= ((ret >> 24) & 0xff);
ret8 |= ((ret >> 16) & 0xff);
ret8 |= ((ret >> 8) & 0xff);
return(~ret8);
} }
/* read mode 1 */
ret = (svga->latch ^ mask16[svga->colourcompare & 0x0f]) & mask16[svga->colournocare & 0x0f];
ret |= ret >> 16;
ret |= ret >> 8;
ret = (~ret) & 0xff;
return(ret);
} }

View File

@@ -877,7 +877,7 @@ ui_sb_menu_command(int idm, uint8_t tag)
/* Save current drive/pathname for later re-use. */ /* Save current drive/pathname for later re-use. */
cdev->prev_host_drive = cdev->host_drive; cdev->prev_host_drive = cdev->host_drive;
if (! cdev->prev_image_path) if (! cdev->prev_image_path)
cdev->prev_image_path = (wchar_t *)mem_alloc(1024); cdev->prev_image_path = (wchar_t *)mem_alloc(1024 * sizeof(wchar_t));
wcscpy(cdev->prev_image_path, str); wcscpy(cdev->prev_image_path, str);
/* Close the current drive/pathname. */ /* Close the current drive/pathname. */

View File

@@ -12,7 +12,7 @@
* we will not use that, but, instead, use a new window which * we will not use that, but, instead, use a new window which
* coverrs the entire desktop. * coverrs the entire desktop.
* *
* Version: @(#)win_sdl.c 1.0.5 2018/10/05 * Version: @(#)win_sdl.c 1.0.6 2018/10/21
* *
* Authors: Fred N. van Kempen, <decwiz@yahoo.com> * Authors: Fred N. van Kempen, <decwiz@yahoo.com>
* Michael Dr<44>ing, <michael@drueing.de> * Michael Dr<44>ing, <michael@drueing.de>
@@ -83,7 +83,10 @@ static SDL_Window *sdl_win = NULL;
static SDL_Renderer *sdl_render = NULL; static SDL_Renderer *sdl_render = NULL;
static SDL_Texture *sdl_tex = NULL; static SDL_Texture *sdl_tex = NULL;
static HWND sdl_hwnd = NULL; static HWND sdl_hwnd = NULL;
static HWND sdl_parent_hwnd = NULL;
static int sdl_w, sdl_h; static int sdl_w, sdl_h;
static int cur_w, cur_h;
static int sdl_fs;
/* Pointers to the real functions. */ /* Pointers to the real functions. */
@@ -130,15 +133,131 @@ static const dllimp_t sdl_imports[] = {
}; };
static void
sdl_stretch(int *w, int *h, int *x, int *y)
{
double dw, dh, dx, dy, temp, temp2, ratio_w, ratio_h, gsr, hsr;
switch (vid_fullscreen_scale) {
case FULLSCR_SCALE_FULL:
*w = sdl_w;
*h = sdl_h;
*x = 0;
*y = 0;
break;
case FULLSCR_SCALE_43:
dw = (double) sdl_w;
dh = (double) sdl_h;
temp = (dh / 3.0) * 4.0;
dx = (dw - temp) / 2.0;
dw = temp;
*w = (int) dw;
*h = (int) dh;
*x = (int) dx;
*y = 0;
break;
case FULLSCR_SCALE_SQ:
dw = (double) sdl_w;
dh = (double) sdl_h;
temp = ((double) *w);
temp2 = ((double) *h);
dx = (dw / 2.0) - ((dh * temp) / (temp2 * 2.0));
dy = 0.0;
if (dx < 0.0) {
dx = 0.0;
dy = (dw / 2.0) - ((dh * temp2) / (temp * 2.0));
}
dw -= (dx * 2.0);
dh -= (dy * 2.0);
*w = (int) dw;
*h = (int) dh;
*x = (int) dx;
*y = (int) dy;
break;
case FULLSCR_SCALE_INT:
dw = (double) sdl_w;
dh = (double) sdl_h;
temp = ((double) *w);
temp2 = ((double) *h);
ratio_w = dw / ((double) *w);
ratio_h = dh / ((double) *h);
if (ratio_h < ratio_w)
ratio_w = ratio_h;
dx = (dw / 2.0) - ((temp * ratio_w) / 2.0);
dy = (dh / 2.0) - ((temp2 * ratio_h) / 2.0);
dw -= (dx * 2.0);
dh -= (dy * 2.0);
*w = (int) dw;
*h = (int) dh;
*x = (int) dx;
*y = (int) dy;
break;
case FULLSCR_SCALE_KEEPRATIO:
dw = (double) sdl_w;
dh = (double) sdl_h;
hsr = dw / dh;
gsr = ((double) *w) / ((double) *h);
if (gsr <= hsr) {
temp = dh * gsr;
dx = (dw - temp) / 2.0;
dw = temp;
*w = (int) dw;
*h = (int) dh;
*x = (int) dx;
*y = 0;
} else {
temp = dw / gsr;
dy = (dh - temp) / 2.0;
dh = temp;
*w = (int) dw;
*h = (int) dh;
*x = 0;
*y = (int) dy;
}
break;
}
}
static void
sdl_resize(int x, int y)
{
int ww = 0, wh = 0, wx = 0, wy = 0;
DEBUG("SDL: resizing to %dx%d\n", x, y);
if ((x == cur_w) && (y == cur_h)) return;
DEBUG("sdl_resize(%i, %i)\n", x, y);
ww = x;
wh = y;
sdl_stretch(&ww, &wh, &wx, &wy);
MoveWindow(sdl_hwnd, wx, wy, ww, wh, TRUE);
cur_w = x;
cur_h = y;
}
static void static void
sdl_blit(int x, int y, int y1, int y2, int w, int h) sdl_blit(int x, int y, int y1, int y2, int w, int h)
{ {
SDL_Rect r_src; SDL_Rect r_src;
void *pixeldata; void *pixeldata;
int xx, yy, ret;
int pitch; int pitch;
int yy;
if ((y1 == y2) || (buffer32 == NULL)) { if (y1 == y2) {
video_blit_complete();
return;
}
if (buffer32 == NULL) {
video_blit_complete(); video_blit_complete();
return; return;
} }
@@ -151,25 +270,34 @@ sdl_blit(int x, int y, int y1, int y2, int w, int h)
sdl_LockTexture(sdl_tex, 0, &pixeldata, &pitch); sdl_LockTexture(sdl_tex, 0, &pixeldata, &pitch);
for (yy = y1; yy < y2; yy++) { for (yy = y1; yy < y2; yy++) {
if ((y + yy) >= 0 && (y + yy) < buffer32->h) if ((y + yy) >= 0 && (y + yy) < buffer32->h) {
#if 0 if (vid_grayscale || invert_display)
if (video_grayscale || invert_display)
video_transform_copy((uint32_t *) &(((uint8_t *)pixeldata)[yy * pitch]), &(((uint32_t *)buffer32->line[y + yy])[x]), w); video_transform_copy((uint32_t *) &(((uint8_t *)pixeldata)[yy * pitch]), &(((uint32_t *)buffer32->line[y + yy])[x]), w);
else else
#endif
memcpy((uint32_t *) &(((uint8_t *)pixeldata)[yy * pitch]), &(((uint32_t *)buffer32->line[y + yy])[x]), w * 4); memcpy((uint32_t *) &(((uint8_t *)pixeldata)[yy * pitch]), &(((uint32_t *)buffer32->line[y + yy])[x]), w * 4);
}
} }
video_blit_complete(); video_blit_complete();
sdl_UnlockTexture(sdl_tex); sdl_UnlockTexture(sdl_tex);
if (sdl_fs) {
get_screen_size_natural(&xx, &yy);
DEBUG("sdl_blit(%i, %i, %i, %i, %i, %i) (%i, %i)\n", x, y, y1, y2, w, h, xx, yy);
if (w == xx)
sdl_resize(w, h);
DEBUG("(%08X, %08X, %08X)\n", sdl_win, sdl_render, sdl_tex);
}
r_src.x = 0; r_src.x = 0;
r_src.y = 0; r_src.y = 0;
r_src.w = w; r_src.w = w;
r_src.h = h; r_src.h = h;
sdl_RenderCopy(sdl_render, sdl_tex, &r_src, 0); ret = sdl_RenderCopy(sdl_render, sdl_tex, &r_src, 0);
if (ret)
DEBUG("SDL: unable to copy texture to renderer (%s)\n", sdl_GetError());
sdl_RenderPresent(sdl_render); sdl_RenderPresent(sdl_render);
} }
@@ -199,15 +327,18 @@ sdl_close(void)
if (sdl_hwnd != NULL) { if (sdl_hwnd != NULL) {
plat_set_input(hwndMain); plat_set_input(hwndMain);
#if 1
ShowWindow(hwndRender, TRUE); ShowWindow(hwndRender, TRUE);
SetFocus(hwndMain); SetFocus(hwndMain);
#endif
DestroyWindow(sdl_hwnd); DestroyWindow(sdl_hwnd);
sdl_hwnd = NULL; sdl_hwnd = NULL;
} }
if (sdl_parent_hwnd != NULL) {
DestroyWindow(sdl_parent_hwnd);
sdl_parent_hwnd = NULL;
}
/* Quit and unload the DLL if possible. */ /* Quit and unload the DLL if possible. */
if (sdl_handle != NULL) { if (sdl_handle != NULL) {
sdl_Quit(); sdl_Quit();
@@ -223,6 +354,7 @@ sdl_init(int fs)
{ {
wchar_t temp[128]; wchar_t temp[128];
SDL_version ver; SDL_version ver;
int x, y;
INFO("SDL: init (fs=%d)\n", fs); INFO("SDL: init (fs=%d)\n", fs);
@@ -253,7 +385,7 @@ sdl_init(int fs)
/* Create the desktop-covering window. */ /* Create the desktop-covering window. */
swprintf(temp, sizeof_w(temp), swprintf(temp, sizeof_w(temp),
L"%s v%s Full-Screen", EMU_NAME, emu_version); L"%s v%s Full-Screen", EMU_NAME, emu_version);
sdl_hwnd = CreateWindow(FS_CLASS_NAME, sdl_parent_hwnd = CreateWindow(FS_CLASS_NAME,
temp, temp,
WS_POPUP, WS_POPUP,
0, 0, sdl_w, sdl_h, 0, 0, sdl_w, sdl_h,
@@ -261,12 +393,28 @@ sdl_init(int fs)
NULL, NULL,
hInstance, hInstance,
NULL); NULL);
SetWindowPos(sdl_parent_hwnd, HWND_TOPMOST,
0, 0, sdl_w, sdl_h, SWP_SHOWWINDOW);
/* Create the actual rendering window. */
swprintf(temp, sizeof_w(temp), L"%s v%s", EMU_NAME, emu_version);
sdl_hwnd = CreateWindow(FS_CLASS_NAME,
temp,
WS_POPUP,
0, 0, sdl_w, sdl_h,
sdl_parent_hwnd,
NULL,
hInstance,
NULL);
DEBUG("SDL: FS %dx%d window at %08lx\n", sdl_w, sdl_h, sdl_hwnd); DEBUG("SDL: FS %dx%d window at %08lx\n", sdl_w, sdl_h, sdl_hwnd);
/* Redirect RawInput to this new window. */ /* Redirect RawInput to this new window. */
plat_set_input(sdl_hwnd); plat_set_input(sdl_hwnd);
/* Show the window, make it topmost, and give it focus. */ /* Show the window, make it topmost, and give it focus. */
get_screen_size_natural(&x, &y);
sdl_stretch(&sdl_w, &sdl_h, &x, &y);
SetWindowPos(sdl_hwnd, HWND_TOPMOST, SetWindowPos(sdl_hwnd, HWND_TOPMOST,
0, 0, sdl_w, sdl_h, SWP_SHOWWINDOW); 0, 0, sdl_w, sdl_h, SWP_SHOWWINDOW);
@@ -276,11 +424,13 @@ sdl_init(int fs)
/* Create the SDL window from the render window. */ /* Create the SDL window from the render window. */
sdl_win = sdl_CreateWindowFrom((void *)hwndRender); sdl_win = sdl_CreateWindowFrom((void *)hwndRender);
} }
if (sdl_win == NULL) { if (sdl_win == NULL) {
ERRLOG("SDL: unable to CreateWindowFrom (%s)\n", sdl_GetError()); ERRLOG("SDL: unable to CreateWindowFrom (%s)\n", sdl_GetError());
sdl_close(); sdl_close();
return(0); return(0);
} }
sdl_fs = fs;
/* /*
* TODO: * TODO:
@@ -320,55 +470,18 @@ sdl_init(int fs)
} }
static void
sdl_resize(int x, int y)
{
DEBUG("SDL: resizing to %dx%d\n", x, y);
}
static void static void
sdl_screenshot(const wchar_t *fn) sdl_screenshot(const wchar_t *fn)
{ {
#if 0 #if 0
int i, res, x, y, width = 0, height = 0; uint8_t *pixels = NULL;
unsigned char* rgba = NULL; int res;
png_bytep *b_rgb = NULL;
FILE *fp = NULL;
sdl_GetWindowSize(sdl_win, &width, &height); sdl_GetWindowSize(sdl_win, &width, &height);
/* Create file. */
if ((fp = plat_fopen(fn, L"wb")) == NULL) {
ERRLOG("SDL: screenshot: file %ls could not be opened for writing\n", fn);
return;
}
/* initialize stuff */
png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
if (png_ptr == NULL) {
ERRLOG("SDL: screenshot: create_write_struct failed\n");
fclose(fp);
return;
}
info_ptr = png_create_info_struct(png_ptr);
if (info_ptr == NULL) {
ERRLOG("SDL: screenshot: create_info_struct failed");
fclose(fp);
return;
}
png_init_io(png_ptr, fp);
png_set_IHDR(png_ptr, info_ptr, width, height,
8, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE,
PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
pixels = (uint8_t *)mem_alloc(width * height * 4); pixels = (uint8_t *)mem_alloc(width * height * 4);
if (pixels == NULL) { if (pixels == NULL) {
ERRLOG("SDL: screenshot: unable to allocate RGBA Bitmap memory\n"); ERRLOG("SDL: screenshot: unable to allocate RGBA Bitmap memory\n");
fclose(fp);
return; return;
} }
@@ -377,41 +490,10 @@ sdl_screenshot(const wchar_t *fn)
if (res != 0) { if (res != 0) {
ERRLOG("SDL: screenshot: error reading render pixels\n"); ERRLOG("SDL: screenshot: error reading render pixels\n");
free(pixels); free(pixels);
fclose(fp);
return; return;
} }
if ((b_rgb = (png_bytep *)mem_alloc(sizeof(png_bytep) * height)) == NULL) { if (pixels) free(pixels);
ERRLOG("[sdl_take_screenshot] Unable to Allocate RGB Bitmap Memory");
free(rgba);
fclose(fp);
return;
}
for (y = 0; y < height; ++y) {
b_rgb[y] = (png_byte *)mem_alloc(png_get_rowbytes(png_ptr, info_ptr));
for (x = 0; x < width; ++x) {
b_rgb[y][(x) * 3 + 0] = rgba[(y * width + x) * 4 + 0];
b_rgb[y][(x) * 3 + 1] = rgba[(y * width + x) * 4 + 1];
b_rgb[y][(x) * 3 + 2] = rgba[(y * width + x) * 4 + 2];
}
}
png_write_info(png_ptr, info_ptr);
png_write_image(png_ptr, b_rgb);
png_write_end(png_ptr, NULL);
/* cleanup heap allocation */
for (i = 0; i < height; i++)
if (b_rgb[i]) free(b_rgb[i]);
if (b_rgb) free(b_rgb);
if (rgba) free(rgba);
if (fp) fclose(fp);
#endif #endif
} }