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 +}