Renamed the Paradise WD90C11 Standalone to Paradise WD90C11-LR and made it use the correct BIOS;
Added the Paradise PVGA1A (standalone) and the Paradise WD90C30-LR, both with configurable video memory; Added the Toshiba T3100e.
This commit is contained in:
@@ -8,7 +8,7 @@
|
||||
*
|
||||
* General keyboard driver interface.
|
||||
*
|
||||
* Version: @(#)keyboard.c 1.0.9 2017/11/03
|
||||
* Version: @(#)keyboard.c 1.0.10 2017/12/31
|
||||
*
|
||||
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
@@ -194,6 +194,13 @@ keyboard_input(int down, uint16_t scan)
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
keyboard_recv(uint16_t key)
|
||||
{
|
||||
return recv_key[key];
|
||||
}
|
||||
|
||||
|
||||
/* Do we have Control-Alt-PgDn in the keyboard buffer? */
|
||||
int
|
||||
keyboard_isfsexit(void)
|
||||
|
@@ -8,7 +8,7 @@
|
||||
*
|
||||
* Definitions for the keyboard interface.
|
||||
*
|
||||
* Version: @(#)keyboard.h 1.0.6 2017/11/06
|
||||
* Version: @(#)keyboard.h 1.0.7 2017/12/31
|
||||
*
|
||||
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
@@ -60,6 +60,7 @@ extern void keyboard_poll_host(void);
|
||||
extern void keyboard_process(void);
|
||||
extern uint16_t keyboard_convert(int ch);
|
||||
extern void keyboard_input(int down, uint16_t scan);
|
||||
extern int keyboard_recv(uint16_t key);
|
||||
extern int keyboard_isfsexit(void);
|
||||
extern int keyboard_ismsexit(void);
|
||||
|
||||
|
@@ -8,7 +8,7 @@
|
||||
*
|
||||
* Intel 8042 (AT keyboard controller) emulation.
|
||||
*
|
||||
* Version: @(#)keyboard_at.c 1.0.11 2017/12/25
|
||||
* Version: @(#)keyboard_at.c 1.0.12 2017/12/31
|
||||
*
|
||||
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
@@ -35,6 +35,7 @@
|
||||
#include "device.h"
|
||||
#include "timer.h"
|
||||
#include "machine/machine.h"
|
||||
#include "machine/m_at_t3100e.h"
|
||||
#include "floppy/floppy.h"
|
||||
#include "floppy/fdc.h"
|
||||
#include "sound/sound.h"
|
||||
@@ -567,6 +568,29 @@ kbd_adddata_keyboard(uint8_t val)
|
||||
return;
|
||||
}
|
||||
|
||||
/* Test for T3100E 'Fn' key (Right Alt / Right Ctrl) */
|
||||
if (romset == ROM_T3100E && (keyboard_recv(0xb8) || keyboard_recv(0x9d)))
|
||||
{
|
||||
switch (val)
|
||||
{
|
||||
case 0x4f: t3100e_notify_set(0x01); break; /* End */
|
||||
case 0x50: t3100e_notify_set(0x02); break; /* Down */
|
||||
case 0x51: t3100e_notify_set(0x03); break; /* PgDn */
|
||||
case 0x52: t3100e_notify_set(0x04); break; /* Ins */
|
||||
case 0x53: t3100e_notify_set(0x05); break; /* Del */
|
||||
case 0x54: t3100e_notify_set(0x06); break; /* SysRQ */
|
||||
case 0x45: t3100e_notify_set(0x07); break; /* NumLock */
|
||||
case 0x46: t3100e_notify_set(0x08); break; /* ScrLock */
|
||||
case 0x47: t3100e_notify_set(0x09); break; /* Home */
|
||||
case 0x48: t3100e_notify_set(0x0A); break; /* Up */
|
||||
case 0x49: t3100e_notify_set(0x0B); break; /* PgUp */
|
||||
case 0x4A: t3100e_notify_set(0x0C); break; /* Keypad -*/
|
||||
case 0x4B: t3100e_notify_set(0x0D); break; /* Left */
|
||||
case 0x4C: t3100e_notify_set(0x0E); break; /* KP 5 */
|
||||
case 0x4D: t3100e_notify_set(0x0F); break; /* Right */
|
||||
}
|
||||
}
|
||||
|
||||
key_queue[key_queue_end] = (((keyboard_mode & 0x40) && !(keyboard_mode & 0x20)) ? (nont_to_t[val] | sc_or) : val);
|
||||
key_queue_end = (key_queue_end + 1) & 0xf;
|
||||
|
||||
@@ -656,6 +680,11 @@ write_register:
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xb6: /* T3100e - set colour/mono switch */
|
||||
if (romset == ROM_T3100E)
|
||||
t3100e_mono_set(val);
|
||||
break;
|
||||
|
||||
case 0xcb: /*AMI - set keyboard mode*/
|
||||
kbdlog("AMI - set keyboard mode\n");
|
||||
break;
|
||||
@@ -924,6 +953,8 @@ bad_command:
|
||||
|
||||
case 0xaa: /*Self-test*/
|
||||
kbdlog("Self-test\n");
|
||||
if(romset == ROM_T3100E)
|
||||
kbd->status |= STAT_IFULL;
|
||||
if (! kbd->initialized) {
|
||||
kbd->initialized = 1;
|
||||
key_ctrl_queue_start = key_ctrl_queue_end = 0;
|
||||
@@ -998,10 +1029,64 @@ bad_command:
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xb0: case 0xb1: case 0xb2: case 0xb3:
|
||||
case 0xb4: case 0xb5: case 0xb6: case 0xb7:
|
||||
case 0xb8: case 0xb9: case 0xba: case 0xbb:
|
||||
case 0xbc: case 0xbd: case 0xbe: case 0xbf:
|
||||
case 0xb0: /* T3100e: Turbo on */
|
||||
if (romset == ROM_T3100E) {
|
||||
t3100e_turbo_set(1);
|
||||
break;
|
||||
}
|
||||
case 0xb1: /* T3100e: Turbo off */
|
||||
if (romset == ROM_T3100E) {
|
||||
t3100e_turbo_set(0);
|
||||
break;
|
||||
}
|
||||
case 0xb2: /* T3100e: Select external display */
|
||||
if (romset == ROM_T3100E) {
|
||||
t3100e_display_set(0x00);
|
||||
break;
|
||||
}
|
||||
case 0xb3: /* T3100e: Select internal display */
|
||||
if (romset == ROM_T3100E) {
|
||||
t3100e_display_set(0x01);
|
||||
break;
|
||||
}
|
||||
case 0xb4: /* T3100e: Get configuration / status */
|
||||
if (romset == ROM_T3100E) {
|
||||
kbd_adddata(t3100e_config_get());
|
||||
break;
|
||||
}
|
||||
case 0xb5: /* T3100e: Get colour / mono byte */
|
||||
if (romset == ROM_T3100E) {
|
||||
kbd_adddata(t3100e_mono_get());
|
||||
break;
|
||||
}
|
||||
case 0xb6: /* T3100e: Set colour / mono byte */
|
||||
if (romset == ROM_T3100E) {
|
||||
kbd->want60 = 1;
|
||||
break;
|
||||
}
|
||||
case 0xb7: /* T3100e: Emulate PS/2 keyboard - not implemented */
|
||||
case 0xb8: /* T3100e: Emulate AT keyboard - not implemented */
|
||||
if (romset == ROM_T3100E)
|
||||
break;
|
||||
case 0xbb: /* T3100e: Read 'Fn' key.
|
||||
Return it for right Ctrl and right Alt; on the real
|
||||
T3100e, these keystrokes could only be generated
|
||||
using 'Fn'. */
|
||||
if (romset == ROM_T3100E)
|
||||
{
|
||||
if (keyboard_recv(0xb8) || /* Right Alt */
|
||||
keyboard_recv(0x9d)) /* Right Ctrl */
|
||||
kbd_adddata(0x04);
|
||||
else kbd_adddata(0x00);
|
||||
break;
|
||||
}
|
||||
case 0xbc: /* T3100e: Reset Fn+Key notification */
|
||||
if (romset == ROM_T3100E) {
|
||||
t3100e_notify_set(0x00);
|
||||
break;
|
||||
}
|
||||
case 0xb9: case 0xba:
|
||||
case 0xbd: case 0xbe: case 0xbf:
|
||||
/*Set keyboard lines low (B0-B7) or high (B8-BF)*/
|
||||
kbdlog("ATkbd: set keyboard lines low (B0-B7) or high (B8-BF)\n");
|
||||
kbd_adddata(0x00);
|
||||
@@ -1009,8 +1094,17 @@ bad_command:
|
||||
|
||||
case 0xc0: /*Read input port*/
|
||||
kbdlog("ATkbd: read input port\n");
|
||||
kbd_adddata(kbd->input_port | 4 | fdc_ps1_525());
|
||||
kbd->input_port = ((kbd->input_port + 1) & 3) | (kbd->input_port & 0xfc) | fdc_ps1_525();
|
||||
|
||||
/* The T3100e returns all bits set except bit 6 which
|
||||
* is set by t3100e_mono_set() */
|
||||
if (romset == ROM_T3100E) {
|
||||
kbd->input_port = (t3100e_mono_get() & 1) ? 0xFF : 0xBF;
|
||||
kbd_adddata(kbd->input_port | 4 | fdc_ps1_525());
|
||||
kbd->input_port = ((kbd->input_port + 1) & 3) | (kbd->input_port & 0xfc);
|
||||
} else {
|
||||
kbd_adddata(kbd->input_port | 4 | fdc_ps1_525());
|
||||
kbd->input_port = ((kbd->input_port + 1) & 3) | (kbd->input_port & 0xfc) | fdc_ps1_525();
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xc1: /*Copy bits 0 to 3 of input port to status bits 4 to 7*/
|
||||
|
721
src/machine/m_at_t3100e.c
Normal file
721
src/machine/m_at_t3100e.c
Normal file
@@ -0,0 +1,721 @@
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <wchar.h>
|
||||
|
||||
#include "../86box.h"
|
||||
#include "../io.h"
|
||||
#include "../mouse.h"
|
||||
#include "../mem.h"
|
||||
#include "../device.h"
|
||||
#include "../cpu/cpu.h"
|
||||
#include "../floppy/fdd.h"
|
||||
#include "../video/vid_t3100e.h"
|
||||
|
||||
#include "machine.h"
|
||||
#include "m_at_t3100e.h"
|
||||
|
||||
/* The Toshiba 3100e is a 286-based portable.
|
||||
*
|
||||
* To bring up the BIOS setup screen hold down the 'Fn' key on booting
|
||||
*
|
||||
* Memory management
|
||||
* ~~~~~~~~~~~~~~~~~
|
||||
*
|
||||
* Motherboard memory is divided into:
|
||||
* - Conventional memory: Either 512k or 640k
|
||||
* - Upper memory: Either 512k or 384k, depending on amount of
|
||||
* conventional memory. Upper memory can be
|
||||
* used either as EMS or XMS.
|
||||
* - High memory: 0-4Mb, depending on RAM installed. The BIOS
|
||||
* setup screen allows some or all of this to be
|
||||
* used as EMS; the remainder is XMS.
|
||||
*
|
||||
* Additional memory (either EMS or XMS) can also be provided by ISA
|
||||
* expansion cards.
|
||||
*
|
||||
* Under test in PCEM, the BIOS will boot with up to 65368Kb of memory in
|
||||
* total (16Mb less 16k). However it will give an error with RAM sizes
|
||||
* above 8Mb, if any of the high memory is allocated as EMS, because the
|
||||
* builtin EMS page registers can only access up to 8Mb.
|
||||
*
|
||||
* Memory is controlled by writes to I/O port 8084h:
|
||||
* Bit 7: Always 0 }
|
||||
* Bit 6: Always 1 } These bits select which motherboard function to
|
||||
* Bit 5: Always 0 } access.
|
||||
* Bit 4: Set to treat upper RAM as XMS
|
||||
* Bit 3: Enable external RAM boards?
|
||||
* Bit 2: Set for 640k conventional memory, clear for 512k
|
||||
* Bit 1: Enable RAM beyond 1Mb.
|
||||
* Bit 0: Enable EMS.
|
||||
*
|
||||
* The last value written to this port is saved at 0040:0093h, and in
|
||||
* CMOS memory at offset 0x37. If the top bit of the CMOS byte is set,
|
||||
* then high memory is being provided by an add-on card rather than the
|
||||
* mainboard; accordingly, the BIOS will not allow high memory to be
|
||||
* used as EMS.
|
||||
*
|
||||
* EMS is controlled by 16 page registers:
|
||||
*
|
||||
* Page mapped at 0xD000 0xD400 0xD800 0xDC00
|
||||
* ------------------------------------------------------
|
||||
* Pages 0x00-0x7F 0x208 0x4208 0x8208 0xc208
|
||||
* Pages 0x80-0xFF 0x218 0x4218 0x8218 0xc218
|
||||
* Pages 0x100-0x17F 0x258 0x4258 0x8258 0xc258
|
||||
* Pages 0x180-0x1FF 0x268 0x4268 0x8268 0xc268
|
||||
*
|
||||
* The value written has bit 7 set to enable EMS, reset to disable it.
|
||||
*
|
||||
* So: OUT 0x208, 0x80 will page in the first 16k page at 0xD0000.
|
||||
* OUT 0x208, 0x00 will page out EMS, leaving nothing at 0xD0000.
|
||||
* OUT 0x4208, 0x80 will page in the first 16k page at 0xD4000.
|
||||
* OUT 0x218, 0x80 will page in the 129th 16k page at 0xD0000.
|
||||
*
|
||||
* etc.
|
||||
*
|
||||
* To use EMS from DOS, you will need the Toshiba EMS driver (TOSHEMM.ZIP).
|
||||
* This supports the above system, plus further ranges of ports at
|
||||
* 0x_2A8, 0x_2B8, 0x_2C8.
|
||||
*
|
||||
*/
|
||||
|
||||
static const int t3100e_log = 0;
|
||||
|
||||
extern uint8_t *ram; /* Physical RAM */
|
||||
|
||||
/* Features not implemented:
|
||||
* > Four video fonts.
|
||||
* > BIOS-controlled mapping of serial ports to IRQs.
|
||||
* > Custom keyboard controller. This has a number of extra commands in the
|
||||
* 0xB0-0xBC range, for such things as turbo on/off, and switching the
|
||||
* keyboard between AT and PS/2 modes. Currently I have only implemented
|
||||
* command 0xBB, so that self-test completes successfully. Commands include:
|
||||
*
|
||||
* 0xB0: Turbo on
|
||||
* 0xB1: Turbo off
|
||||
* 0xB2: Internal display on?
|
||||
* 0xB3: Internal display off?
|
||||
* 0xB5: Get settings byte (bottom bit is colour / mono setting)
|
||||
* 0xB6: Set settings byte
|
||||
* 0xB7: Behave as 101-key PS/2 keyboard
|
||||
* 0xB8: Behave as 84-key AT keyboard
|
||||
* 0xBB: Return a byte, bit 2 is Fn key state, other bits unknown.
|
||||
*
|
||||
* The other main I/O port needed to POST is:
|
||||
* 0x8084: System control.
|
||||
* Top 3 bits give command, bottom 5 bits give parameters.
|
||||
* 000 => set serial port IRQ / addresses
|
||||
* bit 4: IRQ5 serial port base: 1 => 0x338, 0 => 0x3E8
|
||||
* bits 3, 2, 0 specify serial IRQs for COM1, COM2, COM3:
|
||||
* 00 0 => 4, 3, 5
|
||||
* 00 1 => 4, 5, 3
|
||||
* 01 0 => 3, 4, 5
|
||||
* 01 1 => 3, 5, 4
|
||||
* 10 0 => 4, -, 3
|
||||
* 10 1 => 3, -, 4
|
||||
* 010 => set memory mappings
|
||||
* bit 4 set if upper RAM is XMS
|
||||
* bit 3 enable add-on memory boards beyond 5Mb?
|
||||
* bit 2 set for 640k sysram, clear for 512k sysram
|
||||
* bit 1 enable mainboard XMS
|
||||
* bit 0 enable mainboard EMS
|
||||
* 100 => set parallel mode / LCD settings
|
||||
* bit 4 set for bidirectional parallel port
|
||||
* bit 3 set to disable internal CGA
|
||||
* bit 2 set for single-pixel LCD font
|
||||
* bits 0,1 for display font
|
||||
*/
|
||||
|
||||
void at_init();
|
||||
|
||||
/* The T3100e motherboard can (and does) dynamically reassign RAM between
|
||||
* conventional, XMS and EMS. This translates to monkeying with the mappings.
|
||||
*/
|
||||
|
||||
extern mem_mapping_t base_mapping;
|
||||
|
||||
extern mem_mapping_t ram_low_mapping; /* This is to switch conventional RAM
|
||||
* between 512k and 640k */
|
||||
|
||||
extern mem_mapping_t ram_mid_mapping; /* This will not be used */
|
||||
|
||||
extern mem_mapping_t ram_high_mapping; /* This is RAM beyond 1Mb if any */
|
||||
|
||||
extern uint8_t *ram;
|
||||
|
||||
static unsigned t3100e_ems_page_reg[] =
|
||||
{
|
||||
0x208, 0x4208, 0x8208, 0xc208, /* The first four map the first 2Mb */
|
||||
/* of RAM into the page frame */
|
||||
0x218, 0x4218, 0x8218, 0xc218, /* The next four map the next 2Mb */
|
||||
/* of RAM */
|
||||
0x258, 0x4258, 0x8258, 0xc258, /* and so on. */
|
||||
0x268, 0x4268, 0x8268, 0xc268,
|
||||
};
|
||||
|
||||
struct t3100e_ems_regs
|
||||
{
|
||||
uint8_t page[16];
|
||||
mem_mapping_t mapping[4];
|
||||
uint32_t page_exec[4]; /* Physical location of memory pages */
|
||||
uint32_t upper_base; /* Start of upper RAM */
|
||||
uint8_t upper_pages; /* Pages of EMS available from upper RAM */
|
||||
uint8_t upper_is_ems; /* Upper RAM is EMS? */
|
||||
mem_mapping_t upper_mapping;
|
||||
uint8_t notify; /* Notification from keyboard controller */
|
||||
uint8_t turbo; /* 0 for 6MHz, else full speed */
|
||||
uint8_t mono; /* Emulates PC/AT 'mono' motherboard switch */
|
||||
/* Bit 0 is 0 for colour, 1 for mono */
|
||||
} t3100e_ems;
|
||||
|
||||
void t3100e_ems_out(uint16_t addr, uint8_t val, void *p);
|
||||
|
||||
|
||||
/* Given a memory address (which ought to be in the page frame at 0xD0000),
|
||||
* which page does it relate to? */
|
||||
static int addr_to_page(uint32_t addr)
|
||||
{
|
||||
if ((addr & 0xF0000) == 0xD0000)
|
||||
{
|
||||
return ((addr >> 14) & 3);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* And vice versa: Given a page slot, which memory address does it
|
||||
* correspond to? */
|
||||
static uint32_t page_to_addr(int pg)
|
||||
{
|
||||
return 0xD0000 + ((pg & 3) * 16384);
|
||||
}
|
||||
|
||||
/* Given an EMS page ID, return its physical address in RAM. */
|
||||
uint32_t t3100e_ems_execaddr(struct t3100e_ems_regs *regs,
|
||||
int pg, uint16_t val)
|
||||
{
|
||||
uint32_t addr;
|
||||
|
||||
if (!(val & 0x80)) return 0; /* Bit 7 reset => not mapped */
|
||||
|
||||
val &= 0x7F;
|
||||
val += (0x80 * (pg >> 2)); /* The high bits of the register bank */
|
||||
/* are used to extend val to allow up */
|
||||
/* to 8Mb of EMS to be accessed */
|
||||
|
||||
/* Is it in the upper memory range? */
|
||||
if (regs->upper_is_ems)
|
||||
{
|
||||
if (val < regs->upper_pages)
|
||||
{
|
||||
addr = regs->upper_base + 0x4000 * val;
|
||||
return addr;
|
||||
}
|
||||
val -= regs->upper_pages;
|
||||
}
|
||||
/* Otherwise work down from the top of high RAM (so, the more EMS,
|
||||
* the less XMS) */
|
||||
if ((val * 0x4000) + 0x100000 >= (mem_size * 1024))
|
||||
{
|
||||
return 0; /* Not enough high RAM for this page */
|
||||
}
|
||||
/* High RAM found */
|
||||
addr = (mem_size * 1024) - 0x4000 * (val + 1);
|
||||
|
||||
return addr;
|
||||
}
|
||||
|
||||
|
||||
/* The registers governing the EMS ports are in rather a nonintuitive order */
|
||||
static int port_to_page(uint16_t addr)
|
||||
{
|
||||
switch (addr)
|
||||
{
|
||||
case 0x208: return 0;
|
||||
case 0x4208: return 1;
|
||||
case 0x8208: return 2;
|
||||
case 0xC208: return 3;
|
||||
case 0x218: return 4;
|
||||
case 0x4218: return 5;
|
||||
case 0x8218: return 6;
|
||||
case 0xC218: return 7;
|
||||
case 0x258: return 8;
|
||||
case 0x4258: return 9;
|
||||
case 0x8258: return 10;
|
||||
case 0xC258: return 11;
|
||||
case 0x268: return 12;
|
||||
case 0x4268: return 13;
|
||||
case 0x8268: return 14;
|
||||
case 0xC268: return 15;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Used to dump the memory mapping table, for debugging
|
||||
void dump_mappings()
|
||||
{
|
||||
mem_mapping_t *mm = base_mapping.next;
|
||||
|
||||
if (!t3100e_log) return;
|
||||
while (mm)
|
||||
{
|
||||
const char *name = "";
|
||||
uint32_t offset = (uint32_t)(mm->exec - ram);
|
||||
|
||||
if (mm == &ram_low_mapping ) name = "LOW ";
|
||||
if (mm == &ram_mid_mapping ) name = "MID ";
|
||||
if (mm == &ram_high_mapping) name = "HIGH";
|
||||
if (mm == &t3100e_ems.upper_mapping) name = "UPPR";
|
||||
if (mm == &t3100e_ems.mapping[0])
|
||||
{
|
||||
name = "EMS0";
|
||||
offset = t3100e_ems.page_exec[0];
|
||||
}
|
||||
if (mm == &t3100e_ems.mapping[1])
|
||||
{
|
||||
name = "EMS1";
|
||||
offset = t3100e_ems.page_exec[1];
|
||||
}
|
||||
if (mm == &t3100e_ems.mapping[2])
|
||||
{
|
||||
name = "EMS2";
|
||||
offset = t3100e_ems.page_exec[2];
|
||||
}
|
||||
if (mm == &t3100e_ems.mapping[3])
|
||||
{
|
||||
name = "EMS3";
|
||||
offset = t3100e_ems.page_exec[3];
|
||||
}
|
||||
|
||||
pclog(" %p | base=%05x size=%05x %c @ %06x %s\n", mm,
|
||||
mm->base, mm->size, mm->enable ? 'Y' : 'N',
|
||||
offset, name);
|
||||
|
||||
mm = mm->next;
|
||||
}
|
||||
}*/
|
||||
|
||||
void t3100e_map_ram(uint8_t val)
|
||||
{
|
||||
int n;
|
||||
int32_t upper_len;
|
||||
|
||||
if (t3100e_log)
|
||||
{
|
||||
pclog("OUT 0x8084, %02x [ set memory mapping :", val | 0x40);
|
||||
if (val & 1) pclog("ENABLE_EMS ");
|
||||
if (val & 2) pclog("ENABLE_XMS ");
|
||||
if (val & 4) pclog("640K ");
|
||||
if (val & 8) pclog("X8X ");
|
||||
if (val & 16) pclog("UPPER_IS_XMS ");
|
||||
pclog("\n");
|
||||
}
|
||||
/* Bit 2 controls size of conventional memory */
|
||||
if (val & 4)
|
||||
{
|
||||
t3100e_ems.upper_base = 0xA0000;
|
||||
t3100e_ems.upper_pages = 24;
|
||||
}
|
||||
else
|
||||
{
|
||||
t3100e_ems.upper_base = 0x80000;
|
||||
t3100e_ems.upper_pages = 32;
|
||||
}
|
||||
upper_len = t3100e_ems.upper_pages * 16384;
|
||||
|
||||
mem_mapping_set_addr(&ram_low_mapping, 0, t3100e_ems.upper_base);
|
||||
/* Bit 0 set if upper RAM is EMS */
|
||||
t3100e_ems.upper_is_ems = (val & 1);
|
||||
|
||||
/* Bit 1 set if high RAM is enabled */
|
||||
if (val & 2)
|
||||
{
|
||||
mem_mapping_enable(&ram_high_mapping);
|
||||
}
|
||||
else
|
||||
{
|
||||
mem_mapping_disable(&ram_high_mapping);
|
||||
}
|
||||
|
||||
/* Bit 4 set if upper RAM is mapped to high memory
|
||||
* (and bit 1 set if XMS enabled) */
|
||||
if ((val & 0x12) == 0x12)
|
||||
{
|
||||
mem_mapping_set_addr(&t3100e_ems.upper_mapping,
|
||||
mem_size * 1024,
|
||||
upper_len);
|
||||
mem_mapping_enable(&t3100e_ems.upper_mapping);
|
||||
mem_mapping_set_exec(&t3100e_ems.upper_mapping, ram + t3100e_ems.upper_base);
|
||||
}
|
||||
else
|
||||
{
|
||||
mem_mapping_disable(&t3100e_ems.upper_mapping);
|
||||
}
|
||||
/* Recalculate EMS mappings */
|
||||
for (n = 0; n < 4; n++)
|
||||
{
|
||||
t3100e_ems_out(t3100e_ems_page_reg[n], t3100e_ems.page[n],
|
||||
&t3100e_ems);
|
||||
}
|
||||
|
||||
//dump_mappings();
|
||||
}
|
||||
|
||||
|
||||
void t3100e_notify_set(uint8_t value)
|
||||
{
|
||||
t3100e_ems.notify = value;
|
||||
}
|
||||
|
||||
void t3100e_mono_set(uint8_t value)
|
||||
{
|
||||
t3100e_ems.mono = value;
|
||||
}
|
||||
|
||||
uint8_t t3100e_mono_get(void)
|
||||
{
|
||||
return t3100e_ems.mono;
|
||||
}
|
||||
|
||||
void t3100e_turbo_set(uint8_t value)
|
||||
{
|
||||
t3100e_ems.turbo = value;
|
||||
if (!value)
|
||||
{
|
||||
int c = cpu;
|
||||
cpu = 0; /* 286/6 */
|
||||
cpu_set();
|
||||
cpu = c;
|
||||
}
|
||||
else
|
||||
{
|
||||
cpu_set();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
uint8_t t3100e_sys_in(uint16_t addr, void *p)
|
||||
{
|
||||
struct t3100e_ems_regs *regs = (struct t3100e_ems_regs *)p;
|
||||
|
||||
/* The low 4 bits always seem to be 0x0C. The high 4 are a
|
||||
* notification sent by the keyboard controller when it detects
|
||||
* an [Fn] key combination */
|
||||
if (t3100e_log) pclog("IN 0x8084\n");
|
||||
return 0x0C | (regs->notify << 4);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Handle writes to the T3100e system control port at 0x8084 */
|
||||
void t3100e_sys_out(uint16_t addr, uint8_t val, void *p)
|
||||
{
|
||||
// struct t3100e_ems_regs *regs = (struct t3100e_ems_regs *)p;
|
||||
|
||||
switch (val & 0xE0)
|
||||
{
|
||||
case 0x00: /* Set serial port IRQs. Not implemented */
|
||||
if (t3100e_log) pclog("OUT 0x8084, %02x [ set serial port IRQs]\n", val);
|
||||
break;
|
||||
case 0x40: /* Set RAM mappings. */
|
||||
t3100e_map_ram(val & 0x1F);
|
||||
break;
|
||||
|
||||
case 0x80: /* Set video options. */
|
||||
t3100e_video_options_set(val & 0x1F); break;
|
||||
|
||||
/* Other options not implemented. */
|
||||
default: if (t3100e_log) pclog("OUT 0x8084, %02x\n", val); break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
uint8_t t3100e_config_get(void)
|
||||
{
|
||||
/* The byte returned:
|
||||
Bit 7: Set if internal plasma display enabled
|
||||
Bit 6: Set if running at 6MHz, clear at full speed
|
||||
Bit 5: Always 1?
|
||||
Bit 4: Set if the FD2MB jumper is present (internal floppy is ?tri-mode)
|
||||
Bit 3: Clear if the FD2 jumper is present (two internal floppies)
|
||||
Bit 2: Set if the internal drive is A:, clear if B:
|
||||
Bit 1: Set if the parallel port is configured as a floppy connector
|
||||
for the second drive.
|
||||
Bit 0: Set if the F2HD jumper is present (internal floppy is 720k)
|
||||
*/
|
||||
uint8_t value = 0x28; /* Start with bits 5 and 3 set. */
|
||||
|
||||
int type_a = fdd_get_type(0);
|
||||
int type_b = fdd_get_type(1);
|
||||
int prt_switch; /* External drive type: 0=> none, 1=>A, 2=>B */
|
||||
|
||||
/* Get display setting */
|
||||
if (t3100e_display_get()) value |= 0x80;
|
||||
if (!t3100e_ems.turbo) value |= 0x40;
|
||||
|
||||
/* Try to determine the floppy types.*/
|
||||
|
||||
prt_switch = (type_b ? 2 : 0);
|
||||
switch(type_a)
|
||||
{
|
||||
/* Since a T3100e cannot have an internal 5.25" drive, mark 5.25" A: drive as
|
||||
* being external, and set the internal type based on type_b. */
|
||||
case 1: /* 360k */
|
||||
case 2: /* 1.2Mb */
|
||||
case 3: /* 1.2Mb RPMx2*/
|
||||
prt_switch = 1; /* External drive is A: */
|
||||
switch (type_b)
|
||||
{
|
||||
case 1: /* 360k */
|
||||
case 4: value |= 1; break; /* 720k */
|
||||
case 6: value |= 0x10; break; /* Tri-mode */
|
||||
/* All others will be treated as 1.4M */
|
||||
}
|
||||
break;
|
||||
case 4: value |= 0x01; /* 720k */
|
||||
if (type_a == type_b)
|
||||
{
|
||||
value &= (~8); /* Two internal drives */
|
||||
prt_switch = 0; /* No external drive */
|
||||
}
|
||||
break;
|
||||
case 5: /* 1.4M */
|
||||
case 7: /* 2.8M */
|
||||
if (type_a == type_b)
|
||||
{
|
||||
value &= (~8); /* Two internal drives */
|
||||
prt_switch = 0; /* No external drive */
|
||||
}
|
||||
break;
|
||||
case 6: /* 3-mode */
|
||||
value |= 0x10;
|
||||
if (type_a == type_b)
|
||||
{
|
||||
value &= (~8); /* Two internal drives */
|
||||
prt_switch = 0; /* No external drive */
|
||||
}
|
||||
break;
|
||||
} /* End switch */
|
||||
switch (prt_switch)
|
||||
{
|
||||
case 0: value |= 4; break; /* No external floppy */
|
||||
case 1: value |= 2; break; /* External floppy is A: */
|
||||
case 2: value |= 6; break; /* External floppy is B: */
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
/* Read EMS page register */
|
||||
uint8_t t3100e_ems_in(uint16_t addr, void *p)
|
||||
{
|
||||
struct t3100e_ems_regs *regs = (struct t3100e_ems_regs *)p;
|
||||
|
||||
return regs->page[port_to_page(addr)];
|
||||
|
||||
}
|
||||
|
||||
/* Write EMS page register */
|
||||
void t3100e_ems_out(uint16_t addr, uint8_t val, void *p)
|
||||
{
|
||||
struct t3100e_ems_regs *regs = (struct t3100e_ems_regs *)p;
|
||||
int pg = port_to_page(addr);
|
||||
|
||||
regs->page_exec[pg & 3] = t3100e_ems_execaddr(regs, pg, val);
|
||||
if (t3100e_log) pclog("EMS: page %d %02x -> %02x [%06x]\n",
|
||||
pg, regs->page[pg], val, regs->page_exec[pg & 3]);
|
||||
regs->page[pg] = val;
|
||||
|
||||
pg &= 3;
|
||||
/* Bit 7 set if page is enabled, reset if page is disabled */
|
||||
if (regs->page_exec[pg])
|
||||
{
|
||||
if (t3100e_log) pclog("Enabling EMS RAM at %05x\n",
|
||||
page_to_addr(pg));
|
||||
mem_mapping_enable(®s->mapping[pg]);
|
||||
mem_mapping_set_exec(®s->mapping[pg], ram + regs->page_exec[pg]);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (t3100e_log) pclog("Disabling EMS RAM at %05x\n",
|
||||
page_to_addr(pg));
|
||||
mem_mapping_disable(®s->mapping[pg]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Read RAM in the EMS page frame */
|
||||
static uint8_t ems_read_ram(uint32_t addr, void *priv)
|
||||
{
|
||||
struct t3100e_ems_regs *regs = (struct t3100e_ems_regs *)priv;
|
||||
int pg = addr_to_page(addr);
|
||||
|
||||
if (pg < 0) return 0xFF;
|
||||
addr = regs->page_exec[pg] + (addr & 0x3FFF);
|
||||
return ram[addr];
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
static uint16_t ems_read_ramw(uint32_t addr, void *priv)
|
||||
{
|
||||
struct t3100e_ems_regs *regs = (struct t3100e_ems_regs *)priv;
|
||||
int pg = addr_to_page(addr);
|
||||
|
||||
if (pg < 0) return 0xFF;
|
||||
//pclog("ems_read_ramw addr=%05x ", addr);
|
||||
addr = regs->page_exec[pg] + (addr & 0x3FFF);
|
||||
//pclog("-> %06x val=%04x\n", addr, *(uint16_t *)&ram[addr]);
|
||||
return *(uint16_t *)&ram[addr];
|
||||
}
|
||||
|
||||
|
||||
static uint32_t ems_read_raml(uint32_t addr, void *priv)
|
||||
{
|
||||
struct t3100e_ems_regs *regs = (struct t3100e_ems_regs *)priv;
|
||||
int pg = addr_to_page(addr);
|
||||
|
||||
if (pg < 0) return 0xFF;
|
||||
addr = regs->page_exec[pg] + (addr & 0x3FFF);
|
||||
return *(uint32_t *)&ram[addr];
|
||||
}
|
||||
|
||||
/* Write RAM in the EMS page frame */
|
||||
static void ems_write_ram(uint32_t addr, uint8_t val, void *priv)
|
||||
{
|
||||
struct t3100e_ems_regs *regs = (struct t3100e_ems_regs *)priv;
|
||||
int pg = addr_to_page(addr);
|
||||
|
||||
if (pg < 0) return;
|
||||
addr = regs->page_exec[pg] + (addr & 0x3FFF);
|
||||
ram[addr] = val;
|
||||
}
|
||||
|
||||
|
||||
static void ems_write_ramw(uint32_t addr, uint16_t val, void *priv)
|
||||
{
|
||||
struct t3100e_ems_regs *regs = (struct t3100e_ems_regs *)priv;
|
||||
int pg = addr_to_page(addr);
|
||||
|
||||
if (pg < 0) return;
|
||||
//pclog("ems_write_ramw addr=%05x ", addr);
|
||||
addr = regs->page_exec[pg] + (addr & 0x3FFF);
|
||||
//pclog("-> %06x val=%04x\n", addr, val);
|
||||
|
||||
*(uint16_t *)&ram[addr] = val;
|
||||
}
|
||||
|
||||
|
||||
static void ems_write_raml(uint32_t addr, uint32_t val, void *priv)
|
||||
{
|
||||
struct t3100e_ems_regs *regs = (struct t3100e_ems_regs *)priv;
|
||||
int pg = addr_to_page(addr);
|
||||
|
||||
if (pg < 0) return;
|
||||
addr = regs->page_exec[pg] + (addr & 0x3FFF);
|
||||
*(uint32_t *)&ram[addr] = val;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Read RAM in the upper area. This is basically what the 'remapped'
|
||||
* mapping in mem.c does, except that the upper area can move around */
|
||||
static uint8_t upper_read_ram(uint32_t addr, void *priv)
|
||||
{
|
||||
struct t3100e_ems_regs *regs = (struct t3100e_ems_regs *)priv;
|
||||
|
||||
addr = (addr - (1024 * mem_size)) + regs->upper_base;
|
||||
return ram[addr];
|
||||
}
|
||||
|
||||
static uint16_t upper_read_ramw(uint32_t addr, void *priv)
|
||||
{
|
||||
struct t3100e_ems_regs *regs = (struct t3100e_ems_regs *)priv;
|
||||
|
||||
addr = (addr - (1024 * mem_size)) + regs->upper_base;
|
||||
return *(uint16_t *)&ram[addr];
|
||||
}
|
||||
|
||||
static uint32_t upper_read_raml(uint32_t addr, void *priv)
|
||||
{
|
||||
struct t3100e_ems_regs *regs = (struct t3100e_ems_regs *)priv;
|
||||
|
||||
addr = (addr - (1024 * mem_size)) + regs->upper_base;
|
||||
return *(uint32_t *)&ram[addr];
|
||||
}
|
||||
|
||||
|
||||
static void upper_write_ram(uint32_t addr, uint8_t val, void *priv)
|
||||
{
|
||||
struct t3100e_ems_regs *regs = (struct t3100e_ems_regs *)priv;
|
||||
|
||||
addr = (addr - (1024 * mem_size)) + regs->upper_base;
|
||||
ram[addr] = val;
|
||||
}
|
||||
|
||||
|
||||
static void upper_write_ramw(uint32_t addr, uint16_t val, void *priv)
|
||||
{
|
||||
struct t3100e_ems_regs *regs = (struct t3100e_ems_regs *)priv;
|
||||
|
||||
addr = (addr - (1024 * mem_size)) + regs->upper_base;
|
||||
*(uint16_t *)&ram[addr] = val;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void upper_write_raml(uint32_t addr, uint32_t val, void *priv)
|
||||
{
|
||||
struct t3100e_ems_regs *regs = (struct t3100e_ems_regs *)priv;
|
||||
|
||||
addr = (addr - (1024 * mem_size)) + regs->upper_base;
|
||||
*(uint32_t *)&ram[addr] = val;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void machine_at_t3100e_init(machine_t *model)
|
||||
{
|
||||
int pg;
|
||||
|
||||
memset(&t3100e_ems, 0, sizeof(t3100e_ems));
|
||||
|
||||
machine_at_ide_init(model);
|
||||
/* Hook up system control port */
|
||||
io_sethandler(0x8084, 0x0001,
|
||||
t3100e_sys_in, NULL, NULL,
|
||||
t3100e_sys_out, NULL, NULL, &t3100e_ems);
|
||||
|
||||
/* Start monitoring all 16 EMS registers */
|
||||
for (pg = 0; pg < 16; pg++)
|
||||
{
|
||||
io_sethandler(t3100e_ems_page_reg[pg], 0x0001,
|
||||
t3100e_ems_in, NULL, NULL,
|
||||
t3100e_ems_out, NULL, NULL, &t3100e_ems);
|
||||
}
|
||||
|
||||
/* Map the EMS page frame */
|
||||
for (pg = 0; pg < 4; pg++)
|
||||
{
|
||||
if (t3100e_log) pclog("Adding memory map at %x for page %d\n", page_to_addr(pg), pg);
|
||||
mem_mapping_add(&t3100e_ems.mapping[pg],
|
||||
page_to_addr(pg), 16384,
|
||||
ems_read_ram, ems_read_ramw, ems_read_raml,
|
||||
ems_write_ram, ems_write_ramw, ems_write_raml,
|
||||
NULL, MEM_MAPPING_EXTERNAL,
|
||||
&t3100e_ems);
|
||||
/* Start them all off disabled */
|
||||
mem_mapping_disable(&t3100e_ems.mapping[pg]);
|
||||
}
|
||||
/* Mapping for upper RAM when in use as XMS*/
|
||||
mem_mapping_add(&t3100e_ems.upper_mapping, mem_size * 1024, 384 * 1024,
|
||||
upper_read_ram, upper_read_ramw, upper_read_raml,
|
||||
upper_write_ram, upper_write_ramw, upper_write_raml,
|
||||
NULL, MEM_MAPPING_INTERNAL, &t3100e_ems);
|
||||
mem_mapping_disable(&t3100e_ems.upper_mapping);
|
||||
|
||||
device_add(&t3100e_device);
|
||||
}
|
7
src/machine/m_at_t3100e.h
Normal file
7
src/machine/m_at_t3100e.h
Normal file
@@ -0,0 +1,7 @@
|
||||
void t3100e_notify_set(uint8_t value);
|
||||
void t3100e_display_set(uint8_t value);
|
||||
uint8_t t3100e_display_get();
|
||||
uint8_t t3100e_config_get();
|
||||
void t3100e_turbo_set(uint8_t value);
|
||||
uint8_t t3100e_mono_get();
|
||||
void t3100e_mono_set(uint8_t value);
|
@@ -100,6 +100,8 @@ extern void machine_at_ide_init(machine_t *);
|
||||
extern void machine_at_top_remap_init(machine_t *);
|
||||
extern void machine_at_ide_top_remap_init(machine_t *);
|
||||
|
||||
extern void machine_at_t3100e_init(machine_t *);
|
||||
|
||||
extern void machine_at_p54tp4xe_init(machine_t *);
|
||||
extern void machine_at_endeavor_init(machine_t *);
|
||||
extern void machine_at_zappa_init(machine_t *);
|
||||
|
@@ -11,7 +11,7 @@
|
||||
* NOTES: OpenAT wip for 286-class machine with open BIOS.
|
||||
* PS2_M80-486 wip, pending receipt of TRM's for machine.
|
||||
*
|
||||
* Version: @(#)machine_table.c 1.0.8 2017/12/29
|
||||
* Version: @(#)machine_table.c 1.0.9 2017/12/31
|
||||
*
|
||||
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
@@ -72,8 +72,9 @@ machine_t machines[] = {
|
||||
{ "[286 ISA] IBM XT Model 286", ROM_IBMXT286, "ibmxt286", {{"", cpus_ibmxt286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT, 256,15872, 128, 63, machine_at_top_remap_init, NULL, nvr_at_close },
|
||||
{ "[286 ISA] Samsung SPC-4200P", ROM_SPC4200P, "spc4200p", {{"", cpus_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT | MACHINE_PS2, 512, 2048, 128, 127, machine_at_scat_init, NULL, nvr_at_close },
|
||||
#ifdef WALTJE
|
||||
{ "[286 ISA] OpenAT 286", ROM_OPENAT, "open_at", {{"", cpus_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT, 512, 4096, 128, 127, machine_at_init, NULL, nvr_at_close },
|
||||
{ "[286 ISA] OpenAT 286", ROM_OPENAT, "open_at", {{"", cpus_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT, 512, 4096, 128, 127, machine_at_init, NULL, nvr_at_close },
|
||||
#endif
|
||||
{ "[286 ISA] Toshiba 3100e", ROM_T3100E, "t3100e", {{"", cpus_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 1, MACHINE_ISA | MACHINE_AT | MACHINE_HDC, 1024, 5120, 256, 63, machine_at_t3100e_init, NULL, nvr_at_close },
|
||||
|
||||
{ "[286 MCA] IBM PS/2 model 50", ROM_IBMPS2_M50, "ibmps2_m50", {{"", cpus_ps2_m30_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 1, MACHINE_MCA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC_PS2, 1, 16, 1, 63, machine_ps2_model_50_init, NULL, nvr_at_close },
|
||||
|
||||
|
@@ -13,7 +13,7 @@
|
||||
* - c386sx16 BIOS fails checksum
|
||||
* - the loadfont() calls should be done elsewhere
|
||||
*
|
||||
* Version: @(#)rom.c 1.0.22 2017/12/29
|
||||
* Version: @(#)rom.c 1.0.23 2017/12/31
|
||||
*
|
||||
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
@@ -819,6 +819,13 @@ rom_load_bios(int rom_id)
|
||||
return(1);
|
||||
#endif
|
||||
|
||||
case ROM_T3100E:
|
||||
loadfont(L"roms/machines/t3100e/t3100e_font.bin", 5);
|
||||
if (rom_load_linear(
|
||||
L"roms/machines/t3100e/t3100e.rom",
|
||||
0x000000, 65536, 0, rom)) return(1);
|
||||
break;
|
||||
|
||||
default:
|
||||
pclog("ROM: don't know how to handle ROM set %d !\n", rom_id);
|
||||
}
|
||||
|
@@ -8,7 +8,7 @@
|
||||
*
|
||||
* Definitions for the ROM image handler.
|
||||
*
|
||||
* Version: @(#)rom.h 1.0.8 2017/12/29
|
||||
* Version: @(#)rom.h 1.0.9 2017/12/31
|
||||
*
|
||||
* Author: Fred N. van Kempen, <decwiz@yahoo.com>
|
||||
* Copyright 2017 Fred N. van Kempen.
|
||||
@@ -140,6 +140,8 @@ enum {
|
||||
ROM_OPENAT, /* PC/AT clone with Open BIOS */
|
||||
#endif
|
||||
|
||||
ROM_T3100E,
|
||||
|
||||
ROM_MAX
|
||||
};
|
||||
|
||||
|
@@ -8,7 +8,7 @@
|
||||
*
|
||||
* Emulation of the old and new IBM CGA graphics cards.
|
||||
*
|
||||
* Version: @(#)vid_cga.c 1.0.11 2017/12/28
|
||||
* Version: @(#)vid_cga.c 1.0.12 2017/12/31
|
||||
*
|
||||
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
@@ -221,12 +221,12 @@ void cga_poll(void *p)
|
||||
if (drawcursor)
|
||||
{
|
||||
for (c = 0; c < 8; c++)
|
||||
buffer->line[cga->displine][(x << 3) + c + 8] = cols[(fontdat[chr][cga->sc & 7] & (1 << (c ^ 7))) ? 1 : 0] ^ 15;
|
||||
buffer->line[cga->displine][(x << 3) + c + 8] = cols[(fontdat[chr + cga->fontbase][cga->sc & 7] & (1 << (c ^ 7))) ? 1 : 0] ^ 15;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (c = 0; c < 8; c++)
|
||||
buffer->line[cga->displine][(x << 3) + c + 8] = cols[(fontdat[chr][cga->sc & 7] & (1 << (c ^ 7))) ? 1 : 0];
|
||||
buffer->line[cga->displine][(x << 3) + c + 8] = cols[(fontdat[chr + cga->fontbase][cga->sc & 7] & (1 << (c ^ 7))) ? 1 : 0];
|
||||
}
|
||||
cga->ma++;
|
||||
}
|
||||
@@ -253,12 +253,12 @@ void cga_poll(void *p)
|
||||
if (drawcursor)
|
||||
{
|
||||
for (c = 0; c < 8; c++)
|
||||
buffer->line[cga->displine][(x << 4)+(c << 1) + 8] = buffer->line[cga->displine][(x << 4) + (c << 1) + 1 + 8] = cols[(fontdat[chr][cga->sc & 7] & (1 << (c ^ 7))) ? 1 : 0] ^ 15;
|
||||
buffer->line[cga->displine][(x << 4)+(c << 1) + 8] = buffer->line[cga->displine][(x << 4) + (c << 1) + 1 + 8] = cols[(fontdat[chr + cga->fontbase][cga->sc & 7] & (1 << (c ^ 7))) ? 1 : 0] ^ 15;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (c = 0; c < 8; c++)
|
||||
buffer->line[cga->displine][(x << 4) + (c << 1) + 8] = buffer->line[cga->displine][(x << 4) + (c << 1) + 1 + 8] = cols[(fontdat[chr][cga->sc & 7] & (1 << (c ^ 7))) ? 1 : 0];
|
||||
buffer->line[cga->displine][(x << 4) + (c << 1) + 8] = buffer->line[cga->displine][(x << 4) + (c << 1) + 1 + 8] = cols[(fontdat[chr + cga->fontbase][cga->sc & 7] & (1 << (c ^ 7))) ? 1 : 0];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -8,7 +8,7 @@
|
||||
*
|
||||
* Emulation of the old and new IBM CGA graphics cards.
|
||||
*
|
||||
* Version: @(#)vid_cga.h 1.0.1 2017/12/29
|
||||
* Version: @(#)vid_cga.h 1.0.2 2017/12/31
|
||||
*
|
||||
* Author: Sarah Walker, <http://pcem-emulator.co.uk/>
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
@@ -27,6 +27,7 @@ typedef struct cga_t
|
||||
|
||||
uint8_t cgamode, cgacol;
|
||||
|
||||
int fontbase;
|
||||
int linepos, displine;
|
||||
int sc, vc;
|
||||
int cgadispon;
|
||||
|
@@ -132,12 +132,12 @@ void compaq_cga_poll(void *p)
|
||||
else if (drawcursor)
|
||||
{
|
||||
for (c = 0; c < 8; c++)
|
||||
((uint32_t *)buffer32->line[self->cga.displine])[(x << 3) + c + 8] = cols[(fontdatm[chr][self->cga.sc & 15] & (1 << (c ^ 7))) ? 1 : 0] ^ 0xffffff;
|
||||
((uint32_t *)buffer32->line[self->cga.displine])[(x << 3) + c + 8] = cols[(fontdatm[chr + self->cga.fontbase][self->cga.sc & 15] & (1 << (c ^ 7))) ? 1 : 0] ^ 0xffffff;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (c = 0; c < 8; c++)
|
||||
((uint32_t *)buffer32->line[self->cga.displine])[(x << 3) + c + 8] = cols[(fontdatm[chr][self->cga.sc & 15] & (1 << (c ^ 7))) ? 1 : 0];
|
||||
((uint32_t *)buffer32->line[self->cga.displine])[(x << 3) + c + 8] = cols[(fontdatm[chr + self->cga.fontbase][self->cga.sc & 15] & (1 << (c ^ 7))) ? 1 : 0];
|
||||
}
|
||||
self->cga.ma++;
|
||||
}
|
||||
@@ -187,13 +187,13 @@ void compaq_cga_poll(void *p)
|
||||
{
|
||||
for (c = 0; c < 8; c++)
|
||||
((uint32_t *)buffer32->line[self->cga.displine])[(x << 4)+(c << 1) + 8] =
|
||||
((uint32_t *)buffer32->line[self->cga.displine])[(x << 4) + (c << 1) + 1 + 8] = cols[(fontdatm[chr][self->cga.sc & 15] & (1 << (c ^ 7))) ? 1 : 0] ^ 15;
|
||||
((uint32_t *)buffer32->line[self->cga.displine])[(x << 4) + (c << 1) + 1 + 8] = cols[(fontdatm[chr + self->cga.fontbase][self->cga.sc & 15] & (1 << (c ^ 7))) ? 1 : 0] ^ 15;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (c = 0; c < 8; c++)
|
||||
((uint32_t *)buffer32->line[self->cga.displine])[(x << 4) + (c << 1) + 8] =
|
||||
((uint32_t *)buffer32->line[self->cga.displine])[(x << 4) + (c << 1) + 1 + 8] = cols[(fontdatm[chr][self->cga.sc & 15] & (1 << (c ^ 7))) ? 1 : 0];
|
||||
((uint32_t *)buffer32->line[self->cga.displine])[(x << 4) + (c << 1) + 1 + 8] = cols[(fontdatm[chr + self->cga.fontbase][self->cga.sc & 15] & (1 << (c ^ 7))) ? 1 : 0];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -10,7 +10,7 @@
|
||||
* PC2086, PC3086 use PVGA1A
|
||||
* MegaPC uses W90C11A
|
||||
*
|
||||
* Version: @(#)vid_paradise.c 1.0.2 2017/11/04
|
||||
* Version: @(#)vid_paradise.c 1.0.3 2017/12/31
|
||||
*
|
||||
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
@@ -43,7 +43,8 @@ typedef struct paradise_t
|
||||
enum
|
||||
{
|
||||
PVGA1A = 0,
|
||||
WD90C11
|
||||
WD90C11,
|
||||
WD90C30
|
||||
} type;
|
||||
|
||||
uint32_t read_bank[4], write_bank[4];
|
||||
@@ -207,37 +208,39 @@ uint8_t paradise_in(uint16_t addr, void *p)
|
||||
void paradise_remap(paradise_t *paradise)
|
||||
{
|
||||
svga_t *svga = ¶dise->svga;
|
||||
|
||||
uint8_t mask = (paradise->type == WD90C11) ? 0x7f : 0xff;
|
||||
|
||||
if (svga->seqregs[0x11] & 0x80)
|
||||
{
|
||||
paradise->read_bank[0] = paradise->read_bank[2] = (svga->gdcreg[0x9] & 0x7f) << 12;
|
||||
paradise->read_bank[1] = paradise->read_bank[3] = ((svga->gdcreg[0x9] & 0x7f) << 12) + ((svga->gdcreg[6] & 0x08) ? 0 : 0x8000);
|
||||
paradise->write_bank[0] = paradise->write_bank[2] = (svga->gdcreg[0xa] & 0x7f) << 12;
|
||||
paradise->write_bank[1] = paradise->write_bank[3] = ((svga->gdcreg[0xa] & 0x7f) << 12) + ((svga->gdcreg[6] & 0x08) ? 0 : 0x8000);
|
||||
paradise->read_bank[0] = paradise->read_bank[2] = (svga->gdcreg[0x9] & mask) << 12;
|
||||
paradise->read_bank[1] = paradise->read_bank[3] = ((svga->gdcreg[0x9] & mask) << 12) + ((svga->gdcreg[6] & 0x08) ? 0 : 0x8000);
|
||||
paradise->write_bank[0] = paradise->write_bank[2] = (svga->gdcreg[0xa] & mask) << 12;
|
||||
paradise->write_bank[1] = paradise->write_bank[3] = ((svga->gdcreg[0xa] & mask) << 12) + ((svga->gdcreg[6] & 0x08) ? 0 : 0x8000);
|
||||
}
|
||||
else if (svga->gdcreg[0xe] & 0x08)
|
||||
{
|
||||
if (svga->gdcreg[0x6] & 0xc)
|
||||
{
|
||||
paradise->read_bank[0] = paradise->read_bank[2] = (svga->gdcreg[0xa] & 0x7f) << 12;
|
||||
paradise->write_bank[0] = paradise->write_bank[2] = (svga->gdcreg[0xa] & 0x7f) << 12;
|
||||
paradise->read_bank[1] = paradise->read_bank[3] = ((svga->gdcreg[0x9] & 0x7f) << 12) + ((svga->gdcreg[6] & 0x08) ? 0 : 0x8000);
|
||||
paradise->write_bank[1] = paradise->write_bank[3] = ((svga->gdcreg[0x9] & 0x7f) << 12) + ((svga->gdcreg[6] & 0x08) ? 0 : 0x8000);
|
||||
paradise->read_bank[0] = paradise->read_bank[2] = (svga->gdcreg[0xa] & mask) << 12;
|
||||
paradise->write_bank[0] = paradise->write_bank[2] = (svga->gdcreg[0xa] & mask) << 12;
|
||||
paradise->read_bank[1] = paradise->read_bank[3] = ((svga->gdcreg[0x9] & mask) << 12) + ((svga->gdcreg[6] & 0x08) ? 0 : 0x8000);
|
||||
paradise->write_bank[1] = paradise->write_bank[3] = ((svga->gdcreg[0x9] & mask) << 12) + ((svga->gdcreg[6] & 0x08) ? 0 : 0x8000);
|
||||
}
|
||||
else
|
||||
{
|
||||
paradise->read_bank[0] = paradise->write_bank[0] = (svga->gdcreg[0xa] & 0x7f) << 12;
|
||||
paradise->read_bank[1] = paradise->write_bank[1] = ((svga->gdcreg[0xa] & 0x7f) << 12) + ((svga->gdcreg[6] & 0x08) ? 0 : 0x8000);
|
||||
paradise->read_bank[2] = paradise->write_bank[2] = (svga->gdcreg[0x9] & 0x7f) << 12;
|
||||
paradise->read_bank[3] = paradise->write_bank[3] = ((svga->gdcreg[0x9] & 0x7f) << 12) + ((svga->gdcreg[6] & 0x08) ? 0 : 0x8000);
|
||||
paradise->read_bank[0] = paradise->write_bank[0] = (svga->gdcreg[0xa] & mask) << 12;
|
||||
paradise->read_bank[1] = paradise->write_bank[1] = ((svga->gdcreg[0xa] & mask) << 12) + ((svga->gdcreg[6] & 0x08) ? 0 : 0x8000);
|
||||
paradise->read_bank[2] = paradise->write_bank[2] = (svga->gdcreg[0x9] & mask) << 12;
|
||||
paradise->read_bank[3] = paradise->write_bank[3] = ((svga->gdcreg[0x9] & mask) << 12) + ((svga->gdcreg[6] & 0x08) ? 0 : 0x8000);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
paradise->read_bank[0] = paradise->read_bank[2] = (svga->gdcreg[0x9] & 0x7f) << 12;
|
||||
paradise->read_bank[1] = paradise->read_bank[3] = ((svga->gdcreg[0x9] & 0x7f) << 12) + ((svga->gdcreg[6] & 0x08) ? 0 : 0x8000);
|
||||
paradise->write_bank[0] = paradise->write_bank[2] = (svga->gdcreg[0x9] & 0x7f) << 12;
|
||||
paradise->write_bank[1] = paradise->write_bank[3] = ((svga->gdcreg[0x9] & 0x7f) << 12) + ((svga->gdcreg[6] & 0x08) ? 0 : 0x8000);
|
||||
paradise->read_bank[0] = paradise->read_bank[2] = (svga->gdcreg[0x9] & mask) << 12;
|
||||
paradise->read_bank[1] = paradise->read_bank[3] = ((svga->gdcreg[0x9] & mask) << 12) + ((svga->gdcreg[6] & 0x08) ? 0 : 0x8000);
|
||||
paradise->write_bank[0] = paradise->write_bank[2] = (svga->gdcreg[0x9] & mask) << 12;
|
||||
paradise->write_bank[1] = paradise->write_bank[3] = ((svga->gdcreg[0x9] & mask) << 12) + ((svga->gdcreg[6] & 0x08) ? 0 : 0x8000);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -264,7 +267,7 @@ uint8_t paradise_read(uint32_t addr, void *p)
|
||||
}
|
||||
|
||||
|
||||
void *paradise_pvga1a_init(device_t *info)
|
||||
void *paradise_pvga1a_init(device_t *info, uint32_t memsize)
|
||||
{
|
||||
paradise_t *paradise = malloc(sizeof(paradise_t));
|
||||
svga_t *svga = ¶dise->svga;
|
||||
@@ -272,7 +275,7 @@ void *paradise_pvga1a_init(device_t *info)
|
||||
|
||||
io_sethandler(0x03c0, 0x0020, paradise_in, NULL, NULL, paradise_out, NULL, NULL, paradise);
|
||||
|
||||
svga_init(¶dise->svga, paradise, 1 << 18, /*256kb*/
|
||||
svga_init(¶dise->svga, paradise, memsize, /*256kb*/
|
||||
NULL,
|
||||
paradise_in, paradise_out,
|
||||
NULL,
|
||||
@@ -332,9 +335,44 @@ void *paradise_wd90c11_init(device_t *info)
|
||||
return paradise;
|
||||
}
|
||||
|
||||
void *paradise_wd90c30_init(device_t *info, uint32_t memsize)
|
||||
{
|
||||
paradise_t *paradise = malloc(sizeof(paradise_t));
|
||||
svga_t *svga = ¶dise->svga;
|
||||
memset(paradise, 0, sizeof(paradise_t));
|
||||
|
||||
io_sethandler(0x03c0, 0x0020, paradise_in, NULL, NULL, paradise_out, NULL, NULL, paradise);
|
||||
|
||||
svga_init(¶dise->svga, paradise, memsize,
|
||||
paradise_recalctimings,
|
||||
paradise_in, paradise_out,
|
||||
NULL,
|
||||
NULL);
|
||||
|
||||
mem_mapping_set_handler(¶dise->svga.mapping, paradise_read, NULL, NULL, paradise_write, NULL, NULL);
|
||||
mem_mapping_set_p(¶dise->svga.mapping, paradise);
|
||||
|
||||
svga->crtc[0x31] = 'W';
|
||||
svga->crtc[0x32] = 'D';
|
||||
svga->crtc[0x33] = '9';
|
||||
svga->crtc[0x34] = '0';
|
||||
svga->crtc[0x35] = 'C';
|
||||
svga->crtc[0x36] = '3';
|
||||
svga->crtc[0x37] = '0';
|
||||
|
||||
svga->bpp = 8;
|
||||
svga->miscout = 1;
|
||||
|
||||
svga->linear_base = 0;
|
||||
|
||||
paradise->type = WD90C11;
|
||||
|
||||
return paradise;
|
||||
}
|
||||
|
||||
static void *paradise_pvga1a_pc2086_init(device_t *info)
|
||||
{
|
||||
paradise_t *paradise = paradise_pvga1a_init(info);
|
||||
paradise_t *paradise = paradise_pvga1a_init(info, 1 << 18);
|
||||
|
||||
if (paradise)
|
||||
rom_init(¶dise->bios_rom, L"roms/machines/pc2086/40186.ic171", 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL);
|
||||
@@ -343,7 +381,7 @@ static void *paradise_pvga1a_pc2086_init(device_t *info)
|
||||
}
|
||||
static void *paradise_pvga1a_pc3086_init(device_t *info)
|
||||
{
|
||||
paradise_t *paradise = paradise_pvga1a_init(info);
|
||||
paradise_t *paradise = paradise_pvga1a_init(info, 1 << 18);
|
||||
|
||||
if (paradise)
|
||||
rom_init(¶dise->bios_rom, L"roms/machines/pc3086/c000.bin", 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL);
|
||||
@@ -351,6 +389,27 @@ static void *paradise_pvga1a_pc3086_init(device_t *info)
|
||||
return paradise;
|
||||
}
|
||||
|
||||
static void *paradise_pvga1a_standalone_init(device_t *info)
|
||||
{
|
||||
paradise_t *paradise;
|
||||
uint32_t memory = 512;
|
||||
|
||||
memory = device_get_config_int("memory");
|
||||
memory <<= 10;
|
||||
|
||||
paradise = paradise_pvga1a_init(info, memory);
|
||||
|
||||
if (paradise)
|
||||
rom_init(¶dise->bios_rom, L"roms/video/pvga1a/BIOS.BIN", 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL);
|
||||
|
||||
return paradise;
|
||||
}
|
||||
|
||||
static int paradise_pvga1a_standalone_available(void)
|
||||
{
|
||||
return rom_present(L"roms/video/pvga1a/BIOS.BIN");
|
||||
}
|
||||
|
||||
static void *paradise_wd90c11_megapc_init(device_t *info)
|
||||
{
|
||||
paradise_t *paradise = paradise_wd90c11_init(info);
|
||||
@@ -364,9 +423,40 @@ static void *paradise_wd90c11_megapc_init(device_t *info)
|
||||
return paradise;
|
||||
}
|
||||
|
||||
static void *paradise_wd90c11_standalone_init(device_t *info)
|
||||
{
|
||||
paradise_t *paradise = paradise_wd90c11_init(info);
|
||||
|
||||
if (paradise)
|
||||
rom_init(¶dise->bios_rom, L"roms/video/wd90c11/WD90C11.VBI", 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL);
|
||||
|
||||
return paradise;
|
||||
}
|
||||
|
||||
static int paradise_wd90c11_standalone_available(void)
|
||||
{
|
||||
return rom_present(L"roms/machines/megapc/41651-bios lo.u18") && rom_present(L"roms/machines/megapc/211253-bios hi.u19");
|
||||
return rom_present(L"roms/video/wd90c11/WD90C11.VBI");
|
||||
}
|
||||
|
||||
static void *paradise_wd90c30_standalone_init(device_t *info)
|
||||
{
|
||||
paradise_t *paradise;
|
||||
uint32_t memory = 512;
|
||||
|
||||
memory = device_get_config_int("memory");
|
||||
memory <<= 10;
|
||||
|
||||
paradise = paradise_wd90c30_init(info, memory);
|
||||
|
||||
if (paradise)
|
||||
rom_init(¶dise->bios_rom, L"roms/video/wd90c30/90C30-LR.VBI", 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL);
|
||||
|
||||
return paradise;
|
||||
}
|
||||
|
||||
static int paradise_wd90c30_standalone_available(void)
|
||||
{
|
||||
return rom_present(L"roms/video/wd90c30/90C30-LR.VBI");
|
||||
}
|
||||
|
||||
void paradise_close(void *p)
|
||||
@@ -426,6 +516,45 @@ device_t paradise_pvga1a_pc3086_device =
|
||||
paradise_force_redraw,
|
||||
paradise_add_status_info
|
||||
};
|
||||
|
||||
static device_config_t paradise_pvga1a_config[] =
|
||||
{
|
||||
{
|
||||
"memory", "Memory size", CONFIG_SELECTION, "", 512,
|
||||
{
|
||||
{
|
||||
"256 kB", 256
|
||||
},
|
||||
{
|
||||
"512 kB", 512
|
||||
},
|
||||
{
|
||||
"1 MB", 1024
|
||||
},
|
||||
{
|
||||
""
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"", "", -1
|
||||
}
|
||||
};
|
||||
|
||||
device_t paradise_pvga1a_device =
|
||||
{
|
||||
"Paradise PVGA1A",
|
||||
DEVICE_ISA,
|
||||
0,
|
||||
paradise_pvga1a_standalone_init,
|
||||
paradise_close,
|
||||
NULL,
|
||||
paradise_pvga1a_standalone_available,
|
||||
paradise_speed_changed,
|
||||
paradise_force_redraw,
|
||||
paradise_add_status_info,
|
||||
paradise_pvga1a_config
|
||||
};
|
||||
device_t paradise_wd90c11_megapc_device =
|
||||
{
|
||||
"Paradise WD90C11 (Amstrad MegaPC)",
|
||||
@@ -441,10 +570,10 @@ device_t paradise_wd90c11_megapc_device =
|
||||
};
|
||||
device_t paradise_wd90c11_device =
|
||||
{
|
||||
"Paradise WD90C11",
|
||||
"Paradise WD90C11-LR",
|
||||
DEVICE_ISA,
|
||||
0,
|
||||
paradise_wd90c11_megapc_init,
|
||||
paradise_wd90c11_standalone_init,
|
||||
paradise_close,
|
||||
NULL,
|
||||
paradise_wd90c11_standalone_available,
|
||||
@@ -452,3 +581,39 @@ device_t paradise_wd90c11_device =
|
||||
paradise_force_redraw,
|
||||
paradise_add_status_info
|
||||
};
|
||||
|
||||
static device_config_t paradise_wd90c30_config[] =
|
||||
{
|
||||
{
|
||||
"memory", "Memory size", CONFIG_SELECTION, "", 1024,
|
||||
{
|
||||
{
|
||||
"512 kB", 512
|
||||
},
|
||||
{
|
||||
"1 MB", 1024
|
||||
},
|
||||
{
|
||||
""
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"", "", -1
|
||||
}
|
||||
};
|
||||
|
||||
device_t paradise_wd90c30_device =
|
||||
{
|
||||
"Paradise WD90C30-LR",
|
||||
DEVICE_ISA,
|
||||
0,
|
||||
paradise_wd90c30_standalone_init,
|
||||
paradise_close,
|
||||
NULL,
|
||||
paradise_wd90c30_standalone_available,
|
||||
paradise_speed_changed,
|
||||
paradise_force_redraw,
|
||||
paradise_add_status_info,
|
||||
paradise_wd90c30_config
|
||||
};
|
||||
|
@@ -3,5 +3,7 @@
|
||||
*/
|
||||
extern device_t paradise_pvga1a_pc2086_device;
|
||||
extern device_t paradise_pvga1a_pc3086_device;
|
||||
extern device_t paradise_pvga1a_device;
|
||||
extern device_t paradise_wd90c11_megapc_device;
|
||||
extern device_t paradise_wd90c11_device;
|
||||
extern device_t paradise_wd90c30_device;
|
||||
|
726
src/video/vid_t3100e.c
Normal file
726
src/video/vid_t3100e.c
Normal file
@@ -0,0 +1,726 @@
|
||||
/* Emulate the Toshiba 3100e plasma display. This display has a fixed 640x400
|
||||
* resolution. */
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <wchar.h>
|
||||
|
||||
#include "../86box.h"
|
||||
#include "../device.h"
|
||||
#include "../io.h"
|
||||
#include "../mem.h"
|
||||
#include "../timer.h"
|
||||
#include "../cpu/cpu.h"
|
||||
#include "video.h"
|
||||
#include "vid_cga.h"
|
||||
#include "vid_t3100e.h"
|
||||
|
||||
#define T3100E_XSIZE 640
|
||||
#define T3100E_YSIZE 400
|
||||
|
||||
/* T3100e CRTC regs (from the ROM):
|
||||
*
|
||||
* Selecting a character height of 3 seems to be sufficient to convert the
|
||||
* 640x200 graphics mode to 640x400 (and, by analogy, 320x200 to 320x400).
|
||||
*
|
||||
*
|
||||
* Horiz-----> Vert------> I ch
|
||||
* 38 28 2D 0A 1F 06 19 1C 02 07 06 07 CO40
|
||||
* 71 50 5A 0A 1F 06 19 1C 02 07 06 07 CO80
|
||||
* 38 28 2D 0A 7F 06 64 70 02 01 06 07 Graphics
|
||||
* 61 50 52 0F 19 06 19 19 02 0D 0B 0C MONO
|
||||
* 2D 28 22 0A 67 00 64 67 02 03 06 07 640x400
|
||||
*/
|
||||
|
||||
/* Mapping of attributes to colours */
|
||||
static uint32_t amber, black;
|
||||
static uint8_t boldcols[256]; /* Which attributes use the bold font */
|
||||
static uint32_t blinkcols[256][2];
|
||||
static uint32_t normcols[256][2];
|
||||
|
||||
/* Video options set by the motherboard; they will be picked up by the card
|
||||
* on the next poll.
|
||||
*
|
||||
* Bit 3: Disable built-in video (for add-on card)
|
||||
* Bit 2: Thin font
|
||||
* Bits 0,1: Font set (not currently implemented)
|
||||
*/
|
||||
static uint8_t st_video_options;
|
||||
static uint8_t st_display_internal = -1;
|
||||
|
||||
void t3100e_video_options_set(uint8_t options)
|
||||
{
|
||||
st_video_options = options;
|
||||
}
|
||||
|
||||
void t3100e_display_set(uint8_t internal)
|
||||
{
|
||||
st_display_internal = internal;
|
||||
}
|
||||
|
||||
uint8_t t3100e_display_get()
|
||||
{
|
||||
return st_display_internal;
|
||||
}
|
||||
|
||||
|
||||
typedef struct t3100e_t
|
||||
{
|
||||
mem_mapping_t mapping;
|
||||
|
||||
cga_t cga; /* The CGA is used for the external
|
||||
* display; most of its registers are
|
||||
* ignored by the plasma display. */
|
||||
|
||||
int font; /* Current font, 0-3 */
|
||||
int enabled; /* Hardware enabled, 0 or 1 */
|
||||
int internal; /* Using internal display? */
|
||||
uint8_t attrmap; /* Attribute mapping register */
|
||||
|
||||
int dispontime, dispofftime;
|
||||
|
||||
int linepos, displine;
|
||||
int vc;
|
||||
int dispon;
|
||||
int vsynctime;
|
||||
uint8_t video_options;
|
||||
|
||||
uint8_t *vram;
|
||||
} t3100e_t;
|
||||
|
||||
|
||||
void t3100e_recalctimings(t3100e_t *t3100e);
|
||||
void t3100e_write(uint32_t addr, uint8_t val, void *p);
|
||||
uint8_t t3100e_read(uint32_t addr, void *p);
|
||||
void t3100e_recalcattrs(t3100e_t *t3100e);
|
||||
|
||||
|
||||
void t3100e_out(uint16_t addr, uint8_t val, void *p)
|
||||
{
|
||||
t3100e_t *t3100e = (t3100e_t *)p;
|
||||
switch (addr)
|
||||
{
|
||||
/* Emulated CRTC, register select */
|
||||
case 0x3d0: case 0x3d2: case 0x3d4: case 0x3d6:
|
||||
cga_out(addr, val, &t3100e->cga);
|
||||
break;
|
||||
|
||||
/* Emulated CRTC, value */
|
||||
case 0x3d1: case 0x3d3: case 0x3d5: case 0x3d7:
|
||||
/* Register 0x12 controls the attribute mappings for the
|
||||
* plasma screen. */
|
||||
if (t3100e->cga.crtcreg == 0x12)
|
||||
{
|
||||
t3100e->attrmap = val;
|
||||
t3100e_recalcattrs(t3100e);
|
||||
return;
|
||||
}
|
||||
cga_out(addr, val, &t3100e->cga);
|
||||
|
||||
t3100e_recalctimings(t3100e);
|
||||
return;
|
||||
|
||||
/* CGA control register */
|
||||
case 0x3D8:
|
||||
cga_out(addr, val, &t3100e->cga);
|
||||
return;
|
||||
/* CGA colour register */
|
||||
case 0x3D9:
|
||||
cga_out(addr, val, &t3100e->cga);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t t3100e_in(uint16_t addr, void *p)
|
||||
{
|
||||
t3100e_t *t3100e = (t3100e_t *)p;
|
||||
uint8_t val;
|
||||
|
||||
switch (addr)
|
||||
{
|
||||
case 0x3d1: case 0x3d3: case 0x3d5: case 0x3d7:
|
||||
if (t3100e->cga.crtcreg == 0x12)
|
||||
{
|
||||
val = t3100e->attrmap & 0x0F;
|
||||
if (t3100e->internal) val |= 0x30; /* Plasma / CRT */
|
||||
return val;
|
||||
}
|
||||
}
|
||||
|
||||
return cga_in(addr, &t3100e->cga);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void t3100e_write(uint32_t addr, uint8_t val, void *p)
|
||||
{
|
||||
t3100e_t *t3100e = (t3100e_t *)p;
|
||||
egawrites++;
|
||||
|
||||
// pclog("CGA_WRITE %04X %02X\n", addr, val);
|
||||
t3100e->vram[addr & 0x7fff] = val;
|
||||
cycles -= 4;
|
||||
}
|
||||
|
||||
|
||||
|
||||
uint8_t t3100e_read(uint32_t addr, void *p)
|
||||
{
|
||||
t3100e_t *t3100e = (t3100e_t *)p;
|
||||
egareads++;
|
||||
cycles -= 4;
|
||||
|
||||
// pclog("CGA_READ %04X\n", addr);
|
||||
return t3100e->vram[addr & 0x7fff];
|
||||
}
|
||||
|
||||
|
||||
|
||||
void t3100e_recalctimings(t3100e_t *t3100e)
|
||||
{
|
||||
double disptime;
|
||||
double _dispontime, _dispofftime;
|
||||
|
||||
if (!t3100e->internal)
|
||||
{
|
||||
cga_recalctimings(&t3100e->cga);
|
||||
return;
|
||||
}
|
||||
disptime = 651;
|
||||
_dispontime = 640;
|
||||
_dispofftime = disptime - _dispontime;
|
||||
t3100e->dispontime = (int)(_dispontime * (1 << TIMER_SHIFT));
|
||||
t3100e->dispofftime = (int)(_dispofftime * (1 << TIMER_SHIFT));
|
||||
}
|
||||
|
||||
|
||||
/* Draw a row of text in 80-column mode */
|
||||
void t3100e_text_row80(t3100e_t *t3100e)
|
||||
{
|
||||
uint32_t cols[2];
|
||||
int x, c;
|
||||
uint8_t chr, attr;
|
||||
int drawcursor;
|
||||
int cursorline;
|
||||
int bold;
|
||||
int blink;
|
||||
uint16_t addr;
|
||||
uint8_t sc;
|
||||
uint16_t ma = (t3100e->cga.crtc[13] | (t3100e->cga.crtc[12] << 8)) & 0x7fff;
|
||||
uint16_t ca = (t3100e->cga.crtc[15] | (t3100e->cga.crtc[14] << 8)) & 0x7fff;
|
||||
|
||||
sc = (t3100e->displine) & 15;
|
||||
addr = ((ma & ~1) + (t3100e->displine >> 4) * 80) * 2;
|
||||
ma += (t3100e->displine >> 4) * 80;
|
||||
|
||||
if ((t3100e->cga.crtc[10] & 0x60) == 0x20)
|
||||
{
|
||||
cursorline = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
cursorline = ((t3100e->cga.crtc[10] & 0x0F)*2 <= sc) &&
|
||||
((t3100e->cga.crtc[11] & 0x0F)*2 >= sc);
|
||||
}
|
||||
for (x = 0; x < 80; x++)
|
||||
{
|
||||
chr = t3100e->vram[(addr + 2 * x) & 0x7FFF];
|
||||
attr = t3100e->vram[(addr + 2 * x + 1) & 0x7FFF];
|
||||
drawcursor = ((ma == ca) && cursorline &&
|
||||
(t3100e->cga.cgamode & 8) && (t3100e->cga.cgablink & 16));
|
||||
|
||||
blink = ((t3100e->cga.cgablink & 16) && (t3100e->cga.cgamode & 0x20) &&
|
||||
(attr & 0x80) && !drawcursor);
|
||||
|
||||
if (t3100e->video_options & 4)
|
||||
bold = boldcols[attr] ? chr + 256 : chr;
|
||||
else
|
||||
bold = boldcols[attr] ? chr : chr + 256;
|
||||
bold += 512 * (t3100e->video_options & 3);
|
||||
|
||||
if (t3100e->cga.cgamode & 0x20) /* Blink */
|
||||
{
|
||||
cols[1] = blinkcols[attr][1];
|
||||
cols[0] = blinkcols[attr][0];
|
||||
if (blink) cols[1] = cols[0];
|
||||
}
|
||||
else
|
||||
{
|
||||
cols[1] = normcols[attr][1];
|
||||
cols[0] = normcols[attr][0];
|
||||
}
|
||||
if (drawcursor)
|
||||
{
|
||||
for (c = 0; c < 8; c++)
|
||||
{
|
||||
((uint32_t *)buffer32->line[t3100e->displine])[(x << 3) + c] = cols[(fontdatm[bold][sc] & (1 << (c ^ 7))) ? 1 : 0] ^ (amber ^ black);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (c = 0; c < 8; c++)
|
||||
((uint32_t *)buffer32->line[t3100e->displine])[(x << 3) + c] = cols[(fontdatm[bold][sc] & (1 << (c ^ 7))) ? 1 : 0];
|
||||
}
|
||||
++ma;
|
||||
}
|
||||
}
|
||||
|
||||
/* Draw a row of text in 40-column mode */
|
||||
void t3100e_text_row40(t3100e_t *t3100e)
|
||||
{
|
||||
uint32_t cols[2];
|
||||
int x, c;
|
||||
uint8_t chr, attr;
|
||||
int drawcursor;
|
||||
int cursorline;
|
||||
int bold;
|
||||
int blink;
|
||||
uint16_t addr;
|
||||
uint8_t sc;
|
||||
uint16_t ma = (t3100e->cga.crtc[13] | (t3100e->cga.crtc[12] << 8)) & 0x7fff;
|
||||
uint16_t ca = (t3100e->cga.crtc[15] | (t3100e->cga.crtc[14] << 8)) & 0x7fff;
|
||||
|
||||
sc = (t3100e->displine) & 15;
|
||||
addr = ((ma & ~1) + (t3100e->displine >> 4) * 40) * 2;
|
||||
ma += (t3100e->displine >> 4) * 40;
|
||||
|
||||
if ((t3100e->cga.crtc[10] & 0x60) == 0x20)
|
||||
{
|
||||
cursorline = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
cursorline = ((t3100e->cga.crtc[10] & 0x0F)*2 <= sc) &&
|
||||
((t3100e->cga.crtc[11] & 0x0F)*2 >= sc);
|
||||
}
|
||||
for (x = 0; x < 40; x++)
|
||||
{
|
||||
chr = t3100e->vram[(addr + 2 * x) & 0x7FFF];
|
||||
attr = t3100e->vram[(addr + 2 * x + 1) & 0x7FFF];
|
||||
drawcursor = ((ma == ca) && cursorline &&
|
||||
(t3100e->cga.cgamode & 8) && (t3100e->cga.cgablink & 16));
|
||||
|
||||
blink = ((t3100e->cga.cgablink & 16) && (t3100e->cga.cgamode & 0x20) &&
|
||||
(attr & 0x80) && !drawcursor);
|
||||
|
||||
if (t3100e->video_options & 4)
|
||||
bold = boldcols[attr] ? chr + 256 : chr;
|
||||
else bold = boldcols[attr] ? chr : chr + 256;
|
||||
bold += 512 * (t3100e->video_options & 3);
|
||||
|
||||
if (t3100e->cga.cgamode & 0x20) /* Blink */
|
||||
{
|
||||
cols[1] = blinkcols[attr][1];
|
||||
cols[0] = blinkcols[attr][0];
|
||||
if (blink) cols[1] = cols[0];
|
||||
}
|
||||
else
|
||||
{
|
||||
cols[1] = normcols[attr][1];
|
||||
cols[0] = normcols[attr][0];
|
||||
}
|
||||
if (drawcursor)
|
||||
{
|
||||
for (c = 0; c < 8; c++)
|
||||
{
|
||||
((uint32_t *)buffer32->line[t3100e->displine])[(x << 4) + c*2] =
|
||||
((uint32_t *)buffer32->line[t3100e->displine])[(x << 4) + c*2 + 1] = cols[(fontdatm[bold][sc] & (1 << (c ^ 7))) ? 1 : 0] ^ (amber ^ black);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (c = 0; c < 8; c++)
|
||||
{
|
||||
((uint32_t *)buffer32->line[t3100e->displine])[(x << 4) + c*2] =
|
||||
((uint32_t *)buffer32->line[t3100e->displine])[(x << 4) + c*2+1] = cols[(fontdatm[bold][sc] & (1 << (c ^ 7))) ? 1 : 0];
|
||||
}
|
||||
}
|
||||
++ma;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/* Draw a line in CGA 640x200 or T3100e 640x400 mode */
|
||||
void t3100e_cgaline6(t3100e_t *t3100e)
|
||||
{
|
||||
int x, c;
|
||||
uint8_t dat;
|
||||
uint32_t ink = 0;
|
||||
uint16_t addr;
|
||||
uint32_t fg = (t3100e->cga.cgacol & 0x0F) ? amber : black;
|
||||
uint32_t bg = black;
|
||||
|
||||
uint16_t ma = (t3100e->cga.crtc[13] | (t3100e->cga.crtc[12] << 8)) & 0x7fff;
|
||||
|
||||
if (t3100e->cga.crtc[9] == 3) /* 640*400 */
|
||||
{
|
||||
addr = ((t3100e->displine) & 1) * 0x2000 +
|
||||
((t3100e->displine >> 1) & 1) * 0x4000 +
|
||||
(t3100e->displine >> 2) * 80 +
|
||||
((ma & ~1) << 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
addr = ((t3100e->displine >> 1) & 1) * 0x2000 +
|
||||
(t3100e->displine >> 2) * 80 +
|
||||
((ma & ~1) << 1);
|
||||
}
|
||||
for (x = 0; x < 80; x++)
|
||||
{
|
||||
dat = t3100e->vram[addr & 0x7FFF];
|
||||
addr++;
|
||||
|
||||
for (c = 0; c < 8; c++)
|
||||
{
|
||||
ink = (dat & 0x80) ? fg : bg;
|
||||
if (!(t3100e->cga.cgamode & 8)) ink = black;
|
||||
((uint32_t *)buffer32->line[t3100e->displine])[x*8+c] = ink;
|
||||
dat = dat << 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Draw a line in CGA 320x200 mode. Here the CGA colours are converted to
|
||||
* dither patterns: colour 1 to 25% grey, colour 2 to 50% grey */
|
||||
void t3100e_cgaline4(t3100e_t *t3100e)
|
||||
{
|
||||
int x, c;
|
||||
uint8_t dat, pattern;
|
||||
uint32_t ink0 = 0, ink1 = 0;
|
||||
uint16_t addr;
|
||||
|
||||
uint16_t ma = (t3100e->cga.crtc[13] | (t3100e->cga.crtc[12] << 8)) & 0x7fff;
|
||||
if (t3100e->cga.crtc[9] == 3) /* 320*400 undocumented */
|
||||
{
|
||||
addr = ((t3100e->displine) & 1) * 0x2000 +
|
||||
((t3100e->displine >> 1) & 1) * 0x4000 +
|
||||
(t3100e->displine >> 2) * 80 +
|
||||
((ma & ~1) << 1);
|
||||
}
|
||||
else /* 320*200 */
|
||||
{
|
||||
addr = ((t3100e->displine >> 1) & 1) * 0x2000 +
|
||||
(t3100e->displine >> 2) * 80 +
|
||||
((ma & ~1) << 1);
|
||||
}
|
||||
for (x = 0; x < 80; x++)
|
||||
{
|
||||
dat = t3100e->vram[addr & 0x7FFF];
|
||||
addr++;
|
||||
|
||||
for (c = 0; c < 4; c++)
|
||||
{
|
||||
pattern = (dat & 0xC0) >> 6;
|
||||
if (!(t3100e->cga.cgamode & 8)) pattern = 0;
|
||||
|
||||
switch (pattern & 3)
|
||||
{
|
||||
case 0: ink0 = ink1 = black; break;
|
||||
case 1: if (t3100e->displine & 1)
|
||||
{
|
||||
ink0 = black; ink1 = black;
|
||||
}
|
||||
else
|
||||
{
|
||||
ink0 = amber; ink1 = black;
|
||||
}
|
||||
break;
|
||||
case 2: if (t3100e->displine & 1)
|
||||
{
|
||||
ink0 = black; ink1 = amber;
|
||||
}
|
||||
else
|
||||
{
|
||||
ink0 = amber; ink1 = black;
|
||||
}
|
||||
break;
|
||||
case 3: ink0 = ink1 = amber; break;
|
||||
|
||||
}
|
||||
((uint32_t *)buffer32->line[t3100e->displine])[x*8+2*c] = ink0;
|
||||
((uint32_t *)buffer32->line[t3100e->displine])[x*8+2*c+1] = ink1;
|
||||
dat = dat << 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void t3100e_poll(void *p)
|
||||
{
|
||||
t3100e_t *t3100e = (t3100e_t *)p;
|
||||
|
||||
if (t3100e->video_options != st_video_options)
|
||||
{
|
||||
t3100e->video_options = st_video_options;
|
||||
|
||||
if (t3100e->video_options & 8) /* Disable internal CGA */
|
||||
mem_mapping_disable(&t3100e->mapping);
|
||||
else mem_mapping_enable(&t3100e->mapping);
|
||||
|
||||
/* Set the font used for the external display */
|
||||
t3100e->cga.fontbase = (512 * (t3100e->video_options & 3))
|
||||
+ ((t3100e->video_options & 4) ? 256 : 0);
|
||||
|
||||
}
|
||||
/* Switch between internal plasma and external CRT display. */
|
||||
if (st_display_internal != -1 && st_display_internal != t3100e->internal)
|
||||
{
|
||||
t3100e->internal = st_display_internal;
|
||||
t3100e_recalctimings(t3100e);
|
||||
}
|
||||
if (!t3100e->internal)
|
||||
{
|
||||
cga_poll(&t3100e->cga);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (!t3100e->linepos)
|
||||
{
|
||||
t3100e->cga.vidtime += t3100e->dispofftime;
|
||||
t3100e->cga.cgastat |= 1;
|
||||
t3100e->linepos = 1;
|
||||
if (t3100e->dispon)
|
||||
{
|
||||
if (t3100e->displine == 0)
|
||||
{
|
||||
video_wait_for_buffer();
|
||||
}
|
||||
|
||||
/* Graphics */
|
||||
if (t3100e->cga.cgamode & 0x02)
|
||||
{
|
||||
if (t3100e->cga.cgamode & 0x10)
|
||||
t3100e_cgaline6(t3100e);
|
||||
else t3100e_cgaline4(t3100e);
|
||||
}
|
||||
else
|
||||
if (t3100e->cga.cgamode & 0x01) /* High-res text */
|
||||
{
|
||||
t3100e_text_row80(t3100e);
|
||||
}
|
||||
else
|
||||
{
|
||||
t3100e_text_row40(t3100e);
|
||||
}
|
||||
}
|
||||
t3100e->displine++;
|
||||
/* Hardcode a fixed refresh rate and VSYNC timing */
|
||||
if (t3100e->displine == 400) /* Start of VSYNC */
|
||||
{
|
||||
t3100e->cga.cgastat |= 8;
|
||||
t3100e->dispon = 0;
|
||||
}
|
||||
if (t3100e->displine == 416) /* End of VSYNC */
|
||||
{
|
||||
t3100e->displine = 0;
|
||||
t3100e->cga.cgastat &= ~8;
|
||||
t3100e->dispon = 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (t3100e->dispon)
|
||||
{
|
||||
t3100e->cga.cgastat &= ~1;
|
||||
}
|
||||
t3100e->cga.vidtime += t3100e->dispontime;
|
||||
t3100e->linepos = 0;
|
||||
|
||||
if (t3100e->displine == 400)
|
||||
{
|
||||
/* Hardcode 640x400 window size */
|
||||
if (T3100E_XSIZE != xsize || T3100E_YSIZE != ysize)
|
||||
{
|
||||
xsize = T3100E_XSIZE;
|
||||
ysize = T3100E_YSIZE;
|
||||
if (xsize < 64) xsize = 656;
|
||||
if (ysize < 32) ysize = 200;
|
||||
set_screen_size(xsize, ysize);
|
||||
}
|
||||
video_blit_memtoscreen(0, 0, 0, ysize, xsize, ysize);
|
||||
|
||||
frames++;
|
||||
/* Fixed 640x400 resolution */
|
||||
video_res_x = T3100E_XSIZE;
|
||||
video_res_y = T3100E_YSIZE;
|
||||
|
||||
if (t3100e->cga.cgamode & 0x02)
|
||||
{
|
||||
if (t3100e->cga.cgamode & 0x10)
|
||||
video_bpp = 1;
|
||||
else video_bpp = 2;
|
||||
|
||||
}
|
||||
else video_bpp = 0;
|
||||
t3100e->cga.cgablink++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void t3100e_recalcattrs(t3100e_t *t3100e)
|
||||
{
|
||||
int n;
|
||||
|
||||
/* val behaves as follows:
|
||||
* Bit 0: Attributes 01-06, 08-0E are inverse video
|
||||
* Bit 1: Attributes 01-06, 08-0E are bold
|
||||
* Bit 2: Attributes 11-16, 18-1F, 21-26, 28-2F ... F1-F6, F8-FF
|
||||
* are inverse video
|
||||
* Bit 3: Attributes 11-16, 18-1F, 21-26, 28-2F ... F1-F6, F8-FF
|
||||
* are bold */
|
||||
|
||||
/* Set up colours */
|
||||
amber = makecol(0xf7, 0x7C, 0x34);
|
||||
black = makecol(0x17, 0x0C, 0x00);
|
||||
|
||||
/* Initialise the attribute mapping. Start by defaulting everything
|
||||
* to black on amber, and with bold set by bit 3 */
|
||||
for (n = 0; n < 256; n++)
|
||||
{
|
||||
boldcols[n] = (n & 8) != 0;
|
||||
blinkcols[n][0] = normcols[n][0] = amber;
|
||||
blinkcols[n][1] = normcols[n][1] = black;
|
||||
}
|
||||
|
||||
/* Colours 0x11-0xFF are controlled by bits 2 and 3 of the
|
||||
* passed value. Exclude x0 and x8, which are always black on
|
||||
* amber. */
|
||||
for (n = 0x11; n <= 0xFF; n++)
|
||||
{
|
||||
if ((n & 7) == 0) continue;
|
||||
if (t3100e->attrmap & 4) /* Inverse */
|
||||
{
|
||||
blinkcols[n][0] = normcols[n][0] = amber;
|
||||
blinkcols[n][1] = normcols[n][1] = black;
|
||||
}
|
||||
else /* Normal */
|
||||
{
|
||||
blinkcols[n][0] = normcols[n][0] = black;
|
||||
blinkcols[n][1] = normcols[n][1] = amber;
|
||||
}
|
||||
if (t3100e->attrmap & 8) boldcols[n] = 1; /* Bold */
|
||||
}
|
||||
/* Set up the 01-0E range, controlled by bits 0 and 1 of the
|
||||
* passed value. When blinking is enabled this also affects 81-8E. */
|
||||
for (n = 0x01; n <= 0x0E; n++)
|
||||
{
|
||||
if (n == 7) continue;
|
||||
if (t3100e->attrmap & 1)
|
||||
{
|
||||
blinkcols[n][0] = normcols[n][0] = amber;
|
||||
blinkcols[n][1] = normcols[n][1] = black;
|
||||
blinkcols[n+128][0] = amber;
|
||||
blinkcols[n+128][1] = black;
|
||||
}
|
||||
else
|
||||
{
|
||||
blinkcols[n][0] = normcols[n][0] = black;
|
||||
blinkcols[n][1] = normcols[n][1] = amber;
|
||||
blinkcols[n+128][0] = black;
|
||||
blinkcols[n+128][1] = amber;
|
||||
}
|
||||
if (t3100e->attrmap & 2) boldcols[n] = 1;
|
||||
}
|
||||
/* Colours 07 and 0F are always amber on black. If blinking is
|
||||
* enabled so are 87 and 8F. */
|
||||
for (n = 0x07; n <= 0x0F; n += 8)
|
||||
{
|
||||
blinkcols[n][0] = normcols[n][0] = black;
|
||||
blinkcols[n][1] = normcols[n][1] = amber;
|
||||
blinkcols[n+128][0] = black;
|
||||
blinkcols[n+128][1] = amber;
|
||||
}
|
||||
/* When not blinking, colours 81-8F are always amber on black. */
|
||||
for (n = 0x81; n <= 0x8F; n ++)
|
||||
{
|
||||
normcols[n][0] = black;
|
||||
normcols[n][1] = amber;
|
||||
boldcols[n] = (n & 0x08) != 0;
|
||||
}
|
||||
|
||||
|
||||
/* Finally do the ones which are solid black. These differ between
|
||||
* the normal and blinking mappings */
|
||||
for (n = 0; n <= 0xFF; n += 0x11)
|
||||
{
|
||||
normcols[n][0] = normcols[n][1] = black;
|
||||
}
|
||||
/* In the blinking range, 00 11 22 .. 77 and 80 91 A2 .. F7 are black */
|
||||
for (n = 0; n <= 0x77; n += 0x11)
|
||||
{
|
||||
blinkcols[n][0] = blinkcols[n][1] = black;
|
||||
blinkcols[n+128][0] = blinkcols[n+128][1] = black;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void *t3100e_init(device_t *info)
|
||||
{
|
||||
t3100e_t *t3100e = malloc(sizeof(t3100e_t));
|
||||
memset(t3100e, 0, sizeof(t3100e_t));
|
||||
cga_init(&t3100e->cga);
|
||||
|
||||
t3100e->internal = 1;
|
||||
|
||||
/* 32k video RAM */
|
||||
t3100e->vram = malloc(0x8000);
|
||||
|
||||
timer_add(t3100e_poll, &t3100e->cga.vidtime, TIMER_ALWAYS_ENABLED, t3100e);
|
||||
|
||||
/* Occupy memory between 0xB8000 and 0xBFFFF */
|
||||
mem_mapping_add(&t3100e->mapping, 0xb8000, 0x8000, t3100e_read, NULL, NULL, t3100e_write, NULL, NULL, NULL, 0, t3100e);
|
||||
/* Respond to CGA I/O ports */
|
||||
io_sethandler(0x03d0, 0x000c, t3100e_in, NULL, NULL, t3100e_out, NULL, NULL, t3100e);
|
||||
|
||||
/* Default attribute mapping is 4 */
|
||||
t3100e->attrmap = 4;
|
||||
t3100e_recalcattrs(t3100e);
|
||||
|
||||
/* Start off in 80x25 text mode */
|
||||
t3100e->cga.cgastat = 0xF4;
|
||||
t3100e->cga.vram = t3100e->vram;
|
||||
t3100e->enabled = 1;
|
||||
t3100e->video_options = 0xFF;
|
||||
return t3100e;
|
||||
}
|
||||
|
||||
void t3100e_close(void *p)
|
||||
{
|
||||
t3100e_t *t3100e = (t3100e_t *)p;
|
||||
|
||||
free(t3100e->vram);
|
||||
free(t3100e);
|
||||
}
|
||||
|
||||
void t3100e_speed_changed(void *p)
|
||||
{
|
||||
t3100e_t *t3100e = (t3100e_t *)p;
|
||||
|
||||
t3100e_recalctimings(t3100e);
|
||||
}
|
||||
|
||||
device_t t3100e_device =
|
||||
{
|
||||
"Toshiba T3100e",
|
||||
0,
|
||||
0,
|
||||
t3100e_init,
|
||||
t3100e_close,
|
||||
NULL,
|
||||
NULL,
|
||||
t3100e_speed_changed,
|
||||
NULL,
|
||||
NULL
|
||||
};
|
4
src/video/vid_t3100e.h
Normal file
4
src/video/vid_t3100e.h
Normal file
@@ -0,0 +1,4 @@
|
||||
extern device_t t3100e_device;
|
||||
|
||||
void t3100e_video_options_set(uint8_t options);
|
||||
void t3100e_display_set(uint8_t internal);
|
@@ -8,7 +8,7 @@
|
||||
*
|
||||
* Define all known video cards.
|
||||
*
|
||||
* Version: @(#)vid_table.c 1.0.7 2017/12/29
|
||||
* Version: @(#)vid_table.c 1.0.8 2017/12/31
|
||||
*
|
||||
* Authors: Miran Grca, <mgrca8@gmail.com>
|
||||
* Fred N. van Kempen, <decwiz@yahoo.com>
|
||||
@@ -115,7 +115,9 @@ video_cards[] = {
|
||||
{ "[ISA] MDSI Genius", "genius", &genius_device, GFX_GENIUS },
|
||||
{ "[ISA] OAK OTI-067", "oti067", &oti067_device, GFX_OTI067 },
|
||||
{ "[ISA] OAK OTI-077", "oti077", &oti077_device, GFX_OTI077 },
|
||||
{ "[ISA] Paradise WD90C11", "wd90c11", ¶dise_wd90c11_device, GFX_WD90C11 },
|
||||
{ "[ISA] Paradise PVGA1A", "pvga1a", ¶dise_pvga1a_device, GFX_PVGA1A },
|
||||
{ "[ISA] Paradise WD90C11-LR", "wd90c11", ¶dise_wd90c11_device, GFX_WD90C11 },
|
||||
{ "[ISA] Paradise WD90C30-LR", "wd90c30", ¶dise_wd90c30_device, GFX_WD90C30 },
|
||||
{ "[ISA] Plantronics ColorPlus", "plantronics", &colorplus_device, GFX_COLORPLUS },
|
||||
{"[ISA] TI CF62011 SVGA", "ti_cf62011",
|
||||
&ti_cf62011_device, GFX_TICF62011 },
|
||||
|
@@ -40,7 +40,7 @@
|
||||
* W = 3 bus clocks
|
||||
* L = 4 bus clocks
|
||||
*
|
||||
* Version: @(#)video.c 1.0.11 2017/12/15
|
||||
* Version: @(#)video.c 1.0.12 2017/12/31
|
||||
*
|
||||
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
@@ -76,8 +76,8 @@ enum {
|
||||
bitmap_t *screen = NULL,
|
||||
*buffer = NULL,
|
||||
*buffer32 = NULL;
|
||||
uint8_t fontdat[256][8]; /* IBM CGA font */
|
||||
uint8_t fontdatm[256][16]; /* IBM MDA font */
|
||||
uint8_t fontdat[2048][8]; /* IBM CGA font */
|
||||
uint8_t fontdatm[2048][16]; /* IBM MDA font */
|
||||
uint8_t fontdatw[512][32]; /* Wyse700 font */
|
||||
uint8_t fontdat8x12[256][16]; /* MDSI Genius font */
|
||||
uint32_t pal_lookup[256];
|
||||
@@ -632,6 +632,36 @@ loadfont(wchar_t *s, int format)
|
||||
fontdat8x12[c][d] = fgetc(f);
|
||||
break;
|
||||
|
||||
case 5: /* Toshiba 3100e */
|
||||
for (d = 0; d < 2048; d += 512) /* Four languages... */
|
||||
{
|
||||
for (c = d; c < d+256; c++)
|
||||
{
|
||||
fread(&fontdatm[c][8], 1, 8, f);
|
||||
}
|
||||
for (c = d+256; c < d+512; c++)
|
||||
{
|
||||
fread(&fontdatm[c][8], 1, 8, f);
|
||||
}
|
||||
for (c = d; c < d+256; c++)
|
||||
{
|
||||
fread(&fontdatm[c][0], 1, 8, f);
|
||||
}
|
||||
for (c = d+256; c < d+512; c++)
|
||||
{
|
||||
fread(&fontdatm[c][0], 1, 8, f);
|
||||
}
|
||||
fseek(f, 4096, SEEK_CUR); /* Skip blank section */
|
||||
for (c = d; c < d+256; c++)
|
||||
{
|
||||
fread(&fontdat[c][0], 1, 8, f);
|
||||
}
|
||||
for (c = d+256; c < d+512; c++)
|
||||
{
|
||||
fread(&fontdat[c][0], 1, 8, f);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
(void)fclose(f);
|
||||
|
@@ -8,7 +8,7 @@
|
||||
*
|
||||
* Definitions for the video controller module.
|
||||
*
|
||||
* Version: @(#)video.h 1.0.6 2017/12/29
|
||||
* Version: @(#)video.h 1.0.7 2017/12/31
|
||||
*
|
||||
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
@@ -68,7 +68,7 @@ enum {
|
||||
GFX_COMPAQ_VGA, /* Compaq/Paradise VGA */
|
||||
GFX_CL_GD5446, /* Cirrus Logic CL-GD5446 */
|
||||
GFX_VGAWONDERXL, /* Compaq ATI VGA Wonder XL (28800-5) */
|
||||
GFX_WD90C11, /* Paradise WD90C11 Standalone */
|
||||
GFX_WD90C11, /* Paradise WD90C11-LR Standalone */
|
||||
GFX_OTI077, /* Oak OTI-077 */
|
||||
GFX_VGAWONDERXL24, /* Compaq ATI VGA Wonder XL24 (28800-6) */
|
||||
GFX_STEALTH64_VLB, /* S3 Vision864 (Diamond Stealth 64) VLB */
|
||||
@@ -94,6 +94,8 @@ enum {
|
||||
GFX_TICF62011, /* TI CF62011 */
|
||||
GFX_COMPAQ_CGA, /* Compaq CGA */
|
||||
GFX_COMPAQ_CGA_2, /* Compaq CGA 2 */
|
||||
GFX_PVGA1A, /* Paradise PVGA1A Standalone */
|
||||
GFX_WD90C30, /* Paradise WD90C30-LR Standalone */
|
||||
|
||||
GFX_MAX
|
||||
};
|
||||
@@ -108,7 +110,7 @@ enum {
|
||||
gfxcard!=GFX_GENIUS && gfxcard!=GFX_COMPAQ_EGA && \
|
||||
gfxcard!=GFX_SUPER_EGA && gfxcard!=GFX_HERCULESPLUS) && \
|
||||
(romset!=ROM_PC1640 && romset!=ROM_PC1512 && \
|
||||
romset!=ROM_TANDY && romset!=ROM_PC200))
|
||||
romset!=ROM_TANDY && romset!=ROM_PC200 && romset!=ROM_T3100E))
|
||||
|
||||
enum {
|
||||
FULLSCR_SCALE_FULL = 0,
|
||||
@@ -151,8 +153,8 @@ extern int video_fullscreen,
|
||||
video_fullscreen_scale,
|
||||
video_fullscreen_first;
|
||||
extern int fullchange;
|
||||
extern uint8_t fontdat[256][8];
|
||||
extern uint8_t fontdatm[256][16];
|
||||
extern uint8_t fontdat[2048][8];
|
||||
extern uint8_t fontdatm[2048][16];
|
||||
extern uint32_t *video_6to8,
|
||||
*video_15to32,
|
||||
*video_16to32;
|
||||
|
@@ -355,6 +355,7 @@ MCHOBJ := machine.o machine_table.o \
|
||||
m_xt.o m_xt_compaq.o m_xt_laserxt.o \
|
||||
m_at.o m_at_ali1429.o m_at_commodore.o \
|
||||
m_at_neat.o m_at_headland.o \
|
||||
m_at_t3100e.o \
|
||||
m_at_opti495.o m_at_scat.o \
|
||||
m_at_compaq.o m_at_wd76c10.o \
|
||||
m_at_sis_85c471.o m_at_sis_85c496.o \
|
||||
@@ -440,6 +441,7 @@ VIDOBJ := video.o \
|
||||
vid_hercules.o vid_herculesplus.o vid_incolor.o \
|
||||
vid_colorplus.o \
|
||||
vid_genius.o \
|
||||
vid_t3100e.o \
|
||||
vid_s3.o vid_s3_virge.o \
|
||||
vid_et4000.o vid_et4000w32.o vid_icd2061.o \
|
||||
vid_oti067.o \
|
||||
|
Reference in New Issue
Block a user