Skip to content

Commit 78402e1

Browse files
committed
Updates
1 parent dd0ebc3 commit 78402e1

18 files changed

+235
-37
lines changed

.editorconfig

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
root = true
2+
[*]
3+
4+
indent_size = 4
5+
indent_style = space
6+
tab_width = 4
7+
end_of_line = lf
8+
insert_final_newline = tue
9+
trim_trailing_whitespace = true
10+
max_line_length = 120

LICENSE

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2024 Timothy Sarbin
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

README.md

+53
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,25 @@
11
# Abyss Engine
22

3+
Abyss Engine clean-room reimplementation of **Diablo 2**, written in C.
4+
The goal is to recreate the original game engine, but on a portable platform that can also easily be modded and
5+
extended.
6+
7+
This is **not** a reverse-engineering project, and no original code from the game is used. It will also not be
8+
compaible with the original game's save files or multiplayer systems.
9+
10+
Before running the engine, make sure it is [configured](#configuration) properly.
11+
12+
You can hang out with the developers and other community members on `#AbyssEngine` at `irc.libera.chat`.
13+
We no longer maintain a Discord presence. Any such servers are not affiliated with this project.
14+
15+
## Supported Platforms
16+
17+
* Windows 10+ (x64, Arm64)
18+
* macOS (Arm64)
19+
* Linux (x64, Arm64)
20+
21+
Other platforms may work, but are not officially supported.
22+
323
## Building
424

525
### Prerequisites
@@ -15,6 +35,24 @@ git submodule update --init --recursive
1535

1636
### Compiling
1737

38+
#### Visual Studio 2022 / Clion / VSCode (with CMake Tools extensions)
39+
40+
Open the root project folder in the IDE and build the solution.
41+
42+
#### XCode
43+
44+
Generate an XCode project with cmake:
45+
46+
```bash
47+
mkdir build
48+
cd build
49+
cmake .. -G Xcode
50+
```
51+
52+
Then load the generated Xcode project and build it.
53+
54+
#### Command Line
55+
1856
```bash
1957
mkdir build
2058
cd build
@@ -27,6 +65,9 @@ On **Linux** and **Windows**, you can run the engine by executing the `abyss` ex
2765

2866
For **macOS**, you can run the engine by executing the `Abyss Engine.app` bundle in the build directory.
2967

68+
Please note that the engine requires the `abyss.ini` configuration file. If you haven't set it,
69+
please refer to the [Configuration](#configuration) section below.
70+
3071
### Output Logs
3172

3273
If you run AbyssEngine from the command line, it will output logs to the console.
@@ -39,6 +80,18 @@ of the app bundle on the command line:
3980

4081
## Configuration
4182

83+
### MPQ files
84+
85+
This engine requires the original Diablo 2+LOD MPQ files to run. These files are not included in the repository.
86+
You can legally obtain them by purchasing a physical copy of the game, or from a digital distribution platform
87+
such as battle.net.
88+
89+
There are a lot of pirated versions of the game available online, but we do not condone piracy, and most of them
90+
are modded in a way that is not supported by the engine. Please don't waste developer resources by reporting issues
91+
while using pirated versions of the game.
92+
93+
### abyss.ini
94+
4295
In order for Abyss Engine to run, it needs to load abyss.ini. A template of this file is located at
4396
`/content/abyss.ini` in the source repo, and should be placed in the local settings folder for abyss
4497
based on the platform:

src/abyss.c

+33-6
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ int main(int argc, char **argv) {
2222

2323
LOG_DEBUG("Loading configuration...");
2424
char *config_path = malloc(4096);
25+
FAIL_IF_NULL(config_path);
26+
2527
memset(config_path, 0, 4096);
2628
#ifdef _WIN32
2729
snprintf(config_path, 4096, "%s\\abyss\\abyss.ini", getenv("APPDATA"));
@@ -37,10 +39,10 @@ int main(int argc, char **argv) {
3739
fileman_init();
3840

3941
LOG_DEBUG("Creating window...");
40-
sdl_window =
41-
SDL_CreateWindow("Abyss Engine", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
42-
(int)((float)800 * config->graphics.initial_scale),
43-
(int)((float)600 * config->graphics.initial_scale), SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE);
42+
sdl_window = SDL_CreateWindow("Abyss Engine", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
43+
(int)((float)800 * config->graphics.initial_scale),
44+
(int)((float)600 * config->graphics.initial_scale),
45+
SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI);
4446

4547
if (sdl_window == NULL) {
4648
FATAL(SDL_GetError());
@@ -77,11 +79,36 @@ int main(int argc, char **argv) {
7779
switch (sdl_event.type) {
7880
case SDL_QUIT:
7981
running = false;
80-
break;
82+
continue;
8183
case SDL_MOUSEMOTION:
8284
mouse_x = sdl_event.motion.x;
8385
mouse_y = sdl_event.motion.y;
84-
break;
86+
continue;
87+
case SDL_KEYDOWN:
88+
if (sdl_event.key.keysym.sym == SDLK_F4 && sdl_event.key.keysym.mod == KMOD_LALT) {
89+
running = false;
90+
}
91+
if (sdl_event.key.keysym.sym == SDLK_RETURN &&
92+
(sdl_event.key.keysym.mod == KMOD_LALT || sdl_event.key.keysym.mod == KMOD_RALT)) {
93+
SDL_SetWindowFullscreen(sdl_window,
94+
config->graphics.fullscreen ? 0 : SDL_WINDOW_FULLSCREEN_DESKTOP);
95+
config->graphics.fullscreen = !config->graphics.fullscreen;
96+
}
97+
// if in text input, handle backspace
98+
if (strlen(text_input) > 0 && sdl_event.key.keysym.sym == SDLK_BACKSPACE) {
99+
text_input[strlen(text_input) - 1] = '\0';
100+
}
101+
key_pressed[sdl_event.key.keysym.scancode] = true;
102+
103+
continue;
104+
case SDL_KEYUP:
105+
key_pressed[sdl_event.key.keysym.scancode] = false;
106+
continue;
107+
case SDL_TEXTINPUT:
108+
if (strlen(text_input) + strlen(sdl_event.text.text) < MAX_TEXT_INPUT_LENGTH) {
109+
strcat(text_input, sdl_event.text.text);
110+
}
111+
continue;
85112
}
86113
}
87114

src/common/config.c

+14-4
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ static const char *default_mpqs[] = {"d2exp.mpq", "d2xmusic.mpq", "d2xtalk.mpq"
2424
free(X); \
2525
} \
2626
(X) = malloc(sizeof(char) * (strlen(Y) + 1)); \
27+
FAIL_IF_NULL(X); \
2728
memset(X, 0, sizeof(char) * (strlen(Y) + 1)); \
2829
strcat(X, Y);
2930

@@ -207,6 +208,8 @@ void config_set(char *category, char *key, char *value) {
207208

208209
void config_load(const char *file_path) {
209210
config = malloc(sizeof(config_t));
211+
FAIL_IF_NULL(config);
212+
210213
memset(config, 0, sizeof(config_t));
211214
config->mpqs = calloc(0, sizeof(char *));
212215
config->num_mpqs = 0;
@@ -218,6 +221,11 @@ void config_load(const char *file_path) {
218221
char *value = malloc(sizeof(char) * MAX_LINE_LEN);
219222
char *line = malloc(sizeof(char) * MAX_LINE_LEN);
220223

224+
FAIL_IF_NULL(category);
225+
FAIL_IF_NULL(key);
226+
FAIL_IF_NULL(value);
227+
FAIL_IF_NULL(line);
228+
221229
memset(category, 0, sizeof(char) * MAX_LINE_LEN);
222230
memset(key, 0, sizeof(char) * MAX_LINE_LEN);
223231
memset(value, 0, sizeof(char) * MAX_LINE_LEN);
@@ -286,20 +294,22 @@ void config_free() {
286294

287295
void config_add_mpq(const char *mpq_file) {
288296
config->num_mpqs++;
289-
config->mpqs = realloc(config->mpqs, config->num_mpqs * sizeof(char *));
290297

291-
if (config->mpqs == NULL) {
292-
LOG_FATAL("Could not allocate memory for MPQs!");
293-
}
298+
config->mpqs = realloc(config->mpqs, config->num_mpqs * sizeof(char *));
299+
FAIL_IF_NULL(config->mpqs);
294300

295301
config->mpqs[config->num_mpqs - 1] = malloc(sizeof(char) * MAX_LINE_LEN);
302+
FAIL_IF_NULL(config->mpqs[config->num_mpqs - 1]);
303+
296304
memset(config->mpqs[config->num_mpqs - 1], 0, sizeof(char) * MAX_LINE_LEN);
297305
strcat(config->mpqs[config->num_mpqs - 1], config->base_path);
298306
strcat(config->mpqs[config->num_mpqs - 1], mpq_file);
299307
}
300308

301309
void config_set_sane_defaults() {
302310
char *base_path = malloc(sizeof(char) * 4096);
311+
FAIL_IF_NULL(base_path);
312+
303313
memset(base_path, 0, sizeof(char) * 4096);
304314
getcwd(base_path, 4096);
305315
SET_PARAM_STR(config->base_path, base_path);

src/common/fileman.c

+3
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,10 @@ char *fix_path(const char *path) {
2929

3030
void fileman_init() {
3131
fileman = malloc(sizeof(fileman_t));
32+
FAIL_IF_NULL(fileman);
33+
3234
memset(fileman, 0, sizeof(fileman_t));
35+
3336
fileman->mpqs = calloc(0, sizeof(mpq_t *));
3437
fileman->files = calloc(0, sizeof(fileman_file_entry_t));
3538

src/common/globals.c

+19-5
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,21 @@
11
#include "globals.h"
22

3-
SDL_Window *sdl_window = NULL;
4-
SDL_Renderer *sdl_renderer = NULL;
5-
bool running = false;
6-
int mouse_x = 0;
7-
int mouse_y = 0;
3+
SDL_Window *sdl_window = NULL;
4+
SDL_Renderer *sdl_renderer = NULL;
5+
bool running = false;
6+
int mouse_x = 0;
7+
int mouse_y = 0;
8+
bool key_pressed[SDL_NUM_SCANCODES] = {0};
9+
char text_input[MAX_TEXT_INPUT_LENGTH + 1] = {0};
10+
11+
void start_text_input() {
12+
memset(text_input, 0, sizeof(text_input));
13+
SDL_StartTextInput();
14+
}
15+
16+
void stop_text_input() {
17+
memset(text_input, 0, sizeof(text_input));
18+
SDL_StopTextInput();
19+
}
20+
21+
bool is_in_text_input() { return SDL_IsTextInputActive(); }

src/common/globals.h

+9-1
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,26 @@
11
#ifndef ABYSS_GLOBALS_H
22
#define ABYSS_GLOBALS_H
33

4-
#include <SDL2/SDL.h>
54
#include "resource_paths.h"
5+
#include <SDL2/SDL.h>
66
#include <stdbool.h>
77

88
#define FATAL(MSG) \
99
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Fatal Error", MSG, sdl_window); \
1010
exit(-1);
1111

12+
#define MAX_TEXT_INPUT_LENGTH 100
13+
1214
extern SDL_Window *sdl_window;
1315
extern SDL_Renderer *sdl_renderer;
1416
extern bool running;
1517
extern int mouse_x;
1618
extern int mouse_y;
19+
extern bool key_pressed[SDL_NUM_SCANCODES];
20+
extern char text_input[MAX_TEXT_INPUT_LENGTH + 1];
21+
22+
void start_text_input();
23+
void stop_text_input();
24+
bool is_in_text_input();
1725

1826
#endif // ABYSS_GLOBALS_H

src/common/log.c

+17-5
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,19 @@
33
#include <stdio.h>
44
#include <stdlib.h>
55
#include <string.h>
6+
#ifdef _WIN32
7+
#include <Windows.h>
8+
#endif // _WIN32
69

10+
#define MAX_LOG_LINE_LENGTH 4096
711
log_level_t log_level = LOG_LEVEL_ERROR;
812

913
static const char *log_level_strings[] = {"", "DEBUG", "INFO ", "WARN ", "ERROR", "FATAL"};
1014

1115
void log_set_level(const log_level_t level) { log_level = level; }
1216

1317
void log_message(log_level_t level, const char *file, int line, const char *format, ...) {
18+
char msg[MAX_LOG_LINE_LENGTH];
1419
va_list args;
1520

1621
if (level < log_level) {
@@ -19,23 +24,30 @@ void log_message(log_level_t level, const char *file, int line, const char *form
1924

2025
#ifdef _WIN32
2126
printf("[%s] %s:%i - ", log_level_strings[level], strrchr(file, '\\') + 1, line);
27+
if (IsDebuggerPresent()) {
28+
memset(msg, 0, sizeof(char) * MAX_LOG_LINE_LENGTH);
29+
snprintf(msg, MAX_LOG_LINE_LENGTH, "%s(%i): [%s] ", file, line, log_level_strings[level]);
30+
va_start(args, format);
31+
const int len = strchr(msg, '\0') - msg;
32+
vsnprintf(strchr(msg, '\0'), len, format, args);
33+
va_end(args);
34+
strcat(msg, "\n");
35+
OutputDebugString(msg);
36+
}
2237
#else
2338
printf("[%s] %s:%i - ", log_level_strings[level], strrchr(file, '/') + 1, line);
2439
#endif
2540
va_start(args, format);
2641
vprintf(format, args);
2742
va_end(args);
28-
2943
printf("\n");
3044

3145
if (level == LOG_LEVEL_FATAL) {
32-
char *msg = malloc(sizeof(char) * 10000);
33-
memset(msg, 0, sizeof(char) * 10000);
46+
memset(msg, 0, sizeof(char) * MAX_LOG_LINE_LENGTH);
3447
va_start(args, format);
35-
vsnprintf(msg, 10000, format, args);
48+
vsnprintf(msg, MAX_LOG_LINE_LENGTH, format, args);
3649
va_end(args);
3750
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Error", msg, sdl_window);
38-
free(msg);
3951
exit(-1);
4052
}
4153
}

src/common/log.h

+2
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
#define LOG_ERROR(...) log_message(LOG_LEVEL_ERROR, __FILE__, __LINE__, __VA_ARGS__)
1010
#define LOG_FATAL(...) log_message(LOG_LEVEL_FATAL, __FILE__, __LINE__, __VA_ARGS__)
1111

12+
#define FAIL_IF_NULL(ptr) if (ptr == NULL) { LOG_FATAL("Failed to allocate memory."); }
13+
1214
typedef enum {
1315
LOG_LEVEL_EVERYTHING,
1416
LOG_LEVEL_DEBUG,

0 commit comments

Comments
 (0)