Monday 6 April 2015

Z80 Size Programming Challenge #4

The fourth Z80 challenge for the ZX Spectrum was issued last week:

Back to something simple for the next challenge, a diagonal fade-to-white CLS. Write the shortest code to wipe the screen by increasing the ink colour of each character until it reaches white.

The clear should start at the top left and move one character across the screen per frame. The initial screen can be assumed to be monochrome — black text, white background, flash off, bright off. There's no need to clear the screen bitmap. Here's a demonstration of the clear in slow motion:

Target: under 50 bytes.

The deadline is Monday 6th April, midday (GMT).

  1. Your program shouldn't rely on the initial contents of registers.
  2. Programs must halt between frames. The HALT is included in the size.
  3. No RAM/ROM other than the attribute memory should be written to.
  4. Programs must return. The RET instruction is included in the size.
  5. So everyone has a fair chance comment with the code size not code.
  6. There are no prizes, just the chance to show off your coding skills.

Final Results

Congratulations to everyone who entered and Arcadiy Gobuzov who claimed first place with a solution in 26 bytes. Most of the solutions use LDDR to move the attribute data with anonymous and Ralph Becket being the two exceptions. Here are the final results:

CoderSize
Arcadiy Gobuzov26
ub880d27
Bohumil Novacek27
anonymous27
Adrian Brown27
John Metcalf27
Ralph Becket30
Jim Bagley31
Paul Rhodes31

Winning Entry

Here's Arcadiy's winning entry in 26 bytes:

        xor a ; if comment then 25, but exit if a==56 on start
loop:        
        ld hl,#5ADF   ;
        cp (hl)       ;
        ld bc,#02E0   ; 23 lines of attributes
        ld de,#5AFF   ; 
        lddr          ; move down attributes
        ld c,e        ; e = #1F
        add hl,bc     ;
        lddr          ; roll upper line of attributes to right
        halt
        ret z
        ld a,(de)     ; de = first address of attibutes
        cp #3F        ;
        adc a,c       ; add 0 or 1 (carry)
        ld (de),a     ; now a in range [38..3f]
        jr loop

Here's my own solution in 27 bytes. Unfortunately I missed the final CP (HL) to squeeze out the last byte:

fadetowhite:
        ld de,23295 ; 90 255
        ld a,(de)
        cp 63
        ret z
        ld hl,23263 ; 90 223
        ld bc,736   ;  2 224
        halt
        lddr
        ld c,e
        add hl,bc
        lddr
        ld a,(de)
        cp 63
        adc a,c
        ld (de),a
        jr fadetowhite

Here's an alternative — a fade-to-black wipe (from white ink, black paper, no bright, no flash) in 25 bytes:

fadetoblack:
        ld de,23295 ; 90 255
        ld a,(de)
        or a
        ret z
        ld hl,23263 ; 90 223
        ld bc,736   ;  2 224
        halt
        lddr
        ld c,e
        add hl,bc
        lddr
        ld a,(de)
        add a,l
        sbc a,l
        ld (de),a
        jr fadetoblack