ZalaXa 8 — Clearing the NIRVANA+ Screen

If you take a screenshot of the part 7 code and look at it in a screen editor such as ZX-Paintbrush, you’ll see we’re setting attributes to black-on-black1 but not clearing pixels. This is going to cause us problems later when we start writing to the screen, so let’s address that now.

We’ll still clear the 8×8 attributes, because that happens very fast and gives a nice snappy transition. But let’s add a ClsNirvana routine that we call afterwards:

15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
; utilities.asm
 
ClsNirvana              proc
                        di                              ; 1) Clear all pixels
                        ld (RestoreStack), sp           ; SMC> Save the stack
                        ld sp, AttributeAddress         ; Set stack to end of screen
                        ld de, $0000                    ; All pixels unset
                        ld b, 0                         ; Loop 256 times: 12 words * 256 = 6144 bytes
LoopPixels:
                        loop 12
                          push de
                        lend
                        djnz LoopPixels
RestoreStack equ $+1:   ld sp, SMC                      ; <SMC Restore the stack
 
                        ld hl, ClsNirvanaGame           ; 2) Clear 8x2 attributes
                        ld ix, race_raster
                        ld de, NAttrVOffset
                        xor a
                        ld (Col+1), a
LoopAttr:               ld b, (hl)
                        xor a
                        cp b
                        jp z, TopRow
                        inc hl
                        ld c, (hl)
                        inc hl
Times:                  ld a, (Col+1)
                        cp 32
                        jp nz, Skip
                        xor a
                        add ix, de
Skip:                   inc a
                        ld (Col+1), a
Col:                    ld a, (deltas-1)                ; NIRVANA_org+8957 (65280, $FF00)
                        ld (Delta+2), a
Delta:                  ld (ix+0), c
                        djnz Times
                        jp LoopAttr
TopRow:
                        ClsAttrLine(0, BrightRedBlackP) ; 3) Clear top row of 8x8 attributes
                        ret
pend

This is split into three sections[I believe Einar Saukas, the author of NIRVANA+, gave me the original version of this routine, although I’ve hacked it about several times since. Thanks, Einar![/note]:

  1. Pixel clear: This uses a faster, stack-based way of block copying bytes than we used in the ldir-based ClsAttr routine (part 3).
  2. Multicolour attribute clear: This is the fiddly one. there are 2944 ($B80) multicolour attributes, and they aren’t laid out contiguously in memory. In fact the attributes for column 7 aren’t even near the attributes for column 8, for example. Every line of attributes is laid out 82 bytes after the previous line, moving down the screen. To find anything else, we need to use the deltas lookup table that NIRVANA+ handily provides. The upshot is that we need a slightly more complicated routine to set these attributes. This section uses a colour table for more flexibility. I’ll talk about this in more detail in a minute.
  3. Top row attribute clear: In NIRVANA+, the top row of attributes are always rendered with standard 8×8 attributes. The third section does this. Here, I’m setting them to red, because the arcade Galaga displays red status text on the top row. You can configure NIRVANA+ to render some of the lower rows with 8×8 attributes too. The main advantage of doing this is to to reclaim some of the processor time used for drawing the attributes for your user code, if your program design can get away with not having multicolour over the full screen. For this reason, I’m being slightly flexible and writing this section with a macro, which allows me to specify the row I want to clear2:
21
22
23
24
25
26
27
28
29
30
31
32
33
34
; macros.asm
 
ClsAttrLine             macro(Line, Colour)
                        if Colour = DimBlackBlackP
                         xor a
                        else
                          ld a, Colour
                        endif
                        ld hl, AttributeAddress+(Line*32)
                        ld (hl), a
                        ld de, AttributeAddress+(Line*32)+1
                        ld bc, 32
                        ldir
mend

I usually set any pixels and 8×8 attributes at the end of setup routines, as they can sometimes display earlier than the multicolour parts, particularly if you have NIRVANA+ turned off while you do the setup. I don’t think it matters much here, but it’s helpful to keep this as the last section of ClsNirvana.

The colour table used by the second section looks like this. It consists of pairs of bytes, with a zero byte terminator. The first byte of each pair is a count, and the second byte is a colour. The counts should add up to 2944. By all means make them add up to less, but if they add up to more, code will get overwritten and weird things will happen. Be warned!

Here, I’m setting the second character row to white on black (32 columns x 4 attribute lines = 128), as we’ll display scores here. The rest of the screen will get cleared to yellow on black. Our bullets will probably be yellow, and this might make the drawing code slightly easier if the screen is already the right colour.

35
36
37
38
39
40
41
42
43
44
; database.asm
 
ClsNirvanaGame          proc
                        db 128, BrightWhiteBlackP
                        loop 11
                          db 255, BrightYellowBlackP
                        lend
                        db 11, BrightYellowBlackP
                        db 0
pend

The sprites (only the ship, so far) have their own background and foreground colours, and will always overlay attribute values written this way, so we don’t need to worry about them here.

I defined a whole bunch of colour constants uing equ. This lets us refer to named foreground and background colours when we hardcode them. Check them out on line 81 of constants.asm, if you’re interested.

If you assemble and run the part 8 code, you will see… exactly the same results as part 7! But we have set ourselves up nicely for the next part, so it’s all good 🙂

If you want to see at least some visible change, play around with the ClsNirvanaGame colour table. It can be as long or complicated as you like! See if you can make a blocky pattern out of individual attributes. I used this technique to animate clouds on the Jet Power Jack main menu—notice how both the blue and white clouds go behind most of the graphics, but go in front of a few parts – the letters p, e and k in the title, for example:

Yes, this really is the 406th version of Jet Power Jack, and counting3. One day it will get finished and released…

That’s all for today! Let’s get fancy with proportional fonts next time 🙂

  1. Actually, we’re setting 8×8 attributes to black-on-black, but not the 8×2 multicolour attributes. The latter just happen to be black anyway when the program is first loaded, but they probably won’t be always be—for example, if we write code later to restart the game.
  2. xor a is a slightly faster way of writing ld a, 0.
  3. Specifically, my 406th git commit.

Leave a Reply

Your email address will not be published. Required fields are marked *