PCem
view src/vid_pc200.c @ 164:9a88154e8608
Implemented NMI mask register for XT machines.
Fixed PC200 NMI stuff.
| author | TomW |
|---|---|
| date | Sat Sep 27 18:39:06 2014 +0100 |
| parents | b53e148867e5 |
| children |
line source
1 /*PC200 video emulation.
2 CGA with some NMI stuff. But we don't need that as it's only used for TV and
3 LCD displays, and we're emulating a CRT*/
4 #include <stdlib.h>
5 #include "ibm.h"
6 #include "device.h"
7 #include "io.h"
8 #include "mem.h"
9 #include "timer.h"
10 #include "video.h"
11 #include "vid_cga.h"
12 #include "vid_pc200.h"
14 typedef struct pc200_t
15 {
16 mem_mapping_t mapping;
18 cga_t cga;
20 uint8_t reg_3dd, reg_3de, reg_3df;
21 } pc200_t;
23 static uint8_t crtcmask[32] =
24 {
25 0xff, 0xff, 0xff, 0xff, 0x7f, 0x1f, 0x7f, 0x7f, 0xf3, 0x1f, 0x7f, 0x1f, 0x3f, 0xff, 0x3f, 0xff,
26 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
27 };
29 void pc200_out(uint16_t addr, uint8_t val, void *p)
30 {
31 pc200_t *pc200 = (pc200_t *)p;
32 cga_t *cga = &pc200->cga;
33 uint8_t old;
35 switch (addr)
36 {
37 case 0x3d5:
38 if (!(pc200->reg_3de & 0x40) && cga->crtcreg <= 11)
39 {
40 if (pc200->reg_3de & 0x80)
41 nmi = 1;
43 pc200->reg_3dd = 0x20 | (cga->crtcreg & 0x1f);
44 pc200->reg_3df = val;
45 return;
46 }
47 old = cga->crtc[cga->crtcreg];
48 cga->crtc[cga->crtcreg] = val & crtcmask[cga->crtcreg];
49 if (old != val)
50 {
51 if (cga->crtcreg < 0xe || cga->crtcreg > 0x10)
52 {
53 fullchange = changeframecount;
54 cga_recalctimings(cga);
55 }
56 }
57 return;
59 case 0x3d8:
60 old = cga->cgamode;
61 cga->cgamode = val;
62 if ((cga->cgamode ^ old) & 3)
63 cga_recalctimings(cga);
64 pc200->reg_3dd |= 0x80;
65 if (pc200->reg_3de & 0x80)
66 nmi = 1;
67 return;
69 case 0x3de:
70 pc200->reg_3de = val;
71 pc200->reg_3dd = 0x1f;
72 if (val & 0x80)
73 pc200->reg_3dd |= 0x40;
74 return;
75 }
76 cga_out(addr, val, cga);
77 }
79 uint8_t pc200_in(uint16_t addr, void *p)
80 {
81 pc200_t *pc200 = (pc200_t *)p;
82 cga_t *cga = &pc200->cga;
83 uint8_t temp;
85 switch (addr)
86 {
87 case 0x3D8:
88 return cga->cgamode;
90 case 0x3DD:
91 temp = pc200->reg_3dd;
92 pc200->reg_3dd &= 0x1f;
93 nmi = 0;
94 return temp;
96 case 0x3DE:
97 return (pc200->reg_3de & 0xc7) | 0x10; /*External CGA*/
99 case 0x3DF:
100 return pc200->reg_3df;
101 }
102 return cga_in(addr, cga);
103 }
105 void *pc200_init()
106 {
107 pc200_t *pc200 = malloc(sizeof(pc200_t));
108 cga_t *cga = &pc200->cga;
109 memset(pc200, 0, sizeof(pc200_t));
111 pc200->cga.vram = malloc(0x4000);
112 cga_init(&pc200->cga);
114 timer_add(cga_poll, &cga->vidtime, TIMER_ALWAYS_ENABLED, cga);
115 mem_mapping_add(&pc200->mapping, 0xb8000, 0x08000, cga_read, NULL, NULL, cga_write, NULL, NULL, NULL, 0, cga);
116 io_sethandler(0x03d0, 0x0010, pc200_in, NULL, NULL, pc200_out, NULL, NULL, pc200);
117 return pc200;
118 }
120 void pc200_close(void *p)
121 {
122 pc200_t *pc200 = (pc200_t *)p;
124 free(pc200->cga.vram);
125 free(pc200);
126 }
128 void pc200_speed_changed(void *p)
129 {
130 pc200_t *pc200 = (pc200_t *)p;
132 cga_recalctimings(&pc200->cga);
133 }
135 device_t pc200_device =
136 {
137 "Amstrad PC200 (video)",
138 0,
139 pc200_init,
140 pc200_close,
141 NULL,
142 pc200_speed_changed,
143 NULL,
144 NULL
145 };
