mirror of
https://github.com/86Box/86Box.git
synced 2026-02-22 09:35:32 -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:
284
386_ref.cpp
Normal file
284
386_ref.cpp
Normal file
@@ -0,0 +1,284 @@
|
||||
extern "C"
|
||||
{
|
||||
#include <stdarg.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <wchar.h>
|
||||
#include <math.h>
|
||||
#ifndef INFINITY
|
||||
# define INFINITY (__builtin_inff())
|
||||
#endif
|
||||
#define HAVE_STDARG_H
|
||||
#include "../86box.h"
|
||||
#include "cpu.h"
|
||||
#include "x86.h"
|
||||
#include "x87.h"
|
||||
#include "../nmi.h"
|
||||
#include "../mem.h"
|
||||
#include "../pic.h"
|
||||
#include "../pit.h"
|
||||
#include "../timer.h"
|
||||
#include "../floppy/fdd.h"
|
||||
#include "../floppy/fdc.h"
|
||||
|
||||
#define CPU_BLOCK_END()
|
||||
|
||||
uint16_t flags,eflags;
|
||||
uint32_t oldds,oldss,olddslimit,oldsslimit,olddslimitw,oldsslimitw;
|
||||
|
||||
x86seg gdt,ldt,idt,tr;
|
||||
x86seg _cs,_ds,_es,_ss,_fs,_gs;
|
||||
x86seg _oldds;
|
||||
|
||||
uint32_t cr2, cr3, cr4;
|
||||
uint32_t dr[8];
|
||||
|
||||
#include "x86_flags.h"
|
||||
|
||||
#ifdef ENABLE_386_REF_LOG
|
||||
int x386_ref_do_log = ENABLE_386_REF_LOG;
|
||||
#endif
|
||||
|
||||
|
||||
static void
|
||||
x386_ref_log(const char *fmt, ...)
|
||||
{
|
||||
#ifdef ENABLE_386_REF_LOG
|
||||
va_list ap;
|
||||
|
||||
if (x386_do_log) {
|
||||
va_start(ap, fmt);
|
||||
pclog_ex(fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
enum class translate_kind
|
||||
{
|
||||
TRANSLATE_READ, TRANSLATE_WRITE, TRANSLATE_EXEC
|
||||
};
|
||||
|
||||
|
||||
enum class exception_type
|
||||
{
|
||||
FAULT, TRAP, ABORT
|
||||
};
|
||||
|
||||
|
||||
struct cpu_exception
|
||||
{
|
||||
exception_type type;
|
||||
uint8_t fault_type;
|
||||
uint32_t error_code;
|
||||
bool error_code_valid;
|
||||
cpu_exception(exception_type _type, uint8_t _fault_type, uint32_t errcode, bool errcodevalid)
|
||||
: type(_type)
|
||||
, fault_type(_fault_type)
|
||||
, error_code(errcode)
|
||||
, error_code_valid(errcodevalid) {}
|
||||
};
|
||||
|
||||
|
||||
void
|
||||
type_check_ref(x86seg* segment, uint32_t offset, translate_kind kind)
|
||||
{
|
||||
bool system_seg = !((segment->flags_ref >> 4) & 1);
|
||||
bool executable = (segment->flags_ref >> 3) & 1;
|
||||
|
||||
if(!system_seg)
|
||||
{
|
||||
if(executable) {
|
||||
bool readable = (segment->flags_ref >> 1) & 1;
|
||||
switch(kind) {
|
||||
case TRANSLATE_READ:
|
||||
if (!readable)
|
||||
throw cpu_exception(FAULT, ABRT_GPF, 0, true);
|
||||
break;
|
||||
case TRANSLATE_WRITE:
|
||||
throw cpu_exception(FAULT, ABRT_GPF, 0, true);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
bool writeable = (segment->flags_ref >> 1) & 1;
|
||||
switch(kind) {
|
||||
case TRANSLATE_WRITE:
|
||||
if (!writeable)
|
||||
throw cpu_exception(FAULT, ABRT_GPF, 0, true);
|
||||
break;
|
||||
case TRANSLATE_EXEC:
|
||||
throw cpu_exception(FAULT, ABRT_GPF, 0, true);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// TODO
|
||||
x386_ref_log("type_check_ref called with a system-type segment! Execution correctness is not guaranteed past this point!\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
limit_check_ref(x86seg* segment, uint32_t offset, translate_kind kind)
|
||||
{
|
||||
uint8_t fault_type = ABRT_GPF;
|
||||
uint32_t addr = offset & ((1 << (32 - 12)) - 1);
|
||||
|
||||
if (segment == &_ss)
|
||||
fault_type = ABRT_SS;
|
||||
|
||||
switch(kind) {
|
||||
case translate_kind::READ:
|
||||
case translate_kind::WRITE:
|
||||
// Data segment.
|
||||
bool expand_down = (segment->flags_ref >> 2) & 1;
|
||||
bool big_seg = (segment->flags_ref >> 14) & 1; // TODO: Not sure if this is ever used. Test this!
|
||||
bool granularity = (segment->flags_ref >> 15) & 1;
|
||||
uint32_t lower_bound;
|
||||
uint32_t upper_bound;
|
||||
if (big_seg != granularity)
|
||||
x386_ref_log("B bit doesn't equal granularity bit! Execution correctness is not guaranteed past this point!\n");
|
||||
if (expand_down) {
|
||||
if (granularity) {
|
||||
lower_bound = ((addr << 12) | 0xfff) + 1;
|
||||
upper_bound = 0xffffffff; //4G - 1
|
||||
} else {
|
||||
lower_bound = addr + 1;
|
||||
upper_bound = 0xffff; //64K - 1
|
||||
}
|
||||
} else {
|
||||
lower_bound = 0;
|
||||
if (granularity)
|
||||
upper_bound = (addr << 12) | 0xfff;
|
||||
else
|
||||
upper_bound = addr;
|
||||
}
|
||||
if ((addr < lower_bound) || (addr > upper_bound))
|
||||
throw cpu_exception(FAULT, fault_type, 0, true);
|
||||
break;
|
||||
|
||||
default:
|
||||
bool granularity = (segment->flags_ref >> 15) & 1;
|
||||
uint32_t limit;
|
||||
|
||||
if (granularity)
|
||||
limit = (addr << 12) | 0xfff;
|
||||
else
|
||||
limit = addr;
|
||||
|
||||
if (addr > limit)
|
||||
throw cpu_exception(FAULT, fault_type, 0, true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
privilege_check_ref(x86seg* segment, uint32_t offset, translate_kind kind)
|
||||
{
|
||||
bool system_seg = !((segment->flags_ref >> 4) & 1);
|
||||
bool executable = (segment->flags_ref >> 3) & 1;
|
||||
|
||||
if (!system_seg) {
|
||||
if(executable) {
|
||||
bool conforming = (segment->flags_ref >> 2) & 1;
|
||||
if (conforming)
|
||||
return;
|
||||
else {
|
||||
int seg_rpl = segment->seg & 3;
|
||||
int dpl = (segment->flags_ref >> 5) & 3;
|
||||
if (dpl < CPL)
|
||||
throw cpu_exception(FAULT, ABRT_GPF, 0, true);
|
||||
if (dpl < seg_rpl)
|
||||
throw cpu_exception(FAULT, ABRT_GPF, 0, true);
|
||||
}
|
||||
} else {
|
||||
int seg_rpl = segment->seg & 3;
|
||||
int dpl = (segment->flags_ref >> 5) & 3;
|
||||
if (dpl < CPL)
|
||||
throw cpu_exception(FAULT, ABRT_GPF, 0, true);
|
||||
if (dpl < seg_rpl)
|
||||
throw cpu_exception(FAULT, ABRT_GPF, 0, true);
|
||||
}
|
||||
} else {
|
||||
// TODO
|
||||
x386_ref_log("privilege_check_ref called with a system-type segment! Execution correctness is not guaranteed past this point!\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#define rammap(x) ((uint32_t *)(_mem_exec[(x) >> 14]))[((x) >> 2) & 0xfff]
|
||||
|
||||
|
||||
uint32_t
|
||||
translate_addr_ref(x86seg* segment, uint32_t offset, translate_kind kind)
|
||||
{
|
||||
// Segment-level checks.
|
||||
type_check_ref(segment, offset, kind);
|
||||
limit_check_ref(segment, offset, kind);
|
||||
privilege_check_ref(segment, offset, kind);
|
||||
|
||||
uint32_t addr = segment->base + offset;
|
||||
|
||||
if (!(cr0 >> 31))
|
||||
return addr;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
readmemb_ref(x86seg* segment, uint32_t offset)
|
||||
{
|
||||
uint32_t addr = translate_addr_ref(segment, offset, TRANSLATE_READ);
|
||||
return mem_readb_phys_dma(addr);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
writememb_ref(x86seg* segment, uint32_t offset, uint8_t data)
|
||||
{
|
||||
uint32_t addr = translate_addr_ref(segment, offset, TRANSLATE_READ);
|
||||
mem_writeb_phys_dma(addr, data);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
exec386_ref(int cycs)
|
||||
{
|
||||
uint8_t temp;
|
||||
uint32_t addr;
|
||||
int tempi;
|
||||
int cycdiff;
|
||||
int oldcyc;
|
||||
|
||||
cycles+=cycs;
|
||||
|
||||
while (cycles>0) {
|
||||
timer_start_period(cycles << TIMER_SHIFT);
|
||||
|
||||
oldcs = CS;
|
||||
cpu_state.oldpc = cpu_state.pc;
|
||||
oldcpl = CPL;
|
||||
cpu_state.op32 = use32;
|
||||
|
||||
x86_was_reset = 0;
|
||||
|
||||
dontprint = 0;
|
||||
|
||||
cpu_state.ea_seg = &_ds;
|
||||
cpu_state.ssegs = 0;
|
||||
|
||||
try {
|
||||
} catch(cpu_exception) {
|
||||
}
|
||||
|
||||
timer_end_period(cycles << TIMER_SHIFT);
|
||||
}
|
||||
}
|
||||
}
|
||||
BIN
EMM386.EX_
Normal file
BIN
EMM386.EX_
Normal file
Binary file not shown.
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
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user