News:

Printed Amstrad Addict magazine announced, check it out here!

Main Menu
avatar_EgoTrip

[CPCtelera] Interrupts and palette changes

Started by EgoTrip, 18:05, 11 September 16

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

EgoTrip

I used the example project to change the border during each interrupt. It works first time, but positions change (often when I change palette and stuff) and mess everything up. How do I ensure that it remains constant?

arnoldemu

Quote from: EgoTrip on 18:05, 11 September 16
I used the example project to change the border during each interrupt. It works first time, but positions change (often when I change palette and stuff) and mess everything up. How do I ensure that it remains constant?
Please can you post some code?

Positions will change if interrupts are disabled too long (check the cpctelera documentation because it should say which functions will disable interrupts).

Also, in the interrupt function you need to do as little as possible. Doing too much will delay the next interrupt and make them move.

Palette changes, mode changes, scanning keyboard, playing music should be ok, but don't try to do all in the same interrupt, you have 6 so you need to spread the work. In the interrupt function have a number you increment. When it reaches 6 set it back to 0. Then you can do something like this:


if (interruptIndex==1)
{

}
else if (interruptIndex==2)
{
}
interruptIndex++;
if (interruptIndex>=6)
{
interruptIndex = 0;
}
etc


Another thing is that setting the interrupt in cpctelera probably always starts it almost immediately.

If you want changes at the same place then you need to synchronise it with a point on the display, the best is the vsync.

Wait for vsync start, then enable interrupts and they should always be in the same order.



My games. My Games
My website with coding examples: Unofficial Amstrad WWW Resource

EgoTrip

My code is essentially the same as yours, and theres nothing in it except the music play call and the palette change.

I did set it up directly after the cpct_waitVSYNC(); but it still messes up.

arnoldemu

Quote from: EgoTrip on 22:02, 11 September 16
My code is essentially the same as yours, and theres nothing in it except the music play call and the palette change.

I did set it up directly after the cpct_waitVSYNC(); but it still messes up.
Ok I will make some code that will work. :)

My games. My Games
My website with coding examples: Unofficial Amstrad WWW Resource

Arnaud

#4
Some functions can disable interruptions, for example reenable firmware for read file or cpct_scanKeyboard_f

arnoldemu

Example below. I had to add some inline assembler to ensure synchronisation was good.
My games. My Games
My website with coding examples: Unofficial Amstrad WWW Resource

Arnaud

A question why are you waiting for next VSync at the end of VSync ?

Wait one VSync and start immediatly the interrupt cannot work ? (it should explains why sometime my colors are totaly desynchronized in my code)

   
    // wait start of vsync (but also if vsync is active it will return immediately)
    cpct_waitVSYNC();
   
    // wait end of vsync
    __asm
    ld b,#0x0f5
    wve:
    in a,(c)
    rra
    jr c,wve
    __endasm;
   
    // wait start of next
    cpct_waitVSYNC();


arnoldemu

Quote from: Arnaud on 20:06, 12 September 16
A question why are you waiting for next VSync at the end of VSync ?
cpct_waitVsync does two things:
1. if vsync has not started it will wait for start of vsync.
2. if vsync has started it will break immediately.

2 is a problem.

Normally int comes 2 lines after start of vsync, but if 2 happens, then it could be after this time. So problem comes if we can't know if before or after.

So the fix:
- cpct_waitVsync
- wait for vsync to end.
- cpct_waitVsync

This will always work. I will give ronaldo a new function.

:)

My games. My Games
My website with coding examples: Unofficial Amstrad WWW Resource

ronaldo

@arnoldemu there is another way to do this in CPCtelera, besides your nice classical approach :) . You can use cpct_count2VSYNC(). This code would do the trick:

while(cpct_count2VSYNC() == 1);
cpct_setInterruptHandler ( interruptHandler);

cpct_count2VSYNC does the same as cpct_waitVSYNC but counting the number of loop interations it waits until it finds VSYNC active. If it is called with VSYNC active, it will return immediately with a value of 1. If it is called when VSYNC is not active, it will return with a value greater than one.

Of course you can refine this a little bit by disabling interrupts, but that's mostly the approach without using asm :) .

However, I'm not sure if this is the problem that @EgoTrip is describing. I'm curious to see his source, because I don't fully understand what he is referring to.

EgoTrip

I can't get your code to work @arnoldemu it just throws up loads of compiler errors.

Also yours doesn't work either @ronaldo it still doesn't stay synchronised.

arnoldemu

Quote from: ronaldo on 23:17, 12 September 16
@arnoldemu there is another way to do this in CPCtelera, besides your nice classical approach :) . You can use cpct_count2VSYNC(). This code would do the trick:

while(cpct_count2VSYNC() == 1);
cpct_setInterruptHandler ( interruptHandler);

cpct_count2VSYNC does the same as cpct_waitVSYNC but counting the number of loop interations it waits until it finds VSYNC active. If it is called with VSYNC active, it will return immediately with a value of 1. If it is called when VSYNC is not active, it will return with a value greater than one.

Of course you can refine this a little bit by disabling interrupts, but that's mostly the approach without using asm :) .

However, I'm not sure if this is the problem that @EgoTrip is describing. I'm curious to see his source, because I don't fully understand what he is referring to.
@ronaldo: cpct_count2VSYNC() doesn't count 2 vsyncs. :(
It seems to times the length of the vsync or similar to that by incrementing HL.

No I need to ensure that I see the start of a vsync and the only way to do that is wait for it to end, and then wait for a new one to begin.




My games. My Games
My website with coding examples: Unofficial Amstrad WWW Resource

arnoldemu

Quote from: EgoTrip on 08:44, 13 September 16
I can't get your code to work @arnoldemu it just throws up loads of compiler errors.

Also yours doesn't work either @ronaldo it still doesn't stay synchronised.
I am using cpctelera 1.4. You will need to rename main.txt to main.c because I had to rename it to attach it here.
Can you put a couple of the errors here in a post?
My games. My Games
My website with coding examples: Unofficial Amstrad WWW Resource

EgoTrip

Error 1 was CPCtelera not liking the label in the code. So I removed it and had a jr c,-5 instead, then Error 2 was the console complaining about relocatable code or something, I am tying this from memory. I'll be able to give you full details later.

All I want to do is have colour splits on the title screen and make sure they are in the same places each time. But the game obviously messes up the interrupt orders with all the keypresses and stuff.

arnoldemu

Quote from: EgoTrip on 09:58, 13 September 16
Error 1 was CPCtelera not liking the label in the code. So I removed it and had a jr c,-5 instead, then Error 2 was the console complaining about relocatable code or something, I am tying this from memory. I'll be able to give you full details later.

All I want to do is have colour splits on the title screen and make sure they are in the same places each time. But the game obviously messes up the interrupt orders with all the keypresses and stuff.
yes the code does this. I modified the label to see if that helps. Updated main.txt attached.

I am using cpctelera-1.4 and sdcc-3.5.5 and I am compiling it on windows.


My games. My Games
My website with coding examples: Unofficial Amstrad WWW Resource

arnoldemu

I see that the existing cpctelera function cpct_count2VSYNC() is more of a timing thing. I have some good ideas to improve it :)

I have e-mailed the new library functions to ronaldo:

u16 cpct_getVSYNCActive()

returns immediately.  0 means VSYNC not active, non-zero means VSYNC active. Can be used inside an interrupt function to know if the int you are handling is the one triggered inside the vsync.

void cpct_syncVSYNCStart()

guarantees it syncs to the start of the VSYNC even if it means waiting an entire frame to see it. It replaces the "hack" code in my example.


My games. My Games
My website with coding examples: Unofficial Amstrad WWW Resource

EgoTrip

#15
nope, still getting

src/main.c:144: info 218: z80instructionSize() failed to parse line node, assuming 999 bytes
' wve::'


I tried it with jr c,-5 instead and it compiled but just reset the machine.

EgoTrip

I appear to have got it working. I used the code @ronaldo provided. In the example, it declared the static int i in the interrupt function, but instead I have declared it with all the rest of the variables. Then set i to 0 at the appropriate place. It seems to be synced right every time now, hopefully thats done.

Thanks for your help @arnold and @ronaldo

Powered by SMFPacks Menu Editor Mod