1 /*Oak OTI067 emulation*/
2 #include <stdlib.h>
3 #include "ibm.h"
4 #include "device.h"
5 #include "io.h"
6 #include "mem.h"
7 #include "rom.h"
8 #include "video.h"
9 #include "vid_oti067.h"
10 #include "vid_svga.h"
11 #include "acer386sx.h"
12
13 typedef struct oti067_t
14 {
15 svga_t svga;
16
17 rom_t bios_rom;
18
19 int index;
20 uint8_t regs[32];
21
22 uint8_t pos;
23 uint8_t dipswitch_val;
24
25 uint32_t vram_size;
26 uint32_t vram_mask;
27 } oti067_t;
28
oti067_out(uint16_t addr,uint8_t val,void * p)29 void oti067_out(uint16_t addr, uint8_t val, void *p)
30 {
31 oti067_t *oti067 = (oti067_t *)p;
32 svga_t *svga = &oti067->svga;
33 uint8_t old;
34
35 // pclog("oti067_out : %04X %02X %02X %i\n", addr, val, ram[0x489], ins);
36
37 if ((((addr&0xFFF0) == 0x3D0 || (addr&0xFFF0) == 0x3B0) && addr < 0x3de) && !(svga->miscout & 1)) addr ^= 0x60;
38
39 switch (addr)
40 {
41 case 0x3D4:
42 svga->crtcreg = val & 0x3f;
43 return;
44 case 0x3D5:
45 if (svga->crtcreg & 0x20)
46 return;
47 if ((svga->crtcreg < 7) && (svga->crtc[0x11] & 0x80))
48 return;
49 if ((svga->crtcreg == 7) && (svga->crtc[0x11] & 0x80))
50 val = (svga->crtc[7] & ~0x10) | (val & 0x10);
51 old = svga->crtc[svga->crtcreg];
52 svga->crtc[svga->crtcreg] = val;
53 if (old != val)
54 {
55 if (svga->crtcreg < 0xE || svga->crtcreg > 0x10)
56 {
57 svga->fullchange = changeframecount;
58 svga_recalctimings(svga);
59 }
60 }
61 break;
62
63 case 0x3DE:
64 oti067->index = val & 0x1f;
65 return;
66 case 0x3DF:
67 oti067->regs[oti067->index] = val;
68 switch (oti067->index)
69 {
70 case 0xD:
71 svga->vram_display_mask = (val & 0xc) ? oti067->vram_mask : 0x3ffff;
72 if ((val & 0x80) && oti067->vram_size == 256)
73 mem_mapping_disable(&svga->mapping);
74 else
75 mem_mapping_enable(&svga->mapping);
76 if (!(val & 0x80))
77 svga->vram_display_mask = 0x3ffff;
78 break;
79 case 0x11:
80 svga->read_bank = (val & 0xf) * 65536;
81 svga->write_bank = (val >> 4) * 65536;
82 break;
83 }
84 return;
85 }
86 svga_out(addr, val, svga);
87 }
88
oti067_in(uint16_t addr,void * p)89 uint8_t oti067_in(uint16_t addr, void *p)
90 {
91 oti067_t *oti067 = (oti067_t *)p;
92 svga_t *svga = &oti067->svga;
93 uint8_t temp;
94
95 // if (addr != 0x3da && addr != 0x3ba) pclog("oti067_in : %04X ", addr);
96
97 if ((((addr&0xFFF0) == 0x3D0 || (addr&0xFFF0) == 0x3B0) && addr < 0x3de) && !(svga->miscout & 1)) addr ^= 0x60;
98
99 switch (addr)
100 {
101 case 0x3D4:
102 temp = svga->crtcreg;
103 break;
104 case 0x3D5:
105 if (svga->crtcreg & 0x20)
106 temp = 0xff;
107 else
108 temp = svga->crtc[svga->crtcreg];
109 break;
110
111 case 0x3DE:
112 temp = oti067->index | (2 << 5);
113 break;
114 case 0x3DF:
115 if (oti067->index==0x10) temp = oti067->dipswitch_val;
116 else temp = oti067->regs[oti067->index];
117 break;
118
119 default:
120 temp = svga_in(addr, svga);
121 break;
122 }
123 // if (addr != 0x3da && addr != 0x3ba) pclog("%02X %04X:%04X\n", temp, CS,pc);
124 return temp;
125 }
126
oti067_pos_out(uint16_t addr,uint8_t val,void * p)127 void oti067_pos_out(uint16_t addr, uint8_t val, void *p)
128 {
129 oti067_t *oti067 = (oti067_t *)p;
130
131 if ((val & 8) != (oti067->pos & 8))
132 {
133 if (val & 8)
134 io_sethandler(0x03c0, 0x0020, oti067_in, NULL, NULL, oti067_out, NULL, NULL, oti067);
135 else
136 io_removehandler(0x03c0, 0x0020, oti067_in, NULL, NULL, oti067_out, NULL, NULL, oti067);
137 }
138
139 oti067->pos = val;
140 }
141
oti067_pos_in(uint16_t addr,void * p)142 uint8_t oti067_pos_in(uint16_t addr, void *p)
143 {
144 oti067_t *oti067 = (oti067_t *)p;
145
146 return oti067->pos;
147 }
148
oti067_recalctimings(svga_t * svga)149 void oti067_recalctimings(svga_t *svga)
150 {
151 oti067_t *oti067 = (oti067_t *)svga->p;
152
153 if (oti067->regs[0x14] & 0x08) svga->ma_latch |= 0x10000;
154 if (oti067->regs[0x0d] & 0x0c) svga->rowoffset <<= 1;
155 svga->interlace = oti067->regs[0x14] & 0x80;
156 }
157
oti067_common_init(char * bios_fn,int vram_size)158 void *oti067_common_init(char *bios_fn, int vram_size)
159 {
160 oti067_t *oti067 = malloc(sizeof(oti067_t));
161 memset(oti067, 0, sizeof(oti067_t));
162
163 rom_init(&oti067->bios_rom, bios_fn, 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL);
164
165 oti067->vram_size = vram_size;
166 oti067->vram_mask = (vram_size << 10) - 1;
167
168 svga_init(&oti067->svga, oti067, vram_size << 10,
169 oti067_recalctimings,
170 oti067_in, oti067_out,
171 NULL,
172 NULL);
173
174 io_sethandler(0x03c0, 0x0020, oti067_in, NULL, NULL, oti067_out, NULL, NULL, oti067);
175 io_sethandler(0x46e8, 0x0001, oti067_pos_in, NULL, NULL, oti067_pos_out, NULL, NULL, oti067);
176
177 oti067->svga.miscout = 1;
178
179 oti067->dipswitch_val = 0x18;
180 return oti067;
181 }
182
oti067_enable_disable(void * p,int enable)183 void oti067_enable_disable(void *p, int enable)
184 {
185 oti067_t *oti067 = (oti067_t *)p;
186
187 mem_mapping_disable(&oti067->bios_rom.mapping);
188 io_removehandler(0x03c0, 0x0020, oti067_in, NULL, NULL, oti067_out, NULL, NULL, oti067);
189 io_removehandler(0x46e8, 0x0001, oti067_pos_in, NULL, NULL, oti067_pos_out, NULL, NULL, oti067);
190 mem_mapping_disable(&oti067->svga.mapping);
191 if (enable)
192 {
193 mem_mapping_enable(&oti067->bios_rom.mapping);
194 io_sethandler(0x03c0, 0x0020, oti067_in, NULL, NULL, oti067_out, NULL, NULL, oti067);
195 io_sethandler(0x46e8, 0x0001, oti067_pos_in, NULL, NULL, oti067_pos_out, NULL, NULL, oti067);
196 mem_mapping_enable(&oti067->svga.mapping);
197 }
198 }
199
oti067_init()200 void *oti067_init()
201 {
202 int vram_size = device_get_config_int("memory");
203 return oti067_common_init("oti067/bios.bin", vram_size);
204 }
205
oti067_acer386_init()206 void *oti067_acer386_init()
207 {
208 oti067_t *oti067 = oti067_common_init("acer386/oti067.bin", 512);
209
210 acer386sx_set_oti067(oti067);
211
212 return oti067;
213 }
214
oti067_ama932j_init()215 void *oti067_ama932j_init()
216 {
217 oti067_t *oti067 = oti067_common_init("ama932j/oti067.bin", 512);
218
219 oti067->dipswitch_val |= 0x20;
220 return oti067;
221 }
222
oti067_available()223 static int oti067_available()
224 {
225 return rom_present("oti067/bios.bin");
226 }
227
oti067_close(void * p)228 void oti067_close(void *p)
229 {
230 oti067_t *oti067 = (oti067_t *)p;
231
232 svga_close(&oti067->svga);
233
234 free(oti067);
235 }
236
oti067_speed_changed(void * p)237 void oti067_speed_changed(void *p)
238 {
239 oti067_t *oti067 = (oti067_t *)p;
240
241 svga_recalctimings(&oti067->svga);
242 }
243
oti067_force_redraw(void * p)244 void oti067_force_redraw(void *p)
245 {
246 oti067_t *oti067 = (oti067_t *)p;
247
248 oti067->svga.fullchange = changeframecount;
249 }
250
oti067_add_status_info(char * s,int max_len,void * p)251 void oti067_add_status_info(char *s, int max_len, void *p)
252 {
253 oti067_t *oti067 = (oti067_t *)p;
254
255 svga_add_status_info(s, max_len, &oti067->svga);
256 }
257
258 static device_config_t oti067_config[] =
259 {
260 {
261 .name = "memory",
262 .description = "Memory size",
263 .type = CONFIG_SELECTION,
264 .selection =
265 {
266 {
267 .description = "256 kB",
268 .value = 256
269 },
270 {
271 .description = "512 kB",
272 .value = 512
273 },
274 {
275 .description = ""
276 }
277 },
278 .default_int = 512
279 },
280 {
281 .type = -1
282 }
283 };
284
285 device_t oti067_device =
286 {
287 "Oak OTI-067",
288 0,
289 oti067_init,
290 oti067_close,
291 oti067_available,
292 oti067_speed_changed,
293 oti067_force_redraw,
294 oti067_add_status_info,
295 oti067_config
296 };
297 device_t oti067_acer386_device =
298 {
299 "Oak OTI-067 (Acermate 386SX/25N)",
300 0,
301 oti067_acer386_init,
302 oti067_close,
303 oti067_available,
304 oti067_speed_changed,
305 oti067_force_redraw,
306 oti067_add_status_info
307 };
308 device_t oti067_ama932j_device =
309 {
310 "Oak OTI-067 (AMA-932J)",
311 0,
312 oti067_ama932j_init,
313 oti067_close,
314 oti067_available,
315 oti067_speed_changed,
316 oti067_force_redraw,
317 oti067_add_status_info
318 };
319