Library with basic functions to control the Interrupt Service Routine (ISR) for Z80 Mode 1 interrupts on MSX system. Allows you to save, replace, disable and recover the ISR under the MSX-DOS environment.
You can use it in combination with the Interrupt M1 Hooks library, to work with the hooks defined in MSX system, but with an optimized ISR.
This project is an Open Source library. You can add part or all of this code in your application development or include it in other libraries/engines.
Use them for developing MSX applications using Small Device C Compiler SDCC
.
This library is part of the MSX fR3eL Project.
Name | Description |
---|---|
DisableI |
Disable interrupts. Add DI code in Z80 assembler. |
EnableI |
Enable interrupts. Add EI code in Z80 assembler. |
HALT |
Suspends all actions until the next interrupt. Add HALT code in Z80 assembler. |
Save_ISR | |
---|---|
Save Old ISR vector | |
Function | Save_ISR() |
Input | --- |
Output | --- |
Examples: | Save_ISR(); |
Install_ISR | |
---|---|
Set new ISR vector | |
Function | Install_ISR(isr) |
Input | [isr] ISR Function |
Output | --- |
Examples: | Install_ISR(my_ISR); |
Restore_ISR | |
---|---|
Restore old ISR vector/td> | |
Function | Restore_ISR() |
Input | --- |
Output | --- |
Examples: | Restore_ISR(); |
Disable_ISR | |
---|---|
Disable ISR (Install an ISR with the minimum code so as not to block the Z80.) | |
Function | Disable_ISR() |
Input | --- |
Output | --- |
Examples: | Disable_ISR(); |
ISR_Basic | |
---|---|
Basic ISR for M1 interrupt of Z80 * Saves all Z80 registers on the stack. * Calls the two hooks of the system: TIMI (VBLANK) and KEYI | |
Function | ISR_Basic() |
Input | --- |
Output | --- |
Examples: | Install_ISR(ISR_Basic); |
This library aims to simplify the use of interrupt in your programs for MSX computers, but depending on how you want your program to behave, it will require you to follow a series of steps that are described in the following use cases.
In the event that you do not know how interruptions work in MSX, I recommend that you read some articles that are referenced at the end of this document.
This library contains various functions to have full control of the Interrupt Service Routine (ISR), of the Z80's Mode 1 interrupt. It will allow you to save the original system links, replace them, disable them and recover them.
It is designed for the development of MSX-DOS applications, although it is possible to use it in the programming of 48K ROMs where the BIOS is not used or where interrupts are disabled before accessing the BIOS.
Note: |
---|
If your application does not need to return to DOS, you will not need to save and retrieve the ISR and system hooks. |
The MSX system uses an Interrupt Service Routine (ISR) that manages DOS and BASIC functionalities. This produces two problems:
- It consumes some CPU cycles (Maybe you need all the power of MSX in your program).
- The DOS ISR also executes the BIOS ISR (KEYINT), from which hooks are called. At that time, the BIOS will be visible to the CPU. If your function is on page 0, the Z80 will lose the thread of execution and will throw a fatal error.
You have two options:
- create your own ISR and replace the system one.
- use
ISR_Basic
included in library and install your function in one of the system hooks (requires the interruptM1_Hooks library).
If your application has to go back to DOS, before assigning a new ISR, you must save the link of the system ISR, executing the Save_ISR ()
function and before exiting, you must restore the system ISR with the Restore_ISR ( )
.
This example is illustrative only.
In the examples\test01_isr\
folder of the project sources you will find a complete application where you can check the behavior of the library.
/* -----------------------------------------------------------------------------
Mode 1 ISR example
----------------------------------------------------------------------------- */
#include "../include/interruptM1_ISR.h"
void my_ISR(void);
usigned int conta;
void main(void)
{
char n=255;
conta=0;
Save_ISR();
Install_ISR(my_ISR);
while(n>0)
{
HALT;
n--;
}
Restore_ISR();
__asm
ld C,#0x00 ;Program terminate
call 0x0005 ;MSX-DOS entry
__endasm;
}
void my_ISR(void) __naked
{
__asm
push IY ;<--- save all the Z80 records although it is only necessary to save those that are used in the ISR
push IX ; in this case, it would be vast to save only the pairs of registers AF and IY
push HL
push DE
push BC
push AF
exx ;now we go for the alternative registers
ex AF,AF
push HL
push DE
push BC
push AF
in A,(0x99) ;read if VDP interrupt and Disable interrupt call to CPU
and A
jp P,exitISR ;IF NOT (VDP INTERRUPT) THEN exit
ld (0xF3E7),A ;save VDP reg#0 in STATFL system variable
ld IY,#_conta
inc 0 (IY)
jr NZ,exitISR
inc 1 (IY)
exitISR:
pop AF ;<--- recovers all Z80 records
pop BC
pop DE
pop HL
ex AF,AF
exx
pop AF
pop BC
pop DE
pop HL
pop IX
pop IY
ei ;<--- IMPORTANT! Before exiting, enable interrupts.
ret
__endasm;
}
If you want to use the hooks defined in the MSX system (TIMI and KEYI) you have to consider what was explained in the previous point about the change of page 0 (when executing the ISR KEYINT of the BIOS).
So as not to complicate, we recommend changing the system ISR to ISR_Basic
included in this library.
This interrupt routine minimizes what is necessary to execute the hooks.
Your function will not need anything more than to do a ret
at the end, since the ISR_Basic
will take care of protecting all the Z80 registers and what is necessary for everything to work well.
To work with hooks, you will need to include the interruptM1_Hooks library to your project.
WARNING! |
---|
Before switching to a new ISR, it is recommended to disable the hooks (use Disable_TIMI() and Disable_KEYI() ), because system routines make changes to memory pages and could crash the system. Disabling interrupts is not a good solution, because many functions turn interrupts on. |
ATTENTION! |
---|
SDCC provides some extended keywords to program an Interrupt Service Routine (ISR), but it is useless in our case as we use the system ISR (BIOS). Therefore we should NOT ADD __interrupt in our functions since it would add redundant code that could affect the correct execution of our program. |
This example is illustrative only.
In the examples\test02_hooks\
folder of the project sources you will find a complete application where you can check the behavior of the library.
/* -----------------------------------------------------------------------------
Interrupts Mode 1 TIMI hook Example
----------------------------------------------------------------------------- */
#include "../include/interruptM1_ISR.h"
#include "../include/interruptM1_Hooks.h"
void TestM1(void);
void my_TIMI1(void);
void my_TIMI2(void);
char conta;
void main(void)
{
conta=0;
//Save the ISRs and hooks of the system so that when the program leave, can retrieve them.
Save_ISR();
Save_TIMI();
Save_KEYI();
//Disabled the hooks, so that when assigning the ISR_Basic, the system routines are not executed.
Disable_TIMI();
Disable_KEYI();
Install_ISR(ISR_Basic); //Install the ISR_Basic
Install_TIMI(my_TIMI1); //Install the first function for the interrupt
TestM1();
Disable_TIMI(); //disable hook vector
TestM1();
Install_TIMI(my_TIMI2); //Install the second function for the interrupt
TestM1();
//restore hooks and system ISR.
Restore_TIMI();
Restore_KEYI();
Restore_ISR();
__asm
ld C,#0x00 ;Program terminate
call 0x0005 ;MSX-DOS entry
__endasm;
}
void TestM1(void)
{
char n=255;
while(n>0)
{
HALT;
n--;
}
}
// C
void my_TIMI1(void)
{
conta++;
}
// assembler
void my_TIMI2(void) __naked
{
__asm
ld HL,_conta
inc (HL)
ret
__endasm;
}
- Z80 Family - CPU User Manual (by ZiLOG) (PDF)
- MSX2 Technical Handbook - Chapter 2 - 4.5 Interrupt usage
- The MSX Red Book - 4. ROM BIOS - KEYINT
- Z80 Family Interrupt Structure (by Michael Moore)
- MSX Computer Magazine - Nº 51 Januari 1992 - Interrupts - Page 6. (In English on MSX Assembly Page)
- MSX Resource Center - Wiki - System hooks
- VBLANK - Vertical Blank interrupt (Wikipedia)
- Karoshi MSX Community - Interrupciones del MSX (por SapphiRe)
- MSX Inside 005 - Interrupciones (por SapphiRe)
- MSX Inside 006 - Interrupciones VBLANK (por SapphiRe)
- MSX Inside 007 - Interrupciones de Línea (por SapphiRe)
This document is licensed under a Creative Commons Attribution-NonCommercial 4.0 International License.