;
; Graphics driver for the 160x102x16 mode on the Lynx.
;
-; Based on Stephen L. Judds GRLIB code
+; All the drawing functions are simply done by sprites as the sprite
+; engine is the only way to do fast graphics on a Lynx.
+;
+; So the code is not really based on any algorithms done by somebody.
+; I have looked at other routines in the cc65 libs to see what kind of
+; entry points we need. And I have looked at the old cc65 libs by
+; Bastian Schick to see how things worked in the past.
+;
+; This code is written by Karri Kaksonen, 2004 for the cc65 compiler.
;
.include "zeropage.inc"
.include "tgi-error.inc"
.include "lynx.inc"
+ .include "extzp.inc"
.macpack generic
.word 160 ; X resolution
.word 102 ; Y resolution
.byte 16 ; Number of drawing colors
- .byte 1 ; Number of screens available
+ .byte 2 ; Number of screens available
.byte 8 ; System font X size
.byte 8 ; System font Y size
.res 4, $00 ; Reserved for future extensions
Y1 := ptr2
X2 := ptr3
Y2 := ptr4
-RADIUS := tmp1
-
-ROW := tmp2 ; Bitmap row...
-COL := tmp3 ; ...and column, both set by PLOT
-TEMP := tmp4
-TEMP2 := sreg
-POINT := regsave
-INRANGE := regsave+2 ; PLOT variable, $00 = coordinates in range
-CHUNK := X2 ; Used in the line routine
-OLDCHUNK := X2+1 ; Dito
+STRPTR := ptr3
+FONTOFF := ptr4
+STROFF := tmp3
+STRLEN := tmp4
; Absolute variables used in the code
DRAWINDEX: .res 1 ; Pen to use for drawing
VIEWPAGEL: .res 1
VIEWPAGEH: .res 1
-
-; INIT/DONE
-OLDD018: .res 1 ; Old register value
-
-; Line routine stuff
-DX: .res 2
-DY: .res 2
-
-; Circle routine stuff, overlaid by BAR variables
-X1SAVE:
-CURX: .res 1
-CURY: .res 1
-Y1SAVE:
-BROW: .res 1 ; Bottom row
-TROW: .res 1 ; Top row
-X2SAVE:
-LCOL: .res 1 ; Left column
-RCOL: .res 1 ; Right column
-Y2SAVE:
-CHUNK1: .res 1
-OLDCH1: .res 1
-CHUNK2: .res 1
-OLDCH2: .res 1
+DRAWPAGEL: .res 1
+DRAWPAGEH: .res 1
; Text output stuff
TEXTMAGX: .res 1
TEXTMAGY: .res 1
TEXTDIR: .res 1
+BGINDEX: .res 1 ; Pen to use for text background
+
+text_bitmap: .res 8*(1+20+1)+1
+; 8 rows with (one offset-byte plus 20 character bytes plus one fill-byte) plus one 0-offset-byte
; Constants and tables
PALETTESIZE = * - DEFPALETTE
-BITTAB: .byte $80,$40,$20,$10,$08,$04,$02,$01
-BITCHUNK: .byte $FF,$7F,$3F,$1F,$0F,$07,$03,$01
-
-VBASE = $E000 ; Video memory base address
-CBASE = $D000 ; Color memory base address
-
-
.code
; ------------------------------------------------------------------------
;
INSTALL:
+ lda #1
+ sta TEXTMAGX
+ sta TEXTMAGY
+ stz BGINDEX
rts
INIT:
; Done, reset the error code
-
lda #TGI_ERR_OK
sta ERROR
rts
;
; Must set an error code: YES
;
+; The TGI lacks a way to draw sprites. As that functionality is vital to
+; Lynx games we borrow this CONTROL function to implement the still
+; missing tgi_draw_sprite funtion. To use this in your C-program
+; do a #define tgi_draw_sprite(spr) tgi_ioctl(0, spr)
+;
+; To do a flip-screen call tgi_ioctl(1, 0)
+;
+; To set the background index for text outputs call tgi_ioctl(2, bgindex)
CONTROL:
- lda #TGI_ERR_INV_FUNC
+ cmp #2
+ bne @L0
+ lda ptr1
+ sta BGINDEX
+ lda #TGI_ERR_OK
+ sta ERROR
+ rts
+@L0:
+ cmp #1
+ bne @L2
+ lda __sprsys
+ eor #8
+ sta __sprsys
+ sta SPRSYS
+
+ lda __viddma
+ eor #2
+ sta __viddma
+ sta DISPCTL
+ ldy VIEWPAGEL
+ ldx VIEWPAGEH
+ and #2
+ beq @L1
+ clc
+ tya
+ adc #<8159
+ tay
+ txa
+ adc #>8159
+ tax
+@L1:
+ sty DISPADRL
+ stx DISPADRH
+ lda #TGI_ERR_OK
+ sta ERROR
+ rts
+@L2:
+ lda ptr1 ; Get the sprite address
+ ldx ptr1+1
+
+draw_sprite: ; Draw it in render buffer
+ sta SCBNEXTL
+ stx SCBNEXTH
+ lda DRAWPAGEL
+ ldx DRAWPAGEH
+ sta VIDBASL
+ stx VIDBASH
+ lda #1
+ sta SPRGO
+ stz SDONEACK
+@L3: stz CPUSLEEP
+ lda SPRSYS
+ lsr
+ bcs @L3
+ stz SDONEACK
+ lda #TGI_ERR_OK
sta ERROR
rts
.code
CLEAR: lda #<cls_sprite
ldx #>cls_sprite
-draw_sprite:
- sta $fc10
- stx $fc11
- lda #1
- sta $fc91
- stz $fd90
-@L3: stz CPUSLEEP
- lda $fc92
- lsr
- bcs @L3
- stz $fd90
- rts
+ bra draw_sprite
; ------------------------------------------------------------------------
; SETVIEWPAGE: Set the visible page. Called with the new page in A (0..n).
;
; Must set an error code: NO (will only be called if page ok)
;
+; It is a good idea to call this function during the vertical blanking
+; period. If you call it in the middle of the screen update then half of
+; the drawn frame will be from the old buffer and the other half is
+; from the new buffer. This is usually noticed by the user.
SETVIEWPAGE:
- beq @L1
- lda #<$fe00-8160-8160
- ldx #>$fe00-8160-8160
+ beq @L1 ; page == maxpages-1
+ ldy #<$de20 ; page 0
+ ldx #>$de20
bra @L2
-@L1: lda #<$fe00-8160
- ldx #>$fe00-8160
-@L2: sta DISPADRL ; $FD94
- sta VIEWPAGEL
- stx DISPADRH ; $FD95
- sta VIEWPAGEH
+@L1:
+ ldy #<$be40 ; page 1
+ ldx #>$be40
+@L2:
+ sty VIEWPAGEL ; Save viewpage for getpixel
+ stx VIEWPAGEH
+
+ lda __viddma ; Process flipped displays
+ and #2
+ beq @L3
+ clc
+ tya
+ adc #<8159
+ tay
+ txa
+ adc #>8159
+ tax
+@L3:
+ sty DISPADRL ; $FD94
+ stx DISPADRH ; $FD95
rts
; ------------------------------------------------------------------------
;
SETDRAWPAGE:
- beq @L1
- lda #<$fe00-8160-8160
- ldx #>$fe00-8160-8160
+ beq @L1 ; page == maxpages-1
+ lda #<$de20 ; page 0
+ ldx #>$de20
bra @L2
-@L1: lda #<$fe00-8160
- ldx #>$fe00-8160
-@L2: sta VIDBASL ; $FD94
- stx VIDBASH ; $FD95
+@L1:
+ lda #<$be40 ; page 1
+ ldx #>$be40
+@L2:
+ sta DRAWPAGEL
+ stx DRAWPAGEH
rts
; ------------------------------------------------------------------------
;
; Must set an error code: NO
;
-
+
.data
pixel_sprite:
.byte %00000001 ; A pixel sprite
.addr 0,pixel_bitmap
pix_x: .word 0
pix_y: .word 0
- .word $0100
- .word $0100
+ .word $100
+ .word $100
pix_c: .byte $00
-
+
.code
SETPIXEL:
lda X1
; LINE: Draw a line from X1/Y1 to X2/Y2, where X1/Y1 = ptr1/ptr2 and
; X2/Y2 = ptr3/ptr4 using the current drawing color.
;
-; To deal with off-screen coordinates, the current row
-; and column (40x25) is kept track of. These are set
-; negative when the point is off the screen, and made
-; positive when the point is within the visible screen.
-;
-; X1,X2 etc. are set up above (x2=LINNUM in particular)
-; Format is LINE x2,y2,x1,y1
-;
; Must set an error code: NO
;
+ .data
+
+line_sprite:
+ .byte 0 ; Will be replaced by the code
+ .byte %00110000
+ .byte %00100000
+ .word 0,pixel_bitmap
+line_x:
+ .word 0
+line_y:
+ .word 0
+line_sx:
+ .word $100
+line_sy:
+ .word $100
+ .word 0
+line_tilt:
+ .word 0
+line_c:
+ .byte $e
+
LINE:
- rts
+ lda DRAWINDEX
+ sta line_c
+ stz line_sx
+ stz line_sy
+
+ sec
+ lda X2
+ sbc X1
+ lda X2+1
+ sbc X1+1
+ bpl @L1
+ lda X1
+ ldx X2
+ sta X2
+ stx X1
+ lda X1+1
+ ldx X2+1
+ sta X2+1
+ stx X1+1
+ lda Y1
+ ldx Y2
+ sta Y2
+ stx Y1
+ lda Y1+1
+ ldx Y2+1
+ sta Y2+1
+ stx Y1+1
+@L1:
+ lda #%00000000 ; Not flipped
+ sta line_sprite
+
+ sec
+ lda Y2
+ sbc Y1
+ sta Y2
+ lda Y2+1
+ sbc Y1+1
+ sta Y2+1
+ bpl @L2
+ sec
+ lda #0
+ sbc Y2
+ sta Y2
+ lda #0
+ sbc Y2+1
+ sta Y2+1
+ lda #%00010000 ; Vertical flip
+ sta line_sprite
+@L2:
+ lda X1
+ sta line_x
+ lda X1+1
+ sta line_x+1
+ lda Y1
+ sta line_y
+ lda Y1+1
+ sta line_y+1
+
+ lda Y2
+ ina
+ sta line_sy+1
+ sta MATHP ; hardware divide
+ stz MATHN
+
+ stz MATHH
+ stz MATHG
+ sec
+ lda X2
+ sbc X1
+ ina
+ sta MATHF
+ stz MATHE
+@L3:
+ lda SPRSYS
+ bmi @L3 ; wait for math done (bit 7 of sprsys)
+ lda MATHC
+ sta line_tilt
+ lda MATHB
+ sta line_tilt+1
+ bne @L4
+ lda #1
+ sta line_sx+1
+ bra @L6
+@L4:
+ bit line_tilt
+ bpl @L5
+ ina
+@L5:
+ sta line_sx+1
+@L6:
+ lda #<line_sprite
+ ldx #>line_sprite
+ jmp draw_sprite
; ------------------------------------------------------------------------
; BAR: Draw a filled rectangle with the corners X1/Y1, X2/Y2, where
lda X2
sec
sbc X1
+ ina
sta bar_sx+1
lda Y2
sec
sbc Y1
+ ina
sta bar_sy+1
lda DRAWINDEX
sta bar_c
;
; Must set an error code: NO
;
+; There is no sensible way of drawing a circle on a Lynx. As I would
+; have to use line elements to do the circle I rather do it in C than
+; create it here in the driver.
+
+; To do a circle please add this to your C program
+
+;int sintbl[9] = {
+; 0, // 0 degrees
+; 3196, // 11.25 degrees
+; 6270, // 22.5 degrees
+; 9102, // 33.75 degrees
+; 11585, // 45 degrees
+; 13623, // 56.25 degrees
+; 15137, // 67.5 degrees
+; 16069, // 78.75 degrees
+; 16384 // 90 degrees
+;};
+
+;int sin(char d)
+;{
+; char neg;
+; d = d & 31;
+; neg = d > 16;
+; d = d & 15;
+; if (d > 8)
+; d = 16 - d;
+; if (neg)
+; return -sintbl[d];
+; else
+; return sintbl[d];
+;}
+
+;void tgi_Circle(int x0, int y0, unsigned char r)
+;{
+; char i;
+; int x1, y1, x2, y2;
+;
+; x1 = ((long)sin(0) * r + 8192) / 16384 + x0;
+; y1 = ((long)sin(8) * r + 8192) / 16384 + y0;
+; for (i = 1; i <= 32; i++) {
+; x2 = ((long)sin(i) * r + 8192) / 16384 + x0;
+; y2 = ((long)sin(i+8) * r + 8192) / 16384 + y0;
+; tgi_line(x1, y1, x2, y2);
+; x1 = x2;
+; y1 = y2;
+; }
+;}
+
+;#define tgi_circle tgi_Circle
CIRCLE:
- rts
+ rts
; ------------------------------------------------------------------------
; TEXTSTYLE: Set the style used when calling OUTTEXT. Text scaling in X and Y
sta TEXTDIR
rts
-
; ------------------------------------------------------------------------
; OUTTEXT: Output text at X/Y = ptr1/ptr2 using the current color and the
; current text style. The text to output is given as a zero terminated
;
OUTTEXT:
- rts
+ lda TEXTMAGX ; Scale sprite
+ sta text_sx+1
+ lda TEXTMAGY
+ sta text_sy+1
+
+ stz text_sprite ; Set normal sprite
+ lda BGINDEX
+ bne @L1
+ lda #4
+ sta text_sprite ; Set opaque sprite
+@L1:
+ lda DRAWINDEX ; Set color
+ asl
+ asl
+ asl
+ asl
+ ora BGINDEX
+ sta text_c
+
+ lda X1 ; Set start position
+ sta text_x
+ lda X1+1
+ sta text_x+1
+ lda Y1
+ sta text_y
+ lda Y1+1
+ sta text_y+1
+
+ ldy #-1 ; Calculate string length
+@L2:
+ iny
+ lda (STRPTR),y
+ bne @L2
+ cpy #20
+ bmi @L3
+ ldy #20
+@L3:
+ sty STRLEN
+ bne @L4
+ rts ; Zero length string
+@L4:
+ iny ; Prepare text_bitmap
+ iny
+ sty STROFF
+
+ ldy #8-1 ; 8 pixel lines per character
+ ldx #0
+ clc
+@L5:
+ lda STROFF
+ sta text_bitmap,x
+ txa
+ adc STROFF
+ tax
+ lda #$ff
+ sta text_bitmap-1,x
+ dey
+ bpl @L5
+ stz text_bitmap,x
+
+ stz tmp2
+ iny
+@L6:
+ lda (STRPTR),y
+ sty tmp1
+
+ sec ; (ch-' ') * 8
+ sbc #32
+ stz FONTOFF
+ stz FONTOFF+1
+ asl
+ asl
+ rol FONTOFF+1
+ asl
+ rol FONTOFF+1
+ clc ; Choose font
+ adc #<font
+ sta FONTOFF
+ lda FONTOFF+1
+ adc #>font
+ sta FONTOFF+1
+
+; and now copy the 8 bytes of that char
+
+ ldx tmp2
+ inx
+ stx tmp2
+
+; draw char from top to bottom, reading char-data from offset 8-1 to offset 0
+ ldy #8-1
+@L7:
+ lda (FONTOFF),y ; *chptr
+ sta text_bitmap,x ;textbuf[y*(1+len+1)+1+x]
+
+ txa
+ adc STROFF
+ tax
+
+ dey
+ bpl @L7
+
+ ; goto next char
+ ldy tmp1
+ iny
+ dec STRLEN
+ bne @L6
+
+ lda #<text_sprite
+ ldx #>text_sprite
+ jmp draw_sprite
+.data
+text_sprite:
+ .byte $00,$90,$20
+ .addr 0, text_bitmap
+text_x:
+ .word 0
+text_y:
+ .word 0
+text_sx:
+ .word $100
+text_sy:
+ .word $100
+text_c:
+ .byte 0
+
+.rodata
+; The Font
+; 96 characters from ASCII 32 to 127
+; 8 pixels wide, 8 pixels high
+; bit value 0 = foreground, bit value 1 = background / transparent
+font:
+; VERSAIL
+ .byte $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF ;32
+ .byte $FF, $E7, $FF, $FF, $E7, $E7, $E7, $E7 ;33
+ .byte $FF, $FF, $FF, $FF, $FF, $99, $99, $99 ;34
+ .byte $FF, $99, $99, $00, $99, $00, $99, $99 ;35
+ .byte $FF, $E7, $83, $F9, $C3, $9F, $C1, $E7 ;36
+ .byte $FF, $B9, $99, $CF, $E7, $F3, $99, $9D ;37
+ .byte $FF, $C0, $99, $98, $C7, $C3, $99, $C3 ;38
+ .byte $FF, $FF, $FF, $FF, $FF, $E7, $F3, $F9 ;39
+ .byte $FF, $F3, $E7, $CF, $CF, $CF, $E7, $F3 ;40
+ .byte $FF, $CF, $E7, $F3, $F3, $F3, $E7, $CF ;41
+ .byte $FF, $FF, $99, $C3, $00, $C3, $99, $FF ;42
+ .byte $FF, $FF, $E7, $E7, $81, $E7, $E7, $FF ;43
+ .byte $CF, $E7, $E7, $FF, $FF, $FF, $FF, $FF ;44
+ .byte $FF, $FF, $FF, $FF, $81, $FF, $FF, $FF ;45
+ .byte $FF, $E7, $E7, $FF, $FF, $FF, $FF, $FF ;46
+ .byte $FF, $9F, $CF, $E7, $F3, $F9, $FC, $FF ;47
+ .byte $FF, $C3, $99, $99, $89, $91, $99, $C3 ;48
+ .byte $FF, $81, $E7, $E7, $E7, $C7, $E7, $E7 ;49
+ .byte $FF, $81, $9F, $CF, $F3, $F9, $99, $C3 ;50
+ .byte $FF, $C3, $99, $F9, $E3, $F9, $99, $C3 ;51
+ .byte $FF, $F9, $F9, $80, $99, $E1, $F1, $F9 ;52
+ .byte $FF, $C3, $99, $F9, $F9, $83, $9F, $81 ;53
+ .byte $FF, $C3, $99, $99, $83, $9F, $99, $C3 ;54
+ .byte $FF, $E7, $E7, $E7, $E7, $F3, $99, $81 ;55
+ .byte $FF, $C3, $99, $99, $C3, $99, $99, $C3 ;56
+ .byte $FF, $C3, $99, $F9, $C1, $99, $99, $C3 ;57
+ .byte $FF, $FF, $E7, $FF, $FF, $E7, $FF, $FF ;58
+ .byte $CF, $E7, $E7, $FF, $FF, $E7, $FF, $FF ;59
+ .byte $FF, $F1, $E7, $CF, $9F, $CF, $E7, $F1 ;60
+ .byte $FF, $FF, $FF, $81, $FF, $81, $FF, $FF ;61
+ .byte $FF, $8F, $E7, $F3, $F9, $F3, $E7, $8F ;62
+ .byte $FF, $E7, $FF, $E7, $F3, $F9, $99, $C3 ;63
+
+
+ .byte $FF, $C3, $9D, $9F, $91, $91, $99, $C3 ;0
+ .byte $FF, $99, $99, $99, $81, $99, $C3, $E7 ;1
+ .byte $FF, $83, $99, $99, $83, $99, $99, $83 ;2
+ .byte $FF, $C3, $99, $9F, $9F, $9F, $99, $C3 ;3
+ .byte $FF, $87, $93, $99, $99, $99, $93, $87 ;4
+ .byte $FF, $81, $9F, $9F, $87, $9F, $9F, $81 ;5
+ .byte $FF, $9F, $9F, $9F, $87, $9F, $9F, $81 ;6
+ .byte $FF, $C3, $99, $99, $91, $9F, $99, $C3 ;7
+ .byte $FF, $99, $99, $99, $81, $99, $99, $99 ;8
+ .byte $FF, $C3, $E7, $E7, $E7, $E7, $E7, $C3 ;9
+ .byte $FF, $C7, $93, $F3, $F3, $F3, $F3, $E1 ;10
+ .byte $FF, $99, $93, $87, $8F, $87, $93, $99 ;11
+ .byte $FF, $81, $9F, $9F, $9F, $9F, $9F, $9F ;12
+ .byte $FF, $9C, $9C, $9C, $94, $80, $88, $9C ;13
+ .byte $FF, $99, $99, $91, $81, $81, $89, $99 ;14
+ .byte $FF, $C3, $99, $99, $99, $99, $99, $C3 ;15
+ .byte $FF, $9F, $9F, $9F, $83, $99, $99, $83 ;16
+ .byte $FF, $F1, $C3, $99, $99, $99, $99, $C3 ;17
+ .byte $FF, $99, $93, $87, $83, $99, $99, $83 ;18
+ .byte $FF, $C3, $99, $F9, $C3, $9F, $99, $C3 ;19
+ .byte $FF, $E7, $E7, $E7, $E7, $E7, $E7, $81 ;20
+ .byte $FF, $C3, $99, $99, $99, $99, $99, $99 ;21
+ .byte $FF, $E7, $C3, $99, $99, $99, $99, $99 ;22
+ .byte $FF, $9C, $88, $80, $94, $9C, $9C, $9C ;23
+ .byte $FF, $99, $99, $C3, $E7, $C3, $99, $99 ;24
+ .byte $FF, $E7, $E7, $E7, $C3, $99, $99, $99 ;25
+ .byte $FF, $81, $9F, $CF, $E7, $F3, $F9, $81 ;26
+ .byte $FF, $C3, $CF, $CF, $CF, $CF, $CF, $C3 ;27
+ .byte $FF, $03, $9D, $CF, $83, $CF, $ED, $F3 ;28
+ .byte $FF, $C3, $F3, $F3, $F3, $F3, $F3, $C3 ;29
+ .byte $E7, $E7, $E7, $E7, $81, $C3, $E7, $FF ;30
+ .byte $FF, $EF, $CF, $80, $80, $CF, $EF, $FF ;31
+
+
+; gemena
+ .byte $FF, $C3, $9D, $9F, $91, $91, $99, $C3 ;224
+ .byte $FF, $C1, $99, $C1, $F9, $C3, $FF, $FF ;225
+ .byte $FF, $83, $99, $99, $83, $9F, $9F, $FF ;226
+ .byte $FF, $C3, $9F, $9F, $9F, $C3, $FF, $FF ;227
+ .byte $FF, $C1, $99, $99, $C1, $F9, $F9, $FF ;228
+ .byte $FF, $C3, $9F, $81, $99, $C3, $FF, $FF ;229
+ .byte $FF, $E7, $E7, $E7, $C1, $E7, $F1, $FF ;230
+ .byte $83, $F9, $C1, $99, $99, $C1, $FF, $FF ;231
+ .byte $FF, $99, $99, $99, $83, $9F, $9F, $FF ;232
+ .byte $FF, $C3, $E7, $E7, $C7, $FF, $E7, $FF ;233
+ .byte $C3, $F9, $F9, $F9, $F9, $FF, $F9, $FF ;234
+ .byte $FF, $99, $93, $87, $93, $9F, $9F, $FF ;235
+ .byte $FF, $C3, $E7, $E7, $E7, $E7, $C7, $FF ;236
+ .byte $FF, $9C, $94, $80, $80, $99, $FF, $FF ;237
+ .byte $FF, $99, $99, $99, $99, $83, $FF, $FF ;238
+ .byte $FF, $C3, $99, $99, $99, $C3, $FF, $FF ;239
+ .byte $9F, $9F, $83, $99, $99, $83, $FF, $FF ;240
+ .byte $F9, $F9, $C1, $99, $99, $C1, $FF, $FF ;241
+ .byte $FF, $9F, $9F, $9F, $99, $83, $FF, $FF ;242
+ .byte $FF, $83, $F9, $C3, $9F, $C1, $FF, $FF ;243
+ .byte $FF, $F1, $E7, $E7, $E7, $81, $E7, $FF ;244
+ .byte $FF, $C1, $99, $99, $99, $99, $FF, $FF ;245
+ .byte $FF, $E7, $C3, $99, $99, $99, $FF, $FF ;246
+ .byte $FF, $C9, $C1, $80, $94, $9C, $FF, $FF ;247
+ .byte $FF, $99, $C3, $E7, $C3, $99, $FF, $FF ;248
+ .byte $87, $F3, $C1, $99, $99, $99, $FF, $FF ;249
+ .byte $FF, $81, $CF, $E7, $F3, $81, $FF, $FF ;250
+ .byte $FF, $C3, $CF, $CF, $CF, $CF, $CF, $C3 ;251
+ .byte $FF, $03, $9D, $CF, $83, $CF, $ED, $F3 ;252
+ .byte $FF, $C3, $F3, $F3, $F3, $F3, $F3, $C3 ;253
+ .byte $E7, $E7, $E7, $E7, $81, $C3, $E7, $FF ;254
+ .byte $FF, $EF, $CF, $80, $80, $CF, $EF, $FF ;255