Подробное повествование на FreePascal.ru
My misadventures with Raspberry Pi 2 @ OpenArena board
(2014) обсуждение DRR на GameDev.ru
January 2023
Began a great cleanup and restructurization of the code base. The Kakan code is still incomplete.
August 2022
Decided to completely redo the rendering architecture, and also the asset management. Enter Kakan, an abstraction layer over GLES2 inspired by Vulkan.
March 2021
Switched from LGPL v2.1+ to MPL 2.0.
October 2020
Decided to drop a lot of things forever: fpc 2.6.4 support, Win98 support, developer mode on platforms other than Win32. I'm growing too old, there are more and more silver hairs in my beard. I should concentrate on the reachable goals while I still have time left.
September 2020
I have participated in the annual GUI contest at GameDev.ru. I advice against looking into my entry there, though: too unstable, too many things are still a total mess.
March 2020
Tons of refactoring and code cleaning in the engine itself. Successful adaptation to fpc 3.2. Some work on restoring Win98 support. Some work on completing the grand structural rehaul (not done yet).
February 2020
Core GUI classes finished.
January 19, 2020
The Grand Rehaul of my persistency system is finally over. The engine compiles and runs without crashing.
September 2018
Added virtual screen resolution clamped to 1280x720..1280x960. Window aspect outside of 4:3..16:9 result in pillar/letterboxing.
September 2018
Achieved Platinum level of Wine compatibility as my Unicode patch also hacks around the FPC bug #27221.
September 2018
Perfected the Unicode patch for fpc 2.6.4 & 3.0, the Windows versions are now able tu run from folders with names not representable in system 8-bit code page. The fpc dev team *partially* fixed the problem it in 3.0 but classes are still *not* Unicode. Don't remind me of lazutf8, I'm designing my engine as fully Lazarus-independent. True Jedi do not seek easy paths.
September 2018
Rehauled text rendering, uses a single monospace bitmapped font for now. Most importantly, the mechanism is not split anymore, everything is at the module's side. Mother only provides the default texture.
July 2018
Perfected the window manager for Win32. A tad incorrect architecture
was chosen, the main thread freezing during window resize. I restructured
my code so that heartbeat pulse could work from WM_PAINT in my window function.
Sigh. This part of WinAPI is a mess.
Many thanks to MrShoor from GameDev.ru boards, see this thread
04.10.2017
Unicode migration in progress. I'm glad to announce that Chentrah will support Unicode paths no matter which compiler is used. Yes, even 2.6.4.
I had to rip lots of stuff from 3.0.2 RTL including FindFirst, ChangeFileExt and even paramStr. Thankfully, all is left is to debug my new hack weeding out all bugs. Hilariously, it works beter with 2.6.4 now that id does with 3.0.2.
12.06.2017
Today, for the first time in the history of mankind, the Raspberry Pi 2 version of Chentrah started up and did not crash.
The hardware surface overlaps all windows, including the mouse pointer. You can see background through halos around the text (reminder to self: find how to disable blending). Unfortunately, some shit driver spams console with "glGetError 0x500" slowing everything to a crawl, so I can't tell what FPS really are.
You can only make screenshots using a physical camera as the hardware surface doesn't show on screenshots.
11.06.2017
Voodoo coding at its finest
I spent at least a week wall-banging why my GLES2 renderer wasn't working. The shaders compliled, the uniforms and attributes passed properly, not a single error... and an empty black screen. I was re-checking my code for rendering copy-ported from C examples. I was re-checking my vector and matrix math operators. I was banging my head against nearest wall. And then, out of pure desperation, I corrected one line in my vertex shader,
gl_Position = u_matrix * vec4(a_position[0], a_position[1], a_position[2], 0);
to
gl_Position = u_matrix * vec4(a_position[0], a_position[1], a_position[2], 1.0);.
Lo and behold, it started wrking at once!
Huh, who coulda thought that that extra component was so important...
Yes, I know my projective geometry that well.
17.12.2016
Public test #20 (download, 11Mb). Mouse capture, screenshots, lots of code refactoring under the hood. Press "2" to capture the mouse (does not work in the main menu). Press "F3" to make a screenshot.More in Russisn...
02.09.2015
Public test #19 (download, 6.2Mb). Multi-threaded structure, thread synchronization, physics in a separate thread, TONS of code refactoring under the hood. The first test to include the sources. The keys 1..3 select logic synchronization method, 4..0 set logic tick length (achieved using Sleep()) F5 - create restore point, F9 - roll the session back. More in Russisn...
11.01.2014
Public test #16 (download, 2.3Mb). Render to texture, automatic graphics quality control, adaptive supersampling using pixel shader for better smoothing
10.11.2013
Unexpected glitches during testing in 32-bit Wine in 64-bit Debian 7.2 wheezy. One was eventually written off as a glitch of sshfs/fuse, but the second one was more serious. The application was locking up on exit, with Wine logging in an endless cycle:
err:ntdll:RtlpWaitForCriticalSection section 0x1d4148 "?" wait timed out in thread 0009, blocked by 3d3d3d3d, retrying (60 sec)
My code was using bare TRTLCriticalSection, I changed it to use TCriticalSection wrapper class from syncobjs unit. That solved the problem and I could observe 20 FPS on a free implementation of OpenGL 2
06.01.2010
The exception handling problem in Win32 is utterly defeated! Using the sources of the System unit, I wrote a simple hack that extends the exception catching to the module DLL making any wrappers unnecessary. It's really simple. Install your own exception handler where you check if exception address belongs to your DLL and just jump to the proc in the DLL that raises a language exception. Otherwise just call the old handler..It's simple!
26.12.2008
I did a horrible, perverted thing with my spare computer... But I now know that Chentrah does work in a vanilla, freshly-installed Windows 98 SE (installing it brought back so much memories... Ahh, nostalgic ). The only upgrade I applied was the nVidia display driver (guess what? There is OpenGL 2.0 support for the ole Win98!)
18.08.2008
I upgraded FreePascal for Linux from 2.2.0 to 2.2.2. The size of the game module DLL dropped from 1800 to 700 Kilobytes, which is good news. The mother module, on the other hand, stopped linking. Turns out, there was a problem with Vampyre Imaging library. Or, more precisely, with the OpenJpeg library it uses. The formerly working {$linklib stdc++} didn't work any more, and the errors hinted that my executable doesn't have some additional c libraries linked in. I guess that's why executable size dropped so: prior, fpc used c libraries. Now it doesn't.
I remade the corresponding Vampyre unit for dynamic linking to libopenjpeg.so but surprisingly, that didn't work either. After some googling and additional researching I found that the .so expected my executable to have the c libraries it needed! I resolved this by dynamically loading libstdc++ with the magic RTLD_GLOBAL flag, like this:
dll2:= dlopen(PChar('libstdc++.so.5'), RTLD_NOW or RTLD_GLOBAL);
dll := dlopen(PChar('libopenjpeg.so'), RTLD_NOW or RTLD_GLOBAL);
And that magic RTLD_GLOBAL makes the DLLS search for missing dependencies in each other.
28.07.2008
I tested it under user with name "山田" (Yamada) made of characters not representable in the system 8-bit encoding (CP 1251 in my case). Chentrah properly reported invalid user name and inacessibility of the user's home folder in "documents and settings" (the path had question marks in it). What is really strange, the user name also appeared to be "??" despite the fact that I use GetUserNameW(). Wonders of WinAPI?
27.07.2008
Another perversion. The win32 version can detect when it runs in Wine and exploit the fact that Wine by default maps the filesystem root as drive Z:\ - so Chentrah tries to store its user data and settings data the Linux way: /home/<username>/.chentrah
23.07.2008
The FreePascal bug #4605 (exceptions in DLLs are not caught) was making the very architecture of Chentrah unusable because any exception in the game module would shot straight through to the mother module. And then the program could only kill itself by throwing itself at the wall: such goodies as auto-saving in case of render crash were simply not possible.
Waiting for a fix is no use: the bug hangs there in the bugtracker since year 2003. The exception handling in Windows is undocumented, all compiler developers (for Borland, I know for sure) had to reverse-engineer it to provide support for it.
But me, I have found a roundabout trick mitigating the worst of this problem. Instead of useles try...except blocks I employ a wrapper procedure of the mother module. The game module passes it its own routine which the wrapper calls enclosing it in a try...except block of its own and thus catching any exception in it. Ugly? Yes. Totally perverted? Yes. But it works.
10.05.2008
I tried to implement the custom mouse pointer support (with ability lo load any image). Well, drawing it using OpenGL is easy. Switching off the hardware system pointer is entirely different matter (And no, I know about ShowCursor(false) but that works for entire screen. I needed something for my window only, something that would not affect another applications)
In the end, the only reliable solution was to load a custom system pointer with a totally transparent image. After implementing it for both Win32 and X, i decided: what the khell? and did the rest of the work.
Now my chentrah has two pointer mechanisms: the usual color one via OpenGL and the hardware 1-bit black and white pointer it uses when fps drops below 30.
19.03.2008
My X server (the Linux graphic shell) started crashing at switching to the terminal via Ctrl+Alt+F1. I used the opportunity to test Chentrah for robustness. Lo and behold, it saves the session with no problem. Ha. Try to find any other engine that would autosave the game at the crash of the entire graphics environment! Try beat this, Micro$oft!
29.01.2008
Lo and behold! A self-debugging program! It can scry the source position by the exception address adding it to the error message. Just like Frankenshtein, I sewn this thing together from the chunks of the dead RTL modules.
25.11.2007
Finally the main execiutable has all its function revamped. The GUI allows reporting error mesages and asking questions without dependence on MessageBox() or xmessage. Also, all the essential files - like the default config or font bitmap - are built into the main executable.
18.11.2007
I hought two weeks ago I would be working on pixel shaders at last. But what have I done? The text output and beginnings of the GUI. To not mention a lot of various ground work.
20.10.2007
I took one look at my window manager, and I felt ill. In no way would I present this bug-ridden crapyard as a part of my coming grand presentation!
There's only one thing I can do: take a scalpel and begin to work... Sheesh! When will I get to the pixel shaders already...?
03.10.2007
It was easier than I expected. The resource manager is up and working, it is a magnitude simpler now. I hope I can prepare the test #13 for the public demonstration soon
24.09.2007
Thinking of it, the resource manager architecture is a total crap. I have to re-create it from the scratch.
Also, I finally got fed with my Linux window manager bugs. This contraption, scrapped together from the pieces of code I don't even fully understand, is beyond any help. I have downloaded the Ogre sources, to read through OgreGLXWindow.cpp and see how to do it right. Now I at least about the existence of such thing as Xrandr X extension. Till now I used Xxf86vm to switch video modes.
24.06.2007
The battle was fierce and seemingly endless, but all the bugs are slain, at last. The resource manager in its minimal configuration is up and running. At last I can continue working on my font/GUI text manager.
Also, accomplised upgrading to Chepersy 0.8.1, full conversion of sources to unicode (utf8), wrapping all function of the exe back-called by the dll into try... blocks (exceptions should *never* cross the exe/dll boundary), and rearranging the folder structure so that it wold be 100% compatible with Linux and Vista (no writing into the program directory).
09.05.2007
Finally hunted down the elusive bug with incorrect passing of Russian characters in error messages from the module to the main program. The cause was pure idiocy: among the dozen of overloaded version of the procedure Die() there was none that would eat a bare Widestring. So the Ansi version was being called without fanfare, quietly converting my unicode string into something matching system locale. And then the resulting disaster was processed by my custom procedure for recoding cp1251 to Unicode. Obviously, that only worked as intended under real MustDie with Russian locale.
P.S. This screenshot is made in Linux. I simply have "Redmond 2000" theme installed. With wallpaper "Bliss"...
Whoever calls me a pervert first, will get punched in the facee.
24.04.2007
Everything is delayed as I move from ASPLinux 11.2 (a heavily patched Russian clone of Fedora Core 4) to Fedora Core 6... Everything is fine and danРІy except the fact that the Russian support is sub-par at best. There is no single font in the Windows cp1251 encoding I use, them all buggers support only koi-8!
13.03.2007
I finished moving from libPng to Vampyre Imaging library. It gives me multitude more — including a lot of supported formats, easy compilation right from the sources, filtering/processing functions et cetera — while the total size of binary files is practically the same. The cge.exe bloated up to 320 Kilobytes (the Linux version up to a Megabyte) but I now don't need to provide the libpng.dll.
04.02.2007
The window manager took the form it will keep for a long, long time. The Linux version now has no fullscreen mode support. The Win32 version performs a complete program restart when you switch from the fullscreen to windowed mode.
This screenshot: Win32- and Linux-versions of CGE coexist peacefully on a single Gnome desktop. What is funny, they both run smoothly, with a full hardware acceleration.
29.01.2007
The delay related to me switching to Linux comes to an end. Surprisingly, I only had to correct a couple lines of code to get a working native version. Only the switching between fullscreen modes is glitchy, it seems I have missed something. Should have used FreeGlut instead of writing my own window manager. But these are minor trifles. Turns out, the main executable in Linux is huge, 600 Kilobytes in size, and, the cherry on top, it cannot be compressed with UPX: it becomes unable to determine its own file name and path. Also, the dynamic libraries of modules are one and a half megabytes large, and that is after running "strip" !
In short, my main focus now is cross-compilation and running the engine in wine. Since CGE runs perfectly there (the glitches while switching between fullscreen and windowed are unrelated, it glitched in Windows too. Something is wrong with setting the window parameters).
03.10.2006
Test #13 is not ready yet, but I updated Test #12 on the download page, correcting a severe bug that, most likely, caused the test to crash with most of OpenGL drivers. Also its structure updated, to reflect the changes in the engine core.
!
20.09.2006
Nooooo! FreePascal is 5% slower!
15.09.2006
Here we go...
Began adding support for Turbo Delphi Explorer (free version).
15.08.2006
I have corrected an idiotic bug, the arrays were accessed via wrong indexes. As a result, after adding a new class or enumerated type, the game loading routine crashed happily with an AV. The test #12 is updated.
Now, why does it incorrectly process the Russian text in the error messages?..
05.08.2006
Test #12 is ready and uploaded ... sort of. Now, where do I get the money to pay for restoring my Internet access?..
03.08.2006
I optimized it at last. Constructor calls during the loading now take 40% of the overall time. It is the limit for the chosen program architecture. I will optimize the constructors too, but at the later stages.
To feel the real performance of the system I downclocked my system to match the planned minimum system requirements: 1000MHz CPU/200 MHz RAM. (I tried to set it at 133MHz, but the system just doesn't start below 200 - damn progress! Cheb, meet the Clear CMOS jumper. Clear CMOS jumper, meet Cheb).
If the class field cast changes, the class loaded via more complex, converting algorithm, which slows the loading down two-three times. Note that this doesn't affect the classes that remain unchanged.
24.07.2006
The day of stress test. On top of completing my long-awaited persistency system, I invented a very simple but precise and effective method of finding bottlenecks in the code ({$include + Asm + RDTSC) and performed a stress-test of my new system, forcing it to save and load complex structure consisting of a million of objects... I wasn't statisfied by its performance: rate of 200 thousands objects per second is very slow in my opinion, the advanced features like automatic resolving of deleted/added object fields, converting enumerated types if the values of their constants were changed, etc., do not justify it.
Anyway, the bottleneck testing was a bit shocking to me. One accessing of a field of a record field of a object of an object array property of an object takes as much time as dozen calls of virtual methods which perform intensive memory copying to/from TMemoryStream object... Anyway, note to self: keep data strucures simple! Otherwise the compiler doesn't have much chances to optimize anything...
Somebody could ask me: why bother so much with performance of this thing?.. It's unlikely, after all, to have the game world of a million objects... True, but I always dreamed to create some advanced spell effects, many of which require storing the game state and restoring it, or spawning a copy of game worlds and running it parallelly, or even creating one snapshot of game world per frame... For example, clairvoyance where you may have a real, functional foreboding, or time travel where you can hop a few seconds into the past to avoid the mob of monsters - and see yourself, fighting the said monsters back.
20.07.2006
I have no words Except the cuss ones
Why the hell does the FPC RTL report the stack overflow as "Unknown run-time error 202"...?! It cost me many hours of debugging before I figured to use {$memory} compiler directive to set the stack limit at 1Gbyte. On top of all, I don't even have my Internet access now, to ask at the forums. Drats.
03.07.2006
It lives! It lives!!! Mwa-ha-ha-ha-ha-ha!!!
My dream, my persistency system comes true...! Look out, one-two days - and I'll upload the Test #12. The test of my persistency system. What it does?.. Oh, it's simple. It store the entire object tree into a stream, then loads it back. What's so fancy about this...? Well, let's just say the stuff has very high backward compatibility, easily surviving the process of adding or removing fields of a class. Add here a scrupulous parser and validator... They won't let me forget about even a tiny field, keeping the system always consistent.
25.06.2006
Just a bit more effort - and my dream of many years will come true...
23.06.2006
I updated the Test #11 archive(s) on the download page. Corrections:
1. GNU GPL license now included, as it should be.
2. Lazarus project file (optional) updated, with "long strings" option turned on, as it should be.
3. Did I forget to announce here that the test is out?.. Uh-oh.
22.06.2006
Beware of validator
29.05.2006
Module manager 90% completed, console is 80% completed. After that I could consider the engine core finished, and move to more interesting task - the modules themselves!
26.05.2006
As people's philosophy says - "Better spend a day on writing the validator than spend a week later on searching for the cause of some stupid screw-up"...
17.05.2006
I was forced to go back to using LibPng. The built-in FPC image loading modules proved absolutely inefficient, it took them twenty seconds to load a tiny 256x256 .PNG...! For the reference: the LibPng decodes a 4096x4096 monstrosity in less than two and a half seconds!
07.05.2006
The engine core is almost finished... Gosh, how much background work...! The Test #10 coming soon.
18.04.2006
а) I started revising my strategy. What I was doing before was too epic. *Of course* it stalled. Now I'll follow the advice of Occam-jiisan and cut the extra burden out with the said razor. These need to go: 1) the MODding system (I now doubt anyone but me will work on the project); 2) The automatic generation of the methods of saving/loading the object by the class' field list (I can do it manually). 3) The built-in code editor and the possibility to call the compiler from within the engine (at least, for now).
б) I revized the project of the actual game that will be based on my engine. It will be a cross-breed of Diablo (auto-generated dungeons, magic, castrated RPG system, etc) and Doom II (reusing the models already existing for Doomsday will greatly reduce the cost). The total quantity of monsters and weapons will be achieved via recoloring ang having the several size variations.
24.07.2005
How could I be so blind! FreePascal has PNG support among its standard libraries - I didn't need any LibPng!
Am idiot.
05.06.2005
15.05.2005 05.11.2004
27.10.2004 25.01.2004 18.01.2004
Engine structure is something more or less ordered now, "compiling on the fly" works well, and now the detachable part of the engine has access to functions of OpenGL32.dll loaded by the main program.
15.01.2004
03.06.2003
02.06.2003 23.05.2003
11.04.2003 18.01.2003
13.01.2003
20.12.2002 29.11.2002
27.11.2002
20.11.2002
12.11.2002
10.11.2002
The configuration manager has been corrected and simplified (there were too many unnecessary features).
Then LibPng showed its temper, refusing to run under Windows 98. I tried to replace my current version, I implemented a sofhisticated procedure for checking dependencies... When I was ready to give up, I figured that it just can't find zlib1.dll, which was in the same folder... By intuition, I added a comand SetCurrentDir(
Moving to XP highlighted some problems... Surprisingly, caused not by evil Bill's machinations but by internal mismatches in FreePascal RTL: SetWindowLong declaration conflicted with some constants, Compiler yelled about range checking error
while evaluating constant value, then everything runned finely... Until I ran it on XP, which choked with my invalid window and started acting funny at attempts to switch the video mode... Corrected that by adding my own declaration of SetWindowLong (and reported the FreePascal bug #4043),
but just discovered a new bug - this time in the configuration manager
Today is historical day. First time in human history, Linux version of CGE started up and did one-two unsure steps forth... It still can't properly shutdown whithout angry yell of the X server, it ignores window resizing, and can'tswith to fullscreen... But it already can draw using OpenGL, and even receives mouse input!..
Cadaver had twitched slightly.
I managed to compile my engine using the last beta version of FPC (1.9.2) and get working results... Crashes were due to my own mistake: I stuffed the compiler with too many command-line switches (hell, I can't even remember what most of them are for!)... Removed that trash - and program immediately stopped crashing.
I decided to put MOST of the code to the detachable part (including all the rendering), the host program will control only textures, app. window, OpenGL, etc...
Also, added a console (part of the host program) - it's not for typing, it only shows log contents... Anyway, the engine will contain code editor for editing self, so complex console don't needed. Scrolled by the mouse wheel.
After a long pause, project is continued.
The first steps on the way of "recompiling on the fly", without restarting program and OpenGL and reloading resources.
I uploaded test #7. It's raw as hell.
Dumb Delphi incorrectly works with a unit where one piece of code included with {$include} three times with different compiler switches (a good way to keep all declarations in one place). Farewell, Delphi!
Starting from this day, the engine can be compiled in the FreePascal as well as in Delphi.
I decided to cardinally change engine building strategy.
Previously, main goal was to achieve controlability and playability in conditions of extremely low FPS (10..15) - that was because in many years I got used to play on low-end hardware (DungeonKeper II on K62-300 without hardware acceleration and with 32Mb RAM, Kingpin on same machine with VoodooII, Morrowind on Duron-800 with GF2MX) - and thus I adapted entire engine structure for principles of execution physics+control and graphics in two separate threads.
After long, meditative thinking I decided that all described above is very wrong. Now I consider playing with FPS lower 25 as especially perverted version of masochism...
So, new strategy is to hold FPS at least 25 - at any cost. For this, all far 3d objects will be cahed as impostors. Multithreading is only for background tasks like texture loading and game saving.
+ some optimization: 1000-spruce forest runs at 35 FPS!..
+ loading and rendering *.CME scripts and *.MD2 models
+ switching texture filtering modes (bi-, trilinear, anisotropic) and LOD bias
Borland rised Delphi price up to the sky. I started migration of my engine to the FreePascal.
+ menu classes (currently based on the hypertext class)
+ main menu and video mode selecting menu
- some bugs.. :) it seems, I repeat myself...
+ working text aligning: to left, right and width
+ text is now a hypertext with working links
- some bugs
+ text output with auto-fitting to specified output frame (can include pictures, too)
+ shows FPSes
+ thanks to FMOD, it now supports music in almost any format: OGG, MP3, S3M, MID...
- some bugs
+ working show lists, extrapolation and compensation for low FPSes
+ it works, it works!!! It even can draw a cube!