node-rcheevos 0.5.0 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +47 -47
- package/lib/index.d.ts +111 -6
- package/lib/index.js +90 -1
- package/package.json +1 -1
- package/prebuilds/darwin-arm64/node-rcheevos.node +0 -0
- package/prebuilds/win32-x64/node-rcheevos.node +0 -0
package/README.md
CHANGED
|
@@ -1,77 +1,77 @@
|
|
|
1
1
|
# node-rcheevos
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
[](https://www.npmjs.com/package/node-rcheevos)
|
|
4
4
|
|
|
5
|
-
Generate RetroAchievements hashes for ROMs in Node.js. Uses the
|
|
5
|
+
Generate RetroAchievements hashes for ROMs in Node.js. Uses the same [rcheevos](https://github.com/RetroAchievements/rcheevos) C library that RetroArch uses, so your hashes will match exactly.
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
## Why not just reimplement the hashing in JavaScript?
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
I tried that first. Each console has its own special hashing rules - NES strips the iNES header, SNES might have a 512-byte header to skip, PlayStation has to parse `SYSTEM.CNF` to find which executable to hash, N64 needs byte-order conversion depending on the ROM format. The [RetroAchievements docs](https://docs.retroachievements.org/developer-docs/game-identification.html) explain all this, but keeping JavaScript implementations updated for 40+ systems when RA changes their logic is a pain. Easier to just wrap their C library directly.
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
This wraps the official C library as a native Node addon, so it just works. Same hashing logic as the source of truth, supports all the systems RetroAchievements does (Game Boy, NES, SNES, PlayStation, PSP, you name it).
|
|
14
|
-
|
|
15
|
-
## Install
|
|
11
|
+
Built this for [ROMie](https://github.com/JZimz/romie) but figured it's useful standalone.
|
|
16
12
|
|
|
13
|
+
## Installation
|
|
17
14
|
```bash
|
|
18
15
|
npm install node-rcheevos
|
|
19
16
|
```
|
|
20
17
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
## How to use it
|
|
18
|
+
Includes pre-built binaries for macOS, Windows, and Linux (both x64 and ARM64). If you're on something else, it'll build from source automatically.
|
|
24
19
|
|
|
20
|
+
## Quick Start
|
|
25
21
|
```javascript
|
|
26
|
-
const { rhash } = require('node-rcheevos');
|
|
22
|
+
const { rhash, ConsoleId } = require('node-rcheevos');
|
|
27
23
|
|
|
28
|
-
const md5 = rhash(
|
|
29
|
-
console.log(md5);
|
|
24
|
+
const md5 = rhash(ConsoleId.GAMEBOY, '/path/to/pokemon-red.gb');
|
|
25
|
+
console.log(md5); // "bb7df04e1b0a2570657527a7e108ae23"
|
|
30
26
|
```
|
|
31
27
|
|
|
32
|
-
|
|
28
|
+
## API
|
|
33
29
|
|
|
34
|
-
|
|
35
|
-
import { rhash } from 'node-rcheevos';
|
|
30
|
+
### `rhash(consoleId, path, buffer?)`
|
|
36
31
|
|
|
37
|
-
|
|
38
|
-
|
|
32
|
+
**Parameters:**
|
|
33
|
+
- `consoleId` (number): RetroAchievements console ID (use `ConsoleId` constants or numeric values)
|
|
34
|
+
- `path` (string): Path to your ROM file
|
|
35
|
+
- `buffer` (Buffer, optional): ROM data if you already have it in memory
|
|
39
36
|
|
|
40
|
-
|
|
37
|
+
**Returns:** MD5 hash as a lowercase hex string
|
|
41
38
|
|
|
42
|
-
|
|
43
|
-
npx rhash -c 4 /path/to/game.gb
|
|
44
|
-
```
|
|
39
|
+
**Throws:** Error if the file doesn't exist, can't be read, or the console ID is invalid
|
|
45
40
|
|
|
46
|
-
|
|
41
|
+
### `ConsoleId`
|
|
47
42
|
|
|
48
|
-
|
|
43
|
+
Exported constants for all console IDs if you prefer named constants over numbers.
|
|
49
44
|
|
|
50
|
-
|
|
45
|
+
```javascript
|
|
46
|
+
const { ConsoleId } = require('node-rcheevos');
|
|
51
47
|
|
|
52
|
-
|
|
48
|
+
console.log(ConsoleId.GAMEBOY); // 4
|
|
49
|
+
console.log(ConsoleId.PLAYSTATION); // 12
|
|
50
|
+
console.log(ConsoleId.PSP); // 41
|
|
51
|
+
```
|
|
53
52
|
|
|
54
|
-
|
|
53
|
+
### Buffer limitations
|
|
55
54
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
| 4 | Game Boy |
|
|
62
|
-
| 5 | Game Boy Advance |
|
|
63
|
-
| 6 | Game Boy Color |
|
|
64
|
-
| 7 | NES/Famicom |
|
|
65
|
-
| 11 | Game Gear |
|
|
66
|
-
| 12 | PlayStation |
|
|
67
|
-
| 27 | PlayStation Portable |
|
|
68
|
-
| 38 | Nintendo 3DS |
|
|
69
|
-
| 39 | Dreamcast |
|
|
55
|
+
**Works with buffers** (cartridge-based systems like GB, GBA, NES, SNES):
|
|
56
|
+
```javascript
|
|
57
|
+
const buffer = fs.readFileSync('/path/to/game.gb');
|
|
58
|
+
const md5 = rhash(ConsoleId.GAMEBOY, '/path/to/game.gb', buffer);
|
|
59
|
+
```
|
|
70
60
|
|
|
71
|
-
|
|
61
|
+
**Doesn't work with buffers** (disc-based like PlayStation, PSP, and arcade systems):
|
|
62
|
+
```javascript
|
|
63
|
+
// Passing a buffer will throw an error - must use file path
|
|
64
|
+
const md5 = rhash(ConsoleId.PLAYSTATION, '/path/to/game.bin');
|
|
65
|
+
```
|
|
72
66
|
|
|
73
|
-
|
|
67
|
+
Disc-based systems need to read specific sectors from the image file, and arcade systems hash the filename, so they can't work with in-memory buffers.
|
|
68
|
+
|
|
69
|
+
## CLI Usage
|
|
70
|
+
```bash
|
|
71
|
+
npx rhash -c 4 /path/to/game.gb
|
|
72
|
+
```
|
|
74
73
|
|
|
74
|
+
## Building from Source
|
|
75
75
|
```bash
|
|
76
76
|
git clone --recursive https://github.com/jzimz/node-rcheevos.git
|
|
77
77
|
cd node-rcheevos
|
|
@@ -79,8 +79,8 @@ npm install
|
|
|
79
79
|
npm run build
|
|
80
80
|
```
|
|
81
81
|
|
|
82
|
-
The `--recursive` flag pulls in the rcheevos
|
|
82
|
+
The `--recursive` flag is important - it pulls in the rcheevos library. Without it, you won't have anything to build against.
|
|
83
83
|
|
|
84
84
|
## License
|
|
85
85
|
|
|
86
|
-
MIT. The rcheevos library
|
|
86
|
+
MIT. The rcheevos library is also MIT.
|
package/lib/index.d.ts
CHANGED
|
@@ -1,7 +1,112 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* RetroAchievements console identifiers.
|
|
3
|
+
* Use these constants instead of magic numbers for better readability.
|
|
4
|
+
*
|
|
5
|
+
* @example
|
|
6
|
+
* ```typescript
|
|
7
|
+
* import { rhash, ConsoleId } from 'node-rcheevos';
|
|
8
|
+
*
|
|
9
|
+
* const md5 = rhash(ConsoleId.GAMEBOY, '/path/to/game.gb');
|
|
10
|
+
* ```
|
|
11
|
+
*/
|
|
12
|
+
export const ConsoleId: {
|
|
13
|
+
readonly UNKNOWN: 0;
|
|
14
|
+
readonly MEGA_DRIVE: 1;
|
|
15
|
+
readonly NINTENDO_64: 2;
|
|
16
|
+
readonly SUPER_NINTENDO: 3;
|
|
17
|
+
readonly GAMEBOY: 4;
|
|
18
|
+
readonly GAMEBOY_ADVANCE: 5;
|
|
19
|
+
readonly GAMEBOY_COLOR: 6;
|
|
20
|
+
readonly NINTENDO: 7;
|
|
21
|
+
readonly PC_ENGINE: 8;
|
|
22
|
+
readonly SEGA_CD: 9;
|
|
23
|
+
readonly SEGA_32X: 10;
|
|
24
|
+
readonly MASTER_SYSTEM: 11;
|
|
25
|
+
readonly PLAYSTATION: 12;
|
|
26
|
+
readonly ATARI_LYNX: 13;
|
|
27
|
+
readonly NEOGEO_POCKET: 14;
|
|
28
|
+
readonly GAME_GEAR: 15;
|
|
29
|
+
readonly GAMECUBE: 16;
|
|
30
|
+
readonly ATARI_JAGUAR: 17;
|
|
31
|
+
readonly NINTENDO_DS: 18;
|
|
32
|
+
readonly WII: 19;
|
|
33
|
+
readonly WII_U: 20;
|
|
34
|
+
readonly PLAYSTATION_2: 21;
|
|
35
|
+
readonly XBOX: 22;
|
|
36
|
+
readonly MAGNAVOX_ODYSSEY2: 23;
|
|
37
|
+
readonly POKEMON_MINI: 24;
|
|
38
|
+
readonly ATARI_2600: 25;
|
|
39
|
+
readonly MS_DOS: 26;
|
|
40
|
+
readonly ARCADE: 27;
|
|
41
|
+
readonly VIRTUAL_BOY: 28;
|
|
42
|
+
readonly MSX: 29;
|
|
43
|
+
readonly COMMODORE_64: 30;
|
|
44
|
+
readonly ZX81: 31;
|
|
45
|
+
readonly ORIC: 32;
|
|
46
|
+
readonly SG1000: 33;
|
|
47
|
+
readonly VIC20: 34;
|
|
48
|
+
readonly AMIGA: 35;
|
|
49
|
+
readonly ATARI_ST: 36;
|
|
50
|
+
readonly AMSTRAD_PC: 37;
|
|
51
|
+
readonly APPLE_II: 38;
|
|
52
|
+
readonly SATURN: 39;
|
|
53
|
+
readonly DREAMCAST: 40;
|
|
54
|
+
readonly PSP: 41;
|
|
55
|
+
readonly CDI: 42;
|
|
56
|
+
readonly THREEDO: 43;
|
|
57
|
+
readonly COLECOVISION: 44;
|
|
58
|
+
readonly INTELLIVISION: 45;
|
|
59
|
+
readonly VECTREX: 46;
|
|
60
|
+
readonly PC8800: 47;
|
|
61
|
+
readonly PC9800: 48;
|
|
62
|
+
readonly PCFX: 49;
|
|
63
|
+
readonly ATARI_5200: 50;
|
|
64
|
+
readonly ATARI_7800: 51;
|
|
65
|
+
readonly X68K: 52;
|
|
66
|
+
readonly WONDERSWAN: 53;
|
|
67
|
+
readonly CASSETTEVISION: 54;
|
|
68
|
+
readonly SUPER_CASSETTEVISION: 55;
|
|
69
|
+
readonly NEO_GEO_CD: 56;
|
|
70
|
+
readonly FAIRCHILD_CHANNEL_F: 57;
|
|
71
|
+
readonly FM_TOWNS: 58;
|
|
72
|
+
readonly ZX_SPECTRUM: 59;
|
|
73
|
+
readonly GAME_AND_WATCH: 60;
|
|
74
|
+
readonly NOKIA_NGAGE: 61;
|
|
75
|
+
readonly NINTENDO_3DS: 62;
|
|
76
|
+
readonly SUPERVISION: 63;
|
|
77
|
+
readonly SHARPX1: 64;
|
|
78
|
+
readonly TIC80: 65;
|
|
79
|
+
readonly THOMSONTO8: 66;
|
|
80
|
+
readonly PC6000: 67;
|
|
81
|
+
readonly PICO: 68;
|
|
82
|
+
readonly MEGADUCK: 69;
|
|
83
|
+
readonly ZEEBO: 70;
|
|
84
|
+
readonly ARDUBOY: 71;
|
|
85
|
+
readonly WASM4: 72;
|
|
86
|
+
readonly ARCADIA_2001: 73;
|
|
87
|
+
readonly INTERTON_VC_4000: 74;
|
|
88
|
+
readonly ELEKTOR_TV_GAMES_COMPUTER: 75;
|
|
89
|
+
readonly PC_ENGINE_CD: 76;
|
|
90
|
+
readonly ATARI_JAGUAR_CD: 77;
|
|
91
|
+
readonly NINTENDO_DSI: 78;
|
|
92
|
+
readonly TI83: 79;
|
|
93
|
+
readonly UZEBOX: 80;
|
|
94
|
+
readonly FAMICOM_DISK_SYSTEM: 81;
|
|
95
|
+
readonly HUBS: 100;
|
|
96
|
+
readonly EVENTS: 101;
|
|
97
|
+
readonly STANDALONE: 102;
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Valid console ID values for the rhash function.
|
|
102
|
+
* This is the union of all values in the ConsoleId object.
|
|
103
|
+
*/
|
|
104
|
+
export type ConsoleIdValue = typeof ConsoleId[keyof typeof ConsoleId];
|
|
105
|
+
|
|
1
106
|
/**
|
|
2
107
|
* Generate a hash for a ROM file using the RetroAchievements algorithm.
|
|
3
108
|
*
|
|
4
|
-
* @param consoleId - The RetroAchievements console ID
|
|
109
|
+
* @param consoleId - The RetroAchievements console ID
|
|
5
110
|
* @param path - Path to the ROM file (required even when using buffer, for file extension detection)
|
|
6
111
|
* @param buffer - Optional buffer containing ROM data. If provided, hashes from memory instead of reading file
|
|
7
112
|
* @returns MD5 hash as a 32-character hex string
|
|
@@ -9,15 +114,15 @@
|
|
|
9
114
|
*
|
|
10
115
|
* @example
|
|
11
116
|
* ```typescript
|
|
12
|
-
* import { rhash } from 'node-rcheevos';
|
|
117
|
+
* import { rhash, ConsoleId } from 'node-rcheevos';
|
|
13
118
|
* import { readFileSync } from 'fs';
|
|
14
119
|
*
|
|
15
|
-
* // Hash from file
|
|
16
|
-
* const md5 = rhash(
|
|
120
|
+
* // Hash from file using ConsoleId constant or use literal numbers
|
|
121
|
+
* const md5 = rhash(ConsoleId.PSP, '/path/to/game.iso');
|
|
17
122
|
*
|
|
18
123
|
* // Hash from buffer (useful if already in memory)
|
|
19
124
|
* const buffer = readFileSync('/path/to/game.iso');
|
|
20
|
-
* const md5 = rhash(
|
|
125
|
+
* const md5 = rhash(ConsoleId.PSP, '/path/to/game.iso', buffer);
|
|
21
126
|
* ```
|
|
22
127
|
*/
|
|
23
|
-
export function rhash(consoleId:
|
|
128
|
+
export function rhash(consoleId: ConsoleIdValue, path: string, buffer?: Buffer): string;
|
package/lib/index.js
CHANGED
|
@@ -1,5 +1,94 @@
|
|
|
1
1
|
const addon = require('node-gyp-build')(__dirname + '/..');
|
|
2
2
|
|
|
3
|
+
const ConsoleId = {
|
|
4
|
+
UNKNOWN: 0,
|
|
5
|
+
MEGA_DRIVE: 1,
|
|
6
|
+
NINTENDO_64: 2,
|
|
7
|
+
SUPER_NINTENDO: 3,
|
|
8
|
+
GAMEBOY: 4,
|
|
9
|
+
GAMEBOY_ADVANCE: 5,
|
|
10
|
+
GAMEBOY_COLOR: 6,
|
|
11
|
+
NINTENDO: 7,
|
|
12
|
+
PC_ENGINE: 8,
|
|
13
|
+
SEGA_CD: 9,
|
|
14
|
+
SEGA_32X: 10,
|
|
15
|
+
MASTER_SYSTEM: 11,
|
|
16
|
+
PLAYSTATION: 12,
|
|
17
|
+
ATARI_LYNX: 13,
|
|
18
|
+
NEOGEO_POCKET: 14,
|
|
19
|
+
GAME_GEAR: 15,
|
|
20
|
+
GAMECUBE: 16,
|
|
21
|
+
ATARI_JAGUAR: 17,
|
|
22
|
+
NINTENDO_DS: 18,
|
|
23
|
+
WII: 19,
|
|
24
|
+
WII_U: 20,
|
|
25
|
+
PLAYSTATION_2: 21,
|
|
26
|
+
XBOX: 22,
|
|
27
|
+
MAGNAVOX_ODYSSEY2: 23,
|
|
28
|
+
POKEMON_MINI: 24,
|
|
29
|
+
ATARI_2600: 25,
|
|
30
|
+
MS_DOS: 26,
|
|
31
|
+
ARCADE: 27,
|
|
32
|
+
VIRTUAL_BOY: 28,
|
|
33
|
+
MSX: 29,
|
|
34
|
+
COMMODORE_64: 30,
|
|
35
|
+
ZX81: 31,
|
|
36
|
+
ORIC: 32,
|
|
37
|
+
SG1000: 33,
|
|
38
|
+
VIC20: 34,
|
|
39
|
+
AMIGA: 35,
|
|
40
|
+
ATARI_ST: 36,
|
|
41
|
+
AMSTRAD_PC: 37,
|
|
42
|
+
APPLE_II: 38,
|
|
43
|
+
SATURN: 39,
|
|
44
|
+
DREAMCAST: 40,
|
|
45
|
+
PSP: 41,
|
|
46
|
+
CDI: 42,
|
|
47
|
+
THREEDO: 43,
|
|
48
|
+
COLECOVISION: 44,
|
|
49
|
+
INTELLIVISION: 45,
|
|
50
|
+
VECTREX: 46,
|
|
51
|
+
PC8800: 47,
|
|
52
|
+
PC9800: 48,
|
|
53
|
+
PCFX: 49,
|
|
54
|
+
ATARI_5200: 50,
|
|
55
|
+
ATARI_7800: 51,
|
|
56
|
+
X68K: 52,
|
|
57
|
+
WONDERSWAN: 53,
|
|
58
|
+
CASSETTEVISION: 54,
|
|
59
|
+
SUPER_CASSETTEVISION: 55,
|
|
60
|
+
NEO_GEO_CD: 56,
|
|
61
|
+
FAIRCHILD_CHANNEL_F: 57,
|
|
62
|
+
FM_TOWNS: 58,
|
|
63
|
+
ZX_SPECTRUM: 59,
|
|
64
|
+
GAME_AND_WATCH: 60,
|
|
65
|
+
NOKIA_NGAGE: 61,
|
|
66
|
+
NINTENDO_3DS: 62,
|
|
67
|
+
SUPERVISION: 63,
|
|
68
|
+
SHARPX1: 64,
|
|
69
|
+
TIC80: 65,
|
|
70
|
+
THOMSONTO8: 66,
|
|
71
|
+
PC6000: 67,
|
|
72
|
+
PICO: 68,
|
|
73
|
+
MEGADUCK: 69,
|
|
74
|
+
ZEEBO: 70,
|
|
75
|
+
ARDUBOY: 71,
|
|
76
|
+
WASM4: 72,
|
|
77
|
+
ARCADIA_2001: 73,
|
|
78
|
+
INTERTON_VC_4000: 74,
|
|
79
|
+
ELEKTOR_TV_GAMES_COMPUTER: 75,
|
|
80
|
+
PC_ENGINE_CD: 76,
|
|
81
|
+
ATARI_JAGUAR_CD: 77,
|
|
82
|
+
NINTENDO_DSI: 78,
|
|
83
|
+
TI83: 79,
|
|
84
|
+
UZEBOX: 80,
|
|
85
|
+
FAMICOM_DISK_SYSTEM: 81,
|
|
86
|
+
HUBS: 100,
|
|
87
|
+
EVENTS: 101,
|
|
88
|
+
STANDALONE: 102
|
|
89
|
+
};
|
|
90
|
+
|
|
3
91
|
module.exports = {
|
|
4
|
-
rhash: addon.rhash
|
|
92
|
+
rhash: addon.rhash,
|
|
93
|
+
ConsoleId
|
|
5
94
|
};
|
package/package.json
CHANGED
|
Binary file
|
|
Binary file
|