updated bords/mappers/stuff to 0.98.15, lots of them got broken, asmcore support...
[fceu.git] / mappers / 24and26.c
index 50f732a..3368856 100644 (file)
@@ -1,7 +1,7 @@
 /* FCE Ultra - NES/Famicom Emulator
  *
  * Copyright notice for this file:
- *  Copyright (C) 2002 Ben Parnell
+ *  Copyright (C) 2002 Xodnizel
  *
  * 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
 
 #include "mapinc.h"
 
+static void (*sfun[3])(void);
+
 #define vrctemp mapbyte1[0]
-#define regb000 mapbyte3[0]
-#define regb001 mapbyte3[1]
-#define regb002 mapbyte3[2]
-#define exchstat mapbyte4[0]
 #define VPSG2 mapbyte3
 #define VPSG mapbyte2
 
@@ -33,81 +31,74 @@ static void DoSQV2(void);
 static void DoSawV(void);
 
 static int swaparoo;
-static int32 inc;
-static DECLFW(VRC6PSGW90)
-{
- DoSQV1();VPSG[0]=V;
-}
-static DECLFW(VRC6PSGW91)
-{
- DoSQV1();VPSG[2]=V;
-}
-static DECLFW(VRC6PSGW92)
-{
- DoSQV1();VPSG[3]=V;
-}
-static DECLFW(VRC6PSGWA0)
-{
- DoSQV2();VPSG[4]=V;
-}
-static DECLFW(VRC6PSGWA1)
-{
- DoSQV2();VPSG[6]=V;
-}
-static DECLFW(VRC6PSGWA2)
-{
- DoSQV2();VPSG[7]=V;
-}
-static DECLFW(VRC6PSGWB0)
-{
- DoSawV();VPSG2[0]=V;
-}
-static DECLFW(VRC6PSGWB1)
-{
- DoSawV();VPSG2[1]=V;
-}
-static DECLFW(VRC6PSGWB2)
-{
- DoSawV();VPSG2[2]=V;
-}
 
 static int acount=0;
 
 static void FP_FASTAPASS(1) KonamiIRQHook(int a)
 {
-  #define LCYCS 114
+  #define LCYCS 341
+//  #define LCYCS ((227*2)+1)
   if(IRQa)
   {
-   acount+=a;
+   acount+=a*3;
    if(acount>=LCYCS)
    {
     doagainbub:acount-=LCYCS;IRQCount++;
-    if(IRQCount==0x100) {TriggerIRQ();IRQCount=IRQLatch;}
+    if(IRQCount==0x100)
+    {
+     X6502_IRQBegin(FCEU_IQEXT);
+     IRQCount=IRQLatch;
+    }
     if(acount>=LCYCS) goto doagainbub;
    }
  }
 }
 
-DECLFW(Mapper24_write)
+static DECLFW(VRC6SW)
 {
-       if(swaparoo)
-        A=(A&0xFFFC)|((A>>1)&1)|((A<<1)&2);
+        A&=0xF003;
+        if(A>=0x9000 && A<=0x9002)
+        {
+         VPSG[A&3]=V;
+         if(sfun[0]) sfun[0]();
+        }
+        else if(A>=0xa000 && A<=0xa002)
+        {
+         VPSG[4|(A&3)]=V;
+         if(sfun[1]) sfun[1]();
+        }
+        else if(A>=0xb000 && A<=0xb002)
+        {
+         VPSG2[A&3]=V;
+         if(sfun[2]) sfun[2]();
+        }
 
+}
+
+static DECLFW(Mapper24_write)
+{
+        if(swaparoo)
+         A=(A&0xFFFC)|((A>>1)&1)|((A<<1)&2);
+        if(A>=0x9000 && A<=0xb002)
+        {
+         VRC6SW(A,V);
+         return;
+        }
+        A&=0xF003;
+//        if(A>=0xF000) printf("%d, %d, $%04x:$%02x\n",scanline,timestamp,A,V);
         switch(A&0xF003)
-       {
-         case 0x8000:ROM_BANK16(0x8000,V);
-                     X6502_Rebase();break;
+        {
+         case 0x8000:ROM_BANK16(0x8000,V);break;
          case 0xB003:
-                switch(V&0xF)
-                {
-                 case 0x0:MIRROR_SET2(1);break;
-                 case 0x4:MIRROR_SET2(0);break;
-                 case 0x8:onemir(0);break;
-                 case 0xC:onemir(1);break;
-                }
-                break;
-         case 0xC000:ROM_BANK8(0xC000,V);
-                     X6502_Rebase();break;
+                    switch(V&0xF)
+                 {
+                  case 0x0:MIRROR_SET2(1);break;
+                  case 0x4:MIRROR_SET2(0);break;
+                  case 0x8:onemir(0);break;
+                  case 0xC:onemir(1);break;
+                 }
+                 break;
+         case 0xC000:ROM_BANK8(0xC000,V);break;
          case 0xD000:VROM_BANK1(0x0000,V);break;
          case 0xD001:VROM_BANK1(0x0400,V);break;
          case 0xD002:VROM_BANK1(0x0800,V);break;
@@ -116,113 +107,73 @@ DECLFW(Mapper24_write)
          case 0xE001:VROM_BANK1(0x1400,V);break;
          case 0xE002:VROM_BANK1(0x1800,V);break;
          case 0xE003:VROM_BANK1(0x1c00,V);break;
-         case 0xF000:IRQLatch=V;break;
+         case 0xF000:IRQLatch=V;
+                        //acount=0;
+                        break;
          case 0xF001:IRQa=V&2;
                      vrctemp=V&1;
-                     if(V&2) {IRQCount=IRQLatch;}
-                    //acount=0;
+                     if(V&2)
+                     {
+                      IRQCount=IRQLatch;
+                      acount=0;
+                     }
+                     X6502_IRQEnd(FCEU_IQEXT);
                      break;
-         case 0xf002:IRQa=vrctemp;break;
+         case 0xf002:IRQa=vrctemp;
+                     X6502_IRQEnd(FCEU_IQEXT);break;
          case 0xF003:break;
   }
 }
 
-static int CVBC[3]={0,0,0};
-static int32 vcount[2];
+static int32 CVBC[3];
+static int32 vcount[3];
+static int32 dcount[2];
 
-static void DoSQV1(void)
+static INLINE void DoSQV(int x)
 {
-    uint8 amp;
-    int32 freq;
-    int V;
-    int32 start,end;
-
-    start=CVBC[0];
-    end=(SOUNDTS<<16)/soundtsinc;
-    if(end<=start) return;
-    CVBC[0]=end;
-
-    if(VPSG[0x3]&0x80)
+ int32 V;
+ int32 amp=(((VPSG[x<<2]&15)<<8)*6/8)>>4;
+ int32 start,end;
+
+ start=CVBC[x];
+ end=(SOUNDTS<<16)/soundtsinc;
+ if(end<=start) return;
+ CVBC[x]=end;
+
+ if(VPSG[(x<<2)|0x2]&0x80)
+ {
+  if(VPSG[x<<2]&0x80)
+  {
+   for(V=start;V<end;V++)
+    Wave[V>>4]+=amp;
+  }
+  else
+  {
+   int32 thresh=(VPSG[x<<2]>>4)&7;
+   int32 freq=((VPSG[(x<<2)|0x1]|((VPSG[(x<<2)|0x2]&15)<<8))+1)<<17;
+   for(V=start;V<end;V++)
+   {
+    if(dcount[x]>thresh)        /* Greater than, not >=.  Important. */
+     Wave[V>>4]+=amp;
+    vcount[x]-=nesincsize;
+    while(vcount[x]<=0)            /* Should only be <0 in a few circumstances. */
     {
-     amp=(VPSG[0]&15)<<4;
-     if(VPSG[0]&0x80)
-     {
-      for(V=start;V<end;V++)
-       Wave[V>>4]+=amp;
-     }
-     else
-     {
-      unsigned long dcycs;
-      freq=(((VPSG[0x2]|((VPSG[0x3]&15)<<8))+1));
-      inc=(long double)((unsigned long)((FSettings.SndRate OVERSAMPLE)<<12))/((long double)PSG_base/freq);
-      switch(VPSG[0]&0x70)
-      {
-       default:
-       case 0x00:dcycs=inc>>4;break;
-       case 0x10:dcycs=inc>>3;break;
-       case 0x20:dcycs=(inc*3)>>4;break;
-       case 0x30:dcycs=inc>>2;break;
-       case 0x40:dcycs=(inc*5)>>4;break;
-       case 0x50:dcycs=(inc*6)>>4;break;
-       case 0x60:dcycs=(inc*7)>>4;break;
-       case 0x70:dcycs=inc>>1;break;
-      }
-             for(V=start;V<end;V++)
-              {
-               if(vcount[0]<dcycs)
-                 Wave[V>>4]+=amp;
-               vcount[0]+=0x1000;
-               if(vcount[0]>=inc) vcount[0]-=inc;
-               }
-     }
+     vcount[x]+=freq;
+     dcount[x]=(dcount[x]+1)&15;
     }
+   }
+  }
+ }
 }
-static void DoSQV2(void)
-{
-    uint8 amp;
-    int32 freq;
-    int V;
-    int32 start,end;
 
-    start=CVBC[1];
-    end=(SOUNDTS<<16)/soundtsinc;
   if(end<=start) return;
-    CVBC[1]=end;
+static void DoSQV1(void)
+{
DoSQV(0);
+}
 
-    if(VPSG[0x7]&0x80)
-    {
-     amp=(VPSG[4]&15)<<4;
-     if(VPSG[4]&0x80)
-     {
-      for(V=start;V<end;V++)
-       Wave[V>>4]+=amp;
-     }
-     else
-     {
-      unsigned long dcycs;
-      freq=(((VPSG[0x6]|((VPSG[0x7]&15)<<8))+1));
-      inc=(long double)((unsigned long)((FSettings.SndRate OVERSAMPLE)<<12))/((long double)PSG_base/freq);
-      switch(VPSG[4]&0x70)
-      {
-       default:
-       case 0x00:dcycs=inc>>4;break;
-       case 0x10:dcycs=inc>>3;break;
-       case 0x20:dcycs=(inc*3)>>4;break;
-       case 0x30:dcycs=inc>>2;break;
-       case 0x40:dcycs=(inc*5)>>4;break;
-       case 0x50:dcycs=(inc*6)>>4;break;
-       case 0x60:dcycs=(inc*7)>>4;break;
-       case 0x70:dcycs=inc>>1;break;
-      }
-             for(V=start;V<end;V++)
-              {
-               if(vcount[1]<dcycs)
-                 Wave[V>>4]+=amp;
-               vcount[1]+=0x1000;
-               if(vcount[1]>=inc) vcount[1]-=inc;
-               }
-     }
-    }
+static void DoSQV2(void)
+{
+ DoSQV(1);
 }
 
 static void DoSawV(void)
@@ -237,7 +188,7 @@ static void DoSawV(void)
 
    if(VPSG2[2]&0x80)
    {
-    static int64 saw1phaseacc=0;
+    static int32 saw1phaseacc=0;
     uint32 freq3;
     static uint8 b3=0;
     static int32 phaseacc=0;
@@ -247,13 +198,13 @@ static void DoSawV(void)
 
     for(V=start;V<end;V++)
     {
-     saw1phaseacc-=nesincsizeLL;
+     saw1phaseacc-=nesincsize;
      if(saw1phaseacc<=0)
      {
-      int64 t;
+      int32 t;
       rea:
       t=freq3;
-      t<<=50;  // 49 + 1
+      t<<=18;
       saw1phaseacc+=t;
       phaseacc+=VPSG2[0]&0x3f;
       b3++;
@@ -264,90 +215,161 @@ static void DoSawV(void)
       }
       if(saw1phaseacc<=0)
        goto rea;
-      duff=(((phaseacc>>3)&0x1f)<<4);
+      duff=(((phaseacc>>3)&0x1f)<<4)*6/8;
       }
      Wave[V>>4]+=duff;
     }
    }
 }
 
-void VRC6Sound(int Count)
+#if 0
+static INLINE void DoSQVHQ(int x)
 {
-    int x;
+ int32 V;
+ int32 amp=((VPSG[x<<2]&15)<<8)*6/8;
 
-    DoSQV1();
-    DoSQV2();
-    DoSawV();
-    for(x=0;x<3;x++)
-     CVBC[x]=Count;
+ if(VPSG[(x<<2)|0x2]&0x80)
+ {
+  if(VPSG[x<<2]&0x80)
+  {
+   for(V=CVBC[x];V<SOUNDTS;V++)
+    WaveHi[V]+=amp;
+  }
+  else
+  {
+   int32 thresh=(VPSG[x<<2]>>4)&7;
+   for(V=CVBC[x];V<SOUNDTS;V++)
+   {
+    if(dcount[x]>thresh)        /* Greater than, not >=.  Important. */
+     WaveHi[V]+=amp;
+    vcount[x]--;
+    if(vcount[x]<=0)            /* Should only be <0 in a few circumstances. */
+    {
+     vcount[x]=(VPSG[(x<<2)|0x1]|((VPSG[(x<<2)|0x2]&15)<<8))+1;
+     dcount[x]=(dcount[x]+1)&15;
+    }
+   }
+  }
+ }
+ CVBC[x]=SOUNDTS;
 }
 
-static int satype=0;
+static void DoSQV1HQ(void)
+{
+ DoSQVHQ(0);
+}
 
-void VRC6SoundC(void)
+static void DoSQV2HQ(void)
 {
-  int x;
+ DoSQVHQ(1);
+}
 
-  if(FSettings.SndRate)
-   VRC6_ESI(satype);
-  else
+static void DoSawVHQ(void)
+{
+ static uint8 b3=0;
+ static int32 phaseacc=0;
+ int32 V;
+
+ if(VPSG2[2]&0x80)
+ {
+  for(V=CVBC[2];V<SOUNDTS;V++)
   {
-   for(x=000;x<0x1000;x+=4)
+   WaveHi[V]+=(((phaseacc>>3)&0x1f)<<8)*6/8;
+   vcount[2]--;
+   if(vcount[2]<=0)
    {
-          SetWriteHandler(0x9000+x,0x9002+x,0);
-          SetWriteHandler(0xa000+x,0xa002+x,0);
-          SetWriteHandler(0xb000+x,0xb002+x,0);
+    vcount[2]=(VPSG2[1]+((VPSG2[2]&15)<<8)+1)<<1;
+    phaseacc+=VPSG2[0]&0x3f;
+    b3++;
+    if(b3==7)
+    {
+     b3=0;
+     phaseacc=0;
+   }
+
    }
   }
+ }
+ CVBC[2]=SOUNDTS;
 }
+#endif
+
 
-void VRC6_ESI(int t)
+void VRC6Sound(int Count)
 {
-        int x;
+    int x;
 
-       satype=t;
+    DoSQV1();
+    DoSQV2();
+    DoSawV();
+    for(x=0;x<3;x++)
+     CVBC[x]=Count;
+}
 
-        GameExpSound.RChange=VRC6SoundC;
+#if 0
+void VRC6SoundHQ(void)
+{
+    DoSQV1HQ();
+    DoSQV2HQ();
+    DoSawVHQ();
+}
+
+void VRC6SyncHQ(int32 ts)
+{
+ int x;
+ for(x=0;x<3;x++) CVBC[x]=ts;
+}
+#endif
+
+static void VRC6_ESI(void)
+{
+        GameExpSound.RChange=VRC6_ESI;
         GameExpSound.Fill=VRC6Sound;
+        GameExpSound.HiFill=0;//VRC6SoundHQ;
+        GameExpSound.HiSync=0;//VRC6SyncHQ;
+
+        memset(CVBC,0,sizeof(CVBC));
+        memset(vcount,0,sizeof(vcount));
+        memset(dcount,0,sizeof(dcount));
         if(FSettings.SndRate)
-         for(x=000;x<0x1000;x+=4)
+        {
+#if 0
+         if(FSettings.soundq>=1)
+         {
+          sfun[0]=DoSQV1HQ;
+          sfun[1]=DoSQV2HQ;
+          sfun[2]=DoSawVHQ;
+         }
+         else
+#endif
          {
-          uint32 a;
-
-          a=0x9000+x;
-          SetWriteHandler(a,a,VRC6PSGW90);
-          SetWriteHandler(a+(1^t),a+(1^t),VRC6PSGW91);
-          SetWriteHandler(a+(2^t),a+(2^t),VRC6PSGW92);
-
-          a=0xa000+x;
-          SetWriteHandler(a,a,VRC6PSGWA0);
-          SetWriteHandler(a+(1^t),a+(1^t),VRC6PSGWA1);
-          SetWriteHandler(a+(2^t),a+(2^t),VRC6PSGWA2);
-
-          a=0xb000+x;
-          SetWriteHandler(a,a,VRC6PSGWB0);
-          SetWriteHandler(a+(1^t),a+(1^t),VRC6PSGWB1);
-          SetWriteHandler(a+(2^t),a+(2^t),VRC6PSGWB2);
+          sfun[0]=DoSQV1;
+          sfun[1]=DoSQV2;
+          sfun[2]=DoSawV;
          }
+        }
+        else
+         memset(sfun,0,sizeof(sfun));
 }
 
 void Mapper24_init(void)
 {
         SetWriteHandler(0x8000,0xffff,Mapper24_write);
-        if(FSettings.SndRate)
-         VRC6_ESI(0);
-        GameExpSound.RChange=VRC6SoundC;
+        VRC6_ESI();
         MapIRQHook=KonamiIRQHook;
-       swaparoo=0;
+        swaparoo=0;
 }
 
 void Mapper26_init(void)
 {
         SetWriteHandler(0x8000,0xffff,Mapper24_write);
-       if(FSettings.SndRate)
-         VRC6_ESI(3);
-       GameExpSound.RChange=VRC6SoundC;
+        VRC6_ESI();
         MapIRQHook=KonamiIRQHook;
-       swaparoo=1;
+        swaparoo=1;
 }
 
+void NSFVRC6_Init(void)
+{
+        VRC6_ESI();
+        SetWriteHandler(0x8000,0xbfff,VRC6SW);
+}