If you followed the other chapter you already know that BeamRacer is an extremely powerful new tool allowing you to explore the VIC-II and Commodore 64 graphics and visual effects in both old, well-known as well as new, completely uncharted ways. At the very core of BeamRacer lies a programmable coprocessor called VASYL with its own registers, instruction set and memory.
Programming VASYL is definitely easy for seasoned Commodore 64 machine-language programmers who mastered their favourite development toolchain and can spawn another PRG in “no-time”. But we wanted it to be even more accessible and enabling. Therefore an idea for BASIC extension was born and materialised shortly thereafter.
How about some complex graphics effects and augmentation for BASIC programs? We all know that those are not possible without machine code routines stashed somewhere (typically at 49152 upwards) in available RAM. With BeamRacer installed you can still use the same methods. You can POKE or read from storage whatever you need. But you can also load “VBASIC” and have all the VASYL power at your BASIC programming fingertips with zero setup time.
At least that was the idea that initially guided us. And yes - it's all there. But to be completely frank we have to admit that once VBASIC matured, we also found it an indispensable tool for developing, testing and debugging not only VASYL programming ideas but for example checking quickly how VIC behaves when treated one or another way, without all the boilerplate code needed to cycle-exactly trigger something. An eye opening and mouth corners rising experience
Summing up - you will appreciate VBASIC for:
VBASIC is an integral part of BeamRacer support software. It is currently distributed in binary form of a BASIC loadable PRG file that needs to be RUN after loading.
As part of initialisation process VBASIC installs itself in the RAM area, address of which is normally occupied by BASIC ROM code, and adds additional routines at the very top of memory available for BASIC programs. It also verifies the presence of an installed BeamRacer card and activates it if found. Thanks to that your programs do not need to perform any additional steps to check and activate BeamRacer. Last but not least it adds helper routines and modifies several system variables and vectors. This allows to provide correct information about available memory and enables seamless BASIC programming experience. As a result all the standard behaviour for STOP, STOP/RESTORE etc. remains unchanged, while actively maintaining both the VBASIC extension and BeamRacer active at the same time.
There's a lot to talk about here so let's begin without additional delays.
Before we go into BeamRacer specific stuff – first things first: hexadecimal numbers. BASIC programmers are usually used to having only decimal numbers at their disposal. We didn't want to leave it that way though. We know very well that the more one's skills grow, the more important an easy way of working with hexadecimal addresses and data becomes. Therefore hexadecimal numbers received first-class VBASIC citizenship from day one.
VBASIC allows up to 16 bit hexadecimal entry wherever appropriate:
10 POKE 53280,14 20 POKE $D021,$0E 30 PRINT PEEK($D012) 40 POKE $0400,16:REM P 50 POKE 1025,$11:REM Q 60 POKE $C000,96:REM RTS 70 SYS $C000 80 PRINT $D000/$10
etc. are all valid now. So are:
10 FOR I = $100 TO $1000 STEP $10 20 REM DO GREAT STUFF WITH I 30 NEXT I
Hexadecimal input is one important thing, the other side of the coin is getting your numbers output in hex. VBASIC has you covered there too.
10 PRINT 49152/16 : REM WE KNOW WE GET 3072 20 PRINT 49152/256 &W : REM HUH ? 30 PRINT HI(49152) &B : REM HUH^2 ?
Any numeric expression can be passed to one of &
modifiers:
B
- for one BYTE
(eight bit)W
- for one WORD
(16 bit)L
- for one LONG
(32 bit)hexadecimal output. Please note that there is no automatic promotion to higher number of bits. If you enter
PRINT 49152 &B
what you get is only the eight least significant bits as a hexadecimal number.
The same applies for &W
, obviously with the output being limited to 16 least significant bits in this case. Try
PRINT 70000 &B PRINT 70000 &W PRINT 70000 &L
and you'll get the idea. If you don't explicitly specify the modifier
PRINT 255& PRINT 256& PRINT 53248& PRINT 16777215&
the most appropriate one will be chosen automatically. Values up to 32-bit long are supported.
PEEKs and especially POKEs are inseparable part of every BASIC programs that strives for utilising graphics capabilities of the computer. Be it bitmapped graphics, be it the the first “up up and away” sprites experience or actually _anything_ beyond the blue-on-blue textual interface the machine powers up with. Built-in support for PEEK and POKE is limited to eight bit values though. VBASIC adds keywords for handling 16 bit values easily. Setting address vectors or pointers is as easy as
DPOKE $C000,$0400
or
DPOKE 49152,1024
which in both forms sets a pointer to address 1024 with its LO byte (0) located at 49152 and HI byte (4) at 49153.
Obtaining the starting address of BASIC memory becomes as easy as
PRINT DPEEK(43)
Length of current BASIC program can be retrieved as
PRINT DPEEK(45) - DPEEK(43) - 2
And the (in)famous
10 POKE 53280,0 20 POKE 53281,0
sequence becomes
10 DPOKE 53280,0
Basically everywhere, where dealing with “little endian” 16-bit values is needed, these come in handy and do all the LO/HI calculations for you.
Speaking of HI and LO bytes of an address (or any 16-bit value for that matter) – VBASIC provides functions that simplify working with them too. And they are named… yeah, you guessed that already, didn't you?
10 PRINT HI(53281) 20 PRINT LO(53281)
Even if the above mentioned features alone are noteworthy additions to BASIC programming environment, the most important part is the full-fledged support for BeamRacer, including displaylist programming.
As explained in Introduction to BeamRacer Programming, to maintain highest possible compatibility, BeamRacer remains hidden on power-up and needs to be software activated with a “register knocking” technique before accessing any of its software accessible features. All programs that want to interact with VASYL or other BeamRacer features, like GreydotKilla™ for example, need to perform the init'n check sequence as described in Initialisation section. VBASIC takes that responsibility on its shoulders and not only activates BeamRacer as part of its startup-sequence but also automatically reactivates it after every BRK/NMI/STOP-RESTORE combination. Breaking out of VASYL programs and disabling display list is therefore as easy as hitting the famous keys combination, without worries about disabling either VBASIC or BeamRacer on the way. All regular BASIC programming activities, short of directly overwriting values at any of vital memory locations or SW/HW resets/jams do not affect VBASIC and BeamRacer's availability.
VBASIC enables and in some cases simplifies VASYL programming, debugging and testing directly from within BASIC. It is achieved in a few distinctive ways.
Certain VASYL programming sequences can be simplified with VBASIC statements, which combine several low level accesses into a single high level directive. The most common and required for virtually every displaylist employing program is the configuration of VASYL PORT register(s), which act as proxy gateways between the CPU and VASYL memory. In order to transfer any displaylist code to where it can be executed, at least one of the two available PORT registers needs to be employed. Configuring them is therefore the first step of displaylist transfer. In contrast to how it is done in assembler, when using VBASIC this can be done in one shot as:
10 VCFG 0,0
which configures
Other examples of such statements are:
1000 DLON : REM START DISPLAYLIST EXECUTION
1000 DLOFF : REM STOP DISPLAYLIST EXECUTION
1000 BANK 3 : REM SET VASYL MEMORY BANK TO 3
Full list and description can be found in the reference section below.
VBASIC provides full support for all VASYL/displaylist opcodes in the form of BASIC statements and functions. In order to form them, assembly opcodes are prepended with letter “V”. Thus WAIT
becomes VWAIT
, MOV
becomes VMOV
, END
becomes VEND
and so on.
The way BASIC interprets those keywords is tuned for both flexibility and the easiest possible way of transferring displaylists into VASYL local memory. I. e. whenever such keyword is encountered, its arguments are parsed and assembled into appropriate VASYL binary code. The resulting bytes are then either immediately sent to previously configured "conveyor" (if invoked as statement) and no additional steps are necessary, or returned to be e. g. stored in a variable for later use (when invoked as funcion).
Even if creating simple to medium complexity blocks of VASYL programs (aka displaylists) is very easy, having a method for verifying the state of displaylist memory is a hard to overrate feature. Especially at times when things don't work as imagined. For this purpose we equipped VBASIC with a complete displaylist disassembler, allowing us to peek into what VASYL sees and executes while doing its hard work.
Disassembler is invoked with VLIST
statement:
VLIST [<START>[,<END>]]
All VBASIC keywords grouped into three categories:
Tokens from this group require to be called as functions, with parentheses, even if no arguments are expected for some of them
FUNCTION: Returns detailed information about VBASIC and BeamRacer (if the latter is installed) versions
Synopsis: ABOUT()
Examples:
PRINT ABOUT()
AB$ = ABOUT() REM NOW DO SOMETHING WITH THE STRING
FUNCTION: Returns “double peek” value from <ADDRESS> in main computer address space
Synopsis: DPEEK(<ADDRESS>)
Examples:
BL = DPEEK(45) - DPEEK(43) - 2 : REM GET CURRENT BASIC PROGRAM SIZE IN BYTES PRINT BL&W : REM PRINT IT AS 16-BIT HEXADECIMAL NUMBER
FUNCTION: Returns “HI” byte (eight most significant bits) of <VALUE> interpreted as 16-bit unsigned integer
Synopsis: LO(<VALUE>)
Where <VALUE> is a number in the 16-bit unsigned int range: 0..65535
Examples:
PRINT HI(53281)&B
FUNCTION: Returns “LO” byte (eight least significant bits) of <VALUE> interpreted as 16-bit unsigned integer
Synopsis: LO(<VALUE>)
Where <VALUE> is a number in the 16-bit unsigned int range: 0..65535
Examples:
PRINT LO(53280)&B
FUNCTION: Returns “double peek” value from <ADDRESS> in currently selected bank of VASYL memory
Synopsis: VDPEEK(<ADDRESS>)
Examples:
PRINT VDPEEK($100)&W
FUNCTION: Returns 8-bit value from <ADDRESS> in currently selected bank of VASYL memory
Synopsis: VPEEK(<ADDRESS>)
Examples:
PRINT VPEEK($100)
Tokens from this group require to be used as statements with arguments given without parentheses
STATEMENT: Copy data between different VASYL RAM regions or between computer's main and VASYL's memory.
Synopsis: COPY #<TO>, #<FROM>, <LENGTH>
Discussion:
There are two “conveyors”, which are used every time data needs to be shifted in or out of VASYL RAM. Every display list program employs at least one of them in order to find its way into VASYL accessible memory. VBASIC provides one more “conveyor” though. While the first two, numbered 0
and 1
are directly connected with two VASYL <ports>, the third one extends this form of memory access to cover also the main computer RAM.
Conveyors:
Examples:
VCFG 2,49152,1 : REM ALWAYS CONFIGURE BEFORE USING VCFG 0,$1000,1 : REM ALWAYS CONFIGURE BEFORE USING COPY #0,#2,4096: REM STASH CONTENT OF $C000-$CFFF TO VASYL RAM AT $1000
VCFG 2,49152,1 : REM ALWAYS CONFIGURE BEFORE USING VCFG 0,$1000,1 : REM ALWAYS CONFIGURE BEFORE USING COPY #2,#0,4096: REM PULL 4KIB OF DATA FROM VASYL RAM AT $1000 TO MAIN RAM AT $C000
BANK 1 : REM SET VASYL RAM BANK TO 1 VCFG 1,0,1 : REM ALWAYS CONFIGURE BEFORE USING FOR L=0 TO 7 : REM WE NEED EIGHT CHUNKS by 1KIB VCFG 2,$4000+L,8 : REM ALWAYS CONFIGURE BEFORE USING COPY #1,#2,1024 : REM CONVERT 1KIB OF HIRES DATA TO LINEAR NEXT L : REM REPEAT UNTIL 8KIB TRANSFERRED
STATEMENT: Turn off displaylist execution
Synopsis: DLOFF
Examples:
100 DLOFF : REM TURN DISPLAYLIST EXECUTION OFF
STATEMENT: Turn on displaylist execution
Synopsis: DLON
Examples:
100 VCFG 0,0 : REM PORT0, ADDRESS0
110 VWAIT $83,0
120 VMOV $21,$14
130 VDELAYV $28
140 VMOV $21,6
999 VEND : REM END OF DISPLAYLIST
1000 DLON : REM START DISPLAYLIST EXECUTION
Discussion:
Turning displaylist execution on needs to be done _after_ the displaylist program is transferred to VASYL memory. It is a common practice to put it right after the displaylist closing VEND
statement.
STATEMENT: Double POKE
Synopsis: DPOKE <ADDRESS>,<VALUE>
Examples:
DPOKE $1000,32768 : REM STORES $00 AT $1000 AND $80 AT $1001
DPOKE $10FE,$FF : REM STORES $00 AT $10FE AND $FF AT $10FF
DPOKE $D020,$00 : REM STORES $00 AT $D020 AND $D021
STATEMENT: Define a label in displaylist code
Synopsis: LABEL X%
Examples:
[...] 130 VSETA 10 140 LABEL A% 150 VMOV $20,0 160 VMOV $20,1 170 VDECA 180 VBRA A% 999 VEND
Discussion:
The variable after the LABEL
statement needs to be declared (and later referred to) as integer variable – with percent (%
) sign following the name. Declaration of this variable with LABEL
statement must precede any reference to it
STATEMENT: Configure VBASIC's “conveyor”
Synopsis: VCFG <CONVEYOR>,<ADDRESS>[,<STEP>[,<BANK>]]
0
, 1
or 2
)PORT
numbers 0
and 1
) or Commodore 64 memory (for PORT
number 2
)1
Examples:
VCFG 0,0 : REM CONFIGURE CONVEYOR 0 TO POINT TO ADDRESS $0000 WITH STEP 1
VCFG 0,0,1 : REM CONFIGURE CONVEYOR 0 TO POINT TO ADDRESS $0000 WITH STEP 1
VCFG 1,32768,-$80,3 : REM CONFIGURE CONVEYOR 1 TO POINT TO ADDRESS $8000 WITH STEP -128 IN BANK 3
VCFG 2,49152 : REM CONFIGURE CONVEYOR 2 TO POINT TO ADDRESS $C000 IN COMPUTER RAM WITH STEP 1
STATEMENT: Stores <DATA>
in VASYL memory through currently configured PORT
Synopsis: VDATA <DATA>
Examples:
1000 VCFG 1,$200,2 1100 VDATA 12,$0d,1 : REM STORE 12 AT $0200, 13 AT $0202 AND 1 AT $0204
1000 VCFG 1,$200,2 1000 VDATA "0c0d01" : REM THE SAME AS PREVIOUS EXAMPLE
Discussion:
While CBM BASIC provides DATA
and READ
statements, which can be used to place binary data in VASYL memory
100 FOR I=0 TO 7 110 READ A 120 VPOKE $1000+I,A 130 NEXT I 140 DATA 0,6,14,15,1,15,14,6
this method is both inflexible and leaving much to be desired in terms of speed of execution. Both aspects become especially important when dealing with larger amounts of data. Using VDATA
not only transfers the data much faster but also allows far greater flexibility
100 VCFG 1,$1000 110 VDATA 0,6,14,15,1,15,14,6
achieves the same results but requires no (slow) BASIC loop, no upfront knowledge of data stream length and moreover allows also a special “string” form
100 VCFG 1,$1000 110 VDATA "00060e0f010f0e06"
STATEMENT: Double POKE for VASYL memory
Synopsis: VDPOKE <ADDRESS>,<VALUE>
Examples:
VDPOKE $1000,32768 : REM STORES $00 AT $1000 AND $80 AT $1001
VDPOKE $10FE,$FF : REM STORES $FF AT $10FE AND $00 AT $10FF
STATEMENT: Invoke displaylist disassembler
Synopsis: VLIST [<START>[,<END>]]
Examples:
VLIST
VLIST 4096
VLIST $100
VLIST 256,512
Discussion:
Disassembler can be invoked in three different ways
With no arguments disassembly begins from the next address after the last, previously disassembled one (or $0000 on the first invocation) and outputs full screen less one top and three bottom lines. This allows easy browsing of subsequent memory ranges by simply pressing HOME
and RETURN
to display next screen worth of disassembly
VLIST
When one argument is given, that argument determines the first VASYL memory address to be disassembled. Output is limited to one screen, the same as when no arguments are given
VLIST $100
With two arguments, the second one determines the exclusive end of address range to be disassembled. Output is continuous and scrolling can be slowed down by holding CONTROL
key depressed
VLIST 256,512
STATEMENT: VASYL memory equivalent of the regular POKE statement.
Synopsis: VPOKE <ADDRESS>,<VALUE>
Examples:
VPOKE 4096,128
VPOKE $100,$FF
All the following keywords accept both statement (no parentheses) and function (with parentheses) methods of invocation. Obviously they behave differently depending on whether they are invoked as a statement or as a function
STATEMENT: Set current VASYL RAM bank to <BANK>
Synopsis: BANK <BANK>
Examples:
BANK 1
FUNCTION: Returns currently selected VASYL RAM bank
Synopsis: BANK()
Examples:
PRINT BANK()
STATEMENT: Set BeamRacer status to <NUM>
Synopsis: RACER <NUM>
Where <NUM> can be 0, 1, 2, 3 meaning
Examples:
RACER 0 : REM DEACTIVATE BEAMRACER
FUNCTION: Returns current status of BeamRacer
Where returned value can be 0, 1, 2, 255 meaning
Synopsis: RACER()
Examples:
100 RS=RACER() 110 PRINT "BEAMRACER "; 120 IF RS=0 THEN PRINT "INACTIVE" 130 IF RS=1 THEN PRINT "TRANSIENT" 140 IF RS=2 THEN PRINT "ACTIVE" 150 IF RS=255 THEN PRINT "NOT FOUND"
Discussion:
When VBASIC is run, and BeamRacer is installed, the status of BeamRacer is set to 2
, which means that it is activated and gets reactivated after every RUN/STOP-RESTORE combination. When BeamRacer is not installed, its status is set to 255
DISPLAYLIST: Force a badline after RASTERLINES
of rasterlines
STATEMENT: Assembles BADLINE <RASTERLINES> and stores the result in memory
Synopsis: VBADLINE [<RASTERLINES>
Examples:
VBADLINE 3 : REM NEXT BADLINE THREE LINES LATER
FUNCTION: Returns assembled BADLINE <RASTERLINES>
Synopsis: VBADLINE(<RASTERLINES>)
Examples:
A = VBADLINE(3) : REM ASSEMBLE AND ASSIGN THE RESULT TO A VARIABLE
Discussion: The command sets the vertical scroll bits in VIC-II SCROLY
register to a calculated value that will trigger badline on requested positive, vertical offset from the current rasterline. It does NOT delay displaylist execution
DISPLAYLIST: Continue Display List execution at address <address>
STATEMENT: Assembles BRA <ADDRESS> and stores the result in memory
Synopsis: VBRA <ADDRESS>|*<OFFSET>
Examples:
[...]
150 VSETA 12
160 LABEL A%
[...]
190 VDECA
200 VBRA A%
999 VEND
[...]
200 VBRA 100 : REM CONTINUE AT ADDRESS $64
999 VEND
[...]
200 VBRA *-2 : REM INFINITE LOOP
999 VEND
FUNCTION: Returns assembled BRA <OFFSET>
Synopsis: VBRA(*<OFFSET>)
Examples:
A = VBRA(*+10): REM ASSEMBLE AND ASSIGN THE RESULT TO A VARIABLE
Discussion: While it is technically possible to use VBRA(<ADDRESS>) notation also in function mode, it is not very useful.
DISPLAYLIST: Decrement counter A
or skip next instruction if zero reached
STATEMENT: Assembles DECA and stores the result in memory
Synopsis: VDECA
Examples:
100 VCFG 0,0 : REM ALWAYS CONFIGURE
110 VWAIT $33,0 : REM WAIT FOR FIRST PAPER LINE
120 VSETA 12 : REM TWELVE TIMES
130 LABEL A% : REM LOOP CODE BEGINS HERE
140 VMOV $21, 14 : REM LIGHT BLUE
150 VDELAYV 8 : REM DELAY EIGHT RASTERLINES
160 VMOV $21, 6 : REM DARK BLUE
170 VDELAYV 8 : REM DELAY EIGHT RASTERLINES
180 VDECA : REM DECREMENT COUNTER
190 VBRA A% : REM LOOP TO LABEL A% UNLESS COUNTER REACHED ZERO
999 VEND : REM ALWAYS CLOSE DISPLAYLIST OFF
FUNCTION: Returns assembled DECA
Synopsis: VDECA()
Examples:
A = VDECA : REM ASSEMBLE AND ASSIGN THE RESULT TO A VARIABLE
DISPLAYLIST: Decrement counter B
or skip next instruction if zero reached
STATEMENT: Assembles ''DECB'' and stores the result in memory
Synopsis: VDECB
Examples:
VDECB : REM DECREMENT COUNTER B
FUNCTION: Returns assembled DECB
Synopsis: VDECB()
Examples:
B = VDECB : REM ASSEMBLE AND ASSIGN THE RESULT TO A VARIABLE
DISPLAYLIST: Delays displaylist execution for given number of <CYCLES>
STATEMENT: Assembles and stores DELAYH <CYCLES> in VASYL memory
Synopsis: VDELAYH <CYCLES>
Examples:
VDELAYH 3 : REM WAIT THREE CYCLES
FUNCTION: Returns assembled DELAYH <CYCLES>
Synopsis: VDELAYH(<CYCLES>)
Examples:
PRINT VDELAYH(3)&W : REM PRINT ASSEMBLED 3-CYCLE DELAYH AS HEX WORD
Discussion:
The <CYCLES>
argument accepts values up to 63, which makes it easy to delay displaylist execution across rasterline boundary. While this is technically correct, please note that the number of cycles per rasterline varies between VIC variants. Crossing rasterline boundary with DELAYH
leads therefore to VIC variant dependent code and should be avoided. Please see also note at DELAYH
DISPLAYLIST: Delays displaylist execution for given number of <RASTERLINES>
STATEMENT: Assembles DELAYV <RASTERLINES> and stores the result in memory
Synopsis: VDELAYV <RASTERLINES>
Examples:
VDELAYV $28 : REM WAIT FORTY RASTERLINES
FUNCTION: Returns assembled DELAYV <RASTERLINES>
Synopsis: VDELAYV(<RASTERLINES>)
Examples:
PRINT VDELAYV(200)&W : REM PRINT ASSEMBLED 200-LINE DELAYV AS HEX WORD
Discussion:
Vertical delay AKA VDELAYV
delays execution until the beginning (cycle 0) of the line coming specified number of lines later than the one this statement is executed. Please also note that on physical hardware the first cycles of each rasterline are located within “horizontal blanking interval”, i. e. out of visible range. This means a program:
VCFG 0,0
VWAIT $50,20
VDELAYV 10
VMOV $20,0
VMOV $20,14
VEND
will NOT show the expected black dash, even if your display device is capable of showing all of the picture generated by the computer1).
DISPLAYLIST: Close displaylist program off
STATEMENT: Assembles END and stores the result in memory
Synopsis: VEND
Examples:
VEND : REM END OF DISPLAYLIST
FUNCTION: Returns assembled END
Synopsis: VEND()
Examples:
A = VEND() : REM STORE ASSEMBLED END OF DISPLAYLIST BYTES IN A VARIABLE
DISPLAYLIST: Send Interrupt Request (IRQ)
STATEMENT: Assembles and stores IRQ in memory
Synopsis: VIRQ
Examples:
VIRQ : REM TRIGGER INTERRUPT REQUEST
FUNCTION: Returns assembled IRQ
Synopsis: VIRQ()
Examples:
?VIRQ() : REM PRINT IRQ AS 8-BIT NUMBER
Discussion:
Check also IRQ for more details
DISPLAYLIST: Set mask for next horizontal target comparison to <MASKVALUE>
STATEMENT: Assembles and stores MASKH <MASKVALUE> (P
bit cleared) in memory
Synopsis: VMASKH <MASKVALUE>
Examples:
VMASKH 7 : REM ONLY THREE LOWER BITS COUNT ON NEXT HORIZONTAL COMPARISON
FUNCTION: Returns MASKH <MASKVALUE> assembled with P
bit cleared
Synopsis: VMASKH(<MASKVALUE>)
Examples:
?VMASKH(7) : REM PRINT ASSEMBLED MASKH WITH P BIT CLEARED AND THREE LSB ACTIVE
Discussion:
Setting non-standard mask value right before VEND
is highly discouraged as it may lead to undesirable results. For more information check also MASKH
DISPLAYLIST: Set mask for all horizontal targets comparison to <MASKVALUE>
STATEMENT: Assembles and stores MASKH <MASKVALUE> (P
bit set) in memory
Synopsis: VMASKPH <MASKVALUE>
Examples:
VMASKPH 7 : REM ONLY THREE LOWER BITS COUNT ON HORIZONTAL COMPARISONS
FUNCTION: Returns MASKH <MASKVALUE> assembled with P
bit set
Synopsis: VMASKPH(<MASKVALUE>)
Examples:
?VMASKPH(7) : REM PRINT ASSEMBLED MASKH P BIT SET AND THREE LSB ACTIVE
Discussion:
Setting non-standard mask value right before VEND
is highly discouraged as it may lead to undesirable results. Check also MASKH
DISPLAYLIST: Set mask for all vertical target comparison to «VALUE»
STATEMENT: Assembles MASKV with P
bit set and stores it in memory
Synopsis: VMASKPV <MASKVALUE>
Examples:
VMASKPV 127 : REM SEVEN LOWER BITS COUNT ON VERTICAL COMPARISONS
FUNCTION: Returns MASKV assembled with P
bit set
Synopsis: VMASKPV(<MASKVALUE>)
Examples:
PV = VMASKPV(127) : REM SEVEN LOWER BITS COUNT ON VERTICAL COMPARISONS
Discussion:
Setting non-standard mask value right before VEND
is highly discouraged as it may lead to undesirable results. For more information see also MASKV
DISPLAYLIST: Set mask for next vertical target comparison to <MASKVALUE>
STATEMENT: Assembles MASKV with P
bit cleared and stores result in memory
Synopsis: VMASKV <MASKVALUE>
Examples:
VMASKV 127 : REM SEVEN LOWER BITS COUNT ON NEXT VERTICAL COMPARISON
FUNCTION: Returns MASKV assembled with P
bit cleared
Synopsis: VMASKV(<MASKVALUE>)
Examples:
V = VMASKV(127) : REM SEVEN LOWER BITS COUNT ON NEXT VERTICAL COMPARISON
Discussion:
Setting non-standard mask value right before VEND
is highly discouraged as it may lead to undesirable results. For more information check also MASKV
DISPLAYLIST: Store <VALUE> in <REGISTER>
STATEMENT: Assembles MOV and stores the result in memory
Synopsis: VMOV <REGISTER>,<VALUE>
Examples:
VMOV $20,3 : REM SET BORDER COLOUR TO CYAN
VMOV $43,128 : REM STROBE DISPLAYLIST EXECUTION IN ANOTHER BANK
FUNCTION: Returns assembled MOV
Synopsis: VMOV(<REGISTER>,<VALUE>)
Examples:
BR = VMOV($20,3) : REM STORE ASSEMBLED VMOV TO A VARIABLE
SR = VMOV($43,128) : REM STROBE DISPLAYLIST EXECUTION IN ANOTHER BANK
Discussion:
REGISTER can refer to either VIC-II or VASYL register. Depending on REGISTER value falling into one of the three possible ranges it can refer to
$00..$2e
- VIC-II registers, accessible by CPU in the $d000..$d02e
address range. Gets assembled as MOV$31..$3e
- bus accessible VASYL registers. CPU can access them in the $d031..$d03e
address range. Gets assembled as MOV$40..$4c
- VASYL internal registers. Not available for the CPU. Can only be acessed by VASYL himself, while executing displaylist programs. Gets assembled as MOVIPlease note that writing to VIC-II and VASYL registers from within a displaylist program differs substantially in the way it is technically executed. Writing to VIC-II registers requires bus access and cannot happen during time periods when VIC occupies the bus completely (e. g. during “badlines”). Writing to VASYL registers on the other hand can be done internally and is therefore not restricted by bus availability. Please also check notes at MOV and MOVI for additional information.
DISPLAYLIST: Does nothing (other than using one cycle)
STATEMENT: Assembles VNOP and stores it in memory
Synopsis: VNOP
Examples:
VNOP : REM USE A CYCLE
FUNCTION: Returns assembled VNOP
Synopsis: VNOP()
Examples:
NP = VNOP() : REM ASSIGN ASSEMBLED VNOP TO A VARIABLE
Discussion:
As useless as it looks, among other uses:
can be achieved by careful placement of VNOP opcodes in the displaylist programs.
DISPLAYLIST: Set counter A to <VALUE>
STATEMENT: Assembles SETA and stores the result in memory
Synopsis: VSETA <VALUE>
Examples:
VSETA 12 : REM TWELVE TIMES
100 VCFG 0,0 : REM ALWAYS CONFIGURE
110 VWAIT $33,0 : REM WAIT FOR FIRST PAPER LINE
120 VSETA 12 : REM TWELVE TIMES
130 VLABEL A% : REM LOOP CODE BEGINS HERE
140 VMOV $21, 14 : REM LIGHT BLUE
150 VDELAYV 8 : REM DELAY EIGHT RASTERLINES
160 VMOV $21, 6 : REM DARK BLUE
170 VDELAYV 8 : REM DELAY EIGHT RASTERLINES
180 VDECA : REM DECREMENT COUNTER
190 VBRA A% : REM LOOP TO LABEL A% UNLESS COUNTER REACHED ZERO
999 VEND : REM ALWAYS CLOSE DISPLAYLIST OFF
FUNCTION: Returns assembled SETA
Synopsis: VSETA(<VALUE>)
Examples:
?VSETA(12)&W : REM PRINT ASSEMBLED SETA VALUE AS HEX WORD
Discussion:
DISPLAYLIST: Set counter B to «VALUE»
STATEMENT: Assemble SETB and store the result in memory
Synopsis: VSETB <VALUE>
Examples:
VSETB 210
FUNCTION: Returns assembled SETB
Synopsis: VSETB(<VALUE>)
Examples:
CNT = VSETB(48) : REM ASSIGN ASSEMBLED SETB TO A VARIABLE
Discussion:
DISPLAYLIST: Make following WAIT
skip an instruction if past the target
STATEMENT: Assembles SKIP and stores the result in memory
Synopsis: VSKIP
Examples:
VSKIP : REM SKIP TWO BYTES AFTER NEXT WAIT IF PAST TARGET
FUNCTION: Returns assembled SKIP
Synopsis: VSKIP()
Examples:
?VSKIP() : REM PRINT ASSEMBLED SKIP VALUE
Discussion:
Check also SKIP
DISPLAYLIST: Wait until cycle <H> of rasterline <V>
STATEMENT: Assembles WAIT and stores the result in memory
Synopsis: VWAIT <V>,<H>
Examples:
VWAIT $26,$0A : REM WAIT UNTIL FIRST VISIBLE CYCLE OF RASTERLINE $26
FUNCTION: Returns assembled WAIT
Synopsis: VWAIT(<V>,<H>)
Examples:
WT = VWAIT($26,$0A) : REM ASSIGN ASSEMBLED WAIT TO A VARIABLE
Discussion:
More information available in the WAIT opcode description
DISPLAYLIST: Delays displaylist execution until beginning (cycle 0) of a rasterline immediately preceding the next badline.
STATEMENT: Assemble WAITBAD and store the result in memory
Synopsis: VWAITBAD
Examples:
VWAITBAD : REM WAIT FOR A LINE BEFORE NEXT BADLINE
FUNCTION: Return assembled WAITBAD
Synopsis: VWAITBAD()
Examples:
?VWAITBAD()
Discussion:
Check also notes at WAITBAD for more information
DISPLAYLIST: Wait for VASYL's <PORT> to finish repeating writes
STATEMENT: Assemble WAITREP and store the result in memory
Synopsis: VWAITREP <PORT>
Examples:
VWAITREP 0 : REM WAIT FOR PORT 0 TO FINISH REPEATING WRITES
FUNCTION: Returns assembled WAITREP
Synopsis: VWAITREP(<PORT>)
Examples:
WR = VWAITREP(0) : REM ASSIGN ASSEMBLED WAITREP TO A VARIABLE
Discussion:
Check WAITREP for more details
DISPLAYLIST: Transfer byte TO <REGISTER> from <PORT>
STATEMENT: Assembles XFER and stores the result in memory
Synopsis: VXFER <REGISTER>,<PORT>
Examples:
VXFER $20,1 : REM READ BYTE FROM PORT1 WRITE TO EXTCOL ($D020)
100 REM PREPARE DATA - STORE $00 TO $0F STARTING AT $100
110 FOR I=0 TO 15:POKE $100+I,I:NEXT I
120 VCFG 0,0 : REM CONFIGURE PORT0
130 REM CONFIGURE PORT1 FROM WITHIN THE DISPLAYLIST
140 VMOV $38,15:VMOV $39,1 : REM POINT IT TO $10F
150 VMOV $3A,255 : REM WITH STEP -1
160 VSETA 15 : REM OUR COLOUR COUNTER
170 VWAIT $26,$0A : REM WAIT UNTIL FIRST VISIBLE CYCLE OF RASTERLINE $26
180 LABEL A% : REM LOOP TARGET
190 VXFER $20,1 : REM TRANSFER TO EXTCOL REGISTER FROM PORT1
200 VDECA
210 VBRA A% : REM BRANCH TO PREVIOUSLY DEFINED LABEL
999 VEND
1000 DLON
FUNCTION: Returns assembled XFER
Synopsis: VXFER(<REGISTER>,<PORT>)
Examples:
?VXFER($20,1) : REM PRINT VALUE OF ASSEMBLED XFER $20,1
Discussion:
There are seven bits reserved for REGISTER value, even if currently only numbers in the range of $00..$4e are valid. XFER does not require port to be set for reading. See also XFER for more details
TBD