Have Any Developments Been Made On This
Is anyone working on this to make it run faster and/or more stable.
Is anyone working on this to make it run faster and/or more stable.
Is anyone working on this to make it run faster and/or more stable.
If I don't update the post - this does not mean that there is no progress.
I've integrated no2chem's DosBox dynamic core patches into my own code, added several specific optimizations, and here is the video showing the current emulation speed:
http://www.multiupload.nl/N6N0JYV3IK - it is HOMM 3 with the hires patch.
The build is still unstable - you can see that it hangs in the video end. But of cause I'm working on that.
I'll publish the binaries when I'll fix current problems and would add more functionality - for example the registry virtualization layer needed by old apps that write to HKLM (that layer is present on desktop Win8, but is removed from RT as there is no need in compatibility). You may see the need of this layer in HOMM 3 video - as I have to reset all game settings on every launch. There are more things to do, fortunately I'm on vacation and have enough time for coding.
The emulation speed seems to be much faster now, is that all from the dynamic core and is that all going to be coming in the next update?
By the way - found the reason why HOMM stopped responding in the end of the posted video. It was due to the lack of "LOCK" prefix emulation in DosBox. Binkw32.dll (video decoder) heavily uses "lock inc [addr] / lock dec [addr]" for synchronization. As DosBox is only single-threaded, it does not need "lock" command at all. But for me it is a must as those operations need to be atomic on multiprocessor machines.
This is awesome, and the fact that you've got HOMM3 (one of my favourite games) running very close to lag free is amazing. Great work!
I'm excited to play HOMM3 on my Surface. One question though, would this emulation be eventually able to emulate proper touch events? As HOMM3 is basically a mouse only game, with touch it could definitely work as a proper game, just need to change the way the game reads touch events (rather than move the cursor, click). Would this be possible?
Thank you for the offer - but I've already implemented all the registry manipulation functions, including the registry key redirection for HKLM that is readonly now for programs that are not run as admin.... I have a small lib for that so if you need something like that I might share it.I am not saying this is great code but might be useful...
Great work. Looking forward to seeing further developments (and helping if I could).
Just out of interest was reading up on the vaguely similar older project at http://wiki.winehq.org/ARM (WINE on Android/LInux ARM)
Yes, I'm looking at their sources and to the code of ReactOS (they have some ARM support too). I can't directly borrow their code as we have too much differences in the core, but I'm looking on the ways how they've implemented some non obvious/undocumented things. And I'm also heavily studying the leaked Windows NT4 and 2000 sources (of cause I don't use any part of them in my project, but they contain really useful information).Just out of interest was reading up on the vaguely similar older project at http://wiki.winehq.org/ARM (WINE on Android/LInux ARM)
Yes, I'm looking at their sources and to the code of ReactOS (they have some ARM support too). I can't directly borrow their code as we have too much differences in the core, but I'm looking on the ways how they've implemented some non obvious/undocumented things. And I'm also heavily studying the leaked Windows NT4 and 2000 sources (of cause I don't use any part of them in my project, but they contain really useful information).
I'll publish a new version this weekend.
The second - incorrect emulation. Or maybe it is my fault, I could initialize emulated FPU control word with a wrong value, for example I could set rounding to the wrong direction (I've taken the value from a desktop Windows 8, and it may differ for Win98 programs). I've tried the Bochs core - the same problem there, so it really may be my bug.Hmm... is 80387 (x86 floating point instruction set) emulation not available, or is it justa bug in the ARM port of DOSBox?
The second - incorrect emulation. Or maybe it is my fault, I could initialize emulated FPU control word with a wrong value, for example I could set rounding to the wrong direction (I've taken the value from a desktop Windows 8, and it may differ for Win98 programs). I've tried the Bochs core - the same problem there, so it really may be my bug.
Edited:
It was my bug. I've set FPU control word to 0x37F, while Win98 value was 0x27F. That one bit controls the FPU precision and caused problems in Pinball.
Not exactly a port, it is a clean remake based on the old ideas.heh, is this a port of the app you showed off back in the CE days? -awesome getting that ported over
The idea is very simple:
#define DEFINE_FUNC1(name) \
static const ModuleDef str_##name={DLL_NAME,#name}; \
EXTERN_C DW STUB_EXPORT stub_##name(DW p1) \
{ \
DW *p=&p1; \
__asm { mov eax,p } \
__asm { jmp f1 } \
__asm { mov eax,offset str_##name } \
f1: __asm { in eax,0xe5 } \
__asm { mov p,eax } \
return (DW)p; \
}
.....
#define DEFINE_FUNC3(name) \
static const ModuleDef str_##name={DLL_NAME,#name}; \
EXTERN_C DW STUB_EXPORT stub_##name(DW p1,DW p2,DW p3) \
{ \
DW *p=&p1; \
__asm { mov eax,p } \
__asm { jmp f1 } \
__asm { mov eax,offset str_##name } \
f1: __asm { in eax,0xe5 } \
__asm { mov p,eax } \
return (DW)p; \
}
....
DEFINE_FUNC1(AddAtomA)
DEFINE_FUNC1(AddAtomW)
DEFINE_FUNC7(CreateFileA) -- number in macro == number of parameters to a __stdcall WinAPI function.
Compiler automatically generates "ret N*4" at the end of such function.
I've decided to use such c+asm approach instead of making a tiny assebler stub,
as I can easily implement some of such functions in C directly in a stub DLL plus it
simplifies debugging. And the functions have a usual C prologue/epilogue, so that
the emulated program may even patch them in runtime, for example for hooks.
...
#define DEFINE_FUNC1(name) \
EXTERN_C DW STUB_IMPORT name(DW); \ -- this behaves like a function prototype to compiler
EXTERN_C DW STUB_EXPORT yact_##name(DW *R) \ -- R - pointer to the x86 stack
{ \
DW r=name(p1); \ // call the func passing it paramers from the emulated stack, p1==R[0], p2==R[1] and so on
LEAVE(1); \ // empty macro, as the stack is unwinded in x86 stub DLL now
return r; \
}
...
#define DEFINE_FUNC3(name) \
EXTERN_C DW STUB_IMPORT name(DW,DW,DW); \
EXTERN_C DW STUB_EXPORT yact_##name(DW *R) \
{ \
DW r=name(p1,p2,p3); \
LEAVE(3); \
return r; \
}
...
DEFINE_FUNC1(AddAtomA)
DEFINE_FUNC1(AddAtomW)
DEFINE_FUNC7(CreateFileA) // as you see - implementation part is identical to an x86 stub, so I can use the same stub-generator tool
static DWORD WINAPI ThreadProc(
LPVOID lpParameter // [0] == orig func, [1] == orig param
)
{
__EXCEPTION_REGISTRATION_RECORD R;
DWORD *Parm=(DWORD*)lpParameter;
DWORD *TEB=(DWORD*)PeLdrGetCurrentTeb();
R.Next=(__EXCEPTION_REGISTRATION_RECORD*)-1;
R.Handler=(void*)CbReturnToHost();
TEB[0]=(DWORD)&R; // in case of unhandled exception - just return
PeLdrNotifyNewThread(NULL,DLL_THREAD_ATTACH);
DWORD Ret=EmuExecute(Parm[0],1,Parm[1]); // 1 == number of parameters to the emulated function
delete Parm;
return Ret;
}
EXTERN_C DW STUB_EXPORT yact_CreateThread(DW *R)
{
DWORD* Parm=new DWORD[2];
Parm[0]=p3; // TODO: no out-of-memory checking for now
Parm[1]=p4;
DWORD StackSize=p2;
if(StackSize)
StackSize+=1024*1024; // I reserve some space for my own needs (debugging)
else
StackSize=2*1024*1024; // TODO: I don't support autogrow stacks, so reserve 2 Mb
DWORD t=(DWORD)CreateThread((LPSECURITY_ATTRIBUTES)p1,StackSize,ThreadProc,Parm,p5,(LPDWORD)p6);
LEAVE(6);
return t;
}