# Resource Manager
Unit: `ResMan`
Centralized resource loading from XML manifest.
## XML Format
```xml
```
**Paths are relative to XML location.** If `RES.XML` is in `DATA\`, then `path="TEST.PCX"` loads `DATA\TEST.PCX`.
## Types
```pascal
type
TResourceType = (ResType_Music, ResType_Sound, ResType_Image,
ResType_Font, ResType_Sprite, ResType_Palette);
TResourceManager = object
procedure Init(UseLazyLoading: Boolean);
function LoadFromXML(const Filename: String): Boolean;
{ Resource access }
function GetImage(const Name: String): PImage;
function GetFont(const Name: String): PFont;
function GetSprite(const Name: String): PSprite;
function GetSound(const Name: String): Integer; { Returns sound ID }
function GetMusic(const Name: String): PHSC_Obj;
function GetPalette(const Name: String): PPalette;
{ Manual resource management }
function LoadResource(const Name: String): Boolean;
procedure UnloadResource(const Name: String); { Free individual resource }
procedure Done;
end;
```
## Example
```pascal
uses ResMan, VGA, Sprite;
var
ResMgr: TResourceManager;
PlayerSprite: PSprite;
PlayerPalette: PPalette;
Player: TSpriteInstance;
begin
{ Initialize with lazy loading }
ResMgr.Init(True);
if not ResMgr.LoadFromXML('DATA\RES.XML') then
begin
WriteLn('ERROR: ', ResMgr.LastError);
Halt(1);
end;
{ Get resources (auto-loads on first access) }
PlayerSprite := ResMgr.GetSprite('player_run');
if PlayerSprite = nil then
begin
WriteLn('ERROR: ', ResMgr.LastError);
Halt(1);
end;
{ Get extracted palette }
PlayerPalette := ResMgr.GetPalette('player');
if PlayerPalette <> nil then
SetPalette(PlayerPalette^);
{ Setup sprite instance }
Player.Sprite := PlayerSprite;
Player.X := 100;
Player.Y := 50;
Player.CurrentTime := 0.0;
{ Game loop... }
UpdateSprite(Player, DeltaTime);
DrawSprite(Player, BackBuffer);
{ Cleanup }
ResMgr.Done; { Frees all resources }
end.
```
## Palettes
**Two types:**
1. **Standalone palette:**
```xml
```
2. **Image-extracted palette:**
```xml
```
**Usage:**
```pascal
{ Get extracted palette }
Pal := ResMgr.GetPalette('player');
if Pal <> nil then
SetPalette(Pal^);
```
## Music Singleton
Only one music track loads at a time:
```pascal
{ Load title music }
TitleMusic := ResMgr.GetMusic('title');
TitleMusic^.Start;
{ Load level music (title auto-unloaded) }
GameMusic := ResMgr.GetMusic('level1');
GameMusic^.Start;
{ TitleMusic pointer now invalid! }
```
## Manual Resource Unloading
Free individual resources when no longer needed:
```pascal
{ Load level assets }
BgImage := ResMgr.GetImage('level1_bg');
EnemySprite := ResMgr.GetSprite('enemy1');
{ Use them... }
{ Switch to next level - free old assets }
ResMgr.UnloadResource('level1_bg');
ResMgr.UnloadResource('enemy1');
{ Load new level assets }
BgImage := ResMgr.GetImage('level2_bg');
EnemySprite := ResMgr.GetSprite('enemy2');
```
**Supported:**
- Images, fonts, sprites, palettes, music
**Not supported:**
- Sounds (managed by SoundBank as a group)
**Behavior:**
- Frees memory immediately
- Marks resource as unloaded (can be re-loaded via lazy loading)
- Invalidates all pointers to that resource
⚠️ **Warning:** After unloading, any existing pointers become invalid!
```pascal
Img := ResMgr.GetImage('player');
ResMgr.UnloadResource('player');
PutImage(0, 0, Img, FB); { ❌ CRASH - pointer invalid! }
```
## Critical Notes
1. **XML-relative paths** - All paths relative to XML file location
2. **Lazy vs eager loading** - `Init(True)` for lazy, `Init(False)` for eager
3. **Music cleanup** - Don't call `Music^.Done` manually, let `ResMgr.Done` handle it
4. **Dependency resolution** - Sprites auto-load parent images
5. **Error handling** - Check `ResMgr.LastError` when `GetXXX` returns nil
## Error Handling
```pascal
Img := ResMgr.GetImage('invalid');
if Img = nil then
WriteLn('Error: ', ResMgr.LastError);
```
Common errors:
- `"Resource not found: name"` - Name not in XML
- `"Failed to load image"` - File missing or corrupt
- `"Sprite references unknown image"` - Missing dependency
## Benefits
- Declarative resource definitions (XML, not code)
- Name-based lookup (no hardcoded paths)
- Automatic dependency resolution
- Palette extraction and management
- Centralized cleanup
## Dependencies
- MINIXML (XML parsing)
- STRMAP (name lookup)
- PCX, VGAFONT, SPRITE, SNDBANK, PLAYHSC