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