Last active
February 28, 2021 15:36
-
-
Save lynxluna/70254736054d1a136b35f7b4f54e75ce to your computer and use it in GitHub Desktop.
Open and read to stack
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
; vi: syntax=masm | |
.8086 | |
.MODEL SMALL | |
CR EQU 0DH | |
LF EQU 0AH | |
; PCX Header Structure | |
; -not used at the moment | |
PCXHEADER STRUCT | |
identifier BYTE ? | |
version BYTE ? | |
encoding BYTE ? | |
bpp BYTE ? | |
xstart WORD ? | |
ystart WORD ? | |
xend WORD ? | |
yend WORD ? | |
hres WORD ? | |
vres WORD ? | |
palette BYTE 48 DUP (?) | |
reserved BYTE ? | |
bitplanes BYTE ? | |
bpl WORD ? | |
paltype WORD ? | |
hscreen WORD ? | |
vscreen WORD ? | |
reserved2 BYTE 54 DUP (?) | |
PCXHEADER ENDS | |
; -------------- Segments who hold data ---------------------- | |
DGROUP GROUP _DATA, _BSS, _STACK | |
_DATA SEGMENT WORD PUBLIC 'DATA' | |
USAGE DB CR, LF, 'PCX2BIT - Copyright (c) 2021 Didiet Noor' | |
DB CR, LF, '----------------------------------------' | |
DB CR, LF, 'For trimming and converting 8-bit PCX to a 2-bit RAW colour' | |
DB CR, LF, CR, LF | |
DB 'USAGE: PCX2BIT [file name]', CR, LF | |
USAGELEN EQU $-USAGE | |
EXT DB 'CGA', 00H | |
ERR_FILE_NOT_FOUND DB 'DOS ERROR: File Not Found', CR, LF, '$' | |
ERR_UNKNOWN DB 'DOS ERROR: Unknown', CR, LF, '$' | |
ERR_NOT_PCX DB 'Not A PCX File!', CR, LF, '$' | |
ERR_MCB_CORRUP DB 'DOS ERROR: Memory Control Block Destroyed', CR, LF, '$' | |
ERR_INSUFFICIENT_MEM DB 'DOS ERROR: Insufficient Memory', CR, LF, '$' | |
_DATA ENDS | |
_BSS SEGMENT WORD PUBLIC 'DATA' | |
FILENAME DB 20 DUP (?) | |
TARGETFILE DB 20 DUP (?) | |
FH WORD ? | |
TFH WORD ? | |
BSSLEN EQU $-FILENAME | |
_BSS ENDS | |
_STACK SEGMENT PARA STACK 'STACK' | |
DB 1024 DUP (?) | |
_STACK ENDS | |
; I'll put text on the beginning of the code | |
; All procedures follows WATCOM C calling convention | |
_TEXT SEGMENT WORD PUBLIC USE16 'CODE' | |
; First and foremost is the nprint routine | |
; AX = pointer to the buffer to be printed | |
; DX = buffer length | |
; AX, BX, CX, DX are all changed | |
nprint PROC NEAR WATCOM_C str: PTR, length: WORD | |
ASSUME DS: DGROUP, SS: DGROUP, CS:_TEXT, ES: NOTHING | |
; AX = PTR, DX = LENGTH | |
STDOUT EQU 1 | |
XCHG AX, DX ; To make DX holds the pointer needed for INT 21H | |
MOV CX, AX ; CX = length | |
MOV BX, STDOUT ; write to stdout | |
MOV AH, 40H ; | |
INT 21H | |
RET | |
nprint ENDP | |
prints MACRO str | |
MOV AH, 09H | |
LEA DX, str | |
INT 21H | |
ENDM | |
; print usage | |
printusage MACRO | |
LEA AX, USAGE | |
MOV DX, USAGELEN | |
CALL nprint | |
ENDM | |
; setting the rest of the program free | |
; so we can allocate later | |
; INPUT ES = address of the PSP | |
; OUTPUT - | |
; CLOBBERS AX, BX, CL, FLAGS | |
; Info : SS:SP points to the SS:SP which will point to the end of the program storage | |
; Find out the length of the program to be tight-fitted | |
setfree MACRO | |
MOV BX, SS | |
MOV AX, ES | |
SUB BX, AX ; ss-es => number of paragraph from PSP to the beginning of the stack | |
MOV AX, SP | |
MOV CL, 4 | |
SHR AX, CL ; sp is in the end of the stack segment, means it's the length of the | |
; stack segment | |
ADD BX, AX | |
INC BX ; ADD ONE PARAGRAPH just in case | |
MOV AH, 4AH ; Modify allocation | |
INT 21H | |
ENDM | |
; TERMINATE PROGRAM | |
exit MACRO statuscode | |
MOV AH, 4CH | |
MOV AL, statuscode | |
INT 21H | |
ENDM | |
exitnormal MACRO | |
exit 0 | |
ENDM | |
; PARSING Command from the PSP | |
; ES: the stack segment of the PSP | |
; AX: the buffer address | |
; DX: buffer length | |
; output | |
; AX: actual length | |
; Notes: Command contains space, therefore we remove the preceding space | |
parsecommand PROC NEAR WATCOM_C buf: PTR, len: WORD | |
CMDLENGTH EQU BYTE PTR ES:[80H] | |
CMDLINE EQU ES:[81H] | |
MOV CL, CMDLENGTH | |
AND CX, 0FH | |
JNZ @@1 | |
printusage | |
exit 1 | |
@@1: | |
DEC CL | |
CMP CX, len | |
JLE @@2 | |
MOV CX, len | |
@@2: | |
LEA SI, CMDLINE | |
INC SI | |
MOV DI, buf | |
PUSH DS | |
PUSH CX | |
; Exchange DS and ES, clobbering AX | |
MOV AX, ES | |
MOV DS, AX | |
MOV AX, DGROUP | |
MOV ES, AX | |
CLD | |
REP MOVSB | |
POP AX | |
POP DS | |
RET | |
parsecommand ENDP | |
closefile PROC NEAR WATCOM_C handle: WORD | |
MOV BX, handle | |
MOV AH, 3EH | |
INT 21H | |
RET | |
closefile ENDP | |
openfile PROC NEAR WATCOM_C fname: PTR | |
MOV DX, fname | |
XOR AX, AX | |
MOV AH, 3DH | |
INT 21H | |
RET | |
openfile ENDP | |
main PROC FAR | |
MOV AX, DGROUP | |
MOV DS, AX | |
; NEEDS TO BE INVOKED BEFORE STACK SETUP | |
; can't use local variable | |
setfree | |
PUSH BP | |
MOV BP, SP | |
HEADERLENGTH EQU 80H | |
RBUFLEN EQU 40H | |
WBUFLEN EQU 40H | |
EXTRALEN EQU 10 * 2 ; 10 BYTES FOR WORD | |
STACKBOTTOM EQU HEADERLENGTH + RBUFLEN + WBUFLEN + EXTRALEN | |
SUB SP, STACKBOTTOM; Reserve space on stack | |
; LOCAL VARIABLES | |
TEMP EQU SS:[BP - STACKBOTTOM] | |
LINENUMBER EQU TEMP + 2 | |
TARGETBYTES EQU LINENUMBER + 2 | |
QC EQU TARGETBYTES + 2 | |
COLOR EQU QC + 1 | |
HEADER EQU COLOR + 1 | |
RBUF EQU HEADER + HEADERLENGTH | |
WBUF EQU RBUF + RBUFLEN | |
LEA AX, FILENAME | |
MOV DX, 19 ; reduce one | |
CALL parsecommand | |
; DONE PARSING COMMAND SET ES=DS | |
MOV TEMP, AX ; character count | |
MOV AX, DS | |
MOV ES, AX | |
LEA BX, FILENAME | |
MOV DI, TEMP | |
MOV BYTE PTR [BX + DI], 0H ; ASCIIZ | |
; target = FILENAME.CGA | |
MOV CX, TEMP | |
SUB CX, 3 | |
MOV SI, BX | |
LEA DI, TARGETFILE | |
REP MOVSB | |
LEA SI, EXT | |
MOV CX, 4 | |
REP MOVSB | |
; open file | |
LEA AX, FILENAME | |
CALL openfile | |
JC @@on_error | |
MOV FH, AX | |
MOV WORD PTR TEMP, DS | |
MOV BX, FH | |
MOV AX, SS | |
MOV DS, AX | |
; Read File, BX assigned before | |
MOV AH, 3FH | |
MOV CX, 80H | |
LEA DX, HEADER | |
INT 21H | |
MOV DS, WORD PTR TEMP | |
MOV AL, BYTE PTR HEADER | |
CMP AL, 0AH | |
JNE @@closeandexit | |
MOV AX, WORD PTR HEADER + 8 | |
MOV CX, WORD PTR HEADER + 4 | |
SUB AX, CX | |
INC AX ; source buffer = line bytes X | |
MOV DX, AX | |
MOV CL, 2 | |
SHR AX, CL ; destination byte = line bytes X / 4 | |
MOV TARGETBYTES, AX | |
MOV CX, WORD PTR HEADER + 10 | |
MOV AX, WORD PTR HEADER + 6 | |
SUB CX, AX ; line number | |
INC CX | |
MOV LINENUMBER, CX | |
MOV AX, SS | |
MOV ES, AX | |
XOR SI, SI | |
LEA DI, RBUF | |
XOR AX, AX ; ZERO OUT THE BUFFER | |
MOV CX, RBUFLEN + WBUFLEN | |
CLD | |
REP STOSB | |
MOV BX, FH | |
MOV CX, RBUFLEN | |
MOV TEMP, DS | |
MOV AX, SS | |
MOV DS, AX | |
XOR AX, AX | |
; zero count | |
MOV QC, AX | |
MOV COLOR, AX | |
LEA DI, WBUF | |
@@readmore: | |
LEA SI, RBUF | |
MOV DX, SI | |
MOV AH, 3FH | |
INT 21H | |
JC @@closeandexit | |
XOR CX, CX | |
XOR DX, DX | |
@nextbyte: | |
MOV DL, [SI] | |
CMP DL, 0C0H | |
JB @normalpixel | |
AND DL, 3FH; MORE THAN 1 PIXEL | |
INC SI | |
LODSB | |
JMP @processpixel | |
@normalpixel: | |
MOV DL, 1; 1 pixel only | |
@processpixel: | |
MOV BYTE PTR COLOR, AL | |
@nextquartet: | |
MOV CL, 6 | |
MOV CH, 0 | |
@nextshift1: | |
SHL AL, CL | |
OR CH, AL | |
CMP CL, 0 | |
JZ @storebyte | |
SUB CL, 2 | |
DEC DL | |
JZ @checkbuf | |
MOV AL, BYTE PTR COLOR | |
JMP @nextshift1 | |
@checkbuf: | |
LEA BX, [RBUF + RBUFLEN] | |
CMP SI, BX | |
JNE @nextbyte | |
JMP @readmore | |
@storebyte: | |
MOV AL, CH | |
STOSB | |
MOV AL, BYTE PTR COLOR | |
LEA BX, [WBUF + WBUFLEN] | |
CMP DI, BX | |
JNE @nextquartet | |
LEA DI, WBUF | |
JMP @nextquartet | |
MOV AX, FH | |
CALL closefile | |
JC @@on_error | |
JMP @@termnormal | |
@@closetargetandexit: | |
MOV BX, TFH | |
CALL closefile | |
@@closeandexit: | |
MOV BX, FH | |
CALL closefile | |
@@on_error: | |
CMP AX, 02H | |
JNE @@@1 | |
prints ERR_FILE_NOT_FOUND | |
JMP @@notnormal | |
@@@1: | |
CMP AX, 07H | |
JNE @@@2 | |
prints ERR_MCB_CORRUP | |
JMP @@notnormal | |
@@@2: | |
CMP AX, 08H | |
JNE @@@3 | |
prints ERR_INSUFFICIENT_MEM | |
JMP @@notnormal | |
@@@3: | |
prints ERR_UNKNOWN | |
@@notnormal: | |
MOV SP, BP | |
POP BP | |
exit 1 | |
@@termnormal: | |
MOV SP, BP | |
POP BP | |
exitnormal | |
RET | |
main ENDP | |
_TEXT ENDS | |
END main | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment