;SPG runner, version 0.2
 
;EVO version
 
 
 
;данный код использует одну внешнюю
 
;функцию - LOADING
 
;у неё только 2 входных параметра:
 
;HL - адрес куда грузить
 
;B  - кол-во блоков размером в 2к,
 
;     которые нужно загрузить
 
 
 
;перед первым вызовом LOADING'а, оная
 
;должна быть спозиционирована на начало
 
;файла SPG
 
 
 
;затем, при каждом последующем обращении
 
;к ней, должен грузиться очередной кусок
 
;данного файла.
 
;  Т.е. после каждого обращения к данной
 
;процедуре, она должна сохранять позицию
 
;в нутри файла и продолжать читать даные
 
;из него с того  же  места,  на  котором
 
;остановились при прошлом обращении...
 
 
 
;        ORG $
 
PAGER   EQU 0X5000;0X4800
 
LOBU    EQU 0XA000
 
;---------------------------------------
 
RUNSPG2 LD IYH,0
 
        LD HL,LOBU
 
        LD B,1
 
        CALL LOADING
 
        LD HL,LOBU+32
 
        LD DE,IDNT
 
        LD B,12;см.описание заголовка SPG
 
RAZ     LD A,(DE)
 
        CP (HL)
 
        RET NZ
 
        INC HL
 
        INC DE
 
        DJNZ RAZ
 
;в кратце тут идет сканирование блоков, которые по страницам грузятся.
 
;блоков максимум 12 может быть
 
 
 
        LD A,(HL)
 
        CP 3
 
        RET NC;выходим, если версия выше 0.2 (0X02)
 
        CP 2
 
        JR C,OF4;SPG версии 0X00 или 0X01
 
;SPGv0.2:
 
        LD A,15
 
        LD (VrS+1),A
 
        LD A,16
 
        LD (V2A+1),A
 
        LD (V2F+1),A
 
        LD A,4
 
        LD (V2B+1),A
 
        LD A,15
 
        LD (V2C+1),A
 
;SPGv0.0/0.1:
 
OF4     ;LD HL,SPGLOG:CALL SPGLOG
 
        LD HL,LOBU
 
        LD DE,PAGER
 
        LD BC,0X0800
 
        LDIR
 
;-------
 
        LD HL,MANAG0
 
        LD DE,PAGER
 
        LD BC,32
 
        LDIR;кидаем манагер сраниц в заголовок SPG (ибо первые 32б там не пользуются)
 
        XOR A
 
        CALL PAGER;включаем 0ю страницу
 
;-------
 
V2A     LD A,8
 
        LD (C0),A;счетчик!
 
;тут далее переносятся нужные переменные из заголовка SPG файла, там расположение стека, стартовый адресс и т.д.
 
        LD HL,(PAGER+64)
 
        LD (SAR+1),HL
 
 
 
        LD A,(PAGER+66)
 
        LD (SPA+1),A
 
        LD HL,(PAGER+74)
 
        LD A,H
 
        CP 0X40
 
        JR NC,NSPZ
 
        LD HL,(SPBU)
 
NSPZ    LD (SSPA+1),HL
 
 
 
        LD HL,(PAGER+68)
 
        LD (V2E+1),HL
 
 
 
        LD HL,(PAGER+76)
 
                LD A,H
 
                OR L
 
                JR Z,V2Di
 
        LD (V2D+1),HL
 
V2Di    LD BC,(PAGER+78)
 
        LD A,B
 
        OR C
 
        JR Z,MAA
 
        LD A,B
 
        OR A
 
        JR Z,MAA
 
        LD B,1
 
        LD A,C
 
        CP 0X41
 
        JR C,MAA
 
        LD C,0
 
MAA     LD (LAA+1),BC
 
 
 
        LD IX,PAGER+128
 
GROP    LD A,(IX+2)
 
        CP 14
 
        JR C,NSPL
 
        LD A,13;ограничение на макс размер блока, дабы на поврежденных SPG не получить затирание всей памяти.
 
NSPL    LD (SPGL+1),A
 
 
 
        LD A,(IX+3)
 
VrS     AND 7
 
        DI
 
        CALL PAGER;на выходе в A
 
;                     знач. порта 0X7FFD
 
 
 
        LD HL,PAGER+512
 
        LD E,(IX)
 
        LD D,(IX+1)
 
        LD BC,0X0600
 
        CALL LC
 
        EX DE,HL
 
        LD A,H
 
        CP 0XA0
 
        JR C,DIPL;типо загрузили все блоки (условие: когда адрес загрузки блока ниже 0XA000 переходим к стадии запуска SPG)
 
SPGL    LD B,1
 
        LD A,B
 
        OR A
 
        CALL NZ,LOADING;иначе грузим очередной блок SPG файла в память (в заданную страницу)
 
 
 
V2B     LD DE,8
 
        ADD IX,DE;собственно переходим к описателю след. блока
 
 
 
        LD A,(C0)
 
        DEC A
 
        LD (C0),A
 
        JR NZ,GROP;идем на загрузку след блока, если счетчик не говорит обратного
 
;-------
 
;тут выставляем нужный стек, прерывания и т.д. ну и включаем нужную страницу (что в заголовке SPG указана)
 
;и делаем JP на заданный адрес
 
;экран чистить не нужно
 
DIPL    DI
 
        LD A,63
 
        LD I,A
 
        IM 1
 
        LD IY,0X5C3A
 
 
 
        LD HL,PAGER
 
V2E     LD DE,0
 
        LD BC,32
 
        LDIR
 
 
 
LAA     LD BC,0
 
        LD A,B
 
        OR C
 
        JR Z,SPA
 
        LD HL,PAGER+192
 
V2D     LD DE,0X5B00
 
        LDIR
 
 
 
SPA     LD A,0
 
V2C     AND 7
 
        CALL PAGER
 
 
 
        LD A,(PAGER+67);опять смотрим заголовок SPG файла
 
        CP 1
 
        JR NZ,NNx
 
        LD A,(DRVE)
 
        LD (0X5CF6),A
 
 
 
NNx     LD A,(V2C+1)
 
        CP 7
 
        JR Z,SSPA
 
        LD HL,PAGER+49
 
        LD E,5
 
OUTZ    LD C,(HL)
 
        INC HL
 
        LD B,(HL)
 
        INC HL
 
        LD A,B
 
        OR C
 
        JR Z,OUTz
 
        LD A,(HL)
 
        OUT (C),A
 
OUTz    INC HL
 
        DEC E
 
        JR NZ,OUTZ
 
 
 
SSPA    LD SP,0
 
SAR     JP 0
 
;-------
 
LC      LD A,(C0)
 
V2F     CP 8
 
        RET NZ;вызывается только когда счетчик обнулился, чтобы только один раз оную вызвать
 
        LD A,D
 
        CP 0XA0
 
        JR NC,V01;самый первый блок может грузиться в адрес ниже 0Xa000
 
 
 
        LD (SREZ+4),DE
 
        ADD A,6
 
        LD D,A
 
        PUSH DE
 
        LD HL,(SAR+1)
 
        LD (SR1+1),HL;стартовый адрес выставляем
 
        LD DE,PAGER+0X20
 
        LD (SAR+1),DE;тут резидент будет (пересылает блок, что оказался вместе с заголовком SPG, ибо грузим блоки по 2кб)
 
        LD HL,SREZ
 
        LD BC,16
 
        LDIR
 
        POP DE
 
        RET
 
 
 
V01     LDIR
 
        RET
 
 
 
SREZ    LD HL,PAGER+512
 
        LD DE,0
 
        LD BC,0X0600
 
        LDIR
 
SR1     JP 0
 
 
 
IDNT    DB "SpectrumProg"
 
;-------
 
SPBU    DW 0X6000
 
C0      NOP
 
DRVE    DB 0;номер активного дисковода
 
 
 
;---------------------------------------
 
MANAG0  ;I:A - num of PAGE (VALID: 0-15)
 
        PUSH BC
 
        LD C,A
 
        AND %11111000
 
        LD A,C
 
        JR Z,K128
 
        AND 7
 
        OR %01000000
 
K128    OR 16
 
        LD BC,0X7FFD
 
        OUT (C),A
 
        POP BC
 
        RET
 
;---------------------------------------
 
 
 
LOADING         PUSH IX
 
                LD A,B
 
                ADD A,A
 
                ADD A,A
 
                LD IYL,A
 
                CALL LD_FILE
 
                POP IX
 
                RET
 
 
 
;---------------------------------------