Exemple #1
0
		public void WriteByte( int address, int value ) {
			if( address >= 0xC000 && address <= 0xDFFF ) {
				workRam[ address - 0xC000 ] = (byte)value;
			} else if( address >= 0xFE00 && address <= 0xFEFF ) {
				oam[ address - 0xFE00 ] = (byte)value;
			} else if( address >= 0xFF80 && address <= 0xFFFE ) {
				highRam[ 0xFF & address ] = (byte)value;
			} else if( address >= 0x8000 && address <= 0x9FFF ) {
				int videoRamIndex = address - 0x8000;
				videoRam[ videoRamIndex ] = (byte)value;
				if( address < 0x9000 ) {
					spriteTileInvalidated[ videoRamIndex >> 4 ] = true;
				}
				if( address < 0x9800 ) {
					invalidateAllBackgroundTilesRequest = true;
				} else if( address >= 0x9C00 ) {
					int tileIndex = address - 0x9C00;
					backgroundTileInvalidated[ tileIndex >> 5, tileIndex & 0x1F ] = true;
				} else {
					int tileIndex = address - 0x9800;
					backgroundTileInvalidated[ tileIndex >> 5, tileIndex & 0x1F ] = true;
				}
			} else if( address <= 0x7FFF || ( address >= 0xA000 && address <= 0xBFFF ) ) {
				cartridge.WriteByte( address, value );
			} else if( address >= 0xE000 && address <= 0xFDFF ) {
				workRam[ address - 0xE000 ] = (byte)value;
			} else {
				switch( address ) {
					case 0xFF00: // key pad
						keyP14 = ( value & 0x10 ) != 0x10;
						keyP15 = ( value & 0x20 ) != 0x20;
						break;
					case 0xFF04: // Timer divider            
						break;
					case 0xFF05: // Timer counter
						timerCounter = value;
						break;
					case 0xFF06: // Timer modulo
						timerModulo = value;
						break;
					case 0xFF07:  // Time Control
						timerRunning = ( value & 0x04 ) == 0x04;
						timerFrequency = (TimerFrequencyType)( 0x03 & value );
						break;
					case 0xFF0F: // Interrupt Flag (an interrupt request)
						keyPressedInterruptRequested = ( value & 0x10 ) == 0x10;
						serialIOTransferCompleteInterruptRequested = ( value & 0x08 ) == 0x08;
						timerOverflowInterruptRequested = ( value & 0x04 ) == 0x04;
						lcdcInterruptRequested = ( value & 0x02 ) == 0x02;
						vBlankInterruptRequested = ( value & 0x01 ) == 0x01;
						break;
					case 0xFF40: { // LCDC control
							bool _backgroundAndWindowTileDataSelect = backgroundAndWindowTileDataSelect;
							bool _backgroundTileMapDisplaySelect = backgroundTileMapDisplaySelect;
							bool _windowTileMapDisplaySelect = windowTileMapDisplaySelect;

							lcdControlOperationEnabled = ( value & 0x80 ) == 0x80;
							windowTileMapDisplaySelect = ( value & 0x40 ) == 0x40;
							windowDisplayed = ( value & 0x20 ) == 0x20;
							backgroundAndWindowTileDataSelect = ( value & 0x10 ) == 0x10;
							backgroundTileMapDisplaySelect = ( value & 0x08 ) == 0x08;
							largeSprites = ( value & 0x04 ) == 0x04;
							spritesDisplayed = ( value & 0x02 ) == 0x02;
							backgroundDisplayed = ( value & 0x01 ) == 0x01;

							if( _backgroundAndWindowTileDataSelect != backgroundAndWindowTileDataSelect
								|| _backgroundTileMapDisplaySelect != backgroundTileMapDisplaySelect
								|| _windowTileMapDisplaySelect != windowTileMapDisplaySelect ) {
								invalidateAllBackgroundTilesRequest = true;
							}

							break;
						}
					case 0xFF41: // LCDC Status
						lcdcLycLyCoincidenceInterruptEnabled = ( value & 0x40 ) == 0x40;
						lcdcOamInterruptEnabled = ( value & 0x20 ) == 0x20;
						lcdcVBlankInterruptEnabled = ( value & 0x10 ) == 0x10;
						lcdcHBlankInterruptEnabled = ( value & 0x08 ) == 0x08;
						lcdcMode = (LcdcModeType)( value & 0x03 );
						break;
					case 0xFF42: // Scroll Y;
						scrollY = value;
						break;
					case 0xFF43: // Scroll X;
						scrollX = value;
						break;
					case 0xFF44: // LY
						ly = value;
						break;
					case 0xFF45: // LY Compare
						lyCompare = value;
						break;
					case 0xFF46: // Memory Transfer
						value <<= 8;
						for( int i = 0; i < 0x8C; i++ ) {
							WriteByte( 0xFE00 | i, ReadByte( value | i ) );
						}
						break;
					case 0xFF47: // Background palette
						Console.WriteLine( "[0xFF47] = {0:X}", value );
						for( int i = 0; i < 4; i++ ) {
							switch( value & 0x03 ) {
								case 0:
									backgroundPalette[ i ] = WHITE;
									break;
								case 1:
									backgroundPalette[ i ] = LIGHT_GRAY;
									break;
								case 2:
									backgroundPalette[ i ] = DARK_GRAY;
									break;
								case 3:
									backgroundPalette[ i ] = BLACK;
									break;
							}
							value >>= 2;
						}
						invalidateAllBackgroundTilesRequest = true;
						break;
					case 0xFF48: // Object palette 0
						for( int i = 0; i < 4; i++ ) {
							switch( value & 0x03 ) {
								case 0:
									objectPalette0[ i ] = WHITE;
									break;
								case 1:
									objectPalette0[ i ] = LIGHT_GRAY;
									break;
								case 2:
									objectPalette0[ i ] = DARK_GRAY;
									break;
								case 3:
									objectPalette0[ i ] = BLACK;
									break;
							}
							value >>= 2;
						}
						invalidateAllSpriteTilesRequest = true;
						break;
					case 0xFF49: // Object palette 1
						for( int i = 0; i < 4; i++ ) {
							switch( value & 0x03 ) {
								case 0:
									objectPalette1[ i ] = WHITE;
									break;
								case 1:
									objectPalette1[ i ] = LIGHT_GRAY;
									break;
								case 2:
									objectPalette1[ i ] = DARK_GRAY;
									break;
								case 3:
									objectPalette1[ i ] = BLACK;
									break;
							}
							value >>= 2;
						}
						invalidateAllSpriteTilesRequest = true;
						break;
					case 0xFF4A: // Window Y
						windowY = value;
						break;
					case 0xFF4B: // Window X
						windowX = value;
						break;
					case 0xFFFF: // Interrupt Enable
						keyPressedInterruptEnabled = ( value & 0x10 ) == 0x10;
						serialIOTransferCompleteInterruptEnabled = ( value & 0x08 ) == 0x08;
						timerOverflowInterruptEnabled = ( value & 0x04 ) == 0x04;
						lcdcInterruptEnabled = ( value & 0x02 ) == 0x02;
						vBlankInterruptEnabled = ( value & 0x01 ) == 0x01;
						break;
				}
			}
		}
Exemple #2
0
        public void WriteByte(int address, int value)
        {
            if (address >= 0xC000 && address <= 0xDFFF)
            {
                workRam [address - 0xC000] = (byte)value;
            } else if (address >= 0xFE00 && address <= 0xFEFF)
            {
                oam [address - 0xFE00] = (byte)value;
            } else if (address >= 0xFF80 && address <= 0xFFFE)
            {
                highRam [0xFF & address] = (byte)value;
            } else if (address >= 0x8000 && address <= 0x9FFF)
            {
                int videoRamIndex = address - 0x8000;
                videoRam [videoRamIndex] = (byte)value;
                if (address < 0x9000)
                {
                    spriteTileInvalidated [videoRamIndex >> 4] = true;
                }
                if (address < 0x9800)
                {
                    invalidateAllBackgroundTilesRequest = true;
                } else if (address >= 0x9C00)
                {
                    int tileIndex = address - 0x9C00;
                    backgroundTileInvalidated [tileIndex >> 5, tileIndex & 0x1F] = true;
                } else
                {
                    int tileIndex = address - 0x9800;
                    backgroundTileInvalidated [tileIndex >> 5, tileIndex & 0x1F] = true;
                }
            } else if (address <= 0x7FFF || (address >= 0xA000 && address <= 0xBFFF))
            {
                cartridge.WriteByte(address, value);
            } else if (address >= 0xE000 && address <= 0xFDFF)
            {
                workRam [address - 0xE000] = (byte)value;
            } else
            {
                switch (address)
                {
                    case 0xFF00: // key pad
                        keyP14 = (value & 0x10) != 0x10;
                        keyP15 = (value & 0x20) != 0x20;
                        break;
                    case 0xFF04: // Timer divider
                        break;
                    case 0xFF05: // Timer counter
                        timerCounter = value;
                        break;
                    case 0xFF06: // Timer modulo
                        timerModulo = value;
                        break;
                    case 0xFF07:  // Time Control
                        timerRunning = (value & 0x04) == 0x04;
                        timerFrequency = (TimerFrequencyType)(0x03 & value);
                        break;
                    case 0xFF0F: // Interrupt Flag (an interrupt request)
                        keyPressedInterruptRequested = (value & 0x10) == 0x10;
                        serialIOTransferCompleteInterruptRequested = (value & 0x08) == 0x08;
                        timerOverflowInterruptRequested = (value & 0x04) == 0x04;
                        lcdcInterruptRequested = (value & 0x02) == 0x02;
                        vBlankInterruptRequested = (value & 0x01) == 0x01;
                        break;
                    case 0xFF10:           // Sound channel 1, sweep
                        SoundChip.channel1.SetSweep(
                            (value & 0x70) >> 4,
                            (value & 0x07),
                            (value & 0x08) == 1);
                        soundRegisters [0x10 - 0x10] = value;
                        break;

                    case 0xFF11:           // Sound channel 1, length and wave duty
                        SoundChip.channel1.SetDutyCycle((value & 0xC0) >> 6);
                        SoundChip.channel1.SetLength(value & 0x3F);
                        soundRegisters [0x11 - 0x10] = value;
                        break;

                    case 0xFF12:           // Sound channel 1, volume envelope
                        SoundChip.channel1.SetEnvelope(
                            (value & 0xF0) >> 4,
                            (value & 0x07),
                            (value & 0x08) == 8);
                        soundRegisters [0x12 - 0x10] = value;
                        break;

                    case 0xFF13:           // Sound channel 1, frequency low
                        soundRegisters [0x13 - 0x10] = value;
                        SoundChip.channel1.SetFrequency(
                        ((soundRegisters [0x14 - 0x10] & 0x07) << 8) + soundRegisters [0x13 - 0x10]);
                        break;

                    case 0xFF14:           // Sound channel 1, frequency high
                        soundRegisters [0x14 - 0x10] = value;

                        if ((soundRegisters [0x14 - 0x10] & 0x80) != 0)
                        {
                            SoundChip.channel1.SetLength(soundRegisters [0x11 - 0x10] & 0x3F);
                            SoundChip.channel1.SetEnvelope(
                                (soundRegisters [0x12 - 0x10] & 0xF0) >> 4,
                                (soundRegisters [0x12 - 0x10] & 0x07),
                                (soundRegisters [0x12 - 0x10] & 0x08) == 8);
                        }
                        if ((soundRegisters [0x14 - 0x10] & 0x40) == 0)
                        {
                            SoundChip.channel1.SetLength(-1);
                        }

                        SoundChip.channel1.SetFrequency(
                            ((soundRegisters [0x14 - 0x10] & 0x07) << 8) + soundRegisters [0x13 - 0x10]);

                        break;

                    case 0xFF17:           // Sound channel 2, volume envelope
                        SoundChip.channel2.SetEnvelope(
                            (value & 0xF0) >> 4,
                            value & 0x07,
                            (value & 0x08) == 8);
                        soundRegisters [0x17 - 0x10] = value;
                        break;

                    case 0xFF18:           // Sound channel 2, frequency low
                        soundRegisters [0x18 - 0x10] = value;
                        SoundChip.channel2.SetFrequency(
                            ((soundRegisters [0x19 - 0x10] & 0x07) << 8) + soundRegisters [0x18 - 0x10]);
                        break;

                    case 0xFF19:           // Sound channel 2, frequency high
                        soundRegisters [0x19 - 0x10] = value;

                        if ((value & 0x80) != 0)
                        {
                            SoundChip.channel2.SetLength(soundRegisters [0x21 - 0x10] & 0x3F);
                            SoundChip.channel2.SetEnvelope(
                                (soundRegisters [0x17 - 0x10] & 0xF0) >> 4,
                                (soundRegisters [0x17 - 0x10] & 0x07),
                                (soundRegisters [0x17 - 0x10] & 0x08) == 8);
                        }
                        if ((soundRegisters [0x19 - 0x10] & 0x40) == 0)
                        {
                            SoundChip.channel2.SetLength(-1);
                        }
                        SoundChip.channel2.SetFrequency(
                            ((soundRegisters [0x19 - 0x10] & 0x07) << 8) + soundRegisters [0x18 - 0x10]);
                        break;

                    case 0xFF16:           // Sound channel 2, length and wave duty
                        SoundChip.channel2.SetDutyCycle((value & 0xC0) >> 6);
                        SoundChip.channel2.SetLength(value & 0x3F);
                        soundRegisters [0x16 - 0x10] = value;
                        break;

                    case 0xFF1A:           // Sound channel 3, on/off
                        if ((value & 0x80) != 0)
                        {
                            SoundChip.channel3.SetVolume((soundRegisters [0x1C - 0x10] & 0x60) >> 5);
                        } else
                        {
                            SoundChip.channel3.SetVolume(0);
                        }
                        soundRegisters [0x1A - 0x10] = value;
                        break;

                    case 0xFF1B:           // Sound channel 3, length
                        soundRegisters [0x1B - 0x10] = value;
                        SoundChip.channel3.SetLength(value);
                        break;

                    case 0xFF1C:           // Sound channel 3, volume
                        soundRegisters [0x1C - 0x10] = value;
                        SoundChip.channel3.SetVolume((value & 0x60) >> 5);
                        break;

                    case 0xFF1D:           // Sound channel 3, frequency lower 8-bit
                        soundRegisters [0x1D - 0x10] = value;
                        SoundChip.channel3.SetFrequency(
                        ((soundRegisters [0x1E - 0x10] & 0x07) << 8) + soundRegisters [0x1D - 0x10]);
                        break;

                    case 0xFF1E:           // Sound channel 3, frequency higher 3-bit
                        soundRegisters [0x1E - 0x10] = value;
                        if ((soundRegisters [0x19 - 0x10] & 0x80) != 0)
                        {
                            SoundChip.channel3.SetLength(soundRegisters [0x1B - 0x10]);
                        }
                        SoundChip.channel3.SetFrequency(
                            ((soundRegisters [0x1E - 0x10] & 0x07) << 8) + soundRegisters [0x1D - 0x10]);
                        break;

                    case 0xFF20:           // Sound channel 4, length
                        SoundChip.channel4.SetLength(value & 0x3F);
                        soundRegisters [0x20 - 0x10] = value;
                        break;

                    case 0xFF21:           // Sound channel 4, volume envelope
                        SoundChip.channel4.SetEnvelope(
                        (value & 0xF0) >> 4,
                        (value & 0x07),
                        (value & 0x08) == 8);
                        soundRegisters [0x21 - 0x10] = value;
                        break;

                    case 0xFF22:           // Sound channel 4, polynomial parameters
                        SoundChip.channel4.SetParameters(
                        (value & 0x07),
                        (value & 0x08) == 8,
                        (value & 0xF0) >> 4);
                        soundRegisters [0x22 - 0x10] = value;
                        break;

                    case 0xFF23:          // Sound channel 4, initial/consecutive
                        soundRegisters [0x23 - 0x10] = value;
                        if ((value & 0x80) != 0)
                        {
                            SoundChip.channel4.SetLength(soundRegisters [0x20 - 0x10] & 0x3F);
                        } else if (((value & 0x80) & 0x40) == 0)
                        {
                            SoundChip.channel4.SetLength(-1);
                        }
                        break;
                    case 0xFF24:
                        // TODO volume
                        break;
                    case 0xFF25:           // Stereo select
                        int chanData;
                        soundRegisters [0x25 - 0x10] = value;

                        chanData = 0;
                        if ((value & 0x01) != 0)
                        {
                            chanData |= SquareWaveGenerator.CHAN_LEFT;
                        }
                        if ((value & 0x10) != 0)
                        {
                            chanData |= SquareWaveGenerator.CHAN_RIGHT;
                        }
                        SoundChip.channel1.SetChannel(chanData);

                        chanData = 0;
                        if ((value & 0x02) != 0)
                        {
                            chanData |= SquareWaveGenerator.CHAN_LEFT;
                        }
                        if ((value & 0x20) != 0)
                        {
                            chanData |= SquareWaveGenerator.CHAN_RIGHT;
                        }
                        SoundChip.channel2.SetChannel(chanData);

                        chanData = 0;
                        if ((value & 0x04) != 0)
                        {
                            chanData |= VoluntaryWaveGenerator.CHAN_LEFT;
                        }
                        if ((value & 0x40) != 0)
                        {
                            chanData |= VoluntaryWaveGenerator.CHAN_RIGHT;
                        }
                        SoundChip.channel3.SetChannel(chanData);

                        chanData = 0;
                        if ((value & 0x08) != 0)
                        {
                            chanData |= NoiseGenerator.CHAN_LEFT;
                        }
                        if ((value & 0x80) != 0)
                        {
                            chanData |= NoiseGenerator.CHAN_RIGHT;
                        }
                        SoundChip.channel4.SetChannel(chanData);

                        break;
                    case 0xFF26:
                        SoundChip.soundEnabled = (value & 0x80) == 1;
                        break;
                    case 0xFF30:
                    case 0xFF31:
                    case 0xFF32:
                    case 0xFF33:
                    case 0xFF34:
                    case 0xFF35:
                    case 0xFF36:
                    case 0xFF37:
                    case 0xFF38:
                    case 0xFF39:
                    case 0xFF3A:
                    case 0xFF3B:
                    case 0xFF3C:
                    case 0xFF3D:
                    case 0xFF3E:
                    case 0xFF3F:
                        SoundChip.channel3.SetSamplePair(address - 0xFF30, value);
                        soundRegisters [address - 0xFF10] = value;
                        break;
                    case 0xFF40:
                        { // LCDC control
                            bool _backgroundAndWindowTileDataSelect = backgroundAndWindowTileDataSelect;
                            bool _backgroundTileMapDisplaySelect = backgroundTileMapDisplaySelect;
                            bool _windowTileMapDisplaySelect = windowTileMapDisplaySelect;

                            lcdControlOperationEnabled = (value & 0x80) == 0x80;
                            windowTileMapDisplaySelect = (value & 0x40) == 0x40;
                            windowDisplayed = (value & 0x20) == 0x20;
                            backgroundAndWindowTileDataSelect = (value & 0x10) == 0x10;
                            backgroundTileMapDisplaySelect = (value & 0x08) == 0x08;
                            largeSprites = (value & 0x04) == 0x04;
                            spritesDisplayed = (value & 0x02) == 0x02;
                            backgroundDisplayed = (value & 0x01) == 0x01;

                            if (_backgroundAndWindowTileDataSelect != backgroundAndWindowTileDataSelect
                                || _backgroundTileMapDisplaySelect != backgroundTileMapDisplaySelect
                                || _windowTileMapDisplaySelect != windowTileMapDisplaySelect)
                            {
                                invalidateAllBackgroundTilesRequest = true;
                            }

                            break;
                        }
                    case 0xFF41: // LCDC Status
                        lcdcLycLyCoincidenceInterruptEnabled = (value & 0x40) == 0x40;
                        lcdcOamInterruptEnabled = (value & 0x20) == 0x20;
                        lcdcVBlankInterruptEnabled = (value & 0x10) == 0x10;
                        lcdcHBlankInterruptEnabled = (value & 0x08) == 0x08;
                        lcdcMode = (LcdcModeType)(value & 0x03);
                        break;
                    case 0xFF42: // Scroll Y;
                        scrollY = value;
                        break;
                    case 0xFF43: // Scroll X;
                        scrollX = value;
                        break;
                    case 0xFF44: // LY
                        ly = value;
                        break;
                    case 0xFF45: // LY Compare
                        lyCompare = value;
                        break;
                    case 0xFF46: // Memory Transfer
                        value <<= 8;
                        for (int i = 0; i < 0x8C; i++)
                        {
                            WriteByte(0xFE00 | i, ReadByte(value | i));
                        }
                        break;
                    case 0xFF47: // Background palette
                        Console.WriteLine("[0xFF47] = {0:X}", value);
                        for (int i = 0; i < 4; i++)
                        {
                            switch (value & 0x03)
                            {
                                case 0:
                                    backgroundPalette [i] = WHITE;
                                    break;
                                case 1:
                                    backgroundPalette [i] = LIGHT_GRAY;
                                    break;
                                case 2:
                                    backgroundPalette [i] = DARK_GRAY;
                                    break;
                                case 3:
                                    backgroundPalette [i] = BLACK;
                                    break;
                            }
                            value >>= 2;
                        }
                        invalidateAllBackgroundTilesRequest = true;
                        break;
                    case 0xFF48: // Object palette 0
                        for (int i = 0; i < 4; i++)
                        {
                            switch (value & 0x03)
                            {
                                case 0:
                                    objectPalette0 [i] = WHITE;
                                    break;
                                case 1:
                                    objectPalette0 [i] = LIGHT_GRAY;
                                    break;
                                case 2:
                                    objectPalette0 [i] = DARK_GRAY;
                                    break;
                                case 3:
                                    objectPalette0 [i] = BLACK;
                                    break;
                            }
                            value >>= 2;
                        }
                        invalidateAllSpriteTilesRequest = true;
                        break;
                    case 0xFF49: // Object palette 1
                        for (int i = 0; i < 4; i++)
                        {
                            switch (value & 0x03)
                            {
                                case 0:
                                    objectPalette1 [i] = WHITE;
                                    break;
                                case 1:
                                    objectPalette1 [i] = LIGHT_GRAY;
                                    break;
                                case 2:
                                    objectPalette1 [i] = DARK_GRAY;
                                    break;
                                case 3:
                                    objectPalette1 [i] = BLACK;
                                    break;
                            }
                            value >>= 2;
                        }
                        invalidateAllSpriteTilesRequest = true;
                        break;
                    case 0xFF4A: // Window Y
                        windowY = value;
                        break;
                    case 0xFF4B: // Window X
                        windowX = value;
                        break;
                    case 0xFFFF: // Interrupt Enable
                        keyPressedInterruptEnabled = (value & 0x10) == 0x10;
                        serialIOTransferCompleteInterruptEnabled = (value & 0x08) == 0x08;
                        timerOverflowInterruptEnabled = (value & 0x04) == 0x04;
                        lcdcInterruptEnabled = (value & 0x02) == 0x02;
                        vBlankInterruptEnabled = (value & 0x01) == 0x01;
                        break;
                }
            }
        }