Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- //------------------------------------------------------------------------
- // This file is part of OmniPas.
- //
- // You can find OmniPas here:
- // https://bitbucket.org/paul_nicholls/omnipas/src/master/
- //
- // this file was translated (and modified) from:
- // https://github.com/SlithyMatt/zxs-assembly-tutorial/blob/main/Lesson12/irq.asm
- //
- // OmniPas is free software: you can redistribute it and/or modify
- // it under the terms of the GNU General Public License as published by
- // the Free Software Foundation, either version 3 of the License, or
- // (at your option) any later version.
- //
- // OmniPas is distributed in the hope that it will be useful,
- // but WITHOUT ANY WARRANTY// without even the implied warranty of
- // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- // GNU General Public License for more details.
- //
- // You should have received a copy of the GNU General Public License
- // along with OmniPas. If not, see <https://www.gnu.org/licenses/>.
- //------------------------------------------------------------------------
- unit spectrum_irq;
- type
- TIRQ = record
- framecounter : Word;
- vbSync : Byte;
- end;
- var
- IRQ : TIRQ;
- macro saveAllRegisters(); assembler;
- asm
- // stash all registers to stack
- push af
- push bc
- push de
- push hl
- ex af,af' // exchange AF and AF'
- exx // exchange BE,DE,HL with BE',DE',HL'
- push af
- push bc
- push de
- push hl
- push ix
- push iy
- end;
- macro restoreAllRegisters(); assembler;
- asm
- // restore all registers from stack
- pop iy
- pop ix
- pop hl
- pop de
- pop bc
- pop af
- ex af,af' // exchange AF and AF'
- exx // exchange BE,DE,HL with BE',DE',HL'
- pop hl
- pop de
- pop bc
- pop af
- end;
- macro exitIRQ(); assembler;
- asm
- ei
- end;
- procedure vbSyncIRQ; assembler; volatile;
- asm
- :saveAllRegisters();
- // increment frame counter
- ld hl,(IRQ.framecounter)
- inc hl
- ld (IRQ.framecounter),hl
- // set vertical blank sync
- ld a,1
- ld (IRQ.vbSync),a
- USER_IRQ:
- call $ffff
- :restoreAllRegisters();
- :exitIRQ();
- end;
- procedure waitFor_vblank(); assembler;
- asm
- // wait for vbSync <> 0
- !:
- ld a,(IRQ.vbSync)
- cp 0
- jp z,!-
- // reset vbSync to 0
- xor a
- ld (IRQ.vbSync),a
- end;
- procedure setupInterrupt(irqRoutineAddr : Word); assembler;
- const
- IM2_TABLE = $FE00; // 256 byte page (+ 1 byte) for IM2
- IM2_VECTOR = $FDFD; // 3 bytes for JP routine under IM2 table
- asm
- // link user irq to our routine
- ld hl,(irqRoutineAddr)
- ld (vbSyncIRQ.USER_IRQ + 1),hl
- // zero counters
- ld hl,0
- ld (IRQ.framecounter),hl
- xor a
- ld (IRQ.vbSync),a
- // Setup Interrupt Mode 2
- di // disable interrupts
- ld de,IM2_TABLE // de = beginning of 257 bytes to set to $FD
- ld hl,IM2_VECTOR // hl = vector location ($FDFD)
- ld a,d //
- ld i,a // i = custom IM2 table page
- ld a,l // a = $FD
- fill_loop:
- ld (de),a // set byte in IM2 table to $FD
- inc e // de = next byte (unless e = 0)
- jp nz,fill_loop // loop until whole page is set to $FD (e = 0)
- inc d // de = 257th byte of table
- ld (de),a // set last byte to $FD
- ld (hl),$C3 // place unconditional JP opcode at vector
- inc l // hl = vector + 1
- ld (hl),<vbSyncIRQ // low byte of custom handler address
- inc l // hl = vector + 2
- ld (hl),>vbSyncIRQ // high byte of custom handler address
- im 2 // set interrupt mode 2
- ei // re-enable interrupts
- end;
Advertisement
Add Comment
Please, Sign In to add comment