-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathport.c
118 lines (94 loc) · 3.1 KB
/
port.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
#include <stdio.h>
#include <assert.h>
#include <stdint.h>
#include "password.h"
#define WORD_SIZE 20
static uint32_t etanks(uint8_t amount);
static inline uint32_t bitSet(uint32_t bits, uint8_t pos);
static void decodePassword(uint32_t bits, char letter, uint8_t OFFSET);
// beaten = 0, alive = 1
static uint32_t bubbleman(uint32_t alive) {
return alive ? 1 << 7 : 1 << 10; // C3 / D1
}
static uint32_t airman(uint32_t alive) {
return alive ? 1 << 11 : 1 << 17; // D2 / E3
}
static uint32_t quickman(uint32_t alive) {
return alive ? 1 << 8 : 1 << 3; // C4 / B4
}
static uint32_t woodman(uint32_t alive) {
return alive ? 1 << 4 : 1 << 12; // B5 / D3
}
static uint32_t crashman(uint32_t alive) {
return alive ? 1 << 16 : 1 << 9; // E2 / C5
}
static uint32_t flashman(uint32_t alive) {
return alive ? 1 << 18: 1 << 5; // E4 / C1
}
static uint32_t metalman(uint32_t alive) {
return alive ? 1 << 15: 1 << 19; // E1 / E5
}
static uint32_t heatman(uint32_t alive) {
return alive ? 1 << 14 : 1 << 1; // D5 / B2
}
static void decode(const uint32_t bits) {
decodePassword(bits, 'A', 21); // offset +1 (bit number 21... 1-indexed)
decodePassword(bits, 'B', 1);
decodePassword(bits, 'C', 6);
decodePassword(bits, 'D', 11);
decodePassword(bits, 'E', 16);
}
static void decodePassword(const uint32_t bits, const char letter, const uint8_t OFFSET) {
for (int i = 0; i < 5; i++) {
if (bitSet(bits, (OFFSET + i ))) {
printf("%c%i ", letter, (i + 1));
}
}
}
static uint32_t bitSet(const uint32_t bits, const uint8_t pos) {
return (bits & (1 << (pos - 1))) != 0;
}
/*
Circular left shift of words E-B (bits 1-20) depending on the number of
etanks. Clears out e-tanks (A-word) if set.
Call this function *before* etanks()
*/
static uint32_t rotateLeft(const uint32_t bits, const uint8_t ETANKS) {
assert(ETANKS <= MAX_ETANKS);
if (ETANKS == 0) {
return bits;
}
const uint32_t mask = 0xFFFFF; // bits 1-20
// clear first 5 bits used for etanks (A word)
// left rotation of bits by 1-4 steps.
// 20 bit word size
const uint32_t leftmost = (bits & mask) >> (WORD_SIZE - ETANKS);
// we only keep the rightmost 20 bits
const uint32_t rightmost = (bits << ETANKS) & mask;
return leftmost | rightmost;
}
uint32_t generatePassword(struct options* config) {
uint32_t bits = 0;
const uint8_t ETANKS = config->etanks;
bits = bits | bubbleman( config->bubbleman );
bits = bits | airman( config->airman );
bits = bits | quickman( config->quickman);
bits = bits | woodman( config->woodman);
bits = bits | crashman( config->crashman);
bits = bits | flashman( config->flashman);
bits = bits | metalman( config->metalman);
bits = bits | heatman( config->heatman);
bits = rotateLeft(bits, ETANKS);
bits = bits | etanks(ETANKS);
if (config->debug) {
printf("%#x\n", bits);
return bits;
}
decode(bits);
printf("\n");
return 0;
}
static uint32_t etanks(const uint8_t amount) {
uint32_t etanks = (1 << (WORD_SIZE + amount));
return etanks;
}