/**********************************************************************
This file is part of Crack dot Com's free source code release of
Golgotha.
for
information about compiling & licensing issues visit this URL
If that doesn't help, contact Jonathan Clark at
golgotha_source@usa.net (Subject should have "GOLG" in it)
***********************************************************************/
#include "glide/gr_vram.hh"
#include "image/image.hh"
#include "r1_api.hh"
#include "time/profile.hh"
#include "video/glide/glide_display.hh"
#include "r1_clip.hh"
#include "r1_win.hh"
#include "video/glide/glide.h"
#include "device/processor.hh"
#ifdef _WINDOWS
#include "software/amd3d/amd3d.h"
#define USE_AMD3D
#endif
static i4_bool gr_support_amd3d = i4_F;
static float gr_const_r, gr_const_g, gr_const_b, gr_const_a, gr_x2, gr_y2;
//dont reorder this
static struct gr_static_struct
{
float gr_xadd, gr_yadd; // window offset additions
float gr_smul, gr_tmul; // texture coordinate multiplers
float gr_r_tint_mul, gr_g_tint_mul;
float gr_a_mul, gr_w_mul; // scales the w value to best fit application's range
float VTX_SNAP_1, VTX_SNAP_2;
float gr_b_tint_mul;
float gr_xoff, gr_yoff; // window offset additions
} gr_static_info = {0.f, 0.f, 0.f, 0.f, 1.f, 1.f, 255.f, 1.f, (float)(1L<<19), (float)(1L<<19), 1.f };
static i4_profile_class pf_glide_single_poly("glide render single poly");
static i4_profile_class pf_glide_shadows("glide shadows");
static i4_profile_class pf_glide_sprite("glide sprite");
static i4_profile_class pf_render_list("glide render list");
static i4_profile_class pf_use_texture("glide use texture");
static i4_profile_class pf_begin_render("glide begin render");
static i4_profile_class pf_end_render("glide end render");
static i4_profile_class pf_vram_select_texture("glide select texture");
static i4_profile_class pf_setup_vert("glide setup vert");
typedef i4_bool (*gr_copy_vert_function_type)(GrVertex *dst, r1_vert *src, int t_verts);
gr_copy_vert_function_type gr_copy_vert_function=0;
w32 gr_old_flags;
#ifdef _WINDOWS
inline w32 gset_and_get_flags() // returns old flags
{
w32 control_word_new;
w32 control_word_old;
_asm {
finit
fwait
fnstcw control_word_old ;
fwait
mov eax, control_word_old ;
and eax, 0xfffffcff ;
mov control_word_new, eax ;
fldcw control_word_new ;
fwait
}
return control_word_old;
}
inline void grestore_flags(w32 old_value) // returns old flags
{
_asm {
fldcw old_value ;
}
}
inline void gsnap_vert(GrVertex *dst)
{
dst->x += gr_static_info.VTX_SNAP_1;
dst->x -= gr_static_info.VTX_SNAP_1;
dst->y += gr_static_info.VTX_SNAP_1;
dst->y -= gr_static_info.VTX_SNAP_1;
}
#else
inline w32 gset_and_get_flags()
{
return 0;
}
inline void grestore_flags(w32 old)
{
}
inline void gsnap_vert(GrVertex *dst)
{
dst->x = float(int(dst->x * 16.0))/16.;
dst->y = float(int(dst->y * 16.0))/16.;
}
#endif
#if 1
inline i4_bool gr_check_vert(GrVertex *dst) { return i4_T; }
#else
inline i4_bool gr_check_vert(GrVertex *dst)
{
if (dst->xyx>gr_x2 || dst->y>gr_y2)
return i4_F;
else
return i4_T;
}
#endif
i4_bool gr_copy_all_amd3d(GrVertex *dst, r1_vert *src, int t_verts);
i4_bool gr_copy_all(GrVertex *dst, r1_vert *src, int t_verts)
{
while (t_verts--)
{
float oow = src->w * gr_static_info.gr_w_mul;
dst->x = src->px + gr_static_info.gr_xoff;
dst->y = src->py + gr_static_info.gr_yoff;
gsnap_vert(dst);
dst->oow = oow;
dst->r = src->r * gr_static_info.gr_r_tint_mul;
dst->g = src->g * gr_static_info.gr_g_tint_mul;
dst->b = src->b * gr_static_info.gr_b_tint_mul;
dst->tmuvtx[0].sow = src->s * gr_static_info.gr_smul * oow;
dst->tmuvtx[0].tow = src->t * gr_static_info.gr_tmul * oow;
dst->tmuvtx[0].oow = oow;
dst->a = src->a*255.f;
//if (!gr_check_vert(dst))
//{
// i4_warning("vert out of window");
// return i4_F;
//}
dst++;
src++;
}
return i4_T;
}
// this is used if R1_ALPHA_DISABLED & R1_WHITE_SHADING
i4_bool gr_copy_white_shade(GrVertex *dst, r1_vert *src, int t_verts)
{
while (t_verts--)
{
float oow = src->w * gr_static_info.gr_w_mul;
dst->x=src->px + gr_static_info.gr_xoff;
dst->y=src->py + gr_static_info.gr_yoff;
gsnap_vert(dst);
dst->oow=oow;
float base_color=src->r;
dst->r=base_color * gr_static_info.gr_r_tint_mul;
dst->g=base_color * gr_static_info.gr_g_tint_mul;
dst->b=base_color * gr_static_info.gr_b_tint_mul;
dst->tmuvtx[0].sow=src->s * gr_static_info.gr_smul * oow;
dst->tmuvtx[0].tow=src->t * gr_static_info.gr_tmul * oow;
dst->tmuvtx[0].oow=oow;
dst->a=src->a * 255;
if (!gr_check_vert(dst))
{
i4_warning("vert out of window");
return i4_F;
}
dst++;
src++;
}
return i4_T;
}
i4_bool gr_copy_fullbright_shade(GrVertex *dst, r1_vert *src, int t_verts)
{
while (t_verts--)
{
float oow = src->w * gr_static_info.gr_w_mul;
dst->x=src->px + gr_static_info.gr_xoff;
dst->y=src->py + gr_static_info.gr_yoff;
gsnap_vert(dst);
dst->oow=oow;
dst->r = gr_static_info.gr_r_tint_mul;
dst->g = gr_static_info.gr_g_tint_mul;
dst->b = gr_static_info.gr_b_tint_mul;
dst->tmuvtx[0].sow=src->s * gr_static_info.gr_smul * oow;
dst->tmuvtx[0].tow=src->t * gr_static_info.gr_tmul * oow;
dst->tmuvtx[0].oow=oow;
dst->a=src->a * 255;
if (!gr_check_vert(dst))
{
i4_warning("vert out of window");
return i4_F;
}
dst++;
src++;
}
return i4_T;
}
i4_bool gr_copy_no_shade(GrVertex *dst, r1_vert *src, int t_verts)
{
while (t_verts--)
{
float oow = src->w * gr_static_info.gr_w_mul;
dst->x=src->px + gr_static_info.gr_xoff;
dst->y=src->py + gr_static_info.gr_yoff;
gsnap_vert(dst);
dst->oow=oow;
dst->r = gr_const_r * gr_static_info.gr_r_tint_mul;
dst->g = gr_const_g * gr_static_info.gr_g_tint_mul;
dst->b = gr_const_b * gr_static_info.gr_b_tint_mul;
dst->tmuvtx[0].sow=src->s * gr_static_info.gr_smul * oow;
dst->tmuvtx[0].tow=src->t * gr_static_info.gr_tmul * oow;
dst->tmuvtx[0].oow=oow;
dst->a=src->a * 255;
if (!gr_check_vert(dst))
{
i4_warning("vert out of window");
return i4_F;
}
dst++;
src++;
}
return i4_T;
}
class r1_glide_render_window_class : public r1_render_window_class
{
public:
r1_glide_render_window_class *next_rw;
i4_bool need_flip_update;
r1_glide_render_window_class(w16 w, w16 h,
r1_expand_type expand_type,
r1_render_api_class *api);
~r1_glide_render_window_class();
void draw(i4_draw_context_class &context);
void request_redraw(i4_bool for_a_child)
{
if (!for_a_child)
{
if (children.begin()!=children.end())
children.begin()->request_redraw(i4_F);
}
need_flip_update=i4_T;
r1_render_window_class::request_redraw(for_a_child);
}
char *name() { return "glide render window"; }
};
r1_glide_render_window_class *r1_render_window_list=0;
r1_glide_render_window_class::r1_glide_render_window_class(w16 w, w16 h,
r1_expand_type expand_type,
r1_render_api_class *api)
: r1_render_window_class(w,h, expand_type, api)
{
need_flip_update=i4_T;
next_rw=r1_render_window_list;
r1_render_window_list=this;
}
r1_glide_render_window_class::~r1_glide_render_window_class()
{
if (this==r1_render_window_list)
r1_render_window_list=next_rw;
else
{
r1_glide_render_window_class *last=0;
for (r1_glide_render_window_class *p=r1_render_window_list; p && p!=this;)
{
last=p;
p=p->next_rw;
}
last->next_rw=next_rw;
}
}
class r1_glide_render_class : public r1_render_api_class
{
static i4_display_class *display;
r1_write_mask_type pre_holy_write_mask;
r1_alpha_type pre_holy_alpha_mode;
i4_bool texture_mode;
i4_bool holy_mode;
i4_bool holy_mode_lock;
public:
r1_glide_render_class *next_rw;
enum { MAX_VERTS=32 };
char *name() { return "glide"; }
virtual void copy_part(i4_image_class *im,
int x, int y, // position on screen
int x1, int y1, // area of image to copy
int x2, int y2)
{
if (i4_glide_display)
{
i4_image_class *bbuf;
bbuf=i4_glide_display->lock_frame_buffer(I4_BACK_FRAME_BUFFER, I4_FRAME_BUFFER_WRITE);
if (bbuf)
{
im->put_part(bbuf, i4_f_to_i(gr_static_info.gr_xoff) + x,
i4_f_to_i(gr_static_info.gr_yoff) + y,x1,y1,x2,y2,
*context);
i4_glide_display->unlock_frame_buffer(I4_BACK_FRAME_BUFFER);
}
}
}
void enable_holy()
{
if (!holy_mode && !holy_mode_lock)
{
holy_mode_lock = i4_T;
pre_holy_write_mask = get_write_mask();
pre_holy_alpha_mode = get_alpha_mode();
set_write_mode(R1_COMPARE_W | R1_WRITE_COLOR);
holy_mode = i4_T;
set_alpha_mode(R1_ALPHA_LINEAR);
holy_mode_lock = i4_F;
}
}
void disable_holy()
{
if (holy_mode && !holy_mode_lock)
{
holy_mode_lock = i4_T;
set_write_mode(pre_holy_write_mask);
holy_mode=i4_F;
set_alpha_mode(pre_holy_alpha_mode);
holy_mode_lock = i4_F;
}
}
virtual void set_z_range(float _near_z, float _far_z)
{
r1_near_clip_z = _near_z;
r1_far_clip_z = _far_z;
gr_static_info.gr_w_mul = _far_z / (float)GR_WDEPTHVALUE_FARTHEST;
}
r1_color_tint_handle register_color_tint(i4_float r, i4_float g, i4_float b)
{
if (num_color_tints==MAX_COLOR_TINTS) return 0;
color_tint_list[num_color_tints].r = r * 255.f;
color_tint_list[num_color_tints].g = g * 255.f;
color_tint_list[num_color_tints].b = b * 255.f;
num_color_tints++;
return num_color_tints-1;
}
void set_color_tint(r1_color_tint_handle c)
{
if (c==0)
{
gr_static_info.gr_r_tint_mul = 255.f;
gr_static_info.gr_g_tint_mul = 255.f;
gr_static_info.gr_b_tint_mul = 255.f;
color_tint_on = i4_F;
}
else
{
color_tint_on = i4_T;
gr_static_info.gr_r_tint_mul = color_tint_list[c].r;
gr_static_info.gr_g_tint_mul = color_tint_list[c].g;
gr_static_info.gr_b_tint_mul = color_tint_list[c].b;
}
}
virtual void set_shading_mode(r1_shading_type type)
{
if (type!=shade_mode)
{
if (type==R1_SHADE_DISABLED)
gr_copy_vert_function=gr_copy_fullbright_shade;
else if (type==R1_CONSTANT_SHADING)
{
gr_const_r=((const_color&0xff0000)>>16)/255.0;
gr_const_g=((const_color&0xff00)>>8)/255.0;
gr_const_b=((const_color&0xff)>>0)/255.0;
gr_copy_vert_function=gr_copy_no_shade;
}
else if (type==R1_WHITE_SHADING)
gr_copy_vert_function=gr_copy_white_shade;
else
{
if (!gr_support_amd3d)
gr_copy_vert_function = gr_copy_all;
else
gr_copy_vert_function = gr_copy_all_amd3d;
}
r1_render_api_class::set_shading_mode(type);
}
}
virtual void set_constant_color(w32 color)
{
if (color!=get_constant_color())
{
r1_render_api_class::set_constant_color(color);
switch (shade_mode)
{
case R1_SHADE_DISABLED :
gr_copy_vert_function=gr_copy_fullbright_shade;
break;
case R1_CONSTANT_SHADING :
{
gr_const_r=((const_color&0xff0000)>>16)/255.0;
gr_const_g=((const_color&0xff00)>>8)/255.0;
gr_const_b=((const_color&0xff)>>0)/255.0;
gr_copy_vert_function=gr_copy_no_shade;
} break;
case R1_WHITE_SHADING :
gr_copy_vert_function=gr_copy_white_shade;
break;
case R1_COLORED_SHADING :
if (!gr_support_amd3d)
gr_copy_vert_function = gr_copy_all;
else
gr_copy_vert_function = gr_copy_all_amd3d;
break;
}
grConstantColorValue(color);
//grAlphaTestReferenceValue(color>>24);
}
}
r1_glide_render_class()
{
holy_mode = i4_F;
holy_mode_lock = i4_F;
last_node=0;
write_mask=R1_COMPARE_W | R1_WRITE_W | R1_WRITE_COLOR;
shade_mode=R1_SHADE_DISABLED;
alpha_mode=R1_ALPHA_DISABLED;
texture_mode=i4_T;
//currently, only flag is R1_SOFTWARE (and this is hardware)
render_device_flags=0;
}
r1_glide_vram_class *vram() { return (r1_glide_vram_class *)tmanager; }
// returns false if display is not compatible with render_api, i.e. if you pass
// the directx display to the glide render api it return false
// init will create the texture manager, which can be used after this call
virtual i4_bool init(i4_display_class *_display)
{
if (_display==i4_glide_display)
{
display=_display;
tmanager=new r1_glide_vram_class(display->get_palette());
#ifdef USE_AMD3D
i4_cpu_info_struct s;
i4_get_cpu_info(&s);
if (s.cpu_flags & i4_cpu_info_struct::AMD3D)
gr_support_amd3d = i4_T;
#endif
if (!gr_support_amd3d)
gr_copy_vert_function = gr_copy_all;
else
gr_copy_vert_function = gr_copy_all_amd3d;
return i4_T;
}
else return i4_F;
}
// texture handle is obtained from the texture manager, this is enables texture mapping
virtual void use_texture(r1_texture_handle material_ref, sw32 desired_width, w32 frame)
{
pf_use_texture.start();
if (!tmanager->valid_handle(material_ref))
{
disable_texture();
pf_use_texture.stop();
return;
}
else
if (!texture_mode)
{
guColorCombineFunction(GR_COLORCOMBINE_TEXTURE_TIMES_ITRGB);
texture_mode = i4_T;
}
sw32 width,height;
r1_miplevel_t *mip = tmanager->get_texture(material_ref, frame, desired_width, width, height);
// don't select the texture again if it's the same one we used last time
if (mip)
{
i4_bool is_alpha = mip->entry->is_alphatexture();
i4_bool is_holy = mip->entry->is_transparent();
if (is_alpha || is_holy)
enable_holy();
else
disable_holy();
if (mip != last_node)
{
last_node = mip;
pf_vram_select_texture.start();
vram()->select_texture(mip->vram_handle, gr_static_info.gr_smul, gr_static_info.gr_tmul, is_holy, is_alpha);
pf_vram_select_texture.stop();
}
}
pf_use_texture.stop();
}
// drawing will the constant color to render with if textures are disabled
virtual void disable_texture()
{
if (texture_mode)
{
guColorCombineFunction(GR_COLORCOMBINE_ITRGB); // turn off textures
texture_mode = i4_F;
last_node = 0;
disable_holy();
}
}
virtual void set_alpha_mode(r1_alpha_type type)
{
if (holy_mode)
disable_holy();
if (type==get_alpha_mode()) return;
switch (type)
{
case R1_ALPHA_DISABLED :
grAlphaBlendFunction(GR_BLEND_ONE,GR_BLEND_ZERO,
GR_BLEND_ZERO,GR_BLEND_ZERO);
grAlphaCombine(GR_COMBINE_FUNCTION_ZERO, GR_COMBINE_FACTOR_NONE,
GR_COMBINE_LOCAL_NONE,GR_COMBINE_OTHER_NONE,0);
break;
case R1_ALPHA_CONSTANT : // enable alpha
grAlphaBlendFunction(GR_BLEND_SRC_ALPHA, GR_BLEND_ONE_MINUS_SRC_ALPHA,
GR_BLEND_ZERO,GR_BLEND_ZERO);
if (!holy_mode)
{
grAlphaCombine(GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_OTHER_CONSTANT,
GR_COMBINE_LOCAL_NONE,GR_COMBINE_OTHER_CONSTANT,0);
}
else
{
grAlphaCombine(GR_COMBINE_FUNCTION_SCALE_OTHER,
GR_COMBINE_FACTOR_TEXTURE_ALPHA,
GR_COMBINE_LOCAL_NONE,
GR_COMBINE_OTHER_CONSTANT,0);
}
break;
case R1_ALPHA_LINEAR :
grAlphaBlendFunction(GR_BLEND_SRC_ALPHA, GR_BLEND_ONE_MINUS_SRC_ALPHA,
GR_BLEND_ZERO,GR_BLEND_ZERO);
if (!holy_mode)
{
grAlphaCombine(GR_COMBINE_FUNCTION_LOCAL, GR_COMBINE_FACTOR_NONE,
GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_NONE, 0);
}
else
{
grAlphaCombine(GR_COMBINE_FUNCTION_SCALE_OTHER,
GR_COMBINE_FACTOR_TEXTURE_ALPHA,
GR_COMBINE_LOCAL_NONE,
GR_COMBINE_OTHER_ITERATED,0);
}
break;
}
r1_render_api_class::set_alpha_mode(type);
}
virtual void set_filter_mode(r1_filter_type type)
{
if (type!=filter_mode)
{
//if (type==R1_NO_FILTERING)
// grTexFilterMode(GR_TMU0,GR_TEXTUREFILTER_POINT_SAMPLED,GR_TEXTUREFILTER_POINT_SAMPLED);
//else
//if (type==R1_BILINEAR_FILTERING)
grTexFilterMode(GR_TMU0,GR_TEXTUREFILTER_BILINEAR,GR_TEXTUREFILTER_BILINEAR);
}
r1_render_api_class::set_filter_mode(type);
}
virtual void set_write_mode(r1_write_mask_type mask)
{
if (holy_mode)
disable_holy();
w32 diff=mask^get_write_mask(); // bits that differ
if (diff & R1_WRITE_COLOR) // need to change the color write mask
grColorMask(mask & R1_WRITE_COLOR ? 1 : 0, 0); // turn on color writes
if (diff & (R1_WRITE_W | R1_COMPARE_W)) // change z write or compare?
{
switch (mask & (R1_WRITE_W | R1_COMPARE_W))
{
case R1_WRITE_W :
grDepthBufferMode(GR_DEPTHBUFFER_WBUFFER);
grDepthMask(1);
grDepthBufferFunction(GR_CMP_ALWAYS); // write to all z always (no compare)
break;
case R1_WRITE_W | R1_COMPARE_W :
grDepthBufferMode(GR_DEPTHBUFFER_WBUFFER);
grDepthMask(1);
grDepthBufferFunction(GR_CMP_LESS);
break;
case R1_COMPARE_W :
grDepthBufferMode(GR_DEPTHBUFFER_WBUFFER);
grDepthMask(0);
grDepthBufferFunction(GR_CMP_LESS);
break;
case 0 :
grDepthBufferMode(GR_DEPTHBUFFER_DISABLE);
grDepthMask(0);
break;
}
}
r1_render_api_class::set_write_mode(mask);
}
/*
virtual void render_poly(int t_verts, r1_vert *verts, int *vertex_index)
{
pf_setup_vert.start();
GrVertex g_vert_buf[MAX_VERTS];
for (int i=0; iget_palette());
}
r1_render_window_class *create_render_window(int visable_w, int visable_h,
r1_expand_type type)
{
return new r1_glide_render_window_class(visable_w, visable_h, R1_COPY_1x1, this);
}
void clear_area(int x1, int y1, int x2, int y2, w32 color, float z)
{
w32 old_const_color=get_constant_color();
set_constant_color(color);
r1_shading_type old_shade_mode=get_shade_mode();
set_shading_mode(R1_CONSTANT_SHADING);
disable_texture();
disable_holy();
r1_vert v[4];
float w = 1.f/z;
v[0].px=x1; v[0].py=y1;
v[1].px=x1; v[1].py=y2+1;
v[2].px=x2+1; v[2].py=y2+1;
v[3].px=x2+1; v[3].py=y1;
GrVertex g_vert_buf[4];
if (!gr_copy_vert_function(g_vert_buf, v, 4)) return;
if (z==r1_far_clip_z)
{
g_vert_buf[0].oow = GR_WDEPTHVALUE_NEAREST;
g_vert_buf[1].oow = GR_WDEPTHVALUE_NEAREST;
g_vert_buf[2].oow = GR_WDEPTHVALUE_NEAREST;
g_vert_buf[3].oow = GR_WDEPTHVALUE_NEAREST;
}
else
if (z==r1_near_clip_z)
{
g_vert_buf[0].oow = GR_WDEPTHVALUE_FARTHEST;
g_vert_buf[1].oow = GR_WDEPTHVALUE_FARTHEST;
g_vert_buf[2].oow = GR_WDEPTHVALUE_FARTHEST;
g_vert_buf[3].oow = GR_WDEPTHVALUE_FARTHEST;
}
else
{
float oow = (1.f/(float)z) * gr_static_info.gr_w_mul;
g_vert_buf[0].oow = oow;
g_vert_buf[1].oow = oow;
g_vert_buf[2].oow = oow;
g_vert_buf[3].oow = oow;
}
grDrawPolygonVertexList(4, g_vert_buf);
set_shading_mode(old_shade_mode);
set_constant_color(old_const_color);
}
};
r1_glide_render_class r1_glide_render;
i4_display_class *r1_glide_render_class::display=0;
void r1_glide_render_window_class::draw(i4_draw_context_class &_context)
{
r1_render_api_class::context = &_context;
gr_static_info.gr_xoff = _context.xoff;
gr_static_info.gr_yoff = _context.yoff;
gr_static_info.gr_xadd = _context.xoff + gr_static_info.VTX_SNAP_1;
gr_static_info.gr_yadd = _context.yoff + gr_static_info.VTX_SNAP_1;
gr_x2 = gr_static_info.gr_xoff + width();
gr_y2 = gr_static_info.gr_yoff + height();
pf_begin_render.start();
clip_with_z(_context);
pf_begin_render.stop();
gr_old_flags=gset_and_get_flags();
r1_render_window_class::draw(_context);
grestore_flags(gr_old_flags);
if (need_flip_update)
{
request_redraw(i4_T);
for (win_iter i=children.begin(); i!=children.end(); ++i)
i->request_redraw(i4_F);
need_flip_update=i4_F;
}
// if there was a texture miss
if (r1_glide_render.get_tmanager()->texture_resolution_change())
for (r1_glide_render_window_class *w=r1_render_window_list; w; w=w->next_rw)
w->request_redraw(i4_F);
}
#ifdef USE_AMD3D
w32 r1vtxsize = sizeof(r1_vert);
w32 grvtxsize = sizeof(GrVertex);
i4_bool gr_copy_all_amd3d(GrVertex *dst, r1_vert *src, int t_verts)
{
_asm
{
mov esi,dword ptr [t_verts]
mov edi,dword ptr [src]
and esi,esi
jz done
lea ecx, dword ptr [gr_static_info]
mov edx,dword ptr [dst]
movq mm7, qword ptr [ecx]gr_static_struct.gr_xadd //gr_y_add | gr_x_add
mov eax,edi
movq mm6, qword ptr [ecx]gr_static_struct.gr_smul //gr_tmul | gr_smul
mov ebx,edx
movq mm5, qword ptr [ecx]gr_static_struct.gr_r_tint_mul //gr_g_tint | gr_r_tint
add eax,dword ptr [r1vtxsize]
movq mm4, qword ptr [ecx]gr_static_struct.gr_a_mul //gr_w_mul | gr_a_mul
add ebx,dword ptr [grvtxsize]
//while (t_verts--)
//{
looper:
cmp esi,1
je dont_prefetch
prefetch (_eax)
prefetch (_ebx)
dont_prefetch:
movq mm3, qword ptr [edi]r1_vert.a //src->w | src->a
movq mm2, qword ptr [edi]r1_vert.r //src->g | src->r
movq mm1, qword ptr [edi]r1_vert.s //src->t | src->s
movq mm0, qword ptr [edi]r1_vert.px //src->py | src->px
pfmul (m3, m4) //mm3 - src->w * gr_w_mul | src->a * gr_a_mul
pfmul (m2, m5) //mm2 - src->g * gr_g_mul | src->r * gr_r_mul
pfmul (m1, m6) //mm1 - src->t * gr_tmul | src->s * gr_smul
pfadd (m0, m7) //mm0 - src->py + gr_yoff + VTX_SNAP | src->px + gr_xoff + VTX_SNAP
movq qword ptr [edx]GrVertex.a, mm3 //dst->oow = src->w*gr_w_mul | dst->a = src->a * 255.f
punpckhdq mm3,mm3 //mm3 - oow | oow
movq qword ptr [edx]GrVertex.r, mm2 //dst->r = src->r*gr_r_mul | dst->g = src->g * gr_g_mul
add eax,dword ptr [r1vtxsize]
movd dword ptr [edx]GrVertex.tmuvtx[0].oow,mm3
pfmul (m1, m3) //mm1 - tow | sow
movq mm3,qword ptr [ecx]gr_static_struct.VTX_SNAP_1
add ebx,dword ptr [grvtxsize]
movd mm2, dword ptr [edi]r1_vert.b //mm2 - src->b
movq qword ptr [edx]GrVertex.tmuvtx[0].sow,mm1 //dst->tmuvtx[0].sow = src->s*src->oow;
//dst->tmuvtx[0].tow = src->t*src->tow
pfsub (m0,m3) //mm0 - src->py + gr_yoff | src->px + gr_xoff
movd mm3, dword ptr [ecx]gr_static_struct.gr_b_tint_mul //mm3 - gr_b_mul
movq qword ptr [edx]GrVertex.x,mm0 //dst->x = src->px+VTX_SNAP-VTX_SNAP+gr_x_off
//dst->y = src->py+VTX_SNAP-VTX_SNAP+gr_y_off
pfmul (m2,m3) //mm2 - src->b * gr_b_mul
add edi,dword ptr [r1vtxsize]
movd dword ptr [edx]GrVertex.b, mm2 //dst->b = src->b * gr_b_mul
add edx,dword ptr [grvtxsize]
dec esi
jnz looper
femms
done:
}
return i4_T;
}
#else
i4_bool gr_copy_all_amd3d(GrVertex *dst, r1_vert *src, int t_verts)
{
}
#endif