Recreated Keen 4-6 Source Code

Here is where to post about the latest Commander Keen fangame or modification you've finished, a new website you've made, or another Keen-related creation.
User avatar
Multimania
Vortininja
Posts: 86
Joined: Sat Nov 10, 2007 8:10
Location: Hiding in a small, cramped corner of the BwB megarocket.
Contact:

Re: Recreated Keen 4-6 Source Code

Post by Multimania »

basic wrote: Sat Jun 08, 2024 10:07 1. in the first screen there is a memory overview and it says only 512KB is free to use. Is there any way to use more than 512KB in this Keen project? I might be able to make do, but ideally I would like to have at least 100MB.
Keen is a 16-bit program, so can access at most* 640k of memory (including the size of the .exe: the memory overview does not count this). There are some techniques you can use to squeeze a few extra kilobytes in (and if you want to use EMS/XMS, you can access a few megabytes of memory, but not all at once).

If you want to use more, you really want to have a 32-bit or 64-bit game (which will require a 386 or better processor). The Omnispeak project is a re-implementation of Keen for newer processors and OSes, and can take advantage of as much memory as you require.
basic wrote: Sat Jun 08, 2024 10:07 2. I'm kinda new to C and anything on the web that teaches it uses malloc, but that doesn't work in this project. What do I use instead of malloc, or how do I get a pointer to a struct?
Keen has its own custom memory allocator, which can be found in ID_MM.{C,H}. Typically, the way you allocate memory in Keen is to create a global pointer, and pass a pointer to that pointer to MM_GetPtr():

Code: Select all

int *mydata;
MM_GetPtr(&mydata, sizeof(mydata));
You free these with MM_FreePtr(), or can call MM_SetPurge() to mark the memory as low-priority so the game can free it automatically if memory is low. You should call MM_SetLock(&ptr, true) before using the data, and MM_SetLock(&ptr, false) after using it.

This more complicated system lets Keen move data around in memory when it's not in use (and even throw out low-priority data if there's not enough memory), which is important to both keep the game running with only ~600KB of memory, and to avoid needing to re-read data from disk if there's enough spare memory to keep it cached.

It's worth looking at ID_MM.H, as well as generally looking at where functions starting with MM_ are used throughout the code to get an idea of how this works.

*This is a little bit simplified, but the processor allows a maximum of ~1MB of conventional memory, and traditionally enough of this is reserved to leave you with only 640KB for all programs, and the OS.
User avatar
K1n9_Duk3
Vorticon Elite
Posts: 790
Joined: Mon Aug 25, 2008 9:30
Location: Germany
Contact:

Re: Recreated Keen 4-6 Source Code

Post by K1n9_Duk3 »

Multimania wrote: Sun Jun 09, 2024 2:33 Keen has its own custom memory allocator, which can be found in ID_MM.{C,H}. Typically, the way you allocate memory in Keen is to create a global pointer, and pass a pointer to that pointer to MM_GetPtr():

Code: Select all

int _seg *mydata;
MM_GetPtr(&mydata, sizeof(*mydata));
Fixed it for you.

The memory manager of the 16-bit DOS version of Keen 4-6 operates on "_seg" pointers. These segment-based pointers can be turned into "far" pointers, but not into "near" pointers. In the memory model used by the Keen games, every (data) pointer not explicitly declared as "far" or "_seg" is a near pointer by default.

As you can see, things can get complicated when writing C code for 16-bit DOS programs, so maybe you're better off using Omnispeak if you're new to programming in C. It would probably be a bit easier.
Hail to the K1n9, baby!
http://k1n9duk3.shikadi.net
Post Reply