Autor
| Smooth horizontal scroll on MSX2 using r#23
|
Metalion msx freak Mensajes: 235 | Publicado: Septiembre 05 2007, 20:26   |
Hi,
I'm making an horizontal scroll on MSX2 using the VDP r#23 (in SCREEN5 and in ASM). I feel that the scroll is not as smooth as it should be, even when synching to PC vertical blank on BlueMSX.
So I said to myself that maybe I need to use a scanline interrupt to make it smoother.
But I'm not sure it is necessary ...
I read somewhere that I could do it two ways :
- either a scanline interrupt (by setting r#19 and r#0)
- or simply set the r#19 and check on r#0 until the scanline bit is set by the VDP
I don't know (yet) how to handle VDP interrupts, anyone can help me on this ?
|
|
Edwin msx professional Mensajes: 620 | Publicado: Septiembre 05 2007, 20:59   |
First of all, r#23 is for vertical scrolling, not horizontal.
And no, you shouldn't need a line interrupt to make it smooth. You will need that if you want to have a static score panel or something like that. For full screen scroll syncing to vblank is enough. However, on an emulator it may not appear smooth because the refresh frequency of you PC monitor is probably not a multiple of the msx frequency.
VDP triggers interrupts which can be checked inside an interrupt handler by reading the appropriate status register.
|
|
dvik msx master Mensajes: 1312 | Publicado: Septiembre 05 2007, 21:26   |
In bluemsx, the best result for scrollers is with the "Asynchronous PC Vblank" mode. Then the emulator interpolates the msx framerate to the PC framerate and the result is quite smooth.
|
|
Metalion msx freak Mensajes: 235 | Publicado: Septiembre 05 2007, 23:13   |
Quote:
| First of all, r#23 is for vertical scrolling, not horizontal
|
Yes, you are right of course, I meant vertical ...
Quote:
| VDP triggers interrupts which can be checked inside an interrupt handler by reading the appropriate status register
|
OK I understood that I don't need a scanline interrupt, but for the sake of learning a little bit, I would like to have more details about those type of interrupts. The interrupt handler is managed by a RST 038h, which in turns calls the 0FD9Ah hook in the system area. Am I right so far ?
But this hook is also called every 50th (or 60th) of a second by a timer (maybe the clock itself ?). So how do you know if the interrupt is generated by the VDP or if it is a standard interrupt ?
Also, I read (I think it was on the MSX Assembly website) that if you wanted to do some specific stuff after a scanline, you could also choose not to set the interrupt enabling bit (IE1) in r#0, and only check on r#0 until the scan interrupt flag (F) is set in s#0. Anyone can confirm this ?
Quote:
| In bluemsx, the best result for scrollers is with the "Asynchronous PC Vblank" mode
|
Thanks dvik, I will try this ASAP.
|
|
Edwin msx professional Mensajes: 620 | Publicado: Septiembre 06 2007, 01:11   |
The VDP vertical blank interrupt *is* actually the standard interrupt (on which the FD9F hook is also called).
However, in hook FD9A you can check whether the interrupt is a vblank by testing bit 7 of VDP status register 0. Note that reading it will reset the interrupt flag.
The line interrupt works by setting a line in register 19. If you set the IE1 bit, the VDP will generate an interrupt when the retrace arrives at that line. You can check this by testing bit 0 in VDP status register 1. You can indeed not set IE1 and poll the bit to wait for the line.
The polling trick does not work for the vblank bit though. It works in emulators, but on the real thing you will lose irqs because the bit gets reset before it's set to 1.
|
|
Metalion msx freak Mensajes: 235 | Publicado: Septiembre 06 2007, 08:57   |
Quote:
| The VDP vertical blank interrupt *is* actually the standard interrupt
|
I see, so it means that there is only one interrupt call, always generated by the VDP.
When does that interrupt happens when the scanline interrupt is not set in r#19 and r#0 ?
At scanline zero ? |
|
Edwin msx professional Mensajes: 620 | Publicado: Septiembre 06 2007, 19:58   |
I think you may have misunderstood me a bit. The vblank interrupt and the line interrupt are separate interrupts that originate from the vdp. The vblank interrupt is used by the system as the standard interrupt. They can be turned on and off with the IE0 and IE1 bits.
The vblank interrupt occurs at the bottom of the screen where the border starts.
R#19 is the register where you can specify at which line the line interrupt should occur.
Of course, since the z80 only has one interrupt line, you'll have to check with the vdp which of the two interrupts occurred. (if any, because an external device could also have caused an interrupt)
|
|
Metalion msx freak Mensajes: 235 | Publicado: Septiembre 06 2007, 20:39   |
OK, I get it ... Thanks.
Now, what I would like to know is how do you manage an interrupt routine (from vblank) when you want to do simultaneous things on screen. For example, you're sending data to the VDP on the main program, and you want the interrupt to handle another graphic task elsewhere on the screen (let's say you want to draw a line).
I suppose you have to break down the background task in little parts so they can be handled during an interrupt ?
How many Z80 ops can you squeeze in an interrupt without disturbing the main code ?
Do you use some kind of incremented timer to sequence things ?
I suppose the standard interrupt is also used to send music data to PSG or SCC ?
That's a lot of questions, but I am finally willing to do something with interrupts (20 years later than expected !), and I don't know where to start.
|
|
Edwin msx professional Mensajes: 620 | Publicado: Septiembre 06 2007, 21:49   |
What you do with the interrupt is basically your own choice. You don't even have to put any useful code in the interrupt routine at all, you can just use it for synchronisation.
As for amount of stuff you can squeeze in. You can do everything in the interrupt. Just be sure that you don't get in interrupt while still being inside an interrupt handler. Could get messy.
But music players are common. But if you're going to do things that are heavy on the vdp, you may want to realise that the vdp can transfer stuff much quicker during vblank. So best make use of that when you need it. Otherwise there is no set plan or some fixed rules. All up to your own code design.
|
|
AuroraMSX
 msx master Mensajes: 1249 | Publicado: Septiembre 07 2007, 21:24   |
Quote:
| The vblank interrupt occurs at the bottom of the screen where the border starts.
|
Really? So, one could regard the VBLANK interrupt as a line interrupt on line 212?  I actually thought the VBLANK interrupt was generated when the vertical retrace starts - at the end of the video frame. This is much later than "at the bottom of the screen, where the border starts" ... |
|
[D-Tail]
 msx guru Mensajes: 3018 | Publicado: Septiembre 08 2007, 11:48   |
When you'd play with R#23, the bottom of the screen varies - it's no longer per se 192 or 212. Hence, I guess that VBLANK occurs after line 255. But I'm too lazy to look that up right now, hehe.
|
|
NYYRIKKI msx master Mensajes: 1510 | Publicado: Septiembre 08 2007, 20:15   |
VBLANC always occurs in same place (about the border start as Edwin said) AFAIK R#23 content does not have any effect on that.
Test program: 10 _TURBO ON
20 '#I 118
30 COLOR,4:COLOR,0:GOTO20 |
|
Alex msx lover Mensajes: 96 | Publicado: Septiembre 08 2007, 23:53   |
I concur with NYYRIKKI and Edwin that VBLANC occurs at start of bottom border. Note that it is influenced by bit 7 of R#9, which indicates the number of display lines (192 or 212).
I have never tried what happens with VBLANC interrupt if you apply the 'border overscan trick' by flipping bit 7 of R#9 between line 192 and 212. I assume that VBLANC interrupt will not happen in such case.
|
|
Metalion msx freak Mensajes: 235 | Publicado: Septiembre 09 2007, 17:14   |
Thanks for all these informations.
How do you do when you want the interrupt to handle a major jump in your program ?
For example, let's say the main program does the demo/intro part of a game, and you're using the interrupt to play the music and check if the player is pressing a key to start the game. Here is how I see it :
- You modify the interrupt hook (either a new address to use during the game, or you close it with a RET)
- You make a JP to the start of your game program
But it means that you will never return from the call made at the hook by the $38 routine. Is that a problem ?
Maybe the interrupt hook call is the last thing made by the $38 routine ?
|
|
|
|
|