OSK, A FASTER & MORE USER-CONFIGURABLE ONSCREEN KEYBOARD:
(Found this by accident when looking for something else. It's from 2018, but still works great on my Clara HD.)
USBMS Shenanigans...
https://www.mobileread.com/forums/sh...0&postcount=14
https://github.com/shermp/go-kobo-input
shermp/go-kobo-input
$ mkdir osk-build
$ cd osk-build/
$ wget
https://golang.org/dl/go1.20.2.linux-amd64.tar.gz
$ sudo tar -C /usr/local -xzf go1.20.2.linux-amd64.tar.gz
$ echo "export PATH=/usr/local/go/bin:${PATH}" | sudo tee -a $HOME/.profile
$ source $HOME/.profile
$ go version
go version go1.20.2 linux/amd64
$ source ~/koxtoolchain/refs/x-compile.sh kobo env bare
Note: This refers to the KOReader toolchain from:
https://www.mobileread.com/forums/sh...16&postcount=4
You could try a different toolchain if you feel lucky.
$ env GO111MODULE=off go get github.com/shermp/go-fbink-v2
$ cd ~/go/src/github.com/shermp/go-fbink-v2/
$ cd gofbink/
$ env GOOS=linux GOARCH=arm CGO_ENABLED=1 CC=arm-kobo-linux-gnueabihf-gcc CXX=arm-kobo-linux-gnueabihf-g++ go build
$ cd ../example/
$ env GOOS=linux GOARCH=arm CGO_ENABLED=1 CC=arm-kobo-linux-gnueabihf-gcc CXX=arm-kobo-linux-gnueabihf-g++ go build
Copy the /go/src/github.com/shermp/go-fbink-v2/example/example binary to the /mnt/onboard/.adds/koreader/scripts/ folder of your Kobo.
Run these commands from an SSH session to the Kobo:
# . /korenv.sh
# example
(Should display some nice text messages on Kobo display.)
***
Now for the keyboard:
Back on your PC run:
$ env GO111MODULE=off go get github.com/fogleman/gg
$ env GO111MODULE=off go get github.com/shermp/go-osk
//$ env GO111MODULE=off go get github.com/shermp/kobo-sim-usb/simusb
$ env GO111MODULE=off go get github.com/shermp/go-kobo-input
$ cd ~/go/src/github.com/shermp/go-kobo-input/
$ cd koboin-osk-sample/
$ nano -l main.go
Code:
25 // "fmt"
...
32 // "github.com/shermp/kobo-sim-usb/simusb"
...
57 // u, err := simusb.New(fb)
58 // if err != nil {
59 // fmt.Println(err)
60 // }
61 // err = u.Start(true, true)
62 // if err != nil {
63 // fmt.Println(err)
64 // return
65 // }
66 // defer u.End(true)
Note: the USBMS did work at one time, but stopped along the way, and I am skipping it for now because it's a pain to debug since USB networking must not be activated in this mode.
$ env GO111MODULE=off GOOS=linux GOARCH=arm CGO_ENABLED=1 CC=arm-kobo-linux-gnueabihf-gcc CXX=arm-kobo-linux-gnueabihf-g++ go build
$ arm-kobo-linux-gnueabihf-strip koboin-osk-sample
$ file koboin-osk-sample
koboin-osk-sample: ELF 32-bit LSB executable, ARM, EABI5 version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux-armhf.so.3, for GNU/Linux 2.6.33, Go
Copy the ~/go/src/github.com/shermp/go-kobo-input/koboin-osk-sample/koboin-osk-sample binary to the /mnt/onboard/.adds/koreader/scripts/ folder of your Kobo.
Copy the keymap-en_us.json and Roboto-Medium.ttf files from the ~/go/src/github.com/shermp/go-kobo-input/koboin-osk-sample/ folder to the /mnt/onboard/.adds/koreader/ folder of your Kobo.
To avoid keyboard taps activating a Nickel function:
From More tab (second tab from right at bottom of screen), select Activity.
If you are in SideloadedMode=true, then Activity tab is second from left at bottom of screen.
Run these commands from an SSH session to the Kobo:
# . /korenv.sh
# koboin-osk-sample
Tap the CAP key for uppercase letters.
Tap the RET key to exit.
***
To customize our keyboard, we need to:
1. FIX KEY REPEAT ERRORS
2. CHANGE LAYOUT
3. SEND INPUT TO FBPAD
***
$ cd ~/go/src/github.com/shermp/go-osk/
$ cd osk/
1. FIX KEY REPEAT ERRORS:
$ nano -l osk.go
Code:
27 // "strings"
...
253 kc.DrawStringAnchored(string(k.KeyCode), kmx, kmy, 0.5, 0.5)
'''
273 if time.Since(v.debounceStartTm) < (200 * time.Millisecond) {
2. CHANGE LAYOUT:
$ nano -l osk.go
Code:
41 KTesc = 7
42 KTtab = 8
43 KTup = 9
44 KTdown = 10
45 KTleft = 11
46 KTright = 12
47 KTpgUp = 13
48 KTpgDn = 14
...
198 case KTalt:
199 return "ALT"
200 case KTbackspace:
201 return "BKSP"
202 case KTcapsLock:
203 return "CAP"
204 case KTcarriageReturn:
205 return "RET"
206 case KTcontrol:
207 return "CTL"
208 case KTdelete:
209 return "DEL"
210 case KTesc:
211 return "ESC"
212 case KTtab:
213 return "TAB"
214 case KTup:
215 return "^"
216 case KTdown:
217 return "V"
218 case KTleft:
219 return "<"
220 case KTright:
221 return ">"
222 case KTpgUp:
223 return "<<"
224 case KTpgDn:
225 return ">>"
$ cd ~/go/src/github.com/shermp/go-kobo-input/
$ cd koboin-osk-sample/
$ nano -l keymap-en_us.json
Spoiler:
Code:
79 "char": "-"
...
83 "keyType": 0,
84 "keyWidth": 1,
85 "char": "="
...
93 "isPadding": false,
94 "keyType": 7,
95 "keyWidth": 1,
96 "char": ""
...
159 "isPadding": false,
160 "keyType": 2,
161 "keyWidth": 1,
162 "char": ""
163 }
164 ]
...
233 "char": ";"
...
239 "char": "'"
...
249 {
250 "rowHeight": 1,
251 "keys": [
252 {
253 "isPadding": false,
254 "keyType": 8,
255 "keyWidth": 1,
256 "char": ""
...
316 "char": "/"
...
319 "isPadding": false,
320 "keyType": 0,
321 "keyWidth": 1,
322 "char": "|"
...
327 "rowHeight": 1,
328 "keys": [
329 {
330 "isPadding": false,
331 "keyType": 9,
332 "keyWidth": 1,
333 "char": ""
334 },
335 {
336 "isPadding": false,
337 "keyType": 10,
338 "keyWidth": 1,
339 "char": ""
340 },
341 {
342 "isPadding": false,
343 "keyType": 11,
344 "keyWidth": 1,
345 "char": ""
346 },
347 {
348 "isPadding": false,
349 "keyType": 12,
350 "keyWidth": 1,
351 "char": ""
352 },
353 {
354 "isPadding": false,
355 "keyType": 0,
356 "keyWidth": 2,
357 "char": " "
358 },
359 {
360 "isPadding": false,
361 "keyType": 0,
362 "keyWidth": 1,
363 "char": "["
364 },
365 {
366 "isPadding": false,
367 "keyType": 0,
368 "keyWidth": 1,
369 "char": "]"
370 },
371 {
372 "isPadding": false,
373 "keyType": 13,
374 "keyWidth": 1,
375 "char": ""
376 },
377 {
378 "isPadding": false,
379 "keyType": 14,
380 "keyWidth": 1,
381 "char": ""
382 },
383 {
384 "isPadding": false,
385 "keyType": 5,
386 "keyWidth": 1,
387 "char": ""
388 },
389 {
390 "isPadding": false,
391 "keyType": 1,
392 "keyWidth": 1,
393 "char": ""
394 }
395 ]
396 }
397 ]
$ cp keymap-en_us.json keymap1-en_us.json
$ cp keymap-en_us.json keymap2-en_us.json
$ nano -l keymap2-en_us.json
$ nano -l main.go
Spoiler:
Code:
27 // "unicode"
...
67 fb.Println("Welcome to the test!")
68 fb.Println("Have Fun!")
69 var k osk.Key
70 var prevType int
71
72 // Load a keymap file for the OSK
73 keymap1JSON, _ := ioutil.ReadFile("./keymap1-en_us.json")
74 km1 := osk.KeyMap{}
75 json.Unmarshal(keymap1JSON, &km1)
76 // Create an OSK
77 vk1, _ := osk.New(&km1, 1080, 1440)
78 // Generate an image of the OSK
79 vk1PNG := "./osk1-en_us.png"
80 vk1Font := "./Roboto-Medium.ttf"
81 vk1.CreateIMG(vk1PNG, vk1Font)
82
83 // Load a keymap file for the OSK
84 keymap2JSON, _ := ioutil.ReadFile("./keymap2-en_us.json")
85 km2 := osk.KeyMap{}
86 json.Unmarshal(keymap2JSON, &km2)
87 // Create an OSK
88 vk2, _ := osk.New(&km2, 1080, 1440)
89 // Generate an image of the OSK
90 vk2PNG := "./osk2-en_us.png"
91 vk2Font := "./Roboto-Medium.ttf"
92 vk2.CreateIMG(vk2PNG, vk2Font)
93
94 // Print the image to the screen. Its position on screen should match that stored
95 // in the keyboard object
96 fb.PrintImage(vk1PNG, int16(vk1.StartCoords.X), int16(vk1.StartCoords.Y), &cfg)
97 runeStr := []rune{}
98 upperCase := false
99 // cfg.Row = 16
100 // Read the input from the touch screen
101 L:
...
104 if err != nil {
105 continue
106 }
107 if upperCase {
108 k, err = vk2.GetPressedKey(x, y)
109 } else {
110 k, err = vk1.GetPressedKey(x, y)
111 }
112 if err != nil {
...
119 case osk.KTstandardChar:
120 var key rune
121 key = k.KeyCode
122 runeStr = append(runeStr, key)
...
130 case osk.KTcapsLock:
131 if prevType != osk.KTcapsLock {
132 upperCase = !upperCase
133 if upperCase {
134 fb.PrintImage(vk2PNG, int16(vk2.StartCoords.X), int16(vk2.StartCoords.Y), &cfg)
135 } else {
136 fb.PrintImage(vk1PNG, int16(vk1.StartCoords.X), int16(vk1.StartCoords.Y), &cfg)
137 }
138 }
...
143 }
144 prevType = k.KeyType
145 }
146 }
147
$ env GO111MODULE=off GOOS=linux GOARCH=arm CGO_ENABLED=1 CC=arm-kobo-linux-gnueabihf-gcc CXX=arm-kobo-linux-gnueabihf-g++ go build
$ arm-kobo-linux-gnueabihf-strip koboin-osk-sample
Copy the ~/go/src/github.com/shermp/go-kobo-input/koboin-osk-sample/koboin-osk-sample binary to the /mnt/onboard/.adds/koreader/scripts/ folder of your Kobo.
Copy the keymap1-en_us.json and keymap2-en_us.json files from the ~/go/src/github.com/shermp/go-kobo-input/koboin-osk-sample/ folder to the /mnt/onboard/.adds/koreader/ folder of your Kobo.
To avoid keyboard taps activating a Nickel function:
From More tab (second tab from right at bottom of screen), select Activity.
If you are in SideloadedMode=true, then Activity tab is second from left at bottom of screen.
Run these commands from an SSH session to the Kobo:
# . /korenv.sh
# koboin-osk-sample
Tap the CAP key to change layouts.
Tap the RET key to exit.
***
3. SEND INPUT TO FBPAD:
To be able to use our keyboard with fbpad terminal, we will send ANSI codes with IOCTL calls instead of simulating input events with uinput.
$ cd ~/go/src/github.com/shermp/go-kobo-input/
$ cd koboin-osk-sample/
$ nano -l main.go
Spoiler:
Code:
21 package main
22
23 import (
24 "encoding/json"
25 "fmt"
26 "io/ioutil"
27 // "unicode"
28 "os"
29 "syscall"
30 "unsafe"
31 "github.com/shermp/go-fbink-v2/gofbink"
32 "github.com/shermp/go-kobo-input/koboin"
33 "github.com/shermp/go-osk/osk"
34 // "github.com/shermp/kobo-sim-usb/simusb"
35 )
36
37 var ttyFile *os.File
38 var eno syscall.Errno
39 //var key byte
40 var upperCase bool
41 var ctlState bool
42 var altState bool
43 // sendAnsiSeq sends an ANSI escape string to open tty
44 func sendAnsiSeq(ansiSeq string) syscall.Errno {
45 seqBytes := []byte(ansiSeq)
46 for i := 0; i < len(seqBytes); i++ {
47 _, _, eno = syscall.Syscall(syscall.SYS_IOCTL,ttyFile.Fd(),syscall.TIOCSTI,uintptr(unsafe.Pointer(&seqBytes[i])),)
48 if eno != 0 {
49 return eno
50 }
51 }
52 return 0
53 }
54
55 func main() {
...
73 fb.Init(&cfg)
74 var err error
75 var tty = "/dev/pts/0"
76 ttyFile, err = os.Open(tty)
77 if err != nil {
78 fmt.Println(err)
79 tty = "/dev/pts/1"
80 ttyFile, err = os.Open(tty)
81 if err != nil {
82 fmt.Println(err)
83 }
84 }
85 defer ttyFile.Close()
86
87 // Use kobo-sim-usb to enter USBMS mode where we can use the
...
126 // Print the image to the screen. Its position on screen should match that stored
127 // in the keyboard object
128 fb.PrintImage(vk1PNG, int16(vk1.StartCoords.X), int16(vk1.StartCoords.Y), &cfg)
129 // runeStr := []rune{}
130 upperCase = false
131 ctlState = false
132 altState = false
133 // cfg.Row = 16
134 // Read the input from the touch screen
135 //L:
...
152 switch k.KeyType {
153 case osk.KTstandardChar:
154 key := k.KeyCode
155 tabSeq := []byte(string(key))
156 if (ctlState) {
157 byteSeq := []byte(tabSeq)
158 if (byteSeq[0] > 64) && (byteSeq[0] < 91) {
159 byteSeq[0] -= 64
160 seqErr := sendAnsiSeq(string(byteSeq[0]))
161 if seqErr != 0 {
162 fmt.Println(seqErr)
163 }
164 } else if (byteSeq[0] > 96) && (byteSeq[0] < 123) {
165 byteSeq[0] -= 96
166 seqErr := sendAnsiSeq(string(byteSeq[0]))
167 if seqErr != 0 {
168 fmt.Println(seqErr)
169 }
170 }
171 } else {
172 seqErr := sendAnsiSeq(string(tabSeq))
173 if seqErr != 0 {
174 fmt.Println(seqErr)
175 }
176 }
177 case osk.KTcarriageReturn:
178 tabSeq := []byte{13}
179 seqErr := sendAnsiSeq(string(tabSeq))
180 if seqErr != 0 {
181 fmt.Println(seqErr)
182 }
183 case osk.KTbackspace:
184 tabSeq := []byte{8}
185 seqErr := sendAnsiSeq(string(tabSeq))
186 if seqErr != 0 {
187 fmt.Println(seqErr)
188 }
189 case osk.KTdelete:
190 tabSeq := []byte{127}
191 seqErr := sendAnsiSeq(string(tabSeq))
192 if seqErr != 0 {
193 fmt.Println(seqErr)
194 }
195 case osk.KTcapsLock:
196 if prevType != osk.KTcapsLock {
197 upperCase = !upperCase
198 if upperCase {
199 fb.PrintImage(vk2PNG, int16(vk2.StartCoords.X), int16(vk2.StartCoords.Y), &cfg)
200 } else {
201 fb.PrintImage(vk1PNG, int16(vk1.StartCoords.X), int16(vk1.StartCoords.Y), &cfg)
202 }
203 }
204 case osk.KTcontrol:
205 ctlState = !ctlState
206 case osk.KTalt:
207 altState = !altState
208 case osk.KTesc:
209 tabSeq := []byte{27}
210 seqErr := sendAnsiSeq(string(tabSeq))
211 if seqErr != 0 {
212 fmt.Println(seqErr)
213 }
214 case osk.KTtab:
215 tabSeq := []byte{9}
216 seqErr := sendAnsiSeq(string(tabSeq))
217 if seqErr != 0 {
218 fmt.Println(seqErr)
219 }
220 case osk.KTup:
221 tabSeq := []byte{27,91,65}
222 seqErr := sendAnsiSeq(string(tabSeq))
223 if seqErr != 0 {
224 fmt.Println(seqErr)
225 }
226 case osk.KTdown:
227 tabSeq := []byte{27,91,66}
228 seqErr := sendAnsiSeq(string(tabSeq))
229 if seqErr != 0 {
230 fmt.Println(seqErr)
231 }
232 case osk.KTleft:
233 tabSeq := []byte{27,91,68}
234 seqErr := sendAnsiSeq(string(tabSeq))
235 if seqErr != 0 {
236 fmt.Println(seqErr)
237 }
238 case osk.KTright:
239 tabSeq := []byte{27,91,67}
240 seqErr := sendAnsiSeq(string(tabSeq))
241 if seqErr != 0 {
242 fmt.Println(seqErr)
243 }
244 case osk.KTpgUp:
245 tabSeq := []byte{27,91,53,126}
246 seqErr := sendAnsiSeq(string(tabSeq))
247 if seqErr != 0 {
248 fmt.Println(seqErr)
249 }
250 case osk.KTpgDn:
251 tabSeq := []byte{27,91,54,126}
252 seqErr := sendAnsiSeq(string(tabSeq))
253 if seqErr != 0 {
254 fmt.Println(seqErr)
255 }
256 // break L
257 default:
258 continue
259 }
260 prevType = k.KeyType
261 }
262 }
$ env GO111MODULE=off GOOS=linux GOARCH=arm CGO_ENABLED=1 CC=arm-kobo-linux-gnueabihf-gcc CXX=arm-kobo-linux-gnueabihf-g++ go build -o oskansi
$ arm-kobo-linux-gnueabihf-strip oskansi
Copy the ~/go/src/github.com/shermp/go-kobo-input/koboin-osk-sample/oskansi binary to the /mnt/onboard/.adds/koreader/scripts/ folder of your Kobo.
Note: we have renamed the app "oskansi", meaning on screen keyboard that sends keypresses as ANSI sequences.
Now, edit our /mnt/onboard/.adds/koreader/scripts/fbmenu.sh script (from Post #7 above) so we can call our oskansi keyboard app from NickelMenu:
# nano -l /mnt/onboard/.adds/koreader/scripts/fbmenu.sh
Code:
6 qndb -m dlgConfirmSetTitle "1-Stop agetty; 2-fbpadkb; 3-fbpadkbS; 4-fbpad; 5-fbpadS; 6-oskansi; 7-oskansiS; Select option (1-7):"
...
18 if [ "$num" == "1" ]; then
19 qndb -m mwcToast 500 "You selected 1-Stop agetty+fbpad"
20 fbcmd="/usr/bin/pkill agetty"
21 qndb -m mwcToast 200 "$fbcmd"
22 fberr=$($fbcmd 2>&1)
23 fbcmd="/usr/bin/pkill fbpad"
24 qndb -m mwcToast 200 "$fbcmd"
25 fberr=$($fbcmd 2>&1)
26 fbcmd="/usr/bin/pkill fbkeyboard"
27 qndb -m mwcToast 200 "$fbcmd"
28 fberr=$($fbcmd 2>&1)
29 fbcmd="/usr/bin/pkill oskansi"
30 qndb -m mwcToast 200 "$fbcmd"
31 fberr=$($fbcmd 2>&1)
...
58 elif [ "$num" == "6" ]; then
59 qndb -m mwcToast 1000 "You selected 6-oskansi"
60 export HOME="/mnt/onboard/.adds/koreader/"
61 cd "$HOME"
62 fbcmd="eval /mnt/onboard/.adds/koreader/scripts/fbpadkb /bin/sh 0</dev/tty1"
63 qndb -m mwcToast 1000 "$fbcmd"
64 fberr=$($fbcmd 2>&1) &
65 fbcmd="/mnt/onboard/.adds/koreader/scripts/oskansi"
66 qndb -m mwcToast 1000 "$fbcmd"
67 fberr=$($fbcmd 2>&1)
68 elif [ "$num" == "7" ]; then
69 qndb -m mwcToast 1000 "You selected 7-oskansiS"
70 export HOME="/mnt/onboard/.adds/koreader/"
71 cd "$HOME"
72 fbcmd="eval /mnt/onboard/.adds/koreader/scripts/fbpadkbS /bin/sh 0</dev/tty1"
73 qndb -m mwcToast 1000 "$fbcmd"
74 fberr=$($fbcmd 2>&1) &
75 fbcmd="/mnt/onboard/.adds/koreader/scripts/oskansi"
76 qndb -m mwcToast 1000 "$fbcmd"
77 fberr=$($fbcmd 2>&1)
78 else
79 qndb -m mwcToast 1000 "You selected an invalid option"
80 fi
81
82 qndb -m mwcToast 1000 "${fberr:-"Bye!"}"
***
To avoid keyboard taps activating a Nickel function:
From More tab (second tab from right at bottom of screen), select Activity.
If you are in SideloadedMode=true, then Activity tab is second from left at bottom of screen.
Oskansi keyboard can be started and stopped from NickelMenu and unlike fbkeyboard, doesn't require networking, as well as being much faster, due to sending ANSI codes with IOCTL calls instead of simulating input events with uinput.
The biggest issue might be that nothing appears on the fbpad screen due to e.g. oskansi sending codes to /dev/pts/0 but fbpad being on /dev/pts/1, but that shouldn't happen if you start oskansi before any other SSH session.
*Also pls see *UPDATE below for NickelMenu entry.
***
And don't forget to copy the keymap1-en_us.json, keymap2-en_us.json, and Roboto-Medium.ttf files to the /mnt/onboard/.adds/koreader/ folder of your Kobo.
Oskansi binary or fbmenu.sh script should be in /mnt/onboard/.adds/koreader/scripts/ folder.
If you're using the fbmenu.sh script above to launch oskansi, you need:
1) NickelDBus installed
https://www.mobileread.com/forums/sh...ht=nickel+dbus
2) A NickelMenu config entry like:
menu_item :main :fbmenu :cmd_spawn :quiet:exec /mnt/onboard/.adds/koreader/scripts/fbmenu.sh
chain_success :dbg_toast :Started fbmenu
chain_failure :dbg_toast :Error
If you're not using the fbmenu.sh script, you could try NickelMenu config entries like:
menu_item :main :fbpadkb :cmd_spawn :quiet :/mnt/onboard/.adds/koreader/scripts/fbpadkb /bin/sh 0</dev/tty1
chain_success :dbg_toast :Started fbpadkb
chain_failure :dbg_toast :Error starting fbpadkb
menu_item :main : oskansi :cmd_spawn :quiet:exec /mnt/onboard/.adds/koreader/scripts/oskansi
chain_success :dbg_toast :Started oskansi
chain_failure :dbg_toast :Error
*** UPDATE ***
* The NickelMenu command (if not using fbmenu.sh) for oskansi should be:
menu_item :main : oskansi :cmd_spawn :quiet:export HOME="/mnt/onboard/.adds/koreader/" && cd "$HOME" && /mnt/onboard/.adds/koreader/scripts/oskansi
This is because oskansi looks for the font and .json files in the current folder, which would be / by default, so it wouldn't find them if you put them in /mnt/onboard/.adds/koreader/ .
***
And grab the fbpadkb.bin binary from Post #6 above and rename it fbpadkb. You need to run this before oskansi.
You do not need the agetty hack from Post #7 above, and can comment out the line in /etc/udev/rules.d/90-fbpad.rules unless you are using fbpad with a USB keyboard.
Note that the CTL key in oskansi is a toggle so if you forget to retap it you may get funny characters.
Though it only works with alphabetic characters.
ALT key is a dummy key - maybe someone will want to activate it one day!
***
*UPDATE2*
Unfortunately, setting "EnableDebugServices=false" in [DeveloperSettings] in the /mnt/onboard/.kobo/Kobo/Kobo eReader.conf file, stopped oskansi keyboard from talking to fbpadkb.
Fortunately, you just need to run Dropbear or even telnet from NickelMenu beforehand, and then oskansi works again.
https://www.mobileread.com/forums/sh...d.php?t=353810
So it seems that:
-fbpad with USB keyboard needs agetty started and stopped in order to not stall.
-fbkeyboard needs WiFi on (or USB networking connected), though no hotspot connection needed, in order to not eventually freeze.
-oskansi needs either "EnableDebugServices=true" or dropbear/telnet started beforehand via NickelMenu in order to communicate with fbpad.
***
* Must rename oskansi.zip to oskansi.xz and extract with xz -d.