There follows a disassembly of my rewrite of the Impossible Triangle-drawing code, as mentioned in my previous post. The rewritten part of the routine now saves eight bytes, compared with the original.
N.B. I believe that this is exactly the sort of thing that the CPIR command should be used for (unlike Matthew's dodgy application of CPIR in the room-drawing code, which gives rise to the Cell Graphics Bug).
Title_screen_data EQU #885D ; A new data table, which contains all the attribute values which were individually checked
; via CP #nn commands in the original code (and the former operand of a LD A, #nn command)
Triangle_graphic_data EQU #8431 ; The original table containing the pixel-graphics used to create the impossible triangle.
; There are two halves to this table (at #8431 and #8441), and each half contains a pair
; of two eight-byte graphics (e.g. graphics start at #8431 and #8439 for the first half of the table)
LD DE, #5800
LD A, (DE)
LD HL, Title_screen_data ; HL now points at the start of the data table, in preparation for the CPIR loops (and other commands) that follow
LD BC, #0005 ; BC counts down the CPIR loop, but B is also used to indicate which half of the graphic data at #8431 is picked up
CPIR ; Search through the first five entries in the data table
JR Z, Nothing_to_draw ; If there is a match, then this particular screen cell contains no pixel-graphics
LD C, #03 ; B still holds 00 at this point (and HL is pointing at the next part of the data table)
CPIR ; Search through the next three entries in the data table
JR Z, Draw_triangle_segment ; If there is a match, then draw a part of the triangle using the first half of the graphic data at #8431
CP (HL) ; Check A against the penultimate value in the data table...
INC HL ; ...and move HL on to the final entry in the table (I tried a CPI command here, but that doesn't preserve B = #00)
JR Z, switch_INK_and_PAPER ; If there is a match with the penultimate entry, then we are at the 'tricky corner' of the triangle
LD B, #10 ; No match in the data table, so we need to select a graphic from the second half of the pixel data
JR Draw_triangle_segment ' (i.e. the parts of the triangle which slope 'up-to-the-right')
Title_screen_data: ; This table could be moved elsewhere in the code, but every path through this routine jumps past it,
; so it can safely be left here
DEFB #00 #09 #24 #2D #D3 ; These entries correspond to parts of the screen with no pixel-graphics (i.e. the black background, flashing lettering,
; or solid parts of the triangle which have matching INK and PAPER colours)
DEFB #05 #08 #29 ; All remaining entries in the table correspond to parts of the triangle which slope 'down-to-the-right'
DEFB #2C #25 ; If the attribute in the cell under consideration is #2C (green INK/cyan PAPER), then replace it with #25 (cyan INK/green PAPER)
; N.B. I could have save an extra byte by retaining the original commands for the last two entries [CP #2C and LD A, #25 / LD (DE), A],
; and omitting the last two entries in the table, but I considered it more elegant to have all the data stored within a single data table
DEFS #08 ; Eight unused bytes (NOPs) - the point of the exercise! (These can obviously be consolidated elsewhere)
LD A, (HL) ; Pick up the final entry in the data table and update the attribute in this cell (this swaps the INK/PAPER colours around...
LD (DE), A ; ... which allows the green/cyan corner of the triangle to be drawn using all four of the graphics at #8431)
; N.B. From hereon in, there are further byte-efficiencies to be achieved, which are documented earlier in this thread,
; but which I haven't (yet) incorporated below
LD A, E
AND #01 ; Whether E has an even or odd value determines which half of the selected pair of graphics from #8431 is used
OR B ; Determines which pair of graphics from #8431 is used (N.B. this has been changed from the OR C in the original code)
LD C, A
LD B, #00
LD HL, Triangle_graphic_data
ADD HL, BC
BIT 0, D
LD D, #40
JR Z, correct_part_of_screen_identified
LD D, #48
LD B, #08
LD A, D
JP NZ, Impossible_triangle_loop
EDIT: I should also mention that the above rewrite still works if the erroneous attribute in the original title screen is corrected (i.e. the green/black cell inside the lower part of the letter 'S', which should properly be green and blue).
This can be fixed by editing the data at source, within page #98 (i.e. POKE #98D2, #0C) - no change to the new table at #885D is required, because the corresponding triangle segment slopes down-to-the-left, and so it doesn't need a specific entry in the table (the correct graphic is selected 'by default').
Edited by IRF, 24 February 2019 - 11:08 AM.