|
|
1.1 root 1: /*
2: * Hatari - natfeats.c
3: *
1.1.1.2 ! root 4: * Copyright (C) 2012-2014 by Eero Tamminen
1.1 root 5: *
6: * This file is distributed under the GNU General Public License, version 2
7: * or at your option any later version. Read the file gpl.txt for details.
8: *
9: * natfeats.c - Hatari Native features identification and call forwarding,
1.1.1.2 ! root 10: * modeled after similar code in Aranym (written by Petr Stehlik),
1.1 root 11: * specified here:
12: * http://wiki.aranym.org/natfeats/proposal
13: */
14: const char Natfeats_fileid[] = "Hatari natfeats.c : " __DATE__ " " __TIME__;
15:
16: #include <stdio.h>
17: #include "main.h"
18: #include "version.h"
19: #include "configuration.h"
20: #include "stMemory.h"
21: #include "m68000.h"
22: #include "natfeats.h"
1.1.1.2 ! root 23: #include "control.h"
! 24: #include "log.h"
1.1 root 25:
1.1.1.2 ! root 26:
! 27: /* whether to allow XBIOS(255) style
! 28: * Hatari command line parsing with "command" NF
! 29: */
! 30: #define NF_COMMAND 0
1.1 root 31:
32: /* TODO:
33: * - supervisor vs. user stack handling?
34: * - clipboard and hostfs native features?
35: */
36:
37:
1.1.1.2 ! root 38: /* ----------------------------------
! 39: * Native Features shared with Aranym
! 40: */
! 41:
! 42: /**
! 43: * NF_NAME - emulator name
! 44: * Stack arguments are:
! 45: * - pointer to buffer for emulator name, and
! 46: * - uint32_t for its size
! 47: * If subid is set, emulator name includes also version information
! 48: */
1.1 root 49: static bool nf_name(Uint32 stack, Uint32 subid, Uint32 *retval)
50: {
51: Uint32 ptr, len;
52: const char *str;
53: char *buf;
54:
55: ptr = STMemory_ReadLong(stack);
56: len = STMemory_ReadLong(stack + SIZE_LONG);
1.1.1.2 ! root 57: LOG_TRACE(TRACE_NATFEATS, "NF_NAME[%d](0x%x, %d)\n", subid, ptr, len);
1.1 root 58:
59: if (!STMemory_ValidArea(ptr, len)) {
60: M68000_BusError(ptr, BUS_ERROR_WRITE);
61: return false;
62: }
63: if (subid) {
64: str = PROG_NAME;
65: } else {
66: str = "Hatari";
67: }
68: buf = (char *)STRAM_ADDR(ptr);
69: *retval = snprintf(buf, len, "%s", str);
70: return true;
71: }
72:
1.1.1.2 ! root 73: /**
! 74: * NF_VERSION - NativeFeatures version
! 75: * returns version number
! 76: */
1.1 root 77: static bool nf_version(Uint32 stack, Uint32 subid, Uint32 *retval)
78: {
1.1.1.2 ! root 79: LOG_TRACE(TRACE_NATFEATS, "NF_VERSION() -> 0x00010000\n");
1.1 root 80: *retval = 0x00010000;
81: return true;
82: }
83:
1.1.1.2 ! root 84: /**
! 85: * NF_STDERR - print string to stderr
! 86: * Stack arguments are:
! 87: * - pointer to buffer containing the string
! 88: */
1.1 root 89: static bool nf_stderr(Uint32 stack, Uint32 subid, Uint32 *retval)
90: {
91: const char *str;
92: Uint32 ptr;
93:
94: ptr = STMemory_ReadLong(stack);
1.1.1.2 ! root 95: LOG_TRACE(TRACE_NATFEATS, "NF_STDERR(0x%x)\n", ptr);
1.1 root 96:
97: if (!STMemory_ValidArea(ptr, 1)) {
98: M68000_BusError(ptr, BUS_ERROR_READ);
99: return false;
100: }
101: str = (const char *)STRAM_ADDR(ptr);
102: *retval = fprintf(stderr, "%s", str);
103: fflush(stderr);
104: return true;
105: }
106:
1.1.1.2 ! root 107: /**
! 108: * NF_SHUTDOWN - exit emulator normally
! 109: * Needs to be called from supervisor mode
! 110: */
1.1 root 111: static bool nf_shutdown(Uint32 stack, Uint32 subid, Uint32 *retval)
112: {
1.1.1.2 ! root 113: LOG_TRACE(TRACE_NATFEATS, "NF_SHUTDOWN()\n");
1.1 root 114: ConfigureParams.Log.bConfirmQuit = false;
1.1.1.2 ! root 115: Main_RequestQuit(0);
1.1 root 116: return true;
117: }
118:
1.1.1.2 ! root 119: /* ----------------------------------
! 120: * Native Features specific to Hatari
! 121: */
! 122:
! 123: /**
! 124: * NF_EXIT - exit emulator with given exit code
! 125: * Stack arguments are:
! 126: * - emulator's int32_t exit value
! 127: */
! 128: static bool nf_exit(Uint32 stack, Uint32 subid, Uint32 *retval)
! 129: {
! 130: Sint32 exitval;
! 131:
! 132: ConfigureParams.Log.bConfirmQuit = false;
! 133: exitval = STMemory_ReadLong(stack);
! 134: LOG_TRACE(TRACE_NATFEATS, "NF_EXIT(%d)\n", exitval);
! 135: Main_RequestQuit(exitval);
! 136: return true;
! 137: }
! 138:
! 139: /**
! 140: * NF_DEBUGGER - invoke debugger
! 141: */
! 142: static bool nf_debugger(Uint32 stack, Uint32 subid, Uint32 *retval)
! 143: {
! 144: LOG_TRACE(TRACE_NATFEATS, "NF_DEBUGGER()\n");
! 145: M68000_SetSpecial(SPCFLAG_DEBUGGER);
! 146: return true;
! 147: }
! 148:
! 149: /**
! 150: * NF_FASTFORWARD - set fast forward state
! 151: * Stack arguments are:
! 152: * - state 0: off, >=1: on
! 153: */
! 154: static bool nf_fastforward(Uint32 stack, Uint32 subid, Uint32 *retval)
! 155: {
! 156: Uint32 val;
! 157:
! 158: val = STMemory_ReadLong(stack);
! 159: *retval = ConfigureParams.System.bFastForward;
! 160: LOG_TRACE(TRACE_NATFEATS, "NF_FASTFORWARD(%d -> %d)\n", *retval, val);
! 161: ConfigureParams.System.bFastForward = ( val ? true : false );
! 162: return true;
! 163: }
! 164:
! 165: #if NF_COMMAND
! 166: /**
! 167: * NF_COMMAND - execute Hatari (cli / debugger) command
! 168: * Stack arguments are:
! 169: * - pointer to command string
! 170: */
! 171: static bool nf_command(Uint32 stack, Uint32 subid, Uint32 *retval)
! 172: {
! 173: const char *buffer;
! 174: Uint32 ptr;
! 175:
! 176: ptr = STMemory_ReadLong(stack);
! 177:
! 178: if (!STMemory_ValidArea(ptr, 1)) {
! 179: M68000_BusError(ptr, BUS_ERROR_READ);
! 180: return false;
! 181: }
! 182: buffer = (const char *)STRAM_ADDR(ptr);
! 183: LOG_TRACE(TRACE_NATFEATS, "NF_COMMAND(0x%x \"%s\")\n", ptr, buffer);
! 184:
! 185: Control_ProcessBuffer(buffer);
! 186: return true;
! 187: }
! 188: #endif
! 189:
1.1 root 190: /* ---------------------------- */
191:
192: #define FEATNAME_MAX 16
193:
194: static const struct {
195: const char *name; /* feature name */
196: bool super; /* should be called only in supervisor mode */
197: bool (*cb)(Uint32 stack, Uint32 subid, Uint32 *retval);
198: } features[] = {
1.1.1.2 ! root 199: #if NF_COMMAND
! 200: { "NF_COMMAND", false, nf_command },
! 201: #endif
1.1 root 202: { "NF_NAME", false, nf_name },
203: { "NF_VERSION", false, nf_version },
204: { "NF_STDERR", false, nf_stderr },
1.1.1.2 ! root 205: { "NF_SHUTDOWN", true, nf_shutdown },
! 206: { "NF_EXIT", false, nf_exit },
! 207: { "NF_DEBUGGER", false, nf_debugger },
! 208: { "NF_FASTFORWARD", false, nf_fastforward }
1.1 root 209: };
210:
211: /* macros from Aranym */
212: #define ID_SHIFT 20
213: #define IDX2MASTERID(idx) (((idx)+1) << ID_SHIFT)
214: #define MASTERID2IDX(id) (((id) >> ID_SHIFT)-1)
215: #define MASKOUTMASTERID(id) ((id) & ((1L << ID_SHIFT)-1))
216:
217:
218: /**
219: * Set retval to internal ID for requested Native Feature,
220: * or zero if feature is unknown/unsupported.
221: *
222: * Return true if caller is to proceed normally,
223: * false if there was an exception.
224: */
225: bool NatFeat_ID(Uint32 stack, Uint32 *retval)
226: {
227: const char *name;
228: Uint32 ptr;
229: int i;
230:
231: ptr = STMemory_ReadLong(stack);
232: if (!STMemory_ValidArea(ptr, FEATNAME_MAX)) {
233: M68000_BusError(ptr, BUS_ERROR_READ);
234: return false;
235: }
236:
237: name = (const char *)STRAM_ADDR(ptr);
1.1.1.2 ! root 238: LOG_TRACE(TRACE_NATFEATS, "NF ID(0x%x \"%s\")\n", ptr, name);
1.1 root 239:
240: for (i = 0; i < ARRAYSIZE(features); i++) {
241: if (strcmp(features[i].name, name) == 0) {
242: *retval = IDX2MASTERID(i);
243: return true;
244: }
245: }
246: /* unknown feature */
247: *retval = 0;
248: return true;
249: }
250:
251: /**
252: * Do given Native Feature, if it is supported
253: * and set 'retval' accordingly.
254: *
255: * Return true if caller is to proceed normally,
256: * false if there was an exception.
257: */
258: bool NatFeat_Call(Uint32 stack, bool super, Uint32 *retval)
259: {
260: Uint32 subid = STMemory_ReadLong(stack);
261: unsigned int idx = MASTERID2IDX(subid);
262: subid = MASKOUTMASTERID(subid);
263:
264: if (idx >= ARRAYSIZE(features)) {
1.1.1.2 ! root 265: LOG_TRACE(TRACE_NATFEATS, "ERROR: invalid NF ID %d requested\n", idx);
1.1 root 266: return true; /* undefined */
267: }
268: if (features[idx].super && !super) {
1.1.1.2 ! root 269: LOG_TRACE(TRACE_NATFEATS, "ERROR: NF function %d called without supervisor mode\n", idx);
1.1 root 270: Exception(8, 0, M68000_EXC_SRC_CPU);
271: return false;
272: }
273: stack += SIZE_LONG;
274: return features[idx].cb(stack, subid, retval);
275: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.