/* * UAE - The Un*x Amiga Emulator * * Win32 interface * * Copyright 1997 Mathias Ortmann * Copyright 1997-2001 Brian King * Copyright 2000-2002 Bernd Roesch */ #define NATIVEBUFFNUM 4 #define AMIGASAMPLESIZE 4 #define RECORDBUFFER 50 //survive 9 sec of blocking at 44100 #include "sysconfig.h" #if defined(AHI) #include #include #include #include #include #include "sysdeps.h" #include "options.h" #include "audio.h" #include "memory.h" #include "events.h" #include "custom.h" #include "newcpu.h" #include "traps.h" #include "od-win32/win32.h" #include "dxwrap.h" #include "win32.h" #include "parser.h" #include "enforcer.h" #include "ahidsound.h" #include #include #include #include "sounddep/sound.h" static struct sound_data sdahi; static struct sound_data *sdp = &sdahi; static long samples, playchannel, intcount; static int record_enabled; int ahi_on; static uae_u8 soundneutral; static unsigned int *sndbufrecpt; static uae_u8 *ahisndbuffer, *sndrecbuffer; static int ahisndbufsize, ahitweak;; static uae_u8 *ahisndbufpt; static uae_u8 *sndptrmax; int ahi_pollrate = 40; int sound_freq_ahi, sound_channels_ahi, sound_bits_ahi; static int amigablksize; static DWORD sound_flushes2; extern HWND hAmigaWnd; // for record static LPDIRECTSOUNDCAPTURE lpDS2r = NULL; static LPDIRECTSOUNDCAPTUREBUFFER lpDSBprimary2r = NULL; static LPDIRECTSOUNDCAPTUREBUFFER lpDSB2r = NULL; struct winuae //this struct is put in a6 if you call //execute native function { HWND amigawnd; //address of amiga Window Windows Handle unsigned int changenum; //number to detect screen close/open unsigned int z3offset; //the offset to add to acsess Z3 mem from Dll side }; static struct winuae uaevar; static struct winuae *a6; #if defined(X86_MSVC_ASSEMBLY) #define CREATE_NATIVE_FUNC_PTR2 uae_u32 (*native_func)(uae_u32, uae_u32, uae_u32, uae_u32, uae_u32, uae_u32, uae_u32,\ uae_u32, uae_u32, uae_u32, uae_u32, uae_u32, uae_u32,uae_u32,uae_u32) #define SET_NATIVE_FUNC2(x) native_func = (uae_u32 (*)(uae_u32, uae_u32, uae_u32, uae_u32, uae_u32, uae_u32, uae_u32, uae_u32, uae_u32, uae_u32, uae_u32, uae_u32, uae_u32,uae_u32,uae_u32))(x) #define CALL_NATIVE_FUNC2(d1,d2,d3,d4,d5,d6,d7,a1,a2,a3,a4,a5,a6,a7) if(native_func) return native_func(d1,d2,d3,d4,d5,d6,d7,a1,a2,a3,a4,a5,a6,a7,regs_) static uae_u32 REGPARAM2 emulib_ExecuteNativeCode2 (TrapContext *context) { unsigned int espstore; uae_u8* object_UAM = (uae_u8*) m68k_areg (&context->regs, 0); uae_u32 d1 = m68k_dreg (&context->regs, 1); uae_u32 d2 = m68k_dreg (&context->regs, 2); uae_u32 d3 = m68k_dreg (&context->regs, 3); uae_u32 d4 = m68k_dreg (&context->regs, 4); uae_u32 d5 = m68k_dreg (&context->regs, 5); uae_u32 d6 = m68k_dreg (&context->regs, 6); uae_u32 d7 = m68k_dreg (&context->regs, 7); uae_u32 a1 = m68k_areg (&context->regs, 1); uae_u32 a2 = m68k_areg (&context->regs, 2); uae_u32 a3 = m68k_areg (&context->regs, 3); uae_u32 a4 = m68k_areg (&context->regs, 4); uae_u32 a5 = m68k_areg (&context->regs, 5); uae_u32 a7 = m68k_areg (&context->regs, 7); uae_u32 regs_ = (uae_u32)&context->regs; CREATE_NATIVE_FUNC_PTR2; uaevar.z3offset = (uae_u32)(get_real_address (0x10000000) - 0x10000000); uaevar.amigawnd = hAmigaWnd; a6 = &uaevar; if (object_UAM) { SET_NATIVE_FUNC2 (object_UAM); __asm { mov espstore,esp push regs_ push a7 push a6 push a5 push a4 push a3 push a2 push a1 push d7 push d6 push d5 push d4 push d3 push d2 push d1 call native_func mov esp,espstore } //CALL_NATIVE_FUNC2( d1, d2,d3, d4, d5, d6, d7, a1, a2, a3, a4 , a5 , a6 , a7); } else { return 0; } } #endif void ahi_close_sound (void) { HRESULT hr = DS_OK; if (!ahi_on) return; ahi_on = 0; record_enabled = 0; ahisndbufpt = ahisndbuffer; close_sound_device (sdp); #if 0 if (lpDSB2) { hr = IDirectSoundBuffer_Stop (lpDSB2); if(FAILED (hr)) write_log (_T("AHI: SoundStop() failure: %s\n"), DXError (hr)); } else { write_log (_T("AHI: Sound Stopped...\n")); } if (lpDSB2) IDirectSoundBuffer_Release (lpDSB2); lpDSB2 = NULL; if (lpDSBprimary2) IDirectSoundBuffer_Release (lpDSBprimary2); lpDSBprimary2 = NULL; if (lpDS2) IDirectSound_Release (lpDS2); lpDS2 = NULL; #endif if (lpDSB2r) IDirectSoundCaptureBuffer_Release (lpDSB2r); lpDSB2r = NULL; if (lpDS2r) IDirectSound_Release (lpDS2r); lpDS2r = NULL; if (ahisndbuffer) xfree (ahisndbuffer); ahisndbuffer = NULL; } void ahi_updatesound (int force) { static int doint; uae_u8 *ptr; if (sound_flushes2 == 1) { intcount = 1; INTREQ_f (0x8000 | 0x2000); resume_sound_device (sdp); } if (blocking_sound_device (sdp)) return; if (force == 1) { doint = 1; } if (doint) { INTREQ_f (0x8000 | 0x2000); intcount += doint; doint = 0; } ptr = ahisndbuffer; while (blocking_sound_device (sdp) == 0 && ptr < ahisndbufpt) { int blocksize = amigablksize * AMIGASAMPLESIZE; if (currprefs.sound_stereo_swap_ahi) { int i; uae_s16 *p = (uae_s16*)ptr; for (i = 0; i < blocksize / 2; i += 2) { uae_s16 tmp; tmp = p[i + 0]; p[i + 0] = p[i + 1]; p[i + 1] = tmp; } } send_sound (sdp, (uae_u16*)ptr); ptr += blocksize; doint++; } if (ptr < ahisndbufpt) { int diff = ahisndbufpt - ptr; memmove (ahisndbuffer, ptr, diff); ahisndbufpt = ahisndbuffer + diff; sndptrmax = ahisndbuffer + ahisndbufsize - diff; } else { ahisndbufpt = ahisndbuffer; sndptrmax = ahisndbuffer + ahisndbufsize; } } #if 0 void ahi_updatesound (int force) { HRESULT hr; int pos; unsigned int dwBytes1, dwBytes2; LPVOID dwData1, dwData2; static int oldpos; if (sound_flushes2 == 1) { oldpos = 0; intcount = 1; INTREQ_f (0x8000 | 0x2000); hr = IDirectSoundBuffer_Play (lpDSB2, 0, 0, DSBPLAY_LOOPING); if(hr == DSERR_BUFFERLOST) { IDirectSoundBuffer_Restore (lpDSB2); hr = IDirectSoundBuffer_Play (lpDSB2, 0, 0, DSBPLAY_LOOPING); } } hr = IDirectSoundBuffer_GetCurrentPosition (lpDSB2, &pos, 0); if (hr != DSERR_BUFFERLOST) { pos -= ahitweak; if (pos < 0) pos += ahisndbufsize; if (pos >= ahisndbufsize) pos -= ahisndbufsize; pos = (pos / (amigablksize * 4)) * (amigablksize * 4); if (force == 1) { if (oldpos != pos) { intcount = 1; INTREQ_f (0x8000 | 0x2000); return; //to generate amiga ints every amigablksize } else { return; } } } hr = IDirectSoundBuffer_Lock (lpDSB2, oldpos, amigablksize * 4, &dwData1, &dwBytes1, &dwData2, &dwBytes2, 0); if(hr == DSERR_BUFFERLOST) { write_log (_T("AHI: lostbuf %d %x\n"), pos, amigablksize); IDirectSoundBuffer_Restore (lpDSB2); hr = IDirectSoundBuffer_Lock (lpDSB2, oldpos, amigablksize * 4, &dwData1, &dwBytes1, &dwData2, &dwBytes2, 0); } if(FAILED(hr)) return; if (currprefs.sound_stereo_swap_ahi) { int i; uae_s16 *p = (uae_s16*)ahisndbuffer; for (i = 0; i < (dwBytes1 + dwBytes2) / 2; i += 2) { uae_s16 tmp; tmp = p[i + 0]; p[i + 0] = p[i + 1]; p[i + 1] = tmp; } } memcpy (dwData1, ahisndbuffer, dwBytes1); if (dwData2) memcpy (dwData2, (uae_u8*)ahisndbuffer + dwBytes1, dwBytes2); sndptrmax = ahisndbuffer + ahisndbufsize; ahisndbufpt = (int*)ahisndbuffer; IDirectSoundBuffer_Unlock (lpDSB2, dwData1, dwBytes1, dwData2, dwBytes2); oldpos += amigablksize * 4; if (oldpos >= ahisndbufsize) oldpos -= ahisndbufsize; if (oldpos != pos) { intcount = 1; INTREQ_f (0x8000 | 0x2000); } } #endif void ahi_finish_sound_buffer (void) { sound_flushes2++; ahi_updatesound (2); } static WAVEFORMATEX wavfmt; static int ahi_init_record_win32 (void) { HRESULT hr; DSCBUFFERDESC sound_buffer_rec; // Record begin hr = DirectSoundCaptureCreate (NULL, &lpDS2r, NULL); if (FAILED (hr)) { write_log (_T("AHI: DirectSoundCaptureCreate() failure: %s\n"), DXError (hr)); record_enabled = -1; return 0; } memset (&sound_buffer_rec, 0, sizeof (DSCBUFFERDESC)); sound_buffer_rec.dwSize = sizeof (DSCBUFFERDESC); sound_buffer_rec.dwBufferBytes = amigablksize * 4 * RECORDBUFFER; sound_buffer_rec.lpwfxFormat = &wavfmt; sound_buffer_rec.dwFlags = 0 ; hr = IDirectSoundCapture_CreateCaptureBuffer (lpDS2r, &sound_buffer_rec, &lpDSB2r, NULL); if (FAILED (hr)) { write_log (_T("AHI: CreateCaptureSoundBuffer() failure: %s\n"), DXError(hr)); record_enabled = -1; return 0; } hr = IDirectSoundCaptureBuffer_Start (lpDSB2r, DSCBSTART_LOOPING); if (FAILED (hr)) { write_log (_T("AHI: DirectSoundCaptureBuffer_Start failed: %s\n"), DXError (hr)); record_enabled = -1; return 0; } record_enabled = 1; write_log (_T("AHI: Init AHI Audio Recording \n")); return 1; } void setvolume_ahi (int vol) { set_volume_sound_device (sdp, vol, 0); #if 0 HRESULT hr; if (!lpDS2) return; hr = IDirectSoundBuffer_SetVolume (lpDSB2, vol); if (FAILED (hr)) write_log (_T("AHI: SetVolume(%d) failed: %s\n"), vol, DXError (hr)); #endif } static int ahi_init_sound_win32 (void) { int num, ret; #if 0 HRESULT hr; DSBUFFERDESC sound_buffer; DSCAPS DSCaps; #endif ret = 0; if (!amigablksize) return 0; soundneutral = 0; ahisndbufsize = (amigablksize * AMIGASAMPLESIZE) * NATIVEBUFFNUM; // use 4 native buffer ahisndbuffer = malloc (ahisndbufsize + 32); if (!ahisndbuffer) return 0; num = enumerate_sound_devices (); if (currprefs.win32_soundcard >= num) currprefs.win32_soundcard = changed_prefs.win32_soundcard = 0; ret = open_sound_device (sdp, currprefs.win32_soundcard, amigablksize * AMIGASAMPLESIZE, sound_freq_ahi, sound_channels_ahi); if (!ret) return 0; write_log (_T("AHI: Init AHI Sound Rate %d, Channels %d, Bits %d, Buffsize %d\n"), sound_freq_ahi, sound_channels_ahi, sound_bits_ahi, amigablksize); wavfmt.wFormatTag = WAVE_FORMAT_PCM; wavfmt.nChannels = sound_channels_ahi; wavfmt.nSamplesPerSec = sound_freq_ahi; wavfmt.wBitsPerSample = sound_bits_ahi; wavfmt.nBlockAlign = wavfmt.wBitsPerSample / 8 * wavfmt.nChannels; wavfmt.nAvgBytesPerSec = wavfmt.nBlockAlign * sound_freq_ahi; wavfmt.cbSize = 0; #if 0 if (sound_devices[currprefs.win32_soundcard].type != SOUND_DEVICE_DS) hr = DirectSoundCreate (NULL, &lpDS2, NULL); else hr = DirectSoundCreate (&sound_devices[currprefs.win32_soundcard].guid, &lpDS2, NULL); if (FAILED (hr)) { write_log (_T("AHI: DirectSoundCreate() failure: %s\n"), DXError (hr)); return 0; } memset (&sound_buffer, 0, sizeof (DSBUFFERDESC)); sound_buffer.dwSize = sizeof (DSBUFFERDESC); sound_buffer.dwFlags = DSBCAPS_PRIMARYBUFFER; sound_buffer.dwBufferBytes = 0; sound_buffer.lpwfxFormat = NULL; DSCaps.dwSize = sizeof(DSCAPS); hr = IDirectSound_GetCaps (lpDS2, &DSCaps); if (SUCCEEDED (hr)) { if (DSCaps.dwFlags & DSCAPS_EMULDRIVER) write_log (_T("AHI: Your DirectSound Driver is emulated via WaveOut - yuck!\n")); } if (FAILED (IDirectSound_SetCooperativeLevel (lpDS2, hMainWnd, DSSCL_PRIORITY))) return 0; hr = IDirectSound_CreateSoundBuffer (lpDS2, &sound_buffer, &lpDSBprimary2, NULL); if (FAILED (hr)) { write_log (_T("AHI: CreateSoundBuffer() failure: %s\n"), DXError(hr)); return 0; } hr = IDirectSoundBuffer_SetFormat (lpDSBprimary2, &wavfmt); if (FAILED (hr)) { write_log (_T("AHI: SetFormat() failure: %s\n"), DXError (hr)); return 0; } sound_buffer.dwBufferBytes = ahisndbufsize; sound_buffer.lpwfxFormat = &wavfmt; sound_buffer.dwFlags = DSBCAPS_CTRLFREQUENCY | DSBCAPS_CTRLVOLUME | DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_GLOBALFOCUS | DSBCAPS_LOCSOFTWARE; sound_buffer.guid3DAlgorithm = GUID_NULL; hr = IDirectSound_CreateSoundBuffer (lpDS2, &sound_buffer, &lpDSB2, NULL); if (FAILED (hr)) { write_log (_T("AHI: CreateSoundBuffer() failure: %s\n"), DXError (hr)); return 0; } hr = IDirectSoundBuffer_GetFormat (lpDSBprimary2,&wavfmt,500,0); if (FAILED (hr)) { write_log (_T("AHI: GetFormat() failure: %s\n"), DXError (hr)); return 0; } #endif setvolume_ahi (0); ahisndbufpt = ahisndbuffer; sndptrmax = ahisndbuffer + ahisndbufsize; memset (ahisndbuffer, soundneutral, amigablksize * 8); ahi_on = 1; intcount = 0; return sound_freq_ahi; } int ahi_open_sound (void) { int rate; uaevar.changenum++; if (!sound_freq_ahi) return 0; if (ahi_on) ahi_close_sound (); sound_flushes2 = 1; if ((rate = ahi_init_sound_win32 ())) return rate; return 0; } static void *bswap_buffer = NULL; static uae_u32 bswap_buffer_size = 0; static double syncdivisor; uae_u32 REGPARAM2 ahi_demux (TrapContext *context) { //use the extern int (6 #13) // d0 0=opensound d1=unit d2=samplerate d3=blksize ret: sound frequency // d0 6=opensound_new d1=unit d2=samplerate d3=blksize ret d4=channels d5=bits d6=zero: sound frequency // d0 1=closesound d1=unit // d0 2=writesamples d1=unit a0=addr write blksize samples to card // d0 3=readsamples d1=unit a0=addr read samples from card ret: d0=samples read // make sure you have from amigaside blksize*4 mem alloced // d0=-1 no data available d0=-2 no recording open // d0 > 0 there are more blksize Data in the que // do the loop until d0 get 0 // if d0 is greater than 200 bring a message // that show the user that data is lost // maximum blocksbuffered are 250 (8,5 sec) // d0 4=writeinterrupt d1=unit d0=0 no interrupt happen for this unit // d0=-2 no playing open //note units for now not support use only unit 0 // d0 5=? // d0=10 get clipboard size d0=size in bytes // d0=11 get clipboard data a0=clipboarddata //Note: a get clipboard size must do before // d0=12 write clipboard data a0=clipboarddata // d0=13 setp96mouserate d1=hz value // d0=100 open dll d1=dll name in windows name conventions // d0=101 get dll function addr d1=dllhandle a0 function/var name // d0=102 exec dllcode a0=addr of function (see 101) // d0=103 close dll // d0=104 screenlost // d0=105 mem offset // d0=106 16Bit byteswap // d0=107 32Bit byteswap // d0=108 free swap array // d0=200 ahitweak d1=offset for dsound position pointer int opcode = m68k_dreg (&context->regs, 0); switch (opcode) { uae_u32 src, num_vars; static int cap_pos, clipsize; static TCHAR *clipdat; case 0: cap_pos = 0; sound_bits_ahi = 16; sound_channels_ahi = 2; sound_freq_ahi = m68k_dreg (&context->regs, 2); amigablksize = m68k_dreg (&context->regs, 3); sound_freq_ahi = ahi_open_sound(); uaevar.changenum--; return sound_freq_ahi; case 6: /* new open function */ cap_pos = 0; sound_freq_ahi = m68k_dreg (&context->regs, 2); amigablksize = m68k_dreg (&context->regs, 3); sound_channels_ahi = m68k_dreg (&context->regs, 4); sound_bits_ahi = m68k_dreg (&context->regs, 5); sound_freq_ahi = ahi_open_sound(); uaevar.changenum--; return sound_freq_ahi; case 1: ahi_close_sound(); sound_freq_ahi = 0; return 0; case 2: { int i; uaecptr addr = m68k_areg (&context->regs, 0); if (valid_address (addr, amigablksize * AMIGASAMPLESIZE)) { uae_u8 *src = get_real_address (addr); for (i = 0; i < amigablksize; i++) { if (ahisndbufpt >= sndptrmax) break; *ahisndbufpt++ = src[1]; *ahisndbufpt++ = src[0]; *ahisndbufpt++ = src[3]; *ahisndbufpt++ = src[2]; src += 4; } } ahi_finish_sound_buffer (); } return amigablksize; case 3: { LPTSTR pos1,pos2; uaecptr addr; HRESULT hr; int i, t, todo, byte1, byte2, cur_pos; if (!ahi_on) return -2; if (record_enabled == 0) ahi_init_record_win32 (); if (record_enabled < 0) return -2; hr = IDirectSoundCaptureBuffer_GetCurrentPosition (lpDSB2r, &t, &cur_pos); if (FAILED(hr)) return -1; t = amigablksize * 4; if (cap_pos <= cur_pos) todo = cur_pos - cap_pos; else todo = cur_pos + (RECORDBUFFER * t) - cap_pos; if (todo < t) //if no complete buffer ready exit return -1; hr = IDirectSoundCaptureBuffer_Lock (lpDSB2r, cap_pos, t, &pos1, &byte1, &pos2, &byte2, 0); if (FAILED(hr)) return -1; if ((cap_pos + t) < (t * RECORDBUFFER)) cap_pos = cap_pos + t; else cap_pos = 0; addr = m68k_areg (&context->regs, 0); sndbufrecpt = (unsigned int*)pos1; t /= 4; for (i = 0; i < t; i++) { put_long (addr, *sndbufrecpt++); addr += 4; } t *= 4; IDirectSoundCaptureBuffer_Unlock (lpDSB2r, pos1, byte1, pos2, byte2); return (todo - t) / t; } case 4: { int i; if (!ahi_on) return -2; i = intcount; intcount = 0; return i; } case 5: if (!ahi_on) return 0; ahi_updatesound (1); return 1; case 10: #if 1 if (OpenClipboard (0)) { clipdat = GetClipboardData (CF_TEXT); if (clipdat) { clipsize = _tcslen (clipdat); clipsize++; return clipsize; } } #endif return 0; case 11: { #if 1 int i; for (i = 0; i < clipsize; i++) put_byte (m68k_areg (&context->regs, 0) + i, clipdat[i]); CloseClipboard (); #endif } return 0; case 12: { #if 1 TCHAR *s = au (get_real_address (m68k_areg (®s, 0))); static LPTSTR p; int slen; if (OpenClipboard (0)) { EmptyClipboard(); slen = _tcslen (s); if (p) GlobalFree (p); p = GlobalAlloc (GMEM_MOVEABLE, (slen + 1) * sizeof (TCHAR)); if (p) { TCHAR *p2 = GlobalLock (p); if (p2) { _tcscpy (p2, s); GlobalUnlock (p); SetClipboardData (CF_TEXT, p); } } CloseClipboard (); } xfree (s); #endif } return 0; case 13: /* HACK */ { //for higher P96 mouse draw rate extern int p96hack_vpos2, hack_vpos ,p96refresh_active; extern uae_u16 vtotal; extern unsigned int new_beamcon0; p96hack_vpos2 = 0; if (m68k_dreg (&context->regs, 1) > 0) p96hack_vpos2 = 15625 / m68k_dreg (&context->regs, 1); if (!currprefs.cs_ciaatod) changed_prefs.cs_ciaatod = currprefs.cs_ciaatod = currprefs.ntscmode ? 2 : 1; p96refresh_active=1; picasso_refresh (); } //end for higher P96 mouse draw rate return 0; case 20: return enforcer_enable(m68k_dreg (&context->regs, 1)); case 21: return enforcer_disable(); case 25: flushprinter (); return 0; #if defined(X86_MSVC_ASSEMBLY) case 100: // open dll { TCHAR *dlldir = TEXT ("winuae_dll"); TCHAR *dllname; uaecptr dllptr; HMODULE h = NULL; TCHAR dpath[MAX_DPATH]; TCHAR newdllpath[MAX_DPATH]; int ok = 0; TCHAR *filepart; dllptr = m68k_areg (&context->regs, 0); dllname = au ((uae_char*)get_real_address (dllptr)); dpath[0] = 0; GetFullPathName (dllname, sizeof dpath / sizeof (TCHAR), dpath, &filepart); if (_tcslen (dpath) > _tcslen (start_path_data) && !_tcsncmp (dpath, start_path_data, _tcslen (start_path_data))) { /* path really is relative to winuae directory */ ok = 1; _tcscpy (newdllpath, dpath + _tcslen (start_path_data)); if (!_tcsncmp (newdllpath, dlldir, _tcslen (dlldir))) /* remove "winuae_dll" */ _tcscpy (newdllpath, dpath + _tcslen (start_path_data) + 1 + _tcslen (dlldir)); _stprintf (dpath, _T("%s%s%s"), start_path_data, WIN32_PLUGINDIR, newdllpath); h = LoadLibrary (dpath); if (h == NULL) write_log (_T("native open: '%s' = %d\n"), dpath, GetLastError ()); if (h == NULL) { _stprintf (dpath, _T("%s%s\\%s"), start_path_data, dlldir, newdllpath); h = LoadLibrary (dllname); if (h == NULL) write_log (_T("fallback native open: '%s' = %d\n"), dpath, GetLastError ()); } } else { write_log (_T("native open outside of installation dir '%s'!\n"), dpath); } xfree (dllname); #if 0 if (h == NULL) { h = LoadLibrary (filepart); write_log (_T("native file open: '%s' = %p\n"), filepart, h); if (h == NULL) { _stprintf (dpath, "%s%s%s", start_path_data, WIN32_PLUGINDIR, filepart); h = LoadLibrary (dpath); write_log (_T("native path open: '%s' = %p\n"), dpath, h); } } #endif syncdivisor = (3580000.0 * CYCLE_UNIT) / (double)syncbase; return (uae_u32)h; } case 101: //get dll label { HMODULE m; uaecptr funcaddr; char *funcname; m = (HMODULE) m68k_dreg (&context->regs, 1); funcaddr = m68k_areg (&context->regs, 0); funcname = get_real_address (funcaddr); return (uae_u32) GetProcAddress (m, funcname); } case 102: //execute native code { uae_u32 ret; unsigned long rate1; double v; rate1 = read_processor_time (); ret = emulib_ExecuteNativeCode2 (context); rate1 = read_processor_time () - rate1; v = syncdivisor * rate1; if (v > 0) { if (v > 1000000 * CYCLE_UNIT) v = 1000000 * CYCLE_UNIT; do_extra_cycles ((unsigned long)(syncdivisor * rate1)); //compensate the time stay in native func } return ret; } case 103: //close dll { HMODULE libaddr; libaddr = (HMODULE) m68k_dreg (&context->regs, 1); FreeLibrary (libaddr); return 0; } #endif case 104: //screenlost { static int oldnum = 0; if (uaevar.changenum == oldnum) return 0; oldnum = uaevar.changenum; return 1; } #if defined(X86_MSVC_ASSEMBLY) case 105: //returns memory offset return (uae_u32) get_real_address (0); case 106: //byteswap 16bit vars //a0 = start address //d1 = number of 16bit vars //returns address of new array src = m68k_areg (&context->regs, 0); num_vars = m68k_dreg (&context->regs, 1); if (bswap_buffer_size < num_vars * 2) { bswap_buffer_size = (num_vars + 1024) * 2; free(bswap_buffer); bswap_buffer = (void*)malloc(bswap_buffer_size); } __asm { mov esi, dword ptr [src] mov edi, dword ptr [bswap_buffer] mov ecx, num_vars mov ebx, ecx and ecx, 3 je BSWAP_WORD_4X BSWAP_WORD_LOOP: mov ax, [esi] mov dl, al mov al, ah mov ah, dl mov [edi], ax add esi, 2 add edi, 2 loopne BSWAP_WORD_LOOP BSWAP_WORD_4X: mov ecx, ebx shr ecx, 2 je BSWAP_WORD_END BSWAP_WORD_4X_LOOP: mov ax, [esi] mov dl, al mov al, ah mov ah, dl mov [edi], ax mov ax, [esi+2] mov dl, al mov al, ah mov ah, dl mov [edi+2], ax mov ax, [esi+4] mov dl, al mov al, ah mov ah, dl mov [edi+4], ax mov ax, [esi+6] mov dl, al mov al, ah mov ah, dl mov [edi+6], ax add esi, 8 add edi, 8 loopne BSWAP_WORD_4X_LOOP BSWAP_WORD_END: } return (uae_u32) bswap_buffer; case 107: //byteswap 32bit vars - see case 106 //a0 = start address //d1 = number of 32bit vars //returns address of new array src = m68k_areg (&context->regs, 0); num_vars = m68k_dreg (&context->regs, 1); if (bswap_buffer_size < num_vars * 4) { bswap_buffer_size = (num_vars + 16384) * 4; free(bswap_buffer); bswap_buffer = (void*)malloc(bswap_buffer_size); } __asm { mov esi, dword ptr [src] mov edi, dword ptr [bswap_buffer] mov ecx, num_vars mov ebx, ecx and ecx, 3 je BSWAP_DWORD_4X BSWAP_DWORD_LOOP: mov eax, [esi] bswap eax mov [edi], eax add esi, 4 add edi, 4 loopne BSWAP_DWORD_LOOP BSWAP_DWORD_4X: mov ecx, ebx shr ecx, 2 je BSWAP_DWORD_END BSWAP_DWORD_4X_LOOP: mov eax, [esi] bswap eax mov [edi], eax mov eax, [esi+4] bswap eax mov [edi+4], eax mov eax, [esi+8] bswap eax mov [edi+8], eax mov eax, [esi+12] bswap eax mov [edi+12], eax add esi, 16 add edi, 16 loopne BSWAP_DWORD_4X_LOOP BSWAP_DWORD_END: } return (uae_u32) bswap_buffer; case 108: //frees swap array bswap_buffer_size = 0; free (bswap_buffer); bswap_buffer = NULL; return 0; #endif case 200: ahitweak = m68k_dreg (&context->regs, 1); ahi_pollrate = m68k_dreg (&context->regs, 2); if (ahi_pollrate < 10) ahi_pollrate = 10; if (ahi_pollrate > 60) ahi_pollrate = 60; return 1; default: return 0x12345678; // Code for not supportet function } } #endif