diff options
author | Theo de Raadt <deraadt@cvs.openbsd.org> | 1995-10-18 08:53:40 +0000 |
---|---|---|
committer | Theo de Raadt <deraadt@cvs.openbsd.org> | 1995-10-18 08:53:40 +0000 |
commit | d6583bb2a13f329cf0332ef2570eb8bb8fc0e39c (patch) | |
tree | ece253b876159b39c620e62b6c9b1174642e070e /sys/arch/amiga/dev/grfabs_cc.c |
initial import of NetBSD tree
Diffstat (limited to 'sys/arch/amiga/dev/grfabs_cc.c')
-rw-r--r-- | sys/arch/amiga/dev/grfabs_cc.c | 3116 |
1 files changed, 3116 insertions, 0 deletions
diff --git a/sys/arch/amiga/dev/grfabs_cc.c b/sys/arch/amiga/dev/grfabs_cc.c new file mode 100644 index 00000000000..645bbea9aa2 --- /dev/null +++ b/sys/arch/amiga/dev/grfabs_cc.c @@ -0,0 +1,3116 @@ +/* $NetBSD: grfabs_cc.c,v 1.10 1995/10/05 12:41:12 chopps 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 <sys/param.h> +#include <sys/systm.h> +#include <sys/errno.h> +#include <sys/cdefs.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; +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; +# 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 */ +#endif + +/* monitor functions. */ +monitor_t * +cc_init_monitor() +{ + 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(m) + 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() +{ + if (m_this_data->current_mode) + return(m_this_data->current_mode); + else + return(NULL); +} + +dmode_t * +get_next_mode(d) + 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(size, depth) + dimen_t *size; + u_char depth; +{ + dmode_t *save; + dmode_t *dm; + long dt, 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(width, height, depth, flags) + u_short width, height, depth, 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? becuase 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 */ + total_size = amiga_round_page(plane_size * depth) + /* for length */ + (temp_size) + (array_size) + sizeof(bmap_t) + + NBPG; /* for alignment */ + bm = alloc_chipmem(total_size); + if (bm) { + if (flags & BMF_CLEAR) { + bzero(bm, 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 *) amiga_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(bm) + 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(d) + dmode_t *d; +{ + if (d) { + m_this_data->current_mode = d; + return; + } + /* turn off display */ + m_this_data->current_mode = NULL; + wait_tof(); + wait_tof(); + custom.cop1lc = PREP_DMA_MEM(null_mode_copper_list); +} +/* + * 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, +#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() +{ + int i = 0; + int error = 0; + while (mode_init_funcs[i]) { + mode_init_funcs[i] (); + i++; + } + return (error); +} + +monitor_t * +cc_get_monitor(d) + dmode_t *d; +{ + return (DMDATA(d)->monitor); +} + +view_t * +cc_get_current_view(d) + dmode_t *d; +{ + return (DMDATA(d)->current_view); +} + + +view_t * +cc_alloc_view(mode, dim, depth) + 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) { + int i; + 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(depth) + 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(depth) + 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(vcm, cm, use) + colormap_t *vcm, *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(v, cm) + 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(v, cm) + 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(v, cm) + 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(depth) + 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(v, cm) + 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(v, cm) + 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(v, bm, mode, dbox) + view_t *v; + bmap_t *bm; + dmode_t *mode; + box_t *dbox; +{ + vdata_t *vd = VDATA(v); + v->bitmap = bm; + vd->mode = mode; + bcopy(dbox, &v->display, 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(v) + view_t *v; +{ + if (v) { + vdata_t *vd = VDATA(v); + dmode_t *md = vd->mode; + v->remove_view(v); + free_chipmem(VDATA(v)->colormap); + cc_monitor->free_bitmap(v->bitmap); + free_chipmem(v); + } +} + +void +cc_remove_view(v) + 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(v) + view_t *v; +{ + return (VDATA(v)->mode); +} + +void +cc_mode_vbl_handler(d) + 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(d) + 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() +{ + /* this function should only be called once. */ + if (!h_this) { + u_short len = std_copper_list_len; + cop_t *cp; + + h_this = &hires_mode; + h_this_data = &hires_mode_data; + bzero(h_this, sizeof(dmode_t)); + bzero(h_this_data, 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]; + + bcopy(std_copper_list, h_this_data->frames[F_STORE_LONG], std_copper_list_size); + bcopy(std_copper_list, h_this_data->frames[F_LONG], 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(v) + view_t *v; +{ + if (h_this_data->current_view != v) { + vdata_t *vd = VDATA(v); + monitor_t *monitor = h_this_data->monitor; + 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() +{ + /* this function should only be called once. */ + if (!hl_this) { + u_short len = std_copper_list_len; + cop_t *cp; + + hl_this = &hires_lace_mode; + hl_this_data = &hires_lace_mode_data; + bzero(hl_this, sizeof(dmode_t)); + bzero(hl_this_data, 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]; + + bcopy(std_copper_list, hl_this_data->frames[F_LACE_STORE_LONG], std_copper_list_size); + bcopy(std_copper_list, hl_this_data->frames[F_LACE_STORE_SHORT], std_copper_list_size); + bcopy(std_copper_list, hl_this_data->frames[F_LACE_LONG], std_copper_list_size); + bcopy(std_copper_list, hl_this_data->frames[F_LACE_SHORT], 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(v) + view_t *v; +{ + if (hl_this_data->current_view != v) { + vdata_t *vd = VDATA(v); + monitor_t *monitor = hl_this_data->monitor; + 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() +{ + /* this function should only be called once. */ + if (!hdl_this) { + u_short len = std_dlace_copper_list_len; + cop_t *cp; + + hdl_this = &hires_dlace_mode; + hdl_this_data = &hires_dlace_mode_data; + bzero(hdl_this, sizeof(dmode_t)); + bzero(hdl_this_data, 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(v) + view_t *v; +{ + if (hdl_this_data->current_view != v) { + vdata_t *vd = VDATA(v); + monitor_t *monitor = hdl_this_data->monitor; + cop_t *cp = hdl_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; + 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() +{ + /* 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; + bzero(a24_this, sizeof(dmode_t)); + bzero(a24_this_data, sizeof(dmdata_t)); + + a24_this->name = "ntsc: A2024 15khz"; + 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. */ + bcopy(std_a2024_copper_list, a24_this_data->frames[0], 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(v) + view_t *v; +{ + if (a24_this_data->current_view != v) { + vdata_t *vd = VDATA(v); + monitor_t *monitor = a24_this_data->monitor; + cop_t *cp, *tmp; + u_char *inst_plane[2]; + 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 line_mod = 0xbc; /* standard 2024 15khz mod. */ + 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(d) + 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() +{ + /* 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; + cop_t *cp; + + aga_this = &aga_mode; + aga_this_data = &aga_mode_data; + bzero(aga_this, sizeof(dmode_t)); + bzero(aga_this_data, 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]; + + bcopy(aga_copper_list, aga_this_data->frames[F_STORE_LONG], aga_copper_list_size); + bcopy(aga_copper_list, aga_this_data->frames[F_LONG], aga_copper_list_size); + + aga_this_data->bplcon0 = 0x0240 | USE_CON3; /* color composite + * enable, + * shres. */ + aga_this_data->std_start_x = 0x4f /*STANDARD_VIEW_X*/; + 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 */ + +int AGA_htotal = 0x79; +int AGA_hsstrt = 0xe; +int AGA_hsstop = 0x1c; +int AGA_hbstrt = 0x8; +int AGA_hbstop = 0x1e; +int AGA_vtotal = 0x1ec; +int AGA_vsstrt = 0x3; +int AGA_vsstop = 0x6; +int AGA_vbstrt = 0x0; +int AGA_vbstop = 0x19; +int AGA_hcenter = 0x4a; + +void +display_aga_view(v) + view_t *v; +{ + if (aga_this_data->current_view != v) { + vdata_t *vd = VDATA(v); + monitor_t *monitor = aga_this_data->monitor; + 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) %x\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 %08x", 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 +} + +#endif /* GRF_AGA */ +#endif /* GRF_NTSC */ + +/* + * PAL modes. + */ + +#if defined (GRF_PAL) + +dmode_t * +cc_init_pal_hires() +{ + /* this function should only be called once. */ + if (!ph_this) { + u_short len = std_copper_list_len; + cop_t *cp; + + ph_this = &pal_hires_mode; + ph_this_data = &pal_hires_mode_data; + bzero(ph_this, sizeof(dmode_t)); + bzero(ph_this_data, 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]; + + bcopy(std_copper_list, ph_this_data->frames[F_STORE_LONG], std_copper_list_size); + bcopy(std_copper_list, ph_this_data->frames[F_LONG], 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(v) + view_t *v; +{ + if (ph_this_data->current_view != v) { + vdata_t *vd = VDATA(v); + monitor_t *monitor = ph_this_data->monitor; + 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() +{ + /* this function should only be called once. */ + if (!phl_this) { + u_short len = std_copper_list_len; + cop_t *cp; + + phl_this = &pal_hires_lace_mode; + phl_this_data = &pal_hires_lace_mode_data; + bzero(phl_this, sizeof(dmode_t)); + bzero(phl_this_data, 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]; + + bcopy(std_copper_list, phl_this_data->frames[F_LACE_STORE_LONG], std_copper_list_size); + bcopy(std_copper_list, phl_this_data->frames[F_LACE_STORE_SHORT], std_copper_list_size); + bcopy(std_copper_list, phl_this_data->frames[F_LACE_LONG], std_copper_list_size); + bcopy(std_copper_list, phl_this_data->frames[F_LACE_SHORT], 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(v) + view_t *v; +{ + if (phl_this_data->current_view != v) { + vdata_t *vd = VDATA(v); + monitor_t *monitor = phl_this_data->monitor; + 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])); + + + bcopy(phl_this_data->frames[F_LACE_STORE_LONG], phl_this_data->frames[F_LACE_STORE_SHORT], 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() +{ + /* this function should only be called once. */ + if (!phdl_this) { + u_short len = std_dlace_copper_list_len; + cop_t *cp; + + phdl_this = &pal_hires_dlace_mode; + phdl_this_data = &pal_hires_dlace_mode_data; + bzero(phdl_this, sizeof(dmode_t)); + bzero(phdl_this_data, 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]; + + bcopy(std_dlace_copper_list, phdl_this_data->frames[F_LACE_STORE_LONG], std_dlace_copper_list_size); + bcopy(std_dlace_copper_list, phdl_this_data->frames[F_LACE_STORE_SHORT], std_dlace_copper_list_size); + bcopy(std_dlace_copper_list, phdl_this_data->frames[F_LACE_LONG], std_dlace_copper_list_size); + bcopy(std_dlace_copper_list, phdl_this_data->frames[F_LACE_SHORT], 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(v) + view_t *v; +{ + if (phdl_this_data->current_view != v) { + vdata_t *vd = VDATA(v); + monitor_t *monitor = phdl_this_data->monitor; + cop_t *cp = phdl_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; + 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])); + + bcopy(phdl_this_data->frames[F_LACE_STORE_LONG], phdl_this_data->frames[F_LACE_STORE_SHORT], 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() +{ + /* 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; + bzero(p24_this, sizeof(dmode_t)); + bzero(p24_this_data, sizeof(dmdata_t)); + + p24_this->name = "pal: A2024 15khz"; + 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. */ + bcopy(std_pal_a2024_copper_list, p24_this_data->frames[0], 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]; + bcopy(p24_this_data->frames[0], p24_this_data->frames[i], 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(v) + view_t *v; +{ + if (p24_this_data->current_view != v) { + vdata_t *vd = VDATA(v); + monitor_t *monitor = p24_this_data->monitor; + cop_t *cp, *tmp; + u_char *inst_plane[2]; + 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 line_mod = 0xbc; /* standard 2024 15khz mod. */ + 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 */ + + bcopy(p24_this_data->frames[F_QD_STORE_QUAD0], p24_this_data->frames[F_QD_STORE_QUAD1], std_pal_a2024_copper_list_size); + bcopy(p24_this_data->frames[F_QD_STORE_QUAD0], p24_this_data->frames[F_QD_STORE_QUAD2], std_pal_a2024_copper_list_size); + bcopy(p24_this_data->frames[F_QD_STORE_QUAD0], p24_this_data->frames[F_QD_STORE_QUAD3], 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(d) + 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() +{ + /* 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; + cop_t *cp; + + paga_this = &paga_mode; + paga_this_data = &paga_mode_data; + bzero(paga_this, sizeof(dmode_t)); + bzero(paga_this_data, 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]; + + bcopy(aga_copper_list, paga_this_data->frames[F_STORE_LONG], aga_copper_list_size); + bcopy(aga_copper_list, paga_this_data->frames[F_LONG], 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 (VGAOnly is commented-out) */ + +int pAGA_htotal = 0x081; /* 0x079 */ +int pAGA_hsstrt = 0x00f; /* 0x00f */ +int pAGA_hsstop = 0x019; /* 0x019 */ +int pAGA_hbstrt = 0x001; /* 0x001 */ +int pAGA_hbstop = 0x021; /* 0x021 */ +int pAGA_vtotal = 0x23d; /* 0x24d */ +int pAGA_vsstrt = 0x001; /* 0x001 */ +int pAGA_vsstop = 0x008; /* 0x008 */ +int pAGA_vbstrt = 0x000; /* 0x000 */ +int pAGA_vbstop = 0x017; /* 0x019 */ +int pAGA_hcenter = 0x04f; /* 0x04b */ + +void +display_pal_aga_view(v) + view_t *v; +{ + if (paga_this_data->current_view != v) { + vdata_t *vd = VDATA(v); + monitor_t *monitor = paga_this_data->monitor; + 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) %x\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 %08x", 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 */ |