gbasys
diff 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 diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/gfx.c Sun Mar 04 04:04:25 2012 +0200 1.3 @@ -0,0 +1,189 @@ 1.4 +/* 1.5 +Copyright 2004 John Tsiombikas <nuclear@siggraph.org> 1.6 + 1.7 +This file is part of libgba, a library for GameBoy Advance development. 1.8 + 1.9 +This program is free software; you can redistribute it and/or modify 1.10 +it under the terms of the GNU General Public License as published by 1.11 +the Free Software Foundation; either version 2 of the License, or 1.12 +(at your option) any later version. 1.13 + 1.14 +This program is distributed in the hope that it will be useful, 1.15 +but WITHOUT ANY WARRANTY; without even the implied warranty of 1.16 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1.17 +GNU General Public License for more details. 1.18 + 1.19 +You should have received a copy of the GNU General Public License 1.20 +along with this program; if not, write to the Free Software 1.21 +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 1.22 +*/ 1.23 + 1.24 +#include "libgba_config.h" 1.25 + 1.26 +#include <stdlib.h> 1.27 +#include "gfx.h" 1.28 + 1.29 +#define FRAME_SEL_BIT 0x10 1.30 + 1.31 +#define H_BLANK_OAM 0x20 1.32 +#define OBJ_MAP_2D 0x0 1.33 +#define OBJ_MAP_1D 0x40 1.34 +#define FORCE_BLANK 0x80 1.35 +#define BG0_ENABLE 0x100 1.36 +#define BG1_ENABLE 0x200 1.37 +#define BG2_ENABLE 0x400 1.38 +#define BG3_ENABLE 0x800 1.39 + 1.40 +static volatile unsigned short *reg_disp_ctl = (void*)0x4000000; 1.41 +static volatile unsigned short *reg_vcount = (void*)0x4000006; 1.42 + 1.43 +static int xres, yres; 1.44 +static int sizeof_pixel; 1.45 +static int page_flipping; 1.46 +static int allocated_back_buffer; 1.47 + 1.48 +static struct pixel_buffer fbuf, bbuf; 1.49 +struct pixel_buffer *front_buffer = &fbuf; 1.50 +struct pixel_buffer *back_buffer = &bbuf; 1.51 + 1.52 +#define show_page(n) ((n) ? (*reg_disp_ctl |= FRAME_SEL_BIT) : (*reg_disp_ctl &= ~FRAME_SEL_BIT)) 1.53 +#define swap_page() (*reg_disp_ctl ^= FRAME_SEL_BIT) 1.54 + 1.55 +int set_video_mode(int mode, int double_buffering) { 1.56 + if(mode < 3 || mode > 5) return -1; 1.57 + 1.58 + /* mode 5: 160x128, otherwise: 240x160 */ 1.59 + xres = (mode == 5) ? 160 : 240; 1.60 + yres = (mode == 5) ? 128 : 160; 1.61 + 1.62 + sizeof_pixel = (mode == 4) ? 1 : 2; 1.63 + 1.64 + *reg_disp_ctl = mode | BG2_ENABLE; 1.65 + 1.66 + show_page(0); 1.67 + 1.68 + if(allocated_back_buffer) { 1.69 + free(back_buffer->pixels); 1.70 + } 1.71 + 1.72 + front_buffer->pixels = (void*)0x6000000; 1.73 + front_buffer->x = back_buffer->x = xres; 1.74 + front_buffer->y = back_buffer->y = yres; 1.75 + front_buffer->bpp = back_buffer->bpp = sizeof_pixel * 8; 1.76 + 1.77 + if(mode > 3) { 1.78 + page_flipping = 1; 1.79 + back_buffer->pixels = (void*)0x600a000; 1.80 + } else { 1.81 + page_flipping = 0; 1.82 + if(double_buffering) { 1.83 + back_buffer->pixels = malloc(xres * yres * sizeof_pixel); 1.84 + } 1.85 + } 1.86 +} 1.87 + 1.88 +void flip(void) { 1.89 + static void *tmp; 1.90 + 1.91 + if(page_flipping) { 1.92 + swap_page(); 1.93 + tmp = front_buffer->pixels; 1.94 + front_buffer->pixels = back_buffer->pixels; 1.95 + back_buffer->pixels = tmp; 1.96 + } else { 1.97 + /*dma_copy32(3, front_buffer->pixels, back_buffer->pixels, (xres * yres) >> 1);*/ 1.98 + dma_copy32(3, front_buffer->pixels, back_buffer->pixels, 19200); 1.99 + } 1.100 +} 1.101 + 1.102 +/* ------- pixel buffer operations ------- */ 1.103 + 1.104 +struct pixel_buffer *create_pixel_buffer(int x, int y, int bpp) { 1.105 + struct pixel_buffer *pbuf = malloc(sizeof(struct pixel_buffer)); 1.106 + if(pbuf) { 1.107 + pbuf->pixels = malloc(x * y * bpp / 8); 1.108 + pbuf->x = x; 1.109 + pbuf->y = y; 1.110 + pbuf->bpp = bpp; 1.111 + } 1.112 + return pbuf; 1.113 +} 1.114 + 1.115 +void destroy_pixel_buffer(struct pixel_buffer *pbuf) { 1.116 + free(pbuf->pixels); 1.117 + free(pbuf); 1.118 +} 1.119 + 1.120 +void clear_buffer(struct pixel_buffer *pbuf, unsigned short color) { 1.121 + int sz = pbuf->x * pbuf->y; 1.122 + 1.123 + if(pbuf->bpp == 8) { 1.124 + color |= color << 8; 1.125 + sz >>= 1; 1.126 + } 1.127 + 1.128 + dma_fill16(3, pbuf->pixels, color, sz); 1.129 +} 1.130 + 1.131 +void copy_buffer(const struct pixel_buffer *src, struct pixel_buffer *dst) { 1.132 + int words; 1.133 + 1.134 + if(src->x != dst->x || src->y != dst->y || src->bpp != dst->bpp) return; 1.135 + 1.136 + words = (src->x * src->y) >> (src->bpp == 16 ? 1 : 2); 1.137 + dma_copy32(3, dst->pixels, src->pixels, words); 1.138 +} 1.139 + 1.140 + 1.141 +void draw_line(int x1, int y1, int x2, int y2, unsigned short col, struct pixel_buffer *pbuf) { 1.142 + int dx, dy, dx2, dy2; 1.143 + int x_inc, y_inc; 1.144 + int error; 1.145 + int i; 1.146 + unsigned short *ptr = pbuf->pixels; 1.147 + 1.148 + ptr += y1 * pbuf->x + x1; 1.149 + dx = x2 - x1; 1.150 + dy = y2 - y1; 1.151 + 1.152 + if(dx >= 0) { 1.153 + x_inc = 1; 1.154 + } else { 1.155 + x_inc = -1; 1.156 + dx = -dx; 1.157 + } 1.158 + 1.159 + if(dy >= 0) { 1.160 + y_inc = pbuf->x; 1.161 + } else { 1.162 + y_inc = -pbuf->x; 1.163 + dy = -dy; 1.164 + } 1.165 + 1.166 + dx2 = dx << 1; 1.167 + dy2 = dy << 1; 1.168 + 1.169 + if(dx > dy) { 1.170 + error = dy2 - dx; 1.171 + for(i=0; i<=dx; i++) { 1.172 + *ptr = col; 1.173 + if(error >= 0) { 1.174 + error -= dx2; 1.175 + ptr += y_inc; 1.176 + } 1.177 + error += dy2; 1.178 + ptr += x_inc; 1.179 + } 1.180 + } else { 1.181 + error = dx2 - dy; 1.182 + for(i=0;i<=dy;i++) { 1.183 + *ptr = col; 1.184 + if(error >= 0) { 1.185 + error -= dy2; 1.186 + ptr += x_inc; 1.187 + } 1.188 + error += dx2; 1.189 + ptr += y_inc; 1.190 + } 1.191 + } 1.192 +}