home *** CD-ROM | disk | FTP | other *** search
/ Programming Languages Suite / ProgLangD.iso / Assembly / PHOTO.ASM < prev    next >
Assembly Source File  |  1979-12-31  |  15KB  |  285 lines

  1.  
  2. INTERRUPTS      SEGMENT AT 0H   ;This is where the keyboard interrupt
  3.         ORG     9H*4            ;holds the address of its service routine
  4. KEYBOARD_INT    LABEL   WORD  
  5. INTERRUPTS      ENDS
  6.  
  7. SCREEN  SEGMENT AT 0B000H       ;A dummy segment to use as the
  8. SCREEN  ENDS                    ;Extra Segment 
  9.  
  10. ROM_BIOS_DATA   SEGMENT AT 40H  ;BIOS statuses held here, also keyboard buffer
  11.  
  12.         ORG     1AH
  13.         HEAD DW      ?                  ;Unread chars go from Head to Tail
  14.         TAIL DW      ?
  15.         BUFFER       DW      16 DUP (?)         ;The buffer itself
  16.         BUFFER_END   LABEL   WORD
  17.  
  18. ROM_BIOS_DATA   ENDS
  19.  
  20. CODE_SEG        SEGMENT
  21.         ASSUME  CS:CODE_SEG
  22.         ORG     100H            ;ORG = 100H to make this into a .COM file
  23. FIRST:  JMP     LOAD_SNAPSHOT   ;First time through jump to initialize routine
  24.  
  25.         COPY_RIGHT DB  '(C) S. HOLZNER 1985'  ;An Ascii signature
  26.         KEYS   DW   310EH,2106H,1E01H,3002H,2E03H ;A Sample: ^N,^F,^A,^B,^C
  27. ;       KEYS   DW   5 DUP(0)
  28.         FLASHED    DB      0               ;Have we flashed a screenful? 1=yes
  29.         SNAPSHOT_OFFSET      DW      0          ;Chooses 1st 250 bytes or 2nd
  30.         SCREEN_SEG_OFFSET       DW      0       ;0 for mono, 8000H for graphics
  31.         IO_CHAR         DW      ?               ;Holds addr of Put or Get_Char
  32.         FILE_SIZE       DW      0               ;Read in this many bytes
  33.         OLD_KEY_INT     LABEL   WORD
  34.         OLD_KEYBOARD_INT        DD      ?       ;Location of old kbd interrupt
  35.         FILE            DB  'A.DAT',0           ;Asciiz. Changed to B.Dat, etc.
  36.         WS_FLAG         DB      0               ;<-- Set to 1 to strip WordStar 
  37.         SNAPSHOT             DB      10000 DUP (32) ;Storage for screens
  38.  
  39. SNAP    PROC    NEAR            ;The keyboard interrupt will now come here.
  40.         ASSUME  CS:CODE_SEG
  41.         PUSH    AX              ;Save the used registers for good form
  42.         PUSH    BX
  43.         PUSH    CX
  44.         PUSH    DX
  45.         PUSH    DI
  46.         PUSH    SI
  47.         PUSH    DS
  48.         PUSH    ES
  49.         PUSHF                   ;First, call old keyboard interrupt
  50.         CALL    OLD_KEYBOARD_INT
  51.  
  52.         ASSUME  DS:ROM_BIOS_DATA        ;Examine the char just put in
  53.         MOV     BX,ROM_BIOS_DATA
  54.         MOV     DS,BX
  55.         MOV     BX,TAIL                 ;Point to current tail
  56.         CMP     BX,HEAD                 ;If at head, kbd int has deleted char
  57.         JE      IN                      ;So leave 
  58.         SUB     BX,2                    ;Point to just read in character
  59.         CMP     BX,OFFSET BUFFER        ;Did we undershoot buffer?
  60.         JAE     NO_WRAP                 ;Nope
  61.         MOV     BX,OFFSET BUFFER_END    ;Yes -- move to buffer top
  62.         SUB     BX,2                    ;Point to just read in character
  63. NO_WRAP:MOV     DX,[BX]                 ;** Typed character in DX now **
  64.         LEA     SI,KEYS                 ;Point to Keys for search
  65.         CMP     FLASHED,1               ;Should we restore screen?
  66.         JE      RESTORE                 ;Yes, jump there
  67.         CMP     DX,CS:[SI]              ;Compare to first key (Store screen)
  68.         JE      STORE                   ;So Store
  69.         ADD     SI,2                    ;Point to next key
  70.         CMP     DX,CS:[SI]              ;Second key -- should we flash screen?
  71.         JE      FLASH                   ;Yes     
  72.         MOV     CX,3                    ;No -- check for .Dat keys (A.Dat,etc)
  73.         MOV     SNAPSHOT_OFFSET,4000    ;Point to beginning of .Dats in memory
  74. TEST:   ADD     SI,2                    ;Increment to next key
  75.         CMP     DX,CS:[SI]              ;Is it right?
  76.         JE      DATS                    ;Yes, flash a .Dat file on screen
  77.         ADD     SNAPSHOT_OFFSET,2000    ;Point to next .Dat
  78.         LOOP    TEST                    ;And go back until all three are done
  79.         JMP     OUT                     ;No keys matched. Jump Out.
  80. STORE:  MOV     TAIL,BX                 ;Delete character from buffer
  81.         MOV     FLASHED,0               ;Switch Modes on Flashed
  82.         MOV     SNAPSHOT_OFFSET,0       ;Point to screen storage part of pad
  83.         LEA     AX,GET_CHAR             ;Make IO use Get_char so current screen
  84.         MOV     IO_CHAR,AX              ;is stored
  85.         CALL    IO                      ;Store Screen
  86. IN:     JMP     OUT                     ;Done here, let's go.
  87. FLASH:  MOV     TAIL,BX
  88.         MOV     FLASHED,1           ;Switch Modes, next key will restore screen
  89.         MOV     SNAPSHOT_OFFSET,2000    ;Point to screen storage part 
  90.         LEA     AX,GET_CHAR             ;Make IO use Get_char so current screen
  91.         MOV     IO_CHAR,AX              ;is stored
  92.         CALL    IO                      ;Store Screen
  93.         MOV     SNAPSHOT_OFFSET,0       ;Use 1st 250 bytes of Snapshot memory
  94.         LEA     AX,PUT_CHAR             ;Make IO use Put-Char so it does
  95.         MOV     IO_CHAR,AX              
  96.         CALL    IO                      ;Put result on screen
  97.         JMP     OUT                     ;Done here.
  98. RESTORE:
  99.         MOV     FLASHED,0               ;Restore screen from memory
  100.         MOV     TAIL,BX                 ;Delete character from buffer
  101.         MOV     SNAPSHOT_OFFSET,2000    ;Point to storage part of memory
  102.         LEA     AX,PUT_CHAR             ;Make IO call Put_Char as it scans
  103.         MOV     IO_CHAR,AX              ;over all locations in screen
  104.         CALL    IO                      ;Restore screen
  105.         JMP     OUT                     ;And leave
  106.       
  107. DATS:   MOV     TAIL,BX
  108.         MOV     FLASHED,1           ;Switch Modes, next key will restore screen
  109.         PUSH    SNAPSHOT_OFFSET         ;Save this while Offset set for storing
  110.         MOV     SNAPSHOT_OFFSET,2000    ;Point to screen storage part 
  111.         LEA     AX,GET_CHAR             ;Make IO use Get_char so current screen
  112.         MOV     IO_CHAR,AX              ;is stored
  113.         CALL    IO                      ;Store Screen
  114.         POP     SNAPSHOT_OFFSET         ;Restore pointer to stored .Dat
  115.         LEA     AX,PUT_CHAR             ;Make IO use Put-Char so it does
  116.         MOV     IO_CHAR,AX              
  117.         CALL    IO                      ;Put result on screen
  118.  
  119. OUT:    POP     ES                      ;Do the Pops of all registers.
  120.         POP     DS
  121.         POP     SI
  122.         POP     DI
  123.         POP     DX
  124.         POP     CX
  125.         POP     BX
  126.         POP     AX     
  127.         IRET                    ;An interrupt needs an IRET
  128. SNAP    ENDP
  129.  
  130. GET_CHAR        PROC    NEAR    ;Gets a char from screen and advances position
  131.         PUSH    DX
  132.         MOV     SI,2            ;Loop twice, once for char, once for attribute
  133. G_WAIT_LOW:
  134.         MOV     AH,ES:[DI]      ;Do the move from the screen, one byte at a time
  135.         INC     DI              ;Move to next screen location                   
  136.         DEC     SI              ;Decrement loop counter
  137.         CMP     SI,0            ;Are we done?
  138.         JE      LEAVE           ;Yes
  139.         MOV     SNAPSHOT[BX],AH      ;No -- put char we got into snapshot
  140.         JMP     G_WAIT_LOW      ;Do it again
  141. LEAVE:  INC     BX              ;Update location
  142.         POP     DX
  143.         RET
  144. GET_CHAR        ENDP
  145.  
  146. PUT_CHAR        PROC    NEAR    ;Puts one char on screen and advances position
  147.         PUSH    DX
  148.         MOV     AH,SNAPSHOT[BX]      ;Get the char to be put onto the screen
  149.         MOV     SI,2            ;Loop twice, once for char, once for attribute
  150.         MOV     ES:[DI],AH      ;Move to screen, one byte at a time
  151.         ADD     DI,2
  152.         SUB     SI,2
  153.         INC     BX              ;Point to next char 
  154.         POP     DX
  155.         RET                     ;Exeunt
  156. PUT_CHAR        ENDP
  157.  
  158. IO      PROC    NEAR           ;This scans over all screen positions 
  159.         ASSUME  ES:SCREEN               ;Use screen as extra segment
  160.         MOV     BX,SCREEN
  161.         MOV     ES,BX
  162.         
  163.         MOV     DI,SCREEN_SEG_OFFSET    ;DI will be pointer to screen postion
  164.         MOV     BX,SNAPSHOT_OFFSET           ;BX will be location pointer
  165.         MOV     CX,25                   ;There will be 10 lines
  166. LINE_LOOP:      
  167.         MOV     DX,80                   ;And 25 spaces across
  168. CHAR_LOOP:
  169.         CALL    IO_CHAR                 ;Call Put-Char or Get-Char
  170.         DEC     DX                      ;Decrement character loop counter
  171.         JNZ     CHAR_LOOP               ;If not zero, scan over next character
  172.         LOOP    LINE_LOOP               ;And now go back to do next line
  173.         RET                             ;Finished
  174. IO      ENDP
  175.                          
  176. READ_FILE       PROC    NEAR            ;Reads .Dats and formats in memory.
  177.         PUSH    CX                      ;Save used registers
  178.         PUSH    DX
  179.         PUSH    DI
  180.         ASSUME  DS:CODE_SEG,ES:CODE_SEG
  181.         MOV     BX,AX                   ;Put passed file handle in BX
  182.         MOV     CX,2000                 ;Ask for 2000 bytes (Tops)
  183.         LEA     DX,DATA                 ;Point DS:DX at Data area at end
  184.         MOV     AH,3FH                  ;Ask for reading service
  185.         INT     21H                     ;And go get 'em
  186.         MOV     CX,AX                   ;Store number of bytes read
  187.         MOV     AH,3EH                  ;Now close file
  188.         INT     21H                     
  189.         CALL    WS                      ;Strip high bit if necessary
  190.         LEA     SI,DATA                 ;Transfer from CS:[SI] to DS:[BX] now
  191.         CMP     CX,2000                 ;Make sure on number of bytes read in.
  192.         JBE     THE_LOOP
  193.         MOV     CX,2000                 ;Format file into Snapshot area now
  194. THE_LOOP:                               ;Loop over character by character
  195.         CMP     BYTE PTR [SI],9         ;Is it a tab?
  196.         JNE     NOTAB                   ;Add 8 spaces for tabs
  197.         ADD     DI,8
  198.         INC     SI                      ;And point to next character
  199.         JMP     CONT
  200. NOTAB:  CMP     BYTE PTR [SI],13        ;Is it a carriage return?
  201.         JNE     OK                      ;No, store the character
  202. FILL:   INC     SI                      ;Found a <CR>. Fill to end of line 
  203.         DEC     CX                      ;Get rid of line feeds
  204.         CMP     BYTE PTR [SI],13        ;Treat additional <CR>s as new lines
  205.         JE      CR
  206.         CMP     BYTE PTR [SI],' '       ;Bona Fide character?
  207.         JB      FILL                    ;No, keep going past all linefeeds
  208. CR:     CMP     CX,0                    ;Yes, start to fill to end of line here
  209.         JLE     FIN                     ;Check on loop index
  210.         INC     CX                      ;And readjust it from skipping lf.s
  211.         MOV     AX,DI                   ;AH will check if we're at end of line
  212.         SUB     AX,OFFSET SNAPSHOT+4000 ;Get distance into screen
  213.         MOV     DL,80                   ;Divide by 80 to find columns
  214.         DIV     DL                      
  215. CHECK:  CMP     AH,79                   ;Remainder of 79?
  216.         JA      CONT                    ;If more, have begun a new line.
  217. ADD:    INC     DI                      ;Add a space by incrementing DI
  218.         INC     AH                      ;And keep track by incrementing AH too.
  219.         JMP     CHECK                   ;At edge of screen?
  220. OK:     CMP     DI,OFFSET SNAP    ;Past end of storage area? (Many tabs and CRs)
  221.         JAE     FIN                     ;Yes, don't move byte into it
  222.         MOVSB                           ;No, safe to move byte from [SI] to [DI]
  223. CONT:   LOOP    THE_LOOP                ;And keep going for all bytes in file
  224. FIN:    POP     DI
  225.         POP     DX
  226.         POP     CX
  227.         RET                             ;Exit here.
  228. READ_FILE       ENDP
  229.                                     
  230. WS      PROC    NEAR                    ;This will strip high bits from the
  231.         CMP     WS_FLAG,1               ;  read-in file if WS_Flag = 1
  232.         JNE     RETWS                   ;IF WS_Flag is not 1, exit
  233.         PUSH    SI                      ;Store used registers
  234.         PUSH    CX
  235.         LEA     SI,DATA                 ;Point to read-in file
  236.         MOV     CX,2000                 ;Do 2000 bytes
  237. ALOOP:  AND     BYTE PTR CS:[SI],127    ;Strip top bit
  238.         INC     SI                      ;Point to next one.
  239.         LOOP    ALOOP                   ;And keep going
  240.         POP     CX                      ;Pops
  241.         POP     SI
  242. RETWS:  RET                             ;And Exit.
  243. WS      ENDP
  244.  
  245. LOAD_SNAPSHOT        PROC    NEAR    ;This procedure intializes everything
  246.         ASSUME  DS:INTERRUPTS   ;The data segment will be the Interrupt area
  247.         MOV     AX,INTERRUPTS
  248.         MOV     DS,AX
  249.         
  250.         MOV     AX,KEYBOARD_INT         ;Get the old interrupt service routine
  251.         MOV     OLD_KEY_INT,AX          ;address and put it into our location
  252.         MOV     AX,KEYBOARD_INT[2]      ;OLD_KEYBOARD_INT so we can call it.
  253.         MOV     OLD_KEY_INT[2],AX
  254.         
  255.         MOV     KEYBOARD_INT,OFFSET SNAP  ;Now load the address of our program
  256.         MOV     KEYBOARD_INT[2],CS         ;routine into the keyboard interrupt
  257.                                         
  258.         MOV     AH,15                   ;Ask for service 15 of INT 10H 
  259.         INT     10H                     ;This tells us how display is set up
  260.         TEST    AL,4                    ;Is it?
  261.         JNZ     READ                    ;Yes - jump out
  262.         MOV     SCREEN_SEG_OFFSET,8000H ;No - set up for graphics display
  263. READ:   PUSH    CS                      ;Now read in A.Dat, B.Dat etc.
  264.         POP     DS                      ;Set DS correctly
  265.         MOV     CX,3                    ;Loop over three files
  266.         LEA     DI,SNAPSHOT+4000        ;Store starting in this area
  267. LOOP:   ASSUME  DS:CODE_SEG             ;Loop over files
  268.         LEA     DX,FILE                 ;Point to file name
  269.         MOV     AX,3D00H                ;Service 3DH, attribute 0 for file
  270.         INT     21H                     ;Open file
  271.         JC      EXIT                    ;If not found, exit
  272.         CALL    READ_FILE               ;Pass file handle in AX to Read_File
  273.         ADD     DI,2000                 ;Point to next storage area
  274.         MOV     BX,DX                   ;Change A.Dat into B.Dat etc.
  275.         INC     BYTE PTR CS:[BX]        ;A.DAT-->B.DAT etc.
  276.         LOOP    LOOP                    ;Keep going over all files.
  277. EXIT:   MOV     DX,OFFSET LOAD_SNAPSHOT ;Set up everything but LOAD_SNAPSHOT to
  278.         INT     27H                     ;stay and attach itself to DOS
  279. LOAD_SNAPSHOT        ENDP
  280. DATA:
  281.         CODE_SEG        ENDS
  282.         
  283.         END     FIRST   ;END "FIRST" so 8088 will go to FIRST first.
  284.  
  285.