Something about IE0 / IE1 bits and R#19

Pagina 1/2
| 2

Door ARTRAG

Enlighted (6443)

afbeelding van ARTRAG

18-09-2008, 11:14

I need a screen split in screen 5 and I use IE1 and R#19.

I have RAM in Page 0.

My ISR code has two routines:

vdpregs0    equ 0f3dfh
vdpregs1    equ 0ffe7h-8

_interrupt1:
    push    af

; disable screen (test)

        ld  a,(vdpregs0+1)
        and 255-64
        ld  (vdpregs0+1),a        ; 3/13
        out (0x99),a
        ld  a,0x80 + 1
        out (0x99),a

; reset X scrolling

        xor a
        out (0x99),a
        ld a, 0x80 + 18
        out (0x99),a

; red color for test

        ld a,8
        out (0x99),a
        ld a, 0x80 + 7
        out (0x99),a

    push    hl    

; set the new line interrupt at a lower line

        ld  hl,_interrupt2
        ld  (0x0038+1),hl

        ld  hl,vdpregs1+23    ; 3/10
        ld  a,255            ; 2/7
        add a,(hl)           ; 1/7
        ld  (vdpregs1+19),a        ; 3/13
        out (0x99),a
        ld  a,0x80 + 19
        out (0x99),a

    pop hl

; reset the line interrupt flag enabling the next line interrupt

        ld a,1
        out (0x99),a
        ld a, 0x80 + 15
        out (0x99),a

    in a,(0x99)

        xor a
        out (0x99),a
        ld a, 0x80 + 15
        out (0x99),a
        
    pop af
    ret
    
_interrupt2:
    push    af

; green color for test

        ld a,3
        out (0x99),a
        ld a, 0x80 + 7
        out (0x99),a

; enable screen (test)

        ld  a,(vdpregs0+1)
        or 64
        ld  (vdpregs0+1),a        ; 3/13
        out (0x99),a
        ld  a,0x80 + 1
        out (0x99),a

    push    hl    

; restore the line interrupt at a higher line

        ld  hl,_interrupt1
        ld  (0x0038+1),hl

        ld  hl,vdpregs1+23    ; 3/10
        ld  a,11*16-2        ; 2/7
        add a,(hl)           ; 1/7
        ld  (vdpregs1+19),a        ; 3/13
        out (0x99),a
        ld  a,0x80 + 19
        out (0x99),a

    pop hl

; read the S#0 !!! why I need this ???

    in a,(0x99)

        ld a,1
        out (0x99),a
        ld a, 0x80 + 15
        out (0x99),a

; read the S#1 enabling the next line interrupt

    in a,(0x99)

        xor a
        out (0x99),a
        ld a, 0x80 + 15
        out (0x99),a
       
    pop af
	ret	
#endasm


In my main, at initialization time, I have:

        di

        ld  hl,_interrupt1
        ld  a,0xC3
        ld  (0x0038+1),hl
        ld  (0x0038),a

        ld  a,(vdpregs0)
        or  16
        ld  (vdpregs0),a        ; enable IE1
        out (0x99),a
        ld  a,0x80
        out (0x99),a

        ld  hl,vdpregs1+23    ; 3/10
        ld  a,11*16-2        ; 2/7
        add a,(hl)           ; 1/7
        ld  (vdpregs1+19),a        ; 3/13
        out (0x99),a
        ld  a,0x80 + 19
        out (0x99),a

        ei

At first glance the code works (tested on bluemsx)
I can see a red bar between line 11*16-2 and the end of the screen (line 192 in my test).

I've got the feeling that something does not work as it should...

If I set IE1 in R#0 I enable line interrupt at the line in R#19

The second interrupts was planned at line 255 !!
The green color, instead, starts midway at line 192 !!

My first question is:
a) Can we set line interrupts into the vertical border?

This leads to a new question:
b) is the line interrupt additional to the normal Vblank interrupt we get when IE0 is set ?
As I did not reset IE0 in R#1 I should continue to get the normal Vblank...
But that should prevent the call of interrupt2 at line 255...

I tried to disable IE0 (in theory no more vblank) but I get only a red screen, i.e. a call to interrupt1 and nothing else.
c) do IE1 AND IE0 interact?

Any expert here ?

Aangemeld of registreer om reacties te plaatsen

Van Edwin

Paragon (1182)

afbeelding van Edwin

18-09-2008, 12:22

I didn't analyse your code in detail, but I can give you some answers

a) That depends on whether you are in 50 Hz or not. For 60 Hz that last line you can use is slightly under 240 (I'd have to like up the exact number).

b, c) Yes, vblank is separate. I'm not sure what happens when you turn off vblank and leave only line interrupts on. Never tried that.

Not that you don't *have* to use the line interrupt, you can poll for it as well. This makes code much easier in some cases.

Van ARTRAG

Enlighted (6443)

afbeelding van ARTRAG

18-09-2008, 15:17

Edwin, if you are right, I should be able to set only ONE line interrupt at line 11*16-2, relying on vblank for the second interrupt.
In this case the following code should work, could you confirm ?

ISR routines:

vdpregs0    equ 0f3dfh
vdpregs1    equ 0ffe7h-8

_interrupt1:
    push    af

; disable screen (test)

        ld  a,(vdpregs0+1)
        and 255-64
        ld  (vdpregs0+1),a        ; 3/13
        out (0x99),a
        ld  a,0x80 + 1
        out (0x99),a

; reset X scrolling

        xor a
        out (0x99),a
        ld a, 0x80 + 18
        out (0x99),a

; red color for test

        ld a,8
        out (0x99),a
        ld a, 0x80 + 7
        out (0x99),a

    push    hl    

; set the new interrupt routine to be called at vblank

        ld  hl,_interrupt2
        ld  (0x0038+1),hl

    pop hl

; reset the line interrupt flag enabling the next line interrupt

        ld a,1
        out (0x99),a
        ld a, 0x80 + 15
        out (0x99),a

    in a,(0x99)

        xor a
        out (0x99),a
        ld a, 0x80 + 15
        out (0x99),a
        
    pop af
    ret
    
_interrupt2:
    push    af

; green color for test

        ld a,3
        out (0x99),a
        ld a, 0x80 + 7
        out (0x99),a

; enable screen (test)

        ld  a,(vdpregs0+1)
        or 64
        ld  (vdpregs0+1),a        ; 3/13
        out (0x99),a
        ld  a,0x80 + 1
        out (0x99),a

    push    hl    

; restore the line interrupt at a higher line

        ld  hl,_interrupt1
        ld  (0x0038+1),hl

    pop hl

; read the S#0 !!! why I need this ???

    in a,(0x99)
       
    pop af
    ret

Where in the main I have as before:

        di

        ld  hl,_interrupt1
        ld  a,0xC3
        ld  (0x0038+1),hl
        ld  (0x0038),a

        ld  a,(vdpregs0)
        or  16
        ld  (vdpregs0),a        ; enable IE1
        out (0x99),a
        ld  a,0x80
        out (0x99),a

; set line interrupt in R#19

        ld  hl,vdpregs1+23    ; 3/10
        ld  a,11*16-2        ; 2/7
        add a,(hl)           ; 1/7
        ld  (vdpregs1+19),a        ; 3/13
        out (0x99),a
        ld  a,0x80 + 19
        out (0x99),a

        ei

Can you confirm if this code is consistent with what you know ?

Van ARTRAG

Enlighted (6443)

afbeelding van ARTRAG

18-09-2008, 15:50

PS
Ignore the comment
; read the S#0 !!! why I need this ???

it should be
; read the S#0

I did cut&paste

Van ARTRAG

Enlighted (6443)

afbeelding van ARTRAG

18-09-2008, 17:53

Edwin
I tested the code in the second post and it hangs
It calls the inerrupt1 (line interrupts) just once and than it hangs!!

Interrupt2 is never called!!
Any explanation? (I use bluemsx)

Van Sonic_aka_T

Enlighted (4130)

afbeelding van Sonic_aka_T

18-09-2008, 19:04

I didn't really read through all the code, but I do know the LI is indeed seperate from VBLANK and I know you can set as many line interrupts (sequentially) as you can handle CPU-wise. Generally I even do two LI's for a single line interrupt event. First I set a line interrupt to ensure the code is interrupted at roughly the correct time (usually like 10 lines ahead). Then with ints disabled (of course) I re-set reg#19 to the actual line I want my effect and start polling the VDP. This ensures the effect will indeed occur at the desired line and gets rid of any cpu-dependant timing. Usually this will be line -1 or -2 by the way. Then I start polling HR to ensure the timing is just right. Often it's possible to pre-out some data, sending only the last byte of a VDP command when just in HR. When working with the BIOS ISR enabled always make sure you properly disable interrupts, select S#0 before enabling them, and ensure you restore registers as required...

Van ARTRAG

Enlighted (6443)

afbeelding van ARTRAG

18-09-2008, 20:06

Sonic can you post here a working segment of code ?
The description you did is very complex and evil is in details

Van Edwin

Paragon (1182)

afbeelding van Edwin

18-09-2008, 20:43

You only made one mistake as far as I can see. You need to EI at the end of your interrupt handler. It gets disabled when the handler is called. One of the little quirks creating your own $38 handler. Smile

Van Alex

Master (205)

afbeelding van Alex

18-09-2008, 21:39

You only made one mistake as far as I can see. You need to EI at the end of your interrupt handler. It gets disabled when the handler is called. One of the little quirks creating your own $38 handler. Smile

Another point is that you should return with a reti from the interrupt routine and not with a ret. The difference is that Z80 puts a few other signals on the control bus, which might be monitored by circuits (for examples in cartridges) that are interested to know when the Z80 returns from the interrupt routine.

Van Arjan

Paladin (718)

afbeelding van Arjan

18-09-2008, 21:46

Ah, didn't know that!
Also, make sure to check if it was really the VDP which generated the interrupt. You never know which other devices might generate an interrupt.

Van ARTRAG

Enlighted (6443)

afbeelding van ARTRAG

19-09-2008, 00:25

Thanks!!
I'll try asap

Pagina 1/2
| 2