Skip to content

Instantly share code, notes, and snippets.

@mikezila
Last active March 7, 2021 23:53
Show Gist options
  • Save mikezila/f1f710dae1e65b9dd9a96f0601dc49ca to your computer and use it in GitHub Desktop.
Save mikezila/f1f710dae1e65b9dd9a96f0601dc49ca to your computer and use it in GitHub Desktop.
Rip textures from a quake1 bsp. Requires the palette.lmp file with the quake palette.
require 'chunky_png'
Texture = Struct.new(:name, :width, :height, :pixels)
TextureLump = Struct.new(:count, :offsets)
textures = []
bsp = IO.read(ARGV.first, mode: "rb")
palette = IO.read("palette.lmp", mode: "rb")
tex_lump_offset = bsp[20, 4].unpack("L").first
tex_lump = TextureLump.new
tex_lump.count = bsp[tex_lump_offset, 4].unpack("L").first
tex_lump.offsets = []
#Collect offsets to textures
(0...tex_lump.count).each do |i|
index = tex_lump_offset + 4 + (i * 4)
tex_lump.offsets[i] = bsp[index, 4].unpack("L").first
end
#Collect texture data
(0...tex_lump.count).each do |i|
offset = tex_lump_offset + tex_lump.offsets[i]
tex = Texture.new
tex.name = bsp[offset, 16]
tex.width = bsp[offset + 16, 4].unpack("L").first
tex.height = bsp[offset + 20, 4].unpack("L").first
tex_size = tex.width * tex.height
colors = bsp[offset + 40, tex_size].unpack("C*")
tex.pixels = []
colors.each do |color|
tex.pixels.push(palette[color*3, 3].unpack("C*"))
end
tex.pixels = tex.pixels.flatten
textures.push(tex)
end
textures.each do |tex|
png = ChunkyPNG::Image.new(tex.width, tex.height)
(0...tex.height).each do |y|
(0...tex.width).each do |x|
index = ((y * tex.width) + x) * 3
png.set_pixel(x, y, ChunkyPNG::Color.rgb(tex.pixels[index], tex.pixels[index+1], tex.pixels[index+2]))
end
end
png.save(tex.name[0...tex.name.index("\0")].gsub('*','') + ".png", :fast_rgb)
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment