Splitscreen Scrolling using R#19 in MSX2

Page 1/13
| 2 | 3 | 4 | 5 | 6

By santiontanon

Paladin (819)

santiontanon's picture

07-08-2016, 18:39

Hi guys, I've been trying to get some smooth scrolling on MSX2 for my Transball games, and I'm having some problems.

What I'm trying to do for now is:
- I want to use VDP registers R#18 and R#23 to get hardware pixel-by-pixel scroll (as suggested to me here in the forums)
- That's not too hard, but the tricky part is that the top 8 pixels of the screen have a scoreboard that should not scroll.
- So, reading the V9938 manual I saw that there is a register R#19 with which I can set an interrupt to occur after a certain scanline is drawn. So, I thought I could set R#18 and R#23 to 0 for the first 8 lines, and then with that interrupt, set R#18 and R#23 to the actual scroll values for the rest of the screen.

Seems simple, but for some reason, I can't seem to get it right...

What I'm doing is:

Before starting the game, I set the registers as:

    ;; generate a line interrupt after the first 8 pixels (the score board):
    ld b,8
    ld c,19
    call WRTVDP

    ld a,(VDP_REGISTER_0) ;; read BIOS copy of register R#0	
    or #10	;; set bit 4 of register 0 to 1
    ld b,a
    ld c,0
    call WRTVDP

Then, in my TIMI interrupt, I read the value of status register S#01, and check if bit 0 is 1 (line interrupt) or 0 (interrupt telling me the whole screen has ben drawn).

I'm suspecting that my code to read S#01 might not be correct. I'm right now using a bunch of BIOS calls (to select register 1, and then select register 0 again, since I've read you should always leave register 0 selected):

    di
    ld b,1
    ld c,15
    call WRTVDP    
    call RDVDP
    push af
    ld b,0
    ld c,15
    call WRTVDP    
    pop af
    ei
    bit 0,a

Then depending on the status of the bit, for now I'm just setting R#23 to 0 or to 100 just to test, but what I see is simply that it always believes it is a "whole screen" interrupt, i.e. I don't seem to ever get a line interrupt.

So, my questions are:
1) is the basic idea correct?
2) if it is, then what am I missing?

Thanks a lot in advance guys! Smile

Login or register to post comments

By Victor

Champion (468)

Victor's picture

07-08-2016, 18:59

I think that you've seen this page... But here it is...

Grauws's split screen article

By ARTRAG

Enlighted (6234)

ARTRAG's picture

07-08-2016, 20:30

You can follow my code here
https://github.com/Maneldemo/Uridium-2-for-msx

Be aware: the rom works on real he an openmsx only

By santiontanon

Paladin (819)

santiontanon's picture

08-08-2016, 00:28

Thanks Victor! I had read Grauw's article, but unfortunately, that article assumes you already know how to do it, and is geared at clarifying some of the complex details. Since what I need to know is how to start doing it, none of my questions where answered there Smile My questions are much simpler, i.e.: I'd like to see example code that sets R#19 and all other related registers so that the line interrupt actually happens.

And Thanks Artrag too! I downloaded the Uridium 2 code, I think the code I am looking for is in file "isr.asm", functions "_isrinit" and "_scroll". I'll look at those in more detail tomorrow. But at a quick glance, your "_isrinit" is basically identical to what I wrote, except that I use BIOS calls rather than direct register access... I'll check "_scroll" later to see if there is something that I'm missing there...

By ARTRAG

Enlighted (6234)

ARTRAG's picture

08-08-2016, 00:34

My advice is to use ports and make it work, you will step back to bios later

By ToriHino

Champion (354)

ToriHino's picture

08-08-2016, 07:39

Maybe this video from Nyyrikki can help as well:
https://www.youtube.com/watch?v=cnqruXo-udA

By santiontanon

Paladin (819)

santiontanon's picture

08-08-2016, 17:20

Thanks ToriHino!

I finally found the problem! I have now a basic example working, so, I can get now to implement it into the game. The problem (in case anyone cares Smile ) was that I was setting my interrupt in the TIMI interrupt, instead of in the HKEY. As soon as I switched my interrupt code to HKEY everything worked magically.

I noticed it by realizing that ARTRAG's code directly sets the interrupt in address #0038, while I was using the TIMI interrupt. I noticed in Nyyrikki's video he used address #fd9a, which was different from the TIMI one I was using. So, changing that it works!

Thanks again guys!

In case it can be useful to anyone, here's a full working example of splitscreen pixel-by-pixel scroll (only works on MSX2 or higher):

;-----------------------------------------------
; BIOS calls:
WRTVDP: equ #0047
FILVRM: equ #0056
CHGMOD: equ #005f
;-----------------------------------------------
; System variables
VDP_REGISTER_0: equ #f3df
TIMI:   equ #fd9f       ; timer interrupt hook
HKEY:   equ #fd9a       ; hkey interrupt hook
;-----------------------------------------------
; VRAM map in Screen 2
NAMTBL2:  equ     #1800   ; name table address 
;-----------------------------------------------

    org 04000H   ; Somewhere out of the way of small basic programs
;-----------------------------------------------
    db "AB" ;   ROM signature
    dw Execute  ; start address
    db 0,0,0,0,0,0,0,0,0,0,0,0
;-----------------------------------------------

Execute:
    ld a,1      ; Change screen mode
    call CHGMOD

    call Set_MSX2_Interrupt    

    ld a,'A'
    ld bc,32*4
    ld hl,NAMTBL2
    call FILVRM
    ld a,'B'
    ld bc,32*22
    ld hl,NAMTBL2+32*4
    call FILVRM

Loop:
    jp Loop


Set_MSX2_Interrupt:
    di

    ld a,#c3    ;; #c3 is the opcode for "jp", so this sets "jp MSX2_SmoothScroll_Interrupt" as the interrupt code
    ld (HKEY),a
    ld hl,MSX2_SmoothScroll_Interrupt
    ld (HKEY+1),hl

    ;; set the line interrupt to trigger after the first 32 lines
    ld a,29
    out (#99),a
    ld a,19+128
    out (#99),a

    ;; activate line interrupts:
    ld a,(VDP_REGISTER_0)
    or #10
    ld (VDP_REGISTER_0),a
    out (#99),a
    ld a,0+128
    out (#99),a

    ei
    ret



MSX2_SmoothScroll_Interrupt:
    push af
        
    ;; if bit 0 of register S#1 is 1, this is a line interrupt
    ;; read S#1:
    ld a,1  ; read S#1
    out (#99),a
    ld a,128+15
    out (#99),a
    in a,(#99)

    rrca
    jp c,MSX2_SmoothScroll_Interrupt_Line_Interrupt 

    ;; We get to this point if it's a vertical sync interrupt:
    xor a   ; read S#0 (otherwise, the program hangs)
    out (#99),a
    ld a,128+15
    out (#99),a 
    in a,(#99)

    ;; Set NO vertical offset:
    ld b,0
    ld c,23
    call WRTVDP

    pop af
    ret

    ;; We get to this point if it's a line interrupt:
MSX2_SmoothScroll_Interrupt_Line_Interrupt:
    xor a   ; read S#0 (otherwise, the program hangs)
    out (#99),a
    ld a,128+15
    out (#99),a 
    in a,(#99)

    ;; Set a moving vertical offset to simulate scroll:
    ld a,(vertical_scroll_for_r23)
    inc a
    and #0f ; modulo 16
    ld (vertical_scroll_for_r23),a
    ld b,a
    ld c,23
    call WRTVDP

    pop af
    ret

End:         

    ds 8000h - $

    org #c000
RAM:    
vertical_scroll_for_r23:
    ds virtual 1

By Victor

Champion (468)

Victor's picture

08-08-2016, 20:28

santiontanon wrote:

I finally found the problem! I have now a basic example working, so, I can get now to implement it into the game.

Yes!! Great!! Waiting to see that in your game.

Thanks for sharing the code... I'll take a look....

By santiontanon

Paladin (819)

santiontanon's picture

09-08-2016, 17:26

ok! almost there!

Here's a video of my first working version: https://youtu.be/ubRILtWu0eU

There are still 2 glitches:
- garbage appears at the bottom of the screen (easy fix)
- sprites flicker awfully when they are in the top half of the screen (this I still need to figure out why)

I am a bit confused as to why the second one happens. I guess understanding the timing of when the Sprite attributes are read with respect to when the screen is drawn would help. I'll dig into the VDP manual, but any help on that would be appreciated :)

By ARTRAG

Enlighted (6234)

ARTRAG's picture

09-08-2016, 18:39

All depends by the time you write the updated SAT with respect to the raster beam
I would say you are updating the SAT in the end of your isr routine
You should make sure to write the sprite attributes after the vsync interrupt (line192) but before the line interrupt (line 8)

By Victor

Champion (468)

Victor's picture

09-08-2016, 18:53

With masks in the right and left borders... It would be perfect...

Page 1/13
| 2 | 3 | 4 | 5 | 6