News:

Printed Amstrad Addict magazine announced, check it out here!

Main Menu
avatar_teopl

Cpctelera: screen distorion

Started by teopl, 21:51, 01 December 19

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

teopl

Hi!

Only sometimes I get image like this: (once in a few minutes of trying)



I suspect that it happens when I disable/enable interrupts but I don't understand what is the reason behind this and how to properly solve this?

I guess I did not do something to sync things or maybe interrupt functions takes longer then supposed or I messed up registers... I can only guess since I don't understand it but I guess someone more experienced already had this issue.

Any idea about why is this happening or how to debug?

cperezgrin

As far as I know about CPC (not much ;D ), this can be caused by two factors:- Something is changing your video memory (#C000-#FFFF)
- Something is changing the start of the video memory address (CRTC Register)
So you can check in debug mode if the video memory is changing.
Are you using doble buffer for render the screen?

Arnaud

#2
Hi,

- If you are drawing in interruption, the problem could be it takes more time than interrupt. In this case you should externalize this function.

- When you disable interrupt you have to synchronize before relaunch it :


cpct_waitVSYNC();

__asm
halt
halt
__endasm;

cpct_waitVSYNC();

cpct_setInterruptHandler(interruptFunction);

teopl

cperezgrin:

I am not using double buffer so there should be no moving of screen.
It crossed my mind that something is changing the start of the video memory address (CRTC Register) but it's not me :)
It may be Arkos player or some other asm routines I use...

But why is then usually OK and only sometimes is wrong?

arnaud:

This indeed sounds like the long interrupt function - I am not drawing but I have some arithmetics, few ifs and (and this is suspicious) I change palette inside interrupt (and accessing indexed array).

Also I am already syncing on start like this:

            // sync
            cpct_waitVSYNC();
            __asm__("halt");
            __asm__("halt");
            cpct_waitVSYNC();

            cpct_setInterruptHandler(teopl_interrupt_handler);


I guess it's the same like the code you posted.

To be precise, this is my (new) interrupt function so I hope it will not cause more issues like that.

Please let my know is something looks wrong...


static void teopl_interrupt_handler(void) {

    cpct_setPalette(g_teopl_video_palette_game[_tick], 4);

    _tick_dt_prepared++;
   
    // ---

    cpct_scanKeyboard_if();

    if (!g_teopl_interrupt_keyboard_event) {

        if (cpct_isAnyKeyPressed_f()) {

            g_teopl_interrupt_keyboard_event = 1;
        }
    }

    // ---

    if (_tick == 5) {

        _tick = 0;

        teopl_sound_play();
    }
    else {
        _tick++;
    }
}

Arnaud

@teopl,
at first glance your interrupt function seems to be ok.
Try to remove your functions inside the interrupt to see what happened.

It looks like your screen memory pointer have an offset applied.

Btw if you are out of ideas your can send me your code, i'll take a look.





cperezgrin

Hi, something I have learnt a few days ago. The cpctelera Arkos play function uses the alternative registers (AF',BC',...) but the interrupt handler only saves and restores the normal register. This may cause some random behaviour if the int is triggered in the middle of a function that uses alternative register (like easytiles). Arkos music play will change the value of the alternative register while the inthandler function is executing, and the original value is lost.
So you should manually save and restore the value of the alternative registers begore using Arkos' musicPlay.

teopl

I know that arkos is using all registers from this post http://www.cpcwiki.eu/forum/programming/cpctelera-arkos-2-conversion-problem/msg176450/#msg176450

... but I did not think a lot about that

Also, here http://lronaldo.github.io/cpctelera/files/firmware/cpct_setInterruptHandler-s.html it says:

However, be very careful if you modify the alternate set of registers (AF', BC', DE', HL') as they will not be saved by default.  User is responsible for saving and restoring the values on the alternate register set whenever they are modified.  Otherwise, behaviour is undefined when returning from the function.

and since I call the arkos play which modifies all registers, that may be a problem.

Arnaud

If you are not using alternate register (by using easytilemap for example) there won't be any problems.

I just take a look into your code of cpcretrodev and i haven't see use of it.

teopl

#8
@Arnaud yes, it looks like that I am not using alternate registers except from the interrupt when calling arkos player.

My current code is not that different from the cpcretrodev, one difference is:

- interrupt function is little longer
- I am setting the palette inside the interrupt function
- I am setting pallete after removing interrupt
- ... (something else?)

(I am experimenting on ways to use screen memory so I want to hide it with palette changes)

I did not test this on real machine, only winape.

When it happens, the game works normally except the screen is moved by offset... But I am not moving it and it happens rarely so I can't know if it's fixed until I know the exact reason for this.

------------------
(Edit: Turns out I am calling some arkos stop functions when disabling interrupts, I think I managed to always reproduce the issue so I will investigate more and let you know the results...)

Arnaud

Quote from: teopl on 22:12, 03 December 19Turns out I am calling some arkos stop functions when disabling interrupts, I think I managed to always reproduce the issue so I will investigate more and let you know the results...)

I encountered problem when i used arkos2 functions in same time in interrupt and in main code.
The solution was to put all arkos2 functions in interrupt and control them with  global flags.

teopl

Quote from: Arnaud on 08:56, 04 December 19
I encountered problem when i used arkos2 functions in same time in interrupt and in main code.
The solution was to put all arkos2 functions in interrupt and control them with  global flags.

yes, looks like this is the reason, thanks! Although the play function was called from interrupt, I was calling the stop and all the sfx play functions from the main program so this is fixed like you described.

Powered by SMFPacks Menu Editor Mod