Jelajahi Sumber

* switch to interrupt mode 2 and install a custom maskable interrupt handler in
the ZX Spectrum startup code, because the ROM handler requires the IY register
to always have a specific value, but the FPC code generator uses the IY
register for various purposes, which causes random crashes and glitches when
the timer interrupt occurs.

git-svn-id: trunk@45677 -

nickysn 5 tahun lalu
induk
melakukan
1ae70c6825
1 mengubah file dengan 47 tambahan dan 1 penghapusan
  1. 47 1
      rtl/zxspectrum/si_prc.pp

+ 47 - 1
rtl/zxspectrum/si_prc.pp

@@ -33,7 +33,7 @@ procedure PascalMain; external name 'PASCALMAIN';
 { this *must* always remain the first procedure with code in this unit }
 { this *must* always remain the first procedure with code in this unit }
 procedure _start; assembler; nostackframe; public name 'start';
 procedure _start; assembler; nostackframe; public name 'start';
 label
 label
-  bstart,bend,loop;
+  bstart,bend,loop,loop2,our_int_handler,key_int;
 asm
 asm
     { init the stack }
     { init the stack }
     ld sp, offset fpc_stackarea_end
     ld sp, offset fpc_stackarea_end
@@ -57,9 +57,55 @@ loop:
     { save IY (must be done after zeroing the .bss section) }
     { save IY (must be done after zeroing the .bss section) }
     ld (FPC_SAVE_IY), iy
     ld (FPC_SAVE_IY), iy
 
 
+    { prepare to run in interrupt mode 2; install our own interrupt handler }
+    di
+    ld de, 65024
+    ld hl, 65021
+    ld a, d
+    ld i, a
+    ld a, l
+loop2:
+    ld (de), a
+    inc e
+    jr nz, loop2
+    inc d
+    ld (de), a
+    ld (hl), 195
+    ld hl, offset our_int_handler
+    ld (65022), hl
+    im 2
+    ei
+
     { ready to run the main program }
     { ready to run the main program }
     jp PASCALMAIN
     jp PASCALMAIN
 
 
+    { replacement for the ROM interrupt handler that preserves IY and that
+      doesn't break if IY is changed }
+our_int_handler:
+    push af
+    push hl
+    push iy
+    ld iy, (FPC_SAVE_IY)
+    ld hl, (23672)
+    inc hl
+    ld (23672), hl
+    ld a, h
+    or a, l
+    jr nz, key_int
+    inc (iy+64)
+key_int:
+    push bc
+    push de
+    call 703
+    pop de
+    pop bc
+    ld (FPC_SAVE_IY), iy
+    pop iy
+    pop hl
+    pop af
+    ei
+    reti
+
     { When using the SDCC-SDLDZ80 linker, the first object module defines the
     { When using the SDCC-SDLDZ80 linker, the first object module defines the
       order of areas (sections). Since this module contains the startup code,
       order of areas (sections). Since this module contains the startup code,
       it is loaded first, so we define all the sections we use in the proper
       it is loaded first, so we define all the sections we use in the proper