Compare commits

..
63 Commits
Author SHA1 Message Date
iris 35f20a16b8 i should implement DSP DMA... 2026-05-20 17:55:07 +02:00
iris f9ab690ccd i need to start caring about carry >.< 2026-05-19 12:26:51 +02:00
iris 8824b6b75a Merge commit 'f070e484cdac8a6d6a2e6f039aa69555e0739133' 2026-05-19 08:51:06 +02:00
iris f070e484cd Squashed 'external/ircolib/' changes from bb3f168e1..d611a21e5
d611a21e5 imma stop using size_t

git-subtree-dir: external/ircolib
git-subtree-split: d611a21e50fcfdfb5f34a7f79c4c690c50d85c5f
2026-05-19 08:51:06 +02:00
iris 7d706e703f sdf 2026-05-19 08:48:58 +02:00
iris 03a6a9b383 ok imma stop using size_t at this point 2026-05-19 08:48:52 +02:00
iris 8d6d6c0672 Merge commit 'a8099e3aeafb464445d1c3ee3a852697d37a1e69' 2026-05-19 08:43:09 +02:00
iris a8099e3aea Squashed 'external/ircolib/' changes from 7df4ec224..bb3f168e1
bb3f168e1 fix compilation on windows

git-subtree-dir: external/ircolib
git-subtree-split: bb3f168e134aee5dd5460e57b43d06ef84a06092
2026-05-19 08:43:08 +02:00
iris 2f0c837464 cool 2026-05-19 00:11:48 +02:00
iris e265677727 Squashed 'external/ircolib/' changes from ec06dab..7df4ec2
7df4ec2 clear bit

git-subtree-dir: external/ircolib
git-subtree-split: 7df4ec22463394c2763fef61b581b3d2980778ef
2026-05-19 00:06:03 +02:00
iris f375b9c0ee Merge commit 'e26567772789c28c79920624e1622a7a3306c560' 2026-05-19 00:06:03 +02:00
iris 59b6c70c3f booogs 2026-05-19 00:04:56 +02:00
iris 0754d52d67 Squashed 'external/ircolib/' changes from cf68f4c..ec06dab
ec06dab logging

git-subtree-dir: external/ircolib
git-subtree-split: ec06dab96452fb0d3b4c93e71dbdf9869e39f7e5
2026-05-18 23:29:31 +02:00
iris b50e0a529d Merge commit '0754d52d67766f39276ae32771bca3f28b1ac3dc' 2026-05-18 23:29:31 +02:00
iris 74b13b4d70 Squashed 'external/ircolib/' changes from 8cb69c8..cf68f4c
cf68f4c improvements

git-subtree-dir: external/ircolib
git-subtree-split: cf68f4c385c6f2def0e359c3c2a7621ce78062a8
2026-05-18 23:28:07 +02:00
iris 8c0b0bfc1b Merge commit '74b13b4d7049f9181b1241195324e85af2d9653a' 2026-05-18 23:28:07 +02:00
iris 5024d45e58 Squashed 'external/ircolib/' changes from ce3cd72..8cb69c8
8cb69c8 Merge commit '634f6ff006c8811c47a7a07356f46214f5d8a736' as 'external/ircolib'
2230d4c dhjkfhsdf
c2e22fb better logs
eee9fcf there might be an off by 1 error...
aeb5094 getting floating point stuff now
b13161f Branches simplified, and working!
e48f6a6 trying to simplify branches
b2f415a start crediting people <3
723e668 rfi
9a2d437 oris
7c456e5 rendering Panda correctly
df6f382 Merge commit '4870214d575293257604fa75a6458f0f0a7ea083' as 'external/yuv2rgb'
4870214 Squashed 'external/yuv2rgb/' content from commit ee78934c8
8bd3935 YUV
9df9eda almost rendering correctly
c8d2b36 Merge commit '411251c6242b04119edc41ce83f09f0714e2d32b' as 'external/SDL'
411251c Squashed 'external/SDL/' content from commit 716c767b7
d057a31 xfb loop copy finished
9c3a678 getting closer and closer to the xfb copy loop in panda
fc26f75 bcx partially implemented
df68e42 getting conditional branch now
2be9570 getting to my first branch now
e598f02 Merge commit '2201a0227297b9251717e44adc32554a51ca0ed6' as 'external/xbyak'
2201a02 Squashed 'external/xbyak/' content from commit 431abd86
fc5beeb start executing
0b1d14b loading dols
5f1e3aa asdfasfd
be41857 todo list in readme
93cab1e we load the ELF correctly it seems!
831e03e Merge commit '884e597e3572c5a47c15270649c1e0c24fae3a18' as 'external/cflags'
884e597 Squashed 'external/cflags/' content from commit cc3ea1b
cc2dfc0 do not care about sections as hazel teaches
2b01767 cool
f563827 Merge commit '44fea07a8bae832d53bfdcec3b4cfbf0b60f987d' as 'external/ircolib'
44fea07 Squashed 'external/ircolib/' content from commit ce3cd726
1803ee7 ok
e5413f9 introduce capstone
c0de074 Merge commit '802798ce3c8baa4697120580f87bc1ee377306d3' as 'external/capstone'
802798c Squashed 'external/capstone/' content from commit e46f64fa
ef8e742 read ELF
fede961 Merge commit 'a67f311330461cf90801a74fe351a4a80a5abb11' as 'external/ELFIO'
a67f311 Squashed 'external/ELFIO/' content from commit 94f7706
ad83dec gitignore
9130ede first commit

git-subtree-dir: external/ircolib
git-subtree-split: 8cb69c875cb5e3e3a8f18204ed88ea73de456df6
2026-05-18 23:22:33 +02:00
iris 83e3f5423f Merge commit '5024d45e589ebd708e2d5091632197235a1b1e23' 2026-05-18 23:22:33 +02:00
iris bb54f0c15b sadfasdf 2026-05-18 23:22:30 +02:00
iris 634f6ff006 Squashed 'external/ircolib/' content from commit ce3cd72
git-subtree-dir: external/ircolib
git-subtree-split: ce3cd726c8df8388d554abf8bb55d55020eb4450
2026-05-18 23:13:51 +02:00
iris f72110272d Merge commit '634f6ff006c8811c47a7a07356f46214f5d8a736' as 'external/ircolib' 2026-05-18 23:13:51 +02:00
iris 2230d4c662 dhjkfhsdf 2026-05-18 23:13:35 +02:00
iris c2e22fb742 better logs 2026-05-18 23:00:43 +02:00
iris eee9fcfb17 there might be an off by 1 error... 2026-05-18 17:42:02 +02:00
iris aeb5094b05 getting floating point stuff now 2026-05-18 12:06:03 +02:00
iris b13161f9c2 Branches simplified, and working! 2026-05-18 09:56:15 +02:00
iris e48f6a6402 trying to simplify branches 2026-05-15 18:11:07 +02:00
iris b2f415a6ea start crediting people <3 2026-05-15 09:57:57 +02:00
iris 723e66871d rfi 2026-05-15 09:45:26 +02:00
iris 9a2d437b24 oris 2026-05-14 16:49:10 +02:00
iris 7c456e50c5 rendering Panda correctly 2026-05-14 12:16:43 +02:00
iris df6f382a4b Merge commit '4870214d575293257604fa75a6458f0f0a7ea083' as 'external/yuv2rgb' 2026-05-14 11:28:27 +02:00
iris 4870214d57 Squashed 'external/yuv2rgb/' content from commit ee78934c8
git-subtree-dir: external/yuv2rgb
git-subtree-split: ee78934c8d542e8402bcb6eef7259217a6f859bc
2026-05-14 11:28:27 +02:00
iris 8bd39350ee YUV 2026-05-14 11:27:36 +02:00
iris 9df9eda9fd almost rendering correctly 2026-05-13 18:02:23 +02:00
iris c8d2b3677f Merge commit '411251c6242b04119edc41ce83f09f0714e2d32b' as 'external/SDL' 2026-05-13 17:47:57 +02:00
iris 411251c624 Squashed 'external/SDL/' content from commit 716c767b7
git-subtree-dir: external/SDL
git-subtree-split: 716c767b7e7099fb0e2fda9db59227a7e1d1d8a4
2026-05-13 17:47:57 +02:00
iris d057a31269 xfb loop copy finished 2026-05-13 17:46:37 +02:00
iris 9c3a6789f6 getting closer and closer to the xfb copy loop in panda 2026-05-13 11:27:28 +02:00
iris fc26f75118 bcx partially implemented 2026-05-13 09:44:31 +02:00
iris df68e42d61 getting conditional branch now 2026-05-12 17:55:05 +02:00
iris 2be9570aa9 getting to my first branch now 2026-05-12 14:27:59 +02:00
iris e598f02995 Merge commit '2201a0227297b9251717e44adc32554a51ca0ed6' as 'external/xbyak' 2026-05-12 14:03:16 +02:00
iris 2201a02272 Squashed 'external/xbyak/' content from commit 431abd86
git-subtree-dir: external/xbyak
git-subtree-split: 431abd865e70a46d56f5aa0e1f87572decb60169
2026-05-12 14:03:16 +02:00
iris fc5beebd8e start executing 2026-05-12 14:02:34 +02:00
iris 0b1d14bcd5 loading dols 2026-05-12 10:44:44 +02:00
iris 5f1e3aa095 asdfasfd 2026-05-11 23:46:36 +02:00
iris be41857c42 todo list in readme 2026-05-11 23:45:10 +02:00
iris 93cab1ee41 we load the ELF correctly it seems! 2026-05-11 23:44:19 +02:00
iris 831e03e868 Merge commit '884e597e3572c5a47c15270649c1e0c24fae3a18' as 'external/cflags' 2026-05-11 22:22:03 +02:00
iris 884e597e35 Squashed 'external/cflags/' content from commit cc3ea1b
git-subtree-dir: external/cflags
git-subtree-split: cc3ea1b95d49fb3183cc26b60a7caa978e80500b
2026-05-11 22:22:03 +02:00
iris cc2dfc0218 do not care about sections as hazel teaches 2026-05-11 22:20:49 +02:00
iris 2b0176790e cool 2026-05-11 18:07:14 +02:00
iris f563827898 Merge commit '44fea07a8bae832d53bfdcec3b4cfbf0b60f987d' as 'external/ircolib' 2026-05-11 18:02:01 +02:00
iris 44fea07a8b Squashed 'external/ircolib/' content from commit ce3cd726
git-subtree-dir: external/ircolib
git-subtree-split: ce3cd726c8df8388d554abf8bb55d55020eb4450
2026-05-11 18:02:01 +02:00
iris 1803ee7de8 ok 2026-05-11 17:56:32 +02:00
iris e5413f9abd introduce capstone 2026-05-11 14:17:07 +02:00
iris c0de07465b Merge commit '802798ce3c8baa4697120580f87bc1ee377306d3' as 'external/capstone' 2026-05-11 11:55:07 +02:00
iris 802798ce3c Squashed 'external/capstone/' content from commit e46f64fa
git-subtree-dir: external/capstone
git-subtree-split: e46f64fadb351e9ecd05264fab26f2772feb0994
2026-05-11 11:55:07 +02:00
iris ef8e742694 read ELF 2026-05-11 11:54:46 +02:00
iris fede961d15 Merge commit 'a67f311330461cf90801a74fe351a4a80a5abb11' as 'external/ELFIO' 2026-05-11 11:41:03 +02:00
iris a67f311330 Squashed 'external/ELFIO/' content from commit 94f7706
git-subtree-dir: external/ELFIO
git-subtree-split: 94f7706b5325b2ad9872e4481278278592cf86c9
2026-05-11 11:41:03 +02:00
iris ad83dec7ea gitignore 2026-05-11 11:40:57 +02:00
6667 changed files with 4077936 additions and 1 deletions
+56
View File
@@ -0,0 +1,56 @@
---
Language: Cpp
BasedOnStyle: LLVM
AlignConsecutiveAssignments: false
AlignConsecutiveDeclarations: false
AlignOperands: false
AlignTrailingComments: false
AlwaysBreakTemplateDeclarations: Yes
BreakBeforeBraces: Custom
BraceWrapping:
AfterCaseLabel: false
AfterClass: false
AfterControlStatement: false
AfterEnum: false
AfterFunction: false
AfterNamespace: false
AfterStruct: false
AfterUnion: false
AfterExternBlock: false
BeforeCatch: true
BeforeElse: false
BeforeLambdaBody: false
BeforeWhile: true
SplitEmptyFunction: false
SplitEmptyRecord: false
SplitEmptyNamespace: false
BreakConstructorInitializers: AfterColon
BreakConstructorInitializersBeforeComma: false
ColumnLimit: 120
ConstructorInitializerAllOnOneLineOrOnePerLine: false
IndentAccessModifiers: false
AccessModifierOffset: 0
ContinuationIndentWidth: 0
IncludeCategories:
- Regex: '^<.*'
Priority: 1
- Regex: '^".*'
Priority: 2
- Regex: '.*'
Priority: 3
IncludeIsMainRegex: '([-_](test|unittest))?$'
IndentCaseBlocks: true
InsertNewlineAtEOF: true
MacroBlockBegin: ''
MacroBlockEnd: ''
SortIncludes: Never
MaxEmptyLinesToKeep: 2
NamespaceIndentation: Inner
SpaceInEmptyParentheses: false
SpacesInAngles: false
SpacesInConditionalStatement: false
SpacesInCStyleCastParentheses: false
SpacesInParentheses: false
TabWidth: 4
IndentWidth: 4
...
+4
View File
@@ -0,0 +1,4 @@
CompileFlags:
CompilationDatabase: build/
Completion:
HeaderInsertion: Never
+3
View File
@@ -0,0 +1,3 @@
tests/
build/
.vscode/
+39
View File
@@ -0,0 +1,39 @@
cmake_minimum_required(VERSION 3.23)
project(weee CXX)
set(CMAKE_CXX_STANDARD 23)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
option(BUILD_SHARED_LIBS OFF)
include_directories(external/ELFIO)
include_directories(external/capstone/include)
include_directories(external/cflags/include)
include_directories(external/SDL/include)
include_directories(external/xbyak)
include_directories(external)
if(WIN32)
add_compile_definitions(_CRT_SECURE_NO_WARNINGS)
add_compile_definitions(NOMINMAX)
endif()
add_compile_options(-fno-operator-names)
set(CAPSTONE_ARCHITECTURE_DEFAULT OFF)
set(CAPSTONE_PPC_SUPPORT ON)
add_subdirectory(external/capstone)
add_subdirectory(external/SDL)
add_executable(weee main.cpp core/mem.cpp core/loaders/elf.cpp
core/loaders/dol.cpp
core/broadway.cpp
core/broadway/instructions.cpp
core/broadway/mmio/vi.cpp
core/broadway/mmio/pi.cpp
core/broadway/mmio/mi.cpp
core/broadway/mmio/dsp.cpp
core/broadway/mmio/ai.cpp
core/broadway/mmio/exi.cpp
core/broadway/mmio/si.cpp)
target_link_libraries(weee PUBLIC SDL3::SDL3 capstone)
target_include_directories(weee PUBLIC core)
+9 -1
View File
@@ -1 +1,9 @@
# weee
# weee
- [x] ELF
- [x] DOL
- [x] panda.dol
- [ ] libogc simple examples
## Cool people
- [layle](https://github.com/ioncodes/), thanks for the IDA plugins and resources. Check out [*his* Wii emulator](https://github.com/ioncodes/gecko)
+285
View File
@@ -0,0 +1,285 @@
#include <broadway/utils.hpp>
#include <mem.hpp>
#include <print>
#include <ircolib/log.hpp>
#include <ircolib/mem_access.hpp>
#include <array>
namespace weee::core {
broadway::broadway() {
if (cs_open(CS_ARCH_PPC, cs_mode(CS_MODE_BIG_ENDIAN | CS_MODE_32), &capstone) != CS_ERR_OK) {
std::println("warning: could not initialize capstone. Disassembly is disabled");
disasm_available = false;
}
}
void broadway::set_pc(ircolib::u32 value) { pc = value; }
void broadway::run(mem &mem) {
std::println("pc: 0x{:08X}", pc);
for (int i = 0; i < 1000000; i++) {
ircolib::u32 instr = fetch(mem);
execute(instr, mem);
}
}
ircolib::u32 broadway::fetch(mem &mem) {
ircolib::u32 val = mem.read32(pc)
.and_then([&](ircolib::u32 val) { return std::expected<ircolib::u32, std::string>(val); })
.or_else([&](std::string e) {
ircolib::panic("broadway read failed. Reason {} (pc: 0x{:08X})", e, pc);
return std::expected<ircolib::u32, std::string>();
})
.value();
pc += 4;
return val;
}
void broadway::decode_special3(ircolib::u32 instr, mem &mem) {
auto secondary = utils::secondary(instr);
switch (secondary) {
case 38:
mtfsb1(instr);
break;
case 711:
mtfsf(instr);
break;
default:
std::println("broadway unknown special3 {} (0x{:04X}) (pc 0x{:08X})", secondary, secondary, pc - 4);
std::println("disassembly:");
print_disasm(instr);
ircolib::panic("LR: 0x{:08X}", lr);
}
}
void broadway::decode_special2(ircolib::u32 instr, mem &mem) {
auto secondary = utils::secondary(instr);
switch (secondary) {
case 0x000:
cmp(instr);
break;
case 0x008:
subfc(instr);
break;
case 0x00A:
addc(instr);
break;
case 0x013:
mfcr(instr);
break;
case 0x017:
lwzx(instr, mem);
break;
case 0x01C:
and(instr);
break;
case 0x020:
cmpl(instr);
break;
case 0x028:
subf(instr);
break;
case 0x053:
mfmsr(instr);
break;
case 0x088:
subfe(instr);
break;
case 0x08A:
adde(instr);
break;
case 0x090:
mtcrf(instr);
break;
case 0x092:
mtmsr(instr);
break;
case 0x097:
stwx(instr, mem);
break;
case 0x0CA:
addze(instr);
break;
case 0x0D2:
ircolib::warn("broadway TODO mtsr (pc 0x{:08X})", pc - 4);
break;
case 0x0EB:
mullw(instr);
break;
case 0x117:
lhzx(instr, mem);
break;
case 0x173:
mftb(instr);
break;
case 0x1BC:
or (instr);
break;
case 0x153:
case 0x1D3:
mftspr(ircolib::is_bit_set<ircolib::u32, 7>(secondary), instr);
break;
case 0x1DC:
nand(instr);
break;
case 0x10A:
add(instr);
break;
case 0x1CB:
divwu(instr);
break;
case 0x256: // sync
break;
case 0x318:
sraw(instr);
break;
default:
std::println("broadway unknown special2 {} (0x{:04X}) (pc 0x{:08X})", secondary, secondary, pc - 4);
std::println("disassembly:");
print_disasm(instr);
ircolib::panic("LR: 0x{:08X}", lr);
}
}
void broadway::decode_special1(ircolib::u32 instr, mem &mem) {
switch (utils::secondary(instr)) {
case 0x10:
bclrx(instr);
break;
case 0x32:
rfi(instr);
break;
case 0x96: // isync
break;
default:
std::println("broadway unknown special1 {} (0x{:04X}) (pc 0x{:08X})", utils::secondary(instr),
utils::secondary(instr), pc - 4);
std::println("disassembly:");
print_disasm(instr);
ircolib::panic("LR: 0x{:08X}", lr);
}
}
void broadway::execute(ircolib::u32 instr, mem &mem) {
const auto primary = utils::primary(instr);
switch (primary) {
case 7:
mulli(instr);
break;
case 8:
subfic(instr);
break;
case 10:
cmpli(instr);
break;
case 11:
cmpi(instr);
break;
case 12:
addic(instr);
break;
case 13:
addicr(instr);
break;
case 14:
addi(instr);
break;
case 15:
addis(instr);
break;
case 16:
bcx(instr);
break;
case 18:
bx(instr);
break;
case 19:
decode_special1(instr, mem);
break;
case 20:
rlwimi(instr);
break;
case 21:
rlwinm(instr);
break;
case 24:
ori(instr);
break;
case 25:
oris(instr);
break;
case 26:
xori(instr);
break;
case 28:
andi(instr);
break;
case 29:
andis(instr);
break;
case 31:
decode_special2(instr, mem);
break;
case 32:
lwz(instr, mem);
break;
case 33:
lwzu(instr, mem);
break;
case 34:
lbz(instr, mem);
break;
case 36:
stw(instr, mem);
break;
case 37:
stwu(instr, mem);
break;
case 38:
stb(instr, mem);
break;
case 39:
stbu(instr, mem);
break;
case 40:
lhz(instr, mem);
break;
case 44:
sth(instr, mem);
break;
case 45:
sthu(instr, mem);
break;
case 50:
lfd(instr, mem);
break;
case 63:
decode_special3(instr, mem);
break;
default:
std::println("broadway::execute unimplemented instruction 0x{:08X} / 0b{:032b} ({})", instr, instr, primary);
std::println("disassembly:");
print_disasm(instr);
ircolib::panic("LR: 0x{:08X}", lr);
}
}
void broadway::print_disasm(ircolib::u32 instr) {
if (!disasm_available)
return;
cs_insn *insn;
auto instr_buff = ircolib::integral_to_slice(std::byteswap(instr));
ircolib::u32 count = cs_disasm(capstone, instr_buff.data(), instr_buff.size(), pc - 4, 1, &insn);
if (count <= 0)
return;
ircolib::u32 j;
for (j = 0; j < count; j++) {
std::println("\t0x{:x}:\t{}\t\t{}", insn[j].address, insn[j].mnemonic, insn[j].op_str);
}
cs_free(insn, count);
}
} // namespace weee::core
+140
View File
@@ -0,0 +1,140 @@
#pragma once
#include <ircolib/types.hpp>
#include <capstone/capstone.h>
#include <xbyak/xbyak.h>
#include <array>
namespace weee::core {
struct mem;
struct broadway {
broadway();
void set_pc(ircolib::u32);
void run(mem &);
private:
ircolib::u32 fetch(mem &);
void print_disasm(ircolib::u32);
void execute(ircolib::u32, mem &);
bool disasm_available = true;
ircolib::u32 pc = 0, lr = 0, ctr = 0, cr = 0, srr0 = 0, fpscr = 0, msr = 0, tbl = 0, tbu = 0;
union {
struct {
unsigned bytecount : 7;
unsigned : 22;
unsigned ca : 1;
unsigned ov : 1;
unsigned so : 1;
};
ircolib::u32 raw;
} xer;
void set_cr(ircolib::u8 value, ircolib::u8 index) {
cr &= ~(0xffff << index * 4);
cr |= (value << index * 4);
}
bool get_cr_bit(ircolib::u8 index, ircolib::u8 bit) { return (cr >> index * 4) & (1 << (4 - bit)); }
// bat registers indexes
static constexpr ircolib::u32 BAT_LOWER_OFFSET = 0;
static constexpr ircolib::u32 BAT_UPPER_OFFSET = 8;
std::array<ircolib::u32, 16> ibat, dbat;
std::array<ircolib::u32, 32> gpr{};
struct Fgr {
ircolib::u64 ps0, ps1;
};
std::array<Fgr, 32> fgrs{};
// ircolib::u32 const_gpr_lookup{};
csh capstone;
// Xbyak::CodeGenerator code;
// instructions
void decode_special1(ircolib::u32, mem &);
void decode_special2(ircolib::u32, mem &);
void decode_special3(ircolib::u32, mem &);
void branch(bool, bool, ircolib::u32);
bool test_cond_and_ctr(ircolib::u32);
void andi(ircolib::u32);
void andis(ircolib::u32);
void and(ircolib::u32);
void add(ircolib::u32);
void addc(ircolib::u32);
void adde(ircolib::u32);
void addze(ircolib::u32);
void addis(ircolib::u32);
void addi(ircolib::u32);
void addic(ircolib::u32);
void addicr(ircolib::u32);
void ori(ircolib::u32);
void oris(ircolib::u32);
void bx(ircolib::u32);
void bcx(ircolib::u32);
void mftspr(bool, ircolib::u32);
void mtcrf(ircolib::u32);
void stw(ircolib::u32, mem &);
void stb(ircolib::u32, mem &);
void stwu(ircolib::u32, mem &);
void sthu(ircolib::u32, mem &);
void stwx(ircolib::u32, mem &);
void stbu(ircolib::u32, mem &);
void sth(ircolib::u32, mem &);
void lbz(ircolib::u32, mem &);
void lwz(ircolib::u32, mem &);
void lwzx(ircolib::u32, mem &);
void lhz(ircolib::u32, mem &);
void lhzx(ircolib::u32, mem &);
void lfd(ircolib::u32, mem &);
void bclrx(ircolib::u32);
void cmpi(ircolib::u32);
void cmpli(ircolib::u32);
void cmp(ircolib::u32);
void cmpl(ircolib::u32);
void rlwinm(ircolib::u32);
void rlwimi(ircolib::u32);
void lwzu(ircolib::u32, mem &);
void rfi(ircolib::u32);
void mfcr(ircolib::u32);
void mtfsf(ircolib::u32);
void mtfsb1(ircolib::u32);
void mtfsb0(ircolib::u32);
void mfmsr(ircolib::u32);
void mtmsr(ircolib::u32);
void mullw(ircolib::u32);
void mulli(ircolib::u32);
void nand(ircolib::u32);
void subf(ircolib::u32);
void subfc(ircolib::u32);
void subfic(ircolib::u32);
void subfe(ircolib::u32);
void or (ircolib::u32);
void xori(ircolib::u32);
void divwu(ircolib::u32);
void mftb(ircolib::u32);
void sraw(ircolib::u32);
inline void cr0_update(bool condition, ircolib::s32 result) {
if (condition) {
const bool b0 = result < 0;
const bool b1 = result >= 0;
const bool b2 = result == 0;
const bool b3 = xer.so;
set_cr((b0 << 3) | (b1 << 2) | (b2 << 1) | (b3 << 0), 0);
}
}
inline void cr1_update(bool condition) {
if (condition) {
const ircolib::u8 field = (fpscr >> 28) & 0xf;
set_cr(field, 1);
}
}
};
} // namespace weee::core
+660
View File
@@ -0,0 +1,660 @@
#include "ircolib/log.hpp"
#include <broadway/utils.hpp>
#include <mem.hpp>
namespace weee::core {
void broadway::add(ircolib::u32 instr) {
gpr[utils::RD(instr)] = gpr[utils::RA(instr)] + gpr[utils::RB(instr)];
cr0_update(instr & 1, gpr[utils::RD(instr)]);
}
void broadway::addc(ircolib::u32 instr) {
ircolib::u32 sum;
bool carry = __builtin_add_overflow(gpr[utils::RA(instr)], gpr[utils::RB(instr)], &sum);
cr0_update(instr & 1, sum);
xer.ca = carry;
gpr[utils::RD(instr)] = sum;
}
void broadway::adde(ircolib::u32 instr) {
ircolib::u32 sum;
bool c0 = __builtin_add_overflow(gpr[utils::RA(instr)], gpr[utils::RB(instr)], &sum);
bool c1 = __builtin_add_overflow(sum, xer.ca, &sum);
cr0_update(instr & 1, sum);
xer.ca = c0 | c1;
gpr[utils::RD(instr)] = sum;
}
void broadway::addze(ircolib::u32 instr) {
ircolib::u32 sum;
bool c1 = __builtin_add_overflow(gpr[utils::RA(instr)], xer.ca, &sum);
cr0_update(instr & 1, sum);
xer.ca = c1;
gpr[utils::RD(instr)] = sum;
}
void broadway::addi(ircolib::u32 instr) {
if (utils::RA(instr) == 0) { // li
gpr[utils::RD(instr)] = ircolib::s32(utils::SIMM(instr));
return;
}
gpr[utils::RD(instr)] = gpr[utils::RA(instr)] + (ircolib::s32(utils::SIMM(instr)));
}
void broadway::addic(ircolib::u32 instr) {
ircolib::u32 sum;
bool carry = __builtin_add_overflow(gpr[utils::RA(instr)], ircolib::s32(utils::SIMM(instr)), &sum);
gpr[utils::RD(instr)] = sum;
xer.ca = carry;
}
void broadway::addicr(ircolib::u32 instr) {
ircolib::u32 sum;
bool carry = __builtin_add_overflow(gpr[utils::RA(instr)], ircolib::s32(utils::SIMM(instr)), &sum);
cr0_update(true, sum);
gpr[utils::RD(instr)] = sum;
xer.ca = carry;
}
void broadway::addis(ircolib::u32 instr) {
if (utils::RA(instr) == 0) { // lis
gpr[utils::RD(instr)] = ircolib::s32(utils::SIMM(instr)) << 16;
return;
}
gpr[utils::RD(instr)] = gpr[utils::RA(instr)] + (ircolib::s32(utils::SIMM(instr)) << 16);
}
void broadway::ori(ircolib::u32 instr) { gpr[utils::RA(instr)] = gpr[utils::RS(instr)] | utils::UIMM(instr); }
void broadway::oris(ircolib::u32 instr) {
gpr[utils::RA(instr)] = gpr[utils::RS(instr)] | ((ircolib::u32)utils::UIMM(instr) << 16);
}
void broadway::branch(bool aa, bool lk, ircolib::u32 bd) {
if (!aa)
bd += pc - 4;
if (lk)
lr = pc;
pc = bd;
}
void broadway::bx(ircolib::u32 instr) {
const bool link = instr & 1;
const bool absolute = instr & 2;
ircolib::s32 li = (ircolib::s32(instr << 6) >> 6) & 0xFFFFFFFC;
branch(absolute, link, li);
}
bool broadway::test_cond_and_ctr(ircolib::u32 instr) {
const ircolib::u8 bo = (instr >> 21) & 0x1f;
const ircolib::u8 bi = (instr >> 16) & 0x1f;
const bool ctr_ok = ircolib::is_bit_set(bo, 2) || ((--ctr == 0) == (ircolib::is_bit_set(bo, 1)));
const bool cond_ok = ircolib::is_bit_set(bo, 4) || (get_cr_bit(0, bi) == ircolib::is_bit_set(bo, 3));
return cond_ok && ctr_ok;
}
void broadway::bcx(ircolib::u32 instr) {
const bool link = instr & 1;
const bool absolute = instr & 2;
ircolib::s32 bd = (ircolib::s32(instr << 16) >> 16) & 0xFFFFFFFC;
if (test_cond_and_ctr(instr)) {
branch(absolute, link, bd);
}
}
void broadway::mftspr(bool dir, ircolib::u32 instr) {
const ircolib::u32 spr_field = (instr >> 11) & 0x3FF;
auto move_to_or_from_spr = [&](ircolib::u32 &spr) {
if (dir) { // mtspr
spr = gpr[utils::RS(instr)];
return;
}
// mfspr
gpr[utils::RD(instr)] = spr;
};
switch (spr_field) {
case 0b0000100000:
move_to_or_from_spr(xer.raw);
break;
case 0b0100000000:
move_to_or_from_spr(lr);
break;
case 0b0100100000:
move_to_or_from_spr(ctr);
break;
case 0b1101000000:
move_to_or_from_spr(srr0);
break;
case 0b1101100000: // srr1
break;
case 0b1000011111: // hid0
break;
case 0b1100011100: // hid2
break;
case 0b1100111111: // l2cr
break;
case 0b1000110000:
move_to_or_from_spr(ibat[BAT_LOWER_OFFSET + 0]);
break;
case 0b1000010000:
move_to_or_from_spr(ibat[BAT_UPPER_OFFSET + 0]);
break;
case 0b1001010000:
move_to_or_from_spr(ibat[BAT_UPPER_OFFSET + 1]);
break;
case 0b1010010000:
move_to_or_from_spr(ibat[BAT_UPPER_OFFSET + 2]);
break;
case 0b1011010000:
move_to_or_from_spr(ibat[BAT_UPPER_OFFSET + 3]);
break;
case 0b1100110000:
move_to_or_from_spr(dbat[BAT_LOWER_OFFSET + 0]);
break;
case 0b1101110000:
move_to_or_from_spr(dbat[BAT_LOWER_OFFSET + 1]);
break;
case 0b1100010000:
move_to_or_from_spr(dbat[BAT_UPPER_OFFSET + 0]);
break;
case 0b1101010000:
move_to_or_from_spr(dbat[BAT_UPPER_OFFSET + 1]);
break;
case 0b1110010000:
move_to_or_from_spr(dbat[BAT_UPPER_OFFSET + 2]);
break;
case 0b1111010000:
move_to_or_from_spr(dbat[BAT_UPPER_OFFSET + 3]);
break;
default:
ircolib::warn("broadway::m{}spr with unimplemented spr field of value "
"0b{:010b} (0x{:04X}) (pc 0x{:08X})",
dir ? 't' : 'f', spr_field, spr_field, pc - 4);
}
}
void broadway::stwu(ircolib::u32 instr, mem &mem) {
if (utils::RA(instr) == 0)
ircolib::panic("broadway::stwu with ra == 0");
const ircolib::u32 EA = ircolib::s32(gpr[utils::RA(instr)]) + utils::SIMM(instr);
auto _ = mem.write32(EA, gpr[utils::RS(instr)])
.and_then([&] {
gpr[utils::RA(instr)] = EA;
return std::expected<void, std::string>();
})
.or_else([&](std::string e) {
ircolib::panic("stwu broadway write failed. Reason: {} (pc: 0x{:08X})", e, pc - 4);
return std::expected<void, std::string>();
});
}
void broadway::sthu(ircolib::u32 instr, mem &mem) {
if (utils::RA(instr) == 0)
ircolib::panic("broadway::sthu with ra == 0");
const ircolib::u32 EA = ircolib::s32(gpr[utils::RA(instr)]) + utils::SIMM(instr);
auto _ = mem.write16(EA, gpr[utils::RS(instr)])
.and_then([&] {
gpr[utils::RA(instr)] = EA;
return std::expected<void, std::string>();
})
.or_else([&](std::string e) {
ircolib::panic("sthu broadway write failed. Reason: {} (pc: 0x{:08X})", e, pc - 4);
return std::expected<void, std::string>();
});
}
void broadway::stbu(ircolib::u32 instr, mem &mem) {
if (utils::RA(instr) == 0)
ircolib::panic("broadway::stbu with ra == 0");
const ircolib::u32 EA = ircolib::s32(gpr[utils::RA(instr)]) + utils::SIMM(instr);
auto _ = mem.write8(EA, gpr[utils::RS(instr)])
.and_then([&] {
gpr[utils::RA(instr)] = EA;
return std::expected<void, std::string>();
})
.or_else([&](std::string e) {
ircolib::panic("stbu broadway write failed. Reason: {} (pc: 0x{:08X})", e, pc - 4);
return std::expected<void, std::string>();
});
}
void broadway::stw(ircolib::u32 instr, mem &mem) {
ircolib::s32 b = gpr[utils::RA(instr)];
if (utils::RA(instr) == 0)
b = 0;
const ircolib::u32 EA = b + utils::SIMM(instr);
auto _ = mem.write32(EA, gpr[utils::RS(instr)])
.and_then([&] { return std::expected<void, std::string>(); })
.or_else([&](std::string e) {
ircolib::panic("stw broadway write failed. Reason: {} (pc: 0x{:08X})", e, pc - 4);
return std::expected<void, std::string>();
});
}
void broadway::stb(ircolib::u32 instr, mem &mem) {
ircolib::s32 b = gpr[utils::RA(instr)];
if (utils::RA(instr) == 0)
b = 0;
const ircolib::u32 EA = b + utils::SIMM(instr);
auto _ = mem.write8(EA, gpr[utils::RS(instr)])
.and_then([&] { return std::expected<void, std::string>(); })
.or_else([&](std::string e) {
ircolib::panic("stw broadway write failed. Reason: {} (pc: 0x{:08X})", e, pc - 4);
return std::expected<void, std::string>();
});
}
void broadway::sth(ircolib::u32 instr, mem &mem) {
ircolib::u32 b = gpr[utils::RA(instr)];
if (utils::RA(instr) == 0)
b = 0;
const ircolib::u32 EA = b + utils::SIMM(instr);
auto _ = mem.write16(EA, ircolib::u16(gpr[utils::RS(instr)]))
.and_then([&] { return std::expected<void, std::string>(); })
.or_else([&](std::string e) {
ircolib::panic("sth broadway write failed. Reason: {} (pc: 0x{:08X})", e, pc - 4);
return std::expected<void, std::string>();
});
}
void broadway::stwx(ircolib::u32 instr, mem &mem) {
ircolib::u32 b = gpr[utils::RA(instr)];
if (utils::RA(instr) == 0)
b = 0;
const ircolib::u32 EA = b + gpr[utils::RB(instr)];
auto _ = mem.write32(EA, gpr[utils::RS(instr)])
.and_then([&] { return std::expected<void, std::string>(); })
.or_else([&](std::string e) {
ircolib::panic("stwx broadway write failed. Reason: {} (pc: 0x{:08X})", e, pc - 4);
return std::expected<void, std::string>();
});
}
void broadway::lwz(ircolib::u32 instr, mem &mem) {
ircolib::u32 b = gpr[utils::RA(instr)];
if (utils::RA(instr) == 0)
b = 0;
ircolib::u32 ea = ircolib::s32(b) + utils::SIMM(instr);
gpr[utils::RD(instr)] = mem.read32(ea)
.and_then([&](ircolib::u32 val) { return std::expected<ircolib::u32, std::string>(val); })
.or_else([&](std::string e) {
ircolib::panic("lwz broadway read failed. Reason {} (pc: 0x{:08X})", e, pc - 4);
return std::expected<ircolib::u32, std::string>();
})
.value();
}
void broadway::lwzx(ircolib::u32 instr, mem &mem) {
ircolib::u32 b = gpr[utils::RA(instr)];
if (utils::RA(instr) == 0)
b = 0;
ircolib::u32 ea = ircolib::s32(b) + gpr[utils::RB(instr)];
gpr[utils::RD(instr)] = mem.read32(ea)
.and_then([&](ircolib::u32 val) { return std::expected<ircolib::u32, std::string>(val); })
.or_else([&](std::string e) {
ircolib::panic("lwz broadway read failed. Reason {} (pc: 0x{:08X})", e, pc - 4);
return std::expected<ircolib::u32, std::string>();
})
.value();
}
void broadway::lhz(ircolib::u32 instr, mem &mem) {
ircolib::u32 b = gpr[utils::RA(instr)];
if (utils::RA(instr) == 0)
b = 0;
ircolib::u32 ea = ircolib::s32(b) + utils::SIMM(instr);
gpr[utils::RD(instr)] = mem.read16(ea)
.and_then([&](ircolib::u32 val) { return std::expected<ircolib::u32, std::string>(val); })
.or_else([&](std::string e) {
ircolib::panic("lhz broadway read failed. Reason {} (pc: 0x{:08X})", e, pc - 4);
return std::expected<ircolib::u32, std::string>();
})
.value();
}
void broadway::lhzx(ircolib::u32 instr, mem &mem) {
ircolib::u32 b = gpr[utils::RA(instr)];
if (utils::RA(instr) == 0)
b = 0;
ircolib::u32 ea = ircolib::s32(b) + gpr[utils::RB(instr)];
gpr[utils::RD(instr)] = mem.read16(ea)
.and_then([&](ircolib::u32 val) { return std::expected<ircolib::u32, std::string>(val); })
.or_else([&](std::string e) {
ircolib::panic("lhzx broadway read failed. Reason {} (pc: 0x{:08X})", e, pc - 4);
return std::expected<ircolib::u32, std::string>();
})
.value();
}
void broadway::lbz(ircolib::u32 instr, mem &mem) {
ircolib::u32 b = gpr[utils::RA(instr)];
if (utils::RA(instr) == 0)
b = 0;
ircolib::u32 ea = ircolib::s32(b) + utils::SIMM(instr);
gpr[utils::RD(instr)] = mem.read8(ea)
.and_then([&](ircolib::u32 val) { return std::expected<ircolib::u32, std::string>(val); })
.or_else([&](std::string e) {
ircolib::panic("lbz broadway read failed. Reason {} (pc: 0x{:08X})", e, pc - 4);
return std::expected<ircolib::u32, std::string>();
})
.value();
}
void broadway::lfd(ircolib::u32 instr, mem &mem) {
ircolib::u32 b = gpr[utils::RA(instr)];
if (utils::RA(instr) == 0)
b = 0;
ircolib::u32 ea = ircolib::s32(b) + utils::SIMM(instr);
fgrs[utils::RD(instr)].ps0 =
mem.read64(ea)
.and_then([&](ircolib::u64 val) { return std::expected<ircolib::u64, std::string>(val); })
.or_else([&](std::string e) {
ircolib::panic("lfd broadway read failed. Reason {} (pc: 0x{:08X})", e, pc - 4);
return std::expected<ircolib::u64, std::string>();
})
.value();
}
void broadway::bclrx(ircolib::u32 instr) {
const bool link = instr & 1;
ircolib::s32 bd = lr & 0xFFFFFFFC;
if (test_cond_and_ctr(instr)) {
branch(true, link, bd);
}
}
void broadway::cmpi(ircolib::u32 instr) {
const ircolib::s32 a = gpr[utils::RA(instr)];
const ircolib::s32 simm = utils::SIMM(instr);
ircolib::u8 c;
if (a < simm)
c = 0b001;
else if (a > simm)
c = 0b010;
else
c = 0b100;
const ircolib::u8 result = (xer.so << 3) | c;
set_cr(result, utils::crfD(instr));
}
void broadway::cmpli(ircolib::u32 instr) {
const ircolib::u32 a = gpr[utils::RA(instr)];
const ircolib::u32 uimm = utils::UIMM(instr);
ircolib::u8 c;
if (a < uimm)
c = 0b001;
else if (a > uimm)
c = 0b010;
else
c = 0b100;
const ircolib::u8 result = (xer.so << 3) | c;
set_cr(result, utils::crfD(instr));
}
void broadway::cmp(ircolib::u32 instr) {
const ircolib::s32 a = gpr[utils::RA(instr)];
const ircolib::s32 b = gpr[utils::RB(instr)];
ircolib::u8 c;
if (a < b)
c = 0b001;
else if (a > b)
c = 0b010;
else
c = 0b100;
const ircolib::u8 result = (xer.so << 3) | c;
set_cr(result, utils::crfD(instr));
}
void broadway::cmpl(ircolib::u32 instr) {
const ircolib::u32 a = gpr[utils::RA(instr)];
const ircolib::u32 b = gpr[utils::RB(instr)];
ircolib::u8 c;
if (a < b)
c = 0b001;
else if (a > b)
c = 0b010;
else
c = 0b100;
const ircolib::u8 result = (xer.so << 3) | c;
set_cr(result, utils::crfD(instr));
}
void broadway::rlwinm(ircolib::u32 instr) {
const ircolib::u8 sh = (instr >> 11) & 0x1f;
ircolib::u32 r = std::rotl(gpr[utils::RS(instr)], sh);
const ircolib::u8 mb = (instr >> 6) & 0x1f;
const ircolib::u8 me = (instr >> 1) & 0x1f;
const ircolib::u32 start = 0xffffffff >> mb;
const ircolib::u32 end = 0x7fffffff >> me;
ircolib::u32 mask = start ^ end;
if (mb > me)
mask = ~mask;
r &= mask;
gpr[utils::RA(instr)] = r;
cr0_update(instr & 1, r);
}
void broadway::rlwimi(ircolib::u32 instr) {
const ircolib::u8 sh = (instr >> 11) & 0x1f;
ircolib::u32 r = std::rotl(gpr[utils::RS(instr)], sh);
const ircolib::u8 mb = (instr >> 6) & 0x1f;
const ircolib::u8 me = (instr >> 1) & 0x1f;
const ircolib::u32 start = 0xffffffff >> mb;
const ircolib::u32 end = 0x7fffffff >> me;
ircolib::u32 mask = start ^ end;
if (mb > me)
mask = ~mask;
r &= mask;
r |= (gpr[utils::RA(instr)] & ~mask);
gpr[utils::RA(instr)] = r;
cr0_update(instr & 1, r);
}
void broadway::lwzu(ircolib::u32 instr, mem &mem) {
if (utils::RA(instr) == 0 || utils::RA(instr) == utils::RD(instr))
ircolib::panic("broadway::lwzu with ra == 0");
const ircolib::u32 EA = ircolib::s32(gpr[utils::RA(instr)]) + utils::SIMM(instr);
gpr[utils::RD(instr)] = mem.read32(EA)
.and_then([&](ircolib::u32 val) {
gpr[utils::RA(instr)] = EA;
return std::expected<ircolib::u32, std::string>(val);
})
.or_else([&](std::string e) {
ircolib::panic("lwzu broadway read failed. Reason {} (pc: 0x{:08X})", e, pc - 4);
return std::expected<ircolib::u32, std::string>();
})
.value();
}
void broadway::rfi(ircolib::u32 instr) {
pc = srr0;
ircolib::clear_bit(msr, 13);
}
void broadway::andi(ircolib::u32 instr) {
const ircolib::s32 result = gpr[utils::RS(instr)] & utils::UIMM(instr);
gpr[utils::RA(instr)] = result;
cr0_update(true, result);
}
void broadway::andis(ircolib::u32 instr) {
const ircolib::s32 result = gpr[utils::RS(instr)] & (ircolib::u32(utils::UIMM(instr)) << 16);
gpr[utils::RA(instr)] = result;
cr0_update(true, result);
}
void broadway::and(ircolib::u32 instr) {
const ircolib::s32 result = gpr[utils::RS(instr)] & gpr[utils::RB(instr)];
gpr[utils::RA(instr)] = result;
cr0_update(instr & 1, result);
}
void broadway::mtfsf(ircolib::u32 instr) {
const ircolib::u8 fm = (instr >> 17) & 0xff;
ircolib::u8 mask = 0;
for (int i = 0; i < 8; i++) {
if (ircolib::is_bit_set(fm, i)) {
mask |= 0xf << (i * 4);
}
}
ircolib::u32 frb = fgrs[utils::RB(instr)].ps0;
fpscr = (fpscr & ~mask) | (frb & mask);
cr1_update(instr & 1);
}
void broadway::mtfsb0(ircolib::u32 instr) {
ircolib::u32 mask = ~(1 << utils::RD(instr));
fpscr = fpscr & mask;
cr1_update(instr & 1);
}
void broadway::mtfsb1(ircolib::u32 instr) {
ircolib::u32 bit = 1 << utils::RD(instr);
ircolib::u32 mask = ~bit;
fpscr = (fpscr & mask) | bit;
cr1_update(instr & 1);
}
void broadway::mfmsr(ircolib::u32 instr) { gpr[utils::RS(instr)] = msr; }
void broadway::mtmsr(ircolib::u32 instr) { msr = gpr[utils::RS(instr)]; }
void broadway::nand(ircolib::u32 instr) {
gpr[utils::RA(instr)] = ~(gpr[utils::RS(instr)] & gpr[utils::RB(instr)]);
cr0_update(instr & 1, gpr[utils::RA(instr)]);
}
void broadway::subf(ircolib::u32 instr) {
gpr[utils::RD(instr)] = ~gpr[utils::RA(instr)] + gpr[utils::RB(instr)];
cr0_update(instr & 1, gpr[utils::RD(instr)]);
}
void broadway::subfc(ircolib::u32 instr) {
ircolib::u32 sum;
bool c0 = __builtin_add_overflow(~gpr[utils::RA(instr)], 1, &sum);
bool c1 = __builtin_add_overflow(sum, gpr[utils::RB(instr)], &sum);
cr0_update(instr & 1, sum);
xer.ca = !c0 | c1;
gpr[utils::RD(instr)] = sum;
}
void broadway::subfic(ircolib::u32 instr) {
ircolib::u32 sum;
bool c0 = __builtin_add_overflow(~gpr[utils::RA(instr)], 1, &sum);
bool c1 = __builtin_add_overflow(sum, utils::SIMM(instr), &sum);
xer.ca = !c0 | c1;
gpr[utils::RD(instr)] = sum;
}
void broadway::subfe(ircolib::u32 instr) {
ircolib::u32 sum;
bool c0 = __builtin_add_overflow(~gpr[utils::RA(instr)], gpr[utils::RB(instr)], &sum);
bool c1 = __builtin_add_overflow(sum, xer.ca, &sum);
cr0_update(instr & 1, sum);
xer.ca = c0 | c1;
gpr[utils::RD(instr)] = sum;
}
void broadway:: or (ircolib::u32 instr) {
gpr[utils::RA(instr)] = gpr[utils::RS(instr)] | gpr[utils::RB(instr)];
cr0_update(instr & 1, gpr[utils::RA(instr)]);
}
void broadway::xori(ircolib::u32 instr) { gpr[utils::RA(instr)] = gpr[utils::RS(instr)] ^ utils::UIMM(instr); }
void broadway::mullw(ircolib::u32 instr) {
gpr[utils::RD(instr)] = ircolib::u64(gpr[utils::RA(instr)]) * ircolib::u64(gpr[utils::RB(instr)]);
}
void broadway::mulli(ircolib::u32 instr) {
gpr[utils::RD(instr)] = ircolib::u64(gpr[utils::RA(instr)]) * ircolib::u64(utils::SIMM(instr));
}
void broadway::mfcr(ircolib::u32 instr) { gpr[utils::RD(instr)] = cr; }
void broadway::mtcrf(ircolib::u32 instr) {
ircolib::u32 mask = 0;
const ircolib::u8 crm = (instr >> 13) & 0xff;
for (int i = 0; i < 7; i++) {
if (ircolib::is_bit_set(crm, i)) {
set_cr(gpr[utils::RS(instr)] & (0xffff << i * 4), i);
}
}
}
void broadway::divwu(ircolib::u32 instr) {
ircolib::u32 dividend = gpr[utils::RA(instr)];
ircolib::u32 divisor = gpr[utils::RB(instr)];
if (divisor == 0) {
if ((instr >> 11) & 1)
xer.ov = true;
return;
}
gpr[utils::RD(instr)] = dividend / divisor;
cr0_update(instr & 1, gpr[utils::RD(instr)]);
}
void broadway::mftb(ircolib::u32 instr) {
const ircolib::u32 tbr = (instr >> 11) & 0x3FF;
if (tbr != 392 && tbr != 424)
ircolib::panic("broadway::mftb with tbr != 268 && != 269 ({})", tbr);
if (tbr == 392)
gpr[utils::RD(instr)] = tbl;
if (tbr == 424)
gpr[utils::RD(instr)] = tbu;
}
void broadway::sraw(ircolib::u32 instr) {
ircolib::u8 shift = std::min(gpr[utils::RB(instr)] & 0x3f, ircolib::u32(31));
ircolib::s32 rs = gpr[utils::RS(instr)];
ircolib::s32 result = rs >> shift;
ircolib::u32 mask = (1 << shift) - 1;
cr0_update(instr & 1, result);
xer.ca = (rs < 0) & ((ircolib::u32(rs) & mask) != 0);
gpr[utils::RA(instr)] = result;
}
} // namespace weee::core
+31
View File
@@ -0,0 +1,31 @@
#include <broadway/mmio/ai.hpp>
#include <mem.hpp>
#include <ircolib/log.hpp>
namespace weee::core {
audio_interface::audio_interface(mem &mem) {
mem.register_read32_handler(0x0c006c00, 0x0c006c1f, [&](ircolib::u32 addr) { return read32(addr); });
mem.register_write32_handler(0x0c006c00, 0x0c006c1f,
[&](ircolib::u32 addr, ircolib::u32 value) { return write32(addr, value); });
}
ircolib::u32 audio_interface::read32(ircolib::u32 addr) {
switch (addr) {
case 0:
return ctrl.raw;
default:
ircolib::panic("audio_interface::read32 from unimplemented addr 0x{:08X}", addr);
return 0;
}
}
void audio_interface::write32(ircolib::u32 addr, ircolib::u32 value) {
switch (addr) {
case 0:
ctrl.raw = value;
break;
default:
ircolib::panic("audio_interface::write32 to unimplemented addr 0x{:08X} with value 0x{:08X}", addr, value);
}
}
} // namespace weee::core
+26
View File
@@ -0,0 +1,26 @@
#pragma once
#include <ircolib/types.hpp>
namespace weee::core {
struct mem;
struct audio_interface {
audio_interface(mem &);
ircolib::u32 read32(ircolib::u32);
void write32(ircolib::u32, ircolib::u32);
union {
struct {
unsigned pstat : 1;
unsigned afr : 1;
unsigned aiintmsk : 1;
unsigned aiint : 1;
unsigned aiintvld : 1;
unsigned screset : 1;
unsigned dsp_sr : 1;
unsigned : 25;
};
ircolib::u32 raw;
} ctrl;
};
} // namespace weee::core
+152
View File
@@ -0,0 +1,152 @@
#include <broadway/mmio/dsp.hpp>
#include <mem.hpp>
#include <ircolib/log.hpp>
namespace weee::core {
dsp::dsp(mem &mem) {
mem.register_read16_handler(0x0c005000, 0x0c0051ff, [&](ircolib::u32 addr) { return read16(addr); });
mem.register_write16_handler(0x0c005000, 0x0c0051ff,
[&](ircolib::u32 addr, ircolib::u16 value) { return write16(addr, value); });
mem.register_read32_handler(0x0c005000, 0x0c0051ff, [&](ircolib::u32 addr) { return read32(addr); });
mem.register_write32_handler(0x0c005000, 0x0c0051ff,
[&](ircolib::u32 addr, ircolib::u32 value) { return write32(addr, value); });
}
ircolib::u32 dsp::read32(ircolib::u32 addr) {
switch (addr) {
case 0x20:
return ar_dma_mmaddr.whole;
case 0x24:
return ar_dma_araddr.whole;
case 0x28:
return ar_dma_cnt.whole;
case 0x30:
return dma_start_addr.whole;
default:
ircolib::panic("dsp::read32 from unimplemented addr 0x{:08X}", addr);
return 0;
}
}
void dsp::write32(ircolib::u32 addr, ircolib::u32 value) {
switch (addr) {
case 0x20:
ar_dma_mmaddr.whole = value;
break;
case 0x24:
ar_dma_araddr.whole = value;
break;
case 0x28:
ar_dma_cnt.whole = value;
break;
case 0x30:
dma_start_addr.whole = value;
break;
default:
ircolib::panic("dsp::write32 to unimplemented addr 0x{:08X} with value 0x{:08X}", addr, value);
}
}
ircolib::u16 dsp::read16(ircolib::u32 addr) {
switch (addr) {
case 0x00:
return dsp_mail_hi;
case 0x02:
return dsp_mail_lo;
case 0x04:
return cpu_mail_hi;
case 0x06:
return cpu_mail_lo;
case 0x0a:
return csr.raw;
case 0x12:
return ar_size;
case 0x20:
return ar_dma_mmaddr.hi;
case 0x22:
return ar_dma_mmaddr.lo;
case 0x24:
return ar_dma_araddr.hi;
case 0x26:
return ar_dma_araddr.lo;
case 0x28:
return ar_dma_cnt.hi;
case 0x2a:
return ar_dma_cnt.lo;
case 0x30:
return dma_start_addr.hi;
case 0x32:
return dma_start_addr.lo;
default:
ircolib::panic("dsp::read16 from unimplemented addr 0x{:08X}", addr);
return 0;
}
}
void dsp::write16(ircolib::u32 addr, ircolib::u16 value) {
switch (addr) {
case 0x00:
dsp_mail_hi = value;
break;
case 0x02:
dsp_mail_lo = value;
break;
case 0x0a:
{
Csr ccsr = {.raw = value};
Csr ocsr = csr;
csr = ccsr;
if (csr.res || (ocsr.boot_mode != ccsr.boot_mode && ccsr.boot_mode)) {
cpu_mail_hi = 0;
cpu_mail_lo = 0;
dsp_mail_hi = 0;
dsp_mail_lo = 0;
}
if (csr.piint)
csr.piint = false;
if (csr.aidint)
csr.aidint = false;
if (csr.arint)
csr.arint = false;
if (csr.dspint)
csr.dspint = false;
}
break;
case 0x12:
ar_size = value;
break;
case 0x20:
ar_dma_mmaddr.hi = value;
break;
case 0x22:
ar_dma_mmaddr.lo = value;
break;
case 0x24:
ar_dma_araddr.hi = value;
break;
case 0x26:
ar_dma_araddr.lo = value;
break;
case 0x28:
ar_dma_cnt.hi = value;
break;
case 0x2a:
ar_dma_cnt.lo = value;
csr.arint = true;
break;
case 0x30:
dma_start_addr.hi = value;
break;
case 0x32:
dma_start_addr.lo = value;
break;
default:
ircolib::panic("dsp::write16 from unimplemented addr 0x{:08X} with value 0x{:04X}", addr, value);
}
}
} // namespace weee::core
+43
View File
@@ -0,0 +1,43 @@
#pragma once
#include <ircolib/types.hpp>
namespace weee::core {
struct mem;
struct dsp {
dsp(mem &);
ircolib::u16 read16(ircolib::u32);
void write16(ircolib::u32, ircolib::u16);
ircolib::u32 read32(ircolib::u32);
void write32(ircolib::u32, ircolib::u32);
union Csr {
struct {
unsigned res : 1;
unsigned piint : 1;
unsigned halt : 1;
unsigned aidint : 1;
unsigned aidint_mask : 1;
unsigned arint : 1;
unsigned arint_mask : 1;
unsigned dspint : 1;
unsigned dspint_mask : 1;
unsigned int_status : 1;
unsigned : 1;
unsigned boot_mode : 1;
unsigned : 4;
};
ircolib::u16 raw;
} csr;
union {
struct {
ircolib::u32 lo;
ircolib::u32 hi;
};
ircolib::u64 whole;
} ar_dma_mmaddr, ar_dma_araddr, ar_dma_cnt, dma_start_addr;
ircolib::u16 ar_size;
ircolib::u16 dsp_mail_hi = 0, dsp_mail_lo = 0, cpu_mail_hi = 0, cpu_mail_lo = 0;
};
} // namespace weee::core
+41
View File
@@ -0,0 +1,41 @@
#include <broadway/mmio/exi.hpp>
#include <mem.hpp>
#include <ircolib/log.hpp>
namespace weee::core {
exi::exi(mem &mem) {
mem.register_read32_handler(0x0c006800, 0x0c00683f, [&](ircolib::u32 addr) { return read32(addr); });
mem.register_write32_handler(0x0c006800, 0x0c00683f,
[&](ircolib::u32 addr, ircolib::u32 value) { return write32(addr, value); });
}
ircolib::u32 exi::read32(ircolib::u32 addr) {
switch (addr) {
case 0:
return param0.raw;
case 0x14:
return param1.raw;
case 0x28:
return param2.raw;
default:
ircolib::panic("exi::read32 from unimplemented addr 0x{:08X}", addr);
return 0;
}
}
void exi::write32(ircolib::u32 addr, ircolib::u32 value) {
switch (addr) {
case 0:
param0.raw = value;
break;
case 0x14:
param1.raw = value;
break;
case 0x28:
param2.raw = value;
break;
default:
ircolib::panic("exi::write32 to unimplemented addr 0x{:08X} with value 0x{:08X}", addr, value);
}
}
} // namespace weee::core
+30
View File
@@ -0,0 +1,30 @@
#pragma once
#include <ircolib/types.hpp>
namespace weee::core {
struct mem;
struct exi {
exi(mem &);
ircolib::u32 read32(ircolib::u32);
void write32(ircolib::u32, ircolib::u32);
union {
struct {
unsigned ext_int_mask : 1;
unsigned ext_int : 1;
unsigned tc_int_mask : 1;
unsigned tc_int : 1;
unsigned clk : 3;
unsigned cs : 3;
unsigned ext_int_mask2 : 1;
unsigned ext_int2 : 1;
unsigned ext : 1;
unsigned romdis : 1;
unsigned : 18;
};
ircolib::u32 raw;
} param0, param1, param2;
};
} // namespace weee::core
+20
View File
@@ -0,0 +1,20 @@
#include <mem.hpp>
#include <broadway/mmio/mi.hpp>
#include <ircolib/log.hpp>
namespace weee::core {
memory_interface::memory_interface(mem &mem) {
mem.register_write16_handler(0x0c004000, 0x0c00407f,
[&](ircolib::u32 addr, ircolib::u16 value) { write16(addr, value); });
}
void memory_interface::write16(ircolib::u32 addr, ircolib::u16 value) {
switch (addr) {
case 0x1C:
int_mask.raw = value;
break;
default:
ircolib::panic("memory_interface::write16 to unimplemented addr 0x{:08X} with value 0x{:04X}", addr, value);
}
}
} // namespace weee::core
+23
View File
@@ -0,0 +1,23 @@
#pragma once
#include <ircolib/types.hpp>
namespace weee::core {
struct mem;
struct memory_interface {
union {
struct {
unsigned mem0 : 1;
unsigned mem1 : 1;
unsigned mem2 : 1;
unsigned mem3 : 1;
unsigned all : 1;
unsigned : 27;
};
ircolib::u32 raw;
} int_mask;
memory_interface(mem &);
void write16(ircolib::u32, ircolib::u16);
};
} // namespace weee::core
+31
View File
@@ -0,0 +1,31 @@
#include <mem.hpp>
#include <broadway/mmio/pi.hpp>
#include <ircolib/log.hpp>
namespace weee::core {
processor_interface::processor_interface(mem &mem) {
mem.register_write32_handler(0x0c003000, 0x0c0030ff,
[&](ircolib::u32 addr, ircolib::u32 value) { return write32(addr, value); });
mem.register_read32_handler(0x0c003000, 0x0c0030ff, [&](ircolib::u32 addr) { return read32(addr); });
}
void processor_interface::write32(ircolib::u32 addr, ircolib::u32 value) {
switch (addr) {
case 0x04:
intmr.raw = value;
break;
default:
ircolib::panic("processor_interface::write32 to unimplemented addr 0x{:08X} with value 0x{:08X}", addr, value);
}
}
ircolib::u32 processor_interface::read32(ircolib::u32 addr) {
switch (addr) {
case 0x2c:
return 2;
default:
ircolib::panic("processor_interface::read32 from unimplemented addr 0x{:08X}", addr);
return 0;
}
}
} // namespace weee::core
+33
View File
@@ -0,0 +1,33 @@
#pragma once
#include <ircolib/types.hpp>
namespace weee::core {
struct mem;
struct processor_interface {
union {
struct {
unsigned error : 1;
unsigned rsw : 1;
unsigned di : 1;
unsigned si : 1;
unsigned exi : 1;
unsigned ai : 1;
unsigned dsp : 1;
unsigned mem : 1;
unsigned vi : 1;
unsigned pe_token : 1;
unsigned pe_finish : 1;
unsigned cp : 1;
unsigned debug : 1;
unsigned hsp : 1;
unsigned : 18;
};
ircolib::u32 raw;
} intmr;
processor_interface(mem &);
void write32(ircolib::u32, ircolib::u32);
ircolib::u32 read32(ircolib::u32);
};
} // namespace weee::core
+46
View File
@@ -0,0 +1,46 @@
#include <broadway/mmio/si.hpp>
#include <mem.hpp>
#include <ircolib/log.hpp>
namespace weee::core {
serial_interface::serial_interface(mem &mem) {
mem.register_read32_handler(0x0c006400, 0x0c0064ff, [&](ircolib::u32 addr) { return read32(addr); });
mem.register_write32_handler(0x0c006400, 0x0c0064ff,
[&](ircolib::u32 addr, ircolib::u32 value) { return write32(addr, value); });
}
ircolib::u32 serial_interface::read32(ircolib::u32 addr) {
switch (addr) {
case 0x30:
return sipoll.raw;
case 0x34:
return sicomcsr.raw;
case 0x38:
return sisr.raw;
case 0x3C:
return clock_lk.raw;
default:
ircolib::panic("serial_interface::read32 from unimplemented addr 0x{:08X}", addr);
return 0;
}
}
void serial_interface::write32(ircolib::u32 addr, ircolib::u32 value) {
switch (addr) {
case 0x30:
sipoll.raw = value;
break;
case 0x34:
sicomcsr.raw = value;
break;
case 0x38:
sisr.raw = value;
break;
case 0x3C:
clock_lk.raw = value;
break;
default:
ircolib::panic("serial_interface::write32 to unimplemented addr 0x{:08X} with value 0x{:08X}", addr, value);
}
}
} // namespace weee::core
+75
View File
@@ -0,0 +1,75 @@
#pragma once
#include <ircolib/types.hpp>
namespace weee::core {
struct mem;
struct serial_interface {
serial_interface(mem &);
ircolib::u32 read32(ircolib::u32);
void write32(ircolib::u32, ircolib::u32);
union {
struct {
unsigned vbcpy : 4;
unsigned en : 4;
unsigned y : 8;
unsigned x : 8;
unsigned : 8;
};
ircolib::u32 raw;
} sipoll;
union {
struct {
unsigned tstart : 1;
unsigned channel : 2;
unsigned cben : 1;
unsigned cmden : 1;
unsigned inlength : 7;
unsigned : 1;
unsigned outlength : 7;
unsigned : 1;
unsigned chen : 1;
unsigned chnum : 2;
unsigned rdstintmsk : 1;
unsigned rdstint : 1;
unsigned comerr : 1;
unsigned tcintmsk : 1;
unsigned tcint : 1;
};
ircolib::u32 raw;
} sicomcsr;
union {
struct {
unsigned : 31;
unsigned lock : 1;
};
ircolib::u32 raw;
} clock_lk;
union {
struct {
unsigned joy3 : 6;
unsigned : 2;
unsigned joy2 : 6;
unsigned : 2;
unsigned joy1 : 6;
unsigned : 2;
unsigned unrun : 1;
unsigned ovrun0 : 1;
unsigned coll0 : 1;
unsigned norep0 : 1;
unsigned wrst0 : 1;
unsigned rdst0 : 1;
unsigned : 1;
unsigned wr : 1;
};
ircolib::u32 raw;
} sisr;
};
} // namespace weee::core
+133
View File
@@ -0,0 +1,133 @@
#include <broadway/mmio/vi.hpp>
#include <ircolib/log.hpp>
#include <mem.hpp>
namespace weee::core {
video_interface::video_interface(mem &mem) {
mem.register_read16_handler(0x0c002000, 0x0c0020ff, [&](ircolib::u32 addr) { return read16(addr); });
mem.register_read32_handler(0x0c002000, 0x0c0020ff, [&](ircolib::u32 addr) { return read32(addr); });
mem.register_write16_handler(0x0c002000, 0x0c0020ff,
[&](ircolib::u32 addr, ircolib::u16 value) { write16(addr, value); });
mem.register_write32_handler(0x0c002000, 0x0c0020ff,
[&](ircolib::u32 addr, ircolib::u32 value) { write32(addr, value); });
}
ircolib::u16 video_interface::read16(ircolib::u32 addr) {
switch (addr) {
case 0x00:
return vtr.raw;
case 0x02:
return dcr.raw;
case 0x4a:
return hsr.raw;
case 0x6c:
return viclk & 1;
case 0x70:
return 0x0280;
default:
ircolib::panic("video_interface::read16 from unimplemented addr 0x{:04X}", addr);
return 0;
}
}
ircolib::u32 video_interface::read32(ircolib::u32 addr) {
switch (addr) {
case 0x02:
return dcr.raw;
case 0x04:
return htr0.raw;
case 0x08:
return htr1.raw;
case 0x0c:
return vto.raw;
case 0x10:
return vte.raw;
case 0x14:
return bbei.raw;
case 0x18:
return bboi.raw;
case 0x1c:
return tfbl.raw & 0x1ffffe00;
case 0x24:
return bfbl.raw & 0x10fffe00;
case 0x4c:
case 0x50:
case 0x54:
return fct0[addr - 0x4c].raw;
case 0x58:
case 0x5c:
case 0x60:
case 0x64:
return fct1[addr - 0x58].raw;
default:
ircolib::panic("video_interface::read32 from unimplemented addr 0x{:04X}", addr);
return 0;
}
}
void video_interface::write16(ircolib::u32 addr, ircolib::u16 value) {
switch (addr) {
case 0x00:
vtr.raw = value;
break;
case 0x02:
dcr.raw = value;
break;
case 0x4a:
hsr.raw = value;
break;
case 0x6c:
viclk = value & 1;
break;
case 0x70:
break;
default:
ircolib::panic("video_interface::write16 to unimplemented addr 0x{:04X} with value 0x{:04X}", addr, value);
}
}
void video_interface::write32(ircolib::u32 addr, ircolib::u32 value) {
switch (addr) {
case 0x02:
dcr.raw = value;
break;
case 0x04:
htr0.raw = value;
break;
case 0x08:
htr1.raw = value;
break;
case 0x0c:
vto.raw = value;
break;
case 0x10:
vte.raw = value;
break;
case 0x14:
bbei.raw = value;
break;
case 0x18:
bboi.raw = value;
break;
case 0x1c:
tfbl.raw = value & 0x1ffffe00;
break;
case 0x24:
bfbl.raw = value & 0x10fffe00;
break;
case 0x4c:
case 0x50:
case 0x54:
fct0[addr - 0x4c].raw = value;
break;
case 0x58:
case 0x5c:
case 0x60:
case 0x64:
fct1[addr - 0x58].raw = value;
break;
default:
ircolib::panic("video_interface::write32 to unimplemented addr 0x{:04X} with value 0x{:08X}", addr, value);
}
}
} // namespace weee::core
+139
View File
@@ -0,0 +1,139 @@
#pragma once
#include <ircolib/types.hpp>
namespace weee::core {
struct mem;
struct video_interface {
video_interface(mem &);
void write16(ircolib::u32, ircolib::u16);
void write32(ircolib::u32, ircolib::u32);
ircolib::u16 read16(ircolib::u32);
ircolib::u32 read32(ircolib::u32);
ircolib::u32 xfb_top_addr() {
auto addr = tfbl.fbb;
if (tfbl.page) {
addr <<= 5;
}
return addr + tfbl.xof;
}
union DCR {
struct {
unsigned e : 1;
unsigned r : 1;
unsigned i : 1;
unsigned d : 1;
unsigned le0 : 2;
unsigned le1 : 2;
unsigned fmt : 2;
unsigned : 6;
};
ircolib::u16 raw;
} dcr;
union HTR0 {
struct {
unsigned hlw : 9;
unsigned : 7;
unsigned hce : 7;
unsigned : 1;
unsigned hcs : 7;
unsigned : 1;
};
ircolib::u32 raw;
} htr0;
union HTR1 {
struct {
unsigned hsy : 7;
unsigned hbe : 10;
unsigned hbs : 10;
unsigned : 5;
};
ircolib::u32 raw;
} htr1;
union VTR {
struct {
unsigned equ : 4;
unsigned acv : 10;
unsigned : 2;
};
ircolib::u16 raw;
} vtr;
union VTO {
struct {
unsigned prb : 10;
unsigned : 6;
unsigned psb : 10;
unsigned : 6;
};
ircolib::u32 raw;
} vto, vte;
union BBI {
struct {
unsigned bs1 : 5;
unsigned be1 : 11;
unsigned bs3 : 5;
unsigned be3 : 11;
};
ircolib::u32 raw;
} bbei, bboi;
union FBR {
struct {
unsigned : 3;
unsigned page : 1;
unsigned xof : 4;
unsigned fbb : 24;
};
ircolib::u32 raw;
} tfbl{}, bfbl{};
union FCT012 {
struct {
unsigned tap0 : 10;
unsigned tap1 : 10;
unsigned tap2 : 10;
unsigned : 2;
};
ircolib::u32 raw;
} fct0[3];
union FCT3456 {
struct {
unsigned tap0 : 8;
unsigned tap1 : 8;
unsigned tap2 : 8;
unsigned tap3 : 8;
};
ircolib::u32 raw;
} fct1[4];
union HSR {
struct {
unsigned stp : 9;
unsigned : 3;
unsigned hs_en : 1;
unsigned : 3;
};
ircolib::u16 raw;
} hsr;
bool viclk;
};
} // namespace weee::core
+14
View File
@@ -0,0 +1,14 @@
#pragma once
#include <broadway.hpp>
namespace weee::core::utils {
static inline ircolib::u8 primary(ircolib::u32 instr) { return (instr >> 26) & 0x3f; }
static inline ircolib::u16 secondary(ircolib::u32 instr) { return (instr >> 1) & 0x3ff; }
static inline ircolib::u8 RD(ircolib::u32 instr) { return (instr >> 21) & 0x1f; }
static inline ircolib::u8 RB(ircolib::u32 instr) { return (instr >> 11) & 0x1f; }
static inline ircolib::u8 RS(ircolib::u32 instr) { return RD(instr); }
static inline ircolib::u8 RA(ircolib::u32 instr) { return (instr >> 16) & 0x1f; }
static inline ircolib::u16 UIMM(ircolib::u32 instr) { return instr & 0xffff; }
static inline ircolib::s16 SIMM(ircolib::u32 instr) { return UIMM(instr); }
static inline ircolib::u8 crfD(ircolib::u32 instr) { return (instr >> 23) & 7; }
} // namespace weee::core::utils
+64
View File
@@ -0,0 +1,64 @@
#include <loaders/dol.hpp>
#include <mem.hpp>
#include <broadway.hpp>
#include <ircolib/file.hpp>
#include <ircolib/mem_access.hpp>
#include <array>
namespace weee::core {
bool load_dol(const std::string &path, mem &mem, broadway &broadway) {
auto bin = ircolib::read_file_binary(path);
if (bin.size() <= 0)
return false;
struct header {
struct section {
ircolib::u32 offset, addr, size;
};
std::array<section, 7> text;
std::array<section, 11> data;
ircolib::u32 bss_address, bss_size, entry_point;
} hdr;
for (ircolib::u32 bin_index = 0; bin_index < 0xD8; bin_index += 4) {
if (ircolib::is_inside_range(bin_index, 0, 0x1b)) // text file offsets
hdr.text[bin_index / 4].offset = std::byteswap(ircolib::read_access<ircolib::u32>(bin, bin_index));
if (ircolib::is_inside_range(bin_index, 0x1c, 0x47)) // data file offsets
hdr.data[(bin_index - 0x1c) / 4].offset = std::byteswap(ircolib::read_access<ircolib::u32>(bin, bin_index));
if (ircolib::is_inside_range(bin_index, 0x48, 0x63)) // text loading addresses
hdr.text[(bin_index - 0x48) / 4].addr = std::byteswap(ircolib::read_access<ircolib::u32>(bin, bin_index));
if (ircolib::is_inside_range(bin_index, 0x64, 0x8f)) // data loading addresses
hdr.data[(bin_index - 0x64) / 4].addr = std::byteswap(ircolib::read_access<ircolib::u32>(bin, bin_index));
if (ircolib::is_inside_range(bin_index, 0x90, 0xab)) // text sizes
hdr.text[(bin_index - 0x90) / 4].size = std::byteswap(ircolib::read_access<ircolib::u32>(bin, bin_index));
if (ircolib::is_inside_range(bin_index, 0xac, 0xd7)) // data sizes
hdr.data[(bin_index - 0xac) / 4].size = std::byteswap(ircolib::read_access<ircolib::u32>(bin, bin_index));
}
hdr.bss_address = std::byteswap(ircolib::read_access<ircolib::u32>(bin, 0xD8));
hdr.bss_size = std::byteswap(ircolib::read_access<ircolib::u32>(bin, 0xDC));
mem.set(0, hdr.bss_size, hdr.bss_address & 0x0FFFFFFF);
hdr.entry_point = std::byteswap(ircolib::read_access<ircolib::u32>(bin, 0xE0));
broadway.set_pc(hdr.entry_point);
for (const auto &section : hdr.text) {
if (section.offset == 0)
continue;
mem.copy(&bin[section.offset], section.size, section.addr & 0x0FFFFFFF);
}
for (const auto &section : hdr.data) {
if (section.offset == 0)
continue;
mem.copy(&bin[section.offset], section.size, section.addr & 0x0FFFFFFF);
}
return true;
}
} // namespace weee::core
+10
View File
@@ -0,0 +1,10 @@
#pragma once
#include <ircolib/types.hpp>
#include <string>
namespace weee::core {
struct mem;
struct broadway;
bool load_dol(const std::string &, mem &, broadway &);
} // namespace weee::core
+51
View File
@@ -0,0 +1,51 @@
#include <loaders/elf.hpp>
#include <mem.hpp>
#include <broadway.hpp>
#include <elfio/elfio.hpp>
#include <print>
namespace weee::core {
bool load_elf(const std::string &path, mem &mem, broadway &broadway) {
ELFIO::elfio reader;
if (!reader.load(path))
return false;
ircolib::u32 sanity_bss_check_count = 0;
for (const auto &segment : reader.segments) {
const auto segment_type = segment->get_type();
if (segment_type != ELFIO::PT_LOAD && segment_type != ELFIO::PT_TLS && segment_type != ELFIO::PT_NOTE)
continue;
if (segment->get_memory_size() == 0)
continue;
const bool exc = segment->get_flags() & ELFIO::PF_X;
const bool rd = segment->get_flags() & ELFIO::PF_R;
const bool wr = segment->get_flags() & ELFIO::PF_W;
std::println("Segment {} {}{}{} @ 0x{:08X} -> 0x{:08X}", segment->get_index(), rd ? 'R' : '_', wr ? 'W' : '_',
exc ? 'X' : '_', segment->get_virtual_address(),
segment->get_virtual_address() + segment->get_memory_size() - 1);
if (segment->get_file_size() == 0) {
sanity_bss_check_count++;
if (sanity_bss_check_count > 1) {
std::println("weee does not support multiple .bss segments");
return -2;
}
// .bss we zero out
mem.set(0, segment->get_memory_size(), segment->get_virtual_address() & 0x0FFFFFFF);
continue;
}
mem.copy((ircolib::u8 *)segment->get_data(), segment->get_file_size(),
segment->get_virtual_address() & 0x0FFFFFFF);
}
broadway.set_pc(reader.get_entry());
return true;
}
} // namespace weee::core
+10
View File
@@ -0,0 +1,10 @@
#pragma once
#include <ircolib/types.hpp>
#include <string>
namespace weee::core {
struct mem;
struct broadway;
bool load_elf(const std::string &, mem &, broadway &);
} // namespace weee::core
+178
View File
@@ -0,0 +1,178 @@
#include <cstring>
#include <mem.hpp>
#include <ircolib/log.hpp>
#include <ircolib/mem_access.hpp>
namespace weee::core {
mem::mem() : vi(*this), pi(*this), mi(*this), dsp(*this), ai(*this), exi(*this), si(*this) {
mem1.resize(24_mib);
std::fill(mem1.begin(), mem1.end(), 0);
ipl.resize(1_mib);
std::fill(ipl.begin(), ipl.end(), 0);
register_read8_handler(0x00000000, 0x017fffff, [&](ircolib::u32 addr) { return mem1[addr]; });
register_read16_handler(0x00000000, 0x017fffff,
[&](ircolib::u32 addr) { return ircolib::read_access<ircolib::u16>(mem1, addr); });
register_read32_handler(0x00000000, 0x017fffff,
[&](ircolib::u32 addr) { return ircolib::read_access<ircolib::u32>(mem1, addr); });
register_read64_handler(0x00000000, 0x017fffff,
[&](ircolib::u32 addr) { return ircolib::read_access<ircolib::u64>(mem1, addr); });
register_write8_handler(0x00000000, 0x017fffff, [&](ircolib::u32 addr, ircolib::u8 value) { mem1[addr] = value; });
register_write16_handler(0x00000000, 0x017fffff, [&](ircolib::u32 addr, ircolib::u16 value) {
ircolib::write_access<ircolib::u16>(mem1, addr, value);
});
register_write32_handler(0x00000000, 0x017fffff, [&](ircolib::u32 addr, ircolib::u32 value) {
ircolib::write_access<ircolib::u32>(mem1, addr, value);
});
register_write64_handler(0x00000000, 0x0fffffff, [&](ircolib::u32 addr, ircolib::u32 value) {
ircolib::write_access<ircolib::u64>(mem1, addr, value);
});
register_read8_handler(0x0ff00000, 0x0fffffff, [&](ircolib::u32 addr) { return ipl[addr]; });
register_read16_handler(0x0ff00000, 0x0fffffff,
[&](ircolib::u32 addr) { return ircolib::read_access<ircolib::u16>(ipl, addr); });
register_read32_handler(0x0ff00000, 0x0fffffff,
[&](ircolib::u32 addr) { return ircolib::read_access<ircolib::u32>(ipl, addr); });
register_read64_handler(0x0ff00000, 0x0fffffff,
[&](ircolib::u32 addr) { return ircolib::read_access<ircolib::u64>(ipl, addr); });
register_write8_handler(0x0ff00000, 0x0fffffff, [&](ircolib::u32 addr, ircolib::u8 value) { ipl[addr] = value; });
register_write16_handler(0x0ff00000, 0x0fffffff, [&](ircolib::u32 addr, ircolib::u16 value) {
ircolib::write_access<ircolib::u16>(ipl, addr, value);
});
register_write32_handler(0x0ff00000, 0x0fffffff, [&](ircolib::u32 addr, ircolib::u32 value) {
ircolib::write_access<ircolib::u32>(ipl, addr, value);
});
register_write64_handler(0x0ff00000, 0x0fffffff, [&](ircolib::u32 addr, ircolib::u32 value) {
ircolib::write_access<ircolib::u64>(ipl, addr, value);
});
}
void mem::copy(std::vector<ircolib::u8> &src, const ircolib::u32 offset) {
if (offset + src.size() >= mem1.size())
ircolib::panic("mem::copy outside mem1 range (src @ 0x{:08} for size 0x{:08X})", offset, src.size());
ircolib::swap_buffer<ircolib::u32>(src);
std::copy(src.begin(), src.end(), mem1.begin() + offset);
}
void mem::copy(ircolib::u8 *src, const ircolib::u32 size, const ircolib::u32 offset) {
if (offset + size >= mem1.size())
ircolib::panic("mem::copy outside mem1 range (src @ 0x{:08} for size 0x{:08X})", offset, size);
ircolib::swap_buffer<ircolib::u32>(src, size);
memcpy(&mem1[offset], src, size);
}
void mem::set(const ircolib::u8 val, const ircolib::u32 size, const ircolib::u32 offset) {
if (offset + size >= mem1.size())
ircolib::panic("mem::set outside mem1 range (@ 0x{:08} for size 0x{:08X})", offset, size);
memset(&mem1[offset], val, size);
}
std::expected<ircolib::u8, std::string> mem::read8(ircolib::u32 addr) {
addr &= 0x0FFFFFFF;
for (const auto &handler : read8_handlers) {
if (ircolib::is_inside_range(addr, handler.start, handler.end)) {
return handler.func(addr - handler.start);
}
}
return std::unexpected(std::format("mem::read8 unimplemented addr 0x{:08X}", addr));
}
std::expected<ircolib::u16, std::string> mem::read16(ircolib::u32 addr) {
addr &= 0x0FFFFFFF;
for (const auto &handler : read16_handlers) {
if (ircolib::is_inside_range(addr, handler.start, handler.end)) {
return handler.func(addr - handler.start);
}
}
return std::unexpected(std::format("mem::read16 unimplemented addr 0x{:08X}", addr));
}
std::expected<ircolib::u32, std::string> mem::read32(ircolib::u32 addr) {
addr &= 0x0FFFFFFF;
for (const auto &handler : read32_handlers) {
if (ircolib::is_inside_range(addr, handler.start, handler.end)) {
return handler.func(addr - handler.start);
}
}
return std::unexpected(std::format("mem::read32 unimplemented addr 0x{:08X}", addr));
}
std::expected<ircolib::u64, std::string> mem::read64(ircolib::u32 addr) {
addr &= 0x0FFFFFFF;
for (const auto &handler : read64_handlers) {
if (ircolib::is_inside_range(addr, handler.start, handler.end)) {
return handler.func(addr - handler.start);
}
}
return std::unexpected(std::format("mem::read64 unimplemented addr 0x{:08X}", addr));
}
std::expected<void, std::string> mem::write8(ircolib::u32 addr, ircolib::u8 value) {
addr &= 0x0FFFFFFF;
for (const auto &handler : write8_handlers) {
if (ircolib::is_inside_range(addr, handler.start, handler.end)) {
handler.func(addr - handler.start, value);
return std::expected<void, std::string>();
}
}
return std::unexpected(std::format("mem::write8 unimplemented addr 0x{:08X} = 0x{:02X}", addr, value));
}
std::expected<void, std::string> mem::write16(ircolib::u32 addr, ircolib::u16 value) {
addr &= 0x0FFFFFFF;
for (const auto &handler : write16_handlers) {
if (ircolib::is_inside_range(addr, handler.start, handler.end)) {
handler.func(addr - handler.start, value);
return std::expected<void, std::string>();
}
}
return std::unexpected(std::format("mem::write16 unimplemented addr 0x{:08X} = 0x{:04X}", addr, value));
}
std::expected<void, std::string> mem::write32(ircolib::u32 addr, ircolib::u32 value) {
addr &= 0x0FFFFFFF;
for (const auto &handler : write32_handlers) {
if (ircolib::is_inside_range(addr, handler.start, handler.end)) {
handler.func(addr - handler.start, value);
return std::expected<void, std::string>();
}
}
return std::unexpected(std::format("mem::write32 unimplemented addr 0x{:08X} = 0x{:08X}", addr, value));
}
std::expected<void, std::string> mem::write64(ircolib::u32 addr, ircolib::u64 value) {
addr &= 0x0FFFFFFF;
for (const auto &handler : write64_handlers) {
if (ircolib::is_inside_range(addr, handler.start, handler.end)) {
handler.func(addr - handler.start, value);
return std::expected<void, std::string>();
}
}
return std::unexpected(std::format("mem::write64 unimplemented addr 0x{:08X} = 0x{:016X}", addr, value));
}
} // namespace weee::core
+99
View File
@@ -0,0 +1,99 @@
#pragma once
#include <string>
#include <vector>
#include <ircolib/types.hpp>
#include <broadway/mmio/vi.hpp>
#include <broadway/mmio/pi.hpp>
#include <broadway/mmio/mi.hpp>
#include <broadway/mmio/dsp.hpp>
#include <broadway/mmio/ai.hpp>
#include <broadway/mmio/exi.hpp>
#include <broadway/mmio/si.hpp>
#include <functional>
#include <expected>
namespace weee::core {
template <typename T>
struct read_handler {
std::function<T(ircolib::u32)> func;
ircolib::u32 start, end;
};
template <typename T>
struct write_handler {
std::function<void(ircolib::u32, T)> func;
ircolib::u32 start, end;
};
struct mem {
mem();
void register_read8_handler(ircolib::u32 start, ircolib::u32 end,
const std::function<ircolib::u8(ircolib::u32)> &func) {
read8_handlers.push_back({std::move(func), start, end});
}
void register_read16_handler(ircolib::u32 start, ircolib::u32 end,
const std::function<ircolib::u16(ircolib::u32)> &func) {
read16_handlers.push_back({std::move(func), start, end});
}
void register_read32_handler(ircolib::u32 start, ircolib::u32 end,
const std::function<ircolib::u32(ircolib::u32)> &func) {
read32_handlers.push_back({std::move(func), start, end});
}
void register_read64_handler(ircolib::u32 start, ircolib::u32 end,
const std::function<ircolib::u64(ircolib::u32)> &func) {
read64_handlers.push_back({std::move(func), start, end});
}
void register_write8_handler(ircolib::u32 start, ircolib::u32 end,
const std::function<void(ircolib::u32, ircolib::u8)> &func) {
write8_handlers.push_back({std::move(func), start, end});
}
void register_write16_handler(ircolib::u32 start, ircolib::u32 end,
const std::function<void(ircolib::u32, ircolib::u16)> &func) {
write16_handlers.push_back({std::move(func), start, end});
}
void register_write32_handler(ircolib::u32 start, ircolib::u32 end,
const std::function<void(ircolib::u32, ircolib::u32)> &func) {
write32_handlers.push_back({std::move(func), start, end});
}
void register_write64_handler(ircolib::u32 start, ircolib::u32 end,
const std::function<void(ircolib::u32, ircolib::u64)> &func) {
write64_handlers.push_back({std::move(func), start, end});
}
std::expected<ircolib::u8, std::string> read8(ircolib::u32);
std::expected<ircolib::u16, std::string> read16(ircolib::u32);
std::expected<ircolib::u32, std::string> read32(ircolib::u32);
std::expected<ircolib::u64, std::string> read64(ircolib::u32);
std::expected<void, std::string> write8(ircolib::u32, ircolib::u8);
std::expected<void, std::string> write16(ircolib::u32, ircolib::u16);
std::expected<void, std::string> write32(ircolib::u32, ircolib::u32);
std::expected<void, std::string> write64(ircolib::u32, ircolib::u64);
void copy(std::vector<ircolib::u8> &src, const ircolib::u32 offset);
void copy(ircolib::u8 *src, const ircolib::u32 size, const ircolib::u32 offset);
void set(const ircolib::u8 val, const ircolib::u32 size, const ircolib::u32 offset);
std::vector<ircolib::u8> mem1;
std::vector<ircolib::u8> ipl{};
private:
std::vector<read_handler<ircolib::u8>> read8_handlers{};
std::vector<read_handler<ircolib::u16>> read16_handlers{};
std::vector<read_handler<ircolib::u32>> read32_handlers{};
std::vector<read_handler<ircolib::u64>> read64_handlers{};
std::vector<write_handler<ircolib::u8>> write8_handlers{};
std::vector<write_handler<ircolib::u16>> write16_handlers{};
std::vector<write_handler<ircolib::u32>> write32_handlers{};
std::vector<write_handler<ircolib::u64>> write64_handlers{};
public:
video_interface vi;
processor_interface pi;
memory_interface mi;
dsp dsp;
exi exi;
audio_interface ai;
serial_interface si;
};
} // namespace weee::core
+34
View File
@@ -0,0 +1,34 @@
BasedOnStyle : LLVM
AccessModifierOffset : -2
AlignAfterOpenBracket : true
AlignConsecutiveAssignments : true
AlignConsecutiveDeclarations : true
AlignConsecutiveMacros : true
AlignEscapedNewlines : true
AlignOperands : true
AlignTrailingComments : true
BinPackParameters : false
BraceWrapping:
AfterCaseLabel : true
AfterClass : true
AfterEnum : true
AfterFunction : true
AfterNamespace : false
AfterStruct : true
AfterExternBlock : true
BeforeCatch : true
BeforeElse : true
BreakBeforeBraces : Custom
ColumnLimit : 80
FixNamespaceComments : true
IndentCaseLabels : false
IndentWidth : 4
NamespaceIndentation : Inner
PointerAlignment : Left
ReflowComments : false
SortIncludes : false
SpacesInConditionalStatement : true
SpacesInParentheses : true
TabWidth : 4
UseTab : Never
+1
View File
@@ -0,0 +1 @@
*.a binary
+99
View File
@@ -0,0 +1,99 @@
name: C/C++ CI
on:
push:
branches: [ "main" ]
pull_request:
branches: [ "main" ]
workflow_call:
workflow_dispatch:
permissions:
contents: read
jobs:
build:
name: CMake Build & Test
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, ubuntu-22.04, windows-latest, windows-2022, macos-13, macos-15]
build_type: [Release, Debug]
cpp_compiler: [g++, clang++, cl]
include:
- os: windows-latest
cpp_compiler: cl
c_compiler: cl
- os: windows-2022
cpp_compiler: cl
c_compiler: cl
- os: ubuntu-latest
cpp_compiler: g++
c_compiler: gcc
- os: ubuntu-latest
cpp_compiler: clang++
c_compiler: clang
- os: ubuntu-22.04
cpp_compiler: g++
c_compiler: gcc
- os: ubuntu-22.04
cpp_compiler: clang++
c_compiler: clang
- os: macos-13
cpp_compiler: g++
c_compiler: gcc
- os: macos-13
cpp_compiler: clang++
c_compiler: clang
- os: macos-15
cpp_compiler: g++
c_compiler: gcc
- os: macos-15
cpp_compiler: clang++
c_compiler: clang
exclude:
- os: windows-latest
cpp_compiler: g++
- os: windows-latest
cpp_compiler: clang++
- os: windows-2022
cpp_compiler: g++
- os: windows-2022
cpp_compiler: clang++
- os: ubuntu-latest
cpp_compiler: cl
- os: ubuntu-22.04
cpp_compiler: cl
- os: macos-13
cpp_compiler: cl
- os: macos-15
cpp_compiler: cl
steps:
- uses: actions/checkout@v4
with:
repository: 'Serge1/ELFIO'
- name: Set reusable strings
# Turn repeated input strings (such as the build output directory) into step outputs. These step outputs can be used throughout the workflow file.
id: strings
shell: bash
run: |
echo "build-output-dir=${{ github.workspace }}/build/${{ matrix.build_type }}/${{ matrix.cpp_compiler }}" >> "$GITHUB_OUTPUT"
- name: Configure CMake
run: >
cmake -B ${{ steps.strings.outputs.build-output-dir }}
-DCMAKE_CXX_COMPILER=${{ matrix.cpp_compiler }}
-DCMAKE_C_COMPILER=${{ matrix.c_compiler }}
-DCMAKE_BUILD_TYPE=${{ matrix.build_type }}
-DELFIO_BUILD_EXAMPLES=YES -DELFIO_BUILD_TESTS=YES
-S ${{ github.workspace }}
- name: Build
run: cmake --build ${{ steps.strings.outputs.build-output-dir }} --config ${{ matrix.build_type }}
- name: Test
working-directory: ${{ steps.strings.outputs.build-output-dir }}
run: ctest --build-config ${{ matrix.build_type }} --output-on-failure --verbose
+69
View File
@@ -0,0 +1,69 @@
name: "CodeQL"
on:
push:
branches: [main]
pull_request:
# The branches below must be a subset of the branches above
branches: [master]
schedule:
- cron: '0 15 * * 5'
permissions:
contents: read
jobs:
analyze:
permissions:
actions: read # for github/codeql-action/init to get workflow details
contents: read # for actions/checkout to fetch code
security-events: write # for github/codeql-action/analyze to upload SARIF results
name: Analyze
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
# Override automatic language detection by changing the below list
# Supported options are ['csharp', 'cpp', 'go', 'java', 'javascript', 'python']
language: ['cpp']
# Learn more...
# https://docs.github.com/en/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#overriding-automatic-language-detection
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
# We must fetch at least the immediate parents so that if this is
# a pull request then we can checkout the head.
fetch-depth: 2
# If this run was triggered by a pull request event, then checkout
# the head of the pull request instead of the merge commit.
#- run: git checkout HEAD^2
# if: ${{ github.event_name == 'pull_request' }}
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v3
with:
languages: ${{ matrix.language }}
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
#- name: Autobuild
# uses: github/codeql-action/autobuild@v1
# ️ Command-line programs to run using the OS shell.
# 📚 https://git.io/JvXDl
# ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
# and modify them (or add more) to build your code if your project
# uses a compiled language
- run: |
cmake -B build -D ELFIO_BUILD_EXAMPLES=ON
cmake --build build
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v3
+100
View File
@@ -0,0 +1,100 @@
autom4te.cache
Debug
Release
.vs
tmp/
docs
tests/Debug
tests/Release
tests/ELFIOTest
tests/ELFIOTest.exe
tests/runELFtests.trs
examples/ELFDump/Debug
examples/anonymizer/anonymizer
examples/anonymizer/anonymizer.exe
examples/elfdump/elfdump
examples/elfdump/elfdump.exe
examples/tutorial/tutorial
examples/tutorial/tutorial.exe
examples/write_obj/write_obj
examples/write_obj/write_obj.exe
examples/writer/writer
examples/writer/writer.exe
# generated elf files
tests/elf_examples/*_copy
tests/elf_examples/*_copy.elf
tests/elf_examples/elf_dummy_header_i386_32.elf
tests/elf_examples/elf_dummy_header_i386_64.elf
tests/elf_examples/elf_dummy_header_ppc_32.elf
tests/elf_examples/elf_dummy_header_ppc_64.elf
tests/elf_examples/write_exe_i386_32
tests/elf_examples/write_exe_i386_32_w_addr
tests/elf_examples/write_exe_i386_32_wo_addr
tests/elf_examples/write_exe_i386_32_section_added
tests/elf_examples/ppc-32bit-testcopy*.elf
tests/elf_examples/null_section_inside_segment*
tests/elf_examples/segment_containing_no_section*
tests/elf_examples/test_symbols_order.elf
tests/elf_examples/zavl_gen.ko
tests/elfio_fuzzer
tests/corpus
examples/writer/hello_x86_64
examples/write_obj/hello
examples/c_wrapper/c_example
examples/add_section/add_section
examples/elfdump/elfdump.trs
# various unwanted files (backups, objects, cmake artifacts)
*~
*.o
*.kate-swp
*.swp
.#*
\#*#
CMakeCache.txt
CMakeSettings.json
Makefile
CMakeFiles
/build*/
out
*.res
# autotools artifacts
.deps
config.status
ELFIOTest/runELFtests.trs
# eclipse project files
.settings
.project
.cproject
.cdtproject
.cdtbuild
# netbeans project files
/dist/
Makefile
.dep.inc
nbproject
# QtCreator project files
CMakeLists.txt.user
# ignore all _ prefixed directories (usually used for generated directories)
_*/
# Latex build output
*.pdf
*.log
*.out
*.aux
*.bbl
*.toc
*.blg
+19
View File
@@ -0,0 +1,19 @@
{
"configurations": [
{
"name": "Linux",
"includePath": [
"${workspaceFolder}",
"${workspaceFolder}/**"
],
"defines": [],
"compilerPath": "/usr/bin/g++",
"cStandard": "c11",
"cppStandard": "c++17",
"intelliSenseMode": "clang-x64",
"compileCommands": "${workspaceFolder}/build/compile_commands.json",
"configurationProvider": "ms-vscode.cmake-tools"
}
],
"version": 4
}
+122
View File
@@ -0,0 +1,122 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "Run ELFIO Tests",
"type": "cppdbg",
"request": "launch",
"program": "${workspaceFolder}/build/tests/ELFIOTest",
"args": [
//"--gtest_filter=ELFIOTest.load32",
],
"stopAtEntry": false,
"cwd": "${workspaceFolder}/build/tests",
"environment": [],
"externalConsole": false,
"MIMode": "gdb",
"setupCommands": [
{
"description": "Enable pretty-printing for gdb",
"text": "-enable-pretty-printing",
"ignoreFailures": true
}
],
//"preLaunchTask": "ELFIO Test build",
"miDebuggerPath": "/usr/bin/gdb"
},
{
"name": "Run ELFIO Tests (Windows)",
"type": "cppvsdbg",
"request": "launch",
"program": "${workspaceFolder}/build/tests/Debug/ELFIOTest.exe",
"args": [],
"stopAtEntry": false,
"cwd": "${workspaceFolder}/build/tests",
"environment": [],
"console": "externalTerminal"
},
{
"name": "arioso (Windows)",
"type": "cppvsdbg",
"request": "launch",
"program": "${workspaceFolder}/build/examples/arioso/Debug/arioso.exe",
"args": ["${workspaceFolder}/build/tests/ario/simple_text.a", "-e", "hello.c", "-d", "hello.c", "-a", "hello.c"],
"stopAtEntry": false,
"cwd": "${workspaceFolder}/build/examples/arioso",
"environment": [],
"console": "externalTerminal"
},
{
"name": "Run ELF Dump",
"type": "cppdbg",
"request": "launch",
"program": "${workspaceFolder}/build/examples/elfdump/elfdump",
"args": ["build/tests/crash-de896e9e31bf6f4c540e7462ccc0440018e4f0de"],
"stopAtEntry": false,
"cwd": "${workspaceFolder}",
"environment": [],
"externalConsole": false,
"MIMode": "gdb",
"setupCommands": [
{
"description": "Enable pretty-printing for gdb",
"text": "-enable-pretty-printing",
"ignoreFailures": true
}
],
"preLaunchTask": "ELF Dump Build",
"miDebuggerPath": "/usr/bin/gdb"
},
{
"name": "Run proc_mem",
"type": "cppdbg",
"request": "launch",
"program": "${workspaceFolder}/build/examples/proc_mem/proc_mem",
"args": ["11706", "/usr/bin/bash"],
"stopAtEntry": false,
"cwd": "${workspaceFolder}",
"environment": [],
"externalConsole": false,
"MIMode": "gdb",
"setupCommands": [
{
"description": "Enable pretty-printing for gdb",
"text": "-enable-pretty-printing",
"ignoreFailures": true
}
],
"miDebuggerPath": "/home/user/ELFIO/examples/sudo_gdb.sh"
},
{
"name": "Run dump for /proc/kcore",
"type": "cppdbg",
"request": "launch",
"program": "${workspaceFolder}/build/examples/elfdump/elfdump",
"args": ["/proc/kcore"],
"stopAtEntry": false,
"cwd": "${workspaceFolder}",
"environment": [],
"externalConsole": false,
"MIMode": "gdb",
"setupCommands": [
{
"description": "Enable pretty-printing for gdb",
"text": "-enable-pretty-printing",
"ignoreFailures": true
}
],
"miDebuggerPath": "/home/user/ELFIO/examples/sudo_gdb.sh"
},
{
"name": "Fuzzer",
"type": "lldb",
"request": "launch",
"program": "${workspaceFolder}/build/tests/elfio_fuzzer",
"args": ["crash-7143f5e49745dc6ce8909e642f9351d9d6496020"],
"cwd": "${workspaceFolder}/build/tests"
}
]
}
+131
View File
@@ -0,0 +1,131 @@
{
"files.associations": {
"copyright": "json",
"*.ipp": "cpp",
"strstream": "cpp",
"cerrno": "cpp",
"csetjmp": "cpp",
"cstdarg": "cpp",
"rope": "cpp",
"iostream": "cpp",
"streambuf": "cpp",
"*.tcc": "cpp",
"regex": "cpp",
"algorithm": "cpp",
"array": "cpp",
"atomic": "cpp",
"bit": "cpp",
"bitset": "cpp",
"cassert": "cpp",
"cctype": "cpp",
"cfloat": "cpp",
"chrono": "cpp",
"ciso646": "cpp",
"climits": "cpp",
"clocale": "cpp",
"cmath": "cpp",
"complex": "cpp",
"cstddef": "cpp",
"cstdint": "cpp",
"cstdio": "cpp",
"cstdlib": "cpp",
"cstring": "cpp",
"ctime": "cpp",
"cwchar": "cpp",
"cwctype": "cpp",
"deque": "cpp",
"list": "cpp",
"map": "cpp",
"set": "cpp",
"string": "cpp",
"unordered_map": "cpp",
"vector": "cpp",
"exception": "cpp",
"functional": "cpp",
"iterator": "cpp",
"memory": "cpp",
"memory_resource": "cpp",
"numeric": "cpp",
"optional": "cpp",
"random": "cpp",
"ratio": "cpp",
"string_view": "cpp",
"system_error": "cpp",
"tuple": "cpp",
"type_traits": "cpp",
"utility": "cpp",
"fstream": "cpp",
"initializer_list": "cpp",
"iomanip": "cpp",
"ios": "cpp",
"iosfwd": "cpp",
"istream": "cpp",
"limits": "cpp",
"locale": "cpp",
"new": "cpp",
"ostream": "cpp",
"queue": "cpp",
"sstream": "cpp",
"stdexcept": "cpp",
"thread": "cpp",
"cfenv": "cpp",
"cinttypes": "cpp",
"typeindex": "cpp",
"typeinfo": "cpp",
"variant": "cpp",
"compare": "cpp",
"any": "cpp",
"charconv": "cpp",
"concepts": "cpp",
"condition_variable": "cpp",
"csignal": "cpp",
"filesystem": "cpp",
"format": "cpp",
"forward_list": "cpp",
"mutex": "cpp",
"span": "cpp",
"stop_token": "cpp",
"unordered_set": "cpp",
"xfacet": "cpp",
"xhash": "cpp",
"xiosbase": "cpp",
"xlocale": "cpp",
"xlocbuf": "cpp",
"xlocinfo": "cpp",
"xlocmes": "cpp",
"xlocmon": "cpp",
"xlocnum": "cpp",
"xloctime": "cpp",
"xmemory": "cpp",
"xstring": "cpp",
"xtr1common": "cpp",
"xtree": "cpp",
"xutility": "cpp"
},
"svn.ignoreMissingSvnWarning": true,
"editor.tokenColorCustomizations": {
"textMateRules": [
{
"scope": "googletest.failed",
"settings": {
"foreground": "#f00"
}
},
{
"scope": "googletest.passed",
"settings": {
"foreground": "#0f0"
}
},
{
"scope": "googletest.run",
"settings": {
"foreground": "#0f0"
}
}
]
},
"gtest-adapter.debugConfig": "Run ELFIO Tests",
"gtest-adapter.supportLocation": true,
"sonarlint.pathToCompileCommands": "${workspaceFolder}/build/compile_commands.json"
}
+104
View File
@@ -0,0 +1,104 @@
{
"tasks": [
{
"type": "shell",
"label": "ELFIO Test build",
"command": "make",
"args": ["INCLUDES=-I..", "CXXFLAGS='-g -O0'"],
"options": {
"cwd": "${workspaceRoot}/build/tests"
},
"group": {
"kind": "build",
"isDefault": true
},
"problemMatcher": ["$gcc"]
},
{
"type": "shell",
"label": "ELF Dump Build",
"command": "make",
"args": ["INCLUDES=-I..", "CXXFLAGS='-g -O0'"],
"options": {
"cwd": "${workspaceRoot}/build"
},
"group": {
"kind": "build",
"isDefault": true
}
},
{
"type": "shell",
"label": "clang-tidy",
"command": "clang-tidy",
"args": [
"--checks=*,-modernize-use-trailing-return-type,-modernize-avoid-c-arrays,-llvm*,-fuchsia-*,-altera-*",
"-header-filter=./*",
"examples/elfdump/elfdump.cpp",
"--",
"-I."
],
"options": {
"cwd": "${workspaceRoot}"
},
"group": {
"kind": "build",
"isDefault": true
},
"problemMatcher": ["$gcc"]
},
{
"type": "shell",
"label": "Fuzzer",
"command": "clang",
"args": [
"-g",
"-O0",
"-fsanitize=fuzzer,address",
"-I..",
"elfio_fuzzer.cpp",
"-o",
"elfio_fuzzer"
],
"options": {
"cwd": "${workspaceRoot}/tests"
},
"group": {
"kind": "build",
"isDefault": true
},
"problemMatcher": ["$gcc"]
},
{
"type": "shell",
"label": "Fuzzer Tests",
"command": "./elfio_fuzzer",
"args": ["-jobs=8", "corpus"],
"options": {
"cwd": "${workspaceRoot}/tests"
},
"group": {
"kind": "build",
"isDefault": true
},
"problemMatcher": ["$gcc"]
},
{
"type": "cmake",
"label": "CMake: clean",
"command": "clean",
"problemMatcher": [],
"detail": "CMake template clean task"
},
{
"type": "cmake",
"label": "CMake: clean rebuild",
"command": "cleanRebuild",
"targets": ["ALL_BUILD"],
"group": "build",
"problemMatcher": [],
"detail": "CMake template clean rebuild task"
}
],
"version": "2.0.0"
}
+157
View File
@@ -0,0 +1,157 @@
cmake_minimum_required(VERSION 3.10)
# Detect if we are the top level CMakeLists.txt or are we included in some
# other project
if(NOT DEFINED PROJECT_NAME)
set(IS_TOP_PROJECT TRUE)
endif()
if(IS_TOP_PROJECT)
# Turn this on in order to build elfio examples
option(ELFIO_BUILD_EXAMPLES "Build ELFIO examples" ON)
# Turn this on in order to build tests
option(ELFIO_BUILD_TESTS "Build ELFIO tests" OFF)
# Generate output of compile commands during generation
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
endif()
# Read version from header file
set(version_header "elfio/elfio_version.hpp")
file(READ ${version_header} ver)
string(REGEX MATCH "#define ELFIO_VERSION \"([0-9\.]+)\"" _ ${ver})
if(NOT CMAKE_MATCH_1)
message(FATAL_ERROR "Unable to parse version from ${version_header}")
endif()
set(version ${CMAKE_MATCH_1})
# Use configure_file to make configure step depend on elfio_version.hpp
configure_file(${version_header} ${CMAKE_CURRENT_BINARY_DIR}/elfio_version.hpp.copy COPYONLY)
project(elfio VERSION ${version} LANGUAGES C CXX)
include(GNUInstallDirs)
# Create a header only CMake target for elfio
add_library(elfio INTERFACE)
add_library(elfio::elfio ALIAS elfio)
add_library(ario INTERFACE)
add_library(ario::ario ALIAS ario)
target_include_directories(
elfio
INTERFACE
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>)
target_include_directories(
ario
INTERFACE
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>)
# If this is the top level project, add in logic to install elfio
if(IS_TOP_PROJECT)
# Enable C++17 for examples and tests
if(ELFIO_BUILD_EXAMPLES OR ELFIO_BUILD_TESTS)
set(CMAKE_CXX_STANDARD 17)
endif()
if(ELFIO_BUILD_EXAMPLES)
# set (CMAKE_CXX_FLAGS "-Wall")
add_subdirectory(examples)
endif()
if(ELFIO_BUILD_TESTS)
# set (CMAKE_CXX_FLAGS "-Wall")
enable_testing()
add_custom_target(check COMMAND ${CMAKE_CTEST_COMMAND} USES_TERMINAL)
add_subdirectory(tests)
endif()
include(CMakePackageConfigHelpers)
# Create a file that includes the current project version. This will be
# installed with the elfio CMake package.
write_basic_package_version_file(
"${PROJECT_NAME}ConfigVersion.cmake"
VERSION
${PROJECT_VERSION}
COMPATIBILITY
SameMajorVersion)
# Create the default ${PROJECT_NAME}Config.cmake file which will be
# installed and found by calls to `find_package(elfio)`.
configure_package_config_file(
"${PROJECT_SOURCE_DIR}/cmake/${PROJECT_NAME}Config.cmake.in"
"${PROJECT_BINARY_DIR}/${PROJECT_NAME}Config.cmake"
INSTALL_DESTINATION
${CMAKE_INSTALL_DATAROOTDIR}/${PROJECT_NAME}/cmake)
# Install the previously generated "config" and "version" files
install(
FILES
"${PROJECT_BINARY_DIR}/${PROJECT_NAME}Config.cmake"
"${PROJECT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake"
DESTINATION
${CMAKE_INSTALL_DATAROOTDIR}/${PROJECT_NAME}/cmake)
# Install the entire local `elfio` directory to the include directory
install(
DIRECTORY
elfio
DESTINATION
${CMAKE_INSTALL_INCLUDEDIR})
# Create a ${PROJECT_NAME}Targets.cmake file that is referenced by the
# ${PROJECT_NAME}Config.cmake file and includes the target information
# needed to compile/link against all targets exported under the
# ${PROJECT_NAME}_Targets export
install(
EXPORT
${PROJECT_NAME}_Targets
FILE
${PROJECT_NAME}Targets.cmake
NAMESPACE
${PROJECT_NAME}::
DESTINATION
${CMAKE_INSTALL_DATAROOTDIR}/${PROJECT_NAME}/cmake)
# Add the elfio target to the ${PROJECT_NAME}_Targets export
install(
TARGETS
elfio
EXPORT
${PROJECT_NAME}_Targets)
# cmake -B build; cmake --build build; cpack --config build/CPackSourceConfig.cmake
# cmake -B build -D ELFIO_BUILD_EXAMPLES=ON -DELFIO_BUILD_TESTS=ON -G Ninja; cmake --build build; cpack --config build/CPackSourceConfig.cmake
set(_fmt TGZ)
if(WIN32)
set(_fmt ZIP)
endif()
set(CPACK_GENERATOR ${_fmt})
set(CPACK_SOURCE_GENERATOR ${_fmt})
set(CPACK_PACKAGE_VENDOR "ELFIO")
set(CPACK_PACKAGE_CONTACT "Serge Lamikhov-Center")
set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/LICENSE.txt")
set(CPACK_RESOURCE_FILE_README "${CMAKE_CURRENT_SOURCE_DIR}/README.md")
set(CPACK_OUTPUT_FILE_PREFIX "${CMAKE_CURRENT_BINARY_DIR}/package")
set(CPACK_PACKAGE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
string(TOLOWER ${CMAKE_SYSTEM_NAME} _sys)
string(TOLOWER ${PROJECT_NAME} _project_lower)
set(CPACK_PACKAGE_FILE_NAME "${_project_lower}-${_sys}")
set(CPACK_SOURCE_PACKAGE_FILE_NAME "${_project_lower}-${PROJECT_VERSION}")
set(CPACK_SOURCE_IGNORE_FILES "/.git.*;/.vs.*;/build;/.clang-format;/doc/site;/doc/elfio.docx;/doc/images/callouts/;/doc/images/colorsvg/;/doc/images/res2/;/doc/images/.*\.svg;/doc/images/.*\.gif;/doc/images/[^/]*\.png$;/doc/images/.*\.tif;/examples/sudo_gdb.sh;/tests")
install(FILES ${CPACK_RESOURCE_FILE_README} ${CPACK_RESOURCE_FILE_LICENSE}
DESTINATION share/docs/${PROJECT_NAME})
include(CPack)
endif()
+21
View File
@@ -0,0 +1,21 @@
MIT License
Copyright (C) 2001-present by Serge Lamikhov-Center
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
+167
View File
@@ -0,0 +1,167 @@
<!--- # <img src="res/20231119165006-100.png" width="100"> ELFIO -->
# ![ELFIO Logo](doc/images/res/20231119165006-100.png "ELFIO") ![ELFIO Title](doc/images/res/title.png "ELFIO")
![C/C++ CI](https://github.com/serge1/ELFIO/workflows/C/C++%20CI/badge.svg)
![CodeQL](https://github.com/serge1/ELFIO/workflows/CodeQL/badge.svg)
[![Documentation](https://img.shields.io/badge/doc-download-brightgreen)](http://elfio.sourceforge.net/elfio.pdf)
[![License](https://img.shields.io/badge/License-MIT-brightgreen.svg)](https://github.com/serge1/ELFIO/blob/master/COPYING)
---
## Table of Contents
- [Overview](#overview)
- [ELFIO: ELF Object and Executable File Reader/Writer](#elfio-elf-object-and-executable-file-readerwriter)
- [ARIO: Advanced Archive Input/Output Library](#ario-advanced-archive-inputoutput-library)
- [Who Uses ELFIO & ARIO?](#who-uses-elfio--ario)
- [Installation](#installation)
- [Getting Started](#getting-started)
- [Project Structure](#project-structure)
- [Examples](#examples)
- [Support](#support)
- [Contributing](#contributing)
- [License](#license)
- [Resources](#resources)
---
## Overview
**ELFIO** and **ARIO** are robust, header-only C++ libraries designed to make binary file and archive manipulation effortless, efficient, and portable. Whether you are building compilers, linkers, binary analysis tools, or custom build systems, these libraries provide the foundation you need for working with ELF files and UNIX archives.
---
## ELFIO: ELF Object and Executable File Reader/Writer
**ELFIO** is a lightweight, header-only C++ library for reading and generating ELF (Executable and Linkable Format) binary files. It is completely standalone, requiring no external dependencies, and integrates seamlessly into any C++ project. Built to ISO C++ standards, ELFIO ensures compatibility across a wide range of architectures and compilers.
**Key Features:**
- **Header-only:** Just include the header files—no need to build or link external libraries.
- **No dependencies:** Pure C++ implementation.
- **Cross-platform:** Works on Windows, Linux, and macOS.
- **Comprehensive ELF support:** Read, create, and modify ELF files, including sections, segments, and symbols.
- **Easy integration:** Designed for both small utilities and large-scale applications.
- **Actively maintained:** Trusted by open-source and commercial projects worldwide.
> 📖 Comprehensive documentation is available in the [ELFIO - Tutorial and User Manual (PDF)](http://elfio.sourceforge.net/elfio.pdf).
---
## ARIO: Advanced Archive Input/Output Library
**ARIO** is a modern, high-performance, header-only C++ library for reading, creating, and modifying UNIX `ar` archive files (commonly used for static libraries). ARIO is designed to work seamlessly with ELFIO, providing a unified and intuitive interface for archive manipulation and binary data management.
**Why Choose ARIO?**
- **Header-only:** Effortless integration—just include `ario.hpp` in your project.
- **Zero dependencies:** No need for external libraries or build steps.
- **Universal access:** Read and write to files, memory, and custom streams.
- **Cross-platform:** Consistent behavior on Windows, Linux, and macOS.
- **Optimized for performance:** Minimal overhead for high-throughput applications.
- **Seamless ELFIO integration:** Easily combine ELF and archive operations in your toolchain.
- **Intuitive API:** Designed for productivity and ease of use.
**Typical Use Cases:**
- Building and modifying static libraries (`.a` files)
- Extracting or replacing object files within archives
- Analyzing and manipulating symbol tables in archives
- Custom build tools and binary utilities
- Automated toolchains and CI/CD systems
---
## Who Uses ELFIO & ARIO?
- Open-source projects
- Commercial toolchains
- Academic research
- Embedded systems
- Binary analysis and reverse engineering tools
---
## Installation
Simply copy the `elfio` and/or `ario` directories into your project and include the relevant headers. No build or linking steps are required.
---
## Getting Started
1. **Add the header files** to your project:
- For ELFIO: `#include <elfio/elfio.hpp>`
- For ARIO: `#include <ario/ario.hpp>`
2. **No build steps required:** Both libraries are header-only.
3. **Example: Reading an ELF file**
```cpp
#include <elfio/elfio.hpp>
ELFIO::elfio reader;
if (reader.load("my_binary.elf")) {
// Access ELF sections, segments, symbols, etc.
}
```
4. **Example: Reading an archive file**
```cpp
#include <ario/ario.hpp>
ARIO::ario archive;
if (archive.load("libmylib.a").ok()) {
for (const auto& member : archive.members) {
std::cout << "Member: " << member.name << std::endl;
}
}
```
---
## Project Structure
- `elfio/` — ELFIO header files
- `ario/` — ARIO header files
- `examples/` — Example usage and sample tools
---
## Examples
The `examples/` directory contains a collection of sample programs demonstrating how to use ELFIO and ARIO in real-world scenarios. Each example focuses on a specific use case, such as reading and modifying ELF files, manipulating archive files, or integrating with C code. These examples serve both as practical tutorials and as a starting point for your own tools and applications.
**Purpose:**
- Illustrate typical usage patterns for ELFIO and ARIO
- Provide ready-to-use code for common binary and archive operations
- Help users quickly get started and understand library capabilities
Explore the `examples/` subdirectories for detailed demonstrations, including adding sections to ELF files, anonymizing binaries, working with archives, and more.
---
## Support
For questions or support, please open an issue on [GitHub](https://github.com/serge1/ELFIO/issues).
---
## Contributing
Contributions, bug reports, and feature requests are welcome! Please open an issue or submit a pull request on [GitHub](https://github.com/serge1/ELFIO).
---
## License
This project is licensed under the [MIT License](https://github.com/serge1/ELFIO/blob/main/LICENSE.txt).
---
## Resources
- [ELFIO Documentation (PDF)](http://elfio.sourceforge.net/elfio.pdf)
- [ELFIO on GitHub](https://github.com/serge1/ELFIO)
- [ELF Specification](https://refspecs.linuxbase.org/elf/elf.pdf)
+930
View File
@@ -0,0 +1,930 @@
//------------------------------------------------------------------------------
//! @file ario.hpp
//! @brief ARIO - Simple ar(1) archive reader/writer interface
//!
//! This file provides the ARIO namespace and the ario class for reading and manipulating UNIX ar archives.
//!
//! Copyright (C) 2025-present by Serge Lamikhov-Center
//!
//! Permission is hereby granted, free of charge, to any person obtaining a copy
//! of this software and associated documentation files (the "Software"), to deal
//! in the Software without restriction, including without limitation the rights
//! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
//! copies of the Software, and to permit persons to whom the Software is
//! furnished to do so, subject to the following conditions:
//!
//! The above copyright notice and this permission notice shall be included in
//! all copies or substantial portions of the Software.
//!
//! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
//! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
//! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
//! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
//! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
//! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
//! THE SOFTWARE.
#ifndef ARIO_HPP
#define ARIO_HPP
#include <iostream>
#include <fstream>
#include <iomanip>
#include <string>
#include <string_view>
#include <sstream>
#include <vector>
#include <optional>
#include <unordered_map>
#include <algorithm>
#include <memory>
#include <cstdint>
//------------------------------------------------------------------------------
namespace ARIO {
//------------------------------------------------------------------------------
//! @class ario
//! @brief Class for reading and manipulating ar(1) archives
class ario
{
public:
//------------------------------------------------------------------------------
//! @brief Error structure for ARIO operations
class Result
{
public:
Result() = default;
Result( const std::string& msg ) : message( msg ) {}
Result( std::string&& msg ) : message( std::move( msg ) ) {}
bool ok() const { return !message.has_value(); }
std::string what() const { return message.value_or( "No errors" ); }
private:
std::optional<std::string> message; ///< Error message, if any
};
//------------------------------------------------------------------------------
//! @struct Member
//! @brief Represents a single member (file) in the archive
class Member
{
public:
std::string name = {}; ///< Name of the member
int date = {}; ///< Date of the member
int uid = {}; ///< User ID of the member
int gid = {}; ///< Group ID of the member
int mode = {}; ///< Mode of the member
size_t size = {}; ///< Size of the member in the archive
//------------------------------------------------------------------------------
//! @brief Get the data of the member as a string
//! @return The data of the member
std::string data() const
{
if ( new_data.has_value() ) {
return new_data.value();
}
if ( !pstream ) {
return { "No input stream available for member data" };
}
std::string data( size, '\0' );
std::streamoff current_pos = pstream->tellg();
pstream->seekg( filepos + HEADER_SIZE, std::ios::beg );
if ( pstream->fail() ) {
return { "Failed to seek to member data position" };
}
pstream->read( &data[0], size );
if ( pstream->fail() || (size_t)pstream->gcount() < size ) {
return { "Failed to read member data" };
}
// Reset the stream position
pstream->clear();
pstream->seekg( current_pos, std::ios::beg );
return data;
}
operator std::string() const { return name; }
operator std::string_view() const { return name; }
operator const char*() const { return name.c_str(); }
bool operator==( std::string_view name ) const
{
return this->name == name;
}
protected:
void set_input_stream( std::shared_ptr<std::istream>& pstream )
{
this->pstream = pstream;
}
void set_new_data( std::string_view data ) { this->new_data = data; }
protected:
std::string short_name = {}; ///< Short name of the member
std::shared_ptr<std::istream> pstream =
nullptr; ///< Pointer to the input stream
std::streamoff filepos = {}; ///< File position in the archive
std::optional<std::string> new_data = {};
friend class ario;
};
//------------------------------------------------------------------------------
//! @class Members
//! @brief Provides access to the members of the archive
class Members
{
public:
//------------------------------------------------------------------------------
//! @brief Constructor
//! @param parent Pointer to the parent ario object
explicit Members( ario* parent ) : parent( parent ) {}
//------------------------------------------------------------------------------
//! @brief Get the number of members
//! @return The number of members
size_t size() const { return parent->members_.size(); }
//------------------------------------------------------------------------------
//! @brief Get a member by index
//! @param index The index of the member
//! @return Reference to the member
const Member& operator[]( size_t index ) const
{
if ( index >= parent->members_.size() ) {
throw std::out_of_range( "Member index out of range" );
}
return parent->members_[index];
}
//------------------------------------------------------------------------------
//! @brief Get a member by name
//! @param name The name of the member
//! @return Reference to the member, throws if not found
const Member& operator[]( std::string_view name ) const
{
for ( const auto& m : parent->members_ ) {
if ( m == name ) {
return m;
}
}
throw std::out_of_range( std::string( "Member not found: " ) +
std::string( name ) );
}
//------------------------------------------------------------------------------
//! @brief Get an iterator to the beginning of the members
//! @return Iterator to the beginning of the members
std::vector<Member>::iterator begin()
{
return parent->members_.begin();
}
//------------------------------------------------------------------------------
//! @brief Get an iterator to the end of the members
//! @return Iterator to the end of the members
std::vector<Member>::iterator end() { return parent->members_.end(); }
//------------------------------------------------------------------------------
//! @brief Get a const iterator to the beginning of the members
//! @return Const iterator to the beginning of the members
std::vector<Member>::const_iterator begin() const
{
return parent->members_.cbegin();
}
//------------------------------------------------------------------------------
//! @brief Get a const iterator to the end of the members
//! @return Const iterator to the end of the members
std::vector<Member>::const_iterator end() const
{
return parent->members_.cend();
}
//------------------------------------------------------------------------------
//! @brief Get a const reference to the first member
//! @return Const reference to the first member
const Member& front() const
{
if ( parent->members_.empty() ) {
throw std::out_of_range( "No members in archive" );
}
return parent->members_.front();
}
//------------------------------------------------------------------------------
//! @brief Get a const reference to the last member
//! @return Const reference to the last member
const Member& back() const
{
if ( parent->members_.empty() ) {
throw std::out_of_range( "No members in archive" );
}
return parent->members_.back();
}
private:
ario* parent; //!< Pointer to the parent ario object
};
//------------------------------------------------------------------------------
//! @brief Constructor
explicit ario() : members( this ) {};
ario( const ario& ) = delete;
ario& operator=( const ario& ) = delete;
ario( ario&& ) = delete;
ario& operator=( ario&& ) = delete;
~ario() = default;
//------------------------------------------------------------------------------
//! @brief Load an archive from a file
//! @param file_name The name of the archive file
//! @return Error object indicating success or failure
Result load( const std::string& file_name )
{
auto ifs = std::make_unique<std::ifstream>();
if ( !ifs ) {
return { "Failed to create input stream" };
}
ifs->open( file_name.c_str(), std::ios::in | std::ios::binary );
if ( !*ifs ) {
return { "Failed to open file: " + file_name };
}
auto result = load( std::move( ifs ) );
return result;
}
//------------------------------------------------------------------------------
//! @brief Load an archive from a stream
//! @param stream The input stream to load from
//! @return Error object indicating success or failure
Result load( std::unique_ptr<std::istream> is )
{
if ( !is ) {
return { "Input stream is null" };
}
pstream = std::move( is );
if ( !*pstream ) {
return { "Failed to set input stream" };
}
members_.clear();
auto result = load_header();
if ( !result.ok() ) {
return result;
}
result = load_members();
if ( !result.ok() ) {
return result;
}
return {};
}
//------------------------------------------------------------------------------
//! @brief Save an archive to a file
//! @param file_name The name of the archive file
//! @return Error object indicating success or failure
Result save( const std::string& file_name )
{
std::ofstream ofs;
ofs.open( file_name.c_str(), std::ios::out | std::ios::binary );
if ( !ofs ) {
return { "Failed to open file: " + file_name };
}
auto result = save( ofs );
ofs.close();
return result;
}
//------------------------------------------------------------------------------
//! @brief Save an archive to a stream
//! @param stream The output stream to save to
//! @return Error object indicating success or failure
Result save( std::ostream& os )
{
if ( !os ) {
return { "Output stream is null" };
}
os.clear();
os.seekp( 0, std::ios::beg );
auto result = save_header( os );
if ( !result.ok() ) {
return result;
}
// Save symbol table if it exists
if ( !symbol_table.empty() ) {
result = save_symbol_table( os );
if ( !result.ok() ) {
return result;
}
}
// Save long name directory if it exists
if ( !string_table.empty() ) {
result = save_long_name_directory( os );
if ( !result.ok() ) {
return result;
}
}
result = save_members( os );
if ( !result.ok() ) {
return result;
}
return {};
}
//! @brief Find a symbol in the archive
//! @param name The name of the symbol to find
//! @param out_member Pointer to store the found member
//! @param member Reference to store the found member
//! @return Error object indicating success or failure
//! If the symbol is found, out_member will point to the corresponding member
//! If the symbol is not found, out_member will stay unchanged
Result
find_symbol( std::string_view name,
std::optional<std::reference_wrapper<const ario::Member>>&
member ) const
{
const auto it = symbol_table.find( std::string( name ) );
if ( it != symbol_table.end() ) {
member = members_[it->second];
return {};
}
member = std::nullopt;
return { std::string( "Symbol not found: " ) + std::string( name ) };
}
//------------------------------------------------------------------------------
//! @brief Get symbols for a specific member
//! @param m Pointer to the member
//! @param symbols Vector to store the found symbols
//! @return Error object indicating success or failure
//! If the member is found, symbols will contain the associated symbols
//! If the member is not found, symbols will be empty
Result get_symbols_for_member( const ario::Member& member,
std::vector<std::string>& symbols ) const
{
std::string_view member_name = member.name;
size_t index = std::distance(
members.begin(),
std::find_if(
members.begin(), members.end(), [&]( const auto& mem ) {
return std::string_view( mem.name ) == member_name;
} ) );
if ( index >= members.size() ) {
return { "Member not found in archive" };
}
symbols.clear();
for ( const auto& symbol : symbol_table ) {
if ( symbol.second == index ) {
symbols.emplace_back( symbol.first );
}
}
return {};
}
//------------------------------------------------------------------------------
//! @brief Add a member to the archive
//! @param member The member to add
//! @param data The data associated with the member
//! @return Error object indicating success or failure
Result add_member( const Member& member, std::string_view data )
{
// Don't allow empty member names
if ( member.name.empty() ) {
return { "Member name cannot be empty" };
}
// Check if the member with such name already exists
for ( const auto& mem : members_ ) {
if ( mem.name == member.name ) {
return { "Member '" + member.name + "' already exists" };
}
}
auto& new_member = members_.emplace_back( member );
new_member.size = data.size();
new_member.pstream = nullptr;
new_member.set_new_data( data );
if ( member.name.size() < FIELD_NAME_SIZE ) {
new_member.short_name = member.name + "/";
}
else {
auto location = string_table.size();
string_table += member.name + "/\x0A";
new_member.short_name = "/" + std::to_string( location );
}
return {};
}
//------------------------------------------------------------------------------
//! @brief Add symbols for a member
//! @param member The member to add symbols for
//! @param symbols The symbols to add
//! @return Error object indicating success or failure
Result add_symbols_for_member( const ario::Member& member,
const std::vector<std::string>& symbols )
{
std::string_view member_name = member.name;
size_t index = std::distance(
members.begin(),
std::find_if(
members.begin(), members.end(), [&]( const auto& mem ) {
return std::string_view( mem.name ) == member_name;
} ) );
if ( index >= members.size() ) {
return { "Member not found in archive" };
}
for ( const auto& symbol : symbols ) {
symbol_table[symbol] = index;
}
return {};
}
protected:
//------------------------------------------------------------------------------
//! @brief Load the archive header
//! @param in Input file stream
//! @return Error object indicating success or failure
Result load_header()
{
auto arch_magic = std::string( ARCH_MAGIC );
auto arch_magic_size = arch_magic.size();
std::string magic( arch_magic_size, ' ' );
pstream->read( &magic[0], arch_magic_size );
if ( magic != arch_magic ) {
return { std::string( "Invalid archive format. Expected magic: " ) +
arch_magic + ", but got " + magic };
}
return {};
}
//------------------------------------------------------------------------------
//! @brief Load all members from the archive
//! @param in Input file stream
//! @return Error object indicating success or failure
Result load_members()
{
while ( true ) {
Member m;
m.set_input_stream( pstream );
char header[HEADER_SIZE];
auto filepos = pstream->tellg();
pstream->read( header, HEADER_SIZE );
if ( pstream->gcount() < HEADER_SIZE ) {
if ( pstream->gcount() > 0 ) {
return { "Corrupted archive" }; // End of file or error
}
break; // End of file reached
}
std::streamoff current_pos = pstream->tellg();
m.short_name = std::string( header, FIELD_NAME_SIZE );
m.name = m.short_name;
m.filepos = filepos;
std::string date_str( header + FIELD_NAME_SIZE, FIELD_DATE_SIZE );
std::string uid_str( header + FIELD_NAME_SIZE + FIELD_DATE_SIZE,
FIELD_UID_SIZE );
std::string gid_str( header + +FIELD_NAME_SIZE + FIELD_DATE_SIZE +
FIELD_UID_SIZE,
FIELD_GID_SIZE );
std::string mode_str( header + FIELD_NAME_SIZE + FIELD_DATE_SIZE +
FIELD_UID_SIZE + FIELD_GID_SIZE,
FIELD_MODE_SIZE );
std::string size_str( header + FIELD_NAME_SIZE + FIELD_DATE_SIZE +
FIELD_UID_SIZE + FIELD_GID_SIZE +
FIELD_MODE_SIZE,
FIELD_SIZE_SIZE );
try {
// Get m.size from the header. Do it earlier due to the potential use of m.data()
// It is the only valid field in special members like symbol table and long name directory
m.size = std::stoi( size_str );
}
catch ( const std::exception& ) {
return { "Invalid member size" };
}
if ( m.short_name ==
"/ " ) { // Special case for the symbol table
m.name = "/";
auto result = load_symbol_table();
if ( !result.ok() ) {
return result;
}
}
else if (
m.short_name ==
"// " ) { // Special case for the long name directory
m.name = "//";
string_table = m.data(); // Read the long name directory data
}
else {
try {
m.date = std::stoi( date_str );
m.uid = std::stoi( uid_str );
m.gid = std::stoi( gid_str );
m.mode = std::stoi( mode_str, nullptr, FIELD_MODE_SIZE );
}
catch ( const std::exception& ) {
return { "Invalid member header's field: " + m.short_name +
", " + date_str + ", " + uid_str + ", " + gid_str +
", " + mode_str };
}
if ( m.short_name[0] == '/' ) {
auto name_result = convert_name( m.short_name );
if ( !name_result.has_value() ) {
return { "Failed to convert long name for member " +
m.short_name };
}
m.name = *name_result;
}
else {
m.name = m.short_name.substr( 0, m.short_name.find( '/' ) );
}
// Add only the regular member to the list
members_.emplace_back( m );
}
// Skip the content of the member
pstream->clear();
pstream->seekg( current_pos + m.size + m.size % 2, std::ios::beg );
}
pstream->clear();
// Substitute symbol locations with member indexes
for ( auto& symbol : symbol_table ) {
auto index = 0;
const auto it = std::find_if(
members_.begin(), members_.end(),
[&]( const Member& m ) { return m.filepos == symbol.second; } );
if ( it != members_.end() ) {
index = (std::uint32_t)std::distance( members_.begin(), it );
}
symbol.second = index;
}
return {};
}
//------------------------------------------------------------------------------
//! @brief Save the archive header
//! @param os Output stream to save the header
//! @return Error object indicating success or failure
Result save_header( std::ostream& os )
{
if ( !os ) {
return { "Output stream is null" };
}
// Write the archive magic string
os << ARCH_MAGIC;
return {};
}
//------------------------------------------------------------------------------
//! @brief Calculate the size of the symbol table
//! @return The size of the symbol table in bytes
//! The size includes the header, number of symbols, symbol locations, and names
//! It also includes padding if the size is odd
//! @note The symbol table is saved after the archive header and before the long name directory
std::streamoff calculate_symbol_table_size() const
{
auto num_of_symbols = static_cast<std::uint32_t>( symbol_table.size() );
// Calculate the symbol table size
auto symbol_table_size =
HEADER_SIZE +
sizeof( num_of_symbols ) + // Size of the number of symbols
num_of_symbols *
( sizeof( std::uint32_t ) ); // Size of each symbol location
for ( const auto& symbol : symbol_table ) {
// Size of each symbol name + null terminator
symbol_table_size += symbol.first.size() + 1;
}
// Add padding byte if the size is odd
symbol_table_size += symbol_table_size % 2;
return symbol_table_size;
}
//------------------------------------------------------------------------------
//! @brief Calculate the relative offsets of members in the archive
//! @return A vector of relative offsets for each member
//! The offsets are calculated from the start of the archive
std::vector<std::uint32_t> calculate_member_relative_offsets()
{
std::vector<std::uint32_t> member_relative_offset;
size_t position = 0;
member_relative_offset.reserve( members_.size() );
for ( const auto& member : members_ ) {
// Store the relative offset of the member in the archive
member_relative_offset.push_back(
static_cast<std::uint32_t>( position ) );
position += HEADER_SIZE + member.size +
member.size % 2; // Add padding if needed
}
return member_relative_offset;
}
//------------------------------------------------------------------------------
//! @brief Calculate the size of the long names directory
//! @return The size of the long names directory in bytes
//! The size includes the header and the string table
//! It also includes padding if the size is odd
//! @note The long names directory is saved after the symbol table and before the members
std::streamoff calculate_long_names_dir_size()
{
return HEADER_SIZE + string_table.size() + string_table.size() % 2;
}
//------------------------------------------------------------------------------
//! @brief Save the symbol table to the archive
//! @param os Output stream to save the symbol table
//! @return Error object indicating success or failure
Result save_symbol_table( std::ostream& os )
{
if ( !os ) {
return { "Output stream is null" };
}
auto num_of_symbols = static_cast<std::uint32_t>( symbol_table.size() );
if ( num_of_symbols == 0 ) {
return {};
}
auto symbol_table_size = calculate_symbol_table_size();
auto long_names_dir_size = calculate_long_names_dir_size();
auto member_relative_offset = calculate_member_relative_offsets();
// Write the symbol table header
os << "/ 0 0 0 0 "
<< std::setw( FIELD_SIZE_SIZE ) << std::left << std::dec
<< symbol_table_size - HEADER_SIZE << HEADER_END_MAGIC;
// Write the number of symbols
char buf[4];
buf[0] = static_cast<char>( ( num_of_symbols >> 24 ) & 0xFF );
buf[1] = static_cast<char>( ( num_of_symbols >> 16 ) & 0xFF );
buf[2] = static_cast<char>( ( num_of_symbols >> 8 ) & 0xFF );
buf[3] = static_cast<char>( ( num_of_symbols >> 0 ) & 0xFF );
// Write the number of symbols as a 4-byte big-endian integer
os.write( buf, sizeof( buf ) );
// Write symbol locations (location of the member in the archive)
auto members_start_from =
std::string( ARCH_MAGIC ).size() +
static_cast<std::uint32_t>( symbol_table_size ) +
static_cast<std::uint32_t>( long_names_dir_size );
for ( const auto& symbol : symbol_table ) {
auto index = static_cast<std::uint32_t>( symbol.second );
auto location = members_start_from + member_relative_offset[index];
buf[0] = static_cast<char>( ( location >> 24 ) & 0xFF );
buf[1] = static_cast<char>( ( location >> 16 ) & 0xFF );
buf[2] = static_cast<char>( ( location >> 8 ) & 0xFF );
buf[3] = static_cast<char>( ( location >> 0 ) & 0xFF );
os.write( buf, sizeof( buf ) );
}
if ( os.fail() ) {
return { "Failed to write symbol table" };
}
// Write symbol names
for ( const auto& symbol : symbol_table ) {
os << symbol.first << '\0'; // Null-terminated string
}
if ( os.tellp() % 2 != 0 ) {
os << '\x0A';
}
if ( os.fail() ) {
return { "Failed to write symbol table" };
}
return {};
}
//------------------------------------------------------------------------------
//! @brief Save the long name directory to the archive
//! @param os Output stream to save the long name directory
//! @return Error object indicating success or failure
Result save_long_name_directory( std::ostream& os )
{
if ( !os ) {
return { "Output stream is null" };
}
// clang-format off
// Write the long name directory
os << "// "
<< std::setw( FIELD_SIZE_SIZE ) << std::left << std::dec << string_table.size()
<< HEADER_END_MAGIC
<< string_table;
// clang-format on
if ( string_table.size() % 2 != 0 ) {
// Write a padding byte if the size is odd
os.put( '\x0A' );
}
if ( os.fail() ) {
return { "Failed to write member data" };
}
return {};
}
//------------------------------------------------------------------------------
//! @brief Save the member information to the archive
//! @param os Output stream to save the member information
//! @return Error object indicating success or failure
Result save_members( std::ostream& os )
{
if ( !os ) {
return { "Output stream is null" };
}
for ( const auto& member : members_ ) {
// clang-format off
// Write the member header
os << std::setw( FIELD_NAME_SIZE ) << std::left << member.short_name
<< std::setw( FIELD_DATE_SIZE ) << std::left << member.date
<< std::setw( FIELD_UID_SIZE ) << std::left << member.uid
<< std::setw( FIELD_GID_SIZE ) << std::left << member.gid
<< std::setw( FIELD_MODE_SIZE ) << std::left << std::oct << member.mode
<< std::setw( FIELD_SIZE_SIZE ) << std::left << std::dec << member.size
<< HEADER_END_MAGIC;
// clang-format on
// Write the content of the member
os.write( member.data().data(), member.size );
if ( os.fail() ) {
return { "Failed to write member data" };
}
if ( member.size % 2 != 0 ) {
// Write a padding byte if the size is odd
os.put( '\x0A' );
if ( os.fail() ) {
return { "Failed to write padding byte" };
}
}
}
return {};
}
//------------------------------------------------------------------------------
//! @brief Read the symbol table from the archive symbol table member
//! @return Error object indicating success or failure
Result load_symbol_table()
{
char buf[4];
pstream->read( buf, sizeof( buf ) );
if ( pstream->gcount() < sizeof( buf ) ) {
return { "Failed to read symbol table" };
}
std::uint32_t num_of_symbols =
( static_cast<std::uint8_t>( buf[0] ) << 24 ) |
( static_cast<std::uint8_t>( buf[1] ) << 16 ) |
( static_cast<std::uint8_t>( buf[2] ) << 8 ) |
( static_cast<std::uint8_t>( buf[3] ) << 0 );
std::vector<std::pair<std::uint32_t, std::string>> v( num_of_symbols );
// Read symbol locations
for ( std::uint32_t i = 0; i < num_of_symbols; ++i ) {
pstream->read( buf, sizeof( buf ) );
if ( pstream->gcount() < sizeof( buf ) ) {
return { "Failed to read symbol table" };
}
std::uint32_t member_location =
( static_cast<std::uint8_t>( buf[0] ) << 24 ) |
( static_cast<std::uint8_t>( buf[1] ) << 16 ) |
( static_cast<std::uint8_t>( buf[2] ) << 8 ) |
( static_cast<std::uint8_t>( buf[3] ) << 0 );
v[i].first = member_location;
}
// Read symbol names
for ( std::uint32_t i = 0; i < num_of_symbols; ++i ) {
std::string sym_name;
std::getline( *pstream, sym_name, '\0' );
v[i].second = sym_name;
}
// Copy to symbol_table map
for ( const auto& pair : v ) {
symbol_table[pair.second] = pair.first;
}
return {};
}
//------------------------------------------------------------------------------
//! @brief Convert a short name to a long name using the long name directory
//! @param short_name The short name to convert
//! @return The long name
std::optional<std::string> convert_name( std::string_view short_name )
{
auto pos = short_name.find( '/' );
if ( pos == 0 ) {
if ( short_name.size() < 3 ) {
return std::nullopt;
}
size_t offset_in_dir = 0;
try {
offset_in_dir = std::stoul( std::string(
short_name.substr( 1, short_name.size() - 2 ) ) );
}
catch ( const std::exception& ) {
return std::nullopt;
}
if ( offset_in_dir >= string_table.size() ) {
return std::nullopt;
}
auto end = string_table.find( '/', offset_in_dir );
if ( end == std::string::npos || end <= offset_in_dir ) {
return std::nullopt;
}
std::string long_name =
string_table.substr( offset_in_dir, end - offset_in_dir );
return long_name;
}
else if ( pos != std::string::npos && pos != 0 &&
pos < short_name.size() ) {
return std::string( short_name.substr( 0, pos ) );
}
return std::string( short_name );
}
public:
Members members; //!< Members object
protected:
static constexpr const char* ARCH_MAGIC =
"!<arch>\x0A"; ///< Archive magic string
static constexpr const char* HEADER_END_MAGIC =
"\x60\x0A"; ///< End of header magic
static constexpr std::streamsize HEADER_SIZE =
60; ///< Size of archive header
static constexpr unsigned int FIELD_NAME_SIZE = 16;
static constexpr unsigned int FIELD_DATE_SIZE = 12;
static constexpr unsigned int FIELD_UID_SIZE = 6;
static constexpr unsigned int FIELD_GID_SIZE = 6;
static constexpr unsigned int FIELD_MODE_SIZE = 8;
static constexpr unsigned int FIELD_SIZE_SIZE = 10;
//!< Pointer to the input stream
//! It is used to read the archive members
//! data even after the archive is loaded
std::shared_ptr<std::istream> pstream = nullptr;
std::vector<Member> members_; //!< Vector of archive members
//!< Symbol table
//!< This is a map from symbol names to member indexes
//!< The member index is the index in the members_ vector
//!< This allows for quick lookup of symbols by name
std::unordered_map<std::string, size_t> symbol_table;
std::string string_table; //!< Long names for members
};
} // namespace ARIO
#endif // ARIO_HPP
+5
View File
@@ -0,0 +1,5 @@
# Basic CMake package config file
@PACKAGE_INIT@
include("${CMAKE_CURRENT_LIST_DIR}/@PROJECT_NAME@Targets.cmake")
check_required_components("@PROJECT_NAME@")
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
Binary file not shown.

After

Width:  |  Height:  |  Size: 207 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 837 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 374 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 889 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 329 B

+15
View File
@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 12.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 51448) -->
<!DOCTYPE svg [
<!ENTITY ns_svg "http://www.w3.org/2000/svg">
<!ENTITY ns_xlink "http://www.w3.org/1999/xlink">
]>
<svg version="1.0" id="Layer_1" xmlns="&ns_svg;" xmlns:xlink="&ns_xlink;" width="33" height="33" viewBox="0 0 33 33"
style="overflow:visible;enable-background:new 0 0 33 33;" xml:space="preserve">
<circle style="stroke:#000000;" cx="16.5" cy="16.5" r="16"/>
<g>
<g style="enable-background:new ;">
<path style="fill:#FFFFFF;" d="M10.428,10.411h0.56c3.78,0,4.788-1.96,4.872-3.444h3.22v19.88h-3.92V13.154h-4.732V10.411z"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 718 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 929 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 361 B

+18
View File
@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 12.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 51448) -->
<!DOCTYPE svg [
<!ENTITY ns_svg "http://www.w3.org/2000/svg">
<!ENTITY ns_xlink "http://www.w3.org/1999/xlink">
]>
<svg version="1.0" id="Layer_1" xmlns="&ns_svg;" xmlns:xlink="&ns_xlink;" width="33" height="33" viewBox="0 0 33 33"
style="overflow:visible;enable-background:new 0 0 33 33;" xml:space="preserve">
<circle style="stroke:#000000;" cx="16.5" cy="16.5" r="16"/>
<g>
<g style="enable-background:new ;">
<path style="fill:#FFFFFF;" d="M3.815,10.758h0.48c3.24,0,4.104-1.681,4.176-2.952h2.76v17.04h-3.36V13.11H3.815V10.758z"/>
<path style="fill:#FFFFFF;" d="M22.175,7.806c4.009,0,5.904,2.76,5.904,8.736c0,5.975-1.896,8.76-5.904,8.76
c-4.008,0-5.904-2.785-5.904-8.76C16.271,10.566,18.167,7.806,22.175,7.806z M22.175,22.613c1.921,0,2.448-1.68,2.448-6.071
c0-4.393-0.527-6.049-2.448-6.049c-1.92,0-2.448,1.656-2.448,6.049C19.727,20.934,20.255,22.613,22.175,22.613z"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 202 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 565 B

+16
View File
@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 12.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 51448) -->
<!DOCTYPE svg [
<!ENTITY ns_svg "http://www.w3.org/2000/svg">
<!ENTITY ns_xlink "http://www.w3.org/1999/xlink">
]>
<svg version="1.0" id="Layer_1" xmlns="&ns_svg;" xmlns:xlink="&ns_xlink;" width="33" height="33" viewBox="0 0 33 33"
style="overflow:visible;enable-background:new 0 0 33 33;" xml:space="preserve">
<circle style="stroke:#000000;" cx="16.5" cy="16.5" r="16"/>
<g>
<g style="enable-background:new ;">
<path style="fill:#FFFFFF;" d="M5.209,10.412h0.48c3.24,0,4.104-1.681,4.176-2.952h2.76V24.5h-3.36V12.764H5.209V10.412z"/>
<path style="fill:#FFFFFF;" d="M18.553,10.412h0.48c3.24,0,4.104-1.681,4.176-2.952h2.76V24.5h-3.359V12.764h-4.056V10.412z"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 843 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 210 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 617 B

+18
View File
@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 12.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 51448) -->
<!DOCTYPE svg [
<!ENTITY ns_svg "http://www.w3.org/2000/svg">
<!ENTITY ns_xlink "http://www.w3.org/1999/xlink">
]>
<svg version="1.0" id="Layer_1" xmlns="&ns_svg;" xmlns:xlink="&ns_xlink;" width="33" height="33" viewBox="0 0 33 33"
style="overflow:visible;enable-background:new 0 0 33 33;" xml:space="preserve">
<circle style="stroke:#000000;" cx="16.5" cy="16.5" r="16"/>
<g>
<g style="enable-background:new ;">
<path style="fill:#FFFFFF;" d="M4.813,10.412h0.48c3.24,0,4.104-1.681,4.176-2.952h2.76V24.5h-3.36V12.764H4.813V10.412z"/>
<path style="fill:#FFFFFF;" d="M17.316,13.484c0-5.545,4.056-6.024,5.568-6.024c3.265,0,5.856,1.92,5.856,5.376
c0,2.928-1.896,4.416-3.553,5.544c-2.256,1.584-3.432,2.353-3.815,3.145h7.392V24.5h-11.64c0.12-1.992,0.264-4.08,3.96-6.768
c3.072-2.232,4.296-3.097,4.296-5.017c0-1.128-0.72-2.424-2.353-2.424c-2.352,0-2.423,1.944-2.447,3.192H17.316z"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 209 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 623 B

+20
View File
@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 12.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 51448) -->
<!DOCTYPE svg [
<!ENTITY ns_svg "http://www.w3.org/2000/svg">
<!ENTITY ns_xlink "http://www.w3.org/1999/xlink">
]>
<svg version="1.0" id="Layer_1" xmlns="&ns_svg;" xmlns:xlink="&ns_xlink;" width="33" height="33" viewBox="0 0 33 33"
style="overflow:visible;enable-background:new 0 0 33 33;" xml:space="preserve">
<circle style="stroke:#000000;" cx="16.5" cy="16.5" r="16"/>
<g>
<g style="enable-background:new ;">
<path style="fill:#FFFFFF;" d="M3.813,10.412h0.48c3.24,0,4.104-1.681,4.176-2.952h2.76V24.5h-3.36V12.764H3.813V10.412z"/>
<path style="fill:#FFFFFF;" d="M20.611,14.636h0.529c1.008,0,2.855-0.096,2.855-2.304c0-0.624-0.288-2.185-2.137-2.185
c-2.303,0-2.303,2.185-2.303,2.784h-3.12c0-3.191,1.8-5.472,5.64-5.472c2.279,0,5.279,1.152,5.279,4.752
c0,1.728-1.08,2.808-2.039,3.24V15.5c0.6,0.168,2.568,1.056,2.568,3.96c0,3.216-2.377,5.496-5.809,5.496
c-1.607,0-5.928-0.36-5.928-5.688h3.288l-0.024,0.024c0,0.912,0.24,2.976,2.496,2.976c1.344,0,2.52-0.911,2.52-2.808
c0-2.328-2.256-2.424-3.816-2.424V14.636z"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 205 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 411 B

+17
View File
@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 12.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 51448) -->
<!DOCTYPE svg [
<!ENTITY ns_svg "http://www.w3.org/2000/svg">
<!ENTITY ns_xlink "http://www.w3.org/1999/xlink">
]>
<svg version="1.0" id="Layer_1" xmlns="&ns_svg;" xmlns:xlink="&ns_xlink;" width="33" height="33" viewBox="0 0 33 33"
style="overflow:visible;enable-background:new 0 0 33 33;" xml:space="preserve">
<circle style="stroke:#000000;" cx="16.5" cy="16.5" r="16"/>
<g>
<g style="enable-background:new ;">
<path style="fill:#FFFFFF;" d="M4.146,10.412h0.48c3.24,0,4.104-1.681,4.176-2.952h2.76V24.5h-3.36V12.764H4.146V10.412z"/>
<path style="fill:#FFFFFF;" d="M28.457,20.732h-1.896V24.5h-3.36v-3.768h-6.72v-2.904L22.746,7.46h3.815v10.656h1.896V20.732z
M23.201,18.116c0-4.128,0.072-6.792,0.072-7.32h-0.048l-4.272,7.32H23.201z"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 923 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 210 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 640 B

+19
View File
@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 12.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 51448) -->
<!DOCTYPE svg [
<!ENTITY ns_svg "http://www.w3.org/2000/svg">
<!ENTITY ns_xlink "http://www.w3.org/1999/xlink">
]>
<svg version="1.0" id="Layer_1" xmlns="&ns_svg;" xmlns:xlink="&ns_xlink;" width="33" height="33" viewBox="0 0 33 33"
style="overflow:visible;enable-background:new 0 0 33 33;" xml:space="preserve">
<circle style="stroke:#000000;" cx="16.5" cy="16.5" r="16"/>
<g>
<g style="enable-background:new ;">
<path style="fill:#FFFFFF;" d="M3.479,11.079h0.48c3.24,0,4.104-1.681,4.176-2.952h2.76v17.04h-3.36V13.43H3.479V11.079z"/>
<path style="fill:#FFFFFF;" d="M19.342,14.943c0.625-0.433,1.392-0.937,3.048-0.937c2.279,0,5.16,1.584,5.16,5.496
c0,2.328-1.176,6.121-6.192,6.121c-2.664,0-5.376-1.584-5.544-5.016h3.36c0.144,1.391,0.888,2.326,2.376,2.326
c1.607,0,2.544-1.367,2.544-3.191c0-1.512-0.72-3.047-2.496-3.047c-0.456,0-1.608,0.023-2.256,1.223l-3-0.143l1.176-9.361h9.36
v2.832h-6.937L19.342,14.943z"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

+20
View File
@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 12.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 51448) -->
<!DOCTYPE svg [
<!ENTITY ns_svg "http://www.w3.org/2000/svg">
<!ENTITY ns_xlink "http://www.w3.org/1999/xlink">
]>
<svg version="1.0" id="Layer_1" xmlns="&ns_svg;" xmlns:xlink="&ns_xlink;" width="33" height="33" viewBox="0 0 33 33"
style="overflow:visible;enable-background:new 0 0 33 33;" xml:space="preserve">
<circle style="stroke:#000000;" cx="16.5" cy="16.5" r="16"/>
<g>
<g style="enable-background:new ;">
<path style="fill:#FFFFFF;" d="M3.813,10.412h0.48c3.24,0,4.104-1.681,4.176-2.952h2.76V24.5h-3.36V12.764H3.813V10.412z"/>
<path style="fill:#FFFFFF;" d="M24.309,11.78c-0.097-0.96-0.721-1.633-1.969-1.633c-2.184,0-2.688,2.496-2.808,4.704L19.58,14.9
c0.456-0.624,1.296-1.416,3.191-1.416c3.529,0,5.209,2.712,5.209,5.256c0,3.72-2.28,6.216-5.568,6.216
c-5.16,0-6.168-4.32-6.168-8.568c0-3.24,0.432-8.928,6.336-8.928c0.695,0,2.641,0.264,3.48,1.104
c0.936,0.912,1.271,1.416,1.584,3.217H24.309z M22.172,16.172c-1.271,0-2.568,0.792-2.568,2.928c0,1.849,1.056,3.168,2.664,3.168
c1.225,0,2.353-0.936,2.353-3.239C24.62,16.868,23.229,16.172,22.172,16.172z"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

+17
View File
@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 12.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 51448) -->
<!DOCTYPE svg [
<!ENTITY ns_svg "http://www.w3.org/2000/svg">
<!ENTITY ns_xlink "http://www.w3.org/1999/xlink">
]>
<svg version="1.0" id="Layer_1" xmlns="&ns_svg;" xmlns:xlink="&ns_xlink;" width="33" height="33" viewBox="0 0 33 33"
style="overflow:visible;enable-background:new 0 0 33 33;" xml:space="preserve">
<circle style="stroke:#000000;" cx="16.5" cy="16.5" r="16"/>
<g>
<g style="enable-background:new ;">
<path style="fill:#FFFFFF;" d="M3.479,11.079h0.48c3.24,0,4.104-1.681,4.176-2.952h2.76v17.04h-3.36V13.43H3.479V11.079z"/>
<path style="fill:#FFFFFF;" d="M27.838,11.006c-1.631,1.776-5.807,6.816-6.215,14.16h-3.457c0.36-6.816,4.632-12.24,6.072-13.776
h-8.472l0.072-2.976h12V11.006z"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 883 B

+21
View File
@@ -0,0 +1,21 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 12.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 51448) -->
<!DOCTYPE svg [
<!ENTITY ns_svg "http://www.w3.org/2000/svg">
<!ENTITY ns_xlink "http://www.w3.org/1999/xlink">
]>
<svg version="1.0" id="Layer_1" xmlns="&ns_svg;" xmlns:xlink="&ns_xlink;" width="33" height="33" viewBox="0 0 33 33"
style="overflow:visible;enable-background:new 0 0 33 33;" xml:space="preserve">
<circle style="stroke:#000000;" cx="16.5" cy="16.5" r="16"/>
<g>
<g style="enable-background:new ;">
<path style="fill:#FFFFFF;" d="M4.813,10.412h0.48c3.24,0,4.104-1.681,4.176-2.952h2.76V24.5h-3.36V12.764H4.813V10.412z"/>
<path style="fill:#FFFFFF;" d="M23.172,24.956c-4.392,0-5.904-2.856-5.904-5.185c0-0.863,0-3.119,2.592-4.319
c-1.344-0.672-2.064-1.752-2.064-3.336c0-2.904,2.328-4.656,5.304-4.656c3.528,0,5.4,2.088,5.4,4.44
c0,1.464-0.6,2.712-1.968,3.432c1.632,0.815,2.544,1.896,2.544,4.104C29.076,21.596,27.684,24.956,23.172,24.956z M23.124,16.916
c-1.224,0-2.4,0.792-2.4,2.64c0,1.632,0.936,2.712,2.472,2.712c1.752,0,2.424-1.512,2.424-2.688
C25.62,18.38,24.996,16.916,23.124,16.916z M25.284,12.26c0-1.296-0.888-2.112-1.968-2.112c-1.512,0-2.305,0.864-2.305,2.112
c0,1.008,0.744,2.112,2.185,2.112C24.516,14.372,25.284,13.484,25.284,12.26z"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

+20
View File
@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 12.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 51448) -->
<!DOCTYPE svg [
<!ENTITY ns_svg "http://www.w3.org/2000/svg">
<!ENTITY ns_xlink "http://www.w3.org/1999/xlink">
]>
<svg version="1.0" id="Layer_1" xmlns="&ns_svg;" xmlns:xlink="&ns_xlink;" width="33" height="33" viewBox="0 0 33 33"
style="overflow:visible;enable-background:new 0 0 33 33;" xml:space="preserve">
<circle style="stroke:#000000;" cx="16.5" cy="16.5" r="16"/>
<g>
<g style="enable-background:new ;">
<path style="fill:#FFFFFF;" d="M4.146,10.746h0.48c3.24,0,4.104-1.681,4.176-2.952h2.76v17.041h-3.36V13.097H4.146V10.746z"/>
<path style="fill:#FFFFFF;" d="M20.225,20.898v0.023c0.192,1.176,0.936,1.68,1.968,1.68c1.392,0,2.783-1.176,2.808-4.752
l-0.048-0.049c-0.768,1.152-2.088,1.441-3.24,1.441c-3.264,0-5.16-2.473-5.16-5.329c0-4.176,2.472-6.12,5.808-6.12
c5.904,0,6,6.36,6,8.76c0,6.601-3.12,8.736-6.192,8.736c-2.904,0-4.992-1.68-5.28-4.391H20.225z M22.434,16.553
c1.176,0,2.472-0.84,2.472-2.855c0-1.944-0.841-3.145-2.568-3.145c-0.864,0-2.424,0.433-2.424,2.88
C19.913,16.001,21.161,16.553,22.434,16.553z"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 907 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 353 B

+17
View File
@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 12.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 51448) -->
<!DOCTYPE svg [
<!ENTITY ns_svg "http://www.w3.org/2000/svg">
<!ENTITY ns_xlink "http://www.w3.org/1999/xlink">
]>
<svg version="1.0" id="Layer_1" xmlns="&ns_svg;" xmlns:xlink="&ns_xlink;" width="33" height="33" viewBox="0 0 33 33"
style="overflow:visible;enable-background:new 0 0 33 33;" xml:space="preserve">
<circle style="stroke:#000000;" cx="16.5" cy="16.5" r="16"/>
<g>
<g style="enable-background:new ;">
<path style="fill:#FFFFFF;" d="M9.668,12.328c0-6.469,4.732-7.028,6.496-7.028c3.808,0,6.833,2.24,6.833,6.271
c0,3.416-2.213,5.152-4.145,6.469c-2.632,1.848-4.004,2.744-4.452,3.668h8.624v3.472H9.444c0.14-2.324,0.308-4.76,4.62-7.896
c3.584-2.604,5.012-3.612,5.012-5.853c0-1.315-0.84-2.828-2.744-2.828c-2.744,0-2.828,2.269-2.856,3.725H9.668z"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 943 B

+20
View File
@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 12.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 51448) -->
<!DOCTYPE svg [
<!ENTITY ns_svg "http://www.w3.org/2000/svg">
<!ENTITY ns_xlink "http://www.w3.org/1999/xlink">
]>
<svg version="1.0" id="Layer_1" xmlns="&ns_svg;" xmlns:xlink="&ns_xlink;" width="33" height="33" viewBox="0 0 33 33"
style="overflow:visible;enable-background:new 0 0 33 33;" xml:space="preserve">
<circle style="stroke:#000000;" cx="16.5" cy="16.5" r="16"/>
<g>
<g style="enable-background:new ;">
<path style="fill:#FFFFFF;" d="M3.972,13.484c0-5.545,4.056-6.024,5.568-6.024c3.264,0,5.856,1.92,5.856,5.376
c0,2.928-1.896,4.416-3.552,5.544c-2.256,1.584-3.432,2.353-3.816,3.145h7.392V24.5H3.78c0.12-1.992,0.264-4.08,3.96-6.768
c3.072-2.232,4.296-3.097,4.296-5.017c0-1.128-0.72-2.424-2.352-2.424c-2.352,0-2.424,1.944-2.448,3.192H3.972z"/>
<path style="fill:#FFFFFF;" d="M23.172,7.46c4.008,0,5.904,2.76,5.904,8.736c0,5.976-1.896,8.76-5.904,8.76
s-5.904-2.784-5.904-8.76C17.268,10.22,19.164,7.46,23.172,7.46z M23.172,22.268c1.92,0,2.448-1.68,2.448-6.071
c0-4.393-0.528-6.049-2.448-6.049s-2.448,1.656-2.448,6.049C20.724,20.588,21.252,22.268,23.172,22.268z"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

+18
View File
@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 12.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 51448) -->
<!DOCTYPE svg [
<!ENTITY ns_svg "http://www.w3.org/2000/svg">
<!ENTITY ns_xlink "http://www.w3.org/1999/xlink">
]>
<svg version="1.0" id="Layer_1" xmlns="&ns_svg;" xmlns:xlink="&ns_xlink;" width="33" height="33" viewBox="0 0 33 33"
style="overflow:visible;enable-background:new 0 0 33 33;" xml:space="preserve">
<circle style="stroke:#000000;" cx="16.5" cy="16.5" r="16"/>
<g>
<g style="enable-background:new ;">
<path style="fill:#FFFFFF;" d="M5.306,13.151c0-5.545,4.056-6.024,5.568-6.024c3.264,0,5.856,1.92,5.856,5.376
c0,2.928-1.896,4.416-3.552,5.544c-2.256,1.584-3.432,2.353-3.816,3.145h7.392v2.976H5.114c0.12-1.992,0.264-4.08,3.96-6.768
c3.072-2.232,4.296-3.097,4.296-5.017c0-1.128-0.72-2.424-2.352-2.424c-2.352,0-2.424,1.944-2.448,3.192H5.306z"/>
<path style="fill:#FFFFFF;" d="M19.49,10.079h0.48c3.239,0,4.104-1.681,4.176-2.952h2.761v17.04h-3.361V12.431H19.49V10.079z"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.0 KiB

+20
View File
@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 12.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 51448) -->
<!DOCTYPE svg [
<!ENTITY ns_svg "http://www.w3.org/2000/svg">
<!ENTITY ns_xlink "http://www.w3.org/1999/xlink">
]>
<svg version="1.0" id="Layer_1" xmlns="&ns_svg;" xmlns:xlink="&ns_xlink;" width="33" height="33" viewBox="0 0 33 33"
style="overflow:visible;enable-background:new 0 0 33 33;" xml:space="preserve">
<circle style="stroke:#000000;" cx="16.5" cy="16.5" r="16"/>
<g>
<g style="enable-background:new ;">
<path style="fill:#FFFFFF;" d="M3.972,13.484c0-5.545,4.056-6.024,5.568-6.024c3.264,0,5.856,1.92,5.856,5.376
c0,2.928-1.896,4.416-3.552,5.544c-2.256,1.584-3.432,2.353-3.816,3.145h7.392V24.5H3.78c0.12-1.992,0.264-4.08,3.96-6.768
c3.072-2.232,4.296-3.097,4.296-5.017c0-1.128-0.72-2.424-2.352-2.424c-2.352,0-2.424,1.944-2.448,3.192H3.972z"/>
<path style="fill:#FFFFFF;" d="M17.316,13.484c0-5.545,4.056-6.024,5.568-6.024c3.265,0,5.856,1.92,5.856,5.376
c0,2.928-1.896,4.416-3.553,5.544c-2.256,1.584-3.432,2.353-3.815,3.145h7.392V24.5h-11.64c0.12-1.992,0.264-4.08,3.96-6.768
c3.072-2.232,4.296-3.097,4.296-5.017c0-1.128-0.72-2.424-2.353-2.424c-2.352,0-2.423,1.944-2.447,3.192H17.316z"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

+22
View File
@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 12.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 51448) -->
<!DOCTYPE svg [
<!ENTITY ns_svg "http://www.w3.org/2000/svg">
<!ENTITY ns_xlink "http://www.w3.org/1999/xlink">
]>
<svg version="1.0" id="Layer_1" xmlns="&ns_svg;" xmlns:xlink="&ns_xlink;" width="33" height="33" viewBox="0 0 33 33"
style="overflow:visible;enable-background:new 0 0 33 33;" xml:space="preserve">
<circle style="stroke:#000000;" cx="16.5" cy="16.5" r="16"/>
<g>
<g style="enable-background:new ;">
<path style="fill:#FFFFFF;" d="M3.972,13.484c0-5.545,4.056-6.024,5.568-6.024c3.264,0,5.856,1.92,5.856,5.376
c0,2.928-1.896,4.416-3.552,5.544c-2.256,1.584-3.432,2.353-3.816,3.145h7.392V24.5H3.78c0.12-1.992,0.264-4.08,3.96-6.768
c3.072-2.232,4.296-3.097,4.296-5.017c0-1.128-0.72-2.424-2.352-2.424c-2.352,0-2.424,1.944-2.448,3.192H3.972z"/>
<path style="fill:#FFFFFF;" d="M21.612,14.636h0.528c1.008,0,2.855-0.096,2.855-2.304c0-0.624-0.287-2.185-2.136-2.185
c-2.304,0-2.304,2.185-2.304,2.784h-3.12c0-3.191,1.8-5.472,5.64-5.472c2.28,0,5.28,1.152,5.28,4.752
c0,1.728-1.08,2.808-2.04,3.24V15.5c0.6,0.168,2.568,1.056,2.568,3.96c0,3.216-2.377,5.496-5.809,5.496
c-1.607,0-5.928-0.36-5.928-5.688h3.288l-0.024,0.024c0,0.912,0.24,2.976,2.496,2.976c1.344,0,2.521-0.911,2.521-2.808
c0-2.328-2.257-2.424-3.816-2.424V14.636z"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.4 KiB

+19
View File
@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 12.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 51448) -->
<!DOCTYPE svg [
<!ENTITY ns_svg "http://www.w3.org/2000/svg">
<!ENTITY ns_xlink "http://www.w3.org/1999/xlink">
]>
<svg version="1.0" id="Layer_1" xmlns="&ns_svg;" xmlns:xlink="&ns_xlink;" width="33" height="33" viewBox="0 0 33 33"
style="overflow:visible;enable-background:new 0 0 33 33;" xml:space="preserve">
<circle style="stroke:#000000;" cx="16.5" cy="16.5" r="16"/>
<g>
<g style="enable-background:new ;">
<path style="fill:#FFFFFF;" d="M4.972,13.484c0-5.545,4.056-6.024,5.568-6.024c3.264,0,5.856,1.92,5.856,5.376
c0,2.928-1.896,4.416-3.552,5.544c-2.256,1.584-3.432,2.353-3.816,3.145h7.392V24.5H4.78c0.12-1.992,0.264-4.08,3.96-6.768
c3.072-2.232,4.296-3.097,4.296-5.017c0-1.128-0.72-2.424-2.352-2.424c-2.352,0-2.424,1.944-2.448,3.192H4.972z"/>
<path style="fill:#FFFFFF;" d="M30.124,20.732h-1.896V24.5h-3.36v-3.768h-6.72v-2.904L24.412,7.46h3.816v10.656h1.896V20.732z
M24.868,18.116c0-4.128,0.071-6.792,0.071-7.32h-0.047l-4.272,7.32H24.868z"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

+21
View File
@@ -0,0 +1,21 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 12.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 51448) -->
<!DOCTYPE svg [
<!ENTITY ns_svg "http://www.w3.org/2000/svg">
<!ENTITY ns_xlink "http://www.w3.org/1999/xlink">
]>
<svg version="1.0" id="Layer_1" xmlns="&ns_svg;" xmlns:xlink="&ns_xlink;" width="33" height="33" viewBox="0 0 33 33"
style="overflow:visible;enable-background:new 0 0 33 33;" xml:space="preserve">
<circle style="stroke:#000000;" cx="16.5" cy="16.5" r="16"/>
<g>
<g style="enable-background:new ;">
<path style="fill:#FFFFFF;" d="M3.972,13.484c0-5.545,4.056-6.024,5.568-6.024c3.264,0,5.856,1.92,5.856,5.376
c0,2.928-1.896,4.416-3.552,5.544c-2.256,1.584-3.432,2.353-3.816,3.145h7.392V24.5H3.78c0.12-1.992,0.264-4.08,3.96-6.768
c3.072-2.232,4.296-3.097,4.296-5.017c0-1.128-0.72-2.424-2.352-2.424c-2.352,0-2.424,1.944-2.448,3.192H3.972z"/>
<path style="fill:#FFFFFF;" d="M20.676,14.276c0.624-0.433,1.393-0.937,3.049-0.937c2.279,0,5.16,1.584,5.16,5.496
c0,2.328-1.177,6.12-6.193,6.12c-2.664,0-5.375-1.584-5.543-5.016h3.36c0.144,1.392,0.889,2.327,2.376,2.327
c1.608,0,2.544-1.367,2.544-3.191c0-1.513-0.72-3.048-2.496-3.048c-0.455,0-1.607,0.023-2.256,1.224l-3-0.144l1.176-9.36h9.36
v2.832h-6.937L20.676,14.276z"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

+22
View File
@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 12.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 51448) -->
<!DOCTYPE svg [
<!ENTITY ns_svg "http://www.w3.org/2000/svg">
<!ENTITY ns_xlink "http://www.w3.org/1999/xlink">
]>
<svg version="1.0" id="Layer_1" xmlns="&ns_svg;" xmlns:xlink="&ns_xlink;" width="33" height="33" viewBox="0 0 33 33"
style="overflow:visible;enable-background:new 0 0 33 33;" xml:space="preserve">
<circle style="stroke:#000000;" cx="16.5" cy="16.5" r="16"/>
<g>
<g style="enable-background:new ;">
<path style="fill:#FFFFFF;" d="M3.972,13.484c0-5.545,4.056-6.024,5.568-6.024c3.264,0,5.856,1.92,5.856,5.376
c0,2.928-1.896,4.416-3.552,5.544c-2.256,1.584-3.432,2.353-3.816,3.145h7.392V24.5H3.78c0.12-1.992,0.264-4.08,3.96-6.768
c3.072-2.232,4.296-3.097,4.296-5.017c0-1.128-0.72-2.424-2.352-2.424c-2.352,0-2.424,1.944-2.448,3.192H3.972z"/>
<path style="fill:#FFFFFF;" d="M25.309,11.78c-0.097-0.96-0.721-1.633-1.969-1.633c-2.184,0-2.688,2.496-2.808,4.704L20.58,14.9
c0.456-0.624,1.296-1.416,3.191-1.416c3.529,0,5.209,2.712,5.209,5.256c0,3.72-2.28,6.216-5.568,6.216
c-5.16,0-6.168-4.32-6.168-8.568c0-3.24,0.432-8.928,6.336-8.928c0.695,0,2.641,0.264,3.48,1.104
c0.936,0.912,1.271,1.416,1.584,3.217H25.309z M23.172,16.172c-1.271,0-2.568,0.792-2.568,2.928c0,1.849,1.056,3.168,2.664,3.168
c1.225,0,2.353-0.936,2.353-3.239C25.62,16.868,24.229,16.172,23.172,16.172z"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.4 KiB

+19
View File
@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 12.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 51448) -->
<!DOCTYPE svg [
<!ENTITY ns_svg "http://www.w3.org/2000/svg">
<!ENTITY ns_xlink "http://www.w3.org/1999/xlink">
]>
<svg version="1.0" id="Layer_1" xmlns="&ns_svg;" xmlns:xlink="&ns_xlink;" width="33" height="33" viewBox="0 0 33 33"
style="overflow:visible;enable-background:new 0 0 33 33;" xml:space="preserve">
<circle style="stroke:#000000;" cx="16.5" cy="16.5" r="16"/>
<g>
<g style="enable-background:new ;">
<path style="fill:#FFFFFF;" d="M3.972,13.484c0-5.545,4.056-6.024,5.568-6.024c3.264,0,5.856,1.92,5.856,5.376
c0,2.928-1.896,4.416-3.552,5.544c-2.256,1.584-3.432,2.353-3.816,3.145h7.392V24.5H3.78c0.12-1.992,0.264-4.08,3.96-6.768
c3.072-2.232,4.296-3.097,4.296-5.017c0-1.128-0.72-2.424-2.352-2.424c-2.352,0-2.424,1.944-2.448,3.192H3.972z"/>
<path style="fill:#FFFFFF;" d="M29.172,10.34c-1.632,1.776-5.808,6.816-6.216,14.16H19.5c0.36-6.816,4.632-12.24,6.072-13.776
H17.1l0.072-2.976h12V10.34z"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

+23
View File
@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 12.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 51448) -->
<!DOCTYPE svg [
<!ENTITY ns_svg "http://www.w3.org/2000/svg">
<!ENTITY ns_xlink "http://www.w3.org/1999/xlink">
]>
<svg version="1.0" id="Layer_1" xmlns="&ns_svg;" xmlns:xlink="&ns_xlink;" width="33" height="33" viewBox="0 0 33 33"
style="overflow:visible;enable-background:new 0 0 33 33;" xml:space="preserve">
<circle style="stroke:#000000;" cx="16.5" cy="16.5" r="16"/>
<g>
<g style="enable-background:new ;">
<path style="fill:#FFFFFF;" d="M3.972,13.484c0-5.545,4.056-6.024,5.568-6.024c3.264,0,5.856,1.92,5.856,5.376
c0,2.928-1.896,4.416-3.552,5.544c-2.256,1.584-3.432,2.353-3.816,3.145h7.392V24.5H3.78c0.12-1.992,0.264-4.08,3.96-6.768
c3.072-2.232,4.296-3.097,4.296-5.017c0-1.128-0.72-2.424-2.352-2.424c-2.352,0-2.424,1.944-2.448,3.192H3.972z"/>
<path style="fill:#FFFFFF;" d="M23.172,24.956c-4.392,0-5.904-2.856-5.904-5.185c0-0.863,0-3.119,2.592-4.319
c-1.344-0.672-2.064-1.752-2.064-3.336c0-2.904,2.328-4.656,5.304-4.656c3.528,0,5.4,2.088,5.4,4.44
c0,1.464-0.6,2.712-1.968,3.432c1.632,0.815,2.544,1.896,2.544,4.104C29.076,21.596,27.684,24.956,23.172,24.956z M23.124,16.916
c-1.224,0-2.4,0.792-2.4,2.64c0,1.632,0.936,2.712,2.472,2.712c1.752,0,2.424-1.512,2.424-2.688
C25.62,18.38,24.996,16.916,23.124,16.916z M25.284,12.26c0-1.296-0.888-2.112-1.968-2.112c-1.512,0-2.305,0.864-2.305,2.112
c0,1.008,0.744,2.112,2.185,2.112C24.516,14.372,25.284,13.484,25.284,12.26z"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.5 KiB

+22
View File
@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 12.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 51448) -->
<!DOCTYPE svg [
<!ENTITY ns_svg "http://www.w3.org/2000/svg">
<!ENTITY ns_xlink "http://www.w3.org/1999/xlink">
]>
<svg version="1.0" id="Layer_1" xmlns="&ns_svg;" xmlns:xlink="&ns_xlink;" width="33" height="33" viewBox="0 0 33 33"
style="overflow:visible;enable-background:new 0 0 33 33;" xml:space="preserve">
<circle style="stroke:#000000;" cx="16.5" cy="16.5" r="16"/>
<g>
<g style="enable-background:new ;">
<path style="fill:#FFFFFF;" d="M3.972,13.484c0-5.545,4.056-6.024,5.568-6.024c3.264,0,5.856,1.92,5.856,5.376
c0,2.928-1.896,4.416-3.552,5.544c-2.256,1.584-3.432,2.353-3.816,3.145h7.392V24.5H3.78c0.12-1.992,0.264-4.08,3.96-6.768
c3.072-2.232,4.296-3.097,4.296-5.017c0-1.128-0.72-2.424-2.352-2.424c-2.352,0-2.424,1.944-2.448,3.192H3.972z"/>
<path style="fill:#FFFFFF;" d="M20.893,20.564v0.023c0.191,1.176,0.936,1.68,1.967,1.68c1.393,0,2.785-1.176,2.809-4.752
l-0.048-0.048c-0.769,1.152-2.088,1.44-3.24,1.44c-3.264,0-5.16-2.473-5.16-5.328c0-4.176,2.472-6.12,5.807-6.12
c5.904,0,6.001,6.36,6.001,8.76c0,6.601-3.12,8.736-6.192,8.736c-2.904,0-4.992-1.68-5.28-4.392H20.893z M23.1,16.22
c1.176,0,2.473-0.84,2.473-2.855c0-1.944-0.84-3.145-2.568-3.145c-0.863,0-2.424,0.433-2.424,2.88
C20.58,15.668,21.828,16.22,23.1,16.22z"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 914 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 350 B

+19
View File
@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 12.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 51448) -->
<!DOCTYPE svg [
<!ENTITY ns_svg "http://www.w3.org/2000/svg">
<!ENTITY ns_xlink "http://www.w3.org/1999/xlink">
]>
<svg version="1.0" id="Layer_1" xmlns="&ns_svg;" xmlns:xlink="&ns_xlink;" width="33" height="33" viewBox="0 0 33 33"
style="overflow:visible;enable-background:new 0 0 33 33;" xml:space="preserve">
<circle style="stroke:#000000;" cx="16.5" cy="16.5" r="16"/>
<g>
<g style="enable-background:new ;">
<path style="fill:#FFFFFF;" d="M15.127,14.005h0.616c1.176,0,3.332-0.112,3.332-2.688c0-0.728-0.336-2.548-2.492-2.548
c-2.688,0-2.688,2.548-2.688,3.248h-3.64c0-3.724,2.1-6.384,6.58-6.384c2.66,0,6.16,1.344,6.16,5.544
c0,2.016-1.261,3.276-2.38,3.78v0.056c0.699,0.196,2.996,1.232,2.996,4.62c0,3.752-2.772,6.412-6.776,6.412
c-1.876,0-6.916-0.42-6.916-6.636h3.836l-0.028,0.027c0,1.064,0.28,3.473,2.912,3.473c1.568,0,2.94-1.064,2.94-3.276
c0-2.716-2.632-2.828-4.452-2.828V14.005z"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

+22
View File
@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 12.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 51448) -->
<!DOCTYPE svg [
<!ENTITY ns_svg "http://www.w3.org/2000/svg">
<!ENTITY ns_xlink "http://www.w3.org/1999/xlink">
]>
<svg version="1.0" id="Layer_1" xmlns="&ns_svg;" xmlns:xlink="&ns_xlink;" width="33" height="33" viewBox="0 0 33 33"
style="overflow:visible;enable-background:new 0 0 33 33;" xml:space="preserve">
<circle style="stroke:#000000;" cx="16.5" cy="16.5" r="16"/>
<g>
<g style="enable-background:new ;">
<path style="fill:#FFFFFF;" d="M8.268,14.636h0.528c1.008,0,2.856-0.096,2.856-2.304c0-0.624-0.288-2.185-2.136-2.185
c-2.304,0-2.304,2.185-2.304,2.784h-3.12c0-3.191,1.8-5.472,5.64-5.472c2.28,0,5.28,1.152,5.28,4.752
c0,1.728-1.08,2.808-2.04,3.24V15.5c0.6,0.168,2.568,1.056,2.568,3.96c0,3.216-2.376,5.496-5.808,5.496
c-1.608,0-5.928-0.36-5.928-5.688h3.288l-0.024,0.024c0,0.912,0.24,2.976,2.496,2.976c1.344,0,2.52-0.911,2.52-2.808
c0-2.328-2.256-2.424-3.816-2.424V14.636z"/>
<path style="fill:#FFFFFF;" d="M23.172,7.46c4.008,0,5.904,2.76,5.904,8.736c0,5.976-1.896,8.76-5.904,8.76
s-5.904-2.784-5.904-8.76C17.268,10.22,19.164,7.46,23.172,7.46z M23.172,22.268c1.92,0,2.448-1.68,2.448-6.071
c0-4.393-0.528-6.049-2.448-6.049s-2.448,1.656-2.448,6.049C20.724,20.588,21.252,22.268,23.172,22.268z"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 907 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 345 B

+16
View File
@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 12.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 51448) -->
<!DOCTYPE svg [
<!ENTITY ns_svg "http://www.w3.org/2000/svg">
<!ENTITY ns_xlink "http://www.w3.org/1999/xlink">
]>
<svg version="1.0" id="Layer_1" xmlns="&ns_svg;" xmlns:xlink="&ns_xlink;" width="33" height="33" viewBox="0 0 33 33"
style="overflow:visible;enable-background:new 0 0 33 33;" xml:space="preserve">
<circle style="stroke:#000000;" cx="16.5" cy="16.5" r="16"/>
<g>
<g style="enable-background:new ;">
<path style="fill:#FFFFFF;" d="M21.891,20.784h-2.212v4.396h-3.92v-4.396h-7.84v-3.389L15.227,5.3h4.452v12.432h2.212V20.784z
M15.759,17.731c0-4.815,0.084-7.924,0.084-8.54h-0.056l-4.984,8.54H15.759z"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 799 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 916 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 348 B

+18
View File
@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 12.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 51448) -->
<!DOCTYPE svg [
<!ENTITY ns_svg "http://www.w3.org/2000/svg">
<!ENTITY ns_xlink "http://www.w3.org/1999/xlink">
]>
<svg version="1.0" id="Layer_1" xmlns="&ns_svg;" xmlns:xlink="&ns_xlink;" width="33" height="33" viewBox="0 0 33 33"
style="overflow:visible;enable-background:new 0 0 33 33;" xml:space="preserve">
<circle style="stroke:#000000;" cx="16.5" cy="16.5" r="16"/>
<g>
<g style="enable-background:new ;">
<path style="fill:#FFFFFF;" d="M14.035,14.252c0.728-0.504,1.624-1.092,3.556-1.092c2.66,0,6.02,1.848,6.02,6.411
c0,2.717-1.372,7.141-7.224,7.141c-3.108,0-6.272-1.849-6.468-5.853h3.92c0.168,1.624,1.036,2.717,2.772,2.717
c1.876,0,2.968-1.597,2.968-3.725c0-1.764-0.839-3.556-2.912-3.556c-0.532,0-1.876,0.028-2.632,1.428l-3.5-0.168l1.372-10.92
h10.919v3.304h-8.092L14.035,14.252z"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 985 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 218 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 355 B

+19
View File
@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 12.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 51448) -->
<!DOCTYPE svg [
<!ENTITY ns_svg "http://www.w3.org/2000/svg">
<!ENTITY ns_xlink "http://www.w3.org/1999/xlink">
]>
<svg version="1.0" id="Layer_1" xmlns="&ns_svg;" xmlns:xlink="&ns_xlink;" width="33" height="33" viewBox="0 0 33 33"
style="overflow:visible;enable-background:new 0 0 33 33;" xml:space="preserve">
<circle style="stroke:#000000;" cx="16.5" cy="16.5" r="16"/>
<g>
<g style="enable-background:new ;">
<path style="fill:#FFFFFF;" d="M19.106,10.673c-0.112-1.12-0.84-1.904-2.296-1.904c-2.548,0-3.136,2.912-3.276,5.488l0.056,0.056
c0.532-0.728,1.512-1.651,3.724-1.651c4.116,0,6.077,3.164,6.077,6.131c0,4.34-2.66,7.252-6.497,7.252
c-6.02,0-7.196-5.039-7.196-9.996c0-3.78,0.504-10.416,7.392-10.416c0.812,0,3.08,0.308,4.061,1.288
c1.092,1.063,1.483,1.652,1.848,3.752H19.106z M16.614,15.797c-1.484,0-2.996,0.924-2.996,3.416c0,2.156,1.232,3.697,3.108,3.697
c1.428,0,2.745-1.094,2.745-3.781C19.471,16.609,17.846,15.797,16.614,15.797z"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 907 B

Some files were not shown because too many files have changed in this diff Show More