[Back to GRAPHICS SWAG index]  [Back to Main SWAG index]  [Original]

{
A couple of months ago, I posted an unfinished procedure to move a row of
pixels one pixel to the left and asked for help. Didn't get any response
(pretty normal, since it's really a lot of work to figure out someone else's
assembler code :), but in the meantime I've been able to finish it. Don't know
whether there's still anybody out there who can use it (the original
requester, Fabian Thylman(n?), seems to have left Fidonet), but here it is
anyway...
}

PROCEDURE MoveRow1PixelLeft(x,y, length: WORD; VAR tempbuf);
{For Mode-X, 320*200*4. Moves length pixels at (x,y) one position to the
left.}{Tempbuf should be an array of byte/char, with size = length div 4.
}{Public domain by Jonas Maebe (2:292/624.7). SWAG, you can include this if
}{you guys feel like it :)
}ASSEMBLER;
VAR sisav, disav: word;
    planecount: byte;
ASM
   cld
   push ds
   mov ax, $a000
   mov di, x
   mov ds, ax           {ds = videosegment}
   mov bx, di           {bx = di = x}
   mov ax, y
   shr di, 2
   shl ax, 5
   add di, ax
   shl ax, 2
   add di, ax           {di = y * 160 + x div 4}
   mov si, di           {source = destination = (x,y)}
   and bl, 11b
   mov bh, bl           {bh holds value for read plane}
   dec bl               {write plane points to previous plane}
   cmp bl, $ff          {bl = -1?}
   jne @bl_ok
   mov bl, 3            {set bl so it points to plane four (write plane)}
   dec di               {and di to point to the previous memlocation}
  @bl_ok:
   mov cl, bl
   mov bl, 1
   shl bl, cl           {bl holds value to set the write plane}
   mov cx, length       {cx holds the length of the row that has to be}
                        {moved}
   mov sisav, si
   mov disav, di        {save si and di for later}
   mov planecount, 3    {and initialize the plane counter}
   mov dx, grac
   mov ah, bl           {set read plane to value of writeplane, first save}
   dec ah               {all pixels that'll be overwritten by the first move}
   jns @ok
   xor ah, ah           {the next few adjustments are still a mystery to me}
  @ok:                  {and I've have found them out by trial and error.}
   cmp ah, 3            {If anyone can explain *WHY* the read plane has to}
   jne @ok2             {set this way, please do tell me...}
   dec ah
  @ok2:
   mov al, 4
   out dx, ax
   mov si, di
   sub cx, 3
   inc si
   les di, tempbuf
   shr cx, 3
   jnc @even
   movsb
  @even:                {all pixels that are to be overwritten are saved in}
   rep movsw            {tempbuf}
   mov si, sisav
   mov di, disav
   mov ax, $a000
   mov cx, length
   mov es, ax
  @newplane:
   mov dx, grac
   mov ah, bh
   mov al, 4
   out dx, ax           {select read plane}
  @writeplane:
   mov dx, sequ
   mov ah, bl
   mov al, 2
   out dx, ax           {select write plane}
   shr cx, 3            {shr 2 because there are 4 planes + shr 1 because}
   jnc @counter_even    {we're doing movsw's, only the last shifted-out}
   movsb                {bit is kept in the carry flag}
  @counter_even:
   rep movsw            {move pixels}
   cmp planecount, 0
   je @end
   mov cx, length       {reload the counter}
   mov si, sisav        {restore si}
   dec cx               {decrease the length by one; because we move on to}
                        {the next pixel, the length of the row becomes one}
                        {less}
   mov di, disav        {restore di}
   mov length, cx       {and save the length}
   inc bh               {increase the read plane}
   cmp bh, 4            {if it's four, wrap around since there are only 4}
                        {planes to read from (and with 4 it would point to 5)}
   jne @noreset_bh
   mov bh, 0            {reset bh}
   inc si               {next pixel because we reset bh}
   mov sisav, si        {plane zero}
  @noreset_bh:
   cmp bl, 1000b        {test if it points to the 4th plane}
   je @reset_bl
   add bl, bl           {increase write plane (same as shl bl, 1)}
   dec planecount
   jnz @newplane        {planecounter 0 -> finish him! :)}
   lds si, tempbuf
   jmp @writeplane        {it doesn't -> don't reset}
  @reset_bl:
   mov bl, 1            {select plane 0}
   inc di               {and point to the next pixel, same reason as with}
   mov disav, di        {read plane}
   dec planecount
   jnz @newplane        {planecounter 0 -> finish him! :)}
   lds si, tempbuf
   jmp @writeplane
  @end:
   mov ah, 1
   mov cl, bh
   shl ah, cl
   mov al, 2            {let the write plane point to the last pixel}
   out dx, ax           {we've read (write plane = read plane)}
   mov si, sisav
   mov cx, length
   shr cx, 2
   jnc @even2
   inc si
  @even2:
   add si, cx
   xor bl, bl
   mov es:[si], bl      {and zero the last pixel (erase it)}
   pop ds               {restore data segment}
END;

[Back to GRAPHICS SWAG index]  [Back to Main SWAG index]  [Original]