You probably want to use Einar's ZX0 for compression unless your level format is really simple to run-length encode.
I run length encoded the levels for my Manic Miner remake, here is an example so you get the idea of what I did. This was my first attempt at ASM programming so probably could do a lot better. I could compress a lot more by packing the row/column into 9 bits and the repeat count into the high bits of a 16 bit number rather than using a byte for each.
Code: Select all
; some macros to pack pointers to graphics into 8 bits rather than 16
MACRO celltype gfx
db (gfx - gfx_platform0) / 8
ENDM
MACRO keytype gfx
db (gfx - gfx_key0) / 8
ENDM
; macro for ink, paper, bright
MACRO IPB ink, paper, bright
db ink|(paper<<3)|(bright<<6)
ENDM
; Central Cavern (Spectrum Version)
Central_Cavern:
dc "Central Cavern"
; border/paper
db 2
; cell graphics
celltype gfx_platform0
celltype gfx_wall0
celltype gfx_spiky0
celltype gfx_crumbly0
celltype gfx_platform0
celltype gfx_platform0
celltype gfx_spiky1
celltype gfx_conveyor0
celltype gfx_conveyor0
; cell attribs
IPB 2, 0, 1
IPB 6, 2, 0
IPB 4, 0, 1
IPB 2, 0, 0
IPB 0, 0, 0
IPB 0, 0, 0
IPB 5, 0, 0
IPB 4, 0, 0
IPB 4, 0, 0
; willy start position x, y. bit 4 of y is set if facing left
db 2, 13
; exit position
db 29, 13
; exit colour
IPB 6, 1, 0
; keytype
keytype gfx_key0
db 5 ; number of keys
; position of keys
db 9, 0
db 29, 0
db 16, 1
db 24, 4
db 30, 6
; guardians
db 1 ; number of guardians
; something like start position, end position of patrol path and some other stuff I can't remember ;) Obvs the attribs (64+6) here too.
; seems to be terminated with a 0 since some enemies need extra data
db gfx_robot0/256, 0, 8, 7, 8, 15, 64+6, 0
; single blocks
db SPIKY_A, 23, 4
db SPIKY_A, 27, 4
db SPIKY_A, 21, 8
db SPIKY_A, 12, 12
db SPIKY_B, 11, 0
db SPIKY_B, 16, 0
; repeat blocks: platforms
db HORZ_REPEAT|PLATFORM_A, 1, 5, 30
db HORZ_REPEAT|PLATFORM_A, 1, 7, 3
db HORZ_REPEAT|PLATFORM_A, 1, 9, 4
db HORZ_REPEAT|PLATFORM_A, 29, 10, 2
db HORZ_REPEAT|PLATFORM_A, 28, 12, 3
db HORZ_REPEAT|PLATFORM_A, 5, 13, 15
db HORZ_REPEAT|PLATFORM_A, 1, 15, 30
; crumbly platforms
db HORZ_REPEAT|CRUMBLY, 14, 5, 4
db HORZ_REPEAT|CRUMBLY, 19, 5, 4
db HORZ_REPEAT|CRUMBLY, 23, 12, 5
; walls
db HORZ_REPEAT|WALL_A, 17, 8, 3
db HORZ_REPEAT|WALL_A, 20, 12, 3
; conveyor
db HORZ_REPEAT|CONVEYOR_L, 8, 9, 20
db #ff ; terminator
ENDIF
; The Cold Room
The_Cold_Room:
dc "The Cold Room"
; border/paper
IPB 2, 1, 0
; cell graphics
celltype gfx_platform0
celltype gfx_wall0
celltype gfx_spiky0
celltype gfx_crumbly0
celltype gfx_platform0
celltype gfx_platform0
celltype gfx_spiky4
celltype gfx_conveyor0
celltype gfx_conveyor0
; cell attribs
IPB 3, 1, 1
IPB 6, 2, 0
IPB 0, 0, 0
IPB 3, 1, 0
IPB 0, 0, 0
IPB 0, 0, 0
IPB 5, 1, 0
IPB 6, 1, 0
IPB 6, 1, 0
; willy start position x, y. bit 4 of y is set if facing left
db 2, 13
; exit position
db 29, 13
; exit colour
IPB 3, 2, 1
; keytype
keytype gfx_key2
db 5|(1<<4) ; number of keys/paper colour
db 7, 1
db 25, 1
db 26, 7
db 3, 9
db 19, 12
; guardians
db 2 ; number of guardians
db gfx_penguin0/256, 7, 18, 3, 1, 18
IPB 6, 1, 0
db 0
db gfx_penguin0/256, 7, 29, 13, 12, 29
IPB 5, 1, 0
db 0
; single blocks
db SPIKY_B, 30, 1
db PLATFORM_A, 25, 3
db PLATFORM_A, 1, 7
; repeat blocks
db HORZ_REPEAT|WALL_A, 19, 0, 12
db HORZ_REPEAT|PLATFORM_A, 1, 5, 19
db HORZ_REPEAT|CRUMBLY, 21, 3, 4
db HORZ_REPEAT|PLATFORM_A, 21, 6, 4
db HORZ_REPEAT|CRUMBLY, 26, 6, 2
db HORZ_REPEAT|CRUMBLY, 2, 7, 5
db HORZ_REPEAT|PLATFORM_A, 9, 9, 7
db HORZ_REPEAT|CRUMBLY, 19, 10, 4
db HORZ_REPEAT|CONVEYOR_R, 3, 11, 4
db HORZ_REPEAT|PLATFORM_A, 14, 12, 4
db HORZ_REPEAT|CRUMBLY, 8, 13, 4
db HORZ_REPEAT|PLATFORM_A, 1, 15, 30
db VERT_REPEAT|WALL_A, 25, 6, 7
db VERT_REPEAT|WALL_A, 28, 5, 8
db VERT_REPEAT|CRUMBLY, 26, 8, 5
db VERT_REPEAT|CRUMBLY, 27, 8, 5
db #ff
So I had horizontal and vertical repeating cells in the level. Could also add rectangles instead of just horizontal/vertical repeat.
Guardian sprite data starts on a 256 byte aligned boundary so I can just use 8 bits for those as well.