Preliminary PCjr emulation.
Improvements to PIT and serial emulation.
This commit is contained in:
parent
f8575b7b97
commit
f18f10574a
27 changed files with 1659 additions and 377 deletions
35
src/808x.c
35
src/808x.c
|
|
@ -804,14 +804,16 @@ void clockhardware()
|
|||
int diff = cycdiff - cycles - current_diff;
|
||||
|
||||
current_diff += diff;
|
||||
pit.c[0] -= diff;
|
||||
pit.c[1] -= diff;
|
||||
if (pit.gate[2]) pit.c[2] -= diff;
|
||||
if (pit.running[0]) pit.c[0] -= diff;
|
||||
if (pit.running[1]) pit.c[1] -= diff;
|
||||
if (pit.running[2]) pit.c[2] -= diff;
|
||||
if ((pit.c[0] < 1) || (pit.c[1] < 1) || (pit.c[2] < 1)) pit_poll();
|
||||
|
||||
timer_clock(diff);
|
||||
}
|
||||
|
||||
static int takeint = 0;
|
||||
|
||||
|
||||
int firstrepcycle=1;
|
||||
|
||||
|
|
@ -826,6 +828,7 @@ void rep(int fv)
|
|||
uint32_t oldds;
|
||||
startrep:
|
||||
temp=FETCH();
|
||||
|
||||
// if (firstrepcycle && temp==0xA5) printf("REP MOVSW %06X:%04X %06X:%04X\n",ds,SI,es,DI);
|
||||
// if (output) printf("REP %02X %04X\n",temp,ipc);
|
||||
switch (temp)
|
||||
|
|
@ -1047,6 +1050,8 @@ void rep(int fv)
|
|||
}
|
||||
CX=c;
|
||||
if (changeds) ds=oldds;
|
||||
if (IRQTEST)
|
||||
takeint = 1;
|
||||
// if (pc==ipc) FETCHCLEAR();
|
||||
}
|
||||
|
||||
|
|
@ -1056,7 +1061,6 @@ uint16_t lastpc,lastcs;
|
|||
int firstrepcycle;
|
||||
int skipnextprint=0;
|
||||
|
||||
|
||||
int instime=0;
|
||||
//#if 0
|
||||
void execx86(int cycs)
|
||||
|
|
@ -1102,7 +1106,7 @@ void execx86(int cycs)
|
|||
{
|
||||
// if ((opcode!=0xF2 && opcode!=0xF3) || firstrepcycle)
|
||||
// {
|
||||
if (!skipnextprint) printf("%04X:%04X : %04X %04X %04X %04X %04X %04X %04X %04X %04X %04X %04X %04X %02X %04X %02X %02X %02X %02X\n",cs,pc,AX,BX,CX,DX,CS,DS,ES,SS,DI,SI,BP,SP,opcode,flags, ram[0x413], ram[0x414], ram[0x415], ram[0x416]);
|
||||
if (!skipnextprint) printf("%04X:%04X : %04X %04X %04X %04X %04X %04X %04X %04X %04X %04X %04X %04X %02X %04X %i %p %02X\n",cs,pc,AX,BX,CX,DX,CS,DS,ES,SS,DI,SI,BP,SP,opcode,flags, ins, ram, ram[0x1a925]);
|
||||
skipnextprint=0;
|
||||
// ins++;
|
||||
// }
|
||||
|
|
@ -2373,7 +2377,7 @@ void execx86(int cycs)
|
|||
lastpc=pc;
|
||||
lastcs=CS;
|
||||
temp=FETCH();
|
||||
|
||||
|
||||
if (ssegs) ss=oldss;
|
||||
writememw(ss,((SP-2)&0xFFFF),flags|0xF000);
|
||||
writememw(ss,((SP-4)&0xFFFF),CS);
|
||||
|
|
@ -2399,6 +2403,7 @@ void execx86(int cycs)
|
|||
SP+=6;
|
||||
cycles-=44;
|
||||
FETCHCLEAR();
|
||||
nmi_enable = 1;
|
||||
break;
|
||||
case 0xD0:
|
||||
fetchea();
|
||||
|
|
@ -3427,7 +3432,22 @@ void execx86(int cycs)
|
|||
loadcs(readmemw(0,addr+2));
|
||||
FETCHCLEAR();
|
||||
}
|
||||
else if ((flags&I_FLAG) && (pic.pend&~pic.mask) && !ssegs && !noint)
|
||||
else if (nmi && nmi_enable)
|
||||
{
|
||||
// output = 3;
|
||||
writememw(ss,(SP-2)&0xFFFF,flags|0xF000);
|
||||
writememw(ss,(SP-4)&0xFFFF,CS);
|
||||
writememw(ss,(SP-6)&0xFFFF,pc);
|
||||
SP-=6;
|
||||
addr=2<<2;
|
||||
flags&=~I_FLAG;
|
||||
flags&=~T_FLAG;
|
||||
pc=readmemw(0,addr);
|
||||
loadcs(readmemw(0,addr+2));
|
||||
FETCHCLEAR();
|
||||
nmi_enable = 0;
|
||||
}
|
||||
else if (takeint && !ssegs && !noint)
|
||||
{
|
||||
temp=picinterrupt();
|
||||
if (temp!=0xFF)
|
||||
|
|
@ -3447,6 +3467,7 @@ void execx86(int cycs)
|
|||
// printf("INTERRUPT\n");
|
||||
}
|
||||
}
|
||||
takeint = (flags&I_FLAG) && (pic.pend&~pic.mask);
|
||||
|
||||
if (noint) noint=0;
|
||||
ins++;
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ CFLAGS = -O3 -march=i686 -fomit-frame-pointer
|
|||
OBJ = 386.o 808x.o acer386sx.o ali1429.o amstrad.o cdrom-ioctl.o \
|
||||
config.o cpu.o dac.o device.o dma.o ega.o fdc.o \
|
||||
headland.o i430vx.o ide.o io.o jim.o keyboard.o keyboard_amstrad.o keyboard_at.o \
|
||||
keyboard_olim24.o keyboard_xt.o lpt.o mcr.o mem.o model.o \
|
||||
keyboard_olim24.o keyboard_pcjr.o keyboard_xt.o lpt.o mcr.o mem.o model.o \
|
||||
mouse.o mouse_ps2.o mouse_serial.o neat.o nvr.o olivetti_m24.o \
|
||||
opti.o pc.o pci.o pic.o piix.o pit.o ppi.o rom.o serial.o sis496.o sound.o sound_ad1848.o sound_adlib.o \
|
||||
sound_adlibgold.o sound_cms.o sound_emu8k.o sound_gus.o sound_mpu401_uart.o sound_opl.o \
|
||||
|
|
@ -15,7 +15,7 @@ OBJ = 386.o 808x.o acer386sx.o ali1429.o amstrad.o cdrom-ioctl.o \
|
|||
vid_ati_mach64.o vid_ati18800.o vid_ati28800.o vid_ati68860_ramdac.o vid_cga.o \
|
||||
vid_cl5429.o vid_ega.o vid_et4000.o vid_et4000w32.o vid_et4000w32i.o \
|
||||
vid_hercules.o vid_icd2061.o vid_ics2595.o vid_mda.o vid_olivetti_m24.o \
|
||||
vid_oti067.o vid_paradise.o vid_pc1512.o vid_pc1640.o vid_pc200.o vid_s3.o \
|
||||
vid_oti067.o vid_paradise.o vid_pc1512.o vid_pc1640.o vid_pc200.o vid_pcjr.o vid_s3.o \
|
||||
vid_s3_virge.o vid_sdac_ramdac.o vid_stg_ramdac.o vid_svga.o vid_svga_render.o \
|
||||
vid_tandy.o vid_tgui9440.o vid_tkd8001_ramdac.o vid_tvga.o vid_unk_ramdac.o vid_vga.o \
|
||||
vid_voodoo.o video.o wd76c10.o win.o win-d3d.o win-d3d-fs.o win-ddraw.o win-ddraw-fs.o win-keyboard.o win-midi.o \
|
||||
|
|
|
|||
|
|
@ -68,6 +68,13 @@ CPU cpus_8088[] =
|
|||
{"", -1, 0, 0, 0, 0}
|
||||
};
|
||||
|
||||
CPU cpus_pcjr[] =
|
||||
{
|
||||
/*8088 PCjr*/
|
||||
{"8088/4.77", CPU_8088, 0, 4772727, 1, 0, 0, 0},
|
||||
{"", -1, 0, 0, 0, 0}
|
||||
};
|
||||
|
||||
CPU cpus_8086[] =
|
||||
{
|
||||
/*8086 standard*/
|
||||
|
|
@ -259,7 +266,7 @@ void cpu_set()
|
|||
cpu_hasrdtsc = 0;
|
||||
cpu_hasMMX = 0;
|
||||
cpu_hasMSR = 0;
|
||||
|
||||
|
||||
if (cpu_iscyrix)
|
||||
io_sethandler(0x0022, 0x0002, cyrix_read, NULL, NULL, cyrix_write, NULL, NULL, NULL);
|
||||
else
|
||||
|
|
|
|||
|
|
@ -61,6 +61,7 @@ extern CPU cpus_Am486[];
|
|||
extern CPU cpus_Cx486[];
|
||||
extern CPU cpus_WinChip[];
|
||||
|
||||
extern CPU cpus_pcjr[];
|
||||
extern CPU cpus_pc1512[];
|
||||
extern CPU cpus_ibmat[];
|
||||
extern CPU cpus_acer[];
|
||||
|
|
|
|||
166
src/fdc.c
166
src/fdc.c
|
|
@ -7,6 +7,31 @@
|
|||
#include "pic.h"
|
||||
#include "timer.h"
|
||||
|
||||
/*FDC*/
|
||||
typedef struct FDC
|
||||
{
|
||||
uint8_t dor,stat,command,dat,st0;
|
||||
int head,track[256],sector,drive,lastdrive;
|
||||
int pos;
|
||||
uint8_t params[256];
|
||||
uint8_t res[256];
|
||||
int pnum,ptot;
|
||||
int rate;
|
||||
uint8_t specify[256];
|
||||
int eot[256];
|
||||
int lock;
|
||||
int perp;
|
||||
uint8_t config, pretrk;
|
||||
int abort;
|
||||
|
||||
int pcjr;
|
||||
|
||||
int watchdog_timer;
|
||||
int watchdog_count;
|
||||
} FDC;
|
||||
|
||||
static FDC fdc;
|
||||
|
||||
void fdc_poll();
|
||||
int timetolive;
|
||||
int TRACKS[2] = {80, 80};
|
||||
|
|
@ -38,6 +63,7 @@ void loaddisc(int d, char *fn)
|
|||
if (ftell(f)<=(160*1024)) { SECTORS[d]=8; TRACKS[d] = 40; SIDES[d]=1; discrate[d]=2; }
|
||||
else if (ftell(f)<=(180*1024)) { SECTORS[d]=9; TRACKS[d] = 40; SIDES[d]=1; discrate[d]=2; }
|
||||
else if (ftell(f)<=(320*1024)) { SECTORS[d]=8; TRACKS[d] = 40; discrate[d]=2; }
|
||||
else if (ftell(f)<=(360*1024)) { SECTORS[d]=9; TRACKS[d] = 40; discrate[d]=2; } /*Double density*/
|
||||
else if (ftell(f)<(1024*1024)) { SECTORS[d]=9; TRACKS[d] = 80; discrate[d]=2; } /*Double density*/
|
||||
else if (ftell(f)<(0x1A4000-1)) { SECTORS[d]=18; TRACKS[d] = 80; discrate[d]=0; } /*High density (not supported by Tandy 1000)*/
|
||||
else if (ftell(f) == 1884159) { SECTORS[d]=23; TRACKS[d] = 80; discrate[d]=0; } /*XDF format - used by OS/2 Warp*/
|
||||
|
|
@ -111,6 +137,29 @@ void fdc_reset()
|
|||
}
|
||||
int ins;
|
||||
|
||||
static void fdc_int()
|
||||
{
|
||||
if (!fdc.pcjr)
|
||||
picint(1 << 6);
|
||||
}
|
||||
|
||||
static void fdc_watchdog_poll(void *p)
|
||||
{
|
||||
FDC *fdc = (FDC *)p;
|
||||
|
||||
fdc->watchdog_count--;
|
||||
if (fdc->watchdog_count)
|
||||
fdc->watchdog_timer += 1000 * TIMER_USEC;
|
||||
else
|
||||
{
|
||||
// pclog("Watchdog timed out\n");
|
||||
|
||||
fdc->watchdog_timer = 0;
|
||||
if (fdc->dor & 0x20)
|
||||
picint(1 << 6);
|
||||
}
|
||||
}
|
||||
|
||||
void fdc_write(uint16_t addr, uint8_t val, void *priv)
|
||||
{
|
||||
// printf("Write FDC %04X %02X %04X:%04X %i %02X %i rate=%i\n",addr,val,cs>>4,pc,ins,fdc.st0,ins,fdc.rate);
|
||||
|
|
@ -120,18 +169,39 @@ void fdc_write(uint16_t addr, uint8_t val, void *priv)
|
|||
case 2: /*DOR*/
|
||||
// if (val == 0xD && (cs >> 4) == 0xFC81600 && ins > 769619936) output = 3;
|
||||
// printf("DOR was %02X\n",fdc.dor);
|
||||
if (val&4)
|
||||
if (fdc.pcjr)
|
||||
{
|
||||
fdc.stat=0x80;
|
||||
fdc.pnum=fdc.ptot=0;
|
||||
if ((fdc.dor & 0x40) && !(val & 0x40))
|
||||
{
|
||||
fdc.watchdog_timer = 1000 * TIMER_USEC;
|
||||
fdc.watchdog_count = 1000;
|
||||
picintc(1 << 6);
|
||||
// pclog("watchdog set %i %i\n", fdc.watchdog_timer, TIMER_USEC);
|
||||
}
|
||||
if ((val & 0x80) && !(fdc.dor & 0x80))
|
||||
{
|
||||
timer_process();
|
||||
disctime = 128 * (1 << TIMER_SHIFT);
|
||||
timer_update_outstanding();
|
||||
discint=-1;
|
||||
fdc_reset();
|
||||
}
|
||||
}
|
||||
if ((val&4) && !(fdc.dor&4))
|
||||
else
|
||||
{
|
||||
timer_process();
|
||||
disctime = 128 * (1 << TIMER_SHIFT);
|
||||
timer_update_outstanding();
|
||||
discint=-1;
|
||||
fdc_reset();
|
||||
if (val&4)
|
||||
{
|
||||
fdc.stat=0x80;
|
||||
fdc.pnum=fdc.ptot=0;
|
||||
}
|
||||
if ((val&4) && !(fdc.dor&4))
|
||||
{
|
||||
timer_process();
|
||||
disctime = 128 * (1 << TIMER_SHIFT);
|
||||
timer_update_outstanding();
|
||||
discint=-1;
|
||||
fdc_reset();
|
||||
}
|
||||
}
|
||||
fdc.dor=val;
|
||||
// printf("DOR now %02X\n",val);
|
||||
|
|
@ -147,6 +217,12 @@ void fdc_write(uint16_t addr, uint8_t val, void *priv)
|
|||
}
|
||||
return;
|
||||
case 5: /*Command register*/
|
||||
if ((fdc.stat & 0xf0) == 0xb0)
|
||||
{
|
||||
fdc.dat = val;
|
||||
fdc.stat &= ~0x80;
|
||||
break;
|
||||
}
|
||||
// pclog("Write command reg %i %i\n",fdc.pnum, fdc.ptot);
|
||||
if (fdc.pnum==fdc.ptot)
|
||||
{
|
||||
|
|
@ -315,6 +391,8 @@ void fdc_write(uint16_t addr, uint8_t val, void *priv)
|
|||
{
|
||||
fdc.head = (fdc.params[0] & 4) ? 1 : 0;
|
||||
}
|
||||
if (discint == 5 && fdc.pcjr)
|
||||
fdc.stat = 0xb0;
|
||||
timer_update_outstanding();
|
||||
// if (discint==5) fdc.pos=512;
|
||||
}
|
||||
|
|
@ -350,6 +428,11 @@ uint8_t fdc_read(uint16_t addr, void *priv)
|
|||
break;
|
||||
case 5: /*Data*/
|
||||
fdc.stat&=~0x80;
|
||||
if ((fdc.stat & 0xf0) == 0xf0)
|
||||
{
|
||||
temp = fdc.dat;
|
||||
break;
|
||||
}
|
||||
if (paramstogo)
|
||||
{
|
||||
paramstogo--;
|
||||
|
|
@ -412,13 +495,13 @@ void fdc_poll()
|
|||
case -3: /*End of command with interrupt*/
|
||||
// if (output) printf("EOC - interrupt!\n");
|
||||
//pclog("EOC\n");
|
||||
picint(0x40);
|
||||
fdc_int();
|
||||
case -2: /*End of command*/
|
||||
fdc.stat = (fdc.stat & 0xf) | 0x80;
|
||||
return;
|
||||
case -1: /*Reset*/
|
||||
//pclog("Reset\n");
|
||||
picint(0x40);
|
||||
fdc_int();
|
||||
fdc_reset_stat = 4;
|
||||
return;
|
||||
case 2: /*Read track*/
|
||||
|
|
@ -430,7 +513,10 @@ void fdc_poll()
|
|||
{
|
||||
fdc.dat=disc[fdc.drive][fdc.head][fdc.track[fdc.drive]][fdc.sector-1][fdc.pos];
|
||||
// pclog("Read %i %i %i %i %02X\n",fdc.head,fdc.track,fdc.sector,fdc.pos,fdc.dat);
|
||||
dma_channel_write(2, fdc.dat);
|
||||
if (fdc.pcjr)
|
||||
fdc.stat = 0xf0;
|
||||
else
|
||||
dma_channel_write(2, fdc.dat);
|
||||
timer_process();
|
||||
disctime = 60 * (1 << TIMER_SHIFT);
|
||||
timer_update_outstanding();
|
||||
|
|
@ -440,7 +526,7 @@ void fdc_poll()
|
|||
disctime=0;
|
||||
discint=-2;
|
||||
// pclog("RT\n");
|
||||
picint(0x40);
|
||||
fdc_int();
|
||||
fdc.stat=0xD0;
|
||||
fdc.res[4]=(fdc.head?4:0)|fdc.drive;
|
||||
fdc.res[5]=fdc.res[2]=0;
|
||||
|
|
@ -488,7 +574,10 @@ void fdc_poll()
|
|||
}
|
||||
if (fdc.pos<512)
|
||||
{
|
||||
temp = dma_channel_read(2);
|
||||
if (fdc.pcjr)
|
||||
temp = fdc.dat;
|
||||
else
|
||||
temp = dma_channel_read(2);
|
||||
if (temp == DMA_NODATA)
|
||||
{
|
||||
discint=0xFD;
|
||||
|
|
@ -502,8 +591,10 @@ void fdc_poll()
|
|||
fdc.dat=disc[fdc.drive][fdc.head][fdc.track[fdc.drive]][fdc.sector-1][fdc.pos]=temp;
|
||||
// printf("Write data %i %i %02X %i:%i:%i:%i\n",fdc.sector-1,fdc.pos,fdc.dat,fdc.head,fdc.track[fdc.drive],fdc.sector-1,fdc.pos);
|
||||
timer_process();
|
||||
disctime = 60 * (1 << TIMER_SHIFT);
|
||||
disctime = 600 * (1 << TIMER_SHIFT);
|
||||
timer_update_outstanding();
|
||||
if (fdc.pcjr && fdc.pos != 512)
|
||||
fdc.stat = 0xb0;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
|
@ -511,7 +602,7 @@ void fdc_poll()
|
|||
disctime=0;
|
||||
discint=-2;
|
||||
// pclog("WD\n");
|
||||
picint(0x40);
|
||||
fdc_int();
|
||||
fdc.stat=0xD0;
|
||||
fdc.res[4]=(fdc.head?4:0)|fdc.drive;
|
||||
fdc.res[5]=0;
|
||||
|
|
@ -528,6 +619,8 @@ void fdc_poll()
|
|||
{
|
||||
fdc.pos=0;
|
||||
fdc.sector++;
|
||||
if (fdc.pcjr)
|
||||
fdc.stat = 0xb0;
|
||||
}
|
||||
return;
|
||||
case 6: /*Read data*/
|
||||
|
|
@ -537,12 +630,19 @@ void fdc_poll()
|
|||
}
|
||||
if (fdc.pos<512)
|
||||
{
|
||||
fdc.dat=disc[fdc.drive][fdc.head][fdc.track[fdc.drive]][fdc.sector-1][fdc.pos];
|
||||
fdc.dat = disc[fdc.drive][fdc.head][fdc.track[fdc.drive]][fdc.sector - 1][fdc.pos];
|
||||
// printf("Read disc %i %i %i %i %02X\n",fdc.head,fdc.track,fdc.sector,fdc.pos,fdc.dat);
|
||||
if (dma_channel_write(2, fdc.dat) & DMA_OVER)
|
||||
fdc.abort = 1;
|
||||
if (fdc.pcjr)
|
||||
{
|
||||
fdc.stat = 0xf0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (dma_channel_write(2, fdc.dat) & DMA_OVER)
|
||||
fdc.abort = 1;
|
||||
}
|
||||
timer_process();
|
||||
disctime = 60 * (1 << TIMER_SHIFT);
|
||||
disctime = 256 * (1 << TIMER_SHIFT);
|
||||
timer_update_outstanding();
|
||||
}
|
||||
else
|
||||
|
|
@ -551,7 +651,7 @@ void fdc_poll()
|
|||
fdc.abort = 0;
|
||||
disctime=0;
|
||||
discint=-2;
|
||||
picint(0x40);
|
||||
fdc_int();
|
||||
// pclog("RD\n");
|
||||
fdc.stat=0xD0;
|
||||
fdc.res[4]=(fdc.head?4:0)|fdc.drive;
|
||||
|
|
@ -640,7 +740,7 @@ void fdc_poll()
|
|||
case 10: /*Read sector ID*/
|
||||
disctime=0;
|
||||
discint=-2;
|
||||
picint(0x40);
|
||||
fdc_int();
|
||||
fdc.stat=0xD0;
|
||||
fdc.res[4]=(fdc.head?4:0)|fdc.drive;
|
||||
fdc.res[5]=0;
|
||||
|
|
@ -693,14 +793,14 @@ void fdc_poll()
|
|||
fdc.perp = fdc.params[0];
|
||||
fdc.stat = 0x80;
|
||||
disctime = 0;
|
||||
// picint(0x40);
|
||||
// fdc_int();
|
||||
return;
|
||||
case 0x13: /*Configure*/
|
||||
fdc.config = fdc.params[1];
|
||||
fdc.pretrk = fdc.params[2];
|
||||
fdc.stat = 0x80;
|
||||
disctime = 0;
|
||||
// picint(0x40);
|
||||
// fdc_int();
|
||||
return;
|
||||
case 0x14: /*Unlock*/
|
||||
fdc.lock = 0;
|
||||
|
|
@ -723,7 +823,7 @@ void fdc_poll()
|
|||
case 0xfc: /*Invalid*/
|
||||
fdc.dat = fdc.st0 = 0x80;
|
||||
// pclog("Inv!\n");
|
||||
//picint(0x40);
|
||||
//fdc_int();
|
||||
fdc.stat = (fdc.stat & 0xf) | 0xd0;
|
||||
// fdc.stat|=0xC0;
|
||||
fdc.res[10] = fdc.st0;
|
||||
|
|
@ -742,7 +842,7 @@ void fdc_poll()
|
|||
pclog("DMA Aborted\n");
|
||||
disctime=0;
|
||||
discint=-2;
|
||||
picint(0x40);
|
||||
fdc_int();
|
||||
fdc.stat=0xD0;
|
||||
fdc.res[4]=(fdc.head?4:0)|fdc.drive;
|
||||
fdc.res[5]=0;
|
||||
|
|
@ -759,7 +859,7 @@ void fdc_poll()
|
|||
disctime = 0;
|
||||
/* disctime=0;
|
||||
discint=-2;
|
||||
picint(0x40);
|
||||
fdc_int();
|
||||
fdc.stat=0xD0;
|
||||
fdc.res[4]=0xC8|(fdc.head?4:0)|fdc.drive;
|
||||
fdc.res[5]=0;
|
||||
|
|
@ -774,7 +874,7 @@ void fdc_poll()
|
|||
pclog("Wrong rate\n");
|
||||
disctime=0;
|
||||
discint=-2;
|
||||
picint(0x40);
|
||||
fdc_int();
|
||||
fdc.stat=0xD0;
|
||||
fdc.res[4]=0x40|(fdc.head?4:0)|fdc.drive;
|
||||
fdc.res[5]=5;
|
||||
|
|
@ -799,7 +899,15 @@ void fdc_init()
|
|||
void fdc_add()
|
||||
{
|
||||
io_sethandler(0x03f0, 0x0006, fdc_read, NULL, NULL, fdc_write, NULL, NULL, NULL);
|
||||
io_sethandler(0x03f7, 0x0001, fdc_read, NULL, NULL, fdc_write, NULL, NULL, NULL);
|
||||
io_sethandler(0x03f7, 0x0001, fdc_read, NULL, NULL, fdc_write, NULL, NULL, NULL);
|
||||
fdc.pcjr = 0;
|
||||
}
|
||||
|
||||
void fdc_add_pcjr()
|
||||
{
|
||||
io_sethandler(0x00f0, 0x0006, fdc_read, NULL, NULL, fdc_write, NULL, NULL, NULL);
|
||||
timer_add(fdc_watchdog_poll, &fdc.watchdog_timer, &fdc.watchdog_timer, &fdc);
|
||||
fdc.pcjr = 1;
|
||||
}
|
||||
|
||||
void fdc_remove()
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
void fdc_init();
|
||||
void fdc_add();
|
||||
void fdc_add_pcjr();
|
||||
void fdc_remove();
|
||||
void fdc_reset();
|
||||
void fdc_poll();
|
||||
|
|
|
|||
28
src/ibm.h
28
src/ibm.h
|
|
@ -199,6 +199,13 @@ typedef struct PIT
|
|||
int delay[3];
|
||||
int rereadlatch[3];
|
||||
int gate[3];
|
||||
int out[3];
|
||||
int running[3];
|
||||
int enabled[3];
|
||||
int newcount[3];
|
||||
int count[3];
|
||||
int using_timer[3];
|
||||
int initial[3];
|
||||
} PIT;
|
||||
|
||||
PIT pit;
|
||||
|
|
@ -250,25 +257,6 @@ extern int pic_intpending;
|
|||
int intcount;
|
||||
|
||||
|
||||
/*FDC*/
|
||||
typedef struct FDC
|
||||
{
|
||||
uint8_t dor,stat,command,dat,st0;
|
||||
int head,track[256],sector,drive,lastdrive;
|
||||
int pos;
|
||||
uint8_t params[256];
|
||||
uint8_t res[256];
|
||||
int pnum,ptot;
|
||||
int rate;
|
||||
uint8_t specify[256];
|
||||
int eot[256];
|
||||
int lock;
|
||||
int perp;
|
||||
uint8_t config, pretrk;
|
||||
int abort;
|
||||
} FDC;
|
||||
|
||||
FDC fdc;
|
||||
int disctime;
|
||||
char discfns[2][256];
|
||||
int driveempty[2];
|
||||
|
|
@ -290,6 +278,7 @@ int driveempty[2];
|
|||
#define ET4000W32 (gfxcard==GFX_ET4000W32 && VGA)
|
||||
#define AT (romset>=ROM_IBMAT)
|
||||
#define PCI (romset >= ROM_PCI486)
|
||||
#define PCJR (romset == ROM_IBMPCJR)
|
||||
|
||||
#define AMIBIOS (romset==ROM_AMI386 || romset==ROM_AMI486 || romset == ROM_WIN486)
|
||||
|
||||
|
|
@ -299,6 +288,7 @@ enum
|
|||
{
|
||||
ROM_IBMPC = 0, /*301 keyboard error, 131 cassette (!!!) error*/
|
||||
ROM_IBMXT, /*301 keyboard error*/
|
||||
ROM_IBMPCJR,
|
||||
ROM_GENXT, /*'Generic XT BIOS'*/
|
||||
ROM_DTKXT,
|
||||
ROM_EUROPC,
|
||||
|
|
|
|||
202
src/keyboard_pcjr.c
Normal file
202
src/keyboard_pcjr.c
Normal file
|
|
@ -0,0 +1,202 @@
|
|||
#include "ibm.h"
|
||||
#include "device.h"
|
||||
#include "io.h"
|
||||
#include "mem.h"
|
||||
#include "pic.h"
|
||||
#include "sound.h"
|
||||
#include "sound_sn76489.h"
|
||||
#include "sound_speaker.h"
|
||||
#include "timer.h"
|
||||
|
||||
#include "keyboard.h"
|
||||
#include "keyboard_pcjr.h"
|
||||
|
||||
#define STAT_PARITY 0x80
|
||||
#define STAT_RTIMEOUT 0x40
|
||||
#define STAT_TTIMEOUT 0x20
|
||||
#define STAT_LOCK 0x10
|
||||
#define STAT_CD 0x08
|
||||
#define STAT_SYSFLAG 0x04
|
||||
#define STAT_IFULL 0x02
|
||||
#define STAT_OFULL 0x01
|
||||
|
||||
struct
|
||||
{
|
||||
int latched;
|
||||
int data;
|
||||
int nmi_enabled;
|
||||
|
||||
int serial_data[44];
|
||||
int serial_pos;
|
||||
|
||||
uint8_t pa;
|
||||
uint8_t pb;
|
||||
} keyboard_pcjr;
|
||||
|
||||
static uint8_t key_queue[16];
|
||||
static int key_queue_start = 0, key_queue_end = 0;
|
||||
|
||||
void keyboard_pcjr_poll()
|
||||
{
|
||||
keybsenddelay += (220 * TIMER_USEC);
|
||||
|
||||
|
||||
if (key_queue_start != key_queue_end && !keyboard_pcjr.serial_pos && !keyboard_pcjr.latched)
|
||||
{
|
||||
int c;
|
||||
int p = 0;
|
||||
uint8_t key = key_queue[key_queue_start];
|
||||
|
||||
// pclog("Reading %02X from the key queue at %i\n", key, key_queue_start);
|
||||
key_queue_start = (key_queue_start + 1) & 0xf;
|
||||
|
||||
keyboard_pcjr.latched = 1;
|
||||
|
||||
keyboard_pcjr.serial_data[0] = 1; /*Start bit*/
|
||||
keyboard_pcjr.serial_data[1] = 0;
|
||||
|
||||
for (c = 0; c < 8; c++)
|
||||
{
|
||||
if (key & (1 << c))
|
||||
{
|
||||
keyboard_pcjr.serial_data[(c + 1) * 2] = 1;
|
||||
keyboard_pcjr.serial_data[(c + 1) * 2 + 1] = 0;
|
||||
p++;
|
||||
}
|
||||
else
|
||||
{
|
||||
keyboard_pcjr.serial_data[(c + 1) * 2] = 0;
|
||||
keyboard_pcjr.serial_data[(c + 1) * 2 + 1] = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (p & 1) /*Parity*/
|
||||
{
|
||||
keyboard_pcjr.serial_data[9 * 2] = 1;
|
||||
keyboard_pcjr.serial_data[9 * 2 + 1] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
keyboard_pcjr.serial_data[9 * 2] = 0;
|
||||
keyboard_pcjr.serial_data[9 * 2 + 1] = 1;
|
||||
}
|
||||
|
||||
for (c = 0; c < 11; c++) /*11 stop bits*/
|
||||
{
|
||||
keyboard_pcjr.serial_data[(c + 10) * 2] = 0;
|
||||
keyboard_pcjr.serial_data[(c + 10) * 2 + 1] = 0;
|
||||
}
|
||||
|
||||
keyboard_pcjr.serial_pos++;
|
||||
}
|
||||
|
||||
if (keyboard_pcjr.serial_pos)
|
||||
{
|
||||
keyboard_pcjr.data = keyboard_pcjr.serial_data[keyboard_pcjr.serial_pos - 1];
|
||||
nmi = keyboard_pcjr.data;
|
||||
keyboard_pcjr.serial_pos++;
|
||||
if (keyboard_pcjr.serial_pos == 42+1)
|
||||
keyboard_pcjr.serial_pos = 0;
|
||||
// pclog("Keyboard poll %i %i\n", keyboard_pcjr.data, keyboard_pcjr.serial_pos);
|
||||
}
|
||||
}
|
||||
|
||||
void keyboard_pcjr_adddata(uint8_t val)
|
||||
{
|
||||
key_queue[key_queue_end] = val;
|
||||
// pclog("keyboard_pcjr : %02X added to key queue at %i\n", val, key_queue_end);
|
||||
key_queue_end = (key_queue_end + 1) & 0xf;
|
||||
return;
|
||||
}
|
||||
|
||||
void keyboard_pcjr_write(uint16_t port, uint8_t val, void *priv)
|
||||
{
|
||||
// pclog("keyboard_pcjr : write %04X %02X %02X\n", port, val, keyboard_pcjr.pb);
|
||||
/* if (ram[8] == 0xc3)
|
||||
{
|
||||
output = 3;
|
||||
}*/
|
||||
switch (port)
|
||||
{
|
||||
case 0x60:
|
||||
keyboard_pcjr.pa = val;
|
||||
break;
|
||||
|
||||
case 0x61:
|
||||
keyboard_pcjr.pb = val;
|
||||
gated = ((val & 3) == 3);
|
||||
if (gated)
|
||||
wasgated = 1;
|
||||
pit_set_gate(2, val & 1);
|
||||
sn76489_mute = speaker_mute = 1;
|
||||
switch (val & 0x60)
|
||||
{
|
||||
case 0x00:
|
||||
speaker_mute = 0;
|
||||
break;
|
||||
case 0x60:
|
||||
sn76489_mute = 0;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xa0:
|
||||
keyboard_pcjr.nmi_enabled = val & 0x80;
|
||||
pit_set_using_timer(1, !(val & 0x20));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t keyboard_pcjr_read(uint16_t port, void *priv)
|
||||
{
|
||||
uint8_t temp;
|
||||
// pclog("keyboard_pcjr : read %04X ", port);
|
||||
switch (port)
|
||||
{
|
||||
case 0x60:
|
||||
temp = keyboard_pcjr.pa;
|
||||
break;
|
||||
|
||||
case 0x61:
|
||||
temp = keyboard_pcjr.pb;
|
||||
break;
|
||||
|
||||
case 0x62:
|
||||
temp = (keyboard_pcjr.latched ? 1 : 0);
|
||||
temp |= 0x02; /*Modem card not installed*/
|
||||
temp |= (ppispeakon ? 0x10 : 0);
|
||||
temp |= (ppispeakon ? 0x20 : 0);
|
||||
temp |= (keyboard_pcjr.data ? 0x40: 0);
|
||||
// temp |= 0x04;
|
||||
if (keyboard_pcjr.data)
|
||||
temp |= 0x40;
|
||||
break;
|
||||
|
||||
case 0xa0:
|
||||
keyboard_pcjr.latched = 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
pclog("\nBad XT keyboard read %04X\n", port);
|
||||
//dumpregs();
|
||||
//exit(-1);
|
||||
}
|
||||
// pclog("%02X\n", temp);
|
||||
return temp;
|
||||
}
|
||||
|
||||
void keyboard_pcjr_reset()
|
||||
{
|
||||
}
|
||||
|
||||
void keyboard_pcjr_init()
|
||||
{
|
||||
//return;
|
||||
io_sethandler(0x0060, 0x0004, keyboard_pcjr_read, NULL, NULL, keyboard_pcjr_write, NULL, NULL, NULL);
|
||||
io_sethandler(0x00a0, 0x0008, keyboard_pcjr_read, NULL, NULL, keyboard_pcjr_write, NULL, NULL, NULL);
|
||||
keyboard_pcjr_reset();
|
||||
keyboard_send = keyboard_pcjr_adddata;
|
||||
keyboard_poll = keyboard_pcjr_poll;
|
||||
|
||||
timer_add(keyboard_pcjr_poll, &keybsenddelay, TIMER_ALWAYS_ENABLED, NULL);
|
||||
}
|
||||
3
src/keyboard_pcjr.h
Normal file
3
src/keyboard_pcjr.h
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
void keyboard_pcjr_init();
|
||||
void keyboard_pcjr_reset();
|
||||
void keyboard_pcjr_poll();
|
||||
|
|
@ -344,6 +344,15 @@ int loadbios()
|
|||
return 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case ROM_IBMPCJR:
|
||||
f = romfopen("roms/ibmpcjr/bios.rom","rb");
|
||||
if (!f) break;
|
||||
fread(rom, 0x10000, 1, f);
|
||||
fclose(f);
|
||||
memset(vrom,0x63,0x8000);
|
||||
return 1;
|
||||
|
||||
case ROM_GENXT:
|
||||
f=romfopen("roms/genxt/pcxt.rom","rb");
|
||||
if (!f) break;
|
||||
|
|
|
|||
20
src/model.c
20
src/model.c
|
|
@ -16,6 +16,7 @@
|
|||
#include "keyboard_amstrad.h"
|
||||
#include "keyboard_at.h"
|
||||
#include "keyboard_olim24.h"
|
||||
#include "keyboard_pcjr.h"
|
||||
#include "keyboard_xt.h"
|
||||
#include "lpt.h"
|
||||
#include "mouse_ps2.h"
|
||||
|
|
@ -36,6 +37,7 @@
|
|||
#include "xtide.h"
|
||||
|
||||
void xt_init();
|
||||
void pcjr_init();
|
||||
void tandy1k_init();
|
||||
void ams_init();
|
||||
void europc_init();
|
||||
|
|
@ -56,6 +58,7 @@ MODEL models[] =
|
|||
{
|
||||
{"IBM PC", ROM_IBMPC, { "", cpus_8088, "", NULL, "", NULL}, 0, xt_init},
|
||||
{"IBM XT", ROM_IBMXT, { "", cpus_8088, "", NULL, "", NULL}, 0, xt_init},
|
||||
{"IBM PCjr", ROM_IBMPCJR, { "", cpus_pcjr, "", NULL, "", NULL}, 1, pcjr_init},
|
||||
{"Generic XT clone", ROM_GENXT, { "", cpus_8088, "", NULL, "", NULL}, 0, xt_init},
|
||||
{"DTK XT clone", ROM_DTKXT, { "", cpus_8088, "", NULL, "", NULL}, 0, xt_init},
|
||||
{"Tandy 1000", ROM_TANDY, { "", cpus_8088, "", NULL, "", NULL}, 1, tandy1k_init},
|
||||
|
|
@ -112,18 +115,30 @@ void common_init()
|
|||
lpt_init();
|
||||
pic_init();
|
||||
pit_init();
|
||||
serial1_init(0x3f8);
|
||||
serial2_init(0x2f8);
|
||||
serial1_init(0x3f8, 4);
|
||||
serial2_init(0x2f8, 3);
|
||||
}
|
||||
|
||||
void xt_init()
|
||||
{
|
||||
common_init();
|
||||
pit_set_out_func(1, pit_refresh_timer_xt);
|
||||
keyboard_xt_init();
|
||||
mouse_serial_init();
|
||||
xtide_init();
|
||||
}
|
||||
|
||||
void pcjr_init()
|
||||
{
|
||||
fdc_add_pcjr();
|
||||
pic_init();
|
||||
pit_init();
|
||||
pit_set_out_func(0, pit_irq0_timer_pcjr);
|
||||
serial1_init(0x2f8, 3);
|
||||
keyboard_pcjr_init();
|
||||
device_add(&sn76489_device);
|
||||
}
|
||||
|
||||
void tandy1k_init()
|
||||
{
|
||||
common_init();
|
||||
|
|
@ -163,6 +178,7 @@ void olim24_init()
|
|||
void at_init()
|
||||
{
|
||||
common_init();
|
||||
pit_set_out_func(1, pit_refresh_timer_at);
|
||||
dma16_init();
|
||||
ide_init();
|
||||
keyboard_at_init();
|
||||
|
|
|
|||
|
|
@ -10,7 +10,8 @@ void mouse_serial_poll(int x, int y, int b)
|
|||
{
|
||||
uint8_t mousedat[3];
|
||||
|
||||
if (!(serial.ier&1)) return;
|
||||
if (!(serial1.ier & 1))
|
||||
return;
|
||||
if (!x && !y && b==oldb) return;
|
||||
|
||||
oldb=b;
|
||||
|
|
@ -28,42 +29,44 @@ void mouse_serial_poll(int x, int y, int b)
|
|||
mousedat[1]=x&0x3F;
|
||||
mousedat[2]=y&0x3F;
|
||||
|
||||
if (!(serial.mctrl&0x10))
|
||||
if (!(serial1.mctrl&0x10))
|
||||
{
|
||||
serial_write_fifo(mousedat[0]);
|
||||
serial_write_fifo(mousedat[1]);
|
||||
serial_write_fifo(mousedat[2]);
|
||||
pclog("Serial data %02X %02X %02X\n", mousedat[0], mousedat[1], mousedat[2]);
|
||||
serial_write_fifo(&serial1, mousedat[0]);
|
||||
serial_write_fifo(&serial1, mousedat[1]);
|
||||
serial_write_fifo(&serial1, mousedat[2]);
|
||||
}
|
||||
}
|
||||
|
||||
void mouse_serial_rcr()
|
||||
void mouse_serial_rcr(void *p)
|
||||
{
|
||||
mousepos=-1;
|
||||
mousedelay=5000 * (1 << TIMER_SHIFT);
|
||||
}
|
||||
|
||||
void mousecallback()
|
||||
void mousecallback(void *p)
|
||||
{
|
||||
SERIAL *serial = (SERIAL *)p;
|
||||
mousedelay = 0;
|
||||
if (mousepos == -1)
|
||||
{
|
||||
mousepos = 0;
|
||||
serial_fifo_read = serial_fifo_write = 0;
|
||||
serial.linestat &= ~1;
|
||||
serial_write_fifo('M');
|
||||
/* serial_fifo_read = serial_fifo_write = 0;
|
||||
serial.lsr &= ~1;*/
|
||||
serial_write_fifo(serial, 'M');
|
||||
}
|
||||
else if (serial_fifo_read != serial_fifo_write)
|
||||
/* else if (serial_fifo_read != serial_fifo_write)
|
||||
{
|
||||
serial.iir=4;
|
||||
serial.linestat|=1;
|
||||
serial.lsr|=1;
|
||||
if (serial.mctrl&8) picint(0x10);
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
void mouse_serial_init()
|
||||
{
|
||||
mouse_poll = mouse_serial_poll;
|
||||
serial_rcr = mouse_serial_rcr;
|
||||
timer_add(mousecallback, &mousedelay, &mousedelay, NULL);
|
||||
serial1.rcr_callback = mouse_serial_rcr;
|
||||
timer_add(mousecallback, &mousedelay, &mousedelay, &serial1);
|
||||
}
|
||||
|
||||
|
|
|
|||
2
src/pc.c
2
src/pc.c
|
|
@ -46,7 +46,6 @@ extern int readlnum,writelnum;
|
|||
void fullspeed();
|
||||
|
||||
int framecount,fps;
|
||||
int pitsec;
|
||||
int intcount;
|
||||
int wakeups,wokeups;
|
||||
int output;
|
||||
|
|
@ -343,7 +342,6 @@ void runpc()
|
|||
egareads=egawrites=0;
|
||||
cycles_lost = 0;
|
||||
mmuflush=0;
|
||||
pitsec=0;
|
||||
intcount=0;
|
||||
wakeups=wokeups=0;
|
||||
intcount=pitcount=0;
|
||||
|
|
|
|||
487
src/pit.c
487
src/pit.c
|
|
@ -19,7 +19,6 @@
|
|||
//Tyrian writes 4300 or 17512
|
||||
int displine;
|
||||
|
||||
int pitsec=0;
|
||||
double PITCONST;
|
||||
float cpuclock;
|
||||
float isa_timing, bus_timing;
|
||||
|
|
@ -30,7 +29,7 @@ void setpitclock(float clock)
|
|||
// printf("PIT clock %f\n",clock);
|
||||
cpuclock=clock;
|
||||
PITCONST=clock/1193182.0;
|
||||
CGACONST=(clock/(19687500.0/11.0));
|
||||
CGACONST=(clock/(19687503.0/11.0));
|
||||
MDACONST=(clock/2032125.0);
|
||||
VGACONST1=(clock/25175000.0);
|
||||
VGACONST2=(clock/28322000.0);
|
||||
|
|
@ -57,6 +56,9 @@ void pit_reset()
|
|||
pit.ctrls[0]=pit.ctrls[1]=pit.ctrls[2]=0;
|
||||
pit.thit[0]=1;
|
||||
spkstat=0;
|
||||
pit.gate[0] = pit.gate[1] = 1;
|
||||
pit.gate[2] = 0;
|
||||
pit.using_timer[0] = pit.using_timer[1] = pit.using_timer[2] = 1;
|
||||
}
|
||||
|
||||
void clearpit()
|
||||
|
|
@ -69,12 +71,209 @@ float pit_timer0_freq()
|
|||
// pclog("PIT timer 0 freq %04X %f %f\n",pit.l[0],(float)pit.l[0],1193182.0f/(float)pit.l[0]);
|
||||
return 1193182.0f/(float)pit.l[0];
|
||||
}
|
||||
|
||||
static void (*pit_set_out_funcs[3])(int new_out, int old_out);
|
||||
|
||||
static void pit_set_out(int t, int out)
|
||||
{
|
||||
pit_set_out_funcs[t](out, pit.out[t]);
|
||||
pit.out[t] = out;
|
||||
}
|
||||
|
||||
static void pit_load(int t)
|
||||
{
|
||||
int l = pit.l[t] ? pit.l[t] : 0x10000;
|
||||
pit.newcount[t] = 0;
|
||||
switch (pit.m[t])
|
||||
{
|
||||
case 0: /*Interrupt on terminal count*/
|
||||
pit.count[t] = l;
|
||||
pit.c[t] = l * PITCONST;
|
||||
pit_set_out(t, 0);
|
||||
pit.thit[t] = 0;
|
||||
pit.enabled[t] = pit.gate[t];
|
||||
break;
|
||||
case 1: /*Hardware retriggerable one-shot*/
|
||||
pit.enabled[t] = 1;
|
||||
break;
|
||||
case 2: /*Rate generator*/
|
||||
if (pit.initial[t])
|
||||
{
|
||||
pit.count[t] = l - 1;
|
||||
pit.c[t] = (l - 1) * PITCONST;
|
||||
pit_set_out(t, 1);
|
||||
pit.thit[t] = 0;
|
||||
}
|
||||
pit.enabled[t] = pit.gate[t];
|
||||
break;
|
||||
case 3: /*Square wave mode*/
|
||||
if (pit.initial[t])
|
||||
{
|
||||
pit.count[t] = l;
|
||||
pit.c[t] = ((l + 1) >> 1) * PITCONST;
|
||||
pit_set_out(t, 1);
|
||||
pit.thit[t] = 0;
|
||||
}
|
||||
pit.enabled[t] = pit.gate[t];
|
||||
break;
|
||||
case 4: /*Software triggered stobe*/
|
||||
if (!pit.thit[t] && !pit.initial[t])
|
||||
pit.newcount[t] = 1;
|
||||
else
|
||||
{
|
||||
pit.count[t] = l;
|
||||
pit.c[t] = l * PITCONST;
|
||||
pit_set_out(t, 0);
|
||||
pit.thit[t] = 0;
|
||||
}
|
||||
pit.enabled[t] = pit.gate[t];
|
||||
break;
|
||||
case 5: /*Hardware triggered stobe*/
|
||||
pit.enabled[t] = 1;
|
||||
break;
|
||||
}
|
||||
pit.initial[t] = 0;
|
||||
pit.running[t] = pit.enabled[t] && pit.using_timer[t];
|
||||
// pclog("pit_load: t=%i running=%i thit=%i enabled=%i m=%i l=%x c=%g gate=%i\n", t, pit.running[t], pit.thit[t], pit.enabled[t], pit.m[t], pit.l[t], pit.c[t], pit.gate[t]);
|
||||
}
|
||||
|
||||
void pit_set_gate(int t, int gate)
|
||||
{
|
||||
int l = pit.l[t] ? pit.l[t] : 0x10000;
|
||||
switch (pit.m[t])
|
||||
{
|
||||
case 0: /*Interrupt on terminal count*/
|
||||
case 4: /*Software triggered stobe*/
|
||||
pit.enabled[t] = gate;
|
||||
break;
|
||||
case 1: /*Hardware retriggerable one-shot*/
|
||||
case 5: /*Hardware triggered stobe*/
|
||||
if (gate && !pit.gate[t])
|
||||
{
|
||||
pit.count[t] = l;
|
||||
pit.c[t] = l * PITCONST;
|
||||
pit_set_out(t, 0);
|
||||
pit.thit[t] = 0;
|
||||
pit.enabled[t] = 1;
|
||||
}
|
||||
break;
|
||||
case 2: /*Rate generator*/
|
||||
if (gate && !pit.gate[t])
|
||||
{
|
||||
pit.count[t] = l - 1;
|
||||
pit.c[t] = (l - 1) * PITCONST;
|
||||
pit_set_out(t, 1);
|
||||
pit.thit[t] = 0;
|
||||
}
|
||||
pit.enabled[t] = gate;
|
||||
break;
|
||||
case 3: /*Square wave mode*/
|
||||
if (gate && !pit.gate[t])
|
||||
{
|
||||
pit.count[t] = l;
|
||||
pit.c[t] = ((l + 1) >> 1) * PITCONST;
|
||||
pit_set_out(t, 1);
|
||||
pit.thit[t] = 0;
|
||||
}
|
||||
pit.enabled[t] = gate;
|
||||
break;
|
||||
}
|
||||
pit.gate[t] = gate;
|
||||
pit.running[t] = pit.enabled[t] && pit.using_timer[t];
|
||||
// pclog("pit_set_gate: t=%i gate=%i\n", t, gate);
|
||||
}
|
||||
|
||||
static void pit_over(int t)
|
||||
{
|
||||
int l = pit.l[t] ? pit.l[t] : 0x10000;
|
||||
switch (pit.m[t])
|
||||
{
|
||||
case 0: /*Interrupt on terminal count*/
|
||||
case 1: /*Hardware retriggerable one-shot*/
|
||||
if (!pit.thit[t])
|
||||
pit_set_out(t, 1);
|
||||
pit.thit[t] = 1;
|
||||
pit.count[t] += 0xffff;
|
||||
pit.c[t] += 0xffff * PITCONST;
|
||||
break;
|
||||
case 2: /*Rate generator*/
|
||||
pit.count[t] += l;
|
||||
pit.c[t] += l * PITCONST;
|
||||
pit_set_out(t, 0);
|
||||
pit_set_out(t, 1);
|
||||
break;
|
||||
case 3: /*Square wave mode*/
|
||||
if (pit.out[t])
|
||||
{
|
||||
pit_set_out(t, 0);
|
||||
pit.count[t] += (l >> 1);
|
||||
pit.c[t] += (l >> 1) * PITCONST;
|
||||
}
|
||||
else
|
||||
{
|
||||
pit_set_out(t, 1);
|
||||
pit.count[t] += ((l + 1) >> 1);
|
||||
pit.c[t] = ((l + 1) >> 1) * PITCONST;
|
||||
}
|
||||
break;
|
||||
case 4: /*Software triggered strove*/
|
||||
if (!pit.thit[t])
|
||||
{
|
||||
pit_set_out(t, 0);
|
||||
pit_set_out(t, 1);
|
||||
}
|
||||
if (pit.newcount[t])
|
||||
{
|
||||
pit.newcount[t] = 0;
|
||||
pit.count[t] += l;
|
||||
pit.c[t] += l * PITCONST;
|
||||
}
|
||||
else
|
||||
{
|
||||
pit.thit[t] = 1;
|
||||
pit.count[t] += 0xffff;
|
||||
pit.c[t] += 0xffff * PITCONST;
|
||||
}
|
||||
break;
|
||||
case 5: /*Hardware triggered strove*/
|
||||
if (!pit.thit[t])
|
||||
{
|
||||
pit_set_out(t, 0);
|
||||
pit_set_out(t, 1);
|
||||
}
|
||||
pit.thit[t] = 1;
|
||||
break;
|
||||
}
|
||||
pit.running[t] = pit.enabled[t] && pit.using_timer[t];
|
||||
}
|
||||
|
||||
static int pit_read_timer(int t)
|
||||
{
|
||||
// pclog("pit_read_timer: t=%i using_timer=%i m=%i\n", t, pit.using_timer[t], pit.m[t]);
|
||||
if (pit.using_timer[t])
|
||||
{
|
||||
int read = pit.c[t] / PITCONST;
|
||||
if (pit.m[t] == 2)
|
||||
read++;
|
||||
if (read < 0)
|
||||
read = 0;
|
||||
if (read > 0x10000)
|
||||
read = 0x10000;
|
||||
if (pit.m[t] == 3)
|
||||
read <<= 1;
|
||||
return read;
|
||||
}
|
||||
if (pit.m[t] == 2)
|
||||
return pit.count[t] + 1;
|
||||
return pit.count[t];
|
||||
}
|
||||
|
||||
extern int ins;
|
||||
void pit_write(uint16_t addr, uint8_t val, void *priv)
|
||||
{
|
||||
int t;
|
||||
cycles -= (int)PITCONST;
|
||||
// printf("Write PIT %04X %02X %04X:%08X %i %i\n",addr,val,CS,pc,ins);
|
||||
// if (val != 0x40) pclog("Write PIT %04X %02X %04X:%08X %i %i\n",addr,val,CS,pc,ins, pit.gate[0]);
|
||||
switch (addr&3)
|
||||
{
|
||||
case 3: /*CTRL*/
|
||||
|
|
@ -82,12 +281,16 @@ void pit_write(uint16_t addr, uint8_t val, void *priv)
|
|||
{
|
||||
if (!(val&0x20))
|
||||
{
|
||||
if (val&2) pit.rl[0]=pit.c[0]/PITCONST;
|
||||
if (val&4) pit.rl[1]=pit.c[1]/PITCONST;
|
||||
if (val&8) pit.rl[2]=pit.c[2]/PITCONST;
|
||||
if (val & 2)
|
||||
pit.rl[0] = pit.using_timer[0] ? (pit.c[0] / PITCONST) : pit.count[0];
|
||||
if (val & 4)
|
||||
pit.rl[1] = pit.using_timer[1] ? (pit.c[1] / PITCONST) : pit.count[1];
|
||||
if (val & 8)
|
||||
pit.rl[2] = pit.using_timer[2] ? (pit.c[2] / PITCONST) : pit.count[2];
|
||||
}
|
||||
return;
|
||||
}
|
||||
t = val >> 6;
|
||||
pit.ctrls[val>>6]=pit.ctrl=val;
|
||||
if ((val>>7)==3)
|
||||
{
|
||||
|
|
@ -99,26 +302,26 @@ void pit_write(uint16_t addr, uint8_t val, void *priv)
|
|||
// printf("CTRL write %02X\n",val);
|
||||
if (!(pit.ctrl&0x30))
|
||||
{
|
||||
pit.rl[val>>6]=pit.c[val>>6]/PITCONST;
|
||||
if (pit.c[val>>6]<0) pit.rl[val>>6]=0;
|
||||
pit.rl[t] = pit_read_timer(t);
|
||||
// pclog("Timer latch %f %04X %04X\n",pit.c[0],pit.rl[0],pit.l[0]);
|
||||
pit.ctrl|=0x30;
|
||||
pit.rereadlatch[val>>6]=0;
|
||||
pit.rm[val>>6]=3;
|
||||
pit.ctrl |= 0x30;
|
||||
pit.rereadlatch[t] = 0;
|
||||
pit.rm[t] = 3;
|
||||
}
|
||||
else
|
||||
{
|
||||
pit.rm[val>>6]=pit.wm[val>>6]=(pit.ctrl>>4)&3;
|
||||
pit.m[val>>6]=(val>>1)&7;
|
||||
if (pit.m[val>>6]>5)
|
||||
pit.m[val>>6]&=3;
|
||||
if (!(pit.rm[val>>6]))
|
||||
{
|
||||
pit.rm[val>>6]=3;
|
||||
pit.rl[val>>6]=pit.c[val>>6]/PITCONST;
|
||||
}
|
||||
pit.rereadlatch[val>>6]=1;
|
||||
if ((val>>6)==2) ppispeakon=speakon=(pit.m[2]==0)?0:1;
|
||||
pit.rm[val>>6]=pit.wm[val>>6]=(pit.ctrl>>4)&3;
|
||||
pit.m[val>>6]=(val>>1)&7;
|
||||
if (pit.m[val>>6]>5)
|
||||
pit.m[val>>6]&=3;
|
||||
if (!(pit.rm[val>>6]))
|
||||
{
|
||||
pit.rm[val>>6]=3;
|
||||
pit.rl[t] = pit_read_timer(t);
|
||||
}
|
||||
pit.rereadlatch[val>>6]=1;
|
||||
if ((val>>6)==2) ppispeakon=speakon=(pit.m[2]==0)?0:1;
|
||||
pit.initial[t] = 1;
|
||||
// pclog("ppispeakon %i\n",ppispeakon);
|
||||
}
|
||||
pit.wp=0;
|
||||
|
|
@ -132,196 +335,188 @@ void pit_write(uint16_t addr, uint8_t val, void *priv)
|
|||
{
|
||||
case 1:
|
||||
pit.l[t]=val;
|
||||
pit.thit[t]=0;
|
||||
pit.c[t]=pit.l[t]*PITCONST;
|
||||
if (!t)
|
||||
picintc(1);
|
||||
// pit.thit[t]=0;
|
||||
pit_load(t);
|
||||
// pit.c[t]=pit.l[t]*PITCONST;
|
||||
// if (!t)
|
||||
// picintc(1);
|
||||
break;
|
||||
case 2:
|
||||
pit.l[t]=(val<<8);
|
||||
pit.thit[t]=0;
|
||||
pit.c[t]=pit.l[t]*PITCONST;
|
||||
if (!t)
|
||||
picintc(1);
|
||||
// pit.thit[t]=0;
|
||||
pit_load(t);
|
||||
// pit.c[t]=pit.l[t]*PITCONST;
|
||||
// if (!t)
|
||||
// picintc(1);
|
||||
break;
|
||||
case 0:
|
||||
pit.l[t]&=0xFF;
|
||||
pit.l[t]|=(val<<8);
|
||||
pit.c[t]=pit.l[t]*PITCONST;
|
||||
pit_load(t);
|
||||
// pit.c[t]=pit.l[t]*PITCONST;
|
||||
// pclog("%04X %f\n",pit.l[t],pit.c[t]);
|
||||
pit.thit[t]=0;
|
||||
// pit.thit[t]=0;
|
||||
pit.wm[t]=3;
|
||||
if (!t)
|
||||
picintc(1);
|
||||
// if (!t)
|
||||
// picintc(1);
|
||||
break;
|
||||
case 3:
|
||||
pit.l[t]&=0xFF00;
|
||||
pit.l[t]|=val;
|
||||
pit.wm[t]=0;
|
||||
break;
|
||||
/*
|
||||
if (pit.wp)
|
||||
{
|
||||
pit.l[t]&=0xFF;
|
||||
pit.l[t]|=(val<<8);
|
||||
pit.c[t]=pit.l[t]*PITCONST;
|
||||
pit.thit[t]=0;
|
||||
}
|
||||
else
|
||||
{
|
||||
pit.l[t]&=0xFF00;
|
||||
pit.l[t]|=val;
|
||||
}
|
||||
pit.rl[t]=pit.l[t];
|
||||
pit.wp^=1;
|
||||
pit.rm[t]=3;
|
||||
pit.rereadlatch[t]=1;
|
||||
break;*/
|
||||
}
|
||||
speakval=(((float)pit.l[2]/(float)pit.l[0])*0x4000)-0x2000;
|
||||
// printf("Speakval now %i\n",speakval);
|
||||
// if (speakval>0x2000)
|
||||
// printf("Speaker overflow - %i %i %04X %04X\n",pit.l[0],pit.l[2],pit.l[0],pit.l[2]);
|
||||
if (speakval>0x2000) speakval=0x2000;
|
||||
if (!pit.l[t])
|
||||
/* if (!pit.l[t])
|
||||
{
|
||||
pit.l[t]|=0x10000;
|
||||
pit.c[t]=pit.l[t]*PITCONST;
|
||||
}
|
||||
}*/
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t pit_read(uint16_t addr, void *priv)
|
||||
{
|
||||
int t;
|
||||
uint8_t temp;
|
||||
cycles -= (int)PITCONST;
|
||||
// printf("Read PIT %04X ",addr);
|
||||
switch (addr&3)
|
||||
{
|
||||
case 0: case 1: case 2: /*Timers*/
|
||||
if (pit.rereadlatch[addr&3])// || !(pit.ctrls[addr&3]&0x30))
|
||||
t = addr & 3;
|
||||
if (pit.rereadlatch[addr & 3])
|
||||
{
|
||||
pit.rereadlatch[addr&3]=0;
|
||||
pit.rl[addr&3]=pit.c[addr&3]/PITCONST;
|
||||
if ((pit.c[addr&3]/PITCONST)>65536) pit.rl[addr&3]=0xFFFF;
|
||||
pit.rereadlatch[addr & 3] = 0;
|
||||
pit.rl[t] = pit_read_timer(t);
|
||||
}
|
||||
switch (pit.rm[addr&3])
|
||||
switch (pit.rm[addr & 3])
|
||||
{
|
||||
case 0:
|
||||
temp=pit.rl[addr&3]>>8;
|
||||
pit.rm[addr&3]=3;
|
||||
pit.rereadlatch[addr&3]=1;
|
||||
temp = pit.rl[addr & 3] >> 8;
|
||||
pit.rm[addr & 3] = 3;
|
||||
pit.rereadlatch[addr & 3] = 1;
|
||||
break;
|
||||
case 1:
|
||||
temp=(pit.rl[addr&3])&0xFF;
|
||||
pit.rereadlatch[addr&3]=1;
|
||||
temp = (pit.rl[addr & 3]) & 0xFF;
|
||||
pit.rereadlatch[addr & 3] = 1;
|
||||
break;
|
||||
case 2:
|
||||
temp=(pit.rl[addr&3])>>8;
|
||||
pit.rereadlatch[addr&3]=1;
|
||||
temp = (pit.rl[addr & 3]) >> 8;
|
||||
pit.rereadlatch[addr & 3] = 1;
|
||||
break;
|
||||
case 3:
|
||||
temp=(pit.rl[addr&3])&0xFF;
|
||||
if (pit.m[addr&3]&0x80) pit.m[addr&3]&=7;
|
||||
else pit.rm[addr&3]=0;
|
||||
temp = (pit.rl[addr & 3]) & 0xFF;
|
||||
if (pit.m[addr & 3] & 0x80)
|
||||
pit.m[addr & 3] &= 7;
|
||||
else
|
||||
pit.rm[addr & 3] = 0;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 3: /*Control*/
|
||||
temp=pit.ctrl;
|
||||
temp = pit.ctrl;
|
||||
break;
|
||||
}
|
||||
// pclog("%02X\n", temp);
|
||||
// printf("%02X %i %i %04X:%04X\n",temp,pit.rm[addr&3],pit.wp,cs>>4,pc);
|
||||
return temp;
|
||||
}
|
||||
|
||||
void pit_poll()
|
||||
{
|
||||
pitsec++;
|
||||
// printf("Poll pit %f %f %f\n",pit.c[0],pit.c[1],pit.c[2]);
|
||||
if (pit.c[0]<1)
|
||||
{
|
||||
if (pit.m[0]==0 || pit.m[0]==4)
|
||||
{
|
||||
// pit.c[0]&=0xFFFF;
|
||||
pit.c[0]+=(0x10000*PITCONST);
|
||||
}
|
||||
else if (pit.m[0]==3 || pit.m[0]==2)
|
||||
{
|
||||
if (pit.l[0]) pit.c[0]+=((float)(pit.l[0]*PITCONST));
|
||||
else pit.c[0]+=((float)(0x10000*PITCONST));
|
||||
}
|
||||
// pit.c[0]+=(pit.l[0]*PITCONST);
|
||||
// if (output) printf("PIT over! %f %i\n",pit.c[0],pit.m[0]);
|
||||
if (!pit.thit[0])// && (pit.l[0]>0x14))
|
||||
{
|
||||
// printf("PIT int!\n");
|
||||
/// printf("%05X %05X %02X\n",pit.c[0],pit.l[0],pit.ctrls[0]);
|
||||
picint(1);
|
||||
}
|
||||
if (!pit.m[0] || pit.m[0]==4) pit.thit[0]=1;
|
||||
// if ((pit.ctrls[0]&0xE)==2) pit.thit[0]=1;
|
||||
pitcount++;
|
||||
}
|
||||
if (pit.c[1]<1)
|
||||
{
|
||||
// if (output) printf("PIT1 over %02X\n",pit.m[1]);
|
||||
if (pit.m[1]==0 || pit.m[1]==4)
|
||||
{
|
||||
pit.c[1]=0xFFFFFF*PITCONST;
|
||||
}
|
||||
else
|
||||
{
|
||||
pit.c[1]+=(pit.l[1]*PITCONST);
|
||||
}
|
||||
// if (output) pclog("%f %04X %02X\n",pit.c[1],pit.l[1],pit.ctrls[1]);
|
||||
// printf("DMA0!\n");
|
||||
dma_channel_read(0);
|
||||
if (AT)
|
||||
ppi.pb ^= 0x10;
|
||||
}
|
||||
if (pit.c[2]<1)
|
||||
{
|
||||
// printf("PIT 2 over %i\n",pit.m[2]);
|
||||
if (!pit.m[2] || pit.m[2]==4)
|
||||
{
|
||||
pit.c[2]+=(0x10000*PITCONST);
|
||||
speakon^=1;
|
||||
ppispeakon^=1;
|
||||
}
|
||||
else
|
||||
{
|
||||
pit.c[2]+=((pit.l[2]*PITCONST)/2);
|
||||
if (pit.l[2]>0x30) /*Some games use very high frequencies as 'speaker off'. This stops them from generating noise*/
|
||||
speakon^=1;
|
||||
ppispeakon^=1;
|
||||
// printf("Speakon %i %04X %i\n",speakon,pit.l[2],pit.c[2]);
|
||||
}
|
||||
// if (pit.ctrls[2]&0xE) pit.c[2]+=(pit.l[2]*PITCONST);
|
||||
// spkstat^=0x20;
|
||||
}
|
||||
if (pit.c[0] < 1 && pit.running[0])
|
||||
pit_over(0);
|
||||
if (pit.c[1] < 1 && pit.running[1])
|
||||
pit_over(1);
|
||||
if (pit.c[2] < 1 && pit.running[2])
|
||||
pit_over(2);
|
||||
}
|
||||
|
||||
void pit_set_gate(int channel, int gate)
|
||||
void pit_clock(int t)
|
||||
{
|
||||
if (gate && !pit.gate[channel])
|
||||
{
|
||||
switch (pit.m[channel])
|
||||
{
|
||||
case 1: /*Hardware retriggerable one-shot*/
|
||||
case 2: /*Rate generator*/
|
||||
case 3: /*Square wave mode*/
|
||||
case 5: /*Hardware triggered strobe (retriggerable)*/
|
||||
pit.c[channel] = pit.l[2] * PITCONST;
|
||||
break;
|
||||
}
|
||||
}
|
||||
pit.gate[channel] = gate;
|
||||
if (pit.thit[t] || !pit.enabled[t])
|
||||
return;
|
||||
|
||||
if (pit.using_timer[t])
|
||||
return;
|
||||
|
||||
pit.count[t] -= (pit.m[t] == 3) ? 2 : 1;
|
||||
if (!pit.count[t])
|
||||
pit_over(t);
|
||||
}
|
||||
|
||||
void pit_set_using_timer(int t, int using_timer)
|
||||
{
|
||||
// pclog("pit_set_using_timer: t=%i using_timer=%i\n", t, using_timer);
|
||||
if (pit.using_timer[t] && !using_timer)
|
||||
pit.count[t] = pit_read_timer(t);
|
||||
if (!pit.using_timer[t] && using_timer)
|
||||
pit.c[t] = pit.count[t] * PITCONST;
|
||||
pit.using_timer[t] = using_timer;
|
||||
pit.running[t] = pit.enabled[t] && pit.using_timer[t];
|
||||
}
|
||||
|
||||
void pit_set_out_func(int t, void (*func)(int new_out, int old_out))
|
||||
{
|
||||
pit_set_out_funcs[t] = func;
|
||||
}
|
||||
|
||||
void pit_null_timer(int new_out, int old_out)
|
||||
{
|
||||
}
|
||||
|
||||
void pit_irq0_timer(int new_out, int old_out)
|
||||
{
|
||||
if (new_out && !old_out)
|
||||
picint(1);
|
||||
if (!new_out)
|
||||
picintc(1);
|
||||
}
|
||||
|
||||
void pit_irq0_timer_pcjr(int new_out, int old_out)
|
||||
{
|
||||
if (new_out && !old_out)
|
||||
{
|
||||
picint(1);
|
||||
pit_clock(1);
|
||||
}
|
||||
if (!new_out)
|
||||
picintc(1);
|
||||
}
|
||||
|
||||
void pit_refresh_timer_xt(int new_out, int old_out)
|
||||
{
|
||||
if (new_out && !old_out)
|
||||
dma_channel_read(0);
|
||||
}
|
||||
|
||||
void pit_refresh_timer_at(int new_out, int old_out)
|
||||
{
|
||||
if (new_out && !old_out)
|
||||
ppi.pb ^= 0x10;
|
||||
}
|
||||
|
||||
void pit_speaker_timer(int new_out, int old_out)
|
||||
{
|
||||
speakon = ppispeakon = new_out;
|
||||
}
|
||||
|
||||
|
||||
void pit_init()
|
||||
{
|
||||
io_sethandler(0x0040, 0x0004, pit_read, NULL, NULL, pit_write, NULL, NULL, NULL);
|
||||
pit.gate[0] = pit.gate[1] = 1;
|
||||
pit.gate[2] = 0;
|
||||
pit.using_timer[0] = pit.using_timer[1] = pit.using_timer[2] = 1;
|
||||
|
||||
pit_set_out_func(0, pit_irq0_timer);
|
||||
pit_set_out_func(1, pit_null_timer);
|
||||
pit_set_out_func(2, pit_speaker_timer);
|
||||
}
|
||||
|
|
|
|||
11
src/pit.h
11
src/pit.h
|
|
@ -2,3 +2,14 @@ extern double PITCONST;
|
|||
void pit_init();
|
||||
void pit_reset();
|
||||
void pit_set_gate(int channel, int gate);
|
||||
void pit_set_using_timer(int t, int using_timer);
|
||||
void pit_set_out_func(int t, void (*func)(int new_out, int old_out));
|
||||
void pit_clock(int t);
|
||||
|
||||
|
||||
void pit_null_timer(int new_out, int old_out);
|
||||
void pit_irq0_timer(int new_out, int old_out);
|
||||
void pit_irq0_timer_pcjr(int new_out, int old_out);
|
||||
void pit_refresh_timer_xt(int new_out, int old_out);
|
||||
void pit_refresh_timer_at(int new_out, int old_out);
|
||||
void pit_speaker_timer(int new_out, int old_out);
|
||||
|
|
|
|||
308
src/serial.c
308
src/serial.c
|
|
@ -5,211 +5,251 @@
|
|||
#include "serial.h"
|
||||
#include "timer.h"
|
||||
|
||||
SERIAL serial,serial2;
|
||||
enum
|
||||
{
|
||||
SERIAL_INT_LSR = 1,
|
||||
SERIAL_INT_RECEIVE = 2,
|
||||
SERIAL_INT_TRANSMIT = 4,
|
||||
SERIAL_INT_MSR = 8
|
||||
};
|
||||
|
||||
SERIAL serial1, serial2;
|
||||
|
||||
int mousepos=-1;
|
||||
int mousedelay;
|
||||
uint8_t serial_fifo[256];
|
||||
int serial_fifo_read, serial_fifo_write;
|
||||
|
||||
void (*serial_rcr)();
|
||||
|
||||
void serial_reset()
|
||||
{
|
||||
serial.iir=serial.ier=serial.lcr=0;
|
||||
serial2.iir=serial2.ier=serial2.lcr=0;
|
||||
mousedelay=0;
|
||||
serial_fifo_read = serial_fifo_write = 0;
|
||||
serial1.iir = serial1.ier = serial1.lcr = 0;
|
||||
serial2.iir = serial2.ier = serial2.lcr = 0;
|
||||
mousedelay = 0;
|
||||
serial1.fifo_read = serial1.fifo_write = 0;
|
||||
serial2.fifo_read = serial2.fifo_write = 0;
|
||||
}
|
||||
|
||||
void serial_write_fifo(uint8_t dat)
|
||||
void serial_update_ints(SERIAL *serial)
|
||||
{
|
||||
serial_fifo[serial_fifo_write] = dat;
|
||||
serial_fifo_write = (serial_fifo_write + 1) & 0xFF;
|
||||
if (!(serial.linestat & 1))
|
||||
int stat = 0;
|
||||
|
||||
serial->iir = 1;
|
||||
|
||||
if ((serial->ier & 4) && (serial->int_status & SERIAL_INT_LSR)) /*Line status interrupt*/
|
||||
{
|
||||
serial.linestat|=1;
|
||||
if ((serial.mctrl & 8) && (serial.ier & 1))
|
||||
picint(0x10);
|
||||
serial.iir=4;
|
||||
stat = 1;
|
||||
serial->iir = 6;
|
||||
}
|
||||
else if ((serial->ier & 1) && (serial->int_status & SERIAL_INT_RECEIVE)) /*Recieved data available*/
|
||||
{
|
||||
stat = 1;
|
||||
serial->iir = 4;
|
||||
}
|
||||
else if ((serial->ier & 2) && (serial->int_status & SERIAL_INT_TRANSMIT)) /*Transmit data empty*/
|
||||
{
|
||||
stat = 1;
|
||||
serial->iir = 2;
|
||||
}
|
||||
else if ((serial->ier & 8) && (serial->int_status & SERIAL_INT_MSR)) /*Modem status interrupt*/
|
||||
{
|
||||
stat = 1;
|
||||
serial->iir = 0;
|
||||
}
|
||||
|
||||
if (stat && ((serial->mctrl & 8) || PCJR))
|
||||
picintlevel(1 << serial->irq);
|
||||
else
|
||||
picintc(1 << serial->irq);
|
||||
}
|
||||
|
||||
void serial_write_fifo(SERIAL *serial, uint8_t dat)
|
||||
{
|
||||
// pclog("serial_write_fifo %02X\n", serial->lsr);
|
||||
serial->fifo[serial->fifo_write] = dat;
|
||||
serial->fifo_write = (serial->fifo_write + 1) & 0xFF;
|
||||
if (!(serial->lsr & 1))
|
||||
{
|
||||
serial->lsr |= 1;
|
||||
serial->int_status |= SERIAL_INT_RECEIVE;
|
||||
serial_update_ints(serial);
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t serial_read_fifo()
|
||||
uint8_t serial_read_fifo(SERIAL *serial)
|
||||
{
|
||||
if (serial_fifo_read != serial_fifo_write)
|
||||
if (serial->fifo_read != serial->fifo_write)
|
||||
{
|
||||
serial.dat = serial_fifo[serial_fifo_read];
|
||||
serial_fifo_read = (serial_fifo_read + 1) & 0xFF;
|
||||
serial->dat = serial->fifo[serial->fifo_read];
|
||||
serial->fifo_read = (serial->fifo_read + 1) & 0xFF;
|
||||
}
|
||||
return serial.dat;
|
||||
return serial->dat;
|
||||
}
|
||||
|
||||
void sendserial(uint8_t dat)
|
||||
{
|
||||
serial.rcr=dat;
|
||||
serial.linestat|=1;
|
||||
if (serial.mctrl&8) picint(0x10);
|
||||
serial.iir=4;
|
||||
}
|
||||
|
||||
void serial_write(uint16_t addr, uint8_t val, void *priv)
|
||||
void serial_write(uint16_t addr, uint8_t val, void *p)
|
||||
{
|
||||
SERIAL *serial = (SERIAL *)p;
|
||||
// pclog("Write serial %03X %02X %04X:%04X\n",addr,val,CS,pc);
|
||||
switch (addr&7)
|
||||
{
|
||||
case 0:
|
||||
if (serial.lcr&0x80 && !AMSTRADIO)
|
||||
if (serial->lcr & 0x80 && !AMSTRADIO)
|
||||
{
|
||||
serial.dlab1=val;
|
||||
serial->dlab1 = val;
|
||||
return;
|
||||
}
|
||||
serial.thr=val;
|
||||
serial.linestat|=0x20;
|
||||
if (serial.mctrl&0x10)
|
||||
serial->thr = val;
|
||||
serial->lsr |= 0x20;
|
||||
serial->int_status |= SERIAL_INT_TRANSMIT;
|
||||
serial_update_ints(serial);
|
||||
if (serial->mctrl & 0x10)
|
||||
{
|
||||
serial_write_fifo(val);
|
||||
// serial.rcr=val;
|
||||
// serial.linestat|=1;
|
||||
serial_write_fifo(serial, val);
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
if (serial.lcr&0x80 && !AMSTRADIO)
|
||||
if (serial->lcr & 0x80 && !AMSTRADIO)
|
||||
{
|
||||
serial.dlab2=val;
|
||||
serial->dlab2 = val;
|
||||
return;
|
||||
}
|
||||
serial.ier=val;
|
||||
serial->ier = val;
|
||||
serial_update_ints(serial);
|
||||
break;
|
||||
case 3:
|
||||
serial->lcr = val;
|
||||
break;
|
||||
case 3: serial.lcr=val; break;
|
||||
case 4:
|
||||
if ((val&2) && !(serial.mctrl&2))
|
||||
if ((val & 2) && !(serial->mctrl & 2))
|
||||
{
|
||||
if (serial_rcr)
|
||||
serial_rcr();
|
||||
if (serial->rcr_callback)
|
||||
serial->rcr_callback(serial);
|
||||
// pclog("RCR raised! sending M\n");
|
||||
}
|
||||
serial.mctrl=val;
|
||||
serial->mctrl = val;
|
||||
if (val & 0x10)
|
||||
{
|
||||
uint8_t new_msr;
|
||||
|
||||
new_msr = (val & 0x0c) << 4;
|
||||
new_msr |= (val & 0x02) ? 0x10: 0;
|
||||
new_msr |= (val & 0x01) ? 0x20: 0;
|
||||
|
||||
if ((serial->msr ^ new_msr) & 0x10)
|
||||
new_msr |= 0x01;
|
||||
if ((serial->msr ^ new_msr) & 0x20)
|
||||
new_msr |= 0x02;
|
||||
if ((serial->msr ^ new_msr) & 0x80)
|
||||
new_msr |= 0x08;
|
||||
if ((serial->msr & 0x40) && !(new_msr & 0x40))
|
||||
new_msr |= 0x04;
|
||||
|
||||
serial->msr = new_msr;
|
||||
}
|
||||
break;
|
||||
case 5:
|
||||
serial->lsr = val;
|
||||
if (serial->lsr & 0x01)
|
||||
serial->int_status |= SERIAL_INT_RECEIVE;
|
||||
if (serial->lsr & 0x1e)
|
||||
serial->int_status |= SERIAL_INT_LSR;
|
||||
if (serial->lsr & 0x20)
|
||||
serial->int_status |= SERIAL_INT_TRANSMIT;
|
||||
serial_update_ints(serial);
|
||||
break;
|
||||
case 6:
|
||||
serial->msr = val;
|
||||
if (serial->msr & 0x0f)
|
||||
serial->int_status |= SERIAL_INT_MSR;
|
||||
serial_update_ints(serial);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t serial_read(uint16_t addr, void *priv)
|
||||
uint8_t serial_read(uint16_t addr, void *p)
|
||||
{
|
||||
uint8_t temp;
|
||||
SERIAL *serial = (SERIAL *)p;
|
||||
uint8_t temp = 0;
|
||||
// pclog("Read serial %03X %04X(%08X):%04X %i %i ", addr, CS, cs, pc, mousedelay, ins);
|
||||
switch (addr&7)
|
||||
{
|
||||
case 0:
|
||||
if (serial.lcr&0x80 && !AMSTRADIO) return serial.dlab1;
|
||||
// picintc(0x10);
|
||||
serial.iir=1;
|
||||
serial.linestat&=~1;
|
||||
temp=serial_read_fifo();
|
||||
if (serial_fifo_read != serial_fifo_write)
|
||||
{
|
||||
mousepos = 0;
|
||||
mousedelay = 5000 * (1 << TIMER_SHIFT);
|
||||
// pclog("Next FIFO\n");
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
if (serial.lcr&0x80 && !AMSTRADIO) temp = serial.dlab2;
|
||||
else temp = serial.ier;
|
||||
break;
|
||||
case 2: temp=serial.iir; break;
|
||||
case 3: temp=serial.lcr; break;
|
||||
case 4: temp=serial.mctrl; break;
|
||||
case 5: temp=serial.linestat; serial.linestat|=0x60; break;
|
||||
default: temp=0;
|
||||
}
|
||||
// pclog("%02X\n",temp);
|
||||
return temp;
|
||||
}
|
||||
if (serial->lcr & 0x80 && !AMSTRADIO)
|
||||
return serial->dlab1;
|
||||
|
||||
void serial2_write(uint16_t addr, uint8_t val, void *priv)
|
||||
{
|
||||
// pclog("Write serial2 %03X %02X %04X:%04X\n",addr,val,cs>>4,pc);
|
||||
switch (addr&7)
|
||||
{
|
||||
case 0:
|
||||
if (serial2.lcr&0x80 && !AMSTRADIO)
|
||||
serial->lsr &= ~1;
|
||||
serial->int_status &= ~SERIAL_INT_RECEIVE;
|
||||
serial_update_ints(serial);
|
||||
temp = serial_read_fifo(serial);
|
||||
if (serial->fifo_read != serial->fifo_write)
|
||||
{
|
||||
serial2.dlab1=val;
|
||||
return;
|
||||
}
|
||||
serial2.thr=val;
|
||||
serial2.linestat|=0x20;
|
||||
if (serial2.mctrl&0x10)
|
||||
{
|
||||
serial2.rcr=val;
|
||||
serial2.linestat|=1;
|
||||
serial->lsr |= 1;
|
||||
serial->int_status |= SERIAL_INT_RECEIVE;
|
||||
serial_update_ints(serial);
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
if (serial2.lcr&0x80 && !AMSTRADIO)
|
||||
{
|
||||
serial2.dlab2=val;
|
||||
return;
|
||||
}
|
||||
serial2.ier=val;
|
||||
if (serial->lcr & 0x80 && !AMSTRADIO)
|
||||
temp = serial->dlab2;
|
||||
else
|
||||
temp = serial->ier;
|
||||
break;
|
||||
case 2:
|
||||
temp = serial->iir;
|
||||
if ((temp & 0xe) == 2)
|
||||
{
|
||||
serial->int_status &= ~SERIAL_INT_TRANSMIT;
|
||||
serial_update_ints(serial);
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
temp = serial->lcr;
|
||||
break;
|
||||
case 3: serial2.lcr=val; break;
|
||||
case 4:
|
||||
serial2.mctrl=val;
|
||||
temp = serial->mctrl;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t serial2_read(uint16_t addr, void *priv)
|
||||
{
|
||||
uint8_t temp;
|
||||
// pclog("Read serial2 %03X %04X:%04X\n",addr,cs>>4,pc);
|
||||
switch (addr&7)
|
||||
{
|
||||
case 0:
|
||||
if (serial2.lcr&0x80 && !AMSTRADIO) return serial2.dlab1;
|
||||
serial2.iir=1;
|
||||
serial2.linestat&=~1;
|
||||
temp=serial2.rcr;
|
||||
case 5:
|
||||
serial->lsr |= 0x20;
|
||||
temp = serial->lsr;
|
||||
if (serial->lsr & 0x1f)
|
||||
serial->lsr &= ~0x1e;
|
||||
// serial.lsr |= 0x60;
|
||||
serial->int_status &= ~SERIAL_INT_LSR;
|
||||
serial_update_ints(serial);
|
||||
break;
|
||||
case 1:
|
||||
if (serial2.lcr&0x80 && !AMSTRADIO) return serial2.dlab2;
|
||||
temp=0;
|
||||
case 6:
|
||||
temp = serial->msr;
|
||||
serial->msr &= ~0x0f;
|
||||
serial->int_status &= ~SERIAL_INT_MSR;
|
||||
serial_update_ints(serial);
|
||||
break;
|
||||
case 2: temp=serial2.iir; break;
|
||||
case 3: temp=serial2.lcr; break;
|
||||
case 4: temp=serial2.mctrl; break;
|
||||
case 5: temp=serial2.linestat; break;
|
||||
default: temp=0;
|
||||
}
|
||||
// pclog("%02X\n",temp);
|
||||
return temp;
|
||||
}
|
||||
|
||||
|
||||
/*Tandy might need COM1 at 2f8*/
|
||||
void serial1_init(uint16_t addr)
|
||||
void serial1_init(uint16_t addr, int irq)
|
||||
{
|
||||
io_sethandler(addr, 0x0008, serial_read, NULL, NULL, serial_write, NULL, NULL, NULL);
|
||||
serial_rcr = NULL;
|
||||
io_sethandler(addr, 0x0008, serial_read, NULL, NULL, serial_write, NULL, NULL, &serial1);
|
||||
serial1.irq = irq;
|
||||
serial1.rcr_callback = NULL;
|
||||
}
|
||||
void serial1_remove()
|
||||
{
|
||||
io_removehandler(0x2e8, 0x0008, serial_read, NULL, NULL, serial_write, NULL, NULL, NULL);
|
||||
io_removehandler(0x2f8, 0x0008, serial_read, NULL, NULL, serial_write, NULL, NULL, NULL);
|
||||
io_removehandler(0x3e8, 0x0008, serial_read, NULL, NULL, serial_write, NULL, NULL, NULL);
|
||||
io_removehandler(0x3f8, 0x0008, serial_read, NULL, NULL, serial_write, NULL, NULL, NULL);
|
||||
io_removehandler(0x2e8, 0x0008, serial_read, NULL, NULL, serial_write, NULL, NULL, &serial1);
|
||||
io_removehandler(0x2f8, 0x0008, serial_read, NULL, NULL, serial_write, NULL, NULL, &serial1);
|
||||
io_removehandler(0x3e8, 0x0008, serial_read, NULL, NULL, serial_write, NULL, NULL, &serial1);
|
||||
io_removehandler(0x3f8, 0x0008, serial_read, NULL, NULL, serial_write, NULL, NULL, &serial1);
|
||||
}
|
||||
|
||||
void serial2_init(uint16_t addr)
|
||||
void serial2_init(uint16_t addr, int irq)
|
||||
{
|
||||
io_sethandler(addr, 0x0008, serial2_read, NULL, NULL, serial2_write, NULL, NULL, NULL);
|
||||
io_sethandler(addr, 0x0008, serial_read, NULL, NULL, serial_write, NULL, NULL, &serial2);
|
||||
serial2.irq = irq;
|
||||
serial2.rcr_callback = NULL;
|
||||
}
|
||||
void serial2_remove()
|
||||
{
|
||||
io_removehandler(0x2e8, 0x0008, serial2_read, NULL, NULL, serial2_write, NULL, NULL, NULL);
|
||||
io_removehandler(0x2f8, 0x0008, serial2_read, NULL, NULL, serial2_write, NULL, NULL, NULL);
|
||||
io_removehandler(0x3e8, 0x0008, serial2_read, NULL, NULL, serial2_write, NULL, NULL, NULL);
|
||||
io_removehandler(0x3f8, 0x0008, serial2_read, NULL, NULL, serial2_write, NULL, NULL, NULL);
|
||||
io_removehandler(0x2e8, 0x0008, serial_read, NULL, NULL, serial_write, NULL, NULL, &serial2);
|
||||
io_removehandler(0x2f8, 0x0008, serial_read, NULL, NULL, serial_write, NULL, NULL, &serial2);
|
||||
io_removehandler(0x3e8, 0x0008, serial_read, NULL, NULL, serial_write, NULL, NULL, &serial2);
|
||||
io_removehandler(0x3f8, 0x0008, serial_read, NULL, NULL, serial_write, NULL, NULL, &serial2);
|
||||
}
|
||||
|
|
|
|||
21
src/serial.h
21
src/serial.h
|
|
@ -1,18 +1,23 @@
|
|||
void serial1_init(uint16_t addr);
|
||||
void serial2_init(uint16_t addr);
|
||||
void serial1_init(uint16_t addr, int irq);
|
||||
void serial2_init(uint16_t addr, int irq);
|
||||
void serial1_remove();
|
||||
void serial2_remove();
|
||||
void serial_reset();
|
||||
|
||||
struct SERIAL;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint8_t linestat,thr,mctrl,rcr,iir,ier,lcr;
|
||||
uint8_t lsr,thr,mctrl,rcr,iir,ier,lcr,msr;
|
||||
uint8_t dlab1,dlab2;
|
||||
uint8_t dat;
|
||||
uint8_t int_status;
|
||||
|
||||
int irq;
|
||||
|
||||
void (*rcr_callback)(void *p);
|
||||
uint8_t fifo[256];
|
||||
int fifo_read, fifo_write;
|
||||
} SERIAL;
|
||||
|
||||
extern SERIAL serial,serial2;
|
||||
|
||||
extern int serial_fifo_read, serial_fifo_write;
|
||||
|
||||
extern void (*serial_rcr)();
|
||||
extern SERIAL serial1, serial2;
|
||||
|
|
|
|||
|
|
@ -5,6 +5,8 @@
|
|||
#include "sound.h"
|
||||
#include "sound_sn76489.h"
|
||||
|
||||
int sn76489_mute;
|
||||
|
||||
static float volslog[16]=
|
||||
{
|
||||
0.00000f,0.59715f,0.75180f,0.94650f,
|
||||
|
|
@ -79,9 +81,12 @@ void sn76489_get_buffer(int16_t *buffer, int len, void *p)
|
|||
sn76489_t *sn76489 = (sn76489_t *)p;
|
||||
|
||||
int c;
|
||||
|
||||
for (c = 0; c < len * 2; c++)
|
||||
buffer[c] += sn76489->buffer[c >> 1];
|
||||
|
||||
if (!sn76489_mute)
|
||||
{
|
||||
for (c = 0; c < len * 2; c++)
|
||||
buffer[c] += sn76489->buffer[c >> 1];
|
||||
}
|
||||
|
||||
sn76489->pos = 0;
|
||||
}
|
||||
|
|
@ -179,6 +184,8 @@ void *sn76489_init()
|
|||
sn76489->noise = 3;
|
||||
sn76489->shift = 0x4000;
|
||||
|
||||
sn76489_mute = 0;
|
||||
|
||||
return sn76489;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1 +1,3 @@
|
|||
extern device_t sn76489_device;
|
||||
|
||||
extern int sn76489_mute;
|
||||
|
|
|
|||
|
|
@ -2,6 +2,8 @@
|
|||
#include "sound.h"
|
||||
#include "sound_speaker.h"
|
||||
|
||||
int speaker_mute = 0;
|
||||
|
||||
static int16_t speaker_buffer[SOUNDBUFLEN];
|
||||
|
||||
static int speaker_pos = 0;
|
||||
|
|
@ -30,8 +32,11 @@ static void speaker_get_buffer(int16_t *buffer, int len, void *p)
|
|||
{
|
||||
int c;
|
||||
|
||||
for (c = 0; c < len * 2; c++)
|
||||
buffer[c] += speaker_buffer[c >> 1];
|
||||
if (!speaker_mute)
|
||||
{
|
||||
for (c = 0; c < len * 2; c++)
|
||||
buffer[c] += speaker_buffer[c >> 1];
|
||||
}
|
||||
|
||||
speaker_pos = 0;
|
||||
}
|
||||
|
|
@ -39,4 +44,5 @@ static void speaker_get_buffer(int16_t *buffer, int len, void *p)
|
|||
void speaker_init()
|
||||
{
|
||||
sound_add_handler(speaker_poll, speaker_get_buffer, NULL);
|
||||
speaker_mute = 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1 +1,3 @@
|
|||
void speaker_init();
|
||||
|
||||
extern int speaker_mute;
|
||||
|
|
|
|||
|
|
@ -83,10 +83,10 @@ void um8669f_write(uint16_t port, uint8_t val, void *priv)
|
|||
temp |= 2;
|
||||
switch (temp)
|
||||
{
|
||||
case 0: serial1_init(0x3f8); break;
|
||||
case 1: serial1_init(0x2f8); break;
|
||||
case 2: serial1_init(0x3e8); break;
|
||||
case 3: serial1_init(0x2e8); break;
|
||||
case 0: serial1_init(0x3f8, 4); break;
|
||||
case 1: serial1_init(0x2f8, 4); break;
|
||||
case 2: serial1_init(0x3e8, 4); break;
|
||||
case 3: serial1_init(0x2e8, 4); break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -98,10 +98,10 @@ void um8669f_write(uint16_t port, uint8_t val, void *priv)
|
|||
temp |= 2;
|
||||
switch (temp)
|
||||
{
|
||||
case 0: serial2_init(0x3f8); break;
|
||||
case 1: serial2_init(0x2f8); break;
|
||||
case 2: serial2_init(0x3e8); break;
|
||||
case 3: serial2_init(0x2e8); break;
|
||||
case 0: serial2_init(0x3f8, 3); break;
|
||||
case 1: serial2_init(0x2f8, 3); break;
|
||||
case 2: serial2_init(0x3e8, 3); break;
|
||||
case 3: serial2_init(0x2e8, 3); break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
647
src/vid_pcjr.c
Normal file
647
src/vid_pcjr.c
Normal file
|
|
@ -0,0 +1,647 @@
|
|||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include "ibm.h"
|
||||
#include "device.h"
|
||||
#include "io.h"
|
||||
#include "mem.h"
|
||||
#include "timer.h"
|
||||
#include "video.h"
|
||||
#include "vid_pcjr.h"
|
||||
|
||||
static int i_filt[8],q_filt[8];
|
||||
|
||||
typedef struct pcjr_t
|
||||
{
|
||||
mem_mapping_t mapping;
|
||||
|
||||
uint8_t crtc[32];
|
||||
int crtcreg;
|
||||
|
||||
int array_index;
|
||||
uint8_t array[32];
|
||||
int array_ff;
|
||||
int memctrl;//=-1;
|
||||
uint8_t stat;
|
||||
int addr_mode;
|
||||
|
||||
uint8_t *vram, *b8000;
|
||||
|
||||
int linepos, displine;
|
||||
int sc, vc;
|
||||
int dispon;
|
||||
int con, coff, cursoron, blink;
|
||||
int vsynctime, vadj;
|
||||
uint16_t ma, maback;
|
||||
|
||||
int dispontime, dispofftime, vidtime;
|
||||
int firstline, lastline;
|
||||
} pcjr_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 pcjr_recalcaddress(pcjr_t *pcjr);
|
||||
void pcjr_recalctimings(pcjr_t *pcjr);
|
||||
|
||||
void pcjr_out(uint16_t addr, uint8_t val, void *p)
|
||||
{
|
||||
pcjr_t *pcjr = (pcjr_t *)p;
|
||||
uint8_t old;
|
||||
// pclog("pcjr OUT %04X %02X\n",addr,val);
|
||||
switch (addr)
|
||||
{
|
||||
case 0x3d4:
|
||||
pcjr->crtcreg = val & 0x1f;
|
||||
return;
|
||||
case 0x3d5:
|
||||
// pclog("CRTC write %02X %02x\n", pcjr->crtcreg, val);
|
||||
old = pcjr->crtc[pcjr->crtcreg];
|
||||
pcjr->crtc[pcjr->crtcreg] = val & crtcmask[pcjr->crtcreg];
|
||||
if (old != val)
|
||||
{
|
||||
if (pcjr->crtcreg < 0xe || pcjr->crtcreg > 0x10)
|
||||
{
|
||||
fullchange = changeframecount;
|
||||
pcjr_recalctimings(pcjr);
|
||||
}
|
||||
}
|
||||
return;
|
||||
case 0x3da:
|
||||
// pclog("Array write %02X %02X\n", pcjr->array_index, val);
|
||||
if (!pcjr->array_ff)
|
||||
pcjr->array_index = val & 0x1f;
|
||||
else
|
||||
{
|
||||
if (pcjr->array_index & 0x10)
|
||||
val &= 0x0f;
|
||||
pcjr->array[pcjr->array_index & 0x1f] = val;
|
||||
}
|
||||
pcjr->array_ff = !pcjr->array_ff;
|
||||
break;
|
||||
case 0x3df:
|
||||
pcjr->memctrl = val;
|
||||
pcjr->addr_mode = val >> 6;
|
||||
pcjr_recalcaddress(pcjr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t pcjr_in(uint16_t addr, void *p)
|
||||
{
|
||||
pcjr_t *pcjr = (pcjr_t *)p;
|
||||
// if (addr!=0x3DA) pclog("pcjr IN %04X\n",addr);
|
||||
switch (addr)
|
||||
{
|
||||
case 0x3d4:
|
||||
return pcjr->crtcreg;
|
||||
case 0x3d5:
|
||||
return pcjr->crtc[pcjr->crtcreg];
|
||||
case 0x3da:
|
||||
pcjr->array_ff = 0;
|
||||
pcjr->stat ^= 0x10;
|
||||
return pcjr->stat;
|
||||
}
|
||||
return 0xFF;
|
||||
}
|
||||
|
||||
void pcjr_recalcaddress(pcjr_t *pcjr)
|
||||
{
|
||||
if ((pcjr->memctrl & 0xc0) == 0xc0)
|
||||
{
|
||||
pcjr->vram = &ram[(pcjr->memctrl & 0x06) << 14];
|
||||
pcjr->b8000 = &ram[(pcjr->memctrl & 0x30) << 11];
|
||||
// printf("VRAM at %05X B8000 at %05X\n",((pcjr->memctrl&0x6)<<14)+pcjr->base,((pcjr->memctrl&0x30)<<11)+pcjr->base);
|
||||
}
|
||||
else
|
||||
{
|
||||
pcjr->vram = &ram[(pcjr->memctrl & 0x07) << 14];
|
||||
pcjr->b8000 = &ram[(pcjr->memctrl & 0x38) << 11];
|
||||
// printf("VRAM at %05X B8000 at %05X\n",((pcjr->memctrl&0x7)<<14)+pcjr->base,((pcjr->memctrl&0x38)<<11)+pcjr->base);
|
||||
}
|
||||
}
|
||||
|
||||
void pcjr_write(uint32_t addr, uint8_t val, void *p)
|
||||
{
|
||||
pcjr_t *pcjr = (pcjr_t *)p;
|
||||
if (pcjr->memctrl == -1)
|
||||
return;
|
||||
|
||||
egawrites++;
|
||||
// pclog("pcjr VRAM write %05X %02X %04X:%04X %04X:%04X\n",addr,val,CS,pc,DS,SI);
|
||||
pcjr->b8000[addr & 0x3fff] = val;
|
||||
}
|
||||
|
||||
uint8_t pcjr_read(uint32_t addr, void *p)
|
||||
{
|
||||
pcjr_t *pcjr = (pcjr_t *)p;
|
||||
if (pcjr->memctrl == -1)
|
||||
return 0xff;
|
||||
|
||||
egareads++;
|
||||
// pclog("pcjr VRAM read %05X %02X %04X:%04X\n",addr,pcjr->b8000[addr&0x7FFF],CS,pc);
|
||||
return pcjr->b8000[addr & 0x3fff];
|
||||
}
|
||||
|
||||
void pcjr_recalctimings(pcjr_t *pcjr)
|
||||
{
|
||||
double _dispontime, _dispofftime, disptime;
|
||||
if (pcjr->array[0] & 1)
|
||||
{
|
||||
disptime = pcjr->crtc[0] + 1;
|
||||
_dispontime = pcjr->crtc[1];
|
||||
}
|
||||
else
|
||||
{
|
||||
disptime = (pcjr->crtc[0] + 1) << 1;
|
||||
_dispontime = pcjr->crtc[1] << 1;
|
||||
}
|
||||
_dispofftime = disptime - _dispontime;
|
||||
_dispontime *= CGACONST;
|
||||
_dispofftime *= CGACONST;
|
||||
pcjr->dispontime = (int)(_dispontime * (1 << TIMER_SHIFT));
|
||||
pcjr->dispofftime = (int)(_dispofftime * (1 << TIMER_SHIFT));
|
||||
}
|
||||
|
||||
|
||||
static int ntsc_col[8][8]=
|
||||
{
|
||||
{0,0,0,0,0,0,0,0}, /*Black*/
|
||||
{0,0,1,1,1,1,0,0}, /*Blue*/
|
||||
{1,0,0,0,0,1,1,1}, /*Green*/
|
||||
{0,0,0,0,1,1,1,1}, /*Cyan*/
|
||||
{1,1,1,1,0,0,0,0}, /*Red*/
|
||||
{0,1,1,1,1,0,0,0}, /*Magenta*/
|
||||
{1,1,0,0,0,0,1,1}, /*Yellow*/
|
||||
{1,1,1,1,1,1,1,1} /*White*/
|
||||
};
|
||||
|
||||
/*static 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}
|
||||
};*/
|
||||
|
||||
void pcjr_poll(void *p)
|
||||
{
|
||||
// int *cgapal=cga4pal[((pcjr->col&0x10)>>2)|((cgamode&4)>>1)|((cgacol&0x20)>>5)];
|
||||
pcjr_t *pcjr = (pcjr_t *)p;
|
||||
uint16_t ca = (pcjr->crtc[15] | (pcjr->crtc[14] << 8)) & 0x3fff;
|
||||
int drawcursor;
|
||||
int x, c;
|
||||
int oldvc;
|
||||
uint8_t chr, attr;
|
||||
uint16_t dat;
|
||||
int cols[4];
|
||||
int col;
|
||||
int oldsc;
|
||||
int y_buf[8] = {0, 0, 0, 0, 0, 0, 0, 0}, y_val, y_tot;
|
||||
int i_buf[8] = {0, 0, 0, 0, 0, 0, 0, 0}, i_val, i_tot;
|
||||
int q_buf[8] = {0, 0, 0, 0, 0, 0, 0, 0}, q_val, q_tot;
|
||||
int r, g, b;
|
||||
if (!pcjr->linepos)
|
||||
{
|
||||
// cgapal[0]=pcjr->col&15;
|
||||
// printf("Firstline %i Lastline %i pcjr->displine %i\n",firstline,lastline,pcjr->displine);
|
||||
pcjr->vidtime += pcjr->dispofftime;
|
||||
pcjr->stat &= ~1;
|
||||
pcjr->linepos = 1;
|
||||
oldsc = pcjr->sc;
|
||||
if ((pcjr->crtc[8] & 3) == 3)
|
||||
pcjr->sc = (pcjr->sc << 1) & 7;
|
||||
if (pcjr->dispon)
|
||||
{
|
||||
uint16_t offset = 0;
|
||||
uint16_t mask = 0x1fff;
|
||||
|
||||
if (pcjr->displine < pcjr->firstline)
|
||||
pcjr->firstline = pcjr->displine;
|
||||
pcjr->lastline = pcjr->displine;
|
||||
cols[0] = (pcjr->array[2] & 0xf) + 16;
|
||||
for (c = 0; c < 8; c++)
|
||||
{
|
||||
buffer->line[pcjr->displine][c] = cols[0];
|
||||
if (pcjr->array[0] & 1) buffer->line[pcjr->displine][c + (pcjr->crtc[1] << 3) + 8] = cols[0];
|
||||
else buffer->line[pcjr->displine][c + (pcjr->crtc[1] << 4) + 8] = cols[0];
|
||||
}
|
||||
|
||||
switch (pcjr->addr_mode)
|
||||
{
|
||||
case 0: /*Alpha*/
|
||||
offset = 0;
|
||||
mask = 0x3fff;
|
||||
break;
|
||||
case 1: /*Low resolution graphics*/
|
||||
offset = (pcjr->sc & 1) * 0x2000;
|
||||
break;
|
||||
case 3: /*High resolution graphics*/
|
||||
offset = (pcjr->sc & 3) * 0x2000;
|
||||
break;
|
||||
}
|
||||
|
||||
switch ((pcjr->array[0] & 0x13) | ((pcjr->array[3] & 0x10) << 4))
|
||||
{
|
||||
case 0x13: /*320x200x16*/
|
||||
for (x = 0; x < pcjr->crtc[1]; x++)
|
||||
{
|
||||
dat = (pcjr->vram[((pcjr->ma << 1) & mask) + offset] << 8) |
|
||||
pcjr->vram[((pcjr->ma << 1) & mask) + offset + 1];
|
||||
pcjr->ma++;
|
||||
buffer->line[pcjr->displine][(x << 3) + 8] =
|
||||
buffer->line[pcjr->displine][(x << 3) + 9] = pcjr->array[((dat >> 12) & pcjr->array[1]) + 16] + 16;
|
||||
buffer->line[pcjr->displine][(x << 3) + 10] =
|
||||
buffer->line[pcjr->displine][(x << 3) + 11] = pcjr->array[((dat >> 8) & pcjr->array[1]) + 16] + 16;
|
||||
buffer->line[pcjr->displine][(x << 3) + 12] =
|
||||
buffer->line[pcjr->displine][(x << 3) + 13] = pcjr->array[((dat >> 4) & pcjr->array[1]) + 16] + 16;
|
||||
buffer->line[pcjr->displine][(x << 3) + 14] =
|
||||
buffer->line[pcjr->displine][(x << 3) + 15] = pcjr->array[(dat & pcjr->array[1]) + 16] + 16;
|
||||
}
|
||||
break;
|
||||
case 0x12: /*160x200x16*/
|
||||
for (x = 0; x < pcjr->crtc[1]; x++)
|
||||
{
|
||||
dat = (pcjr->vram[((pcjr->ma << 1) & mask) + offset] << 8) |
|
||||
pcjr->vram[((pcjr->ma << 1) & mask) + offset + 1];
|
||||
pcjr->ma++;
|
||||
buffer->line[pcjr->displine][(x << 4) + 8] =
|
||||
buffer->line[pcjr->displine][(x << 4) + 9] =
|
||||
buffer->line[pcjr->displine][(x << 4) + 10] =
|
||||
buffer->line[pcjr->displine][(x << 4) + 11] = pcjr->array[((dat >> 12) & pcjr->array[1]) + 16] + 16;
|
||||
buffer->line[pcjr->displine][(x << 4) + 12] =
|
||||
buffer->line[pcjr->displine][(x << 4) + 13] =
|
||||
buffer->line[pcjr->displine][(x << 4) + 14] =
|
||||
buffer->line[pcjr->displine][(x << 4) + 15] = pcjr->array[((dat >> 8) & pcjr->array[1]) + 16] + 16;
|
||||
buffer->line[pcjr->displine][(x << 4) + 16] =
|
||||
buffer->line[pcjr->displine][(x << 4) + 17] =
|
||||
buffer->line[pcjr->displine][(x << 4) + 18] =
|
||||
buffer->line[pcjr->displine][(x << 4) + 19] = pcjr->array[((dat >> 4) & pcjr->array[1]) + 16] + 16;
|
||||
buffer->line[pcjr->displine][(x << 4) + 20] =
|
||||
buffer->line[pcjr->displine][(x << 4) + 21] =
|
||||
buffer->line[pcjr->displine][(x << 4) + 22] =
|
||||
buffer->line[pcjr->displine][(x << 4) + 23] = pcjr->array[(dat & pcjr->array[1]) + 16] + 16;
|
||||
}
|
||||
break;
|
||||
case 0x03: /*640x200x4*/
|
||||
for (x = 0; x < pcjr->crtc[1]; x++)
|
||||
{
|
||||
dat = (pcjr->vram[((pcjr->ma << 1) & mask) + offset] << 8) |
|
||||
pcjr->vram[((pcjr->ma << 1) & mask) + offset + 1];
|
||||
pcjr->ma++;
|
||||
for (c = 0; c < 8; c++)
|
||||
{
|
||||
chr = (dat >> 7) & 1;
|
||||
chr |= ((dat >> 14) & 2);
|
||||
buffer->line[pcjr->displine][(x << 3) + 8 + c] = pcjr->array[(chr & pcjr->array[1]) + 16] + 16;
|
||||
dat <<= 1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 0x01: /*80 column text*/
|
||||
for (x = 0; x < pcjr->crtc[1]; x++)
|
||||
{
|
||||
chr = pcjr->vram[((pcjr->ma << 1) & mask) + offset];
|
||||
attr = pcjr->vram[((pcjr->ma << 1) & mask) + offset + 1];
|
||||
drawcursor = ((pcjr->ma == ca) && pcjr->con && pcjr->cursoron);
|
||||
if (pcjr->array[3] & 4)
|
||||
{
|
||||
cols[1] = pcjr->array[ ((attr & 15) & pcjr->array[1]) + 16] + 16;
|
||||
cols[0] = pcjr->array[(((attr >> 4) & 7) & pcjr->array[1]) + 16] + 16;
|
||||
if ((pcjr->blink & 16) && (attr & 0x80) && !drawcursor)
|
||||
cols[1] = cols[0];
|
||||
}
|
||||
else
|
||||
{
|
||||
cols[1] = pcjr->array[((attr & 15) & pcjr->array[1]) + 16] + 16;
|
||||
cols[0] = pcjr->array[((attr >> 4) & pcjr->array[1]) + 16] + 16;
|
||||
}
|
||||
if (pcjr->sc & 8)
|
||||
{
|
||||
for (c = 0; c < 8; c++)
|
||||
buffer->line[pcjr->displine][(x << 3) + c + 8] = cols[0];
|
||||
}
|
||||
else
|
||||
{
|
||||
for (c = 0; c < 8; c++)
|
||||
buffer->line[pcjr->displine][(x << 3) + c + 8] = cols[(fontdat[chr][pcjr->sc & 7] & (1 << (c ^ 7))) ? 1 : 0];
|
||||
}
|
||||
// if (!((ma^(crtc[15]|(crtc[14]<<8)))&0x3FFF)) printf("Cursor match! %04X\n",ma);
|
||||
if (drawcursor)
|
||||
{
|
||||
for (c = 0; c < 8; c++)
|
||||
buffer->line[pcjr->displine][(x << 3) + c + 8] ^= 15;
|
||||
}
|
||||
pcjr->ma++;
|
||||
}
|
||||
break;
|
||||
case 0x00: /*40 column text*/
|
||||
for (x = 0; x < pcjr->crtc[1]; x++)
|
||||
{
|
||||
chr = pcjr->vram[((pcjr->ma << 1) & mask) + offset];
|
||||
attr = pcjr->vram[((pcjr->ma << 1) & mask) + offset + 1];
|
||||
drawcursor = ((pcjr->ma == ca) && pcjr->con && pcjr->cursoron);
|
||||
if (pcjr->array[3] & 4)
|
||||
{
|
||||
cols[1] = pcjr->array[ ((attr & 15) & pcjr->array[1]) + 16] + 16;
|
||||
cols[0] = pcjr->array[(((attr >> 4) & 7) & pcjr->array[1]) + 16] + 16;
|
||||
if ((pcjr->blink & 16) && (attr & 0x80) && !drawcursor)
|
||||
cols[1] = cols[0];
|
||||
}
|
||||
else
|
||||
{
|
||||
cols[1] = pcjr->array[((attr & 15) & pcjr->array[1]) + 16] + 16;
|
||||
cols[0] = pcjr->array[((attr >> 4) & pcjr->array[1]) + 16] + 16;
|
||||
}
|
||||
pcjr->ma++;
|
||||
if (pcjr->sc & 8)
|
||||
{
|
||||
for (c = 0; c < 8; c++)
|
||||
buffer->line[pcjr->displine][(x << 4) + (c << 1) + 8] =
|
||||
buffer->line[pcjr->displine][(x << 4) + (c << 1) + 1 + 8] = cols[0];
|
||||
}
|
||||
else
|
||||
{
|
||||
for (c = 0; c < 8; c++)
|
||||
buffer->line[pcjr->displine][(x << 4) + (c << 1) + 8] =
|
||||
buffer->line[pcjr->displine][(x << 4) + (c << 1) + 1 + 8] = cols[(fontdat[chr][pcjr->sc & 7] & (1 << (c ^ 7))) ? 1 : 0];
|
||||
}
|
||||
if (drawcursor)
|
||||
{
|
||||
for (c = 0; c < 16; c++)
|
||||
buffer->line[pcjr->displine][(x << 4) + c + 8] ^= 15;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 0x02: /*320x200x4*/
|
||||
cols[0] = pcjr->array[0 + 16] + 16;
|
||||
cols[1] = pcjr->array[1 + 16] + 16;
|
||||
cols[2] = pcjr->array[2 + 16] + 16;
|
||||
cols[3] = pcjr->array[3 + 16] + 16;
|
||||
for (x = 0; x < pcjr->crtc[1]; x++)
|
||||
{
|
||||
dat = (pcjr->vram[((pcjr->ma << 1) & mask) + offset] << 8) |
|
||||
pcjr->vram[((pcjr->ma << 1) & mask) + offset + 1];
|
||||
pcjr->ma++;
|
||||
for (c = 0; c < 8; c++)
|
||||
{
|
||||
buffer->line[pcjr->displine][(x << 4) + (c << 1) + 8] =
|
||||
buffer->line[pcjr->displine][(x << 4) + (c << 1) + 1 + 8] = cols[dat >> 14];
|
||||
dat <<= 2;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 0x102: /*640x200x2*/
|
||||
cols[0] = 0;
|
||||
cols[1] = pcjr->array[0 + 16] + 16;
|
||||
for (x = 0; x < pcjr->crtc[1]; x++)
|
||||
{
|
||||
dat = (pcjr->vram[((pcjr->ma << 1) & mask) + offset] << 8) |
|
||||
pcjr->vram[((pcjr->ma << 1) & mask) + offset + 1];
|
||||
pcjr->ma++;
|
||||
for (c = 0; c < 16; c++)
|
||||
{
|
||||
buffer->line[pcjr->displine][(x << 4) + c + 8] = cols[dat >> 15];
|
||||
dat <<= 1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (pcjr->array[3] & 4)
|
||||
{
|
||||
if (pcjr->array[0] & 1) hline(buffer, 0, pcjr->displine, (pcjr->crtc[1] << 3) + 16, (pcjr->array[2] & 0xf) + 16);
|
||||
else hline(buffer, 0, pcjr->displine, (pcjr->crtc[1] << 4) + 16, (pcjr->array[2] & 0xf) + 16);
|
||||
}
|
||||
else
|
||||
{
|
||||
// cols[0] = ((pcjr->mode & 0x12) == 0x12) ? 0 : (pcjr->col & 0xf) + 16;
|
||||
cols[0] = pcjr->array[0 + 16] + 16;
|
||||
if (pcjr->array[0] & 1) hline(buffer, 0, pcjr->displine, (pcjr->crtc[1] << 3) + 16, cols[0]);
|
||||
else hline(buffer, 0, pcjr->displine, (pcjr->crtc[1] << 4) + 16, cols[0]);
|
||||
}
|
||||
}
|
||||
if (pcjr->array[0] & 1) x = (pcjr->crtc[1] << 3) + 16;
|
||||
else x = (pcjr->crtc[1] << 4) + 16;
|
||||
if (cga_comp)
|
||||
{
|
||||
for (c = 0; c < x; c++)
|
||||
{
|
||||
y_buf[(c << 1) & 6] = ntsc_col[buffer->line[pcjr->displine][c] & 7][(c << 1) & 6] ? 0x6000 : 0;
|
||||
y_buf[(c << 1) & 6] += (buffer->line[pcjr->displine][c] & 8) ? 0x3000 : 0;
|
||||
i_buf[(c << 1) & 6] = y_buf[(c << 1) & 6] * i_filt[(c << 1) & 6];
|
||||
q_buf[(c << 1) & 6] = y_buf[(c << 1) & 6] * q_filt[(c << 1) & 6];
|
||||
y_tot = y_buf[0] + y_buf[1] + y_buf[2] + y_buf[3] + y_buf[4] + y_buf[5] + y_buf[6] + y_buf[7];
|
||||
i_tot = i_buf[0] + i_buf[1] + i_buf[2] + i_buf[3] + i_buf[4] + i_buf[5] + i_buf[6] + i_buf[7];
|
||||
q_tot = q_buf[0] + q_buf[1] + q_buf[2] + q_buf[3] + q_buf[4] + q_buf[5] + q_buf[6] + q_buf[7];
|
||||
|
||||
y_val = y_tot >> 10;
|
||||
if (y_val > 255) y_val = 255;
|
||||
y_val <<= 16;
|
||||
i_val = i_tot >> 12;
|
||||
if (i_val > 39041) i_val = 39041;
|
||||
if (i_val < -39041) i_val = -39041;
|
||||
q_val = q_tot >> 12;
|
||||
if (q_val > 34249) q_val = 34249;
|
||||
if (q_val < -34249) q_val = -34249;
|
||||
|
||||
r = (y_val + 249*i_val + 159*q_val) >> 16;
|
||||
g = (y_val - 70*i_val - 166*q_val) >> 16;
|
||||
b = (y_val - 283*i_val + 436*q_val) >> 16;
|
||||
|
||||
y_buf[((c << 1) & 6) + 1] = ntsc_col[buffer->line[pcjr->displine][c] & 7][((c << 1) & 6) + 1] ? 0x6000 : 0;
|
||||
y_buf[((c << 1) & 6) + 1] += (buffer->line[pcjr->displine][c] & 8) ? 0x3000 : 0;
|
||||
i_buf[((c << 1) & 6) + 1] = y_buf[((c << 1) & 6) + 1] * i_filt[((c << 1) & 6) + 1];
|
||||
q_buf[((c << 1) & 6) + 1] = y_buf[((c << 1) & 6) + 1] * q_filt[((c << 1) & 6) + 1];
|
||||
y_tot = y_buf[0] + y_buf[1] + y_buf[2] + y_buf[3] + y_buf[4] + y_buf[5] + y_buf[6] + y_buf[7];
|
||||
i_tot = i_buf[0] + i_buf[1] + i_buf[2] + i_buf[3] + i_buf[4] + i_buf[5] + i_buf[6] + i_buf[7];
|
||||
q_tot = q_buf[0] + q_buf[1] + q_buf[2] + q_buf[3] + q_buf[4] + q_buf[5] + q_buf[6] + q_buf[7];
|
||||
|
||||
y_val = y_tot >> 10;
|
||||
if (y_val > 255) y_val = 255;
|
||||
y_val <<= 16;
|
||||
i_val = i_tot >> 12;
|
||||
if (i_val > 39041) i_val = 39041;
|
||||
if (i_val < -39041) i_val = -39041;
|
||||
q_val = q_tot >> 12;
|
||||
if (q_val > 34249) q_val = 34249;
|
||||
if (q_val < -34249) q_val = -34249;
|
||||
|
||||
r = (y_val + 249*i_val + 159*q_val) >> 16;
|
||||
g = (y_val - 70*i_val - 166*q_val) >> 16;
|
||||
b = (y_val - 283*i_val + 436*q_val) >> 16;
|
||||
if (r > 511) r = 511;
|
||||
if (g > 511) g = 511;
|
||||
if (b > 511) b = 511;
|
||||
|
||||
((uint32_t *)buffer32->line[pcjr->displine])[c] = makecol32(r / 2, g / 2, b / 2);
|
||||
}
|
||||
}
|
||||
pcjr->sc = oldsc;
|
||||
if (pcjr->vc == pcjr->crtc[7] && !pcjr->sc)
|
||||
{
|
||||
pcjr->stat |= 8;
|
||||
// printf("VSYNC on %i %i\n",vc,sc);
|
||||
}
|
||||
pcjr->displine++;
|
||||
if (pcjr->displine >= 360)
|
||||
pcjr->displine = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
pcjr->vidtime += pcjr->dispontime;
|
||||
if (pcjr->dispon)
|
||||
pcjr->stat |= 1;
|
||||
pcjr->linepos = 0;
|
||||
if (pcjr->vsynctime)
|
||||
{
|
||||
pcjr->vsynctime--;
|
||||
if (!pcjr->vsynctime)
|
||||
{
|
||||
pcjr->stat &= ~8;
|
||||
// printf("VSYNC off %i %i\n",vc,sc);
|
||||
}
|
||||
}
|
||||
if (pcjr->sc == (pcjr->crtc[11] & 31) || ((pcjr->crtc[8] & 3) == 3 && pcjr->sc == ((pcjr->crtc[11] & 31) >> 1)))
|
||||
{
|
||||
pcjr->con = 0;
|
||||
pcjr->coff = 1;
|
||||
}
|
||||
if (pcjr->vadj)
|
||||
{
|
||||
pcjr->sc++;
|
||||
pcjr->sc &= 31;
|
||||
pcjr->ma = pcjr->maback;
|
||||
pcjr->vadj--;
|
||||
if (!pcjr->vadj)
|
||||
{
|
||||
pcjr->dispon = 1;
|
||||
pcjr->ma = pcjr->maback = (pcjr->crtc[13] | (pcjr->crtc[12] << 8)) & 0x3fff;
|
||||
pcjr->sc = 0;
|
||||
// printf("Display on!\n");
|
||||
}
|
||||
}
|
||||
else if (pcjr->sc == pcjr->crtc[9] || ((pcjr->crtc[8] & 3) == 3 && pcjr->sc == (pcjr->crtc[9] >> 1)))
|
||||
{
|
||||
pcjr->maback = pcjr->ma;
|
||||
// con=0;
|
||||
// coff=0;
|
||||
pcjr->sc = 0;
|
||||
oldvc = pcjr->vc;
|
||||
pcjr->vc++;
|
||||
pcjr->vc &= 127;
|
||||
// pclog("VC %i %i\n", pcjr->vc, pcjr->crtc[7]);
|
||||
// printf("VC %i %i %i %i %i\n",vc,crtc[4],crtc[6],crtc[7],pcjr->dispon);
|
||||
if (pcjr->vc == pcjr->crtc[6])
|
||||
pcjr->dispon = 0;
|
||||
if (oldvc == pcjr->crtc[4])
|
||||
{
|
||||
// printf("Display over at %i\n",pcjr->displine);
|
||||
pcjr->vc = 0;
|
||||
pcjr->vadj = pcjr->crtc[5];
|
||||
if (!pcjr->vadj)
|
||||
pcjr->dispon = 1;
|
||||
if (!pcjr->vadj)
|
||||
pcjr->ma = pcjr->maback = (pcjr->crtc[13] | (pcjr->crtc[12] << 8)) & 0x3fff;
|
||||
if ((pcjr->crtc[10] & 0x60) == 0x20) pcjr->cursoron = 0;
|
||||
else pcjr->cursoron = pcjr->blink & 16;
|
||||
// printf("CRTC10 %02X %i\n",crtc[10],cursoron);
|
||||
}
|
||||
if (pcjr->vc == pcjr->crtc[7])
|
||||
{
|
||||
pcjr->dispon = 0;
|
||||
pcjr->displine = 0;
|
||||
pcjr->vsynctime = 16;//(crtc[3]>>4)+1;
|
||||
picint(1 << 5);
|
||||
// printf("pcjr->vsynctime %i %02X\n",pcjr->vsynctime,crtc[3]);
|
||||
// pcjr->stat|=8;
|
||||
if (pcjr->crtc[7])
|
||||
{
|
||||
// printf("Lastline %i Firstline %i %i %i %i\n",lastline,firstline,lastline-firstline,crtc[1],xsize);
|
||||
if (pcjr->array[0] & 1) x = (pcjr->crtc[1] << 3) + 16;
|
||||
else x = (pcjr->crtc[1] << 4) + 16;
|
||||
pcjr->lastline++;
|
||||
if (x != xsize || (pcjr->lastline - pcjr->firstline) != ysize)
|
||||
{
|
||||
xsize = x;
|
||||
ysize = pcjr->lastline - pcjr->firstline;
|
||||
// printf("Resize to %i,%i - R1 %i\n",xsize,ysize,crtc[1]);
|
||||
if (xsize < 64) xsize = 656;
|
||||
if (ysize < 32) ysize = 200;
|
||||
updatewindowsize(xsize, (ysize << 1) + 16);
|
||||
}
|
||||
// printf("Blit %i %i\n",firstline,lastline);
|
||||
//printf("Xsize is %i\n",xsize);
|
||||
startblit();
|
||||
if (cga_comp)
|
||||
video_blit_memtoscreen(0, pcjr->firstline-4, 0, (pcjr->lastline - pcjr->firstline) + 8, xsize, (pcjr->lastline - pcjr->firstline) + 8);
|
||||
else
|
||||
video_blit_memtoscreen_8(0, pcjr->firstline-4, xsize, (pcjr->lastline - pcjr->firstline) + 8);
|
||||
endblit();
|
||||
frames++;
|
||||
video_res_x = xsize - 16;
|
||||
video_res_y = ysize;
|
||||
}
|
||||
pcjr->firstline = 1000;
|
||||
pcjr->lastline = 0;
|
||||
pcjr->blink++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
pcjr->sc++;
|
||||
pcjr->sc &= 31;
|
||||
pcjr->ma = pcjr->maback;
|
||||
}
|
||||
if ((pcjr->sc == (pcjr->crtc[10] & 31) || ((pcjr->crtc[8] & 3) == 3 && pcjr->sc == ((pcjr->crtc[10] & 31) >> 1))))
|
||||
pcjr->con = 1;
|
||||
}
|
||||
}
|
||||
|
||||
static void *pcjr_video_init()
|
||||
{
|
||||
int c;
|
||||
int pcjr_tint = -2;
|
||||
pcjr_t *pcjr = malloc(sizeof(pcjr_t));
|
||||
memset(pcjr, 0, sizeof(pcjr_t));
|
||||
|
||||
pcjr->memctrl = -1;
|
||||
|
||||
for (c = 0; c < 8; c++)
|
||||
{
|
||||
i_filt[c] = 512.0 * cos((3.14 * (pcjr_tint + c * 4) / 16.0) - 33.0 / 180.0);
|
||||
q_filt[c] = 512.0 * sin((3.14 * (pcjr_tint + c * 4) / 16.0) - 33.0 / 180.0);
|
||||
}
|
||||
timer_add(pcjr_poll, &pcjr->vidtime, TIMER_ALWAYS_ENABLED, pcjr);
|
||||
mem_mapping_add(&pcjr->mapping, 0xb8000, 0x08000, pcjr_read, NULL, NULL, pcjr_write, NULL, NULL, pcjr);
|
||||
io_sethandler(0x03d0, 0x0010, pcjr_in, NULL, NULL, pcjr_out, NULL, NULL, pcjr);
|
||||
return pcjr;
|
||||
}
|
||||
|
||||
static void pcjr_video_close(void *p)
|
||||
{
|
||||
pcjr_t *pcjr = (pcjr_t *)p;
|
||||
|
||||
free(pcjr);
|
||||
}
|
||||
|
||||
static void pcjr_speed_changed(void *p)
|
||||
{
|
||||
pcjr_t *pcjr = (pcjr_t *)p;
|
||||
|
||||
pcjr_recalctimings(pcjr);
|
||||
}
|
||||
|
||||
device_t pcjr_video_device =
|
||||
{
|
||||
"IBM PCjr (video)",
|
||||
0,
|
||||
pcjr_video_init,
|
||||
pcjr_video_close,
|
||||
NULL,
|
||||
pcjr_speed_changed,
|
||||
NULL,
|
||||
NULL
|
||||
};
|
||||
1
src/vid_pcjr.h
Normal file
1
src/vid_pcjr.h
Normal file
|
|
@ -0,0 +1 @@
|
|||
extern device_t pcjr_video_device;
|
||||
|
|
@ -26,6 +26,7 @@
|
|||
#include "vid_pc1512.h"
|
||||
#include "vid_pc1640.h"
|
||||
#include "vid_pc200.h"
|
||||
#include "vid_pcjr.h"
|
||||
#include "vid_s3.h"
|
||||
#include "vid_s3_virge.h"
|
||||
#include "vid_tandy.h"
|
||||
|
|
@ -203,6 +204,10 @@ void video_init()
|
|||
|
||||
switch (romset)
|
||||
{
|
||||
case ROM_IBMPCJR:
|
||||
device_add(&pcjr_video_device);
|
||||
return;
|
||||
|
||||
case ROM_TANDY:
|
||||
device_add(&tandy_device);
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -49,17 +49,17 @@ void wd76c10_write(uint16_t port, uint16_t val, void *priv)
|
|||
|
||||
switch ((val >> 5) & 7)
|
||||
{
|
||||
case 1: serial1_init(0x3f8); break;
|
||||
case 2: serial1_init(0x2f8); break;
|
||||
case 3: serial1_init(0x3e8); break;
|
||||
case 4: serial1_init(0x2e8); break;
|
||||
case 1: serial1_init(0x3f8, 4); break;
|
||||
case 2: serial1_init(0x2f8, 4); break;
|
||||
case 3: serial1_init(0x3e8, 4); break;
|
||||
case 4: serial1_init(0x2e8, 4); break;
|
||||
}
|
||||
switch ((val >> 1) & 7)
|
||||
{
|
||||
case 1: serial2_init(0x3f8); break;
|
||||
case 2: serial2_init(0x2f8); break;
|
||||
case 3: serial2_init(0x3e8); break;
|
||||
case 4: serial2_init(0x2e8); break;
|
||||
case 1: serial2_init(0x3f8, 3); break;
|
||||
case 2: serial2_init(0x2f8, 3); break;
|
||||
case 3: serial2_init(0x3e8, 3); break;
|
||||
case 4: serial2_init(0x2e8, 3); break;
|
||||
}
|
||||
break;
|
||||
|
||||
|
|
|
|||
|
|
@ -3,6 +3,8 @@ uint32_t oldpc;
|
|||
extern uint32_t rmdat32;
|
||||
int oldcpl;
|
||||
|
||||
extern int nmi_enable;
|
||||
|
||||
int tempc;
|
||||
int cycles,output;
|
||||
int ssegs;
|
||||
|
|
|
|||
Loading…
Reference in a new issue