fpc/rtl/zxspectrum/si_prc.pp
nickysn 1ae70c6825 * 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 -
2020-06-22 14:00:33 +00:00

124 lines
2.5 KiB
ObjectPascal

{
This file is part of the Free Pascal run time library.
Copyright (c) 2020 by Free Pascal development team
This file contains startup code for the ZX Spectrum
See the file COPYING.FPC, included in this distribution,
for details about the copyright.
This program 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.
**********************************************************************}
unit si_prc;
{$SMARTLINK OFF}
interface
implementation
{$GOTO ON}
var
FPC_SAVE_IY: word; external name 'FPC_SAVE_IY';
fpc_stackarea_start: word; external name '__fpc_stackarea_start';
fpc_stackarea_end: word; external name '__fpc_stackarea_end';
procedure PascalMain; external name 'PASCALMAIN';
{ this *must* always remain the first procedure with code in this unit }
procedure _start; assembler; nostackframe; public name 'start';
label
bstart,bend,loop,loop2,our_int_handler,key_int;
asm
{ init the stack }
ld sp, offset fpc_stackarea_end
{ zero the .bss section }
ld bc, offset bstart
ld hl, offset bend
scf
ccf
sbc hl, bc
ld a, 0
loop:
ld (bc), a
inc bc
dec hl
cp a, l
jr NZ, loop
cp a, h
jr NZ, loop
{ save IY (must be done after zeroing the .bss section) }
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 }
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
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
order. }
area '_DATA'
area '_BSS'
bstart:
area '_BSSEND'
bend:
area '_HEAP'
area '_STACK'
area '_CODE'
end;
end.