Advertisement
Guest User

Untitled

a guest
Jun 20th, 2016
261
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 32.71 KB | None | 0 0
  1. /***********************************************************************************
  2.   Snes9x - Portable Super Nintendo Entertainment System (TM) emulator.
  3.  
  4.   (c) Copyright 1996 - 2002  Gary Henderson (gary.henderson@ntlworld.com),
  5.                              Jerremy Koot (jkoot@snes9x.com)
  6.  
  7.   (c) Copyright 2002 - 2004  Matthew Kendora
  8.  
  9.   (c) Copyright 2002 - 2005  Peter Bortas (peter@bortas.org)
  10.  
  11.   (c) Copyright 2004 - 2005  Joel Yliluoma (http://iki.fi/bisqwit/)
  12.  
  13.   (c) Copyright 2001 - 2006  John Weidman (jweidman@slip.net)
  14.  
  15.   (c) Copyright 2002 - 2006  funkyass (funkyass@spam.shaw.ca),
  16.                              Kris Bleakley (codeviolation@hotmail.com)
  17.  
  18.   (c) Copyright 2002 - 2010  Brad Jorsch (anomie@users.sourceforge.net),
  19.                              Nach (n-a-c-h@users.sourceforge.net),
  20.                              zones (kasumitokoduck@yahoo.com)
  21.  
  22.   (c) Copyright 2006 - 2007  nitsuja
  23.  
  24.   (c) Copyright 2009 - 2010  BearOso,
  25.                              OV2
  26.  
  27.  
  28.   BS-X C emulator code
  29.   (c) Copyright 2005 - 2006  Dreamer Nom,
  30.                              zones
  31.  
  32.   C4 x86 assembler and some C emulation code
  33.   (c) Copyright 2000 - 2003  _Demo_ (_demo_@zsnes.com),
  34.                              Nach,
  35.                              zsKnight (zsknight@zsnes.com)
  36.  
  37.   C4 C++ code
  38.   (c) Copyright 2003 - 2006  Brad Jorsch,
  39.                              Nach
  40.  
  41.   DSP-1 emulator code
  42.   (c) Copyright 1998 - 2006  _Demo_,
  43.                              Andreas Naive (andreasnaive@gmail.com),
  44.                              Gary Henderson,
  45.                              Ivar (ivar@snes9x.com),
  46.                              John Weidman,
  47.                              Kris Bleakley,
  48.                              Matthew Kendora,
  49.                              Nach,
  50.                              neviksti (neviksti@hotmail.com)
  51.  
  52.   DSP-2 emulator code
  53.   (c) Copyright 2003         John Weidman,
  54.                              Kris Bleakley,
  55.                              Lord Nightmare (lord_nightmare@users.sourceforge.net),
  56.                              Matthew Kendora,
  57.                              neviksti
  58.  
  59.   DSP-3 emulator code
  60.   (c) Copyright 2003 - 2006  John Weidman,
  61.                              Kris Bleakley,
  62.                              Lancer,
  63.                              z80 gaiden
  64.  
  65.   DSP-4 emulator code
  66.   (c) Copyright 2004 - 2006  Dreamer Nom,
  67.                              John Weidman,
  68.                              Kris Bleakley,
  69.                              Nach,
  70.                              z80 gaiden
  71.  
  72.   OBC1 emulator code
  73.   (c) Copyright 2001 - 2004  zsKnight,
  74.                              pagefault (pagefault@zsnes.com),
  75.                              Kris Bleakley
  76.                              Ported from x86 assembler to C by sanmaiwashi
  77.  
  78.   SPC7110 and RTC C++ emulator code used in 1.39-1.51
  79.   (c) Copyright 2002         Matthew Kendora with research by
  80.                              zsKnight,
  81.                              John Weidman,
  82.                              Dark Force
  83.  
  84.   SPC7110 and RTC C++ emulator code used in 1.52+
  85.   (c) Copyright 2009         byuu,
  86.                              neviksti
  87.  
  88.   S-DD1 C emulator code
  89.   (c) Copyright 2003         Brad Jorsch with research by
  90.                              Andreas Naive,
  91.                              John Weidman
  92.  
  93.   S-RTC C emulator code
  94.   (c) Copyright 2001 - 2006  byuu,
  95.                              John Weidman
  96.  
  97.   ST010 C++ emulator code
  98.   (c) Copyright 2003         Feather,
  99.                              John Weidman,
  100.                              Kris Bleakley,
  101.                              Matthew Kendora
  102.  
  103.   Super FX x86 assembler emulator code
  104.   (c) Copyright 1998 - 2003  _Demo_,
  105.                              pagefault,
  106.                              zsKnight
  107.  
  108.   Super FX C emulator code
  109.   (c) Copyright 1997 - 1999  Ivar,
  110.                              Gary Henderson,
  111.                              John Weidman
  112.  
  113.   Sound emulator code used in 1.5-1.51
  114.   (c) Copyright 1998 - 2003  Brad Martin
  115.   (c) Copyright 1998 - 2006  Charles Bilyue'
  116.  
  117.   Sound emulator code used in 1.52+
  118.   (c) Copyright 2004 - 2007  Shay Green (gblargg@gmail.com)
  119.  
  120.   SH assembler code partly based on x86 assembler code
  121.   (c) Copyright 2002 - 2004  Marcus Comstedt (marcus@mc.pp.se)
  122.  
  123.   2xSaI filter
  124.   (c) Copyright 1999 - 2001  Derek Liauw Kie Fa
  125.  
  126.   HQ2x, HQ3x, HQ4x filters
  127.   (c) Copyright 2003         Maxim Stepin (maxim@hiend3d.com)
  128.  
  129.   NTSC filter
  130.   (c) Copyright 2006 - 2007  Shay Green
  131.  
  132.   GTK+ GUI code
  133.   (c) Copyright 2004 - 2010  BearOso
  134.  
  135.   Win32 GUI code
  136.   (c) Copyright 2003 - 2006  blip,
  137.                              funkyass,
  138.                              Matthew Kendora,
  139.                              Nach,
  140.                              nitsuja
  141.   (c) Copyright 2009 - 2010  OV2
  142.  
  143.   Mac OS GUI code
  144.   (c) Copyright 1998 - 2001  John Stiles
  145.   (c) Copyright 2001 - 2010  zones
  146.  
  147.  
  148.   Specific ports contains the works of other authors. See headers in
  149.   individual files.
  150.  
  151.  
  152.   Snes9x homepage: http://www.snes9x.com/
  153.  
  154.   Permission to use, copy, modify and/or distribute Snes9x in both binary
  155.   and source form, for non-commercial purposes, is hereby granted without
  156.   fee, providing that this license information and copyright notice appear
  157.   with all copies and any derived work.
  158.  
  159.   This software is provided 'as-is', without any express or implied
  160.   warranty. In no event shall the authors be held liable for any damages
  161.   arising from the use of this software or it's derivatives.
  162.  
  163.   Snes9x is freeware for PERSONAL USE only. Commercial users should
  164.   seek permission of the copyright holders first. Commercial use includes,
  165.   but is not limited to, charging money for Snes9x or software derived from
  166.   Snes9x, including Snes9x or derivatives in commercial game bundles, and/or
  167.   using Snes9x as a promotion for your commercial product.
  168.  
  169.   The copyright holders request that bug fixes and improvements to the code
  170.   should be forwarded to them so everyone can benefit from the modifications
  171.   in future versions.
  172.  
  173.   Super NES and Super Nintendo Entertainment System are trademarks of
  174.   Nintendo Co., Limited and its subsidiary companies.
  175.  ***********************************************************************************/
  176.  
  177. #include <string.h>
  178. #include "snes9x.h"
  179. #include "memmap.h"
  180. #include "getset.h"
  181. #include "cpuops.h"
  182. #include "dma.h"
  183. #include "apu.h"
  184. #include "fxinst.h"
  185. #include "fxemu.h"
  186. #include "controls.h"
  187. #include "cheats.h"
  188. #include "snapshot.h"
  189.  
  190. extern struct SLineData     LineData[240];
  191. extern struct SLineMatrixData   LineMatrixData[240];
  192. extern uint8    *HDMAMemPointers[8];
  193. static uint32 idle_loop_target_pc;
  194. static bool8 idle_loop_elimination_enable;
  195.  
  196. bool8 finishedFrame = false;
  197.  
  198. void S9xMainLoop (void)
  199. {
  200.     do
  201.     {
  202.         do
  203.         {
  204.             register uint8  Op;
  205.             register struct SOpcodes *Opcodes;
  206.  
  207.             /* Speedhack - skip idle loop if exists. */
  208.             if (idle_loop_elimination_enable &&
  209.                 (Registers.PBPC == idle_loop_target_pc) && (CPU.Cycles < CPU.NextEvent))
  210.              CPU.Cycles = CPU.NextEvent;
  211.  
  212.             if (CPU.Flags)
  213.             {
  214.                 if (CPU.Flags & NMI_FLAG)
  215.                 {
  216.                     if (Timings.NMITriggerPos <= CPU.Cycles)
  217.                     {
  218.                         CPU.Flags &= ~NMI_FLAG;
  219.                         Timings.NMITriggerPos = 0xffff;
  220.                         if (CPU.WaitingForInterrupt)
  221.                         {
  222.                             CPU.WaitingForInterrupt = FALSE;
  223.                             Registers.PCw++;
  224.                         }
  225.  
  226.                         S9xOpcode_NMI();
  227.                     }
  228.                 }
  229.  
  230.  
  231.                 if (CPU.Flags & IRQ_FLAG)
  232.                 {
  233.                     if (CPU.IRQPending)
  234.                         CPU.IRQPending--;   /* FIXME: In case of IRQ during WRAM refresh */
  235.                     else
  236.                     {
  237.                         if (CPU.WaitingForInterrupt)
  238.                         {
  239.                             CPU.WaitingForInterrupt = FALSE;
  240.                             Registers.PCw++;
  241.                         }
  242.  
  243.                         if (CPU.IRQActive)
  244.                         {
  245.                             /* in IRQ handler $4211 is supposed to be read, so IRQ_FLAG should be cleared. */
  246.                             if (!CheckFlag(IRQ))
  247.                                 S9xOpcode_IRQ();
  248.                         }
  249.                         else
  250.                             CPU.Flags &= ~IRQ_FLAG;
  251.                     }
  252.                 }
  253.  
  254.                 if (CPU.Flags & SCAN_KEYS_FLAG)
  255.                     break;
  256.  
  257.             }
  258.  
  259.             Opcodes = S9xOpcodesSlow;
  260.  
  261.             CPU.PrevCycles = CPU.Cycles;
  262.  
  263.             if (CPU.PCBase)
  264.             {
  265.                 Op = CPU.PCBase[Registers.PCw];
  266.                 CPU.Cycles += CPU.MemSpeed;
  267.                 Opcodes = ICPU.S9xOpcodes;
  268.             }
  269.             else
  270.             {
  271.                 Op = S9xGetByte(Registers.PBPC);
  272.                 OpenBus = Op;
  273.             }
  274.  
  275.             if ((Registers.PCw & MEMMAP_MASK) + ICPU.S9xOpLengths[Op] >= MEMMAP_BLOCK_SIZE)
  276.             {
  277.                 uint8   *oldPCBase = CPU.PCBase;
  278.  
  279.                 CPU.PCBase = S9xGetBasePointer(ICPU.ShiftedPB + ((uint16) (Registers.PCw + 4)));
  280.                 if (oldPCBase != CPU.PCBase || (Registers.PCw & ~MEMMAP_MASK) == (0xffff & ~MEMMAP_MASK))
  281.                     Opcodes = S9xOpcodesSlow;
  282.             }
  283.  
  284.             Registers.PCw++;
  285.             (*Opcodes[Op].S9xOpcode)();
  286.  
  287.  
  288.             if (Settings.SA1)
  289.                 S9xSA1MainLoop();
  290.  
  291.         #if (S9X_ACCURACY_LEVEL <= 2)
  292.             while (CPU.Cycles >= CPU.NextEvent)
  293.                 S9xDoHEventProcessing();
  294.         #endif
  295.        
  296.             if (finishedFrame)
  297.                 break;
  298.            
  299.         }while(1);
  300.  
  301.         if (!finishedFrame)
  302.         {
  303.             S9xPackStatus();
  304.  
  305.             if (CPU.Flags & SCAN_KEYS_FLAG)
  306.             {
  307.                 CPU.Flags &= ~SCAN_KEYS_FLAG;
  308.             }
  309.         }
  310.         else
  311.         {
  312.             finishedFrame = false;
  313.             break;
  314.         }
  315.     }while(!finishedFrame);
  316. }
  317.  
  318.  
  319. static void S9xCheckMissingHTimerPosition (void)
  320. {
  321.     if (PPU.HTimerEnabled && (!PPU.VTimerEnabled || (CPU.V_Counter == PPU.VTimerPosition)))
  322.     {
  323.         S9X_SET_IRQ(PPU_IRQ_SOURCE);
  324.     }
  325.     else if (PPU.VTimerEnabled && (CPU.V_Counter == PPU.VTimerPosition))
  326.     {
  327.         S9X_SET_IRQ(PPU_IRQ_SOURCE);
  328.     }
  329. }
  330.  
  331. static void S9xCheckMissingHTimerHalt(void)
  332. {
  333.     if (PPU.HTimerEnabled && (!PPU.VTimerEnabled || (CPU.V_Counter == PPU.VTimerPosition)))
  334.         CPU.IRQPending = 1;
  335.     else if (PPU.VTimerEnabled && (CPU.V_Counter == PPU.VTimerPosition))
  336.         CPU.IRQPending = 1;
  337. }
  338.  
  339. static INLINE void speedhacks_manager (void)
  340. {
  341.     uint8 var_mem, var_mem2, var_mem3;
  342.    
  343.    idle_loop_target_pc = 0x00;
  344.    idle_loop_elimination_enable = FALSE;
  345.  
  346.     switch(Settings.SpeedhackGameID)
  347.    {
  348.       case SPEEDHACK_CT:
  349.          /* Chrono Trigger mid-frame overscan hack - field to battle transition */
  350.          if (IPPU.RenderedScreenHeight == 239)
  351.             IPPU.RenderedScreenHeight = 224;
  352.          break;
  353.       case SPEEDHACK_DKC1:
  354.          PPU.SFXSpeedupHack = FALSE;
  355.          var_mem = Memory.RAM[0x003E]; /* current level - 7E003E */
  356.          //fprintf(stderr, "current_level: %d.\n", ram);
  357.          if(var_mem == 49 || var_mem == 217 || var_mem == 66 || var_mem == 67)
  358.             PPU.SFXSpeedupHack = TRUE;
  359.          break;
  360.       case SPEEDHACK_FF6:
  361.          PPU.FullClipping = FALSE;
  362.          coldata_update_screen = FALSE;
  363.  
  364.          var_mem = Memory.RAM[0x0063]; /* menu on/off - 7E0063 */
  365.          var_mem2 = Memory.RAM[0x3A8F]; /* battle active - 3A8F */
  366.          var_mem3 = Memory.RAM[0x00BA]; /* covers window toggle - 8991 */
  367.          if(var_mem)
  368.             PPU.FullClipping = var_mem;
  369.  
  370.          /* check if window toggle is on */
  371.          if(var_mem3 == 1)
  372.             coldata_update_screen = TRUE;
  373.          /* check if menu or battle screen is on */
  374.          if(var_mem2 == 1)
  375.             coldata_update_screen = TRUE;
  376.          if(var_mem)
  377.             coldata_update_screen = TRUE;
  378.          break;
  379. #if 0
  380.       case SPEEDHACK_KILLER_INSTINCT:
  381.          {
  382.             PPU.SFXSpeedupHack = TRUE;
  383.             //fprintf(stderr, "character: %d\n", Memory.RAM[0x024E]);
  384.             //fprintf(stderr, "character #2: %d\n", Memory.RAM[0x0252]);
  385.             //fprintf(stderr, "stage: %d\n", Memory.RAM[0x12F0]);
  386.             uint8 level = Memory.RAM[0x12F0]; /* current level - 8012F0XX */
  387.             if(level == 8)
  388.                PPU.SFXSpeedupHack = FALSE;
  389.             break;
  390.          }
  391.       case SPEEDHACK_SUPER_METROID:
  392.          {
  393.             uint8 song = (Memory.RAM[0x07f3] | Memory.RAM[0x07f4] << 8);
  394.             fprintf(stderr, "current_song: %d.\n", song);
  395.          }
  396. #endif
  397.       case SPEEDHACK_STAR_FOX_1:
  398.          if (PPU.BGMode == 1 || PPU.BGMode == 2)
  399.             PPU.SFXSpeedupHack = TRUE;
  400.          else
  401.             PPU.SFXSpeedupHack = FALSE;
  402.          break;
  403.       case SPEEDHACK_SUPER_MARIO_WORLD:
  404.          idle_loop_target_pc = 0x00806B;
  405.          idle_loop_elimination_enable = TRUE;
  406.          break;
  407.       default:
  408.          break;
  409.    }
  410. }
  411.  
  412. static void S9xEndScreenRefresh (void)
  413. {
  414.     FLUSH_REDRAW();
  415.  
  416.    PPU.GunVLatch = 1000; /* i.e., never latch */
  417.    PPU.GunHLatch = 0;
  418.  
  419.    if (!Settings.NormalControls && pad_read)
  420.       S9xControlEOF();
  421.  
  422.     pad_read      = FALSE;
  423.  
  424.     if(Settings.SpeedhackGameID > SPEEDHACK_NONE)
  425.         speedhacks_manager();
  426.  
  427.     if (!(GFX.DoInterlace && GFX.InterlaceFrame == 0))
  428.         S9xDeinitUpdate(IPPU.RenderedScreenWidth, IPPU.RenderedScreenHeight);
  429.    
  430.     S9xApplyCheats();
  431. }
  432.  
  433. static void RenderLine (uint8 C)
  434. {
  435.     LineData[C].BG[0].VOffset = PPU.BG[0].VOffset + 1;
  436.     LineData[C].BG[0].HOffset = PPU.BG[0].HOffset;
  437.     LineData[C].BG[1].VOffset = PPU.BG[1].VOffset + 1;
  438.     LineData[C].BG[1].HOffset = PPU.BG[1].HOffset;
  439.  
  440.     if (PPU.BGMode == 7)
  441.     {
  442.         struct SLineMatrixData *p = &LineMatrixData[C];
  443.         p->MatrixA = PPU.MatrixA;
  444.         p->MatrixB = PPU.MatrixB;
  445.         p->MatrixC = PPU.MatrixC;
  446.         p->MatrixD = PPU.MatrixD;
  447.         p->CentreX = PPU.CentreX;
  448.         p->CentreY = PPU.CentreY;
  449.         p->M7HOFS  = PPU.M7HOFS;
  450.         p->M7VOFS  = PPU.M7VOFS;
  451.     }
  452.     else
  453.     {
  454.         LineData[C].BG[2].VOffset = PPU.BG[2].VOffset + 1;
  455.         LineData[C].BG[2].HOffset = PPU.BG[2].HOffset;
  456.         LineData[C].BG[3].VOffset = PPU.BG[3].VOffset + 1;
  457.         LineData[C].BG[3].HOffset = PPU.BG[3].HOffset;
  458.     }
  459.  
  460.     IPPU.CurrentLine = C + 1;
  461. }
  462.  
  463. static INLINE void S9xReschedule (void)
  464. {
  465.     uint8 next;
  466.     int32 hpos;
  467.  
  468.     next = 0;
  469.     hpos = 0;
  470.  
  471.     switch (CPU.WhichEvent)
  472.     {
  473.         case HC_HBLANK_START_EVENT:
  474.         case HC_IRQ_1_3_EVENT:
  475.             next = HC_HDMA_START_EVENT;
  476.             hpos = Timings.HDMAStart;
  477.             break;
  478.  
  479.         case HC_HDMA_START_EVENT:
  480.         case HC_IRQ_3_5_EVENT:
  481.             next = HC_HCOUNTER_MAX_EVENT;
  482.             hpos = Timings.H_Max;
  483.             break;
  484.  
  485.         case HC_HCOUNTER_MAX_EVENT:
  486.         case HC_IRQ_5_7_EVENT:
  487.             next = HC_HDMA_INIT_EVENT;
  488.             hpos = Timings.HDMAInit;
  489.             break;
  490.  
  491.         case HC_HDMA_INIT_EVENT:
  492.         case HC_IRQ_7_9_EVENT:
  493.             next = HC_RENDER_EVENT;
  494.             hpos = Timings.RenderPos;
  495.             break;
  496.  
  497.         case HC_RENDER_EVENT:
  498.         case HC_IRQ_9_A_EVENT:
  499.             next = HC_WRAM_REFRESH_EVENT;
  500.             hpos = Timings.WRAMRefreshPos;
  501.             break;
  502.  
  503.         case HC_WRAM_REFRESH_EVENT:
  504.         case HC_IRQ_A_1_EVENT:
  505.             next = HC_HBLANK_START_EVENT;
  506.             hpos = Timings.HBlankStart;
  507.             break;
  508.     }
  509.  
  510.     if (((int32) PPU.HTimerPosition > CPU.NextEvent) && ((int32) PPU.HTimerPosition < hpos))
  511.     {
  512.         hpos = (int32) PPU.HTimerPosition;
  513.  
  514.         switch (next)
  515.         {
  516.             case HC_HDMA_START_EVENT:
  517.                 next = HC_IRQ_1_3_EVENT;
  518.                 break;
  519.  
  520.             case HC_HCOUNTER_MAX_EVENT:
  521.                 next = HC_IRQ_3_5_EVENT;
  522.                 break;
  523.  
  524.             case HC_HDMA_INIT_EVENT:
  525.                 next = HC_IRQ_5_7_EVENT;
  526.                 break;
  527.  
  528.             case HC_RENDER_EVENT:
  529.                 next = HC_IRQ_7_9_EVENT;
  530.                 break;
  531.  
  532.             case HC_WRAM_REFRESH_EVENT:
  533.                 next = HC_IRQ_9_A_EVENT;
  534.                 break;
  535.  
  536.             case HC_HBLANK_START_EVENT:
  537.                 next = HC_IRQ_A_1_EVENT;
  538.                 break;
  539.         }
  540.     }
  541.  
  542.     CPU.NextEvent  = hpos;
  543.     CPU.WhichEvent = next;
  544. }
  545.  
  546.  
  547. static INLINE bool8 HDMAReadLineCount (int d)
  548. {
  549.     /* CPU.InDMA is set, so S9xGetXXX() / S9xSetXXX() incur no charges. */
  550.  
  551.     uint8   line;
  552.  
  553.     line = S9xGetByte((DMA[d].ABank << 16) + DMA[d].Address);
  554.     CPU.Cycles += SLOW_ONE_CYCLE;
  555.  
  556.     DMA[d].LineCount = 128;
  557.  
  558.     if (!line)
  559.     {
  560.         DMA[d].Repeat = FALSE;
  561.  
  562.         if (DMA[d].HDMAIndirectAddressing)
  563.         {
  564.             if (PPU.HDMA & (0xfe << d))
  565.             {
  566.                 DMA[d].Address++;
  567.                 CPU.Cycles += (SLOW_ONE_CYCLE << 1);
  568.             }
  569.             else
  570.                 CPU.Cycles += SLOW_ONE_CYCLE;
  571.  
  572.             DMA[d].IndirectAddress = S9xGetWord((DMA[d].ABank << 16) + DMA[d].Address, WRAP_NONE);
  573.             DMA[d].Address++;
  574.         }
  575.  
  576.         DMA[d].Address++;
  577.         HDMAMemPointers[d] = NULL;
  578.  
  579.         return (FALSE);
  580.     }
  581.     else
  582.     if (line == 0x80)
  583.         DMA[d].Repeat = TRUE;
  584.     else
  585.     {
  586.         DMA[d].Repeat = !(line & 0x80);
  587.         DMA[d].LineCount = line & 0x7f;
  588.     }
  589.  
  590.     DMA[d].Address++;
  591.     DMA[d].DoTransfer = TRUE;
  592.  
  593.     if (DMA[d].HDMAIndirectAddressing)
  594.     {
  595.         CPU.Cycles += (SLOW_ONE_CYCLE << 1);
  596.         DMA[d].IndirectAddress = S9xGetWord((DMA[d].ABank << 16) + DMA[d].Address, WRAP_NONE);
  597.         DMA[d].Address += 2;
  598.         HDMAMemPointers[d] = S9xGetMemPointer((DMA[d].IndirectBank << 16) + DMA[d].IndirectAddress);
  599.     }
  600.     else
  601.         HDMAMemPointers[d] = S9xGetMemPointer((DMA[d].ABank << 16) + DMA[d].Address);
  602.  
  603.     return (TRUE);
  604. }
  605.  
  606. static void S9xStartHDMA (void)
  607. {
  608.     uint8 i;
  609.     int32 tmpch;
  610.  
  611.     PPU.HDMA = Memory.FillRAM[0x420c];
  612.     PPU.HDMAEnded = 0;
  613.  
  614.     CPU.InHDMA = TRUE;
  615.     CPU.InDMAorHDMA = TRUE;
  616.  
  617.     tmpch = CPU.CurrentDMAorHDMAChannel;
  618.  
  619.     /* XXX: Not quite right... */
  620.     if (PPU.HDMA != 0)
  621.         CPU.Cycles += Timings.DMACPUSync;
  622.  
  623.     for ( i = 0; i < 8; i++)
  624.     {
  625.         if (PPU.HDMA & (1 << i))
  626.         {
  627.             CPU.CurrentDMAorHDMAChannel = i;
  628.  
  629.             DMA[i].Address = DMA[i].AAddress;
  630.  
  631.             if (!HDMAReadLineCount(i))
  632.             {
  633.                 PPU.HDMA &= ~(1 << i);
  634.                 PPU.HDMAEnded |= (1 << i);
  635.             }
  636.         }
  637.         else
  638.             DMA[i].DoTransfer = FALSE;
  639.     }
  640.  
  641.     CPU.InHDMA = FALSE;
  642.     CPU.InDMAorHDMA = CPU.InDMA;
  643.     CPU.HDMARanInDMA = CPU.InDMA ? PPU.HDMA : 0;
  644.     CPU.CurrentDMAorHDMAChannel = tmpch;
  645. }
  646.  
  647. static int HDMA_ModeByteCounts[8] =
  648. {
  649.     1, 2, 2, 4, 4, 4, 2, 4
  650. };
  651.  
  652. static uint8 S9xDoHDMA (uint8 byte)
  653. {
  654.     uint8 mask;
  655.     uint32  ShiftedIBank;
  656.     uint16  IAddr;
  657.     bool8   temp;
  658.     int32   tmpch;
  659.     int d;
  660.     struct SDMA *p;
  661.  
  662.     p = &DMA[0];
  663.  
  664.     d = 0;
  665.  
  666.     CPU.InHDMA = TRUE;
  667.     CPU.InDMAorHDMA = TRUE;
  668.     CPU.HDMARanInDMA = CPU.InDMA ? byte : 0;
  669.     temp = CPU.InWRAMDMAorHDMA;
  670.     tmpch = CPU.CurrentDMAorHDMAChannel;
  671.  
  672.     /* XXX: Not quite right... */
  673.     CPU.Cycles += Timings.DMACPUSync;
  674.  
  675.     for ( mask = 1; mask; mask <<= 1, p++, d++)
  676.     {
  677.         if (byte & mask)
  678.         {
  679.             CPU.InWRAMDMAorHDMA = FALSE;
  680.             CPU.CurrentDMAorHDMAChannel = d;
  681.  
  682.             if (p->HDMAIndirectAddressing)
  683.             {
  684.                 ShiftedIBank = (p->IndirectBank << 16);
  685.                 IAddr = p->IndirectAddress;
  686.             }
  687.             else
  688.             {
  689.                 ShiftedIBank = (p->ABank << 16);
  690.                 IAddr = p->Address;
  691.             }
  692.  
  693.             if (!HDMAMemPointers[d])
  694.                 HDMAMemPointers[d] = S9xGetMemPointer(ShiftedIBank + IAddr);
  695.  
  696.             if (p->DoTransfer)
  697.             {
  698.                 /* XXX: Hack for Uniracers, because we don't understand
  699.                 OAM Address Invalidation */
  700.                 if (p->BAddress == 0x04 && SNESGameFixes.Uniracers)
  701.                 {
  702.                     PPU.OAMAddr = 0x10c;
  703.                     PPU.OAMFlip = 0;
  704.                 }
  705.  
  706.  
  707.                 if (!p->ReverseTransfer)
  708.                 {
  709.                     if ((IAddr & MEMMAP_MASK) + HDMA_ModeByteCounts[p->TransferMode] >= MEMMAP_BLOCK_SIZE)
  710.                     {
  711.                         /* HDMA REALLY-SLOW PATH */
  712.                         HDMAMemPointers[d] = NULL;
  713.  
  714.                         #define DOBYTE(Addr, RegOff) \
  715.                             CPU.InWRAMDMAorHDMA = (ShiftedIBank == 0x7e0000 || ShiftedIBank == 0x7f0000 || \
  716.                                 (!(ShiftedIBank & 0x400000) && ((uint16) (Addr)) < 0x2000)); \
  717.                             S9xSetPPU(S9xGetByte(ShiftedIBank + ((uint16) (Addr))), 0x2100 + p->BAddress + (RegOff));
  718.  
  719.                         DOBYTE(IAddr, 0);
  720.                         CPU.Cycles += SLOW_ONE_CYCLE;
  721.                         switch (p->TransferMode)
  722.                         {
  723.                             case 0:
  724.                                 break;
  725.  
  726.                             case 5:
  727.                                 DOBYTE(IAddr + 1, 1);
  728.                                 CPU.Cycles += SLOW_ONE_CYCLE;
  729.                                 DOBYTE(IAddr + 2, 0);
  730.                                 CPU.Cycles += SLOW_ONE_CYCLE;
  731.                                 DOBYTE(IAddr + 3, 1);
  732.                                 CPU.Cycles += SLOW_ONE_CYCLE;
  733.                                 break;
  734.  
  735.                             case 1:
  736.                                 DOBYTE(IAddr + 1, 1);
  737.                                 CPU.Cycles += SLOW_ONE_CYCLE;
  738.                                 break;
  739.  
  740.                             case 2:
  741.                             case 6:
  742.                                 DOBYTE(IAddr + 1, 0);
  743.                                 CPU.Cycles += SLOW_ONE_CYCLE;
  744.                                 break;
  745.  
  746.                             case 3:
  747.                             case 7:
  748.                                 DOBYTE(IAddr + 1, 0);
  749.                                 CPU.Cycles += SLOW_ONE_CYCLE;
  750.                                 DOBYTE(IAddr + 2, 1);
  751.                                 CPU.Cycles += SLOW_ONE_CYCLE;
  752.                                 DOBYTE(IAddr + 3, 1);
  753.                                 CPU.Cycles += SLOW_ONE_CYCLE;
  754.                                 break;
  755.  
  756.                             case 4:
  757.                                 DOBYTE(IAddr + 1, 1);
  758.                                 CPU.Cycles += SLOW_ONE_CYCLE;
  759.                                 DOBYTE(IAddr + 2, 2);
  760.                                 CPU.Cycles += SLOW_ONE_CYCLE;
  761.                                 DOBYTE(IAddr + 3, 3);
  762.                                 CPU.Cycles += SLOW_ONE_CYCLE;
  763.                                 break;
  764.                         }
  765.  
  766.                         #undef DOBYTE
  767.                     }
  768.                     else
  769.                     {
  770.                         CPU.InWRAMDMAorHDMA = (ShiftedIBank == 0x7e0000 || ShiftedIBank == 0x7f0000 ||
  771.                             (!(ShiftedIBank & 0x400000) && IAddr < 0x2000));
  772.  
  773.                         if (!HDMAMemPointers[d])
  774.                         {
  775.                             /* HDMA SLOW PATH */
  776.                             uint32  Addr = ShiftedIBank + IAddr;
  777.  
  778.                             switch (p->TransferMode)
  779.                             {
  780.                                 case 0:
  781.                                     S9xSetPPU(S9xGetByte(Addr), 0x2100 + p->BAddress);
  782.                                     CPU.Cycles += SLOW_ONE_CYCLE;
  783.                                     break;
  784.  
  785.                                 case 5:
  786.                                     S9xSetPPU(S9xGetByte(Addr + 0), 0x2100 + p->BAddress);
  787.                                     CPU.Cycles += SLOW_ONE_CYCLE;
  788.                                     S9xSetPPU(S9xGetByte(Addr + 1), 0x2101 + p->BAddress);
  789.                                     CPU.Cycles += SLOW_ONE_CYCLE;
  790.                                     Addr += 2;
  791.                                     /* fall through */
  792.                                 case 1:
  793.                                     S9xSetPPU(S9xGetByte(Addr + 0), 0x2100 + p->BAddress);
  794.                                     CPU.Cycles += SLOW_ONE_CYCLE;
  795.                                     S9xSetPPU(S9xGetByte(Addr + 1), 0x2101 + p->BAddress);
  796.                                     CPU.Cycles += SLOW_ONE_CYCLE;
  797.                                     break;
  798.  
  799.                                 case 2:
  800.                                 case 6:
  801.                                     S9xSetPPU(S9xGetByte(Addr + 0), 0x2100 + p->BAddress);
  802.                                     CPU.Cycles += SLOW_ONE_CYCLE;
  803.                                     S9xSetPPU(S9xGetByte(Addr + 1), 0x2100 + p->BAddress);
  804.                                     CPU.Cycles += SLOW_ONE_CYCLE;
  805.                                     break;
  806.  
  807.                                 case 3:
  808.                                 case 7:
  809.                                     S9xSetPPU(S9xGetByte(Addr + 0), 0x2100 + p->BAddress);
  810.                                     CPU.Cycles += SLOW_ONE_CYCLE;
  811.                                     S9xSetPPU(S9xGetByte(Addr + 1), 0x2100 + p->BAddress);
  812.                                     CPU.Cycles += SLOW_ONE_CYCLE;
  813.                                     S9xSetPPU(S9xGetByte(Addr + 2), 0x2101 + p->BAddress);
  814.                                     CPU.Cycles += SLOW_ONE_CYCLE;
  815.                                     S9xSetPPU(S9xGetByte(Addr + 3), 0x2101 + p->BAddress);
  816.                                     CPU.Cycles += SLOW_ONE_CYCLE;
  817.                                     break;
  818.  
  819.                                 case 4:
  820.                                     S9xSetPPU(S9xGetByte(Addr + 0), 0x2100 + p->BAddress);
  821.                                     CPU.Cycles += SLOW_ONE_CYCLE;
  822.                                     S9xSetPPU(S9xGetByte(Addr + 1), 0x2101 + p->BAddress);
  823.                                     CPU.Cycles += SLOW_ONE_CYCLE;
  824.                                     S9xSetPPU(S9xGetByte(Addr + 2), 0x2102 + p->BAddress);
  825.                                     CPU.Cycles += SLOW_ONE_CYCLE;
  826.                                     S9xSetPPU(S9xGetByte(Addr + 3), 0x2103 + p->BAddress);
  827.                                     CPU.Cycles += SLOW_ONE_CYCLE;
  828.                                     break;
  829.                             }
  830.                         }
  831.                         else
  832.                         {
  833.                             /* HDMA FAST PATH */
  834.                             switch (p->TransferMode)
  835.                             {
  836.                                 case 0:
  837.                                     S9xSetPPU(*HDMAMemPointers[d]++, 0x2100 + p->BAddress);
  838.                                     CPU.Cycles += SLOW_ONE_CYCLE;
  839.                                     break;
  840.  
  841.                                 case 5:
  842.                                     S9xSetPPU(*(HDMAMemPointers[d]), 0x2100 + p->BAddress);
  843.                                     CPU.Cycles += SLOW_ONE_CYCLE;
  844.                                     S9xSetPPU(*(HDMAMemPointers[d] + 1), 0x2101 + p->BAddress);
  845.                                     CPU.Cycles += SLOW_ONE_CYCLE;
  846.                                     HDMAMemPointers[d] += 2;
  847.                                     /* fall through */
  848.                                 case 1:
  849.                                     S9xSetPPU(*(HDMAMemPointers[d]), 0x2100 + p->BAddress);
  850.                                     CPU.Cycles += SLOW_ONE_CYCLE;
  851.                                     S9xSetPPU(*(HDMAMemPointers[d] + 1), 0x2101 + p->BAddress);
  852.                                     CPU.Cycles += SLOW_ONE_CYCLE;
  853.                                     HDMAMemPointers[d] += 2;
  854.                                     break;
  855.  
  856.                                 case 2:
  857.                                 case 6:
  858.                                     S9xSetPPU(*(HDMAMemPointers[d]), 0x2100 + p->BAddress);
  859.                                     CPU.Cycles += SLOW_ONE_CYCLE;
  860.                                     S9xSetPPU(*(HDMAMemPointers[d] + 1), 0x2100 + p->BAddress);
  861.                                     CPU.Cycles += SLOW_ONE_CYCLE;
  862.                                     HDMAMemPointers[d] += 2;
  863.                                     break;
  864.  
  865.                                 case 3:
  866.                                 case 7:
  867.                                     S9xSetPPU(*(HDMAMemPointers[d]), 0x2100 + p->BAddress);
  868.                                     CPU.Cycles += SLOW_ONE_CYCLE;
  869.                                     S9xSetPPU(*(HDMAMemPointers[d] + 1), 0x2100 + p->BAddress);
  870.                                     CPU.Cycles += SLOW_ONE_CYCLE;
  871.                                     S9xSetPPU(*(HDMAMemPointers[d] + 2), 0x2101 + p->BAddress);
  872.                                     CPU.Cycles += SLOW_ONE_CYCLE;
  873.                                     S9xSetPPU(*(HDMAMemPointers[d] + 3), 0x2101 + p->BAddress);
  874.                                     CPU.Cycles += SLOW_ONE_CYCLE;
  875.                                     HDMAMemPointers[d] += 4;
  876.                                     break;
  877.  
  878.                                 case 4:
  879.                                     S9xSetPPU(*(HDMAMemPointers[d]), 0x2100 + p->BAddress);
  880.                                     CPU.Cycles += SLOW_ONE_CYCLE;
  881.                                     S9xSetPPU(*(HDMAMemPointers[d] + 1), 0x2101 + p->BAddress);
  882.                                     CPU.Cycles += SLOW_ONE_CYCLE;
  883.                                     S9xSetPPU(*(HDMAMemPointers[d] + 2), 0x2102 + p->BAddress);
  884.                                     CPU.Cycles += SLOW_ONE_CYCLE;
  885.                                     S9xSetPPU(*(HDMAMemPointers[d] + 3), 0x2103 + p->BAddress);
  886.                                     CPU.Cycles += SLOW_ONE_CYCLE;
  887.                                     HDMAMemPointers[d] += 4;
  888.                                     break;
  889.                             }
  890.                         }
  891.                     }
  892.                 }
  893.  
  894.                 if (p->HDMAIndirectAddressing)
  895.                     p->IndirectAddress += HDMA_ModeByteCounts[p->TransferMode];
  896.                 else
  897.                     p->Address += HDMA_ModeByteCounts[p->TransferMode];
  898.             }
  899.  
  900.             p->DoTransfer = !p->Repeat;
  901.  
  902.             if (!--p->LineCount)
  903.             {
  904.                 if (!HDMAReadLineCount(d))
  905.                 {
  906.                     byte &= ~mask;
  907.                     PPU.HDMAEnded |= mask;
  908.                     p->DoTransfer = FALSE;
  909.                     continue;
  910.                 }
  911.             }
  912.             else
  913.                 CPU.Cycles += SLOW_ONE_CYCLE;
  914.         }
  915.     }
  916.  
  917.     CPU.InHDMA = FALSE;
  918.     CPU.InDMAorHDMA = CPU.InDMA;
  919.     CPU.InWRAMDMAorHDMA = temp;
  920.     CPU.CurrentDMAorHDMAChannel = tmpch;
  921.  
  922.     return (byte);
  923. }
  924.  
  925. void S9xDoHEventProcessing (void)
  926. {
  927.     uint8 tmp;
  928.  
  929.     switch (CPU.WhichEvent)
  930.     {
  931.         case HC_HBLANK_START_EVENT:
  932.             if (PPU.HTimerPosition == Timings.HBlankStart)
  933.                 S9xCheckMissingHTimerPosition();
  934.             S9xReschedule();
  935.             break;
  936.  
  937.         case HC_HDMA_START_EVENT:
  938.             if (PPU.HTimerPosition == Timings.HDMAStart)
  939.                 S9xCheckMissingHTimerPosition();
  940.             S9xReschedule();
  941.  
  942.             if (PPU.HDMA && CPU.V_Counter <= PPU.ScreenHeight)
  943.                 PPU.HDMA = S9xDoHDMA(PPU.HDMA);
  944.  
  945.             break;
  946.  
  947.         case HC_HCOUNTER_MAX_EVENT:
  948.             if (Settings.SuperFX && !SuperFX.oneLineDone && CHECK_EXEC_SUPERFX())
  949.                 S9xSuperFXExec();
  950.             SuperFX.oneLineDone = FALSE; // do this even without SFX
  951.  
  952.             S9xAPUExecute();
  953.             CPU.Cycles -= Timings.H_Max;
  954.             S9xAPUSetReferenceTime(CPU.Cycles);
  955.  
  956.             if ((Timings.NMITriggerPos != 0xffff) && (Timings.NMITriggerPos >= Timings.H_Max))
  957.                 Timings.NMITriggerPos -= Timings.H_Max;
  958.  
  959.             /* MIBR's test */
  960.             //if (CPU.V_Counter == Timings.V_Max - 1) /* 5 frames of lag */
  961.             //if (CPU.V_Counter == 0) /* 4 frames of lag */
  962.             //{
  963.             //    S9xDoAutoJoypad();
  964.             //}
  965.            
  966.             CPU.V_Counter++;
  967.             if (CPU.V_Counter >= Timings.V_Max) /* V ranges from 0 to Timings.V_Max - 1 */
  968.             {
  969.                 CPU.V_Counter = 0;
  970.                 Timings.InterlaceField ^= 1;
  971.  
  972.                 /* From byuu:
  973.                    [NTSC]
  974.                    interlace mode has 525 scanlines: 263 on
  975.                    the even frame, and 262 on the odd.
  976.  
  977.                    non-interlace mode has 524 scanlines:
  978.                    262 scanlines on both even and odd frames.
  979.                    
  980.                    [PAL] <PAL info is unverified on hardware>
  981.                    interlace mode has 625 scanlines: 313 on
  982.                    the even frame, and 312 on the odd.
  983.                    
  984.                    non-interlace mode has 624 scanlines:
  985.                    312 scanlines on both even and odd frames. */
  986.  
  987.                 Timings.V_Max = Timings.V_Max_Master;   /* 262 (NTSC), 312?(PAL) */
  988.  
  989.                 if (IPPU.Interlace && !Timings.InterlaceField)
  990.                     Timings.V_Max += 1; /* 263 (NTSC), 313?(PAL) */
  991.  
  992.                 Memory.FillRAM[0x213F] ^= 0x80;
  993.                 PPU.RangeTimeOver = 0;
  994.  
  995.                 /* FIXME: reading $4210 will wait 2 cycles,
  996.                 then perform reading, then wait 4 more cycles. */
  997.  
  998.                 Memory.FillRAM[0x4210] = MAX_5A22_VERSION;
  999.                 CPU.Flags &= ~NMI_FLAG;
  1000.                 Timings.NMITriggerPos = 0xffff;
  1001.  
  1002.                 ICPU.Frame++;
  1003.                 PPU.HVBeamCounterLatched = 0;
  1004.                 CPU.Flags |= SCAN_KEYS_FLAG;
  1005.             }
  1006.  
  1007.             /* From byuu:
  1008.                In non-interlace mode, there are 341 dots
  1009.                per scanline, and 262 scanlines per frame.
  1010.                
  1011.                On odd frames, scanline 240 is one dot short.
  1012.                In interlace mode, there are always 341 dots
  1013.                per scanline. Even frames have 263 scanlines,
  1014.                and odd frames have 262 scanlines.
  1015.                
  1016.                Interlace mode scanline 240 on odd frames is
  1017.                not missing a dot. */
  1018.  
  1019.             Timings.H_Max = Timings.H_Max_Master;                   /* HC=1364 */
  1020.  
  1021.             if (CPU.V_Counter == 240 && !IPPU.Interlace && Timings.InterlaceField)  /* V=240 */
  1022.                 Timings.H_Max -= ONE_DOT_CYCLE;                 /* HC=1360 */
  1023.  
  1024.             if (CPU.V_Counter != 240 || IPPU.Interlace || !Timings.InterlaceField)  /* V=240 */
  1025.             {
  1026.                 if (Timings.WRAMRefreshPos == SNES_WRAM_REFRESH_HC_v2_MIN_ONE_DOT_CYCLE) /* HC=534 */
  1027.                     Timings.WRAMRefreshPos = SNES_WRAM_REFRESH_HC_v2; /* HC=538 */
  1028.                 else
  1029.                     Timings.WRAMRefreshPos = SNES_WRAM_REFRESH_HC_v2_MIN_ONE_DOT_CYCLE; /* HC=534 */
  1030.             }
  1031.  
  1032.             if (PPU.HTimerPosition == 0)
  1033.                 S9xCheckMissingHTimerPosition();
  1034.  
  1035.             if (CPU.V_Counter == PPU.ScreenHeight + FIRST_VISIBLE_LINE) /* VBlank starts from V=225(240). */
  1036.             {
  1037.                 S9xEndScreenRefresh();
  1038.                 if (!(GFX.DoInterlace && GFX.InterlaceFrame == 0)) /* MIBR */
  1039.                     finishedFrame = true;
  1040.                 PPU.HDMA = 0;
  1041.                 /* Bits 7 and 6 of $4212 are computed when read in S9xGetPPU. */
  1042.                 PPU.ForcedBlanking = (Memory.FillRAM[0x2100] >> 7) & 1;
  1043.  
  1044.                 if (!PPU.ForcedBlanking)
  1045.                 {
  1046.                     PPU.OAMAddr = PPU.SavedOAMAddr;
  1047.  
  1048.                     tmp = 0;
  1049.  
  1050.                     if (PPU.OAMPriorityRotation)
  1051.                         tmp = (PPU.OAMAddr & 0xFE) >> 1;
  1052.                     if ((PPU.OAMFlip & 1) || PPU.FirstSprite != tmp)
  1053.                     {
  1054.                         PPU.FirstSprite = tmp;
  1055.                         IPPU.OBJChanged = TRUE;
  1056.                     }
  1057.  
  1058.                     PPU.OAMFlip = 0;
  1059.                 }
  1060.  
  1061.                 /* FIXME: writing to $4210 will wait 6 cycles. */
  1062.                 Memory.FillRAM[0x4210] = 0x80 | MAX_5A22_VERSION;
  1063.                 if (Memory.FillRAM[0x4200] & 0x80)
  1064.                 {
  1065.                     /* FIXME: triggered at HC=6, checked just
  1066.                     before the final CPU cycle, then, when to
  1067.                     call S9xOpcode_NMI()? */
  1068.                     CPU.Flags |= NMI_FLAG;
  1069.                     Timings.NMITriggerPos = 6 + 6;
  1070.                 }
  1071.  
  1072.             }
  1073.  
  1074.             /* FIXME: not true */
  1075.             if ((CPU.V_Counter == PPU.ScreenHeight + 3) && (Memory.FillRAM[0x4200] & 1))
  1076.             //if (CPU.V_Counter == FIRST_VISIBLE_LINE)
  1077.             {
  1078.                 S9xDoAutoJoypad();
  1079.             }
  1080.  
  1081.             /* V = 1 */
  1082.             if (CPU.V_Counter == FIRST_VISIBLE_LINE)
  1083.             {
  1084.                 GFX.InterlaceFrame = !GFX.InterlaceFrame;
  1085.  
  1086.                 if (!GFX.DoInterlace || !GFX.InterlaceFrame)
  1087.                 {
  1088.                     /* S9x Start Screen Refresh */
  1089.                     bool8 cond_1, cond_2;
  1090.  
  1091.                     GFX.DoInterlace -= (GFX.DoInterlace == TRUE);
  1092.  
  1093.                     IPPU.Interlace    = Memory.FillRAM[0x2133] & 1;
  1094.                     IPPU.InterlaceOBJ = Memory.FillRAM[0x2133] & 2;
  1095.                     IPPU.PseudoHires = Memory.FillRAM[0x2133] & 8;
  1096.  
  1097.                     cond_1 = (Settings.SupportHiRes && (PPU.BGMode == 5 || PPU.BGMode == 6 || IPPU.PseudoHires));
  1098.                     cond_2 = (Settings.SupportHiRes && IPPU.Interlace);
  1099.  
  1100.                     GFX.RealPPL = GFX.Pitch >> 1;
  1101.                     IPPU.RenderedScreenWidth = SNES_WIDTH << cond_1;
  1102.                     IPPU.RenderedScreenHeight = PPU.ScreenHeight << cond_2;
  1103.                     IPPU.DoubleWidthPixels = cond_1;
  1104.                     IPPU.DoubleHeightPixels = cond_2;
  1105.  
  1106.                     GFX.PPL = GFX.RealPPL << cond_2;
  1107.                     GFX.DoInterlace += cond_2;
  1108.                 }
  1109.  
  1110.                 PPU.MosaicStart = 0;
  1111.                 PPU.RecomputeClipWindows = TRUE;
  1112.                 IPPU.PreviousLine = IPPU.CurrentLine = 0;
  1113.  
  1114.                 memset(GFX.ZBuffer, 0, GFX.ScreenSize);
  1115.                 memset(GFX.SubZBuffer, 0, GFX.ScreenSize);
  1116.             }
  1117.  
  1118.             CPU.NextEvent = -1;
  1119.             S9xReschedule();
  1120.  
  1121.             break;
  1122.  
  1123.         case HC_HDMA_INIT_EVENT:
  1124.             if (PPU.HTimerPosition == Timings.HDMAInit)
  1125.                 S9xCheckMissingHTimerPosition();
  1126.             S9xReschedule();
  1127.  
  1128.             if (CPU.V_Counter == 0)
  1129.                 S9xStartHDMA();
  1130.  
  1131.             break;
  1132.  
  1133.         case HC_RENDER_EVENT:
  1134.             if (CPU.V_Counter >= FIRST_VISIBLE_LINE && CPU.V_Counter <= PPU.ScreenHeight)
  1135.                 RenderLine((uint8) (CPU.V_Counter - FIRST_VISIBLE_LINE));
  1136.  
  1137.             if (PPU.HTimerPosition == Timings.RenderPos)
  1138.                 S9xCheckMissingHTimerPosition();
  1139.             S9xReschedule();
  1140.  
  1141.             break;
  1142.  
  1143.         case HC_WRAM_REFRESH_EVENT:
  1144.  
  1145.             if ((PPU.HTimerPosition >= Timings.WRAMRefreshPos) && (PPU.HTimerPosition < (Timings.WRAMRefreshPos + SNES_WRAM_REFRESH_CYCLES)))
  1146.                 S9xCheckMissingHTimerHalt();
  1147.             CPU.Cycles += SNES_WRAM_REFRESH_CYCLES;
  1148.  
  1149.             if (PPU.HTimerPosition == Timings.WRAMRefreshPos)
  1150.                 S9xCheckMissingHTimerPosition();
  1151.             S9xReschedule();
  1152.  
  1153.             break;
  1154.  
  1155.         case HC_IRQ_1_3_EVENT:
  1156.         case HC_IRQ_3_5_EVENT:
  1157.         case HC_IRQ_5_7_EVENT:
  1158.         case HC_IRQ_7_9_EVENT:
  1159.         case HC_IRQ_9_A_EVENT:
  1160.         case HC_IRQ_A_1_EVENT:
  1161.             if ((PPU.HTimerEnabled && (!PPU.VTimerEnabled || (CPU.V_Counter == PPU.VTimerPosition))) || (PPU.VTimerEnabled && (CPU.V_Counter == PPU.VTimerPosition)))
  1162.             {
  1163.                 S9X_SET_IRQ(PPU_IRQ_SOURCE);
  1164.             }
  1165.  
  1166.             S9xReschedule();
  1167.             break;
  1168.     }
  1169.  
  1170. }
  1171.  
  1172. #include "cpuops_.h"
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement