gbasys

view src/gfx.c @ 0:875ef6085efc

gbasys mercurial repository
author John Tsiombikas <nuclear@member.fsf.org>
date Sun, 04 Mar 2012 04:04:25 +0200
parents
children c50064b181c2
line source
1 /*
2 Copyright 2004 John Tsiombikas <nuclear@siggraph.org>
4 This file is part of libgba, a library for GameBoy Advance development.
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
21 #include "libgba_config.h"
23 #include <stdlib.h>
24 #include "gfx.h"
26 #define FRAME_SEL_BIT 0x10
28 #define H_BLANK_OAM 0x20
29 #define OBJ_MAP_2D 0x0
30 #define OBJ_MAP_1D 0x40
31 #define FORCE_BLANK 0x80
32 #define BG0_ENABLE 0x100
33 #define BG1_ENABLE 0x200
34 #define BG2_ENABLE 0x400
35 #define BG3_ENABLE 0x800
37 static volatile unsigned short *reg_disp_ctl = (void*)0x4000000;
38 static volatile unsigned short *reg_vcount = (void*)0x4000006;
40 static int xres, yres;
41 static int sizeof_pixel;
42 static int page_flipping;
43 static int allocated_back_buffer;
45 static struct pixel_buffer fbuf, bbuf;
46 struct pixel_buffer *front_buffer = &fbuf;
47 struct pixel_buffer *back_buffer = &bbuf;
49 #define show_page(n) ((n) ? (*reg_disp_ctl |= FRAME_SEL_BIT) : (*reg_disp_ctl &= ~FRAME_SEL_BIT))
50 #define swap_page() (*reg_disp_ctl ^= FRAME_SEL_BIT)
52 int set_video_mode(int mode, int double_buffering) {
53 if(mode < 3 || mode > 5) return -1;
55 /* mode 5: 160x128, otherwise: 240x160 */
56 xres = (mode == 5) ? 160 : 240;
57 yres = (mode == 5) ? 128 : 160;
59 sizeof_pixel = (mode == 4) ? 1 : 2;
61 *reg_disp_ctl = mode | BG2_ENABLE;
63 show_page(0);
65 if(allocated_back_buffer) {
66 free(back_buffer->pixels);
67 }
69 front_buffer->pixels = (void*)0x6000000;
70 front_buffer->x = back_buffer->x = xres;
71 front_buffer->y = back_buffer->y = yres;
72 front_buffer->bpp = back_buffer->bpp = sizeof_pixel * 8;
74 if(mode > 3) {
75 page_flipping = 1;
76 back_buffer->pixels = (void*)0x600a000;
77 } else {
78 page_flipping = 0;
79 if(double_buffering) {
80 back_buffer->pixels = malloc(xres * yres * sizeof_pixel);
81 }
82 }
83 }
85 void flip(void) {
86 static void *tmp;
88 if(page_flipping) {
89 swap_page();
90 tmp = front_buffer->pixels;
91 front_buffer->pixels = back_buffer->pixels;
92 back_buffer->pixels = tmp;
93 } else {
94 /*dma_copy32(3, front_buffer->pixels, back_buffer->pixels, (xres * yres) >> 1);*/
95 dma_copy32(3, front_buffer->pixels, back_buffer->pixels, 19200);
96 }
97 }
99 /* ------- pixel buffer operations ------- */
101 struct pixel_buffer *create_pixel_buffer(int x, int y, int bpp) {
102 struct pixel_buffer *pbuf = malloc(sizeof(struct pixel_buffer));
103 if(pbuf) {
104 pbuf->pixels = malloc(x * y * bpp / 8);
105 pbuf->x = x;
106 pbuf->y = y;
107 pbuf->bpp = bpp;
108 }
109 return pbuf;
110 }
112 void destroy_pixel_buffer(struct pixel_buffer *pbuf) {
113 free(pbuf->pixels);
114 free(pbuf);
115 }
117 void clear_buffer(struct pixel_buffer *pbuf, unsigned short color) {
118 int sz = pbuf->x * pbuf->y;
120 if(pbuf->bpp == 8) {
121 color |= color << 8;
122 sz >>= 1;
123 }
125 dma_fill16(3, pbuf->pixels, color, sz);
126 }
128 void copy_buffer(const struct pixel_buffer *src, struct pixel_buffer *dst) {
129 int words;
131 if(src->x != dst->x || src->y != dst->y || src->bpp != dst->bpp) return;
133 words = (src->x * src->y) >> (src->bpp == 16 ? 1 : 2);
134 dma_copy32(3, dst->pixels, src->pixels, words);
135 }
138 void draw_line(int x1, int y1, int x2, int y2, unsigned short col, struct pixel_buffer *pbuf) {
139 int dx, dy, dx2, dy2;
140 int x_inc, y_inc;
141 int error;
142 int i;
143 unsigned short *ptr = pbuf->pixels;
145 ptr += y1 * pbuf->x + x1;
146 dx = x2 - x1;
147 dy = y2 - y1;
149 if(dx >= 0) {
150 x_inc = 1;
151 } else {
152 x_inc = -1;
153 dx = -dx;
154 }
156 if(dy >= 0) {
157 y_inc = pbuf->x;
158 } else {
159 y_inc = -pbuf->x;
160 dy = -dy;
161 }
163 dx2 = dx << 1;
164 dy2 = dy << 1;
166 if(dx > dy) {
167 error = dy2 - dx;
168 for(i=0; i<=dx; i++) {
169 *ptr = col;
170 if(error >= 0) {
171 error -= dx2;
172 ptr += y_inc;
173 }
174 error += dy2;
175 ptr += x_inc;
176 }
177 } else {
178 error = dx2 - dy;
179 for(i=0;i<=dy;i++) {
180 *ptr = col;
181 if(error >= 0) {
182 error -= dy2;
183 ptr += x_inc;
184 }
185 error += dx2;
186 ptr += y_inc;
187 }
188 }
189 }