Monday 15 December 2014

Z80 Size Programming Challenge #2

Last week I issued the second Z80 programming challenge:

Something slightly more complex this time. Write the shortest code to mirror the entire Sinclair Spectrum screen (256×192 pixels) left to right including the colours / attributes. The deadline is Monday 15th, midday (GMT).

Target: under 50 bytes.

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

Final Results

We stepped up the difficultly for the second challenge so congratulations to everyone who entered. Introspec ZX and Tim Webber discovered the shortest solutions. Here are the final results:

CoderSize
Introspec Zx34
Tim Webber34
John Metcalf34
Paul Rhodes35
Simon Brattel35
Jim Bagley36
Steve Wetherill38
John Young49
Chris Walsh49
Dariusz EM50

Winning Entries

Introspec submitted the first 34 byte solution using a couple of neat tricks. Note the use of CP L to check which side of the screen it's working on and the byte saved by setting B to #58:

                ld hl,16384+6912

screenflip:     ld d,h
                ld a,l
                xor #1F
                ld e,a
                cp l
                jr nc,noflip

                ld a,(de)
                ld c,(hl)
                ld (hl),a
                ld a,c
                ld (de),a

noflip:         ld b,#58
                ld a,h
                cp b
                jr nc,skipattr

byteflip:       rlc (hl)
                rra
                djnz byteflip
                ld (hl),a

skipattr:       dec hl
                bit 6,h
                jr nz,screenflip
                ret

Tim Webber's solution saves a series of addresses on the stack to be used later:

start:          ld hl,23296
loop1:          dec hl
                bit 6, h
                ret z
                ld a, 87
                cp h
                jr c, noinv
                ld b,8
doinv:          rl (hl)
                rra
                djnz doinv
                ld (hl), a
noinv:          push hl
                bit 4,l
                jr nz, loop1
                pop de
                pop hl
                ld a,(de)
                ld c, (hl)
                ld (hl), a
                ex de, hl
                ld (hl), c
                jr loop1

Although I didn't enter I also found a couple of 34 byte solutions. The first mirrors two bytes in the inner loop:

                ld hl,16384
mirror:         ld d,h
                ld a,l
                xor 31
                ld e,a
                ld a,h
                cp 91
                ret z
                cp 88
                ld a,(de)
                ld c,a
                jr nc,attrib
                ld b,8
                rrca
mirrorbits:     rl (hl)
                rra
                djnz mirrorbits
                db 1 ; skip the next two instructions
attrib:         ld a,(hl)
                ld (hl),c
                ld (de),a
                inc l
                inc hl
                jr mirror

My second has two separate loops. The first loop mirrors bytes, the second mirrors the screen:

                ld hl,22527
mir:            ld a,128
mirrorbits:     rl (hl)
                rra
                jr nc,mirrorbits
                ld (hl),a
                dec hl
                bit 6,h
                jr nz,mir
mirror:         inc hl
                ld d,h
                ld a,l
                xor 31
                ld e,a
                ld a,h
                cp 91
                ret z
                ld a,(de)
                ld c,a
                ld a,(hl)
                ld (hl),c
                ld (de),a
                inc l
                jr mirror

Is 34 Bytes Optimal?

Definitely not! After the deadline a solution was discovered that combines code from Tim Webber and Introspec's entries to mirror the screen in 33 bytes:

start:          ld hl,23296 ; Tim Webber/Introspec
loop1:          dec hl
                bit 6, h
                ret z
                ld a, h
                ld b,88
                cp b
                jr nc, noinv
doinv:          rlc (hl)
                rra
                djnz doinv
                ld (hl), a
noinv:          push hl
                bit 4,l
                jr nz, loop1
                pop de
                pop hl
                ld a,(de)
                ld c, (hl)
                ld (hl), a
                ex de, hl
                ld (hl), c
                jr loop1

Another 33 byte solution combines the code from Tim Webber and Simon Brattel's entries:

start:          ld hl,23296 ; Tim Webber/Simon Brattel
loop1:          dec hl
                ld a,h
                cp 88
                jr nc, noinv
                and 64
                ret z
                add a,a
doinv:          rlc (hl)
                rra
                jr nc,doinv
                ld (hl), a
noinv:          push hl
                bit 4,l
                jr nz, loop1
                pop de
                pop hl
                ld a,(de)
                ld c, (hl)
                ld (hl), a
                ex de, hl
                ld (hl), c
                jr loop1

Entries will be available shortly on John Young's website. Thanks to everyone who entered for making the contest a success :-)

Monday 8 December 2014

Z80 Size Programming Challenge #1

A few days ago I issued a Z80 programming challenge for the ZX Spectrum:

Something simple for the first challenge. Write the shortest code to fill the screen with a chequerboard pattern of 1 pixel squares. No RAM/ROM other than the 6144 byte bitmap screen memory should be written to.

Target: under 25 bytes.

  1. Your program shouldn't rely on the initial contents of registers.
  2. Programs must return. The RET instruction is included in the size.
  3. So everyone has a fair chance comment with the code size not code.
  4. There are no prizes, just the chance to show off your coding skill.

Final Results

Congratulations to all who entered, especially Allan Høiberg and Introspec Zx who both discovered a 15-byte solution. The final results are as follows:

CoderSize
Allan Høiberg15
Introspec Zx15
Jim Bagley16
Paul Rhodes16
Krystian Włosek16
Tim Webber16
Steve Wetherill16
John Young16
Simon Brattel16
John Metcalf16
Dariusz EM17
Chris Walsh23

Winning Entries

Allan was the first to discover a 15-byte solution:

                LD BC,22272
                LD A,85
LoopB:          BIT 6,B
                RET Z
LoopC:          DEC C
                LD (BC),A
                JR NZ,LoopC
                CPL
                DJNZ loopB

Introspec found a 15-byte solution with only one loop:

                ld hl,16384+6143
filloop5:       ld a,h
                rra
                sbc a,a
                xor %01010101
                ld (hl),a
                dec hl
                bit 6,h
                jr nz,filloop5
                ret

My own attempts all fell short at 16 bytes:

                ld hl,22528-256
                ld bc,24*256+170
fill:           dec l
                ld (hl),c
                jr nz,fill
                rrc c
                dec h
                djnz fill
                ret

Entries are archived on John Young's website. Thanks to everyone who entered or otherwise supported the challenge. :-)