Toolbox-2/source/vecdem/vectron-1-asm.spin

595 lines
28 KiB
Plaintext

{
********************************************
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