Skip to content

Commit 7dbcaae

Browse files
committed
nds: create dedicated tilemap renderer
I noticed I had a LOT of duplicate code lying around. Now I have gotten rid of it, and consolidated all the tilemap rendering to a single type.
1 parent dfe8e93 commit 7dbcaae

File tree

10 files changed

+245
-160
lines changed

10 files changed

+245
-160
lines changed

example/nds/explore/runner.go

Lines changed: 0 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,7 @@ import (
1414

1515
"github.com/sukus21/nintil/compression/lz10"
1616
"github.com/sukus21/nintil/compression/rlz"
17-
"github.com/sukus21/nintil/nds"
1817
"github.com/sukus21/nintil/util"
19-
"github.com/sukus21/nintil/util/ezbin"
2018
)
2119

2220
type RunnerFunc func(r *Runner) any
@@ -309,36 +307,3 @@ func drawImgBitmap(w int, h int, t4bpp bool, gfx *bytes.Reader, pal color.Palett
309307

310308
return img
311309
}
312-
313-
func drawImgTilemap(w int, h int, tls []nds.Tile, tlm *bytes.Reader, pal color.Palette) image.Image {
314-
img := image.NewPaletted(
315-
image.Rect(0, 0, w*8, h*8),
316-
pal,
317-
)
318-
319-
xt := 0
320-
yt := 0
321-
for i := 0; i < int(tlm.Size())/2 && yt < h; i++ {
322-
raw := ezbin.ReadSingle[uint16](tlm)
323-
tileId := raw & 0x3FF
324-
tileMirror := raw&0x0400 != 0
325-
tileFlip := raw&0x0800 != 0
326-
// tilePal := int(raw >> 12)
327-
328-
tile := &tls[tileId]
329-
x := xt * 8
330-
y := yt * 8
331-
xt++
332-
if xt >= w {
333-
xt = 0
334-
yt++
335-
}
336-
nds.DrawTileSamePalette(
337-
img, tile,
338-
x, y,
339-
tileMirror, tileFlip,
340-
)
341-
}
342-
343-
return img
344-
}

example/nds/explore/runner_funcs.go

Lines changed: 38 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77
"image"
88
"io"
99
"os"
10+
"path/filepath"
1011

1112
"github.com/sukus21/nintil/nds"
1213
"github.com/sukus21/nintil/nds/pit"
@@ -45,22 +46,22 @@ func addNdsFuncs(r *Runner) {
4546

4647
// Explain whats here at given ROM address
4748
// - uint32 address
48-
// + string
4949
r.AddFunc("here", func(r *Runner) any {
5050
addr := ReadArg[uint32](r)
5151
rom := ReadVar[*nds.Rom](r, "nds")
5252
entry := rom.WhatsHere(addr)
5353
if entry == nil {
54-
return "address not mapped"
54+
fmt.Println("address not mapped")
5555
} else {
56-
return fmt.Sprintf(
56+
fmt.Printf(
5757
"%s [0x%X] [0x%X - 0x%X]\n",
5858
entry.Name(),
5959
addr-entry.From(),
6060
entry.From(),
6161
entry.From()+entry.To(),
6262
)
6363
}
64+
return nil
6465
})
6566

6667
// Opens a .dat entry from memory
@@ -84,12 +85,39 @@ func addNdsFuncs(r *Runner) {
8485

8586
// Opens a .dat entry
8687
// - int index
88+
// + []byte
8789
r.AddFunc("dat", func(r *Runner) any {
8890
index := ReadArg[int](r)
8991
dat := ReadVar[[][]byte](r, "dat_open")
9092
return dat[index]
9193
})
9294

95+
// Get number of entries in a .dat
96+
r.AddFunc("dat_len", func(r *Runner) any {
97+
dat := ReadVar[[][]byte](r, "dat_open")
98+
fmt.Println(len(dat))
99+
return nil
100+
})
101+
102+
// Dump a .dat archive completely
103+
// - string number of folder to dump to
104+
r.AddFunc("dat_dump", func(r *Runner) any {
105+
dat := ReadVar[[][]byte](r, "dat_open")
106+
fname := ReadArg[string](r)
107+
os.MkdirAll(fname, os.ModePerm)
108+
_, basename := filepath.Split(fname)
109+
for i := range dat {
110+
os.WriteFile(
111+
filepath.Join(fname, fmt.Sprintf("%s_%d.bin", basename, i)),
112+
dat[i],
113+
os.ModePerm,
114+
)
115+
}
116+
117+
fmt.Println(".dat dumped")
118+
return nil
119+
})
120+
93121
// Get bitmap image from data
94122
// - int width
95123
// - int height
@@ -131,7 +159,9 @@ func addNdsFuncs(r *Runner) {
131159
panic("unknown bitdepth for timemap, only 4 and 8 supported")
132160
}
133161

134-
return drawImgTilemap(w, h, tls, tlm, pal)
162+
img := nds.NewTilemap(w, h, tls, pal)
163+
binary.Read(tlm, binary.LittleEndian, img.Attributes)
164+
return img
135165
})
136166

137167
// Get tilemap image from data
@@ -162,10 +192,12 @@ func addNdsFuncs(r *Runner) {
162192
for i := range tls {
163193
binary.LittleEndian.PutUint16(tlmbuf[i*2:], uint16(i))
164194
}
195+
tlm := bytes.NewReader(tlmbuf)
165196

166197
// Yup, do thing
167-
tlm := bytes.NewReader(tlmbuf)
168-
return drawImgTilemap(w, h, tls, tlm, pal)
198+
img := nds.NewTilemap(w, h, tls, pal)
199+
binary.Read(tlm, binary.LittleEndian, img.Attributes)
200+
return img
169201
})
170202

171203
// Exports a palette

example/nds/pit/dump/main.go

Lines changed: 26 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,15 @@
11
package main
22

33
import (
4+
"encoding/binary"
45
"fmt"
5-
"io"
6-
"io/fs"
76
"log"
87
"os"
98
"path/filepath"
9+
"strconv"
1010

11+
"github.com/sukus21/nintil/compression/lz10"
12+
"github.com/sukus21/nintil/compression/rlz"
1113
"github.com/sukus21/nintil/nds"
1214
"github.com/sukus21/nintil/nds/pit"
1315
"github.com/sukus21/nintil/util"
@@ -22,37 +24,30 @@ func main() {
2224
defer f.Close()
2325
rom := util.Must1(nds.OpenROM(f))
2426

25-
// Dump NitroFS filesystem
26-
util.Must(fs.WalkDir(rom.Filesystem, ".", func(path string, d fs.DirEntry, err error) error {
27-
if err != nil || d.IsDir() {
28-
return err
29-
}
30-
31-
// Create directory for file
32-
outPath := filepath.Join("nitrofs", path)
33-
dname := filepath.Dir(outPath)
34-
util.Must(os.MkdirAll(dname, os.ModePerm))
35-
36-
// Read file contents
37-
nitroFile := util.Must1(rom.Filesystem.Open(path))
38-
fileContent := util.Must1(io.ReadAll(nitroFile))
39-
nitroFile.Close()
27+
// Dump ARM9 binary in the stupidest way probably
28+
fout := util.Must1(os.Create("arm9.s"))
29+
defer fout.Close()
30+
for i := 0; i < len(rom.Arm9Binary); i += 4 {
31+
fmt.Fprintf(fout, " .word 0x%08X\n", binary.LittleEndian.Uint32(rom.Arm9Binary[i:]))
32+
}
33+
}
4034

41-
// Just dump regular files
42-
if filepath.Ext(path) != ".dat" || !pit.IsDat(fileContent) {
43-
util.Must(os.WriteFile(outPath, fileContent, os.ModePerm))
44-
return nil
35+
func writeFile(fname string, content []byte) error {
36+
if pit.IsDat(content) {
37+
util.Must(os.MkdirAll(fname, os.ModePerm))
38+
for i, content := range pit.UnpackDat(content) {
39+
outPath := filepath.Join(fname, strconv.Itoa(i))
40+
util.Must(writeFile(outPath, content))
4541
}
42+
return nil
43+
}
4644

47-
// .dat file, NOW we are cooking!
48-
datPath := outPath
49-
util.Must(os.Mkdir(datPath, os.ModePerm))
50-
for i, content := range pit.UnpackDat(fileContent) {
51-
outPath := filepath.Join(datPath, fmt.Sprintf("%d", i))
52-
util.Must(os.WriteFile(outPath, content, os.ModePerm))
53-
}
45+
if decomp, err := rlz.Decompress(content); err == nil {
46+
return os.WriteFile(fname+".rlz", decomp, os.ModePerm)
47+
}
48+
if decomp, err := lz10.Decompress(content); err == nil {
49+
return os.WriteFile(fname+".lz10", decomp, os.ModePerm)
50+
}
5451

55-
// Yup, all good
56-
return nil
57-
}))
52+
return os.WriteFile(fname, content, os.ModePerm)
5853
}

example/nds/pit/savephotos/main.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import (
1111
)
1212

1313
func main() {
14-
if len(os.Args) < 2 {
14+
if len(os.Args) != 2 {
1515
fmt.Println("usage:", os.Args[0], "<PiT ROM path>")
1616
return
1717
}
@@ -20,8 +20,8 @@ func main() {
2020
defer f.Close()
2121
rom := util.Must1(nds.OpenROM(f))
2222

23-
util.Must(os.MkdirAll("savephoto", os.ModePerm))
24-
for i := 0; i < 10; i++ {
23+
util.Must(os.MkdirAll("savephotos", os.ModePerm))
24+
for i := range 10 {
2525
img := pit.DecodeSavePhoto(rom, i)
2626
ipath := fmt.Sprintf("savephotos/%d.png", i)
2727
outf := util.Must1(os.Create(ipath))

nds/banner.go

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,7 @@ func SerializeIcon(src image.Image) ([]byte, image.PalettedImage, error) {
147147
tiles := make([]Tile, 16)
148148
for i := range tiles {
149149
t := &tiles[i]
150-
for j := 0; j < 64; j++ {
150+
for j := range 64 {
151151
x := 8*(i&3) + (j & 7)
152152
y := 8*(i>>2) + (j >> 3)
153153
if !isPaletted {
@@ -228,12 +228,10 @@ func OpenBanner(r io.Reader) (*banner, error) {
228228
tiles := DeserializeTiles4BPP(tilesRaw)
229229

230230
// Turn into one big image
231-
icon := image.NewPaletted(image.Rect(0, 0, 32, 32), palette)
231+
icon := NewTilemap(4, 4, tiles, palette)
232232
b.icon = icon
233-
for i := range tiles {
234-
x := (i & 3) * 8
235-
y := (i >> 2) * 8
236-
DrawTileSamePalette(icon, &tiles[i], x, y, false, false)
233+
for i := range icon.Attributes {
234+
icon.Attributes[i] = TilemapAttributes(i)
237235
}
238236

239237
// Read titles

0 commit comments

Comments
 (0)