Prev: 9F99 Up: Map Next: A0CC
9FB4: Draw one character, to the screen or to the back buffer
Maps the ASCII character to a glyph index, then dispatches on the style in A' to one of six render modes: 1 = single height, straight to the screen with the ZX scanline row advance; 2 = single height to the back buffer, nine scanlines being a blank, seven glyph rows and a blank; 3 = double height to the back buffer, each glyph row drawn on two consecutive scanlines; 4 and 5 = the inverted forms of 2 and 3; 0 = double height drawn as separate four- and three-row passes with a column advance between them. The attribute byte goes to one attribute row for the single-height styles and to two for the double-height ones.
Input font definitions are only seven rows high so gaps are left when drawing.
Used by the routine at draw_string_with_style.
Input
A Character to draw (ASCII)
DE Screen address
A' Rendering type (double height, invert, etc.)
C' Attribute
DE' Stride
HL' Attribute address
Output
HL' Attribute address moved on past the character
DE Screen address moved to next column
draw_char 9FB4 SUB $20 If it's not a space character, goto dc_not_space with A reduced
9FB6 JR NZ,dc_not_space
It's a space
9FB8 INC E Move screen address to the next column
9FB9 EXX
9FBA INC L <move something else that's banked>
9FBB EXX
9FBC RET Return
Map ASCII to glyph IDs
dc_not_space 9FBD LD C,$12 Offset = 18
9FBF CP $21 Jump if 'A' or above
9FC1 JR NC,dc_have_range
9FC3 LD C,$0B Offset = 11
9FC5 CP $10 Jump if '0' or above
9FC7 JR NC,dc_have_range
9FC9 LD C,$00 Glyph ID = 0
9FCB DEC A Jump if '!'
9FCC JR Z,dc_have_single
9FCE INC C Glyph ID = 1
9FCF SUB $07 Jump if '('
9FD1 JR Z,dc_have_single
9FD3 INC C Glyph ID = 2
9FD4 DEC A Jump if ')'
9FD5 JR Z,dc_have_single
9FD7 INC C Glyph ID = 3
9FD8 SUB $03 Jump if ','
9FDA JR Z,dc_have_single
9FDC INC C Glyph ID = 4
9FDD JR dc_have_single Anything else is '.'
A is an ASCII character - 32
dc_have_range 9FDF SUB C Convert (ASCII - 32) to glyph ID. C = A - Offset
9FE0 LD C,A
C is a glyph ID
dc_have_single 9FE1 LD A,C Multiply the glyph ID by 7
9FE2 RLCA
9FE3 LD B,A
9FE4 RLCA
9FE5 ADD A,B
9FE6 ADD A,C
9FE7 LD B,$00
9FE9 RL B Add in the carry
9FEB LD C,A BC is now the byte offset
9FEC LD HL,$A27A Point HL at 8x7 font
9FEF ADD HL,BC Point to glyph data
9FF0 EX AF,AF' Get type in C (passed in A' on entry)
9FF1 LD C,A
9FF2 EX AF,AF'
9FF3 DEC C If 1 then jump dc_screen
9FF4 JP Z,dc_screen
9FF7 DEC C If 2 then jump dc_single_height
9FF8 JP Z,dc_single_height
9FFB DEC C
9FFC JR Z,dc_double_height If 3 then jump dc_double_height -- double height
9FFE DEC C
9FFF JR Z,dc_single_height_inverted If 4 then jump dc_single_height_inverted -- single height inverted
A001 DEC C
A002 JR Z,dc_double_height_inverted If 5 then jump dc_double_height_inverted -- double height + inverted
Otherwise it's type 6
A004 PUSH DE
A005 LD B,$04 B = 4
dc_loop1 A007 LD A,(HL) A = *HL
A008 LD (DE),A *DE = A
A009 INC D Move to next row
A00A LD (DE),A *DE = A
A00B INC D Move to next row
A00C INC HL Move to next glyph row
A00D DJNZ dc_loop1 While iterations remain, goto loop1
A00F LD A,D D -= 8
A010 SUB $08
A012 LD D,A
A013 LD A,E E += 32
A014 ADD A,$20
A016 LD E,A
A017 LD B,$03 B = 3
dc_loop2 A019 LD A,(HL) A = *HL
A01A LD (DE),A *DE = A
A01B INC D Move to next row
A01C LD (DE),A *DE = A
A01D INC D Move to next row
A01E INC HL Move to next glyph row
A01F DJNZ dc_loop2 While iterations remain, goto loop2
A021 JR dc_set_double_attrs
dc_double_height_inverted A023 PUSH DE
A024 LD B,$07 B = 7
dc_loop3 A026 LD A,(HL) A = ~*HL
A027 CPL
A028 LD (DE),A *DE = A
A029 INC D Move to next row
A02A LD (DE),A *DE = A
A02B INC D Move to next row
A02C INC HL Move to next glyph row
A02D DJNZ dc_loop3 While iterations remain, goto loop3
A02F JR dc_set_double_attrs
dc_single_height_inverted A031 PUSH DE
A032 LD B,$07 B = 7
dc_loop4 A034 LD A,(HL) *DE = ~*HL
A035 CPL
A036 LD (DE),A
A037 INC HL Move to next glyph row
A038 INC D Move to next row
A039 DJNZ dc_loop4 While iterations remain, goto loop4
A03B JR dc_set_single_attrs
Plots double-height glyphs. DE->screen HL->glyph def
dc_double_height A03D PUSH DE
A03E XOR A *DE = 0
A03F LD (DE),A
A040 INC D D++
A041 LD A,(HL) *DE = *HL
A042 LD (DE),A
A043 INC D D++ -- next row
A044 LDI
A046 DEC E E--
A047 INC D D++
A048 LD A,(HL) Repeat six more times
A049 LD (DE),A
A04A INC D
A04B LDI
A04D DEC E
A04E INC D
A04F LD A,(HL)
A050 LD (DE),A
A051 INC D
A052 LDI
A054 DEC E
A055 INC D
A056 LD A,(HL)
A057 LD (DE),A
A058 INC D
A059 LDI
A05B DEC E
A05C INC D
A05D LD A,(HL)
A05E LD (DE),A
A05F INC D
A060 LDI
A062 DEC E
A063 INC D
A064 LD A,(HL)
A065 LD (DE),A
A066 INC D
A067 LDI
A069 DEC E
A06A INC D
A06B LD A,(HL)
A06C LD (DE),A
A06D INC D
A06E LDI
A070 DEC E
A071 INC D
A072 XOR A A = 0
A073 LD (DE),A *DE = A
dc_set_double_attrs A074 POP DE
A075 INC E E++
A076 EXX
A077 PUSH HL
A078 LD A,(HL) *HL |= C
A079 OR C
A07A LD (HL),A
A07B ADD HL,DE HL += DE
A07C LD A,(HL) *HL |= C
A07D OR C
A07E LD (HL),A
A07F POP HL
A080 INC L L++
A081 EXX
A082 RET Return
dc_single_height A083 PUSH DE
A084 XOR A A = 0
A085 LD (DE),A *DE = A
A086 INC D D++
A087 LDI
A089 DEC E E--
A08A INC D D++
A08B LDI
A08D DEC E E--
A08E INC D D++
A08F LDI
A091 DEC E E--
A092 INC D D++
A093 LDI
A095 DEC E E--
A096 INC D D++
A097 LDI
A099 DEC E E--
A09A INC D D++
A09B LDI
A09D DEC E E--
A09E INC D D++
A09F LDI
A0A1 DEC E E--
A0A2 INC D D++
A0A3 LD (DE),A *DE = A
dc_set_single_attrs A0A4 POP DE
A0A5 INC E E++
A0A6 EXX
A0A7 LD A,(HL) *HL |= C
A0A8 OR C
A0A9 LD (HL),A
A0AA INC L L++
A0AB EXX
A0AC RET Return
dc_screen A0AD PUSH DE Save screen pointer
A0AE LD B,$07 7 iterations/rows
dc_screen_loop A0B0 LD A,(HL) Transfer a byte
A0B1 LD (DE),A
A0B2 INC D Move to next scanline (Y0++)
A0B3 INC HL Move to next row of glyph data
A0B4 LD A,D Did we rollover?
A0B5 AND $07
A0B7 JR NZ,draw_char_0 If no rollover goto loop
A0B9 LD A,D Undo rollover
A0BA SUB $08
A0BC LD D,A
A0BD LD A,E Y3++
A0BE ADD A,$20
A0C0 LD E,A
A0C1 JR NC,draw_char_0 If no rollover goto loop
A0C3 LD A,D There was rollover, so move it to Y6
A0C4 ADD A,$08
A0C6 LD D,A
draw_char_0 A0C7 DJNZ dc_screen_loop Loop until we've done 7 lines
A0C9 POP DE Restore screen pointer
A0CA INC E Move to next column
A0CB RET Return
Prev: 9F99 Up: Map Next: A0CC