Metropoli BBS
VIEWER: hscrcycl.asm MODE: TEXT (CP437)
    IDEAL
    DOSSEG
    MODEL SMALL
    STACK 200h
    CODESEG
    p386
    
    ASSUME CS:@CODE, DS:@CODE
────────────────────────────────────────────────────────────────────────────
STRUC VCHHDR
    Ident   db  "VLACH"
    From    db  ?
    X       db  ?
    Y       db  ?
    NumChar db  ?
ENDS

STRUC Pal
    R       db  ?
    G       db  ?
    B       db  ?
ENDS
────────────────────────────────────────────────────────────────────────────
INCLUDE "MODEX.INC"

FileName_VCH    db      "palFont.VCH",0
FileName_PAL    db      "palFont.PAL",0

Seg_VCH         dw      0

Palette         Pal     256 dup (<>)
VCHHEADER       VCHHDR  <>
CharWidths      db      256 dup (0)

TheMessage      db      "  WOW!! THIS SCROLLER LOOKS REALLY COMPLICATED! "
                db      "  BUT IT ISN'T..  IT'S A PALETTE ROTATE AND A "
                db      "SCROLLER.  KINDA WEIRD, EH?  "
                db      "  RESOLUTION IS: 256X200 PLANAR WITH A CELL HEIGHT "
                db      "OF 1 (2 SCAN LINES PER PIXEL) AND THE VIRTUAL WIDTH "
                db      "IS 520 PIXELS (2X256 + 8, TO HIDE THE AREA THAT'S BEING "
                db      "WORKED ON)          "
                db      0

MsgOff          dw      offset TheMessage
CharOff         dw      0       ;offset to current column to draw of chr
XYsize          dw      ?       ;number of bytes in a char
CurColumn       db      1
DestOff         dw      0
SCReenWidth     =       130
────────────────────────────────────────────────────────────────────────────
    Numcolors   dw  8     ;# of colors to rotate
    NumColors3  dw  8*3   ;# of colors*3
    StartAt     db  2       ;color to start rotate at
    PalIndex    dw  0       ;color to start write at- increased every time
                            ;to produce the rotating effect
    PalIndexVel dw  1       ;amount PalIndex Changes for each screen

    PalOffset   dw  offset Palette + 6
────────────────────────────────────────────────────────────────────────────
PROC RotatePalette NEAR
    pusha

    call  WritePalette

    mov   ax,[PalIndexVel]
    add   [PalIndex],ax    ;change the palette index

    mov   ax,[PalIndex]    ;are we over the number of colors?
    mov   bx,[NumColors]

    cmp   ax,bx
    jl    NotTooHigh
    sub   [PalIndex],bx    ;add [Numcolors] to the index
    jmp   NotTooLow
NotTooHigh:
    cmp   ax,0
    jge   NotTooLow
    add   [PalIndex],bx    ;subtract [Numcolors] to the index
NotTooLow:

    popa
    ret
ENDP

PROC WritePalette NEAR        
    cld

    mov   dx,[PalIndex]
    mov   bx,dx
    add   bx,bx           ;This just multiplies
    add   bx,dx           ;bx by three ( bx = bx + 2*bx )

    mov   si,[PalOffset]
    mov   dx,03c8h
    mov   ax,[PalIndex]
    add   al,[StartAt]
    out   dx,al           ;start writing at [PalIndex]+[StartAt]
    inc   dx
    mov   cx,[NumColors3]
    sub   cx,bx           ;get the number of colors to write
    rep outsb

    mov   al,[StartAt]
    dec   dx              ;point to palette index
    out   dx,al           ;out the number we want to start writing at 
    inc   dx
    mov   cx,bx           ;get the number of colors to write
    rep outsb             ;note that SI is already where we want it

    ret
ENDP         ;well, that's all there is to it

    ────────────────────────────────────────────────────────────────────
    ; Load in the font named in FileName_VCH and loads in the Palette
    ; named in FileName_PAL. 
    ;
    ; Returns CF = 1 if there was an error
    ────────────────────────────────────────────────────────────────────
PROC LoadFont NEAR
    pusha
    push    ds

    mov     ax,cs
    mov     ds,ax
    mov     dx,offset FileName_PAL      ;open the palette file
    mov     ax,3d00h
    int     21h
    jc      @@Error
    mov     bx,ax

    mov     dx,offset Palette           ;read in the palette
    mov     cx,768
    mov     ah,3fh
    int     21h

    mov     ah,3eh                      ;close PAL file
    int     21h

    mov     dx,offset FileName_VCH      ;open VCH file
    mov     ax,3d00h
    int     21h
    jc      @@Error
    mov     bx,ax

    mov     dx,offset VCHHeader         ;load in the header
    mov     cx,size VCHHDR
    mov     ah,3fh
    int     21h

    mov     al,[VCHHEADER.X]            ;calc data size
    mul     [VCHHEADER.Y]
    mov     [XYsize],ax
    movzx   cx,[VCHHEADER.NumChar]
    mul     cx
    mov     cx,ax

    mov     ax,[cs:SEG_VCH]             ;move SEG_VCH into DS, but be sure
    or      ax,ax                       ;the segment isn't 0
    stc
    je      @@Error
    mov     ds,ax
    xor     dx,dx                       ;load in the data
    mov     ah,3fh
    int     21h

    mov     ax,cs
    mov     ds,ax
    mov     dx,offset CharWidths
    movzx   cx,[VCHheader.NumChar]
    mov     ah,3fh
    int     21h                         ;read in widths of chars

    mov     ah,3eh                      ;close VCH file
    int     21h
    clc

@@Error:

    pop     ds
    popa
    ret
ENDP
    ────────────────────────────────────────────────────────────────────
    ;Starts the next letter in the message
    ────────────────────────────────────────────────────────────────────
PROC NewChar NEAR
    pusha
    push    ds
    mov     ax,cs
    mov     ds,ax

    mov     si,[MsgOff]     ;get the offset to the next char
@@MsgLoop:
    lodsb
    or      al,al
    jne     @@IsaChar
    mov     si,offset TheMessage
    jmp short @@MsgLoop

@@IsaChar:
    mov     ah,[VCHHEADer.From]
    add     ah,[VCHHEADer.NumChar]
    cmp     al,[VCHHEADer.FROM]
    jb      @@MsgLoop
    cmp     al,ah
    ja      @@MsgLoop

    mov     [MsgOff],si
    sub     al,[VCHheader.From]
    movzx   ax,al
    mov     bx,ax
    mul     [XYsize]
    mov     [CharOff],ax
    
    mov     al,[CharWidths + bx]
    mov     [CurColumn],al
    
    pop     ds
    popa
    ret
ENDP
    ────────────────────────────────────────────────────────────────────
    ; Draws the Next column onto the screen, calls NewChar if done with
    ; current character
    ────────────────────────────────────────────────────────────────────
PROC DrawColumn NEAR
    pusha
    push    ds es fs
    mov     ax,cs
    mov     ds,ax

    mov     bx,[DestOff]
    add     bx,2
    @Set_Start_Offset

    ;dec     [CurColumn]
    sub     [CurColumn],4
    jg      @@NoNew

    call    NewChar

@@NoNew:
    mov     fs,[SEG_VCH]
    mov     es,[VGASEG]

    mov     bp,SCReenWidth         ;screen width

    mov     dx,SC_Index
    mov     ax,0102h
    out     dx,ax

    movzx   dx,[VCHheader.X]
    movzx   cx,[VCHheader.Y]
    mov     si,[CharOff]    ;fs:si points to the data
    mov     di,[DestOff]
@@Zloop:
    mov     al,[fs:si]
    mov     [es:di],al
    mov     [es:di+SCReenWidth/2],al
    add     di,bp

    add     si,dx

    loop    @@ZLoop
    
    mov     dx,SC_Index
    mov     ax,0202h
    out     dx,ax

    movzx   dx,[VCHheader.X]
    movzx   cx,[VCHheader.Y]
    mov     si,[CharOff]    ;fs:si points to the data
    inc     si
    mov     di,[DestOff]
@@Zloop2:
    mov     al,[fs:si]
    mov     [es:di],al
    mov     [es:di+SCReenWidth/2],al
    add     di,bp

    add     si,dx

    loop    @@ZLoop2
    
    mov     dx,SC_Index
    mov     ax,0402h
    out     dx,ax

    movzx   dx,[VCHheader.X]
    movzx   cx,[VCHheader.Y]
    mov     si,[CharOff]    ;fs:si points to the data
    add     si,2
    mov     di,[DestOff]
@@Zloop3:
    mov     al,[fs:si]
    mov     [es:di],al
    mov     [es:di+SCReenWidth/2],al
    add     di,bp

    add     si,dx

    loop    @@ZLoop3

    mov     dx,SC_Index
    mov     ax,0802h
    out     dx,ax

    movzx   dx,[VCHheader.X]
    movzx   cx,[VCHheader.Y]
    mov     si,[CharOff]    ;fs:si points to the data
    add     si,3
    mov     di,[DestOff]
@@Zloop4:
    mov     al,[fs:si]
    mov     [es:di],al
    mov     [es:di+SCReenWidth/2],al
    add     di,bp

    add     si,dx

    loop    @@ZLoop4

    inc     [DestOff]
    cmp     [DestOff],ScreenWidth/2
    jb      @@okok

    mov     [DestOff],0

@@okok:
    add     [CharOff],4

    pop     fs es ds
    popa
    ret
ENDP

HPPPOS  db  0

PROC Scrollit NEAR
    pusha

    mov     ah,[HPPpos]
    add     ah,2 *2
    mov     [HPPpos],ah
    cmp     ah,8
    jb      @@JustSetIt
    sub     ah,8
    mov     [HPPpos],ah

    call    DrawColumn

@@JustSetIt:
    mov     ah,[HPPpos]
    @Set_HPP

    popa
    ret
ENDP
────────────────────────────────────────────────────────────────────────────
START:
    mov     ax,cs
    mov     ds,ax

    mov     ax,ss
    mov     bx,sp
    add     bx,15
    shr     bx,4
    add     ax,bx
    mov     [SEG_VCH],ax

    @SetModeX m256x200x256, 520

    call    LoadFont
    mov     si,offset Palette
    mov     cx,256
    mov     al,0
    @WritePalette
    
    mov     dx,CRTC_Index
    mov     al,9
    mov     ah,1    ;each dot is 2 high (use HEIGHT-1)
    out     dx,ax

    @SET_PPC    ;set Pixel Panning Compatibility
                ;so the split screen, if I had one, would not be disturbed.
                
@@MainLoop:
    @FullVertWait
    call    RotatePalette
    call    Scrollit

    ;call    DrawColumn

    mov     ah,1
    int     16h
    jz      @@MainLoop

    mov     ah,0
    int     16h

    mov     ax,3
    int     10h
    mov     ax,4c00h
    int     21h
END START
[ RETURN TO DIRECTORY ]