<commit_before>gpub.spec.specTest  = function() {
  module('gpub.spec.specTest');
  var spec = gpub.spec;
  var defaultOptions = gpub.processOptions();
  var bookPurpose = gpub.bookPurpose;
  var ALL_REGION = glift.enums.boardRegions.ALL;

  test('fromSgfs: Default Case', function() {
    var out = spec.create([], defaultOptions);
    deepEqual(out.divId, null);
    deepEqual(out.sgfCollection, []);
    deepEqual(out.sgfMapping, {});
    deepEqual(out.metadata, {});
  });

  test('createExample', function() {
    var out = spec._createExample('zed', [0,0,0], [0,1], ALL_REGION);
    // deepEqual(out.widgetType, 'EXAMPLE');
    deepEqual(out.alias, 'zed');
    deepEqual(out.initialPosition, '3');
    deepEqual(out.nextMovesPath, '0.1');
    deepEqual(out.boardRegion, 'ALL');
  });

  test('fromSgfs: one simple game', function() {
    var out = spec.create([
        '(;GM[1]AW[aa]AB[ba];B[bb]C[The End!])'
      ], defaultOptions);
    var outcol = out.sgfCollection;
    deepEqual(outcol.length, 1);
    deepEqual(outcol[0], spec._createExample('sgf:0', [], [0], 'AUTO'));
  });

  test('fromsGfs: one simple game, with variation', function() {
    var out = spec.create([
      '(;GM[1]AW[aa]AB[ba];B[bb](;W[ab]C[The End!])(;W[ac]C[Surprise!]))'
      ], defaultOptions);
    var outcol = out.sgfCollection;
    deepEqual(outcol.length, 2);
    deepEqual(outcol[0], spec._createExample('sgf:0', [], '0.0', 'AUTO'));
    deepEqual(outcol[1], spec._createExample('sgf:0', [0], '1', 'AUTO'));
  });
};
<commit_msg>Add test for problem set.<commit_after>gpub.spec.specTest  = function() {
  module('gpub.spec.specTest');
  var spec = gpub.spec;
  var defaultOptions = gpub.processOptions();
  var problemSetOpts = gpub.processOptions({
    bookPurpose: gpub.bookPurpose.PROBLEM_SET
  });

  test('Create: Default Case', function() {
    var out = spec.create([], defaultOptions);
    deepEqual(out.divId, null);
    deepEqual(out.sgfCollection, []);
    deepEqual(out.sgfMapping, {});
    deepEqual(out.metadata, {});
  });

  test('createExample', function() {
    var all = glift.enums.boardRegions.ALL;
    var out = spec._createExample('zed', [0,0,0], [0,1], all);
    // deepEqual(out.widgetType, 'EXAMPLE');
    deepEqual(out.alias, 'zed');
    deepEqual(out.initialPosition, '3');
    deepEqual(out.nextMovesPath, '0.1');
    deepEqual(out.boardRegion, 'ALL');
  });

  test('Create: one simple game', function() {
    var out = spec.create([
        '(;GM[1]AW[aa]AB[ba];B[bb]C[The End!])'
      ], defaultOptions);
    var outcol = out.sgfCollection;
    deepEqual(outcol.length, 1);
    deepEqual(outcol[0], spec._createExample('sgf:0', [], [0], 'AUTO'));
  });

  test('Create: one simple game, with variation', function() {
    var out = spec.create([
      '(;GM[1]AW[aa]AB[ba];B[bb](;W[ab]C[The End!])(;W[ac]C[Surprise!]))'
      ], defaultOptions);
    var outcol = out.sgfCollection;
    deepEqual(outcol.length, 2);
    deepEqual(outcol[0], spec._createExample('sgf:0', [], '0.0', 'AUTO'));
    deepEqual(outcol[1], spec._createExample('sgf:0', [0], '1', 'AUTO'));
  });

  test('Create: Problem set', function() {
    var out = spec.create([
        '(;GM[1]AW[aa]AB[ba];B[bb];W[cc](;B[ab]C[Correct!])(;W[ac]C[Surprise!]))'
      ], problemSetOpts);
    ok(out);
    deepEqual(out.sgfDefaults.widgetType, 'STANDARD_PROBLEM');
    var outcol = out.sgfCollection;
    deepEqual(outcol.length, 1);
    deepEqual(outcol[0], {
      'alias': 'sgf:0',
      'boardRegion': 'AUTO'
    });
  });
};
<|endoftext|>


<commit_before>GameBoyAdvanceIO = function() {
	// Video
	this.DISPCNT = 0x000;
	this.GREENSWP = 0x002;
	this.DISPSTAT = 0x004;
	this.VCOUNT = 0x006;
	this.BG0CNT = 0x008;
	this.BG1CNT = 0x00A;
	this.BG2CNT = 0x00C;
	this.BG3CNT = 0x00E;
	this.BG0HOFS = 0x010;
	this.BG0VOFS = 0x012;
	this.BG1HOFS = 0x014;
	this.BG1VOFS = 0x016;
	this.BG2HOFS = 0x018;
	this.BG2VOFS = 0x01A;
	this.BG3HOFS = 0x01C;
	this.BG3VOFS = 0x01E;
	this.BG2PA = 0x020;
	this.BG2PB = 0x022;
	this.BG2PC = 0x024;
	this.BG2PD = 0x026;
	this.BG2X_LO = 0x028;
	this.BG2X_HI = 0x02E;
	this.BG2Y_LO = 0x02C;
	this.BG2Y_HI = 0x02E;
	this.BG3PA = 0x030;
	this.BG3PB = 0x032;
	this.BG3PC = 0x034;
	this.BG3PD = 0x036;
	this.BG3X_LO = 0x038;
	this.BG3X_HI = 0x03A;
	this.BG3Y_LO = 0x03C;
	this.BG3Y_HI = 0x03E;
	this.WIN0H = 0x040;
	this.WIN1H = 0x042;
	this.WIN0V = 0x044;
	this.WIN1V = 0x046;
	this.WININ = 0x048;
	this.WINOUT = 0x04A;
	this.MOSAIC = 0x04C;
	this.BLDCNT = 0x050;
	this.BLDALPHA = 0x052;
	this.BLDY = 0x054;

	// Sound
	this.SOUND1CNT_LO = 0x060;
	this.SOUND1CNT_HI = 0x062;
	this.SOUND1CNT_X = 0x064;
	this.SOUND2CNT_LO = 0x068;
	this.SOUND2CNT_HI = 0x06C;
	this.SOUND3CNT_LO = 0x070;
	this.SOUND3CNT_HI = 0x072;
	this.SOUND3CNT_X = 0x074;
	this.SOUND4CNT_LO = 0x078;
	this.SOUND4CNT_HI = 0x07C;
	this.SOUNDCNT_L0 = 0x080;
	this.SOUNDCNT_HI = 0x082;
	this.SOUNDCNT_X = 0x084;
	this.SOUNDBIAS = 0x088;
	this.FIFO_A_LO = 0x0A0;
	this.FIFO_A_HI = 0x0A2;
	this.FIFO_B_LO = 0x0A4;
	this.FIFO_B_HI = 0x0A6;

	// DMA
	this.DMA0SAD_LO = 0x0B0;
	this.DMA0SAD_HI = 0x0B2;
	this.DMA0DAD_LO = 0x0B4;
	this.DMA0DAD_HI = 0x0B6;
	this.DMA0CNT_LO = 0x0B8;
	this.DMA0CNT_HI = 0x0BA;
	this.DMA1SAD_LO = 0x0BC;
	this.DMA1SAD_HI = 0x0BE;
	this.DMA1DAD_LO = 0x0C0;
	this.DMA1DAD_HI = 0x0C2;
	this.DMA1CNT_LO = 0x0C4;
	this.DMA1CNT_HI = 0x0C6;
	this.DMA2SAD_LO = 0x0C8;
	this.DMA2SAD_HI = 0x0CA;
	this.DMA2DAD_LO = 0x0CC;
	this.DMA2DAD_HI = 0x0CE;
	this.DMA2CNT_LO = 0x0D0;
	this.DMA2CNT_HI = 0x0D2;
	this.DMA3SAD_LO = 0x0D4;
	this.DMA3SAD_HI = 0x0D6;
	this.DMA3DAD_LO = 0x0D8;
	this.DMA3DAD_HI = 0x0DA;
	this.DMA3CNT_LO = 0x0DC;
	this.DMA3CNT_HI = 0x0DE;

	// Timers
	this.TM0CNT_LO = 0x100;
	this.TM0CNT_HI = 0x102;
	this.TM1CNT_LO = 0x104;
	this.TM1CNT_HI = 0x106;
	this.TM2CNT_LO = 0x108;
	this.TM2CNT_HI = 0x10A;
	this.TM3CNT_LO = 0x10C;
	this.TM3CNT_HI = 0x10E;

	// Keypad
	this.KEYINPUT = 0x130;
	this.KEYCNT = 0x132;

	// Interrupts, etc
	this.IE = 0x200;
	this.IF = 0x202;
	this.WAITCNT = 0x204;
	this.IME = 0x208;
};

GameBoyAdvanceIO.prototype.setCPU = function(cpu) {
	this.cpu = cpu;
};

GameBoyAdvanceIO.prototype.setVideo = function(video) {
	this.video = video;
};

GameBoyAdvanceIO.prototype.clear = function() {
	this.registers = new Uint16Array(this.cpu.mmu.SIZE_IO);
};

GameBoyAdvanceIO.prototype.load8 = function(offset) {
	throw "Unimplmeneted unaligned I/O access";
}

GameBoyAdvanceIO.prototype.load16 = function(offset) {
	return this.loadU16(offset) >> 0;
}

GameBoyAdvanceIO.prototype.load32 = function(offset) {
	switch (offset) {
	case this.DMA0CNT_LO:
	case this.DMA1CNT_LO:
	case this.DMA2CNT_LO:
	case this.DMA3CNT_LO:
		return this.loadU16(offset | 2) << 16;
	}

	return this.loadU16(offset) | (this.loadU16(offset | 2) << 16);
};

GameBoyAdvanceIO.prototype.loadU8 = function(offset) {
	throw "Unimplmeneted unaligned I/O access";
}

GameBoyAdvanceIO.prototype.loadU16 = function(offset) {
	switch (offset) {
	case this.DISPCNT:
	case this.WAITCNT:
	case this.IME:
		// Handled transparently by the written registers
		break;
	case this.DISPSTAT:
		return this.registers[offset >> 1] | this.video.readDisplayStat();
	case this.DMA0CNT_HI:
	case this.DMA1CNT_HI:
	case this.DMA2CNT_HI:
	case this.DMA3CNT_HI:
		break;
	default:
		throw "Unimplemented I/O register read: 0x" + offset.toString(16);
	}
	return this.registers[offset >> 1];
};

GameBoyAdvanceIO.prototype.store16 = function(offset, value) {
	switch (offset) {
	// Video
	case this.DISPCNT:
		this.video.writeDisplayControl(value);
		break;
	case this.DISPSTAT:
		value &= this.video.DISPSTAT_MASK;
		this.video.writeDisplayStat(value);
		break;

	// Sound
	// TODO: implement sound
	case this.SOUNDCNT_LO:
		value &= 0xFF77;
		break;
	case this.SOUNDCNT_HI:
		value &= 0xFF0F;
		break;
	case this.SOUNDCNT_X:
		value &= 0x0080;
		break;

	// DMA
	case this.DMA0CNT_LO:
		this.cpu.irq.dmaSetWordCount(0, value);
		return;
	case this.DMA0CNT_HI:
		// The DMA registers need to set the values before writing the control, as writing the
		// control can synchronously trigger a DMA transfer
		this.registers[offset >> 1] = value & 0xFFE0;
		this.cpu.irq.dmaWriteControl(0, value);
		break;
	case this.DMA1CNT_LO:
		this.cpu.irq.dmaSetWordCount(1, value);
		return;
	case this.DMA1CNT_HI:
		this.registers[offset >> 1] = value & 0xFFE0;
		this.cpu.irq.dmaWriteControl(1, value);
		break;
	case this.DMA2CNT_LO:
		this.cpu.irq.dmaSetWordCount(2, value);
		return;
	case this.DMA2CNT_HI:
		this.registers[offset >> 1] = value & 0xFFE0;
		this.cpu.irq.dmaWriteControl(2, value);
		break;
	case this.DMA3CNT_LO:
		this.cpu.irq.dmaSetWordCount(3, value);
		return;
	case this.DMA3CNT_HI:
		this.registers[offset >> 1] = value & 0xFFE0;
		this.cpu.irq.dmaWriteControl(3, value);
		return;

	// Misc
	case this.WAITCNT:
		// TODO: implement this
		value &= 0x5FFF;
		break;
	case this.IME:
		value &= 0x0001;
		this.cpu.irq.masterEnable(value);
		break;
	default:
		throw "Unimplemented I/O register write: 0x" + offset.toString(16);
	}
	this.registers[offset >> 1] = value;
};

GameBoyAdvanceIO.prototype.store32 = function(offset, value) {
	switch (offset) {
	case this.DMA0SAD_LO:
		this.cpu.irq.dmaSetSourceAddress(0, value);
		return;
	case this.DMA0DAD_LO:
		this.cpu.irq.dmaSetDestAddress(0, value);
		return;
	case this.DMA1SAD_LO:
		this.cpu.irq.dmaSetSourceAddress(1, value);
		return;
	case this.DMA1DAD_LO:
		this.cpu.irq.dmaSetDestAddress(1, value);
		return;
	case this.DMA2SAD_LO:
		this.cpu.irq.dmaSetSourceAddress(2, value);
		return;
	case this.DMA2DAD_LO:
		this.cpu.irq.dmaSetDestAddress(2, value);
		return;
	case this.DMA3SAD_LO:
		this.cpu.irq.dmaSetSourceAddress(3, value);
		return;
	case this.DMA3DAD_LO:
		this.cpu.irq.dmaSetDestAddress(3, value);
		return;
	}

	this.store16(offset, value & 0xFFFF);
	this.store16(offset + 2, value >> 16);
};
<commit_msg>Implement unaligned read<commit_after>GameBoyAdvanceIO = function() {
	// Video
	this.DISPCNT = 0x000;
	this.GREENSWP = 0x002;
	this.DISPSTAT = 0x004;
	this.VCOUNT = 0x006;
	this.BG0CNT = 0x008;
	this.BG1CNT = 0x00A;
	this.BG2CNT = 0x00C;
	this.BG3CNT = 0x00E;
	this.BG0HOFS = 0x010;
	this.BG0VOFS = 0x012;
	this.BG1HOFS = 0x014;
	this.BG1VOFS = 0x016;
	this.BG2HOFS = 0x018;
	this.BG2VOFS = 0x01A;
	this.BG3HOFS = 0x01C;
	this.BG3VOFS = 0x01E;
	this.BG2PA = 0x020;
	this.BG2PB = 0x022;
	this.BG2PC = 0x024;
	this.BG2PD = 0x026;
	this.BG2X_LO = 0x028;
	this.BG2X_HI = 0x02E;
	this.BG2Y_LO = 0x02C;
	this.BG2Y_HI = 0x02E;
	this.BG3PA = 0x030;
	this.BG3PB = 0x032;
	this.BG3PC = 0x034;
	this.BG3PD = 0x036;
	this.BG3X_LO = 0x038;
	this.BG3X_HI = 0x03A;
	this.BG3Y_LO = 0x03C;
	this.BG3Y_HI = 0x03E;
	this.WIN0H = 0x040;
	this.WIN1H = 0x042;
	this.WIN0V = 0x044;
	this.WIN1V = 0x046;
	this.WININ = 0x048;
	this.WINOUT = 0x04A;
	this.MOSAIC = 0x04C;
	this.BLDCNT = 0x050;
	this.BLDALPHA = 0x052;
	this.BLDY = 0x054;

	// Sound
	this.SOUND1CNT_LO = 0x060;
	this.SOUND1CNT_HI = 0x062;
	this.SOUND1CNT_X = 0x064;
	this.SOUND2CNT_LO = 0x068;
	this.SOUND2CNT_HI = 0x06C;
	this.SOUND3CNT_LO = 0x070;
	this.SOUND3CNT_HI = 0x072;
	this.SOUND3CNT_X = 0x074;
	this.SOUND4CNT_LO = 0x078;
	this.SOUND4CNT_HI = 0x07C;
	this.SOUNDCNT_L0 = 0x080;
	this.SOUNDCNT_HI = 0x082;
	this.SOUNDCNT_X = 0x084;
	this.SOUNDBIAS = 0x088;
	this.FIFO_A_LO = 0x0A0;
	this.FIFO_A_HI = 0x0A2;
	this.FIFO_B_LO = 0x0A4;
	this.FIFO_B_HI = 0x0A6;

	// DMA
	this.DMA0SAD_LO = 0x0B0;
	this.DMA0SAD_HI = 0x0B2;
	this.DMA0DAD_LO = 0x0B4;
	this.DMA0DAD_HI = 0x0B6;
	this.DMA0CNT_LO = 0x0B8;
	this.DMA0CNT_HI = 0x0BA;
	this.DMA1SAD_LO = 0x0BC;
	this.DMA1SAD_HI = 0x0BE;
	this.DMA1DAD_LO = 0x0C0;
	this.DMA1DAD_HI = 0x0C2;
	this.DMA1CNT_LO = 0x0C4;
	this.DMA1CNT_HI = 0x0C6;
	this.DMA2SAD_LO = 0x0C8;
	this.DMA2SAD_HI = 0x0CA;
	this.DMA2DAD_LO = 0x0CC;
	this.DMA2DAD_HI = 0x0CE;
	this.DMA2CNT_LO = 0x0D0;
	this.DMA2CNT_HI = 0x0D2;
	this.DMA3SAD_LO = 0x0D4;
	this.DMA3SAD_HI = 0x0D6;
	this.DMA3DAD_LO = 0x0D8;
	this.DMA3DAD_HI = 0x0DA;
	this.DMA3CNT_LO = 0x0DC;
	this.DMA3CNT_HI = 0x0DE;

	// Timers
	this.TM0CNT_LO = 0x100;
	this.TM0CNT_HI = 0x102;
	this.TM1CNT_LO = 0x104;
	this.TM1CNT_HI = 0x106;
	this.TM2CNT_LO = 0x108;
	this.TM2CNT_HI = 0x10A;
	this.TM3CNT_LO = 0x10C;
	this.TM3CNT_HI = 0x10E;

	// Keypad
	this.KEYINPUT = 0x130;
	this.KEYCNT = 0x132;

	// Interrupts, etc
	this.IE = 0x200;
	this.IF = 0x202;
	this.WAITCNT = 0x204;
	this.IME = 0x208;
};

GameBoyAdvanceIO.prototype.setCPU = function(cpu) {
	this.cpu = cpu;
};

GameBoyAdvanceIO.prototype.setVideo = function(video) {
	this.video = video;
};

GameBoyAdvanceIO.prototype.clear = function() {
	this.registers = new Uint16Array(this.cpu.mmu.SIZE_IO);
};

GameBoyAdvanceIO.prototype.load8 = function(offset) {
	throw "Unimplmeneted unaligned I/O access";
}

GameBoyAdvanceIO.prototype.load16 = function(offset) {
	return this.loadU16(offset) >> 0;
}

GameBoyAdvanceIO.prototype.load32 = function(offset) {
	switch (offset) {
	case this.DMA0CNT_LO:
	case this.DMA1CNT_LO:
	case this.DMA2CNT_LO:
	case this.DMA3CNT_LO:
		return this.loadU16(offset | 2) << 16;
	}

	return this.loadU16(offset) | (this.loadU16(offset | 2) << 16);
};

GameBoyAdvanceIO.prototype.loadU8 = function(offset) {
	var odd = offset & 0x0001;
	var value = this.loadU16(offset & 0xFFFE);
	return (value >>> (odd << 3)) & 0xFF;
}

GameBoyAdvanceIO.prototype.loadU16 = function(offset) {
	switch (offset) {
	case this.DISPCNT:
	case this.WAITCNT:
	case this.IME:
		// Handled transparently by the written registers
		break;
	case this.DISPSTAT:
		return this.registers[offset >> 1] | this.video.readDisplayStat();
	case this.DMA0CNT_HI:
	case this.DMA1CNT_HI:
	case this.DMA2CNT_HI:
	case this.DMA3CNT_HI:
		break;
	default:
		throw "Unimplemented I/O register read: 0x" + offset.toString(16);
	}
	return this.registers[offset >> 1];
};

GameBoyAdvanceIO.prototype.store16 = function(offset, value) {
	switch (offset) {
	// Video
	case this.DISPCNT:
		this.video.writeDisplayControl(value);
		break;
	case this.DISPSTAT:
		value &= this.video.DISPSTAT_MASK;
		this.video.writeDisplayStat(value);
		break;

	// Sound
	// TODO: implement sound
	case this.SOUNDCNT_LO:
		value &= 0xFF77;
		break;
	case this.SOUNDCNT_HI:
		value &= 0xFF0F;
		break;
	case this.SOUNDCNT_X:
		value &= 0x0080;
		break;

	// DMA
	case this.DMA0CNT_LO:
		this.cpu.irq.dmaSetWordCount(0, value);
		return;
	case this.DMA0CNT_HI:
		// The DMA registers need to set the values before writing the control, as writing the
		// control can synchronously trigger a DMA transfer
		this.registers[offset >> 1] = value & 0xFFE0;
		this.cpu.irq.dmaWriteControl(0, value);
		break;
	case this.DMA1CNT_LO:
		this.cpu.irq.dmaSetWordCount(1, value);
		return;
	case this.DMA1CNT_HI:
		this.registers[offset >> 1] = value & 0xFFE0;
		this.cpu.irq.dmaWriteControl(1, value);
		break;
	case this.DMA2CNT_LO:
		this.cpu.irq.dmaSetWordCount(2, value);
		return;
	case this.DMA2CNT_HI:
		this.registers[offset >> 1] = value & 0xFFE0;
		this.cpu.irq.dmaWriteControl(2, value);
		break;
	case this.DMA3CNT_LO:
		this.cpu.irq.dmaSetWordCount(3, value);
		return;
	case this.DMA3CNT_HI:
		this.registers[offset >> 1] = value & 0xFFE0;
		this.cpu.irq.dmaWriteControl(3, value);
		return;

	// Misc
	case this.WAITCNT:
		// TODO: implement this
		value &= 0x5FFF;
		break;
	case this.IME:
		value &= 0x0001;
		this.cpu.irq.masterEnable(value);
		break;
	default:
		throw "Unimplemented I/O register write: 0x" + offset.toString(16);
	}
	this.registers[offset >> 1] = value;
};

GameBoyAdvanceIO.prototype.store32 = function(offset, value) {
	switch (offset) {
	case this.DMA0SAD_LO:
		this.cpu.irq.dmaSetSourceAddress(0, value);
		return;
	case this.DMA0DAD_LO:
		this.cpu.irq.dmaSetDestAddress(0, value);
		return;
	case this.DMA1SAD_LO:
		this.cpu.irq.dmaSetSourceAddress(1, value);
		return;
	case this.DMA1DAD_LO:
		this.cpu.irq.dmaSetDestAddress(1, value);
		return;
	case this.DMA2SAD_LO:
		this.cpu.irq.dmaSetSourceAddress(2, value);
		return;
	case this.DMA2DAD_LO:
		this.cpu.irq.dmaSetDestAddress(2, value);
		return;
	case this.DMA3SAD_LO:
		this.cpu.irq.dmaSetSourceAddress(3, value);
		return;
	case this.DMA3DAD_LO:
		this.cpu.irq.dmaSetDestAddress(3, value);
		return;
	}

	this.store16(offset, value & 0xFFFF);
	this.store16(offset + 2, value >> 16);
};
<|endoftext|>


<commit_before>class Preload extends Phaser.State {

	preload() {
		// Background Environment Assets
		this.game.load.image('mountains-back', 'assets/mountains-back.png');
		this.game.load.image('hills-mid1', 'assets/hills-mid1.png');
		this.game.load.image('fence-mid2', 'assets/fence-mid2.png');
		this.game.load.image('menu-background', 'assets/corn.png');
		this.game.load.image('ground-front', 'assets/ground-front.png');

		// Menu Assets
		this.game.load.image('cm-title', 'assets/cm-title-darksub.png')
		this.game.load.image('restart', 'assets/restart-button.png');
		this.game.load.image('main-menu', 'assets/menu-button.png');
		this.game.load.image('start-game', 'assets/start-button.png');
		this.game.load.image('stop-game', 'assets/stop-button.png');
		this.game.load.image('send', 'assets/send.png');
		this.game.load.image('how-to', 'assets/how-to.png');
		this.game.load.image('go-back', 'assets/go-back.png');
		this.game.load.spritesheet('instruction', 'assets/instruction.png', 2400, 1800);

		// Player Assets
		this.game.load.spritesheet('cornman', 'assets/cornman2.png', 145, 204);

		// Pixel Obstacle Assets
		this.game.load.spritesheet('tractor', 'assets/tractor.png', 294, 284);
		this.game.load.spritesheet('weed', 'assets/Weeds.png', 160, 160);
		this.game.load.spritesheet('cow', 'assets/cow.png', 255, 255);

		// Pixel Neutral Assets
		this.game.load.image('coin', 'assets/corn-coin.png');
		this.game.load.spritesheet('cloud-ani', 'assets/Cloud-Sheet.png', 559, 200);
		this.game.load.spritesheet('golden-corn', 'assets/golden-coin.png', 140, 140);

		// Pixel Weapon Assets
		this.game.load.spritesheet('bullet', 'assets/bullet.png', 62, 32);
		this.game.load.image('popcorn', 'assets/popcorn.png');

		// Sound & Music Assets
		this.game.load.audio('banjo', 'assets/banjo-music.mp3')

		// Unused Assets
		this.game.load.image('sky', 'assets/sky.png');
		this.game.load.image('rock', 'assets/rock.gif');
		this.game.load.image('blank', 'assets/blankbutton.png');
		this.game.load.image('blank', 'assets/blankbutton.png');
	}

	create() {
		this.game.state.start("Menu");
	}
}

export default Preload;
<commit_msg>fix cloudsheet<commit_after>class Preload extends Phaser.State {

	preload() {
		// Background Environment Assets
		this.game.load.image('mountains-back', 'assets/mountains-back.png');
		this.game.load.image('hills-mid1', 'assets/hills-mid1.png');
		this.game.load.image('fence-mid2', 'assets/fence-mid2.png');
		this.game.load.image('menu-background', 'assets/corn.png');
		this.game.load.image('ground-front', 'assets/ground-front.png');

		// Menu Assets
		this.game.load.image('cm-title', 'assets/cm-title-darksub.png')
		this.game.load.image('restart', 'assets/restart-button.png');
		this.game.load.image('main-menu', 'assets/menu-button.png');
		this.game.load.image('start-game', 'assets/start-button.png');
		this.game.load.image('stop-game', 'assets/stop-button.png');
		this.game.load.image('send', 'assets/send.png');
		this.game.load.image('how-to', 'assets/how-to.png');
		this.game.load.image('go-back', 'assets/go-back.png');
		this.game.load.spritesheet('instruction', 'assets/instruction.png', 2400, 1800);

		// Player Assets
		this.game.load.spritesheet('cornman', 'assets/cornman2.png', 145, 204);

		// Pixel Obstacle Assets
		this.game.load.spritesheet('tractor', 'assets/tractor.png', 294, 284);
		this.game.load.spritesheet('weed', 'assets/Weeds.png', 160, 160);
		this.game.load.spritesheet('cow', 'assets/cow.png', 255, 255);

		// Pixel Neutral Assets
		this.game.load.image('coin', 'assets/corn-coin.png');
		this.game.load.spritesheet('cloud-ani', 'assets/cloud-Sheet.png', 559, 200);
		this.game.load.spritesheet('golden-corn', 'assets/golden-coin.png', 140, 140);

		// Pixel Weapon Assets
		this.game.load.spritesheet('bullet', 'assets/bullet.png', 62, 32);
		this.game.load.image('popcorn', 'assets/popcorn.png');

		// Sound & Music Assets
		this.game.load.audio('banjo', 'assets/banjo-music.mp3')

		// Unused Assets
		this.game.load.image('sky', 'assets/sky.png');
		this.game.load.image('rock', 'assets/rock.gif');
		this.game.load.image('blank', 'assets/blankbutton.png');
		this.game.load.image('blank', 'assets/blankbutton.png');
	}

	create() {
		this.game.state.start("Menu");
	}
}

export default Preload;
<|endoftext|>


<commit_before>GameBoyAdvanceIO = function() {
	// Video
	this.DISPCNT = 0x000;
	this.GREENSWP = 0x002;
	this.DISPSTAT = 0x004;
	this.VCOUNT = 0x006;
	this.BG0CNT = 0x008;
	this.BG1CNT = 0x00A;
	this.BG2CNT = 0x00C;
	this.BG3CNT = 0x00E;
	this.BG0HOFS = 0x010;
	this.BG0VOFS = 0x012;
	this.BG1HOFS = 0x014;
	this.BG1VOFS = 0x016;
	this.BG2HOFS = 0x018;
	this.BG2VOFS = 0x01A;
	this.BG3HOFS = 0x01C;
	this.BG3VOFS = 0x01E;
	this.BG2PA = 0x020;
	this.BG2PB = 0x022;
	this.BG2PC = 0x024;
	this.BG2PD = 0x026;
	this.BG2X_LO = 0x028;
	this.BG2X_HI = 0x02E;
	this.BG2Y_LO = 0x02C;
	this.BG2Y_HI = 0x02E;
	this.BG3PA = 0x030;
	this.BG3PB = 0x032;
	this.BG3PC = 0x034;
	this.BG3PD = 0x036;
	this.BG3X_LO = 0x038;
	this.BG3X_HI = 0x03A;
	this.BG3Y_LO = 0x03C;
	this.BG3Y_HI = 0x03E;
	this.WIN0H = 0x040;
	this.WIN1H = 0x042;
	this.WIN0V = 0x044;
	this.WIN1V = 0x046;
	this.WININ = 0x048;
	this.WINOUT = 0x04A;
	this.MOSAIC = 0x04C;
	this.BLDCNT = 0x050;
	this.BLDALPHA = 0x052;
	this.BLDY = 0x054;

	// Sound
	this.SOUND1CNT_LO = 0x060;
	this.SOUND1CNT_HI = 0x062;
	this.SOUND1CNT_X = 0x064;
	this.SOUND2CNT_LO = 0x068;
	this.SOUND2CNT_HI = 0x06C;
	this.SOUND3CNT_LO = 0x070;
	this.SOUND3CNT_HI = 0x072;
	this.SOUND3CNT_X = 0x074;
	this.SOUND4CNT_LO = 0x078;
	this.SOUND4CNT_HI = 0x07C;
	this.SOUNDCNT_LO = 0x080;
	this.SOUNDCNT_HI = 0x082;
	this.SOUNDCNT_X = 0x084;
	this.SOUNDBIAS = 0x088;
	this.FIFO_A_LO = 0x0A0;
	this.FIFO_A_HI = 0x0A2;
	this.FIFO_B_LO = 0x0A4;
	this.FIFO_B_HI = 0x0A6;

	// DMA
	this.DMA0SAD_LO = 0x0B0;
	this.DMA0SAD_HI = 0x0B2;
	this.DMA0DAD_LO = 0x0B4;
	this.DMA0DAD_HI = 0x0B6;
	this.DMA0CNT_LO = 0x0B8;
	this.DMA0CNT_HI = 0x0BA;
	this.DMA1SAD_LO = 0x0BC;
	this.DMA1SAD_HI = 0x0BE;
	this.DMA1DAD_LO = 0x0C0;
	this.DMA1DAD_HI = 0x0C2;
	this.DMA1CNT_LO = 0x0C4;
	this.DMA1CNT_HI = 0x0C6;
	this.DMA2SAD_LO = 0x0C8;
	this.DMA2SAD_HI = 0x0CA;
	this.DMA2DAD_LO = 0x0CC;
	this.DMA2DAD_HI = 0x0CE;
	this.DMA2CNT_LO = 0x0D0;
	this.DMA2CNT_HI = 0x0D2;
	this.DMA3SAD_LO = 0x0D4;
	this.DMA3SAD_HI = 0x0D6;
	this.DMA3DAD_LO = 0x0D8;
	this.DMA3DAD_HI = 0x0DA;
	this.DMA3CNT_LO = 0x0DC;
	this.DMA3CNT_HI = 0x0DE;

	// Timers
	this.TM0CNT_LO = 0x100;
	this.TM0CNT_HI = 0x102;
	this.TM1CNT_LO = 0x104;
	this.TM1CNT_HI = 0x106;
	this.TM2CNT_LO = 0x108;
	this.TM2CNT_HI = 0x10A;
	this.TM3CNT_LO = 0x10C;
	this.TM3CNT_HI = 0x10E;

	// Keypad
	this.KEYINPUT = 0x130;
	this.KEYCNT = 0x132;

	// Interrupts, etc
	this.IE = 0x200;
	this.IF = 0x202;
	this.WAITCNT = 0x204;
	this.IME = 0x208;

	this.DEFAULT_SOUNDBIAS = 0x200;
};

GameBoyAdvanceIO.prototype.setCPU = function(cpu) {
	this.cpu = cpu;
};

GameBoyAdvanceIO.prototype.setVideo = function(video) {
	this.video = video;
};

GameBoyAdvanceIO.prototype.clear = function() {
	this.registers = new Uint16Array(this.cpu.mmu.SIZE_IO);

	this.registers[this.SOUNDBIAS >> 1] = this.DEFAULT_SOUNDBIAS;
};

GameBoyAdvanceIO.prototype.load8 = function(offset) {
	throw "Unimplmeneted unaligned I/O access";
}

GameBoyAdvanceIO.prototype.load16 = function(offset) {
	return this.loadU16(offset) >> 0;
}

GameBoyAdvanceIO.prototype.load32 = function(offset) {
	switch (offset) {
	case this.DMA0CNT_LO:
	case this.DMA1CNT_LO:
	case this.DMA2CNT_LO:
	case this.DMA3CNT_LO:
		return this.loadU16(offset | 2) << 16;
	}

	return this.loadU16(offset) | (this.loadU16(offset | 2) << 16);
};

GameBoyAdvanceIO.prototype.loadU8 = function(offset) {
	var odd = offset & 0x0001;
	var value = this.loadU16(offset & 0xFFFE);
	return (value >>> (odd << 3)) & 0xFF;
}

GameBoyAdvanceIO.prototype.loadU16 = function(offset) {
	switch (offset) {
	case this.DISPCNT:
	case this.SOUNDBIAS:
	case this.WAITCNT:
	case this.IE:
	case this.IME:
		// Handled transparently by the written registers
		break;
	case this.DISPSTAT:
		return this.registers[offset >> 1] | this.video.readDisplayStat();
	case this.DMA0CNT_HI:
	case this.DMA1CNT_HI:
	case this.DMA2CNT_HI:
	case this.DMA3CNT_HI:
		break;
	default:
		throw "Unimplemented I/O register read: 0x" + offset.toString(16);
	}
	return this.registers[offset >> 1];
};

GameBoyAdvanceIO.prototype.store8 = function(offset, value) {
	switch (offset) {
	case this.SOUND1CNT_HI | 1:
	case this.SOUND2CNT_LO | 1:
	case this.SOUND3CNT_HI:
	case this.SOUND4CNT_LO | 1:
		break;
	case this.SOUND1CNT_X | 1:
	case this.SOUND2CNT_HI | 1:
		value &= 0xC7;
		break;
	case this.SOUND1CNT_LO:
		value &= 0x7F;
		break;
	case this.SOUND3CNT_LO:
	case this.SOUND3CNT_HI | 1:
		value &= 0xE0;
		break;
	case this.SOUND4CNT_HI | 1:
		value &= 0xC0;
		break;
	case this.SOUNDCNT_LO:
		value &= 0x77;
		break;
	case this.SOUNDCNT_X:
		value &= 0x80;
		break;
	case this.SOUNDBIAS | 1:
		value &= 0xC3;
		break;
	default:
		throw "Unimplemented 8-bit I/O register write: 0x" + offset.toString(16);
	}

	if (offset & 1) {
		value <<= 8;
		value |= (this.registers[offset >> 1] & 0x00FF);
	}
	this.registers[offset >> 1] = value;
};

GameBoyAdvanceIO.prototype.store16 = function(offset, value) {
	switch (offset) {
	// Video
	case this.DISPCNT:
		this.video.writeDisplayControl(value);
		break;
	case this.DISPSTAT:
		value &= this.video.DISPSTAT_MASK;
		this.video.writeDisplayStat(value);
		break;

	// Sound
	// TODO: implement sound
	case this.SOUNDCNT_LO:
		value &= 0xFF77;
		break;
	case this.SOUNDCNT_HI:
		value &= 0xFF0F;
		break;
	case this.SOUNDCNT_X:
		value &= 0x0080;
		break;

	// DMA
	case this.DMA0CNT_LO:
		this.cpu.irq.dmaSetWordCount(0, value);
		//return;
		break;
	case this.DMA0CNT_HI:
		// The DMA registers need to set the values before writing the control, as writing the
		// control can synchronously trigger a DMA transfer
		this.registers[offset >> 1] = value & 0xFFE0;
		this.cpu.irq.dmaWriteControl(0, value);
		break;
	case this.DMA1CNT_LO:
		this.cpu.irq.dmaSetWordCount(1, value);
		//return;
		break;
	case this.DMA1CNT_HI:
		this.registers[offset >> 1] = value & 0xFFE0;
		this.cpu.irq.dmaWriteControl(1, value);
		break;
	case this.DMA2CNT_LO:
		this.cpu.irq.dmaSetWordCount(2, value);
		//return;
		break;
	case this.DMA2CNT_HI:
		this.registers[offset >> 1] = value & 0xFFE0;
		this.cpu.irq.dmaWriteControl(2, value);
		break;
	case this.DMA3CNT_LO:
		this.cpu.irq.dmaSetWordCount(3, value);
		//return;
		break;
	case this.DMA3CNT_HI:
		this.registers[offset >> 1] = value & 0xFFE0;
		this.cpu.irq.dmaWriteControl(3, value);
		return;

	// Misc
	case this.IE:
		value &= 0x3FFF;
		this.cpu.irq.setInterruptsEnabled(value);
		break;
	case this.WAITCNT:
		// TODO: implement this
		value &= 0x5FFF;
		break;
	case this.IME:
		value &= 0x0001;
		this.cpu.irq.masterEnable(value);
		break;
	default:
		throw "Unimplemented I/O register write: 0x" + offset.toString(16);
	}
	this.registers[offset >> 1] = value;
};

GameBoyAdvanceIO.prototype.store32 = function(offset, value) {
	switch (offset) {
	case this.DMA0SAD_LO:
		this.cpu.irq.dmaSetSourceAddress(0, value);
		return;
	case this.DMA0DAD_LO:
		this.cpu.irq.dmaSetDestAddress(0, value);
		return;
	case this.DMA1SAD_LO:
		this.cpu.irq.dmaSetSourceAddress(1, value);
		return;
	case this.DMA1DAD_LO:
		this.cpu.irq.dmaSetDestAddress(1, value);
		return;
	case this.DMA2SAD_LO:
		this.cpu.irq.dmaSetSourceAddress(2, value);
		return;
	case this.DMA2DAD_LO:
		this.cpu.irq.dmaSetDestAddress(2, value);
		return;
	case this.DMA3SAD_LO:
		this.cpu.irq.dmaSetSourceAddress(3, value);
		return;
	case this.DMA3DAD_LO:
		this.cpu.irq.dmaSetDestAddress(3, value);
		return;
	}

	this.store16(offset, value & 0xFFFF);
	this.store16(offset + 2, value >> 16);
};
<commit_msg>Cleanup DMA registers<commit_after>GameBoyAdvanceIO = function() {
	// Video
	this.DISPCNT = 0x000;
	this.GREENSWP = 0x002;
	this.DISPSTAT = 0x004;
	this.VCOUNT = 0x006;
	this.BG0CNT = 0x008;
	this.BG1CNT = 0x00A;
	this.BG2CNT = 0x00C;
	this.BG3CNT = 0x00E;
	this.BG0HOFS = 0x010;
	this.BG0VOFS = 0x012;
	this.BG1HOFS = 0x014;
	this.BG1VOFS = 0x016;
	this.BG2HOFS = 0x018;
	this.BG2VOFS = 0x01A;
	this.BG3HOFS = 0x01C;
	this.BG3VOFS = 0x01E;
	this.BG2PA = 0x020;
	this.BG2PB = 0x022;
	this.BG2PC = 0x024;
	this.BG2PD = 0x026;
	this.BG2X_LO = 0x028;
	this.BG2X_HI = 0x02E;
	this.BG2Y_LO = 0x02C;
	this.BG2Y_HI = 0x02E;
	this.BG3PA = 0x030;
	this.BG3PB = 0x032;
	this.BG3PC = 0x034;
	this.BG3PD = 0x036;
	this.BG3X_LO = 0x038;
	this.BG3X_HI = 0x03A;
	this.BG3Y_LO = 0x03C;
	this.BG3Y_HI = 0x03E;
	this.WIN0H = 0x040;
	this.WIN1H = 0x042;
	this.WIN0V = 0x044;
	this.WIN1V = 0x046;
	this.WININ = 0x048;
	this.WINOUT = 0x04A;
	this.MOSAIC = 0x04C;
	this.BLDCNT = 0x050;
	this.BLDALPHA = 0x052;
	this.BLDY = 0x054;

	// Sound
	this.SOUND1CNT_LO = 0x060;
	this.SOUND1CNT_HI = 0x062;
	this.SOUND1CNT_X = 0x064;
	this.SOUND2CNT_LO = 0x068;
	this.SOUND2CNT_HI = 0x06C;
	this.SOUND3CNT_LO = 0x070;
	this.SOUND3CNT_HI = 0x072;
	this.SOUND3CNT_X = 0x074;
	this.SOUND4CNT_LO = 0x078;
	this.SOUND4CNT_HI = 0x07C;
	this.SOUNDCNT_LO = 0x080;
	this.SOUNDCNT_HI = 0x082;
	this.SOUNDCNT_X = 0x084;
	this.SOUNDBIAS = 0x088;
	this.FIFO_A_LO = 0x0A0;
	this.FIFO_A_HI = 0x0A2;
	this.FIFO_B_LO = 0x0A4;
	this.FIFO_B_HI = 0x0A6;

	// DMA
	this.DMA0SAD_LO = 0x0B0;
	this.DMA0SAD_HI = 0x0B2;
	this.DMA0DAD_LO = 0x0B4;
	this.DMA0DAD_HI = 0x0B6;
	this.DMA0CNT_LO = 0x0B8;
	this.DMA0CNT_HI = 0x0BA;
	this.DMA1SAD_LO = 0x0BC;
	this.DMA1SAD_HI = 0x0BE;
	this.DMA1DAD_LO = 0x0C0;
	this.DMA1DAD_HI = 0x0C2;
	this.DMA1CNT_LO = 0x0C4;
	this.DMA1CNT_HI = 0x0C6;
	this.DMA2SAD_LO = 0x0C8;
	this.DMA2SAD_HI = 0x0CA;
	this.DMA2DAD_LO = 0x0CC;
	this.DMA2DAD_HI = 0x0CE;
	this.DMA2CNT_LO = 0x0D0;
	this.DMA2CNT_HI = 0x0D2;
	this.DMA3SAD_LO = 0x0D4;
	this.DMA3SAD_HI = 0x0D6;
	this.DMA3DAD_LO = 0x0D8;
	this.DMA3DAD_HI = 0x0DA;
	this.DMA3CNT_LO = 0x0DC;
	this.DMA3CNT_HI = 0x0DE;

	// Timers
	this.TM0CNT_LO = 0x100;
	this.TM0CNT_HI = 0x102;
	this.TM1CNT_LO = 0x104;
	this.TM1CNT_HI = 0x106;
	this.TM2CNT_LO = 0x108;
	this.TM2CNT_HI = 0x10A;
	this.TM3CNT_LO = 0x10C;
	this.TM3CNT_HI = 0x10E;

	// Keypad
	this.KEYINPUT = 0x130;
	this.KEYCNT = 0x132;

	// Interrupts, etc
	this.IE = 0x200;
	this.IF = 0x202;
	this.WAITCNT = 0x204;
	this.IME = 0x208;

	this.DEFAULT_SOUNDBIAS = 0x200;
};

GameBoyAdvanceIO.prototype.setCPU = function(cpu) {
	this.cpu = cpu;
};

GameBoyAdvanceIO.prototype.setVideo = function(video) {
	this.video = video;
};

GameBoyAdvanceIO.prototype.clear = function() {
	this.registers = new Uint16Array(this.cpu.mmu.SIZE_IO);

	this.registers[this.SOUNDBIAS >> 1] = this.DEFAULT_SOUNDBIAS;
};

GameBoyAdvanceIO.prototype.load8 = function(offset) {
	throw "Unimplmeneted unaligned I/O access";
}

GameBoyAdvanceIO.prototype.load16 = function(offset) {
	return this.loadU16(offset) >> 0;
}

GameBoyAdvanceIO.prototype.load32 = function(offset) {
	switch (offset) {
	case this.DMA0CNT_LO:
	case this.DMA1CNT_LO:
	case this.DMA2CNT_LO:
	case this.DMA3CNT_LO:
		return this.loadU16(offset | 2) << 16;
	}

	return this.loadU16(offset) | (this.loadU16(offset | 2) << 16);
};

GameBoyAdvanceIO.prototype.loadU8 = function(offset) {
	var odd = offset & 0x0001;
	var value = this.loadU16(offset & 0xFFFE);
	return (value >>> (odd << 3)) & 0xFF;
}

GameBoyAdvanceIO.prototype.loadU16 = function(offset) {
	switch (offset) {
	case this.DISPCNT:
	case this.SOUNDBIAS:
	case this.WAITCNT:
	case this.IE:
	case this.IME:
		// Handled transparently by the written registers
		break;
	case this.DISPSTAT:
		return this.registers[offset >> 1] | this.video.readDisplayStat();
	case this.DMA0CNT_HI:
	case this.DMA1CNT_HI:
	case this.DMA2CNT_HI:
	case this.DMA3CNT_HI:
		break;
	default:
		throw "Unimplemented I/O register read: 0x" + offset.toString(16);
	}
	return this.registers[offset >> 1];
};

GameBoyAdvanceIO.prototype.store8 = function(offset, value) {
	switch (offset) {
	case this.SOUND1CNT_HI | 1:
	case this.SOUND2CNT_LO | 1:
	case this.SOUND3CNT_HI:
	case this.SOUND4CNT_LO | 1:
		break;
	case this.SOUND1CNT_X | 1:
	case this.SOUND2CNT_HI | 1:
		value &= 0xC7;
		break;
	case this.SOUND1CNT_LO:
		value &= 0x7F;
		break;
	case this.SOUND3CNT_LO:
	case this.SOUND3CNT_HI | 1:
		value &= 0xE0;
		break;
	case this.SOUND4CNT_HI | 1:
		value &= 0xC0;
		break;
	case this.SOUNDCNT_LO:
		value &= 0x77;
		break;
	case this.SOUNDCNT_X:
		value &= 0x80;
		break;
	case this.SOUNDBIAS | 1:
		value &= 0xC3;
		break;
	default:
		throw "Unimplemented 8-bit I/O register write: 0x" + offset.toString(16);
	}

	if (offset & 1) {
		value <<= 8;
		value |= (this.registers[offset >> 1] & 0x00FF);
	}
	this.registers[offset >> 1] = value;
};

GameBoyAdvanceIO.prototype.store16 = function(offset, value) {
	switch (offset) {
	// Video
	case this.DISPCNT:
		this.video.writeDisplayControl(value);
		break;
	case this.DISPSTAT:
		value &= this.video.DISPSTAT_MASK;
		this.video.writeDisplayStat(value);
		break;

	// Sound
	// TODO: implement sound
	case this.SOUNDCNT_LO:
		value &= 0xFF77;
		break;
	case this.SOUNDCNT_HI:
		value &= 0xFF0F;
		break;
	case this.SOUNDCNT_X:
		value &= 0x0080;
		break;

	// DMA
	case this.DMA0CNT_LO:
		this.cpu.irq.dmaSetWordCount(0, value);
		break;
	case this.DMA0CNT_HI:
		// The DMA registers need to set the values before writing the control, as writing the
		// control can synchronously trigger a DMA transfer
		this.registers[offset >> 1] = value & 0xFFE0;
		this.cpu.irq.dmaWriteControl(0, value);
		return;
	case this.DMA1CNT_LO:
		this.cpu.irq.dmaSetWordCount(1, value);
		break;
	case this.DMA1CNT_HI:
		this.registers[offset >> 1] = value & 0xFFE0;
		this.cpu.irq.dmaWriteControl(1, value);
		return;
	case this.DMA2CNT_LO:
		this.cpu.irq.dmaSetWordCount(2, value);
		break;
	case this.DMA2CNT_HI:
		this.registers[offset >> 1] = value & 0xFFE0;
		this.cpu.irq.dmaWriteControl(2, value);
		return;
	case this.DMA3CNT_LO:
		this.cpu.irq.dmaSetWordCount(3, value);
		break;
	case this.DMA3CNT_HI:
		this.registers[offset >> 1] = value & 0xFFE0;
		this.cpu.irq.dmaWriteControl(3, value);
		return;

	// Misc
	case this.IE:
		value &= 0x3FFF;
		this.cpu.irq.setInterruptsEnabled(value);
		break;
	case this.WAITCNT:
		// TODO: implement this
		value &= 0x5FFF;
		break;
	case this.IME:
		value &= 0x0001;
		this.cpu.irq.masterEnable(value);
		break;
	default:
		throw "Unimplemented I/O register write: 0x" + offset.toString(16);
	}
	this.registers[offset >> 1] = value;
};

GameBoyAdvanceIO.prototype.store32 = function(offset, value) {
	switch (offset) {
	case this.DMA0SAD_LO:
		this.cpu.irq.dmaSetSourceAddress(0, value);
		break;
	case this.DMA0DAD_LO:
		this.cpu.irq.dmaSetDestAddress(0, value);
		break;
	case this.DMA1SAD_LO:
		this.cpu.irq.dmaSetSourceAddress(1, value);
		break;
	case this.DMA1DAD_LO:
		this.cpu.irq.dmaSetDestAddress(1, value);
		break;
	case this.DMA2SAD_LO:
		this.cpu.irq.dmaSetSourceAddress(2, value);
		break;
	case this.DMA2DAD_LO:
		this.cpu.irq.dmaSetDestAddress(2, value);
		break;
	case this.DMA3SAD_LO:
		this.cpu.irq.dmaSetSourceAddress(3, value);
		break;
	case this.DMA3DAD_LO:
		this.cpu.irq.dmaSetDestAddress(3, value);
		break;
	default:
		this.store16(offset, value & 0xFFFF);
		this.store16(offset | 2, value >>> 16);
		return;
	}

	this.registers[offset >> 1] = value & 0xFFFF;
	this.registers[(offset >> 1) + 1] = value >>> 16;
};
<|endoftext|>


<commit_before>    $(function() {
        // render the chart
        var mainChart = new Morris.Area({
            element: 'dashboard-chart--audience',
            lineWidth: 1,
            lineColors: [ '#8ac9e1','#ce77b6', '#ee9c27', '#d13f37'],
            fillOpacity: '.9',
            hideHover: 'auto',
            pointSize: 0,
            data: [],
            xkey: 'timestamp',
            ykeys: ['pageviews', 'sessions', 'users','newusers'],
            labels: ['Pageviews', 'Sessions', 'Users', 'New Sessions'],
            behaveLikeLine: true,
            gridTextColor: '#a7a7a7',
            smooth: true
        });

        // show first tab
        var tab = $('.dashboard-tabs__item:nth-child(2) > div');

        function switchTab(id, url) {
            $('#data_overview').addClass('dashboard__content--loading');
            $('.dashboard-tabs__item').removeClass('dashboard-tabs__item--active');
            $('#tab'+id).addClass('dashboard-tabs__item--active');

            $.ajax({
                type: 'get',
                url: url,
                cache: false,
                success: function(data) {
                    if (data.overview.sessions === 0) {
                        $('#data_no_overview').css('display', 'block');
                        $('#data_overview').css('display', 'none');
                    } else {
                        $('#data_no_overview').css('display', 'none');
                        $('#data_overview').css('display', 'block');
                        $('#data_overview').removeClass('dashboard__content--loading');

                        mainChart.setData(data.overview.chartData);
                        mainChart.ymax = data.overview.chartDataMaxValue;
                        setMetrics(data);
                        setGoals(data);
                    }
                }
            });
        }

        switchTab(tab.attr('data-id'), tab.attr('data-path'));

        // Tab switcher
        $('.dashboard-tabs__item').on('click', function(){
            var id = $(this).find('.dashboard-tabs__controller').attr('data-id');
            var url = $(this).find('.dashboard-tabs__controller').attr('data-path');
            switchTab(id, url);
        });
    });

<commit_msg>Fix chart height<commit_after>    $(function() {
        // show first tab
        var tab = $('.dashboard-tabs__item:nth-child(2) > div');

        function switchTab(id, url) {
            $('#data_overview').addClass('dashboard__content--loading');
            $('.dashboard-tabs__item').removeClass('dashboard-tabs__item--active');
            $('#tab'+id).addClass('dashboard-tabs__item--active');

            $.ajax({
                type: 'get',
                url: url,
                cache: false,
                success: function(data) {
                    if (data.overview.sessions === 0) {
                        $('#data_no_overview').css('display', 'block');
                        $('#data_overview').css('display', 'none');
                    } else {
                        $('#data_no_overview').css('display', 'none');
                        $('#data_overview').css('display', 'block');
                        $('#data_overview').removeClass('dashboard__content--loading');

                        $("#dashboard-chart--audience").html('');
                        // render the chart
                        var mainChart = new Morris.Area({
                            element: 'dashboard-chart--audience',
                            lineWidth: 1,
                            lineColors: [ '#8ac9e1','#ce77b6', '#ee9c27', '#d13f37'],
                            fillOpacity: '.9',
                            hideHover: 'auto',
                            pointSize: 0,
                            data: data.overview.chartData,
                            xkey: 'timestamp',
                            ykeys: ['pageviews', 'sessions', 'users','newusers'],
                            labels: ['Pageviews', 'Sessions', 'Users', 'New Sessions'],
                            behaveLikeLine: true,
                            gridTextColor: '#a7a7a7',
                            smooth: true,
                            ymax: Math.ceil(data.overview.chartDataMaxValue/100)*100
                        });
                        setMetrics(data);
                        setGoals(data);
                    }
                }
            });
        }

        switchTab(tab.attr('data-id'), tab.attr('data-path'));

        // Tab switcher
        $('.dashboard-tabs__item').on('click', function(){
            var id = $(this).find('.dashboard-tabs__controller').attr('data-id');
            var url = $(this).find('.dashboard-tabs__controller').attr('data-path');
            switchTab(id, url);
        });
    });

<|endoftext|>


<commit_before>const AkairoModule = require('./AkairoModule');
const { ArgumentMatches, ArgumentTypes, ArgumentSplits } = require('../utils/Constants');

/**
 * An argument in a command.
 * @typedef {Object} Argument
 * @prop {string} id - ID of the argument.
 * @prop {ArgumentMatch} [match='word'] - Method to match argument.
 * @prop {ArgumentType|string[]|function} [type='string'] - Attempts to cast argument to this type.
An array or a function can be used (more details in ArgumentType).
 * @prop {string|string[]} [prefix] - Ignores word order and uses a word that starts with/matches this prefix (or multiple prefixes if array).
Applicable to 'prefix' and 'flag' only.
 * @prop {number} [index] - Word to start from.
Applicable to 'word', 'text', or 'content' only.
When using with word, this will offset all word arguments after it by 1 unless the index property is also specified for them.
 * @prop {string|number} [defaultValue=''] - Default value if a word is not inputted or a type could not be casted to.
Can also be a function (message => {}).
 * @prop {string|string[]} [description=''] - A description of the argument.
 */

/**
 * The method to match arguments from text.
 *
Possible strings are:
 *

 *
'word' Matches by the order of the words inputted.
Ignores words that matches prefix or flag.
 *

 *
'rest' Matches the rest of the words in order.
Ignores words that matches prefix or flag.
 *

 *
'prefix' Matches words that starts with the prefix.
The word after the prefix is the evaluated argument.
 *

 *
'flag' Matches words that equal this prefix.
The evaluated argument is true or false.
 *

 *
'text' Matches the entire text, except for the command, ignoring words that matches prefix or flag.
 *

 *
'content' Matches the entire text as it was inputted, except for the command.
 * @typedef {string} ArgumentMatch
 */

/**
 * The type that the argument should be cast to.
 *
Possible strings are:
 *

 *
'string' Does not cast to any type.
 *

 *
'number' Casts to an number with parseFloat(), default value if not a number.
 *

 *
'integer' Casts to an integer with parseInt(), default value if not a number.
 *

 *
'dynamic' Casts to a number with parseFloat() or a string if the argument is not a number.
 *

 *
'dynamicInt' Casts to an integer with parseInt() or a string if the argument is not a number.
 *

 *
Possible Discord-related strings:
 *

 *
'user' Tries to resolve to a user.
 *

 *
'member' Tries to resolve to a member.
 *

 *
'channel' Tries to resolve to a channel.
 *

 *
'textChannel' Tries to resolve to a text channel.
 *

 *
'voiceChannel' Tries to resolve to a voice channel.
 *

 *
'role' Tries to resolve to a role.
 *

 *
'emoji' Tries to resolve to a custom emoji.
 *

 *
Many of these types can only be used in a guild.
 *
If any of the above are invalid, the default value will be resolved (recommended to use an ID).
 *

 *
An array of strings can be used to restrict input to only those strings, case insensitive.
 *
The evaluated argument will be all lowercase.
 *
If the input is not in the array, the default value is used.
 *

 *
A function ((word, message) => {}) can also be used to filter or modify arguments.
 *
A return value of true will let the word pass, a falsey return value will use the default value for the argument.
 *
Any other truthy return value will be used as the argument.
 * @typedef {string|string[]} ArgumentType
 */

/**
 * Options to use for command execution behavior.
 * @typedef {Object} CommandOptions
 * @prop {Argument[]} [args=[]] - Arguments to parse.
 * @prop {string} [aliases=[]] - Command names.
 * @prop {string} [category='default'] - Category ID for organization purposes.
 * @prop {string|string[]} [description=''] - Description of the command.
 * @prop {boolean} [ownerOnly=false] - Whether or not to allow client owner(s) only.
 * @prop {string} [channelRestriction='none'] - Restricts channel: 'guild' or 'dm'.
 * @prop {ArgumentSplit} [split='plain'] - Method to split text into words.
 * @prop {RegExp|function} [trigger] - A regex or function (message => {}) returning regex to match in messages that are NOT commands.
The exec function is now ((message, match) => {}) if non-global.
Or, ((message, match, groups) => {}) if global.
 * @prop {Object} [options={}] - An object for custom options.
Accessible with Command#options.
 */

/**
 * The method to split text into words.
 *
Possible strings are:
 *

 *
'plain' Splits word separated by whitespace.
Extra whitespace is ignored.
 *

 *
'split' Splits word separated by whitespace.
 *

 *
'quoted' This is like plain, but counts text inside double quotes as one word.
 *

 *
'sticky' This is like quoted, but makes it so that quoted text must have a whitespace/another double quote before it to count as another word.
It will still span multiple words.
 *

 *
A regex or a character can be used instead (for example, a comma) to split the message by that regex or character.
 * @typedef {string} ArgumentSplit
 */

/** @extends AkairoModule */
class Command extends AkairoModule {
    /**
     * Creates a new command.
     * @param {string} id - Command ID.
     * @param {function} exec - Function ((message, args) => {}) called when command is ran.
     * @param {CommandOptions} [options={}] - Options for the command.
     */
    constructor(id, exec, options = {}){
        super(id, exec, options);

        /**
         * Command names.
         * @type {string[]}
         */
        this.aliases = options.aliases || [];

        /**
         * Arguments for the command.
         * @type {Argument[]}
         */
        this.args = options.args || [];
        this.args.forEach(arg => {
            if (!arg.match) arg.match = ArgumentMatches.WORD;
            if (!arg.type) arg.type = ArgumentTypes.STRING;
            if (!arg.defaultValue) arg.defaultValue = '';

            if (Array.isArray(arg.description)) arg.description = arg.description.join('\n');
            if (!arg.description) arg.description = '';
        });

        /**
         * Description of the command.
         * @type {string}
         */
        this.description = (Array.isArray(options.description) ? options.description.join('\n') : options.description) || '';

        /**
         * Usable only by the client owner.
         * @type {boolean}
         */
        this.ownerOnly = !!options.ownerOnly;

        /**
         * Usable only in this channel type.
         * @type {string}
         */
        this.channelRestriction = options.channelRestriction || 'none';

        /**
         * The command split method.
         * @type {ArgumentSplit}
         */
        this.split = options.split || ArgumentSplits.PLAIN;

        /**
         * Custom options for the command.
         * @type {Object}
         */
        this.options = options.custom || options.options || {};

        /**
         * Gets the regex trigger, if specified.
         * @method
         * @param {Message} message - Message being handled.
         * @returns {RegExp}
         */
        this.trigger = typeof options.trigger === 'function' ? options.trigger : () => options.trigger;

        /**
         * The ID of this command.
         * @name Command#id
         * @type {string}
         */

        /**
         * Executes the command.
         * @method
         * @name Command#exec
         * @returns {*}
         */

        /**
         * The command handler.
         * @readonly
         * @name Command#handler
         * @type {CommandHandler}
         */
    }

    /**
     * The command handler.
Alias to this.handler.
     * @readonly
     * @type {CommandHandler}
     */
    get commandHandler(){
        return this.handler;
    }

    /**
     * Parses text based on this command's args.
     * @param {string} content - String to parse.
     * @param {Message} [message] - Message to use.
     * @returns {Object}
     */
    parse(content, message){
        if (this.args.length === 0) return {};

        const splitFunc = {
            [ArgumentSplits.PLAIN]: () => content.match(/[^\s]+/g),
            [ArgumentSplits.SPLIT]: () => content.split(' '),
            [ArgumentSplits.QUOTED]: () => content.match(/".*?"|[^\s"]+|"/g),
            [ArgumentSplits.STICKY]: () => content.match(/[^\s"]*?".*?"|[^\s"]+|"/g)
        };

        const words = splitFunc[this.split] ? splitFunc[this.split]() || [] : content.split(this.split);
        const args = {};

        const wordArgs = this.args.filter(arg => arg.match === ArgumentMatches.WORD || arg.match === ArgumentMatches.REST);
        const prefixArgs = this.args.filter(arg => arg.match === ArgumentMatches.PREFIX);
        const flagArgs = this.args.filter(arg => arg.match === ArgumentMatches.FLAG);
        const textArgs = this.args.filter(arg => arg.match === ArgumentMatches.TEXT);
        const contentArgs = this.args.filter(arg => arg.match === ArgumentMatches.CONTENT);

        const prefixes = [];
        [...prefixArgs, ...flagArgs].forEach(arg => {
            Array.isArray(arg.prefix) ? prefixes.push(...arg.prefix) : prefixes.push(arg.prefix);
        });

        const noPrefixWords = words.filter(w => !prefixes.some(p => w.startsWith(p)));

        const processType = (arg, word) => {
            const def = typeof arg.defaultValue === 'function' ? arg.defaultValue(message) : arg.defaultValue;

            const typeFunc = {
                [ArgumentTypes.STRING]: () => word || def,
                [ArgumentTypes.NUMBER]: () => {
                    if (isNaN(word) || !word) return def;
                    return parseFloat(word);
                },
                [ArgumentTypes.INTEGER]: () => {
                    if (isNaN(word) || !word) return def;
                    return parseInt(word);
                },
                [ArgumentTypes.DYNAMIC]: () => {
                    if (!word) return def;
                    if (isNaN(word)) return word;
                    return parseFloat(word);
                },
                [ArgumentTypes.DYNAMIC_INT]: () => {
                    if (!word) return def;
                    if (isNaN(word)) return word;
                    return parseInt(word);
                },
                [ArgumentTypes.USER]: () => {
                    const res = val => this.client.util.resolveUser(val, false, true);
                    if (!word) return res(def);
                    return res(word) || res(def);
                },
                [ArgumentTypes.MEMBER]: () => {
                    const res = val => this.client.util.resolveMember(val, message.guild, false, true);
                    if (!word) return res(def);
                    return res(word) || res(def);
                },
                [ArgumentTypes.CHANNEL]: () => {
                    const res = val => this.client.util.resolveChannel(val, message.guild, false, true);
                    if (!word) return res(def);
                    return res(word) || res(def);
                },
                [ArgumentTypes.TEXT_CHANNEL]: () => {
                    const res = val => this.client.util.resolveChannel(val, message.guild, false, true);
                    if (!word) return res(def);

                    const channel = res(word);
                    if (!channel || channel.type !== 'text') return res(def);

                    return channel;
                },
                [ArgumentTypes.VOICE_CHANNEL]: () => {
                    const res = val => this.client.util.resolveChannel(val, message.guild, false, true);
                    if (!word) return res(def);

                    const channel = res(word);
                    if (!channel || channel.type !== 'voice') return res(def);

                    return channel;
                },
                [ArgumentTypes.ROLE]: () => {
                    const res = val => this.client.util.resolveRole(val, message.guild, false, true);
                    if (!word) return res(def);
                    return res(word) || res(def);
                },
                [ArgumentTypes.EMOJI]: () => {
                    const res = val => this.client.util.resolveEmoji(val, message.guild, false, true);
                    if (!word) return res(def);
                    return res(word) || res(def);
                }
            };

            if (Array.isArray(arg.type)){
                if (!arg.type.some(t => t.toLowerCase() === word.toLowerCase())){
                    return def;
                }

                return word.toLowerCase();
            }

            if (typeof arg.type === 'function'){
                const res = arg.type(word, message);
                if (res === true) return word;
                if (!res) return def;

                return res;
            }

            if (typeFunc[arg.type]) return typeFunc[arg.type]();
            return word || def;
        };

        wordArgs.forEach((arg, i) => {
            let word;

            if (arg.match === ArgumentMatches.REST){
                word = noPrefixWords.slice(arg.index == null ? arg.index : i).join(' ') || '';
            } else {
                word = noPrefixWords[arg.index == null ? arg.index : i] || '';
            }

            if ((this.split === ArgumentSplits.QUOTED || this.split === ArgumentSplits.STICKY) && /^".*"$/.test(word)) word = word.slice(1, -1);

            args[arg.id] = processType(arg, word);
        });

        if (prefixArgs.length || flagArgs.length) words.reverse();

        prefixArgs.forEach(arg => {
            let word = words.find(w => Array.isArray(arg.prefix) ? arg.prefix.some(p => w.startsWith(p)) : w.startsWith(arg.prefix)) || '';
            word = word.replace(prefixes.find(p => word.startsWith(p)), '');

            if (this.split === ArgumentSplits.STICKY && /^".*"$/.test(word)) word = word.slice(1, -1);

            args[arg.id] = processType(arg, word);
        });

        flagArgs.forEach(arg => {
            const word = words.find(w => Array.isArray(arg.prefix) ? arg.prefix.some(p => w === p) : w === arg.prefix);
            return args[arg.id] = !!word;
        });

        textArgs.forEach(arg => {
            const def = typeof arg.defaultValue === 'function' ? arg.defaultValue(message) : arg.defaultValue;
            const w = noPrefixWords.slice(arg.index).join(' ') || def;

            args[arg.id] = processType(arg, w);
        });

        contentArgs.forEach(arg => {
            const def = typeof arg.defaultValue === 'function' ? arg.defaultValue(message) : arg.defaultValue;
            const w = content.split(' ').slice(arg.index).join(' ') || def;

            args[arg.id] = processType(arg, w);
        });

        return args;
    }

    /**
     * Reloads the command.
     * @method
     * @name Command#reload
     * @returns {Command}
     */

    /**
     * Removes the command.
     * @method
     * @name Command#remove
     * @returns {Command}
     */

    /**
     * Enables the command.
     * @method
     * @name Command#enable
     * @returns {boolean}
     */

    /**
     * Disables the command.
     * @method
     * @name Command#disable
     * @returns {boolean}
     */
}

module.exports = Command;
<commit_msg>Fix silly mistake.<commit_after>const AkairoModule = require('./AkairoModule');
const { ArgumentMatches, ArgumentTypes, ArgumentSplits } = require('../utils/Constants');

/**
 * An argument in a command.
 * @typedef {Object} Argument
 * @prop {string} id - ID of the argument.
 * @prop {ArgumentMatch} [match='word'] - Method to match argument.
 * @prop {ArgumentType|string[]|function} [type='string'] - Attempts to cast argument to this type.
An array or a function can be used (more details in ArgumentType).
 * @prop {string|string[]} [prefix] - Ignores word order and uses a word that starts with/matches this prefix (or multiple prefixes if array).
Applicable to 'prefix' and 'flag' only.
 * @prop {number} [index] - Word to start from.
Applicable to 'word', 'text', or 'content' only.
When using with word, this will offset all word arguments after it by 1 unless the index property is also specified for them.
 * @prop {string|number} [defaultValue=''] - Default value if a word is not inputted or a type could not be casted to.
Can also be a function (message => {}).
 * @prop {string|string[]} [description=''] - A description of the argument.
 */

/**
 * The method to match arguments from text.
 *
Possible strings are:
 *

 *
'word' Matches by the order of the words inputted.
Ignores words that matches prefix or flag.
 *

 *
'rest' Matches the rest of the words in order.
Ignores words that matches prefix or flag.
 *

 *
'prefix' Matches words that starts with the prefix.
The word after the prefix is the evaluated argument.
 *

 *
'flag' Matches words that equal this prefix.
The evaluated argument is true or false.
 *

 *
'text' Matches the entire text, except for the command, ignoring words that matches prefix or flag.
 *

 *
'content' Matches the entire text as it was inputted, except for the command.
 * @typedef {string} ArgumentMatch
 */

/**
 * The type that the argument should be cast to.
 *
Possible strings are:
 *

 *
'string' Does not cast to any type.
 *

 *
'number' Casts to an number with parseFloat(), default value if not a number.
 *

 *
'integer' Casts to an integer with parseInt(), default value if not a number.
 *

 *
'dynamic' Casts to a number with parseFloat() or a string if the argument is not a number.
 *

 *
'dynamicInt' Casts to an integer with parseInt() or a string if the argument is not a number.
 *

 *
Possible Discord-related strings:
 *

 *
'user' Tries to resolve to a user.
 *

 *
'member' Tries to resolve to a member.
 *

 *
'channel' Tries to resolve to a channel.
 *

 *
'textChannel' Tries to resolve to a text channel.
 *

 *
'voiceChannel' Tries to resolve to a voice channel.
 *

 *
'role' Tries to resolve to a role.
 *

 *
'emoji' Tries to resolve to a custom emoji.
 *

 *
Many of these types can only be used in a guild.
 *
If any of the above are invalid, the default value will be resolved (recommended to use an ID).
 *

 *
An array of strings can be used to restrict input to only those strings, case insensitive.
 *
The evaluated argument will be all lowercase.
 *
If the input is not in the array, the default value is used.
 *

 *
A function ((word, message) => {}) can also be used to filter or modify arguments.
 *
A return value of true will let the word pass, a falsey return value will use the default value for the argument.
 *
Any other truthy return value will be used as the argument.
 * @typedef {string|string[]} ArgumentType
 */

/**
 * Options to use for command execution behavior.
 * @typedef {Object} CommandOptions
 * @prop {Argument[]} [args=[]] - Arguments to parse.
 * @prop {string} [aliases=[]] - Command names.
 * @prop {string} [category='default'] - Category ID for organization purposes.
 * @prop {string|string[]} [description=''] - Description of the command.
 * @prop {boolean} [ownerOnly=false] - Whether or not to allow client owner(s) only.
 * @prop {string} [channelRestriction='none'] - Restricts channel: 'guild' or 'dm'.
 * @prop {ArgumentSplit} [split='plain'] - Method to split text into words.
 * @prop {RegExp|function} [trigger] - A regex or function (message => {}) returning regex to match in messages that are NOT commands.
The exec function is now ((message, match) => {}) if non-global.
Or, ((message, match, groups) => {}) if global.
 * @prop {Object} [options={}] - An object for custom options.
Accessible with Command#options.
 */

/**
 * The method to split text into words.
 *
Possible strings are:
 *

 *
'plain' Splits word separated by whitespace.
Extra whitespace is ignored.
 *

 *
'split' Splits word separated by whitespace.
 *

 *
'quoted' This is like plain, but counts text inside double quotes as one word.
 *

 *
'sticky' This is like quoted, but makes it so that quoted text must have a whitespace/another double quote before it to count as another word.
It will still span multiple words.
 *

 *
A regex or a character can be used instead (for example, a comma) to split the message by that regex or character.
 * @typedef {string} ArgumentSplit
 */

/** @extends AkairoModule */
class Command extends AkairoModule {
    /**
     * Creates a new command.
     * @param {string} id - Command ID.
     * @param {function} exec - Function ((message, args) => {}) called when command is ran.
     * @param {CommandOptions} [options={}] - Options for the command.
     */
    constructor(id, exec, options = {}){
        super(id, exec, options);

        /**
         * Command names.
         * @type {string[]}
         */
        this.aliases = options.aliases || [];

        /**
         * Arguments for the command.
         * @type {Argument[]}
         */
        this.args = options.args || [];
        this.args.forEach(arg => {
            if (!arg.match) arg.match = ArgumentMatches.WORD;
            if (!arg.type) arg.type = ArgumentTypes.STRING;
            if (!arg.defaultValue) arg.defaultValue = '';

            if (Array.isArray(arg.description)) arg.description = arg.description.join('\n');
            if (!arg.description) arg.description = '';
        });

        /**
         * Description of the command.
         * @type {string}
         */
        this.description = (Array.isArray(options.description) ? options.description.join('\n') : options.description) || '';

        /**
         * Usable only by the client owner.
         * @type {boolean}
         */
        this.ownerOnly = !!options.ownerOnly;

        /**
         * Usable only in this channel type.
         * @type {string}
         */
        this.channelRestriction = options.channelRestriction || 'none';

        /**
         * The command split method.
         * @type {ArgumentSplit}
         */
        this.split = options.split || ArgumentSplits.PLAIN;

        /**
         * Custom options for the command.
         * @type {Object}
         */
        this.options = options.custom || options.options || {};

        /**
         * Gets the regex trigger, if specified.
         * @method
         * @param {Message} message - Message being handled.
         * @returns {RegExp}
         */
        this.trigger = typeof options.trigger === 'function' ? options.trigger : () => options.trigger;

        /**
         * The ID of this command.
         * @name Command#id
         * @type {string}
         */

        /**
         * Executes the command.
         * @method
         * @name Command#exec
         * @returns {*}
         */

        /**
         * The command handler.
         * @readonly
         * @name Command#handler
         * @type {CommandHandler}
         */
    }

    /**
     * The command handler.
Alias to this.handler.
     * @readonly
     * @type {CommandHandler}
     */
    get commandHandler(){
        return this.handler;
    }

    /**
     * Parses text based on this command's args.
     * @param {string} content - String to parse.
     * @param {Message} [message] - Message to use.
     * @returns {Object}
     */
    parse(content, message){
        if (this.args.length === 0) return {};

        const splitFunc = {
            [ArgumentSplits.PLAIN]: () => content.match(/[^\s]+/g),
            [ArgumentSplits.SPLIT]: () => content.split(' '),
            [ArgumentSplits.QUOTED]: () => content.match(/".*?"|[^\s"]+|"/g),
            [ArgumentSplits.STICKY]: () => content.match(/[^\s"]*?".*?"|[^\s"]+|"/g)
        };

        const words = splitFunc[this.split] ? splitFunc[this.split]() || [] : content.split(this.split);
        const args = {};

        const wordArgs = this.args.filter(arg => arg.match === ArgumentMatches.WORD || arg.match === ArgumentMatches.REST);
        const prefixArgs = this.args.filter(arg => arg.match === ArgumentMatches.PREFIX);
        const flagArgs = this.args.filter(arg => arg.match === ArgumentMatches.FLAG);
        const textArgs = this.args.filter(arg => arg.match === ArgumentMatches.TEXT);
        const contentArgs = this.args.filter(arg => arg.match === ArgumentMatches.CONTENT);

        const prefixes = [];
        [...prefixArgs, ...flagArgs].forEach(arg => {
            Array.isArray(arg.prefix) ? prefixes.push(...arg.prefix) : prefixes.push(arg.prefix);
        });

        const noPrefixWords = words.filter(w => !prefixes.some(p => w.startsWith(p)));

        const processType = (arg, word) => {
            const def = typeof arg.defaultValue === 'function' ? arg.defaultValue(message) : arg.defaultValue;

            const typeFunc = {
                [ArgumentTypes.STRING]: () => word || def,
                [ArgumentTypes.NUMBER]: () => {
                    if (isNaN(word) || !word) return def;
                    return parseFloat(word);
                },
                [ArgumentTypes.INTEGER]: () => {
                    if (isNaN(word) || !word) return def;
                    return parseInt(word);
                },
                [ArgumentTypes.DYNAMIC]: () => {
                    if (!word) return def;
                    if (isNaN(word)) return word;
                    return parseFloat(word);
                },
                [ArgumentTypes.DYNAMIC_INT]: () => {
                    if (!word) return def;
                    if (isNaN(word)) return word;
                    return parseInt(word);
                },
                [ArgumentTypes.USER]: () => {
                    const res = val => this.client.util.resolveUser(val, false, true);
                    if (!word) return res(def);
                    return res(word) || res(def);
                },
                [ArgumentTypes.MEMBER]: () => {
                    const res = val => this.client.util.resolveMember(val, message.guild, false, true);
                    if (!word) return res(def);
                    return res(word) || res(def);
                },
                [ArgumentTypes.CHANNEL]: () => {
                    const res = val => this.client.util.resolveChannel(val, message.guild, false, true);
                    if (!word) return res(def);
                    return res(word) || res(def);
                },
                [ArgumentTypes.TEXT_CHANNEL]: () => {
                    const res = val => this.client.util.resolveChannel(val, message.guild, false, true);
                    if (!word) return res(def);

                    const channel = res(word);
                    if (!channel || channel.type !== 'text') return res(def);

                    return channel;
                },
                [ArgumentTypes.VOICE_CHANNEL]: () => {
                    const res = val => this.client.util.resolveChannel(val, message.guild, false, true);
                    if (!word) return res(def);

                    const channel = res(word);
                    if (!channel || channel.type !== 'voice') return res(def);

                    return channel;
                },
                [ArgumentTypes.ROLE]: () => {
                    const res = val => this.client.util.resolveRole(val, message.guild, false, true);
                    if (!word) return res(def);
                    return res(word) || res(def);
                },
                [ArgumentTypes.EMOJI]: () => {
                    const res = val => this.client.util.resolveEmoji(val, message.guild, false, true);
                    if (!word) return res(def);
                    return res(word) || res(def);
                }
            };

            if (Array.isArray(arg.type)){
                if (!arg.type.some(t => t.toLowerCase() === word.toLowerCase())){
                    return def;
                }

                return word.toLowerCase();
            }

            if (typeof arg.type === 'function'){
                const res = arg.type(word, message);
                if (res === true) return word;
                if (!res) return def;

                return res;
            }

            if (typeFunc[arg.type]) return typeFunc[arg.type]();
            return word || def;
        };

        wordArgs.forEach((arg, i) => {
            let word;

            if (arg.match === ArgumentMatches.REST){
                word = noPrefixWords.slice(arg.index != null ? arg.index : i).join(' ') || '';
            } else {
                word = noPrefixWords[arg.index != null ? arg.index : i] || '';
            }

            if ((this.split === ArgumentSplits.QUOTED || this.split === ArgumentSplits.STICKY) && /^".*"$/.test(word)) word = word.slice(1, -1);

            args[arg.id] = processType(arg, word);
        });

        if (prefixArgs.length || flagArgs.length) words.reverse();

        prefixArgs.forEach(arg => {
            let word = words.find(w => Array.isArray(arg.prefix) ? arg.prefix.some(p => w.startsWith(p)) : w.startsWith(arg.prefix)) || '';
            word = word.replace(prefixes.find(p => word.startsWith(p)), '');

            if (this.split === ArgumentSplits.STICKY && /^".*"$/.test(word)) word = word.slice(1, -1);

            args[arg.id] = processType(arg, word);
        });

        flagArgs.forEach(arg => {
            const word = words.find(w => Array.isArray(arg.prefix) ? arg.prefix.some(p => w === p) : w === arg.prefix);
            return args[arg.id] = !!word;
        });

        textArgs.forEach(arg => {
            const def = typeof arg.defaultValue === 'function' ? arg.defaultValue(message) : arg.defaultValue;
            const w = noPrefixWords.slice(arg.index).join(' ') || def;

            args[arg.id] = processType(arg, w);
        });

        contentArgs.forEach(arg => {
            const def = typeof arg.defaultValue === 'function' ? arg.defaultValue(message) : arg.defaultValue;
            const w = content.split(' ').slice(arg.index).join(' ') || def;

            args[arg.id] = processType(arg, w);
        });

        return args;
    }

    /**
     * Reloads the command.
     * @method
     * @name Command#reload
     * @returns {Command}
     */

    /**
     * Removes the command.
     * @method
     * @name Command#remove
     * @returns {Command}
     */

    /**
     * Enables the command.
     * @method
     * @name Command#enable
     * @returns {boolean}
     */

    /**
     * Disables the command.
     * @method
     * @name Command#disable
     * @returns {boolean}
     */
}

module.exports = Command;
<|endoftext|>


<commit_before>
(function(exports, undefined){

var CLASS_REGEX = /\[.* (.*)\]/i, // Matches: '[object Date]' => 'Date'
    TO_STRING = Object.prototype.toString;

var basicType = function(obj){
    return CLASS_REGEX.exec(TO_STRING.apply(obj))[1].toLowerCase();
};

var customType = function(name, obj){
    var types = CUSTOM_TYPES[name];

    for (var type in types){
        if (types[type](obj)) return type;
    }

    return false;
};

var domCheck = function(nodeType){
    return function(obj){
        return obj && obj.nodeType === nodeType;
    };
};

var CUSTOM_TYPES = {
    USER: {},
    DOM: {
        'element' : domCheck(1),
        'textnode': domCheck(3),
        'comment' : domCheck(8),
        'document': domCheck(9),
        'fragment': domCheck(11)
    }
};

// Actual is definition:
exports.is = function(obj, type){
    if (arguments.length === 2){

        if (type === undefined) type = 'undefined';
        else if (type === null) type = 'null';

        var typeComparitor = CUSTOM_TYPES.USER[type] || CUSTOM_TYPES.DOM[type.toLowerCase()];

        if (typeComparitor && typeComparitor(obj)) return true;

        return basicType(obj) === type.toLowerCase();

    } else {

        var userType = customType('USER', obj);
        if (userType) return userType;

        return (obj && obj.nodeType !== undefined && customType('DOM', obj)) || basicType(obj);

    }
};

exports.is.add = function(type, comparitor){
    CUSTOM_TYPES.USER[type] = comparitor;
};

exports.is.remove = function(type){
    delete CUSTOM_TYPES.USER[type];
};

})(window);
<commit_msg>Sprinkled a couple comments and reshuffled a things a little<commit_after>
(function(exports, undefined){

var CLASS_REGEX = /\[.* (.*)\]/i, // Matches: '[object Date]' => 'Date'
    TO_STRING = Object.prototype.toString;

// Returns a function to be used when comparing nodes.
var domNodeCheck = function(nodeType){
    return function(obj){
        return obj && obj.nodeType === nodeType;
    };
};

var CUSTOM_TYPES = {
    USER: {},
    DOM: {
        'element' : domNodeCheck(1),
        'textnode': domNodeCheck(3),
        'comment' : domNodeCheck(8),
        'document': domNodeCheck(9),
        'fragment': domNodeCheck(11)
    }
};

// Returns the base type of an object as determined by Object.prototype.toString.
var basicType = function(obj){
    return CLASS_REGEX.exec(TO_STRING.apply(obj))[1].toLowerCase();
};

// Returns a custom type if found.
var customType = function(name, obj){
    var types = CUSTOM_TYPES[name];

    for (var type in types){
        if (types[type](obj)) return type;
    }

    return false;
};

// Actual is definition:
exports.is = function(obj, type){
    if (arguments.length === 2){

        if (type === undefined) type = 'undefined';
        else if (type === null) type = 'null';

        var typeComparitor = CUSTOM_TYPES.USER[type] || CUSTOM_TYPES.DOM[type.toLowerCase()];

        if (typeComparitor && typeComparitor(obj)) return true;

        return basicType(obj) === type.toLowerCase();

    } else {

        var userType = customType('USER', obj);
        if (userType) return userType;

        return (obj && obj.nodeType !== undefined && customType('DOM', obj)) || basicType(obj);

    }
};

exports.is.add = function(type, comparitor){
    CUSTOM_TYPES.USER[type] = comparitor;
};

exports.is.remove = function(type){
    delete CUSTOM_TYPES.USER[type];
};

})(window);
<|endoftext|>