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
