home *** CD-ROM | disk | FTP | other *** search
Text File | 1989-10-30 | 48.0 KB | 1,044 lines |
- ;+---------------------------------------------------------------------------+
- ;! IncludeFile zu !
- ;! HERKULES.ASM !
- ;+---------------------------------------------------------------------------+
- ;Hier zuerst die ZeichenSatz-Tabelle:
- DB 000h,000h,000h,000h,000h,000h,000h,000h
- DB 07Eh,081h,0A5h,081h,0BDh,099h,081h,07Eh
- DB 07Eh,0FFh,0DBh,0FFh,0C3h,0E7h,0FFh,07Eh
- DB 06Ch,0FEh,0FEh,0FEh,07Ch,038h,010h,000h
- DB 010h,038h,07Ch,0FEh,07Ch,038h,010h,000h
- DB 038h,07Ch,038h,0FEh,0FEh,07Ch,038h,07Ch
- DB 010h,010h,038h,07Ch,0FEh,07Ch,038h,07Ch
- DB 000h,000h,018h,03Ch,03Ch,018h,000h,000h
- DB 0FFh,0FFh,0E7h,0C3h,0C3h,0E7h,0FFh,0FFh
- DB 000h,03Ch,066h,042h,042h,066h,03Ch,000h
- DB 0FFh,0C3h,099h,0BDh,0BDh,099h,0C3h,0FFh
- DB 00Fh,007h,00Fh,07Dh,0CCh,0CCh,0CCh,078h
- DB 03Ch,066h,066h,066h,03Ch,018h,07Eh,018h
- DB 03Fh,033h,03Fh,030h,030h,070h,0F0h,0E0h
- DB 07Fh,063h,07Fh,063h,063h,067h,0E6h,0C0h
- DB 099h,05Ah,03Ch,0E7h,0E7h,03Ch,05Ah,099h
- DB 080h,0E0h,0F8h,0FEh,0F8h,0E0h,080h,000h
- DB 002h,00Eh,03Eh,0FEh,03Eh,00Eh,002h,000h
- DB 018h,03Ch,07Eh,018h,018h,07Eh,03Ch,018h
- DB 066h,066h,066h,066h,066h,000h,066h,000h
- DB 07Fh,0DBh,0DBh,07Bh,01Bh,01Bh,01Bh,000h
- DB 03Eh,063h,038h,06Ch,06Ch,038h,0CCh,078h
- DB 000h,000h,000h,000h,07Eh,07Eh,07Eh,000h
- DB 018h,03Ch,07Eh,018h,07Eh,03Ch,018h,0FFh
- DB 018h,03Ch,07Eh,018h,018h,018h,018h,000h
- DB 018h,018h,018h,018h,07Eh,03Ch,018h,000h
- DB 000h,018h,00Ch,0FEh,00Ch,018h,000h,000h
- DB 000h,030h,060h,0FEh,060h,030h,000h,000h
- DB 000h,000h,0C0h,0C0h,0C0h,0FEh,000h,000h
- DB 000h,024h,066h,0FFh,066h,024h,000h,000h
- DB 000h,018h,03Ch,07Eh,0FFh,0FFh,000h,000h
- DB 000h,0FFh,0FFh,07Eh,03Ch,018h,000h,000h
- DB 000h,000h,000h,000h,000h,000h,000h,000h
- DB 030h,078h,078h,078h,030h,000h,030h,000h
- DB 06Ch,06Ch,06Ch,000h,000h,000h,000h,000h
- DB 06Ch,06Ch,0FEh,06Ch,0FEh,06Ch,06Ch,000h
- DB 030h,07Ch,0C0h,078h,00Ch,0F8h,030h,000h
- DB 000h,0C6h,0CCh,018h,030h,066h,0C6h,000h
- DB 038h,06Ch,038h,076h,0DCh,0CCh,076h,000h
- DB 060h,060h,0C0h,000h,000h,000h,000h,000h
- DB 018h,030h,060h,060h,060h,030h,018h,000h
- DB 060h,030h,018h,018h,018h,030h,060h,000h
- DB 000h,066h,03Ch,0FFh,03Ch,066h,000h,000h
- DB 000h,030h,030h,0FCh,030h,030h,000h,000h
- DB 000h,000h,000h,000h,000h,030h,030h,060h
- DB 000h,000h,000h,0FCh,000h,000h,000h,000h
- DB 000h,000h,000h,000h,000h,030h,030h,000h
- DB 006h,00Ch,018h,030h,060h,0C0h,080h,000h
- DB 07Ch,0C6h,0CEh,0DEh,0F6h,0E6h,07Ch,000h
- DB 030h,070h,030h,030h,030h,030h,0FCh,000h
- DB 078h,0CCh,00Ch,038h,060h,0CCh,0FCh,000h
- DB 078h,0CCh,00Ch,038h,00Ch,0CCh,078h,000h
- DB 01Ch,03Ch,06Ch,0CCh,0FEh,00Ch,01Eh,000h
- DB 0FCh,0C0h,0F8h,00Ch,00Ch,0CCh,078h,000h
- DB 038h,060h,0C0h,0F8h,0CCh,0CCh,078h,000h
- DB 0FCh,0CCh,00Ch,018h,030h,030h,030h,000h
- DB 078h,0CCh,0CCh,078h,0CCh,0CCh,078h,000h
- DB 078h,0CCh,0CCh,07Ch,00Ch,018h,070h,000h
- DB 000h,030h,030h,000h,000h,030h,030h,000h
- DB 000h,030h,030h,000h,000h,030h,030h,060h
- DB 018h,030h,060h,0C0h,060h,030h,018h,000h
- DB 000h,000h,0FCh,000h,000h,0FCh,000h,000h
- DB 060h,030h,018h,00Ch,018h,030h,060h,000h
- DB 078h,0CCh,00Ch,018h,030h,000h,030h,000h
- DB 07Ch,0C6h,0DEh,0DEh,0DEh,0C0h,078h,000h
- DB 030h,078h,0CCh,0CCh,0FCh,0CCh,0CCh,000h
- DB 0FCh,066h,066h,07Ch,066h,066h,0FCh,000h
- DB 03Ch,066h,0C0h,0C0h,0C0h,066h,03Ch,000h
- DB 0F8h,06Ch,066h,066h,066h,06Ch,0F8h,000h
- DB 07Eh,060h,060h,078h,060h,060h,07Eh,000h
- DB 07Eh,060h,060h,078h,060h,060h,060h,000h
- DB 03Ch,066h,0C0h,0C0h,0CEh,066h,03Eh,000h
- DB 0CCh,0CCh,0CCh,0FCh,0CCh,0CCh,0CCh,000h
- DB 078h,030h,030h,030h,030h,030h,078h,000h
- DB 01Eh,00Ch,00Ch,00Ch,0CCh,0CCh,078h,000h
- DB 0E6h,066h,06Ch,078h,06Ch,066h,0E6h,000h
- DB 060h,060h,060h,060h,060h,060h,07Eh,000h
- DB 0C6h,0EEh,0FEh,0FEh,0D6h,0C6h,0C6h,000h
- DB 0C6h,0E6h,0F6h,0DEh,0CEh,0C6h,0C6h,000h
- DB 038h,06Ch,0C6h,0C6h,0C6h,06Ch,038h,000h
- DB 0FCh,066h,066h,07Ch,060h,060h,0F0h,000h
- DB 078h,0CCh,0CCh,0CCh,0DCh,078h,01Ch,000h
- DB 0FCh,066h,066h,07Ch,06Ch,066h,0E6h,000h
- DB 078h,0CCh,0E0h,070h,01Ch,0CCh,078h,000h
- DB 0FCh,030h,030h,030h,030h,030h,030h,000h
- DB 0CCh,0CCh,0CCh,0CCh,0CCh,0CCh,0FCh,000h
- DB 0CCh,0CCh,0CCh,0CCh,0CCh,078h,030h,000h
- DB 0C6h,0C6h,0C6h,0D6h,0FEh,0EEh,0C6h,000h
- DB 0C6h,0C6h,06Ch,038h,038h,06Ch,0C6h,000h
- DB 0CCh,0CCh,0CCh,078h,030h,030h,078h,000h
- DB 0FEh,006h,00Ch,018h,030h,060h,0FEh,000h
- DB 078h,060h,060h,060h,060h,060h,078h,000h
- DB 0C0h,060h,030h,018h,00Ch,006h,002h,000h
- DB 078h,018h,018h,018h,018h,018h,078h,000h
- DB 010h,038h,06Ch,0C6h,000h,000h,000h,000h
- DB 000h,000h,000h,000h,000h,000h,000h,0FFh
- DB 030h,030h,018h,000h,000h,000h,000h,000h
- DB 000h,000h,078h,00Ch,07Ch,0CCh,076h,000h
- DB 0E0h,060h,060h,07Ch,066h,066h,0DCh,000h
- DB 000h,000h,078h,0CCh,0C0h,0CCh,078h,000h
- DB 01Ch,00Ch,00Ch,07Ch,0CCh,0CCh,076h,000h
- DB 000h,000h,078h,0CCh,0FCh,0C0h,078h,000h
- DB 038h,06Ch,060h,0F0h,060h,060h,0F0h,000h
- DB 000h,000h,076h,0CCh,0CCh,07Ch,00Ch,0F8h
- DB 0E0h,060h,06Ch,076h,066h,066h,0E6h,000h
- DB 030h,000h,070h,030h,030h,030h,078h,000h
- DB 00Ch,000h,00Ch,00Ch,00Ch,0CCh,0CCh,078h
- DB 0E0h,060h,066h,06Ch,078h,06Ch,0E6h,000h
- DB 070h,030h,030h,030h,030h,030h,078h,000h
- DB 000h,000h,0CCh,0FEh,0FEh,0D6h,0C6h,000h
- DB 000h,000h,0F8h,0CCh,0CCh,0CCh,0CCh,000h
- DB 000h,000h,078h,0CCh,0CCh,0CCh,078h,000h
- DB 000h,000h,0DCh,066h,066h,07Ch,060h,0F0h
- DB 000h,000h,076h,0CCh,0CCh,07Ch,00Ch,01Eh
- DB 000h,000h,0DCh,076h,066h,060h,0F0h,000h
- DB 000h,000h,07Ch,0C0h,078h,00Ch,0F8h,000h
- DB 010h,030h,07Ch,030h,030h,034h,018h,000h
- DB 000h,000h,0CCh,0CCh,0CCh,0CCh,076h,000h
- DB 000h,000h,0CCh,0CCh,0CCh,078h,030h,000h
- DB 000h,000h,0C6h,0D6h,0FEh,0FEh,06Ch,000h
- DB 000h,000h,0C6h,06Ch,038h,06Ch,0C6h,000h
- DB 000h,000h,0CCh,0CCh,0CCh,07Ch,00Ch,0F8h
- DB 000h,000h,0FCh,098h,030h,064h,0FCh,000h
- DB 01Ch,030h,030h,0E0h,030h,030h,01Ch,000h
- DB 018h,018h,018h,000h,018h,018h,018h,000h
- DB 0E0h,030h,030h,01Ch,030h,030h,0E0h,000h
- DB 076h,0DCh,000h,000h,000h,000h,000h,000h
- DB 000h,010h,038h,06Ch,0C6h,0C6h,0FEh,000h
- DB 078h,0CCh,0C0h,0CCh,078h,018h,00Ch,078h
- DB 000h,0CCh,000h,0CCh,0CCh,0CCh,07Eh,000h
- DB 01Ch,000h,078h,0CCh,0FCh,0C0h,078h,000h
- DB 07Eh,0C3h,03Ch,006h,03Eh,066h,03Fh,000h
- DB 0CCh,000h,078h,00Ch,07Ch,0CCh,07Eh,000h
- DB 0E0h,000h,078h,00Ch,07Ch,0CCh,07Eh,000h
- DB 030h,030h,078h,00Ch,07Ch,0CCh,07Eh,000h
- DB 000h,000h,078h,0C0h,0C0h,078h,00Ch,038h
- DB 07Eh,0C3h,03Ch,066h,07Eh,060h,03Ch,000h
- DB 0CCh,000h,078h,0CCh,0FCh,0C0h,078h,000h
- DB 0E0h,000h,078h,0CCh,0FCh,0C0h,078h,000h
- DB 0CCh,000h,070h,030h,030h,030h,078h,000h
- DB 07Ch,0C6h,038h,018h,018h,018h,03Ch,000h
- DB 0E0h,000h,070h,030h,030h,030h,078h,000h
- DB 0C6h,038h,06Ch,0C6h,0FEh,0C6h,0C6h,000h
- DB 030h,030h,000h,078h,0CCh,0FCh,0CCh,000h
- DB 01Ch,000h,0FCh,060h,078h,060h,0FCh,000h
- DB 000h,000h,07Fh,00Ch,07Fh,0CCh,07Fh,000h
- DB 03Eh,06Ch,0CCh,0FEh,0CCh,0CCh,0CEh,000h
- DB 078h,0CCh,000h,078h,0CCh,0CCh,078h,000h
- DB 000h,0CCh,000h,078h,0CCh,0CCh,078h,000h
- DB 000h,0E0h,000h,078h,0CCh,0CCh,078h,000h
- DB 078h,0CCh,000h,0CCh,0CCh,0CCh,07Eh,000h
- DB 000h,0E0h,000h,0CCh,0CCh,0CCh,07Eh,000h
- DB 000h,0CCh,000h,0CCh,0CCh,07Ch,00Ch,0F8h
- DB 0C3h,018h,03Ch,066h,066h,03Ch,018h,000h
- DB 0CCh,000h,0CCh,0CCh,0CCh,0CCh,078h,000h
- DB 018h,018h,07Eh,0C0h,0C0h,07Eh,018h,018h
- DB 038h,06Ch,064h,0F0h,060h,0E6h,0FCh,000h
- DB 0CCh,0CCh,078h,0FCh,030h,0FCh,030h,030h
- DB 0F8h,0CCh,0CCh,0FAh,0C6h,0CFh,0C6h,0C7h
- DB 00Eh,01Bh,018h,03Ch,018h,018h,0D8h,070h
- DB 01Ch,000h,078h,00Ch,07Ch,0CCh,07Eh,000h
- DB 038h,000h,070h,030h,030h,030h,078h,000h
- DB 000h,01Ch,000h,078h,0CCh,0CCh,078h,000h
- DB 000h,01Ch,000h,0CCh,0CCh,0CCh,07Eh,000h
- DB 000h,0F8h,000h,0F8h,0CCh,0CCh,0CCh,000h
- DB 0FCh,000h,0CCh,0ECh,0FCh,0DCh,0CCh,000h
- DB 03Ch,06Ch,06Ch,03Eh,000h,07Eh,000h,000h
- DB 038h,06Ch,06Ch,038h,000h,07Ch,000h,000h
- DB 030h,000h,030h,060h,0C0h,0CCh,078h,000h
- DB 000h,000h,000h,0FCh,0C0h,0C0h,000h,000h
- DB 000h,000h,000h,0FCh,00Ch,00Ch,000h,000h
- DB 0C3h,0C6h,0CCh,0DEh,033h,066h,0CCh,00Fh
- DB 0C3h,0C6h,0CCh,0DBh,037h,06Fh,0CFh,003h
- DB 018h,018h,000h,018h,018h,018h,018h,000h
- DB 000h,033h,066h,0CCh,066h,033h,000h,000h
- DB 000h,0CCh,066h,033h,066h,0CCh,000h,000h
- DB 022h,088h,022h,088h,022h,088h,022h,088h
- DB 055h,0AAh,055h,0AAh,055h,0AAh,055h,0AAh
- DB 0DBh,077h,0DBh,0EEh,0DBh,077h,0DBh,0EEh
- DB 018h,018h,018h,018h,018h,018h,018h,018h
- DB 018h,018h,018h,018h,0F8h,018h,018h,018h
- DB 018h,018h,0F8h,018h,0F8h,018h,018h,018h
- DB 036h,036h,036h,036h,0F6h,036h,036h,036h
- DB 000h,000h,000h,000h,0FEh,036h,036h,036h
- DB 000h,000h,0F8h,018h,0F8h,018h,018h,018h
- DB 036h,036h,0F6h,006h,0F6h,036h,036h,036h
- DB 036h,036h,036h,036h,036h,036h,036h,036h
- DB 000h,000h,0FEh,006h,0F6h,036h,036h,036h
- DB 036h,036h,0F6h,006h,0FEh,000h,000h,000h
- DB 036h,036h,036h,036h,0FEh,000h,000h,000h
- DB 018h,018h,0F8h,018h,0F8h,000h,000h,000h
- DB 000h,000h,000h,000h,0F8h,018h,018h,018h
- DB 018h,018h,018h,018h,01Fh,000h,000h,000h
- DB 018h,018h,018h,018h,0FFh,000h,000h,000h
- DB 000h,000h,000h,000h,0FFh,018h,018h,018h
- DB 018h,018h,018h,018h,01Fh,018h,018h,018h
- DB 000h,000h,000h,000h,0FFh,000h,000h,000h
- DB 018h,018h,018h,018h,0FFh,018h,018h,018h
- DB 018h,018h,01Fh,018h,01Fh,018h,018h,018h
- DB 036h,036h,036h,036h,037h,036h,036h,036h
- DB 036h,036h,037h,030h,03Fh,000h,000h,000h
- DB 000h,000h,03Fh,030h,037h,036h,036h,036h
- DB 036h,036h,0F7h,000h,0FFh,000h,000h,000h
- DB 000h,000h,0FFh,000h,0F7h,036h,036h,036h
- DB 036h,036h,037h,030h,037h,036h,036h,036h
- DB 000h,000h,0FFh,000h,0FFh,000h,000h,000h
- DB 036h,036h,0F7h,000h,0F7h,036h,036h,036h
- DB 018h,018h,0FFh,000h,0FFh,000h,000h,000h
- DB 036h,036h,036h,036h,0FFh,000h,000h,000h
- DB 000h,000h,0FFh,000h,0FFh,018h,018h,018h
- DB 000h,000h,000h,000h,0FFh,036h,036h,036h
- DB 036h,036h,036h,036h,03Fh,000h,000h,000h
- DB 018h,018h,01Fh,018h,01Fh,000h,000h,000h
- DB 000h,000h,01Fh,018h,01Fh,018h,018h,018h
- DB 000h,000h,000h,000h,03Fh,036h,036h,036h
- DB 036h,036h,036h,036h,0FFh,036h,036h,036h
- DB 018h,018h,0FFh,018h,0FFh,018h,018h,018h
- DB 018h,018h,018h,018h,0F8h,000h,000h,000h
- DB 000h,000h,000h,000h,01Fh,018h,018h,018h
- DB 0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh
- DB 000h,000h,000h,000h,0FFh,0FFh,0FFh,0FFh
- DB 0F0h,0F0h,0F0h,0F0h,0F0h,0F0h,0F0h,0F0h
- DB 00Fh,00Fh,00Fh,00Fh,00Fh,00Fh,00Fh,00Fh
- DB 0FFh,0FFh,0FFh,0FFh,000h,000h,000h,000h
- DB 000h,000h,076h,0DCh,0C8h,0DCh,076h,000h
- DB 000h,078h,0CCh,0F8h,0CCh,0F8h,0C0h,0C0h
- DB 000h,0FCh,0CCh,0C0h,0C0h,0C0h,0C0h,000h
- DB 000h,0FEh,06Ch,06Ch,06Ch,06Ch,06Ch,000h
- DB 0FCh,0CCh,060h,030h,060h,0CCh,0FCh,000h
- DB 000h,000h,07Eh,0D8h,0D8h,0D8h,070h,000h
- DB 000h,066h,066h,066h,066h,07Ch,060h,0C0h
- DB 000h,076h,0DCh,018h,018h,018h,018h,000h
- DB 0FCh,030h,078h,0CCh,0CCh,078h,030h,0FCh
- DB 038h,06Ch,0C6h,0FEh,0C6h,06Ch,038h,000h
- DB 038h,06Ch,0C6h,0C6h,06Ch,06Ch,0EEh,000h
- DB 01Ch,030h,018h,07Ch,0CCh,0CCh,078h,000h
- DB 000h,000h,07Eh,0DBh,0DBh,07Eh,000h,000h
- DB 006h,00Ch,07Eh,0DBh,0DBh,07Eh,060h,0C0h
- DB 038h,060h,0C0h,0F8h,0C0h,060h,038h,000h
- DB 078h,0CCh,0CCh,0CCh,0CCh,0CCh,0CCh,000h
- DB 000h,0FCh,000h,0FCh,000h,0FCh,000h,000h
- DB 030h,030h,0FCh,030h,030h,000h,0FCh,000h
- DB 060h,030h,018h,030h,060h,000h,0FCh,000h
- DB 018h,030h,060h,030h,018h,000h,0FCh,000h
- DB 00Eh,01Bh,01Bh,018h,018h,018h,018h,018h
- DB 018h,018h,018h,018h,018h,0D8h,0D8h,070h
- DB 030h,030h,000h,0FCh,000h,030h,030h,000h
- DB 000h,076h,0DCh,000h,076h,0DCh,000h,000h
- DB 038h,06Ch,06Ch,038h,000h,000h,000h,000h
- DB 000h,000h,000h,018h,018h,000h,000h,000h
- DB 000h,000h,000h,000h,018h,000h,000h,000h
- DB 00Fh,00Ch,00Ch,00Ch,0ECh,06Ch,03Ch,01Ch
- DB 078h,06Ch,06Ch,06Ch,06Ch,000h,000h,000h
- DB 070h,018h,030h,060h,078h,000h,000h,000h
- DB 000h,000h,03Ch,03Ch,03Ch,03Ch,000h,000h
- DB 000h,000h,000h,000h,000h,000h,000h,000h
-
- ;----------------------------------------------------------------------------+
-
- Debugging = 0
-
- @BreakPoint MACRO
- IFE Debugging
- Debugging = 1
- IF1
- %OUT *** Debugging activated ***
- ENDIF
- ENDIF
- call BreakPoint
- ENDM
-
- @MarkOn MACRO
- IFE Debugging
- Debugging = 1
- IF1
- %OUT *** Debugging activated ***
- ENDIF
- ENDIF
- call MarkOn
- ENDM
-
- @MarkOff MACRO
- IFE Debugging
- Debugging = 1
- IF1
- %OUT *** Debugging activated ***
- ENDIF
- ENDIF
- call MarkOff
- ENDM
-
- ;----------------------------------------------------------------------------+
-
- ComputeWrapPos MACRO PointerReg ;DL=BytesToMove.
- LOCAL NoWrapping,GotWrapPos
- mov ah,dl
- mov cx,2000h
- sub cx,PointerReg ;CX = Distanz bis zum Wrap.
- test ch,ch ;Distanz >= 256 Bytes?
- jnz NoWrapping ;=> In dieser Zeile kein Wrap.
- cmp cl,dl ;Distanz >= BytesToMove?
- jb GotWrapPos ;Dann ebenfalls kein Wrap.
- NoWrapping:
- mov cl,dl ;In diesem Fall
- mov ch,0 ;CX=ganze Window-Zeile.
- GotWrapPos:
- sub ah,cl ;Wieviel bleibt dann noch übrig?
- ENDM ;CX=Anz MOVSB's vor dem Page-Wrap, AH=Anz dannach.
-
- UpdateCursorPos PROC NEAR ;AX=CursorPos, wird direkt in den Chip geschickt.
- push dx ;Register retten.
- mov dx,ax
- DisplayAdress_Text dl,dh
- push ax ;DisplayAdresse merken.
- mov dx,IndexReg
- mov al,15
- out dx,al ;Select Reg 15
- inc dx
- pop ax ;DisplayAdresse zurückholen
- out dx,al ;und Low Byte schreiben
- dec dx
- mov al,14
- out dx,al ;Select Reg 14
- inc dx
- mov al,ah
- out dx,al ;und High Byte schreiben.
- pop dx
- ret
- UpdateCursorPos ENDP ;AX destroyed.
-
- UpdateDispStart PROC NEAR ;AX=neuer DispStart, DS=40h
- mov CurDispStart,ax
- push dx
- shr ax,1 ;Offset in Words berechnen
- push ax ;und merken.
- mov dx,IndexReg
- mov al,13
- out dx,al ;RegisterNr ins IndexReg
- inc dx
- pop ax ;DisplayPosition nach AX
- out dx,al ;und LowByte ins DataReg.
- dec dx
- mov al,12 ;HighByte: Zuerst RegNr
- out dx,al ;ins IndexReg
- inc dx
- mov al,ah ;und dann das DatenByte
- out dx,al ;ins DataReg.
- pop dx
- ret
- UpdateDispStart ENDP ;AX destroyed
-
- ScrollPartOfScreenUp PROC NEAR
- ;AL=NrOfLines, (CH/CL)-(DH/DL), BL=New Attribute, AH=CurVideoMode, BH=PageNr
- push cx ;Register retten.
- push dx
- push bx
- sub dx,cx ;WindowGröße berechnen.
- add dx,0101h
- cmp al,0 ;NrOfLines=0? => Window soll nicht
- je NowClearWindow ;gescrolled sondern gelöscht werden.
- cmp al,dh ;NrOfLines>=WinSize?
- jae NowClearWindow ;Dann das ganze Window löschen.
- mov bl,al
- cmp ah,7 ;Sind wir im Text-Mode?
- je DoScrolling0 ;Dann ist es ja einfach.
- cmp cs:FastScrollFlag,True ;Soll IMMER langsam gescrolled werden?
- jne DoScrolling0 ;Auch in Ordnung.
- mov al,dl ;Wieviele Zeichen enthält das Window,
- mul dh ;das gescrolled werden soll?
- cmp ax,WholeScr*2/3 ;Weniger als 2/3 des ganzen Screens?
- jb DoScrolling0 ;Dann ebenfalls direkt scrollen.
- nop ;Es soll also FastScrolling gemacht werden. Ok!
- add ch,dh ;(YPos ist für alle Bereiche gleich,
- push cx ;nämlich die erste Zeile unter
- push dx ;dem zu scrollenden Window...)
- mov dl,cl
- mov cl,0
- mov dh,NrOfLines
- call RotateWindowDown ;Bereich 2,
- mov cl,dl
- pop dx
- neg dh
- add dh,NrOfLines
- add dh,bl
- call RotateWindowDown ;Bereich 3 und
- add cl,dl
- mov dl,NrOfChars
- sub dl,cl
- mov dh,NrOfLines
- call RotateWindowDown ;Bereich 4 entgegengesetzt rotieren.
- test bh,1
- GetPageArrayIndex OFFSET(DispStartTable),si ;Um welche Page geht es?
- mov ax,cs:[si]
- add ax,2*NrOfChars ;Entsprechenden DispStart
- and ax,1FFFh ;um 2 Scans (je 4 Dots hoch)
- mov cs:[si],ax ;hochsetzen und
- cmp bh,ActivePage
- jne NoDisplayUpdate0 ;Wurde die active Page gescrolled?
- call UpdateDispStart ;Dann neue DispStart auch an den 6845 schicken.
- NoDisplayUpdate0:
- pop ax
- mov cl,al ;Alte XPosLo wiederholen,
- sub ch,bl ;CH = YPosLo der nach Einscrollen zu löschenden Zeilen.
- neg dl
- add dl,NrOfChars ;(DH/DL) = Größe des nach Einscrollen
- sub dl,cl ;zu löschenden Bereichs.
- mov dh,bl
- jmp SHORT NowClearWindow
- DoScrolling0: ;BL=NrOfLines, (CH/CL)=Upper Left, (DH/DL)=Size of Window
- call RotateWindowUp
- add ch,dh ;Die neu eingescrollten Zeilen müssen noch gelöscht werden,
- sub ch,bl ;und zwar vom unteren Ende des zu scrollenden Bereichs an
- mov dh,bl ;so viele Zeilen, wie das Window gescrolled wurde.
- NowClearWindow: ;CX=WindowStart, DX=WindowSize
- pop bx ;"NewAttrib" und "PageNr" für
- call ClearWindow ;"ClearWindow" zurückholen.
- pop dx
- pop cx
- ret
- ScrollPartOfScreenUp ENDP ;AX and SI destroyed.
-
- ScrollPartOfScreenDown PROC NEAR
- ;AL=NrOfLines, (CH/CL)-(DH/DL), BL=New Attribute, AH=CurVideoMode, BH=PageNr
- push cx ;Register retten.
- push dx
- push bx
- sub dx,cx ;WindowGröße berechnen.
- add dx,0101h
- cmp al,0 ;NrOfLines=0? => Window soll nicht
- je NowClearWindow ;gescrolled sondern gelöscht werden.
- cmp al,dh ;NrOfLines>=WinSize?
- jae NowClearWindow ;Dann das ganze Window löschen.
- mov bl,al
- cmp ah,7 ;Sind wir im Text-Mode?
- je DoScrolling1 ;Dann ist es ja einfach.
- cmp cs:FastScrollFlag,True ;Soll IMMER langsam gescrolled werden?
- jne DoScrolling1 ;Auch in Ordnung.
- mov al,dl ;Wieviele Zeichen enthält das Window,
- mul dh ;das gescrolled werden soll?
- cmp ax,WholeScr*2/3 ;Weniger als 2/3 des ganzen Screens?
- jb DoScrolling1 ;Dann ebenfalls direkt scrollen.
- nop
- add ch,dh ;Es soll also FastScrolling gemacht werden. Ok!
- sub ch,bl ;(YPos ist für alle Bereiche gleich...)
- push dx
- add cl,dl
- mov dl,NrOfChars
- sub dl,cl
- mov dh,NrOfLines
- call RotateWindowUp ;Bereich 4,
- pop dx
- push dx
- sub cl,dl
- neg dh
- add dh,NrOfLines
- add dh,bl
- call RotateWindowUp ;Bereich 3 und
- mov dl,cl
- mov cl,0
- mov dh,NrOfLines
- call RotateWindowUp ;Bereich 2 entgegengesetzt rotieren.
- test bh,1
- GetPageArrayIndex OFFSET(DispStartTable),si ;Um welche Page geht es?
- mov ax,cs:[si]
- sub ax,2*NrOfChars ;Entsprechenden DispStart
- and ax,1FFFh ;um 2 Scans (je 4 Dots hoch)
- mov cs:[si],ax ;zurücksetzen und
- cmp bh,ActivePage
- jne NoDisplayUpdate1 ;Wurde die active Page gescrolled?
- call UpdateDispStart ;Dann neue DispStart auch an den 6845 schicken.
- NoDisplayUpdate1:
- mov cl,dl
- pop dx ;(CL/CH) - (DL/DH)
- sub ch,dh
- add ch,bl ; = nach dem Einscrollen
- mov dh,bl ;zu löschender Bereich.
- jmp NowClearWindow
- DoScrolling1: ;BL=NrOfLines, (CH/CL)=Upper Left, (DH/DL)=Size of Window
- call RotateWindowDown
- mov dh,bl ;Die oben neu eingescrollten Zeilen
- jmp NowClearWindow ;müssen noch gelöscht werden.
- ScrollPartOfScreenDown ENDP ;AX and SI destroyed.
-
- RotParamCheck PROC NEAR
- cmp dh,1 ;Sollen 0 oder 1 Zeile rotiert werden?
- jbe NoRotation ;Brauchen wir gar nicht mit anfangen.
- cmp dl,0 ;Ist das Window so schmal?
- je NoRotation ;Dann sind wir schon fertig.
- mov al,bl
- RangeParam:
- sub al,dh ;Soll das Window um mehr Zeilen rotiert werden als es
- ja RangeParam ;hoch ist? Dann BL in den richtigen Bereich bringen.
- add al,dh ;Vorhin wurde einmal zu oft abgezogen: korrigeren.
- ;cmp al,0 ;Soll um 0 Zeilen rotiert werden?
- ;je NoRotation <-- überflüssig... ;=> Fertig.
- mov bl,al
- mov al,dh ;Soll das Window um
- shr al,1 ;mehr als die Hälfte
- cmp bl,al ;rotiert werden?
- ja ScrollReverse ;Dann lieber andersrum rotieren.
- clc ;Params ok,
- ret ;mit C=0 zurück.
- ScrollReverse: ;Window soll andersrum rotiert werden.
- neg bl ;Rotation-Count an neue Drehrichtung anpassen:
- add bl,dh ;BL := DH - BL.
- ret ;Mit C=1 zurück.
- NoRotation: ;Es gibt nichts zu tun?
- add sp,2 ;Dann Rückkehradresse auf dem Stack verwerfen
- ret ;und zurück zur übergeordneten Routine.
- RotParamCheck ENDP ;AL destroyed.
-
- RotateWindowUp PROC NEAR
- ;BL=NrOfLines, CX=UpperLeft, DX=Size of Window, BH=PageNr.
- call RotParamCheck ;Sind die Parameter in Ordnung?
- jc RotateWindowDown ;Eignen sie sich besser für "RotateDown"?
- push bx
- push cx
- push bp ;Register retten.
- push di
- push ds
- push es
- test bh,1 ;Welches Page betrifft es denn?
- GetPageArrayIndex 0,si
- cmp CurVideoMode,8 ;Sind wir im Graphik-Modus?
- mov ds,cs:[PageSegment+si] ;DS = SEG(ActivePage),
- je GraphRotation0 ;Dann andere Rotation-Routine benutzen.
- nop
- DisplayAdress_Text cl,ch ;DisplayAdresse
- shl ax,1 ;mal 2 Bytes pro Char
- mov si,ax ;=> DS:SI = StartAdresse.
- mov bp,+160
- call RotateTextWindow
- jmp SHORT RotationDone0
- GraphRotation0: ;Also Graphik-Modus.
- push dx ;Dann erst noch ein weiteres Register retten.
- shl bl,1 ;BL (NrOfLines), CH (WinYLo) und DH (WinHeight)
- shl ch,1 ;von ZeichenZeilen (je 8 Dots hoch) nach
- shl dh,1 ;ScanZeilen (je 4 Dots hoch) umrechnen.
- DisplayAdress_Graph cl,ch
- mov si,cs:[DispStartTable+si] ;DisplayAdress
- add si,ax ; + DispStart
- and si,1FFFh ;nach Begrenzung
- mov bp,+NrOfDotsX/8 ;=> DS:SI = StartAdresse.
- mov bh,NrOfDotsY/4
- sub bh,ch ;BH = Anz ScanLines (je 4 Dots hoch) bis zum BottomOfScreen.
- call RotateBitMap ;Erste BitMap (Segment-Offset 0000h),
- call RotateBitMap ;zweite BitMap (Offset 2000h),
- call RotateBitMap ;dritte (Offset 4000h)
- call RotateBitMap ;und vierte (Offset 6000h) seperat rotieren.
- pop dx
- RotationDone0:
- pop es
- pop ds
- pop di ;Gerettete Register zurückholen
- pop bp
- pop cx
- pop bx
- ret ;und fertig.
- RotateWindowUp ENDP ;AX and SI destroyed.
-
- RotateWindowDown PROC NEAR
- ;BL=NrOfLines, CX=UpperLeft, DX=Size of Window, BH=PageNr.
- call RotParamCheck ;Sind die Parameter in Ordnung?
- jc RotateWindowUp ;Eignen sie sich besser für "RotateUp"?
- push bx
- push cx
- push bp
- push di ;Register retten.
- push ds
- push es
- add ch,dh ;*) Rotation muß in der letzten Zeile beginnen
- dec ch ;(und nicht in der ersten).
- test bh,1 ;Welches ist die betroffene Page?
- GetPageArrayIndex 0,si
- cmp CurVideoMode,8
- mov ds,cs:[PageSegment+si] ;DS = SEG(ConcernedPage),
- je GraphRotation1 ;Im GraphikModus andere Rotation-Routine benutzen.
- nop
- cmp ch,25 ;ACHTUNG! Durch den Befehl "ADD CH,DH" bei *)
- jb NoScreenWrap_Text ;ist möglicherweise ein ScreenWrap entstanden!
- sub ch,25
- NoScreenWrap_Text:
- DisplayAdress_Text cl,ch ;DisplayAdresse
- shl ax,1 ;mal 2 Bytes pro Char
- mov si,ax ;=> DS:SI = StartAdresse.
- mov bp,-160
- call RotateTextWindow
- jmp SHORT RotationDone1
- GraphRotation1: ;Also Graphik-Modus.
- push dx ;Dann erst noch ein weiteres Register retten.
- cmp ch,NrOfLines
- jb NoScreenWrap_Graph ;Dasselbe wie oben, nur diesmal im GraphMode.
- sub ch,NrOfLines
- NoScreenWrap_Graph:
- shl bl,1
- shl ch,1 ;BL, CH und DH in Scan-Lines umrechnen (*2),
- inc ch ;CH dabei an das UNTERE Ende der TextZeile setzen.
- shl dh,1
- DisplayAdress_Graph cl,ch
- mov si,cs:[DispStartTable+si] ;DisplayAdress
- add si,ax ; + DispStart
- and si,1FFFh ;nach Begrenzung
- mov bp,-NrOfDotsX/8 ;=> DS:SI = StartAdresse.
- mov bh,ch
- inc bh ;BH = Anz ScanLines bis zum TopOfScreen.
- call RotateBitMap ;Erste BitMap (Segment-Offset 0000h),
- call RotateBitMap ;zweite BitMap (Offset 2000h),
- call RotateBitMap ;dritte (Offset 4000h)
- call RotateBitMap ;und vierte (Offset 6000h) seperat rotieren.
- pop dx
- RotationDone1:
- pop es
- pop ds
- pop di
- pop bp ;Gerettete Register zurückholen.
- pop cx
- pop bx
- ret
- RotateWindowDown ENDP ;AX and SI destroyed.
-
- RotateTextWindow PROC NEAR
- ;BP = Byte-Distanz zur nächsten Zeile (+ oder - 160 Bytes, je nach Richtung)
- ;DS:SI = Adresse der ersten zu bearbeitenden Zeile.
- ;BL = Um wie viele Zeilen,
- ;DL = wie viele Zeichen pro Zeile, und
- ;DH = wie viele Zeilen rotiert werden sollen.
- cld
- mov di,cs
- mov es,di
- mov di,OFFSET RotateBuffer ;[ES:DI] = RotateBuffer.
- mov al,bl ;AL = MoveLine-Count.
- mov ch,0
- push si ;"StartAdresse" für später merken.
- NextLineIntoBuffer:
- push si
- mov cl,dl
- rep movsw
- pop si
- add si,bp
- dec al
- jnz NextLineIntoBuffer
- nop
- mov di,ds
- mov es,di
- pop di ;ES:DI = StartAdresse.
- mov al,dh
- sub al,bl ;AL = MoveLine-Count.
- NextLine:
- push si
- push di
- mov cl,dl
- rep movsw
- pop di
- pop si
- add di,bp
- add si,bp
- dec al
- jnz NextLine
- nop
- mov si,cs
- mov ds,si
- mov si,OFFSET RotateBuffer ;[DS:SI] = RotateBuffer.
- mov al,bl ;AL = MoveLine-Count.
- NextLineFromBuffer:
- push di
- mov cl,dl
- rep movsw
- pop di
- add di,bp
- dec al
- jnz NextLine
- ret
- RotateTextWindow ENDP ;AX, CX, SI, DI, DS, and ES destroyed.
-
- RotateBitMap PROC NEAR
- ;BP = Byte-Distanz zur nächsten Zeile (+ oder - 90 Bytes, je nach Richtung)
- ;DS:SI = Adresse der ersten zu bearbeitenden Zeile.
- ;BH = Wie viele Scan-Lines bis zum ScreenWrap.
- ;BL = Um wie viele ScanLines,
- ;DL = wie viele Bytes pro ScanLine, und
- ;DH = wie viele ScanLines rotiert werden sollen.
- ;!!! ACHTUNG, BH muß kleiner oder gleich BL sein !!!
- cld
- push bx ;Register retten.
- push si
- mov al,bl ;AL = MoveLine-Count.
- mov di,cs
- mov es,di
- mov di,OFFSET RotateBuffer ;[ES:DI] = RotateBuffer.
- push si ;BX und "StartAdress" für später merken.
- MoveLineIntoBuffer:
- ComputeWrapPos si ;CX = Wieviele Bytes können OHNE Page-Wrap ver-
- push si ;schoben werden, AH = wieviele Bytes sind übrig.
- rep movsb ;Ersten Teil bis zum Page-Wrap verschieben,
- xor si,si ;dann Zeiger auf den Anfang der Page zurücksetzen
- mov cl,ah ;und den Rest der Zeile verschieben.
- rep movsb
- pop si
- add si,bp
- dec al ;Müssen noch Zeilen verschoben werden?
- jnz MoveLineIntoBuffer
- nop
- mov di,ds
- mov es,di
- pop di ;ES:DI = StartAdress (Dest).
- mov al,dh
- sub al,bl ;AL = MoveLine-Count.
- sub bh,bl ;BH = ScreenWrap-Count (Source).
- inc bh ;schon mal inkrementieren,
- sub si,bp
- MoveLine: ;es wird nämlich gleich wieder dekrementiert --+
- add si,bp ; !
- dec bh ; <-----+
- jnz NoScreenWrap ;Hat ein ScreenWrap stattgefunden?
- mov bh,NrOfDotsY/4-1 ;Dann neu ansetzen:
- test bp,bp ;Sind wir am UNTEREN oder am OBEREN Ende?
- js SetToBottom
- sub si,ScrSize/4 ;Am unteren? Dann auf das obere setzen und
- add di,(8000h-ScrSize)/4 ;DI für neuen DispStart korrigieren.
- jmp SHORT NoScreenWrap
- SetToBottom:
- add si,ScrSize/4 ;Am oberen? Dann auf das untere setzen und
- sub di,(8000h-ScrSize)/4 ;DI für neuen DispStart korrigieren.
- NoScreenWrap:
- and si,1FFFh
- and di,1FFFh
- ComputeWrapPos si
- test ah,ah ;Kommt in dieser SOURCE-Zeile ein Wrap vor?
- jnz NoSourceWrap
- ComputeWrapPos di ;Nicht? Dann vielleicht in dieser DEST-Zeile.
- NoSourceWrap:
- push si
- push di
- rep movsb ;Ersten Teil der Zeile (bis zum PageWrap) verschieben.
- and si,1FFFh ;Da ich nicht weiß, WELCHES der beiden IndexRegs den
- and di,1FFFh ;Wrap verursacht hat, werden einfach beide zurückgesetzt.
- mov cl,ah
- rep movsb
- pop di
- pop si
- add di,bp ;DI eine Zeile weitersetzen und
- dec al ;MoveLine-Count dekrementieren.
- jnz MoveLine
- nop
- mov si,cs
- mov ds,si
- mov si,OFFSET RotateBuffer ;[DS:SI] = RotateBuffer.
- MoveLineFromBuffer:
- ComputeWrapPos di
- push di
- rep movsb
- xor di,di
- mov cl,ah
- rep movsb
- pop di
- add di,bp
- and di,1FFFh
- dec bl
- jnz MoveLineFromBuffer
- nop
- mov cx,es
- add cx,200h ;DS schon mal auf die nächste BitMap setzen
- mov ds,cx
- pop si
- pop bx ;und Register wieder herstellen.
- ret
- RotateBitMap ENDP ;AX, CX, DI, and ES destroyed, DS:=DS+0200h.
-
- ClearWindow PROC NEAR ;BL=NewAttrib, BH=PageNr, CX=Window Start, DX=WinSize
- push di ;Register retten.
- test bh,1 ;In welcher Page soll gelöscht werden?
- GetPageArrayIndex OFFSET(CursPosTable),di
- push [di] ;Entsprechende CursorPos pushen und
- mov [di],cx ;statt dessen die Pos des Windows dorthin schreiben.
- mov cl,dl ;"NrOfChars" setzen.
- mov ch,0
- ClearNextLine:
- cmp dh,0 ;War das die letzte Zeile?
- je ClearDone ;Dann fertig.
- mov al,' '
- mov ah,CurVideoMode ;(AH muß den momentanen VideoMode enthalten)
- call WriteAttrChar ;Sonst eine Zeile mit Spaces füllen (=löschen).
- inc byte ptr [di+1] ;CursorPos.YPos im BiosSegment eine Zeile
- dec dh ;weitersetzen und ZeilenCount dekrementieren.
- jmp SHORT ClearNextLine ;Nächste Zeile bearbeiten.
- ClearDone:
- pop [di] ;Alte CursorPos wieder herstellen,
- pop di ;Register zurückholen
- ret ;und zurück zum Caller.
- ClearWindow ENDP ;AX, CX, DX, and SI destroyed.
-
- ComputeDotAdress PROC NEAR ;CX=XPos, DX=YPos, ZF=PageNr.
- GetPageArrayIndex 0,bx
- mov es,cs:[PageSegment+bx] ;Entsprechende Werte für
- mov bx,cs:[DispStartTable+bx] ;Seg und Ofs dieser Page holen.
- ror dx,1 ;YPos von Dots in Scans
- ror dx,1 ;(je 4 Punkte hoch) umrechnen.
- mov al,90 ;ScanNr mal 90 Bytes per Scan
- mul dl ;ergibt den Offset der Zeile
- add bx,ax ;(relativ zum DispStart).
- mov ax,cx
- shr ax,1 ;Jetzt noch den Byte-Offset
- shr ax,1 ;innerhalb der Zeile berechnen
- shr ax,1 ;(XPos SHR 3)
- add bx,ax ;und ebenfalls dazuaddieren.
- and bh,1Fh ;BX auf eine BitMap begrenzen!
- shr dh,1 ;Jetzt noch die entsprechende BitMap
- or bh,dh ;über ihre BasisAdresse selektieren.
- and cl,7
- ret
- ComputeDotAdress ENDP ;ES:BX=DotAdress, CL=BitNr. AX and DX destroyed.
-
- HandleBeep PROC NEAR ;BH=PageNr, [DS:SI]=CursorPos im BiosSegment.
- cmp bh,ActivePage ;Soll es in einer anderen als der aktiven
- jne BeepDone ;Page piepen? Dann lassen wir das lieber.
- mov ah,14 ;Function "TeletypeOut"
- mov al,7 ;mit AL=Bel
- pushf ;des alten (!)
- call dword ptr cs:[SavedInt10Vec] ;INT10-Handlers aufrufen.
- BeepDone:
- mov ax,[si]
- ret
- HandleBeep ENDP ;AX=neue CursorPos.
-
- HandleReturn PROC NEAR ;BH=PageNr, [DS:SI]=CursorPos im BiosSegment.
- mov ax,[si]
- mov al,0
- mov [si],ax
- ret
- HandleReturn ENDP ;AX=neue CursorPos.
-
- HandleLinefeed PROC NEAR ;BH=PageNr, [DS:SI]=CursorPos im BiosSegment.
- mov ax,[si] ;CursorPos holen und testen:
- cmp ah,LastTextLine ;Sind wir auf der letzten Zeile?
- je ScrollOneLineUp ;Dann ist eine extra-Behandlung nötig,
- inc ah ;sonst Cursor einfach eine Zeile
- mov [si],ax ;tiefer setzen, neue Pos
- ret
- ScrollOneLineUp:
- push ax
- push bx
- push cx
- push dx
- mov ah,CurVideoMode ;In der betroffenen DisplayPage das
- call ReadAttrChar ;Attrib des Zeichens an der CursorPos
- mov bl,ah ;holen und mit diesem Attribute
- mov al,1 ;die eine Zeile füllen,
- mov ah,CurVideoMode ;die entsteht,
- mov cx,0 ;wenn das Window oben links
- mov dl,byte ptr NrOfColumns ;bis ganz unten rechts
- dec dl ;(also der ganze Screen)
- mov dh,LastTextLine ;der betroffenen Page
- call ScrollPartOfScreenUp ;hochgescrolled wird.
- pop dx
- pop cx ;Register wieder herstellen
- pop bx
- pop ax
- ret ;und fertig.
- HandleLinefeed ENDP ;AX=neue CursorPos, SI destroyed.
-
- HandleBackspace PROC NEAR ;BH=PageNr, [DS:SI]=CursorPos im BiosSegment.
- mov ax,[si] ;Wo steht der Cursor z.Z.?
- cmp al,0 ;Auf der ersten Spalte und soll ein Zeichen zurück?
- IF BsLineUp
- je BackspaceDone ;Dann BackSpace ignorieren
- ELSE
- jne SetCursorBack
- cmp ah,0 ;oder,
- je BackspaceDone ;wenn Cursor nicht schon in Home-Position,
- dec ah ;eine Zeile höher
- mov al,byte ptr NrOfColumns ;auf das letzte Zeichen setzen.
- SetCursorBack:
- ENDIF
- dec al
- mov [si],ax ;Neue Cursor-Position speichern.
- BackspaceDone:
- ret
- HandleBackspace ENDP ;AX=neue CursorPos.
-
- WriteOneChar PROC NEAR ;AL=Char, BL=Attrib, BH=PageNr, [DS:SI]=CursorPos.
- cmp al,7
- je HandleBeep ;Bel,
- cmp al,13
- je HandleReturn ;Cr,
- cmp al,10
- je HandleLineFeed ;Lf und
- cmp al,8
- je HandleBackspace ;Bs separat behandeln,
- push cx ;alle anderen Zeichen
- push si ;als 'Printables' verarbeiten:
- mov cx,1 ;Ein Zeichen
- mov ah,CurVideoMode ;im aktuellen Mode
- call WriteAttrChar ;mit Attribute schreiben,
- pop si
- pop cx
- mov ax,[si] ;Wo steht der Cursor JETZT?
- inc al
- mov [si],ax ;Ein Zeichen weiter nach rechts setzen
- cmp al,byte ptr NrOfColumns ;und testen: Sind wir noch innerhalb
- jne WriteOneCharDone ;der Zeile? Dann ist's ja gut.
- call HandleReturn ;Sonst Cursor auf den Anfang
- call HandleLineFeed ;der nächsten Zeile setzen.
- WriteOneCharDone:
- ret ;Achtung! CursorPos wird NICHT an den 6845 geschickt!
- WriteOneChar ENDP ;AX=neue CursorPos, SI destroyed.
-
- SendStringToPrinter PROC NEAR ;[CS:SI]=PascalString.
- cld
- lods byte ptr cs:[si] ;Längenbyte des
- mov cl,al ;PascalStrings
- mov ch,0 ;nach CX holen.
- clc
- jcxz SendStringDone ;String leer? Dann fertig, mit C=0 zurück.
- mov dl,cs:PrinterNr
- mov dh,0 ;Sonst PrinterNummer nach DX
- SendByteLoop:
- lods byte ptr cs:[si] ;und in einer Schleife ein Zeichen holen,
- mov ah,0
- int 17h ;mittels Bios ausgeben,
- and ah,00111001b ;Status testen (OutOfPaper=False,
- cmp ah,00010000b ;Selected=True, IOError=False und TimeOut=False?)
- loope SendByteLoop ;Status ok? Dann nächstes Zeichen (falls vorhanden).
- clc ;Schleife abgebrochen, woran lag's denn?
- jz SendStringDone ;Bloß Stringende erreicht? Dann war's erfolgreich.
- stc ;Sonst lag es wohl am Status. Mit C=1 zurück.
- SendStringDone:
- ret
- SendStringToPrinter ENDP ;AX, CX, DX, and SI destroyed. C=1 wenn Fehler.
-
- PrintTextScreen PROC NEAR ;AL=ActivePage
- push bx
- push cx
- push dx ;Register retten.
- push si
- test al,1 ;Welche Page ist denn aktiv?
- GetPageArrayIndex 0,si ;Diese Page soll auch gedruckt werden.
- push [CursPosTable+si] ;Momentane CursorPos merken!
- mov ds,cs:[PageSegment+si]
- mov si,OFFSET PrnTextInit ;TextHardcopy-InitString
- call SendStringToPrinter ;zum Drucker schicken.
- jc PrintTextFinished ;Fehler? => Hardcopy abbrechen.
- mov si,0 ;[DS:SI]=Active Page.
- mov bx,0 ;LineCounter initialisieren.
- PrintTextLineLoop:
- mov ax,bx ;Cursor auf den Anfang der
- call UpdateCursorPos ;z.Z. gedruckten Zeile setzen.
- mov cx,80
- mov dl,0
- mov dh,cs:PrinterNr ;DX=Printer-Number.
- cld
- PrintTextCharLoop:
- lods byte ptr ds:[si] ;Erstes Zeichen der Zeile holen,
- inc si ;(Attribute überspringen)
- mov ah,0
- int 17h ;und an Drucker schicken.
- and ah,00111001b
- cmp ah,00010000b
- loope PrintTextCharLoop ;Solange, bis Zeile zuende oder Fehler.
- jnz PrintTextFinished ;Fehler (Drucker offline oder so)?
- cmp cs:PrtScrActive,True ;Oder PrtScr durch erneuten Tastendruck
- jne PrintTextFinished ;abgebrochen? Dann vorzeitig beenden.
- inc bh
- cmp bh,25
- jne PrintTextLineLoop
- PrintTextFinished:
- mov si,OFFSET PrnTextExit ;TextHardcopy-ExitString
- call SendStringToPrinter ;zum Drucker schicken.
- pop ax ;Alte CursorPos wieder holen,
- pop si
- pop dx ;Register wieder herstellen und
- pop cx
- pop bx
- call UpdateCursorPos ;Cursor auf seine alte Position zurücksetzen.
- ret
- PrintTextScreen ENDP ;AX and DS destroyed.
-
- PrintGraphScreen PROC NEAR ;AL=ActivePage
- push bx
- push cx
- push dx ;Register retten.
- push si
- push di
- test al,1
- GetPageArrayIndex 0,di ;Welche Page soll den gedruckt werden?
- mov ds,cs:[PageSegment+di]
- mov di,cs:[DispStartTable+di] ;[DS:DI]=DispStart dieser Page.
- mov si,OFFSET PrnGraphInit ;GraphHardcopy-InitString
- call SendStringToPrinter ;zum Drucker schicken.
- jc PrintGraphFinished ;Fehler? => Hardcopy abbrechen.
- mov bl,NrOfLines ;LineCounter initialisieren.
- PrintGraphLineLoop:
- mov si,OFFSET PrnLineStart
- call SendStringToPrinter ;LineStart-String zum Drucker schicken.
- mov cx,NrOfChars ;Counter für "CharsPerLine" setzen.
- PrintGraphCharLoop:
- cld
- push cx ;CharCount merken.
- mov bh,2 ;Jetzt werden 2 Scans (= 8 Dots = 1 Zeichen)
- ConvertNextByte:
- mov si,OFFSET PrtScr8x8Buffer ;konvertiert und in den Buffer übertragen:
- inc si ;(LängenByte überspringen)
- mov al,[di] ;Ein Byte aus dem Bildschirmspeicher holen,
- xor al,0FFh ;invertieren (für Druck schwarz auf weiß)
- mov cx,8 ;und die 8 Bits einzeln verteilen:
- ConvertNextBit:
- shl al,1 ;MSB des Graphik-Bytes in den Carry schieben
- rcl byte ptr cs:[si],1 ;und von dort in das erste Drucker-Byte,
- inc si ;dann nächstes Bit in das nächste Byte.
- loop ConvertNextBit
- add di,2000h ;Jetzt ist das nächste GraphikByte dran, das
- jno ConvertNextByte ;liegt eine Zeile tiefer in der nächsten BitMap,
- add di,NrOfChars ;aber nach 4 BitMaps einen Scan tiefer setzen.
- and di,1FFFh ;Dabei den PageWrap beachten.
- dec bh
- jnz ConvertNextByte ;Schon beide Scans bearbeitet?
- mov si,OFFSET PrtScr8x8Buffer ;Dann die konvertierten 8 Bytes
- call SendStringToPrinter ;jetzt zum Drucker schicken.
- add di,-2*NrOfChars+1 ;ScreenPointer auf das nächste Zeichen setzen,
- pop cx ;CharCount wieder holen
- loop PrintGraphCharLoop ;und nächstes Zeichen bearbeiten.
- mov si,OFFSET PrnLineEnd
- call SendStringToPrinter ;LineEnd-String zum Drucker schicken.
- jc PrintGraphFinished ;Fehler (z.B. Printer Offline)
- cmp cs:PrtScrActive,True ;oder PrtScr durch erneuten Tasten-
- jne PrintGraphFinished ;druck abgebrochen? Dann beenden.
- add di,NrOfChars ;Sonst ScreenPointer eine Zeile tiefer setzen,
- dec bl ;ZeilenCount dekrementieren
- jnz PrintGraphLineLoop ;und nächste Zeile drucken.
- PrintGraphFinished:
- mov si,OFFSET PrnGraphExit ;GraphHardcopy-ExitString
- call SendStringToPrinter ;zum Drucker schicken.
- pop di
- pop si
- pop dx ;Register wieder herstellen.
- pop cx
- pop bx
- ret
- PrintGraphScreen ENDP ;AX and DS destroyed.