Mar 272015
 

This is a continuation of an earlier article about ZX Spectrum loaders. Hold on to your hats and get your calculators ready, we are going downhill! (Part 1, Part 2)

Last time I finished up stating that next time we’ll need to count and weigh each and every processor tick. This time, our closest ally will be a waiting loop in a routine LD_EDGE_1. Let’s recall that routine:

Do you see it there in LD_DELAY? Yes? So that’s it right there! It takes 7T + 21*(4T+12T) + (4T+7T) = 354T, which is quite a lot of ticks for our purposes. Which purposes, you ask? Well, mostly likely a counter for how much data is remaining to be loaded.

Graphical indicator

In my text game Poradce (The Consultant) I used, besides for some scary flashing, some kind of a “thermometer” that showed how much remains to be loaded. It was that little something on the left side of the screen…

This effect is simpler than you might have expected. The length of the column is almost exactly “file length / 512” (I say “almost exactly” because I had painted it a little shorter…) So I’ll take the upper byte of remaining number of bytes (which is in register pair DE), divide it by two, add offset from the bottom of the screen, convert the coordinate to an address on the screen and mask the byte with value %11100111 – therefore everything else remains except for just two points in the middle, which, coincidentaly, exactly represent our “thermometer” and they get overwritten. To recalculate, I even use a routine PIXEL-ADD ($22AA) from Spectrum’s ROM, which takes the coordinates in B and C (the same coordinate system the PLOT has) and calculates an address on the screen (HL) and a mask of the point (A).

As you can see, I interfered with the timing loop. At the beginning I popped out into my own routine which operates that effect (it is 305T with that diversion) and after returning back I still have enough time, so I’ll wait another 50T, which translates to 355T, which it is pretty much exactly our magic number!

Numeric indicator

If you rather want to show a number instead of some dwindling column, things get more difficult. Each digit must in fact be drawn on the screen, which means eight writes for each digit. And for a three-digit counter this is quite a lot of time, it won’t fit into 354T. So you need to chop the algorithm into parts that fit within this time limit and call them in sequence. The second set of registers and index register IY will be your invaluable tool for this.

Games from Hewson and Czech programs from Universum (I think) had some very nice counters, they used their own font and they also shown fliping digits effect. In another text game I used just a simple counter of “the number of bytes / 64”, which for 48kB block still fits into three digits. At the beginning I prepared the desired digits (in decimal!) into registers D and E (resp. into the mirror ones):

This effect did not take place directly in LD_EDGE but in LD_8_BITS instead. However, LD_EDGE has been modified so as to use significantly different timing values during loading:

The effect ifself then played out as follows:

This, of course, deserves a few explanatory notes:

Registers DE contain the counter itself, stored in BCD coding. The register C contains a bits counter, register B contains a bytes counter. Once they calculate down to zero, the counter gets decreased by 1, the result gets adjusted by DAA instruction and prepared for the actual printing of characters. HL holds the value of $3D00, which coincidentally is an address in the ROM where numbers are stored, and IY holds an address of the routine LD_CHARS, which displays the digits.

When you chop the routine into pieces, you are left with two options. You either edit the code and rewrite the address where you need to jump next, or you store the address somehow. Here it is in the IY register. By using a simple trick CALL LD_RETHERE (as in RETurn HERE) you go back to LD_8_BITS, while the return address gets into IY, so that during the next call the JP (IY) will be directed to the next piece. Note that printing of characters is chopped into small pieces by calling LD_RETHERE.

Time indicator and more

Calculating remaining time is more complicated than counting bytes. You either have to count every bit differently (a one bit is twice as long as a zero bit), or use an interrupt (yes, interrupt in loader!)

I was looking for an example of the first approach, but before I could comment on it, Busy called me and said that he had found his Overscan loader source code, asking me if I want to publish it. So here we go, with Busy’s courtesy, Overscan loader!

(Time calculation and graphical effects are included!)


And here is the source code with Busy’s comments (Thanks!) Because it is a bit long, I shall say my goodbyes right now and wish you good luck in your own experiments.

(Translated by Ondřej Ficek)

 Leave a Reply

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code class="" title="" data-url=""> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong> <pre class="" title="" data-url=""> <span class="" title="" data-url="">

banner