Skip to content

Commit

Permalink
Chore: Patch and flat graphics exporting, refactoring and minor fixes (
Browse files Browse the repository at this point in the history
…#2)

* feat: Patch sprite exporting

* feat: Flat exporting

* fix: Flag help text fix

* chore: Renamed dumper methods file

* chore: File renaming, music method relocation

* chore: Refactoring

* fix: Added missing last column for patch graphics

* chore: Ignore .png files

* fix: Palette parsing break statement
  • Loading branch information
segovia-no authored Jul 18, 2023
1 parent 9992e5d commit b539563
Show file tree
Hide file tree
Showing 9 changed files with 221 additions and 65 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@
*.txt
*.MIDI
*.MUS
*.png

# Build files
wadtogo-darwin-*
wadtogo-linux-*
wadtogo-windows-*
wadtogo-windows-*
4 changes: 2 additions & 2 deletions flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ func (f *Flags) parseFlags() {
dumpLumpsInfo := flag.String("lumpsinfo-dump", "", "Dump WAD's lumps info to file")
dumpWADMusicInfo := flag.String("musicinfo-dump", "", "Dump WAD's music info to file")
dumpWADMapsInfo := flag.String("mapsinfo-dump", "", "Dump WAD's maps info to file")
exportMusic := flag.String("music-export", "", "Export WAD's music to file")
exportSprites := flag.String("sprite-export", "", "Export WAD's sprites to file")
exportMusic := flag.String("music-export", "", "Export WAD's music to folder")
exportSprites := flag.String("sprite-export", "", "Export WAD's sprites to folder")

flag.Parse()

Expand Down
24 changes: 15 additions & 9 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,15 +35,8 @@ func main() {
}

if flagReader.exportSprites != "" {
wadLoader.LoadPalette()
wadLoader.LoadPalettes()
wadLoader.LoadGraphics()

err := wadLoader.ExportAllSprites(flagReader.exportSprites)
if err != nil {
fmt.Println("[Error] Cannot export sprites - " + err.Error())
}

fmt.Println("Sprites exported successfully")
}

// Command execution
Expand All @@ -67,11 +60,24 @@ func main() {
wl.DumpMapNamesToTextFile(flagReader.dumpWADMapsInfo, wadLoader.Maps)
}

if flagReader.exportSprites != "" {
fmt.Println("Exporting sprites...")

err := wadLoader.ExportAllSprites(flagReader.exportSprites)
if err != nil {
fmt.Println("[Error] Cannot export sprites - " + err.Error())
}

fmt.Println("Sprites exported successfully")
}

if flagReader.exportMusic != "" {
fmt.Println("Exporting songs...")

err := wadLoader.ExportAllSongs(flagReader.exportMusic)
if err != nil {
fmt.Println("[Error] Cannot export songs - " + err.Error())
}
fmt.Println("All songs exported successfully")
fmt.Println("Songs exported successfully")
}
}
175 changes: 155 additions & 20 deletions wadloader/graphics.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,11 @@ type PatchPostSegment struct {
PixelData []byte
}

type Flat struct {
Name string
PixelData [4096]byte
}

// Graphic indexes structs
type spriteMarkerIndexes = struct {
S_START int
Expand Down Expand Up @@ -68,12 +73,12 @@ type patchesMarkerIndexes = struct {
}

// Graphic functions
func (wl *WADLoader) LoadPalette() {
wp.checkValidByteReader()
func (wl *WADLoader) DetectPalettes() ([]Palette, error) {

var palettes []Palette

if len(wl.WADLumps) < 1 {
fmt.Println("[Warn] LoadPalette: No Lumps loaded, cannot load palette!")
return
return palettes, errors.New("[Warn] DetectPalette: No Lumps loaded, cannot detect palettes")
}

for _, lump := range wl.WADLumps {
Expand All @@ -82,53 +87,83 @@ func (wl *WADLoader) LoadPalette() {
if string(lumpName) == "PLAYPAL" {
wp.byteReader.Seek(int64(lump.LumpOffset), io.SeekStart)

var palettes []Palette

for i := 0; i < 14; i++ {
var p Palette

errRead := binary.Read(wp.byteReader, binary.LittleEndian, &p)
if errRead != nil {
fmt.Println("[Error] LoadPalette: Cannot read one of the palettes")
return
return palettes, errors.New("[Error] DetectPalette: Cannot read one of the palettes, aborting palette detection")
}

palettes = append(palettes, p)
}

wl.Palettes = palettes
return
break
}
}

if len(palettes) < 1 {
return palettes, errors.New("[Warn] DetectPalette: Couldn't detect palettes")
}

return palettes, nil
}

func (wl *WADLoader) DetectGraphics() ([]Patch, []Patch) {
func (wl *WADLoader) DetectGraphics() ([]Patch, []Patch, []Flat ,error) {

var sprites []Patch
// var flats []Patch // TODO: this is not a patch, but raw data
var patches []Patch
var flats []Flat

if len(wl.WADLumps) < 1 {
fmt.Println("[Warn] DetectGraphics: No Lumps loaded, cannot detect graphic lumps!")
return sprites, patches
return sprites, patches, flats, errors.New("[Warn] DetectGraphics: No Lumps loaded, cannot detect graphic lumps")
}

// Sprite loading
spriteLumps, err := getSpriteLumps(wl.WADLumps)
if err != nil {
return sprites, patches
return sprites, patches, flats, errors.New("[Warn] DetectGraphics: Cannot get sprite lumps")
}

for _, lump := range spriteLumps {
spritePatch, err := parsePatchLump(lump)
if err != nil {
fmt.Println("[Error] DetectGraphics: Cannot parse a sprite patch lump - " + err.Error())
return sprites, patches
return sprites, patches, flats, errors.New("[Error] DetectGraphics: Cannot parse a sprite patch lump - " + err.Error())
}

sprites = append(sprites, spritePatch)
}

return sprites, patches
// Patch sprite loading
patchLumps, err := getPatchLumps(wl.WADLumps)
if err != nil {
return sprites, patches, flats, errors.New("[Warn] DetectGraphics: Cannot detect patch lumps")
}

for _, lump := range patchLumps {
patch, err := parsePatchLump(lump)
if err != nil {
return sprites, patches, flats, errors.New("[Error] DetectGraphics: Cannot parse a patch lump - " + err.Error())
}

patches = append(patches, patch)
}

// Flat loading
flatLumps, err := getFlatLumps(wl.WADLumps)
if err != nil {
return sprites, patches, flats, errors.New("[Warn] DetectGraphics: Cannot detect flat lumps")
}

for _, lump := range flatLumps {
flat, err := parseFlatLump(lump)
if err != nil {
return sprites, patches, flats, errors.New("[Error] DetectGraphics: Cannot parse a patch lump - " + err.Error())
}

flats = append(flats, flat)
}

return sprites, patches, flats, nil
}

func getSpriteLumps(lumps []Lump) ([]Lump, error) {
Expand Down Expand Up @@ -165,6 +200,46 @@ func getSpriteLumps(lumps []Lump) ([]Lump, error) {
return spriteLumps, nil
}

func getPatchLumps(lumps []Lump) ([]Lump, error) {

var patchLumps []Lump

patchIdx, err := getPatchMarkerIndexes(lumps)
if err != nil {
return patchLumps, errors.New("[Error] getPatchLumps: Cannot get patch markers indexes")
}

if patchIdx.P_START != 0 && patchIdx.P_END != 0 {
for i := patchIdx.P_START + 1; i < patchIdx.P_END; i++ {
if lumps[i].LumpSize != 0 { // ignore submarkers
patchLumps = append(patchLumps, lumps[i])
}
}
}

return patchLumps, nil
}

func getFlatLumps(lumps []Lump) ([]Lump, error) {

var flatLumps []Lump

flatIdx, err := getFlatMarkerIndexes(lumps)
if err != nil {
return flatLumps, errors.New("[Error] getFlatLumps: Cannot get flat markers indexes")
}

if flatIdx.F_START != 0 && flatIdx.F_END != 0 {
for i := flatIdx.F_START + 1; i < flatIdx.F_END; i++ {
if lumps[i].LumpSize != 0 { // ignore submarkers
flatLumps = append(flatLumps, lumps[i])
}
}
}

return flatLumps, nil
}

func parsePatchLump(patchLump Lump) (Patch, error) {
wp.checkValidByteReader()

Expand Down Expand Up @@ -197,7 +272,7 @@ func parsePatchLump(patchLump Lump) (Patch, error) {
patch.TopOffset = patchHeader.TopOffset

var patchHeaderPostOffsets []uint32
for i := 0; i < int(patch.Width) - 1; i++ {
for i := 0; i < int(patch.Width); i++ {
var postOffset uint32

errRead = binary.Read(wp.byteReader, binary.LittleEndian, &postOffset)
Expand Down Expand Up @@ -245,6 +320,28 @@ func parsePatchPost(lumpOffset uint32) (PatchPost, error) {
return patchPost, nil
}

func parseFlatLump(flatLump Lump) (Flat, error) {
wp.checkValidByteReader()

var flat Flat

wp.byteReader.Seek(int64(flatLump.LumpOffset), io.SeekStart)

lumpName := string(bytes.Trim(flatLump.LumpName[:], "\x00"))
flat.Name = lumpName

var flatPixelData [4096]byte

errRead := binary.Read(wp.byteReader, binary.LittleEndian, &flatPixelData)
if errRead != nil {
return flat, errors.New("[Error] parseFlatLump: Cannot parse flat lump data - " + lumpName + " - " + errRead.Error())
}

flat.PixelData = flatPixelData

return flat, nil
}

func parsePatchPostSegment(offset uint32) (PatchPostSegment, int64, error) {
wp.checkValidByteReader()
wp.byteReader.Seek(int64(offset), io.SeekStart)
Expand Down Expand Up @@ -413,13 +510,30 @@ func (wl *WADLoader) ExportAllSprites(outputFolder string) error {
}
}

// Sprite exporting
for _, sprite := range wl.Sprites {
exportErr := ExportSprite(sprite, wl.Palettes[0], outputFolder)
if exportErr != nil {
return errors.New("[Error] ExportAllSprites: Cannot export sprite - " + sprite.Name + " - " + exportErr.Error())
}
}

// Patch sprite exporting
for _, patchSprites := range wl.Patches {
exportErr := ExportSprite(patchSprites, wl.Palettes[0], outputFolder)
if exportErr != nil {
return errors.New("[Error] ExportAllSprites: Cannot export patch sprite - " + patchSprites.Name + " - " + exportErr.Error())
}
}

// Flat exporting
for _, flat := range wl.Flats {
exportErr := ExportFlat(flat, wl.Palettes[0], outputFolder)
if exportErr != nil {
return errors.New("[Error] ExportAllSprites: Cannot export flat - " + flat.Name + " - " + exportErr.Error())
}
}

return nil
}

Expand Down Expand Up @@ -448,3 +562,24 @@ func ExportSprite(sprite Patch, palette Palette, outputFolder string) error {

return nil
}

func ExportFlat(flat Flat, palette Palette, outputFolder string) error {
flatImg := image.NewRGBA(image.Rect(0, 0, 64, 64))

for y := 0; y < 64; y++ {
for x := 0; x < 64; x++ {
pixelColor := palette[flat.PixelData[x + y * 64]]
flatImg.Set(x, y, color.RGBA{pixelColor.Red, pixelColor.Green, pixelColor.Blue, 255})
}
}

flatFile, err := os.Create(outputFolder + "/" + flat.Name + ".png")
if err != nil {
return errors.New("[Error] ExportFlat: Cannot create the target file for the flat - " + flat.Name + " - " + err.Error())
}

defer flatFile.Close()
png.Encode(flatFile, flatImg)

return nil
}
File renamed without changes.
File renamed without changes.
28 changes: 28 additions & 0 deletions wadloader/exportMusic.go → wadloader/music.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,36 @@ import (
"errors"
"io"
"os"
"strings"
)

func (wp *WADParser) getMusicFormatFromLump(lump *Lump) (string, error) {
wp.checkValidByteReader()

wp.byteReader.Seek(int64(lump.LumpOffset), io.SeekStart)

// Look for identification header
// ASCII = MTHD -> MIDI format
// ASCII = MUS -> MUS format

var header [4]byte
err := binary.Read(wp.byteReader, binary.LittleEndian, &header)

if err != nil {
return "Unknown", errors.New("[Error] getMusicFormatFromLump: Couldn't read music lump header")
}

musicFormat := string(header[:])

if strings.Contains(musicFormat, "MThd") {
return "MIDI", nil
} else if strings.Contains(musicFormat, "MUS") {
return "MUS", nil
}

return "Invalid", errors.New("[Error] getMusicFormatFromLump: Invalid music format detected")
}

func (wp *WADParser) ExportSong(song *MusicLump, outputFolder string) error {
wp.checkValidByteReader()
wp.byteReader.Seek(int64(song.lump.LumpOffset), io.SeekStart)
Expand Down
Loading

0 comments on commit b539563

Please sign in to comment.