; Entry for Hugi size coding compo #17
;
; By Ruud v Gessel
;
; Thanx all for any feedback or suggestions and the competition
;
; Thanx Claus and Ben for making this compo possible.
;
; Credits of course to TAD for his nice hex->asc routine
;
; And INT-E, up til the 98 bytes version I used a CP/M call to close
; the FCB, nice trick I remembered u using in one of the previous compo's
; Though it saved 2 bytes when I finally got rid of the "JE 5" ;-)
;
;
; PS: Ben, I still hate it that you made me close that FCB, it simply
;          isn't messy enough for me to close things ;-)
;          (No offence, actually I liked the challenge)
;
; Have fun
; Ruud
;

by EQU BYTE PTR

                    .MODEL    TINY
                    .386

                    .CODE
                    
                    ORG       100h

Start:              xchg      ax,bp               ;Address counter
                    inc       bx                  ;Handle to CON out
                    xchg      ax,di               ;9xx safe spot first stosb

FCBCall:            mov       cl,5ch              ;Enough spaces, FCB
                    push      cx                  ;FCB pointer
                    rep stosb                     ;Fill output buffer

Marker              EQU 70h  ;$-1-97h (97h is output buffer)

                    mov       cl,10h              ;Nice record length
                                                  ;Opcode ends with 10h !!
                    pop       dx      ;dx=5ch, needed 1 byte between 10h,02h
                    add       ah,cl               ;AH=function, opcode < 10h!!
                    mov       [bx+69h],cx         ;Set FCB blocksize=16

In_Out:             int       21h                 ;Open, Close, Write or Read
                    mov       dl,97h              ;Output buffer
                    mov       di,dx               ;Output buffer
                    push      bp                  ;For MSB of address
                    push      7fh                 ;Use stack so PF is right
                    jz        FCBCall             ;Close FCB (SP=OK, push 7f)
                    mov       ax,0420h            ;Second always readblock
                    pop       si                  ;Si points to DTA - 1
                    inc       sp                  ; :-) Check it out
                                  ;2 times "PUSH BP", "INC SP" leaves MSB:MSB
                    jnp       FCBCall             ;Read FCB if second time

@First3:            jnc       @AddrByte           ;Jump for address byte
                    inc       di                  ;2 spaces after address
                    
                    ; Stuff the raw data byte or dot followed by 0dh
                    ; and change space to dash if needed

@DataByte:          push      ax                  ;Data byte on stack
@6:                 test      cl,dl               ;Time for a dash? DL=97h
                    mov       ah,0dh              ;0dh comes in handy
                    jne       @5                  ;Nope, still space
                    or        [di],ah             ;Space becomes dash
@5:                 mov       [si+4fh],ax         ;Raw byte followed by 0dh
                    inc       ax                  ;This must be less than 21h
                    cmp       al,20h              ;Check if we need DOT
                    mov       al,0fah             ;In case we need dot
                    jbe       @6                  ;So stuff dot if wrong char
                    inc       di                  ;One up
@AddrByte:          pop       ax                  ;ax=data/address info

                    ; Output hex byte and change trailing space to 0ah

                    aam       10h                 ;Split al in two nibbles
@Nib:               xchg      al,ah               ;High first, low second
                    cmp       al,0ah              ;CF for decimal digit
                                                  ; ALPHA   NUM
                    sbb       al,69h              ;-69h or -6ah
                    das               ;AF for num :-60h or -66h
                    stosb             ;Adds up to :+37h or +30h
                    add       by [si+51h],0f5h    ;Nicely ends up at 0ah
                    jpo       @Nib                ;Loop, 2 bytes

                    lodsb                         ;Get data byte
                    
                    cmp       [di+Marker],cl      ;Check address or byte 0
                    jbe       @First3             ;Jump for address or byte 0

                    ;Sadly we can't use "dec [bx+6bh]" for 2000, NT or DOS 6

                    inc       bp                  ;Address one up
                    cmp       bp,[bx+6bh]         ;Last byte ? (keep the ZF!)
                    loopne    @DataByte           ;Nope, go loop (16 times)
                    push      bp                  ;Needed for LSB of address
                    mov       ah,40h              ;For output to file
                    lea       cx,[si-46h]         ;Line size depends on si
                    jbe       In_Out              ;Output string and read next
                    int       20h                 ;Boohoo expensive return..

                    END       Start

