/* * ============================================================================ * Title: STIC -- Standard Television Interface Chip, AY-3-8900 * Author: J. Zbiciak * $Id$ * ============================================================================ * This module implements the STIC Chip. Its functionality is currently * far from complete. For instance, I don't implement MOBs yet. * ============================================================================ * The STIC processor is active over several regions of memory: * * 0x0000 - 0x001F -- MOB (Movable OBject) controls * 0x0000 + n X Position, MOB #n * 0x0008 + n Y Position, MOB #n * 0x0010 + n Attribute Register, MOB #n * 0x0018 + n Collision Detect, MOB #n * * 0x0020 - 0x0021 -- STIC control registers * 0x0020 Display Enable * 0x0021 Graphics Mode * * 0x0028 - 0x002C -- Global color settings * 0x0028 + n Color Stack (n == 0..3) * 0x002C Border Color * * 0x0030 - 0x0032 -- Display framing * 0x0030 Pixel Column Delay (0..7) * 0x0031 Pixel Row Delay (0..7) * 0x0032 Edge inhibit (bit0->left, bit1->top) * * 0x0200 - 0x035F -- Background Card Table (BACKTAB) * * 0x3800 - 0x39FF -- Graphics RAM * * Note: BACKTAB and GRAM are actually physically * separate. This STIC implementation 'snoops' * these accesses for performance reasons. * * For now, I handle all of the control register accesses into one * peripheral entry and all bus-snooping accesses in a second peripheral * entry. * ============================================================================ */ #ifndef _STIC_H #define _STIC_H 1 #include "cp1600/req_bus.h" /* * ============================================================================ * STIC_T -- Main STIC structure. * * Note: These bitfields seem to be broken at the present. * * STIC_MOB_X_T -- MOB X Position Bitfield Structure * STIC_MOB_Y_T -- MOB Y Position Bitfield Structure * STIC_MOB_A_T -- MOB Attribute Bitfield Structure * STIC_MOB_C_T -- MOB Collision Bitfield Structure * ============================================================================ */ struct stic_t { /* -------------------------------------------------------------------- */ /* The STIC is split into three separate peripherals, since a RD/WR */ /* to something the STIC is interested in needs to go one of three */ /* places -- either (1) to update the general state of the STIC via a */ /* control register, (2) to update the BACKTAB, or (3) to update a */ /* card definition in GRAM. */ /* -------------------------------------------------------------------- */ periph_t stic_cr; periph_t snoop_btab; periph_t snoop_gram; /* -------------------------------------------------------------------- */ /* We just keep a raw image of the STIC registers and decode manually */ /* -------------------------------------------------------------------- */ uint_32 raw [0x40]; uint_8 gmem[0x140 * 8]; /* -------------------------------------------------------------------- */ /* We store several bitmaps and display lists. */ /* -------------------------------------------------------------------- */ int fifo_ptr; /* Video FIFO pointer. */ uint_16 btab_sr [240]; /* BACKTAB as it is in Sys. RAM */ uint_16 btab [240]; /* BACKTAB as STIC sees it */ uint_32 last_bg [12]; /* Last background color by row */ // uint_32 bt_img [240*8]; /* BACKTAB 4-bpp display list. */ uint_8 bt_bmp [240*8]; /* BACKTAB 1-bpp display list. */ uint_32 mob_img [ 16*16 / 8]; /* Expanded/mirrored MOB 4bpp. */ uint_16 mob_bmp [8][16]; /* Expanded/mirrored MOBs 1bpp. */ uint_32 mpl_img [192*224 / 8]; /* MOB image. */ uint_32 mpl_vsb [192*224 /32]; /* MOB visibility bitmap. */ uint_32 mpl_pri [192*224 /32]; /* MOB priority bitmap. */ uint_32 xbt_img [192*112 / 8]; /* Re-tiled BACKTAB image. */ uint_32 xbt_bmp [192*112 /32]; /* Re-tiled BACKTAB 1-bpp. */ uint_32 image [192*224 / 8]; /* Final 192x224 image, 4-bpp. */ uint_8 *disp; gfx_t *gfx; #if 0 /* -------------------------------------------------------------------- */ /* Private GROM, GRAM, BACKTAB memory pointers for efficiency. */ /* -------------------------------------------------------------------- */ uint_16 *grom; uint_16 *gram; uint_16 *backtab; #endif /* -------------------------------------------------------------------- */ /* IRQ and BUSRQ generation. */ /* -------------------------------------------------------------------- */ req_bus_t *req_bus; /* Bus for INTRQ, BUSRQ, INTAK, BUSAK. */ /* -------------------------------------------------------------------- */ /* STIC internal flags. */ /* -------------------------------------------------------------------- */ void (*upd)(struct stic_t*); /* Update fxn for curr disp mode. */ int phase; /* 0 == Start of VBlank, 1 == Start of Pic */ int ve_post; /* Where vid-enables are posted. */ int vid_enable; /* Must be set every vsync to enable vid. */ int mode; /* 1 == FG/BG mode, 0 == Color Stack. */ int bt_dirty; /* BACKTAB is dirty. */ int gr_dirty; /* GRAM is dirty. */ int ob_dirty; /* MOBs are dirty. */ int drop_frame; /* Frames to drop because we're behind. */ uint_64 gmem_accessible;/* CPU can access GRAM/GROM. */ uint_64 stic_accessible;/* CPU can access STIC registers */ uint_64 next_busrq; /* Time of next STIC->CPU bus request. */ uint_64 next_irq; /* Time of next STIC->CPU Interrupt request */ uint_64 next_phase; /* Don't switch phases until after this */ /* -------------------------------------------------------------------- */ /* Performance monitoring. :-) */ /* -------------------------------------------------------------------- */ struct stic_time_t { double full_update; double draw_btab; double draw_mobs; double fix_bord; double merge_planes; double push_vid; double mob_colldet; double gfx_vid_enable; int total_frames; } time; /* -------------------------------------------------------------------- */ /* Demo recording */ /* -------------------------------------------------------------------- */ demo_t *demo; }; #ifndef STIC_T_ #define STIC_T_ 1 typedef struct stic_t stic_t; #endif /* * ============================================================================ * NONE OF THIS TIMING CRAP IS USED. I'M DOING THIS A MUCH SIMPLER WAY NOW. * ============================================================================ * The STIC allows timely GRAM servicing only during VBLANK. Outside * VBLANK, the CPU is stalled with wait-states. The following macros * define the time period for VBLANK and DISPACTV. * * TODO: Consider making these config variables instead. * * STIC_COLBURST -- Color burst frequency (4x the system clock rate) * STIC_FRAMCLKS -- Number of system clocks in one frame * * These values are calculated from the following facts and assumptions. * * -- A full NTSC frame has 525 lines divided into two fields, * * -- As a result each field has 262.5 lines. * * -- The STIC has a vertical resolution of 192 pixels in the graphical * display area. * * -- I think we can safely assume that the STIC treats non-graphics card * areas as "blanking" time, even though it is actively outputting the * background color. (I may end up getting proven wrong here, but the * spec sheet seems to indicate this.) * * -- One display period in system clocks is the colorburst rate * divided by 240 for 60Hz NTSC. * * -- So, the DISPACTV time is 192/262.5 of the total display period * and VBLANK is the remainder. * * Note: This doesn't really take into account the fact that the active * display period shifts slightly when the vertical delay register is * set (for vertical scrolling). For the existing set of Intellivision * games, I don't think it really matters. The _really_ tricky programmers * that relied on exact synchronization behavior between the display chip * and the CPU didn't show up until the C64 demo competitions really took * off, I think. * ============================================================================ */ #define STIC_COLBURST 3579545 /* Exact */ #define STIC_FRAMCLKS 14934 #define STIC_INTRQ_HOLD (2920) #define STIC_BUSRQ_HOLD_FIRST (68) /* First BUSRQ is really short? */ #define STIC_BUSRQ_HOLD_NORMAL (108) /* Typical BUSRQs during display */ #define STIC_BUSRQ_HOLD_EXTRA (38) /* 14th BUSRQ is half-length */ #define STIC_MUST_BUSAK_TIME (68) /* CPU must ACK a BUSRQ by here */ #define STIC_BUSRQ_MARGIN (STIC_BUSRQ_HOLD_NORMAL - STIC_MUST_BUSAK_TIME) #define STIC_STIC_ACCESSIBLE (2900) /* STIC time window during vblank */ #define STIC_GMEM_ACCESSIBLE (3796) /* GRAM/GROM time window during vbl */ #define STIC_INITIAL_OFFSET (2782) /* Starting point of first frame. */ #define STIC_INITIAL_PHASE ( /* * ============================================================================ * STIC_CTRL_RD -- Read from a STIC control register. * STIC_CTRL_WR -- Write to a STIC control register. * STIC_BTAB_WR -- Monitor writes to BACKTAB * STIC_GRAM_WR -- Monitor writes to GRAM * ============================================================================ */ uint_32 stic_ctrl_rd(periph_t *per, periph_t *ign, uint_32 addr, uint_32 data); void stic_ctrl_wr(periph_t *per, periph_t *ign, uint_32 addr, uint_32 data); void stic_btab_wr(periph_t *per, periph_t *ign, uint_32 addr, uint_32 data); void stic_gram_wr(periph_t *per, periph_t *ign, uint_32 addr, uint_32 data); /* * ============================================================================ * STIC_INIT -- Initialize the STIC * STIC_TICK -- Perform a STIC update * ============================================================================ */ int stic_init ( stic_t *stic, uint_16 *grom_img, req_bus_t *irq, gfx_t *gfx, demo_t *demo ); uint_32 stic_tick ( periph_p per, uint_32 len ); #endif /* ======================================================================== */ /* This program is free software; you can redistribute it and/or modify */ /* it under the terms of the GNU General Public License as published by */ /* the Free Software Foundation; either version 2 of the License, or */ /* (at your option) any later version. */ /* */ /* This program is distributed in the hope that it will be useful, */ /* but WITHOUT ANY WARRANTY; without even the implied warranty of */ /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU */ /* General Public License for more details. */ /* */ /* You should have received a copy of the GNU General Public License */ /* along with this program; if not, write to the Free Software */ /* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ /* ======================================================================== */ /* Copyright (c) 1998-1999, Joseph Zbiciak */ /* ======================================================================== */