GFX - Preparing graphic resources when creating games on the ZX Spectrum

Preparing resources for games 
Alone Coder 

Imagine that you wrote an almost goto─ 
first game, and then it turns out that there is no 
one character animation is enough. 
 With traditional (for the Spectrum of the 90s 
years) development method you will have to from─ 
efficiently convert the phases of this animation 
and then glue them to existing ones - whatever 
possible by violating the numbering of sprites, that is 
everything will have to be tested again. 
 Imagine that the game is completely ready, 
but in the process of testing in some ca─ 
shoals detected. With traditional 
method you will have to convert these 
cards and repack the game disc, 
why they might golocation 
files - and again full testing. 
 Or another typical situation - sprites 
YOU DO NOT draw, maps are NOT drawn by YOU, they draw 
these are individual artists and level designers, 
and they want to see the result of their work 
in the working version of the game without your help. 
 What to do?
 All these problems are solved automatically 
assembly. 

Automatic assembly

   Let us make a reservation that some authors
Spectrum games are debugging Snap games─
shots, and when assembling the final version (if
it comes to her - after all, it’s a psychological game
already ready, and you can retire) they have to
re-debug the game with the bootloader.
Don't do that. Later in this article we will dis─
looking at the release build from the very beginning
games. What about debugging functions? You can turn them on─
start and stop using conditional compilation.
   "Release build" means that the game is not─
gko can be released at any time, and
if not published by one author, then it’s easy
maybelifted from the archives by another (wed─
insert with "dead" sources on the site
opensourcezx,which no one knows anymore, 
how to assemble). In addition, you can easily and
easily make bug fixes, versions on
in all languages and for all formats (tap, trd,
SD card...), even if all at the same time
one button.
   Assembly is a sequence of actions─
Viy. And these actions should not be done with your hands,
and by commands in the body file. What could they be?
teams?

 - compilation of assembly code from input─ 
relevant inclusions (for example, assembler 
SjASMPlus).The game does not necessarily have one non─  
dependent piece of code - there is an intro, outro, 
menu... 
 - packing a code block (for example, uti─ 
cast mhmt ) 
 -converting the image to internal format─ 
mat (for example, under the screenATM-Turboutility 
convega - see nedoos/src/games/barbaria/ ) 
 - pulling sprites into the internal 
format (for example, utility nedores ) 
 - conversion of maps, scripts, etc.
 - creating a disk/tape/SD card image, 
copying files there (for example, utilities─ 
tami trdtool, nedotrd, dmimg, bin2tap ) 

 How to bind sprites to code

   There are two typical situations: a) block
sprites contains sprites of the same size, with
access by number (there may be such blocks
a lot); b)  sprite block contains sprites
different sizes with access by name.
   Despite the fact that the first option is sometimes
yeswins in size, I recommend using─
use the second one. The fact is that in the rooms
sprites are very easy to get confused, especially
if you (or a successor to your project)
you will return to the game after a long time
time.
   Having access by name makes it easy to describe
structures with animation. Ideal, of course
it would be possible to animate sprites in programs,
which are intended for this purpose (for example,
AsepriteorPixelorama), but impo utilities─ 
the mouths of them have not yet been written. And the old specs─
Don't support Trumov's sprite editors─
layers, animation clearance and color are on point─
ku. Therefore, for promising games for now
you have to pull sprites frombmp.
 Fortunately, for pulling from bmp there is
tested utility  nedores  (included
NedoOS), which is easy to expand with new ones 
formats.
   What doesnedores do?
 It opens a bmp file (17-color -
for transparency with color per point) from
first parameter, script-descriptor spry─
product from the second parameter and the name of the outputассемблерного файла из третьего параметра.
Скрипт-описатель выглядит, например, так:

;x,y,wid,hgt,defaultcolor (0..15 that will 
           ;be used as ink in empty chr$) 
;6912: color 0 in bmp is for mask 
;16c: color 16 in bmp is for mask 
;formats: 
;B: colour tiles: wid, hgt, data 
;s: b/w sprites:wid8,hgt,(antimsk,antipix) 
;w: b/w sprites: antipixelsw, antimaskw... 
;W: b/w image by columns 
;T: colour tilepic 28xN (size 0xN00 bytes) 
;x: 16c spr: wid/2,hgt,(column:and,or..), 
      ;(0x4000-((hgt-1)*40))...,prsprqwid 
;L: 16c 16x16 tiles (N of tiles in 
                        ;"defaultcolor"):
               ;N of tile for each square 
;i: 16c image;P: DDp palette 
human0=x,0,0,16,16 
human0step=x,16,0,16,16 
human1=x,32,0,16,16 
human1step=x,48,0,16,16 
... 
bulletright=x,16,16,8,8 
bulletleft=x,24,16,8,8 

 Here for each cut sprite
specified name, format ("x" - sprite format
for sprexamp/prspr.asm ), location at
picture and size. prspr by default under─
holds any even width and height
8, 16, 24, 32, but if desired this list
easy to change or add.
   As a result of performing nedores fuss─
produces the following assembler file:

human0=$+4 ;ld iy,human0:call prspr 
 db 0x08 ;width (in double pixels)
 db 0x10 ;height
 db 0xff,0x00 ;mask,graphics
 db 0xff,0x00 ;... db 0xff,0x00
 db 0xff,0x00
 db 0xff,0x00
 db 0xff,0x00
 db 0x47,0x00
 db 0x47,0x00
 db 0xff,0x00
 db 0xff,0x00
 db 0xff,0x00
 db 0xff,0x00
 db 0xff,0x00
 db 0xff,0x00
 db 0xff,0x00
 db 0xff,0x00
 dw 0x3da8 ;смещ-е до след.столбца экрана

 db 0xff,0x00 ;маска,графика
 db 0xff,0x00 ;...
 db 0xff,0x00
 db 0xff,0x00
 db 0x47,0x00
 db 0x00,0x08
 db 0x00,0x09
 db 0x00,0x09
 db 0x00,0x08
 db 0x47,0x00
 db 0xff,0x00
 db 0xff,0x00
 db 0xff,0x00
 db 0xff,0x00
 db 0xff,0x00
 db 0xff,0x00
 dw 0x3da8 ;смещ-е до след.столбца экрана
 ...
 db 0xff,0x00 ;маска,графика
 db 0xff,0x00 ;...
 db 0xff,0x00
 db 0xff,0x00
 db 0xff,0x00
 db 0xff,0x00
 db 0xb8,0x00
 db 0xb8,0x00
 db 0xff,0x00
 db 0xff,0x00
 db 0xff,0x00
 db 0xff,0x00
 db 0xff,0x00
 db 0xff,0x00
 db 0xff,0x00
 db 0xff,0x00
 dw 0xffff ;невозможное смещение =признак
                            ;конца спрайта
 dw prsprqwid ;туда будем выходить

human0step=$+4 ;ld iy,этаметка:call prspr 
 db 0x08 ;ширина (в двойных пикселях)
 db 0x10 ;высота
 db 0xff,0x00 ;mask,graphics
 db 0xff,0x00 ;...
 db 0xff,0x00
 db 0xff,0x00
 db 0xff,0x00
 db 0xff,0x00
 db 0xff,0x00
 db 0x47.0x00
 db 0x47.0x00
 db 0xff,0x00
 db 0xff,0x00
 db 0xff,0x00
 db 0xff,0x00
 db 0xff,0x00
 db 0xff,0x00
 db 0xff,0x00
 dw 0x3da8 ;offset to next screen column
 ...

   For the "color per dot" mode, you can also
import an image by columns ( "i" -
applicable for fonts) and a set of tiles
16x16 with a description of which number is where
in the picture (for examples, see src/games/br/ 
images/W1LAND.dat  and in src/games/sprexamp/ 
tiles.dat ). 
   Alsonedores can import black─
white sprites "s" and "w" and colored tiles 
"T"  for mode 6912 (used in 
nedolang/_sdk/sprite.i and in Dizzy SE ). Mo─ 
You can also import individual color tai─
ly for this mode ( "B").You can import─
Arrange the b/w picture in columns ( "W" ).
   Since the output of nedores is
source code, it can be compiled for any
address and still have access to sprites
by name. Here's how a typical one is described
animation:

heroanim_runright 
 dw HERORUNRIGHT0 ;phase sprite
 db 4 ;delay of this phase
 dw HERORUNRIGHT1 ;next phase sprite
 db 4 ;delay of this phase
dw HERORUNRIGHT2 ;next phase sprite
 db 4 ;delay of this phase
 dw heroanim_runright ;address next.
 ;animations
 ;(after the end of the current one)

   But if the sprites don't fit in the country─
tsu, then the task becomes more complicated... In the example 
sprexamp  instead of sprite addresses after all 
numbers are used (or rather, address addresses─
owls), which were in the same place (sprdata.asm)
describe as constants. But no one stopped─
You can do just that. You can write uti─
Lita automatic number generation
sprites from their addresses, or you can with whom─
peeling games include sprite pages and
Keep track of the page numbers yourself.
   Of course, the page numbers of the sprites are long─
need to be logical, and not those that
are written to the port, because the computers on which
your game will launch, maybe
different, but under  NedoOS  the game can generally
be loaded into random pages.

Working with maps

   Some games require their own re─
map dactors (for example, if the map builds─
from the walls, as inWolfenstein 2004,or from
objects, as in Ball Quest and Dizzy). But
For most games a rectangle is enough─
new grid and editorMapWin.This editor─
Tor allows you to write your own script
saving in the required format, and this
the script can upload more than one file
(for example, the coordinates of enemies separately).
MapWinalso supports multi-layer maps. 
mouths (location of objects, inputs, outputs
it’s logical to do it on a separate layer) and auto─
automatic cutting of pictures into tiles.
   Examples of working withMapWincan be seen in
Unreal Project and sprexamp in NedoOS. 
 Sometimes it is more convenient for a level designer to draw
map in the game itself (this was the case inSpace
Monsters meet THE HARDY ). In thiscase 
it is better to abandon the external editor,
so as not to make converters in both directions.
Then there are two approaches:
 1.If the game itself can save cards, 
then you just need to write it in the assembly batch file 
reading the finished file from the image in directo─ 
riu with sources. 
 2. If the game can't save, then you need to 
give instructions to the level designer on how to do it 
snapshot, and write it in a separate batch file 
calling a utility that will retrieve the ka─ 
mouth from the snapshot. It’s good if for this 
enough to bite the file (for example, utilities─ 
toynedopad).You can register this call and 
in the assembly batch file, but then the snapshot will become 
original map source,which is unhygienic. 

 Working with music and sounds

   The feature of music and sounds is the same as
map editors ( Vortex Tracker , AY FX
Editor ) unload them in a suitable form 
for use in code. Our task is
batch file - just compile the player with
these files or take into account in the loader,
so that they are loaded separately. To the musician
it is enough to know under what names they
must be saved.
   If the player is non-standard, and its com─
the peeler does not work on the command line, then
you will have to rebuild the music into binaries
manually every time the music changes─
las. This is inconvenient, and I hope that the authors
compilers in the future will take this problem into account
and solve it, for example, like this:
 - By default there is a compiler that 
just run on the command line with 
file name. 
 - If the compiler requires manual settings─ 
ek, then you can make its interfaceseparately 
from the compiler itself and pass it to the parameter─ 
options on the command line with the ability to co─ 
pirating to the batch file. 
 - If the compiler generates assembler─ 
ny source, then parts of this source should ─ 
must be included so that the user can do it himself 
correct address, input, output and position 
module relative to the player. 

 Working with scripts

   It's usually easiest to edit
scripts in text form. To avoid writing
for them there is a separate parser, scripting language lu─
It’s better to take a ready-made one - assembler or C. They
allow you to use macros to define
the necessary command words, and if special commands
no, then you can simply write throughDBandDW.
You can write scripts inNedolang,but not
as long as it's not theremacros, then scripting
limited to writing similar structures
data.
   Another option is if the game itself is
look for escape sequences in
text. This game will run slow─
her. If the game is mainly based on dia─
logs, then this is tolerable. It is intolerable if under
these dialogues will eventually run out of space
in memory. Then you will have to develop from─
a useful compression utility, and for this purpose
start from a notation of the form:

text1 
 db "text 1",0 
text2 
 db "text 2",0

and go to the table of message addresses,
which this utility will also generate─
vat. It's good if it generates it in
assembly text form:

text1=_+0 
text2=_+5 

 Then you don’t need space for the table, you can
include this assembly text and references─
directly onto the markstext1andtext2.
 It is clear that for this the structures are from ss─
boxes should not be packed in the same aisle─
de same as texts.
   The topic of scripts is very extensive, options
many, some of us alreadydiscussed in
previous issues Info Guide. But you can’t overcome it─
There are no problems with automation.

 * * *

Please note that automatic 
assembly does not necessarily imply Win─ 
dows. It can also be used on the Spectrum 
for example, in NedoOS.Even inALASMI take a long time 
time used automatic assembly from 
two steps (compilation and packaging), this 
made life much easier when writing sys─ 
dark programs. There was more that could be done 
arbitrary calls during compilation 
(directive RUN ) - for example, for reading C─ 
dark time. But more complex after─ 
action sequences ALASMdo not support─ 
is. 
I wrote onALASM18 years in a row and still 
I return to it from time to time. But less and less 
and less often. 
When you switch to automatic 
assembly, at first it seems difficult or me─ 
long (after all, the result does not appear immediately 
in memory!). But once you set it up properly─ 
build a development environment and body files, and everything 
the gateway to manual assembly seems pointless 
and is fraught with errors. You will especially appreciate it─ 
those if there are already several people in the project 
or long-term support is planned. 

Share your thoughts about the article