initial pandora port, with hardware scaling and stuff
[gpsp.git] / video.c
diff --git a/video.c b/video.c
index 7415c76..a33accf 100644 (file)
--- a/video.c
+++ b/video.c
@@ -87,6 +87,11 @@ static void Ge_Finish_Callback(int id, void *arg)
 
 #elif defined(WIZ_BUILD)
 
+static u16 rot_buffer[240*4];
+static u32 rot_lines_total = 4;
+static u32 rot_line_count = 0;
+static char rot_msg_buff[64];
+
 static u32 screen_offset = 0;
 static u16 *screen_pixels = NULL;
 const u32 screen_pitch = 320;
@@ -97,6 +102,16 @@ const u32 screen_pitch = 320;
 #define get_screen_pitch()                                                    \
   screen_pitch                                                                \
 
+#elif defined(PND_BUILD)
+
+static u16 *screen_pixels = NULL;
+
+#define get_screen_pixels()                                                   \
+  screen_pixels                                                               \
+
+#define get_screen_pitch()                                                    \
+  resolution_width                                                            \
+
 #else
 
 #ifdef GP2X_BUILD
@@ -105,7 +120,6 @@ SDL_Surface *hw_screen;
 #endif
 SDL_Surface *screen;
 const u32 video_scale = 1;
-extern void gp2x_flush_cache(void *beginning_addr, void *end_addr, int flags);
 
 #define get_screen_pixels()                                                   \
   ((u16 *)screen->pixels)                                                     \
@@ -2399,7 +2413,7 @@ fill_line_builder(color32);
 
 #ifdef RENDER_COLOR16_NORMAL
 
-#ifndef GP2X_BUILD
+#ifndef ARM_ARCH
 
 void expand_normal(u16 *screen_ptr, u32 start, u32 end)
 {
@@ -2428,7 +2442,10 @@ void expand_normal(u16 *screen_ptr, u32 start, u32 end)
 #endif
 
 
-#ifndef GP2X_BUILD
+void expand_blend(u32 *screen_src_ptr, u16 *screen_dest_ptr,
+ u32 start, u32 end);
+
+#ifndef ARM_ARCH
 
 void expand_blend(u32 *screen_src_ptr, u16 *screen_dest_ptr,
  u32 start, u32 end)
@@ -3272,6 +3289,28 @@ void update_scanline()
   if(skip_next_frame)
     return;
 
+#ifdef WIZ_BUILD
+  if (screen_scale == unscaled_rot || screen_scale == scaled_aspect_rot)
+  {
+    if (rot_line_count == rot_lines_total)
+    {
+      rot_line_count = 0;
+      if (vcount - rot_lines_total < FONT_HEIGHT && rot_msg_buff[0])
+      {
+        print_string_ext(rot_msg_buff, 0xFFFF, 0x0000, 0, 0,
+          rot_buffer, 240, 0, vcount - rot_lines_total, rot_lines_total);
+        if (vcount >= FONT_HEIGHT)
+          rot_msg_buff[0] = 0;
+      }
+      if (screen_scale == unscaled_rot)
+        do_rotated_blit(gpsp_gp2x_screen, rot_buffer, vcount);
+      else
+        upscale_aspect_row(gpsp_gp2x_screen, rot_buffer, vcount/3);
+    }
+    screen_offset = &rot_buffer[rot_line_count++ * 240];
+  }
+#endif
+
   // If the screen is in in forced blank draw pure white.
   if(dispcnt & 0x80)
   {
@@ -3339,10 +3378,37 @@ void flip_screen()
 
 void flip_screen()
 {
+  if((resolution_width == small_resolution_width) &&
+   (resolution_height == small_resolution_height))
+  {
+    switch(screen_scale)
+    {
+      case scaled_aspect:
+        upscale_aspect(gpsp_gp2x_screen, screen_pixels);
+        break;
+      case unscaled_rot:
+        do_rotated_blit(gpsp_gp2x_screen, rot_buffer, 160);
+        rot_line_count = 0;
+        goto no_clean;
+      case scaled_aspect_rot:
+        rot_line_count = 0;
+        goto no_clean;
+    }
+  }
+  warm_cache_op_all(WOP_D_CLEAN);
+
+no_clean:
   pollux_video_flip();
   screen_pixels = (u16 *)gpsp_gp2x_screen + screen_offset;
 }
 
+#elif defined(PND_BUILD)
+
+void flip_screen()
+{
+  screen_pixels = fb_flip_screen();
+}
+
 #else
 
 #define integer_scale_copy_2()                                                \
@@ -3418,28 +3484,37 @@ void flip_screen()
   }
 #ifdef GP2X_BUILD
   {
-    if((screen_scale == unscaled) &&
-     (resolution_width == small_resolution_width) &&
-     (resolution_height == small_resolution_height))
-    {
-      SDL_Rect srect = {0, 0, 240, 160};
-      SDL_Rect drect = {40, 40, 240, 160};
-      SDL_BlitSurface(screen, &srect, hw_screen, &drect);
-    }
-    else if((screen_scale == scaled_aspect) &&
-     (resolution_width == small_resolution_width) &&
+    if((resolution_width == small_resolution_width) &&
      (resolution_height == small_resolution_height))
     {
-      SDL_Rect drect = {0, 10, 0, 0};
-      SDL_BlitSurface(screen, NULL, hw_screen, &drect);
-    }
-    else
-    {
-      SDL_BlitSurface(screen, NULL, hw_screen, NULL);
+      switch (screen_scale)
+      {
+        case unscaled:
+        {
+          SDL_Rect srect = {0, 0, 240, 160};
+          SDL_Rect drect = {40, 40, 240, 160};
+          warm_cache_op_all(WOP_D_CLEAN);
+          SDL_BlitSurface(screen, &srect, hw_screen, &drect);
+          return;
+        }
+        case scaled_aspect:
+        {
+          SDL_Rect drect = {0, 10, 0, 0};
+          warm_cache_op_all(WOP_D_CLEAN);
+          SDL_BlitSurface(screen, NULL, hw_screen, &drect);
+          return;
+        }
+        case scaled_aspect_sw:
+        {
+          upscale_aspect(hw_screen->pixels, get_screen_pixels());
+          return;
+        }
+        case fullscreen:
+          break;
+      }
     }
-    /* it is unclear if this syscall takes virtual or physical addresses,
-     * but using virtual seems to work for me. */
-    gp2x_flush_cache(hw_screen->pixels, hw_screen->pixels + 320*240, 0);
+    warm_cache_op_all(WOP_D_CLEAN);
+    SDL_BlitSurface(screen, NULL, hw_screen, NULL);
   }
 #else
   SDL_Flip(screen);
@@ -3543,7 +3618,7 @@ void init_video()
   GE_CMD(NOP, 0);
 }
 
-#elif defined(WIZ_BUILD)
+#elif defined(WIZ_BUILD) || defined(PND_BUILD)
 
 void init_video()
 {
@@ -3564,7 +3639,7 @@ void init_video()
   screen = SDL_CreateRGBSurface(SDL_HWSURFACE, 240 * video_scale,
    160 * video_scale, 16, 0xFFFF, 0xFFFF, 0xFFFF, 0);
 
-  gp2x_load_mmuhack();
+  warm_change_cb_upper(WCB_C_BIT|WCB_B_BIT, 1);
 #else
   screen = SDL_SetVideoMode(240 * video_scale, 160 * video_scale, 16, 0);
 #endif
@@ -3688,17 +3763,76 @@ void video_resolution_large()
   fb_use_buffers(1);
   flip_screen();
   clear_screen(0);
+  wiz_lcd_set_portrait(0);
 }
 
 void video_resolution_small()
 {
-  screen_offset = 320*40 + 40;
+  fb_use_buffers(4);
+
+  switch (screen_scale)
+  {
+    case unscaled:
+      screen_offset = 320*40 + 40;
+      wiz_lcd_set_portrait(0);
+      break;
+    case scaled_aspect:
+      screen_offset = 320*(80 - 14) + 80;
+      wiz_lcd_set_portrait(0);
+      break;
+    case unscaled_rot:
+      wiz_lcd_set_portrait(1);
+      rot_lines_total = 4;
+      rot_line_count = 0;
+      break;
+    case scaled_aspect_rot:
+      wiz_lcd_set_portrait(1);
+      rot_lines_total = 3;
+      rot_line_count = 0;
+      break;
+  }
+
+  flip_screen();
+  clear_screen(0);
+
   resolution_width = 240;
   resolution_height = 160;
+}
 
-  fb_use_buffers(999);
+void set_gba_resolution(video_scale_type scale)
+{
+  screen_scale = scale;
+}
+
+void clear_screen(u16 color)
+{
+  u32 col = ((u32)color << 16) | color;
+  u32 *p = gpsp_gp2x_screen;
+  int c = 320*240/2;
+  while (c-- > 0)
+    *p++ = col;
+}
+
+#elif defined(PND_BUILD)
+
+void video_resolution_large()
+{
+  resolution_width = 400;
+  resolution_height = 272;
+
+  fb_set_mode(400, 272, 1, 15, screen_filter);
+  flip_screen();
   clear_screen(0);
+}
+
+void video_resolution_small()
+{
+  resolution_width = 240;
+  resolution_height = 160;
+
+  fb_set_mode(240, 160, 4, screen_scale, screen_filter);
   flip_screen();
+  clear_screen(0);
 }
 
 void set_gba_resolution(video_scale_type scale)
@@ -3709,8 +3843,8 @@ void set_gba_resolution(video_scale_type scale)
 void clear_screen(u16 color)
 {
   u32 col = ((u32)color << 16) | color;
-  u32 *p = gpsp_gp2x_screen;
-  int c = 320*240/2;
+  u32 *p = (u32 *)get_screen_pixels();
+  int c = resolution_width * resolution_height / 2;
   while (c-- > 0)
     *p++ = col;
 }
@@ -3731,7 +3865,7 @@ void video_resolution_large()
     resolution_height = 240;
   SDL_ShowCursor(0);
 
-  gp2x_load_mmuhack();
+  warm_change_cb_upper(WCB_C_BIT|WCB_B_BIT, 1);
 #else
   screen = SDL_SetVideoMode(480, 272, 16, 0);
   resolution_width = 480;
@@ -3749,7 +3883,7 @@ void video_resolution_small()
   SDL_GP2X_AllowGfxMemory(NULL, 0);
 
   w = 320; h = 240;
-  if (screen_scale != unscaled)
+  if (screen_scale == scaled_aspect || screen_scale == fullscreen)
   {
     w = small_resolution_width * video_scale;
     h = small_resolution_height * video_scale;
@@ -3757,13 +3891,16 @@ void video_resolution_small()
   if (screen_scale == scaled_aspect) h += 20;
   hw_screen = SDL_SetVideoMode(w, h, 16, SDL_HWSURFACE);
 
+  w = small_resolution_width * video_scale;
+  if (screen_scale == scaled_aspect_sw)
+    w = 320;
   screen = SDL_CreateRGBSurface(SDL_HWSURFACE,
-   small_resolution_width * video_scale, small_resolution_height *
-   video_scale, 16, 0xFFFF, 0xFFFF, 0xFFFF, 0);
+   w, small_resolution_height * video_scale,
+   16, 0xFFFF, 0xFFFF, 0xFFFF, 0);
 
   SDL_ShowCursor(0);
 
-  gp2x_load_mmuhack();
+  warm_change_cb_upper(WCB_C_BIT|WCB_B_BIT, 1);
 #else
   screen = SDL_SetVideoMode(small_resolution_width * video_scale,
    small_resolution_height * video_scale, 16, 0);
@@ -3819,34 +3956,33 @@ void blit_to_screen(u16 *src, u32 w, u32 h, u32 dest_x, u32 dest_y)
   u32 pitch = get_screen_pitch();
   u16 *dest_ptr = get_screen_pixels() + dest_x + (dest_y * pitch);
 
+  s32 w1 = dest_x + w > pitch ? pitch - dest_x : w;
   u16 *src_ptr = src;
-  u32 line_skip = pitch - w;
-  u32 x, y;
+  s32 x, y;
 
   for(y = 0; y < h; y++)
   {
-    for(x = 0; x < w; x++, src_ptr++, dest_ptr++)
+    for(x = 0; x < w1; x++)
     {
-      *dest_ptr = *src_ptr;
+      dest_ptr[x] = src_ptr[x];
     }
-    dest_ptr += line_skip;
+    src_ptr += w;
+    dest_ptr += pitch;
   }
 }
 
 void print_string_ext(const char *str, u16 fg_color, u16 bg_color,
- u32 x, u32 y, void *_dest_ptr, u32 pitch, u32 pad)
+ u32 x, u32 y, void *_dest_ptr, u32 pitch, u32 pad, u32 h_offset, u32 height)
 {
   u16 *dest_ptr = (u16 *)_dest_ptr + (y * pitch) + x;
   u8 current_char = str[0];
   u32 current_row;
   u32 glyph_offset;
-  u32 i = 0, i2, i3;
+  u32 i = 0, i2, i3, h;
   u32 str_index = 1;
   u32 current_x = x;
 
-
-  /* EDIT */
-  if(y + FONT_HEIGHT > resolution_height)
+  if(y + height > resolution_height)
       return;
 
   while(current_char)
@@ -3861,7 +3997,8 @@ void print_string_ext(const char *str, u16 fg_color, u16 bg_color,
     {
       glyph_offset = _font_offset[current_char];
       current_x += FONT_WIDTH;
-      for(i2 = 0; i2 < FONT_HEIGHT; i2++, glyph_offset++)
+      glyph_offset += h_offset;
+      for(i2 = h_offset, h = 0; i2 < FONT_HEIGHT && h < height; i2++, h++, glyph_offset++)
       {
         current_row = _font_bits[glyph_offset];
         for(i3 = 0; i3 < FONT_WIDTH; i3++)
@@ -3874,7 +4011,7 @@ void print_string_ext(const char *str, u16 fg_color, u16 bg_color,
         }
         dest_ptr += (pitch - FONT_WIDTH);
       }
-      dest_ptr = dest_ptr - (pitch * FONT_HEIGHT) + FONT_WIDTH;
+      dest_ptr = dest_ptr - (pitch * h) + FONT_WIDTH;
     }
 
     i++;
@@ -3903,15 +4040,24 @@ void print_string_ext(const char *str, u16 fg_color, u16 bg_color,
 void print_string(const char *str, u16 fg_color, u16 bg_color,
  u32 x, u32 y)
 {
+#ifdef WIZ_BUILD
+  if ((screen_scale == unscaled_rot || screen_scale == scaled_aspect_rot) &&
+   (resolution_width == small_resolution_width) &&
+   (resolution_height == small_resolution_height))
+  {
+    snprintf(rot_msg_buff, sizeof(rot_msg_buff), "%s", str);
+    return;
+  }
+#endif
   print_string_ext(str, fg_color, bg_color, x, y, get_screen_pixels(),
-   get_screen_pitch(), 0);
+   get_screen_pitch(), 0, 0, FONT_HEIGHT);
 }
 
 void print_string_pad(const char *str, u16 fg_color, u16 bg_color,
  u32 x, u32 y, u32 pad)
 {
   print_string_ext(str, fg_color, bg_color, x, y, get_screen_pixels(),
-   get_screen_pitch(), pad);
+   get_screen_pitch(), pad, 0, FONT_HEIGHT);
 }
 
 u32 debug_cursor_x = 0;