2661 lines
69 KiB
C++
2661 lines
69 KiB
C++
/*
|
|
* UAE - The Un*x Amiga Emulator
|
|
*
|
|
* AutoConfig (tm) Expansions (ZorroII/III)
|
|
*
|
|
* Copyright 1996,1997 Stefan Reinauer <stepan@linux.de>
|
|
* Copyright 1997 Brian King <Brian_King@Mitel.com>
|
|
* - added gfxcard code
|
|
*
|
|
*/
|
|
|
|
#include "sysconfig.h"
|
|
#include "sysdeps.h"
|
|
|
|
#include "options.h"
|
|
#include "uae.h"
|
|
#include "traps.h"
|
|
#include "memory.h"
|
|
#include "rommgr.h"
|
|
#include "custom.h"
|
|
#include "newcpu.h"
|
|
#include "savestate.h"
|
|
#include "gfxboard.h"
|
|
#ifdef CD32
|
|
#include "cd32_fmv.h"
|
|
#endif
|
|
#include "gayle.h"
|
|
#include "autoconf.h"
|
|
#include "devices.h"
|
|
|
|
|
|
#define CARD_FLAG_CAN_Z3 1
|
|
|
|
// More information in first revision HRM Appendix_G
|
|
#define BOARD_PROTOAUTOCONFIG 1
|
|
|
|
#define BOARD_AUTOCONFIG_Z2 2
|
|
#define BOARD_AUTOCONFIG_Z3 3
|
|
#define BOARD_NONAUTOCONFIG_BEFORE 4
|
|
#define BOARD_NONAUTOCONFIG_AFTER_Z2 5
|
|
#define BOARD_NONAUTOCONFIG_AFTER_Z3 6
|
|
#define BOARD_IGNORE 7
|
|
|
|
#define KS12_BOOT_HACK 1
|
|
|
|
#define MAX_EXPANSION_BOARD_SPACE 16
|
|
|
|
/* ********************************************************** */
|
|
/* 00 / 02 */
|
|
/* er_Type */
|
|
|
|
#define Z2_MEM_8MB 0x00 /* Size of Memory Block */
|
|
#define Z2_MEM_4MB 0x07
|
|
#define Z2_MEM_2MB 0x06
|
|
#define Z2_MEM_1MB 0x05
|
|
#define Z2_MEM_512KB 0x04
|
|
#define Z2_MEM_256KB 0x03
|
|
#define Z2_MEM_128KB 0x02
|
|
#define Z2_MEM_64KB 0x01
|
|
/* extended definitions */
|
|
#define Z3_MEM_16MB 0x00
|
|
#define Z3_MEM_32MB 0x01
|
|
#define Z3_MEM_64MB 0x02
|
|
#define Z3_MEM_128MB 0x03
|
|
#define Z3_MEM_256MB 0x04
|
|
#define Z3_MEM_512MB 0x05
|
|
#define Z3_MEM_1GB 0x06
|
|
|
|
#define chainedconfig 0x08 /* Next config is part of the same card */
|
|
#define rom_card 0x10 /* ROM vector is valid */
|
|
#define add_memory 0x20 /* Link RAM into free memory list */
|
|
|
|
/* Type of Expansion Card */
|
|
#define protoautoconfig 0x40
|
|
#define zorroII 0xc0
|
|
#define zorroIII 0x80
|
|
|
|
/* ********************************************************** */
|
|
/* 04 - 06 & 10-16 */
|
|
|
|
/* Manufacturer */
|
|
#define commodore_g 513 /* Commodore Braunschweig (Germany) */
|
|
#define commodore 514 /* Commodore West Chester */
|
|
#define hackers_id 2011 /* Special ID for test cards */
|
|
|
|
/* ********************************************************** */
|
|
/* 08 - 0A */
|
|
/* er_Flags */
|
|
#define Z3_SS_MEM_SAME 0x00
|
|
#define Z3_SS_MEM_AUTO 0x01
|
|
#define Z3_SS_MEM_64KB 0x02
|
|
#define Z3_SS_MEM_128KB 0x03
|
|
#define Z3_SS_MEM_256KB 0x04
|
|
#define Z3_SS_MEM_512KB 0x05
|
|
#define Z3_SS_MEM_1MB 0x06 /* Zorro III card subsize */
|
|
#define Z3_SS_MEM_2MB 0x07
|
|
#define Z3_SS_MEM_4MB 0x08
|
|
#define Z3_SS_MEM_6MB 0x09
|
|
#define Z3_SS_MEM_8MB 0x0a
|
|
#define Z3_SS_MEM_10MB 0x0b
|
|
#define Z3_SS_MEM_12MB 0x0c
|
|
#define Z3_SS_MEM_14MB 0x0d
|
|
#define Z3_SS_MEM_defunct1 0x0e
|
|
#define Z3_SS_MEM_defunct2 0x0f
|
|
|
|
#define force_z3 0x10 /* *MUST* be set if card is Z3 */
|
|
#define ext_size 0x20 /* Use extended size table for bits 0-2 of er_Type */
|
|
#define no_shutup 0x40 /* Card cannot receive Shut_up_forever */
|
|
#define care_addr 0x80 /* Z2=Adress HAS to be $200000-$9fffff Z3=1->mem,0=io */
|
|
|
|
/* ********************************************************** */
|
|
/* 40-42 */
|
|
/* ec_interrupt (unused) */
|
|
|
|
#define enable_irq 0x01 /* enable Interrupt */
|
|
#define reset_card 0x04 /* Reset of Expansion Card - must be 0 */
|
|
#define card_int2 0x10 /* READ ONLY: IRQ 2 active */
|
|
#define card_irq6 0x20 /* READ ONLY: IRQ 6 active */
|
|
#define card_irq7 0x40 /* READ ONLY: IRQ 7 active */
|
|
#define does_irq 0x80 /* READ ONLY: Card currently throws IRQ */
|
|
|
|
/* ********************************************************** */
|
|
|
|
/* ROM defines (DiagVec) */
|
|
|
|
#define rom_4bit (0x00<<14) /* ROM width */
|
|
#define rom_8bit (0x01<<14)
|
|
#define rom_16bit (0x02<<14)
|
|
|
|
#define rom_never (0x00<<12) /* Never run Boot Code */
|
|
#define rom_install (0x01<<12) /* run code at install time */
|
|
#define rom_binddrv (0x02<<12) /* run code with binddrivers */
|
|
|
|
uaecptr ROM_filesys_diagentry;
|
|
uaecptr ROM_hardfile_resname, ROM_hardfile_resid;
|
|
uaecptr ROM_hardfile_init;
|
|
int uae_boot_rom_type;
|
|
int uae_boot_rom_size; /* size = code size only */
|
|
static bool chipdone;
|
|
static int do_mount;
|
|
|
|
#define FILESYS_DIAGPOINT 0x01e0
|
|
#define FILESYS_BOOTPOINT 0x01f0
|
|
#define FILESYS_DIAGAREA 0x2000
|
|
|
|
/* ********************************************************** */
|
|
|
|
struct card_data
|
|
{
|
|
bool (*initrc)(struct autoconfig_info*);
|
|
bool (*initnum)(struct autoconfig_info*);
|
|
addrbank *(*map)(struct autoconfig_info*);
|
|
struct romconfig *rc;
|
|
const TCHAR *name;
|
|
int flags;
|
|
int zorro;
|
|
uaecptr base;
|
|
uae_u32 size;
|
|
// parsing updated fields
|
|
const struct expansionromtype *ert;
|
|
struct autoconfig_info aci;
|
|
};
|
|
|
|
static struct card_data cards_set[MAX_EXPANSION_BOARD_SPACE];
|
|
static struct card_data *cards[MAX_EXPANSION_BOARD_SPACE];
|
|
|
|
static int ecard, cardno, z3num;
|
|
static int restore_cardno;
|
|
static addrbank *expamem_bank_current;
|
|
|
|
static uae_u16 uae_id;
|
|
|
|
static bool isnonautoconfig(int v)
|
|
{
|
|
return v == BOARD_NONAUTOCONFIG_AFTER_Z2 ||
|
|
v == BOARD_NONAUTOCONFIG_AFTER_Z3 ||
|
|
v == BOARD_NONAUTOCONFIG_BEFORE;
|
|
}
|
|
|
|
static bool ks12orolder(void)
|
|
{
|
|
/* check if Kickstart version is below 1.3 */
|
|
return kickstart_version && kickstart_version < 34;
|
|
}
|
|
static bool ks11orolder(void)
|
|
{
|
|
return kickstart_version && kickstart_version < 33;
|
|
}
|
|
|
|
|
|
/* ********************************************************** */
|
|
|
|
/* Please note: ZorroIII implementation seems to work different
|
|
* than described in the HRM. This claims that ZorroIII config
|
|
* address is 0xff000000 while the ZorroII config space starts
|
|
* at 0x00e80000. In reality, both, Z2 and Z3 cards are
|
|
* configured in the ZorroII config space. Kickstart 3.1 doesn't
|
|
* even do a single read or write access to the ZorroIII space.
|
|
* The original Amiga include files tell the same as the HRM.
|
|
* ZorroIII: If you set ext_size in er_Flags and give a Z2-size
|
|
* in er_Type you can very likely add some ZorroII address space
|
|
* to a ZorroIII card on a real Amiga. This is not implemented
|
|
* yet.
|
|
* -- Stefan
|
|
*
|
|
* Surprising that 0xFF000000 isn't used. Maybe it depends on the
|
|
* ROM. Anyway, the HRM says that Z3 cards may appear in Z2 config
|
|
* space, so what we are doing here is correct.
|
|
* -- Bernd
|
|
*/
|
|
|
|
/* Autoconfig address space at 0xE80000 */
|
|
static uae_u8 expamem[65536 + 4];
|
|
#define AUTOMATIC_AUTOCONFIG_MAX_ADDRESS 0x80
|
|
static int expamem_autoconfig_mode;
|
|
static addrbank*(*expamem_map)(struct autoconfig_info*);
|
|
|
|
static uae_u8 expamem_lo;
|
|
static uae_u16 expamem_hi;
|
|
static uaecptr expamem_z3_pointer_real, expamem_z3_pointer_uae;
|
|
static uaecptr expamem_z3_highram_real, expamem_z3_highram_uae;
|
|
uae_u32 expamem_board_size;
|
|
uaecptr expamem_board_pointer;
|
|
static uae_u8 slots_e8[8] = { 0 };
|
|
static uae_u8 slots_20[(8 * 1024 * 1024) / 65536] = { 0 };
|
|
|
|
static int z3hack_override;
|
|
|
|
void set_expamem_z3_hack_mode(int mode)
|
|
{
|
|
z3hack_override = mode;
|
|
}
|
|
|
|
static bool expamem_z3hack(struct uae_prefs *p)
|
|
{
|
|
if (z3hack_override == Z3MAPPING_UAE)
|
|
return true;
|
|
if (z3hack_override == Z3MAPPING_REAL)
|
|
return false;
|
|
return p->z3_mapping_mode == Z3MAPPING_UAE;
|
|
}
|
|
|
|
/* Ugly hack for >2M chip RAM in single pool
|
|
* We can't add it any later or early boot menu
|
|
* stops working because it sets kicktag at the end
|
|
* of chip ram...
|
|
*/
|
|
static void addextrachip (uae_u32 sysbase)
|
|
{
|
|
if (currprefs.chipmem_size <= 0x00200000)
|
|
return;
|
|
if (sysbase & 0x80000001)
|
|
return;
|
|
if (!valid_address (sysbase, 1000))
|
|
return;
|
|
uae_u32 ml = get_long (sysbase + 322);
|
|
if (!valid_address (ml, 32))
|
|
return;
|
|
uae_u32 next;
|
|
while ((next = get_long (ml))) {
|
|
if (!valid_address (ml, 32))
|
|
return;
|
|
uae_u32 upper = get_long (ml + 24);
|
|
uae_u32 lower = get_long (ml + 20);
|
|
if (lower & ~0xffff) {
|
|
ml = next;
|
|
continue;
|
|
}
|
|
uae_u16 attr = get_word (ml + 14);
|
|
if ((attr & 0x8002) != 2) {
|
|
ml = next;
|
|
continue;
|
|
}
|
|
if (upper >= currprefs.chipmem_size)
|
|
return;
|
|
uae_u32 added = currprefs.chipmem_size - upper;
|
|
uae_u32 first = get_long (ml + 16);
|
|
put_long (ml + 24, currprefs.chipmem_size); // mh_Upper
|
|
put_long (ml + 28, get_long (ml + 28) + added); // mh_Free
|
|
uae_u32 next = 0;
|
|
while (first) {
|
|
next = first;
|
|
first = get_long (next);
|
|
}
|
|
if (next) {
|
|
uae_u32 bytes = get_long (next + 4);
|
|
if (next + bytes == 0x00200000) {
|
|
put_long (next + 4, currprefs.chipmem_size - next);
|
|
} else {
|
|
put_long (0x00200000 + 0, 0);
|
|
put_long (0x00200000 + 4, added);
|
|
put_long (next, 0x00200000);
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
|
|
addrbank expamem_null;
|
|
|
|
DECLARE_MEMORY_FUNCTIONS(expamem);
|
|
addrbank expamem_bank = {
|
|
expamem_lget, expamem_wget, expamem_bget,
|
|
expamem_lput, expamem_wput, expamem_bput,
|
|
default_xlate, default_check, NULL, NULL, _T("Autoconfig Z2"),
|
|
dummy_wgeti,
|
|
ABFLAG_IO | ABFLAG_SAFE, S_READ, S_WRITE
|
|
};
|
|
DECLARE_MEMORY_FUNCTIONS(expamemz3);
|
|
static addrbank expamemz3_bank = {
|
|
expamemz3_lget, expamemz3_wget, expamemz3_bget,
|
|
expamemz3_lput, expamemz3_wput, expamemz3_bput,
|
|
default_xlate, default_check, NULL, NULL, _T("Autoconfig Z3"),
|
|
dummy_wgeti,
|
|
ABFLAG_IO | ABFLAG_SAFE, S_READ, S_WRITE
|
|
};
|
|
|
|
static void expamem_init_clear (void)
|
|
{
|
|
memset (expamem, 0xff, sizeof expamem);
|
|
expamem_hi = expamem_lo = 0;
|
|
expamem_map = NULL;
|
|
}
|
|
/* autoconfig area is "non-existing" after last device */
|
|
static void expamem_init_clear_zero (void)
|
|
{
|
|
if (currprefs.cpu_model < 68020) {
|
|
map_banks (&dummy_bank, 0xe8, 1, 0);
|
|
if (!currprefs.address_space_24)
|
|
map_banks (&dummy_bank, AUTOCONFIG_Z3 >> 16, 1, 0);
|
|
} else {
|
|
map_banks(&expamem_bank, 0xe8, 1, 0);
|
|
if (!currprefs.address_space_24)
|
|
map_banks(&expamemz3_bank, AUTOCONFIG_Z3 >> 16, 1, 0);
|
|
}
|
|
expamem_bank_current = NULL;
|
|
}
|
|
|
|
static void expamem_init_clear2 (void)
|
|
{
|
|
expamem_bank.name = _T("Autoconfig Z2");
|
|
expamemz3_bank.name = _T("Autoconfig Z3");
|
|
expamem_init_clear_zero();
|
|
ecard = cardno;
|
|
}
|
|
|
|
static addrbank *expamem_init_last (void)
|
|
{
|
|
expamem_init_clear2();
|
|
return NULL;
|
|
}
|
|
|
|
static uae_u8 REGPARAM2 expamem_read(int addr)
|
|
{
|
|
uae_u8 b = (expamem[addr] & 0xf0) | (expamem[addr + 2] >> 4);
|
|
if (addr == 0 || addr == 2 || addr == 0x40 || addr == 0x42)
|
|
return b;
|
|
b = ~b;
|
|
return b;
|
|
}
|
|
|
|
static void REGPARAM2 expamem_write (uaecptr addr, uae_u32 value)
|
|
{
|
|
addr &= 0xffff;
|
|
if (addr == 00 || addr == 02 || addr == 0x40 || addr == 0x42) {
|
|
expamem[addr] = (value & 0xf0);
|
|
expamem[addr + 2] = (value & 0x0f) << 4;
|
|
} else {
|
|
expamem[addr] = ~(value & 0xf0);
|
|
expamem[addr + 2] = ~((value & 0x0f) << 4);
|
|
}
|
|
}
|
|
|
|
static int REGPARAM2 expamem_type (void)
|
|
{
|
|
return expamem_read(0) & 0xc0;
|
|
}
|
|
|
|
static void expamem_next (addrbank *mapped, addrbank *next);
|
|
|
|
static void call_card_init(int index)
|
|
{
|
|
addrbank *ab, *abe;
|
|
bool ok = false;
|
|
card_data *cd = cards[ecard];
|
|
struct autoconfig_info *aci = &cd->aci;
|
|
|
|
expamem_bank.name = cd->name ? cd->name : _T("None");
|
|
aci->prefs = &currprefs;
|
|
aci->doinit = true;
|
|
aci->devnum = (cd->flags >> 16) & 255;
|
|
aci->ert = cd->ert;
|
|
aci->rc = cd->rc;
|
|
aci->zorro = cd->zorro;
|
|
memset(aci->autoconfig_raw, 0xff, sizeof aci->autoconfig_raw);
|
|
if (cd->initnum) {
|
|
ok = cd->initnum(aci);
|
|
} else {
|
|
ok = cd->initrc(aci);
|
|
}
|
|
if (ok) {
|
|
ab = NULL;
|
|
if (!cd->map)
|
|
ab = aci->addrbankp;
|
|
} else {
|
|
write_log(_T("Card %d: skipping autoconfig (init failed)\n"), ecard);
|
|
expamem_next(NULL, NULL);
|
|
return;
|
|
}
|
|
if (ab == &expamem_null || cd->zorro < 1 || cd->zorro > 3 || aci->zorro < 0) {
|
|
write_log(_T("Card %d: skipping autoconfig (not autoconfig)\n"), ecard);
|
|
expamem_next(NULL, NULL);
|
|
return;
|
|
}
|
|
|
|
expamem_board_pointer = cd->base;
|
|
expamem_board_size = cd->size;
|
|
|
|
abe = ab;
|
|
if (!abe)
|
|
abe = &expamem_bank;
|
|
expamem_autoconfig_mode = 0;
|
|
if (abe != &expamem_bank) {
|
|
for (int i = 0; i < 16 * 4; i++) {
|
|
expamem[i] = abe->sub_banks ? abe->sub_banks[0].bank->bget(i) : abe->bget(i);
|
|
}
|
|
}
|
|
|
|
if (ab) {
|
|
// non-NULL: not using expamem_bank
|
|
expamem_bank_current = ab;
|
|
if ((cd->flags & CARD_FLAG_CAN_Z3) && currprefs.cs_z3autoconfig && !currprefs.address_space_24) {
|
|
map_banks(&expamemz3_bank, AUTOCONFIG_Z3 >> 16, 1, 0);
|
|
map_banks(&dummy_bank, 0xE8, 1, 0);
|
|
} else {
|
|
map_banks(&expamem_bank, 0xE8, 1, 0);
|
|
if (!currprefs.address_space_24)
|
|
map_banks(&dummy_bank, AUTOCONFIG_Z3 >> 16, 1, 0);
|
|
}
|
|
} else {
|
|
if ((cd->flags & CARD_FLAG_CAN_Z3) && currprefs.cs_z3autoconfig && !currprefs.address_space_24) {
|
|
map_banks(&expamemz3_bank, AUTOCONFIG_Z3 >> 16, 1, 0);
|
|
map_banks(&dummy_bank, 0xE8, 1, 0);
|
|
expamem_bank_current = &expamem_bank;
|
|
} else {
|
|
map_banks(&expamem_bank, 0xE8, 1, 0);
|
|
if (!currprefs.address_space_24)
|
|
map_banks(&dummy_bank, AUTOCONFIG_Z3 >> 16, 1, 0);
|
|
expamem_bank_current = NULL;
|
|
}
|
|
}
|
|
}
|
|
|
|
static void boardmessage(addrbank *mapped, bool success)
|
|
{
|
|
uae_u8 type = expamem_read(0);
|
|
int size = expamem_board_size;
|
|
TCHAR sizemod = 'K';
|
|
|
|
size /= 1024;
|
|
if (size > 8 * 1024) {
|
|
sizemod = 'M';
|
|
size /= 1024;
|
|
}
|
|
write_log (_T("Card %d: Z%d 0x%08x %4d%c %s %s%s\n"),
|
|
ecard + 1, (type & 0xc0) == zorroII ? 2 : ((type & 0xc0) == zorroIII ? 3 : 1),
|
|
expamem_board_pointer, size, sizemod,
|
|
type & rom_card ? _T("ROM") : (type & add_memory ? _T("RAM") : _T("IO ")),
|
|
mapped->name,
|
|
success ? _T("") : _T(" [SHUT UP]"));
|
|
}
|
|
|
|
static void expamem_next(addrbank *mapped, addrbank *next)
|
|
{
|
|
if (mapped)
|
|
boardmessage(mapped, mapped->start != 0xffffffff);
|
|
|
|
expamem_init_clear();
|
|
expamem_init_clear_zero();
|
|
for (;;) {
|
|
++ecard;
|
|
if (ecard >= cardno)
|
|
break;
|
|
struct card_data *ec = cards[ecard];
|
|
if (ec->zorro == 3 && ec->base == 0xffffffff) {
|
|
write_log(_T("Autoconfig chain enumeration aborted, 32-bit address space overflow.\n"));
|
|
ecard = cardno;
|
|
break;
|
|
}
|
|
if (ec->initrc && isnonautoconfig(ec->zorro)) {
|
|
struct autoconfig_info aci = { 0 };
|
|
aci.doinit = true;
|
|
aci.prefs = &currprefs;
|
|
aci.rc = cards[ecard]->rc;
|
|
ec->initrc(&aci);
|
|
} else {
|
|
call_card_init(ecard);
|
|
break;
|
|
}
|
|
}
|
|
if (ecard >= cardno) {
|
|
expamem_init_clear2();
|
|
expamem_init_last();
|
|
}
|
|
}
|
|
|
|
static void expamemz3_map(void)
|
|
{
|
|
uaecptr addr = ((expamem_hi << 8) | expamem_lo) << 16;
|
|
if (!expamem_z3hack(&currprefs)) {
|
|
expamem_board_pointer = addr;
|
|
} else {
|
|
if (addr != expamem_board_pointer) {
|
|
put_word (regs.regs[11] + 0x20, expamem_board_pointer >> 16);
|
|
put_word (regs.regs[11] + 0x28, expamem_board_pointer >> 16);
|
|
}
|
|
}
|
|
}
|
|
|
|
static uae_u32 REGPARAM2 expamem_lget (uaecptr addr)
|
|
{
|
|
if (expamem_bank_current && expamem_bank_current != &expamem_bank) {
|
|
if (expamem_autoconfig_mode && (addr & 0xffff) < AUTOMATIC_AUTOCONFIG_MAX_ADDRESS) {
|
|
return (expamem_wget(addr) << 16) | expamem_wget(addr + 2);
|
|
}
|
|
return expamem_bank_current->sub_banks ? expamem_bank_current->sub_banks[0].bank->lget(addr) : expamem_bank_current->lget(addr);
|
|
}
|
|
write_log (_T("warning: Z2 READ.L from address $%08x PC=%x\n"), addr, M68K_GETPC);
|
|
return (expamem_wget (addr) << 16) | expamem_wget (addr + 2);
|
|
}
|
|
|
|
static uae_u32 REGPARAM2 expamem_wget (uaecptr addr)
|
|
{
|
|
if (expamem_bank_current && expamem_bank_current != &expamem_bank) {
|
|
if (expamem_autoconfig_mode && (addr & 0xffff) < AUTOMATIC_AUTOCONFIG_MAX_ADDRESS) {
|
|
return (expamem_bget(addr) << 8) | expamem_bget(addr + 1);
|
|
}
|
|
return expamem_bank_current->sub_banks ? expamem_bank_current->sub_banks[0].bank->wget(addr) : expamem_bank_current->wget(addr);
|
|
}
|
|
if (expamem_type() != zorroIII) {
|
|
if (expamem_bank_current && expamem_bank_current != &expamem_bank)
|
|
return expamem_bank_current->bget(addr) << 8;
|
|
}
|
|
uae_u32 v = (expamem_bget (addr) << 8) | expamem_bget (addr + 1);
|
|
write_log (_T("warning: READ.W from address $%08x=%04x PC=%x\n"), addr, v & 0xffff, M68K_GETPC);
|
|
return v;
|
|
}
|
|
|
|
static uae_u32 REGPARAM2 expamem_bget (uaecptr addr)
|
|
{
|
|
uae_u8 b;
|
|
if (!chipdone) {
|
|
chipdone = true;
|
|
addextrachip (get_long (4));
|
|
}
|
|
if (expamem_bank_current && expamem_bank_current != &expamem_bank) {
|
|
if (expamem_autoconfig_mode && (addr & 0xffff) < AUTOMATIC_AUTOCONFIG_MAX_ADDRESS) {
|
|
return expamem[addr & 0xffff];
|
|
}
|
|
return expamem_bank_current->sub_banks ? expamem_bank_current->sub_banks[0].bank->bget(addr) : expamem_bank_current->bget(addr);
|
|
}
|
|
addr &= 0xFFFF;
|
|
b = expamem[addr];
|
|
return b;
|
|
}
|
|
|
|
static void REGPARAM2 expamem_lput (uaecptr addr, uae_u32 value)
|
|
{
|
|
if (expamem_bank_current && expamem_bank_current != &expamem_bank) {
|
|
if (expamem_autoconfig_mode && (addr & 0xffff) < AUTOMATIC_AUTOCONFIG_MAX_ADDRESS) {
|
|
return;
|
|
}
|
|
expamem_bank_current->sub_banks ? expamem_bank_current->sub_banks[0].bank->lput(addr, value) : expamem_bank_current->lput(addr, value);
|
|
return;
|
|
}
|
|
write_log (_T("warning: Z2 WRITE.L to address $%08x : value $%08x\n"), addr, value);
|
|
}
|
|
|
|
static void REGPARAM2 expamem_wput (uaecptr addr, uae_u32 value)
|
|
{
|
|
value &= 0xffff;
|
|
if (ecard >= cardno)
|
|
return;
|
|
card_data *cd = cards[ecard];
|
|
if (!expamem_map)
|
|
expamem_map = cd->map;
|
|
if (expamem_type () != zorroIII) {
|
|
write_log (_T("warning: WRITE.W to address $%08x : value $%x PC=%08x\n"), addr, value, M68K_GETPC);
|
|
}
|
|
switch (addr & 0xff) {
|
|
case 0x48:
|
|
// A2630 boot rom writes WORDs to Z2 boards!
|
|
if (expamem_type() == zorroII) {
|
|
expamem_lo = 0;
|
|
expamem_hi = (value >> 8) & 0xff;
|
|
expamem_board_pointer = (expamem_hi | (expamem_lo >> 4)) << 16;
|
|
if (expamem_map) {
|
|
expamem_next(expamem_map(&cd->aci), NULL);
|
|
return;
|
|
}
|
|
if (expamem_autoconfig_mode) {
|
|
map_banks_z2(cd->aci.addrbankp, expamem_board_pointer >> 16, expamem_board_size >> 16);
|
|
cd->initrc(&cd->aci);
|
|
expamem_next(cd->aci.addrbankp, NULL);
|
|
return;
|
|
}
|
|
if (expamem_bank_current && expamem_bank_current != &expamem_bank) {
|
|
expamem_bank_current->sub_banks ? expamem_bank_current->sub_banks[0].bank->bput(addr, value >> 8) : expamem_bank_current->bput(addr, value >> 8);
|
|
return;
|
|
}
|
|
}
|
|
// Z3 = do nothing
|
|
break;
|
|
case 0x44:
|
|
if (expamem_type() == zorroIII) {
|
|
expamem_hi = (value & 0xff00) >> 8;
|
|
expamem_lo = value & 0x00ff;
|
|
expamemz3_map();
|
|
}
|
|
if (expamem_map) {
|
|
expamem_next(expamem_map(&cd->aci), NULL);
|
|
return;
|
|
}
|
|
if (expamem_autoconfig_mode) {
|
|
map_banks_z3(cd->aci.addrbankp, expamem_board_pointer >> 16, expamem_board_size >> 16);
|
|
cd->initrc(&cd->aci);
|
|
expamem_next(cd->aci.addrbankp, NULL);
|
|
return;
|
|
}
|
|
break;
|
|
case 0x4c:
|
|
if (expamem_map) {
|
|
expamem_next (NULL, NULL);
|
|
return;
|
|
}
|
|
break;
|
|
}
|
|
if (expamem_bank_current && expamem_bank_current != &expamem_bank) {
|
|
expamem_bank_current->sub_banks ? expamem_bank_current->sub_banks[0].bank->wput(addr, value) : expamem_bank_current->wput(addr, value);
|
|
}
|
|
}
|
|
|
|
static void REGPARAM2 expamem_bput (uaecptr addr, uae_u32 value)
|
|
{
|
|
value &= 0xff;
|
|
if (ecard >= cardno)
|
|
return;
|
|
card_data *cd = cards[ecard];
|
|
if (!expamem_map)
|
|
expamem_map = cd->map;
|
|
if (expamem_type() == protoautoconfig) {
|
|
switch (addr & 0xff) {
|
|
case 0x22:
|
|
expamem_hi = value & 0x7f;
|
|
expamem_board_pointer = AUTOCONFIG_Z2 | (expamem_hi * 4096);
|
|
if (expamem_map) {
|
|
expamem_next(expamem_map(&cd->aci), NULL);
|
|
return;
|
|
}
|
|
break;
|
|
}
|
|
} else {
|
|
switch (addr & 0xff) {
|
|
case 0x48:
|
|
if (expamem_type () == zorroII) {
|
|
expamem_hi = value & 0xff;
|
|
expamem_board_pointer = (expamem_hi | (expamem_lo >> 4)) << 16;
|
|
if (expamem_map) {
|
|
expamem_next(expamem_map(&cd->aci), NULL);
|
|
return;
|
|
}
|
|
if (expamem_autoconfig_mode) {
|
|
map_banks_z2(cd->aci.addrbankp, expamem_board_pointer >> 16, expamem_board_size >> 16);
|
|
cd->initrc(&cd->aci);
|
|
expamem_next(cd->aci.addrbankp, NULL);
|
|
return;
|
|
}
|
|
} else {
|
|
expamem_lo = value & 0xff;
|
|
}
|
|
break;
|
|
case 0x44:
|
|
if (expamem_type() == zorroIII) {
|
|
expamem_hi = value & 0xff;
|
|
expamemz3_map();
|
|
if (expamem_map) {
|
|
expamem_next(expamem_map(&cd->aci), NULL);
|
|
return;
|
|
}
|
|
if (expamem_autoconfig_mode) {
|
|
map_banks_z3(cd->aci.addrbankp, expamem_board_pointer >> 16, expamem_board_size >> 16);
|
|
cd->initrc(&cd->aci);
|
|
expamem_next(cd->aci.addrbankp, NULL);
|
|
return;
|
|
}
|
|
}
|
|
break;
|
|
case 0x4a:
|
|
if (expamem_type () == zorroII) {
|
|
expamem_lo = value & 0xff;
|
|
}
|
|
if (expamem_autoconfig_mode)
|
|
return;
|
|
break;
|
|
|
|
case 0x4c:
|
|
if (expamem_map) {
|
|
expamem_hi = expamem_lo = 0xff;
|
|
expamem_board_pointer = 0xffffffff;
|
|
addrbank *ab = expamem_map(&cd->aci);
|
|
if (ab)
|
|
ab->start = 0xffffffff;
|
|
expamem_next(ab, NULL);
|
|
return;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
if (expamem_bank_current && expamem_bank_current != &expamem_bank) {
|
|
expamem_bank_current->sub_banks ? expamem_bank_current->sub_banks[0].bank->bput(addr, value) : expamem_bank_current->bput(addr, value);
|
|
}
|
|
}
|
|
|
|
static uae_u32 REGPARAM2 expamemz3_bget (uaecptr addr)
|
|
{
|
|
int reg = addr & 0xff;
|
|
if (!expamem_bank_current)
|
|
return 0;
|
|
if (addr & 0x100)
|
|
reg += 2;
|
|
return expamem_bank_current->bget(reg + 0);
|
|
}
|
|
|
|
static uae_u32 REGPARAM2 expamemz3_wget (uaecptr addr)
|
|
{
|
|
uae_u32 v = (expamemz3_bget (addr) << 8) | expamemz3_bget (addr + 1);
|
|
write_log (_T("warning: Z3 READ.W from address $%08x=%04x PC=%x\n"), addr, v & 0xffff, M68K_GETPC);
|
|
return v;
|
|
}
|
|
|
|
static uae_u32 REGPARAM2 expamemz3_lget (uaecptr addr)
|
|
{
|
|
write_log (_T("warning: Z3 READ.L from address $%08x PC=%x\n"), addr, M68K_GETPC);
|
|
return (expamemz3_wget (addr) << 16) | expamemz3_wget (addr + 2);
|
|
}
|
|
|
|
static void REGPARAM2 expamemz3_bput (uaecptr addr, uae_u32 value)
|
|
{
|
|
int reg = addr & 0xff;
|
|
if (!expamem_bank_current)
|
|
return;
|
|
if (addr & 0x100)
|
|
reg += 2;
|
|
if (reg == 0x48) {
|
|
if (expamem_type() == zorroII) {
|
|
expamem_hi = value & 0xff;
|
|
expamem_board_pointer = (expamem_hi | (expamem_lo >> 4)) << 16;
|
|
} else {
|
|
expamem_lo = value & 0xff;
|
|
}
|
|
} else if (reg == 0x44) {
|
|
if (expamem_type() == zorroIII) {
|
|
expamem_hi = value & 0xff;
|
|
expamemz3_map();
|
|
}
|
|
} else if (reg == 0x4a) {
|
|
if (expamem_type() == zorroII)
|
|
expamem_lo = value & 0xff;
|
|
}
|
|
expamem_bank_current->bput(reg, value);
|
|
}
|
|
|
|
static void REGPARAM2 expamemz3_wput (uaecptr addr, uae_u32 value)
|
|
{
|
|
int reg = addr & 0xff;
|
|
if (!expamem_bank_current)
|
|
return;
|
|
if (addr & 0x100)
|
|
reg += 2;
|
|
if (reg == 0x44) {
|
|
if (expamem_type() == zorroIII) {
|
|
expamem_hi = (value & 0xff00) >> 8;
|
|
expamem_lo = value & 0x00ff;
|
|
expamemz3_map();
|
|
}
|
|
}
|
|
expamem_bank_current->wput(reg, value);
|
|
}
|
|
static void REGPARAM2 expamemz3_lput (uaecptr addr, uae_u32 value)
|
|
{
|
|
write_log (_T("warning: Z3 WRITE.L to address $%08x : value $%08x\n"), addr, value);
|
|
}
|
|
|
|
#ifdef CD32
|
|
|
|
static bool expamem_init_cd32fmv (struct autoconfig_info *aci)
|
|
{
|
|
expamem_init_clear ();
|
|
load_rom_rc(aci->rc, ROMTYPE_CD32CART, 262144, 0, expamem, 128, 0);
|
|
memcpy(aci->autoconfig_raw, expamem, sizeof aci->autoconfig_raw);
|
|
expamem_map = cd32_fmv_init;
|
|
return true;
|
|
}
|
|
|
|
#endif
|
|
|
|
/* ********************************************************** */
|
|
|
|
/*
|
|
* Fast Memory
|
|
*/
|
|
|
|
MEMORY_ARRAY_FUNCTIONS(fastmem, 0);
|
|
|
|
addrbank fastmem_bank[MAX_RAM_BOARDS] =
|
|
{
|
|
{
|
|
fastmem0_lget, fastmem0_wget, fastmem0_bget,
|
|
fastmem0_lput, fastmem0_wput, fastmem0_bput,
|
|
fastmem0_xlate, fastmem0_check, NULL, _T("*"), _T("Fast memory"),
|
|
fastmem0_wget,
|
|
ABFLAG_RAM | ABFLAG_THREADSAFE, 0, 0
|
|
}
|
|
};
|
|
|
|
#ifdef FILESYS
|
|
|
|
/*
|
|
* Filesystem device ROM/RAM space
|
|
*/
|
|
|
|
DECLARE_MEMORY_FUNCTIONS(filesys);
|
|
addrbank filesys_bank = {
|
|
filesys_lget, filesys_wget, filesys_bget,
|
|
filesys_lput, filesys_wput, filesys_bput,
|
|
filesys_xlate, filesys_check, NULL, _T("*"), _T("Filesystem autoconfig"),
|
|
filesys_wget,
|
|
ABFLAG_IO | ABFLAG_SAFE, S_READ, S_WRITE
|
|
};
|
|
|
|
static bool filesys_write(uaecptr addr)
|
|
{
|
|
return addr >= 0x4000;
|
|
}
|
|
|
|
static uae_u32 REGPARAM2 filesys_lget (uaecptr addr)
|
|
{
|
|
uae_u8 *m;
|
|
addr -= filesys_bank.start;
|
|
addr &= 65535;
|
|
m = filesys_bank.baseaddr + addr;
|
|
return do_get_mem_long ((uae_u32 *)m);
|
|
}
|
|
|
|
static uae_u32 REGPARAM2 filesys_wget (uaecptr addr)
|
|
{
|
|
uae_u8 *m;
|
|
addr -= filesys_bank.start;
|
|
addr &= 65535;
|
|
m = filesys_bank.baseaddr + addr;
|
|
return do_get_mem_word ((uae_u16 *)m);
|
|
}
|
|
|
|
static uae_u32 REGPARAM2 filesys_bget (uaecptr addr)
|
|
{
|
|
addr -= filesys_bank.start;
|
|
addr &= 65535;
|
|
return filesys_bank.baseaddr[addr];
|
|
}
|
|
|
|
static void REGPARAM2 filesys_bput(uaecptr addr, uae_u32 b)
|
|
{
|
|
addr -= filesys_bank.start;
|
|
addr &= 65535;
|
|
if (!filesys_write(addr))
|
|
return;
|
|
filesys_bank.baseaddr[addr] = b;
|
|
}
|
|
|
|
static void REGPARAM2 filesys_lput (uaecptr addr, uae_u32 l)
|
|
{
|
|
addr -= filesys_bank.start;
|
|
addr &= 65535;
|
|
if (!filesys_write(addr))
|
|
return;
|
|
filesys_bank.baseaddr[addr + 0] = l >> 24;
|
|
filesys_bank.baseaddr[addr + 1] = l >> 16;
|
|
filesys_bank.baseaddr[addr + 2] = l >> 8;
|
|
filesys_bank.baseaddr[addr + 3] = l >> 0;
|
|
}
|
|
|
|
static void REGPARAM2 filesys_wput (uaecptr addr, uae_u32 w)
|
|
{
|
|
addr -= filesys_bank.start;
|
|
addr &= 65535;
|
|
if (!filesys_write(addr))
|
|
return;
|
|
filesys_bank.baseaddr[addr + 0] = w >> 8;
|
|
filesys_bank.baseaddr[addr + 1] = w & 0xff;
|
|
}
|
|
|
|
static int REGPARAM2 filesys_check(uaecptr addr, uae_u32 size)
|
|
{
|
|
addr -= filesys_bank.start;
|
|
addr &= 65535;
|
|
return (addr + size) <= filesys_bank.allocated_size;
|
|
}
|
|
static uae_u8 *REGPARAM2 filesys_xlate(uaecptr addr)
|
|
{
|
|
addr -= filesys_bank.start;
|
|
addr &= 65535;
|
|
return filesys_bank.baseaddr + addr;
|
|
}
|
|
|
|
#endif /* FILESYS */
|
|
|
|
DECLARE_MEMORY_FUNCTIONS(uaeboard);
|
|
addrbank uaeboard_bank = {
|
|
uaeboard_lget, uaeboard_wget, uaeboard_bget,
|
|
uaeboard_lput, uaeboard_wput, uaeboard_bput,
|
|
uaeboard_xlate, uaeboard_check, NULL, _T("*"), _T("UAE Board"),
|
|
dummy_wgeti,
|
|
ABFLAG_IO | ABFLAG_SAFE, S_READ, S_WRITE
|
|
};
|
|
|
|
static uae_u32 uaeboard_base; /* Determined by the OS */
|
|
#define UAEBOARD_WRITEOFFSET 0x4000
|
|
|
|
static bool uaeboard_write(uaecptr addr)
|
|
{
|
|
if (addr >= UAEBOARD_WRITEOFFSET)
|
|
return true;
|
|
return false;
|
|
}
|
|
|
|
static uae_u32 REGPARAM2 uaeboard_wget(uaecptr addr)
|
|
{
|
|
uae_u8 *m;
|
|
addr -= uaeboard_base & 65535;
|
|
addr &= 65535;
|
|
m = uaeboard_bank.baseaddr + addr;
|
|
uae_u16 v = do_get_mem_word((uae_u16 *)m);
|
|
return v;
|
|
}
|
|
|
|
static uae_u32 REGPARAM2 uaeboard_lget(uaecptr addr)
|
|
{
|
|
addr -= uaeboard_base & 65535;
|
|
addr &= 65535;
|
|
uae_u32 v = uaeboard_wget(addr) << 16;
|
|
v |= uaeboard_wget(addr + 2);
|
|
return v;
|
|
}
|
|
|
|
static uae_u32 REGPARAM2 uaeboard_bget(uaecptr addr)
|
|
{
|
|
addr -= uaeboard_base & 65535;
|
|
addr &= 65535;
|
|
return uaeboard_bank.baseaddr[addr];
|
|
}
|
|
|
|
static void REGPARAM2 uaeboard_wput(uaecptr addr, uae_u32 w)
|
|
{
|
|
addr -= uaeboard_base & 65535;
|
|
addr &= 65535;
|
|
if (!uaeboard_write(addr))
|
|
return;
|
|
uae_u8 *m = uaeboard_bank.baseaddr + addr;
|
|
put_word_host(m, w);
|
|
}
|
|
|
|
static void REGPARAM2 uaeboard_lput(uaecptr addr, uae_u32 l)
|
|
{
|
|
addr -= uaeboard_base & 65535;
|
|
addr &= 65535;
|
|
if (!uaeboard_write(addr))
|
|
return;
|
|
uaeboard_wput(addr, l >> 16);
|
|
uaeboard_wput(addr + 2, l);
|
|
}
|
|
|
|
static void REGPARAM2 uaeboard_bput(uaecptr addr, uae_u32 b)
|
|
{
|
|
addr -= uaeboard_base & 65535;
|
|
addr &= 65535;
|
|
if (!uaeboard_write(addr))
|
|
return;
|
|
uaeboard_bank.baseaddr[addr] = b;
|
|
}
|
|
|
|
static int REGPARAM2 uaeboard_check(uaecptr addr, uae_u32 size)
|
|
{
|
|
addr -= uaeboard_base & 65535;
|
|
addr &= 65535;
|
|
return (addr + size) <= uaeboard_bank.allocated_size;
|
|
}
|
|
static uae_u8 *REGPARAM2 uaeboard_xlate(uaecptr addr)
|
|
{
|
|
addr -= uaeboard_base & 65535;
|
|
addr &= 65535;
|
|
return uaeboard_bank.baseaddr + addr;
|
|
}
|
|
|
|
static addrbank *expamem_map_uaeboard(struct autoconfig_info *aci)
|
|
{
|
|
uaeboard_base = expamem_board_pointer;
|
|
uaeboard_bank.start = uaeboard_base;
|
|
map_banks_z2(&uaeboard_bank, uaeboard_base >> 16, 1);
|
|
return &uaeboard_bank;
|
|
}
|
|
|
|
static bool get_params_filesys(struct uae_prefs *prefs, struct expansion_params *p)
|
|
{
|
|
p->device_order = prefs->uaeboard_order;
|
|
return true;
|
|
}
|
|
|
|
static void add_rtarea_pointer(struct autoconfig_info *aci)
|
|
{
|
|
if (aci->doinit) {
|
|
uaecptr addr = 0;
|
|
if (aci->prefs->uaeboard == 1) {
|
|
addr = rtarea_base;
|
|
}
|
|
if (addr) {
|
|
expamem[0x48] = addr >> 24;
|
|
expamem[0x49] = addr >> 16;
|
|
expamem[0x4a] = addr >> 8;
|
|
expamem[0x4b] = addr >> 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
static bool expamem_init_uaeboard(struct autoconfig_info *aci)
|
|
{
|
|
bool ks12 = ks12orolder();
|
|
struct uae_prefs *p = aci->prefs;
|
|
|
|
aci->label = _T("UAE Boot ROM");
|
|
aci->addrbankp = &uaeboard_bank;
|
|
aci->get_params = get_params_filesys;
|
|
|
|
expamem_init_clear();
|
|
expamem_write(0x00, Z2_MEM_64KB | zorroII);
|
|
|
|
expamem_write(0x08, no_shutup);
|
|
|
|
expamem_write(0x04, 1);
|
|
expamem_write(0x10, 6502 >> 8);
|
|
expamem_write(0x14, 6502 & 0xff);
|
|
|
|
expamem_write(0x18, 0x00); /* ser.no. Byte 0 */
|
|
expamem_write(0x1c, 0x00); /* ser.no. Byte 1 */
|
|
expamem_write(0x20, p->uaeboard); /* ser.no. Byte 2 */
|
|
expamem_write(0x24, 0x03); /* ser.no. Byte 3 */
|
|
|
|
uae_u8 *ptr = uaeboard_bank.baseaddr;
|
|
|
|
add_rtarea_pointer(aci);
|
|
|
|
expamem_write(0x28, 0x00); /* ROM-Offset hi */
|
|
expamem_write(0x2c, 0x00); /* ROM-Offset lo */
|
|
|
|
memcpy(aci->autoconfig_raw, expamem, sizeof aci->autoconfig_raw);
|
|
|
|
if (!aci->doinit)
|
|
return true;
|
|
|
|
memcpy(ptr, expamem, 0x100);
|
|
|
|
return true;
|
|
}
|
|
|
|
/*
|
|
* Z3fastmem Memory
|
|
*/
|
|
|
|
MEMORY_ARRAY_FUNCTIONS(z3fastmem, 0);
|
|
|
|
addrbank z3fastmem_bank[MAX_RAM_BOARDS] =
|
|
{
|
|
{
|
|
z3fastmem0_lget, z3fastmem0_wget, z3fastmem0_bget,
|
|
z3fastmem0_lput, z3fastmem0_wput, z3fastmem0_bput,
|
|
z3fastmem0_xlate, z3fastmem0_check, NULL, _T("*"), _T("Zorro III Fast RAM"),
|
|
z3fastmem0_wget,
|
|
ABFLAG_RAM | ABFLAG_THREADSAFE, 0, 0
|
|
}
|
|
};
|
|
|
|
/* ********************************************************** */
|
|
|
|
/*
|
|
* Expansion Card (ZORRO II) for 64/128/256/512KB 1/2/4/8MB of Fast Memory
|
|
*/
|
|
|
|
static addrbank *expamem_map_fastcard(struct autoconfig_info *aci)
|
|
{
|
|
int devnum = aci->devnum;
|
|
uae_u32 start = ((expamem_hi | (expamem_lo >> 4)) << 16);
|
|
addrbank *ab = &fastmem_bank[devnum];
|
|
if (start == 0x00ff0000)
|
|
return ab;
|
|
uae_u32 size = ab->allocated_size;
|
|
ab->start = start;
|
|
if (ab->start && size) {
|
|
map_banks_z2 (ab, ab->start >> 16, size >> 16);
|
|
}
|
|
return ab;
|
|
}
|
|
|
|
static bool fastmem_autoconfig(struct uae_prefs *p, struct autoconfig_info *aci, int zorro, uae_u8 type, uae_u32 serial, int allocated)
|
|
{
|
|
uae_u16 mid = 0;
|
|
uae_u8 pid;
|
|
uae_u8 flags = 0;
|
|
uae_u8 ac[16] = { 0 };
|
|
int boardnum = aci->devnum;
|
|
bool canforceac = false;
|
|
|
|
if (aci->ert) {
|
|
canforceac = true;
|
|
}
|
|
|
|
uae_u8 *forceac = NULL;
|
|
struct ramboard *rb = NULL;
|
|
|
|
if (!mid) {
|
|
if (zorro <= 2) {
|
|
rb = &p->fastmem[boardnum];
|
|
if (rb->autoconfig[0]) {
|
|
forceac = rb->autoconfig;
|
|
} else {
|
|
pid = 81;
|
|
}
|
|
} else {
|
|
int subsize = (allocated == 0x100000 ? Z3_SS_MEM_1MB
|
|
: allocated == 0x200000 ? Z3_SS_MEM_2MB
|
|
: allocated == 0x400000 ? Z3_SS_MEM_4MB
|
|
: allocated == 0x800000 ? Z3_SS_MEM_8MB
|
|
: Z3_SS_MEM_SAME);
|
|
rb = &p->z3fastmem[boardnum];
|
|
if (rb->autoconfig[0]) {
|
|
forceac = rb->autoconfig;
|
|
} else {
|
|
pid = 83;
|
|
}
|
|
flags |= care_addr | force_z3 | (allocated > 0x800000 ? ext_size : subsize);
|
|
}
|
|
} else if (canforceac) {
|
|
if (zorro <= 2) {
|
|
rb = &p->fastmem[boardnum];
|
|
} else if (zorro == 3) {
|
|
rb = &p->z3fastmem[boardnum];
|
|
}
|
|
if (rb && rb->autoconfig[0]) {
|
|
forceac = rb->autoconfig;
|
|
}
|
|
}
|
|
if (!mid) {
|
|
mid = uae_id;
|
|
serial = 1;
|
|
}
|
|
|
|
if (forceac) {
|
|
for (int i = 0; i < 16; i++) {
|
|
ac[i] = forceac[i];
|
|
ac[0] &= ~7;
|
|
ac[0] |= type & 7;
|
|
if (flags)
|
|
ac[0x08 / 4] = flags;
|
|
}
|
|
} else {
|
|
ac[0x00 / 4] = type;
|
|
ac[0x04 / 4] = pid;
|
|
ac[0x08 / 4] = flags;
|
|
ac[0x10 / 4] = mid >> 8;
|
|
ac[0x14 / 4] = (uae_u8)mid;
|
|
ac[0x18 / 4] = serial >> 24;
|
|
ac[0x1c / 4] = serial >> 16;
|
|
ac[0x20 / 4] = serial >> 8;
|
|
ac[0x24 / 4] = serial >> 0;
|
|
}
|
|
|
|
expamem_write(0x00, ac[0x00 / 4]);
|
|
expamem_write(0x04, ac[0x04 / 4]);
|
|
expamem_write(0x08, ac[0x08 / 4]);
|
|
expamem_write(0x10, ac[0x10 / 4]);
|
|
expamem_write(0x14, ac[0x14 / 4]);
|
|
|
|
expamem_write(0x18, ac[0x18 / 4]); /* ser.no. Byte 0 */
|
|
expamem_write(0x1c, ac[0x1c / 4]); /* ser.no. Byte 1 */
|
|
expamem_write(0x20, ac[0x20 / 4]); /* ser.no. Byte 2 */
|
|
expamem_write(0x24, ac[0x24 / 4]); /* ser.no. Byte 3 */
|
|
|
|
expamem_write (0x28, 0x00); /* ROM-Offset hi */
|
|
expamem_write (0x2c, 0x00); /* ROM-Offset lo */
|
|
|
|
expamem_write (0x40, 0x00); /* Ctrl/Statusreg.*/
|
|
|
|
return true;
|
|
}
|
|
|
|
static bool expamem_init_fastcard_2(struct autoconfig_info *aci, int zorro)
|
|
{
|
|
struct uae_prefs *p = aci->prefs;
|
|
addrbank *bank = &fastmem_bank[aci->devnum];
|
|
uae_u8 type = add_memory | zorroII;
|
|
int size = p->fastmem[aci->devnum].size;
|
|
|
|
aci->label = zorro == 1 ? _T("Z1 Fast RAM") : _T("Z2 Fast RAM");
|
|
aci->zorro = zorro;
|
|
|
|
expamem_init_clear ();
|
|
if (size == 65536)
|
|
type |= Z2_MEM_64KB;
|
|
else if (size == 131072)
|
|
type |= Z2_MEM_128KB;
|
|
else if (size == 262144)
|
|
type |= Z2_MEM_256KB;
|
|
else if (size == 524288)
|
|
type |= Z2_MEM_512KB;
|
|
else if (size == 0x100000)
|
|
type |= Z2_MEM_1MB;
|
|
else if (size == 0x200000)
|
|
type |= Z2_MEM_2MB;
|
|
else if (size == 0x400000)
|
|
type |= Z2_MEM_4MB;
|
|
else if (size == 0x800000)
|
|
type |= Z2_MEM_8MB;
|
|
|
|
aci->addrbankp = bank;
|
|
|
|
if (!fastmem_autoconfig(p, aci, BOARD_AUTOCONFIG_Z2, type, 1, size)) {
|
|
aci->zorro = -1;
|
|
}
|
|
|
|
memcpy(aci->autoconfig_raw, expamem, sizeof aci->autoconfig_raw);
|
|
|
|
return true;
|
|
}
|
|
|
|
static bool expamem_init_fastcard(struct autoconfig_info *aci)
|
|
{
|
|
return expamem_init_fastcard_2(aci, 2);
|
|
}
|
|
|
|
/* ********************************************************** */
|
|
|
|
#ifdef FILESYS
|
|
|
|
static bool expamem_rtarea_init(struct autoconfig_info *aci)
|
|
{
|
|
aci->start = rtarea_base;
|
|
aci->size = 65536;
|
|
aci->addrbankp = &rtarea_bank;
|
|
aci->label = _T("UAE Boot ROM");
|
|
return true;
|
|
}
|
|
|
|
/*
|
|
* Filesystem device
|
|
*/
|
|
|
|
static void expamem_map_filesys_update(void)
|
|
{
|
|
/* 68k code needs to know this. */
|
|
uaecptr a = here();
|
|
org(rtarea_base + RTAREA_FSBOARD);
|
|
dl(filesys_bank.start + 0x2000);
|
|
org(a);
|
|
}
|
|
|
|
static addrbank *expamem_map_filesys (struct autoconfig_info *aci)
|
|
{
|
|
mapped_free(&filesys_bank);
|
|
filesys_bank.start = expamem_board_pointer;
|
|
filesys_bank.mask = filesys_bank.reserved_size - 1;
|
|
if (expamem_board_pointer == 0xffffffff)
|
|
return &filesys_bank;
|
|
mapped_malloc(&filesys_bank);
|
|
memcpy (filesys_bank.baseaddr, expamem, 0x3000);
|
|
map_banks_z2(&filesys_bank, filesys_bank.start >> 16, 1);
|
|
expamem_map_filesys_update();
|
|
return &filesys_bank;
|
|
}
|
|
|
|
#if KS12_BOOT_HACK
|
|
static uaecptr ks12_resident;
|
|
static void set_ks12_boot_hack(void)
|
|
{
|
|
uaecptr old = here();
|
|
org(ks12_resident);
|
|
dw(ks12orolder() ? 0x4afc : 0x0000);
|
|
org(ks12_resident + 11);
|
|
db((uae_u8)kickstart_version);
|
|
org(old);
|
|
}
|
|
|
|
void create_ks12_boot(void)
|
|
{
|
|
// KS 1.2 boot resident
|
|
uaecptr name = ds(_T("UAE boot"));
|
|
align(2);
|
|
uaecptr code = here();
|
|
// allocate fake diagarea
|
|
dl(0x48e73f3e); // movem.l d2-d7/a2-a6,-(sp)
|
|
dw(0x203c); // move.l #x,d0
|
|
dl(0x0300);
|
|
dw(0x7201); // moveq #1,d1
|
|
dl(0x4eaeff3a); // jsr -0xc6(a6)
|
|
dw(0x2440); // move.l d0,a2 ;diag area
|
|
dw(0x9bcd); // sub.l a5,a5 ;expansionbase
|
|
dw(0x97cb); // sub.l a3,a3 ;configdev
|
|
dw(0x4eb9); // jsr
|
|
dl(ROM_filesys_diagentry);
|
|
dl(0x4cdf7cfc); // movem.l (sp)+,d2-d7/a2-a6
|
|
dw(0x4e75);
|
|
// struct Resident
|
|
ks12_resident = here();
|
|
dw(0x0000);
|
|
dl(ks12_resident);
|
|
dl(ks12_resident + 26);
|
|
db(1); // RTF_COLDSTART
|
|
db((uae_u8)kickstart_version); // version
|
|
db(0); // NT_UNKNOWN
|
|
db(1); // priority
|
|
dl(name);
|
|
dl(name);
|
|
dl(code);
|
|
set_ks12_boot_hack();
|
|
}
|
|
#endif
|
|
|
|
static bool expamem_init_filesys(struct autoconfig_info *aci)
|
|
{
|
|
bool ks12 = ks12orolder();
|
|
bool rom = !(ks12 || !do_mount);
|
|
|
|
if (aci) {
|
|
aci->label = ks12 ? _T("Pre-KS 1.3 UAE FS ROM") : _T("UAE FS ROM");
|
|
aci->get_params = get_params_filesys;
|
|
aci->addrbankp = &filesys_bank;
|
|
}
|
|
|
|
/* struct DiagArea - the size has to be large enough to store several device ROMTags */
|
|
const uae_u8 diagarea[] = {
|
|
0x90, 0x00, /* da_Config, da_Flags */
|
|
0x02, 0x00, /* da_Size */
|
|
FILESYS_DIAGPOINT >> 8, FILESYS_DIAGPOINT & 0xff,
|
|
FILESYS_BOOTPOINT >> 8, FILESYS_BOOTPOINT & 0xff,
|
|
0, (uae_u8)14, // Name offset
|
|
0, 0, 0, 0,
|
|
(uae_u8)('U'), (uae_u8)('A'), (uae_u8)('E'), 0
|
|
};
|
|
|
|
expamem_init_clear();
|
|
expamem_write (0x00, Z2_MEM_64KB | zorroII | (rom ? rom_card : 0));
|
|
|
|
expamem_write (0x08, no_shutup);
|
|
|
|
expamem_write (0x04, 82);
|
|
expamem_write (0x10, uae_id >> 8);
|
|
expamem_write (0x14, uae_id & 0xff);
|
|
|
|
expamem_write (0x18, 0x00); /* ser.no. Byte 0 */
|
|
expamem_write (0x1c, 0x00); /* ser.no. Byte 1 */
|
|
expamem_write (0x20, 0x00); /* ser.no. Byte 2 */
|
|
expamem_write (0x24, 0x03); /* ser.no. Byte 3 */
|
|
|
|
/* er_InitDiagVec */
|
|
expamem_write (0x28, rom ? 0x20 : 0x00); /* ROM-Offset hi */
|
|
expamem_write (0x2c, 0x00); /* ROM-Offset lo */
|
|
|
|
expamem_write (0x40, 0x00); /* Ctrl/Statusreg.*/
|
|
|
|
add_rtarea_pointer(aci);
|
|
|
|
if (aci && !aci->doinit) {
|
|
memcpy(aci->autoconfig_raw, expamem, sizeof aci->autoconfig_raw);
|
|
return true;
|
|
}
|
|
|
|
/* Build a DiagArea */
|
|
memcpy (expamem + FILESYS_DIAGAREA, diagarea, sizeof diagarea);
|
|
|
|
put_word_host(expamem + FILESYS_DIAGAREA + FILESYS_DIAGPOINT + 0,
|
|
0x7000 | 2); // MOVEQ #x,D0
|
|
/* Call hwtrap_install */
|
|
put_word_host(expamem + FILESYS_DIAGAREA + FILESYS_DIAGPOINT + 2, 0x4EB9); /* JSR */
|
|
put_long_host(expamem + FILESYS_DIAGAREA + FILESYS_DIAGPOINT + 4, filesys_get_entry(9));
|
|
/* Call DiagEntry */
|
|
put_word_host(expamem + FILESYS_DIAGAREA + FILESYS_DIAGPOINT + 8, 0x4EF9); /* JMP */
|
|
put_long_host(expamem + FILESYS_DIAGAREA + FILESYS_DIAGPOINT + 10, ROM_filesys_diagentry);
|
|
|
|
/* What comes next is a plain bootblock */
|
|
put_word_host(expamem + FILESYS_DIAGAREA + FILESYS_BOOTPOINT, 0x4EF9); /* JMP */
|
|
put_long_host(expamem + FILESYS_DIAGAREA + FILESYS_BOOTPOINT + 2, EXPANSION_bootcode);
|
|
|
|
set_ks12_boot_hack();
|
|
|
|
return true;
|
|
}
|
|
|
|
#endif
|
|
|
|
/*
|
|
* Zorro III expansion memory
|
|
*/
|
|
|
|
static addrbank *expamem_map_z3fastmem (struct autoconfig_info *aci)
|
|
{
|
|
int devnum = aci->devnum;
|
|
addrbank *ab = &z3fastmem_bank[devnum];
|
|
uaecptr z3fs = expamem_board_pointer;
|
|
uae_u32 size = currprefs.z3fastmem[devnum].size;
|
|
|
|
if (ab->allocated_size) {
|
|
map_banks_z3(ab, z3fs >> 16, size >> 16);
|
|
}
|
|
return ab;
|
|
}
|
|
|
|
static bool expamem_init_z3fastmem(struct autoconfig_info *aci)
|
|
{
|
|
addrbank *bank = &z3fastmem_bank[aci->devnum];
|
|
|
|
uae_u32 size = aci->prefs->z3fastmem[aci->devnum].size;
|
|
|
|
aci->label = _T("Z3 Fast RAM");
|
|
|
|
int code = (size == 0x100000 ? Z2_MEM_1MB
|
|
: size == 0x200000 ? Z2_MEM_2MB
|
|
: size == 0x400000 ? Z2_MEM_4MB
|
|
: size == 0x800000 ? Z2_MEM_8MB
|
|
: size == 0x1000000 ? Z3_MEM_16MB
|
|
: size == 0x2000000 ? Z3_MEM_32MB
|
|
: size == 0x4000000 ? Z3_MEM_64MB
|
|
: size == 0x8000000 ? Z3_MEM_128MB
|
|
: size == 0x10000000 ? Z3_MEM_256MB
|
|
: size == 0x20000000 ? Z3_MEM_512MB
|
|
: Z3_MEM_1GB);
|
|
|
|
if (size < 0x1000000)
|
|
code = Z3_MEM_16MB; /* Z3 physical board size is always at least 16M */
|
|
|
|
expamem_init_clear();
|
|
if (!fastmem_autoconfig(aci->prefs, aci, BOARD_AUTOCONFIG_Z3, add_memory | zorroIII | code, 1, size))
|
|
aci->zorro = -1;
|
|
|
|
memcpy(aci->autoconfig_raw, expamem, sizeof aci->autoconfig_raw);
|
|
aci->addrbankp = bank;
|
|
|
|
if (!aci->doinit)
|
|
return true;
|
|
|
|
uae_u32 start = bank->start;
|
|
bool alwaysmapz3 = aci->prefs->z3_mapping_mode != Z3MAPPING_REAL;
|
|
if ((alwaysmapz3 || expamem_z3hack(aci->prefs)) && bank->allocated_size) {
|
|
map_banks_z3(bank, start >> 16, size >> 16);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
#ifdef PICASSO96
|
|
/*
|
|
* Fake Graphics Card (ZORRO III) - BDK
|
|
*/
|
|
|
|
static addrbank *expamem_map_gfxcard_z3 (struct autoconfig_info *aci)
|
|
{
|
|
int devnum = aci->devnum;
|
|
gfxmem_banks[devnum]->start = expamem_board_pointer;
|
|
map_banks_z3(gfxmem_banks[devnum], gfxmem_banks[devnum]->start >> 16, gfxmem_banks[devnum]->allocated_size >> 16);
|
|
return gfxmem_banks[devnum];
|
|
}
|
|
|
|
static addrbank *expamem_map_gfxcard_z2 (struct autoconfig_info *aci)
|
|
{
|
|
int devnum = aci->devnum;
|
|
gfxmem_banks[devnum]->start = expamem_board_pointer;
|
|
map_banks_z2(gfxmem_banks[devnum], gfxmem_banks[devnum]->start >> 16, gfxmem_banks[devnum]->allocated_size >> 16);
|
|
return gfxmem_banks[devnum];
|
|
}
|
|
|
|
static bool expamem_init_gfxcard (struct autoconfig_info *aci, bool z3)
|
|
{
|
|
int devnum = aci->devnum;
|
|
struct uae_prefs *p = aci->prefs;
|
|
int size = p->rtgboards[devnum].rtgmem_size;
|
|
int code = (size == 0x100000 ? Z2_MEM_1MB
|
|
: size == 0x200000 ? Z2_MEM_2MB
|
|
: size == 0x400000 ? Z2_MEM_4MB
|
|
: size == 0x800000 ? Z2_MEM_8MB
|
|
: size == 0x1000000 ? Z3_MEM_16MB
|
|
: size == 0x2000000 ? Z3_MEM_32MB
|
|
: size == 0x4000000 ? Z3_MEM_64MB
|
|
: size == 0x8000000 ? Z3_MEM_128MB
|
|
: size == 0x10000000 ? Z3_MEM_256MB
|
|
: size == 0x20000000 ? Z3_MEM_512MB
|
|
: Z3_MEM_1GB);
|
|
int subsize = (size == 0x100000 ? Z3_SS_MEM_1MB
|
|
: size == 0x200000 ? Z3_SS_MEM_2MB
|
|
: size == 0x400000 ? Z3_SS_MEM_4MB
|
|
: size == 0x800000 ? Z3_SS_MEM_8MB
|
|
: Z3_SS_MEM_SAME);
|
|
|
|
aci->label = _T("UAE RTG");
|
|
aci->direct_vram = true;
|
|
|
|
if (size < 0x1000000 && z3)
|
|
code = Z3_MEM_16MB; /* Z3 physical board size is always at least 16M */
|
|
|
|
expamem_init_clear();
|
|
expamem_write (0x00, (z3 ? zorroIII : zorroII) | code);
|
|
|
|
expamem_write (0x08, care_addr | (z3 ? (force_z3 | (size > 0x800000 ? ext_size: subsize)) : 0));
|
|
expamem_write (0x04, 96);
|
|
|
|
expamem_write (0x10, uae_id >> 8);
|
|
expamem_write (0x14, uae_id & 0xff);
|
|
|
|
expamem_write (0x18, 0x00); /* ser.no. Byte 0 */
|
|
expamem_write (0x1c, 0x00); /* ser.no. Byte 1 */
|
|
expamem_write (0x20, 0x00); /* ser.no. Byte 2 */
|
|
expamem_write (0x24, 0x01); /* ser.no. Byte 3 */
|
|
|
|
expamem_write (0x28, 0x00); /* ROM-Offset hi */
|
|
expamem_write (0x2c, 0x00); /* ROM-Offset lo */
|
|
|
|
expamem_write (0x40, 0x00); /* Ctrl/Statusreg.*/
|
|
|
|
memcpy(aci->autoconfig_raw, expamem, sizeof aci->autoconfig_raw);
|
|
aci->addrbankp = gfxmem_banks[devnum];
|
|
return true;
|
|
}
|
|
static bool expamem_init_gfxcard_z3(struct autoconfig_info *aci)
|
|
{
|
|
return expamem_init_gfxcard (aci, true);
|
|
}
|
|
static bool expamem_init_gfxcard_z2 (struct autoconfig_info *aci)
|
|
{
|
|
return expamem_init_gfxcard (aci, false);
|
|
}
|
|
#endif
|
|
|
|
|
|
#ifdef SAVESTATE
|
|
static size_t fast_filepos[MAX_RAM_BOARDS], z3_filepos[MAX_RAM_BOARDS];
|
|
static size_t p96_filepos;
|
|
#endif
|
|
|
|
void free_fastmemory (int boardnum)
|
|
{
|
|
mapped_free (&fastmem_bank[boardnum]);
|
|
}
|
|
|
|
static bool mapped_malloc_dynamic (uae_u32 *currpsize, uae_u32 *changedpsize, addrbank *bank, int max, const TCHAR *label)
|
|
{
|
|
int alloc = *currpsize;
|
|
|
|
bank->allocated_size = 0;
|
|
bank->reserved_size = alloc;
|
|
bank->baseaddr = NULL;
|
|
bank->mask = 0;
|
|
|
|
if (!alloc)
|
|
return false;
|
|
|
|
bank->mask = alloc - 1;
|
|
bank->label = label ? label : _T("*");
|
|
if (mapped_malloc (bank)) {
|
|
*currpsize = alloc;
|
|
*changedpsize = alloc;
|
|
return true;
|
|
}
|
|
write_log (_T("Out of memory for %s, %d bytes.\n"), label ? label : _T("?"), alloc);
|
|
|
|
return false;
|
|
}
|
|
|
|
static void allocate_expamem (void)
|
|
{
|
|
for (int i = 0; i < MAX_RTG_BOARDS; i++) {
|
|
memcpy(&currprefs.rtgboards[i], &changed_prefs.rtgboards[i], sizeof(struct rtgboardconfig));
|
|
}
|
|
|
|
for (int i = 0; i < MAX_RAM_BOARDS; i++) {
|
|
currprefs.fastmem[i].size = changed_prefs.fastmem[i].size;
|
|
currprefs.z3fastmem[i].size = changed_prefs.z3fastmem[i].size;
|
|
}
|
|
|
|
for (int i = 0; i < MAX_RAM_BOARDS; i++) {
|
|
if (fastmem_bank[i].reserved_size != currprefs.fastmem[i].size) {
|
|
free_fastmemory (i);
|
|
|
|
if (fastmem_bank[i].start == 0xffffffff) {
|
|
fastmem_bank[i].reserved_size = 0;
|
|
} else {
|
|
fastmem_bank[i].reserved_size = currprefs.fastmem[i].size;
|
|
fastmem_bank[i].mask = fastmem_bank[i].reserved_size - 1;
|
|
if (fastmem_bank[i].reserved_size && fastmem_bank[i].start != 0xffffffff) {
|
|
mapped_malloc (&fastmem_bank[i]);
|
|
if (fastmem_bank[i].baseaddr == 0) {
|
|
write_log (_T("Out of memory for fastmem card.\n"));
|
|
}
|
|
}
|
|
}
|
|
memory_hardreset(1);
|
|
}
|
|
}
|
|
|
|
if (z3fastmem_bank[0].reserved_size != currprefs.z3fastmem[0].size) {
|
|
mapped_free (&z3fastmem_bank[0]);
|
|
mapped_malloc_dynamic (&currprefs.z3fastmem[0].size, &changed_prefs.z3fastmem[0].size, &z3fastmem_bank[0], 1, _T("*"));
|
|
memory_hardreset(1);
|
|
}
|
|
|
|
#ifdef PICASSO96
|
|
struct rtgboardconfig *rbc = &currprefs.rtgboards[0];
|
|
if (gfxmem_banks[0]->reserved_size != rbc->rtgmem_size) {
|
|
mapped_free (gfxmem_banks[0]);
|
|
mapped_malloc_dynamic (&rbc->rtgmem_size, &changed_prefs.rtgboards[0].rtgmem_size, gfxmem_banks[0], 1, NULL);
|
|
memory_hardreset(1);
|
|
}
|
|
#endif
|
|
|
|
#ifdef SAVESTATE
|
|
if (savestate_state == STATE_RESTORE) {
|
|
for (int i = 0; i < MAX_RAM_BOARDS; i++) {
|
|
if (fastmem_bank[i].allocated_size > 0) {
|
|
restore_ram (fast_filepos[i], fastmem_bank[i].baseaddr);
|
|
if (!fastmem_bank[i].start) {
|
|
// old statefile compatibility support
|
|
fastmem_bank[i].start = 0x00200000;
|
|
}
|
|
map_banks (&fastmem_bank[i], fastmem_bank[i].start >> 16, currprefs.fastmem[i].size >> 16,
|
|
fastmem_bank[i].allocated_size);
|
|
}
|
|
if (z3fastmem_bank[i].allocated_size > 0) {
|
|
restore_ram (z3_filepos[i], z3fastmem_bank[i].baseaddr);
|
|
map_banks (&z3fastmem_bank[i], z3fastmem_bank[i].start >> 16, currprefs.z3fastmem[i].size >> 16,
|
|
z3fastmem_bank[i].allocated_size);
|
|
}
|
|
}
|
|
#ifdef PICASSO96
|
|
if (gfxmem_banks[0]->allocated_size > 0 && gfxmem_banks[0]->start > 0) {
|
|
restore_ram (p96_filepos, gfxmem_banks[0]->baseaddr);
|
|
map_banks(gfxmem_banks[0], gfxmem_banks[0]->start >> 16, currprefs.rtgboards[0].rtgmem_size >> 16,
|
|
gfxmem_banks[0]->allocated_size);
|
|
}
|
|
#endif
|
|
}
|
|
#endif /* SAVESTATE */
|
|
}
|
|
|
|
static uaecptr check_boot_rom (struct uae_prefs *p, int *boot_rom_type)
|
|
{
|
|
uaecptr b = RTAREA_DEFAULT;
|
|
addrbank *ab;
|
|
|
|
*boot_rom_type = 0;
|
|
if (p->boot_rom == 1)
|
|
return 0;
|
|
*boot_rom_type = 1;
|
|
ab = &get_mem_bank (RTAREA_DEFAULT);
|
|
if (ab) {
|
|
if (valid_address (RTAREA_DEFAULT, 65536))
|
|
b = RTAREA_BACKUP;
|
|
}
|
|
if (nr_directory_units (NULL))
|
|
return b;
|
|
if (nr_directory_units (p))
|
|
return b;
|
|
if (p->socket_emu)
|
|
return b;
|
|
if (p->input_tablet > 0)
|
|
return b;
|
|
if (p->rtgboards[0].rtgmem_size)
|
|
return b;
|
|
if (p->chipmem_size > 2 * 1024 * 1024)
|
|
return b;
|
|
if (p->boot_rom >= 3)
|
|
return b;
|
|
if (p->boot_rom == 2 && b == 0xf00000) {
|
|
*boot_rom_type = -1;
|
|
return b;
|
|
}
|
|
*boot_rom_type = 0;
|
|
return 0;
|
|
}
|
|
|
|
uaecptr need_uae_boot_rom (struct uae_prefs *p)
|
|
{
|
|
uaecptr v;
|
|
|
|
uae_boot_rom_type = 0;
|
|
v = check_boot_rom (p, &uae_boot_rom_type);
|
|
if (!rtarea_base) {
|
|
uae_boot_rom_type = 0;
|
|
v = 0;
|
|
}
|
|
return v;
|
|
}
|
|
|
|
static void add_expansions(struct uae_prefs *p, int zorro, int *fastmem_nump, int mode)
|
|
{
|
|
int fastmem_num = MAX_RAM_BOARDS;
|
|
if (fastmem_nump)
|
|
fastmem_num = *fastmem_nump;
|
|
for (int i = 0; expansionroms[i].name; i++) {
|
|
const struct expansionromtype *ert = &expansionroms[i];
|
|
if (ert->zorro == zorro) {
|
|
for (int j = 0; j < MAX_DUPLICATE_EXPANSION_BOARDS; j++) {
|
|
struct romconfig *rc = get_device_romconfig(p, ert->romtype, j);
|
|
if (rc) {
|
|
if (mode == 2)
|
|
continue;
|
|
cards_set[cardno].flags = 0;
|
|
cards_set[cardno].name = ert->name;
|
|
cards_set[cardno].initrc = ert->init;
|
|
cards_set[cardno].rc = rc;
|
|
cards_set[cardno].zorro = zorro;
|
|
cards_set[cardno].ert = ert;
|
|
cards_set[cardno++].map = NULL;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (fastmem_nump)
|
|
*fastmem_nump = fastmem_num;
|
|
}
|
|
|
|
static uae_u8 autoconfig_read(const uae_u8 *autoconfig, int offset)
|
|
{
|
|
uae_u8 b = (autoconfig[offset] & 0xf0) | (autoconfig[offset + 2] >> 4);
|
|
if (offset == 0 || offset == 2 || offset == 0x40 || offset == 0x42)
|
|
return b;
|
|
b = ~b;
|
|
return b;
|
|
}
|
|
|
|
static void expansion_parse_autoconfig(struct card_data *cd, const uae_u8 *autoconfig)
|
|
{
|
|
uae_u8 code = autoconfig[0];
|
|
uae_u32 expamem_z3_size;
|
|
|
|
if ((code & 0xc0) == zorroII) {
|
|
int slotsize;
|
|
// Z2
|
|
cd->zorro = 2;
|
|
code &= 7;
|
|
if (code == 0)
|
|
expamem_board_size = 8 * 1024 * 1024;
|
|
else
|
|
expamem_board_size = 32768 << code;
|
|
slotsize = expamem_board_size / 65536;
|
|
|
|
expamem_board_pointer = 0xffffffff;
|
|
|
|
for (int slottype = 0; slottype < 2; slottype++)
|
|
{
|
|
uae_u8 *slots = slots_e8;
|
|
int numslots = sizeof slots_e8;
|
|
uaecptr slotaddr = AUTOCONFIG_Z2;
|
|
if (slotsize >= 8 || slottype > 0) {
|
|
slots = slots_20;
|
|
numslots = sizeof slots_20;
|
|
slotaddr = AUTOCONFIG_Z2_MEM;
|
|
}
|
|
for (int i = 0; i < numslots; i++) {
|
|
if (((slotsize - 1) & i) == 0) {
|
|
bool free = true;
|
|
for (int j = 0; j < slotsize && j + i < numslots; j++) {
|
|
if (slots[i + j] != 0) {
|
|
free = false;
|
|
break;
|
|
}
|
|
}
|
|
if (free) {
|
|
for (int j = 0; j < slotsize; j++) {
|
|
slots[i + j] = 1;
|
|
}
|
|
expamem_board_pointer = slotaddr + i * 65536;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if (expamem_board_pointer != 0xffffffff || slotsize >= 8)
|
|
break;
|
|
}
|
|
|
|
} else if ((code & 0xc0) == zorroIII) {
|
|
// Z3
|
|
|
|
cd->zorro = 3;
|
|
code &= 7;
|
|
if (autoconfig[2] & ext_size)
|
|
expamem_z3_size = (16 * 1024 * 1024) << code;
|
|
else
|
|
expamem_z3_size = 16 * 1024 * 1024;
|
|
|
|
uaecptr newp = (expamem_z3_pointer_real + expamem_z3_size - 1) & ~(expamem_z3_size - 1);
|
|
if (newp < expamem_z3_pointer_real)
|
|
newp = 0xffffffff;
|
|
expamem_z3_pointer_real = newp;
|
|
|
|
expamem_board_pointer = expamem_z3hack(cd->aci.prefs) ? expamem_z3_pointer_uae : expamem_z3_pointer_real;
|
|
expamem_board_size = expamem_z3_size;
|
|
|
|
} else if ((code & 0xc0) == 0x40) {
|
|
cd->zorro = 1;
|
|
// 0x40 = "Box without init/diagnostic code"
|
|
// proto autoconfig "box" size.
|
|
//expamem_z2_size = (1 << ((code >> 3) & 7)) * 4096;
|
|
// much easier this way, all old-style boards were made for
|
|
// A1000 and didn't have passthrough connector.
|
|
expamem_board_size = 65536;
|
|
expamem_board_pointer = 0xe90000;
|
|
}
|
|
|
|
}
|
|
|
|
static void reset_ac_data(struct uae_prefs *p)
|
|
{
|
|
expamem_z3_pointer_real = Z3BASE_REAL;
|
|
expamem_z3_pointer_uae = Z3BASE_UAE;
|
|
expamem_z3_highram_real = 0;
|
|
expamem_z3_highram_uae = 0;
|
|
|
|
if (p->mbresmem_high_size >= 128 * 1024 * 1024)
|
|
expamem_z3_pointer_uae += (p->mbresmem_high_size - 128 * 1024 * 1024) + 16 * 1024 * 1024;
|
|
expamem_board_pointer = 0;
|
|
expamem_board_size = 0;
|
|
memset(slots_20, 0, sizeof slots_20);
|
|
memset(slots_e8, 0, sizeof slots_e8);
|
|
slots_e8[0] = 1;
|
|
}
|
|
|
|
static void reset_ac(struct uae_prefs *p)
|
|
{
|
|
do_mount = 1;
|
|
|
|
if (need_uae_boot_rom(p) == 0)
|
|
do_mount = 0;
|
|
if (uae_boot_rom_type <= 0)
|
|
do_mount = 0;
|
|
|
|
/* check if Kickstart version is below 1.3 */
|
|
if (ks12orolder() && do_mount) {
|
|
/* warn user */
|
|
#if KS12_BOOT_HACK
|
|
do_mount = -1;
|
|
#else
|
|
write_log (_T("Kickstart version is below 1.3! Disabling automount devices.\n"));
|
|
do_mount = 0;
|
|
#endif
|
|
}
|
|
|
|
uae_id = hackers_id;
|
|
|
|
if (restore_cardno == 0) {
|
|
for (int i = 0; i < MAX_EXPANSION_BOARD_SPACE; i++) {
|
|
memset(&cards_set[i], 0, sizeof(struct card_data));
|
|
}
|
|
}
|
|
|
|
ecard = 0;
|
|
cardno = 0;
|
|
|
|
reset_ac_data(p);
|
|
}
|
|
|
|
void expansion_generate_autoconfig_info(struct uae_prefs *p)
|
|
{
|
|
expansion_scan_autoconfig(p, true);
|
|
}
|
|
|
|
struct autoconfig_info* expansion_get_autoconfig_by_address(struct uae_prefs* p, uaecptr addr, int index)
|
|
{
|
|
if (index >= cardno)
|
|
return NULL;
|
|
for (int i = 0; i < cardno; i++) {
|
|
struct card_data *cd = cards[i];
|
|
if (addr >= cd->base && addr < cd->base + cd->size)
|
|
return &cd->aci;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
static void expansion_init_cards(struct uae_prefs *p)
|
|
{
|
|
reset_ac_data(p);
|
|
|
|
for (int i = 0; i < cardno; i++) {
|
|
bool ok;
|
|
struct card_data *cd = &cards_set[i];
|
|
struct autoconfig_info *aci = &cd->aci;
|
|
memset(aci->autoconfig_raw, 0xff, sizeof aci->autoconfig_raw);
|
|
cd->base = 0;
|
|
cd->size = 0;
|
|
aci->devnum = (cd->flags >> 16) & 255;
|
|
aci->prefs = p;
|
|
aci->ert = cd->ert;
|
|
aci->start = 0xffffffff;
|
|
aci->zorro = cd->zorro;
|
|
if (cd->initnum) {
|
|
ok = cd->initnum(aci);
|
|
} else {
|
|
aci->rc = cd->rc;
|
|
ok = cd->initrc(aci);
|
|
}
|
|
|
|
if ((aci->zorro == 1 || aci->zorro == 2 || aci->zorro == 3) && aci->addrbankp != &expamem_null && (aci->autoconfig_raw[0] != 0xff || aci->autoconfigp)) {
|
|
uae_u8 ac2[16];
|
|
const uae_u8 *a = aci->autoconfigp;
|
|
if (!a) {
|
|
for (int i = 0; i < 16; i++) {
|
|
ac2[i] = autoconfig_read(aci->autoconfig_raw, i * 4);
|
|
}
|
|
a = ac2;
|
|
}
|
|
expansion_parse_autoconfig(cd, a);
|
|
cd->size = expamem_board_size;
|
|
}
|
|
}
|
|
}
|
|
|
|
static int get_order(struct uae_prefs *p, struct card_data *cd)
|
|
{
|
|
if (!cd)
|
|
return EXPANSION_ORDER_MAX - 1;
|
|
if (cd->aci.get_params) {
|
|
struct expansion_params parms;
|
|
if (cd->aci.get_params(p, &parms))
|
|
return parms.device_order;
|
|
}
|
|
if (cd->zorro <= 0)
|
|
return -1;
|
|
if (cd->zorro >= 4)
|
|
return -2;
|
|
if (cd->rc)
|
|
return cd->rc->back->device_order;
|
|
int devnum = (cd->flags >> 16) & 255;
|
|
if (!_tcsicmp(cd->name, _T("Z2Fast")))
|
|
return p->fastmem[devnum].device_order;
|
|
if (!_tcsicmp(cd->name, _T("Z3Fast")))
|
|
return p->z3fastmem[devnum].device_order;
|
|
if (!_tcsicmp(cd->name, _T("Z3RTG")) || !_tcsicmp(cd->name, _T("Z2RTG")))
|
|
return p->rtgboards[devnum].device_order;
|
|
if (!_tcsicmp(cd->name, _T("MegaChipRAM")))
|
|
return -1;
|
|
return EXPANSION_ORDER_MAX - 1;
|
|
}
|
|
|
|
static void expansion_parse_cards(struct uae_prefs *p, bool log)
|
|
{
|
|
if (log)
|
|
write_log(_T("Autoconfig board list:\n"));
|
|
reset_ac_data(p);
|
|
for (int i = 0; i < cardno; i++) {
|
|
bool ok;
|
|
struct card_data *cd = cards[i];
|
|
struct autoconfig_info *aci = &cd->aci;
|
|
memset(aci->autoconfig_raw, 0xff, sizeof aci->autoconfig_raw);
|
|
memset(aci->autoconfig_bytes, 0xff, sizeof aci->autoconfig_bytes);
|
|
cd->base = 0;
|
|
cd->size = 0;
|
|
aci->devnum = (cd->flags >> 16) & 255;
|
|
aci->prefs = p;
|
|
aci->ert = cd->ert;
|
|
aci->zorro = cd->zorro;
|
|
aci->start = 0xffffffff;
|
|
if (cd->initnum) {
|
|
ok = cd->initnum(aci);
|
|
} else {
|
|
aci->rc = cd->rc;
|
|
ok = cd->initrc(aci);
|
|
}
|
|
if (log)
|
|
write_log(_T("Card %02d: "), i + 1);
|
|
if (ok) {
|
|
TCHAR label[MAX_DPATH];
|
|
label[0] = 0;
|
|
if (cd->rc && !label[0]) {
|
|
const struct expansionromtype *ert = get_device_expansion_rom(cd->rc->back->device_type);
|
|
if (ert) {
|
|
_tcscpy(label, ert->friendlyname);
|
|
}
|
|
}
|
|
if (!label[0]) {
|
|
if (aci->label) {
|
|
_tcscpy(label, aci->label);
|
|
} else if (aci->addrbankp && aci->addrbankp->label) {
|
|
_tcscpy(label, aci->addrbankp->label);
|
|
} else {
|
|
_tcscpy(label, _T("<no name>"));
|
|
}
|
|
}
|
|
if (aci->devnum > 0) {
|
|
TCHAR *s = label + _tcslen(label);
|
|
_stprintf(s, _T(" [%d]"), aci->devnum + 1);
|
|
}
|
|
|
|
if ((aci->zorro == 1 || aci->zorro == 2 || aci->zorro == 3) && (aci->autoconfig_raw[0] != 0xff || aci->autoconfigp)) {
|
|
uae_u8 ac2[16];
|
|
const uae_u8 *a = aci->autoconfigp;
|
|
if (!a) {
|
|
for (int i = 0; i < 16; i++) {
|
|
ac2[i] = autoconfig_read(aci->autoconfig_raw, i * 4);
|
|
}
|
|
a = ac2;
|
|
}
|
|
if (log) {
|
|
write_log(_T("'%s'\n"), label);
|
|
write_log(_T(" %02x.%02x.%02x.%02x.%02x.%02x.%02x.%02x.%02x.%02x.%02x.%02x.%02x.%02x.%02x.%02x\n"),
|
|
a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7],
|
|
a[8], a[9], a[10], a[11], a[12], a[13], a[14], a[15]);
|
|
write_log(_T(" MID %u (%04x) PID %u (%02x) SER %08x\n"),
|
|
(a[4] << 8) | a[5], (a[4] << 8) | a[5],
|
|
a[1], a[1],
|
|
(a[6] << 24) | (a[7] << 16) | (a[8] << 8) | a[9]);
|
|
}
|
|
expansion_parse_autoconfig(cd, a);
|
|
uae_u32 size = expamem_board_size;
|
|
TCHAR sizemod = 'K';
|
|
uae_u8 type = a[0];
|
|
size /= 1024;
|
|
if (size > 8 * 1024) {
|
|
sizemod = 'M';
|
|
size /= 1024;
|
|
}
|
|
bool z3 = (type & 0xc0) == zorroIII;
|
|
if (log) {
|
|
write_log(_T(" Z%d 0x%08x 0x%08x %4d%c %s %d\n"),
|
|
(type & 0xc0) == zorroII ? 2 : (z3 ? 3 : 1),
|
|
z3 && !currprefs.z3autoconfig_start ? expamem_z3_pointer_real : expamem_board_pointer,
|
|
z3 && !currprefs.z3autoconfig_start ? expamem_z3_pointer_uae : expamem_board_pointer,
|
|
size, sizemod,
|
|
type & rom_card ? _T("ROM") : (type & add_memory ? _T("RAM") : _T("IO ")), get_order(p, cd));
|
|
}
|
|
cd->base = expamem_board_pointer;
|
|
cd->size = expamem_board_size;
|
|
if ((type & 0xc0) == zorroIII) {
|
|
aci->start = expamem_z3hack(p) ? expamem_z3_pointer_uae : expamem_z3_pointer_real;
|
|
} else {
|
|
aci->start = expamem_board_pointer;
|
|
}
|
|
aci->size = cd->size;
|
|
memcpy(aci->autoconfig_bytes, a, sizeof aci->autoconfig_bytes);
|
|
if (aci->addrbankp) {
|
|
aci->addrbankp->start = expamem_board_pointer;
|
|
if (aci->addrbankp->reserved_size == 0 && !(type & add_memory) && expamem_board_size < 524288) {
|
|
aci->addrbankp->reserved_size = expamem_board_size;
|
|
}
|
|
}
|
|
aci->zorro = cd->zorro;
|
|
if (cd->zorro == 3) {
|
|
if (expamem_z3_pointer_real + expamem_board_size < expamem_z3_pointer_real) {
|
|
expamem_z3_pointer_real = 0xffffffff;
|
|
expamem_z3_highram_real = 0xffffffff;
|
|
} else {
|
|
expamem_z3_pointer_real += expamem_board_size;
|
|
}
|
|
if (expamem_z3_pointer_uae + expamem_board_size < expamem_z3_pointer_uae) {
|
|
expamem_z3_pointer_uae = 0xffffffff;
|
|
expamem_z3_highram_uae = 0xffffffff;
|
|
} else {
|
|
expamem_z3_pointer_uae += expamem_board_size;
|
|
}
|
|
if (expamem_board_pointer + expamem_board_size < expamem_board_pointer) {
|
|
expamem_board_pointer = 0xffffffff;
|
|
} else {
|
|
expamem_board_pointer += expamem_board_size;
|
|
}
|
|
if ((type & add_memory) || aci->direct_vram) {
|
|
if (expamem_z3_pointer_uae != 0xffffffff && expamem_z3_pointer_uae > expamem_z3_highram_uae)
|
|
expamem_z3_highram_uae = expamem_z3_pointer_uae;
|
|
if (expamem_z3_pointer_real != 0xffffffff && expamem_z3_pointer_real > expamem_z3_highram_real)
|
|
expamem_z3_highram_real = expamem_z3_pointer_real;
|
|
}
|
|
|
|
}
|
|
} else {
|
|
cd->base = aci->start;
|
|
cd->size = aci->size;
|
|
if (log)
|
|
write_log(_T("'%s' no autoconfig %08x - %08x.\n"), aci->label ? aci->label : _T("<no name>"), cd->base, cd->base + cd->size - 1);
|
|
}
|
|
_tcscpy(aci->name, label);
|
|
} else {
|
|
if (log)
|
|
write_log(_T("init failed.\n"), i);
|
|
}
|
|
}
|
|
if (log)
|
|
write_log(_T("END\n"));
|
|
}
|
|
|
|
static bool add_card_sort(int index, bool *inuse, int *new_cardnop)
|
|
{
|
|
struct card_data *cd = &cards_set[index];
|
|
int new_cardno = *new_cardnop;
|
|
cards[new_cardno++] = cd;
|
|
inuse[index] = true;
|
|
*new_cardnop = new_cardno;
|
|
return true;
|
|
}
|
|
|
|
static void expansion_autoconfig_sort(struct uae_prefs *p)
|
|
{
|
|
const int zs[] = { BOARD_NONAUTOCONFIG_BEFORE, 0, BOARD_PROTOAUTOCONFIG, BOARD_AUTOCONFIG_Z2, BOARD_NONAUTOCONFIG_AFTER_Z2, BOARD_AUTOCONFIG_Z3, BOARD_NONAUTOCONFIG_AFTER_Z3, -1 };
|
|
bool inuse[MAX_EXPANSION_BOARD_SPACE];
|
|
struct card_data *tcards[MAX_EXPANSION_BOARD_SPACE];
|
|
int new_cardno = 0;
|
|
|
|
// default sort first, sets correct parent/child order
|
|
for (int i = 0; i < cardno; i++) {
|
|
inuse[i] = false;
|
|
cards[i] = NULL;
|
|
}
|
|
cards[cardno] = NULL;
|
|
for (int type = 0; zs[type] >= 0; type++) {
|
|
bool changed = true;
|
|
int z = zs[type];
|
|
bool inuse2[MAX_EXPANSION_BOARD_SPACE];
|
|
memset(inuse2, 0, sizeof inuse2);
|
|
while (changed) {
|
|
changed = false;
|
|
// unmovables first
|
|
int testorder = 0;
|
|
int idx = -1;
|
|
for (int i = 0; i < cardno; i++) {
|
|
if (inuse[i])
|
|
continue;
|
|
if (inuse2[i])
|
|
continue;
|
|
struct card_data *cd = &cards_set[i];
|
|
if (cd->zorro != z)
|
|
continue;
|
|
int order = get_order(p, cd);
|
|
if (order >= 0)
|
|
continue;
|
|
if (testorder > order) {
|
|
testorder = order;
|
|
idx = i;
|
|
}
|
|
}
|
|
if (idx >= 0) {
|
|
inuse2[idx] = true;
|
|
add_card_sort(idx, inuse, &new_cardno);
|
|
changed = true;
|
|
}
|
|
}
|
|
changed = true;
|
|
memset(inuse2, 0, sizeof inuse2);
|
|
while (changed) {
|
|
changed = false;
|
|
for (int i = 0; i < cardno; i++) {
|
|
if (inuse[i])
|
|
continue;
|
|
if (inuse2[i])
|
|
continue;
|
|
struct card_data *cd = &cards_set[i];
|
|
if (cd->zorro != z)
|
|
continue;
|
|
if (get_order(p, cd) < EXPANSION_ORDER_MAX - 1)
|
|
continue;
|
|
inuse2[i] = true;
|
|
add_card_sort(i, inuse, &new_cardno);
|
|
changed = true;
|
|
}
|
|
}
|
|
changed = true;
|
|
memset(inuse2, 0, sizeof inuse2);
|
|
while (changed) {
|
|
// the rest
|
|
changed = false;
|
|
for (int i = 0; i < cardno; i++) {
|
|
if (inuse[i])
|
|
continue;
|
|
if (inuse2[i])
|
|
continue;
|
|
struct card_data *cd = &cards_set[i];
|
|
if (cd->zorro != z)
|
|
continue;
|
|
inuse2[i] = true;
|
|
add_card_sort(i, inuse, &new_cardno);
|
|
changed = true;
|
|
}
|
|
}
|
|
}
|
|
for (int i = 0; i < cardno; i++) {
|
|
if (inuse[i])
|
|
continue;
|
|
cards[new_cardno++] = &cards_set[i];
|
|
}
|
|
for (int i = 0; i < cardno; i++) {
|
|
struct autoconfig_info *aci = &cards[i]->aci;
|
|
tcards[i] = cards[i];
|
|
}
|
|
|
|
new_cardno = 0;
|
|
|
|
// re-sort by board size
|
|
for (int idx = 0; idx < cardno; idx++) {
|
|
struct card_data *cd = tcards[idx];
|
|
if (!cd)
|
|
continue;
|
|
int z = cd->zorro;
|
|
if (z != 2 && z != 3) {
|
|
cards[new_cardno++] = cd;
|
|
tcards[idx] = NULL;
|
|
}
|
|
}
|
|
for (int z = 2; z <= 3; z++) {
|
|
for (;;) {
|
|
int idx2 = -1;
|
|
uae_u32 size = 0;
|
|
for (int j = 0; j < cardno; j++) {
|
|
struct card_data *cdc = tcards[j];
|
|
if (cdc && cdc->size > size && cdc->zorro == z) {
|
|
size = cdc->size;
|
|
idx2 = j;
|
|
}
|
|
}
|
|
if (idx2 < 0)
|
|
break;
|
|
cards[new_cardno++] = tcards[idx2];
|
|
tcards[idx2] = NULL;
|
|
}
|
|
}
|
|
|
|
for (int i = 0; i < cardno; i++) {
|
|
if (tcards[i]) {
|
|
cards[new_cardno++] = tcards[i];
|
|
}
|
|
}
|
|
}
|
|
|
|
static void expansion_add_autoconfig(struct uae_prefs *p)
|
|
{
|
|
int fastmem_num;
|
|
|
|
reset_ac(p);
|
|
|
|
// add possible non-autoconfig boards
|
|
add_expansions(p, BOARD_NONAUTOCONFIG_BEFORE, NULL, 0);
|
|
|
|
fastmem_num = 0;
|
|
add_expansions(p, BOARD_PROTOAUTOCONFIG, &fastmem_num, 0);
|
|
// immediately after Z2Fast so that it can be emulated as A590/A2091 with fast ram.
|
|
add_expansions(p, BOARD_AUTOCONFIG_Z2, &fastmem_num, 0);
|
|
|
|
add_expansions(p, BOARD_NONAUTOCONFIG_AFTER_Z2, NULL, 0);
|
|
|
|
while (fastmem_num < MAX_RAM_BOARDS) {
|
|
if (p->fastmem[fastmem_num].size) {
|
|
cards_set[cardno].flags = fastmem_num << 16;
|
|
cards_set[cardno].name = _T("Z2Fast");
|
|
cards_set[cardno].zorro = 2;
|
|
cards_set[cardno].initnum = expamem_init_fastcard;
|
|
cards_set[cardno++].map = expamem_map_fastcard;
|
|
}
|
|
fastmem_num++;
|
|
}
|
|
|
|
#ifdef FILESYS
|
|
if (do_mount && p->uaeboard >= 0) {
|
|
cards_set[cardno].flags = 0;
|
|
cards_set[cardno].name = _T("UAEFS");
|
|
cards_set[cardno].zorro = 2;
|
|
cards_set[cardno].initnum = expamem_init_filesys;
|
|
cards_set[cardno++].map = expamem_map_filesys;
|
|
}
|
|
if (p->uaeboard > 0) {
|
|
cards_set[cardno].flags = 0;
|
|
cards_set[cardno].name = _T("UAEBOARD");
|
|
cards_set[cardno].zorro = 2;
|
|
cards_set[cardno].initnum = expamem_init_uaeboard;
|
|
cards_set[cardno++].map = expamem_map_uaeboard;
|
|
}
|
|
if (do_mount) {
|
|
cards_set[cardno].flags = 0;
|
|
cards_set[cardno].name = _T("UAEBOOTROM");
|
|
cards_set[cardno].zorro = BOARD_NONAUTOCONFIG_BEFORE;
|
|
cards_set[cardno].initnum = expamem_rtarea_init;
|
|
cards_set[cardno++].map = NULL;
|
|
}
|
|
#endif
|
|
#ifdef PICASSO96
|
|
for (int i = 0; i < MAX_RTG_BOARDS; i++) {
|
|
struct rtgboardconfig *rbc = &p->rtgboards[i];
|
|
if (rbc->rtgmem_size && rbc->rtgmem_type == GFXBOARD_UAE_Z2) {
|
|
cards_set[cardno].flags = 4 | (i << 16);
|
|
cards_set[cardno].zorro = 2;
|
|
cards_set[cardno].name = _T("Z2RTG");
|
|
cards_set[cardno].initnum = expamem_init_gfxcard_z2;
|
|
cards_set[cardno++].map = expamem_map_gfxcard_z2;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
/* Z3 boards last */
|
|
|
|
fastmem_num = 0;
|
|
|
|
// add combo Z3 boards (something + Z3 RAM)
|
|
add_expansions(p, BOARD_AUTOCONFIG_Z3, &fastmem_num, 2);
|
|
|
|
// add remaining RAM boards
|
|
for (int i = fastmem_num; i < MAX_RAM_BOARDS; i++) {
|
|
if (p->z3fastmem[i].size) {
|
|
z3num = 0;
|
|
cards_set[cardno].flags = (2 | CARD_FLAG_CAN_Z3) | (i << 16);
|
|
cards_set[cardno].name = _T("Z3Fast");
|
|
cards_set[cardno].zorro = 3;
|
|
cards_set[cardno].initnum = expamem_init_z3fastmem;
|
|
cards_set[cardno++].map = expamem_map_z3fastmem;
|
|
}
|
|
}
|
|
#ifdef PICASSO96
|
|
for (int i = 0; i < MAX_RTG_BOARDS; i++) {
|
|
if (p->rtgboards[i].rtgmem_size && p->rtgboards[i].rtgmem_type == GFXBOARD_UAE_Z3) {
|
|
cards_set[cardno].flags = 4 | CARD_FLAG_CAN_Z3 | (i << 16);
|
|
cards_set[cardno].name = _T("Z3RTG");
|
|
cards_set[cardno].zorro = 3;
|
|
cards_set[cardno].initnum = expamem_init_gfxcard_z3;
|
|
cards_set[cardno++].map = expamem_map_gfxcard_z3;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
// add non-memory Z3 boards
|
|
add_expansions(p, BOARD_AUTOCONFIG_Z3, NULL, 1);
|
|
|
|
add_expansions(p, BOARD_NONAUTOCONFIG_AFTER_Z3, NULL, 0);
|
|
}
|
|
|
|
void expansion_scan_autoconfig(struct uae_prefs *p, bool log)
|
|
{
|
|
cfgfile_compatibility_romtype(p);
|
|
expansion_add_autoconfig(p);
|
|
expansion_init_cards(p);
|
|
expansion_autoconfig_sort(p);
|
|
expansion_parse_cards(p, log);
|
|
}
|
|
|
|
void expamem_reset (int hardreset)
|
|
{
|
|
reset_ac(&currprefs);
|
|
|
|
chipdone = false;
|
|
|
|
allocate_expamem ();
|
|
expamem_bank.name = _T("Autoconfig [reset]");
|
|
|
|
expansion_add_autoconfig(&currprefs);
|
|
expansion_init_cards(&currprefs);
|
|
expansion_autoconfig_sort(&currprefs);
|
|
expansion_parse_cards(&currprefs, true);
|
|
|
|
// this also resets all autoconfig devices
|
|
devices_reset_ext(hardreset);
|
|
|
|
if (cardno == 0 || savestate_state) {
|
|
expamem_init_clear_zero ();
|
|
} else {
|
|
set_ks12_boot_hack();
|
|
call_card_init(0);
|
|
}
|
|
}
|
|
|
|
void expansion_init (void)
|
|
{
|
|
if (savestate_state != STATE_RESTORE) {
|
|
|
|
for (int i = 0; i < MAX_RAM_BOARDS; i++) {
|
|
fastmem_bank[i].reserved_size = 0;
|
|
fastmem_bank[i].mask = 0;
|
|
fastmem_bank[i].baseaddr = NULL;
|
|
}
|
|
|
|
#ifdef PICASSO96
|
|
for (int i = 0; i < MAX_RTG_BOARDS; i++) {
|
|
gfxmem_banks[i]->reserved_size = 0;
|
|
gfxmem_banks[i]->mask = 0;
|
|
gfxmem_banks[i]->baseaddr = NULL;
|
|
}
|
|
#endif
|
|
|
|
for (int i = 0; i < MAX_RAM_BOARDS; i++) {
|
|
z3fastmem_bank[i].reserved_size = 0;
|
|
z3fastmem_bank[i].mask = 0;
|
|
z3fastmem_bank[i].baseaddr = NULL;
|
|
}
|
|
}
|
|
|
|
allocate_expamem ();
|
|
|
|
if (currprefs.uaeboard) {
|
|
uaeboard_bank.reserved_size = 0x10000;
|
|
mapped_malloc(&uaeboard_bank);
|
|
}
|
|
|
|
}
|
|
|
|
void expansion_cleanup (void)
|
|
{
|
|
for (int i = 0; i < MAX_RAM_BOARDS; i++) {
|
|
mapped_free (&fastmem_bank[i]);
|
|
mapped_free (&z3fastmem_bank[i]);
|
|
}
|
|
|
|
#ifdef PICASSO96
|
|
for (int i = 0; i < MAX_RTG_BOARDS; i++) {
|
|
mapped_free (gfxmem_banks[i]);
|
|
}
|
|
#endif
|
|
|
|
#ifdef FILESYS
|
|
mapped_free (&filesys_bank);
|
|
#endif
|
|
if (currprefs.uaeboard) {
|
|
mapped_free(&uaeboard_bank);
|
|
}
|
|
}
|
|
|
|
void expansion_map(void)
|
|
{
|
|
map_banks(&expamem_bank, 0xE8, 1, 0);
|
|
if (do_mount < 0 && ks11orolder()) {
|
|
filesys_bank.start = 0xe90000;
|
|
mapped_free(&filesys_bank);
|
|
mapped_malloc(&filesys_bank);
|
|
map_banks_z2(&filesys_bank, filesys_bank.start >> 16, 1);
|
|
expamem_init_filesys(0);
|
|
expamem_map_filesys_update();
|
|
}
|
|
}
|
|
|
|
static void clear_bank (addrbank *ab)
|
|
{
|
|
if (!ab->baseaddr || !ab->allocated_size)
|
|
return;
|
|
memset (ab->baseaddr, 0, ab->allocated_size > 0x800000 ? 0x800000 : ab->allocated_size);
|
|
}
|
|
|
|
void expansion_clear(void)
|
|
{
|
|
for (int i = 0; i < MAX_RAM_BOARDS; i++) {
|
|
clear_bank (&fastmem_bank[i]);
|
|
clear_bank (&z3fastmem_bank[i]);
|
|
}
|
|
for (int i = 0; i < MAX_RTG_BOARDS; i++) {
|
|
clear_bank (gfxmem_banks[i]);
|
|
}
|
|
}
|
|
|
|
#ifdef SAVESTATE
|
|
|
|
/* State save/restore code. */
|
|
|
|
uae_u8 *save_fram (int *len, int num)
|
|
{
|
|
*len = fastmem_bank[num].allocated_size;
|
|
return fastmem_bank[num].baseaddr;
|
|
}
|
|
|
|
uae_u8 *save_zram (int *len, int num)
|
|
{
|
|
*len = z3fastmem_bank[num].allocated_size;
|
|
return z3fastmem_bank[num].baseaddr;
|
|
}
|
|
|
|
uae_u8 *save_pram (int *len)
|
|
{
|
|
*len = gfxmem_banks[0]->allocated_size;
|
|
return gfxmem_banks[0]->baseaddr;
|
|
}
|
|
|
|
void restore_fram (int len, size_t filepos, int num)
|
|
{
|
|
fast_filepos[num] = filepos;
|
|
changed_prefs.fastmem[num].size = len;
|
|
}
|
|
|
|
void restore_zram (int len, size_t filepos, int num)
|
|
{
|
|
z3_filepos[num] = filepos;
|
|
changed_prefs.z3fastmem[num].size = len;
|
|
}
|
|
|
|
void restore_pram (int len, size_t filepos)
|
|
{
|
|
p96_filepos = filepos;
|
|
changed_prefs.rtgboards[0].rtgmem_size = len;
|
|
}
|
|
|
|
uae_u8 *save_expansion (int *len, uae_u8 *dstptr)
|
|
{
|
|
uae_u8 *dst, *dstbak;
|
|
if (dstptr)
|
|
dst = dstbak = dstptr;
|
|
else
|
|
dstbak = dst = xmalloc (uae_u8, 6 * 4);
|
|
save_u32 (fastmem_bank[0].start);
|
|
save_u32 (z3fastmem_bank[0].start);
|
|
save_u32 (gfxmem_banks[0]->start);
|
|
save_u32 (rtarea_base);
|
|
*len = dst - dstbak;
|
|
return dstbak;
|
|
}
|
|
|
|
uae_u8 *restore_expansion (uae_u8 *src)
|
|
{
|
|
fastmem_bank[0].start = restore_u32 ();
|
|
z3fastmem_bank[0].start = restore_u32 ();
|
|
gfxmem_banks[0]->start = restore_u32 ();
|
|
rtarea_base = restore_u32 ();
|
|
if (rtarea_base != 0 && rtarea_base != RTAREA_DEFAULT && rtarea_base != RTAREA_BACKUP && (rtarea_base < 0xe90000 || rtarea_base >= 0xf00000))
|
|
rtarea_base = 0;
|
|
return src;
|
|
}
|
|
|
|
uae_u8 *save_expansion_boards(int *len, uae_u8 *dstptr, int cardnum)
|
|
{
|
|
uae_u8 *dst, *dstbak;
|
|
if (cardnum >= cardno)
|
|
return NULL;
|
|
if (dstptr)
|
|
dst = dstbak = dstptr;
|
|
else
|
|
dstbak = dst = xmalloc(uae_u8, 1000);
|
|
save_u32(3);
|
|
save_u32(0);
|
|
save_u32(cardnum);
|
|
struct card_data *ec = cards[cardnum];
|
|
save_u32(ec->base);
|
|
save_u32(ec->size);
|
|
save_u32(ec->flags);
|
|
save_string(ec->name);
|
|
for (int j = 0; j < 16; j++) {
|
|
save_u8(ec->aci.autoconfig_bytes[j]);
|
|
}
|
|
struct romconfig *rc = ec->rc;
|
|
if (rc) {
|
|
save_u32(rc->back->device_type);
|
|
save_u32(rc->back->device_num);
|
|
save_string(rc->romfile);
|
|
save_string(rc->romident);
|
|
} else {
|
|
save_u32(0xffffffff);
|
|
}
|
|
*len = dst - dstbak;
|
|
return dstbak;
|
|
}
|
|
|
|
uae_u8 *restore_expansion_boards(uae_u8 *src)
|
|
{
|
|
if (!src) {
|
|
restore_cardno = 0;
|
|
return NULL;
|
|
}
|
|
TCHAR *s;
|
|
uae_u32 flags = restore_u32();
|
|
if (!(flags & 2))
|
|
return src;
|
|
restore_u32();
|
|
int cardnum = restore_u32();
|
|
restore_cardno = cardnum + 1;
|
|
struct card_data *ec = &cards_set[cardnum];
|
|
cards[cardnum] = ec;
|
|
|
|
ec->base = restore_u32();
|
|
ec->size = restore_u32();
|
|
ec->flags = restore_u32();
|
|
s = restore_string();
|
|
xfree(s);
|
|
for (int j = 0; j < 16; j++) {
|
|
ec->aci.autoconfig_bytes[j] = restore_u8();
|
|
}
|
|
|
|
uae_u32 dev_num = 0;
|
|
uae_u32 romtype = restore_u32();
|
|
if (romtype != 0xffffffff) {
|
|
dev_num = restore_u32();
|
|
ec->aci.devnum = dev_num;
|
|
struct boardromconfig* brc = get_device_rom(&currprefs, romtype, dev_num, NULL);
|
|
if (!brc) {
|
|
brc = get_device_rom_new(&currprefs, romtype, dev_num, NULL);
|
|
}
|
|
struct romconfig *rc = get_device_romconfig(&currprefs, romtype, dev_num);
|
|
if (rc) {
|
|
ec->rc = rc;
|
|
rc->back = brc;
|
|
ec->ert = get_device_expansion_rom(romtype);
|
|
s = restore_string();
|
|
_tcscpy(rc->romfile, s);
|
|
xfree(s);
|
|
s = restore_string();
|
|
_tcscpy(rc->romident, s);
|
|
xfree(s);
|
|
}
|
|
}
|
|
return src;
|
|
}
|
|
|
|
void restore_expansion_finish(void)
|
|
{
|
|
cardno = restore_cardno;
|
|
for (int i = 0; i < cardno; i++) {
|
|
struct card_data *ec = &cards_set[i];
|
|
cards[i] = ec;
|
|
struct romconfig *rc = ec->rc;
|
|
// Handle only IO boards, RAM boards are handled differently
|
|
if (rc && ec->ert) {
|
|
ec->aci.doinit = false;
|
|
ec->aci.start = ec->base;
|
|
ec->aci.size = ec->size;
|
|
ec->aci.prefs = &currprefs;
|
|
_tcscpy(ec->aci.name, ec->ert->friendlyname);
|
|
if (ec->ert->init) {
|
|
if (ec->ert->init(&ec->aci)) {
|
|
if (ec->aci.addrbankp) {
|
|
map_banks(ec->aci.addrbankp, ec->base >> 16, ec->size >> 16, 0);
|
|
}
|
|
}
|
|
}
|
|
ec->aci.doinit = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
#endif /* SAVESTATE */
|
|
|
|
const struct expansionromtype expansionroms[] = {
|
|
|
|
/* built-in controllers */
|
|
#ifdef CD32
|
|
{
|
|
_T("cd32fmv"), _T("CD32 FMV"), _T("Commodore"),
|
|
expamem_init_cd32fmv, NULL, ROMTYPE_CD32CART, BOARD_AUTOCONFIG_Z2,
|
|
EXPANSIONTYPE_INTERNAL
|
|
},
|
|
#endif
|
|
{
|
|
_T("ide_mb"), _T("A600/A1200/A4000 IDE"), _T("Commodore"),
|
|
gayle_ide_init, gayle_add_ide_unit, ROMTYPE_MB_IDE | ROMTYPE_NOT, BOARD_NONAUTOCONFIG_BEFORE,
|
|
EXPANSIONTYPE_INTERNAL | EXPANSIONTYPE_IDE
|
|
},
|
|
{
|
|
_T("pcmcia_mb"), _T("A600/A1200 PCMCIA"), _T("Commodore"),
|
|
gayle_init_pcmcia, NULL, ROMTYPE_MB_PCMCIA | ROMTYPE_NOT, BOARD_NONAUTOCONFIG_BEFORE,
|
|
EXPANSIONTYPE_INTERNAL
|
|
},
|
|
|
|
{
|
|
NULL
|
|
}
|
|
};
|