[stella] Re: Banker (Utility) v0.01

Subject: [stella] Re: Banker (Utility) v0.01
From: "Andrew Davie" <adavie@xxxxxxxxxxx>
Date: Mon, 13 Jan 2003 01:16:39 +1100
Whoops!  I did it again.  Many apologies for my last HTML post.

Attached is a ZIP file with a Utility I have recently written, and some
sample output from that utility.  With a bit of tweaking (addition of
command-line switches) it might be of assistance to others.  'Banker', as I
call it, is designed to take multiple frames of graphics as input, and split
those frames into matrices of sprites (16 bytes deep) over as few 2K banks
as possible, satisfying the following criteria....

a) For any frame, ALL of its sprites must be in a single bank
b) The matrix definition for the frame must be in the same bank as the
sprites it uses
c) Sprites definitions may be re-used by multiple frames, if the sprites are
identical
d) Sprites are defined bottom-up (ie: in reverse byte-sequence, to assist
quick drawing).
e) Frames themselves are unique, so their matrices are not optimised away,
even if frames are identical.

The utility outputs one .asm file per bank it needs to create, and a single
file containing a table of pointers to the frames.  The table gives the bank
and frame address for each frame.


The ZIP file contains the utility (BANKER.EXE) some sample output (.ASM
files) and the graphics files used as input for the sample data (the PNG
files).  The sample art files (random stuff, really) have been sized to 48 x
80 pixels (the size of my sprite system, for now).  The utility is written
so that it doesn't care what size the input graphics are - it will cope with
undersize or oversize files OK.

The utility is used for compiling all of these individual frame files into
banks through the following call...

    banker *.png

Note the use of wildcards for filename specification. Alternatively,
filenames can be explicitely defined;  eg:

    banker a.png b.png c.png d.png

Some command-line switches are also available

    -v         Toggle verbose reporting ON/OFF ... barely functional
    -Xn        Set the frame matrix width to n sprites
    -Yn        Set the frame matrix height to n sprites
    -Nname     Set the output filename prefix to "name" (default = "BANK")

Files are processed in left-to-right order, as they are found on the command
line.  So in the above example, a.png would be packed to frame #0,  b.png
would be frame #1, etc.  When running, the utility displays basic
information about the file it is processing, and the size of the image in
pixels.  After all files have been processed, a summary of the number of
frames, number of banks, and details of the usage in each bank is output.
Bank files are written to the current working directory in the form...

    BANK00.ASM                First bank
    BANK01.ASM                Second bank
    ...etc

and a single file

    BANK_FRAMETABLE.ASM

The BANK_FRAMETABLE.ASM file holds a table (called 'FrameTable') giving the
bank, and an address within the bank, for each of the frames processed from
the frame list on the command line.   Bank numbers are referred to
indirectly through equates, which must be set up in the program including
these .ASM files.  The file also contains an equate, FRAMECOUNT, which gives
the total number of frames in the table.  This equate may be used as a
bounds-check to guarantee that no attempt is made to display illegal frames.

Sample...

------------------------------------------------------------
; BANK_FRAMETABLE.asm
; Created by Banker v0.01

FrameTable

;              Bank  <Frame Address         >Frame Address              #

 .byte FRAMEBANK00, <       FRAME_a_png_0, >       FRAME_a_png_0  ;   0
 .byte FRAMEBANK00, <       FRAME_a_png_1, >       FRAME_a_png_1  ;   1


FRAMECOUNT = 2

; END
------------------------------------------------------------

The table consists of a line per frame.  Each line contains a bank number -
referenced by an equate value - giving the bank in which the frame itself is
defined.  A frame definition consists of a colour, and a matrix giving the
sprite numbers used to build the frame itself.  The sprite data itself comes
from the sprite set which starts at the beginning of each bank.  Thus, the
matrix is a list of sprite indexes.  The draw system uses the index to
calculate an absolute address of the sprite data for draw purposes.  Since
sprites are (currently hardwired) at 16-pixels deep, this is a simple
calculation.

The equate removes any dependancy between the FrameTable and actual physical
bank numbering.  The programmer needs a list assigning bank equates to
actual physical bank numbers - eg:

FRAMEBANK00 = 0
FRAMEBANK01 = 1
...etc

In the above case, this would indicate to the draw system that frame 0 is in
hardware bank #0, and frame #1 is in hardware bank #1, etc.

The individual bank files (BANK00.ASM etc) contain the sprite set - a list
of sprites (each 16-bytes, defined bottom-up) used to build a matrix of
sprites for the sprite system - and definitions of the frames which are
defined in this bank.  Each of the frames is referenced (found) by looking
up the bank/address in the FrameTable, then switching bank and accessing the
frame matrix and spriteset as required.

------------------------------------------------------------
; BANK01.asm
; Created by Banker v0.01

; Sprite set.  Each line is a single sprite, 16 bytes deep, defined
bottom-up

; This bank contains 2 frames, consisting of 39 sprites.

 .byte   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
0,   0
 .byte  17,  19,  17,   1,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
0,   0
 .byte  15,  30, 189, 253, 251, 119,  87,  23,   7,   6,   0,   0,   0,   0,
0,   0
 .byte  64, 224, 240, 240, 232, 208, 240, 224, 192,   0,   0,   0,   0,   0,
0,   0
 .byte  32,  16,   4,   0,   0,   0,   0,   0,   0,   0,   0,   1,   2,   6,
8,   8
 .byte   0,   1,   4,   8,  20, 136,   8,  12,  72, 136, 144,  16,  32,   0,
64,   1
 .byte 128,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
0,   0
 .byte 224, 192, 128,  64,   0,  63,   0,   0,   0,   0,   0,   0,   0,   0,
0,   0
 .byte 232, 232, 192, 161, 129,  65, 129,  67,   3,   1,   1,   1,   0,   0,
0,   0
 .byte 255, 255, 253, 245, 244, 200, 208, 162, 160, 160, 200, 160, 192, 208,
64,  80
 .byte 213,  82,  36,  64,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
0,   0
 .byte   1, 129,  67,   2,  12,  14,   8,  12,   8,  16,  24,  16,  48,  32,
96,  64
 .byte   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   7,  63, 125,
122, 224
 .byte   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 127, 207, 143,
141, 245
 .byte   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 135, 255, 241,
97, 113
 .byte   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 124, 255, 227,
195, 227
 .byte   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,  56, 254, 255,
235, 130
 .byte   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
0, 128
 .byte   3,   7,  30,  56,  56, 112, 240, 208, 200, 204, 255, 127,   0,   0,
0,   0
 .byte 208, 163,  66,   4,   0,   0,   1,   7,  63, 252, 224,   0,   0,   0,
0,   0
 .byte 134,  14,  28,  56,  48, 224, 192, 128,   0,   0,   0,   0,   0,   0,
0,   0
 .byte  14,   7,   3,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
0,   0
 .byte  23, 127, 247, 166,   3,   7,   3,   1,   1,   0,   0,   0,   0,   0,
0,   0
 .byte  14,  30, 250, 238, 182, 110, 182, 222, 252, 248,   0,   0,   0,   0,
0,   0
 .byte   0,   0,   0,   0,   0,   0,   0,   0,   0,   1,   3,   7,  14,  28,
121, 241
 .byte   3,   3,   7,  14,  12,  28, 113, 116, 209, 145, 161,  34, 160, 132,
69, 139
 .byte  63,  31,  30,  14, 174, 102,  46, 111,  82, 115,  98,  58, 110, 240,
248, 156
 .byte   6,   4,   4, 199,  33,   2,  30, 244,  22,  21, 151, 200, 166,  66,
71,  71
 .byte   3,  19,  51, 161, 243,  67,  70, 206, 188, 152,  88,  28,  12, 238,
174,  46
 .byte   0,   0,   0,   0,   0,   1,   0,   1,   3,   3,   3,   3,   3,   3,
3,   3
 .byte 199, 231, 199, 198, 254, 230, 230, 230, 102, 118,  54,  55,  55,  55,
55,  63
 .byte 128, 128, 192, 128, 192, 128, 192, 192, 195, 199, 198, 245, 252, 156,
132, 100
 .byte   0,   0,   0,   0,   0,   0,   0,   0, 192, 224, 248,  92, 172,  38,
38,   6
 .byte   3,   3,   3,   1,   1,   1,   1,   0,   1,   0,   0,   0,   0,   0,
0,   0
 .byte  34,  34,  34, 131,  34, 162, 194, 194, 147, 227, 227, 193, 195, 193,
211, 211
 .byte   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
128, 128
 .byte   0,   0,   1,   1,   1,   1,   1,   1,   0,   1,   3,   3,   6,   2,
6,   3
 .byte  15, 127, 248, 201, 131, 143, 158, 156, 152, 186, 252, 158,   6,  14,
46,  38
 .byte 128, 192, 192, 192, 192, 128,   0,   0,   0,   0,   0,   0,   0,   0,
0,   0

FRAME_ff0_png_11
 .byte $00 ; colour
 .byte 18, 19, 20, 21, 22, 23
 .byte  0, 24, 25, 26, 27, 28
 .byte  0,  0, 29, 30, 31, 32
 .byte  0,  0, 33, 34, 35,  0
 .byte  0,  0, 36, 37, 38,  0


FRAME_eye2_png_12
 .byte $00 ; colour
 .byte  0,  0,  0,  0,  0,  0
 .byte  0,  0,  1,  2,  3,  0
 .byte  0,  0,  4,  5,  6,  0
 .byte  7,  8,  9, 10, 11,  6
 .byte 12, 13, 14, 15, 16, 17


; Total memory = 686 bytes (1362 still free)

------------------------------------------------------------

The (generated) comments at the start of the bank file indicate how many
frames and sprites are packed into the bank.  The sprite set appears first -
currently a list of 16-byte sprites in bottom-up ordering.  Then come the
frames which reference the sprite set via index.

Consider the label FRAME_eye2_png_12 from the above bank definition.  The
label contains the encoded filename of the original file used to generate
the graphics.  In this case, the frame came from "eye2.png".  The absolute
frame number (in terms of the FrameTable table) is also encoded at the end
of the label.

The current frame format consists of

    colour        1 byte - colour of the frame
    matrix        A 30-byte matrix giving indexes of sprites.
                  Each sprite comes from the frame set at the top of the
file.

The comment at the bottom of the file tells how many bytes in the bank have
been used, and how many are still free.  The utility tries to optimise
things by first checking all banks in use to see when it adds a new frame
which bank would require the fewest new sprites (and would still be large
enough to contain the sprites and frame matrix).  So if parts of 'large
sprites' re-use small sections which are aligned on the 16-deep grid... then
the utility will catch this.


Now, that's all very specific to my code - how can this be of use to you
RIGHT NOW?  Well, it reads graphics files of several formats - specifically
JPG, BMP and PNG files - and creates tables of '2600-compatible sprites.
If, for example, you wanted to convert some graphics into sprites... you
could just run the graphic file through this utility to produce a bank, as
above, and then get the converted data from the sprite set.  At the moment
it's in a 16-byte bottom-up format... but I'm VERY open to adding switches
to the command-line to enable this to become the be-all and end-all of
sprite conversion utilities.  Even now, it might save people some time
converting graphics to ASM format... no more manual binary graphics drawing,
hopefully.

Some possible additions....

    o Top-down or bottom-up definitions
    o Specifying different sprite sizes (ie: not just 16 pixels deep)
    o Changing the matrix output format (no colour, etc) (plans are at a
later stage to add additional data such as collision boxes, etc).
    o specifying different bank sizes (currently 2K)


Well, that's about all I have time for.  I'd appreciate any
comments/testing/suggestions on this one.

Cheers
A

Attachment: banker.zip
Description: Zip compressed data

Current Thread