''***************************** ''* Graphics Driver v1.0 * ''* (C) 2005 Parallax, Inc. * ''***************************** ''This version has been modified by Steven Messenger (stevenmess2004) with input from deSilva ''It can now do XOR operations, draw glyphs using the ROM font and maybe some other things will get ''added '' '' Theory of Operation: '' '' A cog is launched which processes commands via the PUB routines. '' '' Points, lines, arcs, sprites, text, and polygons are rasterized into '' a specified stretch of memory which serves as a generic bitmap buffer. '' '' The bitmap can be displayed by the TV.SRC or VGA.SRC driver. '' '' See GRAPHICS_DEMO.SRC for usage example. '' VAR long cog long command long bitmap_base 'bitmap data long bitmap_longs word bases[32] long pixel_width 'pixel data long slices[8] long text_xs, text_ys, text_sp, text_just 'text data (these 4 must be contiguous) PUB start : okay '' Start graphics driver - starts a cog '' returns false if no cog available fontptr := @font 'set font pointer (same for all instances) glyphAddress:=@theGlyph 'set glyph address pixBase:=@clemensBuffer stop okay := cog := cognew(@waste, @command) + 1 PUB stop '' Stop graphics driver - frees a cog if cog cogstop(cog~ - 1) command~ PUB setup(x_tiles, y_tiles, x_origin, y_origin, base_ptr) | bases_ptr, slices_ptr '' Set bitmap parameters '' '' x_tiles - number of x tiles (tiles are 16x16 pixels each) '' y_tiles - number of y tiles '' x_origin - relative-x center pixel '' y_origin - relative-y center pixel '' base_ptr - base address of bitmap 'setcommand(_loop, 0) 'make sure last command finished setcommand(constant((@loop-@waste)>>2), 0) repeat bases_ptr from 0 to x_tiles - 1 <# 31 'write bases bases[bases_ptr] := base_ptr + bases_ptr * y_tiles << 6 y_tiles <<= 4 'adjust arguments and do setup command y_origin := y_tiles - y_origin - 1 bases_ptr := @bases slices_ptr := @slices 'setcommand(_setup, @x_tiles) setcommand(constant((@setup_-@waste)>>2), @x_tiles) bitmap_base := base_ptr 'retain high-level bitmap data bitmap_longs := x_tiles * y_tiles PUB clear '' Clear bitmap 'setcommand(_loop, 0) 'make sure last command finished setcommand(constant((@loop-@waste)>>2), 0) longfill(bitmap_base, 0, bitmap_longs) 'clear bitmap PUB copy(dest_ptr) '' Copy bitmap '' use for double-buffered display (flicker-free) '' '' dest_ptr - base address of destination bitmap 'setcommand(_loop, 0) 'make sure last command finished setcommand(constant((@loop-@waste)>>2), 0) longmove(dest_ptr, bitmap_base, bitmap_longs) 'copy bitmap PUB color(c)|_arg1,_arg2 '' Set pixel color to two-bit pattern '' '' c - color code in bits[1..0] 'setcommand(_color, @colors[c & 3]) 'set color longmove(@_arg1,@color_,2) c:=colors[c&3] setcommand(constant((@arg1-@waste)>>2), @c) PUB width(w) | pixel_passes,_arg2,_arg3,_arg4, r, i, p '' Set pixel width '' actual width is w[3..0] + 1 '' '' w - 0..15 for round pixels, 16..31 for square pixels r := not w & $10 'determine pixel shape/width w &= $F pixel_width := w pixel_passes := w >> 1 + 1 'setcommand(_width, @w) 'do width command now to avoid updating slices when busy longmove(@_arg2,@width_,3) setcommand(constant((@arg2-@waste)>>2), @w) p := w ^ $F 'update slices to new shape/width repeat i from 0 to w >> 1 slices[i] := true >> (p << 1) << (p & $E) if r and pixels[w] & |< i p += 2 if r and i == pixel_passes - 2 p += 2 PUB colorwidth(c, w) '' Set pixel color and width color(c) width(w) PUB plot(x, y) '' Plot point '' '' x,y - point 'setcommand(_plot, @x) setcommand(constant((@plot_-@waste)>>2), @x) PUB line(x, y) '' Draw a line to point '' '' x,y - endpoint 'setcommand(_line, @x) setcommand(constant((@line_-@waste)>>2), @x) PUB arc(x, y, xr, yr, angle, anglestep, steps, arcmode) '' Draw an arc '' '' x,y - center of arc '' xr,yr - radii of arc '' angle - initial angle in bits[12..0] (0..$1FFF = 0°..359.956°) '' anglestep - angle step in bits[12..0] '' steps - number of steps (0 just leaves (x,y) at initial arc position) '' arcmode - 0: plot point(s) '' 1: line to point(s) '' 2: line between points '' 3: line from point(s) to center 'setcommand(_arc, @x) setcommand(constant((@arc_-@waste)>>2), @x) PUB vec(x, y, vecscale, vecangle, vecdef_ptr) '' Draw a vector sprite '' '' x,y - center of vector sprite '' vecscale - scale of vector sprite ($100 = 1x) '' vecangle - rotation angle of vector sprite in bits[12..0] '' vecdef_ptr - address of vector sprite definition '' '' '' Vector sprite definition: '' '' word $8000|$4000+angle 'vector mode + 13-bit angle (mode: $4000=plot, $8000=line) '' word length 'vector length '' ... 'more vectors '' ... '' word 0 'end of definition 'setcommand(_vec, @x) setcommand(constant((@vec_-@waste)>>2), @x) PUB vecarc(x, y, xr, yr, angle, vecscale, vecangle, vecdef_ptr) '' Draw a vector sprite at an arc position '' '' x,y - center of arc '' xr,yr - radii of arc '' angle - angle in bits[12..0] (0..$1FFF = 0°..359.956°) '' vecscale - scale of vector sprite ($100 = 1x) '' vecangle - rotation angle of vector sprite in bits[12..0] '' vecdef_ptr - address of vector sprite definition 'setcommand(_vecarc, @x) setcommand(constant((@vecarc_-@waste)>>2), @x) PUB pix(x, y, pixrot, pixdef_ptr) '' Draw a pixel sprite '' '' x,y - center of vector sprite '' pixrot - 0: 0°, 1: 90°, 2: 180°, 3: 270°, +4: mirror '' pixdef_ptr - address of pixel sprite definition '' '' '' Pixel sprite definition: '' '' word 'word align, express dimensions and center, define pixels '' byte xwords, ywords, xorigin, yorigin '' word %%xxxxxxxx,%%xxxxxxxx '' word %%xxxxxxxx,%%xxxxxxxx '' word %%xxxxxxxx,%%xxxxxxxx '' ... 'setcommand(_pix, @x) setcommand(constant((@pixCall_-@waste)>>2), @x) PUB pixarc(x, y, xr, yr, angle, pixrot, pixdef_ptr) '' Draw a pixel sprite at an arc position '' '' x,y - center of arc '' xr,yr - radii of arc '' angle - angle in bits[12..0] (0..$1FFF = 0°..359.956°) '' pixrot - 0: 0°, 1: 90°, 2: 180°, 3: 270°, +4: mirror '' pixdef_ptr - address of pixel sprite definition 'setcommand(_pixarc, @x) setcommand(constant((@pixArcCall_-@waste)>>2), @x) PUB text(x, y, string_ptr) | justx, justy '' Draw text '' '' x,y - text position (see textmode for sizing and justification) '' string_ptr - address of zero-terminated string (it may be necessary to call .finish '' immediately afterwards to prevent subsequent code from clobbering the '' string as it is being drawn justify(string_ptr, @justx) 'justify string and draw text 'setcommand(_text, @x) setcommand(constant((@text_-@waste)>>2), @x) PUB str(x, y, string_ptr) repeat while byte[string_ptr] drawGlyph(x, y, 0, 0, 0, 0, @theGlyph, byte[string_ptr]) x+=16 string_ptr++ PUB textarc(x, y, xr, yr, angle, string_ptr) | justx, justy '' Draw text at an arc position '' '' x,y - center of arc '' xr,yr - radii of arc '' angle - angle in bits[12..0] (0..$1FFF = 0°..359.956°) '' string_ptr - address of zero-terminated string (it may be necessary to call .finish '' immediately afterwards to prevent subsequent code from clobbering the '' string as it is being drawn justify(string_ptr, @justx) 'justify string and draw text 'setcommand(_textarc, @x) setcommand(constant((@textarc_-@waste)>>2), @x) PUB textmode(x_scale, y_scale, spacing, justification)|_arg4,_arg5,_arg6,_arg7 '' Set text size and justification '' '' x_scale - x character scale, should be 1+ '' y_scale - y character scale, should be 1+ '' spacing - character spacing, 6 is normal '' justification - bits[1..0]: 0..3 = left, center, right, left '' bits[3..2]: 0..3 = bottom, center, top, bottom longmove(@text_xs, @x_scale, 4) 'retain high-level text data longmove(@_arg5, @textmode_,3) setcommand(constant((@arg5-@waste)>>2), @x_scale) 'setcommand(_textmode, @x_scale) 'set text mode 'setcommand(constant((@textmode_-@waste)>>2), @x_scale) PUB setFont(fontType) ''Sets font type case fontType 0: hubPtr:=@replaceStart counter:=60 setcommand(constant((@arg2-@waste)>>2),@setFont_) 1: 'set ROM font hubPtr:=@drawGlyphText_ counter:=60 setcommand(constant((@arg2-@waste)>>2),@setFont_) 2: 'set Clemens font hubPtr:=@clemensStart counter:=60 setcommand(constant((@arg2-@waste)>>2),@setFont_) PUB testSmallGlyph(x,y) pix(x, y, 0, @clemensBuffer) PUB box(x, y, box_width, box_height) | x2, y2, pmin, pmax '' Draw a box with round/square corners, according to pixel width '' '' x,y - box left, box bottom if box_width > pixel_width and box_height > pixel_width pmax := pixel_width - (pmin := pixel_width >> 1) 'get pixel-half-min and pixel-half-max x += pmin 'adjust coordinates to accomodate width y += pmin x2 := x + box_width - 1 - pixel_width y2 := y + box_height - 1 - pixel_width plot(x, y) 'plot round/square corners plot(x, y2) plot(x2, y) plot(x2, y2) fill(x, y2 + pmax, 0, (x2 - x) << 16, 0, 0, pmax) 'fill gaps fill(x, y, 0, (x2 - x) << 16, 0, 0, pmin) fill(x - pmin, y2, 0, (x2 - x + pixel_width) << 16, 0, 0, y2 - y) PUB boxXOR(x, y, box_width, box_height) | x2, y2, pmin, pmax '' Draw a box with square corners '' '' x,y - box left, box bottom fill(x,y+box_height-1,0,box_width<<16,0,0,box_height-1) PUB quad(x1, y1, x2, y2, x3, y3, x4, y4)|tx3,ty3,tx1,ty1 '' Draw a solid quadrilateral '' vertices must be ordered clockwise or counter-clockwise ''x1 must be the bottom right tri(x1, y1, x2, y2, x3, y3) 'draw two triangle to make 4-sides polygon if y4>y3 ty3:=y3+1 tx3:=(x4-x3)/(y4-y3)+x3 else ty3:=y3-1 tx3:=-(x4-x3)/(y4-y3)+x3 if x4>x1 tx1:=x1+1 ty1:=(y4-y1)/(x4-x1)+y1 else tx1:=x1-1 ty1:=-(y4-y1)/(x4-x1)+y1 tri(tx3, ty3, x4, y4, tx1, ty1) {{ so for some calcs so that the triangles don't overlap we want to change x1,y1,x3 and y3 in the second tri slope of line from x3,y3 to x4,y4 is (y4-y3)/(x4-x3) want to make y 1 less so need x3(y3-1 y=mx+b (y-y1)=(y4-y3)/(x4-x3)*(x-x1) we want when x-x1=1 y=(y4-y3)/(x4-x3)+y1 }} PUB tri(x1, y1, x2, y2, x3, y3) | xy[2] '' Draw a solid triangle ' reorder vertices by descending y case (y1 => y2) & %100 | (y2 => y3) & %010 | (y1 => y3) & %001 %000: longmove(@xy, @x1, 2) longmove(@x1, @x3, 2) longmove(@x3, @xy, 2) %010: longmove(@xy, @x1, 2) longmove(@x1, @x2, 4) longmove(@x3, @xy, 2) %011: longmove(@xy, @x1, 2) longmove(@x1, @x2, 2) longmove(@x2, @xy, 2) %100: longmove(@xy, @x3, 2) longmove(@x2, @x1, 4) longmove(@x1, @xy, 2) %101: longmove(@xy, @x2, 2) longmove(@x2, @x3, 2) longmove(@x3, @xy, 2) ' draw triangle fill(x1, y1, (x3 - x1) << 16 / (y1 - y3 + 1), (x2 - x1) << 16 / (y1 - y2 + 1), (x3 - x2) << 16 / (y2 - y3 + 1), y1 - y2, y1 - y3) PUB finish '' Wait for any current graphics command to finish '' use this to insure that it is safe to manually manipulate the bitmap 'setcommand(_loop, 0) 'make sure last command finished setcommand(constant((@loop-@waste)>>2), 0) PUB setXOR setcommand(constant((@arg0-@waste)>>2),@setXOR_) PUB setOverWrite setcommand(constant((@arg0-@waste)>>2),@setOverWrite_) PUB setFontPtr(fontBase)|_arg1,_arg2 longmove(_arg1,setFontPtr_,2) setcommand(constant((@arg1-@waste)>>2),@fontBase) PUB drawGlyph(x,y,xr,yr,angle,pixrot,pixdef_ptr,glyph) ' or (x,y,pixrot,0,0,0,pixdef_ptr,glyph) for non rotate 'pixdef_ptr:=@theGlyph if angle==0 setcommand(constant((@drawGlyph_-@waste)>>2),@x) else setcommand(constant((@drawGlyphArc_-@waste)>>2),@x) PUB pixelColor(qx,qy): qc | sad 'recall the color of a pixel at x,y 'There are 16 pixles in every long, so to get the long with our pixel in it we need to blank off the last 2 bits return (long[bitmap_base+qx*2+qy*4]>>qx//16)&%11 ' sad:=bitmap_base+(qx&12)+((191-qy)*4)+(qx&240)*48 'get the byte address of pixel x,y ' qc:=byte[sad]>>((qx&3)*2)&3 'get the desired pixel's color out of the 4-pixel group PRI fill(x, y, da, db, db2, linechange, lines_minus_1) 'setcommand(_fill, @x) setcommand(constant((@fill_-@waste)>>2), @x) PRI justify(string_ptr, justptr) | x x := (strsize(string_ptr) - 1) * text_xs * text_sp + text_xs * 5 - 1 long[justptr] := -lookupz(text_just >> 2 & 3: 0, x >> 1, x, 0) long[justptr][1] := -lookupz(text_just & 3: 0, text_ys << 3, text_ys << 4, 0) PRI setcommand(cmd, argptr) command := cmd <<16 + argptr 'write command and pointer repeat while command 'wait for command to be cleared, signifying receipt CON ' Vector font primitives xa0 = %000 << 0 'x line start / arc center xa1 = %001 << 0 xa2 = %010 << 0 xa3 = %011 << 0 xa4 = %100 << 0 xa5 = %101 << 0 xa6 = %110 << 0 xa7 = %111 << 0 ya0 = %0000 << 3 'y line start / arc center ya1 = %0001 << 3 ya2 = %0010 << 3 ya3 = %0011 << 3 ya4 = %0100 << 3 ya5 = %0101 << 3 ya6 = %0110 << 3 ya7 = %0111 << 3 ya8 = %1000 << 3 ya9 = %1001 << 3 yaA = %1010 << 3 yaB = %1011 << 3 yaC = %1100 << 3 yaD = %1101 << 3 yaE = %1110 << 3 yaF = %1111 << 3 xb0 = %000 << 7 'x line end xb1 = %001 << 7 xb2 = %010 << 7 xb3 = %011 << 7 xb4 = %100 << 7 xb5 = %101 << 7 xb6 = %110 << 7 xb7 = %111 << 7 yb0 = %0000 << 10 'y line end yb1 = %0001 << 10 yb2 = %0010 << 10 yb3 = %0011 << 10 yb4 = %0100 << 10 yb5 = %0101 << 10 yb6 = %0110 << 10 yb7 = %0111 << 10 yb8 = %1000 << 10 yb9 = %1001 << 10 ybA = %1010 << 10 ybB = %1011 << 10 ybC = %1100 << 10 ybD = %1101 << 10 ybE = %1110 << 10 ybF = %1111 << 10 ax1 = %0 << 7 'x arc radius ax2 = %1 << 7 ay1 = %00 << 8 'y arc radius ay2 = %01 << 8 ay3 = %10 << 8 ay4 = %11 << 8 a0 = %0000 << 10 'arc start/length a1 = %0001 << 10 'bits[1..0] = start (0..3 = 0°, 90°, 180°, 270°) a2 = %0010 << 10 'bits[3..2] = length (0..3 = 360°, 270°, 180°, 90°) a3 = %0011 << 10 a4 = %0100 << 10 a5 = %0101 << 10 a6 = %0110 << 10 a7 = %0111 << 10 a8 = %1000 << 10 a9 = %1001 << 10 aA = %1010 << 10 aB = %1011 << 10 aC = %1100 << 10 aD = %1101 << 10 aE = %1110 << 10 aF = %1111 << 10 fline = %0 << 14 'line command farc = %1 << 14 'arc command more = %1 << 15 'another arc/line DAT ' Color codes colors long %%0000000000000000 long %%1111111111111111 long %%2222222222222222 long %%3333333333333333 ' Round pixel recipes pixels byte %00000000,%00000000,%00000000,%00000000 '0,1,2,3 byte %00000000,%00000000,%00000010,%00000101 '4,5,6,7 byte %00001010,%00001010,%00011010,%00011010 '8,9,A,B byte %00110100,%00111010,%01110100,%01110100 'C,D,E,F ' Vector font - standard ascii characters ($21-$7E) font word fline + xa2 + yaC + xb2 + yb7 + more '! word fline + xa2 + ya5 + xb2 + yb4 word fline + xa1 + yaD + xb1 + ybC + more '" word fline + xa3 + yaD + xb3 + ybC word fline + xa1 + yaA + xb1 + yb6 + more '# word fline + xa3 + yaA + xb3 + yb6 + more word fline + xa0 + ya9 + xb4 + yb9 + more word fline + xa0 + ya7 + xb4 + yb7 word farc + xa2 + ya9 + a9 + ax2 + ay1 + more '$ word farc + xa2 + ya7 + aB + ax2 + ay1 + more word fline + xa0 + ya6 + xb2 + yb6 + more word fline + xa2 + yaA + xb4 + ybA + more word fline + xa2 + yaA + xb2 + ybB + more word fline + xa2 + ya6 + xb2 + yb5 word farc + xa1 + yaA + a0 + ax1 + ay1 + more '% word farc + xa3 + ya6 + a0 + ax1 + ay1 + more word fline + xa0 + ya6 + xb4 + ybA word farc + xa2 + yaA + a7 + ax1 + ay1 + more '& word farc + xa2 + ya7 + a5 + ax2 + ay2 + more word fline + xa1 + yaA + xb4 + yb5 word fline + xa2 + yaD + xb2 + ybC ' ' word farc + xa3 + ya9 + aD + ax1 + ay4 + more '( word farc + xa3 + ya7 + aE + ax1 + ay4 + more word fline + xa2 + ya7 + xb2 + yb9 word farc + xa1 + ya9 + aC + ax1 + ay4 + more ') word farc + xa1 + ya7 + aF + ax1 + ay4 + more word fline + xa2 + ya7 + xb2 + yb9 word fline + xa4 + ya6 + xb0 + ybA + more '* word fline + xa0 + ya6 + xb4 + ybA + more word fline + xa2 + yaB + xb2 + yb5 word fline + xa0 + ya8 + xb4 + yb8 + more '+ word fline + xa2 + yaA + xb2 + yb6 word fline + xa2 + ya4 + xb1 + yb3 ', word fline + xa0 + ya8 + xb4 + yb8 '- word fline + xa2 + ya5 + xb2 + yb4 '. word fline + xa0 + ya4 + xb4 + ybC '/ word farc + xa2 + ya8 + a0 + ax2 + ay4 '0 word fline + xa0 + ya4 + xb4 + yb4 + more '1 word fline + xa2 + ya4 + xb2 + ybC + more word fline + xa0 + yaA + xb2 + ybC word farc + xa2 + yaA + a8 + ax2 + ay2 + more '2 word farc + xa2 + yaA + aF + ax2 + ay3 + more word farc + xa2 + ya4 + aD + ax2 + ay3 + more word fline + xa0 + ya4 + xb4 + yb4 word farc + xa2 + yaA + a7 + ax2 + ay2 + more '3 word farc + xa2 + ya6 + a6 + ax2 + ay2 word fline + xa2 + yaC + xb0 + yb7 + more '4 word fline + xa0 + ya7 + xb4 + yb7 + more word fline + xa3 + ya4 + xb3 + yb8 word farc + xa2 + ya6 + aB + ax2 + ay2 + more '5 word fline + xa4 + yaC + xb0 + ybC + more word fline + xa0 + yaC + xb0 + yb8 + more word fline + xa0 + ya8 + xb2 + yb8 + more word fline + xa0 + ya4 + xb2 + yb4 word farc + xa2 + ya6 + a0 + ax2 + ay2 + more '6 word farc + xa2 + ya8 + aD + ax2 + ay4 + more word fline + xa0 + ya6 + xb0 + yb8 + more word fline + xa2 + yaC + xb3 + ybC word fline + xa0 + yaC + xb4 + ybC + more '7 word fline + xa1 + ya4 + xb4 + ybC word farc + xa2 + ya6 + a0 + ax2 + ay2 + more '8 word farc + xa2 + yaA + a0 + ax2 + ay2 word farc + xa2 + yaA + a0 + ax2 + ay2 + more '9 word farc + xa2 + ya8 + aF + ax2 + ay4 + more word fline + xa4 + ya8 + xb4 + ybA + more word fline + xa1 + ya4 + xb2 + yb4 word fline + xa2 + ya6 + xb2 + yb7 + more ': word fline + xa2 + yaA + xb2 + yb9 word fline + xa2 + ya4 + xb1 + yb3 + more '; word fline + xa2 + ya8 + xb2 + yb7 word fline + xa0 + ya8 + xb4 + ybA + more '< word fline + xa0 + ya8 + xb4 + yb6 word fline + xa0 + yaA + xb4 + ybA + more '= word fline + xa0 + ya6 + xb4 + yb6 word fline + xa4 + ya8 + xb0 + ybA + more '> word fline + xa4 + ya8 + xb0 + yb6 word farc + xa2 + yaB + a8 + ax2 + ay1 + more '? word farc + xa3 + yaB + aF + ax1 + ay2 + more word farc + xa3 + ya7 + aD + ax1 + ay2 + more word fline + xa2 + ya5 + xb2 + yb4 word farc + xa2 + ya8 + a0 + ax1 + ay1 + more '@ word farc + xa2 + ya8 + a4 + ax2 + ay3 + more word farc + xa3 + ya8 + aF + ax1 + ay1 + more word farc + xa2 + ya6 + aF + ax2 + ay1 + more word fline + xa3 + ya7 + xb3 + yb9 word farc + xa2 + yaA + a8 + ax2 + ay2 + more 'A word fline + xa0 + ya4 + xb0 + ybA + more word fline + xa4 + ya4 + xb4 + ybA + more word fline + xa0 + ya8 + xb4 + yb8 word farc + xa2 + yaA + aB + ax2 + ay2 + more 'B word farc + xa2 + ya6 + aB + ax2 + ay2 + more word fline + xa0 + ya4 + xb0 + ybC + more word fline + xa0 + ya4 + xb2 + yb4 + more word fline + xa0 + ya8 + xb2 + yb8 + more word fline + xa0 + yaC + xb2 + ybC word farc + xa2 + yaA + a8 + ax2 + ay2 + more 'C word farc + xa2 + ya6 + aA + ax2 + ay2 + more word fline + xa0 + ya6 + xb0 + ybA word farc + xa2 + yaA + aC + ax2 + ay2 + more 'D word farc + xa2 + ya6 + aF + ax2 + ay2 + more word fline + xa0 + ya4 + xb0 + ybC + more word fline + xa4 + ya6 + xb4 + ybA + more word fline + xa0 + ya4 + xb2 + yb4 + more word fline + xa0 + yaC + xb2 + ybC word fline + xa0 + ya4 + xb0 + ybC + more 'E word fline + xa0 + ya4 + xb4 + yb4 + more word fline + xa0 + ya8 + xb3 + yb8 + more word fline + xa0 + yaC + xb4 + ybC word fline + xa0 + ya4 + xb0 + ybC + more 'F word fline + xa0 + ya8 + xb3 + yb8 + more word fline + xa0 + yaC + xb4 + ybC word farc + xa2 + yaA + a8 + ax2 + ay2 + more 'G word farc + xa2 + ya6 + aA + ax2 + ay2 + more word fline + xa0 + ya6 + xb0 + ybA + more word fline + xa4 + ya4 + xb4 + yb7 + more word fline + xa3 + ya7 + xb4 + yb7 word fline + xa0 + ya4 + xb0 + ybC + more 'H word fline + xa4 + ya4 + xb4 + ybC + more word fline + xa0 + ya8 + xb4 + yb8 word fline + xa2 + ya4 + xb2 + ybC + more 'I word fline + xa0 + ya4 + xb4 + yb4 + more word fline + xa0 + yaC + xb4 + ybC word farc + xa2 + ya6 + aA + ax2 + ay2 + more 'J word fline + xa4 + ya6 + xb4 + ybC word fline + xa0 + ya4 + xb0 + ybC + more 'K word fline + xa4 + yaC + xb0 + yb8 + more word fline + xa4 + ya4 + xb0 + yb8 word fline + xa0 + ya4 + xb0 + ybC + more 'L word fline + xa0 + ya4 + xb4 + yb4 word fline + xa0 + ya4 + xb0 + ybC + more 'M word fline + xa4 + ya4 + xb4 + ybC + more word fline + xa2 + ya8 + xb0 + ybC + more word fline + xa2 + ya8 + xb4 + ybC word fline + xa0 + ya4 + xb0 + ybC + more 'N word fline + xa4 + ya4 + xb4 + ybC + more word fline + xa4 + ya4 + xb0 + ybC word farc + xa2 + yaA + a8 + ax2 + ay2 + more '0 word farc + xa2 + ya6 + aA + ax2 + ay2 + more word fline + xa0 + ya6 + xb0 + ybA + more word fline + xa4 + ya6 + xb4 + ybA word farc + xa2 + yaA + aB + ax2 + ay2 + more 'P word fline + xa0 + ya4 + xb0 + ybC + more word fline + xa0 + ya8 + xb2 + yb8 + more word fline + xa0 + yaC + xb2 + ybC word farc + xa2 + yaA + a8 + ax2 + ay2 + more 'Q word farc + xa2 + ya6 + aA + ax2 + ay2 + more word fline + xa0 + ya6 + xb0 + ybA + more word fline + xa4 + ya6 + xb4 + ybA + more word fline + xa2 + ya6 + xb4 + yb3 word farc + xa2 + yaA + aB + ax2 + ay2 + more 'R word fline + xa0 + ya4 + xb0 + ybC + more word fline + xa0 + ya8 + xb2 + yb8 + more word fline + xa0 + yaC + xb2 + ybC + more word fline + xa4 + ya4 + xb2 + yb8 word farc + xa2 + yaA + a4 + ax2 + ay2 + more 'S word farc + xa2 + ya6 + a6 + ax2 + ay2 word fline + xa2 + ya4 + xb2 + ybC + more 'T word fline + xa0 + yaC + xb4 + ybC word farc + xa2 + ya6 + aA + ax2 + ay2 + more 'U word fline + xa0 + ya6 + xb0 + ybC + more word fline + xa4 + ya6 + xb4 + ybC word fline + xa2 + ya4 + xb0 + ybC + more 'V word fline + xa2 + ya4 + xb4 + ybC word fline + xa0 + yaC + xb0 + yb4 + more 'W word fline + xa4 + yaC + xb4 + yb4 + more word fline + xa1 + ya8 + xb1 + yb4 + more word fline + xa2 + ya8 + xb3 + yb4 word fline + xa4 + ya4 + xb0 + ybC + more 'X word fline + xa0 + ya4 + xb4 + ybC word fline + xa0 + yaC + xb2 + yb8 + more 'Y word fline + xa4 + yaC + xb2 + yb8 + more word fline + xa2 + ya4 + xb2 + yb8 word fline + xa0 + yaC + xb4 + ybC + more 'Z word fline + xa0 + ya4 + xb4 + ybC + more word fline + xa0 + ya4 + xb4 + yb4 word fline + xa2 + yaD + xb2 + yb3 + more '[ word fline + xa2 + yaD + xb4 + ybD + more word fline + xa2 + ya3 + xb4 + yb3 word fline + xa4 + ya4 + xb0 + ybC '\ word fline + xa2 + yaD + xb2 + yb3 + more '[ word fline + xa2 + yaD + xb0 + ybD + more word fline + xa2 + ya3 + xb0 + yb3 word fline + xa2 + yaA + xb0 + yb6 + more '^ word fline + xa2 + yaA + xb4 + yb6 word fline + xa0 + ya1 + xa4 + yb1 '_ word fline + xa1 + ya9 + xb3 + yb7 '` word farc + xa2 + ya6 + a0 + ax2 + ay2 + more 'a word fline + xa4 + ya4 + xb4 + yb8 word farc + xa2 + ya6 + a0 + ax2 + ay2 + more 'b word fline + xa0 + ya4 + xb0 + ybC word farc + xa2 + ya6 + a9 + ax2 + ay2 + more 'c word fline + xa2 + ya4 + xb4 + yb4 + more word fline + xa2 + ya8 + xb4 + yb8 word farc + xa2 + ya6 + a0 + ax2 + ay2 + more 'd word fline + xa4 + ya4 + xb4 + ybC word farc + xa2 + ya6 + a4 + ax2 + ay2 + more 'e word fline + xa0 + ya6 + xb4 + yb6 + more word fline + xa2 + ya4 + xb4 + yb4 word farc + xa4 + yaA + aD + ax2 + ay2 + more 'f word fline + xa0 + ya8 + xb4 + yb8 + more word fline + xa2 + ya4 + xb2 + ybA word farc + xa2 + ya6 + a0 + ax2 + ay2 + more 'g word farc + xa2 + ya3 + aF + ax2 + ay2 + more word fline + xa4 + ya3 + xb4 + yb8 + more word fline + xa1 + ya1 + xb2 + yb1 word farc + xa2 + ya6 + a8 + ax2 + ay2 + more 'h word fline + xa0 + ya4 + xb0 + ybC + more word fline + xa4 + ya4 + xb4 + yb6 'word fline + xa1 + ya4 + xb3 + yb4 + more 'i word fline + xa2 + ya4 + xb2 + yb8 + more 'word fline + xa1 + ya8 + xb2 + yb8 + more word fline + xa2 + yaB + xb2 + ybA word farc + xa0 + ya3 + aF + ax2 + ay2 + more 'j word fline + xa2 + ya3 + xb2 + yb8 + more word fline + xa1 + ya8 + xb2 + yb8 + more word fline + xa2 + yaB + xb2 + ybA word fline + xa0 + ya4 + xb0 + ybC + more 'k word fline + xa0 + ya6 + xb2 + yb6 + more word fline + xa2 + ya6 + xb4 + yb8 + more word fline + xa2 + ya6 + xb4 + yb4 word fline + xa1 + ya4 + xb3 + yb4 + more 'l word fline + xa2 + ya4 + xb2 + ybC + more word fline + xa1 + yaC + xb2 + ybC word farc + xa1 + ya7 + a8 + ax1 + ay1 + more 'm word farc + xa3 + ya7 + a8 + ax1 + ay1 + more word fline + xa0 + ya4 + xb0 + yb8 + more word fline + xa2 + ya4 + xb2 + yb7 + more word fline + xa4 + ya4 + xb4 + yb7 word farc + xa2 + ya6 + a8 + ax2 + ay2 + more 'n word fline + xa0 + ya4 + xb0 + yb8 + more word fline + xa4 + ya4 + xb4 + yb6 word farc + xa2 + ya6 + a0 + ax2 + ay2 'o word farc + xa2 + ya6 + a0 + ax2 + ay2 + more 'p word fline + xa0 + ya1 + xb0 + yb8 word farc + xa2 + ya6 + a0 + ax2 + ay2 + more 'q word fline + xa4 + ya1 + xb4 + yb8 word farc + xa2 + ya7 + a8 + ax2 + ay1 + more 'r word fline + xa0 + ya4 + xb0 + yb8 word farc + xa2 + ya7 + a9 + ax2 + ay1 + more 's word farc + xa2 + ya5 + aB + ax2 + ay1 + more word fline + xa0 + ya4 + xb2 + yb4 + more word fline + xa2 + ya8 + xb4 + yb8 'word farc + xa4 + ya6 + aE + ax2 + ay2 + more 't word fline + xa0 + ya8 + xb1 + yb8 + more word fline + xa3 + ya8 + xb4 + yb8 + more word fline + xa2 + ya4 + xb2 + ybA word farc + xa2 + ya6 + aA + ax2 + ay2 + more 'u word fline + xa0 + ya6 + xb0 + yb8 + more word fline + xa4 + ya4 + xb4 + yb8 word fline + xa0 + ya8 + xb2 + yb4 + more 'v word fline + xa4 + ya8 + xb2 + yb4 word farc + xa1 + ya5 + aA + ax1 + ay1 + more 'w word farc + xa3 + ya5 + aA + ax1 + ay1 + more word fline + xa0 + ya5 + xb0 + yb8 + more word fline + xa2 + ya5 + xb2 + yb6 + more word fline + xa4 + ya5 + xb4 + yb8 word fline + xa0 + ya8 + xb4 + yb4 + more 'x word fline + xa0 + ya4 + xb4 + yb8 word farc + xa2 + ya6 + aA + ax2 + ay2 + more 'y word farc + xa2 + ya3 + aF + ax2 + ay2 + more word fline + xa4 + ya3 + xb4 + yb8 + more word fline + xa0 + ya6 + xb0 + yb8 + more word fline + xa1 + ya1 + xb2 + yb1 word fline + xa0 + ya8 + xb4 + yb8 + more 'z word fline + xa4 + ya8 + xb0 + yb4 + more word fline + xa0 + ya4 + xb4 + yb4 word farc + xa3 + yaA + aD + ax1 + ay3 + more '{ word farc + xa1 + ya6 + aC + ax1 + ay2 + more word farc + xa1 + yaA + aF + ax1 + ay2 + more word farc + xa3 + ya6 + aE + ax1 + ay3 word fline + xa2 + ya3 + xb2 + ybD '| word farc + xa1 + yaA + aC + ax1 + ay3 + more '} word farc + xa3 + ya6 + aD + ax1 + ay2 + more word farc + xa3 + yaA + aE + ax1 + ay2 + more word farc + xa1 + ya6 + aF + ax1 + ay3 word farc + xa1 + ya8 + a8 + ax1 + ay1 + more '~ word farc + xa3 + ya8 + aA + ax1 + ay1 ' Vector font - custom characters ($7F+) word fline + xa2 + ya9 + xb0 + yb4 + more 'delta word fline + xa2 + ya9 + xb4 + yb4 + more word fline + xa0 + ya4 + xb4 + yb4 word farc + xa2 + ya7 + a8 + ax2 + ay2 + more 'omega word farc + xa1 + ya7 + aE + ax1 + ay2 + more word farc + xa3 + ya7 + aF + ax1 + ay2 + more word fline + xa1 + ya5 + xb1 + yb4 + more word fline + xa3 + ya5 + xb3 + yb4 + more word fline + xa0 + ya4 + xb1 + yb4 + more word fline + xa4 + ya4 + xb3 + yb4 word farc + xa2 + ya8 + a0 + ax1 + ay1 'bullet CON fx = 3 'number of custom characters DAT '************************************* '* Assembly language graphics driver * '************************************* org 0 ' ' ' Graphics driver - main loop ' waste long 0 loop rdlong t1,par wz 'wait for command if_z jmp #loop movd :arg,#arg0 'get 8 arguments mov t2,t1 mov t3,#8 :arg rdlong arg0,t2 'this gets modified by the next instruction add :arg,d0 'this changes where we store the argument add t2,#4 'this changes where we read the argument from djnz t3,#:arg wrlong zero,par 'zero command to signify received call #setd 'set dx,dy from arg0,arg1 ror t1,#16 'get the cog location of the command jmp t1 'and jump to it ' ' ' setup(x_tiles, y_tiles*16, x_origin, y_origin, base_ptr) bases_ptr, slices_ptr ' setup_ mov xlongs,arg0 'set xlongs, ylongs mov ylongs,arg1 mov xorigin,arg2 'set xorigin, yorigin 'set these to 0 so we don't need them mov yorigin,arg3 mov basesptr,arg5 'set pointers mov slicesptr,arg6 jmp #loop ' ' ' plot(x, y) can move this out of cog (2 longs) ' plot_ call #plotd jmp #loop ' ' ' line(x, y) can move this out of cog (2 longs) ' line_ call #linepd jmp #loop pixCall_ JMPRET pixret_,#pix_ jmp #loop pixArcCall_ JMPRET pixret_,#pixArc_ jmp #loop ' ' ' arc(x, y, xr, yr, angle, anglestep, iterations, mode) ' arc_ and arg7,#3 'limit mode :loop call #arca 'get arc dx,dy cmp arg7,#1 wz 'if not mode 1, set px,py if_nz mov px,dx if_nz mov py,dy tjz arg6,#loop 'if no points exit with new px,py cmp arg7,#3 wz 'if mode 3, set center if_z call #setd test arg7,#1 wz 'if mode 0 or 2, plot point if_z call #plotp test arg7,#1 wz 'if mode 1 or 3, plot line if_nz call #linepd cmp arg7,#2 wz 'if mode 2, set mode 1 if_z mov arg7,#1 add arg4,arg5 'step angle djnz arg6,#:loop 'loop if more iterations jmp #loop ' ' ' vec(x, y, vecscale, vecangle, vecdef_ptr) ' vecarc(x, y, xr, yr, angle, vecscale, vecangle, vecdef_ptr) ' ' vecdef: word $8000/$4000+angle 'vector mode + 13-bit angle (mode: $4000=plot, $8000=line) ' word length 'vector length ' ... 'more vectors ' ... ' word 0 'end of definition ' vecarc_ call #arcmod vec_ tjz arg2,#loop 'if scale 0, exit :loop rdword t7,arg4 wz 'get vector mode+angle add arg4,#2 if_z jmp #loop 'if mode+angle 0, exit rdword t1,arg4 'get vector length add arg4,#2 'setup for next read abs t2,arg2 wc 'add/sub(scale for normal) vector angle to/from angle mov t6,arg3 sumc t6,t7 call #multiply 'multiply length by scale add t1,#$80 'round up 1/2 lsb shr t1,#8 mov t4,t1 'get arc dx,dy mov t5,t1 call #arcd test t7,h8000 wc 'plot pixel or draw line? if_nc call #plotd test t7,h8000 wc if_c call #linepd jmp #:loop 'get next vector ' ' ' pix(x, y, pixrot, pixdef_ptr) ' pixarc(x, y, xr, yr, angle, pixrot, pixdef_ptr) ' ' pixdef: word ' byte xwords, ywords, xorigin, yorigin ' word %%xxxxxxxx,%%xxxxxxxx ' word %%xxxxxxxx,%%xxxxxxxx ' word %%xxxxxxxx,%%xxxxxxxx ' ... ' pixarc_ call #arcmod pix_ mov t6,pcolor 'save color mov px,dx 'get center into px,py mov py,dy mov sy,pwidth 'get actual pixel width add sy,#1 rdbyte dx,arg3 'get dimensions into dx,dy add arg3,#1 rdbyte dy,arg3 add arg3,#1 rdbyte t1,arg3 'get origin and adjust px,py add arg3,#1 rdbyte t2,arg3 add arg3,#1 neg t2,t2 sub t2,#1 add t2,dy mov t3,sy :adjust test arg2,#%001 wz test arg2,#%110 wc if_z sumnc px,t1 if_nz sumc py,t1 test arg2,#%010 wc if_nz sumnc px,t2 if_z sumnc py,t2 djnz t3,#:adjust :yline mov sx,#0 'plot entire pix mov t3,dx :xword rdword t4,arg3 'read next pix word add arg3,#2 shl t4,#16 mov t5,#8 :xpixel rol t4,#2 'plot pixel within word test t4,#1 wc 'set color muxc pcolor,color1 test t4,#2 wc muxc pcolor,color2 wz '(z=1 if color=0) if_nz call #plotp test arg2,#%001 wz 'update px,py for next x test arg2,#%110 wc if_z sumc px,sy if_nz sumnc py,sy add sx,sy djnz t5,#:xpixel 'another x pixel? djnz t3,#:xword 'another x word? if_z sumnc px,sx 'update px,py for next y if_nz sumc py,sx test arg2,#%010 wc if_nz sumc px,sy if_z sumc py,sy djnz dy,#:yline 'another y line? mov pcolor,t6 'restore color ' jmp #loop pixret_ ret ' ' ' text(x, y, @string) justx, justy ' 0 1 2 3 4 ' textarc(x, y, xr, yr, angle, @string) justx, justy ' 0 1 2 3 4 5 6 7 textarc_ call #arcmod text_ add arg3,arg0 'add x into justx add arg4,arg1 'add y into justy chr rdbyte t1,arg2 wz 'get chr add arg2,#1 'increment chr pointer if_z jmp #loop 'if 0, done 'would replace from here down to setd replaceStart sub t1,#$21 'if chr out of range, skip cmp t1,#$7F-$21+fx wc if_nc jmp #skip1 mov arg5,fontptr 'scan font for chr definition scan tjz t1,#def 't1 is character-21 rdword t2,arg5 'goes through t1 times which will get to the add arg5,#2 'start of the desired character test t2,h8000 wc if_nc sub t1,#1 jmp #scan def rdword t7,arg5 'get font definition word add arg5,#2 'point to next word call #fontxy 'extract initial x,y test t7,#$80 wc 'arc or line? if_nc jmp #line1 mov t2,textsx 'arc, extract x radius mov t3,#%0001_0001_1 call #fontb mov t4,t1 mov t2,textsy 'extract y radius mov t3,#%0010_0011_1 call #fontb mov t5,t1 mov t2,#1 'extract starting angle mov t3,#%0010_0011_0 call #fontb shl t1,#11 mov t6,t1 'extract angle sweep mov t3,#%0010_0011_0 call #fontb neg arg6,t1 shl arg6,#4 add arg6,#65 call #arcd 'plot initial arc point call #plotd arc1 call #arcd 'connect subsequent arc points with lines call #linepd add t6,#$80 djnz arg6,#arc1 jmp #more1 line1 call #plotd 'line, plot initial x,y call #fontxy 'extract terminal x,y call #linepd 'draw line more1 test t7,#$02 wc 'more font definition? if_c jmp #def skip1 mov t1,textsp 'advance x to next chr position mov t2,textsx call #multiply add arg3,t1 jmp #chr 'get next chr 'can't replace past here or need to jump back to chr fontxy mov t2,textsx 'extract x mov t3,#%0011_0111_0 call #fontb 't2 - x_scale mov arg0,t1 't3 - mask for something could drop the 0 on the end and save a couple more longs add arg0,arg3 mov t2,textsy 'extract y mov t3,#%0100_1111_0 call #fontb mov arg1,t1 add arg1,arg4 'may have to put a jmp to setd here 'can use down to here which is I think 60 longs setd mov dx,xorigin 'set dx,dy from arg0,arg1 add dx,arg0 'have to make sure that this does not get mov dy,yorigin 'overwritten as it gets called at the start sub dy,arg1 'of every operation setd_ret fontxy_ret ret fontb mov t1,t7 'extract bitrange from font word shr t3,#1 wc 't1 - t7 - font definition work and t1,t3 't3 - mask - %0100_1111 if_c add t1,#1 shr t3,#4 't3 - %0100 or %0011 shr t7,t3 'shift right 4 or 3 shl t1,#32-4 'multiply t1[3..0] by t2 mov t3,#4 :loop shl t1,#1 wc if_c add t1,t2 djnz t3,#:loop fontb_ret ret ' ' ' fill(x, y, da, db, db2, linechange, lines_minus_1) ' 0 1 2 3 4 5 6 fill_ shl dx,#16 'get left and right fractions or dx,h8000 'dx:=(dx<<16)|$8000 mov t1,dx 't1:=dx mov t2,xlongs 'get x pixels shl t2,#4 't2:=xlongs<<4 add arg6,#1 'pre-increment line counter 'arg6++ yloop add dx,arg2 'adjust left and right fractions 'dx:=dx+da add t1,arg3 't1:=t1+db cmps dx,t1 wc 'get left and right integers if_c mov base0,dx if_c mov base1,t1 if_nc mov base0,t1 if_nc mov base1,dx sar base0,#16 sar base1,#16 cmps base0,t2 wc 'left out of range? if_c cmps hFFFFFFFF,base1 wc 'right out of range? if_c cmp dy,ylongs wc 'y out of range? if_nc jmp #skip2 'if any, skip mins base0,#0 'limit left and right maxs base1,t2 wc if_nc sub base1,#1 shl base0,#1 'make left mask neg mask0,#1 shl mask0,base0 shr base0,#5 shl base1,#1 'make right mask xor base1,#$1E neg mask1,#1 shr mask1,base1 shr base1,#5 sub base1,base0 wz 'ready long count add base1,#1 if_z and mask0,mask1 'if single long, merge masks shl base0,#1 'get long base add base0,basesptr rdword base0,base0 shl dy,#2 add base0,dy shr dy,#2 mov bits0,mask0 'ready left mask xloop mov bits1,pcolor 'make color mask and bits1,bits0 rdlong pass,base0 'read-modify-write long fill1 andn pass,bits0 fill2 or pass,bits1 wrlong pass,base0 shl ylongs,#2 'advance to next long add base0,ylongs shr ylongs,#2 cmp base1,#2 wz 'one more? if_nz neg bits0,#1 'if not, ready full mask if_z mov bits0,mask1 'if one more, ready right mask djnz base1,#xloop 'loop if more longs skip2 sub arg5,#1 wc 'delta change? if_c mov arg3,arg4 'if so, set new deltas {:same} add dy,#1 'adjust y djnz arg6,#yloop 'another y? jmp #loop ' ' ' Plot line from px,py to dx,dy ' linepd cmps dx,px wc, wr 'get x difference negc sx,#1 'set x direction cmps dy,py wc, wr 'get y difference negc sy,#1 'set y direction abs dx,dx 'make differences absolute abs dy,dy cmp dx,dy wc 'determine dominant axis if_nc tjz dx,#:last 'if both differences 0, plot single pixel if_nc mov count,dx 'set pixel count if_c mov count,dy mov ratio,count 'set initial ratio shr ratio,#1 if_c jmp #:yloop 'x or y dominant? :xloop add px,sx 'move plotp to end sub ratio,dy wc if_c add ratio,dx if_c add py,sy call #plotp djnz count,#:xloop jmp #:last 'plot last pixel :yloop add py,sy sub ratio,dx wc if_c add ratio,dy if_c add px,sx call #plotp djnz count,#:yloop :last linepd_ret ret ' ' ' Plot pixel at px,py ' plotd mov px,dx 'set px,py to dx,dy mov py,dy plotp tjnz pwidth,#wplot 'if width > 0, do wide plot mov t1,px 'compute pixel mask shl t1,#1 mov mask0,#%11 shl mask0,t1 shr t1,#5 cmp t1,xlongs wc 'if x or y out of bounds, exit if_c cmp py,ylongs wc if_nc jmp #plotp_ret mov bits0,pcolor 'compute pixel bits and bits0,mask0 shl t1,#1 'get address of pixel long add t1,basesptr mov t2,py rdword t1,t1 shl t2,#2 add t1,t2 rdlong t2,t1 'write pixel plotp1 andn t2,mask0 plotp2 or t2,bits0 wrlong t2,t1 plotp_ret plotd_ret ret ' ' ' Plot wide pixel ' wplot mov t1,py 'if y out of bounds, exit add t1,#7 mov t2,ylongs add t2,#7+8 cmp t1,t2 wc if_nc jmp #plotp_ret mov t1,px 'determine x long pair sub t1,#8 sar t1,#4 cmp t1,xlongs wc muxc waste,#%01 '(use jumps[1..0] to store writes) add t1,#1 cmp t1,xlongs wc muxc waste,#%10 test waste,#%11 wz 'if x out of bounds, exit if_z jmp #plotp_ret shl t1,#1 'get base pair add t1,basesptr rdword base1,t1 sub t1,#2 rdword base0,t1 mov t1,px 'determine pair shifts shl t1,#1 movs :shift1,t1 xor :shift1,#7<<1 add t1,#9<<1 movs :shift0,t1 test t1,#$F<<1 wz '(account for special case) if_z andn waste,#%01 mov pass,#0 'ready to plot slices mov slice,slicesptr :loop rdlong mask0,slice 'get next slice mov mask1,mask0 :shift0 shl mask0,#0 'position slice :shift1 shr mask1,#0 mov bits0,pcolor 'colorize slice and bits0,mask0 mov bits1,pcolor and bits1,mask1 mov t1,py 'plot lower slice add t1,pass cmp t1,ylongs wc if_c call #wslice mov t1,py 'plot upper slice test pwidth,#1 wc subx t1,pass cmp t1,ylongs wc if_c call #wslice add slice,#4 'next slice add pass,#1 cmp pass,passes wz if_nz jmp #:loop jmp #plotp_ret ' ' ' Plot wide pixel slice ' wslice shl t1,#2 'ready long offset add base0,t1 'plot left slice test waste,#%01 wc if_c rdlong t2,base0 wslice1 if_c andn t2,mask0 wslice2 if_c or t2,bits0 if_c wrlong t2,base0 add base1,t1 'plot right slice test waste,#%10 wc if_c rdlong t2,base1 wslice3 if_c andn t2,mask1 wslice4 if_c or t2,bits1 if_c wrlong t2,base1 sub base0,t1 'restore bases sub base1,t1 wslice_ret ret ' ' ' Get arc point from args and then move args 5..7 to 2..4 ' arcmod call #arca 'get arc using first 5 args mov arg0,dx 'set arg0,arg1 sub arg0,xorigin mov arg1,yorigin sub arg1,dy mov arg2,arg5 'move args 5..7 to 2..4 mov arg3,arg6 mov arg4,arg7 arcmod_ret ret ' ' ' Get arc dx,dy from arg0,arg1 ' ' in: arg0,arg1 = center x,y ' arg2/t4 = x length ' arg3/t5 = y length ' arg4/t6 = 13-bit angle ' ' out: dx,dy = arc point ' arca mov t4,arg2 'use args mov t5,arg3 mov t6,arg4 arcd call #setd 'reset dx,dy to arg0,arg1 mov t1,t6 'get arc dx mov t2,t4 call #polarx add dx,t1 mov t1,t6 'get arc dy mov t2,t5 call #polary sub dy,t1 arcd_ret arca_ret ret ' ' ' Polar to cartesian ' ' in: t1 = 13-bit angle ' t2 = 16-bit length ' ' out: t1 = x|y ' polarx add t1,sine_90 'cosine, add 90° for sine lookup polary test t1,sine_180 wz 'get sine quadrant 3|4 into nz test t1,sine_90 wc 'get sine quadrant 2|4 into c negc t1,t1 'if sine quadrant 2|4, negate table offset or t1,sine_table 'or in sine table address >> 1 shl t1,#1 'shift left to get final word address rdword t1,t1 'read sine/cosine word call #multiply 'multiply sine/cosine by length to get x|y add t1,h8000 'add 1/2 lsb to round up x|y fraction shr t1,#16 'justify x|y integer negnz t1,t1 'if sine quadrant 3|4, negate x|y polary_ret polarx_ret ret sine_90 long $0800 '90° bit sine_180 long $1000 '180° bit sine_table long $E000 >> 1 'sine table address shifted right ' ' ' Multiply ' ' in: t1 = 16-bit multiplicand (t1[31..16] must be 0) ' t2 = 16-bit multiplier ' ' out: t1 = 32-bit product ' multiply mov t3,#16 shl t2,#16 shr t1,#1 wc :loop if_c add t1,t2 wc rcr t1,#1 wc djnz t3,#:loop multiply_ret ret ' 'drawGlyphArc(x, y, xr, yr, angle, pixrot, pixdef_ptr, glyph) 'drawGlyph (x, y, pixrot, 0, 0, 0, pixdef_ptr, glyph) ' arg 0 1 2 3 4 5 6 7 drawGlyph_ drawGlyphArc_ ROR arg7,#1 WC SHL arg7,#7 ADD arg7,h8000 MOV t2,#64 MOV t1,arg6 ADD t1,#4 :loop RDWORD t3,arg7 REV t3,#16 IF_NC SHR t3,#1 AND t3,color1':_11111111 'MOV t4,t3 'don't need? 'SHL t4,#1 'don't need? 'OR t3,t4 'don't need? WRWORD t3,t1 ADD t1,#2 ADD arg7,#2 DJNZ t2,#:loop MOVS pixret_,#drawGlyphRet_ TJNZ arg3,#pixarc_ MOV arg3,arg6 JMP #pix_ drawGlyphRet_ JMP #loop ' ' ' Defined data ' zero long 0 'constants d0 long $200 h8000 long $8000 hFFFFFFFF long $FFFFFFFF color1 long %%1111111111111111 color2 long %%2222222222222222 fontptr long 0 'font pointer (set before cognew command) pcolor long %%1111111111111111 'pixel color pwidth long 0 'pixel width passes long 1 'pixel passes textsx long 1 'text scale x textsy long 1 'text scale y textsp long 6 'text spacing arg0 long 1 'arguments passed from high-level arg1 long 1 arg2 long 1 arg3 long 1 arg4 long 1 arg5 long 1 arg6 long 1 arg7 long 1 jmp #loop 'so we don't need the jmp in what we pass in ' ' ' Undefined data ' t1 res 1 'temps t2 res 1 t3 res 1 t4 res 1 t5 res 1 t6 res 1 t7 res 1 basesptr res 1 'pointers slicesptr res 1 xlongs res 1 'bitmap metrics ylongs res 1 xorigin res 1 yorigin res 1 dx res 1 'line/plot coordinates dy res 1 px res 1 py res 1 sx res 1 'line sy res 1 count res 1 ratio res 1 pass res 1 'plot slice res 1 base0 res 1 base1 res 1 mask0 res 1 mask1 res 1 bits0 res 1 bits1 res 1 fit 496 ' instr zcr setXOR_ movi plotp1,#%011001_000 'andn nr movi plotp2,#%011011_001 'xor wr movi wslice1,#%011001_000 'andn nr movi wslice2,#%011011_001 'xor wr movi wslice3,#%011001_000 'andn nr movi wslice4,#%011011_001 'xor wr movi fill1,#%011001_000 'andn nr movi fill2,#%011011_001 'xor wr setOverWrite_ movi plotp1,#%011001_001 'andn wr movi plotp2,#%011010_001 'or wr movi wslice1,#%011001_001 'andn wr movi wslice2,#%011010_001 'or wr movi wslice3,#%011001_001 'andn wr movi wslice4,#%011010_001 'or wr movi fill1,#%011001_001 'andn wr movi fill2,#%011010_001 'or wr ' ' ' textmode(x_scale, y_scale, spacing, justification) can move this out of cog (4 longs) ' textmode_ mov textsx,arg0 'set text x scale mov textsy,arg1 'set text y scale mov textsp,arg2 'set text spacing ' ' ' color(c) can move this out of cog (2 longs) ' color_ mov pcolor,arg0 'set pixel color jmp #loop ' ' ' width(w) pixel_passes can move this out of cog (3 longs) ' width_ mov pwidth,arg0 'set pixel width mov passes,arg1 'set pixel passes jmp #loop ' ' ' setFontPtr(c) can move this out of cog (2 longs) ' setFontPtr_ mov fontptr,arg0 'set pixel color jmp #loop theGlyph 'LONG 0 pixdef word 'crosshair byte 2,32,0,0 word 0[64] ' ' ' setFont(type) ' type 0-VECTOR, 1-ROM, 2-Clemens ' This just copies some code into the cog org arg0 setFont_ hubPtr long 0-0 'points to current long counter long 0-0 'length of code to copy icogptr movd cogPtr,#replaceStart 'allows to be used in other places if wanted cogPtr rdlong replaceStart,hubPtr add cogPtr,#$100 'increment cog pointer add cogPtr,#$100 add hubPtr,#4 'increment hub pointer djnz counter,#cogPtr 'jmp #loop 'is after args fit arg7+1 ' ' ' code used for drawing strings with the rom font ' org replaceStart drawGlyphText_ ROR t1,#1 WC SHL t1,#7 ADD t1,h8000 MOV t2,#64 MOV t5,glyphAddress ADD t5,#4 :loop RDWORD t3,t1 REV t3,#16 IF_NC SHR t3,#1 AND t3,color1 MOV t4,t3 'don't need? SHL t4,#1 'don't need? OR t3,t4 'don't need? WRWORD t3,t5 ADD t5,#2 ADD t1,#2 DJNZ t2,#:loop MOVS pixret_,#drawGlyphEnd MOV s1,arg2 'need to save this, set it to 0 and then restore it MOV arg2,#0 CALL #setd MOV arg3,glyphAddress JMP #pix_ drawGlyphEnd MOV arg2,s1 ADD arg0,textsp JMP #chr glyphAddress long 0 s1 res 1 org replaceStart { 'cbase := $8000+ glyph/2*128 'cbase:=glyph>>1<<7+$8000 'romBase=cbase clemensStart ror romBase,#1 wc 'glyph>>1 shl romBase,#7 'glyph<<7 add romBase,h8000 'glyph+$8000 'REPEAT i from 0 to 11 mov loopC1,#11 'setup for loop around lines 'The Clemens-Trick ' line:= LOOKUPZ(i: 1,4,6,9,11,14,17,20,22,25,27,28,31) 'data is down in clemensTable :loop1 mov romAddr,#clemensTable 'start of table add romAddr,loopC1 'add current row mov romAddr,romAddr 'get the value in clemensTable (this gives the same as above times 4 since we are getting a long) 'pattern := long[cbase][line] 'get from rom add romAddr,romBase 'add in the romBase rdlong pattern,romAddr 'get the data 'pattern2~ 'clear mov pattern2,#0 'IF glyph&1 'fix up for overlaid character 'pattern >>= 1 if_c shr pattern,#1 'the c flag gets set at the start and doesn't get changed anywhere else 'REPEAT 8 mov loopC2,#8 'setup for loop 'pattern2 <<= 2 :loop2 shl pattern2,#2 'if pattern&1 test pattern,#1 wz 'pattern2+=3 if_z add pattern2,#3 'pattern >>= 4 shr pattern,#4 djnz loopC2,#:loop2 'do small loop again 'pixDef2[i+2]:= pattern2 mov pixAddr,#2 'get 2 add pixAddr,loopC1 'add in which row we are on shl pixAddr,#1 'multiply by 2 for word size add pixAddr,pixBase 'add in the address of the pix sprite that we are using wrword pattern2,pixAddr 'write the data back to the hub djnz loopC1,#:loop1 'do big loop again MOV tmpArg2,arg2 'need to save this, set it to 0 and then restore it MOV arg2,#0 'to make not fliped or rotated CALL #setd 'some setup for the pix routine MOV arg3,pixBase ' MOVS pixret_,#clemensEnd ' JMP #pix_ clemensEnd MOV arg2,tmpArg2 'restore arg2 ADD arg0,textsp 'increment x position for next character JMP #chr 'go back for the next character 'return @pixDef2 } org replaceStart ClemensStart ROR romBase,#1 wc SHL romBase,#7 ADD romBase,h8000 MOV loopC1,#0 MOV hubAddr, pixBase ADD hubAddr,#2 :loop1 MOV pattern,loopC1 ADD pattern,#clemensTable MOV pattern,pattern SHL pattern,#2 ADD pattern,romBase RDLONG pattern,pattern if_c SHL pattern,#1 MOV loopC2,#8 MOV pattern2,#0 :loop2 SHL pattern2,#2 TEST pattern,#1 wz if_z ADD pattern2,#3 SHR pattern,#4 DJNZ loopC2,#:loop2 WRWORD pattern2,hubAddr ADD hubAddr,#2 ADD loopC1,#1 CMP loopC1,#12 wz in_nz JMP #:loop1 MOV tmpArg2,arg2 MOV arg2,#0 CALL #setd MOV arg3,pixBase JMPRET pixret_,#pix_ MOV arg2,tmpArg2 ADD arg0,textsp JMP #chr pixBase long 0 'need to set this during setup clemensTable long 4,16,24,36,44,14*4,17*4,20*4,22*4,25*4,27*4,28*4,31*4 tmpArg2 long 0 clemensBuffer word byte 1,12,0,0 word 0[16] org t1 romBase res 1 't1 - where glyph was stored loopC1 res 1 't2 pattern res 1 't3 romAddr res 1 't4 pattern2 res 1 't5 loopC2 res 1 't6 hubAddr res 1 't7