194 lines
6.7 KiB
C++
194 lines
6.7 KiB
C++
#include "wad.h"
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <unordered_map>
|
|
#include <string>
|
|
#include <vector>
|
|
#include <SDL3/SDL.h>
|
|
|
|
namespace wad {
|
|
|
|
char file[13];
|
|
filelump_t *directory;
|
|
uint32_t numlumps;
|
|
|
|
struct patch_t {
|
|
|
|
};
|
|
|
|
std::unordered_map<std::string, draw::surface_t*> flats;
|
|
std::unordered_map<std::string, draw::surface_t*> textures;
|
|
std::unordered_map<std::string, draw::surface_t*> patches;
|
|
std::vector<std::string> patch_names;
|
|
//char (*patch_names)[8];
|
|
|
|
void init(const char *filename) {
|
|
|
|
strcpy(file, filename);
|
|
FILE *f = fopen(filename, "rb");
|
|
|
|
char header[4]; fread(header, 4, 1, f);// printf("header: %*.s\n", 4, header);
|
|
uint32_t infotableofs;
|
|
fread(&numlumps, 4, 1, f);// printf("num lumps: %i\n", numlumps);
|
|
fread(&infotableofs, 4, 1, f);// printf("directory offset: %i\n\n", infotableofs);
|
|
directory = (filelump_t*)malloc(sizeof(filelump_t)*numlumps);
|
|
fseek(f, infotableofs, SEEK_SET);
|
|
for (int i=0; i<numlumps; ++i) {
|
|
fread(&directory[i].filepos, 4, 1, f);
|
|
fread(&directory[i].size, 4, 1, f);
|
|
fread(directory[i].name, 8, 1, f);
|
|
//if (strncmp("TEXTURE1", directory[i].name, 8)==0)
|
|
// printf("num lumps: %8.10s % 6i % 6i\n", directory[i].name,directory[i].filepos, directory[i].size);
|
|
}
|
|
fclose(f);
|
|
|
|
uint8_t *pnames = load("PNAMES");
|
|
int num_pnames = *(uint32_t*)pnames;
|
|
//printf("num pnames: %i\n", num_pnames);
|
|
|
|
//patch_names = (char (*)[8]) malloc(num_pnames * sizeof *patch_names);
|
|
char *names = (char*)(pnames+4);
|
|
for (int i=0;i<num_pnames;++i) {
|
|
char name[9]; name[8]=0;
|
|
for (int j=0;j<8;++j) name[j] = toupper(names[8*i+j]);
|
|
patch_names.push_back(name);
|
|
}
|
|
free(pnames);
|
|
//for (int i=0;i<num_pnames;++i) printf("%s\n", patch_names[i].c_str());
|
|
}
|
|
|
|
uint8_t *load(const char *name) {
|
|
|
|
int i=-1;
|
|
for (i=0; i<numlumps; ++i) if (strncmp(name, directory[i].name,8)==0) break;
|
|
if (i==-1) return nullptr;
|
|
|
|
FILE *f = fopen(file, "rb");
|
|
fseek(f, directory[i].filepos, SEEK_SET);
|
|
uint8_t *buffer = (uint8_t*)malloc(directory[i].size);
|
|
fread(buffer, directory[i].size, 1, f);
|
|
fclose(f);
|
|
|
|
return buffer;
|
|
}
|
|
|
|
uint8_t *load(const char *prev, const char *name, int *size)
|
|
{
|
|
int i=-1;
|
|
for (i=0; i<numlumps; ++i) if (strncmp(prev, directory[i].name,8)==0) break;
|
|
if (i==-1) return nullptr;
|
|
for (; i<numlumps; ++i) if (strncmp(name, directory[i].name,8)==0) break;
|
|
if (i==-1) return nullptr;
|
|
|
|
FILE *f = fopen(file, "rb");
|
|
fseek(f, directory[i].filepos, SEEK_SET);
|
|
uint8_t *buffer = (uint8_t*)malloc(directory[i].size);
|
|
fread(buffer, directory[i].size, 1, f);
|
|
fclose(f);
|
|
|
|
if (size) *size = directory[i].size;
|
|
return buffer;
|
|
}
|
|
|
|
uint32_t *loadPalette(int index)
|
|
{
|
|
uint8_t *palettes = wad::load("PLAYPAL");
|
|
uint32_t *palette = (uint32_t*)malloc(1024);
|
|
for (int i=0;i<256;++i) {
|
|
uint8_t r = palettes[(768*index)+(i*3)];
|
|
uint8_t g = palettes[(768*index)+(i*3)+1];
|
|
uint8_t b = palettes[(768*index)+(i*3)+2];
|
|
palette[i] = (r<<16) | (g<<8) | b;
|
|
}
|
|
free(palettes);
|
|
return palette;
|
|
}
|
|
|
|
draw::surface_t *loadFlat(const char *name)
|
|
{
|
|
if (flats.find(name) != flats.end()) return flats[name];
|
|
|
|
uint8_t *flat = load(name);
|
|
draw::surface_t *surf = draw::newsurf(64, 64);
|
|
int i=0;
|
|
for (int y=0;y<64;++y)
|
|
for (int x=0;x<64;++x)
|
|
surf->pixels[x+y*64] = flat[i++];
|
|
|
|
free(flat);
|
|
flats[name] = surf;
|
|
return surf;
|
|
}
|
|
|
|
draw::surface_t *loadTexture(const char *name)
|
|
{
|
|
if (textures.find(name) != textures.end()) return textures[name];
|
|
|
|
uint8_t *textures_lump = load("TEXTURE1");
|
|
int num_textures_in_lump = ((uint32_t*)textures_lump)[0];
|
|
uint32_t *offsets = &((uint32_t*)textures_lump)[1];
|
|
int i = 0;
|
|
while (i<num_textures_in_lump) {
|
|
char *texture_name = (char*)textures_lump+offsets[i];
|
|
if (strncmp(name, texture_name, 8)==0) break;
|
|
i++;
|
|
}
|
|
SDL_assert(i<num_textures_in_lump);
|
|
//if (i==num_textures_in_lump) { printf("TEXTURA '%s' NO TROBADA!\n", name); return nullptr; }
|
|
|
|
uint8_t *texture_info = textures_lump+offsets[i]+12;
|
|
const int texture_width = ((uint16_t*)texture_info)[0];
|
|
const int texture_height = ((uint16_t*)texture_info)[1];
|
|
draw::surface_t *surf = draw::newsurf(texture_width, texture_height);
|
|
|
|
const int patch_count = ((uint16_t*)texture_info)[4];
|
|
//printf("Texture: %s (%ix%i)\n Patch count: %i\n", name, texture_width, texture_height, patch_count);
|
|
|
|
uint16_t *patches = &((uint16_t*)texture_info)[5];
|
|
for (int i=0; i<patch_count; ++i) {
|
|
const int originx = int16_t(patches[i*5+0]);
|
|
const int originy = int16_t(patches[i*5+1]);
|
|
const int patch_index = patches[i*5+2];
|
|
const char *patch_name = patch_names[patch_index].c_str();
|
|
//printf("Patch. Index:%i, Name:%s, ox:%i, oy:%i\n", patch_index, patch_name, originx, originy);
|
|
draw::surface_t *patch = loadPatch(patch_name);
|
|
draw::drawsurf(originx, originy, patch, surf);
|
|
}
|
|
|
|
free(textures_lump);
|
|
textures[name] = surf;
|
|
return surf;
|
|
}
|
|
|
|
draw::surface_t *loadPatch(const char *name)
|
|
{
|
|
if (patches.find(name) != patches.end()) return patches[name];
|
|
|
|
uint8_t *patch_lump = load(name);
|
|
const int patch_width = ((uint16_t*)patch_lump)[0];
|
|
const int patch_height = ((uint16_t*)patch_lump)[1];
|
|
//printf("Patch:%s, %ix%i\n", name, patch_width, patch_height);
|
|
draw::surface_t *surf = draw::newsurf(patch_width, patch_height);
|
|
uint32_t *offsets = (uint32_t*)(patch_lump+8);
|
|
|
|
for (int i=0; i<patch_width; ++i) {
|
|
uint8_t *post = patch_lump+offsets[i];
|
|
while(true) {
|
|
if (*post == 0xff) break;
|
|
const int offset = *(post++);
|
|
const int length = *(post++);
|
|
post++;
|
|
for (int j=0;j<length;++j) {
|
|
draw::putpsurf(surf, i, offset+j, *(post++));
|
|
}
|
|
post++;
|
|
}
|
|
}
|
|
//https://www.doomwiki.org/wiki/Picture_format
|
|
|
|
free(patch_lump);
|
|
patches[name] = surf;
|
|
return surf;
|
|
}
|
|
} |