Statistics
| Branch: | Revision:

root / main.c @ 1a2d51b8

History | View | Annotate | Download (17 KB)

1
#define F_CPU 16000000L
2

    
3
#include <inttypes.h>
4
#include <avr/io.h>
5
#include <util/delay.h>
6
#include <avr/interrupt.h>
7
#include <avr/pgmspace.h>
8
#include "bricks.h"
9
#include "scorefont.h"
10

    
11
//let's make our lives easier :)
12
#define PORT_(port) PORT ## port
13
#define DDR_(port)  DDR  ## port
14
#define PIN_(port)  PIN  ## port
15
#define PORT(port) PORT_(port)
16
#define DDR(port)  DDR_(port)
17
#define PIN(port)  PIN_(port)
18

    
19
// wallboard pins:
20
#define WALLBOARD_PORT         B
21
#define CLOCK_PIN         PB0
22
#define DATA_GREEN_PIN         PB3
23
#define DATA_RED_PIN         PB1
24
#define OUTPUT_ENABLE_PIN PB2
25
// address lines - please note that the address lines have to be
26
// on the same port and in the current implementation are on 0-3
27
#define ADDRESS_PORT         C
28
#define A0                 PC0
29
#define A1                 PC1
30
#define A2                 PC2
31
#define A3                 PC3
32

    
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
        volatile sprite_t nextSprite;
77
        } player_t;
78

    
79
int main(void);
80
inline void redDot(void);
81
inline void greenDot(void);
82
inline void yellowDot(void);
83
inline void noDot(void);
84
inline void OE(void);
85
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
void handleGamepadInput(player_t* player, uint8_t input);
96
inline void printLine(int16_t line, uint8_t round, sprite_t* sprite, uint8_t player_number);
97
static inline void drawGameArea(player_t player[NUMBER_OF_PLAYERS]);
98
void gameOver(player_t* player);
99
void setNewSprite(volatile sprite_t* sprite);
100
void drawScore(uint16_t* score, uint8_t round);
101

    
102
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 };
103
volatile player_t player[NUMBER_OF_PLAYERS];
104

    
105
volatile uint8_t keypressCounter = 0;
106

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

    
122
        // init player
123
        player[0].score = 0;
124
        player[0].gameAreaStart = 0;
125
        player[0].gameAreaEnd = 28;
126
        player[0].sprite.owner = (player_t*)&player[0];
127
        setNewSprite((sprite_t*)&(player[0].sprite));
128
        player[0].mirrored = 0;
129
        player[0].controllerInputMask = (1<<CONTROLLER0_LEFT) | (1<<CONTROLLER0_DOWN) | (1<<CONTROLLER0_RIGHT) | (1<<CONTROLLER0_ROTATE);
130
        player[0].controllerOffset = 4;
131
        player[0].nextSprite.owner = (player_t*)&player[0];
132
        setNewSprite((sprite_t*)&(player[0].nextSprite));
133
        // next one
134
        player[1].score = 0;
135
        player[1].gameAreaStart = 37;
136
        player[1].gameAreaEnd = 65;
137
        player[1].sprite.owner = (player_t*)&player[1];
138
        setNewSprite((sprite_t*)&(player[1].sprite));
139
        player[1].mirrored = 1;
140
        player[1].controllerInputMask = (1<<CONTROLLER1_LEFT) | (1<<CONTROLLER1_DOWN) | (1<<CONTROLLER1_RIGHT) | (1<<CONTROLLER1_ROTATE);
141
        player[1].controllerOffset = 0;
142
        player[1].nextSprite.owner = (player_t*)&player[1];
143
        setNewSprite((sprite_t*)&(player[1].nextSprite));
144
        while(1){
145
                for(uint8_t delay = 0; delay < TICKS; delay++){
146
                        drawGameArea((player_t*)player);
147
                        if(delay%(TICKS/(NUMBER_OF_PLAYERS)) == 0){
148
                                for(uint8_t playerNumber = 0; playerNumber < NUMBER_OF_PLAYERS; playerNumber++){ //fair handing of input
149
                                        handleGamepadInput((player_t*)&player[playerNumber],
150
                                                                ((~PIN(CONTROLLER0_PORT))& player[playerNumber].controllerInputMask)
151
                                                                        >>player[playerNumber].controllerOffset);
152
                                }
153
                        }
154
                }
155
                for(uint8_t playerNumber = 0; playerNumber < NUMBER_OF_PLAYERS; playerNumber++){
156
                        moveSpriteDown((sprite_t*)&(player[playerNumber].sprite));
157
                        clearCompleteLines((player_t*)&player[playerNumber]);
158
                        moveFlyingRowsDown((player_t*)&player[playerNumber]);
159
                }
160
        }
161
}
162

    
163
void setNewSprite(volatile sprite_t* sprite){
164
        (*sprite).yLowerPos = (*((*sprite).owner)).gameAreaEnd-2;
165
        (*sprite).raw = pgm_read_word(bricks+(keypressCounter%(sizeof(bricks)/sizeof(uint16_t))));
166
        (*sprite).offset = 10;
167
        rawToBlock((uint16_t*)(*sprite).block, (*sprite).raw, (*sprite).offset);
168
        keypressCounter++;
169
}
170

    
171
void gameOver(player_t* player){
172
        for(int16_t line = (*player).gameAreaEnd; line >= (*player).gameAreaStart; line--){
173
                lines[line] = 0x0000;
174
        }
175
        (*player).score = 0;
176
        setNewSprite((sprite_t*)&((*player).sprite));
177
}
178

    
179
void drawScore(uint16_t* score, uint8_t round){
180
        if((*score) & (1<<round)){
181
                redDot();
182
        }
183
        else{
184
                noDot();
185
        }
186
}
187

    
188
inline void printYellowBar(void){
189
        yellowDot();
190
}
191

    
192
inline void printGreenBar(void){
193
        greenDot();
194
}
195

    
196
inline void printRedBar(void){
197
        redDot();
198
}
199

    
200
inline void printEmptyBar(void){
201
        noDot();
202
}
203

    
204
inline void printScoreFontLine(uint8_t scoreNibble, uint8_t step, uint8_t mirror){
205
        if(mirror){
206
                for(int8_t i = 7; i >=0; i--){
207
                        if(score_font[scoreNibble][step] & (1<<i)){
208
                                yellowDot();
209
                        }
210
                        else{
211
                                noDot();
212
                        }
213
                }
214
        }
215
        else{
216
                for(uint8_t i = 0; i < 8; i++){
217
                        if(score_font[scoreNibble][step] & (1<<i)){
218
                                yellowDot();
219
                        }
220
                        else{
221
                                noDot();
222
                        }
223
                }
224
        }
225
}
226

    
227
static inline void drawGameArea(player_t player[NUMBER_OF_PLAYERS]){
228
        PORT(ADDRESS_PORT) = 0;
229
        for(uint8_t round = 0; round < 16; /*round++*/){
230
                for(int16_t line = player[1].gameAreaStart; line <= player[1].gameAreaEnd; line++){
231
                        printLine(line, 15-round/2, (sprite_t*)&(player[1].sprite), 1);
232
                }
233
                printGreenBar();
234
                for(int16_t line = 0; line < 8 ; line++){ //player[1].gameAreaEnd; line < player[0].gameAreaStart; line--){
235
                        if(round <=15 && round >=12){
236
                                printScoreFontLine((player[1].score>>4)&0x0f,15-round, 1);
237
                                break;
238
                        }
239
                        if(round <= 10 && round >= 7){
240
                                printScoreFontLine((player[1].score)&0x0f,10-round, 1);
241
                                break;
242
                        }
243
                        if(round == 5){
244
                                printYellowBar();
245
                        }
246
                        else{
247
                                if(round < 4){
248
                                        if(((line >= 2 && line <= 5)) && (player[1].nextSprite.block[line-2] & (1<<(14-round)))){
249
                                                yellowDot();
250
                                        }
251
                                        else{
252
                                                noDot();
253
                                        }
254
                                }
255
                                else{
256
                                        noDot();
257
                                }
258
                        }
259
                }
260
                printYellowBar();
261
                for(int16_t line = 0; line < 8 ; line++){
262
                        if(round >=0 && round <= 3){
263
                                printScoreFontLine((player[0].score>>4)&0x0f, round, 0);
264
                                break;
265
                        }
266
                        if(round >=5 && round <= 8){
267
                                printScoreFontLine(player[0].score&0x0f, round-5, 0);
268
                                break;
269
                        }
270
                        if(round == 10){
271
                                printYellowBar();
272
                        }
273
                        else{
274
                                if(round > 11){
275
                                        if(((line >= 2 && line <= 5)) && (player[0].nextSprite.block[5-line] & (1<<(25-round)))){
276
                                                yellowDot();
277
                                        }
278
                                        else{
279
                                                noDot();
280
                                        }
281
                                }
282
                                else{
283
                                        noDot();
284
                                }
285
                        }
286
                }
287
                printRedBar();
288
                for(int16_t line = player[0].gameAreaEnd; line >= player[0].gameAreaStart; line--){
289
                        printLine(line, 15-round/2, (sprite_t*)&(player[0].sprite), 0);
290
                }
291

    
292
                OE();
293
                _delay_us(151);
294
                ODE();
295
                round++;
296
                PORT(ADDRESS_PORT) = round;
297
                _delay_us(10); // avoid ghosting
298
        }
299
}
300

    
301
inline void printLine(int16_t line, uint8_t round, sprite_t* sprite, uint8_t player_number){
302
        if((1<<round) & lines[line]){
303
                yellowDot();
304
                yellowDot();
305
        }
306
        else{
307
                if((*sprite).yLowerPos <= line && (*sprite).yLowerPos+4 > line){
308
                        if((1<<round) & (*sprite).block[line-(*sprite).yLowerPos]){
309
                                switch(player_number){
310
                                        case 0:
311
                                                redDot();
312
                                                redDot();
313
                                                break;
314
                                        case 1:
315
                                                greenDot();
316
                                                greenDot();
317
                                                break;
318
                                        default:
319
                                                yellowDot();
320
                                                yellowDot();
321
                                                break;
322
                                }
323
                        }
324
                        else{
325
                                noDot();
326
                                noDot();
327
                        }
328
                }
329
                else{
330
                        noDot();
331
                        noDot();
332
                }
333
        }
334
}
335

    
336
void handleGamepadInput(player_t* player, uint8_t input){
337
        switch(input){
338
                // move > rotate > down
339
                case (LEFT | DOWN | RIGHT | ROTATE):
340
                        keypressCounter+=2;
341
                case (DOWN | ROTATE):
342
                        rotateLeft((sprite_t*)&((*player).sprite));
343
                        rawToBlock((uint16_t*)(*player).sprite.block, (*player).sprite.raw, (*player).sprite.offset);
344
                        moveSpriteDown((sprite_t*)&((*player).sprite));
345
                        keypressCounter+=2;
346
                        break;
347
                case (LEFT | DOWN | RIGHT):
348
                        keypressCounter+=2;
349
                case (DOWN):
350
                        moveSpriteDown((sprite_t*)&((*player).sprite));
351
                        keypressCounter+=1;
352
                        break;
353
                case (RIGHT):
354
                        moveSpriteHorizontal((sprite_t*)&((*player).sprite), -1);
355
                        keypressCounter+=1;
356
                        break;
357
                case (LEFT | RIGHT | ROTATE):
358
                        keypressCounter+=1;
359
                case (RIGHT | ROTATE):
360
                        moveSpriteHorizontal((sprite_t*)&((*player).sprite), -1);
361
                        keypressCounter+=1;
362
                case (ROTATE):
363
                        rotateLeft((sprite_t*)&((*player).sprite));
364
                        rawToBlock((uint16_t*)(*player).sprite.block, (*player).sprite.raw, (*player).sprite.offset);
365
                        keypressCounter+=1;
366
                        break;
367
                case (DOWN | RIGHT):
368
                        moveSpriteHorizontal((sprite_t*)&((*player).sprite), -1);
369
                        moveSpriteDown((sprite_t*)&((*player).sprite));
370
                        keypressCounter+=2;
371
                        break;
372
                case (DOWN | RIGHT | ROTATE):
373
                        moveSpriteHorizontal((sprite_t*)&((*player).sprite), -1);
374
                        rotateLeft((sprite_t*)&((*player).sprite));
375
                        rawToBlock((uint16_t*)(*player).sprite.block, (*player).sprite.raw, (*player).sprite.offset);
376
                        moveSpriteDown((sprite_t*)&((*player).sprite));
377
                        keypressCounter+=3;
378
                        break;
379
                case (LEFT):
380
                        moveSpriteHorizontal((sprite_t*)&((*player).sprite), 1);
381
                        keypressCounter+=1;
382
                        break;
383
                case (LEFT | ROTATE):
384
                        moveSpriteHorizontal((sprite_t*)&((*player).sprite), 1);
385
                        rotateLeft((sprite_t*)&((*player).sprite));
386
                        rawToBlock((uint16_t*)(*player).sprite.block, (*player).sprite.raw, (*player).sprite.offset);
387
                        keypressCounter+=2;
388
                        break;
389
                case (LEFT | DOWN):
390
                        moveSpriteHorizontal((sprite_t*)&((*player).sprite), 1);
391
                        moveSpriteDown((sprite_t*)&((*player).sprite));
392
                        keypressCounter+=2;
393
                        break;
394
                case (LEFT | DOWN | ROTATE):
395
                        moveSpriteHorizontal((sprite_t*)&((*player).sprite), 1);
396
                        rotateLeft((sprite_t*)&((*player).sprite));
397
                        rawToBlock((uint16_t*)(*player).sprite.block, (*player).sprite.raw, (*player).sprite.offset);
398
                        moveSpriteDown((sprite_t*)&((*player).sprite));
399
                        keypressCounter+=3;
400
                        break;
401
                // "nops"
402
                case (LEFT | RIGHT): // left+right = no move
403
                        keypressCounter+=2;
404
                case (0b0000): // nothing pressed
405
                        break;
406
        }
407
}
408

    
409
void rawToBlock(uint16_t block[4], uint16_t raw, int8_t offset){
410
        block[0] = raw & 0xf;
411
        block[1] = (raw>>4) & 0xf;
412
        block[2] = (raw>>8) & 0xf;
413
        block[3] = (raw>>12) & 0xf;
414

    
415
        if(offset > 0){
416
                for(uint8_t i = 0; i < 4; i++){
417
                        block[i] = block[i]<<offset;
418
                }
419
        }
420
        else if(offset < 0){
421
                for(uint8_t i = 0; i < 4; i++){
422
                        block[i] = block[i]>>(offset*-1);
423
                }
424
        }
425
}
426

    
427
void clearCompleteLines(player_t* player){
428
        for(uint8_t line = (*player).gameAreaStart; line <= (*player).gameAreaEnd; line++){
429
                if((lines[line] & (0xffff & ~(NOGAMEAREA>>1))) == (0xffff & ~(NOGAMEAREA>>1))){
430
                        lines[line] ^= (0xffff & ~(NOGAMEAREA>>1));
431
                        (*player).score++;
432
                }
433
        }
434
}
435

    
436
void moveFlyingRowsDown(player_t* player){ // TODO needs fix becase we don't want to touch nogamearea
437
        for(uint8_t line = (*player).gameAreaStart; line <= (*player).gameAreaEnd-1; line++){
438
                if(lines[line] == 0x0000){ // TODO maybe add clear effect with green line?
439
                        lines[line] = lines[line+1];
440
                        // blank line to propagate movement
441
                        lines[line+1] = 0x0000;
442
                }
443
        }
444
}
445

    
446
void moveSpriteToLines(sprite_t* sprite){
447
        for(uint8_t j = 0; j < 4; j++){ // copy sprite to lines
448
                lines[(*sprite).yLowerPos+j] |= (*sprite).block[j];
449
        }
450
}
451

    
452
uint8_t checkPlayerSpriteForCollision(player_t* player, uint16_t block[4], int8_t lookahead){
453
        for(int8_t i = 0; i < 4; i++){
454
                if((*player).sprite.yLowerPos+lookahead+i < (*player).gameAreaStart){
455
                        if((*player).sprite.block[i] == 0x0000){
456
                                continue;
457
                        }
458
                        else{
459
                                return 1;
460
                        }
461
                }
462
                else if((lines[(*player).sprite.yLowerPos+lookahead+i] & block[i]) != 0){ // collision detected
463
                        return 1;
464
                }
465
        }
466
        return 0;
467
}
468

    
469
void moveSpriteDown(sprite_t* sprite){
470
        if(checkPlayerSpriteForCollision((player_t*)(*sprite).owner, (uint16_t*)(*sprite).block, -1)){
471
                if((*sprite).yLowerPos >= (*(*sprite).owner).gameAreaEnd-4){
472
                        gameOver((player_t*)(*sprite).owner);
473
                        return;
474
                }
475
                moveSpriteToLines(sprite);
476
                *sprite = (((player_t*)(*sprite).owner)->nextSprite);
477
                setNewSprite(&(*sprite).owner->nextSprite);
478
                return;
479
        }
480
        (*sprite).yLowerPos--;
481
        if((*sprite).yLowerPos <= 0 && ((*sprite).block[-1*(*sprite).yLowerPos] != 0x00)){
482
                moveSpriteToLines(sprite);
483
                *sprite = (((player_t*)(*sprite).owner)->nextSprite);
484
                setNewSprite(&(*sprite).owner->nextSprite);
485
        }
486
}
487

    
488

    
489
void moveSpriteHorizontal(volatile sprite_t *sprite, int8_t dir){ // -1 if left, 1 if right
490
        uint16_t block[4];
491
        if(dir == 1){
492
                // check if block[*] >= 0x8000, so we cant move left
493
                for(uint8_t i = 0; i < 4; i++){
494
                        if((*sprite).block[i] >= (1<<15)){
495
                                return;
496
                        }
497
                }
498
                for(uint8_t i = 0; i < 4; i++){
499
                        block[i] = (*sprite).block[i] << 1;
500
                }
501
        }
502
        else{
503
                for(uint8_t i = 0; i < 4; i++){
504
                        if(((*sprite).block[i] & (NOGAMEAREA)) != 0x0000){
505
                                return;
506
                        }
507
                }
508
                for(uint8_t i = 0; i < 4; i++){
509
                        block[i] = (*sprite).block[i] >> 1;
510
                }
511
        }
512
        if(checkPlayerSpriteForCollision((player_t*)(*sprite).owner, block, 0)){
513
                return;
514
        }
515
        else{
516
                for(uint8_t i = 0; i < 4; i++){
517
                        (*sprite).block[i] = block[i];
518
                }
519
                (*sprite).offset = (*sprite).offset+dir;
520
        }
521
}
522

    
523
void loopLines(){
524
        uint8_t tmp = lines[0];
525
        for(uint8_t line = 0; line < 89 ; line++){
526
                lines[line] = lines[line+1];
527
        }
528
        lines[89] = tmp;
529
}
530

    
531
inline void greenDot(){
532
        PORT(WALLBOARD_PORT) |= (1<<DATA_GREEN_PIN) | (1<<CLOCK_PIN);
533
        PORT(WALLBOARD_PORT) &= ~((1<<DATA_GREEN_PIN) | (1<<CLOCK_PIN));
534
}
535
inline void redDot(){
536
        PORT(WALLBOARD_PORT) |= (1<<DATA_RED_PIN) | (1<<CLOCK_PIN);
537
        PORT(WALLBOARD_PORT) &= ~((1<<DATA_RED_PIN) | (1<<CLOCK_PIN));
538
}
539
inline void yellowDot(){
540
        PORT(WALLBOARD_PORT) |= (1<<DATA_GREEN_PIN) | (1<<DATA_RED_PIN) | (1<<CLOCK_PIN);
541
        PORT(WALLBOARD_PORT) &= ~((1<<DATA_GREEN_PIN) | (1<<DATA_RED_PIN) | (1<<CLOCK_PIN));
542
}
543
inline void noDot(){
544
        PORT(WALLBOARD_PORT) |= (1<<CLOCK_PIN);
545
        PORT(WALLBOARD_PORT) &= ~(1<<CLOCK_PIN);
546
}
547

    
548
inline void OE(){
549
        PORT(WALLBOARD_PORT) |= (1<<OUTPUT_ENABLE_PIN);
550
}
551

    
552
inline void ODE(){
553
        PORT(WALLBOARD_PORT) &= ~(1<<OUTPUT_ENABLE_PIN);
554
}
555

    
556
void rotateLeft(sprite_t* sprite){
557
        uint16_t block[4];
558
        uint16_t tmp = (*sprite).raw;
559

    
560
        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) );
561

    
562
        rawToBlock(block, tmp, (*sprite).offset);
563

    
564
        // check if sprite violates borders // TODO needs to be updated if game area doesn't span the whole line
565
        for(uint8_t i = 0; i < 4; i++){
566
                if((*sprite).offset < 0){
567
                        if(((block[i]<<((*sprite).offset*-1)) ^ ((tmp&((0xf)<<(i*4)))>>(i*4))) != 0){
568
                                return;
569
                        }
570
                }
571
                else if((*sprite).offset > 0){
572
                        if((((block[i]>>((*sprite).offset)) ^ ((tmp&((0xf)<<(i*4)))>>(i*4))) != 0) || ((block[i] & (NOGAMEAREA>>1)) != 0x0000)){
573
                                return;
574
                        }
575
                }
576
                else{
577
                        break;
578
                }
579
        }
580

    
581
        // check first if rotated sprite crashes, if, drop to game
582
        if(checkPlayerSpriteForCollision((player_t*)(*sprite).owner, block, 0)){
583
                return;
584
        }
585
        else{
586
                (*sprite).raw = tmp;
587
                for(uint8_t i = 0; i < 4; i++){
588
                        (*sprite).block[i] = block[i];
589
                }
590
        }
591
        // TODO rotate with ifs
592
//        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);
593
}