|
|
1.1 root 1: /*
2: * UAE - The Un*x Amiga Emulator
3: *
4: * OS specific functions
5: *
6: * (c) 1995 Bernd Schmidt
1.1.1.2 ! root 7: * (c) 1996 Marcus Sundberg
1.1 root 8: */
9:
1.1.1.2 ! root 10: #include "sysconfig.h"
! 11: #include "sysdeps.h"
1.1 root 12:
13: #include "config.h"
14: #include "options.h"
15: #include "memory.h"
16: #include "custom.h"
17: #include "os.h"
18:
1.1.1.2 ! root 19: #ifdef HAVE_LINUX_JOYSTICK_H
1.1 root 20:
21: static int js0;
1.1.1.2 ! root 22: static int joystickpresent = 0;
1.1 root 23:
24: struct JS_DATA_TYPE jscal;
25:
1.1.1.2 ! root 26: void read_joystick(UWORD *dir, int *button)
1.1 root 27: {
28: static int minx = MAXINT, maxx = MININT,
29: miny = MAXINT, maxy = MININT;
1.1.1.2 ! root 30: int left = 0, right = 0, top = 0, bot = 0;
1.1 root 31: struct JS_DATA_TYPE buffer;
32: int len;
33:
34: *dir = 0;
1.1.1.2 ! root 35: *button = 0;
1.1 root 36: if (!joystickpresent)
37: return;
38:
39: len = read(js0, &buffer, sizeof(buffer));
40: if (len != sizeof(buffer))
41: return;
42:
43: if (buffer.x < minx) minx = buffer.x;
44: if (buffer.y < miny) miny = buffer.y;
45: if (buffer.x > maxx) maxx = buffer.x;
46: if (buffer.y > maxy) maxy = buffer.y;
47:
48: if (buffer.x < (minx + (maxx-minx)/3))
1.1.1.2 ! root 49: left = 1;
1.1 root 50: else if (buffer.x > (minx + 2*(maxx-minx)/3))
1.1.1.2 ! root 51: right = 1;
1.1 root 52:
53: if (buffer.y < (miny + (maxy-miny)/3))
1.1.1.2 ! root 54: top = 1;
1.1 root 55: else if (buffer.y > (miny + 2*(maxy-miny)/3))
1.1.1.2 ! root 56: bot = 1;
1.1 root 57:
58: if (left) top = !top;
59: if (right) bot = !bot;
60: *dir = bot | (right << 1) | (top << 8) | (left << 9);
61: *button = (buffer.buttons & 3) != 0;
62: }
63:
64: void init_joystick(void)
65: {
66: js0 = open("/dev/js0", O_RDONLY);
67: if (js0 < 0)
68: return;
1.1.1.2 ! root 69: joystickpresent = 1;
1.1 root 70: }
71:
72: void close_joystick(void)
73: {
74: if (joystickpresent)
1.1.1.2 ! root 75: close(js0);
! 76: }
! 77:
! 78: #elif defined(__DOS__)
! 79:
! 80: static int joystickpresent = 0;
! 81:
! 82: void read_joystick(UWORD *dir, int *button)
! 83: {
! 84: static int minx = MAXINT, maxx = MININT,
! 85: miny = MAXINT, maxy = MININT;
! 86: int left = 0, right = 0, top = 0, bot = 0;
! 87: char JoyPort;
! 88: int laps, JoyX, JoyY;
! 89:
! 90: *dir = 0;
! 91: *button = 0;
! 92: if (!joystickpresent)
! 93: return;
! 94:
! 95: JoyX = 0;
! 96: JoyY = 0;
! 97: laps = 0;
! 98: __asm__ __volatile__("cli");
! 99: outportb(0x201, 0xff);
! 100: do {
! 101: JoyPort = inportb(0x201);
! 102: JoyX = JoyX + (JoyPort & 1);
! 103: JoyY = JoyY + ((JoyPort & 2) >> 1);
! 104: laps++;
! 105: } while(((JoyPort & 3) != 0) && (laps != 65535));
! 106: __asm__ __volatile__("sti");
! 107:
! 108: if (JoyX < minx) minx = JoyX;
! 109: if (JoyY < miny) miny = JoyY;
! 110: if (JoyX > maxx) maxx = JoyX;
! 111: if (JoyY > maxy) maxy = JoyY;
! 112:
! 113: if (JoyX < (minx + (maxx-minx)/3))
! 114: left = 1;
! 115: else if (JoyX > (minx + 2*(maxx-minx)/3))
! 116: right = 1;
! 117:
! 118: if (JoyY < (miny + (maxy-miny)/3))
! 119: top = 1;
! 120: else if (JoyY > (miny + 2*(maxy-miny)/3))
! 121: bot = 1;
! 122:
! 123: if (left) top = !top;
! 124: if (right) bot = !bot;
! 125: *dir = bot | (right << 1) | (top << 8) | (left << 9);
! 126: *button = ((~JoyPort) & 48) != 0;
! 127: }
! 128:
! 129: void init_joystick(void)
! 130: {
! 131: int laps = 0;
! 132: char JoyPort;
! 133: __asm__ __volatile__("cli");
! 134: outportb(0x201, 0xff);
! 135: do {
! 136: JoyPort = inportb(0x201);
! 137: laps++;
! 138: } while(((JoyPort & 3) != 0) && (laps != 65535));
! 139: __asm__ __volatile__("sti");
! 140: if (laps != 65535)
! 141: joystickpresent = 1;
! 142: }
! 143:
! 144: void close_joystick(void)
! 145: {
1.1 root 146: }
147:
1.1.1.2 ! root 148: #else
! 149: void read_joystick(UWORD *dir, int *button)
1.1 root 150: {
151: *dir = 0;
1.1.1.2 ! root 152: *button = 0;
1.1 root 153: }
154:
155: void init_joystick(void)
156: {
157: }
158:
159: void close_joystick(void)
160: {
161: }
1.1.1.2 ! root 162:
1.1 root 163: #endif
164:
165: CPTR audlc[4], audpt[4];
166: UWORD audvol[4], audper[4], audlen[4], audwlen[4];
167: int audwper[4];
168: UWORD auddat[4];
169: int audsnum[4];
170:
171: /* Audio states. This is not an exact representation of the Audio State Machine
172: * (HRM p. 166), but a simplification. To be honest, I don't completely
173: * understand that picture yet.
174: */
175: int audst[4];
176:
1.1.1.2 ! root 177: int sound_table[256][64];
! 178:
! 179: static void init_sound_table16(void)
! 180: {
! 181: int i,j;
! 182:
! 183: for (i = 0; i < 256; i++)
! 184: for (j = 0; j < 64; j++)
! 185: sound_table[i][j] = j * (BYTE)i;
! 186: }
! 187:
! 188: static void init_sound_table8(void)
! 189: {
! 190: int i,j;
! 191:
! 192: for (i = 0; i < 256; i++)
! 193: for (j = 0; j < 64; j++)
! 194: sound_table[i][j] = (j * (BYTE)i) / 256;
! 195: }
! 196:
1.1 root 197: #ifdef LINUX_SOUND
198:
1.1.1.2 ! root 199: #include <sys/ioctl.h>
1.1 root 200: #include <sys/soundcard.h>
201:
202: static const int n_frames = 10;
203:
204: /* The buffer is too large... */
205: static UWORD buffer[44100], *bufpt;
1.1.1.2 ! root 206: static UBYTE snddata[4];
1.1 root 207:
208: static int frames = 0;
209: static int smplcnt = 0;
1.1.1.2 ! root 210: static int dsprate, dspbits, dspomit = 0;
! 211: static int sndbufsize;
1.1 root 212:
213: static int sfd;
1.1.1.2 ! root 214: static int have_sound;
1.1 root 215:
1.1.1.2 ! root 216: int init_sound (void)
1.1 root 217: {
218: int tmp;
1.1.1.2 ! root 219: int rate;
! 220:
! 221: unsigned long formats;
! 222:
1.1 root 223: sfd = open ("/dev/dsp", O_WRONLY);
224: have_sound = !(sfd < 0);
225: if (!have_sound) {
1.1.1.2 ! root 226: return 0;
1.1 root 227: }
228:
1.1.1.2 ! root 229: ioctl (sfd, SNDCTL_DSP_GETFMTS, &formats);
! 230:
! 231: tmp = 0x0004000D;
! 232: ioctl (sfd, SNDCTL_DSP_SETFRAGMENT, &tmp);
! 233: ioctl (sfd, SNDCTL_DSP_GETBLKSIZE, &sndbufsize);
! 234: #ifndef LINUX_SOUND_SLOW_MACHINE
! 235: dspbits = 16;
! 236: ioctl(sfd, SNDCTL_DSP_SAMPLESIZE, &dspbits);
! 237: ioctl(sfd, SOUND_PCM_READ_BITS, &dspbits);
! 238: if (dspbits != 16)
! 239: #endif
! 240: {
! 241: dspbits = 8;
! 242: ioctl(sfd, SNDCTL_DSP_SAMPLESIZE, &dspbits);
! 243: ioctl(sfd, SOUND_PCM_READ_BITS, &dspbits);
! 244: if (dspbits != 8)
! 245: return 0;
! 246: }
! 247:
1.1 root 248: tmp = 0;
249: ioctl(sfd, SNDCTL_DSP_STEREO, &tmp);
250:
1.1.1.2 ! root 251: #ifndef LINUX_SOUND_SLOW_MACHINE
! 252: dsprate = 0;
! 253: rate = 44100;
! 254: ioctl(sfd, SNDCTL_DSP_SPEED, &rate);
! 255: ioctl(sfd, SOUND_PCM_READ_RATE, &rate);
! 256: if (rate < 43000 || rate > 45000)
! 257: #endif
! 258: {
! 259: dsprate = 1;
! 260: rate = 22050;
! 261: ioctl(sfd, SNDCTL_DSP_SPEED, &rate);
! 262: ioctl(sfd, SOUND_PCM_READ_RATE, &rate);
! 263: /* Some soundcards return 22222 here. */
! 264: if (rate < 21000 || rate > 23000)
! 265: return 0;
! 266: }
! 267: if (dspbits == 16) {
! 268: /* Will this break horribly on Linux/Alpha? Possible... */
! 269: if (!(formats & AFMT_S16_LE))
! 270: return 0;
! 271: init_sound_table16 ();
! 272: } else {
! 273: if (!(formats & AFMT_U8))
! 274: return 0;
! 275: init_sound_table8 ();
! 276: }
! 277: printf ("Sound driver found and configured for %d bits at %d Hz, buffer is %d bytes\n",
! 278: dspbits, rate, sndbufsize);
1.1 root 279: audst[0] = audst[1] = audst[2] = audst[3] = 0;
280: bufpt = buffer;
281: frames = n_frames;
282: smplcnt = 0;
1.1.1.2 ! root 283: return 1;
1.1 root 284: }
285:
286: static void channel_reload (int c)
287: {
288: audst[c] = 1;
289: audpt[c] = audlc[c];
290: audwper[c] = 0;
291: audwlen[c] = audlen[c];
292: audsnum[c] = 1;
293: }
294:
295: void do_sound (void)
296: {
297: smplcnt -= 227;
298: while (smplcnt < 0) {
299: int i;
300: smplcnt += 80;
1.1.1.2 ! root 301: dspomit ^= dsprate;
! 302:
1.1 root 303: for(i = 0; i < 4; i++) {
304: if (dmaen (1<<i)) {
305: if (audst[i] == 0) {
306: /* DMA was turned on for this channel */
307: channel_reload (i);
308: continue;
309: }
310:
311: if (audwper[i] <= 0) {
312: audwper[i] += audper[i];
313: if (audst[i] == 1) {
314: /* Starting a sample, cause interrupt */
315: put_word (0xDFF09C, 0x8000 | (0x80 << i));
316: audst[i] = 2;
317: }
318: audsnum[i] ^= 1;
319: if (audsnum[i] == 0) {
320: auddat[i] = get_word (audpt[i]);
321: audpt[i] += 2;
322: audwlen[i]--;
323: if (audwlen[i] == 0) {
324: channel_reload (i);
325: }
1.1.1.2 ! root 326: }
! 327: }
! 328: if (adkcon & (0x11 << i)) {
! 329: snddata[i] = 0;
! 330: audsnum[i] ^= 2;
! 331: audsnum[i] |= 1;
! 332: if (i < 3) {
! 333: if (adkcon & (0x11 << i)) {
! 334: if (audsnum[i] & 2)
! 335: audvol[i+1] = auddat[i];
! 336: else
! 337: audper[i+1] = auddat[i];
! 338: } else if (adkcon & (1 << i)) {
! 339: audvol[i+1] = auddat[i];
! 340: } else {
! 341: audper[i+1] = auddat[i];
! 342: }
! 343: }
! 344: } else {
! 345: snddata[i] = audsnum[i] & 1 ? auddat[i] : auddat[i] >> 8;
1.1 root 346: }
347: audwper[i] -= 80;
348: } else
349: audst[i] = snddata[i] = 0;
350: }
1.1.1.2 ! root 351: if (dspbits == 16) {
! 352: if (dspomit == 0)
! 353: *bufpt++ = (sound_table[snddata[0]][audvol[0]]
! 354: + sound_table[snddata[1]][audvol[1]]
! 355: + sound_table[snddata[2]][audvol[2]]
! 356: + sound_table[snddata[3]][audvol[3]]);
! 357: } else {
! 358: unsigned char *bp = (unsigned char *)bufpt;
! 359: if (dspomit == 0)
! 360: *bp++ = (sound_table[snddata[0]][audvol[0]]
! 361: + sound_table[snddata[1]][audvol[1]]
! 362: + sound_table[snddata[2]][audvol[2]]
! 363: + sound_table[snddata[3]][audvol[3]] + 128);
! 364: bufpt = (UWORD *)bp;
! 365: }
! 366: if ((char *)bufpt - (char *)buffer >= sndbufsize) {
! 367: write(sfd, buffer, sndbufsize);
! 368: bufpt = buffer;
! 369: }
1.1 root 370: }
371: }
372:
1.1.1.2 ! root 373: #elif defined(AF_SOUND)
! 374:
! 375: #include <AF/AFlib.h>
! 376:
! 377: /* The buffer is too large... */
! 378: static UWORD buffer[44100], *bufpt;
! 379: static UBYTE snddata[4];
! 380:
! 381: static int smplcnt = 0;
! 382: static int dspbits = 0;
! 383: static int sndbufsize;
! 384:
! 385: static AFAudioConn *aud;
! 386: static AC ac;
! 387: static long count = 0;
! 388: static long aftime;
! 389: static int rate;
! 390: static int freq_divisor;
! 391:
! 392:
! 393: static int have_sound;
! 394:
! 395: int init_sound (void)
1.1 root 396: {
1.1.1.2 ! root 397: AFSetACAttributes attributes;
! 398: AFDeviceDescriptor *aDev;
! 399: int device;
! 400:
! 401: aud = AFOpenAudioConn(NULL);
! 402: have_sound = !(aud == NULL);
! 403: if (!have_sound) {
! 404: return 0;
1.1 root 405: }
1.1.1.2 ! root 406:
! 407: for(device = 0; device < ANumberOfAudioDevices(aud); device++) {
! 408: aDev = AAudioDeviceDescriptor(aud, device);
! 409: rate = aDev->playSampleFreq;
! 410: sndbufsize = (rate / 8) * 4;
! 411: if(aDev->inputsFromPhone == 0
! 412: && aDev->outputsToPhone == 0
! 413: && aDev->playNchannels == 1)
! 414: break;
! 415: }
! 416: if (device == ANumberOfAudioDevices(aud)) {
! 417: return 0;
! 418: }
! 419:
! 420: dspbits = 16;
! 421: attributes.type = LIN16;
! 422: ac = AFCreateAC(aud, device, ACEncodingType, &attributes);
! 423: aftime = AFGetTime(ac);
! 424:
! 425: if (dspbits == 16) {
! 426: init_sound_table16 ();
! 427: } else {
! 428: init_sound_table8 ();
! 429: }
! 430:
! 431: freq_divisor = 44100 / rate;
! 432:
! 433: audst[0] = audst[1] = audst[2] = audst[3] = 0;
! 434: bufpt = buffer;
! 435: smplcnt = 0;
! 436: printf ("Sound driver found and configured for %d bits at %d Hz, buffer is %d bytes\n", dspbits, rate, sndbufsize);
! 437: return 1;
1.1 root 438: }
439:
1.1.1.2 ! root 440: static void channel_reload (int c)
! 441: {
! 442: audst[c] = 1;
! 443: audpt[c] = audlc[c];
! 444: audwper[c] = 0;
! 445: audwlen[c] = audlen[c];
! 446: audsnum[c] = 1;
! 447: }
! 448:
! 449: void do_sound (void)
! 450: {
! 451: smplcnt -= 227;
! 452: while (smplcnt < 0) {
! 453: int i;
! 454: smplcnt += 80;
! 455:
! 456: for(i = 0; i < 4; i++) {
! 457: if (dmaen (1<<i)) {
! 458: if (audst[i] == 0) {
! 459: /* DMA was turned on for this channel */
! 460: channel_reload (i);
! 461: continue;
! 462: }
! 463:
! 464: if (audwper[i] <= 0) {
! 465: audwper[i] += audper[i];
! 466: if (audst[i] == 1) {
! 467: /* Starting a sample, cause interrupt */
! 468: put_word (0xDFF09C, 0x8000 | (0x80 << i));
! 469: audst[i] = 2;
! 470: }
! 471: audsnum[i] ^= 1;
! 472: if (audsnum[i] == 0) {
! 473: auddat[i] = get_word (audpt[i]);
! 474: audpt[i] += 2;
! 475: audwlen[i]--;
! 476: if (audwlen[i] == 0) {
! 477: channel_reload (i);
! 478: }
! 479: }
! 480: }
! 481: if (adkcon & (0x11 << i)) {
! 482: snddata[i] = 0;
! 483: audsnum[i] ^= 2;
! 484: audsnum[i] |= 1;
! 485: if (i < 3) {
! 486: if (adkcon & (0x11 << i)) {
! 487: if (audsnum[i] & 2)
! 488: audvol[i+1] = auddat[i];
! 489: else
! 490: audper[i+1] = auddat[i];
! 491: } else if (adkcon & (1 << i)) {
! 492: audvol[i+1] = auddat[i];
! 493: } else {
! 494: audper[i+1] = auddat[i];
! 495: }
! 496: }
! 497: } else {
! 498: snddata[i] = audsnum[i] & 1 ? auddat[i] : auddat[i] >> 8;
! 499: }
! 500: audwper[i] -= 80;
! 501: } else
! 502: audst[i] = snddata[i] = 0;
! 503: }
! 504: if ((count++ % frq_divisor) == 0) {
! 505: long size;
! 506: *bufpt++ = (sound_table[snddata[0]][audvol[0]]
! 507: + sound_table[snddata[1]][audvol[1]]
! 508: + sound_table[snddata[2]][audvol[2]]
! 509: + sound_table[snddata[3]][audvol[3]];
! 510: size = (char *)bufpt - (char *)buffer;
! 511: if (size >= sndbufsize) {
! 512: if (AFGetTime(ac) > aftime)
! 513: aftime = AFGetTime(ac);
! 514: AFPlaySamples(ac, aftime, size, (unsigned char*) buffer);
! 515: aftime += size / 2;
! 516: bufpt = buffer;
! 517: }
! 518: }
! 519: }
! 520: }
! 521:
! 522: #elif defined(__mac__)
! 523:
! 524: #include <Sound.h>
! 525:
! 526: static SndChannelPtr newChannel;
! 527: static ExtSoundHeader theSndBuffer;
! 528: static SndCommand theCmd;
! 529: static const int n_frames = 10;
! 530:
! 531: /* The buffer is too large... */
! 532: static UWORD buffer0[44100], buffer1[44100], *bufpt;
! 533: static UBYTE snddata[4];
! 534:
! 535: static int frames = 0;
! 536: static int smplcnt = 0;
! 537: static long count = 0;
! 538: static int have_sound;
! 539: static int sndbufsize=44100;
! 540: static int nextbuf=0;
! 541: static Boolean sFlag=true;
! 542:
! 543: int init_sound (void)
! 544: {
! 545: if (SndNewChannel(&newChannel, sampledSynth, initMono, NULL))
! 546: return 0;
! 547: init_sound_table8 ();
! 548: smplcnt = 0;
! 549: bufpt = buffer0;
! 550: return 1;
! 551: }
! 552:
! 553: static void channel_reload (int c)
1.1 root 554: {
1.1.1.2 ! root 555: audst[c] = 1;
! 556: audpt[c] = audlc[c];
! 557: audwper[c] = 0;
! 558: audwlen[c] = audlen[c];
! 559: audsnum[c] = 1;
1.1 root 560: }
561:
562: void do_sound (void)
563: {
1.1.1.2 ! root 564: unsigned char *bp;
! 565:
! 566: smplcnt -= 227;
! 567: while (smplcnt < 0) {
! 568: int i;
! 569: smplcnt += 80;
! 570:
! 571: for(i = 0; i < 4; i++) {
! 572: if (dmaen (1<<i)) {
! 573: if (audst[i] == 0) {
! 574: /* DMA was turned on for this channel */
! 575: channel_reload (i);
! 576: continue;
! 577: }
! 578:
! 579: if (audwper[i] <= 0) {
! 580: audwper[i] += audper[i];
! 581: if (audst[i] == 1) {
! 582: /* Starting a sample, cause interrupt */
! 583: put_word (0xDFF09C, 0x8000 | (0x80 << i));
! 584: audst[i] = 2;
! 585: }
! 586: audsnum[i] ^= 1;
! 587: if (audsnum[i] == 0) {
! 588: auddat[i] = get_word (audpt[i]);
! 589: audpt[i] += 2;
! 590: audwlen[i]--;
! 591: if (audwlen[i] == 0) {
! 592: channel_reload (i);
! 593: }
! 594: }
! 595: }
! 596: if (adkcon & (0x11 << i)) {
! 597: snddata[i] = 0;
! 598: audsnum[i] ^= 2;
! 599: audsnum[i] |= 1;
! 600: if (i < 3) {
! 601: if (adkcon & (0x11 << i)) {
! 602: if (audsnum[i] & 2)
! 603: audvol[i+1] = auddat[i];
! 604: else
! 605: audper[i+1] = auddat[i];
! 606: } else if (adkcon & (1 << i)) {
! 607: audvol[i+1] = auddat[i];
! 608: } else {
! 609: audper[i+1] = auddat[i];
! 610: }
! 611: }
! 612: } else {
! 613: snddata[i] = audsnum[i] & 1 ? auddat[i] : auddat[i] >> 8;
! 614: }
! 615: audwper[i] -= 80;
! 616: } else
! 617: audst[i] = snddata[i] = 0;
! 618: }
! 619:
! 620: bp = (unsigned char *)bufpt;
! 621: *bp++ = (sound_table[snddata[0]][audvol[0]]
! 622: + sound_table[snddata[1]][audvol[1]]
! 623: + sound_table[snddata[2]][audvol[2]]
! 624: + sound_table[snddata[3]][audvol[3]] + 128);
! 625: bufpt = (UWORD *)bp;
! 626:
! 627: if (nextbuf == 0) {
! 628: if ((char *)bufpt - (char *)buffer0 >= sndbufsize) {
! 629: nextbuf++;
! 630: bufpt = buffer1;
! 631:
! 632: theSndBuffer.samplePtr = (Ptr)buffer0;
! 633: theSndBuffer.numChannels = 1;
! 634: theSndBuffer.sampleRate = 0xac440000;
! 635: theSndBuffer.encode = extSH;
! 636: theSndBuffer.numFrames = sndbufsize;
! 637: theSndBuffer.sampleSize = 8;
! 638: theCmd.param1 = 0;
! 639: theCmd.param2 = (long)&theSndBuffer;
! 640: theCmd.cmd = bufferCmd;
! 641: SndDoCommand(newChannel, &theCmd, false);
! 642: }
! 643: } else {
! 644: if ((char *)bufpt - (char *)buffer1 >= sndbufsize) {
! 645: nextbuf=0;
! 646: bufpt = buffer0;
! 647:
! 648: theSndBuffer.samplePtr = (Ptr)buffer1;
! 649: theSndBuffer.numChannels = 1;
! 650: theSndBuffer.sampleRate = 0xac440000;
! 651: theSndBuffer.encode = extSH;
! 652: theSndBuffer.numFrames = sndbufsize;
! 653: theSndBuffer.sampleSize = 8;
! 654: theCmd.param1 = 0;
! 655: theCmd.param2 = (long)&theSndBuffer;
! 656: theCmd.cmd = bufferCmd;
! 657: SndDoCommand(newChannel, &theCmd, false);
! 658: }
! 659: }
! 660: }
! 661: }
! 662:
! 663: #else
! 664:
! 665: int init_sound (void)
! 666: {
! 667: return 1;
1.1 root 668: }
669:
1.1.1.2 ! root 670: void do_sound (void)
1.1 root 671: {
672: }
673:
1.1.1.2 ! root 674: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.