Draw characters or graphics on the ZX Spectrum

ZX80, ZX 81, ZX Spectrum, TS2068 and other clones
Post Reply
Fabrizio
Member
Posts: 116
Joined: Tue Jul 11, 2017 9:28 pm

Draw characters or graphics on the ZX Spectrum

Post by Fabrizio »

Hi

I am trying to draw some characters on the Spectrum for my game https://github.com/Fabrizio-Caruso/ASCII-CHASE/
conio.h has some issues and it is super slow (I have open some bug reports).
printf scrolls the screen if the 24th line is drawn.

Do I have other options? Even low level solutions like pokes would be OK if not too complicate? Any documentation?

If characters are not possible, where do I find info with one example on how to draw simple sprites?

https://www.z88dk.org/wiki/doku.php?id= ... umentation
has nothing other than a table of contents.

Fabrizio
alvin
Well known member
Posts: 1872
Joined: Mon Jul 16, 2007 7:39 pm

Post by alvin »

Fabrizio wrote:I am trying to draw some characters on the Spectrum for my game https://github.com/Fabrizio-Caruso/ASCII-CHASE/
conio.h has some issues and it is super slow (I have open some bug reports).
printf scrolls the screen if the 24th line is drawn.

Do I have other options? Even low level solutions like pokes would be OK if not too complicate? Any documentation?

If characters are not possible, where do I find info with one example on how to draw simple sprites?

https://www.z88dk.org/wiki/doku.php?id= ... umentation
has nothing other than a table of contents.
There are two ways you can go - the classic library and the new library.

The newlib has a few sprite engines sp1 (which are true sprites with background tiles) and bifrost/nirvana which can do a number of moving objects that are handled like printing rather than sprites. The special thing about bifrost/nirvana is the colour resolution on a stock spectrum becomes 32x192 through carefully timed display.

The newlib's text terminals are not ansi but do have control codes for positioning text, changing colours, etc. They shouldn't scroll when printing on row 23. This is not the fasted way to print (although maybe it's fast enough) as each print has to go through the stdio mechanism to reach the driver.

At the lowest level there are the display file address manipulators. The spectrum's display is memory mapped and divided into two parts - one is a straight bitmap with bits indicating whether pixels are set or not and the other is a colour overlay at 32x24 resolution. There are many functions, eg, zx_cxy2saddr ( character x,y to screen address) that will return an unsigned char * to a byte in memory that can be poked easily to do pixel plotting, character drawing, etc. This will be fairly fast.

There is a beginner's tutorial for the spectrum and the newlib here:
https://github.com/z88dk/z88dk/blob/mas ... Started.md

It has a section on the display file address manipulators in part 3 where they are used to plot and draw lines. You can also use them to print letters and numbers:

Code: Select all

#include <arch/zx.h>

void printc(unsigned char x, unsigned char y, unsigned char c)
{
   unsigned char *p, *dat;
   unsigned char i;

   dat = 15360 + c*8;                // points into the rom character set
   p = zx_cxy2saddr(x, y);

   for (i = 0; i < 8; ++i)
   {
      *p = *dat++;
      p += 256;
   }
}
This takes advantage of the spectrum's display file organization - once you have the address in the display file of the top of an 8x8 char, the next pixel line down is found by adding 256.

Other examples can be found here:
https://github.com/z88dk/z88dk/tree/mas ... T/EXAMPLES

In particular beepfx.c from that directory for sound effects and in zx/sp1 there are some small examples using sprites. Bifrost and nirvana have simple demos in there but for bfrost the author has 8 series of programs that illustrate more complicated uses. Only the first is in z88dk now in https://github.com/z88dk/z88dk/tree/mas ... advanced_1 but it shows how to quickly build a tap file from a bifrost game without resorting to writing a basic loader. The author's own examples are pointed to in one of the tutorial links above but they are written in an old fashion using a previous instance of the library (before we incorporated it into z88dk) and needs some fixes to compile and can be sped up quite a bit, which this one example can illustrate.

The best example of an open source nirvana game is this:
https://bitbucket.org/CmGonzalez/pietro_bros/src
but it is quite large.



The classic library also has the display file manipulators and a non-ansi terminal which may be faster. There are graphics functions for drawing, etc, but for your particular use you would be more interested in something more sprite-like. There is a set of monochrome functions for putting sprites (or bitmaps), the best example is probably https://github.com/z88dk/z88dk/blob/mas ... microman.c . But it may be too slow for what you want.
stefano
Well known member
Posts: 2145
Joined: Mon Jul 16, 2007 7:39 pm

Post by stefano »

There is a quick way to get nice results with the sprite editor and the classic library using the mono sprite stuff.
It is slow but fairy portable and works.
Fabrizio
Member
Posts: 116
Joined: Tue Jul 11, 2017 9:28 pm

Post by Fabrizio »

Thanks guys for the hints!

I am a newbie with Z88dk and I do not understand how to compile in a way to get my code to work.
My code is plain ANSI C + some conio.h (but I can even get read of conio if necessary).
If I get rid of conio I need something else to print a character at position x, y. I need to know how to compile my code with whatever solution is suggested.
There are lots of combinations with two compilers, two main libraries and many specific libraries and lots of options.
Ideally I would have used conio as a start because it is portable but it seems it is broken in Z88DK. So I need an alternative within Z88DK.

What is classic and what new lib?
Is ansi=classic?? How do I chose the new lib? Can I use conio + new lib?
What is mono sprite sutff? How do I include it? Any doc?
alvin
Well known member
Posts: 1872
Joined: Mon Jul 16, 2007 7:39 pm

Post by alvin »

Fabrizio wrote:What is classic and what newlib?
Is ansi=classic?? How do I chose the new lib? Can I use conio + new lib?
The classic library is the original z88dk library that has been around since the beginning of the project.

The new library is a rewrite from scratch aiming for a subset of C11 compliance. The standard library portion is nearly complete and there are many extensions implemented but some things from classic have not been brought over yet (like graphics, the ansi terminal and some others). But there are new things in the newlib that aren't in classic too

In the future, the two will be brought together so they share largely the same feature set but they will remain separate. The stdio implementation is simpler in classic so that it can result in smaller programs when stdio is used for disk, etc. The newlib implementation aims to be like unix and is therefore larger in size.

If "-clib=sdcc_iy" or "-clib=sdcc_ix" or "-clib=new" is on the compile line you are using newlib. Otherwise you are using the classic library.

If you are interested in newlib the short tutorial introduction to using it with the zx spectrum is a good way to start:
https://github.com/z88dk/z88dk/blob/mas ... Started.md
It will tell you how to construct a compile line and what some of the options mean. It will also touch on the display file manipulators mentioned that let you easily poke to the display, as well as things like reading the keyboard. After that the examples in newlib ( https://github.com/z88dk/z88dk/tree/mas ... T/EXAMPLES ) will give more ideas. Compile lines are either in the .c file or in the readme of the directory. After reading the tutorial the compile lines shouldn't be too alien.
Is ansi=classic?? How do I chose the new lib? Can I use conio + new lib?
There is no conio in the newlib; instead the preference has been for special extensions applied across targets (the input library for reading keys, joysticks and mice, eg).

An ansi terminal usually means a character display device that obeys the control codes understood by the dec vt100 ( https://en.wikipedia.org/wiki/VT100 ). There are other standards as well like the vt52 but usually a vt100 is what is meant. Because very few of the z80 targets in z88dk have an actual vt100 terminal (there may be cp/m machines that do), z88dk has to put software in between stdio and the actual computer to translate vt100 codes so that the target can behave as if it is a vt100 terminal. This way standard software from the 70s and 80s can run on the computer even if it can't natively. So this can slow things down, especially given that the ansi emulation layer is quite general.

You don't have to use a vt100 emulation layer. You can use a simpler or more native terminal instead. For the spectrum that means using a terminal (character output device) that understands the spectrum's native control codes. Spectrum basic understands specific sequences that move cursor, change colour, etc, but these are not the ansi escape sequences. Because these are simpler, the terminal code is also quicker. When you have the clib=ansi stuff in your compile line you are selecting the ansi emulation layer.

The classic library has the ansi emulation layer available. The newlib does not. Both the classic and newlib have simpler terminals more aligned with the native Spectrum's print routines. For the newlib, that tutorial link above will talk about the terminals. For the classic library there is this: https://www.z88dk.org/wiki/doku.php?id= ... ole_driver which will also explain the compile lines and the difference between the vt100 driver and the regular driver.
What is mono sprite sutff? How do I include it? Any doc?
I think the only doc is this one for classic mono sprites:
https://www.z88dk.org/wiki/doku.php?id= ... onosprites

And related again for classic:
https://www.z88dk.org/wiki/doku.php?id= ... nographics
Post Reply