/** * Set retval to internal ID for requested Native Feature, * or zero if feature is unknown/unsupported. * * Return true if caller is to proceed normally, * false if there was an exception. */ bool NatFeat_ID(Uint32 stack, Uint32 *retval) { const char *name; Uint32 ptr; int i; ptr = STMemory_ReadLong(stack); if (!STMemory_ValidArea(ptr, FEATNAME_MAX)) { M68000_BusError(ptr, BUS_ERROR_READ); return false; } name = (const char *)STRAM_ADDR(ptr); Dprintf(("NF ID(0x%x)\n", ptr)); Dprintf((" \"%s\"\n", name)); for (i = 0; i < ARRAYSIZE(features); i++) { if (strcmp(features[i].name, name) == 0) { *retval = IDX2MASTERID(i); return true; } } /* unknown feature */ *retval = 0; return true; }
/** * Copy given memory area safely to Atari RAM. * If the memory area isn't fully within RAM, only the valid parts are written. * Useful for all kinds of IO operations. * * addr - destination Atari RAM address * src - source Hatari memory address * len - number of bytes to copy * name - name / description if this memory copy for error messages * * Return true if whole copy was safe / valid. */ bool STMemory_SafeCopy(Uint32 addr, Uint8 *src, unsigned int len, const char *name) { Uint32 end; if (STMemory_ValidArea(addr, len)) { memcpy(&STRam[addr], src, len); return true; } Log_Printf(LOG_WARN, "Invalid '%s' RAM range 0x%x+%i!\n", name, addr, len); for (end = addr + len; addr < end; addr++, src++) { if (STMemory_ValidArea(addr, 1)) STRam[addr] = *src; } return false; }
/** * DebugInfo_GetSysbase: get and validate system base * return on success sysbase address (+ set rombase), on failure return zero */ static Uint32 DebugInfo_GetSysbase(Uint32 *rombase) { Uint32 sysbase = STMemory_ReadLong(OS_SYSBASE); if (!STMemory_ValidArea(sysbase, OS_HEADER_SIZE)) { fprintf(stderr, "Invalid TOS sysbase RAM address (0x%x)!\n", sysbase); return 0; } /* under TOS, sysbase = os_beg = TosAddress, but not under MiNT -> use os_beg */ *rombase = STMemory_ReadLong(sysbase+0x08); if (!STMemory_ValidArea(*rombase, OS_HEADER_SIZE)) { fprintf(stderr, "Invalid TOS sysbase ROM address (0x%x)!\n", *rombase); return 0; } if (*rombase != TosAddress) { fprintf(stderr, "os_beg (0x%x) != TOS address (0x%x), header in RAM not set up yet?\n", *rombase, TosAddress); return 0; } return sysbase; }
static bool nf_stderr(Uint32 stack, Uint32 subid, Uint32 *retval) { const char *str; Uint32 ptr; ptr = STMemory_ReadLong(stack); //Dprintf(("NF stderr(0x%x)\n", ptr)); if (!STMemory_ValidArea(ptr, 1)) { M68000_BusError(ptr, BUS_ERROR_READ); return false; } str = (const char *)STRAM_ADDR(ptr); *retval = fprintf(stderr, "%s", str); fflush(stderr); return true; }
static bool nf_name(Uint32 stack, Uint32 subid, Uint32 *retval) { Uint32 ptr, len; const char *str; char *buf; ptr = STMemory_ReadLong(stack); len = STMemory_ReadLong(stack + SIZE_LONG); Dprintf(("NF name[%d](0x%x, %d)\n", subid, ptr, len)); if (!STMemory_ValidArea(ptr, len)) { M68000_BusError(ptr, BUS_ERROR_WRITE); return false; } if (subid) { str = PROG_NAME; } else { str = "Hatari"; } buf = (char *)STRAM_ADDR(ptr); *retval = snprintf(buf, len, "%s", str); return true; }
/** * Check whether this is VDI/AES call and see if we need to re-direct * it to our own routines. Return true if VDI_Complete() function * needs to be called on OS call exit, otherwise return false. * * We enter here with Trap #2, so D0 tells which OS call it is (VDI/AES) * and D1 is pointer to VDI/AES vectors, i.e. Control, Intin, Ptsin etc... */ bool VDI_AES_Entry(void) { Uint16 call = Regs[REG_D0]; Uint32 TablePtr = Regs[REG_D1]; #if ENABLE_TRACING /* AES call? */ if (call == 0xC8) { if (!STMemory_ValidArea(TablePtr, 24)) { Log_Printf(LOG_WARN, "AES call failed due to invalid parameter block address 0x%x+%i\n", TablePtr, 24); return false; } /* store values for debugger "info aes" command */ AESControl = STMemory_ReadLong(TablePtr); AESGlobal = STMemory_ReadLong(TablePtr+4); AESIntin = STMemory_ReadLong(TablePtr+8); AESIntout = STMemory_ReadLong(TablePtr+12); AESAddrin = STMemory_ReadLong(TablePtr+16); AESAddrout = STMemory_ReadLong(TablePtr+20); AESOpCode = STMemory_ReadWord(AESControl); LOG_TRACE(TRACE_OS_AES, "AES call %3hd (%s)\n", AESOpCode, AES_Opcode2Name(AESOpCode)); /* using same special opcode trick doesn't work for * both VDI & AES as AES functions can be called * recursively and VDI calls happen inside AES calls. */ return false; } #endif /* VDI call? */ if (call == 0x73) { if (!STMemory_ValidArea(TablePtr, 20)) { Log_Printf(LOG_WARN, "VDI call failed due to invalid parameter block address 0x%x+%i\n", TablePtr, 20); return false; } /* store values for extended VDI resolution handling * and debugger "info vdi" command */ VDIControl = STMemory_ReadLong(TablePtr); VDIIntin = STMemory_ReadLong(TablePtr+4); VDIPtsin = STMemory_ReadLong(TablePtr+8); VDIIntout = STMemory_ReadLong(TablePtr+12); VDIPtsout = STMemory_ReadLong(TablePtr+16); VDIOpCode = STMemory_ReadWord(VDIControl); #if ENABLE_TRACING { Uint16 subcode = STMemory_ReadWord(VDIControl+2*5); LOG_TRACE(TRACE_OS_VDI, "VDI call %3hd/%3hd (%s)\n", VDIOpCode, subcode, VDI_Opcode2Name(VDIOpCode, subcode)); } #endif /* Only workstation open needs to be handled at trap return */ return bUseVDIRes && VDI_isWorkstationOpen(VDIOpCode); } LOG_TRACE((TRACE_OS_VDI|TRACE_OS_AES), "Trap #2 with D0 = 0x%hX\n", call); return false; }