background: add support for 7shades output
This commit is contained in:
parent
0f4f1b69a9
commit
134edfa010
31
7shades_binary_spec.txt
Normal file
31
7shades_binary_spec.txt
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
|
||||||
|
- 32 byte header that is read as 8 longword values as follows:
|
||||||
|
|
||||||
|
struct {
|
||||||
|
uint32_t file_type_id; // must be the constant value "0x00000005"
|
||||||
|
uint32_t size_of_cel_data; // bytes
|
||||||
|
uint32_t size_of_map_data; // bytes
|
||||||
|
uint32_t tile_character_size; // (slChar) one of CHAR_SIZE_*
|
||||||
|
|
||||||
|
uint32_t tile_color_mode; // (slChar) one of COL_TYPE_*
|
||||||
|
uint32_t plane_size; // (slPlane) one of PL_SIZE_*
|
||||||
|
uint32_t map_data; // (slPage) one of PNB_*, one of CN_*
|
||||||
|
|
||||||
|
uint16_t height; // must be the constant value "1"
|
||||||
|
uint16_t width; // must be the constant value "1"
|
||||||
|
}
|
||||||
|
|
||||||
|
-A file type ID - arbitrarily chosen as [5] for this binary type
|
||||||
|
-# of bytes of Cel Data in binary
|
||||||
|
-# of bytes of Map Data in binary
|
||||||
|
-Tile Character Size (Macros defined in sl_def.h)
|
||||||
|
-Tile Character Color Mode (Macros defined in sl_def.h)
|
||||||
|
-Plane Unit Size (Macros defined in sl_def.h)
|
||||||
|
-Map data config (Macros defined in sl_def.h)
|
||||||
|
-Plane dimensions (Height<<16|Width)
|
||||||
|
|
||||||
|
- Pallet data block of 0, 32, or 512 bytes based on the color mode indicated in header
|
||||||
|
|
||||||
|
- Map data block of size indicated in header
|
||||||
|
|
||||||
|
- Cel data block of size indicated in header
|
||||||
146
background.py
146
background.py
@ -1,3 +1,4 @@
|
|||||||
|
import io
|
||||||
import sys
|
import sys
|
||||||
from pprint import pprint, pformat
|
from pprint import pprint, pformat
|
||||||
import textwrap
|
import textwrap
|
||||||
@ -27,21 +28,18 @@ def pack_old_palette_chunk(old_palette_chunk):
|
|||||||
for color in old_palette_chunk.packets[0].colors:
|
for color in old_palette_chunk.packets[0].colors:
|
||||||
f.write(pack_bgr555(*color))
|
f.write(pack_bgr555(*color))
|
||||||
|
|
||||||
def pack_palette_chunk(palette_chunk):
|
def pack_palette_chunk(f, palette_chunk):
|
||||||
with open("palette.bin", "wb") as f:
|
|
||||||
assert palette_chunk.first_color_index_to_change == 0
|
assert palette_chunk.first_color_index_to_change == 0
|
||||||
|
|
||||||
for entry in palette_chunk.entries:
|
for entry in palette_chunk.entries:
|
||||||
color = (entry.red, entry.green, entry.blue)
|
color = (entry.red, entry.green, entry.blue)
|
||||||
f.write(pack_bgr555(*color))
|
f.write(pack_bgr555(*color))
|
||||||
|
|
||||||
print("palette.bin", f.tell(), file=sys.stderr)
|
def pack_palette(f, palette):
|
||||||
|
|
||||||
def pack_palette(palette):
|
|
||||||
if type(palette) is PaletteChunk:
|
if type(palette) is PaletteChunk:
|
||||||
pack_palette_chunk(palette)
|
pack_palette_chunk(f, palette)
|
||||||
elif type(palette) is OldPaletteChunk:
|
elif type(palette) is OldPaletteChunk:
|
||||||
pack_old_palette_chunk(palette)
|
pack_old_palette_chunk(f, palette)
|
||||||
else:
|
else:
|
||||||
assert False, type(palette)
|
assert False, type(palette)
|
||||||
|
|
||||||
@ -82,8 +80,7 @@ def pack_character_1x1(tileset_chunk, offset):
|
|||||||
|
|
||||||
return bytes(buf)
|
return bytes(buf)
|
||||||
|
|
||||||
def pack_character_patterns(filename, tileset_chunk):
|
def pack_character_patterns(f, tileset_chunk):
|
||||||
with open(filename, "wb") as f:
|
|
||||||
for i in range(tileset_chunk.number_of_tiles):
|
for i in range(tileset_chunk.number_of_tiles):
|
||||||
offset = tileset_chunk.tile_width * tileset_chunk.tile_height * i
|
offset = tileset_chunk.tile_width * tileset_chunk.tile_height * i
|
||||||
|
|
||||||
@ -96,10 +93,7 @@ def pack_character_patterns(filename, tileset_chunk):
|
|||||||
|
|
||||||
f.write(buf)
|
f.write(buf)
|
||||||
|
|
||||||
print(filename, f.tell(), file=sys.stderr)
|
def pack_pattern_name_table(f, cel_chunk, x_cells, y_cells):
|
||||||
|
|
||||||
def pack_pattern_name_table(filename, cel_chunk, x_cells, y_cells):
|
|
||||||
with open(filename, "wb") as f:
|
|
||||||
assert type(cel_chunk.data) == CelChunk_CompressedTilemap
|
assert type(cel_chunk.data) == CelChunk_CompressedTilemap
|
||||||
#assert cel_chunk.data.width_in_number_of_tiles <= 64
|
#assert cel_chunk.data.width_in_number_of_tiles <= 64
|
||||||
#assert cel_chunk.data.height_in_number_of_tiles <= 64
|
#assert cel_chunk.data.height_in_number_of_tiles <= 64
|
||||||
@ -139,22 +133,19 @@ def pack_pattern_name_table(filename, cel_chunk, x_cells, y_cells):
|
|||||||
|
|
||||||
f.write(pack_index(pattern))
|
f.write(pack_index(pattern))
|
||||||
|
|
||||||
print(filename, f.tell(), file=sys.stderr)
|
def generate_separate_files(mem):
|
||||||
|
tilesets, layers, palette, cel_chunks = parse_file(mem)
|
||||||
|
|
||||||
with open(sys.argv[1], 'rb') as f:
|
with open("palette.bin", "wb") as f:
|
||||||
buf = f.read()
|
pack_palette(f, palette)
|
||||||
mem = memoryview(buf)
|
|
||||||
|
|
||||||
tilesets, layers, palette, cel_chunks = parse_file(buf)
|
|
||||||
|
|
||||||
pack_palette(palette)
|
|
||||||
|
|
||||||
for tileset_index, tileset_chunk in sorted(tilesets.items(), key=itemgetter(0)):
|
for tileset_index, tileset_chunk in sorted(tilesets.items(), key=itemgetter(0)):
|
||||||
filename = f"character_pattern__tileset_{tileset_index}.bin"
|
filename = f"character_pattern__tileset_{tileset_index}.bin"
|
||||||
pack_character_patterns(filename, tileset_chunk)
|
print(filename)
|
||||||
|
with open(filename, "wb") as f:
|
||||||
|
pack_character_patterns(f, tileset_chunk)
|
||||||
|
|
||||||
for layer_index, cel_chunk in sorted(cel_chunks.items(), key=itemgetter(0)):
|
for layer_index, cel_chunk in sorted(cel_chunks.items(), key=itemgetter(0)):
|
||||||
filename = f"pattern_name_table__layer_{layer_index}.bin"
|
|
||||||
#layers[layer_index]
|
#layers[layer_index]
|
||||||
print(f"layer={layer_index} layer_name={layers[layer_index].layer_name} tileset={layers[layer_index].tileset_index}");
|
print(f"layer={layer_index} layer_name={layers[layer_index].layer_name} tileset={layers[layer_index].tileset_index}");
|
||||||
tileset_chunk = tilesets[layers[layer_index].tileset_index]
|
tileset_chunk = tilesets[layers[layer_index].tileset_index]
|
||||||
@ -162,7 +153,110 @@ for layer_index, cel_chunk in sorted(cel_chunks.items(), key=itemgetter(0)):
|
|||||||
x_cells = 64 // (tileset_chunk.tile_width // 8)
|
x_cells = 64 // (tileset_chunk.tile_width // 8)
|
||||||
y_cells = 64 // (tileset_chunk.tile_height // 8)
|
y_cells = 64 // (tileset_chunk.tile_height // 8)
|
||||||
|
|
||||||
pack_pattern_name_table(filename, cel_chunk, x_cells, y_cells)
|
filename = f"pattern_name_table__layer_{layer_index}.bin"
|
||||||
|
print(filename)
|
||||||
|
with open(filename, "wb") as f:
|
||||||
|
pack_pattern_name_table(f, cel_chunk, x_cells, y_cells)
|
||||||
|
|
||||||
#for layer_index, layer_chunk in enumerate(layers):
|
PNCN0__N0PNB__2WORD = (0 << 15) # PNB_2WORD
|
||||||
# print(f"layer={layer_index} layer_name={layer_chunk.layer_name} tileset={layer_chunk.tileset_index}");
|
PNCN0__N0PNB__1WORD = (1 << 15) # PNB_1WORD
|
||||||
|
PNCN0__N0CNSM = (1 << 14) # CN_12BIT
|
||||||
|
|
||||||
|
PLSZ__N0PLSZ__1x1 = (0b00 << 0) # PL_SIZE_1x1
|
||||||
|
PLSZ__N0PLSZ__2x1 = (0b01 << 0) # PL_SIZE_2x1
|
||||||
|
PLSZ__N0PLSZ__2x2 = (0b11 << 0) # PL_SIZE_2x2
|
||||||
|
|
||||||
|
CHCTLA__N0CHCN__16_COLOR = (0b000 << 4) # COL_TYPE_16
|
||||||
|
CHCTLA__N0CHCN__256_COLOR = (0b001 << 4) # COL_TYPE_256
|
||||||
|
CHCTLA__N0CHCN__2048_COLOR = (0b010 << 4) # COL_TYPE_2048
|
||||||
|
CHCTLA__N0CHCN__32K_COLOR = (0b011 << 4) # COL_TYPE_32768
|
||||||
|
CHCTLA__N0CHCN__16M_COLOR = (0b100 << 4) # COL_TYPE_1M
|
||||||
|
|
||||||
|
CHCTLA__N0CHSZ__1x1_CELL = (0 << 0)
|
||||||
|
CHCTLA__N0CHSZ__2x2_CELL = (1 << 0)
|
||||||
|
|
||||||
|
def header_7shades(size_of_cel_data, # bytes
|
||||||
|
size_of_map_data, # bytes
|
||||||
|
tile_character_size, # CHCTLA__N0CHSZ
|
||||||
|
tile_color_mode, # CHCTLA__N0CHCN
|
||||||
|
plane_size, # PLSZ
|
||||||
|
map_data, # PNCN0
|
||||||
|
): #
|
||||||
|
file_type_id = 0x5
|
||||||
|
width = 1
|
||||||
|
height = 1
|
||||||
|
|
||||||
|
return struct.pack(">IIIIIIIHH",
|
||||||
|
file_type_id,
|
||||||
|
size_of_cel_data,
|
||||||
|
size_of_map_data,
|
||||||
|
tile_character_size,
|
||||||
|
tile_color_mode,
|
||||||
|
plane_size,
|
||||||
|
map_data,
|
||||||
|
width,
|
||||||
|
height)
|
||||||
|
|
||||||
|
def palette_pad_7shades(f_tmp, palette_size):
|
||||||
|
# - Pallet data block of 0, 32, or 512 bytes based on the color mode indicated in header
|
||||||
|
for valid_size in [32, 512]:
|
||||||
|
if palette_size > valid_size:
|
||||||
|
continue
|
||||||
|
while palette_size < valid_size:
|
||||||
|
f_tmp.write(bytes([0]))
|
||||||
|
palette_size += 1
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
assert False, palette_size
|
||||||
|
return palette_size
|
||||||
|
|
||||||
|
def generate_7shades(mem):
|
||||||
|
tilesets, layers, palette, cel_chunks = parse_file(mem)
|
||||||
|
|
||||||
|
f_tmp = io.BytesIO()
|
||||||
|
|
||||||
|
pack_palette(f_tmp, palette)
|
||||||
|
palette_size = f_tmp.getbuffer().nbytes
|
||||||
|
palette_size = palette_pad_7shades(f_tmp, palette_size)
|
||||||
|
print("palette_size", palette_size)
|
||||||
|
|
||||||
|
character_patterns_start = f_tmp.getbuffer().nbytes
|
||||||
|
for tileset_index, tileset_chunk in sorted(tilesets.items(), key=itemgetter(0)):
|
||||||
|
pack_character_patterns(f_tmp, tileset_chunk)
|
||||||
|
break
|
||||||
|
character_patterns_end = f_tmp.getbuffer().nbytes
|
||||||
|
size_of_cel_data = character_patterns_end - character_patterns_start
|
||||||
|
print("character_patterns_size", size_of_cel_data)
|
||||||
|
|
||||||
|
pattern_name_tables_start = f_tmp.getbuffer().nbytes
|
||||||
|
for layer_index, cel_chunk in sorted(cel_chunks.items(), key=itemgetter(0)):
|
||||||
|
tileset_chunk = tilesets[layers[layer_index].tileset_index]
|
||||||
|
x_cells = 64 // (tileset_chunk.tile_width // 8)
|
||||||
|
y_cells = 64 // (tileset_chunk.tile_height // 8)
|
||||||
|
pack_pattern_name_table(f_tmp, cel_chunk, x_cells, y_cells)
|
||||||
|
pattern_name_tables_end = f_tmp.getbuffer().nbytes
|
||||||
|
size_of_map_data = pattern_name_tables_end - pattern_name_tables_start
|
||||||
|
print("pattern_name_table_size", size_of_map_data)
|
||||||
|
|
||||||
|
tile_character_size = CHCTLA__N0CHSZ__2x2_CELL
|
||||||
|
tile_color_mode = CHCTLA__N0CHCN__256_COLOR
|
||||||
|
plane_size = PLSZ__N0PLSZ__2x2
|
||||||
|
map_data = PNCN0__N0PNB__2WORD
|
||||||
|
|
||||||
|
header = header_7shades(size_of_cel_data,
|
||||||
|
size_of_map_data,
|
||||||
|
tile_character_size,
|
||||||
|
tile_color_mode,
|
||||||
|
plane_size,
|
||||||
|
map_data)
|
||||||
|
|
||||||
|
with open("7shades.bin", "wb") as f:
|
||||||
|
f.write(header)
|
||||||
|
f.write(f_tmp.getvalue())
|
||||||
|
|
||||||
|
with open(sys.argv[1], 'rb') as f:
|
||||||
|
buf = f.read()
|
||||||
|
mem = memoryview(buf)
|
||||||
|
|
||||||
|
#generate_separate_files(mem)
|
||||||
|
generate_7shades(mem)
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user