|
|
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:
1.1.1.3 ! root 59: if ( !STMemory_CheckAreaType ( ptr, len, ABFLAG_RAM | ABFLAG_ROM ) ) {
! 60: M68000_BusError(ptr, BUS_ERROR_WRITE, BUS_ERROR_SIZE_BYTE, BUS_ERROR_ACCESS_DATA);
1.1 root 61: return false;
62: }
63: if (subid) {
64: str = PROG_NAME;
65: } else {
66: str = "Hatari";
67: }
1.1.1.3 ! root 68: buf = (char *)STMemory_STAddrToPointer ( ptr );
1.1 root 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:
1.1.1.3 ! root 97: if ( !STMemory_CheckAreaType ( ptr, 1, ABFLAG_RAM | ABFLAG_ROM ) ) {
! 98: M68000_BusError(ptr, BUS_ERROR_READ, BUS_ERROR_SIZE_BYTE, BUS_ERROR_ACCESS_DATA);
1.1 root 99: return false;
100: }
1.1.1.3 ! root 101: str = (const char *)STMemory_STAddrToPointer ( ptr );
1.1 root 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:
1.1.1.3 ! root 178: if ( !STMemory_CheckAreaType ( ptr, 1, ABFLAG_RAM | ABFLAG_ROM ) ) {
! 179: M68000_BusError(ptr, BUS_ERROR_READ, BUS_ERROR_SIZE_BYTE, BUS_ERROR_ACCESS_DATA);
1.1.1.2 root 180: return false;
181: }
1.1.1.3 ! root 182: buffer = (const char *)STMemory_STAddrToPointer ( ptr );
1.1.1.2 root 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);
1.1.1.3 ! root 232: if ( !STMemory_CheckAreaType ( ptr, FEATNAME_MAX, ABFLAG_RAM | ABFLAG_ROM ) ) {
! 233: M68000_BusError(ptr, BUS_ERROR_READ, BUS_ERROR_SIZE_BYTE, BUS_ERROR_ACCESS_DATA);
1.1 root 234: return false;
235: }
236:
1.1.1.3 ! root 237: name = (const char *)STMemory_STAddrToPointer ( 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.1.3 ! root 270: #ifndef WINUAE_FOR_HATARI
! 271: M68000_Exception(8, M68000_EXC_SRC_CPU);
! 272: #else
! 273: M68000_Exception(8, M68000_EXC_SRC_CPU);
! 274: #endif
1.1 root 275: return false;
276: }
277: stack += SIZE_LONG;
278: return features[idx].cb(stack, subid, retval);
279: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.