Class: Doom::WADLoader

Inherits:
Object
  • Object
show all
Defined in:
lib/doom/wad_loader.rb

Overview

WADLoader is responsible for loading and parsing WAD files

Constant Summary collapse

HEADER_SIZE =

WAD file header structure:

  • 4 bytes: WAD type (IWAD or PWAD)

  • 4 bytes: number of lumps

  • 4 bytes: directory offset

12
DIRECTORY_ENTRY_SIZE =

Directory entry structure:

  • 4 bytes: lump offset

  • 4 bytes: lump size

  • 8 bytes: lump name (null-terminated)

16

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(filename) ⇒ WADLoader

Initialize a new WADLoader with the given WAD file

Parameters:

  • filename (String)

    path to the WAD file



22
23
24
25
26
27
# File 'lib/doom/wad_loader.rb', line 22

def initialize(filename)
  @filename = filename
  @lumps = {}
  @directory = []
  load_wad
end

Instance Attribute Details

#directoryObject (readonly)

Returns the value of attribute directory.



18
19
20
# File 'lib/doom/wad_loader.rb', line 18

def directory
  @directory
end

#filenameObject (readonly)

Returns the value of attribute filename.



18
19
20
# File 'lib/doom/wad_loader.rb', line 18

def filename
  @filename
end

#lumpsObject (readonly)

Returns the value of attribute lumps.



18
19
20
# File 'lib/doom/wad_loader.rb', line 18

def lumps
  @lumps
end

#num_lumpsObject (readonly)

Returns the value of attribute num_lumps.



18
19
20
# File 'lib/doom/wad_loader.rb', line 18

def num_lumps
  @num_lumps
end

#wad_typeObject (readonly)

Returns the value of attribute wad_type.



18
19
20
# File 'lib/doom/wad_loader.rb', line 18

def wad_type
  @wad_type
end

Instance Method Details

#get_lump(name) ⇒ String?

Get a specific lump by name

Parameters:

  • name (String)

    the name of the lump

Returns:

  • (String, nil)

    the lump data or nil if not found



89
90
91
# File 'lib/doom/wad_loader.rb', line 89

def get_lump(name)
  @lumps[name]
end

#load_lumps(file) ⇒ Object

Load all lumps from the WAD file

Parameters:

  • file (File)

    the WAD file



77
78
79
80
81
82
83
84
# File 'lib/doom/wad_loader.rb', line 77

def load_lumps(file)
  @directory.each do |entry|
    next if entry[:size] == 0 # Skip markers

    file.seek(entry[:offset])
    @lumps[entry[:name]] = file.read(entry[:size])
  end
end

#load_wadObject

Load and parse the WAD file



30
31
32
33
34
35
36
# File 'lib/doom/wad_loader.rb', line 30

def load_wad
  File.open(@filename, "rb") do |file|
    read_header(file)
    read_directory(file)
    load_lumps(file)
  end
end

#lump_exists?(name) ⇒ Boolean

Check if a lump exists

Parameters:

  • name (String)

    the name of the lump

Returns:

  • (Boolean)

    true if the lump exists



102
103
104
# File 'lib/doom/wad_loader.rb', line 102

def lump_exists?(name)
  @lumps.key?(name)
end

#lump_namesArray<String>

List all lump names

Returns:

  • (Array<String>)

    array of lump names



95
96
97
# File 'lib/doom/wad_loader.rb', line 95

def lump_names
  @lumps.keys
end

#read_directory(file) ⇒ Object

Read the WAD directory

Parameters:

  • file (File)

    the WAD file



57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
# File 'lib/doom/wad_loader.rb', line 57

def read_directory(file)
  # The file position should already be at the directory after read_header
  # We'll use the number of lumps from the instance variable

  @num_lumps.times do
    entry = file.read(DIRECTORY_ENTRY_SIZE)
    lump_offset = entry[0..3].unpack("V")[0]
    lump_size = entry[4..7].unpack("V")[0]
    lump_name = entry[8..15].unpack("Z*")[0]

    @directory << {
      name: lump_name,
      offset: lump_offset,
      size: lump_size
    }
  end
end

#read_header(file) ⇒ Object

Read the WAD file header

Parameters:

  • file (File)

    the WAD file



40
41
42
43
44
45
46
47
48
49
50
51
52
53
# File 'lib/doom/wad_loader.rb', line 40

def read_header(file)
  header = file.read(HEADER_SIZE)
  @wad_type = header[0..3]
  @num_lumps = header[4..7].unpack("V")[0]
  directory_offset = header[8..11].unpack("V")[0]

  # Validate WAD type
  unless ["IWAD", "PWAD"].include?(@wad_type)
    raise Error, "Invalid WAD type: #{@wad_type}"
  end

  # Seek to the directory
  file.seek(directory_offset)
end