AVRA Ver. 1.2.3 vga_indirect.asm Sat Sep 12 21:10:37 2009 ; vga_threaded.asm - threaded generate VGA text, background for frame updates ; author Neil Franklin, last modification 2009.03.11 ; ------ hardware usage ; --- controller model ; we are using an ATmega32 .include "m32def.inc" .list ; --- fuse settings ; fast external quarz osc, max stable startup ; FF: 7:BODLVL=1, 6:BOD=1 (disable), 54:SUT=11, 3210:CKSEL=1111 (ext resonat) ; D9: 7:OCDEN=1 (dis), 6:JTAGEN=1 (dis), 5:SPIEN=0 (en), 4:CKOPT=1 ; 3:EESAVE=1 (not preserve), 21:BOOTSZ=00, 0:BOOTRST=1 ; --- board wiring ; VGA "HD-15" connector pinout (correctly named DE15, D-Shell E-size 15pin) ; pins 1/2/3: R/G/B, 0.7V analog ; pin 4: ID2, TTL ; pin 5: GND (for IDs?) ; pins 6/7/8: GND RGB (for R/G/B coax shields) ; pin 9: n.c./key (can also be wired as +5V for DDC) ; pin 10: GND HV (for H-Sync + V-Sync coax shields) ; pins 11/12: ID0/ID1, TTL ; pin 13: H-Sync, TTL (can also be wired as C-Sync) ; pin 14: V-Sync, TTL ; pin 15: n.c. (can also be wired as ID3) ; (ID1/ID3 can also be wired as SDA/SCA for DDC I2C bus) ; VGA "R" DACs, 3 times 2bit/4value, gives 4*4*4=64 colours, RRGGBB ; each DAC from each bit TTL 5V, to 2bit 0.233+0.466V=0.7V @ 75ohm monitor ; needs per DAC resistors: ; bit0 75ohm/0.233V*5V-75ohm = 1534okm -> resistor 1k5ohm ; bit1 75ohm/0.466V*5V-75ohm = 730ohm -> resistor 680ohm (not 820ohm) ; VGA ports and port bits ; video pixel data .equ VGADPORT = PORTC ; 3 2bit colour DACs, write fast, must be same port ; use full 8bit out, bits 7+6 must accept overwrite .equ VGADDDR = DDRC .equ VGABLACK = 0x00 ; all 3 DACs set to 0b00, clear port .equ VGABLUE = 0x03 ; pins 1+0 blue 2bit DAC .equ VGAGREEN = 0x0C ; pins 3+2 green 2bit DAC .equ VGARED = 0x30 ; pins 5+4 red 2bit DAC .equ VGAWHITE = VGABLUE+VGAGREEN+VGARED ; all 3 DACs set to 0b11, also DDR ; sync control lines .equ VGAHPORT = PORTC ; 1 H-Sync TTL out, can accept draw overwrite with 0 .equ VGAHDDR = DDRC .equ VGAHBIT = PINC6 .equ VGAVPORT = PORTC ; 1 V-Sync TTL out, can accept draw overwrite with 0 .equ VGAVDDR = DDRC .equ VGAVBIT = PINC7 ; control ports and port bits ; size, 25 or 30 rows, VGA text 400@70Hz or graphics 480@60Hz timing .equ SIZPORT = PORTD ; 1 size switch TTL in with Pull-Up .equ SIZPIN = PIND .equ SIZDDR = DDRD .equ SIZBIT = PIND7 ; 0(jumper) = 30 rows, 1(default) = 25 rows ; line 2 mode, 2nd blank or double scan .equ LN2PORT = PORTD ; 1 mode switch TTL in with Pull-Up .equ LN2PIN = PIND .equ LN2DDR = DDRD .equ LN2BIT = PIND6 ; 0(jumper) = double scan, 1(default) = 2nd blank ; 2nd blank colour, blank or background .equ CO2PORT = PORTD ; 1 colour switch TTL in with Pull-Up .equ CO2PIN = PIND .equ CO2DDR = DDRD .equ CO2BIT = PIND5 ; 0(jumper) = background, 1(default) = blank ; ------ constants usage ; --- line timing constant .equ TITOP = 74 ; drawing is 40char * 12clk/char = 480 clocks ; line is draw + 1/4 (120) horiz retrace = 600 clocks ; TITOP is 600/8-1, for 0..TITOP, counting @ clock/8 ; --- basic drawing engine buildup .equ ROWSEGMENTS = 8 ; we draw 8 segments per row .equ SEGMENTLINES = 2 ; and 2 lines per segment ; --- VGA timing constants ; VGA text mode frequencies ;; 2k - increase blank lines due to lack of SRAM on 2k ATmega32 ;.equ VRBBTLINES = 12 ; vertical blanking lines, bottom blank .equ VRBBTLINES = 12+16 ; vertical blanking lines, bottom blank .equ VRPUTLINES = 13 ; vertical blanking lines, retrace pulse ;; 2k - increase blank lines due to lack of SRAM on 2k ATmega32 ;.equ VRTBTLINES = 25 ; vertical blanking lines, top blank .equ VRTBTLINES = 25+16 ; vertical blanking lines, top blank ;; 2k - reduce drawing lines due to lack of SRAM on 2k ATmega32 ;.equ CHDRTROWS = 25 ; draw rows*segments(8)*lines(2) = lines(25*8*2=400) .equ CHDRTROWS = 23 ; draw rows*segments(8)*lines(2) = lines(23*8*2=368) ; VGA graphics mode frequencies ;; 2k - increase blank lines due to lack of SRAM on 2k ATmega32 ;.equ VRBBGLINES = 11 ; vertical blanking lines, bottom blank .equ VRBBGLINES = 11+16+40 ; vertical blanking lines, bottom blank .equ VRPUGLINES = 12 ; vertical blanking lines, retrace pulse ;; 2k - increase blank lines due to lack of SRAM on 2k ATmega32 ;.equ VRTBGLINES = 22 ; vertical blanking lines, top blank .equ VRTBGLINES = 22+16+40 ; vertical blanking lines, top blank ;; 2k - reduce drawing lines to lack of SRAM on 2k ATmega32 ;.equ CHDRGROWS = 30 ; draw rows*segments(8)*lines(2) = lines(30*8*2=480) .equ CHDRGROWS = 23 ; draw rows*segments(8)*lines(2) = lines(23*8*2=368) ; --- vertical blanking state numbers ; VR*LINE loops run VRINSTATE = with these constants, all negative values .equ VRINBB = -1 ; all negative values .equ VRINPU = -2 .equ VRINTB = -3 ; CHDRROW loop runs CHROW = CHDRTROWS|CHDRGROWS..1, all positive values ; ------ register usage ; --- standard ones ; use an systematic naming of AVR registers .include "avr_registers.inc" .list ; --- project specific ones ; here use/(re-)name R15..R2 (fast variables) registers ; avra fails to make an .def (or .equ) to an register name defined by .def ; so here use an 2nd .def with the original R* name, and use -W NoRegDef ; for drawing timer ISR ; registers for storing drawing timer ISR continuation address .def BGCONTH = R15 .def BGCONTL = R14 ; registers for storing drawing timer ISR frame buffer address .def BGFBUFH = R13 .def BGFBUFL = R12 ; for drawing control ; registers for vertical blanking line/blanktype loop counting .def VRLINE = R11 ; identical with CHLINE, same use, same register .def VRINSTATE = R10 ; identical with CHROW, track where drawing is ; registers for line drawing line/segm/row loop counting .def CHLINE = R11 ; identical with VRLINE, same use, same register .def CHSEGM = R23 ; must bei R23=I1, for using immediate ops .def CHROW = R10 ; identical with VRINSTATE, track where drawing is ; for colours ; registers for colour patterns, are the LUT, use for out VGADPORT,value-reg ; use non-immediate fast/specials vars, no immediate load and permanent use .def BLANK = R9 ; constant for colour blanking (black) after line .def LUTBACK = R8 ; 2 colours for foreground and background .def LUTFORE = R7 .def LUTCOL3 = R6 ; 3 alternate foreground colours per row .def LUTCOL2 = R5 .def LUTCOL1 = R4 ; R2 and R3 are still free to use as F0 and F1 ; ------ SRAM usage .dseg .org MINRAM ; --- define stack STACK: D:000060 .byte 0x0020 ; uses leftover 0x0020 hole from 0x0060 to 0x007F ; must be here and this size, for FONTRAM: position ENDOFSTACK: ; T0CMPINT + HPULSE + WAIT uses 2+2+2=6 of these ; 32-6=26 are left for background program usage ; --- define runtime font ; one segment .equ FOCHARS = 0x80 ; 0x80|128 characters possible, must be an 2^n value .equ FOINDEXMASK = 0x7F ; 0..0x7F|127 indexes possible, must be 2^n-1 value ; all segments .equ FOSIZE = ROWSEGMENTS*FOCHARS ; space used for font FONTRAM: ; must be an address dividable by FOCHARS, use 0x0080 D:000080 .byte FOSIZE ; uses 8*128 = 1024bytes (of ATmega32 2048) ; --- define frame buffer ; one row .equ FBROWBEG = 5 ; 5 color bytes, at begin of row ;; 2k - reduce characters per row due to lack of SRAM on 2k ATmega32 ;.equ FBCOLS = 40 ; 40 columns of character index bytes in row (old) .equ FBCOLS = 36 ; 36 columns of character index bytes in row (ld) .equ FBROWEND = 1 ; 1 abort pseudo-char, "return" index, at end of row .equ FBROWLEN = FBROWBEG+FBCOLS+FBROWEND ; legth of row in frame buffer ; entire frame .equ FBROWS = CHDRGROWS ; rows in entire frame buffer, largest mode, graph .equ FBSIZE = FBROWS*FBROWLEN ; space used for frame buffer FBUF: ;; 2k - reduce frame buffer size due to lack of SRAM on 2k ATmega32 ;.byte FBSIZE ; uses 30*(5+40+1) = 1390bytes (of ATmega32 2048) D:000480 .byte FBSIZE ; uses 23*(5+36+1) = 966bytes (of ATmega32 2048) ; --- interruts save background register contents INTSREG: ; ordered in row of restoring/loading/"poping" D:000846 .byte 1 ; SREG first, while still not yet restored regs free INTXL: ; register pairs low first then high D:000847 .byte 1 ; and generally following R0..R31 direction INTXH: D:000848 .byte 1 INTYL: D:000849 .byte 1 INTYH: D:00084a .byte 1 INTZL: D:00084b .byte 1 INTZH: D:00084c .byte 1 ; --- snail animation demo position DESNPOS: D:00084d .byte 1 ; snail horizontal position, 0..FBCOLS-1 ; --- cursor animation demo position DECUPOS: D:00084e .byte 1 ; cursor horizontal position, 0..FBCOLS-1 ; --- left over SRAM 2048 - 32 - 1024 - 966 - 7 - 1 - 1 = 17 ; ------ Flash usage .cseg .org MINROM ; ------ system initialisation ; --- handle reset and interrupts (all identical as all not used) ; set up reset and interrupt vectors VECRESET: C:000000 940c 099c jmp RESET VECINT0: C:000002 940c 002a jmp UNUINT VECINT1: C:000004 940c 002a jmp UNUINT VECINT2: C:000006 940c 002a jmp UNUINT VECT2CMP: C:000008 940c 002a jmp UNUINT VECT2OVF: C:00000a 940c 002a jmp UNUINT VECT1CAP: C:00000c 940c 002a jmp UNUINT VECT1CMPA: C:00000e 940c 002a jmp UNUINT VECT1CMPB: C:000010 940c 002a jmp UNUINT VECT1OVF: C:000012 940c 002a jmp UNUINT VECT0CMP: C:000014 940c 057f jmp T0CMPINT VECT0OVF: C:000016 940c 002a jmp UNUINT VECSPI: C:000018 940c 002a jmp UNUINT VECURXC: C:00001a 940c 002a jmp UNUINT VECUDRE: C:00001c 940c 002a jmp UNUINT VECUTXC: C:00001e 940c 002a jmp UNUINT VECADC: C:000020 940c 002a jmp UNUINT VECEERDY: C:000022 940c 002a jmp UNUINT VECACMP: C:000024 940c 002a jmp UNUINT VECTWI: C:000026 940c 002a jmp UNUINT VECSPM: C:000028 940c 002a jmp UNUINT ; --- handle unused interrupts, despite not used nor triggered UNUINT: ; just return, nothing else makes sense here C:00002a 9518 reti ; ------ debugging helpers ; --- debuging LED, using TxD pin + RS232 adapter + RSR23 tester TxD LED ; reset state is DDR-TxD=0=in, TTL=float/5V, RS232=-12V, LED=red ; allways set port bit and DDR, so no setup is required DBGLEDGRN: C:00002b 9891 cbi PORTD,PINTXD ; TxD=0, TTL=0V, RS232=12V, LED=green C:00002c 9a89 sbi DDRD,PINTXD ; DDR-TxD=1=out C:00002d 9508 ret DBGLEDRED: C:00002e 9a91 sbi PORTD,PINTXD ; TxD=1, TTL=5V, RS232=-12V, LED=red C:00002f 9a89 sbi DDRD,PINTXD ; DDR-TxD=1=out C:000030 9508 ret DBGLEDINV: C:000031 9b91 sbis PORTD,PINTXD C:000032 cffb rjmp DBGLEDRED ; TxD is 0, invert to TxD=1 C:000033 cff7 rjmp DBGLEDGRN ; TxD is 1, invert to TxD=0 ; ------ font unthreading and drawing mechanism ; --- segment drawing routines ; each char in font is an set of ROWSEGMENTS segments ; these get drawn on ROWSEGMENTS consecutive line(pair)s ; each segment consists of 4 pixels, giving 16 different possbile segments ; drawing an segment consists of 4*3 clocks, split as: ; 4 clocks write pixels with out VGADPORT,xxxx (xxxx = LUTFORE or LUTBACK) ; between these 4*2 clocks for unthreading and indirect jumping next char ; the code for unthreading and indirect jumping works like this: ; ijmp requires address in ZH:ZL, no other possible ; ZH is constant, high addr of SEGM table, settable by ldi ZH,high(SEGM) ; ZL is fetched from font segment index tables, each char, by ld ZL, ; ld requires address in XH:XL, as ZH:ZL and YH:YL already used ; XH is per-segment constant, high addr of table, set once for segm draw ; XL is part (bit6..0) fetched from frame buffer, by ld XL,Y+ ; and part (bit7) per-segment constant, low addr of table ; addressed/executed by indirect computed ijmp, only 8bit indexing for speed ; the labels are only needed for jump table building .org 0x0100 ; must be 0x??00, begin of 8bit 256word|512byte page ; hardcoded 0x0100, as avra knows no .align ; will give error message if more than 0x0100 used DRSEGM: ; all 16 segments for character drawing, repeat for each pixelsets segment: ; DRSEGMxxxx: ; {4*(1+2)=12} and 9instr, 16segm=144instr, 9/16 space ; out VGADPORT,LUT* ; {1} current character: draw pixel 1 ; ld XL,Y+ ; {2} next character: get character code/index ; out VGADPORT,LUT* ; {1} current character: draw pixel 2 ; or XL,I0 ; {1} next character: low(half-page base font table) ; nop ; {1} XH:I1 set to segm font table before drawing ; out VGADPORT,LUT* ; {1} current character: draw pixel 3 ; ld ZL,X ; {2} next character: read index, is low(DRSEGM*) ; ; ZH is set to high(DRSEGM*) before drawing ; out VGADPORT,LUT* ; {1} current character: draw pixel 4 ; ijmp ; {2} next character: goto ZH:ZL and execute it ; ; continuation at next chars pixel 1, as above ; ; this results in an endless loop, until abort char DRSEGM0000: C:000100 ba85 out VGADPORT,LUTBACK C:000101 91a9 ld XL,Y+ C:000102 ba85 out VGADPORT,LUTBACK C:000103 2ba6 or XL,I0 C:000104 0000 nop C:000105 ba85 out VGADPORT,LUTBACK C:000106 91ec ld ZL,X C:000107 ba85 out VGADPORT,LUTBACK C:000108 9409 ijmp DRSEGM0001: C:000109 ba85 out VGADPORT,LUTBACK C:00010a 91a9 ld XL,Y+ C:00010b ba85 out VGADPORT,LUTBACK C:00010c 2ba6 or XL,I0 C:00010d 0000 nop C:00010e ba85 out VGADPORT,LUTBACK C:00010f 91ec ld ZL,X C:000110 ba75 out VGADPORT,LUTFORE C:000111 9409 ijmp DRSEGM0010: C:000112 ba85 out VGADPORT,LUTBACK C:000113 91a9 ld XL,Y+ C:000114 ba85 out VGADPORT,LUTBACK C:000115 2ba6 or XL,I0 C:000116 0000 nop C:000117 ba75 out VGADPORT,LUTFORE C:000118 91ec ld ZL,X C:000119 ba85 out VGADPORT,LUTBACK C:00011a 9409 ijmp DRSEGM0011: C:00011b ba85 out VGADPORT,LUTBACK C:00011c 91a9 ld XL,Y+ C:00011d ba85 out VGADPORT,LUTBACK C:00011e 2ba6 or XL,I0 C:00011f 0000 nop C:000120 ba75 out VGADPORT,LUTFORE C:000121 91ec ld ZL,X C:000122 ba75 out VGADPORT,LUTFORE C:000123 9409 ijmp DRSEGM0100: C:000124 ba85 out VGADPORT,LUTBACK C:000125 91a9 ld XL,Y+ C:000126 ba75 out VGADPORT,LUTFORE C:000127 2ba6 or XL,I0 C:000128 0000 nop C:000129 ba85 out VGADPORT,LUTBACK C:00012a 91ec ld ZL,X C:00012b ba85 out VGADPORT,LUTBACK C:00012c 9409 ijmp DRSEGM0101: C:00012d ba85 out VGADPORT,LUTBACK C:00012e 91a9 ld XL,Y+ C:00012f ba75 out VGADPORT,LUTFORE C:000130 2ba6 or XL,I0 C:000131 0000 nop C:000132 ba85 out VGADPORT,LUTBACK C:000133 91ec ld ZL,X C:000134 ba75 out VGADPORT,LUTFORE C:000135 9409 ijmp DRSEGM0110: C:000136 ba85 out VGADPORT,LUTBACK C:000137 91a9 ld XL,Y+ C:000138 ba75 out VGADPORT,LUTFORE C:000139 2ba6 or XL,I0 C:00013a 0000 nop C:00013b ba75 out VGADPORT,LUTFORE C:00013c 91ec ld ZL,X C:00013d ba85 out VGADPORT,LUTBACK C:00013e 9409 ijmp DRSEGM0111: C:00013f ba85 out VGADPORT,LUTBACK C:000140 91a9 ld XL,Y+ C:000141 ba75 out VGADPORT,LUTFORE C:000142 2ba6 or XL,I0 C:000143 0000 nop C:000144 ba75 out VGADPORT,LUTFORE C:000145 91ec ld ZL,X C:000146 ba75 out VGADPORT,LUTFORE C:000147 9409 ijmp DRSEGM1000: C:000148 ba75 out VGADPORT,LUTFORE C:000149 91a9 ld XL,Y+ C:00014a ba85 out VGADPORT,LUTBACK C:00014b 2ba6 or XL,I0 C:00014c 0000 nop C:00014d ba85 out VGADPORT,LUTBACK C:00014e 91ec ld ZL,X C:00014f ba85 out VGADPORT,LUTBACK C:000150 9409 ijmp DRSEGM1001: C:000151 ba75 out VGADPORT,LUTFORE C:000152 91a9 ld XL,Y+ C:000153 ba85 out VGADPORT,LUTBACK C:000154 2ba6 or XL,I0 C:000155 0000 nop C:000156 ba85 out VGADPORT,LUTBACK C:000157 91ec ld ZL,X C:000158 ba75 out VGADPORT,LUTFORE C:000159 9409 ijmp DRSEGM1010: C:00015a ba75 out VGADPORT,LUTFORE C:00015b 91a9 ld XL,Y+ C:00015c ba85 out VGADPORT,LUTBACK C:00015d 2ba6 or XL,I0 C:00015e 0000 nop C:00015f ba75 out VGADPORT,LUTFORE C:000160 91ec ld ZL,X C:000161 ba85 out VGADPORT,LUTBACK C:000162 9409 ijmp DRSEGM1011: C:000163 ba75 out VGADPORT,LUTFORE C:000164 91a9 ld XL,Y+ C:000165 ba85 out VGADPORT,LUTBACK C:000166 2ba6 or XL,I0 C:000167 0000 nop C:000168 ba75 out VGADPORT,LUTFORE C:000169 91ec ld ZL,X C:00016a ba75 out VGADPORT,LUTFORE C:00016b 9409 ijmp DRSEGM1100: C:00016c ba75 out VGADPORT,LUTFORE C:00016d 91a9 ld XL,Y+ C:00016e ba75 out VGADPORT,LUTFORE C:00016f 2ba6 or XL,I0 C:000170 0000 nop C:000171 ba85 out VGADPORT,LUTBACK C:000172 91ec ld ZL,X C:000173 ba85 out VGADPORT,LUTBACK C:000174 9409 ijmp DRSEGM1101: C:000175 ba75 out VGADPORT,LUTFORE C:000176 91a9 ld XL,Y+ C:000177 ba75 out VGADPORT,LUTFORE C:000178 2ba6 or XL,I0 C:000179 0000 nop C:00017a ba85 out VGADPORT,LUTBACK C:00017b 91ec ld ZL,X C:00017c ba75 out VGADPORT,LUTFORE C:00017d 9409 ijmp DRSEGM1110: C:00017e ba75 out VGADPORT,LUTFORE C:00017f 91a9 ld XL,Y+ C:000180 ba75 out VGADPORT,LUTFORE C:000181 2ba6 or XL,I0 C:000182 0000 nop C:000183 ba75 out VGADPORT,LUTFORE C:000184 91ec ld ZL,X C:000185 ba85 out VGADPORT,LUTBACK C:000186 9409 ijmp DRSEGM1111: C:000187 ba75 out VGADPORT,LUTFORE C:000188 91a9 ld XL,Y+ C:000189 ba75 out VGADPORT,LUTFORE C:00018a 2ba6 or XL,I0 C:00018b 0000 nop C:00018c ba75 out VGADPORT,LUTFORE C:00018d 91ec ld ZL,X C:00018e ba75 out VGADPORT,LUTFORE C:00018f 9409 ijmp ; the pseudo-segment for the row end abort pseudo-character ; no drawing after 1st pixel, no timing, no unthreading next character DRSEGMABRT: C:000190 ba95 out VGADPORT,BLANK ; {1} switch off whatever was last background colour ; this is timing critical, so do it before jump ;; 2k - increase blank characters due to lack of SRAM on 2k ATmega32 ; {increase2char*12=24} C:000191 e065 ldi I0,5 ; {1} C:000192 d3e9 rcall WAIT ; {3+(5*3+3)=21} C:000193 0000 nop ; {2} C:000194 0000 nop C:000195 940c 066f jmp CHEND ; {3} go back to common CHDRLINE handler for rest ; no rjmp because font may become too large ; some more pseudo-segments for the "specials" pseudo-characters ; no drawing after 1st pixel, no nop, but after unthread next character ; {1} current character: draw only pixel 1, as spaces all LUTBACK ; {12-1-7=4} time for special stuff, the desired side effects ; {2+1+2+2=7} next character: all unthread stuff at once DRSEGM0FXB: ; for special pseudo-chars "invert" and "underline" C:000197 ba85 out VGADPORT,LUTBACK ; for invert use 8 times, for underline 7space+1this C:000198 2478 eor LUTFORE,LUTBACK ; {1} FORE.eor.BACK "mixed" C:000199 2487 eor LUTBACK,LUTFORE ; {1} BACK.eor.(FORE.eor.BACK) = FORE "unmix" C:00019a 2478 eor LUTFORE,LUTBACK ; {1} (FORE.eor.BACK).eor.FORE = BACK "unmix" C:00019b ba85 out VGADPORT,LUTBACK ; switch to new bg colour halfway through pseudo-space C:00019c 91a9 ld XL,Y+ C:00019d 2ba6 or XL,I0 C:00019e 91ec ld ZL,X C:00019f 9409 ijmp DRSEGM0FX1: ; for special pseudo-char "foregr alt colour 1" C:0001a0 ba85 out VGADPORT,LUTBACK C:0001a1 2474 eor LUTFORE,LUTCOL1 ; {1} FORE.eor.COL1 "mixed" C:0001a2 2447 eor LUTCOL1,LUTFORE ; {1} COL1.eor.(FORE.eor.COL1) = FORE "unmix" C:0001a3 2474 eor LUTFORE,LUTCOL1 ; {1} (FORE.eor.COL1).eor.FORE = COL1 "unmix" C:0001a4 0000 nop ; {1} C:0001a5 91a9 ld XL,Y+ C:0001a6 2ba6 or XL,I0 C:0001a7 91ec ld ZL,X C:0001a8 9409 ijmp DRSEGM0FX2: ; for special pseudo-char "foregr alt colour 2" C:0001a9 ba85 out VGADPORT,LUTBACK C:0001aa 2475 eor LUTFORE,LUTCOL2 ; {1} FORE.eor.COL2 "mixed" C:0001ab 2457 eor LUTCOL2,LUTFORE ; {1} COL2.eor.(FORE.eor.COL2) = FORE "unmix" C:0001ac 2475 eor LUTFORE,LUTCOL2 ; {1} (FORE.eor.COL2).eor.FORE = COL2 "unmix" C:0001ad 0000 nop ; {1} C:0001ae 91a9 ld XL,Y+ C:0001af 2ba6 or XL,I0 C:0001b0 91ec ld ZL,X C:0001b1 9409 ijmp DRSEGM0BX3: ; for special pseudo-char "backgr alt colour 3" C:0001b2 ba85 out VGADPORT,LUTBACK C:0001b3 2486 eor LUTBACK,LUTCOL3 ; {1} BACK.eor.COL3 "mixed" C:0001b4 2468 eor LUTCOL3,LUTBACK ; {1} COL3.eor.(BACK.eor.COL3) = BACK "unmix" C:0001b5 2486 eor LUTBACK,LUTCOL3 ; {1} (BACK.eor.COL3).eor.BACK = COL3 "unmix" C:0001b6 ba85 out VGADPORT,LUTBACK ; switch to new bg colour halfway through pseudo-space C:0001b7 91a9 ld XL,Y+ C:0001b8 2ba6 or XL,I0 C:0001b9 91ec ld ZL,X C:0001ba 9409 ijmp ; ensure that segments fit in 256word|512byte and can be low() 8bit addressed .org DRSEGM+0x0100 ; must use less than an +1 8bit 256word|512byte page ; will give error if over 0x0100 used for DRSEGM* ; --- indexing into segment drawing routines ; table to convert pixel pattern numbers to segment drawing routine addresses ; addressed by computed base+offset, with 16bit base and 8bit offset ; so only one SEGM: label is needed, for marking table base ; the SEGM* are only .equ, not labels, for user using them in .db lines ; the .db lines must have n*2 bytes each, else lpm indexing fails ; group as sets of 4 to save code lines and scrolling ; pattern-as-index value is used as offset to SEGM: label ; first the 16 4-pixel combinations 0000..1111 as indexes 0..15 ; then the pseudo segments for pseudo characters with indexes 16 and above .equ SEGMNO = 0x14 ; we use indexes 0x00..0x13, 0x14 in all SEGM: .equ SEGM0000 = 0x00 .equ SEGM0001 = 0x01 .equ SEGM0010 = 0x02 .equ SEGM0011 = 0x03 .db low(DRSEGM0000), low(DRSEGM0001), low(DRSEGM0010), low(DRSEGM0011) C:000200 0009121B .equ SEGM0100 = 0x04 .equ SEGM0101 = 0x05 .equ SEGM0110 = 0x06 .equ SEGM0111 = 0x07 .db low(DRSEGM0100), low(DRSEGM0101), low(DRSEGM0110), low(DRSEGM0111) C:000202 242D363F .equ SEGM1000 = 0x08 .equ SEGM1001 = 0x09 .equ SEGM1010 = 0x0A .equ SEGM1011 = 0x0B .db low(DRSEGM1000), low(DRSEGM1001), low(DRSEGM1010), low(DRSEGM1011) C:000204 48515A63 .equ SEGM1100 = 0x0C .equ SEGM1101 = 0x0D .equ SEGM1110 = 0x0E .equ SEGM1111 = 0x0F .db low(DRSEGM1100), low(DRSEGM1101), low(DRSEGM1110), low(DRSEGM1111) C:000206 6C757E87 ; no index for DRSEGMABRT, never in font, prevent user screwing stuff up ; as result of this the special character must be built with explicit low() .equ SEGM0FXB = 0x10 .equ SEGM0FX1 = 0x11 .equ SEGM0FX2 = 0x12 .equ SEGM0BX3 = 0x13 .db low(DRSEGM0FXB), low(DRSEGM0FX1), low(DRSEGM0FX2), low(DRSEGM0BX3) C:000208 97A0A9B2 ; --- convert pixel pattern number to segment drawing routine addresse ; parameters: T0: pixel pattern number ; returns: T0: low() of segment routine address SEGMCONV: C:00020a 93ff push ZH ; lpm can unfortunately only use ZH:ZL, so reuse it C:00020b 93ef push ZL ; save it here so multiple callers don't need to C:00020c 3104 cpi T0,SEGMNO ; catch invalid indexes, and so invalid bit patterns C:00020d f008 brlo FOCHINRANGE C:00020e e000 ldi T0,SEGM0000 FOCHINRANGE: C:00020f e0e0 ldi ZL,low(SEGM*2) ; base + offset for T2=SEGM[T2] C:000210 e0f4 ldi ZH,high(SEGM*2) ; *2 because of lpm word->byte addresses ; so index table must be in first 64kbyte|32kword C:000211 0fe0 add ZL,T0 C:000212 e000 ldi T0,0 ; expand offset to 16bit, allways 0, as no adci ZH,0 C:000213 1ff0 adc ZH,T0 C:000214 9104 lpm T0,Z ; get low(DRSEGM*) address C:000215 91ef pop ZL ; restore main ZH:ZL after reusing C:000216 91ff pop ZH C:000217 9508 ret ; --- font segment index tables ; each char in font is an set of indexes (1 per segment) into SEGM table ; addressed by computed base+offset, again with 16bit base and 8bit offset ; the FONTROM: label is only for marking font base ; the font consists entirely of .db statements ; the .db lines must have n*2 bytes each, else lpm indexing fails ; group as sets of 4 to save code lines and scrolling ; intermingled with these are .equ statements for character names ; and also labels for identifying and loading blocks of characters FONTROM: ; include font as separate file, so it may be generated automatically ; is done so from file vga_text_font.fon, by generator ./genfont .include "vga_text_font.inc" ; vga_text_font.inc - font for generating VGA text - converted to code ; generated from vga_text_font.fon, last generation 2009.03.15 SYSTEM: .equ INV = 0x00 .equ ULIN = 0x01 .equ FG1 = 0x02 .equ FG2 = 0x03 .equ BG3 = 0x04 .equ UN0101 = 0x05 .equ UN0110 = 0x06 .equ UN0111 = 0x07 .equ UN1000 = 0x08 .equ UN1001 = 0x09 .equ UN1010 = 0x0A .equ UN1011 = 0x0B .equ UN1100 = 0x0C .equ UN1101 = 0x0D .equ UN1110 = 0x0E .equ UN1111 = 0x0F ; system invert/reverse foreground and background colour 0x00 .db SEGM0FXB, SEGM0FXB, SEGM0FXB, SEGM0FXB C:000218 10101010 .db SEGM0FXB, SEGM0FXB, SEGM0FXB, SEGM0FXB C:00021A 10101010 ; system underline invert/reverse only bottom segment 0x01 .db SEGM0000, SEGM0000, SEGM0000, SEGM0000 C:00021C 00000000 .db SEGM0000, SEGM0000, SEGM0000, SEGM0FXB C:00021E 00000010 ; system wap foreground with alternate colour 1 0x02 .db SEGM0FX1, SEGM0FX1, SEGM0FX1, SEGM0FX1 C:000220 11111111 .db SEGM0FX1, SEGM0FX1, SEGM0FX1, SEGM0FX1 C:000222 11111111 ; system wap foreground with alternate colour 2 0x03 .db SEGM0FX2, SEGM0FX2, SEGM0FX2, SEGM0FX2 C:000224 12121212 .db SEGM0FX2, SEGM0FX2, SEGM0FX2, SEGM0FX2 C:000226 12121212 ; system swap background with alternate colour 3 0x04 .db SEGM0BX3, SEGM0BX3, SEGM0BX3, SEGM0BX3 C:000228 13131313 .db SEGM0BX3, SEGM0BX3, SEGM0BX3, SEGM0BX3 C:00022A 13131313 ; system unused 0101 0x05 .db SEGM0000, SEGM0000, SEGM0110, SEGM0010 C:00022C 00000602 .db SEGM0010, SEGM0110, SEGM0000, SEGM0000 C:00022E 02060000 ; system unused 0110 0x06 .db SEGM0000, SEGM0000, SEGM0110, SEGM0010 C:000230 00000602 .db SEGM0100, SEGM0110, SEGM0000, SEGM0000 C:000232 04060000 ; system unused 0111 0x07 .db SEGM0000, SEGM0000, SEGM0110, SEGM0010 C:000234 00000602 .db SEGM0110, SEGM0110, SEGM0000, SEGM0000 C:000236 06060000 ; system unused 1000 0x08 .db SEGM0000, SEGM0000, SEGM0110, SEGM0100 C:000238 00000604 .db SEGM0000, SEGM0110, SEGM0000, SEGM0000 C:00023A 00060000 ; system unused 1001 0x09 .db SEGM0000, SEGM0000, SEGM0110, SEGM0100 C:00023C 00000604 .db SEGM0010, SEGM0110, SEGM0000, SEGM0000 C:00023E 02060000 ; system unused 1010 0x0A .db SEGM0000, SEGM0000, SEGM0110, SEGM0100 C:000240 00000604 .db SEGM0100, SEGM0110, SEGM0000, SEGM0000 C:000242 04060000 ; system unused 1011 0x0B .db SEGM0000, SEGM0000, SEGM0110, SEGM0100 C:000244 00000604 .db SEGM0110, SEGM0110, SEGM0000, SEGM0000 C:000246 06060000 ; system unused 1100 0x0C .db SEGM0000, SEGM0000, SEGM0110, SEGM0110 C:000248 00000606 .db SEGM0000, SEGM0110, SEGM0000, SEGM0000 C:00024A 00060000 ; system unused 1101 0x0D .db SEGM0000, SEGM0000, SEGM0110, SEGM0110 C:00024C 00000606 .db SEGM0010, SEGM0110, SEGM0000, SEGM0000 C:00024E 02060000 ; system unused 1110 0x0E .db SEGM0000, SEGM0000, SEGM0110, SEGM0110 C:000250 00000606 .db SEGM0100, SEGM0110, SEGM0000, SEGM0000 C:000252 04060000 ; system unused 1111 0x0F .db SEGM0000, SEGM0000, SEGM0110, SEGM0110 C:000254 00000606 .db SEGM0110, SEGM0110, SEGM0000, SEGM0000 C:000256 06060000 BLOCKGRAPHIC: .equ BG0000 = 0x10 .equ BG0001 = 0x11 .equ BG0010 = 0x12 .equ BG0011 = 0x13 .equ BG0100 = 0x14 .equ BG0101 = 0x15 .equ BG0110 = 0x16 .equ BG0111 = 0x17 .equ BG1000 = 0x18 .equ BG1001 = 0x19 .equ BG1010 = 0x1A .equ BG1011 = 0x1B .equ BG1100 = 0x1C .equ BG1101 = 0x1D .equ BG1110 = 0x1E .equ BG1111 = 0x1F ; block graphic 00/00 0x10 .db SEGM0000, SEGM0000, SEGM0000, SEGM0000 C:000258 00000000 .db SEGM0000, SEGM0000, SEGM0000, SEGM0000 C:00025A 00000000 ; block graphic 00/01 0x11 .db SEGM0000, SEGM0000, SEGM0000, SEGM0000 C:00025C 00000000 .db SEGM0011, SEGM0011, SEGM0011, SEGM0011 C:00025E 03030303 ; block graphic 00/10 0x12 .db SEGM0000, SEGM0000, SEGM0000, SEGM0000 C:000260 00000000 .db SEGM1100, SEGM1100, SEGM1100, SEGM1100 C:000262 0C0C0C0C ; block graphic 00/11 0x13 .db SEGM0000, SEGM0000, SEGM0000, SEGM0000 C:000264 00000000 .db SEGM1111, SEGM1111, SEGM1111, SEGM1111 C:000266 0F0F0F0F ; block graphic 01/00 0x14 .db SEGM0011, SEGM0011, SEGM0011, SEGM0011 C:000268 03030303 .db SEGM0000, SEGM0000, SEGM0000, SEGM0000 C:00026A 00000000 ; block graphic 01/01 0x15 .db SEGM0011, SEGM0011, SEGM0011, SEGM0011 C:00026C 03030303 .db SEGM0011, SEGM0011, SEGM0011, SEGM0011 C:00026E 03030303 ; block graphic 01/10 0x16 .db SEGM0011, SEGM0011, SEGM0011, SEGM0011 C:000270 03030303 .db SEGM1100, SEGM1100, SEGM1100, SEGM1100 C:000272 0C0C0C0C ; block graphic 01/11 0x17 .db SEGM0011, SEGM0011, SEGM0011, SEGM0011 C:000274 03030303 .db SEGM1111, SEGM1111, SEGM1111, SEGM1111 C:000276 0F0F0F0F ; block graphic 10/00 0x18 .db SEGM1100, SEGM1100, SEGM1100, SEGM1100 C:000278 0C0C0C0C .db SEGM0000, SEGM0000, SEGM0000, SEGM0000 C:00027A 00000000 ; block graphic 10/01 0x19 .db SEGM1100, SEGM1100, SEGM1100, SEGM1100 C:00027C 0C0C0C0C .db SEGM0011, SEGM0011, SEGM0011, SEGM0011 C:00027E 03030303 ; block graphic 10/10 0x1A .db SEGM1100, SEGM1100, SEGM1100, SEGM1100 C:000280 0C0C0C0C .db SEGM1100, SEGM1100, SEGM1100, SEGM1100 C:000282 0C0C0C0C ; block graphic 10/11 0x1B .db SEGM1100, SEGM1100, SEGM1100, SEGM1100 C:000284 0C0C0C0C .db SEGM1111, SEGM1111, SEGM1111, SEGM1111 C:000286 0F0F0F0F ; block graphic 11/00 0x1C .db SEGM1111, SEGM1111, SEGM1111, SEGM1111 C:000288 0F0F0F0F .db SEGM0000, SEGM0000, SEGM0000, SEGM0000 C:00028A 00000000 ; block graphic 11/01 0x1D .db SEGM1111, SEGM1111, SEGM1111, SEGM1111 C:00028C 0F0F0F0F .db SEGM0011, SEGM0011, SEGM0011, SEGM0011 C:00028E 03030303 ; block graphic 11/10 0x1E .db SEGM1111, SEGM1111, SEGM1111, SEGM1111 C:000290 0F0F0F0F .db SEGM1100, SEGM1100, SEGM1100, SEGM1100 C:000292 0C0C0C0C ; block graphic 11/11 0x1F .db SEGM1111, SEGM1111, SEGM1111, SEGM1111 C:000294 0F0F0F0F .db SEGM1111, SEGM1111, SEGM1111, SEGM1111 C:000296 0F0F0F0F ASCII: ; ASCII " " 0x20 .db SEGM0000, SEGM0000, SEGM0000, SEGM0000 C:000298 00000000 .db SEGM0000, SEGM0000, SEGM0000, SEGM0000 C:00029A 00000000 ; ASCII "!" 0x21 .db SEGM0000, SEGM0100, SEGM0100, SEGM0100 C:00029C 00040404 .db SEGM0100, SEGM0000, SEGM0100, SEGM0000 C:00029E 04000400 ; ASCII """ 0x22 .db SEGM0000, SEGM1010, SEGM1010, SEGM1010 C:0002A0 000A0A0A .db SEGM0000, SEGM0000, SEGM0000, SEGM0000 C:0002A2 00000000 ; ASCII " .db SEGM0000, SEGM1010, SEGM1010, SEGM1110 C:0002A4 000A0A0E .db SEGM1010, SEGM1110, SEGM1010, SEGM1010 C:0002A6 0A0E0A0A ; ASCII "$" 0x24 .db SEGM0000, SEGM0100, SEGM0110, SEGM1100 C:0002A8 0004060C .db SEGM0100, SEGM0110, SEGM1100, SEGM0100 C:0002AA 04060C04 ; ASCII "%" 0x25 .db SEGM0000, SEGM1010, SEGM0010, SEGM0100 C:0002AC 000A0204 .db SEGM0100, SEGM1000, SEGM1010, SEGM0000 C:0002AE 04080A00 ; ASCII "&" 0x26 .db SEGM0000, SEGM0100, SEGM1010, SEGM0100 C:0002B0 00040A04 .db SEGM1010, SEGM1010, SEGM0110, SEGM0000 C:0002B2 0A0A0600 ; ASCII "'" 0x27 .db SEGM0000, SEGM0100, SEGM1000, SEGM0000 C:0002B4 00040800 .db SEGM0000, SEGM0000, SEGM0000, SEGM0000 C:0002B6 00000000 ; ASCII "(" 0x28 .db SEGM0000, SEGM0100, SEGM1000, SEGM1000 C:0002B8 00040808 .db SEGM1000, SEGM1000, SEGM0100, SEGM0000 C:0002BA 08080400 ; ASCII ")" 0x29 .db SEGM0000, SEGM0100, SEGM0010, SEGM0010 C:0002BC 00040202 .db SEGM0010, SEGM0010, SEGM0100, SEGM0000 C:0002BE 02020400 ; ASCII "*" 0x2A .db SEGM0000, SEGM0000, SEGM0100, SEGM1110 C:0002C0 0000040E .db SEGM0100, SEGM1110, SEGM0100, SEGM0000 C:0002C2 040E0400 ; ASCII "+" 0x2B .db SEGM0000, SEGM0000, SEGM0100, SEGM0100 C:0002C4 00000404 .db SEGM1110, SEGM0100, SEGM0100, SEGM0000 C:0002C6 0E040400 ; ASCII "," 0x2C .db SEGM0000, SEGM0000, SEGM0000, SEGM0000 C:0002C8 00000000 .db SEGM0000, SEGM0100, SEGM0100, SEGM1000 C:0002CA 00040408 ; ASCII "-" 0x2D .db SEGM0000, SEGM0000, SEGM0000, SEGM0000 C:0002CC 00000000 .db SEGM1110, SEGM0000, SEGM0000, SEGM0000 C:0002CE 0E000000 ; ASCII "." 0x2E .db SEGM0000, SEGM0000, SEGM0000, SEGM0000 C:0002D0 00000000 .db SEGM0000, SEGM0100, SEGM0100, SEGM0000 C:0002D2 00040400 ; ASCII "/" 0x2F .db SEGM0000, SEGM0010, SEGM0010, SEGM0100 C:0002D4 00020204 .db SEGM0100, SEGM1000, SEGM1000, SEGM0000 C:0002D6 04080800 ; ASCII "0" 0x30 .db SEGM0000, SEGM0100, SEGM1010, SEGM1010 C:0002D8 00040A0A .db SEGM1010, SEGM1010, SEGM0100, SEGM0000 C:0002DA 0A0A0400 ; ASCII "1" 0x31 .db SEGM0000, SEGM0100, SEGM1100, SEGM0100 C:0002DC 00040C04 .db SEGM0100, SEGM0100, SEGM1110, SEGM0000 C:0002DE 04040E00 ; ASCII "2" 0x32 .db SEGM0000, SEGM0100, SEGM1010, SEGM0010 C:0002E0 00040A02 .db SEGM0100, SEGM1000, SEGM1110, SEGM0000 C:0002E2 04080E00 ; ASCII "3" 0x33 .db SEGM0000, SEGM1100, SEGM0010, SEGM0100 C:0002E4 000C0204 .db SEGM0010, SEGM0010, SEGM1100, SEGM0000 C:0002E6 02020C00 ; ASCII "4" 0x34 .db SEGM0000, SEGM1000, SEGM1010, SEGM1010 C:0002E8 00080A0A .db SEGM1110, SEGM0010, SEGM0010, SEGM0000 C:0002EA 0E020200 ; ASCII "5" 0x35 .db SEGM0000, SEGM1110, SEGM1000, SEGM1100 C:0002EC 000E080C .db SEGM0010, SEGM0010, SEGM1100, SEGM0000 C:0002EE 02020C00 ; ASCII "6" 0x36 .db SEGM0000, SEGM0100, SEGM1000, SEGM1100 C:0002F0 0004080C .db SEGM1010, SEGM1010, SEGM0100, SEGM0000 C:0002F2 0A0A0400 ; ASCII "7" 0x37 .db SEGM0000, SEGM1110, SEGM0010, SEGM0010 C:0002F4 000E0202 .db SEGM0100, SEGM0100, SEGM0100, SEGM0000 C:0002F6 04040400 ; ASCII "8" 0x38 .db SEGM0000, SEGM0100, SEGM1010, SEGM0100 C:0002F8 00040A04 .db SEGM1010, SEGM1010, SEGM0100, SEGM0000 C:0002FA 0A0A0400 ; ASCII "9" 0x39 .db SEGM0000, SEGM0100, SEGM1010, SEGM1010 C:0002FC 00040A0A .db SEGM0110, SEGM0010, SEGM0100, SEGM0000 C:0002FE 06020400 ; ASCII ":" 0x3A .db SEGM0000, SEGM0000, SEGM0100, SEGM0100 C:000300 00000404 .db SEGM0000, SEGM0100, SEGM0100, SEGM0000 C:000302 00040400 ; ASCII ";" 0x3B .db SEGM0000, SEGM0000, SEGM0100, SEGM0100 C:000304 00000404 .db SEGM0000, SEGM0100, SEGM0100, SEGM1000 C:000306 00040408 ; ASCII "<" 0x3C .db SEGM0000, SEGM0000, SEGM0010, SEGM0100 C:000308 00000204 .db SEGM1000, SEGM0100, SEGM0010, SEGM0000 C:00030A 08040200 ; ASCII "=" 0x3D .db SEGM0000, SEGM0000, SEGM0000, SEGM1110 C:00030C 0000000E .db SEGM0000, SEGM1110, SEGM0000, SEGM0000 C:00030E 000E0000 ; ASCII ">" 0x3E .db SEGM0000, SEGM0000, SEGM1000, SEGM0100 C:000310 00000804 .db SEGM0010, SEGM0100, SEGM1000, SEGM0000 C:000312 02040800 ; ASCII "?" 0x3F .db SEGM0000, SEGM1100, SEGM0010, SEGM0100 C:000314 000C0204 .db SEGM0100, SEGM0000, SEGM0100, SEGM0000 C:000316 04000400 ; ASCII "@" 0x40 .db SEGM0000, SEGM0100, SEGM1010, SEGM1110 C:000318 00040A0E .db SEGM1110, SEGM1000, SEGM0110, SEGM0000 C:00031A 0E080600 ; ASCII "A" 0x41 .db SEGM0000, SEGM0100, SEGM1010, SEGM1010 C:00031C 00040A0A .db SEGM1110, SEGM1010, SEGM1010, SEGM0000 C:00031E 0E0A0A00 ; ASCII "B" 0x42 .db SEGM0000, SEGM1100, SEGM1010, SEGM1100 C:000320 000C0A0C .db SEGM1010, SEGM1010, SEGM1100, SEGM0000 C:000322 0A0A0C00 ; ASCII "C" 0x43 .db SEGM0000, SEGM0100, SEGM1010, SEGM1000 C:000324 00040A08 .db SEGM1000, SEGM1010, SEGM0100, SEGM0000 C:000326 080A0400 ; ASCII "D" 0x44 .db SEGM0000, SEGM1100, SEGM1010, SEGM1010 C:000328 000C0A0A .db SEGM1010, SEGM1010, SEGM1100, SEGM0000 C:00032A 0A0A0C00 ; ASCII "E" 0x45 .db SEGM0000, SEGM1110, SEGM1000, SEGM1100 C:00032C 000E080C .db SEGM1000, SEGM1000, SEGM1110, SEGM0000 C:00032E 08080E00 ; ASCII "F" 0x46 .db SEGM0000, SEGM1110, SEGM1000, SEGM1000 C:000330 000E0808 .db SEGM1100, SEGM1000, SEGM1000, SEGM0000 C:000332 0C080800 ; ASCII "G" 0x47 .db SEGM0000, SEGM0100, SEGM1010, SEGM1000 C:000334 00040A08 .db SEGM1010, SEGM1010, SEGM0110, SEGM0000 C:000336 0A0A0600 ; ASCII "H" 0x48 .db SEGM0000, SEGM1010, SEGM1010, SEGM1110 C:000338 000A0A0E .db SEGM1010, SEGM1010, SEGM1010, SEGM0000 C:00033A 0A0A0A00 ; ASCII "I" 0x49 .db SEGM0000, SEGM1110, SEGM0100, SEGM0100 C:00033C 000E0404 .db SEGM0100, SEGM0100, SEGM1110, SEGM0000 C:00033E 04040E00 ; ASCII "J" 0x4A .db SEGM0000, SEGM1110, SEGM0100, SEGM0100 C:000340 000E0404 .db SEGM0100, SEGM0100, SEGM1000, SEGM0000 C:000342 04040800 ; ASCII "K" 0x4B .db SEGM0000, SEGM1010, SEGM1010, SEGM1100 C:000344 000A0A0C .db SEGM1100, SEGM1010, SEGM1010, SEGM0000 C:000346 0C0A0A00 ; ASCII "L" 0x4C .db SEGM0000, SEGM1000, SEGM1000, SEGM1000 C:000348 00080808 .db SEGM1000, SEGM1000, SEGM1110, SEGM0000 C:00034A 08080E00 ; ASCII "M" 0x4D .db SEGM0000, SEGM1010, SEGM1110, SEGM1110 C:00034C 000A0E0E .db SEGM1010, SEGM1010, SEGM1010, SEGM0000 C:00034E 0A0A0A00 ; ASCII "N" 0x4E .db SEGM0000, SEGM1110, SEGM1010, SEGM1010 C:000350 000E0A0A .db SEGM1010, SEGM1010, SEGM1010, SEGM0000 C:000352 0A0A0A00 ; ASCII "O" 0x4F .db SEGM0000, SEGM0100, SEGM1010, SEGM1010 C:000354 00040A0A .db SEGM1010, SEGM1010, SEGM0100, SEGM0000 C:000356 0A0A0400 ; ASCII "P" 0x50 .db SEGM0000, SEGM1100, SEGM1010, SEGM1010 C:000358 000C0A0A .db SEGM1100, SEGM1000, SEGM1000, SEGM0000 C:00035A 0C080800 ; ASCII "Q" 0x51 .db SEGM0000, SEGM0100, SEGM1010, SEGM1010 C:00035C 00040A0A .db SEGM1010, SEGM1110, SEGM0110, SEGM0000 C:00035E 0A0E0600 ; ASCII "R" 0x52 .db SEGM0000, SEGM1100, SEGM1010, SEGM1010 C:000360 000C0A0A .db SEGM1100, SEGM1100, SEGM1010, SEGM0000 C:000362 0C0C0A00 ; ASCII "S" 0x53 .db SEGM0000, SEGM0110, SEGM1000, SEGM0100 C:000364 00060804 .db SEGM0010, SEGM0010, SEGM1100, SEGM0000 C:000366 02020C00 ; ASCII "T" 0x54 .db SEGM0000, SEGM1110, SEGM0100, SEGM0100 C:000368 000E0404 .db SEGM0100, SEGM0100, SEGM0100, SEGM0000 C:00036A 04040400 ; ASCII "U" 0x55 .db SEGM0000, SEGM1010, SEGM1010, SEGM1010 C:00036C 000A0A0A .db SEGM1010, SEGM1010, SEGM0100, SEGM0000 C:00036E 0A0A0400 ; ASCII "V" 0x56 .db SEGM0000, SEGM1010, SEGM1010, SEGM1010 C:000370 000A0A0A .db SEGM1010, SEGM0100, SEGM0100, SEGM0000 C:000372 0A040400 ; ASCII "W" 0x57 .db SEGM0000, SEGM1010, SEGM1010, SEGM1010 C:000374 000A0A0A .db SEGM1110, SEGM1110, SEGM1010, SEGM0000 C:000376 0E0E0A00 ; ASCII "X" 0x58 .db SEGM0000, SEGM1010, SEGM1010, SEGM0100 C:000378 000A0A04 .db SEGM0100, SEGM1010, SEGM1010, SEGM0000 C:00037A 040A0A00 ; ASCII "Y" 0x59 .db SEGM0000, SEGM1010, SEGM1010, SEGM1010 C:00037C 000A0A0A .db SEGM0100, SEGM0100, SEGM0100, SEGM0000 C:00037E 04040400 ; ASCII "Z" 0x5A .db SEGM0000, SEGM1110, SEGM0010, SEGM0100 C:000380 000E0204 .db SEGM0100, SEGM1000, SEGM1110, SEGM0000 C:000382 04080E00 ; ASCII "[" 0x5B .db SEGM0000, SEGM0110, SEGM0100, SEGM0100 C:000384 00060404 .db SEGM0100, SEGM0100, SEGM0110, SEGM0000 C:000386 04040600 ; ASCII "" 0x5C .db SEGM0000, SEGM1000, SEGM1000, SEGM0100 C:000388 00080804 .db SEGM0100, SEGM0010, SEGM0010, SEGM0000 C:00038A 04020200 ; ASCII "]" 0x5D .db SEGM0000, SEGM1100, SEGM0100, SEGM0100 C:00038C 000C0404 .db SEGM0100, SEGM0100, SEGM1100, SEGM0000 C:00038E 04040C00 ; ASCII "^" 0x5E .db SEGM0000, SEGM0100, SEGM0100, SEGM1010 C:000390 0004040A .db SEGM0000, SEGM0000, SEGM0000, SEGM0000 C:000392 00000000 ; ASCII "_" 0x5F .db SEGM0000, SEGM0000, SEGM0000, SEGM0000 C:000394 00000000 .db SEGM0000, SEGM0000, SEGM0000, SEGM1110 C:000396 0000000E ; ASCII "`" 0x60 .db SEGM0000, SEGM0100, SEGM0010, SEGM0000 C:000398 00040200 .db SEGM0000, SEGM0000, SEGM0000, SEGM0000 C:00039A 00000000 ; ASCII "a" 0x61 .db SEGM0000, SEGM0000, SEGM0000, SEGM0110 C:00039C 00000006 .db SEGM1010, SEGM1010, SEGM0110, SEGM0000 C:00039E 0A0A0600 ; ASCII "b" 0x62 .db SEGM0000, SEGM1000, SEGM1000, SEGM1100 C:0003A0 0008080C .db SEGM1010, SEGM1010, SEGM1100, SEGM0000 C:0003A2 0A0A0C00 ; ASCII "c" 0x63 .db SEGM0000, SEGM0000, SEGM0000, SEGM0110 C:0003A4 00000006 .db SEGM1000, SEGM1000, SEGM0110, SEGM0000 C:0003A6 08080600 ; ASCII "d" 0x64 .db SEGM0000, SEGM0010, SEGM0010, SEGM0110 C:0003A8 00020206 .db SEGM1010, SEGM1010, SEGM0110, SEGM0000 C:0003AA 0A0A0600 ; ASCII "e" 0x65 .db SEGM0000, SEGM0000, SEGM0000, SEGM0100 C:0003AC 00000004 .db SEGM1010, SEGM1100, SEGM0110, SEGM0000 C:0003AE 0A0C0600 ; ASCII "f" 0x66 .db SEGM0000, SEGM0010, SEGM0100, SEGM1110 C:0003B0 0002040E .db SEGM0100, SEGM0100, SEGM0100, SEGM0000 C:0003B2 04040400 ; ASCII "g" 0x67 .db SEGM0000, SEGM0000, SEGM0000, SEGM0110 C:0003B4 00000006 .db SEGM1010, SEGM0110, SEGM0010, SEGM1100 C:0003B6 0A06020C ; ASCII "h" 0x68 .db SEGM0000, SEGM1000, SEGM1000, SEGM1100 C:0003B8 0008080C .db SEGM1010, SEGM1010, SEGM1010, SEGM0000 C:0003BA 0A0A0A00 ; ASCII "i" 0x69 .db SEGM0000, SEGM0100, SEGM0000, SEGM1100 C:0003BC 0004000C .db SEGM0100, SEGM0100, SEGM1110, SEGM0000 C:0003BE 04040E00 ; ASCII "j" 0x6A .db SEGM0000, SEGM0100, SEGM0000, SEGM1100 C:0003C0 0004000C .db SEGM0100, SEGM0100, SEGM0100, SEGM1000 C:0003C2 04040408 ; ASCII "k" 0x6B .db SEGM0000, SEGM1000, SEGM1000, SEGM1010 C:0003C4 0008080A .db SEGM1100, SEGM1100, SEGM1010, SEGM0000 C:0003C6 0C0C0A00 ; ASCII "l" 0x6C .db SEGM0000, SEGM1100, SEGM0100, SEGM0100 C:0003C8 000C0404 .db SEGM0100, SEGM0100, SEGM1110, SEGM0000 C:0003CA 04040E00 ; ASCII "m" 0x6D .db SEGM0000, SEGM0000, SEGM0000, SEGM1100 C:0003CC 0000000C .db SEGM1110, SEGM1110, SEGM1110, SEGM0000 C:0003CE 0E0E0E00 ; ASCII "n" 0x6E .db SEGM0000, SEGM0000, SEGM0000, SEGM1100 C:0003D0 0000000C .db SEGM1010, SEGM1010, SEGM1010, SEGM0000 C:0003D2 0A0A0A00 ; ASCII "o" 0x6F .db SEGM0000, SEGM0000, SEGM0000, SEGM0100 C:0003D4 00000004 .db SEGM1010, SEGM1010, SEGM0100, SEGM0000 C:0003D6 0A0A0400 ; ASCII "p" 0x70 .db SEGM0000, SEGM0000, SEGM0000, SEGM1100 C:0003D8 0000000C .db SEGM1010, SEGM1100, SEGM1000, SEGM1000 C:0003DA 0A0C0808 ; ASCII "q" 0x71 .db SEGM0000, SEGM0000, SEGM0000, SEGM0110 C:0003DC 00000006 .db SEGM1010, SEGM0110, SEGM0010, SEGM0010 C:0003DE 0A060202 ; ASCII "r" 0x72 .db SEGM0000, SEGM0000, SEGM0000, SEGM1100 C:0003E0 0000000C .db SEGM1010, SEGM1000, SEGM1000, SEGM0000 C:0003E2 0A080800 ; ASCII "s" 0x73 .db SEGM0000, SEGM0000, SEGM0000, SEGM0110 C:0003E4 00000006 .db SEGM1000, SEGM0110, SEGM1100, SEGM0000 C:0003E6 08060C00 ; ASCII "t" 0x74 .db SEGM0000, SEGM0100, SEGM0100, SEGM1110 C:0003E8 0004040E .db SEGM0100, SEGM0100, SEGM0010, SEGM0000 C:0003EA 04040200 ; ASCII "u" 0x75 .db SEGM0000, SEGM0000, SEGM0000, SEGM1010 C:0003EC 0000000A .db SEGM1010, SEGM1010, SEGM0110, SEGM0000 C:0003EE 0A0A0600 ; ASCII "v" 0x76 .db SEGM0000, SEGM0000, SEGM0000, SEGM1010 C:0003F0 0000000A .db SEGM1010, SEGM0100, SEGM0100, SEGM0000 C:0003F2 0A040400 ; ASCII "w" 0x77 .db SEGM0000, SEGM0000, SEGM0000, SEGM1010 C:0003F4 0000000A .db SEGM1010, SEGM1110, SEGM1110, SEGM0000 C:0003F6 0A0E0E00 ; ASCII "x" 0x78 .db SEGM0000, SEGM0000, SEGM0000, SEGM1010 C:0003F8 0000000A .db SEGM0100, SEGM0100, SEGM1010, SEGM0000 C:0003FA 04040A00 ; ASCII "y" 0x79 .db SEGM0000, SEGM0000, SEGM0000, SEGM1010 C:0003FC 0000000A .db SEGM1010, SEGM0110, SEGM0010, SEGM1100 C:0003FE 0A06020C ; ASCII "z" 0x7A .db SEGM0000, SEGM0000, SEGM0000, SEGM1110 C:000400 0000000E .db SEGM0100, SEGM1000, SEGM1110, SEGM0000 C:000402 04080E00 ; ASCII "{" 0x7B .db SEGM0000, SEGM0010, SEGM0100, SEGM0100 C:000404 00020404 .db SEGM1000, SEGM0100, SEGM0100, SEGM0010 C:000406 08040402 ; ASCII "|" 0x7C .db SEGM0000, SEGM0100, SEGM0100, SEGM0100 C:000408 00040404 .db SEGM0100, SEGM0100, SEGM0100, SEGM0000 C:00040A 04040400 ; ASCII "}" 0x7D .db SEGM0000, SEGM1000, SEGM0100, SEGM0100 C:00040C 00080404 .db SEGM0010, SEGM0100, SEGM0100, SEGM1000 C:00040E 02040408 ; ASCII "~" 0x7E .db SEGM0000, SEGM0110, SEGM1100, SEGM0000 C:000410 00060C00 .db SEGM0000, SEGM0000, SEGM0000, SEGM0000 C:000412 00000000 SYSABORT: .equ ABORT = 0x7F ; system abort 0x7F .db SEGM0000, SEGM0000, SEGM0000, SEGM0000 C:000414 00000000 .db SEGM0000, SEGM0000, SEGM0000, SEGM0000 C:000416 00000000 FRAMESQUARE: .equ FS0000 = 0x80 .equ FS0001 = 0x81 .equ FS0010 = 0x82 .equ FS0011 = 0x83 .equ FS0100 = 0x84 .equ FS0101 = 0x85 .equ FS0110 = 0x86 .equ FS0111 = 0x87 .equ FS1000 = 0x88 .equ FS1001 = 0x89 .equ FS1010 = 0x8A .equ FS1011 = 0x8B .equ FS1100 = 0x8C .equ FS1101 = 0x8D .equ FS1110 = 0x8E .equ FS1111 = 0x8F ; frame square element 0/00/0 0x80 .db SEGM0000, SEGM0000, SEGM0000, SEGM0100 C:000418 00000004 .db SEGM0100, SEGM0000, SEGM0000, SEGM0000 C:00041A 04000000 ; frame square element 0/00/1 0x81 .db SEGM0000, SEGM0000, SEGM0000, SEGM0100 C:00041C 00000004 .db SEGM0100, SEGM0100, SEGM0100, SEGM0100 C:00041E 04040404 ; frame square element 0/01/0 0x82 .db SEGM0000, SEGM0000, SEGM0000, SEGM0111 C:000420 00000007 .db SEGM0111, SEGM0000, SEGM0000, SEGM0000 C:000422 07000000 ; frame square element 0/01/1 0x83 .db SEGM0000, SEGM0000, SEGM0000, SEGM0111 C:000424 00000007 .db SEGM0111, SEGM0100, SEGM0100, SEGM0100 C:000426 07040404 ; frame square element 0/10/0 0x84 .db SEGM0000, SEGM0000, SEGM0000, SEGM1100 C:000428 0000000C .db SEGM1100, SEGM0000, SEGM0000, SEGM0000 C:00042A 0C000000 ; frame square element 0/10/1 0x85 .db SEGM0000, SEGM0000, SEGM0000, SEGM1100 C:00042C 0000000C .db SEGM1100, SEGM0100, SEGM0100, SEGM0100 C:00042E 0C040404 ; frame square element 0/11/0 0x86 .db SEGM0000, SEGM0000, SEGM0000, SEGM1111 C:000430 0000000F .db SEGM1111, SEGM0000, SEGM0000, SEGM0000 C:000432 0F000000 ; frame square element 0/11/1 0x87 .db SEGM0000, SEGM0000, SEGM0000, SEGM1111 C:000434 0000000F .db SEGM1111, SEGM0100, SEGM0100, SEGM0100 C:000436 0F040404 ; frame square element 1/00/0 0x88 .db SEGM0100, SEGM0100, SEGM0100, SEGM0100 C:000438 04040404 .db SEGM0100, SEGM0000, SEGM0000, SEGM0000 C:00043A 04000000 ; frame square element 1/00/1 0x89 .db SEGM0100, SEGM0100, SEGM0100, SEGM0100 C:00043C 04040404 .db SEGM0100, SEGM0100, SEGM0100, SEGM0100 C:00043E 04040404 ; frame square element 1/01/0 0x8A .db SEGM0100, SEGM0100, SEGM0100, SEGM0111 C:000440 04040407 .db SEGM0111, SEGM0000, SEGM0000, SEGM0000 C:000442 07000000 ; frame square element 1/01/1 0x8B .db SEGM0100, SEGM0100, SEGM0100, SEGM0111 C:000444 04040407 .db SEGM0111, SEGM0100, SEGM0100, SEGM0100 C:000446 07040404 ; frame square element 1/10/0 0x8C .db SEGM0100, SEGM0100, SEGM0100, SEGM1100 C:000448 0404040C .db SEGM1100, SEGM0000, SEGM0000, SEGM0000 C:00044A 0C000000 ; frame square element 1/10/1 0x8D .db SEGM0100, SEGM0100, SEGM0100, SEGM1100 C:00044C 0404040C .db SEGM1100, SEGM0100, SEGM0100, SEGM0100 C:00044E 0C040404 ; frame square element 1/11/0 0x8E .db SEGM0100, SEGM0100, SEGM0100, SEGM1111 C:000450 0404040F .db SEGM1111, SEGM0000, SEGM0000, SEGM0000 C:000452 0F000000 ; frame square element 1/11/1 0x8F .db SEGM0100, SEGM0100, SEGM0100, SEGM1111 C:000454 0404040F .db SEGM1111, SEGM0100, SEGM0100, SEGM0100 C:000456 0F040404 FRAMEROUND: .equ FR0000 = 0x90 .equ FR0001 = 0x91 .equ FR0010 = 0x92 .equ FR0011 = 0x93 .equ FR0100 = 0x94 .equ FR0101 = 0x95 .equ FR0110 = 0x96 .equ FR0111 = 0x97 .equ FR1000 = 0x98 .equ FR1001 = 0x99 .equ FR1010 = 0x9A .equ FR1011 = 0x9B .equ FR1100 = 0x9C .equ FR1101 = 0x9D .equ FR1110 = 0x9E .equ FR1111 = 0x9F ; frame round element 0/00/0 0x90 .db SEGM0000, SEGM0000, SEGM0000, SEGM0000 C:000458 00000000 .db SEGM0000, SEGM0000, SEGM0000, SEGM0000 C:00045A 00000000 ; frame round element 0/00/1 0x91 .db SEGM0000, SEGM0000, SEGM0000, SEGM0000 C:00045C 00000000 .db SEGM0000, SEGM0100, SEGM0100, SEGM0100 C:00045E 00040404 ; frame round element 0/01/0 0x92 .db SEGM0000, SEGM0000, SEGM0000, SEGM0011 C:000460 00000003 .db SEGM0011, SEGM0000, SEGM0000, SEGM0000 C:000462 03000000 ; frame round element 0/01/1 0x93 .db SEGM0000, SEGM0000, SEGM0000, SEGM0001 C:000464 00000001 .db SEGM0011, SEGM0010, SEGM0100, SEGM0100 C:000466 03020404 ; frame round element 0/10/0 0x94 .db SEGM0000, SEGM0000, SEGM0000, SEGM1000 C:000468 00000008 .db SEGM1000, SEGM0000, SEGM0000, SEGM0000 C:00046A 08000000 ; frame round element 0/10/1 0x95 .db SEGM0000, SEGM0000, SEGM0000, SEGM0000 C:00046C 00000000 .db SEGM1000, SEGM1000, SEGM0100, SEGM0100 C:00046E 08080404 ; frame round element 0/11/0 0x96 .db SEGM0000, SEGM0000, SEGM0000, SEGM1111 C:000470 0000000F .db SEGM1111, SEGM0000, SEGM0000, SEGM0000 C:000472 0F000000 ; frame round element 0/11/1 0x97 .db SEGM0000, SEGM0000, SEGM0000, SEGM0001 C:000474 00000001 .db SEGM1011, SEGM1010, SEGM0100, SEGM0100 C:000476 0B0A0404 ; frame round element 1/00/0 0x98 .db SEGM0100, SEGM0100, SEGM0100, SEGM0000 C:000478 04040400 .db SEGM0000, SEGM0000, SEGM0000, SEGM0000 C:00047A 00000000 ; frame round element 1/00/1 0x99 .db SEGM0100, SEGM0100, SEGM0100, SEGM0100 C:00047C 04040404 .db SEGM0100, SEGM0100, SEGM0100, SEGM0100 C:00047E 04040404 ; frame round element 1/01/0 0x9A .db SEGM0100, SEGM0100, SEGM0010, SEGM0011 C:000480 04040203 .db SEGM0001, SEGM0000, SEGM0000, SEGM0000 C:000482 01000000 ; frame round element 1/01/1 0x9B .db SEGM0100, SEGM0100, SEGM0010, SEGM0011 C:000484 04040203 .db SEGM0011, SEGM0010, SEGM0100, SEGM0100 C:000486 03020404 ; frame round element 1/10/0 0x9C .db SEGM0100, SEGM0100, SEGM1000, SEGM1000 C:000488 04040808 .db SEGM0000, SEGM0000, SEGM0000, SEGM0000 C:00048A 00000000 ; frame round element 1/10/1 0x9D .db SEGM0100, SEGM0100, SEGM1000, SEGM1000 C:00048C 04040808 .db SEGM1000, SEGM1000, SEGM0100, SEGM0100 C:00048E 08080404 ; frame round element 1/11/0 0x9E .db SEGM0100, SEGM0100, SEGM1010, SEGM1011 C:000490 04040A0B .db SEGM0001, SEGM0000, SEGM0000, SEGM0000 C:000492 01000000 ; frame round element 1/11/1 0x9F .db SEGM0100, SEGM0100, SEGM1010, SEGM1011 C:000494 04040A0B .db SEGM1011, SEGM1010, SEGM0100, SEGM0100 C:000496 0B0A0404 BARGRAPHIC: .equ BR00 = 0xA0 .equ BR01 = 0xA1 .equ BR02 = 0xA2 .equ BR03 = 0xA3 .equ BR04 = 0xA4 .equ BR05 = 0xA5 .equ BR06 = 0xA6 .equ BR07 = 0xA7 .equ BR08 = 0xA8 .equ BR18 = 0xA9 .equ BR28 = 0xAA .equ BR38 = 0xAB .equ BR48 = 0xAC .equ BR58 = 0xAD .equ BR68 = 0xAE .equ BR78 = 0xAF ; bar graph 0-0 0xA0 .db SEGM0000, SEGM0000, SEGM0000, SEGM0000 C:000498 00000000 .db SEGM0000, SEGM0000, SEGM0000, SEGM0000 C:00049A 00000000 ; bar graph 0-1 0xA1 .db SEGM0000, SEGM0000, SEGM0000, SEGM0000 C:00049C 00000000 .db SEGM0000, SEGM0000, SEGM0000, SEGM1111 C:00049E 0000000F ; bar graph 0-2 0xA2 .db SEGM0000, SEGM0000, SEGM0000, SEGM0000 C:0004A0 00000000 .db SEGM0000, SEGM0000, SEGM1111, SEGM1111 C:0004A2 00000F0F ; bar graph 0-3 0xA3 .db SEGM0000, SEGM0000, SEGM0000, SEGM0000 C:0004A4 00000000 .db SEGM0000, SEGM1111, SEGM1111, SEGM1111 C:0004A6 000F0F0F ; bar graph 0-4 0xA4 .db SEGM0000, SEGM0000, SEGM0000, SEGM0000 C:0004A8 00000000 .db SEGM1111, SEGM1111, SEGM1111, SEGM1111 C:0004AA 0F0F0F0F ; bar graph 0-5 0xA5 .db SEGM0000, SEGM0000, SEGM0000, SEGM1111 C:0004AC 0000000F .db SEGM1111, SEGM1111, SEGM1111, SEGM1111 C:0004AE 0F0F0F0F ; bar graph 0-6 0xA6 .db SEGM0000, SEGM0000, SEGM1111, SEGM1111 C:0004B0 00000F0F .db SEGM1111, SEGM1111, SEGM1111, SEGM1111 C:0004B2 0F0F0F0F ; bar graph 0-7 0xA7 .db SEGM0000, SEGM1111, SEGM1111, SEGM1111 C:0004B4 000F0F0F .db SEGM1111, SEGM1111, SEGM1111, SEGM1111 C:0004B6 0F0F0F0F ; bar graph 0-8 0xA8 .db SEGM1111, SEGM1111, SEGM1111, SEGM1111 C:0004B8 0F0F0F0F .db SEGM1111, SEGM1111, SEGM1111, SEGM1111 C:0004BA 0F0F0F0F ; bar graph 1-8 0xA9 .db SEGM1111, SEGM1111, SEGM1111, SEGM1111 C:0004BC 0F0F0F0F .db SEGM1111, SEGM1111, SEGM1111, SEGM0000 C:0004BE 0F0F0F00 ; bar graph 2-8 0xAA .db SEGM1111, SEGM1111, SEGM1111, SEGM1111 C:0004C0 0F0F0F0F .db SEGM1111, SEGM1111, SEGM0000, SEGM0000 C:0004C2 0F0F0000 ; bar graph 3-8 0xAB .db SEGM1111, SEGM1111, SEGM1111, SEGM1111 C:0004C4 0F0F0F0F .db SEGM1111, SEGM0000, SEGM0000, SEGM0000 C:0004C6 0F000000 ; bar graph 4-8 0xAC .db SEGM1111, SEGM1111, SEGM1111, SEGM1111 C:0004C8 0F0F0F0F .db SEGM0000, SEGM0000, SEGM0000, SEGM0000 C:0004CA 00000000 ; bar graph 5-8 0xAD .db SEGM1111, SEGM1111, SEGM1111, SEGM0000 C:0004CC 0F0F0F00 .db SEGM0000, SEGM0000, SEGM0000, SEGM0000 C:0004CE 00000000 ; bar graph 6-8 0xAE .db SEGM1111, SEGM1111, SEGM0000, SEGM0000 C:0004D0 0F0F0000 .db SEGM0000, SEGM0000, SEGM0000, SEGM0000 C:0004D2 00000000 ; bar graph 7-8 0xAF .db SEGM1111, SEGM0000, SEGM0000, SEGM0000 C:0004D4 0F000000 .db SEGM0000, SEGM0000, SEGM0000, SEGM0000 C:0004D6 00000000 LINECORNER: .equ HL0 = 0xB0 .equ HL1 = 0xB1 .equ HL2 = 0xB2 .equ HL3 = 0xB3 .equ VL0 = 0xB4 .equ VL1 = 0xB5 .equ VL2 = 0xB6 .equ VL3 = 0xB7 .equ CRTL = 0xB8 .equ CRTR = 0xB9 .equ CRBL = 0xBA .equ CRBR = 0xBB .equ TRTL = 0xBC .equ TRTR = 0xBD .equ TRBL = 0xBE .equ TRBR = 0xBF ; horizontal line 0 0xB0 .db SEGM1111, SEGM1111, SEGM0000, SEGM0000 C:0004D8 0F0F0000 .db SEGM0000, SEGM0000, SEGM0000, SEGM0000 C:0004DA 00000000 ; horizontal line 1 0xB1 .db SEGM0000, SEGM0000, SEGM1111, SEGM1111 C:0004DC 00000F0F .db SEGM0000, SEGM0000, SEGM0000, SEGM0000 C:0004DE 00000000 ; horizontal line 2 0xB2 .db SEGM0000, SEGM0000, SEGM0000, SEGM0000 C:0004E0 00000000 .db SEGM1111, SEGM1111, SEGM0000, SEGM0000 C:0004E2 0F0F0000 ; horizontal line 3 0xB3 .db SEGM0000, SEGM0000, SEGM0000, SEGM0000 C:0004E4 00000000 .db SEGM0000, SEGM0000, SEGM1111, SEGM1111 C:0004E6 00000F0F ; vertical line 0 0xB4 .db SEGM1000, SEGM1000, SEGM1000, SEGM1000 C:0004E8 08080808 .db SEGM1000, SEGM1000, SEGM1000, SEGM1000 C:0004EA 08080808 ; vertical line 1 0xB5 .db SEGM0100, SEGM0100, SEGM0100, SEGM0100 C:0004EC 04040404 .db SEGM0100, SEGM0100, SEGM0100, SEGM0100 C:0004EE 04040404 ; vertical line 2 0xB6 .db SEGM0010, SEGM0010, SEGM0010, SEGM0010 C:0004F0 02020202 .db SEGM0010, SEGM0010, SEGM0010, SEGM0010 C:0004F2 02020202 ; vertical line 3 0xB7 .db SEGM0001, SEGM0001, SEGM0001, SEGM0001 C:0004F4 01010101 .db SEGM0001, SEGM0001, SEGM0001, SEGM0001 C:0004F6 01010101 ; corner top/left 0xB8 .db SEGM1111, SEGM1111, SEGM1000, SEGM1000 C:0004F8 0F0F0808 .db SEGM1000, SEGM1000, SEGM1000, SEGM1000 C:0004FA 08080808 ; corner top/right 0xB9 .db SEGM1111, SEGM1111, SEGM0001, SEGM0001 C:0004FC 0F0F0101 .db SEGM0001, SEGM0001, SEGM0001, SEGM0001 C:0004FE 01010101 ; corner bottom/left 0xBA .db SEGM1000, SEGM1000, SEGM1000, SEGM1000 C:000500 08080808 .db SEGM1000, SEGM1000, SEGM1111, SEGM1111 C:000502 08080F0F ; corner bottom/right 0xBB .db SEGM0001, SEGM0001, SEGM0001, SEGM0001 C:000504 01010101 .db SEGM0001, SEGM0001, SEGM1111, SEGM1111 C:000506 01010F0F ; triangle top/left 0xBC .db SEGM1111, SEGM1111, SEGM1110, SEGM1110 C:000508 0F0F0E0E .db SEGM1100, SEGM1100, SEGM1000, SEGM1000 C:00050A 0C0C0808 ; triangle top/right 0xBD .db SEGM1111, SEGM1111, SEGM0111, SEGM0111 C:00050C 0F0F0707 .db SEGM0011, SEGM0011, SEGM0001, SEGM0001 C:00050E 03030101 ; triangle bottom/left 0xBE .db SEGM1000, SEGM1000, SEGM1100, SEGM1100 C:000510 08080C0C .db SEGM1110, SEGM1110, SEGM1111, SEGM1111 C:000512 0E0E0F0F ; triangle bottom/right 0xBF .db SEGM0001, SEGM0001, SEGM0011, SEGM0011 C:000514 01010303 .db SEGM0111, SEGM0111, SEGM1111, SEGM1111 C:000516 07070F0F ; --- load single char of font from Flash into SRAM ; parameters: ZH:ZL: character definition in Flash, gets incremented ; T2: character position to overwrite in all SRAM segments FOLDCHAR: C:000518 772f andi T2,FOINDEXMASK ; prevent outindexing of the SRAM font tables ; prevent destroying of abort framing by user errors C:000519 372f cpi T2,ABORT ; char - ABORT (abort pseudo-char, do not overwrite) C:00051a f409 brne FOLDNOTABORT ; <>, is ok C:00051b 9508 ret ; =, do nothing FOLDNOTABORT: ; each character in ROM/Flash font has ROWSEGMENTS segment indexes ; ZH:ZL already points to the first of these ; each segment in SRAM font has an table of FOCHARS segment indexes C:00051c e8a0 ldi XL,low(FONTRAM) ; begin of table of all first segments C:00051d e0b0 ldi XH,high(FONTRAM) C:00051e 0fa2 add XL,T2 ; add the characters offset into this segment table ; SRAM font is alligned, can never produce an carry C:00051f e018 ldi T1,ROWSEGMENTS ; for segment = ROWSEGMENTS..1 FOLDLOOP: C:000520 9105 lpm T0,Z+ ; get segment from Flash, are sequential for char C:000521 940e 020a call SEGMCONV ; convert pixel value to low() of routine address C:000523 930c st X,T0 ; write segment to SRAM, not sequential, no X+ C:000524 58a0 subi XL,low(-FOCHARS) ; goto next segments table, same position, +FOCHARS C:000525 4fbf sbci XH,high(-FOCHARS) ; this gives distributing of segments over tables C:000526 951a dec T1 ; next segment C:000527 f7c1 brne FOLDLOOP C:000528 9508 ret ; --- load default font from Flash into SRAM FOINIT: C:000529 e3e0 ldi ZL,low(FONTROM*2) ; begin of font data "file" in Flash C:00052a e0f4 ldi ZH,high(FONTROM*2) ; *2 because of lpm word->byte addresses ; so font must be in first 64kbyte|32kword ; default font is first FOCHARS of defined characters C:00052b e020 ldi T2,0 ; for char = 0..FOCHARS-1 FOINLOOP: C:00052c dfeb rcall FOLDCHAR ; load this char T2 from Flash to SRAM C:00052d 9523 inc T2 ; next index C:00052e 3820 cpi T2,FOCHARS C:00052f f7e1 brne FOINLOOP C:000530 efaf ldi XL,low(FONTRAM+ABORT) ; set segments for abort pseudo-character C:000531 e0b0 ldi XH,high(FONTRAM+ABORT) ; can not use FOCHAR because framing protect C:000532 e018 ldi T1,ROWSEGMENTS FOABLOOP: C:000533 e900 ldi T0,low(DRSEGMABRT) ; allways must be DRSEGMABRT segment, not from font ; may be after all missing or missplaced there C:000534 930c st X,T0 C:000535 58a0 subi XL,low(-FOCHARS) C:000536 4fbf sbci XH,high(-FOCHARS) C:000537 951a dec T1 C:000538 f7d1 brne FOABLOOP C:000539 9508 ret ; ------ frame buffer handling ; --- write colour into frame buffer ; parameters: XH:XL: address where in frame buffer, gets incremented ; only use when at begin of row ; T0: colour code, gets truncated to black(0x00)..white(0x3F) FBWCOLOUR: C:00053a 730f andi T0,VGAWHITE ; prevent false sync signals from user errors ; XH:XL set by caller, contains address in frame buffer C:00053b 930d st X+,T0 ; place this colour C:00053c 9508 ret ; --- read colour from frame buffer ; parameters: XH:XL: address where in frame buffer, gets incremented ; only use when at begin of row ; returns: T0: colour code FBRCOLOUR: ; XH:XL set by caller, contains address in frame buffer C:00053d 910d ld T0,X+ ; extract this colour C:00053e 9508 ret ; --- write character into frame buffer ; parameters: XH:XL: address where in frame buffer, gets incremented ; only use when inside an row ; T0: character code FBWCHAR: C:00053f 770f andi T0,FOINDEXMASK ; prevent outindexing of font tables ; prevent insertion of false abort from user errors C:000540 370f cpi T0,ABORT ; char - ABORT (abort pseudo-char, not in text) C:000541 f409 brne FBWCNOTABORT ; <>, is ok C:000542 e20e ldi T0,0x2E ; =, replace with ASCII "." to show fixup FBWCNOTABORT: ; XH:XL set by caller, contains address in frame buffer C:000543 930d st X+,T0 ; place this char C:000544 9508 ret ; --- read character from frame buffer ; parameters: XH:XL: address where in frame buffer, gets incremented ; only use when inside an row ; returns: T0: character code FBRCHAR: ; XH:XL set by caller, contains address in frame buffer C:000545 910d ld T0,X+ ; extract this character C:000546 9508 ret ; --- write immediate string into frame buffer ; parameters: TOS (old PC): address of string (in Flash!) ; format of constant: .dw length, .db data ; data in .db must allways be pairs ; if not, add an 0 filler byte ; no not include in length count, else gets drawn ; these are assembled-in, after call|rcall FBWSTRI ; XH:XL: address where in frame buffer, gets incremented ; write only while inside current row, only to end of row FBWSTRI: ; next address in calling program, begin of constant ; must use ZH:ZL because of lpm instr C:000547 91ff pop ZH ; call|rcall stores low first/top, big endian(!) C:000548 91ef pop ZL ; so read low as last/top C:000549 0fee lsl ZL ; correct address for prog word vs lpm byte addressing C:00054a 1fff rol ZH ; this will fail on chips larger 64kByte/32kWord C:00054b 939f push DH ; source length, not YH:YL, as not an address C:00054c 938f push DL C:00054d 9185 lpm DL,Z+ ; length of string constant, from program C:00054e 9195 lpm DH,Z+ ; DH:DL set above ; for char = constantlen..1 FBWSLOOP: ; XH:XL set by caller, contains address in frame buffer C:00054f 910c ld T0,X ; check for row end, look at frame buffer index value C:000550 370f cpi T0,ABORT ; index - ABORT (abort pseudo-char, do not overwrite) C:000551 f061 breq FBDSREST ; =, is end of row, abort copying string, drop rest C:000552 9105 lpm T0,Z+ ; copy string data, from program ... C:000553 dfeb rcall FBWCHAR ; ... to frame buffer, breaks T0, does X+ C:000554 9701 sbiw DH:DL,1 ; next char C:000555 f7c9 brne FBWSLOOP FBDSDONE: C:000556 918f pop DL C:000557 919f pop DH C:000558 fde0 sbrc ZL,0 ; first unused byte is in 2nd half of an word ? C:000559 9631 adiw ZH:ZL,1 ; yes, jump over added 2nd halfword filler byte C:00055a 95f6 lsr ZH ; undo prog word vs lpm byte address correction C:00055b 95e7 ror ZL ; new address in calling program, instr after constant C:00055c 9409 ijmp ; ijmp is faster than push ZL push ZH ret ; --- drop immediate string, instead of into frame buffer ; DH:DL still set ; for char = current..1 FBDSLOOP: C:00055d 9105 lpm T0,Z+ ; step over string data, in program, no copy/store FBDSREST: C:00055e 9701 sbiw DH:DL,1 ; next char C:00055f f7e9 brne FBDSLOOP C:000560 cff5 rjmp FBDSDONE ; --- initialise frame buffer FBINIT: C:000561 933f push S0 C:000562 934f push S1 C:000563 e8a0 ldi XL,low(FBUF) ; begin of frame buffer C:000564 e0b4 ldi XH,high(FBUF) C:000565 e137 ldi S0,FBROWS ; for row = FBROWS..1 FBRLOOP: ; set default colours for each row C:000566 e003 ldi T0,0x03 ; background, blue C:000567 dfd2 rcall FBWCOLOUR ; breaks T0, does X+ ;ldi T0,0x0F ; foreground, cyan ;ldi T0,0x1F ; foreground, cyan + 1/3 red C:000568 e10b ldi T0,0x1B ; foreground, cyan + 1/3 red - 1/3 green ;ldi T0,0x2B ; foreground, white - 1/3 red - 1/3 green C:000569 dfd0 rcall FBWCOLOUR C:00056a e10f ldi T0,0x1F ; alt 1 emphasized foregr, cyan + 1/3 red C:00056b dfce rcall FBWCOLOUR ;ldi T0,0x3F ; alt 2 strong foregr, white ;ldi T0,0x3C ; alt 2 strong foregr, yellow C:00056c e20f ldi T0,0x2F ; alt 2 strong foregr, cyan + 2/3 red, white - 1/3 red C:00056d dfcc rcall FBWCOLOUR C:00056e e107 ldi T0,0x17 ; alt 3 marked backgr, blue + 1/3 red and green C:00056f dfca rcall FBWCOLOUR ; blank out and delimit the frame buffer C:000570 e244 ldi S1,FBCOLS ; for column = FBCOLS..1 FBCLOOP: C:000571 e20e ldi T0,0x2E ; fill unused space with ASCII "." C:000572 dfcc rcall FBWCHAR ; breaks T0 (requiring re-load), does X+ C:000573 954a dec S1 ; next column C:000574 f7e1 brne FBCLOOP C:000575 e70f ldi T0,ABORT ; abort pseudo-char, not in lines, frame at row end C:000576 930d st X+,T0 ; can not use FBWCHAR because framing invalid char C:000577 953a dec S0 ; next row C:000578 f769 brne FBRLOOP C:000579 914f pop S1 C:00057a 913f pop S0 C:00057b 9508 ret ; ------ timing delay helper ; --- wait a while doing nothing, spinloop ; parameters: I0: loop count, 1..256 (actually 1..255,0 where 0=256) ; gets destroyed (decremented to 0), to avoid push/pop time ; OK, as seldom reused, often loaded, so use immediate register ; this is only ever called from drawing, is interrupt, so I0 ; timing range: (I0-1)*(1+2) + 1*(1+1) + 4 = I0*3+3 clocks ; together with needed ldi I0, and rcall WAIT 1+3+(I0*3+3) clocks ; gives min 1+3+(1*3+3)=10 clocks, for I0=1 ; gives max 1+3+(256*3+3)=774 clocks, for I0=0 (=256) WAIT: ; {n} in comments = clocks used, for time computation ; this program requires lots of exact clock counting ; single-clock miscounts produce visual artifacts! ; I0 set up by caller ; {0} for LOOP = I0..1 WAILOOP: ; nothing in loop, for highest loop resolution, only 3 clocks C:00057c 956a dec I0 ; {1} next LOOP C:00057d f7f1 brne WAILOOP ; {2|1} C:00057e 9508 ret ; {4} ; ------ handle timer interrupt driven drawing ; backgrounding drawing while blank lines are displayed ; --- interrupt service routine, push background, restore drawing state ; as far as drawing goes, this is an "return" from background T0CMPINT: ; TCNT0 now = 0, in 8 clks 1, in 16 clks 2, ... ; in 600-8 ckls 74, in 600clks again 0 ; {0..3?} last background instr jitter, if not {1} ; {4} interrupt entry|call|cli processing ; {3} interrupt vector does jmp T0CMPINT C:00057f 93f0 084c sts INTZH,ZH ; {2} save registers that are not ISR dedicated C:000581 93e0 084b sts INTZL,ZL ; {2} use sts, to reduce push and stack usage size C:000583 93d0 084a sts INTYH,YH ; {2} C:000585 93c0 0849 sts INTYL,YL ; {2} C:000587 93b0 0848 sts INTXH,XH ; {2} C:000589 93a0 0847 sts INTXL,XL ; {2} C:00058b b76f in I0,SREG ; {1} C:00058c 9360 0846 sts INTSREG,I0 ; {2} ; compensate for timer interrupt latency jitter ; basic method is to nop until 0 or 1 clock before ; timer steps, if not stepped wait 1 clock longer ; repeat entire game 8 clocks (1 timer step) later ; 3 times so that up to 3clocks correction ; as minimal instruction 1clk, maximal 4clk ; now is 22 + 0..3 clocks since TCNT0=0 C:00058e 0000 nop ; {1} ; now is 23 + 1..3 clocks since TCNT0=0 C:00058f b762 in I0,TCNT0 ; {1} if 23+0=23 still TCNT0=2 else already TCNT0=3 C:000590 3062 cpi I0,2 ; {1} if TCNT0 = 2 C:000591 f001 breq TSYNC1 ; {1|2} not delayed by background 1, delay +1 TSYNC1: ; now is 26 + 1..3 clocks since TCNT0=0 C:000592 0000 nop ; {4} C:000593 0000 nop C:000594 0000 nop C:000595 0000 nop ; now is 30 + 1..3 clocks since TCNT0=0 C:000596 b762 in I0,TCNT0 ; {1} if 30+1=31 still TCNT0=3 else already TCNT0=4 C:000597 3063 cpi I0,3 ; {1} if TCNT0 = 3 C:000598 f001 breq TSYNC12 ; {1|2} not delayed by background 1..2, delay +1 TSYNC12: ; now is 34 + 2..3 clocks since TCNT0=0 C:000599 0000 nop ; {4} C:00059a 0000 nop C:00059b 0000 nop C:00059c 0000 nop ; now is 37 + 2..3 clocks since TCNT0=0 C:00059d b762 in I0,TCNT0 ; {1} if 37+2=39 still TCNT0=4 else already TCNT0=5 C:00059e 3064 cpi I0,4 ; {1} if TCNT0 = 4 C:00059f f001 breq TSYNC123 ; {1|2} not delayed by background 1..3, delay +1 TSYNC123: ; now is 40 + 3 clocks since TCNT0=0 ; restore drawing state, as before BACKGROUND C:0005a0 01e6 movw YH:YL,BGFBUFH:BGFBUFL ; {1] restore framebuf address for drawing C:0005a1 01f7 movw ZH:ZL,BGCONTH:BGCONTL ; {1} restore continuation point for "return" C:0005a2 9409 ijmp ; {3} and "return" to the line type that called ; now is 52 clocks since TCNT0=0 ; gives minimal for backgrounding = 23 + 4 + 52 clocks ; so forget backgrounding while horiz retrace ; here is always ijmp to lines *CONT point ; that is left of screen blanking, then horiz pulse ; after that count lines and possibly state change ; next line (or next state) will again BACKGROUND ; --- end of interrupt, store drawing state, pop background ; as far as drawing goes, it "calls" background until timer "returns" ; parameters: ZH:ZL: address for continuation, "return" of the "call" ; YH:YL: current frame buffer address, to save and restore BACKGROUND: ; timing not critical here, as enter background ; only for computing minimal backgrounding time ; drawing state part which has no dedicated variables C:0005a3 017f movw BGCONTH:BGCONTL,ZH:ZL ; {1] save continuation point for "return" C:0005a4 016e movw BGFBUFH:BGFBUFL,YH:YL ; {1] save framebuffer address for drawing C:0005a5 e062 ldi I0,(1< 0xFF C:000670 f021 breq CHNEXSEG ; {1|2} CHLINE now 0x00, was 0xFF, do next segment C:000671 97aa sbiw YH:YL,FBROWLEN ; {2} undo reads, repeat same segment for 2nd line C:000672 e063 ldi I0,3 ; {1} wait rest of its time, 30-(1+3)-(1+1)-2-6=16 C:000673 df08 rcall WAIT ; {3+(3*3+3)=15} C:000674 cfce rjmp CHDRLINE ; {2+(3+1)=6pre} CHNEXSEG: C:000675 9573 inc CHSEGM ; {1} next CHSEGM C:000676 3078 cpi CHSEGM,ROWSEGMENTS ; {1} C:000677 f029 breq CHNEXROW ; {1|2} all segments done, do next row C:000678 97aa sbiw YH:YL,FBROWLEN ; {2} undo reads, repeat same row for other segments C:000679 e061 ldi I0,1 ; {1} wait rest time, 30-(1+3)-(1+2)-(1+1+1)-2-7=11 C:00067a df01 rcall WAIT ; {3+(1*3+3)=9} C:00067b 0000 nop ; {1} C:00067c cfc5 rjmp CHDRSEGM ; {2+(1+3+1)=7pre} CHNEXROW: C:00067d 94aa dec CHROW ; {1} next CHROW C:00067e f051 breq CHNEXSTATE ; {1|2} all rows done, do next state C:00067f 0000 nop ; {9} wait rest, 30-(1+3)-(1+2)-(1+1+2)-(1+1)-8=9 C:000680 0000 nop C:000681 0000 nop C:000682 0000 nop C:000683 0000 nop C:000684 0000 nop C:000685 0000 nop C:000686 0000 nop C:000687 0000 nop C:000688 cfb8 rjmp CHDRROW ; {2+(1+1+3+1)=8pre} CHNEXSTATE: C:000689 0000 nop ; {3} wait rest, 30-(1+3)-(1+2)-(1+1+2)-(1+2)-13=3 C:00068a 0000 nop C:00068b 0000 nop C:00068c cf4f rjmp VRBBSTATE ; {2+11=13pre} on to next state, vert retrace bottom ; ------ X/Y coordinate based frame buffer handling ; --- X/Y write colour into frame buffer ; parameters: S0: row in frame buffer to place colour ; T0: colour code for FBWCOLOUR, gets truncated ; T1: LUT reg to set, 0..4 = back/fore/alt1/alt2/alt3 XYWCOLOUR: C:00068d 3137 cpi S0,FBROWS ; row in 0..(FBROWS-1) ? C:00068e f460 brsh XYOUTRANGE ; >=, dont' colour non-existant row C:00068f 3015 cpi T1,FBROWBEG C:000690 f450 brsh XYOUTRANGE ; >=, dont' set to non-existant LUT colour C:000691 e8a0 ldi XL,low(FBUF) ; begin of frame buffer colours C:000692 e0b4 ldi XH,high(FBUF) C:000693 e22a ldi T2,FBROWLEN ; skip rows before this one C:000694 9f32 mul S0,T2 C:000695 0da0 add XL,ML ; this row of frame buffer colours C:000696 1db1 adc XH,MH C:000697 0fa1 add XL,T1 ; add index for wanted colour byte C:000698 e020 ldi T2,0 C:000699 1fb2 adc XH,T2 C:00069a ce9f rjmp FBWCOLOUR XYOUTRANGE: C:00069b 9508 ret ; --- X/Y read colour from frame buffer ; parameters: S0: row in frame buffer to extract colour ; T1: LUT reg to set, 0..4 = back/fore/alt1/alt2/alt3 ; returns: T0: colour code from FBRCOLOUR XYRCOLOUR: C:00069c 3137 cpi S0,FBROWS ; row in 0..(FBROWS-1) ? C:00069d f7e8 brsh XYOUTRANGE ; >=, dont' colour non-existant row C:00069e 3015 cpi T1,FBROWBEG C:00069f f7d8 brsh XYOUTRANGE ; >=, dont' set to non-existant LUT colour C:0006a0 e8a0 ldi XL,low(FBUF) ; begin of frame buffer colours C:0006a1 e0b4 ldi XH,high(FBUF) C:0006a2 e22a ldi T2,FBROWLEN ; skip rows before this one C:0006a3 9f32 mul S0,T2 C:0006a4 0da0 add XL,ML ; this row of frame buffer colours C:0006a5 1db1 adc XH,MH C:0006a6 0fa1 add XL,T1 ; add index for wanted colour byte C:0006a7 e020 ldi T2,0 C:0006a8 1fb2 adc XH,T2 C:0006a9 ce93 rjmp FBRCOLOUR ; --- X/Y write character into frame buffer ; parameters: S0: row in frame buffer to place character ; S1: column in frame buffer to place character ; T0: ASCII character for FBWCHAR, left converted XYWCHAR: C:0006aa 3137 cpi S0,FBROWS ; row in 0..(FBROWS-1) ? C:0006ab f778 brsh XYOUTRANGE ; >=, dont' draw in non-existant row C:0006ac 3244 cpi S1,FBCOLS ; column in 0..(FBCOLS-1) ? C:0006ad f768 brsh XYOUTRANGE ; >=, dont' draw in non-existant column C:0006ae e8a5 ldi XL,low(FBUF+FBROWBEG) ; begin of frame buffer chars C:0006af e0b4 ldi XH,high(FBUF+FBROWBEG) C:0006b0 e22a ldi T2,FBROWLEN ; skip rows before this one C:0006b1 9f32 mul S0,T2 C:0006b2 0da0 add XL,ML ; this row of frame buffer chars C:0006b3 1db1 adc XH,MH C:0006b4 0fa4 add XL,S1 ; this column in frame buffer C:0006b5 e020 ldi T2,0 C:0006b6 1fb2 adc XH,T2 C:0006b7 ce87 rjmp FBWCHAR ; --- X/Y read character from frame buffer, not needed up to now ; --- X/Y write immediate string into frame buffer ; parameters: S0: row in frame buffer to place first character of string ; S1: column in frame buffer to place first character of string XYWSTRI: C:0006b8 3137 cpi S0,FBROWS ; row in 0..(FBROWS-1) ? C:0006b9 f708 brsh XYOUTRANGE ; >=, dont' draw in non-existant row C:0006ba 3244 cpi S1,FBCOLS ; column in 0..(FBCOLS-1) ? C:0006bb f6f8 brsh XYOUTRANGE ; >=, dont' draw in non-existant column C:0006bc e8a5 ldi XL,low(FBUF+FBROWBEG) ; begin of frame buffer chars C:0006bd e0b4 ldi XH,high(FBUF+FBROWBEG) C:0006be e22a ldi T2,FBROWLEN ; skip rows before this one C:0006bf 9f32 mul S0,T2 C:0006c0 0da0 add XL,ML ; this row of frame buffer chars C:0006c1 1db1 adc XH,MH C:0006c2 0fa4 add XL,S1 ; this column in frame buffer C:0006c3 e020 ldi T2,0 C:0006c4 1fb2 adc XH,T2 C:0006c5 ce81 rjmp FBWSTRI ; ------ demo program ; --- draw an blank row ; parameters: S0: row in frame buffer to blank out DEBLANK_1X36: C:0006c6 dff1 rcall XYWSTRI .dw 36 C:0006c7 0024 .db " " ; empty string C:0006C8 202020202020202020202020202020202020202020202020202020202020202020202020 C:0006da 9533 inc S0 C:0006db 9508 ret ; --- draw entire ASCII char set ; parameters: S0: row in frame buffer to begin at ; S1: column in frame buffer to begin at DEASC_3X32: ; show 95 ASCII chars 32..126 (0x20..0x7E) in 3 rows of 32, 127 as blank C:0006dc dfdb rcall XYWSTRI .dw 32 C:0006dd 0020 .db " !", 0x22, "#$%&", 0x27, "()*+,-./0123456789:;<=>?" C:0006DE 202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F C:0006ee 9533 inc S0 C:0006ef dfc8 rcall XYWSTRI .dw 32 C:0006f0 0020 .db "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_" C:0006F1 404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F C:000701 9533 inc S0 C:000702 dfb5 rcall XYWSTRI .dw 32 C:000703 0020 .db "`abcdefghijklmnopqrstuvwxyz{|}~ " C:000704 606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E20 C:000714 9533 inc S0 C:000715 9508 ret DEASC_3X36: C:000716 dfaf rcall DEBLANK_1X36 ; get rid of left over dots at both ends C:000717 dfae rcall DEBLANK_1X36 C:000718 dfad rcall DEBLANK_1X36 C:000719 5033 subi S0,3 ; back up the 3 rows, for drawing actual stuff C:00071a 5f4e subi S1,-2 ; indent (36-32)/2=2 unused characters C:00071b dfc0 rcall DEASC_3X32 C:00071c 5042 subi S1,2 ; and outdent back C:00071d 9508 ret ; --- draw black row to separate sections ; parameters: S0: row in frame buffer to black out DEBLACK_1X36: C:00071e e000 ldi T0,0x00 ; black C:00071f e010 ldi T1,0 ; set background to black, leave unused foreground C:000720 df6c rcall XYWCOLOUR C:000721 cfa4 rjmp DEBLANK_1X36 ; --- setup 6 black texts on rainbow coloured row backgrounds ; parameters: S0: row in frame buffer to begin at ; T0: background colour DERAIN_1: C:000722 e010 ldi T1,0 ; set background to colour T0 C:000723 df69 rcall XYWCOLOUR C:000724 e000 ldi T0,0x00 ; black C:000725 e011 ldi T1,1 ; set foreground to black C:000726 df66 rcall XYWCOLOUR C:000727 9533 inc S0 C:000728 9508 ret ; parameters: S0: row in frame buffer to begin at DERAIN_6: C:000729 e300 ldi T0,0x30 ; red C:00072a dff7 rcall DERAIN_1 C:00072b e30c ldi T0,0x3C ; yellow C:00072c dff5 rcall DERAIN_1 C:00072d e00c ldi T0,0x0C ; green C:00072e dff3 rcall DERAIN_1 C:00072f e00f ldi T0,0x0F ; cyan C:000730 dff1 rcall DERAIN_1 C:000731 e003 ldi T0,0x03 ; blue C:000732 dfef rcall DERAIN_1 C:000733 e303 ldi T0,0x33 ; magenta C:000734 dfed rcall DERAIN_1 C:000735 5036 subi S0,6 ; back up the 6 rows, for drawing stuff over them C:000736 9508 ret ; --- draw ASCII art wave(s) ; parameters: S0: row in frame buffer to begin at ; S1: column in frame buffer to begin at DEWAVE_1X19: C:000737 df80 rcall XYWSTRI .dw 19 C:000738 0013 .db "-", 0x27, "__`-.__.-", 0x27, "__`-.__", 0 C:000739 2D275F5F602D2E5F5F2E2D275F5F602D2E5F5F00 C:000743 9533 inc S0 C:000744 9508 ret DEWAVE_6X19: C:000745 dff1 rcall DEWAVE_1X19 ; make 6 rows with this (and all other graphics) C:000746 dff0 rcall DEWAVE_1X19 C:000747 dfef rcall DEWAVE_1X19 C:000748 dfee rcall DEWAVE_1X19 C:000749 dfed rcall DEWAVE_1X19 C:00074a dfec rcall DEWAVE_1X19 C:00074b 9508 ret ; --- draw separator(s) of ASCII wave(s) from blockgraphic logo ; parameters: S0: row in frame buffer to begin at ; S1: column in frame buffer to begin at DESEPAR_1X1: C:00074c e10f ldi T0,BG1111 ; block graphics all 4 2x2pixel set to foreground C:00074d df5c rcall XYWCHAR C:00074e 9533 inc S0 C:00074f 9508 ret DESEPAR_6X1: C:000750 dffb rcall DESEPAR_1X1 ; make 6 rows with this (and all other graphics) C:000751 dffa rcall DESEPAR_1X1 C:000752 dff9 rcall DESEPAR_1X1 C:000753 dff8 rcall DESEPAR_1X1 C:000754 dff7 rcall DESEPAR_1X1 C:000755 dff6 rcall DESEPAR_1X1 C:000756 9508 ret ; --- draw logo put together from 2x2pixel blockgraphics ; parameters: S0: row in frame buffer to begin at ; S1: column in frame buffer to begin at DELOGO_6x16: ; print this text using 1/2+7+1/2 * 4x12pixels, of 2x2pixel blockgraphics ; = space used 1/2+7+1/2 * 2x6 chars = 16 chars width, always 6 rows ; .... ........ ........ ........ .... .... ........ ........ ........ .... ; .... ()()()() ()()()() ()()()() ()() ()() ()()()() ()()()() ()()()() .... ; .... ........ ........ ........ .... .... ........ ........ ........ .... ; .... ..()().. ........ ....().. ..() .... ..()..() ....()() ....().. .... ; .... ()...... ........ ..().... ..() .... ..()..() ..().... ..()..() .... ; .... ..().... ..().... ()()().. ()() ().. ..()..() ..().... ..()..() .... ; .... ....().. ()..().. ..().... ..() .... ..()..() ..()..() ..()()() .... ; .... ....().. ()..().. ..().... ..() .... ....().. ..()..() ..()..() .... ; .... ()().... ..().... ..().... .... ().. ....().. ....()() ..()..() .... ; .... ........ ........ ........ .... .... ........ ........ ........ .... ; .... ()()()() ()()()() ()()()() ()() ()() ()()()() ()()()() ()()()() .... ; .... ........ ........ ........ .... .... ........ ........ ........ .... C:000757 df60 rcall XYWSTRI .dw 16 C:000758 0010 .db BG0000, BG0011, BG0011, BG0011, BG0011, BG0011, BG0011, BG0011 C:000759 1013131313131313 .db BG0011, BG0011, BG0011, BG0011, BG0011, BG0011, BG0011, BG0000 C:00075D 1313131313131310 C:000761 9533 inc S0 C:000762 df55 rcall XYWSTRI .dw 16 C:000763 0010 .db BG0000, BG0001, BG0010, BG0000, BG0000, BG0000, BG0010, BG0001 C:000764 1011121010101211 .db BG0000, BG0001, BG0001, BG0000, BG0011, BG0000, BG0010, BG0000 C:000768 1011111013101210 C:00076c 9533 inc S0 C:00076d df4a rcall XYWSTRI .dw 16 C:00076e 0010 .db BG0000, BG1001, BG0000, BG0001, BG0000, BG0111, BG0010, BG0111 C:00076F 1019101110171217 .db BG0010, BG0101, BG0101, BG0101, BG0000, BG0101, BG0101, BG0000 C:000773 1215151510151510 C:000777 9533 inc S0 C:000778 df3f rcall XYWSTRI .dw 16 C:000779 0010 .db BG0000, BG0000, BG1010, BG1010, BG1010, BG0101, BG0000, BG0101 C:00077A 10101A1A1A151015 .db BG0000, BG0100, BG0110, BG0101, BG0101, BG0101, BG1101, BG0000 C:00077E 1014161515151D10 C:000782 9533 inc S0 C:000783 df34 rcall XYWSTRI .dw 16 C:000784 0010 .db BG0000, BG1100, BG0000, BG0100, BG0000, BG0100, BG0000, BG0000 C:000785 101C101410141010 .db BG1000, BG0000, BG1000, BG0000, BG1100, BG0100, BG0100, BG0000 C:000789 181018101C141410 C:00078d 9533 inc S0 C:00078e df29 rcall XYWSTRI .dw 16 C:00078f 0010 .db BG0000, BG1100, BG1100, BG1100, BG1100, BG1100, BG1100, BG1100 C:000790 101C1C1C1C1C1C1C .db BG1100, BG1100, BG1100, BG1100, BG1100, BG1100, BG1100, BG0000 C:000794 1C1C1C1C1C1C1C10 C:000798 9533 inc S0 C:000799 9508 ret ; --- draw graphics, wave(s) + seprator(s) + logo ; parameters: S0: row in frame buffer to begin at ; S1: column in frame buffer to begin at DEGRAPH_6X36: C:00079a dfaa rcall DEWAVE_6X19 C:00079b 5036 subi S0,6 ; back up the 6 rows, for separator C:00079c 5e4d subi S1,-19 ; indent by 19 columns, jump over ASCII wave(s) C:00079d dfb2 rcall DESEPAR_6X1 C:00079e 5036 subi S0,6 ; back up the 6 rows, for logo C:00079f 9543 inc S1 ; indent by 1 column, jump over separator(s) C:0007a0 dfb6 rcall DELOGO_6X16 C:0007a1 5144 subi S1,20 ; and back, both indents, 19 and 1 C:0007a2 9508 ret ; --- draw announce message ; parameters: S0: row in frame buffer to begin at ; S1: column in frame buffer to begin at DEANN_3X36: C:0007a3 df14 rcall XYWSTRI .dw 36 C:0007a4 0024 .db "ATmega32 uC + SoftVGA = 400line 70Hz" C:0007A5 41546D6567613332207543202B20536F6674564741203D203430306C696E65203730487A C:0007b7 9533 inc S0 C:0007b8 deff rcall XYWSTRI .dw 36 C:0007b9 0024 .db "18.432MHz, 3clk/px, 4px/char, 40char" C:0007BA 31382E3433324D487A2C2033636C6B2F70782C203470782F636861722C20343063686172 C:0007cc 9533 inc S0 C:0007cd deea rcall XYWSTRI .dw 36 C:0007ce 0024 .db " neil.franklin.ch/Projects/SoftVGA/ " C:0007CF 206E65696C2E6672616E6B6C696E2E63682F50726F6A656374732F536F66745647412F20 C:0007e1 9533 inc S0 C:0007e2 9508 ret ; --- setup 7 RBG+derivatives coloured texts on black row backgrounds ; parameters: S0: row in frame buffer to begin at ; T0: main foreground colour, rest of colours derived from this DERGB_1: C:0007e3 930f push T0 ; save for multiple reuse C:0007e4 e000 ldi T0,0x00 ; black C:0007e5 e010 ldi T1,0 ; set background to black C:0007e6 dea6 rcall XYWCOLOUR C:0007e7 910f pop T0 C:0007e8 930f push T0 C:0007e9 e011 ldi T1,1 ; set foreground to colour T0 C:0007ea dea2 rcall XYWCOLOUR C:0007eb 910f pop T0 C:0007ec 930f push T0 C:0007ed 720a andi T0,0x2A ; 2/3 bright, kill bit0 of each DAC C:0007ee e012 ldi T1,2 ; set alternate foreground colour 1 C:0007ef de9d rcall XYWCOLOUR C:0007f0 910f pop T0 C:0007f1 930f push T0 C:0007f2 620a ori T0,0x2A ; 2/3 pastel, force bit1 of all DACs C:0007f3 e013 ldi T1,3 ; set alternate foreground colour 2 C:0007f4 de98 rcall XYWCOLOUR C:0007f5 910f pop T0 C:0007f6 7105 andi T0,0x15 ; 1/3 pastel, force bit0 of all DACs C:0007f7 e014 ldi T1,4 ; set alternate background colour 3 C:0007f8 de94 rcall XYWCOLOUR C:0007f9 9533 inc S0 C:0007fa 9508 ret ; parameters: S0: row in frame buffer to begin at DERGB_7: C:0007fb e003 ldi T0,0x03 ; blue C:0007fc dfe6 rcall DERGB_1 C:0007fd e00c ldi T0,0x0C ; green C:0007fe dfe4 rcall DERGB_1 C:0007ff e00f ldi T0,0x0F ; cyan C:000800 dfe2 rcall DERGB_1 C:000801 e300 ldi T0,0x30 ; red C:000802 dfe0 rcall DERGB_1 C:000803 e303 ldi T0,0x33 ; magenta C:000804 dfde rcall DERGB_1 C:000805 e30c ldi T0,0x3C ; yellow C:000806 dfdc rcall DERGB_1 C:000807 e30f ldi T0,0x3F ; white C:000808 dfda rcall DERGB_1 C:000809 5037 subi S0,7 ; back up the 7 rows, for drawing stuff over them C:00080a 9508 ret ; --- draw multistyle/-coloured text ; parameters: S0: row in frame buffer to begin at ; S1: column in frame buffer to begin at DEMULT_1X36: C:00080b deac rcall XYWSTRI .dw 36 C:00080c 0024 .db "n", "o", "r", INV, "i", "n", "v", INV C:00080D 6E6F7200696E7600 .db "n", "o", ULIN, "u", "l", "i", "n", ULIN C:000811 6E6F01756C696E01 .db "n", "o", FG1, "f", "g", "1", FG1, "n" C:000815 6E6F02666731026E .db "o", FG2, "f", "g", "2", FG2, "n", "o" C:000819 6F03666732036E6F .db BG3, "b", "g", "3" C:00081D 04626733 C:00081f 9533 inc S0 C:000820 9508 ret DEMULT_8X36: C:000821 dfe9 rcall DEMULT_1X36 ; make 7 rows with this C:000822 dfe8 rcall DEMULT_1X36 C:000823 dfe7 rcall DEMULT_1X36 C:000824 dfe6 rcall DEMULT_1X36 C:000825 dfe5 rcall DEMULT_1X36 C:000826 dfe4 rcall DEMULT_1X36 C:000827 dfe3 rcall DEMULT_1X36 C:000828 dfe2 rcall DEMULT_1X36 C:000829 9508 ret ; --- rotate ASCII char set background colour ; parameters: S0: row in frame buffer to rotate colour DEROTBG_1: C:00082a e010 ldi T1,0 ; background C:00082b de70 rcall XYRCOLOUR ; read existing colour C:00082c 5f00 subi T0,-0x10 ; only modify red, 4 steps C:00082d de5f rcall XYWCOLOUR ; write new colour C:00082e 9508 ret ; parameters: S2: frame count 0..255 DEROTBG_3: C:00082f 9a94 sbi PORTD,PIND4 C:000830 988c cbi DDRD,PIND4 C:000831 9984 sbic PIND,PIND4 ; only if switch on PortD4 activated C:000832 9508 ret ; no switch, no rotate, abort C:000833 2f05 mov T0,S2 ; rotate every 64th frame, ~1s C:000834 730f andi T0,0x3F ; frame 0|64|128|192|0|...? C:000835 f441 brne DERONOT ; no, do nothing C:000836 933f push S0 ; yes, rotate background colour C:000837 e030 ldi S0,0 ; first row of ASCII char set C:000838 dff1 rcall DEROTBG_1 C:000839 9533 inc S0 C:00083a dfef rcall DEROTBG_1 C:00083b 9533 inc S0 C:00083c dfed rcall DEROTBG_1 C:00083d 913f pop S0 DERONOT: C:00083e 9508 ret ; --- move andalusian video snail across blank row ; parameters: S2: frame count 0..255 DESNAIL_1X36: C:00083f 933f push S0 C:000840 934f push S1 C:000841 e03e ldi S0,14 ; black row just after announce message C:000842 e040 ldi S1,0 C:000843 de82 rcall DEBLANK_1X36 ; restore blank in case switch off, remove old snail C:000844 5031 subi S0,1 ; back up the row, for drawing new snail C:000845 9a93 sbi PORTD,PIND3 C:000846 988b cbi DDRD,PIND3 C:000847 9983 sbic PIND,PIND3 ; only if switch on PortD3 activated C:000848 c010 rjmp DESNNOT ; no switch, no rotate, abort C:000849 9140 084d lds S1,DESNPOS ; wherever snail was drawn last time C:00084b 2f05 mov T0,S2 ; move every 16th frame, ~1/4s C:00084c 700f andi T0,0x0F ; frame 0|16|32|48|..|240|0|...? C:00084d f431 brne DESNSTAY ; no, leave column unchanged C:00084e 9543 inc S1 ; yes, move snail one column to the right C:00084f 3244 cpi S1,FBCOLS ; after last column? C:000850 f008 brlo DESNCOLOK ; <, column OK C:000851 e040 ldi S1,0 ; >=, back to the left column DESNCOLOK: C:000852 9340 084d sts DESNPOS,S1 ; store any changes DESNSTAY: C:000854 de63 rcall XYWSTRI .dw 4 C:000855 0004 .db "_@_/" ; the traditional 1-liner ASCII art C:000856 5F405F2F C:000858 9533 inc S0 DESNNOT: C:000859 914f pop S1 C:00085a 913f pop S0 C:00085b 9508 ret ; --- bounce ball in middle of graohic ; parameters: S0: row in frame buffer to begin at ; S1: column in frame buffer to begin at DEBOFIELD_1X8: C:00085c de5b rcall XYWSTRI .dw 8 C:00085d 0008 .db BG1111, BG0000, BG0000, BG0000 C:00085E 1F101010 .db BG0000, BG0000, BG0000, BG1111 C:000860 1010101F C:000862 9533 inc S0 C:000863 9508 ret ; parameters: S0: row in frame buffer to begin at ; S1: column in frame buffer to begin at DEBOFIELD_6X8: C:000864 dff7 rcall DEBOFIELD_1X8 C:000865 dff6 rcall DEBOFIELD_1X8 C:000866 dff5 rcall DEBOFIELD_1X8 C:000867 dff4 rcall DEBOFIELD_1X8 C:000868 dff3 rcall DEBOFIELD_1X8 C:000869 dff2 rcall DEBOFIELD_1X8 C:00086a 9508 ret ; ball pattern and definition ; must leave 3 pixels width and 3 segmentpairs hight of characters unused ; for 4 drawing positions, shiftable by 0 or 1 or 2 or 3 ; so must bei 4*n-3 pixel size in both directions, for n=3: 4*3-1=9 ; add 3 blank segmentpairs above and below for vertical scrolling ; by positioning ROM pointer on -6|-4|-2|0 segmentpair ; 000011112222333300001111222233330000111122223333 ; | | | ; -6 ................................................ ; -5 ................................................ ; -4 ................................................ ; -3 ................................................ ; -2 ................................................ ; -1__................................................ ; 0 ............@@@@@@@@@@@@........................ ; 1 ........@@@@@@@@@@@@@@@@@@@@.................... ; 2 ........@@@@............@@@@.................... ; 3 ....@@@@....................@@@@................ ; 4 ....@@@@....................@@@@................ ; 5 @@@@............................@@@@............ ; 6 @@@@............................@@@@............ ; 7__@@@@............................@@@@............ ; 0 @@@@............................@@@@............ ; 1 @@@@............................@@@@............ ; 2 @@@@............................@@@@............ ; 3 @@@@............................@@@@............ ; 4 @@@@............................@@@@............ ; 5 ....@@@@....................@@@@................ ; 6 ....@@@@....................@@@@................ ; 7__........@@@@............@@@@.................... ; 0 ........@@@@@@@@@@@@@@@@@@@@.................... ; 1 ............@@@@@@@@@@@@........................ ; 2 ................................................ ; 3 ................................................ ; 4 ................................................ ; 5 ................................................ ; 6 ................................................ ; 7__................................................ ; blanks, 1 .db per 2 segments (1 segmentpair), 3*2*DEBOCHARSWIDE ; vertical/segmentpair offset 3 starts here .db SEGM0000, SEGM0000, SEGM0000, SEGM0000, SEGM0000, SEGM0000 C:00086B 000000000000 ; vertical/segmentpair offset 2 starts here .db SEGM0000, SEGM0000, SEGM0000, SEGM0000, SEGM0000, SEGM0000 C:00086E 000000000000 ; vertical/segmentpair offset 1 starts here .db SEGM0000, SEGM0000, SEGM0000, SEGM0000, SEGM0000, SEGM0000 C:000871 000000000000 ; vertical/segmentpair offset 0 starts here DEBOBALLROM: ; ball, 1 .db per 2 segments (1 segmentpair), 9*2*DEBOCHARSWIDE .db SEGM0001, SEGM1100, SEGM0000, SEGM0011, SEGM1110, SEGM0000 C:000874 010C00030E00 .db SEGM0010, SEGM0010, SEGM0000, SEGM0100, SEGM0001, SEGM0000 C:000877 020200040100 .db SEGM0100, SEGM0001, SEGM0000, SEGM1000, SEGM0000, SEGM1000 C:00087A 040100080008 .db SEGM1000, SEGM0000, SEGM1000, SEGM1000, SEGM0000, SEGM1000 C:00087D 080008080008 .db SEGM1000, SEGM0000, SEGM1000, SEGM1000, SEGM0000, SEGM1000 C:000880 080008080008 .db SEGM1000, SEGM0000, SEGM1000, SEGM1000, SEGM0000, SEGM1000 C:000883 080008080008 .db SEGM1000, SEGM0000, SEGM1000, SEGM0100, SEGM0001, SEGM0000 C:000886 080008040100 .db SEGM0100, SEGM0001, SEGM0000, SEGM0010, SEGM0010, SEGM0000 C:000889 040100020200 .db SEGM0011, SEGM1110, SEGM0000, SEGM0001, SEGM1100, SEGM0000 C:00088C 030E00010C00 ; blanks, 1 .db per 2 segments (1 segmentpair), 3*2*DEBOCHARSWIDE ; vertical/segmentpair offset 3 ends here .db SEGM0000, SEGM0000, SEGM0000, SEGM0000, SEGM0000, SEGM0000 C:00088F 000000000000 ; vertical/segmentpair offset 2 ends here .db SEGM0000, SEGM0000, SEGM0000, SEGM0000, SEGM0000, SEGM0000 C:000892 000000000000 ; vertical/segmentpair offset 1 ends here .db SEGM0000, SEGM0000, SEGM0000, SEGM0000, SEGM0000, SEGM0000 C:000895 000000000000 ; vertical/segmentpair offset 0 ends here ; ball size 3x3=9 chars, codes 0x07..0x0F for tiles of an ball .equ DEBOCHARSWIDE = 3 .equ DEBOCHARSHIGH = 3 .equ DEBOCHARFIRST = 0x07 .equ DEBOCHARAFTER = DEBOCHARFIRST+DEBOCHARSHIGH*DEBOCHARSWIDE ; parameters: T0: pixel pattern number ; T1: horizontal pixel offset to shift by ; S1: last segments shift-out, for shifting in ; returns: T0: pixel pattern number shifted by T1 (0..3) ; S1: this segments shift-out, for next time shifting in DEBOSHIFT: ; big 4-way case, no complex looping C:000898 fb11 bst T1,1 ; 0,1 or 2,3 ? C:000899 f4c6 brtc DEBOSHIFT0OR1 ; is 0,1 C:00089a fb10 bst T1,0 ; 2 or 3 ? C:00089b f46e brtc DEBOSHIFT2 ; is 2 C:00089c fb45 bst S1,5 ; get first saved bit, 2 behind it C:00089d f904 bld T0,4 ; insert it C:00089e 9506 lsr T0 ; shift C:00089f 9547 ror S1 ; save first carry C:0008a0 fb45 bst S1,5 ; get second saved bit C:0008a1 f904 bld T0,4 C:0008a2 9506 lsr T0 C:0008a3 9547 ror S1 C:0008a4 fb45 bst S1,5 ; get third saved bit C:0008a5 f904 bld T0,4 C:0008a6 9506 lsr T0 C:0008a7 9547 ror S1 C:0008a8 c00f rjmp DEBOSHIFT0 DEBOSHIFT2: C:0008a9 fb46 bst S1,6 ; get first saved bit, 1 behind it C:0008aa f904 bld T0,4 ; insert it C:0008ab 9506 lsr T0 ; shift C:0008ac 9547 ror S1 ; save first carry C:0008ad fb46 bst S1,6 ; get second saved bit C:0008ae f904 bld T0,4 C:0008af 9506 lsr T0 C:0008b0 9547 ror S1 C:0008b1 c006 rjmp DEBOSHIFT0 DEBOSHIFT0OR1: C:0008b2 fb10 bst T1,0 ; 0 or 1 ? C:0008b3 f426 brtc DEBOSHIFT0 ; is 0 C:0008b4 fb47 bst S1,7 ; get only saved bit, 0 behind it C:0008b5 f904 bld T0,4 ; insert it C:0008b6 9506 lsr T0 ; shift C:0008b7 9547 ror S1 ; save only carry DEBOSHIFT0: ; do nothing C:0008b8 9508 ret ; parameters: ZH:ZL: character definition in Flash, gets incremented ; T1: horizontal pixel offset ; T2: first character position to overwrite in all SRAM segments DEBOLDROW: ; each segment in SRAM font has an table of FOCHARS segment indexes C:0008b9 e8a0 ldi XL,low(FONTRAM) ; begin of table of all first segments C:0008ba e0b0 ldi XH,high(FONTRAM) C:0008bb 0fa2 add XL,T2 ; add first characters offset into this segment table ; SRAM font is alligned, can never produce an carry C:0008bc 933f push S0 ; we need more registers C:0008bd 934f push S1 C:0008be e038 ldi S0,ROWSEGMENTS ; for segment = ROWSEGMENTS..1 DEBOROLOOP: C:0008bf e040 ldi S1,0 ; blank shift-out for first segments shifting in C:0008c0 9105 lpm T0,Z+ ; get first segment from Flash, are sequential for row C:0008c1 940e 0898 call DEBOSHIFT C:0008c3 940e 020a call SEGMCONV C:0008c5 930d st X+,T0 ; write segment to table, is sequential for row C:0008c6 9105 lpm T0,Z+ ; repeat for second character, same segment C:0008c7 940e 0898 call DEBOSHIFT C:0008c9 940e 020a call SEGMCONV C:0008cb 930d st X+,T0 C:0008cc 9105 lpm T0,Z+ ; repeat for third character, same segment C:0008cd 940e 0898 call DEBOSHIFT C:0008cf 940e 020a call SEGMCONV C:0008d1 930d st X+,T0 C:0008d2 50a3 subi XL,3 ; undo the 3 X+ operations, not sequential any more C:0008d3 58a0 subi XL,low(-FOCHARS) ; goto next segments table, same position, +FOCHARS C:0008d4 4fbf sbci XH,high(-FOCHARS) ; this gives distributing of segments over tables C:0008d5 953a dec S0 ; next segment C:0008d6 f741 brne DEBOROLOOP C:0008d7 914f pop S1 C:0008d8 913f pop S0 C:0008d9 9508 ret ; parameters: T0: vertical segmentpair offset ; T1: horizontal pixel offset DEBOLOAD: ; each character in ROM/Flash font has ROWSEGMENTS segment indexes C:0008da eee8 ldi ZL,low(DEBOBALLROM*2) ; *2 because of lpm C:0008db e1f0 ldi ZH,high(DEBOBALLROM*2) C:0008dc e026 ldi T2,2*DEBOCHARSWIDE ; bytes per segmentpair (vertical position) C:0008dd 9f02 mul T0,T2 ; pre-append [0..3]*2*DEBOCHARSWIDE blanks C:0008de 19e0 sub ZL,ML ; for that start at earlier address C:0008df 09f1 sbc ZH,MH C:0008e0 e027 ldi T2,DEBOCHARFIRST ; for char = DEBOCHARFIRST..DEBOCHARAFTER-1 DEBOLDLOOP: C:0008e1 dfd7 rcall DEBOLDROW ; load row of chars T2..T2+step-1 from Flash to SRAM C:0008e2 5f2d subi T2,-DEBOCHARSWIDE ; next char, step DEBOCHARSWIDE C:0008e3 3120 cpi T2,DEBOCHARAFTER C:0008e4 f7e1 brne DEBOLDLOOP C:0008e5 9508 ret ; parameters: S0: row in frame buffer to begin at ; S1: column in frame buffer to begin at DEBOBALL_3X3: C:0008e6 ddd1 rcall XYWSTRI .dw 3 C:0008e7 0003 .db DEBOCHARFIRST+0+0, DEBOCHARFIRST+0+1, DEBOCHARFIRST+0+2, 0 C:0008E8 07080900 C:0008ea 9533 inc S0 C:0008eb ddcc rcall XYWSTRI .dw 3 C:0008ec 0003 .db DEBOCHARFIRST+3+0, DEBOCHARFIRST+3+1, DEBOCHARFIRST+3+2, 0 C:0008ED 0A0B0C00 C:0008ef 9533 inc S0 C:0008f0 ddc7 rcall XYWSTRI .dw 3 C:0008f1 0003 .db DEBOCHARFIRST+6+0, DEBOCHARFIRST+6+1, DEBOCHARFIRST+6+2, 0 C:0008F2 0D0E0F00 C:0008f4 9533 inc S0 C:0008f5 9508 ret ; parameters: S2: frame count 0..255 DEBOUNCE_6X36: C:0008f6 933f push S0 C:0008f7 934f push S1 C:0008f8 e034 ldi S0,4 ; blank row before graphics C:0008f9 e040 ldi S1,0 C:0008fa de4a rcall DEWAVE_6X19 ; restore waves in case switch off, remove old C:0008fb 5036 subi S0,6 ; back up the 6 rows, for drawing field and ball C:0008fc 9a92 sbi PORTD,PIND2 C:0008fd 988a cbi DDRD,PIND2 C:0008fe 9982 sbic PIND,PIND2 ; only if switch on PortD2 activated C:0008ff c024 rjmp DEBONOT ; no switch, no new field and ball, abort ; drawing field, box delimited by 2 verticals C:000900 e04c ldi S1,12 ; cut back ASCII waves to 12 wide ... C:000901 df62 rcall DEBOFIELD_6X8 ; ... and empty bounce field C:000902 5036 subi S0,6 ; back up the 6 rows, for drawing ball C:000903 9543 inc S1 ; position enter bounce field horizontally ; lissajous figure, with 2:1 frequency, phase shifted C:000904 2f05 mov T0,S2 ; vertic move ball every 2nd frame, ~1/32s, 0..127 C:000905 9506 lsr T0 ; so divide by 2 C:000906 2f10 mov T1,T0 ; horiz move ball every 4th frame, ~1/16s, 0..63 C:000907 9516 lsr T1 ; so divide again by 2 C:000908 5f1c subi T1,-4 ; phase shift 22.5 degrees, 1/16th (of 64 steps), +4 C:000909 710f andi T0,0x1F ; vertic extract 5 bits for 32 (2*4*4) ball positions C:00090a 711f andi T1,0x1F ; horiz same, 2 direct * 4 char posit * 4 pixel posit C:00090b 2f20 mov T2,T0 ; vertic fold directions C:00090c fd24 sbrc T2,4 ; range 16..31 C:00090d e10f ldi T0,31 ; 31-T2 -> 15..0, 2 slopes with duplicate ends C:00090e fd24 sbrc T2,4 ; gives an *really* braindead sine approximation C:00090f 1b02 sub T0,T2 C:000910 2f21 mov T2,T1 ; horiz same C:000911 fd24 sbrc T2,4 C:000912 e11f ldi T1,31 C:000913 fd24 sbrc T2,4 C:000914 1b12 sub T1,T2 C:000915 930f push T0 ; save for char positioning C:000916 931f push T1 C:000917 7003 andi T0,0x03 ; vertic extract lowest 2 bits for 4 pixel positions C:000918 7013 andi T1,0x03 ; horiz same C:000919 940e 08da call DEBOLOAD ; do pixel positioning while set/load font C:00091b 911f pop T1 ; restore for char positioning C:00091c 910f pop T0 C:00091d 9506 lsr T0 ; vertic get rid of pixel positions, so divide by 4 C:00091e 9506 lsr T0 ; extracts next upper 2 bits for 4 char positions C:00091f 0f30 add S0,T0 ; add to row direction C:000920 9516 lsr T1 ; horiz same C:000921 9516 lsr T1 C:000922 0f41 add S1,T1 C:000923 dfc2 rcall DEBOBALL_3X3 ; draw ball using our 3x3 special characters font DEBONOT: C:000924 914f pop S1 C:000925 913f pop S0 C:000926 9508 ret ; --- blink cursor in first announce row ; parameters: S2: frame count 0..255 DECURSOR_3X36: C:000927 933f push S0 C:000928 934f push S1 C:000929 e03b ldi S0,11 ; first row of announce message C:00092a e040 ldi S1,0 C:00092b de77 rcall DEANN_3X36 ; restore announce in case switch off, remove old C:00092c 5033 subi S0,3 ; back up the 2 rows, for drawing separator C:00092d 9a91 sbi PORTD,PIND1 C:00092e 9889 cbi DDRD,PIND1 C:00092f 9981 sbic PIND,PIND1 ; only if switch on PortD1 activated C:000930 c011 rjmp DECUNOT ; no switch, no new cursor, abort C:000931 fd50 sbrc S2,0 ; alternating 2 frames draw cursor or character C:000932 c00f rjmp DECUNOT ; 2nd, do nothing, draws character C:000933 fd54 sbrc S2,4 ; alternating 2*16 frames blink on or off, ~1/2s C:000934 c00d rjmp DECUNOT ; 16..31, do nothing, cursor off C:000935 9140 084e lds S1,DECUPOS ; wherever cursor was drawn last time C:000937 2f05 mov T0,S2 ; move every 2nd blink, every 64th frame, ~1s C:000938 730f andi T0,0x3F ; frame 0|64|128|192|0|...? C:000939 f431 brne DECUSTAY ; no, leave column unchanged C:00093a 9543 inc S1 ; yes, move cursor one column to the right C:00093b 3244 cpi S1,FBCOLS ; after last column? C:00093c f008 brlo DECUCOLOK ; <, column OK C:00093d e040 ldi S1,0 ; >=, back to the left column DECUCOLOK: C:00093e 9340 084e sts DECUPOS,S1 ; store any changes DECUSTAY: ;ldi T0,0x5F ; draw "_" character as cursor C:000940 e10f ldi T0,BG1111 ; draw full block character as cursor C:000941 dd68 rcall XYWCHAR DECUNOT: C:000942 914f pop S1 C:000943 913f pop S0 C:000944 9508 ret ; --- switch different font for all digits on screen DEFODIGITSROM: ; include font as separate file, so it may be generated automatically ; is done so from file vga_defont_digits.fon, by generator ./genfont .include "vga_defont_digits.inc" ; vga_defont_digits.inc - font for generating VGA text - converted to code ; generated from vga_defont_digits.fon, last generation 2009.05.01 DEFODIGITS: .equ DEFOZERO = 0x30 .equ DEFOAFTER = 0x3A ; ASCII "0" 0x30 .db SEGM0000, SEGM1110, SEGM1010, SEGM1010 C:000945 000E0A0A .db SEGM1010, SEGM1010, SEGM1110, SEGM0000 C:000947 0A0A0E00 ; ASCII "1" 0x31 .db SEGM0000, SEGM1100, SEGM0100, SEGM0100 C:000949 000C0404 .db SEGM0100, SEGM0100, SEGM1110, SEGM0000 C:00094B 04040E00 ; ASCII "2" 0x32 .db SEGM0000, SEGM1110, SEGM0010, SEGM0010 C:00094D 000E0202 .db SEGM1110, SEGM1000, SEGM1110, SEGM0000 C:00094F 0E080E00 ; ASCII "3" 0x33 .db SEGM0000, SEGM1110, SEGM0010, SEGM1110 C:000951 000E020E .db SEGM0010, SEGM0010, SEGM1110, SEGM0000 C:000953 02020E00 ; ASCII "4" 0x34 .db SEGM0000, SEGM1010, SEGM1010, SEGM1010 C:000955 000A0A0A .db SEGM1110, SEGM0010, SEGM0010, SEGM0000 C:000957 0E020200 ; ASCII "5" 0x35 .db SEGM0000, SEGM1110, SEGM1000, SEGM1110 C:000959 000E080E .db SEGM0010, SEGM0010, SEGM1110, SEGM0000 C:00095B 02020E00 ; ASCII "6" 0x36 .db SEGM0000, SEGM1110, SEGM1000, SEGM1110 C:00095D 000E080E .db SEGM1010, SEGM1010, SEGM1110, SEGM0000 C:00095F 0A0A0E00 ; ASCII "7" 0x37 .db SEGM0000, SEGM1110, SEGM0010, SEGM0010 C:000961 000E0202 .db SEGM0010, SEGM0010, SEGM0010, SEGM0000 C:000963 02020200 ; ASCII "8" 0x38 .db SEGM0000, SEGM1110, SEGM1010, SEGM1110 C:000965 000E0A0E .db SEGM1010, SEGM1010, SEGM1110, SEGM0000 C:000967 0A0A0E00 ; ASCII "9" 0x39 .db SEGM0000, SEGM1110, SEGM1010, SEGM1010 C:000969 000E0A0A .db SEGM1110, SEGM0010, SEGM1110, SEGM0000 C:00096B 0E020E00 ; parameters: ZH:ZL: character definitions in Flash, gets incremented DEFOLOAD: C:00096d e320 ldi T2,DEFOZERO ; for char = '0'..'9' DEFOLDLOOP: C:00096e dba9 rcall FOLDCHAR ; load this char T2 from Flash to SRAM C:00096f 9523 inc T2 ; next index C:000970 332a cpi T2,DEFOAFTER C:000971 f7e1 brne DEFOLDLOOP C:000972 9508 ret ; parameters: S2: frame count 0..255 DEFONT_0_9: C:000973 ebe0 ldi ZL,low(FONTROM*2+DEFOZERO*ROWSEGMENTS) ; *2 because of lpm C:000974 e0f5 ldi ZH,high(FONTROM*2+DEFOZERO*ROWSEGMENTS) C:000975 940e 096d call DEFOLOAD ; restore/load standard font, chars 0x30..0x39 ; a lot faster than full FOINIT C:000977 9a90 sbi PORTD,PIND0 C:000978 9888 cbi DDRD,PIND0 C:000979 9980 sbic PIND,PIND0 ; only if switch on PortD0 activated C:00097a c007 rjmp DEFONOT ; no switch, no square font, abort C:00097b 2f05 mov T0,S2 ; show on/off for 32+32 frames, blink ~1s C:00097c 7200 andi T0,0x20 ; frame 32..63, second half of blink? C:00097d f421 brne DEFONOT ; no, leave standard font unchanged C:00097e e8ea ldi ZL,low(DEFODIGITSROM*2) ; *2 because of lpm C:00097f e1f2 ldi ZH,high(DEFODIGITSROM*2) C:000980 940e 096d call DEFOLOAD ; set/load square font, chars 0x30..0x39 DEFONOT: C:000982 9508 ret ; --- show something in frame buffer and animate it DEMO: ; no push/pop S0..S2 here, as routine never exited, endless loop C:000983 e030 ldi S0,0 ; row = 0, start at top of screen C:000984 e040 ldi S1,0 ; column = 0, start at left of screen C:000985 dd90 rcall DEASC_3X36 ; rows 0..2 C:000986 dd97 rcall DEBLACK_1X36 ; row 3 C:000987 dda1 rcall DERAIN_6 ; rows 4..9 C:000988 de11 rcall DEGRAPH_6X36 C:000989 dd94 rcall DEBLACK_1X36 ; row 10 C:00098a de18 rcall DEANN_3X36 ; rows 11..13 C:00098b dd92 rcall DEBLACK_1X36 ; row 14 C:00098c de6e rcall DERGB_7 ; rows 15..22 C:00098d de93 rcall DEMULT_8X36 C:00098e dd8f rcall DEBLACK_1X36 ; row 23 ; leave remaining 6 rows 24..29 of dots unused C:00098f e050 ldi S2,0 ; frame counter/timer, no conflict with S0 or S1 C:000990 9350 084d sts DESNPOS,S2 C:000992 9350 084e sts DECUPOS,S2 ENDLESS: C:000994 dc94 rcall VRWAIT ; wait for next frame vertical blank C:000995 9553 inc S2 ; update frame counter C:000996 de98 rcall DEROTBG_3 C:000997 dea7 rcall DESNAIL_1X36 C:000998 df5d rcall DEBOUNCE_6X36 C:000999 df8d rcall DECURSOR_3X36 C:00099a dfd8 rcall DEFONT_0_9 C:00099b cff8 rjmp ENDLESS ; ------ main program ; --- handle reset, initialise system, start display, main loop RESET: ; get stack ready, for calls and interrupts C:00099c e7af ldi XL,low(ENDOFSTACK-1) C:00099d e0b0 ldi XH,high(ENDOFSTACK-1) C:00099e bfad out SPL,XL C:00099f bfbe out SPH,XH ; and then enable interrupts C:0009a0 9478 sei ; set up font C:0009a1 db87 rcall FOINIT ; set up frame buffer C:0009a2 dbbe rcall FBINIT ; set up port(s) for generating sync pulses and control switch C:0009a3 dc2c rcall SYNCINIT ; set up registers and ports for DACs and control switches C:0009a4 dc8a rcall CHINIT ; start display timer and ISR C:0009a5 dc11 rcall DISPLAY ; enter demo, with endless loop, use up background time ; fill frame buffer to show something C:0009a6 cfdc rjmp DEMO Segment usage: Code : 2198 words (4396 bytes) Data : 2031 bytes EEPROM : 0 bytes Assembly completed with no errors.