Intro to Graphics: Z80 Assembly Language for the ZX Spectrum, Episode 11
Vložit
- čas přidán 1. 08. 2024
- This is the eleventh episode of a series that will teach you how to program using Z80 assembly language, specifically for the Sinclair ZX Spectrum. In this episode, we learn the basics of generating graphics for the Spectrum using tiles and bitmaps.
All code and materials for this series are available on GitHub: github.com/SlithyMatt/zxs-ass...
Join our Patreon community: / slithymatt
Chapters:
00:00 Intro
01:12 Fixed Graphics Characters
03:49 User-Defined Graphics (UDG)
06:04 Bitmap Addressing
12:38 Attribute Addressing
16:12 Example Program Intro
17:02 Example UDG Tile Map
20:28 Example Fixed Graphics Tile Map
22:48 Example Bitmap Conversion
31:54 Example Tile Map Rendering
33:22 Example Bitmap/Attribute Loading
33:55 Example Bitmap Manipulation
36:10 Example Demo - Věda a technologie
The way the video memory is organized is fascinating.
Good job Matt! You incorporated several different techniques into one fairly short and easy to follow tutorial.
minor detail: LDIR is not fastest way, but simplest with good speed (and best option for tutorial like this). :)
(there are two faster ways, but require lot more code, either unrolling ldir by `ldi` instructions, or using sequence of pop+push through all registers for even faster memory transfer).
The gfx converter looks nice. Fun fact: The "pro" level tools like this back in the days did not pick paper/ink randomly, but counted pixels of each color in the 8x8 char, and selected the paper/ink to have ink fewer pixels. Which leads to fewer ones in the bitmap, which leads to slightly faster load times from tape (as ones are encoded as longer tone than zero).
The way hardware people explained it to me, the reason why the bitmap ram is in a crazy config is that ULA can read from several RAM chips at the same time.
Thing is, though, the way the original Spectrum handled its RAM was that it had 8 RAM chips, with each one contributing 1 bit--so the ULA would have to read from all 8 chips to assemble a single byte. So I'm not sure that this layout actually made any difference in that regard.
@@d2factotum It has to do with the fact that the ULA is trying to read attribute data and pixel data as quickly as possible packing everything into the bottom byte the way it does allows it to use DRAM page read mode, which is faster, as bits 3-5 of the pixel data will be the same for the attribute and pixel data for the Y coordinate.
Thank you Matt!!
Flashing was famously used to animate the Manic Miner loading screen.
Another thing abou UDGs is that their position in RAM is defined by a system variable UDG - which can be changed. So if you do have more than 21 UDGs then you can define a second portion of memory (maybe the printer buffer for the ZX printer) for a second bank of UDGs. It being quicker to just change the system variable than redefine UDGs on the fly. It is even possible to change the normal 96 printable characters (32 - 127) - by changing the CHARS system variable to point to somewhere in RAM (after copying from the ROM, or defining your own character set).
3:28 thanks for that! 😉
(I didn't expect to find the Ukrainian flag in Z80 assemly language series for ZX Spectrum)
So, those "later episodes" you've been referring to....where can I watch them?
If you have a time machine, you can watch them in the future right now.
How does the Spectrum draw sprites? UDG's or Bitmap data?
Either will work, but most games use just straight bitmap. UDGs require using the ROM routines. But there are no hardware sprites on the Spectrum like there is on the Commodore 64.
@@slithymatt Spectrum's hardware sure was very limited compared to the C64. But what a lot of programmers did with it was incredible.
Any good program to convert the graphic?
I'm doing these tutorials with completely different tools and I can't find any program that converts images and saves the bitmap and attributes into separate .bin files.
The python script I use should work for that. It's right in the repo linked in the description, in the Lesson 11 subdirectory
@@slithymatt And it will work in any program or website that has a python compiler?
@@noveltyman6723 yes
👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍
how did anyone do anything on old computers
Carefully. 🙂
LOL I think the same thing about modern computers.
@@SomeGuyInBrisVegas It's an easy life compared to the 8 bit era.
jp is faster than jr when the branch is taken (jp=10 T-states, jr=12 T-states).
Yup, but JR Is only 8 when not taken, so it's perfect for "jump out" loop termination like this. I could further optimize by storing the loop address in IX and doing a JP (IX), but I didn't want to take the optimization discussion that far off track.
If only SINCLAIR had used the ZILOG Z800 and 64KB of 16bit RAM might have made for a much faster computer as you won't have to do multiplication and division the long way and just use mulu,muls and divu,divs
Considering that the Z800 was an unreleased prototype in 1985, that probably wasn't going to happen in a low-cost computer in 1982.
@@slithymatt Actually OLIVETTI in Modena Italy did release a pc running the said processor and I suspect that it did sell well and would have been much faster than the Sinclair Spectrum, Seems like there is a guy in Germany has one and he just happens to be a CZcamsr search for OLIVETTI running ZILOG Z800 processor.