Commodore 128 Tips & Tricks


Go to content

VDC

How to read/write from/to VDC:

$D600 – address/status register – set number of VDC address/register, then:

wait:
BIT $D600 ;bit 7 indicates if is VDC ready to access
BPL wait ; if it's not ready try again


$D601 – data register – here are values to read/write from/to VDC register which is in $D600

- after reading or writting is
auto - increment of address/register

And how to do it in BASIC V7?

Write:
BANK15
SYS DEC("CDCC"), value, register
or
BANK15
SYS 52684, value, register

where register is the number (0-36) of the internal VDC register you wish to access, and value is the value (0-255) you wish to place in that register.

To read the contents of an internal VDC register from BASIC, use a statement of the form:

BANK15
SYS DEC("CDDA"),, register : RREG A
or
BANK15
SYS 52698,, register : RREG A


Size of VDC-RAM:

Here's program to detect size of VDC-RAM:

1 rem fred's nifty program to determine size of 8563 dram
5 w=dec("cdcc"):r=dec("cdda")
10 bank15: ad=dec("d600"): da=ad+1 :rem setup ml
20 pokead,28: s=peek(da): pokeda,63 :rem select 64k
30 i=16896: sysw,i/256,18:sysw,iand255,19:sysw,85,31 :rem write $55
40 i=16896: sysw,i/256,18:sysw,iand255,19:sysr,,31:rregc1 :rem read here
50 i=17152: sysw,i/256,18:sysw,iand255,19:sysr,,31:rregc2 :rem and here
60 i=16896: sysw,i/256,18:sysw,iand255,19:sysw,170,31 :rem write $aa
70 i=16896: sysw,i/256,18:sysw,iand255,19:sysr,,31:rregc3 :rem read here
80 i=17152: sysw,i/256,18:sysw,iand255,19:sysr,,31:rregc4 :rem and here
90 pokead,28: pokeda,s:sysdec("ff62") :rem restore 16/64k
95 print chr$(14)chr$(147)
100 if c1=c2 and c3=c4 then print "16K": else print"64K" :rem did it echo?
110 end


But also exists more easily method:

SYS52698,,28 : RREGA = 64kB=63/16kB=47

Also detect of chip type and its size:

- register 28/$1C bit 4:
4164 RAM chip (1 × 64kb) or 4416 RAM chip (4 × 16kB)
- size of VDC-RAM:
0 = 16kB
1 = 64kB


Size of VDC-RAM in C64 mode:

;set VDC to 64K mode
0C000 A2 1C LDX #$1C ;charset / RAM register
0C002 20 90 C0 JSR $C090 ;read register
0C005 09 10 ORA #$10 ;assume 64K size
0C007 20 82 C0 JSR $C082 ;write register
;write 0 to address $0000
0C00A A2 12 LDX #$12 ;RAM address hi register
0C00C A9 00 LDA #$00 ;value/address
0C00E 20 82 C0 JSR $C082 ;write register hi
0C011 E8 INX
0C012 20 82 C0 JSR $C082 ;write register lo
0C015 20 80 C0 JSR $C080 ;write zero into RAM
;write $FF to address $8000
0C018 A2 12 LDX #$12 ;RAM address hi register
0C01A A9 80 LDA #$80 ;address hi
0C01C 20 82 C0 JSR $C082 ;write register hi
0C01F E8 INX
0C020 A9 00 LDA #$00 ;address low
0C022 20 82 C0 JSR $C082 ;write register lo
0C025 A9 FF LDA #$FF ;value
0C027 20 80 C0 JSR $C080 ;write $FF into RAM
;get back RAM from $0000
0C02A A2 12 LDX #$12 ;RAM register hi address
0C02C A9 00 LDA #$00 ;address
0C02E 20 82 C0 JSR $C082 ;write register lo
0C031 E8 INX
0C032 20 82 C0 JSR $C082 ;write register hi
0C035 20 8E C0 JSR $C08E ;read RAM at $0000
0C038 8D 46 C0 STA $C046 ;save in +49222
0C03B 60 RTS
;empty space here...
;VDC write routines taken from C128 Editor ROM
0C080 A2 1F LDX #$1F
0C082 8E 00 D6 STX $D600
0C085 2C 00 D6 BIT $D600
0C088 10 FB BPL $C085
0C08A 8D 01 D6 STA $D601
0C08D 60 RTS
;VDC read routines
0C08E A2 1F LDX #$1F
0C090 8E 00 D6 STX $D600
0C093 2C 00 D6 BIT $D600
0C096 10 FB BPL $C093
0C098 AD 01 D6 LDA $D601
0C09B 60 RTS

SYS49152:?PEEK(49222) where:
0 = 64kB
<>0 = 16kB

VDC registers are working in the same style like in C128 mode.


KERNAL routine PLOT ($FFF0) in 80 columns mode:

mmuhi=$ff00 ;MMU config
bsout=$ffd2 ;output primitive
plot=$fff0 ;position cursor
;
*=$2000 ;assemble at 8192
;
lda #%00001110
sta mmuhi ;map in kernel ROM
ldx #10 ;row
ldy #45 ;column
clc
jsr plot ;position
bcs error ;coordinates out of range
;
lda #'A'
jsr bsout ;print char
rts

Properties of 80 columns text:

First codes to upper/lower case:

CHR$(14) = to lower case
CHR$(142) = to upper case

Attribute of current VDC-character:
POKE241,X
bity:
-7-/-6-/-5-/-4-/-3-0
LCASE/RVS/UNDERLINE/FLASH/COLOR
128/64/32/16/0-15

VDC colors using following scheme:
bit 3 = RED
bit 2 = GREEN
bit 1 = BLUE
bit 0 = INTENSITY
...and codes of colors are:
00 = dark black
01 = light black (dark gray)
02 = dark blue
03 = light blue
04 = dark green
05 = light green
06 = dark cyan
07 = light cyan
08 = dark red
09 = light red
10 = dark purple
11 = light purple
12 = dark yellow
13 = light yellow
14 = dark white (light gray)
15 = light white

Copying charset to VDC-RAM:

C128 has routine in ROM.
It copies the Charset to the VDC.
It is at $CE0C.
Just replace the write (JSR $CDCA) with your own.
Please keep in mind that a VDC character is 16 bytes high,
so you can strip the additional 8 byte copy at $CE32.

VDC screen SAVE/LOAD to/from VDC unused area (cache):

vdc_prepare:
lda #$12
sta vdcstatus
lda hibyte
sta vdc_rw
lda #$13
sta vdcstatus
lda lobyte
sta vdc_rw
lda #$1f
sta vdcstatus
rts

vdc_write:
notyet: bit vdcstatus
bpl notyet
sta vdc_rw // writting to VDC
rts

vdc_read:
notyet1:bit vdcstatus
bpl notyet1
lda vdc_rw // reading from VDC
rts

vdc_save:
ldx #$00
ldy #$10
stx x_w
sty y_w
ldx #$00
ldy #$00
citaj: stx x_r
sty y_r
stx lobyte
sty hibyte
jsr vdc_prepare
jsr vdc_read
sta temp
ldx x_w
stx lobyte
ldy y_w
sty hibyte
jsr vdc_prepare
lda temp
jsr vdc_write
inx
stx x_r
stx x_w
ldy y_r
cpx #$00
bne citaj
ldy y_w
iny
sty y_w
tya
and #$0f
tay
sty y_r
cpy #$00
beq done
jmp citaj
done: rts

vdc_load:
ldx #$00
ldy #$00
stx x_w
sty y_w
ldx #$00
ldy #$10
citaj1: stx x_r
sty y_r
stx lobyte
sty hibyte
jsr vdc_prepare
jsr vdc_read
sta temp
ldx x_w
stx lobyte
ldy y_w
sty hibyte
jsr vdc_prepare
lda temp
jsr vdc_write
inx
stx x_r
stx x_w
ldy y_r
cpx #$00
bne citaj1
ldy y_r
iny
sty y_r
tya
and #$0f
tay
sty y_w
cpy #$00
beq done1
ldy y_r
jmp citaj1
done1: rts

Backup of VDC screen to unused VDC area:

by Payton Byrd (Copyright, used in CBM-Command)

;/**************************************************************
;Copyright (c) 2010, Payton Byrd
;All rights reserved.
;
;Redistribution and use in source and binary forms, with or
;without modification, are permitted provided that the following
;conditions are met:
;
;* Redistributions of source code must retain the above
; copyright notice, this list of conditions and the following
; disclaimer.
;
;* Redistributions in binary form must reproduce the above
; copyright notice, this list of conditions and the following
; disclaimer in the documentation and/or other materials
; provided with the distribution.
;
;* Neither the name of Payton Byrd nor the names of its
; contributors may be used to endorse or promote products
; derived from this software without specific prior written
; permission.
;
;THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
;CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
;INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
;MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
;DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
;CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
;SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
;NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
;LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
;HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
;CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
;OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
;EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
;***************************************************************/

.setcpu "6502"
.smart on
.autoimport on
.case on
.importzp sp, sreg, regsave, regbank, tmp1, ptr1, ptr2
.macpack longbranch

.export _writeVdcRegister
.export _readVdcRegister
.export _clearVdcScreen
.export _copyVdcScreen ; void copyScreen(
; unsigned char srcHi,
; unsigned char trgHi)

READ: STA $D600 ; Put the value into the register
RVR1: BIT $D600 ; Compare the top bit of the register
BPL RVR1 ; Branch if the top bit is low (0)
LDA $D601 ; Get the result into the accumulator
RTS

WRITE: STX $D600 ; Put the value into the register
WVR1: BIT $D600 ; Compare the top bit of the register
BPL WVR1 ; Branch if the top bit is low (0)
STA $D601 ; Store the accumulator in the register's value
RTS

.proc _copyVdcScreen
JSR pusha ; Store the accumulator

; Write target address
LDY #$00 ; Offset for second of two parameters
LDA (sp),y ; Load accumulator with parameter value
LDX #18
JSR WRITE ; Writes accumulator to register 18
LDA #00 ; Low bytes are at location 00
INX ; Next register
JSR WRITE ; Writes accumulator to register 19

; Issue block copy command
LDX #24 ; Get value of register 24
LDA #128 ; Set bit 7 hi
JSR WRITE ; Write register 24

; Write source address
LDY #$01 ; Offset for first of two parameters
LDA (sp),y ; Load accumulator with parameter value
LDX #32
JSR WRITE ; Writes accumulator to register 18
LDA #00 ; Low bytes are at location 00
INX ; Next register
JSR WRITE ; Writes accumulator to register 19

; Set block size
LDX #30 ; block size register
LDA #$00 ; Full block size of 256 bytes
JSR WRITE

; Loop until executed 16 times
LDY #$10 ; Copy 16 blocks
CLRPAG: JSR WRITE
DEY
BNE CLRPAG

; We're done, clean up
JSR incsp2
RTS
.endproc


.proc _clearVdcScreen
JSR pusha ; Store the accumulator

; Set the start location
LDY #$01 ; Offset for first of two parameters
LDA (sp),y ; Load accumulator with parameter value
LDX #18
JSR WRITE ; Writes accumulator to register 18

LDY #$00 ; Offset for the second of two parameters
LDA (sp),y ; Store the parameter in the accumulator
INX ; Now we are on register 19
JSR WRITE ; Write the accumulator to register 19

; Set address to clear
LDX #18
LDA #00
JSR WRITE
INX
JSR WRITE

; Clear the copy bit && Reverse Bit
LDX #24 ; Located in register 24
;JSR READ ; Read it to accumulator
;AND #$7F ; OR the accumulator
LDA #$00
JSR WRITE ; Write it back

; Set data byte
LDX #31 ; Located in register 31
JSR WRITE ; Set the register

LDX #30 ; Word count register?
LDA #$00
JSR WRITE

LDY #$10
LDA #00
CLRPAG: JSR WRITE
DEY
BNE CLRPAG

JSR incsp2
RTS
.endproc

;------------------------
; Write A to VDC Register
; stored in X
.proc _writeVdcRegister
JSR pusha ; Store the accumulator

LDY #$01 ; Offset for first of two parameters
LDA (sp),y ; Load accumulator with parameter value
TAX ; Copy accumulator to x

LDY #$00 ; Offset for the second of two parameters
LDA (sp),y ; Store the parameter in the accumulator

JSR WRITE

JSR incsp2 ; Finish our function
RTS
.endproc

;-------------------------
; Read A from VDC Register
; stored in X
.proc _readVdcRegister
JSR pusha ; Store the accumulator

LDY #$00 ; Offset for the parameter
LDA (sp),y ; Store the parameter in the accumulator

JSR READ

JSR incsp1 ; Increment the stack pointer by 1
RTS ; as the return value of the function?
.endproc



Interlaced VDC TEXT/BITMAP:
---------------------------------------------------------------------------
Interlaced Text

1 REM 80X50 TEXT SCREEN F.BOWEN 9/88
10 SYSDEC("CDCC"),DEC("34"),4
20 SYSDEC("CDCC"),DEC("32"),6
30 SYSDEC("CDCC"),DEC("33"),7
40 SYSDEC("CDCC"),3 ,8
50 SYSDEC("CDCC"),DEC("EA"),9
55 : rem Double screen & attribute areas and clear them
60 POKEDEC("A2F"),16:SYSDEC("CDCC"),16,20
70 POKEDEC("A2E"),8 :SYSDEC("CDCC"),8, 12:SCNCLR
80 POKEDEC("A2E"),0 :SYSDEC("CDCC"),0, 12:SCNCLR
90 LIST


---------------------------------------------------------------------------
Interlaced Bitmap

100 REM 640X480 BMM (REQ. 64K VIDEO RAM!) F.BOWEN 9/88
110 :
120 FAST: TRAP410
130 SYSDEC("CDCC"),DEC("7E"),0
140 SYSDEC("CDCC"),DEC("50"),1
150 SYSDEC("CDCC"),DEC("66"),2
160 SYSDEC("CDCC"),DEC("4C"),4
170 SYSDEC("CDCC"),6 ,5
180 SYSDEC("CDCC"),DEC("4C"),6
190 SYSDEC("CDCC"),DEC("47"),7
200 SYSDEC("CDCC"),3 ,8
210 SYSDEC("CDCC"),6 ,9
220 SYSDEC("CDCC"),0 ,24
230 SYSDEC("CDCC"),128+7 ,25
240 SYSDEC("CDCC"),0 ,27
250 SYSDEC("CDCC"),16 ,28
260 SYSDEC("CDCC"),0,12 :SYSDEC("CDCC"),0,13 :SYSDEC("CDCC"),240,26
270 : rem Clear the bitmap using block fills
280 SYSDEC("CDCC"),0,18 :SYSDEC("CDCC"),0,19 :SYSDEC("CDCC"),0,31
290 FORI=0TO255:SYSDEC("CDCC"),0,30 :NEXT
300 : rem Draw a box around the border, rendering into odd & even frames
310 FORI=1TO480/2: EVEN=0+I*80-1: EH=INT(EV/256):EW=(EV-EH*256)
320 : ODD=21360+I*80-1:OH=INT(OD/256):OL=(OD-OH*256)
330 :SYSDEC("CDCC"),OH,18:SYSDEC("CDCC"),OL,19:SYSDEC("CDCA"),1:SYSDEC("CDCA"),
128
340 :SYSDEC("CDCC"),EH,18:SYSDEC("CDCC"),EW,19:SYSDEC("CDCA"),1:SYSDEC("CDCA"),
128
350 :NEXT
360 SYSDEC("CDCC"),0,18:SYSDEC("CDCC"),0,19
370 SYSDEC("CDCC"),255,31 :SYSDEC("CDCC"),79,30: rem use block fill for top of box
380 SYSDEC("CDCC"),OH,18:SYSDEC("CDCC"),OL+1,19
390 SYSDEC("CDCC"),255,31 :SYSDEC("CDCC"),79,30: rem ditto for bottom of box
400 GETKEYA$
410 SYSDEC("E179") :SYSDEC("FF62"): SCNCLR : rem restore screen, d/l chr def's


Back to content | Back to main menu