A SPRITE HANDLING PROJECT
By M.T.Farnworth
Analysis
Problem:
Lack of any hardware or software in the BBC Micro to allow the manipulation
of sprites on the screen.
On many computers Hardware Sprites are taken for granted, however the BBC
was not designed with Hardware Sprites. A hardware sprite is automatically
added to the screen display by the hardware as the data is being sent to the
VDU.
On the BBC however it is neccessary to poke all the data to screen memory in
order to show it on the screen. Sprites of this nature are known as
Software Sprites, as they are created by software instead of hardware.
This produces quite a problem for the average BBC programmer. The problem
being how to get the data into display memory quick enough to make the
program run at a reasonable speed.
The obvious answer is Assembly Language. However this is awkward to write
and takes a considerable amount of time to plan out. For a programmer who
writes programs requiring such utilities regularly, writing this code time
and again becomes quite a chore.
It should also be noted that average programmers will not be fluent in
Assembly Language, and hence some of their ideas will be confined to the
dustbin before they are given a chance.
My plan is to write a set of utilities which will make a program requiring
the use and manipulation of sprites to be quick and easy to write; the
utilities will do all the (extremely complex) donkey work involved in sprite
handling.
My utilities will cover the following areas
1) Sprite printing
2) Sprite Movement handling
3) Score Printing
4) Collision Detection
Constraints
My project will be limited by memory restrictions, since the storage of
sprites takes a considerable amount of memory, and it will be necessary to
use some of the RAM for the program.
Due to the fact that the sprites are of a software type they will take a
considerable amount of proccessor time to run and hence slow down the
execution of the program.
Hardware Requirements
A standard BBC Model B or Master
A backing store e.g. Disk
A monitor
Any type of backing store will be sufficient, so long as it can be read from
and written to.
Design
It will be possible to operate all the utilities from BASIC or Machine Code
with the notable exception of the movement handling program as it would not
be feasible to constantly jump from Machine Code to BASIC. As a result this
area must be handled by the programmer if he is writing in BASIC.
The user will be able to use the utilities on the level which he prefers.
He could use the whole suite of utilities or just the ones which he wishes
to use.
I have chosen to use a half height Mode 5 screen for output. As this gives
me a reasonable 4 colours, has a resolution of 160*128 and leaves enough
memory to use dual screen techniques.
When using dual screen techniques one screen is built up while displaying
another. Then they are swapped and the other displayed. This makes it
possible to display a vast number of sprites without any flicker.
Each byte of memory in Mode 5 is used to display 4 horizontally adjacent
pixels, so the number of positions which the sprites can occupy across the
screen will only be 40. However, I plan to use the full number downwards.
The sprites which the utilities use will be designed on the Sprite designer
by R.A.Waddilove [copyright]
The data created by this program will be stored on disk until it is merged
into one large sprite file for use with the sprite handling utilities. The
first two bytes of the information for each sprite will hold the Width and
Height of the sprite respectively, and then the data will follow.
If a machine code programmer is making use of the movement routines, the
code will be assembled and stored on disk ready for use.
The structure of the files holding data on each sprite will be such that all
the sprites designed are given a number.
When the width and height of a sprite are required this sprite number is
added to another number and the resulting memory location will hold a
certain piece of information on that particular sprite. This will allow
direct access to any piece of data about the sprite. The movement routines
will be pointed to by this same technique. In order to allow the program to
access the sixteen-bit address required the two bytes will be held in
seperate areas of memory.
To allow for the storage of the position of sprites on the screen another
area of memory will be reserved. If every different sprite designed was
given space for its X and Y coordinate then this would only allow the system
to print one of each sprite on the screen and this is evidently useless. To
avoid this the area of memory will be such that the data in it will not only
point to its position on screen but also give the sprite number to which it
refers, for printing purposes. When a sprite is being introduced and it
positions given the data will be stored in a place which tells the collision
detection routine whether it is for use as background, your sprites, or a
sprite which you can hit (i.e. an enemy sprite.)
Also included will be a routine which will allow the users program to check
that all the sprites are fully on screen, and if they are not will destroy
them.
Before using my utilities in a program the user will:
1) Design all the required sprites and group them together in a form
recognised by the sprite printer.
2) Design a main program loop for operating the routine. This loop will be
for calling all the routines the program needs, such as printing all the
sprites whose X and Y coordinates are known.
3) Create a machine code file containing necessary instructions for sprites
along with a pointer file for where the instructions are stored. (if
applicable)
4) Create a background. (if applicable)
5) Choose how many times each sprite can be hit before destruction. (if
applicable)
When this is complete and the relevent files stored to disk they can all be
loaded, and the main routine will control the running of the programs.
Review
The addition of collision detection is important as many programs require
it. For example if a programmer is writing a game it will be more than
likely that collision detection will be necessary. If it is not then the
routine need not be used and the memory it requires can be easily used for
other purposes.
The number printing routine will be useful as it prints a number which can
be used for anything that it is needed for. The routine pokes the numbers
directly to screen memory and as a result has a high operating speed, and
like the collision detection routine need not be used if surplus to
requirements.
I was considering using pixel perfect collision detection but this is slow,
complex and not necessary in many applications. The routine would probably
also need to be different for every application so this has been left for
the user to program if required.
The idea of storing the X and Y coordinates of sprites is useful as it makes
the building up of each screen easier as all that you have to do is call a
routine to print all of them.
The machine code movement facility makes it easier to move sprites around as
all that is needed is to call one routine and all your movement routines are
called automatically and the X and Y coordinates of all sprites updated,
when the machine code instruction routines have been written by the user.
This solution will make the writing of programs which handle sprites easier
for machine code programmers, or in the case of BASIC programmers feasible.
Due to the fact that it is software driven the speed at which the routines
function will depend upon the number of sprites on screen.
Due to the memory restrictions on the BBC the number of sprites which can be
designed will depend upon their size and the amount of memory used by the
routines.
User Guide
Introduction
============
The sprite emulation utilities have been designed to operate at top speed
possible while allowing the use of over 250 sprites on screen at any time,
and ease of use.
It should be noted that the programs provide sprite EMULATION and hence are
not as fast as true hardware sprites, due to the fact that software is
responsible for displaying them.
Throughout the user guide two abbreviations will be used.
ASN - Actual Sprite Number (from the sprites designed)
ISN - Introduced Sprite Number (on the screen in the game)
On the next page is a list of the utilities and their respective execute
addresses. Further explanation on the routines is given as you go through
the guide.
Utility Execute
======= =======
Print Background and move right 4 pixels &1900
Print Background &1907
Print single sprite on selected screen &2C00
Print all introduced sprites &2D11
Do orders for all introduced sprites &2D43
Introduce a single enemy sprite &2D8E
Automatic introduction routine &2DB7
Check for collisions &2DEA
Introduce background sprite &2ED8
Introduce one of your sprites &2EFC
Force introduction of sprite at a point &2F27
Clear introduced sprites &2F45
Print score &2F50
Increase score &2F97
Reset score &2FB9
Show built up screen after raster scan &3014
Show built up screen &3019
Reset sprite handling system &304D
Destroy introduced sprites not fully on screen &3093
N.B. None of the routines preserve the registers.
Print single sprite on selected screen
======================================
To print a sprite to screen the following zero page memory locations should
be set up:
&7A = ASN
&7D = X co-ordinate
&7E = Y co-ordinate
To select which screen the sprite should be printed on enter the highest
significant byte of the top of the screen at &2C1A, i.e. &58 for screen 0,
&6C for screen 1.
It should not be attempted to print a sprite which overlaps or is outside
the screens perimeter, as the results can be unpredictable.
N.B. Memory location &72 normally tells other routines which screen is being
set up. Bit 0 should be 0 for screen 0 and 1 for screen 1. Screen 0 starts
at &5800 and Screen 1 starts at &6C00
Print all introduced sprites
============================
This routine will print all the sprites which have been introduced by any of
the introduction routines.
They will be printed onto the screen which is pointed to by Bit 0 of the
number staored at memory location &72.
You should not attempt to print sprites which overlap the perimeter of the
screen. To destroy all introduced sprites which overlap the edges use the
routine at &3093.
Do orders for all introduced sprites
====================================
This routine will cause the program to jump to the movement routines for all
introduced sprites.
Upon entry into the users instructions for the sprite several memory
locations will be set as below.
&73 = ASN (As explained in Introduction)
&74 = X Coordinate
&75 = Y Coordinate
&76 = Counter
These registers should be altered to change the state of the sprite and in
the state required upon the execution of an RTS by the users instruction
program.
If the users movement routine need to know the ISN of the sprite it can be
found in memory location &83 but this value should not be changed.
N.B. The user's program does not need to maintain any of the registers.
Introduce a single enemy sprite
===============================
This routine can be used to introduce a sprite which would be classed as an
enemy in a space invader game. 192 of these sprites may be created.
To use the routine certain memory locations should be set up:
&84 = ASN
&85 = X Coordinate
&86 = Y Coordinate
&87 = Counter
This routine assigns the sprite with an ISN.
The defense level of the sprite is transfered automatically.
N.B. If there is no room for the sprite no error will result and the sprite
will not be introduced. If the sprite has not been introduced the X
register be equal to zero.
Automatic introduction routine
==============================
This routine should be called regularly if in use. After being clled a
certain number of time it will cause the introduction of a sprite.
If this routine is planned on being used then at the start the following
memory locations should be setup as below.
&88 = 0
&89 = number of calls before first introduction.
&8A = 0
The following pages of memeory should be setup as below.
&27 = Delay before next introduction
&28 = ASN to be introduced
&29 = X Coordinates
&2A = Y Coordinates
&2B = Counters
When the sequence is completed memory location &8A should contain the number
1.
Sprites introduced by this routine are introduced as enemy sprites. (See
collision detection routine for explanation)
The defense level of the sprite is passed automatically.
N.B. If it is required for the program to start with introduction n then
memory location &88 should contain the value n.
Check for Collisions
====================
This routine checks for collisions between sprites introduced as your and
sprites introduced as enemys.
If a collision is detected then the defense level of both your sprite and
the enemy sprite is depleated.
If the defense level becomes zero then their ASN is replaced by either 6 or
7 according to size.
This routine does not use pixel perfect accuracy but considers the sprites
to be rectangular in shape.
N.B. When using this routine ASN 6 and ASN 7 should be small and large
explosions respectivley.
Introduce Background sprites
============================
Background sprites are introduced in exactly the same way as enemy sprites
but are not involved in collision detection and their number is limited to
32, and X register will equal 32 if sprite not introduced.
Introduce one of your sprites
=============================
Your sprites are introduced in exactly the same way as enemy sprites but
their number is limited to 32, and X register will equal 64 if sprite not
introduced.
Force introduction of sprite at a point
=======================================
This routine is used to introduce a sprite with an ISN of your own choice.
This routine has the drawback that it destroys any previously created sprite
which has the specified ISN.
To use this routine certain memory locations should be set up as below:
&73 = ISN
&84 = ASN
&85 = X Coordinate
&86 = Y Coordinate
&87 = Counter
The ISN are as below:
0 - 31 are Background sprites
32 - 63 are Your sprites
64 - 255 are enemy sprites.
Clear introduced sprites
========================
This routine will destroy all introduced sprites.
N.B. Introduced sprites destroyed by this routine cannot be recovered.
Print Score
===========
This routine will print the score in the top left hand corner of the screen.
The screen on which it will print is indicated by Bit 0 of memory location
&72.
Increase Score
==============
This routine will increase the score by the value specified at memory
location &64.
N.B. The valued store at memory location &64 should be in Binary Coded
Decimal. (See Glossary for explanation of BCD)
Reset Score
===========
This routine will reset the score to zero.
Show built up screen after raster scan
======================================
This routine waits until the raster scan has just finished building up the
screen before showing the other screen.
This pause prevents the computer changing the picture half way through the
frame and causing strange effects.
Show built up screen
====================
This routine does the same as the one above but does not wait for the raster
scan. This routine allows the machine to operate faster but can cause an
annoying flicker.
Reset sprite handling system.
=============================
This routine will set up all the programs except the automatic introduction
routine as it does not know the details required for this.
Destroy introduced sprites not fully on screen
==============================================
This routine will destroy any introduced sprite which is outside or
overlaping the screen boundaries.
Memory Usage
=============
As every eventuality cannot be planned for details on memory allocation are
given below.
&1700+ISN = Defense level of introduced sprite
&1800+ASN = Initial defense level of sprite
&1B00+ISN = ASN of introduced sprite
&1C00+ISN = X coordinate of introduced sprite
&1D00+ISN = Y coordinate of introduced sprite
&1E00+ISN = Counter of introduced sprite
&1F00+ASN = Least significant byte of instructions address
&2000+ASN = Most significant byte of instructions address
&2100+ASN = Width of sprite
&2200+ASN = Height of sprite
&2300+ASN = Least significant byte of sprite data start
&2400+ASN = Most significant byte of sprite data start
&2500+ASN = Least significant byte of sprite mask start
&2600+ASN = Most significant byte of sprite mask start
Examples.
=========
Please note some of the following examples will not work unless relevent
data has been created and loaded in, and the routines present in memory.
eg 1
10 REM Print sprite 1
20 MODE 5
30 ?&7A=1:REM Sprite 1
40 ?&7D=10:REM X-coordinate
50 ?&7E=10:REM Y-coordinate
60 ?&2C1A=&58:REM Screen 0
70 CALL &2C00
The routine above will print sprite number 1 at screen location (10,10).
eg 2
10 REM Print moving background
20 CALL &304D:REM Reset System
30 CALL &1900:REM Move background left 4 pixels and print it
40 CALL &3014:REM Show background after Raster Scan
50 GOTO 30
The routine above will show a background moving constantly by.
eg 3
10 REM Sprite on moving background
20 CALL &304D:REM Reset System
30 ?&84=1:REM Sprite 1
40 ?&85=10:REM X-coordinate
50 ?&86=10:REM Y-coordinate
60 ?&87=0:REM Counter (Value not relevent in this example)
70 CALL &2D8E:REM Introduce Sprite
80 REPEAT
90 CALL &1900:REM Print Background
100 CALL &2D11:REM Print Introduced Sprites
110 CALL &3014:REM Show Screen
120 UNTIL FALSE
N.B. All the above examples are writen in BASIC but would work from Machine
Code at a faster rate.
Glossary
========
Binary Coded Decimal (BCD) - This is a technique which uses 4 bits to
represent a number from 0 to 9. When numbers are in this form it is only
necessary to cut out one half of the byte in order to print each digit.
Mask - The mask is used to allow a sprite to be printed to screen without
effecting the pixels on either side. The scenery is ANDed with the mask to
cut a hole of the same shape as the sprite and then the sprite is ORed with
the background.
Least Significant Byte (LSB) & Highest Significant Byte (HSB) - When a
number pointing to a memory location is needed two bytes are used to store
the value. Bits 8-15 make up the HSB and Bits 0-7 make up the LSB.
The ASN is the number which you give a sprite, when using the filecreator to
turn the data into a form readable by the sprite emulation utilities.
The ISN is a number which theis different for every sprite which has been
introduced. The value is normaly allocated by the utilities whilst running
but it can chosen.
Variables Used
Complete Introducer
===================
Mem Location Purpose
&89 Delay counter
&88 Introduction number pointer
EQINT
=====
Mem Location Purpose
&84 ASN of sprite to be introduced
&85 X coordinate of sprite to be introduced
&86 Y coordinate of sprite to be introduced
&87 Counter value for sprite to be introduced
Sprite Location
===============
Mem Location Purpose
&7D Sprites X coordinate
&7E Sprites Y coordinate
&7F Least significant nibble of X coordinate
&73+&74 Memory location at which to store data
Score Routine
=============
Mem Location Purpose
&60-&63 Current score (in BCD)
&64 Value to increase score by
&72 Screen number in Bit 0
Display Screen
==============
Mem Location Purpose
&72 Screen number in Bit 0
SENDORD
=======
Mem Location Purpose
&83 Pointer
&73 ASN of sprite
&74 X Coordinate
&75 Y Coordinate
&76 Counter
SENDSPR
=======
Mem Location Purpose
&82 Pointer giving ISN of sprite
&72 Screen number held in bit 0
&7A ASN of sprite to be printed
&7D X coordinate
&7E Y coordinate
Print Routine
=============
Mem Location Purpose
&73+&74 Memory location at which to store sprite
&75+&76 Copy of &73+&74
&77 Y length of sprite to be printed
&78 Counter to check number of rows printed
&79 X width of sprite to be printed
&7A ASN of sprite to be printed
STATINT
=======
Mem Location Purpose
&84 ASN of sprite to introduce
&85 X coordinate
&86 Y coordinate
&87 Counter
Background Scroller
===================
Mem Location Purpose
&71 Pointer to page containing background data
&70 Pointer to position through page to start
&72 Bit 0 contains screen number
Main Collision Detector
=======================
Mem Location Purpose
&9B ISN pointer for enemy sprite
&9C ISN pointer for your sprite
&9E Your sprites ASN
&93 Your sprites X coordinate
&94 Your sprites Y coordinate
&95 Your sprites X width
&96 Your sprites Y length
&9D Enemy sprites ASN
&97 Enemy sprites X coordinate
&98 Enemy sprites Y coordinate
&99 Enemy sprites X width
&9A Enemy sprites Y length
Sprite File Builder
===================
Variable Purpose
ST Point for storing next sprite at
MT Point for storing next mask at
S% ASN of sprite
?&B00 X width of sprite just loaded
?&B01 Y length of sprite just loaded
FINT
====
Mem Location Purpose
&73 ISN for introduced sprite
&84 ASN of sprite
&85 X coordinate
&86 Y coordinate
&87 Counter
INTRODUCTION CODE
=================
Mem Location Purpose
&84 ASN of sprite
&85 X coordinate
&86 Y coordinate
&87 Counter
[Extensive details of testing removed]
Mikesoft/Andersonic Sprite Emulation Utilities
This project was developed and tested on a BBC Micro Model B. The
implementation satisfies all areas specified in the design and in this
respect is complete.
I consider my project to have been successful in all areas. [This is called,
unbelievable arrogance.]
The programs which I have written have great potential in terms of
expansion. Sprite handling is a very wide field, therefore, although I have
covered the majority of areas to some degree, there will always be certain
things which need writing, and so my utilities provide the bones to
construct such programs relatively easily.