TTLG|Thief|Bioshock|System Shock|Deus Ex|Mobile
Page 1 of 10 123456 ... LastLast
Results 1 to 25 of 235

Thread: System Shock 1 in 800x600 and 1024x768 [v2.0] [nV4 issues fixed!]

  1. #1
    Member
    Registered: Feb 2002

    System Shock 1 in 800x600 and 1024x768 [v2.0] [nV4 issues fixed!]

    A while ago, I read something about how SS1 could have supported resolutions higher than 640x480, but they disabled those in the final build because no computer at the time could run them playably.
    This got me thinking: getting SS1 working at higher resolutions might be as simple as finding the SVGA mode set call and changing its parameters.
    It turned out to be a bit more complicated than that (in some ways; getting the interface working, on the other hand, was far easier than I expected), but here it is: SS1 with support for high resolution rendering.

    Version 2.0 has been released!
    This version takes the form of a seperate patch (about 550kb) which can be used to override the 640x400 and 640x480 modes seperately on both Mok's patched version and the original CDSHOCK.EXE.

    Usage:
    'ss1hr CDSHOCK.EXE' (or drag-dropping CDSHOCK.EXE onto it, for you GUI addicts) will give you an interactive interface from which you can adjust the settings.
    If you want to use it in batch mode, 'ss1hr CDSHOCK.EXE <string of numbers>' will run non-interactively, behaving as though you had entered those numbers as the menu options (as in, 'ss1hr CDSHOCK.EXE 13244'). For example, some useful sequences:
    Code:
    34      Reset to defaults
    114     Reset 640x400 to default
    224     Reset 640x480 to default
    13244   640x400 -> 800x600, 640x480 -> 1024x768
    15224	640x400 -> 1280x1024, 640x480 to default
    The basic commands being (if you're too lazy to look at the menus :p )
    1M  Map 640x400 to mode M
    2M  Map 640x480 to mode M
    3   Reset all to defaults
    4   Exit
    And the mode numbers (the ones in the menu, not the actual SVGA mode numbers!):
    1    640x400
    2    640x480
    3    800x600
    4    1024x768
    5    1280x1024
    Note that failure to end with 4 (exit) may result in crashes, lost settings, etc (but any damage to your copy of SS1 can be corrected with 3, reset to defaults).

    The only real difference from the technical details below is that the code is left unchanged, and instead the SVGA mode number table at 0x00172620 (original) or 0x001460D4 (Mok's) is changed.

    Known bugs:
    - there's some intermittent but serious chop in 1024x768; I think this is a memory page-flipping issue, but I'm not sure. If it's too slow to be playable try the 800x600 version.
    - no widescreen support yet (is this possible?)
    - Movies haven't been rescaled, so they still play at 640x480 in the upper left corner of the screen. They also seem to exhibit some corruption (horizontal streaks across the movie) - if you're seeing them for the first time you might want to watch the movies using 640x480.

    Win32 PE binary
    C source code
    No DOS binary release; if anyone can generate an MZ-format DOS binary I'd be glad to host it. In the meantime, DOS versions of CDSHOCK.EXE (the 640x400 mode is overridden; 640x480 remains unchanged):
    800x600
    1024x768
    1280x1024

    nVidia GeForce 4 users, read this!
    There is an issue with the nV VESA support for resolutions greater than 640x480. This manifests as the monitor turning itself off or reporting "sync out of range" or "refresh rate out of range" when you attempt to use higher resolutions.
    The excellent Infinitron has tracked down a fix for this, which can be found in the links on this page.

    Screenshots:
    1024x768, before I got the interface scaling factors set up right
    800x600
    1024x768
    (800x600) 2-4601 vs a Sec-2 bot on Deck 7
    (1024x768) SHODAN's inner sanctum

    Sizes and MD5sums:
    Code:
    Name         Size    md5sum
      SSHOCK.EXE 1254195 0d95815046907b8201a46ada6b440bca -- original version
     CDSHOCK.EXE 1543695 ca7d6016312453a1b099863ba2e689ab -- CD-enhanced version
     CDSHOCK.MOK 1362115 8ee4a7a9b018d2757d639fdf0cd6f3bc -- Mok's NT patched version
    Technical details


    The information below is obsolete, applying to version 1.0 of SS1-highres, which consisted of several different, hardpatched copies. It is preserved here for informational purposes.


    The actual implementation is kind of ugly. 320x240 and 320x400 should behave normally. 640x400 or 640x480 will actually kick it into high-resolution mode. There are two such modes available, 800x600x8 and 1024x768x8; since this was done, in effect, by replacing the 640x* modes with a single new mode, there are actually two versions of CDSHOCK.EXE, each one supporting a different mode: CDSH800.EXE and CDSH1024.EXE.

    If all you want to do is play in high-res you don't need to read this; this is for people interested in how I did it.
    (note: all offsets are within CDSHOCK.EXE and have no relation to what the program looks like once it's loaded and relocated in memory.)

    Code:
    Offsets:
    Original CDSHOCK.EXE:
    E1661	; interface control calls
    15815B	; set video mode
    16B5B0	; resolution/bit depth tables
    
    Mok's patched binary:
    B5115	; interface control calls
    12BC0F	; set video mode for in-game SVGA
    13f070	; resolution/bit depth tables
    The SVGA mode switch

    At 0x0012BB68 is a function which is used to do a mode switch to an SVGA mode specified by the caller[?]. The actual interesting code starts at 0x0012BC0E, using INT 31 (DPMI SERVICES) to invoke DPMI function 300h (SIMULATE REAL MODE INTERRUPT), simulating INT 10h with AX=4f02 (SVGA SET VIDEO MODE) to change modes:

    Code:
    			; 4f02h = SVGA (4f) SET VIDEO MODE (02)
    66 b8 02 4f		mov     ax, 4F02h
    			; load mode # into EBX
    0f b7 1c 4d 7c 2f 01 00	movzx	ebx, word ptr ds:12F7Ch[ecx*2]
    c1 e2 0f		shl     edx, 0Fh
    57			push    edi
    			; load pointer to real-mode call struct into EDI
    bf b0 28 01 00		mov     edi, 128B0h
    0b da			or      ebx, edx
    			; store AX,BX into struct
    66 89 47 1c		mov     [edi+1Ch], ax
    89 5f 10		mov     [edi+10h], ebx
    51			push    ecx
    			; real-mode interrupt to simulate (10h)
    b3 10			mov     bl, 10h
    			; paragraphs to copy from real-mode stack (0)
    66 b9 00 00		mov     cx, 0
    			; DPMI function (300h SIMULATE REAL-MODE INTERRUPT)
    66 b8 00 03		mov     ax, 300h
    32 ff			xor     bh, bh
    			; DPMI services, AX = function #
    cd 31			int     31h
    			; cleanup
    59			pop     ecx
    This was changed by removing the XOR BH,BH (which is unecessary) and the OR EBX,EDX (which is unecessary in the new code, since the video mode # is hardcoded). This freed up 4 bytes which could be used to set BX just before it gets copied into the real-mode call struct:
    (added instructions in blue, removed ones in red)
    Code:
    			; 4f02h = SVGA (4f) SET VIDEO MODE (02)
    66 b8 02 4f		mov     ax, 4F02h
    			; load mode # into EBX
    0f b7 1c 4d 7c 2f 01 00	movzx	ebx, word ptr ds:12F7Ch[ecx*2]
    c1 e2 0f		shl     edx, 0Fh
    57			push    edi
    			; load pointer to real-mode call struct into EDI
    bf b0 28 01 00		mov     edi, 128B0h
    0b da			or      ebx, edx	; REMOVED
    			; BX = 0x0103 (mode 103h, 800x600x8)
    b3 03			mov	bl, 03h
    b7 01			mov	bh, 01h
    			; store AX,BX into struct
    66 89 47 1c		mov     [edi+1Ch], ax
    89 5f 10		mov     [edi+10h], ebx
    51			push    ecx
    			; real-mode interrupt to simulate (10h)
    b3 10			mov     bl, 10h
    			; paragraphs to copy from real-mode stack (0)
    66 b9 00 00		mov     cx, 0
    			; DPMI function (300h SIMULATE REAL-MODE INTERRUPT)
    66 b8 00 03		mov     ax, 300h
    32 ff			xor     bh, bh	; REMOVED
    			; DPMI services, AX = function #
    cd 31			int     31h
    			; cleanup
    59			pop     ecx
    Thus, whenever it does an SVGA mode change, it's forced into the new mode I picked for it (800x600 in this case; changing MOV BL,03h to MOV BL,05h is used in the 1024x768 version). This is ugly, hackish and inelegant, but it works.

    The LFB parameters

    Just changing the resolution does not result in a usable display, because the renderer completely ignores the values returned by INT 10h/AX=4f01h (SVGA GET VIDEO MODE INFORMATION) and instead uses values from a hardcoded table to determine the width, length and depth of the framebuffer. This table starts at 0x0013F070 and appears to consist of 5-byte structs of the following format:
    0000 uint16_t screen width
    0002 uint16_t screen height
    0004 uint8_t bits per pixel? always 8

    So, making the renderer happy was a simple matter of finding 80 02 E0 01 08 in this table (640x480x8) and changing it to 20 03 58 02 08 (800x600x8) or 00 04 00 03 08 (1024x768x8), then doing the same for 80 02 90 01 08 (640x400x8).

    The interface

    This was actually the first part I got working, having stumbled upon it while looking for something completely different (the SVGA mode switch). At 0x000B50F2 there's a series of function calls, looking something like this (in C):

    Code:
    baz(320,400)	// SS1
    baz(640,400)	// SS1,SVGA mode 100h
    baz(640,480)	// SS1,SVGA mode 101h
    baz(1024,768)	// SVGA mode 107h
    if(thingy == 3) {
    	baz(320,240)	// SS1
    	baz(640,240)
    } else {
    	baz(320,100)	// are these even valid modes?
    	baz(640,350)
    }
    These control, albeit in ways I don't fully understand, the interface scaling and positioning parameters. It's very interesting to note that there's already an entry in place for 1024x768. Replacing the 640,400 and 640,480 calls with 800,600 (for CDSH800) or 1024,768 (for CDSH1024) causes the interface to be properly scaled and all buttons and suchlike to be properly positioned (although the text isn't scaled, resulting in a lot of empty space in the buttons!).
    Last edited by ToxicFrog; 13th Oct 2005 at 23:21. Reason: Version 2.0 released

  2. #2
    Member
    Registered: Oct 2004
    Location: Nikolayevskaya
    Hat duly removed!

  3. #3
    Member
    Registered: Feb 2003
    Location: Finland

    Wohoo!

    Nice work, ToxicFrog!

    System Shock surely looks and works nicely at 1024x768 resolution!

  4. #4
    Member
    Registered: Apr 2001
    Location: England
    ...AAAAARRRGGHHH!!!

    I could've done that, too! Why the hell didn't I?!

    Somewhere on my disk (in the WINIFY project folder) is a nicely decompiled SS1. It's still in Assembly and the variables don't have sensible names yet, but I've split out the segments and identified some parts of it.

    Nice work doing something with the binary, TF!

  5. #5
    Zombified
    Registered: Sep 2004
    ..I want opengl

  6. #6
    Member
    Registered: Feb 2002
    Quote Originally Posted by descenterace
    Somewhere on my disk (in the WINIFY project folder) is a nicely decompiled SS1. It's still in Assembly and the variables don't have sensible names yet, but I've split out the segments and identified some parts of it.
    What did you use to disassemble it? There's something about it that drives IDA insane - I had to load it as a raw binary rather than as an MZ and specify function entry points by hand to get anything sane out of it, and none of the other disassemblers I tried gave me even that much.

    Quote Originally Posted by voodoo47
    ..I want opengl
    You'll have to wait for TSSHP for that, I'm afraid.

  7. #7
    Member
    Registered: Apr 2001
    Location: England
    That won't happen until I've reverse-engineered the whole thing. Which won't happen at all.

    I was planning to pull it apart sufficiently to plug it into a Windows compatibility layer. It'd still be software-rendered, but at least it'd work natively in Windows.

    Even better: if I can fiddle the GDT in Windows without causing a horrible kernel crash, I can write a generalised service which will run DOS/4GW apps natively in Windows XP. But that's still in the realm of 'dreams'.

    I used IDA Pro. It worked fine with SS1, once I'd extracted it from the DOS extender. You might want to use DOS/32A to remove the extender.
    BTW, there is one horrible section where a lookup table is used to call interrupts. Machine Code has been inserted directly into the application and referenced as an array of functions. You should be able to find this bit by looking for CD 10 C3 CD 11 C3 CD 12 C3.
    Then there's a bit where an interrupt call is created on the stack, then a far call is made into that part of the stack segment...
    These guys were not scared of self-modifying/generating code.

  8. #8
    Member
    Registered: Feb 2002
    Quote Originally Posted by descenterace
    I used IDA Pro. It worked fine with SS1, once I'd extracted it from the DOS extender. You might want to use DOS/32A to remove the extender.
    That would be the problem. I'll look into that, thanks.

    Quote Originally Posted by descenterace
    These guys were not scared of self-modifying/generating code.
    Why should they be? Once you've dealt with SHODAN everything else is small potatoes. :P

  9. #9
    Member
    Registered: Jul 1999
    Location: Beta Grove
    I have problems with this, though they are similar (but not exactly the same) to the ones I have with the original CDSHOCK. Trying to replay the intro movie results in a blank screen, but any key/mousepress returns to the main menu. Trying to change resolution to "640x480" in-game results in a blank screen for about a minute and then the game crashes to desktop; with CDSHOCK.EXE it crashed immidiately when I tried to change resolution.

    I am using the CD version of SS1, running it on WinXP using VMSOUND, NOLFB.COM, a winXP patch and a variant of the msdos executable, as detailed in the FAQ, but not the mouse program as it crashes the game and the game runs well (except for being low-res) without it.

  10. #10
    Member
    Registered: Feb 2002
    As a general rule, if it won't work in 640x480, it won't work in 800x600 or 1024x768 either, since what it's doing is fundamentally the same.
    I can't really duplicate your setup here; in particular, mine crashes if I try to run it with NOLFB, but requires MOUSE2KV - but since yours works in 320x* and not in 640x*, that sounds like an SVGA issue. Since you're using VDMS, try ticking 'enable basic VESA support' in the VDMS shortcut if you haven't already; apart from that I can't think of anything to try.
    (Hmm. Although I didn't realize this when I started work on this, it's actually based on Mok's patched XP version, and thus all the offsets etc are into that file, not the stock CDSHOCK.EXE -- so this is in a sense pre-patched for XP. Anyone willing to test it on a win32 box?)

  11. #11
    Member
    Registered: Apr 2001
    Location: England
    <return-of-the-mad-programmer>

    Would it be possible to convert the SS1 binary to some kind of bytecode, then execute it on a Virtual Machine? I started an x86 emulator a few months back but it would've been slower than DOSBox. Maybe a VM designed specifically to replace an extender?

    I could write a Java app to do the initial conversion to bytecode, but the VM would probably have to either be C++ or .NET (function pointers would be a requirement).

    Anyone want me to investigate this further? A VM that can cope with code created on-the-fly might be awkward, but JIT bytecode conversion and compilation might solve it. The bytecode would of course be interpreted, but I'm considering an intermediate step where fixed logical addresses would be replaced by pointers to the VM's registers and memory space.

    And why is it that ideas always strike at 23:15 when I'm trying to sleep?

    [edit] *eep* I might want to do this whole thing in Java, actually. Managing memory will be a bitch otherwise.
    Rejoice, for soon x86 DOS games will all run on Java VMs...

    A VM on a VM? Yeah, I know it's slow. So? What do you expect to use a 3GHz CPU for anyway?

    </return-of-the-mad-programmer>
    Last edited by descenterace; 9th Sep 2005 at 19:39.

  12. #12
    Member
    Registered: Feb 2002
    Java? JAVA?! Your words are madness, for Java is a creation of the elder gods that dwell beyond space and time, created only to drive programmers insane.
    (you might want to look into Lua, though. Garbarge-collected, function references, highly portable and faster, in my experience, than Java)

    The big thing you have to ask yourself is: will this really be any more compatible or performant than DOSBOX?

  13. #13
    Member
    Registered: Apr 2001
    Location: England
    No, but it WILL run games besides SS1 without hassle on WinXP.

    Plus, I want to play Terminal Velocity again.

    Java certainly seems to be... suboptimal... for this task. I might go for C# instead, but I don't know if Mono is up to this task yet and I don't like .NET 1.1's lack of generics.


    If only Java supported delegates.


    Actually, C++ is starting to look attractive again. Memory management shouldn't be a problem since I've come up with a way of handling a native/bytecode duality in the same memory space which doesn't involve heavy GCing. Nicest thing is, it supports self-modifying code. I can even fork off a thread for do background compilation.
    Using static code analysis the 'compiler' would extract semantics from the machine code during the load phase. While it's running, execution lookups look at cached bytecode. If the required address hasn't been translated during the load phase, it means that the instruction pointer is offset from the expected position by a byte or two and the code is re-examined. Delays due to this should be small, and rare too if I can develop a flow analyser based on IDA's.
    Data lookups look at the native memory space. If this is modified in any way, any cached bytecode in the affected area is deleted.

    So now I need a lookup system that's as close to O(n) as possible with consecutive lookups. Some form of N-tree with a large N should do it, indexed by address.
    Last edited by descenterace; 9th Sep 2005 at 21:13.

  14. #14
    Member
    Registered: Feb 2002
    Quote Originally Posted by descenterace
    No, but it WILL run games besides SS1 without hassle on WinXP.
    Forgive me if I'm just not getting the point here, but what it looks like is you're designing a program that does what DOSBOX already does, with no significant performance or compatibility improvements, and expending a lot of effort that could be put into improving DOSBOX itself...

  15. #15
    ToxicFrog: I've not tried this out yet, but I just want to say that you rock. Awesome work. Thank you!! :)

  16. #16
    New Member
    Registered: May 2005
    The patches just don't work for me in XP - when I try to switch to the higher resolutions (or watch the intro) my screen turns black, like the game's using an unsupported resolution or refresh rate. I've tried it with and without NOLFB, MOUSE2KV and VDMSound and played with all the settings I could think of. Any ideas?

    Quote Originally Posted by ToxicFrog
    Anyone willing to test it on a win32 box?
    I'll be testing it on two radically different 98se machines later today.

  17. #17
    Member
    Registered: Nov 2003
    Location: See the wrench in the shadows?
    It's not working under XP for me either. I can actually get in game and everything, but when I switch to the highest resolutions, my monitor actually shut right off because of there being no signal input.
    She's not a maniac, a raving thing, she just goes a little mad sometimes.
    I'm not suffering from insanity; I enjoy every minute of it.

  18. #18
    Member
    Registered: Feb 2002
    o.O That shouldn't happen.
    I take it that it _does_ work when using the original?
    Is your original the stock CDSHOCK.EXE, or Mok's patched version?
    Do both the 800x600 and 1024x768 versions do this?

  19. #19
    Member
    Registered: Nov 2003
    Location: See the wrench in the shadows?
    The original works just fine, and I was using Mok's patch. Both of the versions were doing this, and I got a general protection fault when I hit 'spacebar' to play the game the first time with the 800x600 version.
    She's not a maniac, a raving thing, she just goes a little mad sometimes.
    I'm not suffering from insanity; I enjoy every minute of it.

  20. #20
    Member
    Registered: Feb 2002
    Wow, that is very odd. Especially the GPF - at that point it the game it hasn't, as far as I can tell, even hit the codepath I modified, as 320x240 isn't a VESA mode.
    The aggravating part, of course, is that even an unmodified copy will behave differently on different NT systems, we don't have the source, my efforts to feed it to windows' pathetic excuse for a debugger have failed and I can't even get a decent core file from it.
    In other words, I haven't the faintest of clues what could be going wrong and I can't figure out how to fix it. I'll see if I can get more testing data, but in the meantime, sorry, I have no ideas...if you do get another BSOD, though, could you copy down the register information from it?

  21. #21
    Member
    Registered: Nov 2003
    Location: See the wrench in the shadows?
    The GPF could easily have just been a hiccup that would've happened with the original .exe file, I've had them before. I might have time to do some testing later to see if I have a setting I need to change to get your files working properly. Obviously, if I turn up anything I'll let you know.
    She's not a maniac, a raving thing, she just goes a little mad sometimes.
    I'm not suffering from insanity; I enjoy every minute of it.

  22. #22
    Member
    Registered: Feb 2002
    Well, you need to turn on VESA/SVGA, but if you hadn't already done so the original wouldn't work at 640x480, so.
    I'll get my Shadowy Contacts to work testing it and post if anything turns up on this end, many of them run XP boxen.

  23. #23
    New Member
    Registered: May 2005
    Still can't get it working on XP, but they worked perfectly on both 98 PCs - I didn't even need to change the memory settings.

  24. #24
    Member
    Registered: Apr 2001
    Location: England
    Win98 and WinXP use memory totally differently. Win98 still has DOS running somewhere underneath it (or rather, off to the side somewhere) but WinXP is a pure Protected Mode OS.

  25. #25
    New Member
    Registered: May 2005
    I know that, it's just on one of the PCs I used usually crashes unless I change the DPMI and conventional memory settings and it didn't with the edited executable. (Because it changes the way memory's handled, right?)

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •