Graphics.cpp 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. #include <os.h>
  2. #include <Graphics.h>
  3. #include <misc.h>
  4. #define GRAPHICS WalrusRPG::Graphics
  5. #define LCD_CONTROLLER 0xC0000000
  6. volatile unsigned *lcd_base = (unsigned *) (LCD_CONTROLLER + 0x10);
  7. volatile unsigned *lcd_ris = (unsigned *) (LCD_CONTROLLER + 0x20);
  8. volatile unsigned *lcd_icr = (unsigned *) (LCD_CONTROLLER + 0x28);
  9. volatile unsigned *lcd_control = (unsigned *) (LCD_CONTROLLER + 0x18);
  10. unsigned lcd_control_bkp;
  11. #define BUFFER_SIZE 320 * 240 * 2
  12. unsigned short *buffer_screen = NULL, *buffer_render = NULL, *buffer_ready = NULL, *buffer_os;
  13. bool buffer_swap_ready;
  14. /*
  15. * Buffer management
  16. */
  17. void GRAPHICS::buffer_allocate()
  18. {
  19. buffer_screen = (unsigned short *) malloc(BUFFER_SIZE);
  20. buffer_render = (unsigned short *) malloc(BUFFER_SIZE);
  21. buffer_ready = (unsigned short *) malloc(BUFFER_SIZE);
  22. if (buffer_screen == NULL || buffer_render == NULL || buffer_ready == NULL)
  23. {
  24. free(buffer_screen);
  25. free(buffer_render);
  26. free(buffer_ready);
  27. exit(0);
  28. }
  29. buffer_os = (unsigned short *) *lcd_base;
  30. *lcd_base = (unsigned) buffer_screen;
  31. buffer_swap_ready = false;
  32. // Set up the controller in order to use vsync signals
  33. lcd_control_bkp = *lcd_control;
  34. *lcd_control &= ~(0b11 << 12);
  35. *lcd_control |= 0b11 << 12;
  36. }
  37. void GRAPHICS::buffer_free()
  38. {
  39. free(buffer_screen);
  40. free(buffer_render);
  41. free(buffer_ready);
  42. *lcd_base = (unsigned) buffer_os;
  43. *lcd_control = lcd_control_bkp;
  44. }
  45. void GRAPHICS::buffer_swap_screen()
  46. {
  47. if (buffer_swap_ready)
  48. {
  49. unsigned short *buffer_screen_tmp = buffer_screen;
  50. buffer_screen = buffer_ready;
  51. buffer_ready = buffer_screen_tmp;
  52. *lcd_base = (unsigned) buffer_screen;
  53. buffer_swap_ready = false;
  54. }
  55. }
  56. void GRAPHICS::buffer_swap_render()
  57. {
  58. unsigned short *buffer_ready_tmp = buffer_ready;
  59. buffer_ready = buffer_render;
  60. buffer_render = buffer_ready_tmp;
  61. buffer_swap_ready = true;
  62. }
  63. void GRAPHICS::buffer_fill(unsigned color)
  64. {
  65. unsigned *buffer_render_32 = (unsigned *) buffer_render;
  66. color |= color << 16; // To avoid stupid overflows
  67. for (unsigned i = 0; i < (BUFFER_SIZE / 4); i++)
  68. buffer_render_32[i] = color;
  69. }
  70. /*
  71. * Misc LCD functions
  72. */
  73. void GRAPHICS::lcd_vsync()
  74. {
  75. *lcd_icr = 1 << 3;
  76. while (!(*lcd_ris & (1 << 3)))
  77. ;
  78. }
  79. /*
  80. * Drawing
  81. */
  82. void GRAPHICS::draw_pixel(unsigned x, unsigned y, unsigned short color)
  83. {
  84. buffer_render[x + (y * 320)] = color;
  85. }
  86. void GRAPHICS::draw_sprite_sheet(const unsigned short *sheet, int x, int y, const WalrusRPG::Utils::Rect &window)
  87. {
  88. unsigned short color;
  89. int w = min(window.width + x, 320);
  90. int h = min(window.height + y, 240);
  91. for (int j = max(y, 0), l = window.y - min(y, 0); j < h; j++, l++)
  92. {
  93. for (int i = max(x, 0), k = window.x - min(x, 0); i < w; i++, k++)
  94. {
  95. color = sprite_pixel_get(sheet, k, l);
  96. if (color != sheet[2])
  97. draw_pixel(i, j, color);
  98. }
  99. }
  100. }
  101. /*
  102. * Sprite manipulation
  103. */
  104. unsigned short GRAPHICS::sprite_pixel_get(const unsigned short *sprite, unsigned x, unsigned y)
  105. {
  106. if (x < sprite[0] && y < sprite[1])
  107. return sprite[x + (y * sprite[0]) + 3];
  108. else
  109. return sprite[2];
  110. }