top of page

"Logonite 256B intro" making-of

"Logonite" is a 256B intro for Amstrad CPC.

It was released at LoveByte party on Sunday, February 11th 2024.

« Logonite is similar to kryptonite. It is also known as a disease... This is insane - as I am sick. »


Here is a backup of the archive submitted for the party.


Disclaimer : this article does not explain the "animation by scrolling" principle. Whoever wants to learn about it should first have look at Logon's Run - 3D meets the aging bits demo then read its making-of. Intention for today's article is clear : guidelines to understand full source then get inspired to code your own tinytro. Be sure to check nice tricks in bold blue.



SIZE MATTERS

Actually file size is 255 bytes not 256.

(EDIT : this article is based on party version of the intro. A final version does exist which is 1 byte shorter - 254 bytes. Possibly like a challenge to the reader : how to save 1 more byte ?)


Executable file is loaded at address #0102 while entry is called at #016E.


First initialization bits are copying bytes to #0000 - #0038 so that RST#nn may be used.


Best part of this is about how LDIR ends before BC reaches zero.

Lastly opcode LDIR is overwritten : 1st byte from #ED #B0 is replaced by #00 #B0.

So loop by LDIR is stopped and NOP (#00) then OR B (#B0) are processed.

Benefits : no need to initialize BC before LDIR.

Then main code may start - reactivating interruptions by RST#38.



MEMORY MAP

Let's have a look at those (almost) 256 bytes.



RST#38 - no VBL check but counting HALTs

To get a 50Hz interruption, no frame signal is checked.

(...)

Counting 6 x 300Hz interruptions is shorter than checking port #F5 as coders usually do.



RST#30 - outing to crtc & gate array

It uses OUTI twice.

The unusual trick is about its calls :

outing either the crtc ( #BDxx then #BCxx ports ) or the gate array ( #7Fxx then #7Exx ports).

Calls for CRTC :

Calls for gate array :



RST#18 - starts with fake opcodes from data area

An easy trick : instead of calling RST#28 twice from RST#18, calling it once - then the code from RST#18 ends without RET but goes on with code at RST#28.

That said main trick on RST#18 is about 9 bytes as opcodes which were needed : not 8 - rounded 8 which would have been fine to put at RST#20 address. So what ? There are 7 bytes at address #0018 which are some data from a table (see yellow on memory map) ! By chance and/or with lot of care, those 7 bytes stand for opcodes which do not impact the required code.

OR 0 : DEC B : RLCA : LD B,5 : INC BC are useless opcodes on RST#18 - they come from data area.



RST#08 - ends with a RET which comes from data area

Similar to previous trick : RET is not part of source but part of data area.

CP L : RET are opcodes from data area - only RET is useful.



RST#00 - starts with 3 NOPs

Useless 3 x #00 at RST#00 address.

RST#00 starts by NOP:NOP:NOP which were generated by initialization LDIR.

Fine ! they do not count as bytes from the 256B executable file.

Also an easy trick : no call to RST#08 from RST#00 since the required code is ahead.



inc_y - final RET opcode is also #C9 as data

Easy one but 1 saved byte is 1 saved byte.

Last opcode RET has #C9 as byte which is used also in data area.



loop_X - 2 hidden opcodes at LD IX,#nnnn

(...)

Somewhere in the code were needed a fixed value - no matter its value. Idea : use the 16-bits value as opcodes to spare 2 bytes when jumping right to them.

2 bytes are saved by JR to bytes inside LD IX,#nnnn instruction.



Pseudo-random animations - POPing the OS

How to get pseudo-random numbers for animations ? it includes "random" numbers for square size, square colour and square locate on screen.

This has been achieved by POPing values from the OS area.

Init :

Loop :

Is there anyone who cares about crash after about a few hours of play ? I can't believe there will be someone who will wait so long just to see POPing bad values from screen at #C000 or so (and badly RETurn somewhere in memory). I didn't try.


Pseudo-generated music - reading bytes from OS

How to get pseudo-generation of cool numbers for music ?

This has been achieved by reading a carefully(?) chosen area from the OS.

Finally not so much memory deals with sound : 46 bytes.

Features are:

  • pseudo-random sequence of 8 notes

  • each sequence is played 4 times

  • 8 different sequences

  • fine tune/tone to get sound higher on big loop (256 notes = 8x4x8)

Bytes found from #B900-#B9FF sounded good enough for me. This was my 1st try, I tried other places and adjustments, but finally I'm back to this place and this "song".

Here are the 8 sequences - tone values which are sent to PSG B channel tone (reg3) :

< 1,7,6,6,6,8,7,1 > played 4 times with double-bell (1,1)

< 4,2,1,2,2,6,4,6 > played 4 times

< 7,2,2,1,2,4,2,1 > played 4 times with bells at half-sequence

< 2,2,6,4,8,1,1,4 > played 4 times with double-bell (1,1)

< 2,2,4,6,5,7,2,2 > played 4 times without any bell

< 8,2,2,4,1,1,4,2 > played 4 times with double-bell (1,1)

< 4,6,1,8,1,2,3,3 > played 4 times

< 2,4,3,7,4,3,8,4 > played 4 times and sounds like the start of the song

The higher sound 1 (which I call "the bell") rings at quite a good pace to rhythm the song : a few double-bells (1,1), once at half-sequence (x,x,x,1,x,x,x,1), but also a full sequence without any bell. Amstrad OS is quite a good composer - better than I am.

I was also lucky with last sequence which loops to 1st sequence. Let's have a look at 12bit tone (reg3 as upper byte and reg2 as lower byte) to understand how it loops :

< 207,406,305,704,403,302,801,400 > last sequence at #B900

< 1FF,7FE,6FD,6FC,6FB,8FA,7F9,1F8 > 1st sequence at #B9E0

Thanks to fine tone, the bell <20n> sounds very similar to <1Fn> - and finally 2nn bells from last sequence are heard as if they were low 1. This turns the last sequence to sound as if it was the 1st song sequence with the lowest 1. At least I hear it like that - at least I understand what I tried to explain.

The funny thing is that it would be a different song on a CPC464 since the memory OS differs from the one on a CPC6128 which is the computer the tinytro is aimed at. I am aware that the song which is generated on CPC464 is not as good with the bytes I chose for CPC6128. Note that CPC464 would also show different animations and squares.

Source :

Some note about unrolled loops : yes RST#18 is called 4 times in a row. What about a loop such as : LD B,4 : RST#18: DJNZ $-1 ? This would cost 5 bytes - while repeating 4 times RST#18 costs 4 bytes only.



Everything comes to an end !

I believe you're now ready to have a look at full code.

If you're on main loop, keep an eye on the comments about registers right there :


Video which was recorded @50Hz thanks to Winape emulator :



Overflow / Logon System

Thursday, January 16th 2024.

Gameboy from LOGON'S RUN

 Overflow's RAndom Memory

bottom of page