///////////////////////////////////////////////// // LINEASM.CPP (c) 17/11/1997 Jake Birkett ///////////////////////////////////////////////// // Assembly implementation of Bresenham's Line Algorithm // // External Functions : /////////////////////// // void LineASM(void); // // External Variables : /////////////////////// // unsigned int lx1 = 0; // line start x coord // unsigned int ly1 = 0; // unsigned int lx2 = 0; // line end y coord // unsigned int ly2 = 0; // // unsigned char far *line_dest; // unsigned char line_colour; // 0-255 ///////////////////////////////////////////////// // I N C L U D E S ////////////////////////////// ///////////////////////////////////////////////// #include "lineasm.h" ///////////////////////////////////////////////// // D E F I N E S //////////////////////////////// ///////////////////////////////////////////////// ///////////////////////////////////////////////// // P R O T O T Y P E S ////////////////////////// ///////////////////////////////////////////////// // INTERNAL // EXTERNAL void LineASM(void); ///////////////////////////////////////////////// // G L O B A L S //////////////////////////////// ///////////////////////////////////////////////// // INTERNAL // EXTERNAL unsigned int lx1 = 0; // line start x coord unsigned int ly1 = 0; unsigned int lx2 = 0; // line end y coord unsigned int ly2 = 0; unsigned char far *line_dest=(unsigned char far *)0xA0000000L; // default destination is video buffer unsigned char line_colour; // 0-255 ///////////////////////////////////////////////// // F U N C T I O N S //////////////////////////// ///////////////////////////////////////////////// void LineASM(void) { // Draws a line using Bresenham's Line Algorithm onto the // video buffer or alternate destination specified by line_dest. // Uses 4 octants and pre-specifies up or down // AL = Line_Colour // BX = DeltaX // SI = DeltaY // ES:DI = line dest address // load registers asm push ds; // precaution asm mov al, line_colour; // al = line colour; asm mov bx, lx2; asm sub bx, lx1; // DeltaX asm mov si, ly2; asm sub si, ly1; // DeltaY asm les di, line_dest; // memory dest address asm mov dx, ly1; // calc y offset = y*320 ... y<<8 + y<<6 ... or (y<<2 + y)<<6 quicker asm shl dx, 1; asm shl dx, 1; asm add dx, ly1; asm mov cl, 6; asm shl dx, cl; asm add di, dx; asm add di, lx1; // add x offset asm mov byte ptr es:[di], al; // draw first pixel // see if ldy<0 or ldy>0 asm cmp si, 0; asm jns Line_Down; // if ldy>0 line is moving down asm neg si; // make DeltaY positive asm mov dx, -320; // set y movement to up asm jmp Continue; Line_Down: asm mov dx, 320; // set y movement to down Continue: // see if ldx<0 or ldx>0 asm cmp bx, 0; asm js Down_Left; // if ldx<0 line is moving left Down_Right: // line is moving Down and Right ... Oct 0 and 1 asm cmp bx, si; // is DeltaX>DeltaY asm js V_Line; // no, so do a Vertical Line H_Line: asm mov cx, bx; // cx = number of pixels in line asm jcxz Line_End; // jumps if cx=0 // calc error term values asm shl si, 1; // binary shift left ... DeltaY*2 asm mov bp, si; // bp = error term asm sub bp, bx; // error term starts at DeltaY*2 - DeltaX asm shl bx, 1; // DeltaX*2 asm sub si, bx; // si = DeltaY*2 - DeltaX*2 ... Error Decrement Value ... used in loop asm add bx, si; // bx = clever convert bx to DeltaY*2 ... Error Increment Value ... used in loop H_Line_Loop: asm and bp, bp; // see if error term is negative asm js Move_X_Coord; // yes, stay at same Y Coord // move the Y Coord asm add di, dx; // increment Y Coord ... add 320 to pixel address asm add bp, si; // decrement Error Term with si asm jmp Next_X_Pixel; Move_X_Coord: asm add bp, bx; // increment Error Term with bx Next_X_Pixel: asm inc di; // add 1 to X Coord asm mov byte ptr es:[di], al; asm loop H_Line_Loop; // draw next pixel asm jmp Line_End; V_Line: asm mov cx, si; // cx = number of pixels in line asm jcxz Line_End; // jumps if cx=0 // calc error term values asm shl bx, 1; // binary shift left ... DeltaY*2 asm mov bp, bx; // bp = error term asm sub bp, si; // error term starts at DeltaY*2 - DeltaX asm shl si, 1; // DeltaX*2 asm sub bx, si; // bx = DeltaY*2 - DeltaX*2 ... Error Decrement Value ... used in loop asm add si, bx; // si = clever convert bx to DeltaY*2 ... Error Increment Value ... used in loop V_Line_Loop: asm and bp, bp; // see if error term is negative asm jns Advance_X_Coord; // no, so advance X Coord // don't advance X Coord asm add bp, si; // increment Error Term with si asm jmp Next_Y_Pixel; Advance_X_Coord: asm inc di; // increment X Coord by 1 pixel asm add bp, bx; // decrement Error Term with bx Next_Y_Pixel: asm add di, dx; // add 1 to Y Coord ... address + 320 bytes asm mov byte ptr es:[di], al; asm loop V_Line_Loop; // draw next pixel asm jmp Line_End; Down_Left: asm neg bx; // Make DeltaX positive asm cmp bx, si; // is DeltaX>DeltaY asm js V_Line2; // no, so do a Vertical Line H_Line2: asm mov cx, bx; // cx = number of pixels in line asm jcxz Line_End; // jumps if cx=0 // calc error term values asm shl si, 1; // binary shift left ... DeltaY*2 asm mov bp, si; // bp = error term asm sub bp, bx; // error term starts at DeltaY*2 - DeltaX asm shl bx, 1; // DeltaX*2 asm sub si, bx; // si = DeltaY*2 - DeltaX*2 ... Error Decrement Value ... used in loop asm add bx, si; // bx = clever convert bx to DeltaY*2 ... Error Increment Value ... used in loop H_Line_Loop2: asm and bp, bp; // see if error term is negative asm js Move_X_Coord2; // yes, stay at same Y Coord // move the Y Coord asm add di, dx; // increment Y Coord ... add 320 to pixel address asm add bp, si; // decrement Error Term with si asm jmp Next_X_Pixel2; Move_X_Coord2: asm add bp, bx; // increment Error Term with bx Next_X_Pixel2: asm dec di; // minus 1 to X Coord asm mov byte ptr es:[di], al; asm loop H_Line_Loop2; // draw next pixel asm jmp Line_End; V_Line2: asm mov cx, si; // cx = number of pixels in line asm jcxz Line_End; // jumps if cx=0 // calc error term values asm shl bx, 1; // binary shift left ... DeltaY*2 asm mov bp, bx; // bp = error term asm sub bp, si; // error term starts at DeltaY*2 - DeltaX asm shl si, 1; // DeltaX*2 asm sub bx, si; // bx = DeltaY*2 - DeltaX*2 ... Error Decrement Value ... used in loop asm add si, bx; // si = clever convert bx to DeltaY*2 ... Error Increment Value ... used in loop V_Line_Loop2: asm and bp, bp; // see if error term is negative asm jns Advance_X_Coord2; // no, so advance X Coord // don't advance X Coord asm add bp, si; // increment Error Term with si asm jmp Next_Y_Pixel2; Advance_X_Coord2: asm dec di; // decrement X Coord by 1 pixel asm add bp, bx; // decrement Error Term with bx Next_Y_Pixel2: asm add di, dx; // add 1 to Y Coord ... address + 320 bytes asm mov byte ptr es:[di], al; asm loop V_Line_Loop2; // draw next pixel asm jmp Line_End; Line_End: asm pop ds; // careful end } // end LineASM /////////////////////////////////////////////////
Christ Basic is so much easier, well until you run into slow video buffers and dirty rects problems!