Latching on to the shoulders of giants
A good first step when poking around old games is to see if anybody has had the same idea. Many games, especially the classic Sierra and Lucasarts adventures, have been completely de-compiled, famously ScummVM, in particular does a fantastic job and have absorbed many small projects into its ecosystem as well.
BaKGL seems to have made some progress towards remaking the game and still sees a bit of activity (last update was 10 months ago). In many ways, this person seems to be interested in exactly the same thing as me; learning how the game actually works underneath. However, at this stage I wanted to just see if I could learn anything from the assets. BaKGL is based on XBaK, which did a lot of work describing how assets are stored.
The key files in Betrayal at Krondor are:
KRONDOR.CFG
INSTALL.SCR
STD.DRV
RESOURCE.CFG
VMCODE.OVL
DRIVE.CFG
SNDBLAST.DRV
GENMIDI.DRV
INSTALL.HLP
SX.OVL
KRONDOR.EXE
ADL.DRV
INSTALL.EXE
INSTALL.TXT
FRP.SX
MT32.DRV
STARTUP.GAM
KRONDOR.RMF
KRONDOR.001A lot of these we can guess the purpose of; for example, KRONDOR.EXE is the main executable and GENMIDI.DRV is the MIDI driver.
By its size of alone (12 MB) it seems likely that KRONDOR.001 must be the main resource file. This would be a good place to start.
Searching for this in Ghidra, however, comes up with... nothing.

KRONDOR.001. Do however not krondor.rmf. These are all values stored on the stack, suggestion the code will reference them directly.However some of the other values might be worth exploring.
KRONDOR.CFG is a small file, likely holding the user's config settings from the user (for example, which sound card to use).
The non-file names are string references: You do not have enough memory to run Betrayal... is obviously an error message that appears if the user does not have sufficient memory to run the game. This could be a potential entry point into the game when we get to that stage, but it's not what we’re after right now.
Loading Betrayal at Krondor... please wait. is the string displayed when the game starts up (while waiting for the intro to load). Another good entry point into the game.
krondor.rmf refers to a 14KB file in the game directory. Potentially interesting. Ghidra was able to find where it was being referenced fairly easily.

krondor.rmf. Note that various names given to some of the variables and functions were done on the back of analysis and some guesswork with the assistance of Gemini, but feels pretty accurate at this point.This seemed promising. When looking at XBaK it was named ResourceIndex. From ResourceIndex.h
struct ResourceIndexData
{
unsigned int hashkey;
std::streamoff offset;
unsigned int size;
};
class ResourceIndex
{
private:
std::string resourceFilename;
unsigned int numResources;
std::map <const std::string, ResourceIndexData> resIdxMap;
std::map<const std::string, ResourceIndexData>::iterator resIdxIterator;
public:
ResourceIndex();
virtual ~ResourceIndex();
void Load ( const std::string &filename );
void Save ( const std::string &filename );
std::string GetResourceFilename() const;
unsigned int GetNumResources() const;
bool Find ( const std::string &name, ResourceIndexData &data );
bool GetFirst ( std::string& name, ResourceIndexData &data );
bool GetNext ( std::string& name, ResourceIndexData &data );
};Based on this and the rest of the code from XBaK, we can begin to see a picture of the structure of this file:
Header:
| Offset | Size | Description |
|---|---|---|
| 0 | 4 bytes | Version (u32 LE, must be 1) |
| 4 | 2 bytes | Unknown (u16 LE) |
| 6 | 13 bytes | Resource filename (null-terminated string) |
| 19 | 2 bytes | Number of resources (u16 LE) |
Resource Index (repeats for each resource):
| Offset | Size | Description |
|---|---|---|
| 0 | 4 bytes | Hash key (u32 LE) |
| 4 | 4 bytes | Offset into .001 file (u32 LE) |
With this information, we can use Claude to write a simple tool to display the contents of KRONDOR.RMF:
$ cargo run --bin rmf-explorer gamedata/ | head -n 50
Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.00s
Running `target/debug/rmf-explorer gamedata/`
=== KRONDOR.RMF Explorer ===
RMF size: 14165 bytes (0.01 MB)
Resource File: KRONDOR.001
Number of Resources: 1768
Hash Offset
---------------------
0x64425934 0
0x64525934 113
0x65425934 328
0x65525934 600
0x66425934 713
0x66525934 867
0x67425934 980
0x67525934 1093
0x68425934 1209
0x68525934 1322
0x69425934 1435
0x69525934 1548
0x6a425934 1661
0x6a525934 1774
0x6b425934 1887
0x6b525934 2000
0x6672ce81 2113
0x39ab894a 2459
0xe967cc58 3260
0x1637ffd1 4061
0x62f07c31 4862
0x65907cb6 5663
0x65a07cb6 6464
0x6ad07cb7 7265
0xa1407cb8 8066
0x65f07cb9 8867
0x47c07cba 9668
0x61407cba 10469
0x78c07cbb 11270
0xd7a07cc0 12071
0xaca07cc7 12872
0x86c07cc8 13673
0x94607cc8 14474
0x47cfaa01 15275
0x37b272dd 15465
0x478fab01 19441
0x479fab01 24751
0x47afab01 34384
0x47bfab01 40687
0x47cfab01 53421
0x38b272dd 57444
So far, so good. We've also discovered where KRONDOR.001 is referenced from. Next time, we'll start linking the RMF data to KRONDOR.001.