Exemplo n.º 1
0
void main(void)
{
	pal_spr(palSprites);//set palette for sprites
	oam_size(0);
	ppu_on_all();//enable rendering

	//initialize balls parameters

	for(i=0;i<BALLS_MAX;++i)
	{
		//starting coordinates

		ball_x[i]=rand8();
		ball_y[i]=rand8();

		//direction bits

		j=rand8();

		//horizontal speed -3..-3, excluding 0
		spr=1+(rand8()%3);
		ball_dx[i]=j&1?-spr:spr;

		//vertical speed

		spr=1+(rand8()%3);
		ball_dy[i]=j&2?-spr:spr;
	}

	
	//now the main loop

	while(1)
	{
		ppu_waitnmi();//wait for next TV frame

		spr=0;

		for(i=0;i<BALLS_MAX;++i)
		{
			//set a sprite for current ball

			spr=oam_spr(ball_x[i],ball_y[i],0x40,i&3,spr);//0x40 is tile number, i&3 is palette

			//move the ball

			ball_x[i]+=ball_dx[i];
			ball_y[i]+=ball_dy[i];

			//bounce the ball off the edges

			if(ball_x[i]>=(256-8)) ball_dx[i]=-ball_dx[i];
			if(ball_y[i]>=(240-8)) ball_dy[i]=-ball_dy[i];
		}
	}
}
Exemplo n.º 2
0
void main(void) {
  //set palette for sprites
  pal_spr(palSprites); 

  // set background color to black
  pal_col(0, 0x0f);

  //enable rendering
  ppu_on_all();

  //initialize invader parameters
  for(i=0;i<INVADERS_MAX;++i) {
    //starting coordinates
    invader_x[i]=rand8();
    invader_y[i]=rand8();

    //direction bits
    j=rand8();

    //horizontal speed -3..-3, excluding 0
    spr=1+(rand8()%3);
    invader_dx[i]=j&1?-spr:spr;

    //vertical speed
    spr=1+(rand8()%3);
    invader_dy[i]=j&2?-spr:spr;
  }

  //the main loop
  while(1) {
    //wait for next TV frame
    ppu_wait_frame();

    spr=0;

    for(i=0;i<INVADERS_MAX;++i) {
      //set a sprite for current invader
      spr=oam_spr(invader_x[i],invader_y[i],0x40,i&3,spr);//0x40 is tile number, i&3 is palette

      //move the invader
      invader_x[i]+=invader_dx[i];
      invader_y[i]+=invader_dy[i];

      //bounce the invader off the edges
      if(invader_x[i]>=(256-8)) invader_dx[i]=-invader_dx[i];
      if(invader_y[i]>=(240-8)) invader_dy[i]=-invader_dy[i];
    }
  }
}
Exemplo n.º 3
0
void AddGrass() {
	for (int i = 0; i < 4; i++) {
		for (int y = 0; y < torch.buf.geth(); y++) {
			for (int x = 0; x < torch.buf.getw(); x++) {
				if (game.map.at(x,y)->type != GROUND) continue;
				unsigned int nWater1 = countFoo(x,y,1,WATER),
				             nWater2 = countFoo(x,y,2,WATER),
				             nGrass1 = countFoo(x,y,1,GRASS),
				             nGrass2 = countFoo(x,y,2,GRASS);
				if (rand4() < nWater1 || (rand8() & 0x1f) < nWater2 ||
				    rand4() < nGrass1/2 || (rand8() & 0x1f) < nGrass2/2 ) {
					set_tile(x,y, GRASS);
				}
			}
		}
	}
}
Exemplo n.º 4
0
static void
crypt_line (unsigned char *line, int len)
{
  int i, c, r0, r1, r2;

  for (i = 0; i < len; i++)
    {
      c = line[i];
      r0 = rand8 (0);
      r1 = rand8 (1);
      r2 = rand8 (2);
      c = (c ^ r2) + r0;
      c = q[CRYPT_BYTE (s[CRYPT_BYTE (p[CRYPT_BYTE (c)] + r1)] - r1)];
      c = (c - r0) ^ r2;
      line[i] = c;
    }
}
Exemplo n.º 5
0
void CALakes() {
	for (int y = 0; y < torch.buf.geth(); y++) {
		for (int x = 0; x < torch.buf.getw(); x++) {
			if (!game.map.solid(x,y) && (rand8() < 23) && countFoo(x,y,6,GLASS)) set_tile(x,y, WATER);
		}
	}
	bool *next = new bool[torch.buf.geth()*torch.buf.getw()];
	for (int i = 0; i < 4; i++) {
		memset(next, 0, torch.buf.geth()*torch.buf.getw()*sizeof(bool));
		for (int y = 0; y < torch.buf.geth(); y++) {
			for (int x = 0; x < torch.buf.getw(); x++) {
				if (countFoo(x,y,1,WATER) >= 2) next[y*torch.buf.getw()+x] = true;
				else next[y*torch.buf.getw()+x] = false;
			}
		}
		for (int y = 0; y < torch.buf.geth(); y++) {
			for (int x = 0; x < torch.buf.getw(); x++) {
				//if (!game.map.at(x,y)->desc()->solid || game.map.at(x,y)->type == WATER) {
				if (game.map.at(x,y)->type != GLASS && game.map.at(x,y)->type != 0) {
					if (next[y*torch.buf.getw()+x])
						set_tile(x,y, WATER);
					else if (game.map.at(x,y)->type == WATER)
						set_tile(x,y, GROUND);
				}
			}
		}
	}
	for (int i = 0; i < 3; i++) {
		memset(next, 0, torch.buf.geth()*torch.buf.getw()*sizeof(bool));
		for (int y = 0; y < torch.buf.geth(); y++) {
			for (int x = 0; x < torch.buf.getw(); x++) {
				if (countFoo(x,y,1,WATER) >= 4 - countFoo(x,y,1,GLASS) &&
						countFoo(x,y,2,WATER) >= 16 - countFoo(x,y,2,GLASS)) next[y*torch.buf.getw()+x] = true;
				else next[y*torch.buf.getw()+x] = false;
			}
		}
		for (int y = 0; y < torch.buf.geth(); y++) {
			for (int x = 0; x < torch.buf.getw(); x++) {
				if (!game.map.solid(x,y) || game.map.at(x,y)->type == WATER) {
					if (next[y*torch.buf.getw()+x])
						set_tile(x,y, WATER);
					else
						set_tile(x,y, GROUND);
				}
			}
		}
	}
	delete [] next;
	int w = 0;
	for (int y = 0; y < torch.buf.geth(); y++) {
		for (int x = 0; x < torch.buf.getw(); x++) {
			if (game.map.at(x,y)->type == WATER) w++;
		}
	}
	printf("%d water cells. ", w);
}
Exemplo n.º 6
0
void SpawnCreatures() {
	for (int i = 0, n = 40 + (rand8() % 32); i < n; i++) {
		s16 x = rand32() % torch.buf.getw(), y = rand32() % torch.buf.geth();
		if (game.map.walkable(x,y)) {
			game.map.spawn(BLOWFLY, x, y);
		} else i--;
	}
	for (int i = 0, n = 20 + rand4(); i < n; i++) {
		s16 x = rand32() % torch.buf.getw(), y = rand32() % torch.buf.geth();
		if (game.map.at(x,y)->type == TREE && countFoo(x,y,1,GROUND) >= 1) {
			game.map.spawn(VENUS_FLY_TRAP, x, y);
			set_tile(x,y, GROUND);
		} else i--;
	}

	for (int i = 0, n = 15 + rand4(); i < n; i++) {
		s16 x = rand32() % torch.buf.getw(), y = rand32() % torch.buf.geth();
		if (game.map.walkable(x,y)) {
			game.map.spawn(LABRADOR, x, y);
		} else i--;
	}

	for (int y = 0; y < torch.buf.geth(); y++) {
		for (int x = 0; x < torch.buf.getw(); x++) {
			if (!game.map.occupied(x,y) &&
			    game.map.at(x,y)->type == WATER &&
			    (rand8() & 0x3f) == 0) {
			  Creature *wisp = new Creature(WILL_O_WISP);
			  wisp->setPos(x,y);
			  game.map.at(x,y)->creature = wisp;
			  game.map.monsters.push(wisp);
			  lightsource *li = new lightsource(3<<12,0,1<<11,1<<12);
			  li->orig_intensity = li->intensity = 1<<11;
			  li->x = x<<12; li->y = y<<12;
				game.map.lights.push(li);
				wisp->light = li;
			}
		}
	}
}
Exemplo n.º 7
0
static void
shuffle (int *a, int size, int rstream)
{
  int i, j, temp;

  for (i = size - 1; i >= 0; --i)
    {
      j = rand8 (rstream) % (i + 1);
      temp = a[i];
      a[i] = a[j];
      a[j] = temp;
    }
}
Exemplo n.º 8
0
void main(void)
{
	static unsigned char i,row;
	static int y;
	static unsigned int adr;

	pal_col(1,0x30);//set while color
	
	y=0;
	
	update_list[0]=0x20|NT_UPD_HORZ;//horizontal update sequence, dummy address
	update_list[1]=0x00;
	update_list[2]=32;//update sequence is 32 tiles wide
	update_list[3+32]=NT_UPD_EOF;
	
	set_vram_update(update_list);

	ppu_on_all();//enable rendering
	
	while(1)
	{
		scroll(0,y);//scroll value will be applied on the next nmi

		if(!(y&7))//put new row every 8 pixels
		{
			row=(y>>3)+59;//get row number for update, it is shifted just above the visible part of the screen
			
			if(row>=60) row-=60;//keep the row number within the limits
			
			adr=row<<5;//convert Y from pixels to tiles (row=y/8), then to nametable offset (offset=row*32)
			
			if(adr<960) adr=adr|NAMETABLE_A; else adr=(adr-960)|NAMETABLE_C;//add base address of one of two nametables
			
			update_list[0]=MSB(adr)|NT_UPD_HORZ;//set the address
			update_list[1]=LSB(adr);
			
			for(i=0;i<32;++i) update_list[3+i]=0x10+(rand8()&7);//fill row buffer with random tiles
		}

		--y;//next pixel
		
		if(y<0) y=240*2-1;//keep Y within the total height of two nametables

		ppu_wait_nmi();
	}
Exemplo n.º 9
0
void update_animations() {
	Animation *ani = game.map.animations.head();
	while (ani) {
		assert(ani->obj->desc()->animation);
		if (ani->frame >= 0) {
			// dirty the cache iff it's on the screen
			if (ani->x >= torch.buf.scroll.x && ani->x < torch.buf.scroll.x+32 &&
			    ani->y >= torch.buf.scroll.y && ani->y < torch.buf.scroll.y+24)
				torch.buf.cacheat(ani->x, ani->y)->dirty = 1;
			ani->obj->quantity = ani->frame/4; // whee, hacks
			int len = strlen(ani->obj->desc()->animation);
			if (ani->obj->quantity >= len) {
				ani->obj->quantity = 0;
				ani->frame = -rand8();
			}
		}
		ani->frame++;

		ani = ani->next();
	}
}
Exemplo n.º 10
0
void AddStars() {
	for (int y = 0; y < torch.buf.geth(); y++) {
		for (int x = 0; x < torch.buf.getw(); x++) {
			if (game.map.at(x,y)->type == TERRAIN_NONE && rand8() < 10) {
				// light
				lightsource *li = new lightsource;
				li->set(1, 1<<12, 1<<12, 1<<12);
				li->x = x<<12; li->y = y<<12;
				game.map.lights.push(li);

				// object
				Object *on = addObject(x,y,STAR);
				on->quantity = 0;

				// animation
				Animation *ani = new Animation;
				ani->obj = on;
				ani->frame = 0;
				ani->x = x; ani->y = y;
				game.map.animations.push(ani);
			}
		}
	}
}
Exemplo n.º 11
0
//Standard Chip-8 Instructions
//Technical Reference by Cowgod's
//http://devernay.free.fr/hacks/chip8/C8TECH10.HTM
void fetch_opcode()
{
	
	uint16_t opcode;
	
	opcode = CHIP8.memory[CHIP8.pc]<<8 | CHIP8.memory[CHIP8.pc+1];
	
	if (CHIP8.dt > 0) { CHIP8.dt--; return; }
	
	CHIP8.pc +=2;
	
	
	switch(nibble4(opcode)){
		case 0x0:
			switch(opcode & 0xff){
				/*
				00e0 - CLS 
				Clear the display
				*/
				case 0xe0:
					clear_videobuffer();
					break;
				/*
				00ee - RET
				Return from a subroutine
				The interpreter sets the program counter to the address at the top of the stack, then subtracts 1 from the stack pointer.
				*/
				case 0xee:
		            {   
		                CHIP8.pc = CHIP8.stack[0];
		                int i=0;
		                while (i < CHIP8.sp){
		                    CHIP8.stack[i] = CHIP8.stack[i+1];
		                    i++;
		                }   
		            }   
		            break;
			}
			break;
		
		/*
		1nnn - JP addr
		Jump to location nnn.
		The interpreter sets the program counter to nnn.
		*/	
		case 0x1:
			CHIP8.pc = (opcode & 0xfff);
			break;
		
		/*
		2nnn - CALL addr
		Call subroutine at nnn.
		The interpreter increments the stack pointer, then puts the current PC on the top of the stack. The PC is then set to nnn.
		*/
		case 0x2:
		    {   
		        int i = 16; 
		        while (i > 0){ 
		            CHIP8.stack[i] = CHIP8.stack[i-1];
		            i--;
		        }   
		        CHIP8.stack[0] = CHIP8.pc;
		        CHIP8.pc = addr(opcode) ;
		    }   
		    break;

			
		/*
		3xkk - SE Vx, byte
		Skip next instruction if Vx = kk.
		The interpreter compares register Vx to kk, and if they are equal, increments the program counter by 2.
		*/
		case 0x3:
			if (CHIP8.v[nibble3(opcode)] == (opcode & 0xff))
				CHIP8.pc +=2;
			break;
		
		/*
		4xkk - SNE Vx, byte
		Skip next instruction if Vx != kk.
		The interpreter compares register Vx to kk, and if they are not equal, increments the program counter by 2.
		*/
		case 0x4:
			if (CHIP8.v[nibble3(opcode)] != (opcode & 0xff))
				CHIP8.pc +=2;
			break;
			
		/*
		5xy0 - SE Vx, Vy
		Skip next instruction if Vx = Vy.

		The interpreter compares register Vx to register Vy, and if they are equal, increments the program counter by 2.
		*/
		case 0x5:
			if (CHIP8.v[nibble3(opcode)] == CHIP8.v[nibble2(opcode)])
				CHIP8.pc +=2;
			break;
		/* 
		6xkk - LD Vx, byte
		Set Vx = kk.
		The interpreter puts the value kk into register Vx.
		*/
		case 0x6:
			CHIP8.v[nibble3(opcode)] = (opcode & 0xff);
			break;
			
		/*	
		7xkk - ADD Vx, byte
		Set Vx = Vx + kk.
		Adds the value kk to the value of register Vx, then stores the result in Vx. 
		*/
		case 0x7:
			CHIP8.v[nibble3(opcode)] += (opcode & 0xff);
			break;
			
		//list of opcodes under 0x8	
		case 0x8:
			switch(nibble1(opcode)){
				/*
				8xy0 - LD Vx, Vy
				Set Vx = Vy
				Stores the value of register Vy in register Vx.
				*/
				case 0x0:
					CHIP8.v[nibble3(opcode)] = CHIP8.v[nibble2(opcode)];
					break;
					
				/*
				8xy1 - OR Vx, Vy
				Set Vx = Vx OR Vy.

				Performs a bitwise OR on the values of Vx and Vy, then stores the result in Vx. A bitwise OR compares the corrseponding bits from two values, and if either bit is 1, then the same bit in the result is also 1. Otherwise, it is 0.
				*/
				case 0x1:
					CHIP8.v[nibble3(opcode)] |= CHIP8.v[nibble2(opcode)];
					break;
				/*
				
				*/
				case 0x2:
					CHIP8.v[nibble3(opcode)] &= CHIP8.v[nibble2(opcode)];
					break;
				
				case 0x3:
					CHIP8.v[nibble3(opcode)] ^= CHIP8.v[nibble2(opcode)];
					break;
				/*
				8xy4 - ADD Vx, Vy
				Set Vx = Vx + Vy, set VF = carry.

				The values of Vx and Vy are added together. If the result is greater than 8 bits (i.e., > 255,) VF is set to 1, otherwise 0. Only the lowest 8 bits of the result are kept, and stored in Vx.
				*/
				case 0x4: {
					uint8_t i;
					
					CHIP8.v[15] = 0;
					
					i = CHIP8.v[nibble3(opcode)];
					CHIP8.v[nibble3(opcode)] += CHIP8.v[nibble2(opcode)];
					
					if (i > CHIP8.v[nibble3(opcode)])
						CHIP8.v[15] = 1;
					break;
				}
				/*
				8xy5 - SUB Vx, Vy
				Set Vx = Vx - Vy, set VF = NOT borrow.

				If Vx > Vy, then VF is set to 1, otherwise 0. Then Vy is subtracted from Vx, and the results stored in Vx.
				*/
				case 0x5:
					CHIP8.v[15] = 0;
					
					if (CHIP8.v[nibble3(opcode)] >= CHIP8.v[nibble2(opcode)])
						CHIP8.v[15] = 1;
					
					CHIP8.v[nibble3(opcode)] -= CHIP8.v[nibble2(opcode)];
					break;
					
				/*
				8xy6 - SHR Vx {, Vy}
				Set Vx = Vx SHR 1.
				If the least-significant bit of Vx is 1, then VF is set to 1, otherwise 0. Then Vx is divided by 2.
				*/
				case 0x6:
					CHIP8.v[16] = (CHIP8.v[nibble3(opcode)] & 0x1);
					CHIP8.v[nibble3(opcode)] >>= 1;
					break;
					
				/*
				8xy7 - SUBN Vx, Vy
				Set Vx = Vy - Vx, set VF = NOT borrow.
				If Vy > Vx, then VF is set to 1, otherwise 0. Then Vx is subtracted from Vy, and the results stored in Vx.
				*/
				case 0x7:
					CHIP8.v[15] = 0;
					
					if (CHIP8.v[nibble2(opcode)] >= CHIP8.v[nibble3(opcode)])
						CHIP8.v[0xf] = 1;
					
					CHIP8.v[nibble2(opcode)] -= CHIP8.v[nibble3(opcode)];
					break;
				
				/*
				8xyE - SHL Vx {, Vy}
				Set Vx = Vx SHL 1.

				If the most-significant bit of Vx is 1, then VF is set to 1, otherwise to 0. Then Vx is multiplied by 2.
				*/
				case 0xe:
					CHIP8.v[15] = ((CHIP8.v[nibble3(opcode)] & 0x80) ? 1 : 0);
					CHIP8.v[nibble3(opcode)] <<= 1;
					CHIP8.v[nibble3(opcode)] &= 0xff;
				default:
					fprintf(stderr, "Invalid instruction: %04x\n", opcode);
			}
			
		/*
		9xy0 - SNE Vx, Vy
		Skip next instruction if Vx != Vy.
		The values of Vx and Vy are compared, and if they are not equal, the program counter is increased by 2.
		*/	
		case 0x9:
			if (CHIP8.v[nibble3(opcode)] != CHIP8.v[nibble2(opcode)])
				CHIP8.pc += 2;
			break;
			
		/*	
		Annn - LD I, addr
		Set I = nnn.
		The value of register I is set to nnn.	
		*/
		case 0xA:
			CHIP8.i = (opcode & 0xfff);
			break;	
		
		/*
		Bnnn - JP V0, addr
		Jump to location nnn + V0.
		The program counter is set to nnn plus the value of V0.
		*/
		case 0xB:
			CHIP8.pc = (opcode & 0xfff) + CHIP8.v[0] - 2;
			break;

		/*
		Cxkk - RND Vx, byte
		Set Vx = random byte AND kk.

		The interpreter generates a random number from 0 to 255, which is then ANDed with the value kk. The results are stored in Vx. See instruction 8xy2 for more information on AND.
		*/
		case 0xC:
			CHIP8.v[nibble3(opcode)] = rand8() & (opcode & 0xff);
			break;
			
		/* 
		Dxyn - DRW Vx, Vy, nibble
		Display n-byte sprite starting at memory location I at (Vx, Vy), set VF = collision.

		The interpreter reads n bytes from memory, starting at the address stored in I. These bytes are then displayed as sprites on screen at coordinates (Vx, Vy). Sprites are XORed onto the existing screen. If this causes any pixels to be erased, VF is set to 1, otherwise it is set to 0. If the sprite is positioned so part of it is outside the coordinates of the display, it wraps around to the opposite side of the screen.
		*/
		case 0xD:
			draw_pixels(opcode);
			break;		

		/*
		group of opcodes 0xExxx
		*/
		case 0xE:
			
			switch (opcode & 0xff){
								
				/*
				Ex9E - SKP Vx
				Skip next instruction if key with the value of Vx is pressed.

				Checks the keyboard, and if the key corresponding to the value of Vx is currently in the down position, PC is increased by 2.
				*/
				case 0x9e:
					if (CHIP8.keystate[CHIP8.v[nibble3(opcode)]])
						CHIP8.pc +=2;
					break;
				
				/*
				ExA1 - SKNP Vx
				Skip next instruction if key with the value of Vx is not pressed.

				Checks the keyboard, and if the key corresponding to the value of Vx is currently in the up position, PC is increased by 2.
				
				*/
				case 0xa1: {
					if (!CHIP8.keystate[CHIP8.v[nibble3(opcode)]])
						CHIP8.pc +=2;
					break;
				}
					
				default:
					fprintf(stderr, "Fatal 0xExxx Invalid instruction: %04x\n", opcode);
					break
					
					;
			}
			break;		
		/*
		group of opcodes 0xFxxx
		*/
		case 0xF:
			switch (opcode & 0xff){				
				/*
				Fx07 - LD Vx, DT
				Set Vx = delay timer value.

				The value of DT is placed into Vx.
				*/
				case 0x07:
					CHIP8.v[nibble3(opcode)] = CHIP8.dt;
					break;
				
				/*
				Fx0A - LD Vx, K
				Wait for a key press, store the value of the key in Vx.

				All execution stops until a key is pressed, then the value of that key is stored in Vx.
				
				*/
				case 0x0a:
					//to implement 
					//wait_keypress(opcode)
					wait_keypress(opcode);
					break;
					
					
				/*
				
				*/
				case 0x15:
					CHIP8.dt = CHIP8.v[nibble3(opcode)];
					break;
					
				/*
				
				*/
				case 0x18:
					CHIP8.st = CHIP8.v[nibble3(opcode)];
					break;
				
				/*
				Fx1E - ADD I, Vx
				Set I = I + Vx.

				The values of I and Vx are added, and the results are stored in I.
				*/
				case 0x1e:
					CHIP8.i += CHIP8.v[nibble3(opcode)];
					break;
				
				/*
				Fx29 - LD F, Vx
				Set I = location of sprite for digit Vx.

				The value of I is set to the location for the hexadecimal sprite corresponding to the value of Vx.
				*/
				case 0x29:
					CHIP8.i =  CHIP8.v[nibble3(opcode)] * 5;
					break;
				
				/*
				Fx33 - LD B, Vx
				Store BCD representation of Vx in memory locations I, I+1, and I+2.

				The interpreter takes the decimal value of Vx, and places the hundreds digit in memory at location in I, the tens digit at location I+1, and the ones digit at location I+2.
				*/
				case 0x33:
					CHIP8.memory[CHIP8.i] 	= CHIP8.v[nibble3(opcode)] / 100;
					CHIP8.memory[CHIP8.i+1] = (CHIP8.v[nibble3(opcode)] / 10) % 10;
					CHIP8.memory[CHIP8.i+2] = CHIP8.v[nibble3(opcode)] % 10;
					break;
					
				/*
				Fx55 - LD [I], Vx
				Store registers V0 through Vx in memory starting at location I.

				The interpreter copies the values of registers V0 through Vx into memory, starting at the address in I.
				*/
				case 0x55: {
					int i;
					
					for (i = 0; i <= nibble3(opcode); i++){
						CHIP8.memory[CHIP8.i] = CHIP8.v[i];
						CHIP8.i++;
					}
					break;
				}
				
				/*
				Fx65 - LD Vx, [I]
				Read registers V0 through Vx from memory starting at location I.

				The interpreter reads values from memory starting at location I into registers V0 through Vx.
				*/
				case 0x65: {
					int i;
					
					for (i = 0; i <= nibble3(opcode); i++){
						CHIP8.v[i] = CHIP8.memory[CHIP8.i];
						CHIP8.i++;
					}
					break;
				}
				
				default:
					fprintf(stderr, "Fatal 0xFxxx Invalid instruction: %04x\n", opcode);
					break;
				
			}
			break;

		default:
			fprintf(stderr, "Fatal Invalid instruction: %04x\n", opcode);
			break;		
	}
	

}