int gr_internal_string0m(int x, int y, unsigned char *s ) { unsigned char * fp; unsigned char * text_ptr, * next_row, * text_ptr1; int r, BitMask, i, bits, width, spacing, letter, underline; unsigned int VideoOffset, VideoOffset1; VideoOffset1 = y * ROWSIZE + x; next_row = s; while (next_row != NULL ) { text_ptr1 = next_row; next_row = NULL; if (x==0x8000) { //centered int xx = get_centered_x(text_ptr1); VideoOffset1 = y * ROWSIZE + xx; } for (r=0; r<FHEIGHT; r++) { text_ptr = text_ptr1; VideoOffset = VideoOffset1; while (*text_ptr) { if (*text_ptr == '\n' ) { next_row = &text_ptr[1]; break; } underline = 0; if (*text_ptr == '&' ) { if ((r==FBASELINE+2) || (r==FBASELINE+3)) underline = 1; text_ptr++; } get_char_width(text_ptr[0],text_ptr[1],&width,&spacing); letter = *text_ptr-FMINCHAR; if (!INFONT(letter)) { //not in font, draw as space VideoOffset += spacing; text_ptr++; continue; } if (FFLAGS & FT_PROPORTIONAL) fp = FCHARS[letter]; else fp = FDATA + letter * BITS_TO_BYTES(width)*FHEIGHT; if (underline) for (i=0; i< width; i++ ) DATA[VideoOffset++] = FG_COLOR; else { fp += BITS_TO_BYTES(width)*r; BitMask = 0; for (i=0; i< width; i++ ) { if (BitMask==0) { bits = *fp++; BitMask = 0x80; } if (bits & BitMask) DATA[VideoOffset++] = FG_COLOR; else VideoOffset++; BitMask >>= 1; } } text_ptr++; VideoOffset += spacing-width; } VideoOffset1 += ROWSIZE; y++; } } return 0; }
int gr_internal_string2(int x, int y, unsigned char *s ) { unsigned char * fp; unsigned char * text_ptr, * next_row, * text_ptr1; int r, BitMask, i, bits, width, spacing, letter, underline; int page_switched; unsigned int VideoOffset, VideoOffset1; VideoOffset1 = (unsigned long)DATA + y * ROWSIZE + x; gr_vesa_setpage(VideoOffset1 >> 16); VideoOffset1 &= 0xFFFF; next_row = s; while (next_row != NULL ) { text_ptr1 = next_row; next_row = NULL; if (x==0x8000) { //centered int xx = get_centered_x(text_ptr1); VideoOffset1 = y * ROWSIZE + xx; gr_vesa_setpage(VideoOffset1 >> 16); VideoOffset1 &= 0xFFFF; } for (r=0; r<FHEIGHT; r++) { text_ptr = text_ptr1; VideoOffset = VideoOffset1; page_switched = 0; while (*text_ptr) { if (*text_ptr == '\n' ) { next_row = &text_ptr[1]; break; } underline = 0; if (*text_ptr == '&' ) { if ((r==FBASELINE+2) || (r==FBASELINE+3)) underline = 1; text_ptr++; } get_char_width(text_ptr[0],text_ptr[1],&width,&spacing); Assert(width==spacing); //no kerning support here letter = *text_ptr-FMINCHAR; if (!INFONT(letter)) { //not in font, draw as space VideoOffset += spacing; text_ptr++; continue; } if (FFLAGS & FT_PROPORTIONAL) fp = FCHARS[letter]; else fp = FDATA + letter * BITS_TO_BYTES(width)*FHEIGHT; if (underline) { if ( VideoOffset+width > 0xFFFF ) { for (i=0; i< width; i++ ) { gr_video_memory[VideoOffset++] = FG_COLOR; if (VideoOffset > 0xFFFF ) { VideoOffset -= 0xFFFF + 1; page_switched = 1; gr_vesa_incpage(); } } } else { for (i=0; i< width; i++ ) gr_video_memory[VideoOffset++] = FG_COLOR; } } else { // fp -- dword // VideoOffset // width fp += BITS_TO_BYTES(width)*r; BitMask = 0; if ( VideoOffset+width > 0xFFFF ) { for (i=0; i< width; i++ ) { if (BitMask==0) { bits = *fp++; BitMask = 0x80; } if (bits & BitMask) gr_video_memory[VideoOffset++] = FG_COLOR; else gr_video_memory[VideoOffset++] = BG_COLOR; BitMask >>= 1; if (VideoOffset > 0xFFFF ) { VideoOffset -= 0xFFFF + 1; page_switched = 1; gr_vesa_incpage(); } } } else { if (width == 8 ) { bits = *fp++; if (bits & 0x80) gr_video_memory[VideoOffset+0] = FG_COLOR; else gr_video_memory[VideoOffset+0] = BG_COLOR; if (bits & 0x40) gr_video_memory[VideoOffset+1] = FG_COLOR; else gr_video_memory[VideoOffset+1] = BG_COLOR; if (bits & 0x20) gr_video_memory[VideoOffset+2] = FG_COLOR; else gr_video_memory[VideoOffset+2] = BG_COLOR; if (bits & 0x10) gr_video_memory[VideoOffset+3] = FG_COLOR; else gr_video_memory[VideoOffset+3] = BG_COLOR; if (bits & 0x08) gr_video_memory[VideoOffset+4] = FG_COLOR; else gr_video_memory[VideoOffset+4] = BG_COLOR; if (bits & 0x04) gr_video_memory[VideoOffset+5] = FG_COLOR; else gr_video_memory[VideoOffset+5] = BG_COLOR; if (bits & 0x02) gr_video_memory[VideoOffset+6] = FG_COLOR; else gr_video_memory[VideoOffset+6] = BG_COLOR; if (bits & 0x01) gr_video_memory[VideoOffset+7] = FG_COLOR; else gr_video_memory[VideoOffset+7] = BG_COLOR; VideoOffset += 8; } else { for (i=0; i< width/2 ; i++ ) { if (BitMask==0) { bits = *fp++; BitMask = 0x80; } if (bits & BitMask) gr_video_memory[VideoOffset++] = FG_COLOR; else gr_video_memory[VideoOffset++] = BG_COLOR; BitMask >>= 1; // Unroll twice if (BitMask==0) { bits = *fp++; BitMask = 0x80; } if (bits & BitMask) gr_video_memory[VideoOffset++] = FG_COLOR; else gr_video_memory[VideoOffset++] = BG_COLOR; BitMask >>= 1; } } } } text_ptr++; } VideoOffset1 += ROWSIZE; y++; if (VideoOffset1 > 0xFFFF ) { VideoOffset1 -= 0xFFFF + 1; if (!page_switched) gr_vesa_incpage(); } }
void d3d_batch_string(int sx, int sy, char *s, int bw, int bh, float u_scale, float v_scale, uint color) { int spacing = 0; int width; int x = sx; int y = sy; // centered x =(sx==0x8000) ? get_centered_x(s) : sx; do { HRESULT hr; int magic_num, magic_num2; int len = strlen_magic(s, magic_num, magic_num2); int new_id = -1; if(len == 0) return; // Set to 0 to turn off batching to gfx card memory #if 1 // Check the string is of a valid size if(len > MIN_STRING_LEN && len < MAX_LG_STR_LEN) { bool long_str = (len >= MAX_SM_STR_LEN); int index = find_string(len, magic_num, magic_num2, sx, sy, color, long_str); // We have found the string, render and mark as rendered if(index != -1) { StringBatch *array = (long_str) ? long_str_array : small_str_array; extern VertexTypeInfo vertex_types[D3DVT_MAX]; d3d_SetVertexShader(FONT_VTYPE); hr = GlobalD3DVars::lpD3DDevice->SetStreamSource( 0, array[index].vbuffer, vertex_types[FONT_VTYPE].size); Assert(SUCCEEDED(hr)); hr = GlobalD3DVars::lpD3DDevice->DrawPrimitive( D3DPT_TRIANGLELIST, 0, array[index].char_count * 2); // Assert(SUCCEEDED(hr)); array[index].used_this_frame = true; return; // Prepare to enter the string } else { new_id = find_free_slot(long_str); } } #endif IDirect3DVertexBuffer8 *vbuffer = NULL; FONT_VERTEX *locked_buffer = NULL; StringBatch *array = NULL; if(new_id != -1) { array = (len > MAX_SM_STR_LEN) ? long_str_array : small_str_array; vbuffer = array[new_id].vbuffer; hr = vbuffer->Lock(0, len * 6 * vertex_types[FONT_VTYPE].size, (BYTE **) &locked_buffer, 0); array[new_id].used_this_frame = true; // We can always bail out at this point if(FAILED(hr)) { Assert(0); new_id = -1; } } int char_count = 0; while (*s) { x += spacing; while (*s== '\n' ) { s++; y += Current_font->h; // centered x =(sx==0x8000) ? get_centered_x(s) : sx; } if (*s == 0 ) break; int letter = get_char_width(s[0],s[1],&width,&spacing); s++; //not in font, draw as space if (letter<0) { continue; } int xd, yd, xc, yc; int wc, hc; // Check if this character is totally clipped if ( x + width < gr_screen.clip_left ) continue; if ( y + Current_font->h < gr_screen.clip_top ) continue; if ( x > gr_screen.clip_right ) continue; if ( y > gr_screen.clip_bottom ) continue; xd = yd = 0; if ( x < gr_screen.clip_left ) xd = gr_screen.clip_left - x; if ( y < gr_screen.clip_top ) yd = gr_screen.clip_top - y; xc = x+xd; yc = y+yd; wc = width - xd; hc = Current_font->h - yd; if ( xc + wc > gr_screen.clip_right ) wc = gr_screen.clip_right - xc; if ( yc + hc > gr_screen.clip_bottom ) hc = gr_screen.clip_bottom - yc; if ( wc < 1 ) continue; if ( hc < 1 ) continue; font_char *ch; ch = &Current_font->char_data[letter]; int u = Current_font->bm_u[letter]; int v = Current_font->bm_v[letter]; if ( wc < 1 ) continue; if ( hc < 1 ) continue; FONT_VERTEX *src_v = NULL; if(new_id != -1) { src_v = &locked_buffer[char_count * 6]; } else { src_v = &d3d_verts[char_count * 6]; } #if 0 // Change the color this way to see which strings are being cached uint color2 = (new_id == -1) ? color : 0xff00ff00; // Marks the end of a batch blue if(char_count > (MAX_STRING_LEN - 10)) color2 = 0xff0000ff; #endif d3d_stuff_char(src_v, xc, yc, wc, hc, u+xd, v+yd, bw, bh, u_scale, v_scale, color); char_count++; if(char_count >= MAX_STRING_LEN) { // We've run out of space, we are going to have to go round again break; } } if(new_id != -1) { vbuffer->Unlock(); if(char_count == 0) { array[new_id].free_slot = true; array[new_id].used_this_frame = false; continue; } hr = d3d_SetVertexShader(FONT_VTYPE); Assert(SUCCEEDED(hr)); hr = GlobalD3DVars::lpD3DDevice->SetStreamSource(0, vbuffer, vertex_types[FONT_VTYPE].size); Assert(SUCCEEDED(hr)); hr = GlobalD3DVars::lpD3DDevice->DrawPrimitive(D3DPT_TRIANGLELIST, 0, char_count * 2); // Assert(SUCCEEDED(hr)); // Fill in details array[new_id].char_count = char_count; array[new_id].color = color; array[new_id].free_slot = false; array[new_id].len = len; array[new_id].magic_number = magic_num; array[new_id].magic_number2 = magic_num2; array[new_id].x = sx; array[new_id].y = sy; array[new_id].offsetx = gr_screen.offset_x; array[new_id].offsety = gr_screen.offset_y; array[new_id].used_this_frame = true; } else if(char_count > 0) { d3d_DrawPrimitive(FONT_VTYPE, D3DPT_TRIANGLELIST,(LPVOID)d3d_verts, char_count * 6); } } while (*s); }