The random ramblings of a French programmer living in Norway...
← Starting at Adeline SoftwareLevel creation workflow →
  Adeline's LibMenu
Fri 21st May 2021   
Adeline Software
 Part 1 Part 2 Part 3 Part 4 Part 5 Part 6  

At Adeline Software it was easy to jump from one project to another, start helping, or even take over a tool because things were standardized.

The Adeline Libraries were designed to be very high level, you would work with "3d objects" or "particle flows", "resource item", sometimes actual files, but pretty much never play with handles or pixels: That made the code very understandable because all the complexity and implementation details were hidden in the libraries.


Most of the PC libraries were maintained by Serge Plagnol, while the PlayStation ones were mostly made by Olivier Lhermite.

From a user perspective, it was quite pain-free to use, all we had to do was to include one single header file for each of the library we needed:
  • lib_sys, for all the core stuff (initialization, timers, memory, files, ...)
  • lib_svga, for manipulation 2D frame buffers1.
  • lib_menu, to quickly create user interfaces
  • lib_3d, to display and animate 3D objects
  • lib_cd, to access optical drives
  • lib_ail, to access the audio
And that's it for the core ones2.

We had access to the source code of all these libraries, but in practice all we had to do was to specify the name of the lib file and directly link it from the folder containing the version of the lib we wanted, so we would not waste our time recompiling the same thing again and again.

The System Library

The lib_sys only had two mandatory function calls:

// Config parameters
#define INIT_SVGA (1<<0)
#define INIT_SAMPLE (1<<1)

void InitAdelineSystem(CHAR *nom_fichier,LONG config)
void ClearAdelineSystem()

The first one accepted an optional configuration filename3, and a bit mask telling which features we wanted to enable: SVGA graphics, mouse support, audio mixer, etc...

The second one would just restore whatever was modified.

Once the system properly initialized, we could then have access to any of the supported functionalities (reading keyboard and joysticks, accessing files, allocating memory, data decompression, timers and frame rate management.

Including the holy LoadMalloc.

Praise the Holy LoadMalloc
Praise the Holy LoadMalloc

For some reason, the artists and designers overheard programmers discussing some problem and when the function was mentioned they found the name absolutely hilarious4.

void *LoadMalloc(char *name); // Load/Allocate the specified file
extern U32 LoadMallocFileSize; // Contains the size of the last loaded file

I have to say, it still pains me to see C++ code in 2021, requiring I don't know how many lines of code to just load a file into memory, even without proper error handling.

Sad times.

So anyway, LoadMalloc was awesome, we used it everywhere :D

The Menu Library

User Interfaces are still not a solved problem: Everybody comes up with a new way of doing the same things, but differently and better, and it ends up being forgotten and unmaintained, like the 27 others before it, resulting in most work places forcing you to use totally different paradigms to create user interfaces depending of which team wrote the software, the choice of language, etc... making it very difficult for a programmer to move from project to project.

All the interactive tools at Adeline used the Lib Menu, which basically had an interesting layout system where things where referenced in pseudo characters.

The end result is that no matter how design-blind the programmer would be, the tool would still have properly aligned controls.

MiniDraw - LibMenu in SVGA
MiniDraw - LibMenu in SVGA

A side effect is that it actually made it possible to display the same tool in actual text mode, with a relatively similar appearance without having to do any change in the code.

LibMenu in TEXT mode
LibMenu in TEXT mode

One important parameter though, is that in SVGA mode we only had 256 colors, so we had to make sure that some of the colors would be kept identical to avoid having text and background ending up having the same color.

Which brings the topic of the Adeline color palette!

The TimeCo palette

Since on PC you could NOT have more than one color palette, everything on screen had to share one single palette, which means choices had to be made.

When painting manually, it's easy for a human to select specific colors and draw things, but when displaying 3D objects, with real time lighting, the code needs to know which of the various colors are brighter or darker.

The solution adopted at Adeline was to use "banks" of colors.

Example of color mapping
Example of color mapping

As you can see on the screenshot above, we have 16 banks of 16 colors.

The first 16 colors are designed to be usable for the tools, even on a 16 colors display system.

The next 32 colors form a continuous brown/beige gradient which can used for skin tones in various brightness conditions.

Then we have series of 16 colors gradients in various tones, which are easy to use by the rendering code to show specific colors in different intensities.

It was a real challenge, however, for the artists:

They had to all work together so the entire level would use the same set of fixed colors for the UI, characters, enemies, special effects, background graphics, etc...

That's all for today :)

Adeline Software
 Part 1 Part 2 Part 3 Part 4 Part 5 Part 6  

1. Technically, lib_svga should have been named "lib_2d" or "lib_bitmap", and lib_ail (Audio Interface Library) could have been named "lib_sound"... but back then we were using DOS so we were limited to 8.3 filenames, so choices had to be made.
2. There was some outliers like the "lib_txt" to easily do install menus where only the text mode could be assumed to be available
3. If not set, the program would fetch the content of the ADELINE environment variable
4. I think they used this word as a way to signal us (programmers) that we were using too much technical jargon when explaining things to non programmers.
comments powered by Disqus