home *** CD-ROM | disk | FTP | other *** search
- ; Programm: 136color.asm
- ; Autor: Ingo Kubbilun
- ; (c)1990 DMV Widuch GmbH & Co. KG
-
- ; Implementierung neuer Grafikroutinen
- ; zur Bereitstellung von 136 Farben
- ; gleichzeitig für die EGA-Modi 640x200,
- ; 640x350, 640x480 und 800x600 in das
- ; BIOS durch Halbierung der X-Auflösung
- ;
- ; Programm installiert sich resident im
- ; Speicher und kann durch nochmaligen
- ; Aufruf wieder entfernt werden.
-
- CODE SEGMENT BYTE
-
- ASSUME CS:CODE,DS:CODE
-
- ; EQU's
-
- FBUFADR EQU INIT
- TSENG EQU 29H
- PARADISE EQU 58H
- VIDEO7 EQU 62H
- VMODE_800x600 EQU -1
- REGAX EQU [BP+10H]
-
- ; Sprung zur Installierung
-
- ORG 0100H
-
- START: JMP INIT
- ;Sprung zur Installierungs-Sequenz
-
- ; Daten- und Variablenbereich
-
- ENVSEG DW ?
- MSG1 DB 0DH,0AH,"136COLOR V1.0 gel"
- DB "aden und aktiviert...",0DH
- DB 0AH,"$"
- MSG2 DB 0DH,0AH,"136COLOR V1.0 aus"
- DB " Speicher entfernt...",0DH
- DB 0AH,"$"
- MSG3 DB 0DH,0AH,"136COLOR V1.0 kon"
- DB "nte nicht entfernt werden"
- DB "...",0DH,0AH,"$"
- OLDINT_10H DW ?,?
- OLDSS DW ?
- OLDSP DW ?
- MAXX DW ?
- MAXY DW ?
- GETPOS_ADR DW ?
- MODE_FLAG DB ?
- CRT_MODE DB ?
- ACTIVE_FLAG DB ?
- COLOR DW ?
- SCR_OFFSET DW ?
-
- ; Farbtabelle
-
- COLTAB DB 00H,01H,02H,03H,04H,05H,06H
- DB 07H,08H,09H,0AH,0BH,0CH,0DH
- DB 0EH,0FH,11H,12H,13H,14H,15H
- DB 16H,17H,18H,19H,1AH,1BH,1CH
- DB 1DH,1EH,1FH,22H,23H,24H,25H
- DB 26H,27H,28H,29H,2AH,2BH,2CH
- DB 2DH,2EH,2FH,33H,34H,35H,36H
- DB 37H,38H,39H,3AH,3BH,3CH,3DH
- DB 3EH,3FH,44H,45H,46H,47H,48H
- DB 49H,4AH,4BH,4CH,4DH,4EH,4FH
- DB 55H,56H,57H,58H,59H,5AH,5BH
- DB 5CH,5DH,5EH,5FH,66H,67H,68H
- DB 69H,6AH,6BH,6CH,6DH,6EH,6FH
- DB 77H,78H,79H,7AH,7BH,7CH,7DH
- DB 7EH,7FH,88H,89H,8AH,8BH,8CH
- DB 8DH,8EH,8FH,99H,9AH,9BH,9CH
- DB 9DH,9EH,9FH,0AAH,0ABH,0ACH
- DB 0ADH,0AEH,0AFH,0BBH,0BCH
- DB 0BDH,0BEH,0BFH,0CCH,0CDH
- DB 0CEH,0CFH,0DDH,0DEH,0DFH
- DB 0EEH,0EFH,0FFH
-
- ; Neuer Interrupt-Handler 10H
-
- KEYWORD DB "136COLOR"
-
- NEWINT_10H PROC FAR
- OR AH,AH
- ;Funktion "Bildschirmmodus setzen" ?
- JNZ TEST1
- ;wenn nicht => nächste Fkt. testen
- CALL SET_KOOR
- ;prüfen, ob einer der vier Modi und
- ;evtl. max. Bildschirmausdeh. setzen
- JMP SHORT OLDINT_CALL
- ;Sprung ins BIOS, um Modus zu setzen
- TEST1: CMP AH,0FFH
- ;Funktion "Prog. installiert" ?
- JNZ TEST2
- ;wenn nicht => nächste Fkt. testen
- MOV AL,0AAH
- ;anzeigen, daß Programm installiert
- IRET
- ;zurück zum Aufrufer
- TEST2: CMP AH,0FEH
- ;Funktion "Aktivieren/Deaktivieren"?
- JNZ TEST3
- ;wenn nicht => nächste Fkt. testen
- AND AL,01H
- ;nur 0 und 1 erlaubt
- MOV CS:ACTIVE_FLAG,AL
- ;Aktivierungs-Flag setzen
- IRET
- ;zurück zum Aufrufer
- TEST3: CMP CS:MODE_FLAG,00H
- ;aktueller Modus unbekannt ?
- JNZ FKT_OK
- ;wenn nicht => aufzurufene Funktion
- ;ausführen
- OLDINT_CALL: JMP DWORD PTR CS:OLDINT_10H
- ;Sprung zur ursprüngl. BIOS-Funktion
- FKT_OK: CMP CS:ACTIVE_FLAG,00H
- ;Erweiterung nicht aktiviert ?
- JZ OLDINT_CALL
- ;dann Sprung ins BIOS
- CMP AH,0CH
- ;Funktion "Punkt setzen" ?
- JZ FKT_CALL
- ;dann Ok.
- CMP AH,0DH
- ;Funktion "Punkt lesen" ?
- JNZ OLDINT_CALL
- ;wenn nicht => Sprung ins BIOS
- FKT_CALL: MOV CS:OLDSS,SS
- ;Stacksegment speichern
- MOV CS:OLDSP,SP
- ;Stackpointer speichern
- PUSH CS
- POP SS
- ;Stacksegment=Codesegment
- MOV SP,0100H
- PUSH BP
- PUSH AX
- MOV BP,SP
- ;Basepointer zeigt auf AX
- PUSH DX
- PUSH DS
- ;Datensegment sichern
- PUSH ES
- ;Extrasegment sichern
- PUSH CS
- POP DS
- ;Datensegment=Codesegment
- PUSH AX
- PUSH DX
- ;Register AX und DX auf Stapel
- MOV DX,03CEH
- MOV AX,0205H
- OUT DX,AX
- ;Grafikmodi für EGA-Karte setzen:
- ;Lesemodus 0 / Schreibmodus 2
- AND BH,03H
- ;Seitenangabe zwischen 0 und 3
- MOV SCR_OFFSET,0000H
- ;Offset für Zugriff auf Seiten=0000H
- OR BH,BH
- ;Seitennummer = 0 ?
- JZ SCROFF_OK
- ;dann ist das Offset in Ordnung
- CMP CRT_MODE,0EH
- ;Modus 640x200 ?
- JNZ SCROFF_640x350
- ;nein ? => Seitenoffset für Modus
- ;640x350 setzen
- MOV AL,BH
- XOR AH,AH
- ;Seitennummer nach AX
- MOV DX,4000H
- ;Länge einer Seite nach DX
- MUL DX
- ;SCR_OFFSET berechnen
- MOV SCR_OFFSET,AX
- ;und speichern
- JMP SHORT SCROFF_OK
- ;Sprung zur Ausführungssequenz
- SCROFF_640x350: MOV SCR_OFFSET,8000H
- ;Offset für Seite 1 setzen
- SCROFF_OK: MOV AX,0A000H
- MOV ES,AX
- ;Extrasegment als Videosegment inst.
- POP DX
- POP AX
- ;Register DX und AX restaurieren
- CMP AH,0CH
- ;Funktion "Punkt setzen" ?
- JNZ CHK_FKT1
- ;wenn nicht => nächste Fkt. prüfen
- CALL PUT_PIXEL
- ;sonst Punkt setzen
- JMP SHORT EXIT_NEWINT_10H
- ;und zurück zum Aufrufer
- CHK_FKT1: CALL GET_PIXEL
- ;Funktion "Punkt lesen"
- EXIT_NEWINT_10H: MOV DX,03CEH
- MOV AX,0005H
- OUT DX,AX
- ;alten Lese-/Schreibmodus setzen
- MOV AX,0FF08H
- OUT DX,AX
- ;Bit Mask Register installieren
- POP ES
- POP DS
- POP DX
- POP AX
- POP BP
- ;alle Register vom Stapel
- MOV SS,CS:OLDSS
- ;altes Stacksegment
- MOV SP,CS:OLDSP
- ;und alten Stackpointer installieren
- IRET
- ;zurück zum Aufrufer
- NEWINT_10H ENDP
-
- ;Funktion: maximale Bildschirmausdehnung
- ; für spezifischen Bildschirm-
- ; modus für Grafikroutinen setzen
- ;Eingabe : AL = Bildschirmmodus
- ;Ausgabe : [MAXX], [MAXY] und [GETPOS_ADR]
- ; erhalten Werte, wenn AL =
- ; 0EH,10H,12H oder VMODE_800x600
- ; [MODE_FLAG]=1, wenn einer der
- ; o.g. Modi
- ; [CRT_MODE] = akt. Bildschirmm.
-
-
- SET_KOOR PROC NEAR
- PUSH DS
- PUSH CS
- POP DS
- MOV CRT_MODE,AL
- ;akt. Bildschirmmodus speichern
- CMP AL,0EH
- ;Modus 640x200 ?
- JNZ MODE1
- ;wenn nicht => nächsten Modus testen
- MOV MAXX,320
- MOV MAXY,200
- ;max. Bildschirmausdehnung eintragen
- MOV GETPOS_ADR,OFFSET GPOS_320
- ;Adr. der Routine zur Berechnung der
- ;Bildschirmposition eintragen
- JMP SHORT MODE_OK
- ;Modus bestätigen
- MODE1: CMP AL,10H
- ;Modus 640x350 ?
- JNZ MODE2
- MOV MAXX,320
- MOV MAXY,350
- MOV GETPOS_ADR,OFFSET GPOS_320
- JMP SHORT MODE_OK
- MODE2: CMP AL,12H
- ;Modus 640x480 ?
- JNZ MODE3
- MOV MAXX,320
- MOV MAXY,480
- MOV GETPOS_ADR,OFFSET GPOS_320
- JMP SHORT MODE_OK
- MODE3: CMP AL,VMODE_800x600
- ;Modus 800x600 ?
- JNZ EXIT_SET_KOOR
- ;wenn nicht => unbekannter Modus
- MOV MAXX,400
- MOV MAXY,600
- MOV GETPOS_ADR,OFFSET GPOS_400
- MODE_OK: MOV MODE_FLAG,01H
- ;"Bekannter Modus" anzeigen
- POP DS
- RET
- ;zurück zum Aufrufer
- EXIT_SET_KOOR: MOV MODE_FLAG,00H
- ;"Unbekannter Modus" anzeigen
- MOV ACTIVE_FLAG,00H
- ;erweiterte Funktionen deaktivieren
- POP DS
- RET
- ;und zurück zum Aufrufer
- SET_KOOR ENDP
-
- ;Funktion: Zu einer Farbnummer gehörenden
- ; Farbwert aus COLTAB auslesen
- ;Eingabe : AL = Farbe (0-135)
- ; DX = Y-Position
- ;Ausgabe : [COLOR] = linker und rechter
- ; Farbwert
-
- GET_COLOR PROC NEAR
- PUSH BX
- MOV BL,AL
- ;Farbnummer nach BL
- XOR BH,BH
- MOV AL,[COLTAB+BX]
- ;Farbwert auslesen
- POP BX
- MOV AH,AL
- ;Farbwert nach AH kopieren
- AND AX,0F00FH
- ;oberen Farbwert in AH, bzw. unteren
- ;Farbwert in AL ausmaskieren
- MOV CL,04H
- SHR AH,CL
- ;oberen Farbwert in unteren vier Bit
- ;schieben
- RCR DX,1
- ;unteres Bit der Y-Position ins
- ;Carry-Flag
- JNC GCOLOR_OK
- ;wenn Y-Position gerade => Farbe Ok.
- XCHG AH,AL
- ;sonst linken und rechten Farbwert
- ;vertauschen
- GCOLOR_OK: MOV COLOR,AX
- ;beide Farbwerte abspeichern
- RET
- ;und zurück zum Aufrufer
- GET_COLOR ENDP
-
- ;Funktion: Schnelles Berechnen der Bild-
- ; adresse zu einem Punkt für die
- ; Modi 320x200, 320x350, 320x480
- ;Eingabe : AL = Farbe (0-135)
- ; CX = X-Position
- ; DX = Y-Position
- ;Ausgabe : BX = Bildschirmadresse
-
- GPOS_320 PROC NEAR
- PUSH AX
- PUSH DX
- PUSH CX
- ;Farbe, X- und Y-Position auf Stapel
- MOV BX,DX
- ;Y-Position nach BX
- MOV CL,06H
- SHL BX,CL
- ;mit 64 multiplizieren
- ADD BX,DX
- ADD BX,DX
- ADD BX,DX
- ADD BX,DX
- ADD BX,DX
- ADD BX,DX
- ADD BX,DX
- ADD BX,DX
- ADD BX,DX
- ADD BX,DX
- ADD BX,DX
- ADD BX,DX
- ADD BX,DX
- ADD BX,DX
- ADD BX,DX
- ADD BX,DX
- ;Y-Position 16x aufaddieren
- ;=> Multiplikation mit 80 !
- POP CX
- PUSH CX
- ;X-Position nach CX holen
- SHR CX,1
- SHR CX,1
- ;durch 4 dividieren
- ADD BX,CX
- ;und zur Bildschirmadr. aufaddieren
- ADD BX,SCR_OFFSET
- ;Screenoffset (für Seiten) aufadd.
- CALL GET_COLOR
- ;Farbwert aus Farbe in AL berechnen
- POP CX
- POP DX
- POP AX
- ;alle Register restaurieren
- RET
- ;und zurück zum Aufrufer
- GPOS_320 ENDP
-
- ;Funktion: Schnelles Berechnen der Bild-
- ; adresse zu einem Punkt für den
- ; Modus 400x600
- ;Eingabe : AL = Farbe (0-135)
- ; CX = X-Position
- ; DX = Y-Position
- ;Ausgabe : BX = Bildschirmadresse
-
- GPOS_400 PROC NEAR
- PUSH AX
- PUSH DX
- PUSH CX
- ;Farbe, X- und Y-Position auf Stapel
- MOV BX,DX
- ;Y-Position nach BX
- MOV CX,07H
- SHL BX,CL
- ;mit 128 multiplizieren
- SUBLOOP: SUB BX,DX
- SUB BX,DX
- SUB BX,DX
- SUB BX,DX
- LOOP SUBLOOP
- ;Y-Position 28x subtrahieren
- ;=> Multiplikation mit 100 !
- POP CX
- PUSH CX
- ;X-Position nach CX holen
- SHR CX,1
- SHR CX,1
- ;durch 4 dividieren
- ADD BX,CX
- ;und zur Bildschirmadr. aufaddieren
- ADD BX,SCR_OFFSET
- ;Screenoffset (für Seiten) aufadd.
- CALL GET_COLOR
- ;Farbwert aus Farbe in AL berechnen
- POP CX
- POP DX
- POP AX
- ;alle Register restaurieren
- RET
- ;und zurück zum Aufrufer
- GPOS_400 ENDP
-
- ; Neue INT 10H-Funktionen
-
- ;Funktion: Routine zum Setzen eines Punk-
- ; tes durch Beschreiben der EGA-
- ; Karte
- ;Eingabe : CX = X-Position
- ; DX = Y-Position
- ; AL = Farbnummer (auf Stack)
- ;Ausgabe : keine
-
- PUT_PIXEL PROC NEAR
- MOV AL,[BP]
- ;Farbnummer holen
- CMP CX,MAXX
- ;X-Position > Bildschirmausdehnung ?
- JAE END_PUTPIX
- ;dann keinen Punkt setzen
- CMP DX,MAXY
- ;Y-Position > Bildschirmausdehnung ?
- JAE END_PUTPIX
- ;dann keinen Punkt setzen
- CMP AL,87H
- ;Farbnummer zu groß ?
- JA END_PUTPIX
- ;dann keinen Punkt setzen
- PUSH AX
- PUSH BX
- PUSH CX
- PUSH DX
- ;Register auf Stapel
- PUSH CX
- ;X-Position auf Stapel
- CALL GETPOS_ADR
- ;Bildschirmadresse berechnen
- MOV AL,ES:[BX]
- ;Latch Register laden
- MOV DX,03CEH
- ;Graphics Controller Adresse nach DX
- POP CX
- ;X-Position nach CX
- SHL CX,1
- ;mit 2 multiplizieren
- AND CL,07H
- ;Bits 0-7 ausmaskieren
- PUSH CX
- ;Maske auf Stapel
- MOV AX,8008H
- ;Defaultmaske und Nr. des Bit Mask
- ;Registers (08H) nach AX
- SHR AH,CL
- ;Maske für linken Punkt berechnen
- OUT DX,AX
- ;und Bit Mask Register beschreiben
- MOV AX,COLOR
- ;Farben nach AX holen
- MOV ES:[BX],AH
- ;Farbe für linken Punkt setzen
- POP CX
- ;Maske vom Stapel holen
- INC CL
- ;erhöhen => Maske für rechten Punkt
- PUSH AX
- ;Farben auf Stapel
- MOV AL,ES:[BX]
- ;Latches laden
- MOV AX,8008H
- ;Defaultmask./Bit Mask Reg. nach AX
- SHR AH,CL
- ;Maske für rechten Punkt berechnen
- OUT DX,AX
- ;und Bit Mask Register beschreiben
- POP AX
- ;Farben holen
- MOV ES:[BX],AL
- ;Farbe für rechten Punkt setzen
- POP DX
- POP CX
- POP BX
- POP AX
- ;alle Register restaurieren
- END_PUTPIX: RET
- ;und zurück zum Aufrufer
- PUT_PIXEL ENDP
-
- ;Funktion: Routine zum Lesen eines Punktes
- ; durch Beschreiben der EGA-Karte
- ;Eingabe : CX = X-Position
- ; DX = Y-Position
- ;Ausgabe : AL = Farbe (0-135)
- ; AL = 0FFH bedeutet Farbe nicht
- ; erkannt
- ;Bemerkung: Ausgabe geschieht über Stack
-
- GET_PIXEL PROC NEAR
- CMP CX,MAXX
- ;X-Position > Bildschirmausdehnung ?
- JAE END_GETPIX
- ;dann keinen Punkt lesen
- CMP DX,MAXY
- ;Y-Position > Bildschirmausdehnung ?
- JAE END_GETPIX
- ;dann keinen Punkt lesen
- PUSH BX
- PUSH CX
- PUSH DX
- PUSH SI
- PUSH DI
- ;Register auf Stapel
- PUSH DX
- ;Y-Position auf Stapel
- PUSH CX
- ;X-Position auf Stapel
- CALL GETPOS_ADR
- ;Bildschirmadresse berechnen
- POP CX
- ;X-Position nach CX
- SHL CX,1
- ;mit 2 multiplizieren
- AND CL,07H
- ;Bits 0-7 ausmaskieren
- INC CL
- ;erhöhen, damit Bitnummern 1-8
- MOV DX,03CEH
- ;Graphics Controller Adresse nach DX
- MOV AL,04H
- OUT DX,AL
- ;Read Map Select Register wählen
- INC DX
- ;erhöhen, damit DX auf Datenregister
- ;zeigt
- MOV AL,03H
- ;Planenummer nach AL (0-3)
- MOV SI,BX
- ;Bildschirmadresse nach SI
- XOR BX,BX
- ;linker und rechter Farbwert = 0
- TLOOP: OUT DX,AL
- ;Plane selektieren
- MOV AH,ES:[SI]
- ;ein Byte aus Bildschirmspei. lesen
- SHL AH,CL
- ;Wert d. linken Punktes ins Carry
- RCL BH,1
- ;und nach BH überführen
- SHL AH,1
- ;Wert d. rechten Punktes ins Carry
- RCL BL,1
- ;und nach BL überführen
- DEC AL
- ;Planenummer erniedrigen
- JNS TLOOP
- ;Planes 3-0 bearbeiten
- POP DX
- ;Y-Position nach DX
- RCR DX,1
- ;Y-Position gerade ?
- JNC TEST_OK
- ;dann Farbwerte Ok.
- XCHG BH,BL
- ;sonst linken und rechten Farbwert
- ;vertauschen
- TEST_OK: MOV CL,04H
- SHL BH,CL
- ;linken Farbwert ins obere Nibble
- MOV AL,BL
- OR AL,BH
- ;beide Farbwerte nach AL schreiben
- MOV DI,OFFSET COLTAB
- ;Adresse der Farbtabelle nach DI
- PUSH ES
- PUSH DS
- POP ES
- MOV CX,136
- ;136 Farben möglich
- XOR AH,AH
- ;Zähler auf Null setzen
- TLOOP1: SCASB
- ;Farbwerte in AL mit Tab. vergleich.
- JZ END_TLOOP1
- ;wenn Farbwert gefunden => Ok.
- INC AH
- ;sonst Zähler erhöhen
- LOOP TLOOP1
- ;alle Farben vergleichen
- MOV AH,0FFH
- ;Wert 0FFH bedeutet Farbe nicht gef.
- END_TLOOP1: MOV AL,AH
- ;Farbnummer nach AL
- MOV [BP],AL
- ;und auf Stapel
- POP ES
- POP DI
- POP SI
- POP DX
- POP CX
- POP BX
- ;alle Register restaurieren
- RET
- ;zurück zum Aufrufer
- END_GETPIX: MOV BYTE PTR [BP],00H
- ;wenn X- bzw. Y-Position außerhalb
- ;des Bildschirms => Farbe 0 zurückg.
- RET
- ;zurück zum Aufrufer
- GET_PIXEL ENDP
-
- ; Installierung
-
- INIT: PUSH CS
- POP DS
- MOV AX,3510H
- INT 21H
- ;Interrupt-Vektor 10H lesen
- MOV DI,BX
- ;Offsetadresse nach DI
- SUB DI,08H
- ;Zeiger auf evtl. Erkennungsstring
- MOV SI,OFFSET KEYWORD
- ;Adr. des Erkennungsstrings nach SI
- MOV CX,08H
- ;Erkennungsstring ist 8 Zeichen lang
- REPZ CMPSB
- ;vergleichen
- JZ DELETE_TSR
- ;wenn Programm vorhanden => aus
- ;Speicher entfernen
- MOV OLDINT_10H,BX
- MOV OLDINT_10H+2,ES
- ;sonst alte Interrupt-Adresse spei.
- MOV AH,0FH
- INT 10H
- ;akt. Bildschirmmodus auslesen
- CALL SET_KOOR
- ;evtl. max. Bildschirmausdeh. setzen
- MOV AX,2510H
- MOV DX,OFFSET NEWINT_10H
- INT 21H
- ;neue Interruptadresse setzen
- MOV AX,CS:[002CH]
- ;Segmentadr. des Envir.-Ber. holen
- MOV ENVSEG,AX
- ;und speichern (für evtl. Freigabe)
- MOV AH,09H
- MOV DX,OFFSET MSG1
- INT 21H
- ;Meldung ausgeben
- MOV AX,3100H
- MOV DX,OFFSET INIT
- MOV CL,04H
- SHR DX,CL
- INC DX
- ;Anzahl Paragraphen berechnen
- INT 21H
- ;Programm resident machen und zurück
- ;zur DOS-Ebene
- DELETE_TSR: PUSH ES
- ;Segmentadresse des residenten Pro-
- ;gramms auf Stapel legen
- MOV ES,ES:ENVSEG
- ;Segmentadr. des Envir.-Ber. holen
- MOV AH,49H
- INT 21H
- ;Bereich freigeben
- JC ERR_DELETE_TSR
- ;erfolglos => entfernen nicht mögl.
- POP ES
- ;Segmentadresse des res. Pro. holen
- MOV AH,49H
- INT 21H
- ;Bereich freigeben
- JC ERR_DELETE_TSR1
- ;erfolglos => nicht entfernen
- PUSH DS
- ;akt. Datensegment sichern
- MOV AX,2510H
- LDS DX,DWORD PTR ES:OLDINT_10H
- ;Adr. d. ursprünglichen Int. holen
- INT 21H
- ;und einsetzen
- POP DS
- ;Datensegment restaurieren
- MOV AH,09H
- MOV DX,OFFSET MSG2
- INT 21H
- ;Meldung ausgeben
- MOV AX,4C01H
- INT 21H
- ;und zurück zur DOS-Ebene
- ;(ERRORLEVEL=1)
- ERR_DELETE_TSR: POP ES
- ;Segmentadr. d. res. Pro. holen
- ERR_DELETE_TSR1: MOV AH,09H
- MOV DX,OFFSET MSG3
- INT 21H
- ;Meldung ausgeben
- MOV AX,4C02H
- INT 21H
- ;und zurück zur DOS-Ebene
- ;(ERRORLEVEL=2)
-
- CODE ENDS
- END START