VDC routines for bitmap mode and read/write - where is error?

Started by MIRKOSOFT, March 08, 2011, 03:38 AM

Previous topic - Next topic

0 Members and 2 Guests are viewing this topic.

MIRKOSOFT

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
MIRKOSOFT of megabytes

Commodore 64 was great, Commodore 128 is bigger, better, faster and more!!!

http://www.mirkosoft.sk

tokra

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 ;-)

MIRKOSOFT

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
MIRKOSOFT of megabytes

Commodore 64 was great, Commodore 128 is bigger, better, faster and more!!!

http://www.mirkosoft.sk

tokra

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.


MIRKOSOFT

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
MIRKOSOFT of megabytes

Commodore 64 was great, Commodore 128 is bigger, better, faster and more!!!

http://www.mirkosoft.sk

tokra

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.

MIRKOSOFT

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
MIRKOSOFT of megabytes

Commodore 64 was great, Commodore 128 is bigger, better, faster and more!!!

http://www.mirkosoft.sk

tokra

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.

MIRKOSOFT

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
MIRKOSOFT of megabytes

Commodore 64 was great, Commodore 128 is bigger, better, faster and more!!!

http://www.mirkosoft.sk

tokra

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.

MIRKOSOFT

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
MIRKOSOFT of megabytes

Commodore 64 was great, Commodore 128 is bigger, better, faster and more!!!

http://www.mirkosoft.sk

BigDumbDinosaur

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.
x86?  We ain't got no x86.  We don't need no stinking x86!

tokra

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?).

MIRKOSOFT

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
MIRKOSOFT of megabytes

Commodore 64 was great, Commodore 128 is bigger, better, faster and more!!!

http://www.mirkosoft.sk

tokra

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.

MIRKOSOFT

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
MIRKOSOFT of megabytes

Commodore 64 was great, Commodore 128 is bigger, better, faster and more!!!

http://www.mirkosoft.sk

BigDumbDinosaur

Quote from: tokra on March 11, 2011, 07:12 AM
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?).

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.
x86?  We ain't got no x86.  We don't need no stinking x86!

tokra

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.

MIRKOSOFT

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
MIRKOSOFT of megabytes

Commodore 64 was great, Commodore 128 is bigger, better, faster and more!!!

http://www.mirkosoft.sk