Long story short: Executing DVG instructions in PB sounded like a fun litte project.

Note that the project is still WIP and unfinished, it needs more testing & functions,
anyway i thought its ok enough to release for others to play around.

Links:
Youtube - 8-Bit Show And Tell: C64 Asteroids Emulator? How It Works + SuperCPU Gameplay
Computer Archeology: Asteriods DVG
GitHub - nmikstas: Asteroids Vector Rom
The include:
Code: Select all
EnableExplicit
;-------------------------------------------------------------------------
; Project: Execute Digital Vector Generator (DVG) Instructions
;-------------------------------------------------------------------------
; Inspired by 8-Bit Show And Tell (youtube):
; - https://www.youtube.com/watch?v=5f15S1vVCSk
; Based on information found here:
; - https://computerarcheology.com/Arcade/Asteroids/DVG.html
; - https://github.com/nmikstas/asteroids-disassembly/blob/master/
; AsteroidsSource/asteroids_vector_rom.asm
;-------------------------------------------------------------------------
; Version: dev.1.20 (WIP)
; Author: Mijikai
;-------------------------------------------------------------------------
Structure _DVG_WORDS
y.w
x.w
EndStructure
Structure _DVG_BYTES
b.b
a.b
d.b
c.b
EndStructure
Structure _DVG_OPCODE
StructureUnion
bytes._DVG_BYTES
words._DVG_WORDS
EndStructureUnion
EndStructure
Structure _DVG
*program
*offset
*opcode._DVG_OPCODE
*stack[4]
scale_index.i
scale_global.d
scale_local.d
scale_table_global.d[16]
scale_table_local.d[16]
brightness.i
offset_x.i
offset_y.i
delta_x.i
delta_y.i
*callback
EndStructure
Enumeration DVG_OPCODE
#DVG_OPCODE_VEC_0
#DVG_OPCODE_VEC_1
#DVG_OPCODE_VEC_2
#DVG_OPCODE_VEC_3
#DVG_OPCODE_VEC_4
#DVG_OPCODE_VEC_5
#DVG_OPCODE_VEC_6
#DVG_OPCODE_VEC_7
#DVG_OPCODE_VEC_8
#DVG_OPCODE_VEC_9
#DVG_OPCODE_CUR
#DVG_OPCODE_HALT
#DVG_OPCODE_JSR
#DVG_OPCODE_RTS
#DVG_OPCODE_JMP
#DVG_OPCODE_SVEC
EndEnumeration
Procedure.i dvg_callback(x1.i,y1.i,x2.i,y2.i,brightness.i)
ProcedureReturn #Null
EndProcedure
Procedure.i dvg_reset(*dvg._DVG)
With *dvg
ResetStructure(*dvg,_DVG)
\scale_table_global[0] = 1
\scale_table_global[1] = 2
\scale_table_global[2] = 4
\scale_table_global[3] = 8
\scale_table_global[4] = 16
\scale_table_global[5] = 32
\scale_table_global[6] = 64
\scale_table_global[7] = 128
\scale_table_global[8] = 1 / 256
\scale_table_global[9] = 1 / 128
\scale_table_global[10] = 1 / 64
\scale_table_global[11] = 1 / 32
\scale_table_global[12] = 1 / 16
\scale_table_global[13] = 1 / 8
\scale_table_global[14] = 1 / 4
\scale_table_global[15] = 1 / 2
\scale_table_local[0] = 1 / 512
\scale_table_local[1] = 1 / 256
\scale_table_local[2] = 1 / 128
\scale_table_local[3] = 1 / 64
\scale_table_local[4] = 1 / 32
\scale_table_local[5] = 1 / 16
\scale_table_local[6] = 1 / 8
\scale_table_local[7] = 1 / 4
\scale_table_local[8] = 1 / 2
\scale_table_local[9] = 1
\scale_table_local[10] = 1
\scale_table_local[11] = 1
\scale_table_local[12] = 1
\scale_table_local[13] = 1
\scale_table_local[14] = 1
\scale_table_local[15] = 1
ProcedureReturn #Null
EndWith
EndProcedure
Procedure.i dvg_program(*dvg._DVG,*program,*callback)
With *dvg
dvg_reset(*dvg)
\program = *program
If *callback
\callback = *callback
Else
\callback = @dvg_callback()
EndIf
ProcedureReturn #Null
EndWith
EndProcedure
Procedure.i dvg_execute(*dvg._DVG)
With *dvg
\opcode = \program + \offset
If \opcode\words\y
Select ((\opcode\bytes\a >> 4) & %00001111)
Case #DVG_OPCODE_VEC_0 To #DVG_OPCODE_VEC_9
\scale_index = ((\opcode\bytes\a >> 4) & %00001111)
\scale_local = \scale_table_local[\scale_index] * \scale_global
\delta_x = (\opcode\words\x & %0000001111111111)
\delta_y = (\opcode\words\y & %0000001111111111)
\delta_x - (((\opcode\bytes\c >> 2) & 1) * (\delta_x << 1))
\delta_y - (((\opcode\bytes\a >> 2) & 1) * (\delta_y << 1))
\delta_x * \scale_local
\delta_y * \scale_local
\delta_x + \offset_x
\delta_y + \offset_y
\brightness = ((\opcode\bytes\c >> 4) & %00001111)
If \brightness
CallCFunctionFast(\callback,\offset_x,\offset_y,\delta_x,\delta_y,\brightness)
EndIf
\offset_x = \delta_x
\offset_y = \delta_y
\offset + 4
ProcedureReturn #True
Case #DVG_OPCODE_CUR
\scale_index = ((\opcode\bytes\c >> 4) & %11111111)
If \scale_index < 0
\scale_index - (\scale_index << 1)
EndIf
\scale_global = \scale_table_global[\scale_index]
\offset_x = (\opcode\words\x & %0000001111111111)
\offset_y = (\opcode\words\y & %0000001111111111)
\offset + 4
ProcedureReturn #True
Case #DVG_OPCODE_HALT
ProcedureReturn #False
Case #DVG_OPCODE_JSR
\stack[3] = \stack[2]
\stack[2] = \stack[1]
\stack[1] = \stack[0]
\stack[0] = \offset + 2
\offset + ((((\opcode\words\y & %0000111111111111) - $800) << 1) + $800);<- need testcode for this!
ProcedureReturn #True
Case #DVG_OPCODE_RTS
\offset = \stack[0]
\stack[0] = \stack[1]
\stack[1] = \stack[2]
\stack[2] = \stack[3]
\stack[3] = #Null
ProcedureReturn Bool(\offset <> #Null)
Case #DVG_OPCODE_JMP
\offset + ((((\opcode\words\y & %0000111111111111) - $800) << 1) + $800);<- need testcode for this!
ProcedureReturn #True
Case #DVG_OPCODE_SVEC
\scale_index = ((((\opcode\bytes\b >> 3) & 1) << 1) + ((\opcode\bytes\a >> 3) & 1)) + 1
\scale_local = \scale_table_global[\scale_index] * \scale_global
\delta_x = (\opcode\bytes\b & %00000011)
\delta_y = (\opcode\bytes\a & %00000011)
\delta_x = \delta_x - (((\opcode\bytes\b >> 2) & 1) * (\delta_x << 1))
\delta_y = \delta_y - (((\opcode\bytes\a >> 2) & 1) * (\delta_y << 1))
\delta_x * \scale_local
\delta_y * \scale_local
\brightness = ((\opcode\bytes\b >> 4) & %00001111)
\delta_x + \offset_x
\delta_y + \offset_y
If \brightness
CallCFunctionFast(\callback,\offset_x,\offset_y,\delta_x,\delta_y,\brightness)
EndIf
\offset_x = \delta_x
\offset_y = \delta_y
\offset + 2
ProcedureReturn #True
EndSelect
EndIf
ProcedureReturn #False
EndWith
EndProcedure
Procedure.i dvg_alloc()
ProcedureReturn AllocateStructure(_DVG)
EndProcedure
Procedure.i dvg_free(*dvg._DVG)
FreeStructure(*dvg)
ProcedureReturn #Null
EndProcedure
Code: Select all
EnableExplicit
;DVG Test
XIncludeFile "dvg.pbi"
Procedure.i draw_start()
If StartVectorDrawing(CanvasVectorOutput(0))
VectorSourceColor(RGBA(10,10,10,255))
FillVectorOutput()
ProcedureReturn #True
EndIf
ProcedureReturn #False
EndProcedure
Procedure.i draw_stop()
StopVectorDrawing()
ProcedureReturn #Null
EndProcedure
Procedure.i draw_line(x1.i,y1.i,x2.i,y2.i,brightness.i)
MovePathCursor(x1,y1)
AddPathLine(x2,y2)
VectorSourceColor(RGBA(0,brightness << 4,0,200))
StrokePath(2)
ProcedureReturn #Null
EndProcedure
Procedure.i main()
Protected *dvg
Protected.i exit,draw
*dvg = dvg_alloc()
If *dvg
dvg_program(*dvg,?dvg_test_program,@draw_line())
If OpenWindow(0,0,0,1024,1024,"DVG Test",#PB_Window_SystemMenu|#PB_Window_ScreenCentered)
If CanvasGadget(0,0,0,WindowWidth(0),WindowHeight(0))
AddWindowTimer(0,0,20)
Repeat
Repeat
Select WindowEvent()
Case #PB_Event_Timer
draw = #True
Case #PB_Event_None
Break
Case #PB_Event_CloseWindow
exit = #True
EndSelect
ForEver
If draw
If draw_start()
While dvg_execute(*dvg)
Wend
draw = draw_stop()
EndIf
EndIf
Until exit
EndIf
CloseWindow(0)
EndIf
dvg_free(*dvg)
EndIf
ProcedureReturn #Null
EndProcedure
End main()
DataSection
;Test Pattern. Diamond pattern across screen with a parallel line pattern in the center.
dvg_test_program:
Data.w $A080, $0000 ;CUR scale=0(/512) x=0 y=128
Data.w $7000, $0000 ;VEC scale=7(/4) x=0 y=0 b=0
Data.w $9000, $73FF ;VEC scale=9(/1) x=1023 y=0 b=7
Data.w $92FF, $7000 ;VEC scale=9(/1) x=0 y=767 b=7
Data.w $9000, $77FF ;VEC scale=9(/1) x=-1023 y=0 b=7
Data.w $96FF, $7000 ;VEC scale=9(/1) x=0 y=-767 b=7
Data.w $92FF, $72FF ;VEC scale=9(/1) x=767 y=767 b=7
Data.w $8600, $7200 ;VEC scale=8(/2) x=512 y=-512 b=7
Data.w $87FE, $77FE ;VEC scale=8(/2) x=-1022 y=-1022 b=7
Data.w $9200, $7600 ;VEC scale=9(/1) x=-512 y=512 b=7
Data.w $81FE, $7200 ;VEC scale=8(/2) x=512 y=510 b=7
Data.w $96FF, $72FF ;VEC scale=9(/1) x=767 y=-767 b=7
Data.w $A37F, $03FF ;CUR scale=0(/512) x=1023 y=895
Data.w $7000, $0000 ;VEC scale=7(/4) x=0 y=0 b=0
Data.w $96FF, $76FF ;VEC scale=9(/1) x=-767 y=-767 b=7
Data.w $81FE, $7600 ;VEC scale=8(/2) x=-512 y=510 b=7
Data.w $9200, $7200 ;VEC scale=9(/1) x=512 y=512 b=7
Data.w $87FE, $73FE ;VEC scale=8(/2) x=1022 y=-1022 b=7
Data.w $8600, $7600 ;VEC scale=8(/2) x=-512 y=-512 b=7
Data.w $92FF, $76FF ;VEC scale=9(/1) x=-767 y=767 b=7
Data.w $A1FC, $01F4 ;CUR scale=0(/512) x=500 y=508
Data.w $7000, $0000 ;VEC scale=7(/4) x=0 y=0 b=0
Data.w $F0DB ;SVEC scale=2(/32) x=3 y=0 b=13
Data.w $F900 ;SVEC scale=1(/64) x=0 y=1 b=0
Data.w $F0CF ;SVEC scale=2(/32) x=-3 y=0 b=12
Data.w $F900 ;SVEC scale=1(/64) x=0 y=1 b=0
Data.w $F0BB ;SVEC scale=2(/32) x=3 y=0 b=11
Data.w $F900 ;SVEC scale=1(/64) x=0 y=1 b=0
Data.w $F0AF ;SVEC scale=2(/32) x=-3 y=0 b=10
Data.w $F900 ;SVEC scale=1(/64) x=0 y=1 b=0
Data.w $F09B ;SVEC scale=2(/32) x=3 y=0 b=9
Data.w $F900 ;SVEC scale=1(/64) x=0 y=1 b=0
Data.w $F08F ;SVEC scale=2(/32) x=-3 y=0 b=8
Data.w $F900 ;SVEC scale=1(/64) x=0 y=1 b=0
Data.w $F07B ;SVEC scale=2(/32) x=3 y=0 b=7
Data.w $F900 ;SVEC scale=1(/64) x=0 y=1 b=0
Data.w $F06F ;SVEC scale=2(/32) x=-3 y=0 b=6
Data.w $F900 ;SVEC scale=1(/64) x=0 y=1 b=0
Data.w $F05B ;SVEC scale=2(/32) x=3 y=0 b=5
Data.w $F900 ;SVEC scale=1(/64) x=0 y=1 b=0
Data.w $F04F ;SVEC scale=2(/32) x=-3 y=0 b=4
Data.w $F900 ;SVEC scale=1(/64) x=0 y=1 b=0
Data.w $F03B ;SVEC scale=2(/32) x=3 y=0 b=3
Data.w $F900 ;SVEC scale=1(/64) x=0 y=1 b=0
Data.w $F02F ;SVEC scale=2(/32) x=-3 y=0 b=2
Data.w $D07C ;RTS
EndDataSection