Jump to content
IGNORED

VBI colour cycle routine


Tezz

Recommended Posts

I've been continuing on with coding today and planning some routines.. I'm still thinking about the best way to implement this one though... I need to rotate 6 colour values around 6 colour registers within a VBI routine with a delay included to control the speed. with the delay I was thinking about incrementing a counter so on each pass through the vbi routine when the counter reaches number X the colour values then rotate to the next value.

 

So, for example:

 

I have the colour values 02,04,06,08,0A,0C,

I want to apply these values to colour registers: COLPM0, COLPM1, COLPM2, COLPM3, COLPF0, COLPF1

and rotate the values round the registers in an endless loop with the delay timer.

 

That's pretty straight forward I hear you shout.. well yes, but as it's critical to execute routines optimally during the vbi I wondered if there are any examples of such a routine out there?

 

Thanks,

Tezz

Edited by Tezz
Link to comment
Share on other sites

a quick "out of brain" code without testing...

 

dec delay

lda delay

bmi cycle

...

cycle: lda #value

sta delay

;now rotate from right to left

 

ldx colortab

lda colortab+1

sta colortab

lda colortab+2

sta colortab+1

lda colortab+3

sta colortab+2

lda colortab+4

sta colortab+3

lda colortab+5

sta colortab+4

stx colortab+5

...

ldx #5

loop: lda colortab,x

sta colpm0,x

dex

bpl loop

...

 

colortab: dta 2,4,6,8,10,12

 

does this make sense?

Link to comment
Share on other sites

a quick "out of brain" code without testing...
ditto here...

 

Sometimes I find that wasting a few more 'data' areas can

save you some of code space (and hence a few cycles too),

note the extra zero used on the end of the colour table.

e.g.

 

...

ldx ct_offset

ldy #0

loop:

lda colortab,x

sta colpm0,y

inx

iny

cpy #6

bne loop

lda colortab,x

bne no_reset

sta ct_offset

no_reset:

...

 

colortab:

.byte 2,4,6,8,10,12

.byte 2,4,6,8,10,0

 

Regards,

Mark

Link to comment
Share on other sites

  • 2 weeks later...

@ Heaven

 

Thanks for the code example earlier, I got around to running some test Vblank programs yesterday, the first to move all the P/Ms around from a table which worked fine but for some reason the other test for the colour cycling which I based from your example crashes the emulated Atari? I'm missing an obvious mistake I must have made here somewhere? I can see the routine change the registers briefly before it crashes

 

Any ideas?

Edited by Tezz
Link to comment
Share on other sites

bpl loop

 

ctab: .byte $2

 

An opcode ending in $02 is guaranteed to lockup a machine.

 

You need JMP $E45F after the BPL LOOP (or $E462 if it's a deferred VB).

Thanks! Gees that's the second time in the past few days I've made a simple and obvious mistake and not noticed it! I can't believe I forgot to JMP XITVBV .. Doh!

 

It works fine now.. Thanks again.

Edited by Tezz
Link to comment
Share on other sites

Hi All,

 

I'm stuck on the delay and wondered if anyone can help..

 

I've been using the internal realtime clock as a timer to make a delay in my vbi, I created a quick test vbi program to move a player from left to right using the timer like this below...

 

TIMER equ $14 ; internal realtime clock

 

LDA #0

STA OFFSET

STA SIZEP0

LDA TIMER

AND #1 ; delay

BNE EXIT

INC POSITION

LDA POSITION

STA HPOSP0

 

EXIT: JMP XITVBV

 

so, that works out fine, the value #1 can be increased to delay the move more and more

 

So, now with that test out of the way and back to my actual vbi routine I have the colours rotating from the values in a table however I need to now add in the delay before the new values store as it is too fast. This is where I'm stuck, I was using bpl to branch if positive in the colour storing loop but of course I cannot use LDA TIMER AND#1 before the bpl as that will prevent the bpl from doing it's job in the loop so this code below screws up the vbi.

 

ldx #5

loop: lda ctab,x

sta colpm0,x

dex

LDA TIMER

AND #1

bpl loop

jmp XITVBV

 

So, knowing that that wasn't going to work I tried instead to use cpx and bne to compare when X has reached 0 so I wrote the code like this...

 

ldx #5

loop: lda ctab,x

sta colpm0,x

dex

LDA TIMER

AND #1

cpx #0

bne loop

jmp XITVBV

 

This only stopped colpm3 from being updated in the loop rather than what i need to do in delaying the storing of the values to make the rotation slower.

 

I then tried dropping the timer idea and making a loop instead like this code below but it had the same effect only stopping colpm3 from being updated in the loop..

 

ldx #5

loop: lda ctab,x

sta colpm0,x

jsr count

dex

cpx #0

bne loop

jmp XITVBV

 

ctab: .byte $2,$4,$6,$8,$A,$C

delay .byte $32

 

count: dec delay

lda delay

bmi cycle

 

cycle: lda #32

sta delay

rts

 

So i'm stuck there with it, I can't seem to get the delay before storing to work??

Edited by Tezz
Link to comment
Share on other sites

I am not sure exactly what you are trying to do here and what you mean by too fast? where does ctab get filled in?

 

 

edit:

ah I read back a little farther in the thread. I think you want to be doing the loop to copy ctab to the color everytime. It is the part where you are actually rotating the colors in ctab that you want to skip based on the timer.

Edited by kenfused
Link to comment
Share on other sites

I am not sure exactly what you are trying to do here and what you mean by too fast? where does ctab get filled in?

 

 

edit:

ah I read back a little farther in the thread. I think you want to be doing the loop to copy ctab to the color everytime. It is the part where you are actually rotating the colors in ctab that you want to skip based on the timer.

Hi Ken, thanks for the reply. in my vbi, the part of the code for the actual loop to rotate through the 6 values in the table (without the delay yet) is like this below..

 

ldx #5

loop: lda ctab,x

sta colpm0,x

dex

bpl loop

jmp XITVBV

 

I assumed that the delay must now come before it stores the values to the colour registers,

EDIT ** I mean before the next time around in the loop

 

so I added the timer like this

 

ldx #5

loop: lda ctab,x

sta colpm0,x

dex

LDA TIMER

AND #1

bpl loop

jmp XITVBV

 

but that just crashes the Atari, i think this is because the loop is waiting for a branch when positive checking the status so adding lda timer and #1 messes that up. I tried instead to do it in a few different ways like in the above post but all my attempts didn't work, they either crashed the Atari or didn't add the speed delay?

 

the only code before that loop is Heavens example at the start of this thread to rotate the values in the table once on each pass through which works fine, i just need to delay the speed that the actual colours store and hence slow the speed that the colours rotate around.

 

Thanks,

Tezz

 

EDIT ** I just tried this below, it didn't crash the atari but it also had no effect on the speed at all

 

ldx #5

loop: LDA TIMER

AND #1

lda ctab,x

sta colpm0,x

dex

bpl loop

jmp XITVBV

Edited by Tezz
Link to comment
Share on other sites

Is what you're trying to do make it so that the colour change doesn't happen every frame e.g. only happens once every couple of seconds? If so, I would reckon the best way of doing it is to count frames rather than trying to introduce a delay inside your VBI routine (any sort of delay in a time critical thing like an interrupt routine is generally a bad idea as you can crash the machine). Something like this might do the trick:

 

FCOUNT    .BYTE $31 ; Every 50 frames
         ;
VBLRTN    PHA
         TXA
         PHA
         LDX FCOUNT
         DEX
         ; Have we waited the desired number of frames
         CPX #$00
         BNE DONE
         ; If so, do whatever it is you're doing e.g.
         LDA BAK
         ADC $0F
         STA BAK
         ; Reset the frame counter
         LDX #$31
         ; Store new frame counter value
DONE      STX FCOUNT
         PLA
         TAX
         PLA
         JMP XITVBV

Link to comment
Share on other sites

Is what you're trying to do make it so that the colour change doesn't happen every frame e.g. only happens once every couple of seconds? If so, I would reckon the best way of doing it is to count frames rather than trying to introduce a delay inside your VBI routine (any sort of delay in a time critical thing like an interrupt routine is generally a bad idea as you can crash the machine). Something like this might do the trick:

 

FCOUNT    .BYTE $31 ; Every 50 frames
         ;
VBLRTN    PHA
         TXA
         PHA
         LDX FCOUNT
         DEX
         ; Have we waited the desired number of frames
         CPX #$00
         BNE DONE
         ; If so, do whatever it is you're doing e.g.
         LDA BAK
         ADC $0F
         STA BAK
         ; Reset the frame counter
         LDX #$31
         ; Store new frame counter value
DONE      STX FCOUNT
         PLA
         TAX
         PLA
         JMP XITVBV

Hi, thanks that method sounds like a better idea. Everything I have tried so far crashes. You are right by the way, I'm trying to update the colours from the rotating table roughly every 1/2 second so I think counting the frames is prob a good idea rather than having a delay in the vbi. I was having a rethink before I read your reply and I tried this code below a few minutes ago..

 

ldx #5

 

TIMING: INC COUNT ;TIMING LOOP

LDA COUNT

CMP LIMIT

BNE loop

 

loop: LDA #0

STA COUNT ; reset counter

lda ctab,x

sta colpm0,x

dex

CPX #0

BNE TIMING

bpl LOOP

jmp XITVBV

 

ctab: .BYTE $2,$4,$6,$8,$A,$C

COUNT: .BYTE $00 ;HOW MANY DELAYS SO FAR

LIMIT: .BYTE $08 ;THIS CONTROLS TIME DELAY

 

yet again this just crashes!

 

I'll start working now on implementing your frame count idea!

 

Thanks for your help :)

Link to comment
Share on other sites

Try to modify it like this, it should make colour change every 8 frames (8/50 seconds, as you had 8 in limit).

 

ldx #5

TIMING: INC COUNT;TIMING LOOP
LDA COUNT
CMP LIMIT
BEQ loop
jmp XITVBV

loop: LDA #0
STA COUNT; reset counter
lda ctab,x
sta colpm0,x
dex
bpl LOOP
jmp XITVBV

ctab: .BYTE $2,$4,$6,$8,$A,$C
COUNT: .BYTE $00;HOW MANY DELAYS SO FAR
LIMIT: .BYTE $08;THIS CONTROLS TIME DELAY

Edited by MaPa
Link to comment
Share on other sites

Try to modify it like this, it should make colour change every 8 frames (8/50 seconds, as you had 8 in limit).

 

ldx #5

TIMING: INC COUNT;TIMING LOOP
LDA COUNT
CMP LIMIT
BEQ loop
jmp XITVBV

loop: LDA #0
STA COUNT; reset counter
lda ctab,x
sta colpm0,x
dex
bpl LOOP
jmp XITVBV

ctab: .BYTE $2,$4,$6,$8,$A,$C
COUNT: .BYTE $00;HOW MANY DELAYS SO FAR
LIMIT: .BYTE $08;THIS CONTROLS TIME DELAY

Thanks, that was a big help! :) It's nearly there now, the delay is working and is not crashing any more but what the routine is doing now is executing the wait and then it updates all of the values together at once so instead of a slow rotation, it blinks through all the changes every 8 frames. That's my fault in the way I tried to implement the delay at the wrong point, I think it will need to have the timing loop inside the main colour rotate loop before it stores the new colour value

 

Looking at my full vbi code now below, i think it should include the rotating of the values within the table in the loop also..

 

SETVBV equ $E45C

XITVBV equ $E462

colpm0 equ $D012

 

org $0600

 

START: PLA

LDA #7

LDY #VBROUT&255

LDX #VBROUT/256

JSR SETVBV

RTS

 

VBROUT: ldx ctab ; now rotate from right to left

lda ctab+1

sta ctab

lda ctab+2

sta ctab+1

lda ctab+3

sta ctab+2

lda ctab+4

sta ctab+3

lda ctab+5

sta ctab+4

stx ctab+5

 

ldx #5

 

TIMING: INC COUNT ;TIMING LOOP

LDA COUNT

CMP LIMIT

BEQ loop

jmp XITVBV

 

loop: LDA #0

STA COUNT ; reset counter

lda ctab,x

sta colpm0,x

dex

bpl LOOP

jmp XITVBV

 

ctab: .BYTE $2,$4,$6,$8,$A,$C

COUNT: .BYTE $00 ;HOW MANY DELAYS SO FAR

LIMIT: .BYTE $08 ;THIS CONTROLS TIME DELAY

 

================================================================================

 

After thinking about it some more I wrote this below...

 

SETVBV equ $E45C

XITVBV equ $E462

colpm0 equ $D012

 

org $0600

 

START: PLA

LDA #7

LDY #VBROUT&255

LDX #VBROUT/256

JSR SETVBV

RTS

 

VBROUT: INC COUNT ;TIMING LOOP

LDA COUNT

CMP LIMIT

BEQ MAIN

;jmp XITVBV

 

MAIN: ldx ctab ; now rotate from right to left

lda ctab+1

sta ctab

lda ctab+2

sta ctab+1

lda ctab+3

sta ctab+2

lda ctab+4

sta ctab+3

lda ctab+5

sta ctab+4

stx ctab+5

 

ldx #5

 

loop: LDA #0

STA COUNT ; reset counter

lda ctab,x

sta colpm0,x

dex

bpl VBROUT

jmp XITVBV

 

ctab: .BYTE $2,$4,$6,$8,$A,$C

COUNT: .BYTE $00 ;HOW MANY DELAYS SO FAR

LIMIT: .BYTE $08 ;THIS CONTROLS TIME DELAY

 

This routine is totally wrong this way too! It is only updating one of the colour registers with the 6 values creating a rotating raster bar on each scanline ?

 

I thought this was going to be quite straight forward to do!

 

Any help appreciated!

 

Here's the code structure i am trying to do:

 

START*

read the current value from table

store the value in colour register (storing to COLPM0 - COLPF1)

decrease x to read next value from table (reading right to left)

loop this until the final 6th value has been read from the table and stored in the 6th colour register

wait 8 frames

now rotate the values in the table 1 byte from right to left

repeat START until the table has rotated back 6 times to the beginning

and then loop

 

Thanks,

Tezz

Edited by Tezz
Link to comment
Share on other sites

Try something like this:

 

vbi:			inc count
	lda count
	cmp limit 
	bne store

rotate:		 lda #0
	sta count

	ldx ctab
	lda ctab+1
	sta ctab
	lda ctab+2
	sta ctab+1
	lda ctab+3
	sta ctab+2
	lda ctab+4
	sta ctab+3
	lda ctab+5
	sta ctab+4
	stx ctab+5

store:		  ldx #5
loop:		   lda ctab,x
	sta COLPM0,x
	dex
	bne loop
	jmp XITVBV 


	.zeropage

count:		  .byte	   0


	.rodata

ctab:		  .byte	   $02,$04,$06,$08,$0A,$0C
limit:		 .byte	   $08

 

The code is doing this:

1. Check if we have counted enough VBIs. If not, jump to store (#3).

2. Clear the count. Rotate the color table (this is your code to rotate the table.)

3. Store the color table values to the color registers. This has to be done every VBI, since the OS will reset them from the shadow registers.

 

Oh, I used cc65 to code this up, so the syntax may look a little wierd to you.

testvbi.zip

Edited by Shawn Jefferson
Link to comment
Share on other sites

Thanks Shawn that worked first time! The syntax is virtually the same as MADS that I'm using now. It seems I was nearly there with my last attempt, I missed setting my table count with the ldx #5 as it was going through it each vb. you created the label store: ldx #5 which sorted that. Great! I can move on to the next things now that's done. I kept looking at this thinking it must be something simple I'm doing wrong :roll: Thanks for your help.. and for everyone else's help also ;)

Link to comment
Share on other sites

Yeah, you were nearly there, just needed some tweaking in the logic to make sure that the color regs are set every VBI cycle, and only rotated every X cycles. I didn't change your VBI routine that much, and I'm sure there are ways to optimize it (the other posters are much better at that than I!.) Took me a bit to figure out exactly what you were trying to do though! :) I originally thought it was something more complex.

 

PS. I just noticed that I put the color table (ctab) into the .rodata segment, and then proceed to change it! Doh! Anyone attempting to use my code to learn should just imagine I meant the .data segment instead. ;)

Edited by Shawn Jefferson
Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...