aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJaroslav Hensl <jara@hensl.cz>2024-04-25 00:20:29 +0200
committerJaroslav Hensl <jara@hensl.cz>2024-04-25 00:20:29 +0200
commit7f151e52c991ebd013ff9523004b6584cfd5653e (patch)
treeb2fc948e303703d13760c76f4badd460f909140e
parent484d69bd1cc2104525707f870ae5ca1b2a97bdf3 (diff)
downloadvmdisp9x-7f151e52c991ebd013ff9523004b6584cfd5653e.tar.gz
font fix - added driver fix utility when Watcom linker is used
-rw-r--r--drvfix.c208
-rw-r--r--makefile34
2 files changed, 233 insertions, 9 deletions
diff --git a/drvfix.c b/drvfix.c
new file mode 100644
index 0000000..a2a1df0
--- /dev/null
+++ b/drvfix.c
@@ -0,0 +1,208 @@
+/*****************************************************************************
+
+Copyright (c) 2024 Jaroslav Hensl <emulator@emulace.cz>
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+
+*****************************************************************************/
+
+/* Fix NE executable version to 0x400 */
+
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#pragma pack(push)
+#pragma pack(1)
+
+/* http://www.delorie.com/djgpp/doc/exe/ */
+typedef struct EXE_header {
+ uint16_t signature; /* == 0x5a4D */
+ uint16_t bytes_in_last_block;
+ uint16_t blocks_in_file;
+ uint16_t num_relocs;
+ uint16_t header_paragraphs;
+ uint16_t min_extra_paragraphs;
+ uint16_t max_extra_paragraphs;
+ uint16_t ss;
+ uint16_t sp;
+ uint16_t checksum;
+ uint16_t ip;
+ uint16_t cs;
+ uint16_t reloc_table_offset;
+ uint16_t overlay_number;
+} EXE_header_t;
+
+#define EXE_SIGN 0x5a4D
+
+/* from: https://wiki.osdev.org/NE */
+typedef struct NE_header
+{
+ uint16_t signature; //"NE", 0x4543
+ uint8_t MajLinkerVersion; //The major linker version
+ uint8_t MinLinkerVersion; //The minor linker version
+ uint16_t EntryTableOffset; //Offset of entry table, see below
+ uint16_t EntryTableLength; //Length of entry table in bytes
+ uint32_t FileLoadCRC; //32-bit CRC of entire contents of file
+ uint8_t ProgFlags; //Program flags, bitmapped
+ uint8_t ApplFlags; //Application flags, bitmapped
+ uint16_t AutoDataSegIndex; //The automatic data segment index
+ uint16_t InitHeapSize; //The initial local heap size
+ uint16_t InitStackSize; //The initial stack size
+ uint32_t EntryPoint; //CS:IP entry point, CS is index into segment table
+ uint32_t InitStack; //SS:SP initial stack pointer, SS is index into segment table
+ uint16_t SegCount; //Number of segments in segment table
+ uint16_t ModRefs; //Number of module references (DLLs)
+ uint16_t NoResNamesTabSiz; //Size of non-resident names table, in bytes (Please clarify non-resident names table)
+ uint16_t SegTableOffset; //Offset of Segment table
+ uint16_t ResTableOffset; //Offset of resources table
+ uint16_t ResidNamTable; //Offset of resident names table
+ uint16_t ModRefTable; //Offset of module reference table
+ uint16_t ImportNameTable; //Offset of imported names table (array of counted strings, terminated with string of length 00h)
+ uint32_t OffStartNonResTab; //Offset from start of file to non-resident names table
+ uint16_t MovEntryCount; //Count of moveable entry point listed in entry table
+ uint16_t FileAlnSzShftCnt; //File alignment size shift count (0=9(default 512 byte pages))
+ uint16_t nResTabEntries; //Number of resource table entries
+ uint8_t targOS; //Target OS
+ uint8_t OS2EXEFlags; //Other OS/2 flags
+ uint16_t retThunkOffset; //Offset to return thunks or start of gangload area - what is gangload?
+ uint16_t segrefthunksoff; //Offset to segment reference thunks or size of gangload area
+ uint16_t mincodeswap; //Minimum code swap area size
+ uint16_t expctwinver; //Expected windows version eg. 0x030A, 0x0400
+} NE_header_t;
+
+#define NE_SIGN 0x454E
+
+#pragma pack(pop)
+
+#define ERROR_OPEN -1
+#define ERROR_FREAD -2
+#define ERROR_WRITE -3
+#define ERROR_SEEK -4
+#define ERROR_SIGN_MZ -5
+#define ERROR_SIGN_NE -6
+
+long fix_exe(const char *file, uint16_t new_expctwinver)
+{
+ EXE_header_t exe;
+ NE_header_t ne;
+ FILE *f;
+ int rc = 0;
+ long offset;
+
+ f = fopen(file, "r+b");
+ if(f != NULL)
+ {
+ if(fread(&exe, sizeof(EXE_header_t), 1, f) == 1)
+ {
+ if(exe.signature == EXE_SIGN)
+ {
+ offset = exe.blocks_in_file * 512;
+ if(exe.bytes_in_last_block)
+ {
+ offset -= (512 - exe.bytes_in_last_block);
+ }
+
+ if(fseek(f, offset, SEEK_SET) == 0)
+ {
+ if(fread(&ne, sizeof(NE_header_t), 1, f) == 1)
+ {
+ if(ne.signature == NE_SIGN)
+ {
+ rc = ne.expctwinver;
+ if(ne.expctwinver != new_expctwinver)
+ {
+ ne.expctwinver = new_expctwinver;
+ if(fseek(f, offset, SEEK_SET) == 0)
+ {
+ if(fwrite(&ne, sizeof(NE_header_t), 1, f) != 1)
+ rc = ERROR_WRITE;
+ } else rc = ERROR_SEEK;
+ }
+ } else rc = ERROR_SIGN_NE;
+ } else rc = ERROR_FREAD;
+ } else rc = ERROR_SEEK;
+ } else rc = ERROR_SIGN_MZ;
+ } else rc = ERROR_FREAD;
+
+ fclose(f);
+ } else rc = ERROR_OPEN;
+
+ return rc;
+}
+
+int main(int argc, char *argv[])
+{
+ uint16_t expctwinver = 0x400;
+ long rc;
+
+ if(argc < 2)
+ {
+ printf("Usage: %s <file_to_patch.drv> [new expected windows version in hex]\n"
+ "expected version is 0400 by default.\n\n"
+ "Example: %s mydriver.drv 0400\n", argv[0], argv[0]);
+ return EXIT_FAILURE;
+ }
+
+ if(argc >= 4)
+ {
+ expctwinver = strtol(argv[2], NULL, 16);
+ }
+
+ rc = fix_exe(argv[1], expctwinver);
+
+ if(rc < 0)
+ {
+ switch(rc)
+ {
+ case ERROR_OPEN:
+ printf("Failed to open %s\n", argv[1]);
+ break;
+ case ERROR_FREAD:
+ printf("Read error (file corrupted?)\n");
+ break;
+ case ERROR_WRITE:
+ printf("Write error (file readonly, in usage)\n");
+ break;
+ case ERROR_SEEK:
+ printf("Seek error (file corrupted?)\n");
+ break;
+ case ERROR_SIGN_MZ:
+ printf("File is not EXE!\n");
+ break;
+ case ERROR_SIGN_NE:
+ printf("File is not NE!\n");
+ break;
+ }
+
+ return EXIT_FAILURE;
+ }
+
+ if(rc == expctwinver)
+ {
+ printf("%s: NE.expctwinver is already %lX\n", argv[1], rc);
+ }
+ else
+ {
+ printf("%s: NE.expctwinver %lX => %lX\n", argv[1], rc, ((unsigned long)expctwinver));
+ }
+
+ return EXIT_SUCCESS;
+}
+
diff --git a/makefile b/makefile
index 7766b21..2ca5380 100644
--- a/makefile
+++ b/makefile
@@ -11,16 +11,25 @@ OBJS += &
INCS = -I$(%WATCOM)\h\win -Iddk -Ivmware
-VER_BUILD = 47
+VER_BUILD = 48
FLAGS = -DDRV_VER_BUILD=$(VER_BUILD)
-# Watcom resource compiler haven't -40 option, but without it DIB engine displays
-# wrong some national fonts and denies to use font smooth edge.
+# Watcom resource compiler haven't -40 option, but without it DIB engine
+# displays wrong some national fonts and denies to use font smooth edge.
# This option allow to use MS 16-bit RC.EXE from DDK98 but you need
# 32 bit Windows to run this (and DDK98 installed of course).
#DDK98_PATH = C:\98DDK
+# Alternative to DDK 98 (and 16bit subsystem) on HOST is fix output exe
+# (new executable) flags. Utility source is in drvfix.c but if your
+# HOST machine isn't Windows, you've to adjust these 2 variables:
+# executable file name
+FIXER_EXE = drvfix.exe
+# command line to produce executable
+FIXER_CC = wcl386 -q drvfix.c -fe=$(FIXER_EXE)
+# FIXER_CC = gcc drvfix.c -o drvfix
+
# Define HWBLT if BitBlt can be accelerated.
#FLAGS += -DHWBLT
@@ -57,10 +66,12 @@ RC16_FLAGS = -40 -i $(DDK98_PATH)\inc\win98\inc16 -i res -d DRV_VER_BUILD=$(VER_
BOXVMINI_DRV_RC = $(RC16) $(RC16_FLAGS) res\boxvmini.rc $@
VMWSMINI_DRV_RC = $(RC16) $(RC16_FLAGS) res\vmwsmini.rc $@
QEMUMINI_DRV_RC = $(RC16) $(RC16_FLAGS) res\qemumini.rc $@
+NEED_FIXER =
!else
-BOXVMINI_DRV_RC = wrc -q boxvmini.res $@
-VMWSMINI_DRV_RC = wrc -q vmwsmini.res $@
-QEMUMINI_DRV_RC = wrc -q qemumini.res $@
+BOXVMINI_DRV_RC = wrc -q boxvmini.res $@ && $(FIXER_EXE) $@
+VMWSMINI_DRV_RC = wrc -q vmwsmini.res $@ && $(FIXER_EXE) $@
+QEMUMINI_DRV_RC = wrc -q qemumini.res $@ && $(FIXER_EXE) $@
+NEED_FIXER = $(FIXER_EXE)
!endif
all : vmwsmini.drv vmwsmini.vxd qemumini.drv qemumini.vxd boxvmini.drv boxvmini.vxd
@@ -194,7 +205,11 @@ res/fonts120.bin : res/fonts120.c .autodepend
dibeng.lib : ddk/dibeng.lbc
wlib -b -q -n -fo -ii @$< $@
-boxvmini.drv : $(OBJS) boxvmini.res dibeng.lib
+# Fixer
+$(NEED_FIXER): drvfix.c
+ $(FIXER_CC)
+
+boxvmini.drv : $(OBJS) boxvmini.res dibeng.lib $(NEED_FIXER)
wlink op quiet, start=DriverInit_ disable 2055 $(DBGFILE) @<<boxvmini.lnk
system windows dll initglobal
file dibcall.obj
@@ -261,7 +276,7 @@ import GlobalSmartPageLock KERNEL.230
<<
$(BOXVMINI_DRV_RC)
-vmwsmini.drv : $(OBJS) vmwsmini.res dibeng.lib
+vmwsmini.drv : $(OBJS) vmwsmini.res dibeng.lib $(NEED_FIXER)
wlink op quiet, start=DriverInit_ disable 2055 $(DBGFILE) @<<vmwsmini.lnk
system windows dll initglobal
file dibcall.obj
@@ -328,7 +343,7 @@ import GlobalSmartPageLock KERNEL.230
<<
$(VMWSMINI_DRV_RC)
-qemumini.drv : $(OBJS) qemumini.res dibeng.lib
+qemumini.drv : $(OBJS) qemumini.res dibeng.lib $(NEED_FIXER)
wlink op quiet, start=DriverInit_ disable 2055 $(DBGFILE) @<<qemumini.lnk
system windows dll initglobal
file dibcall.obj
@@ -469,6 +484,7 @@ clean : .symbolic
rm res/*.obj
rm res/*.bin
rm vmware/*.obj
+ -rm -f $(FIXER_EXE)
image : .symbolic boxv9x.img