Ejemplo n.º 1
0
static inline bool8 addCyclesInDMA (uint8 dma_channel)
{
	// Add 8 cycles per byte, sync APU, and do HC related events.
	// If HDMA was done in S9xDoHEventProcessing(), check if it used the same channel as DMA.
	ADD_CYCLES(SLOW_ONE_CYCLE);
	while (CPU.Cycles >= CPU.NextEvent)
		S9xDoHEventProcessing();

	if (CPU.HDMARanInDMA & (1 << dma_channel))
	{
		CPU.HDMARanInDMA = 0;
	#ifdef DEBUGGER
		printf("HDMA and DMA use the same channel %d!\n", dma_channel);
	#endif
		// If HDMA triggers in the middle of DMA transfer and it uses the same channel,
		// it kills the DMA transfer immediately. $43x2 and $43x5 stop updating.
		return (FALSE);
	}

	CPU.HDMARanInDMA = 0;
	return (TRUE);
}
Ejemplo n.º 2
0
int get_indexed(struct _memory *memory, struct _table_6809 *table, char *instruction, uint32_t address, int *cycles_min, int *cycles_max)
{
  const char *name[] = { "x", "y", "u", "s" };
  uint8_t post_byte = READ_RAM(address);
  int reg = (post_byte >> 5) & 0x3;

  if ((post_byte & 0x9f) == 0x84)
  {
    // ,R non-indirect
    sprintf(instruction, "%s ,%s", table->instr, name[reg]);
    return 0;
  }
    else
  if ((post_byte & 0x9f) == 0x94)
  {
    // [,R] indirect
    sprintf(instruction, "%s [,%s]", table->instr, name[reg]);
    ADD_CYCLES(3);
    return 0;
  }
    else
  if ((post_byte & 0x80) == 0x00)
  {
    // 5 bit offset, R non-indirect
    int8_t offset = post_byte & 0x1f;
    if ((offset & 0x10) != 0) { offset |= 0xe0; }
    sprintf(instruction, "%s %d,%s", table->instr, offset, name[reg]);
    ADD_CYCLES(1);
    return 0;
  }
    else
  if ((post_byte & 0x9f) == 0x88)
  {
    // 8 bit offset, R non-indirect
    int8_t offset = READ_RAM(address + 1);
    sprintf(instruction, "%s %d,%s", table->instr, offset, name[reg]);
    ADD_CYCLES(1);
    return 1;
  }
    else
  if ((post_byte & 0x9f) == 0x98)
  {
    // [8 bit offset, R] indirect
    int8_t offset = READ_RAM(address + 1);
    sprintf(instruction, "%s [%d,%s]", table->instr, offset, name[reg]);
    ADD_CYCLES(4);
    return 1;
  }
    else
  if ((post_byte & 0x9f) == 0x89)
  {
    // 16 bit offset, R non-indirect
    int16_t offset = READ_RAM16(address + 1);
    sprintf(instruction, "%s %d,%s", table->instr, offset, name[reg]);
    ADD_CYCLES(4);
    return 2;
  }
    else
  if ((post_byte & 0x9f) == 0x99)
  {
    // [16 bit offset, R] indirect
    int16_t offset = READ_RAM16(address + 1);
    sprintf(instruction, "%s [%d,%s]", table->instr, offset, name[reg]);
    ADD_CYCLES(7);
    return 2;
  }
    else
  if ((post_byte & 0x9f) == 0x86)
  {
    // A,R non-indirect
    sprintf(instruction, "%s a,%s", table->instr, name[reg]);
    ADD_CYCLES(1);
    return 0;
  }
    else
  if ((post_byte & 0x9f) == 0x96)
  {
    // [A,R] non-indirect
    sprintf(instruction, "%s [a,%s]", table->instr, name[reg]);
    ADD_CYCLES(4);
    return 0;
  }
    else
  if ((post_byte & 0x9f) == 0x85)
  {
    // B,R non-indirect
    sprintf(instruction, "%s b,%s", table->instr, name[reg]);
    ADD_CYCLES(1);
    return 0;
  }
    else
  if ((post_byte & 0x9f) == 0x95)
  {
    // [B,R] indirect
    sprintf(instruction, "%s [b,%s]", table->instr, name[reg]);
    ADD_CYCLES(4);
    return 0;
  }
    else
  if ((post_byte & 0x9f) == 0x8b)
  {
    // D,R non-indirect
    sprintf(instruction, "%s d,%s", table->instr, name[reg]);
    ADD_CYCLES(4);
    return 0;
  }
    else
  if ((post_byte & 0x9f) == 0x9b)
  {
    // [D,R] non-indirect
    sprintf(instruction, "%s [d,%s]", table->instr, name[reg]);
    ADD_CYCLES(7);
    return 0;
  }
    else
  if ((post_byte & 0x9f) == 0x80)
  {
    // ,R+ non-indirect
    sprintf(instruction, "%s ,%s+", table->instr, name[reg]);
    ADD_CYCLES(2);
    return 0;
  }
    else
  if ((post_byte & 0x9f) == 0x81)
  {
    // ,R++ non-indirect
    sprintf(instruction, "%s ,%s++", table->instr, name[reg]);
    ADD_CYCLES(3);
    return 0;
  }
    else
  if ((post_byte & 0x9f) == 0x91)
  {
    // [,R++] indirect
    sprintf(instruction, "%s [,%s++]", table->instr, name[reg]);
    ADD_CYCLES(6);
    return 0;
  }
    else
  if ((post_byte & 0x9f) == 0x82)
  {
    // ,-R non-indirect
    sprintf(instruction, "%s ,-%s", table->instr, name[reg]);
    ADD_CYCLES(2);
    return 0;
  }
    else
  if ((post_byte & 0x9f) == 0x83)
  {
    // ,--R non-indirect
    sprintf(instruction, "%s ,--%s", table->instr, name[reg]);
    ADD_CYCLES(3);
    return 0;
  }
    else
  if ((post_byte & 0x9f) == 0x93)
  {
    // [,--R] indirect
    sprintf(instruction, "%s [,--%s]", table->instr, name[reg]);
    ADD_CYCLES(6);
    return 0;
  }
    else
  if ((post_byte & 0x9f) == 0x8c)
  {
    // 8 bit offset, PCR non-indirect
    int8_t offset = READ_RAM(address + 1);
    sprintf(instruction, "%s %d,pc", table->instr, offset);
    ADD_CYCLES(1);
    return 1;
  }
    else
  if ((post_byte & 0x9f) == 0x9c)
  {
    // [8 bit offset, PCR] indirect
    int8_t offset = READ_RAM(address + 1);
    sprintf(instruction, "%s [%d,pc]", table->instr, offset);
    ADD_CYCLES(4);
    return 1;
  }
    else
  if ((post_byte & 0x9f) == 0x8d)
  {
    // 16 bit offset, PCR non-indirect
    int16_t offset = READ_RAM16(address + 1);
    sprintf(instruction, "%s %d,pc", table->instr, offset);
    ADD_CYCLES(5);
    return 2;
  }
    else
  if ((post_byte & 0x9f) == 0x9d)
  {
    // [16 bit offset, PCR] non-indirect
    int16_t offset = READ_RAM16(address + 1);
    sprintf(instruction, "%s [%d,pc]", table->instr, offset);
    ADD_CYCLES(8);
    return 2;
  }
    else
  if ((post_byte & 0x9f) == 0x9f)
  {
    // [16 bit offset] non-indirect
    int16_t offset = READ_RAM16(address + 1);
    sprintf(instruction, "%s [0x%04x]", table->instr, offset);
    ADD_CYCLES(5);
    return 2;
  }

  strcpy(instruction, "???");

  return 0;
}
Ejemplo n.º 3
0
bool8 S9xDoDMA (uint8 Channel)
{
	CPU.InDMA = TRUE;
    CPU.InDMAorHDMA = TRUE;
	CPU.CurrentDMAorHDMAChannel = Channel;

    SDMA	*d = &DMA[Channel];

	// Check invalid DMA first
	if ((d->ABank == 0x7E || d->ABank == 0x7F) && d->BAddress == 0x80 && !d->ReverseTransfer)
	{
		// Attempting a DMA from WRAM to $2180 will not work, WRAM will not be written.
		// Attempting a DMA from $2180 to WRAM will similarly not work,
		// the value written is (initially) the OpenBus value.
		// In either case, the address in $2181-3 is not incremented.

		// Does an invalid DMA actually take time?
		// I'd say yes, since 'invalid' is probably just the WRAM chip
		// not being able to read and write itself at the same time
		// And no, PPU.WRAM should not be updated.

		int32	c = d->TransferBytes;
		// Writing $0000 to $43x5 actually results in a transfer of $10000 bytes, not 0.
		if (c == 0)
			c = 0x10000;

		// 8 cycles per channel
		ADD_CYCLES(SLOW_ONE_CYCLE);
		// 8 cycles per byte
		while (c)
		{
			d->TransferBytes--;
			d->AAddress++;
			c--;
			if (!addCyclesInDMA(Channel))
			{
				CPU.InDMA = FALSE;
				CPU.InDMAorHDMA = FALSE;
				CPU.CurrentDMAorHDMAChannel = -1;
				return (FALSE);
			}
		}

	#ifdef DEBUGGER
		if (Settings.TraceDMA)
		{
			sprintf(String, "DMA[%d]: WRAM Bank:%02X->$2180", Channel, d->ABank);
			S9xMessage(S9X_TRACE, S9X_DMA_TRACE, String);
		}
	#endif

		CPU.InDMA = FALSE;
		CPU.InDMAorHDMA = FALSE;
		CPU.CurrentDMAorHDMAChannel = -1;
		return (TRUE);
	}

	// Prepare for accessing $2118-2119
	switch (d->BAddress)
	{
		case 0x18:
		case 0x19:
			if (IPPU.RenderThisFrame)
				FLUSH_REDRAW();
			break;
	}

	int32	inc = d->AAddressFixed ? 0 : (!d->AAddressDecrement ? 1 : -1);
	int32	count = d->TransferBytes;
	// Writing $0000 to $43x5 actually results in a transfer of $10000 bytes, not 0.
	if (count == 0)
		count = 0x10000;

	// Prepare for custom chip DMA

	// S-DD1

	uint8	*in_sdd1_dma = NULL;

	if (Settings.SDD1)
	{
		if (d->AAddressFixed && Memory.FillRAM[0x4801] > 0)
		{
			// XXX: Should probably verify that we're DMAing from ROM?
			// And somewhere we should make sure we're not running across a mapping boundary too.
			// Hacky support for pre-decompressed S-DD1 data
			inc = !d->AAddressDecrement ? 1 : -1;

			uint8	*in_ptr = S9xGetBasePointer(((d->ABank << 16) | d->AAddress));
			if (in_ptr)
			{
				in_ptr += d->AAddress;
				SDD1_decompress(sdd1_decode_buffer, in_ptr, d->TransferBytes);
			}
		#ifdef DEBUGGER
			else
			{
				sprintf(String, "S-DD1: DMA from non-block address $%02X:%04X", d->ABank, d->AAddress);
				S9xMessage(S9X_WARNING, S9X_DMA_TRACE, String);
			}
		#endif

			in_sdd1_dma = sdd1_decode_buffer;
		}

		Memory.FillRAM[0x4801] = 0;
	}

	// SPC7110

	uint8	*spc7110_dma = NULL;

	if (Settings.SPC7110)
	{
		if (d->AAddress == 0x4800 || d->ABank == 0x50)
		{
			spc7110_dma = new uint8[d->TransferBytes];
			for (int i = 0; i < d->TransferBytes; i++)
				spc7110_dma[i] = s7emu.decomp.read();

			int32	icount = s7emu.r4809 | (s7emu.r480a << 8);
			icount -= d->TransferBytes;
			s7emu.r4809 =  icount & 0x00ff;
			s7emu.r480a = (icount & 0xff00) >> 8;

			inc = 1;
			d->AAddress -= count;
		}
	}