amiga_imgv

changeset 11:3d9aaefb8ba6

interlace mode
author John Tsiombikas <nuclear@member.fsf.org>
date Mon, 30 Oct 2017 15:24:23 +0200
parents 5614fbb9c1de
children 20c7238c60be
files src/amiga/gfx.c src/amiga/hwregs.h src/sdl/gfx.c
diffstat 3 files changed, 108 insertions(+), 9 deletions(-) [+]
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 +}
     2.1 --- a/src/amiga/hwregs.h	Sun Oct 29 22:53:41 2017 +0200
     2.2 +++ b/src/amiga/hwregs.h	Mon Oct 30 15:24:23 2017 +0200
     2.3 @@ -349,6 +349,24 @@
     2.4  #define SETBITS(x)	((x) | 0x8000)
     2.5  #define CLRBITS(x)	(x)
     2.6  
     2.7 +/* interrupt numbers */
     2.8 +enum {
     2.9 +	INTR_TBE,
    2.10 +	INTR_DSKBLK,
    2.11 +	INTR_SOFT,
    2.12 +	INTR_PORTS,
    2.13 +	INTR_COPPER,
    2.14 +	INTR_VERTB,
    2.15 +	INTR_BLITTER,
    2.16 +	INTR_AUDIO0,
    2.17 +	INTR_AUDIO1,
    2.18 +	INTR_AUDIO2,
    2.19 +	INTR_AUDIO3,
    2.20 +	INTR_RBF,
    2.21 +	INTR_DSKSYN,
    2.22 +	INTR_EXTER
    2.23 +};
    2.24 +
    2.25  /* interrupt enable flags */
    2.26  enum {
    2.27  	INTEN_TBE		= 0x0001,
     3.1 --- a/src/sdl/gfx.c	Sun Oct 29 22:53:41 2017 +0200
     3.2 +++ b/src/sdl/gfx.c	Mon Oct 30 15:24:23 2017 +0200
     3.3 @@ -50,6 +50,8 @@
     3.4  
     3.5  void *gfx_set_framebuffer(void *fb, int width, int height)
     3.6  {
     3.7 +	fb_width = width;
     3.8 +	fb_height = height;
     3.9  	return 0;
    3.10  }
    3.11  
    3.12 @@ -131,13 +133,15 @@
    3.13  
    3.14  void gfx_show_image(struct ham_image *img)
    3.15  {
    3.16 -	int i, j, k;
    3.17 -	uint32_t color, palette[16];
    3.18 +	int i, j, k, ncolors;
    3.19 +	uint32_t color, palette[256];
    3.20  	uint32_t *dest;
    3.21  	unsigned char *src;
    3.22  	struct palchange *chg = img->chglist;
    3.23  
    3.24 -	for(i=0; i<16; i++) {
    3.25 +	ncolors = 1 << img->nbitplanes;
    3.26 +
    3.27 +	for(i=0; i<ncolors; i++) {
    3.28  		uint16_t pcol = img->palette[i];
    3.29  		int red = ARED(pcol);
    3.30  		int green = AGREEN(pcol);
    3.31 @@ -152,6 +156,8 @@
    3.32  	dest = fbsurf->pixels;
    3.33  	src = img->pixels;
    3.34  	for(i=0; i<img->height; i++) {
    3.35 +		if(i >= scr_height) break;
    3.36 +
    3.37  		while(chg && chg->line <= i) {
    3.38  			int idx = (chg->entry & 0xf000) >> 12;
    3.39  			int red = ARED(chg->entry);