From a3aef23cd6747d12896de93227686dffa17b0176 Mon Sep 17 00:00:00 2001 From: Tolik <85737314+Tolik-Trek@users.noreply.github.com> Date: Sat, 7 Jun 2025 04:30:14 +1000 Subject: [PATCH] =?UTF-8?q?=D1=82=D0=B5=D1=81=D1=82=D0=B8=D1=80=D0=BE?= =?UTF-8?q?=D0=B2=D0=B0=D0=BD=D0=B8=D0=B5=20=D0=B7=D0=B0=D0=B4=D0=B5=D1=80?= =?UTF-8?q?=D0=B6=D0=B5=D0=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Shared_Includes | 2 +- src/bios/exp/BIOS_FUNC.asm | 96 +++++------ src/bios/exp/EXP.asm | 32 ++-- src/bios/exp/EXTENDED/IDE/ATAPI_DRV.ASM | 178 +++++++++++++------- src/bios/exp/FUNC_RAM_ROM_DRV.ASM | 2 +- src/bios/exp/FUNC_SERVICE.asm | 2 +- src/bios/exp/FUNC_SYS.ASM | 2 - src/bios/rom/SETUP/AUTOIDE.asm | 77 +++++++-- src/bios/rom/SETUP/IM2_INT.asm | 62 ++++--- src/bios/rom/SETUP/MAIN.asm | 22 ++- src/bios/rom/SETUP/VIDEO_IO.asm | 26 ++- src/bios/rom/SETUP/startup_sound.asm | 215 ++++++++++++++++++++++++ src/bios/shared/DEFINES.INC | 1 + src/bios/shared/RECOVERY.IMG | Bin 98304 -> 98304 bytes 14 files changed, 522 insertions(+), 195 deletions(-) create mode 100644 src/bios/rom/SETUP/startup_sound.asm diff --git a/Shared_Includes b/Shared_Includes index be5eed4..83c2b69 160000 --- a/Shared_Includes +++ b/Shared_Includes @@ -1 +1 @@ -Subproject commit be5eed466fa1c0e442b828a42ffc1b9abda23ac9 +Subproject commit 83c2b69b4af0a36475fa42378000fb6e57c59021 diff --git a/src/bios/exp/BIOS_FUNC.asm b/src/bios/exp/BIOS_FUNC.asm index 063881c..dfcd642 100644 --- a/src/bios/exp/BIOS_FUNC.asm +++ b/src/bios/exp/BIOS_FUNC.asm @@ -677,16 +677,15 @@ TAB_5xFNS: ;************************************ ; Вход в функцию по RST18 и RST8 -EXP_FNS_RST18: - PUSH HL - LD L,C - LD H,high TAB_FNS - LD C,(HL) - INC H - LD H,(HL) - LD L,C - EX (SP),HL - RET +EXP_FNS_RST18: PUSH HL + LD L,C + LD H,high TAB_FNS + LD C,(HL) + INC H + LD H,(HL) + LD L,C + EX (SP),HL + RET ; ATA_5x_RESET ; ATA_5x_LONG_READ @@ -704,50 +703,39 @@ EXP_FNS_RST18: ; FN_RESERVED_5x ; DRV_LIST -FN_5x_Parser_1: ; ATA_5x_RESET - LD C,#01 - JP FN_5x_Parser -FN_5x_Parser_2: ; ATA_5x_LONG_READ - LD C,#02 - JP FN_5x_Parser -FN_5x_Parser_3: ; ATA_5x_LONG_WRITE - LD C,#03 - JP FN_5x_Parser -FN_5x_Parser_4: ; ATA_5x_VERIFY - LD C,#04 - JP FN_5x_Parser -FN_5x_Parser_6: ; ATA_5x_WRITE - LD C,#06 - JP FN_5x_Parser -FN_5x_Parser_7: ; ATA_5x_DETECT - LD C,#07 - JP FN_5x_Parser -FN_5x_Parser_8: ; ATA_5x_GET_PAR - LD C,#08 - JP FN_5x_Parser -FN_5x_Parser_9: ; ATA_5x_SET_PAR - LD C,#09 - JP FN_5x_Parser -FN_5x_Parser_E: ; DRV_EXTENDED - LD C,#0E - JP FN_5x_Parser -FN_5x_Parser_5: ; ATA_5x_READ - LD C,5 -FN_5x_Parser: - PUSH HL - LD H,A - AND #F0 - OR C - ; тут в A номер УСТРОЙСТВА + НОМЕР ФУНКЦИИ - LD L,A - LD A,H - LD H,high TAB_5xFNS - LD C,(HL) - INC H - LD H,(HL) - LD L,C - EX (SP),HL - RET +FN_5x_Parser_1: LD C,#01 ; ATA_5x_RESET + JR FN_5x_Parser +FN_5x_Parser_2: LD C,#02 ; ATA_5x_LONG_READ + JR FN_5x_Parser +FN_5x_Parser_3: LD C,#03 ; ATA_5x_LONG_WRITE + JR FN_5x_Parser +FN_5x_Parser_4: LD C,#04 ; ATA_5x_VERIFY + JR FN_5x_Parser +FN_5x_Parser_6: LD C,#06 ; ATA_5x_WRITE + JR FN_5x_Parser +FN_5x_Parser_7: LD C,#07 ; ATA_5x_DETECT + JR FN_5x_Parser +FN_5x_Parser_8: LD C,#08 ; ATA_5x_GET_PAR + JR FN_5x_Parser +FN_5x_Parser_9: LD C,#09 ; ATA_5x_SET_PAR + JR FN_5x_Parser +FN_5x_Parser_E: LD C,#0E ; DRV_EXTENDED + JR FN_5x_Parser +FN_5x_Parser_5: LD C,5 ; ATA_5x_READ +FN_5x_Parser: PUSH HL + LD H,A + AND #F0 + OR C + ; тут в A номер УСТРОЙСТВА + НОМЕР ФУНКЦИИ + LD L,A + LD A,H + LD H,high TAB_5xFNS + LD C,(HL) + INC H + LD H,(HL) + LD L,C + EX (SP),HL + RET ; Вход в функции БИОС из TR-DOS EXP_FNS:; отключаем запись в экран спектрума diff --git a/src/bios/exp/EXP.asm b/src/bios/exp/EXP.asm index 406f2c1..748eff1 100644 --- a/src/bios/exp/EXP.asm +++ b/src/bios/exp/EXP.asm @@ -767,7 +767,7 @@ POST_5_OK: ; Don't use IY before this point if it`s normal booting!!! LD IX,0 XOR A - ADD IX,SP ; восстановить значение переданное загрузчиком конфы (если старт после ресета) + ADD IX,SP ; восстановить значение переданное загрузчиком конфы (если старт после ресета) ; В этом месте у нас IX:IY из Loader.asm ; Дотащили до сюда метку от лоадера ;[x] 31/12/2023 подстраховка от недоутечки памяти @@ -788,7 +788,7 @@ POST_5_OK: JR NZ,.no_conf_reload LD A,#80 .no_conf_reload: - LD R,A ; reg R bit7 - признак работы лоадера + LD R,A ; reg R bit7 - признак запуска с отработкой лоадера конфы ; ; на всякий случай LD HL,ACEX.Config_ID.Sp2000 @@ -881,24 +881,24 @@ No_Reset_handlers: ;-----------------------------------------------------------------------; MODULE Prepare_For_Setup -Set_ALL_Mode: LD A,Port_All_Mode.DEFAULT - LD BC,Port_All_Mode - OUT (C),A +Set_ALL_Mode: LD A,Port_All_Mode.DEFAULT + LD BC,Port_All_Mode + OUT (C),A Set_Default_Screen: - CALL FN_SYNC.INT_DEF ; set default int - ld a,128+4 ; !HARDCODE - CALL FN_SYNC ; set default vsync -Setup_to_RAM: LD HL,Setup_Starter.Start - LD DE,COMPILE_ADDR.SETUP_STARTER - LD BC,Setup_Starter.Size + CALL FN_SYNC.INT_DEF ; set default int + LD A,128+4 ; !HARDCODE + CALL FN_SYNC ; set default vsync +Setup_to_RAM: LD HL,Setup_Starter.Start + LD DE,COMPILE_ADDR.SETUP_STARTER + LD BC,Setup_Starter.Size LDIR ; на стек кладётся адрес возврата и дальше тащится всякими костылями, чтоб вернуться назад - CALL Setup_Starter.Exec ; #C000 + CALL Setup_Starter.Exec ; #C000 ;JP PrepareToZX ENDMODULE -PrepareToZX: ; Setup HDD drives for ZX Spectrum mode +;PrepareToZX: ; Setup HDD drives for ZX Spectrum mode ; DI ; LD D,CMOS_CELL.TRDOSmount ; CALL CMOS_RD @@ -1052,8 +1052,8 @@ PORTS_INIT: OUT (C),A ; глушим ковокс XOR A - OUT (CBL.SYS_PORT),A - LD BC,CBL.OUT + OUT (SP_SND.CBL.SYS_PORT),A + LD BC,SP_SND.CBL.OUT LD A,#80 .CBL_MUTE: OUT (C),A DJNZ .CBL_MUTE @@ -1556,7 +1556,7 @@ BEEP: LD A,#10 JR NZ,BEEP RET ; -.beep_loop: OUT (ZX_Beeper),A +.beep_loop: OUT (SP_SND.Beeper),A LD B,D LD C,E ; diff --git a/src/bios/exp/EXTENDED/IDE/ATAPI_DRV.ASM b/src/bios/exp/EXTENDED/IDE/ATAPI_DRV.ASM index 1c209ae..40ca74d 100644 --- a/src/bios/exp/EXTENDED/IDE/ATAPI_DRV.ASM +++ b/src/bios/exp/EXTENDED/IDE/ATAPI_DRV.ASM @@ -181,7 +181,7 @@ ATAPI_5x_READ: ;PUSH IY ; !FIXIT EX AF,AF' IN A,(SLOT3) EX AF,AF' - JP ATAPI_5x_LONG_READ.main + JR ATAPI_5x_LONG_READ.main ;[]================================================================[#52] ;Function: Long Read Sectors ; A - Disk @@ -198,17 +198,19 @@ ATAPI_5x_LONG_READ: ; ;PUSH IY ; !FIXIT зачем? LD C,1 ; признак long -.main: SAFE_PORTY_2 - PUSH BC - PUSH IX - PUSH HL +.main: EX AF,AF' + AND A ;read + EX AF,AF' + JR ATAPI_BEGIN_RW ; - EX AF,AF' - AND A ;read - EX AF,AF' - CALL RW_ATAPI_SECTORs - ; [ ] sector size. media changed - JP ATA_5x_LONG_READ.shared + ; SAFE_PORTY_2 + ; PUSH BC + ; PUSH IX + ; PUSH HL + ; ; + ; CALL RW_ATAPI_SECTORs + ; ; [ ] sector size. media changed + ; JP ATA_5x_LONG_READ.shared ; JP NC,ATA_5x_LONG_READ.shared ; CP BIOS.Error.UnitAttention ; JR Z,ATAPI_MEDIA_ERROR @@ -278,6 +280,15 @@ RW_ATAPI_SECTORs: ;[]===========================================================[#52, #55] +ATAPI_BEGIN_RW: SAFE_PORTY_2 + PUSH BC + PUSH IX + PUSH HL + ; + CALL RW_ATAPI_SECTORs + ; + JP ATA_5x_LONG_READ.shared + ;[]================================================================[#56] ;Function: Write Sectors ; A - Disk @@ -289,11 +300,14 @@ RW_ATAPI_SECTORs: ; DE - Address + (Sector counter * Size sector) ;WRITE SECTOR(S) ATAPI_5x_WRITE: ;PUSH IY ; !FIXIT зачем? - LD C,0 ; признак short + ; проба бага + LD C,0 ; признак short + ;LD C,1 ; признак long + ; EX AF,AF' IN A,(SLOT3) EX AF,AF' - JP ATAPI_5x_LONG_WRITE.main + JR ATAPI_5x_LONG_WRITE.main ;[]================================================================[#53] ;Function: Long Write Sectors ; A - Disk @@ -310,17 +324,19 @@ ATAPI_5x_LONG_WRITE: ; ;PUSH IY ; !FIXIT зачем? LD C,1 ; признак long -.main: SAFE_PORTY_2 - PUSH BC - PUSH IX - PUSH HL +.main: EX AF,AF' + SCF ;write + EX AF,AF' + JR ATAPI_BEGIN_RW ; - EX AF,AF' - SCF ;write - EX AF,AF' - CALL RW_ATAPI_SECTORs - ; - JP ATA_5x_LONG_READ.shared + ; SAFE_PORTY_2 + ; PUSH BC + ; PUSH IX + ; PUSH HL + ; ; + ; CALL RW_ATAPI_SECTORs + ; ; + ; JP ATA_5x_LONG_READ.shared ;[]================================================================[#57] ;Function: Detect Disk @@ -607,9 +623,10 @@ EXEC_PACKET_COMMAND: ; POP BC OUT (C),B - ; - LD B,#80 -.pause2: DJNZ .pause2 + ; pause + LD B,0 + DJNZ $ + ; DJNZ $ ; EX AF,AF' LD XH,A ; страница для R/W_LONG @@ -617,7 +634,9 @@ EXEC_PACKET_COMMAND: EX AF,AF' EX DE,HL ; -.AP_LOOP: CALL ATAPI_CHECK_DRV +.AP_LOOP: ;LD B,128 + ;DJNZ $ + CALL ATAPI_CHECK_DRV JP C,.error;_APLOOP RET Z ;====== IF DATA REQUEST ===============================================; @@ -626,23 +645,6 @@ EXEC_PACKET_COMMAND: ; LD A,XH OUT (SLOT3),A - ; - ;LD BC,IDE.Read.ByteCountLow - ;IN E,(C) - ;INC C ;LD BC,IDE.Read.ByteCountHigh - ;IN D,(C) ;TRANSFER BLOCK SIZE - ;; - ;LD A,D - ;OR E - ;RET Z ;BLOCK = 0 - ;; уменьшаем счётчик загружаемых байтов в 2 раза. Читаем по 2 байта - ;SRL D - ;RR E - ;; - ;LD BC,IDE.Read.InterruptReason - ;IN A,(C) - ;AND IDE.InterruptReasonByte.IO - ;LD BC,IDE.Read.Data CALL ATAPI_PREPARE_RW RET NC JR Z,.WRITE_DATA @@ -688,24 +690,7 @@ ATAPI_IdlePasses: JP C,EXEC_PACKET_COMMAND.error JP Z,EXEC_PACKET_COMMAND.error_fail ; -.Enter: ;LD BC,IDE.Read.ByteCountLow - ;IN E,(C) - ;INC C ;LD BC,IDE.Read.ByteCountHigh - ;IN D,(C) ;TRANSFER BLOCK SIZE - ;; - ;LD A,D - ;OR E - ;RET Z ;BLOCK = 0 - ;; - ;; уменьшаем счётчик загружаемых байтов в 2 раза. Читаем по 2 байта - ;SRL D - ;RR E - ;; - ;LD BC,IDE.Read.InterruptReason - ;IN A,(C) - ;AND IDE.InterruptReasonByte.IO - ;LD BC,IDE.Read.Data - CALL ATAPI_PREPARE_RW +.Enter: CALL ATAPI_PREPARE_RW RET NC JR Z,.write_data ; @@ -737,6 +722,7 @@ ATAPI_IdlePasses: ATAPI_CHECK_DRV: ;EX DE,HL EXX + ;CALL .zeroWait CALL ATAPI_WAITPRT EXX ; ZF=1 @@ -764,9 +750,25 @@ ATAPI_CHECK_DRV: JP Z,ATAPI_MEDIA_ERROR CP BIOS.Error.ATAPI.UnitAttention JP Z,ATAPI_MEDIA_ERROR + ; + ;CP BIOS.Error.ATAPI.IllegalRequest + ;RET Z + ; SCF RET ; +; .zeroWait: ;LD B,2 +; LD HL,#800 +; .loop: LD A,high IDE.Read.Status +; IN A,(low IDE.Read.Status) +; AND A +; RET NZ +; DEC HL +; LD A,H +; OR L +; JR NZ,.loop +; ;DJNZ .loop +; RET ATAPI_PREPARE_RW: LD BC,IDE.Read.ByteCountLow @@ -836,9 +838,9 @@ ATAPI_GET_ERROR_REG: ; !!! некоторые функции надеются, что на выходе всегда ZF ; не должна трогать рег. C ATAPI_WAITPRT: LD DE,256*IDE.CtrlByte.Busy + 0 -.Custom: LD B,100 +.Custom: LD B,6 ; 3 = общая задержка около секунды LD HL,#0000 - ; + ; 4 128 768 .LOOP: LD A,high IDE.Read.Status IN A,(low IDE.Read.Status) CP #FF @@ -852,13 +854,59 @@ ATAPI_WAITPRT: LD DE,256*IDE.CtrlByte.Busy + 0 LD A,H OR L JR NZ,.LOOP + ; + ; LD A,high IDE.Read.Status + ; IN A,(low IDE.Read.Status) + ; CP #FF + ; SCF + ; RET Z + ; + ; 1 392 512 256 DJNZ .LOOP + ; + ; LD A,high IDE.Read.Status + ; IN A,(low IDE.Read.Status) + ; INC A ;CP #FF + ; SCF + ; RET Z + ; LD A,BIOS.Error.Busy -.error: SCF + RET + ; +.error: SCF RET ;----------------------------------------------------------------------; +;----------------------------------------------------------------------; +; D - MASK, E - PATTERN +; !!! некоторые функции надеются, что на выходе всегда ZF +; не должна трогать рег. C +; ATAPI_WAITPRT: LD DE,256*IDE.CtrlByte.Busy + 0 +; .Custom: +; .LOOP: LD A,high IDE.Read.Status +; IN A,(low IDE.Read.Status) +; CP #FF +; JR Z,.error +; ; +; AND D +; CP E +; RET Z +; JR .LOOP +; ; +; ; LD A,high IDE.Read.Status +; ; IN A,(low IDE.Read.Status) +; ; INC A ;CP #FF +; ; SCF +; ; RET Z +; ; ; +; ; LD A,BIOS.Error.Busy +; ; RET +; ; +; .error: SCF +; RET +;----------------------------------------------------------------------; + ;----------------------------------------------------------------------; ; DE - buffer ATAPI_READ_CAPACITY_DATA: diff --git a/src/bios/exp/FUNC_RAM_ROM_DRV.ASM b/src/bios/exp/FUNC_RAM_ROM_DRV.ASM index ac1e3d2..304df85 100644 --- a/src/bios/exp/FUNC_RAM_ROM_DRV.ASM +++ b/src/bios/exp/FUNC_RAM_ROM_DRV.ASM @@ -119,7 +119,7 @@ RESERVED_PAGES: ;[x] free zx pages! DB #58,#59,#5A,#5B,#5C,#5D,#5E,#5F ; ;DB MODE_PAGE ; ????? - DB CBL.BUFFER_PAGE ; Page for CBL audio + DB SP_SND.CBL.BUFFER_PAGE ; Page for CBL audio DB SYS_PAGE ; Page for system (BIOS) variables DB #FF ; End of the block ; diff --git a/src/bios/exp/FUNC_SERVICE.asm b/src/bios/exp/FUNC_SERVICE.asm index 4116d74..a766644 100644 --- a/src/bios/exp/FUNC_SERVICE.asm +++ b/src/bios/exp/FUNC_SERVICE.asm @@ -72,7 +72,7 @@ RST_CONF: LD A,#80 JR Z,.YES_CBL XOR A -.YES_CBL: LD BC,CBL.SYS_PORT +.YES_CBL: LD BC,SP_SND.CBL.SYS_PORT OUT (C),A ; LD A,E ; config-byte diff --git a/src/bios/exp/FUNC_SYS.ASM b/src/bios/exp/FUNC_SYS.ASM index 04643f5..1a66800 100644 --- a/src/bios/exp/FUNC_SYS.ASM +++ b/src/bios/exp/FUNC_SYS.ASM @@ -163,12 +163,10 @@ EMM.CheckColdInit: INC HL INC DE DJNZ .loop - ; Disable user IM address in SYS_PAGE XOR A LD (SYS_PAGE.INT_ID - #4000),A ; - EX AF,AF' OUT (SLOT2),A RET diff --git a/src/bios/rom/SETUP/AUTOIDE.asm b/src/bios/rom/SETUP/AUTOIDE.asm index 10b58de..c6a76d2 100644 --- a/src/bios/rom/SETUP/AUTOIDE.asm +++ b/src/bios/rom/SETUP/AUTOIDE.asm @@ -397,7 +397,8 @@ SETUP_FROM_CMOS: ; RET /////////////////////////////////////////////////////////////////////[^] /////////////////////////////////////////////////////////////////////[v] -IDESPEC: IN A,(SLOT3) +PARSE_IdentifyDevice: + IN A,(SLOT3) EX AF,AF' LD A,SYS_PAGE OUT (SLOT3),A @@ -440,11 +441,7 @@ IDESPEC: IN A,(SLOT3) ; LD A,(IDENTIFY_DEVICE_BUFFER.NumSectorsPerTrack) LD (IY+IDE.HDD_INIT_TABLE.SectorsPerTrack),A - IF IDE_Optimization - LD B,high IDE.Write.Counter - ELSE - LD BC,IDE.Write.Counter - ENDIF + LD B,high IDE.Write.Counter OUT (C),A LD A,IDE.CMD.ATA.InitializeDeviceParameters CALL IDE_CMD @@ -460,7 +457,8 @@ IDESPEC: IN A,(SLOT3) ; LD (IY+IDE.HDD_INIT_TABLE.SectorsPerCylinderLow),L LD (IY+IDE.HDD_INIT_TABLE.SectorsPerCylinderHigh),H -.END: ; [x] save hdd parameters to cmos for "setup" in settings +.END: RES 1,(IY + IDE.HDD_INIT_TABLE.MediaParameters) ; [ ] removable media + ; [x] save hdd parameters to cmos for "setup" in settings LD A,(IY+IDE.HDD_INIT_TABLE.DRV_Flags) ; for save to cmos in GETPARM ; EX AF,AF' @@ -474,19 +472,22 @@ IDESPEC: IN A,(SLOT3) LD HL,ICHANEL OR (HL) LD (IY+IDE.HDD_INIT_TABLE.DRV_Flags),A + ; + ; ; на всякий случай LD (IY+IDE.HDD_INIT_TABLE.MediaParameters),%0000'0001 LD B,100 ; счётчик попыток (1 попытка - 1 HALT) .get_error_loop: PUSH BC ;LD HL,ATAPI_CMD_PACKET.TEST_UNIT_READY ;CALL EXEC_PACKET_COMMAND.start - CALL EXEC_TEST_CMD + CALL EXEC_TEST_CMD POP BC JR NC,.s_size ; - RES 1,(IY + IDE.HDD_INIT_TABLE.MediaParameters) ; [ ] removable media CP BIOS.Error.ATAPI.UnitAttention - JR Z,IDESPEC.END + JR Z,PARSE_IdentifyDevice.END ;!TEST ;!FIXIT ZIP bug + ;JR Z,.TEST_SET + ; HALT DJNZ .get_error_loop @@ -508,9 +509,59 @@ IDESPEC: IN A,(SLOT3) ; .No_Media: LD (IY+IDE.HDD_INIT_TABLE.SectorSize),H LD (IY+IDE.HDD_INIT_TABLE.SectorSize + 1),L - RES 1,(IY + IDE.HDD_INIT_TABLE.MediaParameters) ; [ ] removable media ; - JR IDESPEC.END + JR PARSE_IdentifyDevice.END ;!TEST ;!FIXIT ZIP bug + ; +/* +;====; ;!TEST ;!FIXIT ZIP bug +.TEST_SET: LD HL,.MODE_SENSE + LD DE,SYS_PAGE.MS_BPB ; просто нужен был буфер + LD BC,BIOS.DRV_EXTENDED.ATAPI_Custom_PCMD + CALL ATAPI_CUSTOM_CMD + JR NC,.OK_DONE + ; + LD A,COLORS.CGA.BORDER.CYAN + OUT (BorderColor),A + JR .go_exit + ; +.OK_DONE: LD A,(SYS_PAGE.MS_BPB + 2) + AND A + JR NZ,.go_exit + ; + LD (SYS_PAGE.MS_BPB + 10),A + LD HL,(SYS_PAGE.MS_BPB) + LD (.MODE_SELECT.Size),HL + LD HL,.MODE_SELECT + LD DE,SYS_PAGE.MS_BPB ; просто нужен был буфер + LD BC,BIOS.DRV_EXTENDED.ATAPI_Custom_PCMD + CALL ATAPI_CUSTOM_CMD + JR NC,.go_exit + ; + LD A,COLORS.CGA.BORDER.GREEN + OUT (BorderColor),A + ;JR .go_exit + ; +.go_exit: AND A + JP PARSE_IdentifyDevice.END + ; + ; + +.MODE_SENSE: BYTE #5A + BYTE #08 +.MODE_SENSE.Page: BYTE #08 ;bit7..6 - Page Control, bit5..0 - Page Code + BLOCK 4,0 + BYTE #02,#00 + BLOCK 3,0 + ; +.MODE_SELECT: BYTE #55 + BYTE #08 +.MODE_SELECT.Page: BYTE #08 ;bit7..6 - Page Control, bit5..0 - Page Code + BLOCK 4,0 +.MODE_SELECT.Size: BYTE #02,#00 + BLOCK 3,0 + ; +;====; ;!TEST +*/ ; /////////////////////////////////////////////////////////////////////[^] @@ -761,7 +812,7 @@ GETPARAM: LD HL,PAUSES.WAIT.IDE LD HL,IDENTIFY_DEVICE_BUFFER INIR INIR - CALL IDESPEC + CALL PARSE_IdentifyDevice ; [x] save hdd parameters to cmos for "setup" in settings CALL SaveToCMOS AND A diff --git a/src/bios/rom/SETUP/IM2_INT.asm b/src/bios/rom/SETUP/IM2_INT.asm index 512791a..f923a6c 100644 --- a/src/bios/rom/SETUP/IM2_INT.asm +++ b/src/bios/rom/SETUP/IM2_INT.asm @@ -17,32 +17,38 @@ INT_POINTER: WORD 0 ENDIF ENDIF -INT_HANDLER: - PUSH AF - EX AF,AF' - PUSH AF - PUSH BC - PUSH DE - PUSH HL - EXX - PUSH BC - PUSH DE - PUSH HL - PUSH IX - PUSH IY - CALL KEYSCAN - POP IY - POP IX - POP HL - POP DE - POP BC - EXX - POP HL - POP DE - POP BC - POP AF - EX AF,AF' - POP AF - EI - RETI +INT_HANDLER: PUSH AF + EX AF,AF' + PUSH AF + PUSH BC + PUSH DE + PUSH HL + EXX + PUSH BC + PUSH DE + PUSH HL + PUSH IX + PUSH IY + CALL KEYSCAN + ; + IF STARTUP_SND + SCF +.sndSwitch: CCF ; SCF/CCF + CALL C,STARTUP_SOUND + ENDIF + ; + POP IY + POP IX + POP HL + POP DE + POP BC + EXX + POP HL + POP DE + POP BC + POP AF + EX AF,AF' + POP AF + EI + RETI ; \ No newline at end of file diff --git a/src/bios/rom/SETUP/MAIN.asm b/src/bios/rom/SETUP/MAIN.asm index 314eac8..c15361e 100644 --- a/src/bios/rom/SETUP/MAIN.asm +++ b/src/bios/rom/SETUP/MAIN.asm @@ -554,15 +554,17 @@ RESTART_ID: .str: DZ "RESTART" .size EQU $ - RESTART_ID.str -Start_again: - ld sp,STACK-2 -START: - DI - PUSH AF - XOR A - LD (ERRSUM),A - LD (ERRSUM.ErrDateTime),A +Start_again: LD SP,STACK-2 +START: DI + PUSH AF + XOR A + LD (ERRSUM),A + LD (ERRSUM.ErrDateTime),A + ; + LD A,R ; reg R bit7 - признак запуска с отработкой лоадера конфы (из SET_CONFIG_ID) + LD (LOGOTYPE.playSnd),A + ; ; LD C,#97 ; RST_to_BIOS_18 ; XOR A @@ -1598,7 +1600,9 @@ ElementsBuffer: .DownCenter: BYTE "┴" ; DC - DownCenter .Size EQU $-ElementsBuffer ; - + IF STARTUP_SND + INCLUDE 'startup_sound.asm' + ENDIF INCLUDE 'VIDEO_IO.asm' INCLUDE 'AUTOIDE.asm' INCLUDE 'SETTINGS.asm' diff --git a/src/bios/rom/SETUP/VIDEO_IO.asm b/src/bios/rom/SETUP/VIDEO_IO.asm index be66ec6..e20e038 100644 --- a/src/bios/rom/SETUP/VIDEO_IO.asm +++ b/src/bios/rom/SETUP/VIDEO_IO.asm @@ -290,22 +290,33 @@ PRSYM: LD B,1 //////////////////// LOGO \\\\\\\\\\\\\\\\\\\\ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; LOGOTYPE: CALL SHOW_LOGO + ; + IF STARTUP_SND +.playSnd+1: LD A,#80 + RLA + JR NC,.noSound + ; + LD A,#37 ; opcode SCF, play sound on + LD (INT_HANDLER.sndSwitch),A +.noSound: ; + ENDIF + ; LD BC,CMOS_CELL.BootUpParams.Mask.StartDelay CALL GET_CMOS_VALUE OR A - JR Z,.EASYDLY ; Delay average + JR Z,.MinDelay DEC A - JR Z,.SKIPDLY ; Delay disabled + JR Z,.AverageDelay ; Delay enabled LD B,LOGO_DELAY_NORM .loop EI push bc HALT - CALL go_setup + CALL go_setup pop bc DJNZ .loop ; Delay average -.SKIPDLY: LD B,LOGO_DELAY_MAX +.AverageDelay: LD B,LOGO_DELAY_MAX .MMA: PUSH BC EI HALT @@ -323,12 +334,17 @@ LOGOTYPE: CALL SHOW_LOGO DI CALL WIN_OPEN.SCR1 ; + IF STARTUP_SND + LD A,#3F ; opcode CCF, play sound off + LD (INT_HANDLER.sndSwitch),A + ENDIF + ; LD DE,0 LD HL,#0920 ;!HARDCODE LOGOTYPE SIZE LD B,7 JP LP_CLS_WIN ; Delay disabled -.EASYDLY: LD B,LOGO_DELAY_MIN +.MinDelay: LD B,LOGO_DELAY_MIN .loop2: EI HALT DJNZ .loop2 diff --git a/src/bios/rom/SETUP/startup_sound.asm b/src/bios/rom/SETUP/startup_sound.asm new file mode 100644 index 0000000..f4417a0 --- /dev/null +++ b/src/bios/rom/SETUP/startup_sound.asm @@ -0,0 +1,215 @@ +; CODE BY Александр -=TmK deMarche=- +; play frame +; use: af,hl,de,bc 251 +STARTUP_SOUND: LD HL,.BYTE_POS + LD A,(HL) + LD C,SP_SND.AY + CP .toneDataSize + 1 + JR C,.play + ;-- mus off + XOR A + LD E,A +.offLp: LD B,high SP_SND.AY.CTRL + OUT (C),A + LD B,high SP_SND.AY.DATA + OUT (C),E + INC A + CP 15 + JR NZ,.offLp + RET + ; +.play: LD DE,#0700+56 + LD B,high SP_SND.AY.CTRL + OUT (C),D + LD B,high SP_SND.AY.DATA + OUT (C),E + CP 33 + JR NC,.playVol + AND 3 + JR NZ,.playVol + ;--- play tone + LD HL,(.WORD_TONE) + ;A=0 +.playToneLp: LD B,high SP_SND.AY.CTRL + OUT (C),A + LD B,high SP_SND.AY.DATA + OUTI + INC A + CP 6 + JR NZ,.playToneLp + ; + LD (.WORD_TONE),HL +.playVol: LD HL,(.WORD_VOL) + LD A,8 + LD E,(HL) + INC HL +.playVolLp: LD B,high SP_SND.AY.CTRL + OUT (C),A + LD B,high SP_SND.AY.DATA + OUT (C),E + INC A + CP 11 + JR NZ,.playVolLp + ; + LD (.WORD_VOL),HL + LD HL,.BYTE_POS + INC (HL) + RET +;----------------------------------------------------------------------- +.BYTE_POS: DB 0 +.WORD_VOL: DW .volData +.WORD_TONE: DW .toneData +;----------------------------------------------------------------------- +.volData: ;DB 11,10,08,06,08,07,06,05 + ;DB 12,11,09,07,09,08,07,06 + DB 13,12,10,08,09,08,07,06 + DB 13,12,10,08,09,08,07,06 + DB 13,12,10,08,09,08,07,06 + DB 12,12,10,08,07,06,05,04 + DB 07,06,05,04,03,02,01,00 + DB 05,04,03,02,01,00,00,00 + DB 04,03,02,02,01,00,00,00 + DB 02,02,01,01,00,00,00,00 + +.toneData: DB 68,3,136,6,162,1 + DB 136,6,136,6,68,3 + DB 57,1,229,4,114,2 + ;DB 68,3,229,4,162,1 + ;DB 46,2,92,4,23,1 + ;DB 57,1,92,4,114,2 + ;DB 209,0,68,3,162,1 + ;DB 46,2,68,3,23,1 + ;DB 209,0,68,3,162,1 +.toneDataSize EQU $ - .toneData + +.codeEnd: DISPLAY "StartUp Sound size: ",/A,.codeEnd - STARTUP_SOUND + +; savesna "startup_sound.sna", #8000 + + + +/* + + + MODULE STARTUP_SOUND + DEFINE SND_VARIANT 2 ; 0, 1, 2 + + IF SND_VARIANT == 0 + DEFINE SND_Const1 15 + DEFINE SND_Const2 7 + ; + ELSEIF SND_VARIANT == 1 + DEFINE SND_Const1 15 + DEFINE SND_Const2 7 + ; + ELSEIF SND_VARIANT == 2 + DEFINE SND_Const1 14 + DEFINE SND_Const2 6 + ENDIF + +codeBegin: LD A,SND_Const1 + LD HL,.volData + LD DE,.sndData +.lp: CALL .snd + CALL .vol + CALL .vol + CALL .vol + DEC A + JP NZ,.lp + ;-- + LD DE,#07ff + LD B,E + OUT (C),D + LD B,#bf + OUT (C),E + RET +;---------------- +.snd: CALL .vol + CP SND_Const2 + RET C + ; +.sndEnd: EX AF,AF + EX DE,HL + PUSH DE + XOR A +.sndLp: LD B,#ff + OUT (C),A + LD B,#bf + OUTI + INC A + CP 6 + JR NZ,.sndLp + POP DE + EX DE,HL + EX AF,AF + RET +;---------------- +.vol: ;EI + ;HALT + EX AF,AF + PUSH DE + LD BC,#fffd + LD DE,#0700+56 + OUT (C),D + LD B,#bf + OUT (C),E + LD A,8 + LD E,(HL) + INC HL +.volLp: LD B,#ff + OUT (C),A + LD B,#bf + OUT (C),E + INC A + CP 11 + JR NZ,.volLp + POP DE + EX AF,AF + RET +;---------------- +.volData: + IF SND_VARIANT == 0 + DB 13,12,10,08,09,08,07,06 + DB 13,12,10,08,09,08,07,06 + DB 13,12,10,08,09,08,07,06 + DB 12,12,10,08,07,06,05,04 + DB 07,06,05,04,03,02,01,00 + DB 05,04,03,02,01,00,00,00 + DB 04,03,02,02,01,00,00,00 + DB 02,02,01,01,00,00,00,00 + ; + ELSEIF SND_VARIANT == 1 + DB 11,10,08,06,08,07,06,05 + DB 12,11,09,07,09,08,07,06 + DB 13,12,10,08,09,08,07,06 + DB 13,12,10,08,07,06,05,04 + DB 08,07,06,05,04,03,02,01 + DB 06,05,04,03,02,01,00,00 + DB 04,04,03,02,01,00,00,00 + DB 02,02,01,01,00,00,00,00 + ; + ELSEIF SND_VARIANT == 2 + DB 15,14,13,10,10,09,09,07 + DB 15,14,13,10,10,09,09,07 + DB 15,14,13,10,10,09,09,07 + DB 15,14,13,10,07,06,05,04 + DB 08,07,06,05,04,03,02,01 + DB 06,05,04,03,02,01,00,00 + DB 04,03,02,01,00,00,00,00 + ENDIF + + +.sndData: DB 68,3,136,6,162,1 + DB 136,6,136,6,68,3 + DB 57,1,229,4,114,2 + DB 68,3,229,4,162,1 + DB 46,2,92,4,23,1 + DB 57,1,92,4,114,2 + DB 209,0,68,3,162,1 + DB 46,2,68,3,23,1 + DB 209,0,68,3,162,1 + +codeEnd: DISPLAY "StartUp Sound size: ",/A,codeEnd-codeBegin + + ENDMODULE +*/ \ No newline at end of file diff --git a/src/bios/shared/DEFINES.INC b/src/bios/shared/DEFINES.INC index a8d2ccc..50529af 100644 --- a/src/bios/shared/DEFINES.INC +++ b/src/bios/shared/DEFINES.INC @@ -17,6 +17,7 @@ BETA_RC EQU 2 ; DEFINE LOGO_DELAY_NORM 100 ; DEFINE LOGO_DELAY_MAX 130 ; ;----------------------------[ TEST ]---------------------------; + DEFINE STARTUP_SND 1 ; DEFINE ERROR_POST_5 0 ; виснуть на ошибке в POST 5 DEFINE TEST_INT 1 ; Тестовый обработчик пользовательского INT DEFINE NEW_FEATURE 0 ; !TODO пункты в сетап diff --git a/src/bios/shared/RECOVERY.IMG b/src/bios/shared/RECOVERY.IMG index eee92388d9b1cb2375aec155d0d71d67275dffd0..148ed49daff8de911931a4565e18f4ad9d200884 100644 GIT binary patch delta 11131 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 TWlGY1Xc|gK?XMK0)p!0c*{VcJ