Re-organisation of video emulation.

This commit is contained in:
TomW 2013-06-24 20:42:35 +01:00
commit 58085bcc87
86 changed files with 8087 additions and 7229 deletions

View file

@ -19,6 +19,8 @@
#include "timer.h"
#include "x86.h"
int nmi = 0;
int nextcyc=0;
int cycdiff;
int is8086=0;

View file

@ -57,3 +57,23 @@ void device_speed_changed()
}
}
}
char *device_add_status_info(char *s, int max_len)
{
int c;
s[0] = 0;
for (c = 0; c < 256; c++)
{
if (devices[c] != NULL)
{
if (devices[c]->add_status_info != NULL)
{
int len = devices[c]->add_status_info(s, max_len, device_priv[c]);
s += len;
max_len -= len;
}
}
}
}

View file

@ -2,11 +2,13 @@ typedef struct device_t
{
char name[50];
void *(*init)();
void (*close)(void *priv);
void (*speed_changed)(void *priv);
void (*close)(void *p);
void (*speed_changed)(void *p);
int (*add_status_info)(char *s, int max_len, void *p);
} device_t;
void device_init();
void device_add(device_t *d);
void device_close_all();
void device_speed_changed();
char *device_add_status_info(char *s, int max_len);

View file

@ -213,7 +213,7 @@ void dma_page_write(uint16_t addr, uint8_t val, void *priv)
{
/* if (!(addr&0xF))
{*/
pclog("Write page %03X %02X %04X:%04X\n",addr,val,CS,pc);
// pclog("Write page %03X %02X %04X:%04X\n",addr,val,CS,pc);
// if (val==0x29 && pc==0xD25) output=1;
// }
dmapages[addr&0xF]=val;
@ -258,12 +258,12 @@ uint8_t _dma_read(uint32_t addr)
{
switch (addr&0xFFFF8000)
{
case 0xA0000: case 0xA8000:
/* case 0xA0000: case 0xA8000:
return video_read_a000(addr, NULL);
case 0xB0000:
return video_read_b000(addr, NULL);
case 0xB8000:
return video_read_b800(addr, NULL);
return video_read_b800(addr, NULL);*/
}
if (isram[addr>>16]) return ram[addr];
return 0xff;
@ -271,9 +271,10 @@ uint8_t _dma_read(uint32_t addr)
void _dma_write(uint32_t addr, uint8_t val)
{
pclog("_dma_write %08X %02X\n", addr, val);
switch (addr&0xFFFF8000)
{
case 0xA0000: case 0xA8000:
/* case 0xA0000: case 0xA8000:
video_write_a000(addr,val, NULL);
return;
case 0xB0000:
@ -284,7 +285,7 @@ void _dma_write(uint32_t addr, uint8_t val)
return;
case 0xC0000: case 0xC8000: case 0xD0000: case 0xD8000:
case 0xE0000: case 0xE8000: case 0xF0000: case 0xF8000:
return;
return;*/
}
if (isram[addr >> 16])
ram[addr] = val;

269
src/ega.c
View file

@ -1,217 +1,10 @@
#include "ibm.h"
#include "video.h"
void doblit();
int egareads=0,egawrites=0;
int framecount=0;
int changeframecount=2;
void redotextlookup();
int output;
int svgaon=0;
uint32_t svgarbank,svgawbank;
uint8_t svgaseg,svgaseg2;
uint8_t svga3d8;
uint8_t oldvram=0;
int frames;
int hsync;
uint8_t cgastat;
uint8_t gdcreg[16];
int gdcaddr;
uint8_t attrregs[32];
int attraddr,attrff=0;
uint8_t ega3c2;
uint8_t rotatevga[8][256];
uint8_t writemask,charset;
int writemode,readmode,readplane,chain4;
uint8_t colourcompare,colournocare;
uint8_t la,lb,lc,ld;
uint8_t *vram;
int egares;
uint8_t seqregs[64];
int seqaddr;
uint8_t oak_regs[32];
int oak_index;
extern int egaswitchread,egaswitches;
/*For VGA non-interlace colour, ID bits should be 1 1 0 or 6*/
int vres=0;
PALETTE vgapal;
uint32_t *pallook,pallook16[256],pallook64[256],pallook256[256];
int dacread,dacwrite,dacpos=0;
int palchange=1;
int fullchange;
int dispontime,dispofftime;
double disptime;
int ega_vtotal,ega_dispend,ega_vsyncstart,ega_split,ega_hdisp,ega_rowoffset;
int vidclock;
float cpuclock;
int bpp;
uint32_t vrammask;
uint8_t changedvram[(8192*1024)/1024];
int charseta,charsetb;
int egapal[16];
int displine;
int rowdbl=0;
int scrblank=0;
uint8_t edatlookup[4][4];
uint32_t textlookup[256][2][16][16];
/*void redotextlookup()
{
int c,d,e;
uint32_t temp;
int coffset=(VGA)?0:64;
for (c=0;c<256;c++)
{
for (d=0;d<16;d++)
{
// printf("ATTR %i=%02X+%02X\n",d,attrregs[d],coffset);
for (e=0;e<16;e++)
{
temp=0;
if (c&0x80) temp|=(attrregs[d]+coffset);
else temp|=(attrregs[e]+coffset);
if (c&0x40) temp|=(attrregs[d]+coffset)<<8;
else temp|=(attrregs[e]+coffset)<<8;
if (c&0x20) temp|=(attrregs[d]+coffset)<<16;
else temp|=(attrregs[e]+coffset)<<16;
if (c&0x10) temp|=(attrregs[d]+coffset)<<24;
else temp|=(attrregs[e]+coffset)<<24;
// if (c==0x5) printf("%08X %i %i %02X %02X\n",temp,d,e,attrregs[d],attrregs[e]);
textlookup[c][0][d][e]=temp;
temp=0;
if (c&0x08) temp|=(attrregs[d]+coffset);
else temp|=(attrregs[e]+coffset);
if (c&0x04) temp|=(attrregs[d]+coffset)<<8;
else temp|=(attrregs[e]+coffset)<<8;
if (c&0x02) temp|=(attrregs[d]+coffset)<<16;
else temp|=(attrregs[e]+coffset)<<16;
if (c&0x01) temp|=(attrregs[d]+coffset)<<24;
else temp|=(attrregs[e]+coffset)<<24;
textlookup[c][1][d][e]=temp;
}
}
}
}*/
void initega()
{
int c,d,e;
bpp=8;
for (c=0;c<256;c++)
{
e=c;
for (d=0;d<8;d++)
{
rotatevga[d][c]=e;
e=(e>>1)|((e&1)?0x80:0);
}
}
crtc[0xC]=crtc[0xD]=0;
for (c=0;c<4;c++)
{
for (d=0;d<4;d++)
{
edatlookup[c][d]=0;
if (c&1) edatlookup[c][d]|=1;
if (d&1) edatlookup[c][d]|=2;
if (c&2) edatlookup[c][d]|=0x10;
if (d&2) edatlookup[c][d]|=0x20;
// printf("Edat %i,%i now %02X\n",c,d,edatlookup[c][d]);
}
}
/*redotextlookup();*/
for (c=0;c<256;c++)
{
pallook64[c]=makecol32(((c>>2)&1)*0xAA,((c>>1)&1)*0xAA,(c&1)*0xAA);
pallook64[c]+=makecol32(((c>>5)&1)*0x55,((c>>4)&1)*0x55,((c>>3)&1)*0x55);
pallook16[c]=makecol32(((c>>2)&1)*0xAA,((c>>1)&1)*0xAA,(c&1)*0xAA);
pallook16[c]+=makecol32(((c>>4)&1)*0x55,((c>>4)&1)*0x55,((c>>4)&1)*0x55);
if ((c&0x17)==6) pallook16[c]=makecol32(0xAA,0x55,0);
// printf("%03i %08X\n",c,pallook[c]);
}
pallook=pallook16;
seqregs[0xC]=0x20;
vrammask=(ET4000)?0xFFFFF:0x1FFFFF;
// writeega_func=writeega;
gdcreg[6]=8;
gdcreg[8]=0xFF;
writemode=0;
chain4=0;
writemask=3;
et4k_b8000=0;
svgarbank=svgawbank=0;
}
uint32_t egabase,egaoffset;
void cacheega()
{
egabase=(crtc[0xC]<<8)|crtc[0xD];
if (ET4000 || ET4000W32 || TRIDENT)
egabase|=((crtc[0x33]&3)<<18);
// printf("EGABASE %05X\n",egabase);
// egaoffset=8-((attrregs[0x13])&7);
// printf("Cache base!\n");
}
void cacheega2()
{
// egabase=(crtc[0xC]<<8)|crtc[0xD];
if (gdcreg[5]&0x40) egaoffset=8-(((attrregs[0x13])&7)>>1);
else egaoffset=8-((attrregs[0x13])&7);
// printf("Cache offset!\n");
}
int olddisplines,oldxsize;
int oldreadflash;
int oldegaaddr,oldegasplit;
int vc,sc;
int egadispon=0;
int linepos;
int displine;
uint32_t ma,maback,ca;
int firstline,lastline;
int xsize,ysize;
int scrollcache;
int con,cursoron,cgablink;
BITMAP *buffer,*vbuf,*buffer32;
int linecountff=0;
void dumpegaregs()
{
int c;
/* int c;
printf("CRTC :");
for (c=0;c<0x20;c++) printf(" %02X",crtc[c]);
printf("\n");
@ -234,64 +27,6 @@ void dumpegaregs()
for (c=0;c<0x10;c++) printf(" %02X",gdcreg[c]);
printf("\n");
// printf("OLD CTRL2 = %02X NEW CTRL2 = %02X DAC = %02X 3C2 = %02X\n",tridentoldctrl2,tridentnewctrl2,tridentdac,ega3c2);
printf("BPP = %02X\n",bpp);
printf("BPP = %02X\n",bpp);*/
}
int oddeven;
int wx,wy;
int vslines;
int frames = 0;
void doblit()
{
startblit();
if ((wx!=xsize || wy!=ysize) && !vid_resize)
{
xsize=wx;
ysize=wy+1;
if (xsize<64) xsize=656;
if (ysize<32) ysize=200;
if (vres) updatewindowsize(xsize,ysize<<1);
else updatewindowsize(xsize,ysize);
}
video_blit_memtoscreen(32, 0, 0, ysize, xsize, ysize);
if (readflash) rectfill(screen,winsizex-40,8,winsizex-8,14,0xFFFFFFFF);
endblit();
frames++;
}
int ega_getdepth()
{
if (!(gdcreg[6]&1)) return 0;
switch (gdcreg[5]&0x60)
{
case 0x00:
return 4;
case 0x20:
return 2;
case 0x40: case 0x60:
if (TRIDENT || ET4000W32) return bpp;
return 8;
}
return 0;
}
int ega_getx()
{
int x;
if (!(gdcreg[6]&1)) return (crtc[1]+1);
if ((attrregs[0x10]&0x40) && !(tridentoldctrl2&0x10)) x=(crtc[1]+1)*4;
else x=(crtc[1]+1)*8;
if (TRIDENT && (bpp==15 || bpp==16)) x>>=1;
if (TRIDENT && bpp==24) x=(x<<1)/3;
return x;
}
int ega_gety()
{
if (crtc[0x1E]&4) return (ega_dispend/((crtc[9]&31)+1))<<1;
if (crtc[9]&0x80) return (ega_dispend/((crtc[9]&31)+1))>>1;
return ega_dispend/((crtc[9]&31)+1);
}

View file

@ -458,3 +458,6 @@ extern int times;
extern float isa_timing, bus_timing;
extern int frame;
uint8_t *vramp;

View file

@ -3,6 +3,7 @@
#include "mem.h"
#include "pic.h"
#include "sound.h"
#include "timer.h"
#include "keyboard.h"
#include "keyboard_amstrad.h"
@ -31,6 +32,7 @@ static uint8_t amstrad_systemstat_1, amstrad_systemstat_2;
void keyboard_amstrad_poll()
{
keybsenddelay += (1000 * TIMER_USEC);
if (keyboard_amstrad.wantirq)
{
keyboard_amstrad.wantirq = 0;
@ -166,4 +168,6 @@ void keyboard_amstrad_init()
keyboard_amstrad_reset();
keyboard_send = keyboard_amstrad_adddata;
keyboard_poll = keyboard_amstrad_poll;
timer_add(keyboard_amstrad_poll, &keybsenddelay, TIMER_ALWAYS_ENABLED, NULL);
}

View file

@ -3,6 +3,7 @@
#include "mem.h"
#include "mouse.h"
#include "pic.h"
#include "timer.h"
#include "keyboard.h"
#include "keyboard_olim24.h"
@ -38,6 +39,7 @@ static uint8_t mouse_scancodes[7];
void keyboard_olim24_poll()
{
keybsenddelay += (1000 * TIMER_USEC);
//pclog("poll %i\n", keyboard_olim24.wantirq);
if (keyboard_olim24.wantirq)
{
@ -283,4 +285,6 @@ void keyboard_olim24_init()
keyboard_send = keyboard_olim24_adddata;
keyboard_poll = keyboard_olim24_poll;
mouse_poll = mouse_olim24_poll;
timer_add(keyboard_olim24_poll, &keybsenddelay, TIMER_ALWAYS_ENABLED, NULL);
}

View file

@ -179,8 +179,6 @@ void pc_reset()
// sb_reset();
ali1429_reset();
et4000w32_reset();
// video_init();
}
@ -209,8 +207,8 @@ void initpc()
initvideo();
mem_init();
loadbios();
mem_load_video_bios();
loadbios();
loaddisc(0,discfns[0]);
loaddisc(1,discfns[1]);
@ -221,10 +219,8 @@ void initpc()
//loadfont();
loadnvr();
resetvideo();
sound_init();
inithdc();
initega();
resetide();
ioctl_open(cdrom_drive);
model_init();
@ -244,7 +240,6 @@ void initpc()
/* if (romset==ROM_AMI386 || romset==ROM_AMI486) */fullspeed();
mem_updatecache();
ali1429_reset();
et4000w32_reset();
// CPUID=(is486 && (cpuspeed==7 || cpuspeed>=9));
// pclog("Init - CPUID %i %i\n",CPUID,cpuspeed);
shadowbios=0;
@ -330,6 +325,7 @@ void runpc()
framecount++;
if (framecountx>=100)
{
pclog("onesec\n");
framecountx=0;
mips=(float)insc/1000000.0f;
insc=0;
@ -404,7 +400,6 @@ void closepc()
{
atapi->exit();
// ioctl_close();
dumpegaregs();
dumppic();
// output=7;
// setpitclock(clocks[0][0][0]);

View file

@ -50,8 +50,9 @@ BEGIN
COMBOBOX IDC_COMBOSPD,62,116,107,120,CBS_DROPDOWN | WS_VSCROLL | WS_TABSTOP
COMBOBOX IDC_COMBOSND,62,136,107,120,CBS_DROPDOWN | WS_VSCROLL | WS_TABSTOP
COMBOBOX IDC_COMBOMEM,62,152,107,120,CBS_DROPDOWN | WS_VSCROLL | WS_TABSTOP
CONTROL "Game Blaster",IDC_CHECK3,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,172,118,10
CONTROL "Composite CGA",IDC_CHECK4,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,188,118,10
CONTROL "CMS / Game Blaster",IDC_CHECK3,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,172,118,10
CONTROL "Gravis Ultrasound",IDC_CHECKGUS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,188,118,10
CONTROL "Composite CGA",IDC_CHECK4,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,204,118,10
LTEXT "Machine :",IDC_STATIC,15,16,40,10
LTEXT "Video :",IDC_STATIC,15,36,34,10
LTEXT "CPU type :",IDC_STATIC,15,56,34,10
@ -150,9 +151,5 @@ BEGIN
LTEXT "6",IDC_STEXT6,16,76,180,10
LTEXT "7",IDC_STEXT7,16,88,180,10
LTEXT "8",IDC_STEXT8,16,100,180,10
LTEXT "9",IDC_STEXT9,16,112,180,10
LTEXT "10",IDC_STEXT10,16,124,180,10
LTEXT "11",IDC_STEXT11,16,136,180,10
LTEXT "12",IDC_STEXT12,16,148,180,10
LTEXT "13",IDC_STEXT13,16,160,180,10
LTEXT "9",IDC_STEXT_DEVICE,16,112,180,1000
END

View file

@ -31,14 +31,15 @@ void setpitclock(float clock)
cpuclock=clock;
PITCONST=clock/1193182.0;
CGACONST=(clock/(19687500.0/11.0));
MDACONST=(clock/1813000.0);
MDACONST=(clock/2032125.0);
VGACONST1=(clock/25175000.0);
VGACONST2=(clock/28322000.0);
isa_timing = clock/8000000.0;
bus_timing = clock/(double)cpu_busspeed;
video_updatetiming();
// pclog("egacycles %i egacycles2 %i temp %f clock %f\n",egacycles,egacycles2,temp,clock);
video_recalctimings();
/* if (video_recalctimings)
video_recalctimings();*/
RTCCONST=clock/32768.0;
TIMER_USEC = (int)((clock / 1000000.0f) * (float)(1 << TIMER_SHIFT));
device_speed_changed();

View file

@ -56,8 +56,4 @@
#define IDC_STEXT6 1105
#define IDC_STEXT7 1106
#define IDC_STEXT8 1107
#define IDC_STEXT9 1108
#define IDC_STEXT10 1109
#define IDC_STEXT11 1110
#define IDC_STEXT12 1111
#define IDC_STEXT13 1112
#define IDC_STEXT_DEVICE 1108

View file

@ -58,5 +58,6 @@ device_t adlib_device =
"AdLib",
adlib_init,
adlib_close,
NULL,
NULL
};

View file

@ -593,5 +593,6 @@ device_t adgold_device =
"AdLib Gold",
adgold_init,
adgold_close,
NULL,
NULL
};

View file

@ -175,5 +175,6 @@ device_t cms_device =
"Creative Music System / Game Blaster",
cms_init,
cms_close,
NULL,
NULL
};

View file

@ -1103,5 +1103,6 @@ device_t gus_device =
"Gravis UltraSound",
gus_init,
gus_close,
gus_speed_changed
gus_speed_changed,
NULL
};

View file

@ -749,5 +749,6 @@ device_t pas16_device =
"Pro Audio Spectrum 16",
pas16_init,
pas16_close,
NULL,
NULL
};

View file

@ -376,40 +376,46 @@ device_t sb_1_device =
"Sound Blaster v1.0",
sb_1_init,
sb_close,
sb_speed_changed
sb_speed_changed,
NULL
};
device_t sb_15_device =
{
"Sound Blaster v1.5",
sb_15_init,
sb_close,
sb_speed_changed
sb_speed_changed,
NULL
};
device_t sb_2_device =
{
"Sound Blaster v2.0",
sb_2_init,
sb_close,
sb_speed_changed
sb_speed_changed,
NULL
};
device_t sb_pro_v1_device =
{
"Sound Blaster Pro v1",
sb_pro_v1_init,
sb_close,
sb_speed_changed
sb_speed_changed,
NULL
};
device_t sb_pro_v2_device =
{
"Sound Blaster Pro v2",
sb_pro_v2_init,
sb_close,
sb_speed_changed
sb_speed_changed,
NULL
};
device_t sb_16_device =
{
"Sound Blaster 16",
sb_16_init,
sb_close,
sb_speed_changed
sb_speed_changed,
NULL
};

View file

@ -272,6 +272,12 @@ void sb_exec_command(sb_dsp_t *dsp)
pclog("sb_exec_command : SB command %02X\n", dsp->sb_command);
switch (dsp->sb_command)
{
case 0x01: /*???*/
sb_add_data(dsp, 0);
break;
case 0x03: /*ASP status*/
sb_add_data(dsp, 0);
break;
case 0x10: /*8-bit direct mode*/
dsp->sbdat = dsp->sbdatl = dsp->sbdatr = (dsp->sb_data[0] ^ 0x80) << 8;
break;

View file

@ -194,5 +194,6 @@ device_t sn76489_device =
"TI SN74689 PSG",
sn76489_init,
sn76489_close,
NULL,
NULL
};

View file

@ -303,5 +303,6 @@ device_t wss_device =
"Windows Sound System",
wss_init,
wss_close,
NULL,
NULL
};

View file

@ -1,142 +1,163 @@
/*ATI 18800 emulation (VGA Edge-16)*/
#include <stdlib.h>
#include "ibm.h"
#include "device.h"
#include "io.h"
#include "video.h"
#include "vid_ati18800.h"
#include "vid_ati_eeprom.h"
#include "vid_svga.h"
static uint8_t ati_regs[256];
static int ati_index;
void ati18800_out(uint16_t addr, uint8_t val, void *priv)
typedef struct ati18800_t
{
svga_t svga;
ati_eeprom_t eeprom;
uint8_t regs[256];
int index;
} ati18800_t;
void ati18800_out(uint16_t addr, uint8_t val, void *p)
{
ati18800_t *ati18800 = (ati18800_t *)p;
svga_t *svga = &ati18800->svga;
uint8_t old;
pclog("ati18800_out : %04X %02X %04X:%04X\n", addr, val, CS,pc);
if (((addr&0xFFF0) == 0x3D0 || (addr&0xFFF0) == 0x3B0) && !(svga_miscout&1)) addr ^= 0x60;
if (((addr&0xFFF0) == 0x3D0 || (addr&0xFFF0) == 0x3B0) && !(svga->miscout&1)) addr ^= 0x60;
switch (addr)
{
case 0x1ce:
ati_index = val;
ati18800->index = val;
break;
case 0x1cf:
ati_regs[ati_index] = val;
switch (ati_index)
ati18800->regs[ati18800->index] = val;
switch (ati18800->index)
{
case 0xb2:
case 0xbe:
if (ati_regs[0xbe] & 8) /*Read/write bank mode*/
if (ati18800->regs[0xbe] & 8) /*Read/write bank mode*/
{
svgarbank = ((ati_regs[0xb2] >> 5) & 7) * 0x10000;
svgawbank = ((ati_regs[0xb2] >> 1) & 7) * 0x10000;
svga->read_bank = ((ati18800->regs[0xb2] >> 5) & 7) * 0x10000;
svga->write_bank = ((ati18800->regs[0xb2] >> 1) & 7) * 0x10000;
}
else /*Single bank mode*/
svgarbank = svgawbank = ((ati_regs[0xb2] >> 1) & 7) * 0x10000;
svga->read_bank = svga->write_bank = ((ati18800->regs[0xb2] >> 1) & 7) * 0x10000;
break;
case 0xb3:
ati_eeprom_write(val & 8, val & 2, val & 1);
ati_eeprom_write(&ati18800->eeprom, val & 8, val & 2, val & 1);
break;
}
break;
case 0x3D4:
crtcreg = val & 0x3f;
svga->crtcreg = val & 0x3f;
return;
case 0x3D5:
if (crtcreg <= 7 && crtc[0x11] & 0x80) return;
old=crtc[crtcreg];
crtc[crtcreg]=val;
if (old!=val)
if (svga->crtcreg <= 7 && svga->crtc[0x11] & 0x80) return;
old = svga->crtc[svga->crtcreg];
svga->crtc[svga->crtcreg] = val;
if (old != val)
{
if (crtcreg<0xE || crtcreg>0x10)
if (svga->crtcreg < 0xe || svga->crtcreg > 0x10)
{
fullchange=changeframecount;
svga_recalctimings();
fullchange = changeframecount;
svga_recalctimings(svga);
}
}
break;
}
svga_out(addr, val, NULL);
svga_out(addr, val, svga);
}
uint8_t ati18800_in(uint16_t addr, void *priv)
uint8_t ati18800_in(uint16_t addr, void *p)
{
ati18800_t *ati18800 = (ati18800_t *)p;
svga_t *svga = &ati18800->svga;
uint8_t temp;
if (addr != 0x3da) pclog("ati18800_in : %04X ", addr);
if (((addr&0xFFF0) == 0x3D0 || (addr&0xFFF0) == 0x3B0) && !(svga_miscout&1)) addr ^= 0x60;
if (((addr&0xFFF0) == 0x3D0 || (addr&0xFFF0) == 0x3B0) && !(svga->miscout&1)) addr ^= 0x60;
switch (addr)
{
case 0x1ce:
temp = ati_index;
temp = ati18800->index;
break;
case 0x1cf:
switch (ati_index)
switch (ati18800->index)
{
case 0xb7:
temp = ati_regs[ati_index] & ~8;
if (ati_eeprom_read())
temp = ati18800->regs[ati18800->index] & ~8;
if (ati_eeprom_read(&ati18800->eeprom))
temp |= 8;
break;
default:
temp = ati_regs[ati_index];
temp = ati18800->regs[ati18800->index];
break;
}
break;
case 0x3D4:
temp = crtcreg;
temp = svga->crtcreg;
break;
case 0x3D5:
temp = crtc[crtcreg];
temp = svga->crtc[svga->crtcreg];
break;
default:
temp = svga_in(addr, NULL);
temp = svga_in(addr, svga);
break;
}
if (addr != 0x3da) pclog("%02X %04X:%04X\n", temp, CS,pc);
return temp;
}
int ati18800_init()
void *ati18800_init()
{
svga_recalctimings_ex = NULL;
svga_vram_limit = 1 << 19; /*512kb*/
vrammask = 0x7ffff;
svgawbank = svgarbank = 0;
bpp = 8;
svga_miscout = 1;
ati18800_t *ati18800 = malloc(sizeof(ati18800_t));
memset(ati18800, 0, sizeof(ati18800_t));
io_sethandler(0x01ce, 0x0002, ati18800_in, NULL, NULL, ati18800_out, NULL, NULL, NULL);
ati_eeprom_load("ati18800.nvr", 0);
return svga_init();
svga_init(&ati18800->svga, ati18800, 1 << 19, /*512kb*/
NULL,
ati18800_in, ati18800_out,
NULL);
io_sethandler(0x01ce, 0x0002, ati18800_in, NULL, NULL, ati18800_out, NULL, NULL, ati18800);
io_sethandler(0x03c0, 0x0020, ati18800_in, NULL, NULL, ati18800_out, NULL, NULL, ati18800);
ati18800->svga.miscout = 1;
ati_eeprom_load(&ati18800->eeprom, "ati18800.nvr", 0);
return ati18800;
}
GFXCARD vid_ati18800 =
void ati18800_close(void *p)
{
ati18800_t *ati18800 = (ati18800_t *)p;
svga_close(&ati18800->svga);
free(ati18800);
}
void ati18800_speed_changed(void *p)
{
ati18800_t *ati18800 = (ati18800_t *)p;
svga_recalctimings(&ati18800->svga);
}
device_t ati18800_device =
{
"ATI-18800",
ati18800_init,
/*IO at 3Cx/3Dx*/
ati18800_out,
ati18800_in,
/*IO at 3Ax/3Bx*/
video_out_null,
video_in_null,
svga_poll,
svga_recalctimings,
svga_write,
video_write_null,
video_write_null,
svga_read,
video_read_null,
video_read_null
ati18800_close,
ati18800_speed_changed,
svga_add_status_info
};

1
src/vid_ati18800.h Normal file
View file

@ -0,0 +1 @@
extern device_t ati18800_device;

View file

@ -1,161 +1,183 @@
/*ATI 28800 emulation (VGA Charger)*/
#include <stdlib.h>
#include "ibm.h"
#include "device.h"
#include "io.h"
#include "video.h"
#include "vid_ati28800.h"
#include "vid_ati_eeprom.h"
#include "vid_svga.h"
#include "vid_svga_render.h"
static uint8_t ati_regs[256];
static int ati_index;
void ati28800_out(uint16_t addr, uint8_t val, void *priv)
typedef struct ati28800_t
{
svga_t svga;
ati_eeprom_t eeprom;
uint8_t regs[256];
int index;
} ati28800_t;
void ati28800_out(uint16_t addr, uint8_t val, void *p)
{
ati28800_t *ati28800 = (ati28800_t *)p;
svga_t *svga = &ati28800->svga;
uint8_t old;
pclog("ati28800_out : %04X %02X %04X:%04X\n", addr, val, CS,pc);
if (((addr&0xFFF0) == 0x3D0 || (addr&0xFFF0) == 0x3B0) && !(svga_miscout&1)) addr ^= 0x60;
if (((addr&0xFFF0) == 0x3D0 || (addr&0xFFF0) == 0x3B0) && !(svga->miscout&1))
addr ^= 0x60;
switch (addr)
{
case 0x1ce:
ati_index = val;
ati28800->index = val;
break;
case 0x1cf:
ati_regs[ati_index] = val;
switch (ati_index)
ati28800->regs[ati28800->index] = val;
switch (ati28800->index)
{
case 0xb2:
case 0xbe:
if (ati_regs[0xbe] & 8) /*Read/write bank mode*/
if (ati28800->regs[0xbe] & 8) /*Read/write bank mode*/
{
svgarbank = ((ati_regs[0xb2] >> 5) & 7) * 0x10000;
svgawbank = ((ati_regs[0xb2] >> 1) & 7) * 0x10000;
svga->read_bank = ((ati28800->regs[0xb2] >> 5) & 7) * 0x10000;
svga->write_bank = ((ati28800->regs[0xb2] >> 1) & 7) * 0x10000;
}
else /*Single bank mode*/
svgarbank = svgawbank = ((ati_regs[0xb2] >> 1) & 7) * 0x10000;
svga->read_bank = svga->write_bank = ((ati28800->regs[0xb2] >> 1) & 7) * 0x10000;
break;
case 0xb3:
ati_eeprom_write(val & 8, val & 2, val & 1);
ati_eeprom_write(&ati28800->eeprom, val & 8, val & 2, val & 1);
break;
}
break;
case 0x3D4:
crtcreg = val & 0x3f;
svga->crtcreg = val & 0x3f;
return;
case 0x3D5:
if (crtcreg <= 7 && crtc[0x11] & 0x80) return;
old=crtc[crtcreg];
crtc[crtcreg]=val;
if (old!=val)
if (svga->crtcreg <= 7 && svga->crtc[0x11] & 0x80) return;
old = svga->crtc[svga->crtcreg];
svga->crtc[svga->crtcreg] = val;
if (old != val)
{
if (crtcreg<0xE || crtcreg>0x10)
if (svga->crtcreg < 0xe || svga->crtcreg > 0x10)
{
fullchange=changeframecount;
svga_recalctimings();
fullchange = changeframecount;
svga_recalctimings(svga);
}
}
break;
}
svga_out(addr, val, NULL);
svga_out(addr, val, svga);
}
uint8_t ati28800_in(uint16_t addr, void *priv)
uint8_t ati28800_in(uint16_t addr, void *p)
{
ati28800_t *ati28800 = (ati28800_t *)p;
svga_t *svga = &ati28800->svga;
uint8_t temp;
if (addr != 0x3da) pclog("ati28800_in : %04X ", addr);
if (((addr&0xFFF0) == 0x3D0 || (addr&0xFFF0) == 0x3B0) && !(svga_miscout&1)) addr ^= 0x60;
if (((addr&0xFFF0) == 0x3D0 || (addr&0xFFF0) == 0x3B0) && !(svga->miscout&1)) addr ^= 0x60;
switch (addr)
{
case 0x1ce:
temp = ati_index;
temp = ati28800->index;
break;
case 0x1cf:
switch (ati_index)
switch (ati28800->index)
{
case 0xb7:
temp = ati_regs[ati_index] & ~8;
if (ati_eeprom_read())
temp = ati28800->regs[ati28800->index] & ~8;
if (ati_eeprom_read(&ati28800->eeprom))
temp |= 8;
break;
default:
temp = ati_regs[ati_index];
temp = ati28800->regs[ati28800->index];
break;
}
break;
case 0x3c2:
if ((vgapal[0].r + vgapal[0].g + vgapal[0].b) >= 0x50)
if ((svga->vgapal[0].r + svga->vgapal[0].g + svga->vgapal[0].b) >= 0x50)
temp = 0;
else
temp = 0x10;
break;
case 0x3D4:
temp = crtcreg;
temp = svga->crtcreg;
break;
case 0x3D5:
temp = crtc[crtcreg];
temp = svga->crtc[svga->crtcreg];
break;
default:
temp = svga_in(addr, NULL);
temp = svga_in(addr, svga);
break;
}
if (addr != 0x3da) pclog("%02X %04X:%04X\n", temp, CS,pc);
return temp;
}
void ati28800_recalctimings()
void ati28800_recalctimings(svga_t *svga)
{
ati28800_t *ati28800 = (ati28800_t *)svga->p;
pclog("ati28800_recalctimings\n");
if (!scrblank && (ati_regs[0xb0] & 0x20)) /*Extended 256 colour modes*/
if (!svga->scrblank && (ati28800->regs[0xb0] & 0x20)) /*Extended 256 colour modes*/
{
pclog("8bpp_highres\n");
svga_render = svga_render_8bpp_highres;
svga_rowoffset <<= 1;
svga_ma <<= 1;
svga->render = svga_render_8bpp_highres;
svga->rowoffset <<= 1;
svga->ma <<= 1;
}
}
int ati28800_init()
void *ati28800_init()
{
svga_recalctimings_ex = ati28800_recalctimings;
svga_vram_limit = 1 << 19; /*512kb*/
vrammask = 0x7ffff;
svgawbank = svgarbank = 0;
bpp = 8;
svga_miscout = 1;
ati28800_t *ati28800 = malloc(sizeof(ati28800_t));
memset(ati28800, 0, sizeof(ati28800_t));
io_sethandler(0x01ce, 0x0002, ati28800_in, NULL, NULL, ati28800_out, NULL, NULL, NULL);
ati_eeprom_load("ati28800.nvr", 0);
return svga_init();
svga_init(&ati28800->svga, ati28800, 1 << 19, /*512kb*/
ati28800_recalctimings,
ati28800_in, ati28800_out,
NULL);
io_sethandler(0x01ce, 0x0002, ati28800_in, NULL, NULL, ati28800_out, NULL, NULL, ati28800);
io_sethandler(0x03c0, 0x0020, ati28800_in, NULL, NULL, ati28800_out, NULL, NULL, ati28800);
ati28800->svga.miscout = 1;
ati_eeprom_load(&ati28800->eeprom, "ati28800.nvr", 0);
return ati28800;
}
GFXCARD vid_ati28800 =
void ati28800_close(void *p)
{
ati28800_t *ati28800 = (ati28800_t *)p;
svga_close(&ati28800->svga);
free(ati28800);
}
void ati28800_speed_changed(void *p)
{
ati28800_t *ati28800 = (ati28800_t *)p;
svga_recalctimings(&ati28800->svga);
}
device_t ati28800_device =
{
"ATI-28800",
ati28800_init,
/*IO at 3Cx/3Dx*/
ati28800_out,
ati28800_in,
/*IO at 3Ax/3Bx*/
video_out_null,
video_in_null,
svga_poll,
svga_recalctimings,
svga_write,
video_write_null,
video_write_null,
svga_read,
video_read_null,
video_read_null
ati28800_close,
ati28800_speed_changed,
svga_add_status_info
};

1
src/vid_ati28800.h Normal file
View file

@ -0,0 +1 @@
extern device_t ati28800_device;

View file

@ -23,46 +23,45 @@ bit 0 Controls 6/8bit DAC. 0: 8bit DAC/LUT, 1: 6bit DAC/LUT
#include "vid_svga.h"
#include "vid_ati68860_ramdac.h"
static uint8_t ramdac_regs[16];
void ati68860_ramdac_out(uint16_t addr, uint8_t val, void *priv)
void ati68860_ramdac_out(uint16_t addr, uint8_t val, ati68860_ramdac_t *ramdac, svga_t *svga)
{
// pclog("ati68860_out : addr %04X val %02X %04X:%04X\n", addr, val, CS,pc);
switch (addr)
{
case 0:
svga_out(0x3c8, val, NULL);
svga_out(0x3c8, val, svga);
break;
case 1:
svga_out(0x3c9, val, NULL);
svga_out(0x3c9, val, svga);
break;
case 2:
svga_out(0x3c6, val, NULL);
svga_out(0x3c6, val, svga);
break;
case 3:
svga_out(0x3c7, val, NULL);
svga_out(0x3c7, val, svga);
break;
default:
ramdac_regs[addr & 0xf] = val;
ramdac->regs[addr & 0xf] = val;
break;
}
}
uint8_t ati68860_ramdac_in(uint16_t addr, void *priv)
uint8_t ati68860_ramdac_in(uint16_t addr, ati68860_ramdac_t *ramdac, svga_t *svga)
{
uint8_t ret = 0;
switch (addr)
{
case 0:
ret = svga_in(0x3c8, NULL);
ret = svga_in(0x3c8, svga);
break;
case 1:
ret = svga_in(0x3c9, NULL);
ret = svga_in(0x3c9, svga);
break;
case 2:
ret = svga_in(0x3c6, NULL);
ret = svga_in(0x3c6, svga);
break;
case 3:
ret = svga_in(0x3c7, NULL);
ret = svga_in(0x3c7, svga);
break;
case 4: case 8:
ret = 2;
@ -75,7 +74,7 @@ uint8_t ati68860_ramdac_in(uint16_t addr, void *priv)
break;
default:
ret = ramdac_regs[addr & 0xf];
ret = ramdac->regs[addr & 0xf];
break;
}
// pclog("ati68860_in : addr %04X ret %02X %04X:%04X\n", addr, ret, CS,pc);

View file

@ -1,2 +1,7 @@
void ati68860_ramdac_out(uint16_t addr, uint8_t val, void *priv);
uint8_t ati68860_ramdac_in(uint16_t addr, void *priv);
typedef struct ati68860_ramdac_t
{
uint8_t regs[16];
} ati68860_ramdac_t;
void ati68860_ramdac_out(uint16_t addr, uint8_t val, ati68860_ramdac_t *ramdac, svga_t *svga);
uint8_t ati68860_ramdac_in(uint16_t addr, ati68860_ramdac_t *ramdac, svga_t *svga);

View file

@ -1,7 +1,6 @@
#include "ibm.h"
#include "vid_ati_eeprom.h"
static uint16_t eeprom[256];
enum
{
EEPROM_IDLE,
@ -29,201 +28,193 @@ enum
EEPROM_OP_EWEN = 3
};
static int oldclk, oldena;
static int eeprom_opcode, eeprom_state, eeprom_count, eeprom_out;
static int eeprom_wp;
static uint32_t eeprom_dat;
static int eeprom_type;
static char eeprom_fn[256] = {0};
void ati_eeprom_load(char *fn, int type)
void ati_eeprom_load(ati_eeprom_t *eeprom, char *fn, int type)
{
FILE *f;
eeprom_type = type;
strcpy(eeprom_fn, fn);
f = romfopen(eeprom_fn, "rb");
eeprom->type = type;
strcpy(eeprom->fn, fn);
f = romfopen(eeprom->fn, "rb");
if (!f)
{
memset(eeprom, 0, type ? 512 : 128);
memset(eeprom->data, 0, eeprom->type ? 512 : 128);
return;
}
fread(eeprom, 1, type ? 512 : 128, f);
fread(eeprom->data, 1, eeprom->type ? 512 : 128, f);
fclose(f);
}
void ati_eeprom_save()
void ati_eeprom_save(ati_eeprom_t *eeprom)
{
FILE *f = romfopen(eeprom_fn, "wb");
FILE *f = romfopen(eeprom->fn, "wb");
if (!f) return;
fwrite(eeprom, 1, eeprom_type ? 512 : 128, f);
fwrite(eeprom->data, 1, eeprom->type ? 512 : 128, f);
fclose(f);
}
void ati_eeprom_write(int ena, int clk, int dat)
void ati_eeprom_write(ati_eeprom_t *eeprom, int ena, int clk, int dat)
{
int c;
pclog("EEPROM write %i %i %i\n", ena, clk, dat);
if (!ena)
{
eeprom_out = 1;
eeprom->out = 1;
}
if (clk && !oldclk)
if (clk && !eeprom->oldclk)
{
if (ena && !oldena)
if (ena && !eeprom->oldena)
{
eeprom_state = EEPROM_WAIT;
eeprom_opcode = 0;
eeprom_count = 3;
eeprom_out = 1;
eeprom->state = EEPROM_WAIT;
eeprom->opcode = 0;
eeprom->count = 3;
eeprom->out = 1;
}
else if (ena)
{
pclog("EEPROM receive %i %i %i\n", ena, clk, dat);
switch (eeprom_state)
switch (eeprom->state)
{
case EEPROM_WAIT:
if (!dat)
break;
eeprom_state = EEPROM_OPCODE;
eeprom->state = EEPROM_OPCODE;
/* fall through */
case EEPROM_OPCODE:
eeprom_opcode = (eeprom_opcode << 1) | (dat ? 1 : 0);
eeprom_count--;
if (!eeprom_count)
eeprom->opcode = (eeprom->opcode << 1) | (dat ? 1 : 0);
eeprom->count--;
if (!eeprom->count)
{
pclog("EEPROM opcode - %i\n", eeprom_opcode);
switch (eeprom_opcode)
pclog("EEPROM opcode - %i\n", eeprom->opcode);
switch (eeprom->opcode)
{
case EEPROM_OP_WRITE:
eeprom_count = eeprom_type ? 24 : 22;
eeprom_state = EEPROM_INPUT;
eeprom_dat = 0;
eeprom->count = eeprom->type ? 24 : 22;
eeprom->state = EEPROM_INPUT;
eeprom->dat = 0;
break;
case EEPROM_OP_READ:
eeprom_count = eeprom_type ? 8 : 6;
eeprom_state = EEPROM_INPUT;
eeprom_dat = 0;
eeprom->count = eeprom->type ? 8 : 6;
eeprom->state = EEPROM_INPUT;
eeprom->dat = 0;
break;
case EEPROM_OP_EW:
eeprom_count = 2;
eeprom_state = EEPROM_INPUT;
eeprom_dat = 0;
eeprom->count = 2;
eeprom->state = EEPROM_INPUT;
eeprom->dat = 0;
break;
case EEPROM_OP_ERASE:
eeprom_count = eeprom_type ? 8 : 6;
eeprom_state = EEPROM_INPUT;
eeprom_dat = 0;
eeprom->count = eeprom->type ? 8 : 6;
eeprom->state = EEPROM_INPUT;
eeprom->dat = 0;
break;
}
}
break;
case EEPROM_INPUT:
eeprom_dat = (eeprom_dat << 1) | (dat ? 1 : 0);
eeprom_count--;
if (!eeprom_count)
eeprom->dat = (eeprom->dat << 1) | (dat ? 1 : 0);
eeprom->count--;
if (!eeprom->count)
{
pclog("EEPROM dat - %02X\n", eeprom_dat);
switch (eeprom_opcode)
pclog("EEPROM dat - %02X\n", eeprom->dat);
switch (eeprom->opcode)
{
case EEPROM_OP_WRITE:
pclog("EEPROM_OP_WRITE addr %02X eeprom_dat %04X\n", (eeprom_dat >> 16) & (eeprom_type ? 255 : 63), eeprom_dat & 0xffff);
if (!eeprom_wp)
pclog("EEPROM_OP_WRITE addr %02X eeprom_dat %04X\n", (eeprom->dat >> 16) & (eeprom->type ? 255 : 63), eeprom->dat & 0xffff);
if (!eeprom->wp)
{
eeprom[(eeprom_dat >> 16) & (eeprom_type ? 255 : 63)] = eeprom_dat & 0xffff;
ati_eeprom_save();
eeprom->data[(eeprom->dat >> 16) & (eeprom->type ? 255 : 63)] = eeprom->dat & 0xffff;
ati_eeprom_save(eeprom);
}
eeprom_state = EEPROM_IDLE;
eeprom_out = 1;
eeprom->state = EEPROM_IDLE;
eeprom->out = 1;
break;
case EEPROM_OP_READ:
eeprom_count = 17;
eeprom_state = EEPROM_OUTPUT;
eeprom_dat = eeprom[eeprom_dat];
pclog("Trigger EEPROM_OUTPUT %04X\n", eeprom_dat);
eeprom->count = 17;
eeprom->state = EEPROM_OUTPUT;
eeprom->dat = eeprom->data[eeprom->dat];
pclog("Trigger EEPROM_OUTPUT %04X\n", eeprom->dat);
break;
case EEPROM_OP_EW:
pclog("EEPROM_OP_EW %i\n", eeprom_dat);
switch (eeprom_dat)
pclog("EEPROM_OP_EW %i\n", eeprom->dat);
switch (eeprom->dat)
{
case EEPROM_OP_EWDS:
eeprom_wp = 1;
eeprom->wp = 1;
break;
case EEPROM_OP_WRAL:
opcode = EEPROM_OP_WRALMAIN;
eeprom_count = 20;
eeprom->opcode = EEPROM_OP_WRALMAIN;
eeprom->count = 20;
break;
case EEPROM_OP_ERAL:
if (!eeprom_wp)
if (!eeprom->wp)
{
memset(eeprom, 0xff, 128);
ati_eeprom_save();
memset(eeprom->data, 0xff, 128);
ati_eeprom_save(eeprom);
}
break;
case EEPROM_OP_EWEN:
eeprom_wp = 0;
eeprom->wp = 0;
break;
}
eeprom_state = EEPROM_IDLE;
eeprom_out = 1;
eeprom->state = EEPROM_IDLE;
eeprom->out = 1;
break;
case EEPROM_OP_ERASE:
pclog("EEPROM_OP_ERASE %i\n", eeprom_dat);
if (!eeprom_wp)
pclog("EEPROM_OP_ERASE %i\n", eeprom->dat);
if (!eeprom->wp)
{
eeprom[eeprom_dat] = 0xffff;
ati_eeprom_save();
eeprom->data[eeprom->dat] = 0xffff;
ati_eeprom_save(eeprom);
}
eeprom_state = EEPROM_IDLE;
eeprom_out = 1;
eeprom->state = EEPROM_IDLE;
eeprom->out = 1;
break;
case EEPROM_OP_WRALMAIN:
pclog("EEPROM_OP_WRAL %04X\n", eeprom_dat);
if (!eeprom_wp)
pclog("EEPROM_OP_WRAL %04X\n", eeprom->dat);
if (!eeprom->wp)
{
for (c = 0; c < 256; c++)
eeprom[c] = eeprom_dat;
ati_eeprom_save();
eeprom->data[c] = eeprom->dat;
ati_eeprom_save(eeprom);
}
eeprom_state = EEPROM_IDLE;
eeprom_out = 1;
eeprom->state = EEPROM_IDLE;
eeprom->out = 1;
break;
}
}
break;
}
}
oldena = ena;
eeprom->oldena = ena;
}
else if (!clk && oldclk)
else if (!clk && eeprom->oldclk)
{
if (ena)
{
switch (eeprom_state)
switch (eeprom->state)
{
case EEPROM_OUTPUT:
eeprom_out = (eeprom_dat & 0x10000) ? 1 : 0;
eeprom_dat <<= 1;
pclog("EEPROM_OUTPUT - data %i\n", eeprom_out);
eeprom_count--;
if (!eeprom_count)
eeprom->out = (eeprom->dat & 0x10000) ? 1 : 0;
eeprom->dat <<= 1;
pclog("EEPROM_OUTPUT - data %i\n", eeprom->out);
eeprom->count--;
if (!eeprom->count)
{
pclog("EEPROM_OUTPUT complete\n");
eeprom_state = EEPROM_IDLE;
eeprom->state = EEPROM_IDLE;
}
break;
}
}
}
oldclk = clk;
eeprom->oldclk = clk;
}
int ati_eeprom_read()
int ati_eeprom_read(ati_eeprom_t *eeprom)
{
return eeprom_out;
return eeprom->out;
}

View file

@ -1,3 +1,16 @@
void ati_eeprom_load(char *fn, int type);
void ati_eeprom_write(int ena, int clk, int dat);
int ati_eeprom_read();
typedef struct ati_eeprom_t
{
uint16_t data[256];
int oldclk, oldena;
int opcode, state, count, out;
int wp;
uint32_t dat;
int type;
char fn[256];
} ati_eeprom_t;
void ati_eeprom_load(ati_eeprom_t *eeprom, char *fn, int type);
void ati_eeprom_write(ati_eeprom_t *eeprom, int ena, int clk, int dat);
int ati_eeprom_read(ati_eeprom_t *eeprom);

File diff suppressed because it is too large Load diff

1
src/vid_ati_mach64.h Normal file
View file

@ -0,0 +1 @@
extern device_t mach64gx_device;

View file

@ -1,110 +1,115 @@
/*CGA emulation*/
#include <stdlib.h>
#include <math.h>
#include "ibm.h"
#include "device.h"
#include "io.h"
#include "mem.h"
#include "timer.h"
#include "video.h"
#include "vid_cga.h"
void cga_recalctimings();
static int i_filt[8],q_filt[8];
void cga_out(uint16_t addr, uint8_t val, void *priv)
static uint8_t crtcmask[32] =
{
0xff, 0xff, 0xff, 0xff, 0x7f, 0x1f, 0x7f, 0x7f, 0xf3, 0x1f, 0x7f, 0x1f, 0x3f, 0xff, 0x3f, 0xff,
0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
void cga_recalctimings(cga_t *cga);
void cga_out(uint16_t addr, uint8_t val, void *p)
{
cga_t *cga = (cga_t *)p;
uint8_t old;
// pclog("CGA_OUT %04X %02X\n", addr, val);
switch (addr)
{
case 0x3D4:
crtcreg=val&31;
cga->crtcreg = val & 31;
return;
case 0x3D5:
old=crtc[crtcreg];
crtc[crtcreg]=val&crtcmask[crtcreg];
if (old!=val)
old = cga->crtc[cga->crtcreg];
cga->crtc[cga->crtcreg] = val & crtcmask[cga->crtcreg];
if (old != val)
{
if (crtcreg<0xE || crtcreg>0x10)
if (cga->crtcreg < 0xe || cga->crtcreg > 0x10)
{
fullchange=changeframecount;
cga_recalctimings();
fullchange = changeframecount;
cga_recalctimings(cga);
}
}
return;
case 0x3D8:
cgamode=val;
cga->cgamode = val;
return;
case 0x3D9:
cgacol=val;
cga->cgacol = val;
return;
}
}
uint8_t cga_in(uint16_t addr, void *priv)
uint8_t cga_in(uint16_t addr, void *p)
{
cga_t *cga = (cga_t *)p;
// pclog("CGA_IN %04X\n", addr);
switch (addr)
{
case 0x3D4:
return crtcreg;
return cga->crtcreg;
case 0x3D5:
return crtc[crtcreg];
return cga->crtc[cga->crtcreg];
case 0x3DA:
return cgastat;
return cga->cgastat;
}
return 0xFF;
}
extern uint8_t charbuffer[256];
void cga_write(uint32_t addr, uint8_t val, void *priv)
void cga_write(uint32_t addr, uint8_t val, void *p)
{
cga_t *cga = (cga_t *)p;
// pclog("CGA_WRITE %04X %02X\n", addr, val);
vram[addr&0x3FFF]=val;
charbuffer[ ((int)(((dispontime - vidtime) * 2) / CGACONST)) & 0xfc] = val;
charbuffer[(((int)(((dispontime - vidtime) * 2) / CGACONST)) & 0xfc) | 1] = val;
cga->vram[addr & 0x3fff] = val;
cga->charbuffer[ ((int)(((cga->dispontime - cga->vidtime) * 2) / CGACONST)) & 0xfc] = val;
cga->charbuffer[(((int)(((cga->dispontime - cga->vidtime) * 2) / CGACONST)) & 0xfc) | 1] = val;
cycles -= 4;
}
uint8_t cga_read(uint32_t addr, void *priv)
uint8_t cga_read(uint32_t addr, void *p)
{
cga_t *cga = (cga_t *)p;
cycles -= 4;
charbuffer[ ((int)(((dispontime - vidtime) * 2) / CGACONST)) & 0xfc] = vram[addr&0x3FFF];
charbuffer[(((int)(((dispontime - vidtime) * 2) / CGACONST)) & 0xfc) | 1] = vram[addr&0x3FFF];
cga->charbuffer[ ((int)(((cga->dispontime - cga->vidtime) * 2) / CGACONST)) & 0xfc] = cga->vram[addr & 0x3fff];
cga->charbuffer[(((int)(((cga->dispontime - cga->vidtime) * 2) / CGACONST)) & 0xfc) | 1] = cga->vram[addr & 0x3fff];
// pclog("CGA_READ %04X\n", addr);
return vram[addr&0x3FFF];
return cga->vram[addr & 0x3fff];
}
void cga_recalctimings()
void cga_recalctimings(cga_t *cga)
{
double disptime;
double _dispontime, _dispofftime;
pclog("Recalc - %i %i %i\n", crtc[0], crtc[1], cgamode & 1);
if (cgamode&1)
pclog("Recalc - %i %i %i\n", cga->crtc[0], cga->crtc[1], cga->cgamode & 1);
if (cga->cgamode & 1)
{
disptime=crtc[0]+1;
_dispontime=crtc[1];
disptime = cga->crtc[0] + 1;
_dispontime = cga->crtc[1];
}
else
{
disptime=(crtc[0]+1)<<1;
_dispontime=crtc[1]<<1;
disptime = (cga->crtc[0] + 1) << 1;
_dispontime = cga->crtc[1] << 1;
}
_dispofftime=disptime-_dispontime;
_dispofftime = disptime - _dispontime;
// printf("%i %f %f %f %i %i\n",cgamode&1,disptime,dispontime,dispofftime,crtc[0],crtc[1]);
_dispontime*=CGACONST;
_dispofftime*=CGACONST;
_dispontime *= CGACONST;
_dispofftime *= CGACONST;
// printf("Timings - on %f off %f frame %f second %f\n",dispontime,dispofftime,(dispontime+dispofftime)*262.0,(dispontime+dispofftime)*262.0*59.92);
dispontime = (int)(_dispontime * (1 << TIMER_SHIFT));
dispofftime = (int)(_dispofftime * (1 << TIMER_SHIFT));
cga->dispontime = (int)(_dispontime * (1 << TIMER_SHIFT));
cga->dispofftime = (int)(_dispofftime * (1 << TIMER_SHIFT));
}
static int linepos,displine;
static int sc,vc;
static int cgadispon;
static int con,coff,cursoron,cgablink;
static int vsynctime,vadj;
static uint16_t ma,maback;
static int oddeven = 0;
static int ntsc_col[8][8]=
{
{0,0,0,0,0,0,0,0}, /*Black*/
@ -117,326 +122,331 @@ static int ntsc_col[8][8]=
{1,1,1,1,1,1,1,1} /*White*/
};
int i_filt[8],q_filt[8];
void cga_poll()
void cga_poll(void *p)
{
uint16_t ca=(crtc[15]|(crtc[14]<<8))&0x3FFF;
cga_t *cga = (cga_t *)p;
uint16_t ca = (cga->crtc[15] | (cga->crtc[14] << 8)) & 0x3fff;
int drawcursor;
int x,c;
int x, c;
int oldvc;
uint8_t chr,attr;
uint8_t chr, attr;
uint16_t dat;
int cols[4];
int col;
int oldsc;
int y_buf[8]={0,0,0,0,0,0,0,0},y_val,y_tot;
int i_buf[8]={0,0,0,0,0,0,0,0},i_val,i_tot;
int q_buf[8]={0,0,0,0,0,0,0,0},q_val,q_tot;
int r,g,b;
if (!linepos)
int y_buf[8] = {0, 0, 0, 0, 0, 0, 0, 0}, y_val, y_tot;
int i_buf[8] = {0, 0, 0, 0, 0, 0, 0, 0}, i_val, i_tot;
int q_buf[8] = {0, 0, 0, 0, 0, 0, 0, 0}, q_val, q_tot;
int r, g, b;
if (!cga->linepos)
{
vidtime+=dispofftime;
cgastat|=1;
linepos=1;
oldsc=sc;
if ((crtc[8] & 3) == 3)
sc = ((sc << 1) + oddeven) & 7;
if (cgadispon)
cga->vidtime += cga->dispofftime;
cga->cgastat |= 1;
cga->linepos = 1;
oldsc = cga->sc;
if ((cga->crtc[8] & 3) == 3)
cga->sc = ((cga->sc << 1) + cga->oddeven) & 7;
if (cga->cgadispon)
{
if (displine<firstline)
if (cga->displine < cga->firstline)
{
firstline=displine;
cga->firstline = cga->displine;
// printf("Firstline %i\n",firstline);
}
lastline=displine;
for (c=0;c<8;c++)
cga->lastline = cga->displine;
for (c = 0; c < 8; c++)
{
if ((cgamode&0x12)==0x12)
if ((cga->cgamode & 0x12) == 0x12)
{
buffer->line[displine][c]=0;
if (cgamode&1) buffer->line[displine][c+(crtc[1]<<3)+8]=0;
else buffer->line[displine][c+(crtc[1]<<4)+8]=0;
buffer->line[cga->displine][c] = 0;
if (cga->cgamode & 1) buffer->line[cga->displine][c + (cga->crtc[1] << 3) + 8] = 0;
else buffer->line[cga->displine][c + (cga->crtc[1] << 4) + 8] = 0;
}
else
{
buffer->line[displine][c]=(cgacol&15)+16;
if (cgamode&1) buffer->line[displine][c+(crtc[1]<<3)+8]=(cgacol&15)+16;
else buffer->line[displine][c+(crtc[1]<<4)+8]=(cgacol&15)+16;
buffer->line[cga->displine][c] = (cga->cgacol & 15) + 16;
if (cga->cgamode & 1) buffer->line[cga->displine][c + (cga->crtc[1] << 3) + 8] = (cga->cgacol & 15) + 16;
else buffer->line[cga->displine][c + (cga->crtc[1] << 4) + 8] = (cga->cgacol & 15) + 16;
}
}
if (cgamode&1)
if (cga->cgamode & 1)
{
for (x=0;x<crtc[1];x++)
for (x = 0; x < cga->crtc[1]; x++)
{
chr=charbuffer[x<<1];
attr=charbuffer[(x<<1)+1];
drawcursor=((ma==ca) && con && cursoron);
if (cgamode&0x20)
chr = cga->charbuffer[x << 1];
attr = cga->charbuffer[(x << 1) + 1];
drawcursor = ((cga->ma == ca) && cga->con && cga->cursoron);
if (cga->cgamode & 0x20)
{
cols[1]=(attr&15)+16;
cols[0]=((attr>>4)&7)+16;
if ((cgablink&8) && (attr&0x80) && !drawcursor) cols[1]=cols[0];
cols[1] = (attr & 15) + 16;
cols[0] = ((attr >> 4) & 7) + 16;
if ((cga->cgablink & 8) && (attr & 0x80) && !cga->drawcursor)
cols[1] = cols[0];
}
else
{
cols[1]=(attr&15)+16;
cols[0]=(attr>>4)+16;
cols[1] = (attr & 15) + 16;
cols[0] = (attr >> 4) + 16;
}
if (drawcursor)
{
for (c=0;c<8;c++)
buffer->line[displine][(x<<3)+c+8]=cols[(fontdat[chr][sc&7]&(1<<(c^7)))?1:0]^15;
for (c = 0; c < 8; c++)
buffer->line[cga->displine][(x << 3) + c + 8] = cols[(fontdat[chr][cga->sc & 7] & (1 << (c ^ 7))) ? 1 : 0] ^ 15;
}
else
{
for (c=0;c<8;c++)
buffer->line[displine][(x<<3)+c+8]=cols[(fontdat[chr][sc&7]&(1<<(c^7)))?1:0];
for (c = 0; c < 8; c++)
buffer->line[cga->displine][(x << 3) + c + 8] = cols[(fontdat[chr][cga->sc & 7] & (1 << (c ^ 7))) ? 1 : 0];
}
ma++;
cga->ma++;
}
}
else if (!(cgamode&2))
else if (!(cga->cgamode & 2))
{
for (x=0;x<crtc[1];x++)
for (x = 0; x < cga->crtc[1]; x++)
{
chr=vram[((ma<<1)&0x3FFF)];
attr=vram[(((ma<<1)+1)&0x3FFF)];
drawcursor=((ma==ca) && con && cursoron);
if (cgamode&0x20)
chr = cga->vram[((cga->ma << 1) & 0x3fff)];
attr = cga->vram[(((cga->ma << 1) + 1) & 0x3fff)];
drawcursor = ((cga->ma == ca) && cga->con && cga->cursoron);
if (cga->cgamode & 0x20)
{
cols[1]=(attr&15)+16;
cols[0]=((attr>>4)&7)+16;
if ((cgablink&8) && (attr&0x80)) cols[1]=cols[0];
cols[1] = (attr & 15) + 16;
cols[0] = ((attr >> 4) & 7) + 16;
if ((cga->cgablink & 8) && (attr & 0x80)) cols[1] = cols[0];
}
else
{
cols[1]=(attr&15)+16;
cols[0]=(attr>>4)+16;
cols[1] = (attr & 15) + 16;
cols[0] = (attr >> 4) + 16;
}
ma++;
cga->ma++;
if (drawcursor)
{
for (c=0;c<8;c++)
buffer->line[displine][(x<<4)+(c<<1)+8]=buffer->line[displine][(x<<4)+(c<<1)+1+8]=cols[(fontdat[chr][sc&7]&(1<<(c^7)))?1:0]^15;
for (c = 0; c < 8; c++)
buffer->line[cga->displine][(x << 4)+(c << 1) + 8] = buffer->line[cga->displine][(x << 4) + (c << 1) + 1 + 8] = cols[(fontdat[chr][cga->sc & 7] & (1 << (c ^ 7))) ? 1 : 0] ^ 15;
}
else
{
for (c=0;c<8;c++)
buffer->line[displine][(x<<4)+(c<<1)+8]=buffer->line[displine][(x<<4)+(c<<1)+1+8]=cols[(fontdat[chr][sc&7]&(1<<(c^7)))?1:0];
for (c = 0; c < 8; c++)
buffer->line[cga->displine][(x << 4) + (c << 1) + 8] = buffer->line[cga->displine][(x << 4) + (c << 1) + 1 + 8] = cols[(fontdat[chr][cga->sc & 7] & (1 << (c ^ 7))) ? 1 : 0];
}
}
}
else if (!(cgamode&16))
else if (!(cga->cgamode & 16))
{
cols[0]=(cgacol&15)|16;
col=(cgacol&16)?24:16;
if (cgamode&4)
cols[0] = (cga->cgacol & 15) | 16;
col = (cga->cgacol & 16) ? 24 : 16;
if (cga->cgamode & 4)
{
cols[1]=col|3;
cols[2]=col|4;
cols[3]=col|7;
cols[1] = col | 3;
cols[2] = col | 4;
cols[3] = col | 7;
}
else if (cgacol&32)
else if (cga->cgacol & 32)
{
cols[1]=col|3;
cols[2]=col|5;
cols[3]=col|7;
cols[1] = col | 3;
cols[2] = col | 5;
cols[3] = col | 7;
}
else
{
cols[1]=col|2;
cols[2]=col|4;
cols[3]=col|6;
cols[1] = col | 2;
cols[2] = col | 4;
cols[3] = col | 6;
}
for (x=0;x<crtc[1];x++)
for (x = 0; x < cga->crtc[1]; x++)
{
dat=(vram[((ma<<1)&0x1FFF)+((sc&1)*0x2000)]<<8)|vram[((ma<<1)&0x1FFF)+((sc&1)*0x2000)+1];
ma++;
for (c=0;c<8;c++)
dat = (cga->vram[((cga->ma << 1) & 0x1fff) + ((cga->sc & 1) * 0x2000)] << 8) | cga->vram[((cga->ma << 1) & 0x1fff) + ((cga->sc & 1) * 0x2000) + 1];
cga->ma++;
for (c = 0; c < 8; c++)
{
buffer->line[displine][(x<<4)+(c<<1)+8]=
buffer->line[displine][(x<<4)+(c<<1)+1+8]=cols[dat>>14];
dat<<=2;
buffer->line[cga->displine][(x << 4) + (c << 1) + 8] =
buffer->line[cga->displine][(x << 4) + (c << 1) + 1 + 8] = cols[dat >> 14];
dat <<= 2;
}
}
}
else
{
cols[0]=0; cols[1]=(cgacol&15)+16;
for (x=0;x<crtc[1];x++)
cols[0] = 0; cols[1] = (cga->cgacol & 15) + 16;
for (x = 0; x < cga->crtc[1]; x++)
{
dat=(vram[((ma<<1)&0x1FFF)+((sc&1)*0x2000)]<<8)|vram[((ma<<1)&0x1FFF)+((sc&1)*0x2000)+1];
ma++;
for (c=0;c<16;c++)
dat = (cga->vram[((cga->ma << 1) & 0x1fff) + ((cga->sc & 1) * 0x2000)] << 8) | cga->vram[((cga->ma << 1) & 0x1fff) + ((cga->sc & 1) * 0x2000) + 1];
cga->ma++;
for (c = 0; c < 16; c++)
{
buffer->line[displine][(x<<4)+c+8]=cols[dat>>15];
dat<<=1;
buffer->line[cga->displine][(x << 4) + c + 8] = cols[dat >> 15];
dat <<= 1;
}
}
}
}
else
{
cols[0]=((cgamode&0x12)==0x12)?0:(cgacol&15)+16;
if (cgamode&1) hline(buffer,0,displine,(crtc[1]<<3)+16,cols[0]);
else hline(buffer,0,displine,(crtc[1]<<4)+16,cols[0]);
cols[0] = ((cga->cgamode & 0x12) == 0x12) ? 0 : (cga->cgacol & 15) + 16;
if (cga->cgamode & 1) hline(buffer, 0, cga->displine, (cga->crtc[1] << 3) + 16, cols[0]);
else hline(buffer, 0, cga->displine, (cga->crtc[1] << 4) + 16, cols[0]);
}
if (cgamode&1) x=(crtc[1]<<3)+16;
else x=(crtc[1]<<4)+16;
if (cga->cgamode & 1) x = (cga->crtc[1] << 3) + 16;
else x = (cga->crtc[1] << 4) + 16;
if (cga_comp)
{
for (c=0;c<x;c++)
for (c = 0; c < x; c++)
{
y_buf[(c<<1)&6]=ntsc_col[buffer->line[displine][c]&7][(c<<1)&6]?0x6000:0;
y_buf[(c<<1)&6]+=(buffer->line[displine][c]&8)?0x3000:0;
i_buf[(c<<1)&6]=y_buf[(c<<1)&6]*i_filt[(c<<1)&6];
q_buf[(c<<1)&6]=y_buf[(c<<1)&6]*q_filt[(c<<1)&6];
y_tot=y_buf[0]+y_buf[1]+y_buf[2]+y_buf[3]+y_buf[4]+y_buf[5]+y_buf[6]+y_buf[7];
i_tot=i_buf[0]+i_buf[1]+i_buf[2]+i_buf[3]+i_buf[4]+i_buf[5]+i_buf[6]+i_buf[7];
q_tot=q_buf[0]+q_buf[1]+q_buf[2]+q_buf[3]+q_buf[4]+q_buf[5]+q_buf[6]+q_buf[7];
y_buf[(c << 1) & 6] = ntsc_col[buffer->line[cga->displine][c] & 7][(c << 1) & 6] ? 0x6000 : 0;
y_buf[(c << 1) & 6] += (buffer->line[cga->displine][c] & 8) ? 0x3000 : 0;
i_buf[(c << 1) & 6] = y_buf[(c << 1) & 6] * i_filt[(c << 1) & 6];
q_buf[(c << 1) & 6] = y_buf[(c << 1) & 6] * q_filt[(c << 1) & 6];
y_tot = y_buf[0] + y_buf[1] + y_buf[2] + y_buf[3] + y_buf[4] + y_buf[5] + y_buf[6] + y_buf[7];
i_tot = i_buf[0] + i_buf[1] + i_buf[2] + i_buf[3] + i_buf[4] + i_buf[5] + i_buf[6] + i_buf[7];
q_tot = q_buf[0] + q_buf[1] + q_buf[2] + q_buf[3] + q_buf[4] + q_buf[5] + q_buf[6] + q_buf[7];
y_val=y_tot>>10;
if (y_val>255) y_val=255;
y_val<<=16;
i_val=i_tot>>12;
if (i_val>39041) i_val=39041;
if (i_val<-39041) i_val=-39041;
q_val=q_tot>>12;
if (q_val>34249) q_val=34249;
if (q_val<-34249) q_val=-34249;
y_val = y_tot >> 10;
if (y_val > 255) y_val = 255;
y_val <<= 16;
i_val = i_tot >> 12;
if (i_val > 39041) i_val = 39041;
if (i_val < -39041) i_val = -39041;
q_val = q_tot >> 12;
if (q_val > 34249) q_val = 34249;
if (q_val < -34249) q_val = -34249;
r=(y_val+249*i_val+159*q_val)>>16;
g=(y_val-70*i_val-166*q_val)>>16;
b=(y_val-283*i_val+436*q_val)>>16;
r = (y_val + 249*i_val + 159*q_val) >> 16;
g = (y_val - 70*i_val - 166*q_val) >> 16;
b = (y_val - 283*i_val + 436*q_val) >> 16;
y_buf[((c<<1)&6)+1]=ntsc_col[buffer->line[displine][c]&7][((c<<1)&6)+1]?0x6000:0;
y_buf[((c<<1)&6)+1]+=(buffer->line[displine][c]&8)?0x3000:0;
i_buf[((c<<1)&6)+1]=y_buf[((c<<1)&6)+1]*i_filt[((c<<1)&6)+1];
q_buf[((c<<1)&6)+1]=y_buf[((c<<1)&6)+1]*q_filt[((c<<1)&6)+1];
y_tot=y_buf[0]+y_buf[1]+y_buf[2]+y_buf[3]+y_buf[4]+y_buf[5]+y_buf[6]+y_buf[7];
i_tot=i_buf[0]+i_buf[1]+i_buf[2]+i_buf[3]+i_buf[4]+i_buf[5]+i_buf[6]+i_buf[7];
q_tot=q_buf[0]+q_buf[1]+q_buf[2]+q_buf[3]+q_buf[4]+q_buf[5]+q_buf[6]+q_buf[7];
y_buf[((c << 1) & 6) + 1] = ntsc_col[buffer->line[cga->displine][c] & 7][((c << 1) & 6) + 1] ? 0x6000 : 0;
y_buf[((c << 1) & 6) + 1] += (buffer->line[cga->displine][c] & 8) ? 0x3000 : 0;
i_buf[((c << 1) & 6) + 1] = y_buf[((c << 1) & 6) + 1] * i_filt[((c << 1) & 6) + 1];
q_buf[((c << 1) & 6) + 1] = y_buf[((c << 1) & 6) + 1] * q_filt[((c << 1) & 6) + 1];
y_tot = y_buf[0] + y_buf[1] + y_buf[2] + y_buf[3] + y_buf[4] + y_buf[5] + y_buf[6] + y_buf[7];
i_tot = i_buf[0] + i_buf[1] + i_buf[2] + i_buf[3] + i_buf[4] + i_buf[5] + i_buf[6] + i_buf[7];
q_tot = q_buf[0] + q_buf[1] + q_buf[2] + q_buf[3] + q_buf[4] + q_buf[5] + q_buf[6] + q_buf[7];
y_val=y_tot>>10;
if (y_val>255) y_val=255;
y_val<<=16;
i_val=i_tot>>12;
if (i_val>39041) i_val=39041;
if (i_val<-39041) i_val=-39041;
q_val=q_tot>>12;
if (q_val>34249) q_val=34249;
if (q_val<-34249) q_val=-34249;
y_val = y_tot >> 10;
if (y_val > 255) y_val = 255;
y_val <<= 16;
i_val = i_tot >> 12;
if (i_val > 39041) i_val = 39041;
if (i_val < -39041) i_val = -39041;
q_val = q_tot >> 12;
if (q_val > 34249) q_val = 34249;
if (q_val < -34249) q_val = -34249;
r+=(y_val+249*i_val+159*q_val)>>16;
g+=(y_val-70*i_val-166*q_val)>>16;
b+=(y_val-283*i_val+436*q_val)>>16;
if (r>511) r=511;
if (g>511) g=511;
if (b>511) b=511;
r = (y_val + 249*i_val + 159*q_val) >> 16;
g = (y_val - 70*i_val - 166*q_val) >> 16;
b = (y_val - 283*i_val + 436*q_val) >> 16;
if (r > 511) r = 511;
if (g > 511) g = 511;
if (b > 511) b = 511;
((uint32_t *)buffer32->line[displine])[c]=makecol32(r/2,g/2,b/2);
((uint32_t *)buffer32->line[cga->displine])[c] = makecol32(r / 2, g / 2, b / 2);
}
}
sc=oldsc;
if (vc==crtc[7] && !sc)
cgastat|=8;
displine++;
if (displine>=360) displine=0;
cga->sc = oldsc;
if (cga->vc == cga->crtc[7] && !cga->sc)
cga->cgastat |= 8;
cga->displine++;
if (cga->displine >= 360)
cga->displine = 0;
}
else
{
vidtime+=dispontime;
if (cgadispon) cgastat&=~1;
linepos=0;
if (vsynctime)
cga->vidtime += cga->dispontime;
if (cga->cgadispon) cga->cgastat &= ~1;
cga->linepos = 0;
if (cga->vsynctime)
{
vsynctime--;
if (!vsynctime)
cgastat&=~8;
cga->vsynctime--;
if (!cga->vsynctime)
cga->cgastat &= ~8;
}
if (sc==(crtc[11]&31) || ((crtc[8]&3)==3 && sc==((crtc[11]&31)>>1))) { con=0; coff=1; }
if ((crtc[8] & 3) == 3 && sc == (crtc[9] >> 1))
maback = ma;
if (vadj)
if (cga->sc == (cga->crtc[11] & 31) || ((cga->crtc[8] & 3) == 3 && cga->sc == ((cga->crtc[11] & 31) >> 1)))
{
cga->con = 0;
cga->coff = 1;
}
if ((cga->crtc[8] & 3) == 3 && cga->sc == (cga->crtc[9] >> 1))
cga->maback = cga->ma;
if (cga->vadj)
{
sc++;
sc&=31;
ma=maback;
vadj--;
if (!vadj)
cga->sc++;
cga->sc &= 31;
cga->ma = cga->maback;
cga->vadj--;
if (!cga->vadj)
{
cgadispon=1;
ma=maback=(crtc[13]|(crtc[12]<<8))&0x3FFF;
sc=0;
cga->cgadispon = 1;
cga->ma = cga->maback = (cga->crtc[13] | (cga->crtc[12] << 8)) & 0x3fff;
cga->sc = 0;
}
}
else if (sc==crtc[9])
else if (cga->sc == cga->crtc[9])
{
maback=ma;
sc=0;
oldvc=vc;
vc++;
vc&=127;
cga->maback = cga->ma;
cga->sc = 0;
oldvc = cga->vc;
cga->vc++;
cga->vc &= 127;
if (vc==crtc[6]) cgadispon=0;
if (cga->vc == cga->crtc[6])
cga->cgadispon = 0;
if (oldvc==crtc[4])
if (oldvc == cga->crtc[4])
{
vc=0;
vadj=crtc[5];
if (!vadj) cgadispon=1;
if (!vadj) ma=maback=(crtc[13]|(crtc[12]<<8))&0x3FFF;
if ((crtc[10]&0x60)==0x20) cursoron=0;
else cursoron=cgablink&8;
cga->vc = 0;
cga->vadj = cga->crtc[5];
if (!cga->vadj) cga->cgadispon = 1;
if (!cga->vadj) cga->ma = cga->maback = (cga->crtc[13] | (cga->crtc[12] << 8)) & 0x3fff;
if ((cga->crtc[10] & 0x60) == 0x20) cga->cursoron = 0;
else cga->cursoron = cga->cgablink & 8;
}
if (vc==crtc[7])
if (cga->vc == cga->crtc[7])
{
cgadispon=0;
displine=0;
vsynctime=(crtc[3]>>4)+1;
if (crtc[7])
cga->cgadispon = 0;
cga->displine = 0;
cga->vsynctime = (cga->crtc[3] >> 4) + 1;
if (cga->crtc[7])
{
if (cgamode&1) x=(crtc[1]<<3)+16;
else x=(crtc[1]<<4)+16;
lastline++;
if (x!=xsize || (lastline-firstline)!=ysize)
if (cga->cgamode & 1) x = (cga->crtc[1] << 3) + 16;
else x = (cga->crtc[1] << 4) + 16;
cga->lastline++;
if (x != xsize || (cga->lastline - cga->firstline) != ysize)
{
xsize=x;
ysize=lastline-firstline;
if (xsize<64) xsize=656;
if (ysize<32) ysize=200;
updatewindowsize(xsize,(ysize<<1)+16);
xsize = x;
ysize = cga->lastline - cga->firstline;
if (xsize < 64) xsize = 656;
if (ysize < 32) ysize = 200;
updatewindowsize(xsize, (ysize << 1) + 16);
}
startblit();
if (cga_comp)
video_blit_memtoscreen(0, firstline-4, 0, (lastline-firstline)+8, xsize, (lastline-firstline)+8);
video_blit_memtoscreen(0, cga->firstline - 4, 0, (cga->lastline - cga->firstline) + 8, xsize, (cga->lastline - cga->firstline) + 8);
else
video_blit_memtoscreen_8(0, firstline-4, xsize, (lastline-firstline)+8);
if (readflash) rectfill(screen,winsizex-40,8,winsizex-8,14,0xFFFFFFFF);
readflash=0;
video_blit_memtoscreen_8(0, cga->firstline - 4, xsize, (cga->lastline - cga->firstline) + 8);
if (readflash) rectfill(screen, winsizex - 40, 8, winsizex - 8, 14, 0xffffffff);
readflash = 0;
frames++;
endblit();
video_res_x = xsize - 16;
video_res_y = ysize;
if (cgamode & 1)
if (cga->cgamode & 1)
{
video_res_x /= 8;
video_res_y /= crtc[9] + 1;
video_res_y /= cga->crtc[9] + 1;
video_bpp = 0;
}
else if (!(cgamode & 2))
else if (!(cga->cgamode & 2))
{
video_res_x /= 16;
video_res_y /= crtc[9] + 1;
video_res_y /= cga->crtc[9] + 1;
video_bpp = 0;
}
else if (!(cgamode&16))
else if (!(cga->cgamode & 16))
{
video_res_x /= 2;
video_bpp = 2;
@ -446,59 +456,72 @@ endblit();
video_bpp = 1;
}
}
firstline=1000;
lastline=0;
cgablink++;
oddeven ^= 1;
cga->firstline = 1000;
cga->lastline = 0;
cga->cgablink++;
cga->oddeven ^= 1;
}
}
else
{
sc++;
sc&=31;
ma=maback;
cga->sc++;
cga->sc &= 31;
cga->ma = cga->maback;
}
if ((sc==(crtc[10]&31) || ((crtc[8]&3)==3 && sc==((crtc[10]&31)>>1)))) con=1;
if (cgadispon && (cgamode&1))
if ((cga->sc == (cga->crtc[10] & 31) || ((cga->crtc[8] & 3) == 3 && cga->sc == ((cga->crtc[10] & 31) >> 1))))
cga->con = 1;
if (cga->cgadispon && (cga->cgamode & 1))
{
for (x=0;x<(crtc[1]<<1);x++)
charbuffer[x]=vram[(((ma<<1)+x)&0x3FFF)];
for (x = 0; x < (cga->crtc[1] << 1); x++)
cga->charbuffer[x] = cga->vram[(((cga->ma << 1) + x) & 0x3fff)];
}
}
}
void cga_init(cga_t *cga)
{
}
int cga_init()
void *cga_standalone_init()
{
int c;
int cga_tint = -2;
for (c=0;c<8;c++)
cga_t *cga = malloc(sizeof(cga_t));
memset(cga, 0, sizeof(cga_t));
cga->vram = malloc(0x4000);
for (c = 0; c < 8; c++)
{
i_filt[c]=512.0*cos((3.14*(cga_tint+c*4)/16.0) - 33.0/180.0);
q_filt[c]=512.0*sin((3.14*(cga_tint+c*4)/16.0) - 33.0/180.0);
i_filt[c] = 512.0 * cos((3.14 * (cga_tint + c * 4) / 16.0) - 33.0 / 180.0);
q_filt[c] = 512.0 * sin((3.14 * (cga_tint + c * 4) / 16.0) - 33.0 / 180.0);
}
mem_sethandler(0xb8000, 0x08000, cga_read, NULL, NULL, cga_write, NULL, NULL, NULL);
return 0;
timer_add(cga_poll, &cga->vidtime, TIMER_ALWAYS_ENABLED, cga);
mem_sethandler(0xb8000, 0x08000, cga_read, NULL, NULL, cga_write, NULL, NULL, cga);
io_sethandler(0x03d0, 0x0010, cga_in, NULL, NULL, cga_out, NULL, NULL, cga);
return cga;
}
GFXCARD vid_cga =
void cga_close(void *p)
{
cga_init,
/*IO at 3Cx/3Dx*/
cga_out,
cga_in,
/*IO at 3Ax/3Bx*/
video_out_null,
video_in_null,
cga_t *cga = (cga_t *)p;
cga_poll,
cga_recalctimings,
free(cga->vram);
free(cga);
}
video_write_null,
video_write_null,
cga_write,
void cga_speed_changed(void *p)
{
cga_t *cga = (cga_t *)p;
cga_recalctimings(cga);
}
video_read_null,
video_read_null,
cga_read
device_t cga_device =
{
"CGA",
cga_standalone_init,
cga_close,
cga_speed_changed,
NULL
};

View file

@ -1,7 +1,38 @@
int cga_init();
void cga_out(uint16_t addr, uint8_t val, void *priv);
uint8_t cga_in(uint16_t addr, void *priv);
void cga_poll();
void cga_write(uint32_t addr, uint8_t val, void *priv);
uint8_t cga_read(uint32_t addr, void *priv);
void cga_recalctimings();
typedef struct cga_t
{
int crtcreg;
uint8_t crtc[32];
uint8_t cgastat;
uint8_t cgamode, cgacol;
int linepos, displine;
int sc, vc;
int cgadispon;
int con, coff, cursoron, cgablink;
int vsynctime, vadj;
uint16_t ma, maback;
int oddeven;
int dispontime, dispofftime;
int vidtime;
int firstline, lastline;
int drawcursor;
uint8_t *vram;
uint8_t charbuffer[256];
} cga_t;
void cga_init(cga_t *cga);
void cga_out(uint16_t addr, uint8_t val, void *p);
uint8_t cga_in(uint16_t addr, void *p);
void cga_write(uint32_t addr, uint8_t val, void *p);
uint8_t cga_read(uint32_t addr, void *p);
void cga_recalctimings(cga_t *cga);
void cga_poll(void *p);
extern device_t cga_device;

File diff suppressed because it is too large Load diff

1
src/vid_cl5429.h Normal file
View file

@ -0,0 +1 @@
extern device_t gd5429_device;

File diff suppressed because it is too large Load diff

View file

@ -1,7 +1,71 @@
int ega_init();
void ega_out(uint16_t addr, uint8_t val, void *priv);
uint8_t ega_in(uint16_t addr, void *priv);
void ega_poll();
void ega_recalctimings();
void ega_write(uint32_t addr, uint8_t val, void *priv);
uint8_t ega_read(uint32_t addr, void *priv);
typedef struct ega_t
{
uint8_t crtcreg;
uint8_t crtc[32];
uint8_t gdcreg[16];
int gdcaddr;
uint8_t attrregs[32];
int attraddr, attrff;
uint8_t seqregs[64];
int seqaddr;
uint8_t miscout;
int vidclock;
uint8_t la, lb, lc, ld;
uint8_t stat;
int fast;
uint8_t colourcompare, colournocare;
int readmode, writemode, readplane;
int chain4;
uint8_t writemask;
uint32_t charseta, charsetb;
uint8_t egapal[16];
uint32_t *pallook;
int vtotal, dispend, vsyncstart, split;
int hdisp, htotal, hdisp_time, rowoffset;
int lowres, interlace;
int linedbl, rowcount;
double clock;
uint32_t ma_latch;
int vres;
int dispontime, dispofftime;
int vidtime;
uint8_t scrblank;
int dispon;
int hdisp_on;
uint32_t ma, maback, ca;
int vc;
int sc;
int linepos, vslines, linecountff, oddeven;
int con, cursoron, blink;
int scrollcache;
int firstline, lastline;
int firstline_draw, lastline_draw;
int displine;
uint8_t *vram;
int vrammask;
int video_res_x, video_res_y, video_bpp;
} ega_t;
void *ega_standalone_init();
void ega_out(uint16_t addr, uint8_t val, void *p);
uint8_t ega_in(uint16_t addr, void *p);
void ega_poll(void *p);
void ega_recalctimings(struct ega_t *ega);
void ega_write(uint32_t addr, uint8_t val, void *p);
uint8_t ega_read(uint32_t addr, void *p);
extern device_t ega_device;

View file

@ -1,141 +1,156 @@
/*ET4000 emulation*/
#include <stdlib.h>
#include "ibm.h"
#include "device.h"
#include "io.h"
#include "video.h"
#include "vid_svga.h"
#include "vid_unk_ramdac.h"
int et4k_b8000;
#include "vid_et4000.h"
void et4000_out(uint16_t addr, uint8_t val, void *priv)
typedef struct et4000_t
{
svga_t svga;
unk_ramdac_t ramdac;
uint8_t banking;
} et4000_t;
void et4000_out(uint16_t addr, uint8_t val, void *p)
{
et4000_t *et4000 = (et4000_t *)p;
svga_t *svga = &et4000->svga;
uint8_t old;
if (((addr&0xFFF0) == 0x3D0 || (addr&0xFFF0) == 0x3B0) && !(svga_miscout&1)) addr ^= 0x60;
if (((addr&0xFFF0) == 0x3D0 || (addr&0xFFF0) == 0x3B0) && !(svga->miscout & 1))
addr ^= 0x60;
pclog("ET4000 out %04X %02X\n", addr, val);
switch (addr)
{
case 0x3C6: case 0x3C7: case 0x3C8: case 0x3C9:
unk_ramdac_out(addr, val, NULL);
unk_ramdac_out(addr, val, &et4000->ramdac, svga);
return;
case 0x3CD: /*Banking*/
svgawbank=(val&0xF)*65536;
svgarbank=((val>>4)&0xF)*65536;
svgaseg=val;
pclog("Banking write %08X %08X %02X\n", svgawbank, svgarbank, val);
svga->write_bank = (val & 0xf) * 0x10000;
svga->read_bank = ((val >> 4) & 0xf) * 0x10000;
et4000->banking = val;
pclog("Banking write %08X %08X %02X\n", svga->write_bank, svga->read_bank, val);
return;
case 0x3CF:
switch (gdcaddr&15)
{
case 6:
et4k_b8000=((crtc[0x36]&0x38)==0x28) && ((gdcreg[6]&0xC)==4);
break;
}
break;
case 0x3D4:
crtcreg = val & 0x3f;
svga->crtcreg = val & 0x3f;
return;
case 0x3D5:
if (crtcreg <= 7 && crtc[0x11] & 0x80) return;
old=crtc[crtcreg];
crtc[crtcreg]=val;
et4k_b8000=((crtc[0x36]&0x38)==0x28) && ((gdcreg[6]&0xC)==4);
if (old!=val)
if (svga->crtcreg <= 7 && svga->crtc[0x11] & 0x80) return;
old = svga->crtc[svga->crtcreg];
svga->crtc[svga->crtcreg] = val;
if (old != val)
{
if (crtcreg<0xE || crtcreg>0x10)
if (svga->crtcreg < 0xE || svga->crtcreg > 0x10)
{
fullchange=changeframecount;
svga_recalctimings();
fullchange = changeframecount;
svga_recalctimings(svga);
}
}
break;
case 0x3D8:
if (val==0xA0) svgaon=1;
if (val==0x29) svgaon=0;
break;
}
svga_out(addr, val, priv);
svga_out(addr, val, svga);
}
uint8_t et4000_in(uint16_t addr, void *priv)
uint8_t et4000_in(uint16_t addr, void *p)
{
if (((addr&0xFFF0) == 0x3D0 || (addr&0xFFF0) == 0x3B0) && !(svga_miscout&1)) addr ^= 0x60;
et4000_t *et4000 = (et4000_t *)p;
svga_t *svga = &et4000->svga;
if (((addr&0xFFF0) == 0x3D0 || (addr&0xFFF0) == 0x3B0) && !(svga->miscout & 1))
addr ^= 0x60;
if (addr != 0x3da) pclog("IN ET4000 %04X\n", addr);
switch (addr)
{
case 0x3C5:
if ((seqaddr&0xF)==7) return seqregs[seqaddr&0xF]|4;
if ((svga->seqaddr & 0xf) == 7) return svga->seqregs[svga->seqaddr & 0xf] | 4;
break;
case 0x3C6: case 0x3C7: case 0x3C8: case 0x3C9:
return unk_ramdac_in(addr, NULL);
return unk_ramdac_in(addr, &et4000->ramdac, svga);
case 0x3CD: /*Banking*/
return svgaseg;
return et4000->banking;
case 0x3D4:
return crtcreg;
return svga->crtcreg;
case 0x3D5:
return crtc[crtcreg];
return svga->crtc[svga->crtcreg];
}
return svga_in(addr, priv);
return svga_in(addr, svga);
}
void et4000_recalctimings()
void et4000_recalctimings(svga_t *svga)
{
svga_ma|=(crtc[0x33]&3)<<16;
if (crtc[0x35]&2) svga_vtotal+=0x400;
if (crtc[0x35]&4) svga_dispend+=0x400;
if (crtc[0x35]&8) svga_vsyncstart+=0x400;
if (crtc[0x35]&0x10) svga_split+=0x400;
if (!svga_rowoffset) svga_rowoffset=0x100;
// if (crtc[0x3F]&0x80) svga_rowoffset+=0x100;
if (crtc[0x3F]&1) svga_htotal+=256;
if (attrregs[0x16]&0x20) svga_hdisp<<=1;
et4000_t *et4000 = (et4000_t *)svga->p;
svga->ma_latch |= (svga->crtc[0x33]&3)<<16;
if (svga->crtc[0x35] & 2) svga->vtotal += 0x400;
if (svga->crtc[0x35] & 4) svga->dispend += 0x400;
if (svga->crtc[0x35] & 8) svga->vsyncstart += 0x400;
if (svga->crtc[0x35] & 0x10) svga->split += 0x400;
if (!svga->rowoffset) svga->rowoffset = 0x100;
if (svga->crtc[0x3f] & 1) svga->htotal += 256;
if (svga->attrregs[0x16] & 0x20) svga->hdisp <<= 1;
// pclog("Rowoffset %i\n",svga_rowoffset);
switch (((svga_miscout >> 2) & 3) | ((crtc[0x34] << 1) & 4))
switch (((svga->miscout >> 2) & 3) | ((svga->crtc[0x34] << 1) & 4))
{
case 0: case 1: break;
case 3: svga_clock = cpuclock/40000000.0; break;
case 5: svga_clock = cpuclock/65000000.0; break;
default: svga_clock = cpuclock/36000000.0; break;
case 3: svga->clock = cpuclock / 40000000.0; break;
case 5: svga->clock = cpuclock / 65000000.0; break;
default: svga->clock = cpuclock / 36000000.0; break;
}
}
int et4000_init()
void *et4000_init()
{
svga_recalctimings_ex = et4000_recalctimings;
svga_vram_limit = 1 << 20; /*1mb*/
vrammask = 0xfffff;
return svga_init();
et4000_t *et4000 = malloc(sizeof(et4000_t));
memset(et4000, 0, sizeof(et4000_t));
io_sethandler(0x03c0, 0x0020, et4000_in, NULL, NULL, et4000_out, NULL, NULL, et4000);
svga_init(&et4000->svga, et4000, 1 << 20, /*1mb*/
et4000_recalctimings,
et4000_in, et4000_out,
NULL);
return et4000;
}
GFXCARD vid_et4000 =
void et4000_close(void *p)
{
et4000_t *et4000 = (et4000_t *)p;
svga_close(&et4000->svga);
free(et4000);
}
void et4000_speed_changed(void *p)
{
et4000_t *et4000 = (et4000_t *)p;
svga_recalctimings(&et4000->svga);
}
device_t et4000_device =
{
"Tseng Labs ET4000AX",
et4000_init,
/*IO at 3Cx/3Dx*/
et4000_out,
et4000_in,
/*IO at 3Ax/3Bx*/
video_out_null,
video_in_null,
svga_poll,
svga_recalctimings,
svga_write,
video_write_null,
video_write_null,
svga_read,
video_read_null,
video_read_null
et4000_close,
et4000_speed_changed,
svga_add_status_info
};

1
src/vid_et4000.h Normal file
View file

@ -0,0 +1 @@
extern device_t et4000_device;

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1 @@
extern device_t et4000w32p_device;

View file

@ -1,296 +1,358 @@
/*Hercules emulation*/
#include <stdlib.h>
#include "ibm.h"
#include "device.h"
#include "mem.h"
#include "timer.h"
#include "video.h"
#include "vid_hercules.h"
void hercules_recalctimings();
void hercules_write(uint32_t addr, uint8_t val, void *priv);
uint8_t hercules_read(uint32_t addr, void *priv);
static uint8_t hercules_ctrl, hercules_ctrl2, hercules_stat;
uint8_t crtcm[32],crtcmreg;
void hercules_out(uint16_t addr, uint8_t val, void *priv)
typedef struct hercules_t
{
uint8_t crtc[32];
int crtcreg;
uint8_t ctrl, ctrl2, stat;
int dispontime, dispofftime;
int vidtime;
int firstline, lastline;
int linepos, displine;
int vc, sc;
uint16_t ma, maback;
int con, coff, cursoron;
int dispon, blink;
int vsynctime, vadj;
uint8_t *vram;
} hercules_t;
static int mdacols[256][2][2];
void hercules_recalctimings(hercules_t *hercules);
void hercules_write(uint32_t addr, uint8_t val, void *p);
uint8_t hercules_read(uint32_t addr, void *p);
void hercules_out(uint16_t addr, uint8_t val, void *p)
{
hercules_t *hercules = (hercules_t *)p;
// pclog("Herc out %04X %02X\n",addr,val);
switch (addr)
{
case 0x3B0: case 0x3B2: case 0x3B4: case 0x3B6:
crtcmreg = val & 31;
case 0x3b0: case 0x3b2: case 0x3b4: case 0x3b6:
hercules->crtcreg = val & 31;
return;
case 0x3B1: case 0x3B3: case 0x3B5: case 0x3B7:
crtcm[crtcmreg] = val;
if (crtcm[10]==6 && crtcm[11]==7) /*Fix for Generic Turbo XT BIOS, which sets up cursor registers wrong*/
case 0x3b1: case 0x3b3: case 0x3b5: case 0x3b7:
hercules->crtc[hercules->crtcreg] = val;
if (hercules->crtc[10] == 6 && hercules->crtc[11] == 7) /*Fix for Generic Turbo XT BIOS, which sets up cursor registers wrong*/
{
crtcm[10]=0xB;
crtcm[11]=0xC;
hercules->crtc[10] = 0xb;
hercules->crtc[11] = 0xc;
}
hercules_recalctimings();
hercules_recalctimings(hercules);
return;
case 0x3B8:
hercules_ctrl = val;
case 0x3b8:
hercules->ctrl = val;
return;
case 0x3BF:
hercules_ctrl2 = val;
video_write_b800 = (val&2) ? hercules_write : video_write_null;
video_read_b800 = (val&2) ? hercules_read : video_read_null;
case 0x3bf:
hercules->ctrl2 = val;
mem_removehandler(0xb8000, 0x08000, hercules_read, NULL, NULL, hercules_write, NULL, NULL, hercules);
if (val & 2)
mem_sethandler(0xb8000, 0x08000, hercules_read, NULL, NULL, hercules_write, NULL, NULL, hercules);
return;
}
}
uint8_t hercules_in(uint16_t addr, void *priv)
uint8_t hercules_in(uint16_t addr, void *p)
{
hercules_t *hercules = (hercules_t *)p;
// pclog("Herc in %04X %02X %04X:%04X %04X\n",addr,(hercules_stat & 0xF) | ((hercules_stat & 8) << 4),CS,pc,CX);
switch (addr)
{
case 0x3B0: case 0x3B2: case 0x3B4: case 0x3B6:
return crtcmreg;
case 0x3B1: case 0x3B3: case 0x3B5: case 0x3B7:
return crtcm[crtcmreg];
case 0x3BA:
return (hercules_stat & 0xF) | ((hercules_stat & 8) << 4);
case 0x3b0: case 0x3b2: case 0x3b4: case 0x3b6:
return hercules->crtcreg;
case 0x3b1: case 0x3b3: case 0x3b5: case 0x3b7:
return hercules->crtc[hercules->crtcreg];
case 0x3ba:
return (hercules->stat & 0xf) | ((hercules->stat & 8) << 4);
}
return 0xff;
}
void hercules_write(uint32_t addr, uint8_t val, void *priv)
void hercules_write(uint32_t addr, uint8_t val, void *p)
{
hercules_t *hercules = (hercules_t *)p;
// pclog("Herc write %08X %02X\n",addr,val);
vram[addr&0xFFFF]=val;
hercules->vram[addr & 0xffff] = val;
}
uint8_t hercules_read(uint32_t addr, void *priv)
uint8_t hercules_read(uint32_t addr, void *p)
{
return vram[addr&0xFFFF];
hercules_t *hercules = (hercules_t *)p;
return hercules->vram[addr & 0xffff];
}
void hercules_recalctimings()
void hercules_recalctimings(hercules_t *hercules)
{
double disptime;
double _dispontime, _dispofftime;
disptime=crtc[0]+1;
_dispontime=crtc[1];
_dispofftime=disptime-_dispontime;
_dispontime*=MDACONST;
_dispofftime*=MDACONST;
dispontime = (int)(_dispontime * (1 << TIMER_SHIFT));
dispofftime = (int)(_dispofftime * (1 << TIMER_SHIFT));
disptime = hercules->crtc[0] + 1;
_dispontime = hercules->crtc[1];
_dispofftime = disptime - _dispontime;
_dispontime *= MDACONST;
_dispofftime *= MDACONST;
hercules->dispontime = (int)(_dispontime * (1 << TIMER_SHIFT));
hercules->dispofftime = (int)(_dispofftime * (1 << TIMER_SHIFT));
}
int mdacols[256][2][2];
static int linepos,displine;
static int vc,sc;
static uint16_t ma,maback;
static int con,coff,cursoron;
static int cgadispon,cgablink;
static int vsynctime,vadj;
void hercules_poll()
void hercules_poll(void *p)
{
uint16_t ca=(crtcm[15]|(crtcm[14]<<8))&0x3FFF;
hercules_t *hercules = (hercules_t *)p;
uint16_t ca = (hercules->crtc[15] | (hercules->crtc[14] << 8)) & 0x3fff;
int drawcursor;
int x,c;
int x, c;
int oldvc;
uint8_t chr,attr;
uint8_t chr, attr;
uint16_t dat;
int cols[4];
int oldsc;
int blink;
if (!linepos)
if (!hercules->linepos)
{
//pclog("Poll %i %i\n",vc,sc);
vidtime+=dispofftime;
hercules_stat|=1;
linepos=1;
oldsc=sc;
if ((crtcm[8]&3)==3) sc=(sc<<1)&7;
if (cgadispon)
hercules->vidtime += hercules->dispofftime;
hercules->stat |= 1;
hercules->linepos = 1;
oldsc = hercules->sc;
if ((hercules->crtc[8] & 3) == 3)
hercules->sc = (hercules->sc << 1) & 7;
if (hercules->dispon)
{
if (displine<firstline)
if (hercules->displine < hercules->firstline)
{
firstline=displine;
hercules->firstline = hercules->displine;
}
lastline=displine;
cols[0]=0;
cols[1]=7;
if ((hercules_ctrl & 2) && (hercules_ctrl2 & 1))
hercules->lastline = hercules->displine;
cols[0] = 0;
cols[1] = 7;
if ((hercules->ctrl & 2) && (hercules->ctrl2 & 1))
{
ca=(sc&3)*0x2000;
if ((hercules_ctrl & 0x80) && (hercules_ctrl2 & 2)) ca+=0x8000;
ca = (hercules->sc & 3) * 0x2000;
if ((hercules->ctrl & 0x80) && (hercules->ctrl2 & 2))
ca += 0x8000;
// printf("Draw herc %04X\n",ca);
for (x=0;x<crtcm[1];x++)
for (x = 0; x < hercules->crtc[1]; x++)
{
dat=(vram[((ma<<1)&0x1FFF)+ca]<<8)|vram[((ma<<1)&0x1FFF)+ca+1];
ma++;
for (c=0;c<16;c++)
buffer->line[displine][(x<<4)+c]=(dat&(32768>>c))?7:0;
dat = (hercules->vram[((hercules->ma << 1) & 0x1fff) + ca] << 8) | hercules->vram[((hercules->ma << 1) & 0x1fff) + ca + 1];
hercules->ma++;
for (c = 0; c < 16; c++)
buffer->line[hercules->displine][(x << 4) + c] = (dat & (32768 >> c)) ? 7 : 0;
}
}
else
{
for (x=0;x<crtcm[1];x++)
for (x = 0; x < hercules->crtc[1]; x++)
{
chr=vram[(ma<<1)&0x3FFF];
attr=vram[((ma<<1)+1)&0x3FFF];
drawcursor=((ma==ca) && con && cursoron);
blink=((cgablink&16) && (hercules_ctrl&0x20) && (attr&0x80) && !drawcursor);
if (sc==12 && ((attr&7)==1))
chr = hercules->vram[(hercules->ma << 1) & 0x3fff];
attr = hercules->vram[((hercules->ma << 1) + 1) & 0x3fff];
drawcursor = ((hercules->ma == ca) && hercules->con && hercules->cursoron);
blink = ((hercules->blink & 16) && (hercules->ctrl & 0x20) && (attr & 0x80) && !drawcursor);
if (hercules->sc == 12 && ((attr & 7) == 1))
{
for (c=0;c<9;c++)
buffer->line[displine][(x*9)+c]=mdacols[attr][blink][1];
for (c = 0; c < 9; c++)
buffer->line[hercules->displine][(x * 9) + c] = mdacols[attr][blink][1];
}
else
{
for (c=0;c<8;c++)
buffer->line[displine][(x*9)+c]=mdacols[attr][blink][(fontdatm[chr][sc]&(1<<(c^7)))?1:0];
if ((chr&~0x1F)==0xC0) buffer->line[displine][(x*9)+8]=mdacols[attr][blink][fontdatm[chr][sc]&1];
else buffer->line[displine][(x*9)+8]=mdacols[attr][blink][0];
for (c = 0; c < 8; c++)
buffer->line[hercules->displine][(x * 9) + c] = mdacols[attr][blink][(fontdatm[chr][hercules->sc] & (1 << (c ^ 7))) ? 1 : 0];
if ((chr & ~0x1f) == 0xc0) buffer->line[hercules->displine][(x * 9) + 8] = mdacols[attr][blink][fontdatm[chr][hercules->sc] & 1];
else buffer->line[hercules->displine][(x * 9) + 8] = mdacols[attr][blink][0];
}
ma++;
hercules->ma++;
if (drawcursor)
{
for (c=0;c<9;c++)
buffer->line[displine][(x*9)+c]^=mdacols[attr][0][1];
for (c = 0; c < 9; c++)
buffer->line[hercules->displine][(x * 9) + c] ^= mdacols[attr][0][1];
}
}
}
}
sc=oldsc;
if (vc==crtcm[7] && !sc)
hercules->sc = oldsc;
if (hercules->vc == hercules->crtc[7] && !hercules->sc)
{
hercules_stat|=8;
hercules->stat |= 8;
// printf("VSYNC on %i %i\n",vc,sc);
}
displine++;
if (displine>=500) displine=0;
hercules->displine++;
if (hercules->displine >= 500)
hercules->displine = 0;
}
else
{
vidtime+=dispontime;
if (cgadispon) hercules_stat&=~1;
linepos=0;
if (vsynctime)
hercules->vidtime += hercules->dispontime;
if (hercules->dispon)
hercules->stat &= ~1;
hercules->linepos = 0;
if (hercules->vsynctime)
{
vsynctime--;
if (!vsynctime)
hercules->vsynctime--;
if (!hercules->vsynctime)
{
hercules_stat&=~8;
hercules->stat &= ~8;
// printf("VSYNC off %i %i\n",vc,sc);
}
}
if (sc==(crtcm[11]&31) || ((crtcm[8]&3)==3 && sc==((crtcm[11]&31)>>1))) { con=0; coff=1; }
if (vadj)
if (hercules->sc == (hercules->crtc[11] & 31) || ((hercules->crtc[8] & 3) == 3 && hercules->sc == ((hercules->crtc[11] & 31) >> 1)))
{
hercules->con = 0;
hercules->coff = 1;
}
if (hercules->vadj)
{
sc++;
sc&=31;
ma=maback;
vadj--;
if (!vadj)
hercules->sc++;
hercules->sc &= 31;
hercules->ma = hercules->maback;
hercules->vadj--;
if (!hercules->vadj)
{
cgadispon=1;
ma=maback=(crtcm[13]|(crtcm[12]<<8))&0x3FFF;
sc=0;
hercules->dispon = 1;
hercules->ma = hercules->maback = (hercules->crtc[13] | (hercules->crtc[12] << 8)) & 0x3fff;
hercules->sc = 0;
}
}
else if (sc==crtcm[9] || ((crtcm[8]&3)==3 && sc==(crtcm[9]>>1)))
else if (hercules->sc == hercules->crtc[9] || ((hercules->crtc[8] & 3) == 3 && hercules->sc == (hercules->crtc[9] >> 1)))
{
maback=ma;
sc=0;
oldvc=vc;
vc++;
vc&=127;
if (vc==crtcm[6]) cgadispon=0;
if (oldvc==crtcm[4])
hercules->maback = hercules->ma;
hercules->sc = 0;
oldvc = hercules->vc;
hercules->vc++;
hercules->vc &= 127;
if (hercules->vc == hercules->crtc[6])
hercules->dispon = 0;
if (oldvc == hercules->crtc[4])
{
// printf("Display over at %i\n",displine);
vc=0;
vadj=crtcm[5];
if (!vadj) cgadispon=1;
if (!vadj) ma=maback=(crtcm[13]|(crtcm[12]<<8))&0x3FFF;
if ((crtcm[10]&0x60)==0x20) cursoron=0;
else cursoron=cgablink&16;
hercules->vc = 0;
hercules->vadj = hercules->crtc[5];
if (!hercules->vadj) hercules->dispon=1;
if (!hercules->vadj) hercules->ma = hercules->maback = (hercules->crtc[13] | (hercules->crtc[12] << 8)) & 0x3fff;
if ((hercules->crtc[10] & 0x60) == 0x20) hercules->cursoron = 0;
else hercules->cursoron = hercules->blink & 16;
}
if (vc==crtcm[7])
if (hercules->vc == hercules->crtc[7])
{
cgadispon=0;
displine=0;
vsynctime=16;//(crtcm[3]>>4)+1;
if (crtcm[7])
hercules->dispon = 0;
hercules->displine = 0;
hercules->vsynctime = 16;//(crtcm[3]>>4)+1;
if (hercules->crtc[7])
{
// printf("Lastline %i Firstline %i %i\n",lastline,firstline,lastline-firstline);
if ((hercules_ctrl & 2) && (hercules_ctrl2 & 1)) x = crtcm[1] << 4;
else x = crtcm[1] * 9;
lastline++;
if (x!=xsize || (lastline-firstline)!=ysize)
if ((hercules->ctrl & 2) && (hercules->ctrl2 & 1)) x = hercules->crtc[1] << 4;
else x = hercules->crtc[1] * 9;
hercules->lastline++;
if (x != xsize || (hercules->lastline - hercules->firstline) != ysize)
{
xsize=x;
ysize=lastline-firstline;
xsize = x;
ysize = hercules->lastline - hercules->firstline;
// printf("Resize to %i,%i - R1 %i\n",xsize,ysize,crtcm[1]);
if (xsize<64) xsize=656;
if (ysize<32) ysize=200;
updatewindowsize(xsize,ysize);
if (xsize < 64) xsize = 656;
if (ysize < 32) ysize = 200;
updatewindowsize(xsize, ysize);
}
startblit();
video_blit_memtoscreen_8(0, firstline, xsize, ysize);
video_blit_memtoscreen_8(0, hercules->firstline, xsize, ysize);
endblit();
frames++;
if ((hercules_ctrl & 2) && (hercules_ctrl2 & 1))
if ((hercules->ctrl & 2) && (hercules->ctrl2 & 1))
{
video_res_x = crtcm[1] * 16;
video_res_y = crtcm[6] * 4;
video_res_x = hercules->crtc[1] * 16;
video_res_y = hercules->crtc[6] * 4;
video_bpp = 1;
}
else
{
video_res_x = crtcm[1];
video_res_y = crtcm[6];
video_res_x = hercules->crtc[1];
video_res_y = hercules->crtc[6];
video_bpp = 0;
}
}
firstline=1000;
lastline=0;
cgablink++;
hercules->firstline = 1000;
hercules->lastline = 0;
hercules->blink++;
}
}
else
{
sc++;
sc&=31;
ma=maback;
hercules->sc++;
hercules->sc &= 31;
hercules->ma = hercules->maback;
}
if ((sc==(crtcm[10]&31) || ((crtcm[8]&3)==3 && sc==((crtcm[10]&31)>>1))))
if ((hercules->sc == (hercules->crtc[10] & 31) || ((hercules->crtc[8] & 3) == 3 && hercules->sc == ((hercules->crtc[10] & 31) >> 1))))
{
con=1;
hercules->con = 1;
// printf("Cursor on - %02X %02X %02X\n",crtcm[8],crtcm[10],crtcm[11]);
}
}
}
int hercules_init()
void *hercules_init()
{
mem_sethandler(0xb0000, 0x08000, hercules_read, NULL, NULL, hercules_write, NULL, NULL, NULL);
return 0;
int c;
hercules_t *hercules = malloc(sizeof(hercules_t));
memset(hercules, 0, sizeof(hercules_t));
hercules->vram = malloc(0x10000);
timer_add(hercules_poll, &hercules->vidtime, TIMER_ALWAYS_ENABLED, hercules);
mem_sethandler(0xb0000, 0x08000, hercules_read, NULL, NULL, hercules_write, NULL, NULL, hercules);
io_sethandler(0x03b0, 0x0010, hercules_in, NULL, NULL, hercules_out, NULL, NULL, hercules);
for (c = 0; c < 256; c++)
{
mdacols[c][0][0] = mdacols[c][1][0] = mdacols[c][1][1] = 16;
if (c & 8) mdacols[c][0][1] = 15 + 16;
else mdacols[c][0][1] = 7 + 16;
}
mdacols[0x70][0][1] = 16;
mdacols[0x70][0][0] = mdacols[0x70][1][0] = mdacols[0x70][1][1] = 16 + 15;
mdacols[0xF0][0][1] = 16;
mdacols[0xF0][0][0] = mdacols[0xF0][1][0] = mdacols[0xF0][1][1] = 16 + 15;
mdacols[0x78][0][1] = 16 + 7;
mdacols[0x78][0][0] = mdacols[0x78][1][0] = mdacols[0x78][1][1] = 16 + 15;
mdacols[0xF8][0][1] = 16 + 7;
mdacols[0xF8][0][0] = mdacols[0xF8][1][0] = mdacols[0xF8][1][1] = 16 + 15;
mdacols[0x00][0][1] = mdacols[0x00][1][1] = 16;
mdacols[0x08][0][1] = mdacols[0x08][1][1] = 16;
mdacols[0x80][0][1] = mdacols[0x80][1][1] = 16;
mdacols[0x88][0][1] = mdacols[0x88][1][1] = 16;
return hercules;
}
GFXCARD vid_hercules =
void hercules_close(void *p)
{
hercules_t *hercules = (hercules_t *)p;
free(hercules->vram);
free(hercules);
}
void hercules_speed_changed(void *p)
{
hercules_t *hercules = (hercules_t *)p;
hercules_recalctimings(hercules);
}
device_t hercules_device =
{
"Hercules",
hercules_init,
/*IO at 3Cx/3Dx*/
video_out_null,
video_in_null,
/*IO at 3Ax/3Bx*/
hercules_out,
hercules_in,
hercules_poll,
hercules_recalctimings,
video_write_null,
hercules_write,
video_write_null,
video_read_null,
hercules_read,
video_read_null
hercules_close,
hercules_speed_changed,
NULL
};

1
src/vid_hercules.h Normal file
View file

@ -0,0 +1 @@
extern device_t hercules_device;

View file

@ -5,70 +5,62 @@
#include "ibm.h"
#include "vid_icd2061.h"
static int icd2061_state;
static int icd2061_status = 0;
static int icd2061_pos = 0;
static int icd2061_unlock = 0;
static uint32_t icd2061_data;
static double icd2061_freq[4];
static uint32_t icd2061_ctrl;
void icd2061_write(int val)
void icd2061_write(icd2061_t *icd2061, int val)
{
int q, p, m, i, a;
if ((val & 1) && !(icd2061_state & 1))
if ((val & 1) && !(icd2061->state & 1))
{
pclog("ICD2061 write %02X %i %08X %i\n", val, icd2061_unlock, icd2061_data, icd2061_pos);
if (!icd2061_status)
pclog("ICD2061 write %02X %i %08X %i\n", val, icd2061->unlock, icd2061->data, icd2061->pos);
if (!icd2061->status)
{
if (val & 2) icd2061_unlock++;
if (val & 2)
icd2061->unlock++;
else
{
if (icd2061_unlock >= 5)
if (icd2061->unlock >= 5)
{
icd2061_status = 1;
icd2061_pos = 0;
icd2061->status = 1;
icd2061->pos = 0;
}
else
icd2061_unlock = 0;
icd2061->unlock = 0;
}
}
else if (val & 1)
{
icd2061_data = (icd2061_data >> 1) | (((val & 2) ? 1 : 0) << 24);
icd2061_pos++;
if (icd2061_pos == 26)
icd2061->data = (icd2061->data >> 1) | (((val & 2) ? 1 : 0) << 24);
icd2061->pos++;
if (icd2061->pos == 26)
{
pclog("ICD2061 data - %08X\n", icd2061_data);
a = (icd2061_data >> 21) & 0x7;
pclog("ICD2061 data - %08X\n", icd2061->data);
a = (icd2061->data >> 21) & 0x7;
if (!(a & 4))
{
q = (icd2061_data & 0x7f) - 2;
m = 1 << ((icd2061_data >> 7) & 0x7);
p = ((icd2061_data >> 10) & 0x7f) - 3;
i = (icd2061_data >> 17) & 0xf;
q = (icd2061->data & 0x7f) - 2;
m = 1 << ((icd2061->data >> 7) & 0x7);
p = ((icd2061->data >> 10) & 0x7f) - 3;
i = (icd2061->data >> 17) & 0xf;
pclog("p %i q %i m %i\n", p, q, m);
if (icd2061_ctrl & (1 << a))
if (icd2061->ctrl & (1 << a))
p <<= 1;
icd2061_freq[a] = ((double)p / (double)q) * 2.0 * 14318184.0 / (double)m;
pclog("ICD2061 freq %i = %f\n", a, icd2061_freq[a]);
icd2061->freq[a] = ((double)p / (double)q) * 2.0 * 14318184.0 / (double)m;
pclog("ICD2061 freq %i = %f\n", a, icd2061->freq[a]);
}
else if (a == 6)
{
icd2061_ctrl = val;
icd2061->ctrl = val;
pclog("ICD2061 ctrl = %08X\n", val);
}
icd2061_unlock = icd2061_data = 0;
icd2061_status = 0;
icd2061->unlock = icd2061->data = 0;
icd2061->status = 0;
}
}
}
icd2061_state = val;
icd2061->state = val;
}
double icd2061_getfreq(int i)
double icd2061_getfreq(icd2061_t *icd2061, int i)
{
pclog("Return freq %f\n", icd2061_freq[i]);
return icd2061_freq[i];
pclog("Return freq %f\n", icd2061->freq[i]);
return icd2061->freq[i];
}

View file

@ -1,2 +1,14 @@
void icd2061_write(int val);
double icd2061_getfreq(int i);
typedef struct icd2061_t
{
int state;
int status;
int pos;
int unlock;
uint32_t data;
double freq[4];
uint32_t ctrl;
} icd2061_t;
void icd2061_write(icd2061_t *icd2061, int val);
double icd2061_getfreq(icd2061_t *icd2061, int i);

View file

@ -6,58 +6,50 @@
enum
{
ICS2595_IDLE,
ICS2595_IDLE = 0,
ICS2595_WRITE,
ICS2595_READ
};
static int ics2595_oldfs3, ics2595_oldfs2;
static int ics2595_dat;
static int ics2595_pos;
static int ics2595_state = ICS2595_IDLE;
static int ics2595_div[4] = {8, 4, 2, 1};
static double ics2595_clocks[16];
double ics2595_output_clock;
void ics2595_write(int strobe, int dat)
void ics2595_write(ics2595_t *ics2595, int strobe, int dat)
{
pclog("ics2595_write : %i %i\n", strobe, dat);
if (strobe)
{
if ((dat & 8) && !ics2595_oldfs3) /*Data clock*/
if ((dat & 8) && !ics2595->oldfs3) /*Data clock*/
{
pclog(" - new dat %i\n", dat & 4);
switch (ics2595_state)
switch (ics2595->state)
{
case ICS2595_IDLE:
ics2595_state = (dat & 4) ? ICS2595_WRITE : ICS2595_IDLE;
ics2595_pos = 0;
ics2595->state = (dat & 4) ? ICS2595_WRITE : ICS2595_IDLE;
ics2595->pos = 0;
break;
case ICS2595_WRITE:
ics2595_dat = (ics2595_dat >> 1);
ics2595->dat = (ics2595->dat >> 1);
if (dat & 4)
ics2595_dat |= (1 << 19);
ics2595_pos++;
if (ics2595_pos == 20)
ics2595->dat |= (1 << 19);
ics2595->pos++;
if (ics2595->pos == 20)
{
int d, n, l;
pclog("ICS2595_WRITE : dat %08X\n", ics2595_dat);
l = (ics2595_dat >> 2) & 31;
n = ((ics2595_dat >> 7) & 255) + 257;
d = ics2595_div[(ics2595_dat >> 16) & 3];
pclog("ICS2595_WRITE : dat %08X\n", ics2595->dat);
l = (ics2595->dat >> 2) & 0xf;
n = ((ics2595->dat >> 7) & 255) + 257;
d = ics2595_div[(ics2595->dat >> 16) & 3];
ics2595_clocks[l] = (14318181.8 * ((double)n / 46.0)) / (double)d;
ics2595->clocks[l] = (14318181.8 * ((double)n / 46.0)) / (double)d;
pclog("ICS2595 clock set - L %i N %i D %i freq = %f\n", l, n, d, (14318181.8 * ((double)n / 46.0)) / (double)d);
ics2595_state = ICS2595_IDLE;
ics2595->state = ICS2595_IDLE;
}
break;
}
}
ics2595_oldfs2 = dat & 4;
ics2595_oldfs3 = dat & 8;
ics2595->oldfs2 = dat & 4;
ics2595->oldfs3 = dat & 8;
}
ics2595_output_clock = ics2595_clocks[dat];
ics2595->output_clock = ics2595->clocks[dat];
}

View file

@ -1,2 +1,12 @@
void ics2595_write(int strobe, int dat);
extern double ics2595_output_clock;
typedef struct ics2595_t
{
int oldfs3, oldfs2;
int dat;
int pos;
int state;
double clocks[16];
double output_clock;
} ics2595_t;
void ics2595_write(ics2595_t *ics2595, int strobe, int dat);

View file

@ -1,259 +1,316 @@
/*MDA emulation*/
#include <stdlib.h>
#include "ibm.h"
#include "device.h"
#include "io.h"
#include "mem.h"
#include "timer.h"
#include "video.h"
#include "vid_mda.h"
void mda_recalctimings();
static uint8_t mda_ctrl,mda_stat;
uint8_t crtcm[32],crtcmreg;
void mda_out(uint16_t addr, uint8_t val, void *priv)
typedef struct mda_t
{
uint8_t crtc[32];
int crtcreg;
uint8_t ctrl, stat;
int dispontime, dispofftime;
int vidtime;
int firstline, lastline;
int linepos, displine;
int vc, sc;
uint16_t ma, maback;
int con, coff, cursoron;
int dispon, blink;
int vsynctime, vadj;
uint8_t *vram;
} mda_t;
static int mdacols[256][2][2];
void mda_recalctimings(mda_t *mda);
void mda_out(uint16_t addr, uint8_t val, void *p)
{
mda_t *mda = (mda_t *)p;
switch (addr)
{
case 0x3B0: case 0x3B2: case 0x3B4: case 0x3B6:
crtcmreg = val & 31;
case 0x3b0: case 0x3b2: case 0x3b4: case 0x3b6:
mda->crtcreg = val & 31;
return;
case 0x3B1: case 0x3B3: case 0x3B5: case 0x3B7:
crtcm[crtcmreg] = val;
if (crtcm[10]==6 && crtcm[11]==7) /*Fix for Generic Turbo XT BIOS, which sets up cursor registers wrong*/
case 0x3b1: case 0x3b3: case 0x3b5: case 0x3b7:
mda->crtc[mda->crtcreg] = val;
if (mda->crtc[10] == 6 && mda->crtc[11] == 7) /*Fix for Generic Turbo XT BIOS, which sets up cursor registers wrong*/
{
crtcm[10]=0xB;
crtcm[11]=0xC;
mda->crtc[10] = 0xb;
mda->crtc[11] = 0xc;
}
mda_recalctimings();
mda_recalctimings(mda);
return;
case 0x3B8:
mda_ctrl = val;
case 0x3b8:
mda->ctrl = val;
return;
}
}
uint8_t mda_in(uint16_t addr, void *priv)
uint8_t mda_in(uint16_t addr, void *p)
{
mda_t *mda = (mda_t *)p;
switch (addr)
{
case 0x3B0: case 0x3B2: case 0x3B4: case 0x3B6:
return crtcmreg;
case 0x3B1: case 0x3B3: case 0x3B5: case 0x3B7:
return crtcm[crtcmreg];
case 0x3BA:
return mda_stat | 0xF0;
case 0x3b0: case 0x3b2: case 0x3b4: case 0x3b6:
return mda->crtcreg;
case 0x3b1: case 0x3b3: case 0x3b5: case 0x3b7:
return mda->crtc[mda->crtcreg];
case 0x3ba:
return mda->stat | 0xF0;
}
return 0xff;
}
void mda_write(uint32_t addr, uint8_t val, void *priv)
void mda_write(uint32_t addr, uint8_t val, void *p)
{
vram[addr&0xFFF]=val;
mda_t *mda = (mda_t *)p;
mda->vram[addr & 0xfff] = val;
}
uint8_t mda_read(uint32_t addr, void *priv)
uint8_t mda_read(uint32_t addr, void *p)
{
return vram[addr&0xFFF];
mda_t *mda = (mda_t *)p;
return mda->vram[addr & 0xfff];
}
void mda_recalctimings()
void mda_recalctimings(mda_t *mda)
{
double _dispontime, _dispofftime;
disptime=crtc[0]+1;
_dispontime=crtc[1];
_dispofftime=disptime-_dispontime;
_dispontime*=MDACONST;
_dispofftime*=MDACONST;
dispontime = (int)(_dispontime * (1 << TIMER_SHIFT));
dispofftime = (int)(_dispofftime * (1 << TIMER_SHIFT));
double _dispontime, _dispofftime, disptime;
disptime = mda->crtc[0] + 1;
_dispontime = mda->crtc[1];
_dispofftime = disptime - _dispontime;
_dispontime *= MDACONST;
_dispofftime *= MDACONST;
mda->dispontime = (int)(_dispontime * (1 << TIMER_SHIFT));
mda->dispofftime = (int)(_dispofftime * (1 << TIMER_SHIFT));
}
int mdacols[256][2][2];
static int linepos,displine;
static int vc,sc;
static uint16_t ma,maback;
static int con,coff,cursoron;
static int cgadispon,cgablink;
static int vsynctime,vadj;
void mda_poll()
void mda_poll(void *p)
{
uint16_t ca=(crtcm[15]|(crtcm[14]<<8))&0x3FFF;
mda_t *mda = (mda_t *)p;
uint16_t ca = (mda->crtc[15] | (mda->crtc[14] << 8)) & 0x3fff;
int drawcursor;
int x,c;
int x, c;
int oldvc;
uint8_t chr,attr;
uint8_t chr, attr;
int cols[4];
int oldsc;
int blink;
if (!linepos)
if (!mda->linepos)
{
vidtime+=dispofftime;
mda_stat|=1;
linepos=1;
oldsc=sc;
if ((crtcm[8]&3)==3) sc=(sc<<1)&7;
if (cgadispon)
mda->vidtime += mda->dispofftime;
mda->stat |= 1;
mda->linepos = 1;
oldsc = mda->sc;
if ((mda->crtc[8] & 3) == 3)
mda->sc = (mda->sc << 1) & 7;
if (mda->dispon)
{
if (displine<firstline)
if (mda->displine < mda->firstline)
{
firstline=displine;
mda->firstline = mda->displine;
}
lastline=displine;
cols[0]=0;
cols[1]=7;
for (x=0;x<crtcm[1];x++)
mda->lastline = mda->displine;
cols[0] = 0;
cols[1] = 7;
for (x = 0; x < mda->crtc[1]; x++)
{
chr=vram[(ma<<1)&0x3FFF];
attr=vram[((ma<<1)+1)&0x3FFF];
drawcursor=((ma==ca) && con && cursoron);
blink=((cgablink&16) && (mda_ctrl&0x20) && (attr&0x80) && !drawcursor);
if (sc==12 && ((attr&7)==1))
chr = mda->vram[(mda->ma << 1) & 0x3fff];
attr = mda->vram[((mda->ma << 1) + 1) & 0x3fff];
drawcursor = ((mda->ma == ca) && mda->con && mda->cursoron);
blink = ((mda->blink & 16) && (mda->ctrl & 0x20) && (attr & 0x80) && !drawcursor);
if (mda->sc == 12 && ((attr & 7) == 1))
{
for (c=0;c<9;c++)
buffer->line[displine][(x*9)+c]=mdacols[attr][blink][1];
for (c = 0; c < 9; c++)
buffer->line[mda->displine][(x * 9) + c] = mdacols[attr][blink][1];
}
else
{
for (c=0;c<8;c++)
buffer->line[displine][(x*9)+c]=mdacols[attr][blink][(fontdatm[chr][sc]&(1<<(c^7)))?1:0];
if ((chr&~0x1F)==0xC0) buffer->line[displine][(x*9)+8]=mdacols[attr][blink][fontdatm[chr][sc]&1];
else buffer->line[displine][(x*9)+8]=mdacols[attr][blink][0];
for (c = 0; c < 8; c++)
buffer->line[mda->displine][(x * 9) + c] = mdacols[attr][blink][(fontdatm[chr][mda->sc] & (1 << (c ^ 7))) ? 1 : 0];
if ((chr & ~0x1f) == 0xc0) buffer->line[mda->displine][(x * 9) + 8] = mdacols[attr][blink][fontdatm[chr][mda->sc] & 1];
else buffer->line[mda->displine][(x * 9) + 8] = mdacols[attr][blink][0];
}
ma++;
mda->ma++;
if (drawcursor)
{
for (c=0;c<9;c++)
buffer->line[displine][(x*9)+c]^=mdacols[attr][0][1];
for (c = 0; c < 9; c++)
buffer->line[mda->displine][(x * 9) + c] ^= mdacols[attr][0][1];
}
}
}
sc=oldsc;
if (vc==crtcm[7] && !sc)
mda->sc = oldsc;
if (mda->vc == mda->crtc[7] && !mda->sc)
{
mda_stat|=8;
mda->stat |= 8;
// printf("VSYNC on %i %i\n",vc,sc);
}
displine++;
if (displine>=500) displine=0;
mda->displine++;
if (mda->displine >= 500)
mda->displine=0;
}
else
{
vidtime+=dispontime;
if (cgadispon) mda_stat&=~1;
linepos=0;
if (vsynctime)
mda->vidtime += mda->dispontime;
if (mda->dispon) mda->stat&=~1;
mda->linepos=0;
if (mda->vsynctime)
{
vsynctime--;
if (!vsynctime)
mda->vsynctime--;
if (!mda->vsynctime)
{
mda_stat&=~8;
mda->stat&=~8;
// printf("VSYNC off %i %i\n",vc,sc);
}
}
if (sc==(crtcm[11]&31) || ((crtcm[8]&3)==3 && sc==((crtcm[11]&31)>>1))) { con=0; coff=1; }
if (vadj)
if (mda->sc == (mda->crtc[11] & 31) || ((mda->crtc[8] & 3) == 3 && mda->sc == ((mda->crtc[11] & 31) >> 1)))
{
mda->con = 0;
mda->coff = 1;
}
if (mda->vadj)
{
sc++;
sc&=31;
ma=maback;
vadj--;
if (!vadj)
mda->sc++;
mda->sc &= 31;
mda->ma = mda->maback;
mda->vadj--;
if (!mda->vadj)
{
cgadispon=1;
ma=maback=(crtcm[13]|(crtcm[12]<<8))&0x3FFF;
sc=0;
mda->dispon = 1;
mda->ma = mda->maback = (mda->crtc[13] | (mda->crtc[12] << 8)) & 0x3fff;
mda->sc = 0;
}
}
else if (sc==crtcm[9] || ((crtcm[8]&3)==3 && sc==(crtcm[9]>>1)))
else if (mda->sc == mda->crtc[9] || ((mda->crtc[8] & 3) == 3 && mda->sc == (mda->crtc[9] >> 1)))
{
maback=ma;
sc=0;
oldvc=vc;
vc++;
vc&=127;
if (vc==crtcm[6]) cgadispon=0;
if (oldvc==crtcm[4])
mda->maback = mda->ma;
mda->sc = 0;
oldvc = mda->vc;
mda->vc++;
mda->vc &= 127;
if (mda->vc == mda->crtc[6])
mda->dispon=0;
if (oldvc == mda->crtc[4])
{
// printf("Display over at %i\n",displine);
vc=0;
vadj=crtcm[5];
if (!vadj) cgadispon=1;
if (!vadj) ma=maback=(crtcm[13]|(crtcm[12]<<8))&0x3FFF;
if ((crtcm[10]&0x60)==0x20) cursoron=0;
else cursoron=cgablink&16;
mda->vc = 0;
mda->vadj = mda->crtc[5];
if (!mda->vadj) mda->dispon = 1;
if (!mda->vadj) mda->ma = mda->maback = (mda->crtc[13] | (mda->crtc[12] << 8)) & 0x3fff;
if ((mda->crtc[10] & 0x60) == 0x20) mda->cursoron = 0;
else mda->cursoron = mda->blink & 16;
}
if (vc==crtcm[7])
if (mda->vc == mda->crtc[7])
{
cgadispon=0;
displine=0;
vsynctime=16;//(crtcm[3]>>4)+1;
if (crtcm[7])
mda->dispon = 0;
mda->displine = 0;
mda->vsynctime = 16;
if (mda->crtc[7])
{
// printf("Lastline %i Firstline %i %i\n",lastline,firstline,lastline-firstline);
x=crtcm[1]*9;
lastline++;
if (x!=xsize || (lastline-firstline)!=ysize)
x = mda->crtc[1] * 9;
mda->lastline++;
if (x != xsize || (mda->lastline - mda->firstline) != ysize)
{
xsize=x;
ysize=lastline-firstline;
xsize = x;
ysize = mda->lastline - mda->firstline;
// printf("Resize to %i,%i - R1 %i\n",xsize,ysize,crtcm[1]);
if (xsize<64) xsize=656;
if (ysize<32) ysize=200;
updatewindowsize(xsize,ysize);
if (xsize < 64) xsize = 656;
if (ysize < 32) ysize = 200;
updatewindowsize(xsize, ysize);
}
startblit();
video_blit_memtoscreen_8(0, firstline, xsize, lastline - firstline);
video_blit_memtoscreen_8(0, mda->firstline, xsize, mda->lastline - mda->firstline);
endblit();
frames++;
video_res_x = crtcm[1];
video_res_y = crtcm[6];
video_res_x = mda->crtc[1];
video_res_y = mda->crtc[6];
video_bpp = 0;
}
firstline=1000;
lastline=0;
cgablink++;
mda->firstline = 1000;
mda->lastline = 0;
mda->blink++;
}
}
else
{
sc++;
sc&=31;
ma=maback;
mda->sc++;
mda->sc &= 31;
mda->ma = mda->maback;
}
if ((sc==(crtcm[10]&31) || ((crtcm[8]&3)==3 && sc==((crtcm[10]&31)>>1))))
if ((mda->sc == (mda->crtc[10] & 31) || ((mda->crtc[8] & 3) == 3 && mda->sc == ((mda->crtc[10] & 31) >> 1))))
{
con=1;
mda->con = 1;
// printf("Cursor on - %02X %02X %02X\n",crtcm[8],crtcm[10],crtcm[11]);
}
}
}
int mda_init()
void *mda_init()
{
mem_sethandler(0xb0000, 0x08000, mda_read, NULL, NULL, mda_write, NULL, NULL, NULL);
return 0;
int c;
mda_t *mda = malloc(sizeof(mda_t));
memset(mda, 0, sizeof(mda_t));
mda->vram = malloc(0x1000);
timer_add(mda_poll, &mda->vidtime, TIMER_ALWAYS_ENABLED, mda);
mem_sethandler(0xb0000, 0x08000, mda_read, NULL, NULL, mda_write, NULL, NULL, mda);
io_sethandler(0x03b0, 0x0010, mda_in, NULL, NULL, mda_out, NULL, NULL, mda);
for (c = 0; c < 256; c++)
{
mdacols[c][0][0] = mdacols[c][1][0] = mdacols[c][1][1] = 16;
if (c & 8) mdacols[c][0][1] = 15 + 16;
else mdacols[c][0][1] = 7 + 16;
}
mdacols[0x70][0][1] = 16;
mdacols[0x70][0][0] = mdacols[0x70][1][0] = mdacols[0x70][1][1] = 16 + 15;
mdacols[0xF0][0][1] = 16;
mdacols[0xF0][0][0] = mdacols[0xF0][1][0] = mdacols[0xF0][1][1] = 16 + 15;
mdacols[0x78][0][1] = 16 + 7;
mdacols[0x78][0][0] = mdacols[0x78][1][0] = mdacols[0x78][1][1] = 16 + 15;
mdacols[0xF8][0][1] = 16 + 7;
mdacols[0xF8][0][0] = mdacols[0xF8][1][0] = mdacols[0xF8][1][1] = 16 + 15;
mdacols[0x00][0][1] = mdacols[0x00][1][1] = 16;
mdacols[0x08][0][1] = mdacols[0x08][1][1] = 16;
mdacols[0x80][0][1] = mdacols[0x80][1][1] = 16;
mdacols[0x88][0][1] = mdacols[0x88][1][1] = 16;
return mda;
}
GFXCARD vid_mda =
void mda_close(void *p)
{
mda_t *mda = (mda_t *)p;
free(mda->vram);
free(mda);
}
void mda_speed_changed(void *p)
{
mda_t *mda = (mda_t *)p;
mda_recalctimings(mda);
}
device_t mda_device =
{
"MDA",
mda_init,
/*IO at 3Cx/3Dx*/
video_out_null,
video_in_null,
/*IO at 3Ax/3Bx*/
mda_out,
mda_in,
mda_poll,
mda_recalctimings,
video_write_null,
mda_write,
video_write_null,
video_read_null,
mda_read,
video_read_null
mda_close,
mda_speed_changed,
NULL
};

1
src/vid_mda.h Normal file
View file

@ -0,0 +1 @@
extern device_t mda_device;

View file

@ -1,436 +1,487 @@
/*Olivetti M24 video emulation
Essentially double-res CGA*/
#include <stdlib.h>
#include "ibm.h"
#include "device.h"
#include "io.h"
#include "mem.h"
#include "timer.h"
#include "video.h"
#include "vid_olivetti_m24.h"
void m24_recalctimings();
static uint8_t m24_ctrl;
static uint32_t m24_base;
void m24_out(uint16_t addr, uint8_t val, void *priv)
typedef struct m24_t
{
uint8_t crtc[32];
int crtcreg;
uint8_t *vram;
uint8_t charbuffer[256];
uint8_t ctrl;
uint32_t base;
uint8_t cgamode, cgacol;
uint8_t stat;
int linepos, displine;
int sc, vc;
int con, coff, cursoron, blink;
int vsynctime, vadj;
int lineff;
uint16_t ma, maback;
int dispon;
int dispontime, dispofftime, vidtime;
int firstline, lastline;
} m24_t;
static uint8_t crtcmask[32] =
{
0xff, 0xff, 0xff, 0xff, 0x7f, 0x1f, 0x7f, 0x7f, 0xf3, 0x1f, 0x7f, 0x1f, 0x3f, 0xff, 0x3f, 0xff,
0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
void m24_recalctimings(m24_t *m24);
void m24_out(uint16_t addr, uint8_t val, void *p)
{
m24_t *m24 = (m24_t *)p;
uint8_t old;
pclog("m24_out %04X %02X\n", addr, val);
switch (addr)
{
case 0x3D4:
crtcreg = val & 31;
case 0x3d4:
m24->crtcreg = val & 31;
return;
case 0x3D5:
old = crtc[crtcreg];
crtc[crtcreg] = val & crtcmask[crtcreg];
case 0x3d5:
old = m24->crtc[m24->crtcreg];
m24->crtc[m24->crtcreg] = val & crtcmask[m24->crtcreg];
if (old != val)
{
if (crtcreg < 0xE || crtcreg > 0x10)
if (m24->crtcreg < 0xe || m24->crtcreg > 0x10)
{
fullchange = changeframecount;
m24_recalctimings();
m24_recalctimings(m24);
}
}
return;
case 0x3D8:
cgamode = val;
case 0x3d8:
m24->cgamode = val;
return;
case 0x3D9:
cgacol = val;
case 0x3d9:
m24->cgacol = val;
return;
case 0x3de:
m24_ctrl = val;
m24_base = (val & 0x08) ? 0x4000 : 0;
m24->ctrl = val;
m24->base = (val & 0x08) ? 0x4000 : 0;
return;
}
}
uint8_t m24_in(uint16_t addr, void *priv)
uint8_t m24_in(uint16_t addr, void *p)
{
m24_t *m24 = (m24_t *)p;
switch (addr)
{
case 0x3D4:
return crtcreg;
case 0x3D5:
return crtc[crtcreg];
case 0x3DA:
return cgastat;
case 0x3d4:
return m24->crtcreg;
case 0x3d5:
return m24->crtc[m24->crtcreg];
case 0x3da:
return m24->stat;
}
return 0xFF;
return 0xff;
}
static uint8_t charbuffer[256];
void m24_write(uint32_t addr, uint8_t val, void *priv)
void m24_write(uint32_t addr, uint8_t val, void *p)
{
vram[addr & 0x7FFF]=val;
charbuffer[ ((int)(((dispontime - vidtime) * 2) / (CGACONST / 2))) & 0xfc] = val;
charbuffer[(((int)(((dispontime - vidtime) * 2) / (CGACONST / 2))) & 0xfc) | 1] = val;
m24_t *m24 = (m24_t *)p;
m24->vram[addr & 0x7FFF]=val;
m24->charbuffer[ ((int)(((m24->dispontime - m24->vidtime) * 2) / (CGACONST / 2))) & 0xfc] = val;
m24->charbuffer[(((int)(((m24->dispontime - m24->vidtime) * 2) / (CGACONST / 2))) & 0xfc) | 1] = val;
}
uint8_t m24_read(uint32_t addr, void *priv)
uint8_t m24_read(uint32_t addr, void *p)
{
return vram[addr & 0x7FFF];
m24_t *m24 = (m24_t *)p;
return m24->vram[addr & 0x7FFF];
}
void m24_recalctimings()
void m24_recalctimings(m24_t *m24)
{
double _dispontime, _dispofftime;
if (cgamode & 1)
double _dispontime, _dispofftime, disptime;
if (m24->cgamode & 1)
{
disptime = crtc[0] + 1;
_dispontime = crtc[1];
disptime = m24->crtc[0] + 1;
_dispontime = m24->crtc[1];
}
else
{
disptime = (crtc[0] + 1) << 1;
_dispontime = crtc[1] << 1;
disptime = (m24->crtc[0] + 1) << 1;
_dispontime = m24->crtc[1] << 1;
}
_dispofftime = disptime - _dispontime;
// printf("%i %f %f %f %i %i\n",cgamode&1,disptime,dispontime,dispofftime,crtc[0],crtc[1]);
_dispontime *= CGACONST / 2;
_dispofftime *= CGACONST / 2;
// printf("Timings - on %f off %f frame %f second %f\n",dispontime,dispofftime,(dispontime+dispofftime)*262.0,(dispontime+dispofftime)*262.0*59.92);
dispontime = (int)(_dispontime * (1 << TIMER_SHIFT));
dispofftime = (int)(_dispofftime * (1 << TIMER_SHIFT));
m24->dispontime = (int)(_dispontime * (1 << TIMER_SHIFT));
m24->dispofftime = (int)(_dispofftime * (1 << TIMER_SHIFT));
}
static int linepos,displine;
static int sc,vc;
static int cgadispon;
static int con,coff,cursoron,cgablink;
static int vsynctime,vadj;
static int m24_lineff = 0;
static uint16_t ma,maback;
void m24_poll()
void m24_poll(void *p)
{
uint16_t ca=(crtc[15]|(crtc[14]<<8))&0x3FFF;
m24_t *m24 = (m24_t *)p;
uint16_t ca = (m24->crtc[15] | (m24->crtc[14] << 8)) & 0x3fff;
int drawcursor;
int x,c;
int x, c;
int oldvc;
uint8_t chr,attr;
uint16_t dat,dat2;
uint8_t chr, attr;
uint16_t dat, dat2;
int cols[4];
int col;
int oldsc;
if (!linepos)
if (!m24->linepos)
{
// pclog("Line poll %i %i %i %i - %04X %i %i %i\n", m24_lineff, vc, sc, vadj, ma, firstline, lastline, displine);
vidtime+=dispofftime;
cgastat|=1;
linepos=1;
oldsc=sc;
if ((crtc[8]&3)==3) sc=(sc<<1)&7;
if (cgadispon)
m24->vidtime += m24->dispofftime;
m24->stat |= 1;
m24->linepos = 1;
oldsc = m24->sc;
if ((m24->crtc[8] & 3) == 3)
m24->sc = (m24->sc << 1) & 7;
if (m24->dispon)
{
if (displine<firstline)
pclog("dispon %i\n", m24->linepos);
if (m24->displine < m24->firstline)
{
firstline=displine;
m24->firstline = m24->displine;
// printf("Firstline %i\n",firstline);
}
lastline=displine;
for (c=0;c<8;c++)
m24->lastline = m24->displine;
for (c = 0; c < 8; c++)
{
if ((cgamode&0x12)==0x12)
if ((m24->cgamode & 0x12) == 0x12)
{
buffer->line[displine][c]=0;
if (cgamode&1) buffer->line[displine][c+(crtc[1]<<3)+8]=0;
else buffer->line[displine][c+(crtc[1]<<4)+8]=0;
buffer->line[m24->displine][c] = 0;
if (m24->cgamode & 1) buffer->line[m24->displine][c + (m24->crtc[1] << 3) + 8] = 0;
else buffer->line[m24->displine][c + (m24->crtc[1] << 4) + 8] = 0;
}
else
{
buffer->line[displine][c]=(cgacol&15)+16;
if (cgamode&1) buffer->line[displine][c+(crtc[1]<<3)+8]=(cgacol&15)+16;
else buffer->line[displine][c+(crtc[1]<<4)+8]=(cgacol&15)+16;
buffer->line[m24->displine][c] = (m24->cgacol & 15) + 16;
if (m24->cgamode & 1) buffer->line[m24->displine][c + (m24->crtc[1] << 3) + 8] = (m24->cgacol & 15) + 16;
else buffer->line[m24->displine][c + (m24->crtc[1] << 4) + 8] = (m24->cgacol & 15) + 16;
}
}
if (cgamode&1)
if (m24->cgamode & 1)
{
for (x=0;x<crtc[1];x++)
for (x = 0; x < m24->crtc[1]; x++)
{
chr = charbuffer[ x << 1];
attr = charbuffer[(x << 1) + 1];
drawcursor=((ma==ca) && con && cursoron);
if (cgamode&0x20)
chr = m24->charbuffer[ x << 1];
attr = m24->charbuffer[(x << 1) + 1];
drawcursor = ((m24->ma == ca) && m24->con && m24->cursoron);
if (m24->cgamode & 0x20)
{
cols[1]=(attr&15)+16;
cols[0]=((attr>>4)&7)+16;
if ((cgablink&16) && (attr&0x80) && !drawcursor) cols[1]=cols[0];
cols[1] = (attr & 15) + 16;
cols[0] = ((attr >> 4) & 7) + 16;
if ((m24->blink & 16) && (attr & 0x80) && !drawcursor)
cols[1] = cols[0];
}
else
{
cols[1]=(attr&15)+16;
cols[0]=(attr>>4)+16;
cols[1] = (attr & 15) + 16;
cols[0] = (attr >> 4) + 16;
}
if (drawcursor)
{
for (c=0;c<8;c++)
buffer->line[displine][(x<<3)+c+8]=cols[(fontdatm[chr][((sc & 7) << 1) | m24_lineff]&(1<<(c^7)))?1:0]^15;
for (c = 0; c < 8; c++)
buffer->line[m24->displine][(x << 3) + c + 8] = cols[(fontdatm[chr][((m24->sc & 7) << 1) | m24->lineff] & (1 << (c ^ 7))) ? 1 : 0] ^ 15;
}
else
{
for (c=0;c<8;c++)
buffer->line[displine][(x<<3)+c+8]=cols[(fontdatm[chr][((sc & 7) << 1) | m24_lineff]&(1<<(c^7)))?1:0];
for (c = 0; c < 8; c++)
buffer->line[m24->displine][(x << 3) + c + 8] = cols[(fontdatm[chr][((m24->sc & 7) << 1) | m24->lineff] & (1 << (c ^ 7))) ? 1 : 0];
}
ma++;
m24->ma++;
}
}
else if (!(cgamode&2))
else if (!(m24->cgamode & 2))
{
for (x=0;x<crtc[1];x++)
for (x = 0; x < m24->crtc[1]; x++)
{
chr=vram[((ma<<1)&0x3FFF) + m24_base];
attr=vram[(((ma<<1)+1)&0x3FFF) + m24_base];
drawcursor=((ma==ca) && con && cursoron);
if (cgamode&0x20)
chr = m24->vram[((m24->ma << 1) & 0x3fff) + m24->base];
attr = m24->vram[(((m24->ma << 1) + 1) & 0x3fff) + m24->base];
drawcursor = ((m24->ma == ca) && m24->con && m24->cursoron);
if (m24->cgamode & 0x20)
{
cols[1]=(attr&15)+16;
cols[0]=((attr>>4)&7)+16;
if ((cgablink&16) && (attr&0x80)) cols[1]=cols[0];
cols[1] = (attr & 15) + 16;
cols[0] = ((attr >> 4) & 7) + 16;
if ((m24->blink & 16) && (attr & 0x80))
cols[1] = cols[0];
}
else
{
cols[1]=(attr&15)+16;
cols[0]=(attr>>4)+16;
cols[1] = (attr & 15) + 16;
cols[0] = (attr >> 4) + 16;
}
ma++;
m24->ma++;
if (drawcursor)
{
for (c=0;c<8;c++)
buffer->line[displine][(x<<4)+(c<<1)+8]=buffer->line[displine][(x<<4)+(c<<1)+1+8]=cols[(fontdatm[chr][((sc & 7) << 1) | m24_lineff]&(1<<(c^7)))?1:0]^15;
for (c = 0; c < 8; c++)
buffer->line[m24->displine][(x << 4) + (c << 1) + 8] =
buffer->line[m24->displine][(x << 4) + (c << 1) + 1 + 8] = cols[(fontdatm[chr][((m24->sc & 7) << 1) | m24->lineff] & (1 << (c ^ 7))) ? 1 : 0] ^ 15;
}
else
{
for (c=0;c<8;c++)
buffer->line[displine][(x<<4)+(c<<1)+8]=buffer->line[displine][(x<<4)+(c<<1)+1+8]=cols[(fontdatm[chr][((sc & 7) << 1) | m24_lineff]&(1<<(c^7)))?1:0];
for (c = 0; c < 8; c++)
buffer->line[m24->displine][(x << 4) + (c << 1) + 8] =
buffer->line[m24->displine][(x << 4) + (c << 1) + 1 + 8] = cols[(fontdatm[chr][((m24->sc & 7) << 1) | m24->lineff] & (1 << (c ^ 7))) ? 1 : 0];
}
}
}
else if (!(cgamode&16))
else if (!(m24->cgamode & 16))
{
cols[0]=(cgacol&15)|16;
col=(cgacol&16)?24:16;
if (cgamode&4)
cols[0] = (m24->cgacol & 15) | 16;
col = (m24->cgacol & 16) ? 24 : 16;
if (m24->cgamode & 4)
{
cols[1]=col|3;
cols[2]=col|4;
cols[3]=col|7;
cols[1] = col | 3;
cols[2] = col | 4;
cols[3] = col | 7;
}
else if (cgacol&32)
else if (m24->cgacol & 32)
{
cols[1]=col|3;
cols[2]=col|5;
cols[3]=col|7;
cols[1] = col | 3;
cols[2] = col | 5;
cols[3] = col | 7;
}
else
{
cols[1]=col|2;
cols[2]=col|4;
cols[3]=col|6;
cols[1] = col | 2;
cols[2] = col | 4;
cols[3] = col | 6;
}
for (x=0;x<crtc[1];x++)
for (x = 0; x < m24->crtc[1]; x++)
{
dat=(vram[((ma<<1)&0x1FFF)+((sc&1)*0x2000) + m24_base]<<8)|vram[((ma<<1)&0x1FFF)+((sc&1)*0x2000)+1 + m24_base];
ma++;
for (c=0;c<8;c++)
dat = (m24->vram[((m24->ma << 1) & 0x1fff) + ((m24->sc & 1) * 0x2000) + m24->base] << 8) |
m24->vram[((m24->ma << 1) & 0x1fff) + ((m24->sc & 1) * 0x2000) + 1 + m24->base];
m24->ma++;
for (c = 0; c < 8; c++)
{
buffer->line[displine][(x<<4)+(c<<1)+8]=
buffer->line[displine][(x<<4)+(c<<1)+1+8]=cols[dat>>14];
dat<<=2;
buffer->line[m24->displine][(x << 4) + (c << 1) + 8] =
buffer->line[m24->displine][(x << 4) + (c << 1) + 1 + 8] = cols[dat >> 14];
dat <<= 2;
}
}
}
else
{
if (m24_ctrl & 1)
if (m24->ctrl & 1)
{
dat2 = ((sc & 1) * 0x4000) | (m24_lineff * 0x2000);
cols[0]=0; cols[1]=/*(cgacol&15)*/15+16;
dat2 = ((m24->sc & 1) * 0x4000) | (m24->lineff * 0x2000);
cols[0] = 0; cols[1] = /*(m24->cgacol & 15)*/15 + 16;
}
else
{
dat2 = (sc & 1) * 0x2000;
cols[0]=0; cols[1]=(cgacol&15)+16;
dat2 = (m24->sc & 1) * 0x2000;
cols[0] = 0; cols[1] = (m24->cgacol & 15) + 16;
}
for (x=0;x<crtc[1];x++)
for (x = 0; x < m24->crtc[1]; x++)
{
dat=(vram[((ma<<1)&0x1FFF) + dat2]<<8) | vram[((ma<<1)&0x1FFF) + dat2 + 1];
ma++;
for (c=0;c<16;c++)
dat = (m24->vram[((m24->ma << 1) & 0x1fff) + dat2] << 8) | m24->vram[((m24->ma << 1) & 0x1fff) + dat2 + 1];
m24->ma++;
for (c = 0; c < 16; c++)
{
buffer->line[displine][(x<<4)+c+8]=cols[dat>>15];
dat<<=1;
buffer->line[m24->displine][(x << 4) + c + 8] = cols[dat >> 15];
dat <<= 1;
}
}
}
}
else
{
cols[0]=((cgamode&0x12)==0x12)?0:(cgacol&15)+16;
if (cgamode&1) hline(buffer,0,displine,(crtc[1]<<3)+16,cols[0]);
else hline(buffer,0,displine,(crtc[1]<<4)+16,cols[0]);
cols[0] = ((m24->cgamode & 0x12) == 0x12) ? 0 : (m24->cgacol & 15) + 16;
if (m24->cgamode & 1) hline(buffer, 0, m24->displine, (m24->crtc[1] << 3) + 16, cols[0]);
else hline(buffer, 0, m24->displine, (m24->crtc[1] << 4) + 16, cols[0]);
}
if (cgamode&1) x=(crtc[1]<<3)+16;
else x=(crtc[1]<<4)+16;
if (m24->cgamode & 1) x = (m24->crtc[1] << 3) + 16;
else x = (m24->crtc[1] << 4) + 16;
sc=oldsc;
if (vc==crtc[7] && !sc)
cgastat|=8;
displine++;
if (displine>=720) displine=0;
m24->sc = oldsc;
if (m24->vc == m24->crtc[7] && !m24->sc)
m24->stat |= 8;
m24->displine++;
if (m24->displine >= 720) m24->displine = 0;
}
else
{
// pclog("Line poll %i %i %i %i\n", m24_lineff, vc, sc, vadj);
vidtime+=dispontime;
if (cgadispon) cgastat&=~1;
linepos=0;
m24_lineff ^= 1;
if (m24_lineff)
m24->vidtime += m24->dispontime;
if (m24->dispon) m24->stat &= ~1;
m24->linepos = 0;
m24->lineff ^= 1;
if (m24->lineff)
{
ma = maback;
m24->ma = m24->maback;
}
else
{
if (vsynctime)
if (m24->vsynctime)
{
vsynctime--;
if (!vsynctime)
cgastat&=~8;
m24->vsynctime--;
if (!m24->vsynctime)
m24->stat &= ~8;
}
if (sc==(crtc[11]&31) || ((crtc[8]&3)==3 && sc==((crtc[11]&31)>>1))) { con=0; coff=1; }
if (vadj)
if (m24->sc == (m24->crtc[11] & 31) || ((m24->crtc[8] & 3) == 3 && m24->sc == ((m24->crtc[11] & 31) >> 1)))
{
m24->con = 0;
m24->coff = 1;
}
if (m24->vadj)
{
sc++;
sc&=31;
ma=maback;
vadj--;
if (!vadj)
m24->sc++;
m24->sc &= 31;
m24->ma = m24->maback;
m24->vadj--;
if (!m24->vadj)
{
cgadispon=1;
ma=maback=(crtc[13]|(crtc[12]<<8))&0x3FFF;
sc=0;
m24->dispon = 1;
m24->ma = m24->maback = (m24->crtc[13] | (m24->crtc[12] << 8)) & 0x3fff;
m24->sc = 0;
}
}
else if (sc==crtc[9] || ((crtc[8]&3)==3 && sc==(crtc[9]>>1)))
else if (m24->sc == m24->crtc[9] || ((m24->crtc[8] & 3) == 3 && m24->sc == (m24->crtc[9] >> 1)))
{
maback=ma;
sc=0;
oldvc=vc;
vc++;
vc&=127;
m24->maback = m24->ma;
m24->sc = 0;
oldvc = m24->vc;
m24->vc++;
m24->vc &= 127;
if (vc==crtc[6])
cgadispon=0;
if (m24->vc == m24->crtc[6])
m24->dispon=0;
if (oldvc==crtc[4])
if (oldvc == m24->crtc[4])
{
vc=0;
vadj=crtc[5];
if (!vadj) cgadispon=1;
if (!vadj) ma=maback=(crtc[13]|(crtc[12]<<8))&0x3FFF;
if ((crtc[10]&0x60)==0x20) cursoron=0;
else cursoron=cgablink&16;
m24->vc = 0;
m24->vadj = m24->crtc[5];
if (!m24->vadj) m24->dispon = 1;
if (!m24->vadj) m24->ma = m24->maback = (m24->crtc[13] | (m24->crtc[12] << 8)) & 0x3fff;
if ((m24->crtc[10] & 0x60) == 0x20) m24->cursoron = 0;
else m24->cursoron = m24->blink & 16;
}
if (vc==crtc[7])
if (m24->vc == m24->crtc[7])
{
cgadispon=0;
displine=0;
vsynctime=(crtc[3]>>4)+1;
if (crtc[7])
m24->dispon = 0;
m24->displine = 0;
m24->vsynctime = (m24->crtc[3] >> 4) + 1;
if (m24->crtc[7])
{
if (cgamode&1) x=(crtc[1]<<3)+16;
else x=(crtc[1]<<4)+16;
lastline++;
if (x!=xsize || (lastline-firstline)!=ysize)
if (m24->cgamode & 1) x = (m24->crtc[1] << 3) + 16;
else x = (m24->crtc[1] << 4) + 16;
m24->lastline++;
if (x != xsize || (m24->lastline - m24->firstline) != ysize)
{
xsize=x;
ysize=lastline-firstline;
if (xsize<64) xsize=656;
if (ysize<32) ysize=200;
xsize = x;
ysize = m24->lastline - m24->firstline;
if (xsize < 64) xsize = 656;
if (ysize < 32) ysize = 200;
updatewindowsize(xsize, ysize + 16);
}
startblit();
video_blit_memtoscreen_8(0, firstline - 8, xsize, (lastline - firstline) + 16);
if (readflash) rectfill(screen,winsizex-40,8,winsizex-8,14,0xFFFFFFFF);
readflash=0;
pclog("m24 blit %i %i\n", m24->firstline, m24->lastline);
video_blit_memtoscreen_8(0, m24->firstline - 8, xsize, (m24->lastline - m24->firstline) + 16);
if (readflash) rectfill(screen, winsizex - 40, 8, winsizex - 8, 14, 0xFFFFFFFF);
readflash = 0;
frames++;
endblit();
video_res_x = xsize - 16;
video_res_y = ysize;
if (cgamode & 1)
if (m24->cgamode & 1)
{
video_res_x /= 8;
video_res_y /= (crtc[9] + 1) * 2;
video_res_y /= (m24->crtc[9] + 1) * 2;
video_bpp = 0;
}
else if (!(cgamode & 2))
else if (!(m24->cgamode & 2))
{
video_res_x /= 16;
video_res_y /= (crtc[9] + 1) * 2;
video_res_y /= (m24->crtc[9] + 1) * 2;
video_bpp = 0;
}
else if (!(cgamode&16))
else if (!(m24->cgamode & 16))
{
video_res_x /= 2;
video_res_y /= 2;
video_bpp = 2;
}
else if (!(m24_ctrl & 1))
else if (!(m24->ctrl & 1))
{
video_res_y /= 2;
video_bpp = 1;
}
}
firstline=1000;
lastline=0;
cgablink++;
m24->firstline = 1000;
m24->lastline = 0;
m24->blink++;
}
}
else
{
sc++;
sc&=31;
ma=maback;
m24->sc++;
m24->sc &= 31;
m24->ma = m24->maback;
}
if ((sc==(crtc[10]&31) || ((crtc[8]&3)==3 && sc==((crtc[10]&31)>>1)))) con=1;
if ((m24->sc == (m24->crtc[10] & 31) || ((m24->crtc[8] & 3) == 3 && m24->sc == ((m24->crtc[10] & 31) >> 1))))
m24->con = 1;
}
if (cgadispon && (cgamode&1))
if (m24->dispon && (m24->cgamode & 1))
{
for (x=0;x<(crtc[1]<<1);x++)
charbuffer[x]=vram[(((ma<<1)+x)&0x3FFF) + m24_base];
for (x = 0; x < (m24->crtc[1] << 1); x++)
m24->charbuffer[x] = m24->vram[(((m24->ma << 1) + x) & 0x3fff) + m24->base];
}
}
}
int m24_init()
void *m24_init()
{
mem_sethandler(0xb8000, 0x08000, m24_read, NULL, NULL, m24_write, NULL, NULL, NULL);
return 0;
int c;
m24_t *m24 = malloc(sizeof(m24_t));
memset(m24, 0, sizeof(m24_t));
m24->vram = malloc(0x8000);
timer_add(m24_poll, &m24->vidtime, TIMER_ALWAYS_ENABLED, m24);
mem_sethandler(0xb8000, 0x08000, m24_read, NULL, NULL, m24_write, NULL, NULL, m24);
io_sethandler(0x03d0, 0x0010, m24_in, NULL, NULL, m24_out, NULL, NULL, m24);
return m24;
}
GFXCARD vid_m24 =
void m24_close(void *p)
{
m24_t *m24 = (m24_t *)p;
free(m24->vram);
free(m24);
}
void m24_speed_changed(void *p)
{
m24_t *m24 = (m24_t *)p;
m24_recalctimings(m24);
}
device_t m24_device =
{
"Olivetti M24 (video)",
m24_init,
/*IO at 3Cx/3Dx*/
m24_out,
m24_in,
/*IO at 3Ax/3Bx*/
video_out_null,
video_in_null,
m24_poll,
m24_recalctimings,
video_write_null,
video_write_null,
m24_write,
video_read_null,
video_read_null,
m24_read
m24_close,
m24_speed_changed,
NULL
};

View file

@ -0,0 +1 @@
extern device_t m24_device;

View file

@ -1,126 +1,151 @@
/*Oak OTI067 emulation*/
#include <stdlib.h>
#include "ibm.h"
#include "device.h"
#include "io.h"
#include "video.h"
#include "vid_oti067.h"
#include "vid_svga.h"
static int oti067_index;
static uint8_t oti067_regs[32];
void oti067_out(uint16_t addr, uint8_t val, void *priv)
typedef struct oti067_t
{
svga_t svga;
int index;
uint8_t regs[32];
} oti067_t;
void oti067_out(uint16_t addr, uint8_t val, void *p)
{
oti067_t *oti067 = (oti067_t *)p;
svga_t *svga = &oti067->svga;
uint8_t old;
// pclog("oti067_out : %04X %02X %02X %i\n", addr, val, ram[0x489], ins);
if ((((addr&0xFFF0) == 0x3D0 || (addr&0xFFF0) == 0x3B0) && addr < 0x3de) && !(svga_miscout&1)) addr ^= 0x60;
if ((((addr&0xFFF0) == 0x3D0 || (addr&0xFFF0) == 0x3B0) && addr < 0x3de) && !(svga->miscout & 1)) addr ^= 0x60;
switch (addr)
{
case 0x3D4:
crtcreg=val&31;
svga->crtcreg = val & 31;
return;
case 0x3D5:
if (crtcreg <= 7 && crtc[0x11] & 0x80) return;
old=crtc[crtcreg];
crtc[crtcreg]=val;
if (old!=val)
if (svga->crtcreg <= 7 && svga->crtc[0x11] & 0x80) return;
old = svga->crtc[svga->crtcreg];
svga->crtc[svga->crtcreg] = val;
if (old != val)
{
if (crtcreg<0xE || crtcreg>0x10)
if (svga->crtcreg < 0xE || svga->crtcreg > 0x10)
{
fullchange=changeframecount;
svga_recalctimings();
fullchange = changeframecount;
svga_recalctimings(svga);
}
}
break;
case 0x3DE: oti067_index=val&0x1F; return;
case 0x3DE:
oti067->index = val & 0x1f;
return;
case 0x3DF:
oti067_regs[oti067_index]=val;
switch (oti067_index)
oti067->regs[oti067->index] = val;
switch (oti067->index)
{
case 0xD:
vrammask=(val&0xC)?0x7FFFF:0x3FFFF;
svga->vrammask = (val & 0xc) ? 0x7ffff : 0x3ffff;
break;
case 0x11:
svgarbank=(val&0xF)*65536;
svgawbank=(val>>4)*65536;
svga->read_bank = (val & 0xf) * 65536;
svga->write_bank = (val >> 4) * 65536;
break;
}
return;
}
svga_out(addr, val, NULL);
svga_out(addr, val, svga);
}
uint8_t oti067_in(uint16_t addr, void *priv)
uint8_t oti067_in(uint16_t addr, void *p)
{
oti067_t *oti067 = (oti067_t *)p;
svga_t *svga = &oti067->svga;
uint8_t temp;
// if (addr != 0x3da && addr != 0x3ba) pclog("oti067_in : %04X ", addr);
if ((((addr&0xFFF0) == 0x3D0 || (addr&0xFFF0) == 0x3B0) && addr < 0x3de) && !(svga_miscout&1)) addr ^= 0x60;
if ((((addr&0xFFF0) == 0x3D0 || (addr&0xFFF0) == 0x3B0) && addr < 0x3de) && !(svga->miscout & 1)) addr ^= 0x60;
switch (addr)
{
case 0x3D4:
temp = crtcreg;
temp = svga->crtcreg;
break;
case 0x3D5:
temp = crtc[crtcreg];
temp = svga->crtc[svga->crtcreg];
break;
case 0x3DE:
temp = oti067_index|(2<<5);
temp = oti067->index | (2 << 5);
break;
case 0x3DF:
if (oti067_index==0x10) temp = 0x18;
else if (oti067_index==0xD) temp = oti067_regs[oti067_index]|0xC0;
else temp = oti067_regs[oti067_index];
if (oti067->index==0x10) temp = 0x18;
else if (oti067->index==0xD) temp = oti067->regs[oti067->index]|0xC0;
else temp = oti067->regs[oti067->index];
break;
default:
temp = svga_in(addr, NULL);
temp = svga_in(addr, svga);
break;
}
// if (addr != 0x3da && addr != 0x3ba) pclog("%02X %04X:%04X\n", temp, CS,pc);
return temp;
}
void oti067_recalctimings()
void oti067_recalctimings(svga_t *svga)
{
if (oti067_regs[0x14]&0x08) svga_ma|=0x10000;
if (oti067_regs[0x0D]&0x0C) svga_rowoffset<<=1;
svga_interlace = oti067_regs[0x14]&0x80;
oti067_t *oti067 = (oti067_t *)svga->p;
if (oti067->regs[0x14] & 0x08) svga->ma_latch |= 0x10000;
if (oti067->regs[0x0d] & 0x0c) svga->rowoffset <<= 1;
svga->interlace = oti067->regs[0x14] & 0x80;
}
int oti067_init()
void *oti067_init()
{
svga_recalctimings_ex = oti067_recalctimings;
svga_vram_limit = 1 << 19; /*512kb*/
vrammask = 0x7ffff;
bpp = 8;
svga_miscout = 1;
return svga_init();
oti067_t *oti067 = malloc(sizeof(oti067_t));
memset(oti067, 0, sizeof(oti067_t));
svga_init(&oti067->svga, oti067, 1 << 19, /*512kb*/
oti067_recalctimings,
oti067_in, oti067_out,
NULL);
io_sethandler(0x03c0, 0x0020, oti067_in, NULL, NULL, oti067_out, NULL, NULL, oti067);
oti067->svga.miscout = 1;
return oti067;
}
GFXCARD vid_oti067 =
void oti067_close(void *p)
{
oti067_t *oti067 = (oti067_t *)p;
svga_close(&oti067->svga);
free(oti067);
}
void oti067_speed_changed(void *p)
{
oti067_t *oti067 = (oti067_t *)p;
svga_recalctimings(&oti067->svga);
}
device_t oti067_device =
{
"Oak OTI-067",
oti067_init,
/*IO at 3Cx/3Dx*/
oti067_out,
oti067_in,
/*IO at 3Ax/3Bx*/
video_out_null,
video_in_null,
svga_poll,
svga_recalctimings,
svga_write,
video_write_null,
video_write_null,
svga_read,
video_read_null,
video_read_null
oti067_close,
oti067_speed_changed,
svga_add_status_info
};

1
src/vid_oti067.h Normal file
View file

@ -0,0 +1 @@
extern device_t oti067_device;

View file

@ -3,271 +3,335 @@
PC2086, PC3086 use PVGA1A
MegaPC uses W90C11A
*/
#include <stdlib.h>
#include "ibm.h"
#include "device.h"
#include "mem.h"
#include "video.h"
#include "vid_paradise.h"
#include "vid_svga.h"
#include "vid_svga_render.h"
#include "vid_unk_ramdac.h"
void paradise_write(uint32_t addr, uint8_t val, void *priv);
uint8_t paradise_read(uint32_t addr, void *priv);
void paradise_remap();
enum
typedef struct paradise_t
{
PVGA1A = 0,
WD90C11
};
svga_t svga;
enum
{
PVGA1A = 0,
WD90C11
} type;
static int paradise_type;
uint32_t read_bank[4], write_bank[4];
} paradise_t;
static uint32_t paradise_bank_r[4], paradise_bank_w[4];
void paradise_write(uint32_t addr, uint8_t val, void *p);
uint8_t paradise_read(uint32_t addr, void *p);
void paradise_remap(paradise_t *paradise);
void paradise_out(uint16_t addr, uint8_t val, void *priv)
void paradise_out(uint16_t addr, uint8_t val, void *p)
{
paradise_t *paradise = (paradise_t *)p;
svga_t *svga = &paradise->svga;
uint8_t old;
if (((addr&0xFFF0) == 0x3D0 || (addr&0xFFF0) == 0x3B0) && !(svga_miscout&1)) addr ^= 0x60;
if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(svga->miscout & 1))
addr ^= 0x60;
// output = 3;
pclog("Paradise out %04X %02X %04X:%04X\n", addr, val, CS, pc);
switch (addr)
{
case 0x3c5:
if (seqaddr > 7)
if (svga->seqaddr > 7)
{
if (paradise_type < WD90C11 || seqregs[6] != 0x48)
if (paradise->type < WD90C11 || svga->seqregs[6] != 0x48)
return;
seqregs[seqaddr & 0x1f] = val;
if (seqaddr == 0x11)
paradise_remap();
svga->seqregs[svga->seqaddr & 0x1f] = val;
if (svga->seqaddr == 0x11)
paradise_remap(paradise);
return;
}
break;
case 0x3cf:
if (gdcaddr >= 0x9 && gdcaddr < 0xf)
if (svga->gdcaddr >= 0x9 && svga->gdcaddr < 0xf)
{
if ((gdcreg[0xf] & 7) != 5)
if ((svga->gdcreg[0xf] & 7) != 5)
return;
}
if (gdcaddr == 6)
if (svga->gdcaddr == 6)
{
if ((gdcreg[6] & 0xc) != (val & 0xc))
if ((svga->gdcreg[6] & 0xc) != (val & 0xc))
{
mem_removehandler(0xa0000, 0x20000, paradise_read, NULL, NULL, paradise_write, NULL, NULL, NULL);
mem_removehandler(0xa0000, 0x20000, paradise_read, NULL, NULL, paradise_write, NULL, NULL, paradise);
// pclog("Write mapping %02X\n", val);
switch (val&0xC)
{
case 0x0: /*128k at A0000*/
mem_sethandler(0xa0000, 0x20000, paradise_read, NULL, NULL, paradise_write, NULL, NULL, NULL);
mem_sethandler(0xa0000, 0x20000, paradise_read, NULL, NULL, paradise_write, NULL, NULL, paradise);
break;
case 0x4: /*64k at A0000*/
mem_sethandler(0xa0000, 0x10000, paradise_read, NULL, NULL, paradise_write, NULL, NULL, NULL);
mem_sethandler(0xa0000, 0x10000, paradise_read, NULL, NULL, paradise_write, NULL, NULL, paradise);
break;
case 0x8: /*32k at B0000*/
mem_sethandler(0xb0000, 0x08000, paradise_read, NULL, NULL, paradise_write, NULL, NULL, NULL);
mem_sethandler(0xb0000, 0x08000, paradise_read, NULL, NULL, paradise_write, NULL, NULL, paradise);
break;
case 0xC: /*32k at B8000*/
mem_sethandler(0xb8000, 0x08000, paradise_read, NULL, NULL, paradise_write, NULL, NULL, NULL);
mem_sethandler(0xb8000, 0x08000, paradise_read, NULL, NULL, paradise_write, NULL, NULL, paradise);
break;
}
}
gdcreg[6] = val;
paradise_remap();
svga->gdcreg[6] = val;
paradise_remap(paradise);
return;
}
if (gdcaddr == 0x9 || gdcaddr == 0xa)
if (svga->gdcaddr == 0x9 || svga->gdcaddr == 0xa)
{
gdcreg[gdcaddr] = val;
paradise_remap();
svga->gdcreg[svga->gdcaddr] = val;
paradise_remap(paradise);
return;
}
if (gdcaddr == 0xe)
if (svga->gdcaddr == 0xe)
{
gdcreg[0xe] = val;
paradise_remap();
svga->gdcreg[0xe] = val;
paradise_remap(paradise);
return;
}
break;
case 0x3D4:
if (paradise_type == PVGA1A)
crtcreg = val & 0x1f;
if (paradise->type == PVGA1A)
svga->crtcreg = val & 0x1f;
else
crtcreg = val & 0x3f;
svga->crtcreg = val & 0x3f;
return;
case 0x3D5:
if (crtcreg <= 7 && crtc[0x11] & 0x80)
if (svga->crtcreg <= 7 && svga->crtc[0x11] & 0x80)
return;
if (crtcreg > 0x29 && (crtc[0x29] & 7) != 5)
if (svga->crtcreg > 0x29 && (svga->crtc[0x29] & 7) != 5)
return;
if (crtcreg >= 0x31 && crtcreg <= 0x37)
if (svga->crtcreg >= 0x31 && svga->crtcreg <= 0x37)
return;
old=crtc[crtcreg];
crtc[crtcreg]=val;
old = svga->crtc[svga->crtcreg];
svga->crtc[svga->crtcreg] = val;
if (old!=val)
if (old != val)
{
if (crtcreg<0xE || crtcreg>0x10)
if (svga->crtcreg < 0xe || svga->crtcreg > 0x10)
{
fullchange=changeframecount;
svga_recalctimings();
fullchange = changeframecount;
svga_recalctimings(&paradise->svga);
}
}
break;
}
svga_out(addr, val, NULL);
svga_out(addr, val, svga);
}
uint8_t paradise_in(uint16_t addr, void *priv)
uint8_t paradise_in(uint16_t addr, void *p)
{
if (((addr&0xFFF0) == 0x3D0 || (addr&0xFFF0) == 0x3B0) && !(svga_miscout&1)) addr ^= 0x60;
paradise_t *paradise = (paradise_t *)p;
svga_t *svga = &paradise->svga;
// if (addr != 0x3da) pclog("Paradise in %04X\n", addr);
if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(svga->miscout & 1))
addr ^= 0x60;
if (addr != 0x3da) pclog("Paradise in %04X\n", addr);
switch (addr)
{
case 0x3c2:
return 0x10;
case 0x3c5:
if (seqaddr > 7)
if (svga->seqaddr > 7)
{
if (paradise_type < WD90C11 || seqregs[6] != 0x48)
if (paradise->type < WD90C11 || svga->seqregs[6] != 0x48)
return 0xff;
if (seqaddr > 0x12)
if (svga->seqaddr > 0x12)
return 0xff;
return seqregs[seqaddr & 0x1f];
return svga->seqregs[svga->seqaddr & 0x1f];
}
break;
case 0x3cf:
if (gdcaddr >= 0x9 && gdcaddr < 0xf)
if (svga->gdcaddr >= 0x9 && svga->gdcaddr < 0xf)
{
if (gdcreg[0xf] & 0x10)
if (svga->gdcreg[0xf] & 0x10)
return 0xff;
switch (gdcaddr)
switch (svga->gdcaddr)
{
case 0xf:
return (gdcreg[0xf] & 0x17) | 0x80;
return (svga->gdcreg[0xf] & 0x17) | 0x80;
}
}
break;
case 0x3D4:
return crtcreg;
return svga->crtcreg;
case 0x3D5:
if (crtcreg > 0x29 && crtcreg < 0x30 && (crtc[0x29] & 0x88) != 0x80)
if (svga->crtcreg > 0x29 && svga->crtcreg < 0x30 && (svga->crtc[0x29] & 0x88) != 0x80)
return 0xff;
return crtc[crtcreg];
return svga->crtc[svga->crtcreg];
}
return svga_in(addr, NULL);
return svga_in(addr, svga);
}
void paradise_remap()
void paradise_remap(paradise_t *paradise)
{
if (seqregs[0x11] & 0x80)
svga_t *svga = &paradise->svga;
if (svga->seqregs[0x11] & 0x80)
{
// pclog("Remap 1\n");
paradise_bank_r[0] = paradise_bank_r[2] = (gdcreg[0x9] & 0x7f) << 12;
paradise_bank_r[1] = paradise_bank_r[3] = ((gdcreg[0x9] & 0x7f) << 12) + ((gdcreg[6] & 0x08) ? 0 : 0x8000);
paradise_bank_w[0] = paradise_bank_w[2] = (gdcreg[0xa] & 0x7f) << 12;
paradise_bank_w[1] = paradise_bank_w[3] = ((gdcreg[0xa] & 0x7f) << 12) + ((gdcreg[6] & 0x08) ? 0 : 0x8000);
paradise->read_bank[0] = paradise->read_bank[2] = (svga->gdcreg[0x9] & 0x7f) << 12;
paradise->read_bank[1] = paradise->read_bank[3] = ((svga->gdcreg[0x9] & 0x7f) << 12) + ((svga->gdcreg[6] & 0x08) ? 0 : 0x8000);
paradise->write_bank[0] = paradise->write_bank[2] = (svga->gdcreg[0xa] & 0x7f) << 12;
paradise->write_bank[1] = paradise->write_bank[3] = ((svga->gdcreg[0xa] & 0x7f) << 12) + ((svga->gdcreg[6] & 0x08) ? 0 : 0x8000);
}
else if (gdcreg[0xe] & 0x08)
else if (svga->gdcreg[0xe] & 0x08)
{
if (gdcreg[0x6] & 0xc)
if (svga->gdcreg[0x6] & 0xc)
{
// pclog("Remap 2\n");
paradise_bank_r[0] = paradise_bank_r[2] = (gdcreg[0xa] & 0x7f) << 12;
paradise_bank_w[0] = paradise_bank_w[2] = (gdcreg[0xa] & 0x7f) << 12;
paradise_bank_r[1] = paradise_bank_r[3] = ((gdcreg[0x9] & 0x7f) << 12) + ((gdcreg[6] & 0x08) ? 0 : 0x8000);
paradise_bank_w[1] = paradise_bank_w[3] = ((gdcreg[0x9] & 0x7f) << 12) + ((gdcreg[6] & 0x08) ? 0 : 0x8000);
paradise->read_bank[0] = paradise->read_bank[2] = (svga->gdcreg[0xa] & 0x7f) << 12;
paradise->write_bank[0] = paradise->write_bank[2] = (svga->gdcreg[0xa] & 0x7f) << 12;
paradise->read_bank[1] = paradise->read_bank[3] = ((svga->gdcreg[0x9] & 0x7f) << 12) + ((svga->gdcreg[6] & 0x08) ? 0 : 0x8000);
paradise->write_bank[1] = paradise->write_bank[3] = ((svga->gdcreg[0x9] & 0x7f) << 12) + ((svga->gdcreg[6] & 0x08) ? 0 : 0x8000);
}
else
{
// pclog("Remap 3\n");
paradise_bank_r[0] = paradise_bank_w[0] = (gdcreg[0xa] & 0x7f) << 12;
paradise_bank_r[1] = paradise_bank_w[1] = ((gdcreg[0xa] & 0x7f) << 12) + ((gdcreg[6] & 0x08) ? 0 : 0x8000);
paradise_bank_r[2] = paradise_bank_w[2] = (gdcreg[0x9] & 0x7f) << 12;
paradise_bank_r[3] = paradise_bank_w[3] = ((gdcreg[0x9] & 0x7f) << 12) + ((gdcreg[6] & 0x08) ? 0 : 0x8000);
paradise->read_bank[0] = paradise->write_bank[0] = (svga->gdcreg[0xa] & 0x7f) << 12;
paradise->read_bank[1] = paradise->write_bank[1] = ((svga->gdcreg[0xa] & 0x7f) << 12) + ((svga->gdcreg[6] & 0x08) ? 0 : 0x8000);
paradise->read_bank[2] = paradise->write_bank[2] = (svga->gdcreg[0x9] & 0x7f) << 12;
paradise->read_bank[3] = paradise->write_bank[3] = ((svga->gdcreg[0x9] & 0x7f) << 12) + ((svga->gdcreg[6] & 0x08) ? 0 : 0x8000);
}
}
else
{
// pclog("Remap 4\n");
paradise_bank_r[0] = paradise_bank_r[2] = (gdcreg[0x9] & 0x7f) << 12;
paradise_bank_r[1] = paradise_bank_r[3] = ((gdcreg[0x9] & 0x7f) << 12) + ((gdcreg[6] & 0x08) ? 0 : 0x8000);
paradise_bank_w[0] = paradise_bank_w[2] = (gdcreg[0x9] & 0x7f) << 12;
paradise_bank_w[1] = paradise_bank_w[3] = ((gdcreg[0x9] & 0x7f) << 12) + ((gdcreg[6] & 0x08) ? 0 : 0x8000);
paradise->read_bank[0] = paradise->read_bank[2] = (svga->gdcreg[0x9] & 0x7f) << 12;
paradise->read_bank[1] = paradise->read_bank[3] = ((svga->gdcreg[0x9] & 0x7f) << 12) + ((svga->gdcreg[6] & 0x08) ? 0 : 0x8000);
paradise->write_bank[0] = paradise->write_bank[2] = (svga->gdcreg[0x9] & 0x7f) << 12;
paradise->write_bank[1] = paradise->write_bank[3] = ((svga->gdcreg[0x9] & 0x7f) << 12) + ((svga->gdcreg[6] & 0x08) ? 0 : 0x8000);
}
// pclog("Remap - %04X %04X\n", paradise_bank_r[0], paradise_bank_w[0]);
// pclog("Remap - %04X %04X\n", paradise->read_bank[0], paradise->write_bank[0]);
}
void paradise_recalctimings()
void paradise_recalctimings(svga_t *svga)
{
svga_lowres = !(gdcreg[0xe] & 0x01);
svga->lowres = !(svga->gdcreg[0xe] & 0x01);
if (svga->bpp == 8 && !svga->lowres)
svga->render = svga_render_8bpp_highres;
}
#define egacycles 1
#define egacycles2 1
void paradise_write(uint32_t addr, uint8_t val, void *priv)
void paradise_write(uint32_t addr, uint8_t val, void *p)
{
paradise_t *paradise = (paradise_t *)p;
// pclog("paradise_write : %05X %02X ", addr, val);
addr = (addr & 0x7fff) + paradise_bank_w[(addr >> 15) & 3];
addr = (addr & 0x7fff) + paradise->write_bank[(addr >> 15) & 3];
// pclog("%08X\n", addr);
svga_write_linear(addr, val, priv);
svga_write_linear(addr, val, &paradise->svga);
}
uint8_t paradise_read(uint32_t addr, void *priv)
uint8_t paradise_read(uint32_t addr, void *p)
{
paradise_t *paradise = (paradise_t *)p;
// pclog("paradise_read : %05X ", addr);
addr = (addr & 0x7fff) + paradise_bank_r[(addr >> 15) & 3];
addr = (addr & 0x7fff) + paradise->read_bank[(addr >> 15) & 3];
// pclog("%08X\n", addr);
return svga_read_linear(addr, priv);
return svga_read_linear(addr, &paradise->svga);
}
int paradise_init()
void *paradise_pvga1a_init()
{
if (romset == ROM_PC2086 || romset == ROM_PC3086)
{
paradise_type = PVGA1A;
vrammask = 0x3ffff;
pclog("Init PVGA1A\n");
svga_vram_limit = 1 << 18; /*256kb*/
}
if (romset == ROM_MEGAPC)
{
paradise_type = WD90C11;
vrammask = 0x7ffff;
crtc[0x36] = '1';
crtc[0x37] = '1';
pclog("Init WD90C11\n");
svga_vram_limit = 1 << 19; /*512kb*/
}
crtc[0x31] = 'W';
crtc[0x32] = 'D';
crtc[0x33] = '9';
crtc[0x34] = '0';
crtc[0x35] = 'C';
svga_recalctimings_ex = paradise_recalctimings;
return svga_init();
paradise_t *paradise = malloc(sizeof(paradise_t));
svga_t *svga = &paradise->svga;
memset(paradise, 0, sizeof(paradise_t));
io_sethandler(0x03c0, 0x0020, paradise_in, NULL, NULL, paradise_out, NULL, NULL, paradise);
svga_init(&paradise->svga, paradise, 1 << 18, /*256kb*/
NULL,
paradise_in, paradise_out,
NULL);
svga->crtc[0x31] = 'W';
svga->crtc[0x32] = 'D';
svga->crtc[0x33] = '9';
svga->crtc[0x34] = '0';
svga->crtc[0x35] = 'C';
svga->bpp = 8;
svga->miscout = 1;
paradise->type = PVGA1A;
return paradise;
}
GFXCARD vid_paradise =
void *paradise_wd90c11_init()
{
paradise_init,
/*IO at 3Cx/3Dx*/
paradise_out,
paradise_in,
/*IO at 3Ax/3Bx*/
video_out_null,
video_in_null,
paradise_t *paradise = malloc(sizeof(paradise_t));
svga_t *svga = &paradise->svga;
memset(paradise, 0, sizeof(paradise_t));
io_sethandler(0x03c0, 0x0020, paradise_in, NULL, NULL, paradise_out, NULL, NULL, paradise);
svga_poll,
svga_recalctimings,
svga_init(&paradise->svga, paradise, 1 << 19, /*512kb*/
paradise_recalctimings,
paradise_in, paradise_out,
NULL);
paradise_write,
video_write_null,
video_write_null,
svga->crtc[0x31] = 'W';
svga->crtc[0x32] = 'D';
svga->crtc[0x33] = '9';
svga->crtc[0x34] = '0';
svga->crtc[0x35] = 'C';
svga->crtc[0x36] = '1';
svga->crtc[0x37] = '1';
paradise_read,
video_read_null,
video_read_null
svga->bpp = 8;
svga->miscout = 1;
paradise->type = WD90C11;
return paradise;
}
void paradise_close(void *p)
{
paradise_t *paradise = (paradise_t *)p;
svga_close(&paradise->svga);
free(paradise);
}
void paradise_speed_changed(void *p)
{
paradise_t *paradise = (paradise_t *)p;
svga_recalctimings(&paradise->svga);
}
device_t paradise_pvga1a_device =
{
"Paradise PVGA1A",
paradise_pvga1a_init,
paradise_close,
paradise_speed_changed,
svga_add_status_info
};
device_t paradise_wd90c11_device =
{
"Paradise WD90C11",
paradise_wd90c11_init,
paradise_close,
paradise_speed_changed,
svga_add_status_info
};

2
src/vid_paradise.h Normal file
View file

@ -0,0 +1,2 @@
extern device_t paradise_pvga1a_device;
extern device_t paradise_wd90c11_device;

View file

@ -6,263 +6,289 @@
The Technical Reference Manual lists the video waitstate time as between 12
and 46 cycles. PCem currently always uses the lower number.*/
#include <stdlib.h>
#include "ibm.h"
#include "device.h"
#include "io.h"
#include "mem.h"
#include "timer.h"
#include "video.h"
#include "vid_cga.h"
#include "vid_pc1512.h"
static uint8_t pc1512_plane_write,pc1512_plane_read,pc1512_border;
void pc1512_recalctimings();
void pc1512_out(uint16_t addr, uint8_t val, void *priv)
typedef struct pc1512_t
{
uint8_t crtc[32];
int crtcreg;
uint8_t cgacol, cgamode, stat;
uint8_t plane_write, plane_read, border;
int linepos, displine;
int sc, vc;
int cgadispon;
int con, coff, cursoron, cgablink;
int vsynctime, vadj;
uint16_t ma, maback;
int dispon;
int blink;
int dispontime, dispofftime, vidtime;
int firstline, lastline;
uint8_t *vram;
} pc1512_t;
static uint8_t crtcmask[32] =
{
0xff, 0xff, 0xff, 0xff, 0x7f, 0x1f, 0x7f, 0x7f, 0xf3, 0x1f, 0x7f, 0x1f, 0x3f, 0xff, 0x3f, 0xff,
0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
static void pc1512_recalctimings(pc1512_t *pc1512);
static void pc1512_out(uint16_t addr, uint8_t val, void *p)
{
pc1512_t *pc1512 = (pc1512_t *)p;
uint8_t old;
// pclog("PC1512 out %04X %02X %04X:%04X\n",addr,val,CS,pc);
pclog("PC1512 out %04X %02X %04X:%04X\n",addr,val,CS,pc);
switch (addr)
{
case 0x3D4:
crtcreg=val&31;
case 0x3d4:
pc1512->crtcreg = val & 31;
return;
case 0x3D5:
old=crtc[crtcreg];
crtc[crtcreg]=val&crtcmask[crtcreg];
if (old!=val)
case 0x3d5:
old = pc1512->crtc[pc1512->crtcreg];
pc1512->crtc[pc1512->crtcreg] = val & crtcmask[pc1512->crtcreg];
if (old != val)
{
if (crtcreg<0xE || crtcreg>0x10)
if (pc1512->crtcreg < 0xe || pc1512->crtcreg > 0x10)
{
fullchange=changeframecount;
pc1512_recalctimings();
fullchange = changeframecount;
pc1512_recalctimings(pc1512);
}
}
return;
case 0x3D8:
if ((val&0x12)==0x12 && (cgamode&0x12)!=0x12)
case 0x3d8:
if ((val & 0x12) == 0x12 && (pc1512->cgamode & 0x12) != 0x12)
{
pc1512_plane_write=0xF;
pc1512_plane_read =0;
pc1512->plane_write = 0xf;
pc1512->plane_read = 0;
}
cgamode=val;
pc1512->cgamode = val;
return;
case 0x3D9:
cgacol=val;
case 0x3d9:
pc1512->cgacol = val;
return;
case 0x3DD:
pc1512_plane_write=val;
case 0x3dd:
pc1512->plane_write = val;
return;
case 0x3DE:
pc1512_plane_read=val&3;
case 0x3de:
pc1512->plane_read = val & 3;
return;
case 0x3DF:
pc1512_border=val;
case 0x3df:
pc1512->border = val;
return;
}
}
uint8_t pc1512_in(uint16_t addr, void *priv)
static uint8_t pc1512_in(uint16_t addr, void *p)
{
pc1512_t *pc1512 = (pc1512_t *)p;
// pclog("PC1512 in %04X %02X %04X:%04X\n",addr,CS,pc);
switch (addr)
{
case 0x3D4:
return crtcreg;
case 0x3D5:
return crtc[crtcreg];
case 0x3DA:
return cgastat;
case 0x3d4:
return pc1512->crtcreg;
case 0x3d5:
return pc1512->crtc[pc1512->crtcreg];
case 0x3da:
return pc1512->stat;
}
return 0xFF;
return 0xff;
}
void pc1512_write(uint32_t addr, uint8_t val, void *priv)
static void pc1512_write(uint32_t addr, uint8_t val, void *p)
{
/* if (CS==0x023E && pc==0x524E)
pc1512_t *pc1512 = (pc1512_t *)p;
cycles -= 12;
addr &= 0x3fff;
if ((pc1512->cgamode & 0x12) == 0x12)
{
dumpregs();
exit(-1);
}
pclog("PC1512 write %08X %02X %02X %01X %04X:%04X\n",addr,val,cgamode&0x12,pc1512_plane_write,CS,pc);*/
cycles-=12;
addr&=0x7FFF;
if ((cgamode&0x12)==0x12)
{
if (pc1512_plane_write&1) vram[addr]=val;
if (pc1512_plane_write&2) vram[addr|0x10000]=val;
if (pc1512_plane_write&4) vram[addr|0x20000]=val;
if (pc1512_plane_write&8) vram[addr|0x30000]=val;
if (pc1512->plane_write & 1) pc1512->vram[addr] = val;
if (pc1512->plane_write & 2) pc1512->vram[addr | 0x4000] = val;
if (pc1512->plane_write & 4) pc1512->vram[addr | 0x8000] = val;
if (pc1512->plane_write & 8) pc1512->vram[addr | 0xc000] = val;
}
else
vram[addr]=val;
pc1512->vram[addr] = val;
}
uint8_t pc1512_read(uint32_t addr, void *priv)
static uint8_t pc1512_read(uint32_t addr, void *p)
{
// pclog("PC1512 read %08X %02X %01X\n",addr,cgamode&0x12,pc1512_plane_read);
cycles-=12;
addr&=0x7FFF;
if ((cgamode&0x12)==0x12)
return vram[addr|(pc1512_plane_read<<16)];
return vram[addr];
pc1512_t *pc1512 = (pc1512_t *)p;
cycles -= 12;
addr &= 0x3fff;
if ((pc1512->cgamode & 0x12) == 0x12)
return pc1512->vram[addr | (pc1512->plane_read << 14)];
return pc1512->vram[addr];
}
static int linepos,displine;
static int sc,vc;
static int cgadispon;
static int con,coff,cursoron,cgablink;
static int vsynctime,vadj;
static uint16_t ma,maback;
int i_filt[8],q_filt[8];
void pc1512_recalctimings()
static void pc1512_recalctimings(pc1512_t *pc1512)
{
double _dispontime, _dispofftime;
double _dispontime, _dispofftime, disptime;
disptime = 128; /*Fixed on PC1512*/
_dispontime = 80;
_dispofftime=disptime-_dispontime;
_dispofftime = disptime - _dispontime;
// printf("%i %f %f %f %i %i\n",cgamode&1,disptime,dispontime,dispofftime,crtc[0],crtc[1]);
_dispontime*=CGACONST;
_dispofftime*=CGACONST;
_dispontime *= CGACONST;
_dispofftime *= CGACONST;
// printf("Timings - on %f off %f frame %f second %f\n",dispontime,dispofftime,(dispontime+dispofftime)*262.0,(dispontime+dispofftime)*262.0*59.92);
dispontime = (int)(_dispontime * (1 << TIMER_SHIFT));
dispofftime = (int)(_dispofftime * (1 << TIMER_SHIFT));
pc1512->dispontime = (int)(_dispontime * (1 << TIMER_SHIFT));
pc1512->dispofftime = (int)(_dispofftime * (1 << TIMER_SHIFT));
}
void pc1512_poll()
static void pc1512_poll(void *p)
{
uint16_t ca=(crtc[15]|(crtc[14]<<8))&0x3FFF;
pc1512_t *pc1512 = (pc1512_t *)p;
uint16_t ca = (pc1512->crtc[15] | (pc1512->crtc[14] << 8)) & 0x3fff;
int drawcursor;
int x,c;
int x, c;
int oldvc;
uint8_t chr,attr;
uint16_t dat,dat2,dat3,dat4;
uint8_t chr, attr;
uint16_t dat, dat2, dat3, dat4;
int cols[4];
int col;
int oldsc;
if (!linepos)
if (!pc1512->linepos)
{
vidtime+=dispofftime;
cgastat|=1;
linepos=1;
oldsc=sc;
if (cgadispon)
pc1512->vidtime += pc1512->dispofftime;
pc1512->stat |= 1;
pc1512->linepos = 1;
oldsc = pc1512->sc;
if (pc1512->dispon)
{
if (displine<firstline) firstline=displine;
lastline=displine;
for (c=0;c<8;c++)
if (pc1512->displine < pc1512->firstline)
pc1512->firstline = pc1512->displine;
pc1512->lastline = pc1512->displine;
for (c = 0; c < 8; c++)
{
if ((cgamode&0x12)==0x12)
if ((pc1512->cgamode & 0x12) == 0x12)
{
buffer->line[displine][c]=(pc1512_border&15)+16;
if (cgamode&1) buffer->line[displine][c+(crtc[1]<<3)+8]=0;
else buffer->line[displine][c+(crtc[1]<<4)+8]=0;
buffer->line[pc1512->displine][c] = (pc1512->border & 15) + 16;
if (pc1512->cgamode & 1) buffer->line[pc1512->displine][c + (pc1512->crtc[1] << 3) + 8] = 0;
else buffer->line[pc1512->displine][c + (pc1512->crtc[1] << 4) + 8] = 0;
}
else
{
buffer->line[displine][c]=(cgacol&15)+16;
if (cgamode&1) buffer->line[displine][c+(crtc[1]<<3)+8]=(cgacol&15)+16;
else buffer->line[displine][c+(crtc[1]<<4)+8]=(cgacol&15)+16;
buffer->line[pc1512->displine][c] = (pc1512->cgacol & 15) + 16;
if (pc1512->cgamode & 1) buffer->line[pc1512->displine][c + (pc1512->crtc[1] << 3) + 8] = (pc1512->cgacol & 15) + 16;
else buffer->line[pc1512->displine][c + (pc1512->crtc[1] << 4) + 8] = (pc1512->cgacol & 15) + 16;
}
}
if (cgamode&1)
if (pc1512->cgamode & 1)
{
for (x = 0; x < 80; x++)
{
chr=vram[((ma<<1)&0x3FFF)];
attr=vram[(((ma<<1)+1)&0x3FFF)];
drawcursor=((ma==ca) && con && cursoron);
if (cgamode&0x20)
chr = pc1512->vram[ ((pc1512->ma << 1) & 0x3fff)];
attr = pc1512->vram[(((pc1512->ma << 1) + 1) & 0x3fff)];
drawcursor = ((pc1512->ma == ca) && pc1512->con && pc1512->cursoron);
if (pc1512->cgamode & 0x20)
{
cols[1]=(attr&15)+16;
cols[0]=((attr>>4)&7)+16;
if ((cgablink&16) && (attr&0x80) && !drawcursor) cols[1]=cols[0];
cols[1] = (attr & 15) + 16;
cols[0] = ((attr >> 4) & 7) + 16;
if ((pc1512->blink & 16) && (attr & 0x80) && !drawcursor)
cols[1] = cols[0];
}
else
{
cols[1]=(attr&15)+16;
cols[0]=(attr>>4)+16;
cols[1] = (attr & 15) + 16;
cols[0] = (attr >> 4) + 16;
}
if (drawcursor)
{
for (c=0;c<8;c++)
buffer->line[displine][(x<<3)+c+8]=cols[(fontdat[chr][sc&7]&(1<<(c^7)))?1:0]^15;
for (c = 0; c < 8; c++)
buffer->line[pc1512->displine][(x << 3) + c + 8] = cols[(fontdat[chr][pc1512->sc & 7] & (1 << (c ^ 7))) ? 1 : 0] ^ 15;
}
else
{
for (c=0;c<8;c++)
buffer->line[displine][(x<<3)+c+8]=cols[(fontdat[chr][sc&7]&(1<<(c^7)))?1:0];
for (c = 0; c < 8; c++)
buffer->line[pc1512->displine][(x << 3) + c + 8] = cols[(fontdat[chr][pc1512->sc & 7] & (1 << (c ^ 7))) ? 1 : 0];
}
ma++;
pc1512->ma++;
}
}
else if (!(cgamode&2))
else if (!(pc1512->cgamode & 2))
{
for (x = 0; x < 40; x++)
{
chr=vram[((ma<<1)&0x3FFF)];
attr=vram[(((ma<<1)+1)&0x3FFF)];
drawcursor=((ma==ca) && con && cursoron);
if (cgamode&0x20)
chr = pc1512->vram[ ((pc1512->ma << 1) & 0x3fff)];
attr = pc1512->vram[(((pc1512->ma << 1) + 1) & 0x3fff)];
drawcursor = ((pc1512->ma == ca) && pc1512->con && pc1512->cursoron);
if (pc1512->cgamode & 0x20)
{
cols[1]=(attr&15)+16;
cols[0]=((attr>>4)&7)+16;
if ((cgablink&16) && (attr&0x80)) cols[1]=cols[0];
cols[1] = (attr & 15) + 16;
cols[0] = ((attr >> 4) & 7) + 16;
if ((pc1512->blink & 16) && (attr & 0x80))
cols[1] = cols[0];
}
else
{
cols[1]=(attr&15)+16;
cols[0]=(attr>>4)+16;
cols[1] = (attr & 15) + 16;
cols[0] = (attr >> 4) + 16;
}
ma++;
pc1512->ma++;
if (drawcursor)
{
for (c=0;c<8;c++)
buffer->line[displine][(x<<4)+(c<<1)+8]=buffer->line[displine][(x<<4)+(c<<1)+1+8]=cols[(fontdat[chr][sc&7]&(1<<(c^7)))?1:0]^15;
for (c = 0; c < 8; c++)
buffer->line[pc1512->displine][(x << 4) + (c << 1) + 8] =
buffer->line[pc1512->displine][(x << 4) + (c << 1) + 1 + 8] = cols[(fontdat[chr][pc1512->sc & 7] & (1 << (c ^ 7))) ? 1 : 0] ^ 15;
}
else
{
for (c=0;c<8;c++)
buffer->line[displine][(x<<4)+(c<<1)+8]=buffer->line[displine][(x<<4)+(c<<1)+1+8]=cols[(fontdat[chr][sc&7]&(1<<(c^7)))?1:0];
for (c = 0; c < 8; c++)
buffer->line[pc1512->displine][(x << 4) + (c << 1) + 8] =
buffer->line[pc1512->displine][(x << 4) + (c << 1) + 1 + 8] = cols[(fontdat[chr][pc1512->sc & 7] & (1 << (c ^ 7))) ? 1 : 0];
}
}
}
else if (!(cgamode&16))
else if (!(pc1512->cgamode&16))
{
cols[0]=(cgacol&15)|16;
col=(cgacol&16)?24:16;
if (cgamode&4)
cols[0] = (pc1512->cgacol & 15) | 16;
col = (pc1512->cgacol & 16) ? 24 : 16;
if (pc1512->cgamode & 4)
{
cols[1]=col|3;
cols[2]=col|4;
cols[3]=col|7;
cols[1] = col | 3;
cols[2] = col | 4;
cols[3] = col | 7;
}
else if (cgacol&32)
else if (pc1512->cgacol & 32)
{
cols[1]=col|3;
cols[2]=col|5;
cols[3]=col|7;
cols[1] = col | 3;
cols[2] = col | 5;
cols[3] = col | 7;
}
else
{
cols[1]=col|2;
cols[2]=col|4;
cols[3]=col|6;
cols[1] = col | 2;
cols[2] = col | 4;
cols[3] = col | 6;
}
for (x = 0; x < 40; x++)
{
dat=(vram[((ma<<1)&0x1FFF)+((sc&1)*0x2000)]<<8)|vram[((ma<<1)&0x1FFF)+((sc&1)*0x2000)+1];
ma++;
for (c=0;c<8;c++)
dat = (pc1512->vram[((pc1512->ma << 1) & 0x1fff) + ((pc1512->sc & 1) * 0x2000)] << 8) | pc1512->vram[((pc1512->ma << 1) & 0x1fff) + ((pc1512->sc & 1) * 0x2000) + 1];
pc1512->ma++;
for (c = 0; c < 8; c++)
{
buffer->line[displine][(x<<4)+(c<<1)+8]=
buffer->line[displine][(x<<4)+(c<<1)+1+8]=cols[dat>>14];
dat<<=2;
buffer->line[pc1512->displine][(x << 4) + (c << 1) + 8] =
buffer->line[pc1512->displine][(x << 4) + (c << 1) + 1 + 8] = cols[dat >> 14];
dat <<= 2;
}
}
}
@ -270,169 +296,191 @@ void pc1512_poll()
{
for (x = 0; x < 40; x++)
{
ca=((ma<<1)&0x1FFF)+((sc&1)*0x2000);
dat=(vram[ca]<<8)|vram[ca+1];
dat2=(vram[ca+0x10000]<<8)|vram[ca+0x10001];
dat3=(vram[ca+0x20000]<<8)|vram[ca+0x20001];
dat4=(vram[ca+0x30000]<<8)|vram[ca+0x30001];
ca = ((pc1512->ma << 1) & 0x1fff) + ((pc1512->sc & 1) * 0x2000);
dat = (pc1512->vram[ca] << 8) | pc1512->vram[ca + 1];
dat2 = (pc1512->vram[ca + 0x4000] << 8) | pc1512->vram[ca + 0x4001];
dat3 = (pc1512->vram[ca + 0x8000] << 8) | pc1512->vram[ca + 0x8001];
dat4 = (pc1512->vram[ca + 0xc000] << 8) | pc1512->vram[ca + 0xc001];
ma++;
for (c=0;c<16;c++)
pc1512->ma++;
for (c = 0; c < 16; c++)
{
buffer->line[displine][(x<<4)+c+8]=(((dat>>15)|((dat2>>15)<<1)|((dat3>>15)<<2)|((dat4>>15)<<3))&(cgacol&15))+16;
dat<<=1;
dat2<<=1;
dat3<<=1;
dat4<<=1;
buffer->line[pc1512->displine][(x << 4) + c + 8] = (((dat >> 15) | ((dat2 >> 15) << 1) | ((dat3 >> 15) << 2) | ((dat4 >> 15) << 3)) & (pc1512->cgacol & 15)) + 16;
dat <<= 1;
dat2 <<= 1;
dat3 <<= 1;
dat4 <<= 1;
}
}
}
}
else
{
cols[0]=((cgamode&0x12)==0x12)?0:(cgacol&15)+16;
if (cgamode&1) hline(buffer,0,displine,(crtc[1]<<3)+16,cols[0]);
else hline(buffer,0,displine,(crtc[1]<<4)+16,cols[0]);
cols[0] = ((pc1512->cgamode & 0x12) == 0x12) ? 0 : (pc1512->cgacol & 15) + 16;
if (pc1512->cgamode & 1) hline(buffer, 0, pc1512->displine, (pc1512->crtc[1] << 3) + 16, cols[0]);
else hline(buffer, 0, pc1512->displine, (pc1512->crtc[1] << 4) + 16, cols[0]);
}
sc=oldsc;
if (vsynctime)
cgastat|=8;
displine++;
if (displine>=360) displine=0;
pc1512->sc = oldsc;
if (pc1512->vsynctime)
pc1512->stat |= 8;
pc1512->displine++;
if (pc1512->displine >= 360)
pc1512->displine = 0;
// pclog("Line %i %i %i %i %i %i\n",displine,cgadispon,firstline,lastline,vc,sc);
}
else
{
vidtime+=dispontime;
if ((lastline-firstline)==199) cgadispon=0; /*Amstrad PC1512 always displays 200 lines, regardless of CRTC settings*/
if (cgadispon) cgastat&=~1;
linepos=0;
if (vsynctime)
pc1512->vidtime += pc1512->dispontime;
if ((pc1512->lastline - pc1512->firstline) == 199)
pc1512->dispon = 0; /*Amstrad PC1512 always displays 200 lines, regardless of CRTC settings*/
if (pc1512->dispon)
pc1512->stat &= ~1;
pc1512->linepos = 0;
if (pc1512->vsynctime)
{
vsynctime--;
if (!vsynctime)
cgastat&=~8;
pc1512->vsynctime--;
if (!pc1512->vsynctime)
pc1512->stat &= ~8;
}
if (sc==(crtc[11]&31)) { con=0; coff=1; }
if (vadj)
if (pc1512->sc == (pc1512->crtc[11] & 31))
{
pc1512->con = 0;
pc1512->coff = 1;
}
if (pc1512->vadj)
{
sc++;
sc&=31;
ma=maback;
vadj--;
if (!vadj)
pc1512->sc++;
pc1512->sc &= 31;
pc1512->ma = pc1512->maback;
pc1512->vadj--;
if (!pc1512->vadj)
{
cgadispon=1;
ma=maback=(crtc[13]|(crtc[12]<<8))&0x3FFF;
sc=0;
pc1512->dispon = 1;
pc1512->ma = pc1512->maback = (pc1512->crtc[13] | (pc1512->crtc[12] << 8)) & 0x3fff;
pc1512->sc = 0;
}
}
else if (sc==crtc[9])
else if (pc1512->sc == pc1512->crtc[9])
{
maback=ma;
sc=0;
oldvc=vc;
vc++;
vc&=127;
pc1512->maback = pc1512->ma;
pc1512->sc = 0;
oldvc = pc1512->vc;
pc1512->vc++;
pc1512->vc &= 127;
if (displine == 32)//oldvc == (cgamode & 2) ? 127 : 31)
if (pc1512->displine == 32)//oldvc == (cgamode & 2) ? 127 : 31)
{
vc=0;
vadj=6;
if ((crtc[10]&0x60)==0x20) cursoron=0;
else cursoron=cgablink&16;
pc1512->vc = 0;
pc1512->vadj = 6;
if ((pc1512->crtc[10] & 0x60) == 0x20) pc1512->cursoron = 0;
else pc1512->cursoron = pc1512->blink & 16;
}
if (displine >= 262)//vc == (cgamode & 2) ? 111 : 27)
if (pc1512->displine >= 262)//vc == (cgamode & 2) ? 111 : 27)
{
cgadispon=0;
displine=0;
vsynctime=46;
pc1512->dispon = 0;
pc1512->displine = 0;
pc1512->vsynctime = 46;
if (cgamode&1) x=(crtc[1]<<3)+16;
else x=(crtc[1]<<4)+16;
x = 640 + 16;
lastline++;
if (x!=xsize || (lastline-firstline)!=ysize)
{
xsize=x;
ysize=lastline-firstline;
if (xsize<64) xsize=656;
if (ysize<32) ysize=200;
updatewindowsize(xsize,(ysize<<1)+16);
}
if (pc1512->cgamode&1) x = (pc1512->crtc[1] << 3) + 16;
else x = (pc1512->crtc[1] << 4) + 16;
x = 640 + 16;
pc1512->lastline++;
if (x != xsize || (pc1512->lastline - pc1512->firstline) != ysize)
{
xsize = x;
ysize = pc1512->lastline - pc1512->firstline;
if (xsize < 64) xsize = 656;
if (ysize < 32) ysize = 200;
updatewindowsize(xsize, (ysize << 1) + 16);
}
startblit();
video_blit_memtoscreen_8(0, firstline - 4, xsize, (lastline - firstline) + 8);
video_blit_memtoscreen_8(0, pc1512->firstline - 4, xsize, (pc1512->lastline - pc1512->firstline) + 8);
// blit(buffer,vbuf,0,firstline-4,0,0,xsize,(lastline-firstline)+8+1);
// if (vid_resize) stretch_blit(vbuf,screen,0,0,xsize,(lastline-firstline)+8+1,0,0,winsizex,winsizey);
// else stretch_blit(vbuf,screen,0,0,xsize,(lastline-firstline)+8+1,0,0,xsize,((lastline-firstline)<<1)+16+2);
// if (readflash) rectfill(screen,winsizex-40,8,winsizex-8,14,0xFFFFFFFF);
// readflash=0;
endblit();
video_res_x = xsize - 16;
video_res_y = ysize;
if (cgamode & 1)
{
video_res_x /= 8;
video_res_y /= crtc[9] + 1;
video_bpp = 0;
}
else if (!(cgamode & 2))
{
video_res_x /= 16;
video_res_y /= crtc[9] + 1;
video_bpp = 0;
}
else if (!(cgamode&16))
{
video_res_x /= 2;
video_bpp = 2;
}
else
{
video_bpp = 4;
}
video_res_x = xsize - 16;
video_res_y = ysize;
if (pc1512->cgamode & 1)
{
video_res_x /= 8;
video_res_y /= pc1512->crtc[9] + 1;
video_bpp = 0;
}
else if (!(pc1512->cgamode & 2))
{
video_res_x /= 16;
video_res_y /= pc1512->crtc[9] + 1;
video_bpp = 0;
}
else if (!(pc1512->cgamode & 16))
{
video_res_x /= 2;
video_bpp = 2;
}
else
{
video_bpp = 4;
}
firstline=1000;
lastline=0;
cgablink++;
pc1512->firstline = 1000;
pc1512->lastline = 0;
pc1512->blink++;
}
}
else
{
sc++;
sc&=31;
ma=maback;
pc1512->sc++;
pc1512->sc &= 31;
pc1512->ma = pc1512->maback;
}
if (sc==(crtc[10]&31)) con=1;
if (pc1512->sc == (pc1512->crtc[10] & 31))
pc1512->con = 1;
}
}
int pc1512_init()
static void *pc1512_init()
{
mem_sethandler(0xb8000, 0x08000, pc1512_read, NULL, NULL, pc1512_write, NULL, NULL, NULL);
return 0;
int c;
pc1512_t *pc1512 = malloc(sizeof(pc1512_t));
memset(pc1512, 0, sizeof(pc1512_t));
pc1512->vram = malloc(0x10000);
pc1512->cgacol = 7;
pc1512->cgamode = 0x12;
timer_add(pc1512_poll, &pc1512->vidtime, TIMER_ALWAYS_ENABLED, pc1512);
mem_sethandler(0xb8000, 0x08000, pc1512_read, NULL, NULL, pc1512_write, NULL, NULL, pc1512);
io_sethandler(0x03d0, 0x0010, pc1512_in, NULL, NULL, pc1512_out, NULL, NULL, pc1512);
return pc1512;
}
GFXCARD vid_pc1512 =
static void pc1512_close(void *p)
{
pc1512_t *pc1512 = (pc1512_t *)p;
free(pc1512->vram);
free(pc1512);
}
static void pc1512_speed_changed(void *p)
{
pc1512_t *pc1512 = (pc1512_t *)p;
pc1512_recalctimings(pc1512);
}
device_t pc1512_device =
{
"Amstrad PC1512 (video)",
pc1512_init,
/*IO at 3Cx/3Dx*/
pc1512_out,
pc1512_in,
/*IO at 3Ax/3Bx*/
video_out_null,
video_in_null,
pc1512_poll,
pc1512_recalctimings,
video_write_null,
video_write_null,
pc1512_write,
video_read_null,
video_read_null,
pc1512_read
pc1512_close,
pc1512_speed_changed,
NULL
};

1
src/vid_pc1512.h Normal file
View file

@ -0,0 +1 @@
extern device_t pc1512_device;

View file

@ -1,99 +1,145 @@
/*PC1640 video emulation.
Mostly standard EGA, but with CGA & Hercules emulation*/
#include <stdlib.h>
#include "ibm.h"
#include "device.h"
#include "io.h"
#include "mem.h"
#include "timer.h"
#include "video.h"
#include "vid_cga.h"
#include "vid_ega.h"
#include "vid_pc1640.h"
static int pc1640_cga=1;
void pc1640_out(uint16_t addr, uint8_t val, void *priv)
typedef struct pc1640_t
{
cga_t cga;
ega_t ega;
int cga_enabled;
int dispontime, dispofftime, vidtime;
} pc1640_t;
void pc1640_out(uint16_t addr, uint8_t val, void *p)
{
pc1640_t *pc1640 = (pc1640_t *)p;
switch (addr)
{
case 0x3DB:
pc1640_cga=val&0x40;
mem_removehandler(0xa0000, 0x20000, ega_read, NULL, NULL, ega_write, NULL, NULL, NULL);
mem_removehandler(0xb8000, 0x08000, cga_read, NULL, NULL, cga_write, NULL, NULL, NULL);
if (pc1640_cga)
mem_sethandler(0xb8000, 0x08000, cga_read, NULL, NULL, cga_write, NULL, NULL, NULL);
case 0x3db:
pc1640->cga_enabled = val & 0x40;
mem_removehandler(0xa0000, 0x20000, ega_read, NULL, NULL, ega_write, NULL, NULL, &pc1640->ega);
mem_removehandler(0xb8000, 0x08000, cga_read, NULL, NULL, cga_write, NULL, NULL, &pc1640->cga);
if (pc1640->cga_enabled)
mem_sethandler(0xb8000, 0x08000, cga_read, NULL, NULL, cga_write, NULL, NULL, &pc1640->cga);
else
{
switch (gdcreg[6] & 0xC)
switch (pc1640->ega.gdcreg[6] & 0xc)
{
case 0x0: /*128k at A0000*/
mem_sethandler(0xa0000, 0x20000, ega_read, NULL, NULL, ega_write, NULL, NULL, NULL);
mem_sethandler(0xa0000, 0x20000, ega_read, NULL, NULL, ega_write, NULL, NULL, &pc1640->ega);
break;
case 0x4: /*64k at A0000*/
mem_sethandler(0xa0000, 0x10000, ega_read, NULL, NULL, ega_write, NULL, NULL, NULL);
mem_sethandler(0xa0000, 0x10000, ega_read, NULL, NULL, ega_write, NULL, NULL, &pc1640->ega);
break;
case 0x8: /*32k at B0000*/
mem_sethandler(0xb0000, 0x08000, ega_read, NULL, NULL, ega_write, NULL, NULL, NULL);
mem_sethandler(0xb0000, 0x08000, ega_read, NULL, NULL, ega_write, NULL, NULL, &pc1640->ega);
break;
case 0xC: /*32k at B8000*/
mem_sethandler(0xb8000, 0x08000, ega_read, NULL, NULL, ega_write, NULL, NULL, NULL);
mem_sethandler(0xb8000, 0x08000, ega_read, NULL, NULL, ega_write, NULL, NULL, &pc1640->ega);
break;
}
}
pclog("3DB write %02X\n", val);
return;
}
if (pc1640_cga) cga_out(addr, val, NULL);
else ega_out(addr, val, NULL);
if (pc1640->cga_enabled) cga_out(addr, val, &pc1640->cga);
else ega_out(addr, val, &pc1640->ega);
}
uint8_t pc1640_in(uint16_t addr, void *priv)
uint8_t pc1640_in(uint16_t addr, void *p)
{
pc1640_t *pc1640 = (pc1640_t *)p;
switch (addr)
{
}
if (pc1640_cga) return cga_in(addr, NULL);
else return ega_in(addr, NULL);
}
void pc1640_recalctimings()
{
if (pc1640_cga) cga_recalctimings();
else ega_recalctimings();
}
void pc1640_poll()
{
if (pc1640_cga) cga_poll();
else ega_poll();
}
int pc1640_init()
{
int r = ega_init();
pc1640_cga = 1;
mem_sethandler(0xb8000, 0x08000, cga_read, NULL, NULL, cga_write, NULL, NULL, NULL);
return r;
if (pc1640->cga_enabled) return cga_in(addr, &pc1640->cga);
else return ega_in(addr, &pc1640->ega);
}
GFXCARD vid_pc1640 =
void pc1640_recalctimings(pc1640_t *pc1640)
{
if (pc1640->cga_enabled)
{
cga_recalctimings(&pc1640->cga);
pc1640->dispontime = pc1640->cga.dispontime;
pc1640->dispofftime = pc1640->cga.dispofftime;
}
else
{
ega_recalctimings(&pc1640->ega);
pc1640->dispontime = pc1640->ega.dispontime;
pc1640->dispofftime = pc1640->ega.dispofftime;
}
}
void pc1640_poll(void *p)
{
pc1640_t *pc1640 = (pc1640_t *)p;
if (pc1640->cga_enabled)
{
pc1640->cga.vidtime = pc1640->vidtime;
cga_poll(&pc1640->cga);
pc1640->vidtime = pc1640->cga.vidtime;
}
else
{
pc1640->ega.vidtime = pc1640->vidtime;
ega_poll(&pc1640->ega);
pc1640->vidtime = pc1640->ega.vidtime;
}
}
void *pc1640_init()
{
pc1640_t *pc1640 = malloc(sizeof(pc1640_t));
cga_t *cga = &pc1640->cga;
ega_t *ega = &pc1640->ega;
memset(pc1640, 0, sizeof(pc1640_t));
ega_init(&pc1640->ega);
pc1640->cga.vram = pc1640->ega.vram;
pc1640->cga_enabled = 1;
cga_init(&pc1640->cga);
timer_add(pc1640_poll, &pc1640->vidtime, TIMER_ALWAYS_ENABLED, pc1640);
mem_sethandler(0xb8000, 0x08000, cga_read, NULL, NULL, cga_write, NULL, NULL, cga);
io_sethandler(0x03a0, 0x0040, pc1640_in, NULL, NULL, pc1640_out, NULL, NULL, pc1640);
return cga;
}
void pc1640_close(void *p)
{
pc1640_t *pc1640 = (pc1640_t *)p;
free(pc1640->ega.vram);
free(pc1640);
}
void pc1640_speed_changed(void *p)
{
pc1640_t *pc1640 = (pc1640_t *)p;
pc1640_recalctimings(pc1640);
}
device_t pc1640_device =
{
"Amstrad PC1640 (video)",
pc1640_init,
/*IO at 3Cx/3Dx*/
pc1640_out,
pc1640_in,
/*IO at 3Ax/3Bx*/
video_out_null,
video_in_null,
pc1640_poll,
pc1640_recalctimings,
ega_write,
video_write_null,
video_write_null,
ega_read,
video_read_null,
video_read_null
pc1640_close,
pc1640_speed_changed,
NULL
};

1
src/vid_pc1640.h Normal file
View file

@ -0,0 +1 @@
extern device_t pc1640_device;

View file

@ -1,104 +1,139 @@
/*PC200 video emulation.
CGA with some NMI stuff. But we don't need that as it's only used for TV and
LCD displays, and we're emulating a CRT*/
#include <stdlib.h>
#include "ibm.h"
#include "device.h"
#include "io.h"
#include "mem.h"
#include "timer.h"
#include "video.h"
#include "vid_cga.h"
#include "vid_pc200.h"
uint8_t pc200_3dd, pc200_3de, pc200_3df;
void pc200_out(uint16_t addr, uint8_t val, void *priv)
typedef struct pc200_t
{
cga_t cga;
uint8_t reg_3dd, reg_3de, reg_3df;
} pc200_t;
static uint8_t crtcmask[32] =
{
0xff, 0xff, 0xff, 0xff, 0x7f, 0x1f, 0x7f, 0x7f, 0xf3, 0x1f, 0x7f, 0x1f, 0x3f, 0xff, 0x3f, 0xff,
0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
void pc200_out(uint16_t addr, uint8_t val, void *p)
{
pc200_t *pc200 = (pc200_t *)p;
cga_t *cga = &pc200->cga;
uint8_t old;
switch (addr)
{
case 0x3D5:
if (!(pc200_3de&0x40) && crtcreg<=11)
case 0x3d5:
if (!(pc200->reg_3de & 0x40) && cga->crtcreg <= 11)
{
if (pc200_3de&0x80) nmi=1;
pc200_3dd=0x20|(crtcreg&0x1F);
pc200_3df=val;
if (pc200->reg_3de & 0x80)
nmi = 1;
pc200->reg_3dd = 0x20 | (cga->crtcreg & 0x1f);
pc200->reg_3df = val;
return;
}
old=crtc[crtcreg];
crtc[crtcreg]=val&crtcmask[crtcreg];
if (old!=val)
old = cga->crtc[cga->crtcreg];
cga->crtc[cga->crtcreg] = val & crtcmask[cga->crtcreg];
if (old != val)
{
if (crtcreg<0xE || crtcreg>0x10)
if (cga->crtcreg < 0xe || cga->crtcreg > 0x10)
{
fullchange=changeframecount;
cga_recalctimings();
fullchange = changeframecount;
cga_recalctimings(cga);
}
}
return;
case 0x3D8:
old = cgamode;
cgamode=val;
if ((cgamode ^ old) & 3)
cga_recalctimings();
pc200_3dd|=0x80;
if (pc200_3de&0x80)
nmi=1;
case 0x3d8:
old = cga->cgamode;
cga->cgamode = val;
if ((cga->cgamode ^ old) & 3)
cga_recalctimings(cga);
pc200->reg_3dd |= 0x80;
if (pc200->reg_3de & 0x80)
nmi = 1;
return;
case 0x3DE:
pc200_3de=val;
pc200_3dd=0x1F;
if (val&0x80) pc200_3dd|=0x40;
case 0x3de:
pc200->reg_3de = val;
pc200->reg_3dd = 0x1f;
if (val & 0x80)
pc200->reg_3dd |= 0x40;
return;
}
cga_out(addr, val, NULL);
cga_out(addr, val, cga);
}
uint8_t pc200_in(uint16_t addr, void *priv)
uint8_t pc200_in(uint16_t addr, void *p)
{
pc200_t *pc200 = (pc200_t *)p;
cga_t *cga = &pc200->cga;
uint8_t temp;
switch (addr)
{
case 0x3D8:
return cgamode;
return cga->cgamode;
case 0x3DD:
temp = pc200_3dd;
pc200_3dd &= 0x1F;
temp = pc200->reg_3dd;
pc200->reg_3dd &= 0x1f;
return temp;
case 0x3DE:
return (pc200_3de&0xC7)| 0x18; /*External CGA*/
return (pc200->reg_3de & 0xc7) | 0x18; /*External CGA*/
case 0x3DF:
return pc200_3df;
return pc200->reg_3df;
}
return cga_in(addr, NULL);
return cga_in(addr, cga);
}
int pc200_init()
void *pc200_init()
{
mem_sethandler(0xb8000, 0x08000, cga_read, NULL, NULL, cga_write, NULL, NULL, NULL);
return cga_init();
pc200_t *pc200 = malloc(sizeof(pc200_t));
cga_t *cga = &pc200->cga;
memset(pc200, 0, sizeof(pc200_t));
pc200->cga.vram = malloc(0x4000);
cga_init(&pc200->cga);
timer_add(cga_poll, &cga->vidtime, TIMER_ALWAYS_ENABLED, cga);
mem_sethandler(0xb8000, 0x08000, cga_read, NULL, NULL, cga_write, NULL, NULL, cga);
io_sethandler(0x03d0, 0x0010, pc200_in, NULL, NULL, pc200_out, NULL, NULL, pc200);
return cga;
}
GFXCARD vid_pc200 =
void pc200_close(void *p)
{
pc200_t *pc200 = (pc200_t *)p;
free(pc200->cga.vram);
free(pc200);
}
void pc200_speed_changed(void *p)
{
pc200_t *pc200 = (pc200_t *)p;
cga_recalctimings(&pc200->cga);
}
device_t pc200_device =
{
"Amstrad PC200 (video)",
pc200_init,
/*IO at 3Cx/3Dx*/
pc200_out,
pc200_in,
/*IO at 3Ax/3Bx*/
video_out_null,
video_in_null,
cga_poll,
cga_recalctimings,
video_write_null,
video_write_null,
cga_write,
video_read_null,
video_read_null,
cga_read
pc200_close,
pc200_speed_changed,
NULL
};

1
src/vid_pc200.h Normal file
View file

@ -0,0 +1 @@
extern device_t pc200_device;

File diff suppressed because it is too large Load diff

2
src/vid_s3.h Normal file
View file

@ -0,0 +1,2 @@
device_t s3_bahamas64_device;
device_t s3_9fx_device;

View file

@ -1,51 +1,66 @@
/*S3 ViRGE emulation
The SVGA core is largely the same as older S3 chips, but the blitter is totally different*/
#include <stdlib.h>
#include "ibm.h"
#include "device.h"
#include "io.h"
#include "mem.h"
#include "pci.h"
#include "video.h"
#include "vid_s3_virge.h"
#include "vid_svga.h"
#include "vid_svga_render.h"
//#include "vid_sdac_ramdac.h"
void s3_virge_updatemapping();
static uint8_t s3_bank;
static uint8_t s3_ma_ext;
static int s3_width = 1024;
static int s3_bpp = 0;
static uint8_t s3_virge_id, s3_virge_id_high, s3_virge_id_low, s3_virge_rev;
uint8_t s3_virge_mmio_read(uint32_t addr, void *priv);
uint16_t s3_virge_mmio_read_w(uint32_t addr, void *priv);
uint32_t s3_virge_mmio_read_l(uint32_t addr, void *priv);
void s3_virge_mmio_write(uint32_t addr, uint8_t val, void *priv);
void s3_virge_mmio_write_w(uint32_t addr, uint16_t val, void *priv);
void s3_virge_mmio_write_l(uint32_t addr, uint32_t val, void *priv);
void s3_virge_out(uint16_t addr, uint8_t val, void *priv)
typedef struct virge_t
{
svga_t svga;
uint8_t bank;
uint8_t ma_ext;
int width;
int bpp;
uint8_t virge_id, virge_id_high, virge_id_low, virge_rev;
uint32_t linear_base, linear_size;
uint8_t pci_regs[256];
} virge_t;
void s3_virge_updatemapping(virge_t *virge);
uint8_t s3_virge_mmio_read(uint32_t addr, void *p);
uint16_t s3_virge_mmio_read_w(uint32_t addr, void *p);
uint32_t s3_virge_mmio_read_l(uint32_t addr, void *p);
void s3_virge_mmio_write(uint32_t addr, uint8_t val, void *p);
void s3_virge_mmio_write_w(uint32_t addr, uint16_t val, void *p);
void s3_virge_mmio_write_l(uint32_t addr, uint32_t val, void *p);
void s3_virge_out(uint16_t addr, uint8_t val, void *p)
{
virge_t *virge = (virge_t *)p;
svga_t *svga = &virge->svga;
uint8_t old;
if (((addr&0xFFF0) == 0x3D0 || (addr&0xFFF0) == 0x3B0) && !(svga_miscout&1)) addr ^= 0x60;
if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(svga->miscout & 1))
addr ^= 0x60;
pclog("S3 out %04X %02X %04X:%08X %04X %04X %i\n", addr, val, CS, pc, ES, BX, ins);
switch (addr)
{
case 0x3c5:
if (seqaddr >= 0x10)
if (svga->seqaddr >= 0x10)
{
seqregs[seqaddr&0x1F]=val;
svga->seqregs[svga->seqaddr & 0x1f]=val;
return;
}
if (seqaddr == 4) /*Chain-4 - update banking*/
if (svga->seqaddr == 4) /*Chain-4 - update banking*/
{
if (val & 8) svgawbank = svgarbank = s3_bank << 16;
else svgawbank = svgarbank = s3_bank << 14;
if (val & 8) svga->write_bank = svga->read_bank = virge->bank << 16;
else svga->write_bank = svga->read_bank = virge->bank << 14;
}
break;
@ -54,107 +69,113 @@ void s3_virge_out(uint16_t addr, uint8_t val, void *priv)
//sdac_ramdac_out(addr,val);
//return;
case 0x3D4:
crtcreg=val&0x7f;
case 0x3d4:
svga->crtcreg = val & 0x7f;
return;
case 0x3D5:
case 0x3d5:
// if (crtcreg == 0x67) pclog("Write CRTC R%02X %02X\n", crtcreg, val);
if (crtcreg <= 7 && crtc[0x11] & 0x80) return;
if (crtcreg >= 0x20 && crtcreg != 0x38 && (crtc[0x38] & 0xcc) != 0x48) return;
old=crtc[crtcreg];
crtc[crtcreg]=val;
switch (crtcreg)
if (svga->crtcreg <= 7 && svga->crtc[0x11] & 0x80)
return;
if (svga->crtcreg >= 0x20 && svga->crtcreg != 0x38 && (svga->crtc[0x38] & 0xcc) != 0x48)
return;
old = svga->crtc[svga->crtcreg];
svga->crtc[svga->crtcreg] = val;
switch (svga->crtcreg)
{
case 0x31:
s3_ma_ext = (s3_ma_ext & 0x1c) | ((val & 0x30) >> 4);
vrammask = (val & 8) ? 0x3fffff : 0x3ffff;
virge->ma_ext = (virge->ma_ext & 0x1c) | ((val & 0x30) >> 4);
svga->vrammask = (val & 8) ? 0x3fffff : 0x3ffff;
break;
case 0x50:
switch (crtc[0x50] & 0xc1)
switch (svga->crtc[0x50] & 0xc1)
{
case 0x00: s3_width = (crtc[0x31] & 2) ? 2048 : 1024; break;
case 0x01: s3_width = 1152; break;
case 0x40: s3_width = 640; break;
case 0x80: s3_width = 800; break;
case 0x81: s3_width = 1600; break;
case 0xc0: s3_width = 1280; break;
case 0x00: virge->width = (svga->crtc[0x31] & 2) ? 2048 : 1024; break;
case 0x01: virge->width = 1152; break;
case 0x40: virge->width = 640; break;
case 0x80: virge->width = 800; break;
case 0x81: virge->width = 1600; break;
case 0xc0: virge->width = 1280; break;
}
s3_bpp = (crtc[0x50] >> 4) & 3;
virge->bpp = (svga->crtc[0x50] >> 4) & 3;
break;
case 0x69:
s3_ma_ext = val & 0x1f;
virge->ma_ext = val & 0x1f;
break;
case 0x35:
s3_bank = (s3_bank & 0x70) | (val & 0xf);
virge->bank = (virge->bank & 0x70) | (val & 0xf);
// pclog("CRTC write R35 %02X\n", val);
if (chain4) svgawbank = svgarbank = s3_bank << 16;
else svgawbank = svgarbank = s3_bank << 14;
if (svga->chain4) svga->write_bank = svga->read_bank = virge->bank << 16;
else svga->write_bank = svga->read_bank = virge->bank << 14;
break;
case 0x51:
s3_bank = (s3_bank & 0x4f) | ((val & 0xc) << 2);
if (chain4) svgawbank = svgarbank = s3_bank << 16;
else svgawbank = svgarbank = s3_bank << 14;
s3_ma_ext = (s3_ma_ext & ~0xc) | ((val & 3) << 2);
virge->bank = (virge->bank & 0x4f) | ((val & 0xc) << 2);
if (svga->chain4) svga->write_bank = svga->read_bank = virge->bank << 16;
else svga->write_bank = svga->read_bank = virge->bank << 14;
virge->ma_ext = (virge->ma_ext & ~0xc) | ((val & 3) << 2);
break;
case 0x6a:
s3_bank = val;
virge->bank = val;
// pclog("CRTC write R6a %02X\n", val);
if (chain4) svgawbank = svgarbank = s3_bank << 16;
else svgawbank = svgarbank = s3_bank << 14;
if (svga->chain4) svga->write_bank = svga->read_bank = virge->bank << 16;
else svga->write_bank = svga->read_bank = virge->bank << 14;
break;
case 0x3a:
if (val & 0x10) gdcreg[5] |= 0x40; /*Horrible cheat*/
if (val & 0x10) svga->gdcreg[5] |= 0x40; /*Horrible cheat*/
break;
case 0x45:
svga_hwcursor.ena = val & 1;
svga->hwcursor.ena = val & 1;
break;
case 0x48:
svga_hwcursor.x = ((crtc[0x46] << 8) | crtc[0x47]) & 0x7ff;
if (bpp == 32) svga_hwcursor.x >>= 1;
svga_hwcursor.y = ((crtc[0x48] << 8) | crtc[0x49]) & 0x7ff;
svga_hwcursor.xoff = crtc[0x4e] & 63;
svga_hwcursor.yoff = crtc[0x4f] & 63;
svga_hwcursor.addr = ((((crtc[0x4c] << 8) | crtc[0x4d]) & 0xfff) * 1024) + (svga_hwcursor.yoff * 16);
svga->hwcursor.x = ((svga->crtc[0x46] << 8) | svga->crtc[0x47]) & 0x7ff;
if (svga->bpp == 32) svga->hwcursor.x >>= 1;
svga->hwcursor.y = ((svga->crtc[0x48] << 8) | svga->crtc[0x49]) & 0x7ff;
svga->hwcursor.xoff = svga->crtc[0x4e] & 63;
svga->hwcursor.yoff = svga->crtc[0x4f] & 63;
svga->hwcursor.addr = ((((svga->crtc[0x4c] << 8) | svga->crtc[0x4d]) & 0xfff) * 1024) + (svga->hwcursor.yoff * 16);
break;
case 0x53:
case 0x58: case 0x59: case 0x5a:
s3_virge_updatemapping();
s3_virge_updatemapping(virge);
break;
case 0x67:
switch (val >> 4)
{
case 3: bpp = 15; break;
case 5: bpp = 16; break;
case 7: bpp = 24; break;
case 13: bpp = 32; break;
default: bpp = 8; break;
case 3: svga->bpp = 15; break;
case 5: svga->bpp = 16; break;
case 7: svga->bpp = 24; break;
case 13: svga->bpp = 32; break;
default: svga->bpp = 8; break;
}
break;
//case 0x55: case 0x43:
// pclog("Write CRTC R%02X %02X\n", crtcreg, val);
}
if (old!=val)
if (old != val)
{
if (crtcreg<0xE || crtcreg>0x10)
if (svga->crtcreg < 0xe || svga->crtcreg > 0x10)
{
fullchange=changeframecount;
svga_recalctimings();
fullchange = changeframecount;
svga_recalctimings(svga);
}
}
break;
}
svga_out(addr, val, NULL);
svga_out(addr, val, svga);
}
uint8_t s3_virge_in(uint16_t addr, void *priv)
uint8_t s3_virge_in(uint16_t addr, void *p)
{
if (((addr&0xFFF0) == 0x3D0 || (addr&0xFFF0) == 0x3B0) && !(svga_miscout&1)) addr ^= 0x60;
virge_t *virge = (virge_t *)p;
svga_t *svga = &virge->svga;
if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(svga->miscout & 1))
addr ^= 0x60;
if (addr != 0x3da) pclog("S3 in %04X %04X:%08X\n", addr, CS, pc);
switch (addr)
@ -164,221 +185,221 @@ uint8_t s3_virge_in(uint16_t addr, void *priv)
//return sdac_ramdac_in(addr);
case 0x3c5:
if (seqaddr >= 0x10)
return seqregs[seqaddr&0x1F];
if (svga->seqaddr >= 0x10)
return svga->seqregs[svga->seqaddr & 0x1f];
break;
case 0x3D4:
return crtcreg;
return svga->crtcreg;
case 0x3D5:
// pclog("Read CRTC R%02X %04X:%04X\n", crtcreg, CS, pc);
switch (crtcreg)
switch (svga->crtcreg)
{
case 0x2d: return s3_virge_id_high; /*Extended chip ID*/
case 0x2e: return s3_virge_id_low; /*New chip ID*/
case 0x2f: return s3_virge_rev;
case 0x30: return s3_virge_id; /*Chip ID*/
case 0x31: return (crtc[0x31] & 0xcf) | ((s3_ma_ext & 3) << 4);
case 0x35: return (crtc[0x35] & 0xf0) | (s3_bank & 0xf);
case 0x51: return (crtc[0x51] & 0xf0) | ((s3_bank >> 2) & 0xc) | ((s3_ma_ext >> 2) & 3);
case 0x69: return s3_ma_ext;
case 0x6a: return s3_bank;
case 0x2d: return virge->virge_id_high; /*Extended chip ID*/
case 0x2e: return virge->virge_id_low; /*New chip ID*/
case 0x2f: return virge->virge_rev;
case 0x30: return virge->virge_id; /*Chip ID*/
case 0x31: return (svga->crtc[0x31] & 0xcf) | ((virge->ma_ext & 3) << 4);
case 0x35: return (svga->crtc[0x35] & 0xf0) | (virge->bank & 0xf);
case 0x51: return (svga->crtc[0x51] & 0xf0) | ((virge->bank >> 2) & 0xc) | ((virge->ma_ext >> 2) & 3);
case 0x69: return virge->ma_ext;
case 0x6a: return virge->bank;
}
return crtc[crtcreg];
return svga->crtc[svga->crtcreg];
}
return svga_in(addr, NULL);
return svga_in(addr, svga);
}
void s3_virge_recalctimings()
void s3_virge_recalctimings(svga_t *svga)
{
virge_t *virge = (virge_t *)svga->p;
// pclog("recalctimings\n");
svga_ma |= (s3_ma_ext << 16);
svga->ma_latch |= (virge->ma_ext << 16);
// pclog("SVGA_MA %08X\n", svga_ma);
// if (gdcreg[5] & 0x40) svga_lowres = !(crtc[0x3a] & 0x10);
if ((gdcreg[5] & 0x40) && (crtc[0x3a] & 0x10))
if ((svga->gdcreg[5] & 0x40) && (svga->crtc[0x3a] & 0x10))
{
switch (bpp)
switch (svga->bpp)
{
case 8:
svga_render = svga_render_8bpp_highres;
svga->render = svga_render_8bpp_highres;
break;
case 15:
svga_render = svga_render_15bpp_highres;
svga->render = svga_render_15bpp_highres;
break;
case 16:
svga_render = svga_render_16bpp_highres;
svga->render = svga_render_16bpp_highres;
break;
case 24:
svga_render = svga_render_24bpp_highres;
svga->render = svga_render_24bpp_highres;
break;
case 32:
svga_render = svga_render_32bpp_highres;
svga->render = svga_render_32bpp_highres;
break;
}
}
if (crtc[0x5d] & 0x01) svga_htotal += 0x100;
if (crtc[0x5d] & 0x02) svga_hdisp += 0x100;
if (crtc[0x5e] & 0x01) svga_vtotal += 0x400;
if (crtc[0x5e] & 0x02) svga_dispend += 0x400;
if (crtc[0x5e] & 0x10) svga_vsyncstart += 0x400;
if (crtc[0x5e] & 0x40) svga_split += 0x400;
if (crtc[0x51] & 0x30) svga_rowoffset += (crtc[0x51] & 0x30) << 4;
else if (crtc[0x43] & 0x04) svga_rowoffset += 0x100;
if (!svga_rowoffset) svga_rowoffset = 256;
svga_interlace = crtc[0x42] & 0x20;
if (bpp == 32)
if (svga->crtc[0x5d] & 0x01) svga->htotal += 0x100;
if (svga->crtc[0x5d] & 0x02) svga->hdisp += 0x100;
if (svga->crtc[0x5e] & 0x01) svga->vtotal += 0x400;
if (svga->crtc[0x5e] & 0x02) svga->dispend += 0x400;
if (svga->crtc[0x5e] & 0x10) svga->vsyncstart += 0x400;
if (svga->crtc[0x5e] & 0x40) svga->split += 0x400;
if (svga->crtc[0x51] & 0x30) svga->rowoffset += (svga->crtc[0x51] & 0x30) << 4;
else if (svga->crtc[0x43] & 0x04) svga->rowoffset += 0x100;
if (!svga->rowoffset) svga->rowoffset = 256;
svga->interlace = svga->crtc[0x42] & 0x20;
if (svga->bpp == 32)
{
svga_htotal <<= 2;
svga_hdisp <<= 2;
svga->htotal <<= 2;
svga->hdisp <<= 2;
}
//svga_clock = cpuclock / sdac_getclock((svga_miscout >> 2) & 3);
// pclog("SVGA_CLOCK = %f %02X %f\n", svga_clock, svga_miscout, cpuclock);
//if (bpp > 8) svga_clock /= 2;
}
static uint32_t s3_linear_base = 0, s3_linear_size = 0;
void s3_virge_updatemapping()
void s3_virge_updatemapping(virge_t *virge)
{
mem_removehandler(s3_linear_base, s3_linear_size, svga_read_linear, svga_readw_linear, svga_readl_linear, svga_write_linear, svga_writew_linear, svga_writel_linear, NULL);
svga_t *svga = &virge->svga;
mem_removehandler(virge->linear_base, virge->linear_size, svga_read_linear, svga_readw_linear, svga_readl_linear, svga_write_linear, svga_writew_linear, svga_writel_linear, svga);
// video_write_a000_w = video_write_a000_l = NULL;
mem_removehandler(0xa0000, 0x20000, svga_read, svga_readw, svga_readl, svga_write, svga_writew, svga_writel, NULL);
mem_removehandler(0xa0000, 0x20000, s3_virge_mmio_read, s3_virge_mmio_read_w, s3_virge_mmio_read_l, s3_virge_mmio_write, s3_virge_mmio_write_w, s3_virge_mmio_write_l, NULL);
pclog("Update mapping - bank %02X ", gdcreg[6] & 0xc);
switch (gdcreg[6] & 0xc) /*Banked framebuffer*/
mem_removehandler(0xa0000, 0x20000, svga_read, svga_readw, svga_readl, svga_write, svga_writew, svga_writel, svga);
mem_removehandler(0xa0000, 0x20000, s3_virge_mmio_read, s3_virge_mmio_read_w, s3_virge_mmio_read_l, s3_virge_mmio_write, s3_virge_mmio_write_w, s3_virge_mmio_write_l, virge);
pclog("Update mapping - bank %02X ", svga->gdcreg[6] & 0xc);
switch (svga->gdcreg[6] & 0xc) /*Banked framebuffer*/
{
case 0x0: /*128k at A0000*/
mem_sethandler(0xa0000, 0x20000, svga_read, svga_readw, svga_readl, svga_write, svga_writew, svga_writel, NULL);
mem_sethandler(0xa0000, 0x20000, svga_read, svga_readw, svga_readl, svga_write, svga_writew, svga_writel, svga);
break;
case 0x4: /*64k at A0000*/
mem_sethandler(0xa0000, 0x10000, svga_read, svga_readw, svga_readl, svga_write, svga_writew, svga_writel, NULL);
mem_sethandler(0xa0000, 0x10000, svga_read, svga_readw, svga_readl, svga_write, svga_writew, svga_writel, svga);
break;
case 0x8: /*32k at B0000*/
mem_sethandler(0xb0000, 0x08000, svga_read, svga_readw, svga_readl, svga_write, svga_writew, svga_writel, NULL);
mem_sethandler(0xb0000, 0x08000, svga_read, svga_readw, svga_readl, svga_write, svga_writew, svga_writel, svga);
break;
case 0xC: /*32k at B8000*/
mem_sethandler(0xb8000, 0x08000, svga_read, svga_readw, svga_readl, svga_write, svga_writew, svga_writel, NULL);
mem_sethandler(0xb8000, 0x08000, svga_read, svga_readw, svga_readl, svga_write, svga_writew, svga_writel, svga);
break;
}
pclog("Linear framebuffer %02X ", crtc[0x58] & 0x10);
if (crtc[0x58] & 0x10) /*Linear framebuffer*/
pclog("Linear framebuffer %02X ", svga->crtc[0x58] & 0x10);
if (svga->crtc[0x58] & 0x10) /*Linear framebuffer*/
{
s3_linear_base = (crtc[0x5a] << 16) | (crtc[0x59] << 24);
switch (crtc[0x58] & 3)
virge->linear_base = (svga->crtc[0x5a] << 16) | (svga->crtc[0x59] << 24);
switch (svga->crtc[0x58] & 3)
{
case 0: /*64k*/
s3_linear_size = 0x10000;
virge->linear_size = 0x10000;
break;
case 1: /*1mb*/
s3_linear_size = 0x100000;
virge->linear_size = 0x100000;
break;
case 2: /*2mb*/
s3_linear_size = 0x200000;
virge->linear_size = 0x200000;
break;
case 3: /*8mb*/
s3_linear_size = 0x400000;
virge->linear_size = 0x400000;
break;
}
s3_linear_base &= ~(s3_linear_size - 1);
virge->linear_base &= ~(virge->linear_size - 1);
// pclog("%08X %08X %02X %02X %02X\n", linear_base, linear_size, crtc[0x58], crtc[0x59], crtc[0x5a]);
pclog("Linear framebuffer at %08X size %08X\n", s3_linear_base, s3_linear_size);
if (s3_linear_base == 0xa0000)
mem_sethandler(0xa0000, 0x10000, svga_read, svga_readw, svga_readl, svga_write, svga_writew, svga_writel, NULL);
pclog("Linear framebuffer at %08X size %08X\n", virge->linear_base, virge->linear_size);
if (virge->linear_base == 0xa0000)
mem_sethandler(0xa0000, 0x10000, svga_read, svga_readw, svga_readl, svga_write, svga_writew, svga_writel, svga);
else
mem_sethandler(s3_linear_base, s3_linear_size, svga_read_linear, svga_readw_linear, svga_readl_linear, svga_write_linear, svga_writew_linear, svga_writel_linear, NULL);
mem_sethandler(virge->linear_base, virge->linear_size, svga_read_linear, svga_readw_linear, svga_readl_linear, svga_write_linear, svga_writew_linear, svga_writel_linear, svga);
}
pclog("Memory mapped IO %02X\n", crtc[0x53] & 0x18);
output = 0;
if ((crtc[0x53] & 0x18) == 0x10) /*Memory mapped IO*/
pclog("Memory mapped IO %02X\n", svga->crtc[0x53] & 0x18);
if ((svga->crtc[0x53] & 0x18) == 0x10) /*Memory mapped IO*/
{
output = 3;
if (crtc[0x53] & 0x20)
mem_sethandler(0xb8000, 0x8000, s3_virge_mmio_read, s3_virge_mmio_read_w, s3_virge_mmio_read_l, s3_virge_mmio_write, s3_virge_mmio_write_w, s3_virge_mmio_write_l, NULL);
if (svga->crtc[0x53] & 0x20)
mem_sethandler(0xb8000, 0x8000, s3_virge_mmio_read, s3_virge_mmio_read_w, s3_virge_mmio_read_l, s3_virge_mmio_write, s3_virge_mmio_write_w, s3_virge_mmio_write_l, virge);
else
mem_sethandler(0xa8000, 0x8000, s3_virge_mmio_read, s3_virge_mmio_read_w, s3_virge_mmio_read_l, s3_virge_mmio_write, s3_virge_mmio_write_w, s3_virge_mmio_write_l, NULL);
mem_sethandler(0xa8000, 0x8000, s3_virge_mmio_read, s3_virge_mmio_read_w, s3_virge_mmio_read_l, s3_virge_mmio_write, s3_virge_mmio_write_w, s3_virge_mmio_write_l, virge);
}
}
uint8_t s3_virge_mmio_read(uint32_t addr, void *priv)
uint8_t s3_virge_mmio_read(uint32_t addr, void *p)
{
pclog("MMIO readb %08X\n", addr);
return 0xff;
}
uint16_t s3_virge_mmio_read_w(uint32_t addr, void *priv)
uint16_t s3_virge_mmio_read_w(uint32_t addr, void *p)
{
pclog("MMIO readw %08X\n", addr);
return 0xffff;
}
uint32_t s3_virge_mmio_read_l(uint32_t addr, void *priv)
uint32_t s3_virge_mmio_read_l(uint32_t addr, void *p)
{
pclog("MMIO readl %08X\n", addr);
return 0xffffffff;
}
void s3_virge_mmio_write(uint32_t addr, uint8_t val, void *priv)
void s3_virge_mmio_write(uint32_t addr, uint8_t val, void *p)
{
pclog("MMIO writeb %08X %02X\n", addr, val);
}
void s3_virge_mmio_write_w(uint32_t addr, uint16_t val, void *priv)
void s3_virge_mmio_write_w(uint32_t addr, uint16_t val, void *p)
{
pclog("MMIO writew %08X %04X\n", addr, val);
}
void s3_virge_mmio_write_l(uint32_t addr, uint32_t val, void *priv)
void s3_virge_mmio_write_l(uint32_t addr, uint32_t val, void *p)
{
pclog("MMIO writel %08X %08X\n", addr, val);
}
void s3_virge_hwcursor_draw(int displine)
void s3_virge_hwcursor_draw(svga_t *svga, int displine)
{
int x;
uint16_t dat[2];
int xx;
int offset = svga_hwcursor_latch.x - svga_hwcursor_latch.xoff;
int offset = svga->hwcursor_latch.x - svga->hwcursor_latch.xoff;
pclog("HWcursor %i %i\n", svga_hwcursor_latch.x, svga_hwcursor_latch.y);
pclog("HWcursor %i %i\n", svga->hwcursor_latch.x, svga->hwcursor_latch.y);
for (x = 0; x < 64; x += 16)
{
dat[0] = (vram[svga_hwcursor_latch.addr] << 8) | vram[svga_hwcursor_latch.addr + 1];
dat[1] = (vram[svga_hwcursor_latch.addr + 2] << 8) | vram[svga_hwcursor_latch.addr + 3];
dat[0] = (svga->vram[svga->hwcursor_latch.addr] << 8) | svga->vram[svga->hwcursor_latch.addr + 1];
dat[1] = (svga->vram[svga->hwcursor_latch.addr + 2] << 8) | svga->vram[svga->hwcursor_latch.addr + 3];
for (xx = 0; xx < 16; xx++)
{
if (offset >= svga_hwcursor_latch.x)
if (offset >= svga->hwcursor_latch.x)
{
if (!(dat[0] & 0x8000))
((uint32_t *)buffer32->line[displine])[offset + 32] = (dat[1] & 0x8000) ? 0xffffff : 0;
else if (dat[1] & 0x8000)
((uint32_t *)buffer32->line[displine])[offset + 32] ^= 0xffffff;
// pclog("Plot %i, %i (%i %i) %04X %04X\n", offset, displine, x+xx, svga_hwcursor_on, dat[0], dat[1]);
// pclog("Plot %i, %i (%i %i) %04X %04X\n", offset, displine, x+xx, svga->hwcursor_on, dat[0], dat[1]);
}
offset++;
dat[0] <<= 1;
dat[1] <<= 1;
}
svga_hwcursor_latch.addr += 4;
svga->hwcursor_latch.addr += 4;
}
}
static uint8_t s3_virge_pci_regs[256];
uint8_t s3_virge_pci_read(int func, int addr, void *priv)
uint8_t s3_virge_pci_read(int func, int addr, void *p)
{
virge_t *virge = (virge_t *)p;
svga_t *svga = &virge->svga;
// pclog("S3 PCI read %08X\n", addr);
switch (addr)
{
case 0x00: return 0x33; /*'S3'*/
case 0x01: return 0x53;
case 0x02: return s3_virge_id_low;
case 0x03: return s3_virge_id_high;
case 0x02: return virge->virge_id_low;
case 0x03: return virge->virge_id_high;
case 0x08: return 0; /*Revision ID*/
case 0x09: return 0; /*Programming interface*/
@ -389,7 +410,7 @@ uint8_t s3_virge_pci_read(int func, int addr, void *priv)
case 0x10: return 0x00; /*Linear frame buffer address*/
case 0x11: return 0x00;
case 0x12: return 0x00;
case 0x13: return crtc[0x59] & 0xfc;
case 0x13: return svga->crtc[0x59] & 0xfc;
case 0x30: return 0x01; /*BIOS ROM address*/
case 0x31: return 0x00;
@ -397,11 +418,14 @@ uint8_t s3_virge_pci_read(int func, int addr, void *priv)
case 0x33: return 0x00;
}
return s3_virge_pci_regs[addr];
return virge->pci_regs[addr];
}
void s3_virge_pci_write(int func, int addr, uint8_t val, void *priv)
void s3_virge_pci_write(int func, int addr, uint8_t val, void *p)
{
virge_t *virge = (virge_t *)p;
svga_t *svga = &virge->svga;
switch (addr)
{
case 0x00: case 0x01: case 0x02: case 0x03:
@ -409,59 +433,68 @@ void s3_virge_pci_write(int func, int addr, uint8_t val, void *priv)
case 0x3d: case 0x3e: case 0x3f:
break;
case 0x13: crtc[0x59] = val & 0xfc; s3_virge_updatemapping(); break;
case 0x13:
svga->crtc[0x59] = val & 0xfc;
s3_virge_updatemapping(virge);
break;
}
s3_virge_pci_regs[addr] = val;
virge->pci_regs[addr] = val;
}
int s3_virge_init()
void *s3_virge_init()
{
s3_virge_pci_regs[4] = 3;
s3_virge_pci_regs[5] = 0;
s3_virge_pci_regs[6] = 0;
s3_virge_pci_regs[7] = 2;
s3_virge_pci_regs[0x3d] = 1;
s3_virge_pci_regs[0x3e] = 4;
s3_virge_pci_regs[0x3f] = 0xff;
virge_t *virge = malloc(sizeof(virge_t));
memset(virge, 0, sizeof(virge_t));
svga_init(&virge->svga, virge, 1 << 22, /*4mb*/
s3_virge_recalctimings,
s3_virge_in, s3_virge_out,
s3_virge_hwcursor_draw);
io_sethandler(0x03c0, 0x0020, s3_virge_in, NULL, NULL, s3_virge_out, NULL, NULL, virge);
virge->pci_regs[4] = 3;
virge->pci_regs[5] = 0;
virge->pci_regs[6] = 0;
virge->pci_regs[7] = 2;
virge->pci_regs[0x3d] = 1;
virge->pci_regs[0x3e] = 4;
virge->pci_regs[0x3f] = 0xff;
s3_virge_id_high = 0x56;
s3_virge_id_low = 0x31;
s3_virge_rev = 0;
s3_virge_id = 0xe1;
virge->virge_id_high = 0x56;
virge->virge_id_low = 0x31;
virge->virge_rev = 0;
virge->virge_id = 0xe1;
svga_recalctimings_ex = s3_virge_recalctimings;
svga_hwcursor_draw = s3_virge_hwcursor_draw;
crtc[0x36] = 1 | (2 << 2) | (1 << 4) | (4 << 5);
crtc[0x37] = 1 | (7 << 5);
virge->svga.crtc[0x36] = 1 | (2 << 2) | (1 << 4) | (4 << 5);
virge->svga.crtc[0x37] = 1 | (7 << 5);
vrammask = 0x3fffff;
pci_add(s3_virge_pci_read, s3_virge_pci_write, NULL);
pci_add(s3_virge_pci_read, s3_virge_pci_write, virge);
svga_vram_limit = 4 << 20; /*4mb*/
return svga_init();
return virge;
}
GFXCARD vid_s3_virge =
void s3_virge_close(void *p)
{
virge_t *virge = (virge_t *)p;
svga_close(&virge->svga);
free(virge);
}
void s3_virge_speed_changed(void *p)
{
virge_t *virge = (virge_t *)p;
svga_recalctimings(&virge->svga);
}
device_t s3_virge_device =
{
"Diamond Stealth 3D 2000 (S3 VIRGE)",
s3_virge_init,
/*IO at 3Cx/3Dx*/
s3_virge_out,
s3_virge_in,
/*IO at 3Ax/3Bx*/
video_out_null,
video_in_null,
svga_poll,
svga_recalctimings,
svga_write,
video_write_null,
video_write_null,
svga_read,
video_read_null,
video_read_null
s3_virge_close,
s3_virge_speed_changed,
svga_add_status_info
};

1
src/vid_s3_virge.h Normal file
View file

@ -0,0 +1 @@
extern device_t s3_virge_device;

View file

@ -5,17 +5,7 @@
#include "vid_svga.h"
#include "vid_sdac_ramdac.h"
struct
{
int magic_count;
uint8_t command;
int windex, rindex;
uint16_t regs[256];
int reg_ff;
int rs2;
} sdac_ramdac;
void sdac_ramdac_out(uint16_t addr, uint8_t val, void *priv)
void sdac_ramdac_out(uint16_t addr, uint8_t val, sdac_ramdac_t *ramdac, svga_t *svga)
{
// /*if (CS!=0xC000) */pclog("OUT RAMDAC %04X %02X %i %04X:%04X %i\n",addr,val,sdac_ramdac.magic_count,CS,pc, sdac_ramdac.rs2);
switch (addr)
@ -23,125 +13,125 @@ void sdac_ramdac_out(uint16_t addr, uint8_t val, void *priv)
case 0x3C6:
if (val == 0xff)
{
sdac_ramdac.rs2 = 0;
sdac_ramdac.magic_count = 0;
ramdac->rs2 = 0;
ramdac->magic_count = 0;
break;
}
if (sdac_ramdac.magic_count < 4) break;
if (sdac_ramdac.magic_count == 4)
if (ramdac->magic_count < 4) break;
if (ramdac->magic_count == 4)
{
sdac_ramdac.command = val;
ramdac->command = val;
// pclog("RAMDAC command reg now %02X\n", val);
switch (val >> 4)
{
case 2: case 3: case 0xa: bpp = 15; break;
case 4: case 0xe: bpp = 24; break;
case 5: case 6: case 0xc: bpp = 16; break;
case 7: bpp = 32; break;
case 0x2: case 0x3: case 0xa: svga->bpp = 15; break;
case 0x4: case 0xe: svga->bpp = 24; break;
case 0x5: case 0x6: case 0xc: svga->bpp = 16; break;
case 0x7: svga->bpp = 32; break;
case 0: case 1: default: bpp = 8; break;
case 0: case 1: default: svga->bpp = 8; break;
}
}
//sdac_ramdac.magic_count = 0;
//ramdac->magic_count = 0;
break;
case 0x3C7:
sdac_ramdac.magic_count = 0;
if (sdac_ramdac.rs2)
sdac_ramdac.rindex = val;
ramdac->magic_count = 0;
if (ramdac->rs2)
ramdac->rindex = val;
break;
case 0x3C8:
sdac_ramdac.magic_count = 0;
if (sdac_ramdac.rs2)
sdac_ramdac.windex = val;
ramdac->magic_count = 0;
if (ramdac->rs2)
ramdac->windex = val;
break;
case 0x3C9:
sdac_ramdac.magic_count = 0;
if (sdac_ramdac.rs2)
ramdac->magic_count = 0;
if (ramdac->rs2)
{
if (!sdac_ramdac.reg_ff) sdac_ramdac.regs[sdac_ramdac.windex] = (sdac_ramdac.regs[sdac_ramdac.windex] & 0xff00) | val;
else sdac_ramdac.regs[sdac_ramdac.windex] = (sdac_ramdac.regs[sdac_ramdac.windex] & 0x00ff) | (val << 8);
sdac_ramdac.reg_ff = !sdac_ramdac.reg_ff;
// pclog("RAMDAC reg %02X now %04X\n", sdac_ramdac.windex, sdac_ramdac.regs[sdac_ramdac.windex]);
if (!sdac_ramdac.reg_ff) sdac_ramdac.windex++;
if (!ramdac->reg_ff) ramdac->regs[ramdac->windex] = (ramdac->regs[ramdac->windex] & 0xff00) | val;
else ramdac->regs[ramdac->windex] = (ramdac->regs[ramdac->windex] & 0x00ff) | (val << 8);
ramdac->reg_ff = !ramdac->reg_ff;
// pclog("RAMDAC reg %02X now %04X\n", ramdac->windex, ramdac->regs[ramdac->windex]);
if (!ramdac->reg_ff) ramdac->windex++;
}
break;
}
svga_out(addr, val, NULL);
svga_out(addr, val, svga);
}
uint8_t sdac_ramdac_in(uint16_t addr, void *priv)
uint8_t sdac_ramdac_in(uint16_t addr, sdac_ramdac_t *ramdac, svga_t *svga)
{
uint8_t temp;
// /*if (CS!=0xC000) */pclog("IN RAMDAC %04X %04X:%04X %i\n",addr,CS,pc, sdac_ramdac.rs2);
// /*if (CS!=0xC000) */pclog("IN RAMDAC %04X %04X:%04X %i\n",addr,CS,pc, ramdac->rs2);
switch (addr)
{
case 0x3C6:
sdac_ramdac.reg_ff = 0;
if (sdac_ramdac.magic_count < 5)
sdac_ramdac.magic_count++;
if (sdac_ramdac.magic_count == 4)
ramdac->reg_ff = 0;
if (ramdac->magic_count < 5)
ramdac->magic_count++;
if (ramdac->magic_count == 4)
{
temp = 0x70; /*SDAC ID*/
sdac_ramdac.rs2 = 1;
ramdac->rs2 = 1;
}
if (sdac_ramdac.magic_count == 5)
if (ramdac->magic_count == 5)
{
temp = sdac_ramdac.command;
sdac_ramdac.magic_count = 0;
temp = ramdac->command;
ramdac->magic_count = 0;
}
return temp;
case 0x3C7:
// if (sdac_ramdac.magic_count < 4)
// if (ramdac->magic_count < 4)
// {
sdac_ramdac.magic_count=0;
ramdac->magic_count=0;
// break;
// }
if (sdac_ramdac.rs2) return sdac_ramdac.rindex;
if (ramdac->rs2) return ramdac->rindex;
break;
case 0x3C8:
// if (sdac_ramdac.magic_count < 4)
// if (ramdac->magic_count < 4)
// {
sdac_ramdac.magic_count=0;
ramdac->magic_count=0;
// break;
// }
if (sdac_ramdac.rs2) return sdac_ramdac.windex;
if (ramdac->rs2) return ramdac->windex;
break;
case 0x3C9:
// if (sdac_ramdac.magic_count < 4)
// if (ramdac->magic_count < 4)
// {
sdac_ramdac.magic_count=0;
ramdac->magic_count=0;
// break;
// }
if (sdac_ramdac.rs2)
if (ramdac->rs2)
{
if (!sdac_ramdac.reg_ff) temp = sdac_ramdac.regs[sdac_ramdac.rindex] & 0xff;
else temp = sdac_ramdac.regs[sdac_ramdac.rindex] >> 8;
sdac_ramdac.reg_ff = !sdac_ramdac.reg_ff;
if (!sdac_ramdac.reg_ff)
if (!ramdac->reg_ff) temp = ramdac->regs[ramdac->rindex] & 0xff;
else temp = ramdac->regs[ramdac->rindex] >> 8;
ramdac->reg_ff = !ramdac->reg_ff;
if (!ramdac->reg_ff)
{
sdac_ramdac.rindex++;
sdac_ramdac.magic_count = 0;
ramdac->rindex++;
ramdac->magic_count = 0;
}
return temp;
}
break;
}
return svga_in(addr, NULL);
return svga_in(addr, svga);
}
float sdac_getclock(int clock)
float sdac_getclock(int clock, sdac_ramdac_t *ramdac)
{
float t;
int m, n1, n2;
// pclog("SDAC_Getclock %i %04X\n", clock, sdac_ramdac.regs[clock]);
// pclog("SDAC_Getclock %i %04X\n", clock, ramdac->regs[clock]);
if (clock == 0) return 25175000.0;
if (clock == 1) return 28322000.0;
clock ^= 1; /*Clocks 2 and 3 seem to be reversed*/
m = (sdac_ramdac.regs[clock] & 0x7f) + 2;
n1 = ((sdac_ramdac.regs[clock] >> 8) & 0x1f) + 2;
n2 = ((sdac_ramdac.regs[clock] >> 13) & 0x07);
m = (ramdac->regs[clock] & 0x7f) + 2;
n1 = ((ramdac->regs[clock] >> 8) & 0x1f) + 2;
n2 = ((ramdac->regs[clock] >> 13) & 0x07);
t = (14318184.0 * ((float)m / (float)n1)) / (float)(1 << n2);
// pclog("SDAC clock %i %i %i %f %04X %f %i\n", m, n1, n2, t, sdac_ramdac.regs[2], 14318184.0 * ((float)m / (float)n1), 1 << n2);
// pclog("SDAC clock %i %i %i %f %04X %f %i\n", m, n1, n2, t, ramdac->regs[2], 14318184.0 * ((float)m / (float)n1), 1 << n2);
return t;
}

View file

@ -1,4 +1,14 @@
void sdac_ramdac_out(uint16_t addr, uint8_t val, void *priv);
uint8_t sdac_ramdac_in(uint16_t addr, void *priv);
typedef struct sdac_ramdac_t
{
int magic_count;
uint8_t command;
int windex, rindex;
uint16_t regs[256];
int reg_ff;
int rs2;
} sdac_ramdac_t;
float sdac_getclock(int clock);
void sdac_ramdac_out(uint16_t addr, uint8_t val, sdac_ramdac_t *ramdac, svga_t *svga);
uint8_t sdac_ramdac_in(uint16_t addr, sdac_ramdac_t *ramdac, svga_t *svga);
float sdac_getclock(int clock, sdac_ramdac_t *ramdac);

View file

@ -4,101 +4,114 @@
#include "vid_svga.h"
#include "vid_stg_ramdac.h"
struct
{
int magic_count;
uint8_t command;
int index;
uint8_t regs[256];
} stg_ramdac;
static int stg_state_read[2][8] = {{1,2,3,4,0,0,0,0}, {1,2,3,4,5,6,7,7}};
static int stg_state_write[8] = {0,0,0,0,0,6,7,7};
int stg_state_read[2][8]={{1,2,3,4,0,0,0,0}, {1,2,3,4,5,6,7,7}};
int stg_state_write[8]={0,0,0,0,0,6,7,7};
void stg_ramdac_out(uint16_t addr, uint8_t val, void *priv)
void stg_ramdac_out(uint16_t addr, uint8_t val, stg_ramdac_t *ramdac, svga_t *svga)
{
int didwrite;
//if (CS!=0xC000) pclog("OUT RAMDAC %04X %02X %i %04X:%04X\n",addr,val,stg_ramdac.magic_count,CS,pc);
switch (addr)
{
case 0x3C6:
switch (stg_ramdac.magic_count)
case 0x3c6:
switch (ramdac->magic_count)
{
case 0: case 1: case 2: case 3: break;
case 4: stg_ramdac.command=val; /*pclog("Write RAMDAC command %02X\n",val);*/ break;
case 5: stg_ramdac.index=(stg_ramdac.index&0xFF00)|val; break;
case 6: stg_ramdac.index=(stg_ramdac.index&0xFF)|(val<<8); break;
case 0: case 1: case 2: case 3:
break;
case 4:
ramdac->command = val;
/*pclog("Write RAMDAC command %02X\n",val);*/
break;
case 5:
ramdac->index = (ramdac->index & 0xff00) | val;
break;
case 6:
ramdac->index = (ramdac->index & 0xff) | (val << 8);
break;
case 7:
pclog("Write RAMDAC reg %02X %02X\n", stg_ramdac.index, val);
if (stg_ramdac.index<0x100) stg_ramdac.regs[stg_ramdac.index]=val;
stg_ramdac.index++;
pclog("Write RAMDAC reg %02X %02X\n", ramdac->index, val);
if (ramdac->index < 0x100)
ramdac->regs[ramdac->index] = val;
ramdac->index++;
break;
}
didwrite = (stg_ramdac.magic_count>=4);
stg_ramdac.magic_count=stg_state_write[stg_ramdac.magic_count&7];
if (stg_ramdac.command&8)
didwrite = (ramdac->magic_count >= 4);
ramdac->magic_count = stg_state_write[ramdac->magic_count & 7];
if (ramdac->command & 8)
{
switch (stg_ramdac.regs[3])
switch (ramdac->regs[3])
{
case 0: case 5: case 7: bpp=8; break;
case 1: case 2: case 8: bpp=15; break;
case 3: case 6: bpp=16; break;
case 4: case 9: bpp=24; break;
default: bpp=8; break;
case 0: case 5: case 7: svga->bpp = 8; break;
case 1: case 2: case 8: svga->bpp = 15; break;
case 3: case 6: svga->bpp = 16; break;
case 4: case 9: svga->bpp = 24; break;
default: svga->bpp = 8; break;
}
}
else
{
switch (stg_ramdac.command>>5)
switch (ramdac->command >> 5)
{
case 0: bpp=8; break;
case 5: bpp=15; break;
case 6: bpp=16; break;
case 7: bpp=24; break;
default: bpp=8; break;
case 0: svga->bpp = 8; break;
case 5: svga->bpp = 15; break;
case 6: svga->bpp = 16; break;
case 7: svga->bpp = 24; break;
default: svga->bpp = 8; break;
}
}
if (didwrite) return;
break;
case 0x3C7: case 0x3C8: case 0x3C9:
stg_ramdac.magic_count=0;
case 0x3c7: case 0x3c8: case 0x3c9:
ramdac->magic_count=0;
break;
}
svga_out(addr, val, NULL);
svga_out(addr, val, svga);
}
uint8_t stg_ramdac_in(uint16_t addr, void *priv)
uint8_t stg_ramdac_in(uint16_t addr, stg_ramdac_t *ramdac, svga_t *svga)
{
uint8_t temp;
//if (CS!=0xC000) pclog("IN RAMDAC %04X %04X:%04X\n",addr,CS,pc);
switch (addr)
{
case 0x3C6:
switch (stg_ramdac.magic_count)
case 0x3c6:
switch (ramdac->magic_count)
{
case 0: case 1: case 2: case 3: temp=0xFF; break;
case 4: temp=stg_ramdac.command; break;
case 5: temp=stg_ramdac.index&0xFF; break;
case 6: temp=stg_ramdac.index>>8; break;
case 0: case 1: case 2: case 3:
temp = 0xff;
break;
case 4:
temp = ramdac->command;
break;
case 5:
temp = ramdac->index & 0xff;
break;
case 6:
temp = ramdac->index >> 8;
break;
case 7:
// pclog("Read RAMDAC index %04X\n",stg_ramdac.index);
switch (stg_ramdac.index)
switch (ramdac->index)
{
case 0: temp=0x44; break;
case 1: temp=0x02; break;
case 0:
temp = 0x44;
break;
case 1:
temp = 0x02;
break;
default:
if (stg_ramdac.index<0x100) temp=stg_ramdac.regs[stg_ramdac.index];
else temp=0xFF;
if (ramdac->index < 0x100) temp = ramdac->regs[ramdac->index];
else temp = 0xff;
break;
}
stg_ramdac.index++;
ramdac->index++;
break;
}
stg_ramdac.magic_count=stg_state_read[(stg_ramdac.command&0x10)?1:0][stg_ramdac.magic_count&7];
ramdac->magic_count = stg_state_read[(ramdac->command & 0x10) ? 1 : 0][ramdac->magic_count & 7];
return temp;
case 0x3C8: case 0x3C9:
stg_ramdac.magic_count=0;
case 0x3c8: case 0x3c9:
ramdac->magic_count=0;
break;
}
return svga_in(addr, NULL);
return svga_in(addr, svga);
}

View file

@ -1,2 +1,10 @@
void stg_ramdac_out(uint16_t addr, uint8_t val, void *priv);
uint8_t stg_ramdac_in(uint16_t addr, void *priv);
typedef struct stg_ramdac_t
{
int magic_count;
uint8_t command;
int index;
uint8_t regs[256];
} stg_ramdac_t;
void stg_ramdac_out(uint16_t addr, uint8_t val, stg_ramdac_t *ramdac, svga_t *svga);
uint8_t stg_ramdac_in(uint16_t addr, stg_ramdac_t *ramdac, svga_t *svga);

File diff suppressed because it is too large Load diff

View file

@ -1,60 +1,123 @@
/*Vertical timings*/
extern int svga_vtotal, svga_dispend, svga_vsyncstart, svga_split;
/*Horizontal timings*/
extern int svga_hdisp, svga_htotal, svga_hdisp_time, svga_rowoffset;
/*Flags - svga_lowres = 1/2 clock in 256+ colour modes, svga_interlace = interlace mode enabled*/
extern int svga_lowres, svga_interlace;
extern int svga_linedbl, svga_rowcount;
/*Status of display on*/
extern int svga_hdisp_on;
extern double svga_clock;
extern uint32_t svga_ma;
extern void (*svga_recalctimings_ex)();
extern uint8_t svga_miscout;
extern int svga_init();
extern void svga_poll();
extern void svga_recalctimings();
typedef struct
typedef struct svga_t
{
int ena;
int x, y;
int xoff, yoff;
uint32_t addr;
} SVGA_HWCURSOR;
uint8_t crtcreg;
uint8_t crtc[128];
uint8_t gdcreg[16];
int gdcaddr;
uint8_t attrregs[32];
int attraddr, attrff;
uint8_t seqregs[64];
int seqaddr;
uint8_t miscout;
int vidclock;
uint32_t vram_limit;
uint8_t la, lb, lc, ld;
uint8_t dac_mask, dac_status;
int dac_read, dac_write, dac_pos;
uint8_t cgastat;
int fast;
uint8_t colourcompare, colournocare;
int readmode, writemode, readplane;
int chain4;
uint8_t writemask;
uint32_t charseta, charsetb;
uint8_t egapal[16];
uint32_t pallook[256];
PALETTE vgapal;
int vtotal, dispend, vsyncstart, split;
int hdisp, hdisp_old, htotal, hdisp_time, rowoffset;
int lowres, interlace;
int linedbl, rowcount;
double clock;
uint32_t ma_latch;
int bpp;
int dispontime, dispofftime;
int vidtime;
uint8_t scrblank;
int dispon;
int hdisp_on;
uint32_t ma, maback, ca;
int vc;
int sc;
int linepos, vslines, linecountff, oddeven;
int con, cursoron, blink;
int scrollcache;
int firstline, lastline;
int firstline_draw, lastline_draw;
int displine;
uint8_t *vram;
uint8_t *changedvram;
int vrammask;
uint32_t write_bank, read_bank;
int fullchange;
int video_res_x, video_res_y, video_bpp;
int frames, fps;
struct
{
int ena;
int x, y;
int xoff, yoff;
uint32_t addr;
} hwcursor, hwcursor_latch;
int hwcursor_on;
void (*render)(struct svga_t *svga);
void (*recalctimings_ex)(struct svga_t *svga);
void (*video_out)(uint16_t addr, uint8_t val, void *p);
uint8_t (*video_in) (uint16_t addr, void *p);
void (*hwcursor_draw)(struct svga_t *svga, int displine);
void *p;
} svga_t;
extern int svga_init(svga_t *svga, void *p, int memsize,
void (*recalctimings_ex)(struct svga_t *svga),
uint8_t (*video_in) (uint16_t addr, void *p),
void (*video_out)(uint16_t addr, uint8_t val, void *p),
void (*hwcursor_draw)(struct svga_t *svga, int displine));
extern void svga_recalctimings(svga_t *svga);
extern SVGA_HWCURSOR svga_hwcursor, svga_hwcursor_latch;
//extern int svga_hwcursor_x, svga_hwcursor_y;
//extern int svga_hwcursor_xoff, svga_hwcursor_yoff;
//extern uint32_t /*svga_hwcursor_addr, */svga_hwcursor_addr_cur;
//extern int svga_hwcursor_ena;
extern int svga_hwcursor_on;
extern void (*svga_hwcursor_draw)(int displine);
uint8_t svga_read(uint32_t addr, void *priv);
uint16_t svga_readw(uint32_t addr, void *priv);
uint32_t svga_readl(uint32_t addr, void *priv);
void svga_write(uint32_t addr, uint8_t val, void *priv);
void svga_writew(uint32_t addr, uint16_t val, void *priv);
void svga_writel(uint32_t addr, uint32_t val, void *priv);
uint8_t svga_read_linear(uint32_t addr, void *priv);
uint16_t svga_readw_linear(uint32_t addr, void *priv);
uint32_t svga_readl_linear(uint32_t addr, void *priv);
void svga_write_linear(uint32_t addr, uint8_t val, void *priv);
void svga_writew_linear(uint32_t addr, uint16_t val, void *priv);
void svga_writel_linear(uint32_t addr, uint32_t val, void *priv);
uint8_t svga_read(uint32_t addr, void *p);
uint16_t svga_readw(uint32_t addr, void *p);
uint32_t svga_readl(uint32_t addr, void *p);
void svga_write(uint32_t addr, uint8_t val, void *p);
void svga_writew(uint32_t addr, uint16_t val, void *p);
void svga_writel(uint32_t addr, uint32_t val, void *p);
uint8_t svga_read_linear(uint32_t addr, void *p);
uint16_t svga_readw_linear(uint32_t addr, void *p);
uint32_t svga_readl_linear(uint32_t addr, void *p);
void svga_write_linear(uint32_t addr, uint8_t val, void *p);
void svga_writew_linear(uint32_t addr, uint16_t val, void *p);
void svga_writel_linear(uint32_t addr, uint32_t val, void *p);
void svga_doblit(int y1, int y2);
extern uint32_t svga_vram_limit;
int svga_add_status_info(char *s, int max_len, void *p);
extern uint8_t svga_rotate[8][256];
void svga_out(uint16_t addr, uint8_t val, void *priv);
uint8_t svga_in(uint16_t addr, void *priv);
void svga_out(uint16_t addr, uint8_t val, void *p);
uint8_t svga_in(uint16_t addr, void *p);

View file

@ -3,36 +3,39 @@
#include "vid_svga.h"
#include "vid_svga_render.h"
void svga_render_blank()
void svga_render_blank(svga_t *svga)
{
int x, xx;
if (firstline_draw == 2000) firstline_draw = displine;
lastline_draw = displine;
for (x=0;x<svga_hdisp;x++)
if (svga->firstline_draw == 2000)
svga->firstline_draw = svga->displine;
svga->lastline_draw = svga->displine;
for (x = 0; x < svga->hdisp; x++)
{
switch (seqregs[1]&9)
switch (svga->seqregs[1] & 9)
{
case 0:
for (xx=0;xx<9;xx++) ((uint32_t *)buffer32->line[displine])[(x*9)+xx+32]=0;
for (xx = 0; xx < 9; xx++) ((uint32_t *)buffer32->line[svga->displine])[(x * 9) + xx + 32] = 0;
break;
case 1:
for (xx=0;xx<8;xx++) ((uint32_t *)buffer32->line[displine])[(x*8)+xx+32]=0;
for (xx = 0; xx < 8; xx++) ((uint32_t *)buffer32->line[svga->displine])[(x * 8) + xx + 32] = 0;
break;
case 8:
for (xx=0;xx<18;xx++) ((uint32_t *)buffer32->line[displine])[(x*18)+xx+32]=0;
for (xx = 0; xx < 18; xx++) ((uint32_t *)buffer32->line[svga->displine])[(x * 18) + xx + 32] = 0;
break;
case 9:
for (xx=0;xx<16;xx++) ((uint32_t *)buffer32->line[displine])[(x*16)+xx+32]=0;
for (xx = 0; xx < 16; xx++) ((uint32_t *)buffer32->line[svga->displine])[(x * 16) + xx + 32] = 0;
break;
}
}
}
void svga_render_text_40()
void svga_render_text_40(svga_t *svga)
{
if (firstline_draw == 2000) firstline_draw = displine;
lastline_draw = displine;
if (svga->firstline_draw == 2000)
svga->firstline_draw = svga->displine;
svga->lastline_draw = svga->displine;
if (fullchange)
{
@ -41,56 +44,59 @@ void svga_render_text_40()
uint8_t chr, attr, dat;
uint32_t charaddr;
int fg, bg;
int xinc = (seqregs[1] & 1) ? 16 : 18;
int xinc = (svga->seqregs[1] & 1) ? 16 : 18;
for (x=0;x<svga_hdisp;x+=xinc)
for (x = 0; x < svga->hdisp; x += xinc)
{
drawcursor=((ma==ca) && con && cursoron);
chr=vram[(ma<<1)];
attr=vram[(ma<<1)+4];
if (attr&8) charaddr=charsetb+(chr*128);
else charaddr=charseta+(chr*128);
drawcursor = ((svga->ma == svga->ca) && svga->con && svga->cursoron);
chr = svga->vram[(svga->ma << 1) & svga->vrammask];
attr = svga->vram[((svga->ma << 1) + 4) & svga->vrammask];
if (attr & 8) charaddr = svga->charsetb + (chr * 128);
else charaddr = svga->charseta + (chr * 128);
if (drawcursor)
{
bg=pallook[egapal[attr&15]];
fg=pallook[egapal[attr>>4]];
bg = svga->pallook[svga->egapal[attr & 15]];
fg = svga->pallook[svga->egapal[attr >> 4]];
}
else
{
fg=pallook[egapal[attr&15]];
bg=pallook[egapal[attr>>4]];
if (attr&0x80 && attrregs[0x10]&8)
fg = svga->pallook[svga->egapal[attr & 15]];
bg = svga->pallook[svga->egapal[attr >> 4]];
if (attr & 0x80 && svga->attrregs[0x10] & 8)
{
bg=pallook[egapal[(attr>>4)&7]];
if (cgablink&16) fg=bg;
bg = svga->pallook[svga->egapal[(attr >> 4) & 7]];
if (svga->blink & 16)
fg = bg;
}
}
dat=vram[charaddr+(sc<<2)];
if (seqregs[1]&1)
dat = svga->vram[charaddr + (svga->sc << 2)];
if (svga->seqregs[1] & 1)
{
for (xx=0;xx<8;xx++)
((uint32_t *)buffer32->line[displine])[(x+32+(xx<<1))&2047]=((uint32_t *)buffer32->line[displine])[(x+33+(xx<<1))&2047]=(dat&(0x80>>xx))?fg:bg;
for (xx = 0; xx < 8; xx++)
((uint32_t *)buffer32->line[svga->displine])[(x + 32 + (xx << 1)) & 2047] = ((uint32_t *)buffer32->line[svga->displine])[(x + 33 + (xx << 1)) & 2047] = (dat & (0x80 >> xx)) ? fg : bg;
}
else
{
for (xx=0;xx<8;xx++)
((uint32_t *)buffer32->line[displine])[(x+32+(xx<<1))&2047]=((uint32_t *)buffer32->line[displine])[(x+33+(xx<<1))&2047]=(dat&(0x80>>xx))?fg:bg;
if ((chr&~0x1F)!=0xC0 || !(attrregs[0x10]&4))
((uint32_t *)buffer32->line[displine])[(x+32+16)&2047]=((uint32_t *)buffer32->line[displine])[(x+32+17)&2047]=bg;
for (xx = 0; xx < 8; xx++)
((uint32_t *)buffer32->line[svga->displine])[(x + 32 + (xx << 1)) & 2047] = ((uint32_t *)buffer32->line[svga->displine])[(x + 33 + (xx << 1)) & 2047] = (dat & (0x80 >> xx)) ? fg : bg;
if ((chr & ~0x1F) != 0xC0 || !(svga->attrregs[0x10] & 4))
((uint32_t *)buffer32->line[svga->displine])[(x + 32 + 16) & 2047] = ((uint32_t *)buffer32->line[svga->displine])[(x + 32 + 17) & 2047] = bg;
else
((uint32_t *)buffer32->line[displine])[(x+32+16)&2047]=((uint32_t *)buffer32->line[displine])[(x+32+17)&2047]=(dat&1)?fg:bg;
((uint32_t *)buffer32->line[svga->displine])[(x + 32 + 16) & 2047] = ((uint32_t *)buffer32->line[svga->displine])[(x + 32 + 17) & 2047] = (dat & 1) ? fg : bg;
}
ma+=4; ma&=vrammask;
svga->ma += 4;
svga->ma &= svga->vrammask;
}
}
}
void svga_render_text_80()
void svga_render_text_80(svga_t *svga)
{
if (firstline_draw == 2000) firstline_draw = displine;
lastline_draw = displine;
if (svga->firstline_draw == 2000)
svga->firstline_draw = svga->displine;
svga->lastline_draw = svga->displine;
if (fullchange)
{
@ -99,388 +105,415 @@ void svga_render_text_80()
uint8_t chr, attr, dat;
uint32_t charaddr;
int fg, bg;
int xinc = (seqregs[1] & 1) ? 8 : 9;
int xinc = (svga->seqregs[1] & 1) ? 8 : 9;
for (x=0;x<svga_hdisp;x+=xinc)
for (x = 0; x < svga->hdisp; x += xinc)
{
drawcursor=((ma==ca) && con && cursoron);
chr=vram[(ma<<1)];
attr=vram[(ma<<1)+4];
if (attr&8) charaddr=charsetb+(chr*128);
else charaddr=charseta+(chr*128);
drawcursor = ((svga->ma == svga->ca) && svga->con && svga->cursoron);
chr = svga->vram[(svga->ma << 1) & svga->vrammask];
attr = svga->vram[((svga->ma << 1) + 4) & svga->vrammask];
if (attr & 8) charaddr = svga->charsetb + (chr * 128);
else charaddr = svga->charseta + (chr * 128);
if (drawcursor)
{
bg=pallook[egapal[attr&15]];
fg=pallook[egapal[attr>>4]];
bg = svga->pallook[svga->egapal[attr & 15]];
fg = svga->pallook[svga->egapal[attr >> 4]];
}
else
{
fg=pallook[egapal[attr&15]];
bg=pallook[egapal[attr>>4]];
if (attr&0x80 && attrregs[0x10]&8)
fg = svga->pallook[svga->egapal[attr & 15]];
bg = svga->pallook[svga->egapal[attr >> 4]];
if (attr & 0x80 && svga->attrregs[0x10] & 8)
{
bg=pallook[egapal[(attr>>4)&7]];
if (cgablink&16) fg=bg;
bg = svga->pallook[svga->egapal[(attr >> 4) & 7]];
if (svga->blink & 16)
fg = bg;
}
}
dat=vram[charaddr+(sc<<2)];
if (seqregs[1]&1)
dat = svga->vram[charaddr + (svga->sc << 2)];
if (svga->seqregs[1] & 1)
{
for (xx=0;xx<8;xx++)
((uint32_t *)buffer32->line[displine])[(x+32+xx)&2047]=(dat&(0x80>>xx))?fg:bg;
for (xx = 0; xx < 8; xx++)
((uint32_t *)buffer32->line[svga->displine])[(x + 32 + xx) & 2047] = (dat & (0x80 >> xx)) ? fg : bg;
}
else
{
for (xx=0;xx<8;xx++)
((uint32_t *)buffer32->line[displine])[(x+32+xx)&2047]=(dat&(0x80>>xx))?fg:bg;
if ((chr&~0x1F)!=0xC0 || !(attrregs[0x10]&4))
((uint32_t *)buffer32->line[displine])[(x+32+8)&2047]=bg;
for (xx = 0; xx < 8; xx++)
((uint32_t *)buffer32->line[svga->displine])[(x + 32 + xx) & 2047] = (dat & (0x80 >> xx)) ? fg : bg;
if ((chr & ~0x1F) != 0xC0 || !(svga->attrregs[0x10] & 4))
((uint32_t *)buffer32->line[svga->displine])[(x + 32 + 8) & 2047] = bg;
else
((uint32_t *)buffer32->line[displine])[(x+32+8)&2047]=(dat&1)?fg:bg;
((uint32_t *)buffer32->line[svga->displine])[(x + 32 + 8) & 2047] = (dat & 1) ? fg : bg;
}
ma+=4; ma&=vrammask;
svga->ma += 4;
svga->ma &= svga->vrammask;
}
}
}
void svga_render_4bpp_lowres()
void svga_render_4bpp_lowres(svga_t *svga)
{
int x, offset;
uint8_t edat[4], dat;
if (firstline_draw == 2000) firstline_draw = displine;
lastline_draw = displine;
if (svga->firstline_draw == 2000)
svga->firstline_draw = svga->displine;
svga->lastline_draw = svga->displine;
offset=((8-scrollcache)<<1)+16;
for (x = 0; x <= svga_hdisp; x += 16)
offset = ((8 - svga->scrollcache) << 1) + 16;
for (x = 0; x <= svga->hdisp; x += 16)
{
edat[0]=vram[ma];
edat[1]=vram[ma|0x1];
edat[2]=vram[ma|0x2];
edat[3]=vram[ma|0x3];
ma+=4; ma&=vrammask;
edat[0] = svga->vram[svga->ma];
edat[1] = svga->vram[svga->ma | 0x1];
edat[2] = svga->vram[svga->ma | 0x2];
edat[3] = svga->vram[svga->ma | 0x3];
svga->ma += 4;
svga->ma &= svga->vrammask;
dat=edatlookup[edat[0]&3][edat[1]&3]|(edatlookup[edat[2]&3][edat[3]&3]<<2);
((uint32_t *)buffer32->line[displine])[x+14+offset]=((uint32_t *)buffer32->line[displine])[x+15+offset]=pallook[egapal[dat&0xF]];
((uint32_t *)buffer32->line[displine])[x+12+offset]=((uint32_t *)buffer32->line[displine])[x+13+offset]=pallook[egapal[dat>>4]];
dat=edatlookup[(edat[0]>>2)&3][(edat[1]>>2)&3]|(edatlookup[(edat[2]>>2)&3][(edat[3]>>2)&3]<<2);
((uint32_t *)buffer32->line[displine])[x+10+offset]=((uint32_t *)buffer32->line[displine])[x+11+offset]=pallook[egapal[dat&0xF]];
((uint32_t *)buffer32->line[displine])[x+8+offset]= ((uint32_t *)buffer32->line[displine])[x+9+offset]=pallook[egapal[dat>>4]];
dat=edatlookup[(edat[0]>>4)&3][(edat[1]>>4)&3]|(edatlookup[(edat[2]>>4)&3][(edat[3]>>4)&3]<<2);
((uint32_t *)buffer32->line[displine])[x+6+offset]= ((uint32_t *)buffer32->line[displine])[x+7+offset]=pallook[egapal[dat&0xF]];
((uint32_t *)buffer32->line[displine])[x+4+offset]= ((uint32_t *)buffer32->line[displine])[x+5+offset]=pallook[egapal[dat>>4]];
dat=edatlookup[edat[0]>>6][edat[1]>>6]|(edatlookup[edat[2]>>6][edat[3]>>6]<<2);
((uint32_t *)buffer32->line[displine])[x+2+offset]= ((uint32_t *)buffer32->line[displine])[x+3+offset]=pallook[egapal[dat&0xF]];
((uint32_t *)buffer32->line[displine])[x+offset]= ((uint32_t *)buffer32->line[displine])[x+1+offset]=pallook[egapal[dat>>4]];
dat = edatlookup[edat[0] & 3][edat[1] & 3] | (edatlookup[edat[2] & 3][edat[3] & 3] << 2);
((uint32_t *)buffer32->line[svga->displine])[x + 14 + offset] = ((uint32_t *)buffer32->line[svga->displine])[x + 15 + offset] = svga->pallook[svga->egapal[dat & 0xf]];
((uint32_t *)buffer32->line[svga->displine])[x + 12 + offset] = ((uint32_t *)buffer32->line[svga->displine])[x + 13 + offset] = svga->pallook[svga->egapal[dat >> 4]];
dat = edatlookup[(edat[0] >> 2) & 3][(edat[1] >> 2) & 3] | (edatlookup[(edat[2] >> 2) & 3][(edat[3] >> 2) & 3] << 2);
((uint32_t *)buffer32->line[svga->displine])[x + 10 + offset] = ((uint32_t *)buffer32->line[svga->displine])[x + 11 + offset] = svga->pallook[svga->egapal[dat & 0xf]];
((uint32_t *)buffer32->line[svga->displine])[x + 8 + offset] = ((uint32_t *)buffer32->line[svga->displine])[x + 9 + offset] = svga->pallook[svga->egapal[dat >> 4]];
dat = edatlookup[(edat[0] >> 4) & 3][(edat[1] >> 4) & 3] | (edatlookup[(edat[2] >> 4) & 3][(edat[3] >> 4) & 3] << 2);
((uint32_t *)buffer32->line[svga->displine])[x + 6 + offset] = ((uint32_t *)buffer32->line[svga->displine])[x + 7 + offset] = svga->pallook[svga->egapal[dat & 0xf]];
((uint32_t *)buffer32->line[svga->displine])[x + 4 + offset] = ((uint32_t *)buffer32->line[svga->displine])[x + 5 + offset] = svga->pallook[svga->egapal[dat >> 4]];
dat = edatlookup[edat[0] >> 6][edat[1] >> 6] | (edatlookup[edat[2] >> 6][edat[3] >> 6] << 2);
((uint32_t *)buffer32->line[svga->displine])[x + 2 + offset] = ((uint32_t *)buffer32->line[svga->displine])[x + 3 + offset] = svga->pallook[svga->egapal[dat & 0xf]];
((uint32_t *)buffer32->line[svga->displine])[x + offset] = ((uint32_t *)buffer32->line[svga->displine])[x + 1 + offset] = svga->pallook[svga->egapal[dat >> 4]];
}
}
void svga_render_4bpp_highres()
void svga_render_4bpp_highres(svga_t *svga)
{
int x, offset;
uint8_t edat[4], dat;
if (firstline_draw == 2000) firstline_draw = displine;
lastline_draw = displine;
if (svga->firstline_draw == 2000)
svga->firstline_draw = svga->displine;
svga->lastline_draw = svga->displine;
offset=(8-scrollcache)+24;
for (x = 0; x <= svga_hdisp; x += 8)
offset = (8 - svga->scrollcache) + 24;
for (x = 0; x <= svga->hdisp; x += 8)
{
edat[0]=vram[ma];
edat[1]=vram[ma|0x1];
edat[2]=vram[ma|0x2];
edat[3]=vram[ma|0x3];
ma+=4; ma&=vrammask;
edat[0] = svga->vram[svga->ma];
edat[1] = svga->vram[svga->ma | 0x1];
edat[2] = svga->vram[svga->ma | 0x2];
edat[3] = svga->vram[svga->ma | 0x3];
svga->ma += 4;
svga->ma &= svga->vrammask;
dat=edatlookup[edat[0]&3][edat[1]&3]|(edatlookup[edat[2]&3][edat[3]&3]<<2);
((uint32_t *)buffer32->line[displine])[x+7+offset]=pallook[egapal[dat&0xF]];
((uint32_t *)buffer32->line[displine])[x+6+offset]=pallook[egapal[dat>>4]];
dat=edatlookup[(edat[0]>>2)&3][(edat[1]>>2)&3]|(edatlookup[(edat[2]>>2)&3][(edat[3]>>2)&3]<<2);
((uint32_t *)buffer32->line[displine])[x+5+offset]=pallook[egapal[dat&0xF]];
((uint32_t *)buffer32->line[displine])[x+4+offset]=pallook[egapal[dat>>4]];
dat=edatlookup[(edat[0]>>4)&3][(edat[1]>>4)&3]|(edatlookup[(edat[2]>>4)&3][(edat[3]>>4)&3]<<2);
((uint32_t *)buffer32->line[displine])[x+3+offset]=pallook[egapal[dat&0xF]];
((uint32_t *)buffer32->line[displine])[x+2+offset]=pallook[egapal[dat>>4]];
dat=edatlookup[edat[0]>>6][edat[1]>>6]|(edatlookup[edat[2]>>6][edat[3]>>6]<<2);
((uint32_t *)buffer32->line[displine])[x+1+offset]=pallook[egapal[dat&0xF]];
((uint32_t *)buffer32->line[displine])[x+offset]= pallook[egapal[dat>>4]];
dat = edatlookup[edat[0] & 3][edat[1] & 3] | (edatlookup[edat[2] & 3][edat[3] & 3] << 2);
((uint32_t *)buffer32->line[svga->displine])[x + 7 + offset] = svga->pallook[svga->egapal[dat & 0xf]];
((uint32_t *)buffer32->line[svga->displine])[x + 6 + offset] = svga->pallook[svga->egapal[dat >> 4]];
dat = edatlookup[(edat[0] >> 2) & 3][(edat[1] >> 2) & 3] | (edatlookup[(edat[2] >> 2) & 3][(edat[3] >> 2) & 3] << 2);
((uint32_t *)buffer32->line[svga->displine])[x + 5 + offset] = svga->pallook[svga->egapal[dat & 0xf]];
((uint32_t *)buffer32->line[svga->displine])[x + 4 + offset] = svga->pallook[svga->egapal[dat >> 4]];
dat = edatlookup[(edat[0] >> 4) & 3][(edat[1] >> 4) & 3] | (edatlookup[(edat[2] >> 4) & 3][(edat[3] >> 4) & 3] << 2);
((uint32_t *)buffer32->line[svga->displine])[x + 3 + offset] = svga->pallook[svga->egapal[dat & 0xf]];
((uint32_t *)buffer32->line[svga->displine])[x + 2 + offset] = svga->pallook[svga->egapal[dat >> 4]];
dat = edatlookup[edat[0] >> 6][edat[1] >> 6] | (edatlookup[edat[2] >> 6][edat[3] >> 6] << 2);
((uint32_t *)buffer32->line[svga->displine])[x + 1 + offset] = svga->pallook[svga->egapal[dat & 0xf]];
((uint32_t *)buffer32->line[svga->displine])[x + offset] = svga->pallook[svga->egapal[dat >> 4]];
}
}
void svga_render_2bpp_lowres()
void svga_render_2bpp_lowres(svga_t *svga)
{
int x, offset;
uint8_t edat[4], dat;
uint8_t edat[2], dat;
if (firstline_draw == 2000) firstline_draw = displine;
lastline_draw = displine;
offset=((8-scrollcache)<<1)+16;
if (svga->firstline_draw == 2000)
svga->firstline_draw = svga->displine;
svga->lastline_draw = svga->displine;
offset = ((8 - svga->scrollcache) << 1) + 16;
/*Low res (320) only, though high res (640) should be possible*/
for (x = 0; x <= svga_hdisp; x += 16)
for (x = 0; x <= svga->hdisp; x += 16)
{
if (sc&1 && !(crtc[0x17]&1))
if (svga->sc & 1 && !(svga->crtc[0x17] & 1))
{
edat[0]=vram[(ma<<1)+0x8000];
edat[1]=vram[(ma<<1)+0x8004];
edat[0] = svga->vram[(svga->ma << 1) + 0x8000];
edat[1] = svga->vram[(svga->ma << 1) + 0x8004];
}
else
{
edat[0]=vram[(ma<<1)];
edat[1]=vram[(ma<<1)+4];
edat[0] = svga->vram[(svga->ma << 1)];
edat[1] = svga->vram[(svga->ma << 1) + 4];
}
ma+=4; ma&=vrammask;
svga->ma += 4; svga->ma &= svga->vrammask;
((uint32_t *)buffer32->line[displine])[x+14+offset]=((uint32_t *)buffer32->line[displine])[x+15+offset]=pallook[egapal[edat[1]&3]];
((uint32_t *)buffer32->line[displine])[x+12+offset]=((uint32_t *)buffer32->line[displine])[x+13+offset]=pallook[egapal[(edat[1]>>2)&3]];
dat=edatlookup[(edat[0]>>2)&3][(edat[1]>>2)&3]|(edatlookup[(edat[2]>>2)&3][(edat[3]>>2)&3]<<2);
((uint32_t *)buffer32->line[displine])[x+10+offset]=((uint32_t *)buffer32->line[displine])[x+11+offset]=pallook[egapal[(edat[1]>>4)&3]];
((uint32_t *)buffer32->line[displine])[x+8+offset]= ((uint32_t *)buffer32->line[displine])[x+9+offset]=pallook[egapal[(edat[1]>>6)&3]];
dat=edatlookup[(edat[0]>>4)&3][(edat[1]>>4)&3]|(edatlookup[(edat[2]>>4)&3][(edat[3]>>4)&3]<<2);
((uint32_t *)buffer32->line[displine])[x+6+offset]= ((uint32_t *)buffer32->line[displine])[x+7+offset]=pallook[egapal[(edat[0]>>0)&3]];
((uint32_t *)buffer32->line[displine])[x+4+offset]= ((uint32_t *)buffer32->line[displine])[x+5+offset]=pallook[egapal[(edat[0]>>2)&3]];
dat=edatlookup[edat[0]>>6][edat[1]>>6]|(edatlookup[edat[2]>>6][edat[3]>>6]<<2);
((uint32_t *)buffer32->line[displine])[x+2+offset]= ((uint32_t *)buffer32->line[displine])[x+3+offset]=pallook[egapal[(edat[0]>>4)&3]];
((uint32_t *)buffer32->line[displine])[x+offset]= ((uint32_t *)buffer32->line[displine])[x+1+offset]=pallook[egapal[(edat[0]>>6)&3]];
((uint32_t *)buffer32->line[svga->displine])[x + 14 + offset] = ((uint32_t *)buffer32->line[svga->displine])[x + 15 + offset] = svga->pallook[svga->egapal[edat[1] & 3]];
((uint32_t *)buffer32->line[svga->displine])[x + 12 + offset] = ((uint32_t *)buffer32->line[svga->displine])[x + 13 + offset] = svga->pallook[svga->egapal[(edat[1] >> 2) & 3]];
((uint32_t *)buffer32->line[svga->displine])[x + 10 + offset] = ((uint32_t *)buffer32->line[svga->displine])[x + 11 + offset] = svga->pallook[svga->egapal[(edat[1] >> 4) & 3]];
((uint32_t *)buffer32->line[svga->displine])[x + 8 + offset] = ((uint32_t *)buffer32->line[svga->displine])[x + 9 + offset] = svga->pallook[svga->egapal[(edat[1] >> 6) & 3]];
((uint32_t *)buffer32->line[svga->displine])[x + 6 + offset] = ((uint32_t *)buffer32->line[svga->displine])[x + 7 + offset] = svga->pallook[svga->egapal[edat[0] & 3]];
((uint32_t *)buffer32->line[svga->displine])[x + 4 + offset] = ((uint32_t *)buffer32->line[svga->displine])[x + 5 + offset] = svga->pallook[svga->egapal[(edat[0] >> 2) & 3]];
((uint32_t *)buffer32->line[svga->displine])[x + 2 + offset] = ((uint32_t *)buffer32->line[svga->displine])[x + 3 + offset] = svga->pallook[svga->egapal[(edat[0] >> 4) & 3]];
((uint32_t *)buffer32->line[svga->displine])[x + offset] = ((uint32_t *)buffer32->line[svga->displine])[x + 1 + offset] = svga->pallook[svga->egapal[(edat[0] >> 6) & 3]];
}
}
void svga_render_8bpp_lowres()
void svga_render_8bpp_lowres(svga_t *svga)
{
int x, offset;
uint8_t edat[4];
if (changedvram[ma>>10] || changedvram[(ma>>10)+1] || changedvram[(ma>>10)+2] || fullchange)
if (svga->changedvram[svga->ma >> 10] || svga->changedvram[(svga->ma >> 10) + 1] || svga->changedvram[(svga->ma >> 10) + 2] || fullchange)
{
if (firstline_draw == 2000) firstline_draw = displine;
lastline_draw = displine;
if (svga->firstline_draw == 2000)
svga->firstline_draw = svga->displine;
svga->lastline_draw = svga->displine;
offset=(8-(scrollcache&6))+24;
offset = (8 - (svga->scrollcache & 6)) + 24;
for (x = 0; x <= svga_hdisp; x += 8)
for (x = 0; x <= svga->hdisp; x += 8)
{
edat[0]=vram[ma];
edat[1]=vram[ma|0x1];
edat[2]=vram[ma|0x2];
edat[3]=vram[ma|0x3];
ma+=4; ma&=vrammask;
((uint32_t *)buffer32->line[displine])[x+6+offset]= ((uint32_t *)buffer32->line[displine])[x+7+offset]=pallook[edat[3]];
((uint32_t *)buffer32->line[displine])[x+4+offset]= ((uint32_t *)buffer32->line[displine])[x+5+offset]=pallook[edat[2]];
((uint32_t *)buffer32->line[displine])[x+2+offset]= ((uint32_t *)buffer32->line[displine])[x+3+offset]=pallook[edat[1]];
((uint32_t *)buffer32->line[displine])[x+offset]= ((uint32_t *)buffer32->line[displine])[x+1+offset]=pallook[edat[0]];
edat[0] = svga->vram[svga->ma];
edat[1] = svga->vram[svga->ma | 0x1];
edat[2] = svga->vram[svga->ma | 0x2];
edat[3] = svga->vram[svga->ma | 0x3];
svga->ma += 4;
svga->ma &= svga->vrammask;
((uint32_t *)buffer32->line[svga->displine])[x + 6 + offset] = ((uint32_t *)buffer32->line[svga->displine])[x + 7 + offset] = svga->pallook[edat[3]];
((uint32_t *)buffer32->line[svga->displine])[x + 4 + offset] = ((uint32_t *)buffer32->line[svga->displine])[x + 5 + offset] = svga->pallook[edat[2]];
((uint32_t *)buffer32->line[svga->displine])[x + 2 + offset] = ((uint32_t *)buffer32->line[svga->displine])[x + 3 + offset] = svga->pallook[edat[1]];
((uint32_t *)buffer32->line[svga->displine])[x + offset] = ((uint32_t *)buffer32->line[svga->displine])[x + 1 + offset] = svga->pallook[edat[0]];
}
}
}
void svga_render_8bpp_highres()
void svga_render_8bpp_highres(svga_t *svga)
{
int x, offset;
uint8_t edat[4];
if (changedvram[ma>>10] || changedvram[(ma>>10)+1] || changedvram[(ma>>10)+2] || fullchange)
if (svga->changedvram[svga->ma >> 10] || svga->changedvram[(svga->ma >> 10) + 1] || svga->changedvram[(svga->ma >> 10) + 2] || fullchange)
{
if (firstline_draw == 2000) firstline_draw = displine;
lastline_draw = displine;
if (svga->firstline_draw == 2000)
svga->firstline_draw = svga->displine;
svga->lastline_draw = svga->displine;
offset = (8 - ((scrollcache & 6) >> 1)) + 24;
offset = (8 - ((svga->scrollcache & 6) >> 1)) + 24;
for (x = 0; x <= svga_hdisp; x += 8)
for (x = 0; x <= svga->hdisp; x += 8)
{
edat[0]=vram[ma];
edat[1]=vram[ma|0x1];
edat[2]=vram[ma|0x2];
edat[3]=vram[ma|0x3];
ma+=4; ma&=vrammask;
((uint32_t *)buffer32->line[displine])[x+3+offset] = pallook[edat[3]];
((uint32_t *)buffer32->line[displine])[x+2+offset] = pallook[edat[2]];
((uint32_t *)buffer32->line[displine])[x+1+offset] = pallook[edat[1]];
((uint32_t *)buffer32->line[displine])[x+offset] = pallook[edat[0]];
edat[0]=vram[ma];
edat[1]=vram[ma|0x1];
edat[2]=vram[ma|0x2];
edat[3]=vram[ma|0x3];
ma+=4; ma&=vrammask;
((uint32_t *)buffer32->line[displine])[x+7+offset] = pallook[edat[3]];
((uint32_t *)buffer32->line[displine])[x+6+offset] = pallook[edat[2]];
((uint32_t *)buffer32->line[displine])[x+5+offset] = pallook[edat[1]];
((uint32_t *)buffer32->line[displine])[x+4+offset] = pallook[edat[0]];
edat[0] = svga->vram[svga->ma];
edat[1] = svga->vram[svga->ma | 0x1];
edat[2] = svga->vram[svga->ma | 0x2];
edat[3] = svga->vram[svga->ma | 0x3];
svga->ma += 4;
svga->ma &= svga->vrammask;
((uint32_t *)buffer32->line[svga->displine])[x + 3 + offset] = svga->pallook[edat[3]];
((uint32_t *)buffer32->line[svga->displine])[x + 2 + offset] = svga->pallook[edat[2]];
((uint32_t *)buffer32->line[svga->displine])[x + 1 + offset] = svga->pallook[edat[1]];
((uint32_t *)buffer32->line[svga->displine])[x + offset] = svga->pallook[edat[0]];
edat[0] = svga->vram[svga->ma];
edat[1] = svga->vram[svga->ma | 0x1];
edat[2] = svga->vram[svga->ma | 0x2];
edat[3] = svga->vram[svga->ma | 0x3];
svga->ma += 4;
svga->ma &= svga->vrammask;
((uint32_t *)buffer32->line[svga->displine])[x + 7 + offset] = svga->pallook[edat[3]];
((uint32_t *)buffer32->line[svga->displine])[x + 6 + offset] = svga->pallook[edat[2]];
((uint32_t *)buffer32->line[svga->displine])[x + 5 + offset] = svga->pallook[edat[1]];
((uint32_t *)buffer32->line[svga->displine])[x + 4 + offset] = svga->pallook[edat[0]];
}
}
}
void svga_render_15bpp_lowres()
void svga_render_15bpp_lowres(svga_t *svga)
{
int x, offset;
uint16_t fg, bg;
if (changedvram[ma>>10] || changedvram[(ma>>10)+1] || changedvram[(ma>>10)+2] || fullchange)
if (svga->changedvram[svga->ma >> 10] || svga->changedvram[(svga->ma >> 10) + 1] || svga->changedvram[(svga->ma >> 10) + 2] || fullchange)
{
if (firstline_draw == 2000) firstline_draw = displine;
lastline_draw = displine;
if (svga->firstline_draw == 2000)
svga->firstline_draw = svga->displine;
svga->lastline_draw = svga->displine;
offset=(8-(scrollcache&6))+24;
offset = (8 - (svga->scrollcache & 6)) + 24;
for (x = 0; x <= svga_hdisp; x += 4)
for (x = 0; x <= svga->hdisp; x += 4)
{
fg=vram[ma]|(vram[ma|0x1]<<8);
bg=vram[ma|0x2]|(vram[ma|0x3]<<8);
ma+=4; ma&=vrammask;
((uint32_t *)buffer32->line[displine])[x+2+offset]=((uint32_t *)buffer32->line[displine])[x+3+offset]=((bg&31)<<3)|(((bg>>5)&31)<<11)|(((bg>>10)&31)<<19);
((uint32_t *)buffer32->line[displine])[x+0+offset]=((uint32_t *)buffer32->line[displine])[x+1+offset]=((fg&31)<<3)|(((fg>>5)&31)<<11)|(((fg>>10)&31)<<19);
fg = svga->vram[svga->ma] | (svga->vram[svga->ma | 0x1] << 8);
bg = svga->vram[svga->ma | 0x2] | (svga->vram[svga->ma | 0x3] << 8);
svga->ma += 4;
svga->ma &= svga->vrammask;
((uint32_t *)buffer32->line[svga->displine])[x + 2 + offset] = ((uint32_t *)buffer32->line[svga->displine])[x + 3 + offset] = ((bg & 31) << 3) | (((bg >> 5) & 31) << 11) | (((bg >> 10) & 31) << 19);
((uint32_t *)buffer32->line[svga->displine])[x + offset] = ((uint32_t *)buffer32->line[svga->displine])[x + 1 + offset] = ((fg & 31) << 3) | (((fg >> 5) & 31) << 11) | (((fg >> 10) & 31) << 19);
}
}
}
void svga_render_15bpp_highres()
void svga_render_15bpp_highres(svga_t *svga)
{
int x, offset;
uint16_t fg, bg;
if (changedvram[ma>>10] || changedvram[(ma>>10)+1] || changedvram[(ma>>10)+2] || fullchange)
if (svga->changedvram[svga->ma >> 10] || svga->changedvram[(svga->ma >> 10) + 1] || svga->changedvram[(svga->ma >> 10) + 2] || fullchange)
{
if (firstline_draw == 2000) firstline_draw = displine;
lastline_draw = displine;
if (svga->firstline_draw == 2000)
svga->firstline_draw = svga->displine;
svga->lastline_draw = svga->displine;
offset = (8 - ((scrollcache & 6) >> 1)) + 24;
offset = (8 - ((svga->scrollcache & 6) >> 1)) + 24;
for (x = 0; x <= svga->hdisp; x += 2)
{
fg = svga->vram[svga->ma] | (svga->vram[svga->ma | 0x1] << 8);
bg = svga->vram[svga->ma | 0x2] | (svga->vram[svga->ma | 0x3] << 8);
svga->ma += 4;
svga->ma &= svga->vrammask;
((uint32_t *)buffer32->line[svga->displine])[x + 1 + offset] = ((bg & 31) << 3) | (((bg >> 5) & 31) << 11) | (((bg >> 10) & 31) << 19);
((uint32_t *)buffer32->line[svga->displine])[x + offset] = ((fg & 31) << 3) | (((fg >> 5) & 31) << 11) | (((fg >> 10) & 31) << 19);
}
}
}
void svga_render_16bpp_lowres(svga_t *svga)
{
int x, offset;
uint16_t fg, bg;
if (svga->changedvram[svga->ma >> 10] || svga->changedvram[(svga->ma >> 10) + 1] || svga->changedvram[(svga->ma >> 10) + 2] || fullchange)
{
if (svga->firstline_draw == 2000)
svga->firstline_draw = svga->displine;
svga->lastline_draw = svga->displine;
offset = (8 - (svga->scrollcache & 6)) + 24;
for (x = 0; x <= svga->hdisp; x += 4)
{
fg = svga->vram[svga->ma] | (svga->vram[svga->ma | 0x1] << 8);
bg = svga->vram[svga->ma | 0x2] | (svga->vram[svga->ma | 0x3] << 8);
svga->ma += 4;
svga->ma &= svga->vrammask;
((uint32_t *)buffer32->line[svga->displine])[x + 2 + offset] = ((uint32_t *)buffer32->line[svga->displine])[x + 3 + offset] = ((bg & 31) << 3) | (((bg >> 5) & 63) << 10) | (((bg >> 11) & 31) << 19);
((uint32_t *)buffer32->line[svga->displine])[x + offset] = ((uint32_t *)buffer32->line[svga->displine])[x + 1 + offset] = ((fg & 31) << 3) | (((fg >> 5) & 63) << 10) | (((fg >> 11) & 31) << 19);
}
}
}
void svga_render_16bpp_highres(svga_t *svga)
{
int x, offset;
uint16_t fg, bg;
if (svga->changedvram[svga->ma >> 10] || svga->changedvram[(svga->ma >> 10) + 1] || svga->changedvram[(svga->ma >> 10) + 2] || fullchange)
{
if (svga->firstline_draw == 2000)
svga->firstline_draw = svga->displine;
svga->lastline_draw = svga->displine;
offset = (8 - ((svga->scrollcache & 6) >> 1)) + 24;
for (x = 0; x <= svga_hdisp; x += 2)
for (x = 0; x <= svga->hdisp; x += 2)
{
fg=vram[ma]|(vram[ma|0x1]<<8);
bg=vram[ma|0x2]|(vram[ma|0x3]<<8);
ma+=4; ma&=vrammask;
((uint32_t *)buffer32->line[displine])[x + 1 + offset] = ((bg&31)<<3)|(((bg>>5)&31)<<11)|(((bg>>10)&31)<<19);
((uint32_t *)buffer32->line[displine])[x + 0 + offset] = ((fg&31)<<3)|(((fg>>5)&31)<<11)|(((fg>>10)&31)<<19);
fg = svga->vram[svga->ma] | (svga->vram[svga->ma | 0x1] << 8);
bg = svga->vram[svga->ma | 0x2] | (svga->vram[svga->ma | 0x3] << 8);
svga->ma += 4;
svga->ma &= svga->vrammask;
((uint32_t *)buffer32->line[svga->displine])[x + 1 + offset] = ((bg & 31) << 3) | (((bg >> 5) & 63) << 10) | (((bg >> 11) & 31) << 19);
((uint32_t *)buffer32->line[svga->displine])[x + offset] = ((fg & 31) << 3) | (((fg >> 5) & 63) << 10) | (((fg >> 11) & 31) << 19);
}
}
}
void svga_render_16bpp_lowres()
{
int x, offset;
uint16_t fg, bg;
if (changedvram[ma>>10] || changedvram[(ma>>10)+1] || changedvram[(ma>>10)+2] || fullchange)
{
if (firstline_draw == 2000) firstline_draw = displine;
lastline_draw = displine;
offset=(8-(scrollcache&6))+24;
for (x = 0; x <= svga_hdisp; x += 4)
{
fg=vram[ma]|(vram[ma|0x1]<<8);
bg=vram[ma|0x2]|(vram[ma|0x3]<<8);
ma+=4; ma&=vrammask;
((uint32_t *)buffer32->line[displine])[x+2+offset]=((uint32_t *)buffer32->line[displine])[x+3+offset]=((bg&31)<<3)|(((bg>>5)&63)<<10)|(((bg>>11)&31)<<19);
((uint32_t *)buffer32->line[displine])[x+0+offset]=((uint32_t *)buffer32->line[displine])[x+1+offset]=((fg&31)<<3)|(((fg>>5)&63)<<10)|(((fg>>11)&31)<<19);
}
}
}
void svga_render_16bpp_highres()
{
int x, offset;
uint16_t fg, bg;
if (changedvram[ma>>10] || changedvram[(ma>>10)+1] || changedvram[(ma>>10)+2] || fullchange)
{
if (firstline_draw == 2000) firstline_draw = displine;
lastline_draw = displine;
offset = (8 - ((scrollcache & 6) >> 1)) + 24;
for (x = 0; x <= svga_hdisp; x += 2)
{
fg=vram[ma]|(vram[ma|0x1]<<8);
bg=vram[ma|0x2]|(vram[ma|0x3]<<8);
ma+=4; ma&=vrammask;
((uint32_t *)buffer32->line[displine])[x + 1 + offset] = ((bg&31)<<3)|(((bg>>5)&63)<<10)|(((bg>>11)&31)<<19);
((uint32_t *)buffer32->line[displine])[x + 0 + offset] = ((fg&31)<<3)|(((fg>>5)&63)<<10)|(((fg>>11)&31)<<19);
}
}
}
void svga_render_24bpp_lowres()
void svga_render_24bpp_lowres(svga_t *svga)
{
int x, offset;
uint32_t fg;
if (changedvram[ma>>10] || changedvram[(ma>>10)+1] || changedvram[(ma>>10)+2] || fullchange)
if (svga->changedvram[svga->ma >> 10] || svga->changedvram[(svga->ma >> 10) + 1] || svga->changedvram[(svga->ma >> 10) + 2] || fullchange)
{
if (firstline_draw == 2000) firstline_draw = displine;
lastline_draw = displine;
if (svga->firstline_draw == 2000)
svga->firstline_draw = svga->displine;
svga->lastline_draw = svga->displine;
offset=(8-(scrollcache&6))+24;
offset = (8 - (svga->scrollcache & 6)) + 24;
for (x = 0; x <= svga_hdisp; x++)
for (x = 0; x <= svga->hdisp; x++)
{
fg=vram[ma]|(vram[ma+1]<<8)|(vram[ma+2]<<16);
ma+=3; ma&=vrammask;
((uint32_t *)buffer32->line[displine])[(x<<1)+offset]=((uint32_t *)buffer32->line[displine])[(x<<1)+1+offset]=fg;
fg = svga->vram[svga->ma] | (svga->vram[svga->ma + 1] << 8) | (svga->vram[svga->ma + 2] << 16);
svga->ma += 3;
svga->ma &= svga->vrammask;
((uint32_t *)buffer32->line[svga->displine])[(x << 1) + offset] = ((uint32_t *)buffer32->line[svga->displine])[(x << 1) + 1 + offset] = fg;
}
}
}
void svga_render_24bpp_highres()
void svga_render_24bpp_highres(svga_t *svga)
{
int x, offset;
uint32_t fg;
if (changedvram[ma>>10] || changedvram[(ma>>10)+1] || changedvram[(ma>>10)+2] || fullchange)
if (svga->changedvram[svga->ma >> 10] || svga->changedvram[(svga->ma >> 10) + 1] || svga->changedvram[(svga->ma >> 10) + 2] || fullchange)
{
if (firstline_draw == 2000) firstline_draw = displine;
lastline_draw = displine;
if (svga->firstline_draw == 2000)
svga->firstline_draw = svga->displine;
svga->lastline_draw = svga->displine;
offset = (8 - ((scrollcache & 6) >> 1)) + 24;
offset = (8 - ((svga->scrollcache & 6) >> 1)) + 24;
for (x = 0; x <= svga_hdisp; x++)
for (x = 0; x <= svga->hdisp; x++)
{
fg=vram[ma]|(vram[ma+1]<<8)|(vram[ma+2]<<16);
ma+=3; ma&=vrammask;
((uint32_t *)buffer32->line[displine])[x + offset] = fg;
fg = svga->vram[svga->ma] | (svga->vram[svga->ma + 1] << 8) | (svga->vram[svga->ma + 2] << 16);
svga->ma += 3;
svga->ma &= svga->vrammask;
((uint32_t *)buffer32->line[svga->displine])[x + offset] = fg;
}
}
}
void svga_render_32bpp_lowres()
void svga_render_32bpp_lowres(svga_t *svga)
{
int x, offset;
uint32_t fg;
if (changedvram[ma>>10] || changedvram[(ma>>10)+1] || changedvram[(ma>>10)+2] || fullchange)
if (svga->changedvram[svga->ma >> 10] || svga->changedvram[(svga->ma >> 10) + 1] || svga->changedvram[(svga->ma >> 10) + 2] || fullchange)
{
if (firstline_draw == 2000) firstline_draw = displine;
lastline_draw = displine;
if (svga->firstline_draw == 2000)
svga->firstline_draw = svga->displine;
svga->lastline_draw = svga->displine;
offset=(8-(scrollcache&6))+24;
offset = (8 - (svga->scrollcache & 6)) + 24;
for (x = 0; x <= svga_hdisp; x++)
for (x = 0; x <= svga->hdisp; x++)
{
fg = vram[ma] | (vram[ma + 1] << 8) | (vram[ma + 2] << 16);
ma += 4; ma &= vrammask;
((uint32_t *)buffer32->line[displine])[(x << 1) + offset] = ((uint32_t *)buffer32->line[displine])[(x << 1) + 1 + offset] = fg;
fg = svga->vram[svga->ma] | (svga->vram[svga->ma + 1] << 8) | (svga->vram[svga->ma + 2] << 16);
svga->ma += 4;
svga->ma &= svga->vrammask;
((uint32_t *)buffer32->line[svga->displine])[(x << 1) + offset] = ((uint32_t *)buffer32->line[svga->displine])[(x << 1) + 1 + offset] = fg;
}
}
}
void svga_render_32bpp_highres()
void svga_render_32bpp_highres(svga_t *svga)
{
int x, offset;
uint32_t fg;
if (changedvram[ma>>10] || changedvram[(ma>>10)+1] || changedvram[(ma>>10)+2] || fullchange)
if (svga->changedvram[svga->ma >> 10] || svga->changedvram[(svga->ma >> 10) + 1] || svga->changedvram[(svga->ma >> 10) + 2] || fullchange)
{
if (firstline_draw == 2000) firstline_draw = displine;
lastline_draw = displine;
if (svga->firstline_draw == 2000)
svga->firstline_draw = svga->displine;
svga->lastline_draw = svga->displine;
offset = (8 - ((scrollcache & 6) >> 1)) + 24;
offset = (8 - ((svga->scrollcache & 6) >> 1)) + 24;
for (x = 0; x <= svga_hdisp; x++)
for (x = 0; x <= svga->hdisp; x++)
{
fg=vram[ma]|(vram[ma+1]<<8)|(vram[ma+2]<<16);
ma+=4; ma&=vrammask;
((uint32_t *)buffer32->line[displine])[x + offset] = fg;
fg = svga->vram[svga->ma] | (svga->vram[svga->ma + 1] << 8) | (svga->vram[svga->ma + 2] << 16);
svga->ma += 4;
svga->ma &= svga->vrammask;
((uint32_t *)buffer32->line[svga->displine])[x + offset] = fg;
}
}
}

View file

@ -9,22 +9,22 @@ extern int scrollcache;
extern uint8_t edatlookup[4][4];
void svga_render_blank();
void svga_render_text_40();
void svga_render_text_80();
void svga_render_blank(svga_t *svga);
void svga_render_text_40(svga_t *svga);
void svga_render_text_80(svga_t *svga);
void svga_render_2bpp_lowres();
void svga_render_4bpp_lowres();
void svga_render_4bpp_highres();
void svga_render_8bpp_lowres();
void svga_render_8bpp_highres();
void svga_render_15bpp_lowres();
void svga_render_15bpp_highres();
void svga_render_16bpp_lowres();
void svga_render_16bpp_highres();
void svga_render_24bpp_lowres();
void svga_render_24bpp_highres();
void svga_render_32bpp_lowres();
void svga_render_32bpp_highres();
void svga_render_2bpp_lowres(svga_t *svga);
void svga_render_4bpp_lowres(svga_t *svga);
void svga_render_4bpp_highres(svga_t *svga);
void svga_render_8bpp_lowres(svga_t *svga);
void svga_render_8bpp_highres(svga_t *svga);
void svga_render_15bpp_lowres(svga_t *svga);
void svga_render_15bpp_highres(svga_t *svga);
void svga_render_16bpp_lowres(svga_t *svga);
void svga_render_16bpp_highres(svga_t *svga);
void svga_render_24bpp_lowres(svga_t *svga);
void svga_render_24bpp_highres(svga_t *svga);
void svga_render_32bpp_lowres(svga_t *svga);
void svga_render_32bpp_highres(svga_t *svga);
extern void (*svga_render)();
extern void (*svga_render)(svga_t *svga);

File diff suppressed because it is too large Load diff

1
src/vid_tandy.h Normal file
View file

@ -0,0 +1 @@
extern device_t tandy_device;

View file

@ -7,29 +7,29 @@
static int tkd8001_state=0;
static uint8_t tkd8001_ctrl;
void tkd8001_ramdac_out(uint16_t addr, uint8_t val, void *priv)
void tkd8001_ramdac_out(uint16_t addr, uint8_t val, tkd8001_ramdac_t *ramdac, svga_t *svga)
{
// pclog("OUT RAMDAC %04X %02X %04X:%04X\n",addr,val,CS,pc);
switch (addr)
{
case 0x3C6:
if (tkd8001_state == 4)
if (ramdac->state == 4)
{
tkd8001_state = 0;
tkd8001_ctrl = val;
switch (val>>5)
ramdac->state = 0;
ramdac->ctrl = val;
switch (val >> 5)
{
case 0: case 1: case 2: case 3:
bpp = 8;
svga->bpp = 8;
break;
case 5:
bpp = 15;
svga->bpp = 15;
break;
case 6:
bpp = 24;
svga->bpp = 24;
break;
case 7:
bpp = 16;
svga->bpp = 16;
break;
}
return;
@ -37,28 +37,28 @@ void tkd8001_ramdac_out(uint16_t addr, uint8_t val, void *priv)
// tkd8001_state = 0;
break;
case 0x3C7: case 0x3C8: case 0x3C9:
tkd8001_state = 0;
ramdac->state = 0;
break;
}
svga_out(addr, val, NULL);
svga_out(addr, val, svga);
}
uint8_t tkd8001_ramdac_in(uint16_t addr, void *priv)
uint8_t tkd8001_ramdac_in(uint16_t addr, tkd8001_ramdac_t *ramdac, svga_t *svga)
{
// pclog("IN RAMDAC %04X %04X:%04X\n",addr,CS,pc);
switch (addr)
{
case 0x3C6:
if (tkd8001_state == 4)
if (ramdac->state == 4)
{
//tkd8001_state = 0;
return tkd8001_ctrl;
return ramdac->ctrl;
}
tkd8001_state++;
ramdac->state++;
break;
case 0x3C7: case 0x3C8: case 0x3C9:
tkd8001_state = 0;
ramdac->state = 0;
break;
}
return svga_in(addr, NULL);
return svga_in(addr, svga);
}

View file

@ -1,2 +1,8 @@
void tkd8001_ramdac_out(uint16_t addr, uint8_t val, void *priv);
uint8_t tkd8001_ramdac_in(uint16_t addr, void *priv);
typedef struct tkd8001_ramdac_t
{
int state;
uint8_t ctrl;
} tkd8001_ramdac_t;
void tkd8001_ramdac_out(uint16_t addr, uint8_t val, tkd8001_ramdac_t *ramdac, svga_t *svga);
uint8_t tkd8001_ramdac_in(uint16_t addr, tkd8001_ramdac_t *ramdac, svga_t *svga);

File diff suppressed because it is too large Load diff

2
src/vid_tvga.h Normal file
View file

@ -0,0 +1,2 @@
extern device_t tvga8900d_device;
extern device_t tgui9440_device;

View file

@ -6,61 +6,58 @@
#include "vid_svga.h"
#include "vid_unk_ramdac.h"
static int unk_state=0;
static uint8_t unk_ctrl;
void unk_ramdac_out(uint16_t addr, uint8_t val, void *priv)
void unk_ramdac_out(uint16_t addr, uint8_t val, unk_ramdac_t *ramdac, svga_t *svga)
{
//pclog("OUT RAMDAC %04X %02X\n",addr,val);
switch (addr)
{
case 0x3C6:
if (unk_state == 4)
if (ramdac->state == 4)
{
unk_state = 0;
unk_ctrl = val;
ramdac->state = 0;
ramdac->ctrl = val;
switch ((val&1)|((val&0xE0)>>4))
{
case 0: case 1: case 2: case 3:
bpp = 8;
svga->bpp = 8;
break;
case 6: case 7:
bpp = 24;
svga->bpp = 24;
break;
case 8: case 9: case 0xA: case 0xB:
bpp = 15;
svga->bpp = 15;
break;
case 0xC: case 0xD: case 0xE: case 0xF:
bpp = 16;
svga->bpp = 16;
break;
}
return;
}
unk_state = 0;
ramdac->state = 0;
break;
case 0x3C7: case 0x3C8: case 0x3C9:
unk_state = 0;
ramdac->state = 0;
break;
}
svga_out(addr, val, NULL);
svga_out(addr, val, svga);
}
uint8_t unk_ramdac_in(uint16_t addr, void *priv)
uint8_t unk_ramdac_in(uint16_t addr, unk_ramdac_t *ramdac, svga_t *svga)
{
//pclog("IN RAMDAC %04X\n",addr);
switch (addr)
{
case 0x3C6:
if (unk_state == 4)
if (ramdac->state == 4)
{
unk_state = 0;
return unk_ctrl;
ramdac->state = 0;
return ramdac->ctrl;
}
unk_state++;
ramdac->state++;
break;
case 0x3C7: case 0x3C8: case 0x3C9:
unk_state = 0;
ramdac->state = 0;
break;
}
return svga_in(addr, NULL);
return svga_in(addr, svga);
}

View file

@ -1,2 +1,8 @@
void unk_ramdac_out(uint16_t addr, uint8_t val, void *priv);
uint8_t unk_ramdac_in(uint16_t addr, void *priv);
typedef struct unk_ramdac_t
{
int state;
uint8_t ctrl;
} unk_ramdac_t;
void unk_ramdac_out(uint16_t addr, uint8_t val, unk_ramdac_t *ramdac, svga_t *svga);
uint8_t unk_ramdac_in(uint16_t addr, unk_ramdac_t *ramdac, svga_t *svga);

View file

@ -1,92 +1,116 @@
/*IBM VGA emulation*/
#include <stdlib.h>
#include "ibm.h"
#include "device.h"
#include "io.h"
#include "video.h"
#include "vid_svga.h"
#include "vid_vga.h"
void vga_out(uint16_t addr, uint8_t val, void *priv)
typedef struct vga_t
{
svga_t svga;
} vga_t;
void vga_out(uint16_t addr, uint8_t val, void *p)
{
vga_t *vga = (vga_t *)p;
svga_t *svga = &vga->svga;
uint8_t old;
pclog("vga_out : %04X %02X %04X:%04X %02X %i\n", addr, val, CS,pc, ram[0x489], ins);
if (((addr&0xFFF0) == 0x3D0 || (addr&0xFFF0) == 0x3B0) && !(svga_miscout&1)) addr ^= 0x60;
if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(svga->miscout & 1))
addr ^= 0x60;
switch (addr)
{
case 0x3D4:
crtcreg = val & 0x1f;
svga->crtcreg = val & 0x1f;
return;
case 0x3D5:
if (crtcreg <= 7 && crtc[0x11] & 0x80) return;
old=crtc[crtcreg];
crtc[crtcreg]=val;
if (old!=val)
if (svga->crtcreg <= 7 && svga->crtc[0x11] & 0x80) return;
old = svga->crtc[svga->crtcreg];
svga->crtc[svga->crtcreg] = val;
if (old != val)
{
if (crtcreg<0xE || crtcreg>0x10)
if (svga->crtcreg < 0xe || svga->crtcreg > 0x10)
{
fullchange=changeframecount;
svga_recalctimings();
fullchange = changeframecount;
svga_recalctimings(svga);
}
}
break;
}
svga_out(addr, val, NULL);
svga_out(addr, val, svga);
}
uint8_t vga_in(uint16_t addr, void *priv)
uint8_t vga_in(uint16_t addr, void *p)
{
vga_t *vga = (vga_t *)p;
svga_t *svga = &vga->svga;
uint8_t temp;
if (addr != 0x3da) pclog("vga_in : %04X ", addr);
if (((addr&0xFFF0) == 0x3D0 || (addr&0xFFF0) == 0x3B0) && !(svga_miscout&1)) addr ^= 0x60;
if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(svga->miscout & 1))
addr ^= 0x60;
switch (addr)
{
case 0x3D4:
temp = crtcreg;
temp = svga->crtcreg;
break;
case 0x3D5:
temp = crtc[crtcreg];
temp = svga->crtc[svga->crtcreg];
break;
default:
temp = svga_in(addr, NULL);
temp = svga_in(addr, svga);
break;
}
if (addr != 0x3da) pclog("%02X %04X:%04X\n", temp, CS,pc);
return temp;
}
int vga_init()
void *vga_init()
{
svga_recalctimings_ex = NULL;
svga_vram_limit = 1 << 18; /*256kb*/
vrammask = 0x3ffff;
svgawbank = svgarbank = 0;
bpp = 8;
svga_miscout = 1;
return svga_init();
vga_t *vga = malloc(sizeof(vga_t));
memset(vga, 0, sizeof(vga_t));
svga_init(&vga->svga, vga, 1 << 18, /*256kb*/
NULL,
vga_in, vga_out,
NULL);
io_sethandler(0x03c0, 0x0020, vga_in, NULL, NULL, vga_out, NULL, NULL, vga);
vga->svga.bpp = 8;
vga->svga.miscout = 1;
return vga;
}
GFXCARD vid_vga =
void vga_close(void *p)
{
vga_t *vga = (vga_t *)p;
svga_close(&vga->svga);
free(vga);
}
void vga_speed_changed(void *p)
{
vga_t *vga = (vga_t *)p;
svga_recalctimings(&vga->svga);
}
device_t vga_device =
{
"VGA",
vga_init,
/*IO at 3Cx/3Dx*/
vga_out,
vga_in,
/*IO at 3Ax/3Bx*/
video_out_null,
video_in_null,
svga_poll,
svga_recalctimings,
svga_write,
video_write_null,
video_write_null,
svga_read,
video_read_null,
video_read_null
vga_close,
vga_speed_changed,
svga_add_status_info
};

1
src/vid_vga.h Normal file
View file

@ -0,0 +1 @@
extern device_t vga_device;

View file

@ -1,13 +1,45 @@
#include <stdio.h>
#include <math.h>
#include "ibm.h"
#include "device.h"
#include "video.h"
#include "vid_svga.h"
#include "io.h"
#include "cpu.h"
#include "timer.h"
int video_timer;
#include "vid_ati18800.h"
#include "vid_ati28800.h"
#include "vid_ati_mach64.h"
#include "vid_cga.h"
#include "vid_cl5429.h"
#include "vid_ega.h"
#include "vid_et4000.h"
#include "vid_et4000w32.h"
#include "vid_hercules.h"
#include "vid_mda.h"
#include "vid_olivetti_m24.h"
#include "vid_oti067.h"
#include "vid_paradise.h"
#include "vid_pc1512.h"
#include "vid_pc1640.h"
#include "vid_pc200.h"
#include "vid_s3.h"
#include "vid_s3_virge.h"
#include "vid_tandy.h"
#include "vid_tvga.h"
#include "vid_vga.h"
int egareads=0,egawrites=0;
int changeframecount=2;
uint8_t rotatevga[8][256];
int frames = 0;
int fullchange;
uint8_t edatlookup[4][4];
/*Video timing settings -
@ -84,70 +116,6 @@ int video_res_x, video_res_y, video_bpp;
void (*video_blit_memtoscreen)(int x, int y, int y1, int y2, int w, int h);
void (*video_blit_memtoscreen_8)(int x, int y, int w, int h);
void (*video_out) (uint16_t addr, uint8_t val, void *priv);
void (*video_mono_out)(uint16_t addr, uint8_t val, void *priv);
uint8_t (*video_in) (uint16_t addr, void *priv);
uint8_t (*video_mono_in)(uint16_t addr, void *priv);
void (*video_write_a000)(uint32_t addr, uint8_t val, void *priv);
void (*video_write_b000)(uint32_t addr, uint8_t val, void *priv);
void (*video_write_b800)(uint32_t addr, uint8_t val, void *priv);
void (*video_write_a000_w)(uint32_t addr, uint16_t val, void *priv);
void (*video_write_a000_l)(uint32_t addr, uint32_t val, void *priv);
uint8_t (*video_read_a000)(uint32_t addr, void *priv);
uint8_t (*video_read_b000)(uint32_t addr, void *priv);
uint8_t (*video_read_b800)(uint32_t addr, void *priv);
void (*video_recalctimings)();
void video_out_null(uint16_t addr, uint8_t val, void *priv)
{
}
uint8_t video_in_null(uint16_t addr, void *priv)
{
return 0xFF;
}
void video_write_null(uint32_t addr, uint8_t val, void *priv)
{
}
uint8_t video_read_null(uint32_t addr, void *priv)
{
return 0xff;
}
void video_load(GFXCARD g)
{
io_sethandler(0x03a0, 0x0020, g.mono_in, NULL, NULL, g.mono_out, NULL, NULL, NULL);
io_sethandler(0x03c0, 0x0020, g.in, NULL, NULL, g.out, NULL, NULL, NULL);
video_out = g.out;
video_in = g.in;
video_mono_out = g.mono_out;
video_mono_in = g.mono_in;
pollvideo = g.poll;
video_recalctimings = g.recalctimings;
video_write_a000 = g.write_a000;
video_write_b000 = g.write_b000;
video_write_b800 = g.write_b800;
video_read_a000 = g.read_a000;
video_read_b000 = g.read_b000;
video_read_b800 = g.read_b800;
video_write_a000_w = video_write_a000_l = NULL;
g.init();
video_timer = timer_add(pollvideo, &vidtime, TIMER_ALWAYS_ENABLED, NULL);
}
void video_init()
{
pclog("Video_init %i %i\n",romset,gfxcard);
@ -155,107 +123,108 @@ void video_init()
switch (romset)
{
case ROM_TANDY:
video_load(vid_tandy);
device_add(&tandy_device);
return;
case ROM_PC1512:
video_load(vid_pc1512);
device_add(&pc1512_device);
return;
case ROM_PC1640:
video_load(vid_pc1640);
device_add(&pc1640_device);
return;
case ROM_PC200:
video_load(vid_pc200);
device_add(&pc200_device);
return;
case ROM_OLIM24:
video_load(vid_m24);
device_add(&m24_device);
return;
case ROM_PC2086:
case ROM_PC3086:
device_add(&paradise_pvga1a_device);
return;
case ROM_MEGAPC:
video_load(vid_paradise);
device_add(&paradise_wd90c11_device);
return;
case ROM_ACER386:
video_load(vid_oti067);
device_add(&oti067_device);
return;
}
switch (gfxcard)
{
case GFX_MDA:
video_load(vid_mda);
device_add(&mda_device);
break;
case GFX_HERCULES:
video_load(vid_hercules);
device_add(&hercules_device);
break;
case GFX_CGA:
video_load(vid_cga);
device_add(&cga_device);
break;
case GFX_EGA:
video_load(vid_ega);
device_add(&ega_device);
break;
case GFX_TVGA:
video_load(vid_tvga);
device_add(&tvga8900d_device);
break;
case GFX_ET4000:
video_load(vid_et4000);
device_add(&et4000_device);
break;
case GFX_ET4000W32:
video_load(vid_et4000w32p);
device_add(&et4000w32p_device);
break;
case GFX_BAHAMAS64:
video_load(vid_s3);
device_add(&s3_bahamas64_device);
break;
case GFX_N9_9FX:
video_load(vid_s3);
device_add(&s3_9fx_device);
break;
case GFX_STEALTH64:
video_load(vid_s3);
break;
case GFX_VIRGE:
video_load(vid_s3_virge);
device_add(&s3_virge_device);
break;
case GFX_TGUI9440:
video_load(vid_tgui9440);
device_add(&tgui9440_device);
break;
case GFX_VGA:
video_load(vid_vga);
device_add(&vga_device);
break;
case GFX_VGAEDGE16:
video_load(vid_ati18800);
device_add(&ati18800_device);
break;
case GFX_VGACHARGER:
video_load(vid_ati28800);
device_add(&ati18800_device);
break;
case GFX_OTI067:
video_load(vid_oti067);
device_add(&oti067_device);
return;
case GFX_MACH64GX:
video_load(vid_mach64);
device_add(&mach64gx_device);
return;
case GFX_CL_GD5429:
video_load(vid_gd5429);
device_add(&gd5429_device);
return;
default:
@ -263,78 +232,26 @@ void video_init()
}
}
uint32_t cga32[256];
BITMAP *buffer,*vbuf;//,*vbuf2;
BITMAP *buffer32;
int speshul=0;
BITMAP *buffer, *buffer32;
uint8_t fontdat[256][8];
uint8_t fontdatm[256][16];
int dispontime,dispofftime;
double disptime;
int svgaon;
uint8_t cgamode=1,cgastat,cgacol=7,ocgamode;
int linepos=0;
int output;
uint8_t *vram,*ram;
int cgadispon=0;
int cgablink;
uint8_t port3de,port3dd,port3df;
uint8_t crtc[128],crtcreg;
uint8_t crtcmask[128]={0xFF,0xFF,0xFF,0xFF,0x7F,0x1F,0x7F,0x7F,0xF3,0x1F,0x7F,0x1F,0x3F,0xFF,0x3F,0xFF,0xFF,0xFF};
uint8_t charbuffer[256];
int crtcams[64]={0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1};
int nmi=0;
int xsize=1,ysize=1;
int firstline=1000,lastline=0;
int ntsc_col[8][8]=
PALETTE cgapal;/* =
{
{0,0,0,0,0,0,0,0}, /*Black*/
{0,0,1,1,1,1,0,0}, /*Blue*/
{1,0,0,0,0,1,1,1}, /*Green*/
{0,0,0,0,1,1,1,1}, /*Cyan*/
{1,1,1,1,0,0,0,0}, /*Red*/
{0,1,1,1,1,0,0,0}, /*Magenta*/
{1,1,0,0,0,0,1,1}, /*Yellow*/
{1,1,1,1,1,1,1,1} /*White*/
};
{ 0, 0, 0},{0,42,0},{42,0,0},{42,21,0},
{ 0, 0, 0},{0,42,42},{42,0,42},{42,42,42},
{ 0, 0, 0},{21,63,21},{63,21,21},{63,63,21},
{ 0, 0, 0},{21,63,63},{63,21,63},{63,63,63},
extern int fullchange;
extern uint32_t vrammask;
int mdacols[256][2][2];
uint8_t gdcreg[16];
int cga4pal[8][4]=
{
{0,2,4,6},{0,3,5,7},{0,3,4,7},{0,3,4,7},
{0,10,12,14},{0,11,13,15},{0,11,12,15},{0,11,12,15}
};
PALETTE cgapal=
{
{0,0,0},{0,42,0},{42,0,0},{42,21,0},
{0,0,0},{0,42,42},{42,0,42},{42,42,42},
{0,0,0},{21,63,21},{63,21,21},{63,63,21},
{0,0,0},{21,63,63},{63,21,63},{63,63,63},
{0,0,0},{0,0,42},{0,42,0},{0,42,42},
{42,0,0},{42,0,42},{42,21,00},{42,42,42},
{21,21,21},{21,21,63},{21,63,21},{21,63,63},
{63,21,21},{63,21,63},{63,63,21},{63,63,63},
{0, 0, 0}, { 0, 0, 42}, { 0, 42, 0}, { 0, 42, 42},
{42, 0, 0}, {42, 0, 42}, {42, 21, 00}, {42, 42, 42},
{21, 21, 21}, {21, 21, 63}, {21, 63, 21}, {21, 63, 63},
{63, 21, 21}, {63, 21, 63}, {63, 63, 21}, {63, 63, 63},
{0,0,0},{0,21,0},{0,0,42},{0,42,42},
{42,0,21},{21,10,21},{42,0,42},{42,0,63},
@ -345,7 +262,7 @@ PALETTE cgapal=
{0,0,0},{0,42,42},{42,0,0},{42,42,42},
{0,0,0},{0,63,63},{63,0,0},{63,63,63},
{0,0,0},{0,63,63},{63,0,0},{63,63,63},
};
};*/
void loadfont(char *s, int format)
{
@ -419,102 +336,53 @@ void loadfont(char *s, int format)
}
void drawscreen()
{
// printf("Drawscreen %i %i %i %i\n",gfxcard,MDA,EGA,TANDY);
// if (EGA) drawscreenega(buffer,vbuf);
/* else if (MDA) {}//drawscreenmda();
else if (TANDY)
{
if ((cgamode&3)==3 || array[3]&0x10) drawscreentandy(tandyvram);
else drawscreencga(tandyvram);
}*/
// else drawscreencga(&vram[0x8000]);
}
PALETTE comppal=
{
{0,0,0},{0,21,0},{0,0,42},{0,42,42},
{42,0,21},{21,10,21},{42,0,42},{42,0,63},
{21,21,21},{21,63,21},{42,21,42},{21,63,31},
{63,0,0},{42,42,0},{63,21,42},{41,41,41}
};
void initvideo()
{
int c;
// set_color_depth(desktop_color_depth());
// if (set_gfx_mode(GFX_AUTODETECT_WINDOWED,2048,2048,0,0))
// set_gfx_mode(GFX_AUTODETECT_WINDOWED,1024,768,0,0);
// vbuf=create_video_bitmap(1280+32,1024+32);
// set_color_depth(32);
buffer32=create_bitmap(2048,2048);
// set_color_depth(8);
buffer=create_bitmap(2048,2048);
// set_color_depth(32);
for (c=0;c<64;c++)
{
cgapal[c+64].r=(((c&4)?2:0)|((c&0x10)?1:0))*21;
cgapal[c+64].g=(((c&2)?2:0)|((c&0x10)?1:0))*21;
cgapal[c+64].b=(((c&1)?2:0)|((c&0x10)?1:0))*21;
if ((c&0x17)==6) cgapal[c+64].g>>=1;
}
for (c=0;c<64;c++)
{
cgapal[c+128].r=(((c&4)?2:0)|((c&0x20)?1:0))*21;
cgapal[c+128].g=(((c&2)?2:0)|((c&0x10)?1:0))*21;
cgapal[c+128].b=(((c&1)?2:0)|((c&0x08)?1:0))*21;
}
for (c=0;c<256;c++) cga32[c]=makecol(cgapal[c].r<<2,cgapal[c].g<<2,cgapal[c].b<<2);
// for (c=0;c<16;c++) cgapal[c+192]=comppal[c];
// set_palette(cgapal);
if (MDA && !TANDY && !AMSTRAD && romset!=ROM_PC200) updatewindowsize(720,350);
else updatewindowsize(656,416);
for (c=17;c<64;c++) crtcmask[c]=0xFF;
}
int c, d, e;
void resetvideo()
{
int c;
if (MDA && !TANDY && !AMSTRAD && romset!=ROM_PC200) updatewindowsize(720,350);
else updatewindowsize(656,416);
cgastat=0;
set_palette(cgapal);
buffer32 = create_bitmap(2048, 2048);
for (c=18;c<64;c++) crtcmask[c]=0xFF;
crtc[0]=0x38;
crtc[1]=0x28;
// crtc[3]=0xFA;
crtc[4]=0x7F;
crtc[5]=0x06;
crtc[6]=0x64;
crtc[7]=0x70;
crtc[8]=0x02;
crtc[9]=1;
buffer = create_bitmap(2048, 2048);
cgacol=7;
for (c=0;c<256;c++)
for (c = 0; c < 64; c++)
{
mdacols[c][0][0]=mdacols[c][1][0]=mdacols[c][1][1]=16;
if (c&8) mdacols[c][0][1]=15+16;
else mdacols[c][0][1]=7+16;
cgapal[c + 64].r = (((c & 4) ? 2 : 0) | ((c & 0x10) ? 1 : 0)) * 21;
cgapal[c + 64].g = (((c & 2) ? 2 : 0) | ((c & 0x10) ? 1 : 0)) * 21;
cgapal[c + 64].b = (((c & 1) ? 2 : 0) | ((c & 0x10) ? 1 : 0)) * 21;
if ((c & 0x17) == 6)
cgapal[c + 64].g >>= 1;
}
for (c = 0; c < 64; c++)
{
cgapal[c + 128].r = (((c & 4) ? 2 : 0) | ((c & 0x20) ? 1 : 0)) * 21;
cgapal[c + 128].g = (((c & 2) ? 2 : 0) | ((c & 0x10) ? 1 : 0)) * 21;
cgapal[c + 128].b = (((c & 1) ? 2 : 0) | ((c & 0x08) ? 1 : 0)) * 21;
}
for (c = 0; c < 256; c++)
{
e = c;
for (d = 0; d < 8; d++)
{
rotatevga[d][c] = e;
e = (e >> 1) | ((e & 1) ? 0x80 : 0);
}
}
for (c = 0; c < 4; c++)
{
for (d = 0; d < 4; d++)
{
edatlookup[c][d] = 0;
if (c & 1) edatlookup[c][d] |= 1;
if (d & 1) edatlookup[c][d] |= 2;
if (c & 2) edatlookup[c][d] |= 0x10;
if (d & 2) edatlookup[c][d] |= 0x20;
// printf("Edat %i,%i now %02X\n",c,d,edatlookup[c][d]);
}
}
mdacols[0x70][0][1]=16;
mdacols[0x70][0][0]=mdacols[0x70][1][0]=mdacols[0x70][1][1]=16+15;
mdacols[0xF0][0][1]=16;
mdacols[0xF0][0][0]=mdacols[0xF0][1][0]=mdacols[0xF0][1][1]=16+15;
mdacols[0x78][0][1]=16+7;
mdacols[0x78][0][0]=mdacols[0x78][1][0]=mdacols[0x78][1][1]=16+15;
mdacols[0xF8][0][1]=16+7;
mdacols[0xF8][0][0]=mdacols[0xF8][1][0]=mdacols[0xF8][1][1]=16+15;
mdacols[0x00][0][1] = mdacols[0x00][1][1] = 16;
mdacols[0x08][0][1] = mdacols[0x08][1][1] = 16;
mdacols[0x80][0][1] = mdacols[0x80][1][1] = 16;
mdacols[0x88][0][1] = mdacols[0x88][1][1] = 16;
}
void closevideo()
{
destroy_bitmap(buffer);
destroy_bitmap(vbuf);
}

View file

@ -1,70 +1,8 @@
extern int egareads,egawrites;
extern int bpp;
extern uint8_t svgaseg,svgaseg2;
extern uint8_t crtcreg;
extern uint8_t crtc[128];
extern uint8_t crtcmask[128];
extern uint8_t gdcreg[16];
extern int gdcaddr;
extern uint8_t attrregs[32];
extern int attraddr,attrff;
extern uint8_t seqregs[64];
extern int seqaddr;
extern int svgaon;
extern uint8_t cgamode,cgacol,cgastat;
extern int egapal[16];
extern int scrblank;
extern uint8_t writemask,charset;
extern int charseta,charsetb;
extern uint8_t colourcompare,colournocare;
extern int readplane,readmode,writemode;
extern int vidclock;
extern int vres;
extern uint32_t *pallook,pallook16[256],pallook64[256],pallook256[256];
extern int fullchange;
extern int changeframecount;
extern int firstline,lastline;
extern int ega_hdisp,ega_rowoffset,ega_split,ega_dispend,ega_vsyncstart,ega_vtotal;
extern int dispontime,dispofftime;
extern double disptime;
extern void (*video_out) (uint16_t addr, uint8_t val, void *priv);
extern void (*video_mono_out)(uint16_t addr, uint8_t val, void *priv);
extern uint8_t (*video_in) (uint16_t addr, void *priv);
extern uint8_t (*video_mono_in)(uint16_t addr, void *priv);
extern void (*video_write_a000)(uint32_t addr, uint8_t val, void *priv);
extern void (*video_write_b000)(uint32_t addr, uint8_t val, void *priv);
extern void (*video_write_b800)(uint32_t addr, uint8_t val, void *priv);
extern uint8_t (*video_read_a000)(uint32_t addr, void *priv);
extern uint8_t (*video_read_b000)(uint32_t addr, void *priv);
extern uint8_t (*video_read_b800)(uint32_t addr, void *priv);
extern void (*video_write_a000_w)(uint32_t addr, uint16_t val, void *priv);
extern void (*video_write_a000_l)(uint32_t addr, uint32_t val, void *priv);
extern void video_out_null(uint16_t addr, uint8_t val, void *priv);
extern uint8_t video_in_null(uint16_t addr, void *priv);
extern void video_write_null(uint32_t addr, uint8_t val, void *priv);
extern uint8_t video_read_null (uint32_t addr, void *priv);
extern int video_timer;
extern uint8_t tridentoldctrl2,tridentnewctrl2;
extern int rowdbl;
typedef struct
{
int w, h;
@ -72,73 +10,23 @@ typedef struct
uint8_t *line[0];
} BITMAP;
extern BITMAP *buffer,*buffer32,*vbuf;
extern BITMAP *buffer, *buffer32;
extern BITMAP *screen;
BITMAP *create_bitmap(int w, int h);
extern int wx,wy;
extern uint8_t fontdat[256][8];
extern uint8_t fontdatm[256][16];
extern int xsize,ysize;
extern int dacread,dacwrite,dacpos;
typedef struct
{
uint8_t r, g, b;
} RGB;
typedef RGB PALETTE[256];
extern PALETTE vgapal;
extern int palchange;
extern uint32_t vrammask;
typedef struct
{
int (*init)();
void (*out)(uint16_t addr, uint8_t val, void *priv);
uint8_t (*in)(uint16_t addr, void *priv);
void (*mono_out)(uint16_t addr, uint8_t val, void *priv);
uint8_t (*mono_in)(uint16_t addr, void *priv);
void (*poll)();
void (*recalctimings)();
void (*write_a000)(uint32_t addr, uint8_t val, void *priv);
void (*write_b000)(uint32_t addr, uint8_t val, void *priv);
void (*write_b800)(uint32_t addr, uint8_t val, void *priv);
uint8_t (*read_a000)(uint32_t addr, void *priv);
uint8_t (*read_b000)(uint32_t addr, void *priv);
uint8_t (*read_b800)(uint32_t addr, void *priv);
} GFXCARD;
extern GFXCARD vid_cga;
extern GFXCARD vid_mda;
extern GFXCARD vid_hercules;
extern GFXCARD vid_pc1512;
extern GFXCARD vid_pc1640;
extern GFXCARD vid_pc200;
extern GFXCARD vid_m24;
extern GFXCARD vid_paradise;
extern GFXCARD vid_tandy;
extern GFXCARD vid_ega;
extern GFXCARD vid_oti067;
extern GFXCARD vid_tvga;
extern GFXCARD vid_et4000;
extern GFXCARD vid_et4000w32p;
extern GFXCARD vid_s3;
extern GFXCARD vid_s3_virge;
extern GFXCARD vid_tgui9440;
extern GFXCARD vid_vga;
extern GFXCARD vid_ati18800;
extern GFXCARD vid_ati28800;
extern GFXCARD vid_mach64;
extern GFXCARD vid_gd5429;
extern float cpuclock;
@ -154,7 +42,6 @@ extern void (*video_recalctimings)();
extern void (*video_blit_memtoscreen)(int x, int y, int y1, int y2, int w, int h);
extern void (*video_blit_memtoscreen_8)(int x, int y, int w, int h);
extern int video_timing_b, video_timing_w, video_timing_l;
extern int video_speed;

View file

@ -377,6 +377,9 @@ int WINAPI WinMain (HINSTANCE hThisInstance,
}
}
}
loadbios();
timeBeginPeriod(1);
// soundobject=CreateEvent(NULL, FALSE, FALSE, NULL);
// soundthreadh=CreateThread(NULL,0,soundthread,NULL,NULL,NULL);
@ -758,8 +761,8 @@ BOOL CALLBACK configdlgproc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lPara
sound_card_current = temp_sound_card_current;
mem_resize();
loadbios();
mem_load_video_bios();
loadbios();
resetpchard();
}
else
@ -1327,6 +1330,7 @@ BOOL CALLBACK statusdlgproc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lPara
{
int egasp;
char s[256];
char device_s[4096];
switch (message)
{
case WM_INITDIALOG:
@ -1350,18 +1354,8 @@ BOOL CALLBACK statusdlgproc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lPara
SendDlgItemMessage(hdlg,IDC_STEXT7,WM_SETTEXT,(WPARAM)NULL,(LPARAM)s);
sprintf(s,"Timer 0 frequency : %fHz",pit_timer0_freq());
SendDlgItemMessage(hdlg,IDC_STEXT8,WM_SETTEXT,(WPARAM)NULL,(LPARAM)s);
if (chain4) sprintf(s,"VGA chained (possibly mode 13h)");
else sprintf(s,"VGA unchained (possibly mode-X)");
SendDlgItemMessage(hdlg,IDC_STEXT9,WM_SETTEXT,(WPARAM)NULL,(LPARAM)s);
/* if (!video_bpp) sprintf(s,"VGA in text mode");
else */sprintf(s,"VGA colour depth : %i bpp", video_bpp);
SendDlgItemMessage(hdlg,IDC_STEXT10,WM_SETTEXT,(WPARAM)NULL,(LPARAM)s);
sprintf(s,"VGA resolution : %i x %i", video_res_x, video_res_y);
SendDlgItemMessage(hdlg,IDC_STEXT11,WM_SETTEXT,(WPARAM)NULL,(LPARAM)s);
sprintf(s,"SB frequency : %i Hz",0);
SendDlgItemMessage(hdlg,IDC_STEXT12,WM_SETTEXT,(WPARAM)NULL,(LPARAM)s);
sprintf(s,"Video refresh rate : %i Hz", emu_fps);
SendDlgItemMessage(hdlg,IDC_STEXT13,WM_SETTEXT,(WPARAM)NULL,(LPARAM)s);
device_add_status_info(device_s, 4096);
SendDlgItemMessage(hdlg,IDC_STEXT_DEVICE,WM_SETTEXT,(WPARAM)NULL,(LPARAM)device_s);
return TRUE;
case WM_COMMAND:
switch (LOWORD(wParam))