English Amiga Board Amiga Lore


Go Back   English Amiga Board > Support > support.WinUAE

 
 
Thread Tools
Old 30 December 2013, 10:30   #21
thellier
Registered User
 
Join Date: Sep 2011
Location: Paris/France
Posts: 148
>Alternatively, you could write a mixed-binary 68k library that runs 68K if the .dll is not found or if not running on a .dll capable system.
This is the way Wazp3D works
Wazp3D.library use my soft3d.library as renderer
the soft3d.library contain native calls to the soft3d.dll but also the full 68k functions if the .dll cant be opened

On the PC side the soft3d side contain both the glue functions and the pure x86 function
SOFT3D_CreateTextureUAE() called from UAE
SOFT3D_CreateTexture() can be called from a windows apps (useless here but present)

>int library = uni_load_library("hello_world_library");
>int function = uni_get_function(library, "hello_world");

Would be more simple to have a standard UAE backdoor that will do an "OpenLibraryNative" and just return a library header (version) and full jumps table
Not very difficult Here it is the code I used in Wazp3D/soft3d (more in Wazp3d sources)
There is only something that MUST be changed = no more open the external library with his full name (soft3d.dll) but the name (soft3d) so allowing to have the same 68k code that will open soft3d.so soft3d.elf

Alain Thellier

Code:
/*==========================================================================*/
void winuae_getnativeaddrall( ULONG dllbase, APTR *funcnames, ULONG *funcptrs,ULONG nb )
{
register ULONG D0 __asm("d0")=GETNATIVEADRESSE;
register ULONG D1 __asm("d1")=dllbase;
register ULONG A0 __asm("a0");

register ULONG D2	__asm("d2");
	
	for(D2=0;D2<nb;D2++)
	{
	D0=GETNATIVEADRESSE;
	D1=dllbase;
	A0=(ULONG)funcnames[0];
	asm volatile ("jsr 0xf0ffc0");
	D0++;					/* only to avoid d0 to be otimized away */
	funcptrs[0]= D0-1;		/* only to avoid d0 to be otimized away like that: funcptrs[0]=GETNATIVEADRESSE */
	funcnames++;
	funcptrs++;
	}
}
/*==========================================================================*/
ULONG winuae_opendll( APTR dllname )
{
	WINUAENATIVE(OPENDLL,0,(ULONG)dllname);
}
/*==========================================================================*/
ULONG  winuae_closedll( ULONG dllbase )
{
	WINUAENATIVE(CLOSEDLL,dllbase,0);
}
/*==========================================================================*/
#define SOFT3D_ClearImageBufferUAE 0
#define SOFT3D_ClearZBufferUAE 1
#define SOFT3D_CreateTextureUAE 2
#define SOFT3D_DoUpdateUAE 3
#define SOFT3D_DrawPrimitiveUAE 4
#define SOFT3D_EndUAE 5
#define SOFT3D_FreeTextureUAE 6
#define SOFT3D_ReadZSpanUAE 7
#define SOFT3D_AllocImageBufferUAE 8
#define SOFT3D_SetBitmapUAE 9
#define SOFT3D_SetClippingUAE 10
#define SOFT3D_SetDrawStateUAE 11
#define SOFT3D_AllocZbufferUAE 12
#define SOFT3D_StartUAE 13
#define SOFT3D_WriteZSpanUAE 14
#define SOFT3D_FlushUAE 15
#define SOFT3D_UpdateTextureUAE 16
#define SOFT3D_DebugUAE 17

UBYTE name0 [] = {"_SOFT3D_ClearImageBufferUAE"};
UBYTE name1 [] = {"_SOFT3D_ClearZBufferUAE"};
UBYTE name2 [] = {"_SOFT3D_CreateTextureUAE"};
UBYTE name3 [] = {"_SOFT3D_DoUpdateUAE"};
UBYTE name4 [] = {"_SOFT3D_DrawPrimitiveUAE"};
UBYTE name5 [] = {"_SOFT3D_EndUAE"};
UBYTE name6 [] = {"_SOFT3D_FreeTextureUAE"};
UBYTE name7 [] = {"_SOFT3D_ReadZSpanUAE"};
UBYTE name8 [] = {"_SOFT3D_AllocImageBufferUAE"};
UBYTE name9 [] = {"_SOFT3D_SetBitmapUAE"};
UBYTE name10[] = {"_SOFT3D_SetClippingUAE"};
UBYTE name11[] = {"_SOFT3D_SetDrawStateUAE"};
UBYTE name12[] = {"_SOFT3D_AllocZbufferUAE"};
UBYTE name13[] = {"_SOFT3D_StartUAE"};
UBYTE name14[] = {"_SOFT3D_WriteZSpanUAE"};
UBYTE name15[] = {"_SOFT3D_FlushUAE"};
UBYTE name16[] = {"_SOFT3D_UpdateTextureUAE"};
UBYTE name17[] = {"_SOFT3D_Debug"};

#define FUNCNB 18
APTR funcnames[FUNCNB]={name0,name1,name2,name3,name4,name5,name6,name7,name8,name9,name10,name11,name12,name13,name14,name15,name16,name17};
ULONG funcptrs[FUNCNB];
ULONG dllbase=0;

#define NLOOP(nbre) for(n=0;n<nbre;n++)
void Libprintf(UBYTE *string, ...);
extern BOOL LibDebug;
/*==================================================================================*/
void OpenSoft3DDLL()
{
BOOL DebugState=LibDebug;
int n;

LibDebug=TRUE;
	Libprintf("OpenSoft3DDLL\n");
	dllbase = winuae_opendll("soft3d.dll");
	if(dllbase == 0)
		{LibDebug=TRUE;LibAlert("Cant open WinUAE/soft3d.dll !"); LibDebug=DebugState; return;} 

	Libprintf("The DLL soft3d.dll is opened :-) (dllbase %ld)\n",dllbase);

	winuae_getnativeaddrall(dllbase,funcnames,funcptrs,FUNCNB);

	NLOOP(FUNCNB)
		if(funcptrs[n]!=0)
		{Libprintf("DLL's function%ld: %ld (from dllbase %ld)\n",n,funcptrs[n],funcptrs[n]-dllbase); }
		else
		{Libprintf("DLL's function%ld: not found ! \n",n); dllbase=0; } 

	if(dllbase!=0)
		{ Libprintf("DLL functions are here :-) \n"); }
	else
		{ Libprintf("DLL fail :-( \n"); dllbase=0; }

}
/*==================================================================================*/
void CloseSoft3DDLL()
{
	Libprintf("CloseSoft3DDLL\n");
	if(dllbase == 0) return;

	winuae_closedll(dllbase);
	Libprintf("The DLL soft3d.dll is closed\n");
}
/*==================================================================================*/

Last edited by Toni Wilen; 30 December 2013 at 10:54. Reason: Code in code tags.
thellier is offline  
AdSense AdSense  
Old 30 December 2013, 10:54   #22
Toni Wilen
WinUAE developer
 
Join Date: Aug 2001
Location: Hämeenlinna/Finland
Age: 42
Posts: 19,542
Quote:
Originally Posted by thellier View Post
Would be more simple to have a standard UAE backdoor that will do an "OpenLibraryNative" and just return a library header (version) and full jumps table
Do you mean it would open the native library, parse its export table and create Amiga-like library from this data? That would be quite interesting idea but:

I don't see how it can work when native libraries are linked based on export name, not order of export. How to map native call to jump vector offset? Library would need to have some extra information.
Toni Wilen is offline  
Old 30 December 2013, 12:39   #23
FrodeSolheim
FS-UAE Developer

FrodeSolheim's Avatar
 
Join Date: Dec 2011
Location: Førde, Norway
Age: 36
Posts: 3,368
Quote:
Originally Posted by Der Wanderer View Post
It would be a good idea if the .dll or .so is NOT aware of being used by UAE.
Means, there should be no glue code on the x86 side. Why? Simply because you may want to use existing libraries that you don't want to contaminate with Amiga specific stuff or you don't even have the source code.
In my opinion, this is a very bad idea for several reasons including:
  • The Amiga library would need to know a lot about the native library, and account for differences between native architectures (CPU and OS). This includes dealing with different calling conventions (cdecl, stdcall, etc), different data type sizes and pointer size, different struct alignment and padding (struct member offsets may be different due to both differing data type sizes and struct alignment). You would also have to byte-swap integers based on whether the native platform is little-endian or big-ending.
  • The native library might give you a pointer which you are expected to use, but the native memory isn't available from the Amiga side (without proxy functions to access it).

It should be much more convenient (and better performance-wise) to handle the Amiga<->native differences on the native side (and it will be compiled into the native library, so no dynamic translation based on native architecture is needed).

If you want to use an existing native library you simply write a wrapper library instead. If you create it yourself you can do as Thellier and include both a "real function" and a wrapper function in the same library, so it can easily be used by both UAE and non-UAE program.

Quote:
Originally Posted by Toni Wilen View Post
I can do the Amiga side library, including some skeleton code that does the important Amiga-side bits.
That is probably a good idea

Quote:
Originally Posted by Toni Wilen View Post
There is only something that MUST be changed = no more open the external library with his full name (soft3d.dll) but the name (soft3d) so allowing to have the same 68k code that will open soft3d.so soft3d.elf
This is already accounted for - as you can see there is no extension in the example. This situation is a little bit more complex than just adding file type extension - we need CPU architecture as part of the name, and for some extension also the OS (or just always include it for consistency), so it would be something like this:
  • soft3d-x86(-windows).dll, soft3d-x86-64(-windows).dll
  • soft3d-x86(-macosx).dylib, soft3d-x86-64(-macosx).dylib soft3d-ppc(-macosx).dylib
  • soft3d-x86-linux.so, etc

I write a custom ELF loader a couple of years ago which can load (position independent) self-contained code from an .so file with an API similar to LoadLibrary/dlopen and friends. So for native code which does not interface with other system libraries, I can include support for this as well and allow the native interface to load one of soft3d-x86.so, soft3d-x86-64.so, soft3d-ppc.so (etc) on all platforms - operating system-specific variants not needed.

Quote:
Originally Posted by Toni Wilen View Post
I don't see how it can work when native libraries are linked based on export name, not order of export. How to map native call to jump vector offset? Library would need to have some extra information.
Yes, it only works because the Amiga library looks up the names in a specific order. If some kind of automation is desired here I guess it must be one of:
  • The Amiga code provides a string list to an UAE library function which resolves the names in order (just what Telliers code does, but the code is moved to the UAE library).
  • Alternatively, the library can export a function (uni_get_function_names) which the native interface the native interface can resolve in order - provided that names are always appended to the list only (to avoid breaking older clients). The Amiga side would still need to have #defines or something for the offsets, so perhaps not a lot better than just let the Amiga side provide the function names of interest, in order, as well...

Regarding library version number (mentioned by Tellier), I included a version number in the UAE_DEFINE_LIBRARY macro, for example:
Code:
UNI_DEFINE_LIBRARY(1, init);
The open library call from the Amiga side takes a minimum library version, and the call fails with UNI_ERROR_LIBRARY_TOO_OLD if the requirement is not met.

Here is more recent example native library which compiles -but I have not tested it because I haven't get any Amiga-side program for it yet (anyone volunteer to write one?):

Code:
#include <string.h>
#include <uae/uni.h>

static const char *message = "";

uni_u32 init() {
    message = "Hello, World!";
    return 0;
}

UNI_DEFINE_LIBRARY(1, init);

UNIAPI void UNICALL hello_world(struct uni *uni) {
    char *data = (char *) UNI_PTR_PARAM(0);
    strcpy(data, message);
}

#pragma pack(2)
struct numbers {
    uni_char c;
    uni_short s;
    uni_long l;
};
#pragma pack()

UNIAPI void UNICALL add_numbers(struct uni *uni) {
    struct numbers *numbers = (struct numbers *) UNI_PTR_PARAM(0);
    uni_long *result = (uni_long *) UNI_PTR_PARAM(1);
    *result = numbers->c + numbers->s + numbers->l;
}
As a side note (and used in the example) it looks like #pragma pack(2) can be used with both MSVC and GCC to safely share C many struct definitions between the Amiga C code and the native C code! (Though not part of the native interface layer itself, please let me know if you see any problems with this )

EDIT: uae_char and uae_short isn't really necessary - just included for consistency. But uae_long is useful in shared structs since int can be either 16- or 32-bit on the Amiga depending on the compiler, and on the native side, longs can be either 32- or 64-bit.

Last edited by FrodeSolheim; 30 December 2013 at 12:44.
FrodeSolheim is offline  
Old 30 December 2013, 13:00   #24
Toni Wilen
WinUAE developer
 
Join Date: Aug 2001
Location: Hämeenlinna/Finland
Age: 42
Posts: 19,542
Very quickly done and simple skeleton code attached, only needs required init calls from main and filesys.

Quote:
Originally Posted by FrodeSolheim View Post
It should be much more convenient (and better performance-wise) to handle the Amiga<->native differences on the native side (and it will be compiled into the native library, so no dynamic translation based on native architecture is needed).
I agree, it should be as transparent API as possible that hides all ugly translation details, including 32/64-bit host CPU differences. It should look like exactly like normal Amiga function call in Amiga-side code and nothing special should be needed in native code either.

Quote:
I write a custom ELF loader a couple of years ago which can load (position
AROS also have portable elf and hunk loader.
Attached Files
File Type: zip uaenat.zip (1.9 KB, 49 views)
Toni Wilen is offline  
Old 30 December 2013, 13:02   #25
FrodeSolheim
FS-UAE Developer

FrodeSolheim's Avatar
 
Join Date: Dec 2011
Location: Førde, Norway
Age: 36
Posts: 3,368
Another thing, there is an alternative function interface we can consider - and I guess this was what Toni really suggested a bit earlier. I am warming to this as it becomes a more elegant esp. when one can share struct definitions on both sides. add_numbers would look like this then:

Code:
#pragma pack(2)
struct add_numbers {
    uni_char c;
    uni_short s;
    uni_long l;
    uni_long result;
};
#pragma pack()

UNIAPI void UNICALL add_numbers(struct uni *uni, struct add_numbers *params) {
    params->result = numbers->c + numbers->s + numbers->l;
}
All native functions would then receive two parameters (uni for interface information and UAE callback functions, and a params struct for the function parameters (and return value(s)).

You would then have to define a struct for each call (or use a common struct for simple calls), and all Amiga-side calls would need to set up a param struct and pass a pointer to it for any calls.

It isn't a really big difference to the current implementation where the same would be realized like this:
Code:
UNIAPI void UNICALL add_numbers(struct uni *uni) {
    struct add_numbers *params = (struct add_numbers *) UNI_PTR_PARAM(0);
    params->result = numbers->c + numbers->s + numbers->l;
}
It is a kind of trade-off: The former looks a lot cleaner for this example, but other simpler calls may look a bit simpler without having to declare param structs.

EDIT: important: I forgot to add byte-swapping macros to all add_number examples - it must be something like this:

params->result = UNI_SWAP_LONG(numbers->c + UNI_SWAP_SHORT(numbers->s) + UNI_SWAP_LONG(numbers->l));
FrodeSolheim is offline  
Old 30 December 2013, 13:27   #26
FrodeSolheim
FS-UAE Developer

FrodeSolheim's Avatar
 
Join Date: Dec 2011
Location: Førde, Norway
Age: 36
Posts: 3,368
While at I can just as well present a third options for argument passing. If the UAE interface layers knows the function signature, it could automatically byte-swap integer arguments if needed, and also resolve Amiga pointers to native pointers. It can also then dynamically build function parameters.

This can be done with a macro which exports a signature string for each function. Something like this:

Code:
UNIAPI("csll") void UNICALL add_numbers(struct uni *uni, uni_char *c,
uni_short *s, uni_long *l, uni_long *result) {
    *result = *c + *s + *l;
}
Pointers are used for all args here, could pass some parameters by value instead if the signature string indicates for each parameter pass by value or reference. After the function call, UAE would then reverse transformations on the parameters before returning to the Amiga caller.

A bit more work to implement (and the library writer must be careful when writing the function signature) but otherwise doable. This approach would work well in tandem with a param struct from the Amiga side - with struct members in the same order as the arguments to the native function.
FrodeSolheim is offline  
Old 30 December 2013, 13:47   #27
FrodeSolheim
FS-UAE Developer

FrodeSolheim's Avatar
 
Join Date: Dec 2011
Location: Førde, Norway
Age: 36
Posts: 3,368
When thinking further, I have a bit more to add about my last post. If the native interface knows the signature of the function (as in my last example), the native interface could just read the parameters off the Amiga stack (if the Amiga stack pointer is valid when control is passed to UAE code). Then, the native code could call a generated Amiga stub function for the call (which simply invokes the native interface with the correct function handle). This would allow the Amiga side to invoke the native interface with just a normal C function prototype declaration?

Of course, none of this is really necessary, and we are in some ways trading flexibility for "elegance" here -And it is somewhat contrary to my initial thoughts of just keeping the native interface bridge itself really simply.

Any thoughts on the different calling conventions?
FrodeSolheim is offline  
Old 30 December 2013, 14:03   #28
Toni Wilen
WinUAE developer
 
Join Date: Aug 2001
Location: Hämeenlinna/Finland
Age: 42
Posts: 19,542
I think automatic byteswapping or address translation does not really help because native code most likely needs to read Amiga-side structures directly, some private, some public, possibly some of them are dynamic.

Also assembly code should be able to use registers directly without pushing anything to stack. (Register parameters are also commonly used in Amiga C-code)

So perhaps my original idea isn't that good..
Toni Wilen is offline  
Old 30 December 2013, 14:35   #29
FrodeSolheim
FS-UAE Developer

FrodeSolheim's Avatar
 
Join Date: Dec 2011
Location: Førde, Norway
Age: 36
Posts: 3,368
Yes, byteswapping macros would still be needed in many cases. And perhaps it could even be a bit confusing for users when to use byte-swapping macros or not.

About UAE-generated Amiga-side stub libraries, they may not be *that* useful. Depending on how the native function definitions look like, a simple python script could instead be written to create a .c/.h and/or assembly stub library for the Amiga if one wants that. This requires that the low-level arguments passing details are fixed (my original plan) instead of possibly being changeable (details hidden by a UAE-provided caller helper library).

With register argument passing we can exploit the fact that C allows variable argument list (with cdecl calling convention), so we can still pass arguments as function arguments on the native side if people like that better than accessing everything via the uni struct, i.e:
Code:
UNIAPI void UNICALL add_numbers(struct uni *uni, uni_u32 c,
uni_u32 s, uni_u32 l, uni_u32 result)
as long as they are passed in the right order in the registers. (If the function is not decorated with some kind of prototype string, you'd still need to resolve Amiga pointer arguments like in the earlier examples).

Last edited by FrodeSolheim; 30 December 2013 at 14:56.
FrodeSolheim is offline  
Old 30 December 2013, 16:17   #30
FrodeSolheim
FS-UAE Developer

FrodeSolheim's Avatar
 
Join Date: Dec 2011
Location: Førde, Norway
Age: 36
Posts: 3,368
Current thoughts:
  • Keep the native interface itself relatively simple, like in this example http://eab.abime.net/showpost.php?p=929935&postcount=23, and pass up to n parameters in registers. The flags register can be used for future extensions.
  • No magic on the Amiga side, instead rely on optional auto-generated library helper modules (C and/or ASM) for convenience and a degree of parameter checking (when using C).
  • To allow for async calls, values are never returned a registers, but always through pointers passed in registers.
  • Use the uaelib demuxer for now, perhaps not much to gain by having a separate library (and there are more than enough free switch cases).
I think having a simple low-level mechanism and having other convince stuff as optional add-ons is the way to go. This allows you to use the convenience stuff, or go "low-level" if you need the flexibility or extra performance.

The parameter macros used in the example will be a good way to auto-generate proxy/helper modules.

Auto-generated modules can become really nice to use from the Amiga side, especially in C code. But proxy functions will mean one extra level of indirection, and a slight performance hit. While use of such proxy function is completely optional of course, there is one optimization we could do:

If there is a very common c calling convention on the Amiga, where n arguments are passed in n specific registers in order, we could use the same registers (in that order) to pass parameters to the UAE handler. Then C proxy functions (if those are used) would not need to re-order parameters for compilers using that calling convention… (Anyone having any input on this?)

@Toni I also have a question for you. Is writing to pointers resolved by get_real_address always safe (from the native side), provided that the Amiga memory is properly allocated/reserved (and UAE isn't reset in the meantime, etc)? (Is there for example an emulated CPU cache for some CPU models?)

Oh, and I still won't mind a volunteer to write some Amiga-side test cases (The Wanderer?)
FrodeSolheim is offline  
Old 30 December 2013, 16:28   #31
Toni Wilen
WinUAE developer
 
Join Date: Aug 2001
Location: Hämeenlinna/Finland
Age: 42
Posts: 19,542
I really hate that uaelib demux stuff because it requires absolute jump address to UAE ROM. It is really non-Amiga like and really ugly way to do it. (This forces UAE boot rom at $f00000 which is annoying with some configs if it needs to also support demux stuff. UAE itself does not require it.)

Thats why I want to do it more Amiga-like, method that does not require any magic numbers or magic addresses.

I can do Amiga side test cases if I am happy enough with the API

get_real_address() is safe as long as memory is RAM or ROM. (not IO-like). addr_valid() can be used to check it.

Data cache emulation is already impossible if any UAE-side expansion is enabled. Handling cache compatible writes or reads from another thread would be really difficult without making CPU emu slow and complex. (Some kind of message queue would be needed at least)
Toni Wilen is offline  
Old 30 December 2013, 18:04   #32
FrodeSolheim
FS-UAE Developer

FrodeSolheim's Avatar
 
Join Date: Dec 2011
Location: Førde, Norway
Age: 36
Posts: 3,368
Current low-level interface, temporarily using the ahi_winuae demuxer. I don't mind at all the interface being moved to a memory-resident library instead afterwards.

Open library: d0 = 199
* a0 - pointer to name of native library
* a1 - pointer to 32-bit result value (library handle or error)
* d1 - minimum required native library version

The returned library handle is not an address, but an opaque handle. If the high bit of of the result is set, the operation failed and the 32-bit value represents an error code.

Get function address: d0 = 198
* a0 - pointer to name of function
* a1 - pointer to 32-bit result value (function handle or error)
* d1 - library handle

The result in a1 is similar to the open library call.

Call function: d0 = 197
* a0 - function handle
* d1 .. d6 - 6 32-bit parameters
* d7 - function call flags
* a7 - pointer for error result (to indicate an invalid function call, or invalid flags, etc)? - Not implemented yet, but could be useful, at the expense of the caller must always provide a valid pointer or 0 here. Optionally, a flag in d7 could be used to specify if the error register pointer is valid or not to avoid one register write if one is not interested in the error (should really not be necessary if the native interface is used correctly).

Close library: d0 = 196
* d1 - library handle

The register usage is somewhat random and can easily be changed at this point. Please suggest other register usage where that is more optimal. For examlpe, is it generally more useful to the Amiga side to pass the parameters using address registers instead? (For example for cases where the parameters are struct pointers? Or perhaps to optimize register usage for a certain "standard" C calling convention as mentioned earlier.

And of course, more than 6 parameters could be used - but I guess that if you need much more than that, you'll probably be passing structs already...
FrodeSolheim is offline  
Old 30 December 2013, 18:23   #33
Toni Wilen
WinUAE developer
 
Join Date: Aug 2001
Location: Hämeenlinna/Finland
Age: 42
Posts: 19,542
Probably best to clone OpenLibrary/CloseLibrary parameter usage.

Open: A1 = name, D0 = version
Close: A1 = handle

Why does return code need a pointer? I don't see why it can't work with async mode, return value in D0 should work exact same. (Or did I miss something?)
Toni Wilen is offline  
Old 30 December 2013, 18:34   #34
FrodeSolheim
FS-UAE Developer

FrodeSolheim's Avatar
 
Join Date: Dec 2011
Location: Førde, Norway
Age: 36
Posts: 3,368
Quote:
Originally Posted by Toni Wilen View Post
Why does return code need a pointer? I don't see why it can't work with async mode, return value in D0 should work exact same. (Or did I miss something?)
I wasn't sure if the registers of the caller's task could be easily updated by the task-resuming code. I should have asked I'll update the code to use D0 as a return register then! I can also then allow the native functions to return a long value to the D0 register.

I do have another question though, in ahidsound_dsonly.cpp, the dll function calls are done with some inline assembly code instead of calling via a C function prototype. Is this a "hack" to make it work with both cdecl / stdcall calling conventions in libraries.

Edit: I'm fine with cloning the OpenLibrary/CloseLibrary usage, but cannot be done until the functionality is moved away from the demux function.

Last edited by FrodeSolheim; 30 December 2013 at 18:45.
FrodeSolheim is offline  
Old 30 December 2013, 19:28   #35
Toni Wilen
WinUAE developer
 
Join Date: Aug 2001
Location: Hämeenlinna/Finland
Age: 42
Posts: 19,542
Quote:
Originally Posted by FrodeSolheim View Post
I wasn't sure if the registers of the caller's task could be easily updated by the task-resuming code. I should have asked I'll update the code to use D0 as a return register then! I can also then allow the native functions to return a long value to the D0 register.
bsdsocket also uses this type of functions and they do work.

Amiga -> native code -> native code calls some Amiga library function -> Amiga side -> m68k code runs again -> back to native side -> final return to original Amiga side with return code in D0. I don't know how this works trap magic works, I only know it works

Quote:
I do have another question though, in ahidsound_dsonly.cpp, the dll function calls are done with some inline assembly code instead of calling via a C function prototype. Is this a "hack" to make it work with both cdecl / stdcall calling conventions in libraries.
I have no idea. Most of it is not mine (mainly the dll check protection and some ahi modifications). Windows clipboard stuff is also mostly obsolete.
Toni Wilen is offline  
Old 01 January 2014, 11:37   #36
FrodeSolheim
FS-UAE Developer

FrodeSolheim's Avatar
 
Join Date: Dec 2011
Location: Førde, Norway
Age: 36
Posts: 3,368
Quote:
Originally Posted by Toni Wilen View Post
I don't know how this works trap magic works, I only know it works
I'll take your word for it (I also peeked into traps.cpp, and fortunately that code is well documented).

Here's a short progress report:

I've managed to create and use "uae-native.library" (I took a look at existing code in bsdsocket and some other places)

I've also got a GCC 2.95 cross-compiling build environment now, so I'm self-supplied with Amiga-side test code. It was a nightmare trying to build GCC 2.95 and related tools until I found https://github.com/cahirwpz/m68k-amigaos-toolchain (highly recommended). I must remember to send a thank-you e-email!

I've not tried to make it asynchronous yet, and I haven't written a library wrapper generator either. The latter will make the Amiga-side code nicer and cleaner, though I think the calling code already looks quite nice without library-specific wrappers.

It is looking quite good now, and I'll post some more information and example code later
FrodeSolheim is offline  
Old 01 January 2014, 12:03   #37
Toni Wilen
WinUAE developer
 
Join Date: Aug 2001
Location: Hämeenlinna/Finland
Age: 42
Posts: 19,542
Quote:
Originally Posted by FrodeSolheim View Post
I've managed to create and use "uae-native.library" (I took a look at existing code in bsdsocket and some other places)
Did you miss the example that is attached to post #24? (There is no true library code in UAE, only devices and resource, bsdsocket is not good example because it is very special per-opener library)

I use aros m68k cross compiling environment myself if I need to compile large C projects. For small stuff I use assembly and sometimes SAS-C.
Toni Wilen is offline  
Old 01 January 2014, 12:09   #38
FrodeSolheim
FS-UAE Developer

FrodeSolheim's Avatar
 
Join Date: Dec 2011
Location: Førde, Norway
Age: 36
Posts: 3,368
I have idea how I missed the first sentence and the attachment on that post while still having read the middle part! Too much Christmas food I guess I'll check out the example code! (Btw, I didn't really copy bsdsocket code as I noticed it was "special", I looked at code from bsdsocket, picasso96, and uaeresources in order to understand how it worked...)
FrodeSolheim is offline  
Old 01 January 2014, 12:16   #39
FrodeSolheim
FS-UAE Developer

FrodeSolheim's Avatar
 
Join Date: Dec 2011
Location: Førde, Norway
Age: 36
Posts: 3,368
Thanks for the example code, it seems I needlessly called into m68k with calls to MakeLibrary and AddLibrary, so I'll remove and clean up that bit. The async code example is also very helpful, thanks
FrodeSolheim is offline  
Old 02 January 2014, 05:14   #40
Der Wanderer
Registered User

Der Wanderer's Avatar
 
Join Date: Dec 2013
Location: Mountain View / USA
Posts: 32
I kinda lost track of your thoughts and plans, but if you instruct me I will of course volunteer to write some code and test it. A good test candidate is my synth.dll, as this is a very useful case of going native.

Nice to see that I got you guys excited about this, regarding that you both are generally more interested in game emulation.

EDIT: note that there are more reasons for native code than just increase raw horsepower. e.g. you can write an AHI driver without the need of the emulation knowing/supporting it. Same for OpenGL or other cool stuff.

Last edited by Der Wanderer; 02 January 2014 at 05:44.
Der Wanderer is offline  
AdSense AdSense  
 


Currently Active Users Viewing This Thread: 1 (0 members and 1 guests)
 
Thread Tools

Similar Threads
Thread Thread Starter Forum Replies Last Post
MSVC100.dll error WinUAE 64 MrX_Cuci support.WinUAE 1 26 February 2013 22:21
WinUAE and Windows dll... Gilloo support.WinUAE 1 19 June 2012 16:46
How easy to port WinUAE to non x86? Silver support.OtherUAE 13 19 November 2008 20:52
native x86 code in WinUAE? Falk support.WinUAE 15 14 June 2008 12:58
SFS x86 native for WinUAE? YoJoe! support.WinUAE 8 17 October 2007 11:40

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT +2. The time now is 07:08.


Powered by vBulletin® Version 3.8.8 Beta 1
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Page generated in 0.25248 seconds with 12 queries