Hi!
I'm really confused!
I'm programming VDC in BITMAP mode and all works in VICE correctly.
If I try to RUN it on real machine (C128DCR/64kB VDC RAM/1,5MB REU/SCPU128/RAMLink/floppies/HDDs etc.) it makes problems like not correct copying blocks of VDC graphics, error characters...
Can anybody check source code below where are only used routines for working with VDC... really don't understand where I do the mistake.
Can anybody help?
////////////////////////////////////////////////////////////////
VDC R/W TO MEMORY ROUTINES
////////////////////////////////////////////////////////////////
vdc_prepare:
ldx #$12
lda hibyte
stx vdcstatus
bag1: bit vdcstatus
bpl bag1
sta vdc_rw
ldx #$13
lda lobyte
stx vdcstatus
bag2: bit vdcstatus
bpl bag2
sta vdc_rw
rts
vdc_write:
ldx #$1f
stx vdcstatus
notyet:
bit vdcstatus
bpl notyet
sta vdc_rw // writting to VDC
rts
vdc_read:
ldx #$1f
stx vdcstatus
notyet1:
bit vdcstatus
bpl notyet1
lda vdc_rw // reading from VDC
rts
////////////////////////////////////////////////////////////////
VDC ROUTINE FOR BLOCK COPY
////////////////////////////////////////////////////////////////
vdx_read:
stx $d600
rvr1: bit $d600
bpl rvr1
lda $d601
rts
vdx_write:
stx $d600
wvr1: bit $d600
bpl wvr1
sta $d601
rts
vdx_copy:
lda deshi // des-hi
ldx #18
jsr vdx_write
lda deslo // des-lo
inx
jsr vdx_write
ldx #24
lda #128
jsr vdx_write
lda srchi // src-hi
ldx #32
jsr vdx_write
lda srclo // src-lo
inx
jsr vdx_write
ldx #30
lda #$00
jsr vdx_write
ldy datahi
clrpag:
jsr vdx_write
dey
bne clrpag
rts
////////////////////////////////////////////////////////////////
SETTING VDC BITMAP MODE
////////////////////////////////////////////////////////////////
set_bitmap:
lda #$1c // read Charset address
sta vdcstatus
jsr nyet
lda vdc_rw
and #$1f
ora #$e0
sta count
lda #$1c // set Charset address
sta vdcstatus
jsr nyet
lda count
sta vdc_rw
lda #$0c // hi-byte of Bitmap
sta vdcstatus
jsr nyet
lda #$00
sta vdc_rw
lda #$0d // lo-byte of Bitmap
sta vdcstatus
jsr nyet
lda #$00
sta vdc_rw
lda #$14 // hi-byte of Attributes
sta vdcstatus
jsr nyet
lda #$40
sta vdc_rw
lda #$15 // lo-byte of Attributes
sta vdcstatus
jsr nyet
lda #$00
sta vdc_rw
lda #$1a // background color
sta vdcstatus
jsr nyet
lda #$22
sta vdc_rw
lda #$19 // read Bitmap mode
sta vdcstatus
jsr nyet
lda vdc_rw
sta textmode
ora #$80
sta count
lda #$19 // set Bitmap mode
sta vdcstatus
jsr nyet
lda count
sta vdc_rw
lda #$00
ldx #$40
sta lobyte
stx hibyte
jsr vdc_prepare
ldy #00
sty count
agx: lda #$22 // dblu|dblu
jsr vdc_write
iny
cpy #00
bne agx
inc count
lda count
cmp #$08
bne agx
rts
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
It's written in syntax of KickAssembler.
Sourcecode is also in attachment as ASM file.
MANY MANY MANY MANY THANKS FOR EVERY HELP!!!!!
Miro
Ok, I may have an idea what you are doing wrong. It looks like you check the status register before writing to $d601 but not before writing to $d600. So the VDC may still be busy processing your last command, when you overwrite $d600. Take a look at a kernal-routine at $c53c:
.C:c53c A9 01 LDA #$01
.C:c53e A2 1E LDX #$1E
.C:c540 20 CC CD JSR $CDCC
.C:c543 2C 00 D6 BIT $D600
.C:c546 10 FB BPL $C543
.C:c548 A2 12 LDX #$12
.C:c54a 20 DA CD JSR $CDDA
.C:c54d CD 3D 0A CMP $0A3D
.C:c550 90 EA BCC $C53C
.C:c552 A2 13 LDX #$13
.C:c554 20 DA CD JSR $CDDA
.C:c557 CD 3C 0A CMP $0A3C
.C:c55a 90 E0 BCC $C53C
.C:c55c 60 RTS
This waits until the VDC is ready again before the next call to the kernal-stubs at $cdcc or $cdda are done. It also fixes another bug in the VDC with register 30 ($1e) that sometimes tends to write or copy an extra byte. The kernal just writes one byte less and checks if an extra byte has been set by the VDC (by checking registers 18 ($12) and 19 ($13)). If not it will just set it manually (that's what the BCC $C53c are for). This may also be the cause of the strange behavior you're witnessing.
Let me know if this helps. The VDC really is a buggy and quirky little chip, but if you tell it exactly what to do it can produce fantastic results ;-)
Hi!
Thank you for your work, but it works not now also in VICE.
It's total disorder on the screen.
I called routine $c53c before every writting to $d600, values A, X, Y were stored into temporary locations and after calling $c53c were loaded again to A, X, Y...
Every help is great, so I'm thankful!
But this big bug must to be solved....
SO? PLEASE HELP ME SOMEBODY...
Many many many thanks for every little bit of help.
Miro
You shouldn't just blindly call $c53c before every write, this routine was just to show the quirks of the VDC. Just make sure you wait for the VDC-ready bit before the next write to $d600, like this:
.C:c543 2C 00 D6 BIT $D600
.C:c546 10 FB BPL $C543
Also make sure the block-copy-routine you use takes care of the sometimes copied extra byte as shown in the kernal code. As this otherwise could lead to unwanted bytes being copied.
Hi my friend!
I forgot to write to source code what seems labels:
.var vdcstatus = $d600
.var vdc_rw = $d601
vdc_write:
ldx #$1f
stx vdcstatus
notyet:
bit vdcstatus
bpl notyet
sta vdc_rw // writting to VDC
rts
Mean you that?
or mean you this:
vdc_write:
ldx #$1f
nyet:
bit vdcstatus
bpl nyet
stx vdcstatus
notyet:
bit vdcstatus
bpl notyet
sta vdc_rw // writting to VDC
rts
Miro
vdc_write:
ldx #$1f
nyet:
bit vdcstatus
bpl nyet
stx vdcstatus
notyet:
bit vdcstatus
bpl notyet
sta vdc_rw // writting to VDC
rts
This one looks good. You should do this for every write to VDC-registers if you do them in a row.
So, I tried it, seems better, dialogs shows corrctly. Bitmap is not copied good. Also, first part of bitmap seems like there's charset...
Can you chcek BLOCK-COPY:
vdx_read:
jsr nyet
stx $d600
rvr1: bit $d600
bpl rvr1
lda $d601
rts
vdx_write:
jsr nyet
stx $d600
wvr1: bit $d600
bpl wvr1
sta $d601
rts
vdx_copy:
lda deshi // des-hi
ldx #18
jsr vdx_write
lda deslo // des-lo
inx
jsr vdx_write
ldx #24
lda #128
jsr vdx_write
lda srchi // src-hi
ldx #32
jsr vdx_write
lda srclo // src-lo
inx
jsr vdx_write
ldx #30
lda #$00
jsr vdx_write
ldy datahi
clrpag:
jsr vdx_write
dey
bne clrpag
rts
and SET-BITMAP:
set_bitmap:
lda #$1c // read Charset address
jsr nyet
sta vdcstatus
jsr nyet
lda vdc_rw
jsr nyet
and #$1f
ora #$e0
sta count
lda #$1c // set Charset address
jsr nyet
sta vdcstatus
jsr nyet
lda count
sta vdc_rw
lda #$0c // hi-byte of Bitmap
jsr nyet
sta vdcstatus
jsr nyet
lda #$00
sta vdc_rw
lda #$0d // lo-byte of Bitmap
jsr nyet
sta vdcstatus
jsr nyet
lda #$00
sta vdc_rw
lda #$14 // hi-byte of Attributes
jsr nyet
sta vdcstatus
jsr nyet
lda #$40
sta vdc_rw
lda #$15 // lo-byte of Attributes
jsr nyet
sta vdcstatus
jsr nyet
lda #$00
sta vdc_rw
lda #$1a // background color
jsr nyet
sta vdcstatus
jsr nyet
lda #$22
sta vdc_rw
lda #$19 // read Bitmap mode
jsr nyet
sta vdcstatus
jsr nyet
lda vdc_rw
sta textmode
ora #$80
sta count
jsr nyet
lda #$19 // set Bitmap mode
sta vdcstatus
jsr nyet
lda count
sta vdc_rw
lda #$00
ldx #$40
sta lobyte
stx hibyte
jsr vdc_prepare
ldy #00
sty count
agx: lda #$22 // dblu|dblu
jsr vdc_write
iny
cpy #00
bne agx
inc count
lda count
cmp #$08
bne agx
rts
Many thanks!
Miro
I don't get why you call "jsr nyet" before each access now. You should just check if the VDC is ready again. By calling the subroutine you are adding a lot of unwanted overhead. Why don't you do it just like in the kernal in the first post I sent? This is a small and working solution: Check if VDC-status is ready and jsr to $cdcc or $cdda.
For the block-copy please see the kernal-routine as well - that takes care of the error in the VDC that sometimes copies one byte to many which could lead to the effects you describe.
Hi!
Yes, I do it twice... why?
You wrote here that maybe I'm not checking it, so I did it twice for sure... I know that it's useless, but really don't know where error is...
RUN IN VICE: all works corectly
REAL MACHINE: except dialogs and Notepad window all works not...
So, here's big Q on you: I want to invite you to co-operate on ACE128 TOS, I lost Jason Lapp's support have in team testers, but I need really good VDC programmer... and I mean that you're, so:
WANT YOU?
Let me know.
Miro
The double-call you do has some serious flaws, take a look at your routine:
vdx_read:
jsr nyet
stx $d600
rvr1: bit $d600
bpl rvr1
lda $d601
rts
When you jsr to nyet in fact THIS gets done by the CPU:
nyet:
bit vdcstatus
bpl nyet
stx vdcstatus
notyet:
bit vdcstatus
bpl notyet
sta vdc_rw // writting to VDC
stx $d600
rvr1: bit $d600
bpl rvr1
lda $d601
rts
That can't be right... Why do you use separate vdc_read and vdx_read?? And vdc_write, vdx_write? What's the difference. Just make use of the kernal-routines like this:
x=register to write to, a=value to write to register
vdc_write:
bit vdcstatus
bpl vdc_write
jsr $cdcc
rts
x=register to read, a=value of register after call
vdc_read:
bit vdcstatus
bpl vdc_read
jsr $cdda
rts
This is short and sweet and uses the kernal-routines. No need to do separate vdx_read and vdx_write...
As for becoming a co-operator: I'm afraid I don't either have the time nor motivation for that, sorry. I might try some VDC-coding myself again, but this would be for interlace-modes and whatnot, just for fun.
Thank you!
I'll try it to do it this night.
But really, I began with simplest solutions and after modifications and code works only in VICE, I did all what I could to do even if it was not logical...
I'm now really lost... this BIG BUG is main problem of VDC displaying of OS...
But I know that VICE emulates C128 best of all emulators, with VDC has ever problems, and when I downloaded VICE2.3 I was very bad surprised...
VICE2.3 in emulation of C128 is totally out of game... If I look at emulation of C64, it's good step to future...
Miro
Quote from: tokra on March 09, 2011, 08:37 AM
Ok, I may have an idea what you are doing wrong. It looks like you check the status register before writing to $d601 but not before writing to $d600.
Wrong. As soon as the loop that tests bit 7 at $D600 exits and the read/write op is done a new register can be written to $D600.
Quote from: BigDumbDinosaur on March 10, 2011, 12:30 PM
Wrong. As soon as the loop that tests bit 7 at $D600 exits and the read/write op is done a new register can be written to $D600.
Hmm, I thought so as well, but stumped over the kernal routine, copied in here again for reference:
.C:c53c A9 01 LDA #$01
.C:c53e A2 1E LDX #$1E
.C:c540 20 CC CD JSR $CDCC
.C:c543 2C 00 D6 BIT $D600
.C:c546 10 FB BPL $C543
.C:c548 A2 12 LDX #$12
.C:c54a 20 DA CD JSR $CDDA
.C:c54d CD 3D 0A CMP $0A3D
.C:c550 90 EA BCC $C53C
.C:c552 A2 13 LDX #$13
.C:c554 20 DA CD JSR $CDDA
.C:c557 CD 3C 0A CMP $0A3C
.C:c55a 90 E0 BCC $C53C
.C:c55c 60 RTS
This does a check if the VDC is read before the next jump to $cdda. According to my "128 intern"-book this fixes a bug in the VDC block copy (only early revisions maybe?) that sometimes copies a byte to many. That's why the kernal copies one byte less than it should and then does the cmp $0a3d and cmp $0a3c and copies one more byte if the VDC hasn't already - thus circumventing this bug in every case. Maybe the extra-check for the status flag is in there to make sure the VDC has finished it's block-copy before asking it if it has copied one byte too many. I can't remember having to check the status flag before setting the register in $d600 in my old programs - so I agree with your post. But maybe the error Miro is seeing really DOES have something to do with the block-copy bug in the VDC. But he hasn't addressed that part of my post at all (yet?).
Hi!
If I understand correctly, earlier versions of VDC chip are not bugfixed?
Now it can look as VICE emulates other version of VDC than I have on real machine.
In VICE is possible to select VDC Rev1 or Rev2 (really I know only 8563 Rev8 and 8563 Rev9) and 8568 - my machine (DCR) has version 8568, flat C128 has 8563 rev9.
Problem to test it is that the flat version of VDC has only 16kB VDC RAM. I know that it is possible to upgrade to 64kB, but ATM is nothing on eBay or so...
So, how?
Miro
http://myworld.ebay.co.uk/alee650 (http://myworld.ebay.co.uk/alee650)
This seller still has them for sale - just not online at the moment. You can just write him through Ebay anyway. I just go two expansion boards for myself. Arrived in under a week.
Thank you very much.
I wrote email him.
I will see the differences btw. chips 8563 R9 and 8568...
Then is here only one Q: if it is so different, how to optimize code? Problem is not in detecting type of chip, this is easy, but it seems that it will need two or more different codes...
Thank you very much.
Miro
Quote from: tokra on March 11, 2011, 07:12 AMQuote from: BigDumbDinosaur on March 10, 2011, 12:30 PM
Wrong. As soon as the loop that tests bit 7 at $D600 exits and the read/write op is done a new register can be written to $D600.
Hmm, I thought so as well, but stumped over the kernal routine, copied in here again for reference:
.C:c53c A9 01 LDA #$01
.C:c53e A2 1E LDX #$1E
.C:c540 20 CC CD JSR $CDCC
.C:c543 2C 00 D6 BIT $D600
.C:c546 10 FB BPL $C543
.C:c548 A2 12 LDX #$12
.C:c54a 20 DA CD JSR $CDDA
.C:c54d CD 3D 0A CMP $0A3D
.C:c550 90 EA BCC $C53C
.C:c552 A2 13 LDX #$13
.C:c554 20 DA CD JSR $CDDA
.C:c557 CD 3C 0A CMP $0A3C
.C:c55a 90 E0 BCC $C53C
.C:c55c 60 RTS
This does a check if the VDC is read before the next jump to $cdda. According to my "128 intern"-book this fixes a bug in the VDC block copy (only early revisions maybe?) that sometimes copies a byte to many. That's why the kernal copies one byte less than it should and then does the cmp $0a3d and cmp $0a3c and copies one more byte if the VDC hasn't already - thus circumventing this bug in every case. Maybe the extra-check for the status flag is in there to make sure the VDC has finished it's block-copy before asking it if it has copied one byte too many. I can't remember having to check the status flag before setting the register in $d600 in my old programs - so I agree with your post. But maybe the error Miro is seeing really DOES have something to do with the block-copy bug in the VDC. But he hasn't addressed that part of my post at all (yet?).
The first batch of VDCs was infested with bugs, the block-copy one being most notorious (there was one other that escapes me, but had to do with driving a PAL displayâ€"it's been too long for me to remember now). I don't know about in Europe, but by the time the flat 128 was released in North America this nuisance had been addressed. Indeed, an examination of the 1986 ROMs seems to indicate that the workaround was no longer considered necessary.
The 128-D was fitted with the 8568 instead of the 8563 that was in the flat 128. The 8568, while software compatible with the 8563, is a different piece and is not electrically interchangeable.
BTW, the "C-128 Internals" book has a number of errors in it, some due to the Data Becker folks having reversed a very early production 128. Other errors crept in due to translation of the original German text into English.
Thanks for clearing that up. I wasn't able to reproduce the block-copy error on my C128 (VDC-Version 1 - Rev 8/9) so I assumed the Version 0 (Rev 7) might be the one that has the bug. All better if that is not the case. I can only see one difference in the kernal for Version 0 (Rev 7) in that it sets register 25 to $40 instead of $47. This would be the only change Miro would have to take care of in his programs then. Otherwise I'm afraid he's back to square one with his strange problem if it's not the block-copy bug that causes the problem.
Hi friends!
OK, thanks to detailed description of possible problems.
I must note fact that v0 = 8563Rev7(1985) / v1 = 8563rev8/9(1986) / v2 = 8568(1986) or v1 = 8563rev8(1986) / v2 = 8563rev9(1986) / v3 = 8568(1986) .... ?
I ordered and paid for VDC RAM Expansion, so I can now test the same code on 8563rev8...when VDC Expansion arrives...
BLOCK COPY is perfectly fast thing in VDC options, so, sure is that I want to use it...
Miro