|
|
1.1 root 1: /*
2: Hatari - hatari-glue.c
3:
1.1.1.4 root 4: This file is distributed under the GNU General Public License, version 2
5: or at your option any later version. Read the file gpl.txt for details.
1.1 root 6:
7: This file contains some code to glue the UAE CPU core to the rest of the
8: emulator and Hatari's "illegal" opcodes.
9: */
10: const char HatariGlue_fileid[] = "Hatari hatari-glue.c : " __DATE__ " " __TIME__;
11:
12:
13: #include <stdio.h>
14:
15: #include "main.h"
16: #include "configuration.h"
17: #include "cycInt.h"
18: #include "tos.h"
19: #include "gemdos.h"
1.1.1.4 root 20: #include "natfeats.h"
1.1 root 21: #include "cart.h"
22: #include "vdi.h"
23: #include "stMemory.h"
24: #include "ikbd.h"
25: #include "screen.h"
26: #include "video.h"
1.1.1.2 root 27: #include "psg.h"
1.1.1.4 root 28: #include "mfp.h"
29: #include "fdc.h"
1.1.1.9 ! root 30: #include "memorySnapShot.h"
1.1 root 31:
32: #include "sysdeps.h"
1.1.1.6 root 33: #include "options_cpu.h"
1.1 root 34: #include "maccess.h"
35: #include "memory.h"
1.1.1.4 root 36: #include "m68000.h"
1.1 root 37: #include "newcpu.h"
1.1.1.3 root 38: #include "cpu_prefetch.h"
1.1.1.9 ! root 39: #include "savestate.h"
1.1 root 40: #include "hatari-glue.h"
41:
42:
43: struct uae_prefs currprefs, changed_prefs;
44:
45: int pendingInterrupts = 0;
46:
47:
48: /**
49: * Reset custom chips
1.1.1.4 root 50: * In case the RESET instruction is called, we must reset all the peripherals
51: * connected to the CPU's reset pin.
1.1 root 52: */
53: void customreset(void)
54: {
55: pendingInterrupts = 0;
56:
1.1.1.4 root 57: /* Reset the IKBD */
58: IKBD_Reset ( false );
1.1 root 59:
60: /* Reseting the GLUE video chip should also set freq/res register to 0 */
61: Video_Reset_Glue ();
1.1.1.2 root 62:
1.1.1.7 root 63: /* Reset the YM2149 (stop any sound) */
64: PSG_Reset ();
1.1.1.4 root 65:
66: /* Reset the MFP */
67: MFP_Reset ();
68:
69: /* Reset the FDC */
1.1.1.5 root 70: FDC_Reset ( false );
1.1 root 71: }
72:
73:
74: /**
75: * Return interrupt number (1 - 7), -1 means no interrupt.
76: * Note that the interrupt stays pending if it can't be executed yet
77: * due to the interrupt level field in the SR.
78: */
79: int intlev(void)
80: {
1.1.1.6 root 81: if ( pendingInterrupts & (1 << 6) ) /* MFP/DSP interrupt ? */
82: return 6;
83: else if ( pendingInterrupts & (1 << 4) ) /* VBL interrupt ? */
1.1.1.4 root 84: return 4;
85: else if ( pendingInterrupts & (1 << 2) ) /* HBL interrupt ? */
86: return 2;
1.1 root 87:
88: return -1;
89: }
90:
1.1.1.9 ! root 91:
! 92: void UAE_Set_Quit_Reset ( bool hard )
! 93: {
! 94: //fprintf ( stderr , "UAE_Set_Quit_Reset %d\n" , hard );
! 95: if ( hard )
! 96: quit_program = UAE_RESET_HARD;
! 97: else
! 98: quit_program = UAE_RESET;
! 99: }
! 100:
! 101:
! 102: void UAE_Set_State_Save ( void )
! 103: {
! 104: //fprintf ( stderr , "UAE_Set_State_Save\n" );
! 105: savestate_state = STATE_SAVE;
! 106: }
! 107:
! 108:
! 109: void UAE_Set_State_Restore ( void )
! 110: {
! 111: //fprintf ( stderr , "UAE_Set_State_Restore\n" );
! 112: savestate_state = STATE_RESTORE;
! 113: }
! 114:
! 115:
! 116:
1.1 root 117: /**
1.1.1.9 ! root 118: * Replace WinUAE's save_state / restore_state functions with Hatari's specific ones
1.1 root 119: */
1.1.1.9 ! root 120: int save_state (const TCHAR *filename, const TCHAR *description)
1.1 root 121: {
1.1.1.9 ! root 122: //fprintf ( stderr , "save_state in\n" );
! 123: MemorySnapShot_Capture_Do ();
! 124: //fprintf ( stderr , "save_state out\n" );
! 125: savestate_state = 0;
! 126: return 0; /* return value is not used */
! 127: }
1.1 root 128:
129:
1.1.1.9 ! root 130: void restore_state (const TCHAR *filename)
! 131: {
! 132: MemorySnapShot_Restore_Do ();
! 133: }
! 134:
! 135:
! 136: void savestate_restore_finish (void)
! 137: {
! 138: //fprintf ( stderr , "savestate_restore_finish in %d\n" , quit_program );
! 139: if (!isrestore ())
! 140: return;
! 141: restore_cpu_finish ();
! 142: savestate_state = 0;
! 143: quit_program = 0; /* at this point, quit_program was already processed, we must reset it */
! 144: //fprintf ( stderr , "savestate_restore_finish out %d\n" , quit_program );
! 145: }
1.1 root 146:
1.1.1.9 ! root 147:
! 148:
! 149:
! 150: /**
! 151: * Initialize 680x0 emulation
! 152: */
! 153: int Init680x0(void)
! 154: {
! 155: //fprintf ( stderr , "Init680x0 in\n" );
! 156: init_m68k();
! 157: //fprintf ( stderr , "Init680x0 out\n" );
1.1 root 158: return true;
159: }
160:
161:
162: /**
163: * Deinitialize 680x0 emulation
164: */
165: void Exit680x0(void)
166: {
167: memory_uninit();
168:
169: free(table68k);
170: table68k = NULL;
171: }
172:
1.1.1.6 root 173:
174: /**
175: * Execute a 'NOP' opcode (increment PC by 2 bytes and take care
176: * of prefetch at the CPU level depending on the current CPU mode)
177: * This is used to return from Gemdos / Natfeats interception, by ignoring
178: * the intercepted opcode and executing a NOP instead once the work has been done.
179: */
180: static void CpuDoNOP ( void )
181: {
182: (*cpufunctbl[0X4E71])(0x4E71);
183: }
184:
185:
1.1 root 186: /**
1.1.1.7 root 187: * Check whether PC is currently in ROM cartridge space - used
188: * to test whether our "illegal" Hatari opcodes should be handled
189: * or whether they are just "normal" illegal opcodes.
190: */
191: static bool is_cart_pc(void)
192: {
193: Uint32 pc = M68000_GetPC();
194:
195: if (ConfigureParams.System.bAddressSpace24 || (pc >> 24) == 0xff)
196: {
197: pc &= 0x00ffffff; /* Mask to 24-bit address */
198: }
199:
200: return pc >= 0xfa0000 && pc < 0xfc0000;
201: }
202:
203:
204: /**
1.1 root 205: * This function will be called at system init by the cartridge routine
206: * (after gemdos init, before booting floppies).
207: * The GEMDOS vector (#$84) is setup and we also initialize the connected
1.1.1.9 ! root 208: * drive mask and Line-A variables (for an extended VDI resolution) from here.
1.1 root 209: */
1.1.1.7 root 210: uae_u32 REGPARAM3 OpCode_SysInit(uae_u32 opcode)
1.1 root 211: {
1.1.1.7 root 212: if (is_cart_pc())
1.1 root 213: {
1.1.1.7 root 214: /* Add any drives mapped by TOS in the interim */
215: ConnectedDriveMask |= STMemory_ReadLong(0x4c2);
216: /* Initialize the connected drive mask */
217: STMemory_WriteLong(0x4c2, ConnectedDriveMask);
218:
1.1 root 219: /* Init on boot - see cart.c */
220: GemDOS_Boot();
221:
222: /* Update LineA for extended VDI res
223: * D0: LineA base, A1: Font base
224: */
225: VDI_LineA(regs.regs[0], regs.regs[9]);
1.1.1.7 root 226:
1.1.1.9 ! root 227: CpuDoNOP();
! 228: }
! 229: else if (!bUseTos)
! 230: {
! 231: GemDOS_Boot();
! 232: CpuDoNOP();
1.1.1.7 root 233: }
234: else
235: {
236: LOG_TRACE(TRACE_OS_GEMDOS | TRACE_OS_BASE | TRACE_OS_VDI | TRACE_OS_AES,
237: "SYSINIT opcode invoked outside of cartridge space\n");
238: /* illegal instruction */
239: op_illg(opcode);
240: fill_prefetch();
1.1 root 241: }
242:
1.1.1.3 root 243: return 4 * CYCLE_UNIT / 2;
1.1 root 244: }
245:
246:
247: /**
248: * Intercept GEMDOS calls.
249: * Used for GEMDOS HD emulation (see gemdos.c).
250: */
1.1.1.7 root 251: uae_u32 REGPARAM3 OpCode_GemDos(uae_u32 opcode)
1.1 root 252: {
1.1.1.7 root 253: if (is_cart_pc())
254: {
255: GemDOS_OpCode(); /* handler code in gemdos.c */
256: CpuDoNOP();
257: }
258: else
259: {
260: LOG_TRACE(TRACE_OS_GEMDOS, "GEMDOS opcode invoked outside of cartridge space\n");
261: /* illegal instruction */
262: op_illg(opcode);
263: fill_prefetch();
264: }
1.1 root 265:
1.1.1.3 root 266: return 4 * CYCLE_UNIT / 2;
1.1 root 267: }
268:
269:
270: /**
271: * This is called after completion of each VDI call
272: */
1.1.1.7 root 273: uae_u32 REGPARAM3 OpCode_VDI(uae_u32 opcode)
1.1 root 274: {
1.1.1.4 root 275: /* this is valid only after VDI trap, called from cartridge code */
1.1.1.7 root 276: if (VDI_OldPC && is_cart_pc())
1.1.1.4 root 277: {
278: VDI_Complete();
279:
280: /* Set PC back to where originated from to continue instruction decoding */
281: m68k_setpc(VDI_OldPC);
282: VDI_OldPC = 0;
283: }
284: else
285: {
1.1.1.7 root 286: LOG_TRACE(TRACE_OS_VDI, "VDI opcode invoked outside of cartridge space\n");
1.1.1.4 root 287: /* illegal instruction */
288: op_illg(opcode);
289: }
1.1 root 290:
1.1.1.6 root 291: fill_prefetch();
1.1.1.3 root 292: return 4 * CYCLE_UNIT / 2;
1.1 root 293: }
1.1.1.4 root 294:
295:
296: /**
297: * Emulator Native Features ID opcode interception.
298: */
1.1.1.7 root 299: uae_u32 REGPARAM3 OpCode_NatFeat_ID(uae_u32 opcode)
1.1.1.4 root 300: {
301: Uint32 stack = Regs[REG_A7] + SIZE_LONG; /* skip return address */
302:
1.1.1.7 root 303: if (NatFeat_ID(stack, &(Regs[REG_D0])))
304: {
1.1.1.6 root 305: CpuDoNOP ();
1.1.1.4 root 306: }
307: return 4 * CYCLE_UNIT / 2;
308: }
309:
310: /**
311: * Emulator Native Features call opcode interception.
312: */
1.1.1.7 root 313: uae_u32 REGPARAM3 OpCode_NatFeat_Call(uae_u32 opcode)
1.1.1.4 root 314: {
315: Uint32 stack = Regs[REG_A7] + SIZE_LONG; /* skip return address */
316: Uint16 SR = M68000_GetSR();
317: bool super;
318:
319: super = ((SR & SR_SUPERMODE) == SR_SUPERMODE);
1.1.1.7 root 320: if (NatFeat_Call(stack, super, &(Regs[REG_D0])))
321: {
1.1.1.6 root 322: CpuDoNOP ();
1.1.1.4 root 323: }
324: return 4 * CYCLE_UNIT / 2;
325: }
1.1.1.6 root 326:
327:
1.1.1.7 root 328: TCHAR* buf_out (TCHAR *buffer, int *bufsize, const TCHAR *format, ...)
329: {
330: va_list parms;
331:
332: if (buffer == NULL)
333: {
334: return NULL;
335: }
336:
337: va_start (parms, format);
338: vsnprintf (buffer, (*bufsize) - 1, format, parms);
339: va_end (parms);
340: *bufsize -= _tcslen (buffer);
1.1.1.6 root 341:
1.1.1.7 root 342: return buffer + _tcslen (buffer);
343: }
344:
345: void error_log(const TCHAR *format, ...)
346: {
347: va_list parms;
1.1.1.6 root 348:
1.1.1.7 root 349: va_start(parms, format);
350: vfprintf(stderr, format, parms);
351: va_end(parms);
1.1.1.6 root 352:
1.1.1.7 root 353: if (format[strlen(format) - 1] != '\n')
354: {
355: fputc('\n', stderr);
356: }
1.1.1.6 root 357: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.