1 /*This is the chipset used in the Award 286 clone model*/
2 #include "ibm.h"
3 #include "cpu.h"
4 #include "io.h"
5 #include "mem.h"
6 #include "scat.h"
7 #include "x86.h"
8 #include "nmi.h"
9
10 static uint8_t scat_regs[256];
11 static int scat_index;
12 static uint8_t scat_port_92 = 0;
13 static uint8_t scat_ems_reg_2xA = 0;
14 static mem_mapping_t scat_low_mapping[32];
15 static mem_mapping_t scat_ems_mapping[32];
16 static mem_mapping_t scat_high_mapping[16];
17 static scat_t scat_stat[32];
18 static uint32_t scat_xms_bound;
19 static mem_mapping_t scat_remap_mapping[6];
20 static mem_mapping_t scat_4000_EFFF_mapping[44];
21 static mem_mapping_t scat_low_ROMCS_mapping[8];
22
23 static int scat_max_map[32] = { 0, 1, 1, 1, 2, 3, 4, 8,
24 4, 8, 12, 16, 20, 24, 28, 32,
25 0, 5, 9, 13, 6, 10, 0, 0,
26 0, 0, 0, 0, 0, 0, 0, 0 };
27 static int scatsx_max_map[32] = { 0, 1, 2, 1, 3, 4, 6, 10,
28 5, 9, 13, 4, 8, 12, 16, 14,
29 18, 22, 26, 20, 24, 28, 32, 18,
30 20, 32, 0, 0, 0, 0, 0, 0 };
31
32 static int external_is_RAS = 0;
33
34 static int scatsx_external_is_RAS[33] = { 0, 0, 0, 0, 0, 0, 0, 0,
35 0, 0, 0, 1, 0, 0, 1, 1,
36 0, 0, 0, 0, 0, 0, 1, 1,
37 1, 1, 1, 1, 1, 1, 1, 1,
38 0 };
39
40 uint8_t scat_read(uint16_t port, void *priv);
41 void scat_write(uint16_t port, uint8_t val, void *priv);
42
scat_romcs_state_update(uint8_t val)43 void scat_romcs_state_update(uint8_t val)
44 {
45 int i;
46 for(i = 0; i < 4; i++)
47 {
48 if (val & 1)
49 {
50 mem_mapping_enable(&scat_low_ROMCS_mapping[i << 1]);
51 mem_mapping_enable(&scat_low_ROMCS_mapping[(i << 1) + 1]);
52 }
53 else
54 {
55 mem_mapping_disable(&scat_low_ROMCS_mapping[i << 1]);
56 mem_mapping_disable(&scat_low_ROMCS_mapping[(i << 1) + 1]);
57 }
58 val >>= 1;
59 }
60
61 for(i = 0; i < 4; i++)
62 {
63 if (val & 1)
64 {
65 mem_mapping_enable(&bios_mapping[i << 1]);
66 mem_mapping_enable(&bios_mapping[(i << 1) + 1]);
67 }
68 else
69 {
70 mem_mapping_disable(&bios_mapping[i << 1]);
71 mem_mapping_disable(&bios_mapping[(i << 1) + 1]);
72 }
73 val >>= 1;
74 }
75 }
76
scat_shadow_state_update()77 void scat_shadow_state_update()
78 {
79 int i, val;
80
81 for (i = 0; i < 24; i++)
82 {
83 val = ((scat_regs[SCAT_SHADOW_RAM_ENABLE_1 + (i >> 3)] >> (i & 7)) & 1) ? MEM_READ_INTERNAL | MEM_WRITE_INTERNAL : MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL;
84 mem_set_mem_state((i + 40) << 14, 0x4000, val);
85 }
86
87 flushmmucache();
88 }
89
scat_set_xms_bound(uint8_t val)90 void scat_set_xms_bound(uint8_t val)
91 {
92 uint32_t max_xms_size = ((scat_regs[SCAT_VERSION] & 0xF0) != 0 && ((val & 0x10) != 0)) || (scat_regs[SCAT_VERSION] >= 4) ? 0xFE0000 : 0xFC0000;
93
94 switch (val & 0x0F)
95 {
96 case 1:
97 scat_xms_bound = 0x100000;
98 break;
99 case 2:
100 scat_xms_bound = 0x140000;
101 break;
102 case 3:
103 scat_xms_bound = 0x180000;
104 break;
105 case 4:
106 scat_xms_bound = 0x200000;
107 break;
108 case 5:
109 scat_xms_bound = 0x300000;
110 break;
111 case 6:
112 scat_xms_bound = 0x400000;
113 break;
114 case 7:
115 scat_xms_bound = (scat_regs[SCAT_VERSION] & 0xF0) == 0 ? 0x600000 : 0x500000;
116 break;
117 case 8:
118 scat_xms_bound = (scat_regs[SCAT_VERSION] & 0xF0) == 0 ? 0x800000 : 0x700000;
119 break;
120 case 9:
121 scat_xms_bound = (scat_regs[SCAT_VERSION] & 0xF0) == 0 ? 0xA00000 : 0x800000;
122 break;
123 case 10:
124 scat_xms_bound = (scat_regs[SCAT_VERSION] & 0xF0) == 0 ? 0xC00000 : 0x900000;
125 break;
126 case 11:
127 scat_xms_bound = (scat_regs[SCAT_VERSION] & 0xF0) == 0 ? 0xE00000 : 0xA00000;
128 break;
129 case 12:
130 scat_xms_bound = (scat_regs[SCAT_VERSION] & 0xF0) == 0 ? max_xms_size : 0xB00000;
131 break;
132 case 13:
133 scat_xms_bound = (scat_regs[SCAT_VERSION] & 0xF0) == 0 ? max_xms_size : 0xC00000;
134 break;
135 case 14:
136 scat_xms_bound = (scat_regs[SCAT_VERSION] & 0xF0) == 0 ? max_xms_size : 0xD00000;
137 break;
138 case 15:
139 scat_xms_bound = (scat_regs[SCAT_VERSION] & 0xF0) == 0 ? max_xms_size : 0xF00000;
140 break;
141 default:
142 scat_xms_bound = max_xms_size;
143 break;
144 }
145
146 if ((((scat_regs[SCAT_VERSION] & 0xF0) == 0) && (val & 0x40) == 0 && (scat_regs[SCAT_DRAM_CONFIGURATION] & 0x0F) == 3) || (((scat_regs[SCAT_VERSION] & 0xF0) != 0) && (scat_regs[SCAT_DRAM_CONFIGURATION] & 0x1F) == 3))
147 {
148 if((val & 0x0F) == 0 || scat_xms_bound > 0x160000)
149 scat_xms_bound = 0x160000;
150 // pclog("Set XMS bound(%02X) = %06X(%dKbytes for EMS access)\n", val, scat_xms_bound, (0x160000 - scat_xms_bound) >> 10);
151 if (scat_xms_bound > 0x100000)
152 mem_set_mem_state(0x100000, scat_xms_bound - 0x100000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
153 if (scat_xms_bound < 0x160000)
154 mem_set_mem_state(scat_xms_bound, 0x160000 - scat_xms_bound, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL);
155 }
156 else
157 {
158 if (scat_xms_bound > max_xms_size)
159 scat_xms_bound = max_xms_size;
160 // pclog("Set XMS bound(%02X) = %06X(%dKbytes for EMS access)\n", val, scat_xms_bound, ((mem_size << 10) - scat_xms_bound) >> 10);
161 if (scat_xms_bound > 0x100000)
162 mem_set_mem_state(0x100000, scat_xms_bound - 0x100000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
163 if (scat_xms_bound < (mem_size << 10))
164 mem_set_mem_state(scat_xms_bound, (mem_size << 10) - scat_xms_bound, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL);
165 }
166
167 mem_mapping_set_addr(&scat_low_mapping[31], 0xF80000, ((scat_regs[SCAT_VERSION] & 0xF0) != 0 && ((val & 0x10) != 0)) || (scat_regs[SCAT_VERSION] >= 4) ? 0x60000 : 0x40000);
168 if(scat_regs[SCAT_VERSION] & 0xF0)
169 {
170 int i;
171 for(i=0;i<8;i++)
172 {
173 if(val & 0x10)
174 mem_mapping_disable(&scat_high_mapping[i]);
175 else
176 mem_mapping_enable(&scat_high_mapping[i]);
177 }
178 }
179 }
180
get_scat_addr(uint32_t addr,scat_t * p)181 uint32_t get_scat_addr(uint32_t addr, scat_t *p)
182 {
183 int nbank;
184
185 if (p && (scat_regs[SCAT_EMS_CONTROL] & 0x80) && (p->regs_2x9 & 0x80))
186 addr = (addr & 0x3fff) | (((p->regs_2x9 & 3) << 8) | p->regs_2x8) << 14;
187
188 if ((scat_regs[SCAT_VERSION] & 0xF0) == 0)
189 {
190 switch((scat_regs[SCAT_EXTENDED_BOUNDARY] & ((scat_regs[SCAT_VERSION] & 0x0F) > 3 ? 0x40 : 0)) | (scat_regs[SCAT_DRAM_CONFIGURATION] & 0x0F))
191 {
192 case 0x41:
193 nbank = addr >> 19;
194 if(nbank < 4)
195 nbank = 1;
196 else if(nbank == 4)
197 nbank = 0;
198 else
199 nbank -= 3;
200 break;
201 case 0x42:
202 nbank = addr >> 19;
203 if(nbank < 8)
204 nbank = 1 + (nbank >> 2);
205 else if(nbank == 8)
206 nbank = 0;
207 else
208 nbank -= 6;
209 break;
210 case 0x43:
211 nbank = addr >> 19;
212 if(nbank < 12)
213 nbank = 1 + (nbank >> 2);
214 else if(nbank == 12)
215 nbank = 0;
216 else
217 nbank -= 9;
218 break;
219 case 0x44:
220 nbank = addr >> 19;
221 if(nbank < 4)
222 nbank = 2;
223 else if(nbank < 6)
224 nbank -= 4;
225 else
226 nbank -= 3;
227 break;
228 case 0x45:
229 nbank = addr >> 19;
230 if(nbank < 8)
231 nbank = 2 + (nbank >> 2);
232 else if(nbank < 10)
233 nbank -= 8;
234 else
235 nbank -= 6;
236 break;
237 default:
238 nbank = addr >> (((scat_regs[SCAT_DRAM_CONFIGURATION] & 0x0F) < 8 && (scat_regs[SCAT_EXTENDED_BOUNDARY] & 0x40) == 0) ? 19 : 21);
239 break;
240 }
241 nbank &= (scat_regs[SCAT_EXTENDED_BOUNDARY] & 0x80) ? 7 : 3;
242 if ((scat_regs[SCAT_EXTENDED_BOUNDARY] & 0x40) == 0 && (scat_regs[SCAT_DRAM_CONFIGURATION] & 0x0F) == 3 && nbank == 2 && (addr & 0x7FFFF) < 0x60000 && mem_size > 640)
243 {
244 nbank = 1;
245 addr ^= 0x70000;
246 }
247
248 if(external_is_RAS && (scat_regs[SCAT_EXTENDED_BOUNDARY] & 0x80) == 0)
249 {
250 if(nbank == 3)
251 nbank = 7;
252 else
253 return 0xFFFFFFFF;
254 }
255 else if(!external_is_RAS && scat_regs[SCAT_EXTENDED_BOUNDARY] & 0x80)
256 {
257 switch(nbank)
258 {
259 case 7:
260 nbank = 3;
261 break;
262 // Note - In the following cases, the chipset accesses multiple memory banks at the same time, so it's impossible to predict which memory bank is actually accessed.
263 case 5:
264 case 1:
265 nbank = 1;
266 break;
267 case 3:
268 nbank = 2;
269 break;
270 default:
271 nbank = 0;
272 break;
273 }
274 }
275
276 if((scat_regs[SCAT_VERSION] & 0x0F) > 3 && (mem_size > 2048) && (mem_size & 1536))
277 {
278 if((mem_size & 1536) == 512)
279 {
280 if(nbank == 0)
281 addr &= 0x7FFFF;
282 else
283 addr = 0x80000 + ((addr & 0x1FFFFF) | ((nbank - 1) << 21));
284 }
285 else
286 {
287 if(nbank < 2)
288 addr = (addr & 0x7FFFF) | (nbank << 19);
289 else
290 addr = 0x100000 + ((addr & 0x1FFFFF) | ((nbank - 2) << 21));
291 }
292 }
293 else
294 {
295 int nbanks_2048k, nbanks_512k;
296 if (mem_size <= ((scat_regs[SCAT_VERSION] & 0x0F) > 3 ? 2048 : 4096) && (((scat_regs[SCAT_DRAM_CONFIGURATION] & 0x0F) < 8) || external_is_RAS))
297 {
298 nbanks_2048k = 0;
299 nbanks_512k = mem_size >> 9;
300 }
301 else
302 {
303 nbanks_2048k = mem_size >> 11;
304 nbanks_512k = (mem_size & 1536) >> 9;
305 }
306 if(nbank < nbanks_2048k || (nbanks_2048k > 0 && nbank >= nbanks_2048k + nbanks_512k + ((mem_size & 511) >> 7)))
307 {
308 addr &= 0x1FFFFF;
309 addr |= (nbank << 21);
310 }
311 else if(nbank < nbanks_2048k + nbanks_512k || nbank >= nbanks_2048k + nbanks_512k + ((mem_size & 511) >> 7))
312 {
313 addr &= 0x7FFFF;
314 addr |= (nbanks_2048k << 21) | ((nbank - nbanks_2048k) << 19);
315 }
316 else
317 {
318 addr &= 0x1FFFF;
319 addr |= (nbanks_2048k << 21) | (nbanks_512k << 19) | ((nbank - nbanks_2048k - nbanks_512k) << 17);
320 }
321 }
322 }
323 else
324 {
325 uint32_t addr2;
326 switch(scat_regs[SCAT_DRAM_CONFIGURATION] & 0x1F)
327 {
328 case 2:
329 case 4:
330 nbank = addr >> 19;
331 if((nbank & (scat_regs[SCAT_EXTENDED_BOUNDARY] & 0x80 ? 7 : 3)) < 2)
332 {
333 nbank = (addr >> 10) & 1;
334 addr2 = addr >> 11;
335 }
336 else
337 addr2 = addr >> 10;
338 break;
339 case 3:
340 nbank = addr >> 19;
341 if((nbank & (scat_regs[SCAT_EXTENDED_BOUNDARY] & 0x80 ? 7 : 3)) < 2)
342 {
343 nbank = (addr >> 10) & 1;
344 addr2 = addr >> 11;
345 }
346 else if((nbank & (scat_regs[SCAT_EXTENDED_BOUNDARY] & 0x80 ? 7 : 3)) == 2 && (addr & 0x7FFFF) < 0x60000)
347 {
348 addr ^= 0x1F0000;
349 nbank = (addr >> 10) & 1;
350 addr2 = addr >> 11;
351 }
352 else
353 addr2 = addr >> 10;
354 break;
355 case 5:
356 nbank = addr >> 19;
357 if((nbank & (scat_regs[SCAT_EXTENDED_BOUNDARY] & 0x80 ? 7 : 3)) < 4)
358 {
359 nbank = (addr >> 10) & 3;
360 addr2 = addr >> 12;
361 }
362 else
363 addr2 = addr >> 10;
364 break;
365 case 6:
366 nbank = addr >> 19;
367 if(nbank < 2)
368 {
369 nbank = (addr >> 10) & 1;
370 addr2 = addr >> 11;
371 }
372 else
373 {
374 nbank = 2 + ((addr - 0x100000) >> 21);
375 addr2 = (addr - 0x100000) >> 11;
376 }
377 break;
378 case 7:
379 case 0x0F:
380 nbank = addr >> 19;
381 if(nbank < 2)
382 {
383 nbank = (addr >> 10) & 1;
384 addr2 = addr >> 11;
385 }
386 else if(nbank < 10)
387 {
388 nbank = 2 + (((addr - 0x100000) >> 11) & 1);
389 addr2 = (addr - 0x100000) >> 12;
390 }
391 else
392 {
393 nbank = 4 + ((addr - 0x500000) >> 21);
394 addr2 = (addr - 0x500000) >> 11;
395 }
396 break;
397 case 8:
398 nbank = addr >> 19;
399 if(nbank < 4)
400 {
401 nbank = 1;
402 addr2 = addr >> 11;
403 }
404 else if(nbank == 4)
405 {
406 nbank = 0;
407 addr2 = addr >> 10;
408 }
409 else
410 {
411 nbank -= 3;
412 addr2 = addr >> 10;
413 }
414 break;
415 case 9:
416 nbank = addr >> 19;
417 if(nbank < 8)
418 {
419 nbank = 1 + ((addr >> 11) & 1);
420 addr2 = addr >> 12;
421 }
422 else if(nbank == 8)
423 {
424 nbank = 0;
425 addr2 = addr >> 10;
426 }
427 else
428 {
429 nbank -= 6;
430 addr2 = addr >> 10;
431 }
432 break;
433 case 0x0A:
434 nbank = addr >> 19;
435 if(nbank < 8)
436 {
437 nbank = 1 + ((addr >> 11) & 1);
438 addr2 = addr >> 12;
439 }
440 else if(nbank < 12)
441 {
442 nbank = 3;
443 addr2 = addr >> 11;
444 }
445 else if(nbank == 12)
446 {
447 nbank = 0;
448 addr2 = addr >> 10;
449 }
450 else
451 {
452 nbank -= 9;
453 addr2 = addr >> 10;
454 }
455 break;
456 case 0x0B:
457 nbank = addr >> 21;
458 addr2 = addr >> 11;
459 break;
460 case 0x0C:
461 case 0x0D:
462 nbank = addr >> 21;
463 if((nbank & (scat_regs[SCAT_EXTENDED_BOUNDARY] & 0x80 ? 7 : 3)) < 2)
464 {
465 nbank = (addr >> 11) & 1;
466 addr2 = addr >> 12;
467 }
468 else
469 addr2 = addr >> 11;
470 break;
471 case 0x0E:
472 case 0x13:
473 nbank = addr >> 21;
474 if((nbank & (scat_regs[SCAT_EXTENDED_BOUNDARY] & 0x80 ? 7 : 3)) < 4)
475 {
476 nbank = (addr >> 11) & 3;
477 addr2 = addr >> 13;
478 }
479 else
480 addr2 = addr >> 11;
481 break;
482 case 0x10:
483 case 0x11:
484 nbank = addr >> 19;
485 if(nbank < 2)
486 {
487 nbank = (addr >> 10) & 1;
488 addr2 = addr >> 11;
489 }
490 else if(nbank < 10)
491 {
492 nbank = 2 + (((addr - 0x100000) >> 11) & 1);
493 addr2 = (addr - 0x100000) >> 12;
494 }
495 else if(nbank < 18)
496 {
497 nbank = 4 + (((addr - 0x500000) >> 11) & 1);
498 addr2 = (addr - 0x500000) >> 12;
499 }
500 else
501 {
502 nbank = 6 + ((addr - 0x900000) >> 21);
503 addr2 = (addr - 0x900000) >> 11;
504 }
505 break;
506 case 0x12:
507 nbank = addr >> 19;
508 if(nbank < 2)
509 {
510 nbank = (addr >> 10) & 1;
511 addr2 = addr >> 11;
512 }
513 else if(nbank < 10)
514 {
515 nbank = 2 + (((addr - 0x100000) >> 11) & 1);
516 addr2 = (addr - 0x100000) >> 12;
517 }
518 else
519 {
520 nbank = 4 + (((addr - 0x500000) >> 11) & 3);
521 addr2 = (addr - 0x500000) >> 13;
522 }
523 break;
524 case 0x14:
525 case 0x15:
526 nbank = addr >> 21;
527 if((nbank & 7) < 4)
528 {
529 nbank = (addr >> 11) & 3;
530 addr2 = addr >> 13;
531 }
532 else if((nbank & 7) < 6)
533 {
534 nbank = 4 + (((addr - 0x800000) >> 11) & 1);
535 addr2 = (addr - 0x800000) >> 12;
536 }
537 else
538 {
539 nbank = 6 + (((addr - 0xC00000) >> 11) & 3);
540 addr2 = (addr - 0xC00000) >> 13;
541 }
542 break;
543 case 0x16:
544 nbank = ((addr >> 21) & 4) | ((addr >> 11) & 3);
545 addr2 = addr >> 13;
546 break;
547 case 0x17:
548 if(external_is_RAS && (addr & 0x800) == 0)
549 return 0xFFFFFFFF;
550 nbank = addr >> 19;
551 if(nbank < 2)
552 {
553 nbank = (addr >> 10) & 1;
554 addr2 = addr >> 11;
555 }
556 else
557 {
558 nbank = 2 + ((addr - 0x100000) >> 23);
559 addr2 = (addr - 0x100000) >> 12;
560 }
561 break;
562 case 0x18:
563 if(external_is_RAS && (addr & 0x800) == 0)
564 return 0xFFFFFFFF;
565 nbank = addr >> 21;
566 if(nbank < 4)
567 {
568 nbank = 1;
569 addr2 = addr >> 12;
570 }
571 else if(nbank == 4)
572 {
573 nbank = 0;
574 addr2 = addr >> 11;
575 }
576 else
577 {
578 nbank -= 3;
579 addr2 = addr >> 11;
580 }
581 break;
582 case 0x19:
583 if(external_is_RAS && (addr & 0x800) == 0)
584 return 0xFFFFFFFF;
585 nbank = addr >> 23;
586 if((nbank & 3) < 2)
587 {
588 nbank = (addr >> 12) & 1;
589 addr2 = addr >> 13;
590 }
591 else
592 addr2 = addr >> 12;
593 break;
594 default:
595 if((scat_regs[SCAT_DRAM_CONFIGURATION] & 0x1F) < 6)
596 {
597 nbank = addr >> 19;
598 addr2 = (addr >> 10) & 0x1FF;
599 }
600 else if((scat_regs[SCAT_DRAM_CONFIGURATION] & 0x1F) < 0x17)
601 {
602 nbank = addr >> 21;
603 addr2 = (addr >> 11) & 0x3FF;
604 }
605 else
606 {
607 nbank = addr >> 23;
608 addr2 = (addr >> 12) & 0x7FF;
609 }
610 break;
611 }
612
613 nbank &= (scat_regs[SCAT_EXTENDED_BOUNDARY] & 0x80) ? 7 : 3;
614 if ((scat_regs[SCAT_DRAM_CONFIGURATION] & 0x1F) > 0x16 && nbank == 3)
615 return 0xFFFFFFFF;
616
617 if(external_is_RAS && (scat_regs[SCAT_EXTENDED_BOUNDARY] & 0x80) == 0)
618 {
619 if(nbank == 3)
620 nbank = 7;
621 else
622 return 0xFFFFFFFF;
623 }
624 else if(!external_is_RAS && scat_regs[SCAT_EXTENDED_BOUNDARY] & 0x80)
625 {
626 switch(nbank)
627 {
628 case 7:
629 nbank = 3;
630 break;
631 // Note - In the following cases, the chipset accesses multiple memory banks at the same time, so it's impossible to predict which memory bank is actually accessed.
632 case 5:
633 case 1:
634 nbank = 1;
635 break;
636 case 3:
637 nbank = 2;
638 break;
639 default:
640 nbank = 0;
641 break;
642 }
643 }
644
645 switch(mem_size & ~511)
646 {
647 case 1024:
648 case 1536:
649 addr &= 0x3FF;
650 if(nbank < 2)
651 addr |= (nbank << 10) | ((addr2 & 0x1FF) << 11);
652 else
653 addr |= ((addr2 & 0x1FF) << 10) | (nbank << 19);
654 break;
655 case 2048:
656 if((scat_regs[SCAT_DRAM_CONFIGURATION] & 0x1F) == 5)
657 {
658 addr &= 0x3FF;
659 if(nbank < 4)
660 addr |= (nbank << 10) | ((addr2 & 0x1FF) << 12);
661 else
662 addr |= ((addr2 & 0x1FF) << 10) | (nbank << 19);
663 }
664 else
665 {
666 addr &= 0x7FF;
667 addr |= ((addr2 & 0x3FF) << 11) | (nbank << 21);
668 }
669 break;
670 case 2560:
671 if(nbank == 0)
672 addr = (addr & 0x3FF) | ((addr2 & 0x1FF) << 10);
673 else
674 {
675 addr &= 0x7FF;
676 addr2 &= 0x3FF;
677 addr = addr + 0x80000 + ((addr2 << 11) | ((nbank - 1) << 21));
678 }
679 break;
680 case 3072:
681 if(nbank < 2)
682 addr = (addr & 0x3FF) | (nbank << 10) | ((addr2 & 0x1FF) << 11);
683 else
684 addr = 0x100000 + ((addr & 0x7FF) | ((addr2 & 0x3FF) << 11) | ((nbank - 2) << 21));
685 break;
686 case 4096:
687 case 6144:
688 addr &= 0x7FF;
689 if(nbank < 2)
690 addr |= (nbank << 11) | ((addr2 & 0x3FF) << 12);
691 else
692 addr |= ((addr2 & 0x3FF) << 11) | (nbank << 21);
693 break;
694 case 4608:
695 if(((scat_regs[SCAT_DRAM_CONFIGURATION] & 0x1F) >= 8 && (scat_regs[SCAT_DRAM_CONFIGURATION] & 0x1F) <= 0x0A) || ((scat_regs[SCAT_DRAM_CONFIGURATION] & 0x1F) == 0x18))
696 {
697 if(nbank == 0)
698 addr = (addr & 0x3FF) | ((addr2 & 0x1FF) << 10);
699 else if(nbank < 3)
700 addr = 0x80000 + ((addr & 0x7FF) | ((nbank - 1) << 11) | ((addr2 & 0x3FF) << 12));
701 else
702 addr = 0x480000 + ((addr & 0x3FF) | ((addr2 & 0x1FF) << 10) | ((nbank - 3) << 19));
703 }
704 else if(nbank == 0)
705 addr = (addr & 0x3FF) | ((addr2 & 0x1FF) << 10);
706 else
707 {
708 addr &= 0x7FF;
709 addr2 &= 0x3FF;
710 addr = addr + 0x80000 + ((addr2 << 11) | ((nbank - 1) << 21));
711 }
712 break;
713 case 5120:
714 case 7168:
715 if(nbank < 2)
716 addr = (addr & 0x3FF) | (nbank << 10) | ((addr2 & 0x1FF) << 11);
717 else if(nbank < 4)
718 addr = 0x100000 + ((addr & 0x7FF) | ((addr2 & 0x3FF) << 12) | ((nbank & 1) << 11));
719 else
720 addr = 0x100000 + ((addr & 0x7FF) | ((addr2 & 0x3FF) << 11) | ((nbank - 2) << 21));
721 break;
722 case 6656:
723 if(((scat_regs[SCAT_DRAM_CONFIGURATION] & 0x1F) >= 8 && (scat_regs[SCAT_DRAM_CONFIGURATION] & 0x1F) <= 0x0A) || ((scat_regs[SCAT_DRAM_CONFIGURATION] & 0x1F) == 0x18))
724 {
725 if(nbank == 0)
726 addr = (addr & 0x3FF) | ((addr2 & 0x1FF) << 10);
727 else if(nbank < 3)
728 addr = 0x80000 + ((addr & 0x7FF) | ((nbank - 1) << 11) | ((addr2 & 0x3FF) << 12));
729 else if(nbank == 3)
730 addr = 0x480000 + ((addr & 0x7FF) | ((addr2 & 0x3FF) << 11));
731 else
732 addr = 0x680000 + ((addr & 0x3FF) | ((addr2 & 0x1FF) << 10) | ((nbank - 4) << 19));
733 }
734 else if(nbank == 0)
735 addr = (addr & 0x3FF) | ((addr2 & 0x1FF) << 10);
736 else if(nbank == 1)
737 {
738 addr &= 0x7FF;
739 addr2 &= 0x3FF;
740 addr = addr + 0x80000 + (addr2 << 11);
741 }
742 else
743 {
744 addr &= 0x7FF;
745 addr2 &= 0x3FF;
746 addr = addr + 0x280000 + ((addr2 << 12) | ((nbank & 1) << 11) | (((nbank - 2) & 6) << 21));
747 }
748 break;
749 case 8192:
750 addr &= 0x7FF;
751 if(nbank < 4)
752 addr |= (nbank << 11) | ((addr2 & 0x3FF) << 13);
753 else
754 addr |= ((addr2 & 0x3FF) << 11) | (nbank << 21);
755 break;
756 case 9216:
757 if(nbank < 2)
758 addr = (addr & 0x3FF) | (nbank << 10) | ((addr2 & 0x1FF) << 11);
759 else if(external_is_RAS)
760 {
761 if(nbank < 6)
762 addr = 0x100000 + ((addr & 0x7FF) | ((addr2 & 0x3FF) << 12) | ((nbank & 1) << 11));
763 else
764 addr = 0x100000 + ((addr & 0x7FF) | ((addr2 & 0x3FF) << 11) | ((nbank - 2) << 21));
765 }
766 else
767 addr = 0x100000 + ((addr & 0xFFF) | ((addr2 & 0x7FF) << 12) | ((nbank - 2) << 23));
768 break;
769 case 10240:
770 if(external_is_RAS)
771 {
772 addr &= 0x7FF;
773 if(nbank < 4)
774 addr |= (nbank << 11) | ((addr2 & 0x3FF) << 13);
775 else
776 addr |= ((addr2 & 0x3FF) << 11) | (nbank << 21);
777 }
778 else if(nbank == 0)
779 addr = (addr & 0x7FF) | ((addr2 & 0x3FF) << 11);
780 else
781 {
782 addr &= 0xFFF;
783 addr2 &= 0x7FF;
784 addr = addr + 0x200000 + ((addr2 << 12) | ((nbank - 1) << 23));
785 }
786 break;
787 case 11264:
788 if(nbank < 2)
789 addr = (addr & 0x3FF) | (nbank << 10) | ((addr2 & 0x1FF) << 11);
790 else if(nbank < 6)
791 addr = 0x100000 + ((addr & 0x7FF) | ((addr2 & 0x3FF) << 12) | ((nbank & 1) << 11));
792 else
793 addr = 0x100000 + ((addr & 0x7FF) | ((addr2 & 0x3FF) << 11) | ((nbank - 2) << 21));
794 break;
795 case 12288:
796 if(external_is_RAS)
797 {
798 addr &= 0x7FF;
799 if(nbank < 4)
800 addr |= (nbank << 11) | ((addr2 & 0x3FF) << 13);
801 else if(nbank < 6)
802 addr |= ((nbank & 1) << 11) | ((addr2 & 0x3FF) << 12) | ((nbank & 4) << 21);
803 else
804 addr |= ((addr2 & 0x3FF) << 11) | (nbank << 21);
805 }
806 else
807 {
808 if(nbank < 2)
809 addr = (addr & 0x7FF) | (nbank << 11) | ((addr2 & 0x3FF) << 12);
810 else
811 addr = 0x400000 + ((addr & 0xFFF) | ((addr2 & 0x7FF) << 12) | ((nbank - 2) << 23));
812 }
813 break;
814 case 13312:
815 if(nbank < 2)
816 addr = (addr & 0x3FF) | (nbank << 10) | ((addr2 & 0x1FF) << 11);
817 else if(nbank < 4)
818 addr = 0x100000 + ((addr & 0x7FF) | ((addr2 & 0x3FF) << 12) | ((nbank & 1) << 11));
819 else
820 addr = 0x500000 + ((addr & 0x7FF) | ((addr2 & 0x3FF) << 13) | ((nbank & 3) << 11));
821 break;
822 case 14336:
823 addr &= 0x7FF;
824 if(nbank < 4)
825 addr |= (nbank << 11) | ((addr2 & 0x3FF) << 13);
826 else if(nbank < 6)
827 addr |= ((nbank & 1) << 11) | ((addr2 & 0x3FF) << 12) | ((nbank & 4) << 21);
828 else
829 addr |= ((addr2 & 0x3FF) << 11) | (nbank << 21);
830 break;
831 case 16384:
832 if(external_is_RAS)
833 {
834 addr &= 0x7FF;
835 addr2 &= 0x3FF;
836 addr |= ((nbank & 3) << 11) | (addr2 << 13) | ((nbank & 4) << 21);
837 }
838 else
839 {
840 addr &= 0xFFF;
841 addr2 &= 0x7FF;
842 if(nbank < 2)
843 addr |= (addr2 << 13) | (nbank << 12);
844 else
845 addr |= (addr2 << 12) | (nbank << 23);
846 }
847 break;
848 default:
849 if(mem_size < 2048 || ((mem_size & 1536) == 512) || (mem_size == 2048 && (scat_regs[SCAT_DRAM_CONFIGURATION] & 0x1F) < 6))
850 {
851 addr &= 0x3FF;
852 addr2 &= 0x1FF;
853 addr |= (addr2 << 10) | (nbank << 19);
854 }
855 else if(mem_size < 8192 || (scat_regs[SCAT_DRAM_CONFIGURATION] & 0x1F) < 0x17)
856 {
857 addr &= 0x7FF;
858 addr2 &= 0x3FF;
859 addr |= (addr2 << 11) | (nbank << 21);
860 }
861 else
862 {
863 addr &= 0xFFF;
864 addr2 &= 0x7FF;
865 addr |= (addr2 << 12) | (nbank << 23);
866 }
867 break;
868 }
869 }
870 return addr;
871 }
872
scat_set_global_EMS_state(int state)873 void scat_set_global_EMS_state(int state)
874 {
875 int i;
876 uint32_t base_addr, virt_addr;
877
878 for(i=((scat_regs[SCAT_VERSION] & 0xF0) == 0) ? 0 : 24; i<32; i++)
879 {
880 base_addr = (i + 16) << 14;
881 if(i >= 24)
882 base_addr += 0x30000;
883 if(state && (scat_stat[i].regs_2x9 & 0x80))
884 {
885 virt_addr = get_scat_addr(base_addr, &scat_stat[i]);
886 if(i < 24) mem_mapping_disable(&scat_4000_EFFF_mapping[i]);
887 else mem_mapping_disable(&scat_4000_EFFF_mapping[i + 12]);
888 mem_mapping_enable(&scat_ems_mapping[i]);
889 if(virt_addr < (mem_size << 10)) mem_mapping_set_exec(&scat_ems_mapping[i], ram + virt_addr);
890 else mem_mapping_set_exec(&scat_ems_mapping[i], NULL);
891 }
892 else
893 {
894 mem_mapping_set_exec(&scat_ems_mapping[i], ram + base_addr);
895 mem_mapping_disable(&scat_ems_mapping[i]);
896
897 int conf = (scat_regs[SCAT_VERSION] & 0xF0) ? (scat_regs[SCAT_DRAM_CONFIGURATION] & 0x1F) : (scat_regs[SCAT_DRAM_CONFIGURATION] & 0xF) | ((scat_regs[SCAT_EXTENDED_BOUNDARY] & 0x40) >> 2);
898 if(i < 24)
899 {
900 if(conf > 1 || (conf == 1 && i < 16))
901 mem_mapping_enable(&scat_4000_EFFF_mapping[i]);
902 else
903 mem_mapping_disable(&scat_4000_EFFF_mapping[i]);
904 }
905 else if(conf > 3 || ((scat_regs[SCAT_VERSION] & 0xF0) != 0 && conf == 2))
906 mem_mapping_enable(&scat_4000_EFFF_mapping[i + 12]);
907 else
908 mem_mapping_disable(&scat_4000_EFFF_mapping[i + 12]);
909 }
910 }
911 flushmmucache();
912 }
913
scat_memmap_state_update()914 void scat_memmap_state_update()
915 {
916 int i;
917 uint32_t addr;
918
919 for(i=(((scat_regs[SCAT_VERSION] & 0xF0) == 0) ? 0 : 16);i<44;i++)
920 {
921 addr = get_scat_addr(0x40000 + (i << 14), NULL);
922 mem_mapping_set_exec(&scat_4000_EFFF_mapping[i], addr < (mem_size << 10) ? ram + addr : NULL);
923 // pclog("scat_memmap_state_update : Address %06X to %06X\n", 0x40000 + (i << 14), addr);
924 }
925 addr = get_scat_addr(0, NULL);
926 // pclog("scat_memmap_state_update : Address 000000 to %06X\n", addr);
927 mem_mapping_set_exec(&scat_low_mapping[0], addr < (mem_size << 10) ? ram + addr : NULL);
928 addr = get_scat_addr(0xF0000, NULL);
929 // pclog("scat_memmap_state_update : Address 0F0000 to %06X\n", addr);
930 mem_mapping_set_exec(&scat_low_mapping[1], addr < (mem_size << 10) ? ram + addr : NULL);
931 for(i=2;i<32;i++)
932 {
933 addr = get_scat_addr(i << 19, NULL);
934 mem_mapping_set_exec(&scat_low_mapping[i], addr < (mem_size << 10) ? ram + addr : NULL);
935 // pclog("scat_memmap_state_update : Address %06X to %06X\n", i << 19, addr);
936 }
937
938 if((scat_regs[SCAT_VERSION] & 0xF0) == 0)
939 {
940 for(i=0;i < scat_max_map[(scat_regs[SCAT_DRAM_CONFIGURATION] & 0xF) | ((scat_regs[SCAT_EXTENDED_BOUNDARY] & 0x40) >> 2)];i++)
941 mem_mapping_enable(&scat_low_mapping[i]);
942 for(;i<32;i++) mem_mapping_disable(&scat_low_mapping[i]);
943
944 for(i=24;i<36;i++)
945 {
946 if(((scat_regs[SCAT_DRAM_CONFIGURATION] & 0xF) | (scat_regs[SCAT_EXTENDED_BOUNDARY] & 0x40)) < 4)
947 mem_mapping_disable(&scat_4000_EFFF_mapping[i]);
948 else
949 mem_mapping_enable(&scat_4000_EFFF_mapping[i]);
950 }
951 }
952 else
953 {
954 for(i=0;i < scatsx_max_map[scat_regs[SCAT_DRAM_CONFIGURATION] & 0x1F];i++)
955 mem_mapping_enable(&scat_low_mapping[i]);
956 for(;i<32;i++) mem_mapping_disable(&scat_low_mapping[i]);
957
958 for(i=24;i<36;i++)
959 {
960 if((scat_regs[SCAT_DRAM_CONFIGURATION] & 0x1F) < 2 || (scat_regs[SCAT_DRAM_CONFIGURATION] & 0x1F) == 3)
961 mem_mapping_disable(&scat_4000_EFFF_mapping[i]);
962 else
963 mem_mapping_enable(&scat_4000_EFFF_mapping[i]);
964 }
965 }
966
967 if((((scat_regs[SCAT_VERSION] & 0xF0) == 0) && (scat_regs[SCAT_EXTENDED_BOUNDARY] & 0x40) == 0) || ((scat_regs[SCAT_VERSION] & 0xF0) != 0))
968 {
969 if((((scat_regs[SCAT_VERSION] & 0xF0) == 0) && (scat_regs[SCAT_DRAM_CONFIGURATION] & 0x0F) == 3) || (((scat_regs[SCAT_VERSION] & 0xF0) != 0) && (scat_regs[SCAT_DRAM_CONFIGURATION] & 0x1F) == 3))
970 {
971 mem_mapping_disable(&scat_low_mapping[2]);
972 for(i=0;i<6;i++)
973 {
974 addr = get_scat_addr(0x100000 + (i << 16), NULL);
975 mem_mapping_set_exec(&scat_remap_mapping[i], addr < (mem_size << 10) ? ram + addr : NULL);
976 mem_mapping_enable(&scat_remap_mapping[i]);
977 // pclog("scat_memmap_state_update : Address %06X to %06X\n", 0x100000 + (i << 16), addr);
978 }
979 }
980 else
981 {
982 for(i=0;i<6;i++)
983 mem_mapping_disable(&scat_remap_mapping[i]);
984 if((((scat_regs[SCAT_VERSION] & 0xF0) == 0) && (scat_regs[SCAT_DRAM_CONFIGURATION] & 0x0F) > 4) || (((scat_regs[SCAT_VERSION] & 0xF0) != 0) && (scat_regs[SCAT_DRAM_CONFIGURATION] & 0x1F) > 3))
985 mem_mapping_enable(&scat_low_mapping[2]);
986 }
987 }
988 else
989 {
990 for(i=0;i<6;i++)
991 mem_mapping_disable(&scat_remap_mapping[i]);
992 mem_mapping_enable(&scat_low_mapping[2]);
993 }
994
995 scat_set_global_EMS_state(scat_regs[SCAT_EMS_CONTROL] & 0x80);
996 }
997
scat_write(uint16_t port,uint8_t val,void * priv)998 void scat_write(uint16_t port, uint8_t val, void *priv)
999 {
1000 uint8_t scat_reg_valid = 0, scat_shadow_update = 0, scat_map_update = 0, index;
1001 uint32_t base_addr, virt_addr;
1002
1003 switch (port)
1004 {
1005 case 0x22:
1006 scat_index = val;
1007 break;
1008
1009 case 0x23:
1010 switch (scat_index)
1011 {
1012 case SCAT_DMA_WAIT_STATE_CONTROL:
1013 case SCAT_CLOCK_CONTROL:
1014 case SCAT_PERIPHERAL_CONTROL:
1015 scat_reg_valid = 1;
1016 break;
1017 case SCAT_EMS_CONTROL:
1018 if(val & 0x40)
1019 {
1020 if(val & 1)
1021 {
1022 io_sethandler(0x0218, 0x0003, scat_read, NULL, NULL, scat_write, NULL, NULL, NULL);
1023 io_removehandler(0x0208, 0x0003, scat_read, NULL, NULL, scat_write, NULL, NULL, NULL);
1024 }
1025 else
1026 {
1027 io_sethandler(0x0208, 0x0003, scat_read, NULL, NULL, scat_write, NULL, NULL, NULL);
1028 io_removehandler(0x0218, 0x0003, scat_read, NULL, NULL, scat_write, NULL, NULL, NULL);
1029 }
1030 }
1031 else
1032 {
1033 io_removehandler(0x0208, 0x0003, scat_read, NULL, NULL, scat_write, NULL, NULL, NULL);
1034 io_removehandler(0x0218, 0x0003, scat_read, NULL, NULL, scat_write, NULL, NULL, NULL);
1035 }
1036 scat_set_global_EMS_state(val & 0x80);
1037 scat_reg_valid = 1;
1038 break;
1039 case SCAT_POWER_MANAGEMENT:
1040 // TODO - Only use AUX parity disable bit for this version. Other bits should be implemented later.
1041 val &= (scat_regs[SCAT_VERSION] & 0xF0) == 0 ? 0x40 : 0x60;
1042 scat_reg_valid = 1;
1043 break;
1044 case SCAT_DRAM_CONFIGURATION:
1045 scat_map_update = 1;
1046
1047 if((scat_regs[SCAT_VERSION] & 0xF0) == 0)
1048 {
1049 cpu_waitstates = (val & 0x70) == 0 ? 1 : 2;
1050 cpu_update_waitstates();
1051 }
1052
1053 scat_reg_valid = 1;
1054 break;
1055 case SCAT_EXTENDED_BOUNDARY:
1056 if((scat_regs[SCAT_VERSION] & 0xF0) == 0)
1057 {
1058 if(scat_regs[SCAT_VERSION] < 4)
1059 {
1060 val &= 0xBF;
1061 scat_set_xms_bound(val & 0x0f);
1062 }
1063 else
1064 {
1065 val = (val & 0x7F) | 0x80;
1066 scat_set_xms_bound(val & 0x4f);
1067 }
1068 }
1069 else
1070 scat_set_xms_bound(val & 0x1f);
1071 mem_set_mem_state(0x40000, 0x60000, (val & 0x20) ? MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL : MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
1072 if((val ^ scat_regs[SCAT_EXTENDED_BOUNDARY]) & 0xC0) scat_map_update = 1;
1073 scat_reg_valid = 1;
1074 break;
1075 case SCAT_ROM_ENABLE:
1076 scat_reg_valid = 1;
1077 scat_romcs_state_update(val);
1078 break;
1079 case SCAT_RAM_WRITE_PROTECT:
1080 scat_reg_valid = 1;
1081 flushmmucache_cr3();
1082 break;
1083 case SCAT_SHADOW_RAM_ENABLE_1:
1084 case SCAT_SHADOW_RAM_ENABLE_2:
1085 case SCAT_SHADOW_RAM_ENABLE_3:
1086 scat_reg_valid = 1;
1087 scat_shadow_update = 1;
1088 break;
1089 case SCATSX_LAPTOP_FEATURES:
1090 if((scat_regs[SCAT_VERSION] & 0xF0) != 0)
1091 {
1092 val = (val & ~8) | (scat_regs[SCATSX_LAPTOP_FEATURES] & 8);
1093 scat_reg_valid = 1;
1094 }
1095 break;
1096 case SCATSX_FAST_VIDEO_CONTROL:
1097 case SCATSX_FAST_VIDEORAM_ENABLE:
1098 case SCATSX_HIGH_PERFORMANCE_REFRESH:
1099 case SCATSX_CAS_TIMING_FOR_DMA:
1100 if((scat_regs[SCAT_VERSION] & 0xF0) != 0) scat_reg_valid = 1;
1101 break;
1102 default:
1103 break;
1104 }
1105 if (scat_reg_valid)
1106 scat_regs[scat_index] = val;
1107 else pclog("Attemped to write unimplemented SCAT register %02X at %04X:%04X\n", scat_index, val, CS, cpu_state.oldpc);
1108 if (scat_shadow_update)
1109 scat_shadow_state_update();
1110 if (scat_map_update)
1111 scat_memmap_state_update();
1112 // pclog("Write SCAT Register %02X to %02X at %04X:%04X\n", scat_index, val, CS, cpu_state.pc);
1113 break;
1114
1115 case 0x92:
1116 if ((mem_a20_alt ^ val) & 2)
1117 {
1118 mem_a20_alt = val & 2;
1119 mem_a20_recalc();
1120 }
1121 if ((~scat_port_92 & val) & 1)
1122 {
1123 softresetx86();
1124 cpu_set_edx();
1125 }
1126 scat_port_92 = val;
1127 break;
1128
1129 case 0x208:
1130 case 0x218:
1131 if ((scat_regs[SCAT_EMS_CONTROL] & 0x41) == (0x40 | ((port & 0x10) >> 4)))
1132 {
1133 // pclog("Write SCAT EMS Control Port %04X to %02X at %04X:%04X\n", port, val, CS, cpu_state.pc);
1134 if((scat_regs[SCAT_VERSION] & 0xF0) == 0) index = scat_ems_reg_2xA & 0x1F;
1135 else index = ((scat_ems_reg_2xA & 0x40) >> 4) + (scat_ems_reg_2xA & 0x3) + 24;
1136 scat_stat[index].regs_2x8 = val;
1137 base_addr = (index + 16) << 14;
1138 if(index >= 24)
1139 base_addr += 0x30000;
1140
1141 if((scat_regs[SCAT_EMS_CONTROL] & 0x80) && (scat_stat[index].regs_2x9 & 0x80))
1142 {
1143 virt_addr = get_scat_addr(base_addr, &scat_stat[index]);
1144 if(virt_addr < (mem_size << 10)) mem_mapping_set_exec(&scat_ems_mapping[index], ram + virt_addr);
1145 else mem_mapping_set_exec(&scat_ems_mapping[index], NULL);
1146 flushmmucache();
1147 }
1148 }
1149 break;
1150 case 0x209:
1151 case 0x219:
1152 if ((scat_regs[SCAT_EMS_CONTROL] & 0x41) == (0x40 | ((port & 0x10) >> 4)))
1153 {
1154 // pclog("Write SCAT EMS Control Port %04X to %02X at %04X:%04X\n", port, val, CS, cpu_state.pc);
1155 if((scat_regs[SCAT_VERSION] & 0xF0) == 0) index = scat_ems_reg_2xA & 0x1F;
1156 else index = ((scat_ems_reg_2xA & 0x40) >> 4) + (scat_ems_reg_2xA & 0x3) + 24;
1157 scat_stat[index].regs_2x9 = val;
1158 base_addr = (index + 16) << 14;
1159 if(index >= 24)
1160 base_addr += 0x30000;
1161
1162 if (scat_regs[SCAT_EMS_CONTROL] & 0x80)
1163 {
1164 if (val & 0x80)
1165 {
1166 virt_addr = get_scat_addr(base_addr, &scat_stat[index]);
1167 if(index < 24) mem_mapping_disable(&scat_4000_EFFF_mapping[index]);
1168 else mem_mapping_disable(&scat_4000_EFFF_mapping[index + 12]);
1169 if(virt_addr < (mem_size << 10)) mem_mapping_set_exec(&scat_ems_mapping[index], ram + virt_addr);
1170 else mem_mapping_set_exec(&scat_ems_mapping[index], NULL);
1171 mem_mapping_enable(&scat_ems_mapping[index]);
1172 // pclog("Map page %d(address %05X) to address %06X\n", index, base_addr, virt_addr);
1173 }
1174 else
1175 {
1176 mem_mapping_set_exec(&scat_ems_mapping[index], ram + base_addr);
1177 mem_mapping_disable(&scat_ems_mapping[index]);
1178 if(index < 24) mem_mapping_enable(&scat_4000_EFFF_mapping[index]);
1179 else mem_mapping_enable(&scat_4000_EFFF_mapping[index + 12]);
1180 // pclog("Unmap page %d(address %06X)\n", index, base_addr);
1181 }
1182 flushmmucache();
1183 }
1184
1185 if (scat_ems_reg_2xA & 0x80)
1186 {
1187 scat_ems_reg_2xA = (scat_ems_reg_2xA & 0xe0) | ((scat_ems_reg_2xA + 1) & (((scat_regs[SCAT_VERSION] & 0xF0) == 0) ? 0x1f : 3));
1188 }
1189 }
1190 break;
1191 case 0x20A:
1192 case 0x21A:
1193 if ((scat_regs[SCAT_EMS_CONTROL] & 0x41) == (0x40 | ((port & 0x10) >> 4)))
1194 {
1195 // pclog("Write SCAT EMS Control Port %04X to %02X at %04X:%04X\n", port, val, CS, cpu_state.pc);
1196 scat_ems_reg_2xA = ((scat_regs[SCAT_VERSION] & 0xF0) == 0) ? val : val & 0xc3;
1197 }
1198 break;
1199 }
1200 }
1201
scat_read(uint16_t port,void * priv)1202 uint8_t scat_read(uint16_t port, void *priv)
1203 {
1204 uint8_t val = 0xff, index;
1205 switch (port)
1206 {
1207 case 0x23:
1208 switch (scat_index)
1209 {
1210 case SCAT_MISCELLANEOUS_STATUS:
1211 val = (scat_regs[scat_index] & 0x3f) | (~nmi_mask & 0x80) | ((mem_a20_key & 2) << 5);
1212 break;
1213 case SCAT_DRAM_CONFIGURATION:
1214 if ((scat_regs[SCAT_VERSION] & 0xF0) == 0) val = (scat_regs[scat_index] & 0x8f) | (cpu_waitstates == 1 ? 0 : 0x10);
1215 else val = scat_regs[scat_index];
1216 break;
1217 case SCAT_EXTENDED_BOUNDARY:
1218 val = scat_regs[scat_index];
1219 if ((scat_regs[SCAT_VERSION] & 0xF0) == 0)
1220 {
1221 if((scat_regs[SCAT_VERSION] & 0x0F) >= 4)
1222 val |= 0x80;
1223 else
1224 val &= 0xAF;
1225 }
1226 break;
1227 default:
1228 val = scat_regs[scat_index];
1229 break;
1230 }
1231 // pclog("Read SCAT Register %02X at %04X:%04X\n", scat_index, CS, cpu_state.pc);
1232 break;
1233
1234 case 0x92:
1235 val = scat_port_92;
1236 break;
1237
1238 case 0x208:
1239 case 0x218:
1240 if ((scat_regs[SCAT_EMS_CONTROL] & 0x41) == (0x40 | ((port & 0x10) >> 4)))
1241 {
1242 // pclog("Read SCAT EMS Control Port %04X at %04X:%04X\n", port, CS, cpu_state.pc);
1243 if((scat_regs[SCAT_VERSION] & 0xF0) == 0) index = scat_ems_reg_2xA & 0x1F;
1244 else index = ((scat_ems_reg_2xA & 0x40) >> 4) + (scat_ems_reg_2xA & 0x3) + 24;
1245 val = scat_stat[index].regs_2x8;
1246 }
1247 break;
1248 case 0x209:
1249 case 0x219:
1250 if ((scat_regs[SCAT_EMS_CONTROL] & 0x41) == (0x40 | ((port & 0x10) >> 4)))
1251 {
1252 // pclog("Read SCAT EMS Control Port %04X at %04X:%04X\n", port, CS, cpu_state.pc);
1253 if((scat_regs[SCAT_VERSION] & 0xF0) == 0) index = scat_ems_reg_2xA & 0x1F;
1254 else index = ((scat_ems_reg_2xA & 0x40) >> 4) + (scat_ems_reg_2xA & 0x3) + 24;
1255 val = scat_stat[index].regs_2x9;
1256 }
1257 break;
1258 case 0x20A:
1259 case 0x21A:
1260 if ((scat_regs[SCAT_EMS_CONTROL] & 0x41) == (0x40 | ((port & 0x10) >> 4)))
1261 {
1262 // pclog("Read SCAT EMS Control Port %04X at %04X:%04X\n", port, CS, cpu_state.pc);
1263 val = scat_ems_reg_2xA;
1264 }
1265 break;
1266 }
1267 return val;
1268 }
1269
mem_read_scatb(uint32_t addr,void * priv)1270 uint8_t mem_read_scatb(uint32_t addr, void *priv)
1271 {
1272 uint8_t val = 0xff;
1273 scat_t *stat = (scat_t *)priv;
1274
1275 addr = get_scat_addr(addr, stat);
1276 if (addr < (mem_size << 10))
1277 val = ram[addr];
1278
1279 return val;
1280 }
1281
mem_write_scatb(uint32_t addr,uint8_t val,void * priv)1282 void mem_write_scatb(uint32_t addr, uint8_t val, void *priv)
1283 {
1284 scat_t *stat = (scat_t *)priv;
1285 uint32_t oldaddr = addr, chkaddr;
1286
1287 addr = get_scat_addr(addr, stat);
1288 chkaddr = stat ? addr : oldaddr;
1289 if (chkaddr >= 0xC0000 && chkaddr < 0x100000)
1290 {
1291 if(scat_regs[SCAT_RAM_WRITE_PROTECT] & (1 << ((chkaddr - 0xC0000) >> 15))) return;
1292 }
1293 if (addr < (mem_size << 10))
1294 ram[addr] = val;
1295 }
1296
mem_read_scatw(uint32_t addr,void * priv)1297 uint16_t mem_read_scatw(uint32_t addr, void *priv)
1298 {
1299 uint16_t val = 0xffff;
1300 scat_t *stat = (scat_t *)priv;
1301
1302 if((addr & 0x3FFF) == 0x3FFF) pclog("mem_read_scatw(%08X, %p) called.\n", addr, priv);
1303 addr = get_scat_addr(addr, stat);
1304 if (addr < (mem_size << 10))
1305 val = *(uint16_t *)&ram[addr];
1306
1307 return val;
1308 }
1309
mem_write_scatw(uint32_t addr,uint16_t val,void * priv)1310 void mem_write_scatw(uint32_t addr, uint16_t val, void *priv)
1311 {
1312 scat_t *stat = (scat_t *)priv;
1313 uint32_t oldaddr = addr, chkaddr;
1314
1315 if((addr & 0x3FFF) == 0x3FFF) pclog("mem_write_scatw(%08X, %04X, %p) called.\n", addr, val, priv);
1316 addr = get_scat_addr(addr, stat);
1317 chkaddr = stat ? addr : oldaddr;
1318 if (chkaddr >= 0xC0000 && chkaddr < 0x100000)
1319 {
1320 if(scat_regs[SCAT_RAM_WRITE_PROTECT] & (1 << ((chkaddr - 0xC0000) >> 15))) return;
1321 }
1322 if (addr < (mem_size << 10))
1323 *(uint16_t *)&ram[addr] = val;
1324 }
1325
mem_read_scatl(uint32_t addr,void * priv)1326 uint32_t mem_read_scatl(uint32_t addr, void *priv)
1327 {
1328 uint32_t val = 0xffffffff;
1329 scat_t *stat = (scat_t *)priv;
1330
1331 if((addr & 0x3FFF) > 0x3FFC) pclog("mem_read_scatl(%08X, %p) called.\n", addr, priv);
1332 addr = get_scat_addr(addr, stat);
1333 if (addr < (mem_size << 10))
1334 val = *(uint32_t *)&ram[addr];
1335
1336 return val;
1337 }
1338
mem_write_scatl(uint32_t addr,uint32_t val,void * priv)1339 void mem_write_scatl(uint32_t addr, uint32_t val, void *priv)
1340 {
1341 scat_t *stat = (scat_t *)priv;
1342 uint32_t oldaddr = addr, chkaddr;
1343
1344 if((addr & 0x3FFF) > 0x3FFC) pclog("mem_write_scatl(%08X, %08X, %p) called.\n", addr, val, priv);
1345 addr = get_scat_addr(addr, stat);
1346 chkaddr = stat ? addr : oldaddr;
1347 if (chkaddr >= 0xC0000 && chkaddr < 0x100000)
1348 {
1349 if(scat_regs[SCAT_RAM_WRITE_PROTECT] & (1 << ((chkaddr - 0xC0000) >> 15))) return;
1350 }
1351 if (addr < (mem_size << 10))
1352 *(uint32_t *)&ram[addr] = val;
1353 }
1354
scat_init()1355 void scat_init()
1356 {
1357 int i;
1358
1359 io_sethandler(0x0022, 0x0002, scat_read, NULL, NULL, scat_write, NULL, NULL, NULL);
1360 io_sethandler(0x0092, 0x0001, scat_read, NULL, NULL, scat_write, NULL, NULL, NULL);
1361
1362 for (i = 0; i < 256; i++)
1363 {
1364 scat_regs[i] = 0xff;
1365 }
1366
1367 scat_regs[SCAT_DMA_WAIT_STATE_CONTROL] = 0;
1368 switch(romset)
1369 {
1370 case ROM_GW286CT:
1371 case ROM_SPC4216P:
1372 scat_regs[SCAT_VERSION] = 4;
1373 break;
1374 default:
1375 scat_regs[SCAT_VERSION] = 1;
1376 break;
1377 }
1378 scat_regs[SCAT_CLOCK_CONTROL] = 2;
1379 scat_regs[SCAT_PERIPHERAL_CONTROL] = 0x80;
1380 scat_regs[SCAT_MISCELLANEOUS_STATUS] = 0x37;
1381 scat_regs[SCAT_POWER_MANAGEMENT] = 0;
1382 scat_regs[SCAT_ROM_ENABLE] = 0xC0;
1383 scat_regs[SCAT_RAM_WRITE_PROTECT] = 0;
1384 scat_regs[SCAT_SHADOW_RAM_ENABLE_1] = 0;
1385 scat_regs[SCAT_SHADOW_RAM_ENABLE_2] = 0;
1386 scat_regs[SCAT_SHADOW_RAM_ENABLE_3] = 0;
1387 scat_regs[SCAT_DRAM_CONFIGURATION] = cpu_waitstates == 1 ? 2 : 0x12;
1388 scat_regs[SCAT_EXTENDED_BOUNDARY] = 0;
1389 scat_regs[SCAT_EMS_CONTROL] = 0;
1390 scat_port_92 = 0;
1391
1392 mem_mapping_disable(&ram_low_mapping);
1393 mem_mapping_disable(&ram_mid_mapping);
1394 mem_mapping_disable(&ram_high_mapping);
1395 for (i = 0; i < 4; i++)
1396 mem_mapping_disable(&bios_mapping[i]);
1397 mem_mapping_add(&scat_low_mapping[0], 0, 0x40000, mem_read_scatb, mem_read_scatw, mem_read_scatl, mem_write_scatb, mem_write_scatw, mem_write_scatl, ram, MEM_MAPPING_INTERNAL, NULL);
1398 mem_mapping_add(&scat_low_mapping[1], 0xF0000, 0x10000, mem_read_scatb, mem_read_scatw, mem_read_scatl, mem_write_scatb, mem_write_scatw, mem_write_scatl, ram + 0xF0000, MEM_MAPPING_INTERNAL, NULL);
1399 for(i=2;i<32;i++)
1400 {
1401 mem_mapping_add(&scat_low_mapping[i], (i << 19), 0x80000, mem_read_scatb, mem_read_scatw, mem_read_scatl, mem_write_scatb, mem_write_scatw, mem_write_scatl, ram + (i << 19), MEM_MAPPING_INTERNAL, NULL);
1402 }
1403 mem_mapping_set_addr(&scat_low_mapping[31], 0xF80000, scat_regs[SCAT_VERSION] < 4 ? 0x40000 : 0x60000);
1404
1405 for (i = 0; i < 44; i++)
1406 mem_mapping_add(&scat_4000_EFFF_mapping[i], 0x40000 + (i << 14), 0x4000, mem_read_scatb, mem_read_scatw, mem_read_scatl, mem_write_scatb, mem_write_scatw, mem_write_scatl, mem_size > 256 + (i << 4) ? ram + 0x40000 + (i << 14) : NULL, MEM_MAPPING_INTERNAL, NULL);
1407 for (i = 0; i < 8; i++)
1408 {
1409 mem_mapping_add(&scat_low_ROMCS_mapping[i], 0xC0000 + (i << 14), 0x4000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_null, mem_write_nullw, mem_write_nulll, rom + ((i << 14) & biosmask), MEM_MAPPING_EXTERNAL|MEM_MAPPING_ROM, NULL);
1410 mem_mapping_disable(&scat_low_ROMCS_mapping[i]);
1411 }
1412
1413 for (i = 0; i < 32; i++)
1414 {
1415 scat_stat[i].regs_2x8 = 0xff;
1416 scat_stat[i].regs_2x9 = 0x03;
1417 mem_mapping_add(&scat_ems_mapping[i], (i + (i >= 24 ? 28 : 16)) << 14, 0x04000, mem_read_scatb, mem_read_scatw, mem_read_scatl, mem_write_scatb, mem_write_scatw, mem_write_scatl, ram + ((i + (i >= 24 ? 28 : 16)) << 14), 0, &scat_stat[i]);
1418 }
1419
1420 for(i=4;i<10;i++) isram[i] = 0;
1421
1422 for (i = (scat_regs[SCAT_VERSION] < 4 ? 0 : 8); i < 16; i++)
1423 {
1424 mem_mapping_add(&scat_high_mapping[i], (i << 14) + 0xFC0000, 0x04000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_null, mem_write_nullw, mem_write_nulll, rom + ((i << 14) & biosmask), 0, NULL);
1425 mem_mapping_enable(&scat_high_mapping[i]);
1426 }
1427
1428 for(i=0;i<6;i++)
1429 mem_mapping_add(&scat_remap_mapping[i], 0x100000 + (i << 16), 0x10000, mem_read_scatb, mem_read_scatw, mem_read_scatl, mem_write_scatb, mem_write_scatw, mem_write_scatl, mem_size >= 1024 ? ram + get_scat_addr(0x100000 + (i << 16), NULL) : NULL, MEM_MAPPING_INTERNAL, NULL);
1430
1431 external_is_RAS = (scat_regs[SCAT_VERSION] > 3) || (((mem_size & ~2047) >> 11) + ((mem_size & 1536) >> 9) + ((mem_size & 511) >> 7)) > 4;
1432
1433 scat_set_xms_bound(0);
1434 scat_memmap_state_update();
1435 scat_shadow_state_update();
1436 }
1437
scatsx_init()1438 void scatsx_init()
1439 {
1440 int i;
1441
1442 io_sethandler(0x0022, 0x0002, scat_read, NULL, NULL, scat_write, NULL, NULL, NULL);
1443 io_sethandler(0x0092, 0x0001, scat_read, NULL, NULL, scat_write, NULL, NULL, NULL);
1444
1445 for (i = 0; i < 256; i++)
1446 {
1447 scat_regs[i] = 0xff;
1448 }
1449
1450 scat_regs[SCAT_DMA_WAIT_STATE_CONTROL] = 0;
1451 scat_regs[SCAT_VERSION] = 0x13;
1452 scat_regs[SCAT_CLOCK_CONTROL] = 6;
1453 scat_regs[SCAT_PERIPHERAL_CONTROL] = 0;
1454 scat_regs[SCAT_MISCELLANEOUS_STATUS] = 0x37;
1455 scat_regs[SCAT_POWER_MANAGEMENT] = 0;
1456 scat_regs[SCAT_ROM_ENABLE] = 0xC0;
1457 scat_regs[SCAT_RAM_WRITE_PROTECT] = 0;
1458 scat_regs[SCAT_SHADOW_RAM_ENABLE_1] = 0;
1459 scat_regs[SCAT_SHADOW_RAM_ENABLE_2] = 0;
1460 scat_regs[SCAT_SHADOW_RAM_ENABLE_3] = 0;
1461 scat_regs[SCAT_DRAM_CONFIGURATION] = 1;
1462 scat_regs[SCAT_EXTENDED_BOUNDARY] = 0;
1463 scat_regs[SCAT_EMS_CONTROL] = 0;
1464 scat_regs[SCATSX_LAPTOP_FEATURES] = 0;
1465 scat_regs[SCATSX_FAST_VIDEO_CONTROL] = 0;
1466 scat_regs[SCATSX_FAST_VIDEORAM_ENABLE] = 0;
1467 scat_regs[SCATSX_HIGH_PERFORMANCE_REFRESH] = 8;
1468 scat_regs[SCATSX_CAS_TIMING_FOR_DMA] = 3;
1469 scat_port_92 = 0;
1470
1471 mem_mapping_disable(&ram_low_mapping);
1472 mem_mapping_disable(&ram_mid_mapping);
1473 mem_mapping_disable(&ram_high_mapping);
1474 for (i = 0; i < 4; i++)
1475 mem_mapping_disable(&bios_mapping[i]);
1476 mem_mapping_add(&scat_low_mapping[0], 0, 0x80000, mem_read_scatb, mem_read_scatw, mem_read_scatl, mem_write_scatb, mem_write_scatw, mem_write_scatl, ram, MEM_MAPPING_INTERNAL, NULL);
1477 mem_mapping_add(&scat_low_mapping[1], 0xF0000, 0x10000, mem_read_scatb, mem_read_scatw, mem_read_scatl, mem_write_scatb, mem_write_scatw, mem_write_scatl, ram + 0xF0000, MEM_MAPPING_INTERNAL, NULL);
1478 for(i=2;i<32;i++)
1479 {
1480 mem_mapping_add(&scat_low_mapping[i], (i << 19), 0x80000, mem_read_scatb, mem_read_scatw, mem_read_scatl, mem_write_scatb, mem_write_scatw, mem_write_scatl, ram + (i << 19), MEM_MAPPING_INTERNAL, NULL);
1481 }
1482 mem_mapping_set_addr(&scat_low_mapping[31], 0xF80000, 0x40000);
1483
1484 for (i = 16; i < 44; i++)
1485 {
1486 mem_mapping_add(&scat_4000_EFFF_mapping[i], 0x40000 + (i << 14), 0x4000, mem_read_scatb, mem_read_scatw, mem_read_scatl, mem_write_scatb, mem_write_scatw, mem_write_scatl, mem_size > 256 + (i << 4) ? ram + 0x40000 + (i << 14) : NULL, MEM_MAPPING_INTERNAL, NULL);
1487 mem_mapping_enable(&scat_4000_EFFF_mapping[i]);
1488 }
1489 for (i = 0; i < 8; i++)
1490 {
1491 mem_mapping_add(&scat_low_ROMCS_mapping[i], 0xC0000 + (i << 14), 0x4000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_null, mem_write_nullw, mem_write_nulll, rom + ((i << 14) & biosmask), MEM_MAPPING_EXTERNAL|MEM_MAPPING_ROM, NULL);
1492 mem_mapping_disable(&scat_low_ROMCS_mapping[i]);
1493 }
1494
1495 for (i = 24; i < 32; i++)
1496 {
1497 scat_stat[i].regs_2x8 = 0xff;
1498 scat_stat[i].regs_2x9 = 0x03;
1499 mem_mapping_add(&scat_ems_mapping[i], (i + 28) << 14, 0x04000, mem_read_scatb, mem_read_scatw, mem_read_scatl, mem_write_scatb, mem_write_scatw, mem_write_scatl, ram + ((i + 28) << 14), 0, &scat_stat[i]);
1500 mem_mapping_disable(&scat_ems_mapping[i]);
1501 }
1502
1503 for (i = 0; i < 16; i++)
1504 {
1505 mem_mapping_add(&scat_high_mapping[i], (i << 14) + 0xFC0000, 0x04000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_null, mem_write_nullw, mem_write_nulll, rom + ((i << 14) & biosmask), 0, NULL);
1506 mem_mapping_enable(&scat_high_mapping[i]);
1507 }
1508
1509 for(i=0;i<6;i++)
1510 mem_mapping_add(&scat_remap_mapping[i], 0x100000 + (i << 16), 0x10000, mem_read_scatb, mem_read_scatw, mem_read_scatl, mem_write_scatb, mem_write_scatw, mem_write_scatl, mem_size >= 1024 ? ram + get_scat_addr(0x100000 + (i << 16), NULL) : NULL, MEM_MAPPING_INTERNAL, NULL);
1511
1512 external_is_RAS = scatsx_external_is_RAS[mem_size >> 9];
1513
1514 scat_set_xms_bound(0);
1515 scat_memmap_state_update();
1516 scat_shadow_state_update();
1517 }
1518