gbasys

annotate src/gfx.c @ 2:e3dc7705ad9c

communications stuff
author John Tsiombikas <nuclear@member.fsf.org>
date Wed, 07 Mar 2012 06:11:51 +0200
parents 875ef6085efc
children 06726f0b8cd3
rev   line source
nuclear@0 1 /*
nuclear@0 2 Copyright 2004 John Tsiombikas <nuclear@siggraph.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@0 24 #include "gfx.h"
nuclear@0 25
nuclear@0 26 #define FRAME_SEL_BIT 0x10
nuclear@0 27
nuclear@0 28 #define H_BLANK_OAM 0x20
nuclear@0 29 #define OBJ_MAP_2D 0x0
nuclear@0 30 #define OBJ_MAP_1D 0x40
nuclear@0 31 #define FORCE_BLANK 0x80
nuclear@0 32 #define BG0_ENABLE 0x100
nuclear@0 33 #define BG1_ENABLE 0x200
nuclear@0 34 #define BG2_ENABLE 0x400
nuclear@0 35 #define BG3_ENABLE 0x800
nuclear@0 36
nuclear@0 37 static volatile unsigned short *reg_disp_ctl = (void*)0x4000000;
nuclear@0 38 static volatile unsigned short *reg_vcount = (void*)0x4000006;
nuclear@0 39
nuclear@0 40 static int xres, yres;
nuclear@0 41 static int sizeof_pixel;
nuclear@0 42 static int page_flipping;
nuclear@0 43 static int allocated_back_buffer;
nuclear@0 44
nuclear@0 45 static struct pixel_buffer fbuf, bbuf;
nuclear@0 46 struct pixel_buffer *front_buffer = &fbuf;
nuclear@0 47 struct pixel_buffer *back_buffer = &bbuf;
nuclear@0 48
nuclear@0 49 #define show_page(n) ((n) ? (*reg_disp_ctl |= FRAME_SEL_BIT) : (*reg_disp_ctl &= ~FRAME_SEL_BIT))
nuclear@0 50 #define swap_page() (*reg_disp_ctl ^= FRAME_SEL_BIT)
nuclear@0 51
nuclear@0 52 int set_video_mode(int mode, int double_buffering) {
nuclear@0 53 if(mode < 3 || mode > 5) return -1;
nuclear@0 54
nuclear@0 55 /* mode 5: 160x128, otherwise: 240x160 */
nuclear@0 56 xres = (mode == 5) ? 160 : 240;
nuclear@0 57 yres = (mode == 5) ? 128 : 160;
nuclear@0 58
nuclear@0 59 sizeof_pixel = (mode == 4) ? 1 : 2;
nuclear@0 60
nuclear@0 61 *reg_disp_ctl = mode | BG2_ENABLE;
nuclear@0 62
nuclear@0 63 show_page(0);
nuclear@0 64
nuclear@0 65 if(allocated_back_buffer) {
nuclear@0 66 free(back_buffer->pixels);
nuclear@0 67 }
nuclear@0 68
nuclear@0 69 front_buffer->pixels = (void*)0x6000000;
nuclear@0 70 front_buffer->x = back_buffer->x = xres;
nuclear@0 71 front_buffer->y = back_buffer->y = yres;
nuclear@0 72 front_buffer->bpp = back_buffer->bpp = sizeof_pixel * 8;
nuclear@1 73
nuclear@0 74 if(mode > 3) {
nuclear@0 75 page_flipping = 1;
nuclear@0 76 back_buffer->pixels = (void*)0x600a000;
nuclear@0 77 } else {
nuclear@0 78 page_flipping = 0;
nuclear@0 79 if(double_buffering) {
nuclear@0 80 back_buffer->pixels = malloc(xres * yres * sizeof_pixel);
nuclear@0 81 }
nuclear@0 82 }
nuclear@0 83 }
nuclear@0 84
nuclear@0 85 void flip(void) {
nuclear@0 86 static void *tmp;
nuclear@1 87
nuclear@0 88 if(page_flipping) {
nuclear@0 89 swap_page();
nuclear@0 90 tmp = front_buffer->pixels;
nuclear@0 91 front_buffer->pixels = back_buffer->pixels;
nuclear@0 92 back_buffer->pixels = tmp;
nuclear@0 93 } else {
nuclear@0 94 /*dma_copy32(3, front_buffer->pixels, back_buffer->pixels, (xres * yres) >> 1);*/
nuclear@0 95 dma_copy32(3, front_buffer->pixels, back_buffer->pixels, 19200);
nuclear@0 96 }
nuclear@0 97 }
nuclear@0 98
nuclear@0 99 /* ------- pixel buffer operations ------- */
nuclear@0 100
nuclear@0 101 struct pixel_buffer *create_pixel_buffer(int x, int y, int bpp) {
nuclear@0 102 struct pixel_buffer *pbuf = malloc(sizeof(struct pixel_buffer));
nuclear@0 103 if(pbuf) {
nuclear@0 104 pbuf->pixels = malloc(x * y * bpp / 8);
nuclear@0 105 pbuf->x = x;
nuclear@0 106 pbuf->y = y;
nuclear@0 107 pbuf->bpp = bpp;
nuclear@0 108 }
nuclear@0 109 return pbuf;
nuclear@0 110 }
nuclear@0 111
nuclear@0 112 void destroy_pixel_buffer(struct pixel_buffer *pbuf) {
nuclear@0 113 free(pbuf->pixels);
nuclear@0 114 free(pbuf);
nuclear@0 115 }
nuclear@0 116
nuclear@0 117 void clear_buffer(struct pixel_buffer *pbuf, unsigned short color) {
nuclear@0 118 int sz = pbuf->x * pbuf->y;
nuclear@0 119
nuclear@0 120 if(pbuf->bpp == 8) {
nuclear@0 121 color |= color << 8;
nuclear@0 122 sz >>= 1;
nuclear@0 123 }
nuclear@1 124
nuclear@0 125 dma_fill16(3, pbuf->pixels, color, sz);
nuclear@0 126 }
nuclear@0 127
nuclear@0 128 void copy_buffer(const struct pixel_buffer *src, struct pixel_buffer *dst) {
nuclear@0 129 int words;
nuclear@1 130
nuclear@0 131 if(src->x != dst->x || src->y != dst->y || src->bpp != dst->bpp) return;
nuclear@0 132
nuclear@0 133 words = (src->x * src->y) >> (src->bpp == 16 ? 1 : 2);
nuclear@0 134 dma_copy32(3, dst->pixels, src->pixels, words);
nuclear@0 135 }
nuclear@0 136
nuclear@0 137
nuclear@0 138 void draw_line(int x1, int y1, int x2, int y2, unsigned short col, struct pixel_buffer *pbuf) {
nuclear@0 139 int dx, dy, dx2, dy2;
nuclear@0 140 int x_inc, y_inc;
nuclear@0 141 int error;
nuclear@0 142 int i;
nuclear@0 143 unsigned short *ptr = pbuf->pixels;
nuclear@0 144
nuclear@0 145 ptr += y1 * pbuf->x + x1;
nuclear@0 146 dx = x2 - x1;
nuclear@0 147 dy = y2 - y1;
nuclear@1 148
nuclear@0 149 if(dx >= 0) {
nuclear@0 150 x_inc = 1;
nuclear@0 151 } else {
nuclear@0 152 x_inc = -1;
nuclear@0 153 dx = -dx;
nuclear@0 154 }
nuclear@1 155
nuclear@0 156 if(dy >= 0) {
nuclear@0 157 y_inc = pbuf->x;
nuclear@0 158 } else {
nuclear@0 159 y_inc = -pbuf->x;
nuclear@0 160 dy = -dy;
nuclear@0 161 }
nuclear@1 162
nuclear@0 163 dx2 = dx << 1;
nuclear@0 164 dy2 = dy << 1;
nuclear@0 165
nuclear@0 166 if(dx > dy) {
nuclear@0 167 error = dy2 - dx;
nuclear@0 168 for(i=0; i<=dx; i++) {
nuclear@0 169 *ptr = col;
nuclear@0 170 if(error >= 0) {
nuclear@0 171 error -= dx2;
nuclear@0 172 ptr += y_inc;
nuclear@0 173 }
nuclear@0 174 error += dy2;
nuclear@0 175 ptr += x_inc;
nuclear@0 176 }
nuclear@0 177 } else {
nuclear@0 178 error = dx2 - dy;
nuclear@0 179 for(i=0;i<=dy;i++) {
nuclear@0 180 *ptr = col;
nuclear@0 181 if(error >= 0) {
nuclear@0 182 error -= dy2;
nuclear@0 183 ptr += x_inc;
nuclear@0 184 }
nuclear@0 185 error += dx2;
nuclear@0 186 ptr += y_inc;
nuclear@0 187 }
nuclear@0 188 }
nuclear@0 189 }