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