• Comments that describe all lines of code until a blank one are placed
into the lines immediately above
• Comments that describe an entire demarcated block are placed
immediately below the dash row at the top
• In any case, there should be a blank line after the top comment of
a demarcated block, to keep IntelliSense-style systems from applying
the block comment to the first actual line of code…
• …but there shouldn't be one before the dash row at the bottom, where
it'd be redundant.
Part of P0207, funded by GhostPhanom.
Let's see if anyone ever tries to compile this codebase with a pre-C89
compiler that enforces the # at the beginning of the line.
Part of P0203, funded by [Anonymous] and GhostRiderCog.
The single underscore version is actually slightly more supported among
the compilers I've seen so far. Also added the exact list now.
Part of P0183, funded by Yanga and [Anonymous].
Oh, so the high score name is only stored backwards for aesthetic
reasons, to make both the name and score blitting loops look identical.
Part of P0173, funded by [Anonymous].
"I don't need the return value in MAINL.EXE? Let's copy-paste the
function and remove all of its `return` statements then!" :zunpet:
Completes P0172, funded by [Anonymous] and Blue Bolt.
Featuring inline assembly for a single ROR instruction. Turbo C++ 4.0J
unfortunately only offers intrinsics for 16-bit rotations.
Part of P0172, funded by [Anonymous] and Blue Bolt.
Stupid one-off functions deserve stupid names, Part 3. This time also
coming with an unnecessary precondition.
Part of P0168, funded by Blue Bolt and rosenrose.
Including the pointless DOS I/O variation in TH05's MAIN.EXE.
I'm slowly running out of characters to remove from the first segment
name in that file, though…
Part of P0148, funded by [Anonymous].
It shouldn't need a comment to communicate that this function does in
fact not load all values from the .CFG file that are part of the
resident structure, but only loads and sets the global pointer to that
structure.
Part of P0148, funded by [Anonymous].
This gets rid of a couple of per-entity sprite bitplane types, makes
sprite declarations easier to read by putting width and height next to
each other… and points out a number of array dimension mistakes -.-
Even in places where we can't use it.
Part of P0138, funded by [Anonymous] and Blue Bolt.
Sure, we can't use them everywhere, but it's really nice to get rid of
that casting madness – and any explicit references to x86 memory
segmentation – wherever we can.
Part of P0138, funded by [Anonymous] and Blue Bolt.
Might look uglier, but has the advantage of not generating an empty
segment with the default name… *and* the default padding, which will
really come in handy with the following breakthrough.
Part of P0137, funded by [Anonymous].
eeb4e7e changed the final C translation unit that used this header to
C++, and we got some more helpful inline functions upcoming.
Part of P0136, funded by [Anonymous].
Allowing us to consistently mirror the declaration in pc98.inc
without adding a planar.inc file. 😛 And points us to two more
dots8_t* arrays that should have used the Planar<> template.
Part of P0135, funded by [Anonymous].
Reason: Pascal calling convention with function parameters but no stack
frame. Theoretically we can __emit__() everything inside this function,
but there's no way we can get a `RETN 8` this way. Oh, and it also
accesses SI and DI without backing them up to the stack.
And thanks to TLINK apparently not reporting fixup overflows when
segments are small enough (?), it took quite a while to get that CALL
correct and not weirdly offset by 32 bytes. 😕
Part of P0134, funded by [Anonymous].
DOS is not the same thing as the underlying CPU, after all. A separate
file not only indicates to future port authors which parts of the code
are x86-specific, but it also speeds up build times…
… in theory, because removing 677 lines from 49 files each doesn't seem
to speed up the build as much as I had hoped? But apparently my whole
system mysteriously got faster in the meantime, and I was getting 22-23
seconds for the entire repo even before this commit. Good enough.
Part of P0134, funded by [Anonymous].
Getting us completely macro-free there… even though it did require a
separate version of those functions if the ID is a pointer.
Part of P0134, funded by [Anonymous].
Undecompilable again. The loading functions have these *_noalpha()
variants that simply set a global variable and fall through to the
regular functions, while cdg_free() has its first `PUSH DI` instruction
after the first expression we'd be decompiling. cdg_free_all() *could*
be decompiled… but would also require _FLAGS trickery, and it's simply
not worth starting a translation unit for one such small function.
Part of P0127, funded by [Anonymous].
Nooooo, gotta throw away that decompilation for the stupidest of
reasons :( Turns out that a function may also be "undecompilable" if
the original code layout places it at a word-aligned address, but the
last byte of the previous function in just one of the original binaries
(TH03's MAIN.EXE, in this case) also lies at a word-aligned address.
There's simply no way to enforce per-function word alignment in Turbo
C++ alone. You *could* fake it with `#pragma codestring`, but of course
that won't work for functions that are part of the SHARED segment, and
where the alignment previously would have been correct. Conditionally
emitting that codestring would work, but then we'd also have to compile
that translation unit at least twice.
Now, I could have created a dummy .ASM file that just contains a single
zero-length but word-aligned SHARED segment, which could be placed
anywhere on the link command line where word alignment is needed… but
the decompilation of this function was a mess anyway, and probably
helped nobody.
Part of P0127, funded by [Anonymous].
And since inlining even removes longer if-else chains if they branch
depending on a literal constant, we can use a regular parameter to
select either MOV or OR in our _FS and _GS poke() template functions,
without needing to duplicate them!
Part of P0127, funded by [Anonymous].
Containing not one, but two decompilation innovations, one of which
works around a compiler bug using C++ template functions…
Completes P0126, funded by [Anonymous] and Blue Bolt.
Another function consisting almost entirely of inline ASM. Still worth
it though, if only to save us from duplicating any declarations in ASM
land.
Part of P0126, funded by [Anonymous] and Blue Bolt.
Wow, this is the first time we're about to call any of these from C
land in ≥TH03? Found no built-in way to just uppercase an identifier
in TASM, so apparently we have to spell out the names in both lower-
and uppercase.
So, let's go back to regular, non-macro PUBLIC / PROC / ENDP code
wherever we can – for all functions introduced in ≥TH03, and for
everything that takes no parameters. It's simply not worth the
trouble.
Part of P0114, funded by Lmocinemod.