mirror of
https://github.com/LIV2/WinUAE.git
synced 2025-12-06 00:12:52 +00:00
277 lines
6.1 KiB
C++
277 lines
6.1 KiB
C++
/*
|
|
* UAE - The Un*x Amiga Emulator
|
|
*
|
|
* A "replacement" for a missing Kickstart
|
|
* Warning! Q&D
|
|
*
|
|
* (c) 1995 Bernd Schmidt
|
|
*/
|
|
|
|
#include "sysconfig.h"
|
|
#include "sysdeps.h"
|
|
|
|
#include "options.h"
|
|
#include "uae.h"
|
|
#include "memory.h"
|
|
#include "custom.h"
|
|
#include "newcpu.h"
|
|
#include "cpu_prefetch.h"
|
|
#include "cia.h"
|
|
#include "disk.h"
|
|
#include "ersatz.h"
|
|
#include "gui.h"
|
|
|
|
#define EOP_INIT 0
|
|
#define EOP_NIMP 1
|
|
#define EOP_SERVEINT 2
|
|
#define EOP_DOIO 3
|
|
#define EOP_OPENLIB 4
|
|
#define EOP_AVAILMEM 5
|
|
#define EOP_ALLOCMEM 6
|
|
#define EOP_ALLOCABS 7
|
|
#define EOP_LOOP 8
|
|
|
|
static int already_failed = 0;
|
|
|
|
void init_ersatz_rom (uae_u8 *data)
|
|
{
|
|
uae_u8 *end = data + 262144 - 16;
|
|
/* cpu emulation uses these now */
|
|
end[1] = 0x18;
|
|
end[3] = 0x19;
|
|
end[5] = 0x1a;
|
|
end[7] = 0x1b;
|
|
end[9] = 0x1c;
|
|
end[11] = 0x1d;
|
|
end[13] = 0x1e;
|
|
end[15] = 0x1f;
|
|
|
|
*data++ = 0x00; *data++ = 0x08; /* initial SP */
|
|
*data++ = 0x00; *data++ = 0x00;
|
|
*data++ = 0x00; *data++ = 0xF8; /* initial PC */
|
|
*data++ = 0x00; *data++ = 0x08;
|
|
|
|
*data++ = 0xFF; *data++ = 0x0D;
|
|
*data++ = 0x00; *data++ = EOP_INIT;
|
|
*data++ = 0xFF; *data++ = 0x0D;
|
|
*data++ = 0x00; *data++ = EOP_NIMP;
|
|
|
|
*data++ = 0xFF; *data++ = 0x0D;
|
|
*data++ = 0x00; *data++ = EOP_LOOP;
|
|
*data++ = 0xFF; *data++ = 0x0D;
|
|
*data++ = 0x00; *data++ = EOP_DOIO;
|
|
|
|
*data++ = 0x4E; *data++ = 0x75;
|
|
*data++ = 0xFF; *data++ = 0x0D;
|
|
*data++ = 0x00; *data++ = EOP_SERVEINT;
|
|
*data++ = 0x4E; *data++ = 0x73;
|
|
|
|
*data++ = 0xFF; *data++ = 0x0D;
|
|
*data++ = 0x00; *data++ = EOP_AVAILMEM;
|
|
*data++ = 0x4E; *data++ = 0x75;
|
|
*data++ = 0xFF; *data++ = 0x0D;
|
|
|
|
*data++ = 0x00; *data++ = EOP_ALLOCMEM;
|
|
*data++ = 0x4E; *data++ = 0x75;
|
|
*data++ = 0xFF; *data++ = 0x0D;
|
|
*data++ = 0x00; *data++ = EOP_ALLOCABS;
|
|
|
|
*data++ = 0x4E; *data++ = 0x75;
|
|
}
|
|
|
|
void ersatz_chipcopy (void)
|
|
{
|
|
/* because CPU emulation is updated and retrieves SP and PC from chip ram */
|
|
memcpy (chipmemory, kickmemory, 256);
|
|
}
|
|
|
|
static void ersatz_failed (void)
|
|
{
|
|
if (already_failed)
|
|
return;
|
|
already_failed = 1;
|
|
notify_user (NUMSG_KICKREPNO);
|
|
uae_restart (-1, NULL);
|
|
}
|
|
|
|
static void ersatz_doio (void)
|
|
{
|
|
uaecptr request = m68k_areg (regs, 1);
|
|
switch (get_word (request + 0x1C)) {
|
|
case 9: /* TD_MOTOR is harmless */
|
|
return;
|
|
case 2: case 0x8002: /* READ commands */
|
|
break;
|
|
|
|
default:
|
|
write_log (_T("Only CMD_READ supported in DoIO()\n"));
|
|
ersatz_failed ();
|
|
}
|
|
{
|
|
uaecptr dest = get_long (request + 0x28);
|
|
int start = get_long (request + 0x2C) / 512;
|
|
int nsecs = get_long (request + 0x24) / 512;
|
|
int tr = start / 11;
|
|
int sec = start % 11;
|
|
while (nsecs--) {
|
|
DISK_ersatz_read (tr, sec, dest);
|
|
dest += 512;
|
|
if (++sec == 11)
|
|
sec = 0, tr++;
|
|
}
|
|
}
|
|
}
|
|
|
|
static void ersatz_init (void)
|
|
{
|
|
int f;
|
|
uaecptr request;
|
|
uaecptr a;
|
|
|
|
already_failed = 0;
|
|
write_log (_T("initializing kickstart replacement\n"));
|
|
if (disk_empty (0)) {
|
|
already_failed = 1;
|
|
notify_user (NUMSG_KICKREP);
|
|
uae_restart (-1, NULL);
|
|
return;
|
|
}
|
|
|
|
regs.s = 0;
|
|
/* Set some interrupt vectors */
|
|
for (a = 8; a < 0xC0; a += 4) {
|
|
put_long (a, 0xF8001A);
|
|
}
|
|
regs.isp = regs.msp = regs.usp = 0x800;
|
|
m68k_areg (regs, 7) = 0x80000;
|
|
regs.intmask = 0;
|
|
|
|
/* Build a dummy execbase */
|
|
put_long (4, m68k_areg (regs, 6) = 0x676);
|
|
put_byte (0x676 + 0x129, 0);
|
|
for (f = 1; f < 105; f++) {
|
|
put_word (0x676 - 6*f, 0x4EF9);
|
|
put_long (0x676 - 6*f + 2, 0xF8000C);
|
|
}
|
|
/* Some "supported" functions */
|
|
put_long (0x676 - 456 + 2, 0xF80014);
|
|
put_long (0x676 - 216 + 2, 0xF80020);
|
|
put_long (0x676 - 198 + 2, 0xF80026);
|
|
put_long (0x676 - 204 + 2, 0xF8002c);
|
|
put_long (0x676 - 210 + 2, 0xF8002a);
|
|
|
|
/* Build an IORequest */
|
|
request = 0x800;
|
|
put_word (request + 0x1C, 2);
|
|
put_long (request + 0x28, 0x4000);
|
|
put_long (request + 0x2C, 0);
|
|
put_long (request + 0x24, 0x200 * 4);
|
|
m68k_areg (regs, 1) = request;
|
|
ersatz_doio ();
|
|
/* kickstart disk loader */
|
|
if (get_long (0x4000) == 0x4b49434b) {
|
|
/* a kickstart disk was found in drive 0! */
|
|
write_log (_T("Loading Kickstart rom image from Kickstart disk\n"));
|
|
/* print some notes... */
|
|
write_log (_T("NOTE: if UAE crashes set CPU to 68000 and/or chipmem size to 512KB!\n"));
|
|
|
|
/* read rom image from kickstart disk */
|
|
put_word (request + 0x1C, 2);
|
|
put_long (request + 0x28, 0xF80000);
|
|
put_long (request + 0x2C, 0x200);
|
|
put_long (request + 0x24, 0x200 * 512);
|
|
m68k_areg (regs, 1) = request;
|
|
ersatz_doio ();
|
|
|
|
/* read rom image once again to mirror address space.
|
|
not elegant, but it works... */
|
|
put_word (request + 0x1C, 2);
|
|
put_long (request + 0x28, 0xFC0000);
|
|
put_long (request + 0x2C, 0x200);
|
|
put_long (request + 0x24, 0x200 * 512);
|
|
m68k_areg (regs, 1) = request;
|
|
ersatz_doio ();
|
|
|
|
disk_eject (0);
|
|
|
|
m68k_setpc (0xFC0002);
|
|
fill_prefetch ();
|
|
uae_reset (0);
|
|
ersatzkickfile = 0;
|
|
return;
|
|
}
|
|
|
|
m68k_setpc (0x400C);
|
|
fill_prefetch ();
|
|
|
|
/* Init the hardware */
|
|
put_long (0x3000, 0xFFFFFFFEul);
|
|
put_long (0xDFF080, 0x3000);
|
|
put_word (0xDFF088, 0);
|
|
put_word (0xDFF096, 0xE390);
|
|
put_word (0xDFF09A, 0xE02C);
|
|
put_word (0xDFF09E, 0x0000);
|
|
put_word (0xDFF092, 0x0038);
|
|
put_word (0xDFF094, 0x00D0);
|
|
put_word (0xDFF08E, 0x2C81);
|
|
put_word (0xDFF090, 0xF4C1);
|
|
put_word (0xDFF02A, 0x8000);
|
|
|
|
put_byte (0xBFD100, 0xF7);
|
|
put_byte (0xBFEE01, 0);
|
|
put_byte (0xBFEF01, 0x08);
|
|
put_byte (0xBFDE00, 0x04);
|
|
put_byte (0xBFDF00, 0x84);
|
|
put_byte (0xBFDD00, 0x9F);
|
|
put_byte (0xBFED01, 0x9F);
|
|
}
|
|
|
|
void ersatz_perform (uae_u16 what)
|
|
{
|
|
switch (what) {
|
|
case EOP_INIT:
|
|
ersatz_init ();
|
|
break;
|
|
|
|
case EOP_SERVEINT:
|
|
{
|
|
uae_u16 intreq = get_word (0xDFF01E);
|
|
/* Just reset all the interrupt request bits */
|
|
if (intreq & 0x0008)
|
|
get_byte (0xbfed01); /* possible keyboard interrupt */
|
|
put_word (0xDFF09C, intreq & 0x3FFF);
|
|
break;
|
|
}
|
|
|
|
case EOP_DOIO:
|
|
ersatz_doio ();
|
|
break;
|
|
|
|
case EOP_AVAILMEM:
|
|
m68k_dreg (regs, 0) = m68k_dreg (regs, 1) & 4 ? 0 : 0x70000;
|
|
break;
|
|
|
|
case EOP_ALLOCMEM:
|
|
m68k_dreg (regs, 0) = m68k_dreg (regs, 1) & 4 ? 0 : 0x0F000;
|
|
break;
|
|
|
|
case EOP_ALLOCABS:
|
|
m68k_dreg (regs, 0) = m68k_areg (regs, 1);
|
|
break;
|
|
|
|
case EOP_NIMP:
|
|
write_log (_T("Unimplemented Kickstart function called\n"));
|
|
ersatz_failed ();
|
|
|
|
/* fall through */
|
|
case EOP_LOOP:
|
|
m68k_setpc (0xF80010);
|
|
break;
|
|
|
|
case EOP_OPENLIB:
|
|
default:
|
|
write_log (_T("Internal error. Giving up.\n"));
|
|
ersatz_failed ();
|
|
}
|
|
}
|