;===================[ Функции распределения памяти ]===================; ; Выход: BC - FREE MEM в блоках по 16k, HL - FULL MEM ;!TEST все SLOT2 на SLOT1 ; ;----------------------------------------------------------------------; ; Определение объема памяти. ; Выход: BC - FREE MEM в блоках по 16k, HL - FULL MEM EMM.GetMemSize: IN A,(SLOT1) LD B,A LD A,SYS_PAGE OUT (SLOT1),A XOR A LD C,A LD HL,SYS_PAGE.RAM_TABLE-#4000-#4000 ; .loop: DEC L JR Z,.exit CP (HL) JR NZ,.loop INC C JP .loop ; .exit: LD HL,#100 ;!HARDCODE max mem pages LD A,B ; L=0 LD B,L OUT (SLOT1),A RET /* .loop: LD A,(HL) INC L JR Z,.exit AND A JR NZ,.loop INC C JR .loop .exit: LD HL,#100 ;!HARDCODE max mem pages LD A,B LD B,0 OUT (SLOT1),A RET */ ;----------------------------------------------------------------------; ; ;!!!!! Если используется SLOT3 со своими страницами, то не пользоваться ; стеком, там может быть SP в режиме спектрума ; ;----------------------------------------------------------------------; ; Инициализация распределения памяти. EMM.InitMem: PUSH BC PUSH HL PUSH DE IN A,(SLOT3) LD C,A LD A,SYS_PAGE OUT (SLOT3),A LD HL,SYS_PAGE.RAM_TABLE ; Адрес RAM FAT в ОЗУ. ; обнуляем таблицу XOR A .loopFree: LD (HL),A INC L JR NZ,.loopFree ; резервируем спец.страницы и страницы ZX ;LD B,RESERVED_PAGES.Blocks LD DE,RESERVED_PAGES ; таблица занятых системных страниц .loop: LD A,(DE) CP #FF JR Z,.exitLoop ; .loopBlk: INC DE LD L,A LD A,(DE) LD (HL),A CP #FF JR NZ,.loopBlk ; .exitLoop: ;INC DE ;DJNZ .loop LD L,A LD (HL),A ; Инициализация ключей RAM-Disks XOR A LD HL,SYS_PAGE.RAMD_KEYS LD B,SYS_PAGE.RAMD_KEYS.NUM .loop2: LD (HL),A INC L DJNZ .loop2 ; [x] 04/11/2023 LD HL,SYS_PAGE.Sp_RAMD_KEYS LD B,SYS_PAGE.Sp_RAMD_KEYS.NUM .loop3: LD (HL),A INC L DJNZ .loop3 ; LD A,C OUT (SLOT3),A POP DE POP HL POP BC RET ;---------------------------------------------------------------------[] RESERVED_PAGES: ;[x] free zx pages! ; Block #1 - можно освободить по ID 1 ;DB 1,3,4,6,7,8,9,10,11,12,13,14,15 ; for Spectrum ; эмулятор ПЗУ ;DB #42,#43,#44,#45,#46,#47;,#48,#49,#4A,#4B ; For (BASIC128, BASIC48, TRDOS, SCORP_ROM)*2, vBIOS, vEXTENSION ;DB #FF ; End of the block ; ; Block #2 - нельзя освобождать DB ZX_PAGE.SLOT0,ZX_PAGE.SLOT2,ZX_PAGE.SLOT1 ; for Spectrum and BIOS starting DB DCP_PAGE ; Ports map DB Spec_Page ; Page for Spectrum mode ; Screen pages DB #50,#51,#52,#53,#54,#55,#56,#57 DB #58,#59,#5A,#5B,#5C,#5D,#5E,#5F ; ;DB MODE_PAGE ; ????? DB SP_SND.CBL.BUFFER_PAGE ; Page for CBL audio DB SYS_PAGE ; Page for system (BIOS) variables DB #FF ; End of the block ; ;----------------------------------------------------------------------; ; ; ;----------------------------------------------------------------------; ; Получить блок памяти N bytes, ; Вход: B - число необходимых блоков ; Выход: L,A - КЛЮЧ RAM-Disk/код ошибки ; CF - признак ошибки ;EMM_FN2M: EMM.GetMem: PUSH BC IN A,(SLOT3) EX AF,AF' LD A,SYS_PAGE OUT (SLOT3),A ; LD HL,SYS_PAGE.RAM_TABLE XOR A LD C,#FF ; Метка конца рамблока ; Заполнить RAM_TABLE .loop2: DEC L JR Z,.error_no_mem CP (HL) JR NZ,.loop2 LD (HL),C LD C,L DJNZ .loop2 ; L = указатель цепочки. EX AF,AF' OUT (SLOT3),A LD A,L AND A POP BC RET ; .error_no_mem: EX AF,AF' OUT (SLOT3),A LD A,C CALL EMM.FreeMem LD L,BIOS.Error.EMM.NoMemory LD A,L SCF POP BC RET /* EMM.GetMem: PUSH BC IN A,(SLOT3) EX AF,AF' LD A,SYS_PAGE OUT (SLOT3),A LD C,B ; сохранить число нужных блоков LD HL,SYS_PAGE.RAM_TABLE ; Цикл проверки наличия нужных блоков. XOR A .loop: DEC L JR Z,.noRAM ; LD A,(HL) ; AND A CP (HL) JR NZ,.loop DJNZ .loop ; Место есть ! LD B,C ; Восстановить нужный объем диска LD C,#FF ; МЕТКА КОНЦА RAM-Disk LD L,A ;low SYS_PAGE.RAM_TABLE ; Заполнить RAM_TABLE ; A = 0 .loop2: DEC L ; LD A,(HL) ; AND A CP (HL) JR NZ,.loop2 LD (HL),C LD C,L DJNZ .loop2 ; L = указатель цепочки. EX AF,AF' OUT (SLOT3),A LD A,L AND A POP BC RET ; .noRAM: LD L,BIOS.Error.EMM.NoMemory EX AF,AF' OUT (SLOT3),A LD A,L SCF POP BC RET */ ;----------------------------------------------------------------------; ; ; ;----------------------------------------------------------------------; ; Получить блок памяти N bytes, для RAM-Disk A ; Вход: B - число необходимых блоков, A - RAM-Disk ; Выход: L,A - КЛЮЧ RAM-Disk/код ошибки ; CF - признак ошибки ;EMM.GetMem: EMM.GetMemRMD: PUSH AF CALL EMM.GetMem JR C,.error1 ; LD B,A POP AF CALL BLK_TO_RAMD RET NC ; .error2: LD L,BIOS.Error.BadNumber ; RAM-Disk занят LD A,L RET ; .error1: POP HL ; чистим стек LD L,A RET ;----------------------------------------------------------------------; ; ;----------------------------------------------------------------------; ; Освободить блок памяти ключа K ; Вход: A - КЛЮЧ RAM-Disk EMM.FreeMemRMD: CALL GET_RAMD_ST RET C SCF RET Z LD C,A IN A,(SLOT3) LD B,A LD A,SYS_PAGE OUT (SLOT3),A LD H,high SYS_PAGE.RAMD_KEYS LD (HL),0 LD A,B OUT (SLOT3),A LD A,C ;JR EMM.FreeMem ;------[ ; Освободить блок памяти ; Вход: A - НАЧАЛО ЦЕПОЧКИ ; НЕ ПОРТИТЬ DE!!! ;EMM_FN3M: EMM.FreeMem: ; [x] теперь нельзя освободить страницу #FF SCF INC A RET Z DEC A ; RET Z ; LD C,A IN A,(SLOT3) EX AF,AF' LD A,SYS_PAGE OUT (SLOT3),A LD H,high SYS_PAGE.RAM_TABLE LD A,C .loop: LD L,A LD A,(HL) ; следующий блок AND A JR Z,.error LD (HL),0 ; Освободить CP #FF ; Если не конец JR NZ,.loop ; продолжать ; [x] 23/08/2024 восстановление цепочки если освобождали не с начала LD A,C LD L,0 LD BC,256 CPIR JR NZ,.exit DEC HL LD (HL),#FF ; .exit: EX AF,AF' OUT (SLOT3),A XOR A ; no error code RET .error: EX AF,AF' OUT (SLOT3),A LD A,BIOS.Error.BadNumber SCF RET ;----------------------------------------------------------------------; ; ; WARNING!!! не трогать DE ;----------------------------------------------------------------------; ; Получить страницу N ключа K ; Вход: A - КЛЮЧ RAM-Disk, B - номер страницы ; Выход: A - страница EMM.GetMemPageRMD: CALL GET_RAMD_ST RET C SCF RET Z ;JR EMM.GetMemPage ;------[ ; Получить страницу N блока K ; Вход: A - блок, B - номер страницы ; Выход: A - страница, IF CF - A=0 - нет блока, A=FF - END ;EMM_FN4M: EMM.GetMemPage: LD L,A IN A,(SLOT1) EX AF,AF' LD A,SYS_PAGE OUT (SLOT1),A INC B LD H,high (SYS_PAGE.RAM_TABLE-#4000-#4000) EMM_F4M_L1: LD A,(HL) AND A JR Z,EMM_F4M_ERR DEC B JR Z,EMM_F4M_END LD L,A CP #FF JR NZ,EMM_F4M_L1 EMM_F4M_ERR: LD L,A EX AF,AF' OUT (SLOT1),A LD A,L SCF RET EMM_F4M_END: EX AF,AF' OUT (SLOT1),A LD A,L AND A RET ;----------------------------------------------------------------------; ; ; ;----------------------------------------------------------------------; ; Получить следующую страницу по FAT ; Вход: A - страница ОЗУ ; Выход: A - следующая страница ОЗУ ;EMM_FN5: EMM.GetMemPageNext: LD L,A AND A SCF RET Z IN A,(SLOT1) LD H,A LD A,SYS_PAGE OUT (SLOT1),A LD A,H LD H,high (SYS_PAGE.RAM_TABLE-#4000-#4000) LD L,(HL) OUT (SLOT1),A LD A,L AND A SCF RET Z AND A RET ;----------------------------------------------------------------------; ; ; ;----------------------------------------------------------------------; ; Получить список страниц блока в HL ; Вход: A - блок, HL - адрес буфера - 256 байт. ; Выход: HL - адрес блока, B - длина блока в страницах ОЗУ ;EMM_FN5M: EMM.GetMemBlkPages: PUSH DE PUSH HL EX DE,HL LD B,0 LD L,A .loop: LD A,L LD (DE),A INC DE AND A JR Z,.error CP #FF JR Z,.end ; IN A,(SLOT1) LD C,A LD A,SYS_PAGE OUT (SLOT1),A LD H,high (SYS_PAGE.RAM_TABLE-#4000-#4000) LD L,(HL) LD A,C OUT (SLOT1),A ; INC B JR NZ,.loop .error: SCF .end: POP HL POP DE RET ; RAMDRV.EXE вызывает эту функцию с адресом в SLOT1, поэтому лучше так не оптимизировать ; EMM.GetMemBlkPages: ; PUSH DE ; PUSH HL ; EX DE,HL ; LD B,0 ; LD L,A ; IN A,(SLOT1) ; LD C,A ; LD A,SYS_PAGE ; OUT (SLOT1),A ; .loop: LD A,L ; LD (DE),A ; INC DE ; AND A ; JR Z,.error ; CP #FF ; JR Z,.end ; ; ; LD H,high +(SYS_PAGE.RAM_TABLE - #4000 - #4000) ; LD L,(HL) ; INC B ; JR NZ,.loop ; .error: SCF ; .end: LD A,C ; OUT (SLOT1),A ; POP HL ; POP DE ; RET ;----------------------------------------------------------------------; ; ; ;----------------------------------------------------------------------; ; разделить блок памяти на два блока ; A - блок, B - длина первого блока после разделения ; выход: A - блок 1, B - блок 2 EMM.DivMemBlocks: INC B DEC B SCF RET Z DEC B LD E,A CALL EMM.GetMemPage ; получить номер страницы блока RET C LD D,A IN A,(SLOT3) EX AF,AF' LD A,SYS_PAGE OUT (SLOT3),A LD H,high +(SYS_PAGE.RAM_TABLE); - #4000 - #4000) LD L,D LD A,(HL) LD (HL),#FF LD B,A EX AF,AF' OUT (SLOT3),A LD A,E AND A RET ;----------------------------------------------------------------------; ; ; ;----------------------------------------------------------------------; ; слить два блока памяти в один ; А - блок 1, B - блок 2 ; выход: А - блок EMM.MergeMemBlocks: LD E,A IN A,(SLOT3) EX AF,AF' LD A,SYS_PAGE OUT (SLOT3),A LD H,high SYS_PAGE.RAM_TABLE LD L,E LD C,B LD B,0 .ADD_L: LD A,(HL) AND A JR Z,.ADD_ERR CP #FF JR Z,.ADD_NEXT LD L,A DJNZ .ADD_L .ADD_ERR: EX AF,AF' OUT (SLOT3),A SCF RET .ADD_NEXT: LD A,C AND A JR Z,.ADD_ERR LD (HL),A EX AF,AF' OUT (SLOT3),A AND A LD A,E RET ;----------------------------------------------------------------------; ; ; ;----------------------------------------------------------------------; ; вход: DE - ram_disk trk_sec, A - RAM-Disk ; выход: HL - адрес, A - page RAMD_CALC_PAGE: CP 16 CCF RET C ; НЕТ ТАКОГО RAM-Disk PUSH AF LD H,D LD L,E ADD HL,HL ADD HL,HL LD B,H LD A,E OR #C0 LD C,A ; C - часть адреса, B - страница POP AF CALL EMM.GetMemPageRMD ; ПОЛУЧИТЬ СТРАНИЦУ LD L,0 LD H,C RET ;----------------------------------------------------------------------; ; ; ;----------------------------------------------------------------------; ; Вход: ; A - RAM Disk ID ; Выход: ; A - Number (0..15) GET_RAMD_NUM: EX AF,AF' IN A,(SLOT1) EX AF,AF' LD BC,SYS_PAGE*256+SLOT1 OUT (C),B LD HL,SYS_PAGE.RAMD_KEYS-#4000-#4000 LD BC,SYS_PAGE.RAMD_KEYS.NUM CPIR EX AF,AF' OUT (SLOT1),A EX AF,AF' SCF RET PE DEC L LD A,L SUB low SYS_PAGE.RAMD_KEYS RET ;----------------------------------------------------------------------; ; ; ;----------------------------------------------------------------------; ; [x] 04/11/2023 ; Вход: ; B = 0: swap to Sp ; B = #FF: swap to ZX ; B = #FE: no swap, only get info ; Выход: ; A - current RAM Drives set SWAP_RAM_DRIVES: IN A,(SLOT3) EX AF,AF' PUSH AF ;на всякий случай LD A,SYS_PAGE OUT (SLOT3),A ; LD A,(SYS_PAGE.CURRENT_RAM_DRV) LD C,A CP B JR Z,.exit ; уже установлен запрашиваемый набор ; LD A,#FE CP B JR Z,.exit ; ничего не менять, выдать текущий набор ; .swap: LD HL,SYS_PAGE.RAMD_KEYS LD DE,SYS_PAGE.Sp_RAMD_KEYS LD B,SYS_PAGE.RAMD_KEYS.NUM .loop: LD A,(DE) LD C,A LD A,(HL) LD (DE),A LD A,C LD (HL),A INC HL INC DE DJNZ .loop ; LD A,(SYS_PAGE.CURRENT_RAM_DRV) XOR #FF LD (SYS_PAGE.CURRENT_RAM_DRV),A LD C,A ; .exit: EX AF,AF' OUT (SLOT3),A POP AF EX AF,AF' LD A,C RET ;----------------------------------------------------------------------; ; ; ;----------------------------------------------------------------------; ; на выходе при А = 0 должен быть установлен флаг Z ; не убивает DE и BC GET_RAMD_ST: CP SYS_PAGE.RAMD_KEYS.NUM CCF RET C PUSH BC LD HL,SYS_PAGE.RAMD_KEYS-#4000-#4000 ADD A,L LD L,A IN A,(SLOT1) LD B,A LD A,SYS_PAGE OUT (SLOT1),A LD C,(HL) LD A,B OUT (SLOT1),A LD A,C POP BC AND A RET ;----------------------------------------------------------------------; ; ; ;----------------------------------------------------------------------; ; RAM-Disk A, BLK - B BLK_TO_RAMD: CP SYS_PAGE.RAMD_KEYS.NUM CCF RET C PUSH HL LD L,A IN A,(SLOT3) LD C,A LD A,SYS_PAGE OUT (SLOT3),A LD A,L LD HL,SYS_PAGE.RAMD_KEYS; - #4000 - #4000 ADD A,L LD L,A LD A,(HL) ; ключ блока AND A JR NZ,BLK_BUSY ; RAM-Disk занят - ошибка LD (HL),B LD A,C OUT (SLOT3),A LD A,B AND A POP HL RET ; BLK_BUSY: LD A,C OUT (SLOT3),A SCF POP HL LD A,L RET ;----------------------------------------------------------------------; ; ; ;----------------------------------------------------------------------; ; RAM-Disk A RAMD_CLEAR: CP SYS_PAGE.RAMD_KEYS.NUM CCF RET C PUSH HL LD L,A IN A,(SLOT3) LD C,A LD A,SYS_PAGE OUT (SLOT3),A LD A,L LD HL,SYS_PAGE.RAMD_KEYS; - #4000 - #4000 ; RAM-Disk свободен ADD A,L LD L,A LD B,A ; запомнить удаляемый рамдиск LD A,(HL) AND A JR Z,BLK_BUSY ; возврат с ошибкой LD (HL),0 LD A,C OUT (SLOT3),A AND A POP HL RET ;----------------------------------------------------------------------; ; ; ;----------------------------------------------------------------------; !FIXIT SAFE_RGADR ;RAMD_R_W: ; ╔════════════════════════════════════════════════╗ ; ║ RD/WR SECTOR ║\ ; ║ HL - BUFER ║\ ; ║ DE - ABS sector в 256b блоках ║\ ; ║ B - число данных в 256b блоках ║\ ; ║ A - block RAM ║\ ; ║ A' - команда чтение/запись/чтение ROM Disk ║\ ; ║ 0 - read, 255 - write, 70 - read ROM DISK║\ ; ║ ** NOT USED TR-DOS VARS ** ║\ ; ╚════════════════════════════════════════════════╝\ ; \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ BLK_RD_WR: AND A SCF RET Z ; AND A INC B DEC B RET Z ; сохраняем состояние прерываний LD C,A LD A,R PUSH AF ; сохраняем PORT_Y IN A,(PORT_Y) PUSH AF LD A,#C0 OUT (PORT_Y),A ; LD A,C DI CALL .start EX AF,AF' ; восстанавливаем PORT_Y POP AF OUT (PORT_Y),A ; восстанавливаем состояние прерываний POP AF JP PO,.noInterrupts EI .noInterrupts: EX AF,AF' RET ; ; .start: EX AF,AF' AND A ; 0 - read JR Z,.reset_Z CP #FF ; write JR Z,.keep_Z ; CP 5 ; old read JR Z,.reset_Z CP 6 ; old write JR Z,.keep_Z ; CP #46 JP Z,ROM_DISK ; EX AF,AF' SCF RET ; .reset_Z: INC A ; set Z for WRITE .keep_Z: EX AF,AF' ; PUSH HL PUSH BC LD C,SLOT1 IN B,(C) LD H,A LD A,SYS_PAGE OUT (SLOT1),A LD A,H ; LD H,high +(SYS_PAGE.RAM_TABLE-#4000-#4000) LD L,A INC D .RAMD_LOOP_D: DEC D JR Z,.NOT_FOUR_BLK LD L,(HL) LD L,(HL) LD L,(HL) LD L,(HL) JP .RAMD_LOOP_D ; .NOT_FOUR_BLK: LD A,E .loop: SUB #40 JR C,.NOT_ONE_BLK LD L,(HL) JP .loop ; .NOT_ONE_BLK: AND #3F LD D,A ; DE - ADRESS in RAM-Disk LD E,0 LD A,L ; L - текущий банк RAM-Disk OUT (C),B ; восстановить страницу POP BC ; длина данных POP HL ; адрес буфера BIT 7,H JR NZ,.BLK_PAGE1 ; LD C,SLOT3 IN C,(C) OUT (SLOT3),A SET 7,D SET 6,D JP .BLK_CONT1 ; .BLK_PAGE1: LD C,SLOT1 IN C,(C) OUT (SLOT1),A RES 7,D SET 6,D ; DE - RamDisk, HL - data .BLK_CONT1: EX AF,AF' JR Z,.NO_EX_RW1 ; WRITE EX DE,HL ; for READ .NO_EX_RW1: EX AF,AF' LD A,16 ; .BLK_LL1: DUP 16 LDI EDUP DEC A JR NZ,.BLK_LL1 ; EX AF,AF' JR Z,.NO_EX_RW2 ; WRITE EX DE,HL ; for READ .NO_EX_RW2: EX AF,AF' ; DEC C прокрутился 256 раз и вернулся ; A = 0 CP B JP Z,.BLK_EXIT_1 ; BIT 6,D JP NZ,.BLK_CONT1 ; BIT 7,D JR Z,.BLK_PAGE3_X ; IN A,(SLOT1) LD E,A LD D,high +(SYS_PAGE.RAM_TABLE-#4000-#4000) LD A,SYS_PAGE OUT (SLOT1),A LD A,(DE) OUT (SLOT1),A LD DE,#4000 JP .BLK_CONT1 ; .BLK_PAGE3_X: IN A,(SLOT3) LD E,A LD D,high SYS_PAGE.RAM_TABLE LD A,SYS_PAGE OUT (SLOT3),A LD A,(DE) OUT (SLOT3),A LD DE,#C000 ; BIT 7,H JP Z,.BLK_CONT1 ; LD E,A LD A,C OUT (SLOT3),A IN A,(SLOT1) LD C,A LD A,E OUT (SLOT1),A LD DE,#4000 JP .BLK_CONT1 ; .BLK_EXIT_1: LD A,D DEC A RLCA LD A,C JR C,.BLK_EXIT_2 OUT (SLOT1),A RET ; .BLK_EXIT_2: OUT (SLOT3),A AND A RET ;----------------------------------------------------------------------; ; ; ;----------------------------------------------------------------------; ;**************************************** ;!!!!! READ_ROM_PAGE_X чтение последних ; 256 байтов ПЗУ в служебную страницу зачем-то ; READ_ROM_PAGE_X: ; LD DE,0 ; LD BC,#100 ; один сектор ; PUSH DE ; PUSH BC ; LD HL,#3F00 ; LD DE,#FF00 ; LD A,#1F ; last page ROM ; JR ROM_DISK.loopRead ;**************************************** ; Чтение с ROM-Disk ; HL - адрес, куда читать ; DE - номер сектора (считать по 256b сектор) ; B - число секторов ; A' - размер сектора (1 - 256b, 2 - 512 b) ROM_DISK: EX AF,AF' LD C,0 ; счетчик DEC A JR Z,.loop ; DEC A SCF RET NZ ; EX DE,HL ADD HL,HL EX DE,HL LD A,B ADD A,A LD B,A RET C ; DI CALL .loop RET C ; AND A RR D RR E XOR A RET ; .loop: PUSH DE ; номер сектора PUSH BC ; LD A,E AND #3F ; ADRESS in ROM-Page PUSH AF ; сохранить адрес ; EX DE,HL ; DE - адрес буфера ADD HL,HL ADD HL,HL ; H - номер банки ; [ ] без привязки ром-диска к align 256 ;LD A,(ROM_DISK.Pages.Number) ;INC H ;CP H ; LD C,H LD B,0 LD HL,ROM_DISK.Pages ADD HL,BC ; LD A,(ROM_DISK.Pages.Number) ; rdlow-ok INC C CP C ; ;LD L,H ;LD H,high ROM_DISK.Pages.Number ; ROM-Disk pages! ; LD A,(HL) ; PAGE-ROM POP HL ; восстановить адрес в ROM-Page LD L,0 ; если далеко захотели - выход с ошибкой JR C,.errorExit ; ROM-Disk-end ; DE - буфер ; HL - адрес в ROM ; B - число секторов ; A - ROM-Page .loopRead: PUSH HL ; откуда PUSH DE ; куда LD HL,-.stackDepth-.readProcedure.size ; memory stack use! ADD HL,SP ; stack PUSH HL ; адрес программы .readProcedure LD DE,.readProcedure ; перенести программу на стек EX DE,HL LD BC,.readProcedure.size LDIR ; программа на стеке LD BC,#100 ; длина сектора RET ; исполнить программу .readProcedure, на стеке адреса буфера и ROM ; DE - next address ; HL - ROM address .readNext: POP BC ; число секторов INC C ; счетчик считанных секторов DEC B ; сектора кончились? JR Z,.normExit BIT 6,H ; чтение не закончено PUSH BC ; сохранить счетчики JR Z,.loopRead ; читать дальше POP BC POP HL ; номер сектора LD A,B LD B,0 ADD HL,BC LD B,A ; вычислить след.сектор EX DE,HL ; теперь HL - адрес, DE сектор, B - сколько еще читать JP .loop ; начать все снова! ; чтение закончено .normExit: POP HL ; сектор, откуда велось чтение ADD HL,BC ; по возврату: HL - след.адрес EX DE,HL ; DE - след.сектор AND A RET ; ошибка .errorExit: ; !TODO сделать, чтоб на выходе показывалось количество прочитанных секторов POP BC POP DE SCF RET ; процедура, переносимая на стек для чтения из ROM-Disk ; осторожнее с PUSH, если надо много, то увеличить .stackDepth .readProcedure: POP DE ; куда POP HL ; откуда OUT (ROM.SLOT0),A ; ROM_PAGE LDIR ; здесь читается из ROM-Disk LD B,A XOR A OUT (ROM.SLOT0),A OUT (SYS_PORT.ROM),A LD A,B JP .readNext .stackDepth EQU 8 ; расстояние от конца процедуры до вершины стека. .readProcedure.size EQU $-.readProcedure ;----------------------------------------------------------------------; ;