map050.c
  1  /*
  2  ** Nofrendo (c) 1998-2000 Matthew Conte (matt@conte.com)
  3  **
  4  **
  5  ** This program is free software; you can redistribute it and/or
  6  ** modify it under the terms of version 2 of the GNU Library General 
  7  ** Public License as published by the Free Software Foundation.
  8  **
  9  ** This program is distributed in the hope that it will be useful, 
 10  ** but WITHOUT ANY WARRANTY; without even the implied warranty of
 11  ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
 12  ** Library General Public License for more details.  To obtain a 
 13  ** copy of the GNU Library General Public License, write to the Free 
 14  ** Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 15  **
 16  ** Any permitted reproduction of these routines, in whole or in part,
 17  ** must bear this legend.
 18  **
 19  **
 20  ** map050.c
 21  **
 22  ** Mapper #50 (SMB2j - 3rd discovered variation)
 23  ** Implementation by Firebug
 24  ** Mapper information courtesy of Kevin Horton
 25  ** $Id: map050.c,v 1.2 2001/04/27 14:37:11 neil Exp $
 26  **
 27  */
 28  
 29  #include "noftypes.h"
 30  #include "nes_mmc.h"
 31  #include "nes.h"
 32  #include "libsnss.h"
 33  #include "log.h"
 34  
 35  static struct
 36  {
 37    bool enabled;
 38    uint32 counter;
 39  } irq;
 40  
 41  /********************************/
 42  /* Mapper #50 IRQ reset routine */
 43  /********************************/
 44  static void map50_irq_reset (void)
 45  {
 46    /* Turn off IRQs */
 47    irq.enabled = false;
 48    irq.counter = 0x0000;
 49  
 50    /* Done */
 51    return;
 52  }
 53  
 54  /**************************************************************/
 55  /* Mapper #50: 3rd discovered variation of SMB2j cart bootleg */
 56  /**************************************************************/
 57  static void map50_init (void)
 58  {
 59    /* Set the hardwired pages */
 60    mmc_bankrom (8, 0x6000, 0x0F);
 61    mmc_bankrom (8, 0x8000, 0x08);
 62    mmc_bankrom (8, 0xA000, 0x09);
 63    mmc_bankrom (8, 0xE000, 0x0B);
 64  
 65    /* Reset the IRQ counter */
 66    map50_irq_reset ();
 67  
 68    /* Done */
 69    return;
 70  }
 71  
 72  /****************************************/
 73  /* Mapper #50 callback for IRQ handling */
 74  /****************************************/
 75  static void map50_hblank (int vblank)
 76  {
 77     /* Counter is M2 based so it doesn't matter whether */
 78     /* the PPU is in its VBlank period or not           */
 79     UNUSED(vblank);
 80  
 81     /* Increment the counter if it is enabled and check for strike */
 82     if (irq.enabled)
 83     {
 84       /* Is there a constant for cycles per scanline? */
 85       /* If so, someone ought to substitute it here   */
 86       irq.counter = irq.counter + 114;
 87  
 88       /* IRQ line is hooked to Q12 of the counter */
 89       if (irq.counter & 0x1000)
 90       {
 91         /* Trigger the IRQ */
 92         nes_irq ();
 93  
 94         /* Reset the counter */
 95         map50_irq_reset ();
 96       }
 97     }
 98  }
 99  
100  /******************************************/
101  /* Mapper #50 write handler ($4000-$5FFF) */
102  /******************************************/
103  static void map50_write (uint32 address, uint8 value)
104  {
105    uint8 selectable_bank;
106  
107    /* For address to be decoded, A5 must be high and A6 low */
108    if ((address & 0x60) != 0x20) return;
109  
110    /* A8 low  = $C000-$DFFF page selection */
111    /* A8 high = IRQ timer toggle */
112    if (address & 0x100)
113    {
114      /* IRQ settings */
115      if (value & 0x01) irq.enabled = true;
116      else              map50_irq_reset ();
117    }
118    else
119    {
120      /* Stupid data line swapping */
121      selectable_bank = 0x00;
122      if (value & 0x08) selectable_bank |= 0x08;
123      if (value & 0x04) selectable_bank |= 0x02;
124      if (value & 0x02) selectable_bank |= 0x01;
125      if (value & 0x01) selectable_bank |= 0x04;
126      mmc_bankrom (8, 0xC000, selectable_bank);
127    }
128  
129    /* Done */
130    return;
131  }
132  
133  /****************************************************/
134  /* Shove extra mapper information into a SNSS block */
135  /****************************************************/
136  static void map50_setstate (SnssMapperBlock *state)
137  {
138    /* TODO: Store SNSS information */
139    UNUSED (state);
140  
141    /* Done */
142    return;
143  }
144  
145  /*****************************************************/
146  /* Pull extra mapper information out of a SNSS block */
147  /*****************************************************/
148  static void map50_getstate (SnssMapperBlock *state)
149  {
150    /* TODO: Retrieve SNSS information */
151    UNUSED (state);
152  
153    /* Done */
154    return;
155  }
156  
157  static const map_memwrite map50_memwrite [] =
158  {
159     { 0x4000, 0x5FFF, map50_write },
160     {     -1,     -1, NULL }
161  };
162  
163  const mapintf_t map50_intf =
164  {
165     50,                               /* Mapper number */
166     "SMB2j (3rd discovered variant)", /* Mapper name */
167     map50_init,                       /* Initialization routine */
168     NULL,                             /* VBlank callback */
169     map50_hblank,                     /* HBlank callback */
170     map50_getstate,                   /* Get state (SNSS) */
171     map50_setstate,                   /* Set state (SNSS) */
172     NULL,                             /* Memory read structure */
173     map50_memwrite,                   /* Memory write structure */
174     NULL                              /* External sound device */
175  };
176  
177  /*
178  ** $Log: map050.c,v $
179  ** Revision 1.2  2001/04/27 14:37:11  neil
180  ** wheeee
181  **
182  ** Revision 1.1  2001/04/27 12:54:40  neil
183  ** blah
184  **
185  ** Revision 1.1  2001/04/27 10:57:41  neil
186  ** wheee
187  **
188  ** Revision 1.1  2000/12/27 19:22:13  firebug
189  ** initial revision
190  **
191  **
192  */