{ ******************************************** VGA graphics Engine TestVersion ******************************************** coded by Beau Schwabe (Parallax) ******************************************** Version 1.0 - initial test release } CON tiles = vga#xtiles * vga#ytiles 'xtiles=16 ytiles 12 tiles32 = tiles * 32 'tiles32=6144 #1, _Sine,_Cosine,_ArcSine,_Plot,_Point,_Character,_Line,_Box VAR long cog, command long sync, pixels[tiles32] word colors[tiles] byte pointcolor_ byte textdata[33] OBJ vga : "vectron-1-drv" CON'############################################################################################################# ' Entry/Exit Routines '################################################################################################################ PUB start : okay '' returns false if no cog available stop vga.start(8, @colors, @pixels, @sync) 'start VGA driver okay := cog := cognew(@loop, @command) + 1 'start VGA graphics & text driver PUB stop '' Stop Assembly Function Engine - frees a cog if cog cogstop(cog~ - 1) 'stop VGA graphics & text driver vga.stop 'stop VGA driver command~ PUB syncvid 'wartet bis sync-fag gesetzt ist repeat until sync sync := 0 CON'############################################################################################################# ' Spin Assembly Calls '################################################################################################################ PUB Sine(Ang)|Arg1_ ' Input = 13-bit angle ranging from 0 to 8191 'Output = 16-bit Sine value ranging from $FFFF0001 ('-1') to $0000FFFF ('1') setcommand(_Sine, @Ang) Result := Arg1_ PUB Cosine(Ang)|Arg1_ ' Input = 13-bit angle ranging from 0 to 8191 'Output = 16-bit Cosine value ranging from $FFFF0001 ('-1') to $0000FFFF ('1') setcommand(_Cosine, @Ang) Result := Arg1_ PUB ArcSine(Ang)|Arg1_ ' Input = signed 16-bit value ranging from $FFFF0001 ('-1') to $0000FFFF ('1') 'Output = signed 11-bit angle ranging from -2047 (-pi/2) to 2047 (pi/2) setcommand(_ArcSine, @Ang) Result := Arg1_ PUB ArcCosine(Ang)|Arg1_,sign ' Input = signed 16-bit value ranging from $FFFF0001 ('-1') to $0000FFFF ('1') sign := Ang 'Output = signed 11-bit angle ranging from -2047 (-pi/2) to 2047 (pi/2) Ang := || Ang setcommand(_ArcSine, @Ang) if sign <> Ang sign := -1 else sign := 1 Result := (Sin_90 - Arg1_)* sign PUB plot(x,y)| Arg2_,Arg3_,Arg4_ 'Sets pixel value at location x,y Arg2_ := @pixels Arg3_ := tiles32 Arg4_ := pointcolor_ setcommand(_Plot, @x) PUB point(x,y)| Arg2_,Arg3_,Arg4_ 'Reads pixel value at location x,y Arg2_ := @pixels Arg3_ := tiles32 setcommand(_Point, @x) Result := Arg4_ PUB character(offX,offY,chr)|Arg3_,Arg4_,Arg5_ 'Place a text character from the ROM table at offset location offsetX,offsetY Arg5_ := chr chr := @pixels '<-- Arg2 <--> Arg5 swap to maintain consistency with PLOT and POINT structures Arg3_ := tiles32 Arg4_ := pointcolor_ setcommand(_Character, @offX) PUB line (px,py,dx,dy)| Arg4_,Arg5_,Arg6_,Arg7_,Arg8_ 'Draws line from px,py to dx,dy Arg4_ := pointcolor_ longmove(@Arg5_,@px,4) dx := @pixels '<-- Arg2 thru Arg8 shift to maintain consistency with PLOT and POINT structures dy := tiles32 setcommand(_Line, @px) PUB box(x1,y1,x2,y2)| Arg4_,Arg5_,Arg6_,Arg7_,Arg8_ 'Draws a box from opposite corners x1,y1 and x2,y2 Arg4_ := pointcolor_ longmove(@Arg5_,@x1,4) x2 := @pixels '<-- Arg2 thru Arg8 shift to maintain consistency with PLOT and POINT structures y2 := tiles32 setcommand(_Box, @x1) CON'############################################################################################################# ' Spin Routines '################################################################################################################ PUB color(tile,cval) 'Set Color tiles on VGA screen colors[tile] := cval PUB pointcolor(pc) 'Sets pixel color "1" or "0" pointcolor_ := pc PUB Text(offX,offY,Address)|chr,i 'Place a text string from the ROM table at offset location offsetX,offsetY i := 0 repeat chr := byte[Address + i] i++ if chr <> 0 character(offX,offY,chr) offX := offX + 16 else quit PUB shape(x,y,sizeX,sizeY,sides,rotation)|angle,sx1,sy1,sx2,sy2 'Draws a shape with center located at x,y if sides => 3 'sizeX and sizeY - control shape aspect ratio repeat angle from 8191/sides to 8191 step 8191/sides ' sides - select the number shape sides sx1 := x + sine(angle+rotation)*sizeX/131070 ' rotation - determines shape orientation sy1 := y + cosine(angle+rotation)*sizeY/131070 sx2 := x + sine(angle+rotation+8191/sides)*sizeX/131070 sy2 := y + cosine(angle+rotation+8191/sides)*sizeY/131070 line(sx1,sy1,sx2,sy2) PUB deg(angle) 'translate deg(0-360) ---> to ---> 13-bit angle(0-8192) return (angle * 1024)/45 PUB bit13(angle) 'translate 13-bit angle(0-8192) ---> to ---> deg(0-360) return (angle * 45)/1024 PUB SimpleNum(x,y,DecimalNumber,DecimalPoint)|sign,DecimalIndex,TempNum,spacing,DecimalFlag,Digit { x,y - upper right text coordinate of MSD (Most Significant Digit) DecimalNumber - signed Decimal number DecimalPoint - number of places from the Right the decimal point should be } spacing := 16 DecimalIndex := 0 TempNum := DecimalNumber 'Preserve sign of DecimalNumber DecimalNumber := ||DecimalNumber if DecimalNumber <> TempNum sign := 1 else sign := 0 if DecimalPoint == 0 character(x,y,$30) 'Insert Zero x := x - spacing repeat 'Print digits if DecimalIndex == DecimalPoint character(x,y,$2E) 'Insert decimal point at proper location x := x - spacing TempNum := DecimalNumber 'Extract the least significant digit TempNum := DecimalNumber - ((TempNum / 10) * 10) Digit := $30 + TempNum 'Display the least significant digit character(x,y,Digit) x := x - spacing DecimalIndex := DecimalIndex + 1 DecimalNumber := DecimalNumber / 10 'Divide DecimalNumber by 10 if DecimalNumber == 0 'Exit logic repeat while DecimalIndex < DecimalPoint ' Do this if DecimalNumber is less than where the decimal point should be character(x,y,$30) x := x - spacing DecimalIndex := DecimalIndex + 1 DecimalFlag := 1 if DecimalIndex == DecimalPoint ' Set flag if DecimalNumber is equal to where the decimal point should be DecimalFlag := 1 if DecimalFlag == 1 character(x,y,$2E) ' Insert decimal and leading Zero x := x - spacing character(x,y,$30) x := x - spacing if sign == 1 ' Restore sign of DecimalNumber character(x,y,$2D) quit PRI setcommand(cmd, argptr) command := cmd << 16 + argptr 'write command and pointer repeat while command 'wait for command to be cleared, signifying receipt CON'############################################################################################################# ' Assembly Routines '################################################################################################################ DAT org ' ' ' VGA graphics Engine - main loop ' ' t1..t15 temporäre variablen loop rdlong t1,par wz 'wait for command if_z jmp #loop 'wenn zeiger 0 dann ohne parameter 't1 zeiger auf parameter 't2 indexzeiger auf parameter 't3 schleifenindex '------------------------------- 9 parameter einlesen movd :arg,#arg0 'setze zeiger in :arg mov t2,t1 'zeiger auf parameter mov t3,#9 'schleifenindex :arg rdlong arg0,t2 'arg0 <-- (t2) parameter einlesen add :arg,d0 '(s-field in :arg) + 1 (d0 enthält $200 = 1 << 9) add t2,#4 'zeiger auf parameter erhöhen djnz t3,#:arg '9 x schleife 't1 zeiger auf parameter 't2 sprungziel '------------------------------- mov AddressLocation,t1 'sichere zeiger um später evtl. resultate an 'spin zu übergeben wrlong zero,par 'zero command to signify command received ror t1,#16+2 'lookup command address 't1 <- (16 + 2) add t1,#jumps 't1 := t1 + @jumps movs :table,t1 'code bei :table modifizieren rol t1,#2 't1 -> 2 shl t1,#3 't1 >> 3 :table mov t2,0 'modifizierte quelle nach t2 kopieren shr t2,t1 and t2,#$FF jmp t2 'jump to command jumps byte 0 '0 byte Sine_ '1 byte Cosine_ '2 byte ArcSine_ '3 byte Plot_ '─┐ byte Point_ ' │ byte Character_ ' ┣─ Additional functions MUST be in groups of 4-bytes (1 long) byte Line_ '─┘ With this setup, there is a limit of 256 possible functions. byte Box_ byte NotUsed_ byte NotUsed_ byte NotUsed_ NotUsed_ jmp #loop {################################################################################################################ Sine/cosine quadrant: 1 2 3 4 angle: $0000...$07FF $0800...$0FFF $1000...$17FF $1800...$1FFF table index: $0000...$07FF $0800...$0001 $0000...$07FF $0800...$0001 mirror: +offset -offset +offset -offset flip: +sample +sample -sample -sample on entry: sin[12..0] holds angle (0° to just under 360°) on exit: sin holds signed value ranging from $0000FFFF ('1') to $FFFF0001 ('-1') } Cosine_ mov t1, Arg0 '<--- cosine entry add t1, sin_90 jmp #CSentry Sine_ mov t1, Arg0 '<--- sine entry CSentry test t1, Sin_90 wc test t1, Sin_180 wz negc t1, t1 or t1, Sin_Table shl t1, #1 rdword t1, t1 negnz t1, t1 mov t2, AddressLocation 'Write data back to Arg1 add t2, #4 wrlong t1, t2 '<--- cosine/sine exit jmp #loop 'Go wait for next command {################################################################################################################ ArcSine/ArcCosine on entry: t2 holds signed 16-bit value ranging from $FFFF0001 ('-1') to $0000FFFF ('1') on exit: t7 holds signed 11-bit angle ranging from -2047 (-pi/2) to 2047 (pi/2) } ArcSine_ '<--- ArcSine entry (t2) mov t2, Arg0 mov t3, t2 'Preserve sign (t3) ; if '-' then t3 = 1 shr t3, #31 abs t2, t2 'Convert to absolute value mov t4, sin_90 'Preload RefHigh (t4) to 2048 mov t5, #0 'Preload RefLow (t5) to 0 mov t6, #11 'Iterations (t6) - equals # of bits on output resolution. Iteration_Loop mov t7, t4 'Add RefHigh and RefLow ; divide by 2 to get Pivot point (t7) add t7, t5 shr t7, #1 mov t8, t7 'Lookup sine value from Pivot location ; range 0-2048 ; 0 to pi/2 or t8, sin_table shl t8, #1 rdword t8, t8 't8 holds sine value ranging from $0000FFFF ('1') to $FFFF0001 ('-1') cmps t2, t8 wc 'Set 'C' if Input (t2) < 'Sine value'(t8) if_c mov t4, t7 'If Input < 'Sine value' then RefHigh = Pivot if_nc mov t5, t7 'If Input >= 'Sine value' then RefLow = Pivot djnz t6, #Iteration_Loop 'Re-Iterate to Pin-Point Reverse Sine lookup value. cmp t3, #1 wc 'Restore sign from t3 if_nc neg t7, t7 mov t1, AddressLocation 'Write data back to Arg1 add t1, #4 wrlong t7, t1 jmp #loop 'Go wait for next command {################################################################################################################ Plot Plots a pixel at location x,y ; pixel color must be set with pointcolor } '<--- Line entry LPlot_ mov lp, #1 'Set Line Flag mov t6, #0 'Clear Point Flag mov t12, #0 'Clear Character Plot Flag jmp #PointJump Point_ '<--- Point entry mov lp, #0 'Clear Line Flag mov t6, #1 'Set Point Flag mov t12, #0 'Clear Character Plot Flag jmp #PointJump CPlot_ '<--- Character Plot entry mov lp, #0 'Clear Line Flag mov t6, #0 'Clear Point Flag mov t12, #1 'Set Character Plot Flag jmp #PointJump Plot_ '<--- Plot entry mov lp, #0 'Clear Line Flag mov t6, #0 'Clear Point Flag mov t12, #0 'Clear Character Plot Flag PointJump cmps Arg0, #0 wc 'Set 'C' if x < 0 if_nc cmps Arg1, #0 wc 'Set 'C' if y < 0 if_nc cmps Xlimit, Arg0 wc 'Set 'C' if x > Xlimit if_nc cmps Ylimit, Arg1 wc 'Set 'C' if y > Ylimit if_c jmp #loop 'Plot points are out of bounds ; skip function 'Go wait for next command mov t1, Arg1 'Calculate Tile position where pixel is located shl t1, #4 'Multiply 'y' by 16 mov t2, Arg0 shr t2, #5 'Divide 'x' by 32 add t1, t2 'Get title position shl t1, #2 '...multiply by 4 for 'long' position offset mov t4, Arg2 add t4, t1 'Add offset to pixel address to get tile address rdlong t5, t4 'Read tile contents mov t3, #1 shl t3, Arg0 'Create bit mask test t6, #1 wc if_c jmp #Point_Test test Arg4, #1 wc 'Test if pixel is ON "1" or OFF "0" if_c jmp #Pixel_On Pixel_Off andn t5, t3 'Clear pixel using tile contents and bit mask wrlong t5, t4 'Write tile contents jmp #PixelDone 'Pixel Done Pixel_On or t5, t3 'Set pixel using tile contents and bit mask wrlong t5, t4 'Write tile contents jmp #PixelDone 'Pixel Done Point_Test muxc t5, t3 wc if_c mov t6, #1 if_nc mov t6, #0 mov t1, AddressLocation 'Write data back to Arg4 add t1, #16 wrlong t6, t1 PixelDone test t12, #1 wc 'Test if this is a Character plot if_c jmp #CharacterPlotDone test lp, #1 wc 'Test if this is a Line plot if_c jmp #LinePlot_ret jmp #loop 'Go wait for next command {################################################################################################################ Character Place a text character from the ROM table at offset location offsetX,offsetY } Character_ mov t7, #31 'Preset Y repeat loop RepeatY mov t8, #15 'Preset X repeat loop '------------------------------------------------------------------------------------------------ mov t9, Arg5 and t9, #1 'chr & 1 add t9, #30 mov t10, #1 '|<30 or |<31 shl t10, t9 'Create bit mask (t10) = |<(30 + chr & 1) '------------------------------------------------------------------------------------------------ mov t11, CharacterTable 'CharacterTable = $8000 mov t9, t7 'y * 4 shl t9, #2 add t11, t9 mov t9, Arg5 'chr * 64 shl t9, #6 add t11, t9 mov t9, Arg5 '(chr & 1)*64 and t9, #1 shl t9, #6 sub t11, t9 rdlong t11, t11 'Read 32bit character data = long[$8000 + y*4+chr*64-(chr & 1)*64] '------------------------------------------------------------------------------------------------ RepeatX test t11, t10 wc if_c jmp #PlotPoint NoPointPlot shr t10, #2 djnz t8, #RepeatX djnz t7, #RepeatY jmp #loop 'Go wait for next command PlotPoint mov offsetX, Arg0 'Hold OffsetX value mov offsetY, Arg1 'Hold OffsetY value add Arg0, t8 'Load Arg0(X) for PLOT command add Arg1, t7 'Load Arg1(Y) for PLOT command jmp #CPlot_ 'Go PLOT point CharacterPlotDone 'Return from PLOT point mov Arg0, offsetX 'Restore OffsetX value mov Arg1, offsetY 'Restore OffsetY value jmp #NoPointPlot {################################################################################################################ Line Draws line from px,py to dx,dy } BoxLine mov bf, #1 'Set Box flag jmp #Xcondition Line_ mov bf, #0 'Clear Box flag Xcondition sub Arg5, Arg7 nr,wc if_nc jmp #px_dominant dx_dominant mov sx, #1 mov deltaX, Arg7 sub deltaX, Arg5 jmp #Ycondition px_dominant mov sx, #0 mov deltaX, Arg5 sub deltaX, Arg7 Ycondition sub Arg6, Arg8 nr,wc if_nc jmp #py_dominant dy_dominant mov sy, #1 mov deltaY, Arg8 sub deltaY, Arg6 jmp #DeltaCondition py_dominant mov sy, #0 mov deltaY, Arg6 sub deltaY, Arg8 DeltaCondition mov ratio, #0 sub deltaY, deltaX nr,wc if_nc jmp #deltaYdominate deltaXdominate mov deltacount, deltaX add deltacount, #1 deltaXplot call #LinePlot test sx, #1 wc if_c add Arg5, #1 if_nc sub Arg5, #1 add ratio, deltaY sub deltaX, ratio nr,wc if_c jmp #ratioXoverflow jmp #deltaXdominateDone ratioXoverflow sub ratio, deltaX test sy, #1 wc if_c add Arg6, #1 if_nc sub Arg6, #1 deltaXdominateDone djnz deltacount, #deltaXplot jmp #LineDone deltaYdominate mov deltacount, deltaY add deltacount, #1 deltaYplot call #LinePlot test sy, #1 wc if_c add Arg6, #1 if_nc sub Arg6, #1 add ratio, deltaX sub deltaY, ratio nr,wc if_c jmp #ratioYoverflow jmp #deltaYdominateDone ratioYoverflow sub ratio, deltaY test sx, #1 wc if_c add Arg5, #1 if_nc sub Arg5, #1 deltaYdominateDone djnz deltacount, #deltaYplot jmp #LineDone LinePlot mov Arg0, Arg5 mov Arg1, Arg6 jmp #LPlot_ LinePlot_ret ret LineDone test bf, #1 wc 'Test if this is a Box line if_nc jmp #loop 'Go wait for next command BoxLine_ret ret {################################################################################################################ Box Draws a box from opposite corners x1,y1 and x2,y2 } Box_ mov x1_, Arg5 mov y1_, Arg6 mov x2_, Arg7 mov y2_, Arg8 mov Arg7, x1_ call #BoxLine mov Arg5, x1_ mov Arg6, y1_ mov Arg7, x2_ mov Arg8, y1_ call #BoxLine mov Arg5, x2_ mov Arg6, y2_ mov Arg7, x1_ mov Arg8, y2_ call #BoxLine mov Arg5, x2_ mov Arg6, y2_ mov Arg7, x2_ mov Arg8, y1_ call #BoxLine jmp #loop 'Go wait for next command { ########################### Defined data ########################### } zero long 0 'constants d0 long $200 Xlimit long 511 Ylimit long 383 CharacterTable long $8000 Sin_90 long $0800 Sin_180 long $1000 sin_table long $E000 >> 1 'sine table base shifted right { ########################### Undefined data ########################### } t1 res 1 'temp variables available for program overhead t2 res 1 t3 res 1 t4 res 1 t5 res 1 t6 res 1 t7 res 1 t8 res 1 t9 res 1 t10 res 1 t11 res 1 t12 res 1 t13 res 1 t14 res 1 t15 res 1 AddressLocation res 1 offsetX res 1 offsetY res 1 deltaX res 1 deltaY res 1 sx res 1 sy res 1 ratio res 1 deltacount res 1 lp res 1 bf res 1 x1_ res 1 y1_ res 1 x2_ res 1 y2_ res 1 arg0 res 1 'arguments passed from high-level arg1 res 1 arg2 res 1 arg3 res 1 arg4 res 1 arg5 res 1 arg6 res 1 arg7 res 1 arg8 res 1