mirror of
https://github.com/BertoldVdb/ms-tools.git
synced 2025-12-10 07:44:46 +01:00
Initial attempt at adding some functions to MS213x firmware
This commit is contained in:
parent
9866c7b404
commit
162cc22d62
15 changed files with 391 additions and 0 deletions
5
ms213x_patch/asm/asm.sh
Executable file
5
ms213x_patch/asm/asm.sh
Executable file
|
|
@ -0,0 +1,5 @@
|
||||||
|
as31 -Fbin init.asm
|
||||||
|
as31 -Fbin hook.asm
|
||||||
|
as31 -Fbin finishf660.asm
|
||||||
|
as31 -Fbin finishsig.asm
|
||||||
|
as31 -Fbin readinfo.asm
|
||||||
36
ms213x_patch/asm/finishf660.asm
Normal file
36
ms213x_patch/asm/finishf660.asm
Normal file
|
|
@ -0,0 +1,36 @@
|
||||||
|
INC DPTR
|
||||||
|
MOVX @DPTR, A
|
||||||
|
|
||||||
|
MOV DPTR, #0x7b10
|
||||||
|
MOVX A, @DPTR
|
||||||
|
MOV R7, A
|
||||||
|
|
||||||
|
INC DPTR
|
||||||
|
MOVX A, @DPTR
|
||||||
|
MOV R6, A
|
||||||
|
|
||||||
|
INC DPTR
|
||||||
|
MOVX A, @DPTR
|
||||||
|
MOV R5, A
|
||||||
|
|
||||||
|
INC DPTR
|
||||||
|
MOVX A, @DPTR
|
||||||
|
MOV R4, A
|
||||||
|
|
||||||
|
MOV DPTR, #0xf660
|
||||||
|
MOV A, R7
|
||||||
|
MOVX @DPTR, A
|
||||||
|
|
||||||
|
INC DPTR
|
||||||
|
MOV A, R6
|
||||||
|
MOVX @DPTR, A
|
||||||
|
|
||||||
|
INC DPTR
|
||||||
|
MOV A, R5
|
||||||
|
MOVX @DPTR, A
|
||||||
|
|
||||||
|
INC DPTR
|
||||||
|
MOV A, R4
|
||||||
|
MOVX @DPTR, A
|
||||||
|
|
||||||
|
RET
|
||||||
1
ms213x_patch/asm/finishf660.bin
Normal file
1
ms213x_patch/asm/finishf660.bin
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
Јрђ{аяЈаюЈаэЈаьђц`прЈорЈнрЈмр"
|
||||||
7
ms213x_patch/asm/finishsig.asm
Normal file
7
ms213x_patch/asm/finishsig.asm
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
ORL A, R7
|
||||||
|
|
||||||
|
MOV DPTR, #0x7b14
|
||||||
|
MOVX @DPTR, A
|
||||||
|
|
||||||
|
MOV R7, A
|
||||||
|
RET
|
||||||
1
ms213x_patch/asm/finishsig.bin
Normal file
1
ms213x_patch/asm/finishsig.bin
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
O<EFBFBD>{đ˙"
|
||||||
82
ms213x_patch/asm/hook.asm
Normal file
82
ms213x_patch/asm/hook.asm
Normal file
|
|
@ -0,0 +1,82 @@
|
||||||
|
hookRun:
|
||||||
|
MOV DPTR, #0x12b3
|
||||||
|
|
||||||
|
MOVX A, @DPTR
|
||||||
|
XRL A, R0
|
||||||
|
JNZ hookRet
|
||||||
|
|
||||||
|
LCALL hookWork
|
||||||
|
|
||||||
|
MOV DPTR, #0x12b3+1
|
||||||
|
MOVX @DPTR, A
|
||||||
|
INC DPTR
|
||||||
|
MOV A, R2
|
||||||
|
MOVX @DPTR, A
|
||||||
|
INC DPTR
|
||||||
|
MOV A, R3
|
||||||
|
MOVX @DPTR, A
|
||||||
|
INC DPTR
|
||||||
|
MOV A, R4
|
||||||
|
MOVX @DPTR, A
|
||||||
|
INC DPTR
|
||||||
|
MOV A, R5
|
||||||
|
MOVX @DPTR, A
|
||||||
|
INC DPTR
|
||||||
|
MOV A, R6
|
||||||
|
MOVX @DPTR, A
|
||||||
|
INC DPTR
|
||||||
|
MOV A, R7
|
||||||
|
MOVX @DPTR, A
|
||||||
|
MOV DPTR, #0x12b3
|
||||||
|
MOV A, #0xFF
|
||||||
|
RLC A
|
||||||
|
MOVX @DPTR, A
|
||||||
|
|
||||||
|
SETB EA
|
||||||
|
|
||||||
|
hookRet:
|
||||||
|
RET
|
||||||
|
|
||||||
|
hookWork:
|
||||||
|
CLR EA
|
||||||
|
|
||||||
|
MOV DPTR, #0x12b3+1
|
||||||
|
MOVX A, @DPTR
|
||||||
|
MOV 1, A
|
||||||
|
|
||||||
|
INC DPTR
|
||||||
|
MOVX A, @DPTR
|
||||||
|
MOV 0, A
|
||||||
|
|
||||||
|
PUSH 0
|
||||||
|
PUSH 1
|
||||||
|
|
||||||
|
INC DPTR
|
||||||
|
MOVX A, @DPTR
|
||||||
|
MOV R3, A
|
||||||
|
|
||||||
|
INC DPTR
|
||||||
|
MOVX A, @DPTR
|
||||||
|
MOV R4, A
|
||||||
|
|
||||||
|
INC DPTR
|
||||||
|
MOVX A, @DPTR
|
||||||
|
MOV R5, A
|
||||||
|
|
||||||
|
INC DPTR
|
||||||
|
MOVX A, @DPTR
|
||||||
|
MOV R6, A
|
||||||
|
|
||||||
|
INC DPTR
|
||||||
|
MOVX A, @DPTR
|
||||||
|
MOV R7, A
|
||||||
|
|
||||||
|
RRC A
|
||||||
|
MOV A, R7
|
||||||
|
|
||||||
|
MOV DPH, R3
|
||||||
|
MOV DPL, R4
|
||||||
|
|
||||||
|
RET ;Call address in HID+1
|
||||||
|
|
||||||
|
|
||||||
BIN
ms213x_patch/asm/hook.bin
Normal file
BIN
ms213x_patch/asm/hook.bin
Normal file
Binary file not shown.
18
ms213x_patch/asm/init.asm
Normal file
18
ms213x_patch/asm/init.asm
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
; Tell host about the existence of this patch
|
||||||
|
|
||||||
|
MOV DPTR, #0x7B00
|
||||||
|
MOV A, #'B'
|
||||||
|
MOVX @DPTR, A
|
||||||
|
INC DPTR
|
||||||
|
MOV A, #'V'
|
||||||
|
MOVX @DPTR, A
|
||||||
|
INC DPTR
|
||||||
|
MOV A, #'D'
|
||||||
|
MOVX @DPTR, A
|
||||||
|
INC DPTR
|
||||||
|
MOV A, #'B'
|
||||||
|
MOVX @DPTR, A
|
||||||
|
INC DPTR
|
||||||
|
CLR A
|
||||||
|
MOVX @DPTR, A
|
||||||
|
RET
|
||||||
BIN
ms213x_patch/asm/init.bin
Normal file
BIN
ms213x_patch/asm/init.bin
Normal file
Binary file not shown.
26
ms213x_patch/asm/readinfo.asm
Normal file
26
ms213x_patch/asm/readinfo.asm
Normal file
|
|
@ -0,0 +1,26 @@
|
||||||
|
; Resolution info
|
||||||
|
MOV DPTR, #0x7b10
|
||||||
|
MOVX A, @DPTR
|
||||||
|
MOV R2, A
|
||||||
|
|
||||||
|
INC DPTR
|
||||||
|
MOVX A, @DPTR
|
||||||
|
MOV R3, A
|
||||||
|
|
||||||
|
INC DPTR
|
||||||
|
MOVX A, @DPTR
|
||||||
|
MOV R4, A
|
||||||
|
|
||||||
|
INC DPTR
|
||||||
|
MOVX A, @DPTR
|
||||||
|
MOV R5, A
|
||||||
|
|
||||||
|
; Signal info
|
||||||
|
INC DPTR
|
||||||
|
MOVX A, @DPTR
|
||||||
|
|
||||||
|
; Frame counter
|
||||||
|
MOV R6, 0x29
|
||||||
|
MOV R7, 0x28
|
||||||
|
|
||||||
|
RET
|
||||||
1
ms213x_patch/asm/readinfo.bin
Normal file
1
ms213x_patch/asm/readinfo.bin
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
<EFBFBD>{את£א<C2A3>£א<C2A3>£א£א®)¯("
|
||||||
48
ms213x_patch/main.go
Normal file
48
ms213x_patch/main.go
Normal file
|
|
@ -0,0 +1,48 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/binary"
|
||||||
|
"flag"
|
||||||
|
"log"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"github.com/BertoldVdb/ms-tools/mshal/ms213x"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
input := flag.String("input", "", "Input filename")
|
||||||
|
output := flag.String("output", "/tmp/modified.bin", "Output filename")
|
||||||
|
flag.Parse()
|
||||||
|
|
||||||
|
in, err := os.ReadFile(*input)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalln("Failed to open file:", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := ms213x.CheckImage(in); err != nil {
|
||||||
|
log.Fatalln("Failed to parse image:", in)
|
||||||
|
}
|
||||||
|
|
||||||
|
clen := binary.BigEndian.Uint16(in[2:])
|
||||||
|
code := in[0x30:]
|
||||||
|
code = code[:clen]
|
||||||
|
|
||||||
|
code, err = patch(code)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalln("Failed to patch code:", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
out := make([]byte, 0x30, 0x30+len(code)+4)
|
||||||
|
copy(out, in)
|
||||||
|
binary.BigEndian.PutUint16(out[2:], uint16(len(code)))
|
||||||
|
|
||||||
|
out = append(out, code...)
|
||||||
|
out = binary.BigEndian.AppendUint32(out, 0)
|
||||||
|
ms213x.FixImage(out)
|
||||||
|
|
||||||
|
os.WriteFile("/tmp/modcode.bin", code, 0644)
|
||||||
|
|
||||||
|
if err := os.WriteFile(*output, out, 0644); err != nil {
|
||||||
|
log.Fatalln("Failed to write output:", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
ms213x_patch/ms213x_patch
Executable file
BIN
ms213x_patch/ms213x_patch
Executable file
Binary file not shown.
122
ms213x_patch/patch.go
Normal file
122
ms213x_patch/patch.go
Normal file
|
|
@ -0,0 +1,122 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/sha256"
|
||||||
|
"encoding/binary"
|
||||||
|
"encoding/hex"
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
|
||||||
|
_ "embed"
|
||||||
|
)
|
||||||
|
|
||||||
|
type patcher struct {
|
||||||
|
image []byte
|
||||||
|
|
||||||
|
hookOffset uint16
|
||||||
|
}
|
||||||
|
|
||||||
|
//go:embed asm/init.bin
|
||||||
|
var patchInit []byte
|
||||||
|
|
||||||
|
//go:embed asm/hook.bin
|
||||||
|
var patchHook []byte
|
||||||
|
|
||||||
|
//go:embed asm/finishf660.bin
|
||||||
|
var patchFinishf660 []byte
|
||||||
|
|
||||||
|
//go:embed asm/finishsig.bin
|
||||||
|
var patchFinishSig []byte
|
||||||
|
|
||||||
|
//go:embed asm/readinfo.bin
|
||||||
|
var patchReadInfo []byte
|
||||||
|
|
||||||
|
func (p *patcher) addCode(code []byte) uint16 {
|
||||||
|
offs := len(p.image)
|
||||||
|
p.image = append(p.image, code...)
|
||||||
|
return uint16(offs)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *patcher) detourCall(offset uint16, dest uint16) {
|
||||||
|
a := p.image[offset]
|
||||||
|
if a != 0x02 && a != 0x12 {
|
||||||
|
panic("Not LJMP or LCALL")
|
||||||
|
}
|
||||||
|
|
||||||
|
var code [6]byte
|
||||||
|
code[0] = 0x12 /* LCALL */
|
||||||
|
binary.BigEndian.PutUint16(code[1:], dest)
|
||||||
|
|
||||||
|
code[3] = 0x02 /* LJMP */
|
||||||
|
copy(code[4:], p.image[offset+1:]) /* Copy original address */
|
||||||
|
|
||||||
|
binary.BigEndian.PutUint16(p.image[offset+1:], p.addCode(code[:]))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *patcher) createHook(cmd uint8) uint16 {
|
||||||
|
return p.addCode([]byte{
|
||||||
|
0x78, cmd,
|
||||||
|
0x02, byte(p.hookOffset >> 8), byte(p.hookOffset),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *patcher) replaceJump(offset, dest uint16) {
|
||||||
|
p.image[offset] = 0x02
|
||||||
|
binary.BigEndian.PutUint16(p.image[offset+1:], dest)
|
||||||
|
}
|
||||||
|
|
||||||
|
func patch(in []byte) ([]byte, error) {
|
||||||
|
/* Check if it is a file we know how to handle */
|
||||||
|
hash := sha256.Sum256(in)
|
||||||
|
hashStr := hex.EncodeToString(hash[:])
|
||||||
|
if hashStr != "cc67f79a043da85dc8e6688a22111ade626e519e1ab549f110b3a06308190047" {
|
||||||
|
return nil, fmt.Errorf("code hash %s is not supported", hashStr)
|
||||||
|
}
|
||||||
|
|
||||||
|
p := patcher{
|
||||||
|
image: in,
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Add init code */
|
||||||
|
p.detourCall(0x4d48, p.addCode(patchInit))
|
||||||
|
|
||||||
|
/* Add hook code and update its internal jump */
|
||||||
|
p.hookOffset = p.addCode(patchHook)
|
||||||
|
binary.BigEndian.PutUint16(p.image[p.hookOffset+8:], binary.BigEndian.Uint16(p.image[p.hookOffset+8:])+p.hookOffset)
|
||||||
|
|
||||||
|
/* Add hook entry to main loop */
|
||||||
|
p.detourCall(0x4d70, p.createHook(0xEF)) /* Not in IRQ, but handled the same as the other USB commands */
|
||||||
|
|
||||||
|
/* Add 0xEE, remove result codes 0xFF and 0xFE which are legitimate commands (function unclear, can still call them
|
||||||
|
* via hook if needed) */
|
||||||
|
table, dflt := p.jumptableParse(0x1d9c)
|
||||||
|
var newTable []jumptableEntry
|
||||||
|
needInsert := true
|
||||||
|
for _, b := range table {
|
||||||
|
if b.Key > 0xEE && needInsert {
|
||||||
|
needInsert = false
|
||||||
|
newTable = append(newTable, jumptableEntry{
|
||||||
|
Key: 0xEE,
|
||||||
|
Address: p.createHook(0xEE),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
if b.Key >= 0xFE {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
newTable = append(newTable, b)
|
||||||
|
}
|
||||||
|
p.jumptableWrite(0x1d9c, newTable, dflt)
|
||||||
|
|
||||||
|
/* Write 0xF660 also to safe place (0x7b10) */
|
||||||
|
binary.BigEndian.PutUint16(p.image[0xbbb3:], 0x7b10)
|
||||||
|
binary.BigEndian.PutUint16(p.image[0xbbbf:], 0x7b12)
|
||||||
|
p.replaceJump(0xbbc3, p.addCode(patchFinishf660))
|
||||||
|
|
||||||
|
/* Write signal info to safe place (0x7b14) */
|
||||||
|
p.replaceJump(0xe9c6, p.addCode(patchFinishSig))
|
||||||
|
|
||||||
|
/* Finally, add read results function */
|
||||||
|
log.Printf("ReadInfo Offset: %02x", p.addCode(patchReadInfo))
|
||||||
|
|
||||||
|
return p.image, nil
|
||||||
|
}
|
||||||
44
ms213x_patch/patch_jumptable.go
Normal file
44
ms213x_patch/patch_jumptable.go
Normal file
|
|
@ -0,0 +1,44 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import "encoding/binary"
|
||||||
|
|
||||||
|
type jumptableEntry struct {
|
||||||
|
Key uint8
|
||||||
|
Address uint16
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *patcher) jumptableParse(offset uint16) ([]jumptableEntry, uint16) {
|
||||||
|
var results []jumptableEntry
|
||||||
|
|
||||||
|
lastKey := -1
|
||||||
|
for {
|
||||||
|
addr := binary.BigEndian.Uint16(p.image[offset:])
|
||||||
|
offset += 2
|
||||||
|
if addr > 0 {
|
||||||
|
key := int(p.image[offset])
|
||||||
|
offset++
|
||||||
|
|
||||||
|
if key < lastKey {
|
||||||
|
panic("Parse error")
|
||||||
|
}
|
||||||
|
lastKey = key
|
||||||
|
|
||||||
|
results = append(results, jumptableEntry{
|
||||||
|
Key: uint8(key),
|
||||||
|
Address: addr,
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
return results, binary.BigEndian.Uint16(p.image[offset:])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *patcher) jumptableWrite(offset uint16, entries []jumptableEntry, dflt uint16) {
|
||||||
|
for _, m := range entries {
|
||||||
|
binary.BigEndian.PutUint16(p.image[offset:], m.Address)
|
||||||
|
p.image[offset+2] = m.Key
|
||||||
|
offset += 3
|
||||||
|
}
|
||||||
|
binary.BigEndian.PutUint16(p.image[offset:], 0)
|
||||||
|
binary.BigEndian.PutUint16(p.image[offset+2:], dflt)
|
||||||
|
}
|
||||||
Loading…
Add table
Reference in a new issue