Mr Sprite

(C) 2012-2013 by Antoine VIGNAU and Olivier ZARDINI

> What is Mr Sprite ?

Mr Sprite is a command-line tool for Windows to manage Sprites and to simplify the integration of Sprites into Apple IIgs games.

Programmers spend a lot of time to prepare Sprites sheets :
 
- You have to ensure the Sprite width is a multiple of 4 pixels (16 bit),
- You have to prepare both Even and Odd aligned versions of the Sprite,
- You have to organize your Sprites into 320x200 pictures to put as many Sprites as you can, trying to minimize lost space
- You have to prepare the Mask sheets
- You have to record Width / Height for each sprite and the Offset (address) of the sprite in the Sprite sheet
- And, finally, you have to write the most efficient code to display the sprite on the Apple IIgs graphic page !
 
Of course, if you want to add new Sprites or modify an existing one, you may have to re-do everything :-( From a programmer's perspective, the only thing we would like to do is to call a function named DrawSprite(sprite_id, screen_address) with only 2 parameters : the sprite identification number and the address of the screen where to display it. MrSprite is here to simplify programmers' life by providing a full set of features including automatic Sprite detection / Sprite alignment / Reverse & Flip effects / Sprite compiler / Direct 65c816 code object output... and more !

Mr Sprite is part of the
Brutal Deluxe's Cross Developpement Tools Project, a full set of utilities available on Windows (and other) platforms to enable the creation of new Apple IIgs software : 65c816 Assembler, 65c816 Desassembler, 65c816 Simulator, Graphic File Converter, Resource Catcher...


> Quick Tour

Sprite Extraction

Most of the time, you start your project with a Sprite sheet downloaded from a Web site. Sprites are together in one picture. Make sure the picture uses GIF format.
 



The EXTRACT command process the Sprite sheet to provide :

- A new Sprite sheet with a frame around each sprite. The sprite width is a multiple of 4 pixels.


- A set of GIF pictures (one per Sprite) :


Pictures Manipulation

Sometime, the sprite sheet does not provide all the required sprites. You have to extend it depending of your needs. For a fighting game, the character has to go Left and Right.

Let's use the MIRROR command to create the missing pictures :


If your character needs to walk on the ceiling, let's use the FLIP command for that :


Once you have all the Sprites you need, end up with ODD command to generate the odd column aligned Sprites :


Sprite Overview

Using the UNIQUE command removes duplicated pictures and the RENAME command gives a new name to all remaining ones (ordered from 0 to N).

The WALLPAPER command creates a large picture containing ALL the sprites together, with Frame and Identification :



Source Code generation

The CODE command compiles the Sprites and creates a set of assembly 65c816 Source Files (Merlin 16+ compatible), one per Sprite :

Spr_010    CLC              ; 36x62, 1483 bytes, 2570 cycles
           SEI              ; Disable Interrupts
           PHD              ; Backup Direct Page
           TSC              ; Backup Stack
   
       STA    StackAddress
   
       LDAL   $E1C068   ; Direct Page and Stack in Bank 01/
   
       ORA    #$0030
   
       STAL   $E1C068
   
       TYA              ; Y = Sprite Target Screen Address (upper left corner)
   
       TCS              ; New Stack address
   
       LDX    #$2222    ; Pattern #1 : 78
   
       LDY    #$0000    ; Pattern #2 : 78
   
       LDA    #$2200    ; Pattern #3 : 19
   
       TCD   
*--       
   
       TYA              ; Line 0
   
       STA    $A8,S
   
       SEP    #$20
   
       LDA    $04,S
   
       AND    #$0F
   
       ORA    #$10
   
       STA    $04,S
   
       LDA    $A4,S
   
       AND    #$0F
   
       ...
*--       
           LDAL   $E1C068   ; Direct Page and Stack in Bank 00/
           AND    #$FFCF
           STAL   $E1C068
           LDA    StackAddress    ; Restore Stack
           TCS   
           PLD              ; Restore Direct Page
           CLI              ; Enable Interrupts
           RTL


The source code file can be put in a Merlin 16+ project and be called by a JSL. The comments contain information such as Sprite Width / Height, Object code Size, Number of Cycles used to display it...

Most of the time, you don't care about manipulating ONE sprite, what you want is to call a unique function dealing with all the sprites you have in your game. To create this single entry point, use the command BANK to generate both object code files (*.bin) and the single entry point code (.txt) :


The object code files are 64 KB long (fit in one memory bank).  The latest one can be smaller than 64 KB. Such object files contain the assembled version of the Source code provided by the CODE command. A short code is provided as a Merlin 16+ compatible source file :

DrawBarb    ASL                  ; A=Sprite Number ($0000-$0041)
            TAX                  ; Y=Target Screen Address ($2000-$9D00)
            LDA    BarbNum,X     ; Relative Sprite Number Table
            JMP    (BarbBank,X)  ; Bank Number Table

BarbNum     HEX    1800,0500,2000,1C00,0000,2C00,1300,1400
            HEX    0B00,0700,0900,0A00,1900,1A00,0900,0A00
            HEX    1B00,1D00,2800,2A00,2600,2B00,0C00,0E00
            HEX    2100,2200,1F00,1E00,1100,1400,2900,2400
            HEX    0600,0200,0E00,0F00,1500,1000,1200,1100
            HEX    0400,0500,0300,0200,0400,2300,1000,1300
            HEX    0700,0800,2700,2500,0D00,0C00,0800,0600
            HEX    0D00,0B00,0300,0100,0100,0000,1600,1700
            HEX    0F00,1200

BarbBank    DA     BarbBank00,BarbBank00,BarbBank00,BarbBank00,BarbBank00,BarbBank00,BarbBank01,BarbBank01
            DA     BarbBank01,BarbBank01,BarbBank00,BarbBank00,BarbBank00,BarbBank00,BarbBank01,BarbBank01
            DA     BarbBank00,BarbBank00,BarbBank00,BarbBank00,BarbBank00,BarbBank00,BarbBank00,BarbBank00
            DA     BarbBank00,BarbBank00,BarbBank00,BarbBank00,BarbBank00,BarbBank00,BarbBank00,BarbBank00
            DA     BarbBank00,BarbBank01,BarbBank01,BarbBank01,BarbBank00,BarbBank01,BarbBank01,BarbBank01
            DA     BarbBank01,BarbBank01,BarbBank00,BarbBank00,BarbBank00,BarbBank00,BarbBank00,BarbBank00
            DA     BarbBank00,BarbBank00,BarbBank00,BarbBank00,BarbBank01,BarbBank01,BarbBank01,BarbBank01
            DA     BarbBank00,BarbBank00,BarbBank01,BarbBank00,BarbBank01,BarbBank01,BarbBank00,BarbBank00
            DA     BarbBank00,BarbBank00

BarbBank00  JSL    $AA0000
            PHK
            PLB
            RTS

BarbBank01  JSL    $AA0000
            PHK
            PLB
            RTS

With a single entry point (DrawBarb), the source code has to be included in your project. The DrawBarb function is called with only two parameters : A = Sprite identification number (see WallPaper for sprite identification) and Y = Target Screen address). It will find the right Bank and will display the Sprite in the $01/2000 Graphic Page (shadowing On). As a programmer, the only thing to do is to allocate the number of required memory banks (= number of object code files), load the object files in the memory banks and populate the BarBankXX JSL $AA0000 address with right ones.



> Commands List


If you do not provide any parameter on the command line, Mr Sprite displays a quick reminder of existing commands :

C:\AppleIIgs>MrSprite.exe
MrSprite.exe v 1.0, (c) Brutal Deluxe 2012-2013.
  Usage : MrSprite.exe COMMAND   <param_1> <param_2> <param_3>...
          ----
          MrSprite.exe EXTRACT   <sprite_file(s)_path> <background_color_RRGGBB> <frame_color_RRGGBB>.
          ----
          MrSprite.exe MIRROR    <sprite_file(s)_path> <background_color_RRGGBB>.
          MrSprite.exe FLIP      <sprite_file(s)_path> <background_color_RRGGBB>.
          MrSprite.exe ODD       <sprite_file(s)_path> <background_color_RRGGBB>.
          ----
          MrSprite.exe UNIQUE    <sprite_file(s)_path>.
          MrSprite.exe RENAME    <file(s)_path>        <new_name>.
          MrSprite.exe WALLPAPER <sprite_file(s)_path> <background_color_RRGGBB> <frame_color_RRGGBB>.
          ----
          MrSprite.exe CODE [-V] <sprite_file(s)_path> <background_color_RRGGBB> <color_0_RRGGBB> <color_1_RRGGBB>...
          MrSprite.exe BANK      <sprite_code(s)_path> <bank_object_name>.
          ----

A few remarks about the Parameters required on the Command Line :
 
        - Some Commands accept an optional -V as first parameter.  This enable the VERBOSE mode for this command (more information are displayed on the screen during command execution and extra files may be generated).
        - If the Windows File or folder paths contains Space characters, quote the path to avoid conflicts (MrSprite.exe UNIQUE "c:\Users and Settings\Project\Barbarian_spr_*.gif").
 
       - All commands accept a set of files. Use wildcard character (*) to specify more than one file (MrSprite.exe UNIQUE c:\Project\Barbarian_spr_*.gif).
        - All colors are using HexaDecimal format. Each component (Red / Green / Blue) can take a value between  00 (0) and FF (255).  A color is represented by its 3 components RGB (Red is FF0000, Black is 000000, White is FFFFFF, Blue is 0000FF...).  Any good Paint program should let you access to the Palette and the Color code in Hexadecimal (also known as HTML code because it is used in HTML language to define a color) :


A few remarks about the software behavior :
        - Any error occuring during the execution of a command is immediately displayed on the Screen. 
        - You can chain several commands using a .bat file.
        - You can re-direct the standard output of a Command into a Text file using the > character (
MrSprite.exe CODE c:\Project\Barbarian_spr*.gif [...] > c:\Project\SpriteStatistics.txt).
        -  The source code generated by the Software uses Merlin 16+ syntax. You can probably adapt it very easily to any other Apple IIgs Assembler.
        -  The only graphic file format recognized is GIF. It is a 256 colors format, with good compression and no quality loss. Perfect for Sprites handling.


EXTRACT
    This command process one or several pictures to search for Sprites located inside. The background color, provided on the command line as a hexadecimal RedGreenBlue code, is used to define the visible part of the sprite, in opposite to the background part. The frame color is used to draw a box around the sprite to define its borders. Of course, the background and the frame color must not be used in the Sprite. This commend may be used on Sprite sheet pictures (one picture with a lot of Sprites inside) or on pictures containing only one sprite (this may be the output of WindowCapture tool when you are recording an animation).

    Syntax
MrSprite.exe EXTRACT  <sprite_file(s)_path>  <background_color_RRGGBB>  <frame_color_RRGGBB>

    Example
MrSprite.exe EXTRACT  c:\Project\Barbarian.gif  41A3EF  FC0204

      On the following picture, the light blue (RGB code = 41A3EF) is the background color and all other colors are part of the sprites. We can see several characters and a logo :


    The command will process the picture to find the Sprites and draw a frame (with the frame color provided on the command line) around each of them. Each sprite width is a multiple of 4 pixels. Here is the result :


    An unexpected result occured : The shadows under the two lower left characters are considered as individual sprites and are not linked to their related bodies. How can you help Mr Sprite to group several parts of the same Sprite together ?

     Edit the picture and use the frame color to draw a frame around the sprites having several distinct parts. You don't need to be too close to the sprite border :


   This time, the command will perfectly find the Sprites in the picture :

 

    A close view let you notice than the sprite is aligned to the left border and may have some empty columns on the right (due to the multiple of 4 pixels width) :


    Each sprite is also extracted from the source picture to become a new picture. The name of the Sprite picture comes from the Source picture where an incremental number is added as a suffix :


MIRROR

    This command is used to flip the source images from Left to Right. A new picture is created (the letter m is added at the end of the name) and the sprite is aligned to the left border. 

    Syntax
MrSprite.exe MIRROR  <sprite_file(s)_path>  <background_color_RRGGBB>

    Example
MrSprite.exe MIRROR  c:\Project\Barbarian_spr*.gif  41A3EF

c:\Project\Barbarian_spr_10.gif c:\Project\Barbarian_spr_10m.gif

FLIP
    This command is used to flip the source images from Top to Bottom. A new picture is created (the letter f is added at the end of the name). 

    Syntax
MrSprite.exe FLIP  <sprite_file(s)_path>  <background_color_RRGGBB>

    Example
MrSprite.exe FLIP  c:\Project\Barbarian_spr*.gif  41A3EF


c:\Project\Barbarian_spr_10.gif c:\Project\Barbarian_spr_10f.gif


ODD
    This command is used to create a Odd Column aligned sprite. Because the source image width is a multiple of 4 pixels, shifting the Sprite (Left to Right) for 1 position may increase by 4 pixels the width of the new picture. The letter o is added at the end of the name. 

    Syntax
MrSprite.exe ODD  <sprite_file(s)_path>  <background_color_RRGGBB>

    Example
MrSprite.exe ODD  c:\Project\Barbarian_spr*.gif  41A3EF


c:\Project\Barbarian_spr_10.gif c:\Project\Barbarian_spr_10o.gif


UNIQUE
    Check all the pictures files and remove all duplicated ones. The clean-up Task is useful because some commands (MIRROR, FLIP, ODD) may generate pictures having exactly the same visual than existing ones.

    Syntax
MrSprite.exe UNIQUE  <sprite_file(s)_path>

    Example
MrSprite.exe UNIQUE  c:\Project\Barbarian_spr*.gif


RENAME

    This command helps to re-index all the remaining files from 0 to N. It is also time to remove from name all references due to picture manipulations (spr fro Sprite, o for ODD, f for FLIP, m for MIRROR...). You end up with a list of files containing only a prefix (new_name parameter) and a number as a suffix (Barbarian_000.gif, Barbarian_001.gif, Barbarian_002.gif...). The suffix will be used as Sprite identification number.

    Syntax
MrSprite.exe RENAME  <file(s)_path>  <new_name>

    Example
MrSprite.exe RENAME  c:\Project\Barbarian_spr*.gif Barbarian


WALLPAPER
    This command creates a large picture will all your sprites together.  Each row receives 10 or 20 sprites, depending of their width. Each sprite is identified by its number. The wallpaper picture is a good quick reference material for sprite usage (help to find the right id for a sprite).


    Syntax
MrSprite.exe WALLPAPER  <sprite_file(s)_path>  <background_color_RRGGBB>  <frame_color_RRGGBB>

    Example
MrSprite.exe WALLPAPER  c:\Project\Barbarian_*.gif  41A3EF  FC0204


CODE
    This command converts a graphic picture into a 65c816 source code file, ready to be used in your Merlin 16+ project. The sprite is compiled and converted as a list of assembly langage instructions. If you run this code, the sprite will be displayed on the screen (Bank $01 only). The result source code file has the same name than the source picture, but the .gif extension is replaced by a .txt.  As usually, you have to provide the background color code. But this time, you also have to provide ALL the colors used in the sprite, in the order compatible with the color palette you want to use on the IIgs side. An Apple IIgs sprite can't use more than 16 colors. Depending on the number of colors your sprites have, you have to provide them as command parameters.  On our example, the sprites are using 3 distints colors : Black (RGB=040204), Gray (RGB=646664) and light Pink (RGB=FCBA9C). This 3 colors will have index 0, 1 and 2 in the Apple IIgs screen palette.

    Syntax
MrSprite.exe CODE  [-V]  <sprite_file(s)_path>  <background_color_RRGGBB>  <color_0_RRGGBB>  <color_1_RRGGBB> ...

    Example
MrSprite.exe CODE  c:\Project\Barbarian_*.gif  41A3EF  040204  646664  FCBA9C

    This source code file contains information such as Sprite ID , Sprite Width / height, Object Code size, Number of cycles used to display the Sprite. This code must be called using a JSL instruction in Full 16 bits mode (REP #$30). The Y register must contain the target screen address ($2000 / $9D00). No border colision is performed, so be careful to define a valid screen address. The anchor of the sprite is the upper left corner of the sprite. Everything has be done to optimize the display of the Sprite in terms of speed.

Spr_010    CLC              ; 36x62, 1483 bytes, 2570 cycles
           SEI              ; Disable Interrupts
           PHD              ; Backup Direct Page
           TSC              ; Backup Stack
   
       STA    StackAddress
   
       LDAL   $E1C068   ; Direct Page and Stack in Bank 01/
   
       ORA    #$0030
   
       STAL   $E1C068
   
       TYA              ; Y = Sprite Target Screen Address (upper left corner)
  ...

           RTL

BANK

     If you have a lot of Sprites in your project, you may not be satisfied by receiving the output of Mr Sprite as individual Source code. Because including the Sprite source inside your existing Project may increase the size of your core Program and perhaps you don't need all the sprites to be in memory together at the same time. For a fighting game (Street Fighter style), each opponent sprites should be loaded when needed. You main character is not going to fight all oponents together but one after the other. In order to simplify Sprite code handling, we have designed the BANK command. It will assemble all the Sprite source code file into 64 KB files, ready to be loaded in one memory Bank. Depending on how many Sprites you have, you may need 1, 2 or more 64 KB banks to store all of them. If you want all your sprites together in memory, you will have one set of Bank files (Bank00.bin, Bank01.bin...). If you have several groups of sprites (one for Ryu, one for ChunLi, one for Zangief...), you will have several sets of Bank files (Ruy00.bin, Ryu01.bin..., ChunLi00.bin, ChunLi01.bin, ...). You will load your bank set when needed. With Mr Sprite, instead of loading the graphic files containing the sprite, you have just to load the Bank files containing the 65c816 object code to display them.  The memory space required to store the Sprite as a graphic image (Sprite + Mask) is about the same than the space required to store the code displaying the sprite. It could be a little bit larger or smaller, depending on the sprite.

      Because Bank files must be transfered into a Prodos file system to be used, the bank file names have to compatible with Prodos name standard (15 characters long, only A-Z, 0-9,  . allowed). This is why the
bank_object_name (3rd parameter) has to be short (we will add 2 characters digit for number and a .bin extension). You can use Cadius tool to perform the transfer between the PC file system and the Prodos image file (Cadius.exe ADDFILE c:\AppleIIgs\HardDrive.2mg /D3/ c:\Project\Barb*.bin).

    Syntax
MrSprite.exe BANK  <sprite_code(s)_path>  <bank_object_name>

    Example
MrSprite.exe BANK  c:\Project\Barbarian_*.txt  Barb

     Once your sprites code have been assembled and packed into bank files, it is hard to know where each sprite is located. To simplify your work, the BANK command provides a single entry point source code you have to use. This code has to be called (via a JSR) with 2 parameters :
            - The sprite identification number (0-N) in Accumulator (16 bits)
            - The Target screen address ($2000-$9D00) in Y register (16 bits)

     It will dispatch your call to the right bank. The name of the entry point and all tables use as prefix or suffix the
<bank_object_name> parameter. so if your are using several groups of bank files, you will receive several entry point source code files to include.

DrawBarb    ASL                  ; A=Sprite Number ($0000-$0041)
            TAX                  ; Y=Target Screen Address ($2000-$9D00)
            LDA    BarbNum,X     ; Relative Sprite Number Table
            JMP    (BarbBank,X)  ; Bank Number Table

BarbNum     HEX    1800,0500,2000,1C00,0000,2C00,1300,1400
            HEX    0B00,0700,0900,0A00,1900,1A00,0900,0A00
            HEX    1B00,1D00,2800,2A00,2600,2B00,0C00,0E00
            HEX    2100,2200,1F00,1E00,1100,1400,2900,2400
            HEX    0600,0200,0E00,0F00,1500,1000,1200,1100
            HEX    0400,0500,0300,0200,0400,2300,1000,1300
            HEX    0700,0800,2700,2500,0D00,0C00,0800,0600
            HEX    0D00,0B00,0300,0100,0100,0000,1600,1700
            HEX    0F00,1200

BarbBank    DA     BarbBank00,BarbBank00,BarbBank00,BarbBank00,BarbBank00,BarbBank00,BarbBank01,BarbBank01
            DA     BarbBank01,BarbBank01,BarbBank00,BarbBank00,BarbBank00,BarbBank00,BarbBank01,BarbBank01
            DA     BarbBank00,BarbBank00,BarbBank00,BarbBank00,BarbBank00,BarbBank00,BarbBank00,BarbBank00
            DA     BarbBank00,BarbBank00,BarbBank00,BarbBank00,BarbBank00,BarbBank00,BarbBank00,BarbBank00
            DA     BarbBank00,BarbBank01,BarbBank01,BarbBank01,BarbBank00,BarbBank01,BarbBank01,BarbBank01
            DA     BarbBank01,BarbBank01,BarbBank00,BarbBank00,BarbBank00,BarbBank00,BarbBank00,BarbBank00
            DA     BarbBank00,BarbBank00,BarbBank00,BarbBank00,BarbBank01,BarbBank01,BarbBank01,BarbBank01
            DA     BarbBank00,BarbBank00,BarbBank01,BarbBank00,BarbBank01,BarbBank01,BarbBank00,BarbBank00
            DA     BarbBank00,BarbBank00

BarbBank00  JSL    $AA0000
            PHK
            PLB
            RTS

BarbBank01  JSL    $AA0000
            PHK
            PLB
            RTS

   Before calling this entry point, you need to perform 3 preliminary tasks :

        - Allocate the right number of 64 KB memory banks. This must be a 64 KB space, starting at $0000. You can use the following code to do it :

AllocOneBank  PushLong #0        ; Allocate 1 bank of 64 KB
              PushLong  #$10000
              PushWord  myID
              PushWord  #%11000000_00011100
              PushLong  #0
              _NewHandle
              PLX                ; Handle lower address
              PLA                ; Handle higher address (00XX)
              XBA
              STA   AB_1+2
AB_1          LDAL  $AAAA01,X    ; Get bank address in A=XX/00
              RTS
 
       - Update the
PREFIXBankXX address in the entry point code with the memory bank (replace the $AA0000 with real bank address).

             JSR   AllocOneBank  ; Bank allocation for Sprites
             STA   BarbBank00+2
             JSR   AllocOneBank
             STA   BarbBank01+2

        - Load MrSprite Bank files in this memory banks (at startup if you are using only one set, when required if you are using several bank sets)

   You are now ready to display Sprites on your Apple IIgs screen :

            LDA   #$0000     ; Display Barbarian Sprite #0
            LDY   #$3432     ; in the Middle of the screen
            JSR   DrawBarb


> Restrictions

- The sprites can't be displayed outside of the screen boundaries or even cross the borders. 
- The sprites can only by displayed in the $01 memory bank (shadowing must be active to see the sprite on the screen).
- The source Code used to erase the Sprite from the screen is not included. This problem will be analyzed / handled in a next coming tool.


> Known Bugs

None

> F.A.Q

Is the Source code available somewhere ?

The Source code is freely available in the Zip file (see download section).
It is currently pakaged as a Visual Studio 2010 Project set of files. The tool is only using C Language, so you can recompile it with any other C ANSI compiler (GCC...).

What about a Macintosh or Linux release ?

Everything has be done to be as independant as possible from the Operating System. The first release has been done using a Windows environment. The Macintosh and Linux ports should be done in the next weeks, as soon as someone is ready to handle it !
The source code is written in C Ansi and the only Operating Systems calls have been isolated in a specific file. So porting the project to Macintosh or Unix systems should take maximum 4 hours to any C programmers having the knowledge of the target platform.

What kind of algorithm do you use ? Direct Page ?  Stack ?  Both ?

Mr Sprite's algorithm and all technical information are discussed in a dedicated article. Click here to read it.

Where Mr Sprite name comes from ?

A very good friend of us, Philippe Leclercq (better known as Teaser from Once Product) did several excellent Apple IIgs software and demos in the 90's (Shiny Bubbles, Plotting, Boink Demo, RGB Demo, Stadium Demo...). One of them was Mr Sprite, a sprite compiler for the Apple IIgs. Like all its other software, Philippe did it in a very polish way. All GS/OS compatible, with intuitive interface (Menu, Windows, Online help), the software was not only very easy to use but it lets you choose & test several algorithms and show you immediately the % of CPU used to animate the sprite you have choosen (using Border color change effects).  Even if the technology we are currently using in our Mr Sprite has nothing to do to what Philippe chose at the time, we kept the same name because we follow the same goal (dream ?) : animate large sprites on the Apple IIgs as fast as we can. Let's see this Mr Sprite as the next generation !


> References

Programming the 65816 - Including the 6502, 65C02 and 65802 by Western Design Center
Le IIgs Epluché
written by D.BAR, D. DELAY, Y. DURANT, J.L SCHMITT and E. WEYLAND
Mr Sprite 2.01 (c) 1993-1994 Philippe 'Teaser' Leclercq / Once Product


> Download

MrSprite v1.0 for Windows 32 & 64 bits + Source Code                     Mr Sprite for Windows