amiga_imgv
diff src/amiga/gfx.c @ 11:3d9aaefb8ba6
interlace mode
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Mon, 30 Oct 2017 15:24:23 +0200 |
parents | ae0ada629b03 |
children |
line diff
1.1 --- a/src/amiga/gfx.c Sun Oct 29 22:53:41 2017 +0200 1.2 +++ b/src/amiga/gfx.c Mon Oct 30 15:24:23 2017 +0200 1.3 @@ -1,6 +1,8 @@ 1.4 #include <stdio.h> 1.5 +#include <stdlib.h> 1.6 #include <assert.h> 1.7 #include <proto/exec.h> 1.8 +#include <exec/interrupts.h> 1.9 #include "gfx.h" 1.10 #include "copper.h" 1.11 #include "hwregs.h" 1.12 @@ -10,16 +12,28 @@ 1.13 static int scr_width, scr_height; 1.14 static int fb_width, fb_height; 1.15 static int num_bitplanes; 1.16 +static unsigned int init_flags; 1.17 +/* updated by vblank_intr to indicate the current field in interlaced mode */ 1.18 +static unsigned short scr_field; 1.19 +static uint32_t *coplist_bplptr[6]; 1.20 + 1.21 static uint16_t prev_intena, prev_intreq, prev_adkcon, prev_dmacon; 1.22 1.23 static unsigned char *framebuf; 1.24 static unsigned long fbsize; 1.25 static int own_framebuf; 1.26 1.27 +static unsigned int short_fields, long_fields; 1.28 + 1.29 +static struct Interrupt *vbint; 1.30 + 1.31 +static __amigainterrupt void vblank_intr(); 1.32 + 1.33 int gfx_init(int nbpl, unsigned int flags) 1.34 { 1.35 uint16_t bplcon0; 1.36 1.37 + init_flags = flags; 1.38 num_bitplanes = nbpl; 1.39 scr_width = fb_width = (flags & GFX_HIRES) ? 640 : 320; 1.40 scr_height = fb_height = (flags & GFX_ILACE) ? 512 : 256; 1.41 @@ -37,6 +51,19 @@ 1.42 return -1; 1.43 } 1.44 1.45 + /* setup vblank interrupt handler */ 1.46 + if(!(vbint = malloc(sizeof *vbint))) { 1.47 + gfx_shutdown(); 1.48 + return -1; 1.49 + } 1.50 + vbint->is_Node.ln_Type = NT_INTERRUPT; 1.51 + vbint->is_Node.ln_Pri = -60; 1.52 + vbint->is_Node.ln_Name = "imgv_vblank_intr"; 1.53 + vbint->is_Data = 0; 1.54 + vbint->is_Code = vblank_intr; 1.55 + 1.56 + AddIntServer(INTR_VERTB, vbint); 1.57 + 1.58 if(!gfx_set_framebuffer(0, scr_width, scr_height)) { 1.59 gfx_shutdown(); 1.60 return -1; 1.61 @@ -83,8 +110,18 @@ 1.62 } 1.63 framebuf = 0; 1.64 1.65 + if(vbint) { 1.66 + RemIntServer(INTR_VERTB, vbint); 1.67 + free(vbint); 1.68 + vbint = 0; 1.69 + } 1.70 + 1.71 cleanup_copper(); 1.72 Permit(); 1.73 + 1.74 + if(init_flags & GFX_ILACE) { 1.75 + printf("fields shown - long: %u / short: %u\n", long_fields, short_fields); 1.76 + } 1.77 } 1.78 1.79 int gfx_screen_width(void) 1.80 @@ -112,7 +149,7 @@ 1.81 framebuf = fb; 1.82 own_framebuf = 0; 1.83 } else { 1.84 - if(!(framebuf = AllocMem(sz, MEMF_CHIP))) { 1.85 + if(!(framebuf = AllocMem(sz, MEMF_CHIP | MEMF_CLEAR))) { 1.86 logmsg("gfx_set_framebuffer failed to allocate %lu bytes of chip mem for framebuffer\n", sz); 1.87 return 0; 1.88 } 1.89 @@ -127,6 +164,9 @@ 1.90 logmsg("bitplane address: %lx\n", (unsigned long)bpladdr); 1.91 1.92 bplmod = (fb_width - scr_width) / 8 + fb_width / 8 * (num_bitplanes - 1); 1.93 + if(init_flags & GFX_ILACE) { 1.94 + bplmod += fb_width / 8 * num_bitplanes; 1.95 + } 1.96 REG_BPL1MOD = bplmod; 1.97 REG_BPL2MOD = bplmod; 1.98 1.99 @@ -158,18 +198,23 @@ 1.100 1.101 void gfx_begin_copperlist(void) 1.102 { 1.103 - static const uint16_t bplptr[] = { 1.104 - REGN_BPL1PTH, REGN_BPL2PTH, REGN_BPL3PTH, REGN_BPL4PTH, REGN_BPL5PTH, REGN_BPL6PTH 1.105 - }; 1.106 int i; 1.107 uint32_t bpladdr; 1.108 + uint16_t reg_bplptr = REGN_BPL1PTH; 1.109 bpladdr = (uint32_t)framebuf; 1.110 1.111 + REG_INTENA = CLRBITS(INTEN_VERTB); 1.112 + 1.113 for(i=0; i<num_bitplanes; i++) { 1.114 - add_copper(COPPER_MOVE(bplptr[i], bpladdr >> 16)); 1.115 - add_copper(COPPER_MOVE(bplptr[i] + 2, bpladdr)); 1.116 + add_copper(COPPER_VWAIT_OVERSCAN(10)); 1.117 + coplist_bplptr[i] = copperlist_end; 1.118 + add_copper(COPPER_MOVE(reg_bplptr, bpladdr >> 16)); 1.119 + reg_bplptr += 2; 1.120 + add_copper(COPPER_MOVE(reg_bplptr, bpladdr)); 1.121 + reg_bplptr += 2; 1.122 bpladdr += fb_width / 8; 1.123 } 1.124 + REG_INTENA = SETBITS(INTEN_VERTB); 1.125 } 1.126 1.127 static int mouse_bnstate(void) 1.128 @@ -242,3 +287,33 @@ 1.129 } 1.130 add_copper(COPPER_END); 1.131 } 1.132 + 1.133 +static __amigainterrupt void vblank_intr() 1.134 +{ 1.135 + if(init_flags & GFX_ILACE) { 1.136 + int i; 1.137 + uint32_t bpladdr; 1.138 + uint16_t reg_bplptr = REGN_BPL1PTH; 1.139 + bpladdr = (uint32_t)framebuf; 1.140 + 1.141 + /* 0: when long frame flag is set in VPOS */ 1.142 + scr_field = REG_VPOSR & 0x8000; 1.143 + if(scr_field) { 1.144 + bpladdr += fb_width / 8 * num_bitplanes; 1.145 + ++long_fields; 1.146 + } else { 1.147 + ++short_fields; 1.148 + } 1.149 + 1.150 + if(coplist_bplptr[0]) { 1.151 + for(i=0; i<num_bitplanes; i++) { 1.152 + coplist_bplptr[i][0] = COPPER_MOVE(reg_bplptr, bpladdr >> 16); 1.153 + reg_bplptr += 2; 1.154 + coplist_bplptr[i][1] = COPPER_MOVE(reg_bplptr, bpladdr); 1.155 + reg_bplptr += 2; 1.156 + bpladdr += fb_width / 8; 1.157 + } 1.158 + } 1.159 + } 1.160 + /* TODO read mouse */ 1.161 +}