; ; We draw a triangle with various interpolations ; t dd ? ;ZBufferPoint* pr1 dd ? ;ZBufferPoint* pr2 dd ? ;ZBufferPoint* l1 dd ? ;ZBufferPoint* l2 dd ? ;ZBufferPoint* fdx1 dd ? ;float fdx2 dd ? ;float fdy1 dd ? ;float fdy2 dd ? ;float fz dd ? ;float d1 dd ? ;float d2 dd ? ;float pz1 dd ? ;unsigned short* pp1 dd ? ;PIXEL* part dd ? update_left dd ? update_right dd ? nb_lines dd ? ;число горизонтальных линий в половине треугольника dx1 dd ? dy1 dd ? ;dx2 dd ? dy2 dd ? error dd ? ;int derror dd ? ;int x1 dd ? ;int dxdy_min dd ? ;int dxdy_max dd ? ;int ; warning: x2 is multiplied by 2^16 x2 dd ? ;int dx2dy2 dd ? ;int if INTERP_Z eq 1 z1 dd ? ;int dzdx dd ? ;int dzdy dd ? ;int dzdl_min dd ? ;int dzdl_max dd ? ;int end if if INTERP_RGB eq 1 r1 dd ? ;int drdx dd ? drdy dd ? drdl_min dd ? drdl_max dd ? g1 dd ? dgdx dd ? dgdy dd ? dgdl_min dd ? dgdl_max dd ? b1 dd ? dbdx dd ? dbdy dd ? dbdl_min dd ? dbdl_max dd ? end if if INTERP_ST eq 1 s1 dd ? ;int dsdx dd ? ;int dsdy dd ? ;int dsdl_min dd ? ;int dsdl_max dd ? ;int t1 dd ? ;int dtdx dd ? ;int dtdy dd ? ;int dtdl_min dd ? ;int dtdl_max dd ? ;int end if if INTERP_STZ eq 1 sz1 dd ? ;float dszdx dd ? ;float dszdy dd ? ;float dszdl_min dd ? ;float dszdl_max dd ? ;float tz1 dd ? ;float dtzdx dd ? ;float dtzdy dd ? ;float dtzdl_min dd ? ;float dtzdl_max dd ? ;float end if if DRAW_LINE_M eq 1 DRAW_LINE 0 ;переменные делаются в макросе else n dd ? ;int - длинна горизонтальной линии в пикселях if INTERP_Z eq 1 pz dd ? ;unsigned short * z dd ? ;uint zz dd ? ;uint end if if INTERP_RGB eq 1 or1 dd ? ;uint og1 dd ? ;uint ob1 dd ? ;uint end if if INTERP_ST eq 1 s dd ? ;uint t dd ? ;uint end if if INTERP_STZ eq 1 s_z dd ? ;float t_z dd ? ;float end if end if endl pushad if DEBUG ;(1) stdcall dbg_print,f_fill_tr,m_1 end if ; we sort the vertex with increasing y mov ebx,[p0] mov ecx,[p1] mov edx,[p2] mov eax,[edx+offs_zbup_y] cmp [ecx+offs_zbup_y],eax ;(2-1) jle @f xchg edx,ecx @@: mov eax,[ecx+offs_zbup_y] cmp [ebx+offs_zbup_y],eax ;(1-0) jle @f xchg ecx,ebx @@: mov eax,[edx+offs_zbup_y] cmp [ecx+offs_zbup_y],eax ;(2-1) jle @f xchg edx,ecx @@: mov [p0],ebx mov [p1],ecx mov [p2],edx ; we compute dXdx and dXdy for all interpolated values mov eax,[ecx+offs_zbup_x] sub eax,[ebx+offs_zbup_x] mov [fdx1],eax ;p1.x - p0.x mov eax,[ecx+offs_zbup_y] sub eax,[ebx+offs_zbup_y] mov [fdy1],eax ;p1.y - p0.y mov eax,[edx+offs_zbup_x] sub eax,[ebx+offs_zbup_x] mov [fdx2],eax ;p2.x - p0.x mov eax,[edx+offs_zbup_y] sub eax,[ebx+offs_zbup_y] mov [fdy2],eax ;p2.y - p0.y fild dword[fdx1] fst dword[fdx1] fild dword[fdy2] fst dword[fdy2] fmulp fild dword[fdx2] fst dword[fdx2] fild dword[fdy1] fst dword[fdy1] fmulp fsubp ;st0 = st1-st0 fst dword[fz] ;fz = fdx1 * fdy2 - fdx2 * fdy1 fldz fcompp ;if (fz == 0) return fstsw ax sahf je .end_f fld1 fdiv dword[fz] ;fz = 1.0 / fz fst dword[fz] ;st0 = fz fld dword[fdx1] fmul st0,st1 fstp dword[fdx1] ;fdx1 *= fz fld dword[fdy1] fmul st0,st1 fstp dword[fdy1] ;fdy1 *= fz fld dword[fdx2] fmul st0,st1 fstp dword[fdx2] ;fdx2 *= fz fld dword[fdy2] fmul st0,st1 fstp dword[fdy2] ;fdy2 *= fz ffree st0 fincstp if INTERP_Z eq 1 mov eax,[ecx+offs_zbup_z] sub eax,[ebx+offs_zbup_z] mov [d1],eax mov eax,[edx+offs_zbup_z] sub eax,[ebx+offs_zbup_z] mov [d2],eax fild dword[d1] ;d1 = p1.z - p0.z fild dword[d2] ;d2 = p2.z - p0.z fld dword[fdy2] fmul st0,st2 fld dword[fdy1] fmul st0,st2 fsubp fistp dword[dzdx] ;dzdx = (int) (fdy2*d1 - fdy1*d2) fld dword[fdx1] fmul st0,st1 fld dword[fdx2] fmul st0,st3 fsubp fistp dword[dzdy] ;dzdy = (int) (fdx1*d2 - fdx2*d1) ffree st0 ;free d2 fincstp ffree st0 ;free d1 fincstp end if if INTERP_RGB eq 1 mov eax,[ecx+offs_zbup_r] sub eax,[ebx+offs_zbup_r] mov [d1],eax mov eax,[edx+offs_zbup_r] sub eax,[ebx+offs_zbup_r] mov [d2],eax fild dword[d1] ;d1 = p1.r - p0.r fild dword[d2] ;d2 = p2.r - p0.r fld dword[fdy2] fmul st0,st2 fld dword[fdy1] fmul st0,st2 fsubp fistp dword[drdx] ;drdx = (int) (fdy2*d1 - fdy1*d2) fld dword[fdx1] fmul st0,st1 fld dword[fdx2] fmul st0,st3 fsubp fistp dword[drdy] ;drdy = (int) (fdx1*d2 - fdx2*d1) ffree st0 ;free d2 fincstp ffree st0 ;free d1 fincstp mov eax,[ecx+offs_zbup_g] sub eax,[ebx+offs_zbup_g] mov [d1],eax mov eax,[edx+offs_zbup_g] sub eax,[ebx+offs_zbup_g] mov [d2],eax fild dword[d1] ;d1 = p1.g - p0.g fild dword[d2] ;d2 = p2.g - p0.g fld dword[fdy2] fmul st0,st2 fld dword[fdy1] fmul st0,st2 fsubp fistp dword[dgdx] ;dgdx = (int) (fdy2*d1 - fdy1*d2) fld dword[fdx1] fmul st0,st1 fld dword[fdx2] fmul st0,st3 fsubp fistp dword[dgdy] ;dgdy = (int) (fdx1*d2 - fdx2*d1) ffree st0 ;free d2 fincstp ffree st0 ;free d1 fincstp mov eax,[ecx+offs_zbup_b] sub eax,[ebx+offs_zbup_b] mov [d1],eax mov eax,[edx+offs_zbup_b] sub eax,[ebx+offs_zbup_b] mov [d2],eax fild dword[d1] ;d1 = p1.b - p0.b fild dword[d2] ;d2 = p2.b - p0.b fld dword[fdy2] fmul st0,st2 fld dword[fdy1] fmul st0,st2 fsubp fistp dword[dbdx] ;dbdx = (int) (fdy2*d1 - fdy1*d2) fld dword[fdx1] fmul st0,st1 fld dword[fdx2] fmul st0,st3 fsubp fistp dword[dbdy] ;dbdy = (int) (fdx1*d2 - fdx2*d1) ffree st0 ;free d2 fincstp ffree st0 ;free d1 fincstp end if if INTERP_ST eq 1 mov eax,[ecx+offs_zbup_s] sub eax,[ebx+offs_zbup_s] mov [d1],eax mov eax,[edx+offs_zbup_s] sub eax,[ebx+offs_zbup_s] mov [d2],eax fild dword[d1] ;d1 = p1.s - p0.s fild dword[d2] ;d2 = p2.s - p0.s fld dword[fdy2] fmul st0,st2 fld dword[fdy1] fmul st0,st2 fsubp fistp dword[dsdx] ;dsdx = (int) (fdy2*d1 - fdy1*d2) fld dword[fdx2] fmul st0,st2 fld dword[fdx1] fmul st0,st2 fsub st0,st1 fistp dword[dsdy] ;dsdy = (int) (fdx1*d2 - fdx2*d1) ffree st0 fincstp ffree st0 ;free d2 fincstp ffree st0 ;free d1 fincstp mov eax,[ecx+offs_zbup_t] sub eax,[ebx+offs_zbup_t] mov [d1],eax mov eax,[edx+offs_zbup_t] sub eax,[ebx+offs_zbup_t] mov [d2],eax fild dword[d1] ;d1 = p1.t - p0.t fild dword[d2] ;d2 = p2.t - p0.t fld dword[fdy1] fmul st0,st1 fld dword[fdy2] fmul st0,st3 fsub st0,st1 fistp dword[dtdx] ;dtdx = (int) (fdy2*d1 - fdy1*d2) ffree st0 fincstp fld dword[fdx2] fmul st0,st2 fld dword[fdx1] fmul st0,st2 fsub st0,st1 fistp dword[dtdy] ;dtdy = (int) (fdx1*d2 - fdx2*d1) ffree st0 fincstp ffree st0 ;free d2 fincstp ffree st0 ;free d1 fincstp end if if INTERP_STZ eq 1 fild dword[ebx+offs_zbup_z] fild dword[ebx+offs_zbup_s] fmul st0,st1 fstp dword[ebx+offs_zbup_sz] ;p0.sz = (float) p0.s * p0.z fild dword[ebx+offs_zbup_t] fmulp fstp dword[ebx+offs_zbup_tz] ;p0.tz = (float) p0.t * p0.z fild dword[ecx+offs_zbup_z] fild dword[ecx+offs_zbup_s] fmul st0,st1 fstp dword[ecx+offs_zbup_sz] ;p1.sz = (float) p1.s * p1.z fild dword[ecx+offs_zbup_t] fmulp fstp dword[ecx+offs_zbup_tz] ;p1.tz = (float) p1.t * p1.z fild dword[edx+offs_zbup_z] fild dword[edx+offs_zbup_s] fmul st0,st1 fstp dword[edx+offs_zbup_sz] ;p2.sz = (float) p2.s * p2.z fild dword[edx+offs_zbup_t] fmulp fstp dword[edx+offs_zbup_tz] ;p2.tz = (float) p2.t * p2.z fld dword[ecx+offs_zbup_sz] fsub dword[ebx+offs_zbup_sz] ;d1 = p1.sz - p0.sz fld dword[edx+offs_zbup_sz] fsub dword[ebx+offs_zbup_sz] ;d2 = p2.sz - p0.sz fld dword[fdy2] fmul st0,st2 fld dword[fdy1] fmul st0,st2 fsubp fstp dword[dszdx] ;dszdx = (fdy2*d1 - fdy1*d2) fld dword[fdx2] fmul st0,st2 fld dword[fdx1] fmul st0,st2 fsub st0,st1 fstp dword[dszdy] ;dszdy = (fdx1*d2 - fdx2*d1) ffree st0 fincstp ffree st0 ;free d2 fincstp ffree st0 ;free d1 fincstp fld dword[ecx+offs_zbup_tz] fsub dword[ebx+offs_zbup_tz] ;d1 = p1.tz - p0.tz fld dword[edx+offs_zbup_tz] fsub dword[ebx+offs_zbup_tz] ;d2 = p2.tz - p0.tz fld dword[fdy1] fmul st0,st1 fld dword[fdy2] fmul st0,st3 fsub st0,st1 fstp dword[dtzdx] ;dtzdx = (fdy2*d1 - fdy1*d2) ffree st0 fincstp fld dword[fdx2] fmul st0,st2 fld dword[fdx1] fmul st0,st2 fsub st0,st1 fstp dword[dtzdy] ;dtzdy = (fdx1*d2 - fdx2*d1) ffree st0 fincstp ffree st0 ;free d2 fincstp ffree st0 ;free d1 fincstp end if ; screen coordinates mov eax,[zb] mov edx,[eax+offs_zbuf_linesize] imul edx,[ebx+offs_zbup_y] add edx,[eax+offs_zbuf_pbuf] mov [pp1],edx ;pp1 = zb.pbuf + zb.linesize * p0.y mov edx,[eax+offs_zbuf_xsize] imul edx,[ebx+offs_zbup_y] shl edx,1 add edx,[eax+offs_zbuf_zbuf] mov [pz1],edx ;pz1 = zb.zbuf + zb.xsize * p0.y DRAW_INIT mov dword[part],0 .cycle_0: mov ebx,[p0] mov ecx,[p1] mov edx,[p2] cmp dword[part],0 ;if (part == 0) jne .els_0 mov dword[update_left],1 mov dword[update_right],1 mov [l1],ebx mov [pr1],ebx fldz fld dword[fz] fcompp ;if (fz > 0) fstsw ax sahf jbe .els_1 mov [l2],edx mov [pr2],ecx jmp .end_1 .els_1: mov [l2],ecx mov [pr2],edx .end_1: mov eax,[ecx+offs_zbup_y] sub eax,[ebx+offs_zbup_y] mov [nb_lines],eax ;nb_lines = p1.y - p0.y jmp .end_0 .els_0: ; second part fldz fld dword[fz] fcompp ;if (fz > 0) fstsw ax sahf jbe .els_2 mov dword[update_left],0 mov dword[update_right],1 mov [pr1],ecx mov [pr2],edx jmp .end_2 .els_2: mov dword[update_left],1 mov dword[update_right],0 mov [l1],ecx mov [l2],edx .end_2: mov eax,[edx+offs_zbup_y] sub eax,[ecx+offs_zbup_y] inc eax mov [nb_lines],eax ;nb_lines = p2.y - p1.y + 1 .end_0: ; compute the values for the left edge cmp dword[update_left],0 ;if (update_left) je .end_upd_l mov ebx,[l1] mov ecx,[l2] mov edx,[ecx+offs_zbup_y] sub edx,[ebx+offs_zbup_y] mov [dy1],edx ;dy1 = l2.y - l1.y mov eax,[ecx+offs_zbup_x] sub eax,[ebx+offs_zbup_x] mov [dx1],eax ;dx1 = l2.x - l1.x cmp edx,0 ;if (dy1 > 0) jle .els_3 xor edx,edx cmp eax,0 jl .otr_dx1 shl eax,16 div dword[dy1] ;eax = (dx1 << 16) / dy1 jmp .end_3 .otr_dx1: neg eax inc eax shl eax,16 div dword[dy1] ;eax = (-dx1 << 16) / dy1 neg eax inc eax jmp .end_3 .els_3: xor eax,eax .end_3: mov edx,[ebx+offs_zbup_x] mov [x1],edx ;x1 = l1.x mov dword[error],0 ;error = 0 mov dword[derror],eax and dword[derror],0xffff ;derror = eax & 0x0000ffff shr eax,16 bt eax,15 jnc @f or eax,0xffff0000 @@: mov [dxdy_min],eax ;dxdy_min = eax >> 16 inc eax mov [dxdy_max],eax if INTERP_Z eq 1 mov eax,[l1] mov eax,[eax+offs_zbup_z] mov [z1],eax ;z1 = l1.z mov eax,[dzdx] imul eax,[dxdy_min] add eax,[dzdy] mov [dzdl_min],eax ;dzdl_min = (dzdy +dzdx*dxdy_min) add eax,[dzdx] mov [dzdl_max],eax ;dzdl_max = dzdl_min +dzdx end if if INTERP_RGB eq 1 mov ebx,[l1] mov eax,[ebx+offs_zbup_r] mov [r1],eax ;r1 = l1.r mov eax,[drdx] imul eax,[dxdy_min] add eax,[drdy] mov [drdl_min],eax ;drdl_min = (drdy +drdx*dxdy_min) add eax,[drdx] mov [drdl_max],eax ;drdl_max = drdl_min +drdx mov eax,[ebx+offs_zbup_g] mov [g1],eax ;g1 = l1.g mov eax,[dgdx] imul eax,[dxdy_min] add eax,[dgdy] mov [dgdl_min],eax ;dgdl_min = (dgdy +dgdx*dxdy_min) add eax,[dgdx] mov [dgdl_max],eax ;dgdl_max = dgdl_min +dgdx mov eax,[ebx+offs_zbup_b] mov [b1],eax ;b1 = l1.b mov eax,[dbdx] imul eax,[dxdy_min] add eax,[dbdy] mov [dbdl_min],eax ;dbdl_min = (dbdy +dbdx*dxdy_min) add eax,[dbdx] mov [dbdl_max],eax ;dbdl_max = dbdl_min +dbdx end if if INTERP_ST eq 1 mov ebx,[l1] mov eax,[ebx+offs_zbup_s] mov [s1],eax ;s1 = l1.s mov eax,[dsdx] imul eax,[dxdy_min] add eax,[dsdy] mov [dsdl_min],eax ;dsdl_min = (dsdy +dsdx*dxdy_min) add eax,[dsdx] mov [dsdl_max],eax ;dsdl_max = dsdl_min +dsdx mov eax,[ebx+offs_zbup_t] mov [t1],eax ;t1 = l1.t mov eax,[dtdx] imul eax,[dxdy_min] add eax,[dtdy] mov [dtdl_min],eax ;dtdl_min = (dtdy +dtdx*dxdy_min) add eax,[dtdx] mov [dtdl_max],eax ;dtdl_max = dtdl_min +dtdx end if if INTERP_STZ eq 1 mov ebx,[l1] mov eax,[ebx+offs_zbup_sz] mov [sz1],eax ;sz1 = l1.sz - преобразований нет, потому без сопроцессора fild dword[dxdy_min] fmul dword[dszdx] fadd dword[dszdy] fst dword[dszdl_min] ;dszdl_min = (dszdy +dszdx*dxdy_min) fadd dword[dszdx] fstp dword[dszdl_max] ;dszdl_max = dszdl_min +dszdx mov eax,[ebx+offs_zbup_tz] mov [tz1],eax ;tz1 = l1.tz - преобразований нет, потому без сопроцессора fild dword[dxdy_min] fmul dword[dtzdx] fadd dword[dtzdy] fst dword[dtzdl_min] ;dtzdl_min = (dtzdy +dtzdx*dxdy_min) fadd dword[dtzdx] fstp dword[dtzdl_max] ;dtzdl_max = dtzdl_min +dtzdx end if .end_upd_l: ; compute values for the right edge cmp dword[update_right],0 ;if(update_right) je .end_upd_r mov ebx,[pr1] mov ecx,[pr2] mov edx,[ebx+offs_zbup_x] mov eax,[ecx+offs_zbup_x] sub eax,edx ;mov [dx2],eax ;dx2 = pr2.x - pr1.x shl edx,16 mov [x2],edx ; x2 = pr1.x << 16 mov edx,[ecx+offs_zbup_y] sub edx,[ebx+offs_zbup_y] mov [dy2],edx ;dy2 = pr2.y - pr1.y cmp edx,0 ;if (dy2 > 0) jle .els_4 xor edx,edx cmp eax,0 jl .otr_dx2 shl eax,16 div dword[dy2] ;eax = (dx2 << 16) / dy2 jmp .end_4 .otr_dx2: neg eax inc eax ;dx2 *= -1 shl eax,16 div dword[dy2] ;eax = (-dx2 << 16) / dy2 neg eax inc eax jmp .end_4 .els_4: xor eax,eax .end_4: mov [dx2dy2],eax .end_upd_r: ; we draw all the scan line of the part if DEBUG ;[nb_lines] push ecx edi mov eax,[nb_lines] mov ecx,80 lea edi,[buf_param] stdcall convert_int_to_str,ecx stdcall str_n_cat,edi,txt_nl,2 stdcall dbg_print,f_fill_tr_nl,buf_param pop edi ecx end if .beg_w_lin: cmp dword[nb_lines],0 ;while (nb_lines>0) jle .end_w_lin dec dword[nb_lines] if DRAW_LINE_M eq 1 DRAW_LINE 1 else ; generic draw line mov eax,[x2] shr eax,16 mov edi,[x1] sub eax,edi mov [n],eax ;n = (x2 >> 16) - x1 imul edi,PSZB add edi,[pp1] ;pp = pp1 + x1 * PSZB if DEBUG ;[n], [x1], [x2]>>16 push ecx edi mov eax,[n] mov ecx,80 lea edi,[buf_param] stdcall convert_int_to_str,ecx stdcall str_n_cat,edi,txt_zp_sp,2 stdcall str_len,edi add edi,eax sub ecx,eax mov eax,[x1] stdcall convert_int_to_str,ecx stdcall str_n_cat,edi,txt_zp_sp,2 stdcall str_len,edi add edi,eax sub ecx,eax mov eax,[x2] shr eax,16 stdcall convert_int_to_str,ecx stdcall str_n_cat,edi,txt_nl,2 stdcall dbg_print,f_fill_tr_nll,buf_param pop edi ecx end if if INTERP_Z eq 1 mov eax,[x1] shl eax,1 add eax,[pz1] mov [pz],eax mov eax,[z1] mov [z],eax end if if INTERP_RGB eq 1 mov eax,[r1] mov [or1],eax mov eax,[g1] mov [og1],eax mov eax,[b1] mov [ob1],eax end if if INTERP_ST eq 1 mov eax,[s1] mov [s],eax mov eax,[t1] mov [t],eax end if if INTERP_STZ eq 1 mov eax,[sz1] mov [s_z],eax mov eax,[tz1] mov [t_z],eax end if align 4 .cycle_1: ;while (n>=3) cmp dword[n],3 jl .cycle_2 PUT_PIXEL 0 PUT_PIXEL 1 PUT_PIXEL 2 PUT_PIXEL 3 if INTERP_Z eq 1 add dword[pz],8 ;=4*sizeof(uint) end if add edi,4*PSZB sub dword[n],4 jmp .cycle_1 .cycle_2: ;while (n>=0) cmp dword[n],0 jl .cycle_2_end PUT_PIXEL 0 if INTERP_Z eq 1 add dword[pz],2 ;=sizeof(uint) end if add edi,PSZB dec dword[n] jmp .cycle_2 .cycle_2_end: end if ;проверка от макроса DRAW_LINE ; left edge mov eax,[derror] add [error],eax cmp dword[error],0 ;if (error > 0) jle .els_er sub dword[error],0x10000 mov eax,[dxdy_max] add [x1],eax if INTERP_Z eq 1 mov eax,[dzdl_max] add [z1],eax end if if INTERP_RGB eq 1 mov eax,[drdl_max] add [r1],eax mov eax,[dgdl_max] add [g1],eax mov eax,[dbdl_max] add [b1],eax end if if INTERP_ST eq 1 mov eax,[dsdl_max] add [s1],eax mov eax,[dtdl_max] add [t1],eax end if if INTERP_STZ eq 1 fld dword[dszdl_max] fadd dword[sz1] fstp dword[sz1] fld dword[dtzdl_max] fadd dword[tz1] fstp dword[tz1] end if jmp .end_er .els_er: mov eax,[dxdy_min] add [x1],eax if INTERP_Z eq 1 mov eax,[dzdl_min] add [z1],eax end if if INTERP_RGB eq 1 mov eax,[drdl_min] add [r1],eax mov eax,[dgdl_min] add [g1],eax mov eax,[dbdl_min] add [b1],eax end if if INTERP_ST eq 1 mov eax,[dsdl_min] add [s1],eax mov eax,[dtdl_min] add [t1],eax end if if INTERP_STZ eq 1 fld dword[dszdl_min] fadd dword[sz1] fstp dword[sz1] fld dword[dtzdl_min] fadd dword[tz1] fstp dword[tz1] end if .end_er: ; right edge mov eax,[dx2dy2] add [x2],eax ; screen coordinates mov ebx,[zb] mov eax,[ebx+offs_zbuf_linesize] add [pp1],eax mov eax,[ebx+offs_zbuf_xsize] shl eax,1 add [pz1],eax jmp .beg_w_lin .end_w_lin: inc dword[part] cmp dword[part],2 jl .cycle_0 .end_f: popad ret endp restore INTERP_Z restore INTERP_RGB restore INTERP_ST restore INTERP_STZ restore DRAW_LINE_M purge DRAW_INIT purge DRAW_LINE purge PUT_PIXEL