--- hatari/src/uae-cpu/hatari-glue.c 2019/04/09 08:47:23 1.1.1.14 +++ hatari/src/uae-cpu/hatari-glue.c 2019/04/09 08:59:34 1.1.1.22 @@ -1,8 +1,8 @@ /* Hatari - hatari-glue.c - This file is distributed under the GNU Public License, version 2 or at - your option any later version. Read the file gpl.txt for details. + 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. This file contains some code to glue the UAE CPU core to the rest of the emulator and Hatari's "illegal" opcodes. @@ -12,20 +12,26 @@ const char HatariGlue_fileid[] = "Hatari #include -#include "../includes/main.h" -#include "../includes/configuration.h" -#include "../includes/int.h" -#include "../includes/tos.h" -#include "../includes/gemdos.h" -#include "../includes/cart.h" -#include "../includes/vdi.h" -#include "../includes/stMemory.h" -#include "../includes/ikbd.h" -#include "../includes/video.h" +#include "main.h" +#include "configuration.h" +#include "cycInt.h" +#include "tos.h" +#include "gemdos.h" +#include "natfeats.h" +#include "cart.h" +#include "vdi.h" +#include "stMemory.h" +#include "ikbd.h" +#include "screen.h" +#include "video.h" +#include "psg.h" +#include "mfp.h" +#include "fdc.h" #include "sysdeps.h" #include "maccess.h" #include "memory.h" +#include "m68000.h" #include "newcpu.h" #include "hatari-glue.h" @@ -37,17 +43,27 @@ int pendingInterrupts = 0; /** * Reset custom chips + * In case the RESET instruction is called, we must reset all the peripherals + * connected to the CPU's reset pin. */ void customreset(void) { pendingInterrupts = 0; - /* In case the 6301 was executing a custom program from its RAM */ - /* we must turn it back to the 'normal' mode. */ - IKBD_Reset_ExeMode (); + /* Reset the IKBD */ + IKBD_Reset ( false ); /* Reseting the GLUE video chip should also set freq/res register to 0 */ Video_Reset_Glue (); + + /* Reset the YM2149 (stop any sound) */ + PSG_Reset (); + + /* Reset the MFP */ + MFP_Reset (); + + /* Reset the FDC */ + FDC_Reset ( false ); } @@ -61,6 +77,7 @@ int intlev(void) /* There are only VBL and HBL autovector interrupts in the ST... */ assert((pendingInterrupts & ~((1<<4)|(1<<2))) == 0); +#if 0 if (pendingInterrupts & (1 << 4)) /* VBL interrupt? */ { if (regs.intmask < 4) @@ -73,6 +90,12 @@ int intlev(void) pendingInterrupts &= ~(1 << 2); return 2; } +#else + if ( pendingInterrupts & (1 << 4) ) /* VBL interrupt ? */ + return 4; + else if ( pendingInterrupts & (1 << 2) ) /* HBL interrupt ? */ + return 2; +#endif return -1; } @@ -88,6 +111,7 @@ int Init680x0(void) currprefs.address_space_24 = changed_prefs.address_space_24 = true; init_m68k(); + Cart_PatchCpuTables(); return true; } @@ -106,6 +130,18 @@ void Exit680x0(void) /** + * Execute a 'NOP' opcode (increment PC by 2 bytes and take care + * of prefetch at the CPU level depending on the current CPU mode) + * This is used to return from Gemdos / Natfeats interception, by ignoring + * the intercepted opcode and executing a NOP instead once the work has been done. + */ +static void CpuDoNOP ( void ) +{ + (*cpufunctbl[0X4E71])(0x4E71); +} + + +/** * Check if the CPU type has been changed */ void check_prefs_changed_cpu(void) @@ -117,11 +153,24 @@ void check_prefs_changed_cpu(void) currprefs.cpu_compatible = changed_prefs.cpu_compatible; set_special(SPCFLAG_MODE_CHANGE); build_cpufunctbl (); + Cart_PatchCpuTables(); } } /** + * Check whether PC is currently in ROM cartridge space - used + * to test whether our "illegal" Hatari opcodes should be handled + * or whether they are just "normal" illegal opcodes. + */ +static bool is_cart_pc(void) +{ + Uint32 pc = M68000_GetPC() & 0x00ffffff; + return pc >= 0xfa0000 && pc < 0xfc0000; +} + + +/** * This function will be called at system init by the cartridge routine * (after gemdos init, before booting floppies). * The GEMDOS vector (#$84) is setup and we also initialize the connected @@ -129,13 +178,13 @@ void check_prefs_changed_cpu(void) */ unsigned long OpCode_SysInit(uae_u32 opcode) { - /* Add any drives mapped by TOS in the interim */ - ConnectedDriveMask |= STMemory_ReadLong(0x4c2); - /* Initialize the connected drive mask */ - STMemory_WriteLong(0x4c2, ConnectedDriveMask); - - if (!bInitGemDOS) + if (is_cart_pc()) { + /* Add any drives mapped by TOS in the interim */ + ConnectedDriveMask |= STMemory_ReadLong(0x4c2); + /* Initialize the connected drive mask */ + STMemory_WriteLong(0x4c2, ConnectedDriveMask); + /* Init on boot - see cart.c */ GemDOS_Boot(); @@ -143,10 +192,23 @@ unsigned long OpCode_SysInit(uae_u32 opc * D0: LineA base, A1: Font base */ VDI_LineA(regs.regs[0], regs.regs[9]); + + CpuDoNOP (); + } + else if (!bUseTos) + { + GemDOS_Boot(); + CpuDoNOP(); + } + else + { + LOG_TRACE(TRACE_OS_GEMDOS | TRACE_OS_BASE | TRACE_OS_VDI | TRACE_OS_AES, + "SYSINIT opcode invoked outside of cartridge space\n"); + /* illegal instruction */ + op_illg(opcode); + fill_prefetch_0(); } - m68k_incpc(2); - fill_prefetch_0(); return 4; } @@ -157,10 +219,19 @@ unsigned long OpCode_SysInit(uae_u32 opc */ unsigned long OpCode_GemDos(uae_u32 opcode) { - GemDOS_OpCode(); /* handler code in gemdos.c */ + if (is_cart_pc()) + { + GemDOS_OpCode(); /* handler code in gemdos.c */ + CpuDoNOP(); + } + else + { + LOG_TRACE(TRACE_OS_GEMDOS, "GEMDOS opcode invoked outside of cartridge space\n"); + /* illegal instruction */ + op_illg(opcode); + fill_prefetch_0(); + } - m68k_incpc(2); - fill_prefetch_0(); return 4; } @@ -170,11 +241,51 @@ unsigned long OpCode_GemDos(uae_u32 opco */ unsigned long OpCode_VDI(uae_u32 opcode) { - VDI_Complete(); - - /* Set PC back to where originated from to continue instruction decoding */ - m68k_setpc(VDI_OldPC); + /* this is valid only after VDI trap, called from cartridge code */ + if (VDI_OldPC && is_cart_pc()) + { + VDI_Complete(); + /* Set PC back to where originated from to continue instruction decoding */ + m68k_setpc(VDI_OldPC); + VDI_OldPC = 0; + } + else + { + LOG_TRACE(TRACE_OS_VDI, "VDI opcode invoked outside of cartridge space\n"); + /* illegal instruction */ + op_illg(opcode); + } fill_prefetch_0(); return 4; } + + +/** + * Emulator Native Features ID opcode interception. + */ +unsigned long OpCode_NatFeat_ID(uae_u32 opcode) +{ + Uint32 stack = Regs[REG_A7] + SIZE_LONG; /* skip return address */ + + if (NatFeat_ID(stack, &(Regs[REG_D0]))) { + CpuDoNOP (); + } + return 4; +} + +/** + * Emulator Native Features call opcode interception. + */ +unsigned long OpCode_NatFeat_Call(uae_u32 opcode) +{ + Uint32 stack = Regs[REG_A7] + SIZE_LONG; /* skip return address */ + Uint16 SR = M68000_GetSR(); + bool super; + + super = ((SR & SR_SUPERMODE) == SR_SUPERMODE); + if (NatFeat_Call(stack, super, &(Regs[REG_D0]))) { + CpuDoNOP (); + } + return 4; +}