Page 22 of 24

Re: Widescreen hack and some other fixes aka AiO Patch

Posted: Sun Nov 11, 2018 12:21 pm
by Mechanist
Interesting, we just found an odd bug.

If a giant's explosive barrel is exploded in his hand at exactly the right moment, Drakan crashes with an access violation after trying to copy slightly under 4GB of RAM.

That tells me that there's a 32-bit overflow error somewhere, since that's clearly wrong.

Said crash can be caused by either directly hitting the barrel with an arrow (very difficult/random, due to the giant's hand bspheres interfering with the collision detection on the barrel itself), or - more consistently - by causing another nearby barrel to explode, which subsequently blows up the barrel the giant is currently carrying.

It was DragonsLover who originally brought this crash to my attention; in his case it manifested in a different way (crashing when the giant was about to pick up the next barrel instead), but I was unable to replicate that particular mode of crashing.

For me it always crashes immediately when the barrel is destroyed - but only if that happens on some very specific frames.
Judging by roughly how many tries it takes to cause the crash, it appears there's an exactly 1 frame window in which the crash can happen.

I expect this to be related to the long-since-fixed crash that sometimes happened when they threw Rynn; especially since the procedure in which the crash occurs appears to show signs of earlier modifications.

The immediate cause of the crash is an access violation at (ImageBase)+161C83h, due to reading past the end of allocated memory. I'm trying to track down the root cause now.

What I've managed to establish so far is that the procedure in question is called with invalid parameters; the arithmetic overflow happens in some other calculations even before that function is called.

Re: Widescreen hack and some other fixes aka AiO Patch

Posted: Thu Dec 20, 2018 11:43 am
by UCyborg
I expect this to be related to the long-since-fixed crash that sometimes happened when they threw Rynn

Doubt it. That fix is just a workaround - zero pointer check - that prevents the crash as that function is not supposed to be called in the first place under that circumstance. By the the time it's called, game is already in inconsistent state, though just reloading the last good save doesn't have any ill effects from what I could tell. The function in question is at offset 0x342C0.

especially since the procedure in which the crash occurs appears to show signs of earlier modifications

Umm...no.

Re: Widescreen hack and some other fixes aka AiO Patch

Posted: Thu Dec 20, 2018 3:20 pm
by Mechanist
The procedure in which the actual crash happens has a whole bunch of NOPs, including multi-byte NOPs.
Although on further consideration, those are probably there because of its extensive use of jump tables?

Anyway, my idea for a "fix" was to check for invalid arguments at the point where the first call with wrong arguments happens, and skip the function call in that case.
This will probably lead to other problems because the game state is most likely also inconsistent at that point... only one way to find out, though.

Unfortunately I didn't have much time to try and work on this issue further; it's kinda low-priority at the moment, and I already feel quite drained coding-wise after having to move all the per-user installer functionality to my DLL patch code.

I did, however, fix the old-but-devastating "numbers bug" which caused game (and/or server) crashes in multiplayer when player names had certain character sequences in them.

Re: Widescreen hack and some other fixes aka AiO Patch

Posted: Thu Dec 20, 2018 7:23 pm
by UCyborg
True, an old style multi-byte NOPs (like lea ecx,[ecx)] to be precise, but not the explicit modern forms as that would result in an exception on old CPUs. It's all compiler generated code, typical appearance when switches are involved.

Can't wrap my head around how do you find assembly an easy language. It's all convulted, cryptic, non-portable; some elegant one-liners in C/C++ take a crapload of instructions in ASM etc. Modern high-level languages are pretty powerful, though there is a learning steep. Hope you're not judging setup of such toolchains based on experience with ancient Visual C++ 6.0.

C++ went through a number of revisions, making a newer compiler a hard requirement for some code to compile in the first place. And such languages are pretty much a must to get things of reasonable complexity done in reasonable time.

Java rules the smartphone land (Android). Quite a significant chunk, especially considering smartphones are embedded devices, for which the old wisdom was to code in ASM to get things done at reasonable speed. We've really come far.

C# is also significant and a must know for those who want to be hardcore programmers in life.

Re: Widescreen hack and some other fixes aka AiO Patch

Posted: Thu Dec 20, 2018 8:31 pm
by Mechanist
UCyborg wrote: Hope you're not judging setup of such toolchains based on experience with ancient Visual C++ 6.0.
Oh no, it gets far worse than that. VC6 would arguably have been an improvement over this mess...
Recently I wasted half a day trying to set up the build environment to compile a simple DLL using a Discord function library (for bots).
Failed miserably and gave up.
Also I ended up with roughly 1GB of source/library/whatever files to compile a ~100kB DLL, which is beyond ludicrous.

Unfortunately I'll need to go back to that one sometime, which gives me the heebie jeebies. I'm most certainly NOT looking forward to that...

I'd have done it the easy way and used Pascal for it, but there are no Pascal libraries for Discord... seriously?
Or I'd have used assembly instead - but I found the documentation of the Discord API to be roughly as comprehensible as the Voynich Manuscript, so forget about that, too.

UCyborg wrote: Can't wrap my head around how do you find assembly an easy language. It's all convulted, cryptic
On the contrary - it's elegant, simple and direct. And just as well, I find all the C-variants needlessly convoluted and cryptic.

Besides, I like how there's no artificial notion of a "datatype" in assembly, beyond the different operand sizes.
A number is just a number, and it can mean any number of things. (ok, I'll stop now...)

Also, it certainly helps that it was what I had started out with. In the DOS era, no less.
You know, the obligatory stuff - like playing music on floppy drives, directly accessing drive sectors, etc.

UCyborg wrote:non-portable
Irrelevant when writing patch code for Win32 binaries. Or anything that targets Win32 exclusively, for that matter.
Your AiO patch code is equally non-portable, since it makes heavy use of WINAPI calls. Of course in that case it's equally irrelevant, for the very same reason.

UCyborg wrote:Modern high-level languages are pretty powerful
Powerful for inducing feelings of rage and/or helplessness in the programmer, that's for sure.

Eg. Pascal can take its datatypes and shove them where the sun don't shine... can't even pass a NULL pointer in the form of a PChar? Seriously? That's just a simple PUSH 0 - why does it arbitrarily refuse to do that but ONLY for PChar??? (NULL pointers for other datatypes are perfectly fine - go figure!)

UCyborg wrote: some elegant one-liners in C/C++ take a crapload of instructions in ASM etc.
That's what macros and function calls are for...
FASM has a stdcall macro which is used in a similar way as function calls in high-level languages. There's much more, too...

Besides, personally I find that breaking up complex one-liners into discrete operations greatly helps code readability, and assembly lends itself naturally towards just such an approach.

Finally... assembly allows various things to be easily done which are not commonly done in other languages.
For example, many of my functions return 2 or 3 values, by using the ECX and/or EDX registers for that purpose, in addition to the usual EAX.

UCyborg wrote: C++ went through a number of revisions, making a newer compiler a hard requirement for some code to compile in the first place.
Nice, software rot. Or rather in this case, source rot?

UCyborg wrote: C# is also significant and a must know for those who want to be hardcore programmers in life.
Haha, lol. Seriously?
I think we might have quite different (and largely incompatible) definitions of what "hardcore" means...

Re: Widescreen hack and some other fixes aka AiO Patch

Posted: Fri Dec 21, 2018 3:37 am
by UCyborg
When it comes to portability, I was speaking in general.

Some game devs tried to be clever with assembly, only for their games to fail miserably several years later. Pro-Rally 2001; just freezes on newer AMD CPUs during level load time. Some guy makes a patch, faking reported CPU vendor string in one of the routines, that fixes it on some, but not all CPUs. So I find the address of the master function dealing with CPUID queries, NOP the call out, BAM, now the game finally works on my PC! Supposedly uses the queries to determine "optimal" way to measure time.

Another example, games that use privileged instructions for some reason to do who knows what, that DxWnd even has a special option for treating such cases so they don't just crash. Interstate '76 supposedly uses them to measure CPU speed. Does Windows 9x just ignore those so they act like NOPs but doesn't throw exception neither?

Well, "hardcore" was the wrong term, I meant in the terms of what is used to get things done. I mean, people use computers to get things done, not to bother with low-level details. First map for DOOM was put together with hex editor. Cool, someone figured how the map data is stored. But majority would choose to make it using specialized tools with nice GUI to work with (which became a thing later), giving them accessible way to turn their vision into a reality. Someone with understanding of low-level details doesn't necessarily have sense to make great maps. It's similar with high level languages, they happen to be the tools that work for most people these days.

Besides, I like how there's no artificial notion of a "datatype" in assembly, beyond the different operand sizes.
A number is just a number, and it can mean any number of things. (ok, I'll stop now...)

Exactly, you have to know if you'll FILD the variable or FLD it. There isn't anything special regarding primitive data types in higher level languages. JavaScript has dynamic data types (type is determined automatically) and auto variables are a thing in C++. Variable declarations in C really just specify the size and signedness, plus the special float and double, the rest are arrays and pointers.

No idea about Pascal.

Besides, personally I find that breaking up complex one-liners into discrete operations greatly helps code readability, and assembly lends itself naturally towards just such an approach.

Back when assembly coding was widespread, programs were simpler. Natural verbosity with today's software would translate to bigger maintenance nightmare (if someone put something like that together in the first place). Millions lines of assembly code, sounds fun.

For example, many of my functions return 2 or 3 values, by using the ECX and/or EDX registers for that purpose, in addition to the usual EAX.

That's what passing parameters by reference (pointers in C) is for. Compiler can optimize the call out and inline it. Even with the function call in place, there's no need to follow standard calling conventions for such functions. In object oriented languages, you can return an instance of the object with calculation results.

Re: Widescreen hack and some other fixes aka AiO Patch

Posted: Fri Dec 21, 2018 7:19 am
by Mechanist
You know, the more I work with Pascal, the more I'm inclined to just ditch it entirely in favor of assembly.

All I would really need is some more nice library functions for dealing with strings and file access, and there would be little reason to hold onto Pascal beyond that point (other than for writing GUI applications, which my patch is certainly not).

In fact, if I ever have the time to spare for it, I guess I'll be gradually moving the Pascal DLL functionality in my patch to the assembly DLL.


Also, another reason why I prefer assembly: it's super useful when I need to plop a detour right in the middle of a function!
I just replace some instructions with a JMP NEAR, then put the replaced instructions in my code, and I can take full advantage of the register environment afforded by the detour's location.
Then just jump back to the next instruction after the detour. Or even to a completely different part of the same function, if the functionality requires it.
So my detour code need not even be a "function" or "procedure" - it's not called with CALL, so why would it have to be?

UCyborg wrote: Supposedly uses the queries to determine "optimal" way to measure time.
Ha! You should have seen how detecting the CPU type looked like before the CPUID opcode was a thing...

UCyborg wrote: Someone with understanding of low-level details doesn't necessarily have sense to make great maps.
Someone with no understanding of low-level details would be equally unable to put together any working map editor in that particular case, either...

Sure, they could make a nice GUI and all, but good luck actually having it work with the data.
In fact, how would you even go about making an editor without any understanding of how the underlying data works (and is stored)???

UCyborg wrote: they happen to be the tools that work for most people these days
Let me bring up an example from another field I used to work in:
Nowadays, a computer is an indispensable tool when it comes to automotive repairs of almost any kind, because of all the onboard electronics and diagnostic stuff.
~25 years ago, the only thing a computer was useful for in a car repair workshop was for accessing the service manuals in digital form. For diagnostics, you had plenty of other tools, including the humble brain box - something that seems to see increasingly little use nowadays...
The cars were mechanically rather simple, and had very little in the way of onboard electronics - in fact in the old diesels, usually the radio/casette player was the most complex onboard electronics device!

TL;dr: times change. Whether for the better or worse, that's obviously a matter of debate.

UCyborg wrote: There isn't anything special regarding primitive data types in higher level languages.
In my last post I provided just one example of such arbitrary "specialness": in Pascal at least, any attempt to pass a null PChar results in a valid pointer to an empty string instead, which is very very different from actually passing a NULL pointer - that's impossible with the PChar type, as far as I can tell. And believe me, I have tried.
And before anyone asks why would you ever want to do such a thing - some WINAPI functions require it, so there you have it.

UCyborg wrote: JavaScript has dynamic data types (type is determined automatically) and auto variables are a thing in C++.
Ugh.
If you mean the thing where the compiler will auto-declare new variables as they appear in the code - it's very convenient alright, at least until you make the first typo in a variable name somewhere - thus auto-declaring a completely new variable where there shouldn't be one!
Then it becomes a nightmare which can be very difficult to debug, if you don't immediately realize what the hell is going on.
Been there, done that. What a mess!

UCyborg wrote: Exactly, you have to know if you'll FILD the variable or FLD it.
Ah, but it also goes the other way.
For example, Pascal invariably throws a fit if you attempt any sort of arithmetic operations on the contents of a Char variable. You have to typecast it then typecast the result back, which just makes everything messy.
Likewise, trying to compare a Char against a numerical constant is a no-go, either. And so on.

UCyborg wrote: Natural verbosity with today's software would translate to bigger maintenance nightmare
You know, there's something about seeing lines like the following one, that makes me cringe:

Code: Select all

lpData[32] ^= (-!((PBYTE)(((PDWORD_PTR)0x487A2C) + 0x30) & 2) ^ lpData[32]) & 1;
But if you consider the assembly code representation, it's immediately clear what this really does:
mov esi,4835A8h ; location of the settings data in memory
mov ebx,487A2Ch ; location of struct which holds the fullscreen state flag

cmp DWORD [ebx],0
jz .write

mov eax,[esi + 20h] ; graphical settings flags
or eax,1 ; select windowed mode

mov ebx,[ebx]
bt DWORD [ebx + 30h],1 ; 2nd least significant bit -> 1 = fullscreen mode, 0 = windowed mode
jnc .windowed

xor eax,1 ; select fullscreen mode

.windowed:
mov [esi + 20h],eax
(in this case, it could be further optimized by moving "mov ebx,[ebx]" to before the first CMP and replacing that with "test ebx,ebx" instead; that would save a few more bytes of code size)

UCyborg wrote:Millions lines of assembly code, sounds fun.
Not nearly as bad as you would think.
I'd say that those who complain about assembly like that have no idea about how to use it correctly... like trying to use a chainsaw without starting the engine first, you know, that kind of thing.

Assembly "works" in a very different way from the other (high-level) languages, so trying to use it in the same way is beyond foolish.

UCyborg wrote:That's what passing parameters by reference (pointers in C) is for. Compiler can optimize the call out and inline it. Even with the function call in place, there's no need to follow standard calling conventions for such functions. In object oriented languages, you can return an instance of the object with calculation results.
Useless overhead everywhere... Why waste time and space on temporary variables when dealing with results that usually won't be relevant more than a dozen lines after the function call is made?

When doing things "my way", it's up to me to decide if I will need these results at a later point (so storing them in a local or global variable) - or even if I will need any of those "extra" results at all!

Re: Widescreen hack and some other fixes aka AiO Patch

Posted: Fri Dec 21, 2018 8:50 pm
by UCyborg
Someone with no understanding of low-level details would be equally unable to put together any working map editor in that particular case, either...

Sure, they could make a nice GUI and all, but good luck actually having it work with the data.
In fact, how would you even go about making an editor without any understanding of how the underlying data works (and is stored)???

It was just an analogy. Nothing was said about folks with potential interest in involvement with map making. But since you brought it up, yes, it has to start with someone with understanding of level stuff. But once you're past that hurdle, many users may be inclined to use your map making software. Likewise with scripting game logic; typical game engine provides scripting capabilities either through some high-level language specific to that particular engine or a more general one. Scripting in Unity3D is done in C#. Obviously no need to know the underlying CPU.

You know, there's something about seeing lines like the following one, that makes me cringe:
...
(in this case, it could be further optimized by moving "mov ebx,[ebx]" to before the first CMP and replacing that with "test ebx,ebx" instead; that would save a few more bytes of code size)

Profiling is a thing in more serious projects to discover performance bottlenecks AFAIK. AiO Patch was made by someone without prior background in programming of any kind, except a tiny bit of beginner level C# (also read some book for dummies in C at one point), and it sort of came to fruition with extended periods of my time spent starring at the screen, figuring out OllyDbg at first, then deciphering what am I even looking at in the first place, eventually picking up subtle hints reading help on assembly commands and various documentation (OllyDbg manual, stuff on MSDN on Windows API and how executables are composed, ...).

It's a wonder something useful came out of it in the first place. :oops: Not a good source for elegant code. I guess it also depends how one writes code, generally speaking.

Nobody would notice if you optimized that bit since it's rarely executed and rather simple. It would fall in the domain of micro-optimizations. You could also drop calls to KERNEL32 functions for dealing with INIs and replace it with better implementation. Due to historic reasons, INI file is opened and closed for read/write on each call on Win32; it stayed open on Win16.

Ever read anything on quirks of CPUs that due to certain factors, a code sequence that should be faster actually executes slower?

Not nearly as bad as you would think.
I'd say that those who complain about assembly like that have no idea about how to use it correctly... like trying to use a chainsaw without starting the engine first, you know, that kind of thing.

Pretty sure someone seeing your rants on HLLs would make the same argument for them.

What about if you want x64 version of the program? You might need to fix some quirks when using a higher level language, depending on how carefully the code was written, at least for cases when program is compiled to native code. Otherwise...re-do everything in x86_64 assembly? And that's just for covering your average desktops/laptops, forget devices with CPUs with whole another instruction set.

Assembly "works" in a very different way from the other (high-level) languages, so trying to use it in the same way is beyond foolish.

Hence being reserved for specific usage scenarios where finer grained control and/or speed rather than being a first choice for general purpose programming. :) I'm not arguing for the former, which includes what you've described at the beginning of your post.

Though you also can't ignore interesting projects out there extending old games in interesting ways, eg. Multi Theft Auto that adds multiplayer capabilities to older Grand Theft Auto games. Appears to use very little assembly.

Drakan devs were also fans of C++, arguing there was no good reason to go with a bit lower level C for speed or anything else, forget anything lower level!

Things may not be optimal at places, but if it works and such languages are useful to people, more power to them!

On the somehow not directly related note, noticing some people being nostalgic for old games or anything of that sort, if you ask me, every era comes with its own problems. Surely it's a wonder what ancient software could do given the constraints of the hardware.

Examples of the bad stuff: Drakan never got proper quality assurance, operating systems were also full of holes out-of-the-box (how many fixes were released for Windows 98?), unfavorable games, music, movies existed etc. etc. One big change to note, no internet back then neither. I'd say information you find on it today can also affect person's perception.

I've seen some guy complain how it's ridiculous some graphics cards today cost $600. Depending on how much you want, there's no reason to even consider a card in such price range. You get a whole lot more for the same money today on the hardware front.

Indeed, at some point, artificial constraints became a thing in software, limiting functionality for either security reasons or your average user today demanding less from it than an average guy from earlier times or due to pure greed. I find the thing with removing functionality for the sake of less demanding user strange since it won't affect the person if it's just sitting there. But geeks may still appreciate it.

Then I've read a forum post somewhere about a security update for some printer. What it apparently did was make the printer software refuse to accept non-original catridges!

Useless overhead everywhere... Why waste time and space on temporary variables when dealing with results that usually won't be relevant more than a dozen lines after the function call is made?

With compiler optimizations thing, I tried to hint that what you've written in C could have translated to the assembly code you've proposed, with ECX and EDX registers being used to return 2 additional values without any actual pointers involved, even though it was expressed that that way in C. There's no doubt there's always room for improvement.

Re: Widescreen hack and some other fixes aka AiO Patch

Posted: Fri Dec 21, 2018 9:19 pm
by Mechanist
In other news - I'm currently fixing the Level Editor... again... this time, it's the bug that causes 2D bounding boxes to be drawn with the wrong size when the objects are rotated around the X and/or Z axes.

UCyborg wrote:It would fall in the domain of micro-optimizations.
Yes. I was thinking of it rather in terms of being more elegant and readable.

UCyborg wrote: You could also drop calls to KERNEL32 functions for dealing with INIs and replace it with better implementation.
What for? The WINAPI functions work perfectly fine for this purpose; no point in reinventing the wheel.

Dege tried to roll his own INI parser and it's an arguably even worse implementation than those WINAPI functions...

UCyborg wrote: Ever read anything on quirks of CPUs that due to certain factors, a code sequence that should be faster actually executes slower?
Yeah.
Also for example, the REP MOVS opcode is not always the fastest way to copy blocks of memory (as opposed to a highly optimized tight loop), due to CPU microcode considerations.

UCyborg wrote: Pretty sure someone seeing your rants on HLLs would make the same argument for them.
But I think we can agree that it makes perfect sense to use a low-level language to create low-level patches?

UCyborg wrote: Drakan devs were also fans of C++, arguing there was no good reason to go with a bit lower level C for speed or anything else, forget anything lower level!
The point is thoroughly moot anyway, what with making individual draw calls for every single polygon, and other such nonsense.
That's such a performance disaster right there, that the (lack of) other optimization becomes completely irrelevant.

UCyborg wrote:What about if you want x64 version of the program?
What if I don't want a 64-bit version? Or to target any other platform than Win32?

Re: Widescreen hack and some other fixes aka AiO Patch

Posted: Sat Dec 22, 2018 12:45 am
by UCyborg
Yes. I was thinking of it rather in terms of being more elegant and readable.

Oh.

What for? The WINAPI functions work perfectly fine for this purpose; no point in reinventing the wheel.

True. Just saw someone needing to deal with much larger INIs where performance bottleneck was apparent due to opening and closing the file all the time instead of keeping it open until it was no longer needed. So he wrote his own and published its code.

Also for example, the REP MOVS opcode is not always the fastest way to copy blocks of memory (as opposed to a highly optimized tight loop), due to CPU microcode considerations.

Good one, I remember reading about it. Or the LOOP opcode often being slower than DEC ECX; JNZ combo.

But I think we can agree that it makes perfect sense to use a low-level language to create low-level patches?

Yes.

The point is thoroughly moot anyway, what with making individual draw calls for every single polygon, and other such nonsense.
That's such a performance disaster right there, that the (lack of) other optimization becomes completely irrelevant.

The article mentions object-oriented design. Optimization is a separate topic I think. Things could always be worse.

What if I don't want a 64-bit version? Or to target any other platform than Win32?

You're free to choose the best option that suits your needs.

Re: Widescreen hack and some other fixes aka AiO Patch

Posted: Sat Dec 22, 2018 7:29 am
by Mechanist
UCyborg wrote:Things could always be worse.
Yes, things are never so bad that they couldn't get even worse.


The Editor bug I mentioned in the last post is not really a bug as such; just an example of staggeringly poor coding.

The function which calculates how the bounding box should appear in the top-down view only takes the Y-axis rotation (and only the X and Z-axis scale factors) into account.
So if you have a model which is large but thin, and turn it on its side, the bounding box shown is completely wrong.

I've already figured out which fields have which meaning; now I just need to figure out some fancy math to calculate the result I want.

Re: Widescreen hack and some other fixes aka AiO Patch

Posted: Thu Dec 27, 2018 10:52 pm
by UCyborg
A minor update has been released; audio device enumeration is now skipped when starting dedicated server.

Re: Widescreen hack and some other fixes aka AiO Patch

Posted: Fri Dec 28, 2018 3:31 am
by Mechanist
Ok, nice. But skipping audio enum helps... with what, exactly?

Audio devices do not appear to be needed anyway (since you can disable audio in the options), and in any case an audio device of some sort can be reasonably expected to be present on mostly any x86-compatible computer hardware nowadays.

Now the much bigger issue here is VIDEO enum... I already made a null renderer to deal with that problem, but the issue remains that disabling video makes the console unusable, so text I/O needs to be redirected to an external console.

I have that planned in the works, but it's a low-priority thing at this time.

The next version of the Community Patch will bring a lot of changes with it, including several improvements to the level editor, as well as a system for allowing using custom inventory icons and "paper maps" in player-created levels.

Re: Widescreen hack and some other fixes aka AiO Patch

Posted: Fri Dec 28, 2018 8:33 am
by UCyborg
Oops, I don't know what the heck happened, but I was having problems with OllyDbg. When I was moving the code around, OllyDbg changed one of the bytes in the saved file. I thought it was a temporary glitch, so double checked the code in code section and saved again, only to realize this morning I released the broken Drakan.exe!

So opening broken Drakan.exe and patching that one byte made it save properly...but saving the entire block before made that one byte come out wrong.

Anyway, it's just that kind of thing that would be done if more thought was put into the server. I'd also use LoadLibrary to load dsound.dll instead of implicitly linking it in if I was writing that thing.

If you have a slower DirectSound wrapper in the game folder, skipping enumeration noticeably reduces startup time. It's redundant either way since audio is not needed for dedicated server, initialiazation of DirectSound interface is already skipped out-of-the-box, but the audio devices were still enumerated. I also remember seeing some errors in the console related to DirectMusic when running dedicated server on the ancient Windows NT4. The only purpose of enumeration code is to allow user select specific device in Riot Engine Options dialog. Until this year, it was practically useless since the game always picked the primary device regardless of what was selected there.

Audio devices do not appear to be needed anyway (since you can disable audio in the options)

One minor quirk here; you can't disable audio through GUI if no audio devices are found. The only difference is that the audio init function will quit earlier if audio is disabled, before calling DirectSoundCreate, which would fail in such case.

Re: Widescreen hack and some other fixes aka AiO Patch

Posted: Fri Dec 28, 2018 2:41 pm
by Mechanist
UCyborg wrote: One minor quirk here; you can't disable audio through GUI if no audio devices are found.
Irrelevant starting with next CP release, since all the settings are now in a per-user INI file (in human-readable format) and not in the registry.

UCyborg wrote:Anyway, it's just that kind of thing that would be done if more thought was put into the server.
Then maybe it would have been smartest for the devs not to make it require a 3D-capable display device despite not using any 3D rendering calls whatsoever, except for device enum (verified)...

Also I don't know what the hell is going on there, but using the NULL renderer results in a massive performance improvement. Even though it only uses Blt(), which is supposed to be fast?