rev |
line source |
nuclear@0
|
1 #include <stdio.h>
|
nuclear@11
|
2 #include <stdlib.h>
|
nuclear@6
|
3 #include <assert.h>
|
nuclear@0
|
4 #include <proto/exec.h>
|
nuclear@11
|
5 #include <exec/interrupts.h>
|
nuclear@0
|
6 #include "gfx.h"
|
nuclear@0
|
7 #include "copper.h"
|
nuclear@0
|
8 #include "hwregs.h"
|
nuclear@0
|
9 #include "logger.h"
|
nuclear@4
|
10 #include "image.h"
|
nuclear@0
|
11
|
nuclear@0
|
12 static int scr_width, scr_height;
|
nuclear@0
|
13 static int fb_width, fb_height;
|
nuclear@0
|
14 static int num_bitplanes;
|
nuclear@11
|
15 static unsigned int init_flags;
|
nuclear@11
|
16 /* updated by vblank_intr to indicate the current field in interlaced mode */
|
nuclear@11
|
17 static unsigned short scr_field;
|
nuclear@11
|
18 static uint32_t *coplist_bplptr[6];
|
nuclear@11
|
19
|
nuclear@0
|
20 static uint16_t prev_intena, prev_intreq, prev_adkcon, prev_dmacon;
|
nuclear@0
|
21
|
nuclear@0
|
22 static unsigned char *framebuf;
|
nuclear@0
|
23 static unsigned long fbsize;
|
nuclear@0
|
24 static int own_framebuf;
|
nuclear@0
|
25
|
nuclear@11
|
26 static unsigned int short_fields, long_fields;
|
nuclear@11
|
27
|
nuclear@11
|
28 static struct Interrupt *vbint;
|
nuclear@11
|
29
|
nuclear@11
|
30 static __amigainterrupt void vblank_intr();
|
nuclear@11
|
31
|
nuclear@0
|
32 int gfx_init(int nbpl, unsigned int flags)
|
nuclear@0
|
33 {
|
nuclear@0
|
34 uint16_t bplcon0;
|
nuclear@0
|
35
|
nuclear@11
|
36 init_flags = flags;
|
nuclear@0
|
37 num_bitplanes = nbpl;
|
nuclear@0
|
38 scr_width = fb_width = (flags & GFX_HIRES) ? 640 : 320;
|
nuclear@0
|
39 scr_height = fb_height = (flags & GFX_ILACE) ? 512 : 256;
|
nuclear@0
|
40
|
nuclear@0
|
41 Forbid();
|
nuclear@0
|
42
|
nuclear@0
|
43 prev_dmacon = REG_DMACONR;
|
nuclear@0
|
44 REG_DMACON = CLRBITS(DMA_ALL);
|
nuclear@0
|
45
|
nuclear@0
|
46 prev_intena = REG_INTENAR;
|
nuclear@0
|
47 prev_intreq = REG_INTREQR;
|
nuclear@0
|
48 prev_adkcon = REG_ADKCONR;
|
nuclear@0
|
49
|
nuclear@6
|
50 if(init_copper(1400, 0) == -1) {
|
nuclear@0
|
51 return -1;
|
nuclear@0
|
52 }
|
nuclear@0
|
53
|
nuclear@11
|
54 /* setup vblank interrupt handler */
|
nuclear@11
|
55 if(!(vbint = malloc(sizeof *vbint))) {
|
nuclear@11
|
56 gfx_shutdown();
|
nuclear@11
|
57 return -1;
|
nuclear@11
|
58 }
|
nuclear@11
|
59 vbint->is_Node.ln_Type = NT_INTERRUPT;
|
nuclear@11
|
60 vbint->is_Node.ln_Pri = -60;
|
nuclear@11
|
61 vbint->is_Node.ln_Name = "imgv_vblank_intr";
|
nuclear@11
|
62 vbint->is_Data = 0;
|
nuclear@11
|
63 vbint->is_Code = vblank_intr;
|
nuclear@11
|
64
|
nuclear@11
|
65 AddIntServer(INTR_VERTB, vbint);
|
nuclear@11
|
66
|
nuclear@0
|
67 if(!gfx_set_framebuffer(0, scr_width, scr_height)) {
|
nuclear@0
|
68 gfx_shutdown();
|
nuclear@0
|
69 return -1;
|
nuclear@0
|
70 }
|
nuclear@0
|
71
|
nuclear@0
|
72 bplcon0 = BPLCON0_COUNT(nbpl) | BPLCON0_COLOR;
|
nuclear@0
|
73 if(flags & GFX_HIRES) bplcon0 |= BPLCON0_HIRES;
|
nuclear@0
|
74 if(flags & GFX_ILACE) bplcon0 |= BPLCON0_LACE;
|
nuclear@0
|
75 if(flags & GFX_HAM) bplcon0 |= BPLCON0_HOMOD;
|
nuclear@0
|
76 if(flags & GFX_DBLPF) bplcon0 |= BPLCON0_DBLPF;
|
nuclear@0
|
77
|
nuclear@0
|
78 REG_BPLCON0 = bplcon0;
|
nuclear@0
|
79 REG_BPLCON1 = 0; /* h-scroll */
|
nuclear@0
|
80 REG_DIWSTART = 0x2c81; /* 81h horiz start, 2ch vertical start */
|
nuclear@0
|
81 REG_DIWSTOP = 0x2cc1;
|
nuclear@0
|
82 REG_DDFSTART = (flags & GFX_HIRES) ? 0x3c : 0x38;
|
nuclear@0
|
83 REG_DDFSTOP = (flags & GFX_HIRES) ? 0xd4 : 0xd0;
|
nuclear@0
|
84
|
nuclear@0
|
85 gfx_wait_vblank();
|
nuclear@0
|
86 gfx_begin_copperlist();
|
nuclear@0
|
87 add_copper(COPPER_END);
|
nuclear@0
|
88
|
nuclear@3
|
89 logmsg("starting DMA\n");
|
nuclear@0
|
90 REG_DMACON = SETBITS(DMA_BPL | DMA_COPPER | DMA_MASTER);
|
nuclear@0
|
91 return 0;
|
nuclear@0
|
92 }
|
nuclear@0
|
93
|
nuclear@0
|
94 void gfx_shutdown(void)
|
nuclear@0
|
95 {
|
nuclear@0
|
96 REG_DMACON = CLRBITS(DMA_ALL);
|
nuclear@0
|
97 REG_DMACON = SETBITS(prev_dmacon);
|
nuclear@0
|
98
|
nuclear@0
|
99 REG_INTREQ = CLRBITS(0x7fff);
|
nuclear@0
|
100 REG_INTREQ = SETBITS(prev_intreq);
|
nuclear@0
|
101
|
nuclear@0
|
102 REG_ADKCON = CLRBITS(0x7fff);
|
nuclear@0
|
103 REG_ADKCON = SETBITS(prev_adkcon);
|
nuclear@0
|
104
|
nuclear@0
|
105 REG_INTENA = CLRBITS(INTEN_ALL);
|
nuclear@0
|
106 REG_INTENA = SETBITS(prev_intena);
|
nuclear@0
|
107
|
nuclear@0
|
108 if(framebuf && own_framebuf) {
|
nuclear@0
|
109 FreeMem(framebuf, fbsize);
|
nuclear@0
|
110 }
|
nuclear@0
|
111 framebuf = 0;
|
nuclear@0
|
112
|
nuclear@11
|
113 if(vbint) {
|
nuclear@11
|
114 RemIntServer(INTR_VERTB, vbint);
|
nuclear@11
|
115 free(vbint);
|
nuclear@11
|
116 vbint = 0;
|
nuclear@11
|
117 }
|
nuclear@11
|
118
|
nuclear@0
|
119 cleanup_copper();
|
nuclear@0
|
120 Permit();
|
nuclear@11
|
121
|
nuclear@11
|
122 if(init_flags & GFX_ILACE) {
|
nuclear@11
|
123 printf("fields shown - long: %u / short: %u\n", long_fields, short_fields);
|
nuclear@11
|
124 }
|
nuclear@0
|
125 }
|
nuclear@0
|
126
|
nuclear@0
|
127 int gfx_screen_width(void)
|
nuclear@0
|
128 {
|
nuclear@0
|
129 return scr_width;
|
nuclear@0
|
130 }
|
nuclear@0
|
131
|
nuclear@0
|
132 int gfx_screen_height(void)
|
nuclear@0
|
133 {
|
nuclear@0
|
134 return scr_height;
|
nuclear@0
|
135 }
|
nuclear@0
|
136
|
nuclear@0
|
137 void *gfx_set_framebuffer(void *fb, int width, int height)
|
nuclear@0
|
138 {
|
nuclear@0
|
139 /*unsigned int bpl_scanline_sz = width / 8;*/
|
nuclear@0
|
140 unsigned long sz = width * height / 8 * num_bitplanes;
|
nuclear@0
|
141 uint32_t bpladdr;
|
nuclear@0
|
142 uint16_t bplmod;
|
nuclear@0
|
143
|
nuclear@0
|
144 if(framebuf && own_framebuf) {
|
nuclear@0
|
145 FreeMem(framebuf, fbsize);
|
nuclear@0
|
146 }
|
nuclear@0
|
147
|
nuclear@0
|
148 if(fb) {
|
nuclear@0
|
149 framebuf = fb;
|
nuclear@0
|
150 own_framebuf = 0;
|
nuclear@0
|
151 } else {
|
nuclear@11
|
152 if(!(framebuf = AllocMem(sz, MEMF_CHIP | MEMF_CLEAR))) {
|
nuclear@0
|
153 logmsg("gfx_set_framebuffer failed to allocate %lu bytes of chip mem for framebuffer\n", sz);
|
nuclear@0
|
154 return 0;
|
nuclear@0
|
155 }
|
nuclear@0
|
156 own_framebuf = 1;
|
nuclear@0
|
157 }
|
nuclear@0
|
158
|
nuclear@0
|
159 fb_width = width;
|
nuclear@0
|
160 fb_height = height;
|
nuclear@0
|
161 fbsize = sz;
|
nuclear@0
|
162
|
nuclear@0
|
163 bpladdr = (uint32_t)framebuf;
|
nuclear@0
|
164 logmsg("bitplane address: %lx\n", (unsigned long)bpladdr);
|
nuclear@0
|
165
|
nuclear@4
|
166 bplmod = (fb_width - scr_width) / 8 + fb_width / 8 * (num_bitplanes - 1);
|
nuclear@11
|
167 if(init_flags & GFX_ILACE) {
|
nuclear@11
|
168 bplmod += fb_width / 8 * num_bitplanes;
|
nuclear@11
|
169 }
|
nuclear@0
|
170 REG_BPL1MOD = bplmod;
|
nuclear@0
|
171 REG_BPL2MOD = bplmod;
|
nuclear@0
|
172
|
nuclear@0
|
173 /*
|
nuclear@0
|
174 REG32_BPL1PT = bpladdr; bpladdr += bpl_scanline_sz;
|
nuclear@0
|
175 REG32_BPL2PT = bpladdr; bpladdr += bpl_scanline_sz;
|
nuclear@0
|
176 REG32_BPL3PT = bpladdr; bpladdr += bpl_scanline_sz;
|
nuclear@0
|
177 REG32_BPL4PT = bpladdr; bpladdr += bpl_scanline_sz;
|
nuclear@0
|
178 REG32_BPL5PT = bpladdr; bpladdr += bpl_scanline_sz;
|
nuclear@0
|
179 REG32_BPL6PT = bpladdr;
|
nuclear@0
|
180 */
|
nuclear@0
|
181 return framebuf;
|
nuclear@0
|
182 }
|
nuclear@0
|
183
|
nuclear@0
|
184 void *gfx_get_framebuffer(void)
|
nuclear@0
|
185 {
|
nuclear@0
|
186 return framebuf;
|
nuclear@0
|
187 }
|
nuclear@0
|
188
|
nuclear@0
|
189 int gfx_framebuffer_width(void)
|
nuclear@0
|
190 {
|
nuclear@0
|
191 return fb_width;
|
nuclear@0
|
192 }
|
nuclear@0
|
193
|
nuclear@0
|
194 int gfx_framebuffer_height(void)
|
nuclear@0
|
195 {
|
nuclear@0
|
196 return fb_height;
|
nuclear@0
|
197 }
|
nuclear@0
|
198
|
nuclear@0
|
199 void gfx_begin_copperlist(void)
|
nuclear@0
|
200 {
|
nuclear@0
|
201 int i;
|
nuclear@0
|
202 uint32_t bpladdr;
|
nuclear@11
|
203 uint16_t reg_bplptr = REGN_BPL1PTH;
|
nuclear@0
|
204 bpladdr = (uint32_t)framebuf;
|
nuclear@0
|
205
|
nuclear@11
|
206 REG_INTENA = CLRBITS(INTEN_VERTB);
|
nuclear@11
|
207
|
nuclear@0
|
208 for(i=0; i<num_bitplanes; i++) {
|
nuclear@11
|
209 add_copper(COPPER_VWAIT_OVERSCAN(10));
|
nuclear@11
|
210 coplist_bplptr[i] = copperlist_end;
|
nuclear@11
|
211 add_copper(COPPER_MOVE(reg_bplptr, bpladdr >> 16));
|
nuclear@11
|
212 reg_bplptr += 2;
|
nuclear@11
|
213 add_copper(COPPER_MOVE(reg_bplptr, bpladdr));
|
nuclear@11
|
214 reg_bplptr += 2;
|
nuclear@5
|
215 bpladdr += fb_width / 8;
|
nuclear@0
|
216 }
|
nuclear@11
|
217 REG_INTENA = SETBITS(INTEN_VERTB);
|
nuclear@0
|
218 }
|
nuclear@0
|
219
|
nuclear@0
|
220 static int mouse_bnstate(void)
|
nuclear@0
|
221 {
|
nuclear@0
|
222 return (REG_CIAA_PORTA & CIAA_PA_FIR0) ? 0 : 1;
|
nuclear@0
|
223 }
|
nuclear@0
|
224
|
nuclear@0
|
225 int gfx_next_event(union gfx_event *ev, int block)
|
nuclear@0
|
226 {
|
nuclear@0
|
227 /* TODO */
|
nuclear@0
|
228 if(block) {
|
nuclear@0
|
229 while(!mouse_bnstate());
|
nuclear@0
|
230 ev->type = GFX_EV_QUIT;
|
nuclear@0
|
231 return 1;
|
nuclear@0
|
232 }
|
nuclear@0
|
233
|
nuclear@0
|
234 if(mouse_bnstate()) {
|
nuclear@0
|
235 ev->type = GFX_EV_QUIT;
|
nuclear@0
|
236 return 1;
|
nuclear@0
|
237 }
|
nuclear@0
|
238
|
nuclear@0
|
239 return 0;
|
nuclear@0
|
240 }
|
nuclear@0
|
241
|
nuclear@0
|
242 void gfx_wait_vpos(int x)
|
nuclear@0
|
243 {
|
nuclear@0
|
244 x <<= 8;
|
nuclear@0
|
245 while((REG32_VPOSR & 0x1ff00) < x);
|
nuclear@0
|
246 }
|
nuclear@0
|
247
|
nuclear@0
|
248 void gfx_wait_vblank(void)
|
nuclear@0
|
249 {
|
nuclear@0
|
250 gfx_wait_vpos(300);
|
nuclear@0
|
251 }
|
nuclear@3
|
252
|
nuclear@3
|
253 void gfx_show_image(struct ham_image *img)
|
nuclear@3
|
254 {
|
nuclear@4
|
255 int i, j, k, fbwidth, fbheight, ncolors, prev_line;
|
nuclear@4
|
256 unsigned char *fbptr = gfx_get_framebuffer();
|
nuclear@4
|
257 struct palchange *chg = img->chglist;
|
nuclear@4
|
258
|
nuclear@4
|
259 fbwidth = gfx_framebuffer_width();
|
nuclear@4
|
260 fbheight = gfx_framebuffer_height();
|
nuclear@4
|
261
|
nuclear@4
|
262 logmsg("showing ham image %dx%d\n", fbwidth, fbheight);
|
nuclear@4
|
263
|
nuclear@4
|
264 memcpy(fbptr, img->pixels, fbwidth * fbheight / 8 * num_bitplanes);
|
nuclear@4
|
265
|
nuclear@4
|
266 /* create copper list that handles the palette */
|
nuclear@4
|
267 clear_copper();
|
nuclear@4
|
268 gfx_begin_copperlist();
|
nuclear@4
|
269 /* initial palette at the start of frame */
|
nuclear@4
|
270 for(i=0; i<16; i++) {
|
nuclear@4
|
271 add_copper(COPPER_MOVE(REGN_COLOR(i), img->palette[i]));
|
nuclear@4
|
272 logmsg("copper palette[%d]: %x\n", i, (unsigned int)img->palette[i]);
|
nuclear@4
|
273 }
|
nuclear@4
|
274 /* add copper instructions for palette changes according to the image changelist */
|
nuclear@4
|
275 prev_line = -1;
|
nuclear@4
|
276 while(chg) {
|
nuclear@4
|
277 assert(chg->line >= prev_line);
|
nuclear@4
|
278 if(chg->line != prev_line) {
|
nuclear@6
|
279 if(chg->line > 255 && prev_line < 255) {
|
nuclear@6
|
280 add_copper(COPPER_VWAIT(255));
|
nuclear@6
|
281 }
|
nuclear@4
|
282 prev_line = chg->line;
|
nuclear@4
|
283 add_copper(COPPER_VWAIT(chg->line));
|
nuclear@4
|
284 }
|
nuclear@4
|
285 add_copper(COPPER_MOVE(REGN_COLOR(chg->entry >> 12), chg->entry & 0xfff));
|
nuclear@6
|
286 chg = chg->next;
|
nuclear@4
|
287 }
|
nuclear@4
|
288 add_copper(COPPER_END);
|
nuclear@3
|
289 }
|
nuclear@11
|
290
|
nuclear@11
|
291 static __amigainterrupt void vblank_intr()
|
nuclear@11
|
292 {
|
nuclear@11
|
293 if(init_flags & GFX_ILACE) {
|
nuclear@11
|
294 int i;
|
nuclear@11
|
295 uint32_t bpladdr;
|
nuclear@11
|
296 uint16_t reg_bplptr = REGN_BPL1PTH;
|
nuclear@11
|
297 bpladdr = (uint32_t)framebuf;
|
nuclear@11
|
298
|
nuclear@11
|
299 /* 0: when long frame flag is set in VPOS */
|
nuclear@11
|
300 scr_field = REG_VPOSR & 0x8000;
|
nuclear@11
|
301 if(scr_field) {
|
nuclear@11
|
302 bpladdr += fb_width / 8 * num_bitplanes;
|
nuclear@11
|
303 ++long_fields;
|
nuclear@11
|
304 } else {
|
nuclear@11
|
305 ++short_fields;
|
nuclear@11
|
306 }
|
nuclear@11
|
307
|
nuclear@11
|
308 if(coplist_bplptr[0]) {
|
nuclear@11
|
309 for(i=0; i<num_bitplanes; i++) {
|
nuclear@11
|
310 coplist_bplptr[i][0] = COPPER_MOVE(reg_bplptr, bpladdr >> 16);
|
nuclear@11
|
311 reg_bplptr += 2;
|
nuclear@11
|
312 coplist_bplptr[i][1] = COPPER_MOVE(reg_bplptr, bpladdr);
|
nuclear@11
|
313 reg_bplptr += 2;
|
nuclear@11
|
314 bpladdr += fb_width / 8;
|
nuclear@11
|
315 }
|
nuclear@11
|
316 }
|
nuclear@11
|
317 }
|
nuclear@11
|
318 /* TODO read mouse */
|
nuclear@11
|
319 }
|