redquark-amiberry-rb/src/memory.cpp
Dimitris Panokostas 032ec401e7 Fixed identation
2017-12-12 22:08:51 +01:00

1802 lines
50 KiB
C++

/*
* UAE - The Un*x Amiga Emulator
*
* Memory management
*
* (c) 1995 Bernd Schmidt
*/
#include "sysconfig.h"
#include "sysdeps.h"
#include "options.h"
#include "uae.h"
#include "memory.h"
#include "rommgr.h"
#include "zfile.h"
#include "custom.h"
#include "newcpu.h"
#include "autoconf.h"
#include "savestate.h"
#include "ar.h"
#include "crc32.h"
#include "gui.h"
#include "akiko.h"
#include "threaddep/thread.h"
#include "gayle.h"
#include "gfxboard.h"
#include "audio.h"
#include "devices.h"
#ifdef JIT
/* Set by each memory handler that does not simply access real memory. */
int special_mem;
#endif
static int mem_hardreset;
static size_t bootrom_filepos, chip_filepos, bogo_filepos, a3000lmem_filepos, a3000hmem_filepos;
/* Set if we notice during initialization that settings changed,
and we must clear all memory to prevent bogus contents from confusing
the Kickstart. */
static bool need_hardreset;
/* The address space setting used during the last reset. */
static bool last_address_space_24;
addrbank *mem_banks[MEMORY_BANKS];
int addr_valid(const TCHAR *txt, uaecptr addr, uae_u32 len)
{
addrbank *ab = &get_mem_bank(addr);
if (ab == 0 || !(ab->flags & (ABFLAG_RAM | ABFLAG_ROM)) || addr < 0x100 || len > 16777215 || !valid_address(addr, len)) {
write_log (_T("corrupt %s pointer %x (%d) detected!\n"), txt, addr, len);
return 0;
}
return 1;
}
/* A dummy bank that only contains zeros */
static uae_u32 REGPARAM3 dummy_lget (uaecptr) REGPARAM;
static uae_u32 REGPARAM3 dummy_wget (uaecptr) REGPARAM;
static uae_u32 REGPARAM3 dummy_bget (uaecptr) REGPARAM;
static void REGPARAM3 dummy_lput (uaecptr, uae_u32) REGPARAM;
static void REGPARAM3 dummy_wput (uaecptr, uae_u32) REGPARAM;
static void REGPARAM3 dummy_bput (uaecptr, uae_u32) REGPARAM;
static int REGPARAM3 dummy_check (uaecptr addr, uae_u32 size) REGPARAM;
/* fake UAE ROM */
extern addrbank fakeuaebootrom_bank;
MEMORY_FUNCTIONS(fakeuaebootrom);
#define MAX_ILG 1000
#define NONEXISTINGDATA 0
//#define NONEXISTINGDATA 0xffffffff
static bool map_uae_boot_rom_direct(void)
{
if (!fakeuaebootrom_bank.allocated_size) {
fakeuaebootrom_bank.start = 0xf00000;
fakeuaebootrom_bank.reserved_size = 65536;
fakeuaebootrom_bank.mask = fakeuaebootrom_bank.reserved_size - 1;
if (!mapped_malloc (&fakeuaebootrom_bank))
return false;
// create jump table to real uae boot rom
for (int i = 0xff00; i < 0xfff8; i += 8) {
uae_u8 *p = fakeuaebootrom_bank.baseaddr + i;
p[0] = 0x4e;
p[1] = 0xf9;
uaecptr p2 = rtarea_base + i;
p[2] = p2 >> 24;
p[3] = p2 >> 16;
p[4] = p2 >> 8;
p[5] = p2 >> 0;
}
}
map_banks(&fakeuaebootrom_bank, 0xf0, 1, 1);
write_log(_T("Mapped fake UAE Boot ROM jump table.\n"));
return true;
}
static bool gary_nonrange(uaecptr addr)
{
if (currprefs.cs_fatgaryrev < 0)
return false;
if (addr < 0xb80000)
return false;
if (addr >= 0xd00000 && addr < 0xdc0000)
return true;
if (addr >= 0xdd0000 && addr < 0xde0000)
return true;
if (addr >= 0xdf8000 && addr < 0xe00000)
return false;
if (addr >= 0xe80000 && addr < 0xf80000)
return false;
return true;
}
uae_u32 dummy_get_safe(uaecptr addr, int size, bool inst, uae_u32 defvalue)
{
uae_u32 v = defvalue;
uae_u32 mask = size == 4 ? 0xffffffff : (1 << (size * 8)) - 1;
if (currprefs.cpu_model >= 68040)
return v & mask;
if (!currprefs.cpu_compatible)
return v & mask;
if (currprefs.address_space_24)
addr &= 0x00ffffff;
if (addr >= 0x10000000)
return v & mask;
// CD32 returns zeros from all unmapped addresses
if (currprefs.cs_cd32cd)
return 0;
if ((currprefs.cpu_model <= 68010) || (currprefs.cpu_model == 68020 && (currprefs.chipset_mask & CSMASK_AGA) && currprefs.address_space_24)) {
if (size == 4) {
v = regs.db & 0xffff;
if (addr & 1)
v = (v << 8) | (v >> 8);
v = (v << 16) | v;
} else if (size == 2) {
v = regs.db & 0xffff;
if (addr & 1)
v = (v << 8) | (v >> 8);
} else {
v = regs.db;
v = (addr & 1) ? (v & 0xff) : ((v >> 8) & 0xff);
}
}
return v & mask;
}
uae_u32 dummy_get (uaecptr addr, int size, bool inst, uae_u32 defvalue)
{
uae_u32 v = defvalue;
if (gary_nonrange(addr) || (size > 1 && gary_nonrange(addr + size - 1))) {
if (gary_toenb)
exception2 (addr, false, size, (regs.s ? 4 : 0) | (inst ? 0 : 1));
return v;
}
return dummy_get_safe(addr, size, inst, defvalue);
}
static uae_u32 REGPARAM2 dummy_lget (uaecptr addr)
{
return dummy_get (addr, 4, false, NONEXISTINGDATA);
}
uae_u32 REGPARAM2 dummy_lgeti (uaecptr addr)
{
return dummy_get (addr, 4, true, NONEXISTINGDATA);
}
static uae_u32 REGPARAM2 dummy_wget (uaecptr addr)
{
return dummy_get (addr, 2, false, NONEXISTINGDATA);
}
uae_u32 REGPARAM2 dummy_wgeti (uaecptr addr)
{
return dummy_get (addr, 2, true, NONEXISTINGDATA);
}
static uae_u32 REGPARAM2 dummy_bget (uaecptr addr)
{
return dummy_get (addr, 1, false, NONEXISTINGDATA);
}
static void REGPARAM2 dummy_lput (uaecptr addr, uae_u32 l)
{
}
static void REGPARAM2 dummy_wput (uaecptr addr, uae_u32 w)
{
}
static void REGPARAM2 dummy_bput (uaecptr addr, uae_u32 b)
{
}
static int REGPARAM2 dummy_check (uaecptr addr, uae_u32 size)
{
return 0;
}
addrbank *get_sub_bank(uaecptr *paddr)
{
int i;
uaecptr addr = *paddr;
addrbank *ab = &get_mem_bank(addr);
struct addrbank_sub *sb = ab->sub_banks;
if (!sb)
return &dummy_bank;
for (i = 0; sb[i].bank; i++) {
int offset = addr & 65535;
if (offset < sb[i + 1].offset) {
uae_u32 mask = sb[i].mask;
uae_u32 maskval = sb[i].maskval;
if ((offset & mask) == maskval) {
*paddr = addr - sb[i].suboffset;
return sb[i].bank;
}
}
}
*paddr = addr - sb[i - 1].suboffset;
return sb[i - 1].bank;
}
uae_u32 REGPARAM3 sub_bank_lget (uaecptr addr) REGPARAM
{
addrbank *ab = get_sub_bank(&addr);
return ab->lget(addr);
}
uae_u32 REGPARAM3 sub_bank_wget(uaecptr addr) REGPARAM
{
addrbank *ab = get_sub_bank(&addr);
return ab->wget(addr);
}
uae_u32 REGPARAM3 sub_bank_bget(uaecptr addr) REGPARAM
{
addrbank *ab = get_sub_bank(&addr);
return ab->bget(addr);
}
void REGPARAM3 sub_bank_lput(uaecptr addr, uae_u32 v) REGPARAM
{
addrbank *ab = get_sub_bank(&addr);
ab->lput(addr, v);
}
void REGPARAM3 sub_bank_wput(uaecptr addr, uae_u32 v) REGPARAM
{
addrbank *ab = get_sub_bank(&addr);
ab->wput(addr, v);
}
void REGPARAM3 sub_bank_bput(uaecptr addr, uae_u32 v) REGPARAM
{
addrbank *ab = get_sub_bank(&addr);
ab->bput(addr, v);
}
uae_u32 REGPARAM3 sub_bank_lgeti(uaecptr addr) REGPARAM
{
addrbank *ab = get_sub_bank(&addr);
return ab->lgeti(addr);
}
uae_u32 REGPARAM3 sub_bank_wgeti(uaecptr addr) REGPARAM
{
addrbank *ab = get_sub_bank(&addr);
return ab->wgeti(addr);
}
int REGPARAM3 sub_bank_check(uaecptr addr, uae_u32 size) REGPARAM
{
addrbank *ab = get_sub_bank(&addr);
return ab->check(addr, size);
}
uae_u8 *REGPARAM3 sub_bank_xlate(uaecptr addr) REGPARAM
{
addrbank *ab = get_sub_bank(&addr);
return ab->xlateaddr(addr);
}
/* Chip memory */
uae_u32 chipmem_full_mask;
static int REGPARAM3 chipmem_check (uaecptr addr, uae_u32 size) REGPARAM;
static uae_u8 *REGPARAM3 chipmem_xlate (uaecptr addr) REGPARAM;
static uae_u32 REGPARAM2 chipmem_lget (uaecptr addr)
{
uae_u32 *m;
addr &= chipmem_bank.mask;
m = (uae_u32 *)(chipmem_bank.baseaddr + addr);
return do_get_mem_long (m);
}
static uae_u32 REGPARAM2 chipmem_wget (uaecptr addr)
{
uae_u16 *m, v;
addr &= chipmem_bank.mask;
m = (uae_u16 *)(chipmem_bank.baseaddr + addr);
v = do_get_mem_word (m);
return v;
}
static uae_u32 REGPARAM2 chipmem_bget (uaecptr addr)
{
uae_u8 v;
addr &= chipmem_bank.mask;
v = chipmem_bank.baseaddr[addr];
return v;
}
void REGPARAM2 chipmem_lput (uaecptr addr, uae_u32 l)
{
uae_u32 *m;
addr &= chipmem_bank.mask;
m = (uae_u32 *)(chipmem_bank.baseaddr + addr);
do_put_mem_long(m, l);
}
void REGPARAM2 chipmem_wput (uaecptr addr, uae_u32 w)
{
uae_u16 *m;
addr &= chipmem_bank.mask;
m = (uae_u16 *)(chipmem_bank.baseaddr + addr);
do_put_mem_word (m, w);
}
void REGPARAM2 chipmem_bput (uaecptr addr, uae_u32 b)
{
addr &= chipmem_bank.mask;
chipmem_bank.baseaddr[addr] = b;
}
void REGPARAM2 chipmem_agnus_wput (uaecptr addr, uae_u32 w)
{
uae_u16 *m;
addr &= chipmem_full_mask;
m = (uae_u16 *)(chipmem_bank.baseaddr + addr);
do_put_mem_word (m, w);
}
static int REGPARAM2 chipmem_check (uaecptr addr, uae_u32 size)
{
addr &= chipmem_bank.mask;
return (addr + size) <= chipmem_bank.allocated_size;
}
static uae_u8 *REGPARAM2 chipmem_xlate (uaecptr addr)
{
addr &= chipmem_bank.mask;
return chipmem_bank.baseaddr + addr;
}
/* Slow memory */
MEMORY_FUNCTIONS(bogomem);
/* A3000 motherboard fast memory */
MEMORY_FUNCTIONS(a3000lmem);
MEMORY_FUNCTIONS(a3000hmem);
/* Kick memory */
uae_u16 kickstart_version;
static void REGPARAM3 kickmem_lput (uaecptr, uae_u32) REGPARAM;
static void REGPARAM3 kickmem_wput (uaecptr, uae_u32) REGPARAM;
static void REGPARAM3 kickmem_bput (uaecptr, uae_u32) REGPARAM;
MEMORY_BGET(kickmem);
MEMORY_WGET(kickmem);
MEMORY_LGET(kickmem);
MEMORY_CHECK(kickmem);
MEMORY_XLATE(kickmem);
static void REGPARAM2 kickmem_lput (uaecptr addr, uae_u32 b)
{
}
static void REGPARAM2 kickmem_wput (uaecptr addr, uae_u32 b)
{
}
static void REGPARAM2 kickmem_bput (uaecptr addr, uae_u32 b)
{
}
/* CD32/CDTV extended kick memory */
static int extendedkickmem_type;
#define EXTENDED_ROM_CD32 1
#define EXTENDED_ROM_CDTV 2
#define EXTENDED_ROM_KS 3
static void REGPARAM3 extendedkickmem_lput (uaecptr, uae_u32) REGPARAM;
static void REGPARAM3 extendedkickmem_wput (uaecptr, uae_u32) REGPARAM;
static void REGPARAM3 extendedkickmem_bput (uaecptr, uae_u32) REGPARAM;
MEMORY_BGET(extendedkickmem);
MEMORY_WGET(extendedkickmem);
MEMORY_LGET(extendedkickmem);
MEMORY_CHECK(extendedkickmem);
MEMORY_XLATE(extendedkickmem);
static void REGPARAM2 extendedkickmem_lput (uaecptr addr, uae_u32 b)
{
}
static void REGPARAM2 extendedkickmem_wput (uaecptr addr, uae_u32 b)
{
}
static void REGPARAM2 extendedkickmem_bput (uaecptr addr, uae_u32 b)
{
}
static void REGPARAM3 extendedkickmem2_lput (uaecptr, uae_u32) REGPARAM;
static void REGPARAM3 extendedkickmem2_wput (uaecptr, uae_u32) REGPARAM;
static void REGPARAM3 extendedkickmem2_bput (uaecptr, uae_u32) REGPARAM;
MEMORY_BGET(extendedkickmem2);
MEMORY_WGET(extendedkickmem2);
MEMORY_LGET(extendedkickmem2);
MEMORY_CHECK(extendedkickmem2);
MEMORY_XLATE(extendedkickmem2);
static void REGPARAM2 extendedkickmem2_lput (uaecptr addr, uae_u32 b)
{
}
static void REGPARAM2 extendedkickmem2_wput (uaecptr addr, uae_u32 b)
{
}
static void REGPARAM2 extendedkickmem2_bput (uaecptr addr, uae_u32 b)
{
}
/* Default memory access functions */
int REGPARAM2 default_check (uaecptr a, uae_u32 b)
{
return 0;
}
static int be_cnt, be_recursive;
uae_u8 *REGPARAM2 default_xlate (uaecptr addr)
{
if (be_recursive) {
cpu_halt(CPU_HALT_OPCODE_FETCH_FROM_NON_EXISTING_ADDRESS);
return kickmem_xlate(2);
}
be_recursive++;
int size = currprefs.cpu_model >= 68020 ? 4 : 2;
if (quit_program == 0) {
/* do this only in 68010+ mode, there are some tricky A500 programs.. */
if(currprefs.cpu_model > 68000 || !currprefs.cpu_compatible) {
if (be_cnt < 3) {
write_log (_T("Your Amiga program just did something terribly stupid %08X PC=%08X\n"), addr, M68K_GETPC);
}
if (gary_toenb && (gary_nonrange(addr) || (size > 1 && gary_nonrange(addr + size - 1)))) {
exception2 (addr, false, size, regs.s ? 4 : 0);
} else {
cpu_halt (CPU_HALT_OPCODE_FETCH_FROM_NON_EXISTING_ADDRESS);
}
}
}
be_recursive--;
return kickmem_xlate (2); /* So we don't crash. */
}
/* Address banks */
addrbank dummy_bank = {
dummy_lget, dummy_wget, dummy_bget,
dummy_lput, dummy_wput, dummy_bput,
default_xlate, dummy_check, NULL, NULL, NULL,
dummy_lgeti, dummy_wgeti,
ABFLAG_NONE, S_READ, S_WRITE
};
addrbank chipmem_bank = {
chipmem_lget, chipmem_wget, chipmem_bget,
chipmem_lput, chipmem_wput, chipmem_bput,
chipmem_xlate, chipmem_check, NULL, _T("chip"), _T("Chip memory"),
chipmem_lget, chipmem_wget,
ABFLAG_RAM | ABFLAG_THREADSAFE | ABFLAG_CHIPRAM, 0, 0
};
addrbank bogomem_bank = {
bogomem_lget, bogomem_wget, bogomem_bget,
bogomem_lput, bogomem_wput, bogomem_bput,
bogomem_xlate, bogomem_check, NULL, _T("bogo"), _T("Slow memory"),
bogomem_lget, bogomem_wget,
ABFLAG_RAM | ABFLAG_THREADSAFE, 0, 0
};
addrbank a3000lmem_bank = {
a3000lmem_lget, a3000lmem_wget, a3000lmem_bget,
a3000lmem_lput, a3000lmem_wput, a3000lmem_bput,
a3000lmem_xlate, a3000lmem_check, NULL, _T("ramsey_low"), _T("RAMSEY memory (low)"),
a3000lmem_lget, a3000lmem_wget,
ABFLAG_RAM | ABFLAG_THREADSAFE, 0, 0
};
addrbank a3000hmem_bank = {
a3000hmem_lget, a3000hmem_wget, a3000hmem_bget,
a3000hmem_lput, a3000hmem_wput, a3000hmem_bput,
a3000hmem_xlate, a3000hmem_check, NULL, _T("ramsey_high"), _T("RAMSEY memory (high)"),
a3000hmem_lget, a3000hmem_wget,
ABFLAG_RAM | ABFLAG_THREADSAFE, 0, 0
};
addrbank kickmem_bank = {
kickmem_lget, kickmem_wget, kickmem_bget,
kickmem_lput, kickmem_wput, kickmem_bput,
kickmem_xlate, kickmem_check, NULL, _T("kick"), _T("Kickstart ROM"),
kickmem_lget, kickmem_wget,
ABFLAG_ROM | ABFLAG_THREADSAFE, 0, S_WRITE
};
addrbank extendedkickmem_bank = {
extendedkickmem_lget, extendedkickmem_wget, extendedkickmem_bget,
extendedkickmem_lput, extendedkickmem_wput, extendedkickmem_bput,
extendedkickmem_xlate, extendedkickmem_check, NULL, NULL, _T("Extended Kickstart ROM"),
extendedkickmem_lget, extendedkickmem_wget,
ABFLAG_ROM | ABFLAG_THREADSAFE, 0, S_WRITE
};
addrbank extendedkickmem2_bank = {
extendedkickmem2_lget, extendedkickmem2_wget, extendedkickmem2_bget,
extendedkickmem2_lput, extendedkickmem2_wput, extendedkickmem2_bput,
extendedkickmem2_xlate, extendedkickmem2_check, NULL, _T("rom_a8"), _T("Extended 2nd Kickstart ROM"),
extendedkickmem2_lget, extendedkickmem2_wget,
ABFLAG_ROM | ABFLAG_THREADSAFE, 0, S_WRITE
};
addrbank fakeuaebootrom_bank = {
fakeuaebootrom_lget, fakeuaebootrom_wget, fakeuaebootrom_bget,
fakeuaebootrom_lput, fakeuaebootrom_wput, fakeuaebootrom_bput,
fakeuaebootrom_xlate, fakeuaebootrom_check, NULL, _T("*"), _T("fakeuaerom"),
fakeuaebootrom_lget, fakeuaebootrom_wget,
ABFLAG_RAM | ABFLAG_THREADSAFE, 0, 0
};
MEMORY_FUNCTIONS(custmem1);
MEMORY_FUNCTIONS(custmem2);
addrbank custmem1_bank = {
custmem1_lget, custmem1_wget, custmem1_bget,
custmem1_lput, custmem1_wput, custmem1_bput,
custmem1_xlate, custmem1_check, NULL, _T("custmem1"), _T("Non-autoconfig RAM #1"),
custmem1_lget, custmem1_wget,
ABFLAG_RAM | ABFLAG_THREADSAFE, 0, 0
};
addrbank custmem2_bank = {
custmem2_lget, custmem2_wget, custmem2_bget,
custmem2_lput, custmem2_wput, custmem2_bput,
custmem2_xlate, custmem2_check, NULL, _T("custmem2"), _T("Non-autoconfig RAM #2"),
custmem2_lget, custmem2_wget,
ABFLAG_RAM | ABFLAG_THREADSAFE, 0, 0
};
static const uae_char *kickstring = "exec.library";
static int read_kickstart (struct zfile *f, uae_u8 *mem, int size, int dochecksum, int noalias)
{
uae_char buffer[20];
int i, j, oldpos;
int cr = 0, kickdisk = 0;
if (size < 0) {
zfile_fseek (f, 0, SEEK_END);
size = zfile_ftell (f) & ~0x3ff;
zfile_fseek (f, 0, SEEK_SET);
}
oldpos = zfile_ftell (f);
i = zfile_fread (buffer, 1, 11, f);
if (!memcmp(buffer, "KICK", 4)) {
zfile_fseek (f, 512, SEEK_SET);
kickdisk = 1;
} else if (memcmp ((uae_char*)buffer, "AMIROMTYPE1", 11) != 0) {
zfile_fseek (f, oldpos, SEEK_SET);
} else {
cloanto_rom = 1;
cr = 1;
}
memset (mem, 0, size);
if (size >= 131072) {
for (i = 0; i < 8; i++) {
mem[size - 16 + i * 2 + 1] = 0x18 + i;
}
mem[size - 20] = size >> 24;
mem[size - 19] = size >> 16;
mem[size - 18] = size >> 8;
mem[size - 17] = size >> 0;
}
i = zfile_fread (mem, 1, size, f);
if (kickdisk && i > ROM_SIZE_256)
i = ROM_SIZE_256;
if (i < size - 20)
kickstart_fix_checksum (mem, size);
j = 1;
while (j < i)
j <<= 1;
i = j;
if (!noalias && i == size / 2)
memcpy (mem + size / 2, mem, size / 2);
if (cr) {
if(!decode_rom (mem, size, cr, i))
return 0;
}
if (size <= 256)
return size;
for (j = 0; j < 256 && i >= ROM_SIZE_256; j++) {
if (!memcmp (mem + j, kickstring, strlen (kickstring) + 1))
break;
}
if (j == 256 || i < ROM_SIZE_256)
dochecksum = 0;
if (dochecksum)
kickstart_checksum (mem, size);
return i;
}
static bool load_extendedkickstart (const TCHAR *romextfile, int type)
{
struct zfile *f;
int size, off;
bool ret = false;
if (_tcslen (romextfile) == 0)
return false;
f = read_rom_name (romextfile);
if (!f) {
notify_user (NUMSG_NOEXTROM);
return false;
}
zfile_fseek (f, 0, SEEK_END);
size = zfile_ftell (f);
extendedkickmem_bank.reserved_size = ROM_SIZE_512;
off = 0;
if (type == 0) {
if (currprefs.cs_cd32cd) {
extendedkickmem_type = EXTENDED_ROM_CD32;
} else if (size > 300000) {
extendedkickmem_type = EXTENDED_ROM_CD32;
}
} else {
extendedkickmem_type = type;
}
if (extendedkickmem_type) {
zfile_fseek (f, off, SEEK_SET);
switch (extendedkickmem_type) {
case EXTENDED_ROM_CD32:
extendedkickmem_bank.label = _T("rom_e0");
mapped_malloc (&extendedkickmem_bank);
extendedkickmem_bank.start = 0xe00000;
break;
}
if (extendedkickmem_bank.baseaddr) {
read_kickstart (f, extendedkickmem_bank.baseaddr, extendedkickmem_bank.allocated_size, 0, 1);
extendedkickmem_bank.mask = extendedkickmem_bank.allocated_size - 1;
ret = true;
}
}
zfile_fclose (f);
return ret;
}
/* disable incompatible drivers */
static int patch_residents (uae_u8 *kickmemory, int size)
{
int i, j, patched = 0;
const uae_char *residents[] = { "NCR scsi.device", NULL };
// "scsi.device", "carddisk.device", "card.resource" };
uaecptr base = size == ROM_SIZE_512 ? 0xf80000 : 0xfc0000;
for (i = 0; i < size - 100; i++) {
if (kickmemory[i] == 0x4a && kickmemory[i + 1] == 0xfc) {
uaecptr addr;
addr = (kickmemory[i + 2] << 24) | (kickmemory[i + 3] << 16) | (kickmemory[i + 4] << 8) | (kickmemory[i + 5] << 0);
if (addr != i + base)
continue;
addr = (kickmemory[i + 14] << 24) | (kickmemory[i + 15] << 16) | (kickmemory[i + 16] << 8) | (kickmemory[i + 17] << 0);
if (addr >= base && addr < base + size) {
j = 0;
while (residents[j]) {
if (!memcmp (residents[j], kickmemory + addr - base, strlen (residents[j]) + 1)) {
TCHAR *s = au (residents[j]);
write_log (_T("KSPatcher: '%s' at %08X disabled\n"), s, i + base);
xfree (s);
kickmemory[i] = 0x4b; /* destroy RTC_MATCHWORD */
patched++;
break;
}
j++;
}
}
}
}
return patched;
}
static void patch_kick(void)
{
int patched = 0;
patched += patch_residents (kickmem_bank.baseaddr, kickmem_bank.allocated_size);
if (extendedkickmem_bank.baseaddr) {
patched += patch_residents (extendedkickmem_bank.baseaddr, extendedkickmem_bank.allocated_size);
if (patched)
kickstart_fix_checksum (extendedkickmem_bank.baseaddr, extendedkickmem_bank.allocated_size);
}
if (patched)
kickstart_fix_checksum (kickmem_bank.baseaddr, kickmem_bank.allocated_size);
}
extern unsigned char arosrom[];
extern unsigned int arosrom_len;
static bool load_kickstart_replacement (void)
{
struct zfile *f;
f = zfile_fopen_data (_T("aros.gz"), arosrom_len, arosrom);
if (!f)
return false;
f = zfile_gunzip (f);
if (!f)
return false;
extendedkickmem_bank.reserved_size = ROM_SIZE_512;
extendedkickmem_bank.mask = ROM_SIZE_512 - 1;
extendedkickmem_bank.label = _T("rom_e0");
extendedkickmem_type = EXTENDED_ROM_KS;
mapped_malloc (&extendedkickmem_bank);
read_kickstart (f, extendedkickmem_bank.baseaddr, ROM_SIZE_512, 0, 1);
kickmem_bank.reserved_size = ROM_SIZE_512;
kickmem_bank.mask = ROM_SIZE_512 - 1;
read_kickstart (f, kickmem_bank.baseaddr, ROM_SIZE_512, 1, 0);
zfile_fclose (f);
// if 68000-68020 config without any other fast ram with m68k aros: enable special extra RAM.
if (currprefs.cpu_model <= 68020 &&
currprefs.cachesize == 0 &&
currprefs.fastmem[0].size == 0 &&
currprefs.z3fastmem[0].size == 0 &&
currprefs.mbresmem_high_size == 0 &&
currprefs.mbresmem_low_size == 0) {
changed_prefs.custom_memory_addrs[0] = currprefs.custom_memory_addrs[0] = 0xa80000;
changed_prefs.custom_memory_sizes[0] = currprefs.custom_memory_sizes[0] = 512 * 1024;
changed_prefs.custom_memory_mask[0] = currprefs.custom_memory_mask[0] = 0;
changed_prefs.custom_memory_addrs[1] = currprefs.custom_memory_addrs[1] = 0xb00000;
changed_prefs.custom_memory_sizes[1] = currprefs.custom_memory_sizes[1] = 512 * 1024;
changed_prefs.custom_memory_mask[1] = currprefs.custom_memory_mask[1] = 0;
}
return true;
}
static struct zfile *get_kickstart_filehandle(struct uae_prefs *p)
{
struct zfile *f;
TCHAR tmprom[MAX_DPATH], tmprom2[MAX_DPATH];
f = read_rom_name (p->romfile);
_tcscpy (tmprom, p->romfile);
if (f == NULL) {
_stprintf (tmprom2, _T("%s%s"), start_path_data, p->romfile);
f = rom_fopen (tmprom2, _T("rb"), ZFD_NORMAL);
if (f == NULL) {
_stprintf (p->romfile, _T("%sroms/kick.rom"), start_path_data);
f = rom_fopen (p->romfile, _T("rb"), ZFD_NORMAL);
if (f == NULL) {
_stprintf (p->romfile, _T("%skick.rom"), start_path_data);
f = rom_fopen(p->romfile, _T("rb"), ZFD_NORMAL);
if (f == NULL)
f = read_rom_name_guess (tmprom);
}
} else {
_tcscpy (p->romfile, tmprom2);
}
}
return f;
}
static int load_kickstart (void)
{
TCHAR tmprom[MAX_DPATH];
cloanto_rom = 0;
if (!_tcscmp (currprefs.romfile, _T(":AROS"))) {
return load_kickstart_replacement ();
}
_tcscpy(tmprom, currprefs.romfile);
struct zfile *f = get_kickstart_filehandle(&currprefs);
addkeydir (currprefs.romfile);
if (f == NULL) /* still no luck */
goto err;
if (f != NULL) {
int filesize, size, maxsize;
int kspos = ROM_SIZE_512;
int extpos = 0;
maxsize = ROM_SIZE_512;
zfile_fseek (f, 0, SEEK_END);
filesize = zfile_ftell (f);
zfile_fseek (f, 0, SEEK_SET);
if (filesize == 1760 * 512) {
filesize = ROM_SIZE_256;
maxsize = ROM_SIZE_256;
}
if (filesize == ROM_SIZE_512 + 8) {
/* GVP 0xf0 kickstart */
zfile_fseek (f, 8, SEEK_SET);
}
if (filesize >= ROM_SIZE_512 * 2) {
struct romdata *rd = getromdatabyzfile(f);
zfile_fseek (f, kspos, SEEK_SET);
}
if (filesize >= ROM_SIZE_512 * 4) {
kspos = ROM_SIZE_512 * 3;
extpos = 0;
zfile_fseek (f, kspos, SEEK_SET);
}
size = read_kickstart (f, kickmem_bank.baseaddr, maxsize, 1, 0);
if (size == 0)
goto err;
kickmem_bank.mask = size - 1;
kickmem_bank.reserved_size = size;
if (filesize >= ROM_SIZE_512 * 2 && !extendedkickmem_type) {
extendedkickmem_bank.reserved_size = ROM_SIZE_512;
extendedkickmem_type = EXTENDED_ROM_KS;
extendedkickmem_bank.label = _T("rom_e0");
extendedkickmem_bank.start = 0xe00000;
mapped_malloc (&extendedkickmem_bank);
zfile_fseek (f, extpos, SEEK_SET);
read_kickstart (f, extendedkickmem_bank.baseaddr, extendedkickmem_bank.allocated_size, 0, 1);
extendedkickmem_bank.mask = extendedkickmem_bank.allocated_size - 1;
}
if (filesize > ROM_SIZE_512 * 2) {
extendedkickmem2_bank.reserved_size = ROM_SIZE_512 * 2;
mapped_malloc (&extendedkickmem2_bank);
zfile_fseek (f, extpos + ROM_SIZE_512, SEEK_SET);
read_kickstart (f, extendedkickmem2_bank.baseaddr, ROM_SIZE_512, 0, 1);
zfile_fseek (f, extpos + ROM_SIZE_512 * 2, SEEK_SET);
read_kickstart (f, extendedkickmem2_bank.baseaddr + ROM_SIZE_512, ROM_SIZE_512, 0, 1);
extendedkickmem2_bank.mask = extendedkickmem2_bank.allocated_size - 1;
extendedkickmem2_bank.start = 0xa80000;
}
}
kickstart_version = (kickmem_bank.baseaddr[12] << 8) | kickmem_bank.baseaddr[13];
if (kickstart_version == 0xffff) {
// 1.0-1.1 and older
kickstart_version = (kickmem_bank.baseaddr[16] << 8) | kickmem_bank.baseaddr[17];
if (kickstart_version > 33)
kickstart_version = 0;
}
zfile_fclose (f);
return 1;
err:
_tcscpy (currprefs.romfile, tmprom);
zfile_fclose (f);
return 0;
}
void init_mem_banks (void)
{
// unsigned so i << 16 won't overflow to negative when i >= 32768
for (unsigned int i = 0; i < MEMORY_BANKS; i++)
mem_banks[i] = &dummy_bank;
}
static bool singlebit (uae_u32 v)
{
while (v && !(v & 1))
v >>= 1;
return (v & ~1) == 0;
}
static void allocate_memory (void)
{
mapped_free(&fakeuaebootrom_bank);
if (chipmem_bank.reserved_size != currprefs.chipmem_size) {
int memsize;
mapped_free (&chipmem_bank);
chipmem_bank.flags &= ~ABFLAG_NOALLOC;
if (currprefs.chipmem_size > 2 * 1024 * 1024) {
free_fastmemory (0);
}
memsize = chipmem_bank.reserved_size = currprefs.chipmem_size;
chipmem_full_mask = chipmem_bank.mask = chipmem_bank.reserved_size - 1;
chipmem_bank.start = chipmem_start_addr;
if (!currprefs.cachesize && memsize < 0x100000)
memsize = 0x100000;
if (memsize > 0x100000 && memsize < 0x200000)
memsize = 0x200000;
chipmem_bank.reserved_size = memsize;
mapped_malloc (&chipmem_bank);
chipmem_bank.reserved_size = currprefs.chipmem_size;
chipmem_bank.allocated_size = currprefs.chipmem_size;
if (chipmem_bank.baseaddr == 0) {
write_log (_T("Fatal error: out of memory for chipmem.\n"));
chipmem_bank.reserved_size = 0;
} else {
need_hardreset = true;
if (memsize > chipmem_bank.allocated_size)
memset (chipmem_bank.baseaddr + chipmem_bank.allocated_size, 0xff, memsize - chipmem_bank.allocated_size);
}
currprefs.chipset_mask = changed_prefs.chipset_mask;
chipmem_full_mask = chipmem_bank.allocated_size - 1;
if (!currprefs.cachesize) {
if (currprefs.chipset_mask & CSMASK_ECS_AGNUS) {
if (chipmem_bank.allocated_size < 0x100000)
chipmem_full_mask = 0x100000 - 1;
if (chipmem_bank.allocated_size > 0x100000 && chipmem_bank.allocated_size < 0x200000)
chipmem_full_mask = chipmem_bank.mask = 0x200000 - 1;
}
}
}
if (bogomem_bank.reserved_size != currprefs.bogomem_size) {
mapped_free (&bogomem_bank);
bogomem_bank.reserved_size = 0;
if(currprefs.bogomem_size > 0x1c0000)
currprefs.bogomem_size = 0x1c0000;
if (currprefs.bogomem_size > 0x180000 && ((changed_prefs.chipset_mask & CSMASK_AGA) || (currprefs.cpu_model >= 68020)))
currprefs.bogomem_size = 0x180000;
bogomem_bank.reserved_size = currprefs.bogomem_size;
if (bogomem_bank.reserved_size >= 0x180000)
bogomem_bank.reserved_size = 0x200000;
bogomem_bank.mask = bogomem_bank.reserved_size - 1;
bogomem_bank.start = bogomem_start_addr;
if (bogomem_bank.reserved_size) {
if (!mapped_malloc (&bogomem_bank)) {
write_log (_T("Out of memory for bogomem.\n"));
bogomem_bank.reserved_size = 0;
}
}
need_hardreset = true;
}
if (a3000lmem_bank.reserved_size != currprefs.mbresmem_low_size) {
mapped_free (&a3000lmem_bank);
a3000lmem_bank.reserved_size = currprefs.mbresmem_low_size;
a3000lmem_bank.mask = a3000lmem_bank.reserved_size - 1;
a3000lmem_bank.start = 0x08000000 - a3000lmem_bank.reserved_size;
if (a3000lmem_bank.reserved_size) {
if (!mapped_malloc (&a3000lmem_bank)) {
write_log (_T("Out of memory for a3000lowmem.\n"));
a3000lmem_bank.reserved_size = 0;
}
}
need_hardreset = true;
}
if (a3000hmem_bank.reserved_size != currprefs.mbresmem_high_size) {
mapped_free (&a3000hmem_bank);
a3000hmem_bank.reserved_size = currprefs.mbresmem_high_size;
a3000hmem_bank.mask = a3000hmem_bank.reserved_size - 1;
a3000hmem_bank.start = 0x08000000;
if (a3000hmem_bank.reserved_size) {
if (!mapped_malloc (&a3000hmem_bank)) {
write_log (_T("Out of memory for a3000highmem.\n"));
a3000hmem_bank.reserved_size = 0;
}
}
need_hardreset = true;
}
if (custmem1_bank.reserved_size != currprefs.custom_memory_sizes[0]) {
mapped_free (&custmem1_bank);
custmem1_bank.reserved_size = currprefs.custom_memory_sizes[0];
// custmem1 and 2 can have non-power of 2 size so only set correct mask if size is power of 2.
custmem1_bank.mask = singlebit (custmem1_bank.reserved_size) ? custmem1_bank.reserved_size - 1 : -1;
custmem1_bank.start = currprefs.custom_memory_addrs[0];
if (custmem1_bank.reserved_size) {
if (!mapped_malloc (&custmem1_bank))
custmem1_bank.reserved_size = 0;
}
}
if (custmem2_bank.reserved_size != currprefs.custom_memory_sizes[1]) {
mapped_free (&custmem2_bank);
custmem2_bank.reserved_size = currprefs.custom_memory_sizes[1];
custmem2_bank.mask = singlebit (custmem2_bank.reserved_size) ? custmem2_bank.reserved_size - 1 : -1;
custmem2_bank.start = currprefs.custom_memory_addrs[1];
if (custmem2_bank.reserved_size) {
if (!mapped_malloc (&custmem2_bank))
custmem2_bank.reserved_size = 0;
}
}
if (savestate_state == STATE_RESTORE) {
if (bootrom_filepos) {
protect_roms (false);
restore_ram (bootrom_filepos, rtarea_bank.baseaddr);
protect_roms (true);
}
restore_ram (chip_filepos, chipmem_bank.baseaddr);
if (bogomem_bank.allocated_size > 0)
restore_ram (bogo_filepos, bogomem_bank.baseaddr);
if (a3000lmem_bank.allocated_size > 0)
restore_ram (a3000lmem_filepos, a3000lmem_bank.baseaddr);
if (a3000hmem_bank.allocated_size > 0)
restore_ram (a3000hmem_filepos, a3000hmem_bank.baseaddr);
}
bootrom_filepos = 0;
chip_filepos = 0;
bogo_filepos = 0;
a3000lmem_filepos = 0;
a3000hmem_filepos = 0;
}
void map_overlay (int chip)
{
int size;
addrbank *cb;
int currPC = m68k_getpc();
size = chipmem_bank.allocated_size >= 0x180000 ? (chipmem_bank.allocated_size >> 16) : 32;
cb = &chipmem_bank;
if (chip) {
map_banks (&dummy_bank, 0, size, 0);
map_banks (cb, 0, size, chipmem_bank.allocated_size);
} else {
addrbank *rb = NULL;
if (size < 32)
size = 32;
cb = &get_mem_bank (0xf00000);
if (!rb && cb && (cb->flags & ABFLAG_ROM) && get_word (0xf00000) == 0x1114)
rb = cb;
cb = &get_mem_bank (0xe00000);
if (!rb && cb && (cb->flags & ABFLAG_ROM) && get_word (0xe00000) == 0x1114)
rb = cb;
if (!rb)
rb = &kickmem_bank;
map_banks (rb, 0, size, 0x80000);
}
if (!isrestore () && valid_address (regs.pc, 4))
m68k_setpc_normal (currPC);
}
static void map_banks_set(addrbank *bank, int start, int size, int realsize)
{
map_banks(bank, start, size, realsize);
}
void memory_clear (void)
{
mem_hardreset = 0;
if (savestate_state == STATE_RESTORE)
return;
if (chipmem_bank.baseaddr)
memset (chipmem_bank.baseaddr, 0, chipmem_bank.allocated_size);
if (bogomem_bank.baseaddr)
memset (bogomem_bank.baseaddr, 0, bogomem_bank.allocated_size);
if (a3000lmem_bank.baseaddr)
memset(a3000lmem_bank.baseaddr, 0, a3000lmem_bank.allocated_size);
if (a3000hmem_bank.baseaddr)
memset(a3000hmem_bank.baseaddr, 0, a3000hmem_bank.allocated_size);
expansion_clear ();
}
static void restore_roms(void)
{
protect_roms (false);
write_log (_T("ROM loader.. (%s)\n"), currprefs.romfile);
kickstart_rom = 1;
memcpy (currprefs.romfile, changed_prefs.romfile, sizeof currprefs.romfile);
memcpy (currprefs.romextfile, changed_prefs.romextfile, sizeof currprefs.romextfile);
need_hardreset = true;
mapped_free (&extendedkickmem_bank);
mapped_free (&extendedkickmem2_bank);
extendedkickmem_bank.reserved_size = 0;
extendedkickmem2_bank.reserved_size = 0;
extendedkickmem_type = 0;
load_extendedkickstart (currprefs.romextfile, 0);
kickmem_bank.mask = ROM_SIZE_512 - 1;
if (!load_kickstart ()) {
if (_tcslen (currprefs.romfile) > 0) {
error_log (_T("Failed to open '%s'\n"), currprefs.romfile);
notify_user (NUMSG_NOROM);
}
load_kickstart_replacement ();
} else {
struct romdata *rd = getromdatabydata (kickmem_bank.baseaddr, kickmem_bank.reserved_size);
if (rd) {
write_log (_T("Known ROM '%s' loaded\n"), rd->name);
if ((rd->cpu & 8) && changed_prefs.cpu_model < 68030) {
notify_user (NUMSG_KS68030PLUS);
uae_restart (-1, NULL);
} else if ((rd->cpu & 3) == 3 && changed_prefs.cpu_model != 68030) {
notify_user (NUMSG_KS68030);
uae_restart (-1, NULL);
} else if ((rd->cpu & 3) == 1 && changed_prefs.cpu_model < 68020) {
notify_user (NUMSG_KS68EC020);
uae_restart (-1, NULL);
} else if ((rd->cpu & 3) == 2 && (changed_prefs.cpu_model < 68020 || changed_prefs.address_space_24)) {
notify_user (NUMSG_KS68020);
uae_restart (-1, NULL);
}
if (rd->cloanto)
cloanto_rom = 1;
kickstart_rom = 0;
if ((rd->type & (ROMTYPE_SPECIALKICK | ROMTYPE_KICK)) == ROMTYPE_KICK)
kickstart_rom = 1;
if ((rd->cpu & 4) && currprefs.cs_compatible) {
/* A4000 ROM = need ramsey, gary and ide */
if (currprefs.cs_ramseyrev < 0)
changed_prefs.cs_ramseyrev = currprefs.cs_ramseyrev = 0x0f;
changed_prefs.cs_fatgaryrev = currprefs.cs_fatgaryrev = 0;
if (currprefs.cs_ide != IDE_A4000)
changed_prefs.cs_ide = currprefs.cs_ide = -1;
}
} else {
write_log (_T("Unknown ROM '%s' loaded\n"), currprefs.romfile);
}
}
patch_kick ();
write_log (_T("ROM loader end\n"));
protect_roms (true);
}
bool read_kickstart_version(struct uae_prefs *p)
{
kickstart_version = 0;
cloanto_rom = 0;
struct zfile *z = get_kickstart_filehandle(p);
if (!z)
return false;
uae_u8 mem[32] = { 0 };
read_kickstart(z, mem, sizeof mem, 0, 0);
zfile_fclose(z);
kickstart_version = (mem[12] << 8) | mem[13];
if (kickstart_version == 0xffff) {
// 1.0-1.1 and older
kickstart_version = (mem[16] << 8) | mem[17];
if (kickstart_version > 33)
kickstart_version = 0;
}
write_log(_T("KS ver = %04x\n"), kickstart_version);
return true;
}
void memory_reset (void)
{
int bnk, bnk_end;
bool gayleorfatgary;
need_hardreset = false;
/* Use changed_prefs, as m68k_reset is called later. */
if (last_address_space_24 != changed_prefs.address_space_24)
need_hardreset = true;
last_address_space_24 = changed_prefs.address_space_24;
if (mem_hardreset > 2)
memory_init ();
be_cnt = be_recursive = 0;
currprefs.chipmem_size = changed_prefs.chipmem_size;
currprefs.bogomem_size = changed_prefs.bogomem_size;
currprefs.mbresmem_low_size = changed_prefs.mbresmem_low_size;
currprefs.mbresmem_high_size = changed_prefs.mbresmem_high_size;
currprefs.cs_ksmirror_e0 = changed_prefs.cs_ksmirror_e0;
currprefs.cs_ksmirror_a8 = changed_prefs.cs_ksmirror_a8;
currprefs.cs_ciaoverlay = changed_prefs.cs_ciaoverlay;
currprefs.cs_ide = changed_prefs.cs_ide;
currprefs.cs_fatgaryrev = changed_prefs.cs_fatgaryrev;
currprefs.cs_ramseyrev = changed_prefs.cs_ramseyrev;
gayleorfatgary = ((currprefs.chipset_mask & CSMASK_AGA) || currprefs.cs_pcmcia || currprefs.cs_ide > 0) && !currprefs.cs_cd32cd;
init_mem_banks ();
allocate_memory ();
if (mem_hardreset > 1
|| _tcscmp (currprefs.romfile, changed_prefs.romfile) != 0
|| _tcscmp (currprefs.romextfile, changed_prefs.romextfile) != 0)
{
restore_roms();
}
map_banks (&custom_bank, 0xC0, 0xE0 - 0xC0, 0);
map_banks (&cia_bank, 0xA0, 32, 0);
if (currprefs.cs_rtc != 3)
/* D80000 - DDFFFF not mapped (A1000 or A2000 = custom chips) */
map_banks (&dummy_bank, 0xD8, 6, 0);
/* map "nothing" to 0x200000 - 0x9FFFFF (0xBEFFFF if Gayle or Fat Gary) */
bnk = chipmem_bank.allocated_size >> 16;
if (bnk < 0x20 + (currprefs.fastmem[0].size >> 16))
bnk = 0x20 + (currprefs.fastmem[0].size >> 16);
bnk_end = currprefs.cs_cd32cd ? 0xBE : (gayleorfatgary ? 0xBF : 0xA0);
map_banks (&dummy_bank, bnk, bnk_end - bnk, 0);
if (gayleorfatgary) {
// a3000 or a4000 = custom chips from 0xc0 to 0xd0
if (currprefs.cs_ide == IDE_A4000)
map_banks (&dummy_bank, 0xd0, 8, 0);
else
map_banks (&dummy_bank, 0xc0, 0xd8 - 0xc0, 0);
} else if (currprefs.cs_cd32cd) {
// CD32: 0xc0 to 0xd0
map_banks(&dummy_bank, 0xd0, 8, 0);
// strange 64k custom mirror
map_banks(&custom_bank, 0xb9, 1, 0);
}
if (bogomem_bank.baseaddr) {
int t = currprefs.bogomem_size >> 16;
if (t > 0x1C)
t = 0x1C;
if (t > 0x18 && ((currprefs.chipset_mask & CSMASK_AGA) || (currprefs.cpu_model >= 68020 && !currprefs.address_space_24)))
t = 0x18;
map_banks (&bogomem_bank, 0xC0, t, 0);
}
if (currprefs.cs_ide || currprefs.cs_pcmcia) {
if (currprefs.cs_ide == IDE_A600A1200 || currprefs.cs_pcmcia) {
map_banks (&gayle_bank, 0xD8, 6, 0);
map_banks (&gayle2_bank, 0xDD, 2, 0);
}
gayle_map_pcmcia ();
if (currprefs.cs_ide == IDE_A4000)
map_banks (&gayle_bank, 0xDD, 1, 0);
if (currprefs.cs_ide < 0 && !currprefs.cs_pcmcia)
map_banks (&gayle_bank, 0xD8, 6, 0);
if (currprefs.cs_ide < 0)
map_banks (&gayle_bank, 0xDD, 1, 0);
}
if (currprefs.cs_rtc == 3) // A2000 clock
map_banks (&clock_bank, 0xD8, 4, 0);
if (currprefs.cs_rtc == 1 || currprefs.cs_rtc == 2)
map_banks (&clock_bank, 0xDC, 1, 0);
else if (currprefs.cs_ksmirror_a8 || currprefs.cs_ide > 0 || currprefs.cs_pcmcia)
map_banks (&clock_bank, 0xDC, 1, 0); /* none clock */
if (currprefs.cs_fatgaryrev >= 0 || currprefs.cs_ramseyrev >= 0)
map_banks (&mbres_bank, 0xDE, 1, 0);
#ifdef CD32
if (currprefs.cs_cd32c2p || currprefs.cs_cd32cd || currprefs.cs_cd32nvram) {
map_banks (&akiko_bank, AKIKO_BASE >> 16, 1, 0);
map_banks (&gayle2_bank, 0xDD, 2, 0);
}
#endif
if (a3000lmem_bank.baseaddr)
map_banks(&a3000lmem_bank, a3000lmem_bank.start >> 16, a3000lmem_bank.allocated_size >> 16, 0);
if (a3000hmem_bank.baseaddr)
map_banks(&a3000hmem_bank, a3000hmem_bank.start >> 16, a3000hmem_bank.allocated_size >> 16, 0);
map_banks_set(&kickmem_bank, 0xF8, 8, 0);
/* map beta Kickstarts at 0x200000/0xC00000/0xF00000 */
if (kickmem_bank.baseaddr[0] == 0x11 && kickmem_bank.baseaddr[2] == 0x4e && kickmem_bank.baseaddr[3] == 0xf9 && kickmem_bank.baseaddr[4] == 0x00) {
uae_u32 addr = kickmem_bank.baseaddr[5];
if (addr == 0x20 && currprefs.chipmem_size <= 0x200000 && currprefs.fastmem[0].size == 0)
map_banks_set(&kickmem_bank, addr, 8, 0);
if (addr == 0xC0 && currprefs.bogomem_size == 0)
map_banks_set(&kickmem_bank, addr, 8, 0);
if (addr == 0xF0)
map_banks_set(&kickmem_bank, addr, 8, 0);
}
#ifdef AUTOCONFIG
expansion_map();
#endif
/* Map the chipmem into all of the lower 8MB */
map_overlay (1);
switch (extendedkickmem_type) {
case EXTENDED_ROM_KS:
map_banks_set(&extendedkickmem_bank, 0xE0, 8, 0);
break;
#ifdef CD32
case EXTENDED_ROM_CD32:
map_banks_set(&extendedkickmem_bank, 0xE0, 8, 0);
break;
#endif
}
#ifdef AUTOCONFIG
if (need_uae_boot_rom (&currprefs))
map_banks_set(&rtarea_bank, rtarea_base >> 16, 1, 0);
#endif
if ((cloanto_rom || currprefs.cs_ksmirror_e0) && !extendedkickmem_type) {
map_banks (&kickmem_bank, 0xE0, 8, 0);
}
if (currprefs.cs_ksmirror_a8) {
if (extendedkickmem2_bank.allocated_size) {
map_banks_set(&extendedkickmem2_bank, 0xa8, 16, 0);
} else {
struct romdata *rd = getromdatabypath (currprefs.cartfile);
if (!rd || rd->id != 63) {
if (extendedkickmem_type == EXTENDED_ROM_CD32 || extendedkickmem_type == EXTENDED_ROM_KS)
map_banks (&extendedkickmem_bank, 0xb0, 8, 0);
else
map_banks (&kickmem_bank, 0xb0, 8, 0);
map_banks (&kickmem_bank, 0xa8, 8, 0);
}
}
}
#ifdef ACTION_REPLAY
action_replay_memory_reset ();
#endif
for (int i = 0; i < 2; i++) {
if (currprefs.custom_memory_sizes[i]) {
map_banks (i == 0 ? &custmem1_bank : &custmem2_bank,
currprefs.custom_memory_addrs[i] >> 16,
currprefs.custom_memory_sizes[i] >> 16, 0);
if (currprefs.custom_memory_mask[i]) {
for (int j = currprefs.custom_memory_addrs[i]; j & currprefs.custom_memory_mask[i]; j += currprefs.custom_memory_sizes[i]) {
map_banks(i == 0 ? &custmem1_bank : &custmem2_bank, j >> 16, currprefs.custom_memory_sizes[i] >> 16, 0);
}
}
}
}
if (mem_hardreset) {
memory_clear ();
}
write_log (_T("memory init end\n"));
}
void memory_init (void)
{
init_mem_banks ();
virtualdevice_init ();
chipmem_bank.reserved_size = 0;
bogomem_bank.reserved_size = 0;
kickmem_bank.baseaddr = NULL;
extendedkickmem_bank.baseaddr = NULL;
extendedkickmem_bank.reserved_size = 0;
extendedkickmem2_bank.baseaddr = NULL;
extendedkickmem2_bank.reserved_size = 0;
extendedkickmem_type = 0;
chipmem_bank.baseaddr = 0;
a3000lmem_bank.reserved_size = a3000hmem_bank.reserved_size = 0;
a3000lmem_bank.baseaddr = a3000hmem_bank.baseaddr = NULL;
bogomem_bank.baseaddr = NULL;
custmem1_bank.reserved_size = custmem2_bank.reserved_size = 0;
custmem1_bank.baseaddr = NULL;
custmem2_bank.baseaddr = NULL;
kickmem_bank.reserved_size = ROM_SIZE_512;
mapped_malloc (&kickmem_bank);
memset (kickmem_bank.baseaddr, 0, ROM_SIZE_512);
_tcscpy (currprefs.romfile, _T("<none>"));
currprefs.romextfile[0] = 0;
#ifdef ACTION_REPLAY
action_replay_unload (0);
action_replay_load ();
action_replay_init (1);
#ifdef ACTION_REPLAY_HRTMON
hrtmon_load ();
#endif
#endif
}
void memory_cleanup (void)
{
mapped_free(&a3000lmem_bank);
mapped_free(&a3000hmem_bank);
mapped_free (&bogomem_bank);
mapped_free (&kickmem_bank);
mapped_free (&chipmem_bank);
mapped_free (&custmem1_bank);
mapped_free (&custmem2_bank);
mapped_free(&fakeuaebootrom_bank);
bogomem_bank.baseaddr = NULL;
kickmem_bank.baseaddr = NULL;
a3000lmem_bank.baseaddr = a3000hmem_bank.baseaddr = NULL;
chipmem_bank.baseaddr = NULL;
custmem1_bank.baseaddr = NULL;
custmem2_bank.baseaddr = NULL;
#ifdef ACTION_REPLAY
action_replay_cleanup();
#endif
}
void memory_hardreset (int mode)
{
if (mode + 1 > mem_hardreset)
mem_hardreset = mode + 1;
}
// do not map if it conflicts with custom banks
void map_banks_cond (addrbank *bank, int start, int size, int realsize)
{
for (int i = 0; i < MAX_CUSTOM_MEMORY_ADDRS; i++) {
int cstart = currprefs.custom_memory_addrs[i] >> 16;
if (!cstart)
continue;
int csize = currprefs.custom_memory_sizes[i] >> 16;
if (!csize)
continue;
if (start <= cstart && start + size >= cstart)
return;
if (cstart <= start && (cstart + size >= start || start + size > cstart))
return;
}
map_banks (bank, start, size, realsize);
}
static void map_banks2 (addrbank *bank, int start, int size, int realsize, int quick)
{
int bnr;
unsigned long int hioffs = 0, endhioffs = 0x100;
uae_u32 realstart = start;
flush_icache_hard (3); /* Sure don't want to keep any old mappings around! */
if (!realsize)
realsize = size << 16;
if ((size << 16) < realsize) {
write_log (_T("Broken mapping, size=%x, realsize=%x\nStart is %x\n"),
size, realsize, start);
}
#ifndef ADDRESS_SPACE_24BIT
if (start >= 0x100) {
for (bnr = start; bnr < start + size; bnr++) {
mem_banks[bnr] = bank;
}
return;
}
#endif
if (last_address_space_24)
endhioffs = 0x10000;
#ifdef ADDRESS_SPACE_24BIT
endhioffs = 0x100;
#endif
for (hioffs = 0; hioffs < endhioffs; hioffs += 0x100) {
for (bnr = start; bnr < start + size; bnr++) {
mem_banks[bnr + hioffs] = bank;
}
}
}
void map_banks (addrbank *bank, int start, int size, int realsize)
{
if (start == 0xffffffff)
return;
if (start >= 0x100) {
if (currprefs.address_space_24)
return;
}
map_banks2 (bank, start, size, realsize, 0);
}
bool validate_banks_z3(addrbank *bank, int start, int size)
{
if (start < 0x1000 || size <= 0) {
error_log(_T("Z3 invalid map_banks(%s) start=%08x size=%08x\n"), bank->name, start << 16, size << 16);
cpu_halt(CPU_HALT_AUTOCONFIG_CONFLICT);
return false;
}
if (size > 0x4000 || start + size > 0xf000) {
error_log(_T("Z3 invalid map_banks(%s) start=%08x size=%08x\n"), bank->name, start << 16, size << 16);
return false;
}
for (int i = start; i < start + size; i++) {
addrbank *ab = &get_mem_bank(start << 16);
if (ab != &dummy_bank && ab != bank) {
error_log(_T("Z3 map_banks(%s) attempting to override existing memory bank '%s' at %08x!\n"), bank->name, ab->name, i << 16);
return false;
}
}
return true;
}
void map_banks_z3(addrbank *bank, int start, int size)
{
if (!validate_banks_z3(bank, start, size))
return;
map_banks(bank, start, size, 0);
}
bool validate_banks_z2(addrbank *bank, int start, int size)
{
if (start < 0x20 || (start >= 0xa0 && start < 0xe9) || start >= 0xf0) {
error_log(_T("Z2 map_banks(%s) with invalid start address %08X\n"), bank->name, start << 16);
cpu_halt(CPU_HALT_AUTOCONFIG_CONFLICT);
return false;
}
if (start >= 0xe9) {
if (start + size > 0xf0) {
error_log(_T("Z2 map_banks(%s) with invalid region %08x - %08X\n"), bank->name, start << 16, (start + size) << 16);
cpu_halt(CPU_HALT_AUTOCONFIG_CONFLICT);
return false;
}
} else {
if (start + size > 0xa0) {
error_log(_T("Z2 map_banks(%s) with invalid region %08x - %08X\n"), bank->name, start << 16, (start + size) << 16);
cpu_halt(CPU_HALT_AUTOCONFIG_CONFLICT);
return false;
}
}
if (size <= 0 || size > 0x80) {
error_log(_T("Z2 map_banks(%s) with invalid size %08x\n"), bank->name, size);
cpu_halt(CPU_HALT_AUTOCONFIG_CONFLICT);
return false;
}
for (int i = start; i < start + size; i++) {
addrbank *ab = &get_mem_bank(start << 16);
if (ab != &dummy_bank) {
error_log(_T("Z2 map_banks(%s) attempting to override existing memory bank '%s' at %08x!\n"), bank->name, ab->name, i << 16);
return false;
}
}
return true;
}
void map_banks_z2 (addrbank *bank, int start, int size)
{
if (!validate_banks_z2(bank, start, size))
return;
map_banks (bank, start, size, 0);
}
void map_banks_quick (addrbank *bank, int start, int size, int realsize)
{
map_banks2 (bank, start, size, realsize, 1);
}
#ifdef SAVESTATE
/* memory save/restore code */
uae_u8 *save_bootrom(int *len)
{
if (!uae_boot_rom_type)
return 0;
*len = uae_boot_rom_size;
return rtarea_bank.baseaddr;
}
uae_u8 *save_cram (int *len)
{
*len = chipmem_bank.allocated_size;
return chipmem_bank.baseaddr;
}
uae_u8 *save_bram (int *len)
{
*len = bogomem_bank.allocated_size;
return bogomem_bank.baseaddr;
}
uae_u8 *save_a3000lram (int *len)
{
*len = a3000lmem_bank.allocated_size;
return a3000lmem_bank.baseaddr;
}
uae_u8 *save_a3000hram (int *len)
{
*len = a3000hmem_bank.allocated_size;
return a3000hmem_bank.baseaddr;
}
void restore_bootrom (int len, size_t filepos)
{
bootrom_filepos = filepos;
}
void restore_cram (int len, size_t filepos)
{
chip_filepos = filepos;
changed_prefs.chipmem_size = len;
}
void restore_bram (int len, size_t filepos)
{
bogo_filepos = filepos;
changed_prefs.bogomem_size = len;
}
void restore_a3000lram (int len, size_t filepos)
{
a3000lmem_filepos = filepos;
changed_prefs.mbresmem_low_size = len;
}
void restore_a3000hram (int len, size_t filepos)
{
a3000hmem_filepos = filepos;
changed_prefs.mbresmem_high_size = len;
}
uae_u8 *restore_rom (uae_u8 *src)
{
uae_u32 crc32, mem_start, mem_size, mem_type, version;
TCHAR *s, *romn;
int i, crcdet;
struct romlist *rl = romlist_getit ();
mem_start = restore_u32 ();
mem_size = restore_u32 ();
mem_type = restore_u32 ();
version = restore_u32 ();
crc32 = restore_u32 ();
romn = restore_string ();
crcdet = 0;
for (i = 0; i < romlist_count (); i++) {
if (rl[i].rd->crc32 == crc32 && crc32) {
if (zfile_exists (rl[i].path)) {
switch (mem_type)
{
case 0:
_tcsncpy (changed_prefs.romfile, rl[i].path, 255);
break;
case 1:
_tcsncpy (changed_prefs.romextfile, rl[i].path, 255);
break;
}
write_log (_T("ROM '%s' = '%s'\n"), romn, rl[i].path);
crcdet = 1;
} else {
write_log (_T("ROM '%s' = '%s' invalid rom scanner path!"), romn, rl[i].path);
}
break;
}
}
s = restore_string ();
if (!crcdet) {
if(zfile_exists (s)) {
switch (mem_type)
{
case 0:
_tcsncpy (changed_prefs.romfile, s, 255);
break;
case 1:
_tcsncpy (changed_prefs.romextfile, s, 255);
break;
}
write_log (_T("ROM detected (path) as '%s'\n"), s);
crcdet = 1;
}
}
xfree (s);
if (!crcdet)
write_log (_T("WARNING: ROM '%s' %d.%d (CRC32=%08x %08x-%08x) not found!\n"),
romn, version >> 16, version & 0xffff, crc32, mem_start, mem_start + mem_size - 1);
xfree (romn);
return src;
}
uae_u8 *save_rom (int first, int *len, uae_u8 *dstptr)
{
static int count;
uae_u8 *dst, *dstbak;
uae_u8 *mem_real_start;
uae_u32 version;
TCHAR *path;
int mem_start, mem_size, mem_type, saverom;
int i;
TCHAR tmpname[1000];
version = 0;
saverom = 0;
if (first)
count = 0;
for (;;) {
mem_type = count;
mem_size = 0;
switch (count) {
case 0: /* Kickstart ROM */
mem_start = 0xf80000;
mem_real_start = kickmem_bank.baseaddr;
mem_size = kickmem_bank.allocated_size;
path = currprefs.romfile;
/* 256KB or 512KB ROM? */
for (i = 0; i < mem_size / 2 - 4; i++) {
if (longget (i + mem_start) != longget (i + mem_start + mem_size / 2))
break;
}
if (i == mem_size / 2 - 4) {
mem_size /= 2;
mem_start += ROM_SIZE_256;
}
version = longget (mem_start + 12); /* version+revision */
_stprintf (tmpname, _T("Kickstart %d.%d"), wordget (mem_start + 12), wordget (mem_start + 14));
break;
case 1: /* Extended ROM */
if (!extendedkickmem_type)
break;
mem_start = extendedkickmem_bank.start;
mem_real_start = extendedkickmem_bank.baseaddr;
mem_size = extendedkickmem_bank.allocated_size;
path = currprefs.romextfile;
version = longget (mem_start + 12); /* version+revision */
if (version == 0xffffffff)
version = longget (mem_start + 16);
_stprintf (tmpname, _T("Extended"));
break;
default:
return 0;
}
count++;
if (mem_size)
break;
}
if (dstptr)
dstbak = dst = dstptr;
else
dstbak = dst = xmalloc (uae_u8, 4 + 4 + 4 + 4 + 4 + 256 + 256 + mem_size);
save_u32 (mem_start);
save_u32 (mem_size);
save_u32 (mem_type);
save_u32 (version);
save_u32 (get_crc32 (mem_real_start, mem_size));
save_string (tmpname);
save_string (path);
if (saverom) {
for (i = 0; i < mem_size; i++)
*dst++ = byteget (mem_start + i);
}
*len = dst - dstbak;
return dstbak;
}
#endif /* SAVESTATE */
/* memory helpers */
void memcpyha_safe (uaecptr dst, const uae_u8 *src, int size)
{
if (!addr_valid (_T("memcpyha"), dst, size))
return;
while (size--)
put_byte (dst++, *src++);
}
void memcpyha (uaecptr dst, const uae_u8 *src, int size)
{
while (size--)
put_byte (dst++, *src++);
}
void memcpyah_safe (uae_u8 *dst, uaecptr src, int size)
{
if (!addr_valid (_T("memcpyah"), src, size))
return;
while (size--)
*dst++ = get_byte(src++);
}
void memcpyah (uae_u8 *dst, uaecptr src, int size)
{
while (size--)
*dst++ = get_byte(src++);
}
uae_char *strcpyah_safe (uae_char *dst, uaecptr src, int maxsize)
{
uae_char *res = dst;
uae_u8 b;
dst[0] = 0;
do {
if (!addr_valid (_T("_tcscpyah"), src, 1))
return res;
b = get_byte(src++);
*dst++ = b;
*dst = 0;
maxsize--;
if (maxsize <= 1)
break;
} while (b);
return res;
}
uaecptr strcpyha_safe (uaecptr dst, const uae_char *src)
{
uaecptr res = dst;
uae_u8 b;
do {
if (!addr_valid (_T("_tcscpyha"), dst, 1))
return res;
b = *src++;
put_byte (dst++, b);
} while (b);
return res;
}