Scrolling the screen in Assembly language back in the old 386 da

Mov CX,Scx
Mov DX,Sdx
Add DX,Y
Add CX,X
Mov Scx,CX
Mov Sdx,DX
Mov AX,04F07H
XOr BX,BX
Int 10H

I was just looking at my old files .. Mwahahahhahah .. calling interrupt 10 .. poof. Whatever I wrote 12 years ago doesn't work in my Intel Core 2 Duo anymore.  It was 386, then 486 .. now it's Core-Quad or whatever.

Here's another one if you like wasting a couple minutes of your life reading this code below just to draw a line from X1,Y1 to X2,Y2 ..

Procedure Line(X1,Y1,X2,Y2:Integer);Assembler;
Const
  Left  = $07;
  Right = $0B;
  Upper = $0D;
  Lower = $0E;

Var
  I,D,Dtx,Dty,Windowy2,Incx2,Incx,Incy,E:Integer;
  Interchange:Byte;
  Pattern:Word;

Asm
  Mov BX,Vp.X1
  Add X1,BX
  Add X2,BX
  Mov SI,Vp.X2
  Mov DI,Vp.Y1
  Add Y1,DI
  Add Y2,DI
  Mov AX,Vp.Y2
  @Start:
  Mov Windowy2,AX
  {BX|SI|DI|WindowY2 = vp.x1|vp.x2|vp.y1|vp.y2}

  Mov CL,0Fh        {start with %1111  }
  Cmp X2,BX         {x2 < WindowX1 ?}
  Jl @v1point2     {yes, don't change flag for "point is left of window"}
  And CL,Left       {no, reset flag       }
  @v1point2:
  Cmp X2,SI         {x2 > WindowX2 ?}
  Jg @v2point2     {yes, don't change flag for "point is right of window"}
  And CL,Right      {no, reset flag       }
  @v2point2:
  Mov AX,Y2
  Cmp AX,DI         {y2 < WindowY1 ?}
  Jl @v3point2     {yes, don't change flag for "point is above window"}
  And CL,Upper      {no, reset flag       }
  @v3point2:
  Cmp AX,Windowy2   {y2 > WindowY2 ?}
  Jg @point1        {yes, don't change flag for "point is below window"}
  And CL,Lower
  @point1:
  Mov CH,0Fh        {start with %1111  }
  Cmp X1,BX         {x1 < WindowX1 ?}
  Jl @v1point1     {yes, don't change flag for "point is left of window"}
  And CH,Left  {no, reset flag      }
  @v1point1:
  Cmp X1,SI         {x1 > WindowX2 ?}
  Jg @v2point1     {yes, don't change flag for "point is right of window"}
  And CH,Right      {no, reset flag       }
  @v2point1:
  Mov AX,Y1
  Cmp AX,DI         {y1 < WindowY1 ?}
  Jl @v3point1      {yes, don't change flag for "point is above window"}
  And CH,Upper      {no, reset flag       }
  @v3point1:
  Cmp AX,Windowy2   {y1 > WindowY2 ?}
  Jg @v4point1      {yes, don't change flag for "point is below window"}
  And CH,Lower
  @v4point1:        {CH holds the area code for point 1          }
                    {CL holds the area code for point 2, CH the one for point 1}
  Mov AX,CX
  And AL,AH         {Code1 AND Code2 <> 0 ?}
  Jnz @Done         {yes, line is completely outside the window}
  Mov AX,CX
  Or AL,AH          {Code1 OR Code2 = 0 ?}
  Jz @Drawline      {yes, line is completely inside the window}
                    {Now do the clipping itself: }
  Mov AX,CX
  Or AH,AH          {Code1 =0 ?}
  Jnz @Cl3          {no, everything ok lah yauow !}
  Mov AX,X1         {yes, swap points!}
  Xchg AX,X2
  Mov X1,AX
  Mov AX,Y1
  Xchg AX,Y2
  Mov Y1,AX
  Xchg CL,CH
  @Cl3:
  Mov AX,X2
  Sub AX,X1
  Mov Dtx,AX                {dtx := x2 - x1}
  Mov AX,Y2
  Sub AX,Y1
  Mov Dty,AX                {dty := y2 - y1}
  Mov AL,CH                 {AL := Code1}
  Test AL,Not Left          {point1 left of window?   }
  Jz @Cl4                   {no  }
                            {yes, compute new coordinates:}
                            { y1 := y1 + (y2 - y1) / (x2 - x1) * (WindowX1 - X1) }
                            { and x1 := WindowX1}
  Mov AX,BX
  Sub AX,X1                 {AX := WindowX1-x1}
  Imul Dty
  Idiv Dtx
  Add Y1,AX
  Mov X1,BX
  Jmp @point1
  @Cl4:
  Test AL,Not Right         {point1 right of window?   }
  Jz @Cl5                   {no  }
  {yes, compute:}
  { y1 := y1 + (y2 - y1) / (x2 - x1) * (WindowX2 - X1), x1 := WindowX2}
  Mov AX,SI                 {SI = WindowX2}
  Sub AX,X1
  Imul Dty
  Idiv Dtx
  Add Y1,AX
  Mov X1,SI
  Jmp @point1

  @Cl5:
  Test AL,Not Upper         {point1 above window?        }
  Jz @Cl6                   {no  }
                            {yes, compute:}
                            { x1 := x1 + (x2 - x1) / (y2 - y1) * (WindowY1 - y1), y1 := WindowY1 }
  Mov AX,DI                 {DI = WindowY1}
  Sub AX,Y1
  Imul Dtx
  Idiv Dty
  Add X1,AX
  Mov Y1,DI
  Jmp @point1

  @Cl6:
  Test AL,Not Lower         {point below window?         }
  Jz @point1                {no  }
  {yes, compute:}
  { x1 := x1 + (x2 - x1) / (y2 - y1) * (WindowY2 - y1), y1 := WindowY2 }
  Mov AX,Windowy2
  Push AX
  Sub AX,Y1
  Imul Dtx
  Idiv Dty
  Add X1,AX
  Pop AX
  Mov Y1,AX
  Jmp @point1

  @Yincr:
  Cmp Incy,0
  Jl @Negy2
  Add DI,BytesPerLine            {y:=y+incy}
  Jmp @Skip73
  @Negy2:
  Sub DI,BytesPerLine            {y:=y-incy}
  @Skip73:
  Jnc @Nobanky
  Add DX,Incy
  Call Setbank
  @Nobanky:
  Retn

  @Drawline:
  mov ax,linepattern
  mov pattern,ax
  Mov AX,Y1
  Mov BX,X1
  Call Vsetoffset
  Mov DI,AX
  Mov SI,X2                     {SI=_DX}
  Sub SI,X1
  Mov Incx,1
  Mov AX,Addx
  Mov Incx2,AX
  Jns @Bx_To_Dy
  Neg Incx
  Neg Incx2
  Neg SI
  @Bx_To_Dy:
  Mov bX,Y2                     {AX=_DY}
  Sub bX,Y1
  Mov Incy,1
  Jns @Skip2
  Neg Incy
  Neg bX
  @Skip2:
  Mov Interchange,FALSE
  Cmp bX,SI                     {_DY compare _DX [SI] }
  Jl @Dy_Lower_Than_Dx
  Inc Interchange
  Xchg bX,SI
  @Dy_Lower_Than_Dx:
  Mov CX,SI                     {loop i:=_DX;  ;initialization}
  inc cx
  ShL SI,1                      {_DX * 2}
  ShL bX,1                      {_DY * 2}
  Mov E,bX
  Sub E,SI
  Mov ES,SegA000
  Mov AX,Currentcolor
  @Mainloop:                    {main loop}
  ror pattern,1
  Jnc @Noplot
  call plotcolor

  @Noplot:
  Cmp E,0
  Jnge @Skipe                   {while e >= 0}
  Cmp Interchange,FALSE
  Je @Itfalse1
  Add DI,Incx2                   {x:=x+incx}
  Jnz @Nobank1                  {DI=bankend ?}
  Add DX,Incx
  Call Setbank
  Jmp @Nobank1
  @Itfalse1:
  Call @Yincr
  @Nobank1:
  Sub E,SI
  @Skipe:
  Cmp Interchange,FALSE
  Je @Itfalse2
  Call @Yincr
  Jmp @Ittrue2
  @Itfalse2:
  Add DI,Incx2                    {x:=x+incx}
  Jnz @Ittrue2                   {DI=bankend ?}
  Add DX,Incx
  Call Setbank
  @Ittrue2:
  Add E,bX
  Loop @Mainloop
  @Done:
End;

And here's the referenced Setbank

Procedure Setbank;Near;Assembler;
Asm
  Cmp DL,Currentbank
  Je @@Nochange
  Mov Currentbank,DL
  Push AX
  Push BX
  Mov AX,4F05H
  XOr BX,BX     {write bank - MOV}
  Int 10H

  Mov AX,4F05H
  Mov BX,0001H  {read bank - AND, OR , XOR}
  Int 10H
  @Noread:
  Pop BX
  Pop AX
  @@Nochange:
End;

How about drawing a mouse cursor on the screen?

Procedure Drawmouse(X,Y:Integer);Assembler;
Var
  Width,Height:Word;
  AndPattern,Xorpattern:Word;
  Nhorshift:Word;
  savebank:byte;

Asm
    cld
    Mov Nhorshift,0
    Mov Height,16
    Mov Width,16
    mov bx,x
    mov dx,y
    Lea SI,MouseShape
    Lodsw
    sub bx,ax   {x-hotspot.x}
    cmp bx,0
    jge @xg
    neg bx
    mov nhorshift,bx
    neg bx
    add bx,16
    mov width,bx
    xor bx,bx
    jmp @xdone
    @xg:
    mov ax,bx
    add ax,16
    cmp ax,getmaxx
    jle @xdone
    mov cx,getmaxx
    inc cx
    sub cx,bx
    mov width,cx
    @Xdone:
    Lodsw
    Sub dx,ax
    Cmp dx,0
    Jge @Yg
    mov ax,dx
    neg ax
    shl ax,1
    add si,ax
    add dx,16
    mov height,dx
    xor dx,dx
    jmp @ydone
    @Yg:
    Mov AX,dx
    Add AX,16
    Cmp AX,getmaxy
    Jle @Ydone
    Mov AX,getmaxy
    Sub AX,dx
    Inc AX
    Mov Height,AX
    @Ydone:
    mov al,20h
    add al,hicolor
    mov byte ptr @p1,al
    mov al,30h
    add al,hicolor
    mov byte ptr @p2,al
    Mov AX,dx
    call vsetoffset
    Mov DI,AX
    Push bytesperline
    Mov AX,Width
    shl ax,cl
    Sub bytesperline,AX
    Mov BL,White
    Mov ES,SegA000
    Mov Bx,white
    cmp cl,false
    je @puty
    mov bx,0ffffh

    @Puty:
    LODSW              {AND}
    mov andpattern,ax
    Mov ax,DS:[SI+30]  {XOR}
    mov xorpattern,ax
    Mov CX,nhorshift
    Rol andpattern,CL
    Rol xorpattern,CL
    Mov CX,Width
    @Putx:
    XOr aX,aX
    Rol andpattern,1
    Jc @Noandput
    db $26
@p1:db $20
    db $05
    @Noandput:
    Rol Xorpattern,1
    Jnc @Noxorput
    db $26
@p2:db $30
    db $1d   {ada warnaan}
    @Noxorput:
    add DI,addx
    jnz @nobank
    inc dl
    call setbank
    @nobank:
    Loop @Putx
    Add DI,bytesperline
    jnc @nobank2
    inc dl
    call setbank
    @nobank2:
    Dec Height
    Jnz @Puty
    @@Done:
    Pop bytesperline
End;

Then call interrupt 33 to set the X and Y. Wheew. Good night. What a week.

Category:  Programming