.model medium
.stack 20h
.386
.code
public gswrap
gswrap proc
;sub gswrap (sseg, sofs, x, y, dseg, dofs)
;stack:
;bp+16  sseg
;bp+14  sofs
;bp+12  x
;bp+10  y
;bp+8   dseg
;bp+6   dofs
;bp+4   retseg
;bp+2   retofs
;bp     bp
;bp-2   ds
;bp-4   es
;bp-6   ss    
;bp-8   good spot to use in the stack

;ds:si = source
;es:di = destination

push bp          ;bp
mov ax, 0a000h

;

 mov bp, sp
 mov bx, 64000

 push ds         ;bp-2
  push es        ;bp-4

   mov ds, [bp+16]
   push ax       ;bp-6 = &ha000

    mov es, [bp+8]
    push bx      ;bp-8 = 64000

     mov si, [bp+14]
     mov di, [bp+6]
 
     mov ax, [bp+12]
 
     xtoobig:
     cmp ax, 159
     jle xnottoobig
  
     sub ax, 320
     jmp xtoobig
  
     xnottoobig:
     cmp ax, -160
     jge xnottoosmall
   
     add ax, 320
     jmp xnottoobig

     xnottoosmall:
     mov bx, [bp+10]                                                          
     mov dx, [bp+16]

     ytoobig:
     cmp bx, 99
     jle ynottoobig

     sub bx, 200
     jmp ytoobig

     ynottoobig:
     cmp bx, -100
     jge ynottoosmall
    
     add bx, 200
     jmp ynottoobig

     ynottoosmall:

     push ax  ;bp-10 = x
      cmp dx, [bp+8]

      jnz wrapto

      ;if you are here, then es = ds.
      ;oookay. ax = x, bx = y, dx = segment, cx = free, es,di,si,ds = set.

      cmp bx, 0
      jz samenoy
      jg sameypos

      neg bx
      mov es, [bp-6] ;es=&ha000
      mov dx, 80

      samey1loop:
      mov cx, bx
      mov di, [bp-8]

      push si ;bp-12 = si
       xor bx, -1

       samey1innerloop1:
       mov eax, [si]
       add si, 320

       mov es:[di], eax
       add di, 4
   
       dec cx
       jnz samey1innerloop1

       mov cx, bx
       xor bx, -1

       add cx, 201
      pop di

      samey1innerloop2:
      mov eax, [si]
      add si, 320
   
      mov [di], eax
      add di, 320

      dec cx
      jnz samey1innerloop2
    
      mov cx, bx
      mov si, [bp-8]
    
      samey1innerloop3:
      mov eax, es:[si]
      add si, 4
      
      mov [di], eax
      add di, 320
    
      dec cx
      jnz samey1innerloop3
    
      sub di, 63996
      dec dx
    
      mov si, di
      jnz samey1loop
      jmp samenoy
    
sameypos:
      mov es, [bp-6] ;es=&ha000
      mov dx, 80
      add si, 63680

      samey2loop:
      mov cx, bx
      mov di, [bp-8]

      push si ;bp-12 = si
       xor bx, -1
  
       samey2innerloop1:
       mov eax, [si]
       sub si, 320
  
       mov es:[di], eax
       add di, 4
  
       dec cx
       jnz samey2innerloop1
  
       mov cx, bx
       xor bx, -1
  
       add cx, 201
      pop di
  
      samey2innerloop2:
      mov eax, [si]
      sub si, 320
  
      mov [di], eax
      sub di, 320
  
      dec cx
      jnz samey2innerloop2
  
      mov cx, bx
      mov si, [bp-8]
  
      samey2innerloop3:
      mov eax, es:[si]
      add si, 4
      
      mov [di], eax
      sub di, 320
  
      dec cx
      jnz samey2innerloop3
  
      add di, 64004
      dec dx
  
      mov si, di
      jnz samey2loop
  
      samenoy:
     pop bx  ;bx = x, ax=free, cx = free, dx = free

     cmp bx, 0
     jz samenox
     jg samexpos

     neg bx
     mov si, [bp+14]
     mov dx, 200
  
     samexloop:
     mov es, [bp-6]
     mov cx, bx
  
     mov ds, [bp+16]
     push si

      add cx, 3
      mov di, [bp-8]
  
      shr cx, 2
      rep movsd
  
      mov si, [bp-10]
      mov cx, bx
  
      mov es, [bp+16]
      add si, bx
  
      mov di, [bp-10]
      xor cx, -1
  
      add cx, 324
      mov ax, bx
  
      shr cx, 2
  
      rep movsd
  
     pop di
     xor ax, -1
  
     mov ds, [bp-6]
     add di, ax
  
     mov si, [bp-8]
     mov cx, bx
  
     add di, 321
  
     rep movsb
  
     mov si, di
     dec dx
  
     jnz samexloop
     jmp samenox
  
samexpos:
     std
     mov si, [bp+14]
     add si, 63996
     mov dx, 200
     mov ax, [bp-8]
     add ax, 800
     mov [bp-8],ax

     samex2loop:
     mov es, [bp-6]
     mov cx, bx

     mov ds, [bp+16]
     push si

      add cx, 3
      mov di, [bp-8]

      shr cx, 2

      rep movsd

      mov si, [bp-10]
      mov cx, bx

      mov es, [bp+16]
      sub si, bx

      mov di, [bp-10]
      xor cx, -1
 
      add cx, 321
  
      mov ax, cx

      shr cx, 2
      and ax, 3

      rep movsd

      cmp ax, 0
      jz norepmovsb

      add si, 3
      add di, 3

      mov cx, ax
      rep movsb

      norepmovsb:
      mov ax, bx

     pop di
     xor ax, -1

     mov ds, [bp-6]
     sub di, ax
   
     mov si, [bp-8]
     mov cx, bx
   
     add si, 3
     sub di, 318
   
     rep movsb
   
     sub di, 3
     mov si, di
     dec dx
   
     jnz samex2loop
     samenox:
     jmp endofwrap

wrapto:
      ;es<>ds
      ;oookay. ax = x, bx = y, dx = sseg, cx = free, es,di,si,ds = ready
      pop ax

     cmp ax, 0
     jz tonox

     cmp bx, 0
     jge yisokay

     add bx, 200
     yisokay:
     cmp ax, 0
     jge xisokay
     
     add ax, 320
     xisokay:
     
     test ax, 3
     jz tocleanx

     push bx           ;bp-10 = y
      xor bx, -1

      mov dx, ax       ;dx = x
      add bx, 201

      shl bx, 2        ;bx=4y
      xor ax, -1       
    
      sub bx, [bp-10]  ;bx=5y
      add ax, 321      ;ax=320-x
     
      add bx, 200

      shl bx, 6        ;bx=320y
      add si, ax       ;x offset set.
     
      mov cx, dx       ;cx=x
      add si, bx       ;y offset set.
       
      shr cx, 2        ;cx=x\4
     pop bx            ;bx=y
     
     push ax           ;bp-10=(320-x)
      mov ax, bx       ;ax=y
      cmp ax, 0
      jz tobadxnoy

      tobadxloop1:
      rep movsd
      mov cx, dx
      and cx, 3
      rep movsb

      sub si, 320

      mov cx, [bp-10]
      and cx, 3
      rep movsb
      mov cx, [bp-10]
      shr cx, 2        ;
      rep movsd

      add si, 320
      mov cx, dx
     
      shr cx, 2
      dec ax
     
      jnz tobadxloop1
      tobadxnoy:
      
      mov si, [bp+14]
      xor bx, -1
     
      add si, [bp-10]
      add bx, 201
     pop ax
    
     tobadxloop2:
     rep movsd
     mov cx, dx
     and cx, 3
     rep movsb

     sub si, 320

     mov cx, ax
     and cx, 3
     rep movsb
     mov cx, ax
     shr cx, 2
     rep movsd

     add si, 320
     mov cx, dx
  
     shr cx, 2
     dec bx
  
     jnz tobadxloop2
  
     jmp endofwrap
    
     tocleanx:
     push bx           ;bp-10 = y
      xor bx, -1

      mov dx, ax       ;dx = x
      add bx, 201

      shl bx, 2        ;bx=4y
      xor ax, -1       
    
      sub bx, [bp-10]  ;bx=5y
      add ax, 321      ;ax=320-x
     
      add bx, 200

      shl bx, 6        ;bx=320y
      add si, ax       ;x offset set.
     
      mov cx, dx       ;cx=x
      add si, bx       ;y offset set.
       
      shr cx, 2        ;cx=x\4
     pop bx            ;bx=y
     
     push ax           ;bp-10=(320-x)
      mov ax, bx       ;ax=y
      cmp ax, 0
      jz toxnoy

      tocleanxloop1:
      rep movsd
    
      mov cx, [bp-10]
      sub si, 320

      shr cx, 2        ;

      rep movsd
     
      add si, 320
      mov cx, dx
     
      shr cx, 2
      dec ax
     
      jnz tocleanxloop1
      toxnoy:
      
      mov si, [bp+14]
      xor bx, -1
     
      add si, [bp-10]
      add bx, 201
     pop ax
    
     tocleanxloop2:
     rep movsd

     mov cx, ax
     sub si, 320

     shr cx, 2
     rep movsd

     add si, 320
     mov cx, dx
  
     shr cx, 2
     dec bx
  
     jnz tocleanxloop2
  
     jmp endofwrap
  
tonox:
     neg bx

     cmp bx, 0
     jge yisokay2

     add bx, 200
     yisokay2:
     cmp ax, 0
     jge xisokay2
     
     add ax, 320
     xisokay2:

     mov ax, bx
     xor bx, -1
     
     mov dx, ax
     add bx, 201   ;ax = dx = y, bx = 200-y
     
     shl ax, 2     ;ax = 4y
     mov cx, bx    ;cx = 200-y
     
     shl cx, 2     ;cx = 4(200-y)
     add ax, dx    ;ax = 5y
     
     shl ax, 6     ;ax = 320y
     add cx, bx    ;cx = 5(200-y)
     
     shl cx, 4     ;cx = 80(200-y)
     add si, ax    ;si = correct
     
     rep movsd
     
     mov si, [bp+14] ;si = original si.
     mov cx, dx    ;cx = y
     
     shl cx, 2     ;cx = 4y
     jz endofwrap
     
     add cx, dx    ;cx = 5y
     
     shl cx, 4     ;cx = 80y
     
     rep movsd
     
     endofwrap:
     cld
   pop eax
  pop es
 pop ds
pop bp

ret 12
gswrap endp
end
