Merge pull request #13 from turol/dos

DOS support with Allegro and DJGPP
This commit is contained in:
ozkl
2024-04-27 17:18:52 +03:00
committed by GitHub
16 changed files with 1402 additions and 35 deletions
+2
View File
@@ -1,8 +1,10 @@
*.o
*.obj
*.exe
*.DS_Store
*.log
*.user
*~
.vs/
Debug/
Release/
+71
View File
@@ -0,0 +1,71 @@
################################################################
#
# $Id:$
#
# $Log:$
#
.PHONY: all clean print
.SUFFIXES:
ifeq ($(V),1)
VB=''
else
VB=@
endif
CC:=i386-pc-msdosdjgpp-gcc
OPTFLAGS:=-O3
CFLAGS+=-std=gnu89
CFLAGS+=$(OPTFLAGS)
CFLAGS+=-Werror
CFLAGS+=-DDOOMGENERIC_RESX=320 -DDOOMGENERIC_RESY=200
CFLAGS+=-DFEATURE_SOUND=1
CFLAGS+=-DCMAP256
# link time optimization, no significant effect on performance
# CFLAGS+=-flto
# LDFLAGS+=-flto $(OPTFLAGS)
# debug
# CFLAGS+=-g
# LDFLAGS+=-g
LIBS+=-lalleg
#LIBS+=-lalld # debug library
# subdirectory for objects
OBJDIR:=djgpp
OUTPUT:=doomgen.exe
SRC_DOOM = dummy.o am_map.o doomdef.o doomstat.o dstrings.o d_event.o d_items.o d_iwad.o d_loop.o d_main.o d_mode.o d_net.o f_finale.o f_wipe.o g_game.o hu_lib.o hu_stuff.o info.o i_cdmus.o i_endoom.o i_joystick.o i_scale.o i_sound.o i_system.o i_timer.o memio.o m_argv.o m_bbox.o m_cheat.o m_config.o m_controls.o m_fixed.o m_menu.o m_misc.o m_random.o p_ceilng.o p_doors.o p_enemy.o p_floor.o p_inter.o p_lights.o p_map.o p_maputl.o p_mobj.o p_plats.o p_pspr.o p_saveg.o p_setup.o p_sight.o p_spec.o p_switch.o p_telept.o p_tick.o p_user.o r_bsp.o r_data.o r_draw.o r_main.o r_plane.o r_segs.o r_sky.o r_things.o sha1.o sounds.o statdump.o st_lib.o st_stuff.o s_sound.o tables.o v_video.o wi_stuff.o w_checksum.o w_file.o w_main.o w_wad.o z_zone.o w_file_stdc.o i_input.o i_video.o doomgeneric.o doomgeneric_allegro.o mus2mid.o i_allegromusic.o i_allegrosound.o
OBJS += $(addprefix $(OBJDIR)/, $(SRC_DOOM))
all: $(OUTPUT)
clean:
rm -rf $(OBJDIR)
rm -f $(OUTPUT)
rm -f $(OUTPUT).gdb
rm -f $(OUTPUT).map
$(OUTPUT): $(OBJS)
@echo [Linking $@]
$(VB)$(CC) $(CFLAGS) $(LDFLAGS) $(OBJS) \
-o $(OUTPUT) $(LIBS)
$(OBJS): | $(OBJDIR)
$(OBJDIR):
mkdir -p $(OBJDIR)
$(OBJDIR)/%.o: %.c
@echo [Compiling $<]
$(VB)$(CC) $(CFLAGS) -c $< -o $@
print:
@echo OBJS: $(OBJS)
+1 -1
View File
@@ -4,7 +4,7 @@
#include "doomgeneric.h"
uint32_t* DG_ScreenBuffer = 0;
pixel_t* DG_ScreenBuffer = NULL;
void M_FindResponseFile(void);
void D_DoomMain (void);
+17 -1
View File
@@ -4,11 +4,27 @@
#include <stdlib.h>
#include <stdint.h>
#ifndef DOOMGENERIC_RESX
#define DOOMGENERIC_RESX 640
#endif // DOOMGENERIC_RESX
#ifndef DOOMGENERIC_RESY
#define DOOMGENERIC_RESY 400
#endif // DOOMGENERIC_RESY
extern uint32_t* DG_ScreenBuffer;
#ifdef CMAP256
typedef uint8_t pixel_t;
#else // CMAP256
typedef uint32_t pixel_t;
#endif // CMAP256
extern pixel_t* DG_ScreenBuffer;
void doomgeneric_Create(int argc, char **argv);
void doomgeneric_Tick();
+453
View File
@@ -0,0 +1,453 @@
// doomgeneric for Allegro library
#include "doomkeys.h"
#include "i_system.h"
#include "i_video.h"
#include "m_argv.h"
#include "doomgeneric.h"
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <unistd.h>
#define ALLEGRO_NO_KEY_DEFINES 1
#include <allegro.h>
#undef uint32_t // ugly hack because Allegro is Old and doesn't know modern GCC has stdint.h
static bool videomode_set = false;
static BITMAP *temp_bitmap = NULL;
static PALETTE pal;
#define KEYQUEUE_SIZE 16
static volatile unsigned int s_KeyQueue[KEYQUEUE_SIZE];
static volatile unsigned int s_KeyQueueWriteIndex = 0;
static unsigned int s_KeyQueueReadIndex = 0;
static volatile unsigned int s_ticks = 0;
void key_callback(int scancode) {
// this is in interrupt context, avoid heavy processing and be careful about volatile writes
s_KeyQueue[s_KeyQueueWriteIndex] = scancode;
s_KeyQueueWriteIndex = (s_KeyQueueWriteIndex + 1) % KEYQUEUE_SIZE;
}
END_OF_FUNCTION(key_callback);
void timer_callback(void) {
// also in interrupt context
s_ticks++;
}
END_OF_FUNCTION(timer_callback);
void DG_Init() {
int result;
printf("Initializing Allegro\n");
result = allegro_init();
if (result != 0)
{
I_Error("Allegro init failed: %d %s\n", result, allegro_error);
}
I_AtExit(allegro_exit, true);
LOCK_FUNCTION(key_callback);
LOCK_VARIABLE(s_KeyQueue);
LOCK_VARIABLE(s_KeyQueueWriteIndex);
LOCK_VARIABLE(s_KeyQueueReadIndex);
LOCK_FUNCTION(timer_callback);
LOCK_VARIABLE(s_ticks);
install_keyboard();
keyboard_lowlevel_callback = key_callback;
install_timer();
result = install_int(timer_callback, 1);
if (result < 0) {
I_Error("Unable to install timer: %d %s\n", result, allegro_error);
}
// don't set video mode yet so initialization messages stay on screen
}
static void back_to_text_mode(void) {
set_gfx_mode(GFX_TEXT, 80, 25, 0, 0);
}
void DG_DrawFrame()
{
if (!DG_ScreenBuffer) {
return;
}
if (!videomode_set) {
int y;
int result;
#ifdef CMAP256
set_color_depth(8);
#else // CMAP256
// does not seem to work on real DOS hardware
set_color_depth(32);
#endif // CMAP256
result = set_gfx_mode(GFX_AUTODETECT_FULLSCREEN, DOOMGENERIC_RESX, DOOMGENERIC_RESY, 0, 0);
if (result < 0) {
I_Error("Failed to set video mode: %s\n", allegro_error);
}
// register an exit handler to return to text mode
// while this is also done by allegro_exit handler registered earlier
// that's too late for ENDOOM screen to work correctly
I_AtExit(back_to_text_mode, true);
if (!screen) {
I_Error("screen is null\n");
}
temp_bitmap = create_bitmap(DOOMGENERIC_RESX, DOOMGENERIC_RESY);
if (!temp_bitmap) {
I_Error("Failed to create temp bitmap\n");
}
// this is an evil hack
// replace the internal line pointers with pointers into DG_ScreenBuffer
// this avoids some copying
// it might crash when freeing the bitmap but we never do
for (y = 0; y < DOOMGENERIC_RESY; y++) {
temp_bitmap->line[y] = (unsigned char *) &DG_ScreenBuffer[y * DOOMGENERIC_RESX];
}
clear_bitmap(temp_bitmap);
videomode_set = true;
palette_changed = true;
}
#ifdef CMAP256
// changing palette implicitly waits for vsync
// TODO: should do it explicitly in case where we don't change palette
if (palette_changed) {
int i;
for (i = 0; i < 256; i++) {
// allegro uses VGA range 0..63
pal[i].r = colors[i].r >> 2;
pal[i].g = colors[i].g >> 2;
pal[i].b = colors[i].b >> 2;
}
set_palette(pal);
palette_changed = false;
}
#endif // CMAP256
blit(temp_bitmap, screen, 0, 0, 0, 0, DOOMGENERIC_RESX, DOOMGENERIC_RESY);
}
void DG_SleepMs(uint32_t ms)
{
rest(ms);
}
uint32_t DG_GetTicksMs()
{
return s_ticks;
}
int DG_GetKey(int *pressed, unsigned char *doomKey)
{
if (s_KeyQueueReadIndex == s_KeyQueueWriteIndex){
//key queue is empty
return 0;
} else {
bool released;
short keyData = 0;
int scancode = s_KeyQueue[s_KeyQueueReadIndex];
s_KeyQueueReadIndex++;
s_KeyQueueReadIndex %= KEYQUEUE_SIZE;
released = scancode & 0x80;
*pressed = !released;
scancode = scancode & 0x7F;
switch (scancode) {
case __allegro_KEY_RIGHT:
keyData = KEY_RIGHTARROW;
break;
case __allegro_KEY_LEFT:
keyData = KEY_LEFTARROW;
break;
case __allegro_KEY_UP:
keyData = KEY_UPARROW;
break;
case __allegro_KEY_DOWN:
keyData = KEY_DOWNARROW;
break;
case __allegro_KEY_COMMA:
keyData = KEY_STRAFE_L;
break;
case __allegro_KEY_STOP:
keyData = KEY_STRAFE_R;
break;
case __allegro_KEY_SPACE:
keyData = KEY_USE;
break;
case __allegro_KEY_LCONTROL:
keyData = KEY_FIRE;
break;
case __allegro_KEY_ESC:
keyData = KEY_ESCAPE;
break;
case __allegro_KEY_ENTER:
keyData = KEY_ENTER;
break;
case __allegro_KEY_TAB:
keyData = KEY_TAB;
break;
case __allegro_KEY_F1:
keyData = KEY_F1;
break;
case __allegro_KEY_F2:
keyData = KEY_F2;
break;
case __allegro_KEY_F3:
keyData = KEY_F3;
break;
case __allegro_KEY_F4:
keyData = KEY_F4;
break;
case __allegro_KEY_F5:
keyData = KEY_F5;
break;
case __allegro_KEY_F6:
keyData = KEY_F6;
break;
case __allegro_KEY_F7:
keyData = KEY_F7;
break;
case __allegro_KEY_F8:
keyData = KEY_F8;
break;
case __allegro_KEY_F9:
keyData = KEY_F9;
break;
case __allegro_KEY_F10:
keyData = KEY_F10;
break;
case __allegro_KEY_F11:
keyData = KEY_F11;
break;
case __allegro_KEY_F12:
keyData = KEY_F12;
break;
case __allegro_KEY_BACKSPACE:
keyData = KEY_BACKSPACE;
break;
case __allegro_KEY_PAUSE:
keyData = KEY_PAUSE;
break;
case __allegro_KEY_EQUALS:
keyData = KEY_EQUALS;
break;
case __allegro_KEY_MINUS:
keyData = KEY_MINUS;
break;
case __allegro_KEY_LSHIFT:
case __allegro_KEY_RSHIFT:
keyData = KEY_RSHIFT;
break;
case __allegro_KEY_RCONTROL:
keyData = KEY_RCTRL;
break;
case __allegro_KEY_ALT:
keyData = KEY_RALT;
break;
case __allegro_KEY_CAPSLOCK:
keyData = KEY_CAPSLOCK;
break;
case __allegro_KEY_NUMLOCK:
keyData = KEY_NUMLOCK;
break;
case __allegro_KEY_SCRLOCK:
keyData = KEY_SCRLCK;
break;
case __allegro_KEY_PRTSCR:
keyData = KEY_PRTSCR;
break;
case __allegro_KEY_HOME:
keyData = KEY_HOME;
break;
case __allegro_KEY_END:
keyData = KEY_END;
break;
case __allegro_KEY_PGUP:
keyData = KEY_PGUP;
break;
case __allegro_KEY_PGDN:
keyData = KEY_PGDN;
break;
case __allegro_KEY_INSERT:
keyData = KEY_INS;
break;
case __allegro_KEY_DEL:
keyData = KEY_DEL;
break;
case __allegro_KEY_0_PAD:
keyData = KEYP_0;
break;
case __allegro_KEY_1_PAD:
keyData = KEYP_1;
break;
case __allegro_KEY_2_PAD:
keyData = KEYP_2;
break;
case __allegro_KEY_3_PAD:
keyData = KEYP_3;
break;
case __allegro_KEY_4_PAD:
keyData = KEYP_4;
break;
case __allegro_KEY_5_PAD:
keyData = KEYP_5;
break;
case __allegro_KEY_6_PAD:
keyData = KEYP_6;
break;
case __allegro_KEY_7_PAD:
keyData = KEYP_7;
break;
case __allegro_KEY_8_PAD:
keyData = KEYP_8;
break;
case __allegro_KEY_9_PAD:
keyData = KEYP_9;
break;
case __allegro_KEY_SLASH_PAD:
keyData = KEYP_DIVIDE;
break;
case __allegro_KEY_PLUS_PAD:
keyData = KEYP_PLUS;
break;
case __allegro_KEY_MINUS_PAD:
keyData = KEYP_MINUS;
break;
case __allegro_KEY_ASTERISK:
keyData = KEYP_MULTIPLY;
break;
case __allegro_KEY_DEL_PAD:
keyData = KEYP_PERIOD;
break;
case __allegro_KEY_EQUALS_PAD:
keyData = KEYP_EQUALS;
break;
case __allegro_KEY_ENTER_PAD:
keyData = KEYP_ENTER;
break;
default:
keyData = scancode_to_ascii(scancode);
break;
}
if (keyData != 0) {
*doomKey = keyData & 0xFF;
}
return 1;
}
return 0;
}
void DG_SetWindowTitle(const char *title)
{
set_window_title(title);
}
int main(int argc, char **argv)
{
doomgeneric_Create(argc, argv);
while (true)
{
doomgeneric_Tick();
}
return 0;
}
+1 -1
View File
@@ -83,7 +83,7 @@ typedef uint8_t byte;
#include <limits.h>
#ifdef _WIN32
#if defined(_WIN32) || defined(__DJGPP__)
#define DIR_SEPARATOR '\\'
#define DIR_SEPARATOR_S "\\"
+308
View File
@@ -0,0 +1,308 @@
//
// Copyright(C) 1993-1996 Id Software, Inc.
// Copyright(C) 2005-2014 Simon Howard
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// DESCRIPTION:
// System interface for music.
//
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "config.h"
#include "doomtype.h"
#include "memio.h"
#include "mus2mid.h"
#include "deh_str.h"
#include "gusconf.h"
#include "i_sound.h"
#include "i_system.h"
#include "i_swap.h"
#include "m_argv.h"
#include "m_config.h"
#include "m_misc.h"
#include "sha1.h"
#include "w_wad.h"
#include "z_zone.h"
#include <allegro/base.h>
#include <allegro/midi.h>
#include <allegro/sound.h>
#include <allegro/system.h>
#define MAXMIDLENGTH (96 * 1024)
#define MID_HEADER_MAGIC "MThd"
#define MUS_HEADER_MAGIC "MUS\x1a"
static boolean music_initialized = false;
static boolean musicpaused = false;
static int current_music_volume;
// Currently playing music track.
MIDI *current_track_music = NULL;
// If true, the currently playing track is being played on loop.
static boolean current_track_loop;
// Shutdown music
static void I_Allegro_ShutdownMusic(void)
{
// nothing here
// TODO: stop song?
}
// Initialize music subsystem
static boolean I_Allegro_InitMusic(void)
{
// nothing here, it's all done by I_Allegro_InitSound
music_initialized = true;
return true;
}
// Set music volume (0 - 127)
static void I_Allegro_SetMusicVolume(int volume)
{
int digivol = -1;
get_volume(&digivol, NULL);
// allegro range 0 - 255
set_volume(digivol, volume * 2);
}
// Start playing a mid
static void I_Allegro_PlaySong(void *handle, boolean looping)
{
int retval;
if (!music_initialized)
{
return;
}
if (handle == NULL)
{
return;
}
current_track_music = (MIDI *) handle;
current_track_loop = looping;
retval = play_midi(current_track_music, looping);
if (retval < 0) {
fprintf(stderr, "Error playing midi: %d \"%s\"\n", retval, allegro_error);
}
}
static void I_Allegro_PauseSong(void)
{
if (!music_initialized)
{
return;
}
musicpaused = true;
midi_pause();
}
static void I_Allegro_ResumeSong(void)
{
if (!music_initialized)
{
return;
}
musicpaused = false;
midi_resume();
}
static void I_Allegro_StopSong(void)
{
if (!music_initialized)
{
return;
}
stop_midi();
current_track_music = NULL;
}
static void I_Allegro_UnRegisterSong(void *handle)
{
MIDI *midi = (MIDI *) handle;
if (!music_initialized)
{
return;
}
if (handle == NULL)
{
return;
}
destroy_midi(midi);
}
// Determine whether memory block is a .mid file
static boolean IsMid(byte *mem, int len)
{
return len > 4 && !memcmp(mem, "MThd", 4);
}
static boolean ConvertMus(byte *musdata, int len, char *filename)
{
MEMFILE *instream;
MEMFILE *outstream;
void *outbuf;
size_t outbuf_len;
int result;
instream = mem_fopen_read(musdata, len);
outstream = mem_fopen_write();
result = mus2mid(instream, outstream);
if (result == 0)
{
mem_get_buf(outstream, &outbuf, &outbuf_len);
M_WriteFile(filename, outbuf, outbuf_len);
}
mem_fclose(instream);
mem_fclose(outstream);
return result;
}
static void *I_Allegro_RegisterSong(void *data, int len)
{
char *filename;
MIDI *music;
if (!music_initialized)
{
return NULL;
}
filename = M_TempFile("doom.mid");
if (IsMid(data, len) && len < MAXMIDLENGTH)
{
M_WriteFile(filename, data, len);
}
else
{
// Assume a MUS file and try to convert
ConvertMus(data, len, filename);
}
// Load the MIDI. In an ideal world we'd load it directly from memory but Allegro
// doesn't support that so we have to generate a temporary file.
music = load_midi(filename);
if (music == NULL)
{
// Failed to load
fprintf(stderr, "Error loading midi: %s\n", allegro_error);
}
// Remove the temporary MIDI file;
remove(filename);
free(filename);
return music;
}
// Is the song playing?
static boolean I_Allegro_MusicIsPlaying(void)
{
if (!music_initialized)
{
return false;
}
return (current_track_music != NULL) && (midi_pos > 0);
}
// Get position in substitute music track, in seconds since start of track.
static double GetMusicPosition(void)
{
return midi_time;
}
// Poll music position; if we have passed the loop point end position
// then we need to go back.
static void I_Allegro_PollMusic(void)
{
// nothing here, allegro takes care of it
}
static snddevice_t music_allegro_devices[] =
{
SNDDEVICE_PAS,
SNDDEVICE_GUS,
SNDDEVICE_WAVEBLASTER,
SNDDEVICE_SOUNDCANVAS,
SNDDEVICE_GENMIDI,
SNDDEVICE_AWE32,
};
music_module_t DG_music_module =
{
music_allegro_devices,
arrlen(music_allegro_devices),
I_Allegro_InitMusic,
I_Allegro_ShutdownMusic,
I_Allegro_SetMusicVolume,
I_Allegro_PauseSong,
I_Allegro_ResumeSong,
I_Allegro_RegisterSong,
I_Allegro_UnRegisterSong,
I_Allegro_PlaySong,
I_Allegro_StopSong,
I_Allegro_MusicIsPlaying,
I_Allegro_PollMusic,
};
+433
View File
@@ -0,0 +1,433 @@
//
// Copyright(C) 1993-1996 Id Software, Inc.
// Copyright(C) 2005-2014 Simon Howard
// Copyright(C) 2008 David Flater
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// DESCRIPTION:
// System interface for sound.
//
#include "config.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <ctype.h>
#include "deh_str.h"
#include "i_sound.h"
#include "i_system.h"
#include "i_swap.h"
#include "m_argv.h"
#include "m_misc.h"
#include "w_wad.h"
#include "z_zone.h"
#include "doomtype.h"
#include <allegro/base.h>
#include <allegro/sound.h>
#include <allegro/system.h>
#define NUM_CHANNELS 16
#define NUM_MIDI_CHANNELS 16
static boolean sound_initialized = false;
static sfxinfo_t *channels_playing[NUM_CHANNELS];
static int allegro_voices[NUM_CHANNELS];
static SAMPLE *dummy_sample = NULL;
static boolean use_sfx_prefix;
// We don't support libsamplerate with Allegro but these have to be here since
// other code requires them
int use_libsamplerate = 0;
// Scale factor used when converting libsamplerate floating point numbers
// to integers. Too high means the sounds can clip; too low means they
// will be too quiet. This is an amount that should avoid clipping most
// of the time: with all the Doom IWAD sound effects, at least. If a PWAD
// is used, clipping might occur.
float libsamplerate_scale = 0.65f;
// Load and convert a sound effect
// Returns true if successful
static boolean CacheSFX(sfxinfo_t *sfxinfo)
{
int lumpnum;
unsigned int lumplen;
int samplerate;
unsigned int length;
byte *data;
SAMPLE *sample;
// need to load the sound
lumpnum = sfxinfo->lumpnum;
data = W_CacheLumpNum(lumpnum, PU_STATIC);
lumplen = W_LumpLength(lumpnum);
// Check the header, and ensure this is a valid sound
if (lumplen < 8
|| data[0] != 0x03 || data[1] != 0x00)
{
// Invalid sound
return false;
}
// 16 bit sample rate field, 32 bit length field
samplerate = (data[3] << 8) | data[2];
length = (data[7] << 24) | (data[6] << 16) | (data[5] << 8) | data[4];
// If the header specifies that the length of the sound is greater than
// the length of the lump itself, this is an invalid sound lump
// We also discard sound lumps that are less than 49 samples long,
// as this is how DMX behaves - although the actual cut-off length
// seems to vary slightly depending on the sample rate. This needs
// further investigation to better understand the correct
// behavior.
if (length > lumplen - 8 || length <= 48)
{
return false;
}
// The DMX sound library seems to skip the first 16 and last 16
// bytes of the lump - reason unknown.
data += 16;
length -= 32;
sample = create_sample(8, 0, samplerate, length);
if (sample == NULL) {
return false;
}
memcpy(sample->data, data, length);
sfxinfo->driver_data = sample;
// don't need the original lump any more
W_ReleaseLumpNum(lumpnum);
return true;
}
static void GetSfxLumpName(sfxinfo_t *sfx, char *buf, size_t buf_len)
{
// Linked sfx lumps? Get the lump number for the sound linked to.
if (sfx->link != NULL)
{
sfx = sfx->link;
}
// Doom adds a DS* prefix to sound lumps; Heretic and Hexen don't
// do this.
if (use_sfx_prefix)
{
M_snprintf(buf, buf_len, "ds%s", DEH_String(sfx->name));
}
else
{
M_StringCopy(buf, DEH_String(sfx->name), buf_len);
}
}
static void I_Allegro_PrecacheSounds(sfxinfo_t *sounds, int num_sounds)
{
char namebuf[9];
int i;
printf("I_Allegro_PrecacheSounds: Precaching all sound effects..");
for (i=0; i<num_sounds; ++i)
{
if ((i % 6) == 0)
{
printf(".");
fflush(stdout);
}
GetSfxLumpName(&sounds[i], namebuf, sizeof(namebuf));
sounds[i].lumpnum = W_CheckNumForName(namebuf);
if (sounds[i].lumpnum != -1)
{
CacheSFX(&sounds[i]);
}
}
printf("\n");
}
//
// Retrieve the raw data lump index
// for a given SFX name.
//
static int I_Allegro_GetSfxLumpNum(sfxinfo_t *sfx)
{
char namebuf[9];
GetSfxLumpName(sfx, namebuf, sizeof(namebuf));
return W_GetNumForName(namebuf);
}
static void I_Allegro_UpdateSoundParams(int handle, int vol, int sep)
{
int left, right;
if (!sound_initialized || handle < 0 || handle >= NUM_CHANNELS)
{
return;
}
if (channels_playing[handle] == NULL) {
return;
}
voice_set_volume(allegro_voices[handle], vol);
voice_set_pan(allegro_voices[handle], sep);
}
//
// Starting a sound means adding it
// to the current list of active sounds
// in the internal channels.
// As the SFX info struct contains
// e.g. a pointer to the raw data,
// it is ignored.
// As our sound handling does not handle
// priority, it is ignored.
// Pitching (that is, increased speed of playback)
// is set, but currently not used by mixing.
//
static int I_Allegro_StartSound(sfxinfo_t *sfxinfo, int channel, int vol, int sep)
{
if (!sound_initialized || channel < 0 || channel >= NUM_CHANNELS)
{
return -1;
}
// Release a sound effect if there is already one playing
// on this channel
if (channels_playing[channel]) {
voice_stop(allegro_voices[channel]);
channels_playing[channel] = NULL;
}
// Get the sound data
if (sfxinfo->driver_data == NULL)
{
if (!CacheSFX(sfxinfo))
{
return -1;
}
}
assert(sfxinfo->driver_data);
// play sound
reallocate_voice(allegro_voices[channel], sfxinfo->driver_data);
voice_set_volume(allegro_voices[channel], vol);
voice_set_pan(allegro_voices[channel], sep);
voice_start(allegro_voices[channel]);
channels_playing[channel] = sfxinfo;
return channel;
}
static void I_Allegro_StopSound(int handle)
{
if (!sound_initialized || handle < 0 || handle >= NUM_CHANNELS)
{
return;
}
if (channels_playing[handle] == NULL) {
return;
}
voice_stop(allegro_voices[handle]);
channels_playing[handle] = NULL;
}
static boolean I_Allegro_SoundIsPlaying(int handle)
{
int position;
if (!sound_initialized || handle < 0 || handle >= NUM_CHANNELS)
{
return false;
}
if (channels_playing[handle] == NULL) {
return false;
}
position = voice_get_position(allegro_voices[handle]);
if (position < 0) {
// finished
return false;
}
// still playing
return true;
}
//
// Periodically called to update the sound system
//
static void I_Allegro_UpdateSound(void)
{
int i;
// loop through all channels which have sample, check if they're finished
for (i = 0; i < NUM_CHANNELS; i++) {
if (channels_playing[i]) {
int position = voice_get_position(allegro_voices[i]);
if (position < 0) {
// finished
channels_playing[i] = NULL;
}
}
}
}
static void I_Allegro_ShutdownSound(void)
{
int i;
if (!sound_initialized)
{
return;
}
for (i = 0; i < NUM_CHANNELS; i++) {
if (channels_playing[i] != NULL) {
voice_stop(allegro_voices[i]);
channels_playing[i] = NULL;
}
deallocate_voice(allegro_voices[i]);
allegro_voices[i] = -1;
}
destroy_sample(dummy_sample);
dummy_sample = NULL;
remove_sound();
sound_initialized = false;
}
static boolean I_Allegro_InitSound(boolean _use_sfx_prefix)
{
int i;
use_sfx_prefix = _use_sfx_prefix;
// No sounds yet
for (i=0; i<NUM_CHANNELS; ++i)
{
channels_playing[i] = NULL;
}
reserve_voices(NUM_CHANNELS, NUM_MIDI_CHANNELS);
i = install_sound(DIGI_AUTODETECT, MIDI_AUTODETECT, "allegro.cfg");
if (i < 0) {
printf("install_sound failed: %d \"%s\"\n", i, allegro_error);
return false;
}
printf("Allegro sound initialized\n");
printf("Mixer quality %d\n", get_mixer_quality());
printf("Mixer freq %d\n", get_mixer_frequency());
printf("Mixer bits %d\n", get_mixer_bits());
printf("Mixer channels %d\n", get_mixer_channels());
printf("Mixer voices %d\n", get_mixer_voices());
printf("Mixer buffer length %d\n", get_mixer_buffer_length());
// create a dummy sample used to create voices
dummy_sample = create_sample(8, 0, 11025, 8);
if (dummy_sample == NULL) {
printf("Failed to create sound sample: %s\n", allegro_error);
return false;
}
for (i = 0; i < NUM_CHANNELS; i++) {
allegro_voices[i] = allocate_voice(dummy_sample);
}
sound_initialized = true;
return true;
}
static snddevice_t sound_allegro_devices[] =
{
SNDDEVICE_SB,
SNDDEVICE_PAS,
SNDDEVICE_GUS,
SNDDEVICE_WAVEBLASTER,
SNDDEVICE_SOUNDCANVAS,
SNDDEVICE_AWE32,
};
sound_module_t DG_sound_module =
{
sound_allegro_devices,
arrlen(sound_allegro_devices),
I_Allegro_InitSound,
I_Allegro_ShutdownSound,
I_Allegro_GetSfxLumpNum,
I_Allegro_UpdateSound,
I_Allegro_UpdateSoundParams,
I_Allegro_StartSound,
I_Allegro_StopSound,
I_Allegro_SoundIsPlaying,
I_Allegro_PrecacheSounds,
};
+20
View File
@@ -26,6 +26,12 @@
#include "txt_main.h"
#endif
#ifdef __DJGPP__
#include <go32.h>
#endif // __DJGPP__
#define ENDOOM_W 80
#define ENDOOM_H 25
@@ -76,6 +82,20 @@ void I_Endoom(byte *endoom_data)
// Shut down text mode screen
TXT_Shutdown();
#elif defined(__DJGPP__)
int y;
// move cursor to bottom
// there's a direct call for moving cursor somewhere but this is simpler to write
for (y = 0; y < ENDOOM_H; y++) {
puts("\n");
}
// allegro exit should have been run already and so we should be in text mode again
movedata(_my_ds(), (unsigned) endoom_data, _dos_ds, 0xB8000UL, ENDOOM_W * ENDOOM_H * 2);
#endif
}
+1 -19
View File
@@ -18,7 +18,7 @@
#include <stdio.h>
#include <stdlib.h>
#ifdef FEATURE_SOUND
#if defined(FEATURE_SOUND) && !defined(__DJGPP__)
#include <SDL_mixer.h>
#endif
@@ -60,24 +60,6 @@ static music_module_t *music_module = NULL;
int snd_musicdevice = SNDDEVICE_SB;
int snd_sfxdevice = SNDDEVICE_SB;
// Sound modules
extern void I_InitTimidityConfig(void);
#ifdef FEATURE_SOUND
extern sound_module_t* DG_sound_module;
extern music_module_t* DG_music_module;
#endif
extern sound_module_t sound_pcsound_module;
extern music_module_t music_opl_module;
// For OPL module:
extern int opl_io_port;
// For native music module:
extern char *timidity_cfg_path;
// DOS-specific options: These are unused but should be maintained
// so that the config file can be shared between chocolate
// doom and doom.exe
+18
View File
@@ -234,5 +234,23 @@ extern char *snd_musiccmd;
void I_BindSoundVariables(void);
// Sound modules
void I_InitTimidityConfig(void);
#ifdef FEATURE_SOUND
extern sound_module_t DG_sound_module;
extern music_module_t DG_music_module;
#endif
extern sound_module_t sound_pcsound_module;
extern music_module_t music_opl_module;
// For OPL module:
extern int opl_io_port;
// For native music module:
extern char *timidity_cfg_path;
#endif
+18 -1
View File
@@ -22,6 +22,19 @@
#ifdef FEATURE_SOUND
#ifdef __DJGPP__
#define SHORT(x) ((signed short) (x))
#define LONG(x) ((signed int) (x))
#define SYS_LITTLE_ENDIAN
#else // __DJGPP__
#include <SDL_endian.h>
// Endianess handling.
@@ -55,7 +68,11 @@
#define doom_wtohs(x) (short int)(x)
#endif
#else
#endif // __DJGPP__
#else // FEATURE_SOUND
#define SHORT(x) ((signed short) (x))
#define LONG(x) ((signed int) (x))
+8 -2
View File
@@ -264,7 +264,7 @@ void I_Quit (void)
#endif
}
#if !defined(_WIN32) && !defined(__MACOSX__)
#if !defined(_WIN32) && !defined(__MACOSX__) && !defined(__DJGPP__)
#define ZENITY_BINARY "/usr/bin/zenity"
// returns non-zero if zenity is available
@@ -347,7 +347,7 @@ static int ZenityErrorBox(char *message)
return result;
}
#endif /* !defined(_WIN32) && !defined(__MACOSX__) */
#endif /* !defined(_WIN32) && !defined(__MACOSX__) && !defined(__DJGPP__) */
//
@@ -448,6 +448,12 @@ void I_Error (char *error, ...)
message,
NULL);
}
#elif defined(__DJGPP__)
{
printf("%s\n", msgbuf);
exit(-1);
}
#else
{
ZenityErrorBox(msgbuf);
+34 -8
View File
@@ -75,15 +75,20 @@ static struct FB_ScreenInfo s_Fb;
int fb_scaling = 1;
int usemouse = 0;
struct color {
uint32_t b:8;
uint32_t g:8;
uint32_t r:8;
uint32_t a:8;
};
#ifdef CMAP256
boolean palette_changed;
struct color colors[256];
#else // CMAP256
static struct color colors[256];
#endif // CMAP256
void I_GetEvent(void);
// The screen buffer; this is modified to draw things to the screen
@@ -183,6 +188,13 @@ void I_InitGraphics (void)
s_Fb.yres = DOOMGENERIC_RESY;
s_Fb.xres_virtual = s_Fb.xres;
s_Fb.yres_virtual = s_Fb.yres;
#ifdef CMAP256
s_Fb.bits_per_pixel = 8;
#else // CMAP256
s_Fb.bits_per_pixel = 32;
s_Fb.blue.length = 8;
@@ -195,6 +207,7 @@ void I_InitGraphics (void)
s_Fb.red.offset = 16;
s_Fb.transp.offset = 24;
#endif // CMAP256
printf("I_InitGraphics: framebuffer: x_res: %d, y_res: %d, x_virtual: %d, y_virtual: %d, bpp: %d\n",
s_Fb.xres, s_Fb.yres, s_Fb.xres_virtual, s_Fb.yres_virtual, s_Fb.bits_per_pixel);
@@ -277,10 +290,17 @@ void I_FinishUpdate (void)
for (i = 0; i < fb_scaling; i++) {
line_out += x_offset;
#ifdef CMAP256
for (fb_scaling == 1) {
if (fb_scaling == 1) {
memcpy(line_out, line_in, SCREENWIDTH); /* fb_width is bigger than Doom SCREENWIDTH... */
} else {
//XXX FIXME fb_scaling support!
int j;
for (j = 0; j < SCREENWIDTH; j++) {
int k;
for (k = 0; k < fb_scaling; k++) {
line_out[j * fb_scaling + k] = line_in[j];
}
}
}
#else
//cmap_to_rgb565((void*)line_out, (void*)line_in, SCREENWIDTH);
@@ -336,6 +356,12 @@ void I_SetPalette (byte* palette)
colors[i].g = gammatable[usegamma][*palette++];
colors[i].b = gammatable[usegamma][*palette++];
}
#ifdef CMAP256
palette_changed = true;
#endif // CMAP256
}
// Given an RGB value, find the closest matching palette index.
+15
View File
@@ -138,6 +138,14 @@ void I_EnableLoadingDisk(void);
void I_EndRead (void);
struct color {
uint32_t b:8;
uint32_t g:8;
uint32_t r:8;
uint32_t a:8;
};
extern char *video_driver;
extern boolean screenvisible;
@@ -157,4 +165,11 @@ extern int aspect_ratio_correct;
extern int show_diskicon;
extern int diskicon_readbytes;
#ifdef CMAP256
extern boolean palette_changed;
extern struct color colors[256];
#endif // CMAP256
#endif
+1 -1
View File
@@ -168,7 +168,7 @@ char *M_TempFile(char *s)
{
char *tempdir;
#ifdef _WIN32
#if defined(_WIN32) || defined(__DJGPP__)
// Check the TEMP environment variable to find the location.