amiga_imgv

annotate src/amiga/gfx.c @ 9:01bd8bbc46d4

foo
author John Tsiombikas <nuclear@member.fsf.org>
date Sun, 29 Oct 2017 21:56:28 +0200
parents 0d3d7b020e6a
children 3d9aaefb8ba6
rev   line source
nuclear@0 1 #include <stdio.h>
nuclear@6 2 #include <assert.h>
nuclear@0 3 #include <proto/exec.h>
nuclear@0 4 #include "gfx.h"
nuclear@0 5 #include "copper.h"
nuclear@0 6 #include "hwregs.h"
nuclear@0 7 #include "logger.h"
nuclear@4 8 #include "image.h"
nuclear@0 9
nuclear@0 10 static int scr_width, scr_height;
nuclear@0 11 static int fb_width, fb_height;
nuclear@0 12 static int num_bitplanes;
nuclear@0 13 static uint16_t prev_intena, prev_intreq, prev_adkcon, prev_dmacon;
nuclear@0 14
nuclear@0 15 static unsigned char *framebuf;
nuclear@0 16 static unsigned long fbsize;
nuclear@0 17 static int own_framebuf;
nuclear@0 18
nuclear@0 19 int gfx_init(int nbpl, unsigned int flags)
nuclear@0 20 {
nuclear@0 21 uint16_t bplcon0;
nuclear@0 22
nuclear@0 23 num_bitplanes = nbpl;
nuclear@0 24 scr_width = fb_width = (flags & GFX_HIRES) ? 640 : 320;
nuclear@0 25 scr_height = fb_height = (flags & GFX_ILACE) ? 512 : 256;
nuclear@0 26
nuclear@0 27 Forbid();
nuclear@0 28
nuclear@0 29 prev_dmacon = REG_DMACONR;
nuclear@0 30 REG_DMACON = CLRBITS(DMA_ALL);
nuclear@0 31
nuclear@0 32 prev_intena = REG_INTENAR;
nuclear@0 33 prev_intreq = REG_INTREQR;
nuclear@0 34 prev_adkcon = REG_ADKCONR;
nuclear@0 35
nuclear@6 36 if(init_copper(1400, 0) == -1) {
nuclear@0 37 return -1;
nuclear@0 38 }
nuclear@0 39
nuclear@0 40 if(!gfx_set_framebuffer(0, scr_width, scr_height)) {
nuclear@0 41 gfx_shutdown();
nuclear@0 42 return -1;
nuclear@0 43 }
nuclear@0 44
nuclear@0 45 bplcon0 = BPLCON0_COUNT(nbpl) | BPLCON0_COLOR;
nuclear@0 46 if(flags & GFX_HIRES) bplcon0 |= BPLCON0_HIRES;
nuclear@0 47 if(flags & GFX_ILACE) bplcon0 |= BPLCON0_LACE;
nuclear@0 48 if(flags & GFX_HAM) bplcon0 |= BPLCON0_HOMOD;
nuclear@0 49 if(flags & GFX_DBLPF) bplcon0 |= BPLCON0_DBLPF;
nuclear@0 50
nuclear@0 51 REG_BPLCON0 = bplcon0;
nuclear@0 52 REG_BPLCON1 = 0; /* h-scroll */
nuclear@0 53 REG_DIWSTART = 0x2c81; /* 81h horiz start, 2ch vertical start */
nuclear@0 54 REG_DIWSTOP = 0x2cc1;
nuclear@0 55 REG_DDFSTART = (flags & GFX_HIRES) ? 0x3c : 0x38;
nuclear@0 56 REG_DDFSTOP = (flags & GFX_HIRES) ? 0xd4 : 0xd0;
nuclear@0 57
nuclear@0 58 gfx_wait_vblank();
nuclear@0 59 gfx_begin_copperlist();
nuclear@0 60 add_copper(COPPER_END);
nuclear@0 61
nuclear@3 62 logmsg("starting DMA\n");
nuclear@0 63 REG_DMACON = SETBITS(DMA_BPL | DMA_COPPER | DMA_MASTER);
nuclear@0 64 return 0;
nuclear@0 65 }
nuclear@0 66
nuclear@0 67 void gfx_shutdown(void)
nuclear@0 68 {
nuclear@0 69 REG_DMACON = CLRBITS(DMA_ALL);
nuclear@0 70 REG_DMACON = SETBITS(prev_dmacon);
nuclear@0 71
nuclear@0 72 REG_INTREQ = CLRBITS(0x7fff);
nuclear@0 73 REG_INTREQ = SETBITS(prev_intreq);
nuclear@0 74
nuclear@0 75 REG_ADKCON = CLRBITS(0x7fff);
nuclear@0 76 REG_ADKCON = SETBITS(prev_adkcon);
nuclear@0 77
nuclear@0 78 REG_INTENA = CLRBITS(INTEN_ALL);
nuclear@0 79 REG_INTENA = SETBITS(prev_intena);
nuclear@0 80
nuclear@0 81 if(framebuf && own_framebuf) {
nuclear@0 82 FreeMem(framebuf, fbsize);
nuclear@0 83 }
nuclear@0 84 framebuf = 0;
nuclear@0 85
nuclear@0 86 cleanup_copper();
nuclear@0 87 Permit();
nuclear@0 88 }
nuclear@0 89
nuclear@0 90 int gfx_screen_width(void)
nuclear@0 91 {
nuclear@0 92 return scr_width;
nuclear@0 93 }
nuclear@0 94
nuclear@0 95 int gfx_screen_height(void)
nuclear@0 96 {
nuclear@0 97 return scr_height;
nuclear@0 98 }
nuclear@0 99
nuclear@0 100 void *gfx_set_framebuffer(void *fb, int width, int height)
nuclear@0 101 {
nuclear@0 102 /*unsigned int bpl_scanline_sz = width / 8;*/
nuclear@0 103 unsigned long sz = width * height / 8 * num_bitplanes;
nuclear@0 104 uint32_t bpladdr;
nuclear@0 105 uint16_t bplmod;
nuclear@0 106
nuclear@0 107 if(framebuf && own_framebuf) {
nuclear@0 108 FreeMem(framebuf, fbsize);
nuclear@0 109 }
nuclear@0 110
nuclear@0 111 if(fb) {
nuclear@0 112 framebuf = fb;
nuclear@0 113 own_framebuf = 0;
nuclear@0 114 } else {
nuclear@0 115 if(!(framebuf = AllocMem(sz, MEMF_CHIP))) {
nuclear@0 116 logmsg("gfx_set_framebuffer failed to allocate %lu bytes of chip mem for framebuffer\n", sz);
nuclear@0 117 return 0;
nuclear@0 118 }
nuclear@0 119 own_framebuf = 1;
nuclear@0 120 }
nuclear@0 121
nuclear@0 122 fb_width = width;
nuclear@0 123 fb_height = height;
nuclear@0 124 fbsize = sz;
nuclear@0 125
nuclear@0 126 bpladdr = (uint32_t)framebuf;
nuclear@0 127 logmsg("bitplane address: %lx\n", (unsigned long)bpladdr);
nuclear@0 128
nuclear@4 129 bplmod = (fb_width - scr_width) / 8 + fb_width / 8 * (num_bitplanes - 1);
nuclear@0 130 REG_BPL1MOD = bplmod;
nuclear@0 131 REG_BPL2MOD = bplmod;
nuclear@0 132
nuclear@0 133 /*
nuclear@0 134 REG32_BPL1PT = bpladdr; bpladdr += bpl_scanline_sz;
nuclear@0 135 REG32_BPL2PT = bpladdr; bpladdr += bpl_scanline_sz;
nuclear@0 136 REG32_BPL3PT = bpladdr; bpladdr += bpl_scanline_sz;
nuclear@0 137 REG32_BPL4PT = bpladdr; bpladdr += bpl_scanline_sz;
nuclear@0 138 REG32_BPL5PT = bpladdr; bpladdr += bpl_scanline_sz;
nuclear@0 139 REG32_BPL6PT = bpladdr;
nuclear@0 140 */
nuclear@0 141 return framebuf;
nuclear@0 142 }
nuclear@0 143
nuclear@0 144 void *gfx_get_framebuffer(void)
nuclear@0 145 {
nuclear@0 146 return framebuf;
nuclear@0 147 }
nuclear@0 148
nuclear@0 149 int gfx_framebuffer_width(void)
nuclear@0 150 {
nuclear@0 151 return fb_width;
nuclear@0 152 }
nuclear@0 153
nuclear@0 154 int gfx_framebuffer_height(void)
nuclear@0 155 {
nuclear@0 156 return fb_height;
nuclear@0 157 }
nuclear@0 158
nuclear@0 159 void gfx_begin_copperlist(void)
nuclear@0 160 {
nuclear@0 161 static const uint16_t bplptr[] = {
nuclear@0 162 REGN_BPL1PTH, REGN_BPL2PTH, REGN_BPL3PTH, REGN_BPL4PTH, REGN_BPL5PTH, REGN_BPL6PTH
nuclear@0 163 };
nuclear@0 164 int i;
nuclear@0 165 uint32_t bpladdr;
nuclear@0 166 bpladdr = (uint32_t)framebuf;
nuclear@0 167
nuclear@0 168 for(i=0; i<num_bitplanes; i++) {
nuclear@0 169 add_copper(COPPER_MOVE(bplptr[i], bpladdr >> 16));
nuclear@0 170 add_copper(COPPER_MOVE(bplptr[i] + 2, bpladdr));
nuclear@5 171 bpladdr += fb_width / 8;
nuclear@0 172 }
nuclear@0 173 }
nuclear@0 174
nuclear@0 175 static int mouse_bnstate(void)
nuclear@0 176 {
nuclear@0 177 return (REG_CIAA_PORTA & CIAA_PA_FIR0) ? 0 : 1;
nuclear@0 178 }
nuclear@0 179
nuclear@0 180 int gfx_next_event(union gfx_event *ev, int block)
nuclear@0 181 {
nuclear@0 182 /* TODO */
nuclear@0 183 if(block) {
nuclear@0 184 while(!mouse_bnstate());
nuclear@0 185 ev->type = GFX_EV_QUIT;
nuclear@0 186 return 1;
nuclear@0 187 }
nuclear@0 188
nuclear@0 189 if(mouse_bnstate()) {
nuclear@0 190 ev->type = GFX_EV_QUIT;
nuclear@0 191 return 1;
nuclear@0 192 }
nuclear@0 193
nuclear@0 194 return 0;
nuclear@0 195 }
nuclear@0 196
nuclear@0 197 void gfx_wait_vpos(int x)
nuclear@0 198 {
nuclear@0 199 x <<= 8;
nuclear@0 200 while((REG32_VPOSR & 0x1ff00) < x);
nuclear@0 201 }
nuclear@0 202
nuclear@0 203 void gfx_wait_vblank(void)
nuclear@0 204 {
nuclear@0 205 gfx_wait_vpos(300);
nuclear@0 206 }
nuclear@3 207
nuclear@3 208 void gfx_show_image(struct ham_image *img)
nuclear@3 209 {
nuclear@4 210 int i, j, k, fbwidth, fbheight, ncolors, prev_line;
nuclear@4 211 unsigned char *fbptr = gfx_get_framebuffer();
nuclear@4 212 struct palchange *chg = img->chglist;
nuclear@4 213
nuclear@4 214 fbwidth = gfx_framebuffer_width();
nuclear@4 215 fbheight = gfx_framebuffer_height();
nuclear@4 216
nuclear@4 217 logmsg("showing ham image %dx%d\n", fbwidth, fbheight);
nuclear@4 218
nuclear@4 219 memcpy(fbptr, img->pixels, fbwidth * fbheight / 8 * num_bitplanes);
nuclear@4 220
nuclear@4 221 /* create copper list that handles the palette */
nuclear@4 222 clear_copper();
nuclear@4 223 gfx_begin_copperlist();
nuclear@4 224 /* initial palette at the start of frame */
nuclear@4 225 for(i=0; i<16; i++) {
nuclear@4 226 add_copper(COPPER_MOVE(REGN_COLOR(i), img->palette[i]));
nuclear@4 227 logmsg("copper palette[%d]: %x\n", i, (unsigned int)img->palette[i]);
nuclear@4 228 }
nuclear@4 229 /* add copper instructions for palette changes according to the image changelist */
nuclear@4 230 prev_line = -1;
nuclear@4 231 while(chg) {
nuclear@4 232 assert(chg->line >= prev_line);
nuclear@4 233 if(chg->line != prev_line) {
nuclear@6 234 if(chg->line > 255 && prev_line < 255) {
nuclear@6 235 add_copper(COPPER_VWAIT(255));
nuclear@6 236 }
nuclear@4 237 prev_line = chg->line;
nuclear@4 238 add_copper(COPPER_VWAIT(chg->line));
nuclear@4 239 }
nuclear@4 240 add_copper(COPPER_MOVE(REGN_COLOR(chg->entry >> 12), chg->entry & 0xfff));
nuclear@6 241 chg = chg->next;
nuclear@4 242 }
nuclear@4 243 add_copper(COPPER_END);
nuclear@3 244 }