multiople textures + closed mesh

Blitz3D Forums/Blitz3D Programming/multiople textures + closed mesh

I have this rather intriguing question, that might orient my development for mesh builder / maze builder that I made.

Right now my meshes are built as unsoldered, thus open. They use various textures and surfaces. Since the mesh is open, it breaks ANY stencil shadow system, and it also seems to have an influence on performance in z buffering.

So, I figured, I need to enhance this situation for those 2 reasons. Meaning, I need to generate a closed mesh, that a stencil shadow system will work flawlessly, and to make z buffering work as fast as possible.

Solutions that I found seem straight forward: What I would have to do would be to regroup all the textures that I use for my meshes into one big texture, but fix all the UV coordinates accordingly for the big texture. In essence, this should help me unify all the surfaces into a single and also help me close the generated mesh.

Any other idea welcomed :P

I've never had a major problem with unwelded meshes. I need this to do proper flatshading but on the odd occasion the gap is visible.

I built a 2d level editor earlier this year and found that the mesh gaps were even more visible. I made a function which extrudes each vertex by a tiny amount based on it's vector to the center of the triangle - this got rid of my visible gap issue and may work for stencils.

Have you got a screenie if this is not what you mean?

It's much more serious than gaps, because a stencil shadow usually needs a closed welded meshes to work. I'm talking by experience with AShadow and Devil Shadow Engine. I'm not even counting the 32K triangle limit of the DX7 for this case (or is that a Blitz3D limit?). Anyhow, this is a different issue alltogether.

To solve that gap issue Stevie G that you're talking about for 2D, I use a very high "virtual" resolution, like 32000 by 24000. That way, I can adequately scale for any physical screen resolution and it will never show any gap, antialias or no antialias. But I use FastImage, so that tool does help me do this scaling.

Its neither.
Its 65536 Triangle Limit as well as Vertex Limit (simply: they are short indexed)


32768 is the limit of GF2 / GF4 MX cards as they can not handle larger triangle buffers


To solve that gap issue Stevie G that you're talking about for 2D, I use a very high "virtual" resolution, like 32000 by 24000. That way, I can adequately scale for any physical screen resolution and it will never show any gap, antialias or no antialias. But I use FastImage, so that tool does help me do this scaling.



The editor was actually 3d but using a flat auto tessalated mesh. Interesting idea re fastimage, can you explain the technique in more detail as I could have use for it? Could it be used, for example to render to a texture buffer bigger than the current screen res or be use to blur or antialias a texture? I'm assuming you do not do this scaling in realtime?

I do the whole screen frefresh, scaling etc in realtime on a PER CHARACTER basis, for my terminal sub-project, and I get roughly 150 fps on my X800 generation card, and AMD K8 processor. I'm very picky on my visuals and what I need to achieve, and I found that FastImage gave me what I wanted the easy way.

Here I'll poste my render function ;)
Function render_page(page_id%)
; Renders a terminal page and it's relative cursor and mouse character pointer
; Layer order:
;       - background shadow tiles
;       - background tiles
;       - foreground text shadow       *** not finished yet ***
;       - text underlines
;       - text map
;       - text strikeouts
;       - cursor shadow tile + background tile + keyboard cursor character
;       - mouse shadow tile + background tile + mouse cursor character
;
; *** shadows are not yet completed and tested.
;
   Local disp%, row%, col%
   If page_exists(page_id) = False Then Return

   If term\timer >= term\page[page_id]\blink_slow_timer Then
      term\page[page_id]\blink_slow_timer = term\timer + term\page[page_id]\blink_slow_rate
      term\page[page_id]\blink_slow_state = (term\page[page_id]\blink_slow_state + 1) Mod 2
   EndIf
   If term\timer >= term\page[page_id]\blink_fast_timer Then
      term\page[page_id]\blink_fast_timer = term\timer + term\page[page_id]\blink_fast_rate
      term\page[page_id]\blink_fast_state = (term\page[page_id]\blink_fast_state + 1) Mod 2
   EndIf

   If term\page[page_id]\palette_rotate_state <> 0 Then
      Select term\page[page_id]\palette_rotate_state
      Case 999
         term_shift_palette(page_id, term\page[page_id]\palette_rotate_start, term\page[page_id]\palette_rotate_end, 1)
         term\page[page_id]\palette_rotate_state = 0
      Case -999
         term_shift_palette(page_id, term\page[page_id]\palette_rotate_start, term\page[page_id]\palette_rotate_end, -1)
         term\page[page_id]\palette_rotate_state = 0
      Default
         If term\timer >= (term\page[page_id]\palette_rotate_timer + term\page[page_id]\palette_rotate_rate) Then
            term\page[page_id]\palette_rotate_timer = term\timer
            term_shift_palette(page_id, term\page[page_id]\palette_rotate_start, term\page[page_id]\palette_rotate_end, term\page[page_id]\palette_rotate_state)
         EndIf
      End Select
   EndIf

   Local page_mode% = term\page[page_id]\mode
   
   If (page_mode And PGMOD_DISPLAY_ON) = False Or (page_mode And PGMOD_CHARS_TILES_SHADOWS_ON) = False Then Return

   Local palette_table% = term\page[page_id]\palette_table
   Local draw_X#, draw_Y#
   Local draw_start_X#, draw_start_Y#, draw_start_col%

   Local text_table%    = term\page[page_id]\layer[PGTBL_text]
   Local t_color_table% = term\page[page_id]\layer[PGTBL_text_color]
   Local b_color_table% = term\page[page_id]\layer[PGTBL_bkgnd_color]
   Local lines_table%   = term\page[page_id]\layer[PGTBL_lines]
   Local attr_table%    = term\page[page_id]\layer[PGTBL_attr]
   Local font_table%    = term\page[page_id]\layer[PGTBL_font]

   Local item_table%    = term\page[page_id]\layer[PGTBL_click_item]
   Local mouse_saved_item% = term\mouse_saved_item

   Local text_mask_table%, t_color_mask_table%, b_color_mask_table%, attr_mask_table%, font_mask_table%
   If term\mouse_page_focus = page_id And (page_mode And PGMOD_MASKS_ON) > False And mouse_saved_item > 0 Then
      text_mask_table%    = term\page[page_id]\layer[PGTBL_text + term\mouse_page_focus_item_layer_offset]
      t_color_mask_table% = term\page[page_id]\layer[PGTBL_text_color + term\mouse_page_focus_item_layer_offset]
      b_color_mask_table% = term\page[page_id]\layer[PGTBL_bkgnd_color + term\mouse_page_focus_item_layer_offset]
      lines_mask_table%   = term\page[page_id]\layer[PGTBL_lines + term\mouse_page_focus_item_layer_offset]
      attr_mask_table%    = term\page[page_id]\layer[PGTBL_attr + term\mouse_page_focus_item_layer_offset]
      font_mask_table%    = term\page[page_id]\layer[PGTBL_font + term\mouse_page_focus_item_layer_offset]
   Else
      text_mask_table%    = term\page[page_id]\layer[PGTBL_text]
      t_color_mask_table% = term\page[page_id]\layer[PGTBL_text_color]
      b_color_mask_table% = term\page[page_id]\layer[PGTBL_bkgnd_color]
      lines_mask_table%   = term\page[page_id]\layer[PGTBL_lines]
      attr_mask_table%    = term\page[page_id]\layer[PGTBL_attr]
      font_mask_table%    = term\page[page_id]\layer[PGTBL_font]
   EndIf

   Local argb%, argb0%, argb1%, argb2%, argb3%
   Local alpha_table%, x_zoom_table%, y_zoom_table%, angle_table%, x_offset_table%, y_offset_table%
   Local special_features% = False
   If page_mode And PGMOD_SPECIAL_FEATURES_ON Then 
      special_features% = page_mode And PGMOD_SF_UPDATE_ALL_ON
   EndIf
   If special_features > False Then
      alpha_table%    = term\page[page_id]\layer[PGTBL_alpha]
      x_zoom_table%   = term\page[page_id]\layer[PGTBL_x_zoom]
      y_zoom_table%   = term\page[page_id]\layer[PGTBL_y_zoom]
      angle_table%    = term\page[page_id]\layer[PGTBL_angle]
      x_offset_table% = term\page[page_id]\layer[PGTBL_x_offset]
      y_offset_table% = term\page[page_id]\layer[PGTBL_y_offset]
      shade_table%    = term\page[page_id]\layer[PGTBL_shade]
   EndIf

   Local X# = term\page[page_id]\X
   Local Y# = term\page[page_id]\Y
   Local render_scale_X# = Float term\current_width / Float TRM_virtual_width
   Local render_scale_Y# = Float term\current_height / Float TRM_virtual_height
   SetProjScale render_scale_X, render_scale_Y
   SetProjHandle -X, -Y
   Local shadow_X# = term_sin(term\shadow_orientation) * term\shadow_distance
   Local shadow_Y# = term_cos(term\shadow_orientation) * term\shadow_distance
   Local char_width# = term\page[page_id]\char_width
   Local char_height# = term\page[page_id]\char_height
   Local cols% = term\page[page_id]\cols
   Local rows% = term\page[page_id]\rows
   Local display_nulls% = page_mode And PGMOD_NULLS_ON
   Local blink_slow_state% = term\page[page_id]\blink_slow_state
   Local blink_fast_state% = term\page[page_id]\blink_fast_state

   ; if the tiles / characters are off the screen, then we limit the drawing
   If X < 0 Then start_col% = Abs(X / char_width + 0.5) Else start_col% = 0
   If Y < 0 Then start_row% = Abs(Y / char_height + 0.5) Else start_row% = 0
   If X > (TRM_virtual_width - term\page[page_id]\active_width) Then end_col% = (cols - 1) - (X / char_width - 0.5) Else end_col% = cols - 1
   If Y > (TRM_virtual_height - term\page[page_id]\active_height) Then end_row% = (rows - 1) - (Y / char_height - 0.5) Else end_row% = rows - 1
   
   
   If (page_mode And PGMOD_TILES_ON) > False Then
      StartDraw
      
      ; background shadow
      If (page_mode And PGMOD_TILE_SHADOWING_ON) > False Then
         SetScale 1.0, 1.0
         SetOrigin 0,0
         SetBlend FI_ALPHABLEND
         SetAlpha term\shadow_alpha
         SetColor 0, 0, 0
         If special_features <> False Then
; ************** TO BE COMPLETED
            If display_nulls <> False Then
               DrawRectSimple_ (shadow_X + start_col * char_width, shadow_Y + start_row * char_height, char_width * (cols - start_col), char_height * (rows - start_row), 1)
            Else
               ; not sure if I should use a bitmap instead **************
               For row = start_row To end_row
                  draw_start_col% = start_col
                  draw_start_X = shadow_X + draw_start_col * char_width
                  draw_start_Y = shadow_Y + row * char_height
                  disp = row * cols + draw_start_col
                  For col = start_col To end_col
                     disp = row * cols + col
                     item% = PeekByte(item_table, disp)
                     If PeekByte(text_table, disp) = 0 Then
                        If (col - draw_start_col) > 0 Then
                           chars% = col - draw_start_col
                           DrawRectSimple_ (draw_start_X, draw_start_Y, char_width * chars, char_height, 1)
                        EndIf
                        draw_start_col = col + 1
                        draw_start_X = shadow_X + draw_start_col * char_width
                     EndIf
                  Next
                  If (col - draw_start_col) > 0 Then
                     DrawRectSimple_ (draw_start_X, draw_start_Y, char_width * (col - draw_start_col), char_height, 1)
                  EndIf
               Next
            EndIf
; ************** TO BE COMPLETED
         Else
            If display_nulls <> False Then
               DrawRectSimple_ (shadow_X + start_col * char_width, shadow_Y + start_row * char_height, char_width * (cols - start_col), char_height * (rows - start_row), 1)
            Else
               ; not sure if I should use a bitmap instead **************
               For row = start_row To end_row
                  draw_start_col% = start_col
                  draw_start_X = shadow_X + draw_start_col * char_width
                  draw_start_Y = shadow_Y + row * char_height
                  disp = row * cols + draw_start_col
                  For col = start_col To end_col
                     disp = row * cols + col
                     item% = PeekByte(item_table, disp)
                     If PeekByte(text_table, disp) = 0 Then
                        If (col - draw_start_col) > 0 Then
                           chars% = col - draw_start_col
                           DrawRectSimple_ (draw_start_X, draw_start_Y, char_width * chars, char_height, 1)
                        EndIf
                        draw_start_col = col + 1
                        draw_start_X = shadow_X + draw_start_col * char_width
                     EndIf
                  Next
                  If (col - draw_start_col) > 0 Then
                     DrawRectSimple_ (draw_start_X, draw_start_Y, char_width * (col - draw_start_col), char_height, 1)
                  EndIf
               Next
            EndIf
         EndIf
      EndIf

      ; background
      SetBlend FI_ALPHABLEND
      SetAlpha term\page[page_id]\bkgnd_alpha
      If special_features And PGMOD_SF_UPDATE_BKGND_ON Then
         For row = start_row To end_row
            For col = start_col To end_col
               disp = row * cols + col
               If item = mouse_saved_item Then
                  argb% = PeekInt (palette_table, PeekByte(b_color_mask_table, disp) Shl 2)
               Else
                  argb% = PeekInt (palette_table, PeekByte(b_color_table, disp) Shl 2)
               EndIf
               If (display_nulls = True And PeekByte(text_table, disp) = 0) Then
               ; skip
               Else
                  If (page_mode And PGMOD_SF_UPDATE_ANGLE_ON) > False Then
                     SetRotation PeekByte(angle_table, disp) * 2
                  EndIf
                  If (page_mode And PGMOD_SF_UPDATE_ALPHA_ON) > False Then
                     SetAlpha PeekByte(alpha_table, disp) * 0.003921569
                  EndIf
                  If (page_mode And PGMOD_SF_UPDATE_ZOOM_ON) > False Then
                     SetScale PeekByte(x_zoom_table, disp) * 0.015625, PeekByte(y_zoom_table, disp) * 0.015625
                  EndIf
                  If (page_mode And PGMOD_SF_UPDATE_OFFSET_ON) > False Then
                     SetOrigin PeekByte(x_offset_table, disp) - 128, PeekByte(y_offset_table, disp) - 128
                  EndIf
                  SetColor (argb Shr 16) And $ff, (argb Shr 8) And $ff, argb And $ff
                  DrawRectSimple_ (col * char_width, row * char_height, char_width, char_height, 1)
               EndIf
            Next
         Next
      Else
         For row = start_row To end_row
            draw_start_col% = start_col
            draw_start_X = draw_start_col * char_width
            draw_start_Y = row * char_height
            disp = row * cols + draw_start_col
            argb% = PeekInt (palette_table, PeekByte(b_color_table, disp) Shl 2)
            old_argb% = argb
            For col = start_col To end_col
               disp = row * cols + col
               item% = PeekByte(item_table, disp)
               If item = mouse_saved_item Then
                  argb% = PeekInt (palette_table, PeekByte(b_color_mask_table, disp) Shl 2)
               Else
                  argb% = PeekInt (palette_table, PeekByte(b_color_table, disp) Shl 2)
               EndIf
               If (display_nulls = False And PeekByte(text_table, disp) = 0) Then
                  If (col - draw_start_col) > 0 Then
                     SetColor (old_argb Shr 16) And $ff, (old_argb Shr 8) And $ff, old_argb And $ff
                     chars% = col - draw_start_col
                     DrawRectSimple_ (draw_start_X, draw_start_Y, char_width * chars, char_height, 1)
                  EndIf
                  draw_start_col = col + 1
                  draw_start_X = draw_start_col * char_width
               ElseIf old_argb <> argb Then
                  SetColor (old_argb Shr 16) And $ff, (old_argb Shr 8) And $ff, old_argb And $ff
                  chars% = col - draw_start_col
                  DrawRectSimple_ (draw_start_X, draw_start_Y, char_width * chars, char_height, 1)
                  old_argb% = argb
                  draw_start_col = col
                  draw_start_X = draw_start_col * char_width
               EndIf
            Next
            If (col - draw_start_col) > 0 Then
               SetColor (argb Shr 16) And $ff, (argb Shr 8) And $ff, argb And $ff
               DrawRectSimple_ (draw_start_X, draw_start_Y, char_width * (col - draw_start_col), char_height, 1)
            EndIf
         Next
      EndIf
      EndDraw
   EndIf

   If (page_mode And PGMOD_CHARS_ON) > False Then
      StartDraw
      
      ; chars
      Local font_select% = $100
      Local font_select_row% = 0
      
      ; char shadow
      If (page_mode And PGMOD_CHAR_SHADOWING_ON) > False Then
         SetColor 0,0,0
         SetBlend FI_ALPHABLEND
         SetAlpha term\page[page_id]\text_alpha
         disp = 0
         For row = 0 To (rows - 1)
            font_select_col% = cols - font_select_col
            For col = 0 To (cols - 1)
               ;************* If mouse is over an item, render character accordingly
               If PeekByte(item_table, disp) = mouse_saved_item Then
                  curr_font% = PeekByte(font_mask_table, disp)
                  If font_select <> curr_font Then
                     font_select% = curr_font
                     font_select_col% = 0
                     font_select_row% = row
                     font = curr_font And TXRNA_FONT_ID
                     scale_X# = char_width / Float (term\font[font]\width)
                     scale_Y# = char_height / Float (term\font[font]\height)
                     SetScale scale_X, scale_Y
                     w# = term\font[font]\width
                     h# = term\font[font]\height
                     draw_X# = (w * 0.5 * scale_X)
                     draw_Y# = (h * 0.5 * scale_Y)
                     font_image% = term\font[font]\image
                     font_size = curr_font And TXRNA_FONT_SIZE
                  EndIf
                  
                  char% = PeekByte(text_mask_table, disp)
                  If char <> 32 And (display_nulls <> False Or (display_nulls = False And char > 0)) Then
                     attr% = PeekByte(attr_table, disp)
                     If (attr And TXRNA_BLINK_SLOW_ON) > False And blink_slow_state > False Then
                      ;skip
                     ElseIf (attr And TXRNA_BLINK_FAST_ON) > False  And blink_fast_state > False Then
                      ;skip
                     Else
                        If row >= start_row And row <= end_row And col >= start_col And col <= end_col Then
                           If special_features And PGMOD_SF_UPDATE_CHARS_ON Then
                              If page_mode And PGMOD_SF_UPDATE_ANGLE_ON Then
                                 SetRotation PeekByte(angle_table, disp) * 2
                              EndIf
                              If page_mode And PGMOD_SF_UPDATE_ZOOM_ON Then
                                 SetScale scale_X * PeekByte(x_zoom_table, disp) * 0.015625, scale_Y * PeekByte(y_zoom_table, disp) * 0.015625
                              EndIf
                              If page_mode And PGMOD_SF_UPDATE_OFFSET_ON Then
                                 SetOrigin PeekByte(x_offset_table, disp) - 128, PeekByte(y_offset_table, disp) - 128
                              EndIf
                              If page_mode And PGMOD_SF_UPDATE_ALPHA_ON Then
                                 alpha% = PeekByte(alpha_table, disp) Shl 24
                              Else
                                 alpha% = $FF000000
                              EndIf
                           EndIf
                           If font_size = False Then
                              DrawImageRectEx_ font_image, draw_X + col * char_width, draw_Y + row * char_height, w, h, char
                           Else
                              Select font_size And TXRNA_FONT_WIDTH_MULTIPLY
                                 Case TXRNA_DOUBLE_WIDTH_ON : partwidth# = w * 0.5 : partx# = (font_select_col Mod 2) * partwidth
                                 Case TXRNA_TRIPLE_WIDTH_ON : partwidth# = w * 0.33333333 : partx# = (font_select_col Mod 3) * partwidth
                                 Case TXRNA_QUADRUPLE_WIDTH_ON : partwidth# = w * 0.25 : partx# = (font_select_col Mod 4) * partwidth
                                 Default : partwidth# = w : partx# = 0
                              End Select
                              Select font_size And TXRNA_FONT_HEIGHT_MULTIPLY
                                 Case TXRNA_DOUBLE_HEIGHT_ON : partheight# = h * 0.5 : party# = (font_select_row Mod 2) * partheight
                                 Case TXRNA_TRIPLE_HEIGHT_ON : partheight# = h * 0.33333333 : party# = (font_select_row Mod 3) * partheight
                                 Case TXRNA_QUADRUPLE_HEIGHT_ON : partheight# = h * 0.25 : party# = (font_select_row Mod 4) * partheight
                                 Default : partheight# = h : party# = 0
                              End Select
                              DrawImagePart_ font_image, draw_X + col * char_width, draw_Y + row * char_height, w, h, partx, party, partwidth, partheight, char, 0
                           EndIf
                        EndIf
                     EndIf
                  EndIf
               Else
                  curr_font% = PeekByte(font_table, disp)
                  If font_select <> curr_font Then
                     font_select% = curr_font
                     font_select_col% = 0
                     font_select_row% = row
                     font = curr_font And TXRNA_FONT_ID
                     scale_X# = char_width / Float (term\font[font]\width)
                     scale_Y# = char_height / Float (term\font[font]\height)
                     SetScale scale_X, scale_Y
                     w# = term\font[font]\width
                     h# = term\font[font]\height
                     draw_X# = (w * 0.5 * scale_X)
                     draw_Y# = (h * 0.5 * scale_Y)
                     font_image% = term\font[font]\image
                     font_size = curr_font And TXRNA_FONT_SIZE
                  EndIf
                  char% = PeekByte(text_table, disp) ; render character, no mouse over effects
                  If char <> 32 And (display_nulls <> False Or (display_nulls = False And char > 0)) Then
                     attr% = PeekByte(attr_table, disp)
                     If (attr And TXRNA_BLINK_SLOW_ON) > False And blink_slow_state > False Then
                      ;skip
                     ElseIf (attr And TXRNA_BLINK_FAST_ON) > False  And blink_fast_state > False Then
                      ;skip
                     Else
                        If row >= start_row And row <= end_row And col >= start_col And col <= end_col Then
                           If special_features And PGMOD_SF_UPDATE_CHARS_ON Then
                              If page_mode And PGMOD_SF_UPDATE_ANGLE_ON Then
                                 SetRotation PeekByte(angle_table, disp) * 2
                              EndIf
                              If page_mode And PGMOD_SF_UPDATE_ZOOM_ON Then
                                 SetScale scale_X * PeekByte(x_zoom_table, disp) * 0.015625, scale_Y * PeekByte(y_zoom_table, disp) * 0.015625
                              EndIf
                              If page_mode And PGMOD_SF_UPDATE_OFFSET_ON Then
                                 SetOrigin PeekByte(x_offset_table, disp) - 128, PeekByte(y_offset_table, disp) - 128
                              EndIf
                              If page_mode And PGMOD_SF_UPDATE_ALPHA_ON Then
                                 alpha% = PeekByte(alpha_table, disp) Shl 24
                              Else
                                 alpha% = $FF000000
                              EndIf
                           EndIf
                           If font_size = False Then
                              DrawImageRectEx_ font_image, draw_X + col * char_width, draw_Y + row * char_height, w, h, char
                           Else
                              Select font_size And TXRNA_FONT_WIDTH_MULTIPLY
                                 Case TXRNA_DOUBLE_WIDTH_ON : partwidth# = w * 0.5 : partx# = (font_select_col Mod 2) * partwidth
                                 Case TXRNA_TRIPLE_WIDTH_ON : partwidth# = w * 0.33333333 : partx# = (font_select_col Mod 3) * partwidth
                                 Case TXRNA_QUADRUPLE_WIDTH_ON : partwidth# = w * 0.25 : partx# = (font_select_col Mod 4) * partwidth
                                 Default : partwidth# = w : partx# = 0
                              End Select
                              Select font_size And TXRNA_FONT_HEIGHT_MULTIPLY
                                 Case TXRNA_DOUBLE_HEIGHT_ON : partheight# = h * 0.5 : party# = (font_select_row Mod 2) * partheight
                                 Case TXRNA_TRIPLE_HEIGHT_ON : partheight# = h * 0.33333333 : party# = (font_select_row Mod 3) * partheight
                                 Case TXRNA_QUADRUPLE_HEIGHT_ON : partheight# = h * 0.25 : party# = (font_select_row Mod 4) * partheight
                                 Default : partheight# = h : party# = 0
                              End Select
                              DrawImagePart_ font_image, draw_X + col * char_width, draw_Y + row * char_height, w, h, partx, party, partwidth, partheight, char, 0
                           EndIf
                        EndIf
                     EndIf
                  EndIf
               EndIf
               font_select_col = font_select_col + 1
               disp = disp + 1
            Next
            font_select_row = font_select_row + 1
         Next
      EndIf
      
      ; the actual characters
      old_argb% = $12345678
      SetBlend FI_ALPHABLEND
      SetAlpha term\page[page_id]\text_alpha
      disp = 0
      For row = 0 To (rows - 1)
         font_select_col% = cols - font_select_col
         For col = 0 To (cols - 1)

            ;************* If mouse is over an item, render character accordingly
            If PeekByte(item_table, disp) = mouse_saved_item Then
               curr_font% = PeekByte(font_mask_table, disp)
               If font_select <> curr_font Then
                  font_select% = curr_font
                  font_select_col% = 0
                  font_select_row% = row
                  font = curr_font And TXRNA_FONT_ID
                  scale_X# = char_width / Float (term\font[font]\width)
                  scale_Y# = char_height / Float (term\font[font]\height)
                  SetScale scale_X, scale_Y
                  w# = term\font[font]\width
                  h# = term\font[font]\height
                  draw_X# = (w * 0.5 * scale_X)
                  draw_Y# = (h * 0.5 * scale_Y)
                  font_image% = term\font[font]\image
                  font_size = curr_font And TXRNA_FONT_SIZE
               EndIf

               char% = PeekByte(text_mask_table, disp)
               If char <> 32 And (display_nulls <> False Or (display_nulls = False And char > 0)) Then
                  attr% = PeekByte(attr_table, disp)
                  If (attr And TXRNA_BLINK_SLOW_ON) > False And blink_slow_state > False Then
                     ;skip
                  ElseIf (attr And TXRNA_BLINK_FAST_ON) > False  And blink_fast_state > False Then
                     ;skip
                  Else
                     If row >= start_row And row <= end_row And col >= start_col And col <= end_col Then
                        If special_features And PGMOD_SF_UPDATE_CHARS_ON Then
                           If page_mode And PGMOD_SF_UPDATE_ANGLE_ON Then
                              SetRotation PeekByte(angle_table, disp) * 2
                           EndIf
                           If page_mode And PGMOD_SF_UPDATE_ZOOM_ON Then
                              SetScale scale_X * PeekByte(x_zoom_table, disp) * 0.015625, scale_Y * PeekByte(y_zoom_table, disp) * 0.015625
                           EndIf
                           If page_mode And PGMOD_SF_UPDATE_OFFSET_ON Then
                              SetOrigin PeekByte(x_offset_table, disp) - 128, PeekByte(y_offset_table, disp) - 128
                           EndIf
                           If page_mode And PGMOD_SF_UPDATE_ALPHA_ON Then
                              alpha% = PeekByte(alpha_table, disp) Shl 24
                           Else
                              alpha% = $FF000000
                           EndIf
                           If page_mode And PGMOD_SF_SHADE_ON Then
                              argb% = PeekInt (palette_table, PeekByte(t_color_mask_table, disp) Shl 2)
                              shade% = PeekByte(shade_table, disp)
                              Select shade And $0F ; color
                                 Case 1 :
                                    If col = (cols - 1) Then
                                       argb1% = PeekInt (palette_table, PeekByte(t_color_mask_table, row * cols) Shl 2)
                                    Else
                                       argb1% = PeekInt (palette_table, PeekByte(t_color_mask_table, disp + 1) Shl 2)
                                    EndIf
                                    argb0 = argb : argb2 = argb1 : argb3 = argb
                                 Case 2 :
                                    If col = 0 Then
                                       argb0% = PeekInt (palette_table, PeekByte(t_color_mask_table, disp + cols - 1) Shl 2)
                                    Else
                                       argb0% = PeekInt (palette_table, PeekByte(t_color_mask_table, disp - 1) Shl 2)
                                    EndIf
                                    argb1 = argb : argb2 = argb : argb3 = argb0
                                 Case 4 :
                                    If row = (rows - 1) Then
                                       argb2% = PeekInt (palette_table, PeekByte(t_color_mask_table, col) Shl 2)
                                    Else
                                       argb2% = PeekInt (palette_table, PeekByte(t_color_mask_table, disp + cols) Shl 2)
                                    EndIf
                                    argb0 = argb : argb1 = argb : argb3 = argb2
                                 Case 8 :
                                    If row = 0 Then
                                       argb0% = PeekInt (palette_table, PeekByte(t_color_mask_table, (row - 1) * cols + col) Shl 2)
                                    Else
                                       argb0% = PeekInt (palette_table, PeekByte(t_color_mask_table, disp - cols) Shl 2)
                                    EndIf
                                    argb1 = argb0 : argb2 = argb : argb3 = argb
                                 Default  :
                                    argb0 = argb : argb1 = argb : argb2 = argb : argb3 = argb
                              End Select
                              Select shade And $F0 ; alpha
                                 Case 16 :
                                    If col = (cols - 1) Then
                                       alpha1% = PeekByte(alpha_table, row * cols) Shl 24
                                    Else
                                       alpha1% = PeekByte(alpha_table, disp + 1) Shl 24
                                    EndIf
                                    SetCustomColor argb0 Or alpha, argb1 Or alpha1, argb2 Or alpha1, argb3 Or alpha
                                 Case 32 :
                                    If col = 0 Then
                                       alpha1% = PeekByte(alpha_table, disp + cols - 1) Shl 24
                                    Else
                                       alpha1% = PeekByte(alpha_table, disp - 1) Shl 24
                                    EndIf
                                    SetCustomColor argb0 Or alpha1, argb1 Or alpha, argb2 Or alpha, argb3 Or alpha1
                                 Case 64 :
                                    If row = (rows - 1) Then
                                       alpha1% = PeekByte(alpha_table, col) Shl 24
                                    Else
                                       alpha1% = PeekByte(alpha_table, disp + cols) Shl 24
                                    EndIf
                                    SetCustomColor argb0 Or alpha, argb1 Or alpha, argb2 Or alpha1, argb3 Or alpha1
                                 Case 128 :
                                    If row = 0 Then
                                       alpha1% = PeekByte(alpha_table, (row - 1) * cols + col) Shl 24
                                    Else
                                       alpha1% = PeekByte(alpha_table, disp - cols) Shl 24
                                    EndIf
                                    SetCustomColor argb0 Or alpha1, argb1 Or alpha1, argb2 Or alpha, argb3 Or alpha
                                 Default :
                                    SetCustomColor argb0 Or alpha, argb1 Or alpha, argb2 Or alpha, argb3 Or alpha
                              End Select
                           Else
                              argb% = PeekInt (palette_table, PeekByte(t_color_mask_table, disp) Shl 2) Or alpha
                              SetCustomColor argb, argb, argb, argb
                           EndIf
                        Else
                           argb% = PeekInt (palette_table, PeekByte(t_color_mask_table, disp) Shl 2) Or $FF000000
                           SetCustomColor argb, argb, argb, argb
                        EndIf
                        If font_size = False Then
                           DrawImageRectEx_ font_image, draw_X + col * char_width, draw_Y + row * char_height, w, h, char
                        Else
                           Select font_size And TXRNA_FONT_WIDTH_MULTIPLY
                              Case TXRNA_DOUBLE_WIDTH_ON : partwidth# = w * 0.5 : partx# = (font_select_col Mod 2) * partwidth
                              Case TXRNA_TRIPLE_WIDTH_ON : partwidth# = w * 0.33333333 : partx# = (font_select_col Mod 3) * partwidth
                              Case TXRNA_QUADRUPLE_WIDTH_ON : partwidth# = w * 0.25 : partx# = (font_select_col Mod 4) * partwidth
                              Default : partwidth# = w : partx# = 0
                           End Select
                           Select font_size And TXRNA_FONT_HEIGHT_MULTIPLY
                              Case TXRNA_DOUBLE_HEIGHT_ON : partheight# = h * 0.5 : party# = (font_select_row Mod 2) * partheight
                              Case TXRNA_TRIPLE_HEIGHT_ON : partheight# = h * 0.33333333 : party# = (font_select_row Mod 3) * partheight
                              Case TXRNA_QUADRUPLE_HEIGHT_ON : partheight# = h * 0.25 : party# = (font_select_row Mod 4) * partheight
                              Default : partheight# = h : party# = 0
                           End Select
                           DrawImagePart_ font_image, draw_X + col * char_width, draw_Y + row * char_height, w, h, partx, party, partwidth, partheight, char, 0
                        EndIf
                     EndIf
                  EndIf
               EndIf

            Else
               curr_font% = PeekByte(font_table, disp)
               If font_select <> curr_font Then
                  font_select% = curr_font
                  font_select_col% = 0
                  font_select_row% = row
                  font = curr_font And TXRNA_FONT_ID
                  scale_X# = char_width / Float (term\font[font]\width)
                  scale_Y# = char_height / Float (term\font[font]\height)
                  SetScale scale_X, scale_Y
                  w# = term\font[font]\width
                  h# = term\font[font]\height
                  draw_X# = (w * 0.5 * scale_X)
                  draw_Y# = (h * 0.5 * scale_Y)
                  font_image% = term\font[font]\image
                  font_size = curr_font And TXRNA_FONT_SIZE
               EndIf

               char% = PeekByte(text_table, disp) ; render character, no mouse over effects
               If char <> 32 And (display_nulls <> False Or (display_nulls = False And char > 0)) Then
                  attr% = PeekByte(attr_table, disp)
                  If (attr And TXRNA_BLINK_SLOW_ON) > False And blink_slow_state > False Then
                     ;skip
                  ElseIf (attr And TXRNA_BLINK_FAST_ON) > False  And blink_fast_state > False Then
                     ;skip
                  Else
                     If row >= start_row And row <= end_row And col >= start_col And col <= end_col Then
                        If special_features And PGMOD_SF_UPDATE_CHARS_ON Then
                           If page_mode And PGMOD_SF_UPDATE_ANGLE_ON Then
                              SetRotation PeekByte(angle_table, disp) * 2
                           EndIf
                           If page_mode And PGMOD_SF_UPDATE_ZOOM_ON Then
                              SetScale scale_X * PeekByte(x_zoom_table, disp) * 0.015625, scale_Y * PeekByte(y_zoom_table, disp) * 0.015625
                           EndIf
                           If page_mode And PGMOD_SF_UPDATE_OFFSET_ON Then
                              SetOrigin PeekByte(x_offset_table, disp) - 128, PeekByte(y_offset_table, disp) - 128
                           EndIf
                           If page_mode And PGMOD_SF_UPDATE_ALPHA_ON Then
                              alpha% = PeekByte(alpha_table, disp) Shl 24
                           Else
                              alpha% = $FF000000
                           EndIf
                           If page_mode And PGMOD_SF_SHADE_ON Then
                              argb% = PeekInt (palette_table, PeekByte(t_color_table, disp) Shl 2)
                              shade% = PeekByte(shade_table, disp)
                              Select shade And $0F ; color
                                 Case 1 :
                                    If col = (cols - 1) Then
                                       argb1% = PeekInt (palette_table, PeekByte(t_color_table, row * cols) Shl 2)
                                    Else
                                       argb1% = PeekInt (palette_table, PeekByte(t_color_table, disp + 1) Shl 2)
                                    EndIf
                                    argb0 = argb : argb2 = argb1 : argb3 = argb
                                 Case 2 :
                                    If col = 0 Then
                                       argb0% = PeekInt (palette_table, PeekByte(t_color_table, disp + cols - 1) Shl 2)
                                    Else
                                       argb0% = PeekInt (palette_table, PeekByte(t_color_table, disp - 1) Shl 2)
                                    EndIf
                                    argb1 = argb : argb2 = argb : argb3 = argb0
                                 Case 4 :
                                    If row = (rows - 1) Then
                                       argb2% = PeekInt (palette_table, PeekByte(t_color_table, col) Shl 2)
                                    Else
                                       argb2% = PeekInt (palette_table, PeekByte(t_color_table, disp + cols) Shl 2)
                                    EndIf
                                    argb0 = argb : argb1 = argb : argb3 = argb2
                                 Case 8 :
                                    If row = 0 Then
                                       argb0% = PeekInt (palette_table, PeekByte(t_color_table, (row - 1) * cols + col) Shl 2)
                                    Else
                                       argb0% = PeekInt (palette_table, PeekByte(t_color_table, disp - cols) Shl 2)
                                    EndIf
                                    argb1 = argb0 : argb2 = argb : argb3 = argb
                                 Default :
                                    argb0 = argb : argb1 = argb : argb2 = argb : argb3 = argb
                              End Select
                              Select shade And $F0 ; alpha
                                 Case 16 :
                                    If col = (cols - 1) Then
                                       alpha1% = PeekByte(alpha_table, row * cols) Shl 24
                                    Else
                                       alpha1% = PeekByte(alpha_table, disp + 1) Shl 24
                                    EndIf
                                    SetCustomColor argb0 Or alpha, argb1 Or alpha1, argb2 Or alpha1, argb3 Or alpha
                                 Case 32 :
                                    If col = 0 Then
                                       alpha1% = PeekByte(alpha_table, disp + cols - 1) Shl 24
                                    Else
                                       alpha1% = PeekByte(alpha_table, disp - 1) Shl 24
                                    EndIf
                                    SetCustomColor argb0 Or alpha1, argb1 Or alpha, argb2 Or alpha, argb3 Or alpha1
                                 Case 64 :
                                    If row = (rows - 1) Then
                                       alpha1% = PeekByte(alpha_table, col) Shl 24
                                    Else
                                       alpha1% = PeekByte(alpha_table, disp + cols) Shl 24
                                    EndIf
                                    SetCustomColor argb0 Or alpha, argb1 Or alpha, argb2 Or alpha1, argb3 Or alpha1
                                 Case 128 :
                                    If row = 0 Then
                                       alpha1% = PeekByte(alpha_table, (row - 1) * cols + col) Shl 24
                                    Else
                                       alpha1% = PeekByte(alpha_table, disp - cols) Shl 24
                                    EndIf
                                    SetCustomColor argb0 Or alpha1, argb1 Or alpha1, argb2 Or alpha, argb3 Or alpha
                                 Default :
                                    SetCustomColor argb0 Or alpha, argb1 Or alpha, argb2 Or alpha, argb3 Or alpha
                              End Select
                           Else
                              argb% = PeekInt (palette_table, PeekByte(t_color_table, disp) Shl 2) Or alpha
                              SetCustomColor argb, argb, argb, argb
                           EndIf
                        Else
                           argb% = PeekInt (palette_table, PeekByte(t_color_table, disp) Shl 2) Or $FF000000
                           SetCustomColor argb, argb, argb, argb
                        EndIf
                        If font_size = False Then
                           DrawImageRectEx_ font_image, draw_X + col * char_width, draw_Y + row * char_height, w, h, char
                        Else
                           Select font_size And TXRNA_FONT_WIDTH_MULTIPLY
                              Case TXRNA_DOUBLE_WIDTH_ON : partwidth# = w * 0.5 : partx# = (font_select_col Mod 2) * partwidth
                              Case TXRNA_TRIPLE_WIDTH_ON : partwidth# = w * 0.33333333 : partx# = (font_select_col Mod 3) * partwidth
                              Case TXRNA_QUADRUPLE_WIDTH_ON : partwidth# = w * 0.25 : partx# = (font_select_col Mod 4) * partwidth
                              Default : partwidth# = w : partx# = 0
                           End Select
                           Select font_size And TXRNA_FONT_HEIGHT_MULTIPLY
                              Case TXRNA_DOUBLE_HEIGHT_ON : partheight# = h * 0.5 : party# = (font_select_row Mod 2) * partheight
                              Case TXRNA_TRIPLE_HEIGHT_ON : partheight# = h * 0.33333333 : party# = (font_select_row Mod 3) * partheight
                              Case TXRNA_QUADRUPLE_HEIGHT_ON : partheight# = h * 0.25 : party# = (font_select_row Mod 4) * partheight
                              Default : partheight# = h : party# = 0
                           End Select
                           DrawImagePart_ font_image, draw_X + col * char_width, draw_Y + row * char_height, w, h, partx, party, partwidth, partheight, char, 0
                        EndIf
                     EndIf
                  EndIf
               EndIf
            EndIf

            font_select_col = font_select_col + 1
            disp = disp + 1
         Next
         font_select_row = font_select_row + 1
      Next
      
      ; *********** strikeout and underline are to be merged into the "lines" scheme *****************
      ; lines_table%
      ; lines_mask_table%
      ; strikeout
      argb% = PeekInt (palette_table, term\page[page_id]\strikeout_color Shl 2)
      SetColor (argb Shr 16) And $ff, (argb Shr 8) And $ff, argb And $ff
      Local strikeout_len% = 0
      SetLineWidth Floor(char_height * 0.04) + 1
      SetBlend FI_ALPHABLEND
      SetAlpha term\page[page_id]\text_alpha
      If special_features And PGMOD_SF_UPDATE_CHARS_ON Then
         For row = start_row To end_row
            For col = start_col To end_col
               disp = row * cols + col
               If PeekByte(item_table, disp) = mouse_saved_item Then
                  strikeout = (PeekByte(attr_mask_table, disp) And TXRNA_STRIKEOUT_ON)
               Else
                  strikeout = (PeekByte(attr_table, disp) And TXRNA_STRIKEOUT_ON)
               EndIf
               If strikeout Then
                  If (page_mode And PGMOD_SF_UPDATE_ANGLE_ON) > False Then
                     SetRotation PeekByte(angle_table, disp) * 2
                  EndIf
                  If (page_mode And PGMOD_SF_UPDATE_ALPHA_ON) > False Then
                     SetAlpha PeekByte(alpha_table, disp) * 0.003921569
                  EndIf
                  If (page_mode And PGMOD_SF_UPDATE_ZOOM_ON) > False Then
                     SetScale PeekByte(x_zoom_table, disp) * 0.015625, PeekByte(y_zoom_table, disp) * 0.015625
                  EndIf
                  If (page_mode And PGMOD_SF_UPDATE_OFFSET_ON) > False Then
                     SetOrigin PeekByte(x_offset_table, disp) - 128, PeekByte(y_offset_table, disp) - 128
                  EndIf
                  SetColor (argb Shr 16) And $ff, (argb Shr 8) And $ff, argb And $ff
                  DrawLineSimple col * char_width, (row + 1) * char_height - char_height * 0.5, (col + 1) * char_width, (row + 1) * char_height - char_height * 0.5
               EndIf
            Next
         Next
      Else
         For row = start_row To end_row
            For col = start_col To end_col
               disp = row * cols + col
               If PeekByte(item_table, disp) = mouse_saved_item Then
                  strikeout = (PeekByte(attr_mask_table, disp) And TXRNA_STRIKEOUT_ON)
               Else
                  strikeout = (PeekByte(attr_table, disp) And TXRNA_STRIKEOUT_ON)
               EndIf
               If strikeout Then
                  If strikeout_len = 0 Then draw_start_col = col
                  strikeout_len = strikeout_len + 1
               Else
                  If strikeout_len > 0 Then
                     draw_start_X = draw_start_col * char_width
                     draw_start_Y = row * char_height + Float char_height * 0.5
                     ;DrawRectSimple draw_start_X, draw_start_Y, char_width * strikeout_len, strikeout_thickness, 1
                     DrawLineSimple draw_start_X, draw_start_Y, draw_start_X + char_width * strikeout_len, draw_start_Y
                     strikeout_len = 0
                  EndIf
               EndIf
            Next
            If strikeout_len > 0 Then
               draw_start_X = draw_start_col * char_width
               draw_start_Y = row * char_height + Float char_height * 0.5
               ;DrawRectSimple draw_start_X, draw_start_Y, char_width * strikeout_len, strikeout_thickness, 1
               DrawLineSimple draw_start_X, draw_start_Y, draw_start_X + char_width * strikeout_len, draw_start_Y
               
               strikeout_len = 0
            EndIf
         Next
      EndIf
      
      ; underline
      Local underline_len% = 0
	   SetLineWidth char_height * 0.04 + 1
      argb% = PeekInt (palette_table, term\page[page_id]\underline_color Shl 2)
      SetColor (argb Shr 16) And $ff, (argb Shr 8) And $ff, argb And $ff
      SetBlend FI_ALPHABLEND
      SetAlpha term\page[page_id]\text_alpha
      If special_features And PGMOD_SF_UPDATE_CHARS_ON Then
         For row = start_row To end_row
            For col = start_col To end_col
               disp = row * cols + col
               If PeekByte(item_table, disp) = mouse_saved_item Then
                  underline% = (PeekByte(attr_mask_table, disp) And TXRNA_UNDERLINE_ON)
               Else
                  underline% = (PeekByte(attr_table, disp) And TXRNA_UNDERLINE_ON)
               EndIf
               If underline Then
                  If (page_mode And PGMOD_SF_UPDATE_ANGLE_ON) > False Then
                     SetRotation PeekByte(angle_table, disp) * 2
                  EndIf
                  If (page_mode And PGMOD_SF_UPDATE_ALPHA_ON) > False Then
                     SetAlpha PeekByte(alpha_table, disp) * 0.003921569
                  EndIf
                  If (page_mode And PGMOD_SF_UPDATE_ZOOM_ON) > False Then
                     SetScale PeekByte(x_zoom_table, disp) * 0.015625, PeekByte(y_zoom_table, disp) * 0.015625
                  EndIf
                  If (page_mode And PGMOD_SF_UPDATE_OFFSET_ON) > False Then
                     SetOrigin PeekByte(x_offset_table, disp) - 128, PeekByte(y_offset_table, disp) - 128
                  EndIf
                  SetColor (argb Shr 16) And $ff, (argb Shr 8) And $ff, argb And $ff
                  DrawLineSimple col * char_width, (row + 1) * char_height - 1, (col + 1) * char_width, (row + 1) * char_height - 1
               EndIf
            Next
         Next
      Else
         For row = start_row To end_row
            For col = start_col To end_col
               disp = row * cols + col
               If PeekByte(item_table, disp) = mouse_saved_item Then
                  underline% = (PeekByte(attr_mask_table, disp) And TXRNA_UNDERLINE_ON)
               Else
                  underline% = (PeekByte(attr_table, disp) And TXRNA_UNDERLINE_ON)
               EndIf
               If underline Then
                  If underline_len = 0 Then draw_start_col = col
                  underline_len = underline_len + 1
               Else
                  If underline_len > 0 Then
                     draw_start_X = draw_start_col * char_width
                     draw_start_Y = row * char_height + char_height - 1
                     DrawLineSimple draw_start_X, draw_start_Y, draw_start_X + char_width * underline_len, draw_start_Y
                     underline_len = 0
                  EndIf
               EndIf
            Next
            If underline_len > 0 Then
               draw_start_X = draw_start_col * char_width
               draw_start_Y = row * char_height + char_height - 1
               DrawLineSimple draw_start_X, draw_start_Y, draw_start_X + char_width * underline_len, draw_start_Y
               underline_len = 0
            EndIf
         Next
      EndIf
      
      EndDraw
   EndIf
   
   term\page[page_id]\mode = term\page[page_id]\mode And PGMOD_UPDATE_DISPLAY_OFF
   If page_id > 3 Then Return

   ; cursor
   If term\page_focus = page_id Then
      col = term\page[page_id]\cursor_col
      row = term\page[page_id]\cursor_row
      If (term\mode And TRMOD_KEYBOARD_CURSOR_ON) > False Then
         If col >= start_col And col <= end_col And row >= start_row And row <= end_row Then 
            If term\cursor_anim_pos > PeekByte(term\cursor_anim_char_table, 0)  Then
               char_pos% = 1
            Else
               char_pos% = term\cursor_anim_pos
            EndIf
            If term\cursor_anim_pos > PeekByte(term\cursor_anim_color_table, 0) Then
               color_pos% = 1
            Else
               color_pos% = term\cursor_anim_pos
            EndIf
            If term\timer >= (term\cursor_timer + term\cursor_anim_delay) Then 
               term\cursor_timer = term\timer
               term\cursor_anim_pos = term\cursor_anim_pos + 1
               If term\cursor_anim_pos > PeekByte(term\cursor_anim_char_table, 0) And term\cursor_anim_pos > PeekByte(term\cursor_anim_color_table, 0) Then
                  term\cursor_anim_pos = 1
               EndIf
            EndIf
            argb% = term_get_palette_color(page_id, PeekByte(term\cursor_anim_color_table%, color_pos))
            StartDraw
            SetColor GetRed(argb), GetGreen(argb), GetBlue(argb)
            scale_X# = char_width / Float term\font[0]\width
            scale_Y# = char_height / Float term\font[0]\height
            draw_X# = (Float term\font[0]\width * 0.5 * scale_X)
            draw_Y# = (Float term\font[0]\height * 0.5 * scale_Y)
            disp = row * cols + col
            If special_features <> False Then
               If (page_mode And PGMOD_SF_UPDATE_ANGLE_ON) > False Then
                  SetRotation PeekByte(angle_table, disp) * 2
               EndIf
               If (page_mode And PGMOD_SF_UPDATE_ALPHA_ON) > False Then
                  If term\page[page_id]\text_alpha < 1.0
                     SetAlpha term\page[page_id]\text_alpha * term\cursor_alpha * (PeekByte(alpha_table, disp) * 0.003921569)
                  Else
                     SetAlpha term\cursor_alpha * (PeekByte(alpha_table, disp) * 0.003921569)
                  EndIf
               Else
                  If term\page[page_id]\text_alpha < 1.0
                     SetAlpha term\page[page_id]\text_alpha * term\cursor_alpha
                  Else
                     SetAlpha term\cursor_alpha
                  EndIf
               EndIf
               If (page_mode And PGMOD_SF_UPDATE_ZOOM_ON) > False Then
                  SetScale scale_X * PeekByte(x_zoom_table, disp) * 0.015625, scale_Y * PeekByte(y_zoom_table, disp) * 0.015625
               EndIf
               If (page_mode And PGMOD_SF_UPDATE_OFFSET_ON) > False Then
                  SetOrigin PeekByte(x_offset_table, disp) - 128, PeekByte(y_offset_table, disp) - 128
               EndIf
            Else
               SetScale scale_X#, scale_Y#
               If term\page[page_id]\text_alpha < 1.0
                  SetAlpha term\page[page_id]\text_alpha * term\cursor_alpha
               Else
                  SetAlpha term\cursor_alpha
               EndIf
            EndIf
            DrawImageRectEx_ term\font[0]\image, draw_X + col * char_width, draw_Y + row * char_height, term\font[0]\width, term\font[0]\height, PeekByte(term\cursor_anim_char_table, char_pos)
            EndDraw
         EndIf
      EndIf
   EndIf

   ; mouse pointer
   If (term\mode And TRMOD_MOUSE_CURSOR_ON) > False Then
      col = ((term\mouse_X - X) - char_width * 0.5) / char_width
      row = ((term\mouse_Y - Y) - char_height * 0.5) / char_height
      If col >= start_col And col <= end_col And row >= start_row And row <= end_row Then 
         If term\mouse_anim_pos > PeekByte(term\mouse_anim_char_table, 0)  Then
            char_pos% = 1
         Else
            char_pos% = term\mouse_anim_pos
         EndIf
         If term\mouse_anim_pos > PeekByte(term\mouse_anim_color_table, 0) Then
            color_pos% = 1
         Else
            color_pos% = term\mouse_anim_pos
         EndIf
         If term\timer >= (term\mouse_timer + term\mouse_anim_delay) Then 
            term\mouse_timer = term\timer
            term\mouse_anim_pos = term\mouse_anim_pos + 1
            If term\mouse_anim_pos > PeekByte(term\mouse_anim_char_table, 0) And term\mouse_anim_pos > PeekByte(term\mouse_anim_color_table, 0) Then
               term\mouse_anim_pos = 1
            EndIf
         EndIf
         StartDraw
         disp = row * cols + col
         
         argb% = term_get_palette_color(page_id, PeekByte(term\mouse_anim_color_table, color_pos))
         SetColor GetRed(argb), GetGreen(argb), GetBlue(argb)
         scale_X# = char_width / Float term\font[0]\width
         scale_Y# = char_height / Float term\font[0]\height
         draw_X# = (Float term\font[0]\width * 0.5 * scale_X)
         draw_Y# = (Float term\font[0]\height * 0.5 * scale_Y)
         If special_features Then
            If page_mode And PGMOD_SF_UPDATE_ANGLE_ON Then
               SetRotation PeekByte(angle_table, disp) * 2
            EndIf
            If page_mode And PGMOD_SF_UPDATE_ZOOM_ON Then
               SetScale scale_X * PeekByte(x_zoom_table, disp) * 0.015625, scale_Y * PeekByte(y_zoom_table, disp) * 0.015625
            EndIf
            If page_mode And PGMOD_SF_UPDATE_OFFSET_ON Then
               SetOrigin PeekByte(x_offset_table, disp) - 128, PeekByte(y_offset_table, disp) - 128
            EndIf
         Else
            SetScale scale_X#, scale_Y#
         EndIf
         SetAlpha term\mouse_alpha
         DrawImageRectEx_ term\font[0]\image, draw_X + col * char_width, draw_Y + row * char_height, term\font[0]\width, term\font[0]\height, PeekByte(term\mouse_anim_char_table, char_pos)
         EndDraw
      EndIf
   EndIf
   
End Function


This routine gets executed every frame for every page displayed. When you set the scale in fastImage, actually you define the scaling values for the following FI instructions. Same with setting colors and others. So it's relatively straight forward, and really fast! When I move my code to BlitzMax, I expect much faster framerates.

Look for SetProjScale and SetProjHandle, as well as SetScale. StartDraw and EndDraw is for building a FI mesh .
=-=-=-=-=-=-=

Anyhow, back to topic plz