/
cpp-branch-changes.txt
529 lines (407 loc) · 25.7 KB
/
cpp-branch-changes.txt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
===============================================================================
This log contains a summary of changes performed in the cpp-branch to
transition Eternity from C to C++. cpp-branch spans SVN revisions from 1344 to
1408.
===============================================================================
-------------------------------------------------------------------------------
01/08/11
Changes in preparation for v3.40.00 release:
I cleaned up the weird and unnecessary cast back to memblock_t when preparing
allocated memory for return from Z_Malloc, as I don't like it referring to
the block's memory as if though it were a memblock_t.
With essel's assistance we have enabled portal overlay specification through
ExtraData sector records; however, I guess SoM didn't test it enough and the
portal overlay system malfunctions severely once there is more than one
distinct overlay in visibility - only the highest numbered sector's overlay
seems to function correctly according to essel. This will be live in the new
release, but nobody's going to get much use out of it until one of us can
figure out what is really going on. Since I didn't write the code, I am at a
disadvantage with figuring it out personally.
I disabled the code that tries to adjust the upper clipping boundary for the
renderer to the bottom of the console to avoid overdraw, because it isn't
working in widescreen aspect ratios for some reason. This may not be worth
fixing in the long run.
CSonicGo found an old glitch dating all the way back to SMMU - if netdemos
were started with -playdemo or the playdemo console command, then EE would
remain in netgame mode after the demo stopped and would crash at some point
later, seemingly arbitrarily, by attempting to execute the netget function
pointer in the low-level netcode with the pointer still set to NULL.
This was fixed by refactoring G_CheckDemoStatus so that it always properly
frees the demo buffer, unsets netgame, and calls G_ReloadDefaults, even if the
game engine is in "singledemo" mode, as it is when using playdemo.
Copyright dates and version info have been updated for the impending release.
cpp-branch is ready for merger back into trunk.
-------------------------------------------------------------------------------
01/03/11
My beta testers found a crash - if you used the addfile command, the program
would segv the next time a sound tried to play. My recent changes to the sound
engine made the code to stop channels in i_sdlsound.cpp capable of trying to
free the channel more than once. This was ending up with a call to Z_ChangeTag
with a NULL parameter.
Besides fixing the sound engine flaw itself, I also added a NULL pointer check
to Z_ChangeTag.
-------------------------------------------------------------------------------
01/02/11
QStrCat was *STILL* exhibiting broken behavior, this time as a consequence of
using the sum of the lengths calculated at the beginning to reset the qstr's
index. Instead, I have replaced all instances of this being done with calls to
strlen(), which, while maybe slower, has its head on straight with respect to
0-vs-1-based numbers in a way I cannot seem to reliably manage. It's far
better to cut myself out of the loop with this and rely on something I know to
be correct for the future.
I've begun to understand why writing your own string library can be painful ;)
-------------------------------------------------------------------------------
01/01/11
Happy New Years!
While working on some features for the next upcoming 10th anniversary release,
I ran headlong into a bizarre and hard-to-crack heap corruption issue.
Turned out my strcat and insert methods in the qstring module were
miscalculating the amount of needed space by ONE character and this was
suddenly, after YEARS of proper functioning, causing a problem. Man I hate when
that happens :P
Took me 3 solid hours of heavy debugging to figure out precisely what was going
on, but now I've learned some very handy techniques for debugging using the
MSVC++ debug heap that will significantly shorten the time in the future if
this should happen again.
I made the S_ISDIR macro actually use the parameter it was being sent, and not
assume that the stat structure it's being used on is named sbuf. This was only
working because they WERE all named that, by virtue of copypasta.
I also added a QStrNormalizeSlashes method, since M_NormalizeSlashes cannot
be safely called directly on a qstring's buffer pointer - this would leave the
strlen inconsistent with the insertion index, causing improper reallocation
and concatenation behavior - in the event that duplicate slashes were
removed from the string.
-game and -iwad may now be used with simple IWAD names (ex: doom.wad) and if
the proper IWAD paths are configured in system.cfg, Eternity will select the
best matching IWAD.
For example, if I have configured IWAD paths for DOOM Registered and Ultimate
DOOM, and start Eternity using only -iwad doom.wad with no doom.wad file in
immediate visibility to the program (ie. in "." or in the exe directory),
Eternity will select the Ultimate DOOM configured IWAD automatically, because
it is the "best" version for the game.
In addition to this, Eternity also now supports the DOOMWADPATH environment
variable, and will find IWADs on that path as well if no paths are
configured or available in system.cfg first.
-------------------------------------------------------------------------------
12/30/10
Fixes galore:
1. Sound engine fix for a problem inherited from trunk -- channel data pointers
can and should be cleared as soon as the audio update thread is finished
with them. This eliminates the extra loop in I_StartSound entirely and
keeps sound channels freed up.
2. Some (Mobj *) casts in Lee's friendly monsters code in p_enemy were no
longer technically correct or safe, and have been replaced with proper
dynamic_cast calls.
3. Unnecessary and dangerous casts of PointThinker pointers to Mobj * and then
immediately back to PointThinker * have been entirely eliminated - I
thought I got all of these previously but some slipped through the cracks
due to using slightly different idioms. They're probably actually safe since
the pointers are never dererenced between all that casting, but it's far
better not to tempt the hoary bearded gods of C++.
4. __attribute__((packed)) should not be used in C++, as it is allegedly
syntactically incompatible with C++, though GCC had yet to actually issue
a single complaint about its presence. All instances have been replaced by
changing the #ifdef _MSC_VER previously used to control all usage of the
#pragma pack(push, 1) and #pragma pack(pop) directives to use:
#if defined(_MSC_VER) || defined(__GNUC___)
- Since GCC has supported #pragma pack for quite a while now, this is by
far the most preferable solution.
-------------------------------------------------------------------------------
12/29/10
Added a "Buddha," or immortality mode, similar to the one in ZDoom, since
essel requested it a while back with the justification that it is beneficial to
testing of maps for gameplay balance purposes, as one can tell at what point a
player of equal skill might start to run low on health, without being in
jeopardy of actually dying and then having to return to full health via the
resurrect command to continue playtesting.
-------------------------------------------------------------------------------
12/28/10
Demo compatibility fixes courtesy of Doomworld Forums user 4mer:
* All subroutines which were split out of PIT_CheckThing for reuse in the 3D
object clipping module MUST use clip.thing directly and not accept it as a
function parameter, due to the potential for (undefined) reentrant calls to
take place which overwrite members of the global clip struct.
The non-reentrancy of DOOM's clipper is well-known to me, as I have struggled
with it before. However, the fact that just changing some lines of code into
a subroutine and passing a value to them through a parameter can break demo
sync is insideous and has serious implications. Further changes to this code
in the future MUST take note of this and be cautious to the point of
paranoia.
This included the routines P_SkullHit, P_Touch, and others. P_SkullHit was
in fact the cause for the desync in the Speed of Doom TAS demo earlier
mentioned, with the failed Arch-vile jump. Several Lost Souls (the greatest
nightmare for demo sync ever) were in the area, and one or more of them were
suffering reentrant clipping behavior.
* mlook math must not be applied during playback of non-Eternity demos. I am
entirely unsure of how I overlooked this, as a similar issue was repaired in
the renderer years ago which was causing the entire screen to be slightly off
the horizontal when at player->pitch == 0 (an extra pixel of sky at the top
was the only reliable indicator of this, and is how it was caught in the
first place).
This roundoff error was apparently so small that it somehow virtually never
caused demo desyncs. However, we're not going to tolerate such obvious
problems when we can avoid them quite easily ;)
* Some code earlier adapted from PrBoom-Plus while fixing Okuplok's SOD MAP33
demo had been deliberately changed to use rigorous, correct handling of
mobj reference counts via calls to P_SetTarget, but according to 4mer this
does disturb demo sync. Since this code is ONLY called during 200-202 demo
playback, and because it seems to maintain a reference count balance that is
in favor of an object NOT being freed even when it could be, it should be
reasonably safe to allow it to slide here.
In NO OTHER code in the engine should mobj references be directly assigned!
Reference counting is an absolute necessity.
* The same-subsector short-circuiting optimization from MBF when checking lines
of sight, which has been a source of demo compatibility problems in the past
already, should *NOT* be applied during 200 - 202 demo playback. cph's prior
fix adapted from an early PrBoom revision only addressed not applying this
code during v1.9 demo playback.
I guess he failed to realize this change was from MBF and not BOOM, but the
"killough 11/98" comment above it is a dead giveaway, as Lee was quite busy
on MBF at the time, as I clearly remember from my own personal experiences
as a beta tester on MBF. I had just started college 2 and a half months
earlier, so that time is quite vivid in my mind.
Eternity itself was still in diapers back then ;) A barely-evolved-past-
DeHackEd hack of BOOM which contained an Imp that fired modified Arachnotron
plasma that left blur trails.
Quite a way we've come since then, eh?
-------------------------------------------------------------------------------
12/27/10
I accidentally lost the code to restore Cardboard floor and ceiling heights
when loading savegames which was causing a really weird infinite horizon
glitch to appear on any sector which had been saved with an altered floor or
ceiling height after reloading the save. Thinker and soundtarget pointers in
sectors were also not being nullified, which although unlikely, probably
could have lead to some interesting problems.
GCC fixes:
* InBuffer::Read had a type conflict between its declaration and definition.
* class Mobj needs declaration in a_small.h even if EE_NO_SMALL_SUPPORT is
defined.
* void *'s need to be cast through size_t as an interim solution for the %p
formatting code in psnprintf, although a more ideal solution is of course
to add proper support for 64-bit pointers. That is a TODO, however.
* All extern declarations of FloatBobOffsets need to be consistent.
* SMMU keybinding code needed proper constness constraints.
* EE_NO_SMALL_SUPPORT has to be #ifndef'd in amx.cpp and amx_core.cpp.
* A goto in f_finale.cpp crossed the declaration of a variable, which isn't
allowed in C++ (except if you're Microsoft).
* Netcode functions also have to cast offsets through size_t, as GCC assumes
through lack of information that these values could be 64-bit precision
(they never are in this case, however).
* libConfuse can longer "cram" defaults for all types of fields into its single
void *def field in cfg_opt_t -- instead I had to rewrite the library to use
a separate default field for each type of cfg_opt_t. Not ideal, and could
probably benefit from object orientation later on.
* DavidPH provided a CMakeLists patch which got this whole thing compiling
again. Super-special thanks to him for his help and patience.
-------------------------------------------------------------------------------
12/26/10
With completion of thinker serialization and a rewrite of the rest of the
savegame module, r1369 has become the first compiling revision of Eternity
under C++!
I have also decided to drop the C prefix from all Eternity class names, as I
hadn't applied it universally and it was really starting to wear thin already.
Leave that crap to Microsoft :P
-------------------------------------------------------------------------------
12/25/10
Ho-ho-hoooo, Merrrrrry Christmas!
Serialization methods have been finished for all CThinker descendants except
for CACSThinker, which is quite complicated, and mobj_t, which is the MOST
complicated of all.
-------------------------------------------------------------------------------
12/24/10
Work continues on the process of thinker deserialization. I have, as discussed
previously, moved the enumeration facility back into CThinker and up out of
mobj_t, since other thinker types may need access to it in the future and I
want to code this in as generic a manner as possible.
The mobj_p table used to track mobj pointers for indices during savegame
loading has been refactored into thinker_p so that it works on all descendants
as necessary.
A virtual deswizzle method has been added to CThinker so that pointer fixups
can be done in a separate second pass, which is necessary since ALL thinkers
must be instantiated before references to them can be restored (a lesson I
learned quite well from the mess in Strife's savegame code ;)
-------------------------------------------------------------------------------
12/23/10
Merged in a demo compatibility fix from trunk, at great inconvenience. It's
going to be necessary to avoid any further code changes to trunk, since SVN
cannot properly merge renamed files.
-------------------------------------------------------------------------------
12/18/10
The thinker factory system for manufacturing new thinker descendant instances
during savegame loading is now complete.
A CThinkerType base class maintains a static-global list head pointer to which
all derived classes add a singleton instance at startup (order is unimportant).
When the savegame code wants to unarchive a thinker, it will first read the
archived class name (which is archived by CThinker::serialize when in write
mode using the virtual getClassName() method), and it will then call the
static FindType method of CThinkerType.
This method will return a CThinkerType descendant object specialized to
construct the same type of Thinker descendant which it names. Because all
thinker type classes are essentially the same except for the name and the
constructor they call (which are equal except one being a compile-time type
and the other being a string literal), CThinkerType specializations are all
defined using a macro, IMPLEMENT_THINKER_TYPE.
This macro should and must be used once per thinker descendant. I am planning
to place these macro definitions near the classes' Think method.
-------------------------------------------------------------------------------
12/16/10
Metatables are now zone allocatable, but a global solution for this which can
be applied to any object is desperately needed before any widespread conversion
of Eternity to C++ beyond the mere basics is undertaken.
I restored the key and type parameters to the getNext* methods of MetaTable,
as it turns out these were needed for something after all - they can in fact
be NULL when starting a new search using these methods, in which case trying
to get the key and type out of the object parameter itself would have caused
quite the ugly access violation.
I renamed copyTable to copyTableTo, and added a matching convenience method
copyTableFrom, so that the directionality of MetaTable copy operations is both
more optional, and bidirectional with minimal trouble.
I am now refactoring all the MetaTable client code, which includes some
significant portions of EDF. With this complete, we'll be back to only
savegame-related errors.
-------------------------------------------------------------------------------
12/15/10
Yet more unnecessary #includes inside headers have been removed. These weren't
causing any problem other than cluttering up the source code and slowing down
compiles, but this is still a good improvement.
I have begun to resolve the nightmare of a situation that is r_defs.h, first
by splitting off a new header r_lighting.h which contains all #defines,
typedefs, and structures related to lighttable_t and light fading. These were
a particular problem, one which had earlier been hacked at grotesquely by
conditionally duplicating the definitions between multiple header files and
disabling duplicates by surrounding them inside their own #ifndef guards.
Terrible!
I changed all the Emacs mode selects *back* to C++, so that automated language
detectors on services like ohloh will detect Eternity's change to C++ properly
even if they pay too much attention to such indicators.
-------------------------------------------------------------------------------
12/13/10
Rewrote the critial MetaAPI. MetaObject is now the polymorphic base class for
all descendant object types, and hashing and the management of MetaObject
specializations for basic types such as int, double, and string have been
retained in the MetaTable class.
The MetaTable class's dual EHashTable structures have been moved into a
"pimpl," or private implementation object, in order to isolate the rest of the
metatable-using code from EHashTable, which is a relatively expensive-to-
include template.
Metatypes no longer exist at all, their functionality having been usurped
entirely by the built-in virtual function calls of C++. Metaobject RTTI *has*
been retained however, since C++'s language RTTI mechanism is not portable
with respect to class names, and these may prove critical later on when Aeon
scripting is designed to interact with metatables.
The CopyTable method of MetaTable has been reimplemented in terms of a rather
standard C++ cloning idiom, whereby a virtual clone() method in MetaObject
acts as a virtual constructor. All MetaObject instances are required to
override clone() and return an instance of their own type by calling their
own copy constructor on *this.
Note that covariant return types have NOT been used, to avoid problems with
compilers that don't support them properly.
-------------------------------------------------------------------------------
12/12/10
Finished rewrite of the ehash_t structure into EHashTable, which is a template
class which uses pointers to members so that it can hash types using any
predetermined key field and set of CDLListItem list links, *without* imposing
any sort of inheritance requirements onto the objects it supports, making it a
pure container type.
-------------------------------------------------------------------------------
12/10/10
As part of the continuing effort to replace all type punning with proper
inheritance, and because I may or may not need this code for supporting
thinker serialization, I have turned to work on the m_dllist, e_hash, and
metaapi modules.
mdllistitem_t has been converted into a POD template class called
CDLListItem<T>. remove and insert methods are supported on the link type, and
list head pointers should now be of type CDLListItem<T> * rather than of the
base type (this was a serious problem with the original design anyway, as it
required weird punning of a pointer-to-pointer that always felt sinful).
-------------------------------------------------------------------------------
12/08/10
I've continued with significant work on the buffered IO classes and the
rewrite of the savegame code, which is the primary remaining obstacle to
compilation. Thinker serialization support is underway, but is unfinished.
-------------------------------------------------------------------------------
11/27/10
I have added a virtual enumeration mechanism to CThinker and an implementation
of it in mobj_t to support twizzling of mutual reference pointers in savegames
in a more encapsulated manner. Needs refinement - I may end up moving it back
up the hierarchy into the thinker class, but time will tell.
I realized I needed to check against "removed" status for all thinkers when
downcasting them to specific types in loops (such as loops that only run on all
valid mobj_t's) because under the old system, a thinker was no longer
considered to be of the same type any longer once its thinker.function member
had been changed to P_RemoveThinkerDeferred. Since Think is now a virtual
method, it is unfortunately static at runtime and cannot be used for RTTI. To
remedy this, I have created a thinker_cast<> template function which tests for
removed status before performing a dynamic_cast. This removes any necessity to
test for removed status all over the code, something definitely to be avoided
at all costs, as forgetting to do it would be a costly mistake indeed.
-------------------------------------------------------------------------------
11/26/10
More #include cleanup has become necessary, but it should hopefully be finished
for the time being.
The buffered output functionality in m_buffer.cpp has been converted to a C++
class, which I hope to rederive from a generic class and then create a read
version of the code to support buffered streaming of savegame data.
(Later):
Added CBufferedFileBase, rederived COutBuffer, and added CInBuffer. EE now
has object-oriented buffered file IO facilities.
-------------------------------------------------------------------------------
11/22/10
Attempting to make changes to degenmobj_t to change it into a PointThinker
base class from which Mobj and QuakeThinker can inherit has caused the entire
codebase to suffer a circular include dependency hell problem that I have
been predicting and fully expecting to occur for a couple of years now.
The chief problem is that headers are including other headers, and then modules
are relying on this in such a fashion that they're not properly including all
of their dependencies independently. This was partially to blame on C's
somewhat lacking abilities for foward type declarations, but also upon
conscious decisions made by both id and especially, later, the BOOM team.
Chief amongst offenders, and key in fact to the current meltdown, is the
header r_defs.h - this massive conglomerate of unrelated structure types is an
absolute nightmare which is either directly or indirectly included into
virtually every single source module in Eternity - and it itself includes
several other headers which, if followed in a tree-like fashion, end up
including most of the code in the engine. This means that any modification
ends up recompiling the entire codebase, and any change - such as innocently
moving degenmobj_t to p_mobj.h - causes a nuclear meltdown.
I have spent significant time to resolve this, chiefly by removing inclusion of
headers within other headers wherever C++ allows this to be avoided simply by
including forward declarations of types that are referenced only by pointer,
for example:
class mobj_t;
struct line_t;
struct sector_t;
These three lines can take the place of 8000 lines of header-included code.
With this resolved, work has continued on conversion of thinker_t's extended
family of structs into a proper virtual class hierarchy. P_InitThinkers has
become a static method of CThinker, and P_RemoveThinker has become a virtual
Remove method.
CPointThinkers contained in sectors, lines, and polyobjects will need to be
temporarily constructed using placement-new, to guarantee that they contain
valid vtable pointers and avoid possible undefined behavior with dynamic_cast
which will be employed in the sound code when testing for sound origins that
are really mobj_t's. If lines/sectors ever become non-POD types, then this
will not be necessary any longer, as they could then call the CPointThinker
constructor on their sound origin items directly.
-------------------------------------------------------------------------------
11/20/10
As noted in trunk, cpp-branch has been split off from trunk at r1344 to begin
work on conversion of Eternity's codebase into the C++ language, so that we
can retain our object-oriented designs without resort to ridiculous constructs
such as unions of multiple structures, which seem to be the best suggestion
from the neckbeards who wrote the C99 standard without regard to the Petabytes
of perfectly valid C code they were backhandedly deprecating.
The process is already well underway with the following series of changes:
* All files have been renamed to .cpp, excepting fraggle's textlib code which
will remain C (with likely need to add extern "C" blocks to its headers).
* VC2008 project has been updated to link to the cpp files.
* Elimination of all errors, including incorrect C++ usage of bool, pointer
casts, and enum types, excepting error C2440, "no conversion from
'void (__cdecl *)(mobj_t *)' to 'think_t'" -- it is obvious that the thinker
type punning system cannot be transitioned into C++, at least not in a clean
manner, and thus as I had previously planned, transitioning thinkers into a
virtual class hierarchy will be a fundamental part of the basic transition
process.
===============================================================================
EOF
===============================================================================