VDP Status register , what do i miss here?

Pagina 2/2
1 |

Van Wlcracks

Champion (487)

afbeelding van Wlcracks

16-02-2018, 17:05

cool thanks for this tip i will study this.

Van TomH

Champion (327)

afbeelding van TomH

16-02-2018, 19:23

Cool. I realise I forgot fully to explain the logic behind my suggestion though. In interrupt mode 2 the Z80 expects the peripheral causing the interrupt to supply a value identifying itself during the interrupt cycle. It uses the I register as the high byte and the value supplied by the peripheral to form the address from which to fetch the address of the interrupt handler. So the intention was to allow vectored interrupts.

I don't think the MSX bus is required to be in any particular state during the interrupt cycle, so you have no idea what will be picked as the low byte of the address. You don't even know whether it'll be even or odd.

So the 16-bit vector might be loaded from any of 256 addresses.

You therefore put your interrupt routine at an address where high byte = low byte, and put that byte into a table 257 times because then it doesn't matter which address the Z80 starts reading the vector from. It'll always end up with the address of your routine.

That all being said, it strikes me that: (i) you're going to have to assume your RAM is always paged in when the interrupt occurs for that to be safe; and (ii) if you can safely assume you've taken full control over paging, you could just put RAM in the lowest bank and place your routine at 0038h. I guess the only difference is whether you want to make 64kb RAM a requirement.

Van Wlcracks

Champion (487)

afbeelding van Wlcracks

17-02-2018, 09:43

Thank you again for your response.

Because i am using SDCC for my little project, i am still troubling with doing this the easy way. IM2 is kinda tricky in my current "workflow".

Polled timing:




Works fine for me to run the code on timed, but i wanted to disable the system interrupts temporary.

I took ROADFIGHTER rom and had a look how konami did it.

They basically hook the whole game on HKEYI. They use a trick for not allowing the system to continue with HTIMI and updating the rest of the system.
Just before they return from HKEYI hook they add:

call 013e

So i guess this is a trick to fool the bios that the vdp didnt generate the interrupt

bios part:

0C3C:   push   hl         
0C3D:   push   de         
0C3E:   push   bc         
0C3F:   push   af         
0C40:   exx               
0C41:   ex     af,af'     
0C42:   push   hl         
0C43:   push   de         
0C44:   push   bc         
0C45:   push   af         
0C46:   push   iy         
0C48:   push   ix         
0C4A:   call   #fd9a      
0C4D:   in     a,(#99)    
0C4F:   and    a          
0C50:   jp     p,#0d02    
0C53:   call   #fd9f      

slowing down system stuff here

0D02:   pop    ix         
0D04:   pop    iy         
0D06:   pop    af         
0D07:   pop    bc         
0D08:   pop    de         
0D09:   pop    hl         
0D0A:   ex     af,af'     
0D0B:   exx               
0D0C:   pop    af         
0D0D:   pop    bc         
0D0E:   pop    de         
0D0F:   pop    hl         
0D10:   ei                
0D11:   ret               

I still dont know how to refer to direct (dynamic) address in SDCC on an interrupt, this looks like a solution for now.

Hope to release my little project soon, working more then a year on this... Yes i suck. Wink

Van Eugeny_Brychkov

Paragon (1225)

afbeelding van Eugeny_Brychkov

18-02-2018, 14:34

Some time ago I caught exactly the same issue when developing something for GR8NET (video player or MP3 player, do not remember exactly). I do not recall how I got this info, most probably someone knowledgeable told me here on the forum.

Solution: it is completely BAD idea to poll status register of the VDP. There are circumstances when interrupt condition occurs, some internal flag is being set, but by reading S#0 you still read old value of 0, but that internal flag gets reset, thus it never appears set in S#0 bits. That's why you miss interrupt condition.
The ONLY reliable way to get 50/60 Hz (and I guess other types of interrupt) from the VDP is using ISR, this way you are 100% complete with correct interrupt flag processing and interrupt-related bits are being improperly handled.

If you are in BASIC and need performance, the only way to get Z80 jumping to your ISR is to use IM2 mode (as previously stated), having I register preset appropriately before you enable interrupts. It will require a jump table of 257 byte size with the same content so that reading from any (addr) LSB and (addr+1) MSB location within this table return the same 16-bit address (e.g. filling table with &h81 will cause jump to address &h8181), not depending on what would-be peripheral device supplies. By the way, looking through Z80 datasheet I do not see it properly and explicitly stating at which bus interrupting device must put vector to - to address A[7:0] or to data D[7:0]!

Van maxis

Champion (512)

afbeelding van maxis

18-02-2018, 17:24

Eugeny_Brychkov wrote:

By the way, looking through Z80 datasheet I do not see it properly and explicitly stating at which bus interrupting device must put vector to - to address A[7:0] or to data D[7:0]!

Eugeny, the device vector always comes to D[7 : 0] on the interrupt vector request -> !M1 & !IORQ.

Z80 address bus is either output or tri-stated.

BEWARE of Z80 and its clones fetching the interrupt table content from ODD addresses when supplied with the ODD vector on the data bus. Z80 manual is mute about it and emulators often ZERO the address bit 0, which is wrong. The real Z80 and its clones take the ODD table entry (0xFF in the LSB) and continue to the next address for the MSB for the jump address fetch when provided with 0xFF on the data bus.
Regarding the ODD device vector address (forbidden combination for the normal CPU operation) here are a few considerations:
- MSX1/2/2+ has historically the pull-up resistors on the databus. I.e. any I/O read yields 0xFF. However, the device vector address must be EVEN, but since 0xFF is returned on an empty data bus it will be ODD. Therefore the ISR address will be fetched from :
LSB is fetched from (I_reg<<8) + 255
and MSB is fetched from (I_reg+1)<<8, where I_reg is the I register.

Bottom line: if the data bus state is unknown and/or it's necessary to get the code running on ANY MSX machine, the ISR vector table MUST have not only 257 entries, but also the SAME MSB and LSB for the interrupt vector routine (required to cover the odd/even case on the data bus). For example, the interrupt vectors like 0xFEFE, 0xFDFD, 0xC1C1 are completely valid since MSB=LSB.

Van PingPong

Prophet (3976)

afbeelding van PingPong

18-02-2018, 20:03

Eugeny_Brychkov wrote:

By the way, looking through Z80 datasheet I do not see it properly and explicitly stating at which bus interrupting device must put vector to - to address A[7:0] or to data D[7:0]!

the Axx lines on z80 are address bus.. Address bus in uni-directional bus.
D0-D7 is of course bidiretional

Pagina 2/2
1 |