Giter VIP home page Giter VIP logo

hpk's Introduction

HPK Archiver for Haemimont Engine game files

Crates.io Rust version Actions build status Downloads

Supported games

  • Tropico 3-5
  • The First Templar
  • Omerta: City of Gangsters
  • Grand Ages: Rome
  • Victor Vran
  • Surviving Mars

Overview

  1. Compatibility Notes
    1. Game Scripting
  2. Building
  3. Installation
  4. Usage
    1. hpk help
    2. hpk list
    3. hpk create
    4. hpk extract
    5. hpk debug-print
  5. HPK File Format

Compatibility Notes

Surviving Mars hangs when hpk files in the DLC folder contain compressed files. Use the --dont-compress-files option when creating files.

Game Scripting

Haeminont uses Lua for scripting their games. The scripts contain only the compiled Lua bytecode and have to be decompiled with unluac or luadec to get the source code. With Victor Vran they switched from Lua 5.1 to 5.3 but the bytecode headers are missing two bytes to make it possible to decompile the scripts.

Victor Vran's Lua Bytecode Header
Broken 1B4C 7561 5300 1993 0D0A 1A0A 0404 ____ 0878 5600 ...
Valid 1B4C 7561 5300 1993 0D0A 1A0A 0404 0404 0878 5600 ...
Surviving Mars' Lua Bytecode Header
Broken 1B4C 7561 5300 1993 0D0A 1A0A 0404 ____ 0878 5600 ...
Valid 1B4C 7561 5300 1993 0D0A 1A0A 0404 0408 0878 5600 ...

Use hpk extract --fix-lua-files ... to fix the scripts on extraction.
Use hpk create --cripple-lua-files ... to change the bytecode header of the compiled lua scripts on repacking. The game can also load plain Lua files instead of a compiled version if you run into any problems.

Building

hpk is written in Rust, so you'll need to grab a Rust installation in order to compile it. Building is easy:

$ git clone https://github.com/nickelc/hpk
$ cd hpk
$ cargo build --release
$ ./target/release/hpk --version
hpk 0.3.0

Installation

Cargo

$ cargo install hpk

Windows

Use the GitHub Releases tab to obtain the binary.

Usage

hpk help

$ hpk help
HPK archiver for Haemimont Engine game files (Tropico 3-5, Omerta, Victor Vran, Surviving Mars etc.)

Usage: hpk <COMMAND>

Commands:
  create       Create a new hpk archive
  extract      Extract files from a hpk archive
  list         List the content of a hpk archive
  debug-print  Print debug information of a hpk archive
  help         Print this message or the help of the given subcommand(s)

Options:
  -h, --help     Print help
  -V, --version  Print version

https://github.com/nickelc/hpk

hpk list

$ hpk list files/omerta/Packs/TextureLists.hpk
entities.lst
fallback.lst
fx.lst
misc.lst
sky.lst
terrains.lst
water.lst

hpk create

$ hpk create -h
Create a new hpk archive

Usage: hpk create [OPTIONS] <dir> <file>

Arguments:
  <dir>   input directory
  <file>  hpk output file

Options:
      --compress
          Compress the whole hpk file
      --chunk-size <SIZE>
          Default chunk size: 32768
      --cripple-lua-files
          Cripple bytecode header for Victor Vran or Surviving Mars
      --with-filedates
          Stores the last modification times in a _filedates file
      --filedate-fmt <FORMAT>
          Specifies the format of the stored filedates.

          default: 'Windows file time' used by Tropico 3 and Grand Ages: Rome
          short: 'Windows file time / 2000' used by Tropico 4 and Omerta
      --dont-compress-files
          No files are compressed. Overrides `--extensions`
      --extensions <EXT>...
          Specifies the file extensions to be compressed. default: [lst,lua,xml,tga,dds,xtex,bin,csv]
      --lz4
          Sets LZ4 as encoder
  -h, --help
          Print help (see more with '--help')

hpk extract

$ hg extract -h
Extract files from a hpk archive

Usage: hpk extract [OPTIONS] <file> <dest> [paths]...

Arguments:
  <file>      hpk archive
  <dest>      destination folder
  [paths]...  An optional list of archive members to be processed, separated by spaces.

Options:
      --ignore-filedates  Skip processing of a _filedates file and just extract it
      --fix-lua-files     Fix the bytecode header of Victor Vran's or Surviving Mars' Lua files
      --force             Force extraction if destination folder is not empty
  -v                      Verbosely list files processed
  -h, --help              Print help

hpk debug-print

$ hpk debug-print files/omerta/Packs/TextureLists.hpk
reading file: files/omerta/Packs/TextureLists.hpk
header:
  data_offset: 0x24
  fragments_residual_offset: 0x0
  fragments_residual_count: 0
  fragments_per_file: 1
  fragments_filesystem_offset: 0x1459
  fragments_filesystem_length: 64
filesystem entries: 8
filesystem fragments:
  0x13D1   len: 136
  0x24     len: 3876
  0xF48    len: 278
  0x105E   len: 82
  0x10B0   len: 134
  0x1136   len: 140
  0x11C2   len: 304
  0x12F2   len: 223
dir:  index=1 depth=0 ""
 fragment: 0x13D1 len: 136
file: index=2 depth=1 "entities.lst"
 fragment: 0x24 len: 3876
 compressed: ZLIB inflated_length=30917 chunk_size=32768 chunks=1
  chunks: 0x10     len: 3860
file: index=3 depth=1 "fallback.lst"
 fragment: 0xF48 len: 278
 compressed: ZLIB inflated_length=2956 chunk_size=32768 chunks=1
  chunks: 0x10     len: 262
file: index=4 depth=1 "fx.lst"
 fragment: 0x105E len: 82
 compressed: ZLIB inflated_length=290 chunk_size=32768 chunks=1
  chunks: 0x10     len: 66
file: index=5 depth=1 "misc.lst"
 fragment: 0x10B0 len: 134
 compressed: ZLIB inflated_length=344 chunk_size=32768 chunks=1
  chunks: 0x10     len: 118
file: index=6 depth=1 "sky.lst"
 fragment: 0x1136 len: 140
 compressed: ZLIB inflated_length=536 chunk_size=32768 chunks=1
  chunks: 0x10     len: 124
file: index=7 depth=1 "terrains.lst"
 fragment: 0x11C2 len: 304
 compressed: ZLIB inflated_length=2268 chunk_size=32768 chunks=1
  chunks: 0x10     len: 288
file: index=8 depth=1 "water.lst"
 fragment: 0x12F2 len: 223
 compressed: ZLIB inflated_length=1978 chunk_size=32768 chunks=1
  chunks: 0x10     len: 207

HPK File Format

Header

Offset Size Value
0 4 Magic number; 0x4C555042 ("BPUL")
4 4 Data offset; 0x24 (36)
8 4 Number of fragments per file; 1, 8
12 4 Unknown; 0xFFFFFFFF
16 4 Offset of the residual fragments in bytes
20 4 Number of residual fragments
24 4 Unknown; 0x1
28 4 Offset of the filesystem fragments in bytes
32 4 Size of the filesystem fragments in bytes

Fragment (Filesystem & Residual)

  • Offsets of fragments are relative from the start of the file.
  • The first filesystem fragment is the root directory.
Offset Size Value
0 4 Offset of a fragment in bytes
4 4 Size of a fragment in bytes

Filesystem Entry: Directory

Offset Size Value
0 4 Fragment Index; Index starts with 1
4 4 Entry Type; File=0x0 Dir=0x1
8 2 Size of the following name in bytes
10 ? Name data

Fragmented File (zlib/lz4/zstd compressed)

Offsets of compressed chunks are relative from the start of a fragment.
Victor Vran (Steam version) and Surviving Mars use LZ4 as compression.
ZSTD is used by Surviving Mars's mod editor.
The challenge hpks of Tropico 5 are compressed like a fragmented file.

Offset Size Value
0 4 Magic number, 0x42494C5A ("ZLIB")
0x20345A4C ("LZ4 ")
0x4454535A ("ZSTD")
4 4 Size of the inflated data in bytes
8 4 Inflated chunk size, 0x0800 (32768)
12 4 Chunk offset in bytes, 0x10 for one chunk
* 4 Additional chunk offsets (optional)

_filedates File

HPK files can contain a _filedates file with the last modification times of the files and directories.
Each line consists of a path and a file time, separated by equals signs.

path/to/file=value
path/to/folder=value

Path is the basic path to the file but for Grand Ages: Rome the actual path is prefixed by
the basename of the original HPK file (Shaders.hpk "Shaders/Shaders/VertexAnim.fx").
Value is either the Windows file time ("default") or the Windows file time divided by 2000 ("short").

Format Games
default Grand Ages: Rome, Tropico 3
short Tropico 4, Omerta

hpk's People

Contributors

nickelc avatar zocker-160 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

hpk's Issues

Support _filedates file

  • Set last modification date from _filedates file on extraction on windows and linux. (detect Tropico 4/5)
  • Generate _filedates file and add option to select the date format on creation.

Jagged Alliance 3 hpk archiving issue

Hi! Thank you for providing hpk unpacker/archiver for Haemimont Engine game files.
I'm currently having a problem when archiving hpk files for localization (Korean language, edited from unpacked Tchinese.hpk file) fonts are missing in-game.

missing fonts in rearchived Tchinese hpk

I first assumed it was font issue, but when I archived the unpacked Tchinese.hpk file without editing, and tested it in-game, same issue occurred.

Following is the link to 1)original Tchinese.hpk file, 2)rearchived Tchinese.hpk file from unpacked files

  1. https://drive.google.com/file/d/1Vmq7td4Qf1E8_2nr_5ciQzGiaOwMTzPW/view?usp=drive_link
  2. https://drive.google.com/file/d/1Ju7h_da_W3UxvuupDLty7YdXxQu3uXYn/view?usp=drive_link

Could it be that I'm somehow doing the archiving process not properly? I've made sure when archiving, the directory order remained same (Tchinese/CurrentLanguage/Game.csv) and used bat file with command line .\hpk.exe create Tchinese Tchinese.hpk

This does not properly extract Surviving Mars files

when extracting the Surviving Mars .hpk files it appears to work correctly, but if you open any of the resulting files they aren't valid. For example if you open a .Lua file the text is unreadable. If you attempt to open a .tga it is not recognized as a valid picture file.

I downloaded this and ran it fresh today just to verify.

Repacked `.hpk` does not work in Surviving Mars (loads forever)

When extracting armstrong.hpk and packing it again, the game refuses to load into the menu.

Looking at your file format specifications, it seems like something weird is going on:

The original file does have the data of the first file right after the one BPUL header starting at 0x24.
The newly created file though does contain two BPUL headers and then the data for the first file, which then starts later (0x48 I guess?)

here the first 200 bytes of each file:

original

4250554C2400000001000000FFFFFFFF000000000000000001000000CA267A0448050000444B4946000020005650383080073804905F0100010000000000000000000080C80D0000000000000000000030B7019D012A80073804004708858588858488020200061604F70681649F6BDB9B27387B27387B27387B27387B27387B27387B27387B27387B27387B27387B27387B27387B27387B27387B27387B27387B27387B27387B27387B27387B27387B27387B27387B27387B27387B27387B27387B27387B27387B

repacked

4250554C2400000001000000FF0000000000000000000000010000006EB07204480500004250554C2400000001000000FFFFFFFF0000000000000000010000008E763000580000004C5A34200E000000000002001000000072657475726E20313031303738324C5A34208E250A000000020024000000D36200003EB60000BA130100C06F010045D40100FF16734200000014000000456E7469746965732F41636164656D792E656E740D0A4D35000000181F000042446F6F7223006FF7310000002023000050466C

Also I noticed that the first header in the repacked archive does have 0x000000FF instead of 0xFFFFFFFF.

Any idea where this difference comes from and if that could be the cause of the problem?

EDIT:
when running it from terminal, the game seems to crash at loading the DLCs, which this file is part of.

.local\share\Steam\steamapps\common\Surviving Mars\CommonLua\Dlc.lua(702): field LoadDlcs
[string ""](-1):  <>
        --- end of stack

EDIT2:
I also noticed, that there is a size difference between the original and the repacked file (the bak is the original one):
Screenshot_20220104_213835

Inject file into package

Is there a command line sequence to allow me to inject files in a hpk package giving the path within the package?

Example Jagged Alliance 3 -

Say we have a folder C:\something\UI\Mercs unpacked from UI.hpk. I modify the files in \Mercs. I then have a couple of files, and I know their paths. Can I skip repacking the folder?

Down the line I want to create a bat to inject a selection of files into UI.hpk and distribute it with the modified files, but only the modified files. Is there a way to inject files with the .bat or do I have to run commands to unpack, overwrite and repack.

I looked through your documentation but I'm stuck.

SIGSEGV: invalid memory reference while cargo build --release

I'm completely new to rust language and sorry for my weak English, so here is the last output:

$ cargo build --release
   Compiling hpk v0.3.4 (/opt/git/hpk)
error: Could not compile `hpk`.

Caused by:
  process didn't exit successfully: `rustc --edition=2018 --crate-name hpk src/main.rs
  --color always --crate-type bin --emit=dep-info,link -C opt-level=3 -C lto -C
  metadata=efda9f278588f912 -C extra-filename=-efda9f278588f912 --out-dir
  /opt/git/hpk/target/release/deps -L dependency=/opt/git/hpk/target/release/deps --extern
  byteorder=/opt/git/hpk/target/release/deps/libbyteorder-8396a9ff3ced34b0.rlib --extern
  clap=/opt/git/hpk/target/release/deps/libclap-6282fbebe1e3647f.rlib --extern
  filetime=/opt/git/hpk/target/release/deps/libfiletime-0206700f28040b46.rlib --extern
  flate2=/opt/git/hpk/target/release/deps/libflate2-cc230f0d2bf00371.rlib --extern
  glob=/opt/git/hpk/target/release/deps/libglob-e086e0d80c192087.rlib --extern
  hpk=/opt/git/hpk/target/release/deps/libhpk-edf78b3620d574a2.rlib --extern
  lz4_compress=/opt/git/hpk/target/release/deps/liblz4_compress-cb84362fc1ac9e99.rlib
  --extern nom=/opt/git/hpk/target/release/deps/libnom-2fb83814f174885f.rlib --extern
  tempfile=/opt/git/hpk/target/release/deps/libtempfile-97e1e08034b9fee1.rlib --extern
  walkdir=/opt/git/hpk/target/release/deps/libwalkdir-f5079254e823656c.rlib --extern
  zstd=/opt/git/hpk/target/release/deps/libzstd-782b431503605148.rlib -L
  native=/opt/git/hpk/target/release/build/miniz-sys-71c32bff269ebcb6/out -L
  native=/opt/git/hpk/target/release/build/zstd-sys-ab6ec32720866ff2/out`
  (signal: 11, SIGSEGV: invalid memory reference)
$ 

rustc --version: 1.32.0
Linux AMD64 under Debian 7.3.0

error: Could not compile `hpk`

what can i do?
pls check my terminal output:

Compiling hpk v0.3.2 (/home/grinsel/Downloads/hpk)
error: Edition 2018 is unstable and only available for nightly builds of rustc.

error: Could not compile hpk.

To learn more, run the command again with --verbose.
grinsel@ding:~/Downloads/hpk$ cargo build --verbose

Compiling hpk v0.3.2 (/home/grinsel/Downloads/hpk)
Running rustc --edition=2018 --crate-name hpk src/hpk/mod.rs --color always --crate-type lib --emit=dep-info,link -C debuginfo=2 -C metadata=d9d205de6e274196 -C extra-filename=-d9d205de6e274196 --out-dir /home/grinsel/Downloads/hpk/target/debug/deps -C incremental=/home/grinsel/Downloads/hpk/target/debug/incremental -L dependency=/home/grinsel/Downloads/hpk/target/debug/deps --extern byteorder=/home/grinsel/Downloads/hpk/target/debug/deps/libbyteorder-988a048c1905d79a.rlib --extern clap=/home/grinsel/Downloads/hpk/target/debug/deps/libclap-1dd52620fc331773.rlib --extern filetime=/home/grinsel/Downloads/hpk/target/debug/deps/libfiletime-3cd8e69c8d1e50d4.rlib --extern flate2=/home/grinsel/Downloads/hpk/target/debug/deps/libflate2-a4dcf890805f6092.rlib --extern glob=/home/grinsel/Downloads/hpk/target/debug/deps/libglob-dfc6ffbad95a9e84.rlib --extern lz4_compress=/home/grinsel/Downloads/hpk/target/debug/deps/liblz4_compress-431422beb68ecad0.rlib --extern nom=/home/grinsel/Downloads/hpk/target/debug/deps/libnom-6b160a556ef528ca.rlib --extern tempfile=/home/grinsel/Downloads/hpk/target/debug/deps/libtempfile-5a6b6bc7620967b1.rlib --extern walkdir=/home/grinsel/Downloads/hpk/target/debug/deps/libwalkdir-4ad7e55a77bda48b.rlib --extern zstd=/home/grinsel/Downloads/hpk/target/debug/deps/libzstd-0fef2881ee8dcbd5.rlib -L native=/home/grinsel/Downloads/hpk/target/debug/build/miniz-sys-24ade8073a23fac7/out -L native=/home/grinsel/Downloads/hpk/target/debug/build/zstd-sys-e586e6dfbfa0abf4/out
error: Edition 2018 is unstable and only available for nightly builds of rustc.

error: Could not compile hpk.

Caused by:
process didn't exit successfully: rustc --edition=2018 --crate-name hpk src/hpk/mod.rs --color always --crate-type lib --emit=dep-info,link -C debuginfo=2 -C metadata=d9d205de6e274196 -C extra-filename=-d9d205de6e274196 --out-dir /home/grinsel/Downloads/hpk/target/debug/deps -C incremental=/home/grinsel/Downloads/hpk/target/debug/incremental -L dependency=/home/grinsel/Downloads/hpk/target/debug/deps --extern byteorder=/home/grinsel/Downloads/hpk/target/debug/deps/libbyteorder-988a048c1905d79a.rlib --extern clap=/home/grinsel/Downloads/hpk/target/debug/deps/libclap-1dd52620fc331773.rlib --extern filetime=/home/grinsel/Downloads/hpk/target/debug/deps/libfiletime-3cd8e69c8d1e50d4.rlib --extern flate2=/home/grinsel/Downloads/hpk/target/debug/deps/libflate2-a4dcf890805f6092.rlib --extern glob=/home/grinsel/Downloads/hpk/target/debug/deps/libglob-dfc6ffbad95a9e84.rlib --extern lz4_compress=/home/grinsel/Downloads/hpk/target/debug/deps/liblz4_compress-431422beb68ecad0.rlib --extern nom=/home/grinsel/Downloads/hpk/target/debug/deps/libnom-6b160a556ef528ca.rlib --extern tempfile=/home/grinsel/Downloads/hpk/target/debug/deps/libtempfile-5a6b6bc7620967b1.rlib --extern walkdir=/home/grinsel/Downloads/hpk/target/debug/deps/libwalkdir-4ad7e55a77bda48b.rlib --extern zstd=/home/grinsel/Downloads/hpk/target/debug/deps/libzstd-0fef2881ee8dcbd5.rlib -L native=/home/grinsel/Downloads/hpk/target/debug/build/miniz-sys-24ade8073a23fac7/out -L native=/home/grinsel/Downloads/hpk/target/debug/build/zstd-sys-e586e6dfbfa0abf4/out (exit code: 1)

Access denied

Hello. I've decided to localize the new game Stranded: Alien Dawn.
But I ran into a problem (maybe I'm too dumb).
Unpacking proceeds normally, everything is decoded correctly.
However, I can't pack it back.
An access denied error pops up. What am I doing wrong?

d:\Works\Tools\hpk-v0.3.9-x86_64-pc-windows-msvc>hpk print "E:\SteamLibrary\steamapps\common\Stranded Alien Dawn\Local\English.hpk"
reading file: E:\SteamLibrary\steamapps\common\Stranded Alien Dawn\Local\English.hpk
header:
  data_offset: 0x24
  fragments_residual_offset: 0x0
  fragments_residual_count: 0
  fragments_per_file: 1
  fragments_filesystem_offset: 0x5E138
  fragments_filesystem_length: 24
filesystem entries: 3
filesystem fragments:
  0x5E11F  len: 25
  0x5E10D  len: 18
  0x24     len: 385257
dir:  index=1 depth=0 ""
 fragment: 0x5E11F len: 25
dir:  index=2 depth=1 "CurrentLanguage"
 fragment: 0x5E10D len: 18
file: index=3 depth=2 "CurrentLanguage\\Game.csv"
 fragment: 0x24 len: 385257
 compressed: ZSTD inflated_length=1989815 chunk_size=131072 chunks=16
  chunks: 0x4C     len: 29351
          0x72F3   len: 27035
          0xDC8E   len: 26581
          0x14463  len: 25720
          0x1A8DB  len: 26760
          0x21163  len: 23628
          0x26DAF  len: 20872
          0x2BF37  len: 28986
          0x33071  len: 29952
          0x3A571  len: 26444
          0x40CBD  len: 17184
          0x44FDD  len: 21604
          0x4A441  len: 25649
          0x50872  len: 25496
          0x56C0A  len: 25503
          0x5CFA9  len: 4416

Error message

d:\Works\Tools\hpk-v0.3.9-x86_64-pc-windows-msvc>hpk create D:\Works\Tools\hpk-v0.3.9-x86_64-pc-windows-msvc\pack D:\Works\Tools\hpk-v0.3.9-x86_64-pc-windows-msvc\extracted
Error: Hpk(Io(Os { code: 5, kind: PermissionDenied, message: "Access denied." }))

Here is the archive with localization English.zip

Help with offsets

I am trying to use hpk to mod Imperium Civitas (Glory of the Roman Empire). So far it has been easy to unpack the files, however I can't manage to repack them again and make it work.

This is how the "original" Packs/data.hpk prints

file is compressed
header:
data_offset: 0x24
fragments_residual_offset: 0x2A299
fragments_residual_count: 49
fragments_per_file: 1
fragments_filesystem_offset: 0x20374
fragments_filesystem_length: 32824
filesystem entries: 4103

and this is what I get when printing the re-packaged data.hpk

file is compressed
header:
data_offset: 0x24
fragments_residual_offset: 0x0
fragments_residual_count: 0
fragments_per_file: 1
fragments_filesystem_offset: 0x1EE164
fragments_filesystem_length: 32824
filesystem entries: 4103

Is there an option I am missing that might be useful to solve this? I have tried playing with the --chunk-size but only changed the fragments_filesystem_offset

Thanks for everything

Garbo

Surviving Mars zstd compression

Hi,

Thanks a lot for your work on the tool and especially putting format details into README, saved me a bunch of time figuring it out from the code.

I've noticed that mods uploaded to Steam Workshop via Surviving Mars Mod Editor are packed into .hpk, which can be extracted by the tool, but unpacked files are still compressed with ZSTD signature at the start.

Which are same fragmented files as lz4/zlib-compressed ones, just using zstd instead of these two.

Decompression script example:
https://github.com/mk-fg/games/blob/master/surviving-mars/zstd-dec.py#L39-L64

Not sure if it's also the case for other compression, but had to add "len(buff) != dst_len" check there as for e.g. .png files, despite ZSTD header, fragments are not compressed.

Attached ModContent.hpk.zip has ModContent.hpk for my simple mod, which has .lua and .png files with ZSTD header in it, both should be decompressible by python script above, but not currently handled by hpk tool itself, unfortunately.

ModContent.hpk.zip

The First Templar

Hello. Could you add support for the first templar game? So that we can extract models, textures, sounds, etc. Thanks!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.