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 "timer.h"
#include "x86.h" #include "x86.h"
int nmi = 0;
int nextcyc=0; int nextcyc=0;
int cycdiff; int cycdiff;
int is8086=0; 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]; char name[50];
void *(*init)(); void *(*init)();
void (*close)(void *priv); void (*close)(void *p);
void (*speed_changed)(void *priv); void (*speed_changed)(void *p);
int (*add_status_info)(char *s, int max_len, void *p);
} device_t; } device_t;
void device_init(); void device_init();
void device_add(device_t *d); void device_add(device_t *d);
void device_close_all(); void device_close_all();
void device_speed_changed(); 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)) /* 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; // if (val==0x29 && pc==0xD25) output=1;
// } // }
dmapages[addr&0xF]=val; dmapages[addr&0xF]=val;
@ -258,12 +258,12 @@ uint8_t _dma_read(uint32_t addr)
{ {
switch (addr&0xFFFF8000) switch (addr&0xFFFF8000)
{ {
case 0xA0000: case 0xA8000: /* case 0xA0000: case 0xA8000:
return video_read_a000(addr, NULL); return video_read_a000(addr, NULL);
case 0xB0000: case 0xB0000:
return video_read_b000(addr, NULL); return video_read_b000(addr, NULL);
case 0xB8000: case 0xB8000:
return video_read_b800(addr, NULL); return video_read_b800(addr, NULL);*/
} }
if (isram[addr>>16]) return ram[addr]; if (isram[addr>>16]) return ram[addr];
return 0xff; return 0xff;
@ -271,9 +271,10 @@ uint8_t _dma_read(uint32_t addr)
void _dma_write(uint32_t addr, uint8_t val) void _dma_write(uint32_t addr, uint8_t val)
{ {
pclog("_dma_write %08X %02X\n", addr, val);
switch (addr&0xFFFF8000) switch (addr&0xFFFF8000)
{ {
case 0xA0000: case 0xA8000: /* case 0xA0000: case 0xA8000:
video_write_a000(addr,val, NULL); video_write_a000(addr,val, NULL);
return; return;
case 0xB0000: case 0xB0000:
@ -284,7 +285,7 @@ void _dma_write(uint32_t addr, uint8_t val)
return; return;
case 0xC0000: case 0xC8000: case 0xD0000: case 0xD8000: case 0xC0000: case 0xC8000: case 0xD0000: case 0xD8000:
case 0xE0000: case 0xE8000: case 0xF0000: case 0xF8000: case 0xE0000: case 0xE8000: case 0xF0000: case 0xF8000:
return; return;*/
} }
if (isram[addr >> 16]) if (isram[addr >> 16])
ram[addr] = val; ram[addr] = val;

269
src/ega.c
View file

@ -1,217 +1,10 @@
#include "ibm.h" #include "ibm.h"
#include "video.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() void dumpegaregs()
{ {
int c; /* int c;
printf("CRTC :"); printf("CRTC :");
for (c=0;c<0x20;c++) printf(" %02X",crtc[c]); for (c=0;c<0x20;c++) printf(" %02X",crtc[c]);
printf("\n"); printf("\n");
@ -234,64 +27,6 @@ void dumpegaregs()
for (c=0;c<0x10;c++) printf(" %02X",gdcreg[c]); for (c=0;c<0x10;c++) printf(" %02X",gdcreg[c]);
printf("\n"); printf("\n");
// printf("OLD CTRL2 = %02X NEW CTRL2 = %02X DAC = %02X 3C2 = %02X\n",tridentoldctrl2,tridentnewctrl2,tridentdac,ega3c2); // 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 float isa_timing, bus_timing;
extern int frame; extern int frame;
uint8_t *vramp;

View file

@ -3,6 +3,7 @@
#include "mem.h" #include "mem.h"
#include "pic.h" #include "pic.h"
#include "sound.h" #include "sound.h"
#include "timer.h"
#include "keyboard.h" #include "keyboard.h"
#include "keyboard_amstrad.h" #include "keyboard_amstrad.h"
@ -31,6 +32,7 @@ static uint8_t amstrad_systemstat_1, amstrad_systemstat_2;
void keyboard_amstrad_poll() void keyboard_amstrad_poll()
{ {
keybsenddelay += (1000 * TIMER_USEC);
if (keyboard_amstrad.wantirq) if (keyboard_amstrad.wantirq)
{ {
keyboard_amstrad.wantirq = 0; keyboard_amstrad.wantirq = 0;
@ -166,4 +168,6 @@ void keyboard_amstrad_init()
keyboard_amstrad_reset(); keyboard_amstrad_reset();
keyboard_send = keyboard_amstrad_adddata; keyboard_send = keyboard_amstrad_adddata;
keyboard_poll = keyboard_amstrad_poll; 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 "mem.h"
#include "mouse.h" #include "mouse.h"
#include "pic.h" #include "pic.h"
#include "timer.h"
#include "keyboard.h" #include "keyboard.h"
#include "keyboard_olim24.h" #include "keyboard_olim24.h"
@ -38,6 +39,7 @@ static uint8_t mouse_scancodes[7];
void keyboard_olim24_poll() void keyboard_olim24_poll()
{ {
keybsenddelay += (1000 * TIMER_USEC);
//pclog("poll %i\n", keyboard_olim24.wantirq); //pclog("poll %i\n", keyboard_olim24.wantirq);
if (keyboard_olim24.wantirq) if (keyboard_olim24.wantirq)
{ {
@ -283,4 +285,6 @@ void keyboard_olim24_init()
keyboard_send = keyboard_olim24_adddata; keyboard_send = keyboard_olim24_adddata;
keyboard_poll = keyboard_olim24_poll; keyboard_poll = keyboard_olim24_poll;
mouse_poll = mouse_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(); // sb_reset();
ali1429_reset(); ali1429_reset();
et4000w32_reset();
// video_init(); // video_init();
} }
@ -209,8 +207,8 @@ void initpc()
initvideo(); initvideo();
mem_init(); mem_init();
loadbios();
mem_load_video_bios(); mem_load_video_bios();
loadbios();
loaddisc(0,discfns[0]); loaddisc(0,discfns[0]);
loaddisc(1,discfns[1]); loaddisc(1,discfns[1]);
@ -221,10 +219,8 @@ void initpc()
//loadfont(); //loadfont();
loadnvr(); loadnvr();
resetvideo();
sound_init(); sound_init();
inithdc(); inithdc();
initega();
resetide(); resetide();
ioctl_open(cdrom_drive); ioctl_open(cdrom_drive);
model_init(); model_init();
@ -244,7 +240,6 @@ void initpc()
/* if (romset==ROM_AMI386 || romset==ROM_AMI486) */fullspeed(); /* if (romset==ROM_AMI386 || romset==ROM_AMI486) */fullspeed();
mem_updatecache(); mem_updatecache();
ali1429_reset(); ali1429_reset();
et4000w32_reset();
// CPUID=(is486 && (cpuspeed==7 || cpuspeed>=9)); // CPUID=(is486 && (cpuspeed==7 || cpuspeed>=9));
// pclog("Init - CPUID %i %i\n",CPUID,cpuspeed); // pclog("Init - CPUID %i %i\n",CPUID,cpuspeed);
shadowbios=0; shadowbios=0;
@ -330,6 +325,7 @@ void runpc()
framecount++; framecount++;
if (framecountx>=100) if (framecountx>=100)
{ {
pclog("onesec\n");
framecountx=0; framecountx=0;
mips=(float)insc/1000000.0f; mips=(float)insc/1000000.0f;
insc=0; insc=0;
@ -404,7 +400,6 @@ void closepc()
{ {
atapi->exit(); atapi->exit();
// ioctl_close(); // ioctl_close();
dumpegaregs();
dumppic(); dumppic();
// output=7; // output=7;
// setpitclock(clocks[0][0][0]); // 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_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_COMBOSND,62,136,107,120,CBS_DROPDOWN | WS_VSCROLL | WS_TABSTOP
COMBOBOX IDC_COMBOMEM,62,152,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 "CMS / 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 "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 "Machine :",IDC_STATIC,15,16,40,10
LTEXT "Video :",IDC_STATIC,15,36,34,10 LTEXT "Video :",IDC_STATIC,15,36,34,10
LTEXT "CPU type :",IDC_STATIC,15,56,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 "6",IDC_STEXT6,16,76,180,10
LTEXT "7",IDC_STEXT7,16,88,180,10 LTEXT "7",IDC_STEXT7,16,88,180,10
LTEXT "8",IDC_STEXT8,16,100,180,10 LTEXT "8",IDC_STEXT8,16,100,180,10
LTEXT "9",IDC_STEXT9,16,112,180,10 LTEXT "9",IDC_STEXT_DEVICE,16,112,180,1000
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
END END

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -376,40 +376,46 @@ device_t sb_1_device =
"Sound Blaster v1.0", "Sound Blaster v1.0",
sb_1_init, sb_1_init,
sb_close, sb_close,
sb_speed_changed sb_speed_changed,
NULL
}; };
device_t sb_15_device = device_t sb_15_device =
{ {
"Sound Blaster v1.5", "Sound Blaster v1.5",
sb_15_init, sb_15_init,
sb_close, sb_close,
sb_speed_changed sb_speed_changed,
NULL
}; };
device_t sb_2_device = device_t sb_2_device =
{ {
"Sound Blaster v2.0", "Sound Blaster v2.0",
sb_2_init, sb_2_init,
sb_close, sb_close,
sb_speed_changed sb_speed_changed,
NULL
}; };
device_t sb_pro_v1_device = device_t sb_pro_v1_device =
{ {
"Sound Blaster Pro v1", "Sound Blaster Pro v1",
sb_pro_v1_init, sb_pro_v1_init,
sb_close, sb_close,
sb_speed_changed sb_speed_changed,
NULL
}; };
device_t sb_pro_v2_device = device_t sb_pro_v2_device =
{ {
"Sound Blaster Pro v2", "Sound Blaster Pro v2",
sb_pro_v2_init, sb_pro_v2_init,
sb_close, sb_close,
sb_speed_changed sb_speed_changed,
NULL
}; };
device_t sb_16_device = device_t sb_16_device =
{ {
"Sound Blaster 16", "Sound Blaster 16",
sb_16_init, sb_16_init,
sb_close, 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); pclog("sb_exec_command : SB command %02X\n", dsp->sb_command);
switch (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*/ case 0x10: /*8-bit direct mode*/
dsp->sbdat = dsp->sbdatl = dsp->sbdatr = (dsp->sb_data[0] ^ 0x80) << 8; dsp->sbdat = dsp->sbdatl = dsp->sbdatr = (dsp->sb_data[0] ^ 0x80) << 8;
break; break;

View file

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

View file

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

View file

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

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)*/ /*ATI 28800 emulation (VGA Charger)*/
#include <stdlib.h>
#include "ibm.h" #include "ibm.h"
#include "device.h"
#include "io.h" #include "io.h"
#include "video.h" #include "video.h"
#include "vid_ati28800.h"
#include "vid_ati_eeprom.h" #include "vid_ati_eeprom.h"
#include "vid_svga.h" #include "vid_svga.h"
#include "vid_svga_render.h" #include "vid_svga_render.h"
static uint8_t ati_regs[256]; typedef struct ati28800_t
static int ati_index;
void ati28800_out(uint16_t addr, uint8_t val, void *priv)
{ {
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; uint8_t old;
pclog("ati28800_out : %04X %02X %04X:%04X\n", addr, val, CS,pc); 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) switch (addr)
{ {
case 0x1ce: case 0x1ce:
ati_index = val; ati28800->index = val;
break; break;
case 0x1cf: case 0x1cf:
ati_regs[ati_index] = val; ati28800->regs[ati28800->index] = val;
switch (ati_index) switch (ati28800->index)
{ {
case 0xb2: case 0xb2:
case 0xbe: 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; svga->read_bank = ((ati28800->regs[0xb2] >> 5) & 7) * 0x10000;
svgawbank = ((ati_regs[0xb2] >> 1) & 7) * 0x10000; svga->write_bank = ((ati28800->regs[0xb2] >> 1) & 7) * 0x10000;
} }
else /*Single bank mode*/ 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; break;
case 0xb3: case 0xb3:
ati_eeprom_write(val & 8, val & 2, val & 1); ati_eeprom_write(&ati28800->eeprom, val & 8, val & 2, val & 1);
break; break;
} }
break; break;
case 0x3D4: case 0x3D4:
crtcreg = val & 0x3f; svga->crtcreg = val & 0x3f;
return; return;
case 0x3D5: case 0x3D5:
if (crtcreg <= 7 && crtc[0x11] & 0x80) return; if (svga->crtcreg <= 7 && svga->crtc[0x11] & 0x80) return;
old=crtc[crtcreg]; old = svga->crtc[svga->crtcreg];
crtc[crtcreg]=val; 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; fullchange = changeframecount;
svga_recalctimings(); svga_recalctimings(svga);
} }
} }
break; 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; uint8_t temp;
if (addr != 0x3da) pclog("ati28800_in : %04X ", addr); 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) switch (addr)
{ {
case 0x1ce: case 0x1ce:
temp = ati_index; temp = ati28800->index;
break; break;
case 0x1cf: case 0x1cf:
switch (ati_index) switch (ati28800->index)
{ {
case 0xb7: case 0xb7:
temp = ati_regs[ati_index] & ~8; temp = ati28800->regs[ati28800->index] & ~8;
if (ati_eeprom_read()) if (ati_eeprom_read(&ati28800->eeprom))
temp |= 8; temp |= 8;
break; break;
default: default:
temp = ati_regs[ati_index]; temp = ati28800->regs[ati28800->index];
break; break;
} }
break; break;
case 0x3c2: 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; temp = 0;
else else
temp = 0x10; temp = 0x10;
break; break;
case 0x3D4: case 0x3D4:
temp = crtcreg; temp = svga->crtcreg;
break; break;
case 0x3D5: case 0x3D5:
temp = crtc[crtcreg]; temp = svga->crtc[svga->crtcreg];
break; break;
default: default:
temp = svga_in(addr, NULL); temp = svga_in(addr, svga);
break; break;
} }
if (addr != 0x3da) pclog("%02X %04X:%04X\n", temp, CS,pc); if (addr != 0x3da) pclog("%02X %04X:%04X\n", temp, CS,pc);
return temp; return temp;
} }
void ati28800_recalctimings() void ati28800_recalctimings(svga_t *svga)
{ {
ati28800_t *ati28800 = (ati28800_t *)svga->p;
pclog("ati28800_recalctimings\n"); 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"); pclog("8bpp_highres\n");
svga_render = svga_render_8bpp_highres; svga->render = svga_render_8bpp_highres;
svga_rowoffset <<= 1; svga->rowoffset <<= 1;
svga_ma <<= 1; svga->ma <<= 1;
} }
} }
int ati28800_init() void *ati28800_init()
{ {
svga_recalctimings_ex = ati28800_recalctimings; ati28800_t *ati28800 = malloc(sizeof(ati28800_t));
svga_vram_limit = 1 << 19; /*512kb*/ memset(ati28800, 0, sizeof(ati28800_t));
vrammask = 0x7ffff;
svgawbank = svgarbank = 0;
bpp = 8;
svga_miscout = 1;
io_sethandler(0x01ce, 0x0002, ati28800_in, NULL, NULL, ati28800_out, NULL, NULL, NULL); svga_init(&ati28800->svga, ati28800, 1 << 19, /*512kb*/
ati28800_recalctimings,
ati_eeprom_load("ati28800.nvr", 0); ati28800_in, ati28800_out,
NULL);
return svga_init();
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, ati28800_init,
/*IO at 3Cx/3Dx*/ ati28800_close,
ati28800_out, ati28800_speed_changed,
ati28800_in, svga_add_status_info
/*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
}; };

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_svga.h"
#include "vid_ati68860_ramdac.h" #include "vid_ati68860_ramdac.h"
static uint8_t ramdac_regs[16]; void ati68860_ramdac_out(uint16_t addr, uint8_t val, ati68860_ramdac_t *ramdac, svga_t *svga)
void ati68860_ramdac_out(uint16_t addr, uint8_t val, void *priv)
{ {
// pclog("ati68860_out : addr %04X val %02X %04X:%04X\n", addr, val, CS,pc); // pclog("ati68860_out : addr %04X val %02X %04X:%04X\n", addr, val, CS,pc);
switch (addr) switch (addr)
{ {
case 0: case 0:
svga_out(0x3c8, val, NULL); svga_out(0x3c8, val, svga);
break; break;
case 1: case 1:
svga_out(0x3c9, val, NULL); svga_out(0x3c9, val, svga);
break; break;
case 2: case 2:
svga_out(0x3c6, val, NULL); svga_out(0x3c6, val, svga);
break; break;
case 3: case 3:
svga_out(0x3c7, val, NULL); svga_out(0x3c7, val, svga);
break; break;
default: default:
ramdac_regs[addr & 0xf] = val; ramdac->regs[addr & 0xf] = val;
break; 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; uint8_t ret = 0;
switch (addr) switch (addr)
{ {
case 0: case 0:
ret = svga_in(0x3c8, NULL); ret = svga_in(0x3c8, svga);
break; break;
case 1: case 1:
ret = svga_in(0x3c9, NULL); ret = svga_in(0x3c9, svga);
break; break;
case 2: case 2:
ret = svga_in(0x3c6, NULL); ret = svga_in(0x3c6, svga);
break; break;
case 3: case 3:
ret = svga_in(0x3c7, NULL); ret = svga_in(0x3c7, svga);
break; break;
case 4: case 8: case 4: case 8:
ret = 2; ret = 2;
@ -75,7 +74,7 @@ uint8_t ati68860_ramdac_in(uint16_t addr, void *priv)
break; break;
default: default:
ret = ramdac_regs[addr & 0xf]; ret = ramdac->regs[addr & 0xf];
break; break;
} }
// pclog("ati68860_in : addr %04X ret %02X %04X:%04X\n", addr, ret, CS,pc); // 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); typedef struct ati68860_ramdac_t
uint8_t ati68860_ramdac_in(uint16_t addr, void *priv); {
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 "ibm.h"
#include "vid_ati_eeprom.h" #include "vid_ati_eeprom.h"
static uint16_t eeprom[256];
enum enum
{ {
EEPROM_IDLE, EEPROM_IDLE,
@ -29,201 +28,193 @@ enum
EEPROM_OP_EWEN = 3 EEPROM_OP_EWEN = 3
}; };
static int oldclk, oldena; void ati_eeprom_load(ati_eeprom_t *eeprom, char *fn, int type)
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)
{ {
FILE *f; FILE *f;
eeprom_type = type; eeprom->type = type;
strcpy(eeprom_fn, fn); strcpy(eeprom->fn, fn);
f = romfopen(eeprom_fn, "rb"); f = romfopen(eeprom->fn, "rb");
if (!f) if (!f)
{ {
memset(eeprom, 0, type ? 512 : 128); memset(eeprom->data, 0, eeprom->type ? 512 : 128);
return; return;
} }
fread(eeprom, 1, type ? 512 : 128, f); fread(eeprom->data, 1, eeprom->type ? 512 : 128, f);
fclose(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; if (!f) return;
fwrite(eeprom, 1, eeprom_type ? 512 : 128, f); fwrite(eeprom->data, 1, eeprom->type ? 512 : 128, f);
fclose(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; int c;
pclog("EEPROM write %i %i %i\n", ena, clk, dat); pclog("EEPROM write %i %i %i\n", ena, clk, dat);
if (!ena) 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->state = EEPROM_WAIT;
eeprom_opcode = 0; eeprom->opcode = 0;
eeprom_count = 3; eeprom->count = 3;
eeprom_out = 1; eeprom->out = 1;
} }
else if (ena) else if (ena)
{ {
pclog("EEPROM receive %i %i %i\n", ena, clk, dat); pclog("EEPROM receive %i %i %i\n", ena, clk, dat);
switch (eeprom_state) switch (eeprom->state)
{ {
case EEPROM_WAIT: case EEPROM_WAIT:
if (!dat) if (!dat)
break; break;
eeprom_state = EEPROM_OPCODE; eeprom->state = EEPROM_OPCODE;
/* fall through */ /* fall through */
case EEPROM_OPCODE: case EEPROM_OPCODE:
eeprom_opcode = (eeprom_opcode << 1) | (dat ? 1 : 0); eeprom->opcode = (eeprom->opcode << 1) | (dat ? 1 : 0);
eeprom_count--; eeprom->count--;
if (!eeprom_count) if (!eeprom->count)
{ {
pclog("EEPROM opcode - %i\n", eeprom_opcode); pclog("EEPROM opcode - %i\n", eeprom->opcode);
switch (eeprom_opcode) switch (eeprom->opcode)
{ {
case EEPROM_OP_WRITE: case EEPROM_OP_WRITE:
eeprom_count = eeprom_type ? 24 : 22; eeprom->count = eeprom->type ? 24 : 22;
eeprom_state = EEPROM_INPUT; eeprom->state = EEPROM_INPUT;
eeprom_dat = 0; eeprom->dat = 0;
break; break;
case EEPROM_OP_READ: case EEPROM_OP_READ:
eeprom_count = eeprom_type ? 8 : 6; eeprom->count = eeprom->type ? 8 : 6;
eeprom_state = EEPROM_INPUT; eeprom->state = EEPROM_INPUT;
eeprom_dat = 0; eeprom->dat = 0;
break; break;
case EEPROM_OP_EW: case EEPROM_OP_EW:
eeprom_count = 2; eeprom->count = 2;
eeprom_state = EEPROM_INPUT; eeprom->state = EEPROM_INPUT;
eeprom_dat = 0; eeprom->dat = 0;
break; break;
case EEPROM_OP_ERASE: case EEPROM_OP_ERASE:
eeprom_count = eeprom_type ? 8 : 6; eeprom->count = eeprom->type ? 8 : 6;
eeprom_state = EEPROM_INPUT; eeprom->state = EEPROM_INPUT;
eeprom_dat = 0; eeprom->dat = 0;
break; break;
} }
} }
break; break;
case EEPROM_INPUT: case EEPROM_INPUT:
eeprom_dat = (eeprom_dat << 1) | (dat ? 1 : 0); eeprom->dat = (eeprom->dat << 1) | (dat ? 1 : 0);
eeprom_count--; eeprom->count--;
if (!eeprom_count) if (!eeprom->count)
{ {
pclog("EEPROM dat - %02X\n", eeprom_dat); pclog("EEPROM dat - %02X\n", eeprom->dat);
switch (eeprom_opcode) switch (eeprom->opcode)
{ {
case EEPROM_OP_WRITE: case EEPROM_OP_WRITE:
pclog("EEPROM_OP_WRITE addr %02X eeprom_dat %04X\n", (eeprom_dat >> 16) & (eeprom_type ? 255 : 63), eeprom_dat & 0xffff); pclog("EEPROM_OP_WRITE addr %02X eeprom_dat %04X\n", (eeprom->dat >> 16) & (eeprom->type ? 255 : 63), eeprom->dat & 0xffff);
if (!eeprom_wp) if (!eeprom->wp)
{ {
eeprom[(eeprom_dat >> 16) & (eeprom_type ? 255 : 63)] = eeprom_dat & 0xffff; eeprom->data[(eeprom->dat >> 16) & (eeprom->type ? 255 : 63)] = eeprom->dat & 0xffff;
ati_eeprom_save(); ati_eeprom_save(eeprom);
} }
eeprom_state = EEPROM_IDLE; eeprom->state = EEPROM_IDLE;
eeprom_out = 1; eeprom->out = 1;
break; break;
case EEPROM_OP_READ: case EEPROM_OP_READ:
eeprom_count = 17; eeprom->count = 17;
eeprom_state = EEPROM_OUTPUT; eeprom->state = EEPROM_OUTPUT;
eeprom_dat = eeprom[eeprom_dat]; eeprom->dat = eeprom->data[eeprom->dat];
pclog("Trigger EEPROM_OUTPUT %04X\n", eeprom_dat); pclog("Trigger EEPROM_OUTPUT %04X\n", eeprom->dat);
break; break;
case EEPROM_OP_EW: case EEPROM_OP_EW:
pclog("EEPROM_OP_EW %i\n", eeprom_dat); pclog("EEPROM_OP_EW %i\n", eeprom->dat);
switch (eeprom_dat) switch (eeprom->dat)
{ {
case EEPROM_OP_EWDS: case EEPROM_OP_EWDS:
eeprom_wp = 1; eeprom->wp = 1;
break; break;
case EEPROM_OP_WRAL: case EEPROM_OP_WRAL:
opcode = EEPROM_OP_WRALMAIN; eeprom->opcode = EEPROM_OP_WRALMAIN;
eeprom_count = 20; eeprom->count = 20;
break; break;
case EEPROM_OP_ERAL: case EEPROM_OP_ERAL:
if (!eeprom_wp) if (!eeprom->wp)
{ {
memset(eeprom, 0xff, 128); memset(eeprom->data, 0xff, 128);
ati_eeprom_save(); ati_eeprom_save(eeprom);
} }
break; break;
case EEPROM_OP_EWEN: case EEPROM_OP_EWEN:
eeprom_wp = 0; eeprom->wp = 0;
break; break;
} }
eeprom_state = EEPROM_IDLE; eeprom->state = EEPROM_IDLE;
eeprom_out = 1; eeprom->out = 1;
break; break;
case EEPROM_OP_ERASE: case EEPROM_OP_ERASE:
pclog("EEPROM_OP_ERASE %i\n", eeprom_dat); pclog("EEPROM_OP_ERASE %i\n", eeprom->dat);
if (!eeprom_wp) if (!eeprom->wp)
{ {
eeprom[eeprom_dat] = 0xffff; eeprom->data[eeprom->dat] = 0xffff;
ati_eeprom_save(); ati_eeprom_save(eeprom);
} }
eeprom_state = EEPROM_IDLE; eeprom->state = EEPROM_IDLE;
eeprom_out = 1; eeprom->out = 1;
break; break;
case EEPROM_OP_WRALMAIN: case EEPROM_OP_WRALMAIN:
pclog("EEPROM_OP_WRAL %04X\n", eeprom_dat); pclog("EEPROM_OP_WRAL %04X\n", eeprom->dat);
if (!eeprom_wp) if (!eeprom->wp)
{ {
for (c = 0; c < 256; c++) for (c = 0; c < 256; c++)
eeprom[c] = eeprom_dat; eeprom->data[c] = eeprom->dat;
ati_eeprom_save(); ati_eeprom_save(eeprom);
} }
eeprom_state = EEPROM_IDLE; eeprom->state = EEPROM_IDLE;
eeprom_out = 1; eeprom->out = 1;
break; break;
} }
} }
break; break;
} }
} }
oldena = ena; eeprom->oldena = ena;
} }
else if (!clk && oldclk) else if (!clk && eeprom->oldclk)
{ {
if (ena) if (ena)
{ {
switch (eeprom_state) switch (eeprom->state)
{ {
case EEPROM_OUTPUT: case EEPROM_OUTPUT:
eeprom_out = (eeprom_dat & 0x10000) ? 1 : 0; eeprom->out = (eeprom->dat & 0x10000) ? 1 : 0;
eeprom_dat <<= 1; eeprom->dat <<= 1;
pclog("EEPROM_OUTPUT - data %i\n", eeprom_out); pclog("EEPROM_OUTPUT - data %i\n", eeprom->out);
eeprom_count--; eeprom->count--;
if (!eeprom_count) if (!eeprom->count)
{ {
pclog("EEPROM_OUTPUT complete\n"); pclog("EEPROM_OUTPUT complete\n");
eeprom_state = EEPROM_IDLE; eeprom->state = EEPROM_IDLE;
} }
break; 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); typedef struct ati_eeprom_t
void ati_eeprom_write(int ena, int clk, int dat); {
int ati_eeprom_read(); 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*/ /*CGA emulation*/
#include <stdlib.h>
#include <math.h> #include <math.h>
#include "ibm.h" #include "ibm.h"
#include "device.h"
#include "io.h" #include "io.h"
#include "mem.h" #include "mem.h"
#include "timer.h" #include "timer.h"
#include "video.h" #include "video.h"
#include "vid_cga.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; uint8_t old;
// pclog("CGA_OUT %04X %02X\n", addr, val); // pclog("CGA_OUT %04X %02X\n", addr, val);
switch (addr) switch (addr)
{ {
case 0x3D4: case 0x3D4:
crtcreg=val&31; cga->crtcreg = val & 31;
return; return;
case 0x3D5: case 0x3D5:
old=crtc[crtcreg]; old = cga->crtc[cga->crtcreg];
crtc[crtcreg]=val&crtcmask[crtcreg]; cga->crtc[cga->crtcreg] = val & crtcmask[cga->crtcreg];
if (old!=val) if (old != val)
{ {
if (crtcreg<0xE || crtcreg>0x10) if (cga->crtcreg < 0xe || cga->crtcreg > 0x10)
{ {
fullchange=changeframecount; fullchange = changeframecount;
cga_recalctimings(); cga_recalctimings(cga);
} }
} }
return; return;
case 0x3D8: case 0x3D8:
cgamode=val; cga->cgamode = val;
return; return;
case 0x3D9: case 0x3D9:
cgacol=val; cga->cgacol = val;
return; 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); // pclog("CGA_IN %04X\n", addr);
switch (addr) switch (addr)
{ {
case 0x3D4: case 0x3D4:
return crtcreg; return cga->crtcreg;
case 0x3D5: case 0x3D5:
return crtc[crtcreg]; return cga->crtc[cga->crtcreg];
case 0x3DA: case 0x3DA:
return cgastat; return cga->cgastat;
} }
return 0xFF; return 0xFF;
} }
extern uint8_t charbuffer[256]; void cga_write(uint32_t addr, uint8_t val, void *p)
void cga_write(uint32_t addr, uint8_t val, void *priv)
{ {
cga_t *cga = (cga_t *)p;
// pclog("CGA_WRITE %04X %02X\n", addr, val); // pclog("CGA_WRITE %04X %02X\n", addr, val);
vram[addr&0x3FFF]=val; cga->vram[addr & 0x3fff] = val;
charbuffer[ ((int)(((dispontime - vidtime) * 2) / CGACONST)) & 0xfc] = val; cga->charbuffer[ ((int)(((cga->dispontime - cga->vidtime) * 2) / CGACONST)) & 0xfc] = val;
charbuffer[(((int)(((dispontime - vidtime) * 2) / CGACONST)) & 0xfc) | 1] = val; cga->charbuffer[(((int)(((cga->dispontime - cga->vidtime) * 2) / CGACONST)) & 0xfc) | 1] = val;
cycles -= 4; 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; cycles -= 4;
charbuffer[ ((int)(((dispontime - vidtime) * 2) / CGACONST)) & 0xfc] = vram[addr&0x3FFF]; cga->charbuffer[ ((int)(((cga->dispontime - cga->vidtime) * 2) / CGACONST)) & 0xfc] = cga->vram[addr & 0x3fff];
charbuffer[(((int)(((dispontime - vidtime) * 2) / CGACONST)) & 0xfc) | 1] = vram[addr&0x3FFF]; cga->charbuffer[(((int)(((cga->dispontime - cga->vidtime) * 2) / CGACONST)) & 0xfc) | 1] = cga->vram[addr & 0x3fff];
// pclog("CGA_READ %04X\n", addr); // 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; double _dispontime, _dispofftime;
pclog("Recalc - %i %i %i\n", crtc[0], crtc[1], cgamode & 1); pclog("Recalc - %i %i %i\n", cga->crtc[0], cga->crtc[1], cga->cgamode & 1);
if (cgamode&1) if (cga->cgamode & 1)
{ {
disptime=crtc[0]+1; disptime = cga->crtc[0] + 1;
_dispontime=crtc[1]; _dispontime = cga->crtc[1];
} }
else else
{ {
disptime=(crtc[0]+1)<<1; disptime = (cga->crtc[0] + 1) << 1;
_dispontime=crtc[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]); // printf("%i %f %f %f %i %i\n",cgamode&1,disptime,dispontime,dispofftime,crtc[0],crtc[1]);
_dispontime*=CGACONST; _dispontime *= CGACONST;
_dispofftime*=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); // 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)); cga->dispontime = (int)(_dispontime * (1 << TIMER_SHIFT));
dispofftime = (int)(_dispofftime * (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]= static int ntsc_col[8][8]=
{ {
{0,0,0,0,0,0,0,0}, /*Black*/ {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*/ {1,1,1,1,1,1,1,1} /*White*/
}; };
int i_filt[8],q_filt[8]; void cga_poll(void *p)
void cga_poll()
{ {
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 drawcursor;
int x,c; int x, c;
int oldvc; int oldvc;
uint8_t chr,attr; uint8_t chr, attr;
uint16_t dat; uint16_t dat;
int cols[4]; int cols[4];
int col; int col;
int oldsc; int oldsc;
int y_buf[8]={0,0,0,0,0,0,0,0},y_val,y_tot; 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 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 q_buf[8] = {0, 0, 0, 0, 0, 0, 0, 0}, q_val, q_tot;
int r,g,b; int r, g, b;
if (!linepos) if (!cga->linepos)
{ {
vidtime+=dispofftime; cga->vidtime += cga->dispofftime;
cgastat|=1; cga->cgastat |= 1;
linepos=1; cga->linepos = 1;
oldsc=sc; oldsc = cga->sc;
if ((crtc[8] & 3) == 3) if ((cga->crtc[8] & 3) == 3)
sc = ((sc << 1) + oddeven) & 7; cga->sc = ((cga->sc << 1) + cga->oddeven) & 7;
if (cgadispon) if (cga->cgadispon)
{ {
if (displine<firstline) if (cga->displine < cga->firstline)
{ {
firstline=displine; cga->firstline = cga->displine;
// printf("Firstline %i\n",firstline); // printf("Firstline %i\n",firstline);
} }
lastline=displine; cga->lastline = cga->displine;
for (c=0;c<8;c++) for (c = 0; c < 8; c++)
{ {
if ((cgamode&0x12)==0x12) if ((cga->cgamode & 0x12) == 0x12)
{ {
buffer->line[displine][c]=0; buffer->line[cga->displine][c] = 0;
if (cgamode&1) buffer->line[displine][c+(crtc[1]<<3)+8]=0; if (cga->cgamode & 1) buffer->line[cga->displine][c + (cga->crtc[1] << 3) + 8] = 0;
else buffer->line[displine][c+(crtc[1]<<4)+8]=0; else buffer->line[cga->displine][c + (cga->crtc[1] << 4) + 8] = 0;
} }
else else
{ {
buffer->line[displine][c]=(cgacol&15)+16; buffer->line[cga->displine][c] = (cga->cgacol & 15) + 16;
if (cgamode&1) buffer->line[displine][c+(crtc[1]<<3)+8]=(cgacol&15)+16; if (cga->cgamode & 1) buffer->line[cga->displine][c + (cga->crtc[1] << 3) + 8] = (cga->cgacol & 15) + 16;
else buffer->line[displine][c+(crtc[1]<<4)+8]=(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]; chr = cga->charbuffer[x << 1];
attr=charbuffer[(x<<1)+1]; attr = cga->charbuffer[(x << 1) + 1];
drawcursor=((ma==ca) && con && cursoron); drawcursor = ((cga->ma == ca) && cga->con && cga->cursoron);
if (cgamode&0x20) if (cga->cgamode & 0x20)
{ {
cols[1]=(attr&15)+16; cols[1] = (attr & 15) + 16;
cols[0]=((attr>>4)&7)+16; cols[0] = ((attr >> 4) & 7) + 16;
if ((cgablink&8) && (attr&0x80) && !drawcursor) cols[1]=cols[0]; if ((cga->cgablink & 8) && (attr & 0x80) && !cga->drawcursor)
cols[1] = cols[0];
} }
else else
{ {
cols[1]=(attr&15)+16; cols[1] = (attr & 15) + 16;
cols[0]=(attr>>4)+16; cols[0] = (attr >> 4) + 16;
} }
if (drawcursor) if (drawcursor)
{ {
for (c=0;c<8;c++) for (c = 0; c < 8; c++)
buffer->line[displine][(x<<3)+c+8]=cols[(fontdat[chr][sc&7]&(1<<(c^7)))?1:0]^15; buffer->line[cga->displine][(x << 3) + c + 8] = cols[(fontdat[chr][cga->sc & 7] & (1 << (c ^ 7))) ? 1 : 0] ^ 15;
} }
else else
{ {
for (c=0;c<8;c++) for (c = 0; c < 8; c++)
buffer->line[displine][(x<<3)+c+8]=cols[(fontdat[chr][sc&7]&(1<<(c^7)))?1:0]; 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)]; chr = cga->vram[((cga->ma << 1) & 0x3fff)];
attr=vram[(((ma<<1)+1)&0x3FFF)]; attr = cga->vram[(((cga->ma << 1) + 1) & 0x3fff)];
drawcursor=((ma==ca) && con && cursoron); drawcursor = ((cga->ma == ca) && cga->con && cga->cursoron);
if (cgamode&0x20) if (cga->cgamode & 0x20)
{ {
cols[1]=(attr&15)+16; cols[1] = (attr & 15) + 16;
cols[0]=((attr>>4)&7)+16; cols[0] = ((attr >> 4) & 7) + 16;
if ((cgablink&8) && (attr&0x80)) cols[1]=cols[0]; if ((cga->cgablink & 8) && (attr & 0x80)) cols[1] = cols[0];
} }
else else
{ {
cols[1]=(attr&15)+16; cols[1] = (attr & 15) + 16;
cols[0]=(attr>>4)+16; cols[0] = (attr >> 4) + 16;
} }
ma++; cga->ma++;
if (drawcursor) if (drawcursor)
{ {
for (c=0;c<8;c++) 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; 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 else
{ {
for (c=0;c<8;c++) 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]; 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; cols[0] = (cga->cgacol & 15) | 16;
col=(cgacol&16)?24:16; col = (cga->cgacol & 16) ? 24 : 16;
if (cgamode&4) if (cga->cgamode & 4)
{ {
cols[1]=col|3; cols[1] = col | 3;
cols[2]=col|4; cols[2] = col | 4;
cols[3]=col|7; cols[3] = col | 7;
} }
else if (cgacol&32) else if (cga->cgacol & 32)
{ {
cols[1]=col|3; cols[1] = col | 3;
cols[2]=col|5; cols[2] = col | 5;
cols[3]=col|7; cols[3] = col | 7;
} }
else else
{ {
cols[1]=col|2; cols[1] = col | 2;
cols[2]=col|4; cols[2] = col | 4;
cols[3]=col|6; 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]; dat = (cga->vram[((cga->ma << 1) & 0x1fff) + ((cga->sc & 1) * 0x2000)] << 8) | cga->vram[((cga->ma << 1) & 0x1fff) + ((cga->sc & 1) * 0x2000) + 1];
ma++; cga->ma++;
for (c=0;c<8;c++) for (c = 0; c < 8; c++)
{ {
buffer->line[displine][(x<<4)+(c<<1)+8]= buffer->line[cga->displine][(x << 4) + (c << 1) + 8] =
buffer->line[displine][(x<<4)+(c<<1)+1+8]=cols[dat>>14]; buffer->line[cga->displine][(x << 4) + (c << 1) + 1 + 8] = cols[dat >> 14];
dat<<=2; dat <<= 2;
} }
} }
} }
else else
{ {
cols[0]=0; cols[1]=(cgacol&15)+16; cols[0] = 0; cols[1] = (cga->cgacol & 15) + 16;
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]; dat = (cga->vram[((cga->ma << 1) & 0x1fff) + ((cga->sc & 1) * 0x2000)] << 8) | cga->vram[((cga->ma << 1) & 0x1fff) + ((cga->sc & 1) * 0x2000) + 1];
ma++; cga->ma++;
for (c=0;c<16;c++) for (c = 0; c < 16; c++)
{ {
buffer->line[displine][(x<<4)+c+8]=cols[dat>>15]; buffer->line[cga->displine][(x << 4) + c + 8] = cols[dat >> 15];
dat<<=1; dat <<= 1;
} }
} }
} }
} }
else else
{ {
cols[0]=((cgamode&0x12)==0x12)?0:(cgacol&15)+16; cols[0] = ((cga->cgamode & 0x12) == 0x12) ? 0 : (cga->cgacol & 15) + 16;
if (cgamode&1) hline(buffer,0,displine,(crtc[1]<<3)+16,cols[0]); if (cga->cgamode & 1) hline(buffer, 0, cga->displine, (cga->crtc[1] << 3) + 16, cols[0]);
else hline(buffer,0,displine,(crtc[1]<<4)+16,cols[0]); else hline(buffer, 0, cga->displine, (cga->crtc[1] << 4) + 16, cols[0]);
} }
if (cgamode&1) x=(crtc[1]<<3)+16; if (cga->cgamode & 1) x = (cga->crtc[1] << 3) + 16;
else x=(crtc[1]<<4)+16; else x = (cga->crtc[1] << 4) + 16;
if (cga_comp) 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] = ntsc_col[buffer->line[cga->displine][c] & 7][(c << 1) & 6] ? 0x6000 : 0;
y_buf[(c<<1)&6]+=(buffer->line[displine][c]&8)?0x3000: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]; 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]; 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]; 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]; 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]; 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; y_val = y_tot >> 10;
if (y_val>255) y_val=255; if (y_val > 255) y_val = 255;
y_val<<=16; y_val <<= 16;
i_val=i_tot>>12; i_val = i_tot >> 12;
if (i_val>39041) i_val=39041; if (i_val > 39041) i_val = 39041;
if (i_val<-39041) i_val=-39041; if (i_val < -39041) i_val = -39041;
q_val=q_tot>>12; q_val = q_tot >> 12;
if (q_val>34249) q_val=34249; if (q_val > 34249) q_val = 34249;
if (q_val<-34249) q_val=-34249; if (q_val < -34249) q_val = -34249;
r=(y_val+249*i_val+159*q_val)>>16; r = (y_val + 249*i_val + 159*q_val) >> 16;
g=(y_val-70*i_val-166*q_val)>>16; g = (y_val - 70*i_val - 166*q_val) >> 16;
b=(y_val-283*i_val+436*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] = ntsc_col[buffer->line[cga->displine][c] & 7][((c << 1) & 6) + 1] ? 0x6000 : 0;
y_buf[((c<<1)&6)+1]+=(buffer->line[displine][c]&8)?0x3000: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]; 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]; 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]; 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]; 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]; 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; y_val = y_tot >> 10;
if (y_val>255) y_val=255; if (y_val > 255) y_val = 255;
y_val<<=16; y_val <<= 16;
i_val=i_tot>>12; i_val = i_tot >> 12;
if (i_val>39041) i_val=39041; if (i_val > 39041) i_val = 39041;
if (i_val<-39041) i_val=-39041; if (i_val < -39041) i_val = -39041;
q_val=q_tot>>12; q_val = q_tot >> 12;
if (q_val>34249) q_val=34249; if (q_val > 34249) q_val = 34249;
if (q_val<-34249) q_val=-34249; if (q_val < -34249) q_val = -34249;
r+=(y_val+249*i_val+159*q_val)>>16; r = (y_val + 249*i_val + 159*q_val) >> 16;
g+=(y_val-70*i_val-166*q_val)>>16; g = (y_val - 70*i_val - 166*q_val) >> 16;
b+=(y_val-283*i_val+436*q_val)>>16; b = (y_val - 283*i_val + 436*q_val) >> 16;
if (r>511) r=511; if (r > 511) r = 511;
if (g>511) g=511; if (g > 511) g = 511;
if (b>511) b=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; cga->sc = oldsc;
if (vc==crtc[7] && !sc) if (cga->vc == cga->crtc[7] && !cga->sc)
cgastat|=8; cga->cgastat |= 8;
displine++; cga->displine++;
if (displine>=360) displine=0; if (cga->displine >= 360)
cga->displine = 0;
} }
else else
{ {
vidtime+=dispontime; cga->vidtime += cga->dispontime;
if (cgadispon) cgastat&=~1; if (cga->cgadispon) cga->cgastat &= ~1;
linepos=0; cga->linepos = 0;
if (vsynctime) if (cga->vsynctime)
{ {
vsynctime--; cga->vsynctime--;
if (!vsynctime) if (!cga->vsynctime)
cgastat&=~8; cga->cgastat &= ~8;
} }
if (sc==(crtc[11]&31) || ((crtc[8]&3)==3 && sc==((crtc[11]&31)>>1))) { con=0; coff=1; } if (cga->sc == (cga->crtc[11] & 31) || ((cga->crtc[8] & 3) == 3 && cga->sc == ((cga->crtc[11] & 31) >> 1)))
if ((crtc[8] & 3) == 3 && sc == (crtc[9] >> 1)) {
maback = ma; cga->con = 0;
if (vadj) cga->coff = 1;
}
if ((cga->crtc[8] & 3) == 3 && cga->sc == (cga->crtc[9] >> 1))
cga->maback = cga->ma;
if (cga->vadj)
{ {
sc++; cga->sc++;
sc&=31; cga->sc &= 31;
ma=maback; cga->ma = cga->maback;
vadj--; cga->vadj--;
if (!vadj) if (!cga->vadj)
{ {
cgadispon=1; cga->cgadispon = 1;
ma=maback=(crtc[13]|(crtc[12]<<8))&0x3FFF; cga->ma = cga->maback = (cga->crtc[13] | (cga->crtc[12] << 8)) & 0x3fff;
sc=0; cga->sc = 0;
} }
} }
else if (sc==crtc[9]) else if (cga->sc == cga->crtc[9])
{ {
maback=ma; cga->maback = cga->ma;
sc=0; cga->sc = 0;
oldvc=vc; oldvc = cga->vc;
vc++; cga->vc++;
vc&=127; 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; cga->vc = 0;
vadj=crtc[5]; cga->vadj = cga->crtc[5];
if (!vadj) cgadispon=1; if (!cga->vadj) cga->cgadispon = 1;
if (!vadj) ma=maback=(crtc[13]|(crtc[12]<<8))&0x3FFF; if (!cga->vadj) cga->ma = cga->maback = (cga->crtc[13] | (cga->crtc[12] << 8)) & 0x3fff;
if ((crtc[10]&0x60)==0x20) cursoron=0; if ((cga->crtc[10] & 0x60) == 0x20) cga->cursoron = 0;
else cursoron=cgablink&8; else cga->cursoron = cga->cgablink & 8;
} }
if (vc==crtc[7]) if (cga->vc == cga->crtc[7])
{ {
cgadispon=0; cga->cgadispon = 0;
displine=0; cga->displine = 0;
vsynctime=(crtc[3]>>4)+1; cga->vsynctime = (cga->crtc[3] >> 4) + 1;
if (crtc[7]) if (cga->crtc[7])
{ {
if (cgamode&1) x=(crtc[1]<<3)+16; if (cga->cgamode & 1) x = (cga->crtc[1] << 3) + 16;
else x=(crtc[1]<<4)+16; else x = (cga->crtc[1] << 4) + 16;
lastline++; cga->lastline++;
if (x!=xsize || (lastline-firstline)!=ysize) if (x != xsize || (cga->lastline - cga->firstline) != ysize)
{ {
xsize=x; xsize = x;
ysize=lastline-firstline; ysize = cga->lastline - cga->firstline;
if (xsize<64) xsize=656; if (xsize < 64) xsize = 656;
if (ysize<32) ysize=200; if (ysize < 32) ysize = 200;
updatewindowsize(xsize,(ysize<<1)+16); updatewindowsize(xsize, (ysize << 1) + 16);
} }
startblit(); startblit();
if (cga_comp) 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 else
video_blit_memtoscreen_8(0, firstline-4, xsize, (lastline-firstline)+8); 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); if (readflash) rectfill(screen, winsizex - 40, 8, winsizex - 8, 14, 0xffffffff);
readflash=0; readflash = 0;
frames++; frames++;
endblit(); endblit();
video_res_x = xsize - 16; video_res_x = xsize - 16;
video_res_y = ysize; video_res_y = ysize;
if (cgamode & 1) if (cga->cgamode & 1)
{ {
video_res_x /= 8; video_res_x /= 8;
video_res_y /= crtc[9] + 1; video_res_y /= cga->crtc[9] + 1;
video_bpp = 0; video_bpp = 0;
} }
else if (!(cgamode & 2)) else if (!(cga->cgamode & 2))
{ {
video_res_x /= 16; video_res_x /= 16;
video_res_y /= crtc[9] + 1; video_res_y /= cga->crtc[9] + 1;
video_bpp = 0; video_bpp = 0;
} }
else if (!(cgamode&16)) else if (!(cga->cgamode & 16))
{ {
video_res_x /= 2; video_res_x /= 2;
video_bpp = 2; video_bpp = 2;
@ -446,59 +456,72 @@ endblit();
video_bpp = 1; video_bpp = 1;
} }
} }
firstline=1000; cga->firstline = 1000;
lastline=0; cga->lastline = 0;
cgablink++; cga->cgablink++;
oddeven ^= 1; cga->oddeven ^= 1;
} }
} }
else else
{ {
sc++; cga->sc++;
sc&=31; cga->sc &= 31;
ma=maback; cga->ma = cga->maback;
} }
if ((sc==(crtc[10]&31) || ((crtc[8]&3)==3 && sc==((crtc[10]&31)>>1)))) con=1; if ((cga->sc == (cga->crtc[10] & 31) || ((cga->crtc[8] & 3) == 3 && cga->sc == ((cga->crtc[10] & 31) >> 1))))
if (cgadispon && (cgamode&1)) cga->con = 1;
if (cga->cgadispon && (cga->cgamode & 1))
{ {
for (x=0;x<(crtc[1]<<1);x++) for (x = 0; x < (cga->crtc[1] << 1); x++)
charbuffer[x]=vram[(((ma<<1)+x)&0x3FFF)]; 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 c;
int cga_tint = -2; 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); 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); 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); timer_add(cga_poll, &cga->vidtime, TIMER_ALWAYS_ENABLED, cga);
return 0; 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, cga_t *cga = (cga_t *)p;
/*IO at 3Cx/3Dx*/
cga_out,
cga_in,
/*IO at 3Ax/3Bx*/
video_out_null,
video_in_null,
cga_poll, free(cga->vram);
cga_recalctimings, free(cga);
}
video_write_null, void cga_speed_changed(void *p)
video_write_null, {
cga_write, cga_t *cga = (cga_t *)p;
cga_recalctimings(cga);
}
video_read_null, device_t cga_device =
video_read_null, {
cga_read "CGA",
cga_standalone_init,
cga_close,
cga_speed_changed,
NULL
}; };

View file

@ -1,7 +1,38 @@
int cga_init(); typedef struct cga_t
void cga_out(uint16_t addr, uint8_t val, void *priv); {
uint8_t cga_in(uint16_t addr, void *priv); int crtcreg;
void cga_poll(); uint8_t crtc[32];
void cga_write(uint32_t addr, uint8_t val, void *priv);
uint8_t cga_read(uint32_t addr, void *priv); uint8_t cgastat;
void cga_recalctimings();
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(); typedef struct ega_t
void ega_out(uint16_t addr, uint8_t val, void *priv); {
uint8_t ega_in(uint16_t addr, void *priv); uint8_t crtcreg;
void ega_poll(); uint8_t crtc[32];
void ega_recalctimings(); uint8_t gdcreg[16];
void ega_write(uint32_t addr, uint8_t val, void *priv); int gdcaddr;
uint8_t ega_read(uint32_t addr, void *priv); 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*/ /*ET4000 emulation*/
#include <stdlib.h>
#include "ibm.h" #include "ibm.h"
#include "device.h"
#include "io.h" #include "io.h"
#include "video.h" #include "video.h"
#include "vid_svga.h" #include "vid_svga.h"
#include "vid_unk_ramdac.h" #include "vid_unk_ramdac.h"
int et4k_b8000; #include "vid_et4000.h"
typedef struct et4000_t
void et4000_out(uint16_t addr, uint8_t val, void *priv)
{ {
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; 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); pclog("ET4000 out %04X %02X\n", addr, val);
switch (addr) switch (addr)
{ {
case 0x3C6: case 0x3C7: case 0x3C8: case 0x3C9: case 0x3C6: case 0x3C7: case 0x3C8: case 0x3C9:
unk_ramdac_out(addr, val, NULL); unk_ramdac_out(addr, val, &et4000->ramdac, svga);
return; return;
case 0x3CD: /*Banking*/ case 0x3CD: /*Banking*/
svgawbank=(val&0xF)*65536; svga->write_bank = (val & 0xf) * 0x10000;
svgarbank=((val>>4)&0xF)*65536; svga->read_bank = ((val >> 4) & 0xf) * 0x10000;
svgaseg=val; et4000->banking = val;
pclog("Banking write %08X %08X %02X\n", svgawbank, svgarbank, val); pclog("Banking write %08X %08X %02X\n", svga->write_bank, svga->read_bank, val);
return; return;
case 0x3CF:
switch (gdcaddr&15)
{
case 6:
et4k_b8000=((crtc[0x36]&0x38)==0x28) && ((gdcreg[6]&0xC)==4);
break;
}
break;
case 0x3D4: case 0x3D4:
crtcreg = val & 0x3f; svga->crtcreg = val & 0x3f;
return; return;
case 0x3D5: case 0x3D5:
if (crtcreg <= 7 && crtc[0x11] & 0x80) return; if (svga->crtcreg <= 7 && svga->crtc[0x11] & 0x80) return;
old=crtc[crtcreg]; old = svga->crtc[svga->crtcreg];
crtc[crtcreg]=val; svga->crtc[svga->crtcreg] = val;
et4k_b8000=((crtc[0x36]&0x38)==0x28) && ((gdcreg[6]&0xC)==4); if (old != val)
if (old!=val)
{ {
if (crtcreg<0xE || crtcreg>0x10) if (svga->crtcreg < 0xE || svga->crtcreg > 0x10)
{ {
fullchange=changeframecount; fullchange = changeframecount;
svga_recalctimings(); svga_recalctimings(svga);
} }
} }
break; 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); if (addr != 0x3da) pclog("IN ET4000 %04X\n", addr);
switch (addr) switch (addr)
{ {
case 0x3C5: case 0x3C5:
if ((seqaddr&0xF)==7) return seqregs[seqaddr&0xF]|4; if ((svga->seqaddr & 0xf) == 7) return svga->seqregs[svga->seqaddr & 0xf] | 4;
break; break;
case 0x3C6: case 0x3C7: case 0x3C8: case 0x3C9: 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*/ case 0x3CD: /*Banking*/
return svgaseg; return et4000->banking;
case 0x3D4: case 0x3D4:
return crtcreg; return svga->crtcreg;
case 0x3D5: 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; et4000_t *et4000 = (et4000_t *)svga->p;
if (crtc[0x35]&2) svga_vtotal+=0x400;
if (crtc[0x35]&4) svga_dispend+=0x400; svga->ma_latch |= (svga->crtc[0x33]&3)<<16;
if (crtc[0x35]&8) svga_vsyncstart+=0x400; if (svga->crtc[0x35] & 2) svga->vtotal += 0x400;
if (crtc[0x35]&0x10) svga_split+=0x400; if (svga->crtc[0x35] & 4) svga->dispend += 0x400;
if (!svga_rowoffset) svga_rowoffset=0x100; if (svga->crtc[0x35] & 8) svga->vsyncstart += 0x400;
// if (crtc[0x3F]&0x80) svga_rowoffset+=0x100; if (svga->crtc[0x35] & 0x10) svga->split += 0x400;
if (crtc[0x3F]&1) svga_htotal+=256; if (!svga->rowoffset) svga->rowoffset = 0x100;
if (attrregs[0x16]&0x20) svga_hdisp<<=1; if (svga->crtc[0x3f] & 1) svga->htotal += 256;
if (svga->attrregs[0x16] & 0x20) svga->hdisp <<= 1;
// pclog("Rowoffset %i\n",svga_rowoffset); // 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 0: case 1: break;
case 3: svga_clock = cpuclock/40000000.0; break; case 3: svga->clock = cpuclock / 40000000.0; break;
case 5: svga_clock = cpuclock/65000000.0; break; case 5: svga->clock = cpuclock / 65000000.0; break;
default: svga_clock = cpuclock/36000000.0; break; default: svga->clock = cpuclock / 36000000.0; break;
} }
} }
int et4000_init() void *et4000_init()
{ {
svga_recalctimings_ex = et4000_recalctimings; et4000_t *et4000 = malloc(sizeof(et4000_t));
svga_vram_limit = 1 << 20; /*1mb*/ memset(et4000, 0, sizeof(et4000_t));
vrammask = 0xfffff;
return svga_init(); 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, et4000_init,
/*IO at 3Cx/3Dx*/ et4000_close,
et4000_out, et4000_speed_changed,
et4000_in, svga_add_status_info
/*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
}; };

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

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

View file

@ -1,2 +1,14 @@
void icd2061_write(int val); typedef struct icd2061_t
double icd2061_getfreq(int i); {
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 enum
{ {
ICS2595_IDLE, ICS2595_IDLE = 0,
ICS2595_WRITE, ICS2595_WRITE,
ICS2595_READ 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 int ics2595_div[4] = {8, 4, 2, 1};
static double ics2595_clocks[16]; void ics2595_write(ics2595_t *ics2595, int strobe, int dat)
double ics2595_output_clock;
void ics2595_write(int strobe, int dat)
{ {
pclog("ics2595_write : %i %i\n", strobe, dat); pclog("ics2595_write : %i %i\n", strobe, dat);
if (strobe) if (strobe)
{ {
if ((dat & 8) && !ics2595_oldfs3) /*Data clock*/ if ((dat & 8) && !ics2595->oldfs3) /*Data clock*/
{ {
pclog(" - new dat %i\n", dat & 4); pclog(" - new dat %i\n", dat & 4);
switch (ics2595_state) switch (ics2595->state)
{ {
case ICS2595_IDLE: case ICS2595_IDLE:
ics2595_state = (dat & 4) ? ICS2595_WRITE : ICS2595_IDLE; ics2595->state = (dat & 4) ? ICS2595_WRITE : ICS2595_IDLE;
ics2595_pos = 0; ics2595->pos = 0;
break; break;
case ICS2595_WRITE: case ICS2595_WRITE:
ics2595_dat = (ics2595_dat >> 1); ics2595->dat = (ics2595->dat >> 1);
if (dat & 4) if (dat & 4)
ics2595_dat |= (1 << 19); ics2595->dat |= (1 << 19);
ics2595_pos++; ics2595->pos++;
if (ics2595_pos == 20) if (ics2595->pos == 20)
{ {
int d, n, l; int d, n, l;
pclog("ICS2595_WRITE : dat %08X\n", ics2595_dat); pclog("ICS2595_WRITE : dat %08X\n", ics2595->dat);
l = (ics2595_dat >> 2) & 31; l = (ics2595->dat >> 2) & 0xf;
n = ((ics2595_dat >> 7) & 255) + 257; n = ((ics2595->dat >> 7) & 255) + 257;
d = ics2595_div[(ics2595_dat >> 16) & 3]; 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); 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; break;
} }
} }
ics2595_oldfs2 = dat & 4; ics2595->oldfs2 = dat & 4;
ics2595_oldfs3 = dat & 8; 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); typedef struct ics2595_t
extern double ics2595_output_clock; {
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*/ /*MDA emulation*/
#include <stdlib.h>
#include "ibm.h" #include "ibm.h"
#include "device.h"
#include "io.h" #include "io.h"
#include "mem.h" #include "mem.h"
#include "timer.h" #include "timer.h"
#include "video.h" #include "video.h"
#include "vid_mda.h"
void mda_recalctimings(); typedef struct mda_t
static uint8_t mda_ctrl,mda_stat;
uint8_t crtcm[32],crtcmreg;
void mda_out(uint16_t addr, uint8_t val, void *priv)
{ {
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) switch (addr)
{ {
case 0x3B0: case 0x3B2: case 0x3B4: case 0x3B6: case 0x3b0: case 0x3b2: case 0x3b4: case 0x3b6:
crtcmreg = val & 31; mda->crtcreg = val & 31;
return; return;
case 0x3B1: case 0x3B3: case 0x3B5: case 0x3B7: case 0x3b1: case 0x3b3: case 0x3b5: case 0x3b7:
crtcm[crtcmreg] = val; mda->crtc[mda->crtcreg] = val;
if (crtcm[10]==6 && crtcm[11]==7) /*Fix for Generic Turbo XT BIOS, which sets up cursor registers wrong*/ if (mda->crtc[10] == 6 && mda->crtc[11] == 7) /*Fix for Generic Turbo XT BIOS, which sets up cursor registers wrong*/
{ {
crtcm[10]=0xB; mda->crtc[10] = 0xb;
crtcm[11]=0xC; mda->crtc[11] = 0xc;
} }
mda_recalctimings(); mda_recalctimings(mda);
return; return;
case 0x3B8: case 0x3b8:
mda_ctrl = val; mda->ctrl = val;
return; 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) switch (addr)
{ {
case 0x3B0: case 0x3B2: case 0x3B4: case 0x3B6: case 0x3b0: case 0x3b2: case 0x3b4: case 0x3b6:
return crtcmreg; return mda->crtcreg;
case 0x3B1: case 0x3B3: case 0x3B5: case 0x3B7: case 0x3b1: case 0x3b3: case 0x3b5: case 0x3b7:
return crtcm[crtcmreg]; return mda->crtc[mda->crtcreg];
case 0x3BA: case 0x3ba:
return mda_stat | 0xF0; return mda->stat | 0xF0;
} }
return 0xff; 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; double _dispontime, _dispofftime, disptime;
disptime=crtc[0]+1; disptime = mda->crtc[0] + 1;
_dispontime=crtc[1]; _dispontime = mda->crtc[1];
_dispofftime=disptime-_dispontime; _dispofftime = disptime - _dispontime;
_dispontime*=MDACONST; _dispontime *= MDACONST;
_dispofftime*=MDACONST; _dispofftime *= MDACONST;
dispontime = (int)(_dispontime * (1 << TIMER_SHIFT)); mda->dispontime = (int)(_dispontime * (1 << TIMER_SHIFT));
dispofftime = (int)(_dispofftime * (1 << TIMER_SHIFT)); mda->dispofftime = (int)(_dispofftime * (1 << TIMER_SHIFT));
} }
int mdacols[256][2][2]; void mda_poll(void *p)
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()
{ {
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 drawcursor;
int x,c; int x, c;
int oldvc; int oldvc;
uint8_t chr,attr; uint8_t chr, attr;
int cols[4]; int cols[4];
int oldsc; int oldsc;
int blink; int blink;
if (!linepos) if (!mda->linepos)
{ {
vidtime+=dispofftime; mda->vidtime += mda->dispofftime;
mda_stat|=1; mda->stat |= 1;
linepos=1; mda->linepos = 1;
oldsc=sc; oldsc = mda->sc;
if ((crtcm[8]&3)==3) sc=(sc<<1)&7; if ((mda->crtc[8] & 3) == 3)
if (cgadispon) 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; mda->lastline = mda->displine;
cols[0]=0; cols[0] = 0;
cols[1]=7; cols[1] = 7;
for (x=0;x<crtcm[1];x++) for (x = 0; x < mda->crtc[1]; x++)
{ {
chr=vram[(ma<<1)&0x3FFF]; chr = mda->vram[(mda->ma << 1) & 0x3fff];
attr=vram[((ma<<1)+1)&0x3FFF]; attr = mda->vram[((mda->ma << 1) + 1) & 0x3fff];
drawcursor=((ma==ca) && con && cursoron); drawcursor = ((mda->ma == ca) && mda->con && mda->cursoron);
blink=((cgablink&16) && (mda_ctrl&0x20) && (attr&0x80) && !drawcursor); blink = ((mda->blink & 16) && (mda->ctrl & 0x20) && (attr & 0x80) && !drawcursor);
if (sc==12 && ((attr&7)==1)) if (mda->sc == 12 && ((attr & 7) == 1))
{ {
for (c=0;c<9;c++) for (c = 0; c < 9; c++)
buffer->line[displine][(x*9)+c]=mdacols[attr][blink][1]; buffer->line[mda->displine][(x * 9) + c] = mdacols[attr][blink][1];
} }
else else
{ {
for (c=0;c<8;c++) for (c = 0; c < 8; c++)
buffer->line[displine][(x*9)+c]=mdacols[attr][blink][(fontdatm[chr][sc]&(1<<(c^7)))?1:0]; 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[displine][(x*9)+8]=mdacols[attr][blink][fontdatm[chr][sc]&1]; if ((chr & ~0x1f) == 0xc0) buffer->line[mda->displine][(x * 9) + 8] = mdacols[attr][blink][fontdatm[chr][mda->sc] & 1];
else buffer->line[displine][(x*9)+8]=mdacols[attr][blink][0]; else buffer->line[mda->displine][(x * 9) + 8] = mdacols[attr][blink][0];
} }
ma++; mda->ma++;
if (drawcursor) if (drawcursor)
{ {
for (c=0;c<9;c++) for (c = 0; c < 9; c++)
buffer->line[displine][(x*9)+c]^=mdacols[attr][0][1]; buffer->line[mda->displine][(x * 9) + c] ^= mdacols[attr][0][1];
} }
} }
} }
sc=oldsc; mda->sc = oldsc;
if (vc==crtcm[7] && !sc) if (mda->vc == mda->crtc[7] && !mda->sc)
{ {
mda_stat|=8; mda->stat |= 8;
// printf("VSYNC on %i %i\n",vc,sc); // printf("VSYNC on %i %i\n",vc,sc);
} }
displine++; mda->displine++;
if (displine>=500) displine=0; if (mda->displine >= 500)
mda->displine=0;
} }
else else
{ {
vidtime+=dispontime; mda->vidtime += mda->dispontime;
if (cgadispon) mda_stat&=~1; if (mda->dispon) mda->stat&=~1;
linepos=0; mda->linepos=0;
if (vsynctime) if (mda->vsynctime)
{ {
vsynctime--; mda->vsynctime--;
if (!vsynctime) if (!mda->vsynctime)
{ {
mda_stat&=~8; mda->stat&=~8;
// printf("VSYNC off %i %i\n",vc,sc); // 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 (mda->sc == (mda->crtc[11] & 31) || ((mda->crtc[8] & 3) == 3 && mda->sc == ((mda->crtc[11] & 31) >> 1)))
if (vadj) {
mda->con = 0;
mda->coff = 1;
}
if (mda->vadj)
{ {
sc++; mda->sc++;
sc&=31; mda->sc &= 31;
ma=maback; mda->ma = mda->maback;
vadj--; mda->vadj--;
if (!vadj) if (!mda->vadj)
{ {
cgadispon=1; mda->dispon = 1;
ma=maback=(crtcm[13]|(crtcm[12]<<8))&0x3FFF; mda->ma = mda->maback = (mda->crtc[13] | (mda->crtc[12] << 8)) & 0x3fff;
sc=0; 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; mda->maback = mda->ma;
sc=0; mda->sc = 0;
oldvc=vc; oldvc = mda->vc;
vc++; mda->vc++;
vc&=127; mda->vc &= 127;
if (vc==crtcm[6]) cgadispon=0; if (mda->vc == mda->crtc[6])
if (oldvc==crtcm[4]) mda->dispon=0;
if (oldvc == mda->crtc[4])
{ {
// printf("Display over at %i\n",displine); // printf("Display over at %i\n",displine);
vc=0; mda->vc = 0;
vadj=crtcm[5]; mda->vadj = mda->crtc[5];
if (!vadj) cgadispon=1; if (!mda->vadj) mda->dispon = 1;
if (!vadj) ma=maback=(crtcm[13]|(crtcm[12]<<8))&0x3FFF; if (!mda->vadj) mda->ma = mda->maback = (mda->crtc[13] | (mda->crtc[12] << 8)) & 0x3fff;
if ((crtcm[10]&0x60)==0x20) cursoron=0; if ((mda->crtc[10] & 0x60) == 0x20) mda->cursoron = 0;
else cursoron=cgablink&16; else mda->cursoron = mda->blink & 16;
} }
if (vc==crtcm[7]) if (mda->vc == mda->crtc[7])
{ {
cgadispon=0; mda->dispon = 0;
displine=0; mda->displine = 0;
vsynctime=16;//(crtcm[3]>>4)+1; mda->vsynctime = 16;
if (crtcm[7]) if (mda->crtc[7])
{ {
// printf("Lastline %i Firstline %i %i\n",lastline,firstline,lastline-firstline); // printf("Lastline %i Firstline %i %i\n",lastline,firstline,lastline-firstline);
x=crtcm[1]*9; x = mda->crtc[1] * 9;
lastline++; mda->lastline++;
if (x!=xsize || (lastline-firstline)!=ysize) if (x != xsize || (mda->lastline - mda->firstline) != ysize)
{ {
xsize=x; xsize = x;
ysize=lastline-firstline; ysize = mda->lastline - mda->firstline;
// printf("Resize to %i,%i - R1 %i\n",xsize,ysize,crtcm[1]); // printf("Resize to %i,%i - R1 %i\n",xsize,ysize,crtcm[1]);
if (xsize<64) xsize=656; if (xsize < 64) xsize = 656;
if (ysize<32) ysize=200; if (ysize < 32) ysize = 200;
updatewindowsize(xsize,ysize); updatewindowsize(xsize, ysize);
} }
startblit(); startblit();
video_blit_memtoscreen_8(0, firstline, xsize, lastline - firstline); video_blit_memtoscreen_8(0, mda->firstline, xsize, mda->lastline - mda->firstline);
endblit(); endblit();
frames++; frames++;
video_res_x = crtcm[1]; video_res_x = mda->crtc[1];
video_res_y = crtcm[6]; video_res_y = mda->crtc[6];
video_bpp = 0; video_bpp = 0;
} }
firstline=1000; mda->firstline = 1000;
lastline=0; mda->lastline = 0;
cgablink++; mda->blink++;
} }
} }
else else
{ {
sc++; mda->sc++;
sc&=31; mda->sc &= 31;
ma=maback; 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]); // 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); int c;
return 0; 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, mda_init,
/*IO at 3Cx/3Dx*/ mda_close,
video_out_null, mda_speed_changed,
video_in_null, 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
}; };

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

View file

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

View file

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

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 PC2086, PC3086 use PVGA1A
MegaPC uses W90C11A MegaPC uses W90C11A
*/ */
#include <stdlib.h>
#include "ibm.h" #include "ibm.h"
#include "device.h"
#include "mem.h" #include "mem.h"
#include "video.h" #include "video.h"
#include "vid_paradise.h"
#include "vid_svga.h" #include "vid_svga.h"
#include "vid_svga_render.h"
#include "vid_unk_ramdac.h" #include "vid_unk_ramdac.h"
void paradise_write(uint32_t addr, uint8_t val, void *priv); typedef struct paradise_t
uint8_t paradise_read(uint32_t addr, void *priv);
void paradise_remap();
enum
{ {
PVGA1A = 0, svga_t svga;
WD90C11
}; 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; 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; // output = 3;
pclog("Paradise out %04X %02X %04X:%04X\n", addr, val, CS, pc); pclog("Paradise out %04X %02X %04X:%04X\n", addr, val, CS, pc);
switch (addr) switch (addr)
{ {
case 0x3c5: 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; return;
seqregs[seqaddr & 0x1f] = val; svga->seqregs[svga->seqaddr & 0x1f] = val;
if (seqaddr == 0x11) if (svga->seqaddr == 0x11)
paradise_remap(); paradise_remap(paradise);
return; return;
} }
break; break;
case 0x3cf: 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; 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); // pclog("Write mapping %02X\n", val);
switch (val&0xC) switch (val&0xC)
{ {
case 0x0: /*128k at A0000*/ 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; break;
case 0x4: /*64k at A0000*/ 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; break;
case 0x8: /*32k at B0000*/ 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; break;
case 0xC: /*32k at B8000*/ 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; break;
} }
} }
gdcreg[6] = val; svga->gdcreg[6] = val;
paradise_remap(); paradise_remap(paradise);
return; return;
} }
if (gdcaddr == 0x9 || gdcaddr == 0xa) if (svga->gdcaddr == 0x9 || svga->gdcaddr == 0xa)
{ {
gdcreg[gdcaddr] = val; svga->gdcreg[svga->gdcaddr] = val;
paradise_remap(); paradise_remap(paradise);
return; return;
} }
if (gdcaddr == 0xe) if (svga->gdcaddr == 0xe)
{ {
gdcreg[0xe] = val; svga->gdcreg[0xe] = val;
paradise_remap(); paradise_remap(paradise);
return; return;
} }
break; break;
case 0x3D4: case 0x3D4:
if (paradise_type == PVGA1A) if (paradise->type == PVGA1A)
crtcreg = val & 0x1f; svga->crtcreg = val & 0x1f;
else else
crtcreg = val & 0x3f; svga->crtcreg = val & 0x3f;
return; return;
case 0x3D5: case 0x3D5:
if (crtcreg <= 7 && crtc[0x11] & 0x80) if (svga->crtcreg <= 7 && svga->crtc[0x11] & 0x80)
return; return;
if (crtcreg > 0x29 && (crtc[0x29] & 7) != 5) if (svga->crtcreg > 0x29 && (svga->crtc[0x29] & 7) != 5)
return; return;
if (crtcreg >= 0x31 && crtcreg <= 0x37) if (svga->crtcreg >= 0x31 && svga->crtcreg <= 0x37)
return; return;
old=crtc[crtcreg]; old = svga->crtc[svga->crtcreg];
crtc[crtcreg]=val; 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; fullchange = changeframecount;
svga_recalctimings(); svga_recalctimings(&paradise->svga);
} }
} }
break; 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) switch (addr)
{ {
case 0x3c2:
return 0x10;
case 0x3c5: 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; return 0xff;
if (seqaddr > 0x12) if (svga->seqaddr > 0x12)
return 0xff; return 0xff;
return seqregs[seqaddr & 0x1f]; return svga->seqregs[svga->seqaddr & 0x1f];
} }
break; break;
case 0x3cf: 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; return 0xff;
switch (gdcaddr) switch (svga->gdcaddr)
{ {
case 0xf: case 0xf:
return (gdcreg[0xf] & 0x17) | 0x80; return (svga->gdcreg[0xf] & 0x17) | 0x80;
} }
} }
break; break;
case 0x3D4: case 0x3D4:
return crtcreg; return svga->crtcreg;
case 0x3D5: 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 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"); // pclog("Remap 1\n");
paradise_bank_r[0] = paradise_bank_r[2] = (gdcreg[0x9] & 0x7f) << 12; paradise->read_bank[0] = paradise->read_bank[2] = (svga->gdcreg[0x9] & 0x7f) << 12;
paradise_bank_r[1] = paradise_bank_r[3] = ((gdcreg[0x9] & 0x7f) << 12) + ((gdcreg[6] & 0x08) ? 0 : 0x8000); paradise->read_bank[1] = paradise->read_bank[3] = ((svga->gdcreg[0x9] & 0x7f) << 12) + ((svga->gdcreg[6] & 0x08) ? 0 : 0x8000);
paradise_bank_w[0] = paradise_bank_w[2] = (gdcreg[0xa] & 0x7f) << 12; paradise->write_bank[0] = paradise->write_bank[2] = (svga->gdcreg[0xa] & 0x7f) << 12;
paradise_bank_w[1] = paradise_bank_w[3] = ((gdcreg[0xa] & 0x7f) << 12) + ((gdcreg[6] & 0x08) ? 0 : 0x8000); 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"); // pclog("Remap 2\n");
paradise_bank_r[0] = paradise_bank_r[2] = (gdcreg[0xa] & 0x7f) << 12; paradise->read_bank[0] = paradise->read_bank[2] = (svga->gdcreg[0xa] & 0x7f) << 12;
paradise_bank_w[0] = paradise_bank_w[2] = (gdcreg[0xa] & 0x7f) << 12; paradise->write_bank[0] = paradise->write_bank[2] = (svga->gdcreg[0xa] & 0x7f) << 12;
paradise_bank_r[1] = paradise_bank_r[3] = ((gdcreg[0x9] & 0x7f) << 12) + ((gdcreg[6] & 0x08) ? 0 : 0x8000); paradise->read_bank[1] = paradise->read_bank[3] = ((svga->gdcreg[0x9] & 0x7f) << 12) + ((svga->gdcreg[6] & 0x08) ? 0 : 0x8000);
paradise_bank_w[1] = paradise_bank_w[3] = ((gdcreg[0x9] & 0x7f) << 12) + ((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 else
{ {
// pclog("Remap 3\n"); // pclog("Remap 3\n");
paradise_bank_r[0] = paradise_bank_w[0] = (gdcreg[0xa] & 0x7f) << 12; paradise->read_bank[0] = paradise->write_bank[0] = (svga->gdcreg[0xa] & 0x7f) << 12;
paradise_bank_r[1] = paradise_bank_w[1] = ((gdcreg[0xa] & 0x7f) << 12) + ((gdcreg[6] & 0x08) ? 0 : 0x8000); paradise->read_bank[1] = paradise->write_bank[1] = ((svga->gdcreg[0xa] & 0x7f) << 12) + ((svga->gdcreg[6] & 0x08) ? 0 : 0x8000);
paradise_bank_r[2] = paradise_bank_w[2] = (gdcreg[0x9] & 0x7f) << 12; paradise->read_bank[2] = paradise->write_bank[2] = (svga->gdcreg[0x9] & 0x7f) << 12;
paradise_bank_r[3] = paradise_bank_w[3] = ((gdcreg[0x9] & 0x7f) << 12) + ((gdcreg[6] & 0x08) ? 0 : 0x8000); paradise->read_bank[3] = paradise->write_bank[3] = ((svga->gdcreg[0x9] & 0x7f) << 12) + ((svga->gdcreg[6] & 0x08) ? 0 : 0x8000);
} }
} }
else else
{ {
// pclog("Remap 4\n"); // pclog("Remap 4\n");
paradise_bank_r[0] = paradise_bank_r[2] = (gdcreg[0x9] & 0x7f) << 12; paradise->read_bank[0] = paradise->read_bank[2] = (svga->gdcreg[0x9] & 0x7f) << 12;
paradise_bank_r[1] = paradise_bank_r[3] = ((gdcreg[0x9] & 0x7f) << 12) + ((gdcreg[6] & 0x08) ? 0 : 0x8000); paradise->read_bank[1] = paradise->read_bank[3] = ((svga->gdcreg[0x9] & 0x7f) << 12) + ((svga->gdcreg[6] & 0x08) ? 0 : 0x8000);
paradise_bank_w[0] = paradise_bank_w[2] = (gdcreg[0x9] & 0x7f) << 12; paradise->write_bank[0] = paradise->write_bank[2] = (svga->gdcreg[0x9] & 0x7f) << 12;
paradise_bank_w[1] = paradise_bank_w[3] = ((gdcreg[0x9] & 0x7f) << 12) + ((gdcreg[6] & 0x08) ? 0 : 0x8000); 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 egacycles 1
#define egacycles2 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); // 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); // 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); // 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); // 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_t *paradise = malloc(sizeof(paradise_t));
{ svga_t *svga = &paradise->svga;
paradise_type = PVGA1A; memset(paradise, 0, sizeof(paradise_t));
vrammask = 0x3ffff;
pclog("Init PVGA1A\n"); io_sethandler(0x03c0, 0x0020, paradise_in, NULL, NULL, paradise_out, NULL, NULL, paradise);
svga_vram_limit = 1 << 18; /*256kb*/
} svga_init(&paradise->svga, paradise, 1 << 18, /*256kb*/
if (romset == ROM_MEGAPC) NULL,
{ paradise_in, paradise_out,
paradise_type = WD90C11; NULL);
vrammask = 0x7ffff;
crtc[0x36] = '1'; svga->crtc[0x31] = 'W';
crtc[0x37] = '1'; svga->crtc[0x32] = 'D';
pclog("Init WD90C11\n"); svga->crtc[0x33] = '9';
svga_vram_limit = 1 << 19; /*512kb*/ svga->crtc[0x34] = '0';
} svga->crtc[0x35] = 'C';
crtc[0x31] = 'W';
crtc[0x32] = 'D'; svga->bpp = 8;
crtc[0x33] = '9'; svga->miscout = 1;
crtc[0x34] = '0';
crtc[0x35] = 'C'; paradise->type = PVGA1A;
svga_recalctimings_ex = paradise_recalctimings;
return svga_init(); return paradise;
} }
GFXCARD vid_paradise = void *paradise_wd90c11_init()
{ {
paradise_init, paradise_t *paradise = malloc(sizeof(paradise_t));
/*IO at 3Cx/3Dx*/ svga_t *svga = &paradise->svga;
paradise_out, memset(paradise, 0, sizeof(paradise_t));
paradise_in,
/*IO at 3Ax/3Bx*/ io_sethandler(0x03c0, 0x0020, paradise_in, NULL, NULL, paradise_out, NULL, NULL, paradise);
video_out_null,
video_in_null,
svga_poll, svga_init(&paradise->svga, paradise, 1 << 19, /*512kb*/
svga_recalctimings, paradise_recalctimings,
paradise_in, paradise_out,
NULL);
paradise_write, svga->crtc[0x31] = 'W';
video_write_null, svga->crtc[0x32] = 'D';
video_write_null, svga->crtc[0x33] = '9';
svga->crtc[0x34] = '0';
svga->crtc[0x35] = 'C';
svga->crtc[0x36] = '1';
svga->crtc[0x37] = '1';
paradise_read, svga->bpp = 8;
video_read_null, svga->miscout = 1;
video_read_null
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 The Technical Reference Manual lists the video waitstate time as between 12
and 46 cycles. PCem currently always uses the lower number.*/ and 46 cycles. PCem currently always uses the lower number.*/
#include <stdlib.h>
#include "ibm.h" #include "ibm.h"
#include "device.h"
#include "io.h" #include "io.h"
#include "mem.h" #include "mem.h"
#include "timer.h" #include "timer.h"
#include "video.h" #include "video.h"
#include "vid_cga.h" #include "vid_pc1512.h"
static uint8_t pc1512_plane_write,pc1512_plane_read,pc1512_border; typedef struct pc1512_t
void pc1512_recalctimings();
void pc1512_out(uint16_t addr, uint8_t val, void *priv)
{ {
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; 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) switch (addr)
{ {
case 0x3D4: case 0x3d4:
crtcreg=val&31; pc1512->crtcreg = val & 31;
return; return;
case 0x3D5: case 0x3d5:
old=crtc[crtcreg]; old = pc1512->crtc[pc1512->crtcreg];
crtc[crtcreg]=val&crtcmask[crtcreg]; pc1512->crtc[pc1512->crtcreg] = val & crtcmask[pc1512->crtcreg];
if (old!=val) if (old != val)
{ {
if (crtcreg<0xE || crtcreg>0x10) if (pc1512->crtcreg < 0xe || pc1512->crtcreg > 0x10)
{ {
fullchange=changeframecount; fullchange = changeframecount;
pc1512_recalctimings(); pc1512_recalctimings(pc1512);
} }
} }
return; return;
case 0x3D8: case 0x3d8:
if ((val&0x12)==0x12 && (cgamode&0x12)!=0x12) if ((val & 0x12) == 0x12 && (pc1512->cgamode & 0x12) != 0x12)
{ {
pc1512_plane_write=0xF; pc1512->plane_write = 0xf;
pc1512_plane_read =0; pc1512->plane_read = 0;
} }
cgamode=val; pc1512->cgamode = val;
return; return;
case 0x3D9: case 0x3d9:
cgacol=val; pc1512->cgacol = val;
return; return;
case 0x3DD: case 0x3dd:
pc1512_plane_write=val; pc1512->plane_write = val;
return; return;
case 0x3DE: case 0x3de:
pc1512_plane_read=val&3; pc1512->plane_read = val & 3;
return; return;
case 0x3DF: case 0x3df:
pc1512_border=val; pc1512->border = val;
return; 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); // pclog("PC1512 in %04X %02X %04X:%04X\n",addr,CS,pc);
switch (addr) switch (addr)
{ {
case 0x3D4: case 0x3d4:
return crtcreg; return pc1512->crtcreg;
case 0x3D5: case 0x3d5:
return crtc[crtcreg]; return pc1512->crtc[pc1512->crtcreg];
case 0x3DA: case 0x3da:
return cgastat; 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(); if (pc1512->plane_write & 1) pc1512->vram[addr] = val;
exit(-1); if (pc1512->plane_write & 2) pc1512->vram[addr | 0x4000] = val;
} if (pc1512->plane_write & 4) pc1512->vram[addr | 0x8000] = val;
pclog("PC1512 write %08X %02X %02X %01X %04X:%04X\n",addr,val,cgamode&0x12,pc1512_plane_write,CS,pc);*/ if (pc1512->plane_write & 8) pc1512->vram[addr | 0xc000] = val;
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;
} }
else 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); pc1512_t *pc1512 = (pc1512_t *)p;
cycles-=12;
addr&=0x7FFF; cycles -= 12;
if ((cgamode&0x12)==0x12) addr &= 0x3fff;
return vram[addr|(pc1512_plane_read<<16)];
return vram[addr]; if ((pc1512->cgamode & 0x12) == 0x12)
return pc1512->vram[addr | (pc1512->plane_read << 14)];
return pc1512->vram[addr];
} }
static int linepos,displine; static void pc1512_recalctimings(pc1512_t *pc1512)
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()
{ {
double _dispontime, _dispofftime; double _dispontime, _dispofftime, disptime;
disptime = 128; /*Fixed on PC1512*/ disptime = 128; /*Fixed on PC1512*/
_dispontime = 80; _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]); // printf("%i %f %f %f %i %i\n",cgamode&1,disptime,dispontime,dispofftime,crtc[0],crtc[1]);
_dispontime*=CGACONST; _dispontime *= CGACONST;
_dispofftime*=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); // 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)); pc1512->dispontime = (int)(_dispontime * (1 << TIMER_SHIFT));
dispofftime = (int)(_dispofftime * (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 drawcursor;
int x,c; int x, c;
int oldvc; int oldvc;
uint8_t chr,attr; uint8_t chr, attr;
uint16_t dat,dat2,dat3,dat4; uint16_t dat, dat2, dat3, dat4;
int cols[4]; int cols[4];
int col; int col;
int oldsc; int oldsc;
if (!linepos) if (!pc1512->linepos)
{ {
vidtime+=dispofftime; pc1512->vidtime += pc1512->dispofftime;
cgastat|=1; pc1512->stat |= 1;
linepos=1; pc1512->linepos = 1;
oldsc=sc; oldsc = pc1512->sc;
if (cgadispon) if (pc1512->dispon)
{ {
if (displine<firstline) firstline=displine; if (pc1512->displine < pc1512->firstline)
lastline=displine; pc1512->firstline = pc1512->displine;
for (c=0;c<8;c++) 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; buffer->line[pc1512->displine][c] = (pc1512->border & 15) + 16;
if (cgamode&1) buffer->line[displine][c+(crtc[1]<<3)+8]=0; if (pc1512->cgamode & 1) buffer->line[pc1512->displine][c + (pc1512->crtc[1] << 3) + 8] = 0;
else buffer->line[displine][c+(crtc[1]<<4)+8]=0; else buffer->line[pc1512->displine][c + (pc1512->crtc[1] << 4) + 8] = 0;
} }
else else
{ {
buffer->line[displine][c]=(cgacol&15)+16; buffer->line[pc1512->displine][c] = (pc1512->cgacol & 15) + 16;
if (cgamode&1) buffer->line[displine][c+(crtc[1]<<3)+8]=(cgacol&15)+16; if (pc1512->cgamode & 1) buffer->line[pc1512->displine][c + (pc1512->crtc[1] << 3) + 8] = (pc1512->cgacol & 15) + 16;
else buffer->line[displine][c+(crtc[1]<<4)+8]=(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++) for (x = 0; x < 80; x++)
{ {
chr=vram[((ma<<1)&0x3FFF)]; chr = pc1512->vram[ ((pc1512->ma << 1) & 0x3fff)];
attr=vram[(((ma<<1)+1)&0x3FFF)]; attr = pc1512->vram[(((pc1512->ma << 1) + 1) & 0x3fff)];
drawcursor=((ma==ca) && con && cursoron); drawcursor = ((pc1512->ma == ca) && pc1512->con && pc1512->cursoron);
if (cgamode&0x20) if (pc1512->cgamode & 0x20)
{ {
cols[1]=(attr&15)+16; cols[1] = (attr & 15) + 16;
cols[0]=((attr>>4)&7)+16; cols[0] = ((attr >> 4) & 7) + 16;
if ((cgablink&16) && (attr&0x80) && !drawcursor) cols[1]=cols[0]; if ((pc1512->blink & 16) && (attr & 0x80) && !drawcursor)
cols[1] = cols[0];
} }
else else
{ {
cols[1]=(attr&15)+16; cols[1] = (attr & 15) + 16;
cols[0]=(attr>>4)+16; cols[0] = (attr >> 4) + 16;
} }
if (drawcursor) if (drawcursor)
{ {
for (c=0;c<8;c++) for (c = 0; c < 8; c++)
buffer->line[displine][(x<<3)+c+8]=cols[(fontdat[chr][sc&7]&(1<<(c^7)))?1:0]^15; buffer->line[pc1512->displine][(x << 3) + c + 8] = cols[(fontdat[chr][pc1512->sc & 7] & (1 << (c ^ 7))) ? 1 : 0] ^ 15;
} }
else else
{ {
for (c=0;c<8;c++) for (c = 0; c < 8; c++)
buffer->line[displine][(x<<3)+c+8]=cols[(fontdat[chr][sc&7]&(1<<(c^7)))?1:0]; 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++) for (x = 0; x < 40; x++)
{ {
chr=vram[((ma<<1)&0x3FFF)]; chr = pc1512->vram[ ((pc1512->ma << 1) & 0x3fff)];
attr=vram[(((ma<<1)+1)&0x3FFF)]; attr = pc1512->vram[(((pc1512->ma << 1) + 1) & 0x3fff)];
drawcursor=((ma==ca) && con && cursoron); drawcursor = ((pc1512->ma == ca) && pc1512->con && pc1512->cursoron);
if (cgamode&0x20) if (pc1512->cgamode & 0x20)
{ {
cols[1]=(attr&15)+16; cols[1] = (attr & 15) + 16;
cols[0]=((attr>>4)&7)+16; cols[0] = ((attr >> 4) & 7) + 16;
if ((cgablink&16) && (attr&0x80)) cols[1]=cols[0]; if ((pc1512->blink & 16) && (attr & 0x80))
cols[1] = cols[0];
} }
else else
{ {
cols[1]=(attr&15)+16; cols[1] = (attr & 15) + 16;
cols[0]=(attr>>4)+16; cols[0] = (attr >> 4) + 16;
} }
ma++; pc1512->ma++;
if (drawcursor) if (drawcursor)
{ {
for (c=0;c<8;c++) 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; 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 else
{ {
for (c=0;c<8;c++) 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]; 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; cols[0] = (pc1512->cgacol & 15) | 16;
col=(cgacol&16)?24:16; col = (pc1512->cgacol & 16) ? 24 : 16;
if (cgamode&4) if (pc1512->cgamode & 4)
{ {
cols[1]=col|3; cols[1] = col | 3;
cols[2]=col|4; cols[2] = col | 4;
cols[3]=col|7; cols[3] = col | 7;
} }
else if (cgacol&32) else if (pc1512->cgacol & 32)
{ {
cols[1]=col|3; cols[1] = col | 3;
cols[2]=col|5; cols[2] = col | 5;
cols[3]=col|7; cols[3] = col | 7;
} }
else else
{ {
cols[1]=col|2; cols[1] = col | 2;
cols[2]=col|4; cols[2] = col | 4;
cols[3]=col|6; cols[3] = col | 6;
} }
for (x = 0; x < 40; x++) for (x = 0; x < 40; x++)
{ {
dat=(vram[((ma<<1)&0x1FFF)+((sc&1)*0x2000)]<<8)|vram[((ma<<1)&0x1FFF)+((sc&1)*0x2000)+1]; dat = (pc1512->vram[((pc1512->ma << 1) & 0x1fff) + ((pc1512->sc & 1) * 0x2000)] << 8) | pc1512->vram[((pc1512->ma << 1) & 0x1fff) + ((pc1512->sc & 1) * 0x2000) + 1];
ma++; pc1512->ma++;
for (c=0;c<8;c++) for (c = 0; c < 8; c++)
{ {
buffer->line[displine][(x<<4)+(c<<1)+8]= buffer->line[pc1512->displine][(x << 4) + (c << 1) + 8] =
buffer->line[displine][(x<<4)+(c<<1)+1+8]=cols[dat>>14]; buffer->line[pc1512->displine][(x << 4) + (c << 1) + 1 + 8] = cols[dat >> 14];
dat<<=2; dat <<= 2;
} }
} }
} }
@ -270,169 +296,191 @@ void pc1512_poll()
{ {
for (x = 0; x < 40; x++) for (x = 0; x < 40; x++)
{ {
ca=((ma<<1)&0x1FFF)+((sc&1)*0x2000); ca = ((pc1512->ma << 1) & 0x1fff) + ((pc1512->sc & 1) * 0x2000);
dat=(vram[ca]<<8)|vram[ca+1]; dat = (pc1512->vram[ca] << 8) | pc1512->vram[ca + 1];
dat2=(vram[ca+0x10000]<<8)|vram[ca+0x10001]; dat2 = (pc1512->vram[ca + 0x4000] << 8) | pc1512->vram[ca + 0x4001];
dat3=(vram[ca+0x20000]<<8)|vram[ca+0x20001]; dat3 = (pc1512->vram[ca + 0x8000] << 8) | pc1512->vram[ca + 0x8001];
dat4=(vram[ca+0x30000]<<8)|vram[ca+0x30001]; dat4 = (pc1512->vram[ca + 0xc000] << 8) | pc1512->vram[ca + 0xc001];
ma++; pc1512->ma++;
for (c=0;c<16;c++) 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; 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; dat <<= 1;
dat2<<=1; dat2 <<= 1;
dat3<<=1; dat3 <<= 1;
dat4<<=1; dat4 <<= 1;
} }
} }
} }
} }
else else
{ {
cols[0]=((cgamode&0x12)==0x12)?0:(cgacol&15)+16; cols[0] = ((pc1512->cgamode & 0x12) == 0x12) ? 0 : (pc1512->cgacol & 15) + 16;
if (cgamode&1) hline(buffer,0,displine,(crtc[1]<<3)+16,cols[0]); if (pc1512->cgamode & 1) hline(buffer, 0, pc1512->displine, (pc1512->crtc[1] << 3) + 16, cols[0]);
else hline(buffer,0,displine,(crtc[1]<<4)+16,cols[0]); else hline(buffer, 0, pc1512->displine, (pc1512->crtc[1] << 4) + 16, cols[0]);
} }
sc=oldsc; pc1512->sc = oldsc;
if (vsynctime) if (pc1512->vsynctime)
cgastat|=8; pc1512->stat |= 8;
displine++; pc1512->displine++;
if (displine>=360) displine=0; if (pc1512->displine >= 360)
pc1512->displine = 0;
// pclog("Line %i %i %i %i %i %i\n",displine,cgadispon,firstline,lastline,vc,sc); // pclog("Line %i %i %i %i %i %i\n",displine,cgadispon,firstline,lastline,vc,sc);
} }
else else
{ {
vidtime+=dispontime; pc1512->vidtime += pc1512->dispontime;
if ((lastline-firstline)==199) cgadispon=0; /*Amstrad PC1512 always displays 200 lines, regardless of CRTC settings*/ if ((pc1512->lastline - pc1512->firstline) == 199)
if (cgadispon) cgastat&=~1; pc1512->dispon = 0; /*Amstrad PC1512 always displays 200 lines, regardless of CRTC settings*/
linepos=0; if (pc1512->dispon)
if (vsynctime) pc1512->stat &= ~1;
pc1512->linepos = 0;
if (pc1512->vsynctime)
{ {
vsynctime--; pc1512->vsynctime--;
if (!vsynctime) if (!pc1512->vsynctime)
cgastat&=~8; pc1512->stat &= ~8;
} }
if (sc==(crtc[11]&31)) { con=0; coff=1; } if (pc1512->sc == (pc1512->crtc[11] & 31))
if (vadj) {
pc1512->con = 0;
pc1512->coff = 1;
}
if (pc1512->vadj)
{ {
sc++; pc1512->sc++;
sc&=31; pc1512->sc &= 31;
ma=maback; pc1512->ma = pc1512->maback;
vadj--; pc1512->vadj--;
if (!vadj) if (!pc1512->vadj)
{ {
cgadispon=1; pc1512->dispon = 1;
ma=maback=(crtc[13]|(crtc[12]<<8))&0x3FFF; pc1512->ma = pc1512->maback = (pc1512->crtc[13] | (pc1512->crtc[12] << 8)) & 0x3fff;
sc=0; pc1512->sc = 0;
} }
} }
else if (sc==crtc[9]) else if (pc1512->sc == pc1512->crtc[9])
{ {
maback=ma; pc1512->maback = pc1512->ma;
sc=0; pc1512->sc = 0;
oldvc=vc; oldvc = pc1512->vc;
vc++; pc1512->vc++;
vc&=127; pc1512->vc &= 127;
if (displine == 32)//oldvc == (cgamode & 2) ? 127 : 31) if (pc1512->displine == 32)//oldvc == (cgamode & 2) ? 127 : 31)
{ {
vc=0; pc1512->vc = 0;
vadj=6; pc1512->vadj = 6;
if ((crtc[10]&0x60)==0x20) cursoron=0; if ((pc1512->crtc[10] & 0x60) == 0x20) pc1512->cursoron = 0;
else cursoron=cgablink&16; 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; pc1512->dispon = 0;
displine=0; pc1512->displine = 0;
vsynctime=46; pc1512->vsynctime = 46;
if (cgamode&1) x=(crtc[1]<<3)+16; if (pc1512->cgamode&1) x = (pc1512->crtc[1] << 3) + 16;
else x=(crtc[1]<<4)+16; else x = (pc1512->crtc[1] << 4) + 16;
x = 640 + 16; x = 640 + 16;
lastline++; pc1512->lastline++;
if (x!=xsize || (lastline-firstline)!=ysize)
{ if (x != xsize || (pc1512->lastline - pc1512->firstline) != ysize)
xsize=x; {
ysize=lastline-firstline; xsize = x;
if (xsize<64) xsize=656; ysize = pc1512->lastline - pc1512->firstline;
if (ysize<32) ysize=200; if (xsize < 64) xsize = 656;
updatewindowsize(xsize,(ysize<<1)+16); if (ysize < 32) ysize = 200;
} updatewindowsize(xsize, (ysize << 1) + 16);
}
startblit(); 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); // 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); // 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); // 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); // if (readflash) rectfill(screen,winsizex-40,8,winsizex-8,14,0xFFFFFFFF);
// readflash=0; // readflash=0;
endblit(); endblit();
video_res_x = xsize - 16; video_res_x = xsize - 16;
video_res_y = ysize; video_res_y = ysize;
if (cgamode & 1) if (pc1512->cgamode & 1)
{ {
video_res_x /= 8; video_res_x /= 8;
video_res_y /= crtc[9] + 1; video_res_y /= pc1512->crtc[9] + 1;
video_bpp = 0; video_bpp = 0;
} }
else if (!(cgamode & 2)) else if (!(pc1512->cgamode & 2))
{ {
video_res_x /= 16; video_res_x /= 16;
video_res_y /= crtc[9] + 1; video_res_y /= pc1512->crtc[9] + 1;
video_bpp = 0; video_bpp = 0;
} }
else if (!(cgamode&16)) else if (!(pc1512->cgamode & 16))
{ {
video_res_x /= 2; video_res_x /= 2;
video_bpp = 2; video_bpp = 2;
} }
else else
{ {
video_bpp = 4; video_bpp = 4;
} }
firstline=1000; pc1512->firstline = 1000;
lastline=0; pc1512->lastline = 0;
cgablink++; pc1512->blink++;
} }
} }
else else
{ {
sc++; pc1512->sc++;
sc&=31; pc1512->sc &= 31;
ma=maback; 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); int c;
return 0; 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, pc1512_init,
/*IO at 3Cx/3Dx*/ pc1512_close,
pc1512_out, pc1512_speed_changed,
pc1512_in, NULL
/*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
}; };

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. /*PC1640 video emulation.
Mostly standard EGA, but with CGA & Hercules emulation*/ Mostly standard EGA, but with CGA & Hercules emulation*/
#include <stdlib.h>
#include "ibm.h" #include "ibm.h"
#include "device.h"
#include "io.h" #include "io.h"
#include "mem.h" #include "mem.h"
#include "timer.h"
#include "video.h" #include "video.h"
#include "vid_cga.h" #include "vid_cga.h"
#include "vid_ega.h" #include "vid_ega.h"
#include "vid_pc1640.h"
static int pc1640_cga=1; typedef struct pc1640_t
void pc1640_out(uint16_t addr, uint8_t val, void *priv)
{ {
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) switch (addr)
{ {
case 0x3DB: case 0x3db:
pc1640_cga=val&0x40; pc1640->cga_enabled = val & 0x40;
mem_removehandler(0xa0000, 0x20000, ega_read, NULL, NULL, ega_write, NULL, NULL, NULL); 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, NULL); mem_removehandler(0xb8000, 0x08000, cga_read, NULL, NULL, cga_write, NULL, NULL, &pc1640->cga);
if (pc1640_cga) if (pc1640->cga_enabled)
mem_sethandler(0xb8000, 0x08000, cga_read, NULL, NULL, cga_write, NULL, NULL, NULL); mem_sethandler(0xb8000, 0x08000, cga_read, NULL, NULL, cga_write, NULL, NULL, &pc1640->cga);
else else
{ {
switch (gdcreg[6] & 0xC) switch (pc1640->ega.gdcreg[6] & 0xc)
{ {
case 0x0: /*128k at A0000*/ 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; break;
case 0x4: /*64k at A0000*/ 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; break;
case 0x8: /*32k at B0000*/ 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; break;
case 0xC: /*32k at B8000*/ 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; break;
} }
} }
pclog("3DB write %02X\n", val); pclog("3DB write %02X\n", val);
return; return;
} }
if (pc1640_cga) cga_out(addr, val, NULL); if (pc1640->cga_enabled) cga_out(addr, val, &pc1640->cga);
else ega_out(addr, val, NULL); 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) 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; if (pc1640->cga_enabled) return cga_in(addr, &pc1640->cga);
else return ega_in(addr, &pc1640->ega);
mem_sethandler(0xb8000, 0x08000, cga_read, NULL, NULL, cga_write, NULL, NULL, NULL);
return r;
} }
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, pc1640_init,
/*IO at 3Cx/3Dx*/ pc1640_close,
pc1640_out, pc1640_speed_changed,
pc1640_in, NULL
/*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
}; };

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. /*PC200 video emulation.
CGA with some NMI stuff. But we don't need that as it's only used for TV and 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*/ LCD displays, and we're emulating a CRT*/
#include <stdlib.h>
#include "ibm.h" #include "ibm.h"
#include "device.h"
#include "io.h" #include "io.h"
#include "mem.h" #include "mem.h"
#include "timer.h"
#include "video.h" #include "video.h"
#include "vid_cga.h" #include "vid_cga.h"
#include "vid_pc200.h"
uint8_t pc200_3dd, pc200_3de, pc200_3df; typedef struct pc200_t
void pc200_out(uint16_t addr, uint8_t val, void *priv)
{ {
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; uint8_t old;
switch (addr) switch (addr)
{ {
case 0x3D5: case 0x3d5:
if (!(pc200_3de&0x40) && crtcreg<=11) if (!(pc200->reg_3de & 0x40) && cga->crtcreg <= 11)
{ {
if (pc200_3de&0x80) nmi=1; if (pc200->reg_3de & 0x80)
pc200_3dd=0x20|(crtcreg&0x1F); nmi = 1;
pc200_3df=val;
pc200->reg_3dd = 0x20 | (cga->crtcreg & 0x1f);
pc200->reg_3df = val;
return; return;
} }
old=crtc[crtcreg]; old = cga->crtc[cga->crtcreg];
crtc[crtcreg]=val&crtcmask[crtcreg]; cga->crtc[cga->crtcreg] = val & crtcmask[cga->crtcreg];
if (old!=val) if (old != val)
{ {
if (crtcreg<0xE || crtcreg>0x10) if (cga->crtcreg < 0xe || cga->crtcreg > 0x10)
{ {
fullchange=changeframecount; fullchange = changeframecount;
cga_recalctimings(); cga_recalctimings(cga);
} }
} }
return; return;
case 0x3D8: case 0x3d8:
old = cgamode; old = cga->cgamode;
cgamode=val; cga->cgamode = val;
if ((cgamode ^ old) & 3) if ((cga->cgamode ^ old) & 3)
cga_recalctimings(); cga_recalctimings(cga);
pc200_3dd|=0x80; pc200->reg_3dd |= 0x80;
if (pc200_3de&0x80) if (pc200->reg_3de & 0x80)
nmi=1; nmi = 1;
return; return;
case 0x3DE: case 0x3de:
pc200_3de=val; pc200->reg_3de = val;
pc200_3dd=0x1F; pc200->reg_3dd = 0x1f;
if (val&0x80) pc200_3dd|=0x40; if (val & 0x80)
pc200->reg_3dd |= 0x40;
return; 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; uint8_t temp;
switch (addr) switch (addr)
{ {
case 0x3D8: case 0x3D8:
return cgamode; return cga->cgamode;
case 0x3DD: case 0x3DD:
temp = pc200_3dd; temp = pc200->reg_3dd;
pc200_3dd &= 0x1F; pc200->reg_3dd &= 0x1f;
return temp; return temp;
case 0x3DE: case 0x3DE:
return (pc200_3de&0xC7)| 0x18; /*External CGA*/ return (pc200->reg_3de & 0xc7) | 0x18; /*External CGA*/
case 0x3DF: 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); pc200_t *pc200 = malloc(sizeof(pc200_t));
return cga_init(); 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, pc200_init,
/*IO at 3Cx/3Dx*/ pc200_close,
pc200_out, pc200_speed_changed,
pc200_in, NULL
/*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
}; };

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

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

View file

@ -1,4 +1,14 @@
void sdac_ramdac_out(uint16_t addr, uint8_t val, void *priv); typedef struct sdac_ramdac_t
uint8_t sdac_ramdac_in(uint16_t addr, void *priv); {
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_svga.h"
#include "vid_stg_ramdac.h" #include "vid_stg_ramdac.h"
struct 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 magic_count;
uint8_t command;
int index;
uint8_t regs[256];
} stg_ramdac;
int stg_state_read[2][8]={{1,2,3,4,0,0,0,0}, {1,2,3,4,5,6,7,7}}; void stg_ramdac_out(uint16_t addr, uint8_t val, stg_ramdac_t *ramdac, svga_t *svga)
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)
{ {
int didwrite; int didwrite;
//if (CS!=0xC000) pclog("OUT RAMDAC %04X %02X %i %04X:%04X\n",addr,val,stg_ramdac.magic_count,CS,pc); //if (CS!=0xC000) pclog("OUT RAMDAC %04X %02X %i %04X:%04X\n",addr,val,stg_ramdac.magic_count,CS,pc);
switch (addr) switch (addr)
{ {
case 0x3C6: case 0x3c6:
switch (stg_ramdac.magic_count) switch (ramdac->magic_count)
{ {
case 0: case 1: case 2: case 3: break; case 0: case 1: case 2: case 3:
case 4: stg_ramdac.command=val; /*pclog("Write RAMDAC command %02X\n",val);*/ break; break;
case 5: stg_ramdac.index=(stg_ramdac.index&0xFF00)|val; break; case 4:
case 6: stg_ramdac.index=(stg_ramdac.index&0xFF)|(val<<8); break; 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: case 7:
pclog("Write RAMDAC reg %02X %02X\n", stg_ramdac.index, val); pclog("Write RAMDAC reg %02X %02X\n", ramdac->index, val);
if (stg_ramdac.index<0x100) stg_ramdac.regs[stg_ramdac.index]=val; if (ramdac->index < 0x100)
stg_ramdac.index++; ramdac->regs[ramdac->index] = val;
ramdac->index++;
break; break;
} }
didwrite = (stg_ramdac.magic_count>=4); didwrite = (ramdac->magic_count >= 4);
stg_ramdac.magic_count=stg_state_write[stg_ramdac.magic_count&7]; ramdac->magic_count = stg_state_write[ramdac->magic_count & 7];
if (stg_ramdac.command&8) if (ramdac->command & 8)
{ {
switch (stg_ramdac.regs[3]) switch (ramdac->regs[3])
{ {
case 0: case 5: case 7: bpp=8; break; case 0: case 5: case 7: svga->bpp = 8; break;
case 1: case 2: case 8: bpp=15; break; case 1: case 2: case 8: svga->bpp = 15; break;
case 3: case 6: bpp=16; break; case 3: case 6: svga->bpp = 16; break;
case 4: case 9: bpp=24; break; case 4: case 9: svga->bpp = 24; break;
default: bpp=8; break; default: svga->bpp = 8; break;
} }
} }
else else
{ {
switch (stg_ramdac.command>>5) switch (ramdac->command >> 5)
{ {
case 0: bpp=8; break; case 0: svga->bpp = 8; break;
case 5: bpp=15; break; case 5: svga->bpp = 15; break;
case 6: bpp=16; break; case 6: svga->bpp = 16; break;
case 7: bpp=24; break; case 7: svga->bpp = 24; break;
default: bpp=8; break; default: svga->bpp = 8; break;
} }
} }
if (didwrite) return; if (didwrite) return;
break; break;
case 0x3C7: case 0x3C8: case 0x3C9: case 0x3c7: case 0x3c8: case 0x3c9:
stg_ramdac.magic_count=0; ramdac->magic_count=0;
break; 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; uint8_t temp;
//if (CS!=0xC000) pclog("IN RAMDAC %04X %04X:%04X\n",addr,CS,pc); //if (CS!=0xC000) pclog("IN RAMDAC %04X %04X:%04X\n",addr,CS,pc);
switch (addr) switch (addr)
{ {
case 0x3C6: case 0x3c6:
switch (stg_ramdac.magic_count) switch (ramdac->magic_count)
{ {
case 0: case 1: case 2: case 3: temp=0xFF; break; case 0: case 1: case 2: case 3:
case 4: temp=stg_ramdac.command; break; temp = 0xff;
case 5: temp=stg_ramdac.index&0xFF; break; break;
case 6: temp=stg_ramdac.index>>8; break; case 4:
temp = ramdac->command;
break;
case 5:
temp = ramdac->index & 0xff;
break;
case 6:
temp = ramdac->index >> 8;
break;
case 7: case 7:
// pclog("Read RAMDAC index %04X\n",stg_ramdac.index); // pclog("Read RAMDAC index %04X\n",stg_ramdac.index);
switch (stg_ramdac.index) switch (ramdac->index)
{ {
case 0: temp=0x44; break; case 0:
case 1: temp=0x02; break; temp = 0x44;
break;
case 1:
temp = 0x02;
break;
default: default:
if (stg_ramdac.index<0x100) temp=stg_ramdac.regs[stg_ramdac.index]; if (ramdac->index < 0x100) temp = ramdac->regs[ramdac->index];
else temp=0xFF; else temp = 0xff;
break; break;
} }
stg_ramdac.index++; ramdac->index++;
break; 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; return temp;
case 0x3C8: case 0x3C9: case 0x3c8: case 0x3c9:
stg_ramdac.magic_count=0; ramdac->magic_count=0;
break; 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); typedef struct stg_ramdac_t
uint8_t stg_ramdac_in(uint16_t addr, void *priv); {
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*/ typedef struct svga_t
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
{ {
int ena; uint8_t crtcreg;
int x, y; uint8_t crtc[128];
int xoff, yoff; uint8_t gdcreg[16];
uint32_t addr; int gdcaddr;
} SVGA_HWCURSOR; 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 int svga_hwcursor_on;
extern void (*svga_hwcursor_draw)(int displine); extern void (*svga_hwcursor_draw)(int displine);
uint8_t svga_read(uint32_t addr, void *priv); uint8_t svga_read(uint32_t addr, void *p);
uint16_t svga_readw(uint32_t addr, void *priv); uint16_t svga_readw(uint32_t addr, void *p);
uint32_t svga_readl(uint32_t addr, void *priv); uint32_t svga_readl(uint32_t addr, void *p);
void svga_write(uint32_t addr, uint8_t val, void *priv); void svga_write(uint32_t addr, uint8_t val, void *p);
void svga_writew(uint32_t addr, uint16_t val, void *priv); void svga_writew(uint32_t addr, uint16_t val, void *p);
void svga_writel(uint32_t addr, uint32_t val, void *priv); void svga_writel(uint32_t addr, uint32_t val, void *p);
uint8_t svga_read_linear(uint32_t addr, void *priv); uint8_t svga_read_linear(uint32_t addr, void *p);
uint16_t svga_readw_linear(uint32_t addr, void *priv); uint16_t svga_readw_linear(uint32_t addr, void *p);
uint32_t svga_readl_linear(uint32_t addr, void *priv); uint32_t svga_readl_linear(uint32_t addr, void *p);
void svga_write_linear(uint32_t addr, uint8_t val, void *priv); void svga_write_linear(uint32_t addr, uint8_t val, void *p);
void svga_writew_linear(uint32_t addr, uint16_t val, void *priv); void svga_writew_linear(uint32_t addr, uint16_t val, void *p);
void svga_writel_linear(uint32_t addr, uint32_t val, void *priv); void svga_writel_linear(uint32_t addr, uint32_t val, void *p);
void svga_doblit(int y1, int y2); int svga_add_status_info(char *s, int max_len, void *p);
extern uint32_t svga_vram_limit;
extern uint8_t svga_rotate[8][256]; extern uint8_t svga_rotate[8][256];
void svga_out(uint16_t addr, uint8_t val, void *priv); void svga_out(uint16_t addr, uint8_t val, void *p);
uint8_t svga_in(uint16_t addr, void *priv); uint8_t svga_in(uint16_t addr, void *p);

View file

@ -3,36 +3,39 @@
#include "vid_svga.h" #include "vid_svga.h"
#include "vid_svga_render.h" #include "vid_svga_render.h"
void svga_render_blank() void svga_render_blank(svga_t *svga)
{ {
int x, xx; int x, xx;
if (firstline_draw == 2000) firstline_draw = displine; if (svga->firstline_draw == 2000)
lastline_draw = displine; svga->firstline_draw = svga->displine;
for (x=0;x<svga_hdisp;x++) svga->lastline_draw = svga->displine;
for (x = 0; x < svga->hdisp; x++)
{ {
switch (seqregs[1]&9) switch (svga->seqregs[1] & 9)
{ {
case 0: 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; break;
case 1: 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; break;
case 8: 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; break;
case 9: 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; break;
} }
} }
} }
void svga_render_text_40() void svga_render_text_40(svga_t *svga)
{ {
if (firstline_draw == 2000) firstline_draw = displine; if (svga->firstline_draw == 2000)
lastline_draw = displine; svga->firstline_draw = svga->displine;
svga->lastline_draw = svga->displine;
if (fullchange) if (fullchange)
{ {
@ -41,56 +44,59 @@ void svga_render_text_40()
uint8_t chr, attr, dat; uint8_t chr, attr, dat;
uint32_t charaddr; uint32_t charaddr;
int fg, bg; 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); drawcursor = ((svga->ma == svga->ca) && svga->con && svga->cursoron);
chr=vram[(ma<<1)]; chr = svga->vram[(svga->ma << 1) & svga->vrammask];
attr=vram[(ma<<1)+4]; attr = svga->vram[((svga->ma << 1) + 4) & svga->vrammask];
if (attr&8) charaddr=charsetb+(chr*128); if (attr & 8) charaddr = svga->charsetb + (chr * 128);
else charaddr=charseta+(chr*128); else charaddr = svga->charseta + (chr * 128);
if (drawcursor) if (drawcursor)
{ {
bg=pallook[egapal[attr&15]]; bg = svga->pallook[svga->egapal[attr & 15]];
fg=pallook[egapal[attr>>4]]; fg = svga->pallook[svga->egapal[attr >> 4]];
} }
else else
{ {
fg=pallook[egapal[attr&15]]; fg = svga->pallook[svga->egapal[attr & 15]];
bg=pallook[egapal[attr>>4]]; bg = svga->pallook[svga->egapal[attr >> 4]];
if (attr&0x80 && attrregs[0x10]&8) if (attr & 0x80 && svga->attrregs[0x10] & 8)
{ {
bg=pallook[egapal[(attr>>4)&7]]; bg = svga->pallook[svga->egapal[(attr >> 4) & 7]];
if (cgablink&16) fg=bg; if (svga->blink & 16)
fg = bg;
} }
} }
dat=vram[charaddr+(sc<<2)]; dat = svga->vram[charaddr + (svga->sc << 2)];
if (seqregs[1]&1) if (svga->seqregs[1] & 1)
{ {
for (xx=0;xx<8;xx++) 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; ((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 else
{ {
for (xx=0;xx<8;xx++) 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; ((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 || !(attrregs[0x10]&4)) if ((chr & ~0x1F) != 0xC0 || !(svga->attrregs[0x10] & 4))
((uint32_t *)buffer32->line[displine])[(x+32+16)&2047]=((uint32_t *)buffer32->line[displine])[(x+32+17)&2047]=bg; ((uint32_t *)buffer32->line[svga->displine])[(x + 32 + 16) & 2047] = ((uint32_t *)buffer32->line[svga->displine])[(x + 32 + 17) & 2047] = bg;
else 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; if (svga->firstline_draw == 2000)
lastline_draw = displine; svga->firstline_draw = svga->displine;
svga->lastline_draw = svga->displine;
if (fullchange) if (fullchange)
{ {
@ -99,388 +105,415 @@ void svga_render_text_80()
uint8_t chr, attr, dat; uint8_t chr, attr, dat;
uint32_t charaddr; uint32_t charaddr;
int fg, bg; 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); drawcursor = ((svga->ma == svga->ca) && svga->con && svga->cursoron);
chr=vram[(ma<<1)]; chr = svga->vram[(svga->ma << 1) & svga->vrammask];
attr=vram[(ma<<1)+4]; attr = svga->vram[((svga->ma << 1) + 4) & svga->vrammask];
if (attr&8) charaddr=charsetb+(chr*128); if (attr & 8) charaddr = svga->charsetb + (chr * 128);
else charaddr=charseta+(chr*128); else charaddr = svga->charseta + (chr * 128);
if (drawcursor) if (drawcursor)
{ {
bg=pallook[egapal[attr&15]]; bg = svga->pallook[svga->egapal[attr & 15]];
fg=pallook[egapal[attr>>4]]; fg = svga->pallook[svga->egapal[attr >> 4]];
} }
else else
{ {
fg=pallook[egapal[attr&15]]; fg = svga->pallook[svga->egapal[attr & 15]];
bg=pallook[egapal[attr>>4]]; bg = svga->pallook[svga->egapal[attr >> 4]];
if (attr&0x80 && attrregs[0x10]&8) if (attr & 0x80 && svga->attrregs[0x10] & 8)
{ {
bg=pallook[egapal[(attr>>4)&7]]; bg = svga->pallook[svga->egapal[(attr >> 4) & 7]];
if (cgablink&16) fg=bg; if (svga->blink & 16)
fg = bg;
} }
} }
dat=vram[charaddr+(sc<<2)]; dat = svga->vram[charaddr + (svga->sc << 2)];
if (seqregs[1]&1) if (svga->seqregs[1] & 1)
{ {
for (xx=0;xx<8;xx++) for (xx = 0; xx < 8; xx++)
((uint32_t *)buffer32->line[displine])[(x+32+xx)&2047]=(dat&(0x80>>xx))?fg:bg; ((uint32_t *)buffer32->line[svga->displine])[(x + 32 + xx) & 2047] = (dat & (0x80 >> xx)) ? fg : bg;
} }
else else
{ {
for (xx=0;xx<8;xx++) for (xx = 0; xx < 8; xx++)
((uint32_t *)buffer32->line[displine])[(x+32+xx)&2047]=(dat&(0x80>>xx))?fg:bg; ((uint32_t *)buffer32->line[svga->displine])[(x + 32 + xx) & 2047] = (dat & (0x80 >> xx)) ? fg : bg;
if ((chr&~0x1F)!=0xC0 || !(attrregs[0x10]&4)) if ((chr & ~0x1F) != 0xC0 || !(svga->attrregs[0x10] & 4))
((uint32_t *)buffer32->line[displine])[(x+32+8)&2047]=bg; ((uint32_t *)buffer32->line[svga->displine])[(x + 32 + 8) & 2047] = bg;
else 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; int x, offset;
uint8_t edat[4], dat; uint8_t edat[4], dat;
if (firstline_draw == 2000) firstline_draw = displine; if (svga->firstline_draw == 2000)
lastline_draw = displine; svga->firstline_draw = svga->displine;
svga->lastline_draw = svga->displine;
offset=((8-scrollcache)<<1)+16; offset = ((8 - svga->scrollcache) << 1) + 16;
for (x = 0; x <= svga_hdisp; x += 16) for (x = 0; x <= svga->hdisp; x += 16)
{ {
edat[0]=vram[ma]; edat[0] = svga->vram[svga->ma];
edat[1]=vram[ma|0x1]; edat[1] = svga->vram[svga->ma | 0x1];
edat[2]=vram[ma|0x2]; edat[2] = svga->vram[svga->ma | 0x2];
edat[3]=vram[ma|0x3]; edat[3] = svga->vram[svga->ma | 0x3];
ma+=4; ma&=vrammask; svga->ma += 4;
svga->ma &= svga->vrammask;
dat=edatlookup[edat[0]&3][edat[1]&3]|(edatlookup[edat[2]&3][edat[3]&3]<<2); 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[svga->displine])[x + 14 + offset] = ((uint32_t *)buffer32->line[svga->displine])[x + 15 + offset] = svga->pallook[svga->egapal[dat & 0xf]];
((uint32_t *)buffer32->line[displine])[x+12+offset]=((uint32_t *)buffer32->line[displine])[x+13+offset]=pallook[egapal[dat>>4]]; ((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); 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[svga->displine])[x + 10 + offset] = ((uint32_t *)buffer32->line[svga->displine])[x + 11 + offset] = svga->pallook[svga->egapal[dat & 0xf]];
((uint32_t *)buffer32->line[displine])[x+8+offset]= ((uint32_t *)buffer32->line[displine])[x+9+offset]=pallook[egapal[dat>>4]]; ((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); 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[svga->displine])[x + 6 + offset] = ((uint32_t *)buffer32->line[svga->displine])[x + 7 + offset] = svga->pallook[svga->egapal[dat & 0xf]];
((uint32_t *)buffer32->line[displine])[x+4+offset]= ((uint32_t *)buffer32->line[displine])[x+5+offset]=pallook[egapal[dat>>4]]; ((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); 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[svga->displine])[x + 2 + offset] = ((uint32_t *)buffer32->line[svga->displine])[x + 3 + offset] = svga->pallook[svga->egapal[dat & 0xf]];
((uint32_t *)buffer32->line[displine])[x+offset]= ((uint32_t *)buffer32->line[displine])[x+1+offset]=pallook[egapal[dat>>4]]; ((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; int x, offset;
uint8_t edat[4], dat; uint8_t edat[4], dat;
if (firstline_draw == 2000) firstline_draw = displine; if (svga->firstline_draw == 2000)
lastline_draw = displine; svga->firstline_draw = svga->displine;
svga->lastline_draw = svga->displine;
offset=(8-scrollcache)+24; offset = (8 - svga->scrollcache) + 24;
for (x = 0; x <= svga_hdisp; x += 8) for (x = 0; x <= svga->hdisp; x += 8)
{ {
edat[0]=vram[ma]; edat[0] = svga->vram[svga->ma];
edat[1]=vram[ma|0x1]; edat[1] = svga->vram[svga->ma | 0x1];
edat[2]=vram[ma|0x2]; edat[2] = svga->vram[svga->ma | 0x2];
edat[3]=vram[ma|0x3]; edat[3] = svga->vram[svga->ma | 0x3];
ma+=4; ma&=vrammask; svga->ma += 4;
svga->ma &= svga->vrammask;
dat=edatlookup[edat[0]&3][edat[1]&3]|(edatlookup[edat[2]&3][edat[3]&3]<<2); 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[svga->displine])[x + 7 + offset] = svga->pallook[svga->egapal[dat & 0xf]];
((uint32_t *)buffer32->line[displine])[x+6+offset]=pallook[egapal[dat>>4]]; ((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); 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[svga->displine])[x + 5 + offset] = svga->pallook[svga->egapal[dat & 0xf]];
((uint32_t *)buffer32->line[displine])[x+4+offset]=pallook[egapal[dat>>4]]; ((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); 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[svga->displine])[x + 3 + offset] = svga->pallook[svga->egapal[dat & 0xf]];
((uint32_t *)buffer32->line[displine])[x+2+offset]=pallook[egapal[dat>>4]]; ((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); 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[svga->displine])[x + 1 + offset] = svga->pallook[svga->egapal[dat & 0xf]];
((uint32_t *)buffer32->line[displine])[x+offset]= pallook[egapal[dat>>4]]; ((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; int x, offset;
uint8_t edat[4], dat; uint8_t edat[2], dat;
if (firstline_draw == 2000) firstline_draw = displine; if (svga->firstline_draw == 2000)
lastline_draw = displine; svga->firstline_draw = svga->displine;
offset=((8-scrollcache)<<1)+16; svga->lastline_draw = svga->displine;
offset = ((8 - svga->scrollcache) << 1) + 16;
/*Low res (320) only, though high res (640) should be possible*/ /*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[0] = svga->vram[(svga->ma << 1) + 0x8000];
edat[1]=vram[(ma<<1)+0x8004]; edat[1] = svga->vram[(svga->ma << 1) + 0x8004];
} }
else else
{ {
edat[0]=vram[(ma<<1)]; edat[0] = svga->vram[(svga->ma << 1)];
edat[1]=vram[(ma<<1)+4]; 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[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[displine])[x+12+offset]=((uint32_t *)buffer32->line[displine])[x+13+offset]=pallook[egapal[(edat[1]>>2)&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]];
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[(edat[1] >> 4) & 3]];
((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[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[displine])[x+8+offset]= ((uint32_t *)buffer32->line[displine])[x+9+offset]=pallook[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]];
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 + 4 + offset] = ((uint32_t *)buffer32->line[svga->displine])[x + 5 + offset] = svga->pallook[svga->egapal[(edat[0] >> 2) & 3]];
((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[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[displine])[x+4+offset]= ((uint32_t *)buffer32->line[displine])[x+5+offset]=pallook[egapal[(edat[0]>>2)&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]];
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]];
} }
} }
void svga_render_8bpp_lowres() void svga_render_8bpp_lowres(svga_t *svga)
{ {
int x, offset; int x, offset;
uint8_t edat[4]; 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; if (svga->firstline_draw == 2000)
lastline_draw = displine; 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[0] = svga->vram[svga->ma];
edat[1]=vram[ma|0x1]; edat[1] = svga->vram[svga->ma | 0x1];
edat[2]=vram[ma|0x2]; edat[2] = svga->vram[svga->ma | 0x2];
edat[3]=vram[ma|0x3]; edat[3] = svga->vram[svga->ma | 0x3];
ma+=4; ma&=vrammask; svga->ma += 4;
((uint32_t *)buffer32->line[displine])[x+6+offset]= ((uint32_t *)buffer32->line[displine])[x+7+offset]=pallook[edat[3]]; svga->ma &= svga->vrammask;
((uint32_t *)buffer32->line[displine])[x+4+offset]= ((uint32_t *)buffer32->line[displine])[x+5+offset]=pallook[edat[2]]; ((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[displine])[x+2+offset]= ((uint32_t *)buffer32->line[displine])[x+3+offset]=pallook[edat[1]]; ((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[displine])[x+offset]= ((uint32_t *)buffer32->line[displine])[x+1+offset]=pallook[edat[0]]; ((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; int x, offset;
uint8_t edat[4]; 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; if (svga->firstline_draw == 2000)
lastline_draw = displine; 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[0] = svga->vram[svga->ma];
edat[1]=vram[ma|0x1]; edat[1] = svga->vram[svga->ma | 0x1];
edat[2]=vram[ma|0x2]; edat[2] = svga->vram[svga->ma | 0x2];
edat[3]=vram[ma|0x3]; edat[3] = svga->vram[svga->ma | 0x3];
ma+=4; ma&=vrammask; svga->ma += 4;
((uint32_t *)buffer32->line[displine])[x+3+offset] = pallook[edat[3]]; svga->ma &= svga->vrammask;
((uint32_t *)buffer32->line[displine])[x+2+offset] = pallook[edat[2]]; ((uint32_t *)buffer32->line[svga->displine])[x + 3 + offset] = svga->pallook[edat[3]];
((uint32_t *)buffer32->line[displine])[x+1+offset] = pallook[edat[1]]; ((uint32_t *)buffer32->line[svga->displine])[x + 2 + offset] = svga->pallook[edat[2]];
((uint32_t *)buffer32->line[displine])[x+offset] = pallook[edat[0]]; ((uint32_t *)buffer32->line[svga->displine])[x + 1 + offset] = svga->pallook[edat[1]];
edat[0]=vram[ma]; ((uint32_t *)buffer32->line[svga->displine])[x + offset] = svga->pallook[edat[0]];
edat[1]=vram[ma|0x1];
edat[2]=vram[ma|0x2]; edat[0] = svga->vram[svga->ma];
edat[3]=vram[ma|0x3]; edat[1] = svga->vram[svga->ma | 0x1];
ma+=4; ma&=vrammask; edat[2] = svga->vram[svga->ma | 0x2];
((uint32_t *)buffer32->line[displine])[x+7+offset] = pallook[edat[3]]; edat[3] = svga->vram[svga->ma | 0x3];
((uint32_t *)buffer32->line[displine])[x+6+offset] = pallook[edat[2]]; svga->ma += 4;
((uint32_t *)buffer32->line[displine])[x+5+offset] = pallook[edat[1]]; svga->ma &= svga->vrammask;
((uint32_t *)buffer32->line[displine])[x+4+offset] = pallook[edat[0]]; ((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; int x, offset;
uint16_t fg, bg; 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; if (svga->firstline_draw == 2000)
lastline_draw = displine; 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); fg = svga->vram[svga->ma] | (svga->vram[svga->ma | 0x1] << 8);
bg=vram[ma|0x2]|(vram[ma|0x3]<<8); bg = svga->vram[svga->ma | 0x2] | (svga->vram[svga->ma | 0x3] << 8);
ma+=4; ma&=vrammask; svga->ma += 4;
((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); svga->ma &= svga->vrammask;
((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); ((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; int x, offset;
uint16_t fg, bg; 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; if (svga->firstline_draw == 2000)
lastline_draw = displine; 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); fg = svga->vram[svga->ma] | (svga->vram[svga->ma | 0x1] << 8);
bg=vram[ma|0x2]|(vram[ma|0x3]<<8); bg = svga->vram[svga->ma | 0x2] | (svga->vram[svga->ma | 0x3] << 8);
ma+=4; ma&=vrammask; svga->ma += 4;
((uint32_t *)buffer32->line[displine])[x + 1 + offset] = ((bg&31)<<3)|(((bg>>5)&31)<<11)|(((bg>>10)&31)<<19); svga->ma &= svga->vrammask;
((uint32_t *)buffer32->line[displine])[x + 0 + offset] = ((fg&31)<<3)|(((fg>>5)&31)<<11)|(((fg>>10)&31)<<19); ((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() void svga_render_24bpp_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 (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()
{ {
int x, offset; int x, offset;
uint32_t fg; 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; if (svga->firstline_draw == 2000)
lastline_draw = displine; 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); fg = svga->vram[svga->ma] | (svga->vram[svga->ma + 1] << 8) | (svga->vram[svga->ma + 2] << 16);
ma+=3; ma&=vrammask; svga->ma += 3;
((uint32_t *)buffer32->line[displine])[(x<<1)+offset]=((uint32_t *)buffer32->line[displine])[(x<<1)+1+offset]=fg; 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; int x, offset;
uint32_t fg; 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; if (svga->firstline_draw == 2000)
lastline_draw = displine; 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); fg = svga->vram[svga->ma] | (svga->vram[svga->ma + 1] << 8) | (svga->vram[svga->ma + 2] << 16);
ma+=3; ma&=vrammask; svga->ma += 3;
((uint32_t *)buffer32->line[displine])[x + offset] = fg; 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; int x, offset;
uint32_t fg; 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; if (svga->firstline_draw == 2000)
lastline_draw = displine; 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); fg = svga->vram[svga->ma] | (svga->vram[svga->ma + 1] << 8) | (svga->vram[svga->ma + 2] << 16);
ma += 4; ma &= vrammask; svga->ma += 4;
((uint32_t *)buffer32->line[displine])[(x << 1) + offset] = ((uint32_t *)buffer32->line[displine])[(x << 1) + 1 + offset] = fg; 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; int x, offset;
uint32_t fg; 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; if (svga->firstline_draw == 2000)
lastline_draw = displine; 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); fg = svga->vram[svga->ma] | (svga->vram[svga->ma + 1] << 8) | (svga->vram[svga->ma + 2] << 16);
ma+=4; ma&=vrammask; svga->ma += 4;
((uint32_t *)buffer32->line[displine])[x + offset] = fg; 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]; extern uint8_t edatlookup[4][4];
void svga_render_blank(); void svga_render_blank(svga_t *svga);
void svga_render_text_40(); void svga_render_text_40(svga_t *svga);
void svga_render_text_80(); void svga_render_text_80(svga_t *svga);
void svga_render_2bpp_lowres(); void svga_render_2bpp_lowres(svga_t *svga);
void svga_render_4bpp_lowres(); void svga_render_4bpp_lowres(svga_t *svga);
void svga_render_4bpp_highres(); void svga_render_4bpp_highres(svga_t *svga);
void svga_render_8bpp_lowres(); void svga_render_8bpp_lowres(svga_t *svga);
void svga_render_8bpp_highres(); void svga_render_8bpp_highres(svga_t *svga);
void svga_render_15bpp_lowres(); void svga_render_15bpp_lowres(svga_t *svga);
void svga_render_15bpp_highres(); void svga_render_15bpp_highres(svga_t *svga);
void svga_render_16bpp_lowres(); void svga_render_16bpp_lowres(svga_t *svga);
void svga_render_16bpp_highres(); void svga_render_16bpp_highres(svga_t *svga);
void svga_render_24bpp_lowres(); void svga_render_24bpp_lowres(svga_t *svga);
void svga_render_24bpp_highres(); void svga_render_24bpp_highres(svga_t *svga);
void svga_render_32bpp_lowres(); void svga_render_32bpp_lowres(svga_t *svga);
void svga_render_32bpp_highres(); 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 int tkd8001_state=0;
static uint8_t tkd8001_ctrl; 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); // pclog("OUT RAMDAC %04X %02X %04X:%04X\n",addr,val,CS,pc);
switch (addr) switch (addr)
{ {
case 0x3C6: case 0x3C6:
if (tkd8001_state == 4) if (ramdac->state == 4)
{ {
tkd8001_state = 0; ramdac->state = 0;
tkd8001_ctrl = val; ramdac->ctrl = val;
switch (val>>5) switch (val >> 5)
{ {
case 0: case 1: case 2: case 3: case 0: case 1: case 2: case 3:
bpp = 8; svga->bpp = 8;
break; break;
case 5: case 5:
bpp = 15; svga->bpp = 15;
break; break;
case 6: case 6:
bpp = 24; svga->bpp = 24;
break; break;
case 7: case 7:
bpp = 16; svga->bpp = 16;
break; break;
} }
return; return;
@ -37,28 +37,28 @@ void tkd8001_ramdac_out(uint16_t addr, uint8_t val, void *priv)
// tkd8001_state = 0; // tkd8001_state = 0;
break; break;
case 0x3C7: case 0x3C8: case 0x3C9: case 0x3C7: case 0x3C8: case 0x3C9:
tkd8001_state = 0; ramdac->state = 0;
break; 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); // pclog("IN RAMDAC %04X %04X:%04X\n",addr,CS,pc);
switch (addr) switch (addr)
{ {
case 0x3C6: case 0x3C6:
if (tkd8001_state == 4) if (ramdac->state == 4)
{ {
//tkd8001_state = 0; //tkd8001_state = 0;
return tkd8001_ctrl; return ramdac->ctrl;
} }
tkd8001_state++; ramdac->state++;
break; break;
case 0x3C7: case 0x3C8: case 0x3C9: case 0x3C7: case 0x3C8: case 0x3C9:
tkd8001_state = 0; ramdac->state = 0;
break; 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); typedef struct tkd8001_ramdac_t
uint8_t tkd8001_ramdac_in(uint16_t addr, void *priv); {
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_svga.h"
#include "vid_unk_ramdac.h" #include "vid_unk_ramdac.h"
static int unk_state=0; void unk_ramdac_out(uint16_t addr, uint8_t val, unk_ramdac_t *ramdac, svga_t *svga)
static uint8_t unk_ctrl;
void unk_ramdac_out(uint16_t addr, uint8_t val, void *priv)
{ {
//pclog("OUT RAMDAC %04X %02X\n",addr,val); //pclog("OUT RAMDAC %04X %02X\n",addr,val);
switch (addr) switch (addr)
{ {
case 0x3C6: case 0x3C6:
if (unk_state == 4) if (ramdac->state == 4)
{ {
unk_state = 0; ramdac->state = 0;
unk_ctrl = val; ramdac->ctrl = val;
switch ((val&1)|((val&0xE0)>>4)) switch ((val&1)|((val&0xE0)>>4))
{ {
case 0: case 1: case 2: case 3: case 0: case 1: case 2: case 3:
bpp = 8; svga->bpp = 8;
break; break;
case 6: case 7: case 6: case 7:
bpp = 24; svga->bpp = 24;
break; break;
case 8: case 9: case 0xA: case 0xB: case 8: case 9: case 0xA: case 0xB:
bpp = 15; svga->bpp = 15;
break; break;
case 0xC: case 0xD: case 0xE: case 0xF: case 0xC: case 0xD: case 0xE: case 0xF:
bpp = 16; svga->bpp = 16;
break; break;
} }
return; return;
} }
unk_state = 0; ramdac->state = 0;
break; break;
case 0x3C7: case 0x3C8: case 0x3C9: case 0x3C7: case 0x3C8: case 0x3C9:
unk_state = 0; ramdac->state = 0;
break; 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); //pclog("IN RAMDAC %04X\n",addr);
switch (addr) switch (addr)
{ {
case 0x3C6: case 0x3C6:
if (unk_state == 4) if (ramdac->state == 4)
{ {
unk_state = 0; ramdac->state = 0;
return unk_ctrl; return ramdac->ctrl;
} }
unk_state++; ramdac->state++;
break; break;
case 0x3C7: case 0x3C8: case 0x3C9: case 0x3C7: case 0x3C8: case 0x3C9:
unk_state = 0; ramdac->state = 0;
break; 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); typedef struct unk_ramdac_t
uint8_t unk_ramdac_in(uint16_t addr, void *priv); {
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*/ /*IBM VGA emulation*/
#include <stdlib.h>
#include "ibm.h" #include "ibm.h"
#include "device.h"
#include "io.h" #include "io.h"
#include "video.h" #include "video.h"
#include "vid_svga.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; uint8_t old;
pclog("vga_out : %04X %02X %04X:%04X %02X %i\n", addr, val, CS,pc, ram[0x489], ins); 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) switch (addr)
{ {
case 0x3D4: case 0x3D4:
crtcreg = val & 0x1f; svga->crtcreg = val & 0x1f;
return; return;
case 0x3D5: case 0x3D5:
if (crtcreg <= 7 && crtc[0x11] & 0x80) return; if (svga->crtcreg <= 7 && svga->crtc[0x11] & 0x80) return;
old=crtc[crtcreg]; old = svga->crtc[svga->crtcreg];
crtc[crtcreg]=val; 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; fullchange = changeframecount;
svga_recalctimings(); svga_recalctimings(svga);
} }
} }
break; 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; uint8_t temp;
if (addr != 0x3da) pclog("vga_in : %04X ", addr); 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) switch (addr)
{ {
case 0x3D4: case 0x3D4:
temp = crtcreg; temp = svga->crtcreg;
break; break;
case 0x3D5: case 0x3D5:
temp = crtc[crtcreg]; temp = svga->crtc[svga->crtcreg];
break; break;
default: default:
temp = svga_in(addr, NULL); temp = svga_in(addr, svga);
break; break;
} }
if (addr != 0x3da) pclog("%02X %04X:%04X\n", temp, CS,pc); if (addr != 0x3da) pclog("%02X %04X:%04X\n", temp, CS,pc);
return temp; return temp;
} }
int vga_init() void *vga_init()
{ {
svga_recalctimings_ex = NULL; vga_t *vga = malloc(sizeof(vga_t));
svga_vram_limit = 1 << 18; /*256kb*/ memset(vga, 0, sizeof(vga_t));
vrammask = 0x3ffff;
svgawbank = svgarbank = 0; svga_init(&vga->svga, vga, 1 << 18, /*256kb*/
bpp = 8; NULL,
svga_miscout = 1; vga_in, vga_out,
return svga_init(); 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, vga_init,
/*IO at 3Cx/3Dx*/ vga_close,
vga_out, vga_speed_changed,
vga_in, svga_add_status_info
/*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
}; };

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 <stdio.h>
#include <math.h> #include <math.h>
#include "ibm.h" #include "ibm.h"
#include "device.h"
#include "video.h" #include "video.h"
#include "vid_svga.h" #include "vid_svga.h"
#include "io.h" #include "io.h"
#include "cpu.h" #include "cpu.h"
#include "timer.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 - /*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)(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_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() void video_init()
{ {
pclog("Video_init %i %i\n",romset,gfxcard); pclog("Video_init %i %i\n",romset,gfxcard);
@ -155,107 +123,108 @@ void video_init()
switch (romset) switch (romset)
{ {
case ROM_TANDY: case ROM_TANDY:
video_load(vid_tandy); device_add(&tandy_device);
return; return;
case ROM_PC1512: case ROM_PC1512:
video_load(vid_pc1512); device_add(&pc1512_device);
return; return;
case ROM_PC1640: case ROM_PC1640:
video_load(vid_pc1640); device_add(&pc1640_device);
return; return;
case ROM_PC200: case ROM_PC200:
video_load(vid_pc200); device_add(&pc200_device);
return; return;
case ROM_OLIM24: case ROM_OLIM24:
video_load(vid_m24); device_add(&m24_device);
return; return;
case ROM_PC2086: case ROM_PC2086:
case ROM_PC3086: case ROM_PC3086:
device_add(&paradise_pvga1a_device);
return;
case ROM_MEGAPC: case ROM_MEGAPC:
video_load(vid_paradise); device_add(&paradise_wd90c11_device);
return; return;
case ROM_ACER386: case ROM_ACER386:
video_load(vid_oti067); device_add(&oti067_device);
return; return;
} }
switch (gfxcard) switch (gfxcard)
{ {
case GFX_MDA: case GFX_MDA:
video_load(vid_mda); device_add(&mda_device);
break; break;
case GFX_HERCULES: case GFX_HERCULES:
video_load(vid_hercules); device_add(&hercules_device);
break; break;
case GFX_CGA: case GFX_CGA:
video_load(vid_cga); device_add(&cga_device);
break; break;
case GFX_EGA: case GFX_EGA:
video_load(vid_ega); device_add(&ega_device);
break; break;
case GFX_TVGA: case GFX_TVGA:
video_load(vid_tvga); device_add(&tvga8900d_device);
break; break;
case GFX_ET4000: case GFX_ET4000:
video_load(vid_et4000); device_add(&et4000_device);
break; break;
case GFX_ET4000W32: case GFX_ET4000W32:
video_load(vid_et4000w32p); device_add(&et4000w32p_device);
break; break;
case GFX_BAHAMAS64: case GFX_BAHAMAS64:
video_load(vid_s3); device_add(&s3_bahamas64_device);
break; break;
case GFX_N9_9FX: case GFX_N9_9FX:
video_load(vid_s3); device_add(&s3_9fx_device);
break; break;
case GFX_STEALTH64: case GFX_STEALTH64:
video_load(vid_s3);
break; break;
case GFX_VIRGE: case GFX_VIRGE:
video_load(vid_s3_virge); device_add(&s3_virge_device);
break; break;
case GFX_TGUI9440: case GFX_TGUI9440:
video_load(vid_tgui9440); device_add(&tgui9440_device);
break; break;
case GFX_VGA: case GFX_VGA:
video_load(vid_vga); device_add(&vga_device);
break; break;
case GFX_VGAEDGE16: case GFX_VGAEDGE16:
video_load(vid_ati18800); device_add(&ati18800_device);
break; break;
case GFX_VGACHARGER: case GFX_VGACHARGER:
video_load(vid_ati28800); device_add(&ati18800_device);
break; break;
case GFX_OTI067: case GFX_OTI067:
video_load(vid_oti067); device_add(&oti067_device);
return; return;
case GFX_MACH64GX: case GFX_MACH64GX:
video_load(vid_mach64); device_add(&mach64gx_device);
return; return;
case GFX_CL_GD5429: case GFX_CL_GD5429:
video_load(vid_gd5429); device_add(&gd5429_device);
return; return;
default: default:
@ -263,78 +232,26 @@ void video_init()
} }
} }
uint32_t cga32[256];
BITMAP *buffer,*vbuf;//,*vbuf2; BITMAP *buffer, *buffer32;
BITMAP *buffer32;
int speshul=0;
uint8_t fontdat[256][8]; uint8_t fontdat[256][8];
uint8_t fontdatm[256][16]; 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 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, 0},{0,42,0},{42,0,0},{42,21,0},
{0,0,1,1,1,1,0,0}, /*Blue*/ { 0, 0, 0},{0,42,42},{42,0,42},{42,42,42},
{1,0,0,0,0,1,1,1}, /*Green*/ { 0, 0, 0},{21,63,21},{63,21,21},{63,63,21},
{0,0,0,0,1,1,1,1}, /*Cyan*/ { 0, 0, 0},{21,63,63},{63,21,63},{63,63,63},
{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, 0, 42}, { 0, 42, 0}, { 0, 42, 42},
extern int fullchange; {42, 0, 0}, {42, 0, 42}, {42, 21, 00}, {42, 42, 42},
{21, 21, 21}, {21, 21, 63}, {21, 63, 21}, {21, 63, 63},
extern uint32_t vrammask; {63, 21, 21}, {63, 21, 63}, {63, 63, 21}, {63, 63, 63},
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,21,0},{0,0,42},{0,42,42}, {0,0,0},{0,21,0},{0,0,42},{0,42,42},
{42,0,21},{21,10,21},{42,0,42},{42,0,63}, {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,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},
{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) 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() void initvideo()
{ {
int c; int c, d, e;
// 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;
}
void resetvideo() buffer32 = create_bitmap(2048, 2048);
{
int c;
if (MDA && !TANDY && !AMSTRAD && romset!=ROM_PC200) updatewindowsize(720,350);
else updatewindowsize(656,416);
cgastat=0;
set_palette(cgapal);
for (c=18;c<64;c++) crtcmask[c]=0xFF; buffer = create_bitmap(2048, 2048);
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;
cgacol=7; for (c = 0; c < 64; c++)
for (c=0;c<256;c++)
{ {
mdacols[c][0][0]=mdacols[c][1][0]=mdacols[c][1][1]=16; cgapal[c + 64].r = (((c & 4) ? 2 : 0) | ((c & 0x10) ? 1 : 0)) * 21;
if (c&8) mdacols[c][0][1]=15+16; cgapal[c + 64].g = (((c & 2) ? 2 : 0) | ((c & 0x10) ? 1 : 0)) * 21;
else mdacols[c][0][1]=7+16; 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() void closevideo()
{ {
destroy_bitmap(buffer); destroy_bitmap(buffer);
destroy_bitmap(vbuf);
} }

View file

@ -1,70 +1,8 @@
extern int egareads,egawrites; 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 fullchange;
extern int changeframecount; 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 typedef struct
{ {
int w, h; int w, h;
@ -72,73 +10,23 @@ typedef struct
uint8_t *line[0]; uint8_t *line[0];
} BITMAP; } BITMAP;
extern BITMAP *buffer,*buffer32,*vbuf; extern BITMAP *buffer, *buffer32;
extern BITMAP *screen; extern BITMAP *screen;
BITMAP *create_bitmap(int w, int h); BITMAP *create_bitmap(int w, int h);
extern int wx,wy;
extern uint8_t fontdat[256][8]; extern uint8_t fontdat[256][8];
extern uint8_t fontdatm[256][16]; extern uint8_t fontdatm[256][16];
extern int xsize,ysize; extern int xsize,ysize;
extern int dacread,dacwrite,dacpos;
typedef struct typedef struct
{ {
uint8_t r, g, b; uint8_t r, g, b;
} RGB; } RGB;
typedef RGB PALETTE[256]; 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; 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)(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 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_timing_b, video_timing_w, video_timing_l;
extern int video_speed; extern int video_speed;

View file

@ -377,6 +377,9 @@ int WINAPI WinMain (HINSTANCE hThisInstance,
} }
} }
} }
loadbios();
timeBeginPeriod(1); timeBeginPeriod(1);
// soundobject=CreateEvent(NULL, FALSE, FALSE, NULL); // soundobject=CreateEvent(NULL, FALSE, FALSE, NULL);
// soundthreadh=CreateThread(NULL,0,soundthread,NULL,NULL,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; sound_card_current = temp_sound_card_current;
mem_resize(); mem_resize();
loadbios();
mem_load_video_bios(); mem_load_video_bios();
loadbios();
resetpchard(); resetpchard();
} }
else else
@ -1327,6 +1330,7 @@ BOOL CALLBACK statusdlgproc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lPara
{ {
int egasp; int egasp;
char s[256]; char s[256];
char device_s[4096];
switch (message) switch (message)
{ {
case WM_INITDIALOG: 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); SendDlgItemMessage(hdlg,IDC_STEXT7,WM_SETTEXT,(WPARAM)NULL,(LPARAM)s);
sprintf(s,"Timer 0 frequency : %fHz",pit_timer0_freq()); sprintf(s,"Timer 0 frequency : %fHz",pit_timer0_freq());
SendDlgItemMessage(hdlg,IDC_STEXT8,WM_SETTEXT,(WPARAM)NULL,(LPARAM)s); SendDlgItemMessage(hdlg,IDC_STEXT8,WM_SETTEXT,(WPARAM)NULL,(LPARAM)s);
if (chain4) sprintf(s,"VGA chained (possibly mode 13h)"); device_add_status_info(device_s, 4096);
else sprintf(s,"VGA unchained (possibly mode-X)"); SendDlgItemMessage(hdlg,IDC_STEXT_DEVICE,WM_SETTEXT,(WPARAM)NULL,(LPARAM)device_s);
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);
return TRUE; return TRUE;
case WM_COMMAND: case WM_COMMAND:
switch (LOWORD(wParam)) switch (LOWORD(wParam))