Revision db70b626

View differences:

bricks.h
1
const uint16_t bricks[] PROGMEM = { 
2
	/* +----+
3
	 * |    |
4
	 * | ## |
5
	 * | ## |
6
	 * |    |
7
	 * +----+ */
8
	0b0000011001100000, 
9

  
10
	/* +----+
11
	 * |    |
12
	 * | #  |
13
	 * | ## |
14
	 * |  # |
15
	 * +----+ */
16
	0b0000010001100010,
17

  
18
	/* +----+
19
	 * |    |
20
	 * |  # |
21
	 * | ## |
22
	 * | #  |
23
	 * +----+ */
24
	0b0000001001100100, 
25

  
26
	/* +----+
27
	 * |    |
28
	 * | #  |
29
	 * | ## |
30
	 * | #  |
31
	 * +----+ */
32
	0b0000010001100100, 
33

  
34
	/* +----+
35
	 * | #  |
36
	 * | #  |
37
	 * | #  |
38
	 * | #  |
39
	 * +----+ */
40
	0b0100010001000100, 
41

  
42
	/* +----+
43
	 * |    |
44
	 * | #  |
45
	 * | #  |
46
	 * | ## |
47
	 * +----+ */
48
	0b0000010001000110, 
49

  
50
	/* +----+
51
	 * |    |
52
	 * |  # |
53
	 * |  # |
54
	 * | ## |
55
	 * +----+ */
56
	0b0000001000100110
57
};
main.c
5 5
#include <util/delay.h>
6 6
#include <avr/interrupt.h>
7 7
#include <avr/pgmspace.h>
8
#include "bricks.h"
9
#include "numbers.h"
10 8
#include "buffer.h"
11 9
//let's make our lives easier :)
12 10
#define PORT_(port) PORT ## port
......
30 28
#define A2 		PC2
31 29
#define A3 		PC3
32 30

  
33
// note that both controllers are on the same port, the reason is
34
// controllerOffset for faster input handling
35
#define CONTROLLER0_PORT   D
36
#define CONTROLLER0_LEFT   PD7
37
#define CONTROLLER0_RIGHT  PD6
38
#define CONTROLLER0_DOWN   PD5
39
#define CONTROLLER0_ROTATE PD4
40
#define CONTROLLER1_PORT   D
41
#define CONTROLLER1_LEFT   PD3
42
#define CONTROLLER1_RIGHT  PD2
43
#define CONTROLLER1_DOWN   PD1
44
#define CONTROLLER1_ROTATE PD0
45

  
46
// control mappings for atari joystick
47
#define LEFT   0b0001
48
#define DOWN   0b0100
49
#define RIGHT  0b0010
50
#define ROTATE 0b1000
51

  
52
// note NOGAMEAREA needs has to be one pixel bigger
53
// because we are lazy in moveSpriteHorizontal (forward check)
54
#define NOGAMEAREA 0b111111111
55
#define TICKS 40
56
#define NUMBER_OF_PLAYERS 2
57

  
58
struct player;
59

  
60
typedef struct sprite {
61
	volatile int8_t offset;
62
	volatile int8_t yLowerPos;
63
	volatile uint16_t block[4];
64
	volatile uint16_t raw;
65
	volatile struct player *owner;
66
	} sprite_t;
67

  
68
typedef struct player {
69
	volatile uint16_t score;
70
	volatile int8_t gameAreaStart;
71
	volatile int8_t gameAreaEnd;
72
	volatile sprite_t sprite;
73
	volatile uint8_t mirrored;
74
	volatile uint8_t controllerOffset;
75
	volatile uint8_t controllerInputMask;
76
	} player_t;
77 31

  
78 32
int main(void);
79 33
inline void customColor(uint8_t colorPins);
80
inline void redDot(void);
81
inline void greenDot(void);
82
inline void yellowDot(void);
83
inline void noDot(void);
84 34
inline void OE(void);
85 35
inline void ODE(void);
86
void loopLines(void);
87
void rotateLeft(sprite_t* sprite);
88
void moveFlyingRowsDown(player_t* player);
89
void moveSpriteDown(sprite_t* sprite);
90
void clearCompleteLines(player_t* player);
91
void rawToBlock(uint16_t block[4], uint16_t raw, int8_t offset);
92
void moveSpriteToLines(sprite_t* sprite);
93
uint8_t checkPlayerSpriteForCollision(player_t* player, uint16_t block[4], int8_t lookahead); // lookahead -1 -> look down
94
void moveSpriteHorizontal(volatile sprite_t *sprite, int8_t dir); // -1 if left, 1 if right
95
inline void printLine(int16_t line, uint8_t round, sprite_t* sprite);
96
static inline void drawGameArea(player_t player[NUMBER_OF_PLAYERS]);
97
void gameOver(player_t* player);
98
void setNewSprite(sprite_t* sprite);
99
void drawScore(uint16_t* score, uint8_t round);
100
void drawNumber(uint8_t startpos, uint16_t number[5]);
101 36
static inline void drawEverything(void);
102 37
inline void printLineBasic(int16_t line, uint8_t round, uint8_t color);
103
void printSignedNumber16(int16_t number);
104

  
105
//volatile uint16_t lines[90] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 };
106
volatile player_t player[NUMBER_OF_PLAYERS];
107

  
108
volatile uint8_t keypressCounter = 0;
109 38

  
110 39
int main(){
111 40
	// hardware init
112 41
	// clock, data and output enable
113 42
	DDR(WALLBOARD_PORT) |= (1<<CLOCK_PIN) | (1<<DATA_RED_PIN) | (1<<DATA_GREEN_PIN) | (1<<OUTPUT_ENABLE_PIN);
114
	// gamepad (PD7 is for bootloadstart):
115
	// 7...4 left down right rotate
116
	//
117
	// move > rotate > down
118
	DDR(CONTROLLER0_PORT) &= ~((1<<CONTROLLER0_LEFT) | (1<<CONTROLLER0_RIGHT) | (1<<CONTROLLER0_DOWN) | (1<<CONTROLLER0_ROTATE));
119
	PORT(CONTROLLER0_PORT) |= (1<<CONTROLLER0_LEFT) | (1<<CONTROLLER0_RIGHT) | (1<<CONTROLLER0_DOWN) | (1<<CONTROLLER0_ROTATE);
120
	DDR(CONTROLLER1_PORT) &= ~((1<<CONTROLLER1_LEFT) | (1<<CONTROLLER1_RIGHT) | (1<<CONTROLLER1_DOWN) | (1<<CONTROLLER1_ROTATE));
121
	PORT(CONTROLLER1_PORT) |= (1<<CONTROLLER1_LEFT) | (1<<CONTROLLER1_RIGHT) | (1<<CONTROLLER1_DOWN) | (1<<CONTROLLER1_ROTATE);
122 43
	// address lines:
123 44
	DDR(ADDRESS_PORT) |= (1<<A3) | (1<<A2) | (1<<A1) | (1<<A0);
124 45

  
125
	// init player
126
	player[0].score = 0;
127
	player[0].gameAreaStart = 0;
128
	player[0].gameAreaEnd = 43;
129
	player[0].sprite.owner = (player_t*)&player[0];
130
	setNewSprite((sprite_t*)&(player[0].sprite));
131
	player[0].mirrored = 0;
132
	player[0].controllerInputMask = (1<<CONTROLLER0_LEFT) | (1<<CONTROLLER0_DOWN) | (1<<CONTROLLER0_RIGHT) | (1<<CONTROLLER0_ROTATE);
133
	player[0].controllerOffset = 4;
134
	// next one
135
	player[1].score = 0;
136
	player[1].gameAreaStart = 46;
137
	player[1].gameAreaEnd = 89;
138
	player[1].sprite.owner = (player_t*)&player[1];
139
	setNewSprite((sprite_t*)&(player[1].sprite));
140
	player[1].mirrored = 1;
141
	player[1].controllerInputMask = (1<<CONTROLLER1_LEFT) | (1<<CONTROLLER1_DOWN) | (1<<CONTROLLER1_RIGHT) | (1<<CONTROLLER1_ROTATE);
142
	player[1].controllerOffset = 0;
143

  
144
	int16_t countdown = 1000;
145 46
	while(1){
146
		//for(uint8_t i = 0; i < 255; i++){
147
			drawEverything();
148
		//}
149
		//printSignedNumber16(countdown);
150
		//countdown--;
151
	}
152
}
153

  
154
void printSignedNumber16(int16_t number){ // quick and dirty
155
	// inspired by:
156
	// http://www.dattalo.com/technical/software/pic/bcd.txt
157

  
158
	uint8_t output[8] = {0,0,0,0,0,0,0,0};
159

  
160
	uint8_t a[4];
161
	a[0] = (number & 0b1111);
162
	a[1] = (number & ((0b1111 << 4))) >> 4;
163
	a[2] = (number & ((0b1111 << 8))) >> 8;
164
	a[3] = (number & ((0b0111 << 12))) >> 12; // ignore the sign
165

  
166
	uint8_t b[5];
167
	b[0] = 6*(a[3] + a[2] + a[1]) + a[0];
168
	b[1] = a[3]*9 + a[2]*5 + a[1];
169
	b[2] = 2*a[2];
170
	b[3] = 4*a[3];
171
	b[4] = 0;
172

  
173
	output[6] = b[0]%10;
174

  
175
	b[1] = (b[1] + (b[0] - output[6])/10);
176
	output[5] = b[1]%10;
177
	b[2] = (b[2] + (b[1] - output[5])/10);
178
	output[4] = b[2]%10;
179

  
180
	b[3] = (b[3] + (b[2] - output[4])/10);
181
	output[3] = b[3]%10;
182

  
183
	output[2] = (b[4] + (b[3] - output[3])/10)%10;
184

  
185
	for(uint8_t i = 0; i < 7; i++){
186
		drawNumber(80-7*i, (uint16_t)bigNumbers[output[i]]);
187
	}
188
}
189

  
190

  
191
void drawNumber(uint8_t startpos, uint16_t number[5]){
192
	for(uint8_t i = 0; i<5; i++){
193
		lines[startpos+4-i] = number[i];
47
		drawEverything();
194 48
	}
195 49
}
196 50

  
197
void setNewSprite(sprite_t* sprite){
198
	(*sprite).yLowerPos = (*((*sprite).owner)).gameAreaEnd-2;
199
	(*sprite).raw = pgm_read_word(bricks+(keypressCounter%(sizeof(bricks)/sizeof(uint16_t))));
200
	(*sprite).offset = 10;
201
	rawToBlock((uint16_t*)(*sprite).block, (*sprite).raw, (*sprite).offset);
202
	keypressCounter++;
203
}
204

  
205
void gameOver(player_t* player){
206
	for(int16_t line = (*player).gameAreaEnd; line >= (*player).gameAreaStart; line--){
207
		lines[line] = 0x0000;
208
	}
209
	(*player).score = 0;
210
	setNewSprite((sprite_t*)&((*player).sprite));
211
}
212

  
213
void drawScore(uint16_t* score, uint8_t round){
214
	if((*score) & (1<<round)){
215
		redDot();
216
	}
217
	else{
218
		noDot();
219
	}
220
}
221 51
static inline void drawEverything(){
222 52
	for(uint8_t intensity = 0; intensity < 16; intensity++){
223 53
		for(uint8_t round = 0; round < intensity; round++){
......
226 56
				printLineBasic(line, round, (1<<DATA_GREEN_PIN));
227 57
			}
228 58
			OE();
229
			_delay_us(40);
59
			_delay_us(20);
230 60
			ODE();
231 61
			_delay_us(1); // avoid ghosting
232 62
		}
......
236 66
				printLineBasic(line, round, (1<<DATA_RED_PIN));
237 67
			}
238 68
			OE();
239
			_delay_us(40);
69
			_delay_us(20);
240 70
			ODE();
241 71
			_delay_us(1); // avoid ghosting
242 72
		}
243 73
	}
244 74
}
245
static inline void drawGameArea(player_t player[NUMBER_OF_PLAYERS]){
246
	for(uint8_t round = 0; round < 16; round++){
247
		for(uint8_t playerNumber = 0; playerNumber < NUMBER_OF_PLAYERS; playerNumber++){
248
			if(player[playerNumber].mirrored){
249
				drawScore((uint16_t*)&(player[playerNumber].score), round); // don't mirror the score, so it's easier to compare
250
				for(int16_t line = player[playerNumber].gameAreaEnd; line >= player[playerNumber].gameAreaStart; line--){
251
					printLine(line, 15-round, (sprite_t*)&(player[playerNumber].sprite));
252
				}
253
			}
254
			else{
255
				for(int16_t line = player[playerNumber].gameAreaStart; line <= player[playerNumber].gameAreaEnd; line++){
256
					printLine(line, round, (sprite_t*)&(player[playerNumber].sprite));
257
				}
258
				drawScore((uint16_t*)&(player[playerNumber].score), round);
259
			}
260
		}
261
		OE();
262
		_delay_us(80);
263
		ODE();
264
		_delay_us(1); // avoid ghosting
265
		PORT(ADDRESS_PORT) = round+1;
266
	}
267
}
75

  
268 76
inline void printLineBasic(int16_t line, uint8_t round, uint8_t color){
269 77
	if((1<<round) & lines[line]){
270 78
		customColor(color);
271 79
	}
272 80
	else{
273
		noDot();
274
	}
275
}
276
inline void printLine(int16_t line, uint8_t round, sprite_t* sprite){
277
	if((1<<round) & lines[line]){
278
		yellowDot();
279
	}
280
	else{
281
		if((*sprite).yLowerPos <= line && (*sprite).yLowerPos+4 > line){
282
			if((1<<round) & (*sprite).block[line-(*sprite).yLowerPos]){
283
				greenDot();
284
			}
285
			else{
286
				noDot();
287
			}
288
		}
289
		else{
290
			noDot();
291
		}
292
	}
293
}
294

  
295
void rawToBlock(uint16_t block[4], uint16_t raw, int8_t offset){
296
	block[0] = raw & 0xf;
297
	block[1] = (raw>>4) & 0xf;
298
	block[2] = (raw>>8) & 0xf;
299
	block[3] = (raw>>12) & 0xf;
300

  
301
	if(offset > 0){
302
		for(uint8_t i = 0; i < 4; i++){
303
			block[i] = block[i]<<offset;
304
		}
305
	}
306
	else if(offset < 0){
307
		for(uint8_t i = 0; i < 4; i++){
308
			block[i] = block[i]>>(offset*-1);
309
		}
81
		customColor(0);
310 82
	}
311 83
}
312 84

  
313
void clearCompleteLines(player_t* player){
314
	for(uint8_t line = (*player).gameAreaStart; line <= (*player).gameAreaEnd; line++){
315
		if((lines[line] & (0xffff & ~(NOGAMEAREA>>1))) == (0xffff & ~(NOGAMEAREA>>1))){
316
			lines[line] ^= (0xffff & ~(NOGAMEAREA>>1));
317
			(*player).score++;
318
		}
319
	}
320
}
321

  
322
void moveFlyingRowsDown(player_t* player){ // TODO needs fix becase we don't want to touch nogamearea
323
	for(uint8_t line = (*player).gameAreaStart; line <= (*player).gameAreaEnd-1; line++){
324
		if(lines[line] == 0x0000){ // TODO maybe add clear effect with green line?
325
			lines[line] = lines[line+1];
326
			// blank line to propagate movement
327
			lines[line+1] = 0x0000;
328
		}
329
	}
330
}
331

  
332
void moveSpriteToLines(sprite_t* sprite){
333
	for(uint8_t j = 0; j < 4; j++){ // copy sprite to lines
334
		lines[(*sprite).yLowerPos+j] |= (*sprite).block[j];
335
	}
336
}
337

  
338
uint8_t checkPlayerSpriteForCollision(player_t* player, uint16_t block[4], int8_t lookahead){
339
	for(int8_t i = 0; i < 4; i++){
340
		if((*player).sprite.yLowerPos+lookahead+i < (*player).gameAreaStart){
341
			if((*player).sprite.block[i] == 0x0000){
342
				continue;
343
			}
344
			else{
345
				return 1;
346
			}
347
		}
348
		else if((lines[(*player).sprite.yLowerPos+lookahead+i] & block[i]) != 0){ // collision detected
349
			return 1;
350
		}
351
	}
352
	return 0;
353
}
354

  
355
void moveSpriteDown(sprite_t* sprite){
356
	if(checkPlayerSpriteForCollision((player_t*)(*sprite).owner, (uint16_t*)(*sprite).block, -1)){
357
		if((*sprite).yLowerPos >= (*(*sprite).owner).gameAreaEnd-4){
358
			gameOver((player_t*)(*sprite).owner);
359
			return;
360
		}
361
		moveSpriteToLines(sprite);
362
		setNewSprite(sprite);
363
		return;
364
	}
365
	(*sprite).yLowerPos--;
366
	if((*sprite).yLowerPos <= 0 && ((*sprite).block[-1*(*sprite).yLowerPos] != 0x00)){
367
		moveSpriteToLines(sprite);
368
		setNewSprite(sprite);
369
	}
370
}
371

  
372

  
373
void moveSpriteHorizontal(volatile sprite_t *sprite, int8_t dir){ // -1 if left, 1 if right
374
	uint16_t block[4];
375
	if(dir == 1){
376
		// check if block[*] >= 0x8000, so we cant move left
377
		for(uint8_t i = 0; i < 4; i++){
378
			if((*sprite).block[i] >= (1<<15)){
379
				return;
380
			}
381
		}
382
		for(uint8_t i = 0; i < 4; i++){
383
			block[i] = (*sprite).block[i] << 1;
384
		}
385
	}
386
	else{
387
		for(uint8_t i = 0; i < 4; i++){
388
			if(((*sprite).block[i] & (NOGAMEAREA)) != 0x0000){
389
				return;
390
			}
391
		}
392
		for(uint8_t i = 0; i < 4; i++){
393
			block[i] = (*sprite).block[i] >> 1;
394
		}
395
	}
396
	if(checkPlayerSpriteForCollision((player_t*)(*sprite).owner, block, 0)){
397
		return;
398
	}
399
	else{
400
		for(uint8_t i = 0; i < 4; i++){
401
			(*sprite).block[i] = block[i];
402
		}
403
		(*sprite).offset = (*sprite).offset+dir;
404
	}
405
}
406

  
407
void loopLines(){
408
	uint8_t tmp = lines[0];
409
	for(uint8_t line = 0; line < 89 ; line++){
410
		lines[line] = lines[line+1];
411
	}
412
	lines[89] = tmp;
413
}
414

  
415 85
inline void customColor(uint8_t colorPins){
416 86
	PORT(WALLBOARD_PORT) |= colorPins | (1<<CLOCK_PIN);
417 87
	PORT(WALLBOARD_PORT) &= ~(colorPins | (1<<CLOCK_PIN));
418 88
}
419 89

  
420
inline void greenDot(){
421
	PORT(WALLBOARD_PORT) |= (1<<DATA_GREEN_PIN) | (1<<CLOCK_PIN);
422
	PORT(WALLBOARD_PORT) &= ~((1<<DATA_GREEN_PIN) | (1<<CLOCK_PIN));
423
}
424
inline void redDot(){
425
	PORT(WALLBOARD_PORT) |= (1<<DATA_RED_PIN) | (1<<CLOCK_PIN);
426
	PORT(WALLBOARD_PORT) &= ~((1<<DATA_RED_PIN) | (1<<CLOCK_PIN));
427
}
428
inline void yellowDot(){
429
	PORT(WALLBOARD_PORT) |= (1<<DATA_GREEN_PIN) | (1<<DATA_RED_PIN) | (1<<CLOCK_PIN);
430
	PORT(WALLBOARD_PORT) &= ~((1<<DATA_GREEN_PIN) | (1<<DATA_RED_PIN) | (1<<CLOCK_PIN));
431
}
432
inline void noDot(){
433
	PORT(WALLBOARD_PORT) |= (1<<CLOCK_PIN);
434
	PORT(WALLBOARD_PORT) &= ~(1<<CLOCK_PIN);
435
}
436

  
437 90
inline void OE(){
438 91
	PORT(WALLBOARD_PORT) |= (1<<OUTPUT_ENABLE_PIN);
439 92
}
......
441 94
inline void ODE(){
442 95
	PORT(WALLBOARD_PORT) &= ~(1<<OUTPUT_ENABLE_PIN);
443 96
}
444

  
445
void rotateLeft(sprite_t* sprite){
446
	uint16_t block[4];
447
	uint16_t tmp = (*sprite).raw;
448

  
449
	tmp =((tmp&(1<<15))>>(15-3) | (tmp&(1<<14))>>(14-7) | (tmp&(1<<13))>>(13-11) | (tmp&(1<<12))<<(15-12) | (tmp&(1<<11))>>(11-2) | (tmp&(1<<10))>>(10-6) | (tmp&(1<<9))<<(10-9) | (tmp&(1<<8))<<(14-8) | (tmp&(1<<7))>>(7-1) | (tmp&(1<<6))>>(6-5) | (tmp&(1<<5))<<(9-5) | (tmp&(1<<4))<<(13-4) | (tmp&(1<<3))>>(3-0) | (tmp&(1<<2))<<(4-2) | (tmp&(1<<1))<<(8-1) | (tmp&(1<<0))<<(12-0) );
450

  
451
	rawToBlock(block, tmp, (*sprite).offset);
452

  
453
	// check if sprite violates borders // TODO needs to be updated if game area doesn't span the whole line
454
	for(uint8_t i = 0; i < 4; i++){
455
		if((*sprite).offset < 0){
456
			if(((block[i]<<((*sprite).offset*-1)) ^ ((tmp&((0xf)<<(i*4)))>>(i*4))) != 0){
457
				return;
458
			}
459
		}
460
		else if((*sprite).offset > 0){
461
			if((((block[i]>>((*sprite).offset)) ^ ((tmp&((0xf)<<(i*4)))>>(i*4))) != 0) || ((block[i] & (NOGAMEAREA>>1)) != 0x0000)){
462
				return;
463
			}
464
		}
465
		else{
466
			break;
467
		}
468
	}
469

  
470
	// check first if rotated sprite crashes, if, drop to game
471
	if(checkPlayerSpriteForCollision((player_t*)(*sprite).owner, block, 0)){
472
		return;
473
	}
474
	else{
475
		(*sprite).raw = tmp;
476
		for(uint8_t i = 0; i < 4; i++){
477
			(*sprite).block[i] = block[i];
478
		}
479
	}
480
	// TODO rotate with ifs
481
//	l = ((u&(1<<7)) ? (1<<7)>>4 : 0) | ((u&(1<<6)) ? ((1<<6)>>1) : 0) | ((u&(1<<3)) ? ((1<<3)>>1) : 0) | ((u&(1<<2)) ? ((1<<2)<<4) : 0) | ((l&(1<<6)) ? (1<<6)>>1 : 0) | ((l&(1<<2)) ? (1<<2)<<2 : 0) | ((l&(1<<3)) ? (1<<3)>>3 : 0) | ((l&(1<<7)) ? (1<<7)>>6 : 0);
482
}
numbers.h
1
const uint16_t bigNumbers[10][5]  = {
2
	/*
3
	 *  ##############  
4
	 * ###          ###
5
	 * ##            ##
6
	 * ###          ###
7
	 *  ############## 
8
	 */
9
	{0b0111111111111110,
10
	 0b1110000000000111,
11
	 0b1100000000000011,
12
	 0b1110000000000111,
13
	 0b0111111111111110},
14
	/*
15
	 *          ###     
16
	 *           ###   
17
	 * ##############  
18
	 * ############### 
19
	 *                 
20
	 */
21
	{0b0000000001110000,
22
	 0b0000000000111000,
23
	 0b1111111111111100,
24
	 0b1111111111111110,
25
	 0b0000000000000000},
26
	/*
27
	 * #####     ####   
28
	 * #######    #### 
29
	 * ### #####   ####
30
	 * ###  ########## 
31
	 * ###    #######  
32
	 */
33
	{0b1111100000111100,
34
	 0b1111111000011110,
35
	 0b1110111110001111,
36
	 0b1110011111111110,
37
	 0b1110000111111100},
38
	/*
39
	 *  ###  ####  ###  
40
	 * ###    ##    ###
41
	 * ###    ##    ###
42
	 * ################
43
	 *  ############## 
44
	 */
45
	{0b0111001111001110,
46
	 0b1110000110000111,
47
	 0b1110000110000111,
48
	 0b1111111111111111,
49
	 0b0111111111111110},
50
	/*
51
	 *     ######       
52
	 *     ### ####    
53
	 *     ###   ####  
54
	 * ############### 
55
	 * ################
56
	 */
57
	{0b0000111111000000,
58
	 0b0000111000111100,
59
	 0b0000111000111100,
60
	 0b1111111111111110,
61
	 0b1111111111111111},
62
	/*
63
	 *  ###   ########  
64
	 * ###     ########
65
	 * ####   ####  ###
66
	 * ###########  ###
67
	 *  #########   ###
68
	 */
69
	{0b0111000111111110,
70
	 0b1110000011111111,
71
	 0b1111000111100111,
72
	 0b1111111111100111,
73
	 0b0111111111000111},
74
	/*
75
	 *   ###########    
76
	 * ############### 
77
	 * ###   ###   ####
78
	 * ###   ###    ###
79
	 *  #######    ### 
80
	 */
81
	{0b0011111111111000,
82
	 0b1111111111111110,
83
	 0b1110001110001111,
84
	 0b1110001110000111,
85
	 0b0111111100001110},
86
	/*
87
	 *             #### 
88
	 *       ###    ###
89
	 * ###########  ###
90
	 * ################
91
	 *       ###  #####
92
	 */
93
	{0b0000000000001111,
94
	 0b0000001110000111,
95
	 0b1111111111100111,
96
	 0b1111111111111111,
97
	 0b0000001110011111},
98
	/*
99
	 *  ###### ######   
100
	 * ###  ##### #### 
101
	 * ##    ###   ### 
102
	 * ###  ##### #### 
103
	 *  ###### ######  
104
	 */
105
	{0b0111111011111100,
106
	 0b1110011111011110,
107
	 0b1100001110001110,
108
	 0b1110011111011110,
109
	 0b0111111011111100},
110
	/*
111
	 *  ###   #######   
112
	 * ###   #### #### 
113
	 * ####  ###   ### 
114
	 * ########## #### 
115
	 *  #############  
116
	 */
117
	{0b0111000111111100,
118
	 0b1110001111011110,
119
	 0b1111001110001110,
120
	 0b1111111111011110,
121
	 0b0111111111111100}
122
};

Also available in: Unified diff