Doing Interrupts on MSX
Posted: Thu Feb 13, 2020 1:50 pm
I have been researching the last couple of days and it seems that all the information about interrupts is distributed everywhere and therefore I'm writing this.
So, how to initialise for interrupts:
0xfd9f is the system variable HTIMI, you can find it in some of the definitions but obviously I can't access them on my level. There is another hook that can be used but that's not a vertical retrace interrupt.
This interrupt is a hook of 5 bytes and sometimes there's assembly code in there. If you are only using a ROM and not disks then you can easily overwrite it.
This interrupt routine is a vertical retrace interrupt, where only register A needs to be preserved.
So for example, if I want to play with the wyzplayer, I use this: (note: a more specific version further on)
Finally, a feature of the vertical retrace interrupt on the MSX, is that the MSX is an international machine. Therefore it can run on 50Hz or 60Hz. I modify a routine i found (on msx.org) to determine what speed it is running on:
(All the numbers inside are system or ROM variables, except for 50 and 60). Returns 50 or 60 depending on the frequency.
I also wrote a new interrupt routine to connect the result together, in which I connect these things together (but it's very ugly). What I do here is to skip calling the play routine every 6th interrupt if it's 60Hz, in this case we can make 50Hz music for the Spectrum as well as MSX.
I have a code where I incorporated all these into the player code, but since that's the previous version, I post these separate functions here first, and perhaps I can incorporate these function into that code later.
I'd also suggest to not move the code of 60Hz and playing into the library because those functions are probably better off in the application level. The im_init_msx() is probably a candidate to move to the library, but also not necessary because this function doesn't do anything with the old hook yet.
Note: these functions are suitable for ROM mode only with no disk usage. For other case I understand that it would need a lot more work like storing and calling the old hook as well as doing an "interslot call". I have no idea how that would work but I was told it would be very complicated and very memory intensive (more than the im2 on the Spectrum).
So, how to initialise for interrupts:
Code: Select all
void __FASTCALL__ im_init_msx()
{
#asm
di
ld hl,_msx_wyz_play
ld (0xfd9f+1),hl
ld a,195
ld (0xfd9f),a
ei
#endasm
}
This interrupt is a hook of 5 bytes and sometimes there's assembly code in there. If you are only using a ROM and not disks then you can easily overwrite it.
This interrupt routine is a vertical retrace interrupt, where only register A needs to be preserved.
So for example, if I want to play with the wyzplayer, I use this: (note: a more specific version further on)
Code: Select all
void __FASTCALL__ msx_wyz_play()
{
#asm
push af
call ay_wyz_play
pop af
#endasm
}
Code: Select all
int __FASTCALL__ msx_get_vreq()
{
#asm
ld hl, 50
ld a,(0x2d)
cp 1
jr nc,tMSX2
tMSX1:
ld a,(0x2b)
bit 7,a
ret nz
ld l, 60
ret
tMSX2:
ld a,(0xffe8)
bit 1,a
ret nz
ld l, 60
ret
#endasm
}
I also wrote a new interrupt routine to connect the result together, in which I connect these things together (but it's very ugly). What I do here is to skip calling the play routine every 6th interrupt if it's 60Hz, in this case we can make 50Hz music for the Spectrum as well as MSX.
Code: Select all
void __FASTCALL__ msx_wyz_play()
{
#asm
push af
ld a, (_wyz_freq60)
and a
jr z, m50hz
ld a, (_wyz_60counter)
and a
jr nz, m60continue
ld a,5
ld (_wyz_60counter), a
jr m50end
m60continue:
dec a
ld (_wyz_60counter), a
m50hz:
call ay_wyz_play
m50end:
pop af
#endasm
}
where I initialised them with:
wyz_freq60 = (msx_get_vreq() == 60);
wyz_60counter = 5;
I'd also suggest to not move the code of 60Hz and playing into the library because those functions are probably better off in the application level. The im_init_msx() is probably a candidate to move to the library, but also not necessary because this function doesn't do anything with the old hook yet.
Note: these functions are suitable for ROM mode only with no disk usage. For other case I understand that it would need a lot more work like storing and calling the old hook as well as doing an "interslot call". I have no idea how that would work but I was told it would be very complicated and very memory intensive (more than the im2 on the Spectrum).