-
Notifications
You must be signed in to change notification settings - Fork 5
/
main_pokitto.cpp
323 lines (258 loc) · 7.18 KB
/
main_pokitto.cpp
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
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
/**
@file main_pokitto.cpp
This is Pokitto implementation of the game front end, using the official
PokittoLib.
by Miloslav Ciz (drummyfish), 2019
Released under CC0 1.0 (https://creativecommons.org/publicdomain/zero/1.0/)
plus a waiver of all other intellectual property. The goal of this work is to
be and remain completely in the public domain forever, available for any use
whatsoever.
*/
#define JOYHAT // compiles the version for Pokitto with joystick hat
#if 0
// for debug:
#define SFG_LOG(s) puts(s);
#define SFG_CPU_LOAD(x) printf("CPU: %d\n",x);
#endif
#if _OSCT == 2
// overclock
#define SFG_FPS 36
#define SFG_DIMINISH_SPRITES 1
#define SFG_RAYCASTING_MAX_HITS 6
#else
#define SFG_FPS 22
#define SFG_DIMINISH_SPRITES 0
#define SFG_RAYCASTING_MAX_HITS 5
#endif
#define SFG_CAN_EXIT 0
#define SFG_PLAYER_TURN_SPEED 135
#ifndef JOYHAT
#define SFG_SCREEN_RESOLUTION_X 110
#define SFG_SCREEN_RESOLUTION_Y 88
#else
#define SFG_SCREEN_RESOLUTION_X 88
#define SFG_SCREEN_RESOLUTION_Y 110
#define SFG_FOV_VERTICAL 350
#define SFG_FOV_HORIZONTAL 210
#include "JoyHat/JoyHat.h"
JoyHat joy;
uint16_t rumbleCooldown = 0;
uint16_t axisThreshold1, axisThreshold2;
#endif
#define SFG_RESOLUTION_SCALEDOWN 1
#define SFG_DITHERED_SHADOW 0
#define SFG_FOG_DIMINISH_STEP 2048
#define SFG_RAYCASTING_MAX_STEPS 20
#define SFG_RAYCASTING_SUBSAMPLE 2
#include "game.h"
#include "sounds.h"
#include "../PokittoLib/Pokitto/POKITTO_HW/clock_11u6x.h"
#include "../PokittoLib/Pokitto/POKITTO_HW/timer_11u6x.h"
#include "../PokittoLib/Pokitto/Pokitto.h"
#include "PokittoCookie.h"
class SaveCookie: public Pokitto::Cookie
{
public:
uint8_t data[SFG_SAVE_SIZE];
};
SaveCookie save;
Pokitto::Core pokitto;
uint8_t *pokittoScreen;
void SFG_setPixel(uint16_t x, uint16_t y, uint8_t colorIndex)
{
#ifndef JOYHAT
pokittoScreen[y * SFG_SCREEN_RESOLUTION_X + x] = colorIndex;
#else
pokittoScreen[x * SFG_SCREEN_RESOLUTION_Y + (SFG_SCREEN_RESOLUTION_Y - 1 - y)]
= colorIndex;
#endif
}
uint32_t SFG_getTimeMs()
{
return pokitto.getTime();
}
void SFG_sleepMs(uint16_t timeMs)
{
}
int8_t SFG_keyPressed(uint8_t key)
{
switch (key)
{
#ifdef JOYHAT
case SFG_KEY_UP: return joy.JoyX() < axisThreshold1; break;
case SFG_KEY_DOWN: return joy.JoyX() > axisThreshold2; break;
case SFG_KEY_RIGHT: return joy.JoyY() > axisThreshold2; break;
case SFG_KEY_LEFT: return joy.JoyY() < axisThreshold1; break;
case SFG_KEY_JUMP: return pokitto.rightBtn(); break;
case SFG_KEY_STRAFE_RIGHT: return pokitto.downBtn(); break;
case SFG_KEY_STRAFE_LEFT: return pokitto.upBtn(); break;
case SFG_KEY_MAP: return pokitto.leftBtn(); break;
case SFG_KEY_PREVIOUS_WEAPON: return joy.Button1(); break;
case SFG_KEY_NEXT_WEAPON: return joy.Button2(); break;
#else
case SFG_KEY_UP: return pokitto.upBtn(); break;
case SFG_KEY_DOWN: return pokitto.downBtn(); break;
case SFG_KEY_RIGHT: return pokitto.rightBtn(); break;
case SFG_KEY_LEFT: return pokitto.leftBtn(); break;
#endif
case SFG_KEY_A: return pokitto.aBtn(); break;
case SFG_KEY_B: return pokitto.bBtn(); break;
case SFG_KEY_C: return pokitto.cBtn(); break;
default: return 0; break;
}
}
void SFG_getMouseOffset(int16_t *x, int16_t *y)
{
}
uint8_t audioBuff[SFG_SFX_SAMPLE_COUNT];
uint16_t audioPos = 0;
uint8_t musicOn = 0;
void SFG_setMusic(uint8_t value)
{
switch (value)
{
case SFG_MUSIC_TURN_ON: musicOn = 1; break;
case SFG_MUSIC_TURN_OFF: musicOn = 0; break;
case SFG_MUSIC_NEXT:
{
/* Skipping a track takes some time, so turn off music for a while
(otherwise noise can be heard). */
uint8_t music = musicOn;
musicOn = 0;
SFG_nextMusicTrack();
musicOn = music;
}
break;
defaule: break;
}
}
static inline uint8_t mixSamples(uint8_t sample1, uint8_t sample2)
{
return (sample1 >> 1) + (sample2 >> 1);
}
void onTimer() // for sound
{
if (Chip_TIMER_MatchPending(LPC_TIMER32_0, 1))
{
Chip_TIMER_ClearMatch(LPC_TIMER32_0, 1);
Pokitto::dac_write(
musicOn ?
mixSamples(audioBuff[audioPos],SFG_getNextMusicSample() / 2) :
audioBuff[audioPos]
);
audioBuff[audioPos] = 127;
audioPos = (audioPos + 1) % SFG_SFX_SAMPLE_COUNT;
}
}
void timerInit(uint32_t samplingRate)
{
Chip_TIMER_Init(LPC_TIMER32_0);
Chip_TIMER_Reset(LPC_TIMER32_0);
Chip_TIMER_MatchEnableInt(LPC_TIMER32_0, 1);
Chip_TIMER_SetMatch(LPC_TIMER32_0, 1,
(Chip_Clock_GetSystemClockRate() / samplingRate));
Chip_TIMER_ResetOnMatchEnable(LPC_TIMER32_0, 1);
Chip_TIMER_Enable(LPC_TIMER32_0);
#define weirdNumber ((IRQn_Type) 18)
NVIC_ClearPendingIRQ(weirdNumber);
NVIC_SetVector(weirdNumber, (uint32_t) &onTimer);
NVIC_EnableIRQ(weirdNumber);
#undef weirdNumber
}
void SFG_save(uint8_t data[SFG_SAVE_SIZE])
{
for (uint8_t i = 0; i < SFG_SAVE_SIZE; ++i)
save.data[i] = data[i];
save.saveCookie();
/* ^ This causes sound to stop as it writes something to timer32, we need to
reinit the audio: */
timerInit(8000);
}
void SFG_processEvent(uint8_t event, uint8_t data)
{
#ifdef JOYHAT
switch (event)
{
case SFG_EVENT_VIBRATE:
if (rumbleCooldown == 0)
{
joy.Rumble(0.025);
rumbleCooldown = 32;
}
break;
default: break;
}
#endif
}
uint8_t SFG_load(uint8_t data[SFG_SAVE_SIZE])
{
for (uint8_t i = 0; i < SFG_SAVE_SIZE; ++i)
data[i] = save.data[i];
return 1;
}
void SFG_playSound(uint8_t soundIndex, uint8_t volume)
{
uint8_t volumeShift = 7 - volume / 32;
uint16_t baseLevel = 128 - (128 >> volumeShift);
uint16_t pos = audioPos;
for (int i = 0; i < SFG_SFX_SAMPLE_COUNT; ++i)
{
audioBuff[pos] = mixSamples(audioBuff[pos],baseLevel +
(SFG_GET_SFX_SAMPLE(soundIndex,i) >> volumeShift));
pos = (pos < SFG_SFX_SAMPLE_COUNT - 1) ? (pos + 1) : 0;
}
}
int main()
{
save.begin("ANARCH",sizeof(save),(char*) &save);
pokitto.begin();
#ifdef JOYHAT
axisThreshold1 = joy.joyScale / 4;
axisThreshold2 = joy.joyScale - axisThreshold1;
#endif
uint8_t allZeros = 1;
for (uint8_t i = 0; i < SFG_SAVE_SIZE; ++i)
if (save.data[i] != 0)
{
allZeros = 0;
break;
}
if (allZeros) // 1st time save?
{
SFG_createDefaultSaveData(save.data);
save.saveCookie();
}
timerInit(8000);
for (uint16_t i = 0; i < SFG_SFX_SAMPLE_COUNT; ++i)
audioBuff[i] = 127;
pokitto.setFrameRate(255);
pokitto.display.setFont(fontTiny);
pokitto.display.persistence = 1;
pokitto.display.setInvisibleColor(-1);
pokitto.display.load565Palette(paletteRGB565);
pokittoScreen = pokitto.display.screenbuffer;
SFG_init();
while (pokitto.isRunning())
{
if (pokitto.update())
SFG_mainLoopBody();
#ifdef JOYHAT
if (rumbleCooldown > 0)
rumbleCooldown--;
#endif
if (SFG_game.state == SFG_GAME_STATE_MENU &&
SFG_game.keyStates[SFG_KEY_LEFT] == 255 &&
SFG_game.keyStates[SFG_KEY_RIGHT] == 255 &&
SFG_game.keyStates[SFG_KEY_B] == 255)
{
// holding L+R+B in menu will erase all saved data
save.deleteCookie();
pokitto.quit();
}
#if 0
pokitto.display.setCursor(0,0);
pokitto.display.print(pokitto.fps_counter);
#endif
}
return 0;
}