Statistics
| Branch: | Revision:

root / main.c @ 65352f3f

History | View | Annotate | Download (16 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

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

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

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

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

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

    
57
struct player;
58

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

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

    
78
int main(void);
79
inline void redDot(void);
80
inline void greenDot(void);
81
inline void yellowDot(void);
82
inline void noDot(void);
83
inline void OE(void);
84
inline void ODE(void);
85
void loopLines(void);
86
void rotateLeft(sprite_t* sprite);
87
void moveFlyingRowsDown(player_t* player);
88
void moveSpriteDown(sprite_t* sprite);
89
void clearCompleteLines(player_t* player);
90
void rawToBlock(uint16_t block[4], uint16_t raw, int8_t offset);
91
void moveSpriteToLines(sprite_t* sprite);
92
uint8_t checkPlayerSpriteForCollision(player_t* player, uint16_t block[4], int8_t lookahead); // lookahead -1 -> look down
93
void moveSpriteHorizontal(volatile sprite_t *sprite, int8_t dir); // -1 if left, 1 if right
94
void handleGamepadInput(player_t* player, uint8_t input);
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(volatile sprite_t* sprite);
99
void drawScore(uint16_t* score, uint8_t round);
100

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

    
104
volatile uint8_t keypressCounter = 0;
105

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

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

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

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

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

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

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

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

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

    
203
static inline void drawGameArea(player_t player[NUMBER_OF_PLAYERS]){
204
        PORT(ADDRESS_PORT) = 0;
205
        for(uint8_t round = 0; round < 16; /*round++*/){
206
                for(int16_t line = player[1].gameAreaStart; line <= player[1].gameAreaEnd; line++){
207
                        printLine(line, 15-round/2, (sprite_t*)&(player[1].sprite));
208
                }
209
                printGreenBar();
210
                for(int16_t line = 0; line < 7 ; line++){ //player[1].gameAreaEnd; line < player[0].gameAreaStart; line--){
211
                        //printLine(line, 15-round, (sprite_t*)&(player[1].sprite));
212
                        if(round == 5){
213
                                printYellowBar();
214
                        }
215
                        else{
216
                                if(round < 4){
217
                                        if(((line >= 2 && line <= 5)) && (player[1].nextSprite.block[line-2] & (1<<(14-round)))){
218
                                                yellowDot();
219
                                        }
220
                                        else{
221
                                                noDot();
222
                                        }
223
                                }
224
                                else{
225
                                        noDot();
226
                                }
227
                        }
228
                }
229
                printYellowBar();
230
                for(int16_t line = 0; line < 7 ; line++){
231
                        if(round == 10){
232
                                printYellowBar();
233
                        }
234
                        else{
235
                                if(round > 11){
236
                                        if(((line >= 2 && line <= 5)) && (player[0].nextSprite.block[5-line] & (1<<(25-round)))){
237
                                                yellowDot();
238
                                        }
239
                                        else{
240
                                                noDot();
241
                                        }
242
                                }
243
                                else{
244
                                        noDot();
245
                                }
246
                        }
247
                }
248
                printRedBar();
249
                for(int16_t line = player[0].gameAreaEnd; line >= player[0].gameAreaStart; line--){
250
                        printLine(line, 15-round/2, (sprite_t*)&(player[0].sprite));
251
                }
252

    
253
                OE();
254
                _delay_us(80);
255
                ODE();
256
                round++;
257
                PORT(ADDRESS_PORT) = round;
258
                _delay_us(10); // avoid ghosting
259
        }
260
}
261

    
262
inline void printLine(int16_t line, uint8_t round, sprite_t* sprite){
263
        if((1<<round) & lines[line]){
264
                yellowDot();
265
                yellowDot();
266
        }
267
        else{
268
                if((*sprite).yLowerPos <= line && (*sprite).yLowerPos+4 > line){
269
                        if((1<<round) & (*sprite).block[line-(*sprite).yLowerPos]){
270
                                greenDot();
271
                                greenDot();
272
                        }
273
                        else{
274
                                noDot();
275
                                noDot();
276
                        }
277
                }
278
                else{
279
                        noDot();
280
                        noDot();
281
                }
282
        }
283
}
284

    
285
void handleGamepadInput(player_t* player, uint8_t input){
286
        switch(input){
287
                // move > rotate > down
288
                case (LEFT | DOWN | RIGHT | ROTATE):
289
                        keypressCounter+=2;
290
                case (DOWN | ROTATE):
291
                        rotateLeft((sprite_t*)&((*player).sprite));
292
                        rawToBlock((uint16_t*)(*player).sprite.block, (*player).sprite.raw, (*player).sprite.offset);
293
                        moveSpriteDown((sprite_t*)&((*player).sprite));
294
                        keypressCounter+=2;
295
                        break;
296
                case (LEFT | DOWN | RIGHT):
297
                        keypressCounter+=2;
298
                case (DOWN):
299
                        moveSpriteDown((sprite_t*)&((*player).sprite));
300
                        keypressCounter+=1;
301
                        break;
302
                case (RIGHT):
303
                        moveSpriteHorizontal((sprite_t*)&((*player).sprite), -1);
304
                        keypressCounter+=1;
305
                        break;
306
                case (LEFT | RIGHT | ROTATE):
307
                        keypressCounter+=1;
308
                case (RIGHT | ROTATE):
309
                        moveSpriteHorizontal((sprite_t*)&((*player).sprite), -1);
310
                        keypressCounter+=1;
311
                case (ROTATE):
312
                        rotateLeft((sprite_t*)&((*player).sprite));
313
                        rawToBlock((uint16_t*)(*player).sprite.block, (*player).sprite.raw, (*player).sprite.offset);
314
                        keypressCounter+=1;
315
                        break;
316
                case (DOWN | RIGHT):
317
                        moveSpriteHorizontal((sprite_t*)&((*player).sprite), -1);
318
                        moveSpriteDown((sprite_t*)&((*player).sprite));
319
                        keypressCounter+=2;
320
                        break;
321
                case (DOWN | RIGHT | ROTATE):
322
                        moveSpriteHorizontal((sprite_t*)&((*player).sprite), -1);
323
                        rotateLeft((sprite_t*)&((*player).sprite));
324
                        rawToBlock((uint16_t*)(*player).sprite.block, (*player).sprite.raw, (*player).sprite.offset);
325
                        moveSpriteDown((sprite_t*)&((*player).sprite));
326
                        keypressCounter+=3;
327
                        break;
328
                case (LEFT):
329
                        moveSpriteHorizontal((sprite_t*)&((*player).sprite), 1);
330
                        keypressCounter+=1;
331
                        break;
332
                case (LEFT | ROTATE):
333
                        moveSpriteHorizontal((sprite_t*)&((*player).sprite), 1);
334
                        rotateLeft((sprite_t*)&((*player).sprite));
335
                        rawToBlock((uint16_t*)(*player).sprite.block, (*player).sprite.raw, (*player).sprite.offset);
336
                        keypressCounter+=2;
337
                        break;
338
                case (LEFT | DOWN):
339
                        moveSpriteHorizontal((sprite_t*)&((*player).sprite), 1);
340
                        moveSpriteDown((sprite_t*)&((*player).sprite));
341
                        keypressCounter+=2;
342
                        break;
343
                case (LEFT | DOWN | ROTATE):
344
                        moveSpriteHorizontal((sprite_t*)&((*player).sprite), 1);
345
                        rotateLeft((sprite_t*)&((*player).sprite));
346
                        rawToBlock((uint16_t*)(*player).sprite.block, (*player).sprite.raw, (*player).sprite.offset);
347
                        moveSpriteDown((sprite_t*)&((*player).sprite));
348
                        keypressCounter+=3;
349
                        break;
350
                // "nops"
351
                case (LEFT | RIGHT): // left+right = no move
352
                        keypressCounter+=2;
353
                case (0b0000): // nothing pressed
354
                        break;
355
        }
356
}
357

    
358
void rawToBlock(uint16_t block[4], uint16_t raw, int8_t offset){
359
        block[0] = raw & 0xf;
360
        block[1] = (raw>>4) & 0xf;
361
        block[2] = (raw>>8) & 0xf;
362
        block[3] = (raw>>12) & 0xf;
363

    
364
        if(offset > 0){
365
                for(uint8_t i = 0; i < 4; i++){
366
                        block[i] = block[i]<<offset;
367
                }
368
        }
369
        else if(offset < 0){
370
                for(uint8_t i = 0; i < 4; i++){
371
                        block[i] = block[i]>>(offset*-1);
372
                }
373
        }
374
}
375

    
376
void clearCompleteLines(player_t* player){
377
        for(uint8_t line = (*player).gameAreaStart; line <= (*player).gameAreaEnd; line++){
378
                if((lines[line] & (0xffff & ~(NOGAMEAREA>>1))) == (0xffff & ~(NOGAMEAREA>>1))){
379
                        lines[line] ^= (0xffff & ~(NOGAMEAREA>>1));
380
                        (*player).score++;
381
                }
382
        }
383
}
384

    
385
void moveFlyingRowsDown(player_t* player){ // TODO needs fix becase we don't want to touch nogamearea
386
        for(uint8_t line = (*player).gameAreaStart; line <= (*player).gameAreaEnd-1; line++){
387
                if(lines[line] == 0x0000){ // TODO maybe add clear effect with green line?
388
                        lines[line] = lines[line+1];
389
                        // blank line to propagate movement
390
                        lines[line+1] = 0x0000;
391
                }
392
        }
393
}
394

    
395
void moveSpriteToLines(sprite_t* sprite){
396
        for(uint8_t j = 0; j < 4; j++){ // copy sprite to lines
397
                lines[(*sprite).yLowerPos+j] |= (*sprite).block[j];
398
        }
399
}
400

    
401
uint8_t checkPlayerSpriteForCollision(player_t* player, uint16_t block[4], int8_t lookahead){
402
        for(int8_t i = 0; i < 4; i++){
403
                if((*player).sprite.yLowerPos+lookahead+i < (*player).gameAreaStart){
404
                        if((*player).sprite.block[i] == 0x0000){
405
                                continue;
406
                        }
407
                        else{
408
                                return 1;
409
                        }
410
                }
411
                else if((lines[(*player).sprite.yLowerPos+lookahead+i] & block[i]) != 0){ // collision detected
412
                        return 1;
413
                }
414
        }
415
        return 0;
416
}
417

    
418
void moveSpriteDown(sprite_t* sprite){
419
        if(checkPlayerSpriteForCollision((player_t*)(*sprite).owner, (uint16_t*)(*sprite).block, -1)){
420
                if((*sprite).yLowerPos >= (*(*sprite).owner).gameAreaEnd-4){
421
                        gameOver((player_t*)(*sprite).owner);
422
                        return;
423
                }
424
                moveSpriteToLines(sprite);
425
                *sprite = (((player_t*)(*sprite).owner)->nextSprite);
426
                setNewSprite(&(*sprite).owner->nextSprite);
427
                return;
428
        }
429
        (*sprite).yLowerPos--;
430
        if((*sprite).yLowerPos <= 0 && ((*sprite).block[-1*(*sprite).yLowerPos] != 0x00)){
431
                moveSpriteToLines(sprite);
432
                *sprite = (((player_t*)(*sprite).owner)->nextSprite);
433
                setNewSprite(&(*sprite).owner->nextSprite);
434
        }
435
}
436

    
437

    
438
void moveSpriteHorizontal(volatile sprite_t *sprite, int8_t dir){ // -1 if left, 1 if right
439
        uint16_t block[4];
440
        if(dir == 1){
441
                // check if block[*] >= 0x8000, so we cant move left
442
                for(uint8_t i = 0; i < 4; i++){
443
                        if((*sprite).block[i] >= (1<<15)){
444
                                return;
445
                        }
446
                }
447
                for(uint8_t i = 0; i < 4; i++){
448
                        block[i] = (*sprite).block[i] << 1;
449
                }
450
        }
451
        else{
452
                for(uint8_t i = 0; i < 4; i++){
453
                        if(((*sprite).block[i] & (NOGAMEAREA)) != 0x0000){
454
                                return;
455
                        }
456
                }
457
                for(uint8_t i = 0; i < 4; i++){
458
                        block[i] = (*sprite).block[i] >> 1;
459
                }
460
        }
461
        if(checkPlayerSpriteForCollision((player_t*)(*sprite).owner, block, 0)){
462
                return;
463
        }
464
        else{
465
                for(uint8_t i = 0; i < 4; i++){
466
                        (*sprite).block[i] = block[i];
467
                }
468
                (*sprite).offset = (*sprite).offset+dir;
469
        }
470
}
471

    
472
void loopLines(){
473
        uint8_t tmp = lines[0];
474
        for(uint8_t line = 0; line < 89 ; line++){
475
                lines[line] = lines[line+1];
476
        }
477
        lines[89] = tmp;
478
}
479

    
480
inline void greenDot(){
481
        PORT(WALLBOARD_PORT) |= (1<<DATA_GREEN_PIN) | (1<<CLOCK_PIN);
482
        PORT(WALLBOARD_PORT) &= ~((1<<DATA_GREEN_PIN) | (1<<CLOCK_PIN));
483
}
484
inline void redDot(){
485
        PORT(WALLBOARD_PORT) |= (1<<DATA_RED_PIN) | (1<<CLOCK_PIN);
486
        PORT(WALLBOARD_PORT) &= ~((1<<DATA_RED_PIN) | (1<<CLOCK_PIN));
487
}
488
inline void yellowDot(){
489
        PORT(WALLBOARD_PORT) |= (1<<DATA_GREEN_PIN) | (1<<DATA_RED_PIN) | (1<<CLOCK_PIN);
490
        PORT(WALLBOARD_PORT) &= ~((1<<DATA_GREEN_PIN) | (1<<DATA_RED_PIN) | (1<<CLOCK_PIN));
491
}
492
inline void noDot(){
493
        PORT(WALLBOARD_PORT) |= (1<<CLOCK_PIN);
494
        PORT(WALLBOARD_PORT) &= ~(1<<CLOCK_PIN);
495
}
496

    
497
inline void OE(){
498
        PORT(WALLBOARD_PORT) |= (1<<OUTPUT_ENABLE_PIN);
499
}
500

    
501
inline void ODE(){
502
        PORT(WALLBOARD_PORT) &= ~(1<<OUTPUT_ENABLE_PIN);
503
}
504

    
505
void rotateLeft(sprite_t* sprite){
506
        uint16_t block[4];
507
        uint16_t tmp = (*sprite).raw;
508

    
509
        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) );
510

    
511
        rawToBlock(block, tmp, (*sprite).offset);
512

    
513
        // check if sprite violates borders // TODO needs to be updated if game area doesn't span the whole line
514
        for(uint8_t i = 0; i < 4; i++){
515
                if((*sprite).offset < 0){
516
                        if(((block[i]<<((*sprite).offset*-1)) ^ ((tmp&((0xf)<<(i*4)))>>(i*4))) != 0){
517
                                return;
518
                        }
519
                }
520
                else if((*sprite).offset > 0){
521
                        if((((block[i]>>((*sprite).offset)) ^ ((tmp&((0xf)<<(i*4)))>>(i*4))) != 0) || ((block[i] & (NOGAMEAREA>>1)) != 0x0000)){
522
                                return;
523
                        }
524
                }
525
                else{
526
                        break;
527
                }
528
        }
529

    
530
        // check first if rotated sprite crashes, if, drop to game
531
        if(checkPlayerSpriteForCollision((player_t*)(*sprite).owner, block, 0)){
532
                return;
533
        }
534
        else{
535
                (*sprite).raw = tmp;
536
                for(uint8_t i = 0; i < 4; i++){
537
                        (*sprite).block[i] = block[i];
538
                }
539
        }
540
        // TODO rotate with ifs
541
//        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);
542
}