Skip to content

Commit 1e5342b

Browse files
authored
Get it to work on Linux (#1)
* fix build, other stuff (i.e. asm decompressor) doesn't quite work yet * bleh (still no worky) * :O it works! * ok but the rest doesn't work * 'minor' detail * OOPS * _ * clean up, add wrapper script, should work now * README formatting * clean up python script * ... and actually use the flags passed to the script * fix (remove) oneKpaq output buffering in python script * new help text in README
1 parent 30687eb commit 1e5342b

15 files changed

+430
-55
lines changed

.gitignore

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
obj/
2+
config.mk
3+
onekpaq
4+
onekpaq_encode
5+
onekpaq_decode
6+
onekpaq_context.cache*

AsmDecode.cpp

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,14 @@
11
/* Copyright (C) Teemu Suutari */
22

3+
#include <string.h> /* memcpy */
34
#include <vector>
45
#include <sys/mman.h>
6+
#ifndef __linux__
57
#include <mach/vm_param.h>
8+
#else
9+
#include <unistd.h>
10+
#define PAGE_SIZE (sysconf(_SC_PAGESIZE))
11+
#endif
612

713
#include "onekpaq_common.h"
814
#include "AsmDecode.hpp"
@@ -42,21 +48,21 @@ static void makeRunnable(void *ptr,ulong size)
4248

4349
std::vector<u8> AsmDecode(const std::vector<u8> &src1,const std::vector<u8> &src2,StreamCodec::EncodeMode mode,uint shift) {
4450
typedef void (*AsmDecompressor)(void*,void*);
45-
void *decompressors[4]={
51+
static void *decompressors[4]={
4652
&onekpaq_decompressor_mode1,
4753
&onekpaq_decompressor_mode2,
4854
&onekpaq_decompressor_mode3,
4955
&onekpaq_decompressor_mode4
5056
};
5157

52-
ulong decompressorShiftOffsets[4]={
58+
static ulong decompressorShiftOffsets[4]={
5359
(ulong)&onekpaq_decompressor_mode1_shift-(ulong)(void*)&onekpaq_decompressor_mode1,
5460
(ulong)&onekpaq_decompressor_mode2_shift-(ulong)(void*)&onekpaq_decompressor_mode2,
5561
(ulong)&onekpaq_decompressor_mode3_shift-(ulong)(void*)&onekpaq_decompressor_mode3,
5662
(ulong)&onekpaq_decompressor_mode4_shift-(ulong)(void*)&onekpaq_decompressor_mode4
5763
};
5864

59-
ulong decompressorSizes[4]={
65+
static ulong decompressorSizes[4]={
6066
(ulong)&onekpaq_decompressor_mode1_end-(ulong)(void*)&onekpaq_decompressor_mode1,
6167
(ulong)&onekpaq_decompressor_mode2_end-(ulong)(void*)&onekpaq_decompressor_mode2,
6268
(ulong)&onekpaq_decompressor_mode3_end-(ulong)(void*)&onekpaq_decompressor_mode3,
@@ -78,7 +84,14 @@ std::vector<u8> AsmDecode(const std::vector<u8> &src1,const std::vector<u8> &src
7884
((u8*)(void*)decompr)[decompressorShiftOffsets[dIndex]]=shift;
7985
makeRunnable((void*)decompr,decompressorSizes[dIndex]);
8086

81-
INFO("Running asm decompressor Xbx=%p Xdi=%p",combine.data()+src1.size(),ret.data()+destStartMargin);
87+
/*fprintf(stderr, "offset = %zu, mode=%zu, dind=%zu, shift=%zu\n", src1.size(), mode, dIndex, shift);
88+
for (size_t i = 0; i < ((src1.size() < 4) ? src1.size() : 4); ++i) {
89+
fprintf(stderr, "src1[%zu] = 0x%x\n", i, src1[i]);
90+
}
91+
for (size_t i = 0; i < ((src2.size() < 4) ? src2.size() : 4); ++i) {
92+
fprintf(stderr, "src2[%zu] = 0x%x\n", i, src2[i]);
93+
}*/
94+
//INFO("Running asm decompressor Xbx=%p Xdi=%p",combine.data()+src1.size(),ret.data()+destStartMargin);
8295
auto timeTaken=Timer([&]() {
8396
decompr(combine.data()+src1.size(),ret.data()+destStartMargin);
8497
});

BlockCodec.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -546,7 +546,7 @@ void BlockCodec::CreateContextModels(const std::vector<u8> &src,bool multipleRet
546546
if (src.size()<=_cm->GetStartOffset()) {
547547
_models.clear();
548548
_models.push_back(Model{0,2});
549-
_rawLength=src.size();
549+
_rawLength=uint(src.size());
550550
_header=EncodeHeaderAndClean(_models);
551551
_estimatedLength=uint(_header.size()+src.size())*8;
552552
return;
@@ -558,7 +558,7 @@ void BlockCodec::CreateContextModels(const std::vector<u8> &src,bool multipleRet
558558

559559
TICK();
560560
DispatchLoop(bitLength,32,[&](size_t i) {
561-
_cm->CalculateAllProbabilities(probabilityMap[i],src,i+_cm->GetStartOffset()*8,_shift);
561+
_cm->CalculateAllProbabilities(probabilityMap[i],src,uint(i+_cm->GetStartOffset()*8),_shift);
562562
});
563563

564564

@@ -569,13 +569,13 @@ void BlockCodec::CreateContextModels(const std::vector<u8> &src,bool multipleRet
569569
auto IterateModels=[&](std::vector<Model> &models)->std::pair<std::vector<Model>,float> {
570570
// parallelization makes this a tad more complicated.
571571
// first loop and then decide the best from the candidates
572-
uint modelListSize=_cm->GetModelCount()*(numWeights+models.size());
572+
size_t modelListSize=_cm->GetModelCount()*(numWeights+models.size());
573573
std::vector<std::pair<std::vector<Model>,float>> modelList(modelListSize);
574574
for (auto &it:modelList) it.second=std::numeric_limits<float>::infinity();
575575

576576
DispatchLoop(modelListSize,1,[&](size_t combinedIndex) {
577-
uint i=combinedIndex/_cm->GetModelCount();
578-
uint newModel=combinedIndex%_cm->GetModelCount();
577+
uint i=uint(combinedIndex/_cm->GetModelCount());
578+
uint newModel=uint(combinedIndex%_cm->GetModelCount());
579579
std::vector<Model> testModels=models;
580580
bool modified=false;
581581
auto current=std::find_if(testModels.begin(),testModels.end(),[&](const Model &a) {

Makefile

Lines changed: 43 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,47 +1,71 @@
11
# Copyright (C) Teemu Suutari
22

3-
BITS := 32
3+
BITS ?= $(shell getconf LONG_BIT)
44
VERSION = 1.1
55

6+
NASM ?= nasm
7+
8+
HAS_LIBDISPATCH ?= 0
9+
610
CC = clang
711
CXX = clang++
8-
COMMONFLAGS = -Os -Wall -Wsign-compare -Wshorten-64-to-32 -Wno-shift-op-parentheses -DONEKPAQ_VERSION="\"$(VERSION)\""
12+
COMMONFLAGS = -g -Os -Wall -Wsign-compare -Wshorten-64-to-32 -Wno-shift-op-parentheses -DONEKPAQ_VERSION="\"$(VERSION)\""
13+
ifeq ($(BITS),32)
14+
COMMONFLAGS += -mtune=i386 -fno-tree-vectorize -ffloat-store -mno-sse2 -mno-mmx
15+
COMMONFLAGS += -mno-sse -mfpmath=387 -m80387
16+
endif
917
CFLAGS = $(COMMONFLAGS)
1018
CXXFLAGS = $(COMMONFLAGS) -std=c++14
11-
AFLAGS = -O2
19+
AFLAGS = -O2 -g
20+
21+
-include config.mk
22+
23+
ifneq ($(HAS_LIBDISPATCH),0)
24+
ifneq ($(LIBDISPATCH_INC_DIR),)
25+
COMMONFLAGS += -DHAS_LIBDISPATCH -I$(LIBDISPATCH_INC_DIR) -L$(LIBDISPATCH_LIB_DIR) -ldispatch -fblocks -lBlocksRuntime
26+
else
27+
COMMONFLAGS += -DHAS_LIBDISPATCH -ldispatch -fblocks -lBlocksRuntime
28+
endif
29+
endif
1230

1331
# debugging...
1432
#COMMONFLAGS += -DDEBUG_BUILD -g
1533
#AFLAGS += -DDEBUG_BUILD -g
1634

1735
ifeq ($(BITS),64)
1836
COMMONFLAGS += -m64
19-
AFLAGS += -fmacho64
37+
AFLAGS += -felf64
2038
else
2139
COMMONFLAGS += -m32
22-
AFLAGS += -fmacho32
40+
AFLAGS += -felf32
2341
endif
2442

25-
PROG = onekpaq
26-
SLINKS = onekpaq_encode onekpaq_decode
27-
OBJS = ArithEncoder.o ArithDecoder.o BlockCodec.o StreamCodec.o AsmDecode.o CacheFile.o \
28-
onekpaq_main.o log.o \
29-
$(foreach decompr,1 2 3 4,onekpaq_cfunc_$(decompr).o)
43+
PROG := onekpaq
44+
SLINKS := onekpaq_encode #onekpaq_decode
45+
OBJS := obj/ArithEncoder.cpp.o obj/ArithDecoder.cpp.o obj/BlockCodec.cpp.o obj/StreamCodec.cpp.o obj/CacheFile.cpp.o \
46+
obj/onekpaq_main.cpp.o obj/log.c.o
47+
48+
ifeq ($(BITS),32)
49+
OBJS := $(OBJS) obj/AsmDecode.cpp.o $(foreach decompr,1 2 3 4,obj/onekpaq_cfunc_$(decompr).asm.o)
50+
endif
3051

3152
all: $(SLINKS)
3253

33-
.asm.o:
34-
nasm $(AFLAGS) $<
54+
%/:
55+
mkdir -p "$@"
56+
57+
#obj/%.asm.o: %.asm obj/
58+
# $(NASM) $(AFLAGS) "$<" -o "$@"
3559

36-
.cpp.o:
37-
$(CXX) $(CXXFLAGS) -c $<
60+
obj/%.cpp.o: %.cpp obj/
61+
$(CXX) $(CXXFLAGS) -c "$<" -o "$@"
3862

39-
.c.o:
40-
$(CC) $(CFLAGS) -c $<
63+
obj/%.c.o: %.c obj/
64+
$(CC) $(CFLAGS) -c "$<" -o "$@"
4165

4266
define decompressors
43-
onekpaq_cfunc_$(1).o: onekpaq_decompressor$(BITS).asm onekpaq_cfunc$(BITS).asm
44-
nasm $(AFLAGS) -DONEKPAQ_DECOMPRESSOR_MODE=$(1) onekpaq_cfunc$(BITS).asm -o onekpaq_cfunc_$(1).o
67+
obj/onekpaq_cfunc_$(1).asm.o: onekpaq_decompressor$(BITS).asm onekpaq_cfunc$(BITS).asm obj/
68+
$(NASM) $(AFLAGS) -DONEKPAQ_DECOMPRESSOR_MODE=$(1) onekpaq_cfunc$(BITS).asm -o "obj/onekpaq_cfunc_$(1).asm.o"
4569
endef
4670

4771
$(foreach decompr,1 2 3 4,$(eval $(call decompressors,$(decompr))))
@@ -60,7 +84,7 @@ clean:
6084
define reporting
6185
report$(1): .PHONY
6286
@rm -f tmp_out
63-
@nasm -O2 -DONEKPAQ_DECOMPRESSOR_MODE=$(1) onekpaq_decompressor$(BITS).asm -o tmp_out
87+
@$(NASM) -O2 -DONEKPAQ_DECOMPRESSOR_MODE=$(1) onekpaq_decompressor$(BITS).asm -o tmp_out
6488
@stat -f "onekpaq decompressor mode$(1) size: %z" tmp_out
6589
@rm -f tmp_out
6690
endef

README.md

Lines changed: 59 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,59 @@
1+
# oneKpaq Linux version
2+
3+
## Dependencies
4+
5+
You may want to install `libdispatch`, or compression will be really really
6+
slow. If there isn't a distro package for it, you can grab it
7+
[here](https://github.com/apple/swift-corelibs-libdispatch/), and then edit
8+
your `config.mk` to set `HAS_LIBDISPATCH` to 1, and `LIBDISPATCH_INC_DIR` and
9+
`LIBDISPATCH_LIB_DIR` to the right values.
10+
11+
In any case, `libdispatch` is not a hard requirement. But you'll really really
12+
want it.
13+
14+
## Compiling
15+
16+
```sh
17+
$ make
18+
```
19+
20+
## Running
21+
22+
For ease of use (to compress a binary immediately into another executable
23+
binary), you probably want to run the Python script instead of the C++ program:
24+
25+
```
26+
$ ./onekpaq.py --help
27+
usage: onekpaq.py [-h] [--onekpaq ONEKPAQ] [--nasm NASM] [--stub STUB]
28+
{1,2,3,4} {1,2,3} input [input ...] output
29+
30+
positional arguments:
31+
{1,2,3,4} Selects the compression and decompression mode: '1' is 'single block,
32+
small decoder', '2' is 'multi-block, small decoder', '3' is 'single block,
33+
fast decoder', '4' is 'multi-block, fast decoder'.
34+
{1,2,3} Compression complexity to use. Higher values mean higher compression, but
35+
also longer compression times.
36+
input Input block(s)
37+
output Output executable
38+
39+
optional arguments:
40+
-h, --help show this help message and exit
41+
--onekpaq ONEKPAQ The onekpaq_encode binary to use
42+
--nasm NASM The nasm binary to use
43+
--stub STUB The assembly decompressor stub to use
44+
45+
$ ./onekpaq.py 3 3 hello hello.okp && ./hello.okp
46+
Hello world!
47+
```
48+
49+
Currently, this program has to be executed in the root directory of this
50+
repository.
51+
52+
-----------------
53+
54+
## Original README
55+
56+
```
157
258
.--------. .--------. .---.
359
`-----. |`------. `. \ \
@@ -6,8 +62,9 @@
662
`---'`---------' `---'
763
864
----------------------------------------------------------------
9-
oneKpaq v1.0 by TS/TDA
65+
oneKpaq v1.0 by TS/TDA
1066
----------------------------------------------------------------
67+
```
1168

1269

1370
Overview
@@ -154,3 +211,4 @@ Thanks
154211

155212
Special thanks to Firehawk - Without his help, these projects
156213
would have stayed at the drawing board. (Also thx for the logo)
214+

SimpleDispatch.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
#ifndef SIMPLEDISPATCH_H
44
#define SIMPLEDISPATCH_H
55

6-
#ifdef __APPLE__
6+
#if defined(__APPLE__) || defined(HAS_LIBDISPATCH)
77

88
#include <dispatch/dispatch.h>
99

StreamCodec.cpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,10 @@
44
#include <tuple>
55
#include <string>
66
#include <memory>
7+
#include <algorithm> /* std::reverse, std::min_element */
8+
#include <limits> /* std::numeric_limits */
9+
#include <string.h> /* memcmp */
10+
#include <stddef.h> /* size_t */
711

812
#include "onekpaq_common.h"
913

@@ -223,7 +227,7 @@ void StreamCodec::Encode(const std::vector<std::vector<u8>> &blocks,EncodeMode m
223227
// should not happen in practice. For now lets pad with 1-3 bytes
224228
_destAsm1.clear();
225229
_destAsm2.clear();
226-
for (uint i=tmp1.size();i<4;i++) _destAsm2.push_back(0);
230+
for (size_t i=tmp1.size();i<4;i++) _destAsm2.push_back(0);
227231
_destAsm2.insert(_destAsm2.end(),tmp1.begin(),tmp1.end());
228232
_destAsm2.insert(_destAsm2.end(),tmp2.begin(),tmp2.end());
229233
} else {
@@ -281,6 +285,7 @@ void StreamCodec::LoadStream(std::vector<u8> singleStream)
281285
prevEnd=headerEnd;
282286
if (isSingle) break;
283287
}
288+
//INFO("prevEnd=%u isSingle=%u", prevEnd, isSingle);
284289
_dest=std::vector<u8>(singleStream.begin()+prevEnd+(isSingle?0:2),singleStream.end());
285290
}
286291

debug32.asm

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,10 @@
1919
; edx third param
2020
; ecx fourth param
2121
; return value in eax
22-
[section .data]
22+
23+
%ifndef ONEKPAQ_NO_SECTIONS
24+
[section .data.onekpaq.func_r_%1]
25+
%endif
2326
%%func_r_%1:
2427
extern %1
2528
dd %1
@@ -36,6 +39,7 @@ extern %1
3639
push edi
3740

3841
call [dword %%func_r_%1]
42+
; call %1
3943

4044
pop edi
4145
pop esi
@@ -47,14 +51,20 @@ extern %1
4751
%endm
4852

4953
%macro DEBUG_PLAIN 1
50-
[section .rodata]
54+
%ifndef ONEKPAQ_NO_SECTIONS
55+
[section .rodata.onekpaq.dbg_text]
56+
%endif
5157
%%dbg_text:
5258
db %1
5359
db 0
5460
__SECT__
5561

5662
mov edi,%%dbg_text
63+
%ifidn __OUTPUT_FORMAT__, elf32
64+
EXTCALL DebugPrint
65+
%else
5766
EXTCALL _DebugPrint
67+
%endif
5868
%endm
5969

6070
%macro DEBUG 1

log.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@ void DebugPrint(const char *str,...)
88
{
99
va_list ap;
1010
va_start(ap,str);
11-
vfprintf(stdout,str,ap);
12-
fflush(stdout);
11+
vfprintf(stderr,str,ap);
12+
fflush(stderr);
1313
va_end(ap);
1414
}
1515

0 commit comments

Comments
 (0)