Import blues from 436ab46f
This commit is contained in:
parent
b0274d5ce2
commit
d4b94bbc15
2
Makefile
2
Makefile
|
@ -37,7 +37,7 @@ game_p2.o: $(P2_SRCS:.c=.o)
|
||||||
ld -r -o $@ $^
|
ld -r -o $@ $^
|
||||||
objcopy --localize-hidden $@
|
objcopy --localize-hidden $@
|
||||||
|
|
||||||
blues: main.o sys_sdl2.o util.o game_bb.o game_ja.o game_p2.o
|
blues: main.o mixer.o sys_sdl2.o util.o game_bb.o game_ja.o game_p2.o
|
||||||
$(CC) $(LDFLAGS) -o $@ $^ $(SDL_LIBS) $(MODPLUG_LIBS)
|
$(CC) $(LDFLAGS) -o $@ $^ $(SDL_LIBS) $(MODPLUG_LIBS)
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
|
|
14
bb/game.c
14
bb/game.c
|
@ -266,7 +266,7 @@ static void do_inter_screen() {
|
||||||
fade_out_palette();
|
fade_out_palette();
|
||||||
}
|
}
|
||||||
|
|
||||||
void game_main() {
|
static void game_run() {
|
||||||
play_music(0);
|
play_music(0);
|
||||||
screen_init();
|
screen_init();
|
||||||
g_vars.start_level = 0;
|
g_vars.start_level = 0;
|
||||||
|
@ -351,15 +351,11 @@ void game_main() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void game_run(const char *data_path) {
|
|
||||||
res_init(data_path, GAME_SCREEN_W * GAME_SCREEN_H);
|
|
||||||
sound_init();
|
|
||||||
game_main();
|
|
||||||
sound_fini();
|
|
||||||
res_fini();
|
|
||||||
}
|
|
||||||
|
|
||||||
EXPORT_SYMBOL struct game_t game_bb = {
|
EXPORT_SYMBOL struct game_t game_bb = {
|
||||||
"Blues Brothers",
|
"Blues Brothers",
|
||||||
|
res_init,
|
||||||
|
res_fini,
|
||||||
|
sound_init,
|
||||||
|
sound_fini,
|
||||||
game_run
|
game_run
|
||||||
};
|
};
|
||||||
|
|
|
@ -203,7 +203,6 @@ extern uint8_t *level_tilesdata_1e8c[];
|
||||||
|
|
||||||
/* game.c */
|
/* game.c */
|
||||||
extern void update_input();
|
extern void update_input();
|
||||||
extern void game_main();
|
|
||||||
|
|
||||||
/* level.c */
|
/* level.c */
|
||||||
extern void load_level_data(int num);
|
extern void load_level_data(int num);
|
||||||
|
|
66
bb/sound.c
66
bb/sound.c
|
@ -1,11 +1,9 @@
|
||||||
|
|
||||||
#include "game.h"
|
#include "game.h"
|
||||||
#include "resource.h"
|
#include "resource.h"
|
||||||
#include "sys.h"
|
#include "mixer.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
||||||
#include <libmodplug/modplug.h>
|
|
||||||
|
|
||||||
#define PAULA_FREQ 3546897
|
#define PAULA_FREQ 3546897
|
||||||
|
|
||||||
static const struct {
|
static const struct {
|
||||||
|
@ -40,17 +38,6 @@ static const char *_modules[] = {
|
||||||
"shot", "mod.shot"
|
"shot", "mod.shot"
|
||||||
};
|
};
|
||||||
|
|
||||||
struct mixerchannel_t {
|
|
||||||
uint8_t *data;
|
|
||||||
uint32_t pos;
|
|
||||||
uint32_t step;
|
|
||||||
uint32_t size;
|
|
||||||
};
|
|
||||||
|
|
||||||
static const int _rate = SYS_AUDIO_FREQ;
|
|
||||||
static struct mixerchannel_t _channel;
|
|
||||||
static ModPlugFile *_mpf;
|
|
||||||
|
|
||||||
static uint8_t *load_file(const char *filename, int *size, uint8_t *buffer) {
|
static uint8_t *load_file(const char *filename, int *size, uint8_t *buffer) {
|
||||||
FILE *fp = fopen_nocase(g_res.datapath, filename);
|
FILE *fp = fopen_nocase(g_res.datapath, filename);
|
||||||
if (!fp) {
|
if (!fp) {
|
||||||
|
@ -76,63 +63,19 @@ static uint8_t *load_file(const char *filename, int *size, uint8_t *buffer) {
|
||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void mix(void *param, uint8_t *buf, int len) {
|
|
||||||
memset(buf, 0, len);
|
|
||||||
if (_mpf) {
|
|
||||||
const int count = ModPlug_Read(_mpf, buf, len);
|
|
||||||
if (count == 0) {
|
|
||||||
ModPlug_SeekOrder(_mpf, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (_channel.data) {
|
|
||||||
for (int i = 0; i < len; i += sizeof(int16_t)) {
|
|
||||||
const int pos = _channel.pos >> 16;
|
|
||||||
if (pos >= _channel.size) {
|
|
||||||
_channel.data = 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
const int sample = *(int16_t *)(buf + i) + ((int8_t)_channel.data[pos]) * 256;
|
|
||||||
*(int16_t *)(buf + i) = (sample < -32768 ? -32768 : (sample > 32767 ? 32767 : sample));
|
|
||||||
_channel.pos += _channel.step;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void sound_init() {
|
void sound_init() {
|
||||||
ModPlug_Settings mp_settings;
|
|
||||||
memset(&mp_settings, 0, sizeof(mp_settings));
|
|
||||||
ModPlug_GetSettings(&mp_settings);
|
|
||||||
mp_settings.mFlags = MODPLUG_ENABLE_OVERSAMPLING | MODPLUG_ENABLE_NOISE_REDUCTION;
|
|
||||||
mp_settings.mChannels = 1;
|
|
||||||
mp_settings.mBits = 16;
|
|
||||||
mp_settings.mFrequency = _rate;
|
|
||||||
mp_settings.mResamplingMode = MODPLUG_RESAMPLE_FIR;
|
|
||||||
mp_settings.mLoopCount = -1;
|
|
||||||
ModPlug_SetSettings(&mp_settings);
|
|
||||||
g_sys.start_audio(mix, 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void sound_fini() {
|
void sound_fini() {
|
||||||
g_sys.stop_audio();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void play_sound(int num) {
|
void play_sound(int num) {
|
||||||
if (g_res.snd) {
|
if (g_res.snd) {
|
||||||
g_sys.lock_audio();
|
g_mix.play_sound(g_res.snd + _sounds_amiga[num].offset * 2, _sounds_amiga[num].size, PAULA_FREQ / 0x358, 0);
|
||||||
_channel.data = g_res.snd + _sounds_amiga[num].offset * 2;
|
|
||||||
_channel.pos = 0;
|
|
||||||
_channel.step = ((PAULA_FREQ / 0x358) << 16) / _rate;
|
|
||||||
_channel.size = _sounds_amiga[num].size;
|
|
||||||
g_sys.unlock_audio();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void play_music(int num) {
|
void play_music(int num) {
|
||||||
g_sys.lock_audio();
|
|
||||||
if (_mpf) {
|
|
||||||
ModPlug_Unload(_mpf);
|
|
||||||
_mpf = 0;
|
|
||||||
}
|
|
||||||
const char *filename = _modules[num * 2]; // Amiga
|
const char *filename = _modules[num * 2]; // Amiga
|
||||||
int size = 0;
|
int size = 0;
|
||||||
uint8_t *buf = load_file(filename, &size, 0);
|
uint8_t *buf = load_file(filename, &size, 0);
|
||||||
|
@ -167,16 +110,15 @@ void play_music(int num) {
|
||||||
size += samples[i].size;
|
size += samples[i].size;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_mpf = ModPlug_Load(buf, size);
|
g_mix.play_music(buf, size);
|
||||||
free(buf);
|
free(buf);
|
||||||
}
|
}
|
||||||
} else { // ExoticA
|
} else { // ExoticA
|
||||||
filename = _modules[num * 2 + 1];
|
filename = _modules[num * 2 + 1];
|
||||||
buf = load_file(filename, &size, 0);
|
buf = load_file(filename, &size, 0);
|
||||||
if (buf) {
|
if (buf) {
|
||||||
_mpf = ModPlug_Load(buf, size);
|
g_mix.play_music(buf, size);
|
||||||
free(buf);
|
free(buf);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
g_sys.unlock_audio();
|
|
||||||
}
|
}
|
||||||
|
|
6
intern.h
6
intern.h
|
@ -63,7 +63,11 @@ struct options_t {
|
||||||
|
|
||||||
struct game_t {
|
struct game_t {
|
||||||
const char *name;
|
const char *name;
|
||||||
void (*run)(const char *data_path);
|
void (*res_init)(const char *data_path, int vga_size);
|
||||||
|
void (*res_fini)();
|
||||||
|
void (*snd_init)();
|
||||||
|
void (*snd_fini)();
|
||||||
|
void (*run)();
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
|
|
16
ja/game.c
16
ja/game.c
|
@ -309,7 +309,7 @@ void do_game_win_screen() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void game_main() {
|
static void game_run() {
|
||||||
play_music(0);
|
play_music(0);
|
||||||
do_splash_screen();
|
do_splash_screen();
|
||||||
g_sys.set_screen_palette(common_palette_data, 0, 128, 6);
|
g_sys.set_screen_palette(common_palette_data, 0, 128, 6);
|
||||||
|
@ -343,15 +343,11 @@ void game_main() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void game_run(const char *data_path) {
|
|
||||||
res_init(data_path, GAME_SCREEN_W * GAME_SCREEN_H);
|
|
||||||
sound_init();
|
|
||||||
game_main();
|
|
||||||
sound_fini();
|
|
||||||
res_fini();
|
|
||||||
}
|
|
||||||
|
|
||||||
EXPORT_SYMBOL struct game_t game_ja = {
|
EXPORT_SYMBOL struct game_t game_ja = {
|
||||||
"Blues Brothers : Jukebox Adventure",
|
"Blues Brothers: Jukebox Adventure",
|
||||||
|
res_init,
|
||||||
|
res_fini,
|
||||||
|
sound_init,
|
||||||
|
sound_fini,
|
||||||
game_run
|
game_run
|
||||||
};
|
};
|
||||||
|
|
|
@ -199,7 +199,6 @@ extern const uint8_t *player_anim_table[];
|
||||||
|
|
||||||
/* game.c */
|
/* game.c */
|
||||||
extern void update_input();
|
extern void update_input();
|
||||||
extern void game_main();
|
|
||||||
extern void do_game_over_screen();
|
extern void do_game_over_screen();
|
||||||
extern void do_game_win_screen();
|
extern void do_game_win_screen();
|
||||||
extern void do_difficulty_screen();
|
extern void do_difficulty_screen();
|
||||||
|
|
83
ja/sound.c
83
ja/sound.c
|
@ -1,11 +1,9 @@
|
||||||
|
|
||||||
#include "game.h"
|
#include "game.h"
|
||||||
#include "resource.h"
|
#include "resource.h"
|
||||||
#include "sys.h"
|
#include "mixer.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
||||||
#include <libmodplug/modplug.h>
|
|
||||||
|
|
||||||
#define MAX_SOUNDS 16
|
#define MAX_SOUNDS 16
|
||||||
|
|
||||||
static const char *_modules[] = {
|
static const char *_modules[] = {
|
||||||
|
@ -16,63 +14,25 @@ static const char *_modules[] = {
|
||||||
"shoot.mod"
|
"shoot.mod"
|
||||||
};
|
};
|
||||||
|
|
||||||
struct mixerchannel_t {
|
|
||||||
uint8_t *data;
|
|
||||||
uint32_t pos;
|
|
||||||
uint32_t step;
|
|
||||||
uint32_t size;
|
|
||||||
const int8_t *seq;
|
|
||||||
};
|
|
||||||
|
|
||||||
static struct {
|
static struct {
|
||||||
uint16_t offset;
|
uint16_t offset;
|
||||||
uint16_t size;
|
uint16_t size;
|
||||||
} _samples[MAX_SOUNDS];
|
} _samples[MAX_SOUNDS];
|
||||||
|
|
||||||
static const int _rate = SYS_AUDIO_FREQ;
|
static const int8_t *_seq;
|
||||||
static struct mixerchannel_t _channel;
|
|
||||||
static ModPlugFile *_mpf;
|
|
||||||
|
|
||||||
static void mix(void *param, uint8_t *buf, int len) {
|
static void repeat_sound_cb(const uint8_t **data, uint32_t *size) {
|
||||||
memset(buf, 0, len);
|
const int next = _seq ? *_seq++ : -1;
|
||||||
if (_mpf) {
|
|
||||||
const int count = ModPlug_Read(_mpf, buf, len);
|
|
||||||
if (count == 0) {
|
|
||||||
ModPlug_SeekOrder(_mpf, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (_channel.data) {
|
|
||||||
for (int i = 0; i < len; i += sizeof(int16_t)) {
|
|
||||||
int pos = _channel.pos >> 16;
|
|
||||||
if (pos >= _channel.size) {
|
|
||||||
const int next = _channel.seq ? *_channel.seq++ : -1;
|
|
||||||
if (next < 0) {
|
if (next < 0) {
|
||||||
_channel.data = 0;
|
*data = 0;
|
||||||
break;
|
*size = 0;
|
||||||
}
|
} else {
|
||||||
_channel.data = g_res.samples + _samples[next].offset;
|
*data = g_res.samples + _samples[next].offset;
|
||||||
_channel.pos = pos = 0;
|
*size = _samples[next].size;
|
||||||
_channel.size = _samples[next].size;
|
|
||||||
}
|
|
||||||
const int sample = *(int16_t *)(buf + i) + ((int8_t)_channel.data[pos]) * 256;
|
|
||||||
*(int16_t *)(buf + i) = (sample < -32768 ? -32768 : (sample > 32767 ? 32767 : sample));
|
|
||||||
_channel.pos += _channel.step;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void sound_init() {
|
void sound_init() {
|
||||||
ModPlug_Settings mp_settings;
|
|
||||||
memset(&mp_settings, 0, sizeof(mp_settings));
|
|
||||||
ModPlug_GetSettings(&mp_settings);
|
|
||||||
mp_settings.mFlags = MODPLUG_ENABLE_OVERSAMPLING | MODPLUG_ENABLE_NOISE_REDUCTION;
|
|
||||||
mp_settings.mChannels = 1;
|
|
||||||
mp_settings.mBits = 16;
|
|
||||||
mp_settings.mFrequency = _rate;
|
|
||||||
mp_settings.mResamplingMode = MODPLUG_RESAMPLE_FIR;
|
|
||||||
mp_settings.mLoopCount = -1;
|
|
||||||
ModPlug_SetSettings(&mp_settings);
|
|
||||||
g_sys.start_audio(mix, 0);
|
|
||||||
uint16_t offset = 0;
|
uint16_t offset = 0;
|
||||||
for (int i = 0; i < MAX_SOUNDS; ++i) {
|
for (int i = 0; i < MAX_SOUNDS; ++i) {
|
||||||
const int num = i;
|
const int num = i;
|
||||||
|
@ -83,41 +43,28 @@ void sound_init() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void sound_fini() {
|
void sound_fini() {
|
||||||
g_sys.stop_audio();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void play_sound(int num) {
|
void play_sound(int num) {
|
||||||
assert(num < MAX_SOUNDS);
|
assert(num < MAX_SOUNDS);
|
||||||
const int sample_offset = _samples[num].offset;
|
const int sample_offset = _samples[num].offset;
|
||||||
const int sample_size = _samples[num].size;
|
const int sample_size = _samples[num].size;
|
||||||
print_debug(DBG_MIXER, "sample num %d offset 0x%x size %d", num, sample_offset, sample_size);
|
print_debug(DBG_SOUND, "sample num %d offset 0x%x size %d", num, sample_offset, sample_size);
|
||||||
if (sample_size == 0) {
|
if (sample_size == 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
g_sys.lock_audio();
|
|
||||||
_channel.data = g_res.samples + sample_offset;
|
|
||||||
_channel.pos = 0;
|
|
||||||
_channel.step = (8000 << 16) / _rate;
|
|
||||||
_channel.size = sample_size;
|
|
||||||
if (num == 10) {
|
if (num == 10) {
|
||||||
static const int8_t seq[] = { 10, 10, 10, 6, -1 };
|
static const int8_t seq[] = { 10, 10, 10, 6, -1 };
|
||||||
_channel.seq = seq + 1;
|
_seq = seq + 1;
|
||||||
} else {
|
} else {
|
||||||
_channel.seq = 0;
|
_seq = 0;
|
||||||
}
|
}
|
||||||
g_sys.unlock_audio();
|
g_mix.play_sound(g_res.samples + sample_offset, sample_size, 8000, _seq ? repeat_sound_cb : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void play_music(int num) {
|
void play_music(int num) {
|
||||||
g_sys.lock_audio();
|
|
||||||
if (_mpf) {
|
|
||||||
ModPlug_Unload(_mpf);
|
|
||||||
_mpf = 0;
|
|
||||||
}
|
|
||||||
const int size = load_file(_modules[num]);
|
const int size = load_file(_modules[num]);
|
||||||
_mpf = ModPlug_Load(g_res.tmp, size);
|
if (size != 0) {
|
||||||
if (_mpf) {
|
g_mix.play_music(g_res.tmp, size);
|
||||||
print_debug(DBG_MIXER, "Loaded module '%s'", ModPlug_GetName(_mpf));
|
|
||||||
}
|
}
|
||||||
g_sys.unlock_audio();
|
|
||||||
}
|
}
|
||||||
|
|
23
main.c
23
main.c
|
@ -2,6 +2,7 @@
|
||||||
#include <getopt.h>
|
#include <getopt.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include "sys.h"
|
#include "sys.h"
|
||||||
|
#include "mixer.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
||||||
struct options_t g_options;
|
struct options_t g_options;
|
||||||
|
@ -36,7 +37,7 @@ static struct game_t *detect_game(const char *data_path) {
|
||||||
const char *filename;
|
const char *filename;
|
||||||
uint16_t size;
|
uint16_t size;
|
||||||
} games[] = {
|
} games[] = {
|
||||||
{ &game_bb, "AVTMAG.SQV", 3069 },
|
{ &game_bb, "MAGASIN.BIN", 2560 },
|
||||||
{ &game_ja, "JARDIN.EAT", 24876 },
|
{ &game_ja, "JARDIN.EAT", 24876 },
|
||||||
{ &game_p2, "MOTIF.SQZ", 9396 },
|
{ &game_p2, "MOTIF.SQZ", 9396 },
|
||||||
{ 0, 0, 0 }
|
{ 0, 0, 0 }
|
||||||
|
@ -51,18 +52,6 @@ static struct game_t *detect_game(const char *data_path) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(PSP)
|
|
||||||
/* stubs */
|
|
||||||
void sound_init() {
|
|
||||||
}
|
|
||||||
void sound_fini() {
|
|
||||||
}
|
|
||||||
void play_sound(int num) {
|
|
||||||
}
|
|
||||||
void play_music(int num) {
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
int main(int argc, char *argv[]) {
|
||||||
const char *data_path = DEFAULT_DATA_PATH;
|
const char *data_path = DEFAULT_DATA_PATH;
|
||||||
int scale_factor = DEFAULT_SCALE_FACTOR;
|
int scale_factor = DEFAULT_SCALE_FACTOR;
|
||||||
|
@ -168,7 +157,13 @@ int main(int argc, char *argv[]) {
|
||||||
} else {
|
} else {
|
||||||
g_sys.init();
|
g_sys.init();
|
||||||
g_sys.set_screen_size(GAME_SCREEN_W, GAME_SCREEN_H, game->name, scale_factor, scale_filter, fullscreen);
|
g_sys.set_screen_size(GAME_SCREEN_W, GAME_SCREEN_H, game->name, scale_factor, scale_filter, fullscreen);
|
||||||
game->run(data_path);
|
game->res_init(data_path, GAME_SCREEN_W * GAME_SCREEN_H);
|
||||||
|
game->snd_init();
|
||||||
|
g_mix.init();
|
||||||
|
game->run();
|
||||||
|
g_mix.fini();
|
||||||
|
game->snd_fini();
|
||||||
|
game->res_fini();
|
||||||
g_sys.fini();
|
g_sys.fini();
|
||||||
}
|
}
|
||||||
if (data_path != DEFAULT_DATA_PATH) {
|
if (data_path != DEFAULT_DATA_PATH) {
|
||||||
|
|
|
@ -0,0 +1,94 @@
|
||||||
|
|
||||||
|
#include "mixer.h"
|
||||||
|
#include "sys.h"
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
|
#include <libmodplug/modplug.h>
|
||||||
|
|
||||||
|
struct mixerchannel_t {
|
||||||
|
const uint8_t *data;
|
||||||
|
uint32_t pos;
|
||||||
|
uint32_t step;
|
||||||
|
uint32_t size;
|
||||||
|
mix_repeat_sound_cb repeat_cb;
|
||||||
|
};
|
||||||
|
|
||||||
|
static const int _rate = SYS_AUDIO_FREQ;
|
||||||
|
static struct mixerchannel_t _channel;
|
||||||
|
static ModPlugFile *_mpf;
|
||||||
|
|
||||||
|
static void mix(void *param, uint8_t *buf, int len) {
|
||||||
|
memset(buf, 0, len);
|
||||||
|
if (_mpf) {
|
||||||
|
const int count = ModPlug_Read(_mpf, buf, len);
|
||||||
|
if (count == 0) {
|
||||||
|
ModPlug_SeekOrder(_mpf, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (_channel.data) {
|
||||||
|
for (int i = 0; i < len; i += sizeof(int16_t)) {
|
||||||
|
int pos = _channel.pos >> 16;
|
||||||
|
if (pos >= _channel.size) {
|
||||||
|
_channel.data = 0;
|
||||||
|
if (_channel.repeat_cb) {
|
||||||
|
_channel.repeat_cb(&_channel.data, &_channel.size);
|
||||||
|
}
|
||||||
|
if (!_channel.data) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
_channel.pos = pos = 0;
|
||||||
|
}
|
||||||
|
const int sample = *(int16_t *)(buf + i) + ((int8_t)_channel.data[pos]) * 256;
|
||||||
|
*(int16_t *)(buf + i) = (sample < -32768 ? -32768 : (sample > 32767 ? 32767 : sample));
|
||||||
|
_channel.pos += _channel.step;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void mixer_init() {
|
||||||
|
ModPlug_Settings mp_settings;
|
||||||
|
memset(&mp_settings, 0, sizeof(mp_settings));
|
||||||
|
ModPlug_GetSettings(&mp_settings);
|
||||||
|
mp_settings.mFlags = MODPLUG_ENABLE_OVERSAMPLING | MODPLUG_ENABLE_NOISE_REDUCTION;
|
||||||
|
mp_settings.mChannels = 1;
|
||||||
|
mp_settings.mBits = 16;
|
||||||
|
mp_settings.mFrequency = _rate;
|
||||||
|
mp_settings.mResamplingMode = MODPLUG_RESAMPLE_FIR;
|
||||||
|
mp_settings.mLoopCount = -1;
|
||||||
|
ModPlug_SetSettings(&mp_settings);
|
||||||
|
g_sys.start_audio(mix, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void mixer_fini() {
|
||||||
|
g_sys.stop_audio();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void play_sound(const uint8_t *data, uint32_t size, int freq, mix_repeat_sound_cb repeat_cb) {
|
||||||
|
g_sys.lock_audio();
|
||||||
|
_channel.data = data;
|
||||||
|
_channel.pos = 0;
|
||||||
|
_channel.step = (freq << 16) / _rate;
|
||||||
|
_channel.size = size;
|
||||||
|
_channel.repeat_cb = repeat_cb;
|
||||||
|
g_sys.unlock_audio();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void play_music(const uint8_t *data, uint32_t size) {
|
||||||
|
g_sys.lock_audio();
|
||||||
|
if (_mpf) {
|
||||||
|
ModPlug_Unload(_mpf);
|
||||||
|
_mpf = 0;
|
||||||
|
}
|
||||||
|
_mpf = ModPlug_Load(data, size);
|
||||||
|
if (_mpf) {
|
||||||
|
print_debug(DBG_MIXER, "Loaded module '%s'", ModPlug_GetName(_mpf));
|
||||||
|
}
|
||||||
|
g_sys.unlock_audio();
|
||||||
|
}
|
||||||
|
|
||||||
|
struct mixer_t g_mix = {
|
||||||
|
.init = mixer_init,
|
||||||
|
.fini = mixer_fini,
|
||||||
|
.play_sound = play_sound,
|
||||||
|
.play_music = play_music,
|
||||||
|
};
|
|
@ -0,0 +1,18 @@
|
||||||
|
|
||||||
|
#ifndef MIXER_H__
|
||||||
|
#define MIXER_H__
|
||||||
|
|
||||||
|
#include "intern.h"
|
||||||
|
|
||||||
|
typedef void (*mix_repeat_sound_cb)(const uint8_t **data, uint32_t *size);
|
||||||
|
|
||||||
|
struct mixer_t {
|
||||||
|
void (*init)();
|
||||||
|
void (*fini)();
|
||||||
|
void (*play_sound)(const uint8_t *data, uint32_t size, int freq, mix_repeat_sound_cb repeat_cb);
|
||||||
|
void (*play_music)(const uint8_t *data, uint32_t size);
|
||||||
|
};
|
||||||
|
|
||||||
|
extern struct mixer_t g_mix;
|
||||||
|
|
||||||
|
#endif
|
28
p2/game.c
28
p2/game.c
|
@ -16,10 +16,6 @@ void update_input() {
|
||||||
g_vars.input.key_down = (g_sys.input.direction & INPUT_DIRECTION_DOWN) != 0 ? 0xFF : 0;
|
g_vars.input.key_down = (g_sys.input.direction & INPUT_DIRECTION_DOWN) != 0 ? 0xFF : 0;
|
||||||
g_vars.input.key_space = g_sys.input.space ? 0xFF : 0;
|
g_vars.input.key_space = g_sys.input.space ? 0xFF : 0;
|
||||||
g_vars.input.key_jump = g_sys.input.jump ? 0xFF : 0;
|
g_vars.input.key_jump = g_sys.input.jump ? 0xFF : 0;
|
||||||
|
|
||||||
g_vars.input.keystate[2] = g_sys.input.digit1;
|
|
||||||
g_vars.input.keystate[3] = g_sys.input.digit2;
|
|
||||||
g_vars.input.keystate[4] = g_sys.input.digit3;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void wait_input(int timeout) {
|
static void wait_input(int timeout) {
|
||||||
|
@ -182,9 +178,8 @@ void do_gameover_screen() {
|
||||||
uint8_t *data = load_file("GAMEOVER.SQZ");
|
uint8_t *data = load_file("GAMEOVER.SQZ");
|
||||||
if (data) {
|
if (data) {
|
||||||
video_copy_img(data);
|
video_copy_img(data);
|
||||||
video_copy_background();
|
|
||||||
g_sys.set_screen_palette(gameover_palette_data, 0, 16, 6);
|
g_sys.set_screen_palette(gameover_palette_data, 0, 16, 6);
|
||||||
g_sys.copy_bitmap(g_res.vga, GAME_SCREEN_W, GAME_SCREEN_H);
|
update_screen_img(g_res.background, 0);
|
||||||
do_gameover_animation();
|
do_gameover_animation();
|
||||||
g_sys.fade_out_palette();
|
g_sys.fade_out_palette();
|
||||||
free(data);
|
free(data);
|
||||||
|
@ -214,16 +209,15 @@ static bool do_menu() {
|
||||||
update_screen_img(data + 768, 0);
|
update_screen_img(data + 768, 0);
|
||||||
g_sys.fade_in_palette();
|
g_sys.fade_in_palette();
|
||||||
free(data);
|
free(data);
|
||||||
memset(g_vars.input.keystate, 0, sizeof(g_vars.input.keystate));
|
|
||||||
const uint32_t start = g_sys.get_timestamp();
|
const uint32_t start = g_sys.get_timestamp();
|
||||||
while (!g_sys.input.quit) {
|
while (!g_sys.input.quit) {
|
||||||
update_input();
|
update_input();
|
||||||
if (g_vars.input.keystate[2] || g_vars.input.keystate[0x4F] || g_sys.input.space) {
|
if (g_sys.input.digit1 || g_sys.input.space) {
|
||||||
g_sys.input.space = 0;
|
g_sys.input.space = 0;
|
||||||
g_sys.fade_out_palette();
|
g_sys.fade_out_palette();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (g_vars.input.keystate[3] || g_vars.input.keystate[0x50]) {
|
if (g_sys.input.digit2 || g_vars.input.key_down) {
|
||||||
g_sys.fade_out_palette();
|
g_sys.fade_out_palette();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -241,13 +235,13 @@ static void do_photos_screen() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void input_check_ctrl_alt_e() {
|
void input_check_ctrl_alt_e() {
|
||||||
if (g_vars.input.keystate[0x1D] && g_vars.input.keystate[0x38] && g_vars.input.keystate[0x12]) {
|
if (0) {
|
||||||
do_photos_screen();
|
do_photos_screen();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void input_check_ctrl_alt_w() {
|
void input_check_ctrl_alt_w() {
|
||||||
if (g_vars.input.keystate[0x1D] && g_vars.input.keystate[0x38] && g_vars.input.keystate[0x11]) {
|
if (0) {
|
||||||
do_credits();
|
do_credits();
|
||||||
wait_input(60);
|
wait_input(60);
|
||||||
}
|
}
|
||||||
|
@ -318,9 +312,8 @@ uint16_t random_get_number3(uint16_t x) {
|
||||||
return rol16(x, 3);
|
return rol16(x, 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void game_run(const char *data_path) {
|
static void game_run() {
|
||||||
res_init(data_path, GAME_SCREEN_W * GAME_SCREEN_H);
|
video_init();
|
||||||
sound_init();
|
|
||||||
video_convert_tiles(g_res.uniondat, g_res.unionlen);
|
video_convert_tiles(g_res.uniondat, g_res.unionlen);
|
||||||
g_vars.level_num = g_options.start_level;
|
g_vars.level_num = g_options.start_level;
|
||||||
do_programmed_in_1992_screen();
|
do_programmed_in_1992_screen();
|
||||||
|
@ -359,12 +352,13 @@ static void game_run(const char *data_path) {
|
||||||
print_debug(DBG_GAME, "previous level %d current %d", level_num, g_vars.level_num);
|
print_debug(DBG_GAME, "previous level %d current %d", level_num, g_vars.level_num);
|
||||||
} while (!g_res.dos_demo && g_vars.level_num != level_num);
|
} while (!g_res.dos_demo && g_vars.level_num != level_num);
|
||||||
}
|
}
|
||||||
sound_fini();
|
|
||||||
res_fini();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
EXPORT_SYMBOL struct game_t game_p2 = {
|
EXPORT_SYMBOL struct game_t game_p2 = {
|
||||||
"Prehistorik 2",
|
"Prehistorik 2",
|
||||||
|
res_init,
|
||||||
|
res_fini,
|
||||||
|
sound_init,
|
||||||
|
sound_fini,
|
||||||
game_run
|
game_run
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -119,7 +119,6 @@ struct vars_t {
|
||||||
uint16_t d, e;
|
uint16_t d, e;
|
||||||
} random;
|
} random;
|
||||||
struct {
|
struct {
|
||||||
bool keystate[128];
|
|
||||||
uint8_t key_left, key_right, key_down, key_up, key_space, key_jump;
|
uint8_t key_left, key_right, key_down, key_up, key_space, key_jump;
|
||||||
uint8_t key_vdir, key_hdir;
|
uint8_t key_vdir, key_hdir;
|
||||||
uint16_t demo_offset;
|
uint16_t demo_offset;
|
||||||
|
@ -322,7 +321,6 @@ extern void random_reset();
|
||||||
extern uint8_t random_get_number();
|
extern uint8_t random_get_number();
|
||||||
extern uint16_t random_get_number2();
|
extern uint16_t random_get_number2();
|
||||||
extern uint16_t random_get_number3(uint16_t x);
|
extern uint16_t random_get_number3(uint16_t x);
|
||||||
extern void game_main();
|
|
||||||
|
|
||||||
/* level.c */
|
/* level.c */
|
||||||
extern void do_level();
|
extern void do_level();
|
||||||
|
@ -337,6 +335,7 @@ extern void monster_change_next_anim(struct object_t *obj);
|
||||||
extern void monster_change_prev_anim(struct object_t *obj);
|
extern void monster_change_prev_anim(struct object_t *obj);
|
||||||
|
|
||||||
/* screen.c */
|
/* screen.c */
|
||||||
|
extern void video_init();
|
||||||
extern void video_draw_string(int offset, int hspace, const char *s);
|
extern void video_draw_string(int offset, int hspace, const char *s);
|
||||||
extern void video_clear();
|
extern void video_clear();
|
||||||
extern void video_copy_img(const uint8_t *src);
|
extern void video_copy_img(const uint8_t *src);
|
||||||
|
@ -352,6 +351,7 @@ extern void video_load_front_tiles();
|
||||||
extern void video_transition_close();
|
extern void video_transition_close();
|
||||||
extern void video_transition_open();
|
extern void video_transition_open();
|
||||||
extern void video_load_sprites();
|
extern void video_load_sprites();
|
||||||
|
extern void video_set_sprite_pos_flags(int flag);
|
||||||
extern void video_draw_sprite(int num, int x, int y, int flag);
|
extern void video_draw_sprite(int num, int x, int y, int flag);
|
||||||
extern void video_put_pixel(int x, int y, uint8_t color);
|
extern void video_put_pixel(int x, int y, uint8_t color);
|
||||||
|
|
||||||
|
|
82
p2/level.c
82
p2/level.c
|
@ -12,7 +12,6 @@ static const bool _demo_inputs = false;
|
||||||
|
|
||||||
static const bool _expert = true;
|
static const bool _expert = true;
|
||||||
|
|
||||||
static const bool _redraw_tilemap = true;
|
|
||||||
static const bool _redraw_panel = true;
|
static const bool _redraw_panel = true;
|
||||||
|
|
||||||
static const uint16_t _undefined = 0x55AA;
|
static const uint16_t _undefined = 0x55AA;
|
||||||
|
@ -323,52 +322,24 @@ static void level_update_tilemap() {
|
||||||
} else if (g_vars.level_animated_tiles_current_tbl == g_vars.tile_tbl3) {
|
} else if (g_vars.level_animated_tiles_current_tbl == g_vars.tile_tbl3) {
|
||||||
g_vars.level_animated_tiles_current_tbl = g_vars.tile_tbl1;
|
g_vars.level_animated_tiles_current_tbl = g_vars.tile_tbl1;
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
if (!_redraw_tilemap) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
video_copy_background();
|
video_copy_background();
|
||||||
g_vars.tile_attr2_flags = 0;
|
g_vars.tile_attr2_flags = 0;
|
||||||
uint16_t offset = (g_vars.tilemap.y << 8) | g_vars.tilemap.x;
|
uint16_t offset = (g_vars.tilemap.y << 8) | g_vars.tilemap.x;
|
||||||
for (int y = 0; y < (TILEMAP_SCREEN_H / 16) + 1; ++y) {
|
int tilemap_w = (TILEMAP_SCREEN_W / 16) + 1;
|
||||||
for (int x = 0; x < (TILEMAP_SCREEN_W / 16) + 1; ++x) {
|
int tilemap_h = (TILEMAP_SCREEN_H / 16) + 1;
|
||||||
|
if (g_vars.level_num == 9) { /* minotaur boss expects original screen resolution */
|
||||||
|
offset = 0;
|
||||||
|
tilemap_w = 320 / 16;
|
||||||
|
tilemap_h = (200 - PANEL_H) / 16;
|
||||||
|
}
|
||||||
|
for (int y = 0; y < tilemap_h; ++y) {
|
||||||
|
for (int x = 0; x < tilemap_w; ++x) {
|
||||||
const uint8_t tile_num = level_get_tile(offset + x);
|
const uint8_t tile_num = level_get_tile(offset + x);
|
||||||
g_vars.tile_attr2_flags |= g_res.level.tile_attributes2[tile_num];
|
g_vars.tile_attr2_flags |= g_res.level.tile_attributes2[tile_num];
|
||||||
if (_redraw_tilemap || g_vars.animated_tile_flag_tbl[tile_num] != 0) {
|
|
||||||
const uint8_t num = g_vars.level_animated_tiles_current_tbl[tile_num];
|
const uint8_t num = g_vars.level_animated_tiles_current_tbl[tile_num];
|
||||||
level_draw_tile(num, x, y);
|
level_draw_tile(num, x, y);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
offset += 256;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void level_draw_tilemap() {
|
|
||||||
if (_redraw_tilemap) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (g_vars.tilemap.redraw_flag1 == 0) {
|
|
||||||
const bool changed = (g_vars.tilemap.x != g_vars.tilemap.prev_x) || (g_vars.tilemap.y != g_vars.tilemap.prev_y);
|
|
||||||
if (!changed) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
g_vars.tilemap.prev_x = g_vars.tilemap.x;
|
|
||||||
g_vars.tilemap.prev_y = g_vars.tilemap.y;
|
|
||||||
if (g_vars.tilemap.redraw_flag2 == 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
g_vars.tilemap.redraw_flag1 = 0;
|
|
||||||
g_vars.tilemap.redraw_flag2 = 0;
|
|
||||||
g_vars.tile_attr2_flags = 0;
|
|
||||||
uint16_t offset = (g_vars.tilemap.y << 8) | g_vars.tilemap.x;
|
|
||||||
for (int y = 0; y < (TILEMAP_SCREEN_H / 16) + 1; ++y) {
|
|
||||||
for (int x = 0; x < TILEMAP_SCREEN_W / 16; ++x) {
|
|
||||||
const uint8_t tile_num = level_get_tile(offset + x);
|
|
||||||
g_vars.tile_attr2_flags |= g_res.level.tile_attributes2[tile_num];
|
|
||||||
level_draw_tile(tile_num, x, y);
|
|
||||||
}
|
|
||||||
offset += 256;
|
offset += 256;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -621,7 +592,6 @@ static void level_init_tilemap() {
|
||||||
g_vars.tilemap.redraw_flag2 = 1;
|
g_vars.tilemap.redraw_flag2 = 1;
|
||||||
g_vars.tilemap.prev_x = _undefined;
|
g_vars.tilemap.prev_x = _undefined;
|
||||||
g_vars.tilemap.prev_y = _undefined;
|
g_vars.tilemap.prev_y = _undefined;
|
||||||
level_draw_tilemap();
|
|
||||||
video_transition_open();
|
video_transition_open();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2388,17 +2358,6 @@ static void level_update_player_flying() {
|
||||||
|
|
||||||
static void level_update_player() {
|
static void level_update_player() {
|
||||||
g_vars.objects_tbl[0].spr_num = 0xFFFF;
|
g_vars.objects_tbl[0].spr_num = 0xFFFF;
|
||||||
if (g_vars.input.keystate[0x3B]) {
|
|
||||||
if (g_vars.restart_level_flag == 0) {
|
|
||||||
level_player_die();
|
|
||||||
g_vars.restart_level_flag = 1;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (g_vars.input.keystate[0x3C]) {
|
|
||||||
g_vars.player_death_flag = 1;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
input_check_ctrl_alt_w();
|
input_check_ctrl_alt_w();
|
||||||
if (_demo_inputs) {
|
if (_demo_inputs) {
|
||||||
if (g_vars.input.demo_offset < g_res.keyblen) {
|
if (g_vars.input.demo_offset < g_res.keyblen) {
|
||||||
|
@ -3014,7 +2973,6 @@ static void level_update_gates() {
|
||||||
g_vars.boss_level5.idle_counter = 8;
|
g_vars.boss_level5.idle_counter = 8;
|
||||||
memset(&g_vars.objects_tbl[91], 0xFF, sizeof(struct object_t) * 6);
|
memset(&g_vars.objects_tbl[91], 0xFF, sizeof(struct object_t) * 6);
|
||||||
}
|
}
|
||||||
level_draw_tilemap();
|
|
||||||
level_update_objects_decors();
|
level_update_objects_decors();
|
||||||
level_update_objects_items();
|
level_update_objects_items();
|
||||||
level_update_objects_monsters();
|
level_update_objects_monsters();
|
||||||
|
@ -3267,16 +3225,20 @@ static void level_update_light_palette() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void level_sync() {
|
static void level_wait() {
|
||||||
update_input();
|
update_input();
|
||||||
g_sys.copy_bitmap(g_res.vga, GAME_SCREEN_W, GAME_SCREEN_H);
|
|
||||||
g_sys.update_screen();
|
|
||||||
g_sys.render_clear_sprites();
|
|
||||||
const int diff = (g_vars.timestamp + (1000 / 30)) - g_sys.get_timestamp();
|
const int diff = (g_vars.timestamp + (1000 / 30)) - g_sys.get_timestamp();
|
||||||
g_sys.sleep(MAX(diff, 10));
|
g_sys.sleep(MAX(diff, 10));
|
||||||
g_vars.timestamp = g_sys.get_timestamp();
|
g_vars.timestamp = g_sys.get_timestamp();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void level_sync() {
|
||||||
|
g_sys.copy_bitmap(g_res.vga, GAME_SCREEN_W, GAME_SCREEN_H);
|
||||||
|
g_sys.update_screen();
|
||||||
|
g_sys.render_clear_sprites();
|
||||||
|
level_wait();
|
||||||
|
}
|
||||||
|
|
||||||
static void level_draw_objects() {
|
static void level_draw_objects() {
|
||||||
++g_vars.level_draw_counter;
|
++g_vars.level_draw_counter;
|
||||||
for (int i = OBJECTS_COUNT - 1; i >= 0; --i) {
|
for (int i = OBJECTS_COUNT - 1; i >= 0; --i) {
|
||||||
|
@ -3482,7 +3444,6 @@ static void level_player_death_animation() {
|
||||||
level_update_objects_bonuses();
|
level_update_objects_bonuses();
|
||||||
level_update_objects_bonus_scores();
|
level_update_objects_bonus_scores();
|
||||||
level_update_tilemap();
|
level_update_tilemap();
|
||||||
level_draw_tilemap();
|
|
||||||
level_draw_panel();
|
level_draw_panel();
|
||||||
level_draw_orbs();
|
level_draw_orbs();
|
||||||
level_draw_objects();
|
level_draw_objects();
|
||||||
|
@ -3572,6 +3533,7 @@ static int level_completed_bonuses_animation_helper() {
|
||||||
}
|
}
|
||||||
|
|
||||||
static void level_completed_bonuses_animation() {
|
static void level_completed_bonuses_animation() {
|
||||||
|
video_set_sprite_pos_flags(1); /* center */
|
||||||
if (g_vars.light.state != 0) {
|
if (g_vars.light.state != 0) {
|
||||||
g_vars.light.palette_flag1 = 0;
|
g_vars.light.palette_flag1 = 0;
|
||||||
g_vars.light.palette_flag2 = 1;
|
g_vars.light.palette_flag2 = 1;
|
||||||
|
@ -3728,6 +3690,7 @@ static void level_completed_bonuses_animation() {
|
||||||
g_vars.objects_tbl[1].x_pos += 2;
|
g_vars.objects_tbl[1].x_pos += 2;
|
||||||
}
|
}
|
||||||
} while (g_vars.objects_tbl[2].x_pos > -52);
|
} while (g_vars.objects_tbl[2].x_pos > -52);
|
||||||
|
video_set_sprite_pos_flags(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void update_object_demo_animation(struct object_t *obj) {
|
static void update_object_demo_animation(struct object_t *obj) {
|
||||||
|
@ -3868,6 +3831,7 @@ void do_gameover_animation() {
|
||||||
g_vars.objects_tbl[i].spr_num = 0xFFFF;
|
g_vars.objects_tbl[i].spr_num = 0xFFFF;
|
||||||
}
|
}
|
||||||
video_load_sprites();
|
video_load_sprites();
|
||||||
|
video_set_sprite_pos_flags(1); /* center */
|
||||||
g_vars.tilemap.x = g_vars.tilemap.scroll_dx = 0;
|
g_vars.tilemap.x = g_vars.tilemap.scroll_dx = 0;
|
||||||
g_vars.tilemap.y = g_vars.tilemap.scroll_dy = 0;
|
g_vars.tilemap.y = g_vars.tilemap.scroll_dy = 0;
|
||||||
static const char *gameover = "GAMEOVER";
|
static const char *gameover = "GAMEOVER";
|
||||||
|
@ -3909,11 +3873,14 @@ void do_gameover_animation() {
|
||||||
do_gameover_animation_helper();
|
do_gameover_animation_helper();
|
||||||
level_draw_objects();
|
level_draw_objects();
|
||||||
level_update_panel();
|
level_update_panel();
|
||||||
level_sync();
|
g_sys.update_screen();
|
||||||
|
g_sys.render_clear_sprites();
|
||||||
|
level_wait();
|
||||||
if (g_sys.input.quit) {
|
if (g_sys.input.quit) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} while (timer_counter < 630 && !g_sys.input.space);
|
} while (timer_counter < 630 && !g_sys.input.space);
|
||||||
|
video_set_sprite_pos_flags(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void do_level() {
|
void do_level() {
|
||||||
|
@ -3949,7 +3916,6 @@ void do_level() {
|
||||||
g_vars.tilemap_adjust_player_pos_flag = false;
|
g_vars.tilemap_adjust_player_pos_flag = false;
|
||||||
level_update_scrolling();
|
level_update_scrolling();
|
||||||
level_update_tilemap();
|
level_update_tilemap();
|
||||||
level_draw_tilemap();
|
|
||||||
level_draw_panel();
|
level_draw_panel();
|
||||||
level_draw_orbs();
|
level_draw_orbs();
|
||||||
level_draw_objects();
|
level_draw_objects();
|
||||||
|
|
17
p2/screen.c
17
p2/screen.c
|
@ -11,6 +11,15 @@
|
||||||
#define MAX_SPRITESHEET_H 1024
|
#define MAX_SPRITESHEET_H 1024
|
||||||
#define MAX_FRONT_TILES 168
|
#define MAX_FRONT_TILES 168
|
||||||
|
|
||||||
|
static int _spr_pos_flags;
|
||||||
|
|
||||||
|
static int _offset_x_center, _offset_y_center;
|
||||||
|
|
||||||
|
void video_init() {
|
||||||
|
_offset_x_center = (GAME_SCREEN_W > 320) ? (GAME_SCREEN_W - 320) / 2 : 0;
|
||||||
|
_offset_y_center = (GAME_SCREEN_H > 200) ? (GAME_SCREEN_H - 200) / 2 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
static void decode_planar(const uint8_t *src, uint8_t *dst, int dst_pitch, int w, int h, uint8_t transparent_color) {
|
static void decode_planar(const uint8_t *src, uint8_t *dst, int dst_pitch, int w, int h, uint8_t transparent_color) {
|
||||||
const int plane_size = h * w / 8;
|
const int plane_size = h * w / 8;
|
||||||
for (int y = 0; y < h; ++y) {
|
for (int y = 0; y < h; ++y) {
|
||||||
|
@ -279,7 +288,15 @@ void video_load_sprites() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void video_set_sprite_pos_flags(int flags) {
|
||||||
|
_spr_pos_flags = flags;
|
||||||
|
}
|
||||||
|
|
||||||
void video_draw_sprite(int num, int x, int y, int flag) {
|
void video_draw_sprite(int num, int x, int y, int flag) {
|
||||||
|
if (_spr_pos_flags) {
|
||||||
|
x += _offset_x_center;
|
||||||
|
y += _offset_y_center;
|
||||||
|
}
|
||||||
g_sys.render_add_sprite(RENDER_SPR_GAME, num, x, y, flag != 0);
|
g_sys.render_add_sprite(RENDER_SPR_GAME, num, x, y, flag != 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
86
p2/sound.c
86
p2/sound.c
|
@ -1,31 +1,16 @@
|
||||||
|
|
||||||
#include "game.h"
|
#include "game.h"
|
||||||
#include "resource.h"
|
#include "resource.h"
|
||||||
#include "sys.h"
|
#include "mixer.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
||||||
#include <libmodplug/modplug.h>
|
|
||||||
|
|
||||||
#define MAX_SOUNDS 11
|
#define MAX_SOUNDS 11
|
||||||
|
|
||||||
static const bool _volume = false;
|
|
||||||
|
|
||||||
static const uint16_t sound_sizes_tbl[] = {
|
static const uint16_t sound_sizes_tbl[] = {
|
||||||
0x188E, 0x1C80, 0x235E, 0x19E6, 0x0AB2, 0x0912, 0x0000, 0x35D2,
|
0x188E, 0x1C80, 0x235E, 0x19E6, 0x0AB2, 0x0912, 0x0000, 0x35D2,
|
||||||
0x06C4, 0x1C86, 0x0E2E
|
0x06C4, 0x1C86, 0x0E2E
|
||||||
};
|
};
|
||||||
|
|
||||||
static const uint8_t sound_volume_tbl[] = {
|
|
||||||
0x3F,0x37,0x32,0x2F,0x2C,0x2A,0x28,0x27,0x26,0x24,0x23,0x22,0x21,0x21,0x20,0x1F,
|
|
||||||
0x1E,0x1E,0x1D,0x1C,0x1C,0x1B,0x1B,0x1A,0x1A,0x19,0x19,0x19,0x18,0x18,0x17,0x17,
|
|
||||||
0x17,0x16,0x16,0x16,0x15,0x15,0x15,0x15,0x14,0x14,0x14,0x14,0x13,0x13,0x13,0x13,
|
|
||||||
0x12,0x12,0x12,0x12,0x11,0x11,0x11,0x11,0x11,0x10,0x10,0x10,0x10,0x10,0x0F,0x0F,
|
|
||||||
0x0F,0x0F,0x0F,0x0F,0x0E,0x0E,0x0E,0x0E,0x0E,0x0E,0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,
|
|
||||||
0x0D,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0B,0x0B,0x0B,0x0B,0x0B,0x0B,0x0B,
|
|
||||||
0x0B,0x0A,0x0A,0x0A,0x0A,0x0A,0x0A,0x0A,0x0A,0x0A,0x09,0x09,0x09,0x09,0x09,0x09,
|
|
||||||
0x09,0x09,0x09,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x07,0x07
|
|
||||||
};
|
|
||||||
|
|
||||||
static const char *trk_names_tbl[] = {
|
static const char *trk_names_tbl[] = {
|
||||||
"PRES.TRK",
|
"PRES.TRK",
|
||||||
"CODE.TRK",
|
"CODE.TRK",
|
||||||
|
@ -47,85 +32,35 @@ static const char *trk_names_tbl[] = {
|
||||||
"BOULA.TRK"
|
"BOULA.TRK"
|
||||||
};
|
};
|
||||||
|
|
||||||
struct mixerchannel_t {
|
|
||||||
uint8_t *data;
|
|
||||||
uint32_t pos;
|
|
||||||
uint32_t step;
|
|
||||||
uint32_t size;
|
|
||||||
};
|
|
||||||
|
|
||||||
static const int _rate = SYS_AUDIO_FREQ;
|
|
||||||
static struct mixerchannel_t _channel;
|
|
||||||
static ModPlugFile *_mpf;
|
|
||||||
static int _music_num;
|
static int _music_num;
|
||||||
|
|
||||||
static uint16_t sound_offsets_tbl[MAX_SOUNDS];
|
static uint16_t sound_offsets_tbl[MAX_SOUNDS];
|
||||||
|
|
||||||
static void mix(void *param, uint8_t *buf, int len) {
|
|
||||||
memset(buf, 0, len);
|
|
||||||
if (_mpf) {
|
|
||||||
const int count = ModPlug_Read(_mpf, buf, len);
|
|
||||||
if (count == 0) {
|
|
||||||
ModPlug_SeekOrder(_mpf, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (_channel.data) {
|
|
||||||
for (int i = 0; i < len; i += sizeof(int16_t)) {
|
|
||||||
const int pos = _channel.pos >> 16;
|
|
||||||
if (pos >= _channel.size) {
|
|
||||||
_channel.data = 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
const int8_t pcm = _volume ? sound_volume_tbl[(_channel.data[pos] ^ 0x80) >> 1] : _channel.data[pos];
|
|
||||||
const int sample = *(int16_t *)(buf + i) + pcm * 256;
|
|
||||||
*(int16_t *)(buf + i) = (sample < -32768 ? -32768 : (sample > 32767 ? 32767 : sample));
|
|
||||||
_channel.pos += _channel.step;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void sound_init() {
|
void sound_init() {
|
||||||
ModPlug_Settings mp_settings;
|
|
||||||
memset(&mp_settings, 0, sizeof(mp_settings));
|
|
||||||
ModPlug_GetSettings(&mp_settings);
|
|
||||||
mp_settings.mFlags = MODPLUG_ENABLE_OVERSAMPLING | MODPLUG_ENABLE_NOISE_REDUCTION;
|
|
||||||
mp_settings.mChannels = 1;
|
|
||||||
mp_settings.mBits = 16;
|
|
||||||
mp_settings.mFrequency = _rate;
|
|
||||||
mp_settings.mResamplingMode = MODPLUG_RESAMPLE_FIR;
|
|
||||||
mp_settings.mLoopCount = -1;
|
|
||||||
ModPlug_SetSettings(&mp_settings);
|
|
||||||
uint16_t offset = 0;
|
uint16_t offset = 0;
|
||||||
for (int i = 0; i < MAX_SOUNDS; ++i) {
|
for (int i = 0; i < MAX_SOUNDS; ++i) {
|
||||||
sound_offsets_tbl[i] = offset;
|
sound_offsets_tbl[i] = offset;
|
||||||
offset += sound_sizes_tbl[i];
|
offset += sound_sizes_tbl[i];
|
||||||
}
|
}
|
||||||
_music_num = -1;
|
_music_num = -1;
|
||||||
g_sys.start_audio(mix, 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void sound_fini() {
|
void sound_fini() {
|
||||||
g_sys.stop_audio();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void play_sound(int num) {
|
void play_sound(int num) {
|
||||||
assert(num < MAX_SOUNDS);
|
assert(num < MAX_SOUNDS);
|
||||||
print_debug(DBG_MIXER, "play_sound %d", num);
|
print_debug(DBG_SOUND, "play_sound %d", num);
|
||||||
if (!g_res.samples) { /* no SAMPLE. file with demo */
|
if (!g_res.samples) { /* no SAMPLE. file with demo */
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const int sample_offset = sound_offsets_tbl[num];
|
const int sample_offset = sound_offsets_tbl[num];
|
||||||
const int sample_size = sound_sizes_tbl[num];
|
const int sample_size = sound_sizes_tbl[num];
|
||||||
print_debug(DBG_MIXER, "sample num %d offset 0x%x size %d", num, sample_offset, sample_size);
|
print_debug(DBG_SOUND, "sample num %d offset 0x%x size %d", num, sample_offset, sample_size);
|
||||||
if (sample_size == 0) {
|
if (sample_size == 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
g_sys.lock_audio();
|
g_mix.play_sound(g_res.samples + sample_offset, sample_size, 8000, 0);
|
||||||
_channel.data = g_res.samples + sample_offset;
|
|
||||||
_channel.pos = 0;
|
|
||||||
_channel.step = (8000 << 16) / _rate;
|
|
||||||
_channel.size = sample_size;
|
|
||||||
g_sys.unlock_audio();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void play_music(int num) {
|
void play_music(int num) {
|
||||||
|
@ -137,21 +72,12 @@ void play_music(int num) {
|
||||||
}
|
}
|
||||||
const char *filename = trk_names_tbl[num];
|
const char *filename = trk_names_tbl[num];
|
||||||
if (filename) {
|
if (filename) {
|
||||||
print_debug(DBG_MIXER, "play_music '%s'", filename);
|
print_debug(DBG_SOUND, "play_music '%s'", filename);
|
||||||
g_sys.lock_audio();
|
|
||||||
if (_mpf) {
|
|
||||||
ModPlug_Unload(_mpf);
|
|
||||||
_mpf = 0;
|
|
||||||
}
|
|
||||||
uint8_t *data = load_file(filename);
|
uint8_t *data = load_file(filename);
|
||||||
if (data) {
|
if (data) {
|
||||||
_mpf = ModPlug_Load(data, g_uncompressed_size);
|
g_mix.play_music(data, g_uncompressed_size);
|
||||||
if (_mpf) {
|
|
||||||
print_debug(DBG_MIXER, "Loaded module '%s'", ModPlug_GetName(_mpf));
|
|
||||||
}
|
|
||||||
free(data);
|
free(data);
|
||||||
_music_num = num;
|
_music_num = num;
|
||||||
}
|
}
|
||||||
g_sys.unlock_audio();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
14
util.c
14
util.c
|
@ -73,15 +73,19 @@ FILE *fopen_nocase(const char *path, const char *filename) {
|
||||||
snprintf(buf, sizeof(buf), "%s/%s", path, filename);
|
snprintf(buf, sizeof(buf), "%s/%s", path, filename);
|
||||||
FILE *fp = fopen(buf, "rb");
|
FILE *fp = fopen(buf, "rb");
|
||||||
if (!fp) {
|
if (!fp) {
|
||||||
|
static void (*const str[3])(char *) = {
|
||||||
|
string_upper,
|
||||||
|
string_lower,
|
||||||
|
0
|
||||||
|
};
|
||||||
char *p = buf + strlen(path) + 1;
|
char *p = buf + strlen(path) + 1;
|
||||||
string_upper(p);
|
for (int i = 0; str[i] && !fp; ++i) {
|
||||||
fp = fopen(buf, "rb");
|
(str[i])(p);
|
||||||
if (!fp) {
|
if (strcmp(filename, p) != 0) {
|
||||||
char *p = buf + strlen(path) + 1;
|
|
||||||
string_lower(p);
|
|
||||||
fp = fopen(buf, "rb");
|
fp = fopen(buf, "rb");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return fp;
|
return fp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue