/// <summary>
        /// Calculates the code for the Brightness HDMA with the desired channel, Table and possibly SA-1 compatible
        /// </summary>
        /// <param name="channel"></param>
        /// <param name="table"></param>
        /// <param name="sa1"></param>
        /// <returns></returns>
        public override string Code(int channel, HDMATable table, bool sa1)
        {
            DMAMode mode = (table[0].Values.Length == 1 ? DMAMode.P : DMAMode.PP);

            ASMCodeBuilder code       = new ASMCodeBuilder();
            int            channelAdd = 16 * channel;

            table.Name = ".BrightTable";

            code.AppendLabel(INITLabel, "Code to be inserted INIT");
            code.OpenNewBlock();
            code.AppendCode("\tREP #$20", "16 bit mode");
            code.AppendCode("\tLDA #$" + (((Registers.Brightness & 0xFF) << 8) + (int)mode).ToString("X4"));
            code.AppendCode("\tSTA $" + (Registers.DMAMode + channelAdd).ToString("X4"));
            code.AppendCode("\tLDA #" + table.Name, "load high and low byte of table address");
            code.AppendCode("\tSTA $" + (Registers.DMALowByte + channelAdd).ToString("X4"));
            code.AppendCode("\tSEP #$20", "back to 8 bit mode");
            code.AppendCode("\tLDA.b #" + table.Name + ">>16", "load bank byte of table address");
            code.AppendCode("\tSTA $" + (Registers.DMABankByte + channelAdd).ToString("X4"));
            code.AppendCode("\tLDA #$" + (1 << channel).ToString("X2"));
            code.AppendCode("\tTSB $" + RAM.HDMAEnable[sa1].ToString("X4"), "enable HDMA channel " + channel);
            code.AppendCode("\tRTS");
            code.CloseBlock();
            code.AppendEmptyLine();

            code.AppendTable(table);

            return(code.ToString());
        }
        /// <summary>
        /// Calculates the code for overlapping multiple brightness gradients.
        /// <para>The final code will use the channel of the first BrightnessHDMA object passed.</para>
        /// </summary>
        /// <param name="hdma">An array of BrightnessHDMA object that will be overlapped for the final code.</param>
        /// <returns>The final code.</returns>
        public static string MultiCode(params BrightnessHDMA[] hdma)
        {
            if (hdma == null || hdma.Length == 0)
            {
                return(null);
            }

            int channel = hdma[0].Channel;

            EffectClasses.HDMATable table = new HDMATable(".BrightTable");

            using (Bitmap b = BitmapEffects.OverlapImages(hdma.Select(h => h.EffectImage).ToArray()))
            {
                byte scanlines = 1;
                int  now       = 0;
                int  compare   = 0x0F - (b.GetPixel(0, 0).A / 17);
                for (int y = 1; y < b.Height; y++, scanlines++)
                {
                    now = 0x0F - (b.GetPixel(0, y).A / 17);
                    if (compare != now || scanlines >= 0x80)
                    {
                        table.Add(new HDMATableEntry(TableValueType.db, scanlines, (byte)compare));
                        compare   = now;
                        scanlines = 0;
                    }
                }

                if (table.TotalScanlines != Scanlines)
                {
                    table.Add(new HDMATableEntry(TableValueType.db, scanlines, (byte)now));
                }

                table.Add(HDMATableEntry.End);

                DMAMode        mode       = (table[0].Values.Length == 1 ? DMAMode.P : DMAMode.PP);
                ASMCodeBuilder code       = new ASMCodeBuilder();
                int            channelAdd = 16 * channel;
                table.Name = ".BrightTable";

                code.AppendLabel(INITLabel, "Code to be inserted INIT");
                code.OpenNewBlock();
                code.AppendCode("\tREP #$20", "16 bit mode");
                code.AppendCode("\tLDA #$" + (((Registers.Brightness & 0xFF) << 8) + (int)mode).ToString("X4"));
                code.AppendCode("\tSTA $" + (Registers.DMAMode + channelAdd).ToString("X4"));
                code.AppendCode("\tLDA #" + table.Name, "load high and low byte of table address");
                code.AppendCode("\tSTA $" + (Registers.DMALowByte + channelAdd).ToString("X4"));
                code.AppendCode("\tSEP #$20", "back to 8 bit mode");
                code.AppendCode("\tLDA.b #" + table.Name + ">>16", "load bank byte of table address");
                code.AppendCode("\tSTA $" + (Registers.DMABankByte + channelAdd).ToString("X4"));
                code.AppendCode("\tLDA #$" + (1 << channel).ToString("X2"));
                code.AppendCode("\tTSB $" + RAM.HDMAEnable[RAM.SA1].ToString("X4"), "enable HDMA channel " + channel);
                code.AppendCode("\tRTS");
                code.CloseBlock();
                code.AppendEmptyLine();

                code.AppendTable(table);

                return(code.ToString());
            }
        }
Example #3
0
        public static string Code(int Channel, HDMATable Table, bool SA1, string TableName)
        {
            DMAMode       mode       = (Table[0].Values.Length == 1 ? DMAMode.P : DMAMode.PP);
            StringBuilder sbCode     = new StringBuilder();
            int           channelAdd = 16 * Channel;
            string        tableName  = "." + TableName.TrimStart('.');

            sbCode.AppendLine("\tREP #$20");
            sbCode.AppendLine("\tLDA #$" + (((Registers.FixedColor & 0xFF) << 8) + (int)mode).ToString("X4"));
            sbCode.AppendLine("\tSTA $" + (Registers.DMAMode + channelAdd).ToString("X4"));
            sbCode.AppendLine("\tLDA #" + tableName);
            sbCode.AppendLine("\tSTA $" + (Registers.DMALowByte + channelAdd).ToString("X4"));
            sbCode.AppendLine("\tLDY.b #" + tableName + ">>16");
            sbCode.AppendLine("\tSTY $" + (Registers.DMABankByte + channelAdd).ToString("X4"));
            sbCode.AppendLine("\tSEP #$20");
            sbCode.AppendLine("\tLDA #$" + (1 << Channel).ToString("X2"));
            sbCode.AppendLine("\tTSB $" + RAM.HDMAEnable[SA1].ToString("X4"));
            sbCode.AppendLine("\tRTS");
            sbCode.AppendLine();
            sbCode.Append(Table.ToString(tableName));

            return(sbCode.ToString());
        }
Example #4
0
        /// <summary>
        /// Setups the channel.
        /// </summary>
        /// <param name="channel">The channel.</param>
        /// <param name="count">The count.</param>
        /// <param name="mode">The mode.</param>
        /// <param name="type">The type.</param>
        /// <param name="auto">if set to <c>true</c> [auto].</param>
        /// <returns></returns>
        public bool SetupChannel(byte channel, uint count, DMAMode mode, DMATransferType type, bool auto)
        {
            IWriteOnlyIOPort dmaAddress;
            IWriteOnlyIOPort dmaCount;
            IWriteOnlyIOPort dmaPage;
            IMemory memory;

            switch (channel) {
                case 0: dmaAddress = channel0Address; dmaCount = channel0Count; dmaPage = channel0Page; memory = memory0; break;
                case 1: dmaAddress = channel1Address; dmaCount = channel1Count; dmaPage = channel1Page; memory = memory1; break;
                case 2: dmaAddress = channel2Address; dmaCount = channel2Count; dmaPage = channel2Page; memory = memory2; break;
                case 3: dmaAddress = channel3Address; dmaCount = channel3Count; dmaPage = channel3Page; memory = memory3; break;
                default: return false;
            }

            uint address = memory.Address;

            // Disable DMA Controller
            channelMaskRegister.Write8((byte)((byte)channel | 4));

            // Clear any current transfers
            byteWordRegister.Write8((byte)0xFF);	// reset flip-flop

            // Set Address
            dmaAddress.Write8((byte)(address & 0xFF)); // low byte
            dmaAddress.Write8((byte)((address >> 8) & 0xFF)); // high byte
            dmaPage.Write8((byte)((address >> 16) & 0xFF)); // page

            // Clear any current transfers
            byteWordRegister.Write8((byte)0xFF);	// reset flip-flop

            // Set Count
            dmaCount.Write8((byte)((count - 1) & 0xFF)); // low
            dmaCount.Write8((byte)(((count - 1) >> 8) & 0xFF)); // high

            byte value = channel;

            if (auto)
                value = (byte)(value | DMAAutoValue.Auto);
            else
                value = (byte)(value | DMAAutoValue.NoAuto);

            if (mode == DMAMode.ReadFromMemory)
                value = (byte)(value | DMAModeValue.ReadFromMemory);
            else
                value = (byte)(value | DMAModeValue.WriteToMemory);

            switch (type) {
                case DMATransferType.Block: value = (byte)(value | DMATransferTypeValue.Block); break;
                case DMATransferType.CascadeMode: value = (byte)(value | DMATransferTypeValue.CascadeMode); break;
                case DMATransferType.OnDemand: value = (byte)(value | DMATransferTypeValue.OnDemand); break;
                case DMATransferType.Single: value = (byte)(value | DMATransferTypeValue.Single); break;
                default: break;
            }

            // Set DMA Channel to write
            modeRegister.Write8(value);

            // Enable DMA Controller
            channelMaskRegister.Write8((byte)(channel));

            return true;
        }
Example #5
0
		public void SetupChannel (DMAMode mode, DMATransferType type, bool auto, uint count)
		{
			DMA.SetupChannel (channel, count, mode, type, auto);
		}
Example #6
0
        /// <summary>
        /// Setups the channel.
        /// </summary>
        /// <param name="channel">The channel.</param>
        /// <param name="count">The count.</param>
        /// <param name="mode">The mode.</param>
        /// <param name="type">The type.</param>
        /// <param name="auto">if set to <c>true</c> [auto].</param>
        /// <returns></returns>
        public bool SetupChannel(byte channel, uint count, DMAMode mode, DMATransferType type, bool auto)
        {
            IWriteOnlyIOPort dmaAddress;
            IWriteOnlyIOPort dmaCount;
            IWriteOnlyIOPort dmaPage;
            IMemory          memory;

            switch (channel)
            {
            case 0: dmaAddress = channel0Address; dmaCount = channel0Count; dmaPage = channel0Page; memory = memory0; break;

            case 1: dmaAddress = channel1Address; dmaCount = channel1Count; dmaPage = channel1Page; memory = memory1; break;

            case 2: dmaAddress = channel2Address; dmaCount = channel2Count; dmaPage = channel2Page; memory = memory2; break;

            case 3: dmaAddress = channel3Address; dmaCount = channel3Count; dmaPage = channel3Page; memory = memory3; break;

            default: return(false);
            }

            uint address = memory.Address;

            // Disable DMA Controller
            channelMaskRegister.Write8((byte)((byte)channel | 4));

            // Clear any current transfers
            byteWordRegister.Write8((byte)0xFF);                // reset flip-flop

            // Set Address
            dmaAddress.Write8((byte)(address & 0xFF));             // low byte
            dmaAddress.Write8((byte)((address >> 8) & 0xFF));      // high byte
            dmaPage.Write8((byte)((address >> 16) & 0xFF));        // page

            // Clear any current transfers
            byteWordRegister.Write8((byte)0xFF);                // reset flip-flop

            // Set Count
            dmaCount.Write8((byte)((count - 1) & 0xFF));             // low
            dmaCount.Write8((byte)(((count - 1) >> 8) & 0xFF));      // high

            byte value = channel;

            if (auto)
            {
                value = (byte)(value | DMAAutoValue.Auto);
            }
            else
            {
                value = (byte)(value | DMAAutoValue.NoAuto);
            }

            if (mode == DMAMode.ReadFromMemory)
            {
                value = (byte)(value | DMAModeValue.ReadFromMemory);
            }
            else
            {
                value = (byte)(value | DMAModeValue.WriteToMemory);
            }

            switch (type)
            {
            case DMATransferType.Block: value = (byte)(value | DMATransferTypeValue.Block); break;

            case DMATransferType.CascadeMode: value = (byte)(value | DMATransferTypeValue.CascadeMode); break;

            case DMATransferType.OnDemand: value = (byte)(value | DMATransferTypeValue.OnDemand); break;

            case DMATransferType.Single: value = (byte)(value | DMATransferTypeValue.Single); break;

            default: break;
            }

            // Set DMA Channel to write
            modeRegister.Write8(value);

            // Enable DMA Controller
            channelMaskRegister.Write8((byte)(channel));

            return(true);
        }
Example #7
0
		public static unsafe bool SetupChannel (byte channel, uint count, DMAMode mode, DMATransferType type, bool auto)
		{
			IO.Port dma_page;
			IO.Port dma_address;
			IO.Port dma_count;

			if (count > (1024 * 64))
				return false;

			switch (channel) {
				case 1:
					dma_page = IO.Port.DMA_Channel1Page;
					dma_address = IO.Port.DMA_Channel1Address;
					dma_count = IO.Port.DMA_Channel1Count;
					break;
				case 2:
					dma_page = IO.Port.DMA_Channel2Page;
					dma_address = IO.Port.DMA_Channel2Address;
					dma_count = IO.Port.DMA_Channel2Count;
					break;
				case 3:
					dma_page = IO.Port.DMA_Channel3Page;
					dma_address = IO.Port.DMA_Channel3Address;
					dma_count = IO.Port.DMA_Channel3Count;
					break;
				default:
					// TODO: throw an exception when we have exception support
					return false;
			}

			uint address = (uint)GetDMATranserAddress (channel);

			Barrier.Enter ();
			// Disable DMA Controller
			IO.WriteByte (IO.Port.DMA_ChannelMaskRegister, (byte)((byte)channel | 4));

			// Clear any current transfers
			IO.WriteByte (IO.Port.DMA_ClearBytePointerFlipFlop, (byte)0xFF);	// reset flip-flop

			// Set Address	
			IO.WriteByte (dma_address, (byte)(address & 0xFF)); // low byte
			IO.WriteByte (dma_address, (byte)((address >> 8) & 0xFF)); // high byte
			IO.WriteByte (dma_page, (byte)((address >> 16) & 0xFF)); // page

			// Clear any current transfers
			IO.WriteByte (IO.Port.DMA_ClearBytePointerFlipFlop, (byte)0xFF);	// reset flip-flop

			// Set Count
			IO.WriteByte (dma_count, (byte)((count - 1) & 0xFF)); // low
			IO.WriteByte (dma_count, (byte)(((count - 1) >> 8) & 0xFF)); // high

			byte value = (byte)(channel | (auto ? DMAAutoValue.Auto : DMAAutoValue.NoAuto) | ToValue (type));
			value = (byte)(value | (mode == DMAMode.ReadFromMemory ? DMAModeValue.ReadFromMemory : DMAModeValue.WriteToMemory));

			// Set DMA_Channel to write
			IO.WriteByte (IO.Port.DMA_ModeRegister, value);

			// Enable DMA Controller
			IO.WriteByte (IO.Port.DMA_ChannelMaskRegister, (byte)(channel));

			Barrier.Exit ();

			return true;
		}
Example #8
0
 /// <summary>
 /// Builds the mode value used for DMA/HDMA transfer. The value's stored to $43x0
 /// </summary>
 /// <param name="direction">Which direction the transfer should go to/come from</param>
 /// <param name="indirect">Used only in HDMA. Whether the table shown by the pointers has the values or addresses to the values
 /// <para><c>True</c> if the table has addresses</para></param>
 /// <param name="increment">Used only in DMA. Whether the address will be incremented or decremented
 /// <c>True</c> if the address should be decremented</param>
 /// <param name="fixedtrans">When set, the address will not be adjusted</param>
 /// <param name="mode">How often and where bytes should be written to the register</param>
 /// <returns>The compiled byte</returns>
 public static int GetMode(DMADirection direction, bool indirect, bool increment, bool fixedtrans, DMAMode mode)
 {
     return((int)direction + (indirect ? 0x40 : 0) + (increment ? 0x20 : 0) + (fixedtrans ? 0x10 : 0) + (int)mode);
 }
Example #9
0
 /// <summary>
 /// Builds the mode value used for HDMA transfer. The value's stored to $43x0
 /// </summary>
 /// <param name="indirect">Used only in HDMA. Whether the table shown by the pointers has the values or addresses to the values
 /// <para><c>True</c> if the table has addresses</para></param>
 /// <param name="mode">How often and where bytes should be written to the register</param>
 /// <returns>The compiled byte</returns>
 public static int GetMode(bool indirect, DMAMode mode)
 {
     return((int)mode + (indirect ? 0x40 : 0));
 }
Example #10
0
 public void SetupChannel(DMAMode mode, DMATransferType type, bool auto, uint count)
 {
     DMA.SetupChannel(channel, count, mode, type, auto);
 }
Example #11
0
        public static string Code(ColorHDMA red, ColorHDMA green, ColorHDMA blue,
                                  PickSingleChannel single, PickMultiChannel multi, PickMultiChannel tripple)
        {
            bool redEmpty   = red.IsEmpty();
            bool greenEmpty = green.IsEmpty();
            bool blueEmpty  = blue.IsEmpty();

            if (redEmpty && blueEmpty && greenEmpty)
            {
                //fixme Exception
                throw new ArgumentException("Cannot generate code from the provided arguments");
            }

            if (redEmpty && blueEmpty)
            {
                return(green.Code(single()));
            }
            if (greenEmpty && blueEmpty)
            {
                return(red.Code(single()));
            }
            if (redEmpty && greenEmpty)
            {
                return(blue.Code(single()));
            }

            int[] newChannels = new int[] { 3, 4, 5 };
            Dictionary <string, HDMATable> dicTable = new Dictionary <string, HDMATable>();
            HDMATable merged = null;

            if (greenEmpty)
            {
                if (HDMATable.Merge(red.Table, blue.Table, out merged))
                {
                    return(ColorHDMA.Code(single(), merged, ".RedBlueTable"));
                }
                else
                {
                    newChannels = multi();
                    dicTable.Add(".RedTable", red.Table);
                    dicTable.Add(".BlueTable", blue.Table);
                }
            }
            else if (redEmpty)
            {
                if (HDMATable.Merge(green.Table, blue.Table, out merged))
                {
                    return(ColorHDMA.Code(single(), merged, ".GreenBlueTable"));
                }
                else
                {
                    newChannels = multi();
                    dicTable.Add(".GreenTable", green.Table);
                    dicTable.Add(".BlueTable", blue.Table);
                }
            }
            else if (blueEmpty)
            {
                if (HDMATable.Merge(green.Table, red.Table, out merged))
                {
                    return(ColorHDMA.Code(single(), merged, ".RedGreenTable"));
                }
                else
                {
                    newChannels = multi();
                    dicTable.Add(".GreenTable", green.Table);
                    dicTable.Add(".RedTable", red.Table);
                }
            }
            else
            {
                if (HDMATable.Merge(green.Table, red.Table, out merged))
                {
                    newChannels = multi();
                    dicTable.Add(".RedGreenTable", merged);
                    dicTable.Add(".BlueTable", blue.Table);
                }
                else if (HDMATable.Merge(green.Table, blue.Table, out merged))
                {
                    newChannels = multi();
                    dicTable.Add(".GreenBlueTable", merged);
                    dicTable.Add(".RedTable", red.Table);
                }
                else if (HDMATable.Merge(red.Table, blue.Table, out merged))
                {
                    newChannels = multi();
                    dicTable.Add(".RedBlueTable", merged);
                    dicTable.Add(".GreenTable", red.Table);
                }
                else
                {
                    newChannels = tripple();
                    dicTable.Add(".RedTable", red.Table);
                    dicTable.Add(".GreenTable", green.Table);
                    dicTable.Add(".BlueTable", blue.Table);
                }
            }

            if (dicTable.Count != newChannels.Length)
            {
                throw new ArgumentException("Number of channels doesn't match number of tables.");
            }

            Func <KeyValuePair <string, HDMATable>, string> getTablename = old => "." + old.Key.TrimStart('.');

            int           channelTrigger = 0;
            StringBuilder sbCode         = new StringBuilder();

            //sbCode.AppendLine("init:");
            sbCode.AppendLine("\tREP #$20");

            for (int i = 0; i < dicTable.Count; i++)
            {
                KeyValuePair <string, HDMATable> tablePair = dicTable.ElementAt(i);
                DMAMode mode       = (tablePair.Value[0].Values.Length == 1 ? DMAMode.P : DMAMode.PP);
                int     channelAdd = 16 * newChannels[i];
                string  tableName  = getTablename(tablePair);

                sbCode.AppendLine("\tLDA #$" + (((Registers.FixedColor & 0xFF) << 8) + (int)mode).ToString("X4"));
                sbCode.AppendLine("\tSTA $" + (Registers.DMAMode + channelAdd).ToString("X4"));
                sbCode.AppendLine("\tLDA #" + tableName);
                sbCode.AppendLine("\tSTA $" + (Registers.DMALowByte + channelAdd).ToString("X4"));
                sbCode.AppendLine("\tLDY.b #" + tableName + ">>16");
                sbCode.AppendLine("\tSTY $" + (Registers.DMABankByte + channelAdd).ToString("X4"));

                channelTrigger += (1 << newChannels[i]);
            }

            sbCode.AppendLine("\tSEP #$20");
            sbCode.AppendLine("\tLDA #$" + channelTrigger.ToString("X2"));
            sbCode.AppendLine("\tTSB $" + RAM.HDMAEnable[RAM.SA1].ToString("X4") + "|!addr");
            sbCode.AppendLine("\tRTL");

            for (int i = 0; i < dicTable.Count; i++)
            {
                KeyValuePair <string, HDMATable> tablePair = dicTable.ElementAt(i);
                string tableName = getTablename(tablePair);
                sbCode.AppendLine();
                sbCode.Append(tablePair.Value.ToString(tableName));
            }

            return(sbCode.ToString());
        }
Example #12
0
        public static unsafe bool SetupChannel(byte channel, uint count, DMAMode mode, DMATransferType type, bool auto)
        {
            IO.Port dma_page;
            IO.Port dma_address;
            IO.Port dma_count;

            if (count > (1024 * 64))
            {
                return(false);
            }

            switch (channel)
            {
            case 1:
                dma_page    = IO.Port.DMA_Channel1Page;
                dma_address = IO.Port.DMA_Channel1Address;
                dma_count   = IO.Port.DMA_Channel1Count;
                break;

            case 2:
                dma_page    = IO.Port.DMA_Channel2Page;
                dma_address = IO.Port.DMA_Channel2Address;
                dma_count   = IO.Port.DMA_Channel2Count;
                break;

            case 3:
                dma_page    = IO.Port.DMA_Channel3Page;
                dma_address = IO.Port.DMA_Channel3Address;
                dma_count   = IO.Port.DMA_Channel3Count;
                break;

            default:
                // TODO: throw an exception when we have exception support
                return(false);
            }

            uint address = (uint)GetDMATranserAddress(channel);

            Barrier.Enter();
            // Disable DMA Controller
            IO.WriteByte(IO.Port.DMA_ChannelMaskRegister, (byte)((byte)channel | 4));

            // Clear any current transfers
            IO.WriteByte(IO.Port.DMA_ClearBytePointerFlipFlop, (byte)0xFF);                     // reset flip-flop

            // Set Address
            IO.WriteByte(dma_address, (byte)(address & 0xFF));              // low byte
            IO.WriteByte(dma_address, (byte)((address >> 8) & 0xFF));       // high byte
            IO.WriteByte(dma_page, (byte)((address >> 16) & 0xFF));         // page

            // Clear any current transfers
            IO.WriteByte(IO.Port.DMA_ClearBytePointerFlipFlop, (byte)0xFF);                     // reset flip-flop

            // Set Count
            IO.WriteByte(dma_count, (byte)((count - 1) & 0xFF));              // low
            IO.WriteByte(dma_count, (byte)(((count - 1) >> 8) & 0xFF));       // high

            byte value = (byte)(channel | (auto ? DMAAutoValue.Auto : DMAAutoValue.NoAuto) | ToValue(type));

            value = (byte)(value | (mode == DMAMode.ReadFromMemory ? DMAModeValue.ReadFromMemory : DMAModeValue.WriteToMemory));

            // Set DMA_Channel to write
            IO.WriteByte(IO.Port.DMA_ModeRegister, value);

            // Enable DMA Controller
            IO.WriteByte(IO.Port.DMA_ChannelMaskRegister, (byte)(channel));

            Barrier.Exit();

            return(true);
        }