|
| 1 | +#Print64.bas |
| 2 | + |
| 3 | +The 64 column printing routine allows text to be 4 pixels wide instead of 8. |
| 4 | +It is NOT proportional printing, but this is still useful for lining things up in columns. |
| 5 | + |
| 6 | +This routine has been adopted as an included library - so you may include it with |
| 7 | + |
| 8 | +``` |
| 9 | +#include <print64.bas> |
| 10 | +``` |
| 11 | + |
| 12 | +##Usage |
| 13 | + |
| 14 | +``` |
| 15 | +printat64(y,x) |
| 16 | +``` |
| 17 | + |
| 18 | +Moves the print64 system's print cursor to row Y, column X. Note that `0 <= x <= 63` - that is the range of values |
| 19 | +for X can be up to 63. The range of values for Y is the normal 0-23. |
| 20 | + |
| 21 | +* Note that the print64 system's cursor position is independent from that of the ZX Basic Print routine, |
| 22 | +or any other, such as the print42 system. |
| 23 | + |
| 24 | +``` |
| 25 | +printat64(STRING) |
| 26 | +``` |
| 27 | + |
| 28 | + |
| 29 | +Prints the string to the screen at the current Print64 co-ordinates. It does so in the current permanent colours. |
| 30 | + |
| 31 | +NOTE: The ZX Spectrum's attribute system is encoded into the hardware as a 32 character grid. Print64 does its best, |
| 32 | +but changing the paper/bright/flash colour from the background is likely to look imperfect as the attribute |
| 33 | +blocks cannot line up well with the pixel blocks. |
| 34 | + |
| 35 | +##CODE |
| 36 | +* There is a version of this code included with the compiler |
| 37 | +(though the version listed here may or may not be more recent). Code converted to ZXBasic by Britlion, |
| 38 | +based on Andrew Owen's 64 Character code http://www.worldofspectrum.org/forums/showpost.php?p=167447&postcount=1 |
| 39 | + |
| 40 | + |
| 41 | +``` |
| 42 | +SUB printat64 (y as uByte, x as uByte) |
| 43 | + IF y<24 AND x<64 then |
| 44 | + POKE @p64coords,x |
| 45 | + POKE @p64coords+1,y |
| 46 | + ELSE |
| 47 | + asm |
| 48 | + rst 8 ; error "5 Out of screen" |
| 49 | + defb 4 |
| 50 | + end asm |
| 51 | + END IF |
| 52 | +END SUB |
| 53 | +
|
| 54 | +
|
| 55 | +SUB print64 (characters$ as String) |
| 56 | +ASM |
| 57 | +
|
| 58 | +; This frankencode created by Paul Fisher, Andrew Owen, Chris Born and Einar Saukas |
| 59 | +; TODO: |
| 60 | +; * Inverse |
| 61 | +; * Bold (which will use a Second font) |
| 62 | +
|
| 63 | +LD L,(IX+4) |
| 64 | +LD H,(IX+5) ; Get String address of characters$ into HL. |
| 65 | +
|
| 66 | +; Load BC with length of string, and move HL to point to first character. |
| 67 | + ld c, (hl) ; 60020 78 |
| 68 | + inc hl ; 60021 35 |
| 69 | + ld b, (hl) ; 60022 70 |
| 70 | + inc hl ; 60023 35 |
| 71 | +
|
| 72 | +; Test string length. If Zero, exit. |
| 73 | + ld a, c ; 60024 121 |
| 74 | + or b ; 60025 176 |
| 75 | + jp z, p64_END ; 60026 200 |
| 76 | +
|
| 77 | +examineChar: |
| 78 | + ld a, (hl) ; Grab the character |
| 79 | + cp 128 ; too high to print? |
| 80 | + jr nc, nextChar ; then we go to next. |
| 81 | +
|
| 82 | +newLine: |
| 83 | + cp 13 ; Is this a newline character? 60056 254 13 |
| 84 | + jr nz, p64_isPrintable ; If not, hop to testing to see if we can print this 60058 32 13 |
| 85 | + push hl |
| 86 | + push bc |
| 87 | + ld b,0 |
| 88 | + ld hl, p64_coords ; Get coords 60060 237 91 68 235 |
| 89 | + call BLp64_NEXT_ROW ; Go to next line. ; 60064 205 58 235 |
| 90 | + pop bc |
| 91 | + pop hl |
| 92 | +
|
| 93 | + ld (p64_coords), de ; 60067 237 83 68 235 |
| 94 | + jr nextChar ; 60071 24 11 |
| 95 | +
|
| 96 | +p64_isPrintable: |
| 97 | + cp 31 ; Bigger than 31? 60073 254 31 |
| 98 | + jr c, nextChar ; If not, get the next one. 60075 56 7 |
| 99 | + |
| 100 | + push hl ; Save position 60077 229 |
| 101 | + push bc ; Save Count 60078 197 |
| 102 | + call p64_PrintChar ; Call Print SubRoutine |
| 103 | + |
| 104 | + |
| 105 | + |
| 106 | + pop bc ; Recover length count 60082 193 |
| 107 | + pop hl ; Recover Position 60083 225 |
| 108 | +
|
| 109 | +nextChar: |
| 110 | + inc hl ; Point to next character 60084 35 |
| 111 | + dec bc ; Count off this character 60085 11 |
| 112 | + ld a, b ; Did we run out? 60086 120 |
| 113 | + or c ; 60087 177 |
| 114 | + jr nz, examineChar ; If not, examine the next one 60088 32 193 |
| 115 | + jp p64_END ; Otherwise hop to END. 60090 201 |
| 116 | +
|
| 117 | +p64_PrintChar: |
| 118 | +; Arrives with A as a byte to print. |
| 119 | + ld hl,p64_coords |
| 120 | + push hl ; save COL address for later |
| 121 | + ld e, a ; store character value in E |
| 122 | + ld b,0 |
| 123 | + ld c, (hl) ; store current column in BC |
| 124 | +
|
| 125 | + ; Check if character font must be rotated, self-modifying the code accordingly |
| 126 | +
|
| 127 | + xor c ; compare BIT 0 from character value and column |
| 128 | + rra |
| 129 | + ld a, 256-(BLp64_END_LOOP-BLp64_SKIP_RLC) ; instruction DJNZ skipping rotation |
| 130 | + jr nc, BLp64_NOT_RLC ; decide based on BIT 0 comparison |
| 131 | + ld a, 256-(BLp64_END_LOOP-BLp64_INIT_RLC) ; instruction DJNZ using rotation |
| 132 | +
|
| 133 | +BLp64_NOT_RLC: |
| 134 | + ld (BLp64_END_LOOP - 1), a ; modify DJNZ instruction directly |
| 135 | +
|
| 136 | +; Check the half screen byte to be changed, self-modifying the code accordingly |
| 137 | + srl c ; check BIT 0 from current column |
| 138 | + ld a, %00001111 ; mask to change left half of the screen byte |
| 139 | + jr nc, BLp64_SCR_LEFT ; decide based on odd or even column |
| 140 | + cpl ; mask to change right half of the screen byte |
| 141 | +
|
| 142 | +BLp64_SCR_LEFT: |
| 143 | + ld (BLp64_SCR_MASK + 1), a ; modify screen mask value directly |
| 144 | + cpl |
| 145 | + ld (BLp64_FONT_MASK + 1), a ; modify font mask value directly |
| 146 | +
|
| 147 | +; Calculate location of the first byte to be changed on screen |
| 148 | +; The row value is a 5 bits value (0-23), here represented as %000RRrrr |
| 149 | +; The column value is a 6 bits value (0-63), here represented as %00CCCCCc |
| 150 | +; Formula: 0x4000 + ((row & 0x18) << 8) + ((row & 0x07) << 5) + (col >> 1) |
| 151 | +
|
| 152 | + inc hl ; now HL references ROW address |
| 153 | + ld a, (hl) ; now A = %000RRrrr |
| 154 | + call 0e9eh ; now HL = %010RR000rrr00000 |
| 155 | + add hl, bc ; now HL = %010RR000rrrCCCCC |
| 156 | + ex de, hl ; now DE = %010RR000rrrCCCCC |
| 157 | + ; and e=char -> l=char |
| 158 | +
|
| 159 | +; Calculate location of the character font data in p64_charset |
| 160 | +; Formula: p64_charset + 7 * INT ((char-32)/2) - 1 |
| 161 | +
|
| 162 | + ld h, b ; now HL = char (because b=0) |
| 163 | + srl l ; now HL = INT (char/2) |
| 164 | + ld c, l ; now BC = INT (char/2) |
| 165 | + add hl, hl ; now HL = 2 * INT (char/2) |
| 166 | + add hl, hl ; now HL = 4 * INT (char/2) |
| 167 | + add hl, hl ; now HL = 8 * INT (char/2) |
| 168 | + sbc hl, bc ; now HL = 7 * INT (char/2) |
| 169 | + ld bc, p64_charset - 71h |
| 170 | + add hl, bc ; now HL = p64_charset + 7 * INT (char/2) - 0x71 |
| 171 | +
|
| 172 | +
|
| 173 | +; Main loop to copy 8 font bytes into screen (1 blank + 7 from font data) |
| 174 | + xor a ; first font byte is always blank |
| 175 | + ld b, 8 ; execute loop 8 times |
| 176 | +
|
| 177 | +BLp64_INIT_RLC: |
| 178 | + rlca ; switch position between bits 0-3 and bits 4-7 |
| 179 | + rlca |
| 180 | + rlca |
| 181 | + rlca |
| 182 | +
|
| 183 | +BLp64_SKIP_RLC: |
| 184 | +
|
| 185 | +; ----------------------------------------------------------------------------- |
| 186 | +; STANDARD OR INVERSE |
| 187 | +; |
| 188 | +BLp64_INV_C: nop ; either 'NOP' or 'CPL' (modified) |
| 189 | +; ----------------------------------------------------------------------------- |
| 190 | +
|
| 191 | +BLp64_FONT_MASK: |
| 192 | + and %11110000 ; mask half of the font byte |
| 193 | + ld c, a ; store half of the font byte in C |
| 194 | + ld a, (de) ; get screen byte |
| 195 | +
|
| 196 | +BLp64_SCR_MASK: |
| 197 | + and %00001111 ; mask half of the screen byte |
| 198 | + or c ; combine half screen and half font |
| 199 | + ld (de), a ; write result back to screen |
| 200 | + inc d ; next screen location |
| 201 | + inc hl ; next font data location |
| 202 | + ld a, (hl) ; store next font byte in A |
| 203 | + djnz BLp64_INIT_RLC ; repeat loop 8 times (this instruction gets modified) |
| 204 | +
|
| 205 | +BLp64_END_LOOP: |
| 206 | + ; attributes |
| 207 | + ld de,(p64_coords) ; grab coords |
| 208 | + and a ; clear carry |
| 209 | + rr e ; divide x by 2 to get bytes instead of nybbles |
| 210 | + ld a, d ; Get Y coord |
| 211 | + sra a ; |
| 212 | + sra a ; |
| 213 | + sra a ; Multiply by 8 60155 203 47 |
| 214 | + add a, 88 ; Add to attrbute base address |
| 215 | + ld h, a ; Put high byte value for attribute into H. |
| 216 | + ld a, d ; get y value again |
| 217 | + and 7 ; set within third |
| 218 | + rrca ; |
| 219 | + rrca ; |
| 220 | + rrca ; |
| 221 | + add a, e ; add in x value |
| 222 | + ld l, a ; Put low byte for attribute into l |
| 223 | + ld a, (23693) ; Get permanent Colours from System Variable |
| 224 | + ld (hl), a ; Write new attribute |
| 225 | + |
| 226 | + pop hl ; restore AT_COL address |
| 227 | + inc (hl) ; next column |
| 228 | + bit 6, (hl) ; column lower than 64? |
| 229 | + ret z ; return if so |
| 230 | +
|
| 231 | +BLp64_NEXT_ROW: |
| 232 | + ld (hl), b ; reset AT_COL |
| 233 | + inc hl ; store AT_ROW address in HL |
| 234 | + inc (hl) ; next row |
| 235 | + ld a, (hl) |
| 236 | + cp 24 ; row lower than 23? |
| 237 | + ret c ; return if so |
| 238 | + ld (hl), b ; reset AT_ROW |
| 239 | + ret ; done! |
| 240 | + |
| 241 | +
|
| 242 | +end asm |
| 243 | +p64coords: |
| 244 | +asm |
| 245 | +p64_coords: |
| 246 | + defb 0; X Coordinate store |
| 247 | + defb 0; Y Coordinate Store |
| 248 | +
|
| 249 | +p64_charset: ; 60230 |
| 250 | + DEFB 2,2,2,2,0,2,0 ; Space ! |
| 251 | + DEFB 80,82,7,2,7,2,0 ; " # |
| 252 | + DEFB 37,113,66,114,20,117,32 ; $ % |
| 253 | + DEFB 34,84,32,96,80,96,0 ; & ' |
| 254 | + DEFB 36,66,66,66,66,36,0 ; ( ) |
| 255 | + DEFB 0,82,34,119,34,82,0 ; * + |
| 256 | + DEFB 0,0,0,7,32,32,64 ; , - |
| 257 | + DEFB 1,1,2,2,100,100,0 ; . / |
| 258 | + DEFB 34,86,82,82,82,39,0 ; 0 1 |
| 259 | + DEFB 34,85,18,33,69,114,0 ; 2 3 |
| 260 | + DEFB 87,84,118,17,21,18,0 ; 4 5 |
| 261 | + DEFB 55,65,97,82,84,36,0 ; 6 7 |
| 262 | + DEFB 34,85,37,83,85,34,0 ; 8 9 |
| 263 | + DEFB 0,2,32,0,34,2,4 ; : ; |
| 264 | + DEFB 0,16,39,64,39,16,0 ; < = |
| 265 | + DEFB 2,69,33,18,32,66,0 ; > ? |
| 266 | + DEFB 98,149,183,181,133,101,0 ; @ A |
| 267 | + DEFB 98,85,100,84,85,98,0 ; B C |
| 268 | + DEFB 103,84,86,84,84,103,0 ; D E |
| 269 | + DEFB 114,69,116,71,69,66,0 ; F G |
| 270 | + DEFB 87,82,114,82,82,87,0 ; H I |
| 271 | + DEFB 53,21,22,21,85,37,0 ; J K |
| 272 | + DEFB 69,71,71,69,69,117,0 ; L M |
| 273 | + DEFB 82,85,117,117,85,82,0 ; N O |
| 274 | + DEFB 98,85,85,103,71,67,0 ; P Q |
| 275 | + DEFB 98,85,82,97,85,82,0 ; R S |
| 276 | + DEFB 117,37,37,37,37,34,0 ; T U |
| 277 | + DEFB 85,85,85,87,39,37,0 ; V W |
| 278 | + DEFB 85,85,37,82,82,82,0 ; X Y |
| 279 | + DEFB 119,20,36,36,68,119,0 ; Z [ |
| 280 | + DEFB 71,65,33,33,17,23,0 ; \ ] |
| 281 | + DEFB 32,112,32,32,32,47,0 ; ^ _ |
| 282 | + DEFB 32,86,65,99,69,115,0 ; £ a |
| 283 | + DEFB 64,66,101,84,85,98,0 ; b c |
| 284 | + DEFB 16,18,53,86,84,35,0 ; d e |
| 285 | + DEFB 32,82,69,101,67,69,2 ; f g |
| 286 | + DEFB 66,64,102,82,82,87,0 ; h i |
| 287 | + DEFB 20,4,53,22,21,85,32 ; j k |
| 288 | + DEFB 64,69,71,71,85,37,0 ; l m |
| 289 | + DEFB 0,98,85,85,85,82,0 ; n o |
| 290 | + DEFB 0,99,85,85,99,65,65 ; p q |
| 291 | + DEFB 0,99,84,66,65,70,0 ; r s |
| 292 | + DEFB 64,117,69,69,85,34,0 ; t u |
| 293 | + DEFB 0,85,85,87,39,37,0 ; v w |
| 294 | + DEFB 0,85,85,35,81,85,2 ; x y |
| 295 | + DEFB 0,113,18,38,66,113,0 ; z { |
| 296 | + DEFB 32,36,34,35,34,36,0 ; | { |
| 297 | + DEFB 6,169,86,12,6,9,6 ; ~ (c) |
| 298 | +
|
| 299 | +p64_END: |
| 300 | +End Asm |
| 301 | +End Sub |
| 302 | +``` |
| 303 | + |
| 304 | +There's an example of usage here: |
| 305 | + |
| 306 | +``` |
| 307 | +REM Example |
| 308 | +
|
| 309 | +DIM n,x,y as uInteger |
| 310 | +CLS |
| 311 | +
|
| 312 | +FOR n=1 to 1000 |
| 313 | + y=rnd*23 |
| 314 | + x=rnd*62 |
| 315 | + |
| 316 | + ink rnd*8 |
| 317 | +
|
| 318 | + printat64(y, x) |
| 319 | + print64 ("ABCDEFGHIJKLMNOPQRSTUVWXYZ"(n MOD 26 TO n MOD 26)) |
| 320 | +NEXT n |
| 321 | +END |
| 322 | +``` |
0 commit comments