1 /*
2 * UAE - The Un*x Amiga Emulator
3 *
4 * Win32 interface
5 *
6 * Copyright 1997 Mathias Ortmann
7 * Copyright 1997-2001 Brian King
8 * Copyright 2000-2002 Bernd Roesch
9 */
10
11 #define NATIVBUFFNUM 4
12 #define RECORDBUFFER 50 //survive 9 sec of blocking at 44100
13
14 #include "sysconfig.h"
15 #include "sysdeps.h"
16
17 #ifdef AHI
18
19 #include <ctype.h>
20 #include <assert.h>
21
22 #include <stdlib.h>
23 #include <stdarg.h>
24 #include <stdio.h>
25
26 #include "options.h"
27 #include "audio.h"
28 #include "uae/memory.h"
29 #include "events.h"
30 #include "custom.h"
31 #include "newcpu.h"
32 #include "traps.h"
33 #include "sounddep/sound.h"
34 #include "dxwrap.h"
35 #include "parser.h"
36 #include "enforcer.h"
37 #include "ahidsound.h"
38 #include "picasso96.h"
39 #include "uaenative.h"
40 #include "uae/ahi.h"
41
42 #ifdef FSUAE
43 #if defined(WINDOWS) && !defined(_WIN32)
44 #define _WIN32
45 #endif
46 #endif
47
48 static long samples, playchannel, intcount;
49 static int record_enabled;
50 int ahi_on;
51 static uae_u8 *sndptrmax;
52 static uae_u8 soundneutral;
53
54 //static LPSTR lpData,sndptrout;
55 extern uae_u32 chipmem_mask;
56 static uae_u8 *ahisndbuffer, *sndrecbuffer;
57 static int ahisndbufsize, *ahisndbufpt, ahitweak;;
58 int ahi_pollrate = 40;
59
60 int sound_freq_ahi, sound_channels_ahi, sound_bits_ahi;
61
62 static int vin, devicenum;
63 static int amigablksize;
64
65 static DWORD sound_flushes2 = 0;
66
67 #ifdef _WIN32
68 extern HWND hAmigaWnd;
69 #ifdef FSUAE
70 HWND hAmigaWnd;
71 #endif
72 #endif
73
74 struct winuae //this struct is put in a6 if you call
75 //execute native function
76 {
77 #ifdef _WIN32
78 HWND amigawnd; //adress of amiga Window Windows Handle
79 #else
80 void *amigawnd; // dummy
81 #endif
82 unsigned int changenum; //number to detect screen close/open
83 void *z3offset; //the offset to add to acsess Z3 mem from Dll side
84 };
85 static struct winuae uaevar;
86
uaenative_get_uaevar(void)87 void *uaenative_get_uaevar(void) {
88 #ifdef _WIN32
89 uaevar.amigawnd = hAmigaWnd;
90 #endif
91 uaevar.z3offset = get_real_address (0x10000000) - 0x10000000;
92 return &uaevar;
93 }
94
ahi_close_sound(void)95 void ahi_close_sound (void)
96 {
97 if (!ahi_on)
98 return;
99 ahi_on = 0;
100 record_enabled = 0;
101 ahisndbufpt = (int*)ahisndbuffer;
102 #if 0
103 if (lpDSB2) {
104 hr = IDirectSoundBuffer_Stop (lpDSB2);
105 if(FAILED (hr))
106 write_log (_T("AHI: SoundStop() failure: %s\n"), DXError (hr));
107 } else {
108 write_log (_T("AHI: Sound Stopped...\n"));
109 }
110
111 if (lpDSB2)
112 IDirectSoundBuffer_Release (lpDSB2);
113 lpDSB2 = NULL;
114 if (lpDSBprimary2)
115 IDirectSoundBuffer_Release (lpDSBprimary2);
116 lpDSBprimary2 = NULL;
117 if (lpDS2)
118 IDirectSound_Release (lpDS2);
119 lpDS2 = NULL;
120
121 if (lpDSB2r)
122 IDirectSoundCaptureBuffer_Release (lpDSB2r);
123 lpDSB2r = NULL;
124 if (lpDS2r)
125 IDirectSound_Release (lpDS2r);
126 lpDS2r = NULL;
127 #endif
128 if (ahisndbuffer)
129 free (ahisndbuffer);
130 ahisndbuffer = NULL;
131 }
132
ahi_updatesound(int force)133 void ahi_updatesound(int force)
134 {
135 #if 0
136 HRESULT hr;
137 DWORD pos;
138 DWORD dwBytes1, dwBytes2;
139 LPVOID dwData1, dwData2;
140 static int oldpos;
141
142 if (sound_flushes2 == 1) {
143 oldpos = 0;
144 intcount = 1;
145 INTREQ (0x8000 | 0x2000);
146 hr = lpDSB2->Play (0, 0, DSBPLAY_LOOPING);
147 if(hr == DSERR_BUFFERLOST) {
148 lpDSB2->Restore ();
149 hr = lpDSB2->Play (0, 0, DSBPLAY_LOOPING);
150 }
151 }
152
153 hr = lpDSB2->GetCurrentPosition (&pos, 0);
154 if (hr != DSERR_BUFFERLOST) {
155 pos -= ahitweak;
156 if (pos < 0)
157 pos += ahisndbufsize;
158 if (pos >= ahisndbufsize)
159 pos -= ahisndbufsize;
160 pos = (pos / (amigablksize * 4)) * (amigablksize * 4);
161 if (force == 1) {
162 if (oldpos != pos) {
163 intcount = 1;
164 INTREQ (0x8000 | 0x2000);
165 return; //to generate amiga ints every amigablksize
166 } else {
167 return;
168 }
169 }
170 }
171
172 hr = lpDSB2->Lock (oldpos, amigablksize * 4, &dwData1, &dwBytes1, &dwData2, &dwBytes2, 0);
173 if(hr == DSERR_BUFFERLOST) {
174 write_log (_T("AHI: lostbuf %d %x\n"), pos, amigablksize);
175 IDirectSoundBuffer_Restore (lpDSB2);
176 hr = lpDSB2->Lock (oldpos, amigablksize * 4, &dwData1, &dwBytes1, &dwData2, &dwBytes2, 0);
177 }
178 if(FAILED(hr))
179 return;
180
181 if (currprefs.sound_stereo_swap_ahi) {
182 int i;
183 uae_s16 *p = (uae_s16*)ahisndbuffer;
184 for (i = 0; i < (dwBytes1 + dwBytes2) / 2; i += 2) {
185 uae_s16 tmp;
186 tmp = p[i + 0];
187 p[i + 0] = p[i + 1];
188 p[i + 1] = tmp;
189 }
190 }
191
192 memcpy (dwData1, ahisndbuffer, dwBytes1);
193 if (dwData2)
194 memcpy (dwData2, (uae_u8*)ahisndbuffer + dwBytes1, dwBytes2);
195
196 sndptrmax = ahisndbuffer + ahisndbufsize;
197 ahisndbufpt = (int*)ahisndbuffer;
198
199 IDirectSoundBuffer_Unlock (lpDSB2, dwData1, dwBytes1, dwData2, dwBytes2);
200
201 oldpos += amigablksize * 4;
202 if (oldpos >= ahisndbufsize)
203 oldpos -= ahisndbufsize;
204 if (oldpos != pos) {
205 intcount = 1;
206 INTREQ (0x8000 | 0x2000);
207 }
208 #endif
209 }
210
211
ahi_finish_sound_buffer(void)212 void ahi_finish_sound_buffer (void)
213 {
214 #if 0
215 sound_flushes2++;
216 ahi_updatesound(2);
217 #endif
218 }
219
ahi_init_record_win32(void)220 static int ahi_init_record_win32 (void)
221 {
222 #if 0
223 HRESULT hr;
224 DSCBUFFERDESC sound_buffer_rec;
225 // Record begin
226 hr = DirectSoundCaptureCreate (NULL, &lpDS2r, NULL);
227 if (FAILED (hr)) {
228 write_log (_T("AHI: DirectSoundCaptureCreate() failure: %s\n"), DXError (hr));
229 record_enabled = -1;
230 return 0;
231 }
232 memset (&sound_buffer_rec, 0, sizeof (DSCBUFFERDESC));
233 sound_buffer_rec.dwSize = sizeof (DSCBUFFERDESC);
234 sound_buffer_rec.dwBufferBytes = amigablksize * 4 * RECORDBUFFER;
235 sound_buffer_rec.lpwfxFormat = &wavfmt;
236 sound_buffer_rec.dwFlags = 0 ;
237
238 hr = IDirectSoundCapture_CreateCaptureBuffer (lpDS2r, &sound_buffer_rec, &lpDSB2r, NULL);
239 if (FAILED (hr)) {
240 write_log (_T("AHI: CreateCaptureSoundBuffer() failure: %s\n"), DXError(hr));
241 record_enabled = -1;
242 return 0;
243 }
244
245 hr = IDirectSoundCaptureBuffer_Start (lpDSB2r, DSCBSTART_LOOPING);
246 if (FAILED (hr)) {
247 write_log (_T("AHI: DirectSoundCaptureBuffer_Start failed: %s\n"), DXError (hr));
248 record_enabled = -1;
249 return 0;
250 }
251 record_enabled = 1;
252 write_log (_T("AHI: Init AHI Audio Recording \n"));
253 return 1;
254 #endif
255 return 0;
256 }
257
setvolume_ahi(int vol)258 void setvolume_ahi (int vol)
259 {
260 #if 0
261 HRESULT hr;
262 if (!lpDS2)
263 return;
264 hr = IDirectSoundBuffer_SetVolume (lpDSB2, vol);
265 if (FAILED (hr))
266 write_log (_T("AHI: SetVolume(%d) failed: %s\n"), vol, DXError (hr));
267 #endif
268 }
269
ahi_init_sound(void)270 static int ahi_init_sound (void)
271 {
272 #if 0
273 HRESULT hr;
274 DSBUFFERDESC sound_buffer;
275 DSCAPS DSCaps;
276
277 if (lpDS2)
278 return 0;
279
280 enumerate_sound_devices ();
281 wavfmt.wFormatTag = WAVE_FORMAT_PCM;
282 wavfmt.nChannels = sound_channels_ahi;
283 wavfmt.nSamplesPerSec = sound_freq_ahi;
284 wavfmt.wBitsPerSample = sound_bits_ahi;
285 wavfmt.nBlockAlign = wavfmt.wBitsPerSample / 8 * wavfmt.nChannels;
286 wavfmt.nAvgBytesPerSec = wavfmt.nBlockAlign * sound_freq_ahi;
287 wavfmt.cbSize = 0;
288
289 write_log (_T("AHI: Init AHI Sound Rate %d, Channels %d, Bits %d, Buffsize %d\n"),
290 sound_freq_ahi, sound_channels_ahi, sound_bits_ahi, amigablksize);
291
292 if (!amigablksize)
293 return 0;
294 soundneutral = 0;
295 ahisndbufsize = (amigablksize * 4) * NATIVBUFFNUM; // use 4 native buffer
296 ahisndbuffer = xmalloc (uae_u8, ahisndbufsize + 32);
297 if (!ahisndbuffer)
298 return 0;
299 if (sound_devices[currprefs.win32_soundcard]->type != SOUND_DEVICE_DS)
300 hr = DirectSoundCreate (NULL, &lpDS2, NULL);
301 else
302 hr = DirectSoundCreate (&sound_devices[currprefs.win32_soundcard]->guid, &lpDS2, NULL);
303 if (FAILED (hr)) {
304 write_log (_T("AHI: DirectSoundCreate() failure: %s\n"), DXError (hr));
305 return 0;
306 }
307 memset (&sound_buffer, 0, sizeof (DSBUFFERDESC));
308 sound_buffer.dwSize = sizeof (DSBUFFERDESC);
309 sound_buffer.dwFlags = DSBCAPS_PRIMARYBUFFER;
310 sound_buffer.dwBufferBytes = 0;
311 sound_buffer.lpwfxFormat = NULL;
312
313 DSCaps.dwSize = sizeof(DSCAPS);
314 hr = IDirectSound_GetCaps (lpDS2, &DSCaps);
315 if (SUCCEEDED (hr)) {
316 if (DSCaps.dwFlags & DSCAPS_EMULDRIVER)
317 write_log (_T("AHI: Your DirectSound Driver is emulated via WaveOut - yuck!\n"));
318 }
319 if (FAILED (IDirectSound_SetCooperativeLevel (lpDS2, hMainWnd, DSSCL_PRIORITY)))
320 return 0;
321 hr = IDirectSound_CreateSoundBuffer (lpDS2, &sound_buffer, &lpDSBprimary2, NULL);
322 if (FAILED (hr)) {
323 write_log (_T("AHI: CreateSoundBuffer() failure: %s\n"), DXError(hr));
324 return 0;
325 }
326 hr = IDirectSoundBuffer_SetFormat (lpDSBprimary2, &wavfmt);
327 if (FAILED (hr)) {
328 write_log (_T("AHI: SetFormat() failure: %s\n"), DXError (hr));
329 return 0;
330 }
331 sound_buffer.dwBufferBytes = ahisndbufsize;
332 sound_buffer.lpwfxFormat = &wavfmt;
333 sound_buffer.dwFlags = DSBCAPS_CTRLFREQUENCY | DSBCAPS_CTRLVOLUME
334 | DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_GLOBALFOCUS | DSBCAPS_LOCSOFTWARE;
335 sound_buffer.guid3DAlgorithm = GUID_NULL;
336 hr = IDirectSound_CreateSoundBuffer (lpDS2, &sound_buffer, &lpDSB2, NULL);
337 if (FAILED (hr)) {
338 write_log (_T("AHI: CreateSoundBuffer() failure: %s\n"), DXError (hr));
339 return 0;
340 }
341
342 setvolume_ahi (0);
343
344 hr = IDirectSoundBuffer_GetFormat (lpDSBprimary2,&wavfmt,500,0);
345 if (FAILED (hr)) {
346 write_log (_T("AHI: GetFormat() failure: %s\n"), DXError (hr));
347 return 0;
348 }
349
350 ahisndbufpt =(int*)ahisndbuffer;
351 sndptrmax = ahisndbuffer + ahisndbufsize;
352 memset (ahisndbuffer, soundneutral, amigablksize * 8);
353 ahi_on = 1;
354 return sound_freq_ahi;
355 #endif
356 return 0;
357 }
358
ahi_open_sound(void)359 int ahi_open_sound (void)
360 {
361 int rate;
362
363 uaevar.changenum++;
364 if (!sound_freq_ahi)
365 return 0;
366 if (ahi_on)
367 ahi_close_sound ();
368 sound_flushes2 = 1;
369 if ((rate = ahi_init_sound ()))
370 return rate;
371 return 0;
372 }
373
374
375 static void *bswap_buffer = NULL;
376 static uae_u32 bswap_buffer_size = 0;
377 static double syncdivisor;
378
ahi_demux(TrapContext * context)379 uae_u32 REGPARAM2 ahi_demux (TrapContext *context)
380 {
381 //use the extern int (6 #13)
382 // d0 0=opensound d1=unit d2=samplerate d3=blksize ret: sound frequency
383 // d0 6=opensound_new d1=unit d2=samplerate d3=blksize ret d4=channels d5=bits d6=zero: sound frequency
384 // d0 1=closesound d1=unit
385 // d0 2=writesamples d1=unit a0=addr write blksize samples to card
386 // d0 3=readsamples d1=unit a0=addr read samples from card ret: d0=samples read
387 // make sure you have from amigaside blksize*4 mem alloced
388 // d0=-1 no data available d0=-2 no recording open
389 // d0 > 0 there are more blksize Data in the que
390 // do the loop until d0 get 0
391 // if d0 is greater than 200 bring a message
392 // that show the user that data is lost
393 // maximum blocksbuffered are 250 (8,5 sec)
394 // d0 4=writeinterrupt d1=unit d0=0 no interrupt happen for this unit
395 // d0=-2 no playing open
396 //note units for now not support use only unit 0
397 // d0 5=?
398 // d0=10 get clipboard size d0=size in bytes
399 // d0=11 get clipboard data a0=clipboarddata
400 //Note: a get clipboard size must do before
401 // d0=12 write clipboard data a0=clipboarddata
402 // d0=13 setp96mouserate d1=hz value
403 // d0=100 open dll d1=dll name in windows name conventions
404 // d0=101 get dll function addr d1=dllhandle a0 function/var name
405 // d0=102 exec dllcode a0=addr of function (see 101)
406 // d0=103 close dll
407 // d0=104 screenlost
408 // d0=105 mem offset
409 // d0=106 16Bit byteswap
410 // d0=107 32Bit byteswap
411 // d0=108 free swap array
412 // d0=200 ahitweak d1=offset for dsound position pointer
413
414 int opcode = m68k_dreg (regs, 0);
415 printf("AHI demux opcode %d\n", opcode);
416
417 switch (opcode)
418 {
419 uae_u32 src, num_vars;
420 static int cap_pos, clipsize;
421 static TCHAR *clipdat;
422
423 case 0:
424 cap_pos = 0;
425 sound_bits_ahi = 16;
426 sound_channels_ahi = 2;
427 sound_freq_ahi = m68k_dreg (regs, 2);
428 amigablksize = m68k_dreg (regs, 3);
429 sound_freq_ahi = ahi_open_sound();
430 uaevar.changenum--;
431 return sound_freq_ahi;
432 case 6: /* new open function */
433 cap_pos = 0;
434 sound_freq_ahi = m68k_dreg (regs, 2);
435 amigablksize = m68k_dreg (regs, 3);
436 sound_channels_ahi = m68k_dreg (regs, 4);
437 sound_bits_ahi = m68k_dreg (regs, 5);
438 sound_freq_ahi = ahi_open_sound();
439 uaevar.changenum--;
440 return sound_freq_ahi;
441
442 case 1:
443 ahi_close_sound();
444 sound_freq_ahi = 0;
445 return 0;
446
447 case 2:
448 {
449 int i;
450 uaecptr addr = m68k_areg (regs, 0);
451 for (i = 0; i < amigablksize * 4; i += 4)
452 *ahisndbufpt++ = get_long (addr + i);
453 ahi_finish_sound_buffer();
454 }
455 return amigablksize;
456
457 case 3:
458 {
459 #if 0
460 LPVOID pos1, pos2;
461 DWORD t, cur_pos;
462 uaecptr addr;
463 HRESULT hr;
464 int i, todo;
465 DWORD byte1, byte2;
466
467 if (!ahi_on)
468 return -2;
469 if (record_enabled == 0)
470 ahi_init_record_win32();
471 if (record_enabled < 0)
472 return -2;
473 hr = lpDSB2r->GetCurrentPosition(&t, &cur_pos);
474 if (FAILED(hr))
475 return -1;
476
477 t = amigablksize * 4;
478 if (cap_pos <= cur_pos)
479 todo = cur_pos - cap_pos;
480 else
481 todo = cur_pos + (RECORDBUFFER * t) - cap_pos;
482 if (todo < t) //if no complete buffer ready exit
483 return -1;
484 hr = lpDSB2r->Lock(cap_pos, t, &pos1, &byte1, &pos2, &byte2, 0);
485 if (FAILED(hr))
486 return -1;
487 if ((cap_pos + t) < (t * RECORDBUFFER))
488 cap_pos = cap_pos + t;
489 else
490 cap_pos = 0;
491 addr = m68k_areg (regs, 0);
492 uae_u16 *sndbufrecpt = (uae_u16*)pos1;
493 t /= 4;
494 for (i = 0; i < t; i++) {
495 uae_u32 s1, s2;
496 if (currprefs.sound_stereo_swap_ahi) {
497 s1 = sndbufrecpt[1];
498 s2 = sndbufrecpt[0];
499 } else {
500 s1 = sndbufrecpt[0];
501 s2 = sndbufrecpt[1];
502 }
503 sndbufrecpt += 2;
504 put_long (addr, (s1 << 16) | s2);
505 addr += 4;
506 }
507 t *= 4;
508 lpDSB2r->Unlock(pos1, byte1, pos2, byte2);
509 return (todo - t) / t;
510 #endif
511 return -1;
512 }
513
514 case 4:
515 {
516 int i;
517 if (!ahi_on)
518 return -2;
519 i = intcount;
520 intcount = 0;
521 return i;
522 }
523
524 case 5:
525 if (!ahi_on)
526 return 0;
527 ahi_updatesound ( 1 );
528 return 1;
529
530 case 10:
531 #if 0
532 if (OpenClipboard (0)) {
533 clipdat = (TCHAR*)GetClipboardData (CF_UNICODETEXT);
534 if (clipdat) {
535 clipsize = _tcslen (clipdat);
536 clipsize++;
537 return clipsize;
538 }
539 }
540 #endif
541 return 0;
542
543 case 11:
544 {
545 #if 0
546 put_byte (m68k_areg (regs, 0), 0);
547 if (clipdat) {
548 char *tmp = ua (clipdat);
549 int i;
550 for (i = 0; i < clipsize && i < strlen (tmp); i++)
551 put_byte (m68k_areg (regs, 0) + i, tmp[i]);
552 put_byte (m68k_areg (regs, 0) + clipsize - 1, 0);
553 xfree (tmp);
554 }
555 CloseClipboard ();
556 #endif
557 }
558 return 0;
559
560 case 12:
561 {
562 #if 0
563 TCHAR *s = au ((char*)get_real_address (m68k_areg (regs, 0)));
564 static LPTSTR p;
565 int slen;
566
567 if (OpenClipboard (0)) {
568 EmptyClipboard();
569 slen = _tcslen (s);
570 if (p)
571 GlobalFree (p);
572 p = (LPTSTR)GlobalAlloc (GMEM_MOVEABLE, (slen + 1) * sizeof (TCHAR));
573 if (p) {
574 TCHAR *p2 = (TCHAR*)GlobalLock (p);
575 if (p2) {
576 _tcscpy (p2, s);
577 GlobalUnlock (p);
578 SetClipboardData (CF_UNICODETEXT, p);
579 }
580 }
581 CloseClipboard ();
582 }
583 xfree (s);
584 #endif
585 }
586 return 0;
587
588 case 13: /* HACK */
589 { //for higher P96 mouse draw rate
590 set_picasso_hack_rate (m68k_dreg (regs, 1) * 2);
591 } //end for higher P96 mouse draw rate
592 return 0;
593
594 case 20:
595 return enforcer_enable(m68k_dreg (regs, 1));
596
597 case 21:
598 return enforcer_disable();
599
600 case 25:
601 flushprinter ();
602 return 0;
603
604 case 100:
605 return uaenative_open_library (context, UNI_FLAG_COMPAT);
606
607 case 101:
608 return uaenative_get_function (context, UNI_FLAG_COMPAT);
609
610 case 102:
611 return uaenative_call_function(context, UNI_FLAG_COMPAT);
612
613 case 103:
614 return uaenative_close_library (context, UNI_FLAG_COMPAT);
615
616 case 104: //screenlost
617 {
618 static int oldnum = 0;
619 if (uaevar.changenum == oldnum)
620 return 0;
621 oldnum = uaevar.changenum;
622 return 1;
623 }
624
625 #ifndef CPU_64_BIT
626 case 105: //returns memory offset
627 return (uae_u32) get_real_address (0);
628 #endif
629
630 #if defined(X86_MSVC_ASSEMBLY)
631
632 case 106: //byteswap 16bit vars
633 //a0 = start address
634 //d1 = number of 16bit vars
635 //returns address of new array
636 src = m68k_areg (regs, 0);
637 num_vars = m68k_dreg (regs, 1);
638
639 if (bswap_buffer_size < num_vars * 2) {
640 bswap_buffer_size = (num_vars + 1024) * 2;
641 free(bswap_buffer);
642 bswap_buffer = (void*)malloc(bswap_buffer_size);
643 }
644 if (!bswap_buffer)
645 return 0;
646
647 __asm {
648 mov esi, dword ptr [src]
649 mov edi, dword ptr [bswap_buffer]
650 mov ecx, num_vars
651
652 mov ebx, ecx
653 and ecx, 3
654 je BSWAP_WORD_4X
655
656 BSWAP_WORD_LOOP:
657 mov ax, [esi]
658 mov dl, al
659 mov al, ah
660 mov ah, dl
661 mov [edi], ax
662 add esi, 2
663 add edi, 2
664 loopne BSWAP_WORD_LOOP
665
666 BSWAP_WORD_4X:
667 mov ecx, ebx
668 shr ecx, 2
669 je BSWAP_WORD_END
670 BSWAP_WORD_4X_LOOP:
671 mov ax, [esi]
672 mov dl, al
673 mov al, ah
674 mov ah, dl
675 mov [edi], ax
676 mov ax, [esi+2]
677 mov dl, al
678 mov al, ah
679 mov ah, dl
680 mov [edi+2], ax
681 mov ax, [esi+4]
682 mov dl, al
683 mov al, ah
684 mov ah, dl
685 mov [edi+4], ax
686 mov ax, [esi+6]
687 mov dl, al
688 mov al, ah
689 mov ah, dl
690 mov [edi+6], ax
691 add esi, 8
692 add edi, 8
693 loopne BSWAP_WORD_4X_LOOP
694 BSWAP_WORD_END:
695 }
696 return (uae_u32) bswap_buffer;
697
698 case 107: //byteswap 32bit vars - see case 106
699 //a0 = start address
700 //d1 = number of 32bit vars
701 //returns address of new array
702 src = m68k_areg (regs, 0);
703 num_vars = m68k_dreg (regs, 1);
704 if (bswap_buffer_size < num_vars * 4) {
705 bswap_buffer_size = (num_vars + 16384) * 4;
706 free(bswap_buffer);
707 bswap_buffer = (void*)malloc(bswap_buffer_size);
708 }
709 if (!bswap_buffer)
710 return 0;
711 __asm {
712 mov esi, dword ptr [src]
713 mov edi, dword ptr [bswap_buffer]
714 mov ecx, num_vars
715
716 mov ebx, ecx
717 and ecx, 3
718 je BSWAP_DWORD_4X
719
720 BSWAP_DWORD_LOOP:
721 mov eax, [esi]
722 bswap eax
723 mov [edi], eax
724 add esi, 4
725 add edi, 4
726 loopne BSWAP_DWORD_LOOP
727
728 BSWAP_DWORD_4X:
729 mov ecx, ebx
730 shr ecx, 2
731 je BSWAP_DWORD_END
732 BSWAP_DWORD_4X_LOOP:
733 mov eax, [esi]
734 bswap eax
735 mov [edi], eax
736 mov eax, [esi+4]
737 bswap eax
738 mov [edi+4], eax
739 mov eax, [esi+8]
740 bswap eax
741 mov [edi+8], eax
742 mov eax, [esi+12]
743 bswap eax
744 mov [edi+12], eax
745 add esi, 16
746 add edi, 16
747 loopne BSWAP_DWORD_4X_LOOP
748
749 BSWAP_DWORD_END:
750 }
751 return (uae_u32) bswap_buffer;
752
753 case 108: //frees swap array
754 bswap_buffer_size = 0;
755 free (bswap_buffer);
756 bswap_buffer = NULL;
757 return 0;
758
759 case 110:
760 {
761 LARGE_INTEGER p;
762 QueryPerformanceFrequency (&p);
763 put_long (m68k_areg (regs, 0), p.HighPart);
764 put_long (m68k_areg (regs, 0) + 4, p.LowPart);
765 }
766 return 1;
767
768 case 111:
769 {
770 LARGE_INTEGER p;
771 QueryPerformanceCounter (&p);
772 put_long (m68k_areg (regs, 0), p.HighPart);
773 put_long (m68k_areg (regs, 0) + 4, p.LowPart);
774 }
775 return 1;
776
777 #endif
778
779 case 200:
780 ahitweak = m68k_dreg (regs, 1);
781 ahi_pollrate = m68k_dreg (regs, 2);
782 if (ahi_pollrate < 10)
783 ahi_pollrate = 10;
784 if (ahi_pollrate > 60)
785 ahi_pollrate = 60;
786 return 1;
787
788 default:
789 return 0x12345678; // Code for not supported function
790 }
791 }
792
793 #endif // AHI
794