8-Bit Software Online Conversion

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.