ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/SheepShaver/src/macos_util.cpp
Revision: 1.3
Committed: 2003-09-29T22:47:39Z (20 years, 7 months ago) by gbeauche
Branch: MAIN
Changes since 1.2: +8 -8 lines
Log Message:
Little endian fixes to FindLibSymbol(). This is not 64-bit clean and this
needs to go through a more appropriate thunking mechanism.

File Contents

# Content
1 /*
2 * macos_util.cpp - MacOS definitions/utility functions
3 *
4 * SheepShaver (C) 1997-2002 Christian Bauer and Marc Hellwig
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21 #include "sysdeps.h"
22 #include "cpu_emulation.h"
23 #include "main.h"
24 #include "sony.h"
25 #include "disk.h"
26 #include "cdrom.h"
27 #include "xlowmem.h"
28 #include "emul_op.h"
29 #include "macos_util.h"
30
31 #define DEBUG 0
32 #include "debug.h"
33
34
35 // Function pointers
36 typedef long (*cu_ptr)(void *, uint32);
37 static uint32 cu_tvect = 0;
38 static inline long CallUniversal(void *arg1, uint32 arg2)
39 {
40 return (long)CallMacOS2(cu_ptr, cu_tvect, arg1, arg2);
41 }
42 typedef int16 (*gsl_ptr)(char *, uint32, uint32, uint32 *, void **, char *);
43 static uint32 gsl_tvect = 0;
44 static inline int16 GetSharedLibrary(char *arg1, uint32 arg2, uint32 arg3, uint32 *arg4, void **arg5, char *arg6)
45 {
46 return (int16)CallMacOS6(gsl_ptr, gsl_tvect, arg1, arg2, arg3, arg4, arg5, arg6);
47 }
48 typedef int16 (*fs_ptr)(uint32, char *, void **, uint32 *);
49 static uint32 fs_tvect = 0;
50 static inline int16 FindSymbol(uint32 arg1, char *arg2, void **arg3, uint32 *arg4)
51 {
52 return (int16)CallMacOS4(fs_ptr, fs_tvect, arg1, arg2, arg3, arg4);
53 }
54 typedef int16 (*cc_ptr)(uint32 *);
55 static uint32 cc_tvect = 0;
56 static inline int16 CloseConnection(uint32 *arg1)
57 {
58 return (int16)CallMacOS1(cc_ptr, cc_tvect, arg1);
59 }
60
61
62 /*
63 * Reset MacOS utilities
64 */
65
66 void MacOSUtilReset(void)
67 {
68 cu_tvect = 0;
69 gsl_tvect = 0;
70 fs_tvect = 0;
71 cc_tvect = 0;
72 }
73
74
75 /*
76 * Enqueue QElem to list
77 */
78
79 void Enqueue(uint32 elem, uint32 list)
80 {
81 WriteMacInt32(elem + qLink, 0);
82 if (!ReadMacInt32(list + qTail)) {
83 WriteMacInt32(list + qHead, elem);
84 WriteMacInt32(list + qTail, elem);
85 } else {
86 WriteMacInt32(ReadMacInt32(list + qTail) + qLink, elem);
87 WriteMacInt32(list + qTail, elem);
88 }
89 }
90
91
92 /*
93 * Find first free drive number, starting at num
94 */
95
96 static bool is_drive_number_free(int num)
97 {
98 uint32 e = ReadMacInt32(0x308 + qHead);
99 while (e) {
100 uint32 d = e - dsQLink;
101 if ((int)ReadMacInt16(d + dsQDrive) == num)
102 return false;
103 e = ReadMacInt32(e + qLink);
104 }
105 return true;
106 }
107
108 int FindFreeDriveNumber(int num)
109 {
110 while (!is_drive_number_free(num))
111 num++;
112 return num;
113 }
114
115
116 /*
117 * Mount volume with given file handle (call this function when you are unable to
118 * do automatic media change detection and the user has to press a special key
119 * or something to mount a volume; this function will check if there's really a
120 * volume in the drive with SysIsDiskInserted(); volumes which are present on startup
121 * are automatically mounted)
122 */
123
124 void MountVolume(void *fh)
125 {
126 SonyMountVolume(fh) || DiskMountVolume(fh) || CDROMMountVolume(fh);
127 }
128
129
130 /*
131 * Calculate disk image file layout given file size and first 256 data bytes
132 */
133
134 void FileDiskLayout(loff_t size, uint8 *data, loff_t &start_byte, loff_t &real_size)
135 {
136 if (size == 419284 || size == 838484) {
137 // 400K/800K DiskCopy image, 84 byte header
138 start_byte = 84;
139 real_size = (size - 84) & ~0x1ff;
140 } else {
141 // 0..511 byte header
142 start_byte = size & 0x1ff;
143 real_size = size - start_byte;
144 }
145 }
146
147
148 /*
149 * Find symbol in shared library (using CFM)
150 * lib and sym must be Pascal strings!
151 */
152
153 void *FindLibSymbol(char *lib, char *sym)
154 {
155 uint32 conn_id = 0;
156 void *main_addr = NULL;
157 char err[256] = "";
158 uint32 *sym_addr = NULL;
159 uint32 sym_class = 0;
160
161 D(bug("FindLibSymbol %s in %s...\n", sym+1, lib+1));
162
163 if (ReadMacInt32(XLM_RUN_MODE) == MODE_EMUL_OP) {
164 M68kRegisters r;
165
166 // Find shared library
167 static const uint8 proc1[] = {
168 0x55, 0x8f, // subq.l #2,a7
169 0x2f, 0x08, // move.l a0,-(a7)
170 0x2f, 0x3c, 0x70, 0x77, 0x70, 0x63, // move.l #'pwpc',-(a7)
171 0x2f, 0x3c, 0x00, 0x00, 0x00, 0x01, // move.l #kReferenceCFrag,-(a7)
172 0x2f, 0x09, // move.l a1,-(a7)
173 0x2f, 0x0a, // move.l a2,-(a7)
174 0x2f, 0x0b, // move.l a3,-(a7)
175 0x3f, 0x3c, 0x00, 0x01, // (GetSharedLibrary)
176 0xaa, 0x5a, // CFMDispatch
177 0x30, 0x1f, // move.w (a7)+,d0
178 M68K_RTS >> 8, M68K_RTS & 0xff
179 };
180 r.a[0] = (uint32)lib;
181 r.a[1] = (uint32)&conn_id;
182 r.a[2] = (uint32)&main_addr;
183 r.a[3] = (uint32)err;
184 Execute68k((uint32)proc1, &r);
185 D(bug(" GetSharedLibrary: ret %d, connection ID %ld, main %p\n", (int16)r.d[0], ntohl(conn_id), ntohl((uintptr)main_addr)));
186 if (r.d[0])
187 return NULL;
188
189 // Find symbol
190 static const uint8 proc2[] = {
191 0x55, 0x8f, // subq.l #2,a7
192 0x2f, 0x00, // move.l d0,-(a7)
193 0x2f, 0x08, // move.l a0,-(a7)
194 0x2f, 0x09, // move.l a1,-(a7)
195 0x2f, 0x0a, // move.l a2,-(a7)
196 0x3f, 0x3c, 0x00, 0x05, // (FindSymbol)
197 0xaa, 0x5a, // CFMDispatch
198 0x30, 0x1f, // move.w (a7)+,d0
199 M68K_RTS >> 8, M68K_RTS & 0xff
200 };
201 r.d[0] = ntohl(conn_id);
202 r.a[0] = (uint32)sym;
203 r.a[1] = (uint32)&sym_addr;
204 r.a[2] = (uint32)&sym_class;
205 Execute68k((uint32)proc2, &r);
206 D(bug(" FindSymbol1: ret %d, sym_addr %p, sym_class %ld\n", (int16)r.d[0], ntohl((uintptr)sym_addr), ntohl(sym_class)));
207 //!! CloseConnection()?
208 if (r.d[0])
209 return NULL;
210 else
211 return (void *)ntohl((uintptr)sym_addr);
212
213 } else {
214
215 if (GetSharedLibrary == NULL || FindSymbol == NULL) {
216 printf("FATAL: FindLibSymbol() called too early\n");
217 return 0;
218 }
219 int16 res;
220 res = GetSharedLibrary(lib, FOURCC('p','w','p','c'), 1, &conn_id, &main_addr, err);
221 D(bug(" GetSharedLibrary: ret %d, connection ID %ld, main %p\n", res, ntohl(conn_id), ntohl((uintptr)main_addr)));
222 if (res)
223 return NULL;
224 res = FindSymbol(ntohl(conn_id), sym, (void **)&sym_addr, &sym_class);
225 D(bug(" FindSymbol: ret %d, sym_addr %p, sym_class %ld\n", res, ntohl((uintptr)sym_addr), ntohl(sym_class)));
226 //!!?? CloseConnection(&conn_id);
227 if (res)
228 return NULL;
229 else
230 return (void *)ntohl((uintptr)sym_addr);
231 }
232 }
233
234
235 /*
236 * Find CallUniversalProc() TVector
237 */
238
239 void InitCallUniversalProc()
240 {
241 cu_tvect = (uint32)FindLibSymbol("\014InterfaceLib", "\021CallUniversalProc");
242 D(bug("CallUniversalProc TVECT at %08lx\n", cu_tvect));
243 if (cu_tvect == 0) {
244 printf("FATAL: Can't find CallUniversalProc()\n");
245 QuitEmulator();
246 }
247
248 gsl_tvect = (uint32)FindLibSymbol("\014InterfaceLib", "\020GetSharedLibrary");
249 D(bug("GetSharedLibrary TVECT at %08lx\n", gsl_tvect));
250 if (gsl_tvect == 0) {
251 printf("FATAL: Can't find GetSharedLibrary()\n");
252 QuitEmulator();
253 }
254
255 fs_tvect = (uint32)FindLibSymbol("\014InterfaceLib", "\012FindSymbol");
256 D(bug("FindSymbol TVECT at %08lx\n", fs_tvect));
257 if (fs_tvect == 0) {
258 printf("FATAL: Can't find FindSymbol()\n");
259 QuitEmulator();
260 }
261
262 cc_tvect = (uint32)FindLibSymbol("\014InterfaceLib", "\017CloseConnection");
263 D(bug("CloseConnection TVECT at %08lx\n", cc_tvect));
264 if (cc_tvect == 0) {
265 printf("FATAL: Can't find CloseConnection()\n");
266 QuitEmulator();
267 }
268 }
269
270
271 /*
272 * CallUniversalProc
273 */
274
275 long CallUniversalProc(void *upp, uint32 info)
276 {
277 if (cu_tvect == 0) {
278 printf("FATAL: CallUniversalProc() called too early\n");
279 return 0;
280 }
281 return CallUniversal(upp, info);
282 }
283
284
285 /*
286 * Convert time_t value to MacOS time (seconds since 1.1.1904)
287 */
288
289 uint32 TimeToMacTime(time_t t)
290 {
291 // This code is taken from glibc 2.2
292
293 // Convert to number of seconds elapsed since 1-Jan-1904
294 struct tm *local = localtime(&t);
295 const int TM_EPOCH_YEAR = 1900;
296 const int MAC_EPOCH_YEAR = 1904;
297 int a4 = ((local->tm_year + TM_EPOCH_YEAR) >> 2) - !(local->tm_year & 3);
298 int b4 = (MAC_EPOCH_YEAR >> 2) - !(MAC_EPOCH_YEAR & 3);
299 int a100 = a4 / 25 - (a4 % 25 < 0);
300 int b100 = b4 / 25 - (b4 % 25 < 0);
301 int a400 = a100 >> 2;
302 int b400 = b100 >> 2;
303 int intervening_leap_days = (a4 - b4) - (a100 - b100) + (a400 - b400);
304 uint32 days = local->tm_yday + 365 * (local->tm_year - 4) + intervening_leap_days;
305 return local->tm_sec + 60 * (local->tm_min + 60 * (local->tm_hour + 24 * days));
306 }