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:
OBattler
2017-12-31 06:37:19 +01:00
parent 8a9204aa1f
commit d9e7f0c4fc
20 changed files with 1834 additions and 58 deletions

View File

@@ -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)

View File

@@ -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);

View File

@@ -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
View 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(&regs->mapping[pg]);
mem_mapping_set_exec(&regs->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(&regs->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);
}

View 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);

View File

@@ -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 *);

View File

@@ -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 },

View File

@@ -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);
}

View File

@@ -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
};

View File

@@ -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];
}
}
}

View File

@@ -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;

View File

@@ -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];
}
}
}

View File

@@ -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 = &paradise->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 = &paradise->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(&paradise->svga, paradise, 1 << 18, /*256kb*/
svga_init(&paradise->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 = &paradise->svga;
memset(paradise, 0, sizeof(paradise_t));
io_sethandler(0x03c0, 0x0020, paradise_in, NULL, NULL, paradise_out, NULL, NULL, paradise);
svga_init(&paradise->svga, paradise, memsize,
paradise_recalctimings,
paradise_in, paradise_out,
NULL,
NULL);
mem_mapping_set_handler(&paradise->svga.mapping, paradise_read, NULL, NULL, paradise_write, NULL, NULL);
mem_mapping_set_p(&paradise->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(&paradise->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(&paradise->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(&paradise->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(&paradise->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(&paradise->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
};

View File

@@ -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
View 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
View 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);

View File

@@ -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", &paradise_wd90c11_device, GFX_WD90C11 },
{ "[ISA] Paradise PVGA1A", "pvga1a", &paradise_pvga1a_device, GFX_PVGA1A },
{ "[ISA] Paradise WD90C11-LR", "wd90c11", &paradise_wd90c11_device, GFX_WD90C11 },
{ "[ISA] Paradise WD90C30-LR", "wd90c30", &paradise_wd90c30_device, GFX_WD90C30 },
{ "[ISA] Plantronics ColorPlus", "plantronics", &colorplus_device, GFX_COLORPLUS },
{"[ISA] TI CF62011 SVGA", "ti_cf62011",
&ti_cf62011_device, GFX_TICF62011 },

View File

@@ -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);

View File

@@ -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;

View File

@@ -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 \