experimental w.i.p spritesheet
This commit is contained in:
parent
ceaa5edcc6
commit
1ac214e971
3 changed files with 435 additions and 0 deletions
|
@ -30,6 +30,8 @@ type BaseCommand struct {
|
|||
MparPaxExtract MparPaxExtractCommand `command:"mpar-pax-extract" description:"extracts a single file from an pax'd mpar file"`
|
||||
MparPaxReplace MparPaxReplaceCommand `command:"mpar-pax-replace" description:"replaces a single file in a pax'd mpar file"`
|
||||
MparPaxInsert MparPaxInsertCommand `command:"mpar-pax-insert" description:"inserts a single file in a pax'd mpar file"`
|
||||
|
||||
MparSpritemapDump MparSpritemapDumpCommand `command:"mpar-sm-dump" description:"dumps sprites"`
|
||||
}
|
||||
|
||||
var MotoCLI BaseCommand
|
||||
|
|
433
commands/mpar-spritemap-dump.go
Normal file
433
commands/mpar-spritemap-dump.go
Normal file
|
@ -0,0 +1,433 @@
|
|||
package commands
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"encoding/hex"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
|
||||
"git.cheetah.cat/cheetah/moto-flash-data/flashpart"
|
||||
"github.com/rs/zerolog/log"
|
||||
)
|
||||
|
||||
type MparSpritemapDumpCommand struct {
|
||||
SourceFileName string `long:"file" short:"f" required:"true" description:"input-filename"`
|
||||
}
|
||||
|
||||
func writeBitmap(filename string, width, height int, pixelData []byte) error {
|
||||
// BMP Header constants
|
||||
fileHeaderSize := 14
|
||||
infoHeaderSize := 40
|
||||
bitsPerPixel := 24 // 3 bytes per pixel (RGB)
|
||||
rowPadding := (4 - (width*3)%4) % 4 // Rows are padded to multiples of 4 bytes
|
||||
imageSize := (width*3 + rowPadding) * height
|
||||
fileSize := fileHeaderSize + infoHeaderSize + imageSize
|
||||
|
||||
// Create BMP file
|
||||
file, err := os.Create(filename)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
// BMP File Header
|
||||
fileHeader := []byte{
|
||||
'B', 'M', // Signature
|
||||
0, 0, 0, 0, // File size (placeholder)
|
||||
0, 0, // Reserved
|
||||
0, 0, // Reserved
|
||||
54, 0, 0, 0, // Offset to pixel data
|
||||
}
|
||||
binary.LittleEndian.PutUint32(fileHeader[2:], uint32(fileSize))
|
||||
|
||||
// BMP Info Header
|
||||
infoHeader := make([]byte, infoHeaderSize)
|
||||
binary.LittleEndian.PutUint32(infoHeader[0:], uint32(infoHeaderSize)) // Header size
|
||||
binary.LittleEndian.PutUint32(infoHeader[4:], uint32(width)) // Image width
|
||||
binary.LittleEndian.PutUint32(infoHeader[8:], uint32(height)) // Image height
|
||||
binary.LittleEndian.PutUint16(infoHeader[12:], 1) // Planes
|
||||
binary.LittleEndian.PutUint16(infoHeader[14:], uint16(bitsPerPixel)) // Bits per pixel
|
||||
binary.LittleEndian.PutUint32(infoHeader[20:], uint32(imageSize)) // Image size
|
||||
|
||||
// Write headers to file
|
||||
if _, err := file.Write(fileHeader); err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err := file.Write(infoHeader); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Write pixel data with row padding
|
||||
for y := height - 1; y >= 0; y-- { // BMP rows are bottom to top
|
||||
rowStart := y * width * 3
|
||||
rowEnd := rowStart + width*3
|
||||
row := pixelData[rowStart:rowEnd]
|
||||
|
||||
// Write row data
|
||||
if _, err := file.Write(row); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Write padding
|
||||
padding := make([]byte, rowPadding)
|
||||
if _, err := file.Write(padding); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func writeBitmapRGB565(filename string, width, height int, pixelData []uint16) error {
|
||||
// BMP Header constants
|
||||
fileHeaderSize := 14
|
||||
infoHeaderSize := 40
|
||||
bitsPerPixel := 16 // 16 bits per pixel for RGB565
|
||||
rowPadding := (4 - (width*2)%4) % 4 // Rows are padded to multiples of 4 bytes
|
||||
imageSize := (width*2 + rowPadding) * height
|
||||
fileSize := fileHeaderSize + infoHeaderSize + imageSize
|
||||
|
||||
// Create BMP file
|
||||
file, err := os.Create(filename)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
// BMP File Header
|
||||
fileHeader := []byte{
|
||||
'B', 'M', // Signature
|
||||
0, 0, 0, 0, // File size (placeholder)
|
||||
0, 0, // Reserved
|
||||
0, 0, // Reserved
|
||||
54, 0, 0, 0, // Offset to pixel data
|
||||
}
|
||||
binary.LittleEndian.PutUint32(fileHeader[2:], uint32(fileSize))
|
||||
|
||||
// BMP Info Header
|
||||
infoHeader := make([]byte, infoHeaderSize)
|
||||
binary.LittleEndian.PutUint32(infoHeader[0:], uint32(infoHeaderSize)) // Header size
|
||||
binary.LittleEndian.PutUint32(infoHeader[4:], uint32(width)) // Image width
|
||||
binary.LittleEndian.PutUint32(infoHeader[8:], uint32(height)) // Image height
|
||||
binary.LittleEndian.PutUint16(infoHeader[12:], 1) // Planes
|
||||
binary.LittleEndian.PutUint16(infoHeader[14:], uint16(bitsPerPixel)) // Bits per pixel
|
||||
binary.LittleEndian.PutUint32(infoHeader[20:], uint32(imageSize)) // Image size
|
||||
|
||||
// Write headers to file
|
||||
if _, err := file.Write(fileHeader); err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err := file.Write(infoHeader); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Write pixel data with row padding
|
||||
for y := height - 1; y >= 0; y-- { // BMP rows are bottom to top
|
||||
rowStart := y * width
|
||||
rowEnd := rowStart + width
|
||||
row := pixelData[rowStart:rowEnd]
|
||||
|
||||
// Write row data
|
||||
for _, pixel := range row {
|
||||
if err := binary.Write(file, binary.LittleEndian, pixel); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// Write padding
|
||||
padding := make([]byte, rowPadding)
|
||||
if _, err := file.Write(padding); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
func writeBitmapRGB565Bytes(filename string, width, height int, pixelData []byte) error {
|
||||
// BMP Header constants
|
||||
fileHeaderSize := 14
|
||||
infoHeaderSize := 40
|
||||
bitsPerPixel := 16 // 16 bits per pixel for RGB565
|
||||
rowPadding := (4 - (width*2)%4) % 4 // Rows are padded to multiples of 4 bytes
|
||||
imageSize := len(pixelData) // (width*2 + rowPadding) * height
|
||||
fileSize := fileHeaderSize + infoHeaderSize + imageSize
|
||||
|
||||
// Create BMP file
|
||||
file, err := os.Create(filename)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
// BMP File Header
|
||||
fileHeader := []byte{
|
||||
'B', 'M', // Signature
|
||||
0, 0, 0, 0, // File size (placeholder)
|
||||
0, 0, // Reserved
|
||||
0, 0, // Reserved
|
||||
54, 0, 0, 0, // Offset to pixel data
|
||||
}
|
||||
binary.LittleEndian.PutUint32(fileHeader[2:], uint32(fileSize))
|
||||
|
||||
// BMP Info Header
|
||||
infoHeader := make([]byte, infoHeaderSize)
|
||||
binary.LittleEndian.PutUint32(infoHeader[0:], uint32(infoHeaderSize)) // Header size
|
||||
binary.LittleEndian.PutUint32(infoHeader[4:], uint32(width)) // Image width
|
||||
binary.LittleEndian.PutUint32(infoHeader[8:], uint32(height)) // Image height
|
||||
binary.LittleEndian.PutUint16(infoHeader[12:], 1) // Planes
|
||||
binary.LittleEndian.PutUint16(infoHeader[14:], uint16(bitsPerPixel)) // Bits per pixel
|
||||
binary.LittleEndian.PutUint32(infoHeader[20:], uint32(imageSize)) // Image size
|
||||
|
||||
// Write headers to file
|
||||
if _, err := file.Write(fileHeader); err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err := file.Write(infoHeader); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Write pixel data with row padding
|
||||
for y := height - 1; y >= 0; y-- { // BMP rows are bottom to top
|
||||
rowStart := y * width * 2
|
||||
rowEnd := rowStart + width*2
|
||||
row := pixelData[rowStart:rowEnd]
|
||||
|
||||
// Write row data
|
||||
if _, err := file.Write(row); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Write padding
|
||||
padding := make([]byte, rowPadding)
|
||||
if _, err := file.Write(padding); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (command *MparSpritemapDumpCommand) Execute(args []string) error {
|
||||
inputFile, err := os.Open(command.SourceFileName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer inputFile.Close()
|
||||
|
||||
inputFileStat, err := inputFile.Stat()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Info().Int64("fileSize", inputFileStat.Size()).Msg("Reading raw file...")
|
||||
pdata := make([]byte, inputFileStat.Size())
|
||||
_, err = io.ReadFull(inputFile, pdata)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fpHeader := flashpart.ParseFlashPartHeader(pdata[:32])
|
||||
log.Info().Msg(
|
||||
fmt.Sprintf("Media-ID: 0x%02X, Partition Size: 0x%08X / %d bytes, Partition Tag: %s",
|
||||
fpHeader.MediaID,
|
||||
fpHeader.TotalSize,
|
||||
fpHeader.TotalSize,
|
||||
fpHeader.VersionText,
|
||||
),
|
||||
)
|
||||
log.Info().Msg(
|
||||
fmt.Sprintf("Original-Full-Header-Hex: %s", hex.EncodeToString(pdata[:32])),
|
||||
)
|
||||
|
||||
if len(pdata[32:]) != len(pdata)-32 {
|
||||
return errors.New("something doesnt add up")
|
||||
}
|
||||
if len(pdata[32:]) != int(fpHeader.TotalSize)-32 {
|
||||
log.Error().Uint32("header ts", fpHeader.TotalSize).Uint32("len pdata", uint32(len(pdata))).Msg("size mismatch")
|
||||
return nil
|
||||
}
|
||||
|
||||
breader := bytes.NewReader(pdata[32:])
|
||||
// RGB565
|
||||
// 16 byte initial offset
|
||||
// each image 13 x 13
|
||||
|
||||
{
|
||||
header := make([]byte, 380)
|
||||
breader.Read(header)
|
||||
fmt.Println(header)
|
||||
}
|
||||
{
|
||||
// 42
|
||||
// 338 + 42 = 380
|
||||
// + 42 = 718 = wrong
|
||||
// + 12 = 730
|
||||
// + 338 = 1068 = wrong
|
||||
// + 6 = 1074
|
||||
// + 338 = 1412 = wrong
|
||||
// + 8 = 1420
|
||||
// + 338 = 1758 = wrong
|
||||
// + 6 = 1762
|
||||
// + 338 = 2100 = wrong
|
||||
// + 6 = 2106
|
||||
// + 338 = 2444 = wrong
|
||||
|
||||
// + 22 =
|
||||
// + 338 = 2804 = wrong
|
||||
// + 6 = 2810
|
||||
// + 338 = 3148 = wrong
|
||||
// + 6 = 3154
|
||||
// + 338 = 3492 = wrong
|
||||
// + 6 = 3498
|
||||
// + 338 = 3836 = wrong
|
||||
// + 6 = 3842
|
||||
// + 338 = 4180 = wrong
|
||||
// + 6 = 4186
|
||||
// + 338 = 4524 = wrong
|
||||
// + 6 = 4530
|
||||
// + 338 = 4868 = wrong
|
||||
// + 6 = 4874
|
||||
// + 338 = 5212 = wrong
|
||||
// + 6 = 5218
|
||||
// + 338 = 5556 = wrong
|
||||
// + 6 = 5562
|
||||
// ..
|
||||
// + 344 = 5906
|
||||
// + 344 = 6250 = ???
|
||||
// + 344 = 6594 = wrong
|
||||
// - 6 = 6568
|
||||
// + 344 = 6912
|
||||
// + 344 = 7256
|
||||
// + 344 = 7600 = wrong
|
||||
// = 7892 = ?
|
||||
// = 7944 = right?
|
||||
// + 292 = 8236 = right!
|
||||
// + 338 = 8574 = wrong
|
||||
// + 6 = 8580
|
||||
// + 344 = 8924
|
||||
// + 344 = 9268
|
||||
// + 344 = 9612
|
||||
// + 344 = 9956
|
||||
// + 344 = 10300 = wrong
|
||||
// + 266 = 10566
|
||||
// + 344 = 10910 = wrong
|
||||
// + 16 = 10926
|
||||
// + 344+16 = 11270
|
||||
// + 344 = 11614
|
||||
// + 344 = 11958
|
||||
// + 344 = 12302
|
||||
// + 344 = 12646
|
||||
// + 344 = 12990
|
||||
// + 344 = 13334
|
||||
// + 344 = 13678
|
||||
// + 344 = 14022
|
||||
// + 344 = 14366
|
||||
// + 344 = 14710
|
||||
// + 344 = 15054 gps
|
||||
// + 344 = 15398 alarm
|
||||
// + 344 = 15742 ??? = WRONG?
|
||||
// 16086 = wrong
|
||||
// 16774 = wrong
|
||||
// 16858 check-green
|
||||
// 17202 7x13px Tower
|
||||
// 17390 13x13px lock
|
||||
// 17734 14x13 dmo-icon
|
||||
// 18130 13x12 abc-input-mode
|
||||
// 18448 13x13 save-icon
|
||||
// 18792 13x13 dial-icon
|
||||
// + 344
|
||||
// 19136 13x13 msgicon1
|
||||
// + 344
|
||||
// 19480 13x14 alarm-clock-icon
|
||||
// + 344
|
||||
// 19824 13x13 clock-icon
|
||||
// + 344
|
||||
// 20168 13x13 msg-forward-read icon
|
||||
// + 344
|
||||
// 20512 13x13 msg-forward-unread icon
|
||||
// + 344
|
||||
// 20856 13x13 green-left-arrow
|
||||
// + 344
|
||||
// 21200 13x13 blue-triangle
|
||||
// + 344
|
||||
// 21544 13x13 hourglass
|
||||
// + 344
|
||||
// 21888 13x13 idk-icon
|
||||
// + 344
|
||||
// 22232 13x13 idk-icon
|
||||
// + 344
|
||||
// 22576 13x13 idk-icon
|
||||
// + 344
|
||||
// 22920
|
||||
// + 344
|
||||
// 23264
|
||||
// + 344
|
||||
// 23608
|
||||
// + 344
|
||||
// 23952
|
||||
// 24296
|
||||
// 24640
|
||||
// 24984
|
||||
// 25328
|
||||
// 25672
|
||||
// 26016 14x12 abc-input-icon
|
||||
// + 370
|
||||
// 26386 14x12 normal-case
|
||||
// + 370
|
||||
// 26756 14x12 normal-case
|
||||
// + 370
|
||||
// 27126 14x12 numbers-input
|
||||
// + 370
|
||||
// 27496 14x12 at-input
|
||||
// +370
|
||||
// 27866 14x12 'I'
|
||||
// +370
|
||||
// 28236 14x12 'I' UP
|
||||
// +370
|
||||
// 28606 14x12 'I' UPUP
|
||||
// +370
|
||||
// 28976 14x12 '2'
|
||||
|
||||
PICTURE := 16
|
||||
pictoHead := make([]byte, 6)
|
||||
for i := 0; i < PICTURE; i++ {
|
||||
breader.Read(pictoHead)
|
||||
width := binary.LittleEndian.Uint16(pictoHead[0:2])
|
||||
height := binary.LittleEndian.Uint16(pictoHead[2:4])
|
||||
magic := binary.LittleEndian.Uint16(pictoHead[4:6])
|
||||
log.Info().Uint16("width", width).Uint16("height", height).Msg("found pic")
|
||||
firstPic := make([]byte, width*height*2)
|
||||
breader.Read(firstPic)
|
||||
fmt.Println(magic)
|
||||
writeBitmapRGB565Bytes(fmt.Sprintf("debug/%02d.bmp", i), int(width), int(height), firstPic)
|
||||
}
|
||||
}
|
||||
|
||||
// tarReader := tar.NewReader(breader)
|
||||
|
||||
// for {
|
||||
// header, err := tarReader.Next()
|
||||
// if err == io.EOF {
|
||||
// break
|
||||
// }
|
||||
|
||||
// if err != nil {
|
||||
// log.Error().Err(err)
|
||||
// break
|
||||
// }
|
||||
// fmt.Println(header)
|
||||
|
||||
// // if header.Typeflag == tar.TypeReg && !strings.Contains(header.Name, "._") {
|
||||
// // // content, err := io.ReadAll(tarReader)
|
||||
// // // if err != nil {
|
||||
// // // log.Error().Err(err)
|
||||
// // // }
|
||||
|
||||
// // fmt.Println("FILE_NAME: ", header.Name)
|
||||
// // ///fmt.Println(string(content))
|
||||
// // }
|
||||
// }
|
||||
return nil
|
||||
}
|
BIN
spritemap/sprite-reverse.hexproj
Normal file
BIN
spritemap/sprite-reverse.hexproj
Normal file
Binary file not shown.
Loading…
Add table
Reference in a new issue