ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/SheepShaver/src/macos_util.cpp
Revision: 1.1
Committed: 2002-02-04T16:58:13Z (22 years, 3 months ago) by cebix
Branch: MAIN
Branch point for: cebix
Log Message:
Initial revision

File Contents

# User Rev Content
1 cebix 1.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 (*(uint32 *)XLM_RUN_MODE == MODE_EMUL_OP) {
164     M68kRegisters r;
165    
166     // Find shared library
167     static const uint16 proc1[] = {
168     0x558f, // subq.l #2,a7
169     0x2f08, // move.l a0,-(a7)
170     0x2f3c, 0x7077, 0x7063, // move.l #'pwpc',-(a7)
171     0x2f3c, 0, 1, // move.l #kReferenceCFrag,-(a7)
172     0x2f09, // move.l a1,-(a7)
173     0x2f0a, // move.l a2,-(a7)
174     0x2f0b, // move.l a3,-(a7)
175     0x3f3c, 1, // (GetSharedLibrary)
176     0xaa5a, // CFMDispatch
177     0x301f, // move.w (a7)+,d0
178     M68K_RTS
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], conn_id, main_addr));
186     if (r.d[0])
187     return NULL;
188    
189     // Find symbol
190     static const uint16 proc2[] = {
191     0x558f, // subq.l #2,a7
192     0x2f00, // move.l d0,-(a7)
193     0x2f08, // move.l a0,-(a7)
194     0x2f09, // move.l a1,-(a7)
195     0x2f0a, // move.l a2,-(a7)
196     0x3f3c, 5, // (FindSymbol)
197     0xaa5a, // CFMDispatch
198     0x301f, // move.w (a7)+,d0
199     M68K_RTS
200     };
201     r.d[0] = 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(" FindSymbol: ret %d, sym_addr %p, sym_class %ld\n", (int16)r.d[0], sym_addr, sym_class));
207     //!! CloseConnection()?
208     if (r.d[0])
209     return NULL;
210     else
211     return 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, conn_id, main_addr));
222     if (res)
223     return NULL;
224     res = FindSymbol(conn_id, sym, (void **)&sym_addr, &sym_class);
225     D(bug(" FindSymbol: ret %d, sym_addr %p, sym_class %ld\n", res, sym_addr, sym_class));
226     //!!?? CloseConnection(&conn_id);
227     if (res)
228     return NULL;
229     else
230     return 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     }