From 1506291b8da8b064fa7a275fa631041140458160 Mon Sep 17 00:00:00 2001 From: Anatoliy Belyanskiy Date: Sat, 23 Sep 2023 07:29:45 +1000 Subject: [PATCH] =?UTF-8?q?=20=D1=84=D1=83=D0=BD=D0=BA=D1=86=D0=B8=D0=B8?= =?UTF-8?q?=20=D1=80=D0=B0=D0=B1=D0=BE=D1=82=D1=8B=20=D1=81=20=D0=BF=D0=B0?= =?UTF-8?q?=D0=BC=D1=8F=D1=82=D1=8C=D1=8E=20=D0=BD=D0=B5=20=D0=B8=D1=81?= =?UTF-8?q?=D0=BF=D0=BE=D0=BB=D1=8C=D0=B7=D1=83=D1=8E=D1=82=20=D1=82=D0=B5?= =?UTF-8?q?=D0=BF=D0=B5=D1=80=D1=8C=20SLOT2=20-=20=D1=8D=D1=82=D0=BE=20?= =?UTF-8?q?=D0=BC=D0=BE=D0=B3=D0=BB=D0=BE=20=D0=B2=D1=8B=D0=B7=D0=B2=D0=B0?= =?UTF-8?q?=D1=82=D1=8C=20=D0=B1=D0=B0=D0=B3=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/bios/exp/FUNC_RAM_ROM_DRV.ASM | 224 +++++++++++++++--------------- src/bios/shared/DEFINES.INC | 2 +- src/bios/shared/RECOVERY.IMG | Bin 98304 -> 98304 bytes 3 files changed, 114 insertions(+), 112 deletions(-) diff --git a/src/bios/exp/FUNC_RAM_ROM_DRV.ASM b/src/bios/exp/FUNC_RAM_ROM_DRV.ASM index c7cb952..a40eff5 100644 --- a/src/bios/exp/FUNC_RAM_ROM_DRV.ASM +++ b/src/bios/exp/FUNC_RAM_ROM_DRV.ASM @@ -1,15 +1,16 @@ ;===================[ Функции распределения памяти ]===================; - +; Выход: BC - FREE MEM в блоках по 16k, HL - FULL MEM +;!TEST все SLOT2 на SLOT1 ; ;----------------------------------------------------------------------; ; Определение объема памяти. ; Выход: BC - FREE MEM в блоках по 16k, HL - FULL MEM EMM.GetMemSize: - IN A,(SLOT2) + IN A,(SLOT1) LD B,A LD A,SYS_PAGE - OUT (SLOT2),A - LD HL,SYS_PAGE.RAMD_FAT-#4000 + OUT (SLOT1),A + LD HL,SYS_PAGE.RAMD_FAT-#4000 - #4000 LD C,0 .loop: LD A,(HL) INC L @@ -21,7 +22,7 @@ EMM.GetMemSize: .exit: LD HL,#100 LD A,B LD B,0 - OUT (SLOT2),A + OUT (SLOT1),A RET ;----------------------------------------------------------------------; ; @@ -36,11 +37,11 @@ EMM.InitMem: PUSH HL PUSH DE - IN A,(SLOT2) + IN A,(SLOT1) LD C,A LD A,SYS_PAGE - OUT (SLOT2),A - LD HL,SYS_PAGE.RAMD_FAT-#4000 ; Адрес FAT ОЗУ. + OUT (SLOT1),A + LD HL,SYS_PAGE.RAMD_FAT-#4000 - #4000 ; Адрес FAT ОЗУ. ; обнуляем таблицу .loopFree: LD (HL),0 @@ -48,7 +49,7 @@ EMM.InitMem: JR NZ,.loopFree ; резервируем спец.страницы и страницы ZX LD B,RESERVED_PAGES.Blocks - LD DE,RESERVED_PAGES ; таблица занятых системных страниц + LD DE,RESERVED_PAGES ; таблица занятых системных страниц .loop: LD A,(DE) CP #FF JR Z,.exitLoop @@ -65,13 +66,13 @@ EMM.InitMem: LD L,A LD (HL),A ; Инициализация ключей RAM-Disks - LD HL,SYS_PAGE.RAMD_KEYS-#4000 + LD HL,SYS_PAGE.RAMD_KEYS-#4000 - #4000 LD B,SYS_PAGE.RAMD_KEYS.NUM .loop2: LD (HL),0 INC L DJNZ .loop2 LD A,C - OUT (SLOT2),A + OUT (SLOT1),A POP DE POP HL @@ -115,12 +116,12 @@ RESERVED_PAGES: EMM.GetMem: ;PUSH DE PUSH BC - IN A,(SLOT2) + IN A,(SLOT1) EX AF,AF' LD A,SYS_PAGE - OUT (SLOT2),A + OUT (SLOT1),A LD C,B ; сохранить число нужных блоков - LD HL,SYS_PAGE.RAMD_FAT-#4000 + LD HL,SYS_PAGE.RAMD_FAT-#4000 - #4000 ; Цикл проверки наличия нужных блоков. .loop: DEC L JR Z,.noRAM @@ -132,7 +133,7 @@ EMM.GetMem: ; Место есть ! LD B,C ; Восстановить нужный объем диска LD C,#FF ; МЕТКА КОНЦА RAM-Disk - LD HL,SYS_PAGE.RAMD_FAT-#4000 + LD HL,SYS_PAGE.RAMD_FAT-#4000 - #4000 ; Заполнить RAMD_FAT .loop2: DEC L @@ -145,7 +146,7 @@ EMM.GetMem: ; L - указатель цепочки. EX AF,AF' - OUT (SLOT2),A + OUT (SLOT1),A LD A,L AND A POP BC @@ -154,7 +155,7 @@ EMM.GetMem: .noRAM: LD L,1 ; НЕТ ПАМЯТИ EX AF,AF' - OUT (SLOT2),A + OUT (SLOT1),A LD A,L SCF POP BC @@ -203,13 +204,13 @@ EMM.FreeMemRMD: SCF RET Z LD C,A - IN A,(SLOT2) + IN A,(SLOT1) LD B,A LD A,SYS_PAGE - OUT (SLOT2),A + OUT (SLOT1),A LD (HL),0 LD A,B - OUT (SLOT2),A + OUT (SLOT1),A LD A,C ;JR EMM.FreeMem ;------[ @@ -222,12 +223,12 @@ EMM.FreeMem: RET Z LD L,A - IN A,(SLOT2) + IN A,(SLOT1) EX AF,AF' LD A,SYS_PAGE - OUT (SLOT2),A + OUT (SLOT1),A - LD H,high (SYS_PAGE.RAMD_FAT - #4000) + LD H,high (SYS_PAGE.RAMD_FAT - #4000 - #4000) LD A,L EMM_F3M_L1: LD L,A @@ -239,14 +240,14 @@ EMM_F3M_L1: JR NZ,EMM_F3M_L1 ; продолжать EX AF,AF' - OUT (SLOT2),A + OUT (SLOT1),A LD A,0 ;!FIXIT недокументировано AND A RET EMM_FN3M_ERR: EX AF,AF' - OUT (SLOT2),A + OUT (SLOT1),A LD A,2 ;!FIXIT недокументировано SCF RET @@ -273,13 +274,13 @@ EMM.GetMemPageRMD: ;EMM_FN4M: EMM.GetMemPage: LD L,A - IN A,(SLOT2) + IN A,(SLOT1) EX AF,AF' LD A,SYS_PAGE - OUT (SLOT2),A + OUT (SLOT1),A INC B - LD H,high (SYS_PAGE.RAMD_FAT - #4000) + LD H,high (SYS_PAGE.RAMD_FAT - #4000 - #4000) EMM_F4M_L1: LD A,(HL) AND A @@ -292,14 +293,14 @@ EMM_F4M_L1: EMM_F4M_ERR: LD L,A EX AF,AF' - OUT (SLOT2),A + OUT (SLOT1),A LD A,L SCF RET EMM_F4M_END: EX AF,AF' - OUT (SLOT2),A + OUT (SLOT1),A LD A,L AND A RET @@ -319,14 +320,14 @@ EMM.GetMemPageNext: AND A SCF RET Z - IN A,(SLOT2) + IN A,(SLOT1) LD H,A LD A,SYS_PAGE - OUT (SLOT2),A + OUT (SLOT1),A LD A,H - LD H,high (SYS_PAGE.RAMD_FAT - #4000) + LD H,high (SYS_PAGE.RAMD_FAT - #4000 - #4000) LD L,(HL) - OUT (SLOT2),A + OUT (SLOT1),A LD A,L AND A SCF @@ -361,14 +362,14 @@ EMM.GetMemBlkPages: CP #FF JR Z,.end ; - IN A,(SLOT2) + IN A,(SLOT1) LD C,A LD A,SYS_PAGE - OUT (SLOT2),A - LD H,high (SYS_PAGE.RAMD_FAT - #4000) + OUT (SLOT1),A + LD H,high (SYS_PAGE.RAMD_FAT - #4000 - #4000) LD L,(HL) LD A,C - OUT (SLOT2),A + OUT (SLOT1),A ; INC B JR NZ,.loop @@ -450,105 +451,105 @@ BLK_RD_WR: PUSH HL PUSH BC - LD C,SLOT2 + LD C,SLOT1 IN B,(C) - ld h,a + LD H,A LD A,SYS_PAGE - OUT (SLOT2),A - ld a,h + OUT (SLOT1),A + LD A,H - LD H,high (SYS_PAGE.RAMD_FAT - #4000) + LD H,high (SYS_PAGE.RAMD_FAT - #4000 - #4000) LD L,A INC D -RAMD_LOOP_D: +.RAMD_LOOP_D: DEC D - JR Z,NOT_FOUR_BLK + JR Z,.NOT_FOUR_BLK LD L,(HL) LD L,(HL) LD L,(HL) LD L,(HL) - JR RAMD_LOOP_D + JR .RAMD_LOOP_D -NOT_FOUR_BLK: +.NOT_FOUR_BLK: LD A,E .loop: SUB #40 - JR C,NOT_ONE_BLK + JR C,.NOT_ONE_BLK LD L,(HL) JR .loop -NOT_ONE_BLK: +.NOT_ONE_BLK: AND #3F - LD D,A ; DE - ADRESS in RAM-Disk + LD D,A ; DE - ADRESS in RAM-Disk LD E,0 - LD A,L ; L - текущий банк RAM-Disk + LD A,L ; L - текущий банк RAM-Disk - OUT (C),B ; восстановить страницу + OUT (C),B ; восстановить страницу - POP BC ; длина данных - POP HL ; адрес буфера + POP BC ; длина данных + POP HL ; адрес буфера BIT 7,H - JR NZ,BLK_PAGE1 ; !!!!! JR NZ,BLK_PAGE1 ? + JR NZ,.BLK_PAGE1 ; !!!!! JR NZ,BLK_PAGE1 ? -BLK_PAGE3: ; !TODO переделать на SLOT ????? +.BLK_PAGE3: ; !TODO переделать на SLOT ????? LD C,SLOT3 IN C,(C) OUT (SLOT3),A SET 7,D SET 6,D - JR BLK_CONT1 + JR .BLK_CONT1 -BLK_PAGE1: +.BLK_PAGE1: LD C,SLOT1 IN C,(C) OUT (SLOT1),A RES 7,D SET 6,D -BLK_CONT1: ; DE - RamDisk, HL - data +.BLK_CONT1: ; DE - RamDisk, HL - data EX AF,AF' - JR Z,NO_EX_RW1 ; WRITE + JR Z,.NO_EX_RW1 ; WRITE EX DE,HL ; for READ -NO_EX_RW1: +.NO_EX_RW1: EX AF,AF' LD A,16 -BLK_LL1: +.BLK_LL1: DUP 16 LDI EDUP DEC A - JR NZ,BLK_LL1 + JR NZ,.BLK_LL1 EX AF,AF' - JR Z,NO_EX_RW2 ; WRITE + JR Z,.NO_EX_RW2 ; WRITE EX DE,HL ; for READ -NO_EX_RW2: +.NO_EX_RW2: EX AF,AF' ; DEC C прокрутился 256 раз и вернулся INC B ; B уже уменьшился на 1, DEC B - JP Z,BLK_EXIT_1 + JP Z,.BLK_EXIT_1 BIT 6,D - JP NZ,BLK_CONT1 + JP NZ,.BLK_CONT1 BIT 7,D - JR Z,BLK_PAGE3_X + JR Z,.BLK_PAGE3_X IN A,(SLOT1) LD E,A - LD D,#42 + LD D,high (SYS_PAGE.RAMD_FAT - #4000 - #4000) LD A,SYS_PAGE OUT (SLOT1),A LD A,(DE) OUT (SLOT1),A LD DE,#4000 - JP BLK_CONT1 + JP .BLK_CONT1 -BLK_PAGE3_X: +.BLK_PAGE3_X: IN A,(SLOT3) LD E,A LD D,#C2 @@ -559,7 +560,7 @@ BLK_PAGE3_X: LD DE,#C000 BIT 7,H - JP Z,BLK_CONT1 + JP Z,.BLK_CONT1 LD E,A LD A,C @@ -569,17 +570,17 @@ BLK_PAGE3_X: LD A,E OUT (SLOT1),A LD DE,#4000 - JP BLK_CONT1 + JP .BLK_CONT1 -BLK_EXIT_1: +.BLK_EXIT_1: LD A,D DEC A RLCA LD A,C - JR C,BLK_EXIT_2 + JR C,.BLK_EXIT_2 OUT (SLOT1),A RET -BLK_EXIT_2: +.BLK_EXIT_2: OUT (SLOT3),A AND A RET @@ -794,17 +795,17 @@ RAMD_CALC_PAGE: ; A - Number (0..15) GET_RAMD_NUM: EX AF,AF' - IN A,(SLOT2) + IN A,(SLOT1) EX AF,AF' - LD BC,SYS_PAGE * 256 + SLOT2 + LD BC,SYS_PAGE * 256 + SLOT1 OUT (C),B - LD HL,SYS_PAGE.RAMD_KEYS-#4000 + LD HL,SYS_PAGE.RAMD_KEYS-#4000 - #4000 LD BC,SYS_PAGE.RAMD_KEYS.NUM CPIR EX AF,AF' - OUT (SLOT2),A + OUT (SLOT1),A EX AF,AF' SCF @@ -830,17 +831,17 @@ GET_RAMD_ST: PUSH BC - LD HL,SYS_PAGE.RAMD_KEYS-#4000 + LD HL,SYS_PAGE.RAMD_KEYS-#4000 - #4000 ADD A,L LD L,A - IN A,(SLOT2) + IN A,(SLOT1) LD B,A LD A,SYS_PAGE - OUT (SLOT2),A + OUT (SLOT1),A LD C,(HL) LD A,B - OUT (SLOT2),A + OUT (SLOT1),A LD A,C POP BC AND A @@ -861,12 +862,12 @@ BLK_TO_RAMD: PUSH HL LD L,A - IN A,(SLOT2) + IN A,(SLOT1) LD C,A LD A,SYS_PAGE - OUT (SLOT2),A + OUT (SLOT1),A LD A,L - LD HL,SYS_PAGE.RAMD_KEYS-#4000 + LD HL,SYS_PAGE.RAMD_KEYS-#4000 - #4000 ADD A,L LD L,A LD A,(HL) ; ключ блока @@ -875,7 +876,7 @@ BLK_TO_RAMD: LD (HL),B LD A,C - OUT (SLOT2),A + OUT (SLOT1),A LD A,B AND A @@ -884,7 +885,7 @@ BLK_TO_RAMD: BLK_BUSY: LD A,C - OUT (SLOT2),A + OUT (SLOT1),A SCF POP HL @@ -905,12 +906,12 @@ RAMD_CLEAR: PUSH HL LD L,A - IN A,(SLOT2) + IN A,(SLOT1) LD C,A LD A,SYS_PAGE - OUT (SLOT2),A + OUT (SLOT1),A LD A,L - LD HL,SYS_PAGE.RAMD_KEYS-#4000 ; RAM-Disk свободен + LD HL,SYS_PAGE.RAMD_KEYS-#4000 - #4000 ; RAM-Disk свободен ADD A,L LD L,A LD B,A ; запомнить удаляемый рамдиск @@ -919,7 +920,7 @@ RAMD_CLEAR: JR Z,BLK_BUSY ; возврат с ошибкой LD (HL),0 LD A,C - OUT (SLOT2),A + OUT (SLOT1),A AND A POP HL @@ -945,19 +946,19 @@ EMM.DivMemBlocks: RET C LD D,A - IN A,(SLOT2) + IN A,(SLOT1) EX AF,AF' LD A,SYS_PAGE - OUT (SLOT2),A + OUT (SLOT1),A - LD H,high (SYS_PAGE.RAMD_FAT - #4000) + LD H,high (SYS_PAGE.RAMD_FAT - #4000 - #4000) LD L,D LD A,(HL) - LD (HL),0FFH + LD (HL),#FF LD B,A EX AF,AF' - OUT (SLOT2),A + OUT (SLOT1),A LD A,E AND A @@ -974,35 +975,36 @@ EMM.DivMemBlocks: ; выход: А - блок EMM.MergeMemBlocks: LD E,A - IN A,(SLOT2) + IN A,(SLOT1) EX AF,AF' LD A,SYS_PAGE - OUT (SLOT2),A - LD H,high (SYS_PAGE.RAMD_FAT - #4000) + OUT (SLOT1),A + LD H,high (SYS_PAGE.RAMD_FAT - #4000 - #4000) LD L,E LD C,B LD B,0 -EMM_ADD_L: +.EMM_ADD_L: LD A,(HL) AND A - JR Z,EMM_ADD_ERR - CP 0FFH - JR Z,EMM_ADD_NEXT + JR Z,.EMM_ADD_ERR + CP #FF + JR Z,.EMM_ADD_NEXT LD L,A - DJNZ EMM_ADD_L -EMM_ADD_ERR: + DJNZ .EMM_ADD_L + +.EMM_ADD_ERR: EX AF,AF' - OUT (SLOT2),A + OUT (SLOT1),A SCF RET -EMM_ADD_NEXT: +.EMM_ADD_NEXT: LD A,C AND A - JR Z,EMM_ADD_ERR + JR Z,.EMM_ADD_ERR LD (HL),A EX AF,AF' - OUT (SLOT2),A + OUT (SLOT1),A AND A LD A,E RET diff --git a/src/bios/shared/DEFINES.INC b/src/bios/shared/DEFINES.INC index d329567..dfc9e93 100644 --- a/src/bios/shared/DEFINES.INC +++ b/src/bios/shared/DEFINES.INC @@ -20,7 +20,7 @@ DEFINE TEST_INT 1 ; Тестовый обработчик пользовательского INT DEFINE NEW_FEATURE 0 ; !TODO пункты в сетап DEFINE HDDwriteProtect 0 - DEFINE RECOVERYmountTYPE 1 ; 1 - быстрый немного захардкоженый вариант. 2 - более "правильный" + DEFINE RECOVERYmountTYPE 2 ; 1 - быстрый немного захардкоженый вариант. 2 - более "правильный" DEFINE RECOVERYrdChooseTYPE 1 ; 1 - RECOVERY всегда грузится в диск 15, 2 - ищется свободный рамдиск и если такого нет, то занимается 15ый DEFINE FDD_NormalCount 0 ; \ No newline at end of file diff --git a/src/bios/shared/RECOVERY.IMG b/src/bios/shared/RECOVERY.IMG index 3c046d8bdc341af7ef3bb1886a09cd28145d8abd..64067dc5854835777d69c253e8df3d5b50ce94c5 100755 GIT binary patch delta 11352 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 delta 10577 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 SajPr2gjR*C^@Che_J05(&X(i=