;[BEGIN] ;//MODULE: VIDEO ;//CREATE: 19-05-1998 AUTHOR: Denis Parinov ;//UPDATE: 24-10-1999 DNS Restore module ;--------------------------------------------------------------- ;Rev Date Name Description ;--------------------------------------------------------------- ;R03 04-04-2023 BAO FIXED BUGS IN FN SCROLL, SETVMOD, SELPAGE ;R02 07-11-2002 DNS CORRECT FN. WINCOPY & WINREST, ADD "DI+EI" ;R01 07-11-2002 DNS FIX BUG WITH SCROLLUP FN. (A=0) ;--------------------------------------------------------------- ; CLEAR TEXT WINDOW CLEAR: LD C,BIOS.LP_CLS_WIN2 RST ToBIOS AND A RET ; ; PRINT NULL-TERMINATED CHARS STRING ; HL - STRING POINTER PCHARS: .loop: LD A,(HL) INC HL OR A RET Z ;!TEST FOR LP_PR_LINE_DIR ;PUSH HL ;CALL CURSOR ;LD (.CHAR),A ;LD A,(SLOT1) ;PUSH AF ;LD A,(SLOT0) ;LD (SLOT1),A ;LD HL,.CHAR + #4000 ;LD BC,0*256 + BIOS.LP_PR_LINE_DIR ;RST ToBIOS ;POP AF ;LD (SLOT1),A ;POP HL ;JP .loop ; CALL PUTCHAR ;!TEST CR+LF+SCROLL ;CALL CURSOR ;LD A,D ; проверка на переход курсора ;OR E ; в самое начало (X:Y == 0:0) ;CALL Z,PUTCHAR.LFF ; JP .loop ;.CHAR: DZ " ",0 ; PRINT CHAR ; A - CHAR PUTCHAR: ;LD B,A ;CALL CURSOR ;LD A,B ;CP ' ' ;JR NC,.CHAR CP #0D JR Z,.CR_ CP #0A JR Z,.LF_ CP #09 JR Z,.TB_ CP #08 JR Z,.BK_ CP #07 JR Z,.BELL ;SCF ;RET .CHAR: LD BC,1*256 + BIOS.LP_PRINT_SYM ;!TEST CR+LF+SCROLL ;JP ToBIOS RST ToBIOS ; проверка на переход курсора в самое начало (X:Y == 0:0) CALL CURSOR LD A,D OR E RET NZ ;LD A,D ; в DE координаты текущего знакоместа ;XOR E ; Проверяем на координаты #1F:#4F ;XOR #50 ;RET NZ ; если другие - то выход ;LD E,A ;CALL LOCATE ; .LFF: PUSH HL ;!FIXIT сохранять текущие прерывания ;PUSH DE LD BC,1*256 + BIOS.LP_SCROLL_UD LD DE,#0020 ;EI ;HALT ;DI RST ToBIOS LD DE,#1F00 ;PUSH DE CALL LOCATE LD A,' ' LD BC,#50*256 + BIOS.LP_PRINT_SYM RST ToBIOS ;EI ;POP DE LD DE,#1F00 CALL LOCATE POP HL RET .TB_: LD C,BIOS.LP_GET_PLACE ;GET CURSOR RST ToBIOS IF TABisSPACES LD B,E LD A,E AND #F8 ADD A,8 SUB B LD B,A LD A,' ' LD C,BIOS.LP_PRINT_SYM JP ToBIOS ELSE LD A,E ADD A,8 AND #78 ;????? глянуть, что будет если координаты курсора в конце строки почти LD E,A JP LOCATE ENDIF .BK_: LD C,BIOS.LP_GET_PLACE ;GET CURSOR RST ToBIOS XOR A CP E ;!TEST ;JP Z,LOCATE RET Z DEC E JP LOCATE .LF_: LD C,BIOS.LP_GET_PLACE ;GET CURSOR RST ToBIOS LD A,D CP #1F JR NC,.LFF ;!FIXIT срабатывает как CRLF надо скроллить с сохранением Y INC D IFN EnoughtOnly_LF JP LOCATE ELSE CALL LOCATE ; !!!! НЕ разрывать LF_ и CR_ !!!! ENDIF .CR_: LD C,BIOS.LP_GET_PLACE ;GET CURSOR RST ToBIOS LD E,0 JP LOCATE .BELL: LD DE,1200 LD HL,4 JP BEEP .NO_SCROLL: ;CP ' ' ;JR NC,.CHAR CP #0D JR Z,.CR_ CP #0A JR Z,.LF_ CP #09 JR Z,.TB_ CP #08 JR Z,.BK_ CP #07 JR Z,.BELL ;SCF ;RET ._CHAR: LD BC,1*256 + BIOS.LP_PRINT_SYM ;!TEST CR+LF+SCROLL JP ToBIOS ;RST ToBIOS ;-----[] ; ; ; SET CURRENT CURSOR POSITION ;=============================== ; D = Y ; E = X LOCATE: LD C,BIOS.LP_SET_PLACE ; LD A,C ; LD (NO_NEED_SCROLL),A JP ToBIOS ;RET ; GET CURRENT CURSOR POSITION ; out: ; D - Y ; E - X CURSOR: LD C,BIOS.LP_GET_PLACE JP ToBIOS ;RET ; READ CHAR & ATTR FROM THE SCREEN ; in: ; D - Y ; E - X ; out: ; A - CHAR ; B - ATTR RDCHAR: XOR A LD C,BIOS.WIN_GET_SYM RST ToBIOS LD A,L LD B,H AND A RET ; WRITE CHAR & ATTR TO THE SCREEN ; D - Y ; E - X ; A - CHAR ; B - ATTR ;!FIXIT slow как без WIN_GET_SYM тут обойтись? WRCHAR: LD C,A PUSH BC PUSH DE XOR A LD C,BIOS.WIN_GET_SYM RST ToBIOS POP DE POP HL XOR A LD C,BIOS.WIN_PUT_SYM RST ToBIOS AND A RET ; COPY WINDOW FROM THE SCREEN ; D - Y ; E - X ; H - HEIGHT ; L - WIDTH ; IX - ADDRESS ; B - PAGE, IF IX > #C000 WINCOPY: AND A LD A,R ;R02 PUSH AF ;R02 XOR A ;EX AF,AF' ;R03 ;LD A,B ;R03 ;EX AF,AF' ;R03 LD C,BIOS.WIN_COPY DI ;R02 RST ToBIOS POP AF ;R02 RET PO ;R02 EI ;R02 RET ; RESTORE WINDOW TO THE SCREEN ; D - Y ; E - X ; H - HEIGHT ; L - WIDTH ; IX - ADDRESS ; B - PAGE, IF IX > #C000 WINREST: AND A LD A,R ;R02 PUSH AF ;R02 XOR A ;EX AF,AF' ;R03 ;LD A,B ;R03 ;EX AF,AF' ;R03 DI ;R02 LD C,BIOS.WIN_RESTORE RST ToBIOS POP AF ;R02 RET PO ;R02 EI ;R02 RET ; SCROLL WINDOW ; D - Y ; E - X ; H - HEIGHT ; L - WIDTH ; B - SCROLL DIRECTION ; B = 1 - SCROLL UP ; B = 2 - SCROLL DOWN ; A = 0 - CLEAR LINE SCROLL: DJNZ SCR_DW ;!TODO заменить на BIOS.LP_SCROLL_UD и посмотреть, что шустрее ;!TEST ;LD B,A ;LD C,H ;PUSH BC PUSH AF ; PUSH DE PUSH HL LD XH,D LD XL,E INC D DEC H LD C,BIOS.WIN_MOVE XOR A RST ToBIOS POP HL POP DE ;!TEST ;POP BC POP AF ;XOR A ;CP B AND A ; RET NZ LD A,D ADD A,H DEC A ;R01 LD D,A .print: PUSH DE ;R01 CALL LOCATE LD A,' ' LD B,L LD C,BIOS.LP_PRINT_SYM RST ToBIOS POP DE ;R01 CALL LOCATE ;R01 AND A RET SCR_DW: DJNZ SCR_ERR ;!TEST ;LD B,A ;LD C,H ;PUSH BC PUSH AF ;R03 ; PUSH DE PUSH HL LD XH,D LD XL,E INC XH DEC H LD C,BIOS.WIN_MOVE XOR A RST ToBIOS POP HL POP DE ;!TEST ;POP BC POP AF ;R03 ;XOR A ;CP B AND A ; RET NZ JP SCROLL.print ; PUSH DE ;R01 ; CALL LOCATE ; LD A,#20 ; LD B,L ; LD C,BIOS.LP_PRINT_SYM ; RST ToBIOS ; POP DE ;R01 ; CALL LOCATE ;R01 ; AND A RET SCR_ERR: LD A,DSS_Error.sys.INVALID_FUNCTION SCF RET ; SELECT SCREEN PAGE ; B - SCREEN PAGE SELPAGE:;PUSH BC LD A,(VMODE) BIT 7,A JR NZ,.SEL2 PUSH BC LD C,A CALL SETVMOD.TEXT_M POP BC .SEL2: ;POP BC LD A,B AND #01 OUT (SCREEN_SWITCH),A RET ; GET CURRENT VIDEO MODE ; out: ; A - MODE ; B - PAGE GETVMOD IN A,(SCREEN_SWITCH) LD B,A LD A,(VMODE) AND A RET ; SET CURRENT VIDEO MODE ; A - MODE ; B - PAGE SETVMOD: BIT 7,A LD C,A JR NZ,GRAPH .TEXT_M: LD IX,BACKTXT PUSH IX EX AF,AF' LD A,(VMODE) LD (VVMODE),A EX AF,AF' INC A DEC A JR Z,.NOMODE DEC A JR Z,.NOMODE DEC A LD HL,TAB_40x32 JP Z,T_40_32 DEC A LD HL,TAB_80x32 JP Z,T_80_32 .NOMODE: POP IX LD A,DSS_Error.sys.INVALID_VIDEO_MODE SCF RET GRAPH: CALL SAVETXT AND #7F JR Z,G320_16 ; !TODO ? - пока отрабатывает как ошибка DEC A JR Z,G320_56 DEC A JR Z,G640_16 ; DEC A ; JP Z,G640_56 ; !TODO ? - пока отрабатывает как ошибка G320_16: LD A,DSS_Error.sys.INVALID_VIDEO_MODE SCF RET T_80_32: T_40_32: PUSH BC ; LD HL,TAB2 LD A,B RLCA RLCA RLCA RLCA OR B AND #11 XOR #10 LD E,A GRAPH_NEXT: CALL SETMODE POP BC LD A,C LD (VMODE),A LD A,B AND #01 OUT (SCREEN_SWITCH),A LD A,(VMODE) LD C,#81 RST #30 SAFE_PORTY XOR A RET ; T_80_32 PUSH BC ; LD HL,TAB1 ; LD A,B ; RLCA ; RLCA ; RLCA ; RLCA ; OR B ; AND #11 ; XOR #10 ; LD E,A ; CALL SETMODE ; POP BC ; LD A,C ; LD (VMODE),A ; LD A,B ; AND #01 ; OUT (SCREEN_SWITCH),A ; LD A,(VMODE) ; LD C,#81 ; RST #30 ; SAFE_PORTY ; XOR A ; RET G320_56 PUSH BC LD HL,TAB_320x256_0 LD E,#11 CALL SETMODE LD HL,TAB_320x256_1 LD E,#00 JP GRAPH_NEXT ; CALL SETMODE ; POP BC ; LD A,C ; LD (VMODE),A ; LD A,B ; AND #01 ; OUT (SCREEN_SWITCH),A ; LD A,(VMODE) ; LD C,#81 ; RST #30 ; SAFE_PORTY ; XOR A ; RET G640_16 PUSH BC LD HL,TAB_640x256_0 LD E,#11 CALL SETMODE LD HL,TAB_640x256_1 LD E,#00 JP GRAPH_NEXT ; CALL SETMODE ; POP BC ; LD A,C ; LD (VMODE),A ; LD A,B ; AND #01 ; OUT (SCREEN_SWITCH),A ; LD A,(VMODE) ; LD C,#81 ; RST #30 ; SAFE_PORTY ; XOR A ; RET VMODE: DB #03 ;02h - TEXT 40 x 32 (16 colors) ;03h - TEXT 80 x 32 (16 colors) ;80h - GRAF 320 x 256 (16 colors) ;81h - GRAF 320 x 256 (256 colors) ;82h - GRAF 640 x 256 (16 colors) ;83h - GRAF 640 x 256 (256 colors) UNUSED SETMODE: PUSH DE LD DE,SYS_PAGE.SHARED_BUFFER_32b ; грязный хак. кидает данные в буфер служебной страницы биоса. LD BC,ScreenDescriptorTable.Size ; БИОС при использовании IX предполагает, что он указывает IN A,(SLOT3) ; на адрес ниже #C000 и вставляет в третью банку страницу #FE EX AF,AF' LD A,SYS_PAGE OUT (SLOT3),A LDIR EX AF,AF' OUT (SLOT3),A .skip_EI: POP DE LD IX,SYS_PAGE.SHARED_BUFFER_32b ; грязный хак. LD C,BIOS.WIN_OPEN RST ToBIOS SAFE_PORTY ;????? - возможно, что теперь не нужно, везде с банкой 3 работают, проверить XOR A RET ;IX+0 ;HORIZONTAL ;IX+1 ;VERTICAL ;IX+2 ;X - COORD ;IX+3 ;Y - COORD ;IX+4 ;MODE ;IX+5 ;EXT MODE ;IX+6 ;VIDEO RAM X OFFSET (SIGNPLACES) ;IX+7 ;VIDEO RAM Y OFFSET (SIGNPLACES) ; ;....................................................................... ScreenDescriptorTable EQU $ ;80x32 TAB_80x32 DB #28,#20,#00,#00,#1B,#00,#00,#00 ;1 ;40x32 TAB_40x32 DB #28,#20,#00,#00,#3B,#00,#00,#00 ;2 ;640x256 PAGE 0 TAB_640x256_0 DB #28,#20,#00,#00,#00,#00,#00,#00 ;3 ;320x256 PAGE 0 TAB_320x256_0 DB #28,#20,#00,#00,#20,#00,#00,#00 ;4 ;640x256 PAGE 1 TAB_640x256_1 DB #28,#20,#00,#00,#40,#00,#28,#00 ;5 ;320x256 PAGE 1 TAB_320x256_1 DB #28,#20,#00,#00,#60,#00,#28,#00 ;6 ScreenDescriptorTable.Size EQU ($ - ScreenDescriptorTable)/6 ;....................................................................... ; SAVETXT PUSH AF ;!!!!! перенесена логика супер дичайшего ускорения LD A,(VMODE) BIT 7,A JR NZ,NOSAVET SUB #02 JR C,NOSAVET ;; PUSH BC PUSH DE PUSH HL PUSH IX PUSH AF LD C,BIOS.LP_GET_PLACE RST ToBIOS LD (TCURS),DE POP AF LD IX,#C000 LD HL,#2050 OR A JR NZ,SVTEXT1 LD L,#28 SVTEXT1 LD (SVHL1),HL LD DE,#0000 ;EX AF,AF' ;R03 LD A,(BANKTBL+TXTPAGE) LD B,A ;EX AF,AF' ;R03 LD C,BIOS.WIN_COPY XOR A DI RST ToBIOS EI POP IX POP HL POP DE POP BC NOSAVET: POP AF RET BACKTXT PUSH AF VVMODE+1: LD A,#00 BIT 7,A JR Z,NOBACKT PUSH BC PUSH DE PUSH HL PUSH IX LD IX,#C000 SVHL1+1: LD HL,#2050 LD DE,#0000 ;EX AF,AF' ;R03 LD A,(BANKTBL+TXTPAGE) LD B,A ;EX AF,AF' ;R03 LD C,BIOS.WIN_RESTORE XOR A DI RST ToBIOS EI TCURS+1: LD DE,#0000 ;LD C,BIOS.LP_SET_PLACE ;RST ToBIOS CALL LOCATE POP IX POP HL POP DE POP BC NOBACKT: POP AF RET ; SEND A SYMBOL TO THE PRINTER ;============================== ; A - SYMBOL ;!FIXIT заменить на sp2000.inc LPT_A EQU #1B LPT_B EQU #1C PRINT: AND A LD B,A LD A,R LD A,B DI PUSH AF XOR A OUT (LPT_A),A LD A,#10 OUT (LPT_A),A XOR A OUT (LPT_A),A IN A,(LPT_A) ; IN (1Bh): bit 5 - busy, Bit 3 - Ack ;ld c,a ; САЙМАН BIT 5,A ; IN (19h): bit 5 - Paper Enable, Bit 3 - Select JR NZ,LPTBUSY ;and %11011000 ; САЙМАН ;jr z,LPTBUSY ; САЙМАН LD A,B OUT (LPT_B),A POP AF RET PO EI RET LPTBUSY: POP AF ;ld a,c ; САЙМАН SCF RET PO EI RET ; B - SYMBOL ; CF = 1 - PRINTER BUSY ;!FIXIT заменить на sp2000.inc LPT1_C EQU #1D LPT2_D EQU #1E LPT2_C EQU #1F PRINT_INIT: DI LD A,#CF ; port #1F только чеpез LD BC,1F : Out (BC),reg (в альтере идёт перехват этого порта проца, если он в команде явно указан) LD BC,LPT2_C OUT (C),A LD A,#63 OUT (C),A LD A,#C0 ; Bit 7 - Select (1), Bit 6 - Auto_Line_Feed (1) OUT (LPT2_D),A LD A,#0F ; Init printer port for Out OUT (LPT1_C),A ; САЙМАН ВЫРЕЗАЛ XOR A ;LD A,0 OUT (COM_A),A ;LD A,0 OUT (COM_A),A ; ????? надо ли второй раз зассылать и вообще имеет ли смысл com инитить? LD A,5 OUT (COM_A),A LD A,#62 ; bit 7 - Direction for Bufer (0), Bit 1 - Bufer Enable (1) OUT (COM_A),A RET ; САЙМАН ВЫРЕЗАЛ ;//MODULE: VIDEO ;[END] ; ; САЙМАН ; PUSH AF ; LD A,E ; CP #4F ; JP NZ,.exit ; LD A,D ; CP #1F ; JP NZ,.exit ; LD E,0 ; LD C,BIOS.LP_SET_PLACE ; RST ToBIOS ; CALL LFF ; .exit: ; pop af ; RET ; ; САЙМАН ; LD A,D ; в DE координаты текущего знакоместа ; XOR E ; Проверяем на координаты #1F:#4F ; XOR #50 ; RET NZ ; если другие - то выход ; LD E,A ; LD C,BIOS.LP_SET_PLACE ; RST ToBIOS ;LFF: ; ... ;;;;;;;; ; LD A,D ; в DE координаты текущего знакоместа ; XOR E ; Проверяем на координаты #1F:#4F ; XOR #50 ; RET NZ ; если другие - то выход ;;;;;;;;