]> git.sur5r.net Git - cc65/blob - src/sim65/paravirt.c
add gotox, gotoy, and gotoxy
[cc65] / src / sim65 / paravirt.c
1 /*****************************************************************************/
2 /*                                                                           */
3 /*                                paravirt.c                                 */
4 /*                                                                           */
5 /*                Paravirtualization for the sim65 6502 simulator            */
6 /*                                                                           */
7 /*                                                                           */
8 /*                                                                           */
9 /* (C) 2013-2013 Ullrich von Bassewitz                                       */
10 /*               Römerstrasse 52                                             */
11 /*               D-70794 Filderstadt                                         */
12 /* EMail:        uz@cc65.org                                                 */
13 /*                                                                           */
14 /*                                                                           */
15 /* This software is provided 'as-is', without any expressed or implied       */
16 /* warranty.  In no event will the authors be held liable for any damages    */
17 /* arising from the use of this software.                                    */
18 /*                                                                           */
19 /* Permission is granted to anyone to use this software for any purpose,     */
20 /* including commercial applications, and to alter it and redistribute it    */
21 /* freely, subject to the following restrictions:                            */
22 /*                                                                           */
23 /* 1. The origin of this software must not be misrepresented; you must not   */
24 /*    claim that you wrote the original software. If you use this software   */
25 /*    in a product, an acknowledgment in the product documentation would be  */
26 /*    appreciated but is not required.                                       */
27 /* 2. Altered source versions must be plainly marked as such, and must not   */
28 /*    be misrepresented as being the original software.                      */
29 /* 3. This notice may not be removed or altered from any source              */
30 /*    distribution.                                                          */
31 /*                                                                           */
32 /*****************************************************************************/
33
34
35
36 #include <string.h>
37 #include <stdlib.h>
38 #include <fcntl.h>
39 #if defined(_MSC_VER)
40 /* Microsoft compiler */
41 #  include <io.h>
42 #  pragma warning(disable : 4996)
43 #  define O_INITIAL O_BINARY
44 #else
45 /* Anyone else */
46 #  include <unistd.h>
47 #  define O_INITIAL 0
48 #endif
49
50 /* common */
51 #include "cmdline.h"
52 #include "print.h"
53 #include "xmalloc.h"
54
55 /* sim65 */
56 #include "6502.h"
57 #include "memory.h"
58 #include "paravirt.h"
59
60
61
62 /*****************************************************************************/
63 /*                                   Data                                    */
64 /*****************************************************************************/
65
66
67
68 typedef void (*PVFunc) (CPURegs* Regs);
69
70 static unsigned ArgStart;
71
72
73
74 /*****************************************************************************/
75 /*                                   Code                                    */
76 /*****************************************************************************/
77
78
79
80 static unsigned GetAX (CPURegs* Regs)
81 {
82     return Regs->AC + (Regs->XR << 8);
83 }
84
85
86
87 static void SetAX (CPURegs* Regs, unsigned Val)
88 {
89     Regs->AC = Val & 0xFF;
90     Val >>= 8;
91     Regs->XR = Val;
92 }
93
94
95
96 static void MemWriteWord (unsigned Addr, unsigned Val)
97 {
98     MemWriteByte (Addr, Val);
99     Val >>= 8;
100     MemWriteByte (Addr + 1, Val);
101 }
102
103
104
105 static unsigned char Pop (CPURegs* Regs)
106 {
107     return MemReadByte (0x0100 + ++Regs->SP);
108 }
109
110
111
112 static unsigned PopParam (unsigned char Incr)
113 {
114     unsigned SP = MemReadZPWord (0x00);
115     unsigned Val = MemReadWord (SP);
116     MemWriteWord (0x0000, SP + Incr);
117     return Val;
118 }
119
120
121
122 static void PVArgs (CPURegs* Regs)
123 {
124     unsigned ArgC = ArgCount - ArgStart;
125     unsigned ArgV = GetAX (Regs);
126     unsigned SP   = MemReadZPWord (0x00);
127     unsigned Args = SP - (ArgC + 1) * 2;
128
129     Print (stdout, 2, "PVArgs ($%04X)\n", ArgV);
130
131     MemWriteWord (ArgV, Args);
132
133     SP = Args;
134     while (ArgStart < ArgCount) {
135         unsigned I = 0;
136         const char* Arg = ArgVec[ArgStart++];
137         SP -= strlen (Arg) + 1;
138         do {
139             MemWriteByte (SP + I, Arg[I]);
140         }
141         while (Arg[I++]);
142
143         MemWriteWord (Args, SP);
144         Args += 2;
145     }
146     MemWriteWord (Args, 0x0000);
147
148     MemWriteWord (0x0000, SP);
149     SetAX (Regs, ArgC);
150 }
151
152
153
154 static void PVExit (CPURegs* Regs)
155 {
156     Print (stdout, 1, "PVExit ($%02X)\n", Regs->AC);
157
158     exit (Regs->AC);
159 }
160
161
162
163 static void PVOpen (CPURegs* Regs)
164 {
165     char Path[1024];
166     int OFlag = O_INITIAL;
167     unsigned RetVal, I = 0;
168
169     unsigned Mode  = PopParam (Regs->YR - 4);
170     unsigned Flags = PopParam (2);
171     unsigned Name  = PopParam (2);
172
173     do {
174         Path[I] = MemReadByte (Name++);
175     }
176     while (Path[I++]);
177
178     Print (stdout, 2, "PVOpen (\"%s\", $%04X)\n", Path, Flags);
179
180     switch (Flags & 0x03) {
181         case 0x01:
182             OFlag |= O_RDONLY;
183             break;
184         case 0x02:
185             OFlag |= O_WRONLY;
186             break;
187         case 0x03:
188             OFlag |= O_RDWR;
189             break;
190     }
191     if (Flags & 0x10) {
192         OFlag |= O_CREAT;
193     }
194     if (Flags & 0x20) {
195         OFlag |= O_TRUNC;
196     }
197     if (Flags & 0x40) {
198         OFlag |= O_APPEND;
199     }
200     if (Flags & 0x80) {
201         OFlag |= O_EXCL;
202     }
203
204     /* Avoid gcc warning */
205     (void) Mode;
206
207     RetVal = open (Path, OFlag);
208
209     SetAX (Regs, RetVal);
210 }
211
212
213
214 static void PVClose (CPURegs* Regs)
215 {
216     unsigned RetVal;
217
218     unsigned FD = GetAX (Regs);
219
220     Print (stdout, 2, "PVClose ($%04X)\n", FD);
221
222     RetVal = close (FD);
223
224     SetAX (Regs, RetVal);
225 }
226
227
228
229 static void PVRead (CPURegs* Regs)
230 {
231     unsigned char* Data;
232     unsigned RetVal, I = 0;
233
234     unsigned Count = GetAX (Regs);
235     unsigned Buf   = PopParam (2);
236     unsigned FD    = PopParam (2);
237
238     Print (stdout, 2, "PVRead ($%04X, $%04X, $%04X)\n", FD, Buf, Count);
239
240     Data = xmalloc (Count);
241
242     RetVal = read (FD, Data, Count);
243
244     if (RetVal != (unsigned) -1) {
245         while (I < RetVal) {
246             MemWriteByte (Buf++, Data[I++]);
247         }
248     }
249     xfree (Data);
250
251     SetAX (Regs, RetVal);
252 }
253
254
255
256 static void PVWrite (CPURegs* Regs)
257 {
258     unsigned char* Data;
259     unsigned RetVal, I = 0;
260
261     unsigned Count = GetAX (Regs);
262     unsigned Buf   = PopParam (2);
263     unsigned FD    = PopParam (2);
264
265     Print (stdout, 2, "PVWrite ($%04X, $%04X, $%04X)\n", FD, Buf, Count);
266
267     Data = xmalloc (Count);
268     while (I < Count) {
269         Data[I++] = MemReadByte (Buf++);
270     }
271
272     RetVal = write (FD, Data, Count);
273
274     xfree (Data);
275
276     SetAX (Regs, RetVal);
277 }
278
279
280
281 static const PVFunc Hooks[] = {
282     PVArgs,
283     PVExit,
284     PVOpen,
285     PVClose,
286     PVRead,
287     PVWrite,
288 };
289
290
291
292 void ParaVirtInit (unsigned aArgStart)
293 /* Initialize the paravirtualization subsystem */
294 {
295     ArgStart = aArgStart;
296 };
297
298
299
300 void ParaVirtHooks (CPURegs* Regs)
301 /* Potentially execute paravirtualization hooks */
302 {
303     /* Check for paravirtualization address range */
304     if (Regs->PC <  0xFFF0 ||
305         Regs->PC >= 0xFFF0 + sizeof (Hooks) / sizeof (Hooks[0])) {
306         return;
307     }
308
309     /* Call paravirtualization hook */
310     Hooks[Regs->PC - 0xFFF0] (Regs);
311
312     /* Simulate RTS */
313     Regs->PC = Pop(Regs) + (Pop(Regs) << 8) + 1;
314 }