I've worked out what's going wrong with my fix to Bubu's CPIR routine. Every time I have to DEC HL so that the new attributes are dropped in the right place, it reduces the number of squares that the BC loop will check by one. A
slow (for machine code!) solution is to put the loop right back to the initial line so that it starts again at the first square and CPIRs the entire attribute area until it finds nothing:
Code: Select all
loop: ld hl, 22528
ld bc, 32*24
ld de, 256*checkedValue + newValue ; I used 199 here so that flash/bright/paper/ink 0 is replaced with fl1/br1/paper0/ink7
ld a, d
cpir
[b]dec hl[/b] ; this had to be inserted to get the attribute in the right place
ld (hl), e
ld a, b
or c
[b]jr nz, loop[/b] ; no idea why Bubu used JP here...!
On closer inspection I found Bubu's idea was to start the CPIR process again from the point where it found the last attribute to compare with, so where HL had to be dropped by one to compensate for CPIR landing one byte further on from where it should be, so BC also needs to be corrected, nudged back up by one. After some hair-pulling, I worked out that the INC BC has to come
before the CPIR, so that when the CPIR process is finished, BC=0 if there are no attributes left to check - I was putting it after the DEC HL, in which case BC always equals at least 1 and it gets stuck in a loop.
I wrote a (not entirely small!) routine to fill the entire screen (INPUT area as well) with * characters, no flash or bright, black ink, and a random paper colour. To make sure the adjustments worked perfectly, I made sure (23,31) - the last byte of the attributes - was black on black so that the CPIR instruction would pick up on it (at least, given the value I'd put in DE). So now,
this version of Bubu's code will do the job, put the new attributes where they need to be, and scan and correct the entire attribute area without touching the next byte:
Code: Select all
ld hl, 22528
ld bc, 32*24
ld de, 256*checkedValue + newValue
loop:
ld a, d
[b]inc bc[/b]
cpir
[b]dec hl[/b]
ld (hl), e
ld a, b
or c
[b]jr nz, loop[/b]
And to vary it from BASIC:
POKE startaddress+7,CheckedValue
POKE startaddress+8,NewValue
Now the Triumphant Baby can have his day!