Source to src/uaelib.c
/*
* UAE - The U*nix Amiga Emulator
*
* UAE Library v0.1
*
* (c) 1996 Tauno Taipaleenmaki <[email protected]>
*
* Change UAE parameters and other stuff from inside the emulation.
*/
#include "sysconfig.h"
#include "sysdeps.h"
#include <assert.h>
#include <string.h>
#include "options.h"
#include "threaddep/thread.h"
#include "uae.h"
#include "include/memory.h"
#include "custom.h"
#include "newcpu.h"
#include "xwin.h"
#include "traps.h"
#include "autoconf.h"
#include "disk.h"
#include "debug.h"
#include "gensound.h"
#include "picasso96.h"
/* We don't get a numerical version from autoconf, but this is the only place
that wants it, and it doesn't matter - so cheat. */
#define UAEVERSION 0x0826
/*
* Returns UAE Version
*/
static uae_u32 emulib_GetVersion (void)
{
return UAEVERSION;
}
/*
* Resets your amiga
*/
static uae_u32 emulib_HardReset (void)
{
uae_reset(1);
return 0;
}
static uae_u32 emulib_Reset (void)
{
uae_reset(0);
return 0;
}
/*
* Enables SOUND
*/
static uae_u32 emulib_EnableSound (uae_u32 val)
{
if (!sound_available || currprefs.produce_sound == 2)
return 0;
currprefs.produce_sound = val;
return 1;
}
/*
* Enables FAKE JOYSTICK
*/
static uae_u32 emulib_EnableJoystick (uae_u32 val)
{
currprefs.jport0 = val & 255;
currprefs.jport1 = (val >> 8) & 255;
return 1;
}
/*
* Sets the framerate
*/
static uae_u32 emulib_SetFrameRate (uae_u32 val)
{
if (val == 0)
return 0;
else if (val > 20)
return 0;
else {
currprefs.gfx_framerate = val;
return 1;
}
}
/*
* Changes keyboard language settings
*/
static uae_u32 emulib_ChangeLanguage (uae_u32 which)
{
if (which > 6)
return 0;
else {
switch (which) {
case 0:
currprefs.keyboard_lang = KBD_LANG_US;
break;
case 1:
currprefs.keyboard_lang = KBD_LANG_DK;
break;
case 2:
currprefs.keyboard_lang = KBD_LANG_DE;
break;
case 3:
currprefs.keyboard_lang = KBD_LANG_SE;
break;
case 4:
currprefs.keyboard_lang = KBD_LANG_FR;
break;
case 5:
currprefs.keyboard_lang = KBD_LANG_IT;
break;
case 6:
currprefs.keyboard_lang = KBD_LANG_ES;
break;
default:
break;
}
return 1;
}
}
/* The following ones don't work as we never realloc the arrays... */
/*
* Changes chip memory size
* (reboots)
*/
static uae_u32 emulib_ChgCMemSize (uae_u32 memsize)
{
if (memsize != 0x80000 && memsize != 0x100000 &&
memsize != 0x200000) {
memsize = 0x200000;
write_log ("Unsupported chipmem size!\n");
}
m68k_dreg (regs, 0) = 0;
currprefs.chipmem_size = memsize;
uae_reset(0);
return 1;
}
/*
* Changes slow memory size
* (reboots)
*/
static uae_u32 emulib_ChgSMemSize (uae_u32 memsize)
{
if (memsize != 0x80000 && memsize != 0x100000 &&
memsize != 0x180000 && memsize != 0x1C0000) {
memsize = 0;
write_log ("Unsupported bogomem size!\n");
}
m68k_dreg (regs, 0) = 0;
currprefs.bogomem_size = memsize;
uae_reset (0);
return 1;
}
/*
* Changes fast memory size
* (reboots)
*/
static uae_u32 emulib_ChgFMemSize (uae_u32 memsize)
{
if (memsize != 0x100000 && memsize != 0x200000 &&
memsize != 0x400000 && memsize != 0x800000) {
memsize = 0;
write_log ("Unsupported fastmem size!\n");
}
m68k_dreg (regs, 0) = 0;
currprefs.fastmem_size = memsize;
uae_reset (0);
return 0;
}
/*
* Inserts a disk
*/
static uae_u32 emulib_InsertDisk (uaecptr name, uae_u32 drive)
{
int i = 0;
char real_name[256];
if (drive > 3)
return 0;
while ((real_name[i] = get_byte (name + i)) != 0 && i++ != 254)
;
if (i == 255)
return 0; /* ENAMETOOLONG */
strcpy (changed_prefs.df[drive], real_name);
return 1;
}
/*
* Exits the emulator
*/
static uae_u32 emulib_ExitEmu (void)
{
uae_quit ();
return 1;
}
/*
* Gets UAE Configuration
*/
static uae_u32 emulib_GetUaeConfig (uaecptr place)
{
int i,j;
put_long (place, UAEVERSION);
put_long (place + 4, allocated_chipmem);
put_long (place + 8, allocated_bogomem);
put_long (place + 12, allocated_fastmem);
put_long (place + 16, currprefs.gfx_framerate);
put_long (place + 20, currprefs.produce_sound);
put_long (place + 24, currprefs.jport0 | (currprefs.jport1 << 8));
put_long (place + 28, currprefs.keyboard_lang);
if (disk_empty (0))
put_byte (place + 32, 0);
else
put_byte (place + 32, 1);
if (disk_empty (1))
put_byte (place + 33, 0);
else
put_byte (place + 33, 1);
if (disk_empty(2))
put_byte (place + 34, 0);
else
put_byte (place + 34, 1);
if (disk_empty(3))
put_byte (place + 35, 0);
else
put_byte (place + 35, 1);
for (i = 0; i < 256; i++) {
put_byte ((place + 36 + i), currprefs.df[0][i]);
put_byte ((place + 36 + i + 256), currprefs.df[1][i]);
put_byte ((place + 36 + i + 512), currprefs.df[2][i]);
put_byte ((place + 36 + i + 768), currprefs.df[3][i]);
}
return 1;
}
/*
* Sets UAE Configuration
*
* NOT IMPLEMENTED YET
*/
static uae_u32 emulib_SetUaeConfig (uaecptr place)
{
return 1;
}
/*
* Gets the name of the disk in the given drive
*/
static uae_u32 emulib_GetDisk (uae_u32 drive, uaecptr name)
{
int i;
if (drive > 3)
return 0;
for (i = 0;i < 256; i++) {
put_byte (name + i, currprefs.df[drive][i]);
}
return 1;
}
/*
* Enter debugging state
*/
static uae_u32 emulib_Debug (void)
{
activate_debugger ();
return 1;
}
/* We simply find the first "text" hunk, get the offset of its actual code segment (20 bytes away)
* and add that offset to the base address of the object. Now we've got code to execute.
*
* @@@ Brian: does anything actually use this yet?
* @@@ Bernd: Not yet. It needs to get much better. Should spawn off a seperate task to handle the
* function, and then somehow "signal" the Amiga caller that completion or error has
* occurred. I don't know how to do that, so right now it is a synchronous call. Yuck!
* Would be nice to implement jpg decompression functionality for the Amiga which used
* the UAE Host to do all the work, for example.
* @@@ Brian: I disabled it to prevent people from starting to use it - if that happens, we're
* stuck with this.
*/
static uae_u32 FindFunctionInObject (uae_u8 *objectptr)
{
uae_u8 *text_hdr;
uae_u8 offset;
text_hdr = (uae_u8 *)strstr ("text", (char *)objectptr);
if (text_hdr != 0) {
offset = *(text_hdr + 19);
return (uae_u32)(objectptr + offset);
}
return 0;
}
#define CREATE_NATIVE_FUNC_PTR uae_u32 (* native_func) (uae_u32, uae_u32, uae_u32, uae_u32, uae_u32, uae_u32, uae_u32, \
uae_u32, uae_u32, uae_u32, uae_u32, uae_u32, uae_u32)
#define SET_NATIVE_FUNC(x) native_func = (uae_u32 (*)(uae_u32, uae_u32, uae_u32, uae_u32, uae_u32, uae_u32, uae_u32, uae_u32, uae_u32, uae_u32, uae_u32, uae_u32, uae_u32))(x)
#define CALL_NATIVE_FUNC(d1,d2,d3,d4,d5,d6,d7,a1,a2,a3,a4,a5,a6) if(native_func) native_func (d1,d2,d3,d4,d5,d6,d7,a1,a2,a3,a4,a5,a6)
/* A0 - Contains a ptr to the native .obj data. This ptr is Amiga-based. */
/* We simply find the first function in this .obj data, and execute it. */
static uae_u32 emulib_ExecuteNativeCode (void)
{
#if 0
uaecptr object_AAM = m68k_areg (regs, 0);
uae_u32 d1 = m68k_dreg (regs, 1);
uae_u32 d2 = m68k_dreg (regs, 2);
uae_u32 d3 = m68k_dreg (regs, 3);
uae_u32 d4 = m68k_dreg (regs, 4);
uae_u32 d5 = m68k_dreg (regs, 5);
uae_u32 d6 = m68k_dreg (regs, 6);
uae_u32 d7 = m68k_dreg (regs, 7);
uae_u32 a1 = m68k_areg (regs, 1);
uae_u32 a2 = m68k_areg (regs, 2);
uae_u32 a3 = m68k_areg (regs, 3);
uae_u32 a4 = m68k_areg (regs, 4);
uae_u32 a5 = m68k_areg (regs, 5);
uae_u32 a6 = m68k_areg (regs, 6);
uae_u8* object_UAM = NULL;
CREATE_NATIVE_FUNC_PTR;
if (get_mem_bank (object_AAM).check( object_AAM, 1))
object_UAM = get_mem_bank (object_AAM).xlateaddr (object_AAM);
if (object_UAM)
{
SET_NATIVE_FUNC (FindFunctionInObject (object_UAM));
CALL_NATIVE_FUNC (d1, d2, d3, d4, d5, d6, d7, a1, a2, a3, a4, a5, a6);
}
return 1;
#endif
return 0;
}
static uae_u32 uaelib_demux (TrapContext *dummy)
{
#define ARG0 (get_long (m68k_areg (regs, 7) + 4))
#define ARG1 (get_long (m68k_areg (regs, 7) + 8))
#define ARG2 (get_long (m68k_areg (regs, 7) + 12))
#define ARG3 (get_long (m68k_areg (regs, 7) + 16))
switch (ARG0) {
case 0: return emulib_GetVersion ();
case 1: return emulib_GetUaeConfig (ARG1);
case 2: return emulib_SetUaeConfig (ARG1);
case 3: return emulib_HardReset ();
case 4: return emulib_Reset ();
case 5: return emulib_InsertDisk (ARG1, ARG2);
case 6: return emulib_EnableSound (ARG1);
case 7: return emulib_EnableJoystick (ARG1);
case 8: return emulib_SetFrameRate (ARG1);
case 9: return emulib_ChgCMemSize (ARG1);
case 10: return emulib_ChgSMemSize (ARG1);
case 11: return emulib_ChgFMemSize (ARG1);
case 12: return emulib_ChangeLanguage (ARG1);
/* The next call brings bad luck */
case 13: return emulib_ExitEmu ();
case 14: return emulib_GetDisk (ARG1, ARG2);
case 15: return emulib_Debug ();
#ifdef PICASSO96
case 16: return picasso_FindCard ();
case 17: return picasso_FillRect ();
case 18: return picasso_SetSwitch ();
case 19: return picasso_SetColorArray ();
case 20: return picasso_SetDAC ();
case 21: return picasso_SetGC ();
case 22: return picasso_SetPanning ();
case 23: return picasso_CalculateBytesPerRow ();
case 24: return picasso_BlitPlanar2Chunky ();
case 25: return picasso_BlitRect ();
case 26: return picasso_SetDisplay ();
case 27: return picasso_BlitTemplate ();
case 28: return picasso_BlitRectNoMaskComplete ();
case 29: return picasso_InitCard ();
case 30: return picasso_BlitPattern ();
case 31: return picasso_InvertRect ();
case 32: return picasso_BlitPlanar2Direct ();
case 34: return picasso_WaitVerticalSync ();
case 35: return allocated_gfxmem ? 1 : 0;
#endif
case 69: return emulib_ExecuteNativeCode ();
}
return 0;
}
/*
* Installs the UAE LIBRARY
*/
void emulib_install (void)
{
uaecptr a = here ();
org (RTAREA_BASE + 0xFF60);
calltrap (deftrap (uaelib_demux));
dw (RTS);
org (a);
}