]> 4ch.mooo.com Git - 16.git/blobdiff - 16/x_/mxsm.asm
refresh wwww
[16.git] / 16 / x_ / mxsm.asm
diff --git a/16/x_/mxsm.asm b/16/x_/mxsm.asm
new file mode 100755 (executable)
index 0000000..183fba1
--- /dev/null
@@ -0,0 +1,508 @@
+;-----------------------------------------------------------\r
+;\r
+; MXSM.ASM - Set/change mode functions\r
+; Copyright (c) 1993,1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN    PRO\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC  mxChangeMode\r
+PUBLIC  mxGetAspect\r
+PUBLIC  mxGetScreenSize\r
+PUBLIC  mxSetMode\r
+\r
+PUBLIC  mx_ScreenWidth\r
+PUBLIC  mx_ScreenHeight\r
+PUBLIC  mx_BytesPerLine\r
+\r
+MX_TEXT         SEGMENT USE16 PARA PUBLIC 'CODE'\r
+                ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+EXTRN   mxSetSysClipRegion      : FAR\r
+\r
+EXTRN   mx_VideoSegment : WORD\r
+EXTRN   mx_CodeSegment  : WORD\r
+\r
+mx_ScreenWidth  DW      ?               ; Current screen width\r
+mx_ScreenHeight DW      ?\r
+mx_AspectX      DW      ?               ; Aspect ratio for current mode\r
+mx_AspectY      DW      ?\r
+mx_BytesPerLine DW      0               ; Bytes per line\r
+\r
+;\r
+; Tables for setting video modes, sources:\r
+; - MODEX.ASM, Matt Pritchard\r
+; - Dr. Dobb's Journal, Michael Abrash\r
+; - Fractint VIDEO.ASM module\r
+;\r
+TBL_SingleLine  LABEL   WORD            ; CRTC\r
+        DW      04009h                  ; Cell height: 1 scan line\r
+        DW      00014h                  ; Double word mode off\r
+        DW      0E317h                  ; Byte mode on\r
+        DW      0\r
+TBL_DoubleLine  LABEL   WORD            ; CRTC\r
+        DW      04109h                  ; Cell height: 2 scan lines\r
+        DW      00014h\r
+        DW      0E317h\r
+        DW      0\r
+TBL_Width320    LABEL   WORD            ; CRTC\r
+        DW      05F00h                  ; Horizontal total\r
+        DW      04F01h                  ; Horizontal displayed\r
+        DW      05002h                  ; Start horizontal blanking\r
+        DW      08203h                  ; End horizontal blanking\r
+        DW      05404h                  ; Start horizontal sync\r
+        DW      08005h                  ; End horizontal sync\r
+        DW      02813h                  ; Row address\r
+        DW      0\r
+TBL_Width360    LABEL   WORD            ; CRTC\r
+        DW      06B00h                  ; Horizontal total\r
+        DW      05901h                  ; Horizontal displayed\r
+        DW      05A02h                  ; Start horizontal blanking\r
+        DW      08E03h                  ; End horizontal blanking\r
+        DW      05E04h                  ; Start horizontal sync\r
+        DW      08A05h                  ; End horizontal sync\r
+        DW      02D13h                  ; Row address\r
+        DW      0\r
+TBL_Height175   LABEL   WORD            ; CRTC\r
+        DW      0BF06h                  ; Vertical total\r
+        DW      01F07h                  ; Overflow\r
+        DW      08310h                  ; Start vertical sync\r
+        DW      08511h                  ; End vertical sync\r
+        DW      05D12h                  ; Vertical displayed\r
+        DW      06315h                  ; Start vertical blanking\r
+        DW      0BA16h                  ; End vertical blanking\r
+        DW      0\r
+TBL_Height200   LABEL   WORD            ; CRTC\r
+        DW      0BF06h                  ; Vertical total\r
+        DW      01F07h                  ; Overflow\r
+        DW      09C10h                  ; Start vertical sync\r
+        DW      08E11h                  ; End vertical sync\r
+        DW      08F12h                  ; Vertical displayed\r
+        DW      09615h                  ; Start vertical blanking\r
+        DW      0B916h                  ; End vertical blanking\r
+        DW      0\r
+TBL_Height240   LABEL   WORD            ; CRTC\r
+        DW      00D06h                  ; Vertical total\r
+        DW      03E07h                  ; Overflow\r
+        DW      0EA10h                  ; Start vertical sync\r
+        DW      08C11h                  ; End vertical sync\r
+        DW      0DF12h                  ; Vertical displayed\r
+        DW      0E715h                  ; Start vertical blanking\r
+        DW      00616h                  ; End vertical blanking\r
+        DW      0\r
+TBL_Tweak400x600:\r
+        DW      07400h\r
+        DW      06301h\r
+        DW      06402h\r
+        DW      09703h\r
+        DW      06804h\r
+        DW      09505h\r
+        DW      08606h\r
+        DW      0F007h\r
+        DW      06009h\r
+        DW      0310Fh\r
+        DW      05B10h\r
+        DW      08D11h\r
+        DW      05712h\r
+        DW      03213h\r
+        DW      00014h\r
+        DW      06015h\r
+        DW      08016h\r
+        DW      0E317h\r
+        DW      0\r
+\r
+TBL_320x200:\r
+        DB      63h                     ; 400 scan lines, 25 MHz clock\r
+        DW      6, 5                    ; Aspect: 6/5 = 1.2:1\r
+        DW      320, 200                ; Size\r
+        DW      TBL_Width320, TBL_Height200, TBL_DoubleLine, 0\r
+        DW      819                     ; Max height\r
+TBL_320x240:\r
+        DB      0E3h                    ; 400 scan lines, 25 MHz clock\r
+        DW      1, 1                    ; Aspect: 1/1 = 1:1\r
+        DW      320, 240                ; Size\r
+        DW      TBL_Width320, TBL_Height240, TBL_DoubleLine, 0\r
+        DW      819                     ; Max height\r
+TBL_320x400:\r
+        DB      63h                     ; 480 scan lines, 25 MHz clock\r
+        DW      6, 10                   ; Aspect: 6/10 = 0.6:1\r
+        DW      320, 400                ; Size\r
+        DW      TBL_Width320, TBL_Height200, TBL_SingleLine, 0\r
+        DW      819                     ; Max height\r
+TBL_320x480:\r
+        DB      0E3h                    ; 480 scan lines, 25 MHz clock\r
+        DW      1, 2                    ; Aspect: 1/2 = 0.5:1\r
+        DW      320, 480                ; Size\r
+        DW      TBL_Width320, TBL_Height240, TBL_SingleLine, 0\r
+        DW      819                     ; Max height\r
+TBL_360x200:\r
+        DB      067h                    ; 400 scan lines, 28 MHz clock\r
+        DW      27, 20                  ; Aspect: 27/20 = 1.35:1\r
+        DW      360, 200                ; Size\r
+        DW      TBL_Width360, TBL_Height200, TBL_DoubleLine, 0\r
+        DW      728                     ; Max height\r
+TBL_360x240:\r
+        DB      0E7h                    ; 480 scan lines, 28 MHz clock\r
+        DW      9, 8                    ; Aspect: 9/8 = 1.125:1\r
+        DW      360, 240                ; Size\r
+        DW      TBL_Width360, TBL_Height240, TBL_DoubleLine, 0\r
+        DW      728                     ; Max height\r
+TBL_360x400:\r
+        DB      067h                    ; 400 scan lines, 28 MHz clock\r
+        DW      27, 40                  ; Aspect: 27/40 = 0.675:1\r
+        DW      360, 400                ; Size\r
+        DW      TBL_Width360, TBL_Height200, TBL_SingleLine, 0\r
+        DW      728                     ; Max height\r
+TBL_360x480:\r
+        DB      0E7h                    ; 480 scan lines, 28 MHz clock\r
+        DW      9, 16                   ; Aspect: 9/16 = 0.5625:1\r
+        DW      360, 480                ; Size\r
+        DW      TBL_Width360, TBL_Height240, TBL_SingleLine, 0\r
+        DW      728                     ; Max height\r
+TBL_320x175:\r
+        DB      0A3h\r
+        DW      0, 0                    ; Aspect:\r
+        DW      320, 175\r
+        DW      TBL_Width320, TBL_Height175, TBL_DoubleLine, 0\r
+        DW      819\r
+TBL_320x350:\r
+        DB      0A3h\r
+        DW      0, 0                    ; Aspect:\r
+        DW      320, 175\r
+        DW      TBL_Width320, TBL_Height175, TBL_SingleLine, 0\r
+        DW      819\r
+TBL_360x175:\r
+        DB      0A7h\r
+        DW      0, 0                    ; Aspect:\r
+        DW      360, 480                ; Size\r
+        DW      TBL_Width360, TBL_Height175, TBL_DoubleLine, 0\r
+        DW      728                     ; Max height\r
+TBL_360x350:\r
+        DB      0A7h\r
+        DW      0, 0                    ; Aspect:\r
+        DW      360, 480                ; Size\r
+        DW      TBL_Width360, TBL_Height175, TBL_SingleLine, 0\r
+        DW      728                     ; Max height\r
+TBL_400x600:\r
+        DB      0E7h                    ; 28 MHz clock\r
+        DW      1, 2                    ; Aspect: 1/2 = 0.5:1\r
+        DW      400, 600                ; Size\r
+        DW      TBL_Tweak400x600, 0\r
+        DW      655                     ; Max height\r
+\r
+TBL_Mode        LABEL   WORD\r
+        DW      TBL_320x175\r
+        DW      TBL_320x200\r
+        DW      TBL_320x240\r
+        DW      TBL_320x350\r
+        DW      TBL_320x400\r
+        DW      TBL_320x480\r
+        DW      TBL_360x175\r
+        DW      TBL_360x200\r
+        DW      TBL_360x240\r
+        DW      TBL_360x350\r
+        DW      TBL_360x400\r
+        DW      TBL_360x480\r
+        DW      TBL_400x600\r
+\r
+MAXVMODE        EQU     ($-OFFSET TBL_Mode) / 2\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Enables 80x25 color text mode\r
+;\r
+subText         PROC    NEAR\r
+        ASSUME  ds:MX_TEXT\r
+        mov     ax, 0003h\r
+        int     10h                     ; Call BIOS set mode\r
+\r
+        mov     [mx_ScreenHeight], 0\r
+        mov     [mx_BytesPerLine], 0\r
+        ret\r
+subText         ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Enables the selected graphics mode.\r
+;\r
+; Input:\r
+;       Mode    = mode to select (MX_???x???)\r
+; Output:\r
+;       none\r
+;\r
+mxSetMode       PROC    FAR\r
+        ARG     Mode:WORD       = ARG_SIZE\r
+        ASSUME  ds:NOTHING\r
+        .enter  0\r
+        .push   ds, si, es, di\r
+\r
+; Set DS to code segment alias\r
+        mov     ds, [mx_CodeSegment]\r
+        ASSUME  ds:MX_TEXT\r
+\r
+        mov     si, [Mode]\r
+        cmp     si, MAXVMODE            ; Is it a valid mode?\r
+        ja      @@Exit                  ; No, exit\r
+        test    si, si                  ; Text mode?\r
+        jnz     @@Set                   ; No, handle it\r
+\r
+        call    subText                 ; Back to text mode\r
+        jmp     @@Exit                  ; Exit now\r
+\r
+; Set video mode\r
+@@Set:\r
+        dec     si                      ; Skip text mode\r
+        shl     si, 1\r
+        mov     si, TBL_Mode[si]\r
+        cld\r
+\r
+; Use BIOS to set 320x200x256 linear mode\r
+        push    si                      ; Save SI\r
+        mov     ax, 0013h\r
+        int     10h                     ; Use BIOS to set 320x200 linear mode\r
+        pop     si                      ; Restore SI\r
+\r
+        mov     dx, TS\r
+        mov     ax, 0604h\r
+        out     dx, ax                  ; Disable chain-4 mode\r
+        mov     ax, 0100h\r
+        out     dx, ax                  ; Reset\r
+        mov     dx, MISC\r
+        lodsb\r
+        out     dx, al                  ; New timing/size\r
+        mov     dx, TS\r
+        mov     ax, 0300h\r
+        out     dx, ax                  ; Restart sequencer\r
+\r
+; Unlock CRTC registers 0-7\r
+        mov     dx, CRTC\r
+        mov     al, 11h\r
+        out     dx, al                  ; Vertical sync end register\r
+        inc     dx\r
+        in      al, dx\r
+        and     al, 7Fh                 ; Clear write protect bit\r
+        out     dx, al\r
+\r
+        lodsw                           ; Get X aspect\r
+        mov     [mx_AspectX], ax\r
+        lodsw                           ; Get Y aspect\r
+        mov     [mx_AspectY], ax\r
+        lodsw                           ; Get screen width\r
+        mov     [mx_ScreenWidth], ax\r
+        shr     ax, 1\r
+        shr     ax, 1                   ; Divide by four to get bytes per line\r
+        mov     [mx_BytesPerLine], ax\r
+        lodsw                           ; Get screen height\r
+        mov     [mx_ScreenHeight], ax\r
+\r
+; Set CRTC registers\r
+        mov     bx, si\r
+        mov     dx, CRTC\r
+@@TableLoop:\r
+        mov     si, ds:[bx]             ; DS:SI -> table of CRTC registers\r
+        inc     bx\r
+        inc     bx                      ; DS:BX -> offset of next table\r
+        test    si, si                  ; Last table?\r
+        jz      @@EndLoop               ; Yes, exit loop\r
+@@Loop:\r
+        lodsw                           ; Get CRTC register index and value\r
+        test    ax, ax                  ; End of table?\r
+        jz      @@TableLoop             ; Yes, go to next table\r
+        out     dx, ax                  ; Set register AL to value AH\r
+        jmp     @@Loop                  ; Get next register/value\r
+@@EndLoop:\r
+\r
+; Set virtual screen and system clip region\r
+        push    [mx_ScreenWidth]\r
+        push    WORD PTR ds:[bx]\r
+        call    mxSetSysClipRegion\r
+\r
+; Clear video memory\r
+        mov     dx, TS\r
+        mov     ax, 0F02h\r
+        out     dx, ax                  ; Enable all planes\r
+        mov     es, [mx_VideoSegment]\r
+        xor     di, di\r
+        mov     cx, 8000h\r
+        xor     ax, ax\r
+        rep     stosw\r
+\r
+@@Done:\r
+; Lock CRTC registers 0-7 (some cards need this)\r
+        mov     dx, CRTC\r
+        mov     al, 11h\r
+        out     dx, al                  ; Vertical sync end register\r
+        inc     dx\r
+        in      al, dx\r
+        or      al, 80h                 ; Set write protect bit\r
+        out     dx, al\r
+\r
+@@Exit:\r
+        xor     ax, ax\r
+        mov     ax, [mx_ScreenWidth]\r
+        .pop    ds, si, es, di\r
+        .leave  ARG_SIZE\r
+mxSetMode       ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Changes from the current mode the selected graphics mode.\r
+;\r
+; Input:\r
+;       Mode    = mode to select (MX_???x???)\r
+; Output:\r
+;       none\r
+; Notes:\r
+;       this function assumes that mxSetMode and mxSetVirtualScreen\r
+;       have been called first. View size is rearranged to match the\r
+;       specified mode, but video memory is not cleared.\r
+;       Differences from mxSetMode:\r
+;       - video BIOS is not called to initialize graphics;\r
+;       - row address register is not modified;\r
+;       - video memory is not cleared;\r
+;       - mx_BytesPerLine is not modified;\r
+;       - system clip region is not modified.\r
+;\r
+mxChangeMode    PROC    FAR\r
+        ARG     Mode:WORD       = ARG_SIZE\r
+        ASSUME  ds:NOTHING\r
+        .enter  0\r
+        .push   ds, si, es, di\r
+\r
+; Set DS to code segment alias\r
+        mov     ds, [mx_CodeSegment]\r
+        ASSUME  ds:MX_TEXT\r
+\r
+        mov     si, [Mode]\r
+        cmp     si, MAXVMODE            ; Is it a valid mode?\r
+        ja      @@Exit                  ; No, exit\r
+        test    si, si                  ; Text mode?\r
+        jz      @@Exit                  ; Yes, exit\r
+\r
+        dec     si                      ; Skip text mode\r
+        shl     si, 1\r
+        mov     si, TBL_Mode[si]\r
+        cld\r
+\r
+        mov     dx, TS\r
+        mov     ax, 0604h\r
+        out     dx, ax                  ; Disable chain-4 mode\r
+        mov     ax, 0100h\r
+        out     dx, ax                  ; Reset\r
+        mov     dx, MISC\r
+        lodsb\r
+        out     dx, al                  ; New timing/size\r
+        mov     dx, TS\r
+        mov     ax, 0300h\r
+        out     dx, ax                  ; Restart sequencer\r
+\r
+; Unlock CRTC registers 0-7\r
+        mov     dx, CRTC\r
+        mov     al, 11h\r
+        out     dx, al                  ; Vertical sync end register\r
+        inc     dx\r
+        in      al, dx\r
+        and     al, 7Fh                 ; Clear write protect bit\r
+        out     dx, al\r
+\r
+        lodsw                           ; Get X aspect\r
+        mov     [mx_AspectX], ax\r
+        lodsw                           ; Get Y aspect\r
+        mov     [mx_AspectY], ax\r
+        lodsw                           ; Get screen width\r
+        mov     [mx_ScreenWidth], ax\r
+        lodsw                           ; Get screen height\r
+        mov     [mx_ScreenHeight], ax\r
+\r
+; Set CRTC registers\r
+        mov     bx, si\r
+        mov     dx, CRTC\r
+@@TableLoop:\r
+        mov     si, ds:[bx]             ; DS:SI -> table of CRTC registers\r
+        inc     bx\r
+        inc     bx                      ; DS:BX -> offset of next table\r
+        test    si, si                  ; Last table?\r
+        jz      @@EndLoop               ; Yes, exit loop\r
+@@Loop:\r
+        lodsw                           ; Get CRTC register index and value\r
+        test    ax, ax                  ; End of table?\r
+        jz      @@TableLoop             ; Yes, go to next table\r
+        cmp     al, 13h                 ; Row address register?\r
+        je      @@Loop                  ; Yes, ignore it\r
+        out     dx, ax                  ; Set register AL to value AH\r
+        jmp     @@Loop                  ; Get next register/value\r
+@@EndLoop:\r
+\r
+; Lock CRTC registers 0-7 (some cards need this)\r
+        mov     dx, CRTC\r
+        mov     al, 11h\r
+        out     dx, al                  ; Vertical sync end register\r
+        inc     dx\r
+        in      al, dx\r
+        or      al, 80h                 ; Set write protect bit\r
+        out     dx, al\r
+\r
+@@Exit:\r
+        xor     ax, ax\r
+        mov     ax, [mx_ScreenWidth]\r
+        .pop    ds, si, es, di\r
+        .leave  ARG_SIZE\r
+mxChangeMode    ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Returns the aspect ratio for the current mode.\r
+;\r
+; Input:\r
+;       AspectX = pointer to aspect X\r
+;       AspectY = pointer to aspect Y\r
+;\r
+; A rectangle of width AspectX and height AspectY looks like a square.\r
+;\r
+mxGetAspect     PROC FAR\r
+        ARG     AspectY:DWORD,  \\r
+                AspectX:DWORD   = ARG_SIZE\r
+        .enter  0\r
+        .push   ds, si\r
+        ASSUME  ds:NOTHING\r
+\r
+        lds     si, [AspectX]\r
+        mov     ax, [mx_AspectX]\r
+        mov     ds:[si], ax\r
+        lds     si, [AspectY]\r
+        mov     ax, [mx_AspectY]\r
+        mov     ds:[si], ax\r
+\r
+        .pop    ds, si\r
+        .leave  ARG_SIZE\r
+mxGetAspect     ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Returns the current screen size.\r
+;\r
+; Input:\r
+;       Width   = pointer to screen width\r
+;       Height  = pointer to screen height\r
+;\r
+mxGetScreenSize PROC FAR\r
+        ARG     SizeY:DWORD,    \\r
+                SizeX:DWORD     = ARG_SIZE\r
+        .enter  0\r
+        .push   ds, si\r
+        ASSUME  ds:NOTHING\r
+\r
+        lds     si, [SizeX]\r
+        mov     ax, [mx_ScreenWidth]\r
+        mov     ds:[si], ax\r
+        lds     si, [SizeY]\r
+        mov     ax, [mx_ScreenHeight]\r
+        mov     ds:[si], ax\r
+\r
+        .pop    ds, si\r
+        .leave  ARG_SIZE\r
+mxGetScreenSize ENDP\r
+\r
+MX_TEXT         ENDS\r
+END\r