~moody/pse

pse/util.go -rw-r--r-- 4.6 KiB
e4de17d5 — Jacob Moody Introduce pse(1) 9 months ago
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
package pse

import (
	"encoding/json"
	"fmt"
)

func get2(b []byte) uint16 {
	return uint16(b[1])<<8 | uint16(b[0])
}

func get2e(b []byte, key []byte) uint16 {
	return uint16(b[1]^key[1])<<8 | uint16(b[0]^key[0])
}

func put2(i uint16, b []byte) {
	b[1] = byte(i >> 8)
	b[0] = byte(i)
}

func put2e(i uint16, b []byte, key []byte) {
	b[1] = byte(i>>8) ^ byte(key[1])
	b[0] = byte(i) ^ byte(key[0])
}

func get4(b []byte) uint32 {
	return uint32(b[3])<<24 | uint32(b[2])<<16 | uint32(b[1])<<8 | uint32(b[0])
}

func get4e(b []byte, key []byte) uint32 {
	return uint32(b[3]^key[3])<<24 | uint32(b[2]^key[2])<<16 | uint32(b[1]^key[1])<<8 | uint32(b[0]^key[0])
}

func put4(i uint32, b []byte) {
	b[3] = byte(i >> 24)
	b[2] = byte(i >> 16)
	b[1] = byte(i >> 8)
	b[0] = byte(i)
}

func put4e(i uint32, b []byte, key []byte) {
	b[3] = byte(i>>24) ^ key[3]
	b[2] = byte(i>>16) ^ key[2]
	b[1] = byte(i>>8) ^ key[1]
	b[0] = byte(i) ^ key[0]
}

const (
	LangJP = 0x201
	LangEN = 0x202
	LangFR = 0x203
	LangIT = 0x204
	LangDE = 0x205
	LangKR = 0x206
	LangSP = 0x207
)

var kanatran = []rune{
	' ',
	'あ', 'い', 'う', 'え', 'お', 'か', 'き', 'く', 'け', 'こ', 'さ', 'し', 'す', 'せ', 'そ',
	'た', 'ち', 'つ', 'て', 'と', 'な', 'に', 'ぬ', 'ね', 'の', 'は', 'ひ', 'ふ', 'へ', 'ほ', 'ま',
	'み', 'む', 'め', 'も', 'や', 'ゆ', 'よ', 'ら', 'り', 'る', 'れ', 'ろ', 'わ', 'を', 'ん', 'ぁ',
	'ぃ', 'ぅ', 'ぇ', 'ぉ', 'ゃ', 'ゅ', 'ょ', 'が', 'ぎ', 'ぐ', 'げ', 'ご', 'ざ', 'じ', 'ず', 'ぜ',
	'ぞ', 'だ', 'ぢ', 'づ', 'で', 'ど', 'ば', 'び', 'ぶ', 'べ', 'ぼ', 'ぱ', 'ぴ', 'ぷ', 'ぺ', 'ぽ',
	'っ', 'ア', 'イ', 'ウ', 'エ', 'オ', 'カ', 'キ', 'ク', 'ケ', 'コ', 'サ', 'シ', 'ス', 'セ', 'ソ',
	'タ', 'チ', 'ツ', 'テ', 'ト', 'ナ', 'ニ', 'ヌ', 'ネ', 'ノ', 'ハ', 'ヒ', 'フ', 'ヘ', 'ホ', 'マ',
	'ミ', 'ム', 'メ', 'モ', 'ヤ', 'ユ', 'ヨ', 'ラ', 'リ', 'ル', 'レ', 'ロ', 'ワ', 'ヲ', 'ン', 'ァ',
	'ィ', 'ゥ', 'ェ', 'ォ', 'ャ', 'ュ', 'ョ', 'ガ', 'ギ', 'グ', 'ゲ', 'ゴ', 'ザ', 'ジ', 'ズ', 'ゼ',
	'ゾ', 'ダ', 'ヂ', 'ヅ', 'デ', 'ド', 'バ', 'ビ', 'ブ', 'ベ', 'ボ', 'パ', 'ピ', 'プ', 'ペ', 'ポ',
}

func gen3tor(i byte, lang int) (rune, error) {
	if lang == LangJP {
		if int(i) < len(kanatran) {
			return kanatran[i], nil
		}
	}
	//Cover 0-9, A-Z and a-z first
	if i >= 0xA1 && i <= 0xAA {
		return rune('0' + (i - 0xA1)), nil
	}
	if i >= 0xBB && i <= 0xD4 {
		return rune('A' + (i - 0xBB)), nil
	}
	if i >= 0xD5 && i <= 0xEE {
		return rune('a' + (i - 0xD5)), nil
	}
	//Pick up the special characters
	switch i {
	case 0:
		return ' ', nil
	case 0xB3:
		return '‘', nil
	case 0xB4:
		return '’', nil
	case 0xAB:
		return '!', nil
	case 0xAC:
		return '?', nil
	case 0xAD:
		return '.', nil
	case 0xAE:
		return '-', nil
	//String terminator
	case 0xFF:
		return 0, nil
	default:
		return 0, fmt.Errorf("gen3toa: unknown character %d", i)
	}
}

func rtogen3(i rune, lang int) (byte, error) {
	if lang == LangJP {
		for index, r := range kanatran {
			if r == i {
				return byte(index), nil
			}
		}
	}
	if i >= '0' && i <= '9' {
		return 0xA1 + (byte(i) - '0'), nil
	}
	if i >= 'A' && i <= 'Z' {
		return 0xBB + (byte(i) - 'A'), nil
	}
	if i >= 'a' && i <= 'z' {
		return 0xD5 + (byte(i) - 'a'), nil
	}
	switch i {
	case ' ':
		return 0, nil
	case '‘':
		return 0xB3, nil
	case '’':
		return 0xB4, nil
	case '!':
		return 0xAB, nil
	case '?':
		return 0xAC, nil
	case '.':
		return 0xAD, nil
	case '-':
		return 0xAE, nil
	case 0:
		return 0xFF, nil
	default:
		return 0, fmt.Errorf("atogen3: can not convert character %d", i)
	}
}

type PkString struct {
	string

	data []byte
}

//Encoding embedded strings doesn't work nicely.
//Plus this cleans up the json output for structs
//that contain PkStrings.
func (p *PkString) MarshalJSON() ([]byte, error) {
	return json.Marshal(p.string)
}

func (p *PkString) UnmarshalJSON(b []byte) error {
	var tmp string
	err := json.Unmarshal(b, &tmp)
	if err != nil {
		return err
	}
	p.string = tmp
	return nil
}

func NewPkString(data []byte, lang int) (*PkString, error) {
	var tmp []rune
	p := &PkString{data: data}
	for i, b := range data {
		n, err := gen3tor(b, lang)
		if err != nil {
			return nil, err
		}
		if n == 0 {
			p.string = string(tmp[:i])
			return p, nil
		}
		tmp = append(tmp, n)
	}
	p.string = string(tmp[:])
	return p, nil
}

func (p *PkString) Commit(lang int) error {
	var tmp []byte
	for _, r := range append([]rune(p.string), 0x00) {
		n, err := rtogen3(r, lang)
		if err != nil {
			return err
		}
		tmp = append(tmp, n)
		if n == 0xFF {
			break
		}
	}
	copy(p.data, tmp)
	return nil
}