gbasys

view src/gfx.c @ 8:047c61960005

- added bg2 matrix support - changed some stupid const pointers to register addresses to hardcoded compile-time defines
author John Tsiombikas <nuclear@member.fsf.org>
date Sun, 22 Jun 2014 06:26:11 +0300
parents f77381b12726
children 85f219fcdc82
line source
1 /*
2 Copyright 2004-2012 John Tsiombikas <nuclear@member.fsf.org>
4 This file is part of gbasys, 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 "config.h"
23 #include <stdlib.h>
24 #include <string.h>
25 #include "gfx.h"
27 #define FRAME_SEL_BIT 0x10
29 #define H_BLANK_OAM 0x20
30 #define OBJ_MAP_2D 0x0
31 #define OBJ_MAP_1D 0x40
32 #define FORCE_BLANK 0x80
33 #define BG0_ENABLE 0x100
34 #define BG1_ENABLE 0x200
35 #define BG2_ENABLE 0x400
36 #define BG3_ENABLE 0x800
38 #define REG_DISPCTL (*(unsigned short*)0x4000000)
39 #define REG_VCOUNT (*(unsigned short*)0x4000006)
41 #define REG_BG2PA (*(short*)0x4000020)
42 #define REG_BG2PB (*(short*)0x4000022)
43 #define REG_BG2PC (*(short*)0x4000024)
44 #define REG_BG2PD (*(short*)0x4000026)
46 static unsigned short *paladdr = (void*)0x5000000;
48 static int xres, yres;
49 static int sizeof_pixel;
50 static int page_flipping;
51 static int allocated_back_buffer;
53 static struct pixel_buffer fbuf, bbuf;
54 struct pixel_buffer *front_buffer = &fbuf;
55 struct pixel_buffer *back_buffer = &bbuf;
57 #define show_page(n) ((n) ? (REG_DISPCTL |= FRAME_SEL_BIT) : (REG_DISPCTL &= ~FRAME_SEL_BIT))
58 #define swap_page() (REG_DISPCTL ^= FRAME_SEL_BIT)
60 int set_video_mode(int mode, int double_buffering) {
61 if(mode < 3 || mode > 5) return -1;
63 /* mode 5: 160x128, otherwise: 240x160 */
64 xres = (mode == 5) ? 160 : 240;
65 yres = (mode == 5) ? 128 : 160;
67 sizeof_pixel = (mode == 4) ? 1 : 2;
69 REG_DISPCTL = mode | BG2_ENABLE;
71 show_page(0);
73 if(allocated_back_buffer) {
74 free(back_buffer->pixels);
75 }
77 front_buffer->pixels = (void*)0x6000000;
78 front_buffer->x = back_buffer->x = xres;
79 front_buffer->y = back_buffer->y = yres;
80 front_buffer->bpp = back_buffer->bpp = sizeof_pixel * 8;
82 if(mode > 3) {
83 page_flipping = 1;
84 back_buffer->pixels = (void*)0x600a000;
85 } else {
86 page_flipping = 0;
87 if(double_buffering) {
88 back_buffer->pixels = malloc(xres * yres * sizeof_pixel);
89 }
90 }
91 }
93 void flip(void) {
94 static void *tmp;
96 if(page_flipping) {
97 swap_page();
98 tmp = front_buffer->pixels;
99 front_buffer->pixels = back_buffer->pixels;
100 back_buffer->pixels = tmp;
101 } else {
102 /*dma_copy32(3, front_buffer->pixels, back_buffer->pixels, (xres * yres) >> 1);*/
103 dma_copy32(3, front_buffer->pixels, back_buffer->pixels, 19200);
104 }
105 }
107 /* ------- pixel buffer operations ------- */
109 struct pixel_buffer *create_pixel_buffer(int x, int y, int bpp) {
110 struct pixel_buffer *pbuf = malloc(sizeof(struct pixel_buffer));
111 if(pbuf) {
112 pbuf->pixels = malloc(x * y * bpp / 8);
113 pbuf->x = x;
114 pbuf->y = y;
115 pbuf->bpp = bpp;
116 }
117 return pbuf;
118 }
120 void destroy_pixel_buffer(struct pixel_buffer *pbuf) {
121 free(pbuf->pixels);
122 free(pbuf);
123 }
125 void clear_buffer(struct pixel_buffer *pbuf, unsigned short color) {
126 int sz = pbuf->x * pbuf->y;
128 if(pbuf->bpp == 8) {
129 color |= color << 8;
130 sz >>= 1;
131 }
133 dma_fill16(3, pbuf->pixels, color, sz);
134 }
136 void copy_buffer(const struct pixel_buffer *src, struct pixel_buffer *dst) {
137 int words;
139 if(src->x != dst->x || src->y != dst->y || src->bpp != dst->bpp) return;
141 words = (src->x * src->y) >> (src->bpp == 16 ? 1 : 2);
142 dma_copy32(3, dst->pixels, src->pixels, words);
143 }
145 #define MIN(a, b) ((a) < (b) ? (a) : (b))
147 void blit(struct pixel_buffer *src, int src_x, int src_y, int src_w, int src_h,
148 struct pixel_buffer *dst, int dst_x, int dst_y)
149 {
150 int i, pixsize, width, height, dstride, sstride;
151 unsigned char *dptr, *sptr;
153 if(dst->bpp != src->bpp)
154 return;
156 if(src_w <= 0)
157 src_w = src->x;
158 if(src_h <= 0)
159 src_h = src->y;
161 width = MIN(src_w, MIN(src->x - src_x, dst->x - dst_x));
162 height = MIN(src_h, MIN(src->y - src_y, dst->y - dst_y));
164 if(width <= 0 || height <= 0)
165 return;
167 pixsize = dst->bpp / 8;
168 dptr = (unsigned char*)dst->pixels + (dst_y * dst->x + dst_x) * pixsize;
169 sptr = (unsigned char*)src->pixels + (src_y * src->x + src_x) * pixsize;
171 dstride = dst->x * pixsize;
172 sstride = src->x * pixsize;
174 for(i=0; i<height; i++) {
175 memcpy(dptr, sptr, width * pixsize);
176 sptr += sstride;
177 dptr += dstride;
178 }
179 }
181 void set_palette(int idx, int r, int g, int b)
182 {
183 paladdr[idx] = RGB(r, g, b);
184 }
186 void set_bg_matrix(int a, int b, int c, int d)
187 {
188 REG_BG2PA = a;
189 REG_BG2PB = b;
190 REG_BG2PC = c;
191 REG_BG2PD = d;
192 }
194 void set_bg_scale(int x, int y)
195 {
196 set_bg_matrix(x, 0, 0, y);
197 }
199 void draw_line(int x1, int y1, int x2, int y2, unsigned short col, struct pixel_buffer *pbuf) {
200 int dx, dy, dx2, dy2;
201 int x_inc, y_inc;
202 int error;
203 int i;
204 unsigned short *ptr = pbuf->pixels;
206 ptr += y1 * pbuf->x + x1;
207 dx = x2 - x1;
208 dy = y2 - y1;
210 if(dx >= 0) {
211 x_inc = 1;
212 } else {
213 x_inc = -1;
214 dx = -dx;
215 }
217 if(dy >= 0) {
218 y_inc = pbuf->x;
219 } else {
220 y_inc = -pbuf->x;
221 dy = -dy;
222 }
224 dx2 = dx << 1;
225 dy2 = dy << 1;
227 if(dx > dy) {
228 error = dy2 - dx;
229 for(i=0; i<=dx; i++) {
230 *ptr = col;
231 if(error >= 0) {
232 error -= dx2;
233 ptr += y_inc;
234 }
235 error += dy2;
236 ptr += x_inc;
237 }
238 } else {
239 error = dx2 - dy;
240 for(i=0;i<=dy;i++) {
241 *ptr = col;
242 if(error >= 0) {
243 error -= dy2;
244 ptr += x_inc;
245 }
246 error += dx2;
247 ptr += y_inc;
248 }
249 }
250 }