nuclear@0: #include nuclear@6: #include nuclear@0: #include nuclear@0: #include "gfx.h" nuclear@0: #include "copper.h" nuclear@0: #include "hwregs.h" nuclear@0: #include "logger.h" nuclear@4: #include "image.h" nuclear@0: nuclear@0: static int scr_width, scr_height; nuclear@0: static int fb_width, fb_height; nuclear@0: static int num_bitplanes; nuclear@0: static uint16_t prev_intena, prev_intreq, prev_adkcon, prev_dmacon; nuclear@0: nuclear@0: static unsigned char *framebuf; nuclear@0: static unsigned long fbsize; nuclear@0: static int own_framebuf; nuclear@0: nuclear@0: int gfx_init(int nbpl, unsigned int flags) nuclear@0: { nuclear@0: uint16_t bplcon0; nuclear@0: nuclear@0: num_bitplanes = nbpl; nuclear@0: scr_width = fb_width = (flags & GFX_HIRES) ? 640 : 320; nuclear@0: scr_height = fb_height = (flags & GFX_ILACE) ? 512 : 256; nuclear@0: nuclear@0: Forbid(); nuclear@0: nuclear@0: prev_dmacon = REG_DMACONR; nuclear@0: REG_DMACON = CLRBITS(DMA_ALL); nuclear@0: nuclear@0: prev_intena = REG_INTENAR; nuclear@0: prev_intreq = REG_INTREQR; nuclear@0: prev_adkcon = REG_ADKCONR; nuclear@0: nuclear@6: if(init_copper(1400, 0) == -1) { nuclear@0: return -1; nuclear@0: } nuclear@0: nuclear@0: if(!gfx_set_framebuffer(0, scr_width, scr_height)) { nuclear@0: gfx_shutdown(); nuclear@0: return -1; nuclear@0: } nuclear@0: nuclear@0: bplcon0 = BPLCON0_COUNT(nbpl) | BPLCON0_COLOR; nuclear@0: if(flags & GFX_HIRES) bplcon0 |= BPLCON0_HIRES; nuclear@0: if(flags & GFX_ILACE) bplcon0 |= BPLCON0_LACE; nuclear@0: if(flags & GFX_HAM) bplcon0 |= BPLCON0_HOMOD; nuclear@0: if(flags & GFX_DBLPF) bplcon0 |= BPLCON0_DBLPF; nuclear@0: nuclear@0: REG_BPLCON0 = bplcon0; nuclear@0: REG_BPLCON1 = 0; /* h-scroll */ nuclear@0: REG_DIWSTART = 0x2c81; /* 81h horiz start, 2ch vertical start */ nuclear@0: REG_DIWSTOP = 0x2cc1; nuclear@0: REG_DDFSTART = (flags & GFX_HIRES) ? 0x3c : 0x38; nuclear@0: REG_DDFSTOP = (flags & GFX_HIRES) ? 0xd4 : 0xd0; nuclear@0: nuclear@0: gfx_wait_vblank(); nuclear@0: gfx_begin_copperlist(); nuclear@0: add_copper(COPPER_END); nuclear@0: nuclear@3: logmsg("starting DMA\n"); nuclear@0: REG_DMACON = SETBITS(DMA_BPL | DMA_COPPER | DMA_MASTER); nuclear@0: return 0; nuclear@0: } nuclear@0: nuclear@0: void gfx_shutdown(void) nuclear@0: { nuclear@0: REG_DMACON = CLRBITS(DMA_ALL); nuclear@0: REG_DMACON = SETBITS(prev_dmacon); nuclear@0: nuclear@0: REG_INTREQ = CLRBITS(0x7fff); nuclear@0: REG_INTREQ = SETBITS(prev_intreq); nuclear@0: nuclear@0: REG_ADKCON = CLRBITS(0x7fff); nuclear@0: REG_ADKCON = SETBITS(prev_adkcon); nuclear@0: nuclear@0: REG_INTENA = CLRBITS(INTEN_ALL); nuclear@0: REG_INTENA = SETBITS(prev_intena); nuclear@0: nuclear@0: if(framebuf && own_framebuf) { nuclear@0: FreeMem(framebuf, fbsize); nuclear@0: } nuclear@0: framebuf = 0; nuclear@0: nuclear@0: cleanup_copper(); nuclear@0: Permit(); nuclear@0: } nuclear@0: nuclear@0: int gfx_screen_width(void) nuclear@0: { nuclear@0: return scr_width; nuclear@0: } nuclear@0: nuclear@0: int gfx_screen_height(void) nuclear@0: { nuclear@0: return scr_height; nuclear@0: } nuclear@0: nuclear@0: void *gfx_set_framebuffer(void *fb, int width, int height) nuclear@0: { nuclear@0: /*unsigned int bpl_scanline_sz = width / 8;*/ nuclear@0: unsigned long sz = width * height / 8 * num_bitplanes; nuclear@0: uint32_t bpladdr; nuclear@0: uint16_t bplmod; nuclear@0: nuclear@0: if(framebuf && own_framebuf) { nuclear@0: FreeMem(framebuf, fbsize); nuclear@0: } nuclear@0: nuclear@0: if(fb) { nuclear@0: framebuf = fb; nuclear@0: own_framebuf = 0; nuclear@0: } else { nuclear@0: if(!(framebuf = AllocMem(sz, MEMF_CHIP))) { nuclear@0: logmsg("gfx_set_framebuffer failed to allocate %lu bytes of chip mem for framebuffer\n", sz); nuclear@0: return 0; nuclear@0: } nuclear@0: own_framebuf = 1; nuclear@0: } nuclear@0: nuclear@0: fb_width = width; nuclear@0: fb_height = height; nuclear@0: fbsize = sz; nuclear@0: nuclear@0: bpladdr = (uint32_t)framebuf; nuclear@0: logmsg("bitplane address: %lx\n", (unsigned long)bpladdr); nuclear@0: nuclear@4: bplmod = (fb_width - scr_width) / 8 + fb_width / 8 * (num_bitplanes - 1); nuclear@0: REG_BPL1MOD = bplmod; nuclear@0: REG_BPL2MOD = bplmod; nuclear@0: nuclear@0: /* nuclear@0: REG32_BPL1PT = bpladdr; bpladdr += bpl_scanline_sz; nuclear@0: REG32_BPL2PT = bpladdr; bpladdr += bpl_scanline_sz; nuclear@0: REG32_BPL3PT = bpladdr; bpladdr += bpl_scanline_sz; nuclear@0: REG32_BPL4PT = bpladdr; bpladdr += bpl_scanline_sz; nuclear@0: REG32_BPL5PT = bpladdr; bpladdr += bpl_scanline_sz; nuclear@0: REG32_BPL6PT = bpladdr; nuclear@0: */ nuclear@0: return framebuf; nuclear@0: } nuclear@0: nuclear@0: void *gfx_get_framebuffer(void) nuclear@0: { nuclear@0: return framebuf; nuclear@0: } nuclear@0: nuclear@0: int gfx_framebuffer_width(void) nuclear@0: { nuclear@0: return fb_width; nuclear@0: } nuclear@0: nuclear@0: int gfx_framebuffer_height(void) nuclear@0: { nuclear@0: return fb_height; nuclear@0: } nuclear@0: nuclear@0: void gfx_begin_copperlist(void) nuclear@0: { nuclear@0: static const uint16_t bplptr[] = { nuclear@0: REGN_BPL1PTH, REGN_BPL2PTH, REGN_BPL3PTH, REGN_BPL4PTH, REGN_BPL5PTH, REGN_BPL6PTH nuclear@0: }; nuclear@0: int i; nuclear@0: uint32_t bpladdr; nuclear@0: bpladdr = (uint32_t)framebuf; nuclear@0: nuclear@0: for(i=0; i> 16)); nuclear@0: add_copper(COPPER_MOVE(bplptr[i] + 2, bpladdr)); nuclear@5: bpladdr += fb_width / 8; nuclear@0: } nuclear@0: } nuclear@0: nuclear@0: static int mouse_bnstate(void) nuclear@0: { nuclear@0: return (REG_CIAA_PORTA & CIAA_PA_FIR0) ? 0 : 1; nuclear@0: } nuclear@0: nuclear@0: int gfx_next_event(union gfx_event *ev, int block) nuclear@0: { nuclear@0: /* TODO */ nuclear@0: if(block) { nuclear@0: while(!mouse_bnstate()); nuclear@0: ev->type = GFX_EV_QUIT; nuclear@0: return 1; nuclear@0: } nuclear@0: nuclear@0: if(mouse_bnstate()) { nuclear@0: ev->type = GFX_EV_QUIT; nuclear@0: return 1; nuclear@0: } nuclear@0: nuclear@0: return 0; nuclear@0: } nuclear@0: nuclear@0: void gfx_wait_vpos(int x) nuclear@0: { nuclear@0: x <<= 8; nuclear@0: while((REG32_VPOSR & 0x1ff00) < x); nuclear@0: } nuclear@0: nuclear@0: void gfx_wait_vblank(void) nuclear@0: { nuclear@0: gfx_wait_vpos(300); nuclear@0: } nuclear@3: nuclear@3: void gfx_show_image(struct ham_image *img) nuclear@3: { nuclear@4: int i, j, k, fbwidth, fbheight, ncolors, prev_line; nuclear@4: unsigned char *fbptr = gfx_get_framebuffer(); nuclear@4: struct palchange *chg = img->chglist; nuclear@4: nuclear@4: fbwidth = gfx_framebuffer_width(); nuclear@4: fbheight = gfx_framebuffer_height(); nuclear@4: nuclear@4: logmsg("showing ham image %dx%d\n", fbwidth, fbheight); nuclear@4: nuclear@4: memcpy(fbptr, img->pixels, fbwidth * fbheight / 8 * num_bitplanes); nuclear@4: nuclear@4: /* create copper list that handles the palette */ nuclear@4: clear_copper(); nuclear@4: gfx_begin_copperlist(); nuclear@4: /* initial palette at the start of frame */ nuclear@4: for(i=0; i<16; i++) { nuclear@4: add_copper(COPPER_MOVE(REGN_COLOR(i), img->palette[i])); nuclear@4: logmsg("copper palette[%d]: %x\n", i, (unsigned int)img->palette[i]); nuclear@4: } nuclear@4: /* add copper instructions for palette changes according to the image changelist */ nuclear@4: prev_line = -1; nuclear@4: while(chg) { nuclear@4: assert(chg->line >= prev_line); nuclear@4: if(chg->line != prev_line) { nuclear@6: if(chg->line > 255 && prev_line < 255) { nuclear@6: add_copper(COPPER_VWAIT(255)); nuclear@6: } nuclear@4: prev_line = chg->line; nuclear@4: add_copper(COPPER_VWAIT(chg->line)); nuclear@4: } nuclear@4: add_copper(COPPER_MOVE(REGN_COLOR(chg->entry >> 12), chg->entry & 0xfff)); nuclear@6: chg = chg->next; nuclear@4: } nuclear@4: add_copper(COPPER_END); nuclear@3: }