コード例 #1
0
ファイル: SID6510.cs プロジェクト: m4mm0n/HGE
        private void sid_jmp()
        {
            // For de.quippy.sidplay.sidplay compatibility, inherited from environment
            if (m_mode == SID2Types.sid2_env_t.sid2_envR)
            {
                // If a busy loop then just sleep
                if (Cycle_EffectiveAddress == instrStartPC)
                {
                    Register_ProgramCounter = SIDEndian.endian_32lo16(Register_ProgramCounter, Cycle_EffectiveAddress);
                    if (!interruptPending())
                    {
                        this.sleep();
                    }
                }
                else
                {
                    base.jmp_instr();
                }
                return;
            }

            if (player.CheckBankJump(Cycle_EffectiveAddress))
            {
                base.jmp_instr();
            }
            else
            {
                sid_rts();
            }
        }
コード例 #2
0
ファイル: SID6510.cs プロジェクト: m4mm0n/HGE
        internal override void FetchOpcode()
        {
            if (m_mode == SID2Types.sid2_env_t.sid2_envR)
            {
                base.FetchOpcode();
                return;
            }

            // Sid tunes end by wrapping the stack. For compatibility it has to be handled.
            m_sleeping |= (SIDEndian.endian_16hi8(Register_StackPointer) != SP_PAGE);
            m_sleeping |= (SIDEndian.endian_32hi16(Register_ProgramCounter) != 0);
            if (!m_sleeping)
            {
                base.FetchOpcode();
            }

            if (m_framelock == false)
            {
                int timeout = 6000000;
                m_framelock = true;
                // Simulate sidplay1 frame based execution
                while (!m_sleeping && (timeout != 0))
                {
                    base.clock();
                    timeout--;
                }
                if (timeout == 0)
                {
                    player.Reset(true);
                }
                sleep();
                m_framelock = false;
            }
        }
コード例 #3
0
        public void write(short addr, short data)
        {
            if (addr > 0x0f)
            {
                return;
            }

            regs[addr] = data;

            if (locked)
            {
                return; // Stop program changing time interval
            }

            // Sync up timer
            long cycles;

            cycles       = m_eventContext.getTime(m_accessClk, m_phase);
            m_accessClk += cycles;
            ta          -= (int)cycles;
            if (ta == 0)
            {
                _event();
            }

            switch (addr)
            {
            case 0x4:
                ta_latch = SIDEndian.endian_16lo8(ta_latch, data);
                break;

            case 0x5:
                ta_latch = SIDEndian.endian_16hi8(ta_latch, data);
                if ((cra & 0x01) == 0)     // Reload timer if stopped
                {
                    ta = ta_latch;
                }
                break;

            case 0x0e:
                cra = (short)(data | 0x01);
                if ((data & 0x10) != 0)
                {
                    cra &= (~0x10 & 0xff);
                    ta   = ta_latch;
                }
                m_eventContext.schedule(m_taEvent, (long)ta + 1, m_phase);
                break;

            default:
                break;
            }
        }
コード例 #4
0
ファイル: Channel.cs プロジェクト: m4mm0n/HGE
        private void galwayInit()
        {
            if (active)
            {
                return;
            }

            // Check all important parameters are legal
            short r = convertAddr(0x1d);

            galTones      = reg[r];
            reg[r]        = 0;
            galInitLength = reg[convertAddr(0x3d)];
            if (galInitLength == 0)
            {
                return;
            }
            galLoopWait = reg[convertAddr(0x3f)];
            if (galLoopWait == 0)
            {
                return;
            }
            galNullWait = reg[convertAddr(0x5d)];
            if (galNullWait == 0)
            {
                return;
            }

            // Load the other parameters
            r        = convertAddr(0x1e);
            address  = SIDEndian.endian_16(reg[r + 1], reg[r]);
            volShift = (short)(reg[convertAddr(0x3e)] & 0x0f);
            mode     = FM_GALWAY;
            active   = true;
            cycles   = 0;
            outputs  = 0;

            sampleLimit = 8;
            sample      = (byte)(galVolume - 8);
            galwayTonePeriod();

            // Calculate the sample offset
            m_xsid.sampleOffsetCalc();

            // Schedule a sample update
            m_context.schedule(m_xsid.xsidEvent, 0, m_phase);
            m_context.schedule(galwayEvent, cycleCount, m_phase);
        }
コード例 #5
0
        /// <summary>
        /// Common address resolution procedure
        /// </summary>
        /// <param name="c64data"></param>
        /// <param name="fileOffset2"></param>
        /// <returns></returns>
        protected bool resolveAddrs(short[] c64data, int fileOffset2)
        {
            // Originally used as a first attempt at an RSID
            // style format. Now reserved for future use
            if (info.playAddr == 0xffff)
            {
                info.playAddr = 0;
            }

            // loadAddr = 0 means, the address is stored in front of the C64 data.
            if (info.loadAddr == 0)
            {
                if (info.c64dataLen < 2)
                {
                    //info.statusstring = txt_corrupt;
                    return(false);
                }
                info.loadAddr = SIDEndian.endian_16(c64data[fileOffset + 1], c64data[fileOffset + 0]);
                fileOffset   += 2;
                // c64data += 2;
                info.c64dataLen -= 2;
            }

            if (info.compatibility == SIDTUNE_COMPATIBILITY_BASIC)
            {
                if (info.initAddr != 0)
                {
                    //info.statusstring = txt_badAddr;
                    return(false);
                }
            }
            else if (info.initAddr == 0)
            {
                info.initAddr = info.loadAddr;
            }
            return(true);
        }
コード例 #6
0
        /// <summary>
        /// Support for OR-ing two LoadStatus enums
        /// </summary>
        /// <param name="support"></param>
        /// <param name="support2"></param>
        /// <returns></returns>

        /*
         * private LoadStatus orStatus(LoadStatus support, LoadStatus support2)
         * {
         *  int val1 = (support == LoadStatus.LOAD_NOT_MINE) ? 0 : (support == LoadStatus.LOAD_OK) ? 1 : 2;
         *  int val2 = (support2 == LoadStatus.LOAD_NOT_MINE) ? 0 : (support2 == LoadStatus.LOAD_OK) ? 1 : 2;
         *  int erg = val1 | val2;
         *  return (erg == 0) ? LoadStatus.LOAD_NOT_MINE : (erg == 1) ? LoadStatus.LOAD_OK : LoadStatus.LOAD_ERROR;
         * }
         */

        /// <summary>
        /// Cache the data of a single-file or two-file sidtune and its corresponding file names
        /// </summary>
        /// <param name="buf"></param>
        /// <returns></returns>
        private bool acceptSidTune(Buffer_sidtt buf)
        {
            // @FIXME@ - MUS
            if (info.numberOfInfostrings == 3)
            {
                // Add <?> (HVSC standard) to
                // missing title, author,
                // release fields
                for (int i = 0; i < 3; i++)
                {
                    if (infostring[i].Length == 0)
                    {
                        infostring[i]      = "<?>";
                        info.infostring[i] = infostring[i];
                    }
                }
            }

            // Fix bad sidtune set up.
            if (info.songs > SIDTUNE_MAX_SONGS)
            {
                info.songs = SIDTUNE_MAX_SONGS;
            }
            else if (info.songs == 0)
            {
                info.songs++;
            }
            if (info.startSong > info.songs)
            {
                info.startSong = 1;
            }
            else if (info.startSong == 0)
            {
                info.startSong++;
            }

            info.dataFileLen = buf.bufLen;
            info.c64dataLen  = buf.bufLen - fileOffset;

            // Calculate any remaining addresses and then
            // confirm all the file details are correct
            if (resolveAddrs(buf.buf, fileOffset) == false)
            {
                return(false);
            }
            if (!checkRelocInfo())
            {
                return(false);
            }
            if (!checkCompatibility())
            {
                return(false);
            }

            if (info.dataFileLen >= 2)
            {
                // We only detect an offset of two. Some position independent
                // sidtunes contain a load address of 0xE000, but are loaded
                // to 0x0FFE and call player at 0x1000.
                info.fixLoad = (SIDEndian.endian_little16(buf.buf, fileOffset) == (info.loadAddr + 2));
            }

            // Check the size of the data.
            if (info.c64dataLen > SIDTUNE_MAX_MEMORY)
            {
                //info.statusstring = txt_dataTooLong;
                return(false);
            }
            else if (info.c64dataLen == 0)
            {
                //info.statusstring = txt_empty;
                return(false);
            }

            cache.assign(buf.xferPtr(), buf.xferLen());

            //info.statusstring = txt_noErrors;
            return(true);
        }
コード例 #7
0
ファイル: Channel.cs プロジェクト: m4mm0n/HGE
        private void sampleInit()
        {
            if (active && (mode == FM_GALWAY))
            {
                return;
            }

            // Check all important parameters are legal
            short r = convertAddr(0x1d);

            volShift = (short)((0 - reg[r]) >> 1);
            reg[r]   = 0;

            r          = convertAddr(0x1e);
            address    = SIDEndian.endian_16(reg[r + 1], reg[r]);
            r          = convertAddr(0x3d);
            samEndAddr = SIDEndian.endian_16(reg[r + 1], reg[r]);
            if (samEndAddr <= address)
            {
                return;
            }
            samScale  = reg[convertAddr(0x5f)];
            r         = convertAddr(0x5d);
            samPeriod = SIDEndian.endian_16(reg[r + 1], reg[r]) >> samScale;
            if (samPeriod == 0)
            {
                // Stop this channel
                reg[convertAddr(0x1d)] = 0xfd;
                checkForInit();
                return;
            }

            // Load the other parameters
            samNibble     = 0;
            samRepeat     = reg[convertAddr(0x3f)];
            samOrder      = reg[convertAddr(0x7d)];
            r             = convertAddr(0x7e);
            samRepeatAddr = SIDEndian.endian_16(reg[r + 1], reg[r]);
            cycleCount    = samPeriod;

            // Support Galway Samples, but that
            // mode is setup only when a Galway
            // Noise sequence begins
            if (mode == FM_NONE)
            {
                mode = FM_HUELS;
            }

            active  = true;
            cycles  = 0;
            outputs = 0;

            sampleLimit = (short)(8 >> volShift);
            sample      = sampleCalculate();

            // Calculate the sample offset
            m_xsid.sampleOffsetCalc();

            // Schedule a sample update
            m_context.schedule(m_xsid.xsidEvent, 0, m_phase);
            m_context.schedule(sampleEvent, cycleCount, m_phase);
        }
コード例 #8
0
ファイル: MOS656X.cs プロジェクト: m4mm0n/HGE
        public void write(short addr, short data)
        {
            if (addr > 0x3f)
            {
                return;
            }

            regs[addr] = data;

            // Sync up timers
            _event();

            switch (addr)
            {
            case 0x11:     // Control register 1
            {
                raster_irq = SIDEndian.endian_16hi8(raster_irq, (short)(data >> 7));
                ctrl1      = data;
                y_scroll   = data & 7;

                if (raster_x < 11)
                {
                    break;
                }

                // In line $30, the DEN bit controls if Bad Lines can occur
                if ((raster_y == first_dma_line) && ((data & 0x10) != 0))
                {
                    bad_lines_enabled = true;
                }

                // Bad Line condition?
                bad_line = (raster_y >= first_dma_line) && (raster_y <= last_dma_line) && ((raster_y & 7) == y_scroll) && bad_lines_enabled;

                // Start bad dma line now
                if (bad_line && (raster_x < 53))
                {
                    addrctrl(false);
                }
                break;
            }

            case 0x12:     // Raster counter
                raster_irq = SIDEndian.endian_16lo8(raster_irq, data);
                break;

            case 0x17:
                sprite_expand_y |= (short)(~data & 0xff);
                break;

            case 0x19:     // IRQ flags
                idr &= (short)((~data & 0x0f) | 0x80);
                if (idr == 0x80)
                {
                    trigger(0);
                }
                break;

            case 0x1a:     // IRQ mask
                icr = (short)(data & 0x0f);
                trigger(icr & idr);
                break;
            }
        }