180 lines
5.7 KiB
C
180 lines
5.7 KiB
C
/*
|
|
Hatari - cart.c
|
|
|
|
This file is distributed under the GNU General Public License, version 2
|
|
or at your option any later version. Read the file gpl.txt for details.
|
|
|
|
Cartridge program
|
|
|
|
To load programs into memory, through TOS, we need to intercept GEMDOS so we
|
|
can relocate/execute programs via GEMDOS call $4B (Pexec).
|
|
We have some 68000 assembler, located at 0xFA0000 (cartridge memory), which is
|
|
used as our new GEMDOS handler. This checks if we need to intercept the call.
|
|
|
|
The assembler routine can be found in 'cart_asm.s', and has been converted to
|
|
a byte array and stored in 'Cart_data[]' (see cartData.c).
|
|
*/
|
|
const char Cart_fileid[] = "Hatari cart.c : " __DATE__ " " __TIME__;
|
|
|
|
/* 2007/12/09 [NP] Change the function associated to opcodes $8, $a and $c only if hard drive */
|
|
/* emulation is ON. Else, these opcodes should give illegal instructions (also */
|
|
/* see uae-cpu/newcpu.c). */
|
|
|
|
|
|
#include "main.h"
|
|
#include "cart.h"
|
|
#include "configuration.h"
|
|
#include "file.h"
|
|
#include "log.h"
|
|
#include "m68000.h"
|
|
#include "stMemory.h"
|
|
#include "tos.h"
|
|
#include "vdi.h"
|
|
#include "hatari-glue.h"
|
|
#include "newcpu.h"
|
|
|
|
#include "cartData.c"
|
|
|
|
|
|
/* Possible cartridge file extensions to scan for */
|
|
static const char * const psCartNameExts[] =
|
|
{
|
|
".img",
|
|
".rom",
|
|
".stc",
|
|
NULL
|
|
};
|
|
|
|
static int PatchIllegal = false;
|
|
|
|
|
|
/*-----------------------------------------------------------------------*/
|
|
/**
|
|
* Load an external cartridge image file.
|
|
*/
|
|
static void Cart_LoadImage(void)
|
|
{
|
|
Uint8 *pCartData;
|
|
long nCartSize;
|
|
char *pCartFileName = ConfigureParams.Rom.szCartridgeImageFileName;
|
|
|
|
/* Try to load the image file: */
|
|
pCartData = File_Read(pCartFileName, &nCartSize, psCartNameExts);
|
|
if (!pCartData)
|
|
{
|
|
Log_Printf(LOG_ERROR, "Failed to load '%s'.\n", pCartFileName);
|
|
return;
|
|
}
|
|
|
|
if (nCartSize < 40 || (nCartSize > 0x20000 && nCartSize != 0x20004))
|
|
{
|
|
Log_Printf(LOG_ERROR, "Cartridge file '%s' has illegal size.\n", pCartFileName);
|
|
free(pCartData);
|
|
return;
|
|
}
|
|
|
|
/* There are two type of cartridge images, normal 1:1 images which are
|
|
* always smaller than or equal to 0x20000 bytes, and the .STC images,
|
|
* which are always 0x20004 bytes (the first 4 bytes are a dummy header).
|
|
* So if size is 0x20004 bytes we have to skip the first 4 bytes */
|
|
if (nCartSize == 0x20004)
|
|
{
|
|
memcpy(&RomMem[0xfa0000], pCartData+4, 0x20000);
|
|
}
|
|
else
|
|
{
|
|
memcpy(&RomMem[0xfa0000], pCartData, nCartSize);
|
|
}
|
|
|
|
free(pCartData);
|
|
}
|
|
|
|
|
|
/*-----------------------------------------------------------------------*/
|
|
/**
|
|
* Copy ST GEMDOS intercept program image into cartridge memory space
|
|
* or load an external cartridge file.
|
|
* The intercept program is part of Hatari and used as an interface to the host
|
|
* file system through GemDOS. It is also needed for Line-A-Init when using
|
|
* extended VDI resolutions.
|
|
*/
|
|
void Cart_ResetImage(void)
|
|
{
|
|
/* "Clear" cartridge ROM space */
|
|
memset(&RomMem[0xfa0000], 0xff, 0x20000);
|
|
|
|
/* Print a warning if user tries to use an external cartridge file
|
|
* together with GEMDOS HD emulation or extended VDI resolution: */
|
|
if (strlen(ConfigureParams.Rom.szCartridgeImageFileName) > 0)
|
|
{
|
|
if (bUseVDIRes)
|
|
Log_Printf(LOG_WARN, "Cartridge can't be used together with extended VDI resolution!\n");
|
|
if (ConfigureParams.HardDisk.bUseHardDiskDirectories)
|
|
Log_Printf(LOG_WARN, "Cartridge can't be used together with GEMDOS hard disk emulation!\n");
|
|
if (LogTraceFlags & (TRACE_OS_GEMDOS | TRACE_OS_BASE | TRACE_OS_VDI | TRACE_OS_AES))
|
|
Log_Printf(LOG_WARN, "Cartridge can't be used together with GEMDOS/VDI/AES tracing!\n");
|
|
}
|
|
|
|
/* Use internal cartridge trampoline code when user wants extended VDI
|
|
* resolution, GEMDOS HD emulation or to trace GEMDOS, VDI or AES.
|
|
* (OS_BASE does subset of GEMDOS tracing)
|
|
* But don't use it on TOS 0.00, it does not work there. */
|
|
if ((bUseVDIRes || ConfigureParams.HardDisk.bUseHardDiskDirectories ||
|
|
LogTraceFlags & (TRACE_OS_GEMDOS | TRACE_OS_BASE | TRACE_OS_VDI | TRACE_OS_AES))
|
|
&& TosVersion >= 0x100)
|
|
{
|
|
/* Copy built-in cartridge data into the cartridge memory of the ST */
|
|
memcpy(&RomMem[0xfa0000], Cart_data, sizeof(Cart_data));
|
|
PatchIllegal = true;
|
|
}
|
|
else if (strlen(ConfigureParams.Rom.szCartridgeImageFileName) > 0)
|
|
{
|
|
/* Load external image file: */
|
|
Cart_LoadImage();
|
|
}
|
|
}
|
|
|
|
|
|
/*-----------------------------------------------------------------------*/
|
|
/**
|
|
* Patch the cpu tables to intercept some opcodes used for Gemdos HD
|
|
* emulation or for NatFeats.
|
|
* We need to split this from Cart_ResetImage(), as the patches should
|
|
* be applied after building the cpu opcodes tables.
|
|
*/
|
|
void Cart_Patch(void)
|
|
{
|
|
if (PatchIllegal == true)
|
|
{
|
|
//fprintf ( stderr ," Cart_ResetImage patch\n" );
|
|
/* Hatari's specific illegal opcodes for HD emulation */
|
|
cpufunctbl[GEMDOS_OPCODE] = OpCode_GemDos; /* 0x0008 */
|
|
cpufunctbl[SYSINIT_OPCODE] = OpCode_SysInit; /* 0x000a */
|
|
cpufunctbl[VDI_OPCODE] = OpCode_VDI; /* 0x000c */
|
|
}
|
|
else
|
|
{
|
|
//fprintf ( stderr ," Cart_ResetImage no patch\n" );
|
|
/* No built-in cartridge loaded : set same handler as 0x4afc (illegal) */
|
|
cpufunctbl[GEMDOS_OPCODE] = cpufunctbl[ 0x4afc ]; /* 0x0008 */
|
|
cpufunctbl[SYSINIT_OPCODE] = cpufunctbl[ 0x4afc ]; /* 0x000a */
|
|
cpufunctbl[VDI_OPCODE] = cpufunctbl[ 0x4afc ]; /* 0x000c */
|
|
}
|
|
|
|
/* although these don't need cartridge code, it's better
|
|
* to configure all illegal opcodes in same place...
|
|
*/
|
|
if (ConfigureParams.Log.bNatFeats)
|
|
{
|
|
/* illegal opcodes for emulators Native Features */
|
|
cpufunctbl[NATFEAT_ID_OPCODE] = OpCode_NatFeat_ID; /* 0x7300 */
|
|
cpufunctbl[NATFEAT_CALL_OPCODE] = OpCode_NatFeat_Call; /* 0x7301 */
|
|
}
|
|
else
|
|
{
|
|
/* No Native Features : set same handler as 0x4afc (illegal) */
|
|
cpufunctbl[NATFEAT_ID_OPCODE] = cpufunctbl[ 0x4afc ]; /* 0x7300 */
|
|
cpufunctbl[NATFEAT_CALL_OPCODE] = cpufunctbl[ 0x4afc ]; /* 0x7300 */
|
|
}
|
|
}
|