/* $NetBSD: grfabs_cc.c,v 1.35 2011/07/08 09:42:16 mrg Exp $ */
/*
* Copyright (c) 1994 Christian E. Hopps
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by Christian E. Hopps.
* 4. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* abstract interface for custom chips to the amiga abstract graphics driver.
*
*/
#include "opt_amigaccgrf.h"
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: grfabs_cc.c,v 1.35 2011/07/08 09:42:16 mrg Exp $");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/errno.h>
#include <sys/queue.h>
#include <amiga/amiga/custom.h>
#include <amiga/amiga/cc.h>
#include <amiga/dev/grfabs_reg.h>
#include <amiga/dev/grfabs_ccreg.h>
monitor_t *m_this;
mdata_t *m_this_data;
const char *monitor_name = "CCMONITOR";
monitor_t monitor;
mdata_t monitor_data;
cop_t *null_mode_copper_list;
#if defined (GRF_PAL)
# if defined (GRF_A2024)
dmode_t pal_a2024_mode;
dmdata_t pal_a2024_mode_data;
cop_t *pal_a2024_frames[F_QD_TOTAL];
u_char *hedley_init; /* init bitplane. */
dmode_t *p24_this;
dmdata_t *p24_this_data;
dmode_t pal_hires_dlace_mode;
dmdata_t pal_hires_dlace_mode_data;
cop_t *pal_hires_dlace_frames[F_LACE_TOTAL];
dmode_t *phdl_this;
dmdata_t *phdl_this_data;
# endif /* GRF_A2024 */
# if defined (GRF_AGA)
dmode_t paga_mode;
dmdata_t paga_mode_data;
cop_t *paga_frames[F_TOTAL];
dmode_t *paga_this;
dmdata_t *paga_this_data;
# endif /* GRF_AGA */
dmode_t pal_hires_lace_mode;
dmdata_t pal_hires_lace_mode_data;
cop_t *pal_hires_lace_frames[F_LACE_TOTAL];
dmode_t *phl_this;
dmdata_t *phl_this_data;
dmode_t pal_hires_mode;
dmdata_t pal_hires_mode_data;
cop_t *pal_hires_frames[F_TOTAL];
dmode_t *ph_this;
dmdata_t *ph_this_data;
#endif /* PAL */
#if defined (GRF_NTSC)
# if defined (GRF_A2024)
dmode_t a2024_mode;
dmdata_t a2024_mode_data;
cop_t *a2024_frames[F_QD_TOTAL];
u_char *hedley_init; /* init bitplane. */
dmode_t *a24_this;
dmdata_t *a24_this_data;
dmode_t hires_dlace_mode;
dmdata_t hires_dlace_mode_data;
cop_t *hires_dlace_frames[F_LACE_TOTAL];
dmode_t *hdl_this;
dmdata_t *hdl_this_data;
# endif /* GRF_A2024 */
# if defined (GRF_AGA)
dmode_t aga_mode;
dmdata_t aga_mode_data;
cop_t *aga_frames[F_TOTAL];
dmode_t *aga_this;
dmdata_t *aga_this_data;
#if defined (GRF_SUPER72)
dmode_t super72_mode;
dmdata_t super72_mode_data;
cop_t *super72_frames[F_LACE_TOTAL];
dmode_t *super72_this;
dmdata_t *super72_this_data;
#endif /* GRF_SUPER72 */
# endif /* GRF_AGA */
dmode_t hires_lace_mode;
dmdata_t hires_lace_mode_data;
cop_t *hires_lace_frames[F_LACE_TOTAL];
dmode_t *hl_this;
dmdata_t *hl_this_data;
void display_hires_view(view_t * v);
dmode_t hires_mode;
dmdata_t hires_mode_data;
cop_t *hires_frames[F_TOTAL];
dmode_t *h_this;
dmdata_t *h_this_data;
#endif /* GRF_NTSC */
#ifdef GRF_AGA
#define AGA_ENABLE 0x0001
#define AGA_ENABLE2 0x0002
#define AGA_TRACE 0x0004
#define AGA_TRACE2 0x0008
#define AGA_VGAONLY 0x0010
#define AGA_VGA31KHZ 0x0020
int aga_enable = 0; /* set by start_c(), or can be patched */
colormap_t *cc_alloc_aga_colormap(int);
int cc_use_aga_colormap(view_t *, colormap_t *);
#endif
/* monitor functions. */
monitor_t *
cc_init_monitor(void)
{
cop_t *cp;
if (m_this)
return(m_this);
cc_monitor = m_this = &monitor;
/* turn sprite DMA off. we don't support them yet. */
custom.dmacon = DMAF_SPRITE;
/* makre sure sprite data registers are clear as well */
custom.spr[0].data = 0;
custom.spr[0].datb = 0;
m_this->name = monitor_name;
m_this_data = m_this->data = &monitor_data;
m_this->get_current_mode = get_current_mode;
m_this->vbl_handler = (vbl_handler_func *) monitor_vbl_handler;
m_this->get_next_mode = get_next_mode;
m_this->get_best_mode = get_best_mode;
m_this->alloc_bitmap = alloc_bitmap;
m_this->free_bitmap = free_bitmap;
m_this_data->current_mode = NULL;
LIST_INIT(&m_this_data->modes);
cp = null_mode_copper_list = alloc_chipmem(sizeof(cop_t) * 4);
if (!cp)
panic("no chipmem for grf.");
CMOVE(cp, R_COLOR00, 0x0000); /* background is black */
CMOVE(cp, R_BPLCON0, 0x0000); /* no planes to fetch from */
CWAIT(cp, 255, 255); /* COPEND */
CWAIT(cp, 255, 255); /* COPEND really */
/* install this list and turn DMA on */
custom.cop1lc = PREP_DMA_MEM(null_mode_copper_list);
custom.copjmp1 = 0;
custom.dmacon = DMAF_SETCLR | DMAF_MASTER | DMAF_RASTER \
|DMAF_COPPER;
cc_init_modes();
LIST_INSERT_HEAD(monitors, m_this, link);
return (m_this);
}
void
monitor_vbl_handler(monitor_t *m)
{
dmdata_t *dmd;
if (m_this_data->current_mode == NULL)
return;
dmd = DMDATA(m_this_data->current_mode);
if (dmd)
dmd->vbl_handler(m_this_data->current_mode);
}
dmode_t *
get_current_mode(void)
{
if (m_this_data->current_mode)
return(m_this_data->current_mode);
else
return(NULL);
}
dmode_t *
get_next_mode(dmode_t *d)
{
if (d)
return(d->link.le_next);
return(m_this_data->modes.lh_first);
}
/* XXX needs to have more control attributes */
dmode_t *
get_best_mode(dimen_t *size, u_char depth)
{
dmode_t *save;
dmode_t *dm;
long dt = 0, dx, dy, ct;
dmdata_t *dmd;
save = NULL;
dm = m_this_data->modes.lh_first;
while (dm != NULL) {
dmd = dm->data;
if (depth > dmd->max_depth || depth < dmd->min_depth) {
dm = dm->link.le_next;
continue;
} else if (size->width > dmd->max_size.width ||
size->height > dmd->max_size.height) {
dm = dm->link.le_next;
continue;
} else if (size->width < dmd->min_size.width ||
size->height < dmd->min_size.height) {
dm = dm->link.le_next;
continue;
}
dx = abs(dm->nominal_size.width - size->width);
dy = abs(dm->nominal_size.height - size->height);
ct = dx + dy;
if (ct < dt || save == NULL) {
save = dm;
dt = ct;
}
dm = dm->link.le_next;
}
return (save);
}
/* bitmap functions */
bmap_t *
alloc_bitmap(u_short width, u_short height, u_short depth, u_short flags)
{
int i;
u_long total_size;
#ifdef GRF_AGA
u_short lwpr = (flags & BMF_ALIGN64) ? ((width + 63) / 64) * 2 :
(width + 31) / 32; /* AGA needs 64 bit align */
#else
u_short lwpr = (width + 31) / 32;
#endif
u_short wpr = lwpr << 1;
u_short bpr = wpr << 1;
u_short array_size = sizeof(u_char *) * depth;
u_long plane_size = bpr * height;
u_short temp_size = bpr + sizeof(u_long);
bmap_t *bm;
/* note the next allocation will give everything, also note that all
* the stuff we want (including bitmaps) will be long short aligned.
* This is a function of the data being allocated and the fact that
* alloc_chipmem() returns long short aligned data. note also that
* each row of the bitmap is long word aligned and made of exactly n
* longwords. -ch */
/* Sigh, it seems for mapping to work we need the bitplane data to 1:
* be aligned on a page boundry. 2: be n pages large.
*
* why? because the user gets a page aligned address, if this is before
* your allocation, too bad. Also it seems that the mapping routines
* do not watch to closely to the allowable length. so if you go over
* n pages by less than another page, the user gets to write all over
* the entire page. Since you did not allocate up to a page boundry
* (or more) the user writes into someone elses memory. -ch */
#ifdef __powerpc__
#define m68k_round_page(x) ((((unsigned)(x)) + PGOFSET) & ~PGOFSET)
#endif
total_size = m68k_round_page(plane_size * depth) + /* for length */
(temp_size) + (array_size) + sizeof(bmap_t) +
PAGE_SIZE; /* for alignment */
bm = alloc_chipmem(total_size);
if (bm) {
if (flags & BMF_CLEAR) {
memset(bm, 0, total_size);
}
bm->bytes_per_row = bpr;
bm->rows = height;
bm->depth = depth;
bm->flags = flags;
bm->plane = (u_char **) & bm[1];
bm->blit_temp = ((u_char *) bm->plane) + array_size;
bm->plane[0] = (u_char *) m68k_round_page((u_long)
(bm->blit_temp + temp_size));
if (flags & BMF_INTERLEAVED) {
bm->row_mod = bm->bytes_per_row * (depth - 1);
for (i = 1; i < depth; i++) {
bm->plane[i] = bm->plane[i - 1] + bpr;
}
} else {
bm->row_mod = 0;
for (i = 1; i < depth; i++) {
bm->plane[i] = bm->plane[i - 1] + plane_size;
}
}
bm->hardware_address = PREP_DMA_MEM(bm->plane[0]);
return (bm);
}
return (NULL);
}
void
free_bitmap(bmap_t *bm)
{
if (bm)
free_chipmem(bm);
}
/* load a new mode into the current display, if NULL shut display off. */
void
cc_load_mode(dmode_t *d)
{
if (d) {
m_this_data->current_mode = d;
#ifdef __powerpc__ /* XXX ???? */
custom.cop1lc = PREP_DMA_MEM(DMDATA(d)->frames[F_LONG]);
custom.copjmp1 = 0;
#endif
return;
}
/* turn off display */
m_this_data->current_mode = NULL;
wait_tof();
wait_tof();
custom.cop1lc = PREP_DMA_MEM(null_mode_copper_list);
custom.copjmp1 = 0;
}
/*
* CC Mode Stuff.
*/
dmode_t *(*mode_init_funcs[]) (void) = {
#if defined (GRF_NTSC)
#if defined (GRF_A2024)
cc_init_ntsc_a2024,
cc_init_ntsc_hires_dlace,
#endif /* GRF_A2024 */
cc_init_ntsc_hires_lace,
cc_init_ntsc_hires,
#if defined (GRF_AGA)
cc_init_ntsc_aga,
#if defined (GRF_SUPER72)
cc_init_super72,
#endif /* GRF_SUPER72 */
#endif /* GRF_AGA */
#endif /* GRF_NTSC */
#if defined (GRF_PAL)
#if defined (GRF_A2024)
cc_init_pal_a2024,
cc_init_pal_hires_dlace,
#endif /* GRF_A2024 */
cc_init_pal_hires_lace,
cc_init_pal_hires,
#if defined (GRF_AGA)
cc_init_pal_aga,
#endif /* GRF_AGA */
#endif /* GRF_PAL */
NULL
};
int
cc_init_modes(void)
{
int i = 0;
int error = 0;
while (mode_init_funcs[i]) {
mode_init_funcs[i] ();
i++;
}
return (error);
}
monitor_t *
cc_get_monitor(dmode_t *d)
{
return (DMDATA(d)->monitor);
}
view_t *
cc_get_current_view(dmode_t *d)
{
return (DMDATA(d)->current_view);
}
view_t *
cc_alloc_view(dmode_t *mode, dimen_t *dim, u_char depth)
{
view_t *v = alloc_chipmem(sizeof(*v) + sizeof(vdata_t));
if (v) {
bmap_t *bm = cc_monitor->alloc_bitmap(dim->width, dim->height,
depth, BMF_CLEAR | (DMDATA(mode)->max_depth == 8 ? BMF_ALIGN64 : 0));
if (bm) {
box_t box;
v->data = &v[1]; /* at the end of view */
VDATA(v)->colormap = DMDATA(mode)->alloc_colormap(depth);
if (VDATA(v)->colormap) {
INIT_BOX(&box, 0, 0, dim->width, dim->height);
cc_init_view(v, bm, mode, &box);
return (v);
}
cc_monitor->free_bitmap(bm);
}
free_chipmem(v);
}
return (NULL);
}
colormap_t *
cc_alloc_colormap(int depth)
{
u_long size = 1U << depth, i;
colormap_t *cm = alloc_chipmem(sizeof(u_long) * size + sizeof(*cm));
if (cm) {
cm->type = CM_COLOR;
cm->red_mask = 0x0F;
cm->green_mask = 0x0F;
cm->blue_mask = 0x0F;
cm->first = 0;
cm->size = size;
cm->entry = (u_long *) & cm[1]; /* table directly after. */
for (i = 0; i < size; i++) {
cm->entry[i] = CM_WTOL(cc_default_colors[i&31]);
}
return (cm);
}
return (NULL);
}
#ifdef GRF_AGA
colormap_t *
cc_alloc_aga_colormap(int depth)
{
u_long size = 1U << depth, i;
colormap_t *cm = alloc_chipmem(sizeof(u_long) * size + sizeof(*cm));
if (cm) {
cm->type = CM_COLOR;
cm->red_mask = 0x0FF;
cm->green_mask = 0x0FF;
cm->blue_mask = 0x0FF;
cm->first = 0;
cm->size = size;
cm->entry = (u_long *) & cm[1]; /* table directly after. */
for (i = 0; i < size; i++) {
cm->entry[i] = CM_WTOL(cc_default_colors[i&31]) |
(CM_WTOL(cc_default_colors[i&31]) << 4);
}
return (cm);
}
return (NULL);
}
#endif
int
cc_colormap_checkvals(colormap_t *vcm, colormap_t *cm, int use)
{
if (use) {
/* check to see if its the view's colormap, if so just do
* update. */
if (vcm != cm) {
if (cm->first >= vcm->size ||
(cm->first + cm->size) > (cm->first + vcm->size) ||
cm->type != vcm->type) {
return (0);
}
switch (vcm->type) {
case CM_COLOR:
if (cm->red_mask != vcm->red_mask ||
cm->green_mask != vcm->green_mask ||
cm->blue_mask != vcm->blue_mask) {
return (0);
}
break;
case CM_GREYSCALE:
if (cm->grey_mask != vcm->grey_mask) {
return (0);
}
break;
}
}
} else {
if (cm->first >= vcm->size ||
(cm->first + cm->size) > (cm->first + vcm->size)) {
return (0);
}
}
return (1);
}
/* does sanity check on values */
int
cc_get_colormap(view_t *v, colormap_t *cm)
{
colormap_t *vcm = VDATA(v)->colormap;
int i;
if (!cc_colormap_checkvals(vcm, cm, 0)) {
return (EINVAL);
}
cm->type = vcm->type;
switch (vcm->type) {
case CM_COLOR:
cm->red_mask = vcm->red_mask;
cm->green_mask = vcm->green_mask;
cm->blue_mask = vcm->blue_mask;
break;
case CM_GREYSCALE:
cm->grey_mask = vcm->grey_mask;
break;
}
/* copy entries into colormap. */
for (i = cm->first; i < (cm->first + cm->size); i++) {
cm->entry[i] = vcm->entry[i];
}
return (0);
}
/* does sanity check on values */
int
cc_use_colormap(view_t *v, colormap_t *cm)
{
colormap_t *vcm = VDATA(v)->colormap;
int s, i;
if (!cc_colormap_checkvals(vcm, cm, 1)) {
return (EINVAL);
}
/* check to see if its the view's colormap, if so just do update. */
if (vcm != cm) {
/* copy entries into colormap. */
for (i = cm->first; i < (cm->first + cm->size); i++) {
vcm->entry[i] = cm->entry[i];
}
}
s = spltty();
/* is view currently being displayed? */
if (VDATA(v)->flags & VF_DISPLAY) {
/* yes, update the copper lists */
cop_t *tmp, *cp;
int nframes = 1, j;
if (DMDATA(VDATA(v)->mode)->flags & DMF_INTERLACE) {
nframes = 2;
}
for (i = 0; i < nframes; i++) {
cp = DMDATA(VDATA(v)->mode)->frames[i];
tmp = find_copper_inst(cp, CI_MOVE(R_COLOR07));
tmp -= 7;
for (j = 0; j < 32; j++) {
CMOVE(tmp, (R_COLOR00 + (j << 1)),
CM_LTOW(vcm->entry[j]));
}
}
}
splx(s);
return (0);
}
#ifdef GRF_AGA
/* does sanity check on values */
int
cc_use_aga_colormap(view_t *v, colormap_t *cm)
{
colormap_t *vcm = VDATA(v)->colormap;
int s, i;
if (!cc_colormap_checkvals(vcm, cm, 1)) {
return (EINVAL);
}
/* check to see if its the view's colormap, if so just do update. */
if (vcm != cm) {
/* copy entries into colormap. */
for (i = cm->first; i < (cm->first + cm->size); i++) {
vcm->entry[i] = cm->entry[i];
}
}
s = spltty();
/* is view currently being displayed? */
if (VDATA(v)->flags & VF_DISPLAY) {
/* yes, update the copper lists */
cop_t *tmp, *cp;
int nframes = 1, j;
if (DMDATA(VDATA(v)->mode)->flags & DMF_INTERLACE) {
nframes = 2;
}
for (i = 0; i < nframes; i++) {
cp = DMDATA(VDATA(v)->mode)->frames[i];
tmp = find_copper_inst(cp, CI_MOVE(R_COLOR00));
for (j = 0; j < vcm->size; j += 32) {
int k;
for (k = 0; k < 32; k++) {
int ce = vcm->entry[j + k] >> 4;
CMOVE(tmp, (R_COLOR00 + (k << 1)),
CM_LTOW(ce));
}
tmp++;
for (k = 0; k < 32; k++) {
int ce =vcm->entry[j + k];
CMOVE(tmp, (R_COLOR00 + (k << 1)),
CM_LTOW(ce));
}
tmp++;
}
}
}
splx(s);
return (0);
}
#endif
#if defined (GRF_A2024)
colormap_t *
cc_a2024_alloc_colormap(int depth)
{
u_long size = 1U << depth, i;
colormap_t *cm = alloc_chipmem(sizeof(u_long) * size + sizeof(*cm));
if (cm) {
cm->type = CM_GREYSCALE;
cm->grey_mask = 0x03;
cm->first = 0;
cm->size = size;
cm->entry = (u_long *) & cm[1]; /* table directly after. */
for (i = 0; i < size; i++) {
cm->entry[i] = CM_WTOL(cc_a2024_default_colors[i]);
}
return (cm);
}
return (NULL);
}
int
cc_a2024_get_colormap(view_t *v, colormap_t *cm)
{
/* there are no differences (yet) in the way the cm's are stored */
return (cc_get_colormap(v, cm));
}
int
cc_a2024_use_colormap(view_t *v, colormap_t *cm)
{
colormap_t *vcm = VDATA(v)->colormap;
int s, i;
if (!cc_colormap_checkvals(vcm, cm, 1)) {
return (EINVAL);
}
/* check to see if its the view's colormap, if so just do update. */
if (vcm != cm) {
/* copy entries into colormap. */
for (i = cm->first; i < (cm->first + cm->size); i++) {
vcm->entry[i] = cm->entry[i];
}
}
s = spltty();
/* is view currently being displayed? */
if (VDATA(v)->flags & VF_DISPLAY) {
/* yes, update the copper lists */
cop_t *tmp, *cp;
int nframes = 2, nregs = cm->size == 4 ? 16 : 8, j;
if (DMDATA(VDATA(v)->mode)->flags & DMF_HEDLEY_EXP) {
nframes = 4;
}
for (i = 0; i < nframes; i++) {
cp = DMDATA(VDATA(v)->mode)->frames[i];
tmp = find_copper_inst(cp, CI_MOVE(R_COLOR07));
tmp -= 7;
for (j = 0; j < nregs; j++) {
CMOVE(tmp, (R_COLOR00 + (j << 1)),
A2024_CM_TO_CR(vcm, j));
}
}
}
splx(s);
return (0);
}
#endif /* GRF_A2024 */
/*
* CC View stuff.
*/
void
cc_init_view(view_t *v, bmap_t *bm, dmode_t *mode, box_t *dbox)
{
vdata_t *vd = VDATA(v);
v->bitmap = bm;
vd->mode = mode;
memcpy(&v->display, dbox, sizeof(box_t));
v->display_view = DMDATA(vd->mode)->display_view;
v->use_colormap = DMDATA(vd->mode)->use_colormap;
v->get_colormap = DMDATA(vd->mode)->get_colormap;
v->free_view = cc_free_view;
v->get_display_mode = cc_get_display_mode;
v->remove_view = cc_remove_view;
}
void
cc_free_view(view_t *v)
{
if (v) {
v->remove_view(v);
free_chipmem(VDATA(v)->colormap);
cc_monitor->free_bitmap(v->bitmap);
free_chipmem(v);
}
}
void
cc_remove_view(view_t *v)
{
dmode_t *mode = VDATA(v)->mode;
if (MDATA(cc_monitor)->current_mode == mode) {
if (DMDATA(mode)->current_view == v) {
cc_load_mode(NULL);
}
}
if (DMDATA(mode)->current_view == v) {
DMDATA(mode)->current_view = NULL;
}
VDATA(v)->flags &= ~VF_DISPLAY;
}
dmode_t *
cc_get_display_mode(view_t *v)
{
return (VDATA(v)->mode);
}
void
cc_mode_vbl_handler(dmode_t *d)
{
u_short vp = ((custom.vposr & 0x0007) << 8) | ((custom.vhposr) >> 8);
if (vp < 12) {
custom.cop1lc = PREP_DMA_MEM(DMDATA(d)->frames[F_LONG]);
custom.copjmp1 = 0;
}
}
void
cc_lace_mode_vbl_handler(dmode_t *d)
{
u_short vp = ((custom.vposr & 0x0007) << 8) | ((custom.vhposr) >> 8);
if (vp < 12) {
if (custom.vposr & 0x8000) {
custom.cop1lc = PREP_DMA_MEM(DMDATA(d)->frames[F_LACE_LONG]);
} else {
custom.cop1lc = PREP_DMA_MEM(DMDATA(d)->frames[F_LACE_SHORT]);
}
custom.copjmp1 = 0;
}
}
/*
* Modes. (ick)
*/
/*
* NTSC Modes
*/
#if defined (GRF_NTSC)
dmode_t *
cc_init_ntsc_hires(void)
{
/* this function should only be called once. */
if (!h_this) {
u_short len = std_copper_list_len;
h_this = &hires_mode;
h_this_data = &hires_mode_data;
memset(h_this, 0, sizeof(dmode_t));
memset(h_this_data, 0, sizeof(dmdata_t));
h_this->name = "ntsc: hires";
h_this->nominal_size.width = 640;
h_this->nominal_size.height = 200;
h_this_data->max_size.width = 724;
h_this_data->max_size.height = 242;
h_this_data->min_size.width = 320;
h_this_data->min_size.height = 100;
h_this_data->min_depth = 1;
h_this_data->max_depth = 4;
h_this->data = h_this_data;
h_this->get_monitor = cc_get_monitor;
h_this->alloc_view = cc_alloc_view;
h_this->get_current_view = cc_get_current_view;
h_this_data->use_colormap = cc_use_colormap;
h_this_data->get_colormap = cc_get_colormap;
h_this_data->alloc_colormap = cc_alloc_colormap;
h_this_data->display_view = display_hires_view;
h_this_data->monitor = cc_monitor;
h_this_data->frames = hires_frames;
h_this_data->frames[F_LONG] =
alloc_chipmem(std_copper_list_size * F_TOTAL);
if (!h_this_data->frames[F_LONG]) {
panic("couldn't get chipmem for copper list");
}
h_this_data->frames[F_STORE_LONG] =
&h_this_data->frames[F_LONG][len];
memcpy(h_this_data->frames[F_STORE_LONG], std_copper_list,
std_copper_list_size);
memcpy(h_this_data->frames[F_LONG], std_copper_list,
std_copper_list_size);
h_this_data->bplcon0 = 0x8200 | USE_CON3; /* hires, color
* composite enable */
h_this_data->std_start_x = STANDARD_VIEW_X;
h_this_data->std_start_y = STANDARD_VIEW_Y;
h_this_data->vbl_handler =
(vbl_handler_func *) cc_mode_vbl_handler;
#if defined (GRF_ECS) || defined (GRF_AGA)
h_this_data->beamcon0 = STANDARD_NTSC_BEAMCON;
#endif
LIST_INSERT_HEAD(&MDATA(cc_monitor)->modes, h_this, link);
}
return (h_this);
}
void
display_hires_view(view_t *v)
{
if (h_this_data->current_view != v) {
vdata_t *vd = VDATA(v);
cop_t *cp = h_this_data->frames[F_STORE_LONG], *tmp;
int depth = v->bitmap->depth, i;
int hstart, hstop, vstart, vstop, j;
int x, y, w = v->display.width, h = v->display.height;
u_short ddfstart, ddfwidth, con1;
/* round down to nearest even width */
/* w &= 0xfffe; */
/* calculate datafetch width. */
ddfwidth = ((v->bitmap->bytes_per_row >> 1) - 2) << 2;
/* This will center the any overscanned display */
/* and allow user to modify. */
x = v->display.x + h_this_data->std_start_x - ((w - 640) >> 2);
y = v->display.y + h_this_data->std_start_y - ((h - 200) >> 1);
if (y & 1)
y--;
if (!(x & 1))
x--;
hstart = x;
hstop = x + (w >> 1);
vstart = y;
vstop = y + h;
ddfstart = (hstart - 9) >> 1;
/* check for hardware limits, AGA may allow more..? */
/* anyone got a 4000 I can borrow :^) -ch */
if ((ddfstart & 0xfffc) + ddfwidth > 0xd8) {
int d = 0;
/* XXX anyone know the equality properties of
* intermixed logial AND's */
/* XXX and arithmetic operators? */
while (((ddfstart & 0xfffc) + ddfwidth - d) > 0xd8) {
d++;
}
ddfstart -= d;
hstart -= d << 1;
hstop -= d << 1;
}
/* correct the datafetch to proper limits. */
/* delay the actual display of the data until we need it. */
ddfstart &= 0xfffc;
con1 = ((hstart - 9) - (ddfstart << 1)) |
(((hstart - 9) - (ddfstart << 1)) << 4);
if (h_this_data->current_view) {
VDATA(h_this_data->current_view)->flags &=
~VF_DISPLAY; /* mark as no longer displayed. */
}
h_this_data->current_view = v;
cp = h_this_data->frames[F_STORE_LONG];
#if defined (GRF_ECS) || defined (GRF_AGA)
tmp = find_copper_inst(cp, CI_MOVE(R_BPLCON3));
tmp->cp.inst.operand = 0x0020;
#if defined (GRF_AGA)
tmp = find_copper_inst(cp, CI_MOVE(R_FMODE));
tmp->cp.inst.operand = 0;
#endif
tmp = find_copper_inst(cp, CI_MOVE(R_BEAMCON0));
tmp->cp.inst.operand = h_this_data->beamcon0;
tmp = find_copper_inst(cp, CI_MOVE(R_DIWHIGH));
tmp->cp.inst.operand = CALC_DIWHIGH(hstart, vstart, hstop, vstop);
#endif /* ECS */
tmp = find_copper_inst(cp, CI_MOVE(R_BPLCON0));
tmp->cp.inst.operand = h_this_data->bplcon0 | ((depth & 0x7) << 12);
tmp = find_copper_inst(cp, CI_MOVE(R_BPLCON1));
tmp->cp.inst.operand = con1;
tmp = find_copper_inst(cp, CI_MOVE(R_DIWSTART));
tmp->cp.inst.operand = ((vstart & 0xff) << 8) | (hstart & 0xff);
tmp = find_copper_inst(cp, CI_MOVE(R_DIWSTOP));
tmp->cp.inst.operand = ((vstop & 0xff) << 8) | (hstop & 0xff);
tmp = find_copper_inst(cp, CI_MOVE(R_DDFSTART));
tmp->cp.inst.operand = ddfstart;
tmp = find_copper_inst(cp, CI_MOVE(R_DDFSTOP));
tmp->cp.inst.operand = ddfstart + ddfwidth;
tmp = find_copper_inst(cp, CI_MOVE(R_BPL0PTH));
for (i = 0, j = 0; i < depth; j += 2, i++) {
/* update the plane pointers */
tmp[j].cp.inst.operand =
HIADDR(PREP_DMA_MEM(v->bitmap->plane[i]));
tmp[j + 1].cp.inst.operand =
LOADDR(PREP_DMA_MEM(v->bitmap->plane[i]));
}
/* set mods correctly. */
tmp = find_copper_inst(cp, CI_MOVE(R_BPL1MOD));
tmp[0].cp.inst.operand = v->bitmap->row_mod;
tmp[1].cp.inst.operand = v->bitmap->row_mod;
/* set next pointers correctly */
tmp = find_copper_inst(cp, CI_MOVE(R_COP1LCH));
tmp[0].cp.inst.operand =
HIADDR(PREP_DMA_MEM(h_this_data->frames[F_STORE_LONG]));
tmp[1].cp.inst.operand =
LOADDR(PREP_DMA_MEM(h_this_data->frames[F_STORE_LONG]));
cp = h_this_data->frames[F_LONG];
h_this_data->frames[F_LONG] = h_this_data->frames[F_STORE_LONG];
h_this_data->frames[F_STORE_LONG] = cp;
vd->flags |= VF_DISPLAY;
cc_use_colormap(v, vd->colormap);
}
cc_load_mode(h_this);
}
dmode_t *
cc_init_ntsc_hires_lace(void)
{
/* this function should only be called once. */
if (!hl_this) {
u_short len = std_copper_list_len;
hl_this = &hires_lace_mode;
hl_this_data = &hires_lace_mode_data;
memset(hl_this, 0, sizeof(dmode_t));
memset(hl_this_data, 0, sizeof(dmdata_t));
hl_this->name = "ntsc: hires interlace";
hl_this->nominal_size.width = 640;
hl_this->nominal_size.height = 400;
hl_this_data->max_size.width = 724;
hl_this_data->max_size.height = 482;
hl_this_data->min_size.width = 320;
hl_this_data->min_size.height = 200;
hl_this_data->min_depth = 1;
hl_this_data->max_depth = 4;
hl_this->data = hl_this_data;
hl_this->get_monitor = cc_get_monitor;
hl_this->alloc_view = cc_alloc_view;
hl_this->get_current_view = cc_get_current_view;
hl_this_data->use_colormap = cc_use_colormap;
hl_this_data->get_colormap = cc_get_colormap;
hl_this_data->alloc_colormap = cc_alloc_colormap;
hl_this_data->display_view = display_hires_lace_view;
hl_this_data->monitor = cc_monitor;
hl_this_data->flags |= DMF_INTERLACE;
hl_this_data->frames = hires_lace_frames;
hl_this_data->frames[F_LACE_LONG] =
alloc_chipmem(std_copper_list_size * F_LACE_TOTAL);
if (!hl_this_data->frames[F_LACE_LONG]) {
panic("couldn't get chipmem for copper list");
}
hl_this_data->frames[F_LACE_SHORT] =
&hl_this_data->frames[F_LACE_LONG][len];
hl_this_data->frames[F_LACE_STORE_LONG] =
&hl_this_data->frames[F_LACE_SHORT][len];
hl_this_data->frames[F_LACE_STORE_SHORT] =
&hl_this_data->frames[F_LACE_STORE_LONG][len];
memcpy(hl_this_data->frames[F_LACE_STORE_LONG], std_copper_list,
std_copper_list_size);
memcpy(hl_this_data->frames[F_LACE_STORE_SHORT], std_copper_list,
std_copper_list_size);
memcpy(hl_this_data->frames[F_LACE_LONG], std_copper_list,
std_copper_list_size);
memcpy(hl_this_data->frames[F_LACE_SHORT], std_copper_list,
std_copper_list_size);
hl_this_data->bplcon0 = 0x8204 | USE_CON3; /* hires, color
* composite enable,
* lace. */
hl_this_data->std_start_x = STANDARD_VIEW_X;
hl_this_data->std_start_y = STANDARD_VIEW_Y;
hl_this_data->vbl_handler =
(vbl_handler_func *) cc_lace_mode_vbl_handler;
#if defined (GRF_ECS) || defined (GRF_AGA)
hl_this_data->beamcon0 = STANDARD_NTSC_BEAMCON;
#endif
LIST_INSERT_HEAD(&MDATA(cc_monitor)->modes, hl_this, link);
}
return (hl_this);
}
void
display_hires_lace_view(view_t *v)
{
if (hl_this_data->current_view != v) {
vdata_t *vd = VDATA(v);
cop_t *cp = hl_this_data->frames[F_LACE_STORE_LONG], *tmp;
int depth = v->bitmap->depth, i;
int hstart, hstop, vstart, vstop, j;
int x, y, w = v->display.width, h = v->display.height;
u_short ddfstart, ddfwidth, con1;
/* round down to nearest even width */
/* w &= 0xfffe; */
/* calculate datafetch width. */
ddfwidth = ((v->bitmap->bytes_per_row >> 1) - 2) << 2;
/* This will center the any overscanned display */
/* and allow user to modify. */
x = v->display.x + hl_this_data->std_start_x - ((w - 640) >> 2);
y = v->display.y + hl_this_data->std_start_y - ((h - 400) >> 2);
if (y & 1)
y--;
if (!(x & 1))
x--;
hstart = x;
hstop = x + (w >> 1);
vstart = y;
vstop = y + (h >> 1);
ddfstart = (hstart - 9) >> 1;
/* check for hardware limits, AGA may allow more..? */
/* anyone got a 4000 I can borrow :^) -ch */
if ((ddfstart & 0xfffc) + ddfwidth > 0xd8) {
int d = 0;
/* XXX anyone know the equality properties of
* intermixed logial AND's */
/* XXX and arithmetic operators? */
while (((ddfstart & 0xfffc) + ddfwidth - d) > 0xd8) {
d++;
}
ddfstart -= d;
hstart -= d << 1;
hstop -= d << 1;
}
/* correct the datafetch to proper limits. */
/* delay the actual display of the data until we need it. */
ddfstart &= 0xfffc;
con1 = ((hstart - 9) - (ddfstart << 1)) |
(((hstart - 9) - (ddfstart << 1)) << 4);
if (hl_this_data->current_view) {
VDATA(hl_this_data->current_view)->flags &=
~VF_DISPLAY; /* mark as no longer displayed. */
}
hl_this_data->current_view = v;
cp = hl_this_data->frames[F_LACE_STORE_LONG];
#if defined (GRF_ECS) || defined (GRF_AGA)
tmp = find_copper_inst(cp, CI_MOVE(R_BPLCON3));
tmp->cp.inst.operand = 0x0020;
#if defined (GRF_AGA)
tmp = find_copper_inst(cp, CI_MOVE(R_FMODE));
tmp->cp.inst.operand = 0;
#endif
tmp = find_copper_inst(cp, CI_MOVE(R_BEAMCON0));
tmp->cp.inst.operand = hl_this_data->beamcon0;
tmp = find_copper_inst(cp, CI_MOVE(R_DIWHIGH));
tmp->cp.inst.operand = CALC_DIWHIGH(hstart, vstart, hstop, vstop);
#endif /* ECS */
tmp = find_copper_inst(cp, CI_MOVE(R_BPLCON0));
tmp->cp.inst.operand = hl_this_data->bplcon0 | ((depth & 0x7) << 12);
tmp = find_copper_inst(cp, CI_MOVE(R_BPLCON1));
tmp->cp.inst.operand = con1;
tmp = find_copper_inst(cp, CI_MOVE(R_DIWSTART));
tmp->cp.inst.operand = ((vstart & 0xff) << 8) | (hstart & 0xff);
tmp = find_copper_inst(cp, CI_MOVE(R_DIWSTOP));
tmp->cp.inst.operand = ((vstop & 0xff) << 8) | (hstop & 0xff);
tmp = find_copper_inst(cp, CI_MOVE(R_DDFSTART));
tmp->cp.inst.operand = ddfstart;
tmp = find_copper_inst(cp, CI_MOVE(R_DDFSTOP));
tmp->cp.inst.operand = ddfstart + ddfwidth;
tmp = find_copper_inst(cp, CI_MOVE(R_BPL0PTH));
for (i = 0, j = 0; i < depth; j += 2, i++) {
/* update the plane pointers */
tmp[j].cp.inst.operand =
HIADDR(PREP_DMA_MEM(v->bitmap->plane[i]));
tmp[j + 1].cp.inst.operand =
LOADDR(PREP_DMA_MEM(v->bitmap->plane[i]));
}
/* set mods correctly. */
tmp = find_copper_inst(cp, CI_MOVE(R_BPL1MOD));
tmp[0].cp.inst.operand = v->bitmap->bytes_per_row + v->bitmap->row_mod;
tmp[1].cp.inst.operand = v->bitmap->bytes_per_row + v->bitmap->row_mod;
/* set next pointers correctly */
tmp = find_copper_inst(cp, CI_MOVE(R_COP1LCH));
tmp[0].cp.inst.operand =
HIADDR(PREP_DMA_MEM(hl_this_data->frames[F_LACE_STORE_SHORT]));
tmp[1].cp.inst.operand =
LOADDR(PREP_DMA_MEM(hl_this_data->frames[F_LACE_STORE_SHORT]));
bcopy(hl_this_data->frames[F_LACE_STORE_LONG],
hl_this_data->frames[F_LACE_STORE_SHORT], std_copper_list_size);
/* these are the only ones that are different from long frame. */
cp = hl_this_data->frames[F_LACE_STORE_SHORT];
tmp = find_copper_inst(cp, CI_MOVE(R_BPL0PTH));
for (i = 0, j = 0; i < depth; j += 2, i++) {
u_short mod = v->bitmap->bytes_per_row + v->bitmap->row_mod;
/* update plane pointers. high and low. */
tmp[j].cp.inst.operand =
HIADDR(PREP_DMA_MEM(&v->bitmap->plane[i][mod]));
tmp[j + 1].cp.inst.operand =
LOADDR(PREP_DMA_MEM(&v->bitmap->plane[i][mod]));
}
/* set next pointers correctly */
tmp = find_copper_inst(cp, CI_MOVE(R_COP1LCH));
tmp[0].cp.inst.operand =
HIADDR(PREP_DMA_MEM(hl_this_data->frames[F_LACE_STORE_LONG]));
tmp[1].cp.inst.operand =
LOADDR(PREP_DMA_MEM(hl_this_data->frames[F_LACE_STORE_LONG]));
cp = hl_this_data->frames[F_LACE_LONG];
hl_this_data->frames[F_LACE_LONG] =
hl_this_data->frames[F_LACE_STORE_LONG];
hl_this_data->frames[F_LACE_STORE_LONG] = cp;
cp = hl_this_data->frames[F_LACE_SHORT];
hl_this_data->frames[F_LACE_SHORT] =
hl_this_data->frames[F_LACE_STORE_SHORT];
hl_this_data->frames[F_LACE_STORE_SHORT] = cp;
vd->flags |= VF_DISPLAY;
cc_use_colormap(v, vd->colormap);
}
cc_load_mode(hl_this);
}
#if defined (GRF_A2024)
dmode_t *
cc_init_ntsc_hires_dlace(void)
{
/* this function should only be called once. */
if (!hdl_this) {
u_short len = std_dlace_copper_list_len;
hdl_this = &hires_dlace_mode;
hdl_this_data = &hires_dlace_mode_data;
memset(hdl_this, 0, sizeof(dmode_t));
memset(hdl_this_data, 0, sizeof(dmdata_t));
hdl_this->name = "ntsc: hires double interlace";
hdl_this->nominal_size.width = 640;
hdl_this->nominal_size.height = 800;
hdl_this_data->max_size.width = 724;
hdl_this_data->max_size.height = 800;
hdl_this_data->min_size.width = 320;
hdl_this_data->min_size.height = 400;
hdl_this_data->min_depth = 1;
hdl_this_data->max_depth = 2;
hdl_this->data = hdl_this_data;
hdl_this->get_monitor = cc_get_monitor;
hdl_this->alloc_view = cc_alloc_view;
hdl_this->get_current_view = cc_get_current_view;
hdl_this_data->use_colormap = cc_a2024_use_colormap;
hdl_this_data->get_colormap = cc_a2024_get_colormap;
hdl_this_data->alloc_colormap = cc_a2024_alloc_colormap;
hdl_this_data->display_view = display_hires_dlace_view;
hdl_this_data->monitor = cc_monitor;
hdl_this_data->flags |= DMF_INTERLACE;
hdl_this_data->frames = hires_dlace_frames;
hdl_this_data->frames[F_LACE_LONG] =
alloc_chipmem(std_dlace_copper_list_size * F_LACE_TOTAL);
if (!hdl_this_data->frames[F_LACE_LONG]) {
panic("couldn't get chipmem for copper list");
}
hdl_this_data->frames[F_LACE_SHORT] =
&hdl_this_data->frames[F_LACE_LONG][len];
hdl_this_data->frames[F_LACE_STORE_LONG] =
&hdl_this_data->frames[F_LACE_SHORT][len];
hdl_this_data->frames[F_LACE_STORE_SHORT] =
&hdl_this_data->frames[F_LACE_STORE_LONG][len];
bcopy(std_dlace_copper_list,
hdl_this_data->frames[F_LACE_STORE_LONG],
std_dlace_copper_list_size);
bcopy(std_dlace_copper_list,
hdl_this_data->frames[F_LACE_STORE_SHORT],
std_dlace_copper_list_size);
bcopy(std_dlace_copper_list,
hdl_this_data->frames[F_LACE_LONG],
std_dlace_copper_list_size);
bcopy(std_dlace_copper_list,
hdl_this_data->frames[F_LACE_SHORT],
std_dlace_copper_list_size);
hdl_this_data->bplcon0 = 0x8204 | USE_CON3; /* hires, color
* composite enable,
* dlace. */
hdl_this_data->std_start_x = STANDARD_VIEW_X;
hdl_this_data->std_start_y = STANDARD_VIEW_Y;
hdl_this_data->vbl_handler =
(vbl_handler_func *) cc_lace_mode_vbl_handler;
#if defined (GRF_ECS) || defined (GRF_AGA)
hdl_this_data->beamcon0 = STANDARD_NTSC_BEAMCON;
#endif
LIST_INSERT_HEAD(&MDATA(cc_monitor)->modes, hdl_this, link);
}
return (hdl_this);
}
void
display_hires_dlace_view(view_t *v)
{
if (hdl_this_data->current_view != v) {
vdata_t *vd = VDATA(v);
cop_t *cp = hdl_this_data->frames[F_LACE_STORE_LONG], *tmp;
int depth = v->bitmap->depth;
int hstart, hstop, vstart, vstop;
int x, y, w = v->display.width, h = v->display.height;
u_short ddfstart, ddfwidth, con1;
u_short mod1l, mod2l;
/* round down to nearest even width */
/* w &= 0xfffe; */
/* calculate datafetch width. */
ddfwidth = ((v->bitmap->bytes_per_row >> 1) - 2) << 2;
/* This will center the any overscanned display */
/* and allow user to modify. */
x = v->display.x + hdl_this_data->std_start_x - ((w - 640) >> 2);
y = v->display.y + hdl_this_data->std_start_y - ((h - 800) >> 3);
if (y & 1)
y--;
if (!(x & 1))
x--;
hstart = x;
hstop = x + (w >> 1);
vstart = y;
vstop = y + (h >> 2);
ddfstart = (hstart - 9) >> 1;
/* check for hardware limits, AGA may allow more..? */
/* anyone got a 4000 I can borrow :^) -ch */
if ((ddfstart & 0xfffc) + ddfwidth > 0xd8) {
int d = 0;
/* XXX anyone know the equality properties of
* intermixed logial AND's */
/* XXX and arithmetic operators? */
while (((ddfstart & 0xfffc) + ddfwidth - d) > 0xd8) {
d++;
}
ddfstart -= d;
hstart -= d << 1;
hstop -= d << 1;
}
/* correct the datafetch to proper limits. */
/* delay the actual display of the data until we need it. */
ddfstart &= 0xfffc;
con1 = ((hstart - 9) - (ddfstart << 1)) |
(((hstart - 9) - (ddfstart << 1)) << 4);
if (hdl_this_data->current_view) {
VDATA(hdl_this_data->current_view)->flags &=
~VF_DISPLAY; /* mark as no longer displayed. */
}
hdl_this_data->current_view = v;
cp = hdl_this_data->frames[F_LACE_STORE_LONG];
#if defined (GRF_ECS) || defined (GRF_AGA)
tmp = find_copper_inst(cp, CI_MOVE(R_BPLCON3));
tmp->cp.inst.operand = 0x0020;
#if defined (GRF_AGA)
tmp = find_copper_inst(cp, CI_MOVE(R_FMODE));
tmp->cp.inst.operand = 0;
#endif
tmp = find_copper_inst(cp, CI_MOVE(R_BEAMCON0));
tmp->cp.inst.operand = hdl_this_data->beamcon0;
tmp = find_copper_inst(cp, CI_MOVE(R_DIWHIGH));
tmp->cp.inst.operand = CALC_DIWHIGH(hstart, vstart, hstop, vstop);
#endif /* ECS */
tmp = find_copper_inst(cp, CI_MOVE(R_BPLCON0));
tmp->cp.inst.operand =
hdl_this_data->bplcon0 | ((depth & 0x7) << 13); /* times two. */
tmp = find_copper_inst(cp, CI_MOVE(R_BPLCON1));
tmp->cp.inst.operand = con1;
tmp = find_copper_inst(cp, CI_MOVE(R_DIWSTART));
tmp->cp.inst.operand = ((vstart & 0xff) << 8) | (hstart & 0xff);
tmp = find_copper_inst(cp, CI_MOVE(R_DIWSTOP));
tmp->cp.inst.operand = ((vstop & 0xff) << 8) | (hstop & 0xff);
tmp = find_copper_inst(cp, CI_MOVE(R_DDFSTART));
tmp->cp.inst.operand = ddfstart;
tmp = find_copper_inst(cp, CI_MOVE(R_DDFSTOP));
tmp->cp.inst.operand = ddfstart + ddfwidth;
mod1l = v->bitmap->bytes_per_row + v->bitmap->row_mod;
mod2l = mod1l << 1;
/* update plane pointers. */
tmp = find_copper_inst(cp, CI_MOVE(R_BPL0PTH));
tmp[0].cp.inst.operand =
HIADDR(PREP_DMA_MEM(&v->bitmap->plane[0][0]));
tmp[1].cp.inst.operand =
LOADDR(PREP_DMA_MEM(&v->bitmap->plane[0][0]));
tmp[2].cp.inst.operand =
HIADDR(PREP_DMA_MEM(&v->bitmap->plane[0][mod1l]));
tmp[3].cp.inst.operand =
LOADDR(PREP_DMA_MEM(&v->bitmap->plane[0][mod1l]));
if (depth == 2) {
tmp[4].cp.inst.operand =
HIADDR(PREP_DMA_MEM(&v->bitmap->plane[1][0]));
tmp[5].cp.inst.operand =
LOADDR(PREP_DMA_MEM(&v->bitmap->plane[1][0]));
tmp[6].cp.inst.operand =
HIADDR(PREP_DMA_MEM(&v->bitmap->plane[1][mod1l]));
tmp[7].cp.inst.operand =
LOADDR(PREP_DMA_MEM(&v->bitmap->plane[1][mod1l]));
}
/* set modulos. */
tmp = find_copper_inst(cp, CI_MOVE(R_BPL1MOD));
tmp[0].cp.inst.operand = mod2l + mod1l;
tmp[1].cp.inst.operand = mod2l + mod1l;
/* set next coper list pointers */
tmp = find_copper_inst(cp, CI_MOVE(R_COP1LCH));
tmp[0].cp.inst.operand =
HIADDR(PREP_DMA_MEM(hdl_this_data->frames[F_LACE_STORE_SHORT]));
tmp[1].cp.inst.operand =
LOADDR(PREP_DMA_MEM(hdl_this_data->frames[F_LACE_STORE_SHORT]));
bcopy(hdl_this_data->frames[F_LACE_STORE_LONG],
hdl_this_data->frames[F_LACE_STORE_SHORT],
std_dlace_copper_list_size);
/* these are the only ones that are different from long frame. */
cp = hdl_this_data->frames[F_LACE_STORE_SHORT];
/* update plane pointers. */
tmp = find_copper_inst(cp, CI_MOVE(R_BPL0PTH));
tmp[0].cp.inst.operand =
HIADDR(PREP_DMA_MEM(&v->bitmap->plane[0][mod2l]));
tmp[1].cp.inst.operand =
LOADDR(PREP_DMA_MEM(&v->bitmap->plane[0][mod2l]));
tmp[2].cp.inst.operand =
HIADDR(PREP_DMA_MEM(&v->bitmap->plane[0][mod2l + mod1l]));
tmp[3].cp.inst.operand =
LOADDR(PREP_DMA_MEM(&v->bitmap->plane[0][mod2l + mod1l]));
if (depth == 2) {
tmp[4].cp.inst.operand =
HIADDR(PREP_DMA_MEM(&v->bitmap->plane[1][mod2l]));
tmp[5].cp.inst.operand =
LOADDR(PREP_DMA_MEM(&v->bitmap->plane[1][mod2l]));
tmp[6].cp.inst.operand =
HIADDR(PREP_DMA_MEM(&v->bitmap->plane[1][mod2l + mod1l]));
tmp[7].cp.inst.operand =
LOADDR(PREP_DMA_MEM(&v->bitmap->plane[1][mod2l + mod1l]));
}
/* set next copper list pointers */
tmp = find_copper_inst(cp, CI_MOVE(R_COP1LCH));
tmp[0].cp.inst.operand =
HIADDR(PREP_DMA_MEM(hdl_this_data->frames[F_LACE_STORE_LONG]));
tmp[1].cp.inst.operand =
LOADDR(PREP_DMA_MEM(hdl_this_data->frames[F_LACE_STORE_LONG]));
cp = hdl_this_data->frames[F_LACE_LONG];
hdl_this_data->frames[F_LACE_LONG] =
hdl_this_data->frames[F_LACE_STORE_LONG];
hdl_this_data->frames[F_LACE_STORE_LONG] = cp;
cp = hdl_this_data->frames[F_LACE_SHORT];
hdl_this_data->frames[F_LACE_SHORT] =
hdl_this_data->frames[F_LACE_STORE_SHORT];
hdl_this_data->frames[F_LACE_STORE_SHORT] = cp;
vd->flags |= VF_DISPLAY;
cc_a2024_use_colormap(v, vd->colormap);
}
cc_load_mode(hdl_this);
}
dmode_t *
cc_init_ntsc_a2024(void)
{
/* this function should only be called once. */
if (!a24_this) {
int i;
u_short len = std_a2024_copper_list_len;
cop_t *cp;
a24_this = &a2024_mode;
a24_this_data = &a2024_mode_data;
memset(a24_this, 0, sizeof(dmode_t));
memset(a24_this_data, 0, sizeof(dmdata_t));
a24_this->name = "ntsc: A2024 15 kHz";
a24_this->nominal_size.width = 1024;
a24_this->nominal_size.height = 800;
a24_this_data->max_size.width = 1024;
a24_this_data->max_size.height = 800;
a24_this_data->min_size.width = 1024;
a24_this_data->min_size.height = 800;
a24_this_data->min_depth = 1;
a24_this_data->max_depth = 2;
a24_this->data = a24_this_data;
a24_this->get_monitor = cc_get_monitor;
a24_this->alloc_view = cc_alloc_view;
a24_this->get_current_view = cc_get_current_view;
a24_this_data->use_colormap = cc_a2024_use_colormap;
a24_this_data->get_colormap = cc_a2024_get_colormap;
a24_this_data->display_view = display_a2024_view;
a24_this_data->alloc_colormap = cc_a2024_alloc_colormap;
a24_this_data->monitor = cc_monitor;
a24_this_data->flags |= DMF_HEDLEY_EXP;
a24_this_data->frames = a2024_frames;
a24_this_data->frames[F_QD_QUAD0] =
alloc_chipmem(std_a2024_copper_list_size * F_QD_TOTAL);
if (!a24_this_data->frames[F_QD_QUAD0]) {
panic("couldn't get chipmem for copper list");
}
/* setup the hedley init bitplane. */
hedley_init = alloc_chipmem(128);
if (!hedley_init) {
panic("couldn't get chipmem for hedley init bitplane");
}
for (i = 1; i < 128; i++)
hedley_init[i] = 0xff;
hedley_init[0] = 0x03;
/* copy image of standard copper list. */
memcpy(a24_this_data->frames[0], std_a2024_copper_list,
std_a2024_copper_list_size);
/* set the init plane pointer. */
cp = find_copper_inst(a24_this_data->frames[F_QD_QUAD0],
CI_MOVE(R_BPL0PTH));
cp[0].cp.inst.operand = HIADDR(PREP_DMA_MEM(hedley_init));
cp[1].cp.inst.operand = LOADDR(PREP_DMA_MEM(hedley_init));
for (i = 1; i < F_QD_TOTAL; i++) {
a24_this_data->frames[i] = &a24_this_data->frames[i - 1][len];
bcopy(a24_this_data->frames[0],
a24_this_data->frames[i],
std_a2024_copper_list_size);
}
a24_this_data->bplcon0 = 0x8200; /* hires */
a24_this_data->vbl_handler =
(vbl_handler_func *) a2024_mode_vbl_handler;
LIST_INSERT_HEAD(&MDATA(cc_monitor)->modes, a24_this, link);
}
return (a24_this);
}
void
display_a2024_view(view_t *v)
{
if (a24_this_data->current_view != v) {
vdata_t *vd = VDATA(v);
cop_t *cp, *tmp;
u_char *inst_plane[2] = { NULL, NULL };
u_char **plane = inst_plane;
u_long full_line = v->bitmap->bytes_per_row + v->bitmap->row_mod;
u_long half_plane = full_line * v->bitmap->rows / 2;
int depth = v->bitmap->depth, i, j;
plane[0] = v->bitmap->plane[0];
if (depth == 2) {
plane[1] = v->bitmap->plane[1];
}
if (a24_this_data->current_view) {
VDATA(a24_this_data->current_view)->flags &=
~VF_DISPLAY; /* mark as no longer displayed. */
}
cp = a24_this_data->frames[F_QD_STORE_QUAD0];
tmp = find_copper_inst(cp, CI_MOVE(R_COLOR1F));
tmp = find_copper_inst(tmp, CI_MOVE(R_BPLCON0)); /* grab third one. */
tmp->cp.inst.operand = a24_this_data->bplcon0 |
((depth & 0x7) << 13); /* times 2 */
bcopy(a24_this_data->frames[F_QD_STORE_QUAD0],
a24_this_data->frames[F_QD_STORE_QUAD1],
std_a2024_copper_list_size);
bcopy(a24_this_data->frames[F_QD_STORE_QUAD0],
a24_this_data->frames[F_QD_STORE_QUAD2],
std_a2024_copper_list_size);
bcopy(a24_this_data->frames[F_QD_STORE_QUAD0],
a24_this_data->frames[F_QD_STORE_QUAD3],
std_a2024_copper_list_size);
/*
* Mark Id's
*/
tmp = find_copper_inst(a24_this_data->frames[F_QD_STORE_QUAD1],
CI_WAIT(126, 21));
CBUMP(tmp);
CMOVE(tmp, R_COLOR01, QUAD1_ID);
tmp = find_copper_inst(a24_this_data->frames[F_QD_STORE_QUAD2],
CI_WAIT(126, 21));
CBUMP(tmp);
CMOVE(tmp, R_COLOR01, QUAD2_ID);
tmp = find_copper_inst(a24_this_data->frames[F_QD_STORE_QUAD3],
CI_WAIT(126, 21));
CBUMP(tmp);
CMOVE(tmp, R_COLOR01, QUAD3_ID);
plane[0]--;
plane[0]--;
if (depth == 2) {
plane[1]--;
plane[1]--;
}
/*
* Set bitplane pointers.
*/
tmp = find_copper_inst(a24_this_data->frames[F_QD_STORE_QUAD0],
CI_MOVE(R_BPLMOD2));
CBUMP(tmp);
CMOVE(tmp, R_BPL0PTH, HIADDR(PREP_DMA_MEM(&plane[0][0])));
CMOVE(tmp, R_BPL0PTL, LOADDR(PREP_DMA_MEM(&plane[0][0])));
CMOVE(tmp, R_BPL1PTH, HIADDR(PREP_DMA_MEM(&plane[0][full_line])));
CMOVE(tmp, R_BPL1PTL, LOADDR(PREP_DMA_MEM(&plane[0][full_line])));
if (depth == 2) {
CMOVE(tmp, R_BPL2PTH, HIADDR(PREP_DMA_MEM(&plane[1][0])));
CMOVE(tmp, R_BPL2PTL, LOADDR(PREP_DMA_MEM(&plane[1][0])));
CMOVE(tmp, R_BPL3PTH, HIADDR(PREP_DMA_MEM(&plane[1][full_line])));
CMOVE(tmp, R_BPL3PTL, LOADDR(PREP_DMA_MEM(&plane[1][full_line])));
}
#if defined (GRF_ECS) || defined (GRF_AGA)
CMOVE(tmp, R_DIWHIGH, 0x2000);
#endif
CMOVE(tmp, R_COP1LCH,
HIADDR(PREP_DMA_MEM(a24_this_data->frames[F_QD_STORE_QUAD1])));
CMOVE(tmp, R_COP1LCL,
LOADDR(PREP_DMA_MEM(a24_this_data->frames[F_QD_STORE_QUAD1])));
CEND(tmp);
CEND(tmp);
tmp = find_copper_inst(a24_this_data->frames[F_QD_STORE_QUAD1],
CI_MOVE(R_BPLMOD2));
CBUMP(tmp);
CMOVE(tmp, R_BPL0PTH,
HIADDR(PREP_DMA_MEM(&plane[0][HALF_2024_LINE])));
CMOVE(tmp, R_BPL0PTL,
LOADDR(PREP_DMA_MEM(&plane[0][HALF_2024_LINE])));
CMOVE(tmp, R_BPL1PTH,
HIADDR(PREP_DMA_MEM(&plane[0][full_line + HALF_2024_LINE])));
CMOVE(tmp, R_BPL1PTL,
LOADDR(PREP_DMA_MEM(&plane[0][full_line + HALF_2024_LINE])));
if (depth == 2) {
CMOVE(tmp, R_BPL2PTH,
HIADDR(PREP_DMA_MEM(&plane[1][HALF_2024_LINE])));
CMOVE(tmp, R_BPL2PTL,
LOADDR(PREP_DMA_MEM(&plane[1][HALF_2024_LINE])));
CMOVE(tmp, R_BPL3PTH,
HIADDR(PREP_DMA_MEM(&plane[1][full_line + HALF_2024_LINE])));
CMOVE(tmp, R_BPL3PTL,
LOADDR(PREP_DMA_MEM(&plane[1][full_line + HALF_2024_LINE])));
}
#if defined (GRF_ECS) || defined (GRF_AGA)
CMOVE(tmp, R_DIWHIGH, 0x2000);
#endif
CMOVE(tmp, R_COP1LCH,
HIADDR(PREP_DMA_MEM(a24_this_data->frames[F_QD_STORE_QUAD2])));
CMOVE(tmp, R_COP1LCL,
LOADDR(PREP_DMA_MEM(a24_this_data->frames[F_QD_STORE_QUAD2])));
CEND(tmp);
CEND(tmp);
tmp = find_copper_inst(a24_this_data->frames[F_QD_STORE_QUAD2],
CI_MOVE(R_BPLMOD2));
CBUMP(tmp);
CMOVE(tmp, R_BPL0PTH,
HIADDR(PREP_DMA_MEM(&plane[0][half_plane])));
CMOVE(tmp, R_BPL0PTL,
LOADDR(PREP_DMA_MEM(&plane[0][half_plane])));
CMOVE(tmp, R_BPL1PTH,
HIADDR(PREP_DMA_MEM(&plane[0][half_plane + full_line])));
CMOVE(tmp, R_BPL1PTL,
LOADDR(PREP_DMA_MEM(&plane[0][half_plane + full_line])));
if (depth == 2) {
CMOVE(tmp, R_BPL2PTH,
HIADDR(PREP_DMA_MEM(&plane[1][half_plane])));
CMOVE(tmp, R_BPL2PTL,
LOADDR(PREP_DMA_MEM(&plane[1][half_plane])));
CMOVE(tmp, R_BPL3PTH,
HIADDR(PREP_DMA_MEM(&plane[1][half_plane + full_line])));
CMOVE(tmp, R_BPL3PTL,
LOADDR(PREP_DMA_MEM(&plane[1][half_plane + full_line])));
}
#if defined (GRF_ECS) || defined (GRF_AGA)
CMOVE(tmp, R_DIWHIGH, 0x2000);
#endif
CMOVE(tmp, R_COP1LCH,
HIADDR(PREP_DMA_MEM(a24_this_data->frames[F_QD_STORE_QUAD3])));
CMOVE(tmp, R_COP1LCL,
LOADDR(PREP_DMA_MEM(a24_this_data->frames[F_QD_STORE_QUAD3])));
CEND(tmp);
CEND(tmp);
tmp = find_copper_inst(a24_this_data->frames[F_QD_STORE_QUAD3],
CI_MOVE(R_BPLMOD2));
CBUMP(tmp);
CMOVE(tmp, R_BPL0PTH, HIADDR(PREP_DMA_MEM(
&plane[0][half_plane + HALF_2024_LINE])));
CMOVE(tmp, R_BPL0PTL, LOADDR(PREP_DMA_MEM(
&plane[0][half_plane + HALF_2024_LINE])));
CMOVE(tmp, R_BPL1PTH, HIADDR(PREP_DMA_MEM(
&plane[0][half_plane + full_line + HALF_2024_LINE])));
CMOVE(tmp, R_BPL1PTL, LOADDR(PREP_DMA_MEM(
&plane[0][half_plane + full_line + HALF_2024_LINE])));
if (depth == 2) {
CMOVE(tmp, R_BPL2PTH, HIADDR(PREP_DMA_MEM(
&plane[1][half_plane + HALF_2024_LINE])));
CMOVE(tmp, R_BPL2PTL, LOADDR(PREP_DMA_MEM(
&plane[1][half_plane + HALF_2024_LINE])));
CMOVE(tmp, R_BPL3PTH, HIADDR(PREP_DMA_MEM(
&plane[1][half_plane + full_line + HALF_2024_LINE])));
CMOVE(tmp, R_BPL3PTL, LOADDR(PREP_DMA_MEM(
&plane[1][half_plane + full_line + HALF_2024_LINE])));
}
#if defined (GRF_ECS) || defined (GRF_AGA)
CMOVE(tmp, R_DIWHIGH, 0x2000);
#endif
CMOVE(tmp, R_COP1LCH, HIADDR(PREP_DMA_MEM(
a24_this_data->frames[F_QD_STORE_QUAD0])));
CMOVE(tmp, R_COP1LCL, LOADDR(PREP_DMA_MEM(
a24_this_data->frames[F_QD_STORE_QUAD0])));
CEND(tmp);
CEND(tmp);
/* swap new pointers in. */
for (i = F_QD_STORE_QUAD0, j = F_QD_QUAD0;
i <= F_QD_STORE_QUAD3; i++, j++) {
cp = a24_this_data->frames[j];
a24_this_data->frames[j] = a24_this_data->frames[i];
a24_this_data->frames[i] = cp;
}
a24_this_data->current_view = v;
vd->flags |= VF_DISPLAY;
cc_a2024_use_colormap(v, vd->colormap);
}
cc_load_mode(a24_this);
}
void
a2024_mode_vbl_handler(dmode_t *d)
{
u_short vp = ((custom.vposr & 0x0007) << 8) | ((custom.vhposr) >> 8);
if (vp < 12) {
custom.cop1lc =
PREP_DMA_MEM(a24_this_data->frames[a24_this_data->hedley_current]);
custom.copjmp1 = 0;
}
a24_this_data->hedley_current++;
a24_this_data->hedley_current &= 0x3; /* if 4 then 0. */
}
#endif /* GRF_A2024 */
#if defined (GRF_AGA)
dmode_t *
cc_init_ntsc_aga(void)
{
/* this function should only be called once. */
if (!aga_this && (custom.deniseid & 0xff) == 0xf8 &&
aga_enable & AGA_ENABLE) {
u_short len = aga_copper_list_len;
aga_this = &aga_mode;
aga_this_data = &aga_mode_data;
memset(aga_this, 0, sizeof(dmode_t));
memset(aga_this_data, 0, sizeof(dmdata_t));
aga_this->name = "ntsc: AGA dbl";
aga_this->nominal_size.width = 640;
aga_this->nominal_size.height = 400;
aga_this_data->max_size.width = 724;
aga_this_data->max_size.height = 482;
aga_this_data->min_size.width = 320;
aga_this_data->min_size.height = 200;
aga_this_data->min_depth = 1;
aga_this_data->max_depth = 8;
aga_this->data = aga_this_data;
aga_this->get_monitor = cc_get_monitor;
aga_this->alloc_view = cc_alloc_view;
aga_this->get_current_view = cc_get_current_view;
aga_this_data->use_colormap = cc_use_aga_colormap;
aga_this_data->get_colormap = cc_get_colormap;
aga_this_data->alloc_colormap = cc_alloc_aga_colormap;
aga_this_data->display_view = display_aga_view;
aga_this_data->monitor = cc_monitor;
aga_this_data->frames = aga_frames;
aga_this_data->frames[F_LONG] = alloc_chipmem(aga_copper_list_size * F_TOTAL);
if (!aga_this_data->frames[F_LONG]) {
panic("couldn't get chipmem for copper list");
}
aga_this_data->frames[F_STORE_LONG] = &aga_this_data->frames[F_LONG][len];
memcpy(aga_this_data->frames[F_STORE_LONG], aga_copper_list, aga_copper_list_size);
memcpy(aga_this_data->frames[F_LONG], aga_copper_list, aga_copper_list_size);
aga_this_data->bplcon0 = 0x0240 | USE_CON3; /* color composite
* enable,
* shres. */
#ifdef GRF_AGA_VGA
aga_this_data->std_start_x = 0x40 /*STANDARD_VIEW_X*/;
#else
aga_this_data->std_start_x = 0x4f /*STANDARD_VIEW_X*/;
#endif
aga_this_data->std_start_y = 0x2b /*STANDARD_VIEW_Y*/;
aga_this_data->vbl_handler = (vbl_handler_func *) cc_mode_vbl_handler;
aga_this_data->beamcon0 = SPECIAL_BEAMCON ^ VSYNCTRUE;
LIST_INSERT_HEAD(&MDATA(cc_monitor)->modes,
aga_this, link);
}
return (aga_this);
}
/* static, so I can patch and play */
#ifdef GRF_AGA_VGA
int AGA_htotal = 0x71;
int AGA_hsstrt = 0xc;
int AGA_hsstop = 0x16;
int AGA_hbstrt = 0x5;
int AGA_vtotal = 0x1c1;
#else
int AGA_htotal = 0x79;
int AGA_hsstrt = 0xe;
int AGA_hsstop = 0x1c;
int AGA_hbstrt = 0x8;
int AGA_vtotal = 0x1ec;
#endif
int AGA_hbstop = 0x1e;
int AGA_vsstrt = 0x3;
int AGA_vsstop = 0x6;
int AGA_vbstrt = 0x0;
int AGA_vbstop = 0x19;
int AGA_hcenter = 0x4a;
void
display_aga_view(view_t *v)
{
if (aga_this_data->current_view != v) {
vdata_t *vd = VDATA(v);
cop_t *cp = aga_this_data->frames[F_STORE_LONG], *tmp;
int depth = v->bitmap->depth, i;
int hstart, hstop, vstart, vstop, j;
int x, y, w = v->display.width, h = v->display.height;
u_short ddfstart, ddfwidth, con1;
#ifdef DEBUG
if (aga_enable & AGA_TRACE)
printf("display_aga_view(%dx%dx%d) %p\n", w, h,
depth, v);
#endif
/* round down to nearest even width */
/* w &= 0xfffe; */
/* calculate datafetch width. */
ddfwidth = ((v->bitmap->bytes_per_row >> 1) - 4) << 1;
/* this will center the any overscanned display */
/* and allow user to modify. */
x = v->display.x + aga_this_data->std_start_x - ((w - 640) >> 3);
y = v->display.y + aga_this_data->std_start_y - ((h - 400) >> 1);
if (y & 1)
y--;
if (!(x & 1))
x--;
hstart = x;
hstop = x + (w >> 2);
vstart = y;
vstop = y + (h >> 0);
ddfstart = (hstart >> 1) - 8;
#ifdef DEBUG
if (aga_enable & AGA_TRACE2) {
printf (" ddfwidth %04x x %04x y %04x", ddfwidth,
x, y);
printf (" hstart %04x hstop %04x vstart %04x vstop %04x ddfstart %04x\n",
hstart, hstop, vstart, vstop, ddfstart);
}
#endif
/* check for hardware limits, AGA may allow more..? */
/* anyone got a 4000 I can borrow :^) -ch */
if ((ddfstart & 0xfffc) + ddfwidth > 0xd8) {
int d = 0;
/* XXX anyone know the equality properties of
* intermixed logial AND's */
/* XXX and arithmetic operators? */
while (((ddfstart & 0xfffc) + ddfwidth - d) > 0xd8) {
d++;
}
ddfstart -= d;
hstart -= d << 1;
hstop -= d << 1;
}
/* correct the datafetch to proper limits. */
/* delay the actual display of the data until we need it. */
ddfstart &= 0xfffc;
#ifdef DEBUG
if (aga_enable & AGA_TRACE2) {
printf (" ddfwidth %04x x %04x y %04x", ddfwidth,
x, y);
printf (" hstart %04x hstop %04x vstart %04x vstop %04x ddfstart %04x\n",
hstart, hstop, vstart, vstop, ddfstart);
}
#endif
con1 = ((hstart - 9) - (ddfstart << 1)) | (((hstart - 9) - (ddfstart << 1)) << 4);
if (aga_this_data->current_view) {
VDATA(aga_this_data->current_view)->flags &= ~VF_DISPLAY; /* mark as no longer */
/* displayed. */
}
aga_this_data->current_view = v;
cp = aga_this_data->frames[F_STORE_LONG];
tmp = cp;
for (i = 0; i < 8; ++i) {
if (tmp == NULL)
break;
tmp = find_copper_inst(tmp + 1, CI_MOVE(R_BPLCON3));
if (tmp == NULL)
break;
tmp->cp.inst.operand = 0x0ca1 | (i << 13);
tmp = find_copper_inst(tmp + 1, CI_MOVE(R_BPLCON3));
if (tmp == NULL)
break;
tmp->cp.inst.operand = 0x0ea1 | (i << 13);
}
if (tmp)
tmp = find_copper_inst(tmp + 1, CI_MOVE(R_BPLCON3));
if (tmp)
tmp->cp.inst.operand = 0x0ca1;
tmp = find_copper_inst(cp, CI_MOVE(R_FMODE));
tmp->cp.inst.operand = 0x8003;
tmp = find_copper_inst(cp, CI_MOVE(R_HTOTAL));
tmp->cp.inst.operand = AGA_htotal; /* 81/71/73/79? */
tmp = find_copper_inst(cp, CI_MOVE(R_HBSTRT));
tmp->cp.inst.operand = AGA_hbstrt; /* 0x0008 */
tmp = find_copper_inst(cp, CI_MOVE(R_HSSTRT));
tmp->cp.inst.operand = AGA_hsstrt; /* 0x000e */
tmp = find_copper_inst(cp, CI_MOVE(R_HSSTOP));
tmp->cp.inst.operand = AGA_hsstop; /* 0x001c */
tmp = find_copper_inst(cp, CI_MOVE(R_HBSTOP));
tmp->cp.inst.operand = AGA_hsstop; /* 0x001e */
tmp = find_copper_inst(cp, CI_MOVE(R_HCENTER));
tmp->cp.inst.operand = AGA_hcenter; /*AGA_htotal / 2 + AGA_hsstrt */
tmp = find_copper_inst(cp, CI_MOVE(R_VBSTRT));
tmp->cp.inst.operand = AGA_vbstrt; /* 0x0000 */
tmp = find_copper_inst(cp, CI_MOVE(R_VSSTRT));
tmp->cp.inst.operand = AGA_vsstrt; /* 0x016b / AGA_htotal */
tmp = find_copper_inst(cp, CI_MOVE(R_VSSTOP));
tmp->cp.inst.operand = AGA_vsstop; /* 0x02d6 / AGA_htotal */
tmp = find_copper_inst(cp, CI_MOVE(R_VBSTOP));
tmp->cp.inst.operand = AGA_vbstop; /* 0x0bd1 / AGA_htotal */
tmp = find_copper_inst(cp, CI_MOVE(R_VTOTAL));
tmp->cp.inst.operand = AGA_vtotal;
tmp = find_copper_inst(cp, CI_MOVE(R_BEAMCON0));
tmp->cp.inst.operand = aga_this_data->beamcon0;
#ifdef DEBUG
if (aga_enable & AGA_TRACE2)
printf(" beamcon0 %04x", tmp->cp.inst.operand);
#endif
tmp = find_copper_inst(cp, CI_MOVE(R_DIWHIGH));
tmp->cp.inst.operand = CALC_DIWHIGH(hstart, vstart, hstop, vstop);
#ifdef DEBUG
if (aga_enable & AGA_TRACE2)
printf(" diwhigh %04x>", tmp->cp.inst.operand);
#endif
#if 0
tmp->cp.inst.operand = (vstop & 0x0700) | ((hstop & 0x0100) << 5);
#endif
#ifdef DEBUG
if (aga_enable & AGA_TRACE2)
printf("%04x", tmp->cp.inst.operand);
#endif
tmp = find_copper_inst(cp, CI_MOVE(R_BPLCON0));
tmp->cp.inst.operand = aga_this_data->bplcon0 |
((depth & 0x7) << 12) | ((depth & 0x8) << 1);
#ifdef DEBUG
if (aga_enable & AGA_TRACE2)
printf(" bplcon0 %04x", tmp->cp.inst.operand);
#endif
tmp = find_copper_inst(cp, CI_MOVE(R_BPLCON1));
tmp->cp.inst.operand = con1;
#ifdef DEBUG
if (aga_enable & AGA_TRACE2)
printf(" bplcon1 %04x>0000\n", con1);
#endif
tmp = find_copper_inst(cp, CI_MOVE(R_DIWSTART));
tmp->cp.inst.operand = ((vstart & 0xff) << 8) | (hstart & 0xff);
#ifdef DEBUG
if (aga_enable & AGA_TRACE2)
printf(" diwstart %04x", tmp->cp.inst.operand);
#endif
tmp = find_copper_inst(cp, CI_MOVE(R_DIWSTOP));
tmp->cp.inst.operand = ((vstop & 0xff) << 8) | (hstop & 0xff);
#ifdef DEBUG
if (aga_enable & AGA_TRACE2)
printf(" diwstop %04x", tmp->cp.inst.operand);
#endif
tmp = find_copper_inst(cp, CI_MOVE(R_DDFSTART));
tmp->cp.inst.operand = ddfstart;
#ifdef DEBUG
if (aga_enable & AGA_TRACE2)
printf(" ddfstart %04x", tmp->cp.inst.operand);
#endif
tmp = find_copper_inst(cp, CI_MOVE(R_DDFSTOP));
tmp->cp.inst.operand = ddfstart + ddfwidth;
#ifdef DEBUG
if (aga_enable & AGA_TRACE2)
printf(" ddfstop %04x", tmp->cp.inst.operand);
#endif
tmp = find_copper_inst(cp, CI_MOVE(R_BPL0PTH));
for (i = 0, j = 0; i < depth; j += 2, i++) {
/* update the plane pointers */
tmp[j].cp.inst.operand = HIADDR(PREP_DMA_MEM(v->bitmap->plane[i]));
tmp[j + 1].cp.inst.operand = LOADDR(PREP_DMA_MEM(v->bitmap->plane[i]));
#ifdef DEBUG
if (aga_enable & AGA_TRACE2)
printf (" bpl%dpth %p", i, v->bitmap->plane[i]);
#endif
}
/* set mods correctly. */
tmp = find_copper_inst(cp, CI_MOVE(R_BPL1MOD));
tmp[0].cp.inst.operand = v->bitmap->row_mod;
tmp[1].cp.inst.operand = v->bitmap->row_mod;
#ifdef DEBUG
if (aga_enable & AGA_TRACE2)
printf(" bplxmod %04x\n", v->bitmap->row_mod);
#endif
/* set next pointers correctly */
tmp = find_copper_inst(cp, CI_MOVE(R_COP1LCH));
tmp[0].cp.inst.operand = HIADDR(PREP_DMA_MEM(aga_this_data->frames[F_STORE_LONG]));
tmp[1].cp.inst.operand = LOADDR(PREP_DMA_MEM(aga_this_data->frames[F_STORE_LONG]));
cp = aga_this_data->frames[F_LONG];
aga_this_data->frames[F_LONG] = aga_this_data->frames[F_STORE_LONG];
aga_this_data->frames[F_STORE_LONG] = cp;
vd->flags |= VF_DISPLAY;
cc_use_aga_colormap(v, vd->colormap);
}
cc_load_mode(aga_this);
#ifdef DEBUG
if (aga_enable & AGA_TRACE)
aga_enable |= AGA_TRACE2; /* XXXX */
#endif
}
/*
* SUPER72 Mode
*/
#if defined (GRF_SUPER72)
dmode_t *
cc_init_super72(void)
{
/* this function should only be called once. */
if (!super72_this && (custom.deniseid & 0xff) == 0xf8) {
u_short len = aga_copper_list_len;
super72_this = &super72_mode;
super72_this_data = &super72_mode_data;
memset(super72_this, 0, sizeof(dmode_t));
memset(super72_this_data, 0, sizeof(dmdata_t));
super72_this->name = "super72: superhires interlace";
super72_this->nominal_size.width = 800;
super72_this->nominal_size.height = 600;
super72_this_data->max_size.width = 848;
super72_this_data->max_size.height = 614;
super72_this_data->min_size.width = 320;
super72_this_data->min_size.height = 484;
super72_this_data->min_depth = 1;
super72_this_data->max_depth = 8;
super72_this->data = super72_this_data;
super72_this->get_monitor = cc_get_monitor;
super72_this->alloc_view = cc_alloc_view;
super72_this->get_current_view = cc_get_current_view;
super72_this_data->use_colormap = cc_use_aga_colormap;
super72_this_data->get_colormap = cc_get_colormap;
super72_this_data->alloc_colormap = cc_alloc_aga_colormap;
super72_this_data->display_view = display_super72_view;
super72_this_data->monitor = cc_monitor;
super72_this_data->flags |= DMF_INTERLACE;
super72_this_data->frames = super72_frames; /* MAY NEED TO CHANGE COPLIST */
super72_this_data->frames[F_LACE_LONG] =
alloc_chipmem(aga_copper_list_size * F_LACE_TOTAL);
if (!super72_this_data->frames[F_LACE_LONG]) {
panic("couldn't get chipmem for copper list");
}
super72_this_data->frames[F_LACE_SHORT] =
&super72_this_data->frames[F_LACE_LONG][len];
super72_this_data->frames[F_LACE_STORE_LONG] =
&super72_this_data->frames[F_LACE_SHORT][len];
super72_this_data->frames[F_LACE_STORE_SHORT] =
&super72_this_data->frames[F_LACE_STORE_LONG][len];
bcopy(aga_copper_list,
super72_this_data->frames[F_LACE_STORE_LONG],
aga_copper_list_size);
bcopy(aga_copper_list,
super72_this_data->frames[F_LACE_STORE_SHORT],
aga_copper_list_size);
bcopy(aga_copper_list,
super72_this_data->frames[F_LACE_LONG],
aga_copper_list_size);
bcopy(aga_copper_list,
super72_this_data->frames[F_LACE_SHORT],
aga_copper_list_size);
super72_this_data->bplcon0 = 0x0244 | USE_CON3; /* color
* composite enable,
* shres
* lace. */
#if 0 /* patchable variables for testing */
super72_this_data->std_start_x = 0x6c;
super72_this_data->std_start_y = 0x1b;
#endif
super72_this_data->vbl_handler =
(vbl_handler_func *) cc_lace_mode_vbl_handler;
super72_this_data->beamcon0 = (SPECIAL_BEAMCON ^ VSYNCTRUE) |
DISPLAYPAL | 0x4000;
super72_this_data->beamcon0 = 0x5bb0;
LIST_INSERT_HEAD(&MDATA(cc_monitor)->modes, super72_this, link);
}
return (super72_this);
}
/* Super72 83Hz hack monitor values */
/*int super72_htotal = 0x083;
int super72_hsstrt = 0x00d;
int super72_hsstop = 0x01b;
int super72_hbstrt = 0x001;
int super72_hbstop = 0x021;
int super72_vtotal = 0x148;
int super72_vsstrt = 0x2d5;
int super72_vsstop = 0x3ca;
int super72_vbstrt = 0x000;
int super72_vbstop = 0xfdc;
int super72_hcenter = 0x04e;
*/
/* Super72 standard monitor values */
int super72_htotal = 154; /* 0x099*/
int super72_hsstrt = 17; /* 0x01c*/
int super72_hsstop = 27; /* 0x038*/
int super72_hbstrt = 154; /* 0x008*/
int super72_hbstop = 55; /* 0x01e*/
int super72_vtotal = 328; /* 0x147*/
int super72_vsstrt = 11; /* 0x030*/
int super72_vsstop = 18; /* 0x033*/
int super72_vbstrt = 327; /* 0x000*/
int super72_vbstop = 27; /* 0x019*/
int super72_hcenter = 94; /* 0x057*/
int super72_startx = 100;
int super72_starty = 27;
void
display_super72_view(view_t *v)
{
if (super72_this_data->current_view != v) {
vdata_t *vd = VDATA(v);
cop_t *cp = super72_this_data->frames[F_LACE_STORE_LONG], *tmp;
int depth = v->bitmap->depth, i;
int hstart, hstop, vstart, vstop, j;
int x, y, w = v->display.width, h = v->display.height;
u_short ddfstart, ddfwidth, con1;
/* round down to nearest even width */
/* w &= 0xfffe; */
/* calculate datafetch width. */
ddfwidth = ((v->bitmap->bytes_per_row >> 1) - 4) << 1;
/* This will center any overscanned display */
/* and allow user to modify. */
x = (v->display.x >> 1) + super72_startx - ((w - 800) >> 3);
y = v->display.y + super72_starty - ((h - 600) >> 2);
hstart = x;
hstop = x + (w >> 2);
vstart = y;
vstop = y + (h >> 1);
ddfstart = (hstart >> 1) - 16;
ddfstart = (hstart << 2) - 4;
con1 = ddfstart & 63;
ddfstart = (ddfstart & -64) - 64;
ddfwidth = ((w + 64 - 1) & -64) - 64;
ddfwidth = ddfwidth >> 3;
ddfstart = ddfstart >> 3;
super72_hbstrt = ((x << 2) + w + 4) >> 3;
super72_hbstop = (hstart + 1) >> 1;
super72_vbstrt = vstop;
super72_vbstop = vstart - 2;
if ((hstop >> 1) > super72_htotal) {
int d;
d = (hstop >> 1) - super72_htotal;
ddfstart -= d;
hstart -= d << 1;
hstop -= d << 1;
}
if (vstop >= super72_vtotal) {
int d;
d = (vstop - super72_vtotal + 1);
vstart -= d;
vstop -= d;
}
con1 = ((con1 >> 2) & 0x000f) | /* PF1H2-PF1H5 */
((con1 << 8) & 0x0300) | /* PF1H0-PF1H2 */
((con1 << 4) & 0x0c00); /* PF1H6-PF1H7 */
con1 |= con1 << 4; /* PF2H2-PF2H7 */
if (super72_this_data->current_view) {
VDATA(super72_this_data->current_view)->flags &=
~VF_DISPLAY; /* mark as no longer */
/* displayed. */
}
super72_this_data->current_view = v;
cp = super72_this_data->frames[F_LACE_STORE_LONG];
tmp = find_copper_inst(cp, CI_MOVE(R_FMODE));
tmp->cp.inst.operand = 0x8003;
tmp = find_copper_inst(cp, CI_MOVE(R_HTOTAL));
tmp->cp.inst.operand = super72_htotal;
tmp = find_copper_inst(cp, CI_MOVE(R_HBSTRT));
tmp->cp.inst.operand = super72_hbstrt;
tmp = find_copper_inst(cp, CI_MOVE(R_HSSTRT));
tmp->cp.inst.operand = super72_hsstrt;
tmp = find_copper_inst(cp, CI_MOVE(R_HSSTOP));
tmp->cp.inst.operand = super72_hsstop;
tmp = find_copper_inst(cp, CI_MOVE(R_HBSTOP));
tmp->cp.inst.operand = super72_hbstop;
tmp = find_copper_inst(cp, CI_MOVE(R_HCENTER));
tmp->cp.inst.operand = super72_hcenter;
tmp = find_copper_inst(cp, CI_MOVE(R_VBSTRT));
tmp->cp.inst.operand = super72_vbstrt;
tmp = find_copper_inst(cp, CI_MOVE(R_VSSTRT));
tmp->cp.inst.operand = super72_vsstrt;
tmp = find_copper_inst(cp, CI_MOVE(R_VSSTOP));
tmp->cp.inst.operand = super72_vsstop;
tmp = find_copper_inst(cp, CI_MOVE(R_VBSTOP));
tmp->cp.inst.operand = super72_vbstop;
tmp = find_copper_inst(cp, CI_MOVE(R_VTOTAL));
tmp->cp.inst.operand = super72_vtotal;
tmp = find_copper_inst(cp, CI_MOVE(R_BEAMCON0));
tmp->cp.inst.operand = super72_this_data->beamcon0;
tmp = find_copper_inst(cp, CI_MOVE(R_DIWHIGH));
tmp->cp.inst.operand =
CALC_DIWHIGH(hstart, vstart, hstop, vstop);
tmp = find_copper_inst(cp, CI_MOVE(R_BPLCON0));
tmp->cp.inst.operand = super72_this_data->bplcon0 |
((depth & 0x7) << 12) | ((depth & 0x8) << 1);
tmp = find_copper_inst(cp, CI_MOVE(R_BPLCON1));
tmp->cp.inst.operand = con1;
tmp = find_copper_inst(cp, CI_MOVE(R_DIWSTART));
tmp->cp.inst.operand = ((vstart & 0xff) << 8) | (hstart & 0xff);
tmp = find_copper_inst(cp, CI_MOVE(R_DIWSTOP));
tmp->cp.inst.operand = ((vstop & 0xff) << 8) | (hstop & 0xff);
tmp = find_copper_inst(cp, CI_MOVE(R_DDFSTART));
tmp->cp.inst.operand = ddfstart;
tmp = find_copper_inst(cp, CI_MOVE(R_DDFSTOP));
tmp->cp.inst.operand = ddfstart + ddfwidth;
tmp = find_copper_inst(cp, CI_MOVE(R_BPL0PTH));
for (i = 0, j = 0; i < depth; j += 2, i++) {
/* update the plane pointers */
tmp[j].cp.inst.operand =
HIADDR(PREP_DMA_MEM(v->bitmap->plane[i]));
tmp[j + 1].cp.inst.operand =
LOADDR(PREP_DMA_MEM(v->bitmap->plane[i]));
}
/* set mods correctly. */
tmp = find_copper_inst(cp, CI_MOVE(R_BPL1MOD));
tmp[0].cp.inst.operand = v->bitmap->bytes_per_row +
v->bitmap->row_mod;
tmp[1].cp.inst.operand = v->bitmap->bytes_per_row +
v->bitmap->row_mod;
/* set next pointers correctly */
tmp = find_copper_inst(cp, CI_MOVE(R_COP1LCH));
tmp[0].cp.inst.operand =
HIADDR(PREP_DMA_MEM(super72_this_data->frames[F_LACE_STORE_SHORT]));
tmp[1].cp.inst.operand =
LOADDR(PREP_DMA_MEM(super72_this_data->frames[F_LACE_STORE_SHORT]));
bcopy(super72_this_data->frames[F_LACE_STORE_LONG],
super72_this_data->frames[F_LACE_STORE_SHORT],
aga_copper_list_size);
/* these are the only ones that are different from long frame. */
cp = super72_this_data->frames[F_LACE_STORE_SHORT];
tmp = find_copper_inst(cp, CI_MOVE(R_BPL0PTH));
for (i = 0, j = 0; i < depth; j += 2, i++) {
u_short mod = v->bitmap->bytes_per_row +
v->bitmap->row_mod;
/* update plane pointers. high and low. */
tmp[j].cp.inst.operand =
HIADDR(PREP_DMA_MEM(&v->bitmap->plane[i][mod]));
tmp[j + 1].cp.inst.operand =
LOADDR(PREP_DMA_MEM(&v->bitmap->plane[i][mod]));
}
/* set next pointers correctly */
tmp = find_copper_inst(cp, CI_MOVE(R_COP1LCH));
tmp[0].cp.inst.operand =
HIADDR(PREP_DMA_MEM(super72_this_data->frames[F_LACE_STORE_LONG]));
tmp[1].cp.inst.operand =
LOADDR(PREP_DMA_MEM(super72_this_data->frames[F_LACE_STORE_LONG]));
cp = super72_this_data->frames[F_LACE_LONG];
super72_this_data->frames[F_LACE_LONG] =
super72_this_data->frames[F_LACE_STORE_LONG];
super72_this_data->frames[F_LACE_STORE_LONG] = cp;
cp = super72_this_data->frames[F_LACE_SHORT];
super72_this_data->frames[F_LACE_SHORT] =
super72_this_data->frames[F_LACE_STORE_SHORT];
super72_this_data->frames[F_LACE_STORE_SHORT] = cp;
vd->flags |= VF_DISPLAY;
cc_use_aga_colormap(v, vd->colormap);
}
cc_load_mode(super72_this);
}
#endif /* GRF_SUPER72 */
#endif /* GRF_AGA */
#endif /* GRF_NTSC */
/*
* PAL modes.
*/
#if defined (GRF_PAL)
dmode_t *
cc_init_pal_hires(void)
{
/* this function should only be called once. */
if (!ph_this) {
u_short len = std_copper_list_len;
ph_this = &pal_hires_mode;
ph_this_data = &pal_hires_mode_data;
memset(ph_this, 0, sizeof(dmode_t));
memset(ph_this_data, 0, sizeof(dmdata_t));
ph_this->name = "pal: hires";
ph_this->nominal_size.width = 640;
ph_this->nominal_size.height = 256;
ph_this_data->max_size.width = 724;
ph_this_data->max_size.height = 289;
ph_this_data->min_size.width = 320;
ph_this_data->min_size.height = 244;
ph_this_data->min_depth = 1;
ph_this_data->max_depth = 4;
ph_this->data = ph_this_data;
ph_this->get_monitor = cc_get_monitor;
ph_this->alloc_view = cc_alloc_view;
ph_this->get_current_view = cc_get_current_view;
ph_this_data->use_colormap = cc_use_colormap;
ph_this_data->get_colormap = cc_get_colormap;
ph_this_data->alloc_colormap = cc_alloc_colormap;
ph_this_data->display_view = display_pal_hires_view;
ph_this_data->monitor = cc_monitor;
ph_this_data->frames = pal_hires_frames;
ph_this_data->frames[F_LONG] = alloc_chipmem(std_copper_list_size * F_TOTAL);
if (!ph_this_data->frames[F_LONG]) {
panic("couldn't get chipmem for copper list");
}
ph_this_data->frames[F_STORE_LONG] = &ph_this_data->frames[F_LONG][len];
memcpy(ph_this_data->frames[F_STORE_LONG], std_copper_list, std_copper_list_size);
memcpy(ph_this_data->frames[F_LONG], std_copper_list, std_copper_list_size);
ph_this_data->bplcon0 = 0x8200 | USE_CON3; /* pal_hires, color
* composite enable,
* lace. */
ph_this_data->std_start_x = STANDARD_VIEW_X;
ph_this_data->std_start_y = STANDARD_VIEW_Y;
ph_this_data->vbl_handler = (vbl_handler_func *) cc_mode_vbl_handler;
#if defined (GRF_ECS) || defined (GRF_AGA)
ph_this_data->beamcon0 = STANDARD_PAL_BEAMCON;
#endif
LIST_INSERT_HEAD(&MDATA(cc_monitor)->modes, ph_this, link);
}
return (ph_this);
}
void
display_pal_hires_view(view_t *v)
{
if (ph_this_data->current_view != v) {
vdata_t *vd = VDATA(v);
cop_t *cp = ph_this_data->frames[F_STORE_LONG], *tmp;
int depth = v->bitmap->depth, i;
int hstart, hstop, vstart, vstop, j;
int x, y, w = v->display.width, h = v->display.height;
u_short ddfstart, ddfwidth, con1;
/* round down to nearest even width */
/* w &= 0xfffe; */
/* calculate datafetch width. */
ddfwidth = ((v->bitmap->bytes_per_row >> 1) - 2) << 2;
/* This will center the any overscanned display */
/* and allow user to modify. */
x = v->display.x + ph_this_data->std_start_x - ((w - 640) >> 2);
y = v->display.y + ph_this_data->std_start_y - ((h - 256) >> 1);
if (y & 1)
y--;
if (!(x & 1))
x--;
hstart = x;
hstop = x + (w >> 1);
vstart = y;
vstop = y + h;
ddfstart = (hstart - 9) >> 1;
/* check for hardware limits, AGA may allow more..? */
/* anyone got a 4000 I can borrow :^) -ch */
if ((ddfstart & 0xfffc) + ddfwidth > 0xd8) {
int d = 0;
/* XXX anyone know the equality properties of
* intermixed logial AND's */
/* XXX and arithmetic operators? */
while (((ddfstart & 0xfffc) + ddfwidth - d) > 0xd8) {
d++;
}
ddfstart -= d;
hstart -= d << 1;
hstop -= d << 1;
}
/* correct the datafetch to proper limits. */
/* delay the actual display of the data until we need it. */
ddfstart &= 0xfffc;
con1 = ((hstart - 9) - (ddfstart << 1)) | (((hstart - 9) - (ddfstart << 1)) << 4);
if (ph_this_data->current_view) {
VDATA(ph_this_data->current_view)->flags &= ~VF_DISPLAY; /* mark as no longer */
/* displayed. */
}
ph_this_data->current_view = v;
cp = ph_this_data->frames[F_STORE_LONG];
#if defined (GRF_ECS) || defined (GRF_AGA)
#if defined (GRF_AGA)
tmp = find_copper_inst(cp, CI_MOVE(R_FMODE));
tmp->cp.inst.operand = 0;
#endif
tmp = find_copper_inst(cp, CI_MOVE(R_BEAMCON0));
tmp->cp.inst.operand = ph_this_data->beamcon0;
tmp = find_copper_inst(cp, CI_MOVE(R_DIWHIGH));
tmp->cp.inst.operand = CALC_DIWHIGH(hstart, vstart, hstop, vstop);
#endif /* ECS */
tmp = find_copper_inst(cp, CI_MOVE(R_BPLCON0));
tmp->cp.inst.operand = ph_this_data->bplcon0 | ((depth & 0x7) << 12);
tmp = find_copper_inst(cp, CI_MOVE(R_BPLCON1));
tmp->cp.inst.operand = con1;
tmp = find_copper_inst(cp, CI_MOVE(R_DIWSTART));
tmp->cp.inst.operand = ((vstart & 0xff) << 8) | (hstart & 0xff);
tmp = find_copper_inst(cp, CI_MOVE(R_DIWSTOP));
tmp->cp.inst.operand = ((vstop & 0xff) << 8) | (hstop & 0xff);
tmp = find_copper_inst(cp, CI_MOVE(R_DDFSTART));
tmp->cp.inst.operand = ddfstart;
tmp = find_copper_inst(cp, CI_MOVE(R_DDFSTOP));
tmp->cp.inst.operand = ddfstart + ddfwidth;
tmp = find_copper_inst(cp, CI_MOVE(R_BPL0PTH));
for (i = 0, j = 0; i < depth; j += 2, i++) {
/* update the plane pointers */
tmp[j].cp.inst.operand = HIADDR(PREP_DMA_MEM(v->bitmap->plane[i]));
tmp[j + 1].cp.inst.operand = LOADDR(PREP_DMA_MEM(v->bitmap->plane[i]));
}
/* set mods correctly. */
tmp = find_copper_inst(cp, CI_MOVE(R_BPL1MOD));
tmp[0].cp.inst.operand = v->bitmap->row_mod;
tmp[1].cp.inst.operand = v->bitmap->row_mod;
/* set next pointers correctly */
tmp = find_copper_inst(cp, CI_MOVE(R_COP1LCH));
tmp[0].cp.inst.operand = HIADDR(PREP_DMA_MEM(ph_this_data->frames[F_STORE_LONG]));
tmp[1].cp.inst.operand = LOADDR(PREP_DMA_MEM(ph_this_data->frames[F_STORE_LONG]));
cp = ph_this_data->frames[F_LONG];
ph_this_data->frames[F_LONG] = ph_this_data->frames[F_STORE_LONG];
ph_this_data->frames[F_STORE_LONG] = cp;
vd->flags |= VF_DISPLAY;
cc_use_colormap(v, vd->colormap);
}
cc_load_mode(ph_this);
}
dmode_t *
cc_init_pal_hires_lace(void)
{
/* this function should only be called once. */
if (!phl_this) {
u_short len = std_copper_list_len;
phl_this = &pal_hires_lace_mode;
phl_this_data = &pal_hires_lace_mode_data;
memset(phl_this, 0, sizeof(dmode_t));
memset(phl_this_data, 0, sizeof(dmdata_t));
phl_this->name = "pal: hires interlace";
phl_this->nominal_size.width = 640;
phl_this->nominal_size.height = 512;
phl_this_data->max_size.width = 724;
phl_this_data->max_size.height = 578;
phl_this_data->min_size.width = 320;
phl_this_data->min_size.height = 484;
phl_this_data->min_depth = 1;
phl_this_data->max_depth = 4;
phl_this->data = phl_this_data;
phl_this->get_monitor = cc_get_monitor;
phl_this->alloc_view = cc_alloc_view;
phl_this->get_current_view = cc_get_current_view;
phl_this_data->use_colormap = cc_use_colormap;
phl_this_data->get_colormap = cc_get_colormap;
phl_this_data->alloc_colormap = cc_alloc_colormap;
phl_this_data->display_view = display_pal_hires_lace_view;
phl_this_data->monitor = cc_monitor;
phl_this_data->flags |= DMF_INTERLACE;
phl_this_data->frames = pal_hires_lace_frames;
phl_this_data->frames[F_LACE_LONG] = alloc_chipmem(std_copper_list_size * F_LACE_TOTAL);
if (!phl_this_data->frames[F_LACE_LONG]) {
panic("couldn't get chipmem for copper list");
}
phl_this_data->frames[F_LACE_SHORT] = &phl_this_data->frames[F_LACE_LONG][len];
phl_this_data->frames[F_LACE_STORE_LONG] = &phl_this_data->frames[F_LACE_SHORT][len];
phl_this_data->frames[F_LACE_STORE_SHORT] = &phl_this_data->frames[F_LACE_STORE_LONG][len];
memcpy(phl_this_data->frames[F_LACE_STORE_LONG], std_copper_list, std_copper_list_size);
memcpy(phl_this_data->frames[F_LACE_STORE_SHORT], std_copper_list, std_copper_list_size);
memcpy(phl_this_data->frames[F_LACE_LONG], std_copper_list, std_copper_list_size);
memcpy(phl_this_data->frames[F_LACE_SHORT], std_copper_list, std_copper_list_size);
phl_this_data->bplcon0 = 0x8204 | USE_CON3; /* hires, color
* composite enable,
* lace. */
phl_this_data->std_start_x = STANDARD_VIEW_X;
phl_this_data->std_start_y = STANDARD_VIEW_Y;
phl_this_data->vbl_handler = (vbl_handler_func *) cc_lace_mode_vbl_handler;
#if defined (GRF_ECS) || defined (GRF_AGA)
phl_this_data->beamcon0 = STANDARD_PAL_BEAMCON;
#endif
LIST_INSERT_HEAD(&MDATA(cc_monitor)->modes, phl_this, link);
}
return (phl_this);
}
void
display_pal_hires_lace_view(view_t *v)
{
if (phl_this_data->current_view != v) {
vdata_t *vd = VDATA(v);
cop_t *cp = phl_this_data->frames[F_LACE_STORE_LONG], *tmp;
int depth = v->bitmap->depth, i;
int hstart, hstop, vstart, vstop, j;
int x, y, w = v->display.width, h = v->display.height;
u_short ddfstart, ddfwidth, con1;
/* round down to nearest even width */
/* w &= 0xfffe; */
/* calculate datafetch width. */
ddfwidth = ((v->bitmap->bytes_per_row >> 1) - 2) << 2;
/* This will center the any overscanned display */
/* and allow user to modify. */
x = v->display.x + phl_this_data->std_start_x - ((w - 640) >> 2);
y = v->display.y + phl_this_data->std_start_y - ((h - 512) >> 2);
if (y & 1)
y--;
if (!(x & 1))
x--;
hstart = x;
hstop = x + (w >> 1);
vstart = y;
vstop = y + (h >> 1);
ddfstart = (hstart - 9) >> 1;
/* check for hardware limits, AGA may allow more..? */
/* anyone got a 4000 I can borrow :^) -ch */
if ((ddfstart & 0xfffc) + ddfwidth > 0xd8) {
int d = 0;
/* XXX anyone know the equality properties of
* intermixed logial AND's */
/* XXX and arithmetic operators? */
while (((ddfstart & 0xfffc) + ddfwidth - d) > 0xd8) {
d++;
}
ddfstart -= d;
hstart -= d << 1;
hstop -= d << 1;
}
/* correct the datafetch to proper limits. */
/* delay the actual display of the data until we need it. */
ddfstart &= 0xfffc;
con1 = ((hstart - 9) - (ddfstart << 1)) | (((hstart - 9) - (ddfstart << 1)) << 4);
if (phl_this_data->current_view) {
VDATA(phl_this_data->current_view)->flags &= ~VF_DISPLAY; /* mark as no longer */
/* displayed. */
}
phl_this_data->current_view = v;
cp = phl_this_data->frames[F_LACE_STORE_LONG];
#if defined (GRF_ECS) || defined (GRF_AGA)
#if defined (GRF_AGA)
tmp = find_copper_inst(cp, CI_MOVE(R_FMODE));
tmp->cp.inst.operand = 0;
#endif
tmp = find_copper_inst(cp, CI_MOVE(R_BEAMCON0));
tmp->cp.inst.operand = phl_this_data->beamcon0;
tmp = find_copper_inst(cp, CI_MOVE(R_DIWHIGH));
tmp->cp.inst.operand = CALC_DIWHIGH(hstart, vstart, hstop, vstop);
#endif /* ECS */
tmp = find_copper_inst(cp, CI_MOVE(R_BPLCON0));
tmp->cp.inst.operand = phl_this_data->bplcon0 | ((depth & 0x7) << 12);
tmp = find_copper_inst(cp, CI_MOVE(R_BPLCON1));
tmp->cp.inst.operand = con1;
tmp = find_copper_inst(cp, CI_MOVE(R_DIWSTART));
tmp->cp.inst.operand = ((vstart & 0xff) << 8) | (hstart & 0xff);
tmp = find_copper_inst(cp, CI_MOVE(R_DIWSTOP));
tmp->cp.inst.operand = ((vstop & 0xff) << 8) | (hstop & 0xff);
tmp = find_copper_inst(cp, CI_MOVE(R_DDFSTART));
tmp->cp.inst.operand = ddfstart;
tmp = find_copper_inst(cp, CI_MOVE(R_DDFSTOP));
tmp->cp.inst.operand = ddfstart + ddfwidth;
tmp = find_copper_inst(cp, CI_MOVE(R_BPL0PTH));
for (i = 0, j = 0; i < depth; j += 2, i++) {
/* update the plane pointers */
tmp[j].cp.inst.operand = HIADDR(PREP_DMA_MEM(v->bitmap->plane[i]));
tmp[j + 1].cp.inst.operand = LOADDR(PREP_DMA_MEM(v->bitmap->plane[i]));
}
/* set mods correctly. */
tmp = find_copper_inst(cp, CI_MOVE(R_BPL1MOD));
tmp[0].cp.inst.operand = v->bitmap->bytes_per_row + v->bitmap->row_mod;
tmp[1].cp.inst.operand = v->bitmap->bytes_per_row + v->bitmap->row_mod;
/* set next pointers correctly */
tmp = find_copper_inst(cp, CI_MOVE(R_COP1LCH));
tmp[0].cp.inst.operand = HIADDR(PREP_DMA_MEM(phl_this_data->frames[F_LACE_STORE_SHORT]));
tmp[1].cp.inst.operand = LOADDR(PREP_DMA_MEM(phl_this_data->frames[F_LACE_STORE_SHORT]));
memcpy(phl_this_data->frames[F_LACE_STORE_SHORT], phl_this_data->frames[F_LACE_STORE_LONG], std_copper_list_size);
/* these are the only ones that are different from long frame. */
cp = phl_this_data->frames[F_LACE_STORE_SHORT];
tmp = find_copper_inst(cp, CI_MOVE(R_BPL0PTH));
for (i = 0, j = 0; i < depth; j += 2, i++) {
u_short mod = v->bitmap->bytes_per_row + v->bitmap->row_mod;
/* update plane pointers. high and low. */
tmp[j].cp.inst.operand = HIADDR(PREP_DMA_MEM(&v->bitmap->plane[i][mod]));
tmp[j + 1].cp.inst.operand = LOADDR(PREP_DMA_MEM(&v->bitmap->plane[i][mod]));
}
/* set next pointers correctly */
tmp = find_copper_inst(cp, CI_MOVE(R_COP1LCH));
tmp[0].cp.inst.operand = HIADDR(PREP_DMA_MEM(phl_this_data->frames[F_LACE_STORE_LONG]));
tmp[1].cp.inst.operand = LOADDR(PREP_DMA_MEM(phl_this_data->frames[F_LACE_STORE_LONG]));
cp = phl_this_data->frames[F_LACE_LONG];
phl_this_data->frames[F_LACE_LONG] = phl_this_data->frames[F_LACE_STORE_LONG];
phl_this_data->frames[F_LACE_STORE_LONG] = cp;
cp = phl_this_data->frames[F_LACE_SHORT];
phl_this_data->frames[F_LACE_SHORT] = phl_this_data->frames[F_LACE_STORE_SHORT];
phl_this_data->frames[F_LACE_STORE_SHORT] = cp;
vd->flags |= VF_DISPLAY;
cc_use_colormap(v, vd->colormap);
}
cc_load_mode(phl_this);
}
#if defined (GRF_A2024)
dmode_t *
cc_init_pal_hires_dlace(void)
{
/* this function should only be called once. */
if (!phdl_this) {
u_short len = std_dlace_copper_list_len;
phdl_this = &pal_hires_dlace_mode;
phdl_this_data = &pal_hires_dlace_mode_data;
memset(phdl_this, 0, sizeof(dmode_t));
memset(phdl_this_data, 0, sizeof(dmdata_t));
phdl_this->name = "pal: hires double interlace";
phdl_this->nominal_size.width = 640;
phdl_this->nominal_size.height = 1024;
phdl_this_data->max_size.width = 724;
phdl_this_data->max_size.height = 1024;
phdl_this_data->min_size.width = 320;
phdl_this_data->min_size.height = 512;
phdl_this_data->min_depth = 1;
phdl_this_data->max_depth = 2;
phdl_this->data = phdl_this_data;
phdl_this->get_monitor = cc_get_monitor;
phdl_this->alloc_view = cc_alloc_view;
phdl_this->get_current_view = cc_get_current_view;
phdl_this_data->use_colormap = cc_a2024_use_colormap;
phdl_this_data->get_colormap = cc_a2024_get_colormap;
phdl_this_data->alloc_colormap = cc_a2024_alloc_colormap;
phdl_this_data->display_view = display_pal_hires_dlace_view;
phdl_this_data->monitor = cc_monitor;
phdl_this_data->flags |= DMF_INTERLACE;
phdl_this_data->frames = pal_hires_dlace_frames;
phdl_this_data->frames[F_LACE_LONG] = alloc_chipmem(std_dlace_copper_list_size * F_LACE_TOTAL);
if (!phdl_this_data->frames[F_LACE_LONG]) {
panic("couldn't get chipmem for copper list");
}
phdl_this_data->frames[F_LACE_SHORT] = &phdl_this_data->frames[F_LACE_LONG][len];
phdl_this_data->frames[F_LACE_STORE_LONG] = &phdl_this_data->frames[F_LACE_SHORT][len];
phdl_this_data->frames[F_LACE_STORE_SHORT] = &phdl_this_data->frames[F_LACE_STORE_LONG][len];
memcpy(phdl_this_data->frames[F_LACE_STORE_LONG], std_dlace_copper_list, std_dlace_copper_list_size);
memcpy(phdl_this_data->frames[F_LACE_STORE_SHORT], std_dlace_copper_list, std_dlace_copper_list_size);
memcpy(phdl_this_data->frames[F_LACE_LONG], std_dlace_copper_list, std_dlace_copper_list_size);
memcpy(phdl_this_data->frames[F_LACE_SHORT], std_dlace_copper_list, std_dlace_copper_list_size);
phdl_this_data->bplcon0 = 0x8204 | USE_CON3; /* hires, color
* composite enable,
* dlace. */
phdl_this_data->std_start_x = STANDARD_VIEW_X;
phdl_this_data->std_start_y = STANDARD_VIEW_Y;
phdl_this_data->vbl_handler = (vbl_handler_func *) cc_lace_mode_vbl_handler;
#if defined (GRF_ECS) || defined (GRF_AGA)
phdl_this_data->beamcon0 = STANDARD_PAL_BEAMCON;
#endif
LIST_INSERT_HEAD(&MDATA(cc_monitor)->modes, phdl_this, link);
}
return (phdl_this);
}
void
display_pal_hires_dlace_view(view_t *v)
{
if (phdl_this_data->current_view != v) {
vdata_t *vd = VDATA(v);
cop_t *cp = phdl_this_data->frames[F_LACE_STORE_LONG], *tmp;
int depth = v->bitmap->depth;
int hstart, hstop, vstart, vstop;
int x, y, w = v->display.width, h = v->display.height;
u_short ddfstart, ddfwidth, con1;
u_short mod1l, mod2l;
/* round down to nearest even width */
/* w &= 0xfffe; */
/* calculate datafetch width. */
ddfwidth = ((v->bitmap->bytes_per_row >> 1) - 2) << 2;
/* This will center the any overscanned display */
/* and allow user to modify. */
x = v->display.x + phdl_this_data->std_start_x - ((w - 640) >> 2);
y = v->display.y + phdl_this_data->std_start_y - ((h - 1024) >> 3);
if (y & 1)
y--;
if (!(x & 1))
x--;
hstart = x;
hstop = x + (w >> 1);
vstart = y;
vstop = y + (h >> 2);
ddfstart = (hstart - 9) >> 1;
/* check for hardware limits, AGA may allow more..? */
/* anyone got a 4000 I can borrow :^) -ch */
if ((ddfstart & 0xfffc) + ddfwidth > 0xd8) {
int d = 0;
/* XXX anyone know the equality properties of
* intermixed logial AND's */
/* XXX and arithmetic operators? */
while (((ddfstart & 0xfffc) + ddfwidth - d) > 0xd8) {
d++;
}
ddfstart -= d;
hstart -= d << 1;
hstop -= d << 1;
}
/* correct the datafetch to proper limits. */
/* delay the actual display of the data until we need it. */
ddfstart &= 0xfffc;
con1 = ((hstart - 9) - (ddfstart << 1)) | (((hstart - 9) - (ddfstart << 1)) << 4);
if (phdl_this_data->current_view) {
VDATA(phdl_this_data->current_view)->flags &= ~VF_DISPLAY; /* mark as no longer */
/* displayed. */
}
phdl_this_data->current_view = v;
cp = phdl_this_data->frames[F_LACE_STORE_LONG];
#if defined (GRF_ECS) || defined (GRF_AGA)
#if defined (GRF_AGA)
tmp = find_copper_inst(cp, CI_MOVE(R_FMODE));
tmp->cp.inst.operand = 0;
#endif
tmp = find_copper_inst(cp, CI_MOVE(R_BEAMCON0));
tmp->cp.inst.operand = phdl_this_data->beamcon0;
tmp = find_copper_inst(cp, CI_MOVE(R_DIWHIGH));
tmp->cp.inst.operand = CALC_DIWHIGH(hstart, vstart, hstop, vstop);
#endif /* ECS */
tmp = find_copper_inst(cp, CI_MOVE(R_BPLCON0));
tmp->cp.inst.operand = phdl_this_data->bplcon0 | ((depth & 0x7) << 13); /* times two. */
tmp = find_copper_inst(cp, CI_MOVE(R_BPLCON1));
tmp->cp.inst.operand = con1;
tmp = find_copper_inst(cp, CI_MOVE(R_DIWSTART));
tmp->cp.inst.operand = ((vstart & 0xff) << 8) | (hstart & 0xff);
tmp = find_copper_inst(cp, CI_MOVE(R_DIWSTOP));
tmp->cp.inst.operand = ((vstop & 0xff) << 8) | (hstop & 0xff);
tmp = find_copper_inst(cp, CI_MOVE(R_DDFSTART));
tmp->cp.inst.operand = ddfstart;
tmp = find_copper_inst(cp, CI_MOVE(R_DDFSTOP));
tmp->cp.inst.operand = ddfstart + ddfwidth;
mod1l = v->bitmap->bytes_per_row + v->bitmap->row_mod;
mod2l = mod1l << 1;
tmp = find_copper_inst(cp, CI_MOVE(R_BPL0PTH));
tmp[0].cp.inst.operand = HIADDR(PREP_DMA_MEM(&v->bitmap->plane[0][0])); /* update plane
* pointers. */
tmp[1].cp.inst.operand = LOADDR(PREP_DMA_MEM(&v->bitmap->plane[0][0])); /* high and low. */
tmp[2].cp.inst.operand = HIADDR(PREP_DMA_MEM(&v->bitmap->plane[0][mod1l])); /* update plane
* pointers. */
tmp[3].cp.inst.operand = LOADDR(PREP_DMA_MEM(&v->bitmap->plane[0][mod1l])); /* high and low. */
if (depth == 2) {
tmp[4].cp.inst.operand = HIADDR(PREP_DMA_MEM(&v->bitmap->plane[1][0])); /* update plane
* pointers. */
tmp[5].cp.inst.operand = LOADDR(PREP_DMA_MEM(&v->bitmap->plane[1][0])); /* high and low. */
tmp[6].cp.inst.operand = HIADDR(PREP_DMA_MEM(&v->bitmap->plane[1][mod1l])); /* update plane
* pointers. */
tmp[7].cp.inst.operand = LOADDR(PREP_DMA_MEM(&v->bitmap->plane[1][mod1l])); /* high and low. */
}
/* set mods correctly. */
tmp = find_copper_inst(cp, CI_MOVE(R_BPL1MOD));
tmp[0].cp.inst.operand = mod2l + mod1l;
tmp[1].cp.inst.operand = mod2l + mod1l;
/* set next pointers correctly */
tmp = find_copper_inst(cp, CI_MOVE(R_COP1LCH));
tmp[0].cp.inst.operand = HIADDR(PREP_DMA_MEM(phdl_this_data->frames[F_LACE_STORE_SHORT]));
tmp[1].cp.inst.operand = LOADDR(PREP_DMA_MEM(phdl_this_data->frames[F_LACE_STORE_SHORT]));
memcpy(phdl_this_data->frames[F_LACE_STORE_SHORT], phdl_this_data->frames[F_LACE_STORE_LONG], std_dlace_copper_list_size);
/* these are the only ones that are different from long frame. */
cp = phdl_this_data->frames[F_LACE_STORE_SHORT];
tmp = find_copper_inst(cp, CI_MOVE(R_BPL0PTH));
tmp[0].cp.inst.operand = HIADDR(PREP_DMA_MEM(&v->bitmap->plane[0][mod2l])); /* update plane
* pointers. */
tmp[1].cp.inst.operand = LOADDR(PREP_DMA_MEM(&v->bitmap->plane[0][mod2l])); /* high and low. */
tmp[2].cp.inst.operand = HIADDR(PREP_DMA_MEM(&v->bitmap->plane[0][mod2l + mod1l])); /* update plane
* pointers. */
tmp[3].cp.inst.operand = LOADDR(PREP_DMA_MEM(&v->bitmap->plane[0][mod2l + mod1l])); /* high and low. */
if (depth == 2) {
tmp[4].cp.inst.operand = HIADDR(PREP_DMA_MEM(&v->bitmap->plane[1][mod2l])); /* update plane
* pointers. */
tmp[5].cp.inst.operand = LOADDR(PREP_DMA_MEM(&v->bitmap->plane[1][mod2l])); /* high and low. */
tmp[6].cp.inst.operand = HIADDR(PREP_DMA_MEM(&v->bitmap->plane[1][mod2l + mod1l])); /* update plane
* pointers. */
tmp[7].cp.inst.operand = LOADDR(PREP_DMA_MEM(&v->bitmap->plane[1][mod2l + mod1l])); /* high and low. */
}
/* set next pointers correctly */
tmp = find_copper_inst(cp, CI_MOVE(R_COP1LCH));
tmp[0].cp.inst.operand = HIADDR(PREP_DMA_MEM(phdl_this_data->frames[F_LACE_STORE_LONG]));
tmp[1].cp.inst.operand = LOADDR(PREP_DMA_MEM(phdl_this_data->frames[F_LACE_STORE_LONG]));
cp = phdl_this_data->frames[F_LACE_LONG];
phdl_this_data->frames[F_LACE_LONG] = phdl_this_data->frames[F_LACE_STORE_LONG];
phdl_this_data->frames[F_LACE_STORE_LONG] = cp;
cp = phdl_this_data->frames[F_LACE_SHORT];
phdl_this_data->frames[F_LACE_SHORT] = phdl_this_data->frames[F_LACE_STORE_SHORT];
phdl_this_data->frames[F_LACE_STORE_SHORT] = cp;
vd->flags |= VF_DISPLAY;
cc_a2024_use_colormap(v, vd->colormap);
}
cc_load_mode(phdl_this);
}
dmode_t *
cc_init_pal_a2024(void)
{
/* this function should only be called once. */
if (!p24_this) {
int i;
u_short len = std_pal_a2024_copper_list_len;
cop_t *cp;
p24_this = &pal_a2024_mode;
p24_this_data = &pal_a2024_mode_data;
memset(p24_this, 0, sizeof(dmode_t));
memset(p24_this_data, 0, sizeof(dmdata_t));
p24_this->name = "pal: A2024 15 kHz";
p24_this->nominal_size.width = 1024;
p24_this->nominal_size.height = 1024;
p24_this_data->max_size.width = 1024;
p24_this_data->max_size.height = 1024;
p24_this_data->min_size.width = 1024;
p24_this_data->min_size.height = 1024;
p24_this_data->min_depth = 1;
p24_this_data->max_depth = 2;
p24_this->data = p24_this_data;
p24_this->get_monitor = cc_get_monitor;
p24_this->alloc_view = cc_alloc_view;
p24_this->get_current_view = cc_get_current_view;
p24_this_data->use_colormap = cc_a2024_use_colormap;
p24_this_data->get_colormap = cc_a2024_get_colormap;
p24_this_data->display_view = display_pal_a2024_view;
p24_this_data->alloc_colormap = cc_a2024_alloc_colormap;
p24_this_data->monitor = cc_monitor;
p24_this_data->flags |= DMF_HEDLEY_EXP;
p24_this_data->frames = pal_a2024_frames;
p24_this_data->frames[F_QD_QUAD0] = alloc_chipmem(std_pal_a2024_copper_list_size * F_QD_TOTAL);
if (!p24_this_data->frames[F_QD_QUAD0]) {
panic("couldn't get chipmem for copper list");
}
/* setup the hedley init bitplane. */
hedley_init = alloc_chipmem(128);
if (!hedley_init) {
panic("couldn't get chipmem for hedley init bitplane");
}
for (i = 1; i < 128; i++)
hedley_init[i] = 0xff;
hedley_init[0] = 0x03;
/* copy image of standard copper list. */
memcpy(p24_this_data->frames[0], std_pal_a2024_copper_list, std_pal_a2024_copper_list_size);
/* set the init plane pointer. */
cp = find_copper_inst(p24_this_data->frames[F_QD_QUAD0], CI_MOVE(R_BPL0PTH));
cp[0].cp.inst.operand = HIADDR(PREP_DMA_MEM(hedley_init));
cp[1].cp.inst.operand = LOADDR(PREP_DMA_MEM(hedley_init));
for (i = 1; i < F_QD_TOTAL; i++) {
p24_this_data->frames[i] = &p24_this_data->frames[i - 1][len];
memcpy(p24_this_data->frames[i], p24_this_data->frames[0], std_pal_a2024_copper_list_size);
}
p24_this_data->bplcon0 = 0x8200; /* hires */
p24_this_data->vbl_handler = (vbl_handler_func *) pal_a2024_mode_vbl_handler;
LIST_INSERT_HEAD(&MDATA(cc_monitor)->modes, p24_this, link);
}
return (p24_this);
}
void
display_pal_a2024_view(view_t *v)
{
if (p24_this_data->current_view != v) {
vdata_t *vd = VDATA(v);
cop_t *cp, *tmp;
u_char *inst_plane[2] = { NULL, NULL };
u_char **plane = inst_plane;
u_long full_line = v->bitmap->bytes_per_row + v->bitmap->row_mod;
u_long half_plane = full_line * v->bitmap->rows / 2;
int depth = v->bitmap->depth, i, j;
plane[0] = v->bitmap->plane[0];
if (depth == 2) {
plane[1] = v->bitmap->plane[1];
}
if (p24_this_data->current_view) {
VDATA(p24_this_data->current_view)->flags &= ~VF_DISPLAY; /* mark as no longer
* displayed. */
}
cp = p24_this_data->frames[F_QD_STORE_QUAD0];
tmp = find_copper_inst(cp, CI_MOVE(R_COLOR1F));
tmp = find_copper_inst(tmp, CI_MOVE(R_BPLCON0)); /* grab third one. */
tmp->cp.inst.operand = p24_this_data->bplcon0 | ((depth & 0x7) << 13); /* times 2 */
memcpy(p24_this_data->frames[F_QD_STORE_QUAD1], p24_this_data->frames[F_QD_STORE_QUAD0], std_pal_a2024_copper_list_size);
memcpy(p24_this_data->frames[F_QD_STORE_QUAD2], p24_this_data->frames[F_QD_STORE_QUAD0], std_pal_a2024_copper_list_size);
memcpy(p24_this_data->frames[F_QD_STORE_QUAD3], p24_this_data->frames[F_QD_STORE_QUAD0], std_pal_a2024_copper_list_size);
/*
* Mark Id's
*/
tmp = find_copper_inst(p24_this_data->frames[F_QD_STORE_QUAD1], CI_WAIT(126, 29));
CBUMP(tmp);
CMOVE(tmp, R_COLOR01, QUAD1_ID);
tmp = find_copper_inst(p24_this_data->frames[F_QD_STORE_QUAD2], CI_WAIT(126, 29));
CBUMP(tmp);
CMOVE(tmp, R_COLOR01, QUAD2_ID);
tmp = find_copper_inst(p24_this_data->frames[F_QD_STORE_QUAD3], CI_WAIT(126, 29));
CBUMP(tmp);
CMOVE(tmp, R_COLOR01, QUAD3_ID);
plane[0]--;
plane[0]--;
if (depth == 2) {
plane[1]--;
plane[1]--;
}
/*
* Set bitplane pointers.
*/
tmp = find_copper_inst(p24_this_data->frames[F_QD_STORE_QUAD0], CI_MOVE(R_BPLMOD2));
CBUMP(tmp);
CMOVE(tmp, R_BPL0PTH, HIADDR(PREP_DMA_MEM(&plane[0][0])));
CMOVE(tmp, R_BPL0PTL, LOADDR(PREP_DMA_MEM(&plane[0][0])));
CMOVE(tmp, R_BPL1PTH, HIADDR(PREP_DMA_MEM(&plane[0][full_line])));
CMOVE(tmp, R_BPL1PTL, LOADDR(PREP_DMA_MEM(&plane[0][full_line])));
if (depth == 2) {
CMOVE(tmp, R_BPL2PTH, HIADDR(PREP_DMA_MEM(&plane[1][0])));
CMOVE(tmp, R_BPL2PTL, LOADDR(PREP_DMA_MEM(&plane[1][0])));
CMOVE(tmp, R_BPL3PTH, HIADDR(PREP_DMA_MEM(&plane[1][full_line])));
CMOVE(tmp, R_BPL3PTL, LOADDR(PREP_DMA_MEM(&plane[1][full_line])));
}
#if defined (GRF_ECS) || defined (GRF_AGA)
CMOVE(tmp, R_DIWHIGH, 0x2100);
#endif
CMOVE(tmp, R_COP1LCH, HIADDR(PREP_DMA_MEM(p24_this_data->frames[F_QD_STORE_QUAD1])));
CMOVE(tmp, R_COP1LCL, LOADDR(PREP_DMA_MEM(p24_this_data->frames[F_QD_STORE_QUAD1])));
CEND(tmp);
CEND(tmp);
tmp = find_copper_inst(p24_this_data->frames[F_QD_STORE_QUAD1], CI_MOVE(R_BPLMOD2));
CBUMP(tmp);
CMOVE(tmp, R_BPL0PTH, HIADDR(PREP_DMA_MEM(&plane[0][HALF_2024_LINE])));
CMOVE(tmp, R_BPL0PTL, LOADDR(PREP_DMA_MEM(&plane[0][HALF_2024_LINE])));
CMOVE(tmp, R_BPL1PTH, HIADDR(PREP_DMA_MEM(&plane[0][full_line + HALF_2024_LINE])));
CMOVE(tmp, R_BPL1PTL, LOADDR(PREP_DMA_MEM(&plane[0][full_line + HALF_2024_LINE])));
if (depth == 2) {
CMOVE(tmp, R_BPL2PTH, HIADDR(PREP_DMA_MEM(&plane[1][HALF_2024_LINE])));
CMOVE(tmp, R_BPL2PTL, LOADDR(PREP_DMA_MEM(&plane[1][HALF_2024_LINE])));
CMOVE(tmp, R_BPL3PTH, HIADDR(PREP_DMA_MEM(&plane[1][full_line + HALF_2024_LINE])));
CMOVE(tmp, R_BPL3PTL, LOADDR(PREP_DMA_MEM(&plane[1][full_line + HALF_2024_LINE])));
}
#if defined (GRF_ECS) || defined (GRF_AGA)
CMOVE(tmp, R_DIWHIGH, 0x2100);
#endif
CMOVE(tmp, R_COP1LCH, HIADDR(PREP_DMA_MEM(p24_this_data->frames[F_QD_STORE_QUAD2])));
CMOVE(tmp, R_COP1LCL, LOADDR(PREP_DMA_MEM(p24_this_data->frames[F_QD_STORE_QUAD2])));
CEND(tmp);
CEND(tmp);
tmp = find_copper_inst(p24_this_data->frames[F_QD_STORE_QUAD2], CI_MOVE(R_BPLMOD2));
CBUMP(tmp);
CMOVE(tmp, R_BPL0PTH, HIADDR(PREP_DMA_MEM(&plane[0][half_plane])));
CMOVE(tmp, R_BPL0PTL, LOADDR(PREP_DMA_MEM(&plane[0][half_plane])));
CMOVE(tmp, R_BPL1PTH, HIADDR(PREP_DMA_MEM(&plane[0][half_plane + full_line])));
CMOVE(tmp, R_BPL1PTL, LOADDR(PREP_DMA_MEM(&plane[0][half_plane + full_line])));
if (depth == 2) {
CMOVE(tmp, R_BPL2PTH, HIADDR(PREP_DMA_MEM(&plane[1][half_plane])));
CMOVE(tmp, R_BPL2PTL, LOADDR(PREP_DMA_MEM(&plane[1][half_plane])));
CMOVE(tmp, R_BPL3PTH, HIADDR(PREP_DMA_MEM(&plane[1][half_plane + full_line])));
CMOVE(tmp, R_BPL3PTL, LOADDR(PREP_DMA_MEM(&plane[1][half_plane + full_line])));
}
#if defined (GRF_ECS) || defined (GRF_AGA)
CMOVE(tmp, R_DIWHIGH, 0x2100);
#endif
CMOVE(tmp, R_COP1LCH, HIADDR(PREP_DMA_MEM(p24_this_data->frames[F_QD_STORE_QUAD3])));
CMOVE(tmp, R_COP1LCL, LOADDR(PREP_DMA_MEM(p24_this_data->frames[F_QD_STORE_QUAD3])));
CEND(tmp);
CEND(tmp);
tmp = find_copper_inst(p24_this_data->frames[F_QD_STORE_QUAD3], CI_MOVE(R_BPLMOD2));
CBUMP(tmp);
CMOVE(tmp, R_BPL0PTH, HIADDR(PREP_DMA_MEM(&plane[0][half_plane + HALF_2024_LINE])));
CMOVE(tmp, R_BPL0PTL, LOADDR(PREP_DMA_MEM(&plane[0][half_plane + HALF_2024_LINE])));
CMOVE(tmp, R_BPL1PTH, HIADDR(PREP_DMA_MEM(&plane[0][half_plane + full_line + HALF_2024_LINE])));
CMOVE(tmp, R_BPL1PTL, LOADDR(PREP_DMA_MEM(&plane[0][half_plane + full_line + HALF_2024_LINE])));
if (depth == 2) {
CMOVE(tmp, R_BPL2PTH, HIADDR(PREP_DMA_MEM(&plane[1][half_plane + HALF_2024_LINE])));
CMOVE(tmp, R_BPL2PTL, LOADDR(PREP_DMA_MEM(&plane[1][half_plane + HALF_2024_LINE])));
CMOVE(tmp, R_BPL3PTH, HIADDR(PREP_DMA_MEM(&plane[1][half_plane + full_line + HALF_2024_LINE])));
CMOVE(tmp, R_BPL3PTL, LOADDR(PREP_DMA_MEM(&plane[1][half_plane + full_line + HALF_2024_LINE])));
}
#if defined (GRF_ECS) || defined (GRF_AGA)
CMOVE(tmp, R_DIWHIGH, 0x2100);
#endif
CMOVE(tmp, R_COP1LCH, HIADDR(PREP_DMA_MEM(p24_this_data->frames[F_QD_STORE_QUAD0])));
CMOVE(tmp, R_COP1LCL, LOADDR(PREP_DMA_MEM(p24_this_data->frames[F_QD_STORE_QUAD0])));
CEND(tmp);
CEND(tmp);
/* swap new pointers in. */
for (i = F_QD_STORE_QUAD0, j = F_QD_QUAD0;
i <= F_QD_STORE_QUAD3; i++, j++) {
cp = p24_this_data->frames[j];
p24_this_data->frames[j] = p24_this_data->frames[i];
p24_this_data->frames[i] = cp;
}
p24_this_data->current_view = v;
vd->flags |= VF_DISPLAY;
cc_a2024_use_colormap(v, vd->colormap);
}
cc_load_mode(p24_this);
}
void
pal_a2024_mode_vbl_handler(dmode_t *d)
{
u_short vp = ((custom.vposr & 0x0007) << 8) | ((custom.vhposr) >> 8);
if (vp < 20) {
custom.cop1lc = PREP_DMA_MEM(p24_this_data->frames[p24_this_data->hedley_current]);
custom.copjmp1 = 0;
}
p24_this_data->hedley_current++;
p24_this_data->hedley_current &= 0x3; /* if 4 then 0. */
}
#endif /* GRF_A2024 */
#if defined (GRF_AGA)
dmode_t *
cc_init_pal_aga(void)
{
/* this function should only be called once. */
if (!paga_this && (custom.deniseid & 0xff) == 0xf8 &&
aga_enable & AGA_ENABLE) {
u_short len = aga_copper_list_len;
paga_this = &paga_mode;
paga_this_data = &paga_mode_data;
memset(paga_this, 0, sizeof(dmode_t));
memset(paga_this_data, 0, sizeof(dmdata_t));
paga_this->name = "pal: AGA dbl";
paga_this->nominal_size.width = 640;
paga_this->nominal_size.height = 512;
paga_this_data->max_size.width = 720;
paga_this_data->max_size.height = 564;
paga_this_data->min_size.width = 320;
paga_this_data->min_size.height = 200;
paga_this_data->min_depth = 1;
paga_this_data->max_depth = 8;
paga_this->data = paga_this_data;
paga_this->get_monitor = cc_get_monitor;
paga_this->alloc_view = cc_alloc_view;
paga_this->get_current_view = cc_get_current_view;
paga_this_data->use_colormap = cc_use_aga_colormap;
paga_this_data->get_colormap = cc_get_colormap;
paga_this_data->alloc_colormap = cc_alloc_aga_colormap;
paga_this_data->display_view = display_pal_aga_view;
paga_this_data->monitor = cc_monitor;
paga_this_data->frames = paga_frames;
paga_this_data->frames[F_LONG] = alloc_chipmem(aga_copper_list_size * F_TOTAL);
if (!paga_this_data->frames[F_LONG]) {
panic("couldn't get chipmem for copper list");
}
paga_this_data->frames[F_STORE_LONG] = &paga_this_data->frames[F_LONG][len];
memcpy(paga_this_data->frames[F_STORE_LONG], aga_copper_list, aga_copper_list_size);
memcpy(paga_this_data->frames[F_LONG], aga_copper_list, aga_copper_list_size);
paga_this_data->bplcon0 = 0x0240 | USE_CON3; /* color composite
* enable,
* shres. */
paga_this_data->std_start_x = 0x4f /*STANDARD_VIEW_X*/;
paga_this_data->std_start_y = 0x2b /*STANDARD_VIEW_Y*/;
paga_this_data->vbl_handler = (vbl_handler_func *) cc_mode_vbl_handler;
paga_this_data->beamcon0 = STANDARD_PAL_BEAMCON | (SPECIAL_BEAMCON ^ VSYNCTRUE);
LIST_INSERT_HEAD(&MDATA(cc_monitor)->modes,
paga_this, link);
}
return (paga_this);
}
/* static, so I can patch and play */
#ifdef GRF_AGA_VGA
int pAGA_htotal = 0x079;
int pAGA_vtotal = 0x24d;
int pAGA_vbstop = 0x019;
int pAGA_hcenter = 0x04b;
#else
int pAGA_htotal = 0x081;
int pAGA_vtotal = 0x23d;
int pAGA_vbstop = 0x017;
int pAGA_hcenter = 0x04f;
#endif
int pAGA_hsstrt = 0x00f;
int pAGA_hsstop = 0x019;
int pAGA_hbstrt = 0x001;
int pAGA_hbstop = 0x021;
int pAGA_vsstrt = 0x001;
int pAGA_vsstop = 0x008;
int pAGA_vbstrt = 0x000;
void
display_pal_aga_view(view_t *v)
{
if (paga_this_data->current_view != v) {
vdata_t *vd = VDATA(v);
cop_t *cp = paga_this_data->frames[F_STORE_LONG], *tmp;
int depth = v->bitmap->depth, i;
int hstart, hstop, vstart, vstop, j;
int x, y, w = v->display.width, h = v->display.height;
u_short ddfstart, ddfwidth, con1;
#ifdef DEBUG
if (aga_enable & AGA_TRACE)
printf("display_aga_view(%dx%dx%d) %p\n", w, h,
depth, v);
#endif
/* round down to nearest even width */
/* w &= 0xfffe; */
/* calculate datafetch width. */
ddfwidth = ((v->bitmap->bytes_per_row >> 1) - 4) << 1;
/* this will center the any overscanned display */
/* and allow user to modify. */
x = v->display.x + paga_this_data->std_start_x - ((w - 640) >> 3);
y = v->display.y + paga_this_data->std_start_y - ((h - 512) >> 1);
if (y & 1)
y--;
if (!(x & 1))
x--;
hstart = x;
hstop = x + (w >> 2);
vstart = y;
vstop = y + (h >> 0);
ddfstart = (hstart >> 1) - 8;
#ifdef DEBUG
if (aga_enable & AGA_TRACE2) {
printf (" ddfwidth %04x x %04x y %04x", ddfwidth,
x, y);
printf (" hstart %04x hstop %04x vstart %04x vstop %04x ddfstart %04x\n",
hstart, hstop, vstart, vstop, ddfstart);
}
#endif
/* check for hardware limits, AGA may allow more..? */
/* anyone got a 4000 I can borrow :^) -ch */
if ((ddfstart & 0xfffc) + ddfwidth > 0xd8) {
int d = 0;
/* XXX anyone know the equality properties of
* intermixed logial AND's */
/* XXX and arithmetic operators? */
while (((ddfstart & 0xfffc) + ddfwidth - d) > 0xd8) {
d++;
}
ddfstart -= d;
hstart -= d << 1;
hstop -= d << 1;
}
/* correct the datafetch to proper limits. */
/* delay the actual display of the data until we need it. */
ddfstart &= 0xfffc;
#ifdef DEBUG
if (aga_enable & AGA_TRACE2) {
printf (" ddfwidth %04x x %04x y %04x", ddfwidth,
x, y);
printf (" hstart %04x hstop %04x vstart %04x vstop %04x ddfstart %04x\n",
hstart, hstop, vstart, vstop, ddfstart);
}
#endif
con1 = ((hstart - 9) - (ddfstart << 1)) | (((hstart - 9) - (ddfstart << 1)) << 4);
if (paga_this_data->current_view) {
VDATA(paga_this_data->current_view)->flags &= ~VF_DISPLAY; /* mark as no longer */
/* displayed. */
}
paga_this_data->current_view = v;
cp = paga_this_data->frames[F_STORE_LONG];
tmp = cp;
for (i = 0; i < 8; ++i) {
if (tmp == NULL)
break;
tmp = find_copper_inst(tmp + 1, CI_MOVE(R_BPLCON3));
if (tmp == NULL)
break;
tmp->cp.inst.operand = 0x0ca1 | (i << 13);
tmp = find_copper_inst(tmp + 1, CI_MOVE(R_BPLCON3));
if (tmp == NULL)
break;
tmp->cp.inst.operand = 0x0ea1 | (i << 13);
}
if (tmp)
tmp = find_copper_inst(tmp + 1, CI_MOVE(R_BPLCON3));
if (tmp)
tmp->cp.inst.operand = 0x0ca1;
tmp = find_copper_inst(cp, CI_MOVE(R_FMODE));
tmp->cp.inst.operand = 0x8003;
tmp = find_copper_inst(cp, CI_MOVE(R_HTOTAL));
tmp->cp.inst.operand = pAGA_htotal; /* 81/71/73/79? */
tmp = find_copper_inst(cp, CI_MOVE(R_HBSTRT));
tmp->cp.inst.operand = pAGA_hbstrt; /* 0x0008 */
tmp = find_copper_inst(cp, CI_MOVE(R_HSSTRT));
tmp->cp.inst.operand = pAGA_hsstrt; /* 0x000e */
tmp = find_copper_inst(cp, CI_MOVE(R_HSSTOP));
tmp->cp.inst.operand = pAGA_hsstop; /* 0x001c */
tmp = find_copper_inst(cp, CI_MOVE(R_HBSTOP));
tmp->cp.inst.operand = pAGA_hsstop; /* 0x001e */
tmp = find_copper_inst(cp, CI_MOVE(R_HCENTER));
tmp->cp.inst.operand = pAGA_hcenter; /*AGA_htotal / 2 + AGA_hsstrt */
tmp = find_copper_inst(cp, CI_MOVE(R_VBSTRT));
tmp->cp.inst.operand = pAGA_vbstrt; /* 0x0000 */
tmp = find_copper_inst(cp, CI_MOVE(R_VSSTRT));
tmp->cp.inst.operand = pAGA_vsstrt; /* 0x016b / AGA_htotal */
tmp = find_copper_inst(cp, CI_MOVE(R_VSSTOP));
tmp->cp.inst.operand = pAGA_vsstop; /* 0x02d6 / AGA_htotal */
tmp = find_copper_inst(cp, CI_MOVE(R_VBSTOP));
tmp->cp.inst.operand = pAGA_vbstop; /* 0x0bd1 / AGA_htotal */
tmp = find_copper_inst(cp, CI_MOVE(R_VTOTAL));
tmp->cp.inst.operand = pAGA_vtotal;
tmp = find_copper_inst(cp, CI_MOVE(R_BEAMCON0));
tmp->cp.inst.operand = paga_this_data->beamcon0;
#ifdef DEBUG
if (aga_enable & AGA_TRACE2)
printf(" beamcon0 %04x", tmp->cp.inst.operand);
#endif
tmp = find_copper_inst(cp, CI_MOVE(R_DIWHIGH));
tmp->cp.inst.operand = CALC_DIWHIGH(hstart, vstart, hstop, vstop);
#ifdef DEBUG
if (aga_enable & AGA_TRACE2)
printf(" diwhigh %04x>", tmp->cp.inst.operand);
#endif
#if 0
tmp->cp.inst.operand = (vstop & 0x0700) | ((hstop & 0x0100) << 5);
#endif
#ifdef DEBUG
if (aga_enable & AGA_TRACE2)
printf("%04x", tmp->cp.inst.operand);
#endif
tmp = find_copper_inst(cp, CI_MOVE(R_BPLCON0));
tmp->cp.inst.operand = paga_this_data->bplcon0 |
((depth & 0x7) << 12) | ((depth & 0x8) << 1);
#ifdef DEBUG
if (aga_enable & AGA_TRACE2)
printf(" bplcon0 %04x", tmp->cp.inst.operand);
#endif
tmp = find_copper_inst(cp, CI_MOVE(R_BPLCON1));
tmp->cp.inst.operand = con1;
#ifdef DEBUG
if (aga_enable & AGA_TRACE2)
printf(" bplcon1 %04x>0000\n", con1);
#endif
tmp = find_copper_inst(cp, CI_MOVE(R_DIWSTART));
tmp->cp.inst.operand = ((vstart & 0xff) << 8) | (hstart & 0xff);
#ifdef DEBUG
if (aga_enable & AGA_TRACE2)
printf(" diwstart %04x", tmp->cp.inst.operand);
#endif
tmp = find_copper_inst(cp, CI_MOVE(R_DIWSTOP));
tmp->cp.inst.operand = ((vstop & 0xff) << 8) | (hstop & 0xff);
#ifdef DEBUG
if (aga_enable & AGA_TRACE2)
printf(" diwstop %04x", tmp->cp.inst.operand);
#endif
tmp = find_copper_inst(cp, CI_MOVE(R_DDFSTART));
tmp->cp.inst.operand = ddfstart;
#ifdef DEBUG
if (aga_enable & AGA_TRACE2)
printf(" ddfstart %04x", tmp->cp.inst.operand);
#endif
tmp = find_copper_inst(cp, CI_MOVE(R_DDFSTOP));
tmp->cp.inst.operand = ddfstart + ddfwidth;
#ifdef DEBUG
if (aga_enable & AGA_TRACE2)
printf(" ddfstop %04x", tmp->cp.inst.operand);
#endif
tmp = find_copper_inst(cp, CI_MOVE(R_BPL0PTH));
for (i = 0, j = 0; i < depth; j += 2, i++) {
/* update the plane pointers */
tmp[j].cp.inst.operand = HIADDR(PREP_DMA_MEM(v->bitmap->plane[i]));
tmp[j + 1].cp.inst.operand = LOADDR(PREP_DMA_MEM(v->bitmap->plane[i]));
#ifdef DEBUG
if (aga_enable & AGA_TRACE2)
printf (" bpl%dpth %p", i, v->bitmap->plane[i]);
#endif
}
/* set mods correctly. */
tmp = find_copper_inst(cp, CI_MOVE(R_BPL1MOD));
tmp[0].cp.inst.operand = v->bitmap->row_mod;
tmp[1].cp.inst.operand = v->bitmap->row_mod;
#ifdef DEBUG
if (aga_enable & AGA_TRACE2)
printf(" bplxmod %04x\n", v->bitmap->row_mod);
#endif
/* set next pointers correctly */
tmp = find_copper_inst(cp, CI_MOVE(R_COP1LCH));
tmp[0].cp.inst.operand = HIADDR(PREP_DMA_MEM(paga_this_data->frames[F_STORE_LONG]));
tmp[1].cp.inst.operand = LOADDR(PREP_DMA_MEM(paga_this_data->frames[F_STORE_LONG]));
cp = paga_this_data->frames[F_LONG];
paga_this_data->frames[F_LONG] = paga_this_data->frames[F_STORE_LONG];
paga_this_data->frames[F_STORE_LONG] = cp;
vd->flags |= VF_DISPLAY;
cc_use_aga_colormap(v, vd->colormap);
}
cc_load_mode(paga_this);
#ifdef DEBUG
if (aga_enable & AGA_TRACE)
aga_enable |= AGA_TRACE2; /* XXXX */
#endif
}
#endif /* GRF_AGA */
#endif /* GRF_PAL */