Sprites: things that move without the screen moving
Everything drawn on this machine was in a cell. Something between two cells meant rewriting both; something moving a pixel at a time meant rewriting them sixty times a second, which is affordable for one thing and not for twenty. A sprite is put at a pixel and the device draws it over whatever is behind, so moving it costs two bytes. MADE OF TILES, which is the decision the rest follows from: m by n taken in reading order from one index, so there is no second pixel format, no second kind of memory, and nothing a sprite can show that the map cannot. A 16 by 16 character is four tiles and the background can name the same four. 256 entries of 8 bytes at 0xC000 in the atlas - eight so the entry address is a shift, the same no-multiply argument as the palette's four. Position is signed and sixteen bits, because 640 by 400 does not fit in a byte and a sprite has to be able to sit half off the left rather than appearing whole at the edge. A PIXEL OF ZERO IS NOT DRAWN, or every sprite is a rectangle. Tested before the attribute is added, so a hole belongs to the art and not to the colour scheme. The same rule the other way round is what "behind" means: drawn only where the background pixel was zero, so a thing walks behind a pillar and in front of the floor in one frame. All of them draw, every frame, so they cannot flicker. Real machines dropped them per scanline because they had a fixed number of shift registers; this has a loop. The limit is the size of the table, which is a constant rather than a property of what is on screen. And the system takes them down at exit. The sprite table sits in the gap the screen save walks around - to the end of the map, then the palette - and that is right, because nothing the shell draws is a sprite: there is nothing to give back, only something to take away. Otherwise a program that put a ball up and left would leave it over the prompt, in front of everything, with nothing able to type it away. Sprite.asm deliberately leaves its own, because a program that faulted could not have cleared it. Every check here was re-broken and failed: transparency, reading order, draw order, priority, and size. Size needed breaking twice - the first attempt did not compile, and a silent build failure had left the old binary passing. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01E2JrLzFvuFX9fgi1LDRjrW
This commit is contained in:
co-authored by
Claude Opus 5
parent
eee95ef0ce
commit
a916103a7f
@@ -5150,6 +5150,32 @@ screenSane:
|
||||
; the floor for the programs that saved nothing.
|
||||
INIA 0x03
|
||||
OUTA 0x39
|
||||
|
||||
; ---- And no sprites left standing over the shell ----
|
||||
;
|
||||
; The table is in the atlas at 0xC000, and the screen save does not cover it: the pages it
|
||||
; walks run to the end of the map and pick up again at the palette, with the sprites in the
|
||||
; gap between. That is deliberate rather than an oversight. Nothing the shell draws is a
|
||||
; sprite, so there is nothing to GIVE BACK - what is needed is to take away, or a program
|
||||
; that put something on the screen and left would have left it sitting over the prompt,
|
||||
; still there, still in front of everything, and nothing able to type it away.
|
||||
;
|
||||
; A size of nought is no sprite, so filling the table with nought is all of it, and it is
|
||||
; one command rather than 256 of them.
|
||||
CALL screenBank
|
||||
INIA 0d4
|
||||
OUTA 0xE3
|
||||
INIA 0xC0
|
||||
OUTA 0xE4
|
||||
RSTA
|
||||
OUTA 0xE5
|
||||
OUTA 0xE2 ; Fill takes the byte it writes from SourceLow.
|
||||
INIA 0x08
|
||||
OUTA 0xE6
|
||||
RSTA
|
||||
OUTA 0xE7 ; 0x0800, which is 256 entries of eight bytes.
|
||||
INIA 0x02
|
||||
OUTA 0xE8
|
||||
RET
|
||||
|
||||
; Video memory as banks 4 and 5, which is what makes it reachable at all. Bank 3 is the
|
||||
|
||||
Reference in New Issue
Block a user