Closed joncampbell123 closed 3 months ago
It is not a problem create special startup code for Windows 1.0 and setup linker to use this code for windows1 target only. But I know nothing about Windows 1.0 that I cannot comment anyway. I don't know history of __AHSHIFT. If you will have any idea that we can try to implement it.
I wasn't aware of __AHSHIFT until I looked at the C runtime startup ASM file. It looks like it's a constant provided by the Win16 kernel describing the arithmetic shift needed to convert far pointers properly.
In pseudocode the idea is:
ifdef WINDOWS10
ax = call far GETMODULEHANDLE("KERNEL")
dx:ax = call far GETPROCADDRESS(ax,114) ; "__AHINCR" by ordinal
if dx:ax != 0
_HShift = ax ; dx:ax is very likely FFFF:<AHINCR constant value>
else
_HShift = 12
endif
else
_HShift = __AHINCR ; existing code for Windows 2.0 and higher
endif
make sense?
Only Windows 1.x lacks ordinal 114. Using the EXENEDMP tool in DOSLIB, Kernel.exe in Windows 1.04 ordinal symbols only go up to 103 "NETBIOSCALL" and no higher.
I can confirm as well with EXENEDMP and the Windows 1.0 SDK that GetProcAddress() (ordinal 50) and GetModuleHandle() (ordinal 47) exist in Windows 1.04.
Speaking of which, I see a possible optimization in cstrtw16.c:
mov _HShift,al ; ...
cmp al,12 ; real mode?
je notprot ; yes, so leave osmode alone
mov al,1
mov _osmode,al ; protected mode!
If you're going to load "1" into _osmode why not just "mov _osmode,1" instead of loading into AL just to then load to memory? I think the base 8086 instruction set is capable of supporting that.
EDIT: Unless of course this combination of instructions takes fewer bytes than the single MOV instruction...?
I'll make this change myself and submit a pull request. Sound good?
Uh, ok, never mind then.
I understand Windows 1.0 erroring out and crashing to DOS if any symbol in an EXE cannot be resolved, but to crash to DOS if GetProcAddress cannot find a symbol? Really?
If you can't conditionally refer to symbols with GetProcAddress() then what's the point of even using GetProcAddress()????????
Windows 1.0 doesn't have the SetErrorMode() function that 3.0 does when you don't want Windows showing error messages every time GetProcAddress can't find a symbol.
Never mind.
I'd write code to poke at data structures through the HINSTANCE value of "KERNEL" to figure out if __AHINCR exists but that's really not appropriate for C runtime startup code.
Ironically the ASM I wrote worked perfectly fine under Windows 2.0 and 3.0 but those already have __AHINCR anyway, making the test pointless if Windows 1.0 won't even allow GetProcAddress() to retrieve a symbol without making it hard dependency.
Only note _osmode is mainly for OS/2 to differ between DOS real-mode and OS/2 16-bit protected mode. Generaly is used to signal 16-bit protected mode (DOS16M).
It just occurred to me that perhaps the C runtime for Windows 1.0 targets could use GetProcAddress to look for the AHSHIFT symbol (by ordinal) so that any logic to convert far pointers where AHSHIFT is needed will still run properly in the protected mode environment of later windows. Just use GetModuleHandle() and GetProcAddress() to read __AHSHIFT if available, assume real mode if not.
Sound like something I should submit as a pull request?
I will of course test it against real Windows 1.0 through 3.1 in DOSBox-X to make sure there's no ill effects, and that code would only exist in the Windows 1.0 builds of the C runtime startup code.
__AHSHIFT may not exist in Windows 1.0 but I'm pretty sure GETPROCADDRESS and GETMODULEHANDLE exist as part of the base Win16 API even back then.