mirror of
https://github.com/86Box/86Box.git
synced 2026-02-23 09:58:19 -07:00
Fixes for the (S)VGA common DAC and some card-specific DAT's (ATi 68860, BT48x family, and the Cirrus Logic DAC), fixes Star Control II among other things.
This commit is contained in:
2174
backup code/config - Cópia.c
Normal file
2174
backup code/config - Cópia.c
Normal file
File diff suppressed because it is too large
Load Diff
856
backup code/disk/hdc_esdi_mfm.c
Normal file
856
backup code/disk/hdc_esdi_mfm.c
Normal file
@@ -0,0 +1,856 @@
|
||||
/*
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
*
|
||||
* This file is part of the 86Box distribution.
|
||||
*
|
||||
* Driver for the MFM controller (WD1007-vse1) for PC/AT.
|
||||
*
|
||||
* Version: @(#)hdc_mfm_at.c 1.0.13 2018/05/02
|
||||
*
|
||||
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
* Fred N. van Kempen, <decwiz@yahoo.com>
|
||||
*
|
||||
* Copyright 2008-2018 Sarah Walker.
|
||||
* Copyright 2016-2018 Miran Grca.
|
||||
* Copyright 2017,2018 Fred N. van Kempen.
|
||||
*/
|
||||
#define _LARGEFILE_SOURCE
|
||||
#define _LARGEFILE64_SOURCE
|
||||
#define _GNU_SOURCE
|
||||
#include <stdarg.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <wchar.h>
|
||||
#define HAVE_STDARG_H
|
||||
#include "../86box.h"
|
||||
#include "../device.h"
|
||||
#include "../io.h"
|
||||
#include "../mem.h"
|
||||
#include "../pic.h"
|
||||
#include "../rom.h"
|
||||
#include "../cpu/cpu.h"
|
||||
#include "../machine/machine.h"
|
||||
#include "../timer.h"
|
||||
#include "../plat.h"
|
||||
#include "../ui.h"
|
||||
#include "hdc.h"
|
||||
#include "hdd.h"
|
||||
|
||||
|
||||
#define HDC_TIME (TIMER_USEC*10LL)
|
||||
#define BIOS_FILE L"roms/hdd/mfm_at/62-000279-061.bin"
|
||||
|
||||
#define STAT_ERR 0x01
|
||||
#define STAT_INDEX 0x02
|
||||
#define STAT_CORRECTED_DATA 0x04
|
||||
#define STAT_DRQ 0x08 /* Data request */
|
||||
#define STAT_DSC 0x10
|
||||
#define STAT_SEEK_COMPLETE 0x20
|
||||
#define STAT_READY 0x40
|
||||
#define STAT_BUSY 0x80
|
||||
|
||||
#define ERR_DAM_NOT_FOUND 0x01 /* Data Address Mark not found */
|
||||
#define ERR_TR000 0x02 /* track 0 not found */
|
||||
#define ERR_ABRT 0x04 /* command aborted */
|
||||
#define ERR_ID_NOT_FOUND 0x10 /* ID not found */
|
||||
#define ERR_DATA_CRC 0x40 /* data CRC error */
|
||||
#define ERR_BAD_BLOCK 0x80 /* bad block detected */
|
||||
|
||||
#define CMD_NOP 0x00
|
||||
#define CMD_RESTORE 0x10
|
||||
#define CMD_READ 0x20
|
||||
#define CMD_WRITE 0x30
|
||||
#define CMD_VERIFY 0x40
|
||||
#define CMD_FORMAT 0x50
|
||||
#define CMD_SEEK 0x70
|
||||
#define CMD_DIAGNOSE 0x90
|
||||
#define CMD_SET_PARAMETERS 0x91
|
||||
#define CMD_READ_PARAMETERS 0xec
|
||||
|
||||
|
||||
typedef struct {
|
||||
int cfg_spt;
|
||||
int cfg_hpc;
|
||||
int current_cylinder;
|
||||
int real_spt;
|
||||
int real_hpc;
|
||||
int real_tracks;
|
||||
int present;
|
||||
int hdd_num;
|
||||
} drive_t;
|
||||
|
||||
typedef struct {
|
||||
uint8_t status;
|
||||
uint8_t error;
|
||||
int secount,sector,cylinder,head,cylprecomp;
|
||||
uint8_t command;
|
||||
uint8_t fdisk;
|
||||
int pos;
|
||||
|
||||
int drive_sel;
|
||||
int reset;
|
||||
uint16_t buffer[256];
|
||||
int irqstat;
|
||||
|
||||
int64_t callback;
|
||||
|
||||
drive_t drives[2];
|
||||
|
||||
rom_t bios_rom;
|
||||
} mfm_t;
|
||||
|
||||
|
||||
#ifdef ENABLE_MFM_AT_LOG
|
||||
int mfm_at_do_log = ENABLE_MFM_AT_LOG;
|
||||
#endif
|
||||
|
||||
|
||||
static void
|
||||
mfm_at_log(const char *fmt, ...)
|
||||
{
|
||||
#ifdef ENABLE_MFM_AT_LOG
|
||||
va_list ap;
|
||||
|
||||
if (mfm_at_do_log) {
|
||||
va_start(ap, fmt);
|
||||
pclog_ex(fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
static inline void
|
||||
irq_raise(mfm_t *mfm)
|
||||
{
|
||||
if (!(mfm->fdisk & 2))
|
||||
picint(1 << 14);
|
||||
|
||||
mfm->irqstat = 1;
|
||||
}
|
||||
|
||||
|
||||
static inline void
|
||||
irq_lower(mfm_t *mfm)
|
||||
{
|
||||
if (mfm->irqstat) {
|
||||
if (!(mfm->fdisk & 2))
|
||||
picintc(1 << 14);
|
||||
|
||||
mfm->irqstat = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Return the sector offset for the current register values. */
|
||||
static int
|
||||
get_sector(mfm_t *mfm, off64_t *addr)
|
||||
{
|
||||
drive_t *drive = &mfm->drives[mfm->drive_sel];
|
||||
int heads = drive->cfg_hpc;
|
||||
int sectors = drive->cfg_spt;
|
||||
int c, h, s;
|
||||
|
||||
if (mfm->head > heads) {
|
||||
mfm_at_log("mfm_get_sector: past end of configured heads\n");
|
||||
return(1);
|
||||
}
|
||||
|
||||
if (mfm->sector >= sectors+1) {
|
||||
mfm_at_log("mfm_get_sector: past end of configured sectors\n");
|
||||
return(1);
|
||||
}
|
||||
|
||||
if (drive->cfg_spt==drive->real_spt && drive->cfg_hpc==drive->real_hpc) {
|
||||
*addr = ((((off64_t) mfm->cylinder * heads) + mfm->head) *
|
||||
sectors) + (mfm->sector - 1);
|
||||
} else {
|
||||
/*
|
||||
* When performing translation, the firmware seems to leave 1
|
||||
* sector per track inaccessible (spare sector)
|
||||
*/
|
||||
|
||||
*addr = ((((off64_t) mfm->cylinder * heads) + mfm->head) *
|
||||
sectors) + (mfm->sector - 1);
|
||||
|
||||
s = *addr % (drive->real_spt - 1);
|
||||
h = (*addr / (drive->real_spt - 1)) % drive->real_hpc;
|
||||
c = (*addr / (drive->real_spt - 1)) / drive->real_hpc;
|
||||
|
||||
*addr = ((((off64_t)c * drive->real_hpc) + h) * drive->real_spt) + s;
|
||||
}
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
/* Move to the next sector using CHS addressing. */
|
||||
static void
|
||||
next_sector(mfm_t *mfm)
|
||||
{
|
||||
drive_t *drive = &mfm->drives[mfm->drive_sel];
|
||||
|
||||
mfm->sector++;
|
||||
if (mfm->sector == (drive->cfg_spt + 1)) {
|
||||
mfm->sector = 1;
|
||||
if (++mfm->head == drive->cfg_hpc) {
|
||||
mfm->head = 0;
|
||||
mfm->cylinder++;
|
||||
if (drive->current_cylinder < drive->real_tracks)
|
||||
drive->current_cylinder++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
mfm_writew(uint16_t port, uint16_t val, void *priv)
|
||||
{
|
||||
mfm_t *mfm = (mfm_t *)priv;
|
||||
|
||||
mfm->buffer[mfm->pos >> 1] = val;
|
||||
mfm->pos += 2;
|
||||
|
||||
if (mfm->pos >= 512) {
|
||||
mfm->pos = 0;
|
||||
mfm->status = STAT_BUSY;
|
||||
timer_clock();
|
||||
/* 390.625 us per sector at 10 Mbit/s = 1280 kB/s. */
|
||||
mfm->callback = (3125LL * TIMER_USEC) / 8LL;
|
||||
timer_update_outstanding();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
mfm_write(uint16_t port, uint8_t val, void *priv)
|
||||
{
|
||||
mfm_t *mfm = (mfm_t *)priv;
|
||||
|
||||
mfm_at_log("WD1007 write(%04x, %02x)\n", port, val);
|
||||
|
||||
switch (port) {
|
||||
case 0x1f0: /* data */
|
||||
mfm_writew(port, val | (val << 8), priv);
|
||||
return;
|
||||
|
||||
case 0x1f1: /* write precompensation */
|
||||
mfm->cylprecomp = val;
|
||||
return;
|
||||
|
||||
case 0x1f2: /* sector count */
|
||||
mfm->secount = val;
|
||||
return;
|
||||
|
||||
case 0x1f3: /* sector */
|
||||
mfm->sector = val;
|
||||
return;
|
||||
|
||||
case 0x1f4: /* cylinder low */
|
||||
mfm->cylinder = (mfm->cylinder & 0xFF00) | val;
|
||||
return;
|
||||
|
||||
case 0x1f5: /* cylinder high */
|
||||
mfm->cylinder = (mfm->cylinder & 0xFF) | (val << 8);
|
||||
return;
|
||||
|
||||
case 0x1f6: /* drive/Head */
|
||||
mfm->head = val & 0xF;
|
||||
mfm->drive_sel = (val & 0x10) ? 1 : 0;
|
||||
if (mfm->drives[mfm->drive_sel].present) {
|
||||
mfm->status = STAT_READY|STAT_DSC;
|
||||
} else {
|
||||
mfm->status = 0;
|
||||
}
|
||||
return;
|
||||
|
||||
case 0x1f7: /* command register */
|
||||
irq_lower(mfm);
|
||||
mfm->command = val;
|
||||
mfm->error = 0;
|
||||
|
||||
mfm_at_log("WD1007: command %02x\n", val & 0xf0);
|
||||
|
||||
switch (val & 0xf0) {
|
||||
case CMD_RESTORE:
|
||||
mfm->command &= ~0x0f; /*mask off step rate*/
|
||||
mfm->status = STAT_BUSY;
|
||||
timer_clock();
|
||||
mfm->callback = 200LL*HDC_TIME;
|
||||
timer_update_outstanding();
|
||||
break;
|
||||
|
||||
case CMD_SEEK:
|
||||
mfm->command &= ~0x0f; /*mask off step rate*/
|
||||
mfm->status = STAT_BUSY;
|
||||
timer_clock();
|
||||
mfm->callback = 200LL*HDC_TIME;
|
||||
timer_update_outstanding();
|
||||
break;
|
||||
|
||||
default:
|
||||
switch (val) {
|
||||
case CMD_NOP:
|
||||
mfm->status = STAT_BUSY;
|
||||
timer_clock();
|
||||
mfm->callback = 200LL*HDC_TIME;
|
||||
timer_update_outstanding();
|
||||
break;
|
||||
|
||||
case CMD_READ:
|
||||
case CMD_READ+1:
|
||||
case CMD_READ+2:
|
||||
case CMD_READ+3:
|
||||
mfm->command &= ~0x03;
|
||||
if (val & 0x02)
|
||||
fatal("Read with ECC\n");
|
||||
|
||||
case 0xa0:
|
||||
mfm->status = STAT_BUSY;
|
||||
timer_clock();
|
||||
mfm->callback = 200LL*HDC_TIME;
|
||||
timer_update_outstanding();
|
||||
break;
|
||||
|
||||
case CMD_WRITE:
|
||||
case CMD_WRITE+1:
|
||||
case CMD_WRITE+2:
|
||||
case CMD_WRITE+3:
|
||||
mfm->command &= ~0x03;
|
||||
if (val & 0x02)
|
||||
fatal("Write with ECC\n");
|
||||
mfm->status = STAT_DRQ | STAT_DSC;
|
||||
mfm->pos = 0;
|
||||
break;
|
||||
|
||||
case CMD_VERIFY:
|
||||
case CMD_VERIFY+1:
|
||||
mfm->command &= ~0x01;
|
||||
mfm->status = STAT_BUSY;
|
||||
timer_clock();
|
||||
mfm->callback = 200LL*HDC_TIME;
|
||||
timer_update_outstanding();
|
||||
break;
|
||||
|
||||
case CMD_FORMAT:
|
||||
mfm->status = STAT_DRQ;
|
||||
mfm->pos = 0;
|
||||
break;
|
||||
|
||||
case CMD_SET_PARAMETERS: /* Initialize Drive Parameters */
|
||||
mfm->status = STAT_BUSY;
|
||||
timer_clock();
|
||||
mfm->callback = 30LL*HDC_TIME;
|
||||
timer_update_outstanding();
|
||||
break;
|
||||
|
||||
case CMD_DIAGNOSE: /* Execute Drive Diagnostics */
|
||||
mfm->status = STAT_BUSY;
|
||||
timer_clock();
|
||||
mfm->callback = 200LL*HDC_TIME;
|
||||
timer_update_outstanding();
|
||||
break;
|
||||
|
||||
case 0xe0: /*???*/
|
||||
case CMD_READ_PARAMETERS:
|
||||
mfm->status = STAT_BUSY;
|
||||
timer_clock();
|
||||
mfm->callback = 200LL*HDC_TIME;
|
||||
timer_update_outstanding();
|
||||
break;
|
||||
|
||||
default:
|
||||
mfm_at_log("WD1007: bad command %02X\n", val);
|
||||
case 0xe8: /*???*/
|
||||
mfm->status = STAT_BUSY;
|
||||
timer_clock();
|
||||
mfm->callback = 200LL*HDC_TIME;
|
||||
timer_update_outstanding();
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x3f6: /* Device control */
|
||||
if ((mfm->fdisk & 0x04) && !(val & 0x04)) {
|
||||
timer_clock();
|
||||
mfm->callback = 500LL*HDC_TIME;
|
||||
timer_update_outstanding();
|
||||
mfm->reset = 1;
|
||||
mfm->status = STAT_BUSY;
|
||||
}
|
||||
|
||||
if (val & 0x04) {
|
||||
/*Drive held in reset*/
|
||||
timer_clock();
|
||||
mfm->callback = 0LL;
|
||||
timer_update_outstanding();
|
||||
mfm->status = STAT_BUSY;
|
||||
}
|
||||
mfm->fdisk = val;
|
||||
/* Lower IRQ on IRQ disable. */
|
||||
if ((val & 2) && !(mfm->fdisk & 0x02))
|
||||
picintc(1 << 14);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static uint16_t
|
||||
mfm_readw(uint16_t port, void *priv)
|
||||
{
|
||||
mfm_t *mfm = (mfm_t *)priv;
|
||||
uint16_t temp;
|
||||
|
||||
temp = mfm->buffer[mfm->pos >> 1];
|
||||
mfm->pos += 2;
|
||||
|
||||
if (mfm->pos >= 512) {
|
||||
mfm->pos=0;
|
||||
mfm->status = STAT_READY | STAT_DSC;
|
||||
if (mfm->command == CMD_READ || mfm->command == 0xa0) {
|
||||
mfm->secount = (mfm->secount - 1) & 0xff;
|
||||
if (mfm->secount) {
|
||||
next_sector(mfm);
|
||||
mfm->status = STAT_BUSY;
|
||||
timer_clock();
|
||||
/* 390.625 us per sector at 10 Mbit/s = 1280 kB/s. */
|
||||
mfm->callback = (3125LL * TIMER_USEC) / 8LL;
|
||||
timer_update_outstanding();
|
||||
} else {
|
||||
ui_sb_update_icon(SB_HDD|HDD_BUS_MFM, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return(temp);
|
||||
}
|
||||
|
||||
|
||||
static uint8_t
|
||||
mfm_read(uint16_t port, void *priv)
|
||||
{
|
||||
mfm_t *mfm = (mfm_t *)priv;
|
||||
uint8_t temp = 0xff;
|
||||
|
||||
switch (port) {
|
||||
case 0x1f0: /* data */
|
||||
temp = mfm_readw(port, mfm) & 0xff;
|
||||
break;
|
||||
|
||||
case 0x1f1: /* error */
|
||||
temp = mfm->error;
|
||||
break;
|
||||
|
||||
case 0x1f2: /* sector count */
|
||||
temp = mfm->secount;
|
||||
break;
|
||||
|
||||
case 0x1f3: /* sector */
|
||||
temp = mfm->sector;
|
||||
break;
|
||||
|
||||
case 0x1f4: /* cylinder low */
|
||||
temp = (uint8_t)(mfm->cylinder&0xff);
|
||||
break;
|
||||
|
||||
case 0x1f5: /* cylinder high */
|
||||
temp = (uint8_t)(mfm->cylinder>>8);
|
||||
break;
|
||||
|
||||
case 0x1f6: /* drive/Head */
|
||||
temp = (uint8_t)(0xa0|mfm->head|(mfm->drive_sel?0x10:0));
|
||||
break;
|
||||
|
||||
case 0x1f7: /* status */
|
||||
irq_lower(mfm);
|
||||
temp = mfm->status;
|
||||
break;
|
||||
}
|
||||
|
||||
mfm_at_log("WD1007 read(%04x) = %02x\n", port, temp);
|
||||
|
||||
return(temp);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
mfm_callback(void *priv)
|
||||
{
|
||||
mfm_t *mfm = (mfm_t *)priv;
|
||||
drive_t *drive = &mfm->drives[mfm->drive_sel];
|
||||
off64_t addr;
|
||||
|
||||
mfm->callback = 0LL;
|
||||
if (mfm->reset) {
|
||||
mfm->status = STAT_READY|STAT_DSC;
|
||||
mfm->error = 1;
|
||||
mfm->secount = 1;
|
||||
mfm->sector = 1;
|
||||
mfm->head = 0;
|
||||
mfm->cylinder = 0;
|
||||
mfm->reset = 0;
|
||||
|
||||
ui_sb_update_icon(SB_HDD|HDD_BUS_MFM, 0);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
mfm_at_log("WD1007: command %02x\n", mfm->command);
|
||||
|
||||
switch (mfm->command) {
|
||||
case CMD_RESTORE:
|
||||
if (! drive->present) {
|
||||
mfm->status = STAT_READY|STAT_ERR|STAT_DSC;
|
||||
mfm->error = ERR_ABRT;
|
||||
} else {
|
||||
drive->current_cylinder = 0;
|
||||
mfm->status = STAT_READY|STAT_DSC;
|
||||
}
|
||||
irq_raise(mfm);
|
||||
break;
|
||||
|
||||
case CMD_SEEK:
|
||||
if (! drive->present) {
|
||||
mfm->status = STAT_READY|STAT_ERR|STAT_DSC;
|
||||
mfm->error = ERR_ABRT;
|
||||
} else {
|
||||
mfm->status = STAT_READY|STAT_DSC;
|
||||
}
|
||||
irq_raise(mfm);
|
||||
break;
|
||||
|
||||
case CMD_READ:
|
||||
if (! drive->present) {
|
||||
mfm->status = STAT_READY|STAT_ERR|STAT_DSC;
|
||||
mfm->error = ERR_ABRT;
|
||||
irq_raise(mfm);
|
||||
break;
|
||||
}
|
||||
|
||||
if (get_sector(mfm, &addr)) {
|
||||
mfm->error = ERR_ID_NOT_FOUND;
|
||||
mfm->status = STAT_READY|STAT_DSC|STAT_ERR;
|
||||
irq_raise(mfm);
|
||||
break;
|
||||
}
|
||||
|
||||
hdd_image_read(drive->hdd_num, addr, 1,
|
||||
(uint8_t *)mfm->buffer);
|
||||
|
||||
mfm->pos = 0;
|
||||
mfm->status = STAT_DRQ|STAT_READY|STAT_DSC;
|
||||
irq_raise(mfm);
|
||||
ui_sb_update_icon(SB_HDD|HDD_BUS_MFM, 1);
|
||||
break;
|
||||
|
||||
case CMD_WRITE:
|
||||
if (! drive->present) {
|
||||
mfm->status = STAT_READY|STAT_ERR|STAT_DSC;
|
||||
mfm->error = ERR_ABRT;
|
||||
irq_raise(mfm);
|
||||
break;
|
||||
}
|
||||
|
||||
if (get_sector(mfm, &addr)) {
|
||||
mfm->error = ERR_ID_NOT_FOUND;
|
||||
mfm->status = STAT_READY|STAT_DSC|STAT_ERR;
|
||||
irq_raise(mfm);
|
||||
break;
|
||||
}
|
||||
|
||||
hdd_image_write(drive->hdd_num, addr, 1,
|
||||
(uint8_t *)mfm->buffer);
|
||||
|
||||
irq_raise(mfm);
|
||||
mfm->secount = (mfm->secount - 1) & 0xff;
|
||||
if (mfm->secount) {
|
||||
mfm->status = STAT_DRQ|STAT_READY|STAT_DSC;
|
||||
mfm->pos = 0;
|
||||
next_sector(mfm);
|
||||
} else {
|
||||
mfm->status = STAT_READY|STAT_DSC;
|
||||
}
|
||||
ui_sb_update_icon(SB_HDD|HDD_BUS_MFM, 1);
|
||||
break;
|
||||
|
||||
case CMD_VERIFY:
|
||||
if (! drive->present) {
|
||||
mfm->status = STAT_READY|STAT_ERR|STAT_DSC;
|
||||
mfm->error = ERR_ABRT;
|
||||
irq_raise(mfm);
|
||||
break;
|
||||
}
|
||||
|
||||
if (get_sector(mfm, &addr)) {
|
||||
mfm->error = ERR_ID_NOT_FOUND;
|
||||
mfm->status = STAT_READY|STAT_DSC|STAT_ERR;
|
||||
irq_raise(mfm);
|
||||
break;
|
||||
}
|
||||
|
||||
hdd_image_read(drive->hdd_num, addr, 1,
|
||||
(uint8_t *)mfm->buffer);
|
||||
|
||||
ui_sb_update_icon(SB_HDD|HDD_BUS_MFM, 1);
|
||||
next_sector(mfm);
|
||||
mfm->secount = (mfm->secount - 1) & 0xff;
|
||||
if (mfm->secount)
|
||||
mfm->callback = 6LL*HDC_TIME;
|
||||
else {
|
||||
mfm->pos = 0;
|
||||
mfm->status = STAT_READY|STAT_DSC;
|
||||
irq_raise(mfm);
|
||||
}
|
||||
break;
|
||||
|
||||
case CMD_FORMAT:
|
||||
if (! drive->present) {
|
||||
mfm->status = STAT_READY|STAT_ERR|STAT_DSC;
|
||||
mfm->error = ERR_ABRT;
|
||||
irq_raise(mfm);
|
||||
break;
|
||||
}
|
||||
|
||||
if (get_sector(mfm, &addr)) {
|
||||
mfm->error = ERR_ID_NOT_FOUND;
|
||||
mfm->status = STAT_READY|STAT_DSC|STAT_ERR;
|
||||
irq_raise(mfm);
|
||||
break;
|
||||
}
|
||||
|
||||
hdd_image_zero(drive->hdd_num, addr, mfm->secount);
|
||||
|
||||
mfm->status = STAT_READY|STAT_DSC;
|
||||
irq_raise(mfm);
|
||||
ui_sb_update_icon(SB_HDD|HDD_BUS_MFM, 1);
|
||||
break;
|
||||
|
||||
case CMD_DIAGNOSE:
|
||||
mfm->error = 1; /*no error detected*/
|
||||
mfm->status = STAT_READY|STAT_DSC;
|
||||
irq_raise(mfm);
|
||||
break;
|
||||
|
||||
case CMD_SET_PARAMETERS: /* Initialize Drive Parameters */
|
||||
if (drive->present == 0) {
|
||||
mfm->status = STAT_READY|STAT_ERR|STAT_DSC;
|
||||
mfm->error = ERR_ABRT;
|
||||
irq_raise(mfm);
|
||||
break;
|
||||
}
|
||||
|
||||
drive->cfg_spt = mfm->secount;
|
||||
drive->cfg_hpc = mfm->head+1;
|
||||
|
||||
mfm_at_log("WD1007: parameters: spt=%i hpc=%i\n", drive->cfg_spt,drive->cfg_hpc);
|
||||
|
||||
if (! mfm->secount)
|
||||
fatal("WD1007: secount=0\n");
|
||||
mfm->status = STAT_READY|STAT_DSC;
|
||||
irq_raise(mfm);
|
||||
break;
|
||||
|
||||
case CMD_NOP:
|
||||
mfm->status = STAT_READY|STAT_ERR|STAT_DSC;
|
||||
mfm->error = ERR_ABRT;
|
||||
irq_raise(mfm);
|
||||
break;
|
||||
|
||||
case 0xe0:
|
||||
if (! drive->present) {
|
||||
mfm->status = STAT_READY|STAT_ERR|STAT_DSC;
|
||||
mfm->error = ERR_ABRT;
|
||||
irq_raise(mfm);
|
||||
break;
|
||||
}
|
||||
|
||||
switch (mfm->cylinder >> 8) {
|
||||
case 0x31:
|
||||
mfm->cylinder = drive->real_tracks;
|
||||
break;
|
||||
|
||||
case 0x33:
|
||||
mfm->cylinder = drive->real_hpc;
|
||||
break;
|
||||
|
||||
case 0x35:
|
||||
mfm->cylinder = 0x200;
|
||||
break;
|
||||
|
||||
case 0x36:
|
||||
mfm->cylinder = drive->real_spt;
|
||||
break;
|
||||
|
||||
default:
|
||||
mfm_at_log("WD1007: bad read config %02x\n",
|
||||
mfm->cylinder >> 8);
|
||||
}
|
||||
mfm->status = STAT_READY|STAT_DSC;
|
||||
irq_raise(mfm);
|
||||
break;
|
||||
|
||||
case 0xa0:
|
||||
if (! drive->present) {
|
||||
mfm->status = STAT_READY|STAT_ERR|STAT_DSC;
|
||||
mfm->error = ERR_ABRT;
|
||||
} else {
|
||||
memset(mfm->buffer, 0x00, 512);
|
||||
memset(&mfm->buffer[3], 0xff, 512-6);
|
||||
mfm->pos = 0;
|
||||
mfm->status = STAT_DRQ|STAT_READY|STAT_DSC;
|
||||
}
|
||||
irq_raise(mfm);
|
||||
break;
|
||||
|
||||
case CMD_READ_PARAMETERS:
|
||||
if (! drive->present) {
|
||||
mfm->status = STAT_READY|STAT_ERR|STAT_DSC;
|
||||
mfm->error = ERR_ABRT;
|
||||
irq_raise(mfm);
|
||||
break;
|
||||
}
|
||||
|
||||
memset(mfm->buffer, 0x00, 512);
|
||||
mfm->buffer[0] = 0x44; /* general configuration */
|
||||
mfm->buffer[1] = drive->real_tracks; /* number of non-removable cylinders */
|
||||
mfm->buffer[2] = 0; /* number of removable cylinders */
|
||||
mfm->buffer[3] = drive->real_hpc; /* number of heads */
|
||||
mfm->buffer[4] = 600; /* number of unformatted bytes/track */
|
||||
mfm->buffer[5] = mfm->buffer[4] * drive->real_spt; /* number of unformatted bytes/sector */
|
||||
mfm->buffer[6] = drive->real_spt; /* number of sectors */
|
||||
mfm->buffer[7] = 0; /*minimum bytes in inter-sector gap*/
|
||||
mfm->buffer[8] = 0; /* minimum bytes in postamble */
|
||||
mfm->buffer[9] = 0; /* number of words of vendor status */
|
||||
/* controller info */
|
||||
mfm->buffer[20] = 2; /* controller type */
|
||||
mfm->buffer[21] = 1; /* sector buffer size, in sectors */
|
||||
mfm->buffer[22] = 0; /* ecc bytes appended */
|
||||
mfm->buffer[27] = 'W' | ('D' << 8);
|
||||
mfm->buffer[28] = '1' | ('0' << 8);
|
||||
mfm->buffer[29] = '0' | ('7' << 8);
|
||||
mfm->buffer[30] = 'V' | ('-' << 8);
|
||||
mfm->buffer[31] = 'S' | ('E' << 8);
|
||||
mfm->buffer[32] = '1';
|
||||
mfm->buffer[47] = 0; /* sectors per interrupt */
|
||||
mfm->buffer[48] = 0; /* can use double word read/write? */
|
||||
mfm->pos = 0;
|
||||
mfm->status = STAT_DRQ|STAT_READY|STAT_DSC;
|
||||
irq_raise(mfm);
|
||||
break;
|
||||
|
||||
default:
|
||||
mfm_at_log("WD1007: callback on unknown command %02x\n", mfm->command);
|
||||
/*FALLTHROUGH*/
|
||||
|
||||
case 0xe8:
|
||||
mfm->status = STAT_READY|STAT_ERR|STAT_DSC;
|
||||
mfm->error = ERR_ABRT;
|
||||
irq_raise(mfm);
|
||||
break;
|
||||
}
|
||||
|
||||
ui_sb_update_icon(SB_HDD|HDD_BUS_MFM, 0);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
loadhd(mfm_t *mfm, int hdd_num, int d, const wchar_t *fn)
|
||||
{
|
||||
drive_t *drive = &mfm->drives[hdd_num];
|
||||
|
||||
if (! hdd_image_load(d)) {
|
||||
mfm_at_log("WD1007: drive %d not present!\n", d);
|
||||
drive->present = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
drive->cfg_spt = drive->real_spt = hdd[d].spt;
|
||||
drive->cfg_hpc = drive->real_hpc = hdd[d].hpc;
|
||||
drive->real_tracks = hdd[d].tracks;
|
||||
drive->hdd_num = d;
|
||||
drive->present = 1;
|
||||
}
|
||||
|
||||
|
||||
static void *
|
||||
wd1007vse1_init(const device_t *info)
|
||||
{
|
||||
int c, d;
|
||||
|
||||
mfm_t *mfm = malloc(sizeof(mfm_t));
|
||||
memset(mfm, 0x00, sizeof(mfm_t));
|
||||
|
||||
c = 0;
|
||||
for (d=0; d<HDD_NUM; d++) {
|
||||
if ((hdd[d].bus==HDD_BUS_MFM) && (hdd[d].mfm_channel<MFM_NUM)) {
|
||||
loadhd(mfm, hdd[d].mfm_channel, d, hdd[d].fn);
|
||||
|
||||
if (++c >= MFM_NUM) break;
|
||||
}
|
||||
}
|
||||
|
||||
mfm->status = STAT_READY|STAT_DSC;
|
||||
mfm->error = 1;
|
||||
|
||||
rom_init(&mfm->bios_rom,
|
||||
BIOS_FILE, 0xc8000, 0x4000, 0x3fff, 0, MEM_MAPPING_EXTERNAL);
|
||||
|
||||
io_sethandler(0x01f0, 1,
|
||||
mfm_read, mfm_readw, NULL,
|
||||
mfm_write, mfm_writew, NULL, mfm);
|
||||
io_sethandler(0x01f1, 7,
|
||||
mfm_read, NULL, NULL,
|
||||
mfm_write, NULL, NULL, mfm);
|
||||
io_sethandler(0x03f6, 1, NULL, NULL, NULL,
|
||||
mfm_write, NULL, NULL, mfm);
|
||||
|
||||
timer_add(mfm_callback, &mfm->callback, &mfm->callback, mfm);
|
||||
|
||||
ui_sb_update_icon(SB_HDD | HDD_BUS_MFM, 0);
|
||||
|
||||
return(mfm);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
wd1007vse1_close(void *priv)
|
||||
{
|
||||
mfm_t *mfm = (mfm_t *)priv;
|
||||
drive_t *drive;
|
||||
int d;
|
||||
|
||||
for (d=0; d<2; d++) {
|
||||
drive = &mfm->drives[d];
|
||||
|
||||
hdd_image_close(drive->hdd_num);
|
||||
}
|
||||
|
||||
free(mfm);
|
||||
|
||||
ui_sb_update_icon(SB_HDD | HDD_BUS_MFM, 0);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
wd1007vse1_available(void)
|
||||
{
|
||||
return(rom_present(BIOS_FILE));
|
||||
}
|
||||
|
||||
|
||||
const device_t mfm_at_wd1007vse1_device = {
|
||||
"Western Digital WD1007V-SE1 (MFM)",
|
||||
DEVICE_ISA | DEVICE_AT,
|
||||
0,
|
||||
wd1007vse1_init, wd1007vse1_close, NULL,
|
||||
wd1007vse1_available,
|
||||
NULL, NULL,
|
||||
NULL
|
||||
};
|
||||
3023
backup code/disk/hdc_ide - Cópia.c
Normal file
3023
backup code/disk/hdc_ide - Cópia.c
Normal file
File diff suppressed because it is too large
Load Diff
2859
backup code/disk/zip - Cópia.c
Normal file
2859
backup code/disk/zip - Cópia.c
Normal file
File diff suppressed because it is too large
Load Diff
156
backup code/disk/zip - Cópia.h
Normal file
156
backup code/disk/zip - Cópia.h
Normal file
@@ -0,0 +1,156 @@
|
||||
/*
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
*
|
||||
* This file is part of the 86Box distribution.
|
||||
*
|
||||
* Implementation of the Iomega ZIP drive with SCSI(-like)
|
||||
* commands, for both ATAPI and SCSI usage.
|
||||
*
|
||||
* Version: @(#)zip.h 1.0.6 2018/04/30
|
||||
*
|
||||
* Author: Miran Grca, <mgrca8@gmail.com>
|
||||
*
|
||||
* Copyright 2018 Miran Grca.
|
||||
*/
|
||||
#ifndef EMU_ZIP_H
|
||||
#define EMU_ZIP_H
|
||||
|
||||
|
||||
#define ZIP_NUM 4
|
||||
|
||||
#define ZIP_PHASE_IDLE 0x00
|
||||
#define ZIP_PHASE_COMMAND 0x01
|
||||
#define ZIP_PHASE_COMPLETE 0x02
|
||||
#define ZIP_PHASE_DATA_IN 0x03
|
||||
#define ZIP_PHASE_DATA_IN_DMA 0x04
|
||||
#define ZIP_PHASE_DATA_OUT 0x05
|
||||
#define ZIP_PHASE_DATA_OUT_DMA 0x06
|
||||
#define ZIP_PHASE_ERROR 0x80
|
||||
|
||||
#define BUF_SIZE 32768
|
||||
|
||||
#define ZIP_TIME (5LL * 100LL * (1LL << TIMER_SHIFT))
|
||||
|
||||
#define ZIP_SECTORS (96*2048)
|
||||
|
||||
#define ZIP_250_SECTORS (489532)
|
||||
|
||||
|
||||
enum {
|
||||
ZIP_BUS_DISABLED = 0,
|
||||
ZIP_BUS_ATAPI = 4,
|
||||
ZIP_BUS_SCSI,
|
||||
ZIP_BUS_USB
|
||||
};
|
||||
|
||||
|
||||
typedef struct {
|
||||
uint8_t previous_command, error,
|
||||
features, status,
|
||||
phase, *buffer,
|
||||
atapi_cdb[16],
|
||||
current_cdb[16],
|
||||
sense[256];
|
||||
|
||||
uint16_t request_length, max_transfer_len;
|
||||
|
||||
int toctimes, media_status,
|
||||
is_dma, requested_blocks,
|
||||
current_page_len, current_page_pos,
|
||||
total_length, written_length,
|
||||
mode_select_phase, do_page_save,
|
||||
callback, data_pos,
|
||||
packet_status, unit_attention,
|
||||
cdb_len_setting, cdb_len,
|
||||
request_pos, total_read,
|
||||
block_total, all_blocks_total,
|
||||
old_len, block_descriptor_len,
|
||||
init_length;
|
||||
|
||||
uint32_t sector_pos, sector_len,
|
||||
packet_len, pos,
|
||||
seek_pos;
|
||||
|
||||
uint64_t current_page_code;
|
||||
} zip_t;
|
||||
|
||||
typedef struct {
|
||||
unsigned int bus_type; /* 0 = ATAPI, 1 = SCSI */
|
||||
uint8_t ide_channel,
|
||||
bus_mode; /* Bit 0 = PIO suported;
|
||||
Bit 1 = DMA supportd. */
|
||||
|
||||
unsigned int scsi_device_id, scsi_device_lun,
|
||||
is_250;
|
||||
|
||||
wchar_t image_path[1024],
|
||||
prev_image_path[1024];
|
||||
|
||||
int read_only, ui_writeprot;
|
||||
|
||||
uint32_t medium_size, base;
|
||||
|
||||
FILE *f;
|
||||
} zip_drive_t;
|
||||
|
||||
|
||||
extern zip_t *zip[ZIP_NUM];
|
||||
extern zip_drive_t zip_drives[ZIP_NUM];
|
||||
extern uint8_t atapi_zip_drives[8];
|
||||
extern uint8_t scsi_zip_drives[16][8];
|
||||
|
||||
#define zip_sense_error zip[id]->sense[0]
|
||||
#define zip_sense_key zip[id]->sense[2]
|
||||
#define zip_asc zip[id]->sense[12]
|
||||
#define zip_ascq zip[id]->sense[13]
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
extern int (*ide_bus_master_read)(int channel, uint8_t *data, int transfer_length, void *priv);
|
||||
extern int (*ide_bus_master_write)(int channel, uint8_t *data, int transfer_length, void *priv);
|
||||
extern void (*ide_bus_master_set_irq)(int channel, void *priv);
|
||||
extern void *ide_bus_master_priv[2];
|
||||
extern void ioctl_close(uint8_t id);
|
||||
|
||||
extern uint32_t zip_mode_sense_get_channel(uint8_t id, int channel);
|
||||
extern uint32_t zip_mode_sense_get_volume(uint8_t id, int channel);
|
||||
extern void build_atapi_zip_map(void);
|
||||
extern void build_scsi_zip_map(void);
|
||||
extern int zip_ZIP_PHASE_to_scsi(uint8_t id);
|
||||
extern int zip_atapi_phase_to_scsi(uint8_t id);
|
||||
extern void zip_command(uint8_t id, uint8_t *cdb);
|
||||
extern void zip_phase_callback(uint8_t id);
|
||||
extern uint32_t zip_read(uint8_t channel, int length);
|
||||
extern void zip_write(uint8_t channel, uint32_t val, int length);
|
||||
|
||||
extern void zip_close(uint8_t id);
|
||||
extern void zip_disk_reload(uint8_t id);
|
||||
extern void zip_reset(uint8_t id);
|
||||
extern void zip_set_signature(int id);
|
||||
extern void zip_request_sense_for_scsi(uint8_t id, uint8_t *buffer, uint8_t alloc_length);
|
||||
extern void zip_update_cdb(uint8_t *cdb, int lba_pos, int number_of_blocks);
|
||||
extern void zip_insert(uint8_t id);
|
||||
|
||||
extern int find_zip_for_scsi_id(uint8_t scsi_id, uint8_t scsi_lun);
|
||||
extern int zip_read_capacity(uint8_t id, uint8_t *cdb, uint8_t *buffer, uint32_t *len);
|
||||
|
||||
extern void zip_global_init(void);
|
||||
extern void zip_hard_reset(void);
|
||||
|
||||
extern int zip_load(uint8_t id, wchar_t *fn);
|
||||
|
||||
extern void zip_destroy_drives(void);
|
||||
extern void zip_close(uint8_t id);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#endif /*EMU_ZIP_H*/
|
||||
853
backup code/dma.c.old
Normal file
853
backup code/dma.c.old
Normal file
@@ -0,0 +1,853 @@
|
||||
/*
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
*
|
||||
* This file is part of the 86Box distribution.
|
||||
*
|
||||
* Implementation of the Intel DMA controllers.
|
||||
*
|
||||
* Version: @(#)dma.c 1.0.9 2018/03/28
|
||||
*
|
||||
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
*
|
||||
* Copyright 2008-2018 Sarah Walker.
|
||||
* Copyright 2016-2018 Miran Grca.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <wchar.h>
|
||||
#include "86box.h"
|
||||
#include "cpu/cpu.h"
|
||||
#include "cpu/x86.h"
|
||||
#include "machine/machine.h"
|
||||
#include "mca.h"
|
||||
#include "mem.h"
|
||||
#include "io.h"
|
||||
#include "dma.h"
|
||||
|
||||
|
||||
static uint8_t dmaregs[16];
|
||||
static uint8_t dma16regs[16];
|
||||
static uint8_t dmapages[16];
|
||||
|
||||
dma_t dma[8];
|
||||
|
||||
static int dma_wp, dma16_wp;
|
||||
static uint8_t dma_m;
|
||||
static uint8_t dma_stat;
|
||||
static uint8_t dma_stat_rq;
|
||||
static uint8_t dma_command, dma16_command;
|
||||
|
||||
static struct
|
||||
{
|
||||
int xfr_command, xfr_channel;
|
||||
int byte_ptr;
|
||||
|
||||
int is_ps2;
|
||||
} dma_ps2;
|
||||
|
||||
#define DMA_PS2_IOA (1 << 0)
|
||||
#define DMA_PS2_XFER_MEM_TO_IO (1 << 2)
|
||||
#define DMA_PS2_XFER_IO_TO_MEM (3 << 2)
|
||||
#define DMA_PS2_XFER_MASK (3 << 2)
|
||||
#define DMA_PS2_DEC2 (1 << 4)
|
||||
#define DMA_PS2_SIZE16 (1 << 6)
|
||||
|
||||
static void dma_ps2_run(int channel);
|
||||
|
||||
void dma_reset(void)
|
||||
{
|
||||
int c;
|
||||
|
||||
dma_wp = dma16_wp = 0;
|
||||
dma_m = 0;
|
||||
|
||||
for (c = 0; c < 16; c++)
|
||||
dmaregs[c] = 0;
|
||||
for (c = 0; c < 8; c++)
|
||||
{
|
||||
dma[c].mode = 0;
|
||||
dma[c].ac = 0;
|
||||
dma[c].cc = 0;
|
||||
dma[c].ab = 0;
|
||||
dma[c].cb = 0;
|
||||
dma[c].size = (c & 4) ? 1 : 0;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t dma_read(uint16_t addr, void *priv)
|
||||
{
|
||||
int channel = (addr >> 1) & 3;
|
||||
uint8_t temp;
|
||||
switch (addr & 0xf)
|
||||
{
|
||||
case 0: case 2: case 4: case 6: /*Address registers*/
|
||||
dma_wp ^= 1;
|
||||
if (dma_wp)
|
||||
return dma[channel].ac & 0xff;
|
||||
return (dma[channel].ac >> 8) & 0xff;
|
||||
|
||||
case 1: case 3: case 5: case 7: /*Count registers*/
|
||||
dma_wp ^= 1;
|
||||
if (dma_wp)
|
||||
temp = dma[channel].cc & 0xff;
|
||||
else
|
||||
temp = dma[channel].cc >> 8;
|
||||
return temp;
|
||||
|
||||
case 8: /*Status register*/
|
||||
temp = dma_stat & 0xf;
|
||||
dma_stat &= ~0xf;
|
||||
return temp;
|
||||
|
||||
case 0xd:
|
||||
return 0;
|
||||
}
|
||||
return dmaregs[addr & 0xf];
|
||||
}
|
||||
|
||||
void dma_write(uint16_t addr, uint8_t val, void *priv)
|
||||
{
|
||||
int channel = (addr >> 1) & 3;
|
||||
dmaregs[addr & 0xf] = val;
|
||||
switch (addr & 0xf)
|
||||
{
|
||||
case 0: case 2: case 4: case 6: /*Address registers*/
|
||||
dma_wp ^= 1;
|
||||
if (dma_wp)
|
||||
dma[channel].ab = (dma[channel].ab & 0xffff00) | val;
|
||||
else
|
||||
dma[channel].ab = (dma[channel].ab & 0xff00ff) | (val << 8);
|
||||
dma[channel].ac = dma[channel].ab;
|
||||
return;
|
||||
|
||||
case 1: case 3: case 5: case 7: /*Count registers*/
|
||||
dma_wp ^= 1;
|
||||
if (dma_wp)
|
||||
dma[channel].cb = (dma[channel].cb & 0xff00) | val;
|
||||
else
|
||||
dma[channel].cb = (dma[channel].cb & 0x00ff) | (val << 8);
|
||||
dma[channel].cc = dma[channel].cb;
|
||||
return;
|
||||
|
||||
case 8: /*Control register*/
|
||||
dma_command = val;
|
||||
return;
|
||||
|
||||
case 0xa: /*Mask*/
|
||||
if (val & 4)
|
||||
dma_m |= (1 << (val & 3));
|
||||
else
|
||||
dma_m &= ~(1 << (val & 3));
|
||||
return;
|
||||
|
||||
case 0xb: /*Mode*/
|
||||
channel = (val & 3);
|
||||
dma[channel].mode = val;
|
||||
if (dma_ps2.is_ps2)
|
||||
{
|
||||
dma[channel].ps2_mode &= ~0x1c;
|
||||
if (val & 0x20)
|
||||
dma[channel].ps2_mode |= 0x10;
|
||||
if ((val & 0xc) == 8)
|
||||
dma[channel].ps2_mode |= 4;
|
||||
else if ((val & 0xc) == 4)
|
||||
dma[channel].ps2_mode |= 0xc;
|
||||
}
|
||||
return;
|
||||
|
||||
case 0xc: /*Clear FF*/
|
||||
dma_wp = 0;
|
||||
return;
|
||||
|
||||
case 0xd: /*Master clear*/
|
||||
dma_wp = 0;
|
||||
dma_m |= 0xf;
|
||||
return;
|
||||
|
||||
case 0xf: /*Mask write*/
|
||||
dma_m = (dma_m & 0xf0) | (val & 0xf);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static uint8_t dma_ps2_read(uint16_t addr, void *priv)
|
||||
{
|
||||
dma_t *dma_c = &dma[dma_ps2.xfr_channel];
|
||||
uint8_t temp = 0xff;
|
||||
|
||||
switch (addr)
|
||||
{
|
||||
case 0x1a:
|
||||
switch (dma_ps2.xfr_command)
|
||||
{
|
||||
case 2: /*Address*/
|
||||
case 3:
|
||||
switch (dma_ps2.byte_ptr)
|
||||
{
|
||||
case 0:
|
||||
temp = dma_c->ac & 0xff;
|
||||
dma_ps2.byte_ptr = 1;
|
||||
break;
|
||||
case 1:
|
||||
temp = (dma_c->ac >> 8) & 0xff;
|
||||
dma_ps2.byte_ptr = 2;
|
||||
break;
|
||||
case 2:
|
||||
temp = (dma_c->ac >> 16) & 0xff;
|
||||
dma_ps2.byte_ptr = 0;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 4: /*Count*/
|
||||
case 5:
|
||||
if (dma_ps2.byte_ptr)
|
||||
temp = dma_c->cc >> 8;
|
||||
else
|
||||
temp = dma_c->cc & 0xff;
|
||||
dma_ps2.byte_ptr = (dma_ps2.byte_ptr + 1) & 1;
|
||||
break;
|
||||
case 6: /*Read DMA status*/
|
||||
if (dma_ps2.byte_ptr)
|
||||
{
|
||||
temp = ((dma_stat_rq & 0xf0) >> 4) | (dma_stat & 0xf0);
|
||||
dma_stat &= ~0xf0;
|
||||
dma_stat_rq &= ~0xf0;
|
||||
}
|
||||
else
|
||||
{
|
||||
temp = (dma_stat_rq & 0xf) | ((dma_stat & 0xf) << 4);
|
||||
dma_stat &= ~0xf;
|
||||
dma_stat_rq &= ~0xf;
|
||||
}
|
||||
dma_ps2.byte_ptr = (dma_ps2.byte_ptr + 1) & 1;
|
||||
break;
|
||||
case 7: /*Mode*/
|
||||
temp = dma_c->ps2_mode;
|
||||
break;
|
||||
case 8: /*Arbitration Level*/
|
||||
temp = dma_c->arb_level;
|
||||
break;
|
||||
|
||||
default:
|
||||
fatal("Bad XFR Read command %i channel %i\n", dma_ps2.xfr_command, dma_ps2.xfr_channel);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return temp;
|
||||
}
|
||||
|
||||
static void dma_ps2_write(uint16_t addr, uint8_t val, void *priv)
|
||||
{
|
||||
dma_t *dma_c = &dma[dma_ps2.xfr_channel];
|
||||
uint8_t mode;
|
||||
|
||||
switch (addr)
|
||||
{
|
||||
case 0x18:
|
||||
dma_ps2.xfr_channel = val & 0x7;
|
||||
dma_ps2.xfr_command = val >> 4;
|
||||
dma_ps2.byte_ptr = 0;
|
||||
switch (dma_ps2.xfr_command)
|
||||
{
|
||||
case 9: /*Set DMA mask*/
|
||||
dma_m |= (1 << dma_ps2.xfr_channel);
|
||||
break;
|
||||
case 0xa: /*Reset DMA mask*/
|
||||
dma_m &= ~(1 << dma_ps2.xfr_channel);
|
||||
break;
|
||||
case 0xb:
|
||||
if (!(dma_m & (1 << dma_ps2.xfr_channel)))
|
||||
dma_ps2_run(dma_ps2.xfr_channel);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 0x1a:
|
||||
switch (dma_ps2.xfr_command)
|
||||
{
|
||||
case 0: /*I/O address*/
|
||||
if (dma_ps2.byte_ptr)
|
||||
dma_c->io_addr = (dma_c->io_addr & 0x00ff) | (val << 8);
|
||||
else
|
||||
dma_c->io_addr = (dma_c->io_addr & 0xff00) | val;
|
||||
dma_ps2.byte_ptr = (dma_ps2.byte_ptr + 1) & 1;
|
||||
break;
|
||||
|
||||
case 2: /*Address*/
|
||||
switch (dma_ps2.byte_ptr)
|
||||
{
|
||||
case 0:
|
||||
dma_c->ac = (dma_c->ac & 0xffff00) | val;
|
||||
dma_ps2.byte_ptr = 1;
|
||||
break;
|
||||
case 1:
|
||||
dma_c->ac = (dma_c->ac & 0xff00ff) | (val << 8);
|
||||
dma_ps2.byte_ptr = 2;
|
||||
break;
|
||||
case 2:
|
||||
dma_c->ac = (dma_c->ac & 0x00ffff) | (val << 16);
|
||||
dma_ps2.byte_ptr = 0;
|
||||
break;
|
||||
}
|
||||
dma_c->ab = dma_c->ac;
|
||||
break;
|
||||
|
||||
case 4: /*Count*/
|
||||
if (dma_ps2.byte_ptr)
|
||||
dma_c->cc = (dma_c->cc & 0xff) | (val << 8);
|
||||
else
|
||||
dma_c->cc = (dma_c->cc & 0xff00) | val;
|
||||
dma_ps2.byte_ptr = (dma_ps2.byte_ptr + 1) & 1;
|
||||
dma_c->cb = dma_c->cc;
|
||||
break;
|
||||
|
||||
case 7: /*Mode register*/
|
||||
mode = 0;
|
||||
if (val & DMA_PS2_DEC2)
|
||||
mode |= 0x20;
|
||||
if ((val & DMA_PS2_XFER_MASK) == DMA_PS2_XFER_MEM_TO_IO)
|
||||
mode |= 8;
|
||||
else if ((val & DMA_PS2_XFER_MASK) == DMA_PS2_XFER_IO_TO_MEM)
|
||||
mode |= 4;
|
||||
dma_c->mode = (dma_c->mode & ~0x2c) | mode;
|
||||
dma_c->ps2_mode = val;
|
||||
dma_c->size = val & DMA_PS2_SIZE16;
|
||||
break;
|
||||
|
||||
case 8: /*Arbitration Level*/
|
||||
dma_c->arb_level = val;
|
||||
break;
|
||||
|
||||
default:
|
||||
fatal("Bad XFR command %i channel %i val %02x\n", dma_ps2.xfr_command, dma_ps2.xfr_channel, val);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t dma16_read(uint16_t addr, void *priv)
|
||||
{
|
||||
int channel = ((addr >> 2) & 3) + 4;
|
||||
uint8_t temp;
|
||||
addr >>= 1;
|
||||
switch (addr & 0xf)
|
||||
{
|
||||
case 0: case 2: case 4: case 6: /*Address registers*/
|
||||
dma16_wp ^= 1;
|
||||
if (dma_ps2.is_ps2)
|
||||
{
|
||||
if (dma16_wp)
|
||||
return dma[channel].ac;
|
||||
return (dma[channel].ac >> 8) & 0xff;
|
||||
}
|
||||
if (dma16_wp)
|
||||
return (dma[channel].ac >> 1) & 0xff;
|
||||
return (dma[channel].ac >> 9) & 0xff;
|
||||
|
||||
case 1: case 3: case 5: case 7: /*Count registers*/
|
||||
dma16_wp ^= 1;
|
||||
if (dma16_wp)
|
||||
temp = dma[channel].cc & 0xff;
|
||||
else
|
||||
temp = dma[channel].cc >> 8;
|
||||
return temp;
|
||||
|
||||
case 8: /*Status register*/
|
||||
temp = dma_stat >> 4;
|
||||
dma_stat &= ~0xf0;
|
||||
return temp;
|
||||
}
|
||||
return dma16regs[addr & 0xf];
|
||||
}
|
||||
|
||||
void dma16_write(uint16_t addr, uint8_t val, void *priv)
|
||||
{
|
||||
int channel = ((addr >> 2) & 3) + 4;
|
||||
addr >>= 1;
|
||||
dma16regs[addr & 0xf] = val;
|
||||
switch (addr & 0xf)
|
||||
{
|
||||
case 0: case 2: case 4: case 6: /*Address registers*/
|
||||
dma16_wp ^= 1;
|
||||
if (dma_ps2.is_ps2)
|
||||
{
|
||||
if (dma16_wp)
|
||||
dma[channel].ab = (dma[channel].ab & 0xffff00) | val;
|
||||
else
|
||||
dma[channel].ab = (dma[channel].ab & 0xff00ff) | (val << 8);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (dma16_wp)
|
||||
dma[channel].ab = (dma[channel].ab & 0xfffe00) | (val << 1);
|
||||
else
|
||||
dma[channel].ab = (dma[channel].ab & 0xfe01ff) | (val << 9);
|
||||
}
|
||||
dma[channel].ac = dma[channel].ab;
|
||||
return;
|
||||
|
||||
case 1: case 3: case 5: case 7: /*Count registers*/
|
||||
dma16_wp ^= 1;
|
||||
if (dma16_wp)
|
||||
dma[channel].cb = (dma[channel].cb & 0xff00) | val;
|
||||
else
|
||||
dma[channel].cb = (dma[channel].cb & 0x00ff) | (val << 8);
|
||||
dma[channel].cc = dma[channel].cb;
|
||||
return;
|
||||
|
||||
case 8: /*Control register*/
|
||||
return;
|
||||
|
||||
case 0xa: /*Mask*/
|
||||
if (val & 4)
|
||||
dma_m |= (0x10 << (val & 3));
|
||||
else
|
||||
dma_m &= ~(0x10 << (val & 3));
|
||||
return;
|
||||
|
||||
case 0xb: /*Mode*/
|
||||
channel = (val & 3) + 4;
|
||||
dma[channel].mode = val;
|
||||
if (dma_ps2.is_ps2)
|
||||
{
|
||||
dma[channel].ps2_mode &= ~0x1c;
|
||||
if (val & 0x20)
|
||||
dma[channel].ps2_mode |= 0x10;
|
||||
if ((val & 0xc) == 8)
|
||||
dma[channel].ps2_mode |= 4;
|
||||
else if ((val & 0xc) == 4)
|
||||
dma[channel].ps2_mode |= 0xc;
|
||||
}
|
||||
return;
|
||||
|
||||
case 0xc: /*Clear FF*/
|
||||
dma16_wp = 0;
|
||||
return;
|
||||
|
||||
case 0xd: /*Master clear*/
|
||||
dma16_wp = 0;
|
||||
dma_m |= 0xf0;
|
||||
return;
|
||||
|
||||
case 0xf: /*Mask write*/
|
||||
dma_m = (dma_m & 0x0f) | ((val & 0xf) << 4);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void dma_page_write(uint16_t addr, uint8_t val, void *priv)
|
||||
{
|
||||
dmapages[addr & 0xf] = val;
|
||||
switch (addr & 0xf)
|
||||
{
|
||||
case 1:
|
||||
dma[2].page = (AT) ? val : val & 0xf;
|
||||
dma[2].ab = (dma[2].ab & 0xffff) | (dma[2].page << 16);
|
||||
dma[2].ac = (dma[2].ac & 0xffff) | (dma[2].page << 16);
|
||||
break;
|
||||
case 2:
|
||||
dma[3].page = (AT) ? val : val & 0xf;
|
||||
dma[3].ab = (dma[3].ab & 0xffff) | (dma[3].page << 16);
|
||||
dma[3].ac = (dma[3].ac & 0xffff) | (dma[3].page << 16);
|
||||
break;
|
||||
case 3:
|
||||
dma[1].page = (AT) ? val : val & 0xf;
|
||||
dma[1].ab = (dma[1].ab & 0xffff) | (dma[1].page << 16);
|
||||
dma[1].ac = (dma[1].ac & 0xffff) | (dma[1].page << 16);
|
||||
break;
|
||||
case 7:
|
||||
dma[0].page = (AT) ? val : val & 0xf;
|
||||
dma[0].ab = (dma[0].ab & 0xffff) | (dma[0].page << 16);
|
||||
dma[0].ac = (dma[0].ac & 0xffff) | (dma[0].page << 16);
|
||||
break;
|
||||
case 0x9:
|
||||
dma[6].page = val & 0xfe;
|
||||
dma[6].ab = (dma[6].ab & 0x1ffff) | (dma[6].page << 16);
|
||||
dma[6].ac = (dma[6].ac & 0x1ffff) | (dma[6].page << 16);
|
||||
break;
|
||||
case 0xa:
|
||||
dma[7].page = val & 0xfe;
|
||||
dma[7].ab = (dma[7].ab & 0x1ffff) | (dma[7].page << 16);
|
||||
dma[7].ac = (dma[7].ac & 0x1ffff) | (dma[7].page << 16);
|
||||
break;
|
||||
case 0xb:
|
||||
dma[5].page = val & 0xfe;
|
||||
dma[5].ab = (dma[5].ab & 0x1ffff) | (dma[5].page << 16);
|
||||
dma[5].ac = (dma[5].ac & 0x1ffff) | (dma[5].page << 16);
|
||||
break;
|
||||
case 0xf:
|
||||
dma[4].page = val & 0xfe;
|
||||
dma[4].ab = (dma[4].ab & 0x1ffff) | (dma[4].page << 16);
|
||||
dma[4].ac = (dma[4].ac & 0x1ffff) | (dma[4].page << 16);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t dma_page_read(uint16_t addr, void *priv)
|
||||
{
|
||||
return dmapages[addr & 0xf];
|
||||
}
|
||||
|
||||
void dma_init(void)
|
||||
{
|
||||
io_sethandler(0x0000, 0x0010, dma_read, NULL, NULL, dma_write, NULL, NULL, NULL);
|
||||
io_sethandler(0x0080, 0x0008, dma_page_read, NULL, NULL, dma_page_write, NULL, NULL, NULL);
|
||||
dma_ps2.is_ps2 = 0;
|
||||
}
|
||||
|
||||
void dma16_init(void)
|
||||
{
|
||||
io_sethandler(0x00C0, 0x0020, dma16_read, NULL, NULL, dma16_write, NULL, NULL, NULL);
|
||||
io_sethandler(0x0088, 0x0008, dma_page_read, NULL, NULL, dma_page_write, NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
void dma_alias_set(void)
|
||||
{
|
||||
io_sethandler(0x0090, 0x0010, dma_page_read, NULL, NULL, dma_page_write, NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
void dma_alias_remove(void)
|
||||
{
|
||||
io_removehandler(0x0090, 0x0010, dma_page_read, NULL, NULL, dma_page_write, NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
void dma_alias_remove_piix(void)
|
||||
{
|
||||
io_removehandler(0x0090, 0x0001, dma_page_read, NULL, NULL, dma_page_write, NULL, NULL, NULL);
|
||||
io_removehandler(0x0094, 0x0003, dma_page_read, NULL, NULL, dma_page_write, NULL, NULL, NULL);
|
||||
io_removehandler(0x0098, 0x0001, dma_page_read, NULL, NULL, dma_page_write, NULL, NULL, NULL);
|
||||
io_removehandler(0x009C, 0x0003, dma_page_read, NULL, NULL, dma_page_write, NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
void ps2_dma_init(void)
|
||||
{
|
||||
io_sethandler(0x0018, 0x0001, dma_ps2_read, NULL, NULL, dma_ps2_write, NULL, NULL, NULL);
|
||||
io_sethandler(0x001a, 0x0001, dma_ps2_read, NULL, NULL, dma_ps2_write, NULL, NULL, NULL);
|
||||
dma_ps2.is_ps2 = 1;
|
||||
}
|
||||
|
||||
|
||||
uint8_t _dma_read(uint32_t addr)
|
||||
{
|
||||
uint8_t temp = mem_readb_phys_dma(addr);
|
||||
return temp;
|
||||
}
|
||||
|
||||
void _dma_write(uint32_t addr, uint8_t val)
|
||||
{
|
||||
mem_writeb_phys_dma(addr, val);
|
||||
mem_invalidate_range(addr, addr);
|
||||
}
|
||||
|
||||
int dma_channel_read(int channel)
|
||||
{
|
||||
dma_t *dma_c = &dma[channel];
|
||||
uint16_t temp;
|
||||
int tc = 0;
|
||||
|
||||
if (channel < 4)
|
||||
{
|
||||
if (dma_command & 0x04)
|
||||
return DMA_NODATA;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (dma16_command & 0x04)
|
||||
return DMA_NODATA;
|
||||
}
|
||||
|
||||
if (!AT)
|
||||
refreshread();
|
||||
|
||||
if (dma_m & (1 << channel))
|
||||
return DMA_NODATA;
|
||||
if ((dma_c->mode & 0xC) != 8)
|
||||
return DMA_NODATA;
|
||||
|
||||
if (!dma_c->size)
|
||||
{
|
||||
temp = _dma_read(dma_c->ac);
|
||||
|
||||
if (dma_c->mode & 0x20)
|
||||
{
|
||||
if (dma_ps2.is_ps2)
|
||||
dma_c->ac--;
|
||||
else
|
||||
dma_c->ac = (dma_c->ac & 0xff0000) | ((dma_c->ac - 1) & 0xffff);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (dma_ps2.is_ps2)
|
||||
dma_c->ac++;
|
||||
else
|
||||
dma_c->ac = (dma_c->ac & 0xff0000) | ((dma_c->ac + 1) & 0xffff);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
temp = _dma_read(dma_c->ac) |
|
||||
(_dma_read(dma_c->ac + 1) << 8);
|
||||
|
||||
if (dma_c->mode & 0x20)
|
||||
{
|
||||
if (dma_ps2.is_ps2)
|
||||
dma_c->ac -= 2;
|
||||
else
|
||||
dma_c->ac = (dma_c->ac & 0xfe0000) | ((dma_c->ac - 2) & 0x1ffff);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (dma_ps2.is_ps2)
|
||||
dma_c->ac += 2;
|
||||
else
|
||||
dma_c->ac = (dma_c->ac & 0xfe0000) | ((dma_c->ac + 2) & 0x1ffff);
|
||||
}
|
||||
}
|
||||
|
||||
dma_stat_rq |= (1 << channel);
|
||||
|
||||
dma_c->cc--;
|
||||
if (dma_c->cc < 0)
|
||||
{
|
||||
tc = 1;
|
||||
if (dma_c->mode & 0x10) /*Auto-init*/
|
||||
{
|
||||
dma_c->cc = dma_c->cb;
|
||||
dma_c->ac = dma_c->ab;
|
||||
}
|
||||
else
|
||||
dma_m |= (1 << channel);
|
||||
dma_stat |= (1 << channel);
|
||||
}
|
||||
|
||||
if (tc)
|
||||
return temp | DMA_OVER;
|
||||
return temp;
|
||||
}
|
||||
|
||||
int dma_channel_write(int channel, uint16_t val)
|
||||
{
|
||||
dma_t *dma_c = &dma[channel];
|
||||
|
||||
if (channel < 4)
|
||||
{
|
||||
if (dma_command & 0x04)
|
||||
return DMA_NODATA;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (dma16_command & 0x04)
|
||||
return DMA_NODATA;
|
||||
}
|
||||
|
||||
if (!AT)
|
||||
refreshread();
|
||||
|
||||
if (dma_m & (1 << channel))
|
||||
return DMA_NODATA;
|
||||
if ((dma_c->mode & 0xC) != 4)
|
||||
return DMA_NODATA;
|
||||
|
||||
if (!dma_c->size)
|
||||
{
|
||||
_dma_write(dma_c->ac, val);
|
||||
|
||||
if (dma_c->mode & 0x20)
|
||||
{
|
||||
if (dma_ps2.is_ps2)
|
||||
dma_c->ac--;
|
||||
else
|
||||
dma_c->ac = (dma_c->ac & 0xff0000) | ((dma_c->ac - 1) & 0xffff);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (dma_ps2.is_ps2)
|
||||
dma_c->ac++;
|
||||
else
|
||||
dma_c->ac = (dma_c->ac & 0xff0000) | ((dma_c->ac + 1) & 0xffff);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_dma_write(dma_c->ac, val);
|
||||
_dma_write(dma_c->ac + 1, val >> 8);
|
||||
|
||||
if (dma_c->mode & 0x20)
|
||||
{
|
||||
if (dma_ps2.is_ps2)
|
||||
dma_c->ac -= 2;
|
||||
else
|
||||
dma_c->ac = (dma_c->ac & 0xfe0000) | ((dma_c->ac - 2) & 0x1ffff);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (dma_ps2.is_ps2)
|
||||
dma_c->ac += 2;
|
||||
else
|
||||
dma_c->ac = (dma_c->ac & 0xfe0000) | ((dma_c->ac + 2) & 0x1ffff);
|
||||
}
|
||||
}
|
||||
|
||||
dma_stat_rq |= (1 << channel);
|
||||
|
||||
dma_c->cc--;
|
||||
if (dma_c->cc < 0)
|
||||
{
|
||||
if (dma_c->mode & 0x10) /*Auto-init*/
|
||||
{
|
||||
dma_c->cc = dma_c->cb;
|
||||
dma_c->ac = dma_c->ab;
|
||||
}
|
||||
else
|
||||
dma_m |= (1 << channel);
|
||||
dma_stat |= (1 << channel);
|
||||
}
|
||||
|
||||
if (dma_m & (1 << channel))
|
||||
return DMA_OVER;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void dma_ps2_run(int channel)
|
||||
{
|
||||
dma_t *dma_c = &dma[channel];
|
||||
|
||||
switch (dma_c->ps2_mode & DMA_PS2_XFER_MASK)
|
||||
{
|
||||
case DMA_PS2_XFER_MEM_TO_IO:
|
||||
do
|
||||
{
|
||||
if (!dma_c->size)
|
||||
{
|
||||
uint8_t temp = _dma_read(dma_c->ac);
|
||||
outb(dma_c->io_addr, temp);
|
||||
|
||||
if (dma_c->ps2_mode & DMA_PS2_DEC2)
|
||||
dma_c->ac--;
|
||||
else
|
||||
dma_c->ac++;
|
||||
}
|
||||
else
|
||||
{
|
||||
uint16_t temp = _dma_read(dma_c->ac) | (_dma_read(dma_c->ac + 1) << 8);
|
||||
outw(dma_c->io_addr, temp);
|
||||
|
||||
if (dma_c->ps2_mode & DMA_PS2_DEC2)
|
||||
dma_c->ac -= 2;
|
||||
else
|
||||
dma_c->ac += 2;
|
||||
}
|
||||
|
||||
dma_stat_rq |= (1 << channel);
|
||||
dma_c->cc--;
|
||||
} while (dma_c->cc > 0);
|
||||
|
||||
dma_stat |= (1 << channel);
|
||||
break;
|
||||
|
||||
case DMA_PS2_XFER_IO_TO_MEM:
|
||||
do
|
||||
{
|
||||
if (!dma_c->size)
|
||||
{
|
||||
uint8_t temp = inb(dma_c->io_addr);
|
||||
_dma_write(dma_c->ac, temp);
|
||||
|
||||
if (dma_c->ps2_mode & DMA_PS2_DEC2)
|
||||
dma_c->ac--;
|
||||
else
|
||||
dma_c->ac++;
|
||||
}
|
||||
else
|
||||
{
|
||||
uint16_t temp = inw(dma_c->io_addr);
|
||||
_dma_write(dma_c->ac, temp & 0xff);
|
||||
_dma_write(dma_c->ac + 1, temp >> 8);
|
||||
|
||||
if (dma_c->ps2_mode & DMA_PS2_DEC2)
|
||||
dma_c->ac -= 2;
|
||||
else
|
||||
dma_c->ac += 2;
|
||||
}
|
||||
|
||||
dma_stat_rq |= (1 << channel);
|
||||
dma_c->cc--;
|
||||
} while (dma_c->cc > 0);
|
||||
|
||||
ps2_cache_clean();
|
||||
dma_stat |= (1 << channel);
|
||||
break;
|
||||
|
||||
default: /*Memory verify*/
|
||||
do
|
||||
{
|
||||
if (!dma_c->size)
|
||||
{
|
||||
if (dma_c->ps2_mode & DMA_PS2_DEC2)
|
||||
dma_c->ac--;
|
||||
else
|
||||
dma_c->ac++;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (dma_c->ps2_mode & DMA_PS2_DEC2)
|
||||
dma_c->ac -= 2;
|
||||
else
|
||||
dma_c->ac += 2;
|
||||
}
|
||||
|
||||
dma_stat_rq |= (1 << channel);
|
||||
dma->cc--;
|
||||
} while (dma->cc > 0);
|
||||
|
||||
dma_stat |= (1 << channel);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int dma_mode(int channel)
|
||||
{
|
||||
if (channel < 4)
|
||||
{
|
||||
return dma[channel].mode;
|
||||
}
|
||||
else
|
||||
{
|
||||
return dma[channel & 3].mode;
|
||||
}
|
||||
}
|
||||
|
||||
/* DMA Bus Master Page Read/Write */
|
||||
void DMAPageRead(uint32_t PhysAddress, uint8_t *DataRead, uint32_t TotalSize)
|
||||
{
|
||||
uint32_t i = 0;
|
||||
|
||||
#if 0
|
||||
memcpy(DataRead, &ram[PhysAddress], TotalSize);
|
||||
#else
|
||||
for (i = 0; i < TotalSize; i++)
|
||||
DataRead[i] = mem_readb_phys_dma(PhysAddress + i);
|
||||
#endif
|
||||
}
|
||||
|
||||
void DMAPageWrite(uint32_t PhysAddress, const uint8_t *DataWrite, uint32_t TotalSize)
|
||||
{
|
||||
uint32_t i = 0;
|
||||
|
||||
#if 0
|
||||
mem_invalidate_range(PhysAddress, PhysAddress + TotalSize - 1);
|
||||
memcpy(&ram[PhysAddress], DataWrite, TotalSize);
|
||||
#else
|
||||
for (i = 0; i < TotalSize; i++)
|
||||
mem_writeb_phys_dma(PhysAddress + i, DataWrite[i]);
|
||||
|
||||
mem_invalidate_range(PhysAddress, PhysAddress + TotalSize - 1);
|
||||
#endif
|
||||
}
|
||||
74
backup code/dma.h.old
Normal file
74
backup code/dma.h.old
Normal file
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
*
|
||||
* This file is part of the 86Box distribution.
|
||||
*
|
||||
* Implementation of the Intel DMA controllers.
|
||||
*
|
||||
* Version: @(#)dma.h 1.0.5 2018/03/11
|
||||
*
|
||||
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
*
|
||||
* Copyright 2008-2017 Sarah Walker.
|
||||
* Copyright 2016,2017 Miran Grca.
|
||||
*/
|
||||
#ifndef EMU_DMA_H
|
||||
# define EMU_DMA_H
|
||||
|
||||
|
||||
#define DMA_NODATA -1
|
||||
#define DMA_OVER 0x10000
|
||||
#define DMA_VERIFY 0x20000
|
||||
|
||||
|
||||
/*DMA*/
|
||||
typedef struct dma_t
|
||||
{
|
||||
uint32_t ab, ac;
|
||||
uint16_t cb;
|
||||
int cc;
|
||||
int wp;
|
||||
uint8_t m, mode;
|
||||
uint8_t page;
|
||||
uint8_t stat, stat_rq;
|
||||
uint8_t command;
|
||||
int size;
|
||||
|
||||
uint8_t ps2_mode;
|
||||
uint8_t arb_level;
|
||||
uint16_t io_addr;
|
||||
} dma_t;
|
||||
|
||||
extern dma_t dma[8];
|
||||
|
||||
extern void dma_init(void);
|
||||
extern void dma16_init(void);
|
||||
extern void ps2_dma_init(void);
|
||||
extern void dma_reset(void);
|
||||
extern int dma_mode(int channel);
|
||||
|
||||
extern void readdma0(void);
|
||||
extern int readdma1(void);
|
||||
extern uint8_t readdma2(void);
|
||||
extern int readdma3(void);
|
||||
|
||||
extern void writedma2(uint8_t temp);
|
||||
|
||||
extern int dma_channel_read(int channel);
|
||||
extern int dma_channel_write(int channel, uint16_t val);
|
||||
|
||||
extern void dma_alias_set(void);
|
||||
extern void dma_alias_remove(void);
|
||||
extern void dma_alias_remove_piix(void);
|
||||
|
||||
extern void DMAPageRead(uint32_t PhysAddress, uint8_t *DataRead,
|
||||
uint32_t TotalSize);
|
||||
extern void DMAPageWrite(uint32_t PhysAddress, const uint8_t *DataWrite,
|
||||
uint32_t TotalSize);
|
||||
|
||||
|
||||
#endif /*EMU_DMA_H*/
|
||||
916
backup code/intel_piix - Cópia.c
Normal file
916
backup code/intel_piix - Cópia.c
Normal file
@@ -0,0 +1,916 @@
|
||||
/*
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
*
|
||||
* Emulation of the Intel PIIX and PIIX3 Xcelerators.
|
||||
*
|
||||
* PRD format :
|
||||
* word 0 - base address
|
||||
* word 1 - bits 1-15 = byte count, bit 31 = end of transfer
|
||||
*
|
||||
* Version: @(#)intel_piix.c 1.0.16 2018/05/11
|
||||
*
|
||||
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
*
|
||||
* Copyright 2008-2018 Sarah Walker.
|
||||
* Copyright 2016-2018 Miran Grca.
|
||||
*/
|
||||
#include <stdarg.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <wchar.h>
|
||||
#define HAVE_STDARG_H
|
||||
#include "86box.h"
|
||||
#include "scsi/scsi.h"
|
||||
#include "cdrom/cdrom.h"
|
||||
#include "dma.h"
|
||||
#include "io.h"
|
||||
#include "device.h"
|
||||
#include "keyboard.h"
|
||||
#include "mem.h"
|
||||
#include "pci.h"
|
||||
#include "pic.h"
|
||||
#include "disk/hdc.h"
|
||||
#include "disk/hdc_ide.h"
|
||||
#include "disk/zip.h"
|
||||
#include "piix.h"
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint8_t command, status,
|
||||
ptr0;
|
||||
uint32_t ptr, ptr_cur,
|
||||
addr;
|
||||
int count, eot;
|
||||
} piix_busmaster_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int type;
|
||||
uint8_t regs[256], regs_ide[256];
|
||||
piix_busmaster_t bm[2];
|
||||
} piix_t;
|
||||
|
||||
|
||||
static uint8_t piix_bus_master_read(uint16_t port, void *priv);
|
||||
static uint16_t piix_bus_master_readw(uint16_t port, void *priv);
|
||||
static uint32_t piix_bus_master_readl(uint16_t port, void *priv);
|
||||
static void piix_bus_master_write(uint16_t port, uint8_t val, void *priv);
|
||||
static void piix_bus_master_writew(uint16_t port, uint16_t val, void *priv);
|
||||
static void piix_bus_master_writel(uint16_t port, uint32_t val, void *priv);
|
||||
|
||||
|
||||
#ifdef ENABLE_PIIX_LOG
|
||||
int piix_do_log = ENABLE_PIIX_LOG;
|
||||
#endif
|
||||
|
||||
|
||||
static void
|
||||
piix_log(const char *format, ...)
|
||||
{
|
||||
#ifdef ENABLE_PIIX_LOG
|
||||
va_list ap;
|
||||
|
||||
if (piix_do_log) {
|
||||
va_start(ap, format);
|
||||
pclog_ex(format, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
piix_bus_master_handlers(piix_t *dev, uint16_t old_base)
|
||||
{
|
||||
uint16_t base;
|
||||
|
||||
base = (dev->regs_ide[0x20] & 0xf0) | (dev->regs_ide[0x21] << 8);
|
||||
io_removehandler(old_base, 0x08,
|
||||
piix_bus_master_read, piix_bus_master_readw, piix_bus_master_readl,
|
||||
piix_bus_master_write, piix_bus_master_writew, piix_bus_master_writel,
|
||||
&dev->bm[0]);
|
||||
io_removehandler(old_base + 8, 0x08,
|
||||
piix_bus_master_read, piix_bus_master_readw, piix_bus_master_readl,
|
||||
piix_bus_master_write, piix_bus_master_writew, piix_bus_master_writel,
|
||||
&dev->bm[1]);
|
||||
|
||||
if ((dev->regs_ide[0x04] & 1) && base) {
|
||||
io_sethandler(base, 0x08,
|
||||
piix_bus_master_read, piix_bus_master_readw, piix_bus_master_readl,
|
||||
piix_bus_master_write, piix_bus_master_writew, piix_bus_master_writel,
|
||||
&dev->bm[0]);
|
||||
io_sethandler(base + 8, 0x08,
|
||||
piix_bus_master_read, piix_bus_master_readw, piix_bus_master_readl,
|
||||
piix_bus_master_write, piix_bus_master_writew, piix_bus_master_writel,
|
||||
&dev->bm[1]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
piix_write(int func, int addr, uint8_t val, void *priv)
|
||||
{
|
||||
piix_t *dev = (piix_t *) priv;
|
||||
uint8_t valxor;
|
||||
|
||||
uint16_t old_base = (dev->regs_ide[0x20] & 0xf0) | (dev->regs_ide[0x21] << 8);
|
||||
if (func > 1)
|
||||
return;
|
||||
|
||||
if (func == 1) { /*IDE*/
|
||||
piix_log("PIIX IDE write: %02X %02X\n", addr, val);
|
||||
valxor = val ^ dev->regs_ide[addr];
|
||||
|
||||
switch (addr) {
|
||||
case 0x04:
|
||||
dev->regs_ide[0x04] = (val & 5) | 2;
|
||||
if (valxor & 0x01) {
|
||||
ide_pri_disable();
|
||||
ide_sec_disable();
|
||||
if (val & 0x01) {
|
||||
if (dev->regs_ide[0x41] & 0x80)
|
||||
ide_pri_enable();
|
||||
if (dev->regs_ide[0x43] & 0x80)
|
||||
ide_sec_enable();
|
||||
}
|
||||
|
||||
piix_bus_master_handlers(dev, old_base);
|
||||
}
|
||||
break;
|
||||
case 0x07:
|
||||
dev->regs_ide[0x07] = val & 0x3e;
|
||||
break;
|
||||
case 0x0d:
|
||||
dev->regs_ide[0x0d] = val;
|
||||
break;
|
||||
|
||||
case 0x20:
|
||||
dev->regs_ide[0x20] = (val & ~0x0f) | 1;
|
||||
if (valxor)
|
||||
piix_bus_master_handlers(dev, old_base);
|
||||
break;
|
||||
case 0x21:
|
||||
dev->regs_ide[0x21] = val;
|
||||
if (valxor)
|
||||
piix_bus_master_handlers(dev, old_base);
|
||||
break;
|
||||
|
||||
case 0x40:
|
||||
dev->regs_ide[0x40] = val;
|
||||
break;
|
||||
case 0x41:
|
||||
dev->regs_ide[0x41] = val;
|
||||
if (valxor & 0x80) {
|
||||
ide_pri_disable();
|
||||
if ((val & 0x80) && (dev->regs_ide[0x04] & 0x01))
|
||||
ide_pri_enable();
|
||||
}
|
||||
break;
|
||||
case 0x42:
|
||||
dev->regs_ide[0x42] = val;
|
||||
break;
|
||||
case 0x43:
|
||||
dev->regs_ide[0x43] = val;
|
||||
if (valxor & 0x80) {
|
||||
ide_sec_disable();
|
||||
if ((val & 0x80) && (dev->regs_ide[0x04] & 0x01))
|
||||
ide_sec_enable();
|
||||
}
|
||||
break;
|
||||
case 0x44:
|
||||
if (dev->type >= 3) dev->regs_ide[0x44] = val;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
piix_log("PIIX writing value %02X to register %02X\n", val, addr);
|
||||
valxor = val ^ dev->regs[addr];
|
||||
|
||||
if ((addr >= 0x0f) && (addr < 0x4c))
|
||||
return;
|
||||
|
||||
switch (addr) {
|
||||
case 0x00: case 0x01: case 0x02: case 0x03:
|
||||
case 0x08: case 0x09: case 0x0a: case 0x0b:
|
||||
case 0x0e:
|
||||
return;
|
||||
|
||||
case 0x4c:
|
||||
if (valxor) {
|
||||
if (val & 0x80) {
|
||||
if (dev->type == 3)
|
||||
dma_alias_remove();
|
||||
else
|
||||
dma_alias_remove_piix();
|
||||
} else
|
||||
dma_alias_set();
|
||||
}
|
||||
break;
|
||||
case 0x4e:
|
||||
keyboard_at_set_mouse_scan((val & 0x10) ? 1 : 0);
|
||||
break;
|
||||
case 0x60:
|
||||
piix_log("Set IRQ routing: INT A -> %02X\n", val);
|
||||
if (val & 0x80)
|
||||
pci_set_irq_routing(PCI_INTA, PCI_IRQ_DISABLED);
|
||||
else
|
||||
pci_set_irq_routing(PCI_INTA, val & 0xf);
|
||||
break;
|
||||
case 0x61:
|
||||
piix_log("Set IRQ routing: INT B -> %02X\n", val);
|
||||
if (val & 0x80)
|
||||
pci_set_irq_routing(PCI_INTB, PCI_IRQ_DISABLED);
|
||||
else
|
||||
pci_set_irq_routing(PCI_INTB, val & 0xf);
|
||||
break;
|
||||
case 0x62:
|
||||
piix_log("Set IRQ routing: INT C -> %02X\n", val);
|
||||
if (val & 0x80)
|
||||
pci_set_irq_routing(PCI_INTC, PCI_IRQ_DISABLED);
|
||||
else
|
||||
pci_set_irq_routing(PCI_INTC, val & 0xf);
|
||||
break;
|
||||
case 0x63:
|
||||
piix_log("Set IRQ routing: INT D -> %02X\n", val);
|
||||
if (val & 0x80)
|
||||
pci_set_irq_routing(PCI_INTD, PCI_IRQ_DISABLED);
|
||||
else
|
||||
pci_set_irq_routing(PCI_INTD, val & 0xf);
|
||||
break;
|
||||
case 0x6a:
|
||||
if (dev->type == 3)
|
||||
dev->regs[addr] = (val & 0xFD) | (dev->regs[addr] | 2);
|
||||
else
|
||||
dev->regs[addr] = (val & 0xFC) | (dev->regs[addr] | 3);
|
||||
return;
|
||||
case 0x70:
|
||||
piix_log("Set MIRQ routing: MIRQ0 -> %02X\n", val);
|
||||
if (val & 0x80)
|
||||
pci_set_mirq_routing(PCI_MIRQ0, PCI_IRQ_DISABLED);
|
||||
else
|
||||
pci_set_mirq_routing(PCI_MIRQ0, val & 0xf);
|
||||
break;
|
||||
piix_log("MIRQ0 is %s\n", (val & 0x20) ? "disabled" : "enabled");
|
||||
case 0x71:
|
||||
if (dev->type == 1) {
|
||||
piix_log("Set MIRQ routing: MIRQ1 -> %02X\n", val);
|
||||
if (val & 0x80)
|
||||
pci_set_mirq_routing(PCI_MIRQ1, PCI_IRQ_DISABLED);
|
||||
else
|
||||
pci_set_mirq_routing(PCI_MIRQ1, val & 0xf);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
dev->regs[addr] = val;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static uint8_t
|
||||
piix_read(int func, int addr, void *priv)
|
||||
{
|
||||
piix_t *dev = (piix_t *) priv;
|
||||
|
||||
if ((func == 1) && (dev->type & 0x100)) /* PB640's PIIX has no IDE part. */
|
||||
return 0xff;
|
||||
if (func > 1)
|
||||
return 0xff;
|
||||
|
||||
if (func == 1) { /*IDE*/
|
||||
if (addr == 4)
|
||||
return (dev->regs_ide[addr] & 5) | 2;
|
||||
else if (addr == 5)
|
||||
return 0;
|
||||
else if (addr == 6)
|
||||
return 0x80;
|
||||
else if (addr == 7)
|
||||
return dev->regs_ide[addr] & 0x3E;
|
||||
else if (addr == 0xD)
|
||||
return dev->regs_ide[addr] & 0xF0;
|
||||
else if (addr == 0x20)
|
||||
return (dev->regs_ide[addr] & 0xF0) | 1;
|
||||
else if (addr == 0x22)
|
||||
return 0;
|
||||
else if (addr == 0x23)
|
||||
return 0;
|
||||
else if (addr == 0x41) {
|
||||
if (dev->type == 3)
|
||||
return dev->regs_ide[addr] & 0xF3;
|
||||
else
|
||||
return dev->regs_ide[addr] & 0xB3;
|
||||
} else if (addr == 0x43) {
|
||||
if (dev->type == 3)
|
||||
return dev->regs_ide[addr] & 0xF3;
|
||||
else
|
||||
return dev->regs_ide[addr] & 0xB3;
|
||||
} else
|
||||
return dev->regs_ide[addr];
|
||||
} else {
|
||||
if ((addr & 0xFC) == 0x60)
|
||||
return dev->regs[addr] & 0x8F;
|
||||
|
||||
if (addr == 4) {
|
||||
if (dev->type & 0x100)
|
||||
return (dev->regs[addr] & 0x80) | 0x0F;
|
||||
else
|
||||
return (dev->regs[addr] & 0x80) | 7;
|
||||
} else if (addr == 5) {
|
||||
if (dev->type == 3)
|
||||
return dev->regs[addr] & 1;
|
||||
else
|
||||
return 0;
|
||||
} else if (addr == 6)
|
||||
return dev->regs[addr] & 0x80;
|
||||
else if (addr == 7) {
|
||||
if (dev->type == 3)
|
||||
return dev->regs[addr];
|
||||
else {
|
||||
if (dev->type & 0x100)
|
||||
return dev->regs[addr] & 0x02;
|
||||
else
|
||||
return dev->regs[addr] & 0x3E;
|
||||
}
|
||||
} else if (addr == 0x4E)
|
||||
return (dev->regs[addr] & 0xEF) | keyboard_at_get_mouse_scan();
|
||||
else if (addr == 0x69)
|
||||
return dev->regs[addr] & 0xFE;
|
||||
else if (addr == 0x6A) {
|
||||
if (dev->type == 3)
|
||||
return dev->regs[addr] & 0xD1;
|
||||
else
|
||||
return dev->regs[addr] & 0x07;
|
||||
} else if (addr == 0x6B) {
|
||||
if (dev->type == 3)
|
||||
return dev->regs[addr] & 0x80;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
else if (addr == 0x70) {
|
||||
if (dev->type == 3)
|
||||
return dev->regs[addr] & 0xEF;
|
||||
else
|
||||
return dev->regs[addr] & 0xCF;
|
||||
} else if (addr == 0x71) {
|
||||
if (dev->type == 3)
|
||||
return 0;
|
||||
else
|
||||
return dev->regs[addr] & 0xCF;
|
||||
} else if (addr == 0x76) {
|
||||
if (dev->type == 3)
|
||||
return dev->regs[addr] & 0x87;
|
||||
else
|
||||
return dev->regs[addr] & 0x8F;
|
||||
} else if (addr == 0x77) {
|
||||
if (dev->type == 3)
|
||||
return dev->regs[addr] & 0x87;
|
||||
else
|
||||
return dev->regs[addr] & 0x8F;
|
||||
} else if (addr == 0x80) {
|
||||
if (dev->type == 3)
|
||||
return dev->regs[addr] & 0x7F;
|
||||
else if (dev->type == 1)
|
||||
return 0;
|
||||
} else if (addr == 0x82) {
|
||||
if (dev->type == 3)
|
||||
return dev->regs[addr] & 0x0F;
|
||||
else
|
||||
return 0;
|
||||
} else if (addr == 0xA0)
|
||||
return dev->regs[addr] & 0x1F;
|
||||
else if (addr == 0xA3) {
|
||||
if (dev->type == 3)
|
||||
return dev->regs[addr] & 1;
|
||||
else
|
||||
return 0;
|
||||
} else if (addr == 0xA7) {
|
||||
if (dev->type == 3)
|
||||
return dev->regs[addr];
|
||||
else
|
||||
return dev->regs[addr] & 0xEF;
|
||||
} else if (addr == 0xAB) {
|
||||
if (dev->type == 3)
|
||||
return dev->regs[addr];
|
||||
else
|
||||
return dev->regs[addr] & 0xFE;
|
||||
} else
|
||||
return dev->regs[addr];
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
piix_bus_master_next_addr(piix_busmaster_t *dev)
|
||||
{
|
||||
DMAPageRead(dev->ptr_cur, (uint8_t *)&(dev->addr), 4);
|
||||
DMAPageRead(dev->ptr_cur + 4, (uint8_t *)&(dev->count), 4);
|
||||
piix_log("PIIX Bus master DWORDs: %08X %08X\n", dev->addr, dev->count);
|
||||
dev->eot = dev->count >> 31;
|
||||
dev->count &= 0xfffe;
|
||||
if (!dev->count)
|
||||
dev->count = 65536;
|
||||
dev->addr &= 0xfffffffe;
|
||||
dev->ptr_cur += 8;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
piix_bus_master_write(uint16_t port, uint8_t val, void *priv)
|
||||
{
|
||||
piix_busmaster_t *dev = (piix_busmaster_t *) priv;
|
||||
int channel = (port & 8) ? 1 : 0;
|
||||
|
||||
piix_log("PIIX Bus master BYTE write: %04X %02X\n", port, val);
|
||||
|
||||
switch (port & 7) {
|
||||
case 0:
|
||||
piix_log("PIIX Cmd : val = %02X, old = %02X\n", val, dev->command);
|
||||
if ((val & 1) && !(dev->command & 1)) { /*Start*/
|
||||
piix_log("PIIX Bus Master start on channel %i\n", channel);
|
||||
dev->ptr_cur = dev->ptr;
|
||||
piix_bus_master_next_addr(dev);
|
||||
dev->status |= 1;
|
||||
}
|
||||
if (!(val & 1) && (dev->command & 1)) { /*Stop*/
|
||||
piix_log("PIIX Bus Master stop on channel %i\n", channel);
|
||||
dev->status &= ~1;
|
||||
}
|
||||
|
||||
dev->command = val;
|
||||
break;
|
||||
case 2:
|
||||
piix_log("PIIX Status: val = %02X, old = %02X\n", val, dev->status);
|
||||
dev->status &= 0x07;
|
||||
dev->status |= (val & 0x60);
|
||||
if (val & 0x04)
|
||||
dev->status &= ~0x04;
|
||||
if (val & 0x02)
|
||||
dev->status &= ~0x02;
|
||||
break;
|
||||
case 4:
|
||||
dev->ptr = (dev->ptr & 0xffffff00) | (val & 0xfc);
|
||||
dev->ptr %= (mem_size * 1024);
|
||||
dev->ptr0 = val;
|
||||
break;
|
||||
case 5:
|
||||
dev->ptr = (dev->ptr & 0xffff00fc) | (val << 8);
|
||||
dev->ptr %= (mem_size * 1024);
|
||||
break;
|
||||
case 6:
|
||||
dev->ptr = (dev->ptr & 0xff00fffc) | (val << 16);
|
||||
dev->ptr %= (mem_size * 1024);
|
||||
break;
|
||||
case 7:
|
||||
dev->ptr = (dev->ptr & 0x00fffffc) | (val << 24);
|
||||
dev->ptr %= (mem_size * 1024);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
piix_bus_master_writew(uint16_t port, uint16_t val, void *priv)
|
||||
{
|
||||
piix_busmaster_t *dev = (piix_busmaster_t *) priv;
|
||||
|
||||
piix_log("PIIX Bus master WORD write: %04X %04X\n", port, val);
|
||||
|
||||
switch (port & 7) {
|
||||
case 0:
|
||||
case 2:
|
||||
piix_bus_master_write(port, val & 0xff, priv);
|
||||
break;
|
||||
case 4:
|
||||
dev->ptr = (dev->ptr & 0xffff0000) | (val & 0xfffc);
|
||||
dev->ptr %= (mem_size * 1024);
|
||||
dev->ptr0 = val & 0xff;
|
||||
break;
|
||||
case 6:
|
||||
dev->ptr = (dev->ptr & 0x0000fffc) | (val << 16);
|
||||
dev->ptr %= (mem_size * 1024);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
piix_bus_master_writel(uint16_t port, uint32_t val, void *priv)
|
||||
{
|
||||
piix_busmaster_t *dev = (piix_busmaster_t *) priv;
|
||||
|
||||
piix_log("PIIX Bus master DWORD write: %04X %08X\n", port, val);
|
||||
|
||||
switch (port & 7) {
|
||||
case 0:
|
||||
case 2:
|
||||
piix_bus_master_write(port, val & 0xff, priv);
|
||||
break;
|
||||
case 4:
|
||||
dev->ptr = (val & 0xfffffffc);
|
||||
dev->ptr %= (mem_size * 1024);
|
||||
dev->ptr0 = val & 0xff;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static uint8_t
|
||||
piix_bus_master_read(uint16_t port, void *priv)
|
||||
{
|
||||
piix_busmaster_t *dev = (piix_busmaster_t *) priv;
|
||||
|
||||
uint8_t ret = 0xff;
|
||||
|
||||
switch (port & 7) {
|
||||
case 0:
|
||||
ret = dev->command;
|
||||
break;
|
||||
case 2:
|
||||
ret = dev->status & 0x67;
|
||||
break;
|
||||
case 4:
|
||||
ret = dev->ptr0;
|
||||
break;
|
||||
case 5:
|
||||
ret = dev->ptr >> 8;
|
||||
break;
|
||||
case 6:
|
||||
ret = dev->ptr >> 16;
|
||||
break;
|
||||
case 7:
|
||||
ret = dev->ptr >> 24;
|
||||
break;
|
||||
}
|
||||
|
||||
piix_log("PIIX Bus master BYTE read : %04X %02X\n", port, ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static uint16_t
|
||||
piix_bus_master_readw(uint16_t port, void *priv)
|
||||
{
|
||||
piix_busmaster_t *dev = (piix_busmaster_t *) priv;
|
||||
|
||||
uint16_t ret = 0xffff;
|
||||
|
||||
switch (port & 7) {
|
||||
case 0:
|
||||
case 2:
|
||||
ret = (uint16_t) piix_bus_master_read(port, priv);
|
||||
break;
|
||||
case 4:
|
||||
ret = dev->ptr0 | (dev->ptr & 0xff00);
|
||||
break;
|
||||
case 6:
|
||||
ret = dev->ptr >> 16;
|
||||
break;
|
||||
}
|
||||
|
||||
piix_log("PIIX Bus master WORD read : %04X %04X\n", port, ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static uint32_t
|
||||
piix_bus_master_readl(uint16_t port, void *priv)
|
||||
{
|
||||
piix_busmaster_t *dev = (piix_busmaster_t *) priv;
|
||||
|
||||
uint32_t ret = 0xffffffff;
|
||||
|
||||
switch (port & 7) {
|
||||
case 0:
|
||||
case 2:
|
||||
ret = (uint32_t) piix_bus_master_read(port, priv);
|
||||
break;
|
||||
case 4:
|
||||
ret = dev->ptr0 | (dev->ptr & 0xffffff00);
|
||||
break;
|
||||
}
|
||||
|
||||
piix_log("PIIX Bus master DWORD read : %04X %08X\n", port, ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
piix_bus_master_dma_op(int channel, uint8_t *data, int transfer_length, int out, void *priv)
|
||||
{
|
||||
piix_busmaster_t *dev = (piix_busmaster_t *) priv;
|
||||
char *sop;
|
||||
|
||||
int force_end = 0, buffer_pos = 0;
|
||||
|
||||
sop = out ? "Writ" : "Read";
|
||||
|
||||
if (!(dev->status & 1))
|
||||
return 2; /*DMA disabled*/
|
||||
|
||||
piix_log("PIIX Bus master %s: %i bytes\n", out ? "read" : "write", transfer_length);
|
||||
|
||||
while (1) {
|
||||
if (dev->count <= transfer_length) {
|
||||
piix_log("%sing %i bytes to %08X\n", sop, dev->count, dev->addr);
|
||||
if (out)
|
||||
DMAPageWrite(dev->addr, (uint8_t *)(data + buffer_pos), dev->count);
|
||||
else
|
||||
DMAPageRead(dev->addr, (uint8_t *)(data + buffer_pos), dev->count);
|
||||
transfer_length -= dev->count;
|
||||
buffer_pos += dev->count;
|
||||
} else {
|
||||
piix_log("%sing %i bytes to %08X\n", sop, transfer_length, dev->addr);
|
||||
if (out)
|
||||
DMAPageWrite(dev->addr, (uint8_t *)(data + buffer_pos), transfer_length);
|
||||
else
|
||||
DMAPageRead(dev->addr, (uint8_t *)(data + buffer_pos), transfer_length);
|
||||
/* Increase addr and decrease count so that resumed transfers do not mess up. */
|
||||
dev->addr += transfer_length;
|
||||
dev->count -= transfer_length;
|
||||
transfer_length = 0;
|
||||
force_end = 1;
|
||||
}
|
||||
|
||||
if (force_end) {
|
||||
piix_log("Total transfer length smaller than sum of all blocks, partial block\n");
|
||||
dev->status &= ~2;
|
||||
return 0; /* This block has exhausted the data to transfer and it was smaller than the count, break. */
|
||||
} else {
|
||||
if (!transfer_length && !dev->eot) {
|
||||
piix_log("Total transfer length smaller than sum of all blocks, full block\n");
|
||||
dev->status &= ~2;
|
||||
return 0; /* We have exhausted the data to transfer but there's more blocks left, break. */
|
||||
} else if (transfer_length && dev->eot) {
|
||||
piix_log("Total transfer length greater than sum of all blocks\n");
|
||||
dev->status |= 2;
|
||||
return 1; /* There is data left to transfer but we have reached EOT - return with error. */
|
||||
} else if (dev->eot) {
|
||||
piix_log("Regular EOT\n");
|
||||
dev->status &= ~3;
|
||||
return 0; /* We have regularly reached EOT - clear status and break. */
|
||||
} else {
|
||||
/* We have more to transfer and there are blocks left, get next block. */
|
||||
piix_bus_master_next_addr(dev);
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
piix_bus_master_dma_read(int channel, uint8_t *data, int transfer_length, void *priv)
|
||||
{
|
||||
return piix_bus_master_dma_op(channel, data, transfer_length, 1, priv);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
piix_bus_master_dma_write(int channel, uint8_t *data, int transfer_length, void *priv)
|
||||
{
|
||||
return piix_bus_master_dma_op(channel, data, transfer_length, 0, priv);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
piix_bus_master_set_irq(int channel, void *priv)
|
||||
{
|
||||
piix_busmaster_t *dev = (piix_busmaster_t *) priv;
|
||||
dev->status &= ~4;
|
||||
dev->status |= (channel >> 4);
|
||||
|
||||
channel &= 0x01;
|
||||
if (dev->status & 0x04) {
|
||||
if (channel && pci_use_mirq(0))
|
||||
pci_set_mirq(0);
|
||||
else
|
||||
picint(1 << (14 + channel));
|
||||
} else {
|
||||
if ((channel & 1) && pci_use_mirq(0))
|
||||
pci_clear_mirq(0);
|
||||
else
|
||||
picintc(1 << (14 + channel));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
piix_bus_master_reset(piix_t *dev)
|
||||
{
|
||||
uint8_t i;
|
||||
|
||||
uint16_t old_base = (dev->regs_ide[0x20] & 0xf0) | (dev->regs_ide[0x21] << 8);
|
||||
if (old_base) {
|
||||
io_removehandler(old_base, 0x08,
|
||||
piix_bus_master_read, piix_bus_master_readw, piix_bus_master_readl,
|
||||
piix_bus_master_write, piix_bus_master_writew, piix_bus_master_writel,
|
||||
&dev->bm[0]);
|
||||
io_removehandler(old_base + 8, 0x08,
|
||||
piix_bus_master_read, piix_bus_master_readw, piix_bus_master_readl,
|
||||
piix_bus_master_write, piix_bus_master_writew, piix_bus_master_writel,
|
||||
&dev->bm[1]);
|
||||
}
|
||||
|
||||
for (i = 0; i < 2; i++) {
|
||||
dev->bm[i].command = 0x00;
|
||||
dev->bm[i].status = 0x00;
|
||||
dev->bm[i].ptr = dev->bm[i].ptr_cur = 0x00000000;
|
||||
dev->bm[i].addr = 0x00000000;
|
||||
dev->bm[i].ptr0 = 0x00;
|
||||
dev->bm[i].count = dev->bm[i].eot = 0x00000000;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
piix_reset_hard(void *priv)
|
||||
{
|
||||
piix_t *piix = (piix_t *) priv;
|
||||
|
||||
piix_bus_master_reset(piix);
|
||||
|
||||
memset(piix->regs, 0, 256);
|
||||
memset(piix->regs_ide, 0, 256);
|
||||
|
||||
piix->regs[0x00] = 0x86; piix->regs[0x01] = 0x80; /*Intel*/
|
||||
if (piix->type == 3) {
|
||||
piix->regs[0x02] = 0x00; piix->regs[0x03] = 0x70; /*82371SB (PIIX3)*/
|
||||
} else {
|
||||
piix->regs[0x02] = 0x2e; piix->regs[0x03] = 0x12; /*82371FB (PIIX)*/
|
||||
}
|
||||
if (piix->type & 0x100)
|
||||
piix->regs[0x04] = 0x06;
|
||||
else
|
||||
piix->regs[0x04] = 0x07;
|
||||
piix->regs[0x05] = 0x00;
|
||||
piix->regs[0x06] = 0x80; piix->regs[0x07] = 0x02;
|
||||
if (piix->type & 0x100)
|
||||
piix->regs[0x08] = 0x02; /*A0 stepping*/
|
||||
else
|
||||
piix->regs[0x08] = 0x00; /*A0 stepping*/
|
||||
piix->regs[0x09] = 0x00; piix->regs[0x0a] = 0x01; piix->regs[0x0b] = 0x06;
|
||||
if (piix->type & 0x100)
|
||||
piix->regs[0x0e] = 0x00; /*Single-function device*/
|
||||
else
|
||||
piix->regs[0x0e] = 0x80; /*Multi-function device*/
|
||||
piix->regs[0x4c] = 0x4d;
|
||||
piix->regs[0x4e] = 0x03;
|
||||
if (piix->type == 3)
|
||||
piix->regs[0x4f] = 0x00;
|
||||
piix->regs[0x60] = piix->regs[0x61] = piix->regs[0x62] = piix->regs[0x63] = 0x80;
|
||||
piix->regs[0x69] = 0x02;
|
||||
piix->regs[0x70] = 0xc0;
|
||||
if (piix->type != 3)
|
||||
piix->regs[0x71] = 0xc0;
|
||||
piix->regs[0x76] = piix->regs[0x77] = 0x0c;
|
||||
piix->regs[0x78] = 0x02; piix->regs[0x79] = 0x00;
|
||||
if (piix->type == 3) {
|
||||
piix->regs[0x80] = piix->regs[0x82] = 0x00;
|
||||
}
|
||||
piix->regs[0xa0] = 0x08;
|
||||
piix->regs[0xa2] = piix->regs[0xa3] = 0x00;
|
||||
piix->regs[0xa4] = piix->regs[0xa5] = piix->regs[0xa6] = piix->regs[0xa7] = 0x00;
|
||||
piix->regs[0xa8] = 0x0f;
|
||||
piix->regs[0xaa] = piix->regs[0xab] = 0x00;
|
||||
piix->regs[0xac] = 0x00;
|
||||
piix->regs[0xae] = 0x00;
|
||||
|
||||
piix->regs_ide[0x00] = 0x86; piix->regs_ide[0x01] = 0x80; /*Intel*/
|
||||
if (piix->type == 3) {
|
||||
piix->regs_ide[0x02] = 0x10; piix->regs_ide[0x03] = 0x70; /*82371SB (PIIX3)*/
|
||||
} else {
|
||||
piix->regs_ide[0x02] = 0x30; piix->regs_ide[0x03] = 0x12; /*82371FB (PIIX)*/
|
||||
}
|
||||
piix->regs_ide[0x04] = 0x03; piix->regs_ide[0x05] = 0x00;
|
||||
piix->regs_ide[0x06] = 0x80; piix->regs_ide[0x07] = 0x02;
|
||||
piix->regs_ide[0x08] = 0x00;
|
||||
piix->regs_ide[0x09] = 0x80; piix->regs_ide[0x0a] = 0x01; piix->regs_ide[0x0b] = 0x01;
|
||||
piix->regs_ide[0x0d] = 0x00;
|
||||
piix->regs_ide[0x0e] = 0x00;
|
||||
piix->regs_ide[0x20] = 0x01; piix->regs_ide[0x21] = piix->regs_ide[0x22] = piix->regs_ide[0x23] = 0x00; /*Bus master interface base address*/
|
||||
piix->regs_ide[0x40] = piix->regs_ide[0x42] = 0x00;
|
||||
piix->regs_ide[0x41] = piix->regs_ide[0x43] = 0x00;
|
||||
if (piix->type == 3)
|
||||
piix->regs_ide[0x44] = 0x00;
|
||||
|
||||
pci_set_irq_routing(PCI_INTA, PCI_IRQ_DISABLED);
|
||||
pci_set_irq_routing(PCI_INTB, PCI_IRQ_DISABLED);
|
||||
pci_set_irq_routing(PCI_INTC, PCI_IRQ_DISABLED);
|
||||
pci_set_irq_routing(PCI_INTD, PCI_IRQ_DISABLED);
|
||||
|
||||
pci_set_mirq_routing(PCI_MIRQ0, PCI_IRQ_DISABLED);
|
||||
if (piix->type != 3)
|
||||
pci_set_mirq_routing(PCI_MIRQ1, PCI_IRQ_DISABLED);
|
||||
|
||||
ide_pri_disable();
|
||||
ide_sec_disable();
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
piix_reset(void *p)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
for (i = 0; i < CDROM_NUM; i++) {
|
||||
if (cdrom_drives[i].bus_type == CDROM_BUS_ATAPI)
|
||||
cdrom_reset(cdrom[i]);
|
||||
}
|
||||
for (i = 0; i < ZIP_NUM; i++) {
|
||||
if (zip_drives[i].bus_type == ZIP_BUS_ATAPI)
|
||||
zip_reset(i);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
piix_close(void *p)
|
||||
{
|
||||
piix_t *piix = (piix_t *)p;
|
||||
|
||||
free(piix);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
*piix_init(const device_t *info)
|
||||
{
|
||||
piix_t *piix = (piix_t *) malloc(sizeof(piix_t));
|
||||
memset(piix, 0, sizeof(piix_t));
|
||||
|
||||
device_add(&ide_pci_2ch_device);
|
||||
|
||||
pci_add_card(7, piix_read, piix_write, piix);
|
||||
|
||||
piix->type = info->local;
|
||||
piix_reset_hard(piix);
|
||||
|
||||
ide_set_bus_master(piix_bus_master_dma_read, piix_bus_master_dma_write,
|
||||
piix_bus_master_set_irq,
|
||||
&piix->bm[0], &piix->bm[1]);
|
||||
|
||||
port_92_reset();
|
||||
|
||||
port_92_add();
|
||||
|
||||
dma_alias_set();
|
||||
|
||||
pci_enable_mirq(0);
|
||||
pci_enable_mirq(1);
|
||||
|
||||
return piix;
|
||||
}
|
||||
|
||||
|
||||
const device_t piix_device =
|
||||
{
|
||||
"Intel 82371FB (PIIX)",
|
||||
DEVICE_PCI,
|
||||
1,
|
||||
piix_init,
|
||||
piix_close,
|
||||
piix_reset,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL
|
||||
};
|
||||
|
||||
const device_t piix_pb640_device =
|
||||
{
|
||||
"Intel 82371FB (PIIX) (PB640)",
|
||||
DEVICE_PCI,
|
||||
0x101,
|
||||
piix_init,
|
||||
piix_close,
|
||||
piix_reset,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL
|
||||
};
|
||||
|
||||
const device_t piix3_device =
|
||||
{
|
||||
"Intel 82371SB (PIIX3)",
|
||||
DEVICE_PCI,
|
||||
3,
|
||||
piix_init,
|
||||
piix_close,
|
||||
piix_reset,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL
|
||||
};
|
||||
2097
backup code/keyboard_at.c.old
Normal file
2097
backup code/keyboard_at.c.old
Normal file
File diff suppressed because it is too large
Load Diff
876
backup code/mouse_bus - Cópia (2).c
Normal file
876
backup code/mouse_bus - Cópia (2).c
Normal file
@@ -0,0 +1,876 @@
|
||||
/*
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
*
|
||||
* This file is part of the 86Box distribution.
|
||||
*
|
||||
* Implementation of Bus Mouse devices.
|
||||
*
|
||||
* These devices were made by both Microsoft and Logitech. At
|
||||
* first, Microsoft used the same protocol as Logitech, but did
|
||||
* switch to their new protocol for their InPort interface. So,
|
||||
* although alike enough to be handled in the same driver, they
|
||||
* are not the same.
|
||||
*
|
||||
* This code is based on my Minix driver for the Logitech(-mode)
|
||||
* interface. Although that driver blindly took IRQ5, the board
|
||||
* seems to be able to tell the driver what IRQ it is set for.
|
||||
* When testing on MS-DOS (6.22), the 'mouse.exe' driver did not
|
||||
* want to start, and only after disassembling it and inspecting
|
||||
* the code it was discovered that driver actually does use the
|
||||
* IRQ reporting feature. In a really, really weird way, too: it
|
||||
* sets up the board, and then reads the CTRL register which is
|
||||
* supposed to return that IRQ value. Depending on whether or
|
||||
* not the FREEZE bit is set, it has to return either the two's
|
||||
* complemented (negated) value, or (if clear) just the value.
|
||||
* The mouse.com driver reads both values 10,000 times, and
|
||||
* then makes up its mind. Maybe an effort to 'debounce' the
|
||||
* reading of the DIP switches? Oh-well.
|
||||
*
|
||||
* NOTES: Verified with:
|
||||
* AMI WinBIOS 486 (5A, no IRQ detect, OK, IRQ5 only)
|
||||
* Microsoft Mouse.com V2.00 (DOS V6.22, 5A, OK)
|
||||
* Microsoft Mouse.exe V9.1 (DOS V6.22, A5, OK)
|
||||
* Logitech LMouse.com V6.02 (DOS V6.22)
|
||||
* Logitech LMouse.com V6.43 (DOS V6.22)
|
||||
* Microsoft WfW V3.11 on DOS V6.22
|
||||
* GEOS V1.0 (OK, IRQ5 only)
|
||||
* GEOS V2.0 (OK, IRQ5 only)
|
||||
* Microsoft Windows 95 OSR2
|
||||
* Microsoft Windows 98 SE
|
||||
* Microsoft Windows NT 3.1
|
||||
* Microsoft Windows NT 3.51
|
||||
*
|
||||
* The polling frequency for InPort controllers has to
|
||||
* be changed to programmable. Microsoft uses 30Hz,
|
||||
* but ATIXL ports are programmable 30-200Hz.
|
||||
*
|
||||
* Based on an early driver for MINIX 1.5.
|
||||
*
|
||||
* Version: @(#)mouse_bus.c 1.0.39 2018/05/24
|
||||
*
|
||||
* Authors: Fred N. van Kempen, <decwiz@yahoo.com>
|
||||
*
|
||||
* Copyright 1989-2018 Fred N. van Kempen.
|
||||
*/
|
||||
#include <inttypes.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <wchar.h>
|
||||
#define HAVE_STDARG_H
|
||||
#include "86box.h"
|
||||
#include "config.h"
|
||||
#include "io.h"
|
||||
#include "pic.h"
|
||||
#include "timer.h"
|
||||
#include "device.h"
|
||||
#include "mouse.h"
|
||||
|
||||
|
||||
#define MOUSE_PORT 0x023c /* default */
|
||||
#define MOUSE_IRQ 5 /* default */
|
||||
#define MOUSE_BUTTONS 2 /* default */
|
||||
#define MOUSE_DEBUG 0
|
||||
|
||||
|
||||
/* Our mouse device. */
|
||||
typedef struct mouse {
|
||||
const char *name; /* name of this device */
|
||||
int8_t type; /* type of this device */
|
||||
uint16_t base; /* I/O port base to use */
|
||||
int8_t irq; /* IRQ channel to use */
|
||||
uint16_t flags; /* device flags */
|
||||
|
||||
uint8_t r_magic, /* MAGIC register */
|
||||
r_ctrl, /* CONTROL register (WR) */
|
||||
r_conf, /* CONFIG register */
|
||||
r_cmd; /* (MS) current command */
|
||||
|
||||
uint16_t seq; /* general counter */
|
||||
|
||||
uint8_t but, /* current mouse status */
|
||||
but_last;
|
||||
uint8_t cur_but;
|
||||
int8_t x, y;
|
||||
int x_delay,
|
||||
y_delay;
|
||||
uint8_t irq_num;
|
||||
|
||||
int64_t timer; /* mouse event timer */
|
||||
|
||||
uint8_t (*read)(struct mouse *, uint16_t);
|
||||
void (*write)(struct mouse *, uint16_t, uint8_t);
|
||||
} mouse_t;
|
||||
#define FLAG_NEW 0x100 /* device is the newer variant */
|
||||
#define FLAG_INPORT 0x80 /* device is MS InPort */
|
||||
#define FLAG_3BTN 0x20 /* enable 3-button mode */
|
||||
#define FLAG_SCALED 0x10 /* enable delta scaling */
|
||||
#define FLAG_INTR 0x04 /* dev can send interrupts */
|
||||
#define FLAG_FROZEN 0x02 /* do not update counters */
|
||||
#define FLAG_ENABLED 0x01 /* dev is enabled for use */
|
||||
|
||||
|
||||
/* Definitions for Logitech. */
|
||||
#define LTMOUSE_DATA 0 /* DATA register */
|
||||
#define LTMOUSE_MAGIC 1 /* signature magic register */
|
||||
# define LTMAGIC_BYTE1 0xa5 /* most drivers use this */
|
||||
# define LTMAGIC_BYTE2 0x5a /* some drivers use this */
|
||||
#define LTMOUSE_CTRL 2 /* CTRL register */
|
||||
# define LTCTRL_FREEZE 0x80 /* do not sample when set */
|
||||
# define LTCTRL_RD_Y_HI 0x60
|
||||
# define LTCTRL_RD_Y_LO 0x40
|
||||
# define LTCTRL_RD_X_HI 0x20
|
||||
# define LTCTRL_RD_X_LO 0x00
|
||||
# define LTCTRL_RD_MASK 0x60
|
||||
# define LTCTRL_IDIS 0x10
|
||||
# define LTCTRL_IENB 0x00
|
||||
#define LTMOUSE_CONFIG 3 /* CONFIG register */
|
||||
|
||||
/* Definitions for Microsoft. */
|
||||
#define MSMOUSE_CTRL 0 /* CTRL register */
|
||||
# define MSCTRL_RESET 0x80 /* reset controller */
|
||||
# define MSCTRL_FREEZE 0x20 /* HOLD- freeze data */
|
||||
# define MSCTRL_IENB_A 0x08 /* ATIXL intr enable */
|
||||
# define MSCTRL_IENB_M 0x01 /* MS intr enable */
|
||||
# define MSCTRL_COMMAND 0x07
|
||||
# define MSCTRL_RD_Y 0x02
|
||||
# define MSCTRL_RD_X 0x01
|
||||
# define MSCTRL_RD_BUT 0x00
|
||||
#define MSMOUSE_DATA 1 /* DATA register */
|
||||
# define MSDATA_IRQ 0x16
|
||||
# define MSDATA_BASE 0x10 /* MS InPort: 30Hz */
|
||||
# define MSDATA_HZ30 0x01 /* ATIXL 30Hz */
|
||||
# define MSDATA_HZ50 0x02 /* ATIXL 50Hz */
|
||||
# define MSDATA_HZ100 0x03 /* ATIXL 100Hz */
|
||||
# define MSDATA_HZ200 0x04 /* ATIXL 200Hz */
|
||||
#define MSMOUSE_MAGIC 2 /* MAGIC register */
|
||||
# define MAGIC_MSBYTE1 0xde /* indicates MS InPort */
|
||||
# define MAGIC_MSBYTE2 0x12
|
||||
#define MSMOUSE_CONFIG 3 /* CONFIG register */
|
||||
|
||||
|
||||
#ifdef ENABLE_MOUSE_BUS_LOG
|
||||
int mouse_bus_do_log = ENABLE_MOUSE_BUS_LOG;
|
||||
#endif
|
||||
|
||||
|
||||
static void
|
||||
mouse_bus_log(const char *format, ...)
|
||||
{
|
||||
#ifdef ENABLE_MOUSE_BUS_LOG
|
||||
va_list ap;
|
||||
|
||||
if (mouse_bus_do_log) {
|
||||
va_start(ap, format);
|
||||
pclog_ex(format, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/* Reset the controller state. */
|
||||
static void
|
||||
ms_reset(mouse_t *dev)
|
||||
{
|
||||
dev->r_ctrl = 0x00;
|
||||
dev->r_cmd = 0x00;
|
||||
|
||||
dev->seq = 0;
|
||||
|
||||
dev->x = dev->y = 0;
|
||||
dev->but = 0x00;
|
||||
|
||||
dev->flags &= 0xf0;
|
||||
dev->flags |= (FLAG_INTR | FLAG_ENABLED);
|
||||
|
||||
dev->x_delay = dev->y_delay = 0;
|
||||
|
||||
dev->cur_but = 0x00;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
ms_update_data(mouse_t *dev)
|
||||
{
|
||||
int delta_x, delta_y;
|
||||
|
||||
if (dev->x_delay > 127) {
|
||||
delta_x = 127;
|
||||
dev->x_delay -= 127;
|
||||
} else if (dev->x_delay < -128) {
|
||||
delta_x = -128;
|
||||
dev->x_delay += 128;
|
||||
} else {
|
||||
delta_x = dev->x_delay;
|
||||
dev->x_delay = 0;
|
||||
}
|
||||
|
||||
if (dev->y_delay > 127) {
|
||||
delta_y = 127;
|
||||
dev->y_delay -= 127;
|
||||
} else if (dev->y_delay < -128) {
|
||||
delta_y = -128;
|
||||
dev->x_delay += 128;
|
||||
} else {
|
||||
delta_y = dev->y_delay;
|
||||
dev->y_delay = 0;
|
||||
}
|
||||
|
||||
if (!(dev->flags & FLAG_FROZEN)) {
|
||||
dev->x = (int8_t) delta_x;
|
||||
dev->y = (int8_t) delta_y;
|
||||
dev->cur_but = dev->but;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Handle a WRITE to an InPort register. */
|
||||
static void
|
||||
ms_write(mouse_t *dev, uint16_t port, uint8_t val)
|
||||
{
|
||||
uint8_t valxor;
|
||||
|
||||
switch (port) {
|
||||
case MSMOUSE_CTRL:
|
||||
/* Bit 7 is reset. */
|
||||
if (val & MSCTRL_RESET)
|
||||
ms_reset(dev);
|
||||
|
||||
/* Bits 0-2 are the internal register index. */
|
||||
switch (val & 0x07) {
|
||||
case MSCTRL_COMMAND:
|
||||
case MSCTRL_RD_BUT:
|
||||
case MSCTRL_RD_X:
|
||||
case MSCTRL_RD_Y:
|
||||
dev->r_cmd = val & 0x07;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case MSMOUSE_DATA:
|
||||
picintc(1 << dev->irq);
|
||||
|
||||
if (val == MSDATA_IRQ)
|
||||
picint(1 << dev->irq);
|
||||
else {
|
||||
switch (dev->r_cmd) {
|
||||
case MSCTRL_COMMAND:
|
||||
valxor = (dev->r_ctrl ^ val);
|
||||
|
||||
if (valxor & MSCTRL_FREEZE) {
|
||||
if (val & MSCTRL_FREEZE) {
|
||||
/* Hold the sampling while we do something. */
|
||||
dev->flags |= FLAG_FROZEN;
|
||||
} else {
|
||||
/* Reset current state. */
|
||||
dev->flags &= ~FLAG_FROZEN;
|
||||
|
||||
dev->x = dev->y = 0;
|
||||
dev->but = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (val & (MSCTRL_IENB_M | MSCTRL_IENB_A))
|
||||
dev->flags |= FLAG_INTR;
|
||||
else
|
||||
dev->flags &= ~FLAG_INTR;
|
||||
|
||||
dev->r_ctrl = val;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case MSMOUSE_MAGIC:
|
||||
break;
|
||||
|
||||
case MSMOUSE_CONFIG:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Handle a READ from an InPort register. */
|
||||
static uint8_t
|
||||
ms_read(mouse_t *dev, uint16_t port)
|
||||
{
|
||||
uint8_t ret = 0x00;
|
||||
|
||||
switch (port) {
|
||||
case MSMOUSE_CTRL:
|
||||
ret = dev->r_ctrl;
|
||||
break;
|
||||
|
||||
case MSMOUSE_DATA:
|
||||
switch (dev->r_cmd) {
|
||||
case MSCTRL_RD_BUT:
|
||||
ret = dev->cur_but;
|
||||
if (dev->flags & FLAG_NEW)
|
||||
ret |= 0x40; /* On new InPort, always have bit 6 set. */
|
||||
break;
|
||||
|
||||
case MSCTRL_RD_X:
|
||||
ret = dev->x;
|
||||
break;
|
||||
|
||||
case MSCTRL_RD_Y:
|
||||
ret = dev->y;
|
||||
break;
|
||||
|
||||
case MSCTRL_COMMAND:
|
||||
ret = dev->r_ctrl;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case MSMOUSE_MAGIC:
|
||||
if (dev->seq & 0x01)
|
||||
ret = MAGIC_MSBYTE2;
|
||||
else
|
||||
ret = MAGIC_MSBYTE1;
|
||||
dev->seq ^= 1;
|
||||
break;
|
||||
|
||||
case MSMOUSE_CONFIG:
|
||||
/* Not really present in real hardware. */
|
||||
break;
|
||||
}
|
||||
|
||||
return(ret);
|
||||
}
|
||||
|
||||
|
||||
/* Reset the controller state. */
|
||||
static void
|
||||
lt_reset(mouse_t *dev)
|
||||
{
|
||||
dev->r_ctrl = (LTCTRL_IDIS) | 0x0f;
|
||||
dev->r_conf = 0x0e;
|
||||
dev->r_magic = 0x00;
|
||||
|
||||
dev->seq = 0;
|
||||
dev->flags &= 0xf0;
|
||||
|
||||
dev->x = dev->y = 0;
|
||||
dev->but = 0x00;
|
||||
|
||||
dev->irq_num = 0;
|
||||
}
|
||||
|
||||
|
||||
/* Called at 30hz */
|
||||
static void
|
||||
bm_timer(void *priv)
|
||||
{
|
||||
mouse_t *dev = (mouse_t *)priv;
|
||||
|
||||
if (dev->flags & FLAG_INPORT) {
|
||||
dev->timer = ((1000000LL * TIMER_USEC) / 30LL);
|
||||
|
||||
ms_update_data(dev);
|
||||
|
||||
if (dev->flags & FLAG_INTR)
|
||||
picint(1 << dev->irq);
|
||||
} else {
|
||||
picint(1 << dev->irq);
|
||||
|
||||
if (dev->irq_num == 5) {
|
||||
mouse_bus_log("5th IRQ, enabling mouse...\n");
|
||||
lt_reset(dev);
|
||||
dev->flags |= FLAG_ENABLED;
|
||||
}
|
||||
|
||||
if (dev->irq_num == 4) {
|
||||
mouse_bus_log("4th IRQ, going for the 5th...\n");
|
||||
dev->irq_num++;
|
||||
dev->timer = ((1000000LL * TIMER_USEC) / 30LL);
|
||||
} else {
|
||||
mouse_bus_log("IRQ before the 4th, disabling timer...\n");
|
||||
dev->timer = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Handle a WRITE to a Logitech register. */
|
||||
static void
|
||||
lt_write(mouse_t *dev, uint16_t port, uint8_t val)
|
||||
{
|
||||
uint8_t b;
|
||||
|
||||
switch (port) {
|
||||
case LTMOUSE_DATA: /* [00] data register */
|
||||
break;
|
||||
|
||||
case LTMOUSE_MAGIC: /* [01] magic data register */
|
||||
switch(val) {
|
||||
case LTMAGIC_BYTE1:
|
||||
case LTMAGIC_BYTE2:
|
||||
lt_reset(dev);
|
||||
dev->r_magic = val;
|
||||
dev->flags |= FLAG_ENABLED;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case LTMOUSE_CTRL: /* [02] control register */
|
||||
if (!(dev->flags & FLAG_ENABLED)) {
|
||||
dev->irq_num++;
|
||||
dev->timer = ((1000000LL * TIMER_USEC) / 30LL);
|
||||
break;
|
||||
}
|
||||
|
||||
b = (dev->r_ctrl ^ val);
|
||||
if (b & LTCTRL_FREEZE) {
|
||||
if (val & LTCTRL_FREEZE) {
|
||||
/* Hold the sampling while we do something. */
|
||||
dev->flags |= FLAG_FROZEN;
|
||||
} else {
|
||||
/* Reset current state. */
|
||||
dev->flags &= ~FLAG_FROZEN;
|
||||
dev->x = dev->y = 0;
|
||||
if (dev->but)
|
||||
dev->but |= 0x80;
|
||||
}
|
||||
}
|
||||
|
||||
if (b & LTCTRL_IDIS) {
|
||||
/* Disable or enable interrupts. */
|
||||
if (val & LTCTRL_IDIS)
|
||||
dev->flags &= ~FLAG_INTR;
|
||||
else
|
||||
dev->flags |= FLAG_INTR;
|
||||
}
|
||||
|
||||
/* Save new register value. */
|
||||
dev->r_ctrl = val | 0x0F;
|
||||
|
||||
/* Clear any pending interrupts. */
|
||||
picintc(1 << dev->irq);
|
||||
break;
|
||||
|
||||
case LTMOUSE_CONFIG: /* [03] config register */
|
||||
/*
|
||||
* The original Logitech design was based on using a
|
||||
* 8255 parallel I/O chip. This chip has to be set up
|
||||
* for proper operation, and this configuration data
|
||||
* is what is programmed into this register.
|
||||
*
|
||||
* A snippet of code found in the FreeBSD kernel source
|
||||
* explains the value:
|
||||
*
|
||||
* D7 = Mode set flag (1 = active)
|
||||
* D6,D5 = Mode selection (port A)
|
||||
* 00 = Mode 0 = Basic I/O
|
||||
* 01 = Mode 1 = Strobed I/O
|
||||
* 10 = Mode 2 = Bi-dir bus
|
||||
* D4 = Port A direction (1 = input)
|
||||
* D3 = Port C (upper 4 bits) direction. (1 = input)
|
||||
* D2 = Mode selection (port B & C)
|
||||
* 0 = Mode 0 = Basic I/O
|
||||
* 1 = Mode 1 = Strobed I/O
|
||||
* D1 = Port B direction (1 = input)
|
||||
* D0 = Port C (lower 4 bits) direction. (1 = input)
|
||||
*
|
||||
* So 91 means Basic I/O on all 3 ports, Port A is an input
|
||||
* port, B is an output port, C is split with upper 4 bits
|
||||
* being an output port and lower 4 bits an input port, and
|
||||
* enable the sucker. Courtesy Intel 8255 databook. Lars
|
||||
*/
|
||||
dev->r_conf = val;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
lt_read_int(mouse_t *dev)
|
||||
{
|
||||
if (!(dev->flags & FLAG_NEW))
|
||||
return 1; /* On old LogiBus, read the IRQ bits always. */
|
||||
|
||||
if (dev->flags & FLAG_INTR)
|
||||
return 1; /* On new LogiBus, read the IRQ bits if interrupts are enabled. */
|
||||
|
||||
return 0; /* Otherwise, do not. */
|
||||
}
|
||||
|
||||
|
||||
/* Handle a READ from a Logitech register. */
|
||||
static uint8_t
|
||||
lt_read(mouse_t *dev, uint16_t port)
|
||||
{
|
||||
uint8_t ret = 0xff;
|
||||
|
||||
/* The GEOS drivers actually check this. */
|
||||
if (! (dev->flags & FLAG_ENABLED)) return(ret);
|
||||
|
||||
switch (port) {
|
||||
case LTMOUSE_DATA: /* [00] data register */
|
||||
ret = 0x07;
|
||||
if (dev->but & 0x01) /* LEFT */
|
||||
ret &= ~0x04;
|
||||
if (dev->but & 0x02) /* RIGHT */
|
||||
ret &= ~0x01;
|
||||
if (dev->flags & FLAG_3BTN)
|
||||
if (dev->but & 0x04) /* MIDDLE */
|
||||
ret &= ~0x02;
|
||||
ret <<= 5;
|
||||
|
||||
switch(dev->r_ctrl & LTCTRL_RD_MASK) {
|
||||
case LTCTRL_RD_X_LO: /* X, low bits */
|
||||
ret |= (dev->x & 0x0f);
|
||||
break;
|
||||
|
||||
case LTCTRL_RD_X_HI: /* X, high bits */
|
||||
ret |= (dev->x >> 4) & 0x0f;
|
||||
break;
|
||||
|
||||
case LTCTRL_RD_Y_LO: /* Y, low bits */
|
||||
ret |= (dev->y & 0x0f);
|
||||
break;
|
||||
|
||||
case LTCTRL_RD_Y_HI: /* Y, high bits */
|
||||
ret |= (dev->y >> 4) & 0x0f;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case LTMOUSE_MAGIC: /* [01] magic data register */
|
||||
/*
|
||||
* Drivers write a magic byte to this register, usually
|
||||
* this is either 5A (AMI WinBIOS, MS Mouse 2.0) or
|
||||
* A5 (MS Mouse 9.1, Windows drivers, UNIX/Linux/Minix.)
|
||||
*/
|
||||
ret = dev->r_magic;
|
||||
break;
|
||||
|
||||
0x20 >> 5 = 0x01
|
||||
0x20 >> 4 = 0x02
|
||||
0x20 >> 3 = 0x04
|
||||
0x20 >> 2 = 0x08
|
||||
|
||||
case LTMOUSE_CTRL: /* [02] control register */
|
||||
ret = dev->r_ctrl;
|
||||
dev->r_ctrl |= 0x0F;
|
||||
if ((dev->seq > 0x3FF) && lt_read_int(dev)) {
|
||||
/* !IDIS, return DIP switch setting. */
|
||||
dev->r_ctrl &= ~((1 << 5) >> dev->irq);
|
||||
#if 0
|
||||
switch(dev->irq) {
|
||||
case 2:
|
||||
dev->r_ctrl &= ~0x08;
|
||||
break;
|
||||
|
||||
case 3:
|
||||
dev->r_ctrl &= ~0x04;
|
||||
break;
|
||||
|
||||
case 4:
|
||||
dev->r_ctrl &= ~0x02;
|
||||
break;
|
||||
|
||||
case 5:
|
||||
dev->r_ctrl &= ~0x01;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
dev->seq = (dev->seq + 1) & 0x7ff;
|
||||
break;
|
||||
|
||||
case LTMOUSE_CONFIG: /* [03] config register */
|
||||
ret = dev->r_conf;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return(ret);
|
||||
}
|
||||
|
||||
|
||||
/* Handle a WRITE operation to one of our registers. */
|
||||
static void
|
||||
bm_write(uint16_t port, uint8_t val, void *priv)
|
||||
{
|
||||
mouse_t *dev = (mouse_t *)priv;
|
||||
|
||||
mouse_bus_log("%s: write(%d,%02x)\n", dev->name, port & 0x03, val);
|
||||
|
||||
dev->write(dev, port & 0x03, val);
|
||||
}
|
||||
|
||||
|
||||
/* Handle a READ operation from one of our registers. */
|
||||
static uint8_t
|
||||
bm_read(uint16_t port, void *priv)
|
||||
{
|
||||
mouse_t *dev = (mouse_t *)priv;
|
||||
uint8_t ret;
|
||||
|
||||
ret = dev->read(dev, port & 0x03);
|
||||
|
||||
mouse_bus_log("%s: read(%d): %02x\n", dev->name, port & 0x03, ret);
|
||||
|
||||
return(ret);
|
||||
}
|
||||
|
||||
|
||||
/* The emulator calls us with an update on the host mouse device. */
|
||||
static int
|
||||
bm_poll(int x, int y, int z, int b, void *priv)
|
||||
{
|
||||
uint8_t b_last;
|
||||
mouse_t *dev = (mouse_t *)priv;
|
||||
|
||||
b_last = dev->but;
|
||||
|
||||
/* Return early if nothing to do. */
|
||||
if (!x && !y && !z && (dev->but == b))
|
||||
return(1);
|
||||
|
||||
/* If we are not enabled, return. */
|
||||
if (! (dev->flags & FLAG_ENABLED))
|
||||
mouse_bus_log("bm_poll(): Mouse not enabled\n");
|
||||
|
||||
if (dev->flags & FLAG_SCALED) {
|
||||
/* Scale down the motion. */
|
||||
if ((x < -1) || (x > 1)) x >>= 1;
|
||||
if ((y < -1) || (y > 1)) y >>= 1;
|
||||
}
|
||||
|
||||
if (dev->flags & FLAG_INPORT) {
|
||||
if (x || y || z)
|
||||
dev->but = 0x40; /* Mouse has moved. */
|
||||
else
|
||||
dev->but = 0x00;
|
||||
|
||||
if (x > 127) x = 127;
|
||||
if (y > 127) y = 127;
|
||||
if (x < -128) x = -128;
|
||||
if (y < -128) y = -128;
|
||||
|
||||
dev->x_delay += x;
|
||||
dev->y_delay += y;
|
||||
dev->but |= (uint8_t) (((b & 1) << 2) | ((b & 2) >> 1));
|
||||
if (dev->flags & FLAG_3BTN)
|
||||
dev->but |= ((b & 4) >> 1);
|
||||
|
||||
if ((b_last ^ dev->but) & 0x04)
|
||||
dev->but |= 0x20; /* Left button state has changed. */
|
||||
if (((b_last ^ dev->but) & 0x02) && (dev->flags & FLAG_3BTN))
|
||||
dev->but |= 0x10; /* Middle button state has changed. */
|
||||
if ((b_last ^ dev->but) & 0x01)
|
||||
dev->but |= 0x08; /* Right button state has changed. */
|
||||
|
||||
dev->but |= 0x80; /* Packet complete. */
|
||||
} else {
|
||||
/* If we are frozen, do not update the state. */
|
||||
if (! (dev->flags & FLAG_FROZEN)) {
|
||||
/* Add the delta to our state. */
|
||||
x += dev->x;
|
||||
if (x > 127)
|
||||
x = 127;
|
||||
if (x < -128)
|
||||
x = -128;
|
||||
dev->x = (int8_t)x;
|
||||
|
||||
y += dev->y;
|
||||
if (y > 127)
|
||||
y = 127;
|
||||
if (y < -1287)
|
||||
y = -1287;
|
||||
dev->y = (int8_t)y;
|
||||
|
||||
dev->x_delay += x;
|
||||
dev->y_delay += y;
|
||||
|
||||
dev->but = b;
|
||||
}
|
||||
|
||||
/* Either way, generate an interrupt. */
|
||||
if ((dev->flags & FLAG_INTR) && !(dev->flags & FLAG_INPORT))
|
||||
picint(1 << dev->irq);
|
||||
}
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
/* Release all resources held by the device. */
|
||||
static void
|
||||
bm_close(void *priv)
|
||||
{
|
||||
mouse_t *dev = (mouse_t *)priv;
|
||||
|
||||
/* Release our I/O range. */
|
||||
io_removehandler(dev->base, 4,
|
||||
bm_read, NULL, NULL, bm_write, NULL, NULL, dev);
|
||||
|
||||
free(dev);
|
||||
}
|
||||
|
||||
|
||||
/* Initialize the device for use by the user. */
|
||||
static void *
|
||||
bm_init(const device_t *info)
|
||||
{
|
||||
mouse_t *dev;
|
||||
int i, j;
|
||||
|
||||
dev = (mouse_t *)malloc(sizeof(mouse_t));
|
||||
memset(dev, 0x00, sizeof(mouse_t));
|
||||
dev->name = info->name;
|
||||
dev->type = info->local;
|
||||
dev->base = device_get_config_hex16("base");
|
||||
dev->irq = device_get_config_int("irq");
|
||||
i = device_get_config_int("buttons");
|
||||
if (i > 2)
|
||||
dev->flags |= FLAG_3BTN;
|
||||
j = device_get_config_int("model");
|
||||
if (j)
|
||||
dev->flags |= FLAG_NEW;
|
||||
|
||||
switch(dev->type) {
|
||||
case MOUSE_TYPE_LOGIBUS:
|
||||
lt_reset(dev);
|
||||
|
||||
/* Initialize I/O handlers. */
|
||||
dev->read = lt_read;
|
||||
dev->write = lt_write;
|
||||
|
||||
dev->timer = 0;
|
||||
timer_add(bm_timer, &dev->timer, &dev->timer, dev);
|
||||
break;
|
||||
|
||||
case MOUSE_TYPE_INPORT:
|
||||
dev->flags |= FLAG_INPORT;
|
||||
ms_reset(dev);
|
||||
|
||||
/* Initialize I/O handlers. */
|
||||
dev->read = ms_read;
|
||||
dev->write = ms_write;
|
||||
|
||||
dev->timer = (33334LL * TIMER_USEC);
|
||||
timer_add(bm_timer, &dev->timer, TIMER_ALWAYS_ENABLED, dev);
|
||||
break;
|
||||
}
|
||||
|
||||
/* Request an I/O range. */
|
||||
io_sethandler(dev->base, 4,
|
||||
bm_read, NULL, NULL, bm_write, NULL, NULL, dev);
|
||||
|
||||
mouse_bus_log("%s: I/O=%04x, IRQ=%d, buttons=%d, model=%s\n",
|
||||
dev->name, dev->base, dev->irq, i, j ? "new" : "old");
|
||||
|
||||
/* Tell them how many buttons we have. */
|
||||
mouse_set_buttons((dev->flags & FLAG_3BTN) ? 3 : 2);
|
||||
|
||||
/* Return our private data to the I/O layer. */
|
||||
return(dev);
|
||||
}
|
||||
|
||||
|
||||
static const device_config_t bm_config[] = {
|
||||
{
|
||||
"base", "Address", CONFIG_HEX16, "", MOUSE_PORT,
|
||||
{
|
||||
{
|
||||
"0x230", 0x230
|
||||
},
|
||||
{
|
||||
"0x234", 0x234
|
||||
},
|
||||
{
|
||||
"0x238", 0x238
|
||||
},
|
||||
{
|
||||
"0x23C", 0x23c
|
||||
},
|
||||
{
|
||||
""
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"irq", "IRQ", CONFIG_SELECTION, "", MOUSE_IRQ, {
|
||||
{
|
||||
"IRQ 2", 2
|
||||
},
|
||||
{
|
||||
"IRQ 3", 3
|
||||
},
|
||||
{
|
||||
"IRQ 4", 4
|
||||
},
|
||||
{
|
||||
"IRQ 5", 5
|
||||
},
|
||||
{
|
||||
""
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"buttons", "Buttons", CONFIG_SELECTION, "", MOUSE_BUTTONS, {
|
||||
{
|
||||
"Two", 2
|
||||
},
|
||||
{
|
||||
"Three", 3
|
||||
},
|
||||
{
|
||||
""
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"model", "Model", CONFIG_SELECTION, "", 0, {
|
||||
{
|
||||
"Old", 0
|
||||
},
|
||||
{
|
||||
"New", 1
|
||||
},
|
||||
{
|
||||
""
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"", "", -1
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
const device_t mouse_logibus_device = {
|
||||
"Logitech Bus Mouse",
|
||||
DEVICE_ISA,
|
||||
MOUSE_TYPE_LOGIBUS,
|
||||
bm_init, bm_close, NULL,
|
||||
bm_poll, NULL, NULL,
|
||||
bm_config
|
||||
};
|
||||
|
||||
const device_t mouse_msinport_device = {
|
||||
"Microsoft Bus Mouse (InPort)",
|
||||
DEVICE_ISA,
|
||||
MOUSE_TYPE_INPORT,
|
||||
bm_init, bm_close, NULL,
|
||||
bm_poll, NULL, NULL,
|
||||
bm_config
|
||||
};
|
||||
632
backup code/mouse_bus - Cópia (3).c
Normal file
632
backup code/mouse_bus - Cópia (3).c
Normal file
@@ -0,0 +1,632 @@
|
||||
/*
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
*
|
||||
* This file is part of the 86Box distribution.
|
||||
*
|
||||
* Implementation of Bus Mouse devices.
|
||||
*
|
||||
* These devices were made by both Microsoft and Logitech. At
|
||||
* first, Microsoft used the same protocol as Logitech, but did
|
||||
* switch to their new protocol for their InPort interface. So,
|
||||
* although alike enough to be handled in the same driver, they
|
||||
* are not the same.
|
||||
*
|
||||
* NOTES: Ported from Bochs with extensive modifications per testing
|
||||
* of the real hardware, testing of drivers, and the old code.
|
||||
*
|
||||
* Logitech Bus Mouse verified with:
|
||||
* Logitech LMouse.com 3.12
|
||||
* Logitech LMouse.com 3.30
|
||||
* Logitech LMouse.com 3.41
|
||||
* Logitech LMouse.com 3.42
|
||||
* Logitech LMouse.com 4.00
|
||||
* Logitech LMouse.com 5.00
|
||||
* Logitech LMouse.com 6.00
|
||||
* Logitech LMouse.com 6.02 Beta
|
||||
* Logitech LMouse.com 6.02
|
||||
* Logitech LMouse.com 6.12
|
||||
* Logitech LMouse.com 6.20
|
||||
* Logitech LMouse.com 6.23
|
||||
* Logitech LMouse.com 6.30
|
||||
* Logitech LMouse.com 6.31E
|
||||
* Logitech LMouse.com 6.34
|
||||
* Logitech Mouse.exe 6.40
|
||||
* Logitech Mouse.exe 6.41
|
||||
* Logitech Mouse.exe 6.44
|
||||
* Logitech Mouse.exe 6.46
|
||||
* Logitech Mouse.exe 6.50
|
||||
* Microsoft Mouse.com 2.00
|
||||
* Microsoft Mouse.sys 3.00
|
||||
* Microsoft Windows 1.00 DR5
|
||||
* Microsoft Windows 3.10.026
|
||||
* Microsoft Windows NT 3.1
|
||||
* Microsoft Windows 95
|
||||
*
|
||||
* InPort verified with:
|
||||
* Logitech LMouse.com 6.12
|
||||
* Logitech LMouse.com 6.41
|
||||
* Microsoft Windows NT 3.1
|
||||
* Microsoft Windows 98 SE
|
||||
*
|
||||
* Version: @(#)mouse_bus.c 1.0.0 2018/05/23
|
||||
*
|
||||
* Authors: Miran Grca, <mgrca8@gmail.com>
|
||||
*
|
||||
* Copyright 200?-2018 Bochs.
|
||||
* Copyright 2018 Miran Grca.
|
||||
*/
|
||||
#include <inttypes.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <wchar.h>
|
||||
#define HAVE_STDARG_H
|
||||
#include "86box.h"
|
||||
#include "config.h"
|
||||
#include "io.h"
|
||||
#include "pic.h"
|
||||
#include "timer.h"
|
||||
#include "device.h"
|
||||
#include "mouse.h"
|
||||
|
||||
#define IRQ_MASK ((1<<5) >> dev->irq)
|
||||
|
||||
/* MS Inport Bus Mouse Adapter */
|
||||
#define INP_PORT_CONTROL 0x0000
|
||||
#define INP_PORT_DATA 0x0001
|
||||
#define INP_PORT_SIGNATURE 0x0002
|
||||
#define INP_PORT_CONFIG 0x0003
|
||||
|
||||
#define INP_CTRL_READ_BUTTONS 0x00
|
||||
#define INP_CTRL_READ_X 0x01
|
||||
#define INP_CTRL_READ_Y 0x02
|
||||
#define INP_CTRL_COMMAND 0x07
|
||||
#define INP_CTRL_RAISE_IRQ 0x16
|
||||
#define INP_CTRL_RESET 0x80
|
||||
|
||||
#define INP_HOLD_COUNTER (1 << 5)
|
||||
#define INP_ENABLE_TIMER_IRQ (1 << 4)
|
||||
#define INP_ENABLE_DATA_IRQ (1 << 3)
|
||||
#define INP_PERIOD_MASK 0x07
|
||||
|
||||
#define INP_PERIOD (33334LL * TIMER_USEC)
|
||||
|
||||
/* MS/Logictech Standard Bus Mouse Adapter */
|
||||
#define BUSM_PORT_DATA 0x0000
|
||||
#define BUSM_PORT_SIGNATURE 0x0001
|
||||
#define BUSM_PORT_CONTROL 0x0002
|
||||
#define BUSM_PORT_CONFIG 0x0003
|
||||
|
||||
/* The MS/Logitech Standard Bus Mouse sends data about 45 times a second */
|
||||
#define BUSM_PERIOD (22223LL * TIMER_USEC)
|
||||
|
||||
#define HOLD_COUNTER (1 << 7)
|
||||
#define READ_X (0 << 6)
|
||||
#define READ_Y (1 << 6)
|
||||
#define READ_LOW (0 << 5)
|
||||
#define READ_HIGH (1 << 5)
|
||||
#define DISABLE_IRQ (1 << 4)
|
||||
|
||||
#define READ_X_LOW (READ_X | READ_LOW)
|
||||
#define READ_X_HIGH (READ_X | READ_HIGH)
|
||||
#define READ_Y_LOW (READ_Y | READ_LOW)
|
||||
#define READ_Y_HIGH (READ_Y | READ_HIGH)
|
||||
|
||||
|
||||
/* Our mouse device. */
|
||||
typedef struct mouse {
|
||||
int type, model, base, irq, bn,
|
||||
mouse_delayed_dx, mouse_delayed_dy,
|
||||
mouse_buttons,
|
||||
current_x, current_y,
|
||||
current_b,
|
||||
control_val, mouse_buttons_last,
|
||||
config_val, sig_val,
|
||||
command_val, toggle_counter,
|
||||
data_int, hold,
|
||||
interrupts;
|
||||
|
||||
double period;
|
||||
|
||||
int64_t timer_enabled, timer; /* mouse event timer */
|
||||
} mouse_t;
|
||||
|
||||
|
||||
#ifdef ENABLE_MOUSE_BUS_LOG
|
||||
int bm_do_log = ENABLE_MOUSE_BUS_LOG;
|
||||
#endif
|
||||
|
||||
|
||||
static void
|
||||
bm_log(const char *format, ...)
|
||||
{
|
||||
#ifdef ENABLE_MOUSE_BUS_LOG
|
||||
va_list ap;
|
||||
|
||||
if (bm_do_log) {
|
||||
va_start(ap, format);
|
||||
pclog_ex(format, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/* Handle a READ operation from one of our registers. */
|
||||
static uint8_t
|
||||
bm_read(uint16_t port, void *priv)
|
||||
{
|
||||
mouse_t *dev = (mouse_t *)priv;
|
||||
uint8_t value;
|
||||
|
||||
if (dev->type == MOUSE_TYPE_INPORT) {
|
||||
switch (port & 0x03) {
|
||||
case INP_PORT_CONTROL:
|
||||
value = dev->control_val;
|
||||
break;
|
||||
case INP_PORT_DATA:
|
||||
switch (dev->command_val) {
|
||||
case INP_CTRL_READ_BUTTONS:
|
||||
value = dev->current_b | 0x80;
|
||||
if (dev->model)
|
||||
value |= 0x40; /* Newer Logitech mouse drivers look for bit 6 set */
|
||||
break;
|
||||
case INP_CTRL_READ_X:
|
||||
value = dev->current_x;
|
||||
break;
|
||||
case INP_CTRL_READ_Y:
|
||||
value = dev->current_y;
|
||||
break;
|
||||
case INP_CTRL_COMMAND:
|
||||
value = dev->control_val;
|
||||
break;
|
||||
default:
|
||||
bm_log("ERROR: Reading data port in unsupported mode 0x%02x\n", dev->control_val);
|
||||
}
|
||||
break;
|
||||
case INP_PORT_SIGNATURE:
|
||||
if (dev->toggle_counter)
|
||||
value = 0x12;
|
||||
else
|
||||
value = 0xDE;
|
||||
dev->toggle_counter ^= 1;
|
||||
break;
|
||||
case INP_PORT_CONFIG:
|
||||
bm_log("ERROR: Unsupported read from port 0x%04x\n", port);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
switch (port & 0x03) {
|
||||
case BUSM_PORT_CONTROL:
|
||||
value = dev->control_val;
|
||||
dev->control_val |= 0x0F;
|
||||
|
||||
if ((dev->toggle_counter > 0x3FF) && (!dev->model || dev->interrupts))
|
||||
dev->control_val &= ~IRQ_MASK;
|
||||
dev->toggle_counter = (dev->toggle_counter + 1) & 0x7FF;
|
||||
break;
|
||||
case BUSM_PORT_DATA:
|
||||
/* Testing and another source confirm that the buttons are
|
||||
*ALWAYS* present, so I'm going to change this a bit. */
|
||||
switch (dev->control_val & 0x60) {
|
||||
case READ_X_LOW:
|
||||
value = dev->current_x & 0x0F;
|
||||
break;
|
||||
case READ_X_HIGH:
|
||||
value = (dev->current_x >> 4) & 0x0F;
|
||||
break;
|
||||
case READ_Y_LOW:
|
||||
value = dev->current_y & 0x0F;
|
||||
break;
|
||||
case READ_Y_HIGH:
|
||||
value = (dev->current_y >> 4) & 0x0F;
|
||||
break;
|
||||
default:
|
||||
bm_log("ERROR: Reading data port in unsupported mode 0x%02x\n", dev->control_val);
|
||||
}
|
||||
value |= ((dev->current_b ^ 7) << 5);
|
||||
break;
|
||||
case BUSM_PORT_CONFIG:
|
||||
value = dev->config_val;
|
||||
break;
|
||||
case BUSM_PORT_SIGNATURE:
|
||||
value = dev->sig_val;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bm_log("DEBUG: read from address 0x%04x, value = 0x%02x\n", port, value);
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
/* Handle a WRITE operation to one of our registers. */
|
||||
static void
|
||||
bm_write(uint16_t port, uint8_t val, void *priv)
|
||||
{
|
||||
mouse_t *dev = (mouse_t *)priv;
|
||||
|
||||
bm_log("DEBUG: write to address 0x%04x, value = 0x%02x\n", port, val);
|
||||
|
||||
if (dev->type == MOUSE_TYPE_INPORT) {
|
||||
switch (port & 0x03) {
|
||||
case INP_PORT_CONTROL:
|
||||
/* Bit 7 is reset. */
|
||||
if (val & INP_CTRL_RESET)
|
||||
dev->control_val = 0;
|
||||
|
||||
/* Bits 0-2 are the internal register index. */
|
||||
switch(val & 0x07) {
|
||||
case INP_CTRL_COMMAND:
|
||||
case INP_CTRL_READ_BUTTONS:
|
||||
case INP_CTRL_READ_X:
|
||||
case INP_CTRL_READ_Y:
|
||||
dev->command_val = val & 0x07;
|
||||
break;
|
||||
default:
|
||||
bm_log("ERROR: Unsupported command written to port 0x%04x (value = 0x%02x)\n", port, val);
|
||||
}
|
||||
break;
|
||||
case INP_PORT_DATA:
|
||||
picintc(1 << dev->irq);
|
||||
switch(dev->command_val) {
|
||||
case INP_CTRL_COMMAND:
|
||||
dev->hold = (val & INP_HOLD_COUNTER) > 0;
|
||||
|
||||
dev->interrupts = (val & INP_ENABLE_TIMER_IRQ) > 0;
|
||||
dev->data_int = (val & INP_ENABLE_DATA_IRQ) > 0;
|
||||
|
||||
switch(val & INP_PERIOD_MASK) {
|
||||
case 0:
|
||||
dev->period = 0.0;
|
||||
dev->timer_enabled = 0;
|
||||
break;
|
||||
case 1:
|
||||
dev->period = 1000000.0 / 30.0;
|
||||
dev->timer_enabled = (val & INP_ENABLE_TIMER_IRQ) ? *TIMER_ALWAYS_ENABLED : 0;
|
||||
break;
|
||||
case 2:
|
||||
dev->period = 1000000.0 / 50.0;
|
||||
dev->timer_enabled = (val & INP_ENABLE_TIMER_IRQ) ? *TIMER_ALWAYS_ENABLED : 0;
|
||||
break;
|
||||
case 3:
|
||||
dev->period = 1000000.0 / 100.0;
|
||||
dev->timer_enabled = (val & INP_ENABLE_TIMER_IRQ) ? *TIMER_ALWAYS_ENABLED : 0;
|
||||
break;
|
||||
case 4:
|
||||
dev->period = 1000000.0 / 200.0;
|
||||
dev->timer_enabled = (val & INP_ENABLE_TIMER_IRQ) ? *TIMER_ALWAYS_ENABLED : 0;
|
||||
break;
|
||||
case 6:
|
||||
if (val & INP_ENABLE_TIMER_IRQ)
|
||||
picint(1 << dev->irq);
|
||||
dev->control_val &= INP_PERIOD_MASK;
|
||||
dev->control_val |= (val & ~INP_PERIOD_MASK);
|
||||
return;
|
||||
default:
|
||||
bm_log("ERROR: Unsupported period written to port 0x%04x (value = 0x%02x)\n", port, val);
|
||||
}
|
||||
|
||||
dev->control_val = val;
|
||||
|
||||
break;
|
||||
default:
|
||||
bm_log("ERROR: Unsupported write to port 0x%04x (value = 0x%02x)\n", port, val);
|
||||
}
|
||||
break;
|
||||
case INP_PORT_SIGNATURE:
|
||||
case INP_PORT_CONFIG:
|
||||
bm_log("ERROR: Unsupported write to port 0x%04x (value = 0x%02x)\n", port, val);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
switch (port & 0x03) {
|
||||
case BUSM_PORT_CONTROL:
|
||||
dev->control_val = val | 0x0F;
|
||||
|
||||
dev->interrupts = (val & DISABLE_IRQ) == 0;
|
||||
dev->hold = (val & HOLD_COUNTER) > 0;
|
||||
|
||||
picintc(1 << dev->irq);
|
||||
|
||||
break;
|
||||
case BUSM_PORT_CONFIG:
|
||||
dev->config_val = val;
|
||||
break;
|
||||
case BUSM_PORT_SIGNATURE:
|
||||
dev->sig_val = val;
|
||||
break;
|
||||
case BUSM_PORT_DATA:
|
||||
bm_log("ERROR: Unsupported write to port 0x%04x (value = 0x%02x)\n", port, val);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* The emulator calls us with an update on the host mouse device. */
|
||||
static int
|
||||
bm_poll(int x, int y, int z, int b, void *priv)
|
||||
{
|
||||
mouse_t *dev = (mouse_t *)priv;
|
||||
uint8_t shift = 0xff;
|
||||
|
||||
if (dev->type == MOUSE_TYPE_INPORT)
|
||||
shift = 0x07;
|
||||
|
||||
if (!x && !y && !((b ^ dev->mouse_buttons_last) & shift)/* && (dev->type == MOUSE_TYPE_INPORT)*/)
|
||||
return(1); /* State has not changed, do nothing. */
|
||||
|
||||
/* change button staste MRL to LMR */
|
||||
dev->mouse_buttons = (uint8_t) (((b & 1) << 2) | ((b & 2) >> 1));
|
||||
if (dev->bn == 3)
|
||||
dev->mouse_buttons |= ((b & 4) >> 1);
|
||||
|
||||
if (dev->type == MOUSE_TYPE_INPORT) {
|
||||
/* InPort mouse. */
|
||||
|
||||
/* If the mouse has moved, set bit 6. */
|
||||
if (x || y)
|
||||
dev->mouse_buttons |= 0x40;
|
||||
|
||||
/* Set bits 3-5 according to button state changes. */
|
||||
if ((b ^ dev->mouse_buttons_last) & (1 << 0))
|
||||
dev->mouse_buttons |= (1 << 5);
|
||||
if ((b ^ dev->mouse_buttons_last) & (1 << 4) && (dev->bn == 3))
|
||||
dev->mouse_buttons |= (1 << 4);
|
||||
if ((b ^ dev->mouse_buttons_last) & (1 << 2))
|
||||
dev->mouse_buttons |= (1 << 3);
|
||||
}
|
||||
|
||||
dev->mouse_buttons_last = b;
|
||||
|
||||
/* Clamp x and y to between -128 and 127 (int8_t range). */
|
||||
if (x > 127) x = 127;
|
||||
if (x < -128) x = -128;
|
||||
|
||||
if (y > 127) y = 127;
|
||||
if (y < -128) y = -128;
|
||||
|
||||
if (dev->timer_enabled) { /* Timer interrupt mode. */
|
||||
/* Update delayed coordinates. */
|
||||
dev->mouse_delayed_dx += x;
|
||||
dev->mouse_delayed_dy += y;
|
||||
} else { /* Data interrupt mode. */
|
||||
/* If the counters are not frozen, update them. */
|
||||
if (!dev->hold) {
|
||||
dev->current_x = (int8_t) x;
|
||||
dev->current_y = (int8_t) y;
|
||||
|
||||
dev->current_b = dev->mouse_buttons;
|
||||
}
|
||||
|
||||
/* Send interrupt. */
|
||||
if (dev->data_int) {
|
||||
picintc(1 << dev->irq);
|
||||
picint(1 << dev->irq);
|
||||
bm_log("DEBUG: Data Interrupt Fired...\n");
|
||||
}
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
bm_update_data(mouse_t *dev)
|
||||
{
|
||||
int delta_x, delta_y;
|
||||
|
||||
if (dev->mouse_delayed_dx > 127) {
|
||||
delta_x = 127;
|
||||
dev->mouse_delayed_dx -= 127;
|
||||
} else if (dev->mouse_delayed_dx < -128) {
|
||||
delta_x = -128;
|
||||
dev->mouse_delayed_dx += 128;
|
||||
} else {
|
||||
delta_x = dev->mouse_delayed_dx;
|
||||
dev->mouse_delayed_dx = 0;
|
||||
}
|
||||
|
||||
if (dev->mouse_delayed_dy > 127) {
|
||||
delta_y = 127;
|
||||
dev->mouse_delayed_dy -= 127;
|
||||
} else if (dev->mouse_delayed_dy < -128) {
|
||||
delta_y = -128;
|
||||
dev->mouse_delayed_dy += 128;
|
||||
} else {
|
||||
delta_y = dev->mouse_delayed_dy;
|
||||
dev->mouse_delayed_dy = 0;
|
||||
}
|
||||
|
||||
if (!dev->hold) {
|
||||
dev->current_x = (uint8_t) delta_x;
|
||||
dev->current_y = (uint8_t) delta_y;
|
||||
dev->current_b = dev->mouse_buttons;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Called at 30hz */
|
||||
static void
|
||||
bm_timer(void *priv)
|
||||
{
|
||||
mouse_t *dev = (mouse_t *)priv;
|
||||
|
||||
if (dev->type == MOUSE_TYPE_INPORT)
|
||||
dev->timer = ((int64_t) dev->period) * TIMER_USEC;
|
||||
else
|
||||
dev->timer = BUSM_PERIOD;
|
||||
|
||||
if (dev->interrupts) {
|
||||
picintc(1 << dev->irq);
|
||||
picint(1 << dev->irq);
|
||||
bm_log("DEBUG: Timer Interrupt Fired...\n");
|
||||
}
|
||||
|
||||
bm_update_data(dev);
|
||||
}
|
||||
|
||||
|
||||
/* Release all resources held by the device. */
|
||||
static void
|
||||
bm_close(void *priv)
|
||||
{
|
||||
mouse_t *dev = (mouse_t *)priv;
|
||||
|
||||
if (dev)
|
||||
free(dev);
|
||||
}
|
||||
|
||||
|
||||
/* Initialize the device for use by the user. */
|
||||
static void *
|
||||
bm_init(const device_t *info)
|
||||
{
|
||||
mouse_t *dev;
|
||||
|
||||
dev = (mouse_t *)malloc(sizeof(mouse_t));
|
||||
memset(dev, 0x00, sizeof(mouse_t));
|
||||
|
||||
dev->type = info->local;
|
||||
dev->model = device_get_config_int("model");
|
||||
dev->base = device_get_config_hex16("base");
|
||||
dev->irq = device_get_config_int("irq");
|
||||
dev->bn = device_get_config_int("buttons");
|
||||
mouse_set_buttons(dev->bn);
|
||||
|
||||
io_sethandler(dev->base, 4,
|
||||
bm_read, NULL, NULL, bm_write, NULL, NULL, dev);
|
||||
|
||||
dev->mouse_delayed_dx = 0;
|
||||
dev->mouse_delayed_dy = 0;
|
||||
dev->mouse_buttons = 0;
|
||||
dev->current_x =
|
||||
dev->current_y =
|
||||
dev->current_b = 0;
|
||||
|
||||
if (dev->type == MOUSE_TYPE_INPORT) {
|
||||
dev->control_val = 0; /* the control port value */
|
||||
dev->mouse_buttons_last = 0;
|
||||
dev->period = 0.0; /* 30 Hz default */
|
||||
dev->timer = 0LL;
|
||||
dev->timer_enabled = 0;
|
||||
} else {
|
||||
dev->control_val = 0x0f; /* the control port value */
|
||||
dev->config_val = 0x0e; /* the config port value */
|
||||
dev->sig_val = 0; /* the signature port value */
|
||||
dev->timer = BUSM_PERIOD;
|
||||
dev->timer_enabled = *TIMER_ALWAYS_ENABLED;
|
||||
dev->interrupts = 1;
|
||||
}
|
||||
dev->data_int = 0;
|
||||
dev->interrupts = 0; /* timer interrupts off */
|
||||
dev->command_val = 0; /* command byte */
|
||||
dev->toggle_counter = 0; /* signature byte / IRQ bit toggle */
|
||||
dev->hold = 0; /* counter freeze */
|
||||
|
||||
timer_add(bm_timer, &dev->timer, &dev->timer_enabled, dev);
|
||||
|
||||
if (dev->type == MOUSE_TYPE_INPORT)
|
||||
bm_log("MS Inport BusMouse initialized\n");
|
||||
else
|
||||
bm_log("Standard MS/Logitech BusMouse initialized\n");
|
||||
|
||||
return dev;
|
||||
}
|
||||
|
||||
|
||||
static const device_config_t bm_config[] = {
|
||||
{
|
||||
"base", "Address", CONFIG_HEX16, "", 0x23c,
|
||||
{
|
||||
{
|
||||
"0x230", 0x230
|
||||
},
|
||||
{
|
||||
"0x234", 0x234
|
||||
},
|
||||
{
|
||||
"0x238", 0x238
|
||||
},
|
||||
{
|
||||
"0x23C", 0x23c
|
||||
},
|
||||
{
|
||||
""
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"irq", "IRQ", CONFIG_SELECTION, "", 5, {
|
||||
{
|
||||
"IRQ 2", 2
|
||||
},
|
||||
{
|
||||
"IRQ 3", 3
|
||||
},
|
||||
{
|
||||
"IRQ 4", 4
|
||||
},
|
||||
{
|
||||
"IRQ 5", 5
|
||||
},
|
||||
{
|
||||
""
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"buttons", "Buttons", CONFIG_SELECTION, "", 2, {
|
||||
{
|
||||
"Two", 2
|
||||
},
|
||||
{
|
||||
"Three", 3
|
||||
},
|
||||
{
|
||||
""
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"model", "Model", CONFIG_SELECTION, "", 0, {
|
||||
{
|
||||
"Old", 0
|
||||
},
|
||||
{
|
||||
"New", 1
|
||||
},
|
||||
{
|
||||
""
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"", "", -1
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
const device_t mouse_logibus_device = {
|
||||
"Logitech Bus Mouse",
|
||||
DEVICE_ISA,
|
||||
MOUSE_TYPE_LOGIBUS,
|
||||
bm_init, bm_close, NULL,
|
||||
bm_poll, NULL, NULL,
|
||||
bm_config
|
||||
};
|
||||
|
||||
const device_t mouse_msinport_device = {
|
||||
"Microsoft Bus Mouse (InPort)",
|
||||
DEVICE_ISA,
|
||||
MOUSE_TYPE_INPORT,
|
||||
bm_init, bm_close, NULL,
|
||||
bm_poll, NULL, NULL,
|
||||
bm_config
|
||||
};
|
||||
805
backup code/mouse_bus - Cópia (4).c
Normal file
805
backup code/mouse_bus - Cópia (4).c
Normal file
@@ -0,0 +1,805 @@
|
||||
/*
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
*
|
||||
* This file is part of the 86Box distribution.
|
||||
*
|
||||
* Implementation of Bus Mouse devices.
|
||||
*
|
||||
* These devices were made by both Microsoft and Logitech. At
|
||||
* first, Microsoft used the same protocol as Logitech, but did
|
||||
* switch to their new protocol for their InPort interface. So,
|
||||
* although alike enough to be handled in the same driver, they
|
||||
* are not the same.
|
||||
*
|
||||
* NOTES: Ported from Bochs with extensive modifications per testing
|
||||
* of the real hardware, testing of drivers, and the old code.
|
||||
*
|
||||
* Logitech Bus Mouse verified with:
|
||||
* Logitech LMouse.com 3.12
|
||||
* Logitech LMouse.com 3.30
|
||||
* Logitech LMouse.com 3.41
|
||||
* Logitech LMouse.com 3.42
|
||||
* Logitech LMouse.com 4.00
|
||||
* Logitech LMouse.com 5.00
|
||||
* Logitech LMouse.com 6.00
|
||||
* Logitech LMouse.com 6.02 Beta
|
||||
* Logitech LMouse.com 6.02
|
||||
* Logitech LMouse.com 6.12
|
||||
* Logitech LMouse.com 6.20
|
||||
* Logitech LMouse.com 6.23
|
||||
* Logitech LMouse.com 6.30
|
||||
* Logitech LMouse.com 6.31E
|
||||
* Logitech LMouse.com 6.34
|
||||
* Logitech Mouse.exe 6.40
|
||||
* Logitech Mouse.exe 6.41
|
||||
* Logitech Mouse.exe 6.44
|
||||
* Logitech Mouse.exe 6.46
|
||||
* Logitech Mouse.exe 6.50
|
||||
* Microsoft Mouse.com 2.00
|
||||
* Microsoft Mouse.sys 3.00
|
||||
* Microsoft Windows 1.00 DR5
|
||||
* Microsoft Windows 3.10.026
|
||||
* Microsoft Windows NT 3.1
|
||||
* Microsoft Windows 95
|
||||
*
|
||||
* InPort verified with:
|
||||
* Logitech LMouse.com 6.12
|
||||
* Logitech LMouse.com 6.41
|
||||
* Microsoft Windows NT 3.1
|
||||
* Microsoft Windows 98 SE
|
||||
*
|
||||
* Version: @(#)mouse_bus.c 1.0.0 2018/05/23
|
||||
*
|
||||
* Authors: Miran Grca, <mgrca8@gmail.com>
|
||||
* Fred N. van Kempen, <decwiz@yahoo.com>
|
||||
*
|
||||
* Copyright 200?-2018 Bochs.
|
||||
* Copyright 2017,2018 Miran Grca.
|
||||
* Copyright 1989-2018 Fred N. van Kempen.
|
||||
*/
|
||||
#include <inttypes.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <wchar.h>
|
||||
#define HAVE_STDARG_H
|
||||
#include "86box.h"
|
||||
#include "config.h"
|
||||
#include "io.h"
|
||||
#include "pic.h"
|
||||
#include "timer.h"
|
||||
#include "device.h"
|
||||
#include "mouse.h"
|
||||
#if 1
|
||||
#include "random.h"
|
||||
#endif
|
||||
|
||||
#define IRQ_MASK ((1 << 5) >> dev->irq)
|
||||
|
||||
/* MS Inport Bus Mouse Adapter */
|
||||
#define INP_PORT_CONTROL 0x0000
|
||||
#define INP_PORT_DATA 0x0001
|
||||
#define INP_PORT_SIGNATURE 0x0002
|
||||
#define INP_PORT_CONFIG 0x0003
|
||||
|
||||
#define INP_CTRL_READ_BUTTONS 0x00
|
||||
#define INP_CTRL_READ_X 0x01
|
||||
#define INP_CTRL_READ_Y 0x02
|
||||
#define INP_CTRL_COMMAND 0x07
|
||||
#define INP_CTRL_RAISE_IRQ 0x16
|
||||
#define INP_CTRL_RESET 0x80
|
||||
|
||||
#define INP_HOLD_COUNTER (1 << 5)
|
||||
#define INP_ENABLE_TIMER_IRQ (1 << 4)
|
||||
#define INP_ENABLE_DATA_IRQ (1 << 3)
|
||||
#define INP_PERIOD_MASK 0x07
|
||||
|
||||
/* MS/Logictech Standard Bus Mouse Adapter */
|
||||
#define BUSM_PORT_DATA 0x0000
|
||||
#define BUSM_PORT_SIGNATURE 0x0001
|
||||
#define BUSM_PORT_CONTROL 0x0002
|
||||
#define BUSM_PORT_CONFIG 0x0003
|
||||
|
||||
#define HOLD_COUNTER (1 << 7)
|
||||
#define READ_X (0 << 6)
|
||||
#define READ_Y (1 << 6)
|
||||
#define READ_LOW (0 << 5)
|
||||
#define READ_HIGH (1 << 5)
|
||||
#define DISABLE_IRQ (1 << 4)
|
||||
|
||||
#define DEVICE_ACTIVE (1 << 7)
|
||||
|
||||
#define READ_X_LOW (READ_X | READ_LOW)
|
||||
#define READ_X_HIGH (READ_X | READ_HIGH)
|
||||
#define READ_Y_LOW (READ_Y | READ_LOW)
|
||||
#define READ_Y_HIGH (READ_Y | READ_HIGH)
|
||||
|
||||
#define FLAG_INPORT (1 << 0)
|
||||
#define FLAG_NEW (1 << 1)
|
||||
#define FLAG_ENABLED (1 << 2)
|
||||
#define FLAG_HOLD (1 << 3)
|
||||
#define FLAG_TIMER_INT (1 << 4)
|
||||
#define FLAG_DATA_INT (1 << 5)
|
||||
|
||||
static const double periods[4] = { 30.0, 50.0, 100.0, 200.0 };
|
||||
|
||||
|
||||
/* Our mouse device. */
|
||||
typedef struct mouse {
|
||||
int base, irq, bn, flags,
|
||||
mouse_delayed_dx, mouse_delayed_dy,
|
||||
mouse_buttons,
|
||||
current_x, current_y,
|
||||
current_b,
|
||||
control_val, mouse_buttons_last,
|
||||
config_val, sig_val,
|
||||
command_val, toggle_counter;
|
||||
|
||||
double period;
|
||||
|
||||
int64_t timer_enabled, timer; /* mouse event timer */
|
||||
} mouse_t;
|
||||
|
||||
|
||||
#ifdef ENABLE_MOUSE_BUS_LOG
|
||||
int bm_do_log = ENABLE_MOUSE_BUS_LOG;
|
||||
#endif
|
||||
|
||||
|
||||
static void
|
||||
bm_log(const char *format, ...)
|
||||
{
|
||||
#ifdef ENABLE_MOUSE_BUS_LOG
|
||||
va_list ap;
|
||||
|
||||
if (bm_do_log) {
|
||||
va_start(ap, format);
|
||||
pclog_ex(format, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/* Handle a READ operation from one of our registers. */
|
||||
static uint8_t
|
||||
lt_read(uint16_t port, void *priv)
|
||||
{
|
||||
mouse_t *dev = (mouse_t *)priv;
|
||||
uint8_t value;
|
||||
|
||||
switch (port & 0x03) {
|
||||
case BUSM_PORT_DATA:
|
||||
/* Testing and another source confirm that the buttons are
|
||||
*ALWAYS* present, so I'm going to change this a bit. */
|
||||
switch (dev->control_val & 0x60) {
|
||||
case READ_X_LOW:
|
||||
value = dev->current_x & 0x0F;
|
||||
break;
|
||||
case READ_X_HIGH:
|
||||
value = (dev->current_x >> 4) & 0x0F;
|
||||
break;
|
||||
case READ_Y_LOW:
|
||||
value = dev->current_y & 0x0F;
|
||||
break;
|
||||
case READ_Y_HIGH:
|
||||
value = (dev->current_y >> 4) & 0x0F;
|
||||
break;
|
||||
default:
|
||||
bm_log("ERROR: Reading data port in unsupported mode 0x%02x\n", dev->control_val);
|
||||
}
|
||||
value |= ((dev->current_b ^ 7) << 5);
|
||||
break;
|
||||
case BUSM_PORT_SIGNATURE:
|
||||
value = dev->sig_val;
|
||||
break;
|
||||
case BUSM_PORT_CONTROL:
|
||||
value = dev->control_val;
|
||||
dev->control_val |= 0x0F;
|
||||
|
||||
/* If the conditions are right, simulate the flakiness of the correct IRQ bit. */
|
||||
if (!(dev->flags & FLAG_NEW) || (dev->flags & FLAG_TIMER_INT))
|
||||
dev->control_val = (dev->control_val & ~IRQ_MASK) | (random_generate() & IRQ_MASK);
|
||||
break;
|
||||
case BUSM_PORT_CONFIG:
|
||||
/* Read from config port returns control_val in the upper 4 bits when enabled,
|
||||
possibly solid interrupt readout in the lower 4 bits, 0xff when not (at power-up). */
|
||||
if (dev->flags & FLAG_ENABLED)
|
||||
return (dev->control_val | 0x0F) & ~IRQ_MASK;
|
||||
else
|
||||
return 0xff;
|
||||
break;
|
||||
}
|
||||
|
||||
bm_log("DEBUG: read from address 0x%04x, value = 0x%02x\n", port, value);
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
static uint8_t
|
||||
ms_read(uint16_t port, void *priv)
|
||||
{
|
||||
mouse_t *dev = (mouse_t *)priv;
|
||||
uint8_t value;
|
||||
|
||||
switch (port & 0x03) {
|
||||
case INP_PORT_CONTROL:
|
||||
value = dev->control_val;
|
||||
break;
|
||||
case INP_PORT_DATA:
|
||||
switch (dev->command_val) {
|
||||
case INP_CTRL_READ_BUTTONS:
|
||||
value = dev->current_b | 0x80;
|
||||
break;
|
||||
case INP_CTRL_READ_X:
|
||||
value = dev->current_x;
|
||||
break;
|
||||
case INP_CTRL_READ_Y:
|
||||
value = dev->current_y;
|
||||
break;
|
||||
case INP_CTRL_COMMAND:
|
||||
value = dev->control_val;
|
||||
break;
|
||||
default:
|
||||
bm_log("ERROR: Reading data port in unsupported mode 0x%02x\n", dev->control_val);
|
||||
}
|
||||
break;
|
||||
case INP_PORT_SIGNATURE:
|
||||
if (dev->toggle_counter)
|
||||
value = 0x12;
|
||||
else
|
||||
value = 0xDE;
|
||||
dev->toggle_counter ^= 1;
|
||||
break;
|
||||
case INP_PORT_CONFIG:
|
||||
bm_log("ERROR: Unsupported read from port 0x%04x\n", port);
|
||||
break;
|
||||
}
|
||||
|
||||
bm_log("DEBUG: read from address 0x%04x, value = 0x%02x\n", port, value);
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
/* Handle a WRITE operation to one of our registers. */
|
||||
static void
|
||||
lt_write(uint16_t port, uint8_t val, void *priv)
|
||||
{
|
||||
mouse_t *dev = (mouse_t *)priv;
|
||||
|
||||
bm_log("DEBUG: write to address 0x%04x, value = 0x%02x\n", port, val);
|
||||
|
||||
switch (port & 0x03) {
|
||||
case BUSM_PORT_DATA:
|
||||
bm_log("ERROR: Unsupported write to port 0x%04x (value = 0x%02x)\n", port, val);
|
||||
break;
|
||||
case BUSM_PORT_SIGNATURE:
|
||||
dev->sig_val = val;
|
||||
break;
|
||||
case BUSM_PORT_CONTROL:
|
||||
dev->control_val = val | 0x0F;
|
||||
|
||||
if (!(val & DISABLE_IRQ))
|
||||
dev->flags |= FLAG_TIMER_INT;
|
||||
else
|
||||
dev->flags &= ~FLAG_TIMER_INT;
|
||||
|
||||
if (val & HOLD_COUNTER)
|
||||
dev->flags |= FLAG_HOLD;
|
||||
else
|
||||
dev->flags &= ~FLAG_HOLD;
|
||||
|
||||
picintc(1 << dev->irq);
|
||||
|
||||
break;
|
||||
case BUSM_PORT_CONFIG:
|
||||
/*
|
||||
* The original Logitech design was based on using a
|
||||
* 8255 parallel I/O chip. This chip has to be set up
|
||||
* for proper operation, and this configuration data
|
||||
* is what is programmed into this register.
|
||||
*
|
||||
* A snippet of code found in the FreeBSD kernel source
|
||||
* explains the value:
|
||||
*
|
||||
* D7 = Mode set flag (1 = active)
|
||||
* D6,D5 = Mode selection (port A)
|
||||
* 00 = Mode 0 = Basic I/O
|
||||
* 01 = Mode 1 = Strobed I/O
|
||||
* 10 = Mode 2 = Bi-dir bus
|
||||
* D4 = Port A direction (1 = input)
|
||||
* D3 = Port C (upper 4 bits) direction. (1 = input)
|
||||
* D2 = Mode selection (port B & C)
|
||||
* 0 = Mode 0 = Basic I/O
|
||||
* 1 = Mode 1 = Strobed I/O
|
||||
* D1 = Port B direction (1 = input)
|
||||
* D0 = Port C (lower 4 bits) direction. (1 = input)
|
||||
*
|
||||
* So 91 means Basic I/O on all 3 ports, Port A is an input
|
||||
* port, B is an output port, C is split with upper 4 bits
|
||||
* being an output port and lower 4 bits an input port, and
|
||||
* enable the sucker. Courtesy Intel 8255 databook. Lars
|
||||
*/
|
||||
dev->config_val = val;
|
||||
if (val & DEVICE_ACTIVE) {
|
||||
dev->flags |= FLAG_ENABLED;
|
||||
dev->control_val = 0x0F & ~IRQ_MASK;
|
||||
} else
|
||||
dev->flags &= ~FLAG_ENABLED;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Handle a WRITE operation to one of our registers. */
|
||||
static void
|
||||
ms_write(uint16_t port, uint8_t val, void *priv)
|
||||
{
|
||||
mouse_t *dev = (mouse_t *)priv;
|
||||
|
||||
bm_log("DEBUG: write to address 0x%04x, value = 0x%02x\n", port, val);
|
||||
|
||||
switch (port & 0x03) {
|
||||
case INP_PORT_CONTROL:
|
||||
/* Bit 7 is reset. */
|
||||
if (val & INP_CTRL_RESET)
|
||||
dev->control_val = 0;
|
||||
|
||||
/* Bits 0-2 are the internal register index. */
|
||||
switch(val & 0x07) {
|
||||
case INP_CTRL_COMMAND:
|
||||
case INP_CTRL_READ_BUTTONS:
|
||||
case INP_CTRL_READ_X:
|
||||
case INP_CTRL_READ_Y:
|
||||
dev->command_val = val & 0x07;
|
||||
break;
|
||||
default:
|
||||
bm_log("ERROR: Unsupported command written to port 0x%04x (value = 0x%02x)\n", port, val);
|
||||
}
|
||||
break;
|
||||
case INP_PORT_DATA:
|
||||
picintc(1 << dev->irq);
|
||||
switch(dev->command_val) {
|
||||
case INP_CTRL_COMMAND:
|
||||
if (val & INP_HOLD_COUNTER)
|
||||
dev->flags |= FLAG_HOLD;
|
||||
else
|
||||
dev->flags &= ~FLAG_HOLD;
|
||||
|
||||
if (val & INP_ENABLE_TIMER_IRQ)
|
||||
dev->flags |= FLAG_TIMER_INT;
|
||||
else
|
||||
dev->flags &= ~FLAG_TIMER_INT;
|
||||
|
||||
if (val & INP_ENABLE_DATA_IRQ)
|
||||
dev->flags |= FLAG_DATA_INT;
|
||||
else
|
||||
dev->flags &= ~FLAG_DATA_INT;
|
||||
|
||||
switch(val & INP_PERIOD_MASK) {
|
||||
case 0:
|
||||
dev->period = 0.0;
|
||||
dev->timer = 0LL;
|
||||
dev->timer_enabled = 0LL;
|
||||
break;
|
||||
|
||||
case 1:
|
||||
case 2:
|
||||
case 3:
|
||||
case 4:
|
||||
dev->period = 1000000.0 / periods[(val & INP_PERIOD_MASK) - 1];
|
||||
dev->timer = ((int64_t) dev->period) * TIMER_USEC;
|
||||
dev->timer_enabled = (val & INP_ENABLE_TIMER_IRQ) ? 1LL : 0LL;
|
||||
bm_log("DEBUG: Timer is now %sabled at period %i\n", (val & INP_ENABLE_TIMER_IRQ) ? "en" : "dis", (int32_t) dev->period);
|
||||
break;
|
||||
|
||||
case 6:
|
||||
if (val & INP_ENABLE_TIMER_IRQ)
|
||||
picint(1 << dev->irq);
|
||||
dev->control_val &= INP_PERIOD_MASK;
|
||||
dev->control_val |= (val & ~INP_PERIOD_MASK);
|
||||
return;
|
||||
default:
|
||||
bm_log("ERROR: Unsupported period written to port 0x%04x (value = 0x%02x)\n", port, val);
|
||||
}
|
||||
|
||||
dev->control_val = val;
|
||||
|
||||
break;
|
||||
default:
|
||||
bm_log("ERROR: Unsupported write to port 0x%04x (value = 0x%02x)\n", port, val);
|
||||
}
|
||||
break;
|
||||
case INP_PORT_SIGNATURE:
|
||||
case INP_PORT_CONFIG:
|
||||
bm_log("ERROR: Unsupported write to port 0x%04x (value = 0x%02x)\n", port, val);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* The emulator calls us with an update on the host mouse device. */
|
||||
static int
|
||||
bm_poll(int x, int y, int z, int b, void *priv)
|
||||
{
|
||||
mouse_t *dev = (mouse_t *)priv;
|
||||
int xor;
|
||||
|
||||
if (!(dev->flags & FLAG_ENABLED))
|
||||
return(1); /* Mouse is disabled, do nothing. */
|
||||
|
||||
if (!x && !y && !((b ^ dev->mouse_buttons_last) & 0x07)) {
|
||||
dev->mouse_buttons_last = b;
|
||||
return(1); /* State has not changed, do nothing. */
|
||||
}
|
||||
|
||||
/* Converts button states from MRL to LMR. */
|
||||
dev->mouse_buttons = (uint8_t) (((b & 1) << 2) | ((b & 2) >> 1));
|
||||
if (dev->bn == 3)
|
||||
dev->mouse_buttons |= ((b & 4) >> 1);
|
||||
|
||||
if ((dev->flags & FLAG_INPORT) && !dev->timer_enabled) {
|
||||
/* This is an InPort mouse in data interrupt mode,
|
||||
so update bits 6-3 here. */
|
||||
|
||||
/* If the mouse has moved, set bit 6. */
|
||||
if (x || y)
|
||||
dev->mouse_buttons |= 0x40;
|
||||
|
||||
/* Set bits 3-5 according to button state changes. */
|
||||
xor = ((dev->current_b ^ dev->mouse_buttons) & 0x07) << 3;
|
||||
dev->mouse_buttons |= xor;
|
||||
}
|
||||
|
||||
dev->mouse_buttons_last = b;
|
||||
|
||||
/* Clamp x and y to between -128 and 127 (int8_t range). */
|
||||
if (x > 127) x = 127;
|
||||
if (x < -128) x = -128;
|
||||
|
||||
if (y > 127) y = 127;
|
||||
if (y < -128) y = -128;
|
||||
|
||||
if (dev->timer_enabled) {
|
||||
/* Update delayed coordinates. */
|
||||
dev->mouse_delayed_dx += x;
|
||||
dev->mouse_delayed_dy += y;
|
||||
} else {
|
||||
/* If the counters are not frozen, update them. */
|
||||
if (!(dev->flags & FLAG_HOLD)) {
|
||||
dev->current_x = (int8_t) x;
|
||||
dev->current_y = (int8_t) y;
|
||||
|
||||
dev->current_b = dev->mouse_buttons;
|
||||
}
|
||||
|
||||
/* Send interrupt. */
|
||||
if (dev->flags & FLAG_DATA_INT) {
|
||||
picint(1 << dev->irq);
|
||||
bm_log("DEBUG: Data Interrupt Fired...\n");
|
||||
}
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
/* The timer calls us on every tick if the mouse is in timer mode
|
||||
(InPort mouse is so configured, MS/Logitech Bus mouse always). */
|
||||
static void
|
||||
bm_update_data(mouse_t *dev)
|
||||
{
|
||||
int delta_x, delta_y;
|
||||
int xor;
|
||||
|
||||
/* Update the deltas and the delays. */
|
||||
if (dev->mouse_delayed_dx > 127) {
|
||||
delta_x = 127;
|
||||
dev->mouse_delayed_dx -= 127;
|
||||
} else if (dev->mouse_delayed_dx < -128) {
|
||||
delta_x = -128;
|
||||
dev->mouse_delayed_dx += 128;
|
||||
} else {
|
||||
delta_x = dev->mouse_delayed_dx;
|
||||
dev->mouse_delayed_dx = 0;
|
||||
}
|
||||
|
||||
if (dev->mouse_delayed_dy > 127) {
|
||||
delta_y = 127;
|
||||
dev->mouse_delayed_dy -= 127;
|
||||
} else if (dev->mouse_delayed_dy < -128) {
|
||||
delta_y = -128;
|
||||
dev->mouse_delayed_dy += 128;
|
||||
} else {
|
||||
delta_y = dev->mouse_delayed_dy;
|
||||
dev->mouse_delayed_dy = 0;
|
||||
}
|
||||
|
||||
/* If the counters are not frozen, update them. */
|
||||
if (!(dev->flags & FLAG_HOLD)) {
|
||||
dev->current_x = (uint8_t) delta_x;
|
||||
dev->current_y = (uint8_t) delta_y;
|
||||
}
|
||||
|
||||
if (dev->flags & FLAG_INPORT) {
|
||||
/* This is an InPort mouse in timer mode, so update current_b always,
|
||||
and update bits 6-3 (mouse moved and button state changed) here. */
|
||||
xor = ((dev->current_b ^ dev->mouse_buttons) & 0x07) << 3;
|
||||
dev->current_b = (dev->mouse_buttons & 0x87) | xor;
|
||||
if (delta_x || delta_y)
|
||||
dev->current_b |= 0x40;
|
||||
} else if (!(dev->flags & FLAG_HOLD)) {
|
||||
/* This is a MS/Logitech Bus Mouse, so only update current_b if the
|
||||
counters are frozen. */
|
||||
dev->current_b = dev->mouse_buttons;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Called at the configured period (InPort mouse) or 45 times per second (MS/Logitech Bus mouse). */
|
||||
static void
|
||||
bm_timer(void *priv)
|
||||
{
|
||||
mouse_t *dev = (mouse_t *)priv;
|
||||
|
||||
bm_log("DEBUG: Timer Tick (flags=%08X)...\n", dev->flags);
|
||||
|
||||
/* The period is configured either via emulator settings (for MS/Logitech Bus mouse)
|
||||
or via software (for InPort mouse). */
|
||||
dev->timer += ((int64_t) dev->period) * TIMER_USEC;
|
||||
|
||||
if (dev->flags & FLAG_TIMER_INT) {
|
||||
picint(1 << dev->irq);
|
||||
bm_log("DEBUG: Timer Interrupt Fired...\n");
|
||||
}
|
||||
|
||||
bm_update_data(dev);
|
||||
}
|
||||
|
||||
|
||||
/* Release all resources held by the device. */
|
||||
static void
|
||||
bm_close(void *priv)
|
||||
{
|
||||
mouse_t *dev = (mouse_t *)priv;
|
||||
|
||||
if (dev)
|
||||
free(dev);
|
||||
}
|
||||
|
||||
|
||||
/* Initialize the device for use by the user. */
|
||||
static void *
|
||||
bm_init(const device_t *info)
|
||||
{
|
||||
mouse_t *dev;
|
||||
|
||||
dev = (mouse_t *)malloc(sizeof(mouse_t));
|
||||
memset(dev, 0x00, sizeof(mouse_t));
|
||||
|
||||
if (info->local == MOUSE_TYPE_INPORT)
|
||||
dev->flags = FLAG_INPORT;
|
||||
else
|
||||
dev->flags = 0;
|
||||
|
||||
if (device_get_config_int("model"))
|
||||
dev->flags |= FLAG_NEW;
|
||||
|
||||
dev->base = device_get_config_hex16("base");
|
||||
dev->irq = device_get_config_int("irq");
|
||||
dev->bn = device_get_config_int("buttons");
|
||||
mouse_set_buttons(dev->bn);
|
||||
|
||||
dev->mouse_delayed_dx = 0;
|
||||
dev->mouse_delayed_dy = 0;
|
||||
dev->mouse_buttons = 0;
|
||||
dev->mouse_buttons_last = 0;
|
||||
dev->sig_val = 0; /* the signature port value */
|
||||
dev->current_x =
|
||||
dev->current_y =
|
||||
dev->current_b = 0;
|
||||
dev->command_val = 0; /* command byte */
|
||||
dev->toggle_counter = 0; /* signature byte / IRQ bit toggle */
|
||||
|
||||
if (dev->flags & FLAG_INPORT) {
|
||||
dev->control_val = 0; /* the control port value */
|
||||
dev->timer = 0LL;
|
||||
dev->timer_enabled = 0;
|
||||
dev->flags |= FLAG_ENABLED;
|
||||
dev->period = 0.0;
|
||||
|
||||
io_sethandler(dev->base, 4,
|
||||
ms_read, NULL, NULL, ms_write, NULL, NULL, dev);
|
||||
} else {
|
||||
dev->control_val = 0x0f; /* the control port value */
|
||||
dev->config_val = 0x0e; /* the config port value */
|
||||
dev->period = 1000000.0 / ((double) device_get_config_int("hz"));
|
||||
dev->timer = ((int64_t) dev->period) * TIMER_USEC;
|
||||
dev->timer_enabled = 1LL;
|
||||
dev->flags |= FLAG_TIMER_INT;
|
||||
|
||||
io_sethandler(dev->base, 4,
|
||||
lt_read, NULL, NULL, lt_write, NULL, NULL, dev);
|
||||
}
|
||||
|
||||
timer_add(bm_timer, &dev->timer, &dev->timer_enabled, dev);
|
||||
|
||||
if (dev->flags & FLAG_INPORT)
|
||||
bm_log("MS Inport BusMouse initialized\n");
|
||||
else
|
||||
bm_log("Standard MS/Logitech BusMouse initialized\n");
|
||||
|
||||
return dev;
|
||||
}
|
||||
|
||||
|
||||
static const device_config_t lt_config[] = {
|
||||
{
|
||||
"base", "Address", CONFIG_HEX16, "", 0x23c,
|
||||
{
|
||||
{
|
||||
"0x230", 0x230
|
||||
},
|
||||
{
|
||||
"0x234", 0x234
|
||||
},
|
||||
{
|
||||
"0x238", 0x238
|
||||
},
|
||||
{
|
||||
"0x23C", 0x23c
|
||||
},
|
||||
{
|
||||
""
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"irq", "IRQ", CONFIG_SELECTION, "", 5, {
|
||||
{
|
||||
"IRQ 2", 2
|
||||
},
|
||||
{
|
||||
"IRQ 3", 3
|
||||
},
|
||||
{
|
||||
"IRQ 4", 4
|
||||
},
|
||||
{
|
||||
"IRQ 5", 5
|
||||
},
|
||||
{
|
||||
""
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"hz", "Hz", CONFIG_SELECTION, "", 30, {
|
||||
{
|
||||
"30 Hz (JMP2 = 1)", 30
|
||||
},
|
||||
{
|
||||
"45 Hz (JMP2 not populated)", 45
|
||||
},
|
||||
{
|
||||
"60 Hz (JMP 2 = 2)", 60
|
||||
},
|
||||
{
|
||||
""
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"buttons", "Buttons", CONFIG_SELECTION, "", 2, {
|
||||
{
|
||||
"Two", 2
|
||||
},
|
||||
{
|
||||
"Three", 3
|
||||
},
|
||||
{
|
||||
""
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"model", "Model", CONFIG_SELECTION, "", 0, {
|
||||
{
|
||||
"Old", 0
|
||||
},
|
||||
{
|
||||
"New", 1
|
||||
},
|
||||
{
|
||||
""
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"", "", -1
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
static const device_config_t ms_config[] = {
|
||||
{
|
||||
"base", "Address", CONFIG_HEX16, "", 0x23c,
|
||||
{
|
||||
{
|
||||
"0x230", 0x230
|
||||
},
|
||||
{
|
||||
"0x234", 0x234
|
||||
},
|
||||
{
|
||||
"0x238", 0x238
|
||||
},
|
||||
{
|
||||
"0x23C", 0x23c
|
||||
},
|
||||
{
|
||||
""
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"irq", "IRQ", CONFIG_SELECTION, "", 5, {
|
||||
{
|
||||
"IRQ 2", 2
|
||||
},
|
||||
{
|
||||
"IRQ 3", 3
|
||||
},
|
||||
{
|
||||
"IRQ 4", 4
|
||||
},
|
||||
{
|
||||
"IRQ 5", 5
|
||||
},
|
||||
{
|
||||
""
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"buttons", "Buttons", CONFIG_SELECTION, "", 2, {
|
||||
{
|
||||
"Two", 2
|
||||
},
|
||||
{
|
||||
"Three", 3
|
||||
},
|
||||
{
|
||||
""
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"", "", -1
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
const device_t mouse_logibus_device = {
|
||||
"Logitech Bus Mouse",
|
||||
DEVICE_ISA,
|
||||
MOUSE_TYPE_LOGIBUS,
|
||||
bm_init, bm_close, NULL,
|
||||
bm_poll, NULL, NULL,
|
||||
lt_config
|
||||
};
|
||||
|
||||
const device_t mouse_msinport_device = {
|
||||
"Microsoft Bus Mouse (InPort)",
|
||||
DEVICE_ISA,
|
||||
MOUSE_TYPE_INPORT,
|
||||
bm_init, bm_close, NULL,
|
||||
bm_poll, NULL, NULL,
|
||||
ms_config
|
||||
};
|
||||
877
backup code/mouse_bus - Cópia 2.c
Normal file
877
backup code/mouse_bus - Cópia 2.c
Normal file
@@ -0,0 +1,877 @@
|
||||
/*
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
*
|
||||
* This file is part of the 86Box distribution.
|
||||
*
|
||||
* Implementation of Bus Mouse devices.
|
||||
*
|
||||
* These devices were made by both Microsoft and Logitech. At
|
||||
* first, Microsoft used the same protocol as Logitech, but did
|
||||
* switch to their new protocol for their InPort interface. So,
|
||||
* although alike enough to be handled in the same driver, they
|
||||
* are not the same.
|
||||
*
|
||||
* This code is based on my Minix driver for the Logitech(-mode)
|
||||
* interface. Although that driver blindly took IRQ5, the board
|
||||
* seems to be able to tell the driver what IRQ it is set for.
|
||||
* When testing on MS-DOS (6.22), the 'mouse.exe' driver did not
|
||||
* want to start, and only after disassembling it and inspecting
|
||||
* the code it was discovered that driver actually does use the
|
||||
* IRQ reporting feature. In a really, really weird way, too: it
|
||||
* sets up the board, and then reads the CTRL register which is
|
||||
* supposed to return that IRQ value. Depending on whether or
|
||||
* not the FREEZE bit is set, it has to return either the two's
|
||||
* complemented (negated) value, or (if clear) just the value.
|
||||
* The mouse.com driver reads both values 10,000 times, and
|
||||
* then makes up its mind. Maybe an effort to 'debounce' the
|
||||
* reading of the DIP switches? Oh-well.
|
||||
*
|
||||
* NOTES: Verified with:
|
||||
* AMI WinBIOS 486 (5A, no IRQ detect, OK, IRQ5 only)
|
||||
* Microsoft Mouse.com V2.00 (DOS V6.22, 5A, OK)
|
||||
* Microsoft Mouse.exe V9.1 (DOS V6.22, A5, OK)
|
||||
* Logitech LMouse.com V6.02 (DOS V6.22)
|
||||
* Logitech LMouse.com V6.43 (DOS V6.22)
|
||||
* Microsoft WfW V3.11 on DOS V6.22
|
||||
* GEOS V1.0 (OK, IRQ5 only)
|
||||
* GEOS V2.0 (OK, IRQ5 only)
|
||||
* Microsoft Windows 95 OSR2
|
||||
* Microsoft Windows 98 SE
|
||||
* Microsoft Windows NT 3.1
|
||||
* Microsoft Windows NT 3.51
|
||||
*
|
||||
* The polling frequency for InPort controllers has to
|
||||
* be changed to programmable. Microsoft uses 30Hz,
|
||||
* but ATIXL ports are programmable 30-200Hz.
|
||||
*
|
||||
* Based on an early driver for MINIX 1.5.
|
||||
*
|
||||
* Version: @(#)mouse_bus.c 1.0.37 2018/05/22
|
||||
*
|
||||
* Authors: Fred N. van Kempen, <decwiz@yahoo.com>
|
||||
*
|
||||
* Copyright 1989-2018 Fred N. van Kempen.
|
||||
*/
|
||||
#include <inttypes.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <wchar.h>
|
||||
#define HAVE_STDARG_H
|
||||
#include "86box.h"
|
||||
#include "config.h"
|
||||
#include "io.h"
|
||||
#include "pic.h"
|
||||
#include "timer.h"
|
||||
#include "device.h"
|
||||
#include "mouse.h"
|
||||
|
||||
|
||||
#define MOUSE_PORT 0x023c /* default */
|
||||
#define MOUSE_IRQ 5 /* default */
|
||||
#define MOUSE_BUTTONS 2 /* default */
|
||||
#define MOUSE_DEBUG 0
|
||||
|
||||
|
||||
/* Our mouse device. */
|
||||
typedef struct mouse {
|
||||
const char *name; /* name of this device */
|
||||
int8_t type; /* type of this device */
|
||||
uint16_t base; /* I/O base to use */
|
||||
int8_t irq; /* IRQ channel to use */
|
||||
uint16_t flags; /* device flags */
|
||||
|
||||
uint8_t r_magic, /* MAGIC register */
|
||||
r_ctrl, /* CONTROL register (WR) */
|
||||
r_conf, /* CONFIG register */
|
||||
r_cmd; /* (MS) current command */
|
||||
|
||||
uint8_t seq; /* general counter */
|
||||
|
||||
uint8_t but, /* current mouse status */
|
||||
but_last;
|
||||
uint8_t cur_but;
|
||||
int8_t x, y;
|
||||
int x_delay,
|
||||
y_delay;
|
||||
uint8_t irq_num;
|
||||
|
||||
int64_t timer; /* mouse event timer */
|
||||
|
||||
uint8_t (*read)(struct mouse *, uint16_t);
|
||||
void (*write)(struct mouse *, uint16_t, uint8_t);
|
||||
} mouse_t;
|
||||
#define FLAG_NEW 0x100 /* device is the newer variant */
|
||||
#define FLAG_INPORT 0x80 /* device is MS InPort */
|
||||
#define FLAG_3BTN 0x20 /* enable 3-button mode */
|
||||
#define FLAG_SCALED 0x10 /* enable delta scaling */
|
||||
#define FLAG_INTR 0x04 /* dev can send interrupts */
|
||||
#define FLAG_FROZEN 0x02 /* do not update counters */
|
||||
#define FLAG_ENABLED 0x01 /* dev is enabled for use */
|
||||
|
||||
|
||||
/* Definitions for Logitech. */
|
||||
#define LTMOUSE_DATA 0 /* DATA register */
|
||||
#define LTMOUSE_MAGIC 1 /* signature magic register */
|
||||
# define LTMAGIC_BYTE1 0xa5 /* most drivers use this */
|
||||
# define LTMAGIC_BYTE2 0x5a /* some drivers use this */
|
||||
#define LTMOUSE_CTRL 2 /* CTRL register */
|
||||
# define LTCTRL_FREEZE 0x80 /* do not sample when set */
|
||||
# define LTCTRL_RD_Y_HI 0x60
|
||||
# define LTCTRL_RD_Y_LO 0x40
|
||||
# define LTCTRL_RD_X_HI 0x20
|
||||
# define LTCTRL_RD_X_LO 0x00
|
||||
# define LTCTRL_RD_MASK 0x60
|
||||
# define LTCTRL_IDIS 0x10
|
||||
# define LTCTRL_IENB 0x00
|
||||
#define LTMOUSE_CONFIG 3 /* CONFIG register */
|
||||
|
||||
/* Definitions for Microsoft. */
|
||||
#define MSMOUSE_CTRL 0 /* CTRL register */
|
||||
# define MSCTRL_RESET 0x80 /* reset controller */
|
||||
# define MSCTRL_FREEZE 0x20 /* HOLD- freeze data */
|
||||
# define MSCTRL_IENB_A 0x08 /* ATIXL intr enable */
|
||||
# define MSCTRL_IENB_M 0x01 /* MS intr enable */
|
||||
# define MSCTRL_COMMAND 0x07
|
||||
# define MSCTRL_RD_Y 0x02
|
||||
# define MSCTRL_RD_X 0x01
|
||||
# define MSCTRL_RD_BUT 0x00
|
||||
#define MSMOUSE_DATA 1 /* DATA register */
|
||||
# define MSDATA_IRQ 0x16
|
||||
# define MSDATA_BASE 0x10 /* MS InPort: 30Hz */
|
||||
# define MSDATA_HZ30 0x01 /* ATIXL 30Hz */
|
||||
# define MSDATA_HZ50 0x02 /* ATIXL 50Hz */
|
||||
# define MSDATA_HZ100 0x03 /* ATIXL 100Hz */
|
||||
# define MSDATA_HZ200 0x04 /* ATIXL 200Hz */
|
||||
#define MSMOUSE_MAGIC 2 /* MAGIC register */
|
||||
# define MAGIC_MSBYTE1 0xde /* indicates MS InPort */
|
||||
# define MAGIC_MSBYTE2 0x12
|
||||
#define MSMOUSE_CONFIG 3 /* CONFIG register */
|
||||
|
||||
|
||||
#define ENABLE_MOUSE_BUS_LOG 1
|
||||
#ifdef ENABLE_MOUSE_BUS_LOG
|
||||
int mouse_bus_do_log = ENABLE_MOUSE_BUS_LOG;
|
||||
#endif
|
||||
|
||||
|
||||
static void
|
||||
mouse_bus_log(const char *format, ...)
|
||||
{
|
||||
#ifdef ENABLE_MOUSE_BUS_LOG
|
||||
va_list ap;
|
||||
|
||||
if (mouse_bus_do_log) {
|
||||
va_start(ap, format);
|
||||
pclog_ex(format, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/* Reset the controller state. */
|
||||
static void
|
||||
ms_reset(mouse_t *dev)
|
||||
{
|
||||
dev->r_ctrl = 0x00;
|
||||
dev->r_cmd = 0x00;
|
||||
|
||||
dev->seq = 0;
|
||||
|
||||
dev->x = dev->y = 0;
|
||||
dev->but = 0x00;
|
||||
|
||||
dev->flags &= 0xf0;
|
||||
dev->flags |= (FLAG_INTR | FLAG_ENABLED);
|
||||
|
||||
dev->x_delay = dev->y_delay = 0;
|
||||
|
||||
dev->cur_but = 0x00;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
ms_update_data(mouse_t *dev)
|
||||
{
|
||||
int delta_x, delta_y;
|
||||
|
||||
if (dev->x_delay > 127) {
|
||||
delta_x = 127;
|
||||
dev->x_delay -= 127;
|
||||
} else if (dev->x_delay < -128) {
|
||||
delta_x = -128;
|
||||
dev->x_delay += 128;
|
||||
} else {
|
||||
delta_x = dev->x_delay;
|
||||
dev->x_delay = 0;
|
||||
}
|
||||
|
||||
if (dev->y_delay > 127) {
|
||||
delta_y = 127;
|
||||
dev->y_delay -= 127;
|
||||
} else if (dev->y_delay < -128) {
|
||||
delta_y = -128;
|
||||
dev->x_delay += 128;
|
||||
} else {
|
||||
delta_y = dev->y_delay;
|
||||
dev->y_delay = 0;
|
||||
}
|
||||
|
||||
if (!(dev->flags & FLAG_FROZEN)) {
|
||||
dev->x = (int8_t) delta_x;
|
||||
dev->y = (int8_t) delta_y;
|
||||
dev->cur_but = dev->but;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Handle a WRITE to an InPort register. */
|
||||
static void
|
||||
ms_write(mouse_t *dev, uint16_t port, uint8_t val)
|
||||
{
|
||||
uint8_t valxor;
|
||||
|
||||
switch (port) {
|
||||
case MSMOUSE_CTRL:
|
||||
/* Bit 7 is reset. */
|
||||
/* Bits 0-2 are the internal register index. */
|
||||
switch (val) {
|
||||
case MSCTRL_RESET:
|
||||
// ms_reset(dev);
|
||||
dev->r_ctrl = 0x00;
|
||||
dev->r_cmd = 0x00;
|
||||
break;
|
||||
case MSCTRL_COMMAND:
|
||||
case MSCTRL_RD_BUT:
|
||||
case MSCTRL_RD_X:
|
||||
case MSCTRL_RD_Y:
|
||||
dev->r_cmd = val;
|
||||
break;
|
||||
case 0x87:
|
||||
// ms_reset(dev);
|
||||
dev->r_ctrl = 0x00;
|
||||
dev->r_cmd = 0x07;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case MSMOUSE_DATA:
|
||||
picintc(1 << dev->irq);
|
||||
|
||||
if (val == MSDATA_IRQ)
|
||||
picint(1 << dev->irq);
|
||||
else {
|
||||
switch (dev->r_cmd) {
|
||||
case MSCTRL_COMMAND:
|
||||
valxor = (dev->r_ctrl ^ val);
|
||||
|
||||
if (valxor & MSCTRL_FREEZE) {
|
||||
if (val & MSCTRL_FREEZE) {
|
||||
/* Hold the sampling while we do something. */
|
||||
dev->flags |= FLAG_FROZEN;
|
||||
} else {
|
||||
/* Reset current state. */
|
||||
dev->flags &= ~FLAG_FROZEN;
|
||||
|
||||
/* dev->x = dev->y = 0;
|
||||
dev->but = 0; */
|
||||
}
|
||||
}
|
||||
|
||||
if (val & (MSCTRL_IENB_M | MSCTRL_IENB_A))
|
||||
dev->flags |= FLAG_INTR;
|
||||
else
|
||||
dev->flags &= ~FLAG_INTR;
|
||||
|
||||
dev->r_ctrl = val;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case MSMOUSE_MAGIC:
|
||||
break;
|
||||
|
||||
case MSMOUSE_CONFIG:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Handle a READ from an InPort register. */
|
||||
static uint8_t
|
||||
ms_read(mouse_t *dev, uint16_t port)
|
||||
{
|
||||
uint8_t ret = 0x00;
|
||||
|
||||
switch (port) {
|
||||
case MSMOUSE_CTRL:
|
||||
ret = dev->r_ctrl;
|
||||
break;
|
||||
|
||||
case MSMOUSE_DATA:
|
||||
switch (dev->r_cmd) {
|
||||
case MSCTRL_RD_BUT:
|
||||
ret = dev->cur_but;
|
||||
if (dev->flags & FLAG_NEW)
|
||||
ret |= 0x40; /* On new InPort, always have bit 6 set. */
|
||||
break;
|
||||
|
||||
case MSCTRL_RD_X:
|
||||
ret = dev->x;
|
||||
break;
|
||||
|
||||
case MSCTRL_RD_Y:
|
||||
ret = dev->y;
|
||||
break;
|
||||
|
||||
case MSCTRL_COMMAND:
|
||||
ret = dev->r_ctrl;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case MSMOUSE_MAGIC:
|
||||
if (dev->seq & 0x01)
|
||||
ret = MAGIC_MSBYTE2;
|
||||
else
|
||||
ret = MAGIC_MSBYTE1;
|
||||
dev->seq ^= 1;
|
||||
break;
|
||||
|
||||
case MSMOUSE_CONFIG:
|
||||
/* Not really present in real hardware. */
|
||||
break;
|
||||
}
|
||||
|
||||
return(ret);
|
||||
}
|
||||
|
||||
|
||||
/* Reset the controller state. */
|
||||
static void
|
||||
lt_reset(mouse_t *dev)
|
||||
{
|
||||
dev->r_magic = 0x00;
|
||||
dev->r_ctrl = (LTCTRL_IENB);
|
||||
dev->r_conf = 0x00;
|
||||
|
||||
dev->seq = 0;
|
||||
|
||||
dev->x = dev->y = 0;
|
||||
dev->but = 0x00;
|
||||
|
||||
dev->flags &= 0xf0;
|
||||
dev->flags |= FLAG_INTR;
|
||||
|
||||
dev->irq_num = 0;
|
||||
}
|
||||
|
||||
|
||||
/* Called at 30hz */
|
||||
static void
|
||||
bm_timer(void *priv)
|
||||
{
|
||||
mouse_t *dev = (mouse_t *)priv;
|
||||
|
||||
if (dev->flags & FLAG_INPORT) {
|
||||
dev->timer = ((1000000LL * TIMER_USEC) / 30LL);
|
||||
|
||||
ms_update_data(dev);
|
||||
|
||||
if (dev->flags & FLAG_INTR)
|
||||
picint(1 << dev->irq);
|
||||
} else {
|
||||
picint(1 << dev->irq);
|
||||
|
||||
if (dev->irq_num == 5) {
|
||||
mouse_bus_log("5th IRQ, enabling mouse...\n");
|
||||
lt_reset(dev);
|
||||
dev->flags |= FLAG_ENABLED;
|
||||
}
|
||||
|
||||
if (dev->irq_num == 4) {
|
||||
mouse_bus_log("4th IRQ, going for the 5th...\n");
|
||||
dev->irq_num++;
|
||||
dev->timer = ((1000000LL * TIMER_USEC) / 30LL);
|
||||
} else {
|
||||
mouse_bus_log("IRQ before the 4th, disabling timer...\n");
|
||||
dev->timer = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Handle a WRITE to a Logitech register. */
|
||||
static void
|
||||
lt_write(mouse_t *dev, uint16_t port, uint8_t val)
|
||||
{
|
||||
uint8_t b;
|
||||
|
||||
switch (port) {
|
||||
case LTMOUSE_DATA: /* [00] data register */
|
||||
break;
|
||||
|
||||
case LTMOUSE_MAGIC: /* [01] magic data register */
|
||||
switch(val) {
|
||||
case LTMAGIC_BYTE1:
|
||||
case LTMAGIC_BYTE2:
|
||||
lt_reset(dev);
|
||||
dev->r_magic = val;
|
||||
dev->flags |= FLAG_ENABLED;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case LTMOUSE_CTRL: /* [02] control register */
|
||||
if (!(dev->flags & FLAG_ENABLED)) {
|
||||
dev->irq_num++;
|
||||
dev->timer = ((1000000LL * TIMER_USEC) / 30LL);
|
||||
break;
|
||||
}
|
||||
|
||||
b = (dev->r_ctrl ^ val);
|
||||
if (b & LTCTRL_FREEZE) {
|
||||
if (val & LTCTRL_FREEZE) {
|
||||
/* Hold the sampling while we do something. */
|
||||
dev->flags |= FLAG_FROZEN;
|
||||
} else {
|
||||
/* Reset current state. */
|
||||
dev->flags &= ~FLAG_FROZEN;
|
||||
dev->x = dev->y = 0;
|
||||
if (dev->but)
|
||||
dev->but |= 0x80;
|
||||
}
|
||||
}
|
||||
|
||||
if (b & LTCTRL_IDIS) {
|
||||
/* Disable or enable interrupts. */
|
||||
if (val & LTCTRL_IDIS)
|
||||
dev->flags &= ~FLAG_INTR;
|
||||
else
|
||||
dev->flags |= FLAG_INTR;
|
||||
}
|
||||
|
||||
/* Save new register value. */
|
||||
dev->r_ctrl = val;
|
||||
|
||||
/* Clear any pending interrupts. */
|
||||
picintc(1 << dev->irq);
|
||||
break;
|
||||
|
||||
case LTMOUSE_CONFIG: /* [03] config register */
|
||||
/*
|
||||
* The original Logitech design was based on using a
|
||||
* 8255 parallel I/O chip. This chip has to be set up
|
||||
* for proper operation, and this configuration data
|
||||
* is what is programmed into this register.
|
||||
*
|
||||
* A snippet of code found in the FreeBSD kernel source
|
||||
* explains the value:
|
||||
*
|
||||
* D7 = Mode set flag (1 = active)
|
||||
* D6,D5 = Mode selection (port A)
|
||||
* 00 = Mode 0 = Basic I/O
|
||||
* 01 = Mode 1 = Strobed I/O
|
||||
* 10 = Mode 2 = Bi-dir bus
|
||||
* D4 = Port A direction (1 = input)
|
||||
* D3 = Port C (upper 4 bits) direction. (1 = input)
|
||||
* D2 = Mode selection (port B & C)
|
||||
* 0 = Mode 0 = Basic I/O
|
||||
* 1 = Mode 1 = Strobed I/O
|
||||
* D1 = Port B direction (1 = input)
|
||||
* D0 = Port C (lower 4 bits) direction. (1 = input)
|
||||
*
|
||||
* So 91 means Basic I/O on all 3 ports, Port A is an input
|
||||
* port, B is an output port, C is split with upper 4 bits
|
||||
* being an output port and lower 4 bits an input port, and
|
||||
* enable the sucker. Courtesy Intel 8255 databook. Lars
|
||||
*/
|
||||
dev->r_conf = val;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
lt_read_int(mouse_t *dev)
|
||||
{
|
||||
if (!(dev->flags & FLAG_NEW))
|
||||
return 1; /* On old LogiBus, read the IRQ bits always. */
|
||||
|
||||
if (dev->flags & FLAG_INTR)
|
||||
return 1; /* On new LogiBus, read the IRQ bits if interrupts are enabled. */
|
||||
|
||||
return 0; /* Otherwise, do not. */
|
||||
}
|
||||
|
||||
|
||||
/* Handle a READ from a Logitech register. */
|
||||
static uint8_t
|
||||
lt_read(mouse_t *dev, uint16_t port)
|
||||
{
|
||||
uint8_t ret = 0xff;
|
||||
|
||||
/* The GEOS drivers actually check this. */
|
||||
if (! (dev->flags & FLAG_ENABLED)) return(ret);
|
||||
|
||||
switch (port) {
|
||||
case LTMOUSE_DATA: /* [00] data register */
|
||||
ret = 0x07;
|
||||
if (dev->but & 0x01) /* LEFT */
|
||||
ret &= ~0x04;
|
||||
if (dev->but & 0x02) /* RIGHT */
|
||||
ret &= ~0x01;
|
||||
if (dev->flags & FLAG_3BTN)
|
||||
if (dev->but & 0x04) /* MIDDLE */
|
||||
ret &= ~0x02;
|
||||
ret <<= 5;
|
||||
|
||||
switch(dev->r_ctrl & LTCTRL_RD_MASK) {
|
||||
case LTCTRL_RD_X_LO: /* X, low bits */
|
||||
ret |= (dev->x & 0x0f);
|
||||
break;
|
||||
|
||||
case LTCTRL_RD_X_HI: /* X, high bits */
|
||||
ret |= (dev->x >> 4) & 0x0f;
|
||||
break;
|
||||
|
||||
case LTCTRL_RD_Y_LO: /* Y, low bits */
|
||||
ret |= (dev->y & 0x0f);
|
||||
break;
|
||||
|
||||
case LTCTRL_RD_Y_HI: /* Y, high bits */
|
||||
ret |= (dev->y >> 4) & 0x0f;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case LTMOUSE_MAGIC: /* [01] magic data register */
|
||||
/*
|
||||
* Drivers write a magic byte to this register, usually
|
||||
* this is either 5A (AMI WinBIOS, MS Mouse 2.0) or
|
||||
* A5 (MS Mouse 9.1, Windows drivers, UNIX/Linux/Minix.)
|
||||
*/
|
||||
ret = dev->r_magic;
|
||||
break;
|
||||
|
||||
case LTMOUSE_CTRL: /* [02] control register */
|
||||
ret = 0x0f;
|
||||
if (!(dev->r_ctrl & LTCTRL_IDIS) && (dev->seq > 0x3FF) && lt_read_int(dev)) {
|
||||
/* !IDIS, return DIP switch setting. */
|
||||
switch(dev->irq) {
|
||||
case 2:
|
||||
ret &= ~0x08;
|
||||
break;
|
||||
|
||||
case 3:
|
||||
ret &= ~0x04;
|
||||
break;
|
||||
|
||||
case 4:
|
||||
ret &= ~0x02;
|
||||
break;
|
||||
|
||||
case 5:
|
||||
ret &= ~0x01;
|
||||
break;
|
||||
}
|
||||
}
|
||||
dev->seq = (dev->seq + 1) & 0x7ff;
|
||||
break;
|
||||
|
||||
case LTMOUSE_CONFIG: /* [03] config register */
|
||||
ret = dev->r_conf;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return(ret);
|
||||
}
|
||||
|
||||
|
||||
/* Handle a WRITE operation to one of our registers. */
|
||||
static void
|
||||
bm_write(uint16_t port, uint8_t val, void *priv)
|
||||
{
|
||||
mouse_t *dev = (mouse_t *)priv;
|
||||
|
||||
mouse_bus_log("%s: write(%d,%02x)\n", dev->name, port & 0x03, val);
|
||||
|
||||
dev->write(dev, port & 0x03, val);
|
||||
}
|
||||
|
||||
|
||||
/* Handle a READ operation from one of our registers. */
|
||||
static uint8_t
|
||||
bm_read(uint16_t port, void *priv)
|
||||
{
|
||||
mouse_t *dev = (mouse_t *)priv;
|
||||
uint8_t ret;
|
||||
|
||||
ret = dev->read(dev, port & 0x03);
|
||||
|
||||
mouse_bus_log("%s: read(%d): %02x\n", dev->name, port & 0x03, ret);
|
||||
|
||||
return(ret);
|
||||
}
|
||||
|
||||
|
||||
/* The emulator calls us with an update on the host mouse device. */
|
||||
static int
|
||||
bm_poll(int x, int y, int z, int b, void *priv)
|
||||
{
|
||||
uint8_t b_last;
|
||||
mouse_t *dev = (mouse_t *)priv;
|
||||
|
||||
b_last = dev->but;
|
||||
|
||||
/* Return early if nothing to do. */
|
||||
if (!x && !y && !z && (dev->but == b))
|
||||
return(1);
|
||||
|
||||
/* If we are not enabled, return. */
|
||||
if (! (dev->flags & FLAG_ENABLED))
|
||||
mouse_bus_log("bm_poll(): Mouse not enabled\n");
|
||||
|
||||
if (dev->flags & FLAG_SCALED) {
|
||||
/* Scale down the motion. */
|
||||
if ((x < -1) || (x > 1)) x >>= 1;
|
||||
if ((y < -1) || (y > 1)) y >>= 1;
|
||||
}
|
||||
|
||||
if (dev->flags & FLAG_INPORT) {
|
||||
if (x || y || z)
|
||||
dev->but = 0x40; /* Mouse has moved. */
|
||||
else
|
||||
dev->but = 0x00;
|
||||
|
||||
if (x > 127) x = 127;
|
||||
if (y > 127) y = 127;
|
||||
if (x < -128) x = -128;
|
||||
if (y < -128) y = -128;
|
||||
|
||||
dev->x_delay += x;
|
||||
dev->y_delay += y;
|
||||
dev->but |= (uint8_t) (((b & 1) << 2) | ((b & 2) >> 1));
|
||||
if (dev->flags & FLAG_3BTN)
|
||||
dev->but |= ((b & 4) >> 1);
|
||||
|
||||
if ((b_last ^ dev->but) & 0x04)
|
||||
dev->but |= 0x20; /* Left button state has changed. */
|
||||
if (((b_last ^ dev->but) & 0x02) && (dev->flags & FLAG_3BTN))
|
||||
dev->but |= 0x10; /* Middle button state has changed. */
|
||||
if ((b_last ^ dev->but) & 0x01)
|
||||
dev->but |= 0x08; /* Right button state has changed. */
|
||||
|
||||
dev->but |= 0x80; /* Packet complete. */
|
||||
} else {
|
||||
/* If we are frozen, do not update the state. */
|
||||
if (! (dev->flags & FLAG_FROZEN)) {
|
||||
/* Add the delta to our state. */
|
||||
x += dev->x;
|
||||
if (x > 127)
|
||||
x = 127;
|
||||
if (x < -128)
|
||||
x = -128;
|
||||
dev->x = (int8_t)x;
|
||||
|
||||
y += dev->y;
|
||||
if (y > 127)
|
||||
y = 127;
|
||||
if (y < -1287)
|
||||
y = -1287;
|
||||
dev->y = (int8_t)y;
|
||||
|
||||
dev->x_delay += x;
|
||||
dev->y_delay += y;
|
||||
|
||||
dev->but = b;
|
||||
}
|
||||
|
||||
/* Either way, generate an interrupt. */
|
||||
if ((dev->flags & FLAG_INTR) && !(dev->flags & FLAG_INPORT))
|
||||
picint(1 << dev->irq);
|
||||
}
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
/* Release all resources held by the device. */
|
||||
static void
|
||||
bm_close(void *priv)
|
||||
{
|
||||
mouse_t *dev = (mouse_t *)priv;
|
||||
|
||||
/* Release our I/O range. */
|
||||
io_removehandler(dev->base, 4,
|
||||
bm_read, NULL, NULL, bm_write, NULL, NULL, dev);
|
||||
|
||||
free(dev);
|
||||
}
|
||||
|
||||
|
||||
/* Initialize the device for use by the user. */
|
||||
static void *
|
||||
bm_init(const device_t *info)
|
||||
{
|
||||
mouse_t *dev;
|
||||
int i, j;
|
||||
|
||||
dev = (mouse_t *)malloc(sizeof(mouse_t));
|
||||
memset(dev, 0x00, sizeof(mouse_t));
|
||||
dev->name = info->name;
|
||||
dev->type = info->local;
|
||||
dev->irq = device_get_config_int("irq");
|
||||
dev->base = device_get_config_hex16("base");
|
||||
i = device_get_config_int("buttons");
|
||||
if (i > 2)
|
||||
dev->flags |= FLAG_3BTN;
|
||||
j = device_get_config_int("model");
|
||||
if (j)
|
||||
dev->flags |= FLAG_NEW;
|
||||
|
||||
switch(dev->type) {
|
||||
case MOUSE_TYPE_LOGIBUS:
|
||||
lt_reset(dev);
|
||||
|
||||
/* Initialize I/O handlers. */
|
||||
dev->read = lt_read;
|
||||
dev->write = lt_write;
|
||||
|
||||
dev->timer = 0;
|
||||
timer_add(bm_timer, &dev->timer, &dev->timer, dev);
|
||||
break;
|
||||
|
||||
case MOUSE_TYPE_INPORT:
|
||||
dev->flags |= FLAG_INPORT;
|
||||
ms_reset(dev);
|
||||
|
||||
/* Initialize I/O handlers. */
|
||||
dev->read = ms_read;
|
||||
dev->write = ms_write;
|
||||
|
||||
dev->timer = (33334LL * TIMER_USEC);
|
||||
timer_add(bm_timer, &dev->timer, TIMER_ALWAYS_ENABLED, dev);
|
||||
break;
|
||||
}
|
||||
|
||||
/* Request an I/O range. */
|
||||
io_sethandler(dev->base, 4,
|
||||
bm_read, NULL, NULL, bm_write, NULL, NULL, dev);
|
||||
|
||||
mouse_bus_log("%s: I/O=%04x, IRQ=%d, buttons=%d, model=%s\n",
|
||||
dev->name, dev->base, dev->irq, i, j ? "new" : "old");
|
||||
|
||||
/* Tell them how many buttons we have. */
|
||||
mouse_set_buttons((dev->flags & FLAG_3BTN) ? 3 : 2);
|
||||
|
||||
/* Return our private data to the I/O layer. */
|
||||
return(dev);
|
||||
}
|
||||
|
||||
|
||||
static const device_config_t bm_config[] = {
|
||||
{
|
||||
"base", "Address", CONFIG_HEX16, "", MOUSE_PORT,
|
||||
{
|
||||
{
|
||||
"0x230", 0x230
|
||||
},
|
||||
{
|
||||
"0x234", 0x234
|
||||
},
|
||||
{
|
||||
"0x238", 0x238
|
||||
},
|
||||
{
|
||||
"0x23C", 0x23c
|
||||
},
|
||||
{
|
||||
""
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"irq", "IRQ", CONFIG_SELECTION, "", MOUSE_IRQ, {
|
||||
{
|
||||
"IRQ 2", 2
|
||||
},
|
||||
{
|
||||
"IRQ 3", 3
|
||||
},
|
||||
{
|
||||
"IRQ 4", 4
|
||||
},
|
||||
{
|
||||
"IRQ 5", 5
|
||||
},
|
||||
{
|
||||
""
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"buttons", "Buttons", CONFIG_SELECTION, "", MOUSE_BUTTONS, {
|
||||
{
|
||||
"Two", 2
|
||||
},
|
||||
{
|
||||
"Three", 3
|
||||
},
|
||||
{
|
||||
""
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"model", "Model", CONFIG_SELECTION, "", 0, {
|
||||
{
|
||||
"Old", 0
|
||||
},
|
||||
{
|
||||
"New", 1
|
||||
},
|
||||
{
|
||||
""
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"", "", -1
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
const device_t mouse_logibus_device = {
|
||||
"Logitech Bus Mouse",
|
||||
DEVICE_ISA,
|
||||
MOUSE_TYPE_LOGIBUS,
|
||||
bm_init, bm_close, NULL,
|
||||
bm_poll, NULL, NULL,
|
||||
bm_config
|
||||
};
|
||||
|
||||
const device_t mouse_msinport_device = {
|
||||
"Microsoft Bus Mouse (InPort)",
|
||||
DEVICE_ISA,
|
||||
MOUSE_TYPE_INPORT,
|
||||
bm_init, bm_close, NULL,
|
||||
bm_poll, NULL, NULL,
|
||||
bm_config
|
||||
};
|
||||
794
backup code/mouse_bus - Cópia.c
Normal file
794
backup code/mouse_bus - Cópia.c
Normal file
@@ -0,0 +1,794 @@
|
||||
/*
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
*
|
||||
* This file is part of the 86Box distribution.
|
||||
*
|
||||
* Implementation of Bus Mouse devices.
|
||||
*
|
||||
* These devices were made by both Microsoft and Logitech. At
|
||||
* first, Microsoft used the same protocol as Logitech, but did
|
||||
* switch to their new protocol for their InPort interface. So,
|
||||
* although alike enough to be handled in the same driver, they
|
||||
* are not the same.
|
||||
*
|
||||
* This code is based on my Minix driver for the Logitech(-mode)
|
||||
* interface. Although that driver blindly took IRQ5, the board
|
||||
* seems to be able to tell the driver what IRQ it is set for.
|
||||
* When testing on MS-DOS (6.22), the 'mouse.exe' driver did not
|
||||
* want to start, and only after disassembling it and inspecting
|
||||
* the code it was discovered that driver actually does use the
|
||||
* IRQ reporting feature. In a really, really weird way, too: it
|
||||
* sets up the board, and then reads the CTRL register which is
|
||||
* supposed to return that IRQ value. Depending on whether or
|
||||
* not the FREEZE bit is set, it has to return either the two's
|
||||
* complemented (negated) value, or (if clear) just the value.
|
||||
* The mouse.com driver reads both values 10,000 times, and
|
||||
* then makes up its mind. Maybe an effort to 'debounce' the
|
||||
* reading of the DIP switches? Oh-well.
|
||||
*
|
||||
* NOTES: Verified with:
|
||||
* AMI WinBIOS 486 (5A, no IRQ detect, OK, IRQ5 only)
|
||||
* Microsoft Mouse.com V2.00 (DOS V6.22, 5A, OK)
|
||||
* Microsoft Mouse.exe V9.1 (DOS V6.22, A5, OK)
|
||||
* Logitech LMouse.com V6.02 (DOS V6.22)
|
||||
* Logitech LMouse.com V6.43 (DOS V6.22)
|
||||
* Microsoft WfW V3.11 on DOS V6.22
|
||||
* GEOS V1.0 (OK, IRQ5 only)
|
||||
* GEOS V2.0 (OK, IRQ5 only)
|
||||
* Microsoft Windows 95 OSR2
|
||||
* Microsoft Windows 98 SE
|
||||
* Microsoft Windows NT 3.1
|
||||
* Microsoft Windows NT 3.51
|
||||
*
|
||||
* The polling frequency for InPort controllers has to
|
||||
* be changed to programmable. Microsoft uses 30Hz,
|
||||
* but ATIXL ports are programmable 30-200Hz.
|
||||
*
|
||||
* Based on an early driver for MINIX 1.5.
|
||||
*
|
||||
* Version: @(#)mouse_bus.c 1.0.34 2018/04/29
|
||||
*
|
||||
* Authors: Fred N. van Kempen, <decwiz@yahoo.com>
|
||||
*
|
||||
* Copyright 1989-2018 Fred N. van Kempen.
|
||||
*/
|
||||
#include <inttypes.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <wchar.h>
|
||||
#define HAVE_STDARG_H
|
||||
#include "86box.h"
|
||||
#include "config.h"
|
||||
#include "io.h"
|
||||
#include "pic.h"
|
||||
#include "timer.h"
|
||||
#include "device.h"
|
||||
#include "mouse.h"
|
||||
|
||||
|
||||
#define MOUSE_PORT 0x023c /* default */
|
||||
#define MOUSE_IRQ 5 /* default */
|
||||
#define MOUSE_BUTTONS 2 /* default */
|
||||
#define MOUSE_DEBUG 0
|
||||
|
||||
|
||||
/* Our mouse device. */
|
||||
typedef struct mouse {
|
||||
const char *name; /* name of this device */
|
||||
int8_t type; /* type of this device */
|
||||
int8_t irq; /* IRQ channel to use */
|
||||
uint8_t flags; /* device flags */
|
||||
|
||||
uint8_t r_magic, /* MAGIC register */
|
||||
r_ctrl, /* CONTROL register (WR) */
|
||||
r_conf, /* CONFIG register */
|
||||
r_cmd; /* (MS) current command */
|
||||
|
||||
uint8_t seq; /* general counter */
|
||||
|
||||
uint8_t but, /* current mouse status */
|
||||
but_last;
|
||||
uint8_t cur_but;
|
||||
int8_t x, y;
|
||||
int x_delay,
|
||||
y_delay;
|
||||
uint8_t need_upd;
|
||||
uint8_t irq_num;
|
||||
|
||||
int64_t timer; /* mouse event timer */
|
||||
|
||||
uint8_t (*read)(struct mouse *, uint16_t);
|
||||
void (*write)(struct mouse *, uint16_t, uint8_t);
|
||||
} mouse_t;
|
||||
#define FLAG_INPORT 0x80 /* device is MS InPort */
|
||||
#define FLAG_3BTN 0x20 /* enable 3-button mode */
|
||||
#define FLAG_SCALED 0x10 /* enable delta scaling */
|
||||
#define FLAG_INTR 0x04 /* dev can send interrupts */
|
||||
#define FLAG_FROZEN 0x02 /* do not update counters */
|
||||
#define FLAG_ENABLED 0x01 /* dev is enabled for use */
|
||||
|
||||
|
||||
/* Definitions for Logitech. */
|
||||
#define LTMOUSE_DATA 0 /* DATA register */
|
||||
#define LTMOUSE_MAGIC 1 /* signature magic register */
|
||||
# define LTMAGIC_BYTE1 0xa5 /* most drivers use this */
|
||||
# define LTMAGIC_BYTE2 0x5a /* some drivers use this */
|
||||
#define LTMOUSE_CTRL 2 /* CTRL register */
|
||||
# define LTCTRL_FREEZE 0x80 /* do not sample when set */
|
||||
# define LTCTRL_RD_Y_HI 0x60
|
||||
# define LTCTRL_RD_Y_LO 0x40
|
||||
# define LTCTRL_RD_X_HI 0x20
|
||||
# define LTCTRL_RD_X_LO 0x00
|
||||
# define LTCTRL_RD_MASK 0x60
|
||||
# define LTCTRL_IDIS 0x10
|
||||
# define LTCTRL_IENB 0x00
|
||||
#define LTMOUSE_CONFIG 3 /* CONFIG register */
|
||||
|
||||
/* Definitions for Microsoft. */
|
||||
#define MSMOUSE_CTRL 0 /* CTRL register */
|
||||
# define MSCTRL_RESET 0x80 /* reset controller */
|
||||
# define MSCTRL_FREEZE 0x20 /* HOLD- freeze data */
|
||||
# define MSCTRL_IENB_A 0x08 /* ATIXL intr enable */
|
||||
# define MSCTRL_IENB_M 0x01 /* MS intr enable */
|
||||
# define MSCTRL_COMMAND 0x07
|
||||
# define MSCTRL_RD_Y 0x02
|
||||
# define MSCTRL_RD_X 0x01
|
||||
# define MSCTRL_RD_BUT 0x00
|
||||
#define MSMOUSE_DATA 1 /* DATA register */
|
||||
# define MSDATA_IRQ 0x16
|
||||
# define MSDATA_BASE 0x10 /* MS InPort: 30Hz */
|
||||
# define MSDATA_HZ30 0x01 /* ATIXL 30Hz */
|
||||
# define MSDATA_HZ50 0x02 /* ATIXL 50Hz */
|
||||
# define MSDATA_HZ100 0x03 /* ATIXL 100Hz */
|
||||
# define MSDATA_HZ200 0x04 /* ATIXL 200Hz */
|
||||
#define MSMOUSE_MAGIC 2 /* MAGIC register */
|
||||
# define MAGIC_MSBYTE1 0xde /* indicates MS InPort */
|
||||
// # define MAGIC_MSBYTE2 0x12
|
||||
# define MAGIC_MSBYTE2 0x22 /* According to the Bochs code, this sould be 0x22, not 0x12. */
|
||||
#define MSMOUSE_CONFIG 3 /* CONFIG register */
|
||||
|
||||
|
||||
#ifdef ENABLE_MOUSE_BUS_LOG
|
||||
int mouse_bus_do_log = ENABLE_MOUSE_BUS_LOG;
|
||||
#endif
|
||||
|
||||
|
||||
static void
|
||||
mouse_bus_log(const char *format, ...)
|
||||
{
|
||||
#ifdef ENABLE_MOUSE_BUS_LOG
|
||||
va_list ap;
|
||||
|
||||
if (mouse_bus_do_log) {
|
||||
va_start(ap, format);
|
||||
pclog_ex(format, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/* Reset the controller state. */
|
||||
static void
|
||||
ms_reset(mouse_t *dev)
|
||||
{
|
||||
dev->r_ctrl = 0x00;
|
||||
dev->r_cmd = 0x00;
|
||||
|
||||
dev->seq = 0;
|
||||
|
||||
dev->x = dev->y = 0;
|
||||
dev->but = 0x00;
|
||||
|
||||
dev->flags &= 0xf0;
|
||||
dev->flags |= (FLAG_INTR | FLAG_ENABLED);
|
||||
|
||||
dev->x_delay = dev->y_delay = 0;
|
||||
dev->need_upd = 0;
|
||||
|
||||
dev->cur_but = 0x00;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
ms_update_data(mouse_t *dev)
|
||||
{
|
||||
int delta_x, delta_y;
|
||||
|
||||
if (dev->x_delay > 127) {
|
||||
delta_x = 127;
|
||||
dev->x_delay -= 127;
|
||||
} else if (dev->x_delay < -128) {
|
||||
delta_x = -128;
|
||||
dev->x_delay += 128;
|
||||
} else {
|
||||
delta_x = dev->x_delay;
|
||||
dev->x_delay = 0;
|
||||
}
|
||||
|
||||
if (dev->y_delay > 127) {
|
||||
delta_y = 127;
|
||||
dev->y_delay -= 127;
|
||||
} else if (dev->y_delay < -128) {
|
||||
delta_y = -128;
|
||||
dev->x_delay += 128;
|
||||
} else {
|
||||
delta_y = dev->y_delay;
|
||||
dev->y_delay = 0;
|
||||
}
|
||||
|
||||
if ((dev->x_delay == 0) && (dev->y_delay == 0))
|
||||
dev->need_upd = 0;
|
||||
|
||||
dev->x = (int8_t) delta_x;
|
||||
dev->y = (int8_t) delta_y;
|
||||
dev->cur_but = dev->but;
|
||||
}
|
||||
|
||||
|
||||
/* Handle a WRITE to an InPort register. */
|
||||
static void
|
||||
ms_write(mouse_t *dev, uint16_t port, uint8_t val)
|
||||
{
|
||||
switch (port) {
|
||||
case MSMOUSE_CTRL:
|
||||
switch (val) {
|
||||
case MSCTRL_RESET:
|
||||
ms_reset(dev);
|
||||
break;
|
||||
|
||||
case MSCTRL_COMMAND:
|
||||
case MSCTRL_RD_BUT:
|
||||
case MSCTRL_RD_X:
|
||||
case MSCTRL_RD_Y:
|
||||
dev->r_ctrl = val & 0x07;
|
||||
break;
|
||||
|
||||
case 0x87:
|
||||
ms_reset(dev);
|
||||
dev->r_ctrl = MSCTRL_COMMAND;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case MSMOUSE_DATA:
|
||||
picintc(1 << dev->irq);
|
||||
if (val == MSDATA_IRQ) {
|
||||
picint(1<<dev->irq);
|
||||
} else switch (dev->r_ctrl) {
|
||||
case MSCTRL_COMMAND:
|
||||
if (val & MSCTRL_FREEZE) {
|
||||
/* Hold the sampling. */
|
||||
ms_update_data(dev);
|
||||
} else {
|
||||
/* Reset current state. */
|
||||
picintc(1 << dev->irq);
|
||||
}
|
||||
|
||||
if (val & (MSCTRL_IENB_M | MSCTRL_IENB_A))
|
||||
dev->flags |= FLAG_INTR;
|
||||
else
|
||||
dev->flags &= ~FLAG_INTR;
|
||||
|
||||
dev->r_cmd = val;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case MSMOUSE_MAGIC:
|
||||
break;
|
||||
|
||||
case MSMOUSE_CONFIG:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Handle a READ from an InPort register. */
|
||||
static uint8_t
|
||||
ms_read(mouse_t *dev, uint16_t port)
|
||||
{
|
||||
uint8_t ret = 0x00;
|
||||
|
||||
switch (port) {
|
||||
case MSMOUSE_CTRL:
|
||||
ret = dev->r_ctrl;
|
||||
break;
|
||||
|
||||
case MSMOUSE_DATA:
|
||||
switch (dev->r_ctrl) {
|
||||
case MSCTRL_RD_BUT:
|
||||
ret = dev->cur_but;
|
||||
break;
|
||||
|
||||
case MSCTRL_RD_X:
|
||||
ret = dev->x;
|
||||
break;
|
||||
|
||||
case MSCTRL_RD_Y:
|
||||
ret = dev->y;
|
||||
break;
|
||||
|
||||
case MSCTRL_COMMAND:
|
||||
ret = dev->r_cmd;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case MSMOUSE_MAGIC:
|
||||
if (dev->seq & 0x01)
|
||||
ret = MAGIC_MSBYTE2;
|
||||
else
|
||||
ret = MAGIC_MSBYTE1;
|
||||
dev->seq ^= 1;
|
||||
break;
|
||||
|
||||
case MSMOUSE_CONFIG:
|
||||
/* Not really present in real hardware. */
|
||||
break;
|
||||
}
|
||||
|
||||
return(ret);
|
||||
}
|
||||
|
||||
|
||||
/* Reset the controller state. */
|
||||
static void
|
||||
lt_reset(mouse_t *dev)
|
||||
{
|
||||
dev->r_magic = 0x00;
|
||||
dev->r_ctrl = (LTCTRL_IENB);
|
||||
dev->r_conf = 0x00;
|
||||
|
||||
dev->seq = 0;
|
||||
|
||||
dev->x = dev->y = 0;
|
||||
dev->but = 0x00;
|
||||
|
||||
dev->flags &= 0xf0;
|
||||
dev->flags |= FLAG_INTR;
|
||||
|
||||
dev->irq_num = 0;
|
||||
}
|
||||
|
||||
|
||||
/* Called at 30hz */
|
||||
static void
|
||||
bm_timer(void *priv)
|
||||
{
|
||||
mouse_t *dev = (mouse_t *)priv;
|
||||
|
||||
if (dev->flags & FLAG_INPORT) {
|
||||
dev->timer = ((1000000LL * TIMER_USEC) / 30LL);
|
||||
|
||||
if ((dev->flags & FLAG_INTR) && dev->need_upd) {
|
||||
picint(1 << dev->irq);
|
||||
mouse_bus_log("IRQ %i raised\n", dev->irq);
|
||||
}
|
||||
} else {
|
||||
picint(1 << dev->irq);
|
||||
|
||||
if (dev->irq_num == 5) {
|
||||
mouse_bus_log("5th IRQ, enabling mouse...\n");
|
||||
lt_reset(dev);
|
||||
dev->flags |= FLAG_ENABLED;
|
||||
}
|
||||
|
||||
if (dev->irq_num == 4) {
|
||||
mouse_bus_log("4th IRQ, going for the 5th...\n");
|
||||
dev->irq_num++;
|
||||
dev->timer = ((1000000LL * TIMER_USEC) / 30LL);
|
||||
} else {
|
||||
mouse_bus_log("IRQ before the 4th, disabling timer...\n");
|
||||
dev->timer = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Handle a WRITE to a Logitech register. */
|
||||
static void
|
||||
lt_write(mouse_t *dev, uint16_t port, uint8_t val)
|
||||
{
|
||||
uint8_t b;
|
||||
|
||||
switch (port) {
|
||||
case LTMOUSE_DATA: /* [00] data register */
|
||||
break;
|
||||
|
||||
case LTMOUSE_MAGIC: /* [01] magic data register */
|
||||
switch(val) {
|
||||
case LTMAGIC_BYTE1:
|
||||
case LTMAGIC_BYTE2:
|
||||
lt_reset(dev);
|
||||
dev->r_magic = val;
|
||||
dev->flags |= FLAG_ENABLED;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case LTMOUSE_CTRL: /* [02] control register */
|
||||
if (!(dev->flags & FLAG_ENABLED)) {
|
||||
dev->irq_num++;
|
||||
dev->timer = ((1000000LL * TIMER_USEC) / 30LL);
|
||||
break;
|
||||
}
|
||||
|
||||
b = (dev->r_ctrl ^ val);
|
||||
if (b & LTCTRL_FREEZE) {
|
||||
if (val & LTCTRL_FREEZE) {
|
||||
/* Hold the sampling while we do something. */
|
||||
dev->flags |= FLAG_FROZEN;
|
||||
} else {
|
||||
/* Reset current state. */
|
||||
dev->flags &= ~FLAG_FROZEN;
|
||||
dev->x = dev->y = 0;
|
||||
if (dev->but)
|
||||
dev->but |= 0x80;
|
||||
}
|
||||
}
|
||||
|
||||
if (b & LTCTRL_IDIS) {
|
||||
/* Disable or enable interrupts. */
|
||||
if (val & LTCTRL_IDIS)
|
||||
dev->flags &= ~FLAG_INTR;
|
||||
else
|
||||
dev->flags |= FLAG_INTR;
|
||||
}
|
||||
|
||||
/* Save new register value. */
|
||||
dev->r_ctrl = val;
|
||||
|
||||
/* Clear any pending interrupts. */
|
||||
picintc(1 << dev->irq);
|
||||
break;
|
||||
|
||||
case LTMOUSE_CONFIG: /* [03] config register */
|
||||
/*
|
||||
* The original Logitech design was based on using a
|
||||
* 8255 parallel I/O chip. This chip has to be set up
|
||||
* for proper operation, and this configuration data
|
||||
* is what is programmed into this register.
|
||||
*
|
||||
* A snippet of code found in the FreeBSD kernel source
|
||||
* explains the value:
|
||||
*
|
||||
* D7 = Mode set flag (1 = active)
|
||||
* D6,D5 = Mode selection (port A)
|
||||
* 00 = Mode 0 = Basic I/O
|
||||
* 01 = Mode 1 = Strobed I/O
|
||||
* 10 = Mode 2 = Bi-dir bus
|
||||
* D4 = Port A direction (1 = input)
|
||||
* D3 = Port C (upper 4 bits) direction. (1 = input)
|
||||
* D2 = Mode selection (port B & C)
|
||||
* 0 = Mode 0 = Basic I/O
|
||||
* 1 = Mode 1 = Strobed I/O
|
||||
* D1 = Port B direction (1 = input)
|
||||
* D0 = Port C (lower 4 bits) direction. (1 = input)
|
||||
*
|
||||
* So 91 means Basic I/O on all 3 ports, Port A is an input
|
||||
* port, B is an output port, C is split with upper 4 bits
|
||||
* being an output port and lower 4 bits an input port, and
|
||||
* enable the sucker. Courtesy Intel 8255 databook. Lars
|
||||
*/
|
||||
dev->r_conf = val;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Handle a READ from a Logitech register. */
|
||||
static uint8_t
|
||||
lt_read(mouse_t *dev, uint16_t port)
|
||||
{
|
||||
uint8_t ret = 0xff;
|
||||
|
||||
/* The GEOS drivers actually check this. */
|
||||
if (! (dev->flags & FLAG_ENABLED)) return(ret);
|
||||
|
||||
switch (port) {
|
||||
case LTMOUSE_DATA: /* [00] data register */
|
||||
ret = 0x07;
|
||||
if (dev->but & 0x01) /* LEFT */
|
||||
ret &= ~0x04;
|
||||
if (dev->but & 0x02) /* RIGHT */
|
||||
ret &= ~0x01;
|
||||
if (dev->flags & FLAG_3BTN)
|
||||
if (dev->but & 0x04) /* MIDDLE */
|
||||
ret &= ~0x02;
|
||||
ret <<= 5;
|
||||
|
||||
switch(dev->r_ctrl & LTCTRL_RD_MASK) {
|
||||
case LTCTRL_RD_X_LO: /* X, low bits */
|
||||
ret |= (dev->x & 0x0f);
|
||||
break;
|
||||
|
||||
case LTCTRL_RD_X_HI: /* X, high bits */
|
||||
ret |= (dev->x >> 4) & 0x0f;
|
||||
break;
|
||||
|
||||
case LTCTRL_RD_Y_LO: /* Y, low bits */
|
||||
ret |= (dev->y & 0x0f);
|
||||
break;
|
||||
|
||||
case LTCTRL_RD_Y_HI: /* Y, high bits */
|
||||
ret |= (dev->y >> 4) & 0x0f;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case LTMOUSE_MAGIC: /* [01] magic data register */
|
||||
/*
|
||||
* Drivers write a magic byte to this register, usually
|
||||
* this is either 5A (AMI WinBIOS, MS Mouse 2.0) or
|
||||
* A5 (MS Mouse 9.1, Windows drivers, UNIX/Linux/Minix.)
|
||||
*/
|
||||
ret = dev->r_magic;
|
||||
break;
|
||||
|
||||
case LTMOUSE_CTRL: /* [02] control register */
|
||||
ret = 0x0f;
|
||||
if (!(dev->r_ctrl & LTCTRL_IDIS) && (dev->seq++ == 0)) {
|
||||
/* !IDIS, return DIP switch setting. */
|
||||
switch(dev->irq) {
|
||||
case 2:
|
||||
ret &= ~0x08;
|
||||
break;
|
||||
|
||||
case 3:
|
||||
ret &= ~0x04;
|
||||
break;
|
||||
|
||||
case 4:
|
||||
ret &= ~0x02;
|
||||
break;
|
||||
|
||||
case 5:
|
||||
ret &= ~0x01;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case LTMOUSE_CONFIG: /* [03] config register */
|
||||
ret = dev->r_conf;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return(ret);
|
||||
}
|
||||
|
||||
|
||||
/* Handle a WRITE operation to one of our registers. */
|
||||
static void
|
||||
bm_write(uint16_t port, uint8_t val, void *priv)
|
||||
{
|
||||
mouse_t *dev = (mouse_t *)priv;
|
||||
|
||||
mouse_bus_log("%s: write(%d,%02x)\n", dev->name, port-MOUSE_PORT, val);
|
||||
|
||||
dev->write(dev, port-MOUSE_PORT, val);
|
||||
}
|
||||
|
||||
|
||||
/* Handle a READ operation from one of our registers. */
|
||||
static uint8_t
|
||||
bm_read(uint16_t port, void *priv)
|
||||
{
|
||||
mouse_t *dev = (mouse_t *)priv;
|
||||
uint8_t ret;
|
||||
|
||||
ret = dev->read(dev, port-MOUSE_PORT);
|
||||
|
||||
mouse_bus_log("%s: read(%d): %02x\n", dev->name, port-MOUSE_PORT, ret);
|
||||
|
||||
return(ret);
|
||||
}
|
||||
|
||||
|
||||
/* The emulator calls us with an update on the host mouse device. */
|
||||
static int
|
||||
bm_poll(int x, int y, int z, int b, void *priv)
|
||||
{
|
||||
mouse_t *dev = (mouse_t *)priv;
|
||||
|
||||
/* Return early if nothing to do. */
|
||||
if (!x && !y && !z && (dev->but == b))
|
||||
return(1);
|
||||
|
||||
/* If we are not enabled, return. */
|
||||
if (! (dev->flags & FLAG_ENABLED))
|
||||
mouse_bus_log("bm_poll(): Mouse not enabled\n");
|
||||
|
||||
if (dev->flags & FLAG_SCALED) {
|
||||
/* Scale down the motion. */
|
||||
if ((x < -1) || (x > 1)) x >>= 1;
|
||||
if ((y < -1) || (y > 1)) y >>= 1;
|
||||
}
|
||||
|
||||
if (dev->flags & FLAG_INPORT) {
|
||||
if (x > 127) x = 127;
|
||||
if (y > 127) y = 127;
|
||||
if (x < -128) x = -128;
|
||||
if (y < -128) y = -128;
|
||||
|
||||
dev->x_delay += x;
|
||||
dev->y_delay += y;
|
||||
dev->but = (uint8_t)(0x40 | ((b & 1) << 2) | ((b & 2) >> 1));
|
||||
if (dev->flags & FLAG_3BTN)
|
||||
dev->but |= ((b & 4) >> 1);
|
||||
dev->need_upd = 1;
|
||||
} else {
|
||||
/* If we are frozen, do not update the state. */
|
||||
if (! (dev->flags & FLAG_FROZEN)) {
|
||||
/* Add the delta to our state. */
|
||||
x += dev->x;
|
||||
if (x > 127)
|
||||
x = 127;
|
||||
if (x < -128)
|
||||
x = -128;
|
||||
dev->x = (int8_t)x;
|
||||
|
||||
y += dev->y;
|
||||
if (y > 127)
|
||||
y = 127;
|
||||
if (y < -1287)
|
||||
y = -1287;
|
||||
dev->y = (int8_t)y;
|
||||
|
||||
dev->x_delay += x;
|
||||
dev->y_delay += y;
|
||||
|
||||
dev->but = b;
|
||||
}
|
||||
|
||||
/* Either way, generate an interrupt. */
|
||||
if ((dev->flags & FLAG_INTR) && !(dev->flags & FLAG_INPORT))
|
||||
picint(1 << dev->irq);
|
||||
}
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
/* Release all resources held by the device. */
|
||||
static void
|
||||
bm_close(void *priv)
|
||||
{
|
||||
mouse_t *dev = (mouse_t *)priv;
|
||||
|
||||
/* Release our I/O range. */
|
||||
io_removehandler(MOUSE_PORT, 4,
|
||||
bm_read, NULL, NULL, bm_write, NULL, NULL, dev);
|
||||
|
||||
free(dev);
|
||||
}
|
||||
|
||||
|
||||
/* Initialize the device for use by the user. */
|
||||
static void *
|
||||
bm_init(const device_t *info)
|
||||
{
|
||||
mouse_t *dev;
|
||||
int i;
|
||||
|
||||
dev = (mouse_t *)malloc(sizeof(mouse_t));
|
||||
memset(dev, 0x00, sizeof(mouse_t));
|
||||
dev->name = info->name;
|
||||
dev->type = info->local;
|
||||
dev->irq = device_get_config_int("irq");
|
||||
i = device_get_config_int("buttons");
|
||||
if (i > 2)
|
||||
dev->flags |= FLAG_3BTN;
|
||||
|
||||
mouse_bus_log("%s: I/O=%04x, IRQ=%d, buttons=%d\n",
|
||||
dev->name, MOUSE_PORT, dev->irq, i);
|
||||
|
||||
switch(dev->type) {
|
||||
case MOUSE_TYPE_LOGIBUS:
|
||||
lt_reset(dev);
|
||||
|
||||
/* Initialize I/O handlers. */
|
||||
dev->read = lt_read;
|
||||
dev->write = lt_write;
|
||||
|
||||
dev->timer = 0;
|
||||
timer_add(bm_timer, &dev->timer, &dev->timer, dev);
|
||||
break;
|
||||
|
||||
case MOUSE_TYPE_INPORT:
|
||||
dev->flags |= FLAG_INPORT;
|
||||
ms_reset(dev);
|
||||
|
||||
/* Initialize I/O handlers. */
|
||||
dev->read = ms_read;
|
||||
dev->write = ms_write;
|
||||
|
||||
dev->timer = (33334LL * TIMER_USEC);
|
||||
timer_add(bm_timer, &dev->timer, TIMER_ALWAYS_ENABLED, dev);
|
||||
break;
|
||||
}
|
||||
|
||||
/* Request an I/O range. */
|
||||
io_sethandler(MOUSE_PORT, 4,
|
||||
bm_read, NULL, NULL, bm_write, NULL, NULL, dev);
|
||||
|
||||
/* Tell them how many buttons we have. */
|
||||
mouse_set_buttons((dev->flags & FLAG_3BTN) ? 3 : 2);
|
||||
|
||||
/* Return our private data to the I/O layer. */
|
||||
return(dev);
|
||||
}
|
||||
|
||||
|
||||
static const device_config_t bm_config[] = {
|
||||
{
|
||||
"irq", "IRQ", CONFIG_SELECTION, "", MOUSE_IRQ, {
|
||||
{
|
||||
"IRQ 2", 2
|
||||
},
|
||||
{
|
||||
"IRQ 3", 3
|
||||
},
|
||||
{
|
||||
"IRQ 4", 4
|
||||
},
|
||||
{
|
||||
"IRQ 5", 5
|
||||
},
|
||||
{
|
||||
""
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"buttons", "Buttons", CONFIG_SELECTION, "", MOUSE_BUTTONS, {
|
||||
{
|
||||
"Two", 2
|
||||
},
|
||||
{
|
||||
"Three", 3
|
||||
},
|
||||
{
|
||||
""
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"", "", -1
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
const device_t mouse_logibus_device = {
|
||||
"Logitech Bus Mouse",
|
||||
DEVICE_ISA,
|
||||
MOUSE_TYPE_LOGIBUS,
|
||||
bm_init, bm_close, NULL,
|
||||
bm_poll, NULL, NULL,
|
||||
bm_config
|
||||
};
|
||||
|
||||
const device_t mouse_msinport_device = {
|
||||
"Microsoft Bus Mouse (InPort)",
|
||||
DEVICE_ISA,
|
||||
MOUSE_TYPE_INPORT,
|
||||
bm_init, bm_close, NULL,
|
||||
bm_poll, NULL, NULL,
|
||||
bm_config
|
||||
};
|
||||
879
backup code/mouse_bus_good.c
Normal file
879
backup code/mouse_bus_good.c
Normal file
@@ -0,0 +1,879 @@
|
||||
/*
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
*
|
||||
* This file is part of the 86Box distribution.
|
||||
*
|
||||
* Implementation of Bus Mouse devices.
|
||||
*
|
||||
* These devices were made by both Microsoft and Logitech. At
|
||||
* first, Microsoft used the same protocol as Logitech, but did
|
||||
* switch to their new protocol for their InPort interface. So,
|
||||
* although alike enough to be handled in the same driver, they
|
||||
* are not the same.
|
||||
*
|
||||
* This code is based on my Minix driver for the Logitech(-mode)
|
||||
* interface. Although that driver blindly took IRQ5, the board
|
||||
* seems to be able to tell the driver what IRQ it is set for.
|
||||
* When testing on MS-DOS (6.22), the 'mouse.exe' driver did not
|
||||
* want to start, and only after disassembling it and inspecting
|
||||
* the code it was discovered that driver actually does use the
|
||||
* IRQ reporting feature. In a really, really weird way, too: it
|
||||
* sets up the board, and then reads the CTRL register which is
|
||||
* supposed to return that IRQ value. Depending on whether or
|
||||
* not the FREEZE bit is set, it has to return either the two's
|
||||
* complemented (negated) value, or (if clear) just the value.
|
||||
* The mouse.com driver reads both values 10,000 times, and
|
||||
* then makes up its mind. Maybe an effort to 'debounce' the
|
||||
* reading of the DIP switches? Oh-well.
|
||||
*
|
||||
* NOTES: Verified with:
|
||||
* AMI WinBIOS 486 (5A, no IRQ detect, OK, IRQ5 only)
|
||||
* Microsoft Mouse.com V2.00 (DOS V6.22, 5A, OK)
|
||||
* Microsoft Mouse.exe V9.1 (DOS V6.22, A5, OK)
|
||||
* Logitech LMouse.com V6.02 (DOS V6.22)
|
||||
* Logitech LMouse.com V6.43 (DOS V6.22)
|
||||
* Microsoft WfW V3.11 on DOS V6.22
|
||||
* GEOS V1.0 (OK, IRQ5 only)
|
||||
* GEOS V2.0 (OK, IRQ5 only)
|
||||
* Microsoft Windows 95 OSR2
|
||||
* Microsoft Windows 98 SE
|
||||
* Microsoft Windows NT 3.1
|
||||
* Microsoft Windows NT 3.51
|
||||
*
|
||||
* The polling frequency for InPort controllers has to
|
||||
* be changed to programmable. Microsoft uses 30Hz,
|
||||
* but ATIXL ports are programmable 30-200Hz.
|
||||
*
|
||||
* Based on an early driver for MINIX 1.5.
|
||||
*
|
||||
* Version: @(#)mouse_bus.c 1.0.38 2018/05/23
|
||||
*
|
||||
* Authors: Fred N. van Kempen, <decwiz@yahoo.com>
|
||||
*
|
||||
* Copyright 1989-2018 Fred N. van Kempen.
|
||||
*/
|
||||
#include <inttypes.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <wchar.h>
|
||||
#define HAVE_STDARG_H
|
||||
#include "86box.h"
|
||||
#include "config.h"
|
||||
#include "io.h"
|
||||
#include "pic.h"
|
||||
#include "timer.h"
|
||||
#include "device.h"
|
||||
#include "mouse.h"
|
||||
|
||||
|
||||
#define MOUSE_PORT 0x023c /* default */
|
||||
#define MOUSE_IRQ 5 /* default */
|
||||
#define MOUSE_BUTTONS 2 /* default */
|
||||
#define MOUSE_DEBUG 0
|
||||
|
||||
|
||||
/* Our mouse device. */
|
||||
typedef struct mouse {
|
||||
const char *name; /* name of this device */
|
||||
int8_t type; /* type of this device */
|
||||
uint16_t base; /* I/O port base to use */
|
||||
int8_t irq; /* IRQ channel to use */
|
||||
uint16_t flags; /* device flags */
|
||||
|
||||
uint8_t r_magic, /* MAGIC register */
|
||||
r_ctrl, /* CONTROL register (WR) */
|
||||
r_conf, /* CONFIG register */
|
||||
r_cmd; /* (MS) current command */
|
||||
|
||||
uint16_t seq; /* general counter */
|
||||
|
||||
uint8_t but, /* current mouse status */
|
||||
but_last;
|
||||
uint8_t cur_but;
|
||||
int8_t x, y;
|
||||
int x_delay,
|
||||
y_delay;
|
||||
uint8_t irq_num;
|
||||
|
||||
int64_t timer; /* mouse event timer */
|
||||
|
||||
uint8_t (*read)(struct mouse *, uint16_t);
|
||||
void (*write)(struct mouse *, uint16_t, uint8_t);
|
||||
} mouse_t;
|
||||
#define FLAG_NEW 0x100 /* device is the newer variant */
|
||||
#define FLAG_INPORT 0x80 /* device is MS InPort */
|
||||
#define FLAG_3BTN 0x20 /* enable 3-button mode */
|
||||
#define FLAG_SCALED 0x10 /* enable delta scaling */
|
||||
#define FLAG_INTR 0x04 /* dev can send interrupts */
|
||||
#define FLAG_FROZEN 0x02 /* do not update counters */
|
||||
#define FLAG_ENABLED 0x01 /* dev is enabled for use */
|
||||
|
||||
|
||||
/* Definitions for Logitech. */
|
||||
#define LTMOUSE_DATA 0 /* DATA register */
|
||||
#define LTMOUSE_MAGIC 1 /* signature magic register */
|
||||
# define LTMAGIC_BYTE1 0xa5 /* most drivers use this */
|
||||
# define LTMAGIC_BYTE2 0x5a /* some drivers use this */
|
||||
#define LTMOUSE_CTRL 2 /* CTRL register */
|
||||
# define LTCTRL_FREEZE 0x80 /* do not sample when set */
|
||||
# define LTCTRL_RD_Y_HI 0x60
|
||||
# define LTCTRL_RD_Y_LO 0x40
|
||||
# define LTCTRL_RD_X_HI 0x20
|
||||
# define LTCTRL_RD_X_LO 0x00
|
||||
# define LTCTRL_RD_MASK 0x60
|
||||
# define LTCTRL_IDIS 0x10
|
||||
# define LTCTRL_IENB 0x00
|
||||
#define LTMOUSE_CONFIG 3 /* CONFIG register */
|
||||
|
||||
/* Definitions for Microsoft. */
|
||||
#define MSMOUSE_CTRL 0 /* CTRL register */
|
||||
# define MSCTRL_RESET 0x80 /* reset controller */
|
||||
# define MSCTRL_FREEZE 0x20 /* HOLD- freeze data */
|
||||
# define MSCTRL_IENB_A 0x08 /* ATIXL intr enable */
|
||||
# define MSCTRL_IENB_M 0x01 /* MS intr enable */
|
||||
# define MSCTRL_COMMAND 0x07
|
||||
# define MSCTRL_RD_Y 0x02
|
||||
# define MSCTRL_RD_X 0x01
|
||||
# define MSCTRL_RD_BUT 0x00
|
||||
#define MSMOUSE_DATA 1 /* DATA register */
|
||||
# define MSDATA_IRQ 0x16
|
||||
# define MSDATA_BASE 0x10 /* MS InPort: 30Hz */
|
||||
# define MSDATA_HZ30 0x01 /* ATIXL 30Hz */
|
||||
# define MSDATA_HZ50 0x02 /* ATIXL 50Hz */
|
||||
# define MSDATA_HZ100 0x03 /* ATIXL 100Hz */
|
||||
# define MSDATA_HZ200 0x04 /* ATIXL 200Hz */
|
||||
#define MSMOUSE_MAGIC 2 /* MAGIC register */
|
||||
# define MAGIC_MSBYTE1 0xde /* indicates MS InPort */
|
||||
# define MAGIC_MSBYTE2 0x12
|
||||
#define MSMOUSE_CONFIG 3 /* CONFIG register */
|
||||
|
||||
|
||||
#define ENABLE_MOUSE_BUS_LOG 1
|
||||
#ifdef ENABLE_MOUSE_BUS_LOG
|
||||
int mouse_bus_do_log = ENABLE_MOUSE_BUS_LOG;
|
||||
#endif
|
||||
|
||||
|
||||
static void
|
||||
mouse_bus_log(const char *format, ...)
|
||||
{
|
||||
#ifdef ENABLE_MOUSE_BUS_LOG
|
||||
va_list ap;
|
||||
|
||||
if (mouse_bus_do_log) {
|
||||
va_start(ap, format);
|
||||
pclog_ex(format, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/* Reset the controller state. */
|
||||
static void
|
||||
ms_reset(mouse_t *dev)
|
||||
{
|
||||
dev->r_ctrl = 0x00;
|
||||
dev->r_cmd = 0x00;
|
||||
|
||||
dev->seq = 0;
|
||||
|
||||
dev->x = dev->y = 0;
|
||||
dev->but = 0x00;
|
||||
|
||||
dev->flags &= 0xf0;
|
||||
dev->flags |= (FLAG_INTR | FLAG_ENABLED);
|
||||
|
||||
dev->x_delay = dev->y_delay = 0;
|
||||
|
||||
dev->cur_but = 0x00;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
ms_update_data(mouse_t *dev)
|
||||
{
|
||||
int delta_x, delta_y;
|
||||
|
||||
if (dev->x_delay > 127) {
|
||||
delta_x = 127;
|
||||
dev->x_delay -= 127;
|
||||
} else if (dev->x_delay < -128) {
|
||||
delta_x = -128;
|
||||
dev->x_delay += 128;
|
||||
} else {
|
||||
delta_x = dev->x_delay;
|
||||
dev->x_delay = 0;
|
||||
}
|
||||
|
||||
if (dev->y_delay > 127) {
|
||||
delta_y = 127;
|
||||
dev->y_delay -= 127;
|
||||
} else if (dev->y_delay < -128) {
|
||||
delta_y = -128;
|
||||
dev->x_delay += 128;
|
||||
} else {
|
||||
delta_y = dev->y_delay;
|
||||
dev->y_delay = 0;
|
||||
}
|
||||
|
||||
if (!(dev->flags & FLAG_FROZEN)) {
|
||||
dev->x = (int8_t) delta_x;
|
||||
dev->y = (int8_t) delta_y;
|
||||
dev->cur_but = dev->but;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Handle a WRITE to an InPort register. */
|
||||
static void
|
||||
ms_write(mouse_t *dev, uint16_t port, uint8_t val)
|
||||
{
|
||||
uint8_t valxor;
|
||||
|
||||
switch (port) {
|
||||
case MSMOUSE_CTRL:
|
||||
/* Bit 7 is reset. */
|
||||
if (val & MSCTRL_RESET)
|
||||
ms_reset(dev);
|
||||
|
||||
/* Bits 0-2 are the internal register index. */
|
||||
switch (val & 0x07) {
|
||||
case MSCTRL_COMMAND:
|
||||
case MSCTRL_RD_BUT:
|
||||
case MSCTRL_RD_X:
|
||||
case MSCTRL_RD_Y:
|
||||
dev->r_cmd = val & 0x07;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case MSMOUSE_DATA:
|
||||
picintc(1 << dev->irq);
|
||||
|
||||
if (val == MSDATA_IRQ)
|
||||
picint(1 << dev->irq);
|
||||
else {
|
||||
switch (dev->r_cmd) {
|
||||
case MSCTRL_COMMAND:
|
||||
valxor = (dev->r_ctrl ^ val);
|
||||
|
||||
if (valxor & MSCTRL_FREEZE) {
|
||||
if (val & MSCTRL_FREEZE) {
|
||||
/* Hold the sampling while we do something. */
|
||||
dev->flags |= FLAG_FROZEN;
|
||||
} else {
|
||||
/* Reset current state. */
|
||||
dev->flags &= ~FLAG_FROZEN;
|
||||
|
||||
dev->x = dev->y = 0;
|
||||
dev->but = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (val & (MSCTRL_IENB_M | MSCTRL_IENB_A))
|
||||
dev->flags |= FLAG_INTR;
|
||||
else
|
||||
dev->flags &= ~FLAG_INTR;
|
||||
|
||||
dev->r_ctrl = val;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case MSMOUSE_MAGIC:
|
||||
break;
|
||||
|
||||
case MSMOUSE_CONFIG:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Handle a READ from an InPort register. */
|
||||
static uint8_t
|
||||
ms_read(mouse_t *dev, uint16_t port)
|
||||
{
|
||||
uint8_t ret = 0x00;
|
||||
|
||||
switch (port) {
|
||||
case MSMOUSE_CTRL:
|
||||
ret = dev->r_ctrl;
|
||||
break;
|
||||
|
||||
case MSMOUSE_DATA:
|
||||
switch (dev->r_cmd) {
|
||||
case MSCTRL_RD_BUT:
|
||||
ret = dev->cur_but;
|
||||
if (dev->flags & FLAG_NEW)
|
||||
ret |= 0x40; /* On new InPort, always have bit 6 set. */
|
||||
break;
|
||||
|
||||
case MSCTRL_RD_X:
|
||||
ret = dev->x;
|
||||
break;
|
||||
|
||||
case MSCTRL_RD_Y:
|
||||
ret = dev->y;
|
||||
break;
|
||||
|
||||
case MSCTRL_COMMAND:
|
||||
ret = dev->r_ctrl;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case MSMOUSE_MAGIC:
|
||||
if (dev->seq & 0x01)
|
||||
ret = MAGIC_MSBYTE2;
|
||||
else
|
||||
ret = MAGIC_MSBYTE1;
|
||||
dev->seq ^= 1;
|
||||
break;
|
||||
|
||||
case MSMOUSE_CONFIG:
|
||||
/* Not really present in real hardware. */
|
||||
break;
|
||||
}
|
||||
|
||||
return(ret);
|
||||
}
|
||||
|
||||
|
||||
/* Reset the controller state. */
|
||||
static void
|
||||
lt_reset(mouse_t *dev)
|
||||
{
|
||||
dev->r_magic = 0x00;
|
||||
dev->r_ctrl = (LTCTRL_IENB);
|
||||
dev->r_conf = 0x00;
|
||||
|
||||
dev->seq = 0;
|
||||
|
||||
dev->x = dev->y = 0;
|
||||
dev->but = 0x00;
|
||||
|
||||
dev->flags &= 0xf0;
|
||||
dev->flags |= (FLAG_INTR | FLAG_ENABLED);
|
||||
|
||||
dev->irq_num = 0;
|
||||
}
|
||||
|
||||
|
||||
/* Called at 30hz */
|
||||
static void
|
||||
bm_timer(void *priv)
|
||||
{
|
||||
mouse_t *dev = (mouse_t *)priv;
|
||||
|
||||
if (dev->flags & FLAG_INPORT) {
|
||||
dev->timer = ((1000000LL * TIMER_USEC) / 30LL);
|
||||
|
||||
ms_update_data(dev);
|
||||
|
||||
if (dev->flags & FLAG_INTR)
|
||||
picint(1 << dev->irq);
|
||||
} else {
|
||||
picint(1 << dev->irq);
|
||||
|
||||
if (dev->irq_num == 5) {
|
||||
mouse_bus_log("5th IRQ, enabling mouse...\n");
|
||||
lt_reset(dev);
|
||||
dev->flags |= FLAG_ENABLED;
|
||||
}
|
||||
|
||||
if (dev->irq_num == 4) {
|
||||
mouse_bus_log("4th IRQ, going for the 5th...\n");
|
||||
dev->irq_num++;
|
||||
dev->timer = ((1000000LL * TIMER_USEC) / 30LL);
|
||||
} else {
|
||||
mouse_bus_log("IRQ before the 4th, disabling timer...\n");
|
||||
dev->timer = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Handle a WRITE to a Logitech register. */
|
||||
static void
|
||||
lt_write(mouse_t *dev, uint16_t port, uint8_t val)
|
||||
{
|
||||
uint8_t b;
|
||||
|
||||
switch (port) {
|
||||
case LTMOUSE_DATA: /* [00] data register */
|
||||
break;
|
||||
|
||||
case LTMOUSE_MAGIC: /* [01] magic data register */
|
||||
switch(val) {
|
||||
case LTMAGIC_BYTE1:
|
||||
case LTMAGIC_BYTE2:
|
||||
lt_reset(dev);
|
||||
dev->r_magic = val;
|
||||
// dev->flags |= FLAG_ENABLED;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case LTMOUSE_CTRL: /* [02] control register */
|
||||
#if 0
|
||||
if (!(dev->flags & FLAG_ENABLED)) {
|
||||
dev->irq_num++;
|
||||
dev->timer = ((1000000LL * TIMER_USEC) / 30LL);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
b = (dev->r_ctrl ^ val);
|
||||
if (b & LTCTRL_FREEZE) {
|
||||
if (val & LTCTRL_FREEZE) {
|
||||
/* Hold the sampling while we do something. */
|
||||
dev->flags |= FLAG_FROZEN;
|
||||
} else {
|
||||
/* Reset current state. */
|
||||
dev->flags &= ~FLAG_FROZEN;
|
||||
dev->x = dev->y = 0;
|
||||
if (dev->but)
|
||||
dev->but |= 0x80;
|
||||
}
|
||||
}
|
||||
|
||||
if (b & LTCTRL_IDIS) {
|
||||
/* Disable or enable interrupts. */
|
||||
if (val & LTCTRL_IDIS)
|
||||
dev->flags &= ~FLAG_INTR;
|
||||
else
|
||||
dev->flags |= FLAG_INTR;
|
||||
}
|
||||
|
||||
/* Save new register value. */
|
||||
dev->r_ctrl = val | 0x0F;
|
||||
|
||||
/* Clear any pending interrupts. */
|
||||
if (val & LTCTRL_FREEZE) {
|
||||
mouse_bus_log("Freeze: Raise IRQ %i\n", dev->irq);
|
||||
picint(1 << dev->irq); /* Microsoft MOUSE.SYS v3.0 seems to expect every freeze to send an IRQ? */
|
||||
} else {
|
||||
mouse_bus_log("No freeze: Lower IRQ %i\n", dev->irq);
|
||||
picintc(1 << dev->irq);
|
||||
}
|
||||
break;
|
||||
|
||||
case LTMOUSE_CONFIG: /* [03] config register */
|
||||
/*
|
||||
* The original Logitech design was based on using a
|
||||
* 8255 parallel I/O chip. This chip has to be set up
|
||||
* for proper operation, and this configuration data
|
||||
* is what is programmed into this register.
|
||||
*
|
||||
* A snippet of code found in the FreeBSD kernel source
|
||||
* explains the value:
|
||||
*
|
||||
* D7 = Mode set flag (1 = active)
|
||||
* D6,D5 = Mode selection (port A)
|
||||
* 00 = Mode 0 = Basic I/O
|
||||
* 01 = Mode 1 = Strobed I/O
|
||||
* 10 = Mode 2 = Bi-dir bus
|
||||
* D4 = Port A direction (1 = input)
|
||||
* D3 = Port C (upper 4 bits) direction. (1 = input)
|
||||
* D2 = Mode selection (port B & C)
|
||||
* 0 = Mode 0 = Basic I/O
|
||||
* 1 = Mode 1 = Strobed I/O
|
||||
* D1 = Port B direction (1 = input)
|
||||
* D0 = Port C (lower 4 bits) direction. (1 = input)
|
||||
*
|
||||
* So 91 means Basic I/O on all 3 ports, Port A is an input
|
||||
* port, B is an output port, C is split with upper 4 bits
|
||||
* being an output port and lower 4 bits an input port, and
|
||||
* enable the sucker. Courtesy Intel 8255 databook. Lars
|
||||
*/
|
||||
dev->r_conf = val;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
lt_read_int(mouse_t *dev)
|
||||
{
|
||||
if (!(dev->flags & FLAG_NEW))
|
||||
return 1; /* On old LogiBus, read the IRQ bits always. */
|
||||
|
||||
if (dev->flags & FLAG_INTR)
|
||||
return 1; /* On new LogiBus, read the IRQ bits if interrupts are enabled. */
|
||||
|
||||
return 0; /* Otherwise, do not. */
|
||||
}
|
||||
|
||||
|
||||
/* Handle a READ from a Logitech register. */
|
||||
static uint8_t
|
||||
lt_read(mouse_t *dev, uint16_t port)
|
||||
{
|
||||
uint8_t ret = 0xff;
|
||||
|
||||
/* The GEOS drivers actually check this. */
|
||||
if (! (dev->flags & FLAG_ENABLED)) return(ret);
|
||||
|
||||
switch (port) {
|
||||
case LTMOUSE_DATA: /* [00] data register */
|
||||
ret = 0x07;
|
||||
if (dev->but & 0x01) /* LEFT */
|
||||
ret &= ~0x04;
|
||||
if (dev->but & 0x02) /* RIGHT */
|
||||
ret &= ~0x01;
|
||||
if (dev->flags & FLAG_3BTN)
|
||||
if (dev->but & 0x04) /* MIDDLE */
|
||||
ret &= ~0x02;
|
||||
ret <<= 5;
|
||||
|
||||
switch(dev->r_ctrl & LTCTRL_RD_MASK) {
|
||||
case LTCTRL_RD_X_LO: /* X, low bits */
|
||||
ret |= (dev->x & 0x0f);
|
||||
break;
|
||||
|
||||
case LTCTRL_RD_X_HI: /* X, high bits */
|
||||
ret |= (dev->x >> 4) & 0x0f;
|
||||
break;
|
||||
|
||||
case LTCTRL_RD_Y_LO: /* Y, low bits */
|
||||
ret |= (dev->y & 0x0f);
|
||||
break;
|
||||
|
||||
case LTCTRL_RD_Y_HI: /* Y, high bits */
|
||||
ret |= (dev->y >> 4) & 0x0f;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case LTMOUSE_MAGIC: /* [01] magic data register */
|
||||
/*
|
||||
* Drivers write a magic byte to this register, usually
|
||||
* this is either 5A (AMI WinBIOS, MS Mouse 2.0) or
|
||||
* A5 (MS Mouse 9.1, Windows drivers, UNIX/Linux/Minix.)
|
||||
*/
|
||||
ret = dev->r_magic;
|
||||
break;
|
||||
|
||||
case LTMOUSE_CTRL: /* [02] control register */
|
||||
ret = dev->r_ctrl;
|
||||
dev->r_ctrl |= 0x0F;
|
||||
if ((dev->seq > 0x3FF) && lt_read_int(dev)) {
|
||||
/* !IDIS, return DIP switch setting. */
|
||||
switch(dev->irq) {
|
||||
case 2:
|
||||
dev->r_ctrl &= ~0x08;
|
||||
break;
|
||||
|
||||
case 3:
|
||||
dev->r_ctrl &= ~0x04;
|
||||
break;
|
||||
|
||||
case 4:
|
||||
dev->r_ctrl &= ~0x02;
|
||||
break;
|
||||
|
||||
case 5:
|
||||
dev->r_ctrl &= ~0x01;
|
||||
break;
|
||||
}
|
||||
}
|
||||
dev->seq = (dev->seq + 1) & 0x7ff;
|
||||
break;
|
||||
|
||||
case LTMOUSE_CONFIG: /* [03] config register */
|
||||
ret = dev->r_conf;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return(ret);
|
||||
}
|
||||
|
||||
|
||||
/* Handle a WRITE operation to one of our registers. */
|
||||
static void
|
||||
bm_write(uint16_t port, uint8_t val, void *priv)
|
||||
{
|
||||
mouse_t *dev = (mouse_t *)priv;
|
||||
|
||||
mouse_bus_log("%s: write(%d,%02x)\n", dev->name, port & 0x03, val);
|
||||
|
||||
dev->write(dev, port & 0x03, val);
|
||||
}
|
||||
|
||||
|
||||
/* Handle a READ operation from one of our registers. */
|
||||
static uint8_t
|
||||
bm_read(uint16_t port, void *priv)
|
||||
{
|
||||
mouse_t *dev = (mouse_t *)priv;
|
||||
uint8_t ret;
|
||||
|
||||
ret = dev->read(dev, port & 0x03);
|
||||
|
||||
mouse_bus_log("%s: read(%d): %02x\n", dev->name, port & 0x03, ret);
|
||||
|
||||
return(ret);
|
||||
}
|
||||
|
||||
|
||||
/* The emulator calls us with an update on the host mouse device. */
|
||||
static int
|
||||
bm_poll(int x, int y, int z, int b, void *priv)
|
||||
{
|
||||
uint8_t b_last;
|
||||
mouse_t *dev = (mouse_t *)priv;
|
||||
|
||||
b_last = dev->but;
|
||||
|
||||
/* Return early if nothing to do. */
|
||||
if (!x && !y && !z && (dev->but == b))
|
||||
return(1);
|
||||
|
||||
/* If we are not enabled, return. */
|
||||
if (! (dev->flags & FLAG_ENABLED))
|
||||
mouse_bus_log("bm_poll(): Mouse not enabled\n");
|
||||
|
||||
if (dev->flags & FLAG_SCALED) {
|
||||
/* Scale down the motion. */
|
||||
if ((x < -1) || (x > 1)) x >>= 1;
|
||||
if ((y < -1) || (y > 1)) y >>= 1;
|
||||
}
|
||||
|
||||
if (dev->flags & FLAG_INPORT) {
|
||||
if (x || y || z)
|
||||
dev->but = 0x40; /* Mouse has moved. */
|
||||
else
|
||||
dev->but = 0x00;
|
||||
|
||||
if (x > 127) x = 127;
|
||||
if (y > 127) y = 127;
|
||||
if (x < -128) x = -128;
|
||||
if (y < -128) y = -128;
|
||||
|
||||
dev->x_delay += x;
|
||||
dev->y_delay += y;
|
||||
dev->but |= (uint8_t) (((b & 1) << 2) | ((b & 2) >> 1));
|
||||
if (dev->flags & FLAG_3BTN)
|
||||
dev->but |= ((b & 4) >> 1);
|
||||
|
||||
if ((b_last ^ dev->but) & 0x04)
|
||||
dev->but |= 0x20; /* Left button state has changed. */
|
||||
if (((b_last ^ dev->but) & 0x02) && (dev->flags & FLAG_3BTN))
|
||||
dev->but |= 0x10; /* Middle button state has changed. */
|
||||
if ((b_last ^ dev->but) & 0x01)
|
||||
dev->but |= 0x08; /* Right button state has changed. */
|
||||
|
||||
dev->but |= 0x80; /* Packet complete. */
|
||||
} else {
|
||||
/* If we are frozen, do not update the state. */
|
||||
if (! (dev->flags & FLAG_FROZEN)) {
|
||||
/* Add the delta to our state. */
|
||||
x += dev->x;
|
||||
if (x > 127)
|
||||
x = 127;
|
||||
if (x < -128)
|
||||
x = -128;
|
||||
dev->x = (int8_t)x;
|
||||
|
||||
y += dev->y;
|
||||
if (y > 127)
|
||||
y = 127;
|
||||
if (y < -1287)
|
||||
y = -1287;
|
||||
dev->y = (int8_t)y;
|
||||
|
||||
dev->x_delay += x;
|
||||
dev->y_delay += y;
|
||||
|
||||
dev->but = b;
|
||||
}
|
||||
|
||||
/* Either way, generate an interrupt. */
|
||||
if ((dev->flags & FLAG_INTR) && !(dev->flags & FLAG_INPORT))
|
||||
picint(1 << dev->irq);
|
||||
}
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
/* Release all resources held by the device. */
|
||||
static void
|
||||
bm_close(void *priv)
|
||||
{
|
||||
mouse_t *dev = (mouse_t *)priv;
|
||||
|
||||
/* Release our I/O range. */
|
||||
io_removehandler(dev->base, 4,
|
||||
bm_read, NULL, NULL, bm_write, NULL, NULL, dev);
|
||||
|
||||
free(dev);
|
||||
}
|
||||
|
||||
|
||||
/* Initialize the device for use by the user. */
|
||||
static void *
|
||||
bm_init(const device_t *info)
|
||||
{
|
||||
mouse_t *dev;
|
||||
int i, j;
|
||||
|
||||
dev = (mouse_t *)malloc(sizeof(mouse_t));
|
||||
memset(dev, 0x00, sizeof(mouse_t));
|
||||
dev->name = info->name;
|
||||
dev->type = info->local;
|
||||
dev->base = device_get_config_hex16("base");
|
||||
dev->irq = device_get_config_int("irq");
|
||||
i = device_get_config_int("buttons");
|
||||
if (i > 2)
|
||||
dev->flags |= FLAG_3BTN;
|
||||
j = device_get_config_int("model");
|
||||
if (j)
|
||||
dev->flags |= FLAG_NEW;
|
||||
|
||||
switch(dev->type) {
|
||||
case MOUSE_TYPE_LOGIBUS:
|
||||
lt_reset(dev);
|
||||
|
||||
/* Initialize I/O handlers. */
|
||||
dev->read = lt_read;
|
||||
dev->write = lt_write;
|
||||
|
||||
// dev->timer = 0;
|
||||
// timer_add(bm_timer, &dev->timer, &dev->timer, dev);
|
||||
break;
|
||||
|
||||
case MOUSE_TYPE_INPORT:
|
||||
dev->flags |= FLAG_INPORT;
|
||||
ms_reset(dev);
|
||||
|
||||
/* Initialize I/O handlers. */
|
||||
dev->read = ms_read;
|
||||
dev->write = ms_write;
|
||||
|
||||
dev->timer = (33334LL * TIMER_USEC);
|
||||
timer_add(bm_timer, &dev->timer, TIMER_ALWAYS_ENABLED, dev);
|
||||
break;
|
||||
}
|
||||
|
||||
/* Request an I/O range. */
|
||||
io_sethandler(dev->base, 4,
|
||||
bm_read, NULL, NULL, bm_write, NULL, NULL, dev);
|
||||
|
||||
mouse_bus_log("%s: I/O=%04x, IRQ=%d, buttons=%d, model=%s\n",
|
||||
dev->name, dev->base, dev->irq, i, j ? "new" : "old");
|
||||
|
||||
/* Tell them how many buttons we have. */
|
||||
mouse_set_buttons((dev->flags & FLAG_3BTN) ? 3 : 2);
|
||||
|
||||
/* Return our private data to the I/O layer. */
|
||||
return(dev);
|
||||
}
|
||||
|
||||
|
||||
static const device_config_t bm_config[] = {
|
||||
{
|
||||
"base", "Address", CONFIG_HEX16, "", MOUSE_PORT,
|
||||
{
|
||||
{
|
||||
"0x230", 0x230
|
||||
},
|
||||
{
|
||||
"0x234", 0x234
|
||||
},
|
||||
{
|
||||
"0x238", 0x238
|
||||
},
|
||||
{
|
||||
"0x23C", 0x23c
|
||||
},
|
||||
{
|
||||
""
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"irq", "IRQ", CONFIG_SELECTION, "", MOUSE_IRQ, {
|
||||
{
|
||||
"IRQ 2", 2
|
||||
},
|
||||
{
|
||||
"IRQ 3", 3
|
||||
},
|
||||
{
|
||||
"IRQ 4", 4
|
||||
},
|
||||
{
|
||||
"IRQ 5", 5
|
||||
},
|
||||
{
|
||||
""
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"buttons", "Buttons", CONFIG_SELECTION, "", MOUSE_BUTTONS, {
|
||||
{
|
||||
"Two", 2
|
||||
},
|
||||
{
|
||||
"Three", 3
|
||||
},
|
||||
{
|
||||
""
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"model", "Model", CONFIG_SELECTION, "", 0, {
|
||||
{
|
||||
"Old", 0
|
||||
},
|
||||
{
|
||||
"New", 1
|
||||
},
|
||||
{
|
||||
""
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"", "", -1
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
const device_t mouse_logibus_device = {
|
||||
"Logitech Bus Mouse",
|
||||
DEVICE_ISA,
|
||||
MOUSE_TYPE_LOGIBUS,
|
||||
bm_init, bm_close, NULL,
|
||||
bm_poll, NULL, NULL,
|
||||
bm_config
|
||||
};
|
||||
|
||||
const device_t mouse_msinport_device = {
|
||||
"Microsoft Bus Mouse (InPort)",
|
||||
DEVICE_ISA,
|
||||
MOUSE_TYPE_INPORT,
|
||||
bm_init, bm_close, NULL,
|
||||
bm_poll, NULL, NULL,
|
||||
bm_config
|
||||
};
|
||||
795
backup code/mouse_bus_x.c
Normal file
795
backup code/mouse_bus_x.c
Normal file
@@ -0,0 +1,795 @@
|
||||
/*
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
*
|
||||
* This file is part of the 86Box distribution.
|
||||
*
|
||||
* Implementation of Bus Mouse devices.
|
||||
*
|
||||
* These devices were made by both Microsoft and Logitech. At
|
||||
* first, Microsoft used the same protocol as Logitech, but did
|
||||
* switch to their new protocol for their InPort interface. So,
|
||||
* although alike enough to be handled in the same driver, they
|
||||
* are not the same.
|
||||
*
|
||||
* This code is based on my Minix driver for the Logitech(-mode)
|
||||
* interface. Although that driver blindly took IRQ5, the board
|
||||
* seems to be able to tell the driver what IRQ it is set for.
|
||||
* When testing on MS-DOS (6.22), the 'mouse.exe' driver did not
|
||||
* want to start, and only after disassembling it and inspecting
|
||||
* the code it was discovered that driver actually does use the
|
||||
* IRQ reporting feature. In a really, really weird way, too: it
|
||||
* sets up the board, and then reads the CTRL register which is
|
||||
* supposed to return that IRQ value. Depending on whether or
|
||||
* not the FREEZE bit is set, it has to return either the two's
|
||||
* complemented (negated) value, or (if clear) just the value.
|
||||
* The mouse.com driver reads both values 10,000 times, and
|
||||
* then makes up its mind. Maybe an effort to 'debounce' the
|
||||
* reading of the DIP switches? Oh-well.
|
||||
*
|
||||
* NOTES: Verified with:
|
||||
* AMI WinBIOS 486 (5A, no IRQ detect, OK, IRQ5 only)
|
||||
* Microsoft Mouse.com V2.00 (DOS V6.22, 5A, OK)
|
||||
* Microsoft Mouse.exe V9.1 (DOS V6.22, A5, OK)
|
||||
* Logitech LMouse.com V6.02 (DOS V6.22)
|
||||
* Logitech LMouse.com V6.43 (DOS V6.22)
|
||||
* Microsoft WfW V3.11 on DOS V6.22
|
||||
* GEOS V1.0 (OK, IRQ5 only)
|
||||
* GEOS V2.0 (OK, IRQ5 only)
|
||||
* Microsoft Windows 95 OSR2
|
||||
* Microsoft Windows 98 SE
|
||||
* Microsoft Windows NT 3.1
|
||||
* Microsoft Windows NT 3.51
|
||||
*
|
||||
* The polling frequency for InPort controllers has to
|
||||
* be changed to programmable. Microsoft uses 30Hz,
|
||||
* but ATIXL ports are programmable 30-200Hz.
|
||||
*
|
||||
* Based on an early driver for MINIX 1.5.
|
||||
*
|
||||
* Version: @(#)mouse_bus.c 1.0.39 2018/05/24
|
||||
*
|
||||
* Authors: Fred N. van Kempen, <decwiz@yahoo.com>
|
||||
*
|
||||
* Copyright 1989-2018 Fred N. van Kempen.
|
||||
*/
|
||||
#include <inttypes.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <wchar.h>
|
||||
#define HAVE_STDARG_H
|
||||
#include "86box.h"
|
||||
#include "config.h"
|
||||
#include "io.h"
|
||||
#include "pic.h"
|
||||
#include "timer.h"
|
||||
#include "device.h"
|
||||
#include "mouse.h"
|
||||
|
||||
|
||||
#define MOUSE_PORT 0x023c /* default */
|
||||
#define MOUSE_IRQ 5 /* default */
|
||||
#define MOUSE_BUTTONS 2 /* default */
|
||||
#define MOUSE_DEBUG 0
|
||||
|
||||
|
||||
/* Our mouse device. */
|
||||
typedef struct mouse {
|
||||
const char *name; /* name of this device */
|
||||
int8_t type; /* type of this device */
|
||||
uint16_t base; /* I/O port base to use */
|
||||
int8_t irq; /* IRQ channel to use */
|
||||
uint16_t flags; /* device flags */
|
||||
|
||||
uint8_t r_magic, /* MAGIC register */
|
||||
r_ctrl, /* CONTROL register (WR) */
|
||||
r_conf, /* CONFIG register */
|
||||
r_cmd; /* (MS) current command */
|
||||
|
||||
uint16_t seq; /* general counter */
|
||||
|
||||
uint8_t but, /* current mouse status */
|
||||
but_last;
|
||||
uint8_t cur_but;
|
||||
int8_t x, y;
|
||||
int x_delay,
|
||||
y_delay;
|
||||
uint8_t irq_num;
|
||||
|
||||
int64_t timer; /* mouse event timer */
|
||||
|
||||
uint8_t (*read)(struct mouse *, uint16_t);
|
||||
void (*write)(struct mouse *, uint16_t, uint8_t);
|
||||
} mouse_t;
|
||||
#define FLAG_NEW 0x100 /* device is the newer variant */
|
||||
#define FLAG_INPORT 0x80 /* device is MS InPort */
|
||||
#define FLAG_3BTN 0x20 /* enable 3-button mode */
|
||||
#define FLAG_SCALED 0x10 /* enable delta scaling */
|
||||
#define FLAG_INTR 0x04 /* dev can send interrupts */
|
||||
#define FLAG_FROZEN 0x02 /* do not update counters */
|
||||
#define FLAG_ENABLED 0x01 /* dev is enabled for use */
|
||||
|
||||
|
||||
/* Definitions for Logitech. */
|
||||
#define LTMOUSE_DATA 0 /* DATA register */
|
||||
#define LTMOUSE_MAGIC 1 /* signature magic register */
|
||||
# define LTMAGIC_BYTE1 0xa5 /* most drivers use this */
|
||||
# define LTMAGIC_BYTE2 0x5a /* some drivers use this */
|
||||
#define LTMOUSE_CTRL 2 /* CTRL register */
|
||||
# define LTCTRL_FREEZE 0x80 /* do not sample when set */
|
||||
# define LTCTRL_RD_Y_HI 0x60
|
||||
# define LTCTRL_RD_Y_LO 0x40
|
||||
# define LTCTRL_RD_X_HI 0x20
|
||||
# define LTCTRL_RD_X_LO 0x00
|
||||
# define LTCTRL_RD_MASK 0x60
|
||||
# define LTCTRL_IDIS 0x10
|
||||
# define LTCTRL_IENB 0x00
|
||||
#define LTMOUSE_CONFIG 3 /* CONFIG register */
|
||||
|
||||
/* Definitions for Microsoft. */
|
||||
#define MSMOUSE_CTRL 0 /* CTRL register */
|
||||
# define MSCTRL_RESET 0x80 /* reset controller */
|
||||
# define MSCTRL_FREEZE 0x20 /* HOLD- freeze data */
|
||||
# define MSCTRL_IENB_A 0x08 /* ATIXL intr enable */
|
||||
# define MSCTRL_IENB_M 0x01 /* MS intr enable */
|
||||
# define MSCTRL_COMMAND 0x07
|
||||
# define MSCTRL_RD_Y 0x02
|
||||
# define MSCTRL_RD_X 0x01
|
||||
# define MSCTRL_RD_BUT 0x00
|
||||
#define MSMOUSE_DATA 1 /* DATA register */
|
||||
# define MSDATA_IRQ 0x16
|
||||
# define MSDATA_BASE 0x10 /* MS InPort: 30Hz */
|
||||
# define MSDATA_HZ30 0x01 /* ATIXL 30Hz */
|
||||
# define MSDATA_HZ50 0x02 /* ATIXL 50Hz */
|
||||
# define MSDATA_HZ100 0x03 /* ATIXL 100Hz */
|
||||
# define MSDATA_HZ200 0x04 /* ATIXL 200Hz */
|
||||
#define MSMOUSE_MAGIC 2 /* MAGIC register */
|
||||
# define MAGIC_MSBYTE1 0xde /* indicates MS InPort */
|
||||
# define MAGIC_MSBYTE2 0x12
|
||||
#define MSMOUSE_CONFIG 3 /* CONFIG register */
|
||||
|
||||
|
||||
#define ENABLE_MOUSE_BUS_LOG 1
|
||||
#ifdef ENABLE_MOUSE_BUS_LOG
|
||||
int mouse_bus_do_log = ENABLE_MOUSE_BUS_LOG;
|
||||
#endif
|
||||
|
||||
|
||||
static void
|
||||
mouse_bus_log(const char *format, ...)
|
||||
{
|
||||
#ifdef ENABLE_MOUSE_BUS_LOG
|
||||
va_list ap;
|
||||
|
||||
if (mouse_bus_do_log) {
|
||||
va_start(ap, format);
|
||||
pclog_ex(format, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/* Reset the controller state. */
|
||||
static void
|
||||
ms_reset(mouse_t *dev)
|
||||
{
|
||||
dev->r_ctrl = 0x00;
|
||||
dev->r_cmd = 0x00;
|
||||
|
||||
dev->seq = 0;
|
||||
|
||||
dev->x = dev->y = 0;
|
||||
dev->but = 0x00;
|
||||
|
||||
dev->flags &= 0xf0;
|
||||
dev->flags |= (FLAG_INTR | FLAG_ENABLED);
|
||||
|
||||
dev->x_delay = dev->y_delay = 0;
|
||||
|
||||
dev->cur_but = 0x00;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
bm_update_data(mouse_t *dev)
|
||||
{
|
||||
int delta_x, delta_y;
|
||||
|
||||
if (dev->x_delay > 127) {
|
||||
delta_x = 127;
|
||||
dev->x_delay -= 127;
|
||||
} else if (dev->x_delay < -128) {
|
||||
delta_x = -128;
|
||||
dev->x_delay += 128;
|
||||
} else {
|
||||
delta_x = dev->x_delay;
|
||||
dev->x_delay = 0;
|
||||
}
|
||||
|
||||
if (dev->y_delay > 127) {
|
||||
delta_y = 127;
|
||||
dev->y_delay -= 127;
|
||||
} else if (dev->y_delay < -128) {
|
||||
delta_y = -128;
|
||||
dev->x_delay += 128;
|
||||
} else {
|
||||
delta_y = dev->y_delay;
|
||||
dev->y_delay = 0;
|
||||
}
|
||||
|
||||
if (!(dev->flags & FLAG_FROZEN)) {
|
||||
dev->x = (int8_t) delta_x;
|
||||
dev->y = (int8_t) delta_y;
|
||||
dev->cur_but = dev->but;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Handle a WRITE to an InPort register. */
|
||||
static void
|
||||
ms_write(mouse_t *dev, uint16_t port, uint8_t val)
|
||||
{
|
||||
uint8_t valxor;
|
||||
|
||||
switch (port) {
|
||||
case MSMOUSE_CTRL:
|
||||
/* Bit 7 is reset. */
|
||||
if (val & MSCTRL_RESET)
|
||||
ms_reset(dev);
|
||||
|
||||
/* Bits 0-2 are the internal register index. */
|
||||
switch (val & 0x07) {
|
||||
case MSCTRL_COMMAND:
|
||||
case MSCTRL_RD_BUT:
|
||||
case MSCTRL_RD_X:
|
||||
case MSCTRL_RD_Y:
|
||||
dev->r_cmd = val & 0x07;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case MSMOUSE_DATA:
|
||||
picintc(1 << dev->irq);
|
||||
|
||||
if (val == MSDATA_IRQ)
|
||||
picint(1 << dev->irq);
|
||||
else {
|
||||
switch (dev->r_cmd) {
|
||||
case MSCTRL_COMMAND:
|
||||
valxor = (dev->r_ctrl ^ val);
|
||||
|
||||
if (valxor & MSCTRL_FREEZE) {
|
||||
if (val & MSCTRL_FREEZE) {
|
||||
/* Hold the sampling while we do something. */
|
||||
dev->flags |= FLAG_FROZEN;
|
||||
} else {
|
||||
/* Reset current state. */
|
||||
dev->flags &= ~FLAG_FROZEN;
|
||||
|
||||
dev->x = dev->y = 0;
|
||||
dev->but = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (val & (MSCTRL_IENB_M | MSCTRL_IENB_A))
|
||||
dev->flags |= FLAG_INTR;
|
||||
else
|
||||
dev->flags &= ~FLAG_INTR;
|
||||
|
||||
dev->r_ctrl = val;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case MSMOUSE_MAGIC:
|
||||
break;
|
||||
|
||||
case MSMOUSE_CONFIG:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Handle a READ from an InPort register. */
|
||||
static uint8_t
|
||||
ms_read(mouse_t *dev, uint16_t port)
|
||||
{
|
||||
uint8_t ret = 0x00;
|
||||
|
||||
switch (port) {
|
||||
case MSMOUSE_CTRL:
|
||||
ret = dev->r_ctrl;
|
||||
break;
|
||||
|
||||
case MSMOUSE_DATA:
|
||||
switch (dev->r_cmd) {
|
||||
case MSCTRL_RD_BUT:
|
||||
ret = dev->cur_but;
|
||||
if (dev->flags & FLAG_NEW)
|
||||
ret |= 0x40; /* On new InPort, always have bit 6 set. */
|
||||
break;
|
||||
|
||||
case MSCTRL_RD_X:
|
||||
ret = dev->x;
|
||||
break;
|
||||
|
||||
case MSCTRL_RD_Y:
|
||||
ret = dev->y;
|
||||
break;
|
||||
|
||||
case MSCTRL_COMMAND:
|
||||
ret = dev->r_ctrl;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case MSMOUSE_MAGIC:
|
||||
if (dev->seq & 0x01)
|
||||
ret = MAGIC_MSBYTE2;
|
||||
else
|
||||
ret = MAGIC_MSBYTE1;
|
||||
dev->seq ^= 1;
|
||||
break;
|
||||
|
||||
case MSMOUSE_CONFIG:
|
||||
/* Not really present in real hardware. */
|
||||
break;
|
||||
}
|
||||
|
||||
return(ret);
|
||||
}
|
||||
|
||||
|
||||
/* Reset the controller state. */
|
||||
static void
|
||||
lt_reset(mouse_t *dev)
|
||||
{
|
||||
dev->r_ctrl = (LTCTRL_IENB) | 0x0f;
|
||||
dev->r_conf = 0x0e;
|
||||
dev->r_magic = 0x00;
|
||||
|
||||
dev->seq = 0;
|
||||
dev->flags &= 0xf0;
|
||||
dev->flags |= FLAG_INTR;
|
||||
|
||||
dev->x = dev->y = 0;
|
||||
dev->but = 0x00;
|
||||
|
||||
dev->irq_num = 0;
|
||||
}
|
||||
|
||||
|
||||
/* Called at 30hz */
|
||||
static void
|
||||
bm_timer(void *priv)
|
||||
{
|
||||
mouse_t *dev = (mouse_t *)priv;
|
||||
|
||||
if (dev->flags & FLAG_INPORT)
|
||||
dev->timer = ((1000000LL * TIMER_USEC) / 30LL);
|
||||
else
|
||||
dev->timer = ((1000000LL * TIMER_USEC) / 200LL);
|
||||
|
||||
bm_update_data(dev);
|
||||
|
||||
if (dev->flags & FLAG_INTR) {
|
||||
picint(1 << dev->irq);
|
||||
mouse_bus_log("Mouse IRQ %i\n", dev->irq);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Handle a WRITE to a Logitech register. */
|
||||
static void
|
||||
lt_write(mouse_t *dev, uint16_t port, uint8_t val)
|
||||
{
|
||||
uint8_t b;
|
||||
|
||||
switch (port) {
|
||||
case LTMOUSE_DATA: /* [00] data register */
|
||||
break;
|
||||
|
||||
case LTMOUSE_MAGIC: /* [01] magic data register */
|
||||
dev->r_magic = val;
|
||||
break;
|
||||
|
||||
case LTMOUSE_CTRL: /* [02] control register */
|
||||
b = (dev->r_ctrl ^ val);
|
||||
if (b & LTCTRL_FREEZE) {
|
||||
if (val & LTCTRL_FREEZE) {
|
||||
/* Hold the sampling while we do something. */
|
||||
dev->flags |= FLAG_FROZEN;
|
||||
} else {
|
||||
/* Reset current state. */
|
||||
dev->flags &= ~FLAG_FROZEN;
|
||||
dev->x = dev->y = 0;
|
||||
if (dev->but)
|
||||
dev->but |= 0x80;
|
||||
}
|
||||
}
|
||||
|
||||
if (b & LTCTRL_IDIS) {
|
||||
/* Disable or enable interrupts. */
|
||||
if (val & LTCTRL_IDIS)
|
||||
dev->flags &= ~FLAG_INTR;
|
||||
else
|
||||
dev->flags |= FLAG_INTR;
|
||||
}
|
||||
|
||||
/* Save new register value. */
|
||||
dev->r_ctrl = val | 0x0F;
|
||||
|
||||
/* Clear any pending interrupts. */
|
||||
picintc(1 << dev->irq);
|
||||
break;
|
||||
|
||||
case LTMOUSE_CONFIG: /* [03] config register */
|
||||
/*
|
||||
* The original Logitech design was based on using a
|
||||
* 8255 parallel I/O chip. This chip has to be set up
|
||||
* for proper operation, and this configuration data
|
||||
* is what is programmed into this register.
|
||||
*
|
||||
* A snippet of code found in the FreeBSD kernel source
|
||||
* explains the value:
|
||||
*
|
||||
* D7 = Mode set flag (1 = active)
|
||||
* D6,D5 = Mode selection (port A)
|
||||
* 00 = Mode 0 = Basic I/O
|
||||
* 01 = Mode 1 = Strobed I/O
|
||||
* 10 = Mode 2 = Bi-dir bus
|
||||
* D4 = Port A direction (1 = input)
|
||||
* D3 = Port C (upper 4 bits) direction. (1 = input)
|
||||
* D2 = Mode selection (port B & C)
|
||||
* 0 = Mode 0 = Basic I/O
|
||||
* 1 = Mode 1 = Strobed I/O
|
||||
* D1 = Port B direction (1 = input)
|
||||
* D0 = Port C (lower 4 bits) direction. (1 = input)
|
||||
*
|
||||
* So 91 means Basic I/O on all 3 ports, Port A is an input
|
||||
* port, B is an output port, C is split with upper 4 bits
|
||||
* being an output port and lower 4 bits an input port, and
|
||||
* enable the sucker. Courtesy Intel 8255 databook. Lars
|
||||
*/
|
||||
dev->r_conf = val;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
lt_read_int(mouse_t *dev)
|
||||
{
|
||||
if (!(dev->flags & FLAG_NEW))
|
||||
return 1; /* On old LogiBus, read the IRQ bits always. */
|
||||
|
||||
if (dev->flags & FLAG_INTR)
|
||||
return 1; /* On new LogiBus, read the IRQ bits if interrupts are enabled. */
|
||||
|
||||
return 0; /* Otherwise, do not. */
|
||||
}
|
||||
|
||||
|
||||
/* Handle a READ from a Logitech register. */
|
||||
static uint8_t
|
||||
lt_read(mouse_t *dev, uint16_t port)
|
||||
{
|
||||
uint8_t ret = 0xff;
|
||||
|
||||
/* The GEOS drivers actually check this. */
|
||||
if (! (dev->flags & FLAG_ENABLED)) return(ret);
|
||||
|
||||
switch (port) {
|
||||
case LTMOUSE_DATA: /* [00] data register */
|
||||
ret = 0x07;
|
||||
if (dev->cur_but & 0x01) /* LEFT */
|
||||
ret &= ~0x04;
|
||||
if (dev->cur_but & 0x02) /* RIGHT */
|
||||
ret &= ~0x01;
|
||||
if (dev->flags & FLAG_3BTN)
|
||||
if (dev->cur_but & 0x04) /* MIDDLE */
|
||||
ret &= ~0x02;
|
||||
ret <<= 5;
|
||||
|
||||
switch(dev->r_ctrl & LTCTRL_RD_MASK) {
|
||||
case LTCTRL_RD_X_LO: /* X, low bits */
|
||||
ret |= (dev->x & 0x0f);
|
||||
break;
|
||||
|
||||
case LTCTRL_RD_X_HI: /* X, high bits */
|
||||
ret |= (dev->x >> 4) & 0x0f;
|
||||
break;
|
||||
|
||||
case LTCTRL_RD_Y_LO: /* Y, low bits */
|
||||
ret |= (dev->y & 0x0f);
|
||||
break;
|
||||
|
||||
case LTCTRL_RD_Y_HI: /* Y, high bits */
|
||||
ret |= (dev->y >> 4) & 0x0f;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case LTMOUSE_MAGIC: /* [01] magic data register */
|
||||
/*
|
||||
* Drivers write a magic byte to this register, usually
|
||||
* this is either 5A (AMI WinBIOS, MS Mouse 2.0) or
|
||||
* A5 (MS Mouse 9.1, Windows drivers, UNIX/Linux/Minix.)
|
||||
*/
|
||||
ret = dev->r_magic;
|
||||
break;
|
||||
|
||||
case LTMOUSE_CTRL: /* [02] control register */
|
||||
ret = dev->r_ctrl;
|
||||
dev->r_ctrl |= 0x0F;
|
||||
if ((dev->seq > 0x3FF) && lt_read_int(dev))
|
||||
dev->r_ctrl &= ~((1 << 5) >> dev->irq);
|
||||
dev->seq = (dev->seq + 1) & 0x7ff;
|
||||
break;
|
||||
|
||||
case LTMOUSE_CONFIG: /* [03] config register */
|
||||
ret = dev->r_conf;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return(ret);
|
||||
}
|
||||
|
||||
|
||||
/* Handle a WRITE operation to one of our registers. */
|
||||
static void
|
||||
bm_write(uint16_t port, uint8_t val, void *priv)
|
||||
{
|
||||
mouse_t *dev = (mouse_t *)priv;
|
||||
|
||||
mouse_bus_log("%s: write(%d,%02x)\n", dev->name, port & 0x03, val);
|
||||
|
||||
dev->write(dev, port & 0x03, val);
|
||||
}
|
||||
|
||||
|
||||
/* Handle a READ operation from one of our registers. */
|
||||
static uint8_t
|
||||
bm_read(uint16_t port, void *priv)
|
||||
{
|
||||
mouse_t *dev = (mouse_t *)priv;
|
||||
uint8_t ret;
|
||||
|
||||
ret = dev->read(dev, port & 0x03);
|
||||
|
||||
mouse_bus_log("%s: read(%d): %02x\n", dev->name, port & 0x03, ret);
|
||||
|
||||
return(ret);
|
||||
}
|
||||
|
||||
|
||||
/* The emulator calls us with an update on the host mouse device. */
|
||||
static int
|
||||
bm_poll(int x, int y, int z, int b, void *priv)
|
||||
{
|
||||
uint8_t b_last;
|
||||
mouse_t *dev = (mouse_t *)priv;
|
||||
|
||||
b_last = dev->but;
|
||||
|
||||
if (dev->flags & FLAG_INPORT) {
|
||||
if (x || y || z)
|
||||
dev->but = 0x40; /* Mouse has moved. */
|
||||
else
|
||||
dev->but = 0x00;
|
||||
} else
|
||||
dev->but = 0x00;
|
||||
|
||||
if (dev->flags & FLAG_SCALED) {
|
||||
/* Scale down the motion. */
|
||||
if ((x < -1) || (x > 1)) x >>= 1;
|
||||
if ((y < -1) || (y > 1)) y >>= 1;
|
||||
}
|
||||
|
||||
if (x > 127) x = 127;
|
||||
if (y > 127) y = 127;
|
||||
if (x < -128) x = -128;
|
||||
if (y < -128) y = -128;
|
||||
|
||||
dev->x_delay += x;
|
||||
dev->y_delay += y;
|
||||
|
||||
/* Change button state MRL to LMR */
|
||||
dev->but |= (uint8_t) (((b & 1) << 2) | ((b & 2) >> 1));
|
||||
if (dev->flags & FLAG_3BTN)
|
||||
dev->but |= ((b & 4) >> 1);
|
||||
|
||||
if (dev->flags & FLAG_INPORT) {
|
||||
if ((b_last ^ dev->but) & 0x04)
|
||||
dev->but |= 0x20; /* Left button state has changed. */
|
||||
if (((b_last ^ dev->but) & 0x02) && (dev->flags & FLAG_3BTN))
|
||||
dev->but |= 0x10; /* Middle button state has changed. */
|
||||
if ((b_last ^ dev->but) & 0x01)
|
||||
dev->but |= 0x08; /* Right button state has changed. */
|
||||
|
||||
dev->but |= 0x80; /* Packet complete. */
|
||||
}
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
/* Release all resources held by the device. */
|
||||
static void
|
||||
bm_close(void *priv)
|
||||
{
|
||||
mouse_t *dev = (mouse_t *)priv;
|
||||
|
||||
/* Release our I/O range. */
|
||||
io_removehandler(dev->base, 4,
|
||||
bm_read, NULL, NULL, bm_write, NULL, NULL, dev);
|
||||
|
||||
free(dev);
|
||||
}
|
||||
|
||||
|
||||
/* Initialize the device for use by the user. */
|
||||
static void *
|
||||
bm_init(const device_t *info)
|
||||
{
|
||||
mouse_t *dev;
|
||||
int i, j;
|
||||
|
||||
dev = (mouse_t *)malloc(sizeof(mouse_t));
|
||||
memset(dev, 0x00, sizeof(mouse_t));
|
||||
dev->name = info->name;
|
||||
dev->type = info->local;
|
||||
dev->base = device_get_config_hex16("base");
|
||||
dev->irq = device_get_config_int("irq");
|
||||
i = device_get_config_int("buttons");
|
||||
if (i > 2)
|
||||
dev->flags |= FLAG_3BTN;
|
||||
j = device_get_config_int("model");
|
||||
if (j)
|
||||
dev->flags |= FLAG_NEW;
|
||||
|
||||
switch(dev->type) {
|
||||
case MOUSE_TYPE_LOGIBUS:
|
||||
lt_reset(dev);
|
||||
|
||||
/* Initialize I/O handlers. */
|
||||
dev->read = lt_read;
|
||||
dev->write = lt_write;
|
||||
|
||||
dev->timer = ((1000000LL * TIMER_USEC) / 200LL);
|
||||
break;
|
||||
|
||||
case MOUSE_TYPE_INPORT:
|
||||
dev->flags |= FLAG_INPORT;
|
||||
ms_reset(dev);
|
||||
|
||||
/* Initialize I/O handlers. */
|
||||
dev->read = ms_read;
|
||||
dev->write = ms_write;
|
||||
|
||||
dev->timer = ((1000000LL * TIMER_USEC) / 30LL);
|
||||
break;
|
||||
}
|
||||
|
||||
timer_add(bm_timer, &dev->timer, TIMER_ALWAYS_ENABLED, dev);
|
||||
|
||||
/* Request an I/O range. */
|
||||
io_sethandler(dev->base, 4,
|
||||
bm_read, NULL, NULL, bm_write, NULL, NULL, dev);
|
||||
|
||||
mouse_bus_log("%s: I/O=%04x, IRQ=%d, buttons=%d, model=%s\n",
|
||||
dev->name, dev->base, dev->irq, i, j ? "new" : "old");
|
||||
|
||||
/* Tell them how many buttons we have. */
|
||||
mouse_set_buttons((dev->flags & FLAG_3BTN) ? 3 : 2);
|
||||
|
||||
/* Return our private data to the I/O layer. */
|
||||
return(dev);
|
||||
}
|
||||
|
||||
|
||||
static const device_config_t bm_config[] = {
|
||||
{
|
||||
"base", "Address", CONFIG_HEX16, "", MOUSE_PORT,
|
||||
{
|
||||
{
|
||||
"0x230", 0x230
|
||||
},
|
||||
{
|
||||
"0x234", 0x234
|
||||
},
|
||||
{
|
||||
"0x238", 0x238
|
||||
},
|
||||
{
|
||||
"0x23C", 0x23c
|
||||
},
|
||||
{
|
||||
""
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"irq", "IRQ", CONFIG_SELECTION, "", MOUSE_IRQ, {
|
||||
{
|
||||
"IRQ 2", 2
|
||||
},
|
||||
{
|
||||
"IRQ 3", 3
|
||||
},
|
||||
{
|
||||
"IRQ 4", 4
|
||||
},
|
||||
{
|
||||
"IRQ 5", 5
|
||||
},
|
||||
{
|
||||
""
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"buttons", "Buttons", CONFIG_SELECTION, "", MOUSE_BUTTONS, {
|
||||
{
|
||||
"Two", 2
|
||||
},
|
||||
{
|
||||
"Three", 3
|
||||
},
|
||||
{
|
||||
""
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"model", "Model", CONFIG_SELECTION, "", 0, {
|
||||
{
|
||||
"Old", 0
|
||||
},
|
||||
{
|
||||
"New", 1
|
||||
},
|
||||
{
|
||||
""
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"", "", -1
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
const device_t mouse_logibus_device = {
|
||||
"Logitech Bus Mouse",
|
||||
DEVICE_ISA,
|
||||
MOUSE_TYPE_LOGIBUS,
|
||||
bm_init, bm_close, NULL,
|
||||
bm_poll, NULL, NULL,
|
||||
bm_config
|
||||
};
|
||||
|
||||
const device_t mouse_msinport_device = {
|
||||
"Microsoft Bus Mouse (InPort)",
|
||||
DEVICE_ISA,
|
||||
MOUSE_TYPE_INPORT,
|
||||
bm_init, bm_close, NULL,
|
||||
bm_poll, NULL, NULL,
|
||||
bm_config
|
||||
};
|
||||
364
backup code/network/net_pcap - Cópia.c
Normal file
364
backup code/network/net_pcap - Cópia.c
Normal file
@@ -0,0 +1,364 @@
|
||||
/*
|
||||
* VARCem Virtual ARchaeological Computer EMulator.
|
||||
* An emulator of (mostly) x86-based PC systems and devices,
|
||||
* using the ISA,EISA,VLB,MCA and PCI system buses, roughly
|
||||
* spanning the era between 1981 and 1995.
|
||||
*
|
||||
* This file is part of the VARCem Project.
|
||||
*
|
||||
* Handle WinPcap library processing.
|
||||
*
|
||||
* Version: @(#)net_pcap.c 1.0.3 2018/03/15
|
||||
*
|
||||
* Author: Fred N. van Kempen, <decwiz@yahoo.com>
|
||||
*
|
||||
* Copyright 2017,2018 Fred N. van Kempen.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with
|
||||
* or without modification, are permitted provided that the
|
||||
* following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the entire
|
||||
* above notice, this list of conditions and the following
|
||||
* disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the
|
||||
* following disclaimer in the documentation and/or other
|
||||
* materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names
|
||||
* of its contributors may be used to endorse or promote
|
||||
* products derived from this software without specific
|
||||
* prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <wchar.h>
|
||||
#include <pcap/pcap.h>
|
||||
#include "../86box.h"
|
||||
#include "../config.h"
|
||||
#include "../device.h"
|
||||
#include "../plat.h"
|
||||
#include "../plat_dynld.h"
|
||||
#include "network.h"
|
||||
|
||||
|
||||
static volatile void *pcap_handle; /* handle to WinPcap DLL */
|
||||
static volatile pcap_t *pcap; /* handle to WinPcap library */
|
||||
static volatile thread_t *poll_tid;
|
||||
static const netcard_t *poll_card; /* netcard linked to us */
|
||||
static event_t *poll_state;
|
||||
|
||||
|
||||
/* Pointers to the real functions. */
|
||||
static const char *(*f_pcap_lib_version)(void);
|
||||
static int (*f_pcap_findalldevs)(pcap_if_t **,char *);
|
||||
static void (*f_pcap_freealldevs)(pcap_if_t *);
|
||||
static pcap_t *(*f_pcap_open_live)(const char *,int,int,int,char *);
|
||||
static int (*f_pcap_compile)(pcap_t *,struct bpf_program *,
|
||||
const char *,int,bpf_u_int32);
|
||||
static int (*f_pcap_setfilter)(pcap_t *,struct bpf_program *);
|
||||
static const u_char *(*f_pcap_next)(pcap_t *,struct pcap_pkthdr *);
|
||||
static int (*f_pcap_sendpacket)(pcap_t *,const u_char *,int);
|
||||
static void (*f_pcap_close)(pcap_t *);
|
||||
static dllimp_t pcap_imports[] = {
|
||||
{ "pcap_lib_version", &f_pcap_lib_version },
|
||||
{ "pcap_findalldevs", &f_pcap_findalldevs },
|
||||
{ "pcap_freealldevs", &f_pcap_freealldevs },
|
||||
{ "pcap_open_live", &f_pcap_open_live },
|
||||
{ "pcap_compile", &f_pcap_compile },
|
||||
{ "pcap_setfilter", &f_pcap_setfilter },
|
||||
{ "pcap_next", &f_pcap_next },
|
||||
{ "pcap_sendpacket", &f_pcap_sendpacket },
|
||||
{ "pcap_close", &f_pcap_close },
|
||||
{ NULL, NULL },
|
||||
};
|
||||
|
||||
|
||||
/* Handle the receiving of frames from the channel. */
|
||||
static void
|
||||
poll_thread(void *arg)
|
||||
{
|
||||
uint8_t *mac = (uint8_t *)arg;
|
||||
uint8_t *data = NULL;
|
||||
struct pcap_pkthdr h;
|
||||
uint32_t mac_cmp32[2];
|
||||
uint16_t mac_cmp16[2];
|
||||
event_t *evt;
|
||||
|
||||
pclog("PCAP: polling started.\n");
|
||||
thread_set_event(poll_state);
|
||||
|
||||
/* Create a waitable event. */
|
||||
evt = thread_create_event();
|
||||
|
||||
/* As long as the channel is open.. */
|
||||
while (pcap != NULL) {
|
||||
/* Request ownership of the device. */
|
||||
network_wait(1);
|
||||
|
||||
/* Wait for a poll request. */
|
||||
network_poll();
|
||||
|
||||
if (pcap == NULL) break;
|
||||
|
||||
/* Wait for the next packet to arrive. */
|
||||
data = (uint8_t *)f_pcap_next((pcap_t *)pcap, &h);
|
||||
if (data != NULL) {
|
||||
/* Received MAC. */
|
||||
mac_cmp32[0] = *(uint32_t *)(data+6);
|
||||
mac_cmp16[0] = *(uint16_t *)(data+10);
|
||||
|
||||
/* Local MAC. */
|
||||
mac_cmp32[1] = *(uint32_t *)mac;
|
||||
mac_cmp16[1] = *(uint16_t *)(mac+4);
|
||||
if ((mac_cmp32[0] != mac_cmp32[1]) ||
|
||||
(mac_cmp16[0] != mac_cmp16[1])) {
|
||||
|
||||
poll_card->rx(poll_card->priv, data, h.caplen);
|
||||
} else {
|
||||
/* Mark as invalid packet. */
|
||||
data = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* If we did not get anything, wait a while. */
|
||||
if (data == NULL)
|
||||
thread_wait_event(evt, 10);
|
||||
|
||||
/* Release ownership of the device. */
|
||||
network_wait(0);
|
||||
}
|
||||
|
||||
/* No longer needed. */
|
||||
if (evt != NULL)
|
||||
thread_destroy_event(evt);
|
||||
|
||||
pclog("PCAP: polling stopped.\n");
|
||||
thread_set_event(poll_state);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Prepare the (Win)Pcap module for use.
|
||||
*
|
||||
* This is called only once, during application init,
|
||||
* to check for availability of PCAP, and to retrieve
|
||||
* a list of (usable) intefaces for it.
|
||||
*/
|
||||
int
|
||||
net_pcap_prepare(netdev_t *list)
|
||||
{
|
||||
char errbuf[PCAP_ERRBUF_SIZE];
|
||||
pcap_if_t *devlist, *dev;
|
||||
int i = 0;
|
||||
|
||||
/* Local variables. */
|
||||
pcap = NULL;
|
||||
|
||||
/* Try loading the DLL. */
|
||||
#ifdef _WIN32
|
||||
pcap_handle = dynld_module("wpcap.dll", pcap_imports);
|
||||
#else
|
||||
pcap_handle = dynld_module("libpcap.so", pcap_imports);
|
||||
#endif
|
||||
if (pcap_handle == NULL) return(-1);
|
||||
|
||||
/* Retrieve the device list from the local machine */
|
||||
if (f_pcap_findalldevs(&devlist, errbuf) == -1) {
|
||||
pclog("PCAP: error in pcap_findalldevs: %s\n", errbuf);
|
||||
return(-1);
|
||||
}
|
||||
|
||||
for (dev=devlist; dev!=NULL; dev=dev->next) {
|
||||
strcpy(list->device, dev->name);
|
||||
if (dev->description)
|
||||
strcpy(list->description, dev->description);
|
||||
else
|
||||
memset(list->description, '\0', sizeof(list->description));
|
||||
list++; i++;
|
||||
}
|
||||
|
||||
/* Release the memory. */
|
||||
f_pcap_freealldevs(devlist);
|
||||
|
||||
return(i);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Initialize (Win)Pcap for use.
|
||||
*
|
||||
* This is called on every 'cycle' of the emulator,
|
||||
* if and as long the NetworkType is set to PCAP,
|
||||
* and also as long as we have a NetCard defined.
|
||||
*/
|
||||
int
|
||||
net_pcap_init(void)
|
||||
{
|
||||
char errbuf[PCAP_ERRBUF_SIZE];
|
||||
char *str;
|
||||
|
||||
/* Did we already load the library? */
|
||||
if (pcap_handle == NULL) return(-1);
|
||||
#if 0
|
||||
// no, we don't..
|
||||
/* Load the DLL if needed. We already know it exists. */
|
||||
#ifdef _WIN32
|
||||
pcap_handle = dynld_module("wpcap.dll", pcap_imports);
|
||||
#else
|
||||
pcap_handle = dynld_module("libpcap.so", pcap_imports);
|
||||
#endif
|
||||
if (pcap_handle == NULL) return(-1);
|
||||
#endif
|
||||
|
||||
/* Get the PCAP library name and version. */
|
||||
strcpy(errbuf, f_pcap_lib_version());
|
||||
str = strchr(errbuf, '(');
|
||||
if (str != NULL) *(str-1) = '\0';
|
||||
pclog("PCAP: initializing, %s\n", errbuf);
|
||||
|
||||
/* Get the value of our capture interface. */
|
||||
if ((network_host[0] == '\0') || !strcmp(network_host, "none")) {
|
||||
pclog("PCAP: no interface configured!\n");
|
||||
return(-1);
|
||||
}
|
||||
|
||||
poll_tid = NULL;
|
||||
poll_state = NULL;
|
||||
poll_card = NULL;
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
/* Close up shop. */
|
||||
void
|
||||
net_pcap_close(void)
|
||||
{
|
||||
pcap_t *pc;
|
||||
|
||||
if (pcap == NULL) return;
|
||||
|
||||
pclog("PCAP: closing.\n");
|
||||
|
||||
/* Tell the polling thread to shut down. */
|
||||
pc = (pcap_t *)pcap; pcap = NULL;
|
||||
|
||||
/* Tell the thread to terminate. */
|
||||
if (poll_tid != NULL) {
|
||||
network_busy(0);
|
||||
|
||||
/* Wait for the thread to finish. */
|
||||
pclog("PCAP: waiting for thread to end...\n");
|
||||
thread_wait_event(poll_state, -1);
|
||||
pclog("PCAP: thread ended\n");
|
||||
thread_destroy_event(poll_state);
|
||||
|
||||
poll_tid = NULL;
|
||||
poll_state = NULL;
|
||||
poll_card = NULL;
|
||||
}
|
||||
|
||||
/* OK, now shut down Pcap itself. */
|
||||
f_pcap_close(pc);
|
||||
pcap = NULL;
|
||||
|
||||
#if 0
|
||||
// no, we don't..
|
||||
/* Unload the DLL if possible. */
|
||||
if (pcap_handle != NULL) {
|
||||
dynld_close((void *)pcap_handle);
|
||||
pcap_handle = NULL;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Reset (Win)Pcap and activate it.
|
||||
*
|
||||
* This is called on every 'cycle' of the emulator,
|
||||
* if and as long the NetworkType is set to PCAP,
|
||||
* and also as long as we have a NetCard defined.
|
||||
*
|
||||
* We already know we have PCAP available, as this
|
||||
* is called when the network activates itself and
|
||||
* tries to attach to the network module.
|
||||
*/
|
||||
int
|
||||
net_pcap_reset(const netcard_t *card, uint8_t *mac)
|
||||
{
|
||||
char errbuf[PCAP_ERRBUF_SIZE];
|
||||
char filter_exp[255];
|
||||
struct bpf_program fp;
|
||||
|
||||
/* Open a PCAP live channel. */
|
||||
if ((pcap = f_pcap_open_live(network_host, /* interface name */
|
||||
1518, /* max packet size */
|
||||
1, /* promiscuous mode? */
|
||||
10, /* timeout in msec */
|
||||
errbuf)) == NULL) { /* error buffer */
|
||||
pclog(" Unable to open device: %s!\n", network_host);
|
||||
return(-1);
|
||||
}
|
||||
pclog("PCAP: interface: %s\n", network_host);
|
||||
|
||||
/* Create a MAC address based packet filter. */
|
||||
pclog("PCAP: installing filter for MAC=%02x:%02x:%02x:%02x:%02x:%02x\n",
|
||||
mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
|
||||
sprintf(filter_exp,
|
||||
"( ((ether dst ff:ff:ff:ff:ff:ff) or (ether dst %02x:%02x:%02x:%02x:%02x:%02x)) and not (ether src %02x:%02x:%02x:%02x:%02x:%02x) )",
|
||||
mac[0], mac[1], mac[2], mac[3], mac[4], mac[5],
|
||||
mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
|
||||
if (f_pcap_compile((pcap_t *)pcap, &fp, filter_exp, 0, 0xffffffff) != -1) {
|
||||
if (f_pcap_setfilter((pcap_t *)pcap, &fp) != 0) {
|
||||
pclog("PCAP: error installing filter (%s) !\n", filter_exp);
|
||||
f_pcap_close((pcap_t *)pcap);
|
||||
return(-1);
|
||||
}
|
||||
} else {
|
||||
pclog("PCAP: could not compile filter (%s) !\n", filter_exp);
|
||||
f_pcap_close((pcap_t *)pcap);
|
||||
return(-1);
|
||||
}
|
||||
|
||||
/* Save the callback info. */
|
||||
poll_card = card;
|
||||
|
||||
pclog("PCAP: starting thread..\n");
|
||||
poll_state = thread_create_event();
|
||||
poll_tid = thread_create(poll_thread, mac);
|
||||
thread_wait_event(poll_state, -1);
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
/* Send a packet to the Pcap interface. */
|
||||
void
|
||||
net_pcap_in(uint8_t *bufp, int len)
|
||||
{
|
||||
if (pcap == NULL) return;
|
||||
|
||||
network_busy(1);
|
||||
|
||||
f_pcap_sendpacket((pcap_t *)pcap, bufp, len);
|
||||
|
||||
network_busy(0);
|
||||
}
|
||||
1130
backup code/pc - Cópia.c
Normal file
1130
backup code/pc - Cópia.c
Normal file
File diff suppressed because it is too large
Load Diff
368
backup code/scsi/scsi - Cópia (2).h
Normal file
368
backup code/scsi/scsi - Cópia (2).h
Normal file
@@ -0,0 +1,368 @@
|
||||
/*
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
*
|
||||
* This file is part of the 86Box distribution.
|
||||
*
|
||||
* SCSI controller handler header.
|
||||
*
|
||||
* Version: @(#)scsi_h 1.0.17 2018/06/02
|
||||
*
|
||||
* Authors: TheCollector1995, <mariogplayer@gmail.com>
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
* Fred N. van Kempen, <decwiz@yahoo.com>
|
||||
*
|
||||
* Copyright 2016-2018 TheCollector1995.
|
||||
* Copyright 2016-2018 Miran Grca.
|
||||
* Copyright 2017,2018 Fred N. van Kempen.
|
||||
*/
|
||||
#ifndef EMU_SCSI_H
|
||||
#define EMU_SCSI_H
|
||||
|
||||
|
||||
#ifdef WALTJE
|
||||
#define SCSI_TIME (50 * (1 << TIMER_SHIFT))
|
||||
#else
|
||||
#define SCSI_TIME (5 * 100 * (1 << TIMER_SHIFT))
|
||||
#endif
|
||||
|
||||
|
||||
/* Configuration. */
|
||||
#define SCSI_ID_MAX 16 /* 16 on wide buses */
|
||||
#define SCSI_LUN_MAX 8 /* always 8 */
|
||||
|
||||
|
||||
/* SCSI commands. */
|
||||
#define GPCMD_TEST_UNIT_READY 0x00
|
||||
#define GPCMD_REZERO_UNIT 0x01
|
||||
#define GPCMD_REQUEST_SENSE 0x03
|
||||
#define GPCMD_FORMAT_UNIT 0x04
|
||||
#define GPCMD_IOMEGA_SENSE 0x06
|
||||
#define GPCMD_READ_6 0x08
|
||||
#define GPCMD_WRITE_6 0x0a
|
||||
#define GPCMD_SEEK_6 0x0b
|
||||
#define GPCMD_IOMEGA_SET_PROTECTION_MODE 0x0c
|
||||
#define GPCMD_IOMEGA_EJECT 0x0d /* ATAPI only? */
|
||||
#define GPCMD_INQUIRY 0x12
|
||||
#define GPCMD_VERIFY_6 0x13
|
||||
#define GPCMD_MODE_SELECT_6 0x15
|
||||
#define GPCMD_SCSI_RESERVE 0x16
|
||||
#define GPCMD_SCSI_RELEASE 0x17
|
||||
#define GPCMD_MODE_SENSE_6 0x1a
|
||||
#define GPCMD_START_STOP_UNIT 0x1b
|
||||
#define GPCMD_SEND_DIAGNOSTIC 0x1d
|
||||
#define GPCMD_PREVENT_REMOVAL 0x1e
|
||||
#define GPCMD_READ_FORMAT_CAPACITIES 0x23
|
||||
#define GPCMD_READ_CDROM_CAPACITY 0x25
|
||||
#define GPCMD_READ_10 0x28
|
||||
#define GPCMD_WRITE_10 0x2a
|
||||
#define GPCMD_SEEK_10 0x2b
|
||||
#define GPCMD_WRITE_AND_VERIFY_10 0x2e
|
||||
#define GPCMD_VERIFY_10 0x2f
|
||||
#define GPCMD_READ_BUFFER 0x3c
|
||||
#define GPCMD_WRITE_SAME_10 0x41
|
||||
#define GPCMD_READ_SUBCHANNEL 0x42
|
||||
#define GPCMD_READ_TOC_PMA_ATIP 0x43
|
||||
#define GPCMD_READ_HEADER 0x44
|
||||
#define GPCMD_PLAY_AUDIO_10 0x45
|
||||
#define GPCMD_GET_CONFIGURATION 0x46
|
||||
#define GPCMD_PLAY_AUDIO_MSF 0x47
|
||||
#define GPCMD_PLAY_AUDIO_TRACK_INDEX 0x48
|
||||
#define GPCMD_GET_EVENT_STATUS_NOTIFICATION 0x4a
|
||||
#define GPCMD_PAUSE_RESUME 0x4b
|
||||
#define GPCMD_STOP_PLAY_SCAN 0x4e
|
||||
#define GPCMD_READ_DISC_INFORMATION 0x51
|
||||
#define GPCMD_READ_TRACK_INFORMATION 0x52
|
||||
#define GPCMD_MODE_SELECT_10 0x55
|
||||
#define GPCMD_MODE_SENSE_10 0x5a
|
||||
#define GPCMD_PLAY_AUDIO_12 0xa5
|
||||
#define GPCMD_READ_12 0xa8
|
||||
#define GPCMD_WRITE_12 0xaa
|
||||
#define GPCMD_READ_DVD_STRUCTURE 0xad /* For reading. */
|
||||
#define GPCMD_WRITE_AND_VERIFY_12 0xae
|
||||
#define GPCMD_VERIFY_12 0xaf
|
||||
#define GPCMD_PLAY_CD_OLD 0xb4
|
||||
#define GPCMD_READ_CD_OLD 0xb8
|
||||
#define GPCMD_READ_CD_MSF 0xb9
|
||||
#define GPCMD_SCAN 0xba
|
||||
#define GPCMD_SET_SPEED 0xbb
|
||||
#define GPCMD_PLAY_CD 0xbc
|
||||
#define GPCMD_MECHANISM_STATUS 0xbd
|
||||
#define GPCMD_READ_CD 0xbe
|
||||
#define GPCMD_SEND_DVD_STRUCTURE 0xbf /* This is for writing only, irrelevant to PCem. */
|
||||
#define GPCMD_PAUSE_RESUME_ALT 0xc2
|
||||
#define GPCMD_SCAN_ALT 0xcd /* Should be equivalent to 0xba */
|
||||
#define GPCMD_SET_SPEED_ALT 0xda /* Should be equivalent to 0xbb */
|
||||
|
||||
/* Mode page codes for mode sense/set */
|
||||
#define GPMODE_R_W_ERROR_PAGE 0x01
|
||||
#define GPMODE_CDROM_PAGE 0x0d
|
||||
#define GPMODE_CDROM_AUDIO_PAGE 0x0e
|
||||
#define GPMODE_CAPABILITIES_PAGE 0x2a
|
||||
#define GPMODE_ALL_PAGES 0x3f
|
||||
|
||||
/* Mode page codes for presence */
|
||||
#define GPMODEP_R_W_ERROR_PAGE 0x0000000000000002LL
|
||||
#define GPMODEP_CDROM_PAGE 0x0000000000002000LL
|
||||
#define GPMODEP_CDROM_AUDIO_PAGE 0x0000000000004000LL
|
||||
#define GPMODEP_CAPABILITIES_PAGE 0x0000040000000000LL
|
||||
#define GPMODEP_ALL_PAGES 0x8000000000000000LL
|
||||
|
||||
/* SCSI Status Codes */
|
||||
#define SCSI_STATUS_OK 0
|
||||
#define SCSI_STATUS_CHECK_CONDITION 2
|
||||
|
||||
/* SCSI Sense Keys */
|
||||
#define SENSE_NONE 0
|
||||
#define SENSE_NOT_READY 2
|
||||
#define SENSE_ILLEGAL_REQUEST 5
|
||||
#define SENSE_UNIT_ATTENTION 6
|
||||
|
||||
/* SCSI Additional Sense Codes */
|
||||
#define ASC_AUDIO_PLAY_OPERATION 0x00
|
||||
#define ASC_NOT_READY 0x04
|
||||
#define ASC_ILLEGAL_OPCODE 0x20
|
||||
#define ASC_LBA_OUT_OF_RANGE 0x21
|
||||
#define ASC_INV_FIELD_IN_CMD_PACKET 0x24
|
||||
#define ASC_INV_LUN 0x25
|
||||
#define ASC_INV_FIELD_IN_PARAMETER_LIST 0x26
|
||||
#define ASC_WRITE_PROTECTED 0x27
|
||||
#define ASC_MEDIUM_MAY_HAVE_CHANGED 0x28
|
||||
#define ASC_CAPACITY_DATA_CHANGED 0x2A
|
||||
#define ASC_INCOMPATIBLE_FORMAT 0x30
|
||||
#define ASC_MEDIUM_NOT_PRESENT 0x3a
|
||||
#define ASC_DATA_PHASE_ERROR 0x4b
|
||||
#define ASC_ILLEGAL_MODE_FOR_THIS_TRACK 0x64
|
||||
|
||||
#define ASCQ_UNIT_IN_PROCESS_OF_BECOMING_READY 0x01
|
||||
#define ASCQ_INITIALIZING_COMMAND_REQUIRED 0x02
|
||||
#define ASCQ_CAPACITY_DATA_CHANGED 0x09
|
||||
#define ASCQ_AUDIO_PLAY_OPERATION_IN_PROGRESS 0x11
|
||||
#define ASCQ_AUDIO_PLAY_OPERATION_PAUSED 0x12
|
||||
#define ASCQ_AUDIO_PLAY_OPERATION_COMPLETED 0x13
|
||||
|
||||
/* Tell RISC OS that we have a 4x CD-ROM drive (600kb/sec data, 706kb/sec raw).
|
||||
Not that it means anything */
|
||||
#define CDROM_SPEED 706 /* 0x2C2 */
|
||||
|
||||
#define BUFFER_SIZE (256*1024)
|
||||
|
||||
#define RW_DELAY (TIMER_USEC * 500)
|
||||
|
||||
/* Some generally useful CD-ROM information */
|
||||
#define CD_MINS 75 /* max. minutes per CD */
|
||||
#define CD_SECS 60 /* seconds per minute */
|
||||
#define CD_FRAMES 75 /* frames per second */
|
||||
#define CD_FRAMESIZE 2048 /* bytes per frame, "cooked" mode */
|
||||
#define CD_MAX_BYTES (CD_MINS * CD_SECS * CD_FRAMES * CD_FRAMESIZE)
|
||||
#define CD_MAX_SECTORS (CD_MAX_BYTES / 512)
|
||||
|
||||
/* Event notification classes for GET EVENT STATUS NOTIFICATION */
|
||||
#define GESN_NO_EVENTS 0
|
||||
#define GESN_OPERATIONAL_CHANGE 1
|
||||
#define GESN_POWER_MANAGEMENT 2
|
||||
#define GESN_EXTERNAL_REQUEST 3
|
||||
#define GESN_MEDIA 4
|
||||
#define GESN_MULTIPLE_HOSTS 5
|
||||
#define GESN_DEVICE_BUSY 6
|
||||
|
||||
/* Event codes for MEDIA event status notification */
|
||||
#define MEC_NO_CHANGE 0
|
||||
#define MEC_EJECT_REQUESTED 1
|
||||
#define MEC_NEW_MEDIA 2
|
||||
#define MEC_MEDIA_REMOVAL 3 /* only for media changers */
|
||||
#define MEC_MEDIA_CHANGED 4 /* only for media changers */
|
||||
#define MEC_BG_FORMAT_COMPLETED 5 /* MRW or DVD+RW b/g format completed */
|
||||
#define MEC_BG_FORMAT_RESTARTED 6 /* MRW or DVD+RW b/g format restarted */
|
||||
#define MS_TRAY_OPEN 1
|
||||
#define MS_MEDIA_PRESENT 2
|
||||
|
||||
/*
|
||||
* The MMC values are not IDE specific and might need to be moved
|
||||
* to a common header if they are also needed for the SCSI emulation
|
||||
*/
|
||||
|
||||
/* Profile list from MMC-6 revision 1 table 91 */
|
||||
#define MMC_PROFILE_NONE 0x0000
|
||||
#define MMC_PROFILE_CD_ROM 0x0008
|
||||
#define MMC_PROFILE_CD_R 0x0009
|
||||
#define MMC_PROFILE_CD_RW 0x000A
|
||||
#define MMC_PROFILE_DVD_ROM 0x0010
|
||||
#define MMC_PROFILE_DVD_R_SR 0x0011
|
||||
#define MMC_PROFILE_DVD_RAM 0x0012
|
||||
#define MMC_PROFILE_DVD_RW_RO 0x0013
|
||||
#define MMC_PROFILE_DVD_RW_SR 0x0014
|
||||
#define MMC_PROFILE_DVD_R_DL_SR 0x0015
|
||||
#define MMC_PROFILE_DVD_R_DL_JR 0x0016
|
||||
#define MMC_PROFILE_DVD_RW_DL 0x0017
|
||||
#define MMC_PROFILE_DVD_DDR 0x0018
|
||||
#define MMC_PROFILE_DVD_PLUS_RW 0x001A
|
||||
#define MMC_PROFILE_DVD_PLUS_R 0x001B
|
||||
#define MMC_PROFILE_DVD_PLUS_RW_DL 0x002A
|
||||
#define MMC_PROFILE_DVD_PLUS_R_DL 0x002B
|
||||
#define MMC_PROFILE_BD_ROM 0x0040
|
||||
#define MMC_PROFILE_BD_R_SRM 0x0041
|
||||
#define MMC_PROFILE_BD_R_RRM 0x0042
|
||||
#define MMC_PROFILE_BD_RE 0x0043
|
||||
#define MMC_PROFILE_HDDVD_ROM 0x0050
|
||||
#define MMC_PROFILE_HDDVD_R 0x0051
|
||||
#define MMC_PROFILE_HDDVD_RAM 0x0052
|
||||
#define MMC_PROFILE_HDDVD_RW 0x0053
|
||||
#define MMC_PROFILE_HDDVD_R_DL 0x0058
|
||||
#define MMC_PROFILE_HDDVD_RW_DL 0x005A
|
||||
#define MMC_PROFILE_INVALID 0xFFFF
|
||||
|
||||
#define SCSI_ONLY 32
|
||||
#define ATAPI_ONLY 16
|
||||
#define IMPLEMENTED 8
|
||||
#define NONDATA 4
|
||||
#define CHECK_READY 2
|
||||
#define ALLOW_UA 1
|
||||
|
||||
|
||||
extern uint8_t SCSICommandTable[0x100];
|
||||
extern uint8_t mode_sense_pages[0x40];
|
||||
extern int readcdmode;
|
||||
|
||||
/* Mode sense/select stuff. */
|
||||
extern uint8_t mode_pages_in[256][256];
|
||||
extern uint8_t page_flags[256];
|
||||
extern uint8_t prefix_len;
|
||||
extern uint8_t page_current;
|
||||
#define PAGE_CHANGEABLE 1
|
||||
#define PAGE_CHANGED 2
|
||||
|
||||
struct _scsisense_ {
|
||||
uint8_t SenseBuffer[18];
|
||||
uint8_t SenseLength;
|
||||
uint8_t UnitAttention;
|
||||
uint8_t SenseKey;
|
||||
uint8_t Asc;
|
||||
uint8_t Ascq;
|
||||
} SCSISense;
|
||||
|
||||
extern int cd_status;
|
||||
extern int prev_status;
|
||||
|
||||
enum {
|
||||
SCSI_NONE = 0,
|
||||
SCSI_NULL,
|
||||
SCSI_DISK,
|
||||
SCSI_CDROM,
|
||||
SCSI_ZIP
|
||||
};
|
||||
|
||||
#define MSFtoLBA(m,s,f) ((((m*60)+s)*75)+f)
|
||||
|
||||
#define MSG_COMMAND_COMPLETE 0x00
|
||||
|
||||
#define BUS_DBP 0x01
|
||||
#define BUS_SEL 0x02
|
||||
#define BUS_IO 0x04
|
||||
#define BUS_CD 0x08
|
||||
#define BUS_MSG 0x10
|
||||
#define BUS_REQ 0x20
|
||||
#define BUS_BSY 0x40
|
||||
#define BUS_RST 0x80
|
||||
#define BUS_ACK 0x200
|
||||
#define BUS_ATN 0x200
|
||||
#define BUS_ARB 0x8000
|
||||
#define BUS_SETDATA(val) ((uint32_t)val << 16)
|
||||
#define BUS_GETDATA(val) ((val >> 16) & 0xff)
|
||||
#define BUS_DATAMASK 0xff0000
|
||||
|
||||
#define BUS_IDLE (1 << 31)
|
||||
|
||||
#define SCSI_PHASE_DATA_OUT 0
|
||||
#define SCSI_PHASE_DATA_IN BUS_IO
|
||||
#define SCSI_PHASE_COMMAND BUS_CD
|
||||
#define SCSI_PHASE_STATUS (BUS_CD | BUS_IO)
|
||||
#define SCSI_PHASE_MESSAGE_OUT (BUS_MSG | BUS_CD)
|
||||
#define SCSI_PHASE_MESSAGE_IN (BUS_MSG | BUS_CD | BUS_IO)
|
||||
|
||||
typedef struct {
|
||||
uint8_t *CmdBuffer;
|
||||
int LunType;
|
||||
int32_t BufferLength;
|
||||
uint8_t Status;
|
||||
uint8_t Phase;
|
||||
} scsi_device_t;
|
||||
|
||||
|
||||
extern scsi_device_t SCSIDevices[SCSI_ID_MAX][SCSI_LUN_MAX];
|
||||
|
||||
extern void SCSIReset(uint8_t id, uint8_t lun);
|
||||
|
||||
extern int cdrom_add_error_and_subchannel(uint8_t *b, int real_sector_type);
|
||||
extern int cdrom_LBAtoMSF_accurate(void);
|
||||
|
||||
extern int mode_select_init(uint8_t command, uint16_t pl_length, uint8_t do_save);
|
||||
extern int mode_select_terminate(int force);
|
||||
extern int mode_select_write(uint8_t val);
|
||||
|
||||
extern int scsi_card_current;
|
||||
|
||||
extern int scsi_card_available(int card);
|
||||
extern char *scsi_card_getname(int card);
|
||||
#ifdef EMU_DEVICE_H
|
||||
extern const device_t *scsi_card_getdevice(int card);
|
||||
#endif
|
||||
extern int scsi_card_has_config(int card);
|
||||
extern char *scsi_card_get_internal_name(int card);
|
||||
extern int scsi_card_get_from_internal_name(char *s);
|
||||
extern void scsi_mutex(uint8_t start);
|
||||
extern void scsi_card_init(void);
|
||||
|
||||
|
||||
#pragma pack(push,1)
|
||||
typedef struct {
|
||||
uint8_t hi;
|
||||
uint8_t mid;
|
||||
uint8_t lo;
|
||||
} addr24;
|
||||
#pragma pack(pop)
|
||||
|
||||
#define ADDR_TO_U32(x) (((x).hi<<16)|((x).mid<<8)|((x).lo&0xFF))
|
||||
#define U32_TO_ADDR(a,x) do {(a).hi=(x)>>16;(a).mid=(x)>>8;(a).lo=(x)&0xFF;}while(0)
|
||||
|
||||
|
||||
/*
|
||||
*
|
||||
* Scatter/Gather Segment List Definitions
|
||||
*
|
||||
* Adapter limits
|
||||
*/
|
||||
#define MAX_SG_DESCRIPTORS 32 /* Always make the array 32 elements long, if less are used, that's not an issue. */
|
||||
|
||||
#pragma pack(push,1)
|
||||
typedef struct {
|
||||
uint32_t Segment;
|
||||
uint32_t SegmentPointer;
|
||||
} SGE32;
|
||||
#pragma pack(pop)
|
||||
|
||||
#pragma pack(push,1)
|
||||
typedef struct {
|
||||
addr24 Segment;
|
||||
addr24 SegmentPointer;
|
||||
} SGE;
|
||||
#pragma pack(pop)
|
||||
|
||||
#pragma pack(push,1)
|
||||
typedef struct {
|
||||
uint8_t pages[0x40][0x40];
|
||||
} mode_sense_pages_t;
|
||||
#pragma pack(pop)
|
||||
|
||||
|
||||
#define MODE_SELECT_PHASE_IDLE 0
|
||||
#define MODE_SELECT_PHASE_HEADER 1
|
||||
#define MODE_SELECT_PHASE_BLOCK_DESC 2
|
||||
#define MODE_SELECT_PHASE_PAGE_HEADER 3
|
||||
#define MODE_SELECT_PHASE_PAGE 4
|
||||
|
||||
#endif /*EMU_SCSI_H*/
|
||||
|
||||
extern void scsi_mutex_wait(uint8_t wait);
|
||||
236
backup code/scsi/scsi - Cópia.c
Normal file
236
backup code/scsi/scsi - Cópia.c
Normal file
@@ -0,0 +1,236 @@
|
||||
/*
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
*
|
||||
* This file is part of the 86Box distribution.
|
||||
*
|
||||
* Handling of the SCSI controllers.
|
||||
*
|
||||
* Version: @(#)scsi.c 1.0.19 2018/04/29
|
||||
*
|
||||
* Authors: Miran Grca, <mgrca8@gmail.com>
|
||||
* Fred N. van Kempen, <decwiz@yahoo.com>
|
||||
* TheCollector1995, <mariogplayer@gmail.com>
|
||||
*
|
||||
* Copyright 2016-2018 Miran Grca.
|
||||
* Copyright 2017,2018 Fred N. van Kempen.
|
||||
*/
|
||||
#include <stdarg.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <wchar.h>
|
||||
#define HAVE_STDARG_H
|
||||
#include "../86box.h"
|
||||
#include "../mem.h"
|
||||
#include "../rom.h"
|
||||
#include "../timer.h"
|
||||
#include "../device.h"
|
||||
#include "../disk/hdc.h"
|
||||
#include "../disk/zip.h"
|
||||
#include "../plat.h"
|
||||
#include "scsi.h"
|
||||
#include "../cdrom/cdrom.h"
|
||||
#include "scsi_device.h"
|
||||
#include "scsi_aha154x.h"
|
||||
#include "scsi_buslogic.h"
|
||||
#include "scsi_ncr5380.h"
|
||||
#include "scsi_ncr53c810.h"
|
||||
#ifdef WALTJE
|
||||
# include "scsi_wd33c93.h"
|
||||
#endif
|
||||
#include "scsi_x54x.h"
|
||||
|
||||
|
||||
scsi_device_t SCSIDevices[SCSI_ID_MAX][SCSI_LUN_MAX];
|
||||
// uint8_t SCSIPhase = 0xff;
|
||||
// uint8_t SCSIStatus = SCSI_STATUS_OK;
|
||||
char scsi_fn[SCSI_NUM][512];
|
||||
uint16_t scsi_hd_location[SCSI_NUM];
|
||||
|
||||
int scsi_card_current = 0;
|
||||
int scsi_card_last = 0;
|
||||
|
||||
uint32_t SCSI_BufferLength;
|
||||
static volatile
|
||||
mutex_t *scsiMutex;
|
||||
|
||||
|
||||
typedef const struct {
|
||||
const char *name;
|
||||
const char *internal_name;
|
||||
const device_t *device;
|
||||
} SCSI_CARD;
|
||||
|
||||
|
||||
static SCSI_CARD scsi_cards[] = {
|
||||
{ "None", "none", NULL, },
|
||||
{ "[ISA] Adaptec AHA-1540B","aha1540b", &aha1540b_device, },
|
||||
{ "[ISA] Adaptec AHA-1542C","aha1542c", &aha1542c_device, },
|
||||
{ "[ISA] Adaptec AHA-1542CF","aha1542cf", &aha1542cf_device, },
|
||||
{ "[ISA] BusLogic BT-542BH","bt542bh", &buslogic_device, },
|
||||
{ "[ISA] BusLogic BT-545S", "bt545s", &buslogic_545s_device,},
|
||||
{ "[ISA] Longshine LCS-6821N","lcs6821n", &scsi_lcs6821n_device,},
|
||||
{ "[ISA] Ranco RT1000B", "rt1000b", &scsi_rt1000b_device, },
|
||||
{ "[ISA] Trantor T130B", "t130b", &scsi_t130b_device, },
|
||||
{ "[ISA] Sumo SCSI-AT", "scsiat", &scsi_scsiat_device, },
|
||||
#ifdef WALTJE
|
||||
{ "[ISA] Generic WDC33C93", "wd33c93", &scsi_wd33c93_device, },
|
||||
#endif
|
||||
{ "[MCA] Adaptec AHA-1640", "aha1640", &aha1640_device, },
|
||||
{ "[MCA] BusLogic BT-640A", "bt640a", &buslogic_640a_device,},
|
||||
{ "[PCI] BusLogic BT-958D", "bt958d", &buslogic_pci_device, },
|
||||
{ "[PCI] NCR 53C810", "ncr53c810", &ncr53c810_pci_device,},
|
||||
{ "[VLB] BusLogic BT-445S", "bt445s", &buslogic_445s_device,},
|
||||
{ "", "", NULL, },
|
||||
};
|
||||
|
||||
|
||||
#ifdef ENABLE_SCSI_LOG
|
||||
int scsi_do_log = ENABLE_SCSI_LOG;
|
||||
#endif
|
||||
|
||||
|
||||
static void
|
||||
scsi_log(const char *fmt, ...)
|
||||
{
|
||||
#ifdef ENABLE_SCSI_LOG
|
||||
va_list ap;
|
||||
|
||||
if (scsi_do_log) {
|
||||
va_start(ap, fmt);
|
||||
pclog_ex(fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
int scsi_card_available(int card)
|
||||
{
|
||||
if (scsi_cards[card].device)
|
||||
return(device_available(scsi_cards[card].device));
|
||||
|
||||
return(1);
|
||||
}
|
||||
|
||||
|
||||
char *scsi_card_getname(int card)
|
||||
{
|
||||
return((char *) scsi_cards[card].name);
|
||||
}
|
||||
|
||||
|
||||
const device_t *scsi_card_getdevice(int card)
|
||||
{
|
||||
return(scsi_cards[card].device);
|
||||
}
|
||||
|
||||
|
||||
int scsi_card_has_config(int card)
|
||||
{
|
||||
if (! scsi_cards[card].device) return(0);
|
||||
|
||||
return(scsi_cards[card].device->config ? 1 : 0);
|
||||
}
|
||||
|
||||
|
||||
char *scsi_card_get_internal_name(int card)
|
||||
{
|
||||
return((char *) scsi_cards[card].internal_name);
|
||||
}
|
||||
|
||||
|
||||
int scsi_card_get_from_internal_name(char *s)
|
||||
{
|
||||
int c = 0;
|
||||
|
||||
while (strlen((char *) scsi_cards[c].internal_name)) {
|
||||
if (!strcmp((char *) scsi_cards[c].internal_name, s))
|
||||
return(c);
|
||||
c++;
|
||||
}
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
void scsi_mutex(uint8_t start)
|
||||
{
|
||||
if (start)
|
||||
scsiMutex = thread_create_mutex(L"86Box.SCSIMutex");
|
||||
else
|
||||
thread_close_mutex((mutex_t *) scsiMutex);
|
||||
}
|
||||
|
||||
|
||||
void scsi_card_init(void)
|
||||
{
|
||||
int i, j;
|
||||
|
||||
if (!scsi_cards[scsi_card_current].device)
|
||||
return;
|
||||
|
||||
scsi_log("Building SCSI hard disk map...\n");
|
||||
build_scsi_hd_map();
|
||||
scsi_log("Building SCSI CD-ROM map...\n");
|
||||
build_scsi_cdrom_map();
|
||||
scsi_log("Building SCSI ZIP map...\n");
|
||||
build_scsi_zip_map();
|
||||
|
||||
for (i=0; i<SCSI_ID_MAX; i++) {
|
||||
for (j=0; j<SCSI_LUN_MAX; j++) {
|
||||
if (scsi_hard_disks[i][j] != 0xff)
|
||||
SCSIDevices[i][j].LunType = SCSI_DISK;
|
||||
else if (scsi_cdrom_drives[i][j] != 0xff)
|
||||
SCSIDevices[i][j].LunType = SCSI_CDROM;
|
||||
else if (scsi_zip_drives[i][j] != 0xff)
|
||||
SCSIDevices[i][j].LunType = SCSI_ZIP;
|
||||
else
|
||||
SCSIDevices[i][j].LunType = SCSI_NONE;
|
||||
SCSIDevices[i][j].CmdBuffer = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
device_add(scsi_cards[scsi_card_current].device);
|
||||
|
||||
scsi_card_last = scsi_card_current;
|
||||
}
|
||||
|
||||
|
||||
/* Initialization function for the SCSI layer */
|
||||
void SCSIReset(uint8_t id, uint8_t lun)
|
||||
{
|
||||
uint8_t cdrom_id = scsi_cdrom_drives[id][lun];
|
||||
uint8_t zip_id = scsi_zip_drives[id][lun];
|
||||
uint8_t hdc_id = scsi_hard_disks[id][lun];
|
||||
|
||||
if (hdc_id != 0xff)
|
||||
SCSIDevices[id][lun].LunType = SCSI_DISK;
|
||||
else if (cdrom_id != 0xff)
|
||||
SCSIDevices[id][lun].LunType = SCSI_CDROM;
|
||||
else if (zip_id != 0xff)
|
||||
SCSIDevices[id][lun].LunType = SCSI_ZIP;
|
||||
else
|
||||
SCSIDevices[id][lun].LunType = SCSI_NONE;
|
||||
|
||||
scsi_device_reset(id, lun);
|
||||
|
||||
if (SCSIDevices[id][lun].CmdBuffer != NULL) {
|
||||
free(SCSIDevices[id][lun].CmdBuffer);
|
||||
SCSIDevices[id][lun].CmdBuffer = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
scsi_mutex_wait(uint8_t wait)
|
||||
{
|
||||
if (wait)
|
||||
thread_wait_mutex((mutex_t *) scsiMutex);
|
||||
else
|
||||
thread_release_mutex((mutex_t *) scsiMutex);
|
||||
}
|
||||
378
backup code/scsi/scsi - Cópia.h
Normal file
378
backup code/scsi/scsi - Cópia.h
Normal file
@@ -0,0 +1,378 @@
|
||||
/*
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
*
|
||||
* This file is part of the 86Box distribution.
|
||||
*
|
||||
* SCSI controller handler header.
|
||||
*
|
||||
* Version: @(#)scsi_h 1.0.16 2018/03/28
|
||||
*
|
||||
* Authors: TheCollector1995, <mariogplayer@gmail.com>
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
* Fred N. van Kempen, <decwiz@yahoo.com>
|
||||
*
|
||||
* Copyright 2016-2018 TheCollector1995.
|
||||
* Copyright 2016-2018 Miran Grca.
|
||||
* Copyright 2017,2018 Fred N. van Kempen.
|
||||
*/
|
||||
#ifndef EMU_SCSI_H
|
||||
#define EMU_SCSI_H
|
||||
|
||||
|
||||
#ifdef WALTJE
|
||||
#define SCSI_TIME (50 * (1 << TIMER_SHIFT))
|
||||
#else
|
||||
#define SCSI_TIME (5 * 100 * (1 << TIMER_SHIFT))
|
||||
#endif
|
||||
|
||||
|
||||
/* Configuration. */
|
||||
#define SCSI_ID_MAX 16 /* 16 on wide buses */
|
||||
#define SCSI_LUN_MAX 8 /* always 8 */
|
||||
|
||||
|
||||
/* SCSI commands. */
|
||||
#define GPCMD_TEST_UNIT_READY 0x00
|
||||
#define GPCMD_REZERO_UNIT 0x01
|
||||
#define GPCMD_REQUEST_SENSE 0x03
|
||||
#define GPCMD_FORMAT_UNIT 0x04
|
||||
#define GPCMD_IOMEGA_SENSE 0x06
|
||||
#define GPCMD_READ_6 0x08
|
||||
#define GPCMD_WRITE_6 0x0a
|
||||
#define GPCMD_SEEK_6 0x0b
|
||||
#define GPCMD_IOMEGA_SET_PROTECTION_MODE 0x0c
|
||||
#define GPCMD_IOMEGA_EJECT 0x0d /* ATAPI only? */
|
||||
#define GPCMD_INQUIRY 0x12
|
||||
#define GPCMD_VERIFY_6 0x13
|
||||
#define GPCMD_MODE_SELECT_6 0x15
|
||||
#define GPCMD_SCSI_RESERVE 0x16
|
||||
#define GPCMD_SCSI_RELEASE 0x17
|
||||
#define GPCMD_MODE_SENSE_6 0x1a
|
||||
#define GPCMD_START_STOP_UNIT 0x1b
|
||||
#define GPCMD_SEND_DIAGNOSTIC 0x1d
|
||||
#define GPCMD_PREVENT_REMOVAL 0x1e
|
||||
#define GPCMD_READ_FORMAT_CAPACITIES 0x23
|
||||
#define GPCMD_READ_CDROM_CAPACITY 0x25
|
||||
#define GPCMD_READ_10 0x28
|
||||
#define GPCMD_WRITE_10 0x2a
|
||||
#define GPCMD_SEEK_10 0x2b
|
||||
#define GPCMD_WRITE_AND_VERIFY_10 0x2e
|
||||
#define GPCMD_VERIFY_10 0x2f
|
||||
#define GPCMD_READ_BUFFER 0x3c
|
||||
#define GPCMD_WRITE_SAME_10 0x41
|
||||
#define GPCMD_READ_SUBCHANNEL 0x42
|
||||
#define GPCMD_READ_TOC_PMA_ATIP 0x43
|
||||
#define GPCMD_READ_HEADER 0x44
|
||||
#define GPCMD_PLAY_AUDIO_10 0x45
|
||||
#define GPCMD_GET_CONFIGURATION 0x46
|
||||
#define GPCMD_PLAY_AUDIO_MSF 0x47
|
||||
#define GPCMD_PLAY_AUDIO_TRACK_INDEX 0x48
|
||||
#define GPCMD_GET_EVENT_STATUS_NOTIFICATION 0x4a
|
||||
#define GPCMD_PAUSE_RESUME 0x4b
|
||||
#define GPCMD_STOP_PLAY_SCAN 0x4e
|
||||
#define GPCMD_READ_DISC_INFORMATION 0x51
|
||||
#define GPCMD_READ_TRACK_INFORMATION 0x52
|
||||
#define GPCMD_MODE_SELECT_10 0x55
|
||||
#define GPCMD_MODE_SENSE_10 0x5a
|
||||
#define GPCMD_PLAY_AUDIO_12 0xa5
|
||||
#define GPCMD_READ_12 0xa8
|
||||
#define GPCMD_WRITE_12 0xaa
|
||||
#define GPCMD_READ_DVD_STRUCTURE 0xad /* For reading. */
|
||||
#define GPCMD_WRITE_AND_VERIFY_12 0xae
|
||||
#define GPCMD_VERIFY_12 0xaf
|
||||
#define GPCMD_PLAY_CD_OLD 0xb4
|
||||
#define GPCMD_READ_CD_OLD 0xb8
|
||||
#define GPCMD_READ_CD_MSF 0xb9
|
||||
#define GPCMD_SCAN 0xba
|
||||
#define GPCMD_SET_SPEED 0xbb
|
||||
#define GPCMD_PLAY_CD 0xbc
|
||||
#define GPCMD_MECHANISM_STATUS 0xbd
|
||||
#define GPCMD_READ_CD 0xbe
|
||||
#define GPCMD_SEND_DVD_STRUCTURE 0xbf /* This is for writing only, irrelevant to PCem. */
|
||||
#define GPCMD_PAUSE_RESUME_ALT 0xc2
|
||||
#define GPCMD_SCAN_ALT 0xcd /* Should be equivalent to 0xba */
|
||||
#define GPCMD_SET_SPEED_ALT 0xda /* Should be equivalent to 0xbb */
|
||||
|
||||
/* Mode page codes for mode sense/set */
|
||||
#define GPMODE_R_W_ERROR_PAGE 0x01
|
||||
#define GPMODE_CDROM_PAGE 0x0d
|
||||
#define GPMODE_CDROM_AUDIO_PAGE 0x0e
|
||||
#define GPMODE_CAPABILITIES_PAGE 0x2a
|
||||
#define GPMODE_ALL_PAGES 0x3f
|
||||
|
||||
/* Mode page codes for presence */
|
||||
#define GPMODEP_R_W_ERROR_PAGE 0x0000000000000002LL
|
||||
#define GPMODEP_CDROM_PAGE 0x0000000000002000LL
|
||||
#define GPMODEP_CDROM_AUDIO_PAGE 0x0000000000004000LL
|
||||
#define GPMODEP_CAPABILITIES_PAGE 0x0000040000000000LL
|
||||
#define GPMODEP_ALL_PAGES 0x8000000000000000LL
|
||||
|
||||
/* SCSI Status Codes */
|
||||
#define SCSI_STATUS_OK 0
|
||||
#define SCSI_STATUS_CHECK_CONDITION 2
|
||||
|
||||
/* SCSI Sense Keys */
|
||||
#define SENSE_NONE 0
|
||||
#define SENSE_NOT_READY 2
|
||||
#define SENSE_ILLEGAL_REQUEST 5
|
||||
#define SENSE_UNIT_ATTENTION 6
|
||||
|
||||
/* SCSI Additional Sense Codes */
|
||||
#define ASC_AUDIO_PLAY_OPERATION 0x00
|
||||
#define ASC_NOT_READY 0x04
|
||||
#define ASC_ILLEGAL_OPCODE 0x20
|
||||
#define ASC_LBA_OUT_OF_RANGE 0x21
|
||||
#define ASC_INV_FIELD_IN_CMD_PACKET 0x24
|
||||
#define ASC_INV_LUN 0x25
|
||||
#define ASC_INV_FIELD_IN_PARAMETER_LIST 0x26
|
||||
#define ASC_WRITE_PROTECTED 0x27
|
||||
#define ASC_MEDIUM_MAY_HAVE_CHANGED 0x28
|
||||
#define ASC_CAPACITY_DATA_CHANGED 0x2A
|
||||
#define ASC_INCOMPATIBLE_FORMAT 0x30
|
||||
#define ASC_MEDIUM_NOT_PRESENT 0x3a
|
||||
#define ASC_DATA_PHASE_ERROR 0x4b
|
||||
#define ASC_ILLEGAL_MODE_FOR_THIS_TRACK 0x64
|
||||
|
||||
#define ASCQ_UNIT_IN_PROCESS_OF_BECOMING_READY 0x01
|
||||
#define ASCQ_INITIALIZING_COMMAND_REQUIRED 0x02
|
||||
#define ASCQ_CAPACITY_DATA_CHANGED 0x09
|
||||
#define ASCQ_AUDIO_PLAY_OPERATION_IN_PROGRESS 0x11
|
||||
#define ASCQ_AUDIO_PLAY_OPERATION_PAUSED 0x12
|
||||
#define ASCQ_AUDIO_PLAY_OPERATION_COMPLETED 0x13
|
||||
|
||||
/* Tell RISC OS that we have a 4x CD-ROM drive (600kb/sec data, 706kb/sec raw).
|
||||
Not that it means anything */
|
||||
#define CDROM_SPEED 706 /* 0x2C2 */
|
||||
|
||||
#define BUFFER_SIZE (256*1024)
|
||||
|
||||
#define RW_DELAY (TIMER_USEC * 500)
|
||||
|
||||
/* Some generally useful CD-ROM information */
|
||||
#define CD_MINS 75 /* max. minutes per CD */
|
||||
#define CD_SECS 60 /* seconds per minute */
|
||||
#define CD_FRAMES 75 /* frames per second */
|
||||
#define CD_FRAMESIZE 2048 /* bytes per frame, "cooked" mode */
|
||||
#define CD_MAX_BYTES (CD_MINS * CD_SECS * CD_FRAMES * CD_FRAMESIZE)
|
||||
#define CD_MAX_SECTORS (CD_MAX_BYTES / 512)
|
||||
|
||||
/* Event notification classes for GET EVENT STATUS NOTIFICATION */
|
||||
#define GESN_NO_EVENTS 0
|
||||
#define GESN_OPERATIONAL_CHANGE 1
|
||||
#define GESN_POWER_MANAGEMENT 2
|
||||
#define GESN_EXTERNAL_REQUEST 3
|
||||
#define GESN_MEDIA 4
|
||||
#define GESN_MULTIPLE_HOSTS 5
|
||||
#define GESN_DEVICE_BUSY 6
|
||||
|
||||
/* Event codes for MEDIA event status notification */
|
||||
#define MEC_NO_CHANGE 0
|
||||
#define MEC_EJECT_REQUESTED 1
|
||||
#define MEC_NEW_MEDIA 2
|
||||
#define MEC_MEDIA_REMOVAL 3 /* only for media changers */
|
||||
#define MEC_MEDIA_CHANGED 4 /* only for media changers */
|
||||
#define MEC_BG_FORMAT_COMPLETED 5 /* MRW or DVD+RW b/g format completed */
|
||||
#define MEC_BG_FORMAT_RESTARTED 6 /* MRW or DVD+RW b/g format restarted */
|
||||
#define MS_TRAY_OPEN 1
|
||||
#define MS_MEDIA_PRESENT 2
|
||||
|
||||
/*
|
||||
* The MMC values are not IDE specific and might need to be moved
|
||||
* to a common header if they are also needed for the SCSI emulation
|
||||
*/
|
||||
|
||||
/* Profile list from MMC-6 revision 1 table 91 */
|
||||
#define MMC_PROFILE_NONE 0x0000
|
||||
#define MMC_PROFILE_CD_ROM 0x0008
|
||||
#define MMC_PROFILE_CD_R 0x0009
|
||||
#define MMC_PROFILE_CD_RW 0x000A
|
||||
#define MMC_PROFILE_DVD_ROM 0x0010
|
||||
#define MMC_PROFILE_DVD_R_SR 0x0011
|
||||
#define MMC_PROFILE_DVD_RAM 0x0012
|
||||
#define MMC_PROFILE_DVD_RW_RO 0x0013
|
||||
#define MMC_PROFILE_DVD_RW_SR 0x0014
|
||||
#define MMC_PROFILE_DVD_R_DL_SR 0x0015
|
||||
#define MMC_PROFILE_DVD_R_DL_JR 0x0016
|
||||
#define MMC_PROFILE_DVD_RW_DL 0x0017
|
||||
#define MMC_PROFILE_DVD_DDR 0x0018
|
||||
#define MMC_PROFILE_DVD_PLUS_RW 0x001A
|
||||
#define MMC_PROFILE_DVD_PLUS_R 0x001B
|
||||
#define MMC_PROFILE_DVD_PLUS_RW_DL 0x002A
|
||||
#define MMC_PROFILE_DVD_PLUS_R_DL 0x002B
|
||||
#define MMC_PROFILE_BD_ROM 0x0040
|
||||
#define MMC_PROFILE_BD_R_SRM 0x0041
|
||||
#define MMC_PROFILE_BD_R_RRM 0x0042
|
||||
#define MMC_PROFILE_BD_RE 0x0043
|
||||
#define MMC_PROFILE_HDDVD_ROM 0x0050
|
||||
#define MMC_PROFILE_HDDVD_R 0x0051
|
||||
#define MMC_PROFILE_HDDVD_RAM 0x0052
|
||||
#define MMC_PROFILE_HDDVD_RW 0x0053
|
||||
#define MMC_PROFILE_HDDVD_R_DL 0x0058
|
||||
#define MMC_PROFILE_HDDVD_RW_DL 0x005A
|
||||
#define MMC_PROFILE_INVALID 0xFFFF
|
||||
|
||||
#define SCSI_ONLY 32
|
||||
#define ATAPI_ONLY 16
|
||||
#define IMPLEMENTED 8
|
||||
#define NONDATA 4
|
||||
#define CHECK_READY 2
|
||||
#define ALLOW_UA 1
|
||||
|
||||
|
||||
extern uint8_t SCSICommandTable[0x100];
|
||||
extern uint8_t mode_sense_pages[0x40];
|
||||
extern int readcdmode;
|
||||
|
||||
/* Mode sense/select stuff. */
|
||||
extern uint8_t mode_pages_in[256][256];
|
||||
extern uint8_t page_flags[256];
|
||||
extern uint8_t prefix_len;
|
||||
extern uint8_t page_current;
|
||||
#define PAGE_CHANGEABLE 1
|
||||
#define PAGE_CHANGED 2
|
||||
|
||||
struct _scsisense_ {
|
||||
uint8_t SenseBuffer[18];
|
||||
uint8_t SenseLength;
|
||||
uint8_t UnitAttention;
|
||||
uint8_t SenseKey;
|
||||
uint8_t Asc;
|
||||
uint8_t Ascq;
|
||||
} SCSISense;
|
||||
|
||||
extern int cd_status;
|
||||
extern int prev_status;
|
||||
|
||||
enum {
|
||||
SCSI_NONE = 0,
|
||||
SCSI_DISK,
|
||||
SCSI_CDROM,
|
||||
SCSI_ZIP
|
||||
};
|
||||
|
||||
#define MSFtoLBA(m,s,f) ((((m*60)+s)*75)+f)
|
||||
|
||||
#define MSG_COMMAND_COMPLETE 0x00
|
||||
|
||||
#define BUS_DBP 0x01
|
||||
#define BUS_SEL 0x02
|
||||
#define BUS_IO 0x04
|
||||
#define BUS_CD 0x08
|
||||
#define BUS_MSG 0x10
|
||||
#define BUS_REQ 0x20
|
||||
#define BUS_BSY 0x40
|
||||
#define BUS_RST 0x80
|
||||
#define BUS_ACK 0x200
|
||||
#define BUS_ATN 0x200
|
||||
#define BUS_ARB 0x8000
|
||||
#define BUS_SETDATA(val) ((uint32_t)val << 16)
|
||||
#define BUS_GETDATA(val) ((val >> 16) & 0xff)
|
||||
#define BUS_DATAMASK 0xff0000
|
||||
|
||||
#define BUS_IDLE (1 << 31)
|
||||
|
||||
#define SCSI_PHASE_DATA_OUT 0
|
||||
#define SCSI_PHASE_DATA_IN BUS_IO
|
||||
#define SCSI_PHASE_COMMAND BUS_CD
|
||||
#define SCSI_PHASE_STATUS (BUS_CD | BUS_IO)
|
||||
#define SCSI_PHASE_MESSAGE_OUT (BUS_MSG | BUS_CD)
|
||||
#define SCSI_PHASE_MESSAGE_IN (BUS_MSG | BUS_CD | BUS_IO)
|
||||
|
||||
typedef struct {
|
||||
uint8_t *CmdBuffer;
|
||||
int LunType;
|
||||
int32_t BufferLength;
|
||||
uint8_t Status;
|
||||
uint8_t Phase;
|
||||
} scsi_device_t;
|
||||
|
||||
|
||||
extern scsi_device_t SCSIDevices[SCSI_ID_MAX][SCSI_LUN_MAX];
|
||||
|
||||
extern void SCSIReset(uint8_t id, uint8_t lun);
|
||||
|
||||
extern int cdrom_add_error_and_subchannel(uint8_t *b, int real_sector_type);
|
||||
extern int cdrom_LBAtoMSF_accurate(void);
|
||||
|
||||
extern int mode_select_init(uint8_t command, uint16_t pl_length, uint8_t do_save);
|
||||
extern int mode_select_terminate(int force);
|
||||
extern int mode_select_write(uint8_t val);
|
||||
|
||||
extern int scsi_card_current;
|
||||
|
||||
extern int scsi_card_available(int card);
|
||||
extern char *scsi_card_getname(int card);
|
||||
#ifdef EMU_DEVICE_H
|
||||
extern const device_t *scsi_card_getdevice(int card);
|
||||
#endif
|
||||
extern int scsi_card_has_config(int card);
|
||||
extern char *scsi_card_get_internal_name(int card);
|
||||
extern int scsi_card_get_from_internal_name(char *s);
|
||||
extern void scsi_mutex(uint8_t start);
|
||||
extern void scsi_card_init(void);
|
||||
|
||||
extern uint8_t scsi_hard_disks[16][8];
|
||||
|
||||
extern int scsi_hd_err_stat_to_scsi(uint8_t id);
|
||||
extern int scsi_hd_phase_to_scsi(uint8_t id);
|
||||
extern int find_hdc_for_scsi_id(uint8_t scsi_id, uint8_t scsi_lun);
|
||||
extern void build_scsi_hd_map(void);
|
||||
extern void scsi_hd_reset(uint8_t id);
|
||||
extern void scsi_hd_request_sense_for_scsi(uint8_t id, uint8_t *buffer, uint8_t alloc_length);
|
||||
extern void scsi_hd_command(uint8_t id, uint8_t *cdb);
|
||||
extern void scsi_hd_callback(uint8_t id);
|
||||
|
||||
|
||||
#pragma pack(push,1)
|
||||
typedef struct {
|
||||
uint8_t hi;
|
||||
uint8_t mid;
|
||||
uint8_t lo;
|
||||
} addr24;
|
||||
#pragma pack(pop)
|
||||
|
||||
#define ADDR_TO_U32(x) (((x).hi<<16)|((x).mid<<8)|((x).lo&0xFF))
|
||||
#define U32_TO_ADDR(a,x) do {(a).hi=(x)>>16;(a).mid=(x)>>8;(a).lo=(x)&0xFF;}while(0)
|
||||
|
||||
|
||||
/*
|
||||
*
|
||||
* Scatter/Gather Segment List Definitions
|
||||
*
|
||||
* Adapter limits
|
||||
*/
|
||||
#define MAX_SG_DESCRIPTORS 32 /* Always make the array 32 elements long, if less are used, that's not an issue. */
|
||||
|
||||
#pragma pack(push,1)
|
||||
typedef struct {
|
||||
uint32_t Segment;
|
||||
uint32_t SegmentPointer;
|
||||
} SGE32;
|
||||
#pragma pack(pop)
|
||||
|
||||
#pragma pack(push,1)
|
||||
typedef struct {
|
||||
addr24 Segment;
|
||||
addr24 SegmentPointer;
|
||||
} SGE;
|
||||
#pragma pack(pop)
|
||||
|
||||
#pragma pack(push,1)
|
||||
typedef struct {
|
||||
uint8_t pages[0x40][0x40];
|
||||
} mode_sense_pages_t;
|
||||
#pragma pack(pop)
|
||||
|
||||
|
||||
#define MODE_SELECT_PHASE_IDLE 0
|
||||
#define MODE_SELECT_PHASE_HEADER 1
|
||||
#define MODE_SELECT_PHASE_BLOCK_DESC 2
|
||||
#define MODE_SELECT_PHASE_PAGE_HEADER 3
|
||||
#define MODE_SELECT_PHASE_PAGE 4
|
||||
|
||||
#endif /*EMU_SCSI_H*/
|
||||
|
||||
extern void scsi_mutex_wait(uint8_t wait);
|
||||
415
backup code/scsi/scsi_device - Cópia (2).c
Normal file
415
backup code/scsi/scsi_device - Cópia (2).c
Normal file
@@ -0,0 +1,415 @@
|
||||
/*
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
*
|
||||
* This file is part of the 86Box distribution.
|
||||
*
|
||||
* The generic SCSI device command handler.
|
||||
*
|
||||
* Version: @(#)scsi_device.c 1.0.17 2018/06/02
|
||||
*
|
||||
* Authors: Miran Grca, <mgrca8@gmail.com>
|
||||
* Fred N. van Kempen, <decwiz@yahoo.com>
|
||||
*
|
||||
* Copyright 2016-2018 Miran Grca.
|
||||
* Copyright 2017,2018 Fred N. van Kempen.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <wchar.h>
|
||||
#include "../86box.h"
|
||||
#include "../device.h"
|
||||
#include "../disk/hdd.h"
|
||||
#include "scsi.h"
|
||||
#include "scsi_device.h"
|
||||
#include "../cdrom/cdrom.h"
|
||||
#include "../disk/zip.h"
|
||||
#include "scsi_disk.h"
|
||||
|
||||
|
||||
static uint8_t
|
||||
scsi_device_target_command(int lun_type, uint8_t id, uint8_t *cdb)
|
||||
{
|
||||
switch(lun_type) {
|
||||
case SCSI_NULL:
|
||||
scsi_null_command(cdb);
|
||||
return scsi_null_err_stat_to_scsi();
|
||||
case SCSI_DISK:
|
||||
scsi_disk_command(scsi_disk[id], cdb);
|
||||
return scsi_disk_err_stat_to_scsi(scsi_disk[id]);
|
||||
case SCSI_CDROM:
|
||||
cdrom_command(cdrom[id], cdb);
|
||||
return cdrom_CDROM_PHASE_to_scsi(cdrom[id]);
|
||||
case SCSI_ZIP:
|
||||
zip_command(zip[id], cdb);
|
||||
return zip_ZIP_PHASE_to_scsi(zip[id]);
|
||||
default:
|
||||
return SCSI_STATUS_CHECK_CONDITION;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void scsi_device_target_phase_callback(int lun_type, uint8_t id)
|
||||
{
|
||||
switch(lun_type) {
|
||||
case SCSI_NULL:
|
||||
scsi_null_callback();
|
||||
break;
|
||||
case SCSI_DISK:
|
||||
scsi_disk_callback(scsi_disk[id]);
|
||||
break;
|
||||
case SCSI_CDROM:
|
||||
cdrom_phase_callback(cdrom[id]);
|
||||
break;
|
||||
case SCSI_ZIP:
|
||||
zip_phase_callback(zip[id]);
|
||||
break;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
static int scsi_device_target_err_stat_to_scsi(int lun_type, uint8_t id)
|
||||
{
|
||||
switch(lun_type) {
|
||||
case SCSI_NULL:
|
||||
return scsi_null_err_stat_to_scsi();
|
||||
case SCSI_DISK:
|
||||
return scsi_disk_err_stat_to_scsi(scsi_disk[id]);
|
||||
case SCSI_CDROM:
|
||||
return cdrom_CDROM_PHASE_to_scsi(cdrom[id]);
|
||||
case SCSI_ZIP:
|
||||
return zip_ZIP_PHASE_to_scsi(zip[id]);
|
||||
default:
|
||||
return SCSI_STATUS_CHECK_CONDITION;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void scsi_device_target_save_cdb_byte(int lun_type, uint8_t id, uint8_t cdb_byte)
|
||||
{
|
||||
switch(lun_type) {
|
||||
case SCSI_DISK:
|
||||
scsi_disk[id]->request_length = cdb_byte;
|
||||
break;
|
||||
case SCSI_CDROM:
|
||||
cdrom[id]->request_length = cdb_byte;
|
||||
break;
|
||||
case SCSI_ZIP:
|
||||
zip[id]->request_length = cdb_byte;
|
||||
break;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
int64_t scsi_device_get_callback(uint8_t scsi_id, uint8_t scsi_lun)
|
||||
{
|
||||
uint8_t lun_type = SCSIDevices[scsi_id][scsi_lun].LunType;
|
||||
|
||||
uint8_t id = 0;
|
||||
|
||||
switch (lun_type)
|
||||
{
|
||||
case SCSI_DISK:
|
||||
id = scsi_disks[scsi_id][scsi_lun];
|
||||
return scsi_disk[id]->callback;
|
||||
break;
|
||||
case SCSI_CDROM:
|
||||
id = scsi_cdrom_drives[scsi_id][scsi_lun];
|
||||
return cdrom[id]->callback;
|
||||
break;
|
||||
case SCSI_ZIP:
|
||||
id = scsi_zip_drives[scsi_id][scsi_lun];
|
||||
return zip[id]->callback;
|
||||
break;
|
||||
default:
|
||||
return -1LL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
uint8_t *scsi_device_sense(uint8_t scsi_id, uint8_t scsi_lun)
|
||||
{
|
||||
uint8_t lun_type = SCSIDevices[scsi_id][scsi_lun].LunType;
|
||||
|
||||
uint8_t id = 0;
|
||||
|
||||
switch (lun_type)
|
||||
{
|
||||
case SCSI_DISK:
|
||||
id = scsi_disks[scsi_id][scsi_lun];
|
||||
return scsi_disk[id]->sense;
|
||||
break;
|
||||
case SCSI_CDROM:
|
||||
id = scsi_cdrom_drives[scsi_id][scsi_lun];
|
||||
return cdrom[id]->sense;
|
||||
break;
|
||||
case SCSI_ZIP:
|
||||
id = scsi_zip_drives[scsi_id][scsi_lun];
|
||||
return zip[id]->sense;
|
||||
break;
|
||||
default:
|
||||
return scsi_null_device_sense;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void scsi_device_request_sense(uint8_t scsi_id, uint8_t scsi_lun, uint8_t *buffer, uint8_t alloc_length)
|
||||
{
|
||||
uint8_t main_lun_type = SCSIDevices[scsi_id][0].LunType;
|
||||
uint8_t lun_type = SCSIDevices[scsi_id][scsi_lun].LunType;
|
||||
if ((main_lun_type != SCSI_NONE) && (lun_type == SCSI_NONE) && scsi_lun)
|
||||
lun_type = SCSI_NULL;
|
||||
|
||||
uint8_t id = 0;
|
||||
|
||||
switch (lun_type)
|
||||
{
|
||||
case SCSI_NULL:
|
||||
scsi_null_request_sense_for_scsi(buffer, alloc_length);
|
||||
break;
|
||||
case SCSI_DISK:
|
||||
id = scsi_disks[scsi_id][scsi_lun];
|
||||
scsi_disk_request_sense_for_scsi(scsi_disk[id], buffer, alloc_length);
|
||||
break;
|
||||
case SCSI_CDROM:
|
||||
id = scsi_cdrom_drives[scsi_id][scsi_lun];
|
||||
cdrom_request_sense_for_scsi(cdrom[id], buffer, alloc_length);
|
||||
break;
|
||||
case SCSI_ZIP:
|
||||
id = scsi_zip_drives[scsi_id][scsi_lun];
|
||||
zip_request_sense_for_scsi(zip[id], buffer, alloc_length);
|
||||
break;
|
||||
default:
|
||||
memcpy(buffer, scsi_null_device_sense, alloc_length);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void scsi_device_reset(uint8_t scsi_id, uint8_t scsi_lun)
|
||||
{
|
||||
uint8_t main_lun_type = SCSIDevices[scsi_id][0].LunType;
|
||||
uint8_t lun_type = SCSIDevices[scsi_id][scsi_lun].LunType;
|
||||
if ((main_lun_type != SCSI_NONE) && (lun_type == SCSI_NONE) && scsi_lun)
|
||||
lun_type = SCSI_NULL;
|
||||
|
||||
uint8_t id = 0;
|
||||
|
||||
switch (lun_type)
|
||||
{
|
||||
case SCSI_NULL:
|
||||
scsi_null_device_sense[2] = scsi_null_device_sense[12] =
|
||||
scsi_null_device_sense[13] = 0x00;
|
||||
break;
|
||||
case SCSI_DISK:
|
||||
id = scsi_disks[scsi_id][scsi_lun];
|
||||
scsi_disk_reset(scsi_disk[id]);
|
||||
break;
|
||||
case SCSI_CDROM:
|
||||
id = scsi_cdrom_drives[scsi_id][scsi_lun];
|
||||
cdrom_reset(cdrom[id]);
|
||||
break;
|
||||
case SCSI_ZIP:
|
||||
id = scsi_zip_drives[scsi_id][scsi_lun];
|
||||
zip_reset(zip[id]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void scsi_device_type_data(uint8_t scsi_id, uint8_t scsi_lun, uint8_t *type, uint8_t *rmb)
|
||||
{
|
||||
uint8_t lun_type = SCSIDevices[scsi_id][scsi_lun].LunType;
|
||||
|
||||
switch (lun_type)
|
||||
{
|
||||
case SCSI_DISK:
|
||||
*type = *rmb = 0x00;
|
||||
break;
|
||||
case SCSI_CDROM:
|
||||
*type = 0x05;
|
||||
*rmb = 0x80;
|
||||
break;
|
||||
case SCSI_ZIP:
|
||||
*type = 0x00;
|
||||
*rmb = 0x80;
|
||||
break;
|
||||
default:
|
||||
*type = *rmb = 0xff;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int scsi_device_read_capacity(uint8_t scsi_id, uint8_t scsi_lun, uint8_t *cdb, uint8_t *buffer, uint32_t *len)
|
||||
{
|
||||
uint8_t lun_type = SCSIDevices[scsi_id][scsi_lun].LunType;
|
||||
|
||||
uint8_t id = 0;
|
||||
|
||||
switch (lun_type)
|
||||
{
|
||||
case SCSI_DISK:
|
||||
id = scsi_disks[scsi_id][scsi_lun];
|
||||
return scsi_disk_read_capacity(scsi_disk[id], cdb, buffer, len);
|
||||
case SCSI_CDROM:
|
||||
id = scsi_cdrom_drives[scsi_id][scsi_lun];
|
||||
return cdrom_read_capacity(cdrom[id], cdb, buffer, len);
|
||||
case SCSI_ZIP:
|
||||
id = scsi_zip_drives[scsi_id][scsi_lun];
|
||||
return zip_read_capacity(zip[id], cdb, buffer, len);
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int scsi_device_present(uint8_t scsi_id, uint8_t scsi_lun)
|
||||
{
|
||||
uint8_t main_lun_type = SCSIDevices[scsi_id][0].LunType;
|
||||
uint8_t lun_type = SCSIDevices[scsi_id][scsi_lun].LunType;
|
||||
if ((main_lun_type != SCSI_NONE) && (lun_type == SCSI_NONE) && scsi_lun)
|
||||
lun_type = SCSI_NULL;
|
||||
|
||||
switch (lun_type)
|
||||
{
|
||||
case SCSI_NONE:
|
||||
return 0;
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int scsi_device_valid(uint8_t scsi_id, uint8_t scsi_lun)
|
||||
{
|
||||
uint8_t lun_type = SCSIDevices[scsi_id][scsi_lun].LunType;
|
||||
|
||||
uint8_t id = 0;
|
||||
|
||||
switch (lun_type)
|
||||
{
|
||||
case SCSI_DISK:
|
||||
id = scsi_disks[scsi_id][scsi_lun];
|
||||
break;
|
||||
case SCSI_CDROM:
|
||||
id = scsi_cdrom_drives[scsi_id][scsi_lun];
|
||||
break;
|
||||
case SCSI_ZIP:
|
||||
id = scsi_zip_drives[scsi_id][scsi_lun];
|
||||
break;
|
||||
default:
|
||||
id = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
return (id == 0xFF) ? 0 : 1;
|
||||
}
|
||||
|
||||
|
||||
int scsi_device_cdb_length(uint8_t scsi_id, uint8_t scsi_lun)
|
||||
{
|
||||
/* Right now, it's 12 for all devices. */
|
||||
return 12;
|
||||
}
|
||||
|
||||
|
||||
void scsi_device_command_phase0(uint8_t scsi_id, uint8_t scsi_lun, int cdb_len, uint8_t *cdb)
|
||||
{
|
||||
uint8_t id = 0;
|
||||
uint8_t main_lun_type = SCSIDevices[scsi_id][0].LunType;
|
||||
uint8_t lun_type = SCSIDevices[scsi_id][scsi_lun].LunType;
|
||||
if ((main_lun_type != SCSI_NONE) && (lun_type == SCSI_NONE) && scsi_lun)
|
||||
lun_type = SCSI_NULL;
|
||||
|
||||
switch (lun_type) {
|
||||
case SCSI_NULL:
|
||||
id = 0;
|
||||
scsi_null_set_location(scsi_id, scsi_lun);
|
||||
break;
|
||||
case SCSI_DISK:
|
||||
id = scsi_disks[scsi_id][scsi_lun];
|
||||
break;
|
||||
case SCSI_CDROM:
|
||||
id = scsi_cdrom_drives[scsi_id][scsi_lun];
|
||||
break;
|
||||
case SCSI_ZIP:
|
||||
id = scsi_zip_drives[scsi_id][scsi_lun];
|
||||
break;
|
||||
default:
|
||||
id = 0;
|
||||
SCSIDevices[scsi_id][scsi_lun].Phase = SCSI_PHASE_STATUS;
|
||||
SCSIDevices[scsi_id][scsi_lun].Status = SCSI_STATUS_CHECK_CONDITION;
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Since that field in the target struct is never used when
|
||||
* the bus type is SCSI, let's use it for this scope.
|
||||
*/
|
||||
scsi_device_target_save_cdb_byte(lun_type, id, cdb[1]);
|
||||
|
||||
if (cdb_len != 12) {
|
||||
/*
|
||||
* Make sure the LUN field of the temporary CDB is always 0,
|
||||
* otherwise Daemon Tools drives will misbehave when a command
|
||||
* is passed through to them.
|
||||
*/
|
||||
cdb[1] &= 0x1f;
|
||||
}
|
||||
|
||||
/* Finally, execute the SCSI command immediately and get the transfer length. */
|
||||
SCSIDevices[scsi_id][scsi_lun].Phase = SCSI_PHASE_COMMAND;
|
||||
SCSIDevices[scsi_id][scsi_lun].Status = scsi_device_target_command(lun_type, id, cdb);
|
||||
|
||||
if (SCSIDevices[scsi_id][scsi_lun].Phase == SCSI_PHASE_STATUS) {
|
||||
/* Command completed (either OK or error) - call the phase callback to complete the command. */
|
||||
scsi_device_target_phase_callback(lun_type, id);
|
||||
}
|
||||
/* If the phase is DATA IN or DATA OUT, finish this here. */
|
||||
}
|
||||
|
||||
void scsi_device_command_phase1(uint8_t scsi_id, uint8_t scsi_lun)
|
||||
{
|
||||
uint8_t id = 0;
|
||||
uint8_t main_lun_type = SCSIDevices[scsi_id][0].LunType;
|
||||
uint8_t lun_type = SCSIDevices[scsi_id][scsi_lun].LunType;
|
||||
if ((main_lun_type != SCSI_NONE) && (lun_type == SCSI_NONE) && scsi_lun)
|
||||
lun_type = SCSI_NULL;
|
||||
|
||||
switch (lun_type) {
|
||||
case SCSI_NULL:
|
||||
id = 0;
|
||||
break;
|
||||
case SCSI_DISK:
|
||||
id = scsi_disks[scsi_id][scsi_lun];
|
||||
break;
|
||||
case SCSI_CDROM:
|
||||
id = scsi_cdrom_drives[scsi_id][scsi_lun];
|
||||
break;
|
||||
case SCSI_ZIP:
|
||||
id = scsi_zip_drives[scsi_id][scsi_lun];
|
||||
break;
|
||||
default:
|
||||
id = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Call the second phase. */
|
||||
scsi_device_target_phase_callback(lun_type, id);
|
||||
SCSIDevices[scsi_id][scsi_lun].Status = scsi_device_target_err_stat_to_scsi(lun_type, id);
|
||||
/* Command second phase complete - call the callback to complete the command. */
|
||||
scsi_device_target_phase_callback(lun_type, id);
|
||||
}
|
||||
|
||||
int32_t *scsi_device_get_buf_len(uint8_t scsi_id, uint8_t scsi_lun)
|
||||
{
|
||||
return &SCSIDevices[scsi_id][scsi_lun].BufferLength;
|
||||
}
|
||||
416
backup code/scsi/scsi_device - Cópia.c
Normal file
416
backup code/scsi/scsi_device - Cópia.c
Normal file
@@ -0,0 +1,416 @@
|
||||
/*
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
*
|
||||
* This file is part of the 86Box distribution.
|
||||
*
|
||||
* The generic SCSI device command handler.
|
||||
*
|
||||
* Version: @(#)scsi_device.c 1.0.16 2018/03/26
|
||||
*
|
||||
* Authors: Miran Grca, <mgrca8@gmail.com>
|
||||
* Fred N. van Kempen, <decwiz@yahoo.com>
|
||||
*
|
||||
* Copyright 2016-2018 Miran Grca.
|
||||
* Copyright 2017,2018 Fred N. van Kempen.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <wchar.h>
|
||||
#include "../86box.h"
|
||||
#include "../device.h"
|
||||
#include "../disk/hdd.h"
|
||||
#include "../disk/zip.h"
|
||||
#include "scsi.h"
|
||||
#include "../cdrom/cdrom.h"
|
||||
#include "scsi_disk.h"
|
||||
|
||||
|
||||
static uint8_t scsi_null_device_sense[14] = { 0x70,0,SENSE_ILLEGAL_REQUEST,0,0,0,0,0,0,0,0,0,ASC_INV_LUN,0 };
|
||||
|
||||
|
||||
static uint8_t scsi_device_target_command(int lun_type, uint8_t id, uint8_t *cdb)
|
||||
{
|
||||
if (lun_type == SCSI_DISK)
|
||||
{
|
||||
scsi_hd_command(id, cdb);
|
||||
return scsi_hd_err_stat_to_scsi(id);
|
||||
}
|
||||
else if (lun_type == SCSI_CDROM)
|
||||
{
|
||||
cdrom_command(cdrom[id], cdb);
|
||||
return cdrom_CDROM_PHASE_to_scsi(cdrom[id]);
|
||||
}
|
||||
else if (lun_type == SCSI_ZIP)
|
||||
{
|
||||
zip_command(id, cdb);
|
||||
return zip_ZIP_PHASE_to_scsi(id);
|
||||
}
|
||||
else
|
||||
{
|
||||
return SCSI_STATUS_CHECK_CONDITION;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void scsi_device_target_phase_callback(int lun_type, uint8_t id)
|
||||
{
|
||||
if (lun_type == SCSI_DISK)
|
||||
{
|
||||
scsi_hd_callback(id);
|
||||
}
|
||||
else if (lun_type == SCSI_CDROM)
|
||||
{
|
||||
cdrom_phase_callback(cdrom[id]);
|
||||
}
|
||||
else if (lun_type == SCSI_ZIP)
|
||||
{
|
||||
zip_phase_callback(id);
|
||||
}
|
||||
else
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int scsi_device_target_err_stat_to_scsi(int lun_type, uint8_t id)
|
||||
{
|
||||
if (lun_type == SCSI_DISK)
|
||||
{
|
||||
return scsi_hd_err_stat_to_scsi(id);
|
||||
}
|
||||
else if (lun_type == SCSI_CDROM)
|
||||
{
|
||||
return cdrom_CDROM_PHASE_to_scsi(cdrom[id]);
|
||||
}
|
||||
else if (lun_type == SCSI_ZIP)
|
||||
{
|
||||
return zip_ZIP_PHASE_to_scsi(id);
|
||||
}
|
||||
else
|
||||
{
|
||||
return SCSI_STATUS_CHECK_CONDITION;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void scsi_device_target_save_cdb_byte(int lun_type, uint8_t id, uint8_t cdb_byte)
|
||||
{
|
||||
if (lun_type == SCSI_DISK)
|
||||
{
|
||||
shdc[id].request_length = cdb_byte;
|
||||
}
|
||||
else if (lun_type == SCSI_CDROM)
|
||||
{
|
||||
cdrom[id]->request_length = cdb_byte;
|
||||
}
|
||||
else if (lun_type == SCSI_ZIP)
|
||||
{
|
||||
zip[id]->request_length = cdb_byte;
|
||||
}
|
||||
else
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int64_t scsi_device_get_callback(uint8_t scsi_id, uint8_t scsi_lun)
|
||||
{
|
||||
uint8_t lun_type = SCSIDevices[scsi_id][scsi_lun].LunType;
|
||||
|
||||
uint8_t id = 0;
|
||||
|
||||
switch (lun_type)
|
||||
{
|
||||
case SCSI_DISK:
|
||||
id = scsi_hard_disks[scsi_id][scsi_lun];
|
||||
return shdc[id].callback;
|
||||
break;
|
||||
case SCSI_CDROM:
|
||||
id = scsi_cdrom_drives[scsi_id][scsi_lun];
|
||||
return cdrom[id]->callback;
|
||||
break;
|
||||
case SCSI_ZIP:
|
||||
id = scsi_zip_drives[scsi_id][scsi_lun];
|
||||
return zip[id]->callback;
|
||||
break;
|
||||
default:
|
||||
return -1LL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
uint8_t *scsi_device_sense(uint8_t scsi_id, uint8_t scsi_lun)
|
||||
{
|
||||
uint8_t lun_type = SCSIDevices[scsi_id][scsi_lun].LunType;
|
||||
|
||||
uint8_t id = 0;
|
||||
|
||||
switch (lun_type)
|
||||
{
|
||||
case SCSI_DISK:
|
||||
id = scsi_hard_disks[scsi_id][scsi_lun];
|
||||
return shdc[id].sense;
|
||||
break;
|
||||
case SCSI_CDROM:
|
||||
id = scsi_cdrom_drives[scsi_id][scsi_lun];
|
||||
return cdrom[id]->sense;
|
||||
break;
|
||||
case SCSI_ZIP:
|
||||
id = scsi_zip_drives[scsi_id][scsi_lun];
|
||||
return zip[id]->sense;
|
||||
break;
|
||||
default:
|
||||
return scsi_null_device_sense;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void scsi_device_request_sense(uint8_t scsi_id, uint8_t scsi_lun, uint8_t *buffer, uint8_t alloc_length)
|
||||
{
|
||||
uint8_t lun_type = SCSIDevices[scsi_id][scsi_lun].LunType;
|
||||
|
||||
uint8_t id = 0;
|
||||
|
||||
switch (lun_type)
|
||||
{
|
||||
case SCSI_DISK:
|
||||
id = scsi_hard_disks[scsi_id][scsi_lun];
|
||||
scsi_hd_request_sense_for_scsi(id, buffer, alloc_length);
|
||||
break;
|
||||
case SCSI_CDROM:
|
||||
id = scsi_cdrom_drives[scsi_id][scsi_lun];
|
||||
cdrom_request_sense_for_scsi(cdrom[id], buffer, alloc_length);
|
||||
break;
|
||||
case SCSI_ZIP:
|
||||
id = scsi_zip_drives[scsi_id][scsi_lun];
|
||||
zip_request_sense_for_scsi(id, buffer, alloc_length);
|
||||
break;
|
||||
default:
|
||||
memcpy(buffer, scsi_null_device_sense, alloc_length);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void scsi_device_reset(uint8_t scsi_id, uint8_t scsi_lun)
|
||||
{
|
||||
uint8_t lun_type = SCSIDevices[scsi_id][scsi_lun].LunType;
|
||||
|
||||
uint8_t id = 0;
|
||||
|
||||
switch (lun_type)
|
||||
{
|
||||
case SCSI_DISK:
|
||||
id = scsi_hard_disks[scsi_id][scsi_lun];
|
||||
scsi_hd_reset(id);
|
||||
break;
|
||||
case SCSI_CDROM:
|
||||
id = scsi_cdrom_drives[scsi_id][scsi_lun];
|
||||
cdrom_reset(cdrom[id]);
|
||||
break;
|
||||
case SCSI_ZIP:
|
||||
id = scsi_zip_drives[scsi_id][scsi_lun];
|
||||
zip_reset(id);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void scsi_device_type_data(uint8_t scsi_id, uint8_t scsi_lun, uint8_t *type, uint8_t *rmb)
|
||||
{
|
||||
uint8_t lun_type = SCSIDevices[scsi_id][scsi_lun].LunType;
|
||||
|
||||
switch (lun_type)
|
||||
{
|
||||
case SCSI_DISK:
|
||||
*type = *rmb = 0x00;
|
||||
break;
|
||||
case SCSI_CDROM:
|
||||
*type = 0x05;
|
||||
*rmb = 0x80;
|
||||
break;
|
||||
case SCSI_ZIP:
|
||||
*type = 0x00;
|
||||
*rmb = 0x80;
|
||||
break;
|
||||
default:
|
||||
*type = *rmb = 0xff;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int scsi_device_read_capacity(uint8_t scsi_id, uint8_t scsi_lun, uint8_t *cdb, uint8_t *buffer, uint32_t *len)
|
||||
{
|
||||
uint8_t lun_type = SCSIDevices[scsi_id][scsi_lun].LunType;
|
||||
|
||||
uint8_t id = 0;
|
||||
|
||||
switch (lun_type)
|
||||
{
|
||||
case SCSI_DISK:
|
||||
id = scsi_hard_disks[scsi_id][scsi_lun];
|
||||
return scsi_hd_read_capacity(id, cdb, buffer, len);
|
||||
case SCSI_CDROM:
|
||||
id = scsi_cdrom_drives[scsi_id][scsi_lun];
|
||||
return cdrom_read_capacity(cdrom[id], cdb, buffer, len);
|
||||
case SCSI_ZIP:
|
||||
id = scsi_zip_drives[scsi_id][scsi_lun];
|
||||
return zip_read_capacity(id, cdb, buffer, len);
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int scsi_device_present(uint8_t scsi_id, uint8_t scsi_lun)
|
||||
{
|
||||
uint8_t lun_type = SCSIDevices[scsi_id][scsi_lun].LunType;
|
||||
|
||||
switch (lun_type)
|
||||
{
|
||||
case SCSI_NONE:
|
||||
return 0;
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int scsi_device_valid(uint8_t scsi_id, uint8_t scsi_lun)
|
||||
{
|
||||
uint8_t lun_type = SCSIDevices[scsi_id][scsi_lun].LunType;
|
||||
|
||||
uint8_t id = 0;
|
||||
|
||||
switch (lun_type)
|
||||
{
|
||||
case SCSI_DISK:
|
||||
id = scsi_hard_disks[scsi_id][scsi_lun];
|
||||
break;
|
||||
case SCSI_CDROM:
|
||||
id = scsi_cdrom_drives[scsi_id][scsi_lun];
|
||||
break;
|
||||
case SCSI_ZIP:
|
||||
id = scsi_zip_drives[scsi_id][scsi_lun];
|
||||
break;
|
||||
default:
|
||||
id = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
return (id == 0xFF) ? 0 : 1;
|
||||
}
|
||||
|
||||
|
||||
int scsi_device_cdb_length(uint8_t scsi_id, uint8_t scsi_lun)
|
||||
{
|
||||
uint8_t lun_type = SCSIDevices[scsi_id][scsi_lun].LunType;
|
||||
|
||||
uint8_t id = 0;
|
||||
|
||||
switch (lun_type)
|
||||
{
|
||||
case SCSI_CDROM:
|
||||
id = scsi_cdrom_drives[scsi_id][scsi_lun];
|
||||
return cdrom[id]->cdb_len;
|
||||
case SCSI_ZIP:
|
||||
id = scsi_zip_drives[scsi_id][scsi_lun];
|
||||
return zip[id]->cdb_len;
|
||||
default:
|
||||
return 12;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void scsi_device_command_phase0(uint8_t scsi_id, uint8_t scsi_lun, int cdb_len, uint8_t *cdb)
|
||||
{
|
||||
uint8_t lun_type = SCSIDevices[scsi_id][scsi_lun].LunType;
|
||||
|
||||
uint8_t id = 0;
|
||||
|
||||
switch (lun_type)
|
||||
{
|
||||
case SCSI_DISK:
|
||||
id = scsi_hard_disks[scsi_id][scsi_lun];
|
||||
break;
|
||||
case SCSI_CDROM:
|
||||
id = scsi_cdrom_drives[scsi_id][scsi_lun];
|
||||
break;
|
||||
case SCSI_ZIP:
|
||||
id = scsi_zip_drives[scsi_id][scsi_lun];
|
||||
break;
|
||||
default:
|
||||
id = 0;
|
||||
SCSIDevices[scsi_id][scsi_lun].Phase = SCSI_PHASE_STATUS;
|
||||
SCSIDevices[scsi_id][scsi_lun].Status = SCSI_STATUS_CHECK_CONDITION;
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Since that field in the target struct is never used when
|
||||
* the bus type is SCSI, let's use it for this scope.
|
||||
*/
|
||||
scsi_device_target_save_cdb_byte(lun_type, id, cdb[1]);
|
||||
|
||||
if (cdb_len != 12) {
|
||||
/*
|
||||
* Make sure the LUN field of the temporary CDB is always 0,
|
||||
* otherwise Daemon Tools drives will misbehave when a command
|
||||
* is passed through to them.
|
||||
*/
|
||||
cdb[1] &= 0x1f;
|
||||
}
|
||||
|
||||
/* Finally, execute the SCSI command immediately and get the transfer length. */
|
||||
SCSIDevices[scsi_id][scsi_lun].Phase = SCSI_PHASE_COMMAND;
|
||||
SCSIDevices[scsi_id][scsi_lun].Status = scsi_device_target_command(lun_type, id, cdb);
|
||||
|
||||
if (SCSIDevices[scsi_id][scsi_lun].Phase == SCSI_PHASE_STATUS) {
|
||||
/* Command completed (either OK or error) - call the phase callback to complete the command. */
|
||||
scsi_device_target_phase_callback(lun_type, id);
|
||||
}
|
||||
/* If the phase is DATA IN or DATA OUT, finish this here. */
|
||||
}
|
||||
|
||||
void scsi_device_command_phase1(uint8_t scsi_id, uint8_t scsi_lun)
|
||||
{
|
||||
uint8_t lun_type = SCSIDevices[scsi_id][scsi_lun].LunType;
|
||||
|
||||
uint8_t id = 0;
|
||||
|
||||
switch (lun_type)
|
||||
{
|
||||
case SCSI_DISK:
|
||||
id = scsi_hard_disks[scsi_id][scsi_lun];
|
||||
break;
|
||||
case SCSI_CDROM:
|
||||
id = scsi_cdrom_drives[scsi_id][scsi_lun];
|
||||
break;
|
||||
case SCSI_ZIP:
|
||||
id = scsi_zip_drives[scsi_id][scsi_lun];
|
||||
break;
|
||||
default:
|
||||
id = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Call the second phase. */
|
||||
scsi_device_target_phase_callback(lun_type, id);
|
||||
SCSIDevices[scsi_id][scsi_lun].Status = scsi_device_target_err_stat_to_scsi(lun_type, id);
|
||||
/* Command second phase complete - call the callback to complete the command. */
|
||||
scsi_device_target_phase_callback(lun_type, id);
|
||||
}
|
||||
|
||||
int32_t *scsi_device_get_buf_len(uint8_t scsi_id, uint8_t scsi_lun)
|
||||
{
|
||||
return &SCSIDevices[scsi_id][scsi_lun].BufferLength;
|
||||
}
|
||||
69
backup code/scsi/scsi_device - Cópia.h
Normal file
69
backup code/scsi/scsi_device - Cópia.h
Normal file
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
*
|
||||
* This file is part of the 86Box distribution.
|
||||
*
|
||||
* Definitions for the generic SCSI device command handler.
|
||||
*
|
||||
* Version: @(#)scsi_device.h 1.0.8 2018/06/12
|
||||
*
|
||||
* Authors: Miran Grca, <mgrca8@gmail.com>
|
||||
* Fred N. van Kempen, <decwiz@yahoo.com>
|
||||
*/
|
||||
#ifndef SCSI_DEVICE_H
|
||||
# define SCSI_DEVICE_H
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int state;
|
||||
int new_state;
|
||||
int clear_req;
|
||||
uint32_t bus_in, bus_out;
|
||||
int dev_id;
|
||||
|
||||
int command_pos;
|
||||
uint8_t command[20];
|
||||
int data_pos;
|
||||
|
||||
int change_state_delay;
|
||||
int new_req_delay;
|
||||
} scsi_bus_t;
|
||||
|
||||
extern uint8_t *scsi_device_sense(uint8_t id, uint8_t lun);
|
||||
extern void scsi_device_type_data(uint8_t id, uint8_t lun,
|
||||
uint8_t *type, uint8_t *rmb);
|
||||
extern int64_t scsi_device_get_callback(uint8_t scsi_id, uint8_t scsi_lun);
|
||||
extern void scsi_device_request_sense(uint8_t scsi_id, uint8_t scsi_lun,
|
||||
uint8_t *buffer,
|
||||
uint8_t alloc_length);
|
||||
extern void scsi_device_reset(uint8_t scsi_id, uint8_t scsi_lun);
|
||||
extern int scsi_device_read_capacity(uint8_t id, uint8_t lun,
|
||||
uint8_t *cdb, uint8_t *buffer,
|
||||
uint32_t *len);
|
||||
extern int scsi_device_present(uint8_t id, uint8_t lun);
|
||||
extern int scsi_device_valid(uint8_t id, uint8_t lun);
|
||||
extern int scsi_device_cdb_length(uint8_t id, uint8_t lun);
|
||||
extern void scsi_device_command(uint8_t id, uint8_t lun, int cdb_len,
|
||||
uint8_t *cdb);
|
||||
extern void scsi_device_command_phase0(uint8_t scsi_id, uint8_t scsi_lun,
|
||||
int cdb_len, uint8_t *cdb);
|
||||
extern void scsi_device_command_phase1(uint8_t scsi_id, uint8_t scsi_lun);
|
||||
extern int32_t *scsi_device_get_buf_len(uint8_t scsi_id, uint8_t scsi_lun);
|
||||
|
||||
extern int scsi_bus_update(scsi_bus_t *bus, int bus_assert);
|
||||
extern int scsi_bus_read(scsi_bus_t *bus);
|
||||
extern int scsi_bus_match(scsi_bus_t *bus, int bus_assert);
|
||||
|
||||
extern int scsi_null_err_stat_to_scsi(void);
|
||||
extern void scsi_null_request_sense(uint8_t *buffer, uint8_t alloc_length, int desc);
|
||||
extern void scsi_null_request_sense_for_scsi(uint8_t *buffer, uint8_t alloc_length);
|
||||
extern void scsi_null_command(uint8_t *cdb);
|
||||
extern void scsi_null_callback(void);
|
||||
extern void scsi_null_set_location(uint8_t id, uint8_t lun);
|
||||
|
||||
extern uint8_t scsi_null_device_sense[18];
|
||||
|
||||
#endif /*SCSI_DEVICE_H*/
|
||||
1291
backup code/scsi/scsi_disk - Cópia.c
Normal file
1291
backup code/scsi/scsi_disk - Cópia.c
Normal file
File diff suppressed because it is too large
Load Diff
45
backup code/scsi/scsi_disk - Cópia.h
Normal file
45
backup code/scsi/scsi_disk - Cópia.h
Normal file
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
*
|
||||
* Emulation of SCSI fixed and removable disks.
|
||||
*
|
||||
* Version: @(#)scsi_disk.h 1.0.4 2018/04/24
|
||||
*
|
||||
* Author: Miran Grca, <mgrca8@gmail.com>
|
||||
* Copyright 2017,2018 Miran Grca.
|
||||
*/
|
||||
|
||||
|
||||
typedef struct {
|
||||
/* Stuff for SCSI hard disks. */
|
||||
uint8_t status, phase,
|
||||
error,
|
||||
current_cdb[16],
|
||||
sense[256];
|
||||
|
||||
uint16_t request_length;
|
||||
|
||||
int requested_blocks, block_total,
|
||||
packet_status, callback,
|
||||
block_descriptor_len,
|
||||
total_length, do_page_save;
|
||||
|
||||
uint32_t sector_pos, sector_len,
|
||||
packet_len;
|
||||
|
||||
uint64_t current_page_code;
|
||||
|
||||
uint8_t *temp_buffer;
|
||||
} scsi_hard_disk_t;
|
||||
|
||||
|
||||
extern scsi_hard_disk_t shdc[HDD_NUM];
|
||||
extern FILE *shdf[HDD_NUM];
|
||||
|
||||
|
||||
extern void scsi_loadhd(int scsi_id, int scsi_lun, int id);
|
||||
|
||||
int scsi_hd_read_capacity(uint8_t id, uint8_t *cdb, uint8_t *buffer, uint32_t *len);
|
||||
395
backup code/scsi/scsi_null.c
Normal file
395
backup code/scsi/scsi_null.c
Normal file
@@ -0,0 +1,395 @@
|
||||
/*
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
*
|
||||
* Emulation of SCSI null device, used for invalid LUN's where
|
||||
* LUN 0 is valid.
|
||||
*
|
||||
* Version: @(#)scsi_null.c 1.0.0 2018/06/12
|
||||
*
|
||||
* Author: Miran Grca, <mgrca8@gmail.com>
|
||||
*
|
||||
* Copyright 2017,2018 Miran Grca.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include <wchar.h>
|
||||
#define HAVE_STDARG_H
|
||||
#include "../86box.h"
|
||||
#include "../timer.h"
|
||||
#include "../device.h"
|
||||
#include "../nvr.h"
|
||||
#include "../disk/hdd.h"
|
||||
#include "../disk/hdc.h"
|
||||
#include "../disk/hdc_ide.h"
|
||||
#include "../plat.h"
|
||||
#include "../ui.h"
|
||||
#include "scsi.h"
|
||||
#include "../cdrom/cdrom.h"
|
||||
#include "scsi_device.h"
|
||||
|
||||
|
||||
/* Bits of 'status' */
|
||||
#define ERR_STAT 0x01
|
||||
#define DRQ_STAT 0x08 /* Data request */
|
||||
#define DSC_STAT 0x10
|
||||
#define SERVICE_STAT 0x10
|
||||
#define READY_STAT 0x40
|
||||
#define BUSY_STAT 0x80
|
||||
|
||||
/* Bits of 'error' */
|
||||
#define ABRT_ERR 0x04 /* Command aborted */
|
||||
#define MCR_ERR 0x08 /* Media change request */
|
||||
|
||||
#define MAX_BLOCKS_AT_ONCE 340
|
||||
|
||||
|
||||
#define scsi_null_sense_key scsi_null_device_sense[2]
|
||||
#define scsi_null_asc scsi_null_device_sense[12]
|
||||
#define scsi_null_ascq scsi_null_device_sense[13]
|
||||
|
||||
|
||||
static uint8_t status, phase, packet_status, error, command, packet_len, sense_desc;
|
||||
static int64_t callback;
|
||||
static uint8_t null_id, null_lun;
|
||||
static uint8_t *temp_buffer;
|
||||
|
||||
|
||||
|
||||
#ifdef ENABLE_SCSI_NULL_LOG
|
||||
int scsi_null_do_log = ENABLE_SCSI_NULL_LOG;
|
||||
#endif
|
||||
|
||||
|
||||
static void
|
||||
scsi_null_log(const char *fmt, ...)
|
||||
{
|
||||
#ifdef ENABLE_SCSI_NULL_LOG
|
||||
va_list ap;
|
||||
|
||||
if (scsi_null_do_log) {
|
||||
va_start(ap, fmt);
|
||||
pclog_ex(fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/* Translates ATAPI status (ERR_STAT flag) to SCSI status. */
|
||||
int
|
||||
scsi_null_err_stat_to_scsi(void)
|
||||
{
|
||||
if (status & ERR_STAT)
|
||||
return SCSI_STATUS_CHECK_CONDITION;
|
||||
else
|
||||
return SCSI_STATUS_OK;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
scsi_null_command_common(void)
|
||||
{
|
||||
status = BUSY_STAT;
|
||||
phase = 1;
|
||||
if (packet_status == CDROM_PHASE_COMPLETE) {
|
||||
scsi_null_callback();
|
||||
callback = 0LL;
|
||||
} else
|
||||
callback = -1LL; /* Speed depends on SCSI controller */
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
scsi_null_command_complete(void)
|
||||
{
|
||||
packet_status = CDROM_PHASE_COMPLETE;
|
||||
scsi_null_command_common();
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
scsi_null_command_read_dma(void)
|
||||
{
|
||||
packet_status = CDROM_PHASE_DATA_IN_DMA;
|
||||
scsi_null_command_common();
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
scsi_null_data_command_finish(int len, int block_len, int alloc_len, int direction)
|
||||
{
|
||||
if (alloc_len >= 0) {
|
||||
if (alloc_len < len)
|
||||
len = alloc_len;
|
||||
}
|
||||
if (len == 0)
|
||||
scsi_null_command_complete();
|
||||
else {
|
||||
if (direction == 0)
|
||||
scsi_null_command_read_dma();
|
||||
else
|
||||
fatal("SCSI NULL device write command\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
scsi_null_set_phase(uint8_t phase)
|
||||
{
|
||||
SCSIDevices[null_id][null_lun].Phase = phase;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
scsi_null_cmd_error(void)
|
||||
{
|
||||
scsi_null_set_phase(SCSI_PHASE_STATUS);
|
||||
error = ((scsi_null_sense_key & 0xf) << 4) | ABRT_ERR;
|
||||
status = READY_STAT | ERR_STAT;
|
||||
phase = 3;
|
||||
packet_status = 0x80;
|
||||
callback = 50 * SCSI_TIME;
|
||||
scsi_null_log("SCSI NULL: ERROR: %02X/%02X/%02X\n", scsi_null_sense_key, scsi_null_asc, scsi_null_ascq);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
scsi_null_invalid_lun(void)
|
||||
{
|
||||
scsi_null_sense_key = SENSE_ILLEGAL_REQUEST;
|
||||
scsi_null_asc = ASC_INV_LUN;
|
||||
scsi_null_ascq = 0;
|
||||
scsi_null_set_phase(SCSI_PHASE_STATUS);
|
||||
scsi_null_cmd_error();
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
scsi_null_invalid_field(void)
|
||||
{
|
||||
scsi_null_sense_key = SENSE_ILLEGAL_REQUEST;
|
||||
scsi_null_asc = ASC_INV_FIELD_IN_CMD_PACKET;
|
||||
scsi_null_ascq = 0;
|
||||
scsi_null_cmd_error();
|
||||
status = 0x53;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
scsi_null_request_sense(uint8_t *buffer, uint8_t alloc_length, int desc)
|
||||
{
|
||||
/*Will return 18 bytes of 0*/
|
||||
if (alloc_length != 0) {
|
||||
memset(buffer, 0, alloc_length);
|
||||
if (!desc)
|
||||
if (alloc_length <= 18)
|
||||
memcpy(buffer, scsi_null_device_sense, alloc_length);
|
||||
else {
|
||||
memset(buffer, 0x00, alloc_length);
|
||||
memcpy(buffer, scsi_null_device_sense, 18);
|
||||
}
|
||||
else {
|
||||
buffer[1] = scsi_null_sense_key;
|
||||
buffer[2] = scsi_null_asc;
|
||||
buffer[3] = scsi_null_ascq;
|
||||
}
|
||||
} else
|
||||
return;
|
||||
|
||||
buffer[0] = 0x70;
|
||||
|
||||
scsi_null_log("SCSI NULL: Reporting sense: %02X %02X %02X\n", buffer[2], buffer[12], buffer[13]);
|
||||
|
||||
/* Clear the sense stuff as per the spec. */
|
||||
scsi_null_sense_key = scsi_null_asc = scsi_null_ascq = 0x00;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
scsi_null_request_sense_for_scsi(uint8_t *buffer, uint8_t alloc_length)
|
||||
{
|
||||
scsi_null_request_sense(buffer, alloc_length, 0);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
scsi_null_command(uint8_t *cdb)
|
||||
{
|
||||
int32_t *BufLen;
|
||||
uint32_t len;
|
||||
int max_len;
|
||||
unsigned idx = 0;
|
||||
unsigned size_idx, preamble_len;
|
||||
|
||||
BufLen = &SCSIDevices[null_id][null_lun].BufferLength;
|
||||
|
||||
status &= ~ERR_STAT;
|
||||
packet_len = 0;
|
||||
|
||||
scsi_null_set_phase(SCSI_PHASE_STATUS);
|
||||
|
||||
command = cdb[0];
|
||||
switch (cdb[0]) {
|
||||
case GPCMD_REQUEST_SENSE:
|
||||
/* If there's a unit attention condition and there's a buffered not ready, a standalone REQUEST SENSE
|
||||
should forget about the not ready, and report unit attention straight away. */
|
||||
sense_desc = cdb [1];
|
||||
|
||||
if ((*BufLen == -1) || (cdb[4] < *BufLen))
|
||||
*BufLen = cdb[4];
|
||||
|
||||
if (*BufLen < cdb[4])
|
||||
cdb[4] = *BufLen;
|
||||
|
||||
len = (cdb[1] & 1) ? 8 : 18;
|
||||
|
||||
scsi_null_set_phase(SCSI_PHASE_DATA_IN);
|
||||
scsi_null_data_command_finish(len, len, cdb[4], 0);
|
||||
break;
|
||||
|
||||
#if 0
|
||||
case GPCMD_INQUIRY:
|
||||
max_len = cdb[3];
|
||||
max_len <<= 8;
|
||||
max_len |= cdb[4];
|
||||
|
||||
if ((!max_len) || (*BufLen == 0)) {
|
||||
scsi_null_set_phase(SCSI_PHASE_STATUS);
|
||||
packet_status = CDROM_PHASE_COMPLETE;
|
||||
callback = 20 * SCSI_TIME;
|
||||
break;
|
||||
}
|
||||
|
||||
if (cdb[1] & 1) {
|
||||
scsi_null_invalid_field();
|
||||
return;
|
||||
} else {
|
||||
temp_buffer = malloc(1024);
|
||||
|
||||
preamble_len = 5;
|
||||
size_idx = 4;
|
||||
|
||||
memset(temp_buffer, 0, 8);
|
||||
temp_buffer[0] = (3 << 5); /*Invalid*/
|
||||
temp_buffer[1] = 0; /*Fixed*/
|
||||
temp_buffer[2] = 0x02; /*SCSI-2 compliant*/
|
||||
temp_buffer[3] = 0x02;
|
||||
temp_buffer[4] = 31;
|
||||
temp_buffer[6] = 1; /* 16-bit transfers supported */
|
||||
temp_buffer[7] = 0x20; /* Wide bus supported */
|
||||
|
||||
ide_padstr8(temp_buffer + 8, 8, EMU_NAME); /* Vendor */
|
||||
ide_padstr8(temp_buffer + 16, 16, "INVALID"); /* Product */
|
||||
ide_padstr8(temp_buffer + 32, 4, EMU_VERSION); /* Revision */
|
||||
idx = 36;
|
||||
|
||||
if (max_len == 96) {
|
||||
temp_buffer[4] = 91;
|
||||
idx = 96;
|
||||
}
|
||||
}
|
||||
|
||||
temp_buffer[size_idx] = idx - preamble_len;
|
||||
len=idx;
|
||||
|
||||
if (len > max_len)
|
||||
len = max_len;
|
||||
|
||||
if ((*BufLen == -1) || (len < *BufLen))
|
||||
*BufLen = len;
|
||||
|
||||
if (len > *BufLen)
|
||||
len = *BufLen;
|
||||
|
||||
scsi_null_set_phase(SCSI_PHASE_DATA_IN);
|
||||
scsi_null_data_command_finish(len, len, max_len, 0);
|
||||
break;
|
||||
#endif
|
||||
|
||||
default:
|
||||
scsi_null_invalid_lun();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
scsi_null_phase_data_in(void)
|
||||
{
|
||||
uint8_t *hdbufferb = SCSIDevices[null_id][null_lun].CmdBuffer;
|
||||
int32_t *BufLen = &SCSIDevices[null_id][null_lun].BufferLength;
|
||||
|
||||
if (!*BufLen) {
|
||||
scsi_null_log("scsi_null_phase_data_in(): Buffer length is 0\n");
|
||||
scsi_null_set_phase(SCSI_PHASE_STATUS);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
switch (command) {
|
||||
case GPCMD_REQUEST_SENSE:
|
||||
scsi_null_log("SCSI NULL: %08X, %08X\n", hdbufferb, *BufLen);
|
||||
scsi_null_request_sense(hdbufferb, *BufLen, sense_desc & 1);
|
||||
break;
|
||||
#if 0
|
||||
case GPCMD_INQUIRY:
|
||||
memcpy(hdbufferb, temp_buffer, *BufLen);
|
||||
free(temp_buffer);
|
||||
temp_buffer = NULL;
|
||||
scsi_null_log("%02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X\n",
|
||||
hdbufferb[0], hdbufferb[1], hdbufferb[2], hdbufferb[3], hdbufferb[4], hdbufferb[5], hdbufferb[6], hdbufferb[7],
|
||||
hdbufferb[8], hdbufferb[9], hdbufferb[10], hdbufferb[11], hdbufferb[12], hdbufferb[13], hdbufferb[14], hdbufferb[15]);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
fatal("SCSI NULL: Bad Command for phase 2 (%02X)\n", command);
|
||||
break;
|
||||
}
|
||||
|
||||
scsi_null_set_phase(SCSI_PHASE_STATUS);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
scsi_null_callback(void)
|
||||
{
|
||||
switch(packet_status) {
|
||||
case CDROM_PHASE_IDLE:
|
||||
scsi_null_log("SCSI NULL: PHASE_IDLE\n");
|
||||
phase = 1;
|
||||
status = READY_STAT | DRQ_STAT | (status & ERR_STAT);
|
||||
return;
|
||||
case CDROM_PHASE_COMPLETE:
|
||||
scsi_null_log("SCSI NULL: PHASE_COMPLETE\n");
|
||||
status = READY_STAT;
|
||||
phase = 3;
|
||||
packet_status = 0xFF;
|
||||
return;
|
||||
case CDROM_PHASE_DATA_IN_DMA:
|
||||
scsi_null_log("SCSI NULL: PHASE_DATA_IN_DMA\n");
|
||||
scsi_null_phase_data_in();
|
||||
packet_status = CDROM_PHASE_COMPLETE;
|
||||
status = READY_STAT;
|
||||
phase = 3;
|
||||
return;
|
||||
case CDROM_PHASE_ERROR:
|
||||
scsi_null_log("SCSI NULL: PHASE_ERROR\n");
|
||||
status = READY_STAT | ERR_STAT;
|
||||
phase = 3;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
scsi_null_set_location(uint8_t id, uint8_t lun)
|
||||
{
|
||||
null_id = id;
|
||||
null_lun = lun;
|
||||
}
|
||||
305
backup code/video - Cópia/vid_ati18800.c
Normal file
305
backup code/video - Cópia/vid_ati18800.c
Normal file
@@ -0,0 +1,305 @@
|
||||
/*
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
*
|
||||
* This file is part of the 86Box distribution.
|
||||
*
|
||||
* ATI 18800 emulation (VGA Edge-16)
|
||||
*
|
||||
* Version: @(#)vid_ati18800.c 1.0.12 2018/04/29
|
||||
*
|
||||
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
*
|
||||
* Copyright 2008-2018 Sarah Walker.
|
||||
* Copyright 2016-2018 Miran Grca.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <wchar.h>
|
||||
#include "../86box.h"
|
||||
#include "../cpu/cpu.h"
|
||||
#include "../io.h"
|
||||
#include "../mem.h"
|
||||
#include "../rom.h"
|
||||
#include "../device.h"
|
||||
#include "video.h"
|
||||
#include "vid_ati18800.h"
|
||||
#include "vid_ati_eeprom.h"
|
||||
#include "vid_svga.h"
|
||||
#include "vid_svga_render.h"
|
||||
|
||||
|
||||
#if defined(DEV_BRANCH) && defined(USE_VGAWONDER)
|
||||
#define BIOS_ROM_PATH_WONDER L"roms/video/ati18800/VGA_Wonder_V3-1.02.bin"
|
||||
#endif
|
||||
#define BIOS_ROM_PATH_VGA88 L"roms/video/ati18800/vga88.bin"
|
||||
#define BIOS_ROM_PATH_EDGE16 L"roms/video/ati18800/vgaedge16.vbi"
|
||||
|
||||
enum {
|
||||
#if defined(DEV_BRANCH) && defined(USE_VGAWONDER)
|
||||
ATI18800_WONDER = 0,
|
||||
ATI18800_VGA88,
|
||||
ATI18800_EDGE16
|
||||
#else
|
||||
ATI18800_VGA88 = 0,
|
||||
ATI18800_EDGE16
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
typedef struct ati18800_t
|
||||
{
|
||||
svga_t svga;
|
||||
ati_eeprom_t eeprom;
|
||||
|
||||
rom_t bios_rom;
|
||||
|
||||
uint8_t regs[256];
|
||||
int index;
|
||||
} ati18800_t;
|
||||
|
||||
|
||||
static void ati18800_out(uint16_t addr, uint8_t val, void *p)
|
||||
{
|
||||
ati18800_t *ati18800 = (ati18800_t *)p;
|
||||
svga_t *svga = &ati18800->svga;
|
||||
uint8_t old;
|
||||
|
||||
if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(svga->miscout & 1))
|
||||
addr ^= 0x60;
|
||||
|
||||
switch (addr)
|
||||
{
|
||||
case 0x1ce:
|
||||
ati18800->index = val;
|
||||
break;
|
||||
case 0x1cf:
|
||||
ati18800->regs[ati18800->index] = val;
|
||||
switch (ati18800->index)
|
||||
{
|
||||
case 0xb0:
|
||||
svga_recalctimings(svga);
|
||||
case 0xb2:
|
||||
case 0xbe:
|
||||
if (ati18800->regs[0xbe] & 8) /*Read/write bank mode*/
|
||||
{
|
||||
svga->read_bank = ((ati18800->regs[0xb2] >> 5) & 7) * 0x10000;
|
||||
svga->write_bank = ((ati18800->regs[0xb2] >> 1) & 7) * 0x10000;
|
||||
}
|
||||
else /*Single bank mode*/
|
||||
svga->read_bank = svga->write_bank = ((ati18800->regs[0xb2] >> 1) & 7) * 0x10000;
|
||||
break;
|
||||
case 0xb3:
|
||||
ati_eeprom_write(&ati18800->eeprom, val & 8, val & 2, val & 1);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x3D4:
|
||||
svga->crtcreg = val & 0x3f;
|
||||
return;
|
||||
case 0x3D5:
|
||||
if ((svga->crtcreg < 7) && (svga->crtc[0x11] & 0x80) && !(ati18800->regs[0xb4] & 0x80))
|
||||
return;
|
||||
if ((svga->crtcreg == 7) && (svga->crtc[0x11] & 0x80) && !(ati18800->regs[0xb4] & 0x80))
|
||||
val = (svga->crtc[7] & ~0x10) | (val & 0x10);
|
||||
old = svga->crtc[svga->crtcreg];
|
||||
svga->crtc[svga->crtcreg] = val;
|
||||
if (old != val)
|
||||
{
|
||||
if (svga->crtcreg < 0xe || svga->crtcreg > 0x10)
|
||||
{
|
||||
svga->fullchange = changeframecount;
|
||||
svga_recalctimings(svga);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
svga_out(addr, val, svga);
|
||||
}
|
||||
|
||||
static uint8_t ati18800_in(uint16_t addr, void *p)
|
||||
{
|
||||
ati18800_t *ati18800 = (ati18800_t *)p;
|
||||
svga_t *svga = &ati18800->svga;
|
||||
uint8_t temp;
|
||||
|
||||
if (((addr&0xFFF0) == 0x3D0 || (addr&0xFFF0) == 0x3B0) && !(svga->miscout&1)) addr ^= 0x60;
|
||||
|
||||
switch (addr)
|
||||
{
|
||||
case 0x1ce:
|
||||
temp = ati18800->index;
|
||||
break;
|
||||
case 0x1cf:
|
||||
switch (ati18800->index)
|
||||
{
|
||||
case 0xb7:
|
||||
temp = ati18800->regs[ati18800->index] & ~8;
|
||||
if (ati_eeprom_read(&ati18800->eeprom))
|
||||
temp |= 8;
|
||||
break;
|
||||
default:
|
||||
temp = ati18800->regs[ati18800->index];
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x3D4:
|
||||
temp = svga->crtcreg;
|
||||
break;
|
||||
case 0x3D5:
|
||||
temp = svga->crtc[svga->crtcreg];
|
||||
break;
|
||||
default:
|
||||
temp = svga_in(addr, svga);
|
||||
break;
|
||||
}
|
||||
return temp;
|
||||
}
|
||||
|
||||
static void ati18800_recalctimings(svga_t *svga)
|
||||
{
|
||||
ati18800_t *ati18800 = (ati18800_t *)svga->p;
|
||||
|
||||
if(svga->crtc[0x17] & 4)
|
||||
{
|
||||
svga->vtotal <<= 1;
|
||||
svga->dispend <<= 1;
|
||||
svga->vsyncstart <<= 1;
|
||||
svga->split <<= 1;
|
||||
svga->vblankstart <<= 1;
|
||||
}
|
||||
|
||||
if (!svga->scrblank && (ati18800->regs[0xb0] & 0x20)) /*Extended 256 colour modes*/
|
||||
{
|
||||
svga->render = svga_render_8bpp_highres;
|
||||
svga->bpp = 8;
|
||||
svga->rowoffset <<= 1;
|
||||
svga->ma <<= 1;
|
||||
}
|
||||
}
|
||||
|
||||
static void *ati18800_init(const device_t *info)
|
||||
{
|
||||
ati18800_t *ati18800 = malloc(sizeof(ati18800_t));
|
||||
memset(ati18800, 0, sizeof(ati18800_t));
|
||||
|
||||
switch (info->local) {
|
||||
#if defined(DEV_BRANCH) && defined(USE_VGAWONDER)
|
||||
case ATI18800_WONDER:
|
||||
#endif
|
||||
default:
|
||||
#if defined(DEV_BRANCH) && defined(USE_VGAWONDER)
|
||||
rom_init(&ati18800->bios_rom, BIOS_ROM_PATH_WONDER, 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL);
|
||||
break;
|
||||
#endif
|
||||
case ATI18800_VGA88:
|
||||
rom_init(&ati18800->bios_rom, BIOS_ROM_PATH_VGA88, 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL);
|
||||
break;
|
||||
case ATI18800_EDGE16:
|
||||
rom_init(&ati18800->bios_rom, BIOS_ROM_PATH_EDGE16, 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL);
|
||||
break;
|
||||
};
|
||||
|
||||
svga_init(&ati18800->svga, ati18800, 1 << 19, /*512kb*/
|
||||
ati18800_recalctimings,
|
||||
ati18800_in, ati18800_out,
|
||||
NULL,
|
||||
NULL);
|
||||
|
||||
io_sethandler(0x01ce, 0x0002, ati18800_in, NULL, NULL, ati18800_out, NULL, NULL, ati18800);
|
||||
io_sethandler(0x03c0, 0x0020, ati18800_in, NULL, NULL, ati18800_out, NULL, NULL, ati18800);
|
||||
|
||||
ati18800->svga.miscout = 1;
|
||||
|
||||
ati_eeprom_load(&ati18800->eeprom, L"ati18800.nvr", 0);
|
||||
|
||||
return ati18800;
|
||||
}
|
||||
|
||||
#if defined(DEV_BRANCH) && defined(USE_VGAWONDER)
|
||||
static int ati18800_wonder_available(void)
|
||||
{
|
||||
return rom_present(BIOS_ROM_PATH_WONDER);
|
||||
}
|
||||
#endif
|
||||
|
||||
static int ati18800_vga88_available(void)
|
||||
{
|
||||
return rom_present(BIOS_ROM_PATH_VGA88);
|
||||
}
|
||||
|
||||
static int ati18800_available(void)
|
||||
{
|
||||
return rom_present(BIOS_ROM_PATH_EDGE16);
|
||||
}
|
||||
|
||||
static void ati18800_close(void *p)
|
||||
{
|
||||
ati18800_t *ati18800 = (ati18800_t *)p;
|
||||
|
||||
svga_close(&ati18800->svga);
|
||||
|
||||
free(ati18800);
|
||||
}
|
||||
|
||||
static void ati18800_speed_changed(void *p)
|
||||
{
|
||||
ati18800_t *ati18800 = (ati18800_t *)p;
|
||||
|
||||
svga_recalctimings(&ati18800->svga);
|
||||
}
|
||||
|
||||
static void ati18800_force_redraw(void *p)
|
||||
{
|
||||
ati18800_t *ati18800 = (ati18800_t *)p;
|
||||
|
||||
ati18800->svga.fullchange = changeframecount;
|
||||
}
|
||||
|
||||
#if defined(DEV_BRANCH) && defined(USE_VGAWONDER)
|
||||
const device_t ati18800_wonder_device =
|
||||
{
|
||||
"ATI-18800",
|
||||
DEVICE_ISA, ATI18800_WONDER,
|
||||
ati18800_init,
|
||||
ati18800_close,
|
||||
NULL,
|
||||
ati18800_wonder_available,
|
||||
ati18800_speed_changed,
|
||||
ati18800_force_redraw,
|
||||
NULL
|
||||
};
|
||||
#endif
|
||||
|
||||
const device_t ati18800_vga88_device =
|
||||
{
|
||||
"ATI-18800-1",
|
||||
DEVICE_ISA, ATI18800_VGA88,
|
||||
ati18800_init,
|
||||
ati18800_close,
|
||||
NULL,
|
||||
ati18800_vga88_available,
|
||||
ati18800_speed_changed,
|
||||
ati18800_force_redraw,
|
||||
NULL
|
||||
};
|
||||
|
||||
const device_t ati18800_device =
|
||||
{
|
||||
"ATI-18800-5",
|
||||
DEVICE_ISA, ATI18800_EDGE16,
|
||||
ati18800_init,
|
||||
ati18800_close,
|
||||
NULL,
|
||||
ati18800_available,
|
||||
ati18800_speed_changed,
|
||||
ati18800_force_redraw,
|
||||
NULL
|
||||
};
|
||||
6
backup code/video - Cópia/vid_ati18800.h
Normal file
6
backup code/video - Cópia/vid_ati18800.h
Normal file
@@ -0,0 +1,6 @@
|
||||
/* Copyright holders: Sarah Walker
|
||||
see COPYING for more details
|
||||
*/
|
||||
extern const device_t ati18800_wonder_device;
|
||||
extern const device_t ati18800_vga88_device;
|
||||
extern const device_t ati18800_device;
|
||||
645
backup code/video - Cópia/vid_ati28800.c
Normal file
645
backup code/video - Cópia/vid_ati28800.c
Normal file
@@ -0,0 +1,645 @@
|
||||
/*
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
*
|
||||
* This file is part of the 86Box distribution.
|
||||
*
|
||||
* ATI 28800 emulation (VGA Charger and Korean VGA)
|
||||
*
|
||||
* Version: @(#)vid_ati28800.c 1.0.19 2018/05/20
|
||||
*
|
||||
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
* greatpsycho,
|
||||
*
|
||||
* Copyright 2008-2018 Sarah Walker.
|
||||
* Copyright 2016-2018 Miran Grca.
|
||||
* Copyright 2018 greatpsycho.
|
||||
*/
|
||||
#include <stdarg.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <wchar.h>
|
||||
#define HAVE_STDARG_H
|
||||
#include "../86box.h"
|
||||
#include "../cpu/cpu.h"
|
||||
#include "../io.h"
|
||||
#include "../pit.h"
|
||||
#include "../mem.h"
|
||||
#include "../rom.h"
|
||||
#include "../device.h"
|
||||
#include "../timer.h"
|
||||
#include "video.h"
|
||||
#include "vid_ati28800.h"
|
||||
#include "vid_ati_eeprom.h"
|
||||
#include "vid_svga.h"
|
||||
#include "vid_svga_render.h"
|
||||
|
||||
|
||||
#define BIOS_ATIKOR_PATH L"roms/video/ati28800/atikorvga.bin"
|
||||
#define FONT_ATIKOR_PATH L"roms/video/ati28800/ati_ksc5601.rom"
|
||||
|
||||
#define BIOS_VGAXL_EVEN_PATH L"roms/video/ati28800/xleven.bin"
|
||||
#define BIOS_VGAXL_ODD_PATH L"roms/video/ati28800/xlodd.bin"
|
||||
|
||||
#if defined(DEV_BRANCH) && defined(USE_XL24)
|
||||
#define BIOS_XL24_EVEN_PATH L"roms/video/ati28800/112-14318-102.bin"
|
||||
#define BIOS_XL24_ODD_PATH L"roms/video/ati28800/112-14319-102.bin"
|
||||
#endif
|
||||
|
||||
#define BIOS_ROM_PATH L"roms/video/ati28800/bios.bin"
|
||||
|
||||
|
||||
typedef struct ati28800_t
|
||||
{
|
||||
svga_t svga;
|
||||
ati_eeprom_t eeprom;
|
||||
|
||||
rom_t bios_rom;
|
||||
|
||||
uint8_t regs[256];
|
||||
int index;
|
||||
|
||||
uint32_t memory;
|
||||
|
||||
uint8_t port_03dd_val;
|
||||
uint16_t get_korean_font_kind;
|
||||
int in_get_korean_font_kind_set;
|
||||
int get_korean_font_enabled;
|
||||
int get_korean_font_index;
|
||||
uint16_t get_korean_font_base;
|
||||
int ksc5601_mode_enabled;
|
||||
} ati28800_t;
|
||||
|
||||
|
||||
#ifdef ENABLE_ATI28800_LOG
|
||||
int ati28800_do_log = ENABLE_ATI28800_LOG;
|
||||
#endif
|
||||
|
||||
|
||||
static void
|
||||
ati28800_log(const char *fmt, ...)
|
||||
{
|
||||
#ifdef ENABLE_ATI28800_LOG
|
||||
va_list ap;
|
||||
|
||||
if (ati28800_do_log) {
|
||||
va_start(ap, fmt);
|
||||
pclog_ex(fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
static void ati28800_out(uint16_t addr, uint8_t val, void *p)
|
||||
{
|
||||
ati28800_t *ati28800 = (ati28800_t *)p;
|
||||
svga_t *svga = &ati28800->svga;
|
||||
uint8_t old;
|
||||
|
||||
ati28800_log("ati28800_out : %04X %02X %04X:%04X\n", addr, val, CS, cpu_state.pc);
|
||||
|
||||
if (((addr&0xFFF0) == 0x3D0 || (addr&0xFFF0) == 0x3B0) && !(svga->miscout&1))
|
||||
addr ^= 0x60;
|
||||
|
||||
switch (addr)
|
||||
{
|
||||
case 0x1ce:
|
||||
ati28800->index = val;
|
||||
break;
|
||||
case 0x1cf:
|
||||
old=ati28800->regs[ati28800->index];
|
||||
ati28800->regs[ati28800->index] = val;
|
||||
switch (ati28800->index)
|
||||
{
|
||||
case 0xb2:
|
||||
case 0xbe:
|
||||
if (ati28800->regs[0xbe] & 8) /*Read/write bank mode*/
|
||||
{
|
||||
svga->read_bank = ((ati28800->regs[0xb2] >> 5) & 7) * 0x10000;
|
||||
svga->write_bank = ((ati28800->regs[0xb2] >> 1) & 7) * 0x10000;
|
||||
}
|
||||
else /*Single bank mode*/
|
||||
svga->read_bank = svga->write_bank = ((ati28800->regs[0xb2] >> 1) & 7) * 0x10000;
|
||||
break;
|
||||
case 0xb3:
|
||||
ati_eeprom_write(&ati28800->eeprom, val & 8, val & 2, val & 1);
|
||||
break;
|
||||
case 0xb6:
|
||||
if((old ^ val) & 0x10) svga_recalctimings(svga);
|
||||
break;
|
||||
case 0xb8:
|
||||
if((old ^ val) & 0x40) svga_recalctimings(svga);
|
||||
break;
|
||||
case 0xb9:
|
||||
if((old ^ val) & 2) svga_recalctimings(svga);
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x3D4:
|
||||
svga->crtcreg = val & 0x3f;
|
||||
return;
|
||||
case 0x3D5:
|
||||
if ((svga->crtcreg < 7) && (svga->crtc[0x11] & 0x80))
|
||||
return;
|
||||
if ((svga->crtcreg == 7) && (svga->crtc[0x11] & 0x80))
|
||||
val = (svga->crtc[7] & ~0x10) | (val & 0x10);
|
||||
old = svga->crtc[svga->crtcreg];
|
||||
svga->crtc[svga->crtcreg] = val;
|
||||
if (old != val)
|
||||
{
|
||||
if (svga->crtcreg < 0xe || svga->crtcreg > 0x10)
|
||||
{
|
||||
svga->fullchange = changeframecount;
|
||||
svga_recalctimings(svga);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
svga_out(addr, val, svga);
|
||||
}
|
||||
|
||||
void ati28800k_out(uint16_t addr, uint8_t val, void *p)
|
||||
{
|
||||
ati28800_t *ati28800 = (ati28800_t *)p;
|
||||
svga_t *svga = &ati28800->svga;
|
||||
uint16_t oldaddr = addr;
|
||||
|
||||
if (((addr&0xFFF0) == 0x3D0 || (addr&0xFFF0) == 0x3B0) && !(svga->miscout&1))
|
||||
addr ^= 0x60;
|
||||
|
||||
switch (addr)
|
||||
{
|
||||
case 0x1CF:
|
||||
if(ati28800->index == 0xBF && ((ati28800->regs[0xBF] ^ val) & 0x20))
|
||||
{
|
||||
ati28800->ksc5601_mode_enabled = val & 0x20;
|
||||
svga_recalctimings(svga);
|
||||
|
||||
}
|
||||
ati28800_out(oldaddr, val, p);
|
||||
break;
|
||||
case 0x3DD:
|
||||
ati28800->port_03dd_val = val;
|
||||
if(val == 1) ati28800->get_korean_font_enabled = 0;
|
||||
if(ati28800->in_get_korean_font_kind_set)
|
||||
{
|
||||
ati28800->get_korean_font_kind = (val << 8) | (ati28800->get_korean_font_kind & 0xFF);
|
||||
ati28800->get_korean_font_enabled = 1;
|
||||
ati28800->get_korean_font_index = 0;
|
||||
ati28800->in_get_korean_font_kind_set = 0;
|
||||
}
|
||||
break;
|
||||
case 0x3DE:
|
||||
ati28800->in_get_korean_font_kind_set = 0;
|
||||
if(ati28800->get_korean_font_enabled && (ati28800->regs[0xBF] & 0x20))
|
||||
{
|
||||
if((ati28800->get_korean_font_base & 0x7F) > 0x20 && (ati28800->get_korean_font_base & 0x7F) < 0x7F)
|
||||
fontdatksc5601_user[(ati28800->get_korean_font_kind & 4) * 24 + (ati28800->get_korean_font_base & 0x7F) - 0x20].chr[ati28800->get_korean_font_index] = val;
|
||||
ati28800->get_korean_font_index++;
|
||||
ati28800->get_korean_font_index &= 0x1F;
|
||||
}
|
||||
else
|
||||
|
||||
{
|
||||
switch(ati28800->port_03dd_val)
|
||||
{
|
||||
case 0x10:
|
||||
ati28800->get_korean_font_base = ((val & 0x7F) << 7) | (ati28800->get_korean_font_base & 0x7F);
|
||||
break;
|
||||
case 8:
|
||||
ati28800->get_korean_font_base = (ati28800->get_korean_font_base & 0x3F80) | (val & 0x7F);
|
||||
break;
|
||||
case 1:
|
||||
ati28800->get_korean_font_kind = (ati28800->get_korean_font_kind & 0xFF00) | val;
|
||||
if(val & 2)
|
||||
ati28800->in_get_korean_font_kind_set = 1;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
ati28800_out(oldaddr, val, p);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static uint8_t ati28800_in(uint16_t addr, void *p)
|
||||
{
|
||||
ati28800_t *ati28800 = (ati28800_t *)p;
|
||||
svga_t *svga = &ati28800->svga;
|
||||
uint8_t temp;
|
||||
|
||||
if (addr != 0x3da) ati28800_log("ati28800_in : %04X ", addr);
|
||||
|
||||
if (((addr&0xFFF0) == 0x3D0 || (addr&0xFFF0) == 0x3B0) && !(svga->miscout&1)) addr ^= 0x60;
|
||||
|
||||
switch (addr)
|
||||
{
|
||||
case 0x1ce:
|
||||
temp = ati28800->index;
|
||||
break;
|
||||
case 0x1cf:
|
||||
switch (ati28800->index)
|
||||
{
|
||||
case 0xb0:
|
||||
if (ati28800->memory == 256)
|
||||
return 0x08;
|
||||
else if (ati28800->memory == 512)
|
||||
return 0x10;
|
||||
else
|
||||
return 0x18;
|
||||
break;
|
||||
|
||||
case 0xb7:
|
||||
temp = ati28800->regs[ati28800->index] & ~8;
|
||||
if (ati_eeprom_read(&ati28800->eeprom))
|
||||
temp |= 8;
|
||||
break;
|
||||
|
||||
default:
|
||||
temp = ati28800->regs[ati28800->index];
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x3c2:
|
||||
if ((svga->vgapal[0].r + svga->vgapal[0].g + svga->vgapal[0].b) >= 0x50)
|
||||
temp = 0;
|
||||
else
|
||||
temp = 0x10;
|
||||
break;
|
||||
case 0x3D4:
|
||||
temp = svga->crtcreg;
|
||||
break;
|
||||
case 0x3D5:
|
||||
temp = svga->crtc[svga->crtcreg];
|
||||
break;
|
||||
default:
|
||||
temp = svga_in(addr, svga);
|
||||
break;
|
||||
}
|
||||
if (addr != 0x3da) ati28800_log("%02X %04X:%04X\n", temp, CS,cpu_state.pc);
|
||||
return temp;
|
||||
}
|
||||
|
||||
uint8_t ati28800k_in(uint16_t addr, void *p)
|
||||
{
|
||||
ati28800_t *ati28800 = (ati28800_t *)p;
|
||||
svga_t *svga = &ati28800->svga;
|
||||
uint16_t oldaddr = addr;
|
||||
uint8_t temp = 0xFF;
|
||||
|
||||
if (addr != 0x3da) ati28800_log("ati28800k_in : %04X ", addr);
|
||||
|
||||
if (((addr&0xFFF0) == 0x3D0 || (addr&0xFFF0) == 0x3B0) && !(svga->miscout&1)) addr ^= 0x60;
|
||||
|
||||
switch (addr)
|
||||
{
|
||||
case 0x3DE:
|
||||
if (ati28800->get_korean_font_enabled && (ati28800->regs[0xBF] & 0x20))
|
||||
{
|
||||
switch(ati28800->get_korean_font_kind >> 8)
|
||||
{
|
||||
case 4: /* ROM font */
|
||||
temp = fontdatksc5601[ati28800->get_korean_font_base].chr[ati28800->get_korean_font_index++];
|
||||
break;
|
||||
case 2: /* User defined font */
|
||||
if((ati28800->get_korean_font_base & 0x7F) > 0x20 && (ati28800->get_korean_font_base & 0x7F) < 0x7F)
|
||||
temp = fontdatksc5601_user[(ati28800->get_korean_font_kind & 4) * 24 + (ati28800->get_korean_font_base & 0x7F) - 0x20].chr[ati28800->get_korean_font_index];
|
||||
else
|
||||
temp = 0xFF;
|
||||
ati28800->get_korean_font_index++;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
ati28800->get_korean_font_index &= 0x1F;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
temp = ati28800_in(oldaddr, p);
|
||||
break;
|
||||
}
|
||||
if (addr != 0x3da) ati28800_log("%02X %04X:%04X\n", temp, CS,cpu_state.pc);
|
||||
return temp;
|
||||
}
|
||||
|
||||
static void ati28800_recalctimings(svga_t *svga)
|
||||
{
|
||||
ati28800_t *ati28800 = (ati28800_t *)svga->p;
|
||||
|
||||
switch(((ati28800->regs[0xbe] & 0x10) >> 1) | ((ati28800->regs[0xb9] & 2) << 1) | ((svga->miscout & 0x0C) >> 2))
|
||||
{
|
||||
case 0x00: svga->clock = cpuclock / 42954000.0; break;
|
||||
case 0x01: svga->clock = cpuclock / 48771000.0; break;
|
||||
case 0x03: svga->clock = cpuclock / 36000000.0; break;
|
||||
case 0x04: svga->clock = cpuclock / 50350000.0; break;
|
||||
case 0x05: svga->clock = cpuclock / 56640000.0; break;
|
||||
case 0x07: svga->clock = cpuclock / 44900000.0; break;
|
||||
case 0x08: svga->clock = cpuclock / 30240000.0; break;
|
||||
case 0x09: svga->clock = cpuclock / 32000000.0; break;
|
||||
case 0x0A: svga->clock = cpuclock / 37500000.0; break;
|
||||
case 0x0B: svga->clock = cpuclock / 39000000.0; break;
|
||||
case 0x0C: svga->clock = cpuclock / 40000000.0; break;
|
||||
case 0x0D: svga->clock = cpuclock / 56644000.0; break;
|
||||
case 0x0E: svga->clock = cpuclock / 75000000.0; break;
|
||||
case 0x0F: svga->clock = cpuclock / 65000000.0; break;
|
||||
default: break;
|
||||
}
|
||||
|
||||
if(ati28800->regs[0xb8] & 0x40) svga->clock *= 2;
|
||||
|
||||
|
||||
if (ati28800->regs[0xb6] & 0x10)
|
||||
{
|
||||
svga->hdisp <<= 1;
|
||||
svga->htotal <<= 1;
|
||||
svga->rowoffset <<= 1;
|
||||
}
|
||||
|
||||
if(svga->crtc[0x17] & 4)
|
||||
{
|
||||
svga->vtotal <<= 1;
|
||||
svga->dispend <<= 1;
|
||||
svga->vsyncstart <<= 1;
|
||||
svga->split <<= 1;
|
||||
svga->vblankstart <<= 1;
|
||||
}
|
||||
|
||||
if (!svga->scrblank && (ati28800->regs[0xb0] & 0x20)) /*Extended 256 colour modes*/
|
||||
{
|
||||
svga->render = svga_render_8bpp_highres;
|
||||
svga->bpp = 8;
|
||||
svga->rowoffset <<= 1;
|
||||
svga->ma <<= 1;
|
||||
}
|
||||
}
|
||||
|
||||
void ati28800k_recalctimings(svga_t *svga)
|
||||
{
|
||||
ati28800_t *ati28800 = (ati28800_t *) svga->p;
|
||||
|
||||
ati28800_recalctimings(svga);
|
||||
|
||||
if (svga->render == svga_render_text_80 && ati28800->ksc5601_mode_enabled)
|
||||
{
|
||||
svga->render = svga_render_text_80_ksc5601;
|
||||
}
|
||||
}
|
||||
|
||||
void *
|
||||
ati28800k_init(const device_t *info)
|
||||
{
|
||||
ati28800_t *ati28800 = malloc(sizeof(ati28800_t));
|
||||
memset(ati28800, 0, sizeof(ati28800_t));
|
||||
|
||||
ati28800->memory = device_get_config_int("memory");
|
||||
|
||||
ati28800->port_03dd_val = 0;
|
||||
ati28800->get_korean_font_base = 0;
|
||||
ati28800->get_korean_font_index = 0;
|
||||
ati28800->get_korean_font_enabled = 0;
|
||||
ati28800->get_korean_font_kind = 0;
|
||||
ati28800->in_get_korean_font_kind_set = 0;
|
||||
ati28800->ksc5601_mode_enabled = 0;
|
||||
|
||||
rom_init(&ati28800->bios_rom, BIOS_ATIKOR_PATH, 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL);
|
||||
loadfont(FONT_ATIKOR_PATH, 6);
|
||||
|
||||
svga_init(&ati28800->svga, ati28800, ati28800->memory << 10, /*Memory size, default 512KB*/
|
||||
ati28800k_recalctimings,
|
||||
ati28800k_in, ati28800k_out,
|
||||
NULL,
|
||||
NULL);
|
||||
|
||||
io_sethandler(0x01ce, 0x0002, ati28800k_in, NULL, NULL, ati28800k_out, NULL, NULL, ati28800);
|
||||
io_sethandler(0x03c0, 0x0020, ati28800k_in, NULL, NULL, ati28800k_out, NULL, NULL, ati28800);
|
||||
|
||||
ati28800->svga.miscout = 1;
|
||||
|
||||
ati_eeprom_load(&ati28800->eeprom, L"atikorvga.nvr", 0);
|
||||
|
||||
return ati28800;
|
||||
}
|
||||
|
||||
static void *
|
||||
ati28800_init(const device_t *info)
|
||||
{
|
||||
ati28800_t *ati;
|
||||
ati = malloc(sizeof(ati28800_t));
|
||||
memset(ati, 0x00, sizeof(ati28800_t));
|
||||
|
||||
ati->memory = device_get_config_int("memory");
|
||||
|
||||
switch(info->local) {
|
||||
case GFX_VGAWONDERXL:
|
||||
rom_init_interleaved(&ati->bios_rom,
|
||||
BIOS_VGAXL_EVEN_PATH,
|
||||
BIOS_VGAXL_ODD_PATH,
|
||||
0xc0000, 0x10000, 0xffff,
|
||||
0, MEM_MAPPING_EXTERNAL);
|
||||
break;
|
||||
|
||||
#if defined(DEV_BRANCH) && defined(USE_XL24)
|
||||
case GFX_VGAWONDERXL24:
|
||||
rom_init_interleaved(&ati->bios_rom,
|
||||
BIOS_XL24_EVEN_PATH,
|
||||
BIOS_XL24_ODD_PATH,
|
||||
0xc0000, 0x10000, 0xffff,
|
||||
0, MEM_MAPPING_EXTERNAL);
|
||||
break;
|
||||
#endif
|
||||
|
||||
default:
|
||||
rom_init(&ati->bios_rom,
|
||||
BIOS_ROM_PATH,
|
||||
0xc0000, 0x8000, 0x7fff,
|
||||
0, MEM_MAPPING_EXTERNAL);
|
||||
break;
|
||||
}
|
||||
|
||||
svga_init(&ati->svga, ati, ati->memory << 10, /*default: 512kb*/
|
||||
ati28800_recalctimings,
|
||||
ati28800_in, ati28800_out,
|
||||
NULL,
|
||||
NULL);
|
||||
|
||||
io_sethandler(0x01ce, 2,
|
||||
ati28800_in, NULL, NULL,
|
||||
ati28800_out, NULL, NULL, ati);
|
||||
io_sethandler(0x03c0, 32,
|
||||
ati28800_in, NULL, NULL,
|
||||
ati28800_out, NULL, NULL, ati);
|
||||
|
||||
ati->svga.miscout = 1;
|
||||
|
||||
ati_eeprom_load(&ati->eeprom, L"ati28800.nvr", 0);
|
||||
|
||||
return(ati);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
ati28800_available(void)
|
||||
{
|
||||
return(rom_present(BIOS_ROM_PATH));
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
ati28800k_available()
|
||||
{
|
||||
return ((rom_present(BIOS_ATIKOR_PATH) && rom_present(FONT_ATIKOR_PATH)));
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
compaq_ati28800_available(void)
|
||||
{
|
||||
return((rom_present(BIOS_VGAXL_EVEN_PATH) && rom_present(BIOS_VGAXL_ODD_PATH)));
|
||||
}
|
||||
|
||||
|
||||
#if defined(DEV_BRANCH) && defined(USE_XL24)
|
||||
static int
|
||||
ati28800_wonderxl24_available(void)
|
||||
{
|
||||
return((rom_present(BIOS_XL24_EVEN_PATH) && rom_present(BIOS_XL24_ODD_PATH)));
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
static void
|
||||
ati28800_close(void *priv)
|
||||
{
|
||||
ati28800_t *ati = (ati28800_t *)priv;
|
||||
|
||||
svga_close(&ati->svga);
|
||||
|
||||
free(ati);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
ati28800_speed_changed(void *p)
|
||||
{
|
||||
ati28800_t *ati28800 = (ati28800_t *)p;
|
||||
|
||||
svga_recalctimings(&ati28800->svga);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
ati28800_force_redraw(void *priv)
|
||||
{
|
||||
ati28800_t *ati = (ati28800_t *)priv;
|
||||
|
||||
ati->svga.fullchange = changeframecount;
|
||||
}
|
||||
|
||||
|
||||
static const device_config_t ati28800_config[] =
|
||||
{
|
||||
{
|
||||
"memory", "Memory size", CONFIG_SELECTION, "", 512,
|
||||
{
|
||||
{
|
||||
"256 kB", 256
|
||||
},
|
||||
{
|
||||
"512 kB", 512
|
||||
},
|
||||
{
|
||||
"1024 kB", 1024
|
||||
},
|
||||
{
|
||||
""
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"", "", -1
|
||||
}
|
||||
};
|
||||
|
||||
#if defined(DEV_BRANCH) && defined(USE_XL24)
|
||||
static const device_config_t ati28800_wonderxl_config[] =
|
||||
{
|
||||
{
|
||||
"memory", "Memory size", CONFIG_SELECTION, "", 512,
|
||||
{
|
||||
{
|
||||
"256 kB", 256
|
||||
},
|
||||
{
|
||||
"512 kB", 512
|
||||
},
|
||||
{
|
||||
"1 MB", 1024
|
||||
},
|
||||
{
|
||||
""
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"", "", -1
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
const device_t ati28800_device =
|
||||
{
|
||||
"ATI-28800",
|
||||
DEVICE_ISA,
|
||||
0,
|
||||
ati28800_init, ati28800_close, NULL,
|
||||
ati28800_available,
|
||||
ati28800_speed_changed,
|
||||
ati28800_force_redraw,
|
||||
ati28800_config
|
||||
};
|
||||
|
||||
const device_t ati28800k_device =
|
||||
{
|
||||
"ATI Korean VGA",
|
||||
DEVICE_ISA,
|
||||
0,
|
||||
ati28800k_init, ati28800_close, NULL,
|
||||
ati28800k_available,
|
||||
ati28800_speed_changed,
|
||||
ati28800_force_redraw,
|
||||
ati28800_config
|
||||
};
|
||||
|
||||
const device_t compaq_ati28800_device =
|
||||
{
|
||||
"Compaq ATI-28800",
|
||||
DEVICE_ISA,
|
||||
GFX_VGAWONDERXL,
|
||||
ati28800_init, ati28800_close, NULL,
|
||||
compaq_ati28800_available,
|
||||
ati28800_speed_changed,
|
||||
ati28800_force_redraw,
|
||||
ati28800_config
|
||||
};
|
||||
|
||||
#if defined(DEV_BRANCH) && defined(USE_XL24)
|
||||
const device_t ati28800_wonderxl24_device =
|
||||
{
|
||||
"ATI-28800 (VGA Wonder XL24)",
|
||||
DEVICE_ISA,
|
||||
GFX_VGAWONDERXL24,
|
||||
ati28800_init, ati28800_close, NULL,
|
||||
ati28800_wonderxl24_available,
|
||||
ati28800_speed_changed,
|
||||
ati28800_force_redraw,
|
||||
ati28800_wonderxl_config
|
||||
};
|
||||
#endif
|
||||
9
backup code/video - Cópia/vid_ati28800.h
Normal file
9
backup code/video - Cópia/vid_ati28800.h
Normal file
@@ -0,0 +1,9 @@
|
||||
/* Copyright holders: Sarah Walker, Tenshi
|
||||
see COPYING for more details
|
||||
*/
|
||||
extern const device_t ati28800_device;
|
||||
extern const device_t ati28800k_device;
|
||||
extern const device_t compaq_ati28800_device;
|
||||
#if defined(DEV_BRANCH) && defined(USE_XL24)
|
||||
extern const device_t ati28800_wonderxl24_device;
|
||||
#endif
|
||||
197
backup code/video - Cópia/vid_ati68860_ramdac.c
Normal file
197
backup code/video - Cópia/vid_ati68860_ramdac.c
Normal file
@@ -0,0 +1,197 @@
|
||||
/*
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
*
|
||||
* This file is part of the 86Box distribution.
|
||||
*
|
||||
* ATI 68860 RAMDAC emulation (for Mach64)
|
||||
*
|
||||
* ATI 68860/68880 Truecolor DACs:
|
||||
* REG08 (R/W):
|
||||
* bit 0-? Always 2 ??
|
||||
*
|
||||
* REG0A (R/W):
|
||||
* bit 0-? Always 1Dh ??
|
||||
*
|
||||
* REG0B (R/W): (GMR ?)
|
||||
* bit 0-7 Mode. 82h: 4bpp, 83h: 8bpp,
|
||||
* A0h: 15bpp, A1h: 16bpp, C0h: 24bpp,
|
||||
* E3h: 32bpp (80h for VGA modes ?)
|
||||
*
|
||||
* REG0C (R/W): Device Setup Register A
|
||||
* bit 0 Controls 6/8bit DAC. 0: 8bit DAC/LUT, 1: 6bit DAC/LUT
|
||||
* 2-3 Depends on Video memory (= VRAM width ?) .
|
||||
* 1: Less than 1Mb, 2: 1Mb, 3: > 1Mb
|
||||
* 5-6 Always set ?
|
||||
* 7 If set can remove "snow" in some cases
|
||||
* (A860_Delay_L ?) ??
|
||||
*
|
||||
* Version: @(#)vid_ati68860.c 1.0.3 2017/11/04
|
||||
*
|
||||
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
*
|
||||
* Copyright 2008-2017 Sarah Walker.
|
||||
* Copyright 2016,2017 Miran Grca.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <wchar.h>
|
||||
#include "../86box.h"
|
||||
#include "../mem.h"
|
||||
#include "video.h"
|
||||
#include "vid_svga.h"
|
||||
#include "vid_ati68860_ramdac.h"
|
||||
#include "vid_svga_render.h"
|
||||
|
||||
|
||||
void ati68860_ramdac_out(uint16_t addr, uint8_t val, ati68860_ramdac_t *ramdac, svga_t *svga)
|
||||
{
|
||||
switch (addr)
|
||||
{
|
||||
case 0:
|
||||
svga_out(0x3c8, val, svga);
|
||||
break;
|
||||
case 1:
|
||||
svga_out(0x3c9, val, svga);
|
||||
break;
|
||||
case 2:
|
||||
svga_out(0x3c6, val, svga);
|
||||
break;
|
||||
case 3:
|
||||
svga_out(0x3c7, val, svga);
|
||||
break;
|
||||
default:
|
||||
ramdac->regs[addr & 0xf] = val;
|
||||
switch (addr & 0xf)
|
||||
{
|
||||
case 0x4:
|
||||
ramdac->dac_write = val;
|
||||
ramdac->dac_pos = 0;
|
||||
break;
|
||||
case 0x5:
|
||||
switch (ramdac->dac_pos)
|
||||
{
|
||||
case 0:
|
||||
ramdac->dac_r = val;
|
||||
ramdac->dac_pos++;
|
||||
break;
|
||||
case 1:
|
||||
ramdac->dac_g = val;
|
||||
ramdac->dac_pos++;
|
||||
break;
|
||||
case 2:
|
||||
if (ramdac->dac_write > 1)
|
||||
break;
|
||||
ramdac->pal[ramdac->dac_write].r = ramdac->dac_r;
|
||||
ramdac->pal[ramdac->dac_write].g = ramdac->dac_g;
|
||||
ramdac->pal[ramdac->dac_write].b = val;
|
||||
if (ramdac->ramdac_type == RAMDAC_8BIT)
|
||||
ramdac->pallook[ramdac->dac_write] = makecol32(ramdac->pal[ramdac->dac_write].r, ramdac->pal[ramdac->dac_write].g, ramdac->pal[ramdac->dac_write].b);
|
||||
else
|
||||
ramdac->pallook[ramdac->dac_write] = makecol32((ramdac->pal[ramdac->dac_write].r & 0x3f) * 4, (ramdac->pal[ramdac->dac_write].g & 0x3f) * 4, (ramdac->pal[ramdac->dac_write].b & 0x3f) * 4);
|
||||
ramdac->dac_pos = 0;
|
||||
ramdac->dac_write = (ramdac->dac_write + 1) & 255;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xb:
|
||||
switch (val)
|
||||
{
|
||||
case 0x82:
|
||||
ramdac->render = svga_render_4bpp_highres;
|
||||
break;
|
||||
case 0x83:
|
||||
ramdac->render = svga_render_8bpp_highres;
|
||||
break;
|
||||
case 0xa0: case 0xb0:
|
||||
ramdac->render = svga_render_15bpp_highres;
|
||||
break;
|
||||
case 0xa1: case 0xb1:
|
||||
ramdac->render = svga_render_16bpp_highres;
|
||||
break;
|
||||
case 0xc0: case 0xd0:
|
||||
ramdac->render = svga_render_24bpp_highres;
|
||||
break;
|
||||
case 0xe2: case 0xf7:
|
||||
ramdac->render = svga_render_32bpp_highres;
|
||||
break;
|
||||
case 0xe3:
|
||||
ramdac->render = svga_render_ABGR8888_highres;
|
||||
break;
|
||||
case 0xf2:
|
||||
ramdac->render = svga_render_RGBA8888_highres;
|
||||
break;
|
||||
default:
|
||||
ramdac->render = svga_render_8bpp_highres;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 0xc:
|
||||
svga_set_ramdac_type(svga, (val & 1) ? RAMDAC_6BIT : RAMDAC_8BIT);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t ati68860_ramdac_in(uint16_t addr, ati68860_ramdac_t *ramdac, svga_t *svga)
|
||||
{
|
||||
uint8_t ret = 0;
|
||||
switch (addr)
|
||||
{
|
||||
case 0:
|
||||
ret = svga_in(0x3c8, svga);
|
||||
break;
|
||||
case 1:
|
||||
ret = svga_in(0x3c9, svga);
|
||||
break;
|
||||
case 2:
|
||||
ret = svga_in(0x3c6, svga);
|
||||
break;
|
||||
case 3:
|
||||
ret = svga_in(0x3c7, svga);
|
||||
break;
|
||||
case 4: case 8:
|
||||
ret = 2;
|
||||
break;
|
||||
case 6: case 0xa:
|
||||
ret = 0x1d;
|
||||
break;
|
||||
case 0xf:
|
||||
ret = 0xd0;
|
||||
break;
|
||||
|
||||
default:
|
||||
ret = ramdac->regs[addr & 0xf];
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void ati68860_ramdac_init(ati68860_ramdac_t *ramdac)
|
||||
{
|
||||
ramdac->render = svga_render_8bpp_highres;
|
||||
}
|
||||
|
||||
void ati68860_set_ramdac_type(ati68860_ramdac_t *ramdac, int type)
|
||||
{
|
||||
int c;
|
||||
|
||||
if (ramdac->ramdac_type != type)
|
||||
{
|
||||
ramdac->ramdac_type = type;
|
||||
|
||||
for (c = 0; c < 2; c++)
|
||||
{
|
||||
if (ramdac->ramdac_type == RAMDAC_8BIT)
|
||||
ramdac->pallook[c] = makecol32(ramdac->pal[c].r, ramdac->pal[c].g, ramdac->pal[c].b);
|
||||
else
|
||||
ramdac->pallook[c] = makecol32((ramdac->pal[c].r & 0x3f) * 4, (ramdac->pal[c].g & 0x3f) * 4, (ramdac->pal[c].b & 0x3f) * 4);
|
||||
}
|
||||
}
|
||||
}
|
||||
20
backup code/video - Cópia/vid_ati68860_ramdac.h
Normal file
20
backup code/video - Cópia/vid_ati68860_ramdac.h
Normal file
@@ -0,0 +1,20 @@
|
||||
/* Copyright holders: Sarah Walker
|
||||
see COPYING for more details
|
||||
*/
|
||||
typedef struct ati68860_ramdac_t
|
||||
{
|
||||
uint8_t regs[16];
|
||||
void (*render)(struct svga_t *svga);
|
||||
|
||||
int dac_write, dac_pos;
|
||||
int dac_r, dac_g;
|
||||
PALETTE pal;
|
||||
uint32_t pallook[2];
|
||||
|
||||
int ramdac_type;
|
||||
} ati68860_ramdac_t;
|
||||
|
||||
void ati68860_ramdac_out(uint16_t addr, uint8_t val, ati68860_ramdac_t *ramdac, svga_t *svga);
|
||||
uint8_t ati68860_ramdac_in(uint16_t addr, ati68860_ramdac_t *ramdac, svga_t *svga);
|
||||
void ati68860_ramdac_init(ati68860_ramdac_t *ramdac);
|
||||
void ati68860_set_ramdac_type(ati68860_ramdac_t *ramdac, int type);
|
||||
235
backup code/video - Cópia/vid_ati_eeprom.c
Normal file
235
backup code/video - Cópia/vid_ati_eeprom.c
Normal file
@@ -0,0 +1,235 @@
|
||||
/*
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
*
|
||||
* This file is part of the 86Box distribution.
|
||||
*
|
||||
* Emulation of the EEPROM on select ATI cards.
|
||||
*
|
||||
* Version: @(#)vid_ati_eeprom.c 1.0.2 2018/04/11
|
||||
*
|
||||
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
*
|
||||
* Copyright 2008-2018 Sarah Walker.
|
||||
* Copyright 2016-2018 Miran Grca.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <wchar.h>
|
||||
#include "../86box.h"
|
||||
#include "../device.h"
|
||||
#include "../mem.h"
|
||||
#include "../nvr.h"
|
||||
#include "vid_ati_eeprom.h"
|
||||
|
||||
|
||||
enum
|
||||
{
|
||||
EEPROM_IDLE,
|
||||
EEPROM_WAIT,
|
||||
EEPROM_OPCODE,
|
||||
EEPROM_INPUT,
|
||||
EEPROM_OUTPUT
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
EEPROM_OP_EW = 4,
|
||||
EEPROM_OP_WRITE = 5,
|
||||
EEPROM_OP_READ = 6,
|
||||
EEPROM_OP_ERASE = 7,
|
||||
|
||||
EEPROM_OP_WRALMAIN = -1
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
EEPROM_OP_EWDS = 0,
|
||||
EEPROM_OP_WRAL = 1,
|
||||
EEPROM_OP_ERAL = 2,
|
||||
EEPROM_OP_EWEN = 3
|
||||
};
|
||||
|
||||
void ati_eeprom_load(ati_eeprom_t *eeprom, wchar_t *fn, int type)
|
||||
{
|
||||
FILE *f;
|
||||
eeprom->type = type;
|
||||
wcscpy(eeprom->fn, fn);
|
||||
f = nvr_fopen(eeprom->fn, L"rb");
|
||||
if (!f)
|
||||
{
|
||||
memset(eeprom->data, 0, eeprom->type ? 512 : 128);
|
||||
return;
|
||||
}
|
||||
fread(eeprom->data, 1, eeprom->type ? 512 : 128, f);
|
||||
fclose(f);
|
||||
}
|
||||
|
||||
void ati_eeprom_save(ati_eeprom_t *eeprom)
|
||||
{
|
||||
FILE *f = nvr_fopen(eeprom->fn, L"wb");
|
||||
if (!f) return;
|
||||
fwrite(eeprom->data, 1, eeprom->type ? 512 : 128, f);
|
||||
fclose(f);
|
||||
}
|
||||
|
||||
void ati_eeprom_write(ati_eeprom_t *eeprom, int ena, int clk, int dat)
|
||||
{
|
||||
int c;
|
||||
if (!ena)
|
||||
{
|
||||
eeprom->out = 1;
|
||||
}
|
||||
if (clk && !eeprom->oldclk)
|
||||
{
|
||||
if (ena && !eeprom->oldena)
|
||||
{
|
||||
eeprom->state = EEPROM_WAIT;
|
||||
eeprom->opcode = 0;
|
||||
eeprom->count = 3;
|
||||
eeprom->out = 1;
|
||||
}
|
||||
else if (ena)
|
||||
{
|
||||
switch (eeprom->state)
|
||||
{
|
||||
case EEPROM_WAIT:
|
||||
if (!dat)
|
||||
break;
|
||||
eeprom->state = EEPROM_OPCODE;
|
||||
/* fall through */
|
||||
case EEPROM_OPCODE:
|
||||
eeprom->opcode = (eeprom->opcode << 1) | (dat ? 1 : 0);
|
||||
eeprom->count--;
|
||||
if (!eeprom->count)
|
||||
{
|
||||
switch (eeprom->opcode)
|
||||
{
|
||||
case EEPROM_OP_WRITE:
|
||||
eeprom->count = eeprom->type ? 24 : 22;
|
||||
eeprom->state = EEPROM_INPUT;
|
||||
eeprom->dat = 0;
|
||||
break;
|
||||
case EEPROM_OP_READ:
|
||||
eeprom->count = eeprom->type ? 8 : 6;
|
||||
eeprom->state = EEPROM_INPUT;
|
||||
eeprom->dat = 0;
|
||||
break;
|
||||
case EEPROM_OP_EW:
|
||||
eeprom->count = 2;
|
||||
eeprom->state = EEPROM_INPUT;
|
||||
eeprom->dat = 0;
|
||||
break;
|
||||
case EEPROM_OP_ERASE:
|
||||
eeprom->count = eeprom->type ? 8 : 6;
|
||||
eeprom->state = EEPROM_INPUT;
|
||||
eeprom->dat = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case EEPROM_INPUT:
|
||||
eeprom->dat = (eeprom->dat << 1) | (dat ? 1 : 0);
|
||||
eeprom->count--;
|
||||
if (!eeprom->count)
|
||||
{
|
||||
switch (eeprom->opcode)
|
||||
{
|
||||
case EEPROM_OP_WRITE:
|
||||
if (!eeprom->wp)
|
||||
{
|
||||
eeprom->data[(eeprom->dat >> 16) & (eeprom->type ? 255 : 63)] = eeprom->dat & 0xffff;
|
||||
ati_eeprom_save(eeprom);
|
||||
}
|
||||
eeprom->state = EEPROM_IDLE;
|
||||
eeprom->out = 1;
|
||||
break;
|
||||
|
||||
case EEPROM_OP_READ:
|
||||
eeprom->count = 17;
|
||||
eeprom->state = EEPROM_OUTPUT;
|
||||
eeprom->dat = eeprom->data[eeprom->dat];
|
||||
break;
|
||||
case EEPROM_OP_EW:
|
||||
switch (eeprom->dat)
|
||||
{
|
||||
case EEPROM_OP_EWDS:
|
||||
eeprom->wp = 1;
|
||||
break;
|
||||
case EEPROM_OP_WRAL:
|
||||
eeprom->opcode = EEPROM_OP_WRALMAIN;
|
||||
eeprom->count = 20;
|
||||
break;
|
||||
case EEPROM_OP_ERAL:
|
||||
if (!eeprom->wp)
|
||||
{
|
||||
memset(eeprom->data, 0xff, 128);
|
||||
ati_eeprom_save(eeprom);
|
||||
}
|
||||
break;
|
||||
case EEPROM_OP_EWEN:
|
||||
eeprom->wp = 0;
|
||||
break;
|
||||
}
|
||||
eeprom->state = EEPROM_IDLE;
|
||||
eeprom->out = 1;
|
||||
break;
|
||||
|
||||
case EEPROM_OP_ERASE:
|
||||
if (!eeprom->wp)
|
||||
{
|
||||
eeprom->data[eeprom->dat] = 0xffff;
|
||||
ati_eeprom_save(eeprom);
|
||||
}
|
||||
eeprom->state = EEPROM_IDLE;
|
||||
eeprom->out = 1;
|
||||
break;
|
||||
|
||||
case EEPROM_OP_WRALMAIN:
|
||||
if (!eeprom->wp)
|
||||
{
|
||||
for (c = 0; c < 256; c++)
|
||||
eeprom->data[c] = eeprom->dat;
|
||||
ati_eeprom_save(eeprom);
|
||||
}
|
||||
eeprom->state = EEPROM_IDLE;
|
||||
eeprom->out = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
eeprom->oldena = ena;
|
||||
}
|
||||
else if (!clk && eeprom->oldclk)
|
||||
{
|
||||
if (ena)
|
||||
{
|
||||
switch (eeprom->state)
|
||||
{
|
||||
case EEPROM_OUTPUT:
|
||||
eeprom->out = (eeprom->dat & 0x10000) ? 1 : 0;
|
||||
eeprom->dat <<= 1;
|
||||
eeprom->count--;
|
||||
if (!eeprom->count)
|
||||
{
|
||||
eeprom->state = EEPROM_IDLE;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
eeprom->oldclk = clk;
|
||||
}
|
||||
|
||||
int ati_eeprom_read(ati_eeprom_t *eeprom)
|
||||
{
|
||||
return eeprom->out;
|
||||
}
|
||||
|
||||
19
backup code/video - Cópia/vid_ati_eeprom.h
Normal file
19
backup code/video - Cópia/vid_ati_eeprom.h
Normal file
@@ -0,0 +1,19 @@
|
||||
/* Copyright holders: Sarah Walker
|
||||
see COPYING for more details
|
||||
*/
|
||||
typedef struct ati_eeprom_t
|
||||
{
|
||||
uint16_t data[256];
|
||||
|
||||
int oldclk, oldena;
|
||||
int opcode, state, count, out;
|
||||
int wp;
|
||||
uint32_t dat;
|
||||
int type;
|
||||
|
||||
wchar_t fn[256];
|
||||
} ati_eeprom_t;
|
||||
|
||||
void ati_eeprom_load(ati_eeprom_t *eeprom, wchar_t *fn, int type);
|
||||
void ati_eeprom_write(ati_eeprom_t *eeprom, int ena, int clk, int dat);
|
||||
int ati_eeprom_read(ati_eeprom_t *eeprom);
|
||||
3513
backup code/video - Cópia/vid_ati_mach64.c
Normal file
3513
backup code/video - Cópia/vid_ati_mach64.c
Normal file
File diff suppressed because it is too large
Load Diff
22
backup code/video - Cópia/vid_ati_mach64.h
Normal file
22
backup code/video - Cópia/vid_ati_mach64.h
Normal file
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
*
|
||||
* This file is part of the 86Box distribution.
|
||||
*
|
||||
* ATi Mach64 graphics card emulation.
|
||||
*
|
||||
* Version: @(#)vid_ati_mach64.h 1.0.2 2018/03/18
|
||||
*
|
||||
* Author: Sarah Walker, <http://pcem-emulator.co.uk/>
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
* Copyright 2008-2018 Sarah Walker.
|
||||
* Copyright 2016-2018 Miran Grca.
|
||||
*/
|
||||
|
||||
extern const device_t mach64gx_isa_device;
|
||||
extern const device_t mach64gx_vlb_device;
|
||||
extern const device_t mach64gx_pci_device;
|
||||
extern const device_t mach64vt2_device;
|
||||
192
backup code/video - Cópia/vid_bt485_ramdac.c
Normal file
192
backup code/video - Cópia/vid_bt485_ramdac.c
Normal file
@@ -0,0 +1,192 @@
|
||||
/*
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
*
|
||||
* This file is part of the 86Box distribution.
|
||||
*
|
||||
* Brooktree BT485 true colour RAMDAC emulation.
|
||||
*
|
||||
* Currently only a dummy stub for logging and passing output
|
||||
* to the generic SVGA handler.
|
||||
*
|
||||
* Version: @(#)vid_bt485_ramdac.c 1.0.2 2017/11/04
|
||||
*
|
||||
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
*
|
||||
* Copyright 2008-2017 Sarah Walker.
|
||||
* Copyright 2016,2017 Miran Grca.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <wchar.h>
|
||||
#include "../86box.h"
|
||||
#include "../mem.h"
|
||||
#include "video.h"
|
||||
#include "vid_svga.h"
|
||||
#include "vid_bt485_ramdac.h"
|
||||
|
||||
|
||||
int bt485_get_clock_divider(bt485_ramdac_t *ramdac)
|
||||
{
|
||||
return 1; /* Will be implemented later. */
|
||||
}
|
||||
|
||||
void bt485_set_rs2(uint8_t rs2, bt485_ramdac_t *ramdac)
|
||||
{
|
||||
ramdac->rs2 = rs2 ? 1 : 0;
|
||||
}
|
||||
|
||||
void bt485_set_rs3(uint8_t rs3, bt485_ramdac_t *ramdac)
|
||||
{
|
||||
ramdac->rs3 = rs3 ? 1 : 0;
|
||||
}
|
||||
|
||||
void bt485_ramdac_out(uint16_t addr, uint8_t val, bt485_ramdac_t *ramdac, svga_t *svga)
|
||||
{
|
||||
// /*if (CS!=0xC000) */pclog("OUT RAMDAC %04X %02X %i %04X:%04X %i\n",addr,val,sdac_ramdac.magic_count,CS,pc, sdac_ramdac.rs2);
|
||||
uint8_t reg = addr & 3;
|
||||
reg |= (ramdac->rs2 ? 4 : 0);
|
||||
reg |= (ramdac->rs3 ? 8 : 0);
|
||||
pclog("BT485 RAMDAC: Writing %02X to register %02X\n", val, reg);
|
||||
svga_out(addr, val, svga);
|
||||
return;
|
||||
|
||||
switch (addr)
|
||||
{
|
||||
case 0x3C6:
|
||||
if (val == 0xff)
|
||||
{
|
||||
ramdac->rs2 = 0;
|
||||
ramdac->magic_count = 0;
|
||||
break;
|
||||
}
|
||||
if (ramdac->magic_count < 4) break;
|
||||
if (ramdac->magic_count == 4)
|
||||
{
|
||||
ramdac->command = val;
|
||||
// pclog("RAMDAC command reg now %02X\n", val);
|
||||
switch (val >> 4)
|
||||
{
|
||||
case 0x2: case 0x3: case 0xa: svga->bpp = 15; break;
|
||||
case 0x4: case 0xe: svga->bpp = 24; break;
|
||||
case 0x5: case 0x6: case 0xc: svga->bpp = 16; break;
|
||||
case 0x7: svga->bpp = 32; break;
|
||||
|
||||
case 0: case 1: default: svga->bpp = 8; break;
|
||||
}
|
||||
svga_recalctimings(svga);
|
||||
}
|
||||
//ramdac->magic_count = 0;
|
||||
break;
|
||||
|
||||
case 0x3C7:
|
||||
ramdac->magic_count = 0;
|
||||
if (ramdac->rs2)
|
||||
ramdac->rindex = val;
|
||||
break;
|
||||
case 0x3C8:
|
||||
ramdac->magic_count = 0;
|
||||
if (ramdac->rs2)
|
||||
ramdac->windex = val;
|
||||
break;
|
||||
case 0x3C9:
|
||||
ramdac->magic_count = 0;
|
||||
if (ramdac->rs2)
|
||||
{
|
||||
if (!ramdac->reg_ff) ramdac->regs[ramdac->windex] = (ramdac->regs[ramdac->windex] & 0xff00) | val;
|
||||
else ramdac->regs[ramdac->windex] = (ramdac->regs[ramdac->windex] & 0x00ff) | (val << 8);
|
||||
ramdac->reg_ff = !ramdac->reg_ff;
|
||||
// pclog("RAMDAC reg %02X now %04X\n", ramdac->windex, ramdac->regs[ramdac->windex]);
|
||||
if (!ramdac->reg_ff) ramdac->windex++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
svga_out(addr, val, svga);
|
||||
}
|
||||
|
||||
uint8_t bt485_ramdac_in(uint16_t addr, bt485_ramdac_t *ramdac, svga_t *svga)
|
||||
{
|
||||
uint8_t temp;
|
||||
// /*if (CS!=0xC000) */pclog("IN RAMDAC %04X %04X:%04X %i\n",addr,CS,pc, ramdac->rs2);
|
||||
uint8_t reg = addr & 3;
|
||||
reg |= (ramdac->rs2 ? 4 : 0);
|
||||
reg |= (ramdac->rs3 ? 8 : 0);
|
||||
pclog("BT485 RAMDAC: Reading register %02X\n", reg);
|
||||
return svga_in(addr, svga);
|
||||
|
||||
switch (addr)
|
||||
{
|
||||
case 0x3C6:
|
||||
ramdac->reg_ff = 0;
|
||||
if (ramdac->magic_count < 5)
|
||||
ramdac->magic_count++;
|
||||
if (ramdac->magic_count == 4)
|
||||
{
|
||||
temp = 0x70; /*SDAC ID*/
|
||||
ramdac->rs2 = 1;
|
||||
}
|
||||
if (ramdac->magic_count == 5)
|
||||
{
|
||||
temp = ramdac->command;
|
||||
ramdac->magic_count = 0;
|
||||
}
|
||||
return temp;
|
||||
case 0x3C7:
|
||||
// if (ramdac->magic_count < 4)
|
||||
// {
|
||||
ramdac->magic_count=0;
|
||||
// break;
|
||||
// }
|
||||
if (ramdac->rs2) return ramdac->rindex;
|
||||
break;
|
||||
case 0x3C8:
|
||||
// if (ramdac->magic_count < 4)
|
||||
// {
|
||||
ramdac->magic_count=0;
|
||||
// break;
|
||||
// }
|
||||
if (ramdac->rs2) return ramdac->windex;
|
||||
break;
|
||||
case 0x3C9:
|
||||
// if (ramdac->magic_count < 4)
|
||||
// {
|
||||
ramdac->magic_count=0;
|
||||
// break;
|
||||
// }
|
||||
if (ramdac->rs2)
|
||||
{
|
||||
if (!ramdac->reg_ff) temp = ramdac->regs[ramdac->rindex] & 0xff;
|
||||
else temp = ramdac->regs[ramdac->rindex] >> 8;
|
||||
ramdac->reg_ff = !ramdac->reg_ff;
|
||||
if (!ramdac->reg_ff)
|
||||
{
|
||||
ramdac->rindex++;
|
||||
ramdac->magic_count = 0;
|
||||
}
|
||||
return temp;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return svga_in(addr, svga);
|
||||
}
|
||||
|
||||
float bt485_getclock(int clock, void *p)
|
||||
{
|
||||
bt485_ramdac_t *ramdac = (bt485_ramdac_t *)p;
|
||||
float t;
|
||||
int m, n1, n2;
|
||||
// pclog("SDAC_Getclock %i %04X\n", clock, ramdac->regs[clock]);
|
||||
if (clock == 0) return 25175000.0;
|
||||
if (clock == 1) return 28322000.0;
|
||||
clock ^= 1; /*Clocks 2 and 3 seem to be reversed*/
|
||||
m = (ramdac->regs[clock] & 0x7f) + 2;
|
||||
n1 = ((ramdac->regs[clock] >> 8) & 0x1f) + 2;
|
||||
n2 = ((ramdac->regs[clock] >> 13) & 0x07);
|
||||
t = (14318184.0 * ((float)m / (float)n1)) / (float)(1 << n2);
|
||||
// pclog("BT485 clock %i %i %i %f %04X %f %i\n", m, n1, n2, t, ramdac->regs[2], 14318184.0 * ((float)m / (float)n1), 1 << n2);
|
||||
return t;
|
||||
}
|
||||
18
backup code/video - Cópia/vid_bt485_ramdac.h
Normal file
18
backup code/video - Cópia/vid_bt485_ramdac.h
Normal file
@@ -0,0 +1,18 @@
|
||||
/* Copyright holders: Tenshi
|
||||
see COPYING for more details
|
||||
*/
|
||||
typedef struct bt485_ramdac_t
|
||||
{
|
||||
int magic_count;
|
||||
uint8_t command;
|
||||
int windex, rindex;
|
||||
uint16_t regs[256];
|
||||
int reg_ff;
|
||||
int rs2;
|
||||
int rs3;
|
||||
} bt485_ramdac_t;
|
||||
|
||||
void bt485_ramdac_out(uint16_t addr, uint8_t val, bt485_ramdac_t *ramdac, svga_t *svga);
|
||||
uint8_t bt485_ramdac_in(uint16_t addr, bt485_ramdac_t *ramdac, svga_t *svga);
|
||||
|
||||
float bt485_getclock(int clock, void *p);
|
||||
598
backup code/video - Cópia/vid_cga.c
Normal file
598
backup code/video - Cópia/vid_cga.c
Normal file
@@ -0,0 +1,598 @@
|
||||
/*
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
*
|
||||
* This file is part of the 86Box distribution.
|
||||
*
|
||||
* Emulation of the old and new IBM CGA graphics cards.
|
||||
*
|
||||
* Version: @(#)vid_cga.c 1.0.16 2018/04/29
|
||||
*
|
||||
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
*
|
||||
* Copyright 2008-2018 Sarah Walker.
|
||||
* Copyright 2016-2018 Miran Grca.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <wchar.h>
|
||||
#include <math.h>
|
||||
#include "../86box.h"
|
||||
#include "../cpu/cpu.h"
|
||||
#include "../io.h"
|
||||
#include "../pit.h"
|
||||
#include "../mem.h"
|
||||
#include "../rom.h"
|
||||
#include "../timer.h"
|
||||
#include "../device.h"
|
||||
#include "video.h"
|
||||
#include "vid_cga.h"
|
||||
#include "vid_cga_comp.h"
|
||||
|
||||
|
||||
#define CGA_RGB 0
|
||||
#define CGA_COMPOSITE 1
|
||||
|
||||
#define COMPOSITE_OLD 0
|
||||
#define COMPOSITE_NEW 1
|
||||
|
||||
static uint8_t crtcmask[32] =
|
||||
{
|
||||
0xff, 0xff, 0xff, 0xff, 0x7f, 0x1f, 0x7f, 0x7f, 0xf3, 0x1f, 0x7f, 0x1f, 0x3f, 0xff, 0x3f, 0xff,
|
||||
0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
};
|
||||
|
||||
void cga_recalctimings(cga_t *cga);
|
||||
|
||||
void cga_out(uint16_t addr, uint8_t val, void *p)
|
||||
{
|
||||
cga_t *cga = (cga_t *)p;
|
||||
uint8_t old;
|
||||
switch (addr)
|
||||
{
|
||||
case 0x3D4:
|
||||
cga->crtcreg = val & 31;
|
||||
return;
|
||||
case 0x3D5:
|
||||
old = cga->crtc[cga->crtcreg];
|
||||
cga->crtc[cga->crtcreg] = val & crtcmask[cga->crtcreg];
|
||||
if (old != val)
|
||||
{
|
||||
if (cga->crtcreg < 0xe || cga->crtcreg > 0x10)
|
||||
{
|
||||
fullchange = changeframecount;
|
||||
cga_recalctimings(cga);
|
||||
}
|
||||
}
|
||||
return;
|
||||
case 0x3D8:
|
||||
if (((cga->cgamode ^ val) & 5) != 0)
|
||||
{
|
||||
cga->cgamode = val;
|
||||
update_cga16_color(cga->cgamode);
|
||||
}
|
||||
|
||||
if ((cga->cgamode ^ val) & 1)
|
||||
{
|
||||
cga_palette = (cga->rgb_type << 1);
|
||||
cgapal_rebuild();
|
||||
}
|
||||
|
||||
cga->cgamode = val;
|
||||
return;
|
||||
case 0x3D9:
|
||||
cga->cgacol = val;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t cga_in(uint16_t addr, void *p)
|
||||
{
|
||||
cga_t *cga = (cga_t *)p;
|
||||
switch (addr)
|
||||
{
|
||||
case 0x3D4:
|
||||
return cga->crtcreg;
|
||||
case 0x3D5:
|
||||
return cga->crtc[cga->crtcreg];
|
||||
case 0x3DA:
|
||||
return cga->cgastat;
|
||||
}
|
||||
return 0xFF;
|
||||
}
|
||||
|
||||
void cga_waitstates(void *p)
|
||||
{
|
||||
cga_t *cga = (cga_t *)p;
|
||||
int cycle = ((int)(((cga->dispontime - cga->vidtime) * 2) / CGACONST));
|
||||
|
||||
cycles -= 8 - (cycle & 7);
|
||||
|
||||
cycle = ((int)(((cga->dispontime - cga->vidtime) * 2) / CGACONST));
|
||||
cycles -= 16 - (cycle & 15);
|
||||
|
||||
cycle = ((int)(((cga->dispontime - cga->vidtime) * 2) / CGACONST));
|
||||
cycles -= 3 - (cycle % 3);
|
||||
}
|
||||
|
||||
void cga_write(uint32_t addr, uint8_t val, void *p)
|
||||
{
|
||||
cga_t *cga = (cga_t *)p;
|
||||
|
||||
cga->vram[addr & 0x3fff] = val;
|
||||
if (cga->snow_enabled)
|
||||
{
|
||||
cga->charbuffer[ ((int)(((cga->dispontime - cga->vidtime) * 2) / CGACONST)) & 0xfc] = val;
|
||||
cga->charbuffer[(((int)(((cga->dispontime - cga->vidtime) * 2) / CGACONST)) & 0xfc) | 1] = val;
|
||||
}
|
||||
egawrites++;
|
||||
cga_waitstates(cga);
|
||||
}
|
||||
|
||||
uint8_t cga_read(uint32_t addr, void *p)
|
||||
{
|
||||
cga_t *cga = (cga_t *)p;
|
||||
cga_waitstates(cga);
|
||||
if (cga->snow_enabled)
|
||||
{
|
||||
cga->charbuffer[ ((int)(((cga->dispontime - cga->vidtime) * 2) / CGACONST)) & 0xfc] = cga->vram[addr & 0x3fff];
|
||||
cga->charbuffer[(((int)(((cga->dispontime - cga->vidtime) * 2) / CGACONST)) & 0xfc) | 1] = cga->vram[addr & 0x3fff];
|
||||
}
|
||||
egareads++;
|
||||
return cga->vram[addr & 0x3fff];
|
||||
}
|
||||
|
||||
void cga_recalctimings(cga_t *cga)
|
||||
{
|
||||
double disptime;
|
||||
double _dispontime, _dispofftime;
|
||||
if (cga->cgamode & 1)
|
||||
{
|
||||
disptime = (double) (cga->crtc[0] + 1);
|
||||
_dispontime = (double) cga->crtc[1];
|
||||
}
|
||||
else
|
||||
{
|
||||
disptime = (double) ((cga->crtc[0] + 1) << 1);
|
||||
_dispontime = (double) (cga->crtc[1] << 1);
|
||||
}
|
||||
_dispofftime = disptime - _dispontime;
|
||||
_dispontime = _dispontime * CGACONST;
|
||||
_dispofftime = _dispofftime * CGACONST;
|
||||
cga->dispontime = (int64_t)(_dispontime * (1LL << TIMER_SHIFT));
|
||||
cga->dispofftime = (int64_t)(_dispofftime * (1LL << TIMER_SHIFT));
|
||||
}
|
||||
|
||||
void cga_poll(void *p)
|
||||
{
|
||||
cga_t *cga = (cga_t *)p;
|
||||
uint16_t ca = (cga->crtc[15] | (cga->crtc[14] << 8)) & 0x3fff;
|
||||
int drawcursor;
|
||||
int x, c;
|
||||
int oldvc;
|
||||
uint8_t chr, attr;
|
||||
uint16_t dat;
|
||||
int cols[4];
|
||||
int col;
|
||||
int oldsc;
|
||||
|
||||
if (!cga->linepos)
|
||||
{
|
||||
cga->vidtime += cga->dispofftime;
|
||||
cga->cgastat |= 1;
|
||||
cga->linepos = 1;
|
||||
oldsc = cga->sc;
|
||||
if ((cga->crtc[8] & 3) == 3)
|
||||
cga->sc = ((cga->sc << 1) + cga->oddeven) & 7;
|
||||
if (cga->cgadispon)
|
||||
{
|
||||
if (cga->displine < cga->firstline)
|
||||
{
|
||||
cga->firstline = cga->displine;
|
||||
video_wait_for_buffer();
|
||||
}
|
||||
cga->lastline = cga->displine;
|
||||
for (c = 0; c < 8; c++)
|
||||
{
|
||||
if ((cga->cgamode & 0x12) == 0x12)
|
||||
{
|
||||
buffer->line[cga->displine][c] = 0;
|
||||
if (cga->cgamode & 1) buffer->line[cga->displine][c + (cga->crtc[1] << 3) + 8] = 0;
|
||||
else buffer->line[cga->displine][c + (cga->crtc[1] << 4) + 8] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
buffer->line[cga->displine][c] = (cga->cgacol & 15) + 16;
|
||||
if (cga->cgamode & 1) buffer->line[cga->displine][c + (cga->crtc[1] << 3) + 8] = (cga->cgacol & 15) + 16;
|
||||
else buffer->line[cga->displine][c + (cga->crtc[1] << 4) + 8] = (cga->cgacol & 15) + 16;
|
||||
}
|
||||
}
|
||||
if (cga->cgamode & 1)
|
||||
{
|
||||
for (x = 0; x < cga->crtc[1]; x++)
|
||||
{
|
||||
chr = cga->charbuffer[x << 1];
|
||||
attr = cga->charbuffer[(x << 1) + 1];
|
||||
drawcursor = ((cga->ma == ca) && cga->con && cga->cursoron);
|
||||
if (cga->cgamode & 0x20)
|
||||
{
|
||||
cols[1] = (attr & 15) + 16;
|
||||
cols[0] = ((attr >> 4) & 7) + 16;
|
||||
if ((cga->cgablink & 8) && (attr & 0x80) && !cga->drawcursor)
|
||||
cols[1] = cols[0];
|
||||
}
|
||||
else
|
||||
{
|
||||
cols[1] = (attr & 15) + 16;
|
||||
cols[0] = (attr >> 4) + 16;
|
||||
}
|
||||
if (drawcursor)
|
||||
{
|
||||
for (c = 0; c < 8; c++)
|
||||
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->fontbase][cga->sc & 7] & (1 << (c ^ 7))) ? 1 : 0];
|
||||
}
|
||||
cga->ma++;
|
||||
}
|
||||
}
|
||||
else if (!(cga->cgamode & 2))
|
||||
{
|
||||
for (x = 0; x < cga->crtc[1]; x++)
|
||||
{
|
||||
chr = cga->vram[((cga->ma << 1) & 0x3fff)];
|
||||
attr = cga->vram[(((cga->ma << 1) + 1) & 0x3fff)];
|
||||
drawcursor = ((cga->ma == ca) && cga->con && cga->cursoron);
|
||||
if (cga->cgamode & 0x20)
|
||||
{
|
||||
cols[1] = (attr & 15) + 16;
|
||||
cols[0] = ((attr >> 4) & 7) + 16;
|
||||
if ((cga->cgablink & 8) && (attr & 0x80)) cols[1] = cols[0];
|
||||
}
|
||||
else
|
||||
{
|
||||
cols[1] = (attr & 15) + 16;
|
||||
cols[0] = (attr >> 4) + 16;
|
||||
}
|
||||
cga->ma++;
|
||||
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->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->fontbase][cga->sc & 7] & (1 << (c ^ 7))) ? 1 : 0];
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (!(cga->cgamode & 16))
|
||||
{
|
||||
cols[0] = (cga->cgacol & 15) | 16;
|
||||
col = (cga->cgacol & 16) ? 24 : 16;
|
||||
if (cga->cgamode & 4)
|
||||
{
|
||||
cols[1] = col | 3;
|
||||
cols[2] = col | 4;
|
||||
cols[3] = col | 7;
|
||||
}
|
||||
else if (cga->cgacol & 32)
|
||||
{
|
||||
cols[1] = col | 3;
|
||||
cols[2] = col | 5;
|
||||
cols[3] = col | 7;
|
||||
}
|
||||
else
|
||||
{
|
||||
cols[1] = col | 2;
|
||||
cols[2] = col | 4;
|
||||
cols[3] = col | 6;
|
||||
}
|
||||
for (x = 0; x < cga->crtc[1]; x++)
|
||||
{
|
||||
dat = (cga->vram[((cga->ma << 1) & 0x1fff) + ((cga->sc & 1) * 0x2000)] << 8) | cga->vram[((cga->ma << 1) & 0x1fff) + ((cga->sc & 1) * 0x2000) + 1];
|
||||
cga->ma++;
|
||||
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[dat >> 14];
|
||||
dat <<= 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
cols[0] = 0; cols[1] = (cga->cgacol & 15) + 16;
|
||||
for (x = 0; x < cga->crtc[1]; x++)
|
||||
{
|
||||
dat = (cga->vram[((cga->ma << 1) & 0x1fff) + ((cga->sc & 1) * 0x2000)] << 8) | cga->vram[((cga->ma << 1) & 0x1fff) + ((cga->sc & 1) * 0x2000) + 1];
|
||||
cga->ma++;
|
||||
for (c = 0; c < 16; c++)
|
||||
{
|
||||
buffer->line[cga->displine][(x << 4) + c + 8] = cols[dat >> 15];
|
||||
dat <<= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
cols[0] = ((cga->cgamode & 0x12) == 0x12) ? 0 : (cga->cgacol & 15) + 16;
|
||||
if (cga->cgamode & 1) hline(buffer, 0, cga->displine, (cga->crtc[1] << 3) + 16, cols[0]);
|
||||
else hline(buffer, 0, cga->displine, (cga->crtc[1] << 4) + 16, cols[0]);
|
||||
}
|
||||
|
||||
if (cga->cgamode & 1) x = (cga->crtc[1] << 3) + 16;
|
||||
else x = (cga->crtc[1] << 4) + 16;
|
||||
|
||||
if (cga->composite)
|
||||
{
|
||||
for (c = 0; c < x; c++)
|
||||
buffer32->line[cga->displine][c] = buffer->line[cga->displine][c] & 0xf;
|
||||
|
||||
Composite_Process(cga->cgamode, 0, x >> 2, buffer32->line[cga->displine]);
|
||||
}
|
||||
|
||||
cga->sc = oldsc;
|
||||
if (cga->vc == cga->crtc[7] && !cga->sc)
|
||||
cga->cgastat |= 8;
|
||||
cga->displine++;
|
||||
if (cga->displine >= 360)
|
||||
cga->displine = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
cga->vidtime += cga->dispontime;
|
||||
cga->linepos = 0;
|
||||
if (cga->vsynctime)
|
||||
{
|
||||
cga->vsynctime--;
|
||||
if (!cga->vsynctime)
|
||||
cga->cgastat &= ~8;
|
||||
}
|
||||
if (cga->sc == (cga->crtc[11] & 31) || ((cga->crtc[8] & 3) == 3 && cga->sc == ((cga->crtc[11] & 31) >> 1)))
|
||||
{
|
||||
cga->con = 0;
|
||||
cga->coff = 1;
|
||||
}
|
||||
if ((cga->crtc[8] & 3) == 3 && cga->sc == (cga->crtc[9] >> 1))
|
||||
cga->maback = cga->ma;
|
||||
if (cga->vadj)
|
||||
{
|
||||
cga->sc++;
|
||||
cga->sc &= 31;
|
||||
cga->ma = cga->maback;
|
||||
cga->vadj--;
|
||||
if (!cga->vadj)
|
||||
{
|
||||
cga->cgadispon = 1;
|
||||
cga->ma = cga->maback = (cga->crtc[13] | (cga->crtc[12] << 8)) & 0x3fff;
|
||||
cga->sc = 0;
|
||||
}
|
||||
}
|
||||
else if (cga->sc == cga->crtc[9])
|
||||
{
|
||||
cga->maback = cga->ma;
|
||||
cga->sc = 0;
|
||||
oldvc = cga->vc;
|
||||
cga->vc++;
|
||||
cga->vc &= 127;
|
||||
|
||||
if (cga->vc == cga->crtc[6])
|
||||
cga->cgadispon = 0;
|
||||
|
||||
if (oldvc == cga->crtc[4])
|
||||
{
|
||||
cga->vc = 0;
|
||||
cga->vadj = cga->crtc[5];
|
||||
if (!cga->vadj) cga->cgadispon = 1;
|
||||
if (!cga->vadj) cga->ma = cga->maback = (cga->crtc[13] | (cga->crtc[12] << 8)) & 0x3fff;
|
||||
if ((cga->crtc[10] & 0x60) == 0x20) cga->cursoron = 0;
|
||||
else cga->cursoron = cga->cgablink & 8;
|
||||
}
|
||||
|
||||
if (cga->vc == cga->crtc[7])
|
||||
{
|
||||
cga->cgadispon = 0;
|
||||
cga->displine = 0;
|
||||
cga->vsynctime = 16;
|
||||
if (cga->crtc[7])
|
||||
{
|
||||
if (cga->cgamode & 1) x = (cga->crtc[1] << 3) + 16;
|
||||
else x = (cga->crtc[1] << 4) + 16;
|
||||
cga->lastline++;
|
||||
if ((x != xsize) || ((cga->lastline - cga->firstline) != ysize) || video_force_resize_get())
|
||||
{
|
||||
xsize = x;
|
||||
ysize = cga->lastline - cga->firstline;
|
||||
if (xsize < 64) xsize = 656;
|
||||
if (ysize < 32) ysize = 200;
|
||||
set_screen_size(xsize, (ysize << 1) + 16);
|
||||
|
||||
if (video_force_resize_get())
|
||||
video_force_resize_set(0);
|
||||
}
|
||||
|
||||
if (cga->composite)
|
||||
video_blit_memtoscreen(0, cga->firstline - 4, 0, (cga->lastline - cga->firstline) + 8, xsize, (cga->lastline - cga->firstline) + 8);
|
||||
else
|
||||
video_blit_memtoscreen_8(0, cga->firstline - 4, 0, (cga->lastline - cga->firstline) + 8, xsize, (cga->lastline - cga->firstline) + 8);
|
||||
frames++;
|
||||
|
||||
video_res_x = xsize - 16;
|
||||
video_res_y = ysize;
|
||||
if (cga->cgamode & 1)
|
||||
{
|
||||
video_res_x /= 8;
|
||||
video_res_y /= cga->crtc[9] + 1;
|
||||
video_bpp = 0;
|
||||
}
|
||||
else if (!(cga->cgamode & 2))
|
||||
{
|
||||
video_res_x /= 16;
|
||||
video_res_y /= cga->crtc[9] + 1;
|
||||
video_bpp = 0;
|
||||
}
|
||||
else if (!(cga->cgamode & 16))
|
||||
{
|
||||
video_res_x /= 2;
|
||||
video_bpp = 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
video_bpp = 1;
|
||||
}
|
||||
}
|
||||
cga->firstline = 1000;
|
||||
cga->lastline = 0;
|
||||
cga->cgablink++;
|
||||
cga->oddeven ^= 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
cga->sc++;
|
||||
cga->sc &= 31;
|
||||
cga->ma = cga->maback;
|
||||
}
|
||||
if (cga->cgadispon)
|
||||
cga->cgastat &= ~1;
|
||||
if ((cga->sc == (cga->crtc[10] & 31) || ((cga->crtc[8] & 3) == 3 && cga->sc == ((cga->crtc[10] & 31) >> 1))))
|
||||
cga->con = 1;
|
||||
if (cga->cgadispon && (cga->cgamode & 1))
|
||||
{
|
||||
for (x = 0; x < (cga->crtc[1] << 1); x++)
|
||||
cga->charbuffer[x] = cga->vram[(((cga->ma << 1) + x) & 0x3fff)];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void cga_init(cga_t *cga)
|
||||
{
|
||||
cga->composite = 0;
|
||||
}
|
||||
|
||||
void *cga_standalone_init(const device_t *info)
|
||||
{
|
||||
int display_type;
|
||||
cga_t *cga = malloc(sizeof(cga_t));
|
||||
memset(cga, 0, sizeof(cga_t));
|
||||
|
||||
display_type = device_get_config_int("display_type");
|
||||
cga->composite = (display_type != CGA_RGB);
|
||||
cga->revision = device_get_config_int("composite_type");
|
||||
cga->snow_enabled = device_get_config_int("snow_enabled");
|
||||
|
||||
cga->vram = malloc(0x4000);
|
||||
|
||||
cga_comp_init(cga->revision);
|
||||
timer_add(cga_poll, &cga->vidtime, TIMER_ALWAYS_ENABLED, cga);
|
||||
mem_mapping_add(&cga->mapping, 0xb8000, 0x08000, cga_read, NULL, NULL, cga_write, NULL, NULL, NULL, MEM_MAPPING_EXTERNAL, cga);
|
||||
io_sethandler(0x03d0, 0x0010, cga_in, NULL, NULL, cga_out, NULL, NULL, cga);
|
||||
|
||||
overscan_x = overscan_y = 16;
|
||||
|
||||
cga->rgb_type = device_get_config_int("rgb_type");
|
||||
cga_palette = (cga->rgb_type << 1);
|
||||
cgapal_rebuild();
|
||||
|
||||
return cga;
|
||||
}
|
||||
|
||||
void cga_close(void *p)
|
||||
{
|
||||
cga_t *cga = (cga_t *)p;
|
||||
|
||||
free(cga->vram);
|
||||
free(cga);
|
||||
}
|
||||
|
||||
void cga_speed_changed(void *p)
|
||||
{
|
||||
cga_t *cga = (cga_t *)p;
|
||||
|
||||
cga_recalctimings(cga);
|
||||
}
|
||||
|
||||
const device_config_t cga_config[] =
|
||||
{
|
||||
{
|
||||
"display_type", "Display type", CONFIG_SELECTION, "", CGA_RGB,
|
||||
{
|
||||
{
|
||||
"RGB", CGA_RGB
|
||||
},
|
||||
{
|
||||
"Composite", CGA_COMPOSITE
|
||||
},
|
||||
{
|
||||
""
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"composite_type", "Composite type", CONFIG_SELECTION, "", COMPOSITE_OLD,
|
||||
{
|
||||
{
|
||||
"Old", COMPOSITE_OLD
|
||||
},
|
||||
{
|
||||
"New", COMPOSITE_NEW
|
||||
},
|
||||
{
|
||||
""
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"rgb_type", "RGB type", CONFIG_SELECTION, "", 0,
|
||||
{
|
||||
{
|
||||
"Color", 0
|
||||
},
|
||||
{
|
||||
"Green Monochrome", 1
|
||||
},
|
||||
{
|
||||
"Amber Monochrome", 2
|
||||
},
|
||||
{
|
||||
"Gray Monochrome", 3
|
||||
},
|
||||
{
|
||||
"Color (no brown)", 4
|
||||
},
|
||||
{
|
||||
""
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"snow_enabled", "Snow emulation", CONFIG_BINARY, "", 1
|
||||
},
|
||||
{
|
||||
"", "", -1
|
||||
}
|
||||
};
|
||||
|
||||
const device_t cga_device =
|
||||
{
|
||||
"CGA",
|
||||
DEVICE_ISA, 0,
|
||||
cga_standalone_init,
|
||||
cga_close,
|
||||
NULL,
|
||||
NULL,
|
||||
cga_speed_changed,
|
||||
NULL,
|
||||
cga_config
|
||||
};
|
||||
65
backup code/video - Cópia/vid_cga.h
Normal file
65
backup code/video - Cópia/vid_cga.h
Normal file
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
*
|
||||
* This file is part of the 86Box distribution.
|
||||
*
|
||||
* Emulation of the old and new IBM CGA graphics cards.
|
||||
*
|
||||
* Version: @(#)vid_cga.h 1.0.3 2018/03/18
|
||||
*
|
||||
* Author: Sarah Walker, <http://pcem-emulator.co.uk/>
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
* Copyright 2008-2018 Sarah Walker.
|
||||
* Copyright 2016-2018 Miran Grca.
|
||||
*/
|
||||
|
||||
typedef struct cga_t
|
||||
{
|
||||
mem_mapping_t mapping;
|
||||
|
||||
int crtcreg;
|
||||
uint8_t crtc[32];
|
||||
|
||||
uint8_t cgastat;
|
||||
|
||||
uint8_t cgamode, cgacol;
|
||||
|
||||
int fontbase;
|
||||
int linepos, displine;
|
||||
int sc, vc;
|
||||
int cgadispon;
|
||||
int con, coff, cursoron, cgablink;
|
||||
int vsynctime, vadj;
|
||||
uint16_t ma, maback;
|
||||
int oddeven;
|
||||
|
||||
int64_t dispontime, dispofftime;
|
||||
int64_t vidtime;
|
||||
|
||||
int firstline, lastline;
|
||||
|
||||
int drawcursor;
|
||||
|
||||
uint8_t *vram;
|
||||
|
||||
uint8_t charbuffer[256];
|
||||
|
||||
int revision;
|
||||
int composite;
|
||||
int snow_enabled;
|
||||
int rgb_type;
|
||||
} cga_t;
|
||||
|
||||
void cga_init(cga_t *cga);
|
||||
void cga_out(uint16_t addr, uint8_t val, void *p);
|
||||
uint8_t cga_in(uint16_t addr, void *p);
|
||||
void cga_write(uint32_t addr, uint8_t val, void *p);
|
||||
uint8_t cga_read(uint32_t addr, void *p);
|
||||
void cga_recalctimings(cga_t *cga);
|
||||
void cga_poll(void *p);
|
||||
|
||||
extern const device_config_t cga_config[];
|
||||
extern const device_t cga_device;
|
||||
345
backup code/video - Cópia/vid_cga_comp.c
Normal file
345
backup code/video - Cópia/vid_cga_comp.c
Normal file
@@ -0,0 +1,345 @@
|
||||
/*
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
*
|
||||
* This file is part of the 86Box distribution.
|
||||
*
|
||||
* IBM CGA composite filter, borrowed from reenigne's DOSBox
|
||||
* patch and ported to C.
|
||||
*
|
||||
* Version: @(#)vid_cga_comp.c 1.0.3 2017/11/04
|
||||
*
|
||||
* Authors: reenigne,
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
*
|
||||
* Copyright 2015-2017 reenigne.
|
||||
* Copyright 2015-2017 Miran Grca.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <wchar.h>
|
||||
#include <math.h>
|
||||
#include "../86box.h"
|
||||
#include "../device.h"
|
||||
#include "../mem.h"
|
||||
#include "vid_cga.h"
|
||||
#include "vid_cga_comp.h"
|
||||
|
||||
|
||||
int CGA_Composite_Table[1024];
|
||||
|
||||
|
||||
static double brightness = 0;
|
||||
static double contrast = 100;
|
||||
static double saturation = 100;
|
||||
static double sharpness = 0;
|
||||
static double hue_offset = 0;
|
||||
|
||||
/* New algorithm by reenigne
|
||||
Works in all CGA modes/color settings and can simulate older and newer CGA revisions */
|
||||
|
||||
static const double tau = 6.28318531; /* == 2*pi */
|
||||
|
||||
static unsigned char chroma_multiplexer[256] = {
|
||||
2, 2, 2, 2, 114,174, 4, 3, 2, 1,133,135, 2,113,150, 4,
|
||||
133, 2, 1, 99, 151,152, 2, 1, 3, 2, 96,136, 151,152,151,152,
|
||||
2, 56, 62, 4, 111,250,118, 4, 0, 51,207,137, 1,171,209, 5,
|
||||
140, 50, 54,100, 133,202, 57, 4, 2, 50,153,149, 128,198,198,135,
|
||||
32, 1, 36, 81, 147,158, 1, 42, 33, 1,210,254, 34,109,169, 77,
|
||||
177, 2, 0,165, 189,154, 3, 44, 33, 0, 91,197, 178,142,144,192,
|
||||
4, 2, 61, 67, 117,151,112, 83, 4, 0,249,255, 3,107,249,117,
|
||||
147, 1, 50,162, 143,141, 52, 54, 3, 0,145,206, 124,123,192,193,
|
||||
72, 78, 2, 0, 159,208, 4, 0, 53, 58,164,159, 37,159,171, 1,
|
||||
248,117, 4, 98, 212,218, 5, 2, 54, 59, 93,121, 176,181,134,130,
|
||||
1, 61, 31, 0, 160,255, 34, 1, 1, 58,197,166, 0,177,194, 2,
|
||||
162,111, 34, 96, 205,253, 32, 1, 1, 57,123,125, 119,188,150,112,
|
||||
78, 4, 0, 75, 166,180, 20, 38, 78, 1,143,246, 42,113,156, 37,
|
||||
252, 4, 1,188, 175,129, 1, 37, 118, 4, 88,249, 202,150,145,200,
|
||||
61, 59, 60, 60, 228,252,117, 77, 60, 58,248,251, 81,212,254,107,
|
||||
198, 59, 58,169, 250,251, 81, 80, 100, 58,154,250, 251,252,252,252};
|
||||
|
||||
static double intensity[4] = {
|
||||
77.175381, 88.654656, 166.564623, 174.228438};
|
||||
|
||||
#define NEW_CGA(c,i,r,g,b) (((c)/0.72)*0.29 + ((i)/0.28)*0.32 + ((r)/0.28)*0.1 + ((g)/0.28)*0.22 + ((b)/0.28)*0.07)
|
||||
|
||||
double mode_brightness;
|
||||
double mode_contrast;
|
||||
double mode_hue;
|
||||
double min_v;
|
||||
double max_v;
|
||||
|
||||
double video_ri, video_rq, video_gi, video_gq, video_bi, video_bq;
|
||||
int video_sharpness;
|
||||
int tandy_mode_control = 0;
|
||||
|
||||
static bool new_cga = 0;
|
||||
|
||||
void update_cga16_color(uint8_t cgamode) {
|
||||
int x;
|
||||
double c, i, v;
|
||||
double q, a, s, r;
|
||||
double iq_adjust_i, iq_adjust_q;
|
||||
double i0, i3, mode_saturation;
|
||||
|
||||
static const double ri = 0.9563;
|
||||
static const double rq = 0.6210;
|
||||
static const double gi = -0.2721;
|
||||
static const double gq = -0.6474;
|
||||
static const double bi = -1.1069;
|
||||
static const double bq = 1.7046;
|
||||
|
||||
if (!new_cga) {
|
||||
min_v = chroma_multiplexer[0] + intensity[0];
|
||||
max_v = chroma_multiplexer[255] + intensity[3];
|
||||
}
|
||||
else {
|
||||
i0 = intensity[0];
|
||||
i3 = intensity[3];
|
||||
min_v = NEW_CGA(chroma_multiplexer[0], i0, i0, i0, i0);
|
||||
max_v = NEW_CGA(chroma_multiplexer[255], i3, i3, i3, i3);
|
||||
}
|
||||
mode_contrast = 256/(max_v - min_v);
|
||||
mode_brightness = -min_v*mode_contrast;
|
||||
if ((cgamode & 3) == 1)
|
||||
mode_hue = 14;
|
||||
else
|
||||
mode_hue = 4;
|
||||
|
||||
mode_contrast *= contrast * (new_cga ? 1.2 : 1)/100; /* new CGA: 120% */
|
||||
mode_brightness += (new_cga ? brightness-10 : brightness)*5; /* new CGA: -10 */
|
||||
mode_saturation = (new_cga ? 4.35 : 2.9)*saturation/100; /* new CGA: 150% */
|
||||
|
||||
for (x = 0; x < 1024; ++x) {
|
||||
int phase = x & 3;
|
||||
int right = (x >> 2) & 15;
|
||||
int left = (x >> 6) & 15;
|
||||
int rc = right;
|
||||
int lc = left;
|
||||
if ((cgamode & 4) != 0) {
|
||||
rc = (right & 8) | ((right & 7) != 0 ? 7 : 0);
|
||||
lc = (left & 8) | ((left & 7) != 0 ? 7 : 0);
|
||||
}
|
||||
c = chroma_multiplexer[((lc & 7) << 5) | ((rc & 7) << 2) | phase];
|
||||
i = intensity[(left >> 3) | ((right >> 2) & 2)];
|
||||
if (!new_cga)
|
||||
v = c + i;
|
||||
else {
|
||||
double r = intensity[((left >> 2) & 1) | ((right >> 1) & 2)];
|
||||
double g = intensity[((left >> 1) & 1) | (right & 2)];
|
||||
double b = intensity[(left & 1) | ((right << 1) & 2)];
|
||||
v = NEW_CGA(c, i, r, g, b);
|
||||
}
|
||||
CGA_Composite_Table[x] = (int) (v*mode_contrast + mode_brightness);
|
||||
}
|
||||
|
||||
i = CGA_Composite_Table[6*68] - CGA_Composite_Table[6*68 + 2];
|
||||
q = CGA_Composite_Table[6*68 + 1] - CGA_Composite_Table[6*68 + 3];
|
||||
|
||||
a = tau*(33 + 90 + hue_offset + mode_hue)/360.0;
|
||||
c = cos(a);
|
||||
s = sin(a);
|
||||
r = 256*mode_saturation/sqrt(i*i+q*q);
|
||||
|
||||
iq_adjust_i = -(i*c + q*s)*r;
|
||||
iq_adjust_q = (q*c - i*s)*r;
|
||||
|
||||
video_ri = (int) (ri*iq_adjust_i + rq*iq_adjust_q);
|
||||
video_rq = (int) (-ri*iq_adjust_q + rq*iq_adjust_i);
|
||||
video_gi = (int) (gi*iq_adjust_i + gq*iq_adjust_q);
|
||||
video_gq = (int) (-gi*iq_adjust_q + gq*iq_adjust_i);
|
||||
video_bi = (int) (bi*iq_adjust_i + bq*iq_adjust_q);
|
||||
video_bq = (int) (-bi*iq_adjust_q + bq*iq_adjust_i);
|
||||
video_sharpness = (int) (sharpness*256/100);
|
||||
}
|
||||
|
||||
static Bit8u byte_clamp(int v) {
|
||||
v >>= 13;
|
||||
return v < 0 ? 0 : (v > 255 ? 255 : v);
|
||||
}
|
||||
|
||||
/* 2048x1536 is the maximum we can possibly support. */
|
||||
#define SCALER_MAXWIDTH 2048
|
||||
|
||||
static int temp[SCALER_MAXWIDTH + 10]={0};
|
||||
static int atemp[SCALER_MAXWIDTH + 2]={0};
|
||||
static int btemp[SCALER_MAXWIDTH + 2]={0};
|
||||
|
||||
Bit8u * Composite_Process(uint8_t cgamode, Bit8u border, Bit32u blocks/*, bool doublewidth*/, Bit8u *TempLine)
|
||||
{
|
||||
int x;
|
||||
Bit32u x2;
|
||||
|
||||
int w = blocks*4;
|
||||
|
||||
int *o;
|
||||
Bit8u *rgbi;
|
||||
int *b;
|
||||
int *i;
|
||||
Bit32u* srgb;
|
||||
int *ap, *bp;
|
||||
|
||||
#define COMPOSITE_CONVERT(I, Q) do { \
|
||||
i[1] = (i[1]<<3) - ap[1]; \
|
||||
a = ap[0]; \
|
||||
b = bp[0]; \
|
||||
c = i[0]+i[0]; \
|
||||
d = i[-1]+i[1]; \
|
||||
y = ((c+d)<<8) + video_sharpness*(c-d); \
|
||||
rr = y + video_ri*(I) + video_rq*(Q); \
|
||||
gg = y + video_gi*(I) + video_gq*(Q); \
|
||||
bb = y + video_bi*(I) + video_bq*(Q); \
|
||||
++i; \
|
||||
++ap; \
|
||||
++bp; \
|
||||
*srgb = (byte_clamp(rr)<<16) | (byte_clamp(gg)<<8) | byte_clamp(bb); \
|
||||
++srgb; \
|
||||
} while (0)
|
||||
|
||||
#define OUT(v) do { *o = (v); ++o; } while (0)
|
||||
|
||||
/* Simulate CGA composite output */
|
||||
o = temp;
|
||||
rgbi = TempLine;
|
||||
b = &CGA_Composite_Table[border*68];
|
||||
for (x = 0; x < 4; ++x)
|
||||
OUT(b[(x+3)&3]);
|
||||
OUT(CGA_Composite_Table[(border<<6) | ((*rgbi)<<2) | 3]);
|
||||
for (x = 0; x < w-1; ++x) {
|
||||
OUT(CGA_Composite_Table[(rgbi[0]<<6) | (rgbi[1]<<2) | (x&3)]);
|
||||
++rgbi;
|
||||
}
|
||||
OUT(CGA_Composite_Table[((*rgbi)<<6) | (border<<2) | 3]);
|
||||
for (x = 0; x < 5; ++x)
|
||||
OUT(b[x&3]);
|
||||
|
||||
if ((cgamode & 4) != 0) {
|
||||
/* Decode */
|
||||
i = temp + 5;
|
||||
srgb = (Bit32u *)TempLine;
|
||||
for (x2 = 0; x2 < blocks*4; ++x2) {
|
||||
int c = (i[0]+i[0])<<3;
|
||||
int d = (i[-1]+i[1])<<3;
|
||||
int y = ((c+d)<<8) + video_sharpness*(c-d);
|
||||
++i;
|
||||
*srgb = byte_clamp(y)*0x10101;
|
||||
++srgb;
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* Store chroma */
|
||||
i = temp + 4;
|
||||
ap = atemp + 1;
|
||||
bp = btemp + 1;
|
||||
for (x = -1; x < w + 1; ++x) {
|
||||
ap[x] = i[-4]-((i[-2]-i[0]+i[2])<<1)+i[4];
|
||||
bp[x] = (i[-3]-i[-1]+i[1]-i[3])<<1;
|
||||
++i;
|
||||
}
|
||||
|
||||
/* Decode */
|
||||
i = temp + 5;
|
||||
i[-1] = (i[-1]<<3) - ap[-1];
|
||||
i[0] = (i[0]<<3) - ap[0];
|
||||
srgb = (Bit32u *)TempLine;
|
||||
for (x2 = 0; x2 < blocks; ++x2) {
|
||||
int y,a,b,c,d,rr,gg,bb;
|
||||
COMPOSITE_CONVERT(a, b);
|
||||
COMPOSITE_CONVERT(-b, a);
|
||||
COMPOSITE_CONVERT(-a, -b);
|
||||
COMPOSITE_CONVERT(b, -a);
|
||||
}
|
||||
}
|
||||
#undef COMPOSITE_CONVERT
|
||||
#undef OUT
|
||||
|
||||
return TempLine;
|
||||
}
|
||||
|
||||
void IncreaseHue(uint8_t cgamode)
|
||||
{
|
||||
hue_offset += 5.0;
|
||||
|
||||
update_cga16_color(cgamode);
|
||||
}
|
||||
|
||||
void DecreaseHue(uint8_t cgamode)
|
||||
{
|
||||
hue_offset -= 5.0;
|
||||
|
||||
update_cga16_color(cgamode);
|
||||
}
|
||||
|
||||
void IncreaseSaturation(uint8_t cgamode)
|
||||
{
|
||||
saturation += 5;
|
||||
|
||||
update_cga16_color(cgamode);
|
||||
}
|
||||
|
||||
void DecreaseSaturation(uint8_t cgamode)
|
||||
{
|
||||
saturation -= 5;
|
||||
|
||||
update_cga16_color(cgamode);
|
||||
}
|
||||
|
||||
void IncreaseContrast(uint8_t cgamode)
|
||||
{
|
||||
contrast += 5;
|
||||
|
||||
update_cga16_color(cgamode);
|
||||
}
|
||||
|
||||
void DecreaseContrast(uint8_t cgamode)
|
||||
{
|
||||
contrast -= 5;
|
||||
|
||||
update_cga16_color(cgamode);
|
||||
}
|
||||
|
||||
void IncreaseBrightness(uint8_t cgamode)
|
||||
{
|
||||
brightness += 5;
|
||||
|
||||
update_cga16_color(cgamode);
|
||||
}
|
||||
|
||||
void DecreaseBrightness(uint8_t cgamode)
|
||||
{
|
||||
brightness -= 5;
|
||||
|
||||
update_cga16_color(cgamode);
|
||||
}
|
||||
|
||||
void IncreaseSharpness(uint8_t cgamode)
|
||||
{
|
||||
sharpness += 10;
|
||||
|
||||
update_cga16_color(cgamode);
|
||||
}
|
||||
|
||||
void DecreaseSharpness(uint8_t cgamode)
|
||||
{
|
||||
sharpness -= 10;
|
||||
|
||||
update_cga16_color(cgamode);
|
||||
}
|
||||
|
||||
void cga_comp_init(int revision)
|
||||
{
|
||||
new_cga = revision;
|
||||
|
||||
/* Making sure this gets reset after reset. */
|
||||
brightness = 0;
|
||||
contrast = 100;
|
||||
saturation = 100;
|
||||
sharpness = 0;
|
||||
hue_offset = 0;
|
||||
|
||||
update_cga16_color(0);
|
||||
}
|
||||
27
backup code/video - Cópia/vid_cga_comp.h
Normal file
27
backup code/video - Cópia/vid_cga_comp.h
Normal file
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
*
|
||||
* This file is part of the 86Box distribution.
|
||||
*
|
||||
* IBM CGA composite filter, borrowed from reenigne's DOSBox
|
||||
* patch and ported to C.
|
||||
*
|
||||
* Version: @(#)vid_cga.h 1.0.0 2017/05/30
|
||||
*
|
||||
* Author: reenigne,
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
* Copyright 2015-2017 reenigne.
|
||||
* Copyright 2015-2017 Miran Grca.
|
||||
*/
|
||||
|
||||
#define Bit8u uint8_t
|
||||
#define Bit32u uint32_t
|
||||
#define Bitu unsigned int
|
||||
#define bool uint8_t
|
||||
|
||||
void update_cga16_color(uint8_t cgamode);
|
||||
void cga_comp_init(int revision);
|
||||
Bit8u * Composite_Process(uint8_t cgamode, Bit8u border, Bit32u blocks/*, bool doublewidth*/, Bit8u *TempLine);
|
||||
2685
backup code/video - Cópia/vid_cl54xx - Cópia.c
Normal file
2685
backup code/video - Cópia/vid_cl54xx - Cópia.c
Normal file
File diff suppressed because it is too large
Load Diff
2691
backup code/video - Cópia/vid_cl54xx.c
Normal file
2691
backup code/video - Cópia/vid_cl54xx.c
Normal file
File diff suppressed because it is too large
Load Diff
19
backup code/video - Cópia/vid_cl54xx.h
Normal file
19
backup code/video - Cópia/vid_cl54xx.h
Normal file
@@ -0,0 +1,19 @@
|
||||
/* Copyright holders: Sarah Walker
|
||||
see COPYING for more details
|
||||
*/
|
||||
extern const device_t gd5426_vlb_device;
|
||||
extern const device_t gd5428_isa_device;
|
||||
extern const device_t gd5428_vlb_device;
|
||||
extern const device_t gd5429_isa_device;
|
||||
extern const device_t gd5429_vlb_device;
|
||||
extern const device_t gd5430_vlb_device;
|
||||
extern const device_t gd5430_pci_device;
|
||||
extern const device_t gd5434_isa_device;
|
||||
extern const device_t gd5434_vlb_device;
|
||||
extern const device_t gd5434_pci_device;
|
||||
extern const device_t gd5436_pci_device;
|
||||
extern const device_t gd5440_onboard_pci_device;
|
||||
extern const device_t gd5440_pci_device;
|
||||
extern const device_t gd5446_pci_device;
|
||||
extern const device_t gd5446_stb_pci_device;
|
||||
extern const device_t gd5480_pci_device;
|
||||
477
backup code/video - Cópia/vid_colorplus.c
Normal file
477
backup code/video - Cópia/vid_colorplus.c
Normal file
@@ -0,0 +1,477 @@
|
||||
/*
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
*
|
||||
* This file is part of the 86Box distribution.
|
||||
*
|
||||
* Plantronics ColorPlus emulation.
|
||||
*
|
||||
* Version: @(#)vid_colorplus.c 1.0.9 2018/04/26
|
||||
*
|
||||
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
*
|
||||
* Copyright 2008-2018 Sarah Walker.
|
||||
* Copyright 2016-2018 Miran Grca.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <wchar.h>
|
||||
#include <math.h>
|
||||
#include "../86box.h"
|
||||
#include "../cpu/cpu.h"
|
||||
#include "../io.h"
|
||||
#include "../lpt.h"
|
||||
#include "../pit.h"
|
||||
#include "../mem.h"
|
||||
#include "../timer.h"
|
||||
#include "../device.h"
|
||||
#include "video.h"
|
||||
#include "vid_cga.h"
|
||||
#include "vid_colorplus.h"
|
||||
#include "vid_cga_comp.h"
|
||||
|
||||
|
||||
/* Bits in the colorplus control register: */
|
||||
#define COLORPLUS_PLANE_SWAP 0x40 /* Swap planes at 0000h and 4000h */
|
||||
#define COLORPLUS_640x200_MODE 0x20 /* 640x200x4 mode active */
|
||||
#define COLORPLUS_320x200_MODE 0x10 /* 320x200x16 mode active */
|
||||
#define COLORPLUS_EITHER_MODE 0x30 /* Either mode active */
|
||||
|
||||
/* Bits in the CGA graphics mode register */
|
||||
#define CGA_GRAPHICS_MODE 0x02 /* CGA graphics mode selected? */
|
||||
|
||||
#define CGA_RGB 0
|
||||
#define CGA_COMPOSITE 1
|
||||
|
||||
#define COMPOSITE_OLD 0
|
||||
#define COMPOSITE_NEW 1
|
||||
|
||||
|
||||
void cga_recalctimings(cga_t *cga);
|
||||
|
||||
void colorplus_out(uint16_t addr, uint8_t val, void *p)
|
||||
{
|
||||
colorplus_t *colorplus = (colorplus_t *)p;
|
||||
|
||||
if (addr == 0x3DD)
|
||||
{
|
||||
colorplus->control = val & 0x70;
|
||||
}
|
||||
else
|
||||
{
|
||||
cga_out(addr, val, &colorplus->cga);
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t colorplus_in(uint16_t addr, void *p)
|
||||
{
|
||||
colorplus_t *colorplus = (colorplus_t *)p;
|
||||
|
||||
return cga_in(addr, &colorplus->cga);
|
||||
}
|
||||
|
||||
void colorplus_write(uint32_t addr, uint8_t val, void *p)
|
||||
{
|
||||
colorplus_t *colorplus = (colorplus_t *)p;
|
||||
|
||||
if ((colorplus->control & COLORPLUS_PLANE_SWAP) &&
|
||||
(colorplus->control & COLORPLUS_EITHER_MODE) &&
|
||||
(colorplus->cga.cgamode & CGA_GRAPHICS_MODE))
|
||||
{
|
||||
addr ^= 0x4000;
|
||||
}
|
||||
else if (!(colorplus->control & COLORPLUS_EITHER_MODE))
|
||||
{
|
||||
addr &= 0x3FFF;
|
||||
}
|
||||
colorplus->cga.vram[addr & 0x7fff] = val;
|
||||
if (colorplus->cga.snow_enabled)
|
||||
{
|
||||
colorplus->cga.charbuffer[ ((int)(((colorplus->cga.dispontime - colorplus->cga.vidtime) * 2) / CGACONST)) & 0xfc] = val;
|
||||
colorplus->cga.charbuffer[(((int)(((colorplus->cga.dispontime - colorplus->cga.vidtime) * 2) / CGACONST)) & 0xfc) | 1] = val;
|
||||
}
|
||||
egawrites++;
|
||||
cycles -= 4;
|
||||
}
|
||||
|
||||
uint8_t colorplus_read(uint32_t addr, void *p)
|
||||
{
|
||||
colorplus_t *colorplus = (colorplus_t *)p;
|
||||
|
||||
if ((colorplus->control & COLORPLUS_PLANE_SWAP) &&
|
||||
(colorplus->control & COLORPLUS_EITHER_MODE) &&
|
||||
(colorplus->cga.cgamode & CGA_GRAPHICS_MODE))
|
||||
{
|
||||
addr ^= 0x4000;
|
||||
}
|
||||
else if (!(colorplus->control & COLORPLUS_EITHER_MODE))
|
||||
{
|
||||
addr &= 0x3FFF;
|
||||
}
|
||||
cycles -= 4;
|
||||
if (colorplus->cga.snow_enabled)
|
||||
{
|
||||
colorplus->cga.charbuffer[ ((int)(((colorplus->cga.dispontime - colorplus->cga.vidtime) * 2) / CGACONST)) & 0xfc] = colorplus->cga.vram[addr & 0x7fff];
|
||||
colorplus->cga.charbuffer[(((int)(((colorplus->cga.dispontime - colorplus->cga.vidtime) * 2) / CGACONST)) & 0xfc) | 1] = colorplus->cga.vram[addr & 0x7fff];
|
||||
}
|
||||
egareads++;
|
||||
return colorplus->cga.vram[addr & 0x7fff];
|
||||
}
|
||||
|
||||
void colorplus_recalctimings(colorplus_t *colorplus)
|
||||
{
|
||||
cga_recalctimings(&colorplus->cga);
|
||||
}
|
||||
|
||||
void colorplus_poll(void *p)
|
||||
{
|
||||
colorplus_t *colorplus = (colorplus_t *)p;
|
||||
int x, c;
|
||||
int oldvc;
|
||||
uint16_t dat0, dat1;
|
||||
int cols[4];
|
||||
int col;
|
||||
int oldsc;
|
||||
static const int cols16[16] = { 0x10,0x12,0x14,0x16,
|
||||
0x18,0x1A,0x1C,0x1E,
|
||||
0x11,0x13,0x15,0x17,
|
||||
0x19,0x1B,0x1D,0x1F };
|
||||
uint8_t *plane0 = colorplus->cga.vram;
|
||||
uint8_t *plane1 = colorplus->cga.vram + 0x4000;
|
||||
|
||||
/* If one of the extra modes is not selected, drop down to the CGA
|
||||
* drawing code. */
|
||||
if (!((colorplus->control & COLORPLUS_EITHER_MODE) &&
|
||||
(colorplus->cga.cgamode & CGA_GRAPHICS_MODE)))
|
||||
{
|
||||
cga_poll(&colorplus->cga);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!colorplus->cga.linepos)
|
||||
{
|
||||
colorplus->cga.vidtime += colorplus->cga.dispofftime;
|
||||
colorplus->cga.cgastat |= 1;
|
||||
colorplus->cga.linepos = 1;
|
||||
oldsc = colorplus->cga.sc;
|
||||
if ((colorplus->cga.crtc[8] & 3) == 3)
|
||||
colorplus->cga.sc = ((colorplus->cga.sc << 1) + colorplus->cga.oddeven) & 7;
|
||||
if (colorplus->cga.cgadispon)
|
||||
{
|
||||
if (colorplus->cga.displine < colorplus->cga.firstline)
|
||||
{
|
||||
colorplus->cga.firstline = colorplus->cga.displine;
|
||||
video_wait_for_buffer();
|
||||
}
|
||||
colorplus->cga.lastline = colorplus->cga.displine;
|
||||
/* Left / right border */
|
||||
for (c = 0; c < 8; c++)
|
||||
{
|
||||
buffer->line[colorplus->cga.displine][c] =
|
||||
buffer->line[colorplus->cga.displine][c + (colorplus->cga.crtc[1] << 4) + 8] = (colorplus->cga.cgacol & 15) + 16;
|
||||
}
|
||||
if (colorplus->control & COLORPLUS_320x200_MODE)
|
||||
{
|
||||
for (x = 0; x < colorplus->cga.crtc[1]; x++)
|
||||
{
|
||||
dat0 = (plane0[((colorplus->cga.ma << 1) & 0x1fff) + ((colorplus->cga.sc & 1) * 0x2000)] << 8) |
|
||||
plane0[((colorplus->cga.ma << 1) & 0x1fff) + ((colorplus->cga.sc & 1) * 0x2000) + 1];
|
||||
dat1 = (plane1[((colorplus->cga.ma << 1) & 0x1fff) + ((colorplus->cga.sc & 1) * 0x2000)] << 8) |
|
||||
plane1[((colorplus->cga.ma << 1) & 0x1fff) + ((colorplus->cga.sc & 1) * 0x2000) + 1];
|
||||
colorplus->cga.ma++;
|
||||
for (c = 0; c < 8; c++)
|
||||
{
|
||||
buffer->line[colorplus->cga.displine][(x << 4) + (c << 1) + 8] =
|
||||
buffer->line[colorplus->cga.displine][(x << 4) + (c << 1) + 1 + 8] =
|
||||
cols16[(dat0 >> 14) | ((dat1 >> 14) << 2)];
|
||||
dat0 <<= 2;
|
||||
dat1 <<= 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (colorplus->control & COLORPLUS_640x200_MODE)
|
||||
{
|
||||
cols[0] = (colorplus->cga.cgacol & 15) | 16;
|
||||
col = (colorplus->cga.cgacol & 16) ? 24 : 16;
|
||||
if (colorplus->cga.cgamode & 4)
|
||||
{
|
||||
cols[1] = col | 3;
|
||||
cols[2] = col | 4;
|
||||
cols[3] = col | 7;
|
||||
}
|
||||
else if (colorplus->cga.cgacol & 32)
|
||||
{
|
||||
cols[1] = col | 3;
|
||||
cols[2] = col | 5;
|
||||
cols[3] = col | 7;
|
||||
}
|
||||
else
|
||||
{
|
||||
cols[1] = col | 2;
|
||||
cols[2] = col | 4;
|
||||
cols[3] = col | 6;
|
||||
}
|
||||
for (x = 0; x < colorplus->cga.crtc[1]; x++)
|
||||
{
|
||||
dat0 = (plane0[((colorplus->cga.ma << 1) & 0x1fff) + ((colorplus->cga.sc & 1) * 0x2000)] << 8) |
|
||||
plane0[((colorplus->cga.ma << 1) & 0x1fff) + ((colorplus->cga.sc & 1) * 0x2000) + 1];
|
||||
dat1 = (plane1[((colorplus->cga.ma << 1) & 0x1fff) + ((colorplus->cga.sc & 1) * 0x2000)] << 8) |
|
||||
plane1[((colorplus->cga.ma << 1) & 0x1fff) + ((colorplus->cga.sc & 1) * 0x2000) + 1];
|
||||
colorplus->cga.ma++;
|
||||
for (c = 0; c < 16; c++)
|
||||
{
|
||||
buffer->line[colorplus->cga.displine][(x << 4) + c + 8] =
|
||||
cols[(dat0 >> 15) | ((dat1 >> 15) << 1)];
|
||||
dat0 <<= 1;
|
||||
dat1 <<= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else /* Top / bottom border */
|
||||
{
|
||||
cols[0] = (colorplus->cga.cgacol & 15) + 16;
|
||||
hline(buffer, 0, colorplus->cga.displine, (colorplus->cga.crtc[1] << 4) + 16, cols[0]);
|
||||
}
|
||||
|
||||
x = (colorplus->cga.crtc[1] << 4) + 16;
|
||||
|
||||
if (colorplus->cga.composite)
|
||||
{
|
||||
for (c = 0; c < x; c++)
|
||||
buffer32->line[colorplus->cga.displine][c] = buffer->line[colorplus->cga.displine][c] & 0xf;
|
||||
|
||||
Composite_Process(colorplus->cga.cgamode, 0, x >> 2, buffer32->line[colorplus->cga.displine]);
|
||||
}
|
||||
|
||||
colorplus->cga.sc = oldsc;
|
||||
if (colorplus->cga.vc == colorplus->cga.crtc[7] && !colorplus->cga.sc)
|
||||
colorplus->cga.cgastat |= 8;
|
||||
colorplus->cga.displine++;
|
||||
if (colorplus->cga.displine >= 360)
|
||||
colorplus->cga.displine = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
colorplus->cga.vidtime += colorplus->cga.dispontime;
|
||||
colorplus->cga.linepos = 0;
|
||||
if (colorplus->cga.vsynctime)
|
||||
{
|
||||
colorplus->cga.vsynctime--;
|
||||
if (!colorplus->cga.vsynctime)
|
||||
colorplus->cga.cgastat &= ~8;
|
||||
}
|
||||
if (colorplus->cga.sc == (colorplus->cga.crtc[11] & 31) || ((colorplus->cga.crtc[8] & 3) == 3 && colorplus->cga.sc == ((colorplus->cga.crtc[11] & 31) >> 1)))
|
||||
{
|
||||
colorplus->cga.con = 0;
|
||||
colorplus->cga.coff = 1;
|
||||
}
|
||||
if ((colorplus->cga.crtc[8] & 3) == 3 && colorplus->cga.sc == (colorplus->cga.crtc[9] >> 1))
|
||||
colorplus->cga.maback = colorplus->cga.ma;
|
||||
if (colorplus->cga.vadj)
|
||||
{
|
||||
colorplus->cga.sc++;
|
||||
colorplus->cga.sc &= 31;
|
||||
colorplus->cga.ma = colorplus->cga.maback;
|
||||
colorplus->cga.vadj--;
|
||||
if (!colorplus->cga.vadj)
|
||||
{
|
||||
colorplus->cga.cgadispon = 1;
|
||||
colorplus->cga.ma = colorplus->cga.maback = (colorplus->cga.crtc[13] | (colorplus->cga.crtc[12] << 8)) & 0x3fff;
|
||||
colorplus->cga.sc = 0;
|
||||
}
|
||||
}
|
||||
else if (colorplus->cga.sc == colorplus->cga.crtc[9])
|
||||
{
|
||||
colorplus->cga.maback = colorplus->cga.ma;
|
||||
colorplus->cga.sc = 0;
|
||||
oldvc = colorplus->cga.vc;
|
||||
colorplus->cga.vc++;
|
||||
colorplus->cga.vc &= 127;
|
||||
|
||||
if (colorplus->cga.vc == colorplus->cga.crtc[6])
|
||||
colorplus->cga.cgadispon = 0;
|
||||
|
||||
if (oldvc == colorplus->cga.crtc[4])
|
||||
{
|
||||
colorplus->cga.vc = 0;
|
||||
colorplus->cga.vadj = colorplus->cga.crtc[5];
|
||||
if (!colorplus->cga.vadj) colorplus->cga.cgadispon = 1;
|
||||
if (!colorplus->cga.vadj) colorplus->cga.ma = colorplus->cga.maback = (colorplus->cga.crtc[13] | (colorplus->cga.crtc[12] << 8)) & 0x3fff;
|
||||
if ((colorplus->cga.crtc[10] & 0x60) == 0x20) colorplus->cga.cursoron = 0;
|
||||
else colorplus->cga.cursoron = colorplus->cga.cgablink & 8;
|
||||
}
|
||||
|
||||
if (colorplus->cga.vc == colorplus->cga.crtc[7])
|
||||
{
|
||||
colorplus->cga.cgadispon = 0;
|
||||
colorplus->cga.displine = 0;
|
||||
colorplus->cga.vsynctime = 16;
|
||||
if (colorplus->cga.crtc[7])
|
||||
{
|
||||
if (colorplus->cga.cgamode & 1) x = (colorplus->cga.crtc[1] << 3) + 16;
|
||||
else x = (colorplus->cga.crtc[1] << 4) + 16;
|
||||
colorplus->cga.lastline++;
|
||||
if (x != xsize || (colorplus->cga.lastline - colorplus->cga.firstline) != ysize)
|
||||
{
|
||||
xsize = x;
|
||||
ysize = colorplus->cga.lastline - colorplus->cga.firstline;
|
||||
if (xsize < 64) xsize = 656;
|
||||
if (ysize < 32) ysize = 200;
|
||||
set_screen_size(xsize, (ysize << 1) + 16);
|
||||
}
|
||||
|
||||
if (colorplus->cga.composite)
|
||||
video_blit_memtoscreen(0, colorplus->cga.firstline - 4, 0, (colorplus->cga.lastline - colorplus->cga.firstline) + 8, xsize, (colorplus->cga.lastline - colorplus->cga.firstline) + 8);
|
||||
else
|
||||
video_blit_memtoscreen_8(0, colorplus->cga.firstline - 4, 0, (colorplus->cga.lastline - colorplus->cga.firstline) + 8, xsize, (colorplus->cga.lastline - colorplus->cga.firstline) + 8);
|
||||
frames++;
|
||||
|
||||
video_res_x = xsize - 16;
|
||||
video_res_y = ysize;
|
||||
if (colorplus->cga.cgamode & 1)
|
||||
{
|
||||
video_res_x /= 8;
|
||||
video_res_y /= colorplus->cga.crtc[9] + 1;
|
||||
video_bpp = 0;
|
||||
}
|
||||
else if (!(colorplus->cga.cgamode & 2))
|
||||
{
|
||||
video_res_x /= 16;
|
||||
video_res_y /= colorplus->cga.crtc[9] + 1;
|
||||
video_bpp = 0;
|
||||
}
|
||||
else if (!(colorplus->cga.cgamode & 16))
|
||||
{
|
||||
video_res_x /= 2;
|
||||
video_bpp = 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
video_bpp = 1;
|
||||
}
|
||||
}
|
||||
colorplus->cga.firstline = 1000;
|
||||
colorplus->cga.lastline = 0;
|
||||
colorplus->cga.cgablink++;
|
||||
colorplus->cga.oddeven ^= 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
colorplus->cga.sc++;
|
||||
colorplus->cga.sc &= 31;
|
||||
colorplus->cga.ma = colorplus->cga.maback;
|
||||
}
|
||||
if (colorplus->cga.cgadispon)
|
||||
colorplus->cga.cgastat &= ~1;
|
||||
if ((colorplus->cga.sc == (colorplus->cga.crtc[10] & 31) || ((colorplus->cga.crtc[8] & 3) == 3 && colorplus->cga.sc == ((colorplus->cga.crtc[10] & 31) >> 1))))
|
||||
colorplus->cga.con = 1;
|
||||
if (colorplus->cga.cgadispon && (colorplus->cga.cgamode & 1))
|
||||
{
|
||||
for (x = 0; x < (colorplus->cga.crtc[1] << 1); x++)
|
||||
colorplus->cga.charbuffer[x] = colorplus->cga.vram[(((colorplus->cga.ma << 1) + x) & 0x3fff)];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void colorplus_init(colorplus_t *colorplus)
|
||||
{
|
||||
cga_init(&colorplus->cga);
|
||||
}
|
||||
|
||||
void *colorplus_standalone_init(const device_t *info)
|
||||
{
|
||||
int display_type;
|
||||
|
||||
colorplus_t *colorplus = malloc(sizeof(colorplus_t));
|
||||
memset(colorplus, 0, sizeof(colorplus_t));
|
||||
|
||||
/* Copied from the CGA init. Ideally this would be done by
|
||||
* calling a helper function rather than duplicating code */
|
||||
display_type = device_get_config_int("display_type");
|
||||
colorplus->cga.composite = (display_type != CGA_RGB);
|
||||
colorplus->cga.revision = device_get_config_int("composite_type");
|
||||
colorplus->cga.snow_enabled = device_get_config_int("snow_enabled");
|
||||
|
||||
colorplus->cga.vram = malloc(0x8000);
|
||||
|
||||
cga_comp_init(1);
|
||||
timer_add(colorplus_poll, &colorplus->cga.vidtime, TIMER_ALWAYS_ENABLED, colorplus);
|
||||
mem_mapping_add(&colorplus->cga.mapping, 0xb8000, 0x08000, colorplus_read, NULL, NULL, colorplus_write, NULL, NULL, NULL, MEM_MAPPING_EXTERNAL, colorplus);
|
||||
io_sethandler(0x03d0, 0x0010, colorplus_in, NULL, NULL, colorplus_out, NULL, NULL, colorplus);
|
||||
|
||||
lpt3_init(0x3BC);
|
||||
|
||||
return colorplus;
|
||||
}
|
||||
|
||||
void colorplus_close(void *p)
|
||||
{
|
||||
colorplus_t *colorplus = (colorplus_t *)p;
|
||||
|
||||
free(colorplus->cga.vram);
|
||||
free(colorplus);
|
||||
}
|
||||
|
||||
void colorplus_speed_changed(void *p)
|
||||
{
|
||||
colorplus_t *colorplus = (colorplus_t *)p;
|
||||
|
||||
cga_recalctimings(&colorplus->cga);
|
||||
}
|
||||
|
||||
static const device_config_t colorplus_config[] =
|
||||
{
|
||||
{
|
||||
"display_type", "Display type", CONFIG_SELECTION, "", CGA_RGB,
|
||||
{
|
||||
{
|
||||
"RGB", CGA_RGB
|
||||
},
|
||||
{
|
||||
"Composite", CGA_COMPOSITE
|
||||
},
|
||||
{
|
||||
""
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"composite_type", "Composite type", CONFIG_SELECTION, "", COMPOSITE_OLD,
|
||||
{
|
||||
{
|
||||
"Old", COMPOSITE_OLD
|
||||
},
|
||||
{
|
||||
"New", COMPOSITE_NEW
|
||||
},
|
||||
{
|
||||
""
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"snow_enabled", "Snow emulation", CONFIG_BINARY, "", 1
|
||||
},
|
||||
{
|
||||
"", "", -1
|
||||
}
|
||||
};
|
||||
|
||||
const device_t colorplus_device =
|
||||
{
|
||||
"Colorplus",
|
||||
DEVICE_ISA, 0,
|
||||
colorplus_standalone_init,
|
||||
colorplus_close,
|
||||
NULL, NULL,
|
||||
colorplus_speed_changed,
|
||||
NULL,
|
||||
colorplus_config
|
||||
};
|
||||
15
backup code/video - Cópia/vid_colorplus.h
Normal file
15
backup code/video - Cópia/vid_colorplus.h
Normal file
@@ -0,0 +1,15 @@
|
||||
typedef struct colorplus_t
|
||||
{
|
||||
cga_t cga;
|
||||
uint8_t control;
|
||||
} colorplus_t;
|
||||
|
||||
void colorplus_init(colorplus_t *colorplus);
|
||||
void colorplus_out(uint16_t addr, uint8_t val, void *p);
|
||||
uint8_t colorplus_in(uint16_t addr, void *p);
|
||||
void colorplus_write(uint32_t addr, uint8_t val, void *p);
|
||||
uint8_t colorplus_read(uint32_t addr, void *p);
|
||||
void colorplus_recalctimings(colorplus_t *colorplus);
|
||||
void colorplus_poll(void *p);
|
||||
|
||||
extern const device_t colorplus_device;
|
||||
461
backup code/video - Cópia/vid_compaq_cga.c
Normal file
461
backup code/video - Cópia/vid_compaq_cga.c
Normal file
@@ -0,0 +1,461 @@
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <wchar.h>
|
||||
#include <math.h>
|
||||
#include "../86box.h"
|
||||
#include "../cpu/cpu.h"
|
||||
#include "../io.h"
|
||||
#include "../pit.h"
|
||||
#include "../mem.h"
|
||||
#include "../rom.h"
|
||||
#include "../timer.h"
|
||||
#include "../device.h"
|
||||
#include "video.h"
|
||||
#include "vid_cga.h"
|
||||
#include "vid_cga_comp.h"
|
||||
|
||||
#define CGA_RGB 0
|
||||
#define CGA_COMPOSITE 1
|
||||
|
||||
typedef struct compaq_cga_t
|
||||
{
|
||||
cga_t cga;
|
||||
uint32_t flags;
|
||||
} compaq_cga_t;
|
||||
|
||||
static uint8_t mdaattr[256][2][2];
|
||||
|
||||
void compaq_cga_recalctimings(compaq_cga_t *self)
|
||||
{
|
||||
double _dispontime, _dispofftime, disptime;
|
||||
disptime = self->cga.crtc[0] + 1;
|
||||
_dispontime = self->cga.crtc[1];
|
||||
_dispofftime = disptime - _dispontime;
|
||||
_dispontime *= MDACONST;
|
||||
_dispofftime *= MDACONST;
|
||||
self->cga.dispontime = (int)(_dispontime * (1 << TIMER_SHIFT));
|
||||
self->cga.dispofftime = (int)(_dispofftime * (1 << TIMER_SHIFT));
|
||||
}
|
||||
|
||||
void compaq_cga_poll(void *p)
|
||||
{
|
||||
compaq_cga_t *self = (compaq_cga_t *)p;
|
||||
uint16_t ca = (self->cga.crtc[15] | (self->cga.crtc[14] << 8)) & 0x3fff;
|
||||
int drawcursor;
|
||||
int x, c;
|
||||
int oldvc;
|
||||
uint8_t chr, attr;
|
||||
uint32_t cols[4];
|
||||
int oldsc;
|
||||
int underline = 0;
|
||||
int blink = 0;
|
||||
|
||||
/* If in graphics mode or character height is not 13, behave as CGA */
|
||||
if ((self->cga.cgamode & 0x12) || (self->cga.crtc[9] != 13))
|
||||
{
|
||||
overscan_x = overscan_y = 16;
|
||||
cga_poll(&self->cga);
|
||||
return;
|
||||
} else
|
||||
overscan_x = overscan_y = 0;
|
||||
|
||||
/* We are in Compaq 350-line CGA territory */
|
||||
if (!self->cga.linepos)
|
||||
{
|
||||
self->cga.vidtime += self->cga.dispofftime;
|
||||
self->cga.cgastat |= 1;
|
||||
self->cga.linepos = 1;
|
||||
oldsc = self->cga.sc;
|
||||
if ((self->cga.crtc[8] & 3) == 3)
|
||||
self->cga.sc = ((self->cga.sc << 1) + self->cga.oddeven) & 7;
|
||||
if (self->cga.cgadispon)
|
||||
{
|
||||
if (self->cga.displine < self->cga.firstline)
|
||||
{
|
||||
self->cga.firstline = self->cga.displine;
|
||||
video_wait_for_buffer();
|
||||
// printf("Firstline %i\n",firstline);
|
||||
}
|
||||
self->cga.lastline = self->cga.displine;
|
||||
|
||||
cols[0] = (self->cga.cgacol & 15);
|
||||
|
||||
for (c = 0; c < 8; c++)
|
||||
{
|
||||
((uint32_t *)buffer32->line[self->cga.displine])[c] = cols[0];
|
||||
if (self->cga.cgamode & 1)
|
||||
((uint32_t *)buffer32->line[self->cga.displine])[c + (self->cga.crtc[1] << 3) + 8] = cols[0];
|
||||
else
|
||||
((uint32_t *)buffer32->line[self->cga.displine])[c + (self->cga.crtc[1] << 4) + 8] = cols[0];
|
||||
}
|
||||
if (self->cga.cgamode & 1)
|
||||
{
|
||||
for (x = 0; x < self->cga.crtc[1]; x++)
|
||||
{
|
||||
chr = self->cga.charbuffer[x << 1];
|
||||
attr = self->cga.charbuffer[(x << 1) + 1];
|
||||
drawcursor = ((self->cga.ma == ca) && self->cga.con && self->cga.cursoron);
|
||||
if (self->flags) {
|
||||
underline = 0;
|
||||
blink = ((self->cga.cgablink & 8) && (self->cga.cgamode & 0x20) && (attr & 0x80) && !drawcursor);
|
||||
}
|
||||
if (self->flags && (self->cga.cgamode & 0x80))
|
||||
{
|
||||
cols[0] = mdaattr[attr][blink][0];
|
||||
cols[1] = mdaattr[attr][blink][1];
|
||||
if (self->cga.sc == 12 && (attr & 7) == 1) underline = 1;
|
||||
}
|
||||
else if (self->cga.cgamode & 0x20)
|
||||
{
|
||||
cols[1] = (attr & 15) + 16;
|
||||
cols[0] = ((attr >> 4) & 7) + 16;
|
||||
if (self->flags) {
|
||||
if (blink)
|
||||
cols[1] = cols[0];
|
||||
} else {
|
||||
if ((self->cga.cgablink & 8) && (attr & 0x80) && !self->cga.drawcursor)
|
||||
cols[1] = cols[0];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
cols[1] = (attr & 15) + 16;
|
||||
cols[0] = (attr >> 4) + 16;
|
||||
}
|
||||
if (self->flags && underline)
|
||||
{
|
||||
for (c = 0; c < 8; c++)
|
||||
((uint32_t *)buffer32->line[self->cga.displine])[(x << 3) + c + 8] = mdaattr[attr][blink][1];
|
||||
}
|
||||
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.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.fontbase][self->cga.sc & 15] & (1 << (c ^ 7))) ? 1 : 0];
|
||||
}
|
||||
self->cga.ma++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (x = 0; x < self->cga.crtc[1]; x++)
|
||||
{
|
||||
chr = self->cga.vram[((self->cga.ma << 1) & 0x3fff)];
|
||||
attr = self->cga.vram[(((self->cga.ma << 1) + 1) & 0x3fff)];
|
||||
drawcursor = ((self->cga.ma == ca) && self->cga.con && self->cga.cursoron);
|
||||
if (self->flags) {
|
||||
underline = 0;
|
||||
blink = ((self->cga.cgablink & 8) && (self->cga.cgamode & 0x20) && (attr & 0x80) && !drawcursor);
|
||||
}
|
||||
if (self->flags && (self->cga.cgamode & 0x80))
|
||||
{
|
||||
cols[0] = mdaattr[attr][blink][0];
|
||||
cols[1] = mdaattr[attr][blink][1];
|
||||
if (self->cga.sc == 12 && (attr & 7) == 1) underline = 1;
|
||||
}
|
||||
else if (self->cga.cgamode & 0x20)
|
||||
{
|
||||
cols[1] = (attr & 15) + 16;
|
||||
cols[0] = ((attr >> 4) & 7) + 16;
|
||||
if (self->flags) {
|
||||
if (blink)
|
||||
cols[1] = cols[0];
|
||||
} else {
|
||||
if ((self->cga.cgablink & 8) && (attr & 0x80) && !self->cga.drawcursor)
|
||||
cols[1] = cols[0];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
cols[1] = (attr & 15) + 16;
|
||||
cols[0] = (attr >> 4) + 16;
|
||||
}
|
||||
self->cga.ma++;
|
||||
if (self->flags && underline)
|
||||
{
|
||||
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) + 9] = mdaattr[attr][blink][1];
|
||||
}
|
||||
else if (drawcursor)
|
||||
{
|
||||
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.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.fontbase][self->cga.sc & 15] & (1 << (c ^ 7))) ? 1 : 0];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
cols[0] = (self->cga.cgacol & 15) + 16;
|
||||
if (self->cga.cgamode & 1) hline(buffer32, 0, self->cga.displine, (self->cga.crtc[1] << 3) + 16, cols[0]);
|
||||
else hline(buffer32, 0, self->cga.displine, (self->cga.crtc[1] << 4) + 16, cols[0]);
|
||||
}
|
||||
|
||||
if (self->cga.cgamode & 1) x = (self->cga.crtc[1] << 3) + 16;
|
||||
else x = (self->cga.crtc[1] << 4) + 16;
|
||||
|
||||
if (self->cga.composite)
|
||||
{
|
||||
for (c = 0; c < x; c++)
|
||||
buffer32->line[self->cga.displine][c] = ((uint32_t *)buffer32->line[self->cga.displine])[c] & 0xf;
|
||||
|
||||
if (self->flags)
|
||||
Composite_Process(self->cga.cgamode & 0x7F, 0, x >> 2, buffer32->line[self->cga.displine]);
|
||||
else
|
||||
Composite_Process(self->cga.cgamode, 0, x >> 2, buffer32->line[self->cga.displine]);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (c = 0; c < x; c++)
|
||||
buffer->line[self->cga.displine][c] = ((uint32_t *)buffer32->line[self->cga.displine])[c];
|
||||
}
|
||||
|
||||
self->cga.sc = oldsc;
|
||||
if (self->cga.vc == self->cga.crtc[7] && !self->cga.sc)
|
||||
self->cga.cgastat |= 8;
|
||||
self->cga.displine++;
|
||||
if (self->cga.displine >= 500)
|
||||
self->cga.displine = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
self->cga.vidtime += self->cga.dispontime;
|
||||
self->cga.linepos = 0;
|
||||
if (self->cga.vsynctime)
|
||||
{
|
||||
self->cga.vsynctime--;
|
||||
if (!self->cga.vsynctime)
|
||||
self->cga.cgastat &= ~8;
|
||||
}
|
||||
if (self->cga.sc == (self->cga.crtc[11] & 31) || ((self->cga.crtc[8] & 3) == 3 && self->cga.sc == ((self->cga.crtc[11] & 31) >> 1)))
|
||||
{
|
||||
self->cga.con = 0;
|
||||
self->cga.coff = 1;
|
||||
}
|
||||
if ((self->cga.crtc[8] & 3) == 3 && self->cga.sc == (self->cga.crtc[9] >> 1))
|
||||
self->cga.maback = self->cga.ma;
|
||||
if (self->cga.vadj)
|
||||
{
|
||||
self->cga.sc++;
|
||||
self->cga.sc &= 31;
|
||||
self->cga.ma = self->cga.maback;
|
||||
self->cga.vadj--;
|
||||
if (!self->cga.vadj)
|
||||
{
|
||||
self->cga.cgadispon = 1;
|
||||
self->cga.ma = self->cga.maback = (self->cga.crtc[13] | (self->cga.crtc[12] << 8)) & 0x3fff;
|
||||
self->cga.sc = 0;
|
||||
}
|
||||
}
|
||||
else if (self->cga.sc == self->cga.crtc[9])
|
||||
{
|
||||
self->cga.maback = self->cga.ma;
|
||||
self->cga.sc = 0;
|
||||
oldvc = self->cga.vc;
|
||||
self->cga.vc++;
|
||||
self->cga.vc &= 127;
|
||||
|
||||
if (self->cga.vc == self->cga.crtc[6])
|
||||
self->cga.cgadispon = 0;
|
||||
|
||||
if (oldvc == self->cga.crtc[4])
|
||||
{
|
||||
self->cga.vc = 0;
|
||||
self->cga.vadj = self->cga.crtc[5];
|
||||
if (!self->cga.vadj) self->cga.cgadispon = 1;
|
||||
if (!self->cga.vadj) self->cga.ma = self->cga.maback = (self->cga.crtc[13] | (self->cga.crtc[12] << 8)) & 0x3fff;
|
||||
if ((self->cga.crtc[10] & 0x60) == 0x20) self->cga.cursoron = 0;
|
||||
else self->cga.cursoron = self->cga.cgablink & 8;
|
||||
}
|
||||
|
||||
if (self->cga.vc == self->cga.crtc[7])
|
||||
{
|
||||
self->cga.cgadispon = 0;
|
||||
self->cga.displine = 0;
|
||||
self->cga.vsynctime = 16;
|
||||
if (self->cga.crtc[7])
|
||||
{
|
||||
// printf("Lastline %i Firstline %i %i\n",self->cga.lastline,self->cga.firstline,self->cga.lastline-self->cga.firstline);
|
||||
|
||||
if (self->cga.cgamode & 1) x = (self->cga.crtc[1] << 3);
|
||||
else x = (self->cga.crtc[1] << 4);
|
||||
self->cga.lastline++;
|
||||
if (x != xsize || (self->cga.lastline - self->cga.firstline) != ysize)
|
||||
{
|
||||
xsize = x;
|
||||
ysize = self->cga.lastline - self->cga.firstline;
|
||||
// printf("Resize to %i,%i - R1 %i\n",xsize,ysize,self->cga.crtc[1]);
|
||||
|
||||
if (xsize < 64) xsize = 656;
|
||||
if (ysize < 32) ysize = 200;
|
||||
set_screen_size(xsize, ysize);
|
||||
}
|
||||
|
||||
if (self->cga.composite)
|
||||
video_blit_memtoscreen(8, self->cga.firstline, 0, ysize, xsize, ysize);
|
||||
else
|
||||
video_blit_memtoscreen_8(8, self->cga.firstline, 0, ysize, xsize, ysize);
|
||||
frames++;
|
||||
|
||||
video_res_x = xsize - 16;
|
||||
video_res_y = ysize;
|
||||
if (self->cga.cgamode & 1)
|
||||
{
|
||||
video_res_x /= 8;
|
||||
video_res_y /= self->cga.crtc[9] + 1;
|
||||
video_bpp = 0;
|
||||
}
|
||||
else if (!(self->cga.cgamode & 2))
|
||||
{
|
||||
video_res_x /= 16;
|
||||
video_res_y /= self->cga.crtc[9] + 1;
|
||||
video_bpp = 0;
|
||||
}
|
||||
else if (!(self->cga.cgamode & 16))
|
||||
{
|
||||
video_res_x /= 2;
|
||||
video_bpp = 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
video_bpp = 1;
|
||||
}
|
||||
}
|
||||
self->cga.firstline = 1000;
|
||||
self->cga.lastline = 0;
|
||||
self->cga.cgablink++;
|
||||
self->cga.oddeven ^= 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
self->cga.sc++;
|
||||
self->cga.sc &= 31;
|
||||
self->cga.ma = self->cga.maback;
|
||||
}
|
||||
if (self->cga.cgadispon)
|
||||
self->cga.cgastat &= ~1;
|
||||
if ((self->cga.sc == (self->cga.crtc[10] & 31) || ((self->cga.crtc[8] & 3) == 3 && self->cga.sc == ((self->cga.crtc[10] & 31) >> 1))))
|
||||
self->cga.con = 1;
|
||||
if (self->cga.cgadispon && (self->cga.cgamode & 1))
|
||||
{
|
||||
for (x = 0; x < (self->cga.crtc[1] << 1); x++)
|
||||
self->cga.charbuffer[x] = self->cga.vram[(((self->cga.ma << 1) + x) & 0x3fff)];
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void *compaq_cga_init(const device_t *info)
|
||||
{
|
||||
int display_type;
|
||||
int c;
|
||||
compaq_cga_t *self = malloc(sizeof(compaq_cga_t));
|
||||
memset(self, 0, sizeof(compaq_cga_t));
|
||||
|
||||
display_type = device_get_config_int("display_type");
|
||||
self->cga.composite = (display_type != CGA_RGB);
|
||||
self->cga.revision = device_get_config_int("composite_type");
|
||||
self->cga.snow_enabled = device_get_config_int("snow_enabled");
|
||||
|
||||
self->cga.vram = malloc(0x4000);
|
||||
|
||||
cga_comp_init(self->cga.revision);
|
||||
timer_add(compaq_cga_poll, &self->cga.vidtime, TIMER_ALWAYS_ENABLED, self);
|
||||
mem_mapping_add(&self->cga.mapping, 0xb8000, 0x08000, cga_read, NULL, NULL, cga_write, NULL, NULL, NULL, MEM_MAPPING_EXTERNAL, self);
|
||||
io_sethandler(0x03d0, 0x0010, cga_in, NULL, NULL, cga_out, NULL, NULL, self);
|
||||
|
||||
if (info->local) {
|
||||
for (c = 0; c < 256; c++) {
|
||||
mdaattr[c][0][0] = mdaattr[c][1][0] = mdaattr[c][1][1] = 16;
|
||||
if (c & 8) mdaattr[c][0][1] = 15 + 16;
|
||||
else mdaattr[c][0][1] = 7 + 16;
|
||||
}
|
||||
mdaattr[0x70][0][1] = 16;
|
||||
mdaattr[0x70][0][0] = mdaattr[0x70][1][0] = mdaattr[0x70][1][1] = 16 + 15;
|
||||
mdaattr[0xF0][0][1] = 16;
|
||||
mdaattr[0xF0][0][0] = mdaattr[0xF0][1][0] = mdaattr[0xF0][1][1] = 16 + 15;
|
||||
mdaattr[0x78][0][1] = 16 + 7;
|
||||
mdaattr[0x78][0][0] = mdaattr[0x78][1][0] = mdaattr[0x78][1][1] = 16 + 15;
|
||||
mdaattr[0xF8][0][1] = 16 + 7;
|
||||
mdaattr[0xF8][0][0] = mdaattr[0xF8][1][0] = mdaattr[0xF8][1][1] = 16 + 15;
|
||||
mdaattr[0x00][0][1] = mdaattr[0x00][1][1] = 16;
|
||||
mdaattr[0x08][0][1] = mdaattr[0x08][1][1] = 16;
|
||||
mdaattr[0x80][0][1] = mdaattr[0x80][1][1] = 16;
|
||||
mdaattr[0x88][0][1] = mdaattr[0x88][1][1] = 16;
|
||||
}
|
||||
|
||||
self->flags = info->local;
|
||||
|
||||
overscan_x = overscan_y = 16;
|
||||
|
||||
self->cga.rgb_type = device_get_config_int("rgb_type");
|
||||
cga_palette = (self->cga.rgb_type << 1);
|
||||
cgapal_rebuild();
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
void compaq_cga_close(void *p)
|
||||
{
|
||||
compaq_cga_t *self = (compaq_cga_t *)p;
|
||||
|
||||
free(self->cga.vram);
|
||||
free(self);
|
||||
}
|
||||
|
||||
void compaq_cga_speed_changed(void *p)
|
||||
{
|
||||
compaq_cga_t *self = (compaq_cga_t *)p;
|
||||
|
||||
if (self->cga.crtc[9] == 13) /* Character height */
|
||||
{
|
||||
compaq_cga_recalctimings(self);
|
||||
}
|
||||
else
|
||||
{
|
||||
cga_recalctimings(&self->cga);
|
||||
}
|
||||
}
|
||||
|
||||
extern const device_config_t cga_config[];
|
||||
|
||||
const device_t compaq_cga_device =
|
||||
{
|
||||
"Compaq CGA",
|
||||
DEVICE_ISA, 0,
|
||||
compaq_cga_init,
|
||||
compaq_cga_close,
|
||||
NULL,
|
||||
NULL,
|
||||
compaq_cga_speed_changed,
|
||||
NULL,
|
||||
cga_config
|
||||
};
|
||||
|
||||
const device_t compaq_cga_2_device =
|
||||
{
|
||||
"Compaq CGA 2",
|
||||
DEVICE_ISA, 1,
|
||||
compaq_cga_init,
|
||||
compaq_cga_close,
|
||||
NULL,
|
||||
NULL,
|
||||
compaq_cga_speed_changed,
|
||||
NULL,
|
||||
cga_config
|
||||
};
|
||||
11
backup code/video - Cópia/vid_compaq_cga.h
Normal file
11
backup code/video - Cópia/vid_compaq_cga.h
Normal file
@@ -0,0 +1,11 @@
|
||||
#ifndef VIDEO_COMPAQ_CGA_H
|
||||
# define VIDEO_COMPAQ_CGA_H
|
||||
|
||||
|
||||
#ifdef EMU_DEVICE_H
|
||||
extern const device_t compaq_cga_device;
|
||||
extern const device_t compaq_cga_2_device;
|
||||
#endif
|
||||
|
||||
|
||||
#endif /*VIDEO_COMPAQ_CGA_H*/
|
||||
1293
backup code/video - Cópia/vid_ega.c
Normal file
1293
backup code/video - Cópia/vid_ega.c
Normal file
File diff suppressed because it is too large
Load Diff
149
backup code/video - Cópia/vid_ega.h
Normal file
149
backup code/video - Cópia/vid_ega.h
Normal file
@@ -0,0 +1,149 @@
|
||||
/*
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
*
|
||||
* This file is part of the 86Box distribution.
|
||||
*
|
||||
* Emulation of the EGA, Chips & Technologies SuperEGA, and
|
||||
* AX JEGA graphics cards.
|
||||
*
|
||||
* Version: @(#)vid_ega.h 1.0.7 2018/03/18
|
||||
*
|
||||
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
* akm,
|
||||
*
|
||||
* Copyright 2008-2018 Sarah Walker.
|
||||
* Copyright 2016-2018 Miran Grca.
|
||||
* Copyright 2017,2018 akm.
|
||||
*/
|
||||
#ifndef VIDEO_EGA_H
|
||||
# define VIDEO_EGA_H
|
||||
|
||||
|
||||
#ifdef JEGA
|
||||
# define SBCS 0
|
||||
# define DBCS 1
|
||||
# define ID_LEN 6
|
||||
# define NAME_LEN 8
|
||||
# define SBCS19_LEN 256 * 19
|
||||
# define DBCS16_LEN 65536 * 32
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(EMU_MEM_H) && defined(EMU_ROM_H)
|
||||
typedef struct ega_t {
|
||||
mem_mapping_t mapping;
|
||||
|
||||
rom_t bios_rom;
|
||||
|
||||
uint8_t crtcreg;
|
||||
uint8_t crtc[32];
|
||||
uint8_t gdcreg[16];
|
||||
int gdcaddr;
|
||||
uint8_t attrregs[32];
|
||||
int attraddr, attrff;
|
||||
int attr_palette_enable;
|
||||
uint8_t seqregs[64];
|
||||
int seqaddr;
|
||||
|
||||
uint8_t miscout;
|
||||
int vidclock;
|
||||
|
||||
uint8_t la, lb, lc, ld;
|
||||
|
||||
uint8_t stat;
|
||||
|
||||
int fast;
|
||||
uint8_t colourcompare, colournocare;
|
||||
int readmode, writemode, readplane;
|
||||
int chain4, chain2_read, chain2_write;
|
||||
int oddeven_page, oddeven_chain;
|
||||
int extvram;
|
||||
uint8_t writemask;
|
||||
uint32_t charseta, charsetb;
|
||||
|
||||
uint8_t egapal[16];
|
||||
uint32_t *pallook;
|
||||
|
||||
int vtotal, dispend, vsyncstart, split, vblankstart;
|
||||
int hdisp, htotal, hdisp_time, rowoffset;
|
||||
int lowres, interlace;
|
||||
int linedbl, rowcount;
|
||||
double clock;
|
||||
uint32_t ma_latch;
|
||||
|
||||
int vres;
|
||||
|
||||
int64_t dispontime, dispofftime;
|
||||
int64_t vidtime;
|
||||
|
||||
uint8_t scrblank;
|
||||
|
||||
int dispon;
|
||||
int hdisp_on;
|
||||
|
||||
uint32_t ma, maback, ca;
|
||||
int vc;
|
||||
int sc;
|
||||
int linepos, vslines, linecountff, oddeven;
|
||||
int con, cursoron, blink;
|
||||
int scrollcache;
|
||||
|
||||
int firstline, lastline;
|
||||
int firstline_draw, lastline_draw;
|
||||
int displine;
|
||||
|
||||
uint8_t *vram;
|
||||
int vrammask;
|
||||
|
||||
uint32_t vram_limit;
|
||||
|
||||
int video_res_x, video_res_y, video_bpp;
|
||||
|
||||
#ifdef JEGA
|
||||
uint8_t RMOD1, RMOD2, RDAGS, RDFFB, RDFSB, RDFAP, RPESL, RPULP, RPSSC, RPSSU, RPSSL;
|
||||
uint8_t RPPAJ;
|
||||
uint8_t RCMOD, RCCLH, RCCLL, RCCSL, RCCEL, RCSKW, ROMSL, RSTAT;
|
||||
int is_jega, font_index;
|
||||
int chr_left, chr_wide;
|
||||
#endif
|
||||
} ega_t;
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef EMU_DEVICE_H
|
||||
extern const device_t ega_device;
|
||||
extern const device_t cpqega_device;
|
||||
extern const device_t sega_device;
|
||||
#endif
|
||||
#ifdef JEGA
|
||||
extern uint8_t jfont_sbcs_19[SBCS19_LEN]; /* 256 * 19( * 8) */
|
||||
extern uint8_t jfont_dbcs_16[DBCS16_LEN]; /* 65536 * 16 * 2 (* 8) */
|
||||
#endif
|
||||
|
||||
extern int update_overscan;
|
||||
|
||||
#define DISPLAY_RGB 0
|
||||
#define DISPLAY_COMPOSITE 1
|
||||
#define DISPLAY_RGB_NO_BROWN 2
|
||||
#define DISPLAY_GREEN 3
|
||||
#define DISPLAY_AMBER 4
|
||||
#define DISPLAY_WHITE 5
|
||||
|
||||
|
||||
#if defined(EMU_MEM_H) && defined(EMU_ROM_H)
|
||||
extern void ega_init(ega_t *ega, int monitor_type, int is_mono);
|
||||
extern void ega_recalctimings(struct ega_t *ega);
|
||||
#endif
|
||||
|
||||
extern void ega_out(uint16_t addr, uint8_t val, void *p);
|
||||
extern uint8_t ega_in(uint16_t addr, void *p);
|
||||
extern void ega_poll(void *p);
|
||||
extern void ega_write(uint32_t addr, uint8_t val, void *p);
|
||||
extern uint8_t ega_read(uint32_t addr, void *p);
|
||||
|
||||
|
||||
#endif /*VIDEO_EGA_H*/
|
||||
550
backup code/video - Cópia/vid_ega_render.c
Normal file
550
backup code/video - Cópia/vid_ega_render.c
Normal file
@@ -0,0 +1,550 @@
|
||||
/*
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
*
|
||||
* This file is part of the 86Box distribution.
|
||||
*
|
||||
* EGA renderers.
|
||||
*
|
||||
* Version: @(#)vid_ega_render.c 1.0.5 2018/01/24
|
||||
*
|
||||
* Author: Sarah Walker, <http://pcem-emulator.co.uk/>
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
*
|
||||
* Copyright 2008-2018 Sarah Walker.
|
||||
* Copyright 2016-2018 Miran Grca.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <wchar.h>
|
||||
#include "../86box.h"
|
||||
#include "../device.h"
|
||||
#include "../mem.h"
|
||||
#include "../rom.h"
|
||||
#include "video.h"
|
||||
#include "vid_ega.h"
|
||||
#include "vid_ega_render.h"
|
||||
|
||||
|
||||
int ega_display_line(ega_t *ega)
|
||||
{
|
||||
int y_add = (enable_overscan) ? (overscan_y >> 1) : 0;
|
||||
unsigned int dl = ega->displine;
|
||||
if (ega->crtc[9] & 0x1f)
|
||||
{
|
||||
dl -= (ega->crtc[8] & 0x1f);
|
||||
}
|
||||
dl += y_add;
|
||||
dl &= 0x7ff;
|
||||
return dl;
|
||||
}
|
||||
|
||||
void ega_render_blank(ega_t *ega)
|
||||
{
|
||||
int x_add = (enable_overscan) ? 8 : 0;
|
||||
int dl = ega_display_line(ega);
|
||||
int x, xx;
|
||||
|
||||
for (x = 0; x < ega->hdisp; x++)
|
||||
{
|
||||
switch (ega->seqregs[1] & 9)
|
||||
{
|
||||
case 0:
|
||||
for (xx = 0; xx < 9; xx++) ((uint32_t *)buffer32->line[dl])[(x * 9) + xx + 32 + x_add] = 0;
|
||||
break;
|
||||
case 1:
|
||||
for (xx = 0; xx < 8; xx++) ((uint32_t *)buffer32->line[dl])[(x * 8) + xx + 32 + x_add] = 0;
|
||||
break;
|
||||
case 8:
|
||||
for (xx = 0; xx < 18; xx++) ((uint32_t *)buffer32->line[dl])[(x * 18) + xx + 32 + x_add] = 0;
|
||||
break;
|
||||
case 9:
|
||||
for (xx = 0; xx < 16; xx++) ((uint32_t *)buffer32->line[dl])[(x * 16) + xx + 32 + x_add] = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ega_render_text_standard(ega_t *ega, int drawcursor)
|
||||
{
|
||||
int x, xx;
|
||||
int x_add = (enable_overscan) ? 8 : 0;
|
||||
int dl = ega_display_line(ega);
|
||||
|
||||
for (x = 0; x < ega->hdisp; x++)
|
||||
{
|
||||
int drawcursor = ((ega->ma == ega->ca) && ega->con && ega->cursoron);
|
||||
uint8_t chr = ega->vram[(ega->ma << 1) & ega->vrammask];
|
||||
uint8_t attr = ega->vram[((ega->ma << 1) + 1) & ega->vrammask];
|
||||
uint8_t dat;
|
||||
uint32_t fg, bg;
|
||||
uint32_t charaddr;
|
||||
|
||||
if (attr & 8)
|
||||
charaddr = ega->charsetb + (chr * 128);
|
||||
else
|
||||
charaddr = ega->charseta + (chr * 128);
|
||||
|
||||
if (drawcursor)
|
||||
{
|
||||
bg = ega->pallook[ega->egapal[attr & 15]];
|
||||
fg = ega->pallook[ega->egapal[attr >> 4]];
|
||||
}
|
||||
else
|
||||
{
|
||||
fg = ega->pallook[ega->egapal[attr & 15]];
|
||||
bg = ega->pallook[ega->egapal[attr >> 4]];
|
||||
if (attr & 0x80 && ega->attrregs[0x10] & 8)
|
||||
{
|
||||
bg = ega->pallook[ega->egapal[(attr >> 4) & 7]];
|
||||
if (ega->blink & 16)
|
||||
fg = bg;
|
||||
}
|
||||
}
|
||||
|
||||
dat = ega->vram[charaddr + (ega->sc << 2)];
|
||||
if (ega->seqregs[1] & 8)
|
||||
{
|
||||
if (ega->seqregs[1] & 1)
|
||||
{
|
||||
for (xx = 0; xx < 8; xx++)
|
||||
((uint32_t *)buffer32->line[dl])[((x << 4) + 32 + (xx << 1) + x_add) & 2047] =
|
||||
((uint32_t *)buffer32->line[dl])[((x << 4) + 33 + (xx << 1) + x_add) & 2047] = (dat & (0x80 >> xx)) ? fg : bg;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (xx = 0; xx < 8; xx++)
|
||||
((uint32_t *)buffer32->line[dl])[((x * 18) + 32 + (xx << 1) + x_add) & 2047] =
|
||||
((uint32_t *)buffer32->line[dl])[((x * 18) + 33 + (xx << 1) + x_add) & 2047] = (dat & (0x80 >> xx)) ? fg : bg;
|
||||
if ((chr & ~0x1f) != 0xc0 || !(ega->attrregs[0x10] & 4))
|
||||
((uint32_t *)buffer32->line[dl])[((x * 18) + 32 + 16 + x_add) & 2047] =
|
||||
((uint32_t *)buffer32->line[dl])[((x * 18) + 32 + 17 + x_add) & 2047] = bg;
|
||||
else
|
||||
((uint32_t *)buffer32->line[dl])[((x * 18) + 32 + 16 + x_add) & 2047] =
|
||||
((uint32_t *)buffer32->line[dl])[((x * 18) + 32 + 17 + x_add) & 2047] = (dat & 1) ? fg : bg;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ega->seqregs[1] & 1)
|
||||
{
|
||||
for (xx = 0; xx < 8; xx++)
|
||||
((uint32_t *)buffer32->line[dl])[((x << 3) + 32 + xx + x_add) & 2047] = (dat & (0x80 >> xx)) ? fg : bg;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (xx = 0; xx < 8; xx++)
|
||||
((uint32_t *)buffer32->line[dl])[((x * 9) + 32 + xx + x_add) & 2047] = (dat & (0x80 >> xx)) ? fg : bg;
|
||||
if ((chr & ~0x1f) != 0xc0 || !(ega->attrregs[0x10] & 4))
|
||||
((uint32_t *)buffer32->line[dl])[((x * 9) + 32 + 8 + x_add) & 2047] = bg;
|
||||
else
|
||||
((uint32_t *)buffer32->line[dl])[((x * 9) + 32 + 8 + x_add) & 2047] = (dat & 1) ? fg : bg;
|
||||
}
|
||||
}
|
||||
ega->ma += 4;
|
||||
ega->ma &= ega->vrammask;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef JEGA
|
||||
static __inline int is_kanji1(uint8_t chr)
|
||||
{
|
||||
return (chr >= 0x81 && chr <= 0x9f) || (chr >= 0xe0 && chr <= 0xfc);
|
||||
}
|
||||
|
||||
static __inline int is_kanji2(uint8_t chr)
|
||||
{
|
||||
return (chr >= 0x40 && chr <= 0x7e) || (chr >= 0x80 && chr <= 0xfc);
|
||||
}
|
||||
|
||||
void ega_jega_render_blit_text(ega_t *ega, int x, int dl, int start, int width, uint16_t dat, int cw, uint32_t fg, uint32_t bg)
|
||||
{
|
||||
int x_add = (enable_overscan) ? 8 : 0;
|
||||
|
||||
int xx = 0;
|
||||
int xxx = 0;
|
||||
|
||||
if (ega->seqregs[1] & 8)
|
||||
{
|
||||
for (xx = start; xx < (start + width); xx++)
|
||||
for (xxx = 0; xxx < cw; xxx++)
|
||||
((uint32_t *)buffer32->line[dl])[(((x * width) + 32 + (xxx << 1) + ((xx << 1) * cw)) & 2047) + x_add] =
|
||||
((uint32_t *)buffer32->line[dl])[(((x * width) + 33 + (xxx << 1) + ((xx << 1) * cw)) & 2047) + x_add] = (dat & (0x80 >> xx)) ? fg : bg;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (xx = start; xx < (start + width); xx++)
|
||||
((uint32_t *)buffer32->line[dl])[(((x * width) + 32 + xxx + (xx * cw)) & 2047) + x_add] = (dat & (0x80 >> xx)) ? fg : bg;
|
||||
}
|
||||
}
|
||||
|
||||
void ega_render_text_jega(ega_t *ega, int drawcursor)
|
||||
{
|
||||
int dl = ega_display_line(ega);
|
||||
uint8_t chr, attr;
|
||||
uint16_t dat = 0, dat2;
|
||||
int x;
|
||||
uint32_t fg = 0, bg = 0;
|
||||
|
||||
/* Temporary for DBCS. */
|
||||
unsigned int chr_left = 0;
|
||||
unsigned int bsattr = 0;
|
||||
int chr_wide = 0;
|
||||
uint32_t bg_ex = 0;
|
||||
uint32_t fg_ex = 0;
|
||||
|
||||
int blocks = ega->hdisp;
|
||||
int fline;
|
||||
|
||||
unsigned int pad_y, exattr;
|
||||
|
||||
if (fullchange)
|
||||
{
|
||||
for (x = 0; x < ega->hdisp; x++)
|
||||
{
|
||||
drawcursor = ((ega->ma == ega->ca) && ega->con && ega->cursoron);
|
||||
chr = ega->vram[(ega->ma << 1) & ega->vrammask];
|
||||
attr = ega->vram[((ega->ma << 1) + 1) & ega->vrammask];
|
||||
|
||||
if (chr_wide == 0)
|
||||
{
|
||||
if (ega->RMOD2 & 0x80)
|
||||
{
|
||||
fg_ex = ega->pallook[ega->egapal[attr & 15]];
|
||||
|
||||
if (attr & 0x80 && ega->attrregs[0x10] & 8)
|
||||
{
|
||||
bg_ex = ega->pallook[ega->egapal[(attr >> 4) & 7]];
|
||||
}
|
||||
else
|
||||
{
|
||||
bg_ex = ega->pallook[ega->egapal[attr >> 4]];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (attr & 0x40)
|
||||
{
|
||||
/* Reversed in JEGA mode */
|
||||
bg_ex = ega->pallook[ega->egapal[attr & 15]];
|
||||
fg_ex = ega->pallook[0];
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Reversed in JEGA mode */
|
||||
fg_ex = ega->pallook[ega->egapal[attr & 15]];
|
||||
bg_ex = ega->pallook[0];
|
||||
}
|
||||
}
|
||||
|
||||
if (drawcursor)
|
||||
{
|
||||
bg = fg_ex;
|
||||
fg = bg_ex;
|
||||
}
|
||||
else
|
||||
{
|
||||
fg = fg_ex;
|
||||
bg = bg_ex;
|
||||
}
|
||||
|
||||
if (attr & 0x80 && ega->attrregs[0x10] & 8)
|
||||
{
|
||||
if (ega->blink & 16)
|
||||
fg = bg;
|
||||
}
|
||||
|
||||
/* Stay drawing if the char code is DBCS and not at last column. */
|
||||
if (is_kanji1(dat) && (blocks > 1))
|
||||
{
|
||||
/* Set the present char/attr code to the next loop. */
|
||||
chr_left = chr;
|
||||
chr_wide = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* The char code is ANK (8 dots width). */
|
||||
dat = jfont_sbcs_19[chr*19+(ega->sc)]; /* w8xh19 font */
|
||||
ega_jega_render_blit_text(ega, x, dl, 0, 8, dat, 1, fg, bg);
|
||||
if (bsattr & 0x20)
|
||||
{
|
||||
/* Vertical line. */
|
||||
dat = 0x18;
|
||||
ega_jega_render_blit_text(ega, x, fline, 0, 8, dat, 1, fg, bg);
|
||||
}
|
||||
if (ega->sc == 18 && bsattr & 0x10)
|
||||
{
|
||||
/* Underline. */
|
||||
dat = 0xff;
|
||||
ega_jega_render_blit_text(ega, x, fline, 0, 8, dat, 1, fg, bg);
|
||||
}
|
||||
chr_wide = 0;
|
||||
blocks--;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* The char code may be in DBCS. */
|
||||
pad_y = ega->RPSSC;
|
||||
exattr = 0;
|
||||
|
||||
/* Note: The second column should be applied its basic attribute. */
|
||||
if (ega->RMOD2 & 0x40)
|
||||
{
|
||||
/* If JEGA Extended Attribute is enabled. */
|
||||
exattr = attr;
|
||||
if ((exattr & 0x30) == 0x30) pad_y = ega->RPSSL; /* Set top padding of lower 2x character. */
|
||||
else if (exattr & 0x30) pad_y = ega->RPSSU; /* Set top padding of upper 2x character. */
|
||||
}
|
||||
|
||||
if (ega->sc >= pad_y && ega->sc < 16 + pad_y)
|
||||
{
|
||||
/* Check the char code is in Wide charset of Shift-JIS. */
|
||||
if (is_kanji2(chr))
|
||||
{
|
||||
fline = ega->sc - pad_y;
|
||||
chr_left <<= 8;
|
||||
/* Fix vertical position. */
|
||||
chr |= chr_left;
|
||||
/* Horizontal wide font (Extended Attribute). */
|
||||
if (exattr & 0x20)
|
||||
{
|
||||
if (exattr & 0x10) fline = (fline >> 1) + 8;
|
||||
else fline = fline >> 1;
|
||||
}
|
||||
/* Vertical wide font (Extended Attribute). */
|
||||
if (exattr & 0x40)
|
||||
{
|
||||
dat = jfont_dbcs_16[chr * 32 + fline * 2];
|
||||
if (!(exattr & 0x08))
|
||||
dat = jfont_dbcs_16[chr * 32 + fline * 2 + 1];
|
||||
/* Draw 8 dots. */
|
||||
ega_jega_render_blit_text(ega, x, dl, 0, 8, dat, 2, fg, bg);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Get the font pattern. */
|
||||
dat = jfont_dbcs_16[chr * 32 + fline * 2];
|
||||
dat <<= 8;
|
||||
dat |= jfont_dbcs_16[chr * 32 + fline * 2 + 1];
|
||||
/* Bold (Extended Attribute). */
|
||||
if (exattr &= 0x80)
|
||||
{
|
||||
dat2 = dat;
|
||||
dat2 >>= 1;
|
||||
dat |= dat2;
|
||||
/* Original JEGA colours the last row with the next column's attribute. */
|
||||
}
|
||||
/* Draw 16 dots */
|
||||
ega_jega_render_blit_text(ega, x, dl, 0, 16, dat, 1, fg, bg);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Ignore wide char mode, put blank. */
|
||||
dat = 0;
|
||||
ega_jega_render_blit_text(ega, x, dl, 0, 16, dat, 1, fg, bg);
|
||||
}
|
||||
}
|
||||
else if (ega->sc == (17 + pad_y) && (bsattr & 0x10))
|
||||
{
|
||||
/* Underline. */
|
||||
dat = 0xffff;
|
||||
ega_jega_render_blit_text(ega, x, dl, 0, 16, dat, 1, fg, bg);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Draw blank */
|
||||
dat = 0;
|
||||
ega_jega_render_blit_text(ega, x, dl, 0, 16, dat, 1, fg, bg);
|
||||
}
|
||||
|
||||
if (bsattr & 0x20)
|
||||
{
|
||||
/* Vertical line draw at last. */
|
||||
dat = 0x0180;
|
||||
ega_jega_render_blit_text(ega, x, dl, 0, 16, dat, 1, fg, bg);
|
||||
}
|
||||
|
||||
chr_wide = 0;
|
||||
blocks -= 2; /* Move by 2 columns. */
|
||||
}
|
||||
|
||||
ega->ma += 4;
|
||||
ega->ma &= ega->vrammask;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void ega_render_2bpp(ega_t *ega)
|
||||
{
|
||||
int x;
|
||||
int dl = ega_display_line(ega);
|
||||
int offset = ((8 - ega->scrollcache) << 1) + 16;
|
||||
|
||||
for (x = 0; x <= ega->hdisp; x++)
|
||||
{
|
||||
uint8_t edat[2];
|
||||
uint32_t addr = ega->ma;
|
||||
|
||||
if (!(ega->crtc[0x17] & 0x40))
|
||||
{
|
||||
addr = (addr << 1) & ega->vrammask;
|
||||
addr &= ~7;
|
||||
if ((ega->crtc[0x17] & 0x20) && (ega->ma & 0x20000))
|
||||
addr |= 4;
|
||||
if (!(ega->crtc[0x17] & 0x20) && (ega->ma & 0x8000))
|
||||
addr |= 4;
|
||||
}
|
||||
if (!(ega->crtc[0x17] & 0x01))
|
||||
addr = (addr & ~0x8000) | ((ega->sc & 1) ? 0x8000 : 0);
|
||||
if (!(ega->crtc[0x17] & 0x02))
|
||||
addr = (addr & ~0x10000) | ((ega->sc & 2) ? 0x10000 : 0);
|
||||
|
||||
edat[0] = ega->vram[addr];
|
||||
edat[1] = ega->vram[addr | 0x1];
|
||||
if (ega->seqregs[1] & 4)
|
||||
ega->ma += 2;
|
||||
else
|
||||
ega->ma += 4;
|
||||
|
||||
ega->ma &= ega->vrammask;
|
||||
|
||||
((uint32_t *)buffer32->line[dl])[(x << 4) + 14 + offset] = ((uint32_t *)buffer32->line[ega->displine])[(x << 4) + 15 + offset] = ega->pallook[ega->egapal[edat[1] & 3]];
|
||||
((uint32_t *)buffer32->line[dl])[(x << 4) + 12 + offset] = ((uint32_t *)buffer32->line[ega->displine])[(x << 4) + 13 + offset] = ega->pallook[ega->egapal[(edat[1] >> 2) & 3]];
|
||||
((uint32_t *)buffer32->line[dl])[(x << 4) + 10 + offset] = ((uint32_t *)buffer32->line[ega->displine])[(x << 4) + 11 + offset] = ega->pallook[ega->egapal[(edat[1] >> 4) & 3]];
|
||||
((uint32_t *)buffer32->line[dl])[(x << 4) + 8 + offset] = ((uint32_t *)buffer32->line[ega->displine])[(x << 4) + 9 + offset] = ega->pallook[ega->egapal[(edat[1] >> 6) & 3]];
|
||||
((uint32_t *)buffer32->line[dl])[(x << 4) + 6 + offset] = ((uint32_t *)buffer32->line[ega->displine])[(x << 4) + 7 + offset] = ega->pallook[ega->egapal[(edat[0] >> 0) & 3]];
|
||||
((uint32_t *)buffer32->line[dl])[(x << 4) + 4 + offset] = ((uint32_t *)buffer32->line[ega->displine])[(x << 4) + 5 + offset] = ega->pallook[ega->egapal[(edat[0] >> 2) & 3]];
|
||||
((uint32_t *)buffer32->line[dl])[(x << 4) + 2 + offset] = ((uint32_t *)buffer32->line[ega->displine])[(x << 4) + 3 + offset] = ega->pallook[ega->egapal[(edat[0] >> 4) & 3]];
|
||||
((uint32_t *)buffer32->line[dl])[(x << 4) + offset] = ((uint32_t *)buffer32->line[ega->displine])[(x << 4) + 1 + offset] = ega->pallook[ega->egapal[(edat[0] >> 6) & 3]];
|
||||
}
|
||||
}
|
||||
|
||||
void ega_render_4bpp_lowres(ega_t *ega)
|
||||
{
|
||||
int x_add = (enable_overscan) ? 8 : 0;
|
||||
int dl = ega_display_line(ega);
|
||||
int x;
|
||||
int offset = ((8 - ega->scrollcache) << 1) + 16;
|
||||
|
||||
for (x = 0; x <= ega->hdisp; x++)
|
||||
{
|
||||
uint8_t edat[4];
|
||||
uint8_t dat;
|
||||
uint32_t addr = ega->ma;
|
||||
int oddeven = 0;
|
||||
|
||||
if (!(ega->crtc[0x17] & 0x40))
|
||||
{
|
||||
addr = (addr << 1) & ega->vrammask;
|
||||
if (ega->seqregs[1] & 4)
|
||||
oddeven = (addr & 4) ? 1 : 0;
|
||||
addr &= ~7;
|
||||
if ((ega->crtc[0x17] & 0x20) && (ega->ma & 0x20000))
|
||||
addr |= 4;
|
||||
if (!(ega->crtc[0x17] & 0x20) && (ega->ma & 0x8000))
|
||||
addr |= 4;
|
||||
}
|
||||
if (!(ega->crtc[0x17] & 0x01))
|
||||
addr = (addr & ~0x8000) | ((ega->sc & 1) ? 0x8000 : 0);
|
||||
if (!(ega->crtc[0x17] & 0x02))
|
||||
addr = (addr & ~0x10000) | ((ega->sc & 2) ? 0x10000 : 0);
|
||||
|
||||
if (ega->seqregs[1] & 4)
|
||||
{
|
||||
edat[0] = ega->vram[addr | oddeven];
|
||||
edat[2] = ega->vram[addr | oddeven | 0x2];
|
||||
edat[1] = edat[3] = 0;
|
||||
ega->ma += 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
edat[0] = ega->vram[addr];
|
||||
edat[1] = ega->vram[addr | 0x1];
|
||||
edat[2] = ega->vram[addr | 0x2];
|
||||
edat[3] = ega->vram[addr | 0x3];
|
||||
ega->ma += 4;
|
||||
}
|
||||
ega->ma &= ega->vrammask;
|
||||
|
||||
dat = edatlookup[edat[0] & 3][edat[1] & 3] | (edatlookup[edat[2] & 3][edat[3] & 3] << 2);
|
||||
((uint32_t *)buffer32->line[dl])[(x << 4) + 14 + offset + x_add] = ((uint32_t *)buffer32->line[dl])[(x << 4) + 15 + offset + x_add] = ega->pallook[ega->egapal[(dat & 0xf) & ega->attrregs[0x12]]];
|
||||
((uint32_t *)buffer32->line[dl])[(x << 4) + 12 + offset + x_add] = ((uint32_t *)buffer32->line[dl])[(x << 4) + 13 + offset + x_add] = ega->pallook[ega->egapal[(dat >> 4) & ega->attrregs[0x12]]];
|
||||
dat = edatlookup[(edat[0] >> 2) & 3][(edat[1] >> 2) & 3] | (edatlookup[(edat[2] >> 2) & 3][(edat[3] >> 2) & 3] << 2);
|
||||
((uint32_t *)buffer32->line[dl])[(x << 4) + 10 + offset + x_add] = ((uint32_t *)buffer32->line[dl])[(x << 4) + 11 + offset + x_add] = ega->pallook[ega->egapal[(dat & 0xf) & ega->attrregs[0x12]]];
|
||||
((uint32_t *)buffer32->line[dl])[(x << 4) + 8 + offset + x_add] = ((uint32_t *)buffer32->line[dl])[(x << 4) + 9 + offset + x_add] = ega->pallook[ega->egapal[(dat >> 4) & ega->attrregs[0x12]]];
|
||||
dat = edatlookup[(edat[0] >> 4) & 3][(edat[1] >> 4) & 3] | (edatlookup[(edat[2] >> 4) & 3][(edat[3] >> 4) & 3] << 2);
|
||||
((uint32_t *)buffer32->line[dl])[(x << 4) + 6 + offset + x_add] = ((uint32_t *)buffer32->line[dl])[(x << 4) + 7 + offset + x_add] = ega->pallook[ega->egapal[(dat & 0xf) & ega->attrregs[0x12]]];
|
||||
((uint32_t *)buffer32->line[dl])[(x << 4) + 4 + offset + x_add] = ((uint32_t *)buffer32->line[dl])[(x << 4) + 5 + offset + x_add] = ega->pallook[ega->egapal[(dat >> 4) & ega->attrregs[0x12]]];
|
||||
dat = edatlookup[edat[0] >> 6][edat[1] >> 6] | (edatlookup[edat[2] >> 6][edat[3] >> 6] << 2);
|
||||
((uint32_t *)buffer32->line[dl])[(x << 4) + 2 + offset + x_add] = ((uint32_t *)buffer32->line[dl])[(x << 4) + 3 + offset + x_add] = ega->pallook[ega->egapal[(dat & 0xf) & ega->attrregs[0x12]]];
|
||||
((uint32_t *)buffer32->line[dl])[(x << 4) + offset + x_add] = ((uint32_t *)buffer32->line[dl])[(x << 4) + 1 + offset + x_add] = ega->pallook[ega->egapal[(dat >> 4) & ega->attrregs[0x12]]];
|
||||
}
|
||||
}
|
||||
|
||||
void ega_render_4bpp_highres(ega_t *ega)
|
||||
{
|
||||
int x_add = (enable_overscan) ? 8 : 0;
|
||||
int dl = ega_display_line(ega);
|
||||
int x;
|
||||
int offset = (8 - ega->scrollcache) + 24;
|
||||
|
||||
for (x = 0; x <= ega->hdisp; x++)
|
||||
{
|
||||
uint8_t edat[4];
|
||||
uint8_t dat;
|
||||
uint32_t addr = ega->ma;
|
||||
int oddeven = 0;
|
||||
|
||||
if (!(ega->crtc[0x17] & 0x40))
|
||||
{
|
||||
addr = (addr << 1) & ega->vrammask;
|
||||
if (ega->seqregs[1] & 4)
|
||||
oddeven = (addr & 4) ? 1 : 0;
|
||||
addr &= ~7;
|
||||
if ((ega->crtc[0x17] & 0x20) && (ega->ma & 0x20000))
|
||||
addr |= 4;
|
||||
if (!(ega->crtc[0x17] & 0x20) && (ega->ma & 0x8000))
|
||||
addr |= 4;
|
||||
}
|
||||
if (!(ega->crtc[0x17] & 0x01))
|
||||
addr = (addr & ~0x8000) | ((ega->sc & 1) ? 0x8000 : 0);
|
||||
if (!(ega->crtc[0x17] & 0x02))
|
||||
addr = (addr & ~0x10000) | ((ega->sc & 2) ? 0x10000 : 0);
|
||||
|
||||
if (ega->seqregs[1] & 4)
|
||||
{
|
||||
edat[0] = ega->vram[addr | oddeven];
|
||||
edat[2] = ega->vram[addr | oddeven | 0x2];
|
||||
edat[1] = edat[3] = 0;
|
||||
ega->ma += 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
edat[0] = ega->vram[addr];
|
||||
edat[1] = ega->vram[addr | 0x1];
|
||||
edat[2] = ega->vram[addr | 0x2];
|
||||
edat[3] = ega->vram[addr | 0x3];
|
||||
ega->ma += 4;
|
||||
}
|
||||
ega->ma &= ega->vrammask;
|
||||
|
||||
dat = edatlookup[edat[0] & 3][edat[1] & 3] | (edatlookup[edat[2] & 3][edat[3] & 3] << 2);
|
||||
((uint32_t *)buffer32->line[dl])[(x << 3) + 7 + offset + x_add] = ega->pallook[ega->egapal[(dat & 0xf) & ega->attrregs[0x12]]];
|
||||
((uint32_t *)buffer32->line[dl])[(x << 3) + 6 + offset + x_add] = ega->pallook[ega->egapal[(dat >> 4) & ega->attrregs[0x12]]];
|
||||
dat = edatlookup[(edat[0] >> 2) & 3][(edat[1] >> 2) & 3] | (edatlookup[(edat[2] >> 2) & 3][(edat[3] >> 2) & 3] << 2);
|
||||
((uint32_t *)buffer32->line[dl])[(x << 3) + 5 + offset + x_add] = ega->pallook[ega->egapal[(dat & 0xf) & ega->attrregs[0x12]]];
|
||||
((uint32_t *)buffer32->line[dl])[(x << 3) + 4 + offset + x_add] = ega->pallook[ega->egapal[(dat >> 4) & ega->attrregs[0x12]]];
|
||||
dat = edatlookup[(edat[0] >> 4) & 3][(edat[1] >> 4) & 3] | (edatlookup[(edat[2] >> 4) & 3][(edat[3] >> 4) & 3] << 2);
|
||||
((uint32_t *)buffer32->line[dl])[(x << 3) + 3 + offset + x_add] = ega->pallook[ega->egapal[(dat & 0xf) & ega->attrregs[0x12]]];
|
||||
((uint32_t *)buffer32->line[dl])[(x << 3) + 2 + offset + x_add] = ega->pallook[ega->egapal[(dat >> 4) & ega->attrregs[0x12]]];
|
||||
dat = edatlookup[edat[0] >> 6][edat[1] >> 6] | (edatlookup[edat[2] >> 6][edat[3] >> 6] << 2);
|
||||
((uint32_t *)buffer32->line[dl])[(x << 3) + 1 + offset + x_add] = ega->pallook[ega->egapal[(dat & 0xf) & ega->attrregs[0x12]]];
|
||||
((uint32_t *)buffer32->line[dl])[(x << 3) + offset + x_add] = ega->pallook[ega->egapal[(dat >> 4) & ega->attrregs[0x12]]];
|
||||
}
|
||||
}
|
||||
39
backup code/video - Cópia/vid_ega_render.h
Normal file
39
backup code/video - Cópia/vid_ega_render.h
Normal file
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
*
|
||||
* This file is part of the 86Box distribution.
|
||||
*
|
||||
* EGA renderers.
|
||||
*
|
||||
* Version: @(#)vid_ega_render.h 1.0.2 2018/01/24
|
||||
*
|
||||
* Author: Sarah Walker, <http://pcem-emulator.co.uk/>
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
* Copyright 2008-2018 Sarah Walker.
|
||||
* Copyright 2016-2018 Miran Grca.
|
||||
*/
|
||||
|
||||
extern int firstline_draw, lastline_draw;
|
||||
extern int displine;
|
||||
extern int sc;
|
||||
|
||||
extern uint32_t ma, ca;
|
||||
extern int con, cursoron, cgablink;
|
||||
|
||||
extern int scrollcache;
|
||||
|
||||
extern uint8_t edatlookup[4][4];
|
||||
|
||||
void ega_render_blank(ega_t *ega);
|
||||
void ega_render_text_standard(ega_t *ega, int drawcursor);
|
||||
#ifdef JEGA
|
||||
void ega_render_text_jega(ega_t *ega, int drawcursor);
|
||||
#endif
|
||||
|
||||
void ega_render_2bpp(ega_t *ega);
|
||||
|
||||
void ega_render_4bpp_lowres(ega_t *ega);
|
||||
void ega_render_4bpp_highres(ega_t *ega);
|
||||
218
backup code/video - Cópia/vid_et4000.c
Normal file
218
backup code/video - Cópia/vid_et4000.c
Normal file
@@ -0,0 +1,218 @@
|
||||
/*
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
*
|
||||
* This file is part of the 86Box distribution.
|
||||
*
|
||||
* Emulation of the Tseng Labs ET4000.
|
||||
*
|
||||
* Version: @(#)vid_et4000.c 1.0.6 2018/04/26
|
||||
*
|
||||
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
*
|
||||
* Copyright 2008-2018 Sarah Walker.
|
||||
* Copyright 2016-2018 Miran Grca.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <wchar.h>
|
||||
#include "../86box.h"
|
||||
#include "../io.h"
|
||||
#include "../mem.h"
|
||||
#include "../rom.h"
|
||||
#include "../device.h"
|
||||
#include "video.h"
|
||||
#include "vid_svga.h"
|
||||
#include "vid_sc1502x_ramdac.h"
|
||||
#include "vid_et4000.h"
|
||||
|
||||
|
||||
#define BIOS_ROM_PATH L"roms/video/et4000/et4000.bin"
|
||||
|
||||
|
||||
typedef struct et4000_t
|
||||
{
|
||||
svga_t svga;
|
||||
sc1502x_ramdac_t ramdac;
|
||||
|
||||
rom_t bios_rom;
|
||||
|
||||
uint8_t banking;
|
||||
} et4000_t;
|
||||
|
||||
static uint8_t crtc_mask[0x40] =
|
||||
{
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0xff,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
};
|
||||
|
||||
void et4000_out(uint16_t addr, uint8_t val, void *p)
|
||||
{
|
||||
et4000_t *et4000 = (et4000_t *)p;
|
||||
svga_t *svga = &et4000->svga;
|
||||
|
||||
uint8_t old;
|
||||
|
||||
if (((addr&0xFFF0) == 0x3D0 || (addr&0xFFF0) == 0x3B0) && !(svga->miscout & 1))
|
||||
addr ^= 0x60;
|
||||
|
||||
switch (addr)
|
||||
{
|
||||
case 0x3C6: case 0x3C7: case 0x3C8: case 0x3C9:
|
||||
sc1502x_ramdac_out(addr, val, &et4000->ramdac, svga);
|
||||
return;
|
||||
|
||||
case 0x3CD: /*Banking*/
|
||||
svga->write_bank = (val & 0xf) * 0x10000;
|
||||
svga->read_bank = ((val >> 4) & 0xf) * 0x10000;
|
||||
et4000->banking = val;
|
||||
return;
|
||||
case 0x3D4:
|
||||
svga->crtcreg = val & 0x3f;
|
||||
return;
|
||||
case 0x3D5:
|
||||
if ((svga->crtcreg < 7) && (svga->crtc[0x11] & 0x80))
|
||||
return;
|
||||
if ((svga->crtcreg == 7) && (svga->crtc[0x11] & 0x80))
|
||||
val = (svga->crtc[7] & ~0x10) | (val & 0x10);
|
||||
old = svga->crtc[svga->crtcreg];
|
||||
val &= crtc_mask[svga->crtcreg];
|
||||
svga->crtc[svga->crtcreg] = val;
|
||||
if (old != val)
|
||||
{
|
||||
if (svga->crtcreg < 0xE || svga->crtcreg > 0x10)
|
||||
{
|
||||
svga->fullchange = changeframecount;
|
||||
svga_recalctimings(svga);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
svga_out(addr, val, svga);
|
||||
}
|
||||
|
||||
uint8_t et4000_in(uint16_t addr, void *p)
|
||||
{
|
||||
et4000_t *et4000 = (et4000_t *)p;
|
||||
svga_t *svga = &et4000->svga;
|
||||
|
||||
if (((addr&0xFFF0) == 0x3D0 || (addr&0xFFF0) == 0x3B0) && !(svga->miscout & 1))
|
||||
addr ^= 0x60;
|
||||
|
||||
switch (addr)
|
||||
{
|
||||
case 0x3C5:
|
||||
if ((svga->seqaddr & 0xf) == 7) return svga->seqregs[svga->seqaddr & 0xf] | 4;
|
||||
break;
|
||||
|
||||
case 0x3C6: case 0x3C7: case 0x3C8: case 0x3C9:
|
||||
return sc1502x_ramdac_in(addr, &et4000->ramdac, svga);
|
||||
|
||||
case 0x3CD: /*Banking*/
|
||||
return et4000->banking;
|
||||
case 0x3D4:
|
||||
return svga->crtcreg;
|
||||
case 0x3D5:
|
||||
return svga->crtc[svga->crtcreg];
|
||||
}
|
||||
return svga_in(addr, svga);
|
||||
}
|
||||
|
||||
void et4000_recalctimings(svga_t *svga)
|
||||
{
|
||||
svga->ma_latch |= (svga->crtc[0x33]&3)<<16;
|
||||
if (svga->crtc[0x35] & 1) svga->vblankstart += 0x400;
|
||||
if (svga->crtc[0x35] & 2) svga->vtotal += 0x400;
|
||||
if (svga->crtc[0x35] & 4) svga->dispend += 0x400;
|
||||
if (svga->crtc[0x35] & 8) svga->vsyncstart += 0x400;
|
||||
if (svga->crtc[0x35] & 0x10) svga->split += 0x400;
|
||||
if (!svga->rowoffset) svga->rowoffset = 0x100;
|
||||
if (svga->crtc[0x3f] & 1) svga->htotal += 256;
|
||||
if (svga->attrregs[0x16] & 0x20) svga->hdisp <<= 1;
|
||||
|
||||
switch (((svga->miscout >> 2) & 3) | ((svga->crtc[0x34] << 1) & 4))
|
||||
{
|
||||
case 0: case 1: break;
|
||||
case 3: svga->clock = cpuclock / 40000000.0; break;
|
||||
case 5: svga->clock = cpuclock / 65000000.0; break;
|
||||
default: svga->clock = cpuclock / 36000000.0; break;
|
||||
}
|
||||
|
||||
switch (svga->bpp)
|
||||
{
|
||||
case 15: case 16:
|
||||
svga->hdisp /= 2;
|
||||
break;
|
||||
case 24:
|
||||
svga->hdisp /= 3;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void *et4000_init(const device_t *info)
|
||||
{
|
||||
et4000_t *et4000 = malloc(sizeof(et4000_t));
|
||||
memset(et4000, 0, sizeof(et4000_t));
|
||||
|
||||
rom_init(&et4000->bios_rom, BIOS_ROM_PATH, 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL);
|
||||
|
||||
io_sethandler(0x03c0, 0x0020, et4000_in, NULL, NULL, et4000_out, NULL, NULL, et4000);
|
||||
|
||||
svga_init(&et4000->svga, et4000, 1 << 20, /*1mb*/
|
||||
et4000_recalctimings,
|
||||
et4000_in, et4000_out,
|
||||
NULL,
|
||||
NULL);
|
||||
|
||||
return et4000;
|
||||
}
|
||||
|
||||
static int et4000_available(void)
|
||||
{
|
||||
return rom_present(BIOS_ROM_PATH);
|
||||
}
|
||||
|
||||
void et4000_close(void *p)
|
||||
{
|
||||
et4000_t *et4000 = (et4000_t *)p;
|
||||
|
||||
svga_close(&et4000->svga);
|
||||
|
||||
free(et4000);
|
||||
}
|
||||
|
||||
void et4000_speed_changed(void *p)
|
||||
{
|
||||
et4000_t *et4000 = (et4000_t *)p;
|
||||
|
||||
svga_recalctimings(&et4000->svga);
|
||||
}
|
||||
|
||||
void et4000_force_redraw(void *p)
|
||||
{
|
||||
et4000_t *et4000 = (et4000_t *)p;
|
||||
|
||||
et4000->svga.fullchange = changeframecount;
|
||||
}
|
||||
|
||||
const device_t et4000_device =
|
||||
{
|
||||
"Tseng Labs ET4000AX",
|
||||
DEVICE_ISA, 0,
|
||||
et4000_init, et4000_close, NULL,
|
||||
et4000_available,
|
||||
et4000_speed_changed,
|
||||
et4000_force_redraw,
|
||||
NULL
|
||||
};
|
||||
4
backup code/video - Cópia/vid_et4000.h
Normal file
4
backup code/video - Cópia/vid_et4000.h
Normal file
@@ -0,0 +1,4 @@
|
||||
/* Copyright holders: Sarah Walker
|
||||
see COPYING for more details
|
||||
*/
|
||||
extern const device_t et4000_device;
|
||||
1392
backup code/video - Cópia/vid_et4000w32.c
Normal file
1392
backup code/video - Cópia/vid_et4000w32.c
Normal file
File diff suppressed because it is too large
Load Diff
7
backup code/video - Cópia/vid_et4000w32.h
Normal file
7
backup code/video - Cópia/vid_et4000w32.h
Normal file
@@ -0,0 +1,7 @@
|
||||
#if defined(DEV_BRANCH) && defined(USE_STEALTH32)
|
||||
extern const device_t et4000w32p_vlb_device;
|
||||
extern const device_t et4000w32p_pci_device;
|
||||
#endif
|
||||
|
||||
extern const device_t et4000w32p_cardex_vlb_device;
|
||||
extern const device_t et4000w32p_cardex_pci_device;
|
||||
427
backup code/video - Cópia/vid_et4000w32i.c
Normal file
427
backup code/video - Cópia/vid_et4000w32i.c
Normal file
@@ -0,0 +1,427 @@
|
||||
/*
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
*
|
||||
* This file is part of the 86Box distribution.
|
||||
*
|
||||
* The below is (with some removals) a reasonable emulation
|
||||
* of the ET4000/W32i blitter. Unfortunately the Diamond
|
||||
* Stealth 32 is actually an ET4000/W32p! Which has a different
|
||||
* blitter. If only I'd dug out and looked at the card before
|
||||
* trying to emulate it.
|
||||
*
|
||||
* This might be of use for an attempt at an ET4000/W32i.
|
||||
*
|
||||
* Version: @(#)vid_et4000w32i.c 1.0.2 2017/11/04
|
||||
*
|
||||
* Author: Sarah Walker, <http://pcem-emulator.co.uk/>
|
||||
*
|
||||
* Copyright 2008-2017 Sarah Walker.
|
||||
*/
|
||||
#if 0
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <wchar.h>
|
||||
#include "../86box.h"
|
||||
|
||||
int et4k_b8000;
|
||||
|
||||
struct
|
||||
{
|
||||
struct
|
||||
{
|
||||
uint32_t pattern_addr,source_addr,dest_addr;
|
||||
uint16_t pattern_off,source_off,dest_off;
|
||||
uint8_t vbus,xy_dir;
|
||||
uint8_t pattern_wrap,source_wrap;
|
||||
uint16_t count_x,count_y;
|
||||
uint8_t ctrl_routing,ctrl_reload;
|
||||
uint8_t rop_fg,rop_bg;
|
||||
uint16_t pos_x,pos_y;
|
||||
} queued,internal;
|
||||
uint32_t pattern_addr,source_addr,dest_addr;
|
||||
uint32_t pattern_back,dest_back;
|
||||
int pattern_x,source_x;
|
||||
int pattern_x_back;
|
||||
int pattern_y,source_y;
|
||||
uint8_t status;
|
||||
uint32_t cpu_input;
|
||||
int cpu_input_num;
|
||||
} acl;
|
||||
|
||||
#define ACL_WRST 1
|
||||
#define ACL_RDST 2
|
||||
#define ACL_XYST 4
|
||||
#define ACL_SSO 8
|
||||
|
||||
struct
|
||||
{
|
||||
uint32_t base[3];
|
||||
uint8_t ctrl;
|
||||
} mmu;
|
||||
|
||||
void et4000w32_reset()
|
||||
{
|
||||
acl.status=0;
|
||||
acl.cpu_input_num=0;
|
||||
}
|
||||
|
||||
void et4000w32_blit_start();
|
||||
void et4000w32_blit(int count, uint32_t mix, uint32_t sdat, int cpu_input);
|
||||
|
||||
int et4000w32_vbus[4]={1,2,4,4};
|
||||
|
||||
void et4000w32_mmu_write(uint32_t addr, uint8_t val)
|
||||
{
|
||||
int bank;
|
||||
pclog("ET4K write %08X %02X %i %02X %02X %04X(%08X):%08X %04X %04X %02X %08X\n",addr,val,acl.cpu_input_num,acl.status,acl.internal.ctrl_routing,CS,cs,pc,CS,DI,mmu.ctrl,mmu.base[2]);
|
||||
switch (addr&0x6000)
|
||||
{
|
||||
case 0x0000: /*MMU 0*/
|
||||
case 0x2000: /*MMU 1*/
|
||||
case 0x4000: /*MMU 2*/
|
||||
bank=(addr>>13)&3;
|
||||
if (mmu.ctrl&(1<<bank))
|
||||
{
|
||||
if (!(acl.status&ACL_XYST))
|
||||
{
|
||||
// pclog("!ACL_XYST\n");
|
||||
/*if ((acl.internal.ctrl_routing&0x30)==0x10) */acl.queued.dest_addr=(addr&0x1FFF)+mmu.base[bank];
|
||||
acl.internal=acl.queued;
|
||||
et4000w32_blit_start();
|
||||
if (!(acl.internal.ctrl_routing&0x37)) et4000w32_blit(0xFFFFFF, ~0, 0, 0);
|
||||
acl.cpu_input_num=0;
|
||||
}
|
||||
// else if (!(acl.internal.ctrl_routing&7)) pclog("ACL_XYST\n");
|
||||
if (acl.internal.ctrl_routing&7)
|
||||
{
|
||||
acl.cpu_input=(acl.cpu_input&~(0xFF<<(acl.cpu_input_num*8)))|(val<<(acl.cpu_input_num*8));
|
||||
acl.cpu_input_num++;
|
||||
if (acl.cpu_input_num == et4000w32_vbus[acl.internal.vbus & 3])
|
||||
{
|
||||
if ((acl.internal.ctrl_routing&7)==2)
|
||||
et4000w32_blit(acl.cpu_input_num << 3, acl.cpu_input, 0, 1);
|
||||
else if ((acl.internal.ctrl_routing&7)==1)
|
||||
et4000w32_blit(acl.cpu_input_num, ~0, acl.cpu_input, 2);
|
||||
else
|
||||
pclog("Bad ET4K routing %i\n",acl.internal.ctrl_routing&7);
|
||||
acl.cpu_input_num=0;
|
||||
}
|
||||
}
|
||||
// else
|
||||
// pclog("Not ctrl_routing\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
vram[(addr&0x1FFF)+mmu.base[bank]]=val;
|
||||
changedvram[((addr&0x1FFF)+mmu.base[bank])>>12]=changeframecount;
|
||||
}
|
||||
break;
|
||||
case 0x6000:
|
||||
switch (addr&0x7FFF)
|
||||
{
|
||||
case 0x7F00: mmu.base[0]=(mmu.base[0]&0xFFFFFF00)|val; break;
|
||||
case 0x7F01: mmu.base[0]=(mmu.base[0]&0xFFFF00FF)|(val<<8); break;
|
||||
case 0x7F02: mmu.base[0]=(mmu.base[0]&0xFF00FFFF)|(val<<16); break;
|
||||
case 0x7F03: mmu.base[0]=(mmu.base[0]&0x00FFFFFF)|(val<<24); break;
|
||||
case 0x7F04: mmu.base[1]=(mmu.base[1]&0xFFFFFF00)|val; break;
|
||||
case 0x7F05: mmu.base[1]=(mmu.base[1]&0xFFFF00FF)|(val<<8); break;
|
||||
case 0x7F06: mmu.base[1]=(mmu.base[1]&0xFF00FFFF)|(val<<16); break;
|
||||
case 0x7F07: mmu.base[1]=(mmu.base[1]&0x00FFFFFF)|(val<<24); break;
|
||||
case 0x7F08: mmu.base[2]=(mmu.base[2]&0xFFFFFF00)|val; break;
|
||||
case 0x7F09: mmu.base[2]=(mmu.base[2]&0xFFFF00FF)|(val<<8); break;
|
||||
case 0x7F0A: mmu.base[2]=(mmu.base[2]&0xFF00FFFF)|(val<<16); break;
|
||||
case 0x7F0B: mmu.base[2]=(mmu.base[2]&0x00FFFFFF)|(val<<24); break;
|
||||
case 0x7F13: mmu.ctrl=val; break;
|
||||
|
||||
case 0x7F80: acl.queued.pattern_addr=(acl.queued.pattern_addr&0xFFFFFF00)|val; break;
|
||||
case 0x7F81: acl.queued.pattern_addr=(acl.queued.pattern_addr&0xFFFF00FF)|(val<<8); break;
|
||||
case 0x7F82: acl.queued.pattern_addr=(acl.queued.pattern_addr&0xFF00FFFF)|(val<<16); break;
|
||||
case 0x7F83: acl.queued.pattern_addr=(acl.queued.pattern_addr&0x00FFFFFF)|(val<<24); break;
|
||||
case 0x7F84: acl.queued.source_addr =(acl.queued.source_addr &0xFFFFFF00)|val; break;
|
||||
case 0x7F85: acl.queued.source_addr =(acl.queued.source_addr &0xFFFF00FF)|(val<<8); break;
|
||||
case 0x7F86: acl.queued.source_addr =(acl.queued.source_addr &0xFF00FFFF)|(val<<16); break;
|
||||
case 0x7F87: acl.queued.source_addr =(acl.queued.source_addr &0x00FFFFFF)|(val<<24); break;
|
||||
case 0x7F88: acl.queued.pattern_off=(acl.queued.pattern_off&0xFF00)|val; break;
|
||||
case 0x7F89: acl.queued.pattern_off=(acl.queued.pattern_off&0x00FF)|(val<<8); break;
|
||||
case 0x7F8A: acl.queued.source_off =(acl.queued.source_off &0xFF00)|val; break;
|
||||
case 0x7F8B: acl.queued.source_off =(acl.queued.source_off &0x00FF)|(val<<8); break;
|
||||
case 0x7F8C: acl.queued.dest_off =(acl.queued.dest_off &0xFF00)|val; break;
|
||||
case 0x7F8D: acl.queued.dest_off =(acl.queued.dest_off &0x00FF)|(val<<8); break;
|
||||
case 0x7F8E: acl.queued.vbus=val; break;
|
||||
case 0x7F8F: acl.queued.xy_dir=val; break;
|
||||
case 0x7F90: acl.queued.pattern_wrap=val; break;
|
||||
case 0x7F92: acl.queued.source_wrap=val; break;
|
||||
case 0x7F98: acl.queued.count_x =(acl.queued.count_x &0xFF00)|val; break;
|
||||
case 0x7F99: acl.queued.count_x =(acl.queued.count_x &0x00FF)|(val<<8); break;
|
||||
case 0x7F9A: acl.queued.count_y =(acl.queued.count_y &0xFF00)|val; break;
|
||||
case 0x7F9B: acl.queued.count_y =(acl.queued.count_y &0x00FF)|(val<<8); break;
|
||||
case 0x7F9C: acl.queued.ctrl_routing=val; break;
|
||||
case 0x7F9D: acl.queued.ctrl_reload =val; break;
|
||||
case 0x7F9E: acl.queued.rop_bg =val; break;
|
||||
case 0x7F9F: acl.queued.rop_fg =val; break;
|
||||
case 0x7FA0: acl.queued.dest_addr =(acl.queued.dest_addr &0xFFFFFF00)|val; break;
|
||||
case 0x7FA1: acl.queued.dest_addr =(acl.queued.dest_addr &0xFFFF00FF)|(val<<8); break;
|
||||
case 0x7FA2: acl.queued.dest_addr =(acl.queued.dest_addr &0xFF00FFFF)|(val<<16); break;
|
||||
case 0x7FA3: acl.queued.dest_addr =(acl.queued.dest_addr &0x00FFFFFF)|(val<<24);
|
||||
acl.internal=acl.queued;
|
||||
et4000w32_blit_start();
|
||||
acl.cpu_input_num=0;
|
||||
if (!(acl.queued.ctrl_routing&0x37))
|
||||
{
|
||||
et4000w32_blit(0xFFFFFF, ~0, 0, 0);
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t et4000w32_mmu_read(uint32_t addr)
|
||||
{
|
||||
int bank;
|
||||
pclog("ET4K read %08X %04X(%08X):%08X\n",addr,CS,cs,pc);
|
||||
switch (addr&0x6000)
|
||||
{
|
||||
case 0x0000: /*MMU 0*/
|
||||
case 0x2000: /*MMU 1*/
|
||||
case 0x4000: /*MMU 2*/
|
||||
bank=(addr>>13)&3;
|
||||
if (mmu.ctrl&(1<<bank))
|
||||
{
|
||||
/*???*/
|
||||
return 0xFF;
|
||||
}
|
||||
return vram[(addr&0x1FFF)+mmu.base[bank]];
|
||||
case 0x6000:
|
||||
switch (addr&0x7FFF)
|
||||
{
|
||||
case 0x7F00: return mmu.base[0];
|
||||
case 0x7F01: return mmu.base[0]>>8;
|
||||
case 0x7F02: return mmu.base[0]>>16;
|
||||
case 0x7F03: return mmu.base[0]>>24;
|
||||
case 0x7F04: return mmu.base[1];
|
||||
case 0x7F05: return mmu.base[1]>>8;
|
||||
case 0x7F06: return mmu.base[1]>>16;
|
||||
case 0x7F07: return mmu.base[1]>>24;
|
||||
case 0x7F08: return mmu.base[2];
|
||||
case 0x7F09: return mmu.base[2]>>8;
|
||||
case 0x7F0A: return mmu.base[2]>>16;
|
||||
case 0x7F0B: return mmu.base[2]>>24;
|
||||
case 0x7F13: return mmu.ctrl;
|
||||
|
||||
case 0x7F36:
|
||||
// if (acl.internal.pos_x!=acl.internal.count_x || acl.internal.pos_y!=acl.internal.count_y) return acl.status | ACL_XYST;
|
||||
return acl.status & ~(ACL_XYST | ACL_SSO);
|
||||
case 0x7F80: return acl.internal.pattern_addr;
|
||||
case 0x7F81: return acl.internal.pattern_addr>>8;
|
||||
case 0x7F82: return acl.internal.pattern_addr>>16;
|
||||
case 0x7F83: return acl.internal.pattern_addr>>24;
|
||||
case 0x7F84: return acl.internal.source_addr;
|
||||
case 0x7F85: return acl.internal.source_addr>>8;
|
||||
case 0x7F86: return acl.internal.source_addr>>16;
|
||||
case 0x7F87: return acl.internal.source_addr>>24;
|
||||
case 0x7F88: return acl.internal.pattern_off;
|
||||
case 0x7F89: return acl.internal.pattern_off>>8;
|
||||
case 0x7F8A: return acl.internal.source_off;
|
||||
case 0x7F8B: return acl.internal.source_off>>8;
|
||||
case 0x7F8C: return acl.internal.dest_off;
|
||||
case 0x7F8D: return acl.internal.dest_off>>8;
|
||||
case 0x7F8E: return acl.internal.vbus;
|
||||
case 0x7F8F: return acl.internal.xy_dir;
|
||||
case 0x7F90: return acl.internal.pattern_wrap;
|
||||
case 0x7F92: return acl.internal.source_wrap;
|
||||
case 0x7F98: return acl.internal.count_x;
|
||||
case 0x7F99: return acl.internal.count_x>>8;
|
||||
case 0x7F9A: return acl.internal.count_y;
|
||||
case 0x7F9B: return acl.internal.count_y>>8;
|
||||
case 0x7F9C: return acl.internal.ctrl_routing;
|
||||
case 0x7F9D: return acl.internal.ctrl_reload;
|
||||
case 0x7F9E: return acl.internal.rop_bg;
|
||||
case 0x7F9F: return acl.internal.rop_fg;
|
||||
case 0x7FA0: return acl.internal.dest_addr;
|
||||
case 0x7FA1: return acl.internal.dest_addr>>8;
|
||||
case 0x7FA2: return acl.internal.dest_addr>>16;
|
||||
case 0x7FA3: return acl.internal.dest_addr>>24;
|
||||
}
|
||||
return 0xFF;
|
||||
}
|
||||
}
|
||||
|
||||
int et4000w32_wrap_x[8]={0,0,3,7,15,31,63,0xFFFFFFFF};
|
||||
int et4000w32_wrap_y[8]={1,2,4,8,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF};
|
||||
|
||||
void et4000w32_blit_start()
|
||||
{
|
||||
pclog("Blit - %08X %08X %08X (%i,%i) %i %i %i %02X %02X %02X\n",acl.internal.pattern_addr,acl.internal.source_addr,acl.internal.dest_addr,acl.internal.dest_addr%640,acl.internal.dest_addr/640,acl.internal.xy_dir,acl.internal.count_x,acl.internal.count_y,acl.internal.rop_fg,acl.internal.rop_bg, acl.internal.ctrl_routing);
|
||||
acl.pattern_addr=acl.internal.pattern_addr;
|
||||
acl.source_addr =acl.internal.source_addr;
|
||||
acl.dest_addr =acl.internal.dest_addr;
|
||||
acl.dest_back =acl.dest_addr;
|
||||
acl.internal.pos_x=acl.internal.pos_y=0;
|
||||
acl.pattern_x=acl.source_x=acl.pattern_y=acl.source_y=0;
|
||||
acl.status = ACL_XYST;
|
||||
if (!(acl.internal.ctrl_routing&7) || (acl.internal.ctrl_routing&4)) acl.status |= ACL_SSO;
|
||||
if (et4000w32_wrap_x[acl.internal.pattern_wrap&7])
|
||||
{
|
||||
acl.pattern_x=acl.pattern_addr&et4000w32_wrap_x[acl.internal.pattern_wrap&7];
|
||||
acl.pattern_addr&=~et4000w32_wrap_x[acl.internal.pattern_wrap&7];
|
||||
}
|
||||
if (!(acl.internal.pattern_wrap&0x80))
|
||||
{
|
||||
acl.pattern_y=(acl.pattern_addr/(et4000w32_wrap_x[acl.internal.pattern_wrap&7]+1))&(et4000w32_wrap_y[(acl.internal.pattern_wrap>>4)&7]-1);
|
||||
acl.pattern_addr&=~(((et4000w32_wrap_x[acl.internal.pattern_wrap&7]+1)*et4000w32_wrap_y[(acl.internal.pattern_wrap>>4)&7])-1);
|
||||
}
|
||||
acl.pattern_x_back=acl.pattern_x;
|
||||
acl.pattern_back=acl.pattern_addr;
|
||||
}
|
||||
|
||||
void et4000w32_blit(int count, uint32_t mix, uint32_t sdat, int cpu_input)
|
||||
{
|
||||
int c,d;
|
||||
uint8_t pattern,source,dest,out;
|
||||
uint8_t rop;
|
||||
|
||||
// if (count>400) pclog("New blit - %i,%i %06X (%i,%i) %06X %06X\n",acl.internal.count_x,acl.internal.count_y,acl.dest_addr,acl.dest_addr%640,acl.dest_addr/640,acl.source_addr,acl.pattern_addr);
|
||||
// pclog("Blit exec - %i %i %i\n",count,acl.internal.pos_x,acl.internal.pos_y);
|
||||
while (count--)
|
||||
{
|
||||
pclog("%i,%i : ",acl.internal.pos_x,acl.internal.pos_y);
|
||||
if (acl.internal.xy_dir&1)
|
||||
{
|
||||
pattern=vram[(acl.pattern_addr-acl.pattern_x)&0x1FFFFF];
|
||||
source =vram[(acl.source_addr -acl.source_x) &0x1FFFFF];
|
||||
pclog("%06X %06X ",(acl.pattern_addr-acl.pattern_x)&0x1FFFFF,(acl.source_addr -acl.source_x) &0x1FFFFF);
|
||||
}
|
||||
else
|
||||
{
|
||||
pattern=vram[(acl.pattern_addr+acl.pattern_x)&0x1FFFFF];
|
||||
source =vram[(acl.source_addr +acl.source_x) &0x1FFFFF];
|
||||
pclog("%06X %06X ",(acl.pattern_addr+acl.pattern_x)&0x1FFFFF,(acl.source_addr +acl.source_x) &0x1FFFFF);
|
||||
}
|
||||
if (cpu_input==2)
|
||||
{
|
||||
source=sdat&0xFF;
|
||||
sdat>>=8;
|
||||
}
|
||||
dest=vram[acl.dest_addr &0x1FFFFF];
|
||||
out=0;
|
||||
pclog("%06X %i %08X ",acl.dest_addr,mix&1,mix);
|
||||
rop = (mix & 1) ? acl.internal.rop_fg:acl.internal.rop_bg;
|
||||
mix>>=1; mix|=0x80000000;
|
||||
for (c=0;c<8;c++)
|
||||
{
|
||||
d=(dest & (1<<c)) ? 1:0;
|
||||
if (source & (1<<c)) d|=2;
|
||||
if (pattern & (1<<c)) d|=4;
|
||||
if (rop & (1<<d)) out|=(1<<c);
|
||||
}
|
||||
pclog("%06X = %02X\n",acl.dest_addr&0x1FFFFF,out);
|
||||
vram[acl.dest_addr&0x1FFFFF]=out;
|
||||
changedvram[(acl.dest_addr&0x1FFFFF)>>12]=changeframecount;
|
||||
|
||||
acl.pattern_x++;
|
||||
acl.pattern_x&=et4000w32_wrap_x[acl.internal.pattern_wrap&7];
|
||||
acl.source_x++;
|
||||
acl.source_x &=et4000w32_wrap_x[acl.internal.source_wrap&7];
|
||||
if (acl.internal.xy_dir&1) acl.dest_addr--;
|
||||
else acl.dest_addr++;
|
||||
|
||||
acl.internal.pos_x++;
|
||||
if (acl.internal.pos_x>acl.internal.count_x)
|
||||
{
|
||||
if (acl.internal.xy_dir&2)
|
||||
{
|
||||
acl.pattern_addr-=(acl.internal.pattern_off+1);
|
||||
acl.source_addr -=(acl.internal.source_off +1);
|
||||
acl.dest_back=acl.dest_addr=acl.dest_back-(acl.internal.dest_off+1);
|
||||
}
|
||||
else
|
||||
{
|
||||
acl.pattern_addr+=acl.internal.pattern_off+1;
|
||||
acl.source_addr +=acl.internal.source_off +1;
|
||||
acl.dest_back=acl.dest_addr=acl.dest_back+acl.internal.dest_off+1;
|
||||
}
|
||||
acl.pattern_x = acl.pattern_x_back;
|
||||
acl.source_x = 0;
|
||||
acl.pattern_y++;
|
||||
if (acl.pattern_y==et4000w32_wrap_y[(acl.internal.pattern_wrap>>4)&7])
|
||||
{
|
||||
acl.pattern_y=0;
|
||||
acl.pattern_addr=acl.pattern_back;
|
||||
}
|
||||
acl.source_y++;
|
||||
if (acl.source_y ==et4000w32_wrap_y[(acl.internal.source_wrap >>4)&7])
|
||||
{
|
||||
acl.source_y=0;
|
||||
acl.source_addr=acl.internal.source_addr;
|
||||
}
|
||||
|
||||
acl.internal.pos_y++;
|
||||
if (acl.internal.pos_y>acl.internal.count_y)
|
||||
{
|
||||
acl.status = 0;
|
||||
return;
|
||||
}
|
||||
acl.internal.pos_x=0;
|
||||
if (cpu_input) return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* for (y=0;y<=acl.internal.count_y;y++)
|
||||
{
|
||||
dest_back=acl.dest_addr;
|
||||
for (x=0;x<=acl.internal.count_x;x++)
|
||||
{
|
||||
if (acl.internal.xy_dir&1)
|
||||
{
|
||||
pattern=vram[(acl.pattern_addr-pattern_x)&0x1FFFFF];
|
||||
source =vram[(acl.source_addr -source_x) &0x1FFFFF];
|
||||
}
|
||||
else
|
||||
{
|
||||
pattern=vram[(acl.pattern_addr+pattern_x)&0x1FFFFF];
|
||||
source =vram[(acl.source_addr +source_x) &0x1FFFFF];
|
||||
}
|
||||
dest=vram[acl.dest_addr &0x1FFFFF];
|
||||
out=0;
|
||||
for (c=0;c<8;c++)
|
||||
{
|
||||
d=(dest&(1<<c))?1:0;
|
||||
if (source&(1<<c)) d|=2;
|
||||
if (pattern&(1<<c)) d|=4;
|
||||
if (acl.internal.rop_bg&(1<<d)) out|=(1<<c);
|
||||
}
|
||||
vram[acl.dest_addr&0x1FFFFF]=out;
|
||||
changedvram[(acl.dest_addr&0x1FFFFF)>>12]=changeframecount;
|
||||
|
||||
pattern_x++;
|
||||
pattern_x&=et4000w32_wrap_x[acl.internal.pattern_wrap&7];
|
||||
source_x++;
|
||||
source_x &=et4000w32_wrap_x[acl.internal.source_wrap&7];
|
||||
if (acl.internal.xy_dir&1) acl.dest_addr--;
|
||||
else acl.dest_addr++;
|
||||
}
|
||||
acl.pattern_addr+=acl.internal.pattern_off+1;
|
||||
acl.source_addr +=acl.internal.source_off+1;
|
||||
acl.dest_addr=dest_back+acl.internal.dest_off+1;
|
||||
pattern_y++;
|
||||
if (pattern_y==et4000w32_wrap_y[(acl.internal.pattern_wrap>>4)&7])
|
||||
{
|
||||
pattern_y=0;
|
||||
acl.pattern_addr=acl.internal.pattern_addr;
|
||||
}
|
||||
source_y++;
|
||||
if (source_y ==et4000w32_wrap_y[(acl.internal.source_wrap >>4)&7])
|
||||
{
|
||||
source_y=0;
|
||||
acl.source_addr=acl.internal.source_addr;
|
||||
}
|
||||
}*/
|
||||
|
||||
#endif
|
||||
655
backup code/video - Cópia/vid_genius.c
Normal file
655
backup code/video - Cópia/vid_genius.c
Normal file
@@ -0,0 +1,655 @@
|
||||
/*
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
*
|
||||
* This file is part of the 86Box distribution.
|
||||
*
|
||||
* MDSI Genius VHR emulation.
|
||||
*
|
||||
* Version: @(#)vid_genius.c 1.0.10 2018/05/20
|
||||
*
|
||||
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
*
|
||||
* Copyright 2008-2018 Sarah Walker.
|
||||
* Copyright 2016-2018 Miran Grca.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <wchar.h>
|
||||
#include "../86box.h"
|
||||
#include "../io.h"
|
||||
#include "../pit.h"
|
||||
#include "../mem.h"
|
||||
#include "../rom.h"
|
||||
#include "../timer.h"
|
||||
#include "../device.h"
|
||||
#include "../plat.h"
|
||||
#include "video.h"
|
||||
#include "vid_genius.h"
|
||||
|
||||
|
||||
#define BIOS_ROM_PATH L"roms/video/genius/8x12.bin"
|
||||
|
||||
|
||||
#define GENIUS_XSIZE 728
|
||||
#define GENIUS_YSIZE 1008
|
||||
|
||||
|
||||
extern uint8_t fontdat8x12[256][16];
|
||||
|
||||
|
||||
/* I'm at something of a disadvantage writing this emulation: I don't have an
|
||||
* MDSI Genius card, nor do I have the BIOS extension (VHRBIOS.SYS) that came
|
||||
* with it. What I do have are the GEM and Windows 1.04 drivers, plus a driver
|
||||
* for a later MCA version of the card. The latter can be found at
|
||||
* <http://files.mpoli.fi/hardware/DISPLAY/GENIUS/> and is necessary if you
|
||||
* want the Windows driver to work.
|
||||
*
|
||||
* This emulation appears to work correctly with:
|
||||
* The MCA drivers GMC_ANSI.SYS and INS_ANSI.SYS
|
||||
* The GEM driver SDGEN9.VGA
|
||||
* The Windows 1.04 driver GENIUS.DRV
|
||||
*
|
||||
* As far as I can see, the card uses a fixed resolution of 728x1008 pixels.
|
||||
* It has the following modes of operation:
|
||||
*
|
||||
* > MDA-compatible: 80x25 text, each character 9x15 pixels.
|
||||
* > CGA-compatible: 640x200 mono graphics
|
||||
* > Dual: MDA text in the top half, CGA graphics in the bottom
|
||||
* > Native text: 80x66 text, each character 9x15 pixels.
|
||||
* > Native graphics: 728x1008 mono graphics.
|
||||
*
|
||||
* Under the covers, this seems to translate to:
|
||||
* > Text framebuffer. At B000:0000, 16k. Displayed if enable bit is set
|
||||
* in the MDA control register.
|
||||
* > Graphics framebuffer. In native modes goes from A000:0000 to A000:FFFF
|
||||
* and B800:0000 to B800:FFFF. In CGA-compatible
|
||||
* mode only the section at B800:0000 to B800:7FFF
|
||||
* is visible. Displayed if enable bit is set in the
|
||||
* CGA control register.
|
||||
*
|
||||
* Two card-specific registers control text and graphics display:
|
||||
*
|
||||
* 03B0: Control register.
|
||||
* Bit 0: Map all graphics framebuffer into memory.
|
||||
* Bit 2: Unknown. Set by GMC /M; cleared by mode set or GMC /T.
|
||||
* Bit 4: Set for CGA-compatible graphics, clear for native graphics.
|
||||
* Bit 5: Set for black on white, clear for white on black.
|
||||
*
|
||||
* 03B1: Character height register.
|
||||
* Bits 0-1: Character cell height (0 => 15, 1 => 14, 2 => 13, 3 => 12)
|
||||
* Bit 4: Set to double character cell height (scanlines are doubled)
|
||||
* Bit 7: Unknown, seems to be set for all modes except 80x66
|
||||
*
|
||||
* Not having the card also means I don't have its font. According to the
|
||||
* card brochure the font is an 8x12 bitmap in a 9x15 character cell. I
|
||||
* therefore generated it by taking the MDA font, increasing graphics to
|
||||
* 16 pixels in height and reducing the height of characters so they fit
|
||||
* in an 8x12 cell if necessary.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
typedef struct genius_t
|
||||
{
|
||||
mem_mapping_t mapping;
|
||||
|
||||
uint8_t mda_crtc[32]; /* The 'CRTC' as the host PC sees it */
|
||||
int mda_crtcreg; /* Current CRTC register */
|
||||
uint8_t genius_control; /* Native control register
|
||||
* I think bit 0 enables the full
|
||||
* framebuffer.
|
||||
*/
|
||||
uint8_t genius_charh; /* Native character height register:
|
||||
* 00h => chars are 15 pixels high
|
||||
* 81h => chars are 14 pixels high
|
||||
* 83h => chars are 12 pixels high
|
||||
* 90h => chars are 30 pixels high [15 x 2]
|
||||
* 93h => chars are 24 pixels high [12 x 2]
|
||||
*/
|
||||
uint8_t genius_mode; /* Current mode (see list at top of file) */
|
||||
uint8_t cga_ctrl; /* Emulated CGA control register */
|
||||
uint8_t mda_ctrl; /* Emulated MDA control register */
|
||||
uint8_t cga_colour; /* Emulated CGA colour register (ignored) */
|
||||
|
||||
uint8_t mda_stat; /* MDA status (IN 0x3BA) */
|
||||
uint8_t cga_stat; /* CGA status (IN 0x3DA) */
|
||||
|
||||
int font; /* Current font, 0 or 1 */
|
||||
int enabled; /* Display enabled, 0 or 1 */
|
||||
int detach; /* Detach cursor, 0 or 1 */
|
||||
|
||||
int64_t dispontime, dispofftime;
|
||||
int64_t vidtime;
|
||||
|
||||
int linepos, displine;
|
||||
int vc;
|
||||
int dispon, blink;
|
||||
int64_t vsynctime;
|
||||
|
||||
uint8_t *vram;
|
||||
} genius_t;
|
||||
|
||||
static uint32_t genius_pal[4];
|
||||
|
||||
/* Mapping of attributes to colours, in MDA emulation mode */
|
||||
static int mdacols[256][2][2];
|
||||
|
||||
void genius_recalctimings(genius_t *genius);
|
||||
void genius_write(uint32_t addr, uint8_t val, void *p);
|
||||
uint8_t genius_read(uint32_t addr, void *p);
|
||||
|
||||
|
||||
void genius_out(uint16_t addr, uint8_t val, void *p)
|
||||
{
|
||||
genius_t *genius = (genius_t *)p;
|
||||
|
||||
switch (addr)
|
||||
{
|
||||
case 0x3b0: /* Command / control register */
|
||||
genius->genius_control = val;
|
||||
if (val & 1)
|
||||
{
|
||||
mem_mapping_set_addr(&genius->mapping, 0xa0000, 0x28000);
|
||||
}
|
||||
else
|
||||
{
|
||||
mem_mapping_set_addr(&genius->mapping, 0xb0000, 0x10000);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 0x3b1:
|
||||
genius->genius_charh = val;
|
||||
break;
|
||||
|
||||
/* Emulated CRTC, register select */
|
||||
case 0x3b2: case 0x3b4: case 0x3b6:
|
||||
case 0x3d0: case 0x3d2: case 0x3d4: case 0x3d6:
|
||||
genius->mda_crtcreg = val & 31;
|
||||
break;
|
||||
|
||||
/* Emulated CRTC, value */
|
||||
case 0x3b3: case 0x3b5: case 0x3b7:
|
||||
case 0x3d1: case 0x3d3: case 0x3d5: case 0x3d7:
|
||||
genius->mda_crtc[genius->mda_crtcreg] = val;
|
||||
genius_recalctimings(genius);
|
||||
return;
|
||||
|
||||
/* Emulated MDA control register */
|
||||
case 0x3b8:
|
||||
genius->mda_ctrl = val;
|
||||
return;
|
||||
/* Emulated CGA control register */
|
||||
case 0x3D8:
|
||||
genius->cga_ctrl = val;
|
||||
return;
|
||||
/* Emulated CGA colour register */
|
||||
case 0x3D9:
|
||||
genius->cga_colour = val;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t genius_in(uint16_t addr, void *p)
|
||||
{
|
||||
genius_t *genius = (genius_t *)p;
|
||||
|
||||
switch (addr)
|
||||
{
|
||||
case 0x3b0: case 0x3b2: case 0x3b4: case 0x3b6:
|
||||
case 0x3d0: case 0x3d2: case 0x3d4: case 0x3d6:
|
||||
return genius->mda_crtcreg;
|
||||
case 0x3b1: case 0x3b3: case 0x3b5: case 0x3b7:
|
||||
case 0x3d1: case 0x3d3: case 0x3d5: case 0x3d7:
|
||||
return genius->mda_crtc[genius->mda_crtcreg];
|
||||
case 0x3b8:
|
||||
return genius->mda_ctrl;
|
||||
case 0x3d9:
|
||||
return genius->cga_colour;
|
||||
case 0x3ba:
|
||||
return genius->mda_stat;
|
||||
case 0x3d8:
|
||||
return genius->cga_ctrl;
|
||||
case 0x3da:
|
||||
return genius->cga_stat;
|
||||
}
|
||||
return 0xff;
|
||||
}
|
||||
|
||||
void genius_write(uint32_t addr, uint8_t val, void *p)
|
||||
{
|
||||
genius_t *genius = (genius_t *)p;
|
||||
egawrites++;
|
||||
|
||||
if (genius->genius_control & 1)
|
||||
{
|
||||
addr = addr % 0x28000;
|
||||
}
|
||||
else
|
||||
/* If hi-res memory is disabled, only visible in the B000 segment */
|
||||
{
|
||||
addr = (addr & 0xFFFF) + 0x10000;
|
||||
}
|
||||
genius->vram[addr] = val;
|
||||
}
|
||||
|
||||
|
||||
|
||||
uint8_t genius_read(uint32_t addr, void *p)
|
||||
{
|
||||
genius_t *genius = (genius_t *)p;
|
||||
egareads++;
|
||||
|
||||
if (genius->genius_control & 1)
|
||||
{
|
||||
addr = addr % 0x28000;
|
||||
}
|
||||
else
|
||||
/* If hi-res memory is disabled, only visible in the B000 segment */
|
||||
{
|
||||
addr = (addr & 0xFFFF) + 0x10000;
|
||||
}
|
||||
return genius->vram[addr];
|
||||
}
|
||||
|
||||
void genius_recalctimings(genius_t *genius)
|
||||
{
|
||||
double disptime;
|
||||
double _dispontime, _dispofftime;
|
||||
|
||||
disptime = 0x31;
|
||||
_dispontime = 0x28;
|
||||
_dispofftime = disptime - _dispontime;
|
||||
_dispontime *= MDACONST;
|
||||
_dispofftime *= MDACONST;
|
||||
genius->dispontime = (int)(_dispontime * (1 << TIMER_SHIFT));
|
||||
genius->dispofftime = (int)(_dispofftime * (1 << TIMER_SHIFT));
|
||||
}
|
||||
|
||||
|
||||
/* Draw a single line of the screen in either text mode */
|
||||
void genius_textline(genius_t *genius, uint8_t background)
|
||||
{
|
||||
int x;
|
||||
int w = 80; /* 80 characters across */
|
||||
int cw = 9; /* Each character is 9 pixels wide */
|
||||
uint8_t chr, attr;
|
||||
uint8_t bitmap[2];
|
||||
int blink, c, row;
|
||||
int drawcursor, cursorline;
|
||||
uint16_t addr;
|
||||
uint8_t sc;
|
||||
int charh;
|
||||
uint16_t ma = (genius->mda_crtc[13] | (genius->mda_crtc[12] << 8)) & 0x3fff;
|
||||
uint16_t ca = (genius->mda_crtc[15] | (genius->mda_crtc[14] << 8)) & 0x3fff;
|
||||
unsigned char *framebuf = genius->vram + 0x10000;
|
||||
uint32_t col;
|
||||
|
||||
/* Character height is 12-15 */
|
||||
charh = 15 - (genius->genius_charh & 3);
|
||||
if (genius->genius_charh & 0x10)
|
||||
{
|
||||
row = ((genius->displine >> 1) / charh);
|
||||
sc = ((genius->displine >> 1) % charh);
|
||||
}
|
||||
else
|
||||
{
|
||||
row = (genius->displine / charh);
|
||||
sc = (genius->displine % charh);
|
||||
}
|
||||
addr = ((ma & ~1) + row * w) * 2;
|
||||
|
||||
ma += (row * w);
|
||||
|
||||
if ((genius->mda_crtc[10] & 0x60) == 0x20)
|
||||
{
|
||||
cursorline = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
cursorline = ((genius->mda_crtc[10] & 0x1F) <= sc) &&
|
||||
((genius->mda_crtc[11] & 0x1F) >= sc);
|
||||
}
|
||||
|
||||
for (x = 0; x < w; x++)
|
||||
{
|
||||
chr = framebuf[(addr + 2 * x) & 0x3FFF];
|
||||
attr = framebuf[(addr + 2 * x + 1) & 0x3FFF];
|
||||
drawcursor = ((ma == ca) && cursorline && genius->enabled &&
|
||||
(genius->mda_ctrl & 8));
|
||||
|
||||
switch (genius->mda_crtc[10] & 0x60)
|
||||
{
|
||||
case 0x00: drawcursor = drawcursor && (genius->blink & 16); break;
|
||||
case 0x60: drawcursor = drawcursor && (genius->blink & 32); break;
|
||||
}
|
||||
blink = ((genius->blink & 16) &&
|
||||
(genius->mda_ctrl & 0x20) &&
|
||||
(attr & 0x80) && !drawcursor);
|
||||
|
||||
if (genius->mda_ctrl & 0x20) attr &= 0x7F;
|
||||
/* MDA underline */
|
||||
if (sc == charh && ((attr & 7) == 1))
|
||||
{
|
||||
col = mdacols[attr][blink][1];
|
||||
|
||||
if (genius->genius_control & 0x20)
|
||||
{
|
||||
col ^= 0xffffff;
|
||||
}
|
||||
|
||||
for (c = 0; c < cw; c++)
|
||||
{
|
||||
if (col != background)
|
||||
((uint32_t *)buffer32->line[genius->displine])[(x * cw) + c] = col;
|
||||
}
|
||||
}
|
||||
else /* Draw 8 pixels of character */
|
||||
{
|
||||
bitmap[0] = fontdat8x12[chr][sc];
|
||||
for (c = 0; c < 8; c++)
|
||||
{
|
||||
col = mdacols[attr][blink][(bitmap[0] & (1 << (c ^ 7))) ? 1 : 0];
|
||||
if (!(genius->enabled) || !(genius->mda_ctrl & 8))
|
||||
col = mdacols[0][0][0];
|
||||
|
||||
if (genius->genius_control & 0x20)
|
||||
{
|
||||
col ^= 0xffffff;
|
||||
}
|
||||
if (col != background)
|
||||
{
|
||||
((uint32_t *)buffer32->line[genius->displine])[(x * cw) + c] = col;
|
||||
}
|
||||
}
|
||||
/* The ninth pixel column... */
|
||||
if ((chr & ~0x1f) == 0xc0)
|
||||
{
|
||||
/* Echo column 8 for the graphics chars */
|
||||
col = ((uint32_t *)buffer32->line[genius->displine])[(x * cw) + 7];
|
||||
if (col != background)
|
||||
((uint32_t *)buffer32->line[genius->displine])[(x * cw) + 8] = col;
|
||||
}
|
||||
else /* Otherwise fill with background */
|
||||
{
|
||||
col = mdacols[attr][blink][0];
|
||||
if (genius->genius_control & 0x20)
|
||||
{
|
||||
col ^= 0xffffff;
|
||||
}
|
||||
if (col != background)
|
||||
((uint32_t *)buffer32->line[genius->displine])[(x * cw) + 8] = col;
|
||||
}
|
||||
if (drawcursor)
|
||||
{
|
||||
for (c = 0; c < cw; c++)
|
||||
((uint32_t *)buffer32->line[genius->displine])[(x * cw) + c] ^= mdacols[attr][0][1];
|
||||
}
|
||||
++ma;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Draw a line in the CGA 640x200 mode */
|
||||
void genius_cgaline(genius_t *genius)
|
||||
{
|
||||
int x, c;
|
||||
uint32_t dat;
|
||||
uint32_t ink;
|
||||
uint32_t addr;
|
||||
|
||||
ink = (genius->genius_control & 0x20) ? genius_pal[0] : genius_pal[3];
|
||||
/* We draw the CGA at row 600 */
|
||||
if (genius->displine < 600)
|
||||
{
|
||||
return;
|
||||
}
|
||||
addr = 0x18000 + 80 * ((genius->displine - 600) >> 2);
|
||||
if ((genius->displine - 600) & 2)
|
||||
{
|
||||
addr += 0x2000;
|
||||
}
|
||||
|
||||
for (x = 0; x < 80; x++)
|
||||
{
|
||||
dat = genius->vram[addr];
|
||||
addr++;
|
||||
|
||||
for (c = 0; c < 8; c++)
|
||||
{
|
||||
if (dat & 0x80)
|
||||
{
|
||||
((uint32_t *)buffer32->line[genius->displine])[x*8 + c] = ink;
|
||||
}
|
||||
dat = dat << 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Draw a line in the native high-resolution mode */
|
||||
void genius_hiresline(genius_t *genius)
|
||||
{
|
||||
int x, c;
|
||||
uint32_t dat;
|
||||
uint32_t ink;
|
||||
uint32_t addr;
|
||||
|
||||
ink = (genius->genius_control & 0x20) ? genius_pal[0] : genius_pal[3];
|
||||
/* The first 512 lines live at A0000 */
|
||||
if (genius->displine < 512)
|
||||
{
|
||||
addr = 128 * genius->displine;
|
||||
}
|
||||
else /* The second 496 live at B8000 */
|
||||
{
|
||||
addr = 0x18000 + 128 * (genius->displine - 512);
|
||||
}
|
||||
|
||||
for (x = 0; x < 91; x++)
|
||||
{
|
||||
dat = genius->vram[addr];
|
||||
addr++;
|
||||
|
||||
for (c = 0; c < 8; c++)
|
||||
{
|
||||
if (dat & 0x80)
|
||||
{
|
||||
((uint32_t *)buffer32->line[genius->displine])[x*8 + c] = ink;
|
||||
}
|
||||
dat = dat << 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void genius_poll(void *p)
|
||||
{
|
||||
genius_t *genius = (genius_t *)p;
|
||||
int x;
|
||||
uint8_t background;
|
||||
|
||||
if (!genius->linepos)
|
||||
{
|
||||
genius->vidtime += genius->dispofftime;
|
||||
genius->cga_stat |= 1;
|
||||
genius->mda_stat |= 1;
|
||||
genius->linepos = 1;
|
||||
if (genius->dispon)
|
||||
{
|
||||
if (genius->genius_control & 0x20)
|
||||
{
|
||||
background = genius_pal[3];
|
||||
}
|
||||
else
|
||||
{
|
||||
background = genius_pal[0];
|
||||
}
|
||||
if (genius->displine == 0)
|
||||
{
|
||||
video_wait_for_buffer();
|
||||
}
|
||||
/* Start off with a blank line */
|
||||
for (x = 0; x < GENIUS_XSIZE; x++)
|
||||
{
|
||||
((uint32_t *)buffer32->line[genius->displine])[x] = background;
|
||||
}
|
||||
/* If graphics display enabled, draw graphics on top
|
||||
* of the blanked line */
|
||||
if (genius->cga_ctrl & 8)
|
||||
{
|
||||
if (genius->genius_control & 8)
|
||||
{
|
||||
genius_cgaline(genius);
|
||||
}
|
||||
else
|
||||
{
|
||||
genius_hiresline(genius);
|
||||
}
|
||||
}
|
||||
/* If MDA display is enabled, draw MDA text on top
|
||||
* of the lot */
|
||||
if (genius->mda_ctrl & 8)
|
||||
{
|
||||
genius_textline(genius, background);
|
||||
}
|
||||
}
|
||||
genius->displine++;
|
||||
/* Hardcode a fixed refresh rate and VSYNC timing */
|
||||
if (genius->displine == 1008) /* Start of VSYNC */
|
||||
{
|
||||
genius->cga_stat |= 8;
|
||||
genius->dispon = 0;
|
||||
}
|
||||
if (genius->displine == 1040) /* End of VSYNC */
|
||||
{
|
||||
genius->displine = 0;
|
||||
genius->cga_stat &= ~8;
|
||||
genius->dispon = 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (genius->dispon)
|
||||
{
|
||||
genius->cga_stat &= ~1;
|
||||
genius->mda_stat &= ~1;
|
||||
}
|
||||
genius->vidtime += genius->dispontime;
|
||||
genius->linepos = 0;
|
||||
|
||||
if (genius->displine == 1008)
|
||||
{
|
||||
/* Hardcode GENIUS_XSIZE * GENIUS_YSIZE window size */
|
||||
if (GENIUS_XSIZE != xsize || GENIUS_YSIZE != ysize)
|
||||
{
|
||||
xsize = GENIUS_XSIZE;
|
||||
ysize = GENIUS_YSIZE;
|
||||
if (xsize < 64) xsize = 656;
|
||||
if (ysize < 32) ysize = 200;
|
||||
set_screen_size(xsize, ysize);
|
||||
|
||||
if (video_force_resize_get())
|
||||
video_force_resize_set(0);
|
||||
}
|
||||
video_blit_memtoscreen(0, 0, 0, ysize, xsize, ysize);
|
||||
|
||||
frames++;
|
||||
/* Fixed 728x1008 resolution */
|
||||
video_res_x = GENIUS_XSIZE;
|
||||
video_res_y = GENIUS_YSIZE;
|
||||
video_bpp = 1;
|
||||
genius->blink++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void *genius_init(const device_t *info)
|
||||
{
|
||||
int c;
|
||||
genius_t *genius = malloc(sizeof(genius_t));
|
||||
memset(genius, 0, sizeof(genius_t));
|
||||
|
||||
/* 160k video RAM */
|
||||
genius->vram = malloc(0x28000);
|
||||
|
||||
loadfont(BIOS_ROM_PATH, 4);
|
||||
|
||||
timer_add(genius_poll, &genius->vidtime, TIMER_ALWAYS_ENABLED, genius);
|
||||
|
||||
/* Occupy memory between 0xB0000 and 0xBFFFF (moves to 0xA0000 in
|
||||
* high-resolution modes) */
|
||||
mem_mapping_add(&genius->mapping, 0xb0000, 0x10000, genius_read, NULL, NULL, genius_write, NULL, NULL, NULL, MEM_MAPPING_EXTERNAL, genius);
|
||||
/* Respond to both MDA and CGA I/O ports */
|
||||
io_sethandler(0x03b0, 0x000C, genius_in, NULL, NULL, genius_out, NULL, NULL, genius);
|
||||
io_sethandler(0x03d0, 0x0010, genius_in, NULL, NULL, genius_out, NULL, NULL, genius);
|
||||
|
||||
genius_pal[0] = makecol(0x00, 0x00, 0x00);
|
||||
genius_pal[1] = makecol(0x55, 0x55, 0x55);
|
||||
genius_pal[2] = makecol(0xaa, 0xaa, 0xaa);
|
||||
genius_pal[3] = makecol(0xff, 0xff, 0xff);
|
||||
|
||||
/* MDA attributes */
|
||||
/* I don't know if the Genius's MDA emulation actually does
|
||||
* emulate bright / non-bright. For the time being pretend it does. */
|
||||
for (c = 0; c < 256; c++)
|
||||
{
|
||||
mdacols[c][0][0] = mdacols[c][1][0] = mdacols[c][1][1] = genius_pal[0];
|
||||
if (c & 8) mdacols[c][0][1] = genius_pal[3];
|
||||
else mdacols[c][0][1] = genius_pal[2];
|
||||
}
|
||||
mdacols[0x70][0][1] = genius_pal[0];
|
||||
mdacols[0x70][0][0] = mdacols[0x70][1][0] = mdacols[0x70][1][1] = genius_pal[3];
|
||||
mdacols[0xF0][0][1] = genius_pal[0];
|
||||
mdacols[0xF0][0][0] = mdacols[0xF0][1][0] = mdacols[0xF0][1][1] = genius_pal[3];
|
||||
mdacols[0x78][0][1] = genius_pal[2];
|
||||
mdacols[0x78][0][0] = mdacols[0x78][1][0] = mdacols[0x78][1][1] = genius_pal[3];
|
||||
mdacols[0xF8][0][1] = genius_pal[2];
|
||||
mdacols[0xF8][0][0] = mdacols[0xF8][1][0] = mdacols[0xF8][1][1] = genius_pal[3];
|
||||
mdacols[0x00][0][1] = mdacols[0x00][1][1] = genius_pal[0];
|
||||
mdacols[0x08][0][1] = mdacols[0x08][1][1] = genius_pal[0];
|
||||
mdacols[0x80][0][1] = mdacols[0x80][1][1] = genius_pal[0];
|
||||
mdacols[0x88][0][1] = mdacols[0x88][1][1] = genius_pal[0];
|
||||
|
||||
/* Start off in 80x25 text mode */
|
||||
genius->cga_stat = 0xF4;
|
||||
genius->genius_mode = 2;
|
||||
genius->enabled = 1;
|
||||
genius->genius_charh = 0x90; /* Native character height register */
|
||||
return genius;
|
||||
}
|
||||
|
||||
void genius_close(void *p)
|
||||
{
|
||||
genius_t *genius = (genius_t *)p;
|
||||
|
||||
free(genius->vram);
|
||||
free(genius);
|
||||
}
|
||||
|
||||
static int genius_available()
|
||||
{
|
||||
return rom_present(BIOS_ROM_PATH);
|
||||
}
|
||||
|
||||
void genius_speed_changed(void *p)
|
||||
{
|
||||
genius_t *genius = (genius_t *)p;
|
||||
|
||||
genius_recalctimings(genius);
|
||||
}
|
||||
|
||||
const device_t genius_device =
|
||||
{
|
||||
"Genius VHR",
|
||||
DEVICE_ISA, 0,
|
||||
genius_init, genius_close, NULL,
|
||||
genius_available,
|
||||
genius_speed_changed,
|
||||
NULL,
|
||||
NULL
|
||||
};
|
||||
1
backup code/video - Cópia/vid_genius.h
Normal file
1
backup code/video - Cópia/vid_genius.h
Normal file
@@ -0,0 +1 @@
|
||||
extern const device_t genius_device;
|
||||
427
backup code/video - Cópia/vid_hercules.c
Normal file
427
backup code/video - Cópia/vid_hercules.c
Normal file
@@ -0,0 +1,427 @@
|
||||
/*
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
*
|
||||
* This file is part of the 86Box distribution.
|
||||
*
|
||||
* Hercules emulation.
|
||||
*
|
||||
* Version: @(#)vid_hercules.c 1.0.11 2018/04/29
|
||||
*
|
||||
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
*
|
||||
* Copyright 2008-2018 Sarah Walker.
|
||||
* Copyright 2016-2018 Miran Grca.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <wchar.h>
|
||||
#include "../86box.h"
|
||||
#include "../mem.h"
|
||||
#include "../rom.h"
|
||||
#include "../io.h"
|
||||
#include "../lpt.h"
|
||||
#include "../pit.h"
|
||||
#include "../timer.h"
|
||||
#include "../device.h"
|
||||
#include "video.h"
|
||||
#include "vid_hercules.h"
|
||||
|
||||
|
||||
typedef struct hercules_t
|
||||
{
|
||||
mem_mapping_t mapping;
|
||||
|
||||
uint8_t crtc[32];
|
||||
int crtcreg;
|
||||
|
||||
uint8_t ctrl, ctrl2, stat;
|
||||
|
||||
int64_t dispontime, dispofftime;
|
||||
int64_t vidtime;
|
||||
|
||||
int firstline, lastline;
|
||||
|
||||
int linepos, displine;
|
||||
int vc, sc;
|
||||
uint16_t ma, maback;
|
||||
int con, coff, cursoron;
|
||||
int dispon, blink;
|
||||
int64_t vsynctime;
|
||||
int vadj;
|
||||
|
||||
uint8_t *vram;
|
||||
} hercules_t;
|
||||
|
||||
static int mdacols[256][2][2];
|
||||
|
||||
void hercules_recalctimings(hercules_t *hercules);
|
||||
void hercules_write(uint32_t addr, uint8_t val, void *p);
|
||||
uint8_t hercules_read(uint32_t addr, void *p);
|
||||
|
||||
|
||||
void hercules_out(uint16_t addr, uint8_t val, void *p)
|
||||
{
|
||||
hercules_t *hercules = (hercules_t *)p;
|
||||
switch (addr)
|
||||
{
|
||||
case 0x3b0: case 0x3b2: case 0x3b4: case 0x3b6:
|
||||
hercules->crtcreg = val & 31;
|
||||
return;
|
||||
case 0x3b1: case 0x3b3: case 0x3b5: case 0x3b7:
|
||||
hercules->crtc[hercules->crtcreg] = val;
|
||||
if (hercules->crtc[10] == 6 && hercules->crtc[11] == 7) /*Fix for Generic Turbo XT BIOS, which sets up cursor registers wrong*/
|
||||
{
|
||||
hercules->crtc[10] = 0xb;
|
||||
hercules->crtc[11] = 0xc;
|
||||
}
|
||||
hercules_recalctimings(hercules);
|
||||
return;
|
||||
case 0x3b8:
|
||||
hercules->ctrl = val;
|
||||
return;
|
||||
case 0x3bf:
|
||||
hercules->ctrl2 = val;
|
||||
if (val & 2)
|
||||
mem_mapping_set_addr(&hercules->mapping, 0xb0000, 0x10000);
|
||||
else
|
||||
mem_mapping_set_addr(&hercules->mapping, 0xb0000, 0x08000);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t hercules_in(uint16_t addr, void *p)
|
||||
{
|
||||
hercules_t *hercules = (hercules_t *)p;
|
||||
switch (addr)
|
||||
{
|
||||
case 0x3b0: case 0x3b2: case 0x3b4: case 0x3b6:
|
||||
return hercules->crtcreg;
|
||||
case 0x3b1: case 0x3b3: case 0x3b5: case 0x3b7:
|
||||
return hercules->crtc[hercules->crtcreg];
|
||||
case 0x3ba:
|
||||
return (hercules->stat & 0xf) | ((hercules->stat & 8) << 4);
|
||||
}
|
||||
return 0xff;
|
||||
}
|
||||
|
||||
void hercules_write(uint32_t addr, uint8_t val, void *p)
|
||||
{
|
||||
hercules_t *hercules = (hercules_t *)p;
|
||||
egawrites++;
|
||||
hercules->vram[addr & 0xffff] = val;
|
||||
}
|
||||
|
||||
uint8_t hercules_read(uint32_t addr, void *p)
|
||||
{
|
||||
hercules_t *hercules = (hercules_t *)p;
|
||||
egareads++;
|
||||
return hercules->vram[addr & 0xffff];
|
||||
}
|
||||
|
||||
void hercules_recalctimings(hercules_t *hercules)
|
||||
{
|
||||
double disptime;
|
||||
double _dispontime, _dispofftime;
|
||||
disptime = hercules->crtc[0] + 1;
|
||||
_dispontime = hercules->crtc[1];
|
||||
_dispofftime = disptime - _dispontime;
|
||||
_dispontime *= MDACONST;
|
||||
_dispofftime *= MDACONST;
|
||||
hercules->dispontime = (int64_t)(_dispontime * (1 << TIMER_SHIFT));
|
||||
hercules->dispofftime = (int64_t)(_dispofftime * (1 << TIMER_SHIFT));
|
||||
}
|
||||
|
||||
void hercules_poll(void *p)
|
||||
{
|
||||
hercules_t *hercules = (hercules_t *)p;
|
||||
uint16_t ca = (hercules->crtc[15] | (hercules->crtc[14] << 8)) & 0x3fff;
|
||||
int drawcursor;
|
||||
int x, c;
|
||||
int oldvc;
|
||||
uint8_t chr, attr;
|
||||
uint16_t dat;
|
||||
int oldsc;
|
||||
int blink;
|
||||
if (!hercules->linepos)
|
||||
{
|
||||
hercules->vidtime += hercules->dispofftime;
|
||||
hercules->stat |= 1;
|
||||
hercules->linepos = 1;
|
||||
oldsc = hercules->sc;
|
||||
if ((hercules->crtc[8] & 3) == 3)
|
||||
hercules->sc = (hercules->sc << 1) & 7;
|
||||
if (hercules->dispon)
|
||||
{
|
||||
if (hercules->displine < hercules->firstline)
|
||||
{
|
||||
hercules->firstline = hercules->displine;
|
||||
video_wait_for_buffer();
|
||||
}
|
||||
hercules->lastline = hercules->displine;
|
||||
if ((hercules->ctrl & 2) && (hercules->ctrl2 & 1))
|
||||
{
|
||||
ca = (hercules->sc & 3) * 0x2000;
|
||||
if ((hercules->ctrl & 0x80) && (hercules->ctrl2 & 2))
|
||||
ca += 0x8000;
|
||||
// printf("Draw herc %04X\n",ca);
|
||||
for (x = 0; x < hercules->crtc[1]; x++)
|
||||
{
|
||||
dat = (hercules->vram[((hercules->ma << 1) & 0x1fff) + ca] << 8) | hercules->vram[((hercules->ma << 1) & 0x1fff) + ca + 1];
|
||||
hercules->ma++;
|
||||
for (c = 0; c < 16; c++)
|
||||
buffer->line[hercules->displine][(x << 4) + c] = (dat & (32768 >> c)) ? 7 : 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (x = 0; x < hercules->crtc[1]; x++)
|
||||
{
|
||||
chr = hercules->vram[(hercules->ma << 1) & 0xfff];
|
||||
attr = hercules->vram[((hercules->ma << 1) + 1) & 0xfff];
|
||||
drawcursor = ((hercules->ma == ca) && hercules->con && hercules->cursoron);
|
||||
blink = ((hercules->blink & 16) && (hercules->ctrl & 0x20) && (attr & 0x80) && !drawcursor);
|
||||
if (hercules->sc == 12 && ((attr & 7) == 1))
|
||||
{
|
||||
for (c = 0; c < 9; c++)
|
||||
buffer->line[hercules->displine][(x * 9) + c] = mdacols[attr][blink][1];
|
||||
}
|
||||
else
|
||||
{
|
||||
for (c = 0; c < 8; c++)
|
||||
buffer->line[hercules->displine][(x * 9) + c] = mdacols[attr][blink][(fontdatm[chr][hercules->sc] & (1 << (c ^ 7))) ? 1 : 0];
|
||||
if ((chr & ~0x1f) == 0xc0) buffer->line[hercules->displine][(x * 9) + 8] = mdacols[attr][blink][fontdatm[chr][hercules->sc] & 1];
|
||||
else buffer->line[hercules->displine][(x * 9) + 8] = mdacols[attr][blink][0];
|
||||
}
|
||||
hercules->ma++;
|
||||
if (drawcursor)
|
||||
{
|
||||
for (c = 0; c < 9; c++)
|
||||
buffer->line[hercules->displine][(x * 9) + c] ^= mdacols[attr][0][1];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
hercules->sc = oldsc;
|
||||
if (hercules->vc == hercules->crtc[7] && !hercules->sc)
|
||||
{
|
||||
hercules->stat |= 8;
|
||||
// printf("VSYNC on %i %i\n",vc,sc);
|
||||
}
|
||||
hercules->displine++;
|
||||
if (hercules->displine >= 500)
|
||||
hercules->displine = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
hercules->vidtime += hercules->dispontime;
|
||||
if (hercules->dispon)
|
||||
hercules->stat &= ~1;
|
||||
hercules->linepos = 0;
|
||||
if (hercules->vsynctime)
|
||||
{
|
||||
hercules->vsynctime--;
|
||||
if (!hercules->vsynctime)
|
||||
{
|
||||
hercules->stat &= ~8;
|
||||
// printf("VSYNC off %i %i\n",vc,sc);
|
||||
}
|
||||
}
|
||||
if (hercules->sc == (hercules->crtc[11] & 31) || ((hercules->crtc[8] & 3) == 3 && hercules->sc == ((hercules->crtc[11] & 31) >> 1)))
|
||||
{
|
||||
hercules->con = 0;
|
||||
hercules->coff = 1;
|
||||
}
|
||||
if (hercules->vadj)
|
||||
{
|
||||
hercules->sc++;
|
||||
hercules->sc &= 31;
|
||||
hercules->ma = hercules->maback;
|
||||
hercules->vadj--;
|
||||
if (!hercules->vadj)
|
||||
{
|
||||
hercules->dispon = 1;
|
||||
hercules->ma = hercules->maback = (hercules->crtc[13] | (hercules->crtc[12] << 8)) & 0x3fff;
|
||||
hercules->sc = 0;
|
||||
}
|
||||
}
|
||||
else if (hercules->sc == hercules->crtc[9] || ((hercules->crtc[8] & 3) == 3 && hercules->sc == (hercules->crtc[9] >> 1)))
|
||||
{
|
||||
hercules->maback = hercules->ma;
|
||||
hercules->sc = 0;
|
||||
oldvc = hercules->vc;
|
||||
hercules->vc++;
|
||||
hercules->vc &= 127;
|
||||
if (hercules->vc == hercules->crtc[6])
|
||||
hercules->dispon = 0;
|
||||
if (oldvc == hercules->crtc[4])
|
||||
{
|
||||
// printf("Display over at %i\n",displine);
|
||||
hercules->vc = 0;
|
||||
hercules->vadj = hercules->crtc[5];
|
||||
if (!hercules->vadj) hercules->dispon=1;
|
||||
if (!hercules->vadj) hercules->ma = hercules->maback = (hercules->crtc[13] | (hercules->crtc[12] << 8)) & 0x3fff;
|
||||
if ((hercules->crtc[10] & 0x60) == 0x20) hercules->cursoron = 0;
|
||||
else hercules->cursoron = hercules->blink & 16;
|
||||
}
|
||||
if (hercules->vc == hercules->crtc[7])
|
||||
{
|
||||
hercules->dispon = 0;
|
||||
hercules->displine = 0;
|
||||
hercules->vsynctime = 16;//(crtcm[3]>>4)+1;
|
||||
if (hercules->crtc[7])
|
||||
{
|
||||
// printf("Lastline %i Firstline %i %i\n",lastline,firstline,lastline-firstline);
|
||||
if ((hercules->ctrl & 2) && (hercules->ctrl2 & 1)) x = hercules->crtc[1] << 4;
|
||||
else x = hercules->crtc[1] * 9;
|
||||
hercules->lastline++;
|
||||
if ((x != xsize) || ((hercules->lastline - hercules->firstline) != ysize) || video_force_resize_get())
|
||||
{
|
||||
xsize = x;
|
||||
ysize = hercules->lastline - hercules->firstline;
|
||||
// printf("Resize to %i,%i - R1 %i\n",xsize,ysize,crtcm[1]);
|
||||
if (xsize < 64) xsize = 656;
|
||||
if (ysize < 32) ysize = 200;
|
||||
set_screen_size(xsize, ysize);
|
||||
|
||||
if (video_force_resize_get())
|
||||
video_force_resize_set(0);
|
||||
}
|
||||
video_blit_memtoscreen_8(0, hercules->firstline, 0, ysize, xsize, ysize);
|
||||
frames++;
|
||||
if ((hercules->ctrl & 2) && (hercules->ctrl2 & 1))
|
||||
{
|
||||
video_res_x = hercules->crtc[1] * 16;
|
||||
video_res_y = hercules->crtc[6] * 4;
|
||||
video_bpp = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
video_res_x = hercules->crtc[1];
|
||||
video_res_y = hercules->crtc[6];
|
||||
video_bpp = 0;
|
||||
}
|
||||
}
|
||||
hercules->firstline = 1000;
|
||||
hercules->lastline = 0;
|
||||
hercules->blink++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
hercules->sc++;
|
||||
hercules->sc &= 31;
|
||||
hercules->ma = hercules->maback;
|
||||
}
|
||||
if ((hercules->sc == (hercules->crtc[10] & 31) || ((hercules->crtc[8] & 3) == 3 && hercules->sc == ((hercules->crtc[10] & 31) >> 1))))
|
||||
{
|
||||
hercules->con = 1;
|
||||
// printf("Cursor on - %02X %02X %02X\n",crtcm[8],crtcm[10],crtcm[11]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void *hercules_init(const device_t *info)
|
||||
{
|
||||
int c;
|
||||
hercules_t *hercules = malloc(sizeof(hercules_t));
|
||||
memset(hercules, 0, sizeof(hercules_t));
|
||||
|
||||
hercules->vram = malloc(0x10000);
|
||||
|
||||
timer_add(hercules_poll, &hercules->vidtime, TIMER_ALWAYS_ENABLED, hercules);
|
||||
mem_mapping_add(&hercules->mapping, 0xb0000, 0x08000, hercules_read, NULL, NULL, hercules_write, NULL, NULL, NULL, MEM_MAPPING_EXTERNAL, hercules);
|
||||
io_sethandler(0x03b0, 0x0010, hercules_in, NULL, NULL, hercules_out, NULL, NULL, hercules);
|
||||
|
||||
for (c = 0; c < 256; c++)
|
||||
{
|
||||
mdacols[c][0][0] = mdacols[c][1][0] = mdacols[c][1][1] = 16;
|
||||
if (c & 8) mdacols[c][0][1] = 15 + 16;
|
||||
else mdacols[c][0][1] = 7 + 16;
|
||||
}
|
||||
mdacols[0x70][0][1] = 16;
|
||||
mdacols[0x70][0][0] = mdacols[0x70][1][0] = mdacols[0x70][1][1] = 16 + 15;
|
||||
mdacols[0xF0][0][1] = 16;
|
||||
mdacols[0xF0][0][0] = mdacols[0xF0][1][0] = mdacols[0xF0][1][1] = 16 + 15;
|
||||
mdacols[0x78][0][1] = 16 + 7;
|
||||
mdacols[0x78][0][0] = mdacols[0x78][1][0] = mdacols[0x78][1][1] = 16 + 15;
|
||||
mdacols[0xF8][0][1] = 16 + 7;
|
||||
mdacols[0xF8][0][0] = mdacols[0xF8][1][0] = mdacols[0xF8][1][1] = 16 + 15;
|
||||
mdacols[0x00][0][1] = mdacols[0x00][1][1] = 16;
|
||||
mdacols[0x08][0][1] = mdacols[0x08][1][1] = 16;
|
||||
mdacols[0x80][0][1] = mdacols[0x80][1][1] = 16;
|
||||
mdacols[0x88][0][1] = mdacols[0x88][1][1] = 16;
|
||||
|
||||
overscan_x = overscan_y = 0;
|
||||
|
||||
cga_palette = device_get_config_int("rgb_type") << 1;
|
||||
if (cga_palette > 6)
|
||||
{
|
||||
cga_palette = 0;
|
||||
}
|
||||
cgapal_rebuild();
|
||||
|
||||
lpt3_init(0x3BC);
|
||||
|
||||
return hercules;
|
||||
}
|
||||
|
||||
void hercules_close(void *p)
|
||||
{
|
||||
hercules_t *hercules = (hercules_t *)p;
|
||||
|
||||
free(hercules->vram);
|
||||
free(hercules);
|
||||
}
|
||||
|
||||
void hercules_speed_changed(void *p)
|
||||
{
|
||||
hercules_t *hercules = (hercules_t *)p;
|
||||
|
||||
hercules_recalctimings(hercules);
|
||||
}
|
||||
|
||||
static const device_config_t hercules_config[] =
|
||||
{
|
||||
{
|
||||
"rgb_type", "Display type", CONFIG_SELECTION, "", 0,
|
||||
{
|
||||
{
|
||||
"Default", 0
|
||||
},
|
||||
{
|
||||
"Green", 1
|
||||
},
|
||||
{
|
||||
"Amber", 2
|
||||
},
|
||||
{
|
||||
"Gray", 3
|
||||
},
|
||||
{
|
||||
""
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"", "", -1
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
const device_t hercules_device =
|
||||
{
|
||||
"Hercules",
|
||||
DEVICE_ISA, 0,
|
||||
hercules_init, hercules_close, NULL,
|
||||
NULL,
|
||||
hercules_speed_changed,
|
||||
NULL,
|
||||
hercules_config
|
||||
};
|
||||
4
backup code/video - Cópia/vid_hercules.h
Normal file
4
backup code/video - Cópia/vid_hercules.h
Normal file
@@ -0,0 +1,4 @@
|
||||
/* Copyright holders: Sarah Walker
|
||||
see COPYING for more details
|
||||
*/
|
||||
extern const device_t hercules_device;
|
||||
739
backup code/video - Cópia/vid_herculesplus.c
Normal file
739
backup code/video - Cópia/vid_herculesplus.c
Normal file
@@ -0,0 +1,739 @@
|
||||
/*
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
*
|
||||
* This file is part of the 86Box distribution.
|
||||
*
|
||||
* Hercules InColor emulation.
|
||||
*
|
||||
* Version: @(#)vid_herculesplus.c 1.0.9 2018/04/29
|
||||
*
|
||||
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
*
|
||||
* Copyright 2008-2018 Sarah Walker.
|
||||
* Copyright 2016-2018 Miran Grca.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <wchar.h>
|
||||
#include "../86box.h"
|
||||
#include "../io.h"
|
||||
#include "../lpt.h"
|
||||
#include "../pit.h"
|
||||
#include "../mem.h"
|
||||
#include "../rom.h"
|
||||
#include "../timer.h"
|
||||
#include "../device.h"
|
||||
#include "video.h"
|
||||
#include "vid_herculesplus.h"
|
||||
|
||||
|
||||
/* extended CRTC registers */
|
||||
|
||||
#define HERCULESPLUS_CRTC_XMODE 20 /* xMode register */
|
||||
#define HERCULESPLUS_CRTC_UNDER 21 /* Underline */
|
||||
#define HERCULESPLUS_CRTC_OVER 22 /* Overstrike */
|
||||
|
||||
/* character width */
|
||||
#define HERCULESPLUS_CW ((herculesplus->crtc[HERCULESPLUS_CRTC_XMODE] & HERCULESPLUS_XMODE_90COL) ? 8 : 9)
|
||||
|
||||
/* mode control register */
|
||||
#define HERCULESPLUS_CTRL_GRAPH 0x02
|
||||
#define HERCULESPLUS_CTRL_ENABLE 0x08
|
||||
#define HERCULESPLUS_CTRL_BLINK 0x20
|
||||
#define HERCULESPLUS_CTRL_PAGE1 0x80
|
||||
|
||||
/* CRTC status register */
|
||||
#define HERCULESPLUS_STATUS_HSYNC 0x01 /* horizontal sync */
|
||||
#define HERCULESPLUS_STATUS_LIGHT 0x02
|
||||
#define HERCULESPLUS_STATUS_VIDEO 0x08
|
||||
#define HERCULESPLUS_STATUS_ID 0x10 /* Card identification */
|
||||
#define HERCULESPLUS_STATUS_VSYNC 0x80 /* -vertical sync */
|
||||
|
||||
/* configuration switch register */
|
||||
#define HERCULESPLUS_CTRL2_GRAPH 0x01
|
||||
#define HERCULESPLUS_CTRL2_PAGE1 0x02
|
||||
|
||||
/* extended mode register */
|
||||
#define HERCULESPLUS_XMODE_RAMFONT 0x01
|
||||
#define HERCULESPLUS_XMODE_90COL 0x02
|
||||
|
||||
typedef struct herculesplus_t
|
||||
{
|
||||
mem_mapping_t mapping;
|
||||
|
||||
uint8_t crtc[32];
|
||||
int crtcreg;
|
||||
|
||||
uint8_t ctrl, ctrl2, stat;
|
||||
|
||||
int64_t dispontime, dispofftime;
|
||||
int64_t vidtime;
|
||||
|
||||
int firstline, lastline;
|
||||
|
||||
int linepos, displine;
|
||||
int vc, sc;
|
||||
uint16_t ma, maback;
|
||||
int con, coff, cursoron;
|
||||
int dispon, blink;
|
||||
int64_t vsynctime;
|
||||
int vadj;
|
||||
|
||||
uint8_t *vram;
|
||||
} herculesplus_t;
|
||||
|
||||
void herculesplus_recalctimings(herculesplus_t *herculesplus);
|
||||
void herculesplus_write(uint32_t addr, uint8_t val, void *p);
|
||||
uint8_t herculesplus_read(uint32_t addr, void *p);
|
||||
|
||||
static int mdacols[256][2][2];
|
||||
|
||||
void herculesplus_out(uint16_t addr, uint8_t val, void *p)
|
||||
{
|
||||
herculesplus_t *herculesplus = (herculesplus_t *)p;
|
||||
switch (addr)
|
||||
{
|
||||
case 0x3b0: case 0x3b2: case 0x3b4: case 0x3b6:
|
||||
herculesplus->crtcreg = val & 31;
|
||||
return;
|
||||
case 0x3b1: case 0x3b3: case 0x3b5: case 0x3b7:
|
||||
if (herculesplus->crtcreg > 22) return;
|
||||
herculesplus->crtc[herculesplus->crtcreg] = val;
|
||||
if (herculesplus->crtc[10] == 6 && herculesplus->crtc[11] == 7) /*Fix for Generic Turbo XT BIOS, which sets up cursor registers wrong*/
|
||||
{
|
||||
herculesplus->crtc[10] = 0xb;
|
||||
herculesplus->crtc[11] = 0xc;
|
||||
}
|
||||
herculesplus_recalctimings(herculesplus);
|
||||
return;
|
||||
case 0x3b8:
|
||||
herculesplus->ctrl = val;
|
||||
return;
|
||||
case 0x3bf:
|
||||
herculesplus->ctrl2 = val;
|
||||
if (val & 2)
|
||||
mem_mapping_set_addr(&herculesplus->mapping, 0xb0000, 0x10000);
|
||||
else
|
||||
mem_mapping_set_addr(&herculesplus->mapping, 0xb0000, 0x08000);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t herculesplus_in(uint16_t addr, void *p)
|
||||
{
|
||||
herculesplus_t *herculesplus = (herculesplus_t *)p;
|
||||
switch (addr)
|
||||
{
|
||||
case 0x3b0: case 0x3b2: case 0x3b4: case 0x3b6:
|
||||
return herculesplus->crtcreg;
|
||||
case 0x3b1: case 0x3b3: case 0x3b5: case 0x3b7:
|
||||
if (herculesplus->crtcreg > 22) return 0xff;
|
||||
return herculesplus->crtc[herculesplus->crtcreg];
|
||||
case 0x3ba:
|
||||
/* 0x50: InColor card identity */
|
||||
return (herculesplus->stat & 0xf) | ((herculesplus->stat & 8) << 4) | 0x10;
|
||||
}
|
||||
return 0xff;
|
||||
}
|
||||
|
||||
void herculesplus_write(uint32_t addr, uint8_t val, void *p)
|
||||
{
|
||||
herculesplus_t *herculesplus = (herculesplus_t *)p;
|
||||
|
||||
egawrites++;
|
||||
|
||||
addr &= 0xFFFF;
|
||||
|
||||
herculesplus->vram[addr] = val;
|
||||
}
|
||||
|
||||
uint8_t herculesplus_read(uint32_t addr, void *p)
|
||||
{
|
||||
herculesplus_t *herculesplus = (herculesplus_t *)p;
|
||||
|
||||
egareads++;
|
||||
|
||||
addr &= 0xFFFF;
|
||||
return herculesplus->vram[addr];
|
||||
}
|
||||
|
||||
|
||||
|
||||
void herculesplus_recalctimings(herculesplus_t *herculesplus)
|
||||
{
|
||||
double disptime;
|
||||
double _dispontime, _dispofftime;
|
||||
disptime = herculesplus->crtc[0] + 1;
|
||||
_dispontime = herculesplus->crtc[1];
|
||||
_dispofftime = disptime - _dispontime;
|
||||
_dispontime *= MDACONST;
|
||||
_dispofftime *= MDACONST;
|
||||
herculesplus->dispontime = (int64_t)(_dispontime * (1 << TIMER_SHIFT));
|
||||
herculesplus->dispofftime = (int64_t)(_dispofftime * (1 << TIMER_SHIFT));
|
||||
}
|
||||
|
||||
|
||||
static void herculesplus_draw_char_rom(herculesplus_t *herculesplus, int x, uint8_t chr, uint8_t attr)
|
||||
{
|
||||
unsigned i;
|
||||
int elg, blk;
|
||||
unsigned ull;
|
||||
unsigned val;
|
||||
unsigned ifg, ibg;
|
||||
const unsigned char *fnt;
|
||||
int cw = HERCULESPLUS_CW;
|
||||
|
||||
blk = 0;
|
||||
if (herculesplus->ctrl & HERCULESPLUS_CTRL_BLINK)
|
||||
{
|
||||
if (attr & 0x80)
|
||||
{
|
||||
blk = (herculesplus->blink & 16);
|
||||
}
|
||||
attr &= 0x7f;
|
||||
}
|
||||
|
||||
/* MDA-compatible attributes */
|
||||
ibg = 0;
|
||||
ifg = 7;
|
||||
if ((attr & 0x77) == 0x70) /* Invert */
|
||||
{
|
||||
ifg = 0;
|
||||
ibg = 7;
|
||||
}
|
||||
if (attr & 8)
|
||||
{
|
||||
ifg |= 8; /* High intensity FG */
|
||||
}
|
||||
if (attr & 0x80)
|
||||
{
|
||||
ibg |= 8; /* High intensity BG */
|
||||
}
|
||||
if ((attr & 0x77) == 0) /* Blank */
|
||||
{
|
||||
ifg = ibg;
|
||||
}
|
||||
ull = ((attr & 0x07) == 1) ? 13 : 0xffff;
|
||||
|
||||
if (herculesplus->crtc[HERCULESPLUS_CRTC_XMODE] & HERCULESPLUS_XMODE_90COL)
|
||||
{
|
||||
elg = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
elg = ((chr >= 0xc0) && (chr <= 0xdf));
|
||||
}
|
||||
|
||||
fnt = &(fontdatm[chr][herculesplus->sc]);
|
||||
|
||||
if (blk)
|
||||
{
|
||||
val = 0x000; /* Blinking, draw all background */
|
||||
}
|
||||
else if (herculesplus->sc == ull)
|
||||
{
|
||||
val = 0x1ff; /* Underscore, draw all foreground */
|
||||
}
|
||||
else
|
||||
{
|
||||
val = fnt[0] << 1;
|
||||
|
||||
if (elg)
|
||||
{
|
||||
val |= (val >> 1) & 1;
|
||||
}
|
||||
}
|
||||
for (i = 0; i < cw; i++)
|
||||
{
|
||||
buffer->line[herculesplus->displine][x * cw + i] = (val & 0x100) ? ifg : ibg;
|
||||
val = val << 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void herculesplus_draw_char_ram4(herculesplus_t *herculesplus, int x, uint8_t chr, uint8_t attr)
|
||||
{
|
||||
unsigned i;
|
||||
int elg, blk;
|
||||
unsigned ull;
|
||||
unsigned val;
|
||||
unsigned ifg, ibg, cfg;
|
||||
const unsigned char *fnt;
|
||||
int cw = HERCULESPLUS_CW;
|
||||
int blink = herculesplus->ctrl & HERCULESPLUS_CTRL_BLINK;
|
||||
|
||||
blk = 0;
|
||||
if (blink)
|
||||
{
|
||||
if (attr & 0x80)
|
||||
{
|
||||
blk = (herculesplus->blink & 16);
|
||||
}
|
||||
attr &= 0x7f;
|
||||
}
|
||||
|
||||
/* MDA-compatible attributes */
|
||||
ibg = 0;
|
||||
ifg = 7;
|
||||
if ((attr & 0x77) == 0x70) /* Invert */
|
||||
{
|
||||
ifg = 0;
|
||||
ibg = 7;
|
||||
}
|
||||
if (attr & 8)
|
||||
{
|
||||
ifg |= 8; /* High intensity FG */
|
||||
}
|
||||
if (attr & 0x80)
|
||||
{
|
||||
ibg |= 8; /* High intensity BG */
|
||||
}
|
||||
if ((attr & 0x77) == 0) /* Blank */
|
||||
{
|
||||
ifg = ibg;
|
||||
}
|
||||
ull = ((attr & 0x07) == 1) ? 13 : 0xffff;
|
||||
if (herculesplus->crtc[HERCULESPLUS_CRTC_XMODE] & HERCULESPLUS_XMODE_90COL)
|
||||
{
|
||||
elg = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
elg = ((chr >= 0xc0) && (chr <= 0xdf));
|
||||
}
|
||||
fnt = herculesplus->vram + 0x4000 + 16 * chr + herculesplus->sc;
|
||||
|
||||
if (blk)
|
||||
{
|
||||
/* Blinking, draw all background */
|
||||
val = 0x000;
|
||||
}
|
||||
else if (herculesplus->sc == ull)
|
||||
{
|
||||
/* Underscore, draw all foreground */
|
||||
val = 0x1ff;
|
||||
}
|
||||
else
|
||||
{
|
||||
val = fnt[0x00000] << 1;
|
||||
|
||||
if (elg)
|
||||
{
|
||||
val |= (val >> 1) & 1;
|
||||
}
|
||||
}
|
||||
for (i = 0; i < cw; i++)
|
||||
{
|
||||
/* Generate pixel colour */
|
||||
cfg = 0;
|
||||
/* cfg = colour of foreground pixels */
|
||||
if ((attr & 0x77) == 0) cfg = ibg; /* 'blank' attribute */
|
||||
|
||||
buffer->line[herculesplus->displine][x * cw + i] = mdacols[attr][blink][cfg];
|
||||
val = val << 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void herculesplus_draw_char_ram48(herculesplus_t *herculesplus, int x, uint8_t chr, uint8_t attr)
|
||||
{
|
||||
unsigned i;
|
||||
int elg, blk, ul, ol, bld;
|
||||
unsigned ull, oll, ulc = 0, olc = 0;
|
||||
unsigned val;
|
||||
unsigned ibg, cfg;
|
||||
const unsigned char *fnt;
|
||||
int cw = HERCULESPLUS_CW;
|
||||
int blink = herculesplus->ctrl & HERCULESPLUS_CTRL_BLINK;
|
||||
int font = (attr & 0x0F);
|
||||
|
||||
if (font >= 12) font &= 7;
|
||||
|
||||
blk = 0;
|
||||
if (blink)
|
||||
{
|
||||
if (attr & 0x40)
|
||||
{
|
||||
blk = (herculesplus->blink & 16);
|
||||
}
|
||||
attr &= 0x7f;
|
||||
}
|
||||
/* MDA-compatible attributes */
|
||||
if (blink)
|
||||
{
|
||||
ibg = (attr & 0x80) ? 8 : 0;
|
||||
bld = 0;
|
||||
ol = (attr & 0x20) ? 1 : 0;
|
||||
ul = (attr & 0x10) ? 1 : 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
bld = (attr & 0x80) ? 1 : 0;
|
||||
ibg = (attr & 0x40) ? 0x0F : 0;
|
||||
ol = (attr & 0x20) ? 1 : 0;
|
||||
ul = (attr & 0x10) ? 1 : 0;
|
||||
}
|
||||
if (ul)
|
||||
{
|
||||
ull = herculesplus->crtc[HERCULESPLUS_CRTC_UNDER] & 0x0F;
|
||||
ulc = (herculesplus->crtc[HERCULESPLUS_CRTC_UNDER] >> 4) & 0x0F;
|
||||
if (ulc == 0) ulc = 7;
|
||||
}
|
||||
else
|
||||
{
|
||||
ull = 0xFFFF;
|
||||
}
|
||||
if (ol)
|
||||
{
|
||||
oll = herculesplus->crtc[HERCULESPLUS_CRTC_OVER] & 0x0F;
|
||||
olc = (herculesplus->crtc[HERCULESPLUS_CRTC_OVER] >> 4) & 0x0F;
|
||||
if (olc == 0) olc = 7;
|
||||
}
|
||||
else
|
||||
{
|
||||
oll = 0xFFFF;
|
||||
}
|
||||
|
||||
if (herculesplus->crtc[HERCULESPLUS_CRTC_XMODE] & HERCULESPLUS_XMODE_90COL)
|
||||
{
|
||||
elg = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
elg = ((chr >= 0xc0) && (chr <= 0xdf));
|
||||
}
|
||||
fnt = herculesplus->vram + 0x4000 + 16 * chr + 4096 * font + herculesplus->sc;
|
||||
|
||||
if (blk)
|
||||
{
|
||||
/* Blinking, draw all background */
|
||||
val = 0x000;
|
||||
}
|
||||
else if (herculesplus->sc == ull)
|
||||
{
|
||||
/* Underscore, draw all foreground */
|
||||
val = 0x1ff;
|
||||
}
|
||||
else
|
||||
{
|
||||
val = fnt[0x00000] << 1;
|
||||
|
||||
if (elg)
|
||||
{
|
||||
val |= (val >> 1) & 1;
|
||||
}
|
||||
if (bld)
|
||||
{
|
||||
val |= (val >> 1);
|
||||
}
|
||||
}
|
||||
for (i = 0; i < cw; i++)
|
||||
{
|
||||
/* Generate pixel colour */
|
||||
cfg = val & 0x100;
|
||||
if (herculesplus->sc == oll)
|
||||
{
|
||||
cfg = olc ^ ibg; /* Strikethrough */
|
||||
}
|
||||
else if (herculesplus->sc == ull)
|
||||
{
|
||||
cfg = ulc ^ ibg; /* Underline */
|
||||
}
|
||||
else
|
||||
{
|
||||
cfg |= ibg;
|
||||
}
|
||||
|
||||
buffer->line[herculesplus->displine][(x * cw) + i] = mdacols[attr][blink][cfg];
|
||||
val = val << 1;
|
||||
}
|
||||
}
|
||||
|
||||
static void herculesplus_text_line(herculesplus_t *herculesplus, uint16_t ca)
|
||||
{
|
||||
int drawcursor;
|
||||
int x, c;
|
||||
uint8_t chr, attr;
|
||||
uint32_t col;
|
||||
|
||||
for (x = 0; x < herculesplus->crtc[1]; x++)
|
||||
{
|
||||
chr = herculesplus->vram[(herculesplus->ma << 1) & 0xfff];
|
||||
attr = herculesplus->vram[((herculesplus->ma << 1) + 1) & 0xfff];
|
||||
|
||||
drawcursor = ((herculesplus->ma == ca) && herculesplus->con && herculesplus->cursoron);
|
||||
|
||||
switch (herculesplus->crtc[HERCULESPLUS_CRTC_XMODE] & 5)
|
||||
{
|
||||
case 0:
|
||||
case 4: /* ROM font */
|
||||
herculesplus_draw_char_rom(herculesplus, x, chr, attr);
|
||||
break;
|
||||
case 1: /* 4k RAMfont */
|
||||
herculesplus_draw_char_ram4(herculesplus, x, chr, attr);
|
||||
break;
|
||||
case 5: /* 48k RAMfont */
|
||||
herculesplus_draw_char_ram48(herculesplus, x, chr, attr);
|
||||
break;
|
||||
|
||||
}
|
||||
++herculesplus->ma;
|
||||
if (drawcursor)
|
||||
{
|
||||
int cw = HERCULESPLUS_CW;
|
||||
|
||||
col = mdacols[attr][0][1];
|
||||
for (c = 0; c < cw; c++)
|
||||
{
|
||||
((uint32_t *)buffer32->line[herculesplus->displine])[x * cw + c] = col;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void herculesplus_graphics_line(herculesplus_t *herculesplus)
|
||||
{
|
||||
uint16_t ca;
|
||||
int x, c, plane = 0;
|
||||
uint16_t val;
|
||||
|
||||
/* Graphics mode. */
|
||||
ca = (herculesplus->sc & 3) * 0x2000;
|
||||
if ((herculesplus->ctrl & HERCULESPLUS_CTRL_PAGE1) && (herculesplus->ctrl2 & HERCULESPLUS_CTRL2_PAGE1))
|
||||
ca += 0x8000;
|
||||
|
||||
for (x = 0; x < herculesplus->crtc[1]; x++)
|
||||
{
|
||||
val = (herculesplus->vram[((herculesplus->ma << 1) & 0x1fff) + ca + 0x10000 * plane] << 8)
|
||||
| herculesplus->vram[((herculesplus->ma << 1) & 0x1fff) + ca + 0x10000 * plane + 1];
|
||||
|
||||
herculesplus->ma++;
|
||||
for (c = 0; c < 16; c++)
|
||||
{
|
||||
val >>= 1;
|
||||
|
||||
((uint32_t *)buffer32->line[herculesplus->displine])[(x << 4) + c] = (val & 1) ? 7 : 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void herculesplus_poll(void *p)
|
||||
{
|
||||
herculesplus_t *herculesplus = (herculesplus_t *)p;
|
||||
uint16_t ca = (herculesplus->crtc[15] | (herculesplus->crtc[14] << 8)) & 0x3fff;
|
||||
int x;
|
||||
int oldvc;
|
||||
int oldsc;
|
||||
|
||||
if (!herculesplus->linepos)
|
||||
{
|
||||
herculesplus->vidtime += herculesplus->dispofftime;
|
||||
herculesplus->stat |= 1;
|
||||
herculesplus->linepos = 1;
|
||||
oldsc = herculesplus->sc;
|
||||
if ((herculesplus->crtc[8] & 3) == 3)
|
||||
herculesplus->sc = (herculesplus->sc << 1) & 7;
|
||||
if (herculesplus->dispon)
|
||||
{
|
||||
if (herculesplus->displine < herculesplus->firstline)
|
||||
{
|
||||
herculesplus->firstline = herculesplus->displine;
|
||||
video_wait_for_buffer();
|
||||
}
|
||||
herculesplus->lastline = herculesplus->displine;
|
||||
if ((herculesplus->ctrl & HERCULESPLUS_CTRL_GRAPH) && (herculesplus->ctrl2 & HERCULESPLUS_CTRL2_GRAPH))
|
||||
{
|
||||
herculesplus_graphics_line(herculesplus);
|
||||
}
|
||||
else
|
||||
{
|
||||
herculesplus_text_line(herculesplus, ca);
|
||||
}
|
||||
}
|
||||
herculesplus->sc = oldsc;
|
||||
if (herculesplus->vc == herculesplus->crtc[7] && !herculesplus->sc)
|
||||
{
|
||||
herculesplus->stat |= 8;
|
||||
}
|
||||
herculesplus->displine++;
|
||||
if (herculesplus->displine >= 500)
|
||||
herculesplus->displine = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
herculesplus->vidtime += herculesplus->dispontime;
|
||||
if (herculesplus->dispon)
|
||||
herculesplus->stat &= ~1;
|
||||
herculesplus->linepos = 0;
|
||||
if (herculesplus->vsynctime)
|
||||
{
|
||||
herculesplus->vsynctime--;
|
||||
if (!herculesplus->vsynctime)
|
||||
{
|
||||
herculesplus->stat &= ~8;
|
||||
}
|
||||
}
|
||||
if (herculesplus->sc == (herculesplus->crtc[11] & 31) || ((herculesplus->crtc[8] & 3) == 3 && herculesplus->sc == ((herculesplus->crtc[11] & 31) >> 1)))
|
||||
{
|
||||
herculesplus->con = 0;
|
||||
herculesplus->coff = 1;
|
||||
}
|
||||
if (herculesplus->vadj)
|
||||
{
|
||||
herculesplus->sc++;
|
||||
herculesplus->sc &= 31;
|
||||
herculesplus->ma = herculesplus->maback;
|
||||
herculesplus->vadj--;
|
||||
if (!herculesplus->vadj)
|
||||
{
|
||||
herculesplus->dispon = 1;
|
||||
herculesplus->ma = herculesplus->maback = (herculesplus->crtc[13] | (herculesplus->crtc[12] << 8)) & 0x3fff;
|
||||
herculesplus->sc = 0;
|
||||
}
|
||||
}
|
||||
else if (herculesplus->sc == herculesplus->crtc[9] || ((herculesplus->crtc[8] & 3) == 3 && herculesplus->sc == (herculesplus->crtc[9] >> 1)))
|
||||
{
|
||||
herculesplus->maback = herculesplus->ma;
|
||||
herculesplus->sc = 0;
|
||||
oldvc = herculesplus->vc;
|
||||
herculesplus->vc++;
|
||||
herculesplus->vc &= 127;
|
||||
if (herculesplus->vc == herculesplus->crtc[6])
|
||||
herculesplus->dispon = 0;
|
||||
if (oldvc == herculesplus->crtc[4])
|
||||
{
|
||||
herculesplus->vc = 0;
|
||||
herculesplus->vadj = herculesplus->crtc[5];
|
||||
if (!herculesplus->vadj) herculesplus->dispon=1;
|
||||
if (!herculesplus->vadj) herculesplus->ma = herculesplus->maback = (herculesplus->crtc[13] | (herculesplus->crtc[12] << 8)) & 0x3fff;
|
||||
if ((herculesplus->crtc[10] & 0x60) == 0x20) herculesplus->cursoron = 0;
|
||||
else herculesplus->cursoron = herculesplus->blink & 16;
|
||||
}
|
||||
if (herculesplus->vc == herculesplus->crtc[7])
|
||||
{
|
||||
herculesplus->dispon = 0;
|
||||
herculesplus->displine = 0;
|
||||
herculesplus->vsynctime = 16;
|
||||
if (herculesplus->crtc[7])
|
||||
{
|
||||
if ((herculesplus->ctrl & HERCULESPLUS_CTRL_GRAPH) && (herculesplus->ctrl2 & HERCULESPLUS_CTRL2_GRAPH))
|
||||
{
|
||||
x = herculesplus->crtc[1] << 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
x = herculesplus->crtc[1] * 9;
|
||||
}
|
||||
herculesplus->lastline++;
|
||||
if ((x != xsize) || ((herculesplus->lastline - herculesplus->firstline) != ysize) || video_force_resize_get())
|
||||
{
|
||||
xsize = x;
|
||||
ysize = herculesplus->lastline - herculesplus->firstline;
|
||||
if (xsize < 64) xsize = 656;
|
||||
if (ysize < 32) ysize = 200;
|
||||
set_screen_size(xsize, ysize);
|
||||
|
||||
if (video_force_resize_get())
|
||||
video_force_resize_set(0);
|
||||
}
|
||||
video_blit_memtoscreen(0, herculesplus->firstline, 0, herculesplus->lastline - herculesplus->firstline, xsize, herculesplus->lastline - herculesplus->firstline);
|
||||
frames++;
|
||||
if ((herculesplus->ctrl & HERCULESPLUS_CTRL_GRAPH) && (herculesplus->ctrl2 & HERCULESPLUS_CTRL2_GRAPH))
|
||||
{
|
||||
video_res_x = herculesplus->crtc[1] * 16;
|
||||
video_res_y = herculesplus->crtc[6] * 4;
|
||||
video_bpp = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
video_res_x = herculesplus->crtc[1];
|
||||
video_res_y = herculesplus->crtc[6];
|
||||
video_bpp = 0;
|
||||
}
|
||||
}
|
||||
herculesplus->firstline = 1000;
|
||||
herculesplus->lastline = 0;
|
||||
herculesplus->blink++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
herculesplus->sc++;
|
||||
herculesplus->sc &= 31;
|
||||
herculesplus->ma = herculesplus->maback;
|
||||
}
|
||||
if ((herculesplus->sc == (herculesplus->crtc[10] & 31) || ((herculesplus->crtc[8] & 3) == 3 && herculesplus->sc == ((herculesplus->crtc[10] & 31) >> 1))))
|
||||
{
|
||||
herculesplus->con = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void *herculesplus_init(const device_t *info)
|
||||
{
|
||||
int c;
|
||||
herculesplus_t *herculesplus = malloc(sizeof(herculesplus_t));
|
||||
memset(herculesplus, 0, sizeof(herculesplus_t));
|
||||
|
||||
herculesplus->vram = malloc(0x10000); /* 64k VRAM */
|
||||
|
||||
timer_add(herculesplus_poll, &herculesplus->vidtime, TIMER_ALWAYS_ENABLED, herculesplus);
|
||||
mem_mapping_add(&herculesplus->mapping, 0xb0000, 0x10000, herculesplus_read, NULL, NULL, herculesplus_write, NULL, NULL, NULL, MEM_MAPPING_EXTERNAL, herculesplus);
|
||||
io_sethandler(0x03b0, 0x0010, herculesplus_in, NULL, NULL, herculesplus_out, NULL, NULL, herculesplus);
|
||||
|
||||
for (c = 0; c < 256; c++)
|
||||
{
|
||||
mdacols[c][0][0] = mdacols[c][1][0] = mdacols[c][1][1] = 16;
|
||||
if (c & 8) mdacols[c][0][1] = 15 + 16;
|
||||
else mdacols[c][0][1] = 7 + 16;
|
||||
}
|
||||
mdacols[0x70][0][1] = 16;
|
||||
mdacols[0x70][0][0] = mdacols[0x70][1][0] = mdacols[0x70][1][1] = 16 + 15;
|
||||
mdacols[0xF0][0][1] = 16;
|
||||
mdacols[0xF0][0][0] = mdacols[0xF0][1][0] = mdacols[0xF0][1][1] = 16 + 15;
|
||||
mdacols[0x78][0][1] = 16 + 7;
|
||||
mdacols[0x78][0][0] = mdacols[0x78][1][0] = mdacols[0x78][1][1] = 16 + 15;
|
||||
mdacols[0xF8][0][1] = 16 + 7;
|
||||
mdacols[0xF8][0][0] = mdacols[0xF8][1][0] = mdacols[0xF8][1][1] = 16 + 15;
|
||||
mdacols[0x00][0][1] = mdacols[0x00][1][1] = 16;
|
||||
mdacols[0x08][0][1] = mdacols[0x08][1][1] = 16;
|
||||
mdacols[0x80][0][1] = mdacols[0x80][1][1] = 16;
|
||||
mdacols[0x88][0][1] = mdacols[0x88][1][1] = 16;
|
||||
|
||||
lpt3_init(0x3BC);
|
||||
|
||||
return herculesplus;
|
||||
}
|
||||
|
||||
void herculesplus_close(void *p)
|
||||
{
|
||||
herculesplus_t *herculesplus = (herculesplus_t *)p;
|
||||
|
||||
free(herculesplus->vram);
|
||||
free(herculesplus);
|
||||
}
|
||||
|
||||
void herculesplus_speed_changed(void *p)
|
||||
{
|
||||
herculesplus_t *herculesplus = (herculesplus_t *)p;
|
||||
|
||||
herculesplus_recalctimings(herculesplus);
|
||||
}
|
||||
|
||||
const device_t herculesplus_device =
|
||||
{
|
||||
"Hercules Plus",
|
||||
DEVICE_ISA, 0,
|
||||
herculesplus_init, herculesplus_close, NULL,
|
||||
NULL,
|
||||
herculesplus_speed_changed,
|
||||
NULL,
|
||||
NULL
|
||||
};
|
||||
4
backup code/video - Cópia/vid_herculesplus.h
Normal file
4
backup code/video - Cópia/vid_herculesplus.h
Normal file
@@ -0,0 +1,4 @@
|
||||
/* Copyright holders: John Elliott
|
||||
see COPYING for more details
|
||||
*/
|
||||
extern const device_t herculesplus_device;
|
||||
80
backup code/video - Cópia/vid_icd2061.c
Normal file
80
backup code/video - Cópia/vid_icd2061.c
Normal file
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
*
|
||||
* This file is part of the 86Box distribution.
|
||||
*
|
||||
* ICD2061 clock generator emulation.
|
||||
*
|
||||
* Used by ET4000w32/p (Diamond Stealth 32)
|
||||
*
|
||||
* Version: @(#)vid_icd2061.c 1.0.2 2017/11/04
|
||||
*
|
||||
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
*
|
||||
* Copyright 2008-2017 Sarah Walker.
|
||||
* Copyright 2016,2017 Miran Grca.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <wchar.h>
|
||||
#include "../86box.h"
|
||||
#include "vid_icd2061.h"
|
||||
|
||||
|
||||
void icd2061_write(icd2061_t *icd2061, int val)
|
||||
{
|
||||
int q, p, m, a;
|
||||
if ((val & 1) && !(icd2061->state & 1))
|
||||
{
|
||||
if (!icd2061->status)
|
||||
{
|
||||
if (val & 2)
|
||||
icd2061->unlock++;
|
||||
else
|
||||
{
|
||||
if (icd2061->unlock >= 5)
|
||||
{
|
||||
icd2061->status = 1;
|
||||
icd2061->pos = 0;
|
||||
}
|
||||
else
|
||||
icd2061->unlock = 0;
|
||||
}
|
||||
}
|
||||
else if (val & 1)
|
||||
{
|
||||
icd2061->data = (icd2061->data >> 1) | (((val & 2) ? 1 : 0) << 24);
|
||||
icd2061->pos++;
|
||||
if (icd2061->pos == 26)
|
||||
{
|
||||
a = (icd2061->data >> 21) & 0x7;
|
||||
if (!(a & 4))
|
||||
{
|
||||
q = (icd2061->data & 0x7f) - 2;
|
||||
m = 1 << ((icd2061->data >> 7) & 0x7);
|
||||
p = ((icd2061->data >> 10) & 0x7f) - 3;
|
||||
if (icd2061->ctrl & (1 << a))
|
||||
p <<= 1;
|
||||
icd2061->freq[a] = ((double)p / (double)q) * 2.0 * 14318184.0 / (double)m;
|
||||
}
|
||||
else if (a == 6)
|
||||
{
|
||||
icd2061->ctrl = val;
|
||||
}
|
||||
icd2061->unlock = icd2061->data = 0;
|
||||
icd2061->status = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
icd2061->state = val;
|
||||
}
|
||||
|
||||
double icd2061_getfreq(icd2061_t *icd2061, int i)
|
||||
{
|
||||
return icd2061->freq[i];
|
||||
}
|
||||
17
backup code/video - Cópia/vid_icd2061.h
Normal file
17
backup code/video - Cópia/vid_icd2061.h
Normal file
@@ -0,0 +1,17 @@
|
||||
/* Copyright holders: Sarah Walker
|
||||
see COPYING for more details
|
||||
*/
|
||||
typedef struct icd2061_t
|
||||
{
|
||||
int state;
|
||||
int status;
|
||||
int pos;
|
||||
int unlock;
|
||||
uint32_t data;
|
||||
|
||||
double freq[4];
|
||||
uint32_t ctrl;
|
||||
} icd2061_t;
|
||||
|
||||
void icd2061_write(icd2061_t *icd2061, int val);
|
||||
double icd2061_getfreq(icd2061_t *icd2061, int i);
|
||||
73
backup code/video - Cópia/vid_ics2595.c
Normal file
73
backup code/video - Cópia/vid_ics2595.c
Normal file
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
*
|
||||
* This file is part of the 86Box distribution.
|
||||
*
|
||||
* ICS2595 clock chip emulation. Used by ATI Mach64.
|
||||
*
|
||||
* Version: @(#)vid_ics2595.c 1.0.2 2017/11/04
|
||||
*
|
||||
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
*
|
||||
* Copyright 2008-2017 Sarah Walker.
|
||||
* Copyright 2016,2017 Miran Grca.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <wchar.h>
|
||||
#include "../86box.h"
|
||||
#include "vid_ics2595.h"
|
||||
|
||||
|
||||
enum
|
||||
{
|
||||
ICS2595_IDLE = 0,
|
||||
ICS2595_WRITE,
|
||||
ICS2595_READ
|
||||
};
|
||||
|
||||
|
||||
static int ics2595_div[4] = {8, 4, 2, 1};
|
||||
|
||||
|
||||
void ics2595_write(ics2595_t *ics2595, int strobe, int dat)
|
||||
{
|
||||
if (strobe)
|
||||
{
|
||||
if ((dat & 8) && !ics2595->oldfs3) /*Data clock*/
|
||||
{
|
||||
switch (ics2595->state)
|
||||
{
|
||||
case ICS2595_IDLE:
|
||||
ics2595->state = (dat & 4) ? ICS2595_WRITE : ICS2595_IDLE;
|
||||
ics2595->pos = 0;
|
||||
break;
|
||||
case ICS2595_WRITE:
|
||||
ics2595->dat = (ics2595->dat >> 1);
|
||||
if (dat & 4)
|
||||
ics2595->dat |= (1 << 19);
|
||||
ics2595->pos++;
|
||||
if (ics2595->pos == 20)
|
||||
{
|
||||
int d, n, l;
|
||||
l = (ics2595->dat >> 2) & 0xf;
|
||||
n = ((ics2595->dat >> 7) & 255) + 257;
|
||||
d = ics2595_div[(ics2595->dat >> 16) & 3];
|
||||
|
||||
ics2595->clocks[l] = (14318181.8 * ((double)n / 46.0)) / (double)d;
|
||||
ics2595->state = ICS2595_IDLE;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ics2595->oldfs2 = dat & 4;
|
||||
ics2595->oldfs3 = dat & 8;
|
||||
}
|
||||
ics2595->output_clock = ics2595->clocks[dat];
|
||||
}
|
||||
15
backup code/video - Cópia/vid_ics2595.h
Normal file
15
backup code/video - Cópia/vid_ics2595.h
Normal file
@@ -0,0 +1,15 @@
|
||||
/* Copyright holders: Sarah Walker
|
||||
see COPYING for more details
|
||||
*/
|
||||
typedef struct ics2595_t
|
||||
{
|
||||
int oldfs3, oldfs2;
|
||||
int dat;
|
||||
int pos;
|
||||
int state;
|
||||
|
||||
double clocks[16];
|
||||
double output_clock;
|
||||
} ics2595_t;
|
||||
|
||||
void ics2595_write(ics2595_t *ics2595, int strobe, int dat);
|
||||
1083
backup code/video - Cópia/vid_incolor.c
Normal file
1083
backup code/video - Cópia/vid_incolor.c
Normal file
File diff suppressed because it is too large
Load Diff
4
backup code/video - Cópia/vid_incolor.h
Normal file
4
backup code/video - Cópia/vid_incolor.h
Normal file
@@ -0,0 +1,4 @@
|
||||
/* Copyright holders: John Elliott
|
||||
see COPYING for more details
|
||||
*/
|
||||
extern const device_t incolor_device;
|
||||
380
backup code/video - Cópia/vid_mda.c
Normal file
380
backup code/video - Cópia/vid_mda.c
Normal file
@@ -0,0 +1,380 @@
|
||||
/*
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
*
|
||||
* This file is part of the 86Box distribution.
|
||||
*
|
||||
* MDA emulation.
|
||||
*
|
||||
* Version: @(#)vid_mda.c 1.0.11 2018/04/26
|
||||
*
|
||||
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
*
|
||||
* Copyright 2008-2018 Sarah Walker.
|
||||
* Copyright 2016-2018 Miran Grca.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <wchar.h>
|
||||
#include "../86box.h"
|
||||
#include "../io.h"
|
||||
#include "../lpt.h"
|
||||
#include "../pit.h"
|
||||
#include "../mem.h"
|
||||
#include "../rom.h"
|
||||
#include "../timer.h"
|
||||
#include "../device.h"
|
||||
#include "video.h"
|
||||
#include "vid_mda.h"
|
||||
|
||||
|
||||
typedef struct mda_t
|
||||
{
|
||||
mem_mapping_t mapping;
|
||||
|
||||
uint8_t crtc[32];
|
||||
int crtcreg;
|
||||
|
||||
uint8_t ctrl, stat;
|
||||
|
||||
int64_t dispontime, dispofftime;
|
||||
int64_t vidtime;
|
||||
|
||||
int firstline, lastline;
|
||||
|
||||
int linepos, displine;
|
||||
int vc, sc;
|
||||
uint16_t ma, maback;
|
||||
int con, coff, cursoron;
|
||||
int dispon, blink;
|
||||
int64_t vsynctime;
|
||||
int vadj;
|
||||
|
||||
uint8_t *vram;
|
||||
} mda_t;
|
||||
|
||||
static int mdacols[256][2][2];
|
||||
|
||||
void mda_recalctimings(mda_t *mda);
|
||||
|
||||
void mda_out(uint16_t addr, uint8_t val, void *p)
|
||||
{
|
||||
mda_t *mda = (mda_t *)p;
|
||||
switch (addr)
|
||||
{
|
||||
case 0x3b0: case 0x3b2: case 0x3b4: case 0x3b6:
|
||||
mda->crtcreg = val & 31;
|
||||
return;
|
||||
case 0x3b1: case 0x3b3: case 0x3b5: case 0x3b7:
|
||||
mda->crtc[mda->crtcreg] = val;
|
||||
if (mda->crtc[10] == 6 && mda->crtc[11] == 7) /*Fix for Generic Turbo XT BIOS, which sets up cursor registers wrong*/
|
||||
{
|
||||
mda->crtc[10] = 0xb;
|
||||
mda->crtc[11] = 0xc;
|
||||
}
|
||||
mda_recalctimings(mda);
|
||||
return;
|
||||
case 0x3b8:
|
||||
mda->ctrl = val;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t mda_in(uint16_t addr, void *p)
|
||||
{
|
||||
mda_t *mda = (mda_t *)p;
|
||||
switch (addr)
|
||||
{
|
||||
case 0x3b0: case 0x3b2: case 0x3b4: case 0x3b6:
|
||||
return mda->crtcreg;
|
||||
case 0x3b1: case 0x3b3: case 0x3b5: case 0x3b7:
|
||||
return mda->crtc[mda->crtcreg];
|
||||
case 0x3ba:
|
||||
return mda->stat | 0xF0;
|
||||
}
|
||||
return 0xff;
|
||||
}
|
||||
|
||||
void mda_write(uint32_t addr, uint8_t val, void *p)
|
||||
{
|
||||
mda_t *mda = (mda_t *)p;
|
||||
egawrites++;
|
||||
mda->vram[addr & 0xfff] = val;
|
||||
}
|
||||
|
||||
uint8_t mda_read(uint32_t addr, void *p)
|
||||
{
|
||||
mda_t *mda = (mda_t *)p;
|
||||
egareads++;
|
||||
return mda->vram[addr & 0xfff];
|
||||
}
|
||||
|
||||
void mda_recalctimings(mda_t *mda)
|
||||
{
|
||||
double _dispontime, _dispofftime, disptime;
|
||||
disptime = mda->crtc[0] + 1;
|
||||
_dispontime = mda->crtc[1];
|
||||
_dispofftime = disptime - _dispontime;
|
||||
_dispontime *= MDACONST;
|
||||
_dispofftime *= MDACONST;
|
||||
mda->dispontime = (int64_t)(_dispontime * (1 << TIMER_SHIFT));
|
||||
mda->dispofftime = (int64_t)(_dispofftime * (1 << TIMER_SHIFT));
|
||||
}
|
||||
|
||||
void mda_poll(void *p)
|
||||
{
|
||||
mda_t *mda = (mda_t *)p;
|
||||
uint16_t ca = (mda->crtc[15] | (mda->crtc[14] << 8)) & 0x3fff;
|
||||
int drawcursor;
|
||||
int x, c;
|
||||
int oldvc;
|
||||
uint8_t chr, attr;
|
||||
int oldsc;
|
||||
int blink;
|
||||
if (!mda->linepos)
|
||||
{
|
||||
mda->vidtime += mda->dispofftime;
|
||||
mda->stat |= 1;
|
||||
mda->linepos = 1;
|
||||
oldsc = mda->sc;
|
||||
if ((mda->crtc[8] & 3) == 3)
|
||||
mda->sc = (mda->sc << 1) & 7;
|
||||
if (mda->dispon)
|
||||
{
|
||||
if (mda->displine < mda->firstline)
|
||||
{
|
||||
mda->firstline = mda->displine;
|
||||
}
|
||||
mda->lastline = mda->displine;
|
||||
for (x = 0; x < mda->crtc[1]; x++)
|
||||
{
|
||||
chr = mda->vram[(mda->ma << 1) & 0xfff];
|
||||
attr = mda->vram[((mda->ma << 1) + 1) & 0xfff];
|
||||
drawcursor = ((mda->ma == ca) && mda->con && mda->cursoron);
|
||||
blink = ((mda->blink & 16) && (mda->ctrl & 0x20) && (attr & 0x80) && !drawcursor);
|
||||
if (mda->sc == 12 && ((attr & 7) == 1))
|
||||
{
|
||||
for (c = 0; c < 9; c++)
|
||||
buffer->line[mda->displine][(x * 9) + c] = mdacols[attr][blink][1];
|
||||
}
|
||||
else
|
||||
{
|
||||
for (c = 0; c < 8; c++)
|
||||
buffer->line[mda->displine][(x * 9) + c] = mdacols[attr][blink][(fontdatm[chr][mda->sc] & (1 << (c ^ 7))) ? 1 : 0];
|
||||
if ((chr & ~0x1f) == 0xc0) buffer->line[mda->displine][(x * 9) + 8] = mdacols[attr][blink][fontdatm[chr][mda->sc] & 1];
|
||||
else buffer->line[mda->displine][(x * 9) + 8] = mdacols[attr][blink][0];
|
||||
}
|
||||
mda->ma++;
|
||||
if (drawcursor)
|
||||
{
|
||||
for (c = 0; c < 9; c++)
|
||||
buffer->line[mda->displine][(x * 9) + c] ^= mdacols[attr][0][1];
|
||||
}
|
||||
}
|
||||
}
|
||||
mda->sc = oldsc;
|
||||
if (mda->vc == mda->crtc[7] && !mda->sc)
|
||||
{
|
||||
mda->stat |= 8;
|
||||
}
|
||||
mda->displine++;
|
||||
if (mda->displine >= 500)
|
||||
mda->displine=0;
|
||||
}
|
||||
else
|
||||
{
|
||||
mda->vidtime += mda->dispontime;
|
||||
if (mda->dispon) mda->stat&=~1;
|
||||
mda->linepos=0;
|
||||
if (mda->vsynctime)
|
||||
{
|
||||
mda->vsynctime--;
|
||||
if (!mda->vsynctime)
|
||||
{
|
||||
mda->stat&=~8;
|
||||
}
|
||||
}
|
||||
if (mda->sc == (mda->crtc[11] & 31) || ((mda->crtc[8] & 3) == 3 && mda->sc == ((mda->crtc[11] & 31) >> 1)))
|
||||
{
|
||||
mda->con = 0;
|
||||
mda->coff = 1;
|
||||
}
|
||||
if (mda->vadj)
|
||||
{
|
||||
mda->sc++;
|
||||
mda->sc &= 31;
|
||||
mda->ma = mda->maback;
|
||||
mda->vadj--;
|
||||
if (!mda->vadj)
|
||||
{
|
||||
mda->dispon = 1;
|
||||
mda->ma = mda->maback = (mda->crtc[13] | (mda->crtc[12] << 8)) & 0x3fff;
|
||||
mda->sc = 0;
|
||||
}
|
||||
}
|
||||
else if (mda->sc == mda->crtc[9] || ((mda->crtc[8] & 3) == 3 && mda->sc == (mda->crtc[9] >> 1)))
|
||||
{
|
||||
mda->maback = mda->ma;
|
||||
mda->sc = 0;
|
||||
oldvc = mda->vc;
|
||||
mda->vc++;
|
||||
mda->vc &= 127;
|
||||
if (mda->vc == mda->crtc[6])
|
||||
mda->dispon=0;
|
||||
if (oldvc == mda->crtc[4])
|
||||
{
|
||||
mda->vc = 0;
|
||||
mda->vadj = mda->crtc[5];
|
||||
if (!mda->vadj) mda->dispon = 1;
|
||||
if (!mda->vadj) mda->ma = mda->maback = (mda->crtc[13] | (mda->crtc[12] << 8)) & 0x3fff;
|
||||
if ((mda->crtc[10] & 0x60) == 0x20) mda->cursoron = 0;
|
||||
else mda->cursoron = mda->blink & 16;
|
||||
}
|
||||
if (mda->vc == mda->crtc[7])
|
||||
{
|
||||
mda->dispon = 0;
|
||||
mda->displine = 0;
|
||||
mda->vsynctime = 16;
|
||||
if (mda->crtc[7])
|
||||
{
|
||||
x = mda->crtc[1] * 9;
|
||||
mda->lastline++;
|
||||
if ((x != xsize) || ((mda->lastline - mda->firstline) != ysize) || video_force_resize_get())
|
||||
{
|
||||
xsize = x;
|
||||
ysize = mda->lastline - mda->firstline;
|
||||
if (xsize < 64) xsize = 656;
|
||||
if (ysize < 32) ysize = 200;
|
||||
set_screen_size(xsize, ysize);
|
||||
|
||||
if (video_force_resize_get())
|
||||
video_force_resize_set(0);
|
||||
}
|
||||
video_blit_memtoscreen_8(0, mda->firstline, 0, ysize, xsize, ysize);
|
||||
frames++;
|
||||
video_res_x = mda->crtc[1];
|
||||
video_res_y = mda->crtc[6];
|
||||
video_bpp = 0;
|
||||
}
|
||||
mda->firstline = 1000;
|
||||
mda->lastline = 0;
|
||||
mda->blink++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mda->sc++;
|
||||
mda->sc &= 31;
|
||||
mda->ma = mda->maback;
|
||||
}
|
||||
if ((mda->sc == (mda->crtc[10] & 31) || ((mda->crtc[8] & 3) == 3 && mda->sc == ((mda->crtc[10] & 31) >> 1))))
|
||||
{
|
||||
mda->con = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void *mda_init(const device_t *info)
|
||||
{
|
||||
int c;
|
||||
mda_t *mda = malloc(sizeof(mda_t));
|
||||
memset(mda, 0, sizeof(mda_t));
|
||||
|
||||
mda->vram = malloc(0x1000);
|
||||
|
||||
timer_add(mda_poll, &mda->vidtime, TIMER_ALWAYS_ENABLED, mda);
|
||||
mem_mapping_add(&mda->mapping, 0xb0000, 0x08000, mda_read, NULL, NULL, mda_write, NULL, NULL, NULL, MEM_MAPPING_EXTERNAL, mda);
|
||||
io_sethandler(0x03b0, 0x0010, mda_in, NULL, NULL, mda_out, NULL, NULL, mda);
|
||||
|
||||
for (c = 0; c < 256; c++)
|
||||
{
|
||||
mdacols[c][0][0] = mdacols[c][1][0] = mdacols[c][1][1] = 16;
|
||||
if (c & 8) mdacols[c][0][1] = 15 + 16;
|
||||
else mdacols[c][0][1] = 7 + 16;
|
||||
}
|
||||
mdacols[0x70][0][1] = 16;
|
||||
mdacols[0x70][0][0] = mdacols[0x70][1][0] = mdacols[0x70][1][1] = 16 + 15;
|
||||
mdacols[0xF0][0][1] = 16;
|
||||
mdacols[0xF0][0][0] = mdacols[0xF0][1][0] = mdacols[0xF0][1][1] = 16 + 15;
|
||||
mdacols[0x78][0][1] = 16 + 7;
|
||||
mdacols[0x78][0][0] = mdacols[0x78][1][0] = mdacols[0x78][1][1] = 16 + 15;
|
||||
mdacols[0xF8][0][1] = 16 + 7;
|
||||
mdacols[0xF8][0][0] = mdacols[0xF8][1][0] = mdacols[0xF8][1][1] = 16 + 15;
|
||||
mdacols[0x00][0][1] = mdacols[0x00][1][1] = 16;
|
||||
mdacols[0x08][0][1] = mdacols[0x08][1][1] = 16;
|
||||
mdacols[0x80][0][1] = mdacols[0x80][1][1] = 16;
|
||||
mdacols[0x88][0][1] = mdacols[0x88][1][1] = 16;
|
||||
|
||||
overscan_x = overscan_y = 0;
|
||||
|
||||
cga_palette = device_get_config_int("rgb_type") << 1;
|
||||
if (cga_palette > 6)
|
||||
{
|
||||
cga_palette = 0;
|
||||
}
|
||||
cgapal_rebuild();
|
||||
|
||||
lpt3_init(0x3BC);
|
||||
|
||||
return mda;
|
||||
}
|
||||
|
||||
void mda_close(void *p)
|
||||
{
|
||||
mda_t *mda = (mda_t *)p;
|
||||
|
||||
free(mda->vram);
|
||||
free(mda);
|
||||
}
|
||||
|
||||
void mda_speed_changed(void *p)
|
||||
{
|
||||
mda_t *mda = (mda_t *)p;
|
||||
|
||||
mda_recalctimings(mda);
|
||||
}
|
||||
|
||||
static const device_config_t mda_config[] =
|
||||
{
|
||||
{
|
||||
"rgb_type", "Display type", CONFIG_SELECTION, "", 0,
|
||||
{
|
||||
{
|
||||
"Default", 0
|
||||
},
|
||||
{
|
||||
"Green", 1
|
||||
},
|
||||
{
|
||||
"Amber", 2
|
||||
},
|
||||
{
|
||||
"Gray", 3
|
||||
},
|
||||
{
|
||||
""
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"", "", -1
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
const device_t mda_device =
|
||||
{
|
||||
"MDA",
|
||||
DEVICE_ISA, 0,
|
||||
mda_init, mda_close, NULL,
|
||||
NULL,
|
||||
mda_speed_changed,
|
||||
NULL,
|
||||
mda_config
|
||||
};
|
||||
4
backup code/video - Cópia/vid_mda.h
Normal file
4
backup code/video - Cópia/vid_mda.h
Normal file
@@ -0,0 +1,4 @@
|
||||
/* Copyright holders: Sarah Walker
|
||||
see COPYING for more details
|
||||
*/
|
||||
extern const device_t mda_device;
|
||||
3711
backup code/video - Cópia/vid_nv_riva128.c
Normal file
3711
backup code/video - Cópia/vid_nv_riva128.c
Normal file
File diff suppressed because it is too large
Load Diff
3
backup code/video - Cópia/vid_nv_riva128.h
Normal file
3
backup code/video - Cópia/vid_nv_riva128.h
Normal file
@@ -0,0 +1,3 @@
|
||||
extern const device_t riva128_device;
|
||||
extern const device_t rivatnt_device;
|
||||
extern const device_t rivatnt2_device;
|
||||
965
backup code/video - Cópia/vid_nvidia.c
Normal file
965
backup code/video - Cópia/vid_nvidia.c
Normal file
@@ -0,0 +1,965 @@
|
||||
/*
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
*
|
||||
* This file is part of the 86Box distribution.
|
||||
*
|
||||
* nVidia RIVA 128 emulation.
|
||||
*
|
||||
* Version: @(#)vid_nv_riva128.c 1.0.7 2018/04/29
|
||||
*
|
||||
* Author: Melissa Goad
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
*
|
||||
* Copyright 2015-2018 Melissa Goad.
|
||||
* Copyright 2015-2018 Miran Grca.
|
||||
*/
|
||||
#include <stdarg.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <wchar.h>
|
||||
#define HAVE_STDARG_H
|
||||
#include "../86box.h"
|
||||
#include "../cpu/cpu.h"
|
||||
#include "../machine/machine.h"
|
||||
#include "../io.h"
|
||||
#include "../mem.h"
|
||||
#include "../pci.h"
|
||||
#include "../pic.h"
|
||||
#include "../rom.h"
|
||||
#include "../timer.h"
|
||||
#include "../device.h"
|
||||
#include "../plat.h"
|
||||
#include "video.h"
|
||||
#include "vid_nv_riva128.h"
|
||||
#include "vid_svga.h"
|
||||
#include "vid_svga_render.h"
|
||||
|
||||
typedef struct riva128_t
|
||||
{
|
||||
mem_mapping_t linear_mapping;
|
||||
mem_mapping_t mmio_mapping;
|
||||
|
||||
rom_t bios_rom;
|
||||
|
||||
svga_t svga;
|
||||
|
||||
uint8_t card_id;
|
||||
int pci_card;
|
||||
int is_nv3t;
|
||||
|
||||
uint16_t vendor_id;
|
||||
uint16_t device_id;
|
||||
|
||||
uint32_t linear_base, linear_size;
|
||||
|
||||
uint16_t rma_addr;
|
||||
|
||||
uint8_t pci_regs[256];
|
||||
|
||||
int memory_size;
|
||||
|
||||
uint8_t ext_regs_locked;
|
||||
|
||||
uint8_t read_bank;
|
||||
uint8_t write_bank;
|
||||
|
||||
struct
|
||||
{
|
||||
uint32_t intr;
|
||||
uint32_t intr_en;
|
||||
uint32_t intr_line;
|
||||
uint32_t enable;
|
||||
} pmc;
|
||||
|
||||
struct
|
||||
{
|
||||
uint32_t intr;
|
||||
uint32_t intr_en;
|
||||
} pbus;
|
||||
|
||||
struct
|
||||
{
|
||||
uint32_t cache_error;
|
||||
uint32_t intr;
|
||||
uint32_t intr_en;
|
||||
|
||||
uint32_t ramht;
|
||||
uint32_t ramht_addr;
|
||||
uint32_t ramht_size;
|
||||
|
||||
uint32_t ramfc;
|
||||
uint32_t ramfc_addr;
|
||||
|
||||
uint32_t ramro;
|
||||
uint32_t ramro_addr;
|
||||
uint32_t ramro_size;
|
||||
|
||||
uint16_t chan_mode;
|
||||
uint16_t chan_dma;
|
||||
uint16_t chan_size; //0 = 1024, 1 = 512
|
||||
|
||||
uint32_t runout_put, runout_get;
|
||||
|
||||
struct
|
||||
{
|
||||
uint32_t dmaput;
|
||||
uint32_t dmaget;
|
||||
} channels[16];
|
||||
|
||||
struct
|
||||
{
|
||||
int chanid;
|
||||
int push_enabled;
|
||||
int runout;
|
||||
uint32_t get, put;
|
||||
uint32_t ctx;
|
||||
} caches[2];
|
||||
|
||||
struct
|
||||
{
|
||||
int subchan;
|
||||
uint16_t method;
|
||||
uint32_t param;
|
||||
} cache0, cache1[64];
|
||||
} pfifo;
|
||||
|
||||
struct
|
||||
{
|
||||
uint32_t addr;
|
||||
uint32_t data;
|
||||
uint8_t access_reg[4];
|
||||
uint8_t mode;
|
||||
} rma;
|
||||
|
||||
struct
|
||||
{
|
||||
uint32_t intr, intr_en;
|
||||
|
||||
uint64_t time;
|
||||
uint32_t alarm;
|
||||
|
||||
uint16_t clock_mul, clock_div;
|
||||
} ptimer;
|
||||
|
||||
struct
|
||||
{
|
||||
int width;
|
||||
int bpp;
|
||||
uint32_t config_0;
|
||||
} pfb;
|
||||
|
||||
struct
|
||||
{
|
||||
uint32_t boot_0;
|
||||
} pextdev;
|
||||
|
||||
struct
|
||||
{
|
||||
int pgraph_speedhack;
|
||||
|
||||
uint32_t obj_handle[8];
|
||||
uint16_t obj_class[8];
|
||||
|
||||
uint32_t debug[5];
|
||||
|
||||
uint32_t intr;
|
||||
uint32_t intr_en;
|
||||
|
||||
uint32_t invalid;
|
||||
uint32_t invalid_en;
|
||||
|
||||
uint32_t ctx_switch[5];
|
||||
uint32_t ctx_control;
|
||||
uint32_t ctx_user;
|
||||
uint32_t ctx_cache[8][5];
|
||||
|
||||
uint32_t fifo_enable;
|
||||
|
||||
uint32_t fifo_st2_addr;
|
||||
uint32_t fifo_st2_data;
|
||||
|
||||
uint32_t uclip_xmin, uclip_ymin, uclip_xmax, uclip_ymax;
|
||||
uint32_t oclip_xmin, oclip_ymin, oclip_xmax, oclip_ymax;
|
||||
|
||||
uint32_t src_canvas_min, src_canvas_max;
|
||||
uint32_t dst_canvas_min, dst_canvas_max;
|
||||
|
||||
uint8_t rop;
|
||||
|
||||
uint32_t chroma;
|
||||
|
||||
uint32_t beta;
|
||||
|
||||
uint32_t notify;
|
||||
|
||||
//NV3
|
||||
uint32_t surf_offset[4];
|
||||
uint32_t surf_pitch[4];
|
||||
|
||||
uint32_t cliprect_min[2];
|
||||
uint32_t cliprect_max[2];
|
||||
uint32_t cliprect_ctrl;
|
||||
|
||||
uint32_t instance;
|
||||
|
||||
uint32_t dma_intr, dma_intr_en;
|
||||
|
||||
uint32_t status;
|
||||
} pgraph;
|
||||
|
||||
struct
|
||||
{
|
||||
uint32_t nvpll;
|
||||
uint32_t nv_m,nv_n,nv_p;
|
||||
|
||||
uint32_t mpll;
|
||||
uint32_t m_m,m_n,m_p;
|
||||
|
||||
uint32_t vpll;
|
||||
uint32_t v_m,v_n,v_p;
|
||||
|
||||
uint32_t pll_ctrl;
|
||||
|
||||
uint32_t gen_ctrl;
|
||||
} pramdac;
|
||||
|
||||
uint32_t channels[16][8][0x2000];
|
||||
|
||||
struct
|
||||
{
|
||||
int scl;
|
||||
int sda;
|
||||
} i2c;
|
||||
|
||||
int64_t mtime, mfreq;
|
||||
} riva128_t;
|
||||
|
||||
|
||||
#ifdef ENABLE_NVIDIA_LOG
|
||||
int nvidia_do_log = ENABLE_NVIDIA_LOG;
|
||||
#endif
|
||||
|
||||
|
||||
static void
|
||||
nvidia_log(const char *fmt, ...)
|
||||
{
|
||||
#ifdef ENABLE_NVIDIA_LOG
|
||||
va_list ap;
|
||||
|
||||
if (nvidia_do_log) {
|
||||
va_start(ap, fmt);
|
||||
pclog_ex(fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
uint8_t riva128_rma_in(uint16_t addr, void *p)
|
||||
{
|
||||
riva128_t *riva128 = (riva128_t *)p;
|
||||
svga_t* svga = &riva128->svga;
|
||||
uint8_t ret = 0;
|
||||
|
||||
addr &= 0xff;
|
||||
|
||||
//nvidia_log("RIVA 128 RMA read %04X %04X:%08X\n", addr, CS, cpu_state.pc);
|
||||
|
||||
switch(addr)
|
||||
{
|
||||
case 0x00:
|
||||
ret = 0x65;
|
||||
break;
|
||||
case 0x01:
|
||||
ret = 0xd0;
|
||||
break;
|
||||
case 0x02:
|
||||
ret = 0x16;
|
||||
break;
|
||||
case 0x03:
|
||||
ret = 0x2b;
|
||||
break;
|
||||
case 0x08:
|
||||
case 0x09:
|
||||
case 0x0a:
|
||||
case 0x0b:
|
||||
if(riva128->rma.addr < 0x1000000) /*ret = riva128_mmio_read((riva128->rma.addr + (addr & 3)) & 0xffffff, riva128);*/nvidia_log("RIVA 128 MMIO write %08x %08x\n", riva128->rma.addr & 0xffffff, riva128->rma.data);
|
||||
else ret = svga_read_linear((riva128->rma.addr - 0x1000000), svga);
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void riva128_rma_out(uint16_t addr, uint8_t val, void *p)
|
||||
{
|
||||
riva128_t *riva128 = (riva128_t *)p;
|
||||
svga_t* svga = &riva128->svga;
|
||||
|
||||
addr &= 0xff;
|
||||
|
||||
//nvidia_log("RIVA 128 RMA write %04X %02X %04X:%08X\n", addr, val, CS, cpu_state.pc);
|
||||
|
||||
switch(addr)
|
||||
{
|
||||
case 0x04:
|
||||
riva128->rma.addr &= ~0xff;
|
||||
riva128->rma.addr |= val;
|
||||
break;
|
||||
case 0x05:
|
||||
riva128->rma.addr &= ~0xff00;
|
||||
riva128->rma.addr |= (val << 8);
|
||||
break;
|
||||
case 0x06:
|
||||
riva128->rma.addr &= ~0xff0000;
|
||||
riva128->rma.addr |= (val << 16);
|
||||
break;
|
||||
case 0x07:
|
||||
riva128->rma.addr &= ~0xff000000;
|
||||
riva128->rma.addr |= (val << 24);
|
||||
break;
|
||||
case 0x08:
|
||||
case 0x0c:
|
||||
case 0x10:
|
||||
case 0x14:
|
||||
riva128->rma.data &= ~0xff;
|
||||
riva128->rma.data |= val;
|
||||
break;
|
||||
case 0x09:
|
||||
case 0x0d:
|
||||
case 0x11:
|
||||
case 0x15:
|
||||
riva128->rma.data &= ~0xff00;
|
||||
riva128->rma.data |= (val << 8);
|
||||
break;
|
||||
case 0x0a:
|
||||
case 0x0e:
|
||||
case 0x12:
|
||||
case 0x16:
|
||||
riva128->rma.data &= ~0xff0000;
|
||||
riva128->rma.data |= (val << 16);
|
||||
break;
|
||||
case 0x0b:
|
||||
case 0x0f:
|
||||
case 0x13:
|
||||
case 0x17:
|
||||
riva128->rma.data &= ~0xff000000;
|
||||
riva128->rma.data |= (val << 24);
|
||||
if(riva128->rma.addr < 0x1000000) /*riva128_mmio_write_l(riva128->rma.addr & 0xffffff, riva128->rma.data, riva128);*/nvidia_log("RIVA 128 MMIO write %08x %08x\n", riva128->rma.addr & 0xffffff, riva128->rma.data);
|
||||
else svga_writel_linear((riva128->rma.addr - 0x1000000), riva128->rma.data, svga);
|
||||
break;
|
||||
}
|
||||
|
||||
if(addr & 0x10) riva128->rma.addr+=4;
|
||||
}
|
||||
|
||||
uint8_t riva128_in(uint16_t addr, void *p)
|
||||
{
|
||||
riva128_t *riva128 = (riva128_t *)p;
|
||||
svga_t* svga = &riva128->svga;
|
||||
uint8_t ret = 0;
|
||||
|
||||
if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(svga->miscout & 1))
|
||||
addr ^= 0x60;
|
||||
|
||||
// if (addr != 0x3da) nvidia_log("S3 in %04X %04X:%08X ", addr, CS, cpu_state.pc);
|
||||
switch (addr)
|
||||
{
|
||||
case 0x3D4:
|
||||
ret = svga->crtcreg;
|
||||
break;
|
||||
case 0x3D5:
|
||||
switch(svga->crtcreg)
|
||||
{
|
||||
case 0x28:
|
||||
ret = svga->crtc[0x28] & 0x3f;
|
||||
break;
|
||||
case 0x34:
|
||||
ret = svga->displine & 0xff;
|
||||
break;
|
||||
case 0x35:
|
||||
ret = (svga->displine >> 8) & 7;
|
||||
break;
|
||||
case 0x3e:
|
||||
//DDC status register
|
||||
ret = (riva128->i2c.sda << 3) | (riva128->i2c.scl << 2);
|
||||
break;
|
||||
default:
|
||||
ret = svga->crtc[svga->crtcreg];
|
||||
break;
|
||||
}
|
||||
//if(svga->crtcreg > 0x18)
|
||||
// nvidia_log("RIVA 128 Extended CRTC read %02X %04X:%08X\n", svga->crtcreg, CS, cpu_state.pc);
|
||||
break;
|
||||
default:
|
||||
ret = svga_in(addr, svga);
|
||||
break;
|
||||
}
|
||||
// if (addr != 0x3da) nvidia_log("%02X\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void riva128_out(uint16_t addr, uint8_t val, void *p)
|
||||
{
|
||||
riva128_t *riva128 = (riva128_t *)p;
|
||||
svga_t *svga = &riva128->svga;
|
||||
|
||||
uint8_t old;
|
||||
|
||||
if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(svga->miscout & 1))
|
||||
addr ^= 0x60;
|
||||
|
||||
switch(addr)
|
||||
{
|
||||
case 0x3D4:
|
||||
svga->crtcreg = val;
|
||||
return;
|
||||
case 0x3D5:
|
||||
if ((svga->crtcreg < 7) && (svga->crtc[0x11] & 0x80))
|
||||
return;
|
||||
if ((svga->crtcreg == 7) && (svga->crtc[0x11] & 0x80))
|
||||
val = (svga->crtc[7] & ~0x10) | (val & 0x10);
|
||||
old = svga->crtc[svga->crtcreg];
|
||||
svga->crtc[svga->crtcreg] = val;
|
||||
switch(svga->crtcreg)
|
||||
{
|
||||
case 0x1e:
|
||||
riva128->read_bank = val;
|
||||
if (svga->chain4) svga->read_bank = riva128->read_bank << 15;
|
||||
else svga->read_bank = riva128->read_bank << 13;
|
||||
break;
|
||||
case 0x1d:
|
||||
riva128->write_bank = val;
|
||||
if (svga->chain4) svga->write_bank = riva128->write_bank << 15;
|
||||
else svga->write_bank = riva128->write_bank << 13;
|
||||
break;
|
||||
case 0x19:
|
||||
case 0x1a:
|
||||
case 0x25:
|
||||
case 0x28:
|
||||
case 0x2d:
|
||||
svga_recalctimings(svga);
|
||||
break;
|
||||
case 0x38:
|
||||
riva128->rma.mode = val & 0xf;
|
||||
break;
|
||||
case 0x3f:
|
||||
riva128->i2c.sda = (val >> 4) & 1;
|
||||
riva128->i2c.scl = (val >> 5) & 1;
|
||||
break;
|
||||
}
|
||||
//if(svga->crtcreg > 0x18)
|
||||
// nvidia_log("RIVA 128 Extended CRTC write %02X %02x %04X:%08X\n", svga->crtcreg, val, CS, cpu_state.pc);
|
||||
if (old != val)
|
||||
{
|
||||
if (svga->crtcreg < 0xE || svga->crtcreg > 0x10)
|
||||
{
|
||||
svga->fullchange = changeframecount;
|
||||
svga_recalctimings(svga);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
svga_out(addr, val, svga);
|
||||
}
|
||||
|
||||
uint8_t riva128_pci_read(int func, int addr, void *p)
|
||||
{
|
||||
riva128_t *riva128 = (riva128_t *)p;
|
||||
uint8_t ret = 0;
|
||||
//nvidia_log("RIVA 128 PCI read %02X %04X:%08X\n", addr, CS, cpu_state.pc);
|
||||
switch (addr)
|
||||
{
|
||||
case 0x00:
|
||||
ret = riva128->vendor_id & 0xff;
|
||||
break;
|
||||
case 0x01:
|
||||
ret = riva128->vendor_id >> 8;
|
||||
break;
|
||||
|
||||
case 0x02:
|
||||
ret = riva128->device_id & 0xff;
|
||||
break;
|
||||
case 0x03:
|
||||
ret = riva128->device_id >> 8;
|
||||
break;
|
||||
|
||||
case 0x04:
|
||||
ret = riva128->pci_regs[0x04] & 0x37;
|
||||
break;
|
||||
case 0x05:
|
||||
ret = riva128->pci_regs[0x05] & 0x01;
|
||||
break;
|
||||
|
||||
case 0x06:
|
||||
ret = 0x20;
|
||||
break;
|
||||
case 0x07:
|
||||
ret = riva128->pci_regs[0x07] & 0x73;
|
||||
break;
|
||||
|
||||
case 0x08:
|
||||
ret = 0x00;
|
||||
break; /*Revision ID*/
|
||||
case 0x09:
|
||||
ret = 0;
|
||||
break; /*Programming interface*/
|
||||
|
||||
case 0x0a:
|
||||
ret = 0x00;
|
||||
break; /*Supports VGA interface*/
|
||||
case 0x0b:
|
||||
ret = 0x03; /*output = 3; */break;
|
||||
|
||||
case 0x0e:
|
||||
ret = 0x00;
|
||||
break; /*Header type*/
|
||||
|
||||
case 0x13:
|
||||
case 0x17:
|
||||
ret = riva128->pci_regs[addr];
|
||||
break;
|
||||
|
||||
case 0x2c:
|
||||
case 0x2d:
|
||||
case 0x2e:
|
||||
case 0x2f:
|
||||
ret = riva128->pci_regs[addr];
|
||||
//if(CS == 0x0028) output = 3;
|
||||
break;
|
||||
|
||||
case 0x30:
|
||||
return riva128->pci_regs[0x30] & 0x01; /*BIOS ROM address*/
|
||||
case 0x31:
|
||||
return 0x00;
|
||||
case 0x32:
|
||||
return riva128->pci_regs[0x32];
|
||||
case 0x33:
|
||||
return riva128->pci_regs[0x33];
|
||||
|
||||
case 0x34:
|
||||
ret = 0x00;
|
||||
break;
|
||||
|
||||
case 0x3c:
|
||||
ret = riva128->pci_regs[0x3c];
|
||||
break;
|
||||
|
||||
case 0x3d:
|
||||
ret = 0x01;
|
||||
break; /*INTA*/
|
||||
|
||||
case 0x3e:
|
||||
ret = 0x03;
|
||||
break;
|
||||
case 0x3f:
|
||||
ret = 0x01;
|
||||
break;
|
||||
|
||||
}
|
||||
// nvidia_log("%02X\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void riva128_reenable_svga_mappings(svga_t *svga)
|
||||
{
|
||||
switch (svga->gdcreg[6] & 0xc) /*Banked framebuffer*/
|
||||
{
|
||||
case 0x0: /*128k at A0000*/
|
||||
mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x20000);
|
||||
svga->banked_mask = 0xffff;
|
||||
break;
|
||||
case 0x4: /*64k at A0000*/
|
||||
mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x10000);
|
||||
svga->banked_mask = 0xffff;
|
||||
break;
|
||||
case 0x8: /*32k at B0000*/
|
||||
mem_mapping_set_addr(&svga->mapping, 0xb0000, 0x08000);
|
||||
svga->banked_mask = 0x7fff;
|
||||
break;
|
||||
case 0xC: /*32k at B8000*/
|
||||
mem_mapping_set_addr(&svga->mapping, 0xb8000, 0x08000);
|
||||
svga->banked_mask = 0x7fff;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void riva128_pci_write(int func, int addr, uint8_t val, void *p)
|
||||
{
|
||||
//nvidia_log("RIVA 128 PCI write %02X %02X %04X:%08X\n", addr, val, CS, cpu_state.pc);
|
||||
riva128_t *riva128 = (riva128_t *)p;
|
||||
svga_t* svga = &riva128->svga;
|
||||
switch (addr)
|
||||
{
|
||||
case 0x00:
|
||||
case 0x01:
|
||||
case 0x02:
|
||||
case 0x03:
|
||||
case 0x08:
|
||||
case 0x09:
|
||||
case 0x0a:
|
||||
case 0x0b:
|
||||
case 0x3d:
|
||||
case 0x3e:
|
||||
case 0x3f:
|
||||
return;
|
||||
|
||||
case PCI_REG_COMMAND:
|
||||
riva128->pci_regs[PCI_REG_COMMAND] = val & 0x27;
|
||||
mem_mapping_disable(&svga->mapping);
|
||||
mem_mapping_disable(&riva128->mmio_mapping);
|
||||
mem_mapping_disable(&riva128->linear_mapping);
|
||||
if (val & PCI_COMMAND_IO)
|
||||
{
|
||||
io_removehandler(0x03c0, 0x0020, riva128_in, NULL, NULL, riva128_out, NULL, NULL, riva128);
|
||||
io_sethandler(0x03c0, 0x0020, riva128_in, NULL, NULL, riva128_out, NULL, NULL, riva128);
|
||||
}
|
||||
else io_removehandler(0x03c0, 0x0020, riva128_in, NULL, NULL, riva128_out, NULL, NULL, riva128);
|
||||
if (val & PCI_COMMAND_MEM)
|
||||
{
|
||||
uint32_t mmio_addr = riva128->pci_regs[0x13] << 24;
|
||||
uint32_t linear_addr = riva128->pci_regs[0x17] << 24;
|
||||
if (!mmio_addr && !linear_addr)
|
||||
{
|
||||
riva128_reenable_svga_mappings(svga);
|
||||
}
|
||||
if (mmio_addr)
|
||||
{
|
||||
mem_mapping_set_addr(&riva128->mmio_mapping, mmio_addr, 0x1000000);
|
||||
}
|
||||
if (linear_addr)
|
||||
{
|
||||
mem_mapping_set_addr(&riva128->linear_mapping, linear_addr, 0x1000000);
|
||||
}
|
||||
}
|
||||
return;
|
||||
|
||||
case 0x05:
|
||||
riva128->pci_regs[0x05] = val & 0x01;
|
||||
return;
|
||||
|
||||
case 0x07:
|
||||
riva128->pci_regs[0x07] = (riva128->pci_regs[0x07] & 0x8f) | (val & 0x70);
|
||||
return;
|
||||
|
||||
case 0x13:
|
||||
{
|
||||
uint32_t mmio_addr;
|
||||
riva128->pci_regs[addr] = val;
|
||||
mmio_addr = riva128->pci_regs[0x13] << 24;
|
||||
mem_mapping_disable(&riva128->mmio_mapping);
|
||||
if (mmio_addr)
|
||||
{
|
||||
mem_mapping_set_addr(&riva128->mmio_mapping, mmio_addr, 0x1000000);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
case 0x17:
|
||||
{
|
||||
uint32_t linear_addr;
|
||||
riva128->pci_regs[addr] = val;
|
||||
linear_addr = riva128->pci_regs[0x17] << 24;
|
||||
mem_mapping_disable(&riva128->linear_mapping);
|
||||
if (linear_addr)
|
||||
{
|
||||
mem_mapping_set_addr(&riva128->linear_mapping, linear_addr, 0x1000000);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
case 0x30:
|
||||
case 0x32:
|
||||
case 0x33:
|
||||
riva128->pci_regs[addr] = val;
|
||||
mem_mapping_disable(&riva128->bios_rom.mapping);
|
||||
if (riva128->pci_regs[0x30] & 0x01)
|
||||
{
|
||||
uint32_t addr = (riva128->pci_regs[0x32] << 16) | (riva128->pci_regs[0x33] << 24);
|
||||
// nvidia_log("RIVA 128 bios_rom enabled at %08x\n", addr);
|
||||
mem_mapping_set_addr(&riva128->bios_rom.mapping, addr, 0x8000);
|
||||
}
|
||||
return;
|
||||
|
||||
case 0x3c:
|
||||
riva128->pci_regs[0x3c] = val & 0x0f;
|
||||
return;
|
||||
|
||||
case 0x40:
|
||||
case 0x41:
|
||||
case 0x42:
|
||||
case 0x43:
|
||||
riva128->pci_regs[addr - 0x14] = val; //0x40-0x43 are ways to write to 0x2c-0x2f
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void riva128_recalctimings(svga_t *svga)
|
||||
{
|
||||
riva128_t *riva128 = (riva128_t *)svga->p;
|
||||
|
||||
svga->ma_latch += (svga->crtc[0x19] & 0x1f) << 16;
|
||||
svga->rowoffset += (svga->crtc[0x19] & 0xe0) << 3;
|
||||
if (svga->crtc[0x25] & 0x01) svga->vtotal += 0x400;
|
||||
if (svga->crtc[0x25] & 0x02) svga->dispend += 0x400;
|
||||
if (svga->crtc[0x25] & 0x04) svga->vblankstart += 0x400;
|
||||
if (svga->crtc[0x25] & 0x08) svga->vsyncstart += 0x400;
|
||||
if (svga->crtc[0x25] & 0x10) svga->htotal += 0x100;
|
||||
if (svga->crtc[0x2d] & 0x01) svga->hdisp += 0x100;
|
||||
//The effects of the large screen bit seem to just be doubling the row offset.
|
||||
//However, these large modes still don't work. Possibly core SVGA bug? It does report 640x2 res after all.
|
||||
//if (!(svga->crtc[0x1a] & 0x04)) svga->rowoffset <<= 1;
|
||||
switch(svga->crtc[0x28] & 3)
|
||||
{
|
||||
case 1:
|
||||
svga->bpp = 8;
|
||||
svga->lowres = 0;
|
||||
svga->render = svga_render_8bpp_highres;
|
||||
break;
|
||||
case 2:
|
||||
svga->bpp = 16;
|
||||
svga->lowres = 0;
|
||||
svga->render = svga_render_16bpp_highres;
|
||||
break;
|
||||
case 3:
|
||||
svga->bpp = 32;
|
||||
svga->lowres = 0;
|
||||
svga->render = svga_render_32bpp_highres;
|
||||
break;
|
||||
}
|
||||
|
||||
/*if((svga->crtc[0x28] & 3) != 0)
|
||||
{
|
||||
if(svga->crtc[0x1a] & 2) svga_set_ramdac_type(svga, RAMDAC_6BIT);
|
||||
else svga_set_ramdac_type(svga, RAMDAC_8BIT);
|
||||
}
|
||||
else svga_set_ramdac_type(svga, RAMDAC_6BIT);*/
|
||||
|
||||
double freq;
|
||||
|
||||
if (((svga->miscout >> 2) & 2) == 2)
|
||||
{
|
||||
freq = 13500000.0;
|
||||
|
||||
if(riva128->pramdac.v_m == 0) riva128->pramdac.v_m = 1;
|
||||
else
|
||||
{
|
||||
freq = (freq * riva128->pramdac.v_n) / (1 << riva128->pramdac.v_p) / riva128->pramdac.v_m;
|
||||
//nvidia_log("RIVA 128 Pixel clock is %f Hz\n", freq);
|
||||
}
|
||||
|
||||
svga->clock = cpuclock / freq;
|
||||
}
|
||||
|
||||
if(riva128->card_id == 0x03)
|
||||
{
|
||||
freq = 13500000.0;
|
||||
|
||||
if(riva128->pramdac.m_m == 0) riva128->pramdac.m_m = 1;
|
||||
else
|
||||
{
|
||||
freq = (freq * riva128->pramdac.m_n) / (1 << riva128->pramdac.m_p) / riva128->pramdac.m_m;
|
||||
//nvidia_log("RIVA 128 Memory clock is %f Hz\n", freq);
|
||||
}
|
||||
|
||||
riva128->mfreq = freq;
|
||||
riva128->mtime = (int64_t)((TIMER_USEC * 100000000.0) / riva128->mfreq);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void *riva128_init(const device_t *info)
|
||||
{
|
||||
riva128_t *riva128 = malloc(sizeof(riva128_t));
|
||||
memset(riva128, 0, sizeof(riva128_t));
|
||||
|
||||
riva128->card_id = 0x03;
|
||||
riva128->is_nv3t = 0;
|
||||
|
||||
riva128->vendor_id = 0x12d2;
|
||||
riva128->device_id = 0x0018;
|
||||
|
||||
riva128->memory_size = device_get_config_int("memory");
|
||||
|
||||
svga_init(&riva128->svga, riva128, riva128->memory_size << 20,
|
||||
riva128_recalctimings,
|
||||
riva128_in, riva128_out,
|
||||
NULL, NULL);
|
||||
|
||||
riva128->svga.decode_mask = (riva128->memory_size << 20) - 1;
|
||||
|
||||
rom_init(&riva128->bios_rom, L"roms/video/nv_riva128/Diamond_V330_rev-e.vbi", 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL);
|
||||
if (PCI)
|
||||
mem_mapping_disable(&riva128->bios_rom.mapping);
|
||||
|
||||
/*mem_mapping_add(&riva128->mmio_mapping, 0, 0,
|
||||
riva128_mmio_read,
|
||||
riva128_mmio_read_w,
|
||||
riva128_mmio_read_l,
|
||||
riva128_mmio_write,
|
||||
riva128_mmio_write_w,
|
||||
riva128_mmio_write_l,
|
||||
NULL,
|
||||
0,
|
||||
riva128);*/
|
||||
|
||||
mem_mapping_add(&riva128->linear_mapping, 0, 0,
|
||||
svga_read_linear,
|
||||
svga_readw_linear,
|
||||
svga_readl_linear,
|
||||
svga_write_linear,
|
||||
svga_writew_linear,
|
||||
svga_writel_linear,
|
||||
NULL,
|
||||
0,
|
||||
&riva128->svga);
|
||||
|
||||
io_sethandler(0x03c0, 0x0020, riva128_in, NULL, NULL, riva128_out, NULL, NULL, riva128);
|
||||
|
||||
// riva128->pci_regs[4] = 3;
|
||||
riva128->pci_regs[4] = 7;
|
||||
riva128->pci_regs[5] = 0;
|
||||
riva128->pci_regs[6] = 0;
|
||||
riva128->pci_regs[7] = 2;
|
||||
|
||||
riva128->pci_regs[0x2c] = 0xd2;
|
||||
riva128->pci_regs[0x2d] = 0x12;
|
||||
riva128->pci_regs[0x2e] = 0x00;
|
||||
riva128->pci_regs[0x2f] = 0x03;
|
||||
|
||||
riva128->pci_regs[0x30] = 0x00;
|
||||
riva128->pci_regs[0x32] = 0x0c;
|
||||
riva128->pci_regs[0x33] = 0x00;
|
||||
|
||||
riva128->pmc.intr = 0;
|
||||
riva128->pbus.intr = 0;
|
||||
riva128->pfifo.intr = 0;
|
||||
riva128->pgraph.intr = 0;
|
||||
riva128->ptimer.intr = 0;
|
||||
|
||||
riva128->pci_card = pci_add_card(PCI_ADD_VIDEO, riva128_pci_read, riva128_pci_write, riva128);
|
||||
|
||||
riva128->ptimer.clock_mul = 1;
|
||||
riva128->ptimer.clock_div = 1;
|
||||
|
||||
//default values so that the emulator can boot. These'll be overwritten by the video BIOS anyway.
|
||||
riva128->pramdac.m_m = 0x03;
|
||||
riva128->pramdac.m_n = 0xc2;
|
||||
riva128->pramdac.m_p = 0x0d;
|
||||
|
||||
//timer_add(riva128_mclk_poll, &riva128->mtime, &timer_one, riva128);
|
||||
|
||||
return riva128;
|
||||
}
|
||||
|
||||
void riva128_close(void *p)
|
||||
{
|
||||
riva128_t *riva128 = (riva128_t *)p;
|
||||
FILE *f = fopen("vram.dmp", "wb");
|
||||
fwrite(riva128->svga.vram, 4 << 20, 1, f);
|
||||
fclose(f);
|
||||
|
||||
svga_close(&riva128->svga);
|
||||
|
||||
free(riva128);
|
||||
}
|
||||
|
||||
int riva128_available(void)
|
||||
{
|
||||
return rom_present(L"roms/video/nv_riva128/Diamond_V330_rev-e.vbi");
|
||||
}
|
||||
|
||||
void riva128_speed_changed(void *p)
|
||||
{
|
||||
riva128_t *riva128 = (riva128_t *)p;
|
||||
|
||||
svga_recalctimings(&riva128->svga);
|
||||
}
|
||||
|
||||
void riva128_force_redraw(void *p)
|
||||
{
|
||||
riva128_t *riva128 = (riva128_t *)p;
|
||||
|
||||
riva128->svga.fullchange = changeframecount;
|
||||
}
|
||||
|
||||
const device_config_t riva128_config[] =
|
||||
{
|
||||
{
|
||||
"memory", "Memory size", CONFIG_SELECTION, "", 4,
|
||||
{
|
||||
{
|
||||
"1 MB", 1
|
||||
},
|
||||
{
|
||||
"2 MB", 2
|
||||
},
|
||||
{
|
||||
"4 MB", 4
|
||||
},
|
||||
{
|
||||
""
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
"", "", -1
|
||||
}
|
||||
};
|
||||
|
||||
#if 0
|
||||
const device_config_t riva128zx_config[] =
|
||||
{
|
||||
{
|
||||
.name = "memory",
|
||||
.description = "Memory size",
|
||||
.type = CONFIG_SELECTION,
|
||||
.selection =
|
||||
{
|
||||
{
|
||||
.description = "1 MB",
|
||||
.value = 1
|
||||
},
|
||||
{
|
||||
.description = "2 MB",
|
||||
.value = 2
|
||||
},
|
||||
{
|
||||
.description = "4 MB",
|
||||
.value = 4
|
||||
},
|
||||
{
|
||||
.description = "8 MB",
|
||||
.value = 8
|
||||
},
|
||||
{
|
||||
.description = ""
|
||||
}
|
||||
},
|
||||
.default_int = 4
|
||||
},
|
||||
{
|
||||
.type = -1
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
const device_t riva128_device =
|
||||
{
|
||||
"nVidia RIVA 128",
|
||||
DEVICE_PCI,
|
||||
0,
|
||||
riva128_init,
|
||||
riva128_close,
|
||||
NULL,
|
||||
riva128_available,
|
||||
riva128_speed_changed,
|
||||
riva128_force_redraw,
|
||||
riva128_config
|
||||
};
|
||||
1
backup code/video - Cópia/vid_nvidia.h
Normal file
1
backup code/video - Cópia/vid_nvidia.h
Normal file
@@ -0,0 +1 @@
|
||||
extern const device_t riva128_device;
|
||||
423
backup code/video - Cópia/vid_oak_oti.c
Normal file
423
backup code/video - Cópia/vid_oak_oti.c
Normal file
@@ -0,0 +1,423 @@
|
||||
/*
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
*
|
||||
* This file is part of the 86Box distribution.
|
||||
*
|
||||
* Oak OTI037C/67/077 emulation.
|
||||
*
|
||||
* Version: @(#)vid_oak_oti.c 1.0.12 2018/04/26
|
||||
*
|
||||
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
*
|
||||
* Copyright 2008-2018 Sarah Walker.
|
||||
* Copyright 2016-2018 Miran Grca.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <wchar.h>
|
||||
#include "../86box.h"
|
||||
#include "../io.h"
|
||||
#include "../mem.h"
|
||||
#include "../rom.h"
|
||||
#include "../device.h"
|
||||
#include "video.h"
|
||||
#include "vid_oak_oti.h"
|
||||
#include "vid_svga.h"
|
||||
|
||||
#define BIOS_37C_PATH L"roms/video/oti/bios.bin"
|
||||
#define BIOS_77_PATH L"roms/video/oti/oti077.vbi"
|
||||
|
||||
|
||||
typedef struct {
|
||||
svga_t svga;
|
||||
|
||||
rom_t bios_rom;
|
||||
|
||||
int index;
|
||||
uint8_t regs[32];
|
||||
|
||||
uint8_t pos;
|
||||
|
||||
uint8_t enable_register;
|
||||
|
||||
uint32_t vram_size;
|
||||
uint32_t vram_mask;
|
||||
|
||||
uint8_t chip_id;
|
||||
} oti_t;
|
||||
|
||||
|
||||
static void
|
||||
oti_out(uint16_t addr, uint8_t val, void *p)
|
||||
{
|
||||
oti_t *oti = (oti_t *)p;
|
||||
svga_t *svga = &oti->svga;
|
||||
uint8_t old;
|
||||
uint8_t idx;
|
||||
|
||||
if (!(oti->enable_register & 1) && addr != 0x3C3)
|
||||
return;
|
||||
|
||||
if ((((addr&0xFFF0) == 0x3D0 || (addr&0xFFF0) == 0x3B0) && addr < 0x3de) &&
|
||||
!(svga->miscout & 1)) addr ^= 0x60;
|
||||
|
||||
switch (addr) {
|
||||
case 0x3C3:
|
||||
oti->enable_register = val & 1;
|
||||
return;
|
||||
|
||||
case 0x3D4:
|
||||
svga->crtcreg = val;
|
||||
return;
|
||||
|
||||
case 0x3D5:
|
||||
if (svga->crtcreg & 0x20)
|
||||
return;
|
||||
if (((svga->crtcreg & 31) < 7) && (svga->crtc[0x11] & 0x80))
|
||||
return;
|
||||
if (((svga->crtcreg & 31) == 7) && (svga->crtc[0x11] & 0x80))
|
||||
val = (svga->crtc[7] & ~0x10) | (val & 0x10);
|
||||
old = svga->crtc[svga->crtcreg & 31];
|
||||
svga->crtc[svga->crtcreg & 31] = val;
|
||||
if (old != val) {
|
||||
if ((svga->crtcreg & 31) < 0xE || (svga->crtcreg & 31) > 0x10) {
|
||||
svga->fullchange = changeframecount;
|
||||
svga_recalctimings(svga);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x3DE:
|
||||
oti->index = val;
|
||||
return;
|
||||
|
||||
case 0x3DF:
|
||||
idx = oti->index & 0x1f;
|
||||
oti->regs[idx] = val;
|
||||
switch (idx) {
|
||||
case 0xD:
|
||||
if (oti->chip_id)
|
||||
{
|
||||
svga->vram_display_mask = (val & 0xc) ? oti->vram_mask : 0x3ffff;
|
||||
if ((val & 0x80) && oti->vram_size == 256)
|
||||
mem_mapping_disable(&svga->mapping);
|
||||
else
|
||||
mem_mapping_enable(&svga->mapping);
|
||||
if (!(val & 0x80))
|
||||
svga->vram_display_mask = 0x3ffff;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (val & 0x80)
|
||||
mem_mapping_disable(&svga->mapping);
|
||||
else
|
||||
mem_mapping_enable(&svga->mapping);
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x11:
|
||||
svga->read_bank = (val & 0xf) * 65536;
|
||||
svga->write_bank = (val >> 4) * 65536;
|
||||
break;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
svga_out(addr, val, svga);
|
||||
}
|
||||
|
||||
|
||||
static uint8_t
|
||||
oti_in(uint16_t addr, void *p)
|
||||
{
|
||||
oti_t *oti = (oti_t *)p;
|
||||
svga_t *svga = &oti->svga;
|
||||
uint8_t temp;
|
||||
|
||||
if (!(oti->enable_register & 1) && addr != 0x3C3)
|
||||
return 0xff;
|
||||
|
||||
if ((((addr&0xFFF0) == 0x3D0 || (addr&0xFFF0) == 0x3B0) && addr < 0x3de) &&
|
||||
!(svga->miscout & 1)) addr ^= 0x60;
|
||||
|
||||
switch (addr) {
|
||||
case 0x3C3:
|
||||
temp = oti->enable_register;
|
||||
break;
|
||||
|
||||
case 0x3D4:
|
||||
temp = svga->crtcreg;
|
||||
break;
|
||||
|
||||
case 0x3D5:
|
||||
if (svga->crtcreg & 0x20)
|
||||
temp = 0xff;
|
||||
else
|
||||
temp = svga->crtc[svga->crtcreg & 31];
|
||||
break;
|
||||
|
||||
case 0x3DA:
|
||||
svga->attrff = 0;
|
||||
svga->attrff = 0;
|
||||
svga->cgastat &= ~0x30;
|
||||
/* copy color diagnostic info from the overscan color register */
|
||||
switch (svga->attrregs[0x12] & 0x30)
|
||||
{
|
||||
case 0x00: /* P0 and P2 */
|
||||
if (svga->attrregs[0x11] & 0x01)
|
||||
svga->cgastat |= 0x10;
|
||||
if (svga->attrregs[0x11] & 0x04)
|
||||
svga->cgastat |= 0x20;
|
||||
break;
|
||||
case 0x10: /* P4 and P5 */
|
||||
if (svga->attrregs[0x11] & 0x10)
|
||||
svga->cgastat |= 0x10;
|
||||
if (svga->attrregs[0x11] & 0x20)
|
||||
svga->cgastat |= 0x20;
|
||||
break;
|
||||
case 0x20: /* P1 and P3 */
|
||||
if (svga->attrregs[0x11] & 0x02)
|
||||
svga->cgastat |= 0x10;
|
||||
if (svga->attrregs[0x11] & 0x08)
|
||||
svga->cgastat |= 0x20;
|
||||
break;
|
||||
case 0x30: /* P6 and P7 */
|
||||
if (svga->attrregs[0x11] & 0x40)
|
||||
svga->cgastat |= 0x10;
|
||||
if (svga->attrregs[0x11] & 0x80)
|
||||
svga->cgastat |= 0x20;
|
||||
break;
|
||||
}
|
||||
return svga->cgastat;
|
||||
|
||||
case 0x3DE:
|
||||
temp = oti->index | (oti->chip_id << 5);
|
||||
break;
|
||||
|
||||
case 0x3DF:
|
||||
if ((oti->index & 0x1f)==0x10)
|
||||
temp = 0x18;
|
||||
else
|
||||
temp = oti->regs[oti->index & 0x1f];
|
||||
break;
|
||||
|
||||
default:
|
||||
temp = svga_in(addr, svga);
|
||||
break;
|
||||
}
|
||||
|
||||
return(temp);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
oti_pos_out(uint16_t addr, uint8_t val, void *p)
|
||||
{
|
||||
oti_t *oti = (oti_t *)p;
|
||||
|
||||
if ((val & 8) != (oti->pos & 8)) {
|
||||
if (val & 8)
|
||||
io_sethandler(0x03c0, 32, oti_in, NULL, NULL,
|
||||
oti_out, NULL, NULL, oti);
|
||||
else
|
||||
io_removehandler(0x03c0, 32, oti_in, NULL, NULL,
|
||||
oti_out, NULL, NULL, oti);
|
||||
}
|
||||
|
||||
oti->pos = val;
|
||||
}
|
||||
|
||||
|
||||
static uint8_t
|
||||
oti_pos_in(uint16_t addr, void *p)
|
||||
{
|
||||
oti_t *oti = (oti_t *)p;
|
||||
|
||||
return(oti->pos);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
oti_recalctimings(svga_t *svga)
|
||||
{
|
||||
oti_t *oti = (oti_t *)svga->p;
|
||||
|
||||
if (oti->regs[0x14] & 0x08) svga->ma_latch |= 0x10000;
|
||||
|
||||
if (oti->regs[0x0d] & 0x0c) svga->rowoffset <<= 1;
|
||||
|
||||
svga->interlace = oti->regs[0x14] & 0x80;
|
||||
}
|
||||
|
||||
|
||||
static void *
|
||||
oti_init(const device_t *info)
|
||||
{
|
||||
oti_t *oti = malloc(sizeof(oti_t));
|
||||
wchar_t *romfn = NULL;
|
||||
|
||||
memset(oti, 0x00, sizeof(oti_t));
|
||||
oti->chip_id = info->local;
|
||||
|
||||
switch(oti->chip_id) {
|
||||
case 0:
|
||||
romfn = BIOS_37C_PATH;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
case 5:
|
||||
romfn = BIOS_77_PATH;
|
||||
break;
|
||||
}
|
||||
|
||||
rom_init(&oti->bios_rom, romfn,
|
||||
0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL);
|
||||
|
||||
oti->vram_size = device_get_config_int("memory");
|
||||
oti->vram_mask = (oti->vram_size << 10) - 1;
|
||||
|
||||
svga_init(&oti->svga, oti, oti->vram_size << 10,
|
||||
oti_recalctimings, oti_in, oti_out, NULL, NULL);
|
||||
|
||||
io_sethandler(0x03c0, 32,
|
||||
oti_in, NULL, NULL, oti_out, NULL, NULL, oti);
|
||||
io_sethandler(0x46e8, 1, oti_pos_in,NULL,NULL, oti_pos_out,NULL,NULL, oti);
|
||||
|
||||
oti->svga.miscout = 1;
|
||||
|
||||
oti->regs[0] = 0x08; /* fixme: bios wants to read this at index 0? this index is undocumented */
|
||||
|
||||
return(oti);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
oti_close(void *p)
|
||||
{
|
||||
oti_t *oti = (oti_t *)p;
|
||||
|
||||
svga_close(&oti->svga);
|
||||
|
||||
free(oti);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
oti_speed_changed(void *p)
|
||||
{
|
||||
oti_t *oti = (oti_t *)p;
|
||||
|
||||
svga_recalctimings(&oti->svga);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
oti_force_redraw(void *p)
|
||||
{
|
||||
oti_t *oti = (oti_t *)p;
|
||||
|
||||
oti->svga.fullchange = changeframecount;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
oti037c_available(void)
|
||||
{
|
||||
return(rom_present(BIOS_37C_PATH));
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
oti067_077_available(void)
|
||||
{
|
||||
return(rom_present(BIOS_77_PATH));
|
||||
}
|
||||
|
||||
|
||||
static const device_config_t oti067_config[] =
|
||||
{
|
||||
{
|
||||
"memory", "Memory size", CONFIG_SELECTION, "", 512,
|
||||
{
|
||||
{
|
||||
"256 kB", 256
|
||||
},
|
||||
{
|
||||
"512 kB", 512
|
||||
},
|
||||
{
|
||||
""
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"", "", -1
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
static const device_config_t oti077_config[] =
|
||||
{
|
||||
{
|
||||
"memory", "Memory size", CONFIG_SELECTION, "", 1024,
|
||||
{
|
||||
{
|
||||
"256 kB", 256
|
||||
},
|
||||
{
|
||||
"512 kB", 512
|
||||
},
|
||||
{
|
||||
"1 MB", 1024
|
||||
},
|
||||
{
|
||||
""
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"", "", -1
|
||||
}
|
||||
};
|
||||
|
||||
const device_t oti037c_device =
|
||||
{
|
||||
"Oak OTI-037C",
|
||||
DEVICE_ISA,
|
||||
0,
|
||||
oti_init, oti_close, NULL,
|
||||
oti037c_available,
|
||||
oti_speed_changed,
|
||||
oti_force_redraw,
|
||||
oti067_config
|
||||
};
|
||||
|
||||
const device_t oti067_device =
|
||||
{
|
||||
"Oak OTI-067",
|
||||
DEVICE_ISA,
|
||||
2,
|
||||
oti_init, oti_close, NULL,
|
||||
oti067_077_available,
|
||||
oti_speed_changed,
|
||||
oti_force_redraw,
|
||||
oti067_config
|
||||
};
|
||||
|
||||
const device_t oti077_device =
|
||||
{
|
||||
"Oak OTI-077",
|
||||
DEVICE_ISA,
|
||||
5,
|
||||
oti_init, oti_close, NULL,
|
||||
oti067_077_available,
|
||||
oti_speed_changed,
|
||||
oti_force_redraw,
|
||||
oti077_config
|
||||
};
|
||||
7
backup code/video - Cópia/vid_oak_oti.h
Normal file
7
backup code/video - Cópia/vid_oak_oti.h
Normal file
@@ -0,0 +1,7 @@
|
||||
/* Copyright holders: Sarah Walker, Tenshi
|
||||
see COPYING for more details
|
||||
*/
|
||||
extern const device_t oti037c_device;
|
||||
extern const device_t oti067_device;
|
||||
extern const device_t oti067_acer386_device;
|
||||
extern const device_t oti077_device;
|
||||
617
backup code/video - Cópia/vid_paradise.c
Normal file
617
backup code/video - Cópia/vid_paradise.c
Normal file
@@ -0,0 +1,617 @@
|
||||
/*
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
*
|
||||
* This file is part of the 86Box distribution.
|
||||
*
|
||||
* Paradise VGA emulation
|
||||
* PC2086, PC3086 use PVGA1A
|
||||
* MegaPC uses W90C11A
|
||||
*
|
||||
* Version: @(#)vid_paradise.c 1.0.7 2018/04/26
|
||||
*
|
||||
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
*
|
||||
* Copyright 2008-2018 Sarah Walker.
|
||||
* Copyright 2016-2018 Miran Grca.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <wchar.h>
|
||||
#include "../86box.h"
|
||||
#include "../io.h"
|
||||
#include "../mem.h"
|
||||
#include "../rom.h"
|
||||
#include "../device.h"
|
||||
#include "video.h"
|
||||
#include "vid_paradise.h"
|
||||
#include "vid_svga.h"
|
||||
#include "vid_svga_render.h"
|
||||
|
||||
|
||||
typedef struct paradise_t
|
||||
{
|
||||
svga_t svga;
|
||||
|
||||
rom_t bios_rom;
|
||||
|
||||
enum
|
||||
{
|
||||
PVGA1A = 0,
|
||||
WD90C11,
|
||||
WD90C30
|
||||
} type;
|
||||
|
||||
uint32_t read_bank[4], write_bank[4];
|
||||
} paradise_t;
|
||||
|
||||
void paradise_remap(paradise_t *paradise);
|
||||
|
||||
|
||||
void paradise_out(uint16_t addr, uint8_t val, void *p)
|
||||
{
|
||||
paradise_t *paradise = (paradise_t *)p;
|
||||
svga_t *svga = ¶dise->svga;
|
||||
uint8_t old;
|
||||
|
||||
if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(svga->miscout & 1))
|
||||
addr ^= 0x60;
|
||||
switch (addr)
|
||||
{
|
||||
case 0x3c5:
|
||||
if (svga->seqaddr > 7)
|
||||
{
|
||||
if (paradise->type < WD90C11 || svga->seqregs[6] != 0x48)
|
||||
return;
|
||||
svga->seqregs[svga->seqaddr & 0x1f] = val;
|
||||
if (svga->seqaddr == 0x11)
|
||||
paradise_remap(paradise);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x3cf:
|
||||
if (svga->gdcaddr >= 0x9 && svga->gdcaddr < 0xf)
|
||||
{
|
||||
if ((svga->gdcreg[0xf] & 7) != 5)
|
||||
return;
|
||||
}
|
||||
if (svga->gdcaddr == 6)
|
||||
{
|
||||
if ((svga->gdcreg[6] & 0xc) != (val & 0xc))
|
||||
{
|
||||
switch (val&0xC)
|
||||
{
|
||||
case 0x0: /*128k at A0000*/
|
||||
mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x20000);
|
||||
svga->banked_mask = 0xffff;
|
||||
break;
|
||||
case 0x4: /*64k at A0000*/
|
||||
mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x10000);
|
||||
svga->banked_mask = 0xffff;
|
||||
break;
|
||||
case 0x8: /*32k at B0000*/
|
||||
mem_mapping_set_addr(&svga->mapping, 0xb0000, 0x08000);
|
||||
svga->banked_mask = 0x7fff;
|
||||
break;
|
||||
case 0xC: /*32k at B8000*/
|
||||
mem_mapping_set_addr(&svga->mapping, 0xb8000, 0x08000);
|
||||
svga->banked_mask = 0x7fff;
|
||||
break;
|
||||
}
|
||||
}
|
||||
svga->gdcreg[6] = val;
|
||||
paradise_remap(paradise);
|
||||
return;
|
||||
}
|
||||
if (svga->gdcaddr == 0x9 || svga->gdcaddr == 0xa)
|
||||
{
|
||||
svga->gdcreg[svga->gdcaddr] = val;
|
||||
paradise_remap(paradise);
|
||||
return;
|
||||
}
|
||||
if (svga->gdcaddr == 0xe)
|
||||
{
|
||||
svga->gdcreg[0xe] = val;
|
||||
paradise_remap(paradise);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x3D4:
|
||||
svga->crtcreg = val & 0x3f;
|
||||
return;
|
||||
case 0x3D5:
|
||||
if ((paradise->type == PVGA1A) && (svga->crtcreg & 0x20))
|
||||
return;
|
||||
if ((svga->crtcreg < 7) && (svga->crtc[0x11] & 0x80))
|
||||
return;
|
||||
if ((svga->crtcreg == 7) && (svga->crtc[0x11] & 0x80))
|
||||
val = (svga->crtc[7] & ~0x10) | (val & 0x10);
|
||||
if (svga->crtcreg > 0x29 && (svga->crtc[0x29] & 7) != 5)
|
||||
return;
|
||||
if (svga->crtcreg >= 0x31 && svga->crtcreg <= 0x37)
|
||||
return;
|
||||
old = svga->crtc[svga->crtcreg];
|
||||
svga->crtc[svga->crtcreg] = val;
|
||||
|
||||
if (old != val)
|
||||
{
|
||||
if (svga->crtcreg < 0xe || svga->crtcreg > 0x10)
|
||||
{
|
||||
svga->fullchange = changeframecount;
|
||||
svga_recalctimings(¶dise->svga);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
svga_out(addr, val, svga);
|
||||
}
|
||||
|
||||
uint8_t paradise_in(uint16_t addr, void *p)
|
||||
{
|
||||
paradise_t *paradise = (paradise_t *)p;
|
||||
svga_t *svga = ¶dise->svga;
|
||||
|
||||
if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(svga->miscout & 1))
|
||||
addr ^= 0x60;
|
||||
|
||||
switch (addr)
|
||||
{
|
||||
case 0x3c2:
|
||||
return 0x10;
|
||||
|
||||
case 0x3c5:
|
||||
if (svga->seqaddr > 7)
|
||||
{
|
||||
if (paradise->type < WD90C11 || svga->seqregs[6] != 0x48)
|
||||
return 0xff;
|
||||
if (svga->seqaddr > 0x12)
|
||||
return 0xff;
|
||||
return svga->seqregs[svga->seqaddr & 0x1f];
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x3cf:
|
||||
if (svga->gdcaddr >= 0x9 && svga->gdcaddr < 0xf)
|
||||
{
|
||||
if (svga->gdcreg[0xf] & 0x10)
|
||||
return 0xff;
|
||||
switch (svga->gdcaddr)
|
||||
{
|
||||
case 0xf:
|
||||
return (svga->gdcreg[0xf] & 0x17) | 0x80;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x3D4:
|
||||
return svga->crtcreg;
|
||||
case 0x3D5:
|
||||
if ((paradise->type == PVGA1A) && (svga->crtcreg & 0x20))
|
||||
return 0xff;
|
||||
if (svga->crtcreg > 0x29 && svga->crtcreg < 0x30 && (svga->crtc[0x29] & 0x88) != 0x80)
|
||||
return 0xff;
|
||||
return svga->crtc[svga->crtcreg];
|
||||
}
|
||||
return svga_in(addr, svga);
|
||||
}
|
||||
|
||||
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] & 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] & 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] & 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] & 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);
|
||||
}
|
||||
}
|
||||
|
||||
void paradise_recalctimings(svga_t *svga)
|
||||
{
|
||||
paradise_t *paradise = (paradise_t *) svga->p;
|
||||
|
||||
if (paradise->type == WD90C30)
|
||||
svga->interlace = (svga->crtc[0x2d] & 0x20);
|
||||
|
||||
svga->lowres = !(svga->gdcreg[0xe] & 0x01);
|
||||
if (svga->bpp == 8 && !svga->lowres)
|
||||
svga->render = svga_render_8bpp_highres;
|
||||
}
|
||||
|
||||
static void paradise_write(uint32_t addr, uint8_t val, void *p)
|
||||
{
|
||||
paradise_t *paradise = (paradise_t *)p;
|
||||
addr = (addr & 0x7fff) + paradise->write_bank[(addr >> 15) & 3];
|
||||
|
||||
svga_write_linear(addr, val, ¶dise->svga);
|
||||
}
|
||||
static void paradise_writew(uint32_t addr, uint16_t val, void *p)
|
||||
{
|
||||
paradise_t *paradise = (paradise_t *)p;
|
||||
addr = (addr & 0x7fff) + paradise->write_bank[(addr >> 15) & 3];
|
||||
svga_writew_linear(addr, val, ¶dise->svga);
|
||||
}
|
||||
|
||||
static uint8_t paradise_read(uint32_t addr, void *p)
|
||||
{
|
||||
paradise_t *paradise = (paradise_t *)p;
|
||||
addr = (addr & 0x7fff) + paradise->read_bank[(addr >> 15) & 3];
|
||||
return svga_read_linear(addr, ¶dise->svga);
|
||||
}
|
||||
static uint16_t paradise_readw(uint32_t addr, void *p)
|
||||
{
|
||||
paradise_t *paradise = (paradise_t *)p;
|
||||
addr = (addr & 0x7fff) + paradise->read_bank[(addr >> 15) & 3];
|
||||
return svga_readw_linear(addr, ¶dise->svga);
|
||||
}
|
||||
|
||||
void *paradise_pvga1a_init(const 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, /*256kb*/
|
||||
NULL,
|
||||
paradise_in, paradise_out,
|
||||
NULL,
|
||||
NULL);
|
||||
|
||||
mem_mapping_set_handler(¶dise->svga.mapping, paradise_read, paradise_readw, NULL, paradise_write, paradise_writew, 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->bpp = 8;
|
||||
svga->miscout = 1;
|
||||
|
||||
paradise->type = PVGA1A;
|
||||
|
||||
return paradise;
|
||||
}
|
||||
|
||||
void *paradise_wd90c11_init(const device_t *info)
|
||||
{
|
||||
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, 1 << 19, /*512kb*/
|
||||
paradise_recalctimings,
|
||||
paradise_in, paradise_out,
|
||||
NULL,
|
||||
NULL);
|
||||
|
||||
mem_mapping_set_handler(¶dise->svga.mapping, paradise_read, paradise_readw, NULL, paradise_write, paradise_writew, 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] = '1';
|
||||
svga->crtc[0x37] = '1';
|
||||
|
||||
svga->bpp = 8;
|
||||
svga->miscout = 1;
|
||||
|
||||
paradise->type = WD90C11;
|
||||
|
||||
return paradise;
|
||||
}
|
||||
|
||||
void *paradise_wd90c30_init(const 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, paradise_readw, NULL, paradise_write, paradise_writew, 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;
|
||||
|
||||
paradise->type = WD90C11;
|
||||
|
||||
return paradise;
|
||||
}
|
||||
|
||||
static void *paradise_pvga1a_pc2086_init(const device_t *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);
|
||||
|
||||
return paradise;
|
||||
}
|
||||
static void *paradise_pvga1a_pc3086_init(const device_t *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);
|
||||
|
||||
return paradise;
|
||||
}
|
||||
|
||||
static void *paradise_pvga1a_standalone_init(const 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(const device_t *info)
|
||||
{
|
||||
paradise_t *paradise = paradise_wd90c11_init(info);
|
||||
|
||||
if (paradise)
|
||||
rom_init_interleaved(¶dise->bios_rom,
|
||||
L"roms/machines/megapc/41651-bios lo.u18",
|
||||
L"roms/machines/megapc/211253-bios hi.u19",
|
||||
0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL);
|
||||
|
||||
return paradise;
|
||||
}
|
||||
|
||||
static void *paradise_wd90c11_standalone_init(const 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/video/wd90c11/WD90C11.VBI");
|
||||
}
|
||||
|
||||
static void *paradise_wd90c30_standalone_init(const 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)
|
||||
{
|
||||
paradise_t *paradise = (paradise_t *)p;
|
||||
|
||||
svga_close(¶dise->svga);
|
||||
|
||||
free(paradise);
|
||||
}
|
||||
|
||||
void paradise_speed_changed(void *p)
|
||||
{
|
||||
paradise_t *paradise = (paradise_t *)p;
|
||||
|
||||
svga_recalctimings(¶dise->svga);
|
||||
}
|
||||
|
||||
void paradise_force_redraw(void *p)
|
||||
{
|
||||
paradise_t *paradise = (paradise_t *)p;
|
||||
|
||||
paradise->svga.fullchange = changeframecount;
|
||||
}
|
||||
|
||||
|
||||
const device_t paradise_pvga1a_pc2086_device =
|
||||
{
|
||||
"Paradise PVGA1A (Amstrad PC2086)",
|
||||
0,
|
||||
0,
|
||||
paradise_pvga1a_pc2086_init,
|
||||
paradise_close,
|
||||
NULL,
|
||||
NULL,
|
||||
paradise_speed_changed,
|
||||
paradise_force_redraw,
|
||||
NULL
|
||||
};
|
||||
const device_t paradise_pvga1a_pc3086_device =
|
||||
{
|
||||
"Paradise PVGA1A (Amstrad PC3086)",
|
||||
0,
|
||||
0,
|
||||
paradise_pvga1a_pc3086_init,
|
||||
paradise_close,
|
||||
NULL,
|
||||
NULL,
|
||||
paradise_speed_changed,
|
||||
paradise_force_redraw,
|
||||
NULL
|
||||
};
|
||||
|
||||
static const device_config_t paradise_pvga1a_config[] =
|
||||
{
|
||||
{
|
||||
"memory", "Memory size", CONFIG_SELECTION, "", 512,
|
||||
{
|
||||
{
|
||||
"256 kB", 256
|
||||
},
|
||||
{
|
||||
"512 kB", 512
|
||||
},
|
||||
{
|
||||
"1 MB", 1024
|
||||
},
|
||||
{
|
||||
""
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"", "", -1
|
||||
}
|
||||
};
|
||||
|
||||
const 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_pvga1a_config
|
||||
};
|
||||
const device_t paradise_wd90c11_megapc_device =
|
||||
{
|
||||
"Paradise WD90C11 (Amstrad MegaPC)",
|
||||
0,
|
||||
0,
|
||||
paradise_wd90c11_megapc_init,
|
||||
paradise_close,
|
||||
NULL,
|
||||
NULL,
|
||||
paradise_speed_changed,
|
||||
paradise_force_redraw,
|
||||
NULL
|
||||
};
|
||||
const device_t paradise_wd90c11_device =
|
||||
{
|
||||
"Paradise WD90C11-LR",
|
||||
DEVICE_ISA,
|
||||
0,
|
||||
paradise_wd90c11_standalone_init,
|
||||
paradise_close,
|
||||
NULL,
|
||||
paradise_wd90c11_standalone_available,
|
||||
paradise_speed_changed,
|
||||
paradise_force_redraw,
|
||||
NULL
|
||||
};
|
||||
|
||||
static const device_config_t paradise_wd90c30_config[] =
|
||||
{
|
||||
{
|
||||
"memory", "Memory size", CONFIG_SELECTION, "", 1024,
|
||||
{
|
||||
{
|
||||
"512 kB", 512
|
||||
},
|
||||
{
|
||||
"1 MB", 1024
|
||||
},
|
||||
{
|
||||
""
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"", "", -1
|
||||
}
|
||||
};
|
||||
|
||||
const 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_wd90c30_config
|
||||
};
|
||||
9
backup code/video - Cópia/vid_paradise.h
Normal file
9
backup code/video - Cópia/vid_paradise.h
Normal file
@@ -0,0 +1,9 @@
|
||||
/* Copyright holders: Sarah Walker, Tenshi
|
||||
see COPYING for more details
|
||||
*/
|
||||
extern const device_t paradise_pvga1a_pc2086_device;
|
||||
extern const device_t paradise_pvga1a_pc3086_device;
|
||||
extern const device_t paradise_pvga1a_device;
|
||||
extern const device_t paradise_wd90c11_megapc_device;
|
||||
extern const device_t paradise_wd90c11_device;
|
||||
extern const device_t paradise_wd90c30_device;
|
||||
3245
backup code/video - Cópia/vid_s3.c
Normal file
3245
backup code/video - Cópia/vid_s3.c
Normal file
File diff suppressed because it is too large
Load Diff
33
backup code/video - Cópia/vid_s3.h
Normal file
33
backup code/video - Cópia/vid_s3.h
Normal file
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
*
|
||||
* This file is part of the 86Box distribution.
|
||||
*
|
||||
* Emulation of the S3 Trio32, S3 Trio64, and S3 Vision864
|
||||
* graphics cards.
|
||||
*
|
||||
* Version: @(#)vid_s3.h 1.0.2 2018/03/18
|
||||
*
|
||||
* Author: Sarah Walker, <http://pcem-emulator.co.uk/>
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
* Copyright 2008-2018 Sarah Walker.
|
||||
* Copyright 2016-2018 Miran Grca.
|
||||
*/
|
||||
|
||||
const device_t s3_bahamas64_vlb_device;
|
||||
const device_t s3_bahamas64_pci_device;
|
||||
const device_t s3_9fx_vlb_device;
|
||||
const device_t s3_9fx_pci_device;
|
||||
const device_t s3_phoenix_trio32_vlb_device;
|
||||
const device_t s3_phoenix_trio32_pci_device;
|
||||
const device_t s3_phoenix_trio64_vlb_device;
|
||||
const device_t s3_phoenix_trio64_onboard_pci_device;
|
||||
const device_t s3_phoenix_trio64_pci_device;
|
||||
const device_t s3_phoenix_vision864_pci_device;
|
||||
const device_t s3_phoenix_vision864_vlb_device;
|
||||
const device_t s3_diamond_stealth64_pci_device;
|
||||
const device_t s3_diamond_stealth64_vlb_device;
|
||||
/* const device_t s3_miro_vision964_device; */
|
||||
4328
backup code/video - Cópia/vid_s3_virge.c
Normal file
4328
backup code/video - Cópia/vid_s3_virge.c
Normal file
File diff suppressed because it is too large
Load Diff
11
backup code/video - Cópia/vid_s3_virge.h
Normal file
11
backup code/video - Cópia/vid_s3_virge.h
Normal file
@@ -0,0 +1,11 @@
|
||||
/* Copyright holders: Sarah Walker
|
||||
see COPYING for more details
|
||||
*/
|
||||
extern const device_t s3_virge_vlb_device;
|
||||
extern const device_t s3_virge_pci_device;
|
||||
extern const device_t s3_virge_988_vlb_device;
|
||||
extern const device_t s3_virge_988_pci_device;
|
||||
extern const device_t s3_virge_375_vlb_device;
|
||||
extern const device_t s3_virge_375_pci_device;
|
||||
extern const device_t s3_virge_375_4_vlb_device;
|
||||
extern const device_t s3_virge_375_4_pci_device;
|
||||
111
backup code/video - Cópia/vid_sc1502x_ramdac.c
Normal file
111
backup code/video - Cópia/vid_sc1502x_ramdac.c
Normal file
@@ -0,0 +1,111 @@
|
||||
/*
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
*
|
||||
* This file is part of the 86Box distribution.
|
||||
*
|
||||
* Emulation of a Sierra SC1502X RAMDAC.
|
||||
*
|
||||
* Used by the TLIVESA1 driver for ET4000.
|
||||
*
|
||||
* Version: @(#)vid_sc1502x_ramdac.c 1.0.2 2017/11/04
|
||||
*
|
||||
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
*
|
||||
* Copyright 2008-2017 Sarah Walker.
|
||||
* Copyright 2016,2017 Miran Grca.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <wchar.h>
|
||||
#include "../86box.h"
|
||||
#include "../mem.h"
|
||||
#include "video.h"
|
||||
#include "vid_svga.h"
|
||||
#include "vid_sc1502x_ramdac.h"
|
||||
|
||||
|
||||
void sc1502x_ramdac_out(uint16_t addr, uint8_t val, sc1502x_ramdac_t *ramdac, svga_t *svga)
|
||||
{
|
||||
int oldbpp = 0;
|
||||
switch (addr)
|
||||
{
|
||||
case 0x3C6:
|
||||
if (ramdac->state == 4)
|
||||
{
|
||||
ramdac->state = 0;
|
||||
if (val == 0xFF) break;
|
||||
ramdac->ctrl = val;
|
||||
oldbpp = svga->bpp;
|
||||
switch ((val&1)|((val&0xC0)>>5))
|
||||
{
|
||||
case 0:
|
||||
svga->bpp = 8;
|
||||
break;
|
||||
case 2: case 3:
|
||||
switch (val & 0x20)
|
||||
{
|
||||
case 0x00: svga->bpp = 32; break;
|
||||
case 0x20: svga->bpp = 24; break;
|
||||
}
|
||||
break;
|
||||
case 4: case 5:
|
||||
svga->bpp = 15;
|
||||
break;
|
||||
case 6:
|
||||
svga->bpp = 16;
|
||||
break;
|
||||
case 7:
|
||||
switch (val & 4)
|
||||
{
|
||||
case 4:
|
||||
switch (val & 0x20)
|
||||
{
|
||||
case 0x00: svga->bpp = 32; break;
|
||||
case 0x20: svga->bpp = 24; break;
|
||||
}
|
||||
break;
|
||||
case 0: default:
|
||||
svga->bpp = 16;
|
||||
break;
|
||||
}
|
||||
case 1: default:
|
||||
break;
|
||||
}
|
||||
if (oldbpp != svga->bpp)
|
||||
{
|
||||
svga_recalctimings(svga);
|
||||
}
|
||||
return;
|
||||
}
|
||||
ramdac->state = 0;
|
||||
break;
|
||||
case 0x3C7: case 0x3C8: case 0x3C9:
|
||||
ramdac->state = 0;
|
||||
break;
|
||||
}
|
||||
svga_out(addr, val, svga);
|
||||
}
|
||||
|
||||
uint8_t sc1502x_ramdac_in(uint16_t addr, sc1502x_ramdac_t *ramdac, svga_t *svga)
|
||||
{
|
||||
switch (addr)
|
||||
{
|
||||
case 0x3C6:
|
||||
if (ramdac->state == 4)
|
||||
{
|
||||
ramdac->state = 0;
|
||||
return ramdac->ctrl;
|
||||
}
|
||||
ramdac->state++;
|
||||
break;
|
||||
case 0x3C7: case 0x3C8: case 0x3C9:
|
||||
ramdac->state = 0;
|
||||
break;
|
||||
}
|
||||
return svga_in(addr, svga);
|
||||
}
|
||||
11
backup code/video - Cópia/vid_sc1502x_ramdac.h
Normal file
11
backup code/video - Cópia/vid_sc1502x_ramdac.h
Normal file
@@ -0,0 +1,11 @@
|
||||
/* Copyright holders: Sarah Walker, Tenshi
|
||||
see COPYING for more details
|
||||
*/
|
||||
typedef struct unk_ramdac_t
|
||||
{
|
||||
int state;
|
||||
uint8_t ctrl;
|
||||
} sc1502x_ramdac_t;
|
||||
|
||||
void sc1502x_ramdac_out(uint16_t addr, uint8_t val, sc1502x_ramdac_t *ramdac, svga_t *svga);
|
||||
uint8_t sc1502x_ramdac_in(uint16_t addr, sc1502x_ramdac_t *ramdac, svga_t *svga);
|
||||
183
backup code/video - Cópia/vid_sdac_ramdac.c
Normal file
183
backup code/video - Cópia/vid_sdac_ramdac.c
Normal file
@@ -0,0 +1,183 @@
|
||||
/*
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
*
|
||||
* This file is part of the 86Box distribution.
|
||||
*
|
||||
* 87C716 'SDAC' true colour RAMDAC emulation.
|
||||
*
|
||||
* Version: @(#)vid_sdac_ramdac.c 1.0.3 2018/03/21
|
||||
*
|
||||
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
*
|
||||
* Copyright 2008-2018 Sarah Walker.
|
||||
* Copyright 2016-2018 Miran Grca.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <wchar.h>
|
||||
#include "../86box.h"
|
||||
#include "../mem.h"
|
||||
#include "video.h"
|
||||
#include "vid_svga.h"
|
||||
#include "vid_sdac_ramdac.h"
|
||||
|
||||
static void sdac_control_write(sdac_ramdac_t *ramdac, svga_t *svga, uint8_t val)
|
||||
{
|
||||
ramdac->command = val;
|
||||
switch (val >> 4)
|
||||
{
|
||||
case 0x2: case 0x3: case 0xa: svga->bpp = 15; break;
|
||||
case 0x4: case 0xe: svga->bpp = 24; break;
|
||||
case 0x5: case 0x6: case 0xc: svga->bpp = 16; break;
|
||||
case 0x7: svga->bpp = 32; break;
|
||||
|
||||
case 0: case 1: default: svga->bpp = 8; break;
|
||||
}
|
||||
}
|
||||
|
||||
static void sdac_reg_write(sdac_ramdac_t *ramdac, int reg, uint8_t val)
|
||||
{
|
||||
if ((reg >= 2 && reg <= 7) || (reg == 0xa) || (reg == 0xe))
|
||||
{
|
||||
if (!ramdac->reg_ff)
|
||||
ramdac->regs[reg] = (ramdac->regs[reg] & 0xff00) | val;
|
||||
else
|
||||
ramdac->regs[reg] = (ramdac->regs[reg] & 0x00ff) | (val << 8);
|
||||
}
|
||||
ramdac->reg_ff = !ramdac->reg_ff;
|
||||
if (!ramdac->reg_ff)
|
||||
ramdac->windex++;
|
||||
}
|
||||
|
||||
static uint8_t sdac_reg_read(sdac_ramdac_t *ramdac, int reg)
|
||||
{
|
||||
uint8_t temp;
|
||||
|
||||
if (!ramdac->reg_ff)
|
||||
temp = ramdac->regs[reg] & 0xff;
|
||||
else
|
||||
temp = ramdac->regs[reg] >> 8;
|
||||
ramdac->reg_ff = !ramdac->reg_ff;
|
||||
if (!ramdac->reg_ff)
|
||||
ramdac->rindex++;
|
||||
|
||||
return temp;
|
||||
}
|
||||
|
||||
void sdac_ramdac_out(uint16_t addr, uint8_t val, sdac_ramdac_t *ramdac, svga_t *svga)
|
||||
{
|
||||
switch (addr)
|
||||
{
|
||||
case 2:
|
||||
if (ramdac->magic_count == 4)
|
||||
sdac_control_write(ramdac, svga, val);
|
||||
ramdac->magic_count = 0;
|
||||
break;
|
||||
|
||||
case 3:
|
||||
ramdac->magic_count = 0;
|
||||
break;
|
||||
case 0:
|
||||
ramdac->magic_count = 0;
|
||||
break;
|
||||
case 1:
|
||||
ramdac->magic_count = 0;
|
||||
break;
|
||||
|
||||
case 4:
|
||||
ramdac->windex = val;
|
||||
ramdac->reg_ff = 0;
|
||||
break;
|
||||
case 5:
|
||||
sdac_reg_write(ramdac, ramdac->windex & 0xff, val);
|
||||
break;
|
||||
case 6:
|
||||
sdac_control_write(ramdac, svga, val);
|
||||
break;
|
||||
case 7:
|
||||
ramdac->rindex = val;
|
||||
ramdac->reg_ff = 0;
|
||||
break;
|
||||
}
|
||||
if (!(addr & 4))
|
||||
{
|
||||
if (addr < 2)
|
||||
svga_out(addr + 0x3c8, val, svga);
|
||||
else
|
||||
svga_out(addr + 0x3c4, val, svga);
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t sdac_ramdac_in(uint16_t addr, sdac_ramdac_t *ramdac, svga_t *svga)
|
||||
{
|
||||
uint8_t temp;
|
||||
switch (addr)
|
||||
{
|
||||
case 2:
|
||||
if (ramdac->magic_count < 5)
|
||||
ramdac->magic_count++;
|
||||
if (ramdac->magic_count == 4)
|
||||
{
|
||||
temp = 0x70; /*SDAC ID*/
|
||||
ramdac->rs2 = 1;
|
||||
}
|
||||
if (ramdac->magic_count == 5)
|
||||
{
|
||||
temp = ramdac->command;
|
||||
ramdac->magic_count = 0;
|
||||
}
|
||||
return temp;
|
||||
case 3:
|
||||
ramdac->magic_count=0;
|
||||
break;
|
||||
case 0:
|
||||
ramdac->magic_count=0;
|
||||
break;
|
||||
case 1:
|
||||
ramdac->magic_count=0;
|
||||
break;
|
||||
|
||||
case 4:
|
||||
return ramdac->windex;
|
||||
case 5:
|
||||
return sdac_reg_read(ramdac, ramdac->rindex & 0xff);
|
||||
case 6:
|
||||
return ramdac->command;
|
||||
case 7:
|
||||
return ramdac->rindex;
|
||||
}
|
||||
if (!(addr & 4))
|
||||
{
|
||||
if (addr < 2)
|
||||
return svga_in(addr + 0x3c8, svga);
|
||||
else
|
||||
return svga_in(addr + 0x3c4, svga);
|
||||
}
|
||||
return 0xff;
|
||||
}
|
||||
|
||||
float sdac_getclock(int clock, void *p)
|
||||
{
|
||||
sdac_ramdac_t *ramdac = (sdac_ramdac_t *)p;
|
||||
float t;
|
||||
int m, n1, n2;
|
||||
if (clock == 0) return 25175000.0;
|
||||
if (clock == 1) return 28322000.0;
|
||||
clock ^= 1; /*Clocks 2 and 3 seem to be reversed*/
|
||||
m = (ramdac->regs[clock] & 0x7f) + 2;
|
||||
n1 = ((ramdac->regs[clock] >> 8) & 0x1f) + 2;
|
||||
n2 = ((ramdac->regs[clock] >> 13) & 0x07);
|
||||
t = (14318184.0 * ((float)m / (float)n1)) / (float)(1 << n2);
|
||||
return t;
|
||||
}
|
||||
|
||||
void sdac_init(sdac_ramdac_t *ramdac)
|
||||
{
|
||||
ramdac->regs[0] = 0x6128;
|
||||
ramdac->regs[1] = 0x623d;
|
||||
}
|
||||
19
backup code/video - Cópia/vid_sdac_ramdac.h
Normal file
19
backup code/video - Cópia/vid_sdac_ramdac.h
Normal file
@@ -0,0 +1,19 @@
|
||||
/* Copyright holders: Sarah Walker, Tenshi
|
||||
see COPYING for more details
|
||||
*/
|
||||
typedef struct sdac_ramdac_t
|
||||
{
|
||||
int magic_count;
|
||||
uint8_t command;
|
||||
int windex, rindex;
|
||||
uint16_t regs[256];
|
||||
int reg_ff;
|
||||
int rs2;
|
||||
} sdac_ramdac_t;
|
||||
|
||||
void sdac_init(sdac_ramdac_t *ramdac);
|
||||
|
||||
void sdac_ramdac_out(uint16_t addr, uint8_t val, sdac_ramdac_t *ramdac, svga_t *svga);
|
||||
uint8_t sdac_ramdac_in(uint16_t addr, sdac_ramdac_t *ramdac, svga_t *svga);
|
||||
|
||||
float sdac_getclock(int clock, void *p);
|
||||
181
backup code/video - Cópia/vid_stg_ramdac.c
Normal file
181
backup code/video - Cópia/vid_stg_ramdac.c
Normal file
@@ -0,0 +1,181 @@
|
||||
/*
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
*
|
||||
* This file is part of the 86Box distribution.
|
||||
*
|
||||
* STG1702 true colour RAMDAC emulation.
|
||||
*
|
||||
* Version: @(#)vid_stg_ramdac.c 1.0.4 2018/01/25
|
||||
*
|
||||
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
*
|
||||
* Copyright 2008-2018 Sarah Walker.
|
||||
* Copyright 2016-2018 Miran Grca.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <wchar.h>
|
||||
#include "../86box.h"
|
||||
#include "../mem.h"
|
||||
#include "video.h"
|
||||
#include "vid_svga.h"
|
||||
#include "vid_stg_ramdac.h"
|
||||
|
||||
|
||||
static int stg_state_read[2][8] = {{1,2,3,4,0,0,0,0}, {1,2,3,4,5,6,7,7}};
|
||||
static int stg_state_write[8] = {0,0,0,0,0,6,7,7};
|
||||
|
||||
|
||||
void stg_ramdac_set_bpp(svga_t *svga, stg_ramdac_t *ramdac)
|
||||
{
|
||||
if (ramdac->command & 0x8)
|
||||
{
|
||||
switch (ramdac->regs[3])
|
||||
{
|
||||
case 0: case 5: case 7: svga->bpp = 8; break;
|
||||
case 1: case 2: case 8: svga->bpp = 15; break;
|
||||
case 3: case 6: svga->bpp = 16; break;
|
||||
case 4: case 9: svga->bpp = 24; break;
|
||||
default: svga->bpp = 8; break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (ramdac->command >> 5)
|
||||
{
|
||||
case 0: svga->bpp = 8; break;
|
||||
case 5: svga->bpp = 15; break;
|
||||
case 6: svga->bpp = 16; break;
|
||||
case 7: svga->bpp = 24; break;
|
||||
default: svga->bpp = 8; break;
|
||||
}
|
||||
}
|
||||
svga_recalctimings(svga);
|
||||
}
|
||||
|
||||
void stg_ramdac_out(uint16_t addr, uint8_t val, stg_ramdac_t *ramdac, svga_t *svga)
|
||||
{
|
||||
int didwrite, old;
|
||||
switch (addr)
|
||||
{
|
||||
case 0x3c6:
|
||||
switch (ramdac->magic_count)
|
||||
{
|
||||
/* 0 = PEL mask register */
|
||||
case 0: case 1: case 2: case 3:
|
||||
break;
|
||||
case 4: /* REG06 */
|
||||
old = ramdac->command;
|
||||
ramdac->command = val;
|
||||
if ((old ^ val) & 8)
|
||||
{
|
||||
stg_ramdac_set_bpp(svga, ramdac);
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((old ^ val) & 0xE0)
|
||||
{
|
||||
stg_ramdac_set_bpp(svga, ramdac);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 5:
|
||||
ramdac->index = (ramdac->index & 0xff00) | val;
|
||||
break;
|
||||
case 6:
|
||||
ramdac->index = (ramdac->index & 0xff) | (val << 8);
|
||||
break;
|
||||
case 7:
|
||||
if (ramdac->index < 0x100)
|
||||
{
|
||||
ramdac->regs[ramdac->index] = val;
|
||||
}
|
||||
if ((ramdac->index == 3) && (ramdac->command & 8)) stg_ramdac_set_bpp(svga, ramdac);
|
||||
ramdac->index++;
|
||||
break;
|
||||
}
|
||||
didwrite = (ramdac->magic_count >= 4);
|
||||
ramdac->magic_count = stg_state_write[ramdac->magic_count & 7];
|
||||
if (didwrite) return;
|
||||
break;
|
||||
case 0x3c7: case 0x3c8: case 0x3c9:
|
||||
ramdac->magic_count=0;
|
||||
break;
|
||||
}
|
||||
svga_out(addr, val, svga);
|
||||
}
|
||||
|
||||
uint8_t stg_ramdac_in(uint16_t addr, stg_ramdac_t *ramdac, svga_t *svga)
|
||||
{
|
||||
uint8_t temp = 0xff;
|
||||
switch (addr)
|
||||
{
|
||||
case 0x3c6:
|
||||
switch (ramdac->magic_count)
|
||||
{
|
||||
case 0: case 1: case 2: case 3:
|
||||
temp = 0xff;
|
||||
break;
|
||||
case 4:
|
||||
temp = ramdac->command;
|
||||
break;
|
||||
case 5:
|
||||
temp = ramdac->index & 0xff;
|
||||
break;
|
||||
case 6:
|
||||
temp = ramdac->index >> 8;
|
||||
break;
|
||||
case 7:
|
||||
switch (ramdac->index)
|
||||
{
|
||||
case 0:
|
||||
temp = 0x44;
|
||||
break;
|
||||
case 1:
|
||||
temp = 0x03;
|
||||
break;
|
||||
case 7:
|
||||
temp = 0x88;
|
||||
break;
|
||||
default:
|
||||
if (ramdac->index < 0x100) temp = ramdac->regs[ramdac->index];
|
||||
else temp = 0xff;
|
||||
break;
|
||||
}
|
||||
ramdac->index++;
|
||||
break;
|
||||
}
|
||||
ramdac->magic_count = stg_state_read[(ramdac->command & 0x10) ? 1 : 0][ramdac->magic_count & 7];
|
||||
return temp;
|
||||
case 0x3c7: case 0x3c8: case 0x3c9:
|
||||
ramdac->magic_count=0;
|
||||
break;
|
||||
}
|
||||
return svga_in(addr, svga);
|
||||
}
|
||||
|
||||
float stg_getclock(int clock, void *p)
|
||||
{
|
||||
stg_ramdac_t *ramdac = (stg_ramdac_t *)p;
|
||||
float t;
|
||||
int m, n, n2;
|
||||
float b, n1, d;
|
||||
uint16_t *c;
|
||||
if (clock == 0) return 25175000.0;
|
||||
if (clock == 1) return 28322000.0;
|
||||
clock ^= 1; /*Clocks 2 and 3 seem to be reversed*/
|
||||
c = (uint16_t *) &ramdac->regs[0x20 + (clock << 1)];
|
||||
m = (*c & 0xff) + 2; /* B+2 */
|
||||
n = ((*c >> 8) & 0x1f) + 2; /* N1+2 */
|
||||
n2 = ((*c >> 13) & 0x07); /* D */
|
||||
b = (float) m;
|
||||
n1 = (float) n;
|
||||
d = (double) (1 << n2);
|
||||
t = (14318184.0 * (b / d)) / n1;
|
||||
return t;
|
||||
}
|
||||
14
backup code/video - Cópia/vid_stg_ramdac.h
Normal file
14
backup code/video - Cópia/vid_stg_ramdac.h
Normal file
@@ -0,0 +1,14 @@
|
||||
/* Copyright holders: Sarah Walker, Tenshi
|
||||
see COPYING for more details
|
||||
*/
|
||||
typedef struct stg_ramdac_t
|
||||
{
|
||||
int magic_count;
|
||||
uint8_t command;
|
||||
int index;
|
||||
uint8_t regs[256];
|
||||
} stg_ramdac_t;
|
||||
|
||||
void stg_ramdac_out(uint16_t addr, uint8_t val, stg_ramdac_t *ramdac, svga_t *svga);
|
||||
uint8_t stg_ramdac_in(uint16_t addr, stg_ramdac_t *ramdac, svga_t *svga);
|
||||
float stg_getclock(int clock, void *p);
|
||||
1353
backup code/video - Cópia/vid_svga.c
Normal file
1353
backup code/video - Cópia/vid_svga.c
Normal file
File diff suppressed because it is too large
Load Diff
205
backup code/video - Cópia/vid_svga.h
Normal file
205
backup code/video - Cópia/vid_svga.h
Normal file
@@ -0,0 +1,205 @@
|
||||
/*
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
*
|
||||
* This file is part of the 86Box distribution.
|
||||
*
|
||||
* Generic SVGA handling.
|
||||
*
|
||||
* Version: @(#)vid_svga.h 1.0.11 2018/04/01
|
||||
*
|
||||
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
*
|
||||
* Copyright 2008-2018 Sarah Walker.
|
||||
* Copyright 2016-2018 Miran Grca.
|
||||
*/
|
||||
|
||||
typedef struct {
|
||||
int ena,
|
||||
x, y, xoff, yoff, xsize, ysize,
|
||||
v_acc, h_acc;
|
||||
uint32_t addr, pitch;
|
||||
} hwcursor_t;
|
||||
|
||||
typedef struct svga_t
|
||||
{
|
||||
mem_mapping_t mapping;
|
||||
|
||||
int enabled;
|
||||
|
||||
uint8_t crtcreg, crtc[128],
|
||||
gdcaddr, gdcreg[64],
|
||||
attrff, attr_palette_enable,
|
||||
attraddr, attrregs[32],
|
||||
seqaddr, seqregs[64],
|
||||
miscout, cgastat,
|
||||
plane_mask, writemask,
|
||||
colourcompare, colournocare,
|
||||
scrblank, egapal[16],
|
||||
*vram, *changedvram;
|
||||
|
||||
int vidclock, fb_only,
|
||||
fast;
|
||||
|
||||
/*The three variables below allow us to implement memory maps like that seen on a 1MB Trio64 :
|
||||
0MB-1MB - VRAM
|
||||
1MB-2MB - VRAM mirror
|
||||
2MB-4MB - open bus
|
||||
4MB-xMB - mirror of above
|
||||
|
||||
For the example memory map, decode_mask would be 4MB-1 (4MB address space), vram_max would be 2MB
|
||||
(present video memory only responds to first 2MB), vram_mask would be 1MB-1 (video memory wraps at 1MB)
|
||||
*/
|
||||
uint32_t decode_mask;
|
||||
uint32_t vram_max;
|
||||
uint32_t vram_mask;
|
||||
|
||||
uint8_t dac_mask, dac_status;
|
||||
int dac_read, dac_write,
|
||||
dac_pos, ramdac_type,
|
||||
dac_r, dac_g;
|
||||
|
||||
int readmode, writemode,
|
||||
readplane, extvram,
|
||||
chain4, chain2_write, chain2_read,
|
||||
oddeven_page, oddeven_chain,
|
||||
set_reset_disabled;
|
||||
|
||||
uint32_t charseta, charsetb,
|
||||
latch, ma_latch,
|
||||
ma, maback,
|
||||
write_bank, read_bank,
|
||||
banked_mask,
|
||||
ca, overscan_color,
|
||||
pallook[256];
|
||||
|
||||
PALETTE vgapal;
|
||||
|
||||
int vtotal, dispend, vsyncstart, split, vblankstart,
|
||||
hdisp, hdisp_old, htotal, hdisp_time, rowoffset,
|
||||
lowres, interlace, linedbl, rowcount, bpp,
|
||||
dispon, hdisp_on,
|
||||
vc, sc, linepos, vslines, linecountff, oddeven,
|
||||
con, cursoron, blink, scrollcache,
|
||||
firstline, lastline, firstline_draw, lastline_draw,
|
||||
displine, fullchange,
|
||||
video_res_x, video_res_y, video_bpp, frames, fps,
|
||||
vram_display_mask,
|
||||
hwcursor_on, overlay_on,
|
||||
hwcursor_oddeven, overlay_oddeven;
|
||||
|
||||
double clock;
|
||||
|
||||
int64_t dispontime, dispofftime,
|
||||
vidtime;
|
||||
|
||||
hwcursor_t hwcursor, hwcursor_latch,
|
||||
overlay, overlay_latch;
|
||||
|
||||
void (*render)(struct svga_t *svga);
|
||||
void (*recalctimings_ex)(struct svga_t *svga);
|
||||
|
||||
void (*video_out)(uint16_t addr, uint8_t val, void *p);
|
||||
uint8_t (*video_in) (uint16_t addr, void *p);
|
||||
|
||||
void (*hwcursor_draw)(struct svga_t *svga, int displine);
|
||||
|
||||
void (*overlay_draw)(struct svga_t *svga, int displine);
|
||||
|
||||
void (*vblank_start)(struct svga_t *svga);
|
||||
|
||||
void (*ven_write)(struct svga_t *svga, uint8_t val, uint32_t addr);
|
||||
|
||||
/*If set then another device is driving the monitor output and the SVGA
|
||||
card should not attempt to display anything */
|
||||
int override;
|
||||
void *p;
|
||||
} svga_t;
|
||||
|
||||
|
||||
extern int svga_init(svga_t *svga, void *p, int memsize,
|
||||
void (*recalctimings_ex)(struct svga_t *svga),
|
||||
uint8_t (*video_in) (uint16_t addr, void *p),
|
||||
void (*video_out)(uint16_t addr, uint8_t val, void *p),
|
||||
void (*hwcursor_draw)(struct svga_t *svga, int displine),
|
||||
void (*overlay_draw)(struct svga_t *svga, int displine));
|
||||
extern void svga_recalctimings(svga_t *svga);
|
||||
extern void svga_close(svga_t *svga);
|
||||
|
||||
uint8_t svga_read(uint32_t addr, void *p);
|
||||
uint16_t svga_readw(uint32_t addr, void *p);
|
||||
uint32_t svga_readl(uint32_t addr, void *p);
|
||||
void svga_write(uint32_t addr, uint8_t val, void *p);
|
||||
void svga_writew(uint32_t addr, uint16_t val, void *p);
|
||||
void svga_writel(uint32_t addr, uint32_t val, void *p);
|
||||
uint8_t svga_read_linear(uint32_t addr, void *p);
|
||||
uint8_t svga_readb_linear(uint32_t addr, void *p);
|
||||
uint16_t svga_readw_linear(uint32_t addr, void *p);
|
||||
uint32_t svga_readl_linear(uint32_t addr, void *p);
|
||||
void svga_write_linear(uint32_t addr, uint8_t val, void *p);
|
||||
void svga_writeb_linear(uint32_t addr, uint8_t val, void *p);
|
||||
void svga_writew_linear(uint32_t addr, uint16_t val, void *p);
|
||||
void svga_writel_linear(uint32_t addr, uint32_t val, void *p);
|
||||
|
||||
void svga_add_status_info(char *s, int max_len, void *p);
|
||||
|
||||
extern uint8_t svga_rotate[8][256];
|
||||
|
||||
void svga_out(uint16_t addr, uint8_t val, void *p);
|
||||
uint8_t svga_in(uint16_t addr, void *p);
|
||||
|
||||
svga_t *svga_get_pri();
|
||||
void svga_set_override(svga_t *svga, int val);
|
||||
|
||||
void svga_set_ven_write(svga_t *svga,
|
||||
void (*ven_write)(struct svga_t *svga, uint8_t val, uint32_t addr));
|
||||
|
||||
void svga_set_ramdac_type(svga_t *svga, int type);
|
||||
void svga_close(svga_t *svga);
|
||||
|
||||
uint32_t svga_mask_addr(uint32_t addr, svga_t *svga);
|
||||
uint32_t svga_mask_changedaddr(uint32_t addr, svga_t *svga);
|
||||
|
||||
void svga_doblit(int y1, int y2, int wx, int wy, svga_t *svga);
|
||||
|
||||
|
||||
enum {
|
||||
RAMDAC_6BIT = 0,
|
||||
RAMDAC_8BIT
|
||||
};
|
||||
|
||||
extern uint32_t shade[5][256];
|
||||
|
||||
|
||||
static __inline__ uint32_t
|
||||
svga_color_transform(uint32_t color)
|
||||
{
|
||||
uint8_t *clr8 = (uint8_t *) &color;
|
||||
if (!video_grayscale && !invert_display)
|
||||
return color;
|
||||
if (video_grayscale) {
|
||||
if (video_graytype) {
|
||||
if (video_graytype == 1)
|
||||
color = ((54 * (uint32_t)clr8[2]) + (183 * (uint32_t)clr8[1]) + (18 * (uint32_t)clr8[0])) / 255;
|
||||
else
|
||||
color = ((uint32_t)clr8[2] + (uint32_t)clr8[1] + (uint32_t)clr8[0]) / 3;
|
||||
} else
|
||||
color = ((76 * (uint32_t)clr8[2]) + (150 * (uint32_t)clr8[1]) + (29 * (uint32_t)clr8[0])) / 255;
|
||||
switch (video_grayscale) {
|
||||
case 2: case 3: case 4:
|
||||
color = shade[video_grayscale][color];
|
||||
break;
|
||||
default:
|
||||
clr8[3] = 0;
|
||||
clr8[0] = color;
|
||||
clr8[1] = clr8[2] = clr8[0];
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (invert_display)
|
||||
color ^= 0x00ffffff;
|
||||
return color;
|
||||
}
|
||||
934
backup code/video - Cópia/vid_svga_render.c
Normal file
934
backup code/video - Cópia/vid_svga_render.c
Normal file
@@ -0,0 +1,934 @@
|
||||
/*
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
*
|
||||
* This file is part of the 86Box distribution.
|
||||
*
|
||||
* SVGA renderers.
|
||||
*
|
||||
* Version: @(#)vid_svga_render.c 1.0.10 2018/03/19
|
||||
*
|
||||
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
*
|
||||
* Copyright 2008-2018 Sarah Walker.
|
||||
* Copyright 2016-2018 Miran Grca.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <wchar.h>
|
||||
#include "../86box.h"
|
||||
#include "../mem.h"
|
||||
#include "video.h"
|
||||
#include "vid_svga.h"
|
||||
#include "vid_svga_render.h"
|
||||
|
||||
|
||||
int invert_display = 0;
|
||||
int video_grayscale = 0;
|
||||
int video_graytype = 0;
|
||||
|
||||
|
||||
uint32_t shade[5][256] =
|
||||
{
|
||||
{0}, // RGB Color (unused)
|
||||
{0}, // RGB Grayscale (unused)
|
||||
{ // Amber monitor
|
||||
0x000000, 0x060000, 0x090000, 0x0d0000, 0x100000, 0x120100, 0x150100, 0x170100, 0x1a0100, 0x1c0100, 0x1e0200, 0x210200, 0x230200, 0x250300, 0x270300, 0x290300,
|
||||
0x2b0400, 0x2d0400, 0x2f0400, 0x300500, 0x320500, 0x340500, 0x360600, 0x380600, 0x390700, 0x3b0700, 0x3d0700, 0x3f0800, 0x400800, 0x420900, 0x440900, 0x450a00,
|
||||
0x470a00, 0x480b00, 0x4a0b00, 0x4c0c00, 0x4d0c00, 0x4f0d00, 0x500d00, 0x520e00, 0x530e00, 0x550f00, 0x560f00, 0x581000, 0x591000, 0x5b1100, 0x5c1200, 0x5e1200,
|
||||
0x5f1300, 0x601300, 0x621400, 0x631500, 0x651500, 0x661600, 0x671600, 0x691700, 0x6a1800, 0x6c1800, 0x6d1900, 0x6e1a00, 0x701a00, 0x711b00, 0x721c00, 0x741c00,
|
||||
0x751d00, 0x761e00, 0x781e00, 0x791f00, 0x7a2000, 0x7c2000, 0x7d2100, 0x7e2200, 0x7f2300, 0x812300, 0x822400, 0x832500, 0x842600, 0x862600, 0x872700, 0x882800,
|
||||
0x8a2900, 0x8b2900, 0x8c2a00, 0x8d2b00, 0x8e2c00, 0x902c00, 0x912d00, 0x922e00, 0x932f00, 0x953000, 0x963000, 0x973100, 0x983200, 0x993300, 0x9b3400, 0x9c3400,
|
||||
0x9d3500, 0x9e3600, 0x9f3700, 0xa03800, 0xa23900, 0xa33a00, 0xa43a00, 0xa53b00, 0xa63c00, 0xa73d00, 0xa93e00, 0xaa3f00, 0xab4000, 0xac4000, 0xad4100, 0xae4200,
|
||||
0xaf4300, 0xb14400, 0xb24500, 0xb34600, 0xb44700, 0xb54800, 0xb64900, 0xb74a00, 0xb94a00, 0xba4b00, 0xbb4c00, 0xbc4d00, 0xbd4e00, 0xbe4f00, 0xbf5000, 0xc05100,
|
||||
0xc15200, 0xc25300, 0xc45400, 0xc55500, 0xc65600, 0xc75700, 0xc85800, 0xc95900, 0xca5a00, 0xcb5b00, 0xcc5c00, 0xcd5d00, 0xce5e00, 0xcf5f00, 0xd06000, 0xd26101,
|
||||
0xd36201, 0xd46301, 0xd56401, 0xd66501, 0xd76601, 0xd86701, 0xd96801, 0xda6901, 0xdb6a01, 0xdc6b01, 0xdd6c01, 0xde6d01, 0xdf6e01, 0xe06f01, 0xe17001, 0xe27201,
|
||||
0xe37301, 0xe47401, 0xe57501, 0xe67602, 0xe77702, 0xe87802, 0xe97902, 0xeb7a02, 0xec7b02, 0xed7c02, 0xee7e02, 0xef7f02, 0xf08002, 0xf18103, 0xf28203, 0xf38303,
|
||||
0xf48403, 0xf58503, 0xf68703, 0xf78803, 0xf88903, 0xf98a04, 0xfa8b04, 0xfb8c04, 0xfc8d04, 0xfd8f04, 0xfe9005, 0xff9105, 0xff9205, 0xff9305, 0xff9405, 0xff9606,
|
||||
0xff9706, 0xff9806, 0xff9906, 0xff9a07, 0xff9b07, 0xff9d07, 0xff9e08, 0xff9f08, 0xffa008, 0xffa109, 0xffa309, 0xffa409, 0xffa50a, 0xffa60a, 0xffa80a, 0xffa90b,
|
||||
0xffaa0b, 0xffab0c, 0xffac0c, 0xffae0d, 0xffaf0d, 0xffb00e, 0xffb10e, 0xffb30f, 0xffb40f, 0xffb510, 0xffb610, 0xffb811, 0xffb912, 0xffba12, 0xffbb13, 0xffbd14,
|
||||
0xffbe14, 0xffbf15, 0xffc016, 0xffc217, 0xffc317, 0xffc418, 0xffc619, 0xffc71a, 0xffc81b, 0xffca1c, 0xffcb1d, 0xffcc1e, 0xffcd1f, 0xffcf20, 0xffd021, 0xffd122,
|
||||
0xffd323, 0xffd424, 0xffd526, 0xffd727, 0xffd828, 0xffd92a, 0xffdb2b, 0xffdc2c, 0xffdd2e, 0xffdf2f, 0xffe031, 0xffe133, 0xffe334, 0xffe436, 0xffe538, 0xffe739
|
||||
},
|
||||
{ // Green monitor
|
||||
0x000000, 0x000400, 0x000700, 0x000900, 0x000b00, 0x000d00, 0x000f00, 0x001100, 0x001300, 0x001500, 0x001600, 0x001800, 0x001a00, 0x001b00, 0x001d00, 0x001e00,
|
||||
0x002000, 0x002100, 0x002300, 0x002400, 0x002601, 0x002701, 0x002901, 0x002a01, 0x002b01, 0x002d01, 0x002e01, 0x002f01, 0x003101, 0x003201, 0x003301, 0x003401,
|
||||
0x003601, 0x003702, 0x003802, 0x003902, 0x003b02, 0x003c02, 0x003d02, 0x003e02, 0x004002, 0x004102, 0x004203, 0x004303, 0x004403, 0x004503, 0x004703, 0x004803,
|
||||
0x004903, 0x004a03, 0x004b04, 0x004c04, 0x004d04, 0x004e04, 0x005004, 0x005104, 0x005205, 0x005305, 0x005405, 0x005505, 0x005605, 0x005705, 0x005806, 0x005906,
|
||||
0x005a06, 0x005b06, 0x005d06, 0x005e07, 0x005f07, 0x006007, 0x006107, 0x006207, 0x006308, 0x006408, 0x006508, 0x006608, 0x006708, 0x006809, 0x006909, 0x006a09,
|
||||
0x006b09, 0x016c0a, 0x016d0a, 0x016e0a, 0x016f0a, 0x01700b, 0x01710b, 0x01720b, 0x01730b, 0x01740c, 0x01750c, 0x01760c, 0x01770c, 0x01780d, 0x01790d, 0x017a0d,
|
||||
0x017b0d, 0x017b0e, 0x017c0e, 0x017d0e, 0x017e0f, 0x017f0f, 0x01800f, 0x018110, 0x028210, 0x028310, 0x028410, 0x028511, 0x028611, 0x028711, 0x028812, 0x028912,
|
||||
0x028a12, 0x028a13, 0x028b13, 0x028c13, 0x028d14, 0x028e14, 0x038f14, 0x039015, 0x039115, 0x039215, 0x039316, 0x039416, 0x039417, 0x039517, 0x039617, 0x039718,
|
||||
0x049818, 0x049918, 0x049a19, 0x049b19, 0x049c19, 0x049c1a, 0x049d1a, 0x049e1b, 0x059f1b, 0x05a01b, 0x05a11c, 0x05a21c, 0x05a31c, 0x05a31d, 0x05a41d, 0x06a51e,
|
||||
0x06a61e, 0x06a71f, 0x06a81f, 0x06a920, 0x06aa20, 0x07aa21, 0x07ab21, 0x07ac21, 0x07ad22, 0x07ae22, 0x08af23, 0x08b023, 0x08b024, 0x08b124, 0x08b225, 0x09b325,
|
||||
0x09b426, 0x09b526, 0x09b527, 0x0ab627, 0x0ab728, 0x0ab828, 0x0ab929, 0x0bba29, 0x0bba2a, 0x0bbb2a, 0x0bbc2b, 0x0cbd2b, 0x0cbe2c, 0x0cbf2c, 0x0dbf2d, 0x0dc02d,
|
||||
0x0dc12e, 0x0ec22e, 0x0ec32f, 0x0ec42f, 0x0fc430, 0x0fc530, 0x0fc631, 0x10c731, 0x10c832, 0x10c932, 0x11c933, 0x11ca33, 0x11cb34, 0x12cc35, 0x12cd35, 0x12cd36,
|
||||
0x13ce36, 0x13cf37, 0x13d037, 0x14d138, 0x14d139, 0x14d239, 0x15d33a, 0x15d43a, 0x16d43b, 0x16d53b, 0x17d63c, 0x17d73d, 0x17d83d, 0x18d83e, 0x18d93e, 0x19da3f,
|
||||
0x19db40, 0x1adc40, 0x1adc41, 0x1bdd41, 0x1bde42, 0x1cdf43, 0x1ce043, 0x1de044, 0x1ee145, 0x1ee245, 0x1fe346, 0x1fe446, 0x20e447, 0x20e548, 0x21e648, 0x22e749,
|
||||
0x22e74a, 0x23e84a, 0x23e94b, 0x24ea4c, 0x25ea4c, 0x25eb4d, 0x26ec4e, 0x27ed4e, 0x27ee4f, 0x28ee50, 0x29ef50, 0x29f051, 0x2af152, 0x2bf153, 0x2cf253, 0x2cf354,
|
||||
0x2df455, 0x2ef455, 0x2ff556, 0x2ff657, 0x30f758, 0x31f758, 0x32f859, 0x32f95a, 0x33fa5a, 0x34fa5b, 0x35fb5c, 0x36fc5d, 0x37fd5d, 0x38fd5e, 0x38fe5f, 0x39ff60
|
||||
},
|
||||
{ // White monitor
|
||||
0x000000, 0x010102, 0x020203, 0x020304, 0x030406, 0x040507, 0x050608, 0x060709, 0x07080a, 0x08090c, 0x080a0d, 0x090b0e, 0x0a0c0f, 0x0b0d10, 0x0c0e11, 0x0d0f12,
|
||||
0x0e1013, 0x0f1115, 0x101216, 0x111317, 0x121418, 0x121519, 0x13161a, 0x14171b, 0x15181c, 0x16191d, 0x171a1e, 0x181b1f, 0x191c20, 0x1a1d21, 0x1b1e22, 0x1c1f23,
|
||||
0x1d2024, 0x1e2125, 0x1f2226, 0x202327, 0x212428, 0x222529, 0x22262b, 0x23272c, 0x24282d, 0x25292e, 0x262a2f, 0x272b30, 0x282c30, 0x292d31, 0x2a2e32, 0x2b2f33,
|
||||
0x2c3034, 0x2d3035, 0x2e3136, 0x2f3237, 0x303338, 0x313439, 0x32353a, 0x33363b, 0x34373c, 0x35383d, 0x36393e, 0x373a3f, 0x383b40, 0x393c41, 0x3a3d42, 0x3b3e43,
|
||||
0x3c3f44, 0x3d4045, 0x3e4146, 0x3f4247, 0x404348, 0x414449, 0x42454a, 0x43464b, 0x44474c, 0x45484d, 0x46494d, 0x474a4e, 0x484b4f, 0x484c50, 0x494d51, 0x4a4e52,
|
||||
0x4b4f53, 0x4c5054, 0x4d5155, 0x4e5256, 0x4f5357, 0x505458, 0x515559, 0x52565a, 0x53575b, 0x54585b, 0x55595c, 0x565a5d, 0x575b5e, 0x585c5f, 0x595d60, 0x5a5e61,
|
||||
0x5b5f62, 0x5c6063, 0x5d6164, 0x5e6265, 0x5f6366, 0x606466, 0x616567, 0x626668, 0x636769, 0x64686a, 0x65696b, 0x666a6c, 0x676b6d, 0x686c6e, 0x696d6f, 0x6a6e70,
|
||||
0x6b6f70, 0x6c7071, 0x6d7172, 0x6f7273, 0x707374, 0x707475, 0x717576, 0x727677, 0x747778, 0x757879, 0x767979, 0x777a7a, 0x787b7b, 0x797c7c, 0x7a7d7d, 0x7b7e7e,
|
||||
0x7c7f7f, 0x7d8080, 0x7e8181, 0x7f8281, 0x808382, 0x818483, 0x828584, 0x838685, 0x848786, 0x858887, 0x868988, 0x878a89, 0x888b89, 0x898c8a, 0x8a8d8b, 0x8b8e8c,
|
||||
0x8c8f8d, 0x8d8f8e, 0x8e908f, 0x8f9190, 0x909290, 0x919391, 0x929492, 0x939593, 0x949694, 0x959795, 0x969896, 0x979997, 0x989a98, 0x999b98, 0x9a9c99, 0x9b9d9a,
|
||||
0x9c9e9b, 0x9d9f9c, 0x9ea09d, 0x9fa19e, 0xa0a29f, 0xa1a39f, 0xa2a4a0, 0xa3a5a1, 0xa4a6a2, 0xa6a7a3, 0xa7a8a4, 0xa8a9a5, 0xa9aaa5, 0xaaaba6, 0xabaca7, 0xacada8,
|
||||
0xadaea9, 0xaeafaa, 0xafb0ab, 0xb0b1ac, 0xb1b2ac, 0xb2b3ad, 0xb3b4ae, 0xb4b5af, 0xb5b6b0, 0xb6b7b1, 0xb7b8b2, 0xb8b9b2, 0xb9bab3, 0xbabbb4, 0xbbbcb5, 0xbcbdb6,
|
||||
0xbdbeb7, 0xbebfb8, 0xbfc0b8, 0xc0c1b9, 0xc1c2ba, 0xc2c3bb, 0xc3c4bc, 0xc5c5bd, 0xc6c6be, 0xc7c7be, 0xc8c8bf, 0xc9c9c0, 0xcacac1, 0xcbcbc2, 0xccccc3, 0xcdcdc3,
|
||||
0xcecec4, 0xcfcfc5, 0xd0d0c6, 0xd1d1c7, 0xd2d2c8, 0xd3d3c9, 0xd4d4c9, 0xd5d5ca, 0xd6d6cb, 0xd7d7cc, 0xd8d8cd, 0xd9d9ce, 0xdadacf, 0xdbdbcf, 0xdcdcd0, 0xdeddd1,
|
||||
0xdfded2, 0xe0dfd3, 0xe1e0d4, 0xe2e1d4, 0xe3e2d5, 0xe4e3d6, 0xe5e4d7, 0xe6e5d8, 0xe7e6d9, 0xe8e7d9, 0xe9e8da, 0xeae9db, 0xebeadc, 0xecebdd, 0xedecde, 0xeeeddf,
|
||||
0xefeedf, 0xf0efe0, 0xf1f0e1, 0xf2f1e2, 0xf3f2e3, 0xf4f3e3, 0xf6f3e4, 0xf7f4e5, 0xf8f5e6, 0xf9f6e7, 0xfaf7e8, 0xfbf8e9, 0xfcf9e9, 0xfdfaea, 0xfefbeb, 0xfffcec
|
||||
}
|
||||
};
|
||||
|
||||
void svga_render_blank(svga_t *svga)
|
||||
{
|
||||
int x, xx;
|
||||
int y_add = enable_overscan ? (overscan_y >> 1) : 0;
|
||||
int x_add = enable_overscan ? 8 : 0;
|
||||
|
||||
if (svga->firstline_draw == 2000)
|
||||
svga->firstline_draw = svga->displine;
|
||||
svga->lastline_draw = svga->displine;
|
||||
|
||||
for (x = 0; x < svga->hdisp; x++)
|
||||
{
|
||||
switch (svga->seqregs[1] & 9)
|
||||
{
|
||||
case 0:
|
||||
for (xx = 0; xx < 9; xx++) ((uint32_t *)buffer32->line[svga->displine + y_add])[(x * 9) + xx + 32 + x_add] = svga_color_transform(0);
|
||||
break;
|
||||
case 1:
|
||||
for (xx = 0; xx < 8; xx++) ((uint32_t *)buffer32->line[svga->displine + y_add])[(x * 8) + xx + 32 + x_add] = svga_color_transform(0);
|
||||
break;
|
||||
case 8:
|
||||
for (xx = 0; xx < 18; xx++) ((uint32_t *)buffer32->line[svga->displine + y_add])[(x * 18) + xx + 32 + x_add] = svga_color_transform(0);
|
||||
break;
|
||||
case 9:
|
||||
for (xx = 0; xx < 16; xx++) ((uint32_t *)buffer32->line[svga->displine + y_add])[(x * 16) + xx + 32 + x_add] = svga_color_transform(0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void svga_render_text_40(svga_t *svga)
|
||||
{
|
||||
int y_add = enable_overscan ? (overscan_y >> 1) : 0;
|
||||
int x_add = enable_overscan ? 8 : 0;
|
||||
|
||||
if (svga->firstline_draw == 2000)
|
||||
svga->firstline_draw = svga->displine;
|
||||
svga->lastline_draw = svga->displine;
|
||||
|
||||
if (svga->fullchange)
|
||||
{
|
||||
uint32_t *p = &((uint32_t *)buffer32->line[svga->displine + y_add])[32 + x_add];
|
||||
int x, xx;
|
||||
int drawcursor;
|
||||
uint8_t chr, attr, dat;
|
||||
uint32_t charaddr;
|
||||
int fg, bg;
|
||||
int xinc = (svga->seqregs[1] & 1) ? 16 : 18;
|
||||
|
||||
for (x = 0; x < svga->hdisp; x += xinc)
|
||||
{
|
||||
drawcursor = ((svga->ma == svga->ca) && svga->con && svga->cursoron);
|
||||
chr = svga->vram[(svga->ma << 1) & svga->vram_display_mask];
|
||||
attr = svga->vram[((svga->ma << 1) + 1) & svga->vram_display_mask];
|
||||
if (attr & 8) charaddr = svga->charsetb + (chr * 128);
|
||||
else charaddr = svga->charseta + (chr * 128);
|
||||
|
||||
if (drawcursor)
|
||||
{
|
||||
bg = svga->pallook[svga->egapal[attr & 15]];
|
||||
fg = svga->pallook[svga->egapal[attr >> 4]];
|
||||
}
|
||||
else
|
||||
{
|
||||
fg = svga->pallook[svga->egapal[attr & 15]];
|
||||
bg = svga->pallook[svga->egapal[attr >> 4]];
|
||||
if (attr & 0x80 && svga->attrregs[0x10] & 8)
|
||||
{
|
||||
bg = svga->pallook[svga->egapal[(attr >> 4) & 7]];
|
||||
if (svga->blink & 16)
|
||||
fg = bg;
|
||||
}
|
||||
}
|
||||
|
||||
fg = svga_color_transform(fg);
|
||||
bg = svga_color_transform(bg);
|
||||
|
||||
dat = svga->vram[charaddr + (svga->sc << 2)];
|
||||
if (svga->seqregs[1] & 1)
|
||||
{
|
||||
for (xx = 0; xx < 16; xx += 2)
|
||||
p[xx] = p[xx + 1] = (dat & (0x80 >> (xx >> 1))) ? fg : bg;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (xx = 0; xx < 16; xx += 2)
|
||||
p[xx] = p[xx + 1] = (dat & (0x80 >> (xx >> 1))) ? fg : bg;
|
||||
if ((chr & ~0x1F) != 0xC0 || !(svga->attrregs[0x10] & 4))
|
||||
p[16] = p[17] = bg;
|
||||
else
|
||||
p[16] = p[17] = (dat & 1) ? fg : bg;
|
||||
}
|
||||
svga->ma += 4;
|
||||
p += xinc;
|
||||
}
|
||||
svga->ma &= svga->vram_display_mask;
|
||||
}
|
||||
}
|
||||
|
||||
void svga_render_text_80(svga_t *svga)
|
||||
{
|
||||
int y_add = enable_overscan ? (overscan_y >> 1) : 0;
|
||||
int x_add = enable_overscan ? 8 : 0;
|
||||
|
||||
if (svga->firstline_draw == 2000)
|
||||
svga->firstline_draw = svga->displine;
|
||||
svga->lastline_draw = svga->displine;
|
||||
|
||||
if (svga->fullchange)
|
||||
{
|
||||
uint32_t *p = &((uint32_t *)buffer32->line[svga->displine + y_add])[32 + x_add];
|
||||
int x, xx;
|
||||
int drawcursor;
|
||||
uint8_t chr, attr, dat;
|
||||
uint32_t charaddr;
|
||||
int fg, bg;
|
||||
int xinc = (svga->seqregs[1] & 1) ? 8 : 9;
|
||||
|
||||
for (x = 0; x < svga->hdisp; x += xinc)
|
||||
{
|
||||
drawcursor = ((svga->ma == svga->ca) && svga->con && svga->cursoron);
|
||||
chr = svga->vram[(svga->ma << 1) & svga->vram_display_mask];
|
||||
attr = svga->vram[((svga->ma << 1) + 1) & svga->vram_display_mask];
|
||||
|
||||
|
||||
if (attr & 8) charaddr = svga->charsetb + (chr * 128);
|
||||
else charaddr = svga->charseta + (chr * 128);
|
||||
|
||||
if (drawcursor)
|
||||
{
|
||||
bg = svga->pallook[svga->egapal[attr & 15]];
|
||||
fg = svga->pallook[svga->egapal[attr >> 4]];
|
||||
}
|
||||
else
|
||||
{
|
||||
fg = svga->pallook[svga->egapal[attr & 15]];
|
||||
bg = svga->pallook[svga->egapal[attr >> 4]];
|
||||
if (attr & 0x80 && svga->attrregs[0x10] & 8)
|
||||
{
|
||||
bg = svga->pallook[svga->egapal[(attr >> 4) & 7]];
|
||||
if (svga->blink & 16)
|
||||
fg = bg;
|
||||
}
|
||||
}
|
||||
|
||||
fg = svga_color_transform(fg);
|
||||
bg = svga_color_transform(bg);
|
||||
|
||||
dat = svga->vram[charaddr + (svga->sc << 2)];
|
||||
if (svga->seqregs[1] & 1)
|
||||
{
|
||||
for (xx = 0; xx < 8; xx++)
|
||||
p[xx] = (dat & (0x80 >> xx)) ? fg : bg;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (xx = 0; xx < 8; xx++)
|
||||
p[xx] = (dat & (0x80 >> xx)) ? fg : bg;
|
||||
if ((chr & ~0x1F) != 0xC0 || !(svga->attrregs[0x10] & 4))
|
||||
p[8] = bg;
|
||||
else
|
||||
p[8] = (dat & 1) ? fg : bg;
|
||||
}
|
||||
svga->ma += 4;
|
||||
p += xinc;
|
||||
}
|
||||
svga->ma &= svga->vram_display_mask;
|
||||
}
|
||||
}
|
||||
|
||||
void svga_render_text_80_ksc5601(svga_t *svga)
|
||||
{
|
||||
int y_add = enable_overscan ? (overscan_y >> 1) : 0;
|
||||
int x_add = enable_overscan ? 8 : 0;
|
||||
|
||||
if (svga->firstline_draw == 2000)
|
||||
svga->firstline_draw = svga->displine;
|
||||
svga->lastline_draw = svga->displine;
|
||||
|
||||
if (svga->fullchange)
|
||||
{
|
||||
uint32_t *p = &((uint32_t *)buffer32->line[svga->displine + y_add])[32 + x_add];
|
||||
int x, xx;
|
||||
int drawcursor;
|
||||
uint8_t chr, attr, dat, nextchr;
|
||||
uint32_t charaddr;
|
||||
int fg, bg;
|
||||
int xinc = (svga->seqregs[1] & 1) ? 8 : 9;
|
||||
|
||||
for (x = 0; x < svga->hdisp; x += xinc)
|
||||
{
|
||||
drawcursor = ((svga->ma == svga->ca) && svga->con && svga->cursoron);
|
||||
chr = svga->vram[(svga->ma << 1) & svga->vram_display_mask];
|
||||
nextchr = svga->vram[((svga->ma + 4) << 1) & svga->vram_display_mask];
|
||||
attr = svga->vram[((svga->ma << 1) + 1) & svga->vram_display_mask];
|
||||
|
||||
|
||||
if (drawcursor)
|
||||
{
|
||||
bg = svga->pallook[svga->egapal[attr & 15]];
|
||||
fg = svga->pallook[svga->egapal[attr >> 4]];
|
||||
}
|
||||
else
|
||||
{
|
||||
fg = svga->pallook[svga->egapal[attr & 15]];
|
||||
bg = svga->pallook[svga->egapal[attr >> 4]];
|
||||
if (attr & 0x80 && svga->attrregs[0x10] & 8)
|
||||
{
|
||||
bg = svga->pallook[svga->egapal[(attr >> 4) & 7]];
|
||||
if (svga->blink & 16)
|
||||
fg = bg;
|
||||
}
|
||||
}
|
||||
|
||||
fg = svga_color_transform(fg);
|
||||
bg = svga_color_transform(bg);
|
||||
|
||||
if(x + xinc < svga->hdisp && (chr & nextchr & 0x80))
|
||||
{
|
||||
if((chr == 0xc9 || chr == 0xfe) && (nextchr > 0xa0 && nextchr < 0xff))
|
||||
dat = fontdatksc5601_user[(chr == 0xfe ? 96 : 0) + (nextchr & 0x7F) - 0x20].chr[svga->sc];
|
||||
else
|
||||
dat = fontdatksc5601[((chr & 0x7F) << 7) | (nextchr & 0x7F)].chr[svga->sc];
|
||||
}
|
||||
else
|
||||
{
|
||||
if (attr & 8) charaddr = svga->charsetb + (chr * 128);
|
||||
else charaddr = svga->charseta + (chr * 128);
|
||||
|
||||
dat = svga->vram[charaddr + (svga->sc << 2)];
|
||||
}
|
||||
if (svga->seqregs[1] & 1)
|
||||
{
|
||||
for (xx = 0; xx < 8; xx++)
|
||||
p[xx] = (dat & (0x80 >> xx)) ? fg : bg;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (xx = 0; xx < 8; xx++)
|
||||
p[xx] = (dat & (0x80 >> xx)) ? fg : bg;
|
||||
if ((chr & ~0x1F) != 0xC0 || !(svga->attrregs[0x10] & 4))
|
||||
p[8] = bg;
|
||||
else
|
||||
p[8] = (dat & 1) ? fg : bg;
|
||||
}
|
||||
svga->ma += 4;
|
||||
p += xinc;
|
||||
|
||||
if(x + xinc < svga->hdisp && (chr & nextchr & 0x80))
|
||||
{
|
||||
attr = svga->vram[((svga->ma << 1) + 1) & svga->vram_display_mask];
|
||||
|
||||
if (drawcursor)
|
||||
{
|
||||
bg = svga->pallook[svga->egapal[attr & 15]];
|
||||
fg = svga->pallook[svga->egapal[attr >> 4]];
|
||||
}
|
||||
else
|
||||
{
|
||||
fg = svga->pallook[svga->egapal[attr & 15]];
|
||||
bg = svga->pallook[svga->egapal[attr >> 4]];
|
||||
if (attr & 0x80 && svga->attrregs[0x10] & 8)
|
||||
{
|
||||
bg = svga->pallook[svga->egapal[(attr >> 4) & 7]];
|
||||
if (svga->blink & 16)
|
||||
fg = bg;
|
||||
}
|
||||
}
|
||||
|
||||
if((chr == 0xc9 || chr == 0xfe) && (nextchr > 0xa0 && nextchr < 0xff))
|
||||
dat = fontdatksc5601_user[(chr == 0xfe ? 96 : 0) + (nextchr & 0x7F) - 0x20].chr[svga->sc + 16];
|
||||
else
|
||||
dat = fontdatksc5601[((chr & 0x7F) << 7) | (nextchr & 0x7F)].chr[svga->sc + 16];
|
||||
if (svga->seqregs[1] & 1)
|
||||
{
|
||||
for (xx = 0; xx < 8; xx++)
|
||||
p[xx] = (dat & (0x80 >> xx)) ? fg : bg;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (xx = 0; xx < 8; xx++)
|
||||
p[xx] = (dat & (0x80 >> xx)) ? fg : bg;
|
||||
if ((chr & ~0x1F) != 0xC0 || !(svga->attrregs[0x10] & 4))
|
||||
p[8] = bg;
|
||||
else
|
||||
p[8] = (dat & 1) ? fg : bg;
|
||||
}
|
||||
|
||||
svga->ma += 4;
|
||||
p += xinc;
|
||||
x += xinc;
|
||||
}
|
||||
}
|
||||
svga->ma &= svga->vram_display_mask;
|
||||
}
|
||||
}
|
||||
|
||||
void svga_render_2bpp_lowres(svga_t *svga)
|
||||
{
|
||||
int changed_offset;
|
||||
|
||||
int y_add = enable_overscan ? (overscan_y >> 1) : 0;
|
||||
int x_add = enable_overscan ? 8 : 0;
|
||||
|
||||
changed_offset = ((svga->ma << 1) + (svga->sc & ~svga->crtc[0x17] & 3) * 0x8000) >> 12;
|
||||
|
||||
if (svga->changedvram[changed_offset] || svga->changedvram[changed_offset + 1] || svga->fullchange)
|
||||
{
|
||||
int x;
|
||||
int offset = ((8 - svga->scrollcache) << 1) + 16;
|
||||
uint32_t *p = &((uint32_t *)buffer32->line[svga->displine + y_add])[offset + x_add];
|
||||
|
||||
if (svga->firstline_draw == 2000)
|
||||
svga->firstline_draw = svga->displine;
|
||||
svga->lastline_draw = svga->displine;
|
||||
|
||||
for (x = 0; x <= svga->hdisp; x += 16)
|
||||
{
|
||||
uint8_t dat[2];
|
||||
|
||||
dat[0] = svga->vram[(svga->ma << 1) + ((svga->sc & ~svga->crtc[0x17] & 3)) * 0x8000];
|
||||
dat[1] = svga->vram[(svga->ma << 1) + ((svga->sc & ~svga->crtc[0x17] & 3)) * 0x8000 + 1];
|
||||
svga->ma += 4;
|
||||
svga->ma &= svga->vram_display_mask;
|
||||
|
||||
p[0] = p[1] = svga_color_transform(svga->pallook[svga->egapal[(dat[0] >> 6) & 3]]);
|
||||
p[2] = p[3] = svga_color_transform(svga->pallook[svga->egapal[(dat[0] >> 4) & 3]]);
|
||||
p[4] = p[5] = svga_color_transform(svga->pallook[svga->egapal[(dat[0] >> 2) & 3]]);
|
||||
p[6] = p[7] = svga_color_transform(svga->pallook[svga->egapal[dat[0] & 3]]);
|
||||
p[8] = p[9] = svga_color_transform(svga->pallook[svga->egapal[(dat[1] >> 6) & 3]]);
|
||||
p[10] = p[11] = svga_color_transform(svga->pallook[svga->egapal[(dat[1] >> 4) & 3]]);
|
||||
p[12] = p[13] = svga_color_transform(svga->pallook[svga->egapal[(dat[1] >> 2) & 3]]);
|
||||
p[14] = p[15] = svga_color_transform(svga->pallook[svga->egapal[dat[1] & 3]]);
|
||||
|
||||
p += 16;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void svga_render_2bpp_highres(svga_t *svga)
|
||||
{
|
||||
int changed_offset;
|
||||
|
||||
int y_add = enable_overscan ? (overscan_y >> 1) : 0;
|
||||
int x_add = enable_overscan ? 8 : 0;
|
||||
|
||||
changed_offset = ((svga->ma << 1) + (svga->sc & ~svga->crtc[0x17] & 3) * 0x8000) >> 12;
|
||||
|
||||
if (svga->changedvram[changed_offset] || svga->changedvram[changed_offset + 1] || svga->fullchange)
|
||||
{
|
||||
int x;
|
||||
int offset = (8 - svga->scrollcache) + 24;
|
||||
uint32_t *p = &((uint32_t *)buffer32->line[svga->displine + y_add])[offset + x_add];
|
||||
|
||||
if (svga->firstline_draw == 2000)
|
||||
svga->firstline_draw = svga->displine;
|
||||
svga->lastline_draw = svga->displine;
|
||||
|
||||
for (x = 0; x <= svga->hdisp; x += 8)
|
||||
{
|
||||
uint8_t dat[2];
|
||||
|
||||
dat[0] = svga->vram[(svga->ma << 1) + ((svga->sc & ~svga->crtc[0x17] & 3)) * 0x8000];
|
||||
dat[1] = svga->vram[(svga->ma << 1) + ((svga->sc & ~svga->crtc[0x17] & 3)) * 0x8000 + 1];
|
||||
svga->ma += 4;
|
||||
svga->ma &= svga->vram_display_mask;
|
||||
|
||||
p[0] = svga_color_transform(svga->pallook[svga->egapal[(dat[0] >> 6) & 3]]);
|
||||
p[1] = svga_color_transform(svga->pallook[svga->egapal[(dat[0] >> 4) & 3]]);
|
||||
p[2] = svga_color_transform(svga->pallook[svga->egapal[(dat[0] >> 2) & 3]]);
|
||||
p[3] = svga_color_transform(svga->pallook[svga->egapal[dat[0] & 3]]);
|
||||
p[4] = svga_color_transform(svga->pallook[svga->egapal[(dat[1] >> 6) & 3]]);
|
||||
p[5] = svga_color_transform(svga->pallook[svga->egapal[(dat[1] >> 4) & 3]]);
|
||||
p[6] = svga_color_transform(svga->pallook[svga->egapal[(dat[1] >> 2) & 3]]);
|
||||
p[7] = svga_color_transform(svga->pallook[svga->egapal[dat[1] & 3]]);
|
||||
|
||||
p += 8;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void svga_render_4bpp_lowres(svga_t *svga)
|
||||
{
|
||||
int y_add = enable_overscan ? (overscan_y >> 1) : 0;
|
||||
int x_add = enable_overscan ? 8 : 0;
|
||||
|
||||
if (svga->changedvram[svga->ma >> 12] || svga->changedvram[(svga->ma >> 12) + 1] || svga->fullchange)
|
||||
{
|
||||
int x;
|
||||
int offset = ((8 - svga->scrollcache) << 1) + 16;
|
||||
uint32_t *p = &((uint32_t *)buffer32->line[svga->displine + y_add])[offset + x_add];
|
||||
|
||||
if (svga->firstline_draw == 2000)
|
||||
svga->firstline_draw = svga->displine;
|
||||
svga->lastline_draw = svga->displine;
|
||||
|
||||
for (x = 0; x <= svga->hdisp; x += 16)
|
||||
{
|
||||
uint8_t edat[4];
|
||||
uint8_t dat;
|
||||
|
||||
*(uint32_t *)(&edat[0]) = *(uint32_t *)(&svga->vram[svga->ma]);
|
||||
svga->ma += 4;
|
||||
svga->ma &= svga->vram_display_mask;
|
||||
|
||||
dat = edatlookup[edat[0] >> 6][edat[1] >> 6] | (edatlookup[edat[2] >> 6][edat[3] >> 6] << 2);
|
||||
p[0] = p[1] = svga_color_transform(svga->pallook[svga->egapal[(dat >> 4) & svga->plane_mask]]);
|
||||
p[2] = p[3] = svga_color_transform(svga->pallook[svga->egapal[dat & svga->plane_mask]]);
|
||||
dat = edatlookup[(edat[0] >> 4) & 3][(edat[1] >> 4) & 3] | (edatlookup[(edat[2] >> 4) & 3][(edat[3] >> 4) & 3] << 2);
|
||||
p[4] = p[5] = svga_color_transform(svga->pallook[svga->egapal[(dat >> 4) & svga->plane_mask]]);
|
||||
p[6] = p[7] = svga_color_transform(svga->pallook[svga->egapal[dat & svga->plane_mask]]);
|
||||
dat = edatlookup[(edat[0] >> 2) & 3][(edat[1] >> 2) & 3] | (edatlookup[(edat[2] >> 2) & 3][(edat[3] >> 2) & 3] << 2);
|
||||
p[8] = p[9] = svga_color_transform(svga->pallook[svga->egapal[(dat >> 4) & svga->plane_mask]]);
|
||||
p[10] = p[11] = svga_color_transform(svga->pallook[svga->egapal[dat & svga->plane_mask]]);
|
||||
dat = edatlookup[edat[0] & 3][edat[1] & 3] | (edatlookup[edat[2] & 3][edat[3] & 3] << 2);
|
||||
p[12] = p[13] = svga_color_transform(svga->pallook[svga->egapal[(dat >> 4) & svga->plane_mask]]);
|
||||
p[14] = p[15] = svga_color_transform(svga->pallook[svga->egapal[dat & svga->plane_mask]]);
|
||||
|
||||
p += 16;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void svga_render_4bpp_highres(svga_t *svga)
|
||||
{
|
||||
int changed_offset;
|
||||
|
||||
int y_add = enable_overscan ? (overscan_y >> 1) : 0;
|
||||
int x_add = enable_overscan ? 8 : 0;
|
||||
|
||||
changed_offset = (svga->ma + (svga->sc & ~svga->crtc[0x17] & 3) * 0x8000) >> 12;
|
||||
|
||||
if (svga->changedvram[changed_offset] || svga->changedvram[changed_offset + 1] || svga->fullchange)
|
||||
{
|
||||
int x;
|
||||
int offset = (8 - svga->scrollcache) + 24;
|
||||
uint32_t *p = &((uint32_t *)buffer32->line[svga->displine + y_add])[offset + x_add];
|
||||
|
||||
if (svga->firstline_draw == 2000)
|
||||
svga->firstline_draw = svga->displine;
|
||||
svga->lastline_draw = svga->displine;
|
||||
|
||||
for (x = 0; x <= svga->hdisp; x += 8)
|
||||
{
|
||||
uint8_t edat[4];
|
||||
uint8_t dat;
|
||||
|
||||
*(uint32_t *)(&edat[0]) = *(uint32_t *)(&svga->vram[svga->ma | ((svga->sc & ~svga->crtc[0x17] & 3)) * 0x8000]);
|
||||
svga->ma += 4;
|
||||
svga->ma &= svga->vram_display_mask;
|
||||
|
||||
dat = edatlookup[edat[0] >> 6][edat[1] >> 6] | (edatlookup[edat[2] >> 6][edat[3] >> 6] << 2);
|
||||
p[0] = svga_color_transform(svga->pallook[svga->egapal[(dat >> 4) & svga->plane_mask]]);
|
||||
p[1] = svga_color_transform(svga->pallook[svga->egapal[dat & svga->plane_mask]]);
|
||||
dat = edatlookup[(edat[0] >> 4) & 3][(edat[1] >> 4) & 3] | (edatlookup[(edat[2] >> 4) & 3][(edat[3] >> 4) & 3] << 2);
|
||||
p[2] = svga_color_transform(svga->pallook[svga->egapal[(dat >> 4) & svga->plane_mask]]);
|
||||
p[3] = svga_color_transform(svga->pallook[svga->egapal[dat & svga->plane_mask]]);
|
||||
dat = edatlookup[(edat[0] >> 2) & 3][(edat[1] >> 2) & 3] | (edatlookup[(edat[2] >> 2) & 3][(edat[3] >> 2) & 3] << 2);
|
||||
p[4] = svga_color_transform(svga->pallook[svga->egapal[(dat >> 4) & svga->plane_mask]]);
|
||||
p[5] = svga_color_transform(svga->pallook[svga->egapal[dat & svga->plane_mask]]);
|
||||
dat = edatlookup[edat[0] & 3][edat[1] & 3] | (edatlookup[edat[2] & 3][edat[3] & 3] << 2);
|
||||
p[6] = svga_color_transform(svga->pallook[svga->egapal[(dat >> 4) & svga->plane_mask]]);
|
||||
p[7] = svga_color_transform(svga->pallook[svga->egapal[dat & svga->plane_mask]]);
|
||||
|
||||
p += 8;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void svga_render_8bpp_lowres(svga_t *svga)
|
||||
{
|
||||
int y_add = enable_overscan ? (overscan_y >> 1) : 0;
|
||||
int x_add = enable_overscan ? 8 : 0;
|
||||
|
||||
if (svga->changedvram[svga->ma >> 12] || svga->changedvram[(svga->ma >> 12) + 1] || svga->fullchange)
|
||||
{
|
||||
int x;
|
||||
int offset = (8 - (svga->scrollcache & 6)) + 24;
|
||||
uint32_t *p = &((uint32_t *)buffer32->line[svga->displine + y_add])[offset + x_add];
|
||||
|
||||
if (svga->firstline_draw == 2000)
|
||||
svga->firstline_draw = svga->displine;
|
||||
svga->lastline_draw = svga->displine;
|
||||
|
||||
for (x = 0; x <= svga->hdisp; x += 8)
|
||||
{
|
||||
uint32_t dat = *(uint32_t *)(&svga->vram[svga->ma & svga->vram_display_mask]);
|
||||
|
||||
p[0] = p[1] = svga_color_transform(svga->pallook[dat & 0xff]);
|
||||
p[2] = p[3] = svga_color_transform(svga->pallook[(dat >> 8) & 0xff]);
|
||||
p[4] = p[5] = svga_color_transform(svga->pallook[(dat >> 16) & 0xff]);
|
||||
p[6] = p[7] = svga_color_transform(svga->pallook[(dat >> 24) & 0xff]);
|
||||
|
||||
svga->ma += 4;
|
||||
p += 8;
|
||||
}
|
||||
svga->ma &= svga->vram_display_mask;
|
||||
}
|
||||
}
|
||||
|
||||
void svga_render_8bpp_highres(svga_t *svga)
|
||||
{
|
||||
int y_add = enable_overscan ? (overscan_y >> 1) : 0;
|
||||
int x_add = enable_overscan ? 8 : 0;
|
||||
|
||||
if (svga->changedvram[svga->ma >> 12] || svga->changedvram[(svga->ma >> 12) + 1] || svga->fullchange)
|
||||
{
|
||||
int x;
|
||||
int offset = (8 - ((svga->scrollcache & 6) >> 1)) + 24;
|
||||
uint32_t *p = &((uint32_t *)buffer32->line[svga->displine + y_add])[offset + x_add];
|
||||
|
||||
if (svga->firstline_draw == 2000)
|
||||
svga->firstline_draw = svga->displine;
|
||||
svga->lastline_draw = svga->displine;
|
||||
|
||||
for (x = 0; x <= svga->hdisp; x += 8)
|
||||
{
|
||||
uint32_t dat;
|
||||
dat = *(uint32_t *)(&svga->vram[svga->ma & svga->vram_display_mask]);
|
||||
p[0] = svga_color_transform(svga->pallook[dat & 0xff]);
|
||||
p[1] = svga_color_transform(svga->pallook[(dat >> 8) & 0xff]);
|
||||
p[2] = svga_color_transform(svga->pallook[(dat >> 16) & 0xff]);
|
||||
p[3] = svga_color_transform(svga->pallook[(dat >> 24) & 0xff]);
|
||||
|
||||
dat = *(uint32_t *)(&svga->vram[(svga->ma + 4) & svga->vram_display_mask]);
|
||||
p[4] = svga_color_transform(svga->pallook[dat & 0xff]);
|
||||
p[5] = svga_color_transform(svga->pallook[(dat >> 8) & 0xff]);
|
||||
p[6] = svga_color_transform(svga->pallook[(dat >> 16) & 0xff]);
|
||||
p[7] = svga_color_transform(svga->pallook[(dat >> 24) & 0xff]);
|
||||
|
||||
svga->ma += 8;
|
||||
p += 8;
|
||||
}
|
||||
svga->ma &= svga->vram_display_mask;
|
||||
}
|
||||
}
|
||||
|
||||
void svga_render_15bpp_lowres(svga_t *svga)
|
||||
{
|
||||
int y_add = enable_overscan ? (overscan_y >> 1) : 0;
|
||||
int x_add = enable_overscan ? 8 : 0;
|
||||
|
||||
if (svga->changedvram[svga->ma >> 12] || svga->changedvram[(svga->ma >> 12) + 1] || svga->fullchange)
|
||||
{
|
||||
int x;
|
||||
int offset = (8 - (svga->scrollcache & 6)) + 24;
|
||||
uint32_t *p = &((uint32_t *)buffer32->line[svga->displine + y_add])[offset + x_add];
|
||||
|
||||
if (svga->firstline_draw == 2000)
|
||||
svga->firstline_draw = svga->displine;
|
||||
svga->lastline_draw = svga->displine;
|
||||
|
||||
for (x = 0; x <= svga->hdisp; x += 4)
|
||||
{
|
||||
uint32_t dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 1)) & svga->vram_display_mask]);
|
||||
|
||||
p[x] = svga_color_transform(video_15to32[dat & 0xffff]);
|
||||
p[x + 1] = svga_color_transform(video_15to32[dat >> 16]);
|
||||
|
||||
dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 1) + 4) & svga->vram_display_mask]);
|
||||
|
||||
p[x] = svga_color_transform(video_15to32[dat & 0xffff]);
|
||||
p[x + 1] = svga_color_transform(video_15to32[dat >> 16]);
|
||||
}
|
||||
svga->ma += x << 1;
|
||||
svga->ma &= svga->vram_display_mask;
|
||||
}
|
||||
}
|
||||
|
||||
void svga_render_15bpp_highres(svga_t *svga)
|
||||
{
|
||||
int y_add = enable_overscan ? (overscan_y >> 1) : 0;
|
||||
int x_add = enable_overscan ? 8 : 0;
|
||||
|
||||
if (svga->changedvram[svga->ma >> 12] || svga->changedvram[(svga->ma >> 12) + 1] || svga->fullchange)
|
||||
{
|
||||
int x;
|
||||
int offset = (8 - ((svga->scrollcache & 6) >> 1)) + 24;
|
||||
uint32_t *p = &((uint32_t *)buffer32->line[svga->displine + y_add])[offset + x_add];
|
||||
|
||||
if (svga->firstline_draw == 2000)
|
||||
svga->firstline_draw = svga->displine;
|
||||
svga->lastline_draw = svga->displine;
|
||||
|
||||
for (x = 0; x <= svga->hdisp; x += 8)
|
||||
{
|
||||
uint32_t dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 1)) & svga->vram_display_mask]);
|
||||
p[x] = svga_color_transform(video_15to32[dat & 0xffff]);
|
||||
p[x + 1] = svga_color_transform(video_15to32[dat >> 16]);
|
||||
|
||||
dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 1) + 4) & svga->vram_display_mask]);
|
||||
p[x + 2] = svga_color_transform(video_15to32[dat & 0xffff]);
|
||||
p[x + 3] = svga_color_transform(video_15to32[dat >> 16]);
|
||||
|
||||
dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 1) + 8) & svga->vram_display_mask]);
|
||||
p[x + 4] = svga_color_transform(video_15to32[dat & 0xffff]);
|
||||
p[x + 5] = svga_color_transform(video_15to32[dat >> 16]);
|
||||
|
||||
dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 1) + 12) & svga->vram_display_mask]);
|
||||
p[x + 6] = svga_color_transform(video_15to32[dat & 0xffff]);
|
||||
p[x + 7] = svga_color_transform(video_15to32[dat >> 16]);
|
||||
}
|
||||
svga->ma += x << 1;
|
||||
svga->ma &= svga->vram_display_mask;
|
||||
}
|
||||
}
|
||||
|
||||
void svga_render_16bpp_lowres(svga_t *svga)
|
||||
{
|
||||
int y_add = enable_overscan ? (overscan_y >> 1) : 0;
|
||||
int x_add = enable_overscan ? 8 : 0;
|
||||
|
||||
if (svga->changedvram[svga->ma >> 12] || svga->changedvram[(svga->ma >> 12) + 1] || svga->fullchange)
|
||||
{
|
||||
int x;
|
||||
int offset = (8 - (svga->scrollcache & 6)) + 24;
|
||||
uint32_t *p = &((uint32_t *)buffer32->line[svga->displine + y_add])[offset + x_add];
|
||||
|
||||
if (svga->firstline_draw == 2000)
|
||||
svga->firstline_draw = svga->displine;
|
||||
svga->lastline_draw = svga->displine;
|
||||
|
||||
for (x = 0; x <= svga->hdisp; x += 4)
|
||||
{
|
||||
uint32_t dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 1)) & svga->vram_display_mask]);
|
||||
|
||||
p[x] = svga_color_transform(video_16to32[dat & 0xffff]);
|
||||
p[x + 1] = svga_color_transform(video_16to32[dat >> 16]);
|
||||
|
||||
dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 1) + 4) & svga->vram_display_mask]);
|
||||
|
||||
p[x] = svga_color_transform(video_16to32[dat & 0xffff]);
|
||||
p[x + 1] = svga_color_transform(video_16to32[dat >> 16]);
|
||||
}
|
||||
svga->ma += x << 1;
|
||||
svga->ma &= svga->vram_display_mask;
|
||||
}
|
||||
}
|
||||
|
||||
void svga_render_16bpp_highres(svga_t *svga)
|
||||
{
|
||||
int y_add = enable_overscan ? (overscan_y >> 1) : 0;
|
||||
int x_add = enable_overscan ? 8 : 0;
|
||||
|
||||
if (svga->changedvram[svga->ma >> 12] || svga->changedvram[(svga->ma >> 12) + 1] || svga->fullchange)
|
||||
{
|
||||
int x;
|
||||
int offset = (8 - ((svga->scrollcache & 6) >> 1)) + 24;
|
||||
uint32_t *p = &((uint32_t *)buffer32->line[svga->displine + y_add])[offset + x_add];
|
||||
|
||||
if (svga->firstline_draw == 2000)
|
||||
svga->firstline_draw = svga->displine;
|
||||
svga->lastline_draw = svga->displine;
|
||||
|
||||
for (x = 0; x <= svga->hdisp; x += 8)
|
||||
{
|
||||
uint32_t dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 1)) & svga->vram_display_mask]);
|
||||
p[x] = svga_color_transform(video_16to32[dat & 0xffff]);
|
||||
p[x + 1] = svga_color_transform(video_16to32[dat >> 16]);
|
||||
|
||||
dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 1) + 4) & svga->vram_display_mask]);
|
||||
p[x + 2] = svga_color_transform(video_16to32[dat & 0xffff]);
|
||||
p[x + 3] = svga_color_transform(video_16to32[dat >> 16]);
|
||||
|
||||
dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 1) + 8) & svga->vram_display_mask]);
|
||||
p[x + 4] = svga_color_transform(video_16to32[dat & 0xffff]);
|
||||
p[x + 5] = svga_color_transform(video_16to32[dat >> 16]);
|
||||
|
||||
dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 1) + 12) & svga->vram_display_mask]);
|
||||
p[x + 6] = svga_color_transform(video_16to32[dat & 0xffff]);
|
||||
p[x + 7] = svga_color_transform(video_16to32[dat >> 16]);
|
||||
}
|
||||
svga->ma += x << 1;
|
||||
svga->ma &= svga->vram_display_mask;
|
||||
}
|
||||
}
|
||||
|
||||
void svga_render_24bpp_lowres(svga_t *svga)
|
||||
{
|
||||
int x, offset;
|
||||
uint32_t fg;
|
||||
|
||||
int y_add = enable_overscan ? (overscan_y >> 1) : 0;
|
||||
int x_add = enable_overscan ? 8 : 0;
|
||||
|
||||
if (svga->changedvram[svga->ma >> 12] || svga->changedvram[(svga->ma >> 12) + 1] || svga->fullchange)
|
||||
{
|
||||
if (svga->firstline_draw == 2000)
|
||||
svga->firstline_draw = svga->displine;
|
||||
svga->lastline_draw = svga->displine;
|
||||
|
||||
offset = (8 - (svga->scrollcache & 6)) + 24;
|
||||
|
||||
for (x = 0; x <= svga->hdisp; x++)
|
||||
{
|
||||
fg = svga->vram[svga->ma] | (svga->vram[svga->ma + 1] << 8) | (svga->vram[svga->ma + 2] << 16);
|
||||
svga->ma += 3;
|
||||
svga->ma &= svga->vram_display_mask;
|
||||
((uint32_t *)buffer32->line[svga->displine + y_add])[(x << 1) + offset + x_add] = ((uint32_t *)buffer32->line[svga->displine + y_add])[(x << 1) + 1 + offset + x_add] = svga_color_transform(fg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void svga_render_24bpp_highres(svga_t *svga)
|
||||
{
|
||||
int y_add = enable_overscan ? (overscan_y >> 1) : 0;
|
||||
int x_add = enable_overscan ? 8 : 0;
|
||||
|
||||
if (svga->changedvram[svga->ma >> 12] || svga->changedvram[(svga->ma >> 12) + 1] || svga->fullchange)
|
||||
{
|
||||
int x;
|
||||
int offset = (8 - ((svga->scrollcache & 6) >> 1)) + 24;
|
||||
uint32_t *p = &((uint32_t *)buffer32->line[svga->displine + y_add])[offset + x_add];
|
||||
|
||||
if (svga->firstline_draw == 2000)
|
||||
svga->firstline_draw = svga->displine;
|
||||
svga->lastline_draw = svga->displine;
|
||||
|
||||
for (x = 0; x <= svga->hdisp; x += 4)
|
||||
{
|
||||
uint32_t dat = *(uint32_t *)(&svga->vram[svga->ma & svga->vram_display_mask]);
|
||||
p[x] = svga_color_transform(dat & 0xffffff);
|
||||
|
||||
dat = *(uint32_t *)(&svga->vram[(svga->ma + 3) & svga->vram_display_mask]);
|
||||
p[x + 1] = svga_color_transform(dat & 0xffffff);
|
||||
|
||||
dat = *(uint32_t *)(&svga->vram[(svga->ma + 6) & svga->vram_display_mask]);
|
||||
p[x + 2] = svga_color_transform(dat & 0xffffff);
|
||||
|
||||
dat = *(uint32_t *)(&svga->vram[(svga->ma + 9) & svga->vram_display_mask]);
|
||||
p[x + 3] = svga_color_transform(dat & 0xffffff);
|
||||
|
||||
svga->ma += 12;
|
||||
}
|
||||
svga->ma &= svga->vram_display_mask;
|
||||
}
|
||||
}
|
||||
|
||||
void svga_render_32bpp_lowres(svga_t *svga)
|
||||
{
|
||||
int x, offset;
|
||||
uint32_t fg;
|
||||
|
||||
int y_add = enable_overscan ? (overscan_y >> 1) : 0;
|
||||
int x_add = enable_overscan ? 8 : 0;
|
||||
|
||||
if (svga->changedvram[svga->ma >> 12] || svga->changedvram[(svga->ma >> 12) + 1] || svga->fullchange)
|
||||
{
|
||||
if (svga->firstline_draw == 2000)
|
||||
svga->firstline_draw = svga->displine;
|
||||
svga->lastline_draw = svga->displine;
|
||||
|
||||
offset = (8 - (svga->scrollcache & 6)) + 24;
|
||||
|
||||
for (x = 0; x <= svga->hdisp; x++)
|
||||
{
|
||||
fg = svga->vram[svga->ma] | (svga->vram[svga->ma + 1] << 8) | (svga->vram[svga->ma + 2] << 16);
|
||||
svga->ma += 4;
|
||||
svga->ma &= svga->vram_display_mask;
|
||||
((uint32_t *)buffer32->line[svga->displine + y_add])[(x << 1) + offset + x_add] = ((uint32_t *)buffer32->line[svga->displine + y_add])[(x << 1) + 1 + offset + x_add] = svga_color_transform(fg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*72%
|
||||
91%*/
|
||||
void svga_render_32bpp_highres(svga_t *svga)
|
||||
{
|
||||
int y_add = enable_overscan ? (overscan_y >> 1) : 0;
|
||||
int x_add = enable_overscan ? 8 : 0;
|
||||
|
||||
if (svga->changedvram[svga->ma >> 12] || svga->changedvram[(svga->ma >> 12) + 1] || svga->changedvram[(svga->ma >> 12) + 2] || svga->fullchange)
|
||||
{
|
||||
int x;
|
||||
int offset = (8 - ((svga->scrollcache & 6) >> 1)) + 24;
|
||||
uint32_t *p = &((uint32_t *)buffer32->line[svga->displine + y_add])[offset + x_add];
|
||||
|
||||
if (svga->firstline_draw == 2000)
|
||||
svga->firstline_draw = svga->displine;
|
||||
svga->lastline_draw = svga->displine;
|
||||
|
||||
for (x = 0; x <= svga->hdisp; x++)
|
||||
{
|
||||
uint32_t dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 2)) & svga->vram_display_mask]);
|
||||
p[x] = svga_color_transform(dat & 0xffffff);
|
||||
}
|
||||
svga->ma += 4;
|
||||
svga->ma &= svga->vram_display_mask;
|
||||
}
|
||||
}
|
||||
|
||||
void svga_render_ABGR8888_highres(svga_t *svga)
|
||||
{
|
||||
int y_add = enable_overscan ? (overscan_y >> 1) : 0;
|
||||
int x_add = enable_overscan ? 8 : 0;
|
||||
|
||||
if (svga->changedvram[svga->ma >> 12] || svga->changedvram[(svga->ma >> 12) + 1] || svga->changedvram[(svga->ma >> 12) + 2] || svga->fullchange)
|
||||
{
|
||||
int x;
|
||||
int offset = (8 - ((svga->scrollcache & 6) >> 1)) + 24;
|
||||
uint32_t *p = &((uint32_t *)buffer32->line[svga->displine + y_add])[offset + x_add];
|
||||
|
||||
if (svga->firstline_draw == 2000)
|
||||
svga->firstline_draw = svga->displine;
|
||||
svga->lastline_draw = svga->displine;
|
||||
|
||||
for (x = 0; x <= svga->hdisp; x++)
|
||||
{
|
||||
uint32_t dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 2)) & svga->vram_display_mask]);
|
||||
p[x] = svga_color_transform((dat & 0xff0000) >> 16) | (dat & 0x00ff00) | ((dat & 0x0000ff) << 16);
|
||||
}
|
||||
svga->ma += 4;
|
||||
svga->ma &= svga->vram_display_mask;
|
||||
}
|
||||
}
|
||||
|
||||
void svga_render_RGBA8888_highres(svga_t *svga)
|
||||
{
|
||||
int y_add = enable_overscan ? (overscan_y >> 1) : 0;
|
||||
int x_add = enable_overscan ? 8 : 0;
|
||||
|
||||
if (svga->changedvram[svga->ma >> 12] || svga->changedvram[(svga->ma >> 12) + 1] || svga->changedvram[(svga->ma >> 12) + 2] || svga->fullchange)
|
||||
{
|
||||
int x;
|
||||
int offset = (8 - ((svga->scrollcache & 6) >> 1)) + 24;
|
||||
uint32_t *p = &((uint32_t *)buffer32->line[svga->displine + y_add])[offset + x_add];
|
||||
|
||||
if (svga->firstline_draw == 2000)
|
||||
svga->firstline_draw = svga->displine;
|
||||
svga->lastline_draw = svga->displine;
|
||||
|
||||
for (x = 0; x <= svga->hdisp; x++)
|
||||
{
|
||||
uint32_t dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 2)) & svga->vram_display_mask]);
|
||||
p[x] = svga_color_transform(dat >> 8);
|
||||
}
|
||||
svga->ma += 4;
|
||||
svga->ma &= svga->vram_display_mask;
|
||||
}
|
||||
}
|
||||
54
backup code/video - Cópia/vid_svga_render.h
Normal file
54
backup code/video - Cópia/vid_svga_render.h
Normal file
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
*
|
||||
* This file is part of the 86Box distribution.
|
||||
*
|
||||
* SVGA renderers.
|
||||
*
|
||||
* Version: @(#)vid_svga_render.h 1.0.1 2018/03/12
|
||||
*
|
||||
* Author: Sarah Walker, <http://pcem-emulator.co.uk/>
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
* Copyright 2008-2018 Sarah Walker.
|
||||
* Copyright 2016-2018 Miran Grca.
|
||||
*/
|
||||
|
||||
extern int firstline_draw, lastline_draw;
|
||||
extern int displine;
|
||||
extern int sc;
|
||||
|
||||
extern uint32_t ma, ca;
|
||||
extern int con, cursoron, cgablink;
|
||||
|
||||
extern int scrollcache;
|
||||
|
||||
extern uint8_t edatlookup[4][4];
|
||||
|
||||
void svga_render_blank(svga_t *svga);
|
||||
void svga_render_text_40(svga_t *svga);
|
||||
void svga_render_text_80(svga_t *svga);
|
||||
void svga_render_text_80_ksc5601(svga_t *svga);
|
||||
|
||||
void svga_render_2bpp_lowres(svga_t *svga);
|
||||
void svga_render_2bpp_highres(svga_t *svga);
|
||||
void svga_render_4bpp_lowres(svga_t *svga);
|
||||
void svga_render_4bpp_highres(svga_t *svga);
|
||||
void svga_render_8bpp_lowres(svga_t *svga);
|
||||
void svga_render_8bpp_highres(svga_t *svga);
|
||||
void svga_render_15bpp_lowres(svga_t *svga);
|
||||
void svga_render_15bpp_highres(svga_t *svga);
|
||||
void svga_render_16bpp_lowres(svga_t *svga);
|
||||
void svga_render_16bpp_highres(svga_t *svga);
|
||||
void svga_render_24bpp_lowres(svga_t *svga);
|
||||
void svga_render_24bpp_highres(svga_t *svga);
|
||||
void svga_render_32bpp_lowres(svga_t *svga);
|
||||
void svga_render_32bpp_highres(svga_t *svga);
|
||||
void svga_render_ABGR8888_lowres(svga_t *svga);
|
||||
void svga_render_ABGR8888_highres(svga_t *svga);
|
||||
void svga_render_RGBA8888_lowres(svga_t *svga);
|
||||
void svga_render_RGBA8888_highres(svga_t *svga);
|
||||
|
||||
extern void (*svga_render)(svga_t *svga);
|
||||
427
backup code/video - Cópia/vid_table.c
Normal file
427
backup code/video - Cópia/vid_table.c
Normal file
@@ -0,0 +1,427 @@
|
||||
/*
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
*
|
||||
* This file is part of the 86Box distribution.
|
||||
*
|
||||
* Define all known video cards.
|
||||
*
|
||||
* Version: @(#)vid_table.c 1.0.29 2018/05/10
|
||||
*
|
||||
* Authors: Miran Grca, <mgrca8@gmail.com>
|
||||
* Fred N. van Kempen, <decwiz@yahoo.com>
|
||||
*
|
||||
* Copyright 2016-2018 Miran Grca.
|
||||
* Copyright 2017,2018 Fred N. van Kempen.
|
||||
*/
|
||||
#include <stdarg.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <wchar.h>
|
||||
#define HAVE_STDARG_H
|
||||
#include "../86box.h"
|
||||
#include "../machine/machine.h"
|
||||
#include "../mem.h"
|
||||
#include "../rom.h"
|
||||
#include "../device.h"
|
||||
#include "../timer.h"
|
||||
#include "../plat.h"
|
||||
#include "video.h"
|
||||
#include "vid_svga.h"
|
||||
|
||||
#include "vid_ati18800.h"
|
||||
#include "vid_ati28800.h"
|
||||
#include "vid_ati_mach64.h"
|
||||
#include "vid_cga.h"
|
||||
#include "vid_cl54xx.h"
|
||||
#include "vid_compaq_cga.h"
|
||||
#include "vid_ega.h"
|
||||
#include "vid_et4000.h"
|
||||
#include "vid_et4000w32.h"
|
||||
#include "vid_genius.h"
|
||||
#include "vid_hercules.h"
|
||||
#include "vid_herculesplus.h"
|
||||
#include "vid_incolor.h"
|
||||
#include "vid_colorplus.h"
|
||||
#include "vid_mda.h"
|
||||
#ifdef DEV_BRANCH
|
||||
# ifdef USE_RIVA
|
||||
# include "vid_nvidia.h"
|
||||
# endif
|
||||
#endif
|
||||
#include "vid_oak_oti.h"
|
||||
#include "vid_paradise.h"
|
||||
#include "vid_s3.h"
|
||||
#include "vid_s3_virge.h"
|
||||
#include "vid_tgui9440.h"
|
||||
#include "vid_ti_cf62011.h"
|
||||
#include "vid_tvga.h"
|
||||
#include "vid_vga.h"
|
||||
#include "vid_voodoo.h"
|
||||
#include "vid_wy700.h"
|
||||
|
||||
|
||||
enum {
|
||||
VIDEO_ISA = 0,
|
||||
VIDEO_BUS
|
||||
};
|
||||
|
||||
#define VIDEO_FLAG_TYPE_CGA 0
|
||||
#define VIDEO_FLAG_TYPE_MDA 1
|
||||
#define VIDEO_FLAG_TYPE_SPECIAL 2
|
||||
#define VIDEO_FLAG_TYPE_MASK 3
|
||||
|
||||
typedef struct {
|
||||
const char *name;
|
||||
const char *internal_name;
|
||||
const device_t *device;
|
||||
int legacy_id;
|
||||
int flags;
|
||||
video_timings_t timing;
|
||||
} VIDEO_CARD;
|
||||
|
||||
|
||||
static const VIDEO_CARD
|
||||
video_cards[] = {
|
||||
{ "None", "none", NULL, GFX_NONE },
|
||||
{ "Internal", "internal", NULL, GFX_INTERNAL, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_ISA, 8, 16, 32, 8, 16, 32}},
|
||||
{ "[ISA] ATI Graphics Pro Turbo (Mach64 GX)", "mach64gx_isa", &mach64gx_isa_device, GFX_MACH64GX_ISA, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_ISA, 3, 3, 6, 5, 5, 10}},
|
||||
{ "[ISA] ATI Korean VGA (ATI-28800-5)", "ati28800k", &ati28800k_device, GFX_ATIKOREANVGA, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_ISA, 3, 3, 6, 5, 5, 10}},
|
||||
{ "[ISA] ATI VGA-88 (ATI-18800-1)", "ati18800v", &ati18800_vga88_device, GFX_VGA88, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_ISA, 8, 16, 32, 8, 16, 32}},
|
||||
{ "[ISA] ATI VGA Charger (ATI-28800-5)", "ati28800", &ati28800_device, GFX_VGACHARGER, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_ISA, 3, 3, 6, 5, 5, 10}},
|
||||
{ "[ISA] ATI VGA Edge-16 (ATI-18800-5)", "ati18800", &ati18800_device, GFX_VGAEDGE16, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_ISA, 8, 16, 32, 8, 16, 32}},
|
||||
#if defined(DEV_BRANCH) && defined(USE_VGAWONDER)
|
||||
{ "[ISA] ATI VGA Wonder (ATI-18800)", "ati18800w", &ati18800_wonder_device, GFX_VGAWONDER, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_ISA, 8, 16, 32, 8, 16, 32}},
|
||||
#endif
|
||||
#if defined(DEV_BRANCH) && defined(USE_XL24)
|
||||
{ "[ISA] ATI VGA Wonder XL24 (ATI-28800-6)", "ati28800w", &ati28800_wonderxl24_device, GFX_VGAWONDERXL24, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_ISA, 3, 3, 6, 5, 5, 10}},
|
||||
#endif
|
||||
{ "[ISA] CGA", "cga", &cga_device, GFX_CGA, VIDEO_FLAG_TYPE_CGA, {VIDEO_ISA, 8, 16, 32, 8, 16, 32}},
|
||||
{ "[ISA] Chips & Technologies SuperEGA", "superega", &sega_device, GFX_SUPER_EGA, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_ISA, 8, 16, 32, 8, 16, 32}},
|
||||
{ "[ISA] Cirrus Logic CL-GD 5428", "cl_gd5428_isa", &gd5428_isa_device, GFX_CL_GD5428_ISA, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_ISA, 3, 3, 6, 8, 8, 12}},
|
||||
{ "[ISA] Cirrus Logic CL-GD 5429", "cl_gd5429_isa", &gd5429_isa_device, GFX_CL_GD5429_ISA, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_ISA, 3, 3, 6, 8, 8, 12}},
|
||||
{ "[ISA] Cirrus Logic CL-GD 5434", "cl_gd5434_isa", &gd5434_isa_device, GFX_CL_GD5434_ISA, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_ISA, 3, 3, 6, 8, 8, 12}},
|
||||
{ "[ISA] Compaq ATI VGA Wonder XL (ATI-28800-5)", "compaq_ati28800", &compaq_ati28800_device, GFX_VGAWONDERXL, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_ISA, 3, 3, 6, 5, 5, 10}},
|
||||
{ "[ISA] Compaq CGA", "compaq_cga", &compaq_cga_device, GFX_COMPAQ_CGA, VIDEO_FLAG_TYPE_CGA, {VIDEO_ISA, 8, 16, 32, 8, 16, 32}},
|
||||
{ "[ISA] Compaq CGA 2", "compaq_cga_2", &compaq_cga_2_device, GFX_COMPAQ_CGA_2, VIDEO_FLAG_TYPE_CGA, {VIDEO_ISA, 8, 16, 32, 8, 16, 32}},
|
||||
{ "[ISA] Compaq EGA", "compaq_ega", &cpqega_device, GFX_COMPAQ_EGA, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_ISA, 8, 16, 32, 8, 16, 32}},
|
||||
{ "[ISA] EGA", "ega", &ega_device, GFX_EGA, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_ISA, 8, 16, 32, 8, 16, 32}},
|
||||
{ "[ISA] Hercules", "hercules", &hercules_device, GFX_HERCULES, VIDEO_FLAG_TYPE_MDA, {VIDEO_ISA, 8, 16, 32, 8, 16, 32}},
|
||||
{ "[ISA] Hercules Plus", "hercules_plus", &herculesplus_device, GFX_HERCULESPLUS, VIDEO_FLAG_TYPE_MDA, {VIDEO_ISA, 8, 16, 32, 8, 16, 32}},
|
||||
{ "[ISA] Hercules InColor", "incolor", &incolor_device, GFX_INCOLOR, VIDEO_FLAG_TYPE_MDA, {VIDEO_ISA, 8, 16, 32, 8, 16, 32}},
|
||||
{ "[ISA] MDA", "mda", &mda_device, GFX_MDA, VIDEO_FLAG_TYPE_MDA, {VIDEO_ISA, 8, 16, 32, 8, 16, 32}},
|
||||
{ "[ISA] MDSI Genius", "genius", &genius_device, GFX_GENIUS, VIDEO_FLAG_TYPE_MDA, {VIDEO_ISA, 8, 16, 32, 8, 16, 32}},
|
||||
{ "[ISA] OAK OTI-037C", "oti037c", &oti037c_device, GFX_OTI037C, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_ISA, 6, 8, 16, 6, 8, 16}},
|
||||
{ "[ISA] OAK OTI-067", "oti067", &oti067_device, GFX_OTI067, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_ISA, 6, 8, 16, 6, 8, 16}},
|
||||
{ "[ISA] OAK OTI-077", "oti077", &oti077_device, GFX_OTI077, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_ISA, 6, 8, 16, 6, 8, 16}},
|
||||
{ "[ISA] Paradise PVGA1A", "pvga1a", ¶dise_pvga1a_device, GFX_PVGA1A, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_ISA, 8, 16, 32, 8, 16, 32}},
|
||||
{ "[ISA] Paradise WD90C11-LR", "wd90c11", ¶dise_wd90c11_device, GFX_WD90C11, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_ISA, 8, 16, 32, 8, 16, 32}},
|
||||
{ "[ISA] Paradise WD90C30-LR", "wd90c30", ¶dise_wd90c30_device, GFX_WD90C30, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_ISA, 6, 8, 16, 6, 8, 16}},
|
||||
{ "[ISA] Plantronics ColorPlus", "plantronics", &colorplus_device, GFX_COLORPLUS, VIDEO_FLAG_TYPE_CGA, {VIDEO_ISA, 8, 16, 32, 8, 16, 32}},
|
||||
#if defined(DEV_BRANCH) && defined(USE_TI)
|
||||
{ "[ISA] TI CF62011 SVGA", "ti_cf62011", &ti_cf62011_device, GFX_TICF62011, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_ISA, 8, 16, 32, 8, 16, 32}},
|
||||
#endif
|
||||
{"[ISA] Trident TVGA8900D", "tvga8900d", &tvga8900d_device, GFX_TVGA, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_ISA, 3, 3, 6, 8, 8, 12}},
|
||||
{"[ISA] Tseng ET4000AX", "et4000ax", &et4000_device, GFX_ET4000, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_ISA, 3, 3, 6, 5, 5, 10}},
|
||||
{"[ISA] VGA", "vga", &vga_device, GFX_VGA, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_ISA, 8, 16, 32, 8, 16, 32}},
|
||||
{"[ISA] Wyse 700", "wy700", &wy700_device, GFX_WY700, VIDEO_FLAG_TYPE_CGA, {VIDEO_ISA, 8, 16, 32, 8, 16, 32}},
|
||||
{"[PCI] ATI Graphics Pro Turbo (Mach64 GX)", "mach64gx_pci", &mach64gx_pci_device, GFX_MACH64GX_PCI, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_BUS, 2, 2, 1, 20, 20, 21}},
|
||||
{"[PCI] ATI Video Xpression (Mach64 VT2)", "mach64vt2", &mach64vt2_device, GFX_MACH64VT2, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_BUS, 2, 2, 1, 20, 20, 21}},
|
||||
{"[PCI] Cardex Tseng ET4000/w32p", "et4000w32p_pci", &et4000w32p_cardex_pci_device, GFX_ET4000W32_CARDEX_PCI, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_BUS, 4, 4, 4, 10, 10, 10}},
|
||||
{"[PCI] Cirrus Logic CL-GD 5430", "cl_gd5430_pci", &gd5430_pci_device, GFX_CL_GD5430_PCI, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_BUS, 4, 4, 8, 10, 10, 20}},
|
||||
{"[PCI] Cirrus Logic CL-GD 5434", "cl_gd5434_pci", &gd5434_pci_device, GFX_CL_GD5434_PCI, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_BUS, 4, 4, 8, 10, 10, 20}},
|
||||
{"[PCI] Cirrus Logic CL-GD 5436", "cl_gd5436_pci", &gd5436_pci_device, GFX_CL_GD5436_PCI, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_BUS, 4, 4, 8, 10, 10, 20}},
|
||||
{"[PCI] Cirrus Logic CL-GD 5440", "cl_gd5440_pci", &gd5440_pci_device, GFX_CL_GD5440_PCI, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_BUS, 4, 4, 8, 10, 10, 20}},
|
||||
{"[PCI] Cirrus Logic CL-GD 5446", "cl_gd5446_pci", &gd5446_pci_device, GFX_CL_GD5446_PCI, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_BUS, 4, 4, 8, 10, 10, 20}},
|
||||
{"[PCI] Cirrus Logic CL-GD 5480", "cl_gd5480_pci", &gd5480_pci_device, GFX_CL_GD5480_PCI, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_BUS, 4, 4, 8, 10, 10, 20}},
|
||||
#if defined(DEV_BRANCH) && defined(USE_STEALTH32)
|
||||
{"[PCI] Diamond Stealth 32 (Tseng ET4000/w32p)", "stealth32_pci", &et4000w32p_pci_device, GFX_ET4000W32_PCI, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_BUS, 4, 4, 4, 10, 10, 10}},
|
||||
#endif
|
||||
{"[PCI] Diamond Stealth 3D 2000 (S3 ViRGE)", "stealth3d_2000_pci", &s3_virge_pci_device, GFX_VIRGE_PCI, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_BUS, 2, 2, 3, 28, 28, 45}},
|
||||
{"[PCI] Diamond Stealth 3D 3000 (S3 ViRGE/VX)", "stealth3d_3000_pci", &s3_virge_988_pci_device, GFX_VIRGEVX_PCI, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_BUS, 2, 2, 4, 26, 26, 42}},
|
||||
{"[PCI] Diamond Stealth 64 DRAM (S3 Trio64)", "stealth64d_pci", &s3_diamond_stealth64_pci_device, GFX_STEALTH64_PCI, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_BUS, 2, 2, 4, 26, 26, 42}},
|
||||
#if defined(DEV_BRANCH) && defined(USE_RIVA)
|
||||
{"[PCI] nVidia RIVA 128", "riva128", &riva128_device, GFX_RIVA128, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_BUS, 2, 2, 3, 24, 24, 36}},
|
||||
/*{"[PCI] nVidia RIVA TNT", "rivatnt", &rivatnt_device, GFX_RIVATNT, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_BUS, 2, 2, 3, 24, 24, 36}},
|
||||
{"[PCI] nVidia RIVA TNT2", "rivatnt2", &rivatnt2_device, GFX_RIVATNT2, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_BUS, 2, 2, 3, 24, 24, 36}},*/
|
||||
#endif
|
||||
{"[PCI] Number Nine 9FX (S3 Trio64)", "n9_9fx_pci", &s3_9fx_pci_device, GFX_N9_9FX_PCI, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_BUS, 3, 2, 4, 25, 25, 40}},
|
||||
{"[PCI] Paradise Bahamas 64 (S3 Vision864)", "bahamas64_pci", &s3_bahamas64_pci_device, GFX_BAHAMAS64_PCI, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_BUS, 4, 4, 5, 20, 20, 35}},
|
||||
{"[PCI] Phoenix S3 Vision864", "px_vision864_pci", &s3_phoenix_vision864_pci_device, GFX_PHOENIX_VISION864_PCI, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_BUS, 4, 4, 5, 20, 20, 35}},
|
||||
{"[PCI] Phoenix S3 Trio32", "px_trio32_pci", &s3_phoenix_trio32_pci_device, GFX_PHOENIX_TRIO32_PCI, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_BUS, 3, 2, 4, 25, 25, 40}},
|
||||
{"[PCI] Phoenix S3 Trio64", "px_trio64_pci", &s3_phoenix_trio64_pci_device, GFX_PHOENIX_TRIO64_PCI, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_BUS, 3, 2, 4, 25, 25, 40}},
|
||||
{"[PCI] S3 ViRGE/DX", "virge375_pci", &s3_virge_375_pci_device, GFX_VIRGEDX_PCI, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_BUS, 2, 2, 3, 28, 28, 45}},
|
||||
{"[PCI] S3 ViRGE/DX (VBE 2.0)", "virge375_vbe20_pci", &s3_virge_375_4_pci_device, GFX_VIRGEDX4_PCI, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_BUS, 2, 2, 3, 28, 28, 45}},
|
||||
{"[PCI] STB Nitro 64V (CL-GD 5446)", "cl_gd5446_stb_pci", &gd5446_stb_pci_device, GFX_CL_GD5446_STB_PCI, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_BUS, 4, 4, 8, 10, 10, 20}},
|
||||
{"[PCI] Trident TGUI9440", "tgui9440_pci", &tgui9440_pci_device, GFX_TGUI9440_PCI, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_BUS, 4, 8, 16, 4, 8, 16}},
|
||||
{"[VLB] ATI Graphics Pro Turbo (Mach64 GX)", "mach64gx_vlb", &mach64gx_vlb_device, GFX_MACH64GX_VLB, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_BUS, 2, 2, 1, 20, 20, 21}},
|
||||
{"[VLB] Cardex Tseng ET4000/w32p", "et4000w32p_vlb", &et4000w32p_cardex_vlb_device, GFX_ET4000W32_CARDEX_VLB, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_BUS, 4, 4, 4, 10, 10, 10}},
|
||||
{"[VLB] Cirrus Logic CL-GD 5428", "cl_gd5428_vlb", &gd5428_vlb_device, GFX_CL_GD5428_VLB, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_BUS, 4, 4, 8, 10, 10, 20}},
|
||||
{"[VLB] Cirrus Logic CL-GD 5429", "cl_gd5429_vlb", &gd5429_vlb_device, GFX_CL_GD5429_VLB, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_BUS, 4, 4, 8, 10, 10, 20}},
|
||||
{"[VLB] Cirrus Logic CL-GD 5434", "cl_gd5434_vlb", &gd5434_vlb_device, GFX_CL_GD5434_VLB, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_BUS, 4, 4, 8, 10, 10, 20}},
|
||||
#if defined(DEV_BRANCH) && defined(USE_STEALTH32)
|
||||
{"[VLB] Diamond Stealth 32 (Tseng ET4000/w32p)", "stealth32_vlb", &et4000w32p_vlb_device, GFX_ET4000W32_VLB, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_BUS, 4, 4, 4, 10, 10, 10}},
|
||||
#endif
|
||||
{"[VLB] Diamond SpeedStar PRO (CL-GD 5426)", "cl_gd5426_vlb", &gd5426_vlb_device, GFX_CL_GD5426_VLB, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_BUS, 4, 4, 8, 10, 10, 20}},
|
||||
{"[VLB] Diamond SpeedStar PRO SE (CL-GD 5430)", "cl_gd5430_vlb", &gd5430_vlb_device, GFX_CL_GD5430_VLB, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_BUS, 4, 4, 8, 10, 10, 20}},
|
||||
{"[VLB] Diamond Stealth 3D 2000 (S3 ViRGE)", "stealth3d_2000_vlb", &s3_virge_vlb_device, GFX_VIRGE_VLB, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_BUS, 2, 2, 3, 28, 28, 45}},
|
||||
{"[VLB] Diamond Stealth 3D 3000 (S3 ViRGE/VX)", "stealth3d_3000_vlb", &s3_virge_988_vlb_device, GFX_VIRGEVX_VLB, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_BUS, 2, 2, 4, 26, 26, 42}},
|
||||
{"[VLB] Diamond Stealth 64 DRAM (S3 Trio64)", "stealth64d_vlb", &s3_diamond_stealth64_vlb_device, GFX_STEALTH64_VLB, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_BUS, 2, 2, 4, 26, 26, 42}},
|
||||
{"[VLB] Number Nine 9FX (S3 Trio64)", "n9_9fx_vlb", &s3_9fx_vlb_device, GFX_N9_9FX_VLB, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_BUS, 3, 2, 4, 25, 25, 40}},
|
||||
{"[VLB] Paradise Bahamas 64 (S3 Vision864)", "bahamas64_vlb", &s3_bahamas64_vlb_device, GFX_BAHAMAS64_VLB, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_BUS, 4, 4, 5, 20, 20, 35}},
|
||||
{"[VLB] Phoenix S3 Vision864", "px_vision864_vlb", &s3_phoenix_vision864_vlb_device, GFX_PHOENIX_VISION864_VLB, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_BUS, 4, 4, 5, 20, 20, 35}},
|
||||
{"[VLB] Phoenix S3 Trio32", "px_trio32_vlb", &s3_phoenix_trio32_vlb_device, GFX_PHOENIX_TRIO32_VLB, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_BUS, 3, 2, 4, 25, 25, 40}},
|
||||
{"[VLB] Phoenix S3 Trio64", "px_trio64_vlb", &s3_phoenix_trio64_vlb_device, GFX_PHOENIX_TRIO64_VLB, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_BUS, 3, 2, 4, 25, 25, 40}},
|
||||
{"[VLB] S3 ViRGE/DX", "virge375_vlb", &s3_virge_375_vlb_device, GFX_VIRGEDX_VLB, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_BUS, 2, 2, 3, 28, 28, 45}},
|
||||
{"[VLB] S3 ViRGE/DX (VBE 2.0)", "virge375_vbe20_vlb", &s3_virge_375_4_vlb_device, GFX_VIRGEDX4_VLB, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_BUS, 2, 2, 3, 28, 28, 45}},
|
||||
{"[VLB] Trident TGUI9400CXi", "tgui9400cxi_vlb", &tgui9400cxi_device, GFX_TGUI9400CXI, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_BUS, 4, 8, 16, 4, 8, 16}},
|
||||
{"[VLB] Trident TGUI9440", "tgui9440_vlb", &tgui9440_vlb_device, GFX_TGUI9440_VLB, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_BUS, 4, 8, 16, 4, 8, 16}},
|
||||
{"", "", NULL, -1 }
|
||||
};
|
||||
|
||||
|
||||
#ifdef ENABLE_VID_TABLE_LOG
|
||||
int vid_table_do_log = ENABLE_VID_TABLE_LOG;
|
||||
#endif
|
||||
|
||||
|
||||
static void
|
||||
vid_table_log(const char *fmt, ...)
|
||||
{
|
||||
#ifdef ENABLE_VID_TABLE_LOG
|
||||
va_list ap;
|
||||
|
||||
if (vid_table_do_log) {
|
||||
va_start(ap, fmt);
|
||||
pclog_ex(fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
video_reset(int card)
|
||||
{
|
||||
vid_table_log("VIDEO: reset (romset=%d, gfxcard=%d, internal=%d)\n",
|
||||
romset, card, (machines[machine].flags & MACHINE_VIDEO)?1:0);
|
||||
|
||||
/* Reset the CGA palette. */
|
||||
cga_palette = 0;
|
||||
cgapal_rebuild();
|
||||
|
||||
if (fontdatksc5601) {
|
||||
free(fontdatksc5601);
|
||||
fontdatksc5601 = NULL;
|
||||
}
|
||||
|
||||
/* Do not initialize internal cards here. */
|
||||
if (!(card == GFX_NONE) && \
|
||||
!(card == GFX_INTERNAL) && !machines[machine].fixed_gfxcard) {
|
||||
vid_table_log("VIDEO: initializing '%s'\n", video_cards[video_old_to_new(card)].name);
|
||||
|
||||
/* Initialize the video card. */
|
||||
device_add(video_cards[video_old_to_new(card)].device);
|
||||
}
|
||||
|
||||
/* Enable the Voodoo if configured. */
|
||||
if (voodoo_enabled)
|
||||
device_add(&voodoo_device);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
video_card_available(int card)
|
||||
{
|
||||
if (video_cards[card].device)
|
||||
return(device_available(video_cards[card].device));
|
||||
|
||||
return(1);
|
||||
}
|
||||
|
||||
|
||||
char *
|
||||
video_card_getname(int card)
|
||||
{
|
||||
return((char *) video_cards[card].name);
|
||||
}
|
||||
|
||||
|
||||
const device_t *
|
||||
video_card_getdevice(int card)
|
||||
{
|
||||
return(video_cards[card].device);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
video_card_has_config(int card)
|
||||
{
|
||||
if (video_cards[card].device == NULL) return(0);
|
||||
|
||||
return(video_cards[card].device->config ? 1 : 0);
|
||||
}
|
||||
|
||||
|
||||
video_timings_t *
|
||||
video_card_gettiming(int card)
|
||||
{
|
||||
return((void *) &video_cards[card].timing);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
video_card_getid(char *s)
|
||||
{
|
||||
int c = 0;
|
||||
|
||||
while (video_cards[c].legacy_id != -1) {
|
||||
if (!strcmp((char *) video_cards[c].name, s))
|
||||
return(c);
|
||||
c++;
|
||||
}
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
video_old_to_new(int card)
|
||||
{
|
||||
int c = 0;
|
||||
|
||||
while (video_cards[c].legacy_id != -1) {
|
||||
if (video_cards[c].legacy_id == card)
|
||||
return(c);
|
||||
c++;
|
||||
}
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
video_new_to_old(int card)
|
||||
{
|
||||
return(video_cards[card].legacy_id);
|
||||
}
|
||||
|
||||
|
||||
char *
|
||||
video_get_internal_name(int card)
|
||||
{
|
||||
return((char *) video_cards[card].internal_name);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
video_get_video_from_internal_name(char *s)
|
||||
{
|
||||
int c = 0;
|
||||
|
||||
while (video_cards[c].legacy_id != -1) {
|
||||
if (!strcmp((char *) video_cards[c].internal_name, s))
|
||||
return(video_cards[c].legacy_id);
|
||||
c++;
|
||||
}
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
int video_is_mda(void)
|
||||
{
|
||||
switch (romset)
|
||||
{
|
||||
case ROM_IBMPCJR:
|
||||
case ROM_TANDY:
|
||||
case ROM_TANDY1000HX:
|
||||
case ROM_TANDY1000SL2:
|
||||
case ROM_PC1512:
|
||||
case ROM_PC1640:
|
||||
case ROM_PC200:
|
||||
case ROM_OLIM24:
|
||||
case ROM_PC2086:
|
||||
case ROM_PC3086:
|
||||
case ROM_MEGAPC:
|
||||
case ROM_MEGAPCDX:
|
||||
case ROM_IBMPS1_2011:
|
||||
case ROM_IBMPS2_M30_286:
|
||||
case ROM_IBMPS2_M50:
|
||||
case ROM_IBMPS2_M55SX:
|
||||
case ROM_IBMPS2_M70_TYPE3:
|
||||
case ROM_IBMPS2_M70_TYPE4:
|
||||
case ROM_IBMPS2_M80:
|
||||
case ROM_IBMPS1_2121:
|
||||
case ROM_T3100E:
|
||||
return 0;
|
||||
}
|
||||
return (video_cards[video_old_to_new(gfxcard)].flags & VIDEO_FLAG_TYPE_MASK) == VIDEO_FLAG_TYPE_MDA;
|
||||
}
|
||||
|
||||
int video_is_cga(void)
|
||||
{
|
||||
switch (romset)
|
||||
{
|
||||
case ROM_IBMPCJR:
|
||||
case ROM_TANDY:
|
||||
case ROM_TANDY1000HX:
|
||||
case ROM_TANDY1000SL2:
|
||||
case ROM_PC1512:
|
||||
case ROM_PC200:
|
||||
case ROM_OLIM24:
|
||||
case ROM_T3100E:
|
||||
return 1;
|
||||
|
||||
case ROM_PC1640:
|
||||
case ROM_PC2086:
|
||||
case ROM_PC3086:
|
||||
case ROM_MEGAPC:
|
||||
case ROM_MEGAPCDX:
|
||||
case ROM_IBMPS1_2011:
|
||||
case ROM_IBMPS2_M30_286:
|
||||
case ROM_IBMPS2_M50:
|
||||
case ROM_IBMPS2_M55SX:
|
||||
case ROM_IBMPS2_M70_TYPE3:
|
||||
case ROM_IBMPS2_M70_TYPE4:
|
||||
case ROM_IBMPS2_M80:
|
||||
case ROM_IBMPS1_2121:
|
||||
return 0;
|
||||
}
|
||||
return (video_cards[video_old_to_new(gfxcard)].flags & VIDEO_FLAG_TYPE_MASK) == VIDEO_FLAG_TYPE_CGA;
|
||||
}
|
||||
|
||||
int video_is_ega_vga(void)
|
||||
{
|
||||
switch (romset)
|
||||
{
|
||||
case ROM_IBMPCJR:
|
||||
case ROM_TANDY:
|
||||
case ROM_TANDY1000HX:
|
||||
case ROM_TANDY1000SL2:
|
||||
case ROM_PC1512:
|
||||
case ROM_PC200:
|
||||
case ROM_OLIM24:
|
||||
case ROM_T3100E:
|
||||
return 0;
|
||||
|
||||
case ROM_PC1640:
|
||||
case ROM_PC2086:
|
||||
case ROM_PC3086:
|
||||
case ROM_MEGAPC:
|
||||
case ROM_MEGAPCDX:
|
||||
case ROM_IBMPS1_2011:
|
||||
case ROM_IBMPS2_M30_286:
|
||||
case ROM_IBMPS2_M50:
|
||||
case ROM_IBMPS2_M55SX:
|
||||
case ROM_IBMPS2_M70_TYPE3:
|
||||
case ROM_IBMPS2_M70_TYPE4:
|
||||
case ROM_IBMPS2_M80:
|
||||
case ROM_IBMPS1_2121:
|
||||
return 1;
|
||||
}
|
||||
return (video_cards[video_old_to_new(gfxcard)].flags & VIDEO_FLAG_TYPE_MASK) == VIDEO_FLAG_TYPE_SPECIAL;
|
||||
}
|
||||
1796
backup code/video - Cópia/vid_tgui9440.c
Normal file
1796
backup code/video - Cópia/vid_tgui9440.c
Normal file
File diff suppressed because it is too large
Load Diff
6
backup code/video - Cópia/vid_tgui9440.h
Normal file
6
backup code/video - Cópia/vid_tgui9440.h
Normal file
@@ -0,0 +1,6 @@
|
||||
/* Copyright holders: Sarah Walker
|
||||
see COPYING for more details
|
||||
*/
|
||||
extern const device_t tgui9400cxi_device;
|
||||
extern const device_t tgui9440_vlb_device;
|
||||
extern const device_t tgui9440_pci_device;
|
||||
312
backup code/video - Cópia/vid_ti_cf62011.c
Normal file
312
backup code/video - Cópia/vid_ti_cf62011.c
Normal file
@@ -0,0 +1,312 @@
|
||||
/*
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
*
|
||||
* This file is part of the 86Box distribution.
|
||||
*
|
||||
* Emulation of the TI CF62011 SVGA chip.
|
||||
*
|
||||
* This chip was used in several of IBM's later machines, such
|
||||
* as the PS/1 Model 2121, and a number of PS/2 models. As noted
|
||||
* in an article on Usenet:
|
||||
*
|
||||
* "In the early 90s IBM looked for some cheap VGA card to
|
||||
* substitute the (relatively) expensive XGA-2 adapter for
|
||||
* *servers*, where the primary purpose is supervision of the
|
||||
* machine rather than real *work* with it in Hi-Res. It was
|
||||
* just to supply a base video, where a XGA-2 were a waste of
|
||||
* potential. They had a contract with TI for some DSPs in
|
||||
* multimedia already (the MWave for instance is based on
|
||||
* TI-DSPs as well as many Thinkpad internal chipsets) and TI
|
||||
* offered them a rather cheap – and inexpensive – chipset
|
||||
* and combined it with a cheap clock oscillator and an Inmos
|
||||
* RAMDAC. That chipset was already pretty much outdated at
|
||||
* that time but IBM decided it would suffice for that low
|
||||
* end purpose.
|
||||
*
|
||||
* Driver support was given under DOS and OS/2 only for base
|
||||
* functions like selection of the vertical refresh and few
|
||||
* different modes only. Not even the Win 3.x support has
|
||||
* been finalized. Technically the adapter could do better
|
||||
* than VGA, but its video BIOS is largely undocumented and
|
||||
* intentionally crippled down to a few functions."
|
||||
*
|
||||
* This chip is reportedly the same one as used in the MCA
|
||||
* IBM SVGA Adapter/A (ID 090EEh), which mostly had faster
|
||||
* VRAM and RAMDAC. The VESA DOS graphics driver for that
|
||||
* card can be used: m95svga.exe
|
||||
*
|
||||
* The controller responds at ports in the range 0x2100-0x210F,
|
||||
* which are the same as the XGA. It supports up to 1MB of VRAM,
|
||||
* but we lock it down to 512K. The PS/1 2122 had 256K.
|
||||
*
|
||||
* Version: @(#)vid_ti_cf62011.c 1.0.7 2018/04/29
|
||||
*
|
||||
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
* Fred N. van Kempen, <decwiz@yahoo.com>
|
||||
*
|
||||
* Copyright 2008-2018 Sarah Walker.
|
||||
* Copyright 2016-2018 Miran Grca.
|
||||
* Copyright 2017,2018 Fred N. van Kempen.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <wchar.h>
|
||||
#include "../86box.h"
|
||||
#include "../config.h"
|
||||
#include "../io.h"
|
||||
#include "../mem.h"
|
||||
#include "../rom.h"
|
||||
#include "../device.h"
|
||||
#include "../video/video.h"
|
||||
#include "../video/vid_vga.h"
|
||||
#include "../video/vid_svga.h"
|
||||
#include "vid_ti_cf62011.h"
|
||||
|
||||
|
||||
typedef struct {
|
||||
svga_t svga;
|
||||
|
||||
rom_t bios_rom;
|
||||
|
||||
int enabled;
|
||||
|
||||
uint32_t vram_size;
|
||||
|
||||
uint8_t banking;
|
||||
uint8_t reg_2100;
|
||||
uint8_t reg_210a;
|
||||
} tivga_t;
|
||||
|
||||
|
||||
static void
|
||||
vid_out(uint16_t addr, uint8_t val, void *priv)
|
||||
{
|
||||
tivga_t *ti = (tivga_t *)priv;
|
||||
svga_t *svga = &ti->svga;
|
||||
uint8_t old;
|
||||
|
||||
#if 0
|
||||
if (((addr & 0xfff0) == 0x03d0 || (addr & 0xfff0) == 0x03b0) &&
|
||||
!(svga->miscout & 1)) addr ^= 0x60;
|
||||
#endif
|
||||
|
||||
switch (addr) {
|
||||
case 0x0102:
|
||||
ti->enabled = (val & 0x01);
|
||||
return;
|
||||
|
||||
case 0x03d4:
|
||||
svga->crtcreg = val & 0x3f;
|
||||
return;
|
||||
|
||||
case 0x03d5:
|
||||
if (svga->crtcreg & 0x20)
|
||||
return;
|
||||
if ((svga->crtcreg < 7) && (svga->crtc[0x11] & 0x80))
|
||||
return;
|
||||
if ((svga->crtcreg == 7) && (svga->crtc[0x11] & 0x80))
|
||||
val = (svga->crtc[7] & ~0x10) | (val & 0x10);
|
||||
old = svga->crtc[svga->crtcreg];
|
||||
svga->crtc[svga->crtcreg] = val;
|
||||
if (old != val) {
|
||||
if (svga->crtcreg < 0xe || svga->crtcreg > 0x10) {
|
||||
svga->fullchange = changeframecount;
|
||||
svga_recalctimings(svga);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x2100:
|
||||
ti->reg_2100 = val;
|
||||
if ((val & 7) < 4)
|
||||
svga->read_bank = svga->write_bank = 0;
|
||||
else
|
||||
svga->read_bank = svga->write_bank = (ti->banking & 0x7) * 0x10000;
|
||||
break;
|
||||
|
||||
case 0x2108:
|
||||
if ((ti->reg_2100 & 7) >= 4)
|
||||
svga->read_bank = svga->write_bank = (val & 0x7) * 0x10000;
|
||||
ti->banking = val;
|
||||
break;
|
||||
|
||||
case 0x210a:
|
||||
ti->reg_210a = val;
|
||||
break;
|
||||
}
|
||||
|
||||
svga_out(addr, val, svga);
|
||||
}
|
||||
|
||||
|
||||
static uint8_t
|
||||
vid_in(uint16_t addr, void *priv)
|
||||
{
|
||||
tivga_t *ti = (tivga_t *)priv;
|
||||
svga_t *svga = &ti->svga;
|
||||
uint8_t ret;
|
||||
|
||||
#if 0
|
||||
if (((addr & 0xfff0) == 0x03d0 || (addr & 0xfff0) == 0x03b0) &&
|
||||
!(svga->miscout & 1)) addr ^= 0x60;
|
||||
#endif
|
||||
|
||||
switch (addr) {
|
||||
case 0x0100:
|
||||
ret = 0xfe;
|
||||
break;
|
||||
|
||||
case 0x0101:
|
||||
ret = 0xe8;
|
||||
break;
|
||||
|
||||
case 0x0102:
|
||||
ret = ti->enabled;
|
||||
break;
|
||||
|
||||
case 0x03d4:
|
||||
ret = svga->crtcreg;
|
||||
break;
|
||||
|
||||
case 0x03d5:
|
||||
if (svga->crtcreg & 0x20)
|
||||
ret = 0xff;
|
||||
else
|
||||
ret = svga->crtc[svga->crtcreg];
|
||||
break;
|
||||
|
||||
case 0x2100:
|
||||
ret = ti->reg_2100;
|
||||
break;
|
||||
|
||||
case 0x2108:
|
||||
ret = ti->banking;
|
||||
break;
|
||||
|
||||
case 0x210a:
|
||||
ret = ti->reg_210a;
|
||||
break;
|
||||
|
||||
default:
|
||||
ret = svga_in(addr, svga);
|
||||
break;
|
||||
}
|
||||
|
||||
return(ret);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
vid_speed_changed(void *priv)
|
||||
{
|
||||
tivga_t *ti = (tivga_t *)priv;
|
||||
|
||||
svga_recalctimings(&ti->svga);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
vid_force_redraw(void *priv)
|
||||
{
|
||||
tivga_t *ti = (tivga_t *)priv;
|
||||
|
||||
ti->svga.fullchange = changeframecount;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
vid_close(void *priv)
|
||||
{
|
||||
tivga_t *ti = (tivga_t *)priv;
|
||||
|
||||
svga_close(&ti->svga);
|
||||
|
||||
free(ti);
|
||||
}
|
||||
|
||||
|
||||
static void *
|
||||
vid_init(const device_t *info)
|
||||
{
|
||||
tivga_t *ti;
|
||||
|
||||
/* Allocate control block and initialize. */
|
||||
ti = (tivga_t *)malloc(sizeof(tivga_t));
|
||||
memset(ti, 0x00, sizeof(tivga_t));
|
||||
|
||||
/* Set amount of VRAM in KB. */
|
||||
if (info->local == 0)
|
||||
ti->vram_size = device_get_config_int("vram_size");
|
||||
else
|
||||
ti->vram_size = info->local;
|
||||
|
||||
svga_init(&ti->svga, ti,
|
||||
ti->vram_size<<10,
|
||||
NULL, vid_in, vid_out, NULL, NULL);
|
||||
|
||||
io_sethandler(0x0100, 2, vid_in, NULL, NULL, NULL, NULL, NULL, ti);
|
||||
io_sethandler(0x03c0, 32, vid_in, NULL, NULL, vid_out, NULL, NULL, ti);
|
||||
io_sethandler(0x2100, 16, vid_in, NULL, NULL, vid_out, NULL, NULL, ti);
|
||||
|
||||
ti->svga.bpp = 8;
|
||||
ti->svga.miscout = 1;
|
||||
|
||||
return(ti);
|
||||
}
|
||||
|
||||
|
||||
#if defined(DEV_BRANCH) && defined(USE_TI)
|
||||
static const device_config_t vid_config[] =
|
||||
{
|
||||
{
|
||||
"vram_size", "Memory Size", CONFIG_SELECTION, "", 256,
|
||||
{
|
||||
{
|
||||
"256K", 256
|
||||
},
|
||||
{
|
||||
"512K", 512
|
||||
},
|
||||
{
|
||||
"1024K", 1024
|
||||
},
|
||||
{
|
||||
""
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"", "", -1
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
const device_t ti_cf62011_device = {
|
||||
"TI CF62011 SVGA",
|
||||
0,
|
||||
0,
|
||||
vid_init, vid_close, NULL,
|
||||
NULL,
|
||||
vid_speed_changed,
|
||||
vid_force_redraw,
|
||||
vid_config
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
const device_t ibm_ps1_2121_device = {
|
||||
"IBM PS/1 Model 2121 SVGA",
|
||||
0,
|
||||
512,
|
||||
vid_init, vid_close, NULL,
|
||||
NULL,
|
||||
vid_speed_changed,
|
||||
vid_force_redraw,
|
||||
NULL
|
||||
};
|
||||
4
backup code/video - Cópia/vid_ti_cf62011.h
Normal file
4
backup code/video - Cópia/vid_ti_cf62011.h
Normal file
@@ -0,0 +1,4 @@
|
||||
#if defined(DEV_BRANCH) && defined(USE_TI)
|
||||
extern const device_t ti_cf62011_device;
|
||||
#endif
|
||||
extern const device_t ibm_ps1_2121_device;
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user