Hi,
first let me say - to clarify - that the "direct $d0" is an assembler directive - it is not a mnemonic that will be assembled into the code.
It just gives the assembler some context information what it should do - when it encounters "extended" addressing - which might be able to be optimized to direct addressing.
Some more words on that.
extended addressing
Is an addressing mode, where the programmer references an address in the memory space. Lets say you want to read into register A the value that resides at address $7001, the statement to do that is:
LDA $7001
Which in machine code is "B6 70 01" which you can see uses 3 bytes of memory memory. The execution time of that statement is 5 cycles.
direct addressing
Is the small brother of extended addressing. In the above example if the assembler has been notified, that the DP register is assumed to contain the value of $70 (the hi byte of the extended address the "70" of the "7001"), than the assembler would have optimiezd the code to direct addressing.
The machine code for the instruction would than be "96 01". Which disassembled would look like
LDA $01.
That instruction is 2 byte long and executes in 4 cycles - less memory, faster -> more efficient!
The tricky part is - you as a programmer must ENSURE at some point that the DP register is set to the right value.
If for whatever reason, when EXECUTING the code the DP register upon entry of the above statement is e.g. $a0, than the resulting LDA would in fact read from address "$a001" instead of the wanted "$7001".
Within the BIOS disassembly all BIOS functions (that use direct addressing) have documentation of what DP register value is expected. You as a programmer must ensure BEFOREHAND that the DP register is set accordingly - otherwise catastrophic events may occur.
Notice:
Regardless of the DP register and the "direct" command, you can FORCE the assembler to an adressing mode.
extended:
LDA >$7001
will never be optimized to direct addressing the ">" is a sign for "extended"
direct:
LDA <$7001
(although it looks stupid) will allways be using direct addressing (or perhaps give a error message depending on the assembler).
more correctly ist should be written as:
LDA <$01
That said, the dp register ONLY works for the addressing mode "direct addressing" - for no other mode.
Now for your other questions.
LDD ,x++
is indexed addressing - regardless of the contents of X - it never is influenced by the DP register!
In your example the red lines are influenced by the DP register,
the green lines are extended addressing - but with the "wrong" hi-byte ($c8 instead of $d0), so they are not optimized.
DRAW_VLC macro
direct $d0 ; following code uses d0
LDD ,X++ ;
STA $C823 ;
CLRA
_DRAW_VLA\?:
STD VIA_port_b
LDB ,X+
INC VIA_port_b ;Disable mux
STB VIA_port_a ;Send X to A/D
DEC VIA_shift_reg ;Put pattern in shift register
STA VIA_t1_cnt_hi ;enable timer 1
LDB ,X+ ; 6
DEC $C823 ; 7
BEQ _DRAW_END\? ; 3 Go back for more points
LDA #$40 ;B-reg = T1 interrupt bit
LF_1\?:
BITA VIA_int_flags ;Wait for T1 to time out
BEQ LF_1\? ;
CLRA ;Wait a moment more
STA VIA_shift_reg ;Clear shift register (blank output)
BRA _DRAW_VLA\? ; 3
_DRAW_END\?:
LDA #$40 ;B-reg = T1 interrupt bitinsert code here
The "VIA" constants are actually addresses in the "$d000" - "$d00f" range
VIA_port_b EQU $D000 ;VIA port B data I/O register
VIA_port_a EQU $D001 ;VIA port A data I/O register (handshaking)
VIA_DDR_b EQU $D002 ;VIA port B data direction register (0=input 1=output)
VIA_DDR_a EQU $D003 ;VIA port A data direction register (0=input 1=output)
VIA_t1_cnt_lo EQU $D004 ;VIA timer 1 count register lo (scale factor)
VIA_t1_cnt_hi EQU $D005 ;VIA timer 1 count register hi
VIA_t1_lch_lo EQU $D006 ;VIA timer 1 latch register lo
VIA_t1_lch_hi EQU $D007 ;VIA timer 1 latch register hi
VIA_t2_lo EQU $D008 ;VIA timer 2 count/latch register lo (refresh)
VIA_t2_hi EQU $D009 ;VIA timer 2 count/latch register hi
VIA_shift_reg EQU $D00A ;VIA shift register
VIA_aux_cntl EQU $D00B ;VIA auxiliary control register
VIA_cntl EQU $D00C ;VIA control register
VIA_int_flags EQU $D00D ;VIA interrupt flags register
VIA_int_enable EQU $D00E ;VIA interrupt enable register
VIA_port_a_nohs EQU $D00F ;VIA port A data I/O register (no handshaking)
So each of these "addresses" is optimized to 8 bit addresses when "extended" addressing is used, and the addressing mode is changed to "direct".
In the above example the code is actually shortened by 7 bytes, and the execution is 7 cycles faster.
Y position
... has NOTHING to do with dp magic.
The y position is set in the very first statement of the draw loop, namely:
STD VIA_port_b
As you notice it is a STD mnemonic, a 16 bit operation.
The STD in that circumstances pokes the value of register A into the VIA_port_b (= $d000) and the value of register B into VIA_port_b+1 (= $d001) and thus setting the y value into Port A of VIA.
Regards
Malban