; LAST UPDATE: 15.07.2025 savelij include macros.a80 include fn_const.a80 include fn_macros.a80 include accel_sp.a80 include ports_sp.a80 include define_sp.a80 include errors_sp.a80 include macros_sp.a80 include dss_sp.a80 include bios_sp.a80 include vers.a80 DEBUG EQU 0 BUF_TOC EQU RESULT + 3000 HDR_FLX "-CDPL",,,FLXMODES.M_ADRORG PluginEntry: MAKEWINDOW WINSUBOBJ.STORE W_MAIN 78,79,484,72 W_FILL 4,2,464,10,COLORI.BLUE + COLORP.BLUE W_TEXT 8,4,COLORI.WHITE + COLORP.BLUE,"SHAOS CD-Player v\{CDVERS}" W_BUTTONTEXT 468,2,12,10,COLORP.HIGHGRAY,"x" W_BORDER 8,15,268,38 W_FILL 10,16,264,36,COLORI.BLACK W_BUTTON 282,15,116,18 W_BUTTON 402,15,36,18 W_BUTTON 442,15,36,18 W_BUTTON 282,35,36,18 W_BUTTON 322,35,36,18 W_BUTTON 362,35,36,18 W_BUTTON 402,35,36,18 W_BUTTON 442,35,36,18 W_HORIZLINE 2,56,480 W_END call JUMPS.ResFire CALL SHOW_BUTTON ; вывод иконок на кнопки IF DEBUG CALL DEBUG_TXTKEYS ; отладочный текст ENDIF call CDinit ; поиск Audio-CD и инит call BIGDIGITSALL plugin_loop: LD HL,FLAG BIT B_RDUPDATE,(HL) JR NZ,.L2 ; перечитываем текущее положение с учетом режимов SET B_RDUPDATE,(HL) BIT B_PAUSE,(HL) JR NZ,.L3 BIT B_TRAY,(HL) JR NZ,.L4 BIT B_PLAY,(HL) CALL NZ,RDSUBCHAN ; или читаем текущее время если трей закрыт и режим плей CALL UPDATE_CURRTRACK ; обновление строки для вывода .L4 LD HL,(APCMD.PLAY_MSF + 6) ; время конца диска LD DE,(RESULT + 9) ; текущее время AND A SBC HL,DE CALL Z,CDSTOP ; принудительный стоп если конец диска JR .L3 ; перерисовываем текущую позицию играния .L2 RES B_RDUPDATE,(HL) BIT B_TRAY,(HL) CALL Z,BIGDIGITSALL ; или выводим на экран ; основной цикл опроса управления .L3 ld ix,PluginMouseTab call JUMPS.TestCoords SPDSS DSSF.SCANKEY jr z,plugin_loop ld a,b or a jr nz,plugin_loop ld a,e CALL CHECKHOTKEYS ; проверка хоткеев по списку JR NC,plugin_loop .L1 cp 0x1B jr z,PluginExit cp 0x0D jr nz,plugin_loop PluginExit: CALL RESTORE_STATE WINDOWCLOSE or a ; cf = 0 ret ; hl - bitmap 32x16 for 16-color mode ; ix,iy - coords (320x256) show: di GETPORT WINSP.CPU0 PUSH AF GETPORT WINSP.Y_PORT PUSH AF SETPORT WINSP.CPU0,0x50 push ix pop de LD C,IYL ld b,16 .L1: ld a,c SETPORT WINSP.Y_PORT,,0 push de ACCEL ACCELCMD.SET_BUFFER ld a,16 ACCEL ACCELCMD.COPY ld a,(hl) ld (de),a ACCEL ACCELCMD.OFF ld de,16 add hl,de pop de inc c dec b jp nz,.L1 POP AF SETPORT WINSP.Y_PORT,,0 POP AF SETPORT WINSP.CPU0,,0 ei ret ; a - digit ; ix,iy - coords (320x256) showd: rlca ld e,0 ld d,a ld hl,digit0 add hl,de call show ld de,16 add iy,de jp show ; показ номера трека и времени проигрывания крупным шрифтом BIGDIGITSALL: LD HL,(Digits) LD (DigitsNone),HL ; копирование номера трека LD HL,FLAG BIT B_PAUSE,(HL) LD DE,Digits ; по умолчанию всегда цифры JR Z,.L3 ; счетчик для моргания в паузе LD A,PAUSEDIGITS .L4 EQU $-1 DEC A JR NZ,.L5 LD A,PAUSEDIGITS .L5 LD (.L4),A JR NZ,.L6 LD A,M_VIEWNONE XOR (HL) LD (HL),A .L6 BIT B_VIEWNONE,(HL) JR Z,.L3 LD DE,DigitsNone ; пустое время в режиме пауза ; печать текущего номера трека и времени .L3 EX DE,HL ; HL - адрес данных для вывода текщего трека/времени играния ld ix,46 ; X ld c,8 ; сколько символов рисовать .L2 ld iy,97 ; Y .L1: push bc push hl push iy ld a,(hl) call showd ld bc,16 add ix,bc pop iy pop hl pop bc inc hl dec c jp nz,.L1 ret CHANGEDISK: LD A,(CDDRIVE) SPBIOS BIOSF.DRV_RESET JR NC,.cont CP ERR_DRV.ATAPI_UnitAttention JR Z,.drv_change CP ERR_DRV.ATAPI_NotReady SCF RET NZ LD A,ERR_DSS.NOT_READY RET .drv_change: LD A,(CDDRIVE) CALL SAVE_MEDIA_CHANGED .cont: CALL INITDISK RET C AND A RET INITDISK: LD B,4 .CD_I_LP PUSH BC LD IX,0x0010 LD HL,0x0000 LD DE,RESULT LD A,(CDDRIVE) SPBIOS BIOSF.DRV_READ,1 POP BC JR NC,.CD_I_OK DJNZ .CD_I_LP .UNKCD LD A,ERR_DSS.UNKNOWN_FORMAT SCF RET .CD_I_OK LD HL,RESULT LD A,(HL) INC HL DEC A JR NZ,.UNKCD LD A,(HL) INC HL CP 'C' JR NZ,.UNKCD LD A,(HL) INC HL CP 'D' JR NZ,.UNKCD XOR A RET RESTORE_STATE: LD B,1 .set_par: EQU $-1 LD A,(CDDRIVE) SPBIOS BIOSF.DRV_SET_PAR RET SAVE_MEDIA_CHANGED: SPBIOS BIOSF.DRV_GET_PAR OR %00000010 LD B,A LD A,(RESTORE_STATE.set_par) OR B LD (RESTORE_STATE.set_par),A RET ; поиск CD-ROM и инициализация CDinit: LD B,0xC0 - 1 .loop: INC B LD A,B CP 0xC4 SCF JP Z,noCD PUSH BC SPBIOS BIOSF.DRV_DETECT POP BC JR NC,.found CP ERR_DRV.ATAPI_MediumError JR Z,.found CP ERR_DRV.ATAPI_UnitAttention JR NZ,.loop .found: LD A,B LD (CDDRIVE),A CALL yesCD0 .CLOSETRAY LD HL,APCMD.CLOSETRAY CALL SEND_PACKET CALL CHANGEDISK LD HL,FLAG RES B_TRAY,(HL) .UPDATE_TOC LD HL,RESULT+6 LD (HL),0xAA LD HL,APCMD.READTOC CALL SEND_PACKET LD HL,RESULT-2 LD B,0xFF LD DE,8 .L1 INC B ADD HL,DE LD A,(HL) CP 0xAA JR NZ,.L1 LD A,B LD (TRACKS),A ; формирование таблицы треков LD HL,RESULT + 4 + 5 LD A,(RESULT + 3) LD DE,BUF_TOC + 3 ; нулевого нет .L2 EX AF,AF' LDI LDI LDI LD A,5 ADD A,L LD L,A ADC A,H SUB L LD H,A EX AF,AF' DEC A JP NZ,.L2 LD DE,APCMD.PLAY_MSF + 6 ; конец диска LDI LDI LDI LD A,(TRACKS) LD HL,TXTTRACKS.DIGITS CALL A2HALFDEC LD A,'0' ADD A,(HL) LD (HL),A DEC HL LD A,'0' ADD A,(HL) LD (HL),A LD HL,TXTTRACKS LD DE,360 LD BC,140 LD A,COLORP.HIGHGRAY + COLORI.BLUE CALL JUMPS.PrnTxtLnIFF LD A,1 LD (CURRENT.TRACK),A ; обновление текущего номера трека и времени играния на экране UPDATE_CURRTRACK LD A,(CURRENT.TRACK) LD HL,Digits CALL A2HALFDEC LD A,(CURRENT.MINUTE) LD HL,Digits.MIN CALL A2HALFDEC LD A,(CURRENT.SECUND) LD HL,Digits.SEC ; конверсия числа для вывода на дисплей A2HALFDEC LD BC,10 .L1 INC B SUB C JR NC,.L1 DEC B ADD A,C LD (HL),B INC HL LD (HL),A RET IF DEBUG A2HEX PUSH AF AND %11110000 RRCA RRCA RRCA RRCA CALL .L2 LD B,A POP AF AND %00001111 .L2 ADD A,'0' CP '9'+1 RET C ADD A,7 RET ENDIF ; CD-ROM найден yesCD0: ld hl,msgY ld a,COLORP.HIGHGRAY + COLORI.BLUE jr CDprn ; CD-ROM не найден noCD: ld hl,msgN ld a,COLORP.HIGHGRAY + COLORI.RED CDprn: ld de,84 ld bc,140 JP JUMPS.PrnTxtLnIFF msgY DZ "CD-ROM is present" msgN DZ "CD-ROM is absent" TXTTRACKS DZ "Tracks: 00" ; количество треков на диске .DIGITS EQU $-3 ; рисование иконок на кнопках по табличке позиций SHOW_BUTTON LD HL,TABLBUTTONS .L1 LD E,(HL) INC HL LD D,(HL) INC HL LD A,D OR E RET Z PUSH DE LD E,(HL) INC HL LD D,(HL) INC HL LD IXH,D LD IXL,E LD E,(HL) INC HL LD D,(HL) INC HL LD IYH,D LD IYL,E EX (SP),HL CALL show POP HL JR .L1 IF DEBUG ; таблица подсказок на хоткеи DEBUG_TXTKEYS LD HL,DEBUGTABLKEYS .L1 LD E,(HL) INC HL LD D,(HL) INC HL LD A,D OR E RET Z PUSH DE LD E,(HL) INC HL LD D,(HL) INC HL LD C,(HL) INC HL LD B,(HL) INC HL EX (SP),HL LD A,COLORP.HIGHGRAY + COLORI.RED CALL JUMPS.PrnTxtLnIFF POP HL JR .L1 ENDIF ; проверка хоткеев по таблице CHECKHOTKEYS LD HL,TABLHOTKEYS .L1 LD B,(HL) INC B DEC B SCF RET Z INC HL LD E,(HL) INC HL LD D,(HL) INC HL CP B JR NZ,.L1 PUSH AF EX DE,HL CALL JP_HL POP AF AND A RET JP_HL JP (HL) ; чтение текущего состояния играния RDSUBCHAN LD HL,APCMD.RDSUBCHAN CALL SEND_PACKET LD A,(RESULT + 6) LD (CURRENT.TRACK),A LD HL,RESULT + 13 LD DE,CURRENT.MINUTE LDI LDI RET ; установка позиции для играния в пакете SETPOS_MSF EXX LD HL,(CURRENT.TRACK) LD H,0 LD E,L LD D,H ADD HL,HL ADD HL,DE LD DE,BUF_TOC ADD HL,DE LD DE,APCMD.PLAY_MSF + 3 LDI LDI LDI EXX RET ; перемотка назад REWIND LD A,(FLAG) BIT B_PAUSE,A RET NZ BIT B_PLAY,A RET Z ; только для режима плей CALL RDSUBCHAN LD HL,APCMD.PLAY_MSF + 3 LD DE,(RESULT + 9) LD A,D SUB PAUSE LD D,A JR NC,.L1 ADD A,60 LD D,A ; новые секунды DEC E ; новые минуты .L1 LD (HL),E ; минуты INC HL LD (HL),D ; секунды INC HL LD (HL),0 ; фрейм JR CDPLAY.L1 ; перемотка вперед FORWARD LD A,(FLAG) BIT B_PAUSE,A RET NZ BIT B_PLAY,A RET Z ; только для режима плей CALL RDSUBCHAN LD HL,APCMD.PLAY_MSF + 3 LD DE,(RESULT + 9) LD A,D ADD A,PAUSE LD D,A CP 60 JR C,REWIND.L1 SUB 60 LD D,A ; новые секунды INC E ; новые минуты JR REWIND.L1 ; предыдущий трек PREV_TRACK LD HL,CURRENT.TRACK LD A,(HL) DEC A RET Z DEC (HL) JR NEXT_TRACK.L1 ; следующий трек NEXT_TRACK LD HL,CURRENT.TRACK LD A,(TRACKS) CP (HL) RET Z INC (HL) .L1 LD HL,0 LD (CURRENT.MINUTE),HL CALL SETPOS_MSF ; установка позиции в пакете CALL UPDATE_CURRTRACK ; обновление строки трека и времени CALL BIGDIGITSALL ; рисование на экран строки трека и времени LD HL,FLAG BIT B_PLAY,(HL) ; режим плей? RET Z ; выход если нет BIT B_PAUSE,(HL) ; режим паузы? RET NZ ; выход если да JR CDPLAY.L1 ; иначе запускаем плей для нового трека ; играть трек CDPLAY: LD HL,FLAG BIT B_PAUSE,(HL) JR NZ,CDPAUSE.PAUSEON ; если из режима пауза, сначала сброс режима BIT B_PLAY,(HL) RET NZ ; если из режима плей, то выходим .L2 SET B_PLAY,(HL) CALL SETPOS_MSF .L1 LD HL,APCMD.PLAY_MSF JP SEND_PACKET CDPAUSE LD HL,FLAG BIT B_PLAY,(HL) RET Z ; если стоп то паузу игнорим BIT B_PAUSE,(HL) JR NZ,.PAUSEON ; включение режима пауза SET B_PAUSE,(HL) CALL RDSUBCHAN LD HL,(RESULT + 9) LD (CURRENT.PAUSE_POS),HL LD HL,APCMD.PAUSE JP SEND_PACKET ; выключение режима пауза .PAUSEON RES B_PAUSE,(HL) RES B_VIEWNONE,(HL) BIT B_PAUSENEW,(HL) RES B_PAUSENEW,(HL) JP Z,CDPLAY.L1 LD HL,(CURRENT.PAUSE_POS) LD (APCMD.PLAY_MSF + 3),HL JR CDPLAY.L1 ; полная остановка CDSTOP: LD HL,FLAG RES B_PLAY,(HL) RES B_PAUSE,(HL) RES B_VIEWNONE,(HL) LD A,1 LD (CURRENT.TRACK),A LD HL,0 LD (CURRENT.MINUTE),HL CALL SETPOS_MSF CALL UPDATE_CURRTRACK CALL BIGDIGITSALL ; команда стоп CD_APSTOP LD HL,APCMD.STOP ; посылка ATAPI пакета SEND_PACKET LD DE,RESULT LD A,0 CDDRIVE EQU $-1 SPBIOS BIOSF.DRV_EXTENDED,DRV_EXTENDED.ATAPI_Custom_PCMD RET ; открытие/закрытие трея CDEJECT: CALL CDSTOP LD HL,FLAG BIT B_TRAY,(HL) SET B_TRAY,(HL) JP NZ,CDinit.CLOSETRAY ; закрытие и реинит ; иначе открытие трея LD HL,APCMD.OPENTRAY CALL SEND_PACKET LD HL,BUF_TOC LD DE,BUF_TOC + 1 LD BC,99 * 3 LD (HL),0 LDIR RET IF DEBUG TXT .D1 DZ "1" .D2 DZ "2" .D3 DZ "3" .D4 DZ "4" .D5 DZ "5" .D6 DZ "6" .D7 DZ "7" .D8 DZ "8" DEBUGTABLKEYS DW TXT.D1,363,95 DW TXT.D2,483,95 DW TXT.D3,523,95 DW TXT.D4,363,115 DW TXT.D5,403,115 DW TXT.D6,443,115 DW TXT.D7,483,115 DW TXT.D8,523,115 DW 0 ENDIF ; таблица иконок для кнопок TABLBUTTONS DW cd_play,201,95 DW cd_paus,241,95 DW cd_stop,261,95 DW cd_ll,181,115 DW cd_l,201,115 DW cd_r,221,115 DW cd_rr,241,115 DW cd_ejec,261,115 DW 0 ; хоткеи TABLHOTKEYS DB '1' DW CDPLAY ; плей DB '2' DW CDPAUSE ; пауза DB '3' DW CDSTOP ; стоп DB '4' DW PREV_TRACK ; предыдущий трек DB '5' DW REWIND ; перемотка назад DB '6' DW FORWARD ; перемотка вперед DB '7' DW NEXT_TRACK ; следующий трек DB '8' DW CDEJECT ; открытие/закрытие трея DB 0 ; текущий трек и текущее время трека Digits DB 0x00,0x00,0x0B .MIN DB 0x00,0x00,0x0A .SEC DB 0x00,0x00 ; пустое время для моргания в паузе DigitsNone DB 0x0B,0x0B,0x0B,0x0B,0x0B,0x0A,0x0B,0x0B ; таблица для мыши PluginMouseTab: dw 546,558, 81, 91,%0000000000100001,0,PluginExit,PluginExit dw 360,476, 94,112,%0000000000000001,0,CDPLAY,0 dw 480,516, 94,112,%0000000000000001,0,CDPAUSE,0 dw 520,556, 94,112,%0000000000000001,0,CDSTOP,0 dw 360,396,114,132,%0000000000000001,0,PREV_TRACK,0 dw 400,436,114,132,%0000000000000001,0,REWIND,0 dw 440,476,114,132,%0000000000000001,0,FORWARD,0 dw 480,516,114,132,%0000000000000001,0,NEXT_TRACK,0 dw 520,556,114,132,%0000000000000001,0,CDEJECT,0 dw 0x8000 APCMD ; 00 01 02 03 04 05 06 07 08 09 0A 0B .STOP DB 0x4E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 .PAUSE DB 0x4B,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ; SM SS SF EM ES EF .PLAY_MSF DB 0x47,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ; 3-5 START MSF, 6-8 END MSF .READTOC DB 0x43,0x02,0x00,0x00,0x00,0x00,0x01,0x03,0x24,0x00,0x00,0x00 .CLOSETRAY DB 0x1B,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00 .OPENTRAY DB 0x1B,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00 .RDSUBCHAN DB 0x42,0x02,0x40,0x01,0x00,0x00,0x00,0x00,0x40,0x00,0x00,0x00 include icons.a80 include digits.a80 FLAG DB 0 BITMASK TRAY, 7 ; 1-трей открыт, 0-трей закрыт BITMASK RDUPDATE, 6 ; 1-обновление времени,0-чтение времени BITMASK PAUSE, 5 ; 1-режим паузы,0-нет BITMASK PLAY, 4 ; 1-режим плей активен,0-нет BITMASK PAUSENEW, 3 ; 1-в режиме пауза нажат переход на другой трек BITMASK VIEWNONE, 2 ; 1-пустые цифры,0-нормальные CURRENT ; номер трека и время для вывода на экран .TRACK DB 0 ; текущий трек .MINUTE DB 0 ; текущая минута .SECUND DB 0 ; текущая секунда .PAUSE_POS DW 0 ; текущая позиция на момент нажатия паузы TRACKS DB 0 ; количество треков на диске ; начало буфера получения результат выполнения ATAPI пакета RESULT DB 0 ; результат выполнения ATAPI команды