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 +}