146 lines
2.8 KiB
C
146 lines
2.8 KiB
C
#include <stdarg.h>
|
|
#include <stdint.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <wchar.h>
|
|
#define HAVE_STDARG_H
|
|
#include <86box/86box.h>
|
|
#include "cpu.h"
|
|
#include <86box/io.h>
|
|
#include <86box/device.h>
|
|
#include <86box/mem.h>
|
|
#include <86box/chipset.h>
|
|
|
|
|
|
typedef struct
|
|
{
|
|
uint8_t cur_reg, tries,
|
|
regs[258];
|
|
} rabbit_t;
|
|
|
|
|
|
static void
|
|
rabbit_recalcmapping(rabbit_t *dev)
|
|
{
|
|
uint32_t shread, shwrite;
|
|
uint32_t shflags = 0;
|
|
|
|
shread = !!(dev->regs[0x101] & 0x40);
|
|
shwrite = !!(dev->regs[0x100] & 0x02);
|
|
|
|
shflags = shread ? MEM_READ_INTERNAL : MEM_READ_EXTANY;
|
|
shflags |= shwrite ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY;
|
|
|
|
shadowbios = !!shread;
|
|
shadowbios_write = !!shwrite;
|
|
|
|
#ifdef USE_SHADOW_C0000
|
|
mem_set_mem_state(0x000c0000, 0x00040000, MEM_READ_EXTANY | MEM_WRITE_EXTANY);
|
|
#else
|
|
mem_set_mem_state(0x000e0000, 0x00020000, MEM_READ_EXTANY | MEM_WRITE_EXTANY);
|
|
#endif
|
|
|
|
switch (dev->regs[0x100] & 0x09) {
|
|
case 0x01:
|
|
/* The one BIOS we use seems to use something else to control C0000-DFFFF shadow,
|
|
no idea what. */
|
|
#ifdef USE_SHADOW_C0000
|
|
/* 64K at 0C0000-0CFFFF */
|
|
mem_set_mem_state(0x000c0000, 0x00010000, shflags);
|
|
/* FALLTHROUGH */
|
|
#endif
|
|
case 0x00:
|
|
/* 64K at 0F0000-0FFFFF */
|
|
mem_set_mem_state(0x000f0000, 0x00010000, shflags);
|
|
break;
|
|
|
|
case 0x09:
|
|
#ifdef USE_SHADOW_C0000
|
|
/* 128K at 0C0000-0DFFFF */
|
|
mem_set_mem_state(0x000c0000, 0x00020000, shflags);
|
|
/* FALLTHROUGH */
|
|
#endif
|
|
case 0x08:
|
|
/* 128K at 0E0000-0FFFFF */
|
|
mem_set_mem_state(0x000e0000, 0x00020000, shflags);
|
|
break;
|
|
}
|
|
|
|
flushmmucache();
|
|
}
|
|
|
|
|
|
static void
|
|
rabbit_write(uint16_t addr, uint8_t val, void *priv)
|
|
{
|
|
rabbit_t *dev = (rabbit_t *) priv;
|
|
|
|
switch (addr) {
|
|
case 0x22:
|
|
dev->cur_reg = val;
|
|
dev->tries = 0;
|
|
break;
|
|
case 0x23:
|
|
if (dev->cur_reg == 0x83) {
|
|
if (dev->tries < 0x02) {
|
|
dev->regs[dev->tries++ | 0x100] = val;
|
|
if (dev->tries == 0x02)
|
|
rabbit_recalcmapping(dev);
|
|
}
|
|
} else
|
|
dev->regs[dev->cur_reg] = val;
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
static uint8_t
|
|
rabbit_read(uint16_t addr, void *priv)
|
|
{
|
|
uint8_t ret = 0xff;
|
|
rabbit_t *dev = (rabbit_t *) priv;
|
|
|
|
switch (addr) {
|
|
case 0x23:
|
|
if (dev->cur_reg == 0x83) {
|
|
if (dev->tries < 0x02)
|
|
ret = dev->regs[dev->tries++ | 0x100];
|
|
} else
|
|
ret = dev->regs[dev->cur_reg];
|
|
break;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
|
|
static void
|
|
rabbit_close(void *priv)
|
|
{
|
|
rabbit_t *dev = (rabbit_t *) priv;
|
|
|
|
free(dev);
|
|
}
|
|
|
|
|
|
static void *
|
|
rabbit_init(const device_t *info)
|
|
{
|
|
rabbit_t *dev = (rabbit_t *) malloc(sizeof(rabbit_t));
|
|
memset(dev, 0, sizeof(rabbit_t));
|
|
|
|
io_sethandler(0x0022, 0x0002, rabbit_read, NULL, NULL, rabbit_write, NULL, NULL, dev);
|
|
|
|
return dev;
|
|
}
|
|
|
|
|
|
const device_t rabbit_device = {
|
|
"SiS Rabbit",
|
|
0,
|
|
0,
|
|
rabbit_init, rabbit_close, NULL,
|
|
{ NULL }, NULL, NULL,
|
|
NULL
|
|
}; |