tools: switch tileset storage format to 2 bits per pixel

This commit is contained in:
Zack Buhman 2023-07-25 00:05:48 +00:00
parent 85e02abc17
commit f764b4ef0d
4 changed files with 85 additions and 49 deletions

View File

@ -9,7 +9,7 @@ DEP = $(patsubst %.o,%.d,$(SRC))
res = $(subst pokered/,res/,$(patsubst %.$(1),%.$(1).o,$(wildcard $(2)*.$(1))))
res_png = $(subst pokered/,res/,$(patsubst %.png,%.$(1).o,$(wildcard $(2)*.png)))
GFX_TILESETS = $(call res_png,4bpp,pokered/gfx/tilesets/)
GFX_TILESETS = $(call res_png,2bpp,pokered/gfx/tilesets/)
GFX_BLOCKSETS = $(call res,bst,pokered/gfx/blocksets/)
MAPS_BLOCKS = $(call res,blk,pokered/maps/)
@ -28,14 +28,14 @@ endef
generated: $(GENERATED)
res/%.4bpp: pokered/%.png
res/%.2bpp: pokered/%.png
@mkdir -p $(dir $@)
python tools/png_to_4bpp.py $< $@
python tools/png_to_nbpp.py $< 2 $@
%.4bpp.h:
%.2bpp.h:
$(BUILD_BINARY_H)
%.4bpp.o: %.4bpp %.4bpp.h
%.2bpp.o: %.2bpp %.2bpp.h
$(BUILD_BINARY_O)
res/%.blk: pokered/%.blk

View File

@ -23,12 +23,28 @@ void palette_data()
uint32_t cell_data(const start_size_t& buf, const uint32_t top)
{
// round to nearest multiple of 32
const uint32_t table_size = (buf.size + 0x20 - 1) & (-0x20);
const uint32_t table_size = ((buf.size * 2) + 0x20 - 1) & (-0x20);
const uint32_t base_address = top - table_size; // in bytes
copy<uint32_t>(&vdp2.vram.u32[(base_address / 4)],
reinterpret_cast<uint32_t const * const>(buf.start),
buf.size);
uint32_t * vram = &vdp2.vram.u32[(base_address / 4)];
for (uint32_t ix = 0; ix < buf.size / 4; ix += 1) {
const uint32_t pixels = reinterpret_cast<uint32_t const * const>(buf.start)[ix];
const uint32_t px0 = pixels >> 16 & 0xffff;
const uint32_t px1 = pixels >> 0 & 0xffff;
#define lshift(n) ((7 - n) * 2)
#define rshift(n) ((7 - n) * 4)
#define px(p, n) (((p >> lshift(n)) & 0b11) << rshift(n))
#define p0(n) (px(px0, n))
#define p1(n) (px(px1, n))
vram[ix * 2 + 0] = p0(7) | p0(6) | p0(5) | p0(4) | p0(3) | p0(2) | p0(1) | p0(0);
vram[ix * 2 + 1] = p1(7) | p1(6) | p1(5) | p1(4) | p1(3) | p1(2) | p1(1) | p1(0);
#undef p1
#undef p0
#undef px
#undef lshift
#undef rshift
}
return base_address;
}
@ -115,7 +131,7 @@ void main()
vdp2.reg.MPABN0 = MPABN0__N0MPB(0) | MPABN0__N0MPA(plane_a); // bits 5~0
vdp2.reg.MPCDN0 = MPABN0__N0MPD(0) | MPABN0__N0MPC(0); // bits 5~0
uint32_t top = (sizeof (union vdp2_vram));// - ((sizeof (union vdp2_vram)) / 8);
uint32_t top = (sizeof (union vdp2_vram));
palette_data();
uint32_t base_address = top = cell_data(tilesets[tileset_t::overworld].tileset, top);
uint32_t base_pattern = base_address / 32;

View File

@ -1,39 +0,0 @@
import sys
from PIL import Image
def two_bpp_index(px):
indices = {0x00: 0, 0x55: 1, 0xaa: 2, 0xff: 3}
assert px in indices, px
return indices[px]
def convert(image):
assert image.mode == 'L', image.mode
width, height = image.size
buf = bytearray(width * height // 2)
for cell_y in range(height//8):
for cell_x in range(width//8):
for y in range(8):
for x in range(8):
px = im.getpixel((cell_x * 8 + x, cell_y * 8 + y))
index = two_bpp_index(px)
buf_ix = x//2 + (4 * (cell_x * 8 + (cell_y * width) + y))
buf[buf_ix] |= (index << 4 * (1 - (x % 2)))
return buf
def debug(buf):
for row in range(len(buf) // 4):
for x in range(4):
px = buf[row * 4 + x]
print((px >> 4) & 0xf, end='')
print((px >> 0) & 0xf, end='')
print()
if (row % 8 == 7):
print()
im = Image.open(sys.argv[1])
buf = convert(im)
with open(sys.argv[2], 'wb') as f:
f.write(buf)

59
tools/png_to_nbpp.py Normal file
View File

@ -0,0 +1,59 @@
import os
import sys
from PIL import Image
def intensity_to_index(px):
indices = {0x00: 0, 0x55: 1, 0xaa: 2, 0xff: 3}
assert px in indices, px
return indices[px]
def convert(image, bpp):
assert bpp in {8, 4, 2}, bpp
px_per_byte = 8 // bpp
px_per_row = 8
bits_per_byte = 8
bytes_per_row = (px_per_row // (bits_per_byte // bpp))
assert image.mode == 'L', image.mode
width, height = image.size
buf = bytearray(width * height // px_per_byte)
for cell_y in range(height//8):
for cell_x in range(width//8):
for y in range(8):
for x in range(8):
px = im.getpixel((cell_x * 8 + x, cell_y * 8 + y))
index = intensity_to_index(px)
buf_ix = x//px_per_byte + (bytes_per_row * (cell_x * 8 + (cell_y * width) + y))
buf[buf_ix] |= (index << bpp * ((px_per_byte - 1) - (x % px_per_byte)))
return buf
def debug(buf, bpp):
assert bpp in {8, 4, 2}, bpp
px_per_byte = 8 // bpp
px_per_row = 8
bits_per_byte = 8
bytes_per_row = (px_per_row // (bits_per_byte // bpp))
bit_mask = (2 ** bpp) - 1
for row in range(len(buf) // bytes_per_row):
for x in range(bytes_per_row):
px = buf[row * bytes_per_row + x]
for shift in reversed(range(0, px_per_row, bpp)):
print((px >> shift) & bit_mask, end='')
print()
if (row % 8 == 7):
print()
in_path = sys.argv[1]
bpp = int(sys.argv[2])
out_path = sys.argv[3]
im = Image.open(in_path)
buf = convert(im, bpp)
if 'NBPP_DEBUG' in os.environ:
debug(buf, bpp)
with open(out_path, 'wb') as f:
f.write(buf)