Compare commits
82 Commits
e52b33671b
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
| a52dc89f9f | |||
| cc2b96f37a | |||
| 80a29d8ff6 | |||
| 4f55d765b4 | |||
| ec732d4627 | |||
| 3f3795df3c | |||
| 2faad79559 | |||
| 9b25dcd691 | |||
| 33b3a641fb | |||
| d3a91b6438 | |||
| fa152cac4d | |||
| e105b2fe35 | |||
| 7f78f20b17 | |||
| b4d6315dea | |||
| a05e73e69a | |||
| 0cc78a7247 | |||
| 5d77974586 | |||
| ae6f5d9df0 | |||
| ecfe1a7eae | |||
| 88f9d0e3d4 | |||
| 28c95303e9 | |||
| 638214a0e2 | |||
| 4fb5448dd9 | |||
| 2a0dddead3 | |||
| edcdaa5c60 | |||
| 77b5a4a153 | |||
| f2b7c5da57 | |||
| 58a47edc79 | |||
| 0a43ba36cd | |||
| e66fe4030d | |||
| 55b58bbe22 | |||
| bc53f9746e | |||
| d7059ac4e3 | |||
| af27592957 | |||
| 7da422fdb6 | |||
| 871c9cf439 | |||
| cf4a6b23c7 | |||
| 71fa87d7a4 | |||
| ecee481b33 | |||
| 3726cc49da | |||
| ef7a45e7cf | |||
| a530304e18 | |||
| f8863d19bd | |||
| f9d3fde4ad | |||
| c2364fbd48 | |||
| 4fe907a733 | |||
| 07fc8a5562 | |||
| 5bd6ca0fa7 | |||
| 7256fcd818 | |||
| 51e89c8603 | |||
| 566b35f4d5 | |||
| 7015bc9576 | |||
| 344952fb5f | |||
| f5dae4984d | |||
| 8fc99a5fb1 | |||
| 91ecc2dc6a | |||
| 1f793f287f | |||
| 44893aeeb0 | |||
| 26e5d92947 | |||
| d81d1133dd | |||
| 7e3b162591 | |||
| a349154545 | |||
| 1f93e8db13 | |||
| 81015d600b | |||
| 5c02d4d44a | |||
| efaddb970a | |||
| f4dbe830db | |||
| 6da93cd854 | |||
| 4084336705 | |||
| 02d60129b1 | |||
| e4a5c07b3d | |||
| e0162e9e0b | |||
| 2fa77d073f | |||
| f3fcc92991 | |||
| 0ed10b019a | |||
| da72450d2a | |||
| 771bbd1e9a | |||
| 95e5d17018 | |||
| 88ac5cf877 | |||
| 9612e7961e | |||
| 0f93aa2a81 | |||
| 179c4b98e2 |
1
.gitignore
vendored
1
.gitignore
vendored
@ -3,3 +3,4 @@
|
|||||||
*.iso
|
*.iso
|
||||||
*.img
|
*.img
|
||||||
*.hdd
|
*.hdd
|
||||||
|
*.6pk
|
||||||
|
|||||||
19
FastLZ/.editorconfig
Normal file
19
FastLZ/.editorconfig
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
# top-most EditorConfig file
|
||||||
|
root = true
|
||||||
|
|
||||||
|
# Unix-style newlines with a newline ending every file
|
||||||
|
[*]
|
||||||
|
charset = utf-8
|
||||||
|
trim_trailing_whitespace = true
|
||||||
|
end_of_line = lf
|
||||||
|
insert_final_newline = true
|
||||||
|
|
||||||
|
[*.{c,h}]
|
||||||
|
indent_size = 2
|
||||||
|
indent_style = space
|
||||||
|
|
||||||
|
[Makefile]
|
||||||
|
indent_style = tab
|
||||||
|
|
||||||
|
[Makefile.win]
|
||||||
|
indent_style = tab
|
||||||
32
FastLZ/.github/workflows/amd64_linux_clang.yml
vendored
Normal file
32
FastLZ/.github/workflows/amd64_linux_clang.yml
vendored
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
name: amd64_linux_clang
|
||||||
|
|
||||||
|
on: [push, pull_request]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
|
||||||
|
amd64_linux_clang:
|
||||||
|
runs-on: ubuntu-20.04
|
||||||
|
timeout-minutes: 10
|
||||||
|
env:
|
||||||
|
CC: clang
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
- name: Retrieve test compression corpus
|
||||||
|
run: |
|
||||||
|
git clone https://github.com/ariya/compression-corpus.git
|
||||||
|
cd compression-corpus
|
||||||
|
cd enwik
|
||||||
|
unzip enwik8.zip
|
||||||
|
- run: sudo apt install -y make clang
|
||||||
|
- run: clang --version
|
||||||
|
- run: cd tests && make roundtrip
|
||||||
|
name: Perform round-trip tests
|
||||||
|
- name: 'Build examples: 6pack and 6unpack'
|
||||||
|
run: cd examples && make
|
||||||
|
- name: 'Run examples: 6pack and 6unpack'
|
||||||
|
run: |
|
||||||
|
cd examples
|
||||||
|
./6pack -v
|
||||||
|
./6pack ../compression-corpus/enwik/enwik8.txt archive.6pk
|
||||||
|
./6unpack -v
|
||||||
|
./6unpack archive.6pk
|
||||||
32
FastLZ/.github/workflows/amd64_linux_gcc.yml
vendored
Normal file
32
FastLZ/.github/workflows/amd64_linux_gcc.yml
vendored
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
name: amd64_linux_gcc
|
||||||
|
|
||||||
|
on: [push, pull_request]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
|
||||||
|
amd64_linux_gcc:
|
||||||
|
runs-on: ubuntu-20.04
|
||||||
|
timeout-minutes: 10
|
||||||
|
env:
|
||||||
|
CC: gcc
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
- name: Retrieve test compression corpus
|
||||||
|
run: |
|
||||||
|
git clone https://github.com/ariya/compression-corpus.git
|
||||||
|
cd compression-corpus
|
||||||
|
cd enwik
|
||||||
|
unzip enwik8.zip
|
||||||
|
- run: sudo apt install -y make gcc
|
||||||
|
- run: gcc --version
|
||||||
|
- run: cd tests && make roundtrip
|
||||||
|
name: Perform round-trip tests
|
||||||
|
- name: 'Build examples: 6pack and 6unpack'
|
||||||
|
run: cd examples && make
|
||||||
|
- name: 'Run examples: 6pack and 6unpack'
|
||||||
|
run: |
|
||||||
|
cd examples
|
||||||
|
./6pack -v
|
||||||
|
./6pack ../compression-corpus/enwik/enwik8.txt archive.6pk
|
||||||
|
./6unpack -v
|
||||||
|
./6unpack archive.6pk
|
||||||
32
FastLZ/.github/workflows/amd64_linux_tcc.yml
vendored
Normal file
32
FastLZ/.github/workflows/amd64_linux_tcc.yml
vendored
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
name: amd64_linux_tcc
|
||||||
|
|
||||||
|
on: [push, pull_request]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
|
||||||
|
amd64_linux_tcc:
|
||||||
|
runs-on: ubuntu-20.04
|
||||||
|
timeout-minutes: 10
|
||||||
|
env:
|
||||||
|
CC: tcc
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
- name: Retrieve test compression corpus
|
||||||
|
run: |
|
||||||
|
git clone https://github.com/ariya/compression-corpus.git
|
||||||
|
cd compression-corpus
|
||||||
|
cd enwik
|
||||||
|
unzip enwik8.zip
|
||||||
|
- run: sudo apt install -y make tcc
|
||||||
|
- run: tcc -v
|
||||||
|
- run: cd tests && make roundtrip
|
||||||
|
name: Perform round-trip tests
|
||||||
|
- name: 'Build examples: 6pack and 6unpack'
|
||||||
|
run: cd examples && make
|
||||||
|
- name: 'Run examples: 6pack and 6unpack'
|
||||||
|
run: |
|
||||||
|
cd examples
|
||||||
|
./6pack -v
|
||||||
|
./6pack ../compression-corpus/enwik/enwik8.txt archive.6pk
|
||||||
|
./6unpack -v
|
||||||
|
./6unpack archive.6pk
|
||||||
29
FastLZ/.github/workflows/amd64_macos_clang.yml
vendored
Normal file
29
FastLZ/.github/workflows/amd64_macos_clang.yml
vendored
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
name: amd64_macos_clang
|
||||||
|
|
||||||
|
on: [push, pull_request]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
|
||||||
|
amd64_macos_clang:
|
||||||
|
runs-on: macos-latest
|
||||||
|
timeout-minutes: 10
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
- name: Retrieve test compression corpus
|
||||||
|
run: |
|
||||||
|
git clone https://github.com/ariya/compression-corpus.git
|
||||||
|
cd compression-corpus
|
||||||
|
cd enwik
|
||||||
|
unzip enwik8.zip
|
||||||
|
- run: cc --version
|
||||||
|
- run: cd tests && make roundtrip
|
||||||
|
name: Perform round-trip tests
|
||||||
|
- name: 'Build examples: 6pack and 6unpack'
|
||||||
|
run: cd examples && make
|
||||||
|
- name: 'Run examples: 6pack and 6unpack'
|
||||||
|
run: |
|
||||||
|
cd examples
|
||||||
|
./6pack -v
|
||||||
|
./6pack ../compression-corpus/enwik/enwik8.txt archive.6pk
|
||||||
|
./6unpack -v
|
||||||
|
./6unpack archive.6pk
|
||||||
32
FastLZ/.github/workflows/amd64_macos_gcc.yml
vendored
Normal file
32
FastLZ/.github/workflows/amd64_macos_gcc.yml
vendored
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
name: amd64_macos_gcc
|
||||||
|
|
||||||
|
on: [push, pull_request]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
|
||||||
|
amd64_macos_gcc:
|
||||||
|
runs-on: macos-12
|
||||||
|
timeout-minutes: 10
|
||||||
|
env:
|
||||||
|
CC: gcc-9
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
- name: Retrieve test compression corpus
|
||||||
|
run: |
|
||||||
|
git clone https://github.com/ariya/compression-corpus.git
|
||||||
|
cd compression-corpus
|
||||||
|
cd enwik
|
||||||
|
unzip enwik8.zip
|
||||||
|
- run: brew install gcc@9
|
||||||
|
- run: gcc-9 --version
|
||||||
|
- run: cd tests && make roundtrip
|
||||||
|
name: Perform round-trip tests
|
||||||
|
- name: 'Build examples: 6pack and 6unpack'
|
||||||
|
run: cd examples && make
|
||||||
|
- name: 'Run examples: 6pack and 6unpack'
|
||||||
|
run: |
|
||||||
|
cd examples
|
||||||
|
./6pack -v
|
||||||
|
./6pack ../compression-corpus/enwik/enwik8.txt archive.6pk
|
||||||
|
./6unpack -v
|
||||||
|
./6unpack archive.6pk
|
||||||
34
FastLZ/.github/workflows/amd64_windows_clang.yml
vendored
Normal file
34
FastLZ/.github/workflows/amd64_windows_clang.yml
vendored
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
name: amd64_windows_clang
|
||||||
|
|
||||||
|
on: [push, pull_request]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
|
||||||
|
amd64_windows_clang:
|
||||||
|
runs-on: windows-2019
|
||||||
|
timeout-minutes: 10
|
||||||
|
env:
|
||||||
|
CC: clang
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
- name: Retrieve test compression corpus
|
||||||
|
run: |
|
||||||
|
git clone https://github.com/ariya/compression-corpus.git
|
||||||
|
cd compression-corpus
|
||||||
|
cd enwik
|
||||||
|
unzip enwik8.zip
|
||||||
|
- uses: msys2/setup-msys2@v2
|
||||||
|
with:
|
||||||
|
install: make mingw-w64-x86_64-clang
|
||||||
|
- run: clang --version
|
||||||
|
- run: cd tests && make roundtrip
|
||||||
|
name: Perform round-trip tests
|
||||||
|
- name: 'Build examples: 6pack and 6unpack'
|
||||||
|
run: cd examples && make
|
||||||
|
- name: 'Run examples: 6pack and 6unpack'
|
||||||
|
run: |
|
||||||
|
cd examples
|
||||||
|
./6pack -v
|
||||||
|
./6pack ../compression-corpus/enwik/enwik8.txt archive.6pk
|
||||||
|
./6unpack -v
|
||||||
|
./6unpack archive.6pk
|
||||||
34
FastLZ/.github/workflows/amd64_windows_gcc.yml
vendored
Normal file
34
FastLZ/.github/workflows/amd64_windows_gcc.yml
vendored
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
name: amd64_windows_gcc
|
||||||
|
|
||||||
|
on: [push, pull_request]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
|
||||||
|
amd64_windows_gcc:
|
||||||
|
runs-on: windows-2019
|
||||||
|
timeout-minutes: 10
|
||||||
|
env:
|
||||||
|
CC: gcc
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
- name: Retrieve test compression corpus
|
||||||
|
run: |
|
||||||
|
git clone https://github.com/ariya/compression-corpus.git
|
||||||
|
cd compression-corpus
|
||||||
|
cd enwik
|
||||||
|
unzip enwik8.zip
|
||||||
|
- uses: msys2/setup-msys2@v2
|
||||||
|
with:
|
||||||
|
install: gcc make
|
||||||
|
- run: gcc --version
|
||||||
|
- run: cd tests && make roundtrip
|
||||||
|
name: Perform round-trip tests
|
||||||
|
- name: 'Build examples: 6pack and 6unpack'
|
||||||
|
run: cd examples && make
|
||||||
|
- name: 'Run examples: 6pack and 6unpack'
|
||||||
|
run: |
|
||||||
|
cd examples
|
||||||
|
./6pack -v
|
||||||
|
./6pack ../compression-corpus/enwik/enwik8.txt archive.6pk
|
||||||
|
./6unpack -v
|
||||||
|
./6unpack archive.6pk
|
||||||
35
FastLZ/.github/workflows/amd64_windows_tcc.yml
vendored
Normal file
35
FastLZ/.github/workflows/amd64_windows_tcc.yml
vendored
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
name: amd64_windows_tcc
|
||||||
|
|
||||||
|
on: [push, pull_request]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
|
||||||
|
amd64_windows_tcc:
|
||||||
|
runs-on: windows-2019
|
||||||
|
timeout-minutes: 10
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
- name: Retrieve test compression corpus
|
||||||
|
run: |
|
||||||
|
git clone https://github.com/ariya/compression-corpus.git
|
||||||
|
cd compression-corpus
|
||||||
|
cd enwik
|
||||||
|
unzip enwik8.zip
|
||||||
|
- name: Install tcc
|
||||||
|
run: |
|
||||||
|
echo "5a3979bd5044b795547a4948a5625a12 tcc.zip" > checksum.md5
|
||||||
|
dos2unix checksum.md5
|
||||||
|
curl -L -o tcc.zip https://archive.org/download/tinyccompiler/tcc-0.9.27-win32-bin.zip
|
||||||
|
md5sum -c checksum.md5 && unzip -q tcc.zip
|
||||||
|
- run: tcc\x86_64-win32-tcc.exe -v
|
||||||
|
- run: cd tests && make roundtrip CC=..\tcc\x86_64-win32-tcc.exe
|
||||||
|
name: Perform round-trip tests
|
||||||
|
- name: 'Build examples: 6pack and 6unpack'
|
||||||
|
run: cd examples && make CC=..\tcc\x86_64-win32-tcc.exe
|
||||||
|
- name: 'Run examples: 6pack and 6unpack'
|
||||||
|
run: |
|
||||||
|
cd examples
|
||||||
|
./6pack -v
|
||||||
|
./6pack ../compression-corpus/enwik/enwik8.txt archive.6pk
|
||||||
|
./6unpack -v
|
||||||
|
./6unpack archive.6pk
|
||||||
30
FastLZ/.github/workflows/amd64_windows_vs2019.yml
vendored
Normal file
30
FastLZ/.github/workflows/amd64_windows_vs2019.yml
vendored
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
name: amd64_windows_vs2019
|
||||||
|
|
||||||
|
on: [push, pull_request]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
|
||||||
|
amd64_windows_vs2019:
|
||||||
|
runs-on: windows-2019
|
||||||
|
timeout-minutes: 10
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
- name: Retrieve test compression corpus
|
||||||
|
run: |
|
||||||
|
git clone https://github.com/ariya/compression-corpus.git
|
||||||
|
cd compression-corpus
|
||||||
|
cd enwik
|
||||||
|
unzip enwik8.zip
|
||||||
|
- uses: ilammy/msvc-dev-cmd@v1
|
||||||
|
- run: cl
|
||||||
|
- run: cd tests && mingw32-make -f Makefile.win roundtrip
|
||||||
|
name: Perform round-trip tests
|
||||||
|
- name: 'Build examples: 6pack and 6unpack'
|
||||||
|
run: cd examples && make -f Makefile.win
|
||||||
|
- name: 'Run examples: 6pack and 6unpack'
|
||||||
|
run: |
|
||||||
|
cd examples
|
||||||
|
./6pack -v
|
||||||
|
./6pack ../compression-corpus/enwik/enwik8.txt archive.6pk
|
||||||
|
./6unpack -v
|
||||||
|
./6unpack archive.6pk
|
||||||
41
FastLZ/.github/workflows/arm64_linux_gcc.yml
vendored
Normal file
41
FastLZ/.github/workflows/arm64_linux_gcc.yml
vendored
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
name: arm64_linux_gcc
|
||||||
|
|
||||||
|
on: [push, pull_request]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
|
||||||
|
arm64_linux_gcc:
|
||||||
|
runs-on: ubuntu-20.04
|
||||||
|
timeout-minutes: 10
|
||||||
|
env:
|
||||||
|
CC: /opt/aarch64-linux-musl-cross/bin/aarch64-linux-musl-gcc
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
- name: Retrieve test compression corpus
|
||||||
|
run: |
|
||||||
|
git clone https://github.com/ariya/compression-corpus.git
|
||||||
|
cd compression-corpus
|
||||||
|
cd enwik
|
||||||
|
unzip enwik8.zip
|
||||||
|
- run: sudo apt-get -y -qq update
|
||||||
|
- run: sudo apt install -y qemu-user
|
||||||
|
- name: Prepare cross-compiler
|
||||||
|
run: |
|
||||||
|
curl -O http://musl.cc/aarch64-linux-musl-cross.tgz
|
||||||
|
tar xzf aarch64-linux-musl-cross.tgz -C /opt
|
||||||
|
- name: Verify compiler version
|
||||||
|
run: /opt/aarch64-linux-musl-cross/bin/aarch64-linux-musl-gcc --version
|
||||||
|
- name: Perform round-trip tests
|
||||||
|
run: |
|
||||||
|
cd tests
|
||||||
|
make test_roundtrip CFLAGS=-static
|
||||||
|
file ./test_roundtrip
|
||||||
|
qemu-aarch64 ./test_roundtrip
|
||||||
|
- name: 'Build and run example: 6pack and 6unpack'
|
||||||
|
run: |
|
||||||
|
cd examples
|
||||||
|
make CFLAGS=-static
|
||||||
|
qemu-aarch64 ./6pack -v
|
||||||
|
qemu-aarch64 ./6pack ../compression-corpus/enwik/enwik8.txt archive.6pk
|
||||||
|
qemu-aarch64 ./6unpack -v
|
||||||
|
qemu-aarch64 ./6unpack archive.6pk
|
||||||
41
FastLZ/.github/workflows/armhf_linux_gcc.yml
vendored
Normal file
41
FastLZ/.github/workflows/armhf_linux_gcc.yml
vendored
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
name: armhf_linux_gcc
|
||||||
|
|
||||||
|
on: [push, pull_request]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
|
||||||
|
armhf_linux_gcc:
|
||||||
|
runs-on: ubuntu-20.04
|
||||||
|
timeout-minutes: 10
|
||||||
|
env:
|
||||||
|
CC: /opt/armel-linux-musleabihf-cross/bin/armel-linux-musleabihf-gcc
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
- name: Retrieve test compression corpus
|
||||||
|
run: |
|
||||||
|
git clone https://github.com/ariya/compression-corpus.git
|
||||||
|
cd compression-corpus
|
||||||
|
cd enwik
|
||||||
|
unzip enwik8.zip
|
||||||
|
- run: sudo apt-get -y -qq update
|
||||||
|
- run: sudo apt install -y qemu-user
|
||||||
|
- name: Prepare cross-compiler
|
||||||
|
run: |
|
||||||
|
curl -O https://musl.cc/armel-linux-musleabihf-cross.tgz
|
||||||
|
tar xzf armel-linux-musleabihf-cross.tgz -C /opt
|
||||||
|
- name: Verify compiler version
|
||||||
|
run: /opt/armel-linux-musleabihf-cross/bin/armel-linux-musleabihf-gcc --version
|
||||||
|
- name: Perform round-trip tests
|
||||||
|
run: |
|
||||||
|
cd tests
|
||||||
|
make test_roundtrip CFLAGS=-static
|
||||||
|
file ./test_roundtrip
|
||||||
|
qemu-arm ./test_roundtrip
|
||||||
|
- name: 'Build and run example: 6pack and 6unpack'
|
||||||
|
run: |
|
||||||
|
cd examples
|
||||||
|
make CFLAGS=-static
|
||||||
|
qemu-arm ./6pack -v
|
||||||
|
qemu-arm ./6pack ../compression-corpus/enwik/enwik8.txt archive.6pk
|
||||||
|
qemu-arm ./6unpack -v
|
||||||
|
qemu-arm ./6unpack archive.6pk
|
||||||
29
FastLZ/.github/workflows/asan.yml
vendored
Normal file
29
FastLZ/.github/workflows/asan.yml
vendored
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
name: Address Sanitizer
|
||||||
|
|
||||||
|
on: [push, pull_request]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
|
||||||
|
asan:
|
||||||
|
runs-on: ubuntu-20.04
|
||||||
|
timeout-minutes: 10
|
||||||
|
env:
|
||||||
|
CC: gcc
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
- name: Retrieve test compression corpus
|
||||||
|
run: |
|
||||||
|
git clone https://github.com/ariya/compression-corpus.git
|
||||||
|
cd compression-corpus
|
||||||
|
cd enwik
|
||||||
|
unzip enwik8.zip
|
||||||
|
- run: sudo apt install -y make gcc
|
||||||
|
- run: gcc --version
|
||||||
|
- run: cd tests && make roundtrip
|
||||||
|
name: Perform round-trip tests
|
||||||
|
env:
|
||||||
|
CFLAGS: "-g -fno-omit-frame-pointer -fsanitize=address"
|
||||||
|
- run: cd tests && make roundtrip
|
||||||
|
name: Perform round-trip tests with FASTLZ_USE_MEMMOVE=0
|
||||||
|
env:
|
||||||
|
CFLAGS: "-g -fno-omit-frame-pointer -fsanitize=address -DFASTLZ_USE_MEMMOVE=0"
|
||||||
19
FastLZ/.github/workflows/codestyle.yml
vendored
Normal file
19
FastLZ/.github/workflows/codestyle.yml
vendored
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
name: Code style
|
||||||
|
|
||||||
|
on: [push, pull_request]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
|
||||||
|
codestyle:
|
||||||
|
runs-on: ubuntu-20.04
|
||||||
|
timeout-minutes: 10
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
- run: sudo apt install -y clang-format-6.0
|
||||||
|
name: Install clang-format
|
||||||
|
- run: clang-format-6.0 --version
|
||||||
|
- run: bash tools/format-code.sh
|
||||||
|
name: Run code formatter
|
||||||
|
- run: git diff
|
||||||
|
- run: git diff --quiet HEAD
|
||||||
|
name: Check if the styling guide is followed
|
||||||
52
FastLZ/.github/workflows/i586_dos_gcc_cross.yml
vendored
Normal file
52
FastLZ/.github/workflows/i586_dos_gcc_cross.yml
vendored
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
name: i586_dos_gcc_cross
|
||||||
|
|
||||||
|
on: [push, pull_request]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
|
||||||
|
i586_dos_gcc_cross:
|
||||||
|
runs-on: ubuntu-20.04
|
||||||
|
timeout-minutes: 15
|
||||||
|
env:
|
||||||
|
CC: /opt/djgpp/bin/i586-pc-msdosdjgpp-gcc
|
||||||
|
LDFLAGS: -static
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
- name: Retrieve test compression corpus
|
||||||
|
run: |
|
||||||
|
git clone https://github.com/ariya/compression-corpus.git
|
||||||
|
cd compression-corpus
|
||||||
|
cd enwik
|
||||||
|
unzip enwik8.zip
|
||||||
|
- run: sudo apt-get -y -qq update
|
||||||
|
- name: Prepare cross-compiler
|
||||||
|
run: |
|
||||||
|
curl -OL https://github.com/andrewwutw/build-djgpp/releases/download/v3.3/djgpp-linux64-gcc1210.tar.bz2
|
||||||
|
tar xf djgpp-linux64-gcc1210.tar.bz2 -C /opt
|
||||||
|
- name: Verify compiler version
|
||||||
|
run: /opt/djgpp/bin/i586-pc-msdosdjgpp-gcc --version
|
||||||
|
- name: Install DOSEMU2
|
||||||
|
run: |
|
||||||
|
sudo add-apt-repository -y ppa:dosemu2/ppa
|
||||||
|
sudo apt update -y
|
||||||
|
sudo apt install -y dosemu2
|
||||||
|
- run: dosemu --version
|
||||||
|
- name: Perform round-trip tests
|
||||||
|
run: |
|
||||||
|
cd tests
|
||||||
|
ln -s ../compression-corpus/ corpus
|
||||||
|
make test_roundtrip TEST_ROUNDTRIP=testrr
|
||||||
|
file ./testrr.exe
|
||||||
|
dosemu -dumb -K . -t -E "testrr corpus/"
|
||||||
|
- name: 'Build and run example: 6pack and 6unpack'
|
||||||
|
run: |
|
||||||
|
cd examples
|
||||||
|
ln -s ../compression-corpus/enwik/enwik8.txt enwik8.txt
|
||||||
|
make
|
||||||
|
file ./6pack.exe
|
||||||
|
dosemu -K . -t -E "6pack.exe -v"
|
||||||
|
dosemu -K . -t -E "6pack.exe enwik8.txt archive.6pk"
|
||||||
|
mv enwik8.txt enwik8.txt.orig
|
||||||
|
dosemu -K . -t -E "6unpack.exe -v"
|
||||||
|
dosemu -K . -t -E "6unpack.exe archive.6pk"
|
||||||
|
ls -l enwik8*
|
||||||
36
FastLZ/.github/workflows/i686_linux_clang.yml
vendored
Normal file
36
FastLZ/.github/workflows/i686_linux_clang.yml
vendored
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
name: i686_linux_clang
|
||||||
|
|
||||||
|
on: [push, pull_request]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
|
||||||
|
i686_linux_clang:
|
||||||
|
runs-on: ubuntu-20.04
|
||||||
|
timeout-minutes: 10
|
||||||
|
env:
|
||||||
|
CC: clang
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
- name: Retrieve test compression corpus
|
||||||
|
run: |
|
||||||
|
git clone https://github.com/ariya/compression-corpus.git
|
||||||
|
cd compression-corpus
|
||||||
|
cd enwik
|
||||||
|
unzip enwik8.zip
|
||||||
|
- run: sudo apt-get -y -qq update
|
||||||
|
- run: sudo apt install -y make clang gcc-multilib qemu-user
|
||||||
|
- run: clang --version
|
||||||
|
- name: Perform round-trip tests
|
||||||
|
run: |
|
||||||
|
cd tests
|
||||||
|
make test_roundtrip CFLAGS="-static -m32"
|
||||||
|
file ./test_roundtrip
|
||||||
|
qemu-i386 ./test_roundtrip
|
||||||
|
- name: 'Build and run example: 6pack and 6unpack'
|
||||||
|
run: |
|
||||||
|
cd examples
|
||||||
|
make CFLAGS="-static -m32"
|
||||||
|
qemu-i386 ./6pack -v
|
||||||
|
qemu-i386 ./6pack ../compression-corpus/enwik/enwik8.txt archive.6pk
|
||||||
|
qemu-i386 ./6unpack -v
|
||||||
|
qemu-i386 ./6unpack archive.6pk
|
||||||
41
FastLZ/.github/workflows/i686_linux_gcc.yml
vendored
Normal file
41
FastLZ/.github/workflows/i686_linux_gcc.yml
vendored
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
name: i686_linux_gcc
|
||||||
|
|
||||||
|
on: [push, pull_request]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
|
||||||
|
i686_linux_gcc:
|
||||||
|
runs-on: ubuntu-20.04
|
||||||
|
timeout-minutes: 10
|
||||||
|
env:
|
||||||
|
CC: /opt/i686-linux-musl-cross/bin/i686-linux-musl-gcc
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
- name: Retrieve test compression corpus
|
||||||
|
run: |
|
||||||
|
git clone https://github.com/ariya/compression-corpus.git
|
||||||
|
cd compression-corpus
|
||||||
|
cd enwik
|
||||||
|
unzip enwik8.zip
|
||||||
|
- run: sudo apt-get -y -qq update
|
||||||
|
- run: sudo apt install -y qemu-user
|
||||||
|
- name: Prepare cross-compiler
|
||||||
|
run: |
|
||||||
|
curl -O https://musl.cc/i686-linux-musl-cross.tgz
|
||||||
|
tar xzf i686-linux-musl-cross.tgz -C /opt
|
||||||
|
- name: Verify compiler version
|
||||||
|
run: /opt/i686-linux-musl-cross/bin/i686-linux-musl-gcc --version
|
||||||
|
- name: Perform round-trip tests
|
||||||
|
run: |
|
||||||
|
cd tests
|
||||||
|
make test_roundtrip CFLAGS=-static
|
||||||
|
file ./test_roundtrip
|
||||||
|
qemu-i386 ./test_roundtrip
|
||||||
|
- name: 'Build and run examples: 6pack and 6unpack'
|
||||||
|
run: |
|
||||||
|
cd examples
|
||||||
|
make CFLAGS=-static
|
||||||
|
qemu-i386 ./6pack -v
|
||||||
|
qemu-i386 ./6pack ../compression-corpus/enwik/enwik8.txt archive.6pk
|
||||||
|
qemu-i386 ./6unpack -v
|
||||||
|
qemu-i386 ./6unpack archive.6pk
|
||||||
35
FastLZ/.github/workflows/i686_windows_tcc.yml
vendored
Normal file
35
FastLZ/.github/workflows/i686_windows_tcc.yml
vendored
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
name: i686_windows_tcc
|
||||||
|
|
||||||
|
on: [push, pull_request]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
|
||||||
|
i686_windows_tcc:
|
||||||
|
runs-on: windows-2019
|
||||||
|
timeout-minutes: 10
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
- name: Retrieve test compression corpus
|
||||||
|
run: |
|
||||||
|
git clone https://github.com/ariya/compression-corpus.git
|
||||||
|
cd compression-corpus
|
||||||
|
cd enwik
|
||||||
|
unzip enwik8.zip
|
||||||
|
- name: Install tcc
|
||||||
|
run: |
|
||||||
|
echo "D73CF66CEC8C761DE38C7A3D16C9EB0D tcc.zip" > checksum.md5
|
||||||
|
dos2unix checksum.md5
|
||||||
|
curl -L -o tcc.zip https://archive.org/download/tinyccompiler/tcc-0.9.27-win64-bin.zip
|
||||||
|
md5sum -c checksum.md5 && unzip -q tcc.zip
|
||||||
|
- run: tcc\i386-win32-tcc.exe -v
|
||||||
|
- run: cd tests && make roundtrip CC=..\tcc\i386-win32-tcc.exe
|
||||||
|
name: Perform round-trip tests
|
||||||
|
- name: 'Build examples: 6pack and 6unpack'
|
||||||
|
run: cd examples && make CC=..\tcc\i386-win32-tcc.exe
|
||||||
|
- name: 'Run examples: 6pack and 6unpack'
|
||||||
|
run: |
|
||||||
|
cd examples
|
||||||
|
./6pack -v
|
||||||
|
./6pack ../compression-corpus/enwik/enwik8.txt archive.6pk
|
||||||
|
./6unpack -v
|
||||||
|
./6unpack archive.6pk
|
||||||
32
FastLZ/.github/workflows/i686_windows_vs2019.yml
vendored
Normal file
32
FastLZ/.github/workflows/i686_windows_vs2019.yml
vendored
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
name: i686_windows_vs2019
|
||||||
|
|
||||||
|
on: [push, pull_request]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
|
||||||
|
i686_windows_vs2019:
|
||||||
|
runs-on: windows-2019
|
||||||
|
timeout-minutes: 10
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
- name: Retrieve test compression corpus
|
||||||
|
run: |
|
||||||
|
git clone https://github.com/ariya/compression-corpus.git
|
||||||
|
cd compression-corpus
|
||||||
|
cd enwik
|
||||||
|
unzip enwik8.zip
|
||||||
|
- uses: ilammy/msvc-dev-cmd@v1
|
||||||
|
with:
|
||||||
|
arch: x86
|
||||||
|
- run: cl
|
||||||
|
- run: cd tests && mingw32-make -f Makefile.win roundtrip
|
||||||
|
name: Perform round-trip tests
|
||||||
|
- name: 'Build examples: 6pack and 6unpack'
|
||||||
|
run: cd examples && make -f Makefile.win
|
||||||
|
- name: 'Run examples: 6pack and 6unpack'
|
||||||
|
run: |
|
||||||
|
cd examples
|
||||||
|
./6pack -v
|
||||||
|
./6pack ../compression-corpus/enwik/enwik8.txt archive.6pk
|
||||||
|
./6unpack -v
|
||||||
|
./6unpack archive.6pk
|
||||||
41
FastLZ/.github/workflows/mips64_linux_gcc.yml
vendored
Normal file
41
FastLZ/.github/workflows/mips64_linux_gcc.yml
vendored
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
name: mips64_linux_gcc
|
||||||
|
|
||||||
|
on: [push, pull_request]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
|
||||||
|
mips64_linux_gcc:
|
||||||
|
runs-on: ubuntu-20.04
|
||||||
|
timeout-minutes: 10
|
||||||
|
env:
|
||||||
|
CC: /opt/mips64-linux-musl-cross/bin/mips64-linux-musl-gcc
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
- name: Retrieve test compression corpus
|
||||||
|
run: |
|
||||||
|
git clone https://github.com/ariya/compression-corpus.git
|
||||||
|
cd compression-corpus
|
||||||
|
cd enwik
|
||||||
|
unzip enwik8.zip
|
||||||
|
- run: sudo apt-get -y -qq update
|
||||||
|
- run: sudo apt install -y qemu-user
|
||||||
|
- name: Prepare cross-compiler
|
||||||
|
run: |
|
||||||
|
curl -O http://musl.cc/mips64-linux-musl-cross.tgz
|
||||||
|
tar xzf mips64-linux-musl-cross.tgz -C /opt
|
||||||
|
- name: Verify compiler version
|
||||||
|
run: /opt/mips64-linux-musl-cross/bin/mips64-linux-musl-gcc --version
|
||||||
|
- name: Perform round-trip tests
|
||||||
|
run: |
|
||||||
|
cd tests
|
||||||
|
make test_roundtrip CFLAGS=-static
|
||||||
|
file ./test_roundtrip
|
||||||
|
qemu-mips64 ./test_roundtrip
|
||||||
|
- name: 'Build and run example: 6pack and 6unpack'
|
||||||
|
run: |
|
||||||
|
cd examples
|
||||||
|
make CFLAGS=-static
|
||||||
|
qemu-mips64 ./6pack -v
|
||||||
|
qemu-mips64 ./6pack ../compression-corpus/enwik/enwik8.txt archive.6pk
|
||||||
|
qemu-mips64 ./6unpack -v
|
||||||
|
qemu-mips64 ./6unpack archive.6pk
|
||||||
41
FastLZ/.github/workflows/mips64el_linux_gcc.yml
vendored
Normal file
41
FastLZ/.github/workflows/mips64el_linux_gcc.yml
vendored
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
name: mips64el_linux_gcc
|
||||||
|
|
||||||
|
on: [push, pull_request]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
|
||||||
|
mips64el_linux_gcc:
|
||||||
|
runs-on: ubuntu-20.04
|
||||||
|
timeout-minutes: 10
|
||||||
|
env:
|
||||||
|
CC: /opt/mips64el-linux-musl-cross/bin/mips64el-linux-musl-gcc
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
- name: Retrieve test compression corpus
|
||||||
|
run: |
|
||||||
|
git clone https://github.com/ariya/compression-corpus.git
|
||||||
|
cd compression-corpus
|
||||||
|
cd enwik
|
||||||
|
unzip enwik8.zip
|
||||||
|
- run: sudo apt-get -y -qq update
|
||||||
|
- run: sudo apt install -y qemu-user
|
||||||
|
- name: Prepare cross-compiler
|
||||||
|
run: |
|
||||||
|
curl -O http://musl.cc/mips64el-linux-musl-cross.tgz
|
||||||
|
tar xzf mips64el-linux-musl-cross.tgz -C /opt
|
||||||
|
- name: Verify compiler version
|
||||||
|
run: /opt/mips64el-linux-musl-cross/bin/mips64el-linux-musl-gcc --version
|
||||||
|
- name: Perform round-trip tests
|
||||||
|
run: |
|
||||||
|
cd tests
|
||||||
|
make test_roundtrip CFLAGS=-static
|
||||||
|
file ./test_roundtrip
|
||||||
|
qemu-mips64el ./test_roundtrip
|
||||||
|
- name: 'Build and run example: 6pack and 6unpack'
|
||||||
|
run: |
|
||||||
|
cd examples
|
||||||
|
make CFLAGS=-static
|
||||||
|
qemu-mips64el ./6pack -v
|
||||||
|
qemu-mips64el ./6pack ../compression-corpus/enwik/enwik8.txt archive.6pk
|
||||||
|
qemu-mips64el ./6unpack -v
|
||||||
|
qemu-mips64el ./6unpack archive.6pk
|
||||||
41
FastLZ/.github/workflows/mips_linux_gcc.yml
vendored
Normal file
41
FastLZ/.github/workflows/mips_linux_gcc.yml
vendored
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
name: mips_linux_gcc
|
||||||
|
|
||||||
|
on: [push, pull_request]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
|
||||||
|
mips_linux_gcc:
|
||||||
|
runs-on: ubuntu-20.04
|
||||||
|
timeout-minutes: 10
|
||||||
|
env:
|
||||||
|
CC: /opt/mips-linux-musl-cross/bin/mips-linux-musl-gcc
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
- name: Retrieve test compression corpus
|
||||||
|
run: |
|
||||||
|
git clone https://github.com/ariya/compression-corpus.git
|
||||||
|
cd compression-corpus
|
||||||
|
cd enwik
|
||||||
|
unzip enwik8.zip
|
||||||
|
- run: sudo apt-get -y -qq update
|
||||||
|
- run: sudo apt install -y qemu-user
|
||||||
|
- name: Prepare cross-compiler
|
||||||
|
run: |
|
||||||
|
curl -O http://musl.cc/mips-linux-musl-cross.tgz
|
||||||
|
tar xzf mips-linux-musl-cross.tgz -C /opt
|
||||||
|
- name: Verify compiler version
|
||||||
|
run: /opt/mips-linux-musl-cross/bin/mips-linux-musl-gcc --version
|
||||||
|
- name: Perform round-trip tests
|
||||||
|
run: |
|
||||||
|
cd tests
|
||||||
|
make test_roundtrip CFLAGS=-static
|
||||||
|
file ./test_roundtrip
|
||||||
|
qemu-mips ./test_roundtrip
|
||||||
|
- name: 'Build and run example: 6pack and 6unpack'
|
||||||
|
run: |
|
||||||
|
cd examples
|
||||||
|
make CFLAGS=-static
|
||||||
|
qemu-mips ./6pack -v
|
||||||
|
qemu-mips ./6pack ../compression-corpus/enwik/enwik8.txt archive.6pk
|
||||||
|
qemu-mips ./6unpack -v
|
||||||
|
qemu-mips ./6unpack archive.6pk
|
||||||
41
FastLZ/.github/workflows/mipsel_linux_gcc.yml
vendored
Normal file
41
FastLZ/.github/workflows/mipsel_linux_gcc.yml
vendored
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
name: mipsel_linux_gcc
|
||||||
|
|
||||||
|
on: [push, pull_request]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
|
||||||
|
mipsel_linux_gcc:
|
||||||
|
runs-on: ubuntu-20.04
|
||||||
|
timeout-minutes: 10
|
||||||
|
env:
|
||||||
|
CC: /opt/mipsel-linux-musl-cross/bin/mipsel-linux-musl-gcc
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
- name: Retrieve test compression corpus
|
||||||
|
run: |
|
||||||
|
git clone https://github.com/ariya/compression-corpus.git
|
||||||
|
cd compression-corpus
|
||||||
|
cd enwik
|
||||||
|
unzip enwik8.zip
|
||||||
|
- run: sudo apt-get -y -qq update
|
||||||
|
- run: sudo apt install -y qemu-user
|
||||||
|
- name: Prepare cross-compiler
|
||||||
|
run: |
|
||||||
|
curl -O http://musl.cc/mipsel-linux-musl-cross.tgz
|
||||||
|
tar xzf mipsel-linux-musl-cross.tgz -C /opt
|
||||||
|
- name: Verify compiler version
|
||||||
|
run: /opt/mipsel-linux-musl-cross/bin/mipsel-linux-musl-gcc --version
|
||||||
|
- name: Perform round-trip tests
|
||||||
|
run: |
|
||||||
|
cd tests
|
||||||
|
make test_roundtrip CFLAGS=-static
|
||||||
|
file ./test_roundtrip
|
||||||
|
qemu-mipsel ./test_roundtrip
|
||||||
|
- name: 'Build and run example: 6pack and 6unpack'
|
||||||
|
run: |
|
||||||
|
cd examples
|
||||||
|
make CFLAGS=-static
|
||||||
|
qemu-mipsel ./6pack -v
|
||||||
|
qemu-mipsel ./6pack ../compression-corpus/enwik/enwik8.txt archive.6pk
|
||||||
|
qemu-mipsel ./6unpack -v
|
||||||
|
qemu-mipsel ./6unpack archive.6pk
|
||||||
41
FastLZ/.github/workflows/powerpc_linux_gcc.yml
vendored
Normal file
41
FastLZ/.github/workflows/powerpc_linux_gcc.yml
vendored
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
name: powerpc_linux_gcc
|
||||||
|
|
||||||
|
on: [push, pull_request]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
|
||||||
|
powerpc_linux_gcc:
|
||||||
|
runs-on: ubuntu-20.04
|
||||||
|
timeout-minutes: 10
|
||||||
|
env:
|
||||||
|
CC: /opt/powerpc-linux-musl-cross/bin/powerpc-linux-musl-gcc
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
- name: Retrieve test compression corpus
|
||||||
|
run: |
|
||||||
|
git clone https://github.com/ariya/compression-corpus.git
|
||||||
|
cd compression-corpus
|
||||||
|
cd enwik
|
||||||
|
unzip enwik8.zip
|
||||||
|
- run: sudo apt-get -y -qq update
|
||||||
|
- run: sudo apt install -y qemu-user
|
||||||
|
- name: Prepare cross-compiler
|
||||||
|
run: |
|
||||||
|
curl -O http://musl.cc/powerpc-linux-musl-cross.tgz
|
||||||
|
tar xzf powerpc-linux-musl-cross.tgz -C /opt
|
||||||
|
- name: Verify compiler version
|
||||||
|
run: /opt/powerpc-linux-musl-cross/bin/powerpc-linux-musl-gcc --version
|
||||||
|
- name: Perform round-trip tests
|
||||||
|
run: |
|
||||||
|
cd tests
|
||||||
|
make test_roundtrip CFLAGS=-static
|
||||||
|
file ./test_roundtrip
|
||||||
|
qemu-ppc ./test_roundtrip
|
||||||
|
- name: 'Build and run example: 6pack and 6unpack'
|
||||||
|
run: |
|
||||||
|
cd examples
|
||||||
|
make CFLAGS=-static
|
||||||
|
qemu-ppc ./6pack -v
|
||||||
|
qemu-ppc ./6pack ../compression-corpus/enwik/enwik8.txt archive.6pk
|
||||||
|
qemu-ppc ./6unpack -v
|
||||||
|
qemu-ppc ./6unpack archive.6pk
|
||||||
41
FastLZ/.github/workflows/ppc64_linux_gcc.yml
vendored
Normal file
41
FastLZ/.github/workflows/ppc64_linux_gcc.yml
vendored
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
name: ppc64_linux_gcc
|
||||||
|
|
||||||
|
on: [push, pull_request]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
|
||||||
|
ppc64_linux_gcc:
|
||||||
|
runs-on: ubuntu-20.04
|
||||||
|
timeout-minutes: 10
|
||||||
|
env:
|
||||||
|
CC: /opt/powerpc64-linux-musl-cross/bin/powerpc64-linux-musl-gcc
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
- name: Retrieve test compression corpus
|
||||||
|
run: |
|
||||||
|
git clone https://github.com/ariya/compression-corpus.git
|
||||||
|
cd compression-corpus
|
||||||
|
cd enwik
|
||||||
|
unzip enwik8.zip
|
||||||
|
- run: sudo apt-get -y -qq update
|
||||||
|
- run: sudo apt install -y qemu-user
|
||||||
|
- name: Prepare cross-compiler
|
||||||
|
run: |
|
||||||
|
curl -O http://musl.cc/powerpc64-linux-musl-cross.tgz
|
||||||
|
tar xzf powerpc64-linux-musl-cross.tgz -C /opt
|
||||||
|
- name: Verify compiler version
|
||||||
|
run: /opt/powerpc64-linux-musl-cross/bin/powerpc64-linux-musl-gcc --version
|
||||||
|
- name: Perform round-trip tests
|
||||||
|
run: |
|
||||||
|
cd tests
|
||||||
|
make test_roundtrip CFLAGS=-static
|
||||||
|
file ./test_roundtrip
|
||||||
|
qemu-ppc64 ./test_roundtrip
|
||||||
|
- name: 'Build and run example: 6pack and 6unpack'
|
||||||
|
run: |
|
||||||
|
cd examples
|
||||||
|
make CFLAGS=-static
|
||||||
|
qemu-ppc64 ./6pack -v
|
||||||
|
qemu-ppc64 ./6pack ../compression-corpus/enwik/enwik8.txt archive.6pk
|
||||||
|
qemu-ppc64 ./6unpack -v
|
||||||
|
qemu-ppc64 ./6unpack archive.6pk
|
||||||
41
FastLZ/.github/workflows/ppc64le_linux_gcc.yml
vendored
Normal file
41
FastLZ/.github/workflows/ppc64le_linux_gcc.yml
vendored
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
name: ppc64le_linux_gcc
|
||||||
|
|
||||||
|
on: [push, pull_request]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
|
||||||
|
ppc64le_linux_gcc:
|
||||||
|
runs-on: ubuntu-20.04
|
||||||
|
timeout-minutes: 10
|
||||||
|
env:
|
||||||
|
CC: /opt/powerpc64le-linux-musl-cross/bin/powerpc64le-linux-musl-gcc
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
- name: Retrieve test compression corpus
|
||||||
|
run: |
|
||||||
|
git clone https://github.com/ariya/compression-corpus.git
|
||||||
|
cd compression-corpus
|
||||||
|
cd enwik
|
||||||
|
unzip enwik8.zip
|
||||||
|
- run: sudo apt-get -y -qq update
|
||||||
|
- run: sudo apt install -y qemu-user
|
||||||
|
- name: Prepare cross-compiler
|
||||||
|
run: |
|
||||||
|
curl -O http://musl.cc/powerpc64le-linux-musl-cross.tgz
|
||||||
|
tar xzf powerpc64le-linux-musl-cross.tgz -C /opt
|
||||||
|
- name: Verify compiler version
|
||||||
|
run: /opt/powerpc64le-linux-musl-cross/bin/powerpc64le-linux-musl-gcc --version
|
||||||
|
- name: Perform round-trip tests
|
||||||
|
run: |
|
||||||
|
cd tests
|
||||||
|
make test_roundtrip CFLAGS=-static
|
||||||
|
file ./test_roundtrip
|
||||||
|
qemu-ppc64le ./test_roundtrip
|
||||||
|
- name: 'Build and run example: 6pack and 6unpack'
|
||||||
|
run: |
|
||||||
|
cd examples
|
||||||
|
make CFLAGS=-static
|
||||||
|
qemu-ppc64le ./6pack -v
|
||||||
|
qemu-ppc64le ./6pack ../compression-corpus/enwik/enwik8.txt archive.6pk
|
||||||
|
qemu-ppc64le ./6unpack -v
|
||||||
|
qemu-ppc64le ./6unpack archive.6pk
|
||||||
41
FastLZ/.github/workflows/riscv64_linux_gcc.yml
vendored
Normal file
41
FastLZ/.github/workflows/riscv64_linux_gcc.yml
vendored
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
name: riscv64_linux_gcc
|
||||||
|
|
||||||
|
on: [push, pull_request]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
|
||||||
|
riscv64_linux_gcc:
|
||||||
|
runs-on: ubuntu-20.04
|
||||||
|
timeout-minutes: 10
|
||||||
|
env:
|
||||||
|
CC: /opt/riscv64-linux-musl-cross/bin/riscv64-linux-musl-gcc
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
- name: Retrieve test compression corpus
|
||||||
|
run: |
|
||||||
|
git clone https://github.com/ariya/compression-corpus.git
|
||||||
|
cd compression-corpus
|
||||||
|
cd enwik
|
||||||
|
unzip enwik8.zip
|
||||||
|
- run: sudo apt-get -y -qq update
|
||||||
|
- run: sudo apt install -y qemu-user
|
||||||
|
- name: Prepare cross-compiler
|
||||||
|
run: |
|
||||||
|
curl -O http://musl.cc/riscv64-linux-musl-cross.tgz
|
||||||
|
tar xzf riscv64-linux-musl-cross.tgz -C /opt
|
||||||
|
- name: Verify compiler version
|
||||||
|
run: /opt/riscv64-linux-musl-cross/bin/riscv64-linux-musl-gcc --version
|
||||||
|
- name: Perform round-trip tests
|
||||||
|
run: |
|
||||||
|
cd tests
|
||||||
|
make test_roundtrip CFLAGS=-static
|
||||||
|
file ./test_roundtrip
|
||||||
|
qemu-riscv64 ./test_roundtrip
|
||||||
|
- name: 'Build and run example: 6pack and 6unpack'
|
||||||
|
run: |
|
||||||
|
cd examples
|
||||||
|
make CFLAGS=-static
|
||||||
|
qemu-riscv64 ./6pack -v
|
||||||
|
qemu-riscv64 ./6pack ../compression-corpus/enwik/enwik8.txt archive.6pk
|
||||||
|
qemu-riscv64 ./6unpack -v
|
||||||
|
qemu-riscv64 ./6unpack archive.6pk
|
||||||
41
FastLZ/.github/workflows/riscv_linux_gcc.yml
vendored
Normal file
41
FastLZ/.github/workflows/riscv_linux_gcc.yml
vendored
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
name: riscv_linux_gcc
|
||||||
|
|
||||||
|
on: [push, pull_request]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
|
||||||
|
riscv_linux_gcc:
|
||||||
|
runs-on: ubuntu-20.04
|
||||||
|
timeout-minutes: 10
|
||||||
|
env:
|
||||||
|
CC: /opt/riscv32-linux-musl-cross/bin/riscv32-linux-musl-gcc
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
- name: Retrieve test compression corpus
|
||||||
|
run: |
|
||||||
|
git clone https://github.com/ariya/compression-corpus.git
|
||||||
|
cd compression-corpus
|
||||||
|
cd enwik
|
||||||
|
unzip enwik8.zip
|
||||||
|
- run: sudo apt-get -y -qq update
|
||||||
|
- run: sudo apt install -y qemu-user
|
||||||
|
- name: Prepare cross-compiler
|
||||||
|
run: |
|
||||||
|
curl -O http://musl.cc/riscv32-linux-musl-cross.tgz
|
||||||
|
tar xzf riscv32-linux-musl-cross.tgz -C /opt
|
||||||
|
- name: Verify compiler version
|
||||||
|
run: /opt/riscv32-linux-musl-cross/bin/riscv32-linux-musl-gcc --version
|
||||||
|
- name: Perform round-trip tests
|
||||||
|
run: |
|
||||||
|
cd tests
|
||||||
|
make test_roundtrip CFLAGS=-static
|
||||||
|
file ./test_roundtrip
|
||||||
|
qemu-riscv32 ./test_roundtrip
|
||||||
|
- name: 'Build and run example: 6pack and 6unpack'
|
||||||
|
run: |
|
||||||
|
cd examples
|
||||||
|
make CFLAGS=-static
|
||||||
|
qemu-riscv32 ./6pack -v
|
||||||
|
qemu-riscv32 ./6pack ../compression-corpus/enwik/enwik8.txt archive.6pk
|
||||||
|
qemu-riscv32 ./6unpack -v
|
||||||
|
qemu-riscv32 ./6unpack archive.6pk
|
||||||
41
FastLZ/.github/workflows/s390x_linux_gcc.yml
vendored
Normal file
41
FastLZ/.github/workflows/s390x_linux_gcc.yml
vendored
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
name: s390x_linux_gcc
|
||||||
|
|
||||||
|
on: [push, pull_request]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
|
||||||
|
s390x_linux_gcc:
|
||||||
|
runs-on: ubuntu-20.04
|
||||||
|
timeout-minutes: 10
|
||||||
|
env:
|
||||||
|
CC: /opt/s390x-linux-musl-cross/bin/s390x-linux-musl-gcc
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
- name: Retrieve test compression corpus
|
||||||
|
run: |
|
||||||
|
git clone https://github.com/ariya/compression-corpus.git
|
||||||
|
cd compression-corpus
|
||||||
|
cd enwik
|
||||||
|
unzip enwik8.zip
|
||||||
|
- run: sudo apt-get -y -qq update
|
||||||
|
- run: sudo apt install -y qemu-user
|
||||||
|
- name: Prepare cross-compiler
|
||||||
|
run: |
|
||||||
|
curl -O http://musl.cc/s390x-linux-musl-cross.tgz
|
||||||
|
tar xzf s390x-linux-musl-cross.tgz -C /opt
|
||||||
|
- name: Verify compiler version
|
||||||
|
run: /opt/s390x-linux-musl-cross/bin/s390x-linux-musl-gcc --version
|
||||||
|
- name: Perform round-trip tests
|
||||||
|
run: |
|
||||||
|
cd tests
|
||||||
|
make test_roundtrip CFLAGS=-static
|
||||||
|
file ./test_roundtrip
|
||||||
|
qemu-s390x ./test_roundtrip
|
||||||
|
- name: 'Build and run example: 6pack and 6unpack'
|
||||||
|
run: |
|
||||||
|
cd examples
|
||||||
|
make CFLAGS=-static
|
||||||
|
qemu-s390x ./6pack -v
|
||||||
|
qemu-s390x ./6pack ../compression-corpus/enwik/enwik8.txt archive.6pk
|
||||||
|
qemu-s390x ./6unpack -v
|
||||||
|
qemu-s390x ./6unpack archive.6pk
|
||||||
1
FastLZ/.gitignore
vendored
Normal file
1
FastLZ/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
*.o
|
||||||
3
FastLZ/.gitmodules
vendored
Normal file
3
FastLZ/.gitmodules
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
[submodule "compression-corpus"]
|
||||||
|
path = compression-corpus
|
||||||
|
url = https://github.com/ariya/compression-corpus.git
|
||||||
8
FastLZ/ChangeLog
Normal file
8
FastLZ/ChangeLog
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
2020-02-02: Version 0.5.0
|
||||||
|
|
||||||
|
Minor speed improvement on the decompressor.
|
||||||
|
Prevent memory violation when decompressing corrupted input.
|
||||||
|
|
||||||
|
2020-01-10: Version 0.4.0
|
||||||
|
|
||||||
|
Only code & infrastructure clean-up, no new functionality.
|
||||||
21
FastLZ/LICENSE.MIT
Normal file
21
FastLZ/LICENSE.MIT
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
FastLZ - Byte-aligned LZ77 compression library
|
||||||
|
Copyright (C) 2005-2020 Ariya Hidayat <ariya.hidayat@gmail.com>
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
207
FastLZ/README.md
Normal file
207
FastLZ/README.md
Normal file
@ -0,0 +1,207 @@
|
|||||||
|
[](https://opensource.org/licenses/MIT)
|
||||||
|
[](https://github.com/ariya/fastlz/actions)
|
||||||
|
[](https://github.com/ariya/fastlz/actions)
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
FastLZ (MIT license) is an ANSI C/C90 implementation of [Lempel-Ziv 77 algorithm](https://en.wikipedia.org/wiki/LZ77_and_LZ78#LZ77) (LZ77) of lossless data compression. It is suitable to compress series of text/paragraphs, sequences of raw pixel data, or any other blocks of data with lots of repetition. It is not intended to be used on images, videos, and other formats of data typically already in an optimal compressed form.
|
||||||
|
|
||||||
|
The focus for FastLZ is a very fast compression and decompression, doing that at the cost of the compression ratio. As an illustration, the comparison with zlib when compressing [enwik8](http://www.mattmahoney.net/dc/textdata.html) (also in [more details](https://github.com/inikep/lzbench)):
|
||||||
|
|
||||||
|
||Ratio|Compression|Decompression
|
||||||
|
|--|--|--|--|
|
||||||
|
|FastLZ |54.2%|159 MB/s|305 MB/s|
|
||||||
|
|zlib -1|42.3%|50 MB/s|184 MB/s|
|
||||||
|
|zlib -9|36.5%|11 MB/s|185 MB/s|
|
||||||
|
|
||||||
|
FastLZ is used by many software products, from a number of games (such as [Death Stranding](https://en.wikipedia.org/wiki/Death_Stranding)) to various open-source projects ([Godot Engine](https://godotengine.org/), [Facebook HHVM](https://hhvm.com/), [Apache Traffic Server](https://trafficserver.apache.org/), [Calligra Office](https://www.calligra.org/), [OSv](http://osv.io/), [Netty](https://netty.io/), etc). It even serves as the basis for other compression projects like [BLOSC](https://blosc.org/).
|
||||||
|
|
||||||
|
For other implementations of byte-aligned LZ77, take a look at [LZ4](https://lz4.github.io/lz4/), [Snappy](http://google.github.io/snappy/), [Density](https://github.com/centaurean/density), [LZO](http://www.oberhumer.com/opensource/lzo/), [LZF](http://oldhome.schmorp.de/marc/liblzf.html), [LZJB](https://en.wikipedia.org/wiki/LZJB), [LZRW](http://www.ross.net/compression/lzrw1.html), etc.
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
FastLZ can be used directly in any C/C++ applications. For other programming languages/environments, use the corresponding binding:
|
||||||
|
|
||||||
|
* [Rust](https://crates.io/crates/fastlz), available on Crates: `cargo install fastlz`
|
||||||
|
* [Python](https://pypi.org/project/fastlz/), available on PyPi: `pip install fastlz`
|
||||||
|
* [JavaScript](https://www.npmjs.com/package/fastlz), available on npm: `npm install fastlz`
|
||||||
|
* [Ruby](https://rubygems.org/gems/fastlz), available on Rubygems: `gem install fastlz`
|
||||||
|
* Lua via [github.com/oneoo/lua-fastlz](https://github.com/oneoo/lua-fastlz)
|
||||||
|
|
||||||
|
FastLZ consists of only two files: `fastlz.h` and `fastlz.c`. Just add these files to your project in order to use FastLZ. For the detailed information on the API to perform compression and decompression, see `fastlz.h`.
|
||||||
|
|
||||||
|
For [Vcpkg](https://github.com/microsoft/vcpkg) users, FastLZ is [already available](https://github.com/microsoft/vcpkg): `vcpkg install fastlz`.
|
||||||
|
|
||||||
|
A simple file compressor called `6pack` is included as an example on how to use FastLZ. The corresponding decompressor is `6unpack`.
|
||||||
|
|
||||||
|
FastLZ supports any standard-conforming ANSI C/C90 compiler, including the popular ones such as [GCC](https://gcc.gnu.org/), [Clang](https://clang.llvm.org/), [Visual Studio](https://visualstudio.microsoft.com/vs/features/cplusplus/), and even [Tiny CC](https://bellard.org/tcc/). FastLZ works well on a number of architectures (32-bit and 64-bit, big endian and little endian), from Intel/AMD, PowerPC, System z, ARM, MIPS, and RISC-V.
|
||||||
|
|
||||||
|
The continuous integration system runs an extensive set of compression-decompression round trips on the following systems:
|
||||||
|
|
||||||
|
|
||||||
|
For more details, check the corresponding [GitHub Actions build logs](https://github.com/ariya/FastLZ/actions).
|
||||||
|
|
||||||
|
| | | | |
|
||||||
|
|----------------------|--------------------------------------------------------------------------------------------------------:|--------------------------------------------------------------------------------------------------:|--------------------------------------------------------------------------------------------:|
|
||||||
|
| **amd64** | **Linux** | **Windows** | **macOS** |
|
||||||
|
| GCC |  |  |  |
|
||||||
|
| Clang |  |  |  |
|
||||||
|
| TinyCC |  |  | |
|
||||||
|
| VS 2019 | |  | |
|
||||||
|
| **i686** | **Linux** | **Windows** | **macOS** |
|
||||||
|
| GCC |  | | |
|
||||||
|
| Clang |  | | |
|
||||||
|
| TinyCC | |  | |
|
||||||
|
| VS 2019 | |  | |
|
||||||
|
| **i586** | **Linux** | **DOS** | |
|
||||||
|
| GCC | |  | |
|
||||||
|
| | **Linux** | | |
|
||||||
|
| **powerpc** | | | |
|
||||||
|
| GCC |  | | |
|
||||||
|
| **ppc64(le)** | | | |
|
||||||
|
| GCC |  | | |
|
||||||
|
| GCC |  | | |
|
||||||
|
| **s390x** | | | |
|
||||||
|
| GCC |  | | |
|
||||||
|
| **armhf** | | | |
|
||||||
|
| GCC |  | | |
|
||||||
|
| **arm64** | | | |
|
||||||
|
| GCC |  | | |
|
||||||
|
| **mips(el)** | | | |
|
||||||
|
| GCC |  | | |
|
||||||
|
| GCC |  | | |
|
||||||
|
| **mips64(el)** | | | |
|
||||||
|
| GCC |  | | |
|
||||||
|
| GCC |  | | |
|
||||||
|
| **riscv** | | | |
|
||||||
|
| GCC |  | | |
|
||||||
|
| **riscv64** | | | |
|
||||||
|
| GCC |  | | |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## Block Format
|
||||||
|
|
||||||
|
Let us assume that FastLZ compresses an array of bytes, called the _uncompressed block_, into another array of bytes, called the _compressed block_. To understand what will be stored in the compressed block, it is illustrative to demonstrate how FastLZ will _decompress_ the block to retrieve the original uncompressed block.
|
||||||
|
|
||||||
|
The first 3-bit of the block, i.e. the 3 most-significant bits of the first byte, is the **block tag**. Currently the block tag determines the compression level used to produce the compressed block.
|
||||||
|
|
||||||
|
|Block tag|Compression level|
|
||||||
|
|---------|-----------------|
|
||||||
|
| 0 | Level 1 |
|
||||||
|
| 1 | Level 2 |
|
||||||
|
|
||||||
|
The content of the block will vary depending on the compression level.
|
||||||
|
|
||||||
|
### Block Format for Level 1
|
||||||
|
|
||||||
|
FastLZ Level 1 implements LZ77 compression algorithm with 8 KB sliding window and up to 264 bytes of match length.
|
||||||
|
|
||||||
|
The compressed block consists of one or more **instructions**.
|
||||||
|
Each instruction starts with a 1-byte opcode, 2-byte opcode, or 3-byte opcode.
|
||||||
|
|
||||||
|
| Instruction type | Opcode[0] | Opcode[1] | Opcode[2]
|
||||||
|
|-----------|------------------|--------------------|--|
|
||||||
|
| Literal run | `000`, L₄-L₀ | -|- |
|
||||||
|
| Short match | M₂-M₀, R₁₂-R₈ | R₇-R₀ | - |
|
||||||
|
| Long match | `111`, R₁₂-R₈ | M₇-M₀ | R₇-R₀ |
|
||||||
|
|
||||||
|
Note that the _very first_ instruction in a compressed block is always a literal run.
|
||||||
|
|
||||||
|
#### Literal run instruction
|
||||||
|
|
||||||
|
For the literal run instruction, there is one or more bytes following the code. This is called the literal run.
|
||||||
|
|
||||||
|
The 5 least-significant bits of `opcode[0]`, _L_, determines the **number of literals** following the opcode. The value of 0 indicates a 1-byte literal run, 1 indicates a 2-byte literal run, and so on. The minimum literal run is 1 and the maximum literal run is 32.
|
||||||
|
|
||||||
|
The decompressor copies (_L + 1_) bytes of literal run, starting from the first one right after opcode.
|
||||||
|
|
||||||
|
_Example_: If the compressed block is a 4-byte array of `[0x02, 0x41, 0x42, 0x43]`, then the opcode is `0x02` and that means a literal run of 3 bytes. The decompressor will then copy the subsequent 3 bytes, `[0x41, 0x42, 0x43]`, to the output buffer. The output buffer now represents the (original) uncompressed block, `[0x41, 0x42, 0x43]`.
|
||||||
|
|
||||||
|
#### Short match instruction
|
||||||
|
|
||||||
|
The 3 most-significant bits of `opcode[0]`, _M_, determines the **match length**. The value of 1 indicates a 3-byte match, 2 indicates a 4-byte match and so on. The minimum match length is 3 and the maximum match length is 8.
|
||||||
|
|
||||||
|
The 5 least-significant bits of `opcode[0]` combined with the 8 bits of the `opcode[1]`, _R_, determines the **reference offset**. Since the offset is encoded in 13 bits, the minimum is 0 and the maximum is 8191.
|
||||||
|
|
||||||
|
The following C code retrieves the match length and reference offset:
|
||||||
|
|
||||||
|
```c
|
||||||
|
M = opcode[0] >> 5;
|
||||||
|
R = 256 * (opcode[0] << 5) + opcode[1];
|
||||||
|
```
|
||||||
|
|
||||||
|
The decompressor copies _(M+2)_ bytes, starting from the location offsetted by _R_ in the output buffer. Note that _R_ is a *back reference*, i.e. the value of 0 corresponds the last byte in the output buffer, 1 is the second to last byte, and so forth.
|
||||||
|
|
||||||
|
_Example 1_: If the compressed block is a 7-byte array of `[0x03, 0x41, 0x42, 0x43, 0x44, 0x20, 0x02]`, then there are two instructions in the there. The first instruction is the literal run of 4 bytes (due to _L = 3_). Thus, the decompressor copies 4 bytes to the output buffer, resulting in `[0x41, 0x42, 0x43, 0x44]`. The second instruction is the short match of 3 bytes (from _M = 1_, i.e `0x20 >> 5`) and the offset of 2. Therefore, the compressor goes back 2 bytes from the last position, copies 3 bytes (`[0x42, 0x43, 0x44]`), and appends them to the output buffer. The output buffer now represents the complete uncompressed data, `[0x41, 0x42, 0x43, 0x44, 0x42, 0x43, 0x44]`.
|
||||||
|
|
||||||
|
_Example 2_: If the compressed block is a 4-byte array of `[0x00, 0x61, 0x40, 0x00]`, then there are two instructions in there. The first instruction is the literal run of just 1 byte (_L = 0_). Thus, the decompressor copies the byte (`0x61`) to the output buffer. The output buffer now becomes `[0x61]`. The second instruction is the short match of 4 bytes (from _M = 2_, i.e. `0x40 >> 5`) and the offset of 0. Therefore, the decompressor copies 4 bytes starting using the back reference of 0 (i.e. the position of `0x61`). The output buffer now represents the complete uncompressed data, `[0x61, 0x61, 0x61, 0x61, 0x61]`.
|
||||||
|
|
||||||
|
#### Long match instruction
|
||||||
|
|
||||||
|
The value of `opcode[1]`, _M_, determines the **match length**. The value of 0 indicates a 9-byte match, 1 indicates a 10-byte match and so on. The minimum match length is 9 and the maximum match length is 264.
|
||||||
|
|
||||||
|
The 5 least-significant bits of `opcode[0]` combined with the 8 bits of `opcode[2]`, _R_, determines the **reference offset**. Since the offset is encoded in 13 bits, the minimum is 0 and the maximum is 8191.
|
||||||
|
|
||||||
|
The following C code retrieves the match length and reference offset:
|
||||||
|
|
||||||
|
```c
|
||||||
|
M = opcode[1];
|
||||||
|
R = 256 * (opcode[0] << 5) + opcode[2];
|
||||||
|
```
|
||||||
|
The decompressor copies _(M+9)_ bytes, starting from the location offsetted by _R_ in the output buffer. Note that _R_ is a *back reference*, i.e. the value of 0 corresponds to the last byte in the output buffer, 1 is for the second to last byte, and so forth.
|
||||||
|
|
||||||
|
_Example_: If the compressed block is a 4-byte array of `[0x01, 0x44, 0x45, 0xE0, 0x01, 0x01]`, then there are two instructions in there. The first instruction is the literal run with the length of 2 (due to _L = 1_). Thus, the decompressor copies the 2-byte literal run (`[0x44, 0x45]`) to the output buffer. The second instruction is the long match with the match length of 10 (from _M = 1_) and the offset of 1. Therefore, the decompressor copies 10 bytes starting using the back reference of 1 (i.e. the position of `0x44`). The output buffer now represents the complete uncompressed data, `[0x44, 0x45, 0x44, 0x45, 0x44, 0x45, 0x44, 0x45, 0x44, 0x45, 0x44, 0x45]`.
|
||||||
|
|
||||||
|
#### Decompressor Reference Implementation
|
||||||
|
|
||||||
|
The following 40-line C function implements a fully-functional decompressor for the above block format. Note that it is intended to be educational, e.g. no bound check is implemented, and therefore it is absolutely **unsafe** for production.
|
||||||
|
|
||||||
|
```c
|
||||||
|
void fastlz_level1_decompress(const uint8_t* input, int length, uint8_t* output) {
|
||||||
|
int src = 0;
|
||||||
|
int dest = 0;
|
||||||
|
while (src < length) {
|
||||||
|
int type = input[src] >> 5;
|
||||||
|
if (type == 0) {
|
||||||
|
/* literal run */
|
||||||
|
int run = 1 + input[src];
|
||||||
|
src = src + 1;
|
||||||
|
while (run > 0) {
|
||||||
|
output[dest] = input[src];
|
||||||
|
src = src + 1;
|
||||||
|
dest = dest + 1;
|
||||||
|
run = run - 1;
|
||||||
|
}
|
||||||
|
} else if (type < 7) {
|
||||||
|
/* short match */
|
||||||
|
int ofs = 256 * (input[src] & 31) + input[src + 1];
|
||||||
|
int len = 2 + (input[src] >> 5);
|
||||||
|
src = src + 2;
|
||||||
|
int ref = dest - ofs - 1;
|
||||||
|
while (len > 0) {
|
||||||
|
output[dest] = output[ref];
|
||||||
|
ref = ref + 1;
|
||||||
|
dest = dest + 1;
|
||||||
|
len = len - 1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* long match */
|
||||||
|
int ofs = 256 * (input[src] & 31) + input[src + 2];
|
||||||
|
int len = 9 + input[src + 1];
|
||||||
|
src = src + 3;
|
||||||
|
int ref = dest - ofs - 1;
|
||||||
|
while (len > 0) {
|
||||||
|
output[dest] = output[ref];
|
||||||
|
ref = ref + 1;
|
||||||
|
dest = dest + 1;
|
||||||
|
len = len - 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Block Format for Level 2
|
||||||
|
|
||||||
|
(To be written)
|
||||||
1
FastLZ/_config.yml
Normal file
1
FastLZ/_config.yml
Normal file
@ -0,0 +1 @@
|
|||||||
|
theme: jekyll-theme-tactile
|
||||||
2
FastLZ/examples/.gitignore
vendored
Normal file
2
FastLZ/examples/.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
6pack
|
||||||
|
6unpack
|
||||||
586
FastLZ/examples/6pack.c
Normal file
586
FastLZ/examples/6pack.c
Normal file
@ -0,0 +1,586 @@
|
|||||||
|
/*
|
||||||
|
6PACK - file compressor using FastLZ (lightning-fast compression library)
|
||||||
|
Copyright (C) 2007-2020 Ariya Hidayat <ariya.hidayat@gmail.com>
|
||||||
|
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#define SIXPACK_VERSION_MAJOR 0
|
||||||
|
#define SIXPACK_VERSION_MINOR 1
|
||||||
|
#define SIXPACK_VERSION_REVISION 0
|
||||||
|
#define SIXPACK_VERSION_STRING "snapshot 20070615"
|
||||||
|
|
||||||
|
#include "fastlz.h"
|
||||||
|
|
||||||
|
#undef PATH_SEPARATOR
|
||||||
|
|
||||||
|
#if defined(MSDOS) || defined(__MSDOS__) || defined(MSDOS)
|
||||||
|
#define PATH_SEPARATOR '\\'
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(WIN32) || defined(__NT__) || defined(_WIN32) || defined(__WIN32__)
|
||||||
|
#define PATH_SEPARATOR '\\'
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef PATH_SEPARATOR
|
||||||
|
#define PATH_SEPARATOR '/'
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#undef SIXPACK_BENCHMARK_WIN32
|
||||||
|
#if defined(WIN32) || defined(__NT__) || defined(_WIN32) || defined(__WIN32__)
|
||||||
|
#if defined(_MSC_VER) || defined(__GNUC__)
|
||||||
|
#define SIXPACK_BENCHMARK_WIN32
|
||||||
|
#include <windows.h>
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* magic identifier for 6pack file */
|
||||||
|
static unsigned char sixpack_magic[8] = {137, '6', 'P', 'K', 13, 10, 26, 10};
|
||||||
|
|
||||||
|
#define BLOCK_SIZE (2 * 64 * 1024)
|
||||||
|
|
||||||
|
/* prototypes */
|
||||||
|
static unsigned long update_adler32(unsigned long checksum, const void* buf, int len);
|
||||||
|
void usage(void);
|
||||||
|
int detect_magic(FILE* f);
|
||||||
|
void write_magic(FILE* f);
|
||||||
|
void write_chunk_header(FILE* f, int id, int options, unsigned long size, unsigned long checksum, unsigned long extra);
|
||||||
|
unsigned long block_compress(const unsigned char* input, unsigned long length, unsigned char* output);
|
||||||
|
int pack_file_compressed(const char* input_file, int method, int level, FILE* f);
|
||||||
|
int pack_file(int compress_level, const char* input_file, const char* output_file);
|
||||||
|
|
||||||
|
/* for Adler-32 checksum algorithm, see RFC 1950 Section 8.2 */
|
||||||
|
#define ADLER32_BASE 65521
|
||||||
|
static unsigned long update_adler32(unsigned long checksum, const void* buf, int len) {
|
||||||
|
const unsigned char* ptr = (const unsigned char*)buf;
|
||||||
|
unsigned long s1 = checksum & 0xffff;
|
||||||
|
unsigned long s2 = (checksum >> 16) & 0xffff;
|
||||||
|
|
||||||
|
while (len > 0) {
|
||||||
|
unsigned k = len < 5552 ? len : 5552;
|
||||||
|
len -= k;
|
||||||
|
|
||||||
|
while (k >= 8) {
|
||||||
|
s1 += *ptr++;
|
||||||
|
s2 += s1;
|
||||||
|
s1 += *ptr++;
|
||||||
|
s2 += s1;
|
||||||
|
s1 += *ptr++;
|
||||||
|
s2 += s1;
|
||||||
|
s1 += *ptr++;
|
||||||
|
s2 += s1;
|
||||||
|
s1 += *ptr++;
|
||||||
|
s2 += s1;
|
||||||
|
s1 += *ptr++;
|
||||||
|
s2 += s1;
|
||||||
|
s1 += *ptr++;
|
||||||
|
s2 += s1;
|
||||||
|
s1 += *ptr++;
|
||||||
|
s2 += s1;
|
||||||
|
k -= 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (k-- > 0) {
|
||||||
|
s1 += *ptr++;
|
||||||
|
s2 += s1;
|
||||||
|
}
|
||||||
|
s1 = s1 % ADLER32_BASE;
|
||||||
|
s2 = s2 % ADLER32_BASE;
|
||||||
|
}
|
||||||
|
return (s2 << 16) + s1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void usage(void) {
|
||||||
|
printf("6pack: high-speed file compression tool\n");
|
||||||
|
printf("Copyright (C) Ariya Hidayat\n");
|
||||||
|
printf("\n");
|
||||||
|
printf("Usage: 6pack [options] input-file output-file\n");
|
||||||
|
printf("\n");
|
||||||
|
printf("Options:\n");
|
||||||
|
printf(" -1 compress faster\n");
|
||||||
|
printf(" -2 compress better\n");
|
||||||
|
printf(" -v show program version\n");
|
||||||
|
#ifdef SIXPACK_BENCHMARK_WIN32
|
||||||
|
printf(" -mem check in-memory compression speed\n");
|
||||||
|
#endif
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* return non-zero if magic sequence is detected */
|
||||||
|
/* warning: reset the read pointer to the beginning of the file */
|
||||||
|
int detect_magic(FILE* f) {
|
||||||
|
unsigned char buffer[8];
|
||||||
|
size_t bytes_read;
|
||||||
|
int c;
|
||||||
|
|
||||||
|
fseek(f, SEEK_SET, 0);
|
||||||
|
bytes_read = fread(buffer, 1, 8, f);
|
||||||
|
fseek(f, SEEK_SET, 0);
|
||||||
|
if (bytes_read < 8) return 0;
|
||||||
|
|
||||||
|
for (c = 0; c < 8; c++)
|
||||||
|
if (buffer[c] != sixpack_magic[c]) return 0;
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void write_magic(FILE* f) { fwrite(sixpack_magic, 8, 1, f); }
|
||||||
|
|
||||||
|
void write_chunk_header(FILE* f, int id, int options, unsigned long size, unsigned long checksum, unsigned long extra) {
|
||||||
|
unsigned char buffer[16];
|
||||||
|
|
||||||
|
buffer[0] = id & 255;
|
||||||
|
buffer[1] = id >> 8;
|
||||||
|
buffer[2] = options & 255;
|
||||||
|
buffer[3] = options >> 8;
|
||||||
|
buffer[4] = size & 255;
|
||||||
|
buffer[5] = (size >> 8) & 255;
|
||||||
|
buffer[6] = (size >> 16) & 255;
|
||||||
|
buffer[7] = (size >> 24) & 255;
|
||||||
|
buffer[8] = checksum & 255;
|
||||||
|
buffer[9] = (checksum >> 8) & 255;
|
||||||
|
buffer[10] = (checksum >> 16) & 255;
|
||||||
|
buffer[11] = (checksum >> 24) & 255;
|
||||||
|
buffer[12] = extra & 255;
|
||||||
|
buffer[13] = (extra >> 8) & 255;
|
||||||
|
buffer[14] = (extra >> 16) & 255;
|
||||||
|
buffer[15] = (extra >> 24) & 255;
|
||||||
|
|
||||||
|
fwrite(buffer, 16, 1, f);
|
||||||
|
}
|
||||||
|
|
||||||
|
int pack_file_compressed(const char* input_file, int method, int level, FILE* f) {
|
||||||
|
FILE* in;
|
||||||
|
unsigned long fsize;
|
||||||
|
unsigned long checksum;
|
||||||
|
const char* shown_name;
|
||||||
|
unsigned char buffer[BLOCK_SIZE];
|
||||||
|
unsigned char result[BLOCK_SIZE * 2]; /* FIXME twice is too large */
|
||||||
|
unsigned char progress[20];
|
||||||
|
int c;
|
||||||
|
unsigned long percent;
|
||||||
|
unsigned long total_read;
|
||||||
|
unsigned long total_compressed;
|
||||||
|
int chunk_size;
|
||||||
|
|
||||||
|
/* sanity check */
|
||||||
|
in = fopen(input_file, "rb");
|
||||||
|
if (!in) {
|
||||||
|
printf("Error: could not open %s\n", input_file);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* find size of the file */
|
||||||
|
fseek(in, 0, SEEK_END);
|
||||||
|
fsize = ftell(in);
|
||||||
|
fseek(in, 0, SEEK_SET);
|
||||||
|
|
||||||
|
/* already a 6pack archive? */
|
||||||
|
if (detect_magic(in)) {
|
||||||
|
printf("Error: file %s is already a 6pack archive!\n", input_file);
|
||||||
|
fclose(in);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* truncate directory prefix, e.g. "foo/bar/FILE.txt" becomes "FILE.txt" */
|
||||||
|
shown_name = input_file + strlen(input_file) - 1;
|
||||||
|
while (shown_name > input_file)
|
||||||
|
if (*(shown_name - 1) == PATH_SEPARATOR)
|
||||||
|
break;
|
||||||
|
else
|
||||||
|
shown_name--;
|
||||||
|
|
||||||
|
/* chunk for File Entry */
|
||||||
|
buffer[0] = fsize & 255;
|
||||||
|
buffer[1] = (fsize >> 8) & 255;
|
||||||
|
buffer[2] = (fsize >> 16) & 255;
|
||||||
|
buffer[3] = (fsize >> 24) & 255;
|
||||||
|
#if 0
|
||||||
|
buffer[4] = (fsize >> 32) & 255;
|
||||||
|
buffer[5] = (fsize >> 40) & 255;
|
||||||
|
buffer[6] = (fsize >> 48) & 255;
|
||||||
|
buffer[7] = (fsize >> 56) & 255;
|
||||||
|
#else
|
||||||
|
/* because fsize is only 32-bit */
|
||||||
|
buffer[4] = 0;
|
||||||
|
buffer[5] = 0;
|
||||||
|
buffer[6] = 0;
|
||||||
|
buffer[7] = 0;
|
||||||
|
#endif
|
||||||
|
buffer[8] = (strlen(shown_name) + 1) & 255;
|
||||||
|
buffer[9] = (strlen(shown_name) + 1) >> 8;
|
||||||
|
checksum = 1L;
|
||||||
|
checksum = update_adler32(checksum, buffer, 10);
|
||||||
|
checksum = update_adler32(checksum, shown_name, strlen(shown_name) + 1);
|
||||||
|
write_chunk_header(f, 1, 0, 10 + strlen(shown_name) + 1, checksum, 0);
|
||||||
|
fwrite(buffer, 10, 1, f);
|
||||||
|
fwrite(shown_name, strlen(shown_name) + 1, 1, f);
|
||||||
|
total_compressed = 16 + 10 + strlen(shown_name) + 1;
|
||||||
|
|
||||||
|
/* for progress status */
|
||||||
|
memset(progress, ' ', 20);
|
||||||
|
if (strlen(shown_name) < 16)
|
||||||
|
for (c = 0; c < (int)strlen(shown_name); c++) progress[c] = shown_name[c];
|
||||||
|
else {
|
||||||
|
for (c = 0; c < 13; c++) progress[c] = shown_name[c];
|
||||||
|
progress[13] = '.';
|
||||||
|
progress[14] = '.';
|
||||||
|
progress[15] = ' ';
|
||||||
|
}
|
||||||
|
progress[16] = '[';
|
||||||
|
progress[17] = 0;
|
||||||
|
printf("%s", progress);
|
||||||
|
for (c = 0; c < 50; c++) printf(".");
|
||||||
|
printf("]\r");
|
||||||
|
printf("%s", progress);
|
||||||
|
|
||||||
|
/* read file and place in archive */
|
||||||
|
total_read = 0;
|
||||||
|
percent = 0;
|
||||||
|
for (;;) {
|
||||||
|
int compress_method = method;
|
||||||
|
int last_percent = (int)percent;
|
||||||
|
size_t bytes_read = fread(buffer, 1, BLOCK_SIZE, in);
|
||||||
|
if (bytes_read == 0) break;
|
||||||
|
total_read += bytes_read;
|
||||||
|
|
||||||
|
/* for progress */
|
||||||
|
if (fsize < (1 << 24))
|
||||||
|
percent = total_read * 100 / fsize;
|
||||||
|
else
|
||||||
|
percent = total_read / 256 * 100 / (fsize >> 8);
|
||||||
|
percent >>= 1;
|
||||||
|
while (last_percent < (int)percent) {
|
||||||
|
printf("#");
|
||||||
|
last_percent++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* too small, don't bother to compress */
|
||||||
|
if (bytes_read < 32) compress_method = 0;
|
||||||
|
|
||||||
|
/* write to output */
|
||||||
|
switch (compress_method) {
|
||||||
|
/* FastLZ */
|
||||||
|
case 1:
|
||||||
|
chunk_size = fastlz_compress_level(level, buffer, bytes_read, result);
|
||||||
|
checksum = update_adler32(1L, result, chunk_size);
|
||||||
|
write_chunk_header(f, 17, 1, chunk_size, checksum, bytes_read);
|
||||||
|
fwrite(result, 1, chunk_size, f);
|
||||||
|
total_compressed += 16;
|
||||||
|
total_compressed += chunk_size;
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* uncompressed, also fallback method */
|
||||||
|
case 0:
|
||||||
|
default:
|
||||||
|
checksum = 1L;
|
||||||
|
checksum = update_adler32(checksum, buffer, bytes_read);
|
||||||
|
write_chunk_header(f, 17, 0, bytes_read, checksum, bytes_read);
|
||||||
|
fwrite(buffer, 1, bytes_read, f);
|
||||||
|
total_compressed += 16;
|
||||||
|
total_compressed += bytes_read;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose(in);
|
||||||
|
if (total_read != fsize) {
|
||||||
|
printf("\n");
|
||||||
|
printf("Error: reading %s failed!\n", input_file);
|
||||||
|
return -1;
|
||||||
|
} else {
|
||||||
|
printf("] ");
|
||||||
|
if (total_compressed < fsize) {
|
||||||
|
if (fsize < (1 << 20))
|
||||||
|
percent = total_compressed * 1000 / fsize;
|
||||||
|
else
|
||||||
|
percent = total_compressed / 256 * 1000 / (fsize >> 8);
|
||||||
|
percent = 1000 - percent;
|
||||||
|
printf("%2d.%d%% saved", (int)percent / 10, (int)percent % 10);
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int pack_file(int compress_level, const char* input_file, const char* output_file) {
|
||||||
|
FILE* f;
|
||||||
|
int result;
|
||||||
|
|
||||||
|
f = fopen(output_file, "rb");
|
||||||
|
if (f) {
|
||||||
|
fclose(f);
|
||||||
|
printf("Error: file %s already exists. Aborted.\n\n", output_file);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
f = fopen(output_file, "wb");
|
||||||
|
if (!f) {
|
||||||
|
printf("Error: could not create %s. Aborted.\n\n", output_file);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
write_magic(f);
|
||||||
|
|
||||||
|
result = pack_file_compressed(input_file, 1, compress_level, f);
|
||||||
|
fclose(f);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef SIXPACK_BENCHMARK_WIN32
|
||||||
|
int benchmark_speed(int compress_level, const char* input_file);
|
||||||
|
|
||||||
|
int benchmark_speed(int compress_level, const char* input_file) {
|
||||||
|
FILE* in;
|
||||||
|
unsigned long fsize;
|
||||||
|
unsigned long maxout;
|
||||||
|
const char* shown_name;
|
||||||
|
unsigned char* buffer;
|
||||||
|
unsigned char* result;
|
||||||
|
size_t bytes_read;
|
||||||
|
|
||||||
|
/* sanity check */
|
||||||
|
in = fopen(input_file, "rb");
|
||||||
|
if (!in) {
|
||||||
|
printf("Error: could not open %s\n", input_file);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* find size of the file */
|
||||||
|
fseek(in, 0, SEEK_END);
|
||||||
|
fsize = ftell(in);
|
||||||
|
fseek(in, 0, SEEK_SET);
|
||||||
|
|
||||||
|
/* already a 6pack archive? */
|
||||||
|
if (detect_magic(in)) {
|
||||||
|
printf("Error: no benchmark for 6pack archive!\n");
|
||||||
|
fclose(in);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* truncate directory prefix, e.g. "foo/bar/FILE.txt" becomes "FILE.txt" */
|
||||||
|
shown_name = input_file + strlen(input_file) - 1;
|
||||||
|
while (shown_name > input_file)
|
||||||
|
if (*(shown_name - 1) == PATH_SEPARATOR)
|
||||||
|
break;
|
||||||
|
else
|
||||||
|
shown_name--;
|
||||||
|
|
||||||
|
maxout = 1.05 * fsize;
|
||||||
|
maxout = (maxout < 66) ? 66 : maxout;
|
||||||
|
buffer = (unsigned char*)malloc(fsize);
|
||||||
|
result = (unsigned char*)malloc(maxout);
|
||||||
|
if (!buffer || !result) {
|
||||||
|
printf("Error: not enough memory!\n");
|
||||||
|
free(buffer);
|
||||||
|
free(result);
|
||||||
|
fclose(in);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("Reading source file....\n");
|
||||||
|
bytes_read = fread(buffer, 1, fsize, in);
|
||||||
|
if (bytes_read != fsize) {
|
||||||
|
printf("Error reading file %s!\n", shown_name);
|
||||||
|
printf("Read %d bytes, expecting %d bytes\n", bytes_read, fsize);
|
||||||
|
free(buffer);
|
||||||
|
free(result);
|
||||||
|
fclose(in);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* shamelessly copied from QuickLZ 1.20 test program */
|
||||||
|
{
|
||||||
|
unsigned int j, y;
|
||||||
|
size_t i, u = 0;
|
||||||
|
double mbs, fastest;
|
||||||
|
unsigned long compressed_size;
|
||||||
|
|
||||||
|
printf("Setting HIGH_PRIORITY_CLASS...\n");
|
||||||
|
SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS);
|
||||||
|
|
||||||
|
printf("Benchmarking FastLZ Level %d, please wait...\n", compress_level);
|
||||||
|
|
||||||
|
i = bytes_read;
|
||||||
|
fastest = 0.0;
|
||||||
|
for (j = 0; j < 3; j++) {
|
||||||
|
y = 0;
|
||||||
|
mbs = GetTickCount();
|
||||||
|
while (GetTickCount() == mbs)
|
||||||
|
;
|
||||||
|
mbs = GetTickCount();
|
||||||
|
while (GetTickCount() - mbs < 3000) /* 1% accuracy with 18.2 timer */
|
||||||
|
{
|
||||||
|
u = fastlz_compress_level(compress_level, buffer, bytes_read, result);
|
||||||
|
y++;
|
||||||
|
}
|
||||||
|
|
||||||
|
mbs = ((double)i * (double)y) / ((double)(GetTickCount() - mbs) / 1000.) / 1000000.;
|
||||||
|
/*printf(" %.1f Mbyte/s ", mbs);*/
|
||||||
|
if (fastest < mbs) fastest = mbs;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("\nCompressed %d bytes into %d bytes (%.1f%%) at %.1f Mbyte/s.\n", (unsigned int)i, (unsigned int)u,
|
||||||
|
(double)u / (double)i * 100., fastest);
|
||||||
|
|
||||||
|
#if 1
|
||||||
|
fastest = 0.0;
|
||||||
|
compressed_size = u;
|
||||||
|
for (j = 0; j < 3; j++) {
|
||||||
|
y = 0;
|
||||||
|
mbs = GetTickCount();
|
||||||
|
while (GetTickCount() == mbs)
|
||||||
|
;
|
||||||
|
mbs = GetTickCount();
|
||||||
|
while (GetTickCount() - mbs < 3000) /* 1% accuracy with 18.2 timer */
|
||||||
|
{
|
||||||
|
u = fastlz_decompress(result, compressed_size, buffer, bytes_read);
|
||||||
|
y++;
|
||||||
|
}
|
||||||
|
|
||||||
|
mbs = ((double)i * (double)y) / ((double)(GetTickCount() - mbs) / 1000.) / 1000000.;
|
||||||
|
/*printf(" %.1f Mbyte/s ", mbs);*/
|
||||||
|
if (fastest < mbs) fastest = mbs;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("\nDecompressed at %.1f Mbyte/s.\n\n(1 MB = 1000000 byte)\n", fastest);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose(in);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif /* SIXPACK_BENCHMARK_WIN32 */
|
||||||
|
|
||||||
|
int main(int argc, char** argv) {
|
||||||
|
int i;
|
||||||
|
int compress_level;
|
||||||
|
int benchmark;
|
||||||
|
char* input_file;
|
||||||
|
char* output_file;
|
||||||
|
|
||||||
|
/* show help with no argument at all*/
|
||||||
|
if (argc == 1) {
|
||||||
|
usage();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* default compression level, not the fastest */
|
||||||
|
compress_level = 2;
|
||||||
|
|
||||||
|
/* do benchmark only when explicitly specified */
|
||||||
|
benchmark = 0;
|
||||||
|
|
||||||
|
/* no file is specified */
|
||||||
|
input_file = 0;
|
||||||
|
output_file = 0;
|
||||||
|
|
||||||
|
for (i = 1; i <= argc; i++) {
|
||||||
|
char* argument = argv[i];
|
||||||
|
|
||||||
|
if (!argument) continue;
|
||||||
|
|
||||||
|
/* display help on usage */
|
||||||
|
if (!strcmp(argument, "-h") || !strcmp(argument, "--help")) {
|
||||||
|
usage();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* check for version information */
|
||||||
|
if (!strcmp(argument, "-v") || !strcmp(argument, "--version")) {
|
||||||
|
printf("6pack: high-speed file compression tool\n");
|
||||||
|
printf("Version %s (using FastLZ %s)\n", SIXPACK_VERSION_STRING, FASTLZ_VERSION_STRING);
|
||||||
|
printf("Copyright (C) Ariya Hidayat\n");
|
||||||
|
printf("\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* test compression speed? */
|
||||||
|
if (!strcmp(argument, "-mem")) {
|
||||||
|
benchmark = 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* compression level */
|
||||||
|
if (!strcmp(argument, "-1") || !strcmp(argument, "--fastest")) {
|
||||||
|
compress_level = 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (!strcmp(argument, "-2")) {
|
||||||
|
compress_level = 2;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* unknown option */
|
||||||
|
if (argument[0] == '-') {
|
||||||
|
printf("Error: unknown option %s\n\n", argument);
|
||||||
|
printf("To get help on usage:\n");
|
||||||
|
printf(" 6pack --help\n\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* first specified file is input */
|
||||||
|
if (!input_file) {
|
||||||
|
input_file = argument;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* next specified file is output */
|
||||||
|
if (!output_file) {
|
||||||
|
output_file = argument;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* files are already specified */
|
||||||
|
printf("Error: unknown option %s\n\n", argument);
|
||||||
|
printf("To get help on usage:\n");
|
||||||
|
printf(" 6pack --help\n\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!input_file) {
|
||||||
|
printf("Error: input file is not specified.\n\n");
|
||||||
|
printf("To get help on usage:\n");
|
||||||
|
printf(" 6pack --help\n\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!output_file && !benchmark) {
|
||||||
|
printf("Error: output file is not specified.\n\n");
|
||||||
|
printf("To get help on usage:\n");
|
||||||
|
printf(" 6pack --help\n\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef SIXPACK_BENCHMARK_WIN32
|
||||||
|
if (benchmark)
|
||||||
|
return benchmark_speed(compress_level, input_file);
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
return pack_file(compress_level, input_file, output_file);
|
||||||
|
|
||||||
|
/* unreachable */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
425
FastLZ/examples/6unpack.c
Normal file
425
FastLZ/examples/6unpack.c
Normal file
@ -0,0 +1,425 @@
|
|||||||
|
/*
|
||||||
|
6PACK - file compressor using FastLZ (lightning-fast compression library)
|
||||||
|
Copyright (C) 2007-2020 Ariya Hidayat <ariya.hidayat@gmail.com>
|
||||||
|
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#define SIXPACK_VERSION_MAJOR 0
|
||||||
|
#define SIXPACK_VERSION_MINOR 1
|
||||||
|
#define SIXPACK_VERSION_REVISION 0
|
||||||
|
#define SIXPACK_VERSION_STRING "0.1.0"
|
||||||
|
|
||||||
|
#include "fastlz.h"
|
||||||
|
|
||||||
|
/* magic identifier for 6pack file */
|
||||||
|
static unsigned char sixpack_magic[8] = {137, '6', 'P', 'K', 13, 10, 26, 10};
|
||||||
|
|
||||||
|
#define BLOCK_SIZE 65536
|
||||||
|
|
||||||
|
/* prototypes */
|
||||||
|
static unsigned long update_adler32(unsigned long checksum, const void* buf, int len);
|
||||||
|
void usage(void);
|
||||||
|
int detect_magic(FILE* f);
|
||||||
|
static unsigned long readU16(const unsigned char* ptr);
|
||||||
|
static unsigned long readU32(const unsigned char* ptr);
|
||||||
|
void read_chunk_header(FILE* f, int* id, int* options, unsigned long* size, unsigned long* checksum,
|
||||||
|
unsigned long* extra);
|
||||||
|
int unpack_file(const char* archive_file);
|
||||||
|
|
||||||
|
/* for Adler-32 checksum algorithm, see RFC 1950 Section 8.2 */
|
||||||
|
#define ADLER32_BASE 65521
|
||||||
|
static unsigned long update_adler32(unsigned long checksum, const void* buf, int len) {
|
||||||
|
const unsigned char* ptr = (const unsigned char*)buf;
|
||||||
|
unsigned long s1 = checksum & 0xffff;
|
||||||
|
unsigned long s2 = (checksum >> 16) & 0xffff;
|
||||||
|
|
||||||
|
while (len > 0) {
|
||||||
|
unsigned k = len < 5552 ? len : 5552;
|
||||||
|
len -= k;
|
||||||
|
|
||||||
|
while (k >= 8) {
|
||||||
|
s1 += *ptr++;
|
||||||
|
s2 += s1;
|
||||||
|
s1 += *ptr++;
|
||||||
|
s2 += s1;
|
||||||
|
s1 += *ptr++;
|
||||||
|
s2 += s1;
|
||||||
|
s1 += *ptr++;
|
||||||
|
s2 += s1;
|
||||||
|
s1 += *ptr++;
|
||||||
|
s2 += s1;
|
||||||
|
s1 += *ptr++;
|
||||||
|
s2 += s1;
|
||||||
|
s1 += *ptr++;
|
||||||
|
s2 += s1;
|
||||||
|
s1 += *ptr++;
|
||||||
|
s2 += s1;
|
||||||
|
k -= 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (k-- > 0) {
|
||||||
|
s1 += *ptr++;
|
||||||
|
s2 += s1;
|
||||||
|
}
|
||||||
|
s1 = s1 % ADLER32_BASE;
|
||||||
|
s2 = s2 % ADLER32_BASE;
|
||||||
|
}
|
||||||
|
return (s2 << 16) + s1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void usage(void) {
|
||||||
|
printf("6unpack: uncompress 6pack archive\n");
|
||||||
|
printf("Copyright (C) Ariya Hidayat\n");
|
||||||
|
printf("\n");
|
||||||
|
printf("Usage: 6unpack archive-file\n");
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* return non-zero if magic sequence is detected */
|
||||||
|
/* warning: reset the read pointer to the beginning of the file */
|
||||||
|
int detect_magic(FILE* f) {
|
||||||
|
unsigned char buffer[8];
|
||||||
|
size_t bytes_read;
|
||||||
|
int c;
|
||||||
|
|
||||||
|
fseek(f, SEEK_SET, 0);
|
||||||
|
bytes_read = fread(buffer, 1, 8, f);
|
||||||
|
fseek(f, SEEK_SET, 0);
|
||||||
|
if (bytes_read < 8) return 0;
|
||||||
|
|
||||||
|
for (c = 0; c < 8; c++)
|
||||||
|
if (buffer[c] != sixpack_magic[c]) return 0;
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static unsigned long readU16(const unsigned char* ptr) { return ptr[0] + (ptr[1] << 8); }
|
||||||
|
|
||||||
|
static unsigned long readU32(const unsigned char* ptr) {
|
||||||
|
return ptr[0] + (ptr[1] << 8) + (ptr[2] << 16) + (ptr[3] << 24);
|
||||||
|
}
|
||||||
|
|
||||||
|
void read_chunk_header(FILE* f, int* id, int* options, unsigned long* size, unsigned long* checksum,
|
||||||
|
unsigned long* extra) {
|
||||||
|
unsigned char buffer[16];
|
||||||
|
fread(buffer, 1, 16, f);
|
||||||
|
|
||||||
|
*id = readU16(buffer) & 0xffff;
|
||||||
|
*options = readU16(buffer + 2) & 0xffff;
|
||||||
|
*size = readU32(buffer + 4) & 0xffffffff;
|
||||||
|
*checksum = readU32(buffer + 8) & 0xffffffff;
|
||||||
|
*extra = readU32(buffer + 12) & 0xffffffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
int unpack_file(const char* input_file) {
|
||||||
|
FILE* in;
|
||||||
|
unsigned long fsize;
|
||||||
|
int c;
|
||||||
|
unsigned long percent;
|
||||||
|
unsigned char progress[20];
|
||||||
|
int chunk_id;
|
||||||
|
int chunk_options;
|
||||||
|
unsigned long chunk_size;
|
||||||
|
unsigned long chunk_checksum;
|
||||||
|
unsigned long chunk_extra;
|
||||||
|
unsigned char buffer[BLOCK_SIZE];
|
||||||
|
unsigned long checksum;
|
||||||
|
|
||||||
|
unsigned long decompressed_size;
|
||||||
|
unsigned long total_extracted;
|
||||||
|
int name_length;
|
||||||
|
char* output_file;
|
||||||
|
FILE* f;
|
||||||
|
|
||||||
|
unsigned char* compressed_buffer;
|
||||||
|
unsigned char* decompressed_buffer;
|
||||||
|
unsigned long compressed_bufsize;
|
||||||
|
unsigned long decompressed_bufsize;
|
||||||
|
|
||||||
|
/* sanity check */
|
||||||
|
in = fopen(input_file, "rb");
|
||||||
|
if (!in) {
|
||||||
|
printf("Error: could not open %s\n", input_file);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* find size of the file */
|
||||||
|
fseek(in, 0, SEEK_END);
|
||||||
|
fsize = ftell(in);
|
||||||
|
fseek(in, 0, SEEK_SET);
|
||||||
|
|
||||||
|
/* not a 6pack archive? */
|
||||||
|
if (!detect_magic(in)) {
|
||||||
|
fclose(in);
|
||||||
|
printf("Error: file %s is not a 6pack archive!\n", input_file);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("Archive: %s", input_file);
|
||||||
|
|
||||||
|
/* position of first chunk */
|
||||||
|
fseek(in, 8, SEEK_SET);
|
||||||
|
|
||||||
|
/* initialize */
|
||||||
|
output_file = 0;
|
||||||
|
f = 0;
|
||||||
|
total_extracted = 0;
|
||||||
|
decompressed_size = 0;
|
||||||
|
percent = 0;
|
||||||
|
compressed_buffer = 0;
|
||||||
|
decompressed_buffer = 0;
|
||||||
|
compressed_bufsize = 0;
|
||||||
|
decompressed_bufsize = 0;
|
||||||
|
|
||||||
|
/* main loop */
|
||||||
|
for (;;) {
|
||||||
|
/* end of file? */
|
||||||
|
size_t pos = ftell(in);
|
||||||
|
if (pos >= fsize) break;
|
||||||
|
|
||||||
|
read_chunk_header(in, &chunk_id, &chunk_options, &chunk_size, &chunk_checksum, &chunk_extra);
|
||||||
|
|
||||||
|
if ((chunk_id == 1) && (chunk_size > 10) && (chunk_size < BLOCK_SIZE)) {
|
||||||
|
/* close current file, if any */
|
||||||
|
printf("\n");
|
||||||
|
free(output_file);
|
||||||
|
output_file = 0;
|
||||||
|
if (f) fclose(f);
|
||||||
|
|
||||||
|
/* file entry */
|
||||||
|
fread(buffer, 1, chunk_size, in);
|
||||||
|
checksum = update_adler32(1L, buffer, chunk_size);
|
||||||
|
if (checksum != chunk_checksum) {
|
||||||
|
free(output_file);
|
||||||
|
output_file = 0;
|
||||||
|
fclose(in);
|
||||||
|
printf("\nError: checksum mismatch!\n");
|
||||||
|
printf("Got %08lX Expecting %08lX\n", checksum, chunk_checksum);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
decompressed_size = readU32(buffer);
|
||||||
|
total_extracted = 0;
|
||||||
|
percent = 0;
|
||||||
|
|
||||||
|
/* get file to extract */
|
||||||
|
name_length = (int)readU16(buffer + 8);
|
||||||
|
if (name_length > (int)chunk_size - 10) name_length = chunk_size - 10;
|
||||||
|
output_file = (char*)malloc(name_length + 1);
|
||||||
|
memset(output_file, 0, name_length + 1);
|
||||||
|
for (c = 0; c < name_length; c++) output_file[c] = buffer[10 + c];
|
||||||
|
|
||||||
|
/* check if already exists */
|
||||||
|
f = fopen(output_file, "rb");
|
||||||
|
if (f) {
|
||||||
|
fclose(f);
|
||||||
|
printf("File %s already exists. Skipped.\n", output_file);
|
||||||
|
free(output_file);
|
||||||
|
output_file = 0;
|
||||||
|
f = 0;
|
||||||
|
} else {
|
||||||
|
/* create the file */
|
||||||
|
f = fopen(output_file, "wb");
|
||||||
|
if (!f) {
|
||||||
|
printf("Can't create file %s. Skipped.\n", output_file);
|
||||||
|
free(output_file);
|
||||||
|
output_file = 0;
|
||||||
|
f = 0;
|
||||||
|
} else {
|
||||||
|
/* for progress status */
|
||||||
|
printf("\n");
|
||||||
|
memset(progress, ' ', 20);
|
||||||
|
if (strlen(output_file) < 16)
|
||||||
|
for (c = 0; c < (int)strlen(output_file); c++) progress[c] = output_file[c];
|
||||||
|
else {
|
||||||
|
for (c = 0; c < 13; c++) progress[c] = output_file[c];
|
||||||
|
progress[13] = '.';
|
||||||
|
progress[14] = '.';
|
||||||
|
progress[15] = ' ';
|
||||||
|
}
|
||||||
|
progress[16] = '[';
|
||||||
|
progress[17] = 0;
|
||||||
|
printf("%s", progress);
|
||||||
|
for (c = 0; c < 50; c++) printf(".");
|
||||||
|
printf("]\r");
|
||||||
|
printf("%s", progress);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((chunk_id == 17) && f && output_file && decompressed_size) {
|
||||||
|
unsigned long remaining;
|
||||||
|
|
||||||
|
/* uncompressed */
|
||||||
|
switch (chunk_options) {
|
||||||
|
/* stored, simply copy to output */
|
||||||
|
case 0:
|
||||||
|
/* read one block at at time, write and update checksum */
|
||||||
|
total_extracted += chunk_size;
|
||||||
|
remaining = chunk_size;
|
||||||
|
checksum = 1L;
|
||||||
|
for (;;) {
|
||||||
|
unsigned long r = (BLOCK_SIZE < remaining) ? BLOCK_SIZE : remaining;
|
||||||
|
size_t bytes_read = fread(buffer, 1, r, in);
|
||||||
|
if (bytes_read == 0) break;
|
||||||
|
fwrite(buffer, 1, bytes_read, f);
|
||||||
|
checksum = update_adler32(checksum, buffer, bytes_read);
|
||||||
|
remaining -= bytes_read;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* verify everything is written correctly */
|
||||||
|
if (checksum != chunk_checksum) {
|
||||||
|
fclose(f);
|
||||||
|
f = 0;
|
||||||
|
free(output_file);
|
||||||
|
output_file = 0;
|
||||||
|
printf("\nError: checksum mismatch. Aborted.\n");
|
||||||
|
printf("Got %08lX Expecting %08lX\n", checksum, chunk_checksum);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* compressed using FastLZ */
|
||||||
|
case 1:
|
||||||
|
/* enlarge input buffer if necessary */
|
||||||
|
if (chunk_size > compressed_bufsize) {
|
||||||
|
compressed_bufsize = chunk_size;
|
||||||
|
free(compressed_buffer);
|
||||||
|
compressed_buffer = (unsigned char*)malloc(compressed_bufsize);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* enlarge output buffer if necessary */
|
||||||
|
if (chunk_extra > decompressed_bufsize) {
|
||||||
|
decompressed_bufsize = chunk_extra;
|
||||||
|
free(decompressed_buffer);
|
||||||
|
decompressed_buffer = (unsigned char*)malloc(decompressed_bufsize);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* read and check checksum */
|
||||||
|
fread(compressed_buffer, 1, chunk_size, in);
|
||||||
|
checksum = update_adler32(1L, compressed_buffer, chunk_size);
|
||||||
|
total_extracted += chunk_extra;
|
||||||
|
|
||||||
|
/* verify that the chunk data is correct */
|
||||||
|
if (checksum != chunk_checksum) {
|
||||||
|
fclose(f);
|
||||||
|
f = 0;
|
||||||
|
free(output_file);
|
||||||
|
output_file = 0;
|
||||||
|
printf("\nError: checksum mismatch. Skipped.\n");
|
||||||
|
printf("Got %08lX Expecting %08lX\n", checksum, chunk_checksum);
|
||||||
|
} else {
|
||||||
|
/* decompress and verify */
|
||||||
|
remaining = fastlz_decompress(compressed_buffer, chunk_size, decompressed_buffer, chunk_extra);
|
||||||
|
if (remaining != chunk_extra) {
|
||||||
|
fclose(f);
|
||||||
|
f = 0;
|
||||||
|
free(output_file);
|
||||||
|
output_file = 0;
|
||||||
|
printf("\nError: decompression failed. Skipped.\n");
|
||||||
|
} else
|
||||||
|
fwrite(decompressed_buffer, 1, chunk_extra, f);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
printf("\nError: unknown compression method (%d)\n", chunk_options);
|
||||||
|
fclose(f);
|
||||||
|
f = 0;
|
||||||
|
free(output_file);
|
||||||
|
output_file = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* for progress, if everything is fine */
|
||||||
|
if (f) {
|
||||||
|
int last_percent = (int)percent;
|
||||||
|
if (decompressed_size < (1 << 24))
|
||||||
|
percent = total_extracted * 100 / decompressed_size;
|
||||||
|
else
|
||||||
|
percent = total_extracted / 256 * 100 / (decompressed_size >> 8);
|
||||||
|
percent >>= 1;
|
||||||
|
while (last_percent < (int)percent) {
|
||||||
|
printf("#");
|
||||||
|
last_percent++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* position of next chunk */
|
||||||
|
fseek(in, pos + 16 + chunk_size, SEEK_SET);
|
||||||
|
}
|
||||||
|
printf("\n\n");
|
||||||
|
|
||||||
|
/* free allocated stuff */
|
||||||
|
free(compressed_buffer);
|
||||||
|
free(decompressed_buffer);
|
||||||
|
free(output_file);
|
||||||
|
|
||||||
|
/* close working files */
|
||||||
|
if (f) fclose(f);
|
||||||
|
fclose(in);
|
||||||
|
|
||||||
|
/* so far so good */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char** argv) {
|
||||||
|
int i;
|
||||||
|
const char* archive_file;
|
||||||
|
|
||||||
|
/* show help with no argument at all*/
|
||||||
|
if (argc == 1) {
|
||||||
|
usage();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* check for help on usage */
|
||||||
|
for (i = 1; i <= argc; i++)
|
||||||
|
if (argv[i])
|
||||||
|
if (!strcmp(argv[i], "-h") || !strcmp(argv[i], "--help")) {
|
||||||
|
usage();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* check for version information */
|
||||||
|
for (i = 1; i <= argc; i++)
|
||||||
|
if (argv[i])
|
||||||
|
if (!strcmp(argv[i], "-v") || !strcmp(argv[i], "--version")) {
|
||||||
|
printf("6unpack: high-speed file compression tool\n");
|
||||||
|
printf("Version %s (using FastLZ %s)\n", SIXPACK_VERSION_STRING, FASTLZ_VERSION_STRING);
|
||||||
|
printf("Copyright (C) Ariya Hidayat\n");
|
||||||
|
printf("\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* needs at least two arguments */
|
||||||
|
if (argc <= 1) {
|
||||||
|
usage();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
archive_file = argv[1];
|
||||||
|
|
||||||
|
return unpack_file(archive_file);
|
||||||
|
}
|
||||||
12
FastLZ/examples/Makefile
Normal file
12
FastLZ/examples/Makefile
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
CFLAGS?=-Wall -std=c90
|
||||||
|
|
||||||
|
all: 6pack 6unpack
|
||||||
|
|
||||||
|
6pack: 6pack.c ../fastlz.c
|
||||||
|
$(CC) -o 6pack $(CFLAGS) -I.. 6pack.c ../fastlz.c
|
||||||
|
|
||||||
|
6unpack: 6unpack.c ../fastlz.c
|
||||||
|
$(CC) -o 6unpack $(CFLAGS) -I.. 6unpack.c ../fastlz.c
|
||||||
|
|
||||||
|
clean :
|
||||||
|
$(RM) 6pack 6unpack *.o
|
||||||
14
FastLZ/examples/Makefile.win
Executable file
14
FastLZ/examples/Makefile.win
Executable file
@ -0,0 +1,14 @@
|
|||||||
|
CC=cl.exe
|
||||||
|
CFLAGS=/Wall
|
||||||
|
RM=del
|
||||||
|
|
||||||
|
all: 6pack 6unpack
|
||||||
|
|
||||||
|
6pack: 6pack.c ../fastlz.c
|
||||||
|
$(CC) -o 6pack $(CFLAGS) -I.. 6pack.c ../fastlz.c
|
||||||
|
|
||||||
|
6unpack: 6unpack.c ../fastlz.c
|
||||||
|
$(CC) -o 6unpack $(CFLAGS) -I.. 6unpack.c ../fastlz.c
|
||||||
|
|
||||||
|
clean :
|
||||||
|
$(RM) 6pack.exe 6unpack.exe *.obj
|
||||||
508
FastLZ/fastlz.c
Normal file
508
FastLZ/fastlz.c
Normal file
@ -0,0 +1,508 @@
|
|||||||
|
/*
|
||||||
|
FastLZ - Byte-aligned LZ77 compression library
|
||||||
|
Copyright (C) 2005-2020 Ariya Hidayat <ariya.hidayat@gmail.com>
|
||||||
|
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "fastlz.h"
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#pragma GCC diagnostic push
|
||||||
|
#pragma GCC diagnostic ignored "-Wimplicit-fallthrough"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Give hints to the compiler for branch prediction optimization.
|
||||||
|
*/
|
||||||
|
#if defined(__clang__) || (defined(__GNUC__) && (__GNUC__ > 2))
|
||||||
|
#define FASTLZ_LIKELY(c) (__builtin_expect(!!(c), 1))
|
||||||
|
#define FASTLZ_UNLIKELY(c) (__builtin_expect(!!(c), 0))
|
||||||
|
#else
|
||||||
|
#define FASTLZ_LIKELY(c) (c)
|
||||||
|
#define FASTLZ_UNLIKELY(c) (c)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Specialize custom 64-bit implementation for speed improvements.
|
||||||
|
*/
|
||||||
|
#if defined(__x86_64__) || defined(_M_X64) || defined(__aarch64__)
|
||||||
|
#define FLZ_ARCH64
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Workaround for DJGPP to find uint8_t, uint16_t, etc.
|
||||||
|
*/
|
||||||
|
#if defined(__MSDOS__) && defined(__GNUC__)
|
||||||
|
#include <stdint-gcc.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(FASTLZ_USE_MEMMOVE) && (FASTLZ_USE_MEMMOVE == 0)
|
||||||
|
|
||||||
|
static void fastlz_memmove(uint8_t* dest, const uint8_t* src, uint32_t count) {
|
||||||
|
do {
|
||||||
|
*dest++ = *src++;
|
||||||
|
} while (--count);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void fastlz_memcpy(uint8_t* dest, const uint8_t* src, uint32_t count) {
|
||||||
|
return fastlz_memmove(dest, src, count);
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
static void fastlz_memmove(uint8_t* dest, const uint8_t* src, uint32_t count) {
|
||||||
|
if ((count > 4) && (dest >= src + count)) {
|
||||||
|
memmove(dest, src, count);
|
||||||
|
} else {
|
||||||
|
switch (count) {
|
||||||
|
default:
|
||||||
|
do {
|
||||||
|
*dest++ = *src++;
|
||||||
|
} while (--count);
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
*dest++ = *src++;
|
||||||
|
case 2:
|
||||||
|
*dest++ = *src++;
|
||||||
|
case 1:
|
||||||
|
*dest++ = *src++;
|
||||||
|
case 0:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void fastlz_memcpy(uint8_t* dest, const uint8_t* src, uint32_t count) { memcpy(dest, src, count); }
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(FLZ_ARCH64)
|
||||||
|
|
||||||
|
static uint32_t flz_readu32(const void* ptr) { return *(const uint32_t*)ptr; }
|
||||||
|
|
||||||
|
static uint32_t flz_cmp(const uint8_t* p, const uint8_t* q, const uint8_t* r) {
|
||||||
|
const uint8_t* start = p;
|
||||||
|
|
||||||
|
if (flz_readu32(p) == flz_readu32(q)) {
|
||||||
|
p += 4;
|
||||||
|
q += 4;
|
||||||
|
}
|
||||||
|
while (q < r)
|
||||||
|
if (*p++ != *q++) break;
|
||||||
|
return p - start;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* FLZ_ARCH64 */
|
||||||
|
|
||||||
|
#if !defined(FLZ_ARCH64)
|
||||||
|
|
||||||
|
static uint32_t flz_readu32(const void* ptr) {
|
||||||
|
const uint8_t* p = (const uint8_t*)ptr;
|
||||||
|
return (p[3] << 24) | (p[2] << 16) | (p[1] << 8) | p[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint32_t flz_cmp(const uint8_t* p, const uint8_t* q, const uint8_t* r) {
|
||||||
|
const uint8_t* start = p;
|
||||||
|
while (q < r)
|
||||||
|
if (*p++ != *q++) break;
|
||||||
|
return p - start;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* !FLZ_ARCH64 */
|
||||||
|
|
||||||
|
#define MAX_COPY 32
|
||||||
|
#define MAX_LEN 264 /* 256 + 8 */
|
||||||
|
#define MAX_L1_DISTANCE 8192
|
||||||
|
#define MAX_L2_DISTANCE 8191
|
||||||
|
#define MAX_FARDISTANCE (65535 + MAX_L2_DISTANCE - 1)
|
||||||
|
|
||||||
|
#define HASH_LOG 13
|
||||||
|
#define HASH_SIZE (1 << HASH_LOG)
|
||||||
|
#define HASH_MASK (HASH_SIZE - 1)
|
||||||
|
|
||||||
|
static uint16_t flz_hash(uint32_t v) {
|
||||||
|
uint32_t h = (v * 2654435769LL) >> (32 - HASH_LOG);
|
||||||
|
return h & HASH_MASK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* special case of memcpy: at most MAX_COPY bytes */
|
||||||
|
static void flz_smallcopy(uint8_t* dest, const uint8_t* src, uint32_t count) {
|
||||||
|
#if defined(FLZ_ARCH64)
|
||||||
|
if (count >= 4) {
|
||||||
|
const uint32_t* p = (const uint32_t*)src;
|
||||||
|
uint32_t* q = (uint32_t*)dest;
|
||||||
|
while (count > 4) {
|
||||||
|
*q++ = *p++;
|
||||||
|
count -= 4;
|
||||||
|
dest += 4;
|
||||||
|
src += 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
fastlz_memcpy(dest, src, count);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* special case of memcpy: exactly MAX_COPY bytes */
|
||||||
|
static void flz_maxcopy(void* dest, const void* src) {
|
||||||
|
#if defined(FLZ_ARCH64)
|
||||||
|
const uint32_t* p = (const uint32_t*)src;
|
||||||
|
uint32_t* q = (uint32_t*)dest;
|
||||||
|
*q++ = *p++;
|
||||||
|
*q++ = *p++;
|
||||||
|
*q++ = *p++;
|
||||||
|
*q++ = *p++;
|
||||||
|
*q++ = *p++;
|
||||||
|
*q++ = *p++;
|
||||||
|
*q++ = *p++;
|
||||||
|
*q++ = *p++;
|
||||||
|
#else
|
||||||
|
fastlz_memcpy(dest, src, MAX_COPY);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint8_t* flz_literals(uint32_t runs, const uint8_t* src, uint8_t* dest) {
|
||||||
|
while (runs >= MAX_COPY) {
|
||||||
|
*dest++ = MAX_COPY - 1;
|
||||||
|
flz_maxcopy(dest, src);
|
||||||
|
src += MAX_COPY;
|
||||||
|
dest += MAX_COPY;
|
||||||
|
runs -= MAX_COPY;
|
||||||
|
}
|
||||||
|
if (runs > 0) {
|
||||||
|
*dest++ = runs - 1;
|
||||||
|
flz_smallcopy(dest, src, runs);
|
||||||
|
dest += runs;
|
||||||
|
}
|
||||||
|
return dest;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint8_t* flz1_match(uint32_t len, uint32_t distance, uint8_t* op) {
|
||||||
|
--distance;
|
||||||
|
if (FASTLZ_UNLIKELY(len > MAX_LEN - 2))
|
||||||
|
while (len > MAX_LEN - 2) {
|
||||||
|
*op++ = (7 << 5) + (distance >> 8);
|
||||||
|
*op++ = MAX_LEN - 2 - 7 - 2;
|
||||||
|
*op++ = (distance & 255);
|
||||||
|
len -= MAX_LEN - 2;
|
||||||
|
}
|
||||||
|
if (len < 7) {
|
||||||
|
*op++ = (len << 5) + (distance >> 8);
|
||||||
|
*op++ = (distance & 255);
|
||||||
|
} else {
|
||||||
|
*op++ = (7 << 5) + (distance >> 8);
|
||||||
|
*op++ = len - 7;
|
||||||
|
*op++ = (distance & 255);
|
||||||
|
}
|
||||||
|
return op;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define FASTLZ_BOUND_CHECK(cond) \
|
||||||
|
if (FASTLZ_UNLIKELY(!(cond))) return 0;
|
||||||
|
|
||||||
|
static int fastlz1_compress(const void* input, int length, void* output) {
|
||||||
|
const uint8_t* ip = (const uint8_t*)input;
|
||||||
|
const uint8_t* ip_start = ip;
|
||||||
|
const uint8_t* ip_bound = ip + length - 4; /* because readU32 */
|
||||||
|
const uint8_t* ip_limit = ip + length - 12 - 1;
|
||||||
|
uint8_t* op = (uint8_t*)output;
|
||||||
|
|
||||||
|
uint32_t htab[HASH_SIZE];
|
||||||
|
uint32_t seq, hash;
|
||||||
|
|
||||||
|
/* initializes hash table */
|
||||||
|
for (hash = 0; hash < HASH_SIZE; ++hash) htab[hash] = 0;
|
||||||
|
|
||||||
|
/* we start with literal copy */
|
||||||
|
const uint8_t* anchor = ip;
|
||||||
|
ip += 2;
|
||||||
|
|
||||||
|
/* main loop */
|
||||||
|
while (FASTLZ_LIKELY(ip < ip_limit)) {
|
||||||
|
const uint8_t* ref;
|
||||||
|
uint32_t distance, cmp;
|
||||||
|
|
||||||
|
/* find potential match */
|
||||||
|
do {
|
||||||
|
seq = flz_readu32(ip) & 0xffffff;
|
||||||
|
hash = flz_hash(seq);
|
||||||
|
ref = ip_start + htab[hash];
|
||||||
|
htab[hash] = ip - ip_start;
|
||||||
|
distance = ip - ref;
|
||||||
|
cmp = FASTLZ_LIKELY(distance < MAX_L1_DISTANCE) ? flz_readu32(ref) & 0xffffff : 0x1000000;
|
||||||
|
if (FASTLZ_UNLIKELY(ip >= ip_limit)) break;
|
||||||
|
++ip;
|
||||||
|
} while (seq != cmp);
|
||||||
|
|
||||||
|
if (FASTLZ_UNLIKELY(ip >= ip_limit)) break;
|
||||||
|
--ip;
|
||||||
|
|
||||||
|
if (FASTLZ_LIKELY(ip > anchor)) {
|
||||||
|
op = flz_literals(ip - anchor, anchor, op);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t len = flz_cmp(ref + 3, ip + 3, ip_bound);
|
||||||
|
op = flz1_match(len, distance, op);
|
||||||
|
|
||||||
|
/* update the hash at match boundary */
|
||||||
|
ip += len;
|
||||||
|
seq = flz_readu32(ip);
|
||||||
|
hash = flz_hash(seq & 0xffffff);
|
||||||
|
htab[hash] = ip++ - ip_start;
|
||||||
|
seq >>= 8;
|
||||||
|
hash = flz_hash(seq);
|
||||||
|
htab[hash] = ip++ - ip_start;
|
||||||
|
|
||||||
|
anchor = ip;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t copy = (uint8_t*)input + length - anchor;
|
||||||
|
op = flz_literals(copy, anchor, op);
|
||||||
|
|
||||||
|
return op - (uint8_t*)output;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int fastlz1_decompress(const void* input, int length, void* output, int maxout) {
|
||||||
|
const uint8_t* ip = (const uint8_t*)input;
|
||||||
|
const uint8_t* ip_limit = ip + length;
|
||||||
|
const uint8_t* ip_bound = ip_limit - 2;
|
||||||
|
uint8_t* op = (uint8_t*)output;
|
||||||
|
uint8_t* op_limit = op + maxout;
|
||||||
|
uint32_t ctrl = (*ip++) & 31;
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
if (ctrl >= 32) {
|
||||||
|
uint32_t len = (ctrl >> 5) - 1;
|
||||||
|
uint32_t ofs = (ctrl & 31) << 8;
|
||||||
|
const uint8_t* ref = op - ofs - 1;
|
||||||
|
if (len == 7 - 1) {
|
||||||
|
FASTLZ_BOUND_CHECK(ip <= ip_bound);
|
||||||
|
len += *ip++;
|
||||||
|
}
|
||||||
|
ref -= *ip++;
|
||||||
|
len += 3;
|
||||||
|
FASTLZ_BOUND_CHECK(op + len <= op_limit);
|
||||||
|
FASTLZ_BOUND_CHECK(ref >= (uint8_t*)output);
|
||||||
|
fastlz_memmove(op, ref, len);
|
||||||
|
op += len;
|
||||||
|
} else {
|
||||||
|
ctrl++;
|
||||||
|
FASTLZ_BOUND_CHECK(op + ctrl <= op_limit);
|
||||||
|
FASTLZ_BOUND_CHECK(ip + ctrl <= ip_limit);
|
||||||
|
fastlz_memcpy(op, ip, ctrl);
|
||||||
|
ip += ctrl;
|
||||||
|
op += ctrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (FASTLZ_UNLIKELY(ip > ip_bound)) break;
|
||||||
|
ctrl = *ip++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return op - (uint8_t*)output;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint8_t* flz2_match(uint32_t len, uint32_t distance, uint8_t* op) {
|
||||||
|
--distance;
|
||||||
|
if (distance < MAX_L2_DISTANCE) {
|
||||||
|
if (len < 7) {
|
||||||
|
*op++ = (len << 5) + (distance >> 8);
|
||||||
|
*op++ = (distance & 255);
|
||||||
|
} else {
|
||||||
|
*op++ = (7 << 5) + (distance >> 8);
|
||||||
|
for (len -= 7; len >= 255; len -= 255) *op++ = 255;
|
||||||
|
*op++ = len;
|
||||||
|
*op++ = (distance & 255);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* far away, but not yet in the another galaxy... */
|
||||||
|
if (len < 7) {
|
||||||
|
distance -= MAX_L2_DISTANCE;
|
||||||
|
*op++ = (len << 5) + 31;
|
||||||
|
*op++ = 255;
|
||||||
|
*op++ = distance >> 8;
|
||||||
|
*op++ = distance & 255;
|
||||||
|
} else {
|
||||||
|
distance -= MAX_L2_DISTANCE;
|
||||||
|
*op++ = (7 << 5) + 31;
|
||||||
|
for (len -= 7; len >= 255; len -= 255) *op++ = 255;
|
||||||
|
*op++ = len;
|
||||||
|
*op++ = 255;
|
||||||
|
*op++ = distance >> 8;
|
||||||
|
*op++ = distance & 255;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return op;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int fastlz2_compress(const void* input, int length, void* output) {
|
||||||
|
const uint8_t* ip = (const uint8_t*)input;
|
||||||
|
const uint8_t* ip_start = ip;
|
||||||
|
const uint8_t* ip_bound = ip + length - 4; /* because readU32 */
|
||||||
|
const uint8_t* ip_limit = ip + length - 12 - 1;
|
||||||
|
uint8_t* op = (uint8_t*)output;
|
||||||
|
|
||||||
|
uint32_t htab[HASH_SIZE];
|
||||||
|
uint32_t seq, hash;
|
||||||
|
|
||||||
|
/* initializes hash table */
|
||||||
|
for (hash = 0; hash < HASH_SIZE; ++hash) htab[hash] = 0;
|
||||||
|
|
||||||
|
/* we start with literal copy */
|
||||||
|
const uint8_t* anchor = ip;
|
||||||
|
ip += 2;
|
||||||
|
|
||||||
|
/* main loop */
|
||||||
|
while (FASTLZ_LIKELY(ip < ip_limit)) {
|
||||||
|
const uint8_t* ref;
|
||||||
|
uint32_t distance, cmp;
|
||||||
|
|
||||||
|
/* find potential match */
|
||||||
|
do {
|
||||||
|
seq = flz_readu32(ip) & 0xffffff;
|
||||||
|
hash = flz_hash(seq);
|
||||||
|
ref = ip_start + htab[hash];
|
||||||
|
htab[hash] = ip - ip_start;
|
||||||
|
distance = ip - ref;
|
||||||
|
cmp = FASTLZ_LIKELY(distance < MAX_FARDISTANCE) ? flz_readu32(ref) & 0xffffff : 0x1000000;
|
||||||
|
if (FASTLZ_UNLIKELY(ip >= ip_limit)) break;
|
||||||
|
++ip;
|
||||||
|
} while (seq != cmp);
|
||||||
|
|
||||||
|
if (FASTLZ_UNLIKELY(ip >= ip_limit)) break;
|
||||||
|
|
||||||
|
--ip;
|
||||||
|
|
||||||
|
/* far, needs at least 5-byte match */
|
||||||
|
if (distance >= MAX_L2_DISTANCE) {
|
||||||
|
if (ref[3] != ip[3] || ref[4] != ip[4]) {
|
||||||
|
++ip;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (FASTLZ_LIKELY(ip > anchor)) {
|
||||||
|
op = flz_literals(ip - anchor, anchor, op);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t len = flz_cmp(ref + 3, ip + 3, ip_bound);
|
||||||
|
op = flz2_match(len, distance, op);
|
||||||
|
|
||||||
|
/* update the hash at match boundary */
|
||||||
|
ip += len;
|
||||||
|
seq = flz_readu32(ip);
|
||||||
|
hash = flz_hash(seq & 0xffffff);
|
||||||
|
htab[hash] = ip++ - ip_start;
|
||||||
|
seq >>= 8;
|
||||||
|
hash = flz_hash(seq);
|
||||||
|
htab[hash] = ip++ - ip_start;
|
||||||
|
|
||||||
|
anchor = ip;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t copy = (uint8_t*)input + length - anchor;
|
||||||
|
op = flz_literals(copy, anchor, op);
|
||||||
|
|
||||||
|
/* marker for fastlz2 */
|
||||||
|
*(uint8_t*)output |= (1 << 5);
|
||||||
|
|
||||||
|
return op - (uint8_t*)output;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int fastlz2_decompress(const void* input, int length, void* output, int maxout) {
|
||||||
|
const uint8_t* ip = (const uint8_t*)input;
|
||||||
|
const uint8_t* ip_limit = ip + length;
|
||||||
|
const uint8_t* ip_bound = ip_limit - 2;
|
||||||
|
uint8_t* op = (uint8_t*)output;
|
||||||
|
uint8_t* op_limit = op + maxout;
|
||||||
|
uint32_t ctrl = (*ip++) & 31;
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
if (ctrl >= 32) {
|
||||||
|
uint32_t len = (ctrl >> 5) - 1;
|
||||||
|
uint32_t ofs = (ctrl & 31) << 8;
|
||||||
|
const uint8_t* ref = op - ofs - 1;
|
||||||
|
|
||||||
|
uint8_t code;
|
||||||
|
if (len == 7 - 1) do {
|
||||||
|
FASTLZ_BOUND_CHECK(ip <= ip_bound);
|
||||||
|
code = *ip++;
|
||||||
|
len += code;
|
||||||
|
} while (code == 255);
|
||||||
|
code = *ip++;
|
||||||
|
ref -= code;
|
||||||
|
len += 3;
|
||||||
|
|
||||||
|
/* match from 16-bit distance */
|
||||||
|
if (FASTLZ_UNLIKELY(code == 255))
|
||||||
|
if (FASTLZ_LIKELY(ofs == (31 << 8))) {
|
||||||
|
FASTLZ_BOUND_CHECK(ip < ip_bound);
|
||||||
|
ofs = (*ip++) << 8;
|
||||||
|
ofs += *ip++;
|
||||||
|
ref = op - ofs - MAX_L2_DISTANCE - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
FASTLZ_BOUND_CHECK(op + len <= op_limit);
|
||||||
|
FASTLZ_BOUND_CHECK(ref >= (uint8_t*)output);
|
||||||
|
fastlz_memmove(op, ref, len);
|
||||||
|
op += len;
|
||||||
|
} else {
|
||||||
|
ctrl++;
|
||||||
|
FASTLZ_BOUND_CHECK(op + ctrl <= op_limit);
|
||||||
|
FASTLZ_BOUND_CHECK(ip + ctrl <= ip_limit);
|
||||||
|
fastlz_memcpy(op, ip, ctrl);
|
||||||
|
ip += ctrl;
|
||||||
|
op += ctrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (FASTLZ_UNLIKELY(ip >= ip_limit)) break;
|
||||||
|
ctrl = *ip++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return op - (uint8_t*)output;
|
||||||
|
}
|
||||||
|
|
||||||
|
int fastlz_compress(const void* input, int length, void* output) {
|
||||||
|
/* for short block, choose fastlz1 */
|
||||||
|
if (length < 65536) return fastlz1_compress(input, length, output);
|
||||||
|
|
||||||
|
/* else... */
|
||||||
|
return fastlz2_compress(input, length, output);
|
||||||
|
}
|
||||||
|
|
||||||
|
int fastlz_decompress(const void* input, int length, void* output, int maxout) {
|
||||||
|
/* magic identifier for compression level */
|
||||||
|
int level = ((*(const uint8_t*)input) >> 5) + 1;
|
||||||
|
|
||||||
|
if (level == 1) return fastlz1_decompress(input, length, output, maxout);
|
||||||
|
if (level == 2) return fastlz2_decompress(input, length, output, maxout);
|
||||||
|
|
||||||
|
/* unknown level, trigger error */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int fastlz_compress_level(int level, const void* input, int length, void* output) {
|
||||||
|
if (level == 1) return fastlz1_compress(input, length, output);
|
||||||
|
if (level == 2) return fastlz2_compress(input, length, output);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma GCC diagnostic pop
|
||||||
97
FastLZ/fastlz.h
Normal file
97
FastLZ/fastlz.h
Normal file
@ -0,0 +1,97 @@
|
|||||||
|
/*
|
||||||
|
FastLZ - Byte-aligned LZ77 compression library
|
||||||
|
Copyright (C) 2005-2020 Ariya Hidayat <ariya.hidayat@gmail.com>
|
||||||
|
|
||||||
|
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 FASTLZ_H
|
||||||
|
#define FASTLZ_H
|
||||||
|
|
||||||
|
#define FASTLZ_VERSION 0x000500
|
||||||
|
|
||||||
|
#define FASTLZ_VERSION_MAJOR 0
|
||||||
|
#define FASTLZ_VERSION_MINOR 5
|
||||||
|
#define FASTLZ_VERSION_REVISION 0
|
||||||
|
|
||||||
|
#define FASTLZ_VERSION_STRING "0.5.0"
|
||||||
|
|
||||||
|
#if defined(__cplusplus)
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
Compress a block of data in the input buffer and returns the size of
|
||||||
|
compressed block. The size of input buffer is specified by length. The
|
||||||
|
minimum input buffer size is 16.
|
||||||
|
|
||||||
|
The output buffer must be at least 5% larger than the input buffer
|
||||||
|
and can not be smaller than 66 bytes.
|
||||||
|
|
||||||
|
If the input is not compressible, the return value might be larger than
|
||||||
|
length (input buffer size).
|
||||||
|
|
||||||
|
The input buffer and the output buffer can not overlap.
|
||||||
|
|
||||||
|
Compression level can be specified in parameter level. At the moment,
|
||||||
|
only level 1 and level 2 are supported.
|
||||||
|
Level 1 is the fastest compression and generally useful for short data.
|
||||||
|
Level 2 is slightly slower but it gives better compression ratio.
|
||||||
|
|
||||||
|
Note that the compressed data, regardless of the level, can always be
|
||||||
|
decompressed using the function fastlz_decompress below.
|
||||||
|
*/
|
||||||
|
|
||||||
|
int fastlz_compress_level(int level, const void* input, int length, void* output);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Decompress a block of compressed data and returns the size of the
|
||||||
|
decompressed block. If error occurs, e.g. the compressed data is
|
||||||
|
corrupted or the output buffer is not large enough, then 0 (zero)
|
||||||
|
will be returned instead.
|
||||||
|
|
||||||
|
The input buffer and the output buffer can not overlap.
|
||||||
|
|
||||||
|
Decompression is memory safe and guaranteed not to write the output buffer
|
||||||
|
more than what is specified in maxout.
|
||||||
|
|
||||||
|
Note that the decompression will always work, regardless of the
|
||||||
|
compression level specified in fastlz_compress_level above (when
|
||||||
|
producing the compressed block).
|
||||||
|
*/
|
||||||
|
|
||||||
|
int fastlz_decompress(const void* input, int length, void* output, int maxout);
|
||||||
|
|
||||||
|
/**
|
||||||
|
DEPRECATED.
|
||||||
|
|
||||||
|
This is similar to fastlz_compress_level above, but with the level
|
||||||
|
automatically chosen.
|
||||||
|
|
||||||
|
This function is deprecated and it will be completely removed in some future
|
||||||
|
version.
|
||||||
|
*/
|
||||||
|
|
||||||
|
int fastlz_compress(const void* input, int length, void* output);
|
||||||
|
|
||||||
|
#if defined(__cplusplus)
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* FASTLZ_H */
|
||||||
13
FastLZ/tests/Makefile
Normal file
13
FastLZ/tests/Makefile
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
CFLAGS?=-Wall -std=c90
|
||||||
|
TEST_ROUNDTRIP?=./test_roundtrip
|
||||||
|
|
||||||
|
all: roundtrip
|
||||||
|
|
||||||
|
roundtrip: test_roundtrip
|
||||||
|
$(TEST_ROUNDTRIP)
|
||||||
|
|
||||||
|
test_roundtrip: test_roundtrip.c ../fastlz.c refimpl.c
|
||||||
|
$(CC) -o $(TEST_ROUNDTRIP) $(CFLAGS) -I.. test_roundtrip.c ../fastlz.c refimpl.c
|
||||||
|
|
||||||
|
clean :
|
||||||
|
$(RM) $(TEST_ROUNDTRIP) *.o
|
||||||
14
FastLZ/tests/Makefile.win
Executable file
14
FastLZ/tests/Makefile.win
Executable file
@ -0,0 +1,14 @@
|
|||||||
|
CC=cl.exe
|
||||||
|
CFLAGS=/Wall /Za
|
||||||
|
RM=del
|
||||||
|
|
||||||
|
TEST_ROUNDTRIP=test_roundtrip.exe
|
||||||
|
|
||||||
|
all: roundtrip
|
||||||
|
|
||||||
|
roundtrip: test_roundtrip.c ../fastlz.c refimpl.c
|
||||||
|
$(CC) -o $(TEST_ROUNDTRIP) $(CFLAGS) -I.. test_roundtrip.c ../fastlz.c refimpl.c
|
||||||
|
$(TEST_ROUNDTRIP)
|
||||||
|
|
||||||
|
clean :
|
||||||
|
$(RM) $(TEST_ROUNDTRIP) *.obj
|
||||||
103
FastLZ/tests/refimpl.c
Normal file
103
FastLZ/tests/refimpl.c
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Workaround for DJGPP to find uint8_t, uint16_t, etc.
|
||||||
|
*/
|
||||||
|
#if defined(__MSDOS__) && defined(__GNUC__)
|
||||||
|
#include <stdint-gcc.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void REF_Level1_decompress(const uint8_t* input, int length, uint8_t* output) {
|
||||||
|
int src = 0;
|
||||||
|
int dest = 0;
|
||||||
|
while (src < length) {
|
||||||
|
int type = input[src] >> 5;
|
||||||
|
if (type == 0) {
|
||||||
|
/* literal run */
|
||||||
|
int run = 1 + input[src];
|
||||||
|
src = src + 1;
|
||||||
|
while (run > 0) {
|
||||||
|
output[dest] = input[src];
|
||||||
|
src = src + 1;
|
||||||
|
dest = dest + 1;
|
||||||
|
run = run - 1;
|
||||||
|
}
|
||||||
|
} else if (type < 7) {
|
||||||
|
/* short match */
|
||||||
|
int ofs = 256 * (input[src] & 31) + input[src + 1];
|
||||||
|
int len = 2 + (input[src] >> 5);
|
||||||
|
src = src + 2;
|
||||||
|
int ref = dest - ofs - 1;
|
||||||
|
while (len > 0) {
|
||||||
|
output[dest] = output[ref];
|
||||||
|
ref = ref + 1;
|
||||||
|
dest = dest + 1;
|
||||||
|
len = len - 1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* long match */
|
||||||
|
int ofs = 256 * (input[src] & 31) + input[src + 2];
|
||||||
|
int len = 9 + input[src + 1];
|
||||||
|
src = src + 3;
|
||||||
|
int ref = dest - ofs - 1;
|
||||||
|
while (len > 0) {
|
||||||
|
output[dest] = output[ref];
|
||||||
|
ref = ref + 1;
|
||||||
|
dest = dest + 1;
|
||||||
|
len = len - 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void REF_Level2_decompress(const uint8_t* input, int length, uint8_t* output) {
|
||||||
|
int src = 0;
|
||||||
|
int dest = 0;
|
||||||
|
while (src < length) {
|
||||||
|
int type = input[src] >> 5;
|
||||||
|
if (type == 0) {
|
||||||
|
/* literal run */
|
||||||
|
int run = 1 + input[src];
|
||||||
|
src = src + 1;
|
||||||
|
while (run > 0) {
|
||||||
|
output[dest] = input[src];
|
||||||
|
src = src + 1;
|
||||||
|
dest = dest + 1;
|
||||||
|
run = run - 1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
int next = 2;
|
||||||
|
int len = 2 + (input[src] >> 5);
|
||||||
|
if (len == 9) {
|
||||||
|
/* long match */
|
||||||
|
next = next + 1;
|
||||||
|
len = len + input[src + 1];
|
||||||
|
if (len == 9 + 255) {
|
||||||
|
/* Gamma code for match length */
|
||||||
|
int nn = input[src + 1];
|
||||||
|
while (nn == 255) {
|
||||||
|
nn = input[src + next - 1];
|
||||||
|
next = next + 1;
|
||||||
|
len += nn;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int ofs = 256 * (input[src] & 31) + input[src + next - 1];
|
||||||
|
if (ofs == 8191) {
|
||||||
|
/* match from 16-bit distance */
|
||||||
|
ofs += 256 * input[src + next] + input[src + next + 1];
|
||||||
|
next = next + 2;
|
||||||
|
}
|
||||||
|
src = src + next;
|
||||||
|
|
||||||
|
int ref = dest - ofs - 1;
|
||||||
|
while (len > 0) {
|
||||||
|
output[dest] = output[ref];
|
||||||
|
ref = ref + 1;
|
||||||
|
dest = dest + 1;
|
||||||
|
len = len - 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
451
FastLZ/tests/test_roundtrip.c
Normal file
451
FastLZ/tests/test_roundtrip.c
Normal file
@ -0,0 +1,451 @@
|
|||||||
|
/*
|
||||||
|
FastLZ - Byte-aligned LZ77 compression library
|
||||||
|
Copyright (C) 2005-2020 Ariya Hidayat <ariya.hidayat@gmail.com>
|
||||||
|
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "fastlz.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Workaround for DJGPP to find uint8_t, uint16_t, etc.
|
||||||
|
*/
|
||||||
|
#if defined(__MSDOS__) && defined(__GNUC__)
|
||||||
|
#include <stdint-gcc.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define LOG
|
||||||
|
#undef LOG
|
||||||
|
|
||||||
|
int compare(const char* name, const uint8_t* a, const uint8_t* b, int size) {
|
||||||
|
int bad = 0;
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < size; ++i) {
|
||||||
|
if (a[i] != b[i]) {
|
||||||
|
bad = 1;
|
||||||
|
printf("Error on %s!\n", name);
|
||||||
|
printf("Different at index %d: expecting %02x,actual %02x\n", i, a[i], b[i]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return bad;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if !defined(__MSDOS__)
|
||||||
|
#define MAX_FILE_SIZE (100 * 1024 * 1024)
|
||||||
|
#else
|
||||||
|
#define MAX_FILE_SIZE (32 * 1024 * 1024)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* prototype, implemented in refimpl.c */
|
||||||
|
void REF_Level1_decompress(const uint8_t* input, int length, uint8_t* output);
|
||||||
|
void REF_Level2_decompress(const uint8_t* input, int length, uint8_t* output);
|
||||||
|
|
||||||
|
/*
|
||||||
|
Same as test_roundtrip_level1 EXCEPT that the decompression is carried out
|
||||||
|
using the highly-simplified, unoptimized vanilla reference decompressor.
|
||||||
|
*/
|
||||||
|
|
||||||
|
void test_ref_decompressor_level1(const char* name, const char* file_name) {
|
||||||
|
#ifdef LOG
|
||||||
|
printf("Processing %s...\n", name);
|
||||||
|
#endif
|
||||||
|
FILE* f = fopen(file_name, "rb");
|
||||||
|
if (!f) {
|
||||||
|
printf("Error: can not open %s!\n", file_name);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
fseek(f, 0L, SEEK_END);
|
||||||
|
long file_size = ftell(f);
|
||||||
|
rewind(f);
|
||||||
|
|
||||||
|
#ifdef LOG
|
||||||
|
printf("Size is %ld bytes.\n", file_size);
|
||||||
|
#endif
|
||||||
|
if (file_size > MAX_FILE_SIZE) {
|
||||||
|
fclose(f);
|
||||||
|
printf("%25s %10ld [skipped, file too big]\n", name, file_size);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t* file_buffer = malloc(file_size);
|
||||||
|
long read = fread(file_buffer, 1, file_size, f);
|
||||||
|
fclose(f);
|
||||||
|
if (read != file_size) {
|
||||||
|
free(file_buffer);
|
||||||
|
printf("Error: only read %ld bytes!\n", read);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef LOG
|
||||||
|
printf("Compressing. Please wait...\n");
|
||||||
|
#endif
|
||||||
|
uint8_t* compressed_buffer = malloc(1.05 * file_size);
|
||||||
|
int compressed_size = fastlz_compress_level(1, file_buffer, file_size, compressed_buffer);
|
||||||
|
double ratio = (100.0 * compressed_size) / file_size;
|
||||||
|
#ifdef LOG
|
||||||
|
printf("Compressing was completed: %ld -> %ld (%.2f%%)\n", file_size, compressed_size, ratio);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef LOG
|
||||||
|
printf("Decompressing. Please wait...\n");
|
||||||
|
#endif
|
||||||
|
uint8_t* uncompressed_buffer = malloc(file_size);
|
||||||
|
if (uncompressed_buffer == NULL) {
|
||||||
|
printf("%25s %10ld -> %10d (%.2f%%) skipped, can't decompress\n", name, file_size, compressed_size, ratio);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
memset(uncompressed_buffer, '-', file_size);
|
||||||
|
REF_Level1_decompress(compressed_buffer, compressed_size, uncompressed_buffer);
|
||||||
|
#ifdef LOG
|
||||||
|
printf("Comparing. Please wait...\n");
|
||||||
|
#endif
|
||||||
|
int result = compare(file_name, file_buffer, uncompressed_buffer, file_size);
|
||||||
|
if (result == 1) {
|
||||||
|
free(uncompressed_buffer);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
free(file_buffer);
|
||||||
|
free(compressed_buffer);
|
||||||
|
free(uncompressed_buffer);
|
||||||
|
#ifdef LOG
|
||||||
|
printf("OK.\n");
|
||||||
|
#else
|
||||||
|
printf("%25s %10ld -> %10d (%.2f%%)\n", name, file_size, compressed_size, ratio);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Same as test_roundtrip_level2 EXCEPT that the decompression is carried out
|
||||||
|
using the highly-simplified, unoptimized vanilla reference decompressor.
|
||||||
|
*/
|
||||||
|
|
||||||
|
void test_ref_decompressor_level2(const char* name, const char* file_name) {
|
||||||
|
#ifdef LOG
|
||||||
|
printf("Processing %s...\n", name);
|
||||||
|
#endif
|
||||||
|
FILE* f = fopen(file_name, "rb");
|
||||||
|
if (!f) {
|
||||||
|
printf("Error: can not open %s!\n", file_name);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
fseek(f, 0L, SEEK_END);
|
||||||
|
long file_size = ftell(f);
|
||||||
|
rewind(f);
|
||||||
|
|
||||||
|
#ifdef LOG
|
||||||
|
printf("Size is %ld bytes.\n", file_size);
|
||||||
|
#endif
|
||||||
|
if (file_size > MAX_FILE_SIZE) {
|
||||||
|
fclose(f);
|
||||||
|
printf("%25s %10ld [skipped, file too big]\n", name, file_size);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t* file_buffer = malloc(file_size);
|
||||||
|
long read = fread(file_buffer, 1, file_size, f);
|
||||||
|
fclose(f);
|
||||||
|
if (read != file_size) {
|
||||||
|
free(file_buffer);
|
||||||
|
printf("Error: only read %ld bytes!\n", read);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef LOG
|
||||||
|
printf("Compressing. Please wait...\n");
|
||||||
|
#endif
|
||||||
|
uint8_t* compressed_buffer = malloc(1.05 * file_size);
|
||||||
|
int compressed_size = fastlz_compress_level(2, file_buffer, file_size, compressed_buffer);
|
||||||
|
double ratio = (100.0 * compressed_size) / file_size;
|
||||||
|
#ifdef LOG
|
||||||
|
printf("Compressing was completed: %ld -> %ld (%.2f%%)\n", file_size, compressed_size, ratio);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef LOG
|
||||||
|
printf("Decompressing. Please wait...\n");
|
||||||
|
#endif
|
||||||
|
uint8_t* uncompressed_buffer = malloc(file_size);
|
||||||
|
if (uncompressed_buffer == NULL) {
|
||||||
|
printf("%25s %10ld -> %10d (%.2f%%) skipped, can't decompress\n", name, file_size, compressed_size, ratio);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
memset(uncompressed_buffer, '-', file_size);
|
||||||
|
|
||||||
|
/* intentionally mask out the block tag */
|
||||||
|
compressed_buffer[0] = compressed_buffer[0] & 31;
|
||||||
|
|
||||||
|
REF_Level2_decompress(compressed_buffer, compressed_size, uncompressed_buffer);
|
||||||
|
#ifdef LOG
|
||||||
|
printf("Comparing. Please wait...\n");
|
||||||
|
#endif
|
||||||
|
int result = compare(file_name, file_buffer, uncompressed_buffer, file_size);
|
||||||
|
if (result == 1) {
|
||||||
|
free(uncompressed_buffer);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
free(file_buffer);
|
||||||
|
free(compressed_buffer);
|
||||||
|
free(uncompressed_buffer);
|
||||||
|
#ifdef LOG
|
||||||
|
printf("OK.\n");
|
||||||
|
#else
|
||||||
|
printf("%25s %10ld -> %10d (%.2f%%)\n", name, file_size, compressed_size, ratio);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Read the content of the file.
|
||||||
|
Compress it first using the Level 1 compressor.
|
||||||
|
Decompress the output with Level 1 decompressor.
|
||||||
|
Compare the result with the original file content.
|
||||||
|
*/
|
||||||
|
void test_roundtrip_level1(const char* name, const char* file_name) {
|
||||||
|
#ifdef LOG
|
||||||
|
printf("Processing %s...\n", name);
|
||||||
|
#endif
|
||||||
|
FILE* f = fopen(file_name, "rb");
|
||||||
|
if (!f) {
|
||||||
|
printf("Error: can not open %s!\n", file_name);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
fseek(f, 0L, SEEK_END);
|
||||||
|
long file_size = ftell(f);
|
||||||
|
rewind(f);
|
||||||
|
|
||||||
|
#ifdef LOG
|
||||||
|
printf("Size is %ld bytes.\n", file_size);
|
||||||
|
#endif
|
||||||
|
if (file_size > MAX_FILE_SIZE) {
|
||||||
|
fclose(f);
|
||||||
|
printf("%25s %10ld [skipped, file too big]\n", name, file_size);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t* file_buffer = malloc(file_size);
|
||||||
|
long read = fread(file_buffer, 1, file_size, f);
|
||||||
|
fclose(f);
|
||||||
|
if (read != file_size) {
|
||||||
|
free(file_buffer);
|
||||||
|
printf("Error: only read %ld bytes!\n", read);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef LOG
|
||||||
|
printf("Compressing. Please wait...\n");
|
||||||
|
#endif
|
||||||
|
uint8_t* compressed_buffer = malloc(1.05 * file_size);
|
||||||
|
int compressed_size = fastlz_compress_level(1, file_buffer, file_size, compressed_buffer);
|
||||||
|
double ratio = (100.0 * compressed_size) / file_size;
|
||||||
|
#ifdef LOG
|
||||||
|
printf("Compressing was completed: %ld -> %ld (%.2f%%)\n", file_size, compressed_size, ratio);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef LOG
|
||||||
|
printf("Decompressing. Please wait...\n");
|
||||||
|
#endif
|
||||||
|
uint8_t* uncompressed_buffer = malloc(file_size);
|
||||||
|
if (uncompressed_buffer == NULL) {
|
||||||
|
printf("%25s %10ld -> %10d (%.2f%%) skipped, can't decompress\n", name, file_size, compressed_size, ratio);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
memset(uncompressed_buffer, '-', file_size);
|
||||||
|
fastlz_decompress(compressed_buffer, compressed_size, uncompressed_buffer, file_size);
|
||||||
|
#ifdef LOG
|
||||||
|
printf("Comparing. Please wait...\n");
|
||||||
|
#endif
|
||||||
|
int result = compare(file_name, file_buffer, uncompressed_buffer, file_size);
|
||||||
|
if (result == 1) {
|
||||||
|
free(uncompressed_buffer);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
free(file_buffer);
|
||||||
|
free(compressed_buffer);
|
||||||
|
free(uncompressed_buffer);
|
||||||
|
#ifdef LOG
|
||||||
|
printf("OK.\n");
|
||||||
|
#else
|
||||||
|
printf("%25s %10ld -> %10d (%.2f%%)\n", name, file_size, compressed_size, ratio);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Read the content of the file.
|
||||||
|
Compress it first using the Level 2 compressor.
|
||||||
|
Decompress the output with Level 2 decompressor.
|
||||||
|
Compare the result with the original file content.
|
||||||
|
*/
|
||||||
|
void test_roundtrip_level2(const char* name, const char* file_name) {
|
||||||
|
#ifdef LOG
|
||||||
|
printf("Processing %s...\n", name);
|
||||||
|
#endif
|
||||||
|
FILE* f = fopen(file_name, "rb");
|
||||||
|
if (!f) {
|
||||||
|
printf("Error: can not open %s!\n", file_name);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
fseek(f, 0L, SEEK_END);
|
||||||
|
long file_size = ftell(f);
|
||||||
|
rewind(f);
|
||||||
|
|
||||||
|
#ifdef LOG
|
||||||
|
printf("Size is %ld bytes.\n", file_size);
|
||||||
|
#endif
|
||||||
|
if (file_size > MAX_FILE_SIZE) {
|
||||||
|
fclose(f);
|
||||||
|
printf("%25s %10ld [skipped, file too big]\n", name, file_size);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t* file_buffer = malloc(file_size);
|
||||||
|
long read = fread(file_buffer, 1, file_size, f);
|
||||||
|
fclose(f);
|
||||||
|
if (read != file_size) {
|
||||||
|
free(file_buffer);
|
||||||
|
printf("Error: only read %ld bytes!\n", read);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef LOG
|
||||||
|
printf("Compressing. Please wait...\n");
|
||||||
|
#endif
|
||||||
|
uint8_t* compressed_buffer = malloc(1.05 * file_size);
|
||||||
|
int compressed_size = fastlz_compress_level(2, file_buffer, file_size, compressed_buffer);
|
||||||
|
double ratio = (100.0 * compressed_size) / file_size;
|
||||||
|
#ifdef LOG
|
||||||
|
printf("Compressing was completed: %ld -> %ld (%.2f%%)\n", file_size, compressed_size, ratio);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef LOG
|
||||||
|
printf("Decompressing. Please wait...\n");
|
||||||
|
#endif
|
||||||
|
uint8_t* uncompressed_buffer = malloc(file_size);
|
||||||
|
if (uncompressed_buffer == NULL) {
|
||||||
|
free(file_buffer);
|
||||||
|
free(compressed_buffer);
|
||||||
|
printf("%25s %10ld -> %10d (%.2f%%) skipped, can't decompress OOM\n", name, file_size, compressed_size, ratio);
|
||||||
|
exit(1);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
memset(uncompressed_buffer, '-', file_size);
|
||||||
|
fastlz_decompress(compressed_buffer, compressed_size, uncompressed_buffer, file_size);
|
||||||
|
#ifdef LOG
|
||||||
|
printf("Comparing. Please wait...\n");
|
||||||
|
#endif
|
||||||
|
int result = compare(file_name, file_buffer, uncompressed_buffer, file_size);
|
||||||
|
if (result == 1) {
|
||||||
|
free(uncompressed_buffer);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
free(file_buffer);
|
||||||
|
free(compressed_buffer);
|
||||||
|
free(uncompressed_buffer);
|
||||||
|
#ifdef LOG
|
||||||
|
printf("OK.\n");
|
||||||
|
#else
|
||||||
|
printf("%25s %10ld -> %10d (%.2f%%)\n", name, file_size, compressed_size, ratio);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char** argv) {
|
||||||
|
const char* default_prefix = "../compression-corpus/";
|
||||||
|
const char* names[] = {"canterbury/alice29.txt",
|
||||||
|
"canterbury/asyoulik.txt",
|
||||||
|
"canterbury/cp.html",
|
||||||
|
"canterbury/fields.c",
|
||||||
|
"canterbury/grammar.lsp",
|
||||||
|
"canterbury/kennedy.xls",
|
||||||
|
"canterbury/lcet10.txt",
|
||||||
|
"canterbury/plrabn12.txt",
|
||||||
|
"canterbury/ptt5",
|
||||||
|
"canterbury/sum",
|
||||||
|
"canterbury/xargs.1",
|
||||||
|
"silesia/dickens",
|
||||||
|
"silesia/mozilla",
|
||||||
|
"silesia/mr",
|
||||||
|
"silesia/nci",
|
||||||
|
"silesia/ooffice",
|
||||||
|
"silesia/osdb",
|
||||||
|
"silesia/reymont",
|
||||||
|
"silesia/samba",
|
||||||
|
"silesia/sao",
|
||||||
|
"silesia/webster",
|
||||||
|
"silesia/x-ray",
|
||||||
|
"silesia/xml",
|
||||||
|
"enwik/enwik8.txt"};
|
||||||
|
|
||||||
|
const char* prefix = (argc == 2) ? argv[1] : default_prefix;
|
||||||
|
|
||||||
|
const int count = sizeof(names) / sizeof(names[0]);
|
||||||
|
int i;
|
||||||
|
|
||||||
|
printf("Test reference decompressor for Level 1\n\n");
|
||||||
|
for (i = 0; i < count; ++i) {
|
||||||
|
const char* name = names[i];
|
||||||
|
char* filename = malloc(strlen(prefix) + strlen(name) + 1);
|
||||||
|
strcpy(filename, prefix);
|
||||||
|
strcat(filename, name);
|
||||||
|
test_ref_decompressor_level1(name, filename);
|
||||||
|
free(filename);
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
|
||||||
|
printf("Test reference decompressor for Level 2\n\n");
|
||||||
|
for (i = 0; i < count; ++i) {
|
||||||
|
const char* name = names[i];
|
||||||
|
char* filename = malloc(strlen(prefix) + strlen(name) + 1);
|
||||||
|
strcpy(filename, prefix);
|
||||||
|
strcat(filename, name);
|
||||||
|
test_ref_decompressor_level2(name, filename);
|
||||||
|
free(filename);
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
|
||||||
|
printf("Test round-trip for Level 1\n\n");
|
||||||
|
for (i = 0; i < count; ++i) {
|
||||||
|
const char* name = names[i];
|
||||||
|
char* filename = malloc(strlen(prefix) + strlen(name) + 1);
|
||||||
|
strcpy(filename, prefix);
|
||||||
|
strcat(filename, name);
|
||||||
|
test_roundtrip_level1(name, filename);
|
||||||
|
free(filename);
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
|
||||||
|
printf("Test round-trip for Level 2\n\n");
|
||||||
|
for (i = 0; i < count; ++i) {
|
||||||
|
const char* name = names[i];
|
||||||
|
char* filename = malloc(strlen(prefix) + strlen(name) + 1);
|
||||||
|
strcpy(filename, prefix);
|
||||||
|
strcat(filename, name);
|
||||||
|
test_roundtrip_level2(name, filename);
|
||||||
|
free(filename);
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
4
FastLZ/tools/format-code.sh
Executable file
4
FastLZ/tools/format-code.sh
Executable file
@ -0,0 +1,4 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
cwd=$(pwd)
|
||||||
|
clang-format-6.0 -i --style='{BasedOnStyle: "google", ColumnLimit: 120}' $cwd/*.h $cwd/*.c $cwd/tests/*.c $cwd/examples/*.c
|
||||||
7
Makefile
7
Makefile
@ -29,6 +29,11 @@ prepare:
|
|||||||
$(PWD)/scripts/build-gcc.sh; \
|
$(PWD)/scripts/build-gcc.sh; \
|
||||||
cd ..; \
|
cd ..; \
|
||||||
fi
|
fi
|
||||||
|
if [ ! -e FastLZ/examples/6pack ] || [ ! -e FastLZ/examples/6unpack ]; then \
|
||||||
|
cd FastLZ/examples; \
|
||||||
|
make; \
|
||||||
|
cd ..; \
|
||||||
|
fi
|
||||||
|
|
||||||
cleanall:
|
cleanall:
|
||||||
make clean
|
make clean
|
||||||
@ -38,7 +43,7 @@ clean:
|
|||||||
make -C kernel ARCH=$(ARCH) ROOT=$(PWD) clean
|
make -C kernel ARCH=$(ARCH) ROOT=$(PWD) clean
|
||||||
make -C user ARCH=$(ARCH) ROOT=$(PWD) clean
|
make -C user ARCH=$(ARCH) ROOT=$(PWD) clean
|
||||||
make -C ulib ARCH=$(ARCH) ROOT=$(PWD) clean
|
make -C ulib ARCH=$(ARCH) ROOT=$(PWD) clean
|
||||||
rm -f mop2.iso base.img disk.hdd
|
rm -f mop2.iso base.img disk.hdd base.img.lz77
|
||||||
|
|
||||||
base:
|
base:
|
||||||
./scripts/mkbaseimg.sh
|
./scripts/mkbaseimg.sh
|
||||||
|
|||||||
213
README.md
Normal file
213
README.md
Normal file
@ -0,0 +1,213 @@
|
|||||||
|
# MOP2 - My OS project (2)
|
||||||
|
|
||||||
|
It's no. 2, because version no. 1 failed...
|
||||||
|
|
||||||
|
## Building
|
||||||
|
|
||||||
|
### Prepare stuff
|
||||||
|
|
||||||
|
```bash
|
||||||
|
make prepare
|
||||||
|
```
|
||||||
|
|
||||||
|
WARNING: This will take a while, since we're building an entire GCC toolchain + BinUtils.
|
||||||
|
|
||||||
|
### For development
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./scripts/devel.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
Will generate an `mop2.iso` image and a `disk.hdd`. You can run both live-iso and drive-installed
|
||||||
|
versions via `qemu-system-x86_64`.
|
||||||
|
|
||||||
|
## Running
|
||||||
|
|
||||||
|
There are two variants for the live-iso and drive-installed systems:
|
||||||
|
- `./run/qemu-x86_64-hdd.sh`
|
||||||
|
- `./run/qemu-x86_64-iso.sh`
|
||||||
|
|
||||||
|
## Blog posts
|
||||||
|
|
||||||
|
Sometimes I post updated on my blog regarding the project: [https://www.kamkow1lair.pl/]
|
||||||
|
|
||||||
|
## Screenshots
|
||||||
|
|
||||||
|

|
||||||
|

|
||||||
|

|
||||||
|
|
||||||
|
## Legal
|
||||||
|
|
||||||
|
See `legal/` for the licenses of projects that where used as refrences. The directory also contains
|
||||||
|
licenses for used libraries.
|
||||||
|
|
||||||
|
LICENSE FOR MOP2:
|
||||||
|
|
||||||
|
```text
|
||||||
|
GNU LESSER GENERAL PUBLIC LICENSE
|
||||||
|
Version 3, 29 June 2007
|
||||||
|
|
||||||
|
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
|
||||||
|
Everyone is permitted to copy and distribute verbatim copies
|
||||||
|
of this license document, but changing it is not allowed.
|
||||||
|
|
||||||
|
|
||||||
|
This version of the GNU Lesser General Public License incorporates
|
||||||
|
the terms and conditions of version 3 of the GNU General Public
|
||||||
|
License, supplemented by the additional permissions listed below.
|
||||||
|
|
||||||
|
0. Additional Definitions.
|
||||||
|
|
||||||
|
As used herein, "this License" refers to version 3 of the GNU Lesser
|
||||||
|
General Public License, and the "GNU GPL" refers to version 3 of the GNU
|
||||||
|
General Public License.
|
||||||
|
|
||||||
|
"The Library" refers to a covered work governed by this License,
|
||||||
|
other than an Application or a Combined Work as defined below.
|
||||||
|
|
||||||
|
An "Application" is any work that makes use of an interface provided
|
||||||
|
by the Library, but which is not otherwise based on the Library.
|
||||||
|
Defining a subclass of a class defined by the Library is deemed a mode
|
||||||
|
of using an interface provided by the Library.
|
||||||
|
|
||||||
|
A "Combined Work" is a work produced by combining or linking an
|
||||||
|
Application with the Library. The particular version of the Library
|
||||||
|
with which the Combined Work was made is also called the "Linked
|
||||||
|
Version".
|
||||||
|
|
||||||
|
The "Minimal Corresponding Source" for a Combined Work means the
|
||||||
|
Corresponding Source for the Combined Work, excluding any source code
|
||||||
|
for portions of the Combined Work that, considered in isolation, are
|
||||||
|
based on the Application, and not on the Linked Version.
|
||||||
|
|
||||||
|
The "Corresponding Application Code" for a Combined Work means the
|
||||||
|
object code and/or source code for the Application, including any data
|
||||||
|
and utility programs needed for reproducing the Combined Work from the
|
||||||
|
Application, but excluding the System Libraries of the Combined Work.
|
||||||
|
|
||||||
|
1. Exception to Section 3 of the GNU GPL.
|
||||||
|
|
||||||
|
You may convey a covered work under sections 3 and 4 of this License
|
||||||
|
without being bound by section 3 of the GNU GPL.
|
||||||
|
|
||||||
|
2. Conveying Modified Versions.
|
||||||
|
|
||||||
|
If you modify a copy of the Library, and, in your modifications, a
|
||||||
|
facility refers to a function or data to be supplied by an Application
|
||||||
|
that uses the facility (other than as an argument passed when the
|
||||||
|
facility is invoked), then you may convey a copy of the modified
|
||||||
|
version:
|
||||||
|
|
||||||
|
a) under this License, provided that you make a good faith effort to
|
||||||
|
ensure that, in the event an Application does not supply the
|
||||||
|
function or data, the facility still operates, and performs
|
||||||
|
whatever part of its purpose remains meaningful, or
|
||||||
|
|
||||||
|
b) under the GNU GPL, with none of the additional permissions of
|
||||||
|
this License applicable to that copy.
|
||||||
|
|
||||||
|
3. Object Code Incorporating Material from Library Header Files.
|
||||||
|
|
||||||
|
The object code form of an Application may incorporate material from
|
||||||
|
a header file that is part of the Library. You may convey such object
|
||||||
|
code under terms of your choice, provided that, if the incorporated
|
||||||
|
material is not limited to numerical parameters, data structure
|
||||||
|
layouts and accessors, or small macros, inline functions and templates
|
||||||
|
(ten or fewer lines in length), you do both of the following:
|
||||||
|
|
||||||
|
a) Give prominent notice with each copy of the object code that the
|
||||||
|
Library is used in it and that the Library and its use are
|
||||||
|
covered by this License.
|
||||||
|
|
||||||
|
b) Accompany the object code with a copy of the GNU GPL and this license
|
||||||
|
document.
|
||||||
|
|
||||||
|
4. Combined Works.
|
||||||
|
|
||||||
|
You may convey a Combined Work under terms of your choice that,
|
||||||
|
taken together, effectively do not restrict modification of the
|
||||||
|
portions of the Library contained in the Combined Work and reverse
|
||||||
|
engineering for debugging such modifications, if you also do each of
|
||||||
|
the following:
|
||||||
|
|
||||||
|
a) Give prominent notice with each copy of the Combined Work that
|
||||||
|
the Library is used in it and that the Library and its use are
|
||||||
|
covered by this License.
|
||||||
|
|
||||||
|
b) Accompany the Combined Work with a copy of the GNU GPL and this license
|
||||||
|
document.
|
||||||
|
|
||||||
|
c) For a Combined Work that displays copyright notices during
|
||||||
|
execution, include the copyright notice for the Library among
|
||||||
|
these notices, as well as a reference directing the user to the
|
||||||
|
copies of the GNU GPL and this license document.
|
||||||
|
|
||||||
|
d) Do one of the following:
|
||||||
|
|
||||||
|
0) Convey the Minimal Corresponding Source under the terms of this
|
||||||
|
License, and the Corresponding Application Code in a form
|
||||||
|
suitable for, and under terms that permit, the user to
|
||||||
|
recombine or relink the Application with a modified version of
|
||||||
|
the Linked Version to produce a modified Combined Work, in the
|
||||||
|
manner specified by section 6 of the GNU GPL for conveying
|
||||||
|
Corresponding Source.
|
||||||
|
|
||||||
|
1) Use a suitable shared library mechanism for linking with the
|
||||||
|
Library. A suitable mechanism is one that (a) uses at run time
|
||||||
|
a copy of the Library already present on the user's computer
|
||||||
|
system, and (b) will operate properly with a modified version
|
||||||
|
of the Library that is interface-compatible with the Linked
|
||||||
|
Version.
|
||||||
|
|
||||||
|
e) Provide Installation Information, but only if you would otherwise
|
||||||
|
be required to provide such information under section 6 of the
|
||||||
|
GNU GPL, and only to the extent that such information is
|
||||||
|
necessary to install and execute a modified version of the
|
||||||
|
Combined Work produced by recombining or relinking the
|
||||||
|
Application with a modified version of the Linked Version. (If
|
||||||
|
you use option 4d0, the Installation Information must accompany
|
||||||
|
the Minimal Corresponding Source and Corresponding Application
|
||||||
|
Code. If you use option 4d1, you must provide the Installation
|
||||||
|
Information in the manner specified by section 6 of the GNU GPL
|
||||||
|
for conveying Corresponding Source.)
|
||||||
|
|
||||||
|
5. Combined Libraries.
|
||||||
|
|
||||||
|
You may place library facilities that are a work based on the
|
||||||
|
Library side by side in a single library together with other library
|
||||||
|
facilities that are not Applications and are not covered by this
|
||||||
|
License, and convey such a combined library under terms of your
|
||||||
|
choice, if you do both of the following:
|
||||||
|
|
||||||
|
a) Accompany the combined library with a copy of the same work based
|
||||||
|
on the Library, uncombined with any other library facilities,
|
||||||
|
conveyed under the terms of this License.
|
||||||
|
|
||||||
|
b) Give prominent notice with the combined library that part of it
|
||||||
|
is a work based on the Library, and explaining where to find the
|
||||||
|
accompanying uncombined form of the same work.
|
||||||
|
|
||||||
|
6. Revised Versions of the GNU Lesser General Public License.
|
||||||
|
|
||||||
|
The Free Software Foundation may publish revised and/or new versions
|
||||||
|
of the GNU Lesser General Public License from time to time. Such new
|
||||||
|
versions will be similar in spirit to the present version, but may
|
||||||
|
differ in detail to address new problems or concerns.
|
||||||
|
|
||||||
|
Each version is given a distinguishing version number. If the
|
||||||
|
Library as you received it specifies that a certain numbered version
|
||||||
|
of the GNU Lesser General Public License "or any later version"
|
||||||
|
applies to it, you have the option of following the terms and
|
||||||
|
conditions either of that published version or of any later version
|
||||||
|
published by the Free Software Foundation. If the Library as you
|
||||||
|
received it does not specify a version number of the GNU Lesser
|
||||||
|
General Public License, you may choose any version of the GNU Lesser
|
||||||
|
General Public License ever published by the Free Software Foundation.
|
||||||
|
|
||||||
|
If the Library as you received it specifies that a proxy can decide
|
||||||
|
whether future versions of the GNU Lesser General Public License shall
|
||||||
|
apply, that proxy's public statement of acceptance of any version is
|
||||||
|
permanent authorization for you to choose that version for the
|
||||||
|
Library.
|
||||||
|
```
|
||||||
@ -1,3 +1,7 @@
|
|||||||
print 'Mounting filesystems...\n'
|
print 'Mounting filesystems...\n'
|
||||||
setlogcmds yes
|
setlogcmds yes
|
||||||
$fs mount -mp uhome -fs LittleFS -dev atasd-ch0-M-part2 -fmt no
|
|
||||||
|
# MOUNTPOINT FILESYSTEM DEVICE NAME DO FORMATTING
|
||||||
|
|
||||||
|
$fs mount -mp uhome -fs LittleFS -dev atasd0mp2 -fmt no
|
||||||
|
$fs mount -mp sys -fs FAT16 -dev atasd0mp1 -fmt no
|
||||||
|
|||||||
@ -1,2 +1,3 @@
|
|||||||
|
# Create an $alias out of basenames of each entry in base:/bin
|
||||||
eachfile !.gitkeep base:/bin \
|
eachfile !.gitkeep base:/bin \
|
||||||
mkaliasbn &EF-ELEM
|
mkaliasbn &EF-ELEM
|
||||||
|
|||||||
115
kernel/FastLZ/6unpack_mem.c
Normal file
115
kernel/FastLZ/6unpack_mem.c
Normal file
@ -0,0 +1,115 @@
|
|||||||
|
#include <stdint.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include "FastLZ/fastlz.h"
|
||||||
|
#include "std/string.h"
|
||||||
|
|
||||||
|
#define SIXPACK_OK 0
|
||||||
|
#define SIXPACK_ERR_MAGIC -1
|
||||||
|
#define SIXPACK_ERR_CHECKSUM -2
|
||||||
|
#define SIXPACK_ERR_DECOMPRESS -3
|
||||||
|
#define SIXPACK_ERR_BAD_FORMAT -4
|
||||||
|
#define SIXPACK_ERR_NO_SPACE -5
|
||||||
|
|
||||||
|
#define ADLER32_BASE 65521
|
||||||
|
#define BLOCK_SIZE 65536
|
||||||
|
|
||||||
|
static const uint8_t sixpack_magic[8] = {137, '6', 'P', 'K', 13, 10, 26, 10};
|
||||||
|
|
||||||
|
static uint32_t update_adler32(uint32_t checksum, const void *buf, int len) {
|
||||||
|
const uint8_t *ptr = (const uint8_t*)buf;
|
||||||
|
uint32_t s1 = checksum & 0xffff;
|
||||||
|
uint32_t s2 = (checksum >> 16) & 0xffff;
|
||||||
|
|
||||||
|
while (len > 0) {
|
||||||
|
unsigned k = len < 5552 ? len : 5552;
|
||||||
|
len -= k;
|
||||||
|
while (k--) {
|
||||||
|
s1 += *ptr++;
|
||||||
|
if (s1 >= ADLER32_BASE) s1 -= ADLER32_BASE;
|
||||||
|
s2 += s1;
|
||||||
|
if (s2 >= ADLER32_BASE) s2 -= ADLER32_BASE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return (s2 << 16) + s1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint32_t readU16(const uint8_t *p) {
|
||||||
|
return (uint32_t)p[0] | ((uint32_t)p[1] << 8);
|
||||||
|
}
|
||||||
|
static uint32_t readU32(const uint8_t *p) {
|
||||||
|
return (uint32_t)p[0] | ((uint32_t)p[1] << 8) | ((uint32_t)p[2] << 16) | ((uint32_t)p[3] << 24);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void read_chunk_header(const uint8_t *p, int *id, int *opts,
|
||||||
|
uint32_t *size, uint32_t *checksum, uint32_t *extra) {
|
||||||
|
*id = (int)readU16(p);
|
||||||
|
*opts = (int)readU16(p + 2);
|
||||||
|
*size = readU32(p + 4);
|
||||||
|
*checksum = readU32(p + 8);
|
||||||
|
*extra = readU32(p + 12);
|
||||||
|
}
|
||||||
|
|
||||||
|
int sixpack_decompress_mem(const uint8_t *input, size_t in_size,
|
||||||
|
uint8_t *output, size_t out_cap)
|
||||||
|
{
|
||||||
|
if (!input || in_size < 8)
|
||||||
|
return SIXPACK_ERR_BAD_FORMAT;
|
||||||
|
|
||||||
|
/* Check magic */
|
||||||
|
for (int i = 0; i < 8; i++)
|
||||||
|
if (input[i] != sixpack_magic[i])
|
||||||
|
return SIXPACK_ERR_MAGIC;
|
||||||
|
|
||||||
|
size_t pos = 8; /* skip magic */
|
||||||
|
size_t written = 0;
|
||||||
|
|
||||||
|
while (pos + 16 <= in_size) {
|
||||||
|
int chunk_id, opts;
|
||||||
|
uint32_t size, checksum, extra;
|
||||||
|
|
||||||
|
read_chunk_header(input + pos, &chunk_id, &opts, &size, &checksum, &extra);
|
||||||
|
pos += 16;
|
||||||
|
|
||||||
|
if (pos + size > in_size)
|
||||||
|
return SIXPACK_ERR_BAD_FORMAT;
|
||||||
|
|
||||||
|
const uint8_t *chunk_data = input + pos;
|
||||||
|
pos += size;
|
||||||
|
|
||||||
|
/* File header chunk */
|
||||||
|
if (chunk_id == 1) {
|
||||||
|
uint32_t decomp_size = readU32(chunk_data);
|
||||||
|
(void)decomp_size; /* not strictly needed here */
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Data chunk */
|
||||||
|
if (chunk_id == 17) {
|
||||||
|
uint32_t cksum = update_adler32(1L, chunk_data, size);
|
||||||
|
if (cksum != checksum)
|
||||||
|
return SIXPACK_ERR_CHECKSUM;
|
||||||
|
|
||||||
|
if (opts == 0) {
|
||||||
|
/* Stored (uncompressed) */
|
||||||
|
if (written + size > out_cap)
|
||||||
|
return SIXPACK_ERR_NO_SPACE;
|
||||||
|
memcpy(output + written, chunk_data, size);
|
||||||
|
written += size;
|
||||||
|
} else if (opts == 1) {
|
||||||
|
/* FastLZ compressed */
|
||||||
|
if (written + extra > out_cap)
|
||||||
|
return SIXPACK_ERR_NO_SPACE;
|
||||||
|
|
||||||
|
int dec = fastlz_decompress(chunk_data, size, output + written, extra);
|
||||||
|
if (dec != (int)extra)
|
||||||
|
return SIXPACK_ERR_DECOMPRESS;
|
||||||
|
|
||||||
|
written += extra;
|
||||||
|
} else {
|
||||||
|
return SIXPACK_ERR_BAD_FORMAT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (int)written;
|
||||||
|
}
|
||||||
7
kernel/FastLZ/6unpack_mem.h
Normal file
7
kernel/FastLZ/6unpack_mem.h
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
#ifndef SIXUNPACK_MEM_H_
|
||||||
|
#define SIXUNPACK_MEM_H_
|
||||||
|
|
||||||
|
int sixpack_decompress_mem(const uint8_t *input, size_t in_size,
|
||||||
|
uint8_t *output, size_t out_cap);
|
||||||
|
|
||||||
|
#endif // SIXUNPACK_MEM_H_
|
||||||
1
kernel/FastLZ/fastlz.c
Symbolic link
1
kernel/FastLZ/fastlz.c
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
../../FastLZ/fastlz.c
|
||||||
1
kernel/FastLZ/fastlz.h
Symbolic link
1
kernel/FastLZ/fastlz.h
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
../../FastLZ/fastlz.h
|
||||||
@ -4,7 +4,8 @@ include $(ROOT)/mk/grabsrc.mk
|
|||||||
|
|
||||||
PUTCHAR_ ?= fb
|
PUTCHAR_ ?= fb
|
||||||
|
|
||||||
CFLAGS := -ffreestanding -Wall -Wextra -g -fcommon -nostdinc
|
CFLAGS := -ffreestanding -Wall -Wextra -fcommon -nostdinc \
|
||||||
|
-fdata-sections -ffunction-sections
|
||||||
|
|
||||||
CFLAGS += -I. \
|
CFLAGS += -I. \
|
||||||
-I$(ROOT)/limine \
|
-I$(ROOT)/limine \
|
||||||
@ -20,24 +21,14 @@ CFLAGS += -I. \
|
|||||||
-DLFS_NO_DEBUG \
|
-DLFS_NO_DEBUG \
|
||||||
-DLFS_NO_WARN \
|
-DLFS_NO_WARN \
|
||||||
-DLFS_NO_ERROR \
|
-DLFS_NO_ERROR \
|
||||||
-DPICO_MOP2 \
|
-DFASTLZ_USE_MEMMOVE=0 \
|
||||||
-DPICO_SUPPORT_TCP \
|
-DFATFS_MAX_OPEN_FILES=128 \
|
||||||
-DPICO_SUPPORT_UDP \
|
-D"FAT_PRINTF(a)"
|
||||||
-DPICO_SUPPORT_ETH \
|
|
||||||
-DPICO_SUPPORT_ICMP4 \
|
|
||||||
-DPICO_SUPPORT_IPV4 \
|
|
||||||
-DPICO_SUPPORT_MUTEX \
|
|
||||||
|
|
||||||
ifeq ($(PUTCHAR_),fb)
|
|
||||||
CFLAGS += -DPUTCHAR_=PUTCHAR_FB
|
|
||||||
else
|
|
||||||
CFLAGS += -DPUTCHAR_=PUTCHAR_SERIAL
|
|
||||||
endif
|
|
||||||
|
|
||||||
include arch/$(ARCH)/$(ARCH).mk
|
include arch/$(ARCH)/$(ARCH).mk
|
||||||
include extconf/extra.mk
|
|
||||||
|
|
||||||
LDFLAGS += -nostdlib -static -T arch/$(ARCH)/link.ld $(shell $(CC) -print-libgcc-file-name)
|
LDFLAGS += -nostdlib -static -T arch/$(ARCH)/link.ld $(shell $(CC) -print-libgcc-file-name) \
|
||||||
|
--gc-sections --strip-all
|
||||||
|
|
||||||
SRCFILES :=
|
SRCFILES :=
|
||||||
|
|
||||||
@ -56,10 +47,10 @@ SRCFILES += $(call GRABSRC, \
|
|||||||
fs/kvfs \
|
fs/kvfs \
|
||||||
fs/littlefs \
|
fs/littlefs \
|
||||||
fs/portlfs \
|
fs/portlfs \
|
||||||
|
fs/fatfs \
|
||||||
|
fs/portfatfs \
|
||||||
baseimg \
|
baseimg \
|
||||||
proc \
|
proc \
|
||||||
hal \
|
|
||||||
hal/$(ARCH) \
|
|
||||||
std \
|
std \
|
||||||
flanterm/src \
|
flanterm/src \
|
||||||
flanterm/src/flanterm_backends \
|
flanterm/src/flanterm_backends \
|
||||||
@ -67,15 +58,20 @@ SRCFILES += $(call GRABSRC, \
|
|||||||
path \
|
path \
|
||||||
rbuf \
|
rbuf \
|
||||||
ipc/pipe \
|
ipc/pipe \
|
||||||
ipc/netsock \
|
ipc/mbus \
|
||||||
dev \
|
dev \
|
||||||
randcrypto \
|
randcrypto \
|
||||||
time \
|
time \
|
||||||
diskpart \
|
diskpart \
|
||||||
netdev \
|
FastLZ \
|
||||||
port_picotcp \
|
io \
|
||||||
port_picotcp/modules \
|
intr \
|
||||||
picotcp/stack \
|
cpu \
|
||||||
|
vmm \
|
||||||
|
pci \
|
||||||
|
pci/ata \
|
||||||
|
pci/qemu_pci_serial \
|
||||||
|
cjob \
|
||||||
)
|
)
|
||||||
|
|
||||||
CFILES := $(call GET_CFILES, $(SRCFILES))
|
CFILES := $(call GET_CFILES, $(SRCFILES))
|
||||||
|
|||||||
@ -1,15 +0,0 @@
|
|||||||
#ifndef ASSERT_H_
|
|
||||||
#define ASSERT_H_
|
|
||||||
|
|
||||||
#include "kprintf.h"
|
|
||||||
#include "hal/hal.h"
|
|
||||||
|
|
||||||
#define ASSERT(mod, cond, fmt, ...) \
|
|
||||||
do { \
|
|
||||||
if (!(cond)) { \
|
|
||||||
ERR(mod, fmt, ##__VA_ARGS__); \
|
|
||||||
hal_hang(); \
|
|
||||||
} \
|
|
||||||
} while(0)
|
|
||||||
|
|
||||||
#endif // ASSERT_H_
|
|
||||||
@ -1,6 +0,0 @@
|
|||||||
#ifndef ATOMIC_H_
|
|
||||||
#define ATOMIC_H_
|
|
||||||
|
|
||||||
#define ATOMIC(X) _Atomic(X)
|
|
||||||
|
|
||||||
#endif // ATOMIC_H_
|
|
||||||
@ -1,37 +1,46 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <limine.h>
|
#include <limine.h>
|
||||||
#include "baseimg.h"
|
#include "baseimg/baseimg.h"
|
||||||
#include "bootinfo/bootinfo.h"
|
#include "bootinfo/bootinfo.h"
|
||||||
#include "kprintf.h"
|
|
||||||
#include "util/util.h"
|
#include "util/util.h"
|
||||||
#include "hal/hal.h"
|
#include "dlmalloc/malloc.h"
|
||||||
|
#include "FastLZ/fastlz.h"
|
||||||
|
#include "FastLZ/6unpack_mem.h"
|
||||||
|
#include "std/string.h"
|
||||||
|
#include "cpu/hang.h"
|
||||||
|
#include "kprintf.h"
|
||||||
|
|
||||||
struct limine_file *baseimg = NULL;
|
#define BASEIMG_DECOMPRESSED (1024*1024*4)
|
||||||
|
|
||||||
|
size_t BASEIMG_DECOMP_SIZE;
|
||||||
|
uint8_t *BASEIMG_DECOMP_ADDR;
|
||||||
|
|
||||||
uint64_t baseimg_getaddr(void) {
|
uint64_t baseimg_getaddr(void) {
|
||||||
return (uint64_t)baseimg->address;
|
return (uint64_t)BASEIMG_DECOMP_ADDR;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t baseimg_getsize(void) {
|
uint64_t baseimg_getsize(void) {
|
||||||
return baseimg->size;
|
return (uint64_t)BASEIMG_DECOMP_SIZE;
|
||||||
}
|
}
|
||||||
|
|
||||||
void baseimg_init(void) {
|
void baseimg_init(void) {
|
||||||
|
struct limine_file *baseimg = NULL;
|
||||||
|
|
||||||
LOG("baseimg", "looking for base image...\n");
|
LOG("baseimg", "looking for base image...\n");
|
||||||
for (size_t i = 0; i < BOOT_INFO.modules->module_count; i++) {
|
for (size_t i = 0; i < BOOT_INFO.modules->module_count; i++) {
|
||||||
struct limine_file *module = BOOT_INFO.modules->modules[i];
|
struct limine_file *module = BOOT_INFO.modules->modules[i];
|
||||||
if (hal_strcmp(util_get_filename(module->path), "base.img") == 0) {
|
if (strcmp(util_get_filename(module->path), "base.img.6pk") == 0) {
|
||||||
baseimg = module;
|
baseimg = module;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (baseimg == NULL) {
|
if (baseimg == NULL) {
|
||||||
ERR("baseimg", "base.img not found\n");
|
ERR("baseimg", "base.img.6pk not found\n");
|
||||||
hal_hang();
|
cpu_hang();
|
||||||
} else {
|
} else {
|
||||||
LOG("baseimg", "base.img found\n");
|
LOG("baseimg", "base.img.6pk found\n");
|
||||||
LOG("baseimg", "addr = %p, size = %lu\n", baseimg->address, baseimg->size);
|
LOG("baseimg", "addr = %p, size = %lu\n", baseimg->address, baseimg->size);
|
||||||
for (size_t i = 0; i < 30; i++) {
|
for (size_t i = 0; i < 30; i++) {
|
||||||
kprintf("%02X ", ((uint8_t *)(baseimg->address))[i]);
|
kprintf("%02X ", ((uint8_t *)(baseimg->address))[i]);
|
||||||
@ -40,4 +49,14 @@ void baseimg_init(void) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BASEIMG_DECOMP_ADDR = dlmalloc(BASEIMG_DECOMPRESSED);
|
||||||
|
int res = sixpack_decompress_mem(baseimg->address, baseimg->size,
|
||||||
|
BASEIMG_DECOMP_ADDR, BASEIMG_DECOMPRESSED);
|
||||||
|
if (res < 0) {
|
||||||
|
ERR("baseimg", "could not uncompress base.img.6pk\n");
|
||||||
|
cpu_hang();
|
||||||
|
}
|
||||||
|
BASEIMG_DECOMP_SIZE = res;
|
||||||
|
kprintf("%p %zu\n", BASEIMG_DECOMP_ADDR, BASEIMG_DECOMP_SIZE);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include "bitmap.h"
|
#include "bitmap/bitmap.h"
|
||||||
#include "util/util.h"
|
#include "util/util.h"
|
||||||
#include "kprintf.h"
|
#include "kprintf.h"
|
||||||
|
|
||||||
|
|||||||
@ -4,8 +4,7 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
#include "vmm/vmm.h"
|
||||||
#include "hal/hal.h"
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint8_t *map;
|
uint8_t *map;
|
||||||
@ -17,7 +16,7 @@ typedef struct {
|
|||||||
} BitMap;
|
} BitMap;
|
||||||
|
|
||||||
#define BITMAP_BLOCKS_PER_BYTE 8
|
#define BITMAP_BLOCKS_PER_BYTE 8
|
||||||
#define BITMAP_BLOCK_SIZE HAL_PAGE_SIZE
|
#define BITMAP_BLOCK_SIZE VMM_PAGE_SIZE
|
||||||
#define BITMAP_INVALID_BLOCK ((size_t)-1)
|
#define BITMAP_INVALID_BLOCK ((size_t)-1)
|
||||||
|
|
||||||
void *bitmap_toptr(BitMap *bm, size_t block);
|
void *bitmap_toptr(BitMap *bm, size_t block);
|
||||||
|
|||||||
@ -1,8 +1,8 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <limine.h>
|
#include <limine.h>
|
||||||
#include "bootinfo.h"
|
#include "bootinfo/bootinfo.h"
|
||||||
#include "hal/hal.h"
|
#include "cpu/hang.h"
|
||||||
|
|
||||||
BootInfo BOOT_INFO;
|
BootInfo BOOT_INFO;
|
||||||
|
|
||||||
@ -26,7 +26,7 @@ DEFINE_REQ(module, MODULE);
|
|||||||
|
|
||||||
void bootinfo_init(void) {
|
void bootinfo_init(void) {
|
||||||
if (framebuffer_req.response == NULL || framebuffer_req.response->framebuffer_count < 1) {
|
if (framebuffer_req.response == NULL || framebuffer_req.response->framebuffer_count < 1) {
|
||||||
hal_hang();
|
cpu_hang();
|
||||||
}
|
}
|
||||||
BOOT_INFO.fb = framebuffer_req.response->framebuffers[0];
|
BOOT_INFO.fb = framebuffer_req.response->framebuffers[0];
|
||||||
|
|
||||||
@ -35,7 +35,7 @@ void bootinfo_init(void) {
|
|||||||
|
|
||||||
struct limine_paging_mode_response *pagingres = paging_req.response;
|
struct limine_paging_mode_response *pagingres = paging_req.response;
|
||||||
if (pagingres->mode != LIMINE_PAGING_MODE_X86_64_4LVL) {
|
if (pagingres->mode != LIMINE_PAGING_MODE_X86_64_4LVL) {
|
||||||
hal_hang();
|
cpu_hang();
|
||||||
}
|
}
|
||||||
|
|
||||||
struct limine_hhdm_response *hhdmres = hhdm_req.response;
|
struct limine_hhdm_response *hhdmres = hhdm_req.response;
|
||||||
@ -68,7 +68,7 @@ void bootinfo_init(void) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (BOOT_INFO.smp_bspindex == (uint64_t)-1) {
|
if (BOOT_INFO.smp_bspindex == (uint64_t)-1) {
|
||||||
hal_hang();
|
cpu_hang();
|
||||||
}
|
}
|
||||||
|
|
||||||
struct limine_rsdp_response *rsdpres = rsdp_req.response;
|
struct limine_rsdp_response *rsdpres = rsdp_req.response;
|
||||||
|
|||||||
36
kernel/cjob/cjob.c
Normal file
36
kernel/cjob/cjob.c
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
#include <stdint.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include "spinlock/spinlock.h"
|
||||||
|
#include "cjob/cjob.h"
|
||||||
|
#include "dlmalloc/malloc.h"
|
||||||
|
#include "util/util.h"
|
||||||
|
|
||||||
|
CJobs CJOBS;
|
||||||
|
static uint64_t cjobids = 0;
|
||||||
|
|
||||||
|
void cjob_init(void) {
|
||||||
|
spinlock_init(&CJOBS.spinlock);
|
||||||
|
CJOBS.cjobs = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t cjob_register(CJobFn fn, void *arg) {
|
||||||
|
CJob *cjob = dlmalloc(sizeof(*cjob));
|
||||||
|
cjob->fn = fn;
|
||||||
|
cjob->arg = arg;
|
||||||
|
int32_t id = cjob->id = cjobids++;
|
||||||
|
|
||||||
|
spinlock_acquire(&CJOBS.spinlock);
|
||||||
|
LL_APPEND(CJOBS.cjobs, cjob);
|
||||||
|
spinlock_release(&CJOBS.spinlock);
|
||||||
|
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
void cjob_runjobs(void) {
|
||||||
|
CJob *cjob, *cjobtmp;
|
||||||
|
spinlock_acquire(&CJOBS.spinlock);
|
||||||
|
LL_FOREACH_SAFE(CJOBS.cjobs, cjob, cjobtmp) {
|
||||||
|
cjob->fn(cjob->arg);
|
||||||
|
}
|
||||||
|
spinlock_release(&CJOBS.spinlock);
|
||||||
|
}
|
||||||
29
kernel/cjob/cjob.h
Normal file
29
kernel/cjob/cjob.h
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
#ifndef CJOB_CJOB_H_
|
||||||
|
#define CJOB_CJOB_H_
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include "spinlock/spinlock.h"
|
||||||
|
|
||||||
|
typedef void (*CJobFn)(void *arg);
|
||||||
|
|
||||||
|
typedef struct CJob {
|
||||||
|
struct CJob *next;
|
||||||
|
CJobFn fn;
|
||||||
|
void *arg;
|
||||||
|
int32_t id;
|
||||||
|
} CJob;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
SpinLock spinlock;
|
||||||
|
CJob *cjobs;
|
||||||
|
} CJobs;
|
||||||
|
|
||||||
|
extern CJobs CJOBS;
|
||||||
|
|
||||||
|
void cjob_init(void);
|
||||||
|
|
||||||
|
int32_t cjob_register(CJobFn fn, void *arg);
|
||||||
|
void cjob_runjobs(void);
|
||||||
|
|
||||||
|
#endif // CJOB_CJOB_H_
|
||||||
@ -1,8 +1,8 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include "compiler/attr.h"
|
#include "compiler/attr.h"
|
||||||
#include "hal/hal.h"
|
#include "cpu/gdt.h"
|
||||||
#include "gdt.h"
|
#include "std/string.h"
|
||||||
|
|
||||||
#define GDT_PRESENT 0x80
|
#define GDT_PRESENT 0x80
|
||||||
#define GDT_TSS 0x89
|
#define GDT_TSS 0x89
|
||||||
@ -43,7 +43,7 @@ void gdt_setentry(GdtEntry *ent, uint32_t base, uint32_t limit, uint8_t acc, uin
|
|||||||
}
|
}
|
||||||
|
|
||||||
void gdt_init(void) {
|
void gdt_init(void) {
|
||||||
hal_memset(&tss, 0, sizeof(tss));
|
memset(&tss, 0, sizeof(tss));
|
||||||
tss.iopb_off = sizeof(tss);
|
tss.iopb_off = sizeof(tss);
|
||||||
|
|
||||||
tss.rsp0 = (uint64_t)(kernelstack + sizeof(kernelstack));
|
tss.rsp0 = (uint64_t)(kernelstack + sizeof(kernelstack));
|
||||||
@ -1,5 +1,8 @@
|
|||||||
#ifndef HAL_GDT_H_
|
#ifndef CPU_GDT_H_
|
||||||
#define HAL_GDT_H_
|
#define CPU_GDT_H_
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include "compiler/attr.h"
|
||||||
|
|
||||||
#define KCODE 0x08
|
#define KCODE 0x08
|
||||||
#define KDATA 0x10
|
#define KDATA 0x10
|
||||||
@ -23,4 +26,4 @@ ALIGNED(16) extern Tss tss;
|
|||||||
|
|
||||||
void gdt_init(void);
|
void gdt_init(void);
|
||||||
|
|
||||||
#endif // HAL_GDT_H_
|
#endif // CPU_GDT_H_
|
||||||
10
kernel/cpu/hang.c
Normal file
10
kernel/cpu/hang.c
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
#include "cpu/hang.h"
|
||||||
|
#include "intr/intr.h"
|
||||||
|
|
||||||
|
void cpu_hang(void) {
|
||||||
|
intr_disable();
|
||||||
|
for(;;) {
|
||||||
|
asm("hlt");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
6
kernel/cpu/hang.h
Normal file
6
kernel/cpu/hang.h
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
#ifndef CPU_HANG_H_
|
||||||
|
#define CPU_HANG_H_
|
||||||
|
|
||||||
|
void cpu_hang(void);
|
||||||
|
|
||||||
|
#endif // CPU_HANG_H_
|
||||||
@ -1,22 +1,16 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include "spinlock/spinlock.h"
|
#include "spinlock/spinlock.h"
|
||||||
#include "dev.h"
|
#include "std/string.h"
|
||||||
|
#include "dev/dev.h"
|
||||||
|
#include "dev/ps2kbdev.h"
|
||||||
#include "hshtb.h"
|
#include "hshtb.h"
|
||||||
#include "hal/hal.h"
|
|
||||||
#include "termdev.h"
|
|
||||||
#include "ps2kbdev.h"
|
|
||||||
#include "serialdev.h"
|
|
||||||
#include "fbdev.h"
|
|
||||||
|
|
||||||
DevTable DEVTABLE;
|
DevTable DEVTABLE;
|
||||||
|
|
||||||
void dev_init(void) {
|
void dev_init(void) {
|
||||||
hal_memset(&DEVTABLE, 0, sizeof(DEVTABLE));
|
memset(&DEVTABLE, 0, sizeof(DEVTABLE));
|
||||||
spinlock_init(&DEVTABLE.spinlock);
|
spinlock_init(&DEVTABLE.spinlock);
|
||||||
|
|
||||||
termdev_init();
|
|
||||||
ps2kbdev_init();
|
ps2kbdev_init();
|
||||||
serialdev_init();
|
|
||||||
fbdev_init();
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,35 +0,0 @@
|
|||||||
#include <stdint.h>
|
|
||||||
#include <stddef.h>
|
|
||||||
#include "fbdev.h"
|
|
||||||
#include "dev.h"
|
|
||||||
#include "sysdefs/dev.h"
|
|
||||||
#include "hshtb.h"
|
|
||||||
#include "spinlock/spinlock.h"
|
|
||||||
#include "util/util.h"
|
|
||||||
#include "hal/hal.h"
|
|
||||||
#include "bootinfo/bootinfo.h"
|
|
||||||
#include "errors.h"
|
|
||||||
|
|
||||||
int32_t fbdev_getinfo(struct Dev *dev, uint8_t *buffer, size_t len, uint64_t pid) {
|
|
||||||
(void)dev; (void)pid;
|
|
||||||
|
|
||||||
if (len != sizeof(FbDevGetInfo)) {
|
|
||||||
return E_INVALIDARGUMENT;
|
|
||||||
}
|
|
||||||
|
|
||||||
FbDevGetInfo info = {
|
|
||||||
.w = BOOT_INFO.fb->width,
|
|
||||||
.h = BOOT_INFO.fb->height,
|
|
||||||
.margin = 20,
|
|
||||||
.fontw = 8,
|
|
||||||
.fonth = 16,
|
|
||||||
};
|
|
||||||
hal_memcpy(buffer, &info, sizeof(info));
|
|
||||||
return E_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
void fbdev_init(void) {
|
|
||||||
Dev *fbdev;
|
|
||||||
HSHTB_ALLOC(DEVTABLE.devs, ident, "fbdev", fbdev);
|
|
||||||
fbdev->fns[DEV_FBDEV_GETINFO] = &fbdev_getinfo;
|
|
||||||
}
|
|
||||||
@ -1,6 +0,0 @@
|
|||||||
#ifndef DEV_FBDEV_H_
|
|
||||||
#define DEV_FBDEV_H_
|
|
||||||
|
|
||||||
void fbdev_init(void);
|
|
||||||
|
|
||||||
#endif // DEV_FBDEV_H_
|
|
||||||
@ -1,15 +1,17 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include "kprintf.h"
|
#include "dev/ps2kbdev.h"
|
||||||
#include "hal/hal.h"
|
#include "dev/dev.h"
|
||||||
#include "ps2kbdev.h"
|
|
||||||
#include "dev.h"
|
|
||||||
#include "errors.h"
|
|
||||||
#include "dlmalloc/malloc.h"
|
#include "dlmalloc/malloc.h"
|
||||||
#include "util/util.h"
|
#include "util/util.h"
|
||||||
#include "hshtb.h"
|
|
||||||
#include "sysdefs/dev.h"
|
#include "sysdefs/dev.h"
|
||||||
#include "proc/proc.h"
|
#include "proc/proc.h"
|
||||||
|
#include "io/io.h"
|
||||||
|
#include "ipc/mbus/mbus.h"
|
||||||
|
#include "intr/intr.h"
|
||||||
|
#include "errors.h"
|
||||||
|
#include "hshtb.h"
|
||||||
|
#include "kprintf.h"
|
||||||
|
|
||||||
#define KB_CTL_STATUS 0x64
|
#define KB_CTL_STATUS 0x64
|
||||||
#define KB_DATA_IN_BUF 0x01
|
#define KB_DATA_IN_BUF 0x01
|
||||||
@ -115,7 +117,7 @@ static uint8_t ctlmap[256] =
|
|||||||
[0xc7] KB_HOME,
|
[0xc7] KB_HOME,
|
||||||
};
|
};
|
||||||
|
|
||||||
int32_t ps2kb_intr(void) {
|
int32_t ps2kbdev_keycode(void) {
|
||||||
static uint8_t shift;
|
static uint8_t shift;
|
||||||
static uint8_t *charcode[4] = { normalmap, shiftmap, ctlmap, ctlmap };
|
static uint8_t *charcode[4] = { normalmap, shiftmap, ctlmap, ctlmap };
|
||||||
uint32_t st, data, c;
|
uint32_t st, data, c;
|
||||||
@ -152,110 +154,23 @@ int32_t ps2kb_intr(void) {
|
|||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef struct Ps2kbEvConsumer {
|
IpcMBus *PS2KB_MBUS;
|
||||||
struct Ps2kbEvConsumer *next;
|
|
||||||
Proc *proc;
|
|
||||||
RBuf rbuf;
|
|
||||||
} Ps2kbEvConsumer;
|
|
||||||
|
|
||||||
struct {
|
void ps2kbdev_intr(IntrStackFrame *frame) {
|
||||||
SpinLock spinlock;
|
(void)frame;
|
||||||
Ps2kbEvConsumer *list;
|
|
||||||
} PS2KB_CONSUMERS = {0};
|
|
||||||
|
|
||||||
int32_t ps2kbdev_readch(struct Dev *dev, uint8_t *buffer, size_t len, uint64_t pid) {
|
int32_t c = ps2kbdev_keycode();
|
||||||
(void)dev; (void)buffer; (void)len;
|
|
||||||
|
|
||||||
Proc *consproc = NULL;
|
|
||||||
spinlock_acquire(&PROCS.spinlock);
|
|
||||||
Proc *proc, *proctmp;
|
|
||||||
LL_FOREACH_SAFE(PROCS.procs, proc, proctmp) {
|
|
||||||
if (proc->pid == pid) {
|
|
||||||
consproc = proc;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
spinlock_release(&PROCS.spinlock);
|
|
||||||
|
|
||||||
if (consproc == NULL) {
|
|
||||||
return E_INVALIDOPER;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t b;
|
|
||||||
int32_t r = -1;
|
|
||||||
|
|
||||||
spinlock_acquire(&PS2KB_CONSUMERS.spinlock);
|
|
||||||
Ps2kbEvConsumer *cons, *constmp;
|
|
||||||
LL_FOREACH_SAFE(PS2KB_CONSUMERS.list, cons, constmp) {
|
|
||||||
if (cons->proc == consproc) {
|
|
||||||
r = rbuf_pop(&cons->rbuf, &b);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
spinlock_release(&PS2KB_CONSUMERS.spinlock);
|
|
||||||
|
|
||||||
if (r == 0) {
|
|
||||||
return b;
|
|
||||||
} else {
|
|
||||||
return E_NOTYET;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#define CONSUMER_RBUF_MAX 0x400
|
|
||||||
|
|
||||||
int32_t ps2kbdev_attchcons(struct Dev *dev, uint8_t *buffer, size_t len, uint64_t pid) {
|
|
||||||
(void)dev; (void)buffer; (void)len;
|
|
||||||
|
|
||||||
spinlock_acquire(&PROCS.spinlock);
|
|
||||||
Proc *proc, *proctmp;
|
|
||||||
LL_FOREACH_SAFE(PROCS.procs, proc, proctmp) {
|
|
||||||
if (proc->pid == pid) {
|
|
||||||
Ps2kbEvConsumer *cons = dlmalloc(sizeof(*cons));
|
|
||||||
cons->proc = proc;
|
|
||||||
uint8_t *buf = dlmalloc(CONSUMER_RBUF_MAX);
|
|
||||||
rbuf_init(&cons->rbuf, buf, CONSUMER_RBUF_MAX);
|
|
||||||
spinlock_acquire(&PS2KB_CONSUMERS.spinlock);
|
|
||||||
LL_APPEND(PS2KB_CONSUMERS.list, cons);
|
|
||||||
spinlock_release(&PS2KB_CONSUMERS.spinlock);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
spinlock_release(&PROCS.spinlock);
|
|
||||||
return E_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ps2kbdev_intr(void) {
|
|
||||||
int32_t c = ps2kb_intr();
|
|
||||||
if (c >= 0) {
|
if (c >= 0) {
|
||||||
uint8_t b = c;
|
uint8_t b = c;
|
||||||
spinlock_acquire(&PS2KB_CONSUMERS.spinlock);
|
ipc_mbuspublish("ps2kb", &b);
|
||||||
Ps2kbEvConsumer *cons, *constmp;
|
|
||||||
LL_FOREACH_SAFE(PS2KB_CONSUMERS.list, cons, constmp) {
|
|
||||||
bool found = false;
|
|
||||||
spinlock_acquire(&PROCS.spinlock);
|
|
||||||
Proc *proc, *proctmp;
|
|
||||||
LL_FOREACH_SAFE(PROCS.procs, proc, proctmp) {
|
|
||||||
if (proc == cons->proc) {
|
|
||||||
found = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!found) {
|
|
||||||
LL_REMOVE(PS2KB_CONSUMERS.list, cons);
|
|
||||||
}
|
|
||||||
spinlock_release(&PROCS.spinlock);
|
|
||||||
|
|
||||||
rbuf_push(&cons->rbuf, b);
|
|
||||||
}
|
|
||||||
spinlock_release(&PS2KB_CONSUMERS.spinlock);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ps2kbdev_init(void) {
|
void ps2kbdev_init(void) {
|
||||||
intr_attchhandler(&ps2kbdev_intr, INTR_IRQBASE+1);
|
|
||||||
|
|
||||||
Dev *ps2kbdev;
|
Dev *ps2kbdev;
|
||||||
HSHTB_ALLOC(DEVTABLE.devs, ident, "ps2kbdev", ps2kbdev);
|
HSHTB_ALLOC(DEVTABLE.devs, ident, "ps2kbdev", ps2kbdev);
|
||||||
spinlock_init(&ps2kbdev->spinlock);
|
spinlock_init(&ps2kbdev->spinlock);
|
||||||
spinlock_init(&PS2KB_CONSUMERS.spinlock);
|
PS2KB_MBUS = ipc_mbusmake("ps2kb", 1, 0x100);
|
||||||
ps2kbdev->fns[DEV_PS2KBDEV_READCH] = &ps2kbdev_readch;
|
|
||||||
ps2kbdev->fns[DEV_PS2KBDEV_ATTCHCONS] = &ps2kbdev_attchcons;
|
intr_attchhandler(&ps2kbdev_intr, INTR_IRQBASE+1);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,81 +0,0 @@
|
|||||||
#include <stdint.h>
|
|
||||||
#include <stddef.h>
|
|
||||||
#include "dev.h"
|
|
||||||
#include "serialdev.h"
|
|
||||||
#include "errors.h"
|
|
||||||
#include "util/util.h"
|
|
||||||
#include "hshtb.h"
|
|
||||||
#include "sysdefs/dev.h"
|
|
||||||
#include "kprintf.h"
|
|
||||||
#include "hal/hal.h"
|
|
||||||
|
|
||||||
// https://wiki.osdev.org/Serial_Ports
|
|
||||||
|
|
||||||
#define PORT 0x3f8
|
|
||||||
|
|
||||||
void serial_init(void) {
|
|
||||||
io_out8(PORT+1, 0x00);
|
|
||||||
io_out8(PORT+3, 0x80);
|
|
||||||
io_out8(PORT+0, 0x03);
|
|
||||||
io_out8(PORT+1, 0x00);
|
|
||||||
io_out8(PORT+3, 0x03);
|
|
||||||
io_out8(PORT+2, 0xC7);
|
|
||||||
io_out8(PORT+4, 0x0B);
|
|
||||||
io_out8(PORT+4, 0x1E);
|
|
||||||
io_out8(PORT+0, 0xAE);
|
|
||||||
|
|
||||||
if (io_in8(PORT+0) != 0xAE) {
|
|
||||||
ERR("serial", "serial is faulty!\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
io_out8(PORT+4, 0x0F);
|
|
||||||
}
|
|
||||||
|
|
||||||
int serial_recvready(void) {
|
|
||||||
return io_in8(PORT+5) & 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t serial_recvb(void) {
|
|
||||||
return io_in8(PORT);
|
|
||||||
}
|
|
||||||
|
|
||||||
int serial_sendready(void) {
|
|
||||||
return io_in8(PORT+5) & 0x20;
|
|
||||||
}
|
|
||||||
|
|
||||||
void serial_sendb(uint8_t b) {
|
|
||||||
io_out8(PORT, b);
|
|
||||||
}
|
|
||||||
|
|
||||||
int32_t serialdev_sendb(struct Dev *dev, uint8_t *buffer, size_t len, uint64_t pid) {
|
|
||||||
(void)dev; (void)len; (void)pid;
|
|
||||||
serial_sendb(buffer[0]);
|
|
||||||
return E_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
int32_t serialdev_sendready(struct Dev *dev, uint8_t *buffer, size_t len, uint64_t pid) {
|
|
||||||
(void)dev; (void)buffer; (void)len; (void)pid;
|
|
||||||
return serial_sendready();
|
|
||||||
}
|
|
||||||
|
|
||||||
int32_t serialdev_recvb(struct Dev *dev, uint8_t *buffer, size_t len, uint64_t pid) {
|
|
||||||
(void)dev; (void)buffer; (void)len; (void)pid;
|
|
||||||
return serial_recvb();
|
|
||||||
}
|
|
||||||
|
|
||||||
int32_t serialdev_recvready(struct Dev *dev, uint8_t *buffer, size_t len, uint64_t pid) {
|
|
||||||
(void)dev; (void)buffer; (void)len; (void)pid;
|
|
||||||
return serial_recvready();
|
|
||||||
}
|
|
||||||
|
|
||||||
void serialdev_init(void) {
|
|
||||||
Dev *serialdev = NULL;
|
|
||||||
HSHTB_ALLOC(DEVTABLE.devs, ident, "serialdev", serialdev);
|
|
||||||
serialdev->fns[DEV_SERIALDEV_SENDB] = &serialdev_sendb;
|
|
||||||
serialdev->fns[DEV_SERIALDEV_SENDREADY] = &serialdev_sendready;
|
|
||||||
serialdev->fns[DEV_SERIALDEV_RECVB] = &serialdev_recvb;
|
|
||||||
serialdev->fns[DEV_SERIALDEV_RECVREADY] = &serialdev_recvready;
|
|
||||||
spinlock_init(&serialdev->spinlock);
|
|
||||||
serial_init();
|
|
||||||
}
|
|
||||||
@ -1,6 +0,0 @@
|
|||||||
#ifndef DEV_SERIALDEV_H_
|
|
||||||
#define DEV_SERIALDEV_H_
|
|
||||||
|
|
||||||
void serialdev_init(void);
|
|
||||||
|
|
||||||
#endif // DEV_SERIALDEV_H_
|
|
||||||
@ -1,23 +0,0 @@
|
|||||||
#include <stdint.h>
|
|
||||||
#include <stddef.h>
|
|
||||||
#include "kprintf.h"
|
|
||||||
#include "hal/hal.h"
|
|
||||||
#include "termdev.h"
|
|
||||||
#include "dev.h"
|
|
||||||
#include "errors.h"
|
|
||||||
#include "util/util.h"
|
|
||||||
#include "hshtb.h"
|
|
||||||
#include "sysdefs/dev.h"
|
|
||||||
|
|
||||||
int32_t termdev_putch(struct Dev *dev, uint8_t *buffer, size_t len, uint64_t pid) {
|
|
||||||
(void)dev; (void)pid;
|
|
||||||
kprintf("%.*s", (int)len, (char *)buffer);
|
|
||||||
return E_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
void termdev_init(void) {
|
|
||||||
Dev *termdev = NULL;
|
|
||||||
HSHTB_ALLOC(DEVTABLE.devs, ident, "termdev", termdev);
|
|
||||||
termdev->fns[DEV_TERMDEV_PUTCH] = &termdev_putch;
|
|
||||||
spinlock_init(&termdev->spinlock);
|
|
||||||
}
|
|
||||||
@ -1,10 +0,0 @@
|
|||||||
#ifndef DEV_TERMDEV_H_
|
|
||||||
#define DEV_TERMDEV_H_
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <stddef.h>
|
|
||||||
#include "dev.h"
|
|
||||||
|
|
||||||
void termdev_init(void);
|
|
||||||
|
|
||||||
#endif // DEV_TERMDEV_H_
|
|
||||||
@ -1,7 +1,7 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include "storedev/storedev.h"
|
#include "storedev/storedev.h"
|
||||||
#include "mbr.h"
|
#include "diskpart/mbr.h"
|
||||||
#include "util/util.h"
|
#include "util/util.h"
|
||||||
#include "kprintf.h"
|
#include "kprintf.h"
|
||||||
|
|
||||||
|
|||||||
@ -2,14 +2,14 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include "storedev/storedev.h"
|
#include "storedev/storedev.h"
|
||||||
#include "mbr.h"
|
#include "diskpart/mbr.h"
|
||||||
#include "diskpart.h"
|
#include "diskpart/diskpart.h"
|
||||||
#include "compiler/attr.h"
|
#include "compiler/attr.h"
|
||||||
#include "errors.h"
|
|
||||||
#include "kprintf.h"
|
|
||||||
#include "hal/hal.h"
|
|
||||||
#include "util/util.h"
|
#include "util/util.h"
|
||||||
#include "dev/dev.h"
|
#include "dev/dev.h"
|
||||||
|
#include "std/string.h"
|
||||||
|
#include "errors.h"
|
||||||
|
#include "kprintf.h"
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint8_t driveattrs;
|
uint8_t driveattrs;
|
||||||
@ -52,7 +52,7 @@ void diskpart_mbr_expose_partitions(StoreDev *sd, MBR *mbr) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
char name1[100];
|
char name1[100];
|
||||||
ksprintf(name1, "%s-part%zu", name, i+1);
|
ksprintf(name1, "%sp%zu", name, i+1);
|
||||||
kprintf("%s\n", name1);
|
kprintf("%s\n", name1);
|
||||||
storedev_create(STOREDEV_PARTSD, name1, &extra);
|
storedev_create(STOREDEV_PARTSD, name1, &extra);
|
||||||
}
|
}
|
||||||
@ -62,7 +62,7 @@ bool diskpart_mbr_probe(StoreDev *sd) {
|
|||||||
LOG("diskpart", "probing for MBR\n");
|
LOG("diskpart", "probing for MBR\n");
|
||||||
|
|
||||||
MBR mbr;
|
MBR mbr;
|
||||||
hal_memset(&mbr, 0, sizeof(mbr));
|
memset(&mbr, 0, sizeof(mbr));
|
||||||
sd->read(sd, (uint8_t *const)&mbr, 0, 0, sizeof(mbr));
|
sd->read(sd, (uint8_t *const)&mbr, 0, 0, sizeof(mbr));
|
||||||
|
|
||||||
if (!(mbr.validsign[0] == 0x55 && mbr.validsign[1] == 0xAA)) {
|
if (!(mbr.validsign[0] == 0x55 && mbr.validsign[1] == 0xAA)) {
|
||||||
|
|||||||
@ -1,14 +1,16 @@
|
|||||||
// Config
|
// Config
|
||||||
|
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include "hal/hal.h"
|
|
||||||
#include "spinlock/spinlock.h"
|
#include "spinlock/spinlock.h"
|
||||||
#include "kprintf.h"
|
|
||||||
#include "bitmap/bitmap.h"
|
#include "bitmap/bitmap.h"
|
||||||
#include "util/util.h"
|
#include "util/util.h"
|
||||||
#include "pmm/pmm.h"
|
#include "pmm/pmm.h"
|
||||||
#include "malloc.h"
|
#include "dlmalloc/malloc.h"
|
||||||
#include "bootinfo/bootinfo.h"
|
#include "bootinfo/bootinfo.h"
|
||||||
|
#include "std/string.h"
|
||||||
|
#include "vmm/vmm.h"
|
||||||
|
#include "cpu/hang.h"
|
||||||
|
#include "kprintf.h"
|
||||||
|
|
||||||
#define USE_DL_PREFIX 1
|
#define USE_DL_PREFIX 1
|
||||||
#define LACKS_SYS_TYPES_H 1
|
#define LACKS_SYS_TYPES_H 1
|
||||||
@ -26,7 +28,7 @@
|
|||||||
#define ABORT \
|
#define ABORT \
|
||||||
do { \
|
do { \
|
||||||
ERR("dlmalloc", "Aborting..."); \
|
ERR("dlmalloc", "Aborting..."); \
|
||||||
hal_hang(); \
|
cpu_hang(); \
|
||||||
} while(0)
|
} while(0)
|
||||||
#define MALLOC_FAILURE_ACTION
|
#define MALLOC_FAILURE_ACTION
|
||||||
#define HAVE_MORECORE 1
|
#define HAVE_MORECORE 1
|
||||||
@ -67,7 +69,7 @@ void *sbrk(long inc) {
|
|||||||
|
|
||||||
uint64_t blocks = _DIV_ROUNDUP(inc, BITMAP_BLOCK_SIZE);
|
uint64_t blocks = _DIV_ROUNDUP(inc, BITMAP_BLOCK_SIZE);
|
||||||
uint8_t *virt = VIRT(pmm_alloc(blocks));
|
uint8_t *virt = VIRT(pmm_alloc(blocks));
|
||||||
hal_memset(virt, 0, blocks * BITMAP_BLOCK_SIZE);
|
memset(virt, 0, blocks * BITMAP_BLOCK_SIZE);
|
||||||
_last = (void *)(virt + inc);
|
_last = (void *)(virt + inc);
|
||||||
return virt;
|
return virt;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1 +0,0 @@
|
|||||||
CFLAGS += -DKPRINTF_COLORS
|
|
||||||
@ -1,345 +0,0 @@
|
|||||||
unsigned char FM_T_437_F16[] = {
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x81, 0x81, 0xa5, 0xa5, 0x81, 0x81,
|
|
||||||
0x81, 0xbd, 0x99, 0x81, 0x81, 0x7e, 0x00, 0x00, 0x00, 0x7e, 0xff, 0xff,
|
|
||||||
0xdb, 0xdb, 0xff, 0xff, 0xff, 0xc3, 0xe7, 0xff, 0xff, 0x7e, 0x00, 0x00,
|
|
||||||
0x00, 0x22, 0x22, 0x77, 0x7f, 0x7f, 0x7f, 0x7f, 0x3e, 0x3e, 0x1c, 0x1c,
|
|
||||||
0x08, 0x00, 0x00, 0x00, 0x00, 0x08, 0x1c, 0x1c, 0x3e, 0x3e, 0x7f, 0x7f,
|
|
||||||
0x3e, 0x3e, 0x1c, 0x1c, 0x08, 0x00, 0x00, 0x00, 0x00, 0x08, 0x1c, 0x1c,
|
|
||||||
0x1c, 0x08, 0x6b, 0x7f, 0x7f, 0x6b, 0x08, 0x1c, 0x3e, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x08, 0x08, 0x1c, 0x3e, 0x7f, 0x7f, 0x7f, 0x7f, 0x2a, 0x08, 0x1c,
|
|
||||||
0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3c, 0x3c, 0x7e, 0x7e, 0x7e,
|
|
||||||
0x7e, 0x7e, 0x3c, 0x3c, 0x18, 0x00, 0x00, 0x00, 0xff, 0xff, 0xe7, 0xc3,
|
|
||||||
0xc3, 0x81, 0x81, 0x81, 0x81, 0x81, 0xc3, 0xc3, 0xe7, 0xff, 0xff, 0xff,
|
|
||||||
0x00, 0x00, 0x18, 0x24, 0x24, 0x42, 0x42, 0x42, 0x42, 0x42, 0x24, 0x24,
|
|
||||||
0x18, 0x00, 0x00, 0x00, 0xff, 0xff, 0xe7, 0xdb, 0xdb, 0xbd, 0xbd, 0xbd,
|
|
||||||
0xbd, 0xbd, 0xdb, 0xdb, 0xe7, 0xff, 0xff, 0xff, 0x00, 0x0f, 0x03, 0x05,
|
|
||||||
0x05, 0x08, 0x1c, 0x22, 0x41, 0x41, 0x41, 0x41, 0x22, 0x1c, 0x00, 0x00,
|
|
||||||
0x00, 0x1c, 0x22, 0x41, 0x41, 0x41, 0x41, 0x22, 0x1c, 0x08, 0x08, 0x3e,
|
|
||||||
0x08, 0x08, 0x00, 0x00, 0x00, 0x08, 0x0c, 0x0a, 0x0a, 0x09, 0x09, 0x09,
|
|
||||||
0x08, 0x08, 0x38, 0x78, 0x78, 0x30, 0x00, 0x00, 0x00, 0x3f, 0x21, 0x3f,
|
|
||||||
0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x23, 0x67, 0xe7, 0xe2, 0x40, 0x00,
|
|
||||||
0x00, 0x49, 0x49, 0x2a, 0x36, 0x14, 0x22, 0xe3, 0x22, 0x14, 0x36, 0x2a,
|
|
||||||
0x49, 0x49, 0x00, 0x00, 0x00, 0x00, 0x40, 0x60, 0x70, 0x78, 0x7c, 0x7e,
|
|
||||||
0x7c, 0x78, 0x70, 0x60, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x06,
|
|
||||||
0x0e, 0x1e, 0x3e, 0x7e, 0x3e, 0x1e, 0x0e, 0x06, 0x02, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x08, 0x1c, 0x2a, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x2a,
|
|
||||||
0x1c, 0x08, 0x00, 0x00, 0x00, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
|
|
||||||
0x22, 0x22, 0x00, 0x00, 0x22, 0x22, 0x00, 0x00, 0x00, 0x3f, 0x49, 0x49,
|
|
||||||
0x49, 0x49, 0x39, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x00, 0x00,
|
|
||||||
0x00, 0x3c, 0x42, 0x42, 0x40, 0x20, 0x58, 0x44, 0x22, 0x1a, 0x04, 0x02,
|
|
||||||
0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0xfe, 0xfe, 0xfe, 0xfe, 0x00, 0x00, 0x00, 0x08, 0x1c, 0x2a,
|
|
||||||
0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x2a, 0x1c, 0x08, 0x3e, 0x00, 0x00,
|
|
||||||
0x00, 0x08, 0x1c, 0x2a, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
|
|
||||||
0x08, 0x08, 0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
|
|
||||||
0x08, 0x08, 0x08, 0x2a, 0x1c, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x04, 0x02, 0x7f, 0x02, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x20, 0x7f, 0x20, 0x10, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x40, 0x40,
|
|
||||||
0x40, 0x40, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x24, 0x42, 0xff, 0x42, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x1c, 0x1c, 0x3e, 0x3e, 0x7f, 0x7f,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x7f, 0x3e, 0x3e,
|
|
||||||
0x1c, 0x1c, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00,
|
|
||||||
0x08, 0x08, 0x00, 0x00, 0x00, 0x24, 0x24, 0x24, 0x24, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x24, 0x24,
|
|
||||||
0x7e, 0x24, 0x24, 0x24, 0x24, 0x24, 0x7e, 0x24, 0x24, 0x24, 0x00, 0x00,
|
|
||||||
0x00, 0x08, 0x1e, 0x2b, 0x28, 0x28, 0x28, 0x1c, 0x0a, 0x0a, 0x0a, 0x6a,
|
|
||||||
0x3c, 0x08, 0x00, 0x00, 0x00, 0x00, 0x32, 0x52, 0x54, 0x64, 0x08, 0x08,
|
|
||||||
0x10, 0x10, 0x26, 0x2a, 0x4a, 0x4c, 0x00, 0x00, 0x00, 0x00, 0x38, 0x44,
|
|
||||||
0x44, 0x44, 0x28, 0x18, 0x24, 0x45, 0x42, 0x42, 0x42, 0x3d, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x04, 0x08, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x08, 0x08, 0x10, 0x10, 0x10, 0x10,
|
|
||||||
0x10, 0x10, 0x10, 0x08, 0x08, 0x04, 0x00, 0x00, 0x00, 0x20, 0x10, 0x10,
|
|
||||||
0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x10, 0x10, 0x20, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x08, 0x49, 0x2a, 0x1c, 0x1c, 0x7f, 0x1c, 0x1c, 0x2a, 0x49,
|
|
||||||
0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x3e,
|
|
||||||
0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x08, 0x08, 0x10, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02,
|
|
||||||
0x04, 0x08, 0x08, 0x10, 0x10, 0x20, 0x20, 0x40, 0x80, 0x80, 0x00, 0x00,
|
|
||||||
0x00, 0x18, 0x24, 0x24, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x24,
|
|
||||||
0x24, 0x18, 0x00, 0x00, 0x00, 0x08, 0x18, 0x28, 0x08, 0x08, 0x08, 0x08,
|
|
||||||
0x08, 0x08, 0x08, 0x08, 0x08, 0x3e, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x42,
|
|
||||||
0x42, 0x02, 0x04, 0x08, 0x10, 0x20, 0x20, 0x40, 0x40, 0x7e, 0x00, 0x00,
|
|
||||||
0x00, 0x3c, 0x42, 0x42, 0x02, 0x02, 0x02, 0x1c, 0x02, 0x02, 0x02, 0x42,
|
|
||||||
0x42, 0x3c, 0x00, 0x00, 0x00, 0x04, 0x0c, 0x0c, 0x14, 0x14, 0x24, 0x24,
|
|
||||||
0x44, 0x44, 0x44, 0x7e, 0x04, 0x04, 0x00, 0x00, 0x00, 0x7e, 0x40, 0x40,
|
|
||||||
0x40, 0x40, 0x7c, 0x02, 0x02, 0x02, 0x02, 0x42, 0x42, 0x3c, 0x00, 0x00,
|
|
||||||
0x00, 0x3c, 0x42, 0x42, 0x40, 0x40, 0x7c, 0x42, 0x42, 0x42, 0x42, 0x42,
|
|
||||||
0x42, 0x3c, 0x00, 0x00, 0x00, 0x7e, 0x42, 0x42, 0x42, 0x04, 0x04, 0x04,
|
|
||||||
0x04, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x42,
|
|
||||||
0x42, 0x42, 0x3c, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00,
|
|
||||||
0x00, 0x3c, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3e, 0x02, 0x02, 0x42,
|
|
||||||
0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18,
|
|
||||||
0x18, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x08, 0x10, 0x20, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x20, 0x10, 0x08, 0x04,
|
|
||||||
0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00,
|
|
||||||
0x00, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x20,
|
|
||||||
0x10, 0x08, 0x04, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x3c, 0x42, 0x42, 0x42, 0x02, 0x04, 0x08, 0x08, 0x08, 0x00, 0x00,
|
|
||||||
0x08, 0x08, 0x00, 0x00, 0x00, 0x1e, 0x22, 0x41, 0x49, 0x55, 0x55, 0x55,
|
|
||||||
0x55, 0x55, 0x57, 0x4b, 0x20, 0x1f, 0x00, 0x00, 0x00, 0x18, 0x24, 0x42,
|
|
||||||
0x42, 0x42, 0x42, 0x42, 0x7e, 0x42, 0x42, 0x42, 0x42, 0x42, 0x00, 0x00,
|
|
||||||
0x00, 0x7c, 0x22, 0x22, 0x22, 0x22, 0x22, 0x3c, 0x22, 0x22, 0x22, 0x22,
|
|
||||||
0x22, 0x7c, 0x00, 0x00, 0x00, 0x1c, 0x22, 0x42, 0x40, 0x40, 0x40, 0x40,
|
|
||||||
0x40, 0x40, 0x40, 0x42, 0x22, 0x1c, 0x00, 0x00, 0x00, 0x78, 0x24, 0x22,
|
|
||||||
0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x24, 0x78, 0x00, 0x00,
|
|
||||||
0x00, 0x7e, 0x40, 0x40, 0x40, 0x40, 0x40, 0x7c, 0x40, 0x40, 0x40, 0x40,
|
|
||||||
0x40, 0x7e, 0x00, 0x00, 0x00, 0x7e, 0x40, 0x40, 0x40, 0x40, 0x40, 0x7c,
|
|
||||||
0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x1c, 0x22, 0x42,
|
|
||||||
0x40, 0x40, 0x40, 0x40, 0x4e, 0x42, 0x42, 0x42, 0x22, 0x1c, 0x00, 0x00,
|
|
||||||
0x00, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x7e, 0x42, 0x42, 0x42, 0x42,
|
|
||||||
0x42, 0x42, 0x00, 0x00, 0x00, 0x1c, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
|
|
||||||
0x08, 0x08, 0x08, 0x08, 0x08, 0x1c, 0x00, 0x00, 0x00, 0x0e, 0x04, 0x04,
|
|
||||||
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x44, 0x44, 0x44, 0x38, 0x00, 0x00,
|
|
||||||
0x00, 0x42, 0x42, 0x44, 0x44, 0x48, 0x50, 0x50, 0x68, 0x48, 0x44, 0x44,
|
|
||||||
0x42, 0x42, 0x00, 0x00, 0x00, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
|
|
||||||
0x40, 0x40, 0x40, 0x40, 0x40, 0x7e, 0x00, 0x00, 0x00, 0x41, 0x63, 0x63,
|
|
||||||
0x55, 0x55, 0x49, 0x49, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x00, 0x00,
|
|
||||||
0x00, 0x42, 0x42, 0x62, 0x62, 0x52, 0x52, 0x4a, 0x4a, 0x46, 0x46, 0x42,
|
|
||||||
0x42, 0x42, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42,
|
|
||||||
0x42, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x78, 0x44, 0x42,
|
|
||||||
0x42, 0x42, 0x44, 0x78, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00,
|
|
||||||
0x00, 0x3c, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x52, 0x4a, 0x44,
|
|
||||||
0x44, 0x3a, 0x00, 0x00, 0x00, 0x7c, 0x42, 0x42, 0x42, 0x42, 0x42, 0x7c,
|
|
||||||
0x48, 0x48, 0x44, 0x44, 0x42, 0x42, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x42,
|
|
||||||
0x40, 0x40, 0x40, 0x3c, 0x02, 0x02, 0x02, 0x42, 0x42, 0x3c, 0x00, 0x00,
|
|
||||||
0x00, 0x7f, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
|
|
||||||
0x08, 0x08, 0x00, 0x00, 0x00, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42,
|
|
||||||
0x42, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x41, 0x41, 0x41,
|
|
||||||
0x41, 0x41, 0x41, 0x41, 0x22, 0x22, 0x22, 0x14, 0x1c, 0x08, 0x00, 0x00,
|
|
||||||
0x00, 0x41, 0x41, 0x41, 0x41, 0x49, 0x49, 0x49, 0x49, 0x55, 0x55, 0x55,
|
|
||||||
0x22, 0x22, 0x00, 0x00, 0x00, 0x41, 0x41, 0x22, 0x36, 0x14, 0x08, 0x08,
|
|
||||||
0x08, 0x14, 0x36, 0x22, 0x41, 0x41, 0x00, 0x00, 0x00, 0x41, 0x41, 0x22,
|
|
||||||
0x22, 0x14, 0x14, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00,
|
|
||||||
0x00, 0x7e, 0x02, 0x02, 0x04, 0x04, 0x08, 0x18, 0x10, 0x20, 0x20, 0x40,
|
|
||||||
0x40, 0x7e, 0x00, 0x00, 0x00, 0x1c, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
|
|
||||||
0x10, 0x10, 0x10, 0x10, 0x10, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80,
|
|
||||||
0x40, 0x20, 0x20, 0x10, 0x10, 0x08, 0x08, 0x04, 0x02, 0x02, 0x00, 0x00,
|
|
||||||
0x00, 0x1c, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
|
|
||||||
0x04, 0x1c, 0x00, 0x00, 0x00, 0x08, 0x14, 0x22, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00,
|
|
||||||
0x00, 0x10, 0x08, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x44, 0x04,
|
|
||||||
0x3c, 0x44, 0x44, 0x44, 0x48, 0x36, 0x00, 0x00, 0x00, 0x40, 0x40, 0x40,
|
|
||||||
0x40, 0x5c, 0x62, 0x42, 0x42, 0x42, 0x42, 0x42, 0x62, 0x5c, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x40, 0x40, 0x40, 0x40, 0x40,
|
|
||||||
0x42, 0x3c, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x3a, 0x46, 0x42,
|
|
||||||
0x42, 0x42, 0x42, 0x42, 0x46, 0x3a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x3c, 0x42, 0x42, 0x42, 0x7e, 0x40, 0x40, 0x42, 0x3c, 0x00, 0x00,
|
|
||||||
0x00, 0x0c, 0x12, 0x10, 0x10, 0x7c, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
|
|
||||||
0x10, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3a, 0x46, 0x42,
|
|
||||||
0x42, 0x42, 0x42, 0x46, 0x3a, 0x02, 0x02, 0x3c, 0x00, 0x40, 0x40, 0x40,
|
|
||||||
0x40, 0x5c, 0x62, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x00, 0x00,
|
|
||||||
0x00, 0x08, 0x08, 0x00, 0x00, 0x18, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
|
|
||||||
0x08, 0x1c, 0x00, 0x00, 0x00, 0x04, 0x04, 0x00, 0x00, 0x0c, 0x04, 0x04,
|
|
||||||
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x24, 0x18, 0x00, 0x40, 0x40, 0x40,
|
|
||||||
0x40, 0x42, 0x44, 0x48, 0x50, 0x60, 0x50, 0x48, 0x44, 0x42, 0x00, 0x00,
|
|
||||||
0x00, 0x18, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
|
|
||||||
0x08, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x52, 0x6d, 0x49,
|
|
||||||
0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x5c, 0x62, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42,
|
|
||||||
0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5c, 0x62, 0x42,
|
|
||||||
0x42, 0x42, 0x42, 0x42, 0x62, 0x5c, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x3a, 0x46, 0x42, 0x42, 0x42, 0x42, 0x42, 0x46, 0x3a, 0x02, 0x02,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x2c, 0x32, 0x20, 0x20, 0x20, 0x20, 0x20,
|
|
||||||
0x20, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x40,
|
|
||||||
0x40, 0x3c, 0x02, 0x02, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x10, 0x10, 0x10,
|
|
||||||
0x10, 0x7c, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x12, 0x0c, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42,
|
|
||||||
0x46, 0x3a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x41, 0x41,
|
|
||||||
0x41, 0x22, 0x22, 0x14, 0x14, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x36, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x42, 0x66, 0x24, 0x18, 0x24, 0x66,
|
|
||||||
0x42, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x42, 0x42,
|
|
||||||
0x42, 0x42, 0x42, 0x46, 0x3a, 0x02, 0x02, 0x3c, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x7e, 0x02, 0x04, 0x04, 0x18, 0x20, 0x20, 0x40, 0x7e, 0x00, 0x00,
|
|
||||||
0x00, 0x04, 0x08, 0x08, 0x08, 0x08, 0x08, 0x10, 0x08, 0x08, 0x08, 0x08,
|
|
||||||
0x08, 0x04, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
|
|
||||||
0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x20, 0x10, 0x10,
|
|
||||||
0x10, 0x10, 0x10, 0x08, 0x10, 0x10, 0x10, 0x10, 0x10, 0x20, 0x00, 0x00,
|
|
||||||
0x00, 0x32, 0x4c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x28,
|
|
||||||
0x44, 0x82, 0x82, 0x82, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x22, 0x42,
|
|
||||||
0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x42, 0x22, 0x1c, 0x08, 0x38,
|
|
||||||
0x00, 0x42, 0x42, 0x00, 0x00, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42,
|
|
||||||
0x46, 0x3a, 0x00, 0x00, 0x00, 0x04, 0x08, 0x10, 0x00, 0x3c, 0x42, 0x42,
|
|
||||||
0x42, 0x7e, 0x40, 0x40, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x10, 0x28, 0x44,
|
|
||||||
0x00, 0x38, 0x44, 0x04, 0x3c, 0x44, 0x44, 0x44, 0x48, 0x36, 0x00, 0x00,
|
|
||||||
0x00, 0x44, 0x44, 0x00, 0x00, 0x38, 0x44, 0x04, 0x3c, 0x44, 0x44, 0x44,
|
|
||||||
0x48, 0x36, 0x00, 0x00, 0x00, 0x20, 0x10, 0x08, 0x00, 0x38, 0x44, 0x04,
|
|
||||||
0x3c, 0x44, 0x44, 0x44, 0x48, 0x36, 0x00, 0x00, 0x00, 0x18, 0x24, 0x18,
|
|
||||||
0x00, 0x38, 0x44, 0x04, 0x3c, 0x44, 0x44, 0x44, 0x48, 0x36, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x40, 0x40, 0x40, 0x40, 0x40,
|
|
||||||
0x42, 0x3c, 0x08, 0x38, 0x00, 0x18, 0x24, 0x42, 0x00, 0x3c, 0x42, 0x42,
|
|
||||||
0x42, 0x7e, 0x40, 0x40, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x42, 0x42, 0x00,
|
|
||||||
0x00, 0x3c, 0x42, 0x42, 0x42, 0x7e, 0x40, 0x40, 0x42, 0x3c, 0x00, 0x00,
|
|
||||||
0x00, 0x20, 0x10, 0x08, 0x00, 0x3c, 0x42, 0x42, 0x42, 0x7e, 0x40, 0x40,
|
|
||||||
0x42, 0x3c, 0x00, 0x00, 0x00, 0x42, 0x42, 0x00, 0x00, 0x18, 0x08, 0x08,
|
|
||||||
0x08, 0x08, 0x08, 0x08, 0x08, 0x1c, 0x00, 0x00, 0x00, 0x08, 0x14, 0x22,
|
|
||||||
0x00, 0x18, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x1c, 0x00, 0x00,
|
|
||||||
0x00, 0x20, 0x10, 0x08, 0x00, 0x18, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
|
|
||||||
0x08, 0x1c, 0x00, 0x00, 0x00, 0x42, 0x42, 0x18, 0x24, 0x42, 0x42, 0x42,
|
|
||||||
0x7e, 0x42, 0x42, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x18, 0x24, 0x18,
|
|
||||||
0x24, 0x42, 0x42, 0x42, 0x7e, 0x42, 0x42, 0x42, 0x42, 0x42, 0x00, 0x00,
|
|
||||||
0x04, 0x08, 0x7e, 0x40, 0x40, 0x40, 0x40, 0x7c, 0x40, 0x40, 0x40, 0x40,
|
|
||||||
0x40, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x49, 0x09,
|
|
||||||
0x39, 0x4f, 0x48, 0x48, 0x49, 0x36, 0x00, 0x00, 0x00, 0x1f, 0x28, 0x48,
|
|
||||||
0x48, 0x48, 0x48, 0x7f, 0x48, 0x48, 0x48, 0x48, 0x48, 0x4f, 0x00, 0x00,
|
|
||||||
0x00, 0x18, 0x24, 0x42, 0x00, 0x3c, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42,
|
|
||||||
0x42, 0x3c, 0x00, 0x00, 0x00, 0x42, 0x42, 0x00, 0x00, 0x3c, 0x42, 0x42,
|
|
||||||
0x42, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x20, 0x10, 0x08,
|
|
||||||
0x00, 0x3c, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00,
|
|
||||||
0x00, 0x18, 0x24, 0x42, 0x00, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42,
|
|
||||||
0x46, 0x3a, 0x00, 0x00, 0x00, 0x20, 0x10, 0x08, 0x00, 0x42, 0x42, 0x42,
|
|
||||||
0x42, 0x42, 0x42, 0x42, 0x46, 0x3a, 0x00, 0x00, 0x00, 0x42, 0x42, 0x00,
|
|
||||||
0x00, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x46, 0x3a, 0x02, 0x02, 0x3c,
|
|
||||||
0x42, 0x42, 0x00, 0x3c, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42,
|
|
||||||
0x42, 0x3c, 0x00, 0x00, 0x42, 0x42, 0x00, 0x42, 0x42, 0x42, 0x42, 0x42,
|
|
||||||
0x42, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08,
|
|
||||||
0x08, 0x3e, 0x49, 0x48, 0x48, 0x48, 0x48, 0x49, 0x3e, 0x08, 0x08, 0x00,
|
|
||||||
0x00, 0x0c, 0x12, 0x10, 0x10, 0x10, 0x7c, 0x10, 0x10, 0x08, 0x38, 0x49,
|
|
||||||
0x49, 0x36, 0x00, 0x00, 0x00, 0x41, 0x41, 0x22, 0x22, 0x14, 0x7f, 0x08,
|
|
||||||
0x08, 0x7f, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x78, 0x44, 0x42,
|
|
||||||
0x42, 0x44, 0x78, 0x40, 0x44, 0x5f, 0x44, 0x44, 0x45, 0x42, 0x00, 0x00,
|
|
||||||
0x00, 0x06, 0x09, 0x09, 0x08, 0x08, 0x3e, 0x08, 0x08, 0x08, 0x08, 0x48,
|
|
||||||
0x48, 0x30, 0x00, 0x00, 0x00, 0x08, 0x10, 0x20, 0x00, 0x38, 0x44, 0x04,
|
|
||||||
0x3c, 0x44, 0x44, 0x44, 0x48, 0x36, 0x00, 0x00, 0x00, 0x04, 0x08, 0x10,
|
|
||||||
0x00, 0x18, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x1c, 0x00, 0x00,
|
|
||||||
0x00, 0x04, 0x08, 0x10, 0x00, 0x3c, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42,
|
|
||||||
0x42, 0x3c, 0x00, 0x00, 0x00, 0x04, 0x08, 0x10, 0x00, 0x42, 0x42, 0x42,
|
|
||||||
0x42, 0x42, 0x42, 0x42, 0x46, 0x3a, 0x00, 0x00, 0x00, 0x32, 0x4c, 0x00,
|
|
||||||
0x00, 0x5c, 0x62, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x00, 0x00,
|
|
||||||
0x32, 0x4c, 0x00, 0x42, 0x62, 0x62, 0x52, 0x52, 0x4a, 0x4a, 0x46, 0x46,
|
|
||||||
0x42, 0x42, 0x00, 0x00, 0x00, 0x38, 0x48, 0x48, 0x34, 0x00, 0x7c, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x48, 0x48,
|
|
||||||
0x30, 0x00, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x10, 0x10, 0x00, 0x00, 0x10, 0x10, 0x10, 0x20, 0x40, 0x42, 0x42,
|
|
||||||
0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e,
|
|
||||||
0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x7e, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x10, 0x30, 0x10, 0x10, 0x11, 0x3a, 0x04, 0x08, 0x16, 0x29, 0x42,
|
|
||||||
0x04, 0x08, 0x0f, 0x00, 0x00, 0x10, 0x30, 0x10, 0x10, 0x11, 0x3a, 0x04,
|
|
||||||
0x08, 0x12, 0x26, 0x4a, 0x1f, 0x02, 0x02, 0x00, 0x00, 0x00, 0x08, 0x08,
|
|
||||||
0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x24, 0x48, 0x24, 0x12, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x24, 0x12,
|
|
||||||
0x24, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x44, 0x11, 0x44,
|
|
||||||
0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44,
|
|
||||||
0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa,
|
|
||||||
0x55, 0xaa, 0x55, 0xaa, 0xee, 0xbb, 0xee, 0xbb, 0xee, 0xbb, 0xee, 0xbb,
|
|
||||||
0xee, 0xbb, 0xee, 0xbb, 0xee, 0xbb, 0xee, 0xbb, 0x08, 0x08, 0x08, 0x08,
|
|
||||||
0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
|
|
||||||
0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0xf8, 0x08, 0x08, 0x08,
|
|
||||||
0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0xf8, 0x08,
|
|
||||||
0xf8, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x24, 0x24, 0x24, 0x24,
|
|
||||||
0x24, 0x24, 0x24, 0x24, 0xe4, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x24, 0x24, 0x24,
|
|
||||||
0x24, 0x24, 0x24, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x08,
|
|
||||||
0xf8, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x24, 0x24, 0x24, 0x24,
|
|
||||||
0x24, 0x24, 0xe4, 0x04, 0xe4, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24,
|
|
||||||
0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24,
|
|
||||||
0x24, 0x24, 0x24, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x04,
|
|
||||||
0xe4, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24,
|
|
||||||
0x24, 0x24, 0xe4, 0x04, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0xfc, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0xf8, 0x08,
|
|
||||||
0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0xf8, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
|
|
||||||
0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x0f, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
|
|
||||||
0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0xff, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
|
|
||||||
0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x0f, 0x08, 0x08, 0x08,
|
|
||||||
0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08,
|
|
||||||
0x08, 0x08, 0x08, 0x08, 0xff, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
|
|
||||||
0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x0f, 0x08, 0x0f, 0x08, 0x08, 0x08,
|
|
||||||
0x08, 0x08, 0x08, 0x08, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24,
|
|
||||||
0x27, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24,
|
|
||||||
0x24, 0x24, 0x27, 0x20, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x20, 0x27, 0x24, 0x24, 0x24,
|
|
||||||
0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0xe7, 0x00,
|
|
||||||
0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0xff, 0x00, 0xe7, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24,
|
|
||||||
0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x27, 0x20, 0x27, 0x24, 0x24, 0x24,
|
|
||||||
0x24, 0x24, 0x24, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00,
|
|
||||||
0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x24, 0x24, 0x24,
|
|
||||||
0x24, 0x24, 0xe7, 0x00, 0xe7, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24,
|
|
||||||
0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24,
|
|
||||||
0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0xff, 0x00, 0xff, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x24, 0x24, 0x24,
|
|
||||||
0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24,
|
|
||||||
0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08,
|
|
||||||
0x08, 0x08, 0x0f, 0x08, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x08, 0x0f, 0x08, 0x08, 0x08,
|
|
||||||
0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x3f, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24,
|
|
||||||
0x24, 0x24, 0x24, 0x24, 0xff, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24,
|
|
||||||
0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0xff, 0x08, 0xff, 0x08, 0x08, 0x08,
|
|
||||||
0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
|
|
||||||
0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x0f, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
|
|
||||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
|
||||||
0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0xf0, 0xf0, 0xf0,
|
|
||||||
0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0,
|
|
||||||
0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f,
|
|
||||||
0x0f, 0x0f, 0x0f, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x32, 0x4a, 0x4a, 0x44, 0x44, 0x44, 0x44, 0x4a, 0x32, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x44, 0x44, 0x48, 0x44, 0x42, 0x42,
|
|
||||||
0x42, 0x4c, 0x40, 0x40, 0x00, 0x7e, 0x42, 0x42, 0x40, 0x40, 0x40, 0x40,
|
|
||||||
0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x7f, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x00, 0x00,
|
|
||||||
0x00, 0x7f, 0x40, 0x40, 0x20, 0x10, 0x08, 0x04, 0x08, 0x10, 0x20, 0x40,
|
|
||||||
0x40, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x48, 0x44,
|
|
||||||
0x44, 0x44, 0x44, 0x44, 0x44, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x62, 0x5d, 0x40, 0x40,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x4e, 0x08, 0x08, 0x08, 0x08, 0x08,
|
|
||||||
0x08, 0x08, 0x00, 0x00, 0x00, 0x7f, 0x08, 0x08, 0x1c, 0x22, 0x41, 0x41,
|
|
||||||
0x41, 0x22, 0x1c, 0x08, 0x08, 0x7f, 0x00, 0x00, 0x00, 0x18, 0x24, 0x24,
|
|
||||||
0x42, 0x42, 0x42, 0x7e, 0x42, 0x42, 0x42, 0x24, 0x24, 0x18, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x18, 0x24, 0x24, 0x42, 0x42, 0x42, 0x42, 0x42, 0x24, 0x24,
|
|
||||||
0x24, 0x66, 0x00, 0x00, 0x00, 0x0e, 0x11, 0x08, 0x04, 0x1c, 0x22, 0x42,
|
|
||||||
0x42, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x36, 0x49, 0x49, 0x49, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x02, 0x02, 0x04, 0x3c, 0x4a, 0x4a, 0x52, 0x52, 0x3c, 0x20,
|
|
||||||
0x40, 0x40, 0x00, 0x00, 0x00, 0x0e, 0x10, 0x20, 0x20, 0x40, 0x40, 0x7c,
|
|
||||||
0x40, 0x40, 0x20, 0x20, 0x10, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c,
|
|
||||||
0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x7e,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x3e,
|
|
||||||
0x08, 0x08, 0x08, 0x08, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20,
|
|
||||||
0x10, 0x08, 0x04, 0x02, 0x04, 0x08, 0x10, 0x20, 0x00, 0x7e, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x04, 0x08, 0x10, 0x20, 0x40, 0x20, 0x10, 0x08, 0x04,
|
|
||||||
0x00, 0x7e, 0x00, 0x00, 0x00, 0x06, 0x09, 0x09, 0x09, 0x08, 0x08, 0x08,
|
|
||||||
0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
|
|
||||||
0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x48, 0x48, 0x48, 0x30, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x18, 0x18,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x32, 0x4c, 0x00,
|
|
||||||
0x32, 0x4c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x48, 0x48,
|
|
||||||
0x48, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x08, 0x08,
|
|
||||||
0x08, 0x08, 0x08, 0x08, 0x28, 0x68, 0x28, 0x18, 0x18, 0x08, 0x00, 0x00,
|
|
||||||
0x00, 0x58, 0x64, 0x44, 0x44, 0x44, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x24, 0x04, 0x18, 0x20, 0x3c, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00
|
|
||||||
};
|
|
||||||
unsigned int FM_T_437_F16_len = 4096;
|
|
||||||
345
kernel/font.h
Normal file
345
kernel/font.h
Normal file
@ -0,0 +1,345 @@
|
|||||||
|
unsigned char FLORI_F16[] = {
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0xc3, 0x81, 0xe7, 0x81, 0xe7,
|
||||||
|
0xbd, 0xc3, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0xff,
|
||||||
|
0xff, 0x99, 0xff, 0xbd, 0x99, 0xc3, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x36, 0x7f, 0x7f, 0x7f, 0x7f, 0x3e, 0x1c, 0x08, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x1c, 0x3e, 0x7f, 0x3e,
|
||||||
|
0x1c, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3c,
|
||||||
|
0x3c, 0xe7, 0xe7, 0xe7, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x18, 0x3c, 0x7e, 0xff, 0xff, 0x7e, 0x18, 0x18, 0x3c, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3c, 0x3c,
|
||||||
|
0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
|
||||||
|
0xff, 0xe7, 0xc3, 0xc3, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x42, 0x42, 0x66, 0x3c, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xc3, 0x99, 0xbd, 0xbd,
|
||||||
|
0x99, 0xc3, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x07,
|
||||||
|
0x0d, 0x19, 0x3c, 0x66, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0xff, 0x81, 0x99, 0xbd, 0xff, 0x99, 0x99, 0x99, 0x99, 0x81, 0x81,
|
||||||
|
0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x33, 0x3f, 0x30, 0x30, 0x30,
|
||||||
|
0x70, 0xf0, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x63,
|
||||||
|
0x7f, 0x63, 0x63, 0x63, 0x67, 0xe7, 0xe6, 0xc0, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x18, 0x18, 0xdb, 0x3c, 0xe7, 0x3c, 0xdb, 0x18, 0x18, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xf0, 0xd8, 0xcc, 0xc6, 0xc3, 0xc6,
|
||||||
|
0xcc, 0xd8, 0xf0, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x0f, 0x1b,
|
||||||
|
0x33, 0x63, 0xc3, 0x63, 0x33, 0x1b, 0x0f, 0x07, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x18, 0x3c, 0x7e, 0xff, 0x18, 0x18, 0x18, 0xff, 0x7e, 0x3c, 0x18,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33,
|
||||||
|
0x00, 0x00, 0x33, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xdb,
|
||||||
|
0xdb, 0xdb, 0x7b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x3e, 0x63, 0x30, 0x7c, 0x66, 0x33, 0x1f, 0x06, 0x63, 0x3e,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x7f, 0x7f, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3c, 0x7e,
|
||||||
|
0xff, 0x18, 0x18, 0x18, 0xff, 0x7e, 0x3c, 0xff, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x18, 0x3c, 0x7e, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
|
||||||
|
0xff, 0x7e, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08,
|
||||||
|
0x0c, 0x0e, 0xff, 0x0e, 0x0c, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x10, 0x30, 0x70, 0xff, 0x70, 0x30, 0x10, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x60, 0x60,
|
||||||
|
0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x24, 0x66, 0xff, 0x66, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x18, 0x18, 0x3c, 0x3c, 0x66, 0x66, 0xc3, 0xc3, 0xff,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xc3, 0xc3, 0x66, 0x66,
|
||||||
|
0x3c, 0x3c, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x24, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x36, 0x7f, 0x36, 0x36, 0x36, 0x7f, 0x36, 0x36, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x08, 0x08, 0x3e, 0x6b, 0x68, 0x68, 0x3e, 0x0b, 0x0b, 0x6b, 0x3e,
|
||||||
|
0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0xdb, 0x76, 0x0c, 0x18,
|
||||||
|
0x30, 0x6e, 0xdb, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c,
|
||||||
|
0x36, 0x3c, 0x18, 0x3b, 0x6e, 0x66, 0x6e, 0x3b, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x0c, 0x0c, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x18, 0x30, 0x30, 0x30, 0x30,
|
||||||
|
0x30, 0x30, 0x18, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x18,
|
||||||
|
0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x08, 0x6b, 0x3e, 0x7f, 0x3e, 0x6b, 0x08, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0xff,
|
||||||
|
0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
|
||||||
|
0x03, 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x3e, 0x63, 0x63, 0x67, 0x6f, 0x7b, 0x73, 0x63, 0x63, 0x3e,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x1c, 0x3c, 0x0c, 0x0c, 0x0c,
|
||||||
|
0x0c, 0x0c, 0x0c, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x63,
|
||||||
|
0x43, 0x03, 0x0e, 0x38, 0x60, 0x60, 0x61, 0x7f, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x3e, 0x63, 0x43, 0x03, 0x1e, 0x03, 0x03, 0x03, 0x63, 0x3e,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x0c, 0x18, 0x33, 0x63, 0x63,
|
||||||
|
0x7f, 0x03, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x61,
|
||||||
|
0x60, 0x60, 0x7e, 0x03, 0x03, 0x03, 0x63, 0x3e, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x1e, 0x30, 0x60, 0x60, 0x7e, 0x63, 0x63, 0x63, 0x63, 0x3e,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x43, 0x03, 0x03, 0x06, 0x0c,
|
||||||
|
0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x63,
|
||||||
|
0x63, 0x63, 0x3e, 0x63, 0x63, 0x63, 0x63, 0x3e, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x3e, 0x63, 0x63, 0x63, 0x63, 0x3f, 0x03, 0x03, 0x06, 0x3c,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00,
|
||||||
|
0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x06, 0x0c, 0x18, 0x30, 0x60, 0x30, 0x18, 0x0c, 0x06,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00,
|
||||||
|
0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60,
|
||||||
|
0x30, 0x18, 0x0c, 0x06, 0x0c, 0x18, 0x30, 0x60, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x3e, 0x63, 0x63, 0x03, 0x0e, 0x18, 0x18, 0x00, 0x18, 0x18,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x63, 0x6f, 0x6b, 0x6b,
|
||||||
|
0x6b, 0x6e, 0x60, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x33,
|
||||||
|
0x63, 0x63, 0x63, 0xff, 0x63, 0x63, 0x63, 0xe3, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x3e, 0x63, 0xe3, 0x63, 0x7e, 0x63, 0x63, 0x63, 0x63, 0xfe,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x33, 0x63, 0x60, 0x60, 0x60,
|
||||||
|
0x60, 0x63, 0x63, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x63,
|
||||||
|
0xe3, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0xfe, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x3f, 0x61, 0xe0, 0x60, 0x7c, 0x60, 0x60, 0x60, 0x61, 0xff,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x61, 0xe0, 0x60, 0x7c, 0x60,
|
||||||
|
0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x33,
|
||||||
|
0x63, 0x60, 0x60, 0x6f, 0x63, 0x63, 0x63, 0x3f, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x63, 0xe3, 0x63, 0x63, 0x7f, 0x63, 0x63, 0x63, 0x63, 0xe3,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x38, 0x18, 0x18, 0x18, 0x18,
|
||||||
|
0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x0e,
|
||||||
|
0x06, 0x06, 0x06, 0x06, 0x66, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x63, 0xe3, 0x66, 0x6c, 0x78, 0x7c, 0x66, 0x63, 0x63, 0xe3,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x70, 0xe0, 0x60, 0x60, 0x60,
|
||||||
|
0x60, 0x60, 0x61, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xe7,
|
||||||
|
0xff, 0xdb, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x63, 0xf3, 0x7b, 0x6f, 0x67, 0x63, 0x63, 0x63, 0x63, 0xe3,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x33, 0x63, 0x63, 0x63, 0x63,
|
||||||
|
0x63, 0x63, 0x63, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x63,
|
||||||
|
0xe3, 0x63, 0x63, 0x7e, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x1e, 0x33, 0x63, 0x63, 0x63, 0x63, 0x63, 0x7b, 0x6f, 0x3e,
|
||||||
|
0x06, 0x03, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x63, 0xe3, 0x63, 0x63, 0x7e,
|
||||||
|
0x6c, 0x66, 0x63, 0xe3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x33,
|
||||||
|
0x63, 0x60, 0x78, 0x1e, 0x03, 0x63, 0x63, 0x7e, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0xff, 0xd9, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x63, 0xe3, 0x63, 0x63, 0x63, 0x63,
|
||||||
|
0x63, 0x63, 0x67, 0x3b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x63, 0xe3,
|
||||||
|
0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x36, 0x1c, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xdb, 0xdb, 0xff, 0x66,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x63, 0xe3, 0x63, 0x3e, 0x1c, 0x3e,
|
||||||
|
0x63, 0x63, 0x63, 0xe3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xc3,
|
||||||
|
0xc3, 0x66, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x3f, 0x63, 0x03, 0x06, 0x0c, 0x18, 0x30, 0x60, 0x61, 0x7f,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x30, 0x30, 0x30, 0x30, 0x30,
|
||||||
|
0x30, 0x30, 0x30, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
|
||||||
|
0xc0, 0x60, 0x30, 0x18, 0x0c, 0x06, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x3c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x3c,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x08, 0x1c, 0x36, 0x63, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x30, 0x30, 0x18, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x03, 0x3f,
|
||||||
|
0x63, 0x63, 0x67, 0x3b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0xe0,
|
||||||
|
0x60, 0x6e, 0x73, 0x63, 0x63, 0x63, 0x63, 0x7e, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x63, 0x60, 0x60, 0x60, 0x63, 0x3e,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x07, 0x03, 0x3f, 0x63, 0x63,
|
||||||
|
0x63, 0x63, 0x67, 0x3b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x3e, 0x63, 0x63, 0x6e, 0x78, 0x73, 0x3e, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x1e, 0x33, 0x30, 0x30, 0x7c, 0x30, 0x30, 0x30, 0x30, 0x30,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x63, 0x63,
|
||||||
|
0x63, 0x67, 0x3b, 0x03, 0x63, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x60, 0xe0,
|
||||||
|
0x60, 0x6e, 0x73, 0x63, 0x63, 0x63, 0x63, 0x63, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x18, 0x18, 0x00, 0x18, 0x38, 0x18, 0x18, 0x18, 0x1b, 0x0e,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x06, 0x00, 0x06, 0x0e, 0x06,
|
||||||
|
0x06, 0x06, 0x06, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x60, 0xe0,
|
||||||
|
0x60, 0x66, 0x66, 0x7c, 0x78, 0x6c, 0x66, 0x63, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x18, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1b, 0x0e,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xdb, 0xdb,
|
||||||
|
0xdb, 0xdb, 0xdb, 0xdb, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x6e, 0xf3, 0x63, 0x63, 0x63, 0x63, 0x63, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x63, 0x63, 0x63, 0x63, 0x63, 0x3e,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6e, 0xf3, 0x63,
|
||||||
|
0x63, 0x63, 0x63, 0x7e, 0x60, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x3f, 0x63, 0x63, 0x63, 0x63, 0x67, 0x3b, 0x03, 0x03, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x6e, 0xf3, 0x63, 0x60, 0x60, 0x60, 0x60,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x63, 0x60,
|
||||||
|
0x3e, 0x03, 0x63, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x18,
|
||||||
|
0x18, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x1b, 0x0e, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x63, 0xe3, 0x63, 0x63, 0x63, 0x67, 0x3b,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x63, 0xe3, 0x63,
|
||||||
|
0x63, 0x66, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0xc3, 0xc3, 0xc3, 0xdb, 0xdb, 0xff, 0x66, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0xe3, 0x36, 0x1c, 0x1c, 0x1c, 0x36, 0x63,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x63, 0xe3, 0x63,
|
||||||
|
0x63, 0x67, 0x3b, 0x03, 0x63, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x3f, 0x66, 0x0c, 0x18, 0x30, 0x61, 0x7f, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x0e, 0x18, 0x18, 0x18, 0x70, 0x18, 0x18, 0x18, 0x18, 0x0e,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x00, 0x18,
|
||||||
|
0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x18,
|
||||||
|
0x18, 0x18, 0x0e, 0x18, 0x18, 0x18, 0x18, 0x70, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x3b, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x1c, 0x36,
|
||||||
|
0x63, 0x63, 0x63, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x33,
|
||||||
|
0x63, 0x60, 0x60, 0x60, 0x60, 0x63, 0x63, 0x3e, 0x03, 0x0e, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x63, 0x63, 0x00, 0x63, 0xe3, 0x63, 0x63, 0x63, 0x67, 0x3b,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x18, 0x30, 0x00, 0x3e, 0x63, 0x63,
|
||||||
|
0x7f, 0x60, 0x63, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x1e, 0x33,
|
||||||
|
0x00, 0x3e, 0x03, 0x3f, 0x63, 0x63, 0x67, 0x3b, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x33, 0x33, 0x00, 0x3e, 0x03, 0x3f, 0x63, 0x63, 0x67, 0x3b,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x0c, 0x06, 0x00, 0x3e, 0x03, 0x3f,
|
||||||
|
0x63, 0x63, 0x67, 0x3b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x36, 0x1c,
|
||||||
|
0x00, 0x3e, 0x03, 0x3f, 0x63, 0x63, 0x67, 0x3b, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x63, 0x60, 0x60, 0x60, 0x63, 0x3e,
|
||||||
|
0x03, 0x0e, 0x00, 0x00, 0x00, 0x08, 0x1c, 0x36, 0x00, 0x3e, 0x63, 0x63,
|
||||||
|
0x7f, 0x60, 0x63, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0x33,
|
||||||
|
0x00, 0x3e, 0x63, 0x63, 0x7f, 0x60, 0x63, 0x3e, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x18, 0x0c, 0x06, 0x00, 0x3e, 0x63, 0x63, 0x7f, 0x60, 0x63, 0x3e,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x36, 0x00, 0x18, 0x18, 0x18,
|
||||||
|
0x18, 0x18, 0x1b, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x1c, 0x36,
|
||||||
|
0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1b, 0x0e, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x30, 0x18, 0x0c, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1b, 0x0e,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x63, 0x63, 0x1e, 0x33, 0x63, 0x63, 0xff,
|
||||||
|
0x63, 0x63, 0x63, 0xe3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x33, 0x1e,
|
||||||
|
0x33, 0x63, 0x63, 0xff, 0x63, 0x63, 0x63, 0xe3, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x1c, 0x30, 0x3f, 0x61, 0xe0, 0x7c, 0x60, 0x60, 0x60, 0x61, 0xff,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x1b, 0x1b,
|
||||||
|
0xfb, 0xdf, 0xd8, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x36,
|
||||||
|
0x66, 0x66, 0x66, 0xff, 0x66, 0x66, 0x66, 0xe7, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x08, 0x1c, 0x36, 0x00, 0x3e, 0x63, 0x63, 0x63, 0x63, 0x63, 0x3e,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x63, 0x63, 0x00, 0x3e, 0x63, 0x63,
|
||||||
|
0x63, 0x63, 0x63, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x18, 0x0c,
|
||||||
|
0x00, 0x3e, 0x63, 0x63, 0x63, 0x63, 0x63, 0x3e, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x08, 0x1c, 0x36, 0x00, 0x63, 0xe3, 0x63, 0x63, 0x63, 0x67, 0x3b,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x18, 0x0c, 0x00, 0x63, 0xe3, 0x63,
|
||||||
|
0x63, 0x63, 0x67, 0x3b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x63, 0x63,
|
||||||
|
0x00, 0x63, 0xe3, 0x63, 0x63, 0x63, 0x3f, 0x03, 0x63, 0x3e, 0x00, 0x00,
|
||||||
|
0x00, 0x63, 0x63, 0x00, 0x1e, 0x33, 0x63, 0x63, 0x63, 0x63, 0x63, 0x3e,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x63, 0x63, 0x00, 0x63, 0xe3, 0x63, 0x63,
|
||||||
|
0x63, 0x63, 0x67, 0x3b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x18, 0x18, 0x7e, 0xc3, 0xc0, 0xc0, 0xc3, 0x7e, 0x18, 0x18, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x1c, 0x36, 0x30, 0x30, 0x78, 0x30, 0x30, 0x30, 0x73, 0x7e,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0x66, 0x3c, 0x18, 0xff, 0x18,
|
||||||
|
0xff, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x66,
|
||||||
|
0x66, 0x7c, 0x62, 0x66, 0x6f, 0x66, 0x66, 0x77, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x0e, 0x1b, 0x18, 0x18, 0x7e, 0x18, 0x18, 0x18, 0x18, 0xd8,
|
||||||
|
0x70, 0x00, 0x00, 0x00, 0x00, 0x06, 0x0c, 0x18, 0x00, 0x3e, 0x03, 0x3f,
|
||||||
|
0x63, 0x63, 0x67, 0x3b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x18, 0x30,
|
||||||
|
0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1b, 0x0e, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x0c, 0x18, 0x30, 0x00, 0x3e, 0x63, 0x63, 0x63, 0x63, 0x63, 0x3e,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x18, 0x30, 0x00, 0x63, 0xe3, 0x63,
|
||||||
|
0x63, 0x63, 0x63, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3b, 0x6e,
|
||||||
|
0x00, 0x6e, 0xf3, 0x63, 0x63, 0x63, 0x63, 0x63, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x3b, 0x6e, 0x00, 0x63, 0xf3, 0x7b, 0x6f, 0x67, 0x63, 0x63, 0xe3,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x6c, 0x6c, 0x3c, 0x00, 0x7e, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6c, 0x6c,
|
||||||
|
0x38, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x0c, 0x0c, 0x00, 0x0c, 0x0c, 0x3c, 0x60, 0x63, 0x63, 0x3e,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x60,
|
||||||
|
0x60, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x7f, 0x03, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x60, 0xe1, 0x63, 0x66, 0x6c, 0x18, 0x36, 0x6b, 0xdb, 0x86, 0x0c,
|
||||||
|
0x1f, 0x00, 0x00, 0x00, 0x00, 0x60, 0xe1, 0x63, 0x66, 0x6c, 0x18, 0x33,
|
||||||
|
0x67, 0xcb, 0x9b, 0x1f, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18,
|
||||||
|
0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x1b, 0x36, 0x6c, 0x36, 0x1b, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6c, 0x36, 0x1b,
|
||||||
|
0x36, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x41, 0x63, 0x36,
|
||||||
|
0x14, 0x41, 0x63, 0x36, 0x14, 0x41, 0x63, 0x36, 0x14, 0x41, 0x63, 0x36,
|
||||||
|
0xdb, 0x00, 0xdb, 0x00, 0xdb, 0x00, 0xdb, 0x00, 0xdb, 0x00, 0xdb, 0x00,
|
||||||
|
0xdb, 0x00, 0xdb, 0x00, 0x00, 0x1c, 0x63, 0x14, 0x63, 0x1c, 0x00, 0x00,
|
||||||
|
0x00, 0x1c, 0x63, 0x14, 0x63, 0x1c, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18,
|
||||||
|
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
|
||||||
|
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0x18, 0x18, 0x18,
|
||||||
|
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x38, 0xf0, 0x00, 0xf0,
|
||||||
|
0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x36, 0x36, 0x36, 0x36,
|
||||||
|
0x36, 0x36, 0x36, 0xf6, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x36, 0x36, 0x36, 0x36,
|
||||||
|
0x36, 0x36, 0x36, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x18, 0xf8,
|
||||||
|
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x36, 0x36, 0x36, 0x36,
|
||||||
|
0x36, 0xf6, 0x06, 0xf6, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
|
||||||
|
0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
|
||||||
|
0x36, 0x36, 0x36, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x0e, 0xe6,
|
||||||
|
0x76, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
|
||||||
|
0x76, 0xe6, 0x0e, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xfe, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0xf8,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0xf0, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
|
||||||
|
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1c, 0x0f, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xff,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
|
||||||
|
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x18,
|
||||||
|
0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18,
|
||||||
|
0x18, 0x18, 0x18, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
|
||||||
|
0x18, 0x18, 0x18, 0x18, 0x1c, 0x0f, 0x00, 0x0f, 0x1c, 0x18, 0x18, 0x18,
|
||||||
|
0x18, 0x18, 0x18, 0x18, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x37,
|
||||||
|
0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
|
||||||
|
0x36, 0x33, 0x38, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x38, 0x33, 0x36, 0x36, 0x36, 0x36,
|
||||||
|
0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xf7, 0x00, 0xff,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0xff, 0x00, 0xf7, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
|
||||||
|
0x36, 0x36, 0x36, 0x36, 0x36, 0x37, 0x30, 0x37, 0x36, 0x36, 0x36, 0x36,
|
||||||
|
0x36, 0x36, 0x36, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xff,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x36, 0x36, 0x36,
|
||||||
|
0x36, 0xf7, 0x00, 0xf7, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
|
||||||
|
0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xe3,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0xff, 0x00, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe3, 0x36, 0x36, 0x36, 0x36,
|
||||||
|
0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x3f,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18,
|
||||||
|
0x18, 0x1f, 0x18, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x18,
|
||||||
|
0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f,
|
||||||
|
0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
|
||||||
|
0x36, 0x36, 0x36, 0xff, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
|
||||||
|
0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x18, 0xff, 0x18, 0x18, 0x18, 0x18,
|
||||||
|
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x38, 0xf0,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x0f, 0x1c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
|
||||||
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||||
|
0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0xf0, 0xf0, 0xf0,
|
||||||
|
0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0,
|
||||||
|
0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f,
|
||||||
|
0x0f, 0x0f, 0x0f, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x3b, 0x6e, 0x6c, 0x6c, 0x6e, 0x3b, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x6e, 0x63, 0x63, 0x63, 0x6e,
|
||||||
|
0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x63, 0x63, 0x60, 0x60, 0x60,
|
||||||
|
0x60, 0x60, 0x60, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x7f, 0x36, 0x36, 0x36, 0x36, 0x36, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0xff, 0xc3, 0x60, 0x30, 0x18, 0x18, 0x30, 0x60, 0xc3, 0xff,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x6c,
|
||||||
|
0x6c, 0x6c, 0x6c, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x33, 0x33, 0x33, 0x33, 0x3e, 0x70, 0x70, 0x60, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3b, 0x6e, 0x0c, 0x0c, 0x0c, 0x0c,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x18, 0x7e, 0xe7, 0xc3, 0xc3,
|
||||||
|
0xe7, 0x7e, 0x18, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3c,
|
||||||
|
0x66, 0xc3, 0xff, 0xc3, 0xc3, 0x66, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x3c, 0x66, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0x66, 0x66, 0xe7,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x30, 0x18, 0x0c, 0x3e, 0x66,
|
||||||
|
0x66, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x7e, 0xdb, 0xdb, 0xdb, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x03, 0x06, 0x7e, 0xdb, 0xdb, 0xf3, 0x7e, 0x60,
|
||||||
|
0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x38, 0x60, 0x60, 0x7e, 0x60,
|
||||||
|
0x60, 0x60, 0x38, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x63,
|
||||||
|
0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x7f, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0xff, 0x18,
|
||||||
|
0x18, 0x18, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x18,
|
||||||
|
0x0c, 0x06, 0x0c, 0x18, 0x30, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x0c, 0x18, 0x30, 0x60, 0x30, 0x18, 0x0c, 0x00, 0x00, 0x7e,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x1b, 0x1b, 0x18, 0x18, 0x18,
|
||||||
|
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
|
||||||
|
0x18, 0x18, 0x18, 0x18, 0xd8, 0xd8, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0xff, 0x00, 0x00, 0x18, 0x18,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3b, 0x6e, 0x00, 0x3b,
|
||||||
|
0x6e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6c, 0x6c,
|
||||||
|
0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x0c, 0x0c,
|
||||||
|
0x0c, 0x0c, 0x0c, 0xec, 0x6c, 0x3c, 0x1c, 0x0c, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x78, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0xd8, 0x18, 0x70, 0xc0, 0xf8, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00
|
||||||
|
};
|
||||||
|
unsigned int FLORI_F16_len = 4096;
|
||||||
@ -1,7 +1,7 @@
|
|||||||
GNU GENERAL PUBLIC LICENSE
|
GNU GENERAL PUBLIC LICENSE
|
||||||
Version 3, 29 June 2007
|
Version 3, 29 June 2007
|
||||||
|
|
||||||
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
|
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
|
||||||
Everyone is permitted to copy and distribute verbatim copies
|
Everyone is permitted to copy and distribute verbatim copies
|
||||||
of this license document, but changing it is not allowed.
|
of this license document, but changing it is not allowed.
|
||||||
|
|
||||||
@ -645,7 +645,7 @@ the "copyright" line and a pointer to where the full notice is found.
|
|||||||
GNU General Public License for more details.
|
GNU General Public License for more details.
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
You should have received a copy of the GNU General Public License
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
Also add information on how to contact you by electronic and paper mail.
|
Also add information on how to contact you by electronic and paper mail.
|
||||||
|
|
||||||
@ -664,11 +664,11 @@ might be different; for a GUI interface, you would use an "about box".
|
|||||||
You should also get your employer (if you work as a programmer) or school,
|
You should also get your employer (if you work as a programmer) or school,
|
||||||
if any, to sign a "copyright disclaimer" for the program, if necessary.
|
if any, to sign a "copyright disclaimer" for the program, if necessary.
|
||||||
For more information on this, and how to apply and follow the GNU GPL, see
|
For more information on this, and how to apply and follow the GNU GPL, see
|
||||||
<http://www.gnu.org/licenses/>.
|
<https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
The GNU General Public License does not permit incorporating your program
|
The GNU General Public License does not permit incorporating your program
|
||||||
into proprietary programs. If your program is a subroutine library, you
|
into proprietary programs. If your program is a subroutine library, you
|
||||||
may consider it more useful to permit linking proprietary applications with
|
may consider it more useful to permit linking proprietary applications with
|
||||||
the library. If this is what you want to do, use the GNU Lesser General
|
the library. If this is what you want to do, use the GNU Lesser General
|
||||||
Public License instead of this License. But first, please read
|
Public License instead of this License. But first, please read
|
||||||
<http://www.gnu.org/philosophy/why-not-lgpl.html>.
|
<https://www.gnu.org/licenses/why-not-lgpl.html>.
|
||||||
167
kernel/fs/fatfs/README.md
Normal file
167
kernel/fs/fatfs/README.md
Normal file
@ -0,0 +1,167 @@
|
|||||||
|
### FAT16/32 File System Library
|
||||||
|
|
||||||
|
Github: [http://github.com/ultraembedded/fat_io_lib](https://github.com/ultraembedded/fat_io_lib)
|
||||||
|
|
||||||
|
#### Intro
|
||||||
|
|
||||||
|
Designed for low memory embedded systems back in 2003, this project is a multi-purpose platform independent C code implementation of a FAT16 & FAT32 driver with read & write support.
|
||||||
|
|
||||||
|
The library provides stdio like interface functions such as fopen(), fgetc(), fputc(), fread(), fwrite() etc, allowing existing applications to be ported easily using a familiar API.
|
||||||
|
The project is aimed at applications which require file system support such as MP3 players, data loggers, etc and has a low memory footprint with customizable build options to enable it to run on platforms such as the Atmel AVR, ARM & PIC microcontrollers.
|
||||||
|
|
||||||
|
The source code is available for free under GPL license, or alternatively, with a commercial compatible license for a small donation.
|
||||||
|
|
||||||
|
This library has been used in many open source projects including;
|
||||||
|
* Aleph - Open source sound computer.
|
||||||
|
* IV:MP - Grand Theft Auto: IV multiplayer game mod.
|
||||||
|
* hxcfloppyemu - HxC Floppy Drive Emulator.
|
||||||
|
|
||||||
|
#### Features
|
||||||
|
|
||||||
|
* Standard file I/O API (fopen(), fread(), fwrite(), etc)
|
||||||
|
* FAT16/FAT32 support (read + write)
|
||||||
|
* Long filename support (optional)
|
||||||
|
* Format function (optional)
|
||||||
|
* Directory listing (optional)
|
||||||
|
* Buffering & caching for higher performance (optional)
|
||||||
|
|
||||||
|
#### API
|
||||||
|
|
||||||
|
The following file IO API is provided:
|
||||||
|
|
||||||
|
* fopen
|
||||||
|
* fclose
|
||||||
|
* fread
|
||||||
|
* fwrite
|
||||||
|
* fputc
|
||||||
|
* fputs
|
||||||
|
* fgetc
|
||||||
|
* fflush
|
||||||
|
* fgetpos
|
||||||
|
* fseek
|
||||||
|
* ftell
|
||||||
|
* feof
|
||||||
|
* remove
|
||||||
|
|
||||||
|
Just add sector read & write functions for the media/platform you are using for a complete file system!
|
||||||
|
|
||||||
|
#### Testing
|
||||||
|
|
||||||
|
Each release of the project is tested using self verifying test benches to ensure validity and to protect against regressions (not currently released).
|
||||||
|
|
||||||
|
#### Commercial
|
||||||
|
|
||||||
|
If you would like to use this code in a commercial project with a closed source compatible license, please contact me.
|
||||||
|
|
||||||
|
#### Configuration
|
||||||
|
See the following defines in src/fat_opts.h:
|
||||||
|
|
||||||
|
```
|
||||||
|
FATFS_IS_LITTLE_ENDIAN [1/0]
|
||||||
|
Which endian is your system? Set to 1 for little endian, 0 for big endian.
|
||||||
|
|
||||||
|
FATFS_MAX_LONG_FILENAME [260]
|
||||||
|
By default, 260 characters (max LFN length). Increase this to support greater path depths.
|
||||||
|
|
||||||
|
FATFS_MAX_OPEN_FILES
|
||||||
|
The more files you wish to have concurrently open, the greater this number should be.
|
||||||
|
This increases the number of FL_FILE file structures in the library, each of these is around 1K in size (assuming 512 byte sectors).
|
||||||
|
|
||||||
|
FAT_BUFFER_SECTORS
|
||||||
|
Minimum is 1, more increases performance.
|
||||||
|
This defines how many FAT sectors can be buffered per FAT_BUFFER entry.
|
||||||
|
|
||||||
|
FAT_BUFFERS
|
||||||
|
Minimum is 1, more increases performance.
|
||||||
|
This defines how many FAT buffer entries are available.
|
||||||
|
Memory usage is FAT_BUFFERS * FAT_BUFFER_SECTORS * FAT_SECTOR_SIZE
|
||||||
|
|
||||||
|
FATFS_INC_WRITE_SUPPORT
|
||||||
|
Support file write functionality.
|
||||||
|
|
||||||
|
FAT_SECTOR_SIZE
|
||||||
|
Sector size used by buffers. Most likely to be 512 bytes (standard for ATA/IDE).
|
||||||
|
|
||||||
|
FAT_PRINTF
|
||||||
|
A define that allows the File IO library to print to console/stdout.
|
||||||
|
Provide your own printf function if printf not available.
|
||||||
|
|
||||||
|
FAT_CLUSTER_CACHE_ENTRIES
|
||||||
|
Size of cluster chain cache (can be undefined if not required).
|
||||||
|
Mem used = FAT_CLUSTER_CACHE_ENTRIES * 4 * 2
|
||||||
|
Improves access speed considerably.
|
||||||
|
|
||||||
|
FATFS_INC_LFN_SUPPORT [1/0]
|
||||||
|
Enable/Disable support for long filenames.
|
||||||
|
|
||||||
|
FATFS_DIR_LIST_SUPPORT [1/0]
|
||||||
|
Include support for directory listing.
|
||||||
|
|
||||||
|
FATFS_INC_TIME_DATE_SUPPORT [1/0]
|
||||||
|
Use time/date functions provided by time.h to update creation & modification timestamps.
|
||||||
|
|
||||||
|
FATFS_INC_FORMAT_SUPPORT
|
||||||
|
Include support for formatting disks (FAT16 only).
|
||||||
|
|
||||||
|
FAT_PRINTF_NOINC_STDIO
|
||||||
|
Disable use of printf & inclusion of stdio.h
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
#### Interfacing to storage media
|
||||||
|
```
|
||||||
|
-----------------------------------------------------------------
|
||||||
|
int media_read(uint32 sector, uint8 *buffer, uint32 sector_count)
|
||||||
|
-----------------------------------------------------------------
|
||||||
|
Params:
|
||||||
|
Sector: 32-bit sector number
|
||||||
|
Buffer: Target buffer to read n sectors of data into.
|
||||||
|
Sector_count: Number of sectors to read
|
||||||
|
|
||||||
|
Return:
|
||||||
|
int, 1 = success, 0 = failure.
|
||||||
|
|
||||||
|
Description:
|
||||||
|
Application/target specific disk/media read function.
|
||||||
|
Sector number (sectors are usually 512 byte pages) to read.
|
||||||
|
|
||||||
|
-----------------------------------------------------------------
|
||||||
|
int media_write(uint32 sector, uint8 *buffer, uint32 sector_count)
|
||||||
|
-----------------------------------------------------------------
|
||||||
|
|
||||||
|
Params:
|
||||||
|
Sector: 32-bit sector number
|
||||||
|
Buffer: Target buffer to write n sectors of data from.
|
||||||
|
Sector_count: Number of sectors to write.
|
||||||
|
|
||||||
|
Return:
|
||||||
|
int, 1 = success, 0 = failure.
|
||||||
|
|
||||||
|
Description:
|
||||||
|
Application/target specific disk/media write function.
|
||||||
|
Sector number (sectors are usually 512 byte pages) to write to.
|
||||||
|
|
||||||
|
|
||||||
|
-----------------------------------------------------------------
|
||||||
|
Use the following API to attach the media IO functions to the File IO library;
|
||||||
|
|
||||||
|
fl_attach_media(media_read, media_write);
|
||||||
|
```
|
||||||
|
|
||||||
|
#### History
|
||||||
|
|
||||||
|
* v2.6.11 - Fix compilation with GCC on 64-bit machines
|
||||||
|
* v2.6.10 - Added support for FAT32 format.
|
||||||
|
* v2.6.9 - Added support for time & date handling.
|
||||||
|
* v2.6.8 - Fixed error with FSINFO sector write.
|
||||||
|
* v2.6.7 - Added fgets(). Fixed C warnings, removed dependency on some string.h functions.
|
||||||
|
* v2.6.6 - Massive read + write performance improvements.
|
||||||
|
* v2.6.5 - Bug fixes for big endian systems.
|
||||||
|
* v2.6.4 - Further bug fixes and performance improvements for write operations.
|
||||||
|
* v2.6.3 - Performance improvements, FAT16 formatting support. Various bug fixes
|
||||||
|
* v2.6 - Basic support for FAT16 added
|
||||||
|
* v2.5 - Code cleaned up. Many bugs fixed. Thread safety functions added.
|
||||||
|
* v2.x - Write support added as well as better stdio like API.
|
||||||
|
* v1.0 - Rewrite of all code to enable multiple files to be opened and provides a better file API.
|
||||||
|
* v0.1b - fopen(), fgetc(), fopenDIR() using new software stack for IDE drives and FAT32 access.
|
||||||
|
* v0.1a - First release; fopen(), fgetc() unbuffered reads.... (27/12/03)
|
||||||
905
kernel/fs/fatfs/fat_access.c
Normal file
905
kernel/fs/fatfs/fat_access.c
Normal file
@ -0,0 +1,905 @@
|
|||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// FAT16/32 File IO Library
|
||||||
|
// V2.6
|
||||||
|
// Ultra-Embedded.com
|
||||||
|
// Copyright 2003 - 2012
|
||||||
|
//
|
||||||
|
// Email: admin@ultra-embedded.com
|
||||||
|
//
|
||||||
|
// License: GPL
|
||||||
|
// If you would like a version with a more permissive license for use in
|
||||||
|
// closed source commercial applications please contact me for details.
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// This file is part of FAT File IO Library.
|
||||||
|
//
|
||||||
|
// FAT File IO Library is free software; you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation; either version 2 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// FAT File IO Library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with FAT File IO Library; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
#include <string.h>
|
||||||
|
#include "fat_defs.h"
|
||||||
|
#include "fat_access.h"
|
||||||
|
#include "fat_table.h"
|
||||||
|
#include "fat_write.h"
|
||||||
|
#include "fat_string.h"
|
||||||
|
#include "fat_misc.h"
|
||||||
|
#include "fat_context.h"
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// fatfs_init: Load FAT Parameters
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
int fatfs_init(struct fat_ctx *ctx, struct fatfs *fs)
|
||||||
|
{
|
||||||
|
uint8 num_of_fats;
|
||||||
|
uint16 reserved_sectors;
|
||||||
|
uint32 FATSz;
|
||||||
|
uint32 root_dir_sectors;
|
||||||
|
uint32 total_sectors;
|
||||||
|
uint32 data_sectors;
|
||||||
|
uint32 count_of_clusters;
|
||||||
|
uint8 valid_partition = 0;
|
||||||
|
|
||||||
|
fs->currentsector.address = FAT32_INVALID_CLUSTER;
|
||||||
|
fs->currentsector.dirty = 0;
|
||||||
|
|
||||||
|
fs->next_free_cluster = 0; // Invalid
|
||||||
|
|
||||||
|
fatfs_fat_init(fs);
|
||||||
|
|
||||||
|
// Make sure we have a read function (write function is optional)
|
||||||
|
if (!fs->disk_io.read_media)
|
||||||
|
return FAT_INIT_MEDIA_ACCESS_ERROR;
|
||||||
|
|
||||||
|
// MBR: Sector 0 on the disk
|
||||||
|
// NOTE: Some removeable media does not have this.
|
||||||
|
|
||||||
|
// Load MBR (LBA 0) into the 512 byte buffer
|
||||||
|
if (!fs->disk_io.read_media(ctx, 0, fs->currentsector.sector, 1))
|
||||||
|
return FAT_INIT_MEDIA_ACCESS_ERROR;
|
||||||
|
|
||||||
|
// Make Sure 0x55 and 0xAA are at end of sector
|
||||||
|
// (this should be the case regardless of the MBR or boot sector)
|
||||||
|
if (fs->currentsector.sector[SIGNATURE_POSITION] != 0x55 || fs->currentsector.sector[SIGNATURE_POSITION+1] != 0xAA)
|
||||||
|
return FAT_INIT_INVALID_SIGNATURE;
|
||||||
|
|
||||||
|
// Now check again using the access function to prove endian conversion function
|
||||||
|
if (GET_16BIT_WORD(fs->currentsector.sector, SIGNATURE_POSITION) != SIGNATURE_VALUE)
|
||||||
|
return FAT_INIT_ENDIAN_ERROR;
|
||||||
|
|
||||||
|
// Verify packed structures
|
||||||
|
if (sizeof(struct fat_dir_entry) != FAT_DIR_ENTRY_SIZE)
|
||||||
|
return FAT_INIT_STRUCT_PACKING;
|
||||||
|
|
||||||
|
// Check the partition type code
|
||||||
|
switch(fs->currentsector.sector[PARTITION1_TYPECODE_LOCATION])
|
||||||
|
{
|
||||||
|
case 0x0B:
|
||||||
|
case 0x06:
|
||||||
|
case 0x0C:
|
||||||
|
case 0x0E:
|
||||||
|
case 0x0F:
|
||||||
|
case 0x05:
|
||||||
|
valid_partition = 1;
|
||||||
|
break;
|
||||||
|
case 0x00:
|
||||||
|
valid_partition = 0;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
if (fs->currentsector.sector[PARTITION1_TYPECODE_LOCATION] <= 0x06)
|
||||||
|
valid_partition = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read LBA Begin for the file system
|
||||||
|
if (valid_partition)
|
||||||
|
fs->lba_begin = GET_32BIT_WORD(fs->currentsector.sector, PARTITION1_LBA_BEGIN_LOCATION);
|
||||||
|
// Else possibly MBR less disk
|
||||||
|
else
|
||||||
|
fs->lba_begin = 0;
|
||||||
|
|
||||||
|
// Load Volume 1 table into sector buffer
|
||||||
|
// (We may already have this in the buffer if MBR less drive!)
|
||||||
|
if (!fs->disk_io.read_media(ctx, fs->lba_begin, fs->currentsector.sector, 1))
|
||||||
|
return FAT_INIT_MEDIA_ACCESS_ERROR;
|
||||||
|
|
||||||
|
// Make sure there are 512 bytes per cluster
|
||||||
|
if (GET_16BIT_WORD(fs->currentsector.sector, 0x0B) != FAT_SECTOR_SIZE)
|
||||||
|
return FAT_INIT_INVALID_SECTOR_SIZE;
|
||||||
|
|
||||||
|
// Load Parameters of FAT partition
|
||||||
|
fs->sectors_per_cluster = fs->currentsector.sector[BPB_SECPERCLUS];
|
||||||
|
reserved_sectors = GET_16BIT_WORD(fs->currentsector.sector, BPB_RSVDSECCNT);
|
||||||
|
num_of_fats = fs->currentsector.sector[BPB_NUMFATS];
|
||||||
|
fs->root_entry_count = GET_16BIT_WORD(fs->currentsector.sector, BPB_ROOTENTCNT);
|
||||||
|
|
||||||
|
if(GET_16BIT_WORD(fs->currentsector.sector, BPB_FATSZ16) != 0)
|
||||||
|
fs->fat_sectors = GET_16BIT_WORD(fs->currentsector.sector, BPB_FATSZ16);
|
||||||
|
else
|
||||||
|
fs->fat_sectors = GET_32BIT_WORD(fs->currentsector.sector, BPB_FAT32_FATSZ32);
|
||||||
|
|
||||||
|
// For FAT32 (which this may be)
|
||||||
|
fs->rootdir_first_cluster = GET_32BIT_WORD(fs->currentsector.sector, BPB_FAT32_ROOTCLUS);
|
||||||
|
fs->fs_info_sector = GET_16BIT_WORD(fs->currentsector.sector, BPB_FAT32_FSINFO);
|
||||||
|
|
||||||
|
// For FAT16 (which this may be), rootdir_first_cluster is actuall rootdir_first_sector
|
||||||
|
fs->rootdir_first_sector = reserved_sectors + (num_of_fats * fs->fat_sectors);
|
||||||
|
fs->rootdir_sectors = ((fs->root_entry_count * 32) + (FAT_SECTOR_SIZE - 1)) / FAT_SECTOR_SIZE;
|
||||||
|
|
||||||
|
// First FAT LBA address
|
||||||
|
fs->fat_begin_lba = fs->lba_begin + reserved_sectors;
|
||||||
|
|
||||||
|
// The address of the first data cluster on this volume
|
||||||
|
fs->cluster_begin_lba = fs->fat_begin_lba + (num_of_fats * fs->fat_sectors);
|
||||||
|
|
||||||
|
if (GET_16BIT_WORD(fs->currentsector.sector, 0x1FE) != 0xAA55) // This signature should be AA55
|
||||||
|
return FAT_INIT_INVALID_SIGNATURE;
|
||||||
|
|
||||||
|
// Calculate the root dir sectors
|
||||||
|
root_dir_sectors = ((GET_16BIT_WORD(fs->currentsector.sector, BPB_ROOTENTCNT) * 32) + (GET_16BIT_WORD(fs->currentsector.sector, BPB_BYTSPERSEC) - 1)) / GET_16BIT_WORD(fs->currentsector.sector, BPB_BYTSPERSEC);
|
||||||
|
|
||||||
|
if(GET_16BIT_WORD(fs->currentsector.sector, BPB_FATSZ16) != 0)
|
||||||
|
FATSz = GET_16BIT_WORD(fs->currentsector.sector, BPB_FATSZ16);
|
||||||
|
else
|
||||||
|
FATSz = GET_32BIT_WORD(fs->currentsector.sector, BPB_FAT32_FATSZ32);
|
||||||
|
|
||||||
|
if(GET_16BIT_WORD(fs->currentsector.sector, BPB_TOTSEC16) != 0)
|
||||||
|
total_sectors = GET_16BIT_WORD(fs->currentsector.sector, BPB_TOTSEC16);
|
||||||
|
else
|
||||||
|
total_sectors = GET_32BIT_WORD(fs->currentsector.sector, BPB_TOTSEC32);
|
||||||
|
|
||||||
|
data_sectors = total_sectors - (GET_16BIT_WORD(fs->currentsector.sector, BPB_RSVDSECCNT) + (fs->currentsector.sector[BPB_NUMFATS] * FATSz) + root_dir_sectors);
|
||||||
|
|
||||||
|
// Find out which version of FAT this is...
|
||||||
|
if (fs->sectors_per_cluster != 0)
|
||||||
|
{
|
||||||
|
count_of_clusters = data_sectors / fs->sectors_per_cluster;
|
||||||
|
|
||||||
|
if(count_of_clusters < 4085)
|
||||||
|
// Volume is FAT12
|
||||||
|
return FAT_INIT_WRONG_FILESYS_TYPE;
|
||||||
|
else if(count_of_clusters < 65525)
|
||||||
|
{
|
||||||
|
// Clear this FAT32 specific param
|
||||||
|
fs->rootdir_first_cluster = 0;
|
||||||
|
|
||||||
|
// Volume is FAT16
|
||||||
|
fs->fat_type = FAT_TYPE_16;
|
||||||
|
return FAT_INIT_OK;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Volume is FAT32
|
||||||
|
fs->fat_type = FAT_TYPE_32;
|
||||||
|
return FAT_INIT_OK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return FAT_INIT_WRONG_FILESYS_TYPE;
|
||||||
|
}
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// fatfs_lba_of_cluster: This function converts a cluster number into a sector /
|
||||||
|
// LBA number.
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
uint32 fatfs_lba_of_cluster(struct fatfs *fs, uint32 Cluster_Number)
|
||||||
|
{
|
||||||
|
if (fs->fat_type == FAT_TYPE_16)
|
||||||
|
return (fs->cluster_begin_lba + (fs->root_entry_count * 32 / FAT_SECTOR_SIZE) + ((Cluster_Number-2) * fs->sectors_per_cluster));
|
||||||
|
else
|
||||||
|
return ((fs->cluster_begin_lba + ((Cluster_Number-2)*fs->sectors_per_cluster)));
|
||||||
|
}
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// fatfs_sector_read:
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
int fatfs_sector_read(struct fat_ctx *ctx, struct fatfs *fs, uint32 lba, uint8 *target, uint32 count)
|
||||||
|
{
|
||||||
|
return fs->disk_io.read_media(ctx, lba, target, count);
|
||||||
|
}
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// fatfs_sector_write:
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
int fatfs_sector_write(struct fat_ctx *ctx, struct fatfs *fs, uint32 lba, uint8 *target, uint32 count)
|
||||||
|
{
|
||||||
|
return fs->disk_io.write_media(ctx, lba, target, count);
|
||||||
|
}
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// fatfs_sector_reader: From the provided startcluster and sector offset
|
||||||
|
// Returns True if success, returns False if not (including if read out of range)
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
int fatfs_sector_reader(struct fat_ctx *ctx, struct fatfs *fs, uint32 start_cluster, uint32 offset, uint8 *target)
|
||||||
|
{
|
||||||
|
uint32 sector_to_read = 0;
|
||||||
|
uint32 cluster_to_read = 0;
|
||||||
|
uint32 cluster_chain = 0;
|
||||||
|
uint32 i;
|
||||||
|
uint32 lba;
|
||||||
|
|
||||||
|
// FAT16 Root directory
|
||||||
|
if (fs->fat_type == FAT_TYPE_16 && start_cluster == 0)
|
||||||
|
{
|
||||||
|
if (offset < fs->rootdir_sectors)
|
||||||
|
lba = fs->lba_begin + fs->rootdir_first_sector + offset;
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
// FAT16/32 Other
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Set start of cluster chain to initial value
|
||||||
|
cluster_chain = start_cluster;
|
||||||
|
|
||||||
|
// Find parameters
|
||||||
|
cluster_to_read = offset / fs->sectors_per_cluster;
|
||||||
|
sector_to_read = offset - (cluster_to_read*fs->sectors_per_cluster);
|
||||||
|
|
||||||
|
// Follow chain to find cluster to read
|
||||||
|
for (i=0; i<cluster_to_read; i++)
|
||||||
|
cluster_chain = fatfs_find_next_cluster(ctx, fs, cluster_chain);
|
||||||
|
|
||||||
|
// If end of cluster chain then return false
|
||||||
|
if (cluster_chain == FAT32_LAST_CLUSTER)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
// Calculate sector address
|
||||||
|
lba = fatfs_lba_of_cluster(fs, cluster_chain)+sector_to_read;
|
||||||
|
}
|
||||||
|
|
||||||
|
// User provided target array
|
||||||
|
if (target)
|
||||||
|
return fs->disk_io.read_media(ctx, lba, target, 1);
|
||||||
|
// Else read sector if not already loaded
|
||||||
|
else if (lba != fs->currentsector.address)
|
||||||
|
{
|
||||||
|
fs->currentsector.address = lba;
|
||||||
|
return fs->disk_io.read_media(ctx, fs->currentsector.address, fs->currentsector.sector, 1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// fatfs_read_sector: Read from the provided cluster and sector offset
|
||||||
|
// Returns True if success, returns False if not
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
int fatfs_read_sector(struct fat_ctx *ctx, struct fatfs *fs, uint32 cluster, uint32 sector, uint8 *target)
|
||||||
|
{
|
||||||
|
// FAT16 Root directory
|
||||||
|
if (fs->fat_type == FAT_TYPE_16 && cluster == 0)
|
||||||
|
{
|
||||||
|
uint32 lba;
|
||||||
|
|
||||||
|
// In FAT16, there are a limited amount of sectors in root dir!
|
||||||
|
if (sector < fs->rootdir_sectors)
|
||||||
|
lba = fs->lba_begin + fs->rootdir_first_sector + sector;
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
// User target buffer passed in
|
||||||
|
if (target)
|
||||||
|
{
|
||||||
|
// Read from disk
|
||||||
|
return fs->disk_io.read_media(ctx, lba, target, 1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Calculate read address
|
||||||
|
fs->currentsector.address = lba;
|
||||||
|
|
||||||
|
// Read from disk
|
||||||
|
return fs->disk_io.read_media(ctx, fs->currentsector.address, fs->currentsector.sector, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// FAT16/32 Other
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// User target buffer passed in
|
||||||
|
if (target)
|
||||||
|
{
|
||||||
|
// Calculate read address
|
||||||
|
uint32 lba = fatfs_lba_of_cluster(fs, cluster) + sector;
|
||||||
|
|
||||||
|
// Read from disk
|
||||||
|
return fs->disk_io.read_media(ctx, lba, target, 1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Calculate write address
|
||||||
|
fs->currentsector.address = fatfs_lba_of_cluster(fs, cluster)+sector;
|
||||||
|
|
||||||
|
// Read from disk
|
||||||
|
return fs->disk_io.read_media(ctx, fs->currentsector.address, fs->currentsector.sector, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// fatfs_write_sector: Write to the provided cluster and sector offset
|
||||||
|
// Returns True if success, returns False if not
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
#if FATFS_INC_WRITE_SUPPORT
|
||||||
|
int fatfs_write_sector(struct fat_ctx *ctx, struct fatfs *fs, uint32 cluster, uint32 sector, uint8 *target)
|
||||||
|
{
|
||||||
|
// No write access?
|
||||||
|
if (!fs->disk_io.write_media)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
// FAT16 Root directory
|
||||||
|
if (fs->fat_type == FAT_TYPE_16 && cluster == 0)
|
||||||
|
{
|
||||||
|
uint32 lba;
|
||||||
|
|
||||||
|
// In FAT16 we cannot extend the root dir!
|
||||||
|
if (sector < fs->rootdir_sectors)
|
||||||
|
lba = fs->lba_begin + fs->rootdir_first_sector + sector;
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
// User target buffer passed in
|
||||||
|
if (target)
|
||||||
|
{
|
||||||
|
// Write to disk
|
||||||
|
return fs->disk_io.write_media(ctx, lba, target, 1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Calculate write address
|
||||||
|
fs->currentsector.address = lba;
|
||||||
|
|
||||||
|
// Write to disk
|
||||||
|
return fs->disk_io.write_media(ctx, fs->currentsector.address, fs->currentsector.sector, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// FAT16/32 Other
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// User target buffer passed in
|
||||||
|
if (target)
|
||||||
|
{
|
||||||
|
// Calculate write address
|
||||||
|
uint32 lba = fatfs_lba_of_cluster(fs, cluster) + sector;
|
||||||
|
|
||||||
|
// Write to disk
|
||||||
|
return fs->disk_io.write_media(ctx, lba, target, 1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Calculate write address
|
||||||
|
fs->currentsector.address = fatfs_lba_of_cluster(fs, cluster)+sector;
|
||||||
|
|
||||||
|
// Write to disk
|
||||||
|
return fs->disk_io.write_media(ctx, fs->currentsector.address, fs->currentsector.sector, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// fatfs_show_details: Show the details about the filesystem
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
void fatfs_show_details(struct fatfs *fs)
|
||||||
|
{
|
||||||
|
FAT_PRINTF(("FAT details:\r\n"));
|
||||||
|
FAT_PRINTF((" Type =%s", (fs->fat_type == FAT_TYPE_32) ? "FAT32": "FAT16"));
|
||||||
|
FAT_PRINTF((" Root Dir First Cluster = %x\r\n", fs->rootdir_first_cluster));
|
||||||
|
FAT_PRINTF((" FAT Begin LBA = 0x%x\r\n",fs->fat_begin_lba));
|
||||||
|
FAT_PRINTF((" Cluster Begin LBA = 0x%x\r\n",fs->cluster_begin_lba));
|
||||||
|
FAT_PRINTF((" Sectors Per Cluster = %d\r\n", fs->sectors_per_cluster));
|
||||||
|
}
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// fatfs_get_root_cluster: Get the root dir cluster
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
uint32 fatfs_get_root_cluster(struct fatfs *fs)
|
||||||
|
{
|
||||||
|
// NOTE: On FAT16 this will be 0 which has a special meaning...
|
||||||
|
return fs->rootdir_first_cluster;
|
||||||
|
}
|
||||||
|
//-------------------------------------------------------------
|
||||||
|
// fatfs_get_file_entry: Find the file entry for a filename
|
||||||
|
//-------------------------------------------------------------
|
||||||
|
uint32 fatfs_get_file_entry(struct fat_ctx *ctx, struct fatfs *fs, uint32 Cluster, char *name_to_find, struct fat_dir_entry *sfEntry)
|
||||||
|
{
|
||||||
|
uint8 item=0;
|
||||||
|
uint16 recordoffset = 0;
|
||||||
|
uint8 i=0;
|
||||||
|
int x=0;
|
||||||
|
char *long_filename = NULL;
|
||||||
|
char short_filename[13];
|
||||||
|
struct lfn_cache lfn;
|
||||||
|
int dotRequired = 0;
|
||||||
|
struct fat_dir_entry *directoryEntry;
|
||||||
|
|
||||||
|
fatfs_lfn_cache_init(&lfn, 1);
|
||||||
|
|
||||||
|
// Main cluster following loop
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
// Read sector
|
||||||
|
if (fatfs_sector_reader(ctx, fs, Cluster, x++, 0)) // If sector read was successfull
|
||||||
|
{
|
||||||
|
// Analyse Sector
|
||||||
|
for (item = 0; item < FAT_DIR_ENTRIES_PER_SECTOR; item++)
|
||||||
|
{
|
||||||
|
// Create the multiplier for sector access
|
||||||
|
recordoffset = FAT_DIR_ENTRY_SIZE * item;
|
||||||
|
|
||||||
|
// Overlay directory entry over buffer
|
||||||
|
directoryEntry = (struct fat_dir_entry*)(fs->currentsector.sector+recordoffset);
|
||||||
|
|
||||||
|
#if FATFS_INC_LFN_SUPPORT
|
||||||
|
// Long File Name Text Found
|
||||||
|
if (fatfs_entry_lfn_text(directoryEntry) )
|
||||||
|
fatfs_lfn_cache_entry(&lfn, fs->currentsector.sector+recordoffset);
|
||||||
|
|
||||||
|
// If Invalid record found delete any long file name information collated
|
||||||
|
else if (fatfs_entry_lfn_invalid(directoryEntry) )
|
||||||
|
fatfs_lfn_cache_init(&lfn, 0);
|
||||||
|
|
||||||
|
// Normal SFN Entry and Long text exists
|
||||||
|
else if (fatfs_entry_lfn_exists(&lfn, directoryEntry) )
|
||||||
|
{
|
||||||
|
long_filename = fatfs_lfn_cache_get(&lfn);
|
||||||
|
|
||||||
|
// Compare names to see if they match
|
||||||
|
if (fatfs_compare_names(long_filename, name_to_find))
|
||||||
|
{
|
||||||
|
memcpy(sfEntry,directoryEntry,sizeof(struct fat_dir_entry));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
fatfs_lfn_cache_init(&lfn, 0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
// Normal Entry, only 8.3 Text
|
||||||
|
if (fatfs_entry_sfn_only(directoryEntry) )
|
||||||
|
{
|
||||||
|
memset(short_filename, 0, sizeof(short_filename));
|
||||||
|
|
||||||
|
// Copy name to string
|
||||||
|
for (i=0; i<8; i++)
|
||||||
|
short_filename[i] = directoryEntry->Name[i];
|
||||||
|
|
||||||
|
// Extension
|
||||||
|
dotRequired = 0;
|
||||||
|
for (i=8; i<11; i++)
|
||||||
|
{
|
||||||
|
short_filename[i+1] = directoryEntry->Name[i];
|
||||||
|
if (directoryEntry->Name[i] != ' ')
|
||||||
|
dotRequired = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Dot only required if extension present
|
||||||
|
if (dotRequired)
|
||||||
|
{
|
||||||
|
// If not . or .. entry
|
||||||
|
if (short_filename[0]!='.')
|
||||||
|
short_filename[8] = '.';
|
||||||
|
else
|
||||||
|
short_filename[8] = ' ';
|
||||||
|
}
|
||||||
|
else
|
||||||
|
short_filename[8] = ' ';
|
||||||
|
|
||||||
|
// Compare names to see if they match
|
||||||
|
if (fatfs_compare_names(short_filename, name_to_find))
|
||||||
|
{
|
||||||
|
memcpy(sfEntry,directoryEntry,sizeof(struct fat_dir_entry));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
fatfs_lfn_cache_init(&lfn, 0);
|
||||||
|
}
|
||||||
|
} // End of if
|
||||||
|
}
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
} // End of while loop
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
//-------------------------------------------------------------
|
||||||
|
// fatfs_sfn_exists: Check if a short filename exists.
|
||||||
|
// NOTE: shortname is XXXXXXXXYYY not XXXXXXXX.YYY
|
||||||
|
//-------------------------------------------------------------
|
||||||
|
#if FATFS_INC_WRITE_SUPPORT
|
||||||
|
int fatfs_sfn_exists(struct fat_ctx *ctx, struct fatfs *fs, uint32 Cluster, char *shortname)
|
||||||
|
{
|
||||||
|
uint8 item=0;
|
||||||
|
uint16 recordoffset = 0;
|
||||||
|
int x=0;
|
||||||
|
struct fat_dir_entry *directoryEntry;
|
||||||
|
|
||||||
|
// Main cluster following loop
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
// Read sector
|
||||||
|
if (fatfs_sector_reader(ctx, fs, Cluster, x++, 0)) // If sector read was successfull
|
||||||
|
{
|
||||||
|
// Analyse Sector
|
||||||
|
for (item = 0; item < FAT_DIR_ENTRIES_PER_SECTOR; item++)
|
||||||
|
{
|
||||||
|
// Create the multiplier for sector access
|
||||||
|
recordoffset = FAT_DIR_ENTRY_SIZE * item;
|
||||||
|
|
||||||
|
// Overlay directory entry over buffer
|
||||||
|
directoryEntry = (struct fat_dir_entry*)(fs->currentsector.sector+recordoffset);
|
||||||
|
|
||||||
|
#if FATFS_INC_LFN_SUPPORT
|
||||||
|
// Long File Name Text Found
|
||||||
|
if (fatfs_entry_lfn_text(directoryEntry) )
|
||||||
|
;
|
||||||
|
|
||||||
|
// If Invalid record found delete any long file name information collated
|
||||||
|
else if (fatfs_entry_lfn_invalid(directoryEntry) )
|
||||||
|
;
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
// Normal Entry, only 8.3 Text
|
||||||
|
if (fatfs_entry_sfn_only(directoryEntry) )
|
||||||
|
{
|
||||||
|
if (strncmp((const char*)directoryEntry->Name, shortname, 11)==0)
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
} // End of if
|
||||||
|
}
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
} // End of while loop
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
//-------------------------------------------------------------
|
||||||
|
// fatfs_update_timestamps: Update date/time details
|
||||||
|
//-------------------------------------------------------------
|
||||||
|
#if FATFS_INC_TIME_DATE_SUPPORT
|
||||||
|
int fatfs_update_timestamps(struct fat_dir_entry *directoryEntry, int create, int modify, int access)
|
||||||
|
{
|
||||||
|
time_t time_now;
|
||||||
|
struct tm * time_info;
|
||||||
|
uint16 fat_time;
|
||||||
|
uint16 fat_date;
|
||||||
|
|
||||||
|
// Get system time
|
||||||
|
time(&time_now);
|
||||||
|
|
||||||
|
// Convert to local time
|
||||||
|
time_info = localtime(&time_now);
|
||||||
|
|
||||||
|
// Convert time to FAT format
|
||||||
|
fat_time = fatfs_convert_to_fat_time(time_info->tm_hour, time_info->tm_min, time_info->tm_sec);
|
||||||
|
|
||||||
|
// Convert date to FAT format
|
||||||
|
fat_date = fatfs_convert_to_fat_date(time_info->tm_mday, time_info->tm_mon + 1, time_info->tm_year + 1900);
|
||||||
|
|
||||||
|
// Update requested fields
|
||||||
|
if (create)
|
||||||
|
{
|
||||||
|
directoryEntry->CrtTime[1] = fat_time >> 8;
|
||||||
|
directoryEntry->CrtTime[0] = fat_time >> 0;
|
||||||
|
directoryEntry->CrtDate[1] = fat_date >> 8;
|
||||||
|
directoryEntry->CrtDate[0] = fat_date >> 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (modify)
|
||||||
|
{
|
||||||
|
directoryEntry->WrtTime[1] = fat_time >> 8;
|
||||||
|
directoryEntry->WrtTime[0] = fat_time >> 0;
|
||||||
|
directoryEntry->WrtDate[1] = fat_date >> 8;
|
||||||
|
directoryEntry->WrtDate[0] = fat_date >> 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (access)
|
||||||
|
{
|
||||||
|
directoryEntry->LstAccDate[1] = fat_time >> 8;
|
||||||
|
directoryEntry->LstAccDate[0] = fat_time >> 0;
|
||||||
|
directoryEntry->LstAccDate[1] = fat_date >> 8;
|
||||||
|
directoryEntry->LstAccDate[0] = fat_date >> 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
//-------------------------------------------------------------
|
||||||
|
// fatfs_update_file_length: Find a SFN entry and update it
|
||||||
|
// NOTE: shortname is XXXXXXXXYYY not XXXXXXXX.YYY
|
||||||
|
//-------------------------------------------------------------
|
||||||
|
#if FATFS_INC_WRITE_SUPPORT
|
||||||
|
int fatfs_update_file_length(struct fat_ctx *ctx, struct fatfs *fs, uint32 Cluster, char *shortname, uint32 fileLength)
|
||||||
|
{
|
||||||
|
uint8 item=0;
|
||||||
|
uint16 recordoffset = 0;
|
||||||
|
int x=0;
|
||||||
|
struct fat_dir_entry *directoryEntry;
|
||||||
|
|
||||||
|
// No write access?
|
||||||
|
if (!fs->disk_io.write_media)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
// Main cluster following loop
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
// Read sector
|
||||||
|
if (fatfs_sector_reader(ctx, fs, Cluster, x++, 0)) // If sector read was successfull
|
||||||
|
{
|
||||||
|
// Analyse Sector
|
||||||
|
for (item = 0; item < FAT_DIR_ENTRIES_PER_SECTOR; item++)
|
||||||
|
{
|
||||||
|
// Create the multiplier for sector access
|
||||||
|
recordoffset = FAT_DIR_ENTRY_SIZE * item;
|
||||||
|
|
||||||
|
// Overlay directory entry over buffer
|
||||||
|
directoryEntry = (struct fat_dir_entry*)(fs->currentsector.sector+recordoffset);
|
||||||
|
|
||||||
|
#if FATFS_INC_LFN_SUPPORT
|
||||||
|
// Long File Name Text Found
|
||||||
|
if (fatfs_entry_lfn_text(directoryEntry) )
|
||||||
|
;
|
||||||
|
|
||||||
|
// If Invalid record found delete any long file name information collated
|
||||||
|
else if (fatfs_entry_lfn_invalid(directoryEntry) )
|
||||||
|
;
|
||||||
|
|
||||||
|
// Normal Entry, only 8.3 Text
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
if (fatfs_entry_sfn_only(directoryEntry) )
|
||||||
|
{
|
||||||
|
if (strncmp((const char*)directoryEntry->Name, shortname, 11)==0)
|
||||||
|
{
|
||||||
|
directoryEntry->FileSize = FAT_HTONL(fileLength);
|
||||||
|
|
||||||
|
#if FATFS_INC_TIME_DATE_SUPPORT
|
||||||
|
// Update access / modify time & date
|
||||||
|
fatfs_update_timestamps(directoryEntry, 0, 1, 1);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Update sfn entry
|
||||||
|
memcpy((uint8*)(fs->currentsector.sector+recordoffset), (uint8*)directoryEntry, sizeof(struct fat_dir_entry));
|
||||||
|
|
||||||
|
// Write sector back
|
||||||
|
return fs->disk_io.write_media(ctx, fs->currentsector.address, fs->currentsector.sector, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} // End of if
|
||||||
|
}
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
} // End of while loop
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
//-------------------------------------------------------------
|
||||||
|
// fatfs_mark_file_deleted: Find a SFN entry and mark if as deleted
|
||||||
|
// NOTE: shortname is XXXXXXXXYYY not XXXXXXXX.YYY
|
||||||
|
//-------------------------------------------------------------
|
||||||
|
#if FATFS_INC_WRITE_SUPPORT
|
||||||
|
int fatfs_mark_file_deleted(struct fat_ctx *ctx, struct fatfs *fs, uint32 Cluster, char *shortname)
|
||||||
|
{
|
||||||
|
uint8 item=0;
|
||||||
|
uint16 recordoffset = 0;
|
||||||
|
int x=0;
|
||||||
|
struct fat_dir_entry *directoryEntry;
|
||||||
|
|
||||||
|
// No write access?
|
||||||
|
if (!fs->disk_io.write_media)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
// Main cluster following loop
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
// Read sector
|
||||||
|
if (fatfs_sector_reader(ctx, fs, Cluster, x++, 0)) // If sector read was successfull
|
||||||
|
{
|
||||||
|
// Analyse Sector
|
||||||
|
for (item = 0; item < FAT_DIR_ENTRIES_PER_SECTOR; item++)
|
||||||
|
{
|
||||||
|
// Create the multiplier for sector access
|
||||||
|
recordoffset = FAT_DIR_ENTRY_SIZE * item;
|
||||||
|
|
||||||
|
// Overlay directory entry over buffer
|
||||||
|
directoryEntry = (struct fat_dir_entry*)(fs->currentsector.sector+recordoffset);
|
||||||
|
|
||||||
|
#if FATFS_INC_LFN_SUPPORT
|
||||||
|
// Long File Name Text Found
|
||||||
|
if (fatfs_entry_lfn_text(directoryEntry) )
|
||||||
|
;
|
||||||
|
|
||||||
|
// If Invalid record found delete any long file name information collated
|
||||||
|
else if (fatfs_entry_lfn_invalid(directoryEntry) )
|
||||||
|
;
|
||||||
|
|
||||||
|
// Normal Entry, only 8.3 Text
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
if (fatfs_entry_sfn_only(directoryEntry) )
|
||||||
|
{
|
||||||
|
if (strncmp((const char *)directoryEntry->Name, shortname, 11)==0)
|
||||||
|
{
|
||||||
|
// Mark as deleted
|
||||||
|
directoryEntry->Name[0] = FILE_HEADER_DELETED;
|
||||||
|
|
||||||
|
#if FATFS_INC_TIME_DATE_SUPPORT
|
||||||
|
// Update access / modify time & date
|
||||||
|
fatfs_update_timestamps(directoryEntry, 0, 1, 1);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Update sfn entry
|
||||||
|
memcpy((uint8*)(fs->currentsector.sector+recordoffset), (uint8*)directoryEntry, sizeof(struct fat_dir_entry));
|
||||||
|
|
||||||
|
// Write sector back
|
||||||
|
return fs->disk_io.write_media(ctx, fs->currentsector.address, fs->currentsector.sector, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} // End of if
|
||||||
|
}
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
} // End of while loop
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// fatfs_list_directory_start: Initialise a directory listing procedure
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
#if FATFS_DIR_LIST_SUPPORT
|
||||||
|
void fatfs_list_directory_start(struct fatfs *fs, struct fs_dir_list_status *dirls, uint32 StartCluster)
|
||||||
|
{
|
||||||
|
dirls->cluster = StartCluster;
|
||||||
|
dirls->sector = 0;
|
||||||
|
dirls->offset = 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// fatfs_list_directory_next: Get the next entry in the directory.
|
||||||
|
// Returns: 1 = found, 0 = end of listing
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
#if FATFS_DIR_LIST_SUPPORT
|
||||||
|
int fatfs_list_directory_next(struct fat_ctx *ctx, struct fatfs *fs, struct fs_dir_list_status *dirls, struct fs_dir_ent *entry)
|
||||||
|
{
|
||||||
|
uint8 i,item;
|
||||||
|
uint16 recordoffset;
|
||||||
|
struct fat_dir_entry *directoryEntry;
|
||||||
|
char *long_filename = NULL;
|
||||||
|
char short_filename[13];
|
||||||
|
struct lfn_cache lfn;
|
||||||
|
int dotRequired = 0;
|
||||||
|
int result = 0;
|
||||||
|
|
||||||
|
// Initialise LFN cache first
|
||||||
|
fatfs_lfn_cache_init(&lfn, 0);
|
||||||
|
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
// If data read OK
|
||||||
|
if (fatfs_sector_reader(ctx, fs, dirls->cluster, dirls->sector, 0))
|
||||||
|
{
|
||||||
|
// Maximum of 16 directory entries
|
||||||
|
for (item = dirls->offset; item < FAT_DIR_ENTRIES_PER_SECTOR; item++)
|
||||||
|
{
|
||||||
|
// Increase directory offset
|
||||||
|
recordoffset = FAT_DIR_ENTRY_SIZE * item;
|
||||||
|
|
||||||
|
// Overlay directory entry over buffer
|
||||||
|
directoryEntry = (struct fat_dir_entry*)(fs->currentsector.sector+recordoffset);
|
||||||
|
|
||||||
|
#if FATFS_INC_LFN_SUPPORT
|
||||||
|
// Long File Name Text Found
|
||||||
|
if ( fatfs_entry_lfn_text(directoryEntry) )
|
||||||
|
fatfs_lfn_cache_entry(&lfn, fs->currentsector.sector+recordoffset);
|
||||||
|
|
||||||
|
// If Invalid record found delete any long file name information collated
|
||||||
|
else if ( fatfs_entry_lfn_invalid(directoryEntry) )
|
||||||
|
fatfs_lfn_cache_init(&lfn, 0);
|
||||||
|
|
||||||
|
// Normal SFN Entry and Long text exists
|
||||||
|
else if (fatfs_entry_lfn_exists(&lfn, directoryEntry) )
|
||||||
|
{
|
||||||
|
// Get text
|
||||||
|
long_filename = fatfs_lfn_cache_get(&lfn);
|
||||||
|
strncpy(entry->filename, long_filename, FATFS_MAX_LONG_FILENAME-1);
|
||||||
|
|
||||||
|
if (fatfs_entry_is_dir(directoryEntry))
|
||||||
|
entry->is_dir = 1;
|
||||||
|
else
|
||||||
|
entry->is_dir = 0;
|
||||||
|
|
||||||
|
#if FATFS_INC_TIME_DATE_SUPPORT
|
||||||
|
// Get time / dates
|
||||||
|
entry->create_time = ((uint16)directoryEntry->CrtTime[1] << 8) | directoryEntry->CrtTime[0];
|
||||||
|
entry->create_date = ((uint16)directoryEntry->CrtDate[1] << 8) | directoryEntry->CrtDate[0];
|
||||||
|
entry->access_date = ((uint16)directoryEntry->LstAccDate[1] << 8) | directoryEntry->LstAccDate[0];
|
||||||
|
entry->write_time = ((uint16)directoryEntry->WrtTime[1] << 8) | directoryEntry->WrtTime[0];
|
||||||
|
entry->write_date = ((uint16)directoryEntry->WrtDate[1] << 8) | directoryEntry->WrtDate[0];
|
||||||
|
#endif
|
||||||
|
|
||||||
|
entry->size = FAT_HTONL(directoryEntry->FileSize);
|
||||||
|
entry->cluster = (FAT_HTONS(directoryEntry->FstClusHI)<<16) | FAT_HTONS(directoryEntry->FstClusLO);
|
||||||
|
|
||||||
|
// Next starting position
|
||||||
|
dirls->offset = item + 1;
|
||||||
|
result = 1;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
// Normal Entry, only 8.3 Text
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
if ( fatfs_entry_sfn_only(directoryEntry) )
|
||||||
|
{
|
||||||
|
fatfs_lfn_cache_init(&lfn, 0);
|
||||||
|
|
||||||
|
memset(short_filename, 0, sizeof(short_filename));
|
||||||
|
|
||||||
|
// Copy name to string
|
||||||
|
for (i=0; i<8; i++)
|
||||||
|
short_filename[i] = directoryEntry->Name[i];
|
||||||
|
|
||||||
|
// Extension
|
||||||
|
dotRequired = 0;
|
||||||
|
for (i=8; i<11; i++)
|
||||||
|
{
|
||||||
|
short_filename[i+1] = directoryEntry->Name[i];
|
||||||
|
if (directoryEntry->Name[i] != ' ')
|
||||||
|
dotRequired = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Dot only required if extension present
|
||||||
|
if (dotRequired)
|
||||||
|
{
|
||||||
|
// If not . or .. entry
|
||||||
|
if (short_filename[0]!='.')
|
||||||
|
short_filename[8] = '.';
|
||||||
|
else
|
||||||
|
short_filename[8] = ' ';
|
||||||
|
}
|
||||||
|
else
|
||||||
|
short_filename[8] = ' ';
|
||||||
|
|
||||||
|
fatfs_get_sfn_display_name(entry->filename, short_filename);
|
||||||
|
|
||||||
|
if (fatfs_entry_is_dir(directoryEntry))
|
||||||
|
entry->is_dir = 1;
|
||||||
|
else
|
||||||
|
entry->is_dir = 0;
|
||||||
|
|
||||||
|
#if FATFS_INC_TIME_DATE_SUPPORT
|
||||||
|
// Get time / dates
|
||||||
|
entry->create_time = ((uint16)directoryEntry->CrtTime[1] << 8) | directoryEntry->CrtTime[0];
|
||||||
|
entry->create_date = ((uint16)directoryEntry->CrtDate[1] << 8) | directoryEntry->CrtDate[0];
|
||||||
|
entry->access_date = ((uint16)directoryEntry->LstAccDate[1] << 8) | directoryEntry->LstAccDate[0];
|
||||||
|
entry->write_time = ((uint16)directoryEntry->WrtTime[1] << 8) | directoryEntry->WrtTime[0];
|
||||||
|
entry->write_date = ((uint16)directoryEntry->WrtDate[1] << 8) | directoryEntry->WrtDate[0];
|
||||||
|
#endif
|
||||||
|
|
||||||
|
entry->size = FAT_HTONL(directoryEntry->FileSize);
|
||||||
|
entry->cluster = (FAT_HTONS(directoryEntry->FstClusHI)<<16) | FAT_HTONS(directoryEntry->FstClusLO);
|
||||||
|
|
||||||
|
// Next starting position
|
||||||
|
dirls->offset = item + 1;
|
||||||
|
result = 1;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}// end of for
|
||||||
|
|
||||||
|
// If reached end of the dir move onto next sector
|
||||||
|
dirls->sector++;
|
||||||
|
dirls->offset = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
135
kernel/fs/fatfs/fat_access.h
Normal file
135
kernel/fs/fatfs/fat_access.h
Normal file
@ -0,0 +1,135 @@
|
|||||||
|
#ifndef __FAT_ACCESS_H__
|
||||||
|
#define __FAT_ACCESS_H__
|
||||||
|
|
||||||
|
#include "fat_defs.h"
|
||||||
|
#include "fat_opts.h"
|
||||||
|
|
||||||
|
struct fat_ctx;
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Defines
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
#define FAT_INIT_OK 0
|
||||||
|
#define FAT_INIT_MEDIA_ACCESS_ERROR (-1)
|
||||||
|
#define FAT_INIT_INVALID_SECTOR_SIZE (-2)
|
||||||
|
#define FAT_INIT_INVALID_SIGNATURE (-3)
|
||||||
|
#define FAT_INIT_ENDIAN_ERROR (-4)
|
||||||
|
#define FAT_INIT_WRONG_FILESYS_TYPE (-5)
|
||||||
|
#define FAT_INIT_WRONG_PARTITION_TYPE (-6)
|
||||||
|
#define FAT_INIT_STRUCT_PACKING (-7)
|
||||||
|
|
||||||
|
#define FAT_DIR_ENTRIES_PER_SECTOR (FAT_SECTOR_SIZE / FAT_DIR_ENTRY_SIZE)
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Function Pointers
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
typedef int (*fn_diskio_read) (struct fat_ctx *ctx, uint32 sector, uint8 *buffer, uint32 sector_count);
|
||||||
|
typedef int (*fn_diskio_write)(struct fat_ctx *ctx, uint32 sector, uint8 *buffer, uint32 sector_count);
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Structures
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
struct disk_if
|
||||||
|
{
|
||||||
|
// User supplied function pointers for disk IO
|
||||||
|
fn_diskio_read read_media;
|
||||||
|
fn_diskio_write write_media;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Forward declaration
|
||||||
|
struct fat_buffer;
|
||||||
|
|
||||||
|
struct fat_buffer
|
||||||
|
{
|
||||||
|
uint8 sector[FAT_SECTOR_SIZE * FAT_BUFFER_SECTORS];
|
||||||
|
uint32 address;
|
||||||
|
int dirty;
|
||||||
|
uint8 * ptr;
|
||||||
|
|
||||||
|
// Next in chain of sector buffers
|
||||||
|
struct fat_buffer *next;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef enum eFatType
|
||||||
|
{
|
||||||
|
FAT_TYPE_16,
|
||||||
|
FAT_TYPE_32
|
||||||
|
} tFatType;
|
||||||
|
|
||||||
|
struct fatfs
|
||||||
|
{
|
||||||
|
// Filesystem globals
|
||||||
|
uint8 sectors_per_cluster;
|
||||||
|
uint32 cluster_begin_lba;
|
||||||
|
uint32 rootdir_first_cluster;
|
||||||
|
uint32 rootdir_first_sector;
|
||||||
|
uint32 rootdir_sectors;
|
||||||
|
uint32 fat_begin_lba;
|
||||||
|
uint16 fs_info_sector;
|
||||||
|
uint32 lba_begin;
|
||||||
|
uint32 fat_sectors;
|
||||||
|
uint32 next_free_cluster;
|
||||||
|
uint16 root_entry_count;
|
||||||
|
uint16 reserved_sectors;
|
||||||
|
uint8 num_of_fats;
|
||||||
|
tFatType fat_type;
|
||||||
|
|
||||||
|
// Disk/Media API
|
||||||
|
struct disk_if disk_io;
|
||||||
|
|
||||||
|
// [Optional] Thread Safety
|
||||||
|
void (*fl_lock)(void);
|
||||||
|
void (*fl_unlock)(void);
|
||||||
|
|
||||||
|
// Working buffer
|
||||||
|
struct fat_buffer currentsector;
|
||||||
|
|
||||||
|
// FAT Buffer
|
||||||
|
struct fat_buffer *fat_buffer_head;
|
||||||
|
struct fat_buffer fat_buffers[FAT_BUFFERS];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct fs_dir_list_status
|
||||||
|
{
|
||||||
|
uint32 sector;
|
||||||
|
uint32 cluster;
|
||||||
|
uint8 offset;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct fs_dir_ent
|
||||||
|
{
|
||||||
|
char filename[FATFS_MAX_LONG_FILENAME];
|
||||||
|
uint8 is_dir;
|
||||||
|
uint32 cluster;
|
||||||
|
uint32 size;
|
||||||
|
|
||||||
|
#if FATFS_INC_TIME_DATE_SUPPORT
|
||||||
|
uint16 access_date;
|
||||||
|
uint16 write_time;
|
||||||
|
uint16 write_date;
|
||||||
|
uint16 create_date;
|
||||||
|
uint16 create_time;
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Prototypes
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
int fatfs_init(struct fat_ctx *ctx, struct fatfs *fs);
|
||||||
|
uint32 fatfs_lba_of_cluster(struct fatfs *fs, uint32 Cluster_Number);
|
||||||
|
int fatfs_sector_reader(struct fat_ctx *ctx, struct fatfs *fs, uint32 Startcluster, uint32 offset, uint8 *target);
|
||||||
|
int fatfs_sector_read(struct fat_ctx *ctx, struct fatfs *fs, uint32 lba, uint8 *target, uint32 count);
|
||||||
|
int fatfs_sector_write(struct fat_ctx *ctx, struct fatfs *fs, uint32 lba, uint8 *target, uint32 count);
|
||||||
|
int fatfs_read_sector(struct fat_ctx *ctx, struct fatfs *fs, uint32 cluster, uint32 sector, uint8 *target);
|
||||||
|
int fatfs_write_sector(struct fat_ctx *ctx, struct fatfs *fs, uint32 cluster, uint32 sector, uint8 *target);
|
||||||
|
void fatfs_show_details(struct fatfs *fs);
|
||||||
|
uint32 fatfs_get_root_cluster(struct fatfs *fs);
|
||||||
|
uint32 fatfs_get_file_entry(struct fat_ctx *ctx, struct fatfs *fs, uint32 Cluster, char *nametofind, struct fat_dir_entry *sfEntry);
|
||||||
|
int fatfs_sfn_exists(struct fat_ctx *ctx, struct fatfs *fs, uint32 Cluster, char *shortname);
|
||||||
|
int fatfs_update_file_length(struct fat_ctx *ctx, struct fatfs *fs, uint32 Cluster, char *shortname, uint32 fileLength);
|
||||||
|
int fatfs_mark_file_deleted(struct fat_ctx *ctx, struct fatfs *fs, uint32 Cluster, char *shortname);
|
||||||
|
void fatfs_list_directory_start(struct fatfs *fs, struct fs_dir_list_status *dirls, uint32 StartCluster);
|
||||||
|
int fatfs_list_directory_next(struct fat_ctx *ctx, struct fatfs *fs, struct fs_dir_list_status *dirls, struct fs_dir_ent *entry);
|
||||||
|
int fatfs_update_timestamps(struct fat_dir_entry *directoryEntry, int create, int modify, int access);
|
||||||
|
|
||||||
|
#endif
|
||||||
91
kernel/fs/fatfs/fat_cache.c
Normal file
91
kernel/fs/fatfs/fat_cache.c
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// FAT16/32 File IO Library
|
||||||
|
// V2.6
|
||||||
|
// Ultra-Embedded.com
|
||||||
|
// Copyright 2003 - 2012
|
||||||
|
//
|
||||||
|
// Email: admin@ultra-embedded.com
|
||||||
|
//
|
||||||
|
// License: GPL
|
||||||
|
// If you would like a version with a more permissive license for use in
|
||||||
|
// closed source commercial applications please contact me for details.
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// This file is part of FAT File IO Library.
|
||||||
|
//
|
||||||
|
// FAT File IO Library is free software; you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation; either version 2 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// FAT File IO Library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with FAT File IO Library; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
#include <string.h>
|
||||||
|
#include "fat_cache.h"
|
||||||
|
|
||||||
|
// Per file cluster chain caching used to improve performance.
|
||||||
|
// This does not have to be enabled for architectures with low
|
||||||
|
// memory space.
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// fatfs_cache_init:
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
int fatfs_cache_init(struct fatfs *fs, FL_FILE *file)
|
||||||
|
{
|
||||||
|
#ifdef FAT_CLUSTER_CACHE_ENTRIES
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i=0;i<FAT_CLUSTER_CACHE_ENTRIES;i++)
|
||||||
|
{
|
||||||
|
file->cluster_cache_idx[i] = 0xFFFFFFFF; // Not used
|
||||||
|
file->cluster_cache_data[i] = 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// fatfs_cache_get_next_cluster:
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
int fatfs_cache_get_next_cluster(struct fatfs *fs, FL_FILE *file, uint32 clusterIdx, uint32 *pNextCluster)
|
||||||
|
{
|
||||||
|
#ifdef FAT_CLUSTER_CACHE_ENTRIES
|
||||||
|
uint32 slot = clusterIdx % FAT_CLUSTER_CACHE_ENTRIES;
|
||||||
|
|
||||||
|
if (file->cluster_cache_idx[slot] == clusterIdx)
|
||||||
|
{
|
||||||
|
*pNextCluster = file->cluster_cache_data[slot];
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// fatfs_cache_set_next_cluster:
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
int fatfs_cache_set_next_cluster(struct fatfs *fs, FL_FILE *file, uint32 clusterIdx, uint32 nextCluster)
|
||||||
|
{
|
||||||
|
#ifdef FAT_CLUSTER_CACHE_ENTRIES
|
||||||
|
uint32 slot = clusterIdx % FAT_CLUSTER_CACHE_ENTRIES;
|
||||||
|
|
||||||
|
if (file->cluster_cache_idx[slot] == clusterIdx)
|
||||||
|
file->cluster_cache_data[slot] = nextCluster;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
file->cluster_cache_idx[slot] = clusterIdx;
|
||||||
|
file->cluster_cache_data[slot] = nextCluster;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
13
kernel/fs/fatfs/fat_cache.h
Normal file
13
kernel/fs/fatfs/fat_cache.h
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
#ifndef __FAT_CACHE_H__
|
||||||
|
#define __FAT_CACHE_H__
|
||||||
|
|
||||||
|
#include "fat_filelib.h"
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Prototypes
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
int fatfs_cache_init(struct fatfs *fs, FL_FILE *file);
|
||||||
|
int fatfs_cache_get_next_cluster(struct fatfs *fs, FL_FILE *file, uint32 clusterIdx, uint32 *pNextCluster);
|
||||||
|
int fatfs_cache_set_next_cluster(struct fatfs *fs, FL_FILE *file, uint32 clusterIdx, uint32 nextCluster);
|
||||||
|
|
||||||
|
#endif
|
||||||
17
kernel/fs/fatfs/fat_context.h
Normal file
17
kernel/fs/fatfs/fat_context.h
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
#ifndef FAT_CONTEXT_H_
|
||||||
|
#define FAT_CONTEXT_H_
|
||||||
|
|
||||||
|
#include "fat_defs.h"
|
||||||
|
#include "fat_filelib.h"
|
||||||
|
|
||||||
|
struct fat_ctx {
|
||||||
|
FL_FILE _files[FATFS_MAX_OPEN_FILES];
|
||||||
|
int _filelib_init;
|
||||||
|
int _filelib_valid;
|
||||||
|
struct fatfs _fs;
|
||||||
|
struct fat_list _open_file_list;
|
||||||
|
struct fat_list _free_file_list;
|
||||||
|
void *extra;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // FAT_CONTEXT_H_
|
||||||
128
kernel/fs/fatfs/fat_defs.h
Normal file
128
kernel/fs/fatfs/fat_defs.h
Normal file
@ -0,0 +1,128 @@
|
|||||||
|
#ifndef __FAT_DEFS_H__
|
||||||
|
#define __FAT_DEFS_H__
|
||||||
|
|
||||||
|
#include "fat_opts.h"
|
||||||
|
#include "fat_types.h"
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// FAT32 Offsets
|
||||||
|
// Name Offset
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// Boot Sector
|
||||||
|
#define BS_JMPBOOT 0 // Length = 3
|
||||||
|
#define BS_OEMNAME 3 // Length = 8
|
||||||
|
#define BPB_BYTSPERSEC 11 // Length = 2
|
||||||
|
#define BPB_SECPERCLUS 13 // Length = 1
|
||||||
|
#define BPB_RSVDSECCNT 14 // Length = 2
|
||||||
|
#define BPB_NUMFATS 16 // Length = 1
|
||||||
|
#define BPB_ROOTENTCNT 17 // Length = 2
|
||||||
|
#define BPB_TOTSEC16 19 // Length = 2
|
||||||
|
#define BPB_MEDIA 21 // Length = 1
|
||||||
|
#define BPB_FATSZ16 22 // Length = 2
|
||||||
|
#define BPB_SECPERTRK 24 // Length = 2
|
||||||
|
#define BPB_NUMHEADS 26 // Length = 2
|
||||||
|
#define BPB_HIDDSEC 28 // Length = 4
|
||||||
|
#define BPB_TOTSEC32 32 // Length = 4
|
||||||
|
|
||||||
|
// FAT 12/16
|
||||||
|
#define BS_FAT_DRVNUM 36 // Length = 1
|
||||||
|
#define BS_FAT_BOOTSIG 38 // Length = 1
|
||||||
|
#define BS_FAT_VOLID 39 // Length = 4
|
||||||
|
#define BS_FAT_VOLLAB 43 // Length = 11
|
||||||
|
#define BS_FAT_FILSYSTYPE 54 // Length = 8
|
||||||
|
|
||||||
|
// FAT 32
|
||||||
|
#define BPB_FAT32_FATSZ32 36 // Length = 4
|
||||||
|
#define BPB_FAT32_EXTFLAGS 40 // Length = 2
|
||||||
|
#define BPB_FAT32_FSVER 42 // Length = 2
|
||||||
|
#define BPB_FAT32_ROOTCLUS 44 // Length = 4
|
||||||
|
#define BPB_FAT32_FSINFO 48 // Length = 2
|
||||||
|
#define BPB_FAT32_BKBOOTSEC 50 // Length = 2
|
||||||
|
#define BS_FAT32_DRVNUM 64 // Length = 1
|
||||||
|
#define BS_FAT32_BOOTSIG 66 // Length = 1
|
||||||
|
#define BS_FAT32_VOLID 67 // Length = 4
|
||||||
|
#define BS_FAT32_VOLLAB 71 // Length = 11
|
||||||
|
#define BS_FAT32_FILSYSTYPE 82 // Length = 8
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// FAT Types
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
#define FAT_TYPE_FAT12 1
|
||||||
|
#define FAT_TYPE_FAT16 2
|
||||||
|
#define FAT_TYPE_FAT32 3
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// FAT32 Specific Statics
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
#define SIGNATURE_POSITION 510
|
||||||
|
#define SIGNATURE_VALUE 0xAA55
|
||||||
|
#define PARTITION1_TYPECODE_LOCATION 450
|
||||||
|
#define FAT32_TYPECODE1 0x0B
|
||||||
|
#define FAT32_TYPECODE2 0x0C
|
||||||
|
#define PARTITION1_LBA_BEGIN_LOCATION 454
|
||||||
|
#define PARTITION1_SIZE_LOCATION 458
|
||||||
|
|
||||||
|
#define FAT_DIR_ENTRY_SIZE 32
|
||||||
|
#define FAT_SFN_SIZE_FULL 11
|
||||||
|
#define FAT_SFN_SIZE_PARTIAL 8
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// FAT32 File Attributes and Types
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
#define FILE_ATTR_READ_ONLY 0x01
|
||||||
|
#define FILE_ATTR_HIDDEN 0x02
|
||||||
|
#define FILE_ATTR_SYSTEM 0x04
|
||||||
|
#define FILE_ATTR_SYSHID 0x06
|
||||||
|
#define FILE_ATTR_VOLUME_ID 0x08
|
||||||
|
#define FILE_ATTR_DIRECTORY 0x10
|
||||||
|
#define FILE_ATTR_ARCHIVE 0x20
|
||||||
|
#define FILE_ATTR_LFN_TEXT 0x0F
|
||||||
|
#define FILE_HEADER_BLANK 0x00
|
||||||
|
#define FILE_HEADER_DELETED 0xE5
|
||||||
|
#define FILE_TYPE_DIR 0x10
|
||||||
|
#define FILE_TYPE_FILE 0x20
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Time / Date details
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
#define FAT_TIME_HOURS_SHIFT 11
|
||||||
|
#define FAT_TIME_HOURS_MASK 0x1F
|
||||||
|
#define FAT_TIME_MINUTES_SHIFT 5
|
||||||
|
#define FAT_TIME_MINUTES_MASK 0x3F
|
||||||
|
#define FAT_TIME_SECONDS_SHIFT 0
|
||||||
|
#define FAT_TIME_SECONDS_MASK 0x1F
|
||||||
|
#define FAT_TIME_SECONDS_SCALE 2
|
||||||
|
#define FAT_DATE_YEAR_SHIFT 9
|
||||||
|
#define FAT_DATE_YEAR_MASK 0x7F
|
||||||
|
#define FAT_DATE_MONTH_SHIFT 5
|
||||||
|
#define FAT_DATE_MONTH_MASK 0xF
|
||||||
|
#define FAT_DATE_DAY_SHIFT 0
|
||||||
|
#define FAT_DATE_DAY_MASK 0x1F
|
||||||
|
#define FAT_DATE_YEAR_OFFSET 1980
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Other Defines
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
#define FAT32_LAST_CLUSTER 0xFFFFFFFF
|
||||||
|
#define FAT32_INVALID_CLUSTER 0xFFFFFFFF
|
||||||
|
|
||||||
|
STRUCT_PACK_BEGIN
|
||||||
|
struct fat_dir_entry STRUCT_PACK
|
||||||
|
{
|
||||||
|
uint8 Name[11];
|
||||||
|
uint8 Attr;
|
||||||
|
uint8 NTRes;
|
||||||
|
uint8 CrtTimeTenth;
|
||||||
|
uint8 CrtTime[2];
|
||||||
|
uint8 CrtDate[2];
|
||||||
|
uint8 LstAccDate[2];
|
||||||
|
uint16 FstClusHI;
|
||||||
|
uint8 WrtTime[2];
|
||||||
|
uint8 WrtDate[2];
|
||||||
|
uint16 FstClusLO;
|
||||||
|
uint32 FileSize;
|
||||||
|
} STRUCT_PACKED;
|
||||||
|
STRUCT_PACK_END
|
||||||
|
|
||||||
|
#endif
|
||||||
1595
kernel/fs/fatfs/fat_filelib.c
Normal file
1595
kernel/fs/fatfs/fat_filelib.c
Normal file
File diff suppressed because it is too large
Load Diff
148
kernel/fs/fatfs/fat_filelib.h
Normal file
148
kernel/fs/fatfs/fat_filelib.h
Normal file
@ -0,0 +1,148 @@
|
|||||||
|
#ifndef __FAT_FILELIB_H__
|
||||||
|
#define __FAT_FILELIB_H__
|
||||||
|
|
||||||
|
#include "fat_opts.h"
|
||||||
|
#include "fat_access.h"
|
||||||
|
#include "fat_list.h"
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Defines
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
#ifndef SEEK_CUR
|
||||||
|
#define SEEK_CUR 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef SEEK_END
|
||||||
|
#define SEEK_END 2
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef SEEK_SET
|
||||||
|
#define SEEK_SET 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef EOF
|
||||||
|
#define EOF (-1)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Structures
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
struct sFL_FILE;
|
||||||
|
|
||||||
|
struct fat_ctx;
|
||||||
|
|
||||||
|
struct cluster_lookup
|
||||||
|
{
|
||||||
|
uint32 ClusterIdx;
|
||||||
|
uint32 CurrentCluster;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct sFL_FILE
|
||||||
|
{
|
||||||
|
uint32 parentcluster;
|
||||||
|
uint32 startcluster;
|
||||||
|
uint32 bytenum;
|
||||||
|
uint32 filelength;
|
||||||
|
int filelength_changed;
|
||||||
|
char path[FATFS_MAX_LONG_FILENAME];
|
||||||
|
char filename[FATFS_MAX_LONG_FILENAME];
|
||||||
|
uint8 shortfilename[11];
|
||||||
|
|
||||||
|
#ifdef FAT_CLUSTER_CACHE_ENTRIES
|
||||||
|
uint32 cluster_cache_idx[FAT_CLUSTER_CACHE_ENTRIES];
|
||||||
|
uint32 cluster_cache_data[FAT_CLUSTER_CACHE_ENTRIES];
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Cluster Lookup
|
||||||
|
struct cluster_lookup last_fat_lookup;
|
||||||
|
|
||||||
|
// Read/Write sector buffer
|
||||||
|
uint8 file_data_sector[FAT_SECTOR_SIZE];
|
||||||
|
uint32 file_data_address;
|
||||||
|
int file_data_dirty;
|
||||||
|
|
||||||
|
// File fopen flags
|
||||||
|
uint8 flags;
|
||||||
|
#define FILE_READ (1 << 0)
|
||||||
|
#define FILE_WRITE (1 << 1)
|
||||||
|
#define FILE_APPEND (1 << 2)
|
||||||
|
#define FILE_BINARY (1 << 3)
|
||||||
|
#define FILE_ERASE (1 << 4)
|
||||||
|
#define FILE_CREATE (1 << 5)
|
||||||
|
|
||||||
|
struct fat_node list_node;
|
||||||
|
} FL_FILE;
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Prototypes
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// External
|
||||||
|
void fl_init(struct fat_ctx *ctx);
|
||||||
|
void fl_attach_locks(struct fat_ctx *ctx, void (*lock)(void), void (*unlock)(void));
|
||||||
|
int fl_attach_media(struct fat_ctx *ctx, fn_diskio_read rd, fn_diskio_write wr);
|
||||||
|
void fl_shutdown(struct fat_ctx *ctx);
|
||||||
|
|
||||||
|
// Standard API
|
||||||
|
void* fl_fopen(struct fat_ctx *ctx, const char *path, const char *modifiers);
|
||||||
|
void fl_fclose(struct fat_ctx *ctx, void *file);
|
||||||
|
int fl_fflush(struct fat_ctx *ctx, void *file);
|
||||||
|
int fl_fgetc(struct fat_ctx *ctx, void *file);
|
||||||
|
char * fl_fgets(struct fat_ctx *ctx, char *s, int n, void *f);
|
||||||
|
int fl_fputc(struct fat_ctx *ctx, int c, void *file);
|
||||||
|
int fl_fputs(struct fat_ctx *ctx, const char * str, void *file);
|
||||||
|
int fl_fwrite(struct fat_ctx *ctx, const void * data, int size, int count, void *file );
|
||||||
|
int fl_fread(struct fat_ctx *ctx, void * data, int size, int count, void *file );
|
||||||
|
int fl_fseek(struct fat_ctx *ctx, void *file , long offset , int origin );
|
||||||
|
int fl_fgetpos(struct fat_ctx *ctx, void *file , uint32 * position);
|
||||||
|
long fl_ftell(struct fat_ctx *ctx, void *f);
|
||||||
|
int fl_feof(struct fat_ctx *ctx, void *f);
|
||||||
|
int fl_remove(struct fat_ctx *ctx, const char * filename);
|
||||||
|
|
||||||
|
// Equivelant dirent.h
|
||||||
|
typedef struct fs_dir_list_status FL_DIR;
|
||||||
|
typedef struct fs_dir_ent fl_dirent;
|
||||||
|
|
||||||
|
FL_DIR* fl_opendir(struct fat_ctx *ctx, const char* path, FL_DIR *dir);
|
||||||
|
int fl_readdir(struct fat_ctx *ctx, FL_DIR *dirls, fl_dirent *entry);
|
||||||
|
int fl_closedir(struct fat_ctx *ctx, FL_DIR* dir);
|
||||||
|
|
||||||
|
// Extensions
|
||||||
|
void fl_listdirectory(struct fat_ctx *ctx, const char *path);
|
||||||
|
int fl_createdirectory(struct fat_ctx *ctx, const char *path);
|
||||||
|
int fl_is_dir(struct fat_ctx *ctx, const char *path);
|
||||||
|
|
||||||
|
int fl_format(struct fat_ctx *ctx, uint32 volume_sectors, const char *name);
|
||||||
|
|
||||||
|
// Test hooks
|
||||||
|
#ifdef FATFS_INC_TEST_HOOKS
|
||||||
|
struct fatfs* fl_get_fs(struct fat_ctx *ctx);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Stdio file I/O names
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
#ifdef USE_FILELIB_STDIO_COMPAT_NAMES
|
||||||
|
|
||||||
|
#define FILE FL_FILE
|
||||||
|
|
||||||
|
#define fopen(a,b) fl_fopen(a, b)
|
||||||
|
#define fclose(a) fl_fclose(a)
|
||||||
|
#define fflush(a) fl_fflush(a)
|
||||||
|
#define fgetc(a) fl_fgetc(a)
|
||||||
|
#define fgets(a,b,c) fl_fgets(a, b, c)
|
||||||
|
#define fputc(a,b) fl_fputc(a, b)
|
||||||
|
#define fputs(a,b) fl_fputs(a, b)
|
||||||
|
#define fwrite(a,b,c,d) fl_fwrite(a, b, c, d)
|
||||||
|
#define fread(a,b,c,d) fl_fread(a, b, c, d)
|
||||||
|
#define fseek(a,b,c) fl_fseek(a, b, c)
|
||||||
|
#define fgetpos(a,b) fl_fgetpos(a, b)
|
||||||
|
#define ftell(a) fl_ftell(a)
|
||||||
|
#define feof(a) fl_feof(a)
|
||||||
|
#define remove(a) fl_remove(a)
|
||||||
|
#define mkdir(a) fl_createdirectory(a)
|
||||||
|
#define rmdir(a) 0
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
532
kernel/fs/fatfs/fat_format.c
Normal file
532
kernel/fs/fatfs/fat_format.c
Normal file
@ -0,0 +1,532 @@
|
|||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// FAT16/32 File IO Library
|
||||||
|
// V2.6
|
||||||
|
// Ultra-Embedded.com
|
||||||
|
// Copyright 2003 - 2012
|
||||||
|
//
|
||||||
|
// Email: admin@ultra-embedded.com
|
||||||
|
//
|
||||||
|
// License: GPL
|
||||||
|
// If you would like a version with a more permissive license for use in
|
||||||
|
// closed source commercial applications please contact me for details.
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// This file is part of FAT File IO Library.
|
||||||
|
//
|
||||||
|
// FAT File IO Library is free software; you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation; either version 2 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// FAT File IO Library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with FAT File IO Library; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
#include <string.h>
|
||||||
|
#include "fat_defs.h"
|
||||||
|
#include "fat_access.h"
|
||||||
|
#include "fat_table.h"
|
||||||
|
#include "fat_write.h"
|
||||||
|
#include "fat_string.h"
|
||||||
|
#include "fat_misc.h"
|
||||||
|
#include "fat_format.h"
|
||||||
|
|
||||||
|
#if FATFS_INC_FORMAT_SUPPORT
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Tables
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
struct sec_per_clus_table
|
||||||
|
{
|
||||||
|
uint32 sectors;
|
||||||
|
uint8 sectors_per_cluster;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct sec_per_clus_table _cluster_size_table16[] =
|
||||||
|
{
|
||||||
|
{ 32680, 2}, // 16MB - 1K
|
||||||
|
{ 262144, 4}, // 128MB - 2K
|
||||||
|
{ 524288, 8}, // 256MB - 4K
|
||||||
|
{ 1048576, 16}, // 512MB - 8K
|
||||||
|
{ 2097152, 32}, // 1GB - 16K
|
||||||
|
{ 4194304, 64}, // 2GB - 32K
|
||||||
|
{ 8388608, 128},// 2GB - 64K [Warning only supported by Windows XP onwards]
|
||||||
|
{ 0 , 0 } // Invalid
|
||||||
|
};
|
||||||
|
|
||||||
|
struct sec_per_clus_table _cluster_size_table32[] =
|
||||||
|
{
|
||||||
|
{ 532480, 1}, // 260MB - 512b
|
||||||
|
{ 16777216, 8}, // 8GB - 4K
|
||||||
|
{ 33554432, 16}, // 16GB - 8K
|
||||||
|
{ 67108864, 32}, // 32GB - 16K
|
||||||
|
{ 0xFFFFFFFF, 64},// >32GB - 32K
|
||||||
|
{ 0 , 0 } // Invalid
|
||||||
|
};
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// fatfs_calc_cluster_size: Calculate what cluster size should be used
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
static uint8 fatfs_calc_cluster_size(uint32 sectors, int is_fat32)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (!is_fat32)
|
||||||
|
{
|
||||||
|
for (i=0; _cluster_size_table16[i].sectors_per_cluster != 0;i++)
|
||||||
|
if (sectors <= _cluster_size_table16[i].sectors)
|
||||||
|
return _cluster_size_table16[i].sectors_per_cluster;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (i=0; _cluster_size_table32[i].sectors_per_cluster != 0;i++)
|
||||||
|
if (sectors <= _cluster_size_table32[i].sectors)
|
||||||
|
return _cluster_size_table32[i].sectors_per_cluster;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// fatfs_erase_sectors: Erase a number of sectors
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
static int fatfs_erase_sectors(struct fat_ctx *ctx, struct fatfs *fs, uint32 lba, int count)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
// Zero sector first
|
||||||
|
memset(fs->currentsector.sector, 0, FAT_SECTOR_SIZE);
|
||||||
|
|
||||||
|
for (i=0;i<count;i++)
|
||||||
|
if (!fs->disk_io.write_media(ctx, lba + i, fs->currentsector.sector, 1))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// fatfs_create_boot_sector: Create the boot sector
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
static int fatfs_create_boot_sector(struct fat_ctx *ctx, struct fatfs *fs, uint32 boot_sector_lba, uint32 vol_sectors, const char *name, int is_fat32)
|
||||||
|
{
|
||||||
|
uint32 total_clusters;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
// Zero sector initially
|
||||||
|
memset(fs->currentsector.sector, 0, FAT_SECTOR_SIZE);
|
||||||
|
|
||||||
|
// OEM Name & Jump Code
|
||||||
|
fs->currentsector.sector[0] = 0xEB;
|
||||||
|
fs->currentsector.sector[1] = 0x3C;
|
||||||
|
fs->currentsector.sector[2] = 0x90;
|
||||||
|
fs->currentsector.sector[3] = 0x4D;
|
||||||
|
fs->currentsector.sector[4] = 0x53;
|
||||||
|
fs->currentsector.sector[5] = 0x44;
|
||||||
|
fs->currentsector.sector[6] = 0x4F;
|
||||||
|
fs->currentsector.sector[7] = 0x53;
|
||||||
|
fs->currentsector.sector[8] = 0x35;
|
||||||
|
fs->currentsector.sector[9] = 0x2E;
|
||||||
|
fs->currentsector.sector[10] = 0x30;
|
||||||
|
|
||||||
|
// Bytes per sector
|
||||||
|
fs->currentsector.sector[11] = (FAT_SECTOR_SIZE >> 0) & 0xFF;
|
||||||
|
fs->currentsector.sector[12] = (FAT_SECTOR_SIZE >> 8) & 0xFF;
|
||||||
|
|
||||||
|
// Get sectors per cluster size for the disk
|
||||||
|
fs->sectors_per_cluster = fatfs_calc_cluster_size(vol_sectors, is_fat32);
|
||||||
|
if (!fs->sectors_per_cluster)
|
||||||
|
return 0; // Invalid disk size
|
||||||
|
|
||||||
|
// Sectors per cluster
|
||||||
|
fs->currentsector.sector[13] = fs->sectors_per_cluster;
|
||||||
|
|
||||||
|
// Reserved Sectors
|
||||||
|
if (!is_fat32)
|
||||||
|
fs->reserved_sectors = 8;
|
||||||
|
else
|
||||||
|
fs->reserved_sectors = 32;
|
||||||
|
fs->currentsector.sector[14] = (fs->reserved_sectors >> 0) & 0xFF;
|
||||||
|
fs->currentsector.sector[15] = (fs->reserved_sectors >> 8) & 0xFF;
|
||||||
|
|
||||||
|
// Number of FATS
|
||||||
|
fs->num_of_fats = 2;
|
||||||
|
fs->currentsector.sector[16] = fs->num_of_fats;
|
||||||
|
|
||||||
|
// Max entries in root dir (FAT16 only)
|
||||||
|
if (!is_fat32)
|
||||||
|
{
|
||||||
|
fs->root_entry_count = 512;
|
||||||
|
fs->currentsector.sector[17] = (fs->root_entry_count >> 0) & 0xFF;
|
||||||
|
fs->currentsector.sector[18] = (fs->root_entry_count >> 8) & 0xFF;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fs->root_entry_count = 0;
|
||||||
|
fs->currentsector.sector[17] = 0;
|
||||||
|
fs->currentsector.sector[18] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// [FAT16] Total sectors (use FAT32 count instead)
|
||||||
|
fs->currentsector.sector[19] = 0x00;
|
||||||
|
fs->currentsector.sector[20] = 0x00;
|
||||||
|
|
||||||
|
// Media type
|
||||||
|
fs->currentsector.sector[21] = 0xF8;
|
||||||
|
|
||||||
|
|
||||||
|
// FAT16 BS Details
|
||||||
|
if (!is_fat32)
|
||||||
|
{
|
||||||
|
// Count of sectors used by the FAT table (FAT16 only)
|
||||||
|
total_clusters = (vol_sectors / fs->sectors_per_cluster) + 1;
|
||||||
|
fs->fat_sectors = (total_clusters/(FAT_SECTOR_SIZE/2)) + 1;
|
||||||
|
fs->currentsector.sector[22] = (uint8)((fs->fat_sectors >> 0) & 0xFF);
|
||||||
|
fs->currentsector.sector[23] = (uint8)((fs->fat_sectors >> 8) & 0xFF);
|
||||||
|
|
||||||
|
// Sectors per track
|
||||||
|
fs->currentsector.sector[24] = 0x00;
|
||||||
|
fs->currentsector.sector[25] = 0x00;
|
||||||
|
|
||||||
|
// Heads
|
||||||
|
fs->currentsector.sector[26] = 0x00;
|
||||||
|
fs->currentsector.sector[27] = 0x00;
|
||||||
|
|
||||||
|
// Hidden sectors
|
||||||
|
fs->currentsector.sector[28] = 0x20;
|
||||||
|
fs->currentsector.sector[29] = 0x00;
|
||||||
|
fs->currentsector.sector[30] = 0x00;
|
||||||
|
fs->currentsector.sector[31] = 0x00;
|
||||||
|
|
||||||
|
// Total sectors for this volume
|
||||||
|
fs->currentsector.sector[32] = (uint8)((vol_sectors>>0)&0xFF);
|
||||||
|
fs->currentsector.sector[33] = (uint8)((vol_sectors>>8)&0xFF);
|
||||||
|
fs->currentsector.sector[34] = (uint8)((vol_sectors>>16)&0xFF);
|
||||||
|
fs->currentsector.sector[35] = (uint8)((vol_sectors>>24)&0xFF);
|
||||||
|
|
||||||
|
// Drive number
|
||||||
|
fs->currentsector.sector[36] = 0x00;
|
||||||
|
|
||||||
|
// Reserved
|
||||||
|
fs->currentsector.sector[37] = 0x00;
|
||||||
|
|
||||||
|
// Boot signature
|
||||||
|
fs->currentsector.sector[38] = 0x29;
|
||||||
|
|
||||||
|
// Volume ID
|
||||||
|
fs->currentsector.sector[39] = 0x12;
|
||||||
|
fs->currentsector.sector[40] = 0x34;
|
||||||
|
fs->currentsector.sector[41] = 0x56;
|
||||||
|
fs->currentsector.sector[42] = 0x78;
|
||||||
|
|
||||||
|
// Volume name
|
||||||
|
for (i=0;i<11;i++)
|
||||||
|
{
|
||||||
|
if (i < (int)strlen(name))
|
||||||
|
fs->currentsector.sector[i+43] = name[i];
|
||||||
|
else
|
||||||
|
fs->currentsector.sector[i+43] = ' ';
|
||||||
|
}
|
||||||
|
|
||||||
|
// File sys type
|
||||||
|
fs->currentsector.sector[54] = 'F';
|
||||||
|
fs->currentsector.sector[55] = 'A';
|
||||||
|
fs->currentsector.sector[56] = 'T';
|
||||||
|
fs->currentsector.sector[57] = '1';
|
||||||
|
fs->currentsector.sector[58] = '6';
|
||||||
|
fs->currentsector.sector[59] = ' ';
|
||||||
|
fs->currentsector.sector[60] = ' ';
|
||||||
|
fs->currentsector.sector[61] = ' ';
|
||||||
|
|
||||||
|
// Signature
|
||||||
|
fs->currentsector.sector[510] = 0x55;
|
||||||
|
fs->currentsector.sector[511] = 0xAA;
|
||||||
|
}
|
||||||
|
// FAT32 BS Details
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Count of sectors used by the FAT table (FAT16 only)
|
||||||
|
fs->currentsector.sector[22] = 0;
|
||||||
|
fs->currentsector.sector[23] = 0;
|
||||||
|
|
||||||
|
// Sectors per track (default)
|
||||||
|
fs->currentsector.sector[24] = 0x3F;
|
||||||
|
fs->currentsector.sector[25] = 0x00;
|
||||||
|
|
||||||
|
// Heads (default)
|
||||||
|
fs->currentsector.sector[26] = 0xFF;
|
||||||
|
fs->currentsector.sector[27] = 0x00;
|
||||||
|
|
||||||
|
// Hidden sectors
|
||||||
|
fs->currentsector.sector[28] = 0x00;
|
||||||
|
fs->currentsector.sector[29] = 0x00;
|
||||||
|
fs->currentsector.sector[30] = 0x00;
|
||||||
|
fs->currentsector.sector[31] = 0x00;
|
||||||
|
|
||||||
|
// Total sectors for this volume
|
||||||
|
fs->currentsector.sector[32] = (uint8)((vol_sectors>>0)&0xFF);
|
||||||
|
fs->currentsector.sector[33] = (uint8)((vol_sectors>>8)&0xFF);
|
||||||
|
fs->currentsector.sector[34] = (uint8)((vol_sectors>>16)&0xFF);
|
||||||
|
fs->currentsector.sector[35] = (uint8)((vol_sectors>>24)&0xFF);
|
||||||
|
|
||||||
|
total_clusters = (vol_sectors / fs->sectors_per_cluster) + 1;
|
||||||
|
fs->fat_sectors = (total_clusters/(FAT_SECTOR_SIZE/4)) + 1;
|
||||||
|
|
||||||
|
// BPB_FATSz32
|
||||||
|
fs->currentsector.sector[36] = (uint8)((fs->fat_sectors>>0)&0xFF);
|
||||||
|
fs->currentsector.sector[37] = (uint8)((fs->fat_sectors>>8)&0xFF);
|
||||||
|
fs->currentsector.sector[38] = (uint8)((fs->fat_sectors>>16)&0xFF);
|
||||||
|
fs->currentsector.sector[39] = (uint8)((fs->fat_sectors>>24)&0xFF);
|
||||||
|
|
||||||
|
// BPB_ExtFlags
|
||||||
|
fs->currentsector.sector[40] = 0;
|
||||||
|
fs->currentsector.sector[41] = 0;
|
||||||
|
|
||||||
|
// BPB_FSVer
|
||||||
|
fs->currentsector.sector[42] = 0;
|
||||||
|
fs->currentsector.sector[43] = 0;
|
||||||
|
|
||||||
|
// BPB_RootClus
|
||||||
|
fs->currentsector.sector[44] = (uint8)((fs->rootdir_first_cluster>>0)&0xFF);
|
||||||
|
fs->currentsector.sector[45] = (uint8)((fs->rootdir_first_cluster>>8)&0xFF);
|
||||||
|
fs->currentsector.sector[46] = (uint8)((fs->rootdir_first_cluster>>16)&0xFF);
|
||||||
|
fs->currentsector.sector[47] = (uint8)((fs->rootdir_first_cluster>>24)&0xFF);
|
||||||
|
|
||||||
|
// BPB_FSInfo
|
||||||
|
fs->currentsector.sector[48] = (uint8)((fs->fs_info_sector>>0)&0xFF);
|
||||||
|
fs->currentsector.sector[49] = (uint8)((fs->fs_info_sector>>8)&0xFF);
|
||||||
|
|
||||||
|
// BPB_BkBootSec
|
||||||
|
fs->currentsector.sector[50] = 6;
|
||||||
|
fs->currentsector.sector[51] = 0;
|
||||||
|
|
||||||
|
// Drive number
|
||||||
|
fs->currentsector.sector[64] = 0x00;
|
||||||
|
|
||||||
|
// Boot signature
|
||||||
|
fs->currentsector.sector[66] = 0x29;
|
||||||
|
|
||||||
|
// Volume ID
|
||||||
|
fs->currentsector.sector[67] = 0x12;
|
||||||
|
fs->currentsector.sector[68] = 0x34;
|
||||||
|
fs->currentsector.sector[69] = 0x56;
|
||||||
|
fs->currentsector.sector[70] = 0x78;
|
||||||
|
|
||||||
|
// Volume name
|
||||||
|
for (i=0;i<11;i++)
|
||||||
|
{
|
||||||
|
if (i < (int)strlen(name))
|
||||||
|
fs->currentsector.sector[i+71] = name[i];
|
||||||
|
else
|
||||||
|
fs->currentsector.sector[i+71] = ' ';
|
||||||
|
}
|
||||||
|
|
||||||
|
// File sys type
|
||||||
|
fs->currentsector.sector[82] = 'F';
|
||||||
|
fs->currentsector.sector[83] = 'A';
|
||||||
|
fs->currentsector.sector[84] = 'T';
|
||||||
|
fs->currentsector.sector[85] = '3';
|
||||||
|
fs->currentsector.sector[86] = '2';
|
||||||
|
fs->currentsector.sector[87] = ' ';
|
||||||
|
fs->currentsector.sector[88] = ' ';
|
||||||
|
fs->currentsector.sector[89] = ' ';
|
||||||
|
|
||||||
|
// Signature
|
||||||
|
fs->currentsector.sector[510] = 0x55;
|
||||||
|
fs->currentsector.sector[511] = 0xAA;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fs->disk_io.write_media(ctx, boot_sector_lba, fs->currentsector.sector, 1))
|
||||||
|
return 1;
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// fatfs_create_fsinfo_sector: Create the FSInfo sector (FAT32)
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
static int fatfs_create_fsinfo_sector(struct fat_ctx *ctx, struct fatfs *fs, uint32 sector_lba)
|
||||||
|
{
|
||||||
|
// Zero sector initially
|
||||||
|
memset(fs->currentsector.sector, 0, FAT_SECTOR_SIZE);
|
||||||
|
|
||||||
|
// FSI_LeadSig
|
||||||
|
fs->currentsector.sector[0] = 0x52;
|
||||||
|
fs->currentsector.sector[1] = 0x52;
|
||||||
|
fs->currentsector.sector[2] = 0x61;
|
||||||
|
fs->currentsector.sector[3] = 0x41;
|
||||||
|
|
||||||
|
// FSI_StrucSig
|
||||||
|
fs->currentsector.sector[484] = 0x72;
|
||||||
|
fs->currentsector.sector[485] = 0x72;
|
||||||
|
fs->currentsector.sector[486] = 0x41;
|
||||||
|
fs->currentsector.sector[487] = 0x61;
|
||||||
|
|
||||||
|
// FSI_Free_Count
|
||||||
|
fs->currentsector.sector[488] = 0xFF;
|
||||||
|
fs->currentsector.sector[489] = 0xFF;
|
||||||
|
fs->currentsector.sector[490] = 0xFF;
|
||||||
|
fs->currentsector.sector[491] = 0xFF;
|
||||||
|
|
||||||
|
// FSI_Nxt_Free
|
||||||
|
fs->currentsector.sector[492] = 0xFF;
|
||||||
|
fs->currentsector.sector[493] = 0xFF;
|
||||||
|
fs->currentsector.sector[494] = 0xFF;
|
||||||
|
fs->currentsector.sector[495] = 0xFF;
|
||||||
|
|
||||||
|
// Signature
|
||||||
|
fs->currentsector.sector[510] = 0x55;
|
||||||
|
fs->currentsector.sector[511] = 0xAA;
|
||||||
|
|
||||||
|
if (fs->disk_io.write_media(ctx, sector_lba, fs->currentsector.sector, 1))
|
||||||
|
return 1;
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// fatfs_erase_fat: Erase FAT table using fs details in fs struct
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
static int fatfs_erase_fat(struct fat_ctx *ctx, struct fatfs *fs, int is_fat32)
|
||||||
|
{
|
||||||
|
uint32 i;
|
||||||
|
|
||||||
|
// Zero sector initially
|
||||||
|
memset(fs->currentsector.sector, 0, FAT_SECTOR_SIZE);
|
||||||
|
|
||||||
|
// Initialise default allocate / reserved clusters
|
||||||
|
if (!is_fat32)
|
||||||
|
{
|
||||||
|
SET_16BIT_WORD(fs->currentsector.sector, 0, 0xFFF8);
|
||||||
|
SET_16BIT_WORD(fs->currentsector.sector, 2, 0xFFFF);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SET_32BIT_WORD(fs->currentsector.sector, 0, 0x0FFFFFF8);
|
||||||
|
SET_32BIT_WORD(fs->currentsector.sector, 4, 0xFFFFFFFF);
|
||||||
|
SET_32BIT_WORD(fs->currentsector.sector, 8, 0x0FFFFFFF);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!fs->disk_io.write_media(ctx, fs->fat_begin_lba + 0, fs->currentsector.sector, 1))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
// Zero remaining FAT sectors
|
||||||
|
memset(fs->currentsector.sector, 0, FAT_SECTOR_SIZE);
|
||||||
|
for (i=1;i<fs->fat_sectors*fs->num_of_fats;i++)
|
||||||
|
if (!fs->disk_io.write_media(ctx, fs->fat_begin_lba + i, fs->currentsector.sector, 1))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// fatfs_format_fat16: Format a FAT16 partition
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
int fatfs_format_fat16(struct fat_ctx *ctx, struct fatfs *fs, uint32 volume_sectors, const char *name)
|
||||||
|
{
|
||||||
|
fs->currentsector.address = FAT32_INVALID_CLUSTER;
|
||||||
|
fs->currentsector.dirty = 0;
|
||||||
|
|
||||||
|
fs->next_free_cluster = 0; // Invalid
|
||||||
|
|
||||||
|
fatfs_fat_init(fs);
|
||||||
|
|
||||||
|
// Make sure we have read + write functions
|
||||||
|
if (!fs->disk_io.read_media || !fs->disk_io.write_media)
|
||||||
|
return FAT_INIT_MEDIA_ACCESS_ERROR;
|
||||||
|
|
||||||
|
// Volume is FAT16
|
||||||
|
fs->fat_type = FAT_TYPE_16;
|
||||||
|
|
||||||
|
// Not valid for FAT16
|
||||||
|
fs->fs_info_sector = 0;
|
||||||
|
fs->rootdir_first_cluster = 0;
|
||||||
|
|
||||||
|
// Sector 0: Boot sector
|
||||||
|
// NOTE: We don't need an MBR, it is a waste of a good sector!
|
||||||
|
fs->lba_begin = 0;
|
||||||
|
if (!fatfs_create_boot_sector(ctx, fs, fs->lba_begin, volume_sectors, name, 0))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
// For FAT16 (which this may be), rootdir_first_cluster is actuall rootdir_first_sector
|
||||||
|
fs->rootdir_first_sector = fs->reserved_sectors + (fs->num_of_fats * fs->fat_sectors);
|
||||||
|
fs->rootdir_sectors = ((fs->root_entry_count * 32) + (FAT_SECTOR_SIZE - 1)) / FAT_SECTOR_SIZE;
|
||||||
|
|
||||||
|
// First FAT LBA address
|
||||||
|
fs->fat_begin_lba = fs->lba_begin + fs->reserved_sectors;
|
||||||
|
|
||||||
|
// The address of the first data cluster on this volume
|
||||||
|
fs->cluster_begin_lba = fs->fat_begin_lba + (fs->num_of_fats * fs->fat_sectors);
|
||||||
|
|
||||||
|
// Initialise FAT sectors
|
||||||
|
if (!fatfs_erase_fat(ctx, fs, 0))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
// Erase Root directory
|
||||||
|
if (!fatfs_erase_sectors(ctx, fs, fs->lba_begin + fs->rootdir_first_sector, fs->rootdir_sectors))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// fatfs_format_fat32: Format a FAT32 partition
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
int fatfs_format_fat32(struct fat_ctx *ctx, struct fatfs *fs, uint32 volume_sectors, const char *name)
|
||||||
|
{
|
||||||
|
fs->currentsector.address = FAT32_INVALID_CLUSTER;
|
||||||
|
fs->currentsector.dirty = 0;
|
||||||
|
|
||||||
|
fs->next_free_cluster = 0; // Invalid
|
||||||
|
|
||||||
|
fatfs_fat_init(fs);
|
||||||
|
|
||||||
|
// Make sure we have read + write functions
|
||||||
|
if (!fs->disk_io.read_media || !fs->disk_io.write_media)
|
||||||
|
return FAT_INIT_MEDIA_ACCESS_ERROR;
|
||||||
|
|
||||||
|
// Volume is FAT32
|
||||||
|
fs->fat_type = FAT_TYPE_32;
|
||||||
|
|
||||||
|
// Basic defaults for normal FAT32 partitions
|
||||||
|
fs->fs_info_sector = 1;
|
||||||
|
fs->rootdir_first_cluster = 2;
|
||||||
|
|
||||||
|
// Sector 0: Boot sector
|
||||||
|
// NOTE: We don't need an MBR, it is a waste of a good sector!
|
||||||
|
fs->lba_begin = 0;
|
||||||
|
if (!fatfs_create_boot_sector(ctx, fs, fs->lba_begin, volume_sectors, name, 1))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
// First FAT LBA address
|
||||||
|
fs->fat_begin_lba = fs->lba_begin + fs->reserved_sectors;
|
||||||
|
|
||||||
|
// The address of the first data cluster on this volume
|
||||||
|
fs->cluster_begin_lba = fs->fat_begin_lba + (fs->num_of_fats * fs->fat_sectors);
|
||||||
|
|
||||||
|
// Initialise FSInfo sector
|
||||||
|
if (!fatfs_create_fsinfo_sector(ctx, fs, fs->fs_info_sector))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
// Initialise FAT sectors
|
||||||
|
if (!fatfs_erase_fat(ctx, fs, 1))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
// Erase Root directory
|
||||||
|
if (!fatfs_erase_sectors(ctx, fs, fatfs_lba_of_cluster(fs, fs->rootdir_first_cluster), fs->sectors_per_cluster))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// fatfs_format: Format a partition with either FAT16 or FAT32 based on size
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
int fatfs_format(struct fat_ctx *ctx, struct fatfs *fs, uint32 volume_sectors, const char *name)
|
||||||
|
{
|
||||||
|
// 2GB - 32K limit for safe behaviour for FAT16
|
||||||
|
if (volume_sectors <= 4194304)
|
||||||
|
return fatfs_format_fat16(ctx, fs, volume_sectors, name);
|
||||||
|
else
|
||||||
|
return fatfs_format_fat32(ctx, fs, volume_sectors, name);
|
||||||
|
}
|
||||||
|
#endif /*FATFS_INC_FORMAT_SUPPORT*/
|
||||||
17
kernel/fs/fatfs/fat_format.h
Normal file
17
kernel/fs/fatfs/fat_format.h
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
#ifndef __FAT_FORMAT_H__
|
||||||
|
#define __FAT_FORMAT_H__
|
||||||
|
|
||||||
|
#include "fat_defs.h"
|
||||||
|
#include "fat_opts.h"
|
||||||
|
#include "fat_access.h"
|
||||||
|
|
||||||
|
struct fat_ctx;
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Prototypes
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
int fatfs_format(struct fat_ctx *ctx, struct fatfs *fs, uint32 volume_sectors, const char *name);
|
||||||
|
int fatfs_format_fat16(struct fat_ctx *ctx, struct fatfs *fs, uint32 volume_sectors, const char *name);
|
||||||
|
int fatfs_format_fat32(struct fat_ctx *ctx, struct fatfs *fs, uint32 volume_sectors, const char *name);
|
||||||
|
|
||||||
|
#endif
|
||||||
161
kernel/fs/fatfs/fat_list.h
Normal file
161
kernel/fs/fatfs/fat_list.h
Normal file
@ -0,0 +1,161 @@
|
|||||||
|
#ifndef __FAT_LIST_H__
|
||||||
|
#define __FAT_LIST_H__
|
||||||
|
|
||||||
|
#ifndef FAT_ASSERT
|
||||||
|
#define FAT_ASSERT(x)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef FAT_INLINE
|
||||||
|
#define FAT_INLINE
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------
|
||||||
|
// Types
|
||||||
|
//-----------------------------------------------------------------
|
||||||
|
struct fat_list;
|
||||||
|
|
||||||
|
struct fat_node
|
||||||
|
{
|
||||||
|
struct fat_node *previous;
|
||||||
|
struct fat_node *next;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct fat_list
|
||||||
|
{
|
||||||
|
struct fat_node *head;
|
||||||
|
struct fat_node *tail;
|
||||||
|
};
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------
|
||||||
|
// Macros
|
||||||
|
//-----------------------------------------------------------------
|
||||||
|
#define fat_list_entry(p, t, m) p ? ((t *)((char *)(p)-(char*)(&((t *)0)->m))) : 0
|
||||||
|
#define fat_list_next(l, p) (p)->next
|
||||||
|
#define fat_list_prev(l, p) (p)->previous
|
||||||
|
#define fat_list_first(l) (l)->head
|
||||||
|
#define fat_list_last(l) (l)->tail
|
||||||
|
#define fat_list_for_each(l, p) for ((p) = (l)->head; (p); (p) = (p)->next)
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------
|
||||||
|
// Inline Functions
|
||||||
|
//-----------------------------------------------------------------
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------
|
||||||
|
// fat_list_init:
|
||||||
|
//-----------------------------------------------------------------
|
||||||
|
static FAT_INLINE void fat_list_init(struct fat_list *list)
|
||||||
|
{
|
||||||
|
FAT_ASSERT(list);
|
||||||
|
|
||||||
|
list->head = list->tail = 0;
|
||||||
|
}
|
||||||
|
//-----------------------------------------------------------------
|
||||||
|
// fat_list_remove:
|
||||||
|
//-----------------------------------------------------------------
|
||||||
|
static FAT_INLINE void fat_list_remove(struct fat_list *list, struct fat_node *node)
|
||||||
|
{
|
||||||
|
FAT_ASSERT(list);
|
||||||
|
FAT_ASSERT(node);
|
||||||
|
|
||||||
|
if(!node->previous)
|
||||||
|
list->head = node->next;
|
||||||
|
else
|
||||||
|
node->previous->next = node->next;
|
||||||
|
|
||||||
|
if(!node->next)
|
||||||
|
list->tail = node->previous;
|
||||||
|
else
|
||||||
|
node->next->previous = node->previous;
|
||||||
|
}
|
||||||
|
//-----------------------------------------------------------------
|
||||||
|
// fat_list_insert_after:
|
||||||
|
//-----------------------------------------------------------------
|
||||||
|
static FAT_INLINE void fat_list_insert_after(struct fat_list *list, struct fat_node *node, struct fat_node *new_node)
|
||||||
|
{
|
||||||
|
FAT_ASSERT(list);
|
||||||
|
FAT_ASSERT(node);
|
||||||
|
FAT_ASSERT(new_node);
|
||||||
|
|
||||||
|
new_node->previous = node;
|
||||||
|
new_node->next = node->next;
|
||||||
|
if (!node->next)
|
||||||
|
list->tail = new_node;
|
||||||
|
else
|
||||||
|
node->next->previous = new_node;
|
||||||
|
node->next = new_node;
|
||||||
|
}
|
||||||
|
//-----------------------------------------------------------------
|
||||||
|
// fat_list_insert_before:
|
||||||
|
//-----------------------------------------------------------------
|
||||||
|
static FAT_INLINE void fat_list_insert_before(struct fat_list *list, struct fat_node *node, struct fat_node *new_node)
|
||||||
|
{
|
||||||
|
FAT_ASSERT(list);
|
||||||
|
FAT_ASSERT(node);
|
||||||
|
FAT_ASSERT(new_node);
|
||||||
|
|
||||||
|
new_node->previous = node->previous;
|
||||||
|
new_node->next = node;
|
||||||
|
if (!node->previous)
|
||||||
|
list->head = new_node;
|
||||||
|
else
|
||||||
|
node->previous->next = new_node;
|
||||||
|
node->previous = new_node;
|
||||||
|
}
|
||||||
|
//-----------------------------------------------------------------
|
||||||
|
// fat_list_insert_first:
|
||||||
|
//-----------------------------------------------------------------
|
||||||
|
static FAT_INLINE void fat_list_insert_first(struct fat_list *list, struct fat_node *node)
|
||||||
|
{
|
||||||
|
FAT_ASSERT(list);
|
||||||
|
FAT_ASSERT(node);
|
||||||
|
|
||||||
|
if (!list->head)
|
||||||
|
{
|
||||||
|
list->head = node;
|
||||||
|
list->tail = node;
|
||||||
|
node->previous = 0;
|
||||||
|
node->next = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
fat_list_insert_before(list, list->head, node);
|
||||||
|
}
|
||||||
|
//-----------------------------------------------------------------
|
||||||
|
// fat_list_insert_last:
|
||||||
|
//-----------------------------------------------------------------
|
||||||
|
static FAT_INLINE void fat_list_insert_last(struct fat_list *list, struct fat_node *node)
|
||||||
|
{
|
||||||
|
FAT_ASSERT(list);
|
||||||
|
FAT_ASSERT(node);
|
||||||
|
|
||||||
|
if (!list->tail)
|
||||||
|
fat_list_insert_first(list, node);
|
||||||
|
else
|
||||||
|
fat_list_insert_after(list, list->tail, node);
|
||||||
|
}
|
||||||
|
//-----------------------------------------------------------------
|
||||||
|
// fat_list_is_empty:
|
||||||
|
//-----------------------------------------------------------------
|
||||||
|
static FAT_INLINE int fat_list_is_empty(struct fat_list *list)
|
||||||
|
{
|
||||||
|
FAT_ASSERT(list);
|
||||||
|
|
||||||
|
return !list->head;
|
||||||
|
}
|
||||||
|
//-----------------------------------------------------------------
|
||||||
|
// fat_list_pop_head:
|
||||||
|
//-----------------------------------------------------------------
|
||||||
|
static FAT_INLINE struct fat_node * fat_list_pop_head(struct fat_list *list)
|
||||||
|
{
|
||||||
|
struct fat_node * node;
|
||||||
|
|
||||||
|
FAT_ASSERT(list);
|
||||||
|
|
||||||
|
node = fat_list_first(list);
|
||||||
|
if (node)
|
||||||
|
fat_list_remove(list, node);
|
||||||
|
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
505
kernel/fs/fatfs/fat_misc.c
Normal file
505
kernel/fs/fatfs/fat_misc.c
Normal file
@ -0,0 +1,505 @@
|
|||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// FAT16/32 File IO Library
|
||||||
|
// V2.6
|
||||||
|
// Ultra-Embedded.com
|
||||||
|
// Copyright 2003 - 2012
|
||||||
|
//
|
||||||
|
// Email: admin@ultra-embedded.com
|
||||||
|
//
|
||||||
|
// License: GPL
|
||||||
|
// If you would like a version with a more permissive license for use in
|
||||||
|
// closed source commercial applications please contact me for details.
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// This file is part of FAT File IO Library.
|
||||||
|
//
|
||||||
|
// FAT File IO Library is free software; you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation; either version 2 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// FAT File IO Library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with FAT File IO Library; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "fat_misc.h"
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// fatfs_lfn_cache_init: Clear long file name cache
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
void fatfs_lfn_cache_init(struct lfn_cache *lfn, int wipeTable)
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
lfn->no_of_strings = 0;
|
||||||
|
|
||||||
|
#if FATFS_INC_LFN_SUPPORT
|
||||||
|
|
||||||
|
// Zero out buffer also
|
||||||
|
if (wipeTable)
|
||||||
|
for (i=0;i<MAX_LONGFILENAME_ENTRIES;i++)
|
||||||
|
memset(lfn->String[i], 0x00, MAX_LFN_ENTRY_LENGTH);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// fatfs_lfn_cache_entry - Function extracts long file name text from sector
|
||||||
|
// at a specific offset
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
#if FATFS_INC_LFN_SUPPORT
|
||||||
|
void fatfs_lfn_cache_entry(struct lfn_cache *lfn, uint8 *entryBuffer)
|
||||||
|
{
|
||||||
|
uint8 LFNIndex, i;
|
||||||
|
LFNIndex = entryBuffer[0] & 0x1F;
|
||||||
|
|
||||||
|
// Limit file name to cache size!
|
||||||
|
if (LFNIndex > MAX_LONGFILENAME_ENTRIES)
|
||||||
|
return ;
|
||||||
|
|
||||||
|
// This is an error condition
|
||||||
|
if (LFNIndex == 0)
|
||||||
|
return ;
|
||||||
|
|
||||||
|
if (lfn->no_of_strings == 0)
|
||||||
|
lfn->no_of_strings = LFNIndex;
|
||||||
|
|
||||||
|
lfn->String[LFNIndex-1][0] = entryBuffer[1];
|
||||||
|
lfn->String[LFNIndex-1][1] = entryBuffer[3];
|
||||||
|
lfn->String[LFNIndex-1][2] = entryBuffer[5];
|
||||||
|
lfn->String[LFNIndex-1][3] = entryBuffer[7];
|
||||||
|
lfn->String[LFNIndex-1][4] = entryBuffer[9];
|
||||||
|
lfn->String[LFNIndex-1][5] = entryBuffer[0x0E];
|
||||||
|
lfn->String[LFNIndex-1][6] = entryBuffer[0x10];
|
||||||
|
lfn->String[LFNIndex-1][7] = entryBuffer[0x12];
|
||||||
|
lfn->String[LFNIndex-1][8] = entryBuffer[0x14];
|
||||||
|
lfn->String[LFNIndex-1][9] = entryBuffer[0x16];
|
||||||
|
lfn->String[LFNIndex-1][10] = entryBuffer[0x18];
|
||||||
|
lfn->String[LFNIndex-1][11] = entryBuffer[0x1C];
|
||||||
|
lfn->String[LFNIndex-1][12] = entryBuffer[0x1E];
|
||||||
|
|
||||||
|
for (i=0; i<MAX_LFN_ENTRY_LENGTH; i++)
|
||||||
|
if (lfn->String[LFNIndex-1][i]==0xFF)
|
||||||
|
lfn->String[LFNIndex-1][i] = 0x20; // Replace with spaces
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// fatfs_lfn_cache_get: Get a reference to the long filename
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
#if FATFS_INC_LFN_SUPPORT
|
||||||
|
char* fatfs_lfn_cache_get(struct lfn_cache *lfn)
|
||||||
|
{
|
||||||
|
// Null terminate long filename
|
||||||
|
if (lfn->no_of_strings == MAX_LONGFILENAME_ENTRIES)
|
||||||
|
lfn->Null = '\0';
|
||||||
|
else if (lfn->no_of_strings)
|
||||||
|
lfn->String[lfn->no_of_strings][0] = '\0';
|
||||||
|
else
|
||||||
|
lfn->String[0][0] = '\0';
|
||||||
|
|
||||||
|
return (char*)&lfn->String[0][0];
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// fatfs_entry_lfn_text: If LFN text entry found
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
#if FATFS_INC_LFN_SUPPORT
|
||||||
|
int fatfs_entry_lfn_text(struct fat_dir_entry *entry)
|
||||||
|
{
|
||||||
|
if ((entry->Attr & FILE_ATTR_LFN_TEXT) == FILE_ATTR_LFN_TEXT)
|
||||||
|
return 1;
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// fatfs_entry_lfn_invalid: If SFN found not relating to LFN
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
#if FATFS_INC_LFN_SUPPORT
|
||||||
|
int fatfs_entry_lfn_invalid(struct fat_dir_entry *entry)
|
||||||
|
{
|
||||||
|
if ( (entry->Name[0]==FILE_HEADER_BLANK) ||
|
||||||
|
(entry->Name[0]==FILE_HEADER_DELETED)||
|
||||||
|
(entry->Attr==FILE_ATTR_VOLUME_ID) ||
|
||||||
|
(entry->Attr & FILE_ATTR_SYSHID) )
|
||||||
|
return 1;
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// fatfs_entry_lfn_exists: If LFN exists and correlation SFN found
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
#if FATFS_INC_LFN_SUPPORT
|
||||||
|
int fatfs_entry_lfn_exists(struct lfn_cache *lfn, struct fat_dir_entry *entry)
|
||||||
|
{
|
||||||
|
if ( (entry->Attr!=FILE_ATTR_LFN_TEXT) &&
|
||||||
|
(entry->Name[0]!=FILE_HEADER_BLANK) &&
|
||||||
|
(entry->Name[0]!=FILE_HEADER_DELETED) &&
|
||||||
|
(entry->Attr!=FILE_ATTR_VOLUME_ID) &&
|
||||||
|
(!(entry->Attr&FILE_ATTR_SYSHID)) &&
|
||||||
|
(lfn->no_of_strings) )
|
||||||
|
return 1;
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// fatfs_entry_sfn_only: If SFN only exists
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
int fatfs_entry_sfn_only(struct fat_dir_entry *entry)
|
||||||
|
{
|
||||||
|
if ( (entry->Attr!=FILE_ATTR_LFN_TEXT) &&
|
||||||
|
(entry->Name[0]!=FILE_HEADER_BLANK) &&
|
||||||
|
(entry->Name[0]!=FILE_HEADER_DELETED) &&
|
||||||
|
(entry->Attr!=FILE_ATTR_VOLUME_ID) &&
|
||||||
|
(!(entry->Attr&FILE_ATTR_SYSHID)) )
|
||||||
|
return 1;
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
// TODO: FILE_ATTR_SYSHID ?!?!??!
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// fatfs_entry_is_dir: Returns 1 if a directory
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
int fatfs_entry_is_dir(struct fat_dir_entry *entry)
|
||||||
|
{
|
||||||
|
if (entry->Attr & FILE_TYPE_DIR)
|
||||||
|
return 1;
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// fatfs_entry_is_file: Returns 1 is a file entry
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
int fatfs_entry_is_file(struct fat_dir_entry *entry)
|
||||||
|
{
|
||||||
|
if (entry->Attr & FILE_TYPE_FILE)
|
||||||
|
return 1;
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// fatfs_lfn_entries_required: Calculate number of 13 characters entries
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
#if FATFS_INC_LFN_SUPPORT
|
||||||
|
int fatfs_lfn_entries_required(char *filename)
|
||||||
|
{
|
||||||
|
int length = (int)strlen(filename);
|
||||||
|
|
||||||
|
if (length)
|
||||||
|
return (length + MAX_LFN_ENTRY_LENGTH - 1) / MAX_LFN_ENTRY_LENGTH;
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// fatfs_filename_to_lfn:
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
#if FATFS_INC_LFN_SUPPORT
|
||||||
|
void fatfs_filename_to_lfn(char *filename, uint8 *buffer, int entry, uint8 sfnChk)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
int nameIndexes[MAX_LFN_ENTRY_LENGTH] = {1,3,5,7,9,0x0E,0x10,0x12,0x14,0x16,0x18,0x1C,0x1E};
|
||||||
|
|
||||||
|
// 13 characters entries
|
||||||
|
int length = (int)strlen(filename);
|
||||||
|
int entriesRequired = fatfs_lfn_entries_required(filename);
|
||||||
|
|
||||||
|
// Filename offset
|
||||||
|
int start = entry * MAX_LFN_ENTRY_LENGTH;
|
||||||
|
|
||||||
|
// Initialise to zeros
|
||||||
|
memset(buffer, 0x00, FAT_DIR_ENTRY_SIZE);
|
||||||
|
|
||||||
|
// LFN entry number
|
||||||
|
buffer[0] = (uint8)(((entriesRequired-1)==entry)?(0x40|(entry+1)):(entry+1));
|
||||||
|
|
||||||
|
// LFN flag
|
||||||
|
buffer[11] = 0x0F;
|
||||||
|
|
||||||
|
// Checksum of short filename
|
||||||
|
buffer[13] = sfnChk;
|
||||||
|
|
||||||
|
// Copy to buffer
|
||||||
|
for (i=0;i<MAX_LFN_ENTRY_LENGTH;i++)
|
||||||
|
{
|
||||||
|
if ( (start+i) < length )
|
||||||
|
buffer[nameIndexes[i]] = filename[start+i];
|
||||||
|
else if ( (start+i) == length )
|
||||||
|
buffer[nameIndexes[i]] = 0x00;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
buffer[nameIndexes[i]] = 0xFF;
|
||||||
|
buffer[nameIndexes[i]+1] = 0xFF;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// fatfs_sfn_create_entry: Create the short filename directory entry
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
#if FATFS_INC_WRITE_SUPPORT
|
||||||
|
void fatfs_sfn_create_entry(char *shortfilename, uint32 size, uint32 startCluster, struct fat_dir_entry *entry, int dir)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
// Copy short filename
|
||||||
|
for (i=0;i<FAT_SFN_SIZE_FULL;i++)
|
||||||
|
entry->Name[i] = shortfilename[i];
|
||||||
|
|
||||||
|
// Unless we have a RTC we might as well set these to 1980
|
||||||
|
entry->CrtTimeTenth = 0x00;
|
||||||
|
entry->CrtTime[1] = entry->CrtTime[0] = 0x00;
|
||||||
|
entry->CrtDate[1] = 0x00;
|
||||||
|
entry->CrtDate[0] = 0x20;
|
||||||
|
entry->LstAccDate[1] = 0x00;
|
||||||
|
entry->LstAccDate[0] = 0x20;
|
||||||
|
entry->WrtTime[1] = entry->WrtTime[0] = 0x00;
|
||||||
|
entry->WrtDate[1] = 0x00;
|
||||||
|
entry->WrtDate[0] = 0x20;
|
||||||
|
|
||||||
|
if (!dir)
|
||||||
|
entry->Attr = FILE_TYPE_FILE;
|
||||||
|
else
|
||||||
|
entry->Attr = FILE_TYPE_DIR;
|
||||||
|
|
||||||
|
entry->NTRes = 0x00;
|
||||||
|
|
||||||
|
entry->FstClusHI = FAT_HTONS((uint16)((startCluster>>16) & 0xFFFF));
|
||||||
|
entry->FstClusLO = FAT_HTONS((uint16)((startCluster>>0) & 0xFFFF));
|
||||||
|
entry->FileSize = FAT_HTONL(size);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// fatfs_lfn_create_sfn: Create a padded SFN
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
#if FATFS_INC_WRITE_SUPPORT
|
||||||
|
int fatfs_lfn_create_sfn(char *sfn_output, char *filename)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
int dotPos = -1;
|
||||||
|
char ext[3];
|
||||||
|
int pos;
|
||||||
|
int len = (int)strlen(filename);
|
||||||
|
|
||||||
|
// Invalid to start with .
|
||||||
|
if (filename[0]=='.')
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
memset(sfn_output, ' ', FAT_SFN_SIZE_FULL);
|
||||||
|
memset(ext, ' ', 3);
|
||||||
|
|
||||||
|
// Find dot seperator
|
||||||
|
for (i = 0; i< len; i++)
|
||||||
|
{
|
||||||
|
if (filename[i]=='.')
|
||||||
|
dotPos = i;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Extract extensions
|
||||||
|
if (dotPos!=-1)
|
||||||
|
{
|
||||||
|
// Copy first three chars of extension
|
||||||
|
for (i = (dotPos+1); i < (dotPos+1+3); i++)
|
||||||
|
if (i<len)
|
||||||
|
ext[i-(dotPos+1)] = filename[i];
|
||||||
|
|
||||||
|
// Shorten the length to the dot position
|
||||||
|
len = dotPos;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add filename part
|
||||||
|
pos = 0;
|
||||||
|
for (i=0;i<len;i++)
|
||||||
|
{
|
||||||
|
if ( (filename[i]!=' ') && (filename[i]!='.') )
|
||||||
|
{
|
||||||
|
if (filename[i] >= 'a' && filename[i] <= 'z')
|
||||||
|
sfn_output[pos++] = filename[i] - 'a' + 'A';
|
||||||
|
else
|
||||||
|
sfn_output[pos++] = filename[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fill upto 8 characters
|
||||||
|
if (pos==FAT_SFN_SIZE_PARTIAL)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add extension part
|
||||||
|
for (i=FAT_SFN_SIZE_PARTIAL;i<FAT_SFN_SIZE_FULL;i++)
|
||||||
|
{
|
||||||
|
if (ext[i-FAT_SFN_SIZE_PARTIAL] >= 'a' && ext[i-FAT_SFN_SIZE_PARTIAL] <= 'z')
|
||||||
|
sfn_output[i] = ext[i-FAT_SFN_SIZE_PARTIAL] - 'a' + 'A';
|
||||||
|
else
|
||||||
|
sfn_output[i] = ext[i-FAT_SFN_SIZE_PARTIAL];
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// fatfs_itoa:
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
static void fatfs_itoa(uint32 num, char *s)
|
||||||
|
{
|
||||||
|
char* cp;
|
||||||
|
char outbuf[12];
|
||||||
|
const char digits[] = "0123456789ABCDEF";
|
||||||
|
|
||||||
|
// Build string backwards
|
||||||
|
cp = outbuf;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
*cp++ = digits[(int)(num % 10)];
|
||||||
|
}
|
||||||
|
while ((num /= 10) > 0);
|
||||||
|
|
||||||
|
*cp-- = 0;
|
||||||
|
|
||||||
|
// Copy in forwards
|
||||||
|
while (cp >= outbuf)
|
||||||
|
*s++ = *cp--;
|
||||||
|
|
||||||
|
*s = 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// fatfs_lfn_generate_tail:
|
||||||
|
// sfn_input = Input short filename, spaced format & in upper case
|
||||||
|
// sfn_output = Output short filename with tail
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
#if FATFS_INC_LFN_SUPPORT
|
||||||
|
#if FATFS_INC_WRITE_SUPPORT
|
||||||
|
int fatfs_lfn_generate_tail(char *sfn_output, char *sfn_input, uint32 tailNum)
|
||||||
|
{
|
||||||
|
int tail_chars;
|
||||||
|
char tail_str[12];
|
||||||
|
|
||||||
|
if (tailNum > 99999)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
// Convert to number
|
||||||
|
memset(tail_str, 0x00, sizeof(tail_str));
|
||||||
|
tail_str[0] = '~';
|
||||||
|
fatfs_itoa(tailNum, tail_str+1);
|
||||||
|
|
||||||
|
// Copy in base filename
|
||||||
|
memcpy(sfn_output, sfn_input, FAT_SFN_SIZE_FULL);
|
||||||
|
|
||||||
|
// Overwrite with tail
|
||||||
|
tail_chars = (int)strlen(tail_str);
|
||||||
|
memcpy(sfn_output+(FAT_SFN_SIZE_PARTIAL-tail_chars), tail_str, tail_chars);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// fatfs_convert_from_fat_time: Convert FAT time to h/m/s
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
#if FATFS_INC_TIME_DATE_SUPPORT
|
||||||
|
void fatfs_convert_from_fat_time(uint16 fat_time, int *hours, int *minutes, int *seconds)
|
||||||
|
{
|
||||||
|
*hours = (fat_time >> FAT_TIME_HOURS_SHIFT) & FAT_TIME_HOURS_MASK;
|
||||||
|
*minutes = (fat_time >> FAT_TIME_MINUTES_SHIFT) & FAT_TIME_MINUTES_MASK;
|
||||||
|
*seconds = (fat_time >> FAT_TIME_SECONDS_SHIFT) & FAT_TIME_SECONDS_MASK;
|
||||||
|
*seconds = *seconds * FAT_TIME_SECONDS_SCALE;
|
||||||
|
}
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// fatfs_convert_from_fat_date: Convert FAT date to d/m/y
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
void fatfs_convert_from_fat_date(uint16 fat_date, int *day, int *month, int *year)
|
||||||
|
{
|
||||||
|
*day = (fat_date >> FAT_DATE_DAY_SHIFT) & FAT_DATE_DAY_MASK;
|
||||||
|
*month = (fat_date >> FAT_DATE_MONTH_SHIFT) & FAT_DATE_MONTH_MASK;
|
||||||
|
*year = (fat_date >> FAT_DATE_YEAR_SHIFT) & FAT_DATE_YEAR_MASK;
|
||||||
|
*year = *year + FAT_DATE_YEAR_OFFSET;
|
||||||
|
}
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// fatfs_convert_to_fat_time: Convert h/m/s to FAT time
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
uint16 fatfs_convert_to_fat_time(int hours, int minutes, int seconds)
|
||||||
|
{
|
||||||
|
uint16 fat_time = 0;
|
||||||
|
|
||||||
|
// Most FAT times are to a resolution of 2 seconds
|
||||||
|
seconds /= FAT_TIME_SECONDS_SCALE;
|
||||||
|
|
||||||
|
fat_time = (hours & FAT_TIME_HOURS_MASK) << FAT_TIME_HOURS_SHIFT;
|
||||||
|
fat_time|= (minutes & FAT_TIME_MINUTES_MASK) << FAT_TIME_MINUTES_SHIFT;
|
||||||
|
fat_time|= (seconds & FAT_TIME_SECONDS_MASK) << FAT_TIME_SECONDS_SHIFT;
|
||||||
|
|
||||||
|
return fat_time;
|
||||||
|
}
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// fatfs_convert_to_fat_date: Convert d/m/y to FAT date
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
uint16 fatfs_convert_to_fat_date(int day, int month, int year)
|
||||||
|
{
|
||||||
|
uint16 fat_date = 0;
|
||||||
|
|
||||||
|
// FAT dates are relative to 1980
|
||||||
|
if (year >= FAT_DATE_YEAR_OFFSET)
|
||||||
|
year -= FAT_DATE_YEAR_OFFSET;
|
||||||
|
|
||||||
|
fat_date = (day & FAT_DATE_DAY_MASK) << FAT_DATE_DAY_SHIFT;
|
||||||
|
fat_date|= (month & FAT_DATE_MONTH_MASK) << FAT_DATE_MONTH_SHIFT;
|
||||||
|
fat_date|= (year & FAT_DATE_YEAR_MASK) << FAT_DATE_YEAR_SHIFT;
|
||||||
|
|
||||||
|
return fat_date;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// fatfs_print_sector:
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
#ifdef FATFS_DEBUG
|
||||||
|
void fatfs_print_sector(uint32 sector, uint8 *data)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
int j;
|
||||||
|
|
||||||
|
FAT_PRINTF(("Sector %d:\n", sector));
|
||||||
|
|
||||||
|
for (i=0;i<FAT_SECTOR_SIZE;i++)
|
||||||
|
{
|
||||||
|
if (!((i) % 16))
|
||||||
|
{
|
||||||
|
FAT_PRINTF((" %04d: ", i));
|
||||||
|
}
|
||||||
|
|
||||||
|
FAT_PRINTF(("%02x", data[i]));
|
||||||
|
if (!((i+1) % 4))
|
||||||
|
{
|
||||||
|
FAT_PRINTF((" "));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!((i+1) % 16))
|
||||||
|
{
|
||||||
|
FAT_PRINTF((" "));
|
||||||
|
for (j=0;j<16;j++)
|
||||||
|
{
|
||||||
|
char ch = data[i-15+j];
|
||||||
|
|
||||||
|
// Is printable?
|
||||||
|
if (ch > 31 && ch < 127)
|
||||||
|
{
|
||||||
|
FAT_PRINTF(("%c", ch));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
FAT_PRINTF(("."));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
FAT_PRINTF(("\n"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
63
kernel/fs/fatfs/fat_misc.h
Normal file
63
kernel/fs/fatfs/fat_misc.h
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
#ifndef __FAT_MISC_H__
|
||||||
|
#define __FAT_MISC_H__
|
||||||
|
|
||||||
|
#include "fat_defs.h"
|
||||||
|
#include "fat_opts.h"
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Defines
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
#define MAX_LONGFILENAME_ENTRIES 20
|
||||||
|
#define MAX_LFN_ENTRY_LENGTH 13
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Macros
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
#define GET_32BIT_WORD(buffer, location) ( ((uint32)buffer[location+3]<<24) + ((uint32)buffer[location+2]<<16) + ((uint32)buffer[location+1]<<8) + (uint32)buffer[location+0] )
|
||||||
|
#define GET_16BIT_WORD(buffer, location) ( ((uint16)buffer[location+1]<<8) + (uint16)buffer[location+0] )
|
||||||
|
|
||||||
|
#define SET_32BIT_WORD(buffer, location, value) { buffer[location+0] = (uint8)((value)&0xFF); \
|
||||||
|
buffer[location+1] = (uint8)((value>>8)&0xFF); \
|
||||||
|
buffer[location+2] = (uint8)((value>>16)&0xFF); \
|
||||||
|
buffer[location+3] = (uint8)((value>>24)&0xFF); }
|
||||||
|
|
||||||
|
#define SET_16BIT_WORD(buffer, location, value) { buffer[location+0] = (uint8)((value)&0xFF); \
|
||||||
|
buffer[location+1] = (uint8)((value>>8)&0xFF); }
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Structures
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
struct lfn_cache
|
||||||
|
{
|
||||||
|
#if FATFS_INC_LFN_SUPPORT
|
||||||
|
// Long File Name Structure (max 260 LFN length)
|
||||||
|
uint8 String[MAX_LONGFILENAME_ENTRIES][MAX_LFN_ENTRY_LENGTH];
|
||||||
|
uint8 Null;
|
||||||
|
#endif
|
||||||
|
uint8 no_of_strings;
|
||||||
|
};
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Prototypes
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
void fatfs_lfn_cache_init(struct lfn_cache *lfn, int wipeTable);
|
||||||
|
void fatfs_lfn_cache_entry(struct lfn_cache *lfn, uint8 *entryBuffer);
|
||||||
|
char* fatfs_lfn_cache_get(struct lfn_cache *lfn);
|
||||||
|
int fatfs_entry_lfn_text(struct fat_dir_entry *entry);
|
||||||
|
int fatfs_entry_lfn_invalid(struct fat_dir_entry *entry);
|
||||||
|
int fatfs_entry_lfn_exists(struct lfn_cache *lfn, struct fat_dir_entry *entry);
|
||||||
|
int fatfs_entry_sfn_only(struct fat_dir_entry *entry);
|
||||||
|
int fatfs_entry_is_dir(struct fat_dir_entry *entry);
|
||||||
|
int fatfs_entry_is_file(struct fat_dir_entry *entry);
|
||||||
|
int fatfs_lfn_entries_required(char *filename);
|
||||||
|
void fatfs_filename_to_lfn(char *filename, uint8 *buffer, int entry, uint8 sfnChk);
|
||||||
|
void fatfs_sfn_create_entry(char *shortfilename, uint32 size, uint32 startCluster, struct fat_dir_entry *entry, int dir);
|
||||||
|
int fatfs_lfn_create_sfn(char *sfn_output, char *filename);
|
||||||
|
int fatfs_lfn_generate_tail(char *sfn_output, char *sfn_input, uint32 tailNum);
|
||||||
|
void fatfs_convert_from_fat_time(uint16 fat_time, int *hours, int *minutes, int *seconds);
|
||||||
|
void fatfs_convert_from_fat_date(uint16 fat_date, int *day, int *month, int *year);
|
||||||
|
uint16 fatfs_convert_to_fat_time(int hours, int minutes, int seconds);
|
||||||
|
uint16 fatfs_convert_to_fat_date(int day, int month, int year);
|
||||||
|
void fatfs_print_sector(uint32 sector, uint8 *data);
|
||||||
|
|
||||||
|
#endif
|
||||||
90
kernel/fs/fatfs/fat_opts.h
Normal file
90
kernel/fs/fatfs/fat_opts.h
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
#ifndef __FAT_OPTS_H__
|
||||||
|
#define __FAT_OPTS_H__
|
||||||
|
|
||||||
|
#ifdef FATFS_USE_CUSTOM_OPTS_FILE
|
||||||
|
#include "fat_custom.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//-------------------------------------------------------------
|
||||||
|
// Configuration
|
||||||
|
//-------------------------------------------------------------
|
||||||
|
|
||||||
|
// Is the processor little endian (1) or big endian (0)
|
||||||
|
#ifndef FATFS_IS_LITTLE_ENDIAN
|
||||||
|
#define FATFS_IS_LITTLE_ENDIAN 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Max filename Length
|
||||||
|
#ifndef FATFS_MAX_LONG_FILENAME
|
||||||
|
#define FATFS_MAX_LONG_FILENAME 260
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Max open files (reduce to lower memory requirements)
|
||||||
|
#ifndef FATFS_MAX_OPEN_FILES
|
||||||
|
#define FATFS_MAX_OPEN_FILES 2
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Number of sectors per FAT_BUFFER (min 1)
|
||||||
|
#ifndef FAT_BUFFER_SECTORS
|
||||||
|
#define FAT_BUFFER_SECTORS 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Max FAT sectors to buffer (min 1)
|
||||||
|
// (mem used is FAT_BUFFERS * FAT_BUFFER_SECTORS * FAT_SECTOR_SIZE)
|
||||||
|
#ifndef FAT_BUFFERS
|
||||||
|
#define FAT_BUFFERS 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Size of cluster chain cache (can be undefined)
|
||||||
|
// Mem used = FAT_CLUSTER_CACHE_ENTRIES * 4 * 2
|
||||||
|
// Improves access speed considerably
|
||||||
|
//#define FAT_CLUSTER_CACHE_ENTRIES 128
|
||||||
|
|
||||||
|
// Include support for writing files (1 / 0)?
|
||||||
|
#ifndef FATFS_INC_WRITE_SUPPORT
|
||||||
|
#define FATFS_INC_WRITE_SUPPORT 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Support long filenames (1 / 0)?
|
||||||
|
// (if not (0) only 8.3 format is supported)
|
||||||
|
#ifndef FATFS_INC_LFN_SUPPORT
|
||||||
|
#define FATFS_INC_LFN_SUPPORT 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Support directory listing (1 / 0)?
|
||||||
|
#ifndef FATFS_DIR_LIST_SUPPORT
|
||||||
|
#define FATFS_DIR_LIST_SUPPORT 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Support time/date (1 / 0)?
|
||||||
|
#ifndef FATFS_INC_TIME_DATE_SUPPORT
|
||||||
|
#define FATFS_INC_TIME_DATE_SUPPORT 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Include support for formatting disks (1 / 0)?
|
||||||
|
#ifndef FATFS_INC_FORMAT_SUPPORT
|
||||||
|
#define FATFS_INC_FORMAT_SUPPORT 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Sector size used
|
||||||
|
#define FAT_SECTOR_SIZE 512
|
||||||
|
|
||||||
|
// Printf output (directory listing / debug)
|
||||||
|
#ifndef FAT_PRINTF
|
||||||
|
// Don't include stdio, but there is a printf function available
|
||||||
|
#ifdef FAT_PRINTF_NOINC_STDIO
|
||||||
|
extern int printf(const char* ctrl1, ... );
|
||||||
|
#define FAT_PRINTF(a) printf a
|
||||||
|
// Include stdio to use printf
|
||||||
|
#else
|
||||||
|
#include <stdio.h>
|
||||||
|
#define FAT_PRINTF(a) printf a
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Time/Date support requires time.h
|
||||||
|
#if FATFS_INC_TIME_DATE_SUPPORT
|
||||||
|
#include <time.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user