;========================================================
;|    PC-9801Vシリーズ専用(グラフィックチャージャ使用)	|
;|    <<イメージスキャンルーチン (By PC-IN502) >>	 	|
;|                               by 杉原 秀圭		|
;|                                  From 1987/09/30	|
;|                                  to   1987/10/18	|
;========================================================
;
BPS9600 =       16              ;Baud Par Second.
ETB     =       17H             ;End of Text Block.
ETX     =       03H             ;End of Text.
MODE_FF =       68H             ;モードフリップフロップポート
GDC_CMD =       0A2H            ;グラフィックGDCコマンドポート
GDC_PARA=       0A0H            ;グラフィックGDCパラメタポート
GRCG_MODE=      07CH            ;グラフィックチャージャ・モードポート
GRCG_TILE=      07EH            ;グラフィックチャージャ・タイルポート
VRAM_B  =       0A800H          ;ブルーVRAM先頭アドレス
VRAM_R  =       0B000H          ;レッドVRAM先頭アドレス
VRAM_G  =       0B800H          ;グリーンVRAM先頭アドレス
VRAM    =       0B000H          ;グラフィックチャージャ用VRAM先頭アドレス
;----------------------------------------------------------
CODE    SEGMENT
        ASSUME  CS:CODE,SS:STACK,DS:DATA1
START:
        MOV     AX,DATA1        ;データセグメント設定。
        MOV     DS,AX           ;
        MOV     AL,3            ;
        MOV     CORFLG,AL       ;
        MOV     BX,OFFSET MSG1  ;開始メッセージ表示。
        CALL    MSGDISP         ;
        MOV     BX,OFFSET MSG2  ;読み取り開始メッセージ表示。
        CALL    MSGDISP         ;
        CALL    KEYWAIT         ;オペレータReady待ち。
        CALL    DISPCLR         ;グラフィック画面クリア。
        CALL    PREPA           ;処理準備、及びエラー処理。
        MOV     AL,FLG          ;
        CMP     AL,1            ;
        JZ      ERR01           ;
        MOV     AX,DATA1        ;データセグメント設定。
        MOV     DS,AX           ;
        CALL    RDDT            ;1ライン読み込み。
        MOV     BL,06H          ;ACK 送信。
        CALL    SEND232C        ;
        MOV     DI,80           ;
        MOV     CL,10000000B    ;
READLOOP:
        PUSH    CX              ;1ライン読み込み。
        CALL    RDDT            ;
        POP     CX              ;
        MOV     AH,BL           ;AHにエンドコードコピー。
        CMP     AH,ETX          ;ETXチェック。
        JE      PRGEND2         ;
        MOV     AL,CORFLG       ;
        DEC     AL              ;
        MOV     CORFLG,AL       ;
        JNE     RL01            ;
        MOV     AL,3            ;
        MOV     CORFLG,AL       ;
        MOV     AX,VRAM         ;
        MOV     ES,AX           ;
        SHL     CL,1            ;
        OR      CL,CL           ;
        JNE     RL01            ;
        MOV     CL,00000001B    ;
        DEC     DI              ;
RL01:   CALL    DISPDATA        ;
        MOV     BL,06H          ;ACK 送信。
        CALL    SEND232C        ;
        JMP     READLOOP        ;
PRGEND2:MOV     BL,06H          ;ACK 送信。
        CALL    SEND232C        ;
        CALL    DISPXOR         ;画面反転。
PRGEND: MOV     AH,4CH          ;プロセスの終了。
        INT     21H             ;
;----------------------------------------------------------
ERR01:  MOV     BX,OFFSET MSG3  ;エラーメッセージ表示。
        CALL    MSGDISP         ;
        JMP     PRGEND          ;異常終了。
;----------------------------------------------------------
MSGDISP         PROC    NEAR
        PUSH    AX              ;ワークレジスタ退避。
        PUSH    DX              ;
        MOV     AH,02           ;文字出力ファンクションコード。
MDLOOP: MOV     DL,[BX]         ;表示文字データ取り込み。
        CMP     DL,0            ;終了判定。
        JZ      MDEND           ;
        INT     21H             ;1文字出力。
        INC     BX              ;ポインタUP。
        JMP     MDLOOP          ;次処理へ。
MDEND:  POP     DX              ;レジスタ復元。
        POP     AX              ;
        RET                     ;呼び出し元へ復帰。
MSGDISP         ENDP
;----------------------------------------------------------
KEYWAIT         PROC    NEAR
        PUSH    AX              ;ワークレジスタ退避。
        MOV     AH,08H          ;1文字入力待ち。
        INT     21H             ;
        POP     AX              ;レジスタ復元。
        RET                     ;呼び出し元へ復元。
KEYWAIT         ENDP
;----------------------------------------------------------
SET232C         PROC    NEAR
        MOV     AX,BPS9600      ;ボーレートを9600に設定。
        OUT     75H,AL          ;
        NOP                     ;
        MOV     AL,AH           ;
        OUT     75H,AL          ;
        MOV     AL,0AAH         ;8251A内部リセット。
        OUT     32H,AL          ;
        MOV     AL,33H          ;
        OUT     32H,AL          ;
        MOV     AL,40H          ;
        OUT     32H,AL          ;
        MOV     AL,4EH          ;
        OUT     32H,AL          ;
        NOP                     ;タイムディレイ。
        NOP                     ;
        NOP                     ;
        NOP                     ;
        NOP                     ;
        NOP                     ;
        MOV     AL,37H          ;コマンド設定。
        OUT     32H,AL          ;
        RET                     ;呼び出し元へ復帰。
SET232C         ENDP
;----------------------------------------------------------
SEND232C        PROC    NEAR
SD232C: IN      AL,32H          ;TXRDY チェック。
        AND     AL,1            ;
        JZ      SD232C          ;
        MOV     AL,BL           ;データ送信。
        OUT     30H,AL          ;
        RET                     ;呼び出し元へ復帰。
SEND232C        ENDP
;----------------------------------------------------------
RCV232C         PROC    NEAR
RC232C: IN      AL,32H          ;READY チェック。
        AND     AL,2            ;
        JZ      RC232C          ;
        IN      AL,30H          ;データ受信。
        MOV     BL,AL           ;
        RET                     ;呼び出し元へ復帰。
RCV232C         ENDP
;----------------------------------------------------------
PREPA           PROC    NEAR
        PUSH    AX              ;ワークレジスタ退避。
        PUSH    BX              ;
        PUSH    CX              ;
        PUSH    DX              ;
        MOV     FLG,0           ;エラーフラグ クリア。
        CALL    SET232C         ;RS-232C初期化。
        CALL    PHAS1           ;フェイズ1実行。
        OR      AL,AL           ;エラーチェック。
        JNZ     PREPA1          ;
        MOV     FLG,1           ;タイムアウト エラー設定。
        JMP     PREPA2          ;
PREPA1: MOV     BL,1BH          ;
        CALL    SEND232C
        MOV     BL,54H
        CALL    SEND232C
        MOV     BL,33H
        CALL    SEND232C
        MOV     BL,1BH
        CALL    SEND232C
        MOV     BL,4FH
        CALL    SEND232C
        MOV     BL,30H
        CALL    SEND232C
        MOV     BL,1BH
        CALL    SEND232C
        MOV     BL,43H
        CALL    SEND232C
        MOV     BL,31H
        CALL    SEND232C
        MOV     BL,1BH
        CALL    SEND232C
        MOV     BL,52H
        CALL    SEND232C
        MOV     BL,30H
        CALL    SEND232C
        MOV     BL,1BH
        CALL    SEND232C
        MOV     BL,47H
        CALL    SEND232C
        MOV     BL,32H
        CALL    SEND232C
        MOV     BL,12H          ;DC2送信。
        CALL    SEND232C        ;
PREPA2: POP     DX              ;レジスタ復元。
        POP     CX              ;
        POP     BX              ;
        POP     AX              ;
        RET                     ;呼び出し元へ復帰。
PREPA           ENDP
;----------------------------------------------------------
PHAS1           PROC    NEAR
        MOV     CX,3000H        ;タイマー設定。
        MOV     BL,5            ;ENQ送信。
        CALL    SEND232C        ;
PHS10:  IN      AL,32H          ;Readyチェック。
        AND     AL,2            ;
        JZ      PHS11           ;
        IN      AL,30H          ;ACKチェック。
        CMP     AL,6            ;
        JNZ     PHS11           ;
        MOV     AL,1            ;復帰コード(正常)設定。
        RET                     ;呼び出し元へ復帰。
PHS11:  LOOP    PHS10           ;リトライ。
        XOR     AL,AL           ;復帰コード(タイムアウト)設定。
        RET                     ;呼び出し元へ復帰。
PHAS1           ENDP
;----------------------------------------------------------
SDESC           PROC    NEAR
        PUSH    DI              ;レジスタ退避。
        MOV     DI,OFFSET ESCDT ;ESCデータポインタ設定。
        MOV     CX,12           ;データ数設定。
        MOV     BL,DS:[DI]      ;ESCデータ送信。
        INC     DI              ;
        CALL    SEND232C        ;
        LOOP    SDES0           ;
        POP     DI              ;レジスタ復元。
        RET                     ;呼び出し元へ復帰。
SDESC           ENDP
;----------------------------------------------------------
RDDT            PROC    NEAR
        PUSH    DI              ;レジスタ退避。
        MOV     DI,OFFSET RDDATA ;読み込みデータポインタ設定。
 RD01:  CALL    RCV232C         ;STX受信チェック。
        CMP     BL,2            ;
        JNZ     RD01            ;
        CALL    RCV232C         ;データ長受信。
        MOV     CH,BL           ;
        CALL    RCV232C         ;
        MOV     CL,BL           ;
RD02:   CALL    RCV232C         ;データ受信。
        MOV     DS:[DI],BL      ;
        INC     DI              ;
        LOOP    RD02            ;
        CALL    RCV232C         ;ETX,ETB受信。
        POP     DI              ;レジスタ復元。
        RET                     ;呼び出し元へ復帰。
RDDT            ENDP
;+------------------------------------------+
;|      ES:DI=表示先頭アドレス		    |
;|      CL   =オフセットビット		    |
;+------------------------------------------+
DISPDATA        PROC    NEAR
        PUSH    AX              ;レジスタ退避。
        PUSH    BX              ;
        PUSH    CX              ;
        PUSH    DX              ;
        PUSH    DI              ;
        MOV     AL,0C8H         ;グラフィックチャージャーにRMRモ
        OUT     GRCG_MODE,AL    ;ードを設定。
        MOV     AL,11111111B    ;全タイルレジスタにFFHセット。
        OUT     GRCG_TILE,AL    ;
        OUT     GRCG_TILE,AL    ;
        OUT     GRCG_TILE,AL    ;
        MOV     BX,OFFSET RDDATA ;データポインタ設定。
        INC     BX              ;
        MOV     CH,50           ;1ラインデータバッファカウンタ設定。
DD00:   MOV     AL,[BX]         ;データ3バイト取り込み。
        MOV     AH,[BX+1]       ;
        MOV     DL,[BX+2]       ;
        ADD     BX,3            ;
        XOR     DH,DH           ;DH=0
        TEST    AL,11100000B    ;ビットデータに変換。
        JZ      DD01            ;
        MOV     DH,10000000B    ;
DD01:   TEST    AL,00011100B    ;(ANDを実行するとCFが0になる。)
        JZ      DD02            ;
        STC                     ;
DD02:   RCR     DH,1            ;
        TEST    AX,1000000000000011B ;
        JZ      DD03            ;
        STC                     ;
DD03:   RCR     DH,1            ;
        TEST    AH,01110000B    ;
        JZ      DD04            ;
        STC                     ;
DD04:   RCR     DH,1            ;
        TEST    AH,00001110B    ;
        JZ      DD05            ;
        STC                     ;
DD05:   RCR     DH,1            ;
        MOV     AL,DL           ;
        TEST    AX,0000000111000000B ;
        JZ      DD06            ;
        STC                     ;
DD06:   RCR     DH,1            ;
        TEST    AL,00111000B    ;
        JZ      DD07            ;
        STC                     ;
DD07:   RCR     DH,1            ;
        TEST    AL,00000111B    ;
        JZ      DD08            ;
        STC                     ;
DD08:   RCR     DH,1            ;
        PUSH    CX              ;CXレジスタ退避。
        MOV     AL,CL           ;AL=オフセットビット。
        MOV     CX,8            ;ビット展開用カウンタ設定。
;       NOT     DH              ;ビット反転。
DD10:   SAR     DH,1            ;
        JNB     DD11            ;
        MOV     ES:[DI],AL      ;
DD11:   ADD     DI,80           ;
        LOOP    DD10            ;
        POP     CX              ;CXレジスタ復元。
        DEC     CH              ;Y方向カウンタ-1。
        JNZ     DD00            ;
        MOV     AL,00H          ;グラフィックチャージャーモード
        OUT     GRCG_MODE,AL    ;を解除。
        POP     DI              ;レジスタ復元。
        POP     DX              ;
        POP     CX              ;
        POP     BX              ;
        POP     AX              ;
        RET                     ;呼び出し元へ復帰。
DISPDATA        ENDP
;----------------------------------------------------------
DISPCLR         PROC    NEAR
        PUSH    AX              ;レジスタ退避。
        PUSH    BX              ;
        PUSH    CX              ;
        PUSH    DX              ;
        MOV     AL,0            ;
        OUT     0A4H,AL         ;表示バンク=0
        OUT     0A6H,AL         ;描画バンク=0
        MOV     AL,04BH         ;
        OUT     GDC_CMD,AL      ;
        MOV     AL,0            ;
        OUT     GDC_PARA,AL     ;GDCカーソルフォームコマンド
        MOV     AL,0H           ;
        OUT     GDC_PARA,AL     ;
        MOV     AL,0H           ;
        OUT     GDC_PARA,AL     ;
        MOV     AL,08H          ;
        OUT     MODE_FF,AL      ;高解像度400ラインモード
        MOV     AL,0FH          ;
        OUT     MODE_FF,AL      ;画面表示ON
        MOV     AL,2            ;
        OUT     MODE_FF,AL      ;カラーモード設定
BGS00:  IN      AL,GDC_PARA     ;
        XOR     AL,20H          ;GDC(PD7220A)のFIFOに空きができる
        TEST    AL,22H          ;と同時に垂直同期信号が発生するまで
        JNE     BGS00           ;ウエイト。
        MOV     AL,0DH          ;GDC画面表示開始コマンド設定。
        OUT     GDC_CMD,AL      ;
        MOV     AL,088H         ;グラフィックチャージャーにTDWモ
        OUT     GRCG_MODE,AL    ;ードを設定。
        XOR     AL,AL           ;タイルパターン(クリア)
        OUT     GRCG_TILE,AL    ;
        OUT     GRCG_TILE,AL    ;
        OUT     GRCG_TILE,AL    ;
        MOV     AX,VRAM         ;
        MOV     DS,AX           ;
        MOV     BX,0            ;
        MOV     CX,16000        ;1画面を指定パターンで埋める。
BGS01:  MOV     [BX],AX         ;
        INC     BX              ;
        INC     BX              ;
        LOOPNE  BGS01           ;
        MOV     AL,00H          ;グラフィックチャージャーモード
        OUT     GRCG_MODE,AL    ;を解除。
        POP     DX              ;レジスタ復元。
        POP     CX              ;
        POP     BX              ;
        POP     AX              ;
        RET                     ;呼び出し元へ復帰。
DISPCLR         ENDP
;----------------------------------------------------------
DISPXOR         PROC    NEAR
        PUSH    AX              ;レジスタ退避。
        PUSH    BX              ;
        PUSH    CX              ;
        PUSH    DX              ;
        PUSH    DS              ;
        MOV     AX,VRAM_B       ;
        MOV     DS,AX           ;
        MOV     CX,40*400       ;
        XOR     BX,BX           ;
DSPX01: MOV     DX,[BX]         ;
        NOT     DX              ;
        MOV     [BX],DX         ;
        ADD     BX,2            ;
        LOOP    DSPX01          ;
        MOV     AX,VRAM_R       ;
        MOV     DS,AX           ;
        MOV     CX,40*400       ;
        XOR     BX,BX           ;
DSPX02: MOV     DX,[BX]         ;
        NOT     DX              ;
        MOV     [BX],DX         ;
        ADD     BX,2            ;
        LOOP    DSPX02          ;
        MOV     AX,VRAM_G       ;
        MOV     DS,AX           ;
        MOV     CX,40*400       ;
        XOR     BX,BX           ;
DSPX03: MOV     DX,[BX]         ;
        NOT     DX              ;
        MOV     [BX],DX         ;
        ADD     BX,2            ;
        LOOP    DSPX03          ;
        POP     DS              ;レジスタ復元。
        POP     DX              ;
        POP     CX              ;
        POP     BX              ;
        POP     AX              ;
        RET                     ;呼び出し元へ復帰。
DISPXOR         ENDP
;----------------------------------------------------------
CODE    ENDS
;====================================================================
DATA1   SEGMENT
CMPWRK  DW      128     DUP(?)
CMPLFO  DB      0
CMPTYP  DB      0
TOORWK  DW      128     DUP(?)
TOORLOP DB      0
TOORTYP DB      0
FLG     DB      0
CORFLG  DB      0
RDDATA  DB      241
ESCDT   DB      1BH,'T3'
ESCD1   DB      1BH,'O0'
;ESCD2  DB      1BH,'X',0,18H,07H,80H
;ESCD3  DB      1BH,'Y',0,18H,0BH,40H
ESCD4   DB      1BH,'R3'
ESCD5   DB      1BH,'C1'
;
MSG1    DB      'Image scanning utility.',0AH,0DH,0
MSG2    DB      'Scanning start. Please,push any key.',0AH,0DH,0
MSG3    DB      'Error !! Please,check and retry.',0AH,0DH,0
MSG4    DB      'Start !!',0AH,0DH,0AH,0DH,0
;
DATA1   ENDS
;====================================================================
STACK   SEGMENT STACK
        DW      4096    DUP(?)
STACK   ENDS