/// <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()); } }
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()); }
/// <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; }
public void SetupChannel (DMAMode mode, DMATransferType type, bool auto, uint count) { DMA.SetupChannel (channel, count, mode, type, auto); }
/// <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); }
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; }
/// <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); }
/// <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)); }
public void SetupChannel(DMAMode mode, DMATransferType type, bool auto, uint count) { DMA.SetupChannel(channel, count, mode, type, auto); }
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()); }
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); }