amiga_imgv

view src/amiga/gfx.c @ 7:4c36d0f44aa6

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