PCem

changeset 71:923b243eba54

Preliminary PCjr emulation. Improvements to PIT and serial emulation.
author TomW
date Sun Jan 12 11:37:09 2014 +0000
parents 4b93215137d7
children 9cba7b285132
files src/808x.c src/Makefile.mingw src/cpu.c src/cpu.h src/fdc.c src/fdc.h src/ibm.h src/keyboard_pcjr.c src/keyboard_pcjr.h src/mem.c src/model.c src/mouse_serial.c src/pc.c src/pit.c src/pit.h src/serial.c src/serial.h src/sound_sn76489.c src/sound_sn76489.h src/sound_speaker.c src/sound_speaker.h src/um8669f.c src/vid_pcjr.c src/vid_pcjr.h src/video.c src/wd76c10.c src/x86.h
diffstat 27 files changed, 1672 insertions(+), 390 deletions(-) [+]
line diff
     1.1 --- a/src/808x.c	Fri Jan 03 20:48:12 2014 +0000
     1.2 +++ b/src/808x.c	Sun Jan 12 11:37:09 2014 +0000
     1.3 @@ -804,14 +804,16 @@
     1.4          int diff = cycdiff - cycles - current_diff;
     1.5          
     1.6          current_diff += diff;
     1.7 -        pit.c[0] -= diff;
     1.8 -        pit.c[1] -= diff;
     1.9 -        if (pit.gate[2]) pit.c[2] -= diff;
    1.10 +        if (pit.running[0]) pit.c[0] -= diff;
    1.11 +        if (pit.running[1]) pit.c[1] -= diff;
    1.12 +        if (pit.running[2]) pit.c[2] -= diff;
    1.13          if ((pit.c[0] < 1) || (pit.c[1] < 1) || (pit.c[2] < 1)) pit_poll();
    1.14          
    1.15          timer_clock(diff);
    1.16  }
    1.17  
    1.18 +static int takeint = 0;
    1.19 +
    1.20  
    1.21  int firstrepcycle=1;
    1.22  
    1.23 @@ -826,6 +828,7 @@
    1.24          uint32_t oldds;
    1.25          startrep:
    1.26          temp=FETCH();
    1.27 +
    1.28  //        if (firstrepcycle && temp==0xA5) printf("REP MOVSW %06X:%04X %06X:%04X\n",ds,SI,es,DI);
    1.29  //        if (output) printf("REP %02X %04X\n",temp,ipc);
    1.30          switch (temp)
    1.31 @@ -1047,6 +1050,8 @@
    1.32          }
    1.33          CX=c;
    1.34          if (changeds) ds=oldds;
    1.35 +        if (IRQTEST)
    1.36 +                takeint = 1;
    1.37  //        if (pc==ipc) FETCHCLEAR();
    1.38  }
    1.39  
    1.40 @@ -1056,7 +1061,6 @@
    1.41  int firstrepcycle;
    1.42  int skipnextprint=0;
    1.43  
    1.44 -
    1.45  int instime=0;
    1.46  //#if 0
    1.47  void execx86(int cycs)
    1.48 @@ -1102,7 +1106,7 @@
    1.49                  {
    1.50  //                        if ((opcode!=0xF2 && opcode!=0xF3) || firstrepcycle)
    1.51  //                        {
    1.52 -                                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]);
    1.53 +                                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]);
    1.54                                  skipnextprint=0;
    1.55  //                                ins++;
    1.56  //                        }
    1.57 @@ -2373,7 +2377,7 @@
    1.58                          lastpc=pc;
    1.59                          lastcs=CS;
    1.60                          temp=FETCH();
    1.61 -                        
    1.62 +
    1.63                          if (ssegs) ss=oldss;
    1.64                          writememw(ss,((SP-2)&0xFFFF),flags|0xF000);
    1.65                          writememw(ss,((SP-4)&0xFFFF),CS);
    1.66 @@ -2399,6 +2403,7 @@
    1.67                          SP+=6;
    1.68                          cycles-=44;
    1.69                          FETCHCLEAR();
    1.70 +                        nmi_enable = 1;
    1.71                          break;
    1.72                          case 0xD0:
    1.73                          fetchea();
    1.74 @@ -3427,7 +3432,22 @@
    1.75                          loadcs(readmemw(0,addr+2));
    1.76                          FETCHCLEAR();
    1.77                  }
    1.78 -                else if ((flags&I_FLAG) && (pic.pend&~pic.mask) && !ssegs && !noint)
    1.79 +                else if (nmi && nmi_enable)
    1.80 +                {
    1.81 +//                        output = 3;
    1.82 +                        writememw(ss,(SP-2)&0xFFFF,flags|0xF000);
    1.83 +                        writememw(ss,(SP-4)&0xFFFF,CS);
    1.84 +                        writememw(ss,(SP-6)&0xFFFF,pc);
    1.85 +                        SP-=6;
    1.86 +                        addr=2<<2;
    1.87 +                        flags&=~I_FLAG;
    1.88 +                        flags&=~T_FLAG;
    1.89 +                        pc=readmemw(0,addr);
    1.90 +                        loadcs(readmemw(0,addr+2));
    1.91 +                        FETCHCLEAR();
    1.92 +                        nmi_enable = 0;
    1.93 +                }
    1.94 +                else if (takeint && !ssegs && !noint)
    1.95                  {
    1.96                          temp=picinterrupt();
    1.97                          if (temp!=0xFF)
    1.98 @@ -3447,6 +3467,7 @@
    1.99  //                                printf("INTERRUPT\n");
   1.100                          }
   1.101                  }
   1.102 +                takeint = (flags&I_FLAG) && (pic.pend&~pic.mask);
   1.103  
   1.104                  if (noint) noint=0;
   1.105                  ins++;
     2.1 --- a/src/Makefile.mingw	Fri Jan 03 20:48:12 2014 +0000
     2.2 +++ b/src/Makefile.mingw	Sun Jan 12 11:37:09 2014 +0000
     2.3 @@ -6,7 +6,7 @@
     2.4  OBJ = 386.o 808x.o acer386sx.o ali1429.o amstrad.o cdrom-ioctl.o \
     2.5  	config.o cpu.o dac.o device.o dma.o ega.o fdc.o \
     2.6  	headland.o i430vx.o ide.o io.o jim.o keyboard.o keyboard_amstrad.o keyboard_at.o \
     2.7 -	keyboard_olim24.o keyboard_xt.o lpt.o mcr.o mem.o model.o \
     2.8 +	keyboard_olim24.o keyboard_pcjr.o keyboard_xt.o lpt.o mcr.o mem.o model.o \
     2.9  	mouse.o mouse_ps2.o mouse_serial.o neat.o nvr.o olivetti_m24.o \
    2.10       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 \
    2.11  	sound_adlibgold.o sound_cms.o sound_emu8k.o sound_gus.o sound_mpu401_uart.o sound_opl.o \
    2.12 @@ -15,7 +15,7 @@
    2.13  	vid_ati_mach64.o vid_ati18800.o vid_ati28800.o vid_ati68860_ramdac.o vid_cga.o \
    2.14  	vid_cl5429.o vid_ega.o vid_et4000.o vid_et4000w32.o vid_et4000w32i.o \
    2.15  	vid_hercules.o vid_icd2061.o vid_ics2595.o vid_mda.o vid_olivetti_m24.o \
    2.16 -	vid_oti067.o vid_paradise.o vid_pc1512.o vid_pc1640.o vid_pc200.o vid_s3.o \
    2.17 +	vid_oti067.o vid_paradise.o vid_pc1512.o vid_pc1640.o vid_pc200.o vid_pcjr.o vid_s3.o \
    2.18  	vid_s3_virge.o vid_sdac_ramdac.o vid_stg_ramdac.o vid_svga.o vid_svga_render.o \
    2.19  	vid_tandy.o vid_tgui9440.o vid_tkd8001_ramdac.o vid_tvga.o vid_unk_ramdac.o vid_vga.o \
    2.20  	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 \
     3.1 --- a/src/cpu.c	Fri Jan 03 20:48:12 2014 +0000
     3.2 +++ b/src/cpu.c	Sun Jan 12 11:37:09 2014 +0000
     3.3 @@ -68,6 +68,13 @@
     3.4          {"",             -1,        0, 0, 0, 0}
     3.5  };
     3.6  
     3.7 +CPU cpus_pcjr[] =
     3.8 +{
     3.9 +        /*8088 PCjr*/
    3.10 +        {"8088/4.77",    CPU_8088,  0,  4772727, 1, 0, 0, 0},
    3.11 +        {"",             -1,        0, 0, 0, 0}
    3.12 +};
    3.13 +
    3.14  CPU cpus_8086[] =
    3.15  {
    3.16          /*8086 standard*/
    3.17 @@ -259,7 +266,7 @@
    3.18          cpu_hasrdtsc = 0;
    3.19          cpu_hasMMX = 0;
    3.20          cpu_hasMSR = 0;
    3.21 -        
    3.22 +
    3.23          if (cpu_iscyrix)
    3.24             io_sethandler(0x0022, 0x0002, cyrix_read, NULL, NULL, cyrix_write, NULL, NULL, NULL);
    3.25          else
     4.1 --- a/src/cpu.h	Fri Jan 03 20:48:12 2014 +0000
     4.2 +++ b/src/cpu.h	Sun Jan 12 11:37:09 2014 +0000
     4.3 @@ -61,6 +61,7 @@
     4.4  extern CPU cpus_Cx486[];
     4.5  extern CPU cpus_WinChip[];
     4.6  
     4.7 +extern CPU cpus_pcjr[];
     4.8  extern CPU cpus_pc1512[];
     4.9  extern CPU cpus_ibmat[];
    4.10  extern CPU cpus_acer[];
     5.1 --- a/src/fdc.c	Fri Jan 03 20:48:12 2014 +0000
     5.2 +++ b/src/fdc.c	Sun Jan 12 11:37:09 2014 +0000
     5.3 @@ -7,6 +7,31 @@
     5.4  #include "pic.h"
     5.5  #include "timer.h"
     5.6  
     5.7 +/*FDC*/
     5.8 +typedef struct FDC
     5.9 +{
    5.10 +        uint8_t dor,stat,command,dat,st0;
    5.11 +        int head,track[256],sector,drive,lastdrive;
    5.12 +        int pos;
    5.13 +        uint8_t params[256];
    5.14 +        uint8_t res[256];
    5.15 +        int pnum,ptot;
    5.16 +        int rate;
    5.17 +        uint8_t specify[256];
    5.18 +        int eot[256];
    5.19 +        int lock;
    5.20 +        int perp;
    5.21 +        uint8_t config, pretrk;
    5.22 +        int abort;
    5.23 +        
    5.24 +        int pcjr;
    5.25 +        
    5.26 +        int watchdog_timer;
    5.27 +        int watchdog_count;
    5.28 +} FDC;
    5.29 +
    5.30 +static FDC fdc;
    5.31 +
    5.32  void fdc_poll();
    5.33  int timetolive;
    5.34  int TRACKS[2] = {80, 80};
    5.35 @@ -38,6 +63,7 @@
    5.36          if (ftell(f)<=(160*1024))       { SECTORS[d]=8;  TRACKS[d] = 40; SIDES[d]=1; discrate[d]=2; }
    5.37          else if (ftell(f)<=(180*1024))  { SECTORS[d]=9;  TRACKS[d] = 40; SIDES[d]=1; discrate[d]=2; }
    5.38          else if (ftell(f)<=(320*1024))  { SECTORS[d]=8;  TRACKS[d] = 40; discrate[d]=2; }
    5.39 +        else if (ftell(f)<=(360*1024))  { SECTORS[d]=9;  TRACKS[d] = 40; discrate[d]=2; } /*Double density*/
    5.40          else if (ftell(f)<(1024*1024))  { SECTORS[d]=9;  TRACKS[d] = 80; discrate[d]=2; } /*Double density*/
    5.41          else if (ftell(f)<(0x1A4000-1)) { SECTORS[d]=18; TRACKS[d] = 80; discrate[d]=0; } /*High density (not supported by Tandy 1000)*/
    5.42          else if (ftell(f) == 1884159)   { SECTORS[d]=23; TRACKS[d] = 80; discrate[d]=0; } /*XDF format - used by OS/2 Warp*/
    5.43 @@ -111,6 +137,29 @@
    5.44  }
    5.45  int ins;
    5.46  
    5.47 +static void fdc_int()
    5.48 +{
    5.49 +        if (!fdc.pcjr)
    5.50 +                picint(1 << 6);
    5.51 +}
    5.52 +
    5.53 +static void fdc_watchdog_poll(void *p)
    5.54 +{
    5.55 +        FDC *fdc = (FDC *)p;
    5.56 +        
    5.57 +        fdc->watchdog_count--;
    5.58 +        if (fdc->watchdog_count)
    5.59 +                fdc->watchdog_timer += 1000 * TIMER_USEC;
    5.60 +        else
    5.61 +        {
    5.62 +//                pclog("Watchdog timed out\n");
    5.63 +        
    5.64 +                fdc->watchdog_timer = 0;
    5.65 +                if (fdc->dor & 0x20)
    5.66 +                        picint(1 << 6);
    5.67 +        }
    5.68 +}
    5.69 +
    5.70  void fdc_write(uint16_t addr, uint8_t val, void *priv)
    5.71  {
    5.72  //        printf("Write FDC %04X %02X %04X:%04X %i %02X %i rate=%i\n",addr,val,cs>>4,pc,ins,fdc.st0,ins,fdc.rate);
    5.73 @@ -120,18 +169,39 @@
    5.74                  case 2: /*DOR*/
    5.75  //                if (val == 0xD && (cs >> 4) == 0xFC81600 && ins > 769619936) output = 3;
    5.76  //                printf("DOR was %02X\n",fdc.dor);
    5.77 -                if (val&4)
    5.78 +                if (fdc.pcjr)
    5.79                  {
    5.80 -                        fdc.stat=0x80;
    5.81 -                        fdc.pnum=fdc.ptot=0;
    5.82 +                        if ((fdc.dor & 0x40) && !(val & 0x40))
    5.83 +                        {
    5.84 +                                fdc.watchdog_timer = 1000 * TIMER_USEC;
    5.85 +                                fdc.watchdog_count = 1000;
    5.86 +                                picintc(1 << 6);
    5.87 +//                                pclog("watchdog set %i %i\n", fdc.watchdog_timer, TIMER_USEC);
    5.88 +                        }
    5.89 +                        if ((val & 0x80) && !(fdc.dor & 0x80))
    5.90 +                        {
    5.91 +        			timer_process();
    5.92 +                                disctime = 128 * (1 << TIMER_SHIFT);
    5.93 +                                timer_update_outstanding();
    5.94 +                                discint=-1;
    5.95 +                                fdc_reset();
    5.96 +                        }
    5.97                  }
    5.98 -                if ((val&4) && !(fdc.dor&4))
    5.99 +                else
   5.100                  {
   5.101 -			timer_process();
   5.102 -                        disctime = 128 * (1 << TIMER_SHIFT);
   5.103 -                        timer_update_outstanding();
   5.104 -                        discint=-1;
   5.105 -                        fdc_reset();
   5.106 +                        if (val&4)
   5.107 +                        {
   5.108 +                                fdc.stat=0x80;
   5.109 +                                fdc.pnum=fdc.ptot=0;
   5.110 +                        }
   5.111 +                        if ((val&4) && !(fdc.dor&4))
   5.112 +                        {
   5.113 +        			timer_process();
   5.114 +                                disctime = 128 * (1 << TIMER_SHIFT);
   5.115 +                                timer_update_outstanding();
   5.116 +                                discint=-1;
   5.117 +                                fdc_reset();
   5.118 +                        }
   5.119                  }
   5.120                  fdc.dor=val;
   5.121  //                printf("DOR now %02X\n",val);
   5.122 @@ -147,6 +217,12 @@
   5.123                  }
   5.124                  return;
   5.125                  case 5: /*Command register*/
   5.126 +                if ((fdc.stat & 0xf0) == 0xb0)
   5.127 +                {
   5.128 +                        fdc.dat = val;
   5.129 +                        fdc.stat &= ~0x80;
   5.130 +                        break;
   5.131 +                }
   5.132  //                pclog("Write command reg %i %i\n",fdc.pnum, fdc.ptot);
   5.133                  if (fdc.pnum==fdc.ptot)
   5.134                  {
   5.135 @@ -315,6 +391,8 @@
   5.136                                  {
   5.137                                          fdc.head = (fdc.params[0] & 4) ? 1 : 0;
   5.138                                  }
   5.139 +                                if (discint == 5 && fdc.pcjr)
   5.140 +                                        fdc.stat = 0xb0;
   5.141                                  timer_update_outstanding();
   5.142  //                                if (discint==5) fdc.pos=512;
   5.143                          }
   5.144 @@ -350,6 +428,11 @@
   5.145                  break;
   5.146                  case 5: /*Data*/
   5.147                  fdc.stat&=~0x80;
   5.148 +                if ((fdc.stat & 0xf0) == 0xf0)
   5.149 +                {
   5.150 +                        temp = fdc.dat;
   5.151 +                        break;
   5.152 +                }
   5.153                  if (paramstogo)
   5.154                  {
   5.155                          paramstogo--;
   5.156 @@ -412,13 +495,13 @@
   5.157                  case -3: /*End of command with interrupt*/
   5.158  //                if (output) printf("EOC - interrupt!\n");
   5.159  //pclog("EOC\n");
   5.160 -                picint(0x40);
   5.161 +                fdc_int();
   5.162                  case -2: /*End of command*/
   5.163                  fdc.stat = (fdc.stat & 0xf) | 0x80;
   5.164                  return;
   5.165                  case -1: /*Reset*/
   5.166  //pclog("Reset\n");
   5.167 -                picint(0x40);
   5.168 +                fdc_int();
   5.169                  fdc_reset_stat = 4;
   5.170                  return;
   5.171                  case 2: /*Read track*/
   5.172 @@ -430,7 +513,10 @@
   5.173                  {
   5.174                          fdc.dat=disc[fdc.drive][fdc.head][fdc.track[fdc.drive]][fdc.sector-1][fdc.pos];
   5.175  //                        pclog("Read %i %i %i %i %02X\n",fdc.head,fdc.track,fdc.sector,fdc.pos,fdc.dat);
   5.176 -                        dma_channel_write(2, fdc.dat);
   5.177 +                        if (fdc.pcjr)
   5.178 +                                fdc.stat = 0xf0;
   5.179 +                        else
   5.180 +                                dma_channel_write(2, fdc.dat);
   5.181                          timer_process();
   5.182                          disctime = 60 * (1 << TIMER_SHIFT);
   5.183                          timer_update_outstanding();
   5.184 @@ -440,7 +526,7 @@
   5.185                          disctime=0;
   5.186                          discint=-2;
   5.187  //                        pclog("RT\n");
   5.188 -                        picint(0x40);
   5.189 +                        fdc_int();
   5.190                          fdc.stat=0xD0;
   5.191                          fdc.res[4]=(fdc.head?4:0)|fdc.drive;
   5.192                          fdc.res[5]=fdc.res[2]=0;
   5.193 @@ -488,7 +574,10 @@
   5.194                  }
   5.195                  if (fdc.pos<512)
   5.196                  {
   5.197 -                        temp = dma_channel_read(2);
   5.198 +                        if (fdc.pcjr)
   5.199 +                                temp = fdc.dat;
   5.200 +                        else
   5.201 +                                temp = dma_channel_read(2);
   5.202                          if (temp == DMA_NODATA)
   5.203                          {
   5.204                                  discint=0xFD;
   5.205 @@ -502,8 +591,10 @@
   5.206                                  fdc.dat=disc[fdc.drive][fdc.head][fdc.track[fdc.drive]][fdc.sector-1][fdc.pos]=temp;
   5.207  //                                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);
   5.208  				timer_process();
   5.209 -                                disctime = 60 * (1 << TIMER_SHIFT);
   5.210 +                                disctime = 600 * (1 << TIMER_SHIFT);
   5.211                                  timer_update_outstanding();
   5.212 +                                if (fdc.pcjr && fdc.pos != 512)
   5.213 +                                        fdc.stat = 0xb0;
   5.214                          }
   5.215                  }
   5.216                  else
   5.217 @@ -511,7 +602,7 @@
   5.218                          disctime=0;
   5.219                          discint=-2;
   5.220  //                        pclog("WD\n");
   5.221 -                        picint(0x40);
   5.222 +                        fdc_int();
   5.223                          fdc.stat=0xD0;
   5.224                          fdc.res[4]=(fdc.head?4:0)|fdc.drive;
   5.225                          fdc.res[5]=0;
   5.226 @@ -528,6 +619,8 @@
   5.227                  {
   5.228                          fdc.pos=0;
   5.229                          fdc.sector++;
   5.230 +                        if (fdc.pcjr)
   5.231 +                                fdc.stat = 0xb0;
   5.232                  }
   5.233                  return;
   5.234                  case 6: /*Read data*/
   5.235 @@ -537,12 +630,19 @@
   5.236                  }
   5.237                  if (fdc.pos<512)
   5.238                  {
   5.239 -                        fdc.dat=disc[fdc.drive][fdc.head][fdc.track[fdc.drive]][fdc.sector-1][fdc.pos];
   5.240 +                        fdc.dat = disc[fdc.drive][fdc.head][fdc.track[fdc.drive]][fdc.sector - 1][fdc.pos];
   5.241  //                        printf("Read disc %i %i %i %i %02X\n",fdc.head,fdc.track,fdc.sector,fdc.pos,fdc.dat);
   5.242 -                        if (dma_channel_write(2, fdc.dat) & DMA_OVER)
   5.243 -                                fdc.abort = 1;
   5.244 +                        if (fdc.pcjr)
   5.245 +                        {
   5.246 +                                fdc.stat = 0xf0;
   5.247 +                        }
   5.248 +                        else
   5.249 +                        {
   5.250 +                                if (dma_channel_write(2, fdc.dat) & DMA_OVER)
   5.251 +                                        fdc.abort = 1;
   5.252 +                        }
   5.253                          timer_process();
   5.254 -                        disctime = 60 * (1 << TIMER_SHIFT);
   5.255 +                        disctime = 256 * (1 << TIMER_SHIFT);
   5.256                          timer_update_outstanding();
   5.257                  }
   5.258                  else
   5.259 @@ -551,7 +651,7 @@
   5.260                          fdc.abort = 0;
   5.261                          disctime=0;
   5.262                          discint=-2;
   5.263 -                        picint(0x40);
   5.264 +                        fdc_int();
   5.265  //                        pclog("RD\n");
   5.266                          fdc.stat=0xD0;
   5.267                          fdc.res[4]=(fdc.head?4:0)|fdc.drive;
   5.268 @@ -640,7 +740,7 @@
   5.269                  case 10: /*Read sector ID*/
   5.270                  disctime=0;
   5.271                  discint=-2;
   5.272 -                picint(0x40);
   5.273 +                fdc_int();
   5.274                  fdc.stat=0xD0;
   5.275                  fdc.res[4]=(fdc.head?4:0)|fdc.drive;
   5.276                  fdc.res[5]=0;
   5.277 @@ -693,14 +793,14 @@
   5.278                  fdc.perp = fdc.params[0];
   5.279                  fdc.stat = 0x80;
   5.280                  disctime = 0;
   5.281 -//                picint(0x40);
   5.282 +//                fdc_int();
   5.283                  return;
   5.284                  case 0x13: /*Configure*/
   5.285                  fdc.config = fdc.params[1];
   5.286                  fdc.pretrk = fdc.params[2];
   5.287                  fdc.stat = 0x80;
   5.288                  disctime = 0;
   5.289 -//                picint(0x40);
   5.290 +//                fdc_int();
   5.291                  return;
   5.292                  case 0x14: /*Unlock*/
   5.293                  fdc.lock = 0;
   5.294 @@ -723,7 +823,7 @@
   5.295                  case 0xfc: /*Invalid*/
   5.296                  fdc.dat = fdc.st0 = 0x80;
   5.297  //                pclog("Inv!\n");
   5.298 -                //picint(0x40);
   5.299 +                //fdc_int();
   5.300                  fdc.stat = (fdc.stat & 0xf) | 0xd0;
   5.301  //                fdc.stat|=0xC0;
   5.302                  fdc.res[10] = fdc.st0;
   5.303 @@ -742,7 +842,7 @@
   5.304                  pclog("DMA Aborted\n");
   5.305                  disctime=0;
   5.306                  discint=-2;
   5.307 -                picint(0x40);
   5.308 +                fdc_int();
   5.309                  fdc.stat=0xD0;
   5.310                  fdc.res[4]=(fdc.head?4:0)|fdc.drive;
   5.311                  fdc.res[5]=0;
   5.312 @@ -759,7 +859,7 @@
   5.313                  disctime = 0;
   5.314  /*                disctime=0;
   5.315                  discint=-2;
   5.316 -                picint(0x40);
   5.317 +                fdc_int();
   5.318                  fdc.stat=0xD0;
   5.319                  fdc.res[4]=0xC8|(fdc.head?4:0)|fdc.drive;
   5.320                  fdc.res[5]=0;
   5.321 @@ -774,7 +874,7 @@
   5.322                  pclog("Wrong rate\n");
   5.323                  disctime=0;
   5.324                  discint=-2;
   5.325 -                picint(0x40);
   5.326 +                fdc_int();
   5.327                  fdc.stat=0xD0;
   5.328                  fdc.res[4]=0x40|(fdc.head?4:0)|fdc.drive;
   5.329                  fdc.res[5]=5;
   5.330 @@ -799,7 +899,15 @@
   5.331  void fdc_add()
   5.332  {
   5.333          io_sethandler(0x03f0, 0x0006, fdc_read, NULL, NULL, fdc_write, NULL, NULL, NULL);
   5.334 -        io_sethandler(0x03f7, 0x0001, fdc_read, NULL, NULL, fdc_write, NULL, NULL, NULL);        
   5.335 +        io_sethandler(0x03f7, 0x0001, fdc_read, NULL, NULL, fdc_write, NULL, NULL, NULL);
   5.336 +        fdc.pcjr = 0;
   5.337 +}
   5.338 +
   5.339 +void fdc_add_pcjr()
   5.340 +{
   5.341 +        io_sethandler(0x00f0, 0x0006, fdc_read, NULL, NULL, fdc_write, NULL, NULL, NULL);
   5.342 +	timer_add(fdc_watchdog_poll, &fdc.watchdog_timer, &fdc.watchdog_timer, &fdc);
   5.343 +        fdc.pcjr = 1;
   5.344  }
   5.345  
   5.346  void fdc_remove()
     6.1 --- a/src/fdc.h	Fri Jan 03 20:48:12 2014 +0000
     6.2 +++ b/src/fdc.h	Sun Jan 12 11:37:09 2014 +0000
     6.3 @@ -1,5 +1,6 @@
     6.4  void fdc_init();
     6.5  void fdc_add();
     6.6 +void fdc_add_pcjr();
     6.7  void fdc_remove();
     6.8  void fdc_reset();
     6.9  void fdc_poll();
     7.1 --- a/src/ibm.h	Fri Jan 03 20:48:12 2014 +0000
     7.2 +++ b/src/ibm.h	Sun Jan 12 11:37:09 2014 +0000
     7.3 @@ -199,6 +199,13 @@
     7.4          int delay[3];
     7.5          int rereadlatch[3];
     7.6          int gate[3];
     7.7 +        int out[3];
     7.8 +        int running[3];
     7.9 +        int enabled[3];
    7.10 +        int newcount[3];
    7.11 +        int count[3];
    7.12 +        int using_timer[3];
    7.13 +        int initial[3];
    7.14  } PIT;
    7.15  
    7.16  PIT pit;
    7.17 @@ -250,25 +257,6 @@
    7.18  int intcount;
    7.19  
    7.20  
    7.21 -/*FDC*/
    7.22 -typedef struct FDC
    7.23 -{
    7.24 -        uint8_t dor,stat,command,dat,st0;
    7.25 -        int head,track[256],sector,drive,lastdrive;
    7.26 -        int pos;
    7.27 -        uint8_t params[256];
    7.28 -        uint8_t res[256];
    7.29 -        int pnum,ptot;
    7.30 -        int rate;
    7.31 -        uint8_t specify[256];
    7.32 -        int eot[256];
    7.33 -        int lock;
    7.34 -        int perp;
    7.35 -        uint8_t config, pretrk;
    7.36 -        int abort;
    7.37 -} FDC;
    7.38 -
    7.39 -FDC fdc;
    7.40  int disctime;
    7.41  char discfns[2][256];
    7.42  int driveempty[2];
    7.43 @@ -290,6 +278,7 @@
    7.44  #define ET4000W32 (gfxcard==GFX_ET4000W32 && VGA)
    7.45  #define AT (romset>=ROM_IBMAT)
    7.46  #define PCI (romset >= ROM_PCI486)
    7.47 +#define PCJR (romset == ROM_IBMPCJR)
    7.48  
    7.49  #define AMIBIOS (romset==ROM_AMI386 || romset==ROM_AMI486 || romset == ROM_WIN486)
    7.50  
    7.51 @@ -299,6 +288,7 @@
    7.52  {
    7.53          ROM_IBMPC = 0,  /*301 keyboard error, 131 cassette (!!!) error*/
    7.54          ROM_IBMXT,      /*301 keyboard error*/
    7.55 +        ROM_IBMPCJR,
    7.56          ROM_GENXT,      /*'Generic XT BIOS'*/
    7.57          ROM_DTKXT,
    7.58          ROM_EUROPC,
     8.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     8.2 +++ b/src/keyboard_pcjr.c	Sun Jan 12 11:37:09 2014 +0000
     8.3 @@ -0,0 +1,202 @@
     8.4 +#include "ibm.h"
     8.5 +#include "device.h"
     8.6 +#include "io.h"
     8.7 +#include "mem.h"
     8.8 +#include "pic.h"
     8.9 +#include "sound.h"
    8.10 +#include "sound_sn76489.h"
    8.11 +#include "sound_speaker.h"
    8.12 +#include "timer.h"
    8.13 +
    8.14 +#include "keyboard.h"
    8.15 +#include "keyboard_pcjr.h"
    8.16 +
    8.17 +#define STAT_PARITY     0x80
    8.18 +#define STAT_RTIMEOUT   0x40
    8.19 +#define STAT_TTIMEOUT   0x20
    8.20 +#define STAT_LOCK       0x10
    8.21 +#define STAT_CD         0x08
    8.22 +#define STAT_SYSFLAG    0x04
    8.23 +#define STAT_IFULL      0x02
    8.24 +#define STAT_OFULL      0x01
    8.25 +
    8.26 +struct
    8.27 +{
    8.28 +        int latched;
    8.29 +        int data;
    8.30 +        int nmi_enabled;
    8.31 +        
    8.32 +        int serial_data[44];
    8.33 +        int serial_pos;
    8.34 +
    8.35 +        uint8_t pa;
    8.36 +        uint8_t pb;
    8.37 +} keyboard_pcjr;
    8.38 +
    8.39 +static uint8_t key_queue[16];
    8.40 +static int key_queue_start = 0, key_queue_end = 0;
    8.41 +
    8.42 +void keyboard_pcjr_poll()
    8.43 +{
    8.44 +        keybsenddelay += (220 * TIMER_USEC);
    8.45 +
    8.46 +
    8.47 +        if (key_queue_start != key_queue_end && !keyboard_pcjr.serial_pos && !keyboard_pcjr.latched)
    8.48 +        {
    8.49 +                int c;
    8.50 +                int p = 0;
    8.51 +                uint8_t key = key_queue[key_queue_start];
    8.52 +                
    8.53 +//                pclog("Reading %02X from the key queue at %i\n", key, key_queue_start);
    8.54 +                key_queue_start = (key_queue_start + 1) & 0xf;
    8.55 +
    8.56 +                keyboard_pcjr.latched = 1;
    8.57 +
    8.58 +                keyboard_pcjr.serial_data[0] = 1; /*Start bit*/
    8.59 +                keyboard_pcjr.serial_data[1] = 0;
    8.60 +                
    8.61 +                for (c = 0; c < 8; c++)
    8.62 +                {
    8.63 +                        if (key & (1 << c))
    8.64 +                        {
    8.65 +                                keyboard_pcjr.serial_data[(c + 1) * 2]     = 1;
    8.66 +                                keyboard_pcjr.serial_data[(c + 1) * 2 + 1] = 0;
    8.67 +                                p++;
    8.68 +                        }
    8.69 +                        else
    8.70 +                        {
    8.71 +                                keyboard_pcjr.serial_data[(c + 1) * 2]     = 0;
    8.72 +                                keyboard_pcjr.serial_data[(c + 1) * 2 + 1] = 1;
    8.73 +                        }
    8.74 +                }
    8.75 +                
    8.76 +                if (p & 1) /*Parity*/
    8.77 +                {
    8.78 +                        keyboard_pcjr.serial_data[9 * 2]     = 1;
    8.79 +                        keyboard_pcjr.serial_data[9 * 2 + 1] = 0;
    8.80 +                }
    8.81 +                else
    8.82 +                {
    8.83 +                        keyboard_pcjr.serial_data[9 * 2]     = 0;
    8.84 +                        keyboard_pcjr.serial_data[9 * 2 + 1] = 1;
    8.85 +                }
    8.86 +                
    8.87 +                for (c = 0; c < 11; c++) /*11 stop bits*/
    8.88 +                {                       
    8.89 +                        keyboard_pcjr.serial_data[(c + 10) * 2]     = 0;
    8.90 +                        keyboard_pcjr.serial_data[(c + 10) * 2 + 1] = 0;
    8.91 +                }
    8.92 +                
    8.93 +                keyboard_pcjr.serial_pos++;
    8.94 +        }
    8.95 +
    8.96 +        if (keyboard_pcjr.serial_pos)
    8.97 +        {
    8.98 +                keyboard_pcjr.data = keyboard_pcjr.serial_data[keyboard_pcjr.serial_pos - 1];       
    8.99 +                nmi = keyboard_pcjr.data;
   8.100 +                keyboard_pcjr.serial_pos++;
   8.101 +                if (keyboard_pcjr.serial_pos == 42+1)
   8.102 +                        keyboard_pcjr.serial_pos = 0;
   8.103 +//                pclog("Keyboard poll %i %i\n", keyboard_pcjr.data, keyboard_pcjr.serial_pos);
   8.104 +        }
   8.105 +}
   8.106 +
   8.107 +void keyboard_pcjr_adddata(uint8_t val)
   8.108 +{
   8.109 +        key_queue[key_queue_end] = val;
   8.110 +//        pclog("keyboard_pcjr : %02X added to key queue at %i\n", val, key_queue_end);
   8.111 +        key_queue_end = (key_queue_end + 1) & 0xf;
   8.112 +        return;
   8.113 +}
   8.114 +
   8.115 +void keyboard_pcjr_write(uint16_t port, uint8_t val, void *priv)
   8.116 +{
   8.117 +//        pclog("keyboard_pcjr : write %04X %02X %02X\n", port, val, keyboard_pcjr.pb);
   8.118 +/*        if (ram[8] == 0xc3) 
   8.119 +        {
   8.120 +                output = 3;
   8.121 +        }*/
   8.122 +        switch (port)
   8.123 +        {
   8.124 +                case 0x60:
   8.125 +                keyboard_pcjr.pa = val;
   8.126 +                break;
   8.127 +                
   8.128 +                case 0x61:
   8.129 +                keyboard_pcjr.pb = val;
   8.130 +                gated = ((val & 3) == 3);
   8.131 +                if (gated) 
   8.132 +                        wasgated = 1;
   8.133 +                pit_set_gate(2, val & 1);
   8.134 +                sn76489_mute = speaker_mute = 1;
   8.135 +                switch (val & 0x60)
   8.136 +                {
   8.137 +                        case 0x00:
   8.138 +                        speaker_mute = 0;
   8.139 +                        break;
   8.140 +                        case 0x60:
   8.141 +                        sn76489_mute = 0;
   8.142 +                        break;
   8.143 +                }
   8.144 +                break;
   8.145 +                
   8.146 +                case 0xa0:
   8.147 +                keyboard_pcjr.nmi_enabled = val & 0x80;
   8.148 +                pit_set_using_timer(1, !(val & 0x20));
   8.149 +                break;
   8.150 +        }
   8.151 +}
   8.152 +
   8.153 +uint8_t keyboard_pcjr_read(uint16_t port, void *priv)
   8.154 +{
   8.155 +        uint8_t temp;
   8.156 +//        pclog("keyboard_pcjr : read %04X ", port);
   8.157 +        switch (port)
   8.158 +        {
   8.159 +                case 0x60:
   8.160 +                temp = keyboard_pcjr.pa;
   8.161 +                break;
   8.162 +                
   8.163 +                case 0x61:
   8.164 +                temp = keyboard_pcjr.pb;
   8.165 +                break;
   8.166 +                
   8.167 +                case 0x62:
   8.168 +                temp = (keyboard_pcjr.latched ? 1 : 0);
   8.169 +                temp |= 0x02; /*Modem card not installed*/
   8.170 +                temp |= (ppispeakon ? 0x10 : 0);
   8.171 +                temp |= (ppispeakon ? 0x20 : 0);
   8.172 +                temp |= (keyboard_pcjr.data ? 0x40: 0);
   8.173 +//                temp |= 0x04;
   8.174 +                if (keyboard_pcjr.data)
   8.175 +                        temp |= 0x40;
   8.176 +                break;
   8.177 +                
   8.178 +                case 0xa0:
   8.179 +                keyboard_pcjr.latched = 0;
   8.180 +                break;
   8.181 +                
   8.182 +                default:
   8.183 +                pclog("\nBad XT keyboard read %04X\n", port);
   8.184 +                //dumpregs();
   8.185 +                //exit(-1);
   8.186 +        }
   8.187 +//        pclog("%02X\n", temp);
   8.188 +        return temp;
   8.189 +}
   8.190 +
   8.191 +void keyboard_pcjr_reset()
   8.192 +{
   8.193 +}
   8.194 +
   8.195 +void keyboard_pcjr_init()
   8.196 +{
   8.197 +        //return;
   8.198 +        io_sethandler(0x0060, 0x0004, keyboard_pcjr_read, NULL, NULL, keyboard_pcjr_write, NULL, NULL,  NULL);
   8.199 +        io_sethandler(0x00a0, 0x0008, keyboard_pcjr_read, NULL, NULL, keyboard_pcjr_write, NULL, NULL,  NULL);
   8.200 +        keyboard_pcjr_reset();
   8.201 +        keyboard_send = keyboard_pcjr_adddata;
   8.202 +        keyboard_poll = keyboard_pcjr_poll;
   8.203 +
   8.204 +        timer_add(keyboard_pcjr_poll, &keybsenddelay, TIMER_ALWAYS_ENABLED,  NULL);
   8.205 +}
     9.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     9.2 +++ b/src/keyboard_pcjr.h	Sun Jan 12 11:37:09 2014 +0000
     9.3 @@ -0,0 +1,3 @@
     9.4 +void keyboard_pcjr_init();
     9.5 +void keyboard_pcjr_reset();
     9.6 +void keyboard_pcjr_poll();
    10.1 --- a/src/mem.c	Fri Jan 03 20:48:12 2014 +0000
    10.2 +++ b/src/mem.c	Sun Jan 12 11:37:09 2014 +0000
    10.3 @@ -344,6 +344,15 @@
    10.4                          return 1;
    10.5                  }
    10.6                  break;
    10.7 +                
    10.8 +                case ROM_IBMPCJR:
    10.9 +                f = romfopen("roms/ibmpcjr/bios.rom","rb");
   10.10 +                if (!f) break;
   10.11 +                fread(rom, 0x10000, 1, f);
   10.12 +                fclose(f);
   10.13 +                memset(vrom,0x63,0x8000);
   10.14 +                return 1;
   10.15 +                
   10.16                  case ROM_GENXT:
   10.17                  f=romfopen("roms/genxt/pcxt.rom","rb");
   10.18                  if (!f) break;
    11.1 --- a/src/model.c	Fri Jan 03 20:48:12 2014 +0000
    11.2 +++ b/src/model.c	Sun Jan 12 11:37:09 2014 +0000
    11.3 @@ -16,6 +16,7 @@
    11.4  #include "keyboard_amstrad.h"
    11.5  #include "keyboard_at.h"
    11.6  #include "keyboard_olim24.h"
    11.7 +#include "keyboard_pcjr.h"
    11.8  #include "keyboard_xt.h"
    11.9  #include "lpt.h"
   11.10  #include "mouse_ps2.h"
   11.11 @@ -36,6 +37,7 @@
   11.12  #include "xtide.h"
   11.13  
   11.14  void           xt_init();
   11.15 +void         pcjr_init();
   11.16  void      tandy1k_init();
   11.17  void          ams_init();
   11.18  void       europc_init();
   11.19 @@ -56,6 +58,7 @@
   11.20  {
   11.21          {"IBM PC",              ROM_IBMPC,     { "",      cpus_8088,    "",    NULL,       "",      NULL},         0,      xt_init},
   11.22          {"IBM XT",              ROM_IBMXT,     { "",      cpus_8088,    "",    NULL,       "",      NULL},         0,      xt_init},
   11.23 +        {"IBM PCjr",            ROM_IBMPCJR,   { "",      cpus_pcjr,    "",    NULL,       "",      NULL},         1,    pcjr_init},
   11.24          {"Generic XT clone",    ROM_GENXT,     { "",      cpus_8088,    "",    NULL,       "",      NULL},         0,      xt_init},
   11.25          {"DTK XT clone",        ROM_DTKXT,     { "",      cpus_8088,    "",    NULL,       "",      NULL},         0,      xt_init},        
   11.26          {"Tandy 1000",          ROM_TANDY,     { "",      cpus_8088,    "",    NULL,       "",      NULL},         1, tandy1k_init},
   11.27 @@ -112,18 +115,30 @@
   11.28          lpt_init();
   11.29          pic_init();
   11.30          pit_init();
   11.31 -        serial1_init(0x3f8);
   11.32 -        serial2_init(0x2f8);
   11.33 +        serial1_init(0x3f8, 4);
   11.34 +        serial2_init(0x2f8, 3);
   11.35  }
   11.36  
   11.37  void xt_init()
   11.38  {
   11.39          common_init();
   11.40 +        pit_set_out_func(1, pit_refresh_timer_xt);
   11.41          keyboard_xt_init();
   11.42          mouse_serial_init();
   11.43          xtide_init();
   11.44  }
   11.45  
   11.46 +void pcjr_init()
   11.47 +{
   11.48 +        fdc_add_pcjr();
   11.49 +        pic_init();
   11.50 +        pit_init();
   11.51 +        pit_set_out_func(0, pit_irq0_timer_pcjr);
   11.52 +        serial1_init(0x2f8, 3);
   11.53 +        keyboard_pcjr_init();
   11.54 +        device_add(&sn76489_device);
   11.55 +}
   11.56 +
   11.57  void tandy1k_init()
   11.58  {
   11.59          common_init();
   11.60 @@ -163,6 +178,7 @@
   11.61  void at_init()
   11.62  {
   11.63          common_init();
   11.64 +        pit_set_out_func(1, pit_refresh_timer_at);
   11.65          dma16_init();
   11.66          ide_init();
   11.67          keyboard_at_init();
    12.1 --- a/src/mouse_serial.c	Fri Jan 03 20:48:12 2014 +0000
    12.2 +++ b/src/mouse_serial.c	Sun Jan 12 11:37:09 2014 +0000
    12.3 @@ -10,7 +10,8 @@
    12.4  {
    12.5          uint8_t mousedat[3];
    12.6          
    12.7 -        if (!(serial.ier&1)) return;
    12.8 +        if (!(serial1.ier & 1))
    12.9 +                return;
   12.10          if (!x && !y && b==oldb) return;
   12.11  
   12.12          oldb=b;
   12.13 @@ -28,42 +29,44 @@
   12.14          mousedat[1]=x&0x3F;
   12.15          mousedat[2]=y&0x3F;
   12.16          
   12.17 -        if (!(serial.mctrl&0x10))
   12.18 +        if (!(serial1.mctrl&0x10))
   12.19          {
   12.20 -                serial_write_fifo(mousedat[0]);
   12.21 -                serial_write_fifo(mousedat[1]);
   12.22 -                serial_write_fifo(mousedat[2]);
   12.23 +                pclog("Serial data %02X %02X %02X\n", mousedat[0], mousedat[1], mousedat[2]);
   12.24 +                serial_write_fifo(&serial1, mousedat[0]);
   12.25 +                serial_write_fifo(&serial1, mousedat[1]);
   12.26 +                serial_write_fifo(&serial1, mousedat[2]);
   12.27          }
   12.28  }
   12.29  
   12.30 -void mouse_serial_rcr()
   12.31 +void mouse_serial_rcr(void *p)
   12.32  {
   12.33          mousepos=-1;
   12.34          mousedelay=5000 * (1 << TIMER_SHIFT);
   12.35  }
   12.36          
   12.37 -void mousecallback()
   12.38 +void mousecallback(void *p)
   12.39  {
   12.40 +        SERIAL *serial = (SERIAL *)p;
   12.41  	mousedelay = 0;
   12.42          if (mousepos == -1)
   12.43          {
   12.44                  mousepos = 0;
   12.45 -                serial_fifo_read = serial_fifo_write = 0;
   12.46 -                serial.linestat &= ~1;
   12.47 -                serial_write_fifo('M');
   12.48 +/*                serial_fifo_read = serial_fifo_write = 0;
   12.49 +                serial.lsr &= ~1;*/
   12.50 +                serial_write_fifo(serial, 'M');
   12.51          }
   12.52 -        else if (serial_fifo_read != serial_fifo_write)
   12.53 +/*        else if (serial_fifo_read != serial_fifo_write)
   12.54          {
   12.55                  serial.iir=4;
   12.56 -                serial.linestat|=1;
   12.57 +                serial.lsr|=1;
   12.58                  if (serial.mctrl&8) picint(0x10);
   12.59 -        }
   12.60 +        }*/
   12.61  }
   12.62  
   12.63  void mouse_serial_init()
   12.64  {
   12.65          mouse_poll = mouse_serial_poll;
   12.66 -        serial_rcr = mouse_serial_rcr;
   12.67 -        timer_add(mousecallback, &mousedelay, &mousedelay,  NULL);
   12.68 +        serial1.rcr_callback = mouse_serial_rcr;
   12.69 +        timer_add(mousecallback, &mousedelay, &mousedelay, &serial1);
   12.70  }
   12.71  
    13.1 --- a/src/pc.c	Fri Jan 03 20:48:12 2014 +0000
    13.2 +++ b/src/pc.c	Sun Jan 12 11:37:09 2014 +0000
    13.3 @@ -46,7 +46,6 @@
    13.4  void fullspeed();
    13.5  
    13.6  int framecount,fps;
    13.7 -int pitsec;
    13.8  int intcount;
    13.9  int wakeups,wokeups;
   13.10  int output;
   13.11 @@ -343,7 +342,6 @@
   13.12                          egareads=egawrites=0;
   13.13                          cycles_lost = 0;
   13.14                          mmuflush=0;
   13.15 -                        pitsec=0;
   13.16                          intcount=0;
   13.17                          wakeups=wokeups=0;
   13.18                          intcount=pitcount=0;
    14.1 --- a/src/pit.c	Fri Jan 03 20:48:12 2014 +0000
    14.2 +++ b/src/pit.c	Sun Jan 12 11:37:09 2014 +0000
    14.3 @@ -19,7 +19,6 @@
    14.4  //Tyrian writes 4300 or 17512
    14.5  int displine;
    14.6  
    14.7 -int pitsec=0;
    14.8  double PITCONST;
    14.9  float cpuclock;
   14.10  float isa_timing, bus_timing;
   14.11 @@ -30,7 +29,7 @@
   14.12  //        printf("PIT clock %f\n",clock);
   14.13          cpuclock=clock;
   14.14          PITCONST=clock/1193182.0;
   14.15 -        CGACONST=(clock/(19687500.0/11.0));
   14.16 +        CGACONST=(clock/(19687503.0/11.0));
   14.17          MDACONST=(clock/2032125.0);
   14.18          VGACONST1=(clock/25175000.0);
   14.19          VGACONST2=(clock/28322000.0);
   14.20 @@ -57,6 +56,9 @@
   14.21          pit.ctrls[0]=pit.ctrls[1]=pit.ctrls[2]=0;
   14.22          pit.thit[0]=1;
   14.23          spkstat=0;
   14.24 +        pit.gate[0] = pit.gate[1] = 1;
   14.25 +        pit.gate[2] = 0;
   14.26 +        pit.using_timer[0] = pit.using_timer[1] = pit.using_timer[2] = 1;
   14.27  }
   14.28  
   14.29  void clearpit()
   14.30 @@ -69,12 +71,209 @@
   14.31  //        pclog("PIT timer 0 freq %04X %f %f\n",pit.l[0],(float)pit.l[0],1193182.0f/(float)pit.l[0]);
   14.32          return 1193182.0f/(float)pit.l[0];
   14.33  }
   14.34 +
   14.35 +static void (*pit_set_out_funcs[3])(int new_out, int old_out);
   14.36 +
   14.37 +static void pit_set_out(int t, int out)
   14.38 +{
   14.39 +        pit_set_out_funcs[t](out, pit.out[t]);
   14.40 +        pit.out[t] = out;
   14.41 +}
   14.42 +
   14.43 +static void pit_load(int t)
   14.44 +{
   14.45 +        int l = pit.l[t] ? pit.l[t] : 0x10000;
   14.46 +        pit.newcount[t] = 0;
   14.47 +        switch (pit.m[t])
   14.48 +        {
   14.49 +                case 0: /*Interrupt on terminal count*/
   14.50 +                pit.count[t] = l;
   14.51 +                pit.c[t] = l * PITCONST;
   14.52 +                pit_set_out(t, 0);
   14.53 +                pit.thit[t] = 0;
   14.54 +                pit.enabled[t] = pit.gate[t];
   14.55 +                break;
   14.56 +                case 1: /*Hardware retriggerable one-shot*/
   14.57 +                pit.enabled[t] = 1;
   14.58 +                break;
   14.59 +                case 2: /*Rate generator*/
   14.60 +                if (pit.initial[t])
   14.61 +                {
   14.62 +                        pit.count[t] = l - 1;
   14.63 +                        pit.c[t] = (l - 1) * PITCONST;
   14.64 +                        pit_set_out(t, 1);
   14.65 +                        pit.thit[t] = 0;
   14.66 +                }
   14.67 +                pit.enabled[t] = pit.gate[t];
   14.68 +                break;
   14.69 +                case 3: /*Square wave mode*/
   14.70 +                if (pit.initial[t])
   14.71 +                {
   14.72 +                        pit.count[t] = l;
   14.73 +                        pit.c[t] = ((l + 1) >> 1) * PITCONST;
   14.74 +                        pit_set_out(t, 1);
   14.75 +                        pit.thit[t] = 0;
   14.76 +                }
   14.77 +                pit.enabled[t] = pit.gate[t];
   14.78 +                break;
   14.79 +                case 4: /*Software triggered stobe*/
   14.80 +                if (!pit.thit[t] && !pit.initial[t])
   14.81 +                        pit.newcount[t] = 1;
   14.82 +                else
   14.83 +                {
   14.84 +                        pit.count[t] = l;
   14.85 +                        pit.c[t] = l * PITCONST;
   14.86 +                        pit_set_out(t, 0);
   14.87 +                        pit.thit[t] = 0;
   14.88 +                }
   14.89 +                pit.enabled[t] = pit.gate[t];
   14.90 +                break;
   14.91 +                case 5: /*Hardware triggered stobe*/
   14.92 +                pit.enabled[t] = 1;
   14.93 +                break;
   14.94 +        }
   14.95 +        pit.initial[t] = 0;
   14.96 +        pit.running[t] = pit.enabled[t] && pit.using_timer[t];
   14.97 +//        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]);
   14.98 +}
   14.99 +
  14.100 +void pit_set_gate(int t, int gate)
  14.101 +{
  14.102 +        int l = pit.l[t] ? pit.l[t] : 0x10000;
  14.103 +        switch (pit.m[t])
  14.104 +        {
  14.105 +                case 0: /*Interrupt on terminal count*/
  14.106 +                case 4: /*Software triggered stobe*/
  14.107 +                pit.enabled[t] = gate;
  14.108 +                break;
  14.109 +                case 1: /*Hardware retriggerable one-shot*/
  14.110 +                case 5: /*Hardware triggered stobe*/
  14.111 +                if (gate && !pit.gate[t])
  14.112 +                {
  14.113 +                        pit.count[t] = l;
  14.114 +                        pit.c[t] = l * PITCONST;
  14.115 +                        pit_set_out(t, 0);
  14.116 +                        pit.thit[t] = 0;
  14.117 +                        pit.enabled[t] = 1;
  14.118 +                }
  14.119 +                break;
  14.120 +                case 2: /*Rate generator*/
  14.121 +                if (gate && !pit.gate[t])
  14.122 +                {
  14.123 +                        pit.count[t] = l - 1;
  14.124 +                        pit.c[t] = (l - 1) * PITCONST;
  14.125 +                        pit_set_out(t, 1);
  14.126 +                        pit.thit[t] = 0;
  14.127 +                }                
  14.128 +                pit.enabled[t] = gate;
  14.129 +                break;
  14.130 +                case 3: /*Square wave mode*/
  14.131 +                if (gate && !pit.gate[t])
  14.132 +                {
  14.133 +                        pit.count[t] = l;
  14.134 +                        pit.c[t] = ((l + 1) >> 1) * PITCONST;
  14.135 +                        pit_set_out(t, 1);
  14.136 +                        pit.thit[t] = 0;
  14.137 +                }
  14.138 +                pit.enabled[t] = gate;
  14.139 +                break;
  14.140 +        }
  14.141 +        pit.gate[t] = gate;
  14.142 +        pit.running[t] = pit.enabled[t] && pit.using_timer[t];
  14.143 +//        pclog("pit_set_gate: t=%i gate=%i\n", t, gate);
  14.144 +}
  14.145 +
  14.146 +static void pit_over(int t)
  14.147 +{
  14.148 +        int l = pit.l[t] ? pit.l[t] : 0x10000;
  14.149 +        switch (pit.m[t])
  14.150 +        {
  14.151 +                case 0: /*Interrupt on terminal count*/
  14.152 +                case 1: /*Hardware retriggerable one-shot*/
  14.153 +                if (!pit.thit[t])
  14.154 +                        pit_set_out(t, 1);
  14.155 +                pit.thit[t] = 1;
  14.156 +                pit.count[t] += 0xffff;
  14.157 +                pit.c[t] += 0xffff * PITCONST;
  14.158 +                break;
  14.159 +                case 2: /*Rate generator*/
  14.160 +                pit.count[t] += l;
  14.161 +                pit.c[t] += l * PITCONST;
  14.162 +                pit_set_out(t, 0);
  14.163 +                pit_set_out(t, 1);
  14.164 +                break;
  14.165 +                case 3: /*Square wave mode*/
  14.166 +                if (pit.out[t])
  14.167 +                {
  14.168 +                        pit_set_out(t, 0);
  14.169 +                        pit.count[t] += (l >> 1);
  14.170 +                        pit.c[t] += (l >> 1) * PITCONST;
  14.171 +                }
  14.172 +                else
  14.173 +                {
  14.174 +                        pit_set_out(t, 1);
  14.175 +                        pit.count[t] += ((l + 1) >> 1);
  14.176 +                        pit.c[t] = ((l + 1) >> 1) * PITCONST;
  14.177 +                }
  14.178 +                break;
  14.179 +                case 4: /*Software triggered strove*/
  14.180 +                if (!pit.thit[t])
  14.181 +                {
  14.182 +                        pit_set_out(t, 0);
  14.183 +                        pit_set_out(t, 1);
  14.184 +                }
  14.185 +                if (pit.newcount[t])
  14.186 +                {
  14.187 +                        pit.newcount[t] = 0;
  14.188 +                        pit.count[t] += l;
  14.189 +                        pit.c[t] += l * PITCONST;
  14.190 +                }
  14.191 +                else
  14.192 +                {
  14.193 +                        pit.thit[t] = 1;
  14.194 +                        pit.count[t] += 0xffff;
  14.195 +                        pit.c[t] += 0xffff * PITCONST;
  14.196 +                }
  14.197 +                break;
  14.198 +                case 5: /*Hardware triggered strove*/
  14.199 +                if (!pit.thit[t])
  14.200 +                {
  14.201 +                                pit_set_out(t, 0);
  14.202 +                        pit_set_out(t, 1);
  14.203 +                }
  14.204 +                pit.thit[t] = 1;
  14.205 +                break;
  14.206 +        }
  14.207 +        pit.running[t] = pit.enabled[t] && pit.using_timer[t];
  14.208 +}
  14.209 +
  14.210 +static int pit_read_timer(int t)
  14.211 +{
  14.212 +//        pclog("pit_read_timer: t=%i using_timer=%i m=%i\n", t, pit.using_timer[t], pit.m[t]);
  14.213 +        if (pit.using_timer[t])
  14.214 +        {
  14.215 +                int read = pit.c[t] / PITCONST;
  14.216 +                if (pit.m[t] == 2)
  14.217 +                        read++;
  14.218 +                if (read < 0)
  14.219 +                        read = 0;
  14.220 +                if (read > 0x10000)
  14.221 +                        read = 0x10000;
  14.222 +                if (pit.m[t] == 3)
  14.223 +                        read <<= 1;
  14.224 +                return read;
  14.225 +        }
  14.226 +        if (pit.m[t] == 2)
  14.227 +                return pit.count[t] + 1;
  14.228 +        return pit.count[t];
  14.229 +}
  14.230 +        
  14.231  extern int ins;
  14.232  void pit_write(uint16_t addr, uint8_t val, void *priv)
  14.233  {
  14.234          int t;
  14.235          cycles -= (int)PITCONST;
  14.236 -//        printf("Write PIT %04X %02X %04X:%08X %i %i\n",addr,val,CS,pc,ins);
  14.237 +//        if (val != 0x40) pclog("Write PIT %04X %02X %04X:%08X %i %i\n",addr,val,CS,pc,ins, pit.gate[0]);
  14.238          switch (addr&3)
  14.239          {
  14.240                  case 3: /*CTRL*/
  14.241 @@ -82,12 +281,16 @@
  14.242                  {
  14.243                          if (!(val&0x20))
  14.244                          {
  14.245 -                                if (val&2) pit.rl[0]=pit.c[0]/PITCONST;
  14.246 -                                if (val&4) pit.rl[1]=pit.c[1]/PITCONST;
  14.247 -                                if (val&8) pit.rl[2]=pit.c[2]/PITCONST;
  14.248 +                                if (val & 2)
  14.249 +                                        pit.rl[0] = pit.using_timer[0] ? (pit.c[0] / PITCONST) : pit.count[0];
  14.250 +                                if (val & 4)
  14.251 +                                        pit.rl[1] = pit.using_timer[1] ? (pit.c[1] / PITCONST) : pit.count[1];
  14.252 +                                if (val & 8)
  14.253 +                                        pit.rl[2] = pit.using_timer[2] ? (pit.c[2] / PITCONST) : pit.count[2];
  14.254                          }
  14.255                          return;
  14.256                  }
  14.257 +                t = val >> 6;
  14.258                  pit.ctrls[val>>6]=pit.ctrl=val;
  14.259                  if ((val>>7)==3)
  14.260                  {
  14.261 @@ -99,26 +302,26 @@
  14.262  //                printf("CTRL write %02X\n",val);
  14.263                  if (!(pit.ctrl&0x30))
  14.264                  {
  14.265 -                        pit.rl[val>>6]=pit.c[val>>6]/PITCONST;
  14.266 -                        if (pit.c[val>>6]<0) pit.rl[val>>6]=0;
  14.267 +                        pit.rl[t] = pit_read_timer(t);
  14.268  //                        pclog("Timer latch %f %04X %04X\n",pit.c[0],pit.rl[0],pit.l[0]);
  14.269 -                        pit.ctrl|=0x30;
  14.270 -                        pit.rereadlatch[val>>6]=0;
  14.271 -                        pit.rm[val>>6]=3;
  14.272 +                        pit.ctrl |= 0x30;
  14.273 +                        pit.rereadlatch[t] = 0;
  14.274 +                        pit.rm[t] = 3;
  14.275                  }
  14.276                  else
  14.277                  {
  14.278 -                                pit.rm[val>>6]=pit.wm[val>>6]=(pit.ctrl>>4)&3;
  14.279 -                                pit.m[val>>6]=(val>>1)&7;
  14.280 -                                if (pit.m[val>>6]>5)
  14.281 -                                   pit.m[val>>6]&=3;
  14.282 -                                if (!(pit.rm[val>>6]))
  14.283 -                                {
  14.284 -                                        pit.rm[val>>6]=3;
  14.285 -                                        pit.rl[val>>6]=pit.c[val>>6]/PITCONST;
  14.286 -                                }
  14.287 -                                pit.rereadlatch[val>>6]=1;
  14.288 -                                if ((val>>6)==2) ppispeakon=speakon=(pit.m[2]==0)?0:1;
  14.289 +                        pit.rm[val>>6]=pit.wm[val>>6]=(pit.ctrl>>4)&3;
  14.290 +                        pit.m[val>>6]=(val>>1)&7;
  14.291 +                        if (pit.m[val>>6]>5)
  14.292 +                                pit.m[val>>6]&=3;
  14.293 +                        if (!(pit.rm[val>>6]))
  14.294 +                        {
  14.295 +                                pit.rm[val>>6]=3;
  14.296 +                                pit.rl[t] = pit_read_timer(t);
  14.297 +                        }
  14.298 +                        pit.rereadlatch[val>>6]=1;
  14.299 +                        if ((val>>6)==2) ppispeakon=speakon=(pit.m[2]==0)?0:1;
  14.300 +                        pit.initial[t] = 1;
  14.301  //                                pclog("ppispeakon %i\n",ppispeakon);
  14.302                  }
  14.303                  pit.wp=0;
  14.304 @@ -132,196 +335,188 @@
  14.305                  {
  14.306                          case 1:
  14.307                          pit.l[t]=val;
  14.308 -                        pit.thit[t]=0;
  14.309 -                        pit.c[t]=pit.l[t]*PITCONST;
  14.310 -                        if (!t)
  14.311 -                                picintc(1);
  14.312 +//                        pit.thit[t]=0;
  14.313 +                        pit_load(t);
  14.314 +//                        pit.c[t]=pit.l[t]*PITCONST;
  14.315 +//                        if (!t)
  14.316 +//                                picintc(1);
  14.317                          break;
  14.318                          case 2:
  14.319                          pit.l[t]=(val<<8);
  14.320 -                        pit.thit[t]=0;
  14.321 -                        pit.c[t]=pit.l[t]*PITCONST;
  14.322 -                        if (!t)
  14.323 -                                picintc(1);
  14.324 +//                        pit.thit[t]=0;
  14.325 +                        pit_load(t);
  14.326 +//                        pit.c[t]=pit.l[t]*PITCONST;
  14.327 +//                        if (!t)
  14.328 +//                                picintc(1);
  14.329                          break;
  14.330                          case 0:
  14.331                          pit.l[t]&=0xFF;
  14.332                          pit.l[t]|=(val<<8);
  14.333 -                        pit.c[t]=pit.l[t]*PITCONST;
  14.334 +                        pit_load(t);
  14.335 +//                        pit.c[t]=pit.l[t]*PITCONST;
  14.336  //                        pclog("%04X %f\n",pit.l[t],pit.c[t]);                        
  14.337 -                        pit.thit[t]=0;
  14.338 +//                        pit.thit[t]=0;
  14.339                          pit.wm[t]=3;
  14.340 -                        if (!t)
  14.341 -                                picintc(1);
  14.342 +//                        if (!t)
  14.343 +//                                picintc(1);
  14.344                          break;
  14.345                          case 3:
  14.346                          pit.l[t]&=0xFF00;
  14.347                          pit.l[t]|=val;
  14.348                          pit.wm[t]=0;
  14.349                          break;
  14.350 -/*
  14.351 -                        if (pit.wp)
  14.352 -                        {
  14.353 -                                pit.l[t]&=0xFF;
  14.354 -                                pit.l[t]|=(val<<8);
  14.355 -                                pit.c[t]=pit.l[t]*PITCONST;
  14.356 -                                pit.thit[t]=0;
  14.357 -                        }
  14.358 -                        else
  14.359 -                        {
  14.360 -                                pit.l[t]&=0xFF00;
  14.361 -                                pit.l[t]|=val;
  14.362 -                        }
  14.363 -                        pit.rl[t]=pit.l[t];
  14.364 -                        pit.wp^=1;
  14.365 -                        pit.rm[t]=3;
  14.366 -                                pit.rereadlatch[t]=1;
  14.367 -                        break;*/
  14.368                  }
  14.369                  speakval=(((float)pit.l[2]/(float)pit.l[0])*0x4000)-0x2000;
  14.370  //                printf("Speakval now %i\n",speakval);
  14.371  //                if (speakval>0x2000)
  14.372  //                   printf("Speaker overflow - %i %i %04X %04X\n",pit.l[0],pit.l[2],pit.l[0],pit.l[2]);
  14.373                  if (speakval>0x2000) speakval=0x2000;
  14.374 -                if (!pit.l[t])
  14.375 +/*                if (!pit.l[t])
  14.376                  {
  14.377                          pit.l[t]|=0x10000;
  14.378                          pit.c[t]=pit.l[t]*PITCONST;
  14.379 -                }
  14.380 +                }*/
  14.381                  break;
  14.382          }
  14.383  }
  14.384  
  14.385  uint8_t pit_read(uint16_t addr, void *priv)
  14.386  {
  14.387 +        int t;
  14.388          uint8_t temp;
  14.389          cycles -= (int)PITCONST;        
  14.390  //        printf("Read PIT %04X ",addr);
  14.391          switch (addr&3)
  14.392          {
  14.393                  case 0: case 1: case 2: /*Timers*/
  14.394 -                if (pit.rereadlatch[addr&3])// || !(pit.ctrls[addr&3]&0x30))
  14.395 +                t = addr & 3;
  14.396 +                if (pit.rereadlatch[addr & 3])
  14.397                  {
  14.398 -                        pit.rereadlatch[addr&3]=0;
  14.399 -                        pit.rl[addr&3]=pit.c[addr&3]/PITCONST;
  14.400 -                        if ((pit.c[addr&3]/PITCONST)>65536) pit.rl[addr&3]=0xFFFF;
  14.401 +                        pit.rereadlatch[addr & 3] = 0;
  14.402 +                        pit.rl[t] = pit_read_timer(t);
  14.403                  }
  14.404 -                switch (pit.rm[addr&3])
  14.405 +                switch (pit.rm[addr & 3])
  14.406                  {
  14.407                          case 0:
  14.408 -                        temp=pit.rl[addr&3]>>8;
  14.409 -                        pit.rm[addr&3]=3;
  14.410 -                        pit.rereadlatch[addr&3]=1;
  14.411 +                        temp = pit.rl[addr & 3] >> 8;
  14.412 +                        pit.rm[addr & 3] = 3;
  14.413 +                        pit.rereadlatch[addr & 3] = 1;
  14.414                          break;
  14.415                          case 1:
  14.416 -                        temp=(pit.rl[addr&3])&0xFF;
  14.417 -                        pit.rereadlatch[addr&3]=1;
  14.418 +                        temp = (pit.rl[addr & 3]) & 0xFF;
  14.419 +                        pit.rereadlatch[addr & 3] = 1;
  14.420                          break;
  14.421                          case 2:
  14.422 -                        temp=(pit.rl[addr&3])>>8;
  14.423 -                        pit.rereadlatch[addr&3]=1;
  14.424 +                        temp = (pit.rl[addr & 3]) >> 8;
  14.425 +                        pit.rereadlatch[addr & 3] = 1;
  14.426                          break;
  14.427                          case 3:
  14.428 -                        temp=(pit.rl[addr&3])&0xFF;
  14.429 -                        if (pit.m[addr&3]&0x80) pit.m[addr&3]&=7;
  14.430 -                        else pit.rm[addr&3]=0;
  14.431 +                        temp = (pit.rl[addr & 3]) & 0xFF;
  14.432 +                        if (pit.m[addr & 3] & 0x80)
  14.433 +                                pit.m[addr & 3] &= 7;
  14.434 +                        else
  14.435 +                                pit.rm[addr & 3] = 0;
  14.436                          break;
  14.437                  }
  14.438                  break;
  14.439                  case 3: /*Control*/
  14.440 -                temp=pit.ctrl;
  14.441 +                temp = pit.ctrl;
  14.442 +                break;
  14.443          }
  14.444 +//        pclog("%02X\n", temp);
  14.445  //        printf("%02X %i %i %04X:%04X\n",temp,pit.rm[addr&3],pit.wp,cs>>4,pc);
  14.446          return temp;
  14.447  }
  14.448  
  14.449  void pit_poll()
  14.450  {
  14.451 -        pitsec++;
  14.452  //                printf("Poll pit %f %f %f\n",pit.c[0],pit.c[1],pit.c[2]);
  14.453 -        if (pit.c[0]<1)
  14.454 -        {
  14.455 -                if (pit.m[0]==0 || pit.m[0]==4)
  14.456 -                {
  14.457 -//                        pit.c[0]&=0xFFFF;
  14.458 -                        pit.c[0]+=(0x10000*PITCONST);
  14.459 -                }
  14.460 -                else if (pit.m[0]==3 || pit.m[0]==2)
  14.461 -                {
  14.462 -                        if (pit.l[0]) pit.c[0]+=((float)(pit.l[0]*PITCONST));
  14.463 -                        else          pit.c[0]+=((float)(0x10000*PITCONST));
  14.464 -                }
  14.465 -//                pit.c[0]+=(pit.l[0]*PITCONST);
  14.466 -//                if (output) printf("PIT over! %f %i\n",pit.c[0],pit.m[0]);
  14.467 -                if (!pit.thit[0])// && (pit.l[0]>0x14))
  14.468 -                {
  14.469 -//                        printf("PIT int!\n");
  14.470 -///                        printf("%05X %05X %02X\n",pit.c[0],pit.l[0],pit.ctrls[0]);
  14.471 -                        picint(1);
  14.472 -                }
  14.473 -                if (!pit.m[0] || pit.m[0]==4) pit.thit[0]=1;
  14.474 -//                if ((pit.ctrls[0]&0xE)==2) pit.thit[0]=1;
  14.475 -                pitcount++;
  14.476 -        }
  14.477 -        if (pit.c[1]<1)
  14.478 -        {
  14.479 - //               if (output) printf("PIT1 over %02X\n",pit.m[1]);
  14.480 -                if (pit.m[1]==0 || pit.m[1]==4)
  14.481 -                {
  14.482 -                        pit.c[1]=0xFFFFFF*PITCONST;
  14.483 -                }
  14.484 -                else
  14.485 -                {
  14.486 -                        pit.c[1]+=(pit.l[1]*PITCONST);
  14.487 -                }
  14.488 -//                if (output) pclog("%f %04X %02X\n",pit.c[1],pit.l[1],pit.ctrls[1]);
  14.489 -//                printf("DMA0!\n");
  14.490 -                dma_channel_read(0);
  14.491 -                if (AT) 
  14.492 -                        ppi.pb ^= 0x10;
  14.493 -        }
  14.494 -        if (pit.c[2]<1)
  14.495 -        {
  14.496 -//                printf("PIT 2 over %i\n",pit.m[2]);
  14.497 -                if (!pit.m[2] || pit.m[2]==4)
  14.498 -                {
  14.499 -                        pit.c[2]+=(0x10000*PITCONST);
  14.500 -                        speakon^=1;
  14.501 -                        ppispeakon^=1;
  14.502 -                }
  14.503 -                else
  14.504 -                {
  14.505 -                        pit.c[2]+=((pit.l[2]*PITCONST)/2);
  14.506 -                        if (pit.l[2]>0x30) /*Some games use very high frequencies as 'speaker off'. This stops them from generating noise*/
  14.507 -                           speakon^=1;
  14.508 -                        ppispeakon^=1;
  14.509 -//                        printf("Speakon %i %04X %i\n",speakon,pit.l[2],pit.c[2]);
  14.510 -                }
  14.511 -//                if (pit.ctrls[2]&0xE) pit.c[2]+=(pit.l[2]*PITCONST);
  14.512 -//                spkstat^=0x20;
  14.513 -        }
  14.514 +        if (pit.c[0] < 1 && pit.running[0])
  14.515 +                pit_over(0);
  14.516 +        if (pit.c[1] < 1 && pit.running[1])
  14.517 +                pit_over(1);
  14.518 +        if (pit.c[2] < 1 && pit.running[2])
  14.519 +                pit_over(2);
  14.520  }
  14.521  
  14.522 -void pit_set_gate(int channel, int gate)
  14.523 +void pit_clock(int t)
  14.524  {
  14.525 -        if (gate && !pit.gate[channel])
  14.526 +        if (pit.thit[t] || !pit.enabled[t])
  14.527 +                return;
  14.528 +        
  14.529 +        if (pit.using_timer[t])
  14.530 +                return;
  14.531 +                
  14.532 +        pit.count[t] -= (pit.m[t] == 3) ? 2 : 1;
  14.533 +        if (!pit.count[t])
  14.534 +                pit_over(t);
  14.535 +}
  14.536 +
  14.537 +void pit_set_using_timer(int t, int using_timer)
  14.538 +{
  14.539 +//        pclog("pit_set_using_timer: t=%i using_timer=%i\n", t, using_timer);        
  14.540 +        if (pit.using_timer[t] && !using_timer)
  14.541 +                pit.count[t] = pit_read_timer(t);
  14.542 +        if (!pit.using_timer[t] && using_timer)
  14.543 +                pit.c[t] = pit.count[t] * PITCONST;
  14.544 +        pit.using_timer[t] = using_timer;
  14.545 +        pit.running[t] = pit.enabled[t] && pit.using_timer[t];
  14.546 +}
  14.547 +
  14.548 +void pit_set_out_func(int t, void (*func)(int new_out, int old_out))
  14.549 +{
  14.550 +        pit_set_out_funcs[t] = func;
  14.551 +}
  14.552 +
  14.553 +void pit_null_timer(int new_out, int old_out)
  14.554 +{
  14.555 +}
  14.556 +
  14.557 +void pit_irq0_timer(int new_out, int old_out)
  14.558 +{
  14.559 +        if (new_out && !old_out)
  14.560 +                picint(1);
  14.561 +        if (!new_out)
  14.562 +                picintc(1);
  14.563 +}
  14.564 +
  14.565 +void pit_irq0_timer_pcjr(int new_out, int old_out)
  14.566 +{
  14.567 +        if (new_out && !old_out)
  14.568          {
  14.569 -                switch (pit.m[channel])
  14.570 -                {
  14.571 -                        case 1: /*Hardware retriggerable one-shot*/
  14.572 -                        case 2: /*Rate generator*/
  14.573 -                        case 3: /*Square wave mode*/
  14.574 -                        case 5: /*Hardware triggered strobe (retriggerable)*/
  14.575 -                        pit.c[channel] = pit.l[2] * PITCONST;
  14.576 -                        break;
  14.577 -                }
  14.578 +                picint(1);
  14.579 +                pit_clock(1);
  14.580          }
  14.581 -        pit.gate[channel] = gate;
  14.582 +        if (!new_out)
  14.583 +                picintc(1);
  14.584  }
  14.585  
  14.586 +void pit_refresh_timer_xt(int new_out, int old_out)
  14.587 +{
  14.588 +        if (new_out && !old_out)
  14.589 +                dma_channel_read(0);
  14.590 +}
  14.591 +
  14.592 +void pit_refresh_timer_at(int new_out, int old_out)
  14.593 +{
  14.594 +        if (new_out && !old_out)
  14.595 +                ppi.pb ^= 0x10;
  14.596 +}
  14.597 +
  14.598 +void pit_speaker_timer(int new_out, int old_out)
  14.599 +{
  14.600 +        speakon = ppispeakon = new_out;
  14.601 +}
  14.602 +
  14.603 +
  14.604  void pit_init()
  14.605  {
  14.606          io_sethandler(0x0040, 0x0004, pit_read, NULL, NULL, pit_write, NULL, NULL, NULL);
  14.607          pit.gate[0] = pit.gate[1] = 1;
  14.608          pit.gate[2] = 0;
  14.609 +        pit.using_timer[0] = pit.using_timer[1] = pit.using_timer[2] = 1;
  14.610 +        
  14.611 +        pit_set_out_func(0, pit_irq0_timer);
  14.612 +        pit_set_out_func(1, pit_null_timer);
  14.613 +        pit_set_out_func(2, pit_speaker_timer);
  14.614  }
    15.1 --- a/src/pit.h	Fri Jan 03 20:48:12 2014 +0000
    15.2 +++ b/src/pit.h	Sun Jan 12 11:37:09 2014 +0000
    15.3 @@ -2,3 +2,14 @@
    15.4  void pit_init();
    15.5  void pit_reset();
    15.6  void pit_set_gate(int channel, int gate);
    15.7 +void pit_set_using_timer(int t, int using_timer);
    15.8 +void pit_set_out_func(int t, void (*func)(int new_out, int old_out));
    15.9 +void pit_clock(int t);
   15.10 +
   15.11 +
   15.12 +void pit_null_timer(int new_out, int old_out);
   15.13 +void pit_irq0_timer(int new_out, int old_out);
   15.14 +void pit_irq0_timer_pcjr(int new_out, int old_out);
   15.15 +void pit_refresh_timer_xt(int new_out, int old_out);
   15.16 +void pit_refresh_timer_at(int new_out, int old_out);
   15.17 +void pit_speaker_timer(int new_out, int old_out);
    16.1 --- a/src/serial.c	Fri Jan 03 20:48:12 2014 +0000
    16.2 +++ b/src/serial.c	Sun Jan 12 11:37:09 2014 +0000
    16.3 @@ -5,211 +5,251 @@
    16.4  #include "serial.h"
    16.5  #include "timer.h"
    16.6  
    16.7 -SERIAL serial,serial2;
    16.8 +enum
    16.9 +{
   16.10 +        SERIAL_INT_LSR = 1,
   16.11 +        SERIAL_INT_RECEIVE = 2,
   16.12 +        SERIAL_INT_TRANSMIT = 4,
   16.13 +        SERIAL_INT_MSR = 8
   16.14 +};
   16.15 +
   16.16 +SERIAL serial1, serial2;
   16.17  
   16.18  int mousepos=-1;
   16.19  int mousedelay;
   16.20 -uint8_t serial_fifo[256];
   16.21 -int serial_fifo_read, serial_fifo_write;
   16.22 -
   16.23 -void (*serial_rcr)();
   16.24  
   16.25  void serial_reset()
   16.26  {
   16.27 -        serial.iir=serial.ier=serial.lcr=0;
   16.28 -        serial2.iir=serial2.ier=serial2.lcr=0;
   16.29 -        mousedelay=0;
   16.30 -        serial_fifo_read = serial_fifo_write = 0;
   16.31 +        serial1.iir = serial1.ier = serial1.lcr = 0;
   16.32 +        serial2.iir = serial2.ier = serial2.lcr = 0;
   16.33 +        mousedelay = 0;
   16.34 +        serial1.fifo_read = serial1.fifo_write = 0;
   16.35 +        serial2.fifo_read = serial2.fifo_write = 0;
   16.36  }
   16.37  
   16.38 -void serial_write_fifo(uint8_t dat)
   16.39 +void serial_update_ints(SERIAL *serial)
   16.40  {
   16.41 -        serial_fifo[serial_fifo_write] = dat;
   16.42 -        serial_fifo_write = (serial_fifo_write + 1) & 0xFF;
   16.43 -        if (!(serial.linestat & 1))
   16.44 +        int stat = 0;
   16.45 +        
   16.46 +        serial->iir = 1;
   16.47 +
   16.48 +        if ((serial->ier & 4) && (serial->int_status & SERIAL_INT_LSR)) /*Line status interrupt*/
   16.49          {
   16.50 -                serial.linestat|=1;
   16.51 -                if ((serial.mctrl & 8) && (serial.ier & 1))
   16.52 -                        picint(0x10);
   16.53 -                serial.iir=4;
   16.54 +                stat = 1;
   16.55 +                serial->iir = 6;
   16.56 +        }
   16.57 +        else if ((serial->ier & 1) && (serial->int_status & SERIAL_INT_RECEIVE)) /*Recieved data available*/
   16.58 +        {
   16.59 +                stat = 1;
   16.60 +                serial->iir = 4;
   16.61 +        }
   16.62 +        else if ((serial->ier & 2) && (serial->int_status & SERIAL_INT_TRANSMIT)) /*Transmit data empty*/
   16.63 +        {
   16.64 +                stat = 1;
   16.65 +                serial->iir = 2;
   16.66 +        }
   16.67 +        else if ((serial->ier & 8) && (serial->int_status & SERIAL_INT_MSR)) /*Modem status interrupt*/
   16.68 +        {
   16.69 +                stat = 1;
   16.70 +                serial->iir = 0;
   16.71 +        }
   16.72 +
   16.73 +        if (stat && ((serial->mctrl & 8) || PCJR))
   16.74 +                picintlevel(1 << serial->irq);               
   16.75 +        else
   16.76 +                picintc(1 << serial->irq);
   16.77 +}
   16.78 +
   16.79 +void serial_write_fifo(SERIAL *serial, uint8_t dat)
   16.80 +{
   16.81 +//        pclog("serial_write_fifo %02X\n", serial->lsr);
   16.82 +        serial->fifo[serial->fifo_write] = dat;
   16.83 +        serial->fifo_write = (serial->fifo_write + 1) & 0xFF;
   16.84 +        if (!(serial->lsr & 1))
   16.85 +        {
   16.86 +                serial->lsr |= 1;
   16.87 +                serial->int_status |= SERIAL_INT_RECEIVE;
   16.88 +                serial_update_ints(serial);
   16.89          }
   16.90  }
   16.91  
   16.92 -uint8_t serial_read_fifo()
   16.93 +uint8_t serial_read_fifo(SERIAL *serial)
   16.94  {
   16.95 -        if (serial_fifo_read != serial_fifo_write)
   16.96 +        if (serial->fifo_read != serial->fifo_write)
   16.97          {
   16.98 -                serial.dat = serial_fifo[serial_fifo_read];
   16.99 -                serial_fifo_read = (serial_fifo_read + 1) & 0xFF;
  16.100 +                serial->dat = serial->fifo[serial->fifo_read];
  16.101 +                serial->fifo_read = (serial->fifo_read + 1) & 0xFF;
  16.102          }
  16.103 -        return serial.dat;
  16.104 +        return serial->dat;
  16.105  }
  16.106  
  16.107 -void sendserial(uint8_t dat)
  16.108 +void serial_write(uint16_t addr, uint8_t val, void *p)
  16.109  {
  16.110 -        serial.rcr=dat;
  16.111 -        serial.linestat|=1;
  16.112 -        if (serial.mctrl&8) picint(0x10);
  16.113 -        serial.iir=4;
  16.114 -}
  16.115 -
  16.116 -void serial_write(uint16_t addr, uint8_t val, void *priv)
  16.117 -{
  16.118 +        SERIAL *serial = (SERIAL *)p;
  16.119  //        pclog("Write serial %03X %02X %04X:%04X\n",addr,val,CS,pc);
  16.120          switch (addr&7)
  16.121          {
  16.122                  case 0:
  16.123 -                if (serial.lcr&0x80 && !AMSTRADIO)
  16.124 +                if (serial->lcr & 0x80 && !AMSTRADIO)
  16.125                  {
  16.126 -                        serial.dlab1=val;
  16.127 +                        serial->dlab1 = val;
  16.128                          return;
  16.129                  }
  16.130 -                serial.thr=val;
  16.131 -                serial.linestat|=0x20;
  16.132 -                if (serial.mctrl&0x10)
  16.133 +                serial->thr = val;
  16.134 +                serial->lsr |= 0x20;
  16.135 +                serial->int_status |= SERIAL_INT_TRANSMIT;
  16.136 +                serial_update_ints(serial);
  16.137 +                if (serial->mctrl & 0x10)
  16.138                  {
  16.139 -                        serial_write_fifo(val);
  16.140 -//                        serial.rcr=val;
  16.141 -//                        serial.linestat|=1;
  16.142 +                        serial_write_fifo(serial, val);
  16.143                  }
  16.144                  break;
  16.145                  case 1:
  16.146 -                if (serial.lcr&0x80 && !AMSTRADIO)
  16.147 +                if (serial->lcr & 0x80 && !AMSTRADIO)
  16.148                  {
  16.149 -                        serial.dlab2=val;
  16.150 +                        serial->dlab2 = val;
  16.151                          return;
  16.152                  }
  16.153 -                serial.ier=val;
  16.154 +                serial->ier = val;
  16.155 +                serial_update_ints(serial);
  16.156                  break;
  16.157 -                case 3: serial.lcr=val; break;
  16.158 +                case 3:
  16.159 +                serial->lcr = val;
  16.160 +                break;
  16.161                  case 4:
  16.162 -                if ((val&2) && !(serial.mctrl&2))
  16.163 +                if ((val & 2) && !(serial->mctrl & 2))
  16.164                  {
  16.165 -                        if (serial_rcr)
  16.166 -                           serial_rcr();
  16.167 +                        if (serial->rcr_callback)
  16.168 +                                serial->rcr_callback(serial);
  16.169  //                        pclog("RCR raised! sending M\n");
  16.170                  }
  16.171 -                serial.mctrl=val;
  16.172 +                serial->mctrl = val;
  16.173 +                if (val & 0x10)
  16.174 +                {
  16.175 +                        uint8_t new_msr;
  16.176 +                        
  16.177 +                        new_msr = (val & 0x0c) << 4;
  16.178 +                        new_msr |= (val & 0x02) ? 0x10: 0;
  16.179 +                        new_msr |= (val & 0x01) ? 0x20: 0;
  16.180 +                        
  16.181 +                        if ((serial->msr ^ new_msr) & 0x10)
  16.182 +                                new_msr |= 0x01;
  16.183 +                        if ((serial->msr ^ new_msr) & 0x20)
  16.184 +                                new_msr |= 0x02;
  16.185 +                        if ((serial->msr ^ new_msr) & 0x80)
  16.186 +                                new_msr |= 0x08;
  16.187 +                        if ((serial->msr & 0x40) && !(new_msr & 0x40))
  16.188 +                                new_msr |= 0x04;
  16.189 +                        
  16.190 +                        serial->msr = new_msr;
  16.191 +                }
  16.192 +                break;
  16.193 +                case 5:
  16.194 +                serial->lsr = val;
  16.195 +                if (serial->lsr & 0x01)
  16.196 +                        serial->int_status |= SERIAL_INT_RECEIVE;
  16.197 +                if (serial->lsr & 0x1e)
  16.198 +                        serial->int_status |= SERIAL_INT_LSR;
  16.199 +                if (serial->lsr & 0x20)
  16.200 +                        serial->int_status |= SERIAL_INT_TRANSMIT;
  16.201 +                serial_update_ints(serial);
  16.202 +                break;
  16.203 +                case 6:
  16.204 +                serial->msr = val;
  16.205 +                if (serial->msr & 0x0f)
  16.206 +                        serial->int_status |= SERIAL_INT_MSR;
  16.207 +                serial_update_ints(serial);
  16.208                  break;
  16.209          }
  16.210  }
  16.211  
  16.212 -uint8_t serial_read(uint16_t addr, void *priv)
  16.213 +uint8_t serial_read(uint16_t addr, void *p)
  16.214  {
  16.215 -        uint8_t temp;
  16.216 +        SERIAL *serial = (SERIAL *)p;
  16.217 +        uint8_t temp = 0;
  16.218  //        pclog("Read serial %03X %04X(%08X):%04X %i %i  ", addr, CS, cs, pc, mousedelay, ins);
  16.219          switch (addr&7)
  16.220          {
  16.221                  case 0:
  16.222 -                if (serial.lcr&0x80 && !AMSTRADIO) return serial.dlab1;
  16.223 -//                picintc(0x10);
  16.224 -                serial.iir=1;
  16.225 -                serial.linestat&=~1;
  16.226 -                temp=serial_read_fifo();
  16.227 -                if (serial_fifo_read != serial_fifo_write)
  16.228 +                if (serial->lcr & 0x80 && !AMSTRADIO)
  16.229 +                        return serial->dlab1;
  16.230 +
  16.231 +                serial->lsr &= ~1;
  16.232 +                serial->int_status &= ~SERIAL_INT_RECEIVE;
  16.233 +                serial_update_ints(serial);
  16.234 +                temp = serial_read_fifo(serial);
  16.235 +                if (serial->fifo_read != serial->fifo_write)
  16.236                  {
  16.237 -                        mousepos = 0;
  16.238 -                        mousedelay = 5000 * (1 << TIMER_SHIFT);
  16.239 -//                        pclog("Next FIFO\n");
  16.240 +                        serial->lsr |= 1;
  16.241 +                        serial->int_status |= SERIAL_INT_RECEIVE;
  16.242 +                        serial_update_ints(serial);
  16.243                  }
  16.244                  break;
  16.245                  case 1:
  16.246 -                if (serial.lcr&0x80 && !AMSTRADIO) temp = serial.dlab2;
  16.247 -                else                               temp = serial.ier;
  16.248 +                if (serial->lcr & 0x80 && !AMSTRADIO)
  16.249 +                        temp = serial->dlab2;
  16.250 +                else
  16.251 +                        temp = serial->ier;
  16.252                  break;
  16.253 -                case 2: temp=serial.iir; break;
  16.254 -                case 3: temp=serial.lcr; break;
  16.255 -                case 4: temp=serial.mctrl; break;
  16.256 -                case 5: temp=serial.linestat; serial.linestat|=0x60; break;
  16.257 -                default: temp=0;
  16.258 +                case 2: 
  16.259 +                temp = serial->iir;
  16.260 +                if ((temp & 0xe) == 2)
  16.261 +                {
  16.262 +                        serial->int_status &= ~SERIAL_INT_TRANSMIT;
  16.263 +                        serial_update_ints(serial);
  16.264 +                }
  16.265 +                break;
  16.266 +                case 3:
  16.267 +                temp = serial->lcr;
  16.268 +                break;
  16.269 +                case 4:
  16.270 +                temp = serial->mctrl;
  16.271 +                break;
  16.272 +                case 5:
  16.273 +                serial->lsr |= 0x20;
  16.274 +                temp = serial->lsr;
  16.275 +                if (serial->lsr & 0x1f)
  16.276 +                        serial->lsr &= ~0x1e;
  16.277 +//                serial.lsr |= 0x60;
  16.278 +                serial->int_status &= ~SERIAL_INT_LSR;
  16.279 +                serial_update_ints(serial);
  16.280 +                break;
  16.281 +                case 6:
  16.282 +                temp = serial->msr;
  16.283 +                serial->msr &= ~0x0f;
  16.284 +                serial->int_status &= ~SERIAL_INT_MSR;
  16.285 +                serial_update_ints(serial);
  16.286 +                break;
  16.287          }
  16.288  //        pclog("%02X\n",temp);
  16.289          return temp;
  16.290  }
  16.291  
  16.292 -void serial2_write(uint16_t addr, uint8_t val, void *priv)
  16.293 +/*Tandy might need COM1 at 2f8*/
  16.294 +void serial1_init(uint16_t addr, int irq)
  16.295  {
  16.296 -//        pclog("Write serial2 %03X %02X %04X:%04X\n",addr,val,cs>>4,pc);
  16.297 -        switch (addr&7)
  16.298 -        {
  16.299 -                case 0:
  16.300 -                if (serial2.lcr&0x80 && !AMSTRADIO)
  16.301 -                {
  16.302 -                        serial2.dlab1=val;
  16.303 -                        return;
  16.304 -                }
  16.305 -                serial2.thr=val;
  16.306 -                serial2.linestat|=0x20;
  16.307 -                if (serial2.mctrl&0x10)
  16.308 -                {
  16.309 -                        serial2.rcr=val;
  16.310 -                        serial2.linestat|=1;
  16.311 -                }
  16.312 -                break;
  16.313 -                case 1:
  16.314 -                if (serial2.lcr&0x80 && !AMSTRADIO)
  16.315 -                {
  16.316 -                        serial2.dlab2=val;
  16.317 -                        return;
  16.318 -                }
  16.319 -                serial2.ier=val;
  16.320 -                break;
  16.321 -                case 3: serial2.lcr=val; break;
  16.322 -                case 4:
  16.323 -                serial2.mctrl=val;
  16.324 -                break;
  16.325 -        }
  16.326 -}
  16.327 -
  16.328 -uint8_t serial2_read(uint16_t addr, void *priv)
  16.329 -{
  16.330 -        uint8_t temp;
  16.331 -//        pclog("Read serial2 %03X %04X:%04X\n",addr,cs>>4,pc);
  16.332 -        switch (addr&7)
  16.333 -        {
  16.334 -                case 0:
  16.335 -                if (serial2.lcr&0x80 && !AMSTRADIO) return serial2.dlab1;
  16.336 -                serial2.iir=1;
  16.337 -                serial2.linestat&=~1;
  16.338 -                temp=serial2.rcr;
  16.339 -                break;
  16.340 -                case 1:
  16.341 -                if (serial2.lcr&0x80 && !AMSTRADIO) return serial2.dlab2;
  16.342 -                temp=0;
  16.343 -                break;
  16.344 -                case 2: temp=serial2.iir; break;
  16.345 -                case 3: temp=serial2.lcr; break;
  16.346 -                case 4: temp=serial2.mctrl; break;
  16.347 -                case 5: temp=serial2.linestat; break;
  16.348 -                default: temp=0;
  16.349 -        }
  16.350 -//        pclog("%02X\n",temp);
  16.351 -        return temp;
  16.352 -}
  16.353 -
  16.354 -
  16.355 -/*Tandy might need COM1 at 2f8*/
  16.356 -void serial1_init(uint16_t addr)
  16.357 -{
  16.358 -        io_sethandler(addr, 0x0008, serial_read,  NULL, NULL, serial_write,  NULL, NULL, NULL);
  16.359 -        serial_rcr = NULL;
  16.360 +        io_sethandler(addr, 0x0008, serial_read,  NULL, NULL, serial_write,  NULL, NULL, &serial1);
  16.361 +        serial1.irq = irq;
  16.362 +        serial1.rcr_callback = NULL;
  16.363  }
  16.364  void serial1_remove()
  16.365  {
  16.366 -        io_removehandler(0x2e8, 0x0008, serial_read,  NULL, NULL, serial_write,  NULL, NULL, NULL);
  16.367 -        io_removehandler(0x2f8, 0x0008, serial_read,  NULL, NULL, serial_write,  NULL, NULL, NULL);
  16.368 -        io_removehandler(0x3e8, 0x0008, serial_read,  NULL, NULL, serial_write,  NULL, NULL, NULL);
  16.369 -        io_removehandler(0x3f8, 0x0008, serial_read,  NULL, NULL, serial_write,  NULL, NULL, NULL);
  16.370 +        io_removehandler(0x2e8, 0x0008, serial_read,  NULL, NULL, serial_write,  NULL, NULL, &serial1);
  16.371 +        io_removehandler(0x2f8, 0x0008, serial_read,  NULL, NULL, serial_write,  NULL, NULL, &serial1);
  16.372 +        io_removehandler(0x3e8, 0x0008, serial_read,  NULL, NULL, serial_write,  NULL, NULL, &serial1);
  16.373 +        io_removehandler(0x3f8, 0x0008, serial_read,  NULL, NULL, serial_write,  NULL, NULL, &serial1);
  16.374  }
  16.375  
  16.376 -void serial2_init(uint16_t addr)
  16.377 +void serial2_init(uint16_t addr, int irq)
  16.378  {
  16.379 -        io_sethandler(addr, 0x0008, serial2_read, NULL, NULL, serial2_write, NULL, NULL, NULL);
  16.380 +        io_sethandler(addr, 0x0008, serial_read, NULL, NULL, serial_write, NULL, NULL, &serial2);
  16.381 +        serial2.irq = irq;
  16.382 +        serial2.rcr_callback = NULL;
  16.383  }
  16.384  void serial2_remove()
  16.385  {
  16.386 -        io_removehandler(0x2e8, 0x0008, serial2_read, NULL, NULL, serial2_write, NULL, NULL, NULL);
  16.387 -        io_removehandler(0x2f8, 0x0008, serial2_read, NULL, NULL, serial2_write, NULL, NULL, NULL);
  16.388 -        io_removehandler(0x3e8, 0x0008, serial2_read, NULL, NULL, serial2_write, NULL, NULL, NULL);
  16.389 -        io_removehandler(0x3f8, 0x0008, serial2_read, NULL, NULL, serial2_write, NULL, NULL, NULL);
  16.390 +        io_removehandler(0x2e8, 0x0008, serial_read, NULL, NULL, serial_write, NULL, NULL, &serial2);
  16.391 +        io_removehandler(0x2f8, 0x0008, serial_read, NULL, NULL, serial_write, NULL, NULL, &serial2);
  16.392 +        io_removehandler(0x3e8, 0x0008, serial_read, NULL, NULL, serial_write, NULL, NULL, &serial2);
  16.393 +        io_removehandler(0x3f8, 0x0008, serial_read, NULL, NULL, serial_write, NULL, NULL, &serial2);
  16.394  }
    17.1 --- a/src/serial.h	Fri Jan 03 20:48:12 2014 +0000
    17.2 +++ b/src/serial.h	Sun Jan 12 11:37:09 2014 +0000
    17.3 @@ -1,18 +1,23 @@
    17.4 -void serial1_init(uint16_t addr);
    17.5 -void serial2_init(uint16_t addr);
    17.6 +void serial1_init(uint16_t addr, int irq);
    17.7 +void serial2_init(uint16_t addr, int irq);
    17.8  void serial1_remove();
    17.9  void serial2_remove();
   17.10  void serial_reset();
   17.11  
   17.12 +struct SERIAL;
   17.13 +
   17.14  typedef struct
   17.15  {
   17.16 -        uint8_t linestat,thr,mctrl,rcr,iir,ier,lcr;
   17.17 +        uint8_t lsr,thr,mctrl,rcr,iir,ier,lcr,msr;
   17.18          uint8_t dlab1,dlab2;
   17.19          uint8_t dat;
   17.20 +        uint8_t int_status;
   17.21 +        
   17.22 +        int irq;
   17.23 +
   17.24 +        void (*rcr_callback)(void *p);
   17.25 +        uint8_t fifo[256];
   17.26 +        int fifo_read, fifo_write;
   17.27  } SERIAL;
   17.28  
   17.29 -extern SERIAL serial,serial2;
   17.30 -
   17.31 -extern int serial_fifo_read, serial_fifo_write;
   17.32 -
   17.33 -extern void (*serial_rcr)();
   17.34 +extern SERIAL serial1, serial2;
    18.1 --- a/src/sound_sn76489.c	Fri Jan 03 20:48:12 2014 +0000
    18.2 +++ b/src/sound_sn76489.c	Sun Jan 12 11:37:09 2014 +0000
    18.3 @@ -5,6 +5,8 @@
    18.4  #include "sound.h"
    18.5  #include "sound_sn76489.h"
    18.6  
    18.7 +int sn76489_mute;
    18.8 +
    18.9  static float volslog[16]=
   18.10  {
   18.11  	0.00000f,0.59715f,0.75180f,0.94650f,
   18.12 @@ -79,9 +81,12 @@
   18.13          sn76489_t *sn76489 = (sn76489_t *)p;
   18.14          
   18.15          int c;
   18.16 -
   18.17 -        for (c = 0; c < len * 2; c++)
   18.18 -                buffer[c] += sn76489->buffer[c >> 1];
   18.19 +        
   18.20 +        if (!sn76489_mute)
   18.21 +        {
   18.22 +                for (c = 0; c < len * 2; c++)
   18.23 +                        buffer[c] += sn76489->buffer[c >> 1];
   18.24 +        }
   18.25  
   18.26          sn76489->pos = 0;
   18.27  }
   18.28 @@ -179,6 +184,8 @@
   18.29          sn76489->noise = 3;
   18.30          sn76489->shift = 0x4000;
   18.31  
   18.32 +        sn76489_mute = 0;
   18.33 +
   18.34          return sn76489;
   18.35  }
   18.36  
    19.1 --- a/src/sound_sn76489.h	Fri Jan 03 20:48:12 2014 +0000
    19.2 +++ b/src/sound_sn76489.h	Sun Jan 12 11:37:09 2014 +0000
    19.3 @@ -1,1 +1,3 @@
    19.4  extern device_t sn76489_device;
    19.5 +
    19.6 +extern int sn76489_mute;
    20.1 --- a/src/sound_speaker.c	Fri Jan 03 20:48:12 2014 +0000
    20.2 +++ b/src/sound_speaker.c	Sun Jan 12 11:37:09 2014 +0000
    20.3 @@ -2,6 +2,8 @@
    20.4  #include "sound.h"
    20.5  #include "sound_speaker.h"
    20.6  
    20.7 +int speaker_mute = 0;
    20.8 +
    20.9  static int16_t speaker_buffer[SOUNDBUFLEN];
   20.10  
   20.11  static int speaker_pos = 0;
   20.12 @@ -30,8 +32,11 @@
   20.13  {
   20.14          int c;
   20.15  
   20.16 -        for (c = 0; c < len * 2; c++)
   20.17 -                buffer[c] += speaker_buffer[c >> 1];
   20.18 +        if (!speaker_mute)
   20.19 +        {
   20.20 +                for (c = 0; c < len * 2; c++)
   20.21 +                        buffer[c] += speaker_buffer[c >> 1];
   20.22 +        }
   20.23  
   20.24          speaker_pos = 0;
   20.25  }
   20.26 @@ -39,4 +44,5 @@
   20.27  void speaker_init()
   20.28  {
   20.29          sound_add_handler(speaker_poll, speaker_get_buffer, NULL);
   20.30 +        speaker_mute = 0;
   20.31  }
    21.1 --- a/src/sound_speaker.h	Fri Jan 03 20:48:12 2014 +0000
    21.2 +++ b/src/sound_speaker.h	Sun Jan 12 11:37:09 2014 +0000
    21.3 @@ -1,1 +1,3 @@
    21.4  void speaker_init();
    21.5 +
    21.6 +extern int speaker_mute;
    22.1 --- a/src/um8669f.c	Fri Jan 03 20:48:12 2014 +0000
    22.2 +++ b/src/um8669f.c	Sun Jan 12 11:37:09 2014 +0000
    22.3 @@ -83,10 +83,10 @@
    22.4                                     temp |= 2;
    22.5                                  switch (temp)
    22.6                                  {
    22.7 -                                        case 0: serial1_init(0x3f8); break;
    22.8 -                                        case 1: serial1_init(0x2f8); break;
    22.9 -                                        case 2: serial1_init(0x3e8); break;
   22.10 -                                        case 3: serial1_init(0x2e8); break;
   22.11 +                                        case 0: serial1_init(0x3f8, 4); break;
   22.12 +                                        case 1: serial1_init(0x2f8, 4); break;
   22.13 +                                        case 2: serial1_init(0x3e8, 4); break;
   22.14 +                                        case 3: serial1_init(0x2e8, 4); break;
   22.15                                  }
   22.16                          }
   22.17                          
   22.18 @@ -98,10 +98,10 @@
   22.19                                     temp |= 2;
   22.20                                  switch (temp)
   22.21                                  {
   22.22 -                                        case 0: serial2_init(0x3f8); break;
   22.23 -                                        case 1: serial2_init(0x2f8); break;
   22.24 -                                        case 2: serial2_init(0x3e8); break;
   22.25 -                                        case 3: serial2_init(0x2e8); break;
   22.26 +                                        case 0: serial2_init(0x3f8, 3); break;
   22.27 +                                        case 1: serial2_init(0x2f8, 3); break;
   22.28 +                                        case 2: serial2_init(0x3e8, 3); break;
   22.29 +                                        case 3: serial2_init(0x2e8, 3); break;
   22.30                                  }
   22.31                          }
   22.32                          
    23.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    23.2 +++ b/src/vid_pcjr.c	Sun Jan 12 11:37:09 2014 +0000
    23.3 @@ -0,0 +1,647 @@
    23.4 +#include <stdlib.h>
    23.5 +#include <math.h>
    23.6 +#include "ibm.h"
    23.7 +#include "device.h"
    23.8 +#include "io.h"
    23.9 +#include "mem.h"
   23.10 +#include "timer.h"
   23.11 +#include "video.h"
   23.12 +#include "vid_pcjr.h"
   23.13 +
   23.14 +static int i_filt[8],q_filt[8];
   23.15 +
   23.16 +typedef struct pcjr_t
   23.17 +{
   23.18 +        mem_mapping_t mapping;
   23.19 +        
   23.20 +        uint8_t crtc[32];
   23.21 +        int crtcreg;
   23.22 +        
   23.23 +        int      array_index;
   23.24 +        uint8_t  array[32];
   23.25 +        int      array_ff;
   23.26 +        int      memctrl;//=-1;
   23.27 +        uint8_t  stat;
   23.28 +        int addr_mode;
   23.29 +        
   23.30 +        uint8_t *vram, *b8000;
   23.31 +
   23.32 +        int linepos, displine;
   23.33 +        int sc, vc;
   23.34 +        int dispon;
   23.35 +        int con, coff, cursoron, blink;
   23.36 +        int vsynctime, vadj;
   23.37 +        uint16_t ma, maback;
   23.38 +        
   23.39 +        int dispontime, dispofftime, vidtime;
   23.40 +        int firstline, lastline;
   23.41 +} pcjr_t;
   23.42 +
   23.43 +static uint8_t crtcmask[32] = 
   23.44 +{
   23.45 +        0xff, 0xff, 0xff, 0xff, 0x7f, 0x1f, 0x7f, 0x7f, 0xf3, 0x1f, 0x7f, 0x1f, 0x3f, 0xff, 0x3f, 0xff,
   23.46 +        0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
   23.47 +};
   23.48 +
   23.49 +void pcjr_recalcaddress(pcjr_t *pcjr);
   23.50 +void pcjr_recalctimings(pcjr_t *pcjr);
   23.51 +        
   23.52 +void pcjr_out(uint16_t addr, uint8_t val, void *p)
   23.53 +{
   23.54 +        pcjr_t *pcjr = (pcjr_t *)p;
   23.55 +        uint8_t old;
   23.56 +//        pclog("pcjr OUT %04X %02X\n",addr,val);
   23.57 +        switch (addr)
   23.58 +        {
   23.59 +                case 0x3d4:
   23.60 +                pcjr->crtcreg = val & 0x1f;
   23.61 +                return;
   23.62 +                case 0x3d5:
   23.63 +//                        pclog("CRTC write %02X %02x\n", pcjr->crtcreg, val);
   23.64 +                old = pcjr->crtc[pcjr->crtcreg];
   23.65 +                pcjr->crtc[pcjr->crtcreg] = val & crtcmask[pcjr->crtcreg];
   23.66 +                if (old != val)
   23.67 +                {
   23.68 +                        if (pcjr->crtcreg < 0xe || pcjr->crtcreg > 0x10)
   23.69 +                        {
   23.70 +                                fullchange = changeframecount;
   23.71 +                                pcjr_recalctimings(pcjr);
   23.72 +                        }
   23.73 +                }
   23.74 +                return;
   23.75 +                case 0x3da:
   23.76 +//                pclog("Array write %02X %02X\n", pcjr->array_index, val);
   23.77 +                if (!pcjr->array_ff)
   23.78 +                        pcjr->array_index = val & 0x1f;
   23.79 +                else
   23.80 +                {
   23.81 +                        if (pcjr->array_index & 0x10)
   23.82 +                                val &= 0x0f;
   23.83 +                        pcjr->array[pcjr->array_index & 0x1f] = val;
   23.84 +                }
   23.85 +                pcjr->array_ff = !pcjr->array_ff;
   23.86 +                break;
   23.87 +                case 0x3df:
   23.88 +                pcjr->memctrl = val;
   23.89 +                pcjr->addr_mode = val >> 6;
   23.90 +                pcjr_recalcaddress(pcjr);
   23.91 +                break;
   23.92 +        }
   23.93 +}
   23.94 +
   23.95 +uint8_t pcjr_in(uint16_t addr, void *p)
   23.96 +{
   23.97 +        pcjr_t *pcjr = (pcjr_t *)p;
   23.98 +//        if (addr!=0x3DA) pclog("pcjr IN %04X\n",addr);
   23.99 +        switch (addr)
  23.100 +        {
  23.101 +                case 0x3d4:
  23.102 +                return pcjr->crtcreg;
  23.103 +                case 0x3d5:
  23.104 +                return pcjr->crtc[pcjr->crtcreg];
  23.105 +                case 0x3da:
  23.106 +                pcjr->array_ff = 0;
  23.107 +                pcjr->stat ^= 0x10;
  23.108 +                return pcjr->stat;
  23.109 +        }
  23.110 +        return 0xFF;
  23.111 +}
  23.112 +
  23.113 +void pcjr_recalcaddress(pcjr_t *pcjr)
  23.114 +{
  23.115 +        if ((pcjr->memctrl & 0xc0) == 0xc0)
  23.116 +        {
  23.117 +                pcjr->vram  = &ram[(pcjr->memctrl & 0x06) << 14];
  23.118 +                pcjr->b8000 = &ram[(pcjr->memctrl & 0x30) << 11];
  23.119 +//                printf("VRAM at %05X B8000 at %05X\n",((pcjr->memctrl&0x6)<<14)+pcjr->base,((pcjr->memctrl&0x30)<<11)+pcjr->base);
  23.120 +        }
  23.121 +        else
  23.122 +        {
  23.123 +                pcjr->vram  = &ram[(pcjr->memctrl & 0x07) << 14];
  23.124 +                pcjr->b8000 = &ram[(pcjr->memctrl & 0x38) << 11];
  23.125 +//                printf("VRAM at %05X B8000 at %05X\n",((pcjr->memctrl&0x7)<<14)+pcjr->base,((pcjr->memctrl&0x38)<<11)+pcjr->base);
  23.126 +        }
  23.127 +}
  23.128 +
  23.129 +void pcjr_write(uint32_t addr, uint8_t val, void *p)
  23.130 +{
  23.131 +        pcjr_t *pcjr = (pcjr_t *)p;
  23.132 +        if (pcjr->memctrl == -1) 
  23.133 +                return;
  23.134 +                
  23.135 +        egawrites++;
  23.136 +//        pclog("pcjr VRAM write %05X %02X %04X:%04X  %04X:%04X\n",addr,val,CS,pc,DS,SI);
  23.137 +        pcjr->b8000[addr & 0x3fff] = val;
  23.138 +}
  23.139 +
  23.140 +uint8_t pcjr_read(uint32_t addr, void *p)
  23.141 +{
  23.142 +        pcjr_t *pcjr = (pcjr_t *)p;
  23.143 +        if (pcjr->memctrl == -1) 
  23.144 +                return 0xff;
  23.145 +                
  23.146 +        egareads++;
  23.147 +//        pclog("pcjr VRAM read  %05X %02X %04X:%04X\n",addr,pcjr->b8000[addr&0x7FFF],CS,pc);
  23.148 +        return pcjr->b8000[addr & 0x3fff];
  23.149 +}
  23.150 +
  23.151 +void pcjr_recalctimings(pcjr_t *pcjr)
  23.152 +{
  23.153 +	double _dispontime, _dispofftime, disptime;
  23.154 +        if (pcjr->array[0] & 1)
  23.155 +        {
  23.156 +                disptime = pcjr->crtc[0] + 1;
  23.157 +                _dispontime = pcjr->crtc[1];
  23.158 +        }
  23.159 +        else
  23.160 +        {
  23.161 +                disptime = (pcjr->crtc[0] + 1) << 1;
  23.162 +                _dispontime = pcjr->crtc[1] << 1;
  23.163 +        }
  23.164 +        _dispofftime = disptime - _dispontime;
  23.165 +        _dispontime  *= CGACONST;
  23.166 +        _dispofftime *= CGACONST;
  23.167 +	pcjr->dispontime  = (int)(_dispontime  * (1 << TIMER_SHIFT));
  23.168 +	pcjr->dispofftime = (int)(_dispofftime * (1 << TIMER_SHIFT));
  23.169 +}
  23.170 +
  23.171 +
  23.172 +static int ntsc_col[8][8]=
  23.173 +{
  23.174 +        {0,0,0,0,0,0,0,0}, /*Black*/
  23.175 +        {0,0,1,1,1,1,0,0}, /*Blue*/
  23.176 +        {1,0,0,0,0,1,1,1}, /*Green*/
  23.177 +        {0,0,0,0,1,1,1,1}, /*Cyan*/
  23.178 +        {1,1,1,1,0,0,0,0}, /*Red*/
  23.179 +        {0,1,1,1,1,0,0,0}, /*Magenta*/
  23.180 +        {1,1,0,0,0,0,1,1}, /*Yellow*/
  23.181 +        {1,1,1,1,1,1,1,1}  /*White*/
  23.182 +};
  23.183 +
  23.184 +/*static int cga4pal[8][4]=
  23.185 +{
  23.186 +        {0,2,4,6},{0,3,5,7},{0,3,4,7},{0,3,4,7},
  23.187 +        {0,10,12,14},{0,11,13,15},{0,11,12,15},{0,11,12,15}
  23.188 +};*/
  23.189 +
  23.190 +void pcjr_poll(void *p)
  23.191 +{
  23.192 +//        int *cgapal=cga4pal[((pcjr->col&0x10)>>2)|((cgamode&4)>>1)|((cgacol&0x20)>>5)];
  23.193 +        pcjr_t *pcjr = (pcjr_t *)p;
  23.194 +        uint16_t ca = (pcjr->crtc[15] | (pcjr->crtc[14] << 8)) & 0x3fff;
  23.195 +        int drawcursor;
  23.196 +        int x, c;
  23.197 +        int oldvc;
  23.198 +        uint8_t chr, attr;
  23.199 +        uint16_t dat;
  23.200 +        int cols[4];
  23.201 +        int col;
  23.202 +        int oldsc;
  23.203 +        int y_buf[8] = {0, 0, 0, 0, 0, 0, 0, 0}, y_val, y_tot;
  23.204 +        int i_buf[8] = {0, 0, 0, 0, 0, 0, 0, 0}, i_val, i_tot;
  23.205 +        int q_buf[8] = {0, 0, 0, 0, 0, 0, 0, 0}, q_val, q_tot;
  23.206 +        int r, g, b;
  23.207 +        if (!pcjr->linepos)
  23.208 +        {
  23.209 +//                cgapal[0]=pcjr->col&15;
  23.210 +//                printf("Firstline %i Lastline %i pcjr->displine %i\n",firstline,lastline,pcjr->displine);
  23.211 +                pcjr->vidtime += pcjr->dispofftime;
  23.212 +                pcjr->stat &= ~1;
  23.213 +                pcjr->linepos = 1;
  23.214 +                oldsc = pcjr->sc;
  23.215 +                if ((pcjr->crtc[8] & 3) == 3) 
  23.216 +                        pcjr->sc = (pcjr->sc << 1) & 7;
  23.217 +                if (pcjr->dispon)
  23.218 +                {
  23.219 +                        uint16_t offset = 0;
  23.220 +                        uint16_t mask = 0x1fff;
  23.221 +                        
  23.222 +                        if (pcjr->displine < pcjr->firstline)
  23.223 +                                pcjr->firstline = pcjr->displine;                                
  23.224 +                        pcjr->lastline = pcjr->displine;
  23.225 +                        cols[0] = (pcjr->array[2] & 0xf) + 16;
  23.226 +                        for (c = 0; c < 8; c++)
  23.227 +                        {
  23.228 +                                buffer->line[pcjr->displine][c] = cols[0];
  23.229 +                                if (pcjr->array[0] & 1) buffer->line[pcjr->displine][c + (pcjr->crtc[1] << 3) + 8] = cols[0];
  23.230 +                                else                    buffer->line[pcjr->displine][c + (pcjr->crtc[1] << 4) + 8] = cols[0];
  23.231 +                        }
  23.232 +                        
  23.233 +                        switch (pcjr->addr_mode)
  23.234 +                        {
  23.235 +                                case 0: /*Alpha*/
  23.236 +                                offset = 0;
  23.237 +                                mask = 0x3fff;
  23.238 +                                break;
  23.239 +                                case 1: /*Low resolution graphics*/
  23.240 +                                offset = (pcjr->sc & 1) * 0x2000;
  23.241 +                                break;
  23.242 +                                case 3: /*High resolution graphics*/
  23.243 +                                offset = (pcjr->sc & 3) * 0x2000;
  23.244 +                                break;
  23.245 +                        }
  23.246 +                        
  23.247 +                        switch ((pcjr->array[0] & 0x13) | ((pcjr->array[3] & 0x10) << 4))
  23.248 +                        {
  23.249 +                                case 0x13: /*320x200x16*/
  23.250 +                                for (x = 0; x < pcjr->crtc[1]; x++)
  23.251 +                                {
  23.252 +                                        dat = (pcjr->vram[((pcjr->ma << 1) & mask) + offset] << 8) | 
  23.253 +                                               pcjr->vram[((pcjr->ma << 1) & mask) + offset + 1];
  23.254 +                                        pcjr->ma++;
  23.255 +                                        buffer->line[pcjr->displine][(x << 3) + 8]  = 
  23.256 +                                        buffer->line[pcjr->displine][(x << 3) + 9]  = pcjr->array[((dat >> 12) & pcjr->array[1]) + 16] + 16;
  23.257 +                                        buffer->line[pcjr->displine][(x << 3) + 10] = 
  23.258 +                                        buffer->line[pcjr->displine][(x << 3) + 11] = pcjr->array[((dat >>  8) & pcjr->array[1]) + 16] + 16;
  23.259 +                                        buffer->line[pcjr->displine][(x << 3) + 12] = 
  23.260 +                                        buffer->line[pcjr->displine][(x << 3) + 13] = pcjr->array[((dat >>  4) & pcjr->array[1]) + 16] + 16;
  23.261 +                                        buffer->line[pcjr->displine][(x << 3) + 14] = 
  23.262 +                                        buffer->line[pcjr->displine][(x << 3) + 15] = pcjr->array[(dat         & pcjr->array[1]) + 16] + 16;
  23.263 +                                }
  23.264 +                                break;
  23.265 +                                case 0x12: /*160x200x16*/
  23.266 +                                for (x = 0; x < pcjr->crtc[1]; x++)
  23.267 +                                {
  23.268 +                                        dat = (pcjr->vram[((pcjr->ma << 1) & mask) + offset] << 8) | 
  23.269 +                                               pcjr->vram[((pcjr->ma << 1) & mask) + offset + 1];
  23.270 +                                        pcjr->ma++;
  23.271 +                                        buffer->line[pcjr->displine][(x << 4) + 8]  = 
  23.272 +                                        buffer->line[pcjr->displine][(x << 4) + 9]  = 
  23.273 +                                        buffer->line[pcjr->displine][(x << 4) + 10] =
  23.274 +                                        buffer->line[pcjr->displine][(x << 4) + 11] = pcjr->array[((dat >> 12) & pcjr->array[1]) + 16] + 16;
  23.275 +                                        buffer->line[pcjr->displine][(x << 4) + 12] = 
  23.276 +                                        buffer->line[pcjr->displine][(x << 4) + 13] =
  23.277 +                                        buffer->line[pcjr->displine][(x << 4) + 14] =
  23.278 +                                        buffer->line[pcjr->displine][(x << 4) + 15] = pcjr->array[((dat >>  8) & pcjr->array[1]) + 16] + 16;
  23.279 +                                        buffer->line[pcjr->displine][(x << 4) + 16] = 
  23.280 +                                        buffer->line[pcjr->displine][(x << 4) + 17] =
  23.281 +                                        buffer->line[pcjr->displine][(x << 4) + 18] =
  23.282 +                                        buffer->line[pcjr->displine][(x << 4) + 19] = pcjr->array[((dat >>  4) & pcjr->array[1]) + 16] + 16;
  23.283 +                                        buffer->line[pcjr->displine][(x << 4) + 20] = 
  23.284 +                                        buffer->line[pcjr->displine][(x << 4) + 21] =
  23.285 +                                        buffer->line[pcjr->displine][(x << 4) + 22] =
  23.286 +                                        buffer->line[pcjr->displine][(x << 4) + 23] = pcjr->array[(dat         & pcjr->array[1]) + 16] + 16;
  23.287 +                                }
  23.288 +                                break;
  23.289 +                                case 0x03: /*640x200x4*/
  23.290 +                                for (x = 0; x < pcjr->crtc[1]; x++)
  23.291 +                                {
  23.292 +                                        dat = (pcjr->vram[((pcjr->ma << 1) & mask) + offset] << 8) |
  23.293 +                                               pcjr->vram[((pcjr->ma << 1) & mask) + offset + 1];
  23.294 +                                        pcjr->ma++;
  23.295 +                                        for (c = 0; c < 8; c++)
  23.296 +                                        {
  23.297 +                                                chr  =  (dat >>  7) & 1;
  23.298 +                                                chr |= ((dat >> 14) & 2);
  23.299 +                                                buffer->line[pcjr->displine][(x << 3) + 8 + c] = pcjr->array[(chr & pcjr->array[1]) + 16] + 16;
  23.300 +                                                dat <<= 1;
  23.301 +                                        }
  23.302 +                                }
  23.303 +                                break;
  23.304 +                                case 0x01: /*80 column text*/
  23.305 +                                for (x = 0; x < pcjr->crtc[1]; x++)
  23.306 +                                {
  23.307 +                                        chr  = pcjr->vram[((pcjr->ma << 1) & mask) + offset];
  23.308 +                                        attr = pcjr->vram[((pcjr->ma << 1) & mask) + offset + 1];
  23.309 +                                        drawcursor = ((pcjr->ma == ca) && pcjr->con && pcjr->cursoron);
  23.310 +                                        if (pcjr->array[3] & 4)
  23.311 +                                        {
  23.312 +                                                cols[1] = pcjr->array[ ((attr & 15)      & pcjr->array[1]) + 16] + 16;
  23.313 +                                                cols[0] = pcjr->array[(((attr >> 4) & 7) & pcjr->array[1]) + 16] + 16;
  23.314 +                                                if ((pcjr->blink & 16) && (attr & 0x80) && !drawcursor) 
  23.315 +                                                        cols[1] = cols[0];
  23.316 +                                        }
  23.317 +                                        else
  23.318 +                                        {
  23.319 +                                                cols[1] = pcjr->array[((attr & 15) & pcjr->array[1]) + 16] + 16;
  23.320 +                                                cols[0] = pcjr->array[((attr >> 4) & pcjr->array[1]) + 16] + 16;
  23.321 +                                        }
  23.322 +                                        if (pcjr->sc & 8)
  23.323 +                                        {
  23.324 +                                                for (c = 0; c < 8; c++)
  23.325 +                                                    buffer->line[pcjr->displine][(x << 3) + c + 8] = cols[0];
  23.326 +                                        }
  23.327 +                                        else
  23.328 +                                        {
  23.329 +                                                for (c = 0; c < 8; c++)
  23.330 +                                                    buffer->line[pcjr->displine][(x << 3) + c + 8] = cols[(fontdat[chr][pcjr->sc & 7] & (1 << (c ^ 7))) ? 1 : 0];
  23.331 +                                        }
  23.332 +//                                        if (!((ma^(crtc[15]|(crtc[14]<<8)))&0x3FFF)) printf("Cursor match! %04X\n",ma);
  23.333 +                                        if (drawcursor)
  23.334 +                                        {
  23.335 +                                                for (c = 0; c < 8; c++)
  23.336 +                                                    buffer->line[pcjr->displine][(x << 3) + c + 8] ^= 15;
  23.337 +                                        }
  23.338 +                                        pcjr->ma++;
  23.339 +                                }
  23.340 +                                break;
  23.341 +                                case 0x00: /*40 column text*/
  23.342 +                                for (x = 0; x < pcjr->crtc[1]; x++)
  23.343 +                                {
  23.344 +                                        chr  = pcjr->vram[((pcjr->ma << 1) & mask) + offset];
  23.345 +                                        attr = pcjr->vram[((pcjr->ma << 1) & mask) + offset + 1];
  23.346 +                                        drawcursor = ((pcjr->ma == ca) && pcjr->con && pcjr->cursoron);
  23.347 +                                        if (pcjr->array[3] & 4)
  23.348 +                                        {
  23.349 +                                                cols[1] = pcjr->array[ ((attr & 15)      & pcjr->array[1]) + 16] + 16;
  23.350 +                                                cols[0] = pcjr->array[(((attr >> 4) & 7) & pcjr->array[1]) + 16] + 16;
  23.351 +                                                if ((pcjr->blink & 16) && (attr & 0x80) && !drawcursor) 
  23.352 +                                                        cols[1] = cols[0];
  23.353 +                                        }
  23.354 +                                        else
  23.355 +                                        {
  23.356 +                                                cols[1] = pcjr->array[((attr & 15) & pcjr->array[1]) + 16] + 16;
  23.357 +                                                cols[0] = pcjr->array[((attr >> 4) & pcjr->array[1]) + 16] + 16;
  23.358 +                                        }
  23.359 +                                        pcjr->ma++;
  23.360 +                                        if (pcjr->sc & 8)
  23.361 +                                        {
  23.362 +                                                for (c = 0; c < 8; c++)
  23.363 +                                                    buffer->line[pcjr->displine][(x << 4) + (c << 1) + 8] = 
  23.364 +                                                    buffer->line[pcjr->displine][(x << 4) + (c << 1) + 1 + 8] = cols[0];
  23.365 +                                        }
  23.366 +                                        else
  23.367 +                                        {
  23.368 +                                                for (c = 0; c < 8; c++)
  23.369 +                                                    buffer->line[pcjr->displine][(x << 4) + (c << 1) + 8] = 
  23.370 +                                                    buffer->line[pcjr->displine][(x << 4) + (c << 1) + 1 + 8] = cols[(fontdat[chr][pcjr->sc & 7] & (1 << (c ^ 7))) ? 1 : 0];
  23.371 +                                        }
  23.372 +                                        if (drawcursor)
  23.373 +                                        {
  23.374 +                                                for (c = 0; c < 16; c++)
  23.375 +                                                    buffer->line[pcjr->displine][(x << 4) + c + 8] ^= 15;
  23.376 +                                        }
  23.377 +                                }
  23.378 +                                break;
  23.379 +                                case 0x02: /*320x200x4*/
  23.380 +                                cols[0] = pcjr->array[0 + 16] + 16;
  23.381 +                                cols[1] = pcjr->array[1 + 16] + 16;
  23.382 +                                cols[2] = pcjr->array[2 + 16] + 16;
  23.383 +                                cols[3] = pcjr->array[3 + 16] + 16;
  23.384 +                                for (x = 0; x < pcjr->crtc[1]; x++)
  23.385 +                                {
  23.386 +                                        dat = (pcjr->vram[((pcjr->ma << 1) & mask) + offset] << 8) | 
  23.387 +                                               pcjr->vram[((pcjr->ma << 1) & mask) + offset + 1];
  23.388 +                                        pcjr->ma++;
  23.389 +                                        for (c = 0; c < 8; c++)
  23.390 +                                        {
  23.391 +                                                buffer->line[pcjr->displine][(x << 4) + (c << 1) + 8] =
  23.392 +                                                buffer->line[pcjr->displine][(x << 4) + (c << 1) + 1 + 8] = cols[dat >> 14];
  23.393 +                                                dat <<= 2;
  23.394 +                                        }
  23.395 +                                }
  23.396 +                                break;
  23.397 +                                case 0x102: /*640x200x2*/
  23.398 +                                cols[0] = 0; 
  23.399 +                                cols[1] = pcjr->array[0 + 16] + 16;
  23.400 +                                for (x = 0; x < pcjr->crtc[1]; x++)
  23.401 +                                {
  23.402 +                                        dat = (pcjr->vram[((pcjr->ma << 1) & mask) + offset] << 8) |
  23.403 +                                               pcjr->vram[((pcjr->ma << 1) & mask) + offset + 1];
  23.404 +                                        pcjr->ma++;
  23.405 +                                        for (c = 0; c < 16; c++)
  23.406 +                                        {
  23.407 +                                                buffer->line[pcjr->displine][(x << 4) + c + 8] = cols[dat >> 15];
  23.408 +                                                dat <<= 1;
  23.409 +                                        }
  23.410 +                                }
  23.411 +                                break;
  23.412 +                        }
  23.413 +                }
  23.414 +                else
  23.415 +                {
  23.416 +                        if (pcjr->array[3] & 4)
  23.417 +                        {
  23.418 +                                if (pcjr->array[0] & 1) hline(buffer, 0, pcjr->displine, (pcjr->crtc[1] << 3) + 16, (pcjr->array[2] & 0xf) + 16);
  23.419 +                                else                 hline(buffer, 0, pcjr->displine, (pcjr->crtc[1] << 4) + 16, (pcjr->array[2] & 0xf) + 16);
  23.420 +                        }
  23.421 +                        else
  23.422 +                        {
  23.423 +//                                cols[0] = ((pcjr->mode & 0x12) == 0x12) ? 0 : (pcjr->col & 0xf) + 16;
  23.424 +                                cols[0] = pcjr->array[0 + 16] + 16;
  23.425 +                                if (pcjr->array[0] & 1) hline(buffer, 0, pcjr->displine, (pcjr->crtc[1] << 3) + 16, cols[0]);
  23.426 +                                else                 hline(buffer, 0, pcjr->displine, (pcjr->crtc[1] << 4) + 16, cols[0]);
  23.427 +                        }
  23.428 +                }
  23.429 +                if (pcjr->array[0] & 1) x = (pcjr->crtc[1] << 3) + 16;
  23.430 +                else                    x = (pcjr->crtc[1] << 4) + 16;
  23.431 +                if (cga_comp)
  23.432 +                {
  23.433 +                        for (c = 0; c < x; c++)
  23.434 +                        {
  23.435 +                                y_buf[(c << 1) & 6] = ntsc_col[buffer->line[pcjr->displine][c] & 7][(c << 1) & 6] ? 0x6000 : 0;
  23.436 +                                y_buf[(c << 1) & 6] += (buffer->line[pcjr->displine][c] & 8) ? 0x3000 : 0;
  23.437 +                                i_buf[(c << 1) & 6] = y_buf[(c << 1) & 6] * i_filt[(c << 1) & 6];
  23.438 +                                q_buf[(c << 1) & 6] = y_buf[(c << 1) & 6] * q_filt[(c << 1) & 6];
  23.439 +                                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];
  23.440 +                                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];
  23.441 +                                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];
  23.442 +
  23.443 +                                y_val = y_tot >> 10;
  23.444 +                                if (y_val > 255) y_val = 255;
  23.445 +                                y_val <<= 16;
  23.446 +                                i_val = i_tot >> 12;
  23.447 +                                if (i_val >  39041) i_val =  39041;
  23.448 +                                if (i_val < -39041) i_val = -39041;
  23.449 +                                q_val = q_tot >> 12;
  23.450 +                                if (q_val >  34249) q_val =  34249;
  23.451 +                                if (q_val < -34249) q_val = -34249;
  23.452 +
  23.453 +                                r = (y_val + 249*i_val + 159*q_val) >> 16;
  23.454 +                                g = (y_val -  70*i_val - 166*q_val) >> 16;
  23.455 +                                b = (y_val - 283*i_val + 436*q_val) >> 16;
  23.456 +
  23.457 +                                y_buf[((c << 1) & 6) + 1] = ntsc_col[buffer->line[pcjr->displine][c] & 7][((c << 1) & 6) + 1] ? 0x6000 : 0;
  23.458 +                                y_buf[((c << 1) & 6) + 1] += (buffer->line[pcjr->displine][c] & 8) ? 0x3000 : 0;
  23.459 +                                i_buf[((c << 1) & 6) + 1] = y_buf[((c << 1) & 6) + 1] * i_filt[((c << 1) & 6) + 1];
  23.460 +                                q_buf[((c << 1) & 6) + 1] = y_buf[((c << 1) & 6) + 1] * q_filt[((c << 1) & 6) + 1];
  23.461 +                                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];
  23.462 +                                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];
  23.463 +                                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];
  23.464 +
  23.465 +                                y_val = y_tot >> 10;
  23.466 +                                if (y_val > 255) y_val = 255;
  23.467 +                                y_val <<= 16;
  23.468 +                                i_val = i_tot >> 12;
  23.469 +                                if (i_val >  39041) i_val =  39041;
  23.470 +                                if (i_val < -39041) i_val = -39041;
  23.471 +                                q_val = q_tot >> 12;
  23.472 +                                if (q_val >  34249) q_val =  34249;
  23.473 +                                if (q_val < -34249) q_val = -34249;
  23.474 +
  23.475 +                                r = (y_val + 249*i_val + 159*q_val) >> 16;
  23.476 +                                g = (y_val -  70*i_val - 166*q_val) >> 16;
  23.477 +                                b = (y_val - 283*i_val + 436*q_val) >> 16;
  23.478 +                                if (r > 511) r = 511;
  23.479 +                                if (g > 511) g = 511;
  23.480 +                                if (b > 511) b = 511;
  23.481 +
  23.482 +                                ((uint32_t *)buffer32->line[pcjr->displine])[c] = makecol32(r / 2, g / 2, b / 2);
  23.483 +                        }
  23.484 +                }
  23.485 +                pcjr->sc = oldsc;
  23.486 +                if (pcjr->vc == pcjr->crtc[7] && !pcjr->sc)
  23.487 +                {
  23.488 +                        pcjr->stat |= 8;
  23.489 +//                        printf("VSYNC on %i %i\n",vc,sc);
  23.490 +                }
  23.491 +                pcjr->displine++;
  23.492 +                if (pcjr->displine >= 360) 
  23.493 +                        pcjr->displine = 0;
  23.494 +        }
  23.495 +        else
  23.496 +        {
  23.497 +                pcjr->vidtime += pcjr->dispontime;
  23.498 +                if (pcjr->dispon) 
  23.499 +                        pcjr->stat |= 1;
  23.500 +                pcjr->linepos = 0;
  23.501 +                if (pcjr->vsynctime)
  23.502 +                {
  23.503 +                        pcjr->vsynctime--;
  23.504 +                        if (!pcjr->vsynctime)
  23.505 +                        {
  23.506 +                                pcjr->stat &= ~8;
  23.507 +//                                printf("VSYNC off %i %i\n",vc,sc);
  23.508 +                        }
  23.509 +                }
  23.510 +                if (pcjr->sc == (pcjr->crtc[11] & 31) || ((pcjr->crtc[8] & 3) == 3 && pcjr->sc == ((pcjr->crtc[11] & 31) >> 1))) 
  23.511 +                { 
  23.512 +                        pcjr->con = 0; 
  23.513 +                        pcjr->coff = 1; 
  23.514 +                }
  23.515 +                if (pcjr->vadj)
  23.516 +                {
  23.517 +                        pcjr->sc++;
  23.518 +                        pcjr->sc &= 31;
  23.519 +                        pcjr->ma = pcjr->maback;
  23.520 +                        pcjr->vadj--;
  23.521 +                        if (!pcjr->vadj)
  23.522 +                        {
  23.523 +                                pcjr->dispon = 1;
  23.524 +                                pcjr->ma = pcjr->maback = (pcjr->crtc[13] | (pcjr->crtc[12] << 8)) & 0x3fff;
  23.525 +                                pcjr->sc = 0;
  23.526 +//                                printf("Display on!\n");
  23.527 +                        }
  23.528 +                }
  23.529 +                else if (pcjr->sc == pcjr->crtc[9] || ((pcjr->crtc[8] & 3) == 3 && pcjr->sc == (pcjr->crtc[9] >> 1)))
  23.530 +                {
  23.531 +                        pcjr->maback = pcjr->ma;
  23.532 +//                        con=0;
  23.533 +//                        coff=0;
  23.534 +                        pcjr->sc = 0;
  23.535 +                        oldvc = pcjr->vc;
  23.536 +                        pcjr->vc++;
  23.537 +                        pcjr->vc &= 127;
  23.538 +//                        pclog("VC %i %i\n", pcjr->vc, pcjr->crtc[7]);
  23.539 +//                        printf("VC %i %i %i %i  %i\n",vc,crtc[4],crtc[6],crtc[7],pcjr->dispon);
  23.540 +                        if (pcjr->vc == pcjr->crtc[6]) 
  23.541 +                                pcjr->dispon = 0;
  23.542 +                        if (oldvc == pcjr->crtc[4])
  23.543 +                        {
  23.544 +//                                printf("Display over at %i\n",pcjr->displine);
  23.545 +                                pcjr->vc = 0;
  23.546 +                                pcjr->vadj = pcjr->crtc[5];
  23.547 +                                if (!pcjr->vadj) 
  23.548 +                                        pcjr->dispon = 1;
  23.549 +                                if (!pcjr->vadj) 
  23.550 +                                        pcjr->ma = pcjr->maback = (pcjr->crtc[13] | (pcjr->crtc[12] << 8)) & 0x3fff;
  23.551 +                                if ((pcjr->crtc[10] & 0x60) == 0x20) pcjr->cursoron = 0;
  23.552 +                                else                                  pcjr->cursoron = pcjr->blink & 16;
  23.553 +//                                printf("CRTC10 %02X %i\n",crtc[10],cursoron);
  23.554 +                        }
  23.555 +                        if (pcjr->vc == pcjr->crtc[7])
  23.556 +                        {
  23.557 +                                pcjr->dispon = 0;
  23.558 +                                pcjr->displine = 0;
  23.559 +                                pcjr->vsynctime = 16;//(crtc[3]>>4)+1;
  23.560 +                                picint(1 << 5);
  23.561 +//                                printf("pcjr->vsynctime %i %02X\n",pcjr->vsynctime,crtc[3]);
  23.562 +//                                pcjr->stat|=8;
  23.563 +                                if (pcjr->crtc[7])
  23.564 +                                {
  23.565 +//                                        printf("Lastline %i Firstline %i  %i   %i %i\n",lastline,firstline,lastline-firstline,crtc[1],xsize);
  23.566 +                                        if (pcjr->array[0] & 1) x = (pcjr->crtc[1] << 3) + 16;
  23.567 +                                        else                    x = (pcjr->crtc[1] << 4) + 16;
  23.568 +                                        pcjr->lastline++;
  23.569 +                                        if (x != xsize || (pcjr->lastline - pcjr->firstline) != ysize)
  23.570 +                                        {
  23.571 +                                                xsize = x;
  23.572 +                                                ysize = pcjr->lastline - pcjr->firstline;
  23.573 +//                                                printf("Resize to %i,%i - R1 %i\n",xsize,ysize,crtc[1]);
  23.574 +                                                if (xsize < 64) xsize = 656;
  23.575 +                                                if (ysize < 32) ysize = 200;
  23.576 +                                                updatewindowsize(xsize, (ysize << 1) + 16);
  23.577 +                                        }
  23.578 +//                                        printf("Blit %i %i\n",firstline,lastline);
  23.579 +//printf("Xsize is %i\n",xsize);
  23.580 +                                startblit();
  23.581 +                                        if (cga_comp) 
  23.582 +                                           video_blit_memtoscreen(0, pcjr->firstline-4, 0, (pcjr->lastline - pcjr->firstline) + 8, xsize, (pcjr->lastline - pcjr->firstline) + 8);
  23.583 +                                        else          
  23.584 +                                           video_blit_memtoscreen_8(0, pcjr->firstline-4, xsize, (pcjr->lastline - pcjr->firstline) + 8);
  23.585 +                                endblit();
  23.586 +                                        frames++;
  23.587 +                                        video_res_x = xsize - 16;
  23.588 +                                        video_res_y = ysize;
  23.589 +                                }
  23.590 +                                pcjr->firstline = 1000;
  23.591 +                                pcjr->lastline = 0;
  23.592 +                                pcjr->blink++;
  23.593 +                        }
  23.594 +                }
  23.595 +                else
  23.596 +                {
  23.597 +                        pcjr->sc++;
  23.598 +                        pcjr->sc &= 31;
  23.599 +                        pcjr->ma = pcjr->maback;
  23.600 +                }
  23.601 +                if ((pcjr->sc == (pcjr->crtc[10] & 31) || ((pcjr->crtc[8] & 3) == 3 && pcjr->sc == ((pcjr->crtc[10] & 31) >> 1)))) 
  23.602 +                        pcjr->con = 1;
  23.603 +        }
  23.604 +}
  23.605 +
  23.606 +static void *pcjr_video_init()
  23.607 +{
  23.608 +        int c;
  23.609 +        int pcjr_tint = -2;
  23.610 +        pcjr_t *pcjr = malloc(sizeof(pcjr_t));
  23.611 +        memset(pcjr, 0, sizeof(pcjr_t));
  23.612 +
  23.613 +        pcjr->memctrl = -1;
  23.614 +        
  23.615 +        for (c = 0; c < 8; c++)
  23.616 +        {
  23.617 +                i_filt[c] = 512.0 * cos((3.14 * (pcjr_tint + c * 4) / 16.0) - 33.0 / 180.0);
  23.618 +                q_filt[c] = 512.0 * sin((3.14 * (pcjr_tint + c * 4) / 16.0) - 33.0 / 180.0);
  23.619 +        }
  23.620 +        timer_add(pcjr_poll, &pcjr->vidtime, TIMER_ALWAYS_ENABLED, pcjr);
  23.621 +        mem_mapping_add(&pcjr->mapping, 0xb8000, 0x08000, pcjr_read, NULL, NULL, pcjr_write, NULL, NULL,  pcjr);
  23.622 +        io_sethandler(0x03d0, 0x0010, pcjr_in, NULL, NULL, pcjr_out, NULL, NULL, pcjr);
  23.623 +        return pcjr;
  23.624 +}
  23.625 +
  23.626 +static void pcjr_video_close(void *p)
  23.627 +{
  23.628 +        pcjr_t *pcjr = (pcjr_t *)p;
  23.629 +
  23.630 +        free(pcjr);
  23.631 +}
  23.632 +
  23.633 +static void pcjr_speed_changed(void *p)
  23.634 +{
  23.635 +        pcjr_t *pcjr = (pcjr_t *)p;
  23.636 +        
  23.637 +        pcjr_recalctimings(pcjr);
  23.638 +}
  23.639 +
  23.640 +device_t pcjr_video_device =
  23.641 +{
  23.642 +        "IBM PCjr (video)",
  23.643 +        0,
  23.644 +        pcjr_video_init,
  23.645 +        pcjr_video_close,
  23.646 +        NULL,
  23.647 +        pcjr_speed_changed,
  23.648 +        NULL,
  23.649 +        NULL
  23.650 +};
    24.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    24.2 +++ b/src/vid_pcjr.h	Sun Jan 12 11:37:09 2014 +0000
    24.3 @@ -0,0 +1,1 @@
    24.4 +extern device_t pcjr_video_device;
    25.1 --- a/src/video.c	Fri Jan 03 20:48:12 2014 +0000
    25.2 +++ b/src/video.c	Sun Jan 12 11:37:09 2014 +0000
    25.3 @@ -26,6 +26,7 @@
    25.4  #include "vid_pc1512.h"
    25.5  #include "vid_pc1640.h"
    25.6  #include "vid_pc200.h"
    25.7 +#include "vid_pcjr.h"
    25.8  #include "vid_s3.h"
    25.9  #include "vid_s3_virge.h"
   25.10  #include "vid_tandy.h"
   25.11 @@ -203,6 +204,10 @@
   25.12  
   25.13          switch (romset)
   25.14          {
   25.15 +                case ROM_IBMPCJR:
   25.16 +                device_add(&pcjr_video_device);
   25.17 +                return;
   25.18 +                
   25.19                  case ROM_TANDY:
   25.20                  device_add(&tandy_device);
   25.21                  return;
    26.1 --- a/src/wd76c10.c	Fri Jan 03 20:48:12 2014 +0000
    26.2 +++ b/src/wd76c10.c	Sun Jan 12 11:37:09 2014 +0000
    26.3 @@ -49,17 +49,17 @@
    26.4                  
    26.5                  switch ((val >> 5) & 7)
    26.6                  {
    26.7 -                        case 1: serial1_init(0x3f8); break;
    26.8 -                        case 2: serial1_init(0x2f8); break;
    26.9 -                        case 3: serial1_init(0x3e8); break;
   26.10 -                        case 4: serial1_init(0x2e8); break;
   26.11 +                        case 1: serial1_init(0x3f8, 4); break;
   26.12 +                        case 2: serial1_init(0x2f8, 4); break;
   26.13 +                        case 3: serial1_init(0x3e8, 4); break;
   26.14 +                        case 4: serial1_init(0x2e8, 4); break;
   26.15                  }
   26.16                  switch ((val >> 1) & 7)
   26.17                  {
   26.18 -                        case 1: serial2_init(0x3f8); break;
   26.19 -                        case 2: serial2_init(0x2f8); break;
   26.20 -                        case 3: serial2_init(0x3e8); break;
   26.21 -                        case 4: serial2_init(0x2e8); break;
   26.22 +                        case 1: serial2_init(0x3f8, 3); break;
   26.23 +                        case 2: serial2_init(0x2f8, 3); break;
   26.24 +                        case 3: serial2_init(0x3e8, 3); break;
   26.25 +                        case 4: serial2_init(0x2e8, 3); break;
   26.26                  }
   26.27                  break;
   26.28  
    27.1 --- a/src/x86.h	Fri Jan 03 20:48:12 2014 +0000
    27.2 +++ b/src/x86.h	Sun Jan 12 11:37:09 2014 +0000
    27.3 @@ -3,6 +3,8 @@
    27.4  extern uint32_t rmdat32;
    27.5  int oldcpl;
    27.6  
    27.7 +extern int nmi_enable;
    27.8 +
    27.9  int tempc;
   27.10  int cycles,output;
   27.11  int ssegs;