Statistics
| Branch: | Revision:

root / main.c @ 0654a4da

History | View | Annotate | Download (15.9 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 "numbers.h"
10
#include "buffer.h"
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
        } 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(sprite_t* sprite);
99
void drawScore(uint16_t* score, uint8_t round);
100
void drawNumber(uint8_t startpos, uint16_t number[5]);
101
static inline void drawEverything(void);
102
inline void printLineBasic(int16_t line, uint8_t round);
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

    
110
int main(){
111
        // hardware init
112
        // clock, data and output enable
113
        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
        // address lines:
123
        DDR(ADDRESS_PORT) |= (1<<A3) | (1<<A2) | (1<<A1) | (1<<A0);
124

    
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
        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];
194
        }
195
}
196

    
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
static inline void drawEverything(){
222
        for(uint8_t round = 0; round < 16; round++){
223
                for(int16_t line = 0; line < 90; line++){
224
                        printLineBasic(line, round);
225
                }
226
                OE();
227
                _delay_us(80);
228
                ODE();
229
                _delay_us(1); // avoid ghosting
230
                PORT(ADDRESS_PORT) = round+1;
231
        }
232
}
233
static inline void drawGameArea(player_t player[NUMBER_OF_PLAYERS]){
234
        for(uint8_t round = 0; round < 16; round++){
235
                for(uint8_t playerNumber = 0; playerNumber < NUMBER_OF_PLAYERS; playerNumber++){
236
                        if(player[playerNumber].mirrored){
237
                                drawScore((uint16_t*)&(player[playerNumber].score), round); // don't mirror the score, so it's easier to compare
238
                                for(int16_t line = player[playerNumber].gameAreaEnd; line >= player[playerNumber].gameAreaStart; line--){
239
                                        printLine(line, 15-round, (sprite_t*)&(player[playerNumber].sprite));
240
                                }
241
                        }
242
                        else{
243
                                for(int16_t line = player[playerNumber].gameAreaStart; line <= player[playerNumber].gameAreaEnd; line++){
244
                                        printLine(line, round, (sprite_t*)&(player[playerNumber].sprite));
245
                                }
246
                                drawScore((uint16_t*)&(player[playerNumber].score), round);
247
                        }
248
                }
249
                OE();
250
                _delay_us(80);
251
                ODE();
252
                _delay_us(1); // avoid ghosting
253
                PORT(ADDRESS_PORT) = round+1;
254
        }
255
}
256
inline void printLineBasic(int16_t line, uint8_t round){
257
        if((1<<round) & lines[line]){
258
                yellowDot();
259
        }
260
        else{
261
                noDot();
262
        }
263
}
264
inline void printLine(int16_t line, uint8_t round, sprite_t* sprite){
265
        if((1<<round) & lines[line]){
266
                yellowDot();
267
        }
268
        else{
269
                if((*sprite).yLowerPos <= line && (*sprite).yLowerPos+4 > line){
270
                        if((1<<round) & (*sprite).block[line-(*sprite).yLowerPos]){
271
                                greenDot();
272
                        }
273
                        else{
274
                                noDot();
275
                        }
276
                }
277
                else{
278
                        noDot();
279
                }
280
        }
281
}
282

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

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

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

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

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

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

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

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

    
433

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

    
468
void loopLines(){
469
        uint8_t tmp = lines[0];
470
        for(uint8_t line = 0; line < 89 ; line++){
471
                lines[line] = lines[line+1];
472
        }
473
        lines[89] = tmp;
474
}
475

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

    
493
inline void OE(){
494
        PORT(WALLBOARD_PORT) |= (1<<OUTPUT_ENABLE_PIN);
495
}
496

    
497
inline void ODE(){
498
        PORT(WALLBOARD_PORT) &= ~(1<<OUTPUT_ENABLE_PIN);
499
}
500

    
501
void rotateLeft(sprite_t* sprite){
502
        uint16_t block[4];
503
        uint16_t tmp = (*sprite).raw;
504

    
505
        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) );
506

    
507
        rawToBlock(block, tmp, (*sprite).offset);
508

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

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