rev |
line source |
nuclear@0
|
1 /*
|
nuclear@3
|
2 Copyright 2004-2012 John Tsiombikas <nuclear@member.fsf.org>
|
nuclear@0
|
3
|
nuclear@1
|
4 This file is part of gbasys, a library for GameBoy Advance development.
|
nuclear@0
|
5
|
nuclear@0
|
6 This program is free software; you can redistribute it and/or modify
|
nuclear@0
|
7 it under the terms of the GNU General Public License as published by
|
nuclear@0
|
8 the Free Software Foundation; either version 2 of the License, or
|
nuclear@0
|
9 (at your option) any later version.
|
nuclear@0
|
10
|
nuclear@0
|
11 This program is distributed in the hope that it will be useful,
|
nuclear@0
|
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
|
nuclear@0
|
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
nuclear@0
|
14 GNU General Public License for more details.
|
nuclear@0
|
15
|
nuclear@0
|
16 You should have received a copy of the GNU General Public License
|
nuclear@0
|
17 along with this program; if not, write to the Free Software
|
nuclear@0
|
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
nuclear@0
|
19 */
|
nuclear@0
|
20
|
nuclear@1
|
21 #include "config.h"
|
nuclear@0
|
22
|
nuclear@0
|
23 #include <stdlib.h>
|
nuclear@3
|
24 #include <string.h>
|
nuclear@0
|
25 #include "gfx.h"
|
nuclear@0
|
26
|
nuclear@0
|
27 #define FRAME_SEL_BIT 0x10
|
nuclear@0
|
28
|
nuclear@0
|
29 #define H_BLANK_OAM 0x20
|
nuclear@0
|
30 #define OBJ_MAP_2D 0x0
|
nuclear@0
|
31 #define OBJ_MAP_1D 0x40
|
nuclear@0
|
32 #define FORCE_BLANK 0x80
|
nuclear@0
|
33 #define BG0_ENABLE 0x100
|
nuclear@0
|
34 #define BG1_ENABLE 0x200
|
nuclear@0
|
35 #define BG2_ENABLE 0x400
|
nuclear@0
|
36 #define BG3_ENABLE 0x800
|
nuclear@0
|
37
|
nuclear@0
|
38 static volatile unsigned short *reg_disp_ctl = (void*)0x4000000;
|
nuclear@0
|
39 static volatile unsigned short *reg_vcount = (void*)0x4000006;
|
nuclear@0
|
40
|
nuclear@0
|
41 static int xres, yres;
|
nuclear@0
|
42 static int sizeof_pixel;
|
nuclear@0
|
43 static int page_flipping;
|
nuclear@0
|
44 static int allocated_back_buffer;
|
nuclear@0
|
45
|
nuclear@0
|
46 static struct pixel_buffer fbuf, bbuf;
|
nuclear@0
|
47 struct pixel_buffer *front_buffer = &fbuf;
|
nuclear@0
|
48 struct pixel_buffer *back_buffer = &bbuf;
|
nuclear@0
|
49
|
nuclear@0
|
50 #define show_page(n) ((n) ? (*reg_disp_ctl |= FRAME_SEL_BIT) : (*reg_disp_ctl &= ~FRAME_SEL_BIT))
|
nuclear@0
|
51 #define swap_page() (*reg_disp_ctl ^= FRAME_SEL_BIT)
|
nuclear@0
|
52
|
nuclear@0
|
53 int set_video_mode(int mode, int double_buffering) {
|
nuclear@0
|
54 if(mode < 3 || mode > 5) return -1;
|
nuclear@0
|
55
|
nuclear@0
|
56 /* mode 5: 160x128, otherwise: 240x160 */
|
nuclear@0
|
57 xres = (mode == 5) ? 160 : 240;
|
nuclear@0
|
58 yres = (mode == 5) ? 128 : 160;
|
nuclear@0
|
59
|
nuclear@0
|
60 sizeof_pixel = (mode == 4) ? 1 : 2;
|
nuclear@0
|
61
|
nuclear@0
|
62 *reg_disp_ctl = mode | BG2_ENABLE;
|
nuclear@0
|
63
|
nuclear@0
|
64 show_page(0);
|
nuclear@0
|
65
|
nuclear@0
|
66 if(allocated_back_buffer) {
|
nuclear@0
|
67 free(back_buffer->pixels);
|
nuclear@0
|
68 }
|
nuclear@0
|
69
|
nuclear@0
|
70 front_buffer->pixels = (void*)0x6000000;
|
nuclear@0
|
71 front_buffer->x = back_buffer->x = xres;
|
nuclear@0
|
72 front_buffer->y = back_buffer->y = yres;
|
nuclear@0
|
73 front_buffer->bpp = back_buffer->bpp = sizeof_pixel * 8;
|
nuclear@1
|
74
|
nuclear@0
|
75 if(mode > 3) {
|
nuclear@0
|
76 page_flipping = 1;
|
nuclear@0
|
77 back_buffer->pixels = (void*)0x600a000;
|
nuclear@0
|
78 } else {
|
nuclear@0
|
79 page_flipping = 0;
|
nuclear@0
|
80 if(double_buffering) {
|
nuclear@0
|
81 back_buffer->pixels = malloc(xres * yres * sizeof_pixel);
|
nuclear@0
|
82 }
|
nuclear@0
|
83 }
|
nuclear@0
|
84 }
|
nuclear@0
|
85
|
nuclear@0
|
86 void flip(void) {
|
nuclear@0
|
87 static void *tmp;
|
nuclear@1
|
88
|
nuclear@0
|
89 if(page_flipping) {
|
nuclear@0
|
90 swap_page();
|
nuclear@0
|
91 tmp = front_buffer->pixels;
|
nuclear@0
|
92 front_buffer->pixels = back_buffer->pixels;
|
nuclear@0
|
93 back_buffer->pixels = tmp;
|
nuclear@0
|
94 } else {
|
nuclear@0
|
95 /*dma_copy32(3, front_buffer->pixels, back_buffer->pixels, (xres * yres) >> 1);*/
|
nuclear@0
|
96 dma_copy32(3, front_buffer->pixels, back_buffer->pixels, 19200);
|
nuclear@0
|
97 }
|
nuclear@0
|
98 }
|
nuclear@0
|
99
|
nuclear@0
|
100 /* ------- pixel buffer operations ------- */
|
nuclear@0
|
101
|
nuclear@0
|
102 struct pixel_buffer *create_pixel_buffer(int x, int y, int bpp) {
|
nuclear@0
|
103 struct pixel_buffer *pbuf = malloc(sizeof(struct pixel_buffer));
|
nuclear@0
|
104 if(pbuf) {
|
nuclear@0
|
105 pbuf->pixels = malloc(x * y * bpp / 8);
|
nuclear@0
|
106 pbuf->x = x;
|
nuclear@0
|
107 pbuf->y = y;
|
nuclear@0
|
108 pbuf->bpp = bpp;
|
nuclear@0
|
109 }
|
nuclear@0
|
110 return pbuf;
|
nuclear@0
|
111 }
|
nuclear@0
|
112
|
nuclear@0
|
113 void destroy_pixel_buffer(struct pixel_buffer *pbuf) {
|
nuclear@0
|
114 free(pbuf->pixels);
|
nuclear@0
|
115 free(pbuf);
|
nuclear@0
|
116 }
|
nuclear@0
|
117
|
nuclear@0
|
118 void clear_buffer(struct pixel_buffer *pbuf, unsigned short color) {
|
nuclear@0
|
119 int sz = pbuf->x * pbuf->y;
|
nuclear@0
|
120
|
nuclear@0
|
121 if(pbuf->bpp == 8) {
|
nuclear@0
|
122 color |= color << 8;
|
nuclear@0
|
123 sz >>= 1;
|
nuclear@0
|
124 }
|
nuclear@1
|
125
|
nuclear@0
|
126 dma_fill16(3, pbuf->pixels, color, sz);
|
nuclear@0
|
127 }
|
nuclear@0
|
128
|
nuclear@0
|
129 void copy_buffer(const struct pixel_buffer *src, struct pixel_buffer *dst) {
|
nuclear@0
|
130 int words;
|
nuclear@1
|
131
|
nuclear@0
|
132 if(src->x != dst->x || src->y != dst->y || src->bpp != dst->bpp) return;
|
nuclear@0
|
133
|
nuclear@0
|
134 words = (src->x * src->y) >> (src->bpp == 16 ? 1 : 2);
|
nuclear@0
|
135 dma_copy32(3, dst->pixels, src->pixels, words);
|
nuclear@0
|
136 }
|
nuclear@0
|
137
|
nuclear@3
|
138 #define MIN(a, b) ((a) < (b) ? (a) : (b))
|
nuclear@3
|
139
|
nuclear@3
|
140 void blit(struct pixel_buffer *src, int src_x, int src_y, int src_w, int src_h,
|
nuclear@3
|
141 struct pixel_buffer *dst, int dst_x, int dst_y)
|
nuclear@3
|
142 {
|
nuclear@3
|
143 int i, pixsize, width, height, dstride, sstride;
|
nuclear@3
|
144 unsigned char *dptr, *sptr;
|
nuclear@3
|
145
|
nuclear@3
|
146 if(dst->bpp != src->bpp)
|
nuclear@3
|
147 return;
|
nuclear@3
|
148
|
nuclear@3
|
149 if(src_w <= 0)
|
nuclear@3
|
150 src_w = src->x;
|
nuclear@3
|
151 if(src_h <= 0)
|
nuclear@3
|
152 src_h = src->y;
|
nuclear@3
|
153
|
nuclear@3
|
154 width = MIN(src_w, MIN(src->x - src_x, dst->x - dst_x));
|
nuclear@3
|
155 height = MIN(src_h, MIN(src->y - src_y, dst->y - dst_y));
|
nuclear@3
|
156
|
nuclear@3
|
157 if(width <= 0 || height <= 0)
|
nuclear@3
|
158 return;
|
nuclear@3
|
159
|
nuclear@3
|
160 pixsize = dst->bpp / 8;
|
nuclear@3
|
161 dptr = (unsigned char*)dst->pixels + (dst_y * dst->x + dst_x) * pixsize;
|
nuclear@3
|
162 sptr = (unsigned char*)src->pixels + (src_y * src->x + src_x) * pixsize;
|
nuclear@3
|
163
|
nuclear@3
|
164 dstride = dst->x * pixsize;
|
nuclear@3
|
165 sstride = src->x * pixsize;
|
nuclear@3
|
166
|
nuclear@3
|
167 for(i=0; i<height; i++) {
|
nuclear@3
|
168 memcpy(dptr, sptr, width * pixsize);
|
nuclear@3
|
169 sptr += sstride;
|
nuclear@3
|
170 dptr += dstride;
|
nuclear@3
|
171 }
|
nuclear@3
|
172 }
|
nuclear@3
|
173
|
nuclear@0
|
174
|
nuclear@0
|
175 void draw_line(int x1, int y1, int x2, int y2, unsigned short col, struct pixel_buffer *pbuf) {
|
nuclear@0
|
176 int dx, dy, dx2, dy2;
|
nuclear@0
|
177 int x_inc, y_inc;
|
nuclear@0
|
178 int error;
|
nuclear@0
|
179 int i;
|
nuclear@0
|
180 unsigned short *ptr = pbuf->pixels;
|
nuclear@0
|
181
|
nuclear@0
|
182 ptr += y1 * pbuf->x + x1;
|
nuclear@0
|
183 dx = x2 - x1;
|
nuclear@0
|
184 dy = y2 - y1;
|
nuclear@1
|
185
|
nuclear@0
|
186 if(dx >= 0) {
|
nuclear@0
|
187 x_inc = 1;
|
nuclear@0
|
188 } else {
|
nuclear@0
|
189 x_inc = -1;
|
nuclear@0
|
190 dx = -dx;
|
nuclear@0
|
191 }
|
nuclear@1
|
192
|
nuclear@0
|
193 if(dy >= 0) {
|
nuclear@0
|
194 y_inc = pbuf->x;
|
nuclear@0
|
195 } else {
|
nuclear@0
|
196 y_inc = -pbuf->x;
|
nuclear@0
|
197 dy = -dy;
|
nuclear@0
|
198 }
|
nuclear@1
|
199
|
nuclear@0
|
200 dx2 = dx << 1;
|
nuclear@0
|
201 dy2 = dy << 1;
|
nuclear@0
|
202
|
nuclear@0
|
203 if(dx > dy) {
|
nuclear@0
|
204 error = dy2 - dx;
|
nuclear@0
|
205 for(i=0; i<=dx; i++) {
|
nuclear@0
|
206 *ptr = col;
|
nuclear@0
|
207 if(error >= 0) {
|
nuclear@0
|
208 error -= dx2;
|
nuclear@0
|
209 ptr += y_inc;
|
nuclear@0
|
210 }
|
nuclear@0
|
211 error += dy2;
|
nuclear@0
|
212 ptr += x_inc;
|
nuclear@0
|
213 }
|
nuclear@0
|
214 } else {
|
nuclear@0
|
215 error = dx2 - dy;
|
nuclear@0
|
216 for(i=0;i<=dy;i++) {
|
nuclear@0
|
217 *ptr = col;
|
nuclear@0
|
218 if(error >= 0) {
|
nuclear@0
|
219 error -= dy2;
|
nuclear@0
|
220 ptr += x_inc;
|
nuclear@0
|
221 }
|
nuclear@0
|
222 error += dx2;
|
nuclear@0
|
223 ptr += y_inc;
|
nuclear@0
|
224 }
|
nuclear@0
|
225 }
|
nuclear@0
|
226 }
|