2022-05-19 01:51:26 -07:00
|
|
|
#include "cycle.h"
|
|
|
|
|
|
|
|
#include "color.h"
|
|
|
|
#include "game_config.h"
|
2022-10-04 23:23:27 -07:00
|
|
|
#include "input.h"
|
2022-05-19 01:51:26 -07:00
|
|
|
#include "palette.h"
|
2022-10-05 00:35:05 -07:00
|
|
|
#include "svga.h"
|
2022-05-19 01:51:26 -07:00
|
|
|
|
2022-09-23 05:43:44 -07:00
|
|
|
namespace fallout {
|
|
|
|
|
2022-06-18 06:09:35 -07:00
|
|
|
#define COLOR_CYCLE_PERIOD_1 (200U)
|
|
|
|
#define COLOR_CYCLE_PERIOD_2 (142U)
|
|
|
|
#define COLOR_CYCLE_PERIOD_3 (100U)
|
|
|
|
#define COLOR_CYCLE_PERIOD_4 (33U)
|
|
|
|
|
2022-05-19 01:51:26 -07:00
|
|
|
// 0x51843C
|
2022-06-18 06:09:35 -07:00
|
|
|
static int gColorCycleSpeedFactor = 1;
|
2022-05-19 01:51:26 -07:00
|
|
|
|
|
|
|
// TODO: Convert colors to RGB.
|
|
|
|
// clang-format off
|
|
|
|
|
|
|
|
// Green.
|
|
|
|
//
|
|
|
|
// 0x518440
|
2022-06-18 06:09:35 -07:00
|
|
|
static unsigned char _slime[12] = {
|
2022-05-19 01:51:26 -07:00
|
|
|
0, 108, 0,
|
|
|
|
11, 115, 7,
|
|
|
|
27, 123, 15,
|
|
|
|
43, 131, 27,
|
|
|
|
};
|
|
|
|
|
|
|
|
// Light gray?
|
|
|
|
//
|
|
|
|
// 0x51844C
|
2022-06-18 06:09:35 -07:00
|
|
|
static unsigned char _shoreline[18] = {
|
2022-05-19 01:51:26 -07:00
|
|
|
83, 63, 43,
|
|
|
|
75, 59, 43,
|
|
|
|
67, 55, 39,
|
|
|
|
63, 51, 39,
|
|
|
|
55, 47, 35,
|
|
|
|
51, 43, 35,
|
|
|
|
};
|
|
|
|
|
|
|
|
// Orange.
|
|
|
|
//
|
|
|
|
// 0x51845E
|
2022-06-18 06:09:35 -07:00
|
|
|
static unsigned char _fire_slow[15] = {
|
2022-05-19 01:51:26 -07:00
|
|
|
255, 0, 0,
|
|
|
|
215, 0, 0,
|
|
|
|
147, 43, 11,
|
|
|
|
255, 119, 0,
|
|
|
|
255, 59, 0,
|
|
|
|
};
|
|
|
|
|
|
|
|
// Red.
|
|
|
|
//
|
|
|
|
// 0x51846D
|
2022-06-18 06:09:35 -07:00
|
|
|
static unsigned char _fire_fast[15] = {
|
2022-05-19 01:51:26 -07:00
|
|
|
71, 0, 0,
|
|
|
|
123, 0, 0,
|
|
|
|
179, 0, 0,
|
|
|
|
123, 0, 0,
|
|
|
|
71, 0, 0,
|
|
|
|
};
|
|
|
|
|
|
|
|
// Light blue.
|
|
|
|
//
|
|
|
|
// 0x51847C
|
2022-06-18 06:09:35 -07:00
|
|
|
static unsigned char _monitors[15] = {
|
2022-05-19 01:51:26 -07:00
|
|
|
107, 107, 111,
|
|
|
|
99, 103, 127,
|
|
|
|
87, 107, 143,
|
|
|
|
0, 147, 163,
|
|
|
|
107, 187, 255,
|
|
|
|
};
|
|
|
|
|
|
|
|
// clang-format on
|
|
|
|
|
|
|
|
// 0x51848C
|
2022-06-18 06:09:35 -07:00
|
|
|
static bool gColorCycleInitialized = false;
|
2022-05-19 01:51:26 -07:00
|
|
|
|
|
|
|
// 0x518490
|
2022-06-18 06:09:35 -07:00
|
|
|
static bool gColorCycleEnabled = false;
|
2022-05-19 01:51:26 -07:00
|
|
|
|
|
|
|
// 0x518494
|
2022-06-18 06:09:35 -07:00
|
|
|
static int _slime_start = 0;
|
2022-05-19 01:51:26 -07:00
|
|
|
|
|
|
|
// 0x518498
|
2022-06-18 06:09:35 -07:00
|
|
|
static int _shoreline_start = 0;
|
2022-05-19 01:51:26 -07:00
|
|
|
|
|
|
|
// 0x51849C
|
2022-06-18 06:09:35 -07:00
|
|
|
static int _fire_slow_start = 0;
|
2022-05-19 01:51:26 -07:00
|
|
|
|
|
|
|
// 0x5184A0
|
2022-06-18 06:09:35 -07:00
|
|
|
static int _fire_fast_start = 0;
|
2022-05-19 01:51:26 -07:00
|
|
|
|
|
|
|
// 0x5184A4
|
2022-06-18 06:09:35 -07:00
|
|
|
static int _monitors_start = 0;
|
2022-05-19 01:51:26 -07:00
|
|
|
|
|
|
|
// 0x5184A8
|
2022-06-18 06:09:35 -07:00
|
|
|
static unsigned char _bobber_red = 0;
|
2022-05-19 01:51:26 -07:00
|
|
|
|
|
|
|
// 0x5184A9
|
2022-06-18 06:09:35 -07:00
|
|
|
static signed char _bobber_diff = -4;
|
2022-05-19 01:51:26 -07:00
|
|
|
|
|
|
|
// 0x56D7D0
|
2022-06-18 06:09:35 -07:00
|
|
|
static unsigned int gColorCycleTimestamp3;
|
2022-05-19 01:51:26 -07:00
|
|
|
|
|
|
|
// 0x56D7D4
|
2022-06-18 06:09:35 -07:00
|
|
|
static unsigned int gColorCycleTimestamp1;
|
2022-05-19 01:51:26 -07:00
|
|
|
|
|
|
|
// 0x56D7D8
|
2022-06-18 06:09:35 -07:00
|
|
|
static unsigned int gColorCycleTimestamp2;
|
2022-05-19 01:51:26 -07:00
|
|
|
|
|
|
|
// 0x56D7DC
|
2022-06-18 06:09:35 -07:00
|
|
|
static unsigned int gColorCycleTimestamp4;
|
2022-05-19 01:51:26 -07:00
|
|
|
|
|
|
|
// 0x42E780
|
|
|
|
void colorCycleInit()
|
|
|
|
{
|
|
|
|
if (gColorCycleInitialized) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool colorCycling;
|
|
|
|
if (!configGetBool(&gGameConfig, GAME_CONFIG_SYSTEM_KEY, GAME_CONFIG_COLOR_CYCLING_KEY, &colorCycling)) {
|
|
|
|
colorCycling = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!colorCycling) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (int index = 0; index < 12; index++) {
|
|
|
|
_slime[index] >>= 2;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (int index = 0; index < 18; index++) {
|
|
|
|
_shoreline[index] >>= 2;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (int index = 0; index < 15; index++) {
|
|
|
|
_fire_slow[index] >>= 2;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (int index = 0; index < 15; index++) {
|
|
|
|
_fire_fast[index] >>= 2;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (int index = 0; index < 15; index++) {
|
|
|
|
_monitors[index] >>= 2;
|
|
|
|
}
|
|
|
|
|
|
|
|
tickersAdd(colorCycleTicker);
|
|
|
|
|
|
|
|
gColorCycleInitialized = true;
|
|
|
|
gColorCycleEnabled = true;
|
|
|
|
|
|
|
|
int cycleSpeedFactor;
|
|
|
|
if (!configGetInt(&gGameConfig, GAME_CONFIG_SYSTEM_KEY, GAME_CONFIG_CYCLE_SPEED_FACTOR_KEY, &cycleSpeedFactor)) {
|
|
|
|
cycleSpeedFactor = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
cycleSetSpeedFactor(cycleSpeedFactor);
|
|
|
|
}
|
|
|
|
|
|
|
|
// 0x42E8CC
|
|
|
|
void colorCycleReset()
|
|
|
|
{
|
|
|
|
if (gColorCycleInitialized) {
|
|
|
|
gColorCycleTimestamp1 = 0;
|
|
|
|
gColorCycleTimestamp2 = 0;
|
|
|
|
gColorCycleTimestamp3 = 0;
|
|
|
|
gColorCycleTimestamp4 = 0;
|
|
|
|
tickersAdd(colorCycleTicker);
|
|
|
|
gColorCycleEnabled = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// 0x42E90C
|
|
|
|
void colorCycleFree()
|
|
|
|
{
|
|
|
|
if (gColorCycleInitialized) {
|
|
|
|
tickersRemove(colorCycleTicker);
|
|
|
|
gColorCycleInitialized = false;
|
|
|
|
gColorCycleEnabled = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// 0x42E930
|
|
|
|
void colorCycleDisable()
|
|
|
|
{
|
|
|
|
gColorCycleEnabled = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// 0x42E93C
|
|
|
|
void colorCycleEnable()
|
|
|
|
{
|
|
|
|
gColorCycleEnabled = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// 0x42E948
|
|
|
|
bool colorCycleEnabled()
|
|
|
|
{
|
|
|
|
return gColorCycleEnabled;
|
|
|
|
}
|
|
|
|
|
|
|
|
// 0x42E950
|
|
|
|
void cycleSetSpeedFactor(int value)
|
|
|
|
{
|
|
|
|
gColorCycleSpeedFactor = value;
|
|
|
|
configSetInt(&gGameConfig, GAME_CONFIG_SYSTEM_KEY, GAME_CONFIG_CYCLE_SPEED_FACTOR_KEY, value);
|
|
|
|
}
|
|
|
|
|
|
|
|
// 0x42E97C
|
|
|
|
void colorCycleTicker()
|
|
|
|
{
|
|
|
|
if (!gColorCycleEnabled) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool changed = false;
|
|
|
|
|
|
|
|
unsigned char* palette = _getSystemPalette();
|
2022-10-05 00:11:47 -07:00
|
|
|
unsigned int time = getTicks();
|
2022-05-19 01:51:26 -07:00
|
|
|
|
|
|
|
if (getTicksBetween(time, gColorCycleTimestamp1) >= COLOR_CYCLE_PERIOD_1 * gColorCycleSpeedFactor) {
|
|
|
|
changed = true;
|
|
|
|
gColorCycleTimestamp1 = time;
|
|
|
|
|
|
|
|
int paletteIndex = 229 * 3;
|
|
|
|
|
|
|
|
for (int index = _slime_start; index < 12; index++) {
|
|
|
|
palette[paletteIndex++] = _slime[index];
|
|
|
|
}
|
|
|
|
|
|
|
|
for (int index = 0; index < _slime_start; index++) {
|
|
|
|
palette[paletteIndex++] = _slime[index];
|
|
|
|
}
|
|
|
|
|
|
|
|
_slime_start -= 3;
|
|
|
|
if (_slime_start < 0) {
|
|
|
|
_slime_start = 9;
|
|
|
|
}
|
|
|
|
|
|
|
|
paletteIndex = 248 * 3;
|
|
|
|
|
|
|
|
for (int index = _shoreline_start; index < 18; index++) {
|
|
|
|
palette[paletteIndex++] = _shoreline[index];
|
|
|
|
}
|
|
|
|
|
|
|
|
for (int index = 0; index < _shoreline_start; index++) {
|
|
|
|
palette[paletteIndex++] = _shoreline[index];
|
|
|
|
}
|
|
|
|
|
|
|
|
_shoreline_start -= 3;
|
|
|
|
if (_shoreline_start < 0) {
|
|
|
|
_shoreline_start = 15;
|
|
|
|
}
|
|
|
|
|
|
|
|
paletteIndex = 238 * 3;
|
|
|
|
|
|
|
|
for (int index = _fire_slow_start; index < 15; index++) {
|
|
|
|
palette[paletteIndex++] = _fire_slow[index];
|
|
|
|
}
|
|
|
|
|
|
|
|
for (int index = 0; index < _fire_slow_start; index++) {
|
|
|
|
palette[paletteIndex++] = _fire_slow[index];
|
|
|
|
}
|
|
|
|
|
|
|
|
_fire_slow_start -= 3;
|
|
|
|
if (_fire_slow_start < 0) {
|
|
|
|
_fire_slow_start = 12;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (getTicksBetween(time, gColorCycleTimestamp2) >= COLOR_CYCLE_PERIOD_2 * gColorCycleSpeedFactor) {
|
|
|
|
changed = true;
|
|
|
|
gColorCycleTimestamp2 = time;
|
|
|
|
|
|
|
|
int paletteIndex = 243 * 3;
|
|
|
|
|
|
|
|
for (int index = _fire_fast_start; index < 15; index++) {
|
|
|
|
palette[paletteIndex++] = _fire_fast[index];
|
|
|
|
}
|
|
|
|
|
|
|
|
for (int index = 0; index < _fire_fast_start; index++) {
|
|
|
|
palette[paletteIndex++] = _fire_fast[index];
|
|
|
|
}
|
|
|
|
|
|
|
|
_fire_fast_start -= 3;
|
|
|
|
if (_fire_fast_start < 0) {
|
|
|
|
_fire_fast_start = 12;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (getTicksBetween(time, gColorCycleTimestamp3) >= COLOR_CYCLE_PERIOD_3 * gColorCycleSpeedFactor) {
|
|
|
|
changed = true;
|
|
|
|
gColorCycleTimestamp3 = time;
|
|
|
|
|
|
|
|
int paletteIndex = 233 * 3;
|
|
|
|
|
|
|
|
for (int index = _monitors_start; index < 15; index++) {
|
|
|
|
palette[paletteIndex++] = _monitors[index];
|
|
|
|
}
|
|
|
|
|
|
|
|
for (int index = 0; index < _monitors_start; index++) {
|
|
|
|
palette[paletteIndex++] = _monitors[index];
|
|
|
|
}
|
|
|
|
|
|
|
|
_monitors_start -= 3;
|
|
|
|
|
|
|
|
if (_monitors_start < 0) {
|
|
|
|
_monitors_start = 12;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (getTicksBetween(time, gColorCycleTimestamp4) >= COLOR_CYCLE_PERIOD_4 * gColorCycleSpeedFactor) {
|
|
|
|
changed = true;
|
|
|
|
gColorCycleTimestamp4 = time;
|
|
|
|
|
|
|
|
if (_bobber_red == 0 || _bobber_red == 60) {
|
|
|
|
_bobber_diff = -_bobber_diff;
|
|
|
|
}
|
|
|
|
|
|
|
|
_bobber_red += _bobber_diff;
|
|
|
|
|
|
|
|
int paletteIndex = 254 * 3;
|
|
|
|
palette[paletteIndex++] = _bobber_red;
|
|
|
|
palette[paletteIndex++] = 0;
|
|
|
|
palette[paletteIndex++] = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (changed) {
|
|
|
|
paletteSetEntriesInRange(palette + 229 * 3, 229, 255);
|
|
|
|
}
|
|
|
|
}
|
2022-09-23 05:43:44 -07:00
|
|
|
|
|
|
|
} // namespace fallout
|