Skip to content

Commit 1d7c00d

Browse files
authored
Reusable server class, rotation fixes, scene generator, ... (#83)
* Added generator command line tool for Serum PUP Scenes * increased frame queue to handle PUP scenes in parallel to ROM animations * Improved frame buffer handling * Added HD support for RGB24DMDs * Refactored dmdServer into a reusable library functionality (used by PPUC backbox) * fixed Serum color rotation issues * fixed some memory leaks * fixed dumps overwrite existing dumps * updated libs
1 parent f3aa0a0 commit 1d7c00d

File tree

28 files changed

+1373
-705
lines changed

28 files changed

+1373
-705
lines changed

.github/workflows/libdmdutil.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,7 @@ jobs:
104104
cp build/Release/dmdutil_static.lib tmp
105105
cp build/Release/dmdutil_test_s.exe tmp
106106
cp build/Release/dmdutil_test.exe tmp
107+
cp build/Release/dmdutil-generate-scenes.exe tmp
107108
cp -r test tmp/
108109
else
109110
ARTIFACT_PATH="libdmdutil-${{ needs.version.outputs.tag }}-${{ matrix.platform }}-${{ matrix.arch }}.tar.gz"
@@ -114,13 +115,15 @@ jobs:
114115
cp build/dmdserver_test tmp
115116
cp build/dmdutil_test_s tmp
116117
cp build/dmdutil_test tmp
118+
cp build/dmdutil-generate-scenes tmp
117119
elif [[ "${{ matrix.platform }}" == "linux" ]]; then
118120
cp build/libdmdutil.a tmp
119121
cp -a build/*.{so,so.*} tmp
120122
cp build/dmdserver tmp
121123
cp build/dmdserver_test tmp
122124
cp build/dmdutil_test_s tmp
123125
cp build/dmdutil_test tmp
126+
cp build/dmdutil-generate-scenes tmp
124127
elif [[ "${{ matrix.platform }}" == "ios" || "${{ matrix.platform }}" == "ios-simulator" || "${{ matrix.platform }}" == "tvos" ]]; then
125128
cp build/libdmdutil.a tmp
126129
cp -a build/*.dylib tmp

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,10 @@ third-party/include/cargs.h
1313
third-party/include/*.hpp
1414
third-party/include/libserialport.h
1515
third-party/include/pupdmd.h
16+
third-party/include/SceneGenerator.h
1617
third-party/include/serum.h
1718
third-party/include/serum-decode.h
1819
third-party/include/ZeDMD.h
20+
third-party/include/LZ4Stream.h
21+
third-party/include/lz4
1922
.DS_Store

CMakeLists.txt

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,15 @@ set(ARCH "x64" CACHE STRING "Arch")
66
option(BUILD_SHARED "Option to build shared library" ON)
77
option(BUILD_STATIC "Option to build static library" ON)
88
option(POST_BUILD_COPY_EXT_LIBS "Option to copy external libraries to build directory" ON)
9+
option(ENABLE_SANITIZERS "Enable AddressSanitizer and UBSan for Debug builds" OFF)
910

1011
message(STATUS "PLATFORM: ${PLATFORM}")
1112
message(STATUS "ARCH: ${ARCH}")
1213

1314
message(STATUS "BUILD_SHARED: ${BUILD_SHARED}")
1415
message(STATUS "BUILD_STATIC: ${BUILD_STATIC}")
1516
message(STATUS "POST_BUILD_COPY_EXT_LIBS: ${POST_BUILD_COPY_EXT_LIBS}")
17+
message(STATUS "ENABLE_SANITIZERS: ${ENABLE_SANITIZERS}")
1618

1719
if(PLATFORM STREQUAL "macos")
1820
set(CMAKE_OSX_DEPLOYMENT_TARGET 14.0)
@@ -67,6 +69,18 @@ set(CMAKE_C_STANDARD 99)
6769
set(CMAKE_CXX_VISIBILITY_PRESET hidden)
6870
set(CMAKE_C_VISIBILITY_PRESET hidden)
6971

72+
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
73+
if(ENABLE_SANITIZERS AND (PLATFORM STREQUAL "macos" OR PLATFORM STREQUAL "linux"))
74+
add_compile_options(-fsanitize=address)
75+
add_link_options(-fsanitize=address)
76+
77+
add_compile_options(-fsanitize=undefined)
78+
add_link_options(-fsanitize=undefined)
79+
80+
add_compile_options(-fno-omit-frame-pointer)
81+
endif()
82+
endif()
83+
7084
set(DMDUTIL_SOURCES
7185
src/Config.cpp
7286
src/DMD.cpp
@@ -75,6 +89,7 @@ set(DMDUTIL_SOURCES
7589
src/ConsoleDMD.cpp
7690
src/Logger.cpp
7791
src/AlphaNumeric.cpp
92+
src/DMDServer.cpp
7893
)
7994

8095
if(PLATFORM STREQUAL "win" OR PLATFORM STREQUAL "macos" OR PLATFORM STREQUAL "linux")
@@ -143,7 +158,7 @@ if(BUILD_SHARED)
143158

144159
if(PLATFORM STREQUAL "win" OR PLATFORM STREQUAL "macos" OR PLATFORM STREQUAL "linux")
145160
add_executable(dmdserver
146-
src/dmdServer.cpp
161+
src/server.cpp
147162
src/Logger.cpp
148163
)
149164
target_link_libraries(dmdserver PUBLIC dmdutil_shared)
@@ -158,6 +173,11 @@ if(BUILD_SHARED)
158173
)
159174
target_link_libraries(dmdutil_test PUBLIC dmdutil_shared)
160175

176+
add_executable(dmdutil-generate-scenes
177+
src/generateScenesDump.cpp
178+
)
179+
target_link_libraries(dmdutil-generate-scenes PUBLIC dmdutil_shared)
180+
161181
if(POST_BUILD_COPY_EXT_LIBS)
162182
if(PLATFORM STREQUAL "win")
163183
if(ARCH STREQUAL "x64")

README.md

Lines changed: 30 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -47,35 +47,17 @@ void test()
4747
Per default it listens on port 6789 on localhost and accepts "raw" TCP connections.
4848

4949
`dmdserver` accepts these command line options:
50-
* -c --config
51-
* Config file
52-
* optional
53-
* default is no config file
54-
* -o --alt-color-path
55-
* "Fixed alt color path, overwriting paths transmitted by DMDUpdates
56-
* optional
57-
* -a --addr
58-
* IP address or host name
59-
* optional
60-
* default is `localhost`
61-
* -p --port
62-
* Port
63-
* optional
64-
* default is `6789`
65-
* -w --wait-for-displays
66-
* Don't terminate if no displays are connected
67-
* optional
68-
* default is to terminate the server process if no displays could be found
69-
* -l --logging
70-
* Enable logging to stderr
71-
* optional
72-
* default is no logging
73-
* -v --verbose
74-
* Enables verbose logging, includes normal logging
75-
* optional
76-
* default is no logging
77-
* -h --help
78-
* Show help
50+
```
51+
-c, --config=VALUE Config file (optional, default is no config file)
52+
-o, --alt-color-path=VALUE Fixed alt color path, overwriting paths transmitted by DMDUpdates (optional)
53+
-u, --pup-videos-path=VALUE Fixed PupVideos path, overwriting paths transmitted by DMDUpdates (optional)
54+
-a, --addr=VALUE IP address or host name (optional, default is 'localhost')
55+
-p, --port=VALUE Port (optional, default is '6789')
56+
-w, --wait-for-displays Don't terminate if no displays are connected (optional, default is to terminate the server process if no displays could be found)
57+
-l, --logging Enable logging to stderr (optional, default is no logging)
58+
-v, --verbose-logging Enables verbose logging, includes normal logging (optional, default is no logging)
59+
-h, --help Show help
60+
```
7961

8062
`dmdserver` expects two packages to render a DMD frame. The first one is a DmdStream header followed by the "data".
8163

@@ -209,7 +191,7 @@ SaveSettings = 0
209191
# Set to 1 if ZeDMD-WiFi is available.
210192
Enabled = 0
211193
# Enter your ZeDMD WiFi IP address here
212-
WiFiAddr =
194+
WiFiAddr =
213195
214196
[Pixelcade]
215197
# Set to 1 if Pixelcade is attached
@@ -218,6 +200,24 @@ Enabled = 1
218200
Device =
219201
```
220202

203+
## Serum PUP Scenes Generator
204+
205+
Serum PUP Scenes are a new feature of libserum_concentrate.
206+
Such scenes base on a defined number of fake frames at a given frame rate.
207+
These frames can be added to the ROM's original frames or overlay some original frames.
208+
The purpose is to add new animations or to replace existing frames with smoother aniations.
209+
Therefore, a colorization other needs a set of scene frames that could be colorized in the colorization editor.
210+
The `dmdutil-generate-scenes` tool generates a dump of such scene frames according to the PUP Scenes specification CSV file.
211+
212+
`dmdutil-generate-scenes` accepts these command line options:
213+
```
214+
-c, --csv=VALUE PUP scenes CSV file to parse
215+
-o, --output=VALUE Output dump file to generate
216+
-d, --depth=VALUE Bit depth of the DMD frames (2 or 4) (optional, default is 2)
217+
-i, --id=VALUE PUP scene trigger ID to generate (optional, default is all scenes)
218+
-h, --help Show help
219+
```
220+
221221
## Building:
222222

223223
#### Windows (x64)

dmdserver.ini

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,10 +39,10 @@ SaveSettings = 0
3939
# Set to 1 if ZeDMD-WiFi is available.
4040
Enabled = 0
4141
# Enter your ZeDMD WiFi IP address here
42-
WiFiAddr =
42+
WiFiAddr =
4343

4444
[Pixelcade]
4545
# Set to 1 if Pixelcade is attached
46-
Enabled = 1
46+
Enabled = 0
4747
# Disable auto-detection and provide a fixed serial port
4848
Device =

include/DMDUtil/DMD.h

Lines changed: 20 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,9 @@
88
#define DMDUTILCALLBACK
99
#endif
1010

11-
#define DMDUTIL_FRAME_BUFFER_SIZE 32
11+
#define DMDUTIL_FRAME_BUFFER_SIZE 128 // Must be a divider of 65535! Must not exceed 256!
1212
#define DMDUTIL_MIN_FRAMES_BEHIND 4
13-
#define DMDUTIL_MAX_FRAMES_BEHIND 16
13+
#define DMDUTIL_MAX_FRAMES_BEHIND 32
1414
#define DMDUTIL_MAX_NAME_SIZE 16
1515
#define DMDUTIL_MAX_PATH_SIZE 256
1616
#define DMDUTIL_MAX_TRANSITIONAL_FRAME_DURATION 25
@@ -68,7 +68,6 @@ class PixelcadeDMD;
6868
class LevelDMD;
6969
class RGB24DMD;
7070
class ConsoleDMD;
71-
7271
class DMDServerConnector;
7372

7473
class DMDUTILAPI DMD
@@ -77,7 +76,7 @@ class DMDUTILAPI DMD
7776
DMD();
7877
~DMD();
7978

80-
enum class Mode
79+
enum class Mode : int
8180
{
8281
Unknown = 0,
8382
Data = 1,
@@ -108,20 +107,20 @@ class DMDUTILAPI DMD
108107
#pragma pack(push, 1) // Align to 1-byte boundaries, important for sending over socket.
109108
struct Update
110109
{
111-
Mode mode;
112-
AlphaNumericLayout layout;
113-
int depth;
114-
uint8_t data[256 * 64 * 3];
115-
uint16_t segData[256 * 64]; // RGB16 or segment data or SerumV1 palette
110+
Mode mode = Mode::Data; // int
111+
AlphaNumericLayout layout = AlphaNumericLayout::NoLayout; // int
112+
int depth = 2;
113+
uint8_t data[256 * 64 * 3] = {0};
114+
uint16_t segData[256 * 64] = {0}; // RGB16 or segment data or SerumV1 palette
116115
uint16_t segData2[128];
117-
bool hasData;
118-
bool hasSegData;
119-
bool hasSegData2;
120-
uint8_t r;
121-
uint8_t g;
122-
uint8_t b;
123-
uint16_t width;
124-
uint16_t height;
116+
bool hasData = false;
117+
bool hasSegData = false;
118+
bool hasSegData2 = false;
119+
uint8_t r = 255;
120+
uint8_t g = 255;
121+
uint8_t b = 255;
122+
uint16_t width = 128;
123+
uint16_t height = 32;
125124

126125
DMDUTILAPI void convertToHostByteOrder();
127126
DMDUTILAPI Update toNetworkByteOrder() const;
@@ -161,6 +160,7 @@ class DMDUTILAPI DMD
161160
void SetRomName(const char* name);
162161
void SetAltColorPath(const char* path);
163162
void SetPUPVideosPath(const char* path);
163+
void SetPUPTrigger(const char source, const uint16_t id, const uint8_t value = 1);
164164
void DumpDMDTxt();
165165
void DumpDMDRaw();
166166
LevelDMD* CreateLevelDMD(uint16_t width, uint16_t height, bool sam);
@@ -185,7 +185,7 @@ class DMDUTILAPI DMD
185185
Update* m_pUpdateBufferQueue[DMDUTIL_FRAME_BUFFER_SIZE];
186186
std::shared_ptr<Update> m_updateBuffered;
187187

188-
uint8_t GetNextBufferQueuePosition(uint8_t bufferPosition, const uint8_t updateBufferQueuePosition);
188+
uint16_t GetNextBufferQueuePosition(uint16_t bufferPosition, const uint16_t updateBufferQueuePosition);
189189
bool ConnectDMDServer();
190190
bool UpdatePalette(uint8_t* pPalette, uint8_t depth, uint8_t r, uint8_t g, uint8_t b);
191191
void UpdateData(const uint8_t* pData, int depth, uint16_t width, uint16_t height, uint8_t r, uint8_t g, uint8_t b,
@@ -232,7 +232,8 @@ class DMDUTILAPI DMD
232232
std::condition_variable_any m_dmdCV;
233233
std::atomic<bool> m_dmdFrameReady;
234234
std::atomic<bool> m_stopFlag;
235-
std::atomic<uint8_t> m_updateBufferQueuePosition;
235+
std::atomic<uint16_t> m_updateBufferQueuePosition;
236+
std::atomic<uint16_t> m_pupSceneId;
236237

237238
bool m_hasUpdateBuffered = false;
238239
static bool m_finding;

include/DMDUtil/DMDServer.h

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
#pragma once
2+
3+
#include <atomic>
4+
#include <mutex>
5+
#include <thread>
6+
#include <vector>
7+
8+
#include "DMDUtil/DMD.h"
9+
#include "sockpp/tcp_acceptor.h"
10+
11+
#define DMDSERVER_MAX_WIDTH 256
12+
#define DMDSERVER_MAX_HEIGHT 64
13+
14+
namespace DMDUtil
15+
{
16+
17+
class DMDUTILAPI DMDServer
18+
{
19+
public:
20+
DMDServer(DMD* dmd, bool fixedAltColorPath = false, bool fixedPupPath = false);
21+
~DMDServer();
22+
23+
bool Start(const char* addr, in_port_t port);
24+
void Stop();
25+
bool IsRunning() const { return m_running.load(std::memory_order_acquire); }
26+
27+
private:
28+
void AcceptLoop();
29+
void ClientThread(sockpp::tcp_socket sock, uint32_t threadId);
30+
31+
DMD* m_dmd;
32+
bool m_fixedAltColorPath;
33+
bool m_fixedPupPath;
34+
std::atomic<bool> m_running{false};
35+
sockpp::tcp_acceptor m_acceptor;
36+
37+
uint32_t m_currentThreadId{0};
38+
std::mutex m_threadMutex;
39+
uint32_t m_disconnectOtherClients{0};
40+
std::vector<uint32_t> m_threads;
41+
std::thread* m_acceptThread{nullptr};
42+
};
43+
44+
} // namespace DMDUtil

include/DMDUtil/DMDUtil.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
#pragma once
22

3-
#define DMDUTIL_VERSION_MAJOR 0 // X Digits
4-
#define DMDUTIL_VERSION_MINOR 9 // Max 2 Digits
5-
#define DMDUTIL_VERSION_PATCH 2 // Max 2 Digits
3+
#define DMDUTIL_VERSION_MAJOR 0 // X Digits
4+
#define DMDUTIL_VERSION_MINOR 10 // Max 2 Digits
5+
#define DMDUTIL_VERSION_PATCH 0 // Max 2 Digits
66

77
#define _DMDUTIL_STR(x) #x
88
#define DMDUTIL_STR(x) _DMDUTIL_STR(x)
@@ -14,5 +14,6 @@
1414
#include "Config.h"
1515
#include "ConsoleDMD.h"
1616
#include "DMD.h"
17+
#include "DMDServer.h"
1718
#include "LevelDMD.h"
1819
#include "RGB24DMD.h"

include/DMDUtil/RGB24DMD.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ class DMDUTILAPI RGB24DMD
1919
RGB24DMD(uint16_t width, uint16_t height);
2020
~RGB24DMD();
2121

22-
virtual void Update(uint8_t* pRGB24Data);
22+
virtual void Update(uint8_t* pRGB24Data, uint16_t width = 0, uint16_t height = 0);
2323
int GetWidth() const { return m_width; }
2424
int GetHeight() const { return m_height; }
2525
int GetLength() const { return m_length; }

platforms/android/arm64-v8a/external.sh

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,9 @@ cmake \
6464
-DCMAKE_BUILD_TYPE=${BUILD_TYPE} \
6565
-B build
6666
cmake --build build -- -j${NUM_PROCS}
67+
cp -r third-party/include/lz4 ../../third-party/include/
68+
cp src/LZ4Stream.h ../../third-party/include/
69+
cp src/SceneGenerator.h ../../third-party/include/
6770
cp src/serum.h ../../third-party/include/
6871
cp src/serum-decode.h ../../third-party/include/
6972
cp build/libserum.so ../../third-party/runtime-libs/android/arm64-v8a/

0 commit comments

Comments
 (0)