EK720/lime-juice

GitHub: EK720/lime-juice

PC-98 ADV 引擎游戏脚本的反编译和重编译工具的 C++ 移植版本,用于复古游戏研究与本地化翻译。

Stars: 0 | Forks: 0

# 注意:在我编写真正的 README 之前,此 README 只是 dantecsm 的 Juice fork 的直接副本。请耐心等待。 ## 用法 安装 [Racket](https://racket-lang.org/) 并运行以下命令: ``` raco exe -o juice.exe mes/juice.rkt ``` 然后参考 [README](./mes/README.md) ## 说明 `--engine ADV --extraop` 的反编译规则 ![graph1.png](https://static.pigsec.cn/wp-content/uploads/repos/2026/03/42c7140eb4103554.png) ![graph2.png](https://static.pigsec.cn/wp-content/uploads/repos/2026/03/7a2bb68d55103601.png) ![graph3.png](https://static.pigsec.cn/wp-content/uploads/repos/2026/03/286090b2ba103610.png) ## 部分脚本语法摘要
branch-var


(set-var A 0)

(branch-var A

(

    (/ (str "A is 0"))

    (/ (str "A is 1"))

    (/ (str "A is 2"))

    (/ (str "A is 3"))

))

相当于


A = 0

switch (A) {

    case 0:

    console.log("A is 0")

    break

    case 1:

    console.log("A is 1")

    break

    case 2:

    console.log("A is 2")

    break

    case 3:

    console.log("A is 3")

    break

}

branch-reg


(set-reg 80 #t)

(branch-reg 80

    ( 

        (/ (str "reg 80 is false")) 

        (/ (str "reg 80 is true"))

    )

)

相当于


reg[80] = true

if (reg[80] === false) {

    console.log("reg 80 is false")

} else {

    console.log("reg 80 is true")

}

if


(set-var A 1)

(set-var B 1)

(if ( 

    (// (? (= A 1)) (str "A is 1"))

    (// (? (= B 2)) (str "B is 2"))

    (// (nop@) (str "A is not 1 and B is not 2"))

))

相当于


A = 1

B = 1

if (A == 1) {

    console.log("A is 1")

} else if (B == 2) {

    console.log("B is 2")

} else {

    console.log("A is not 1 and B is not 2")

}

when


(set-var A 1)

(set-var B 1)

(proc 0)

(when (

    (//  (? (= A 1))

        (str "A = 1") (wait) (text-reset)

    )

    (//  (? (= A 0))

        (str "A = 0") (wait) (text-reset)

    )

    (//  (? (= B 1))

        (str "B = 1") (wait) (text-reset)

    )

))

相当于


A = 1

B = 1

if (A == 1) {

  console.log("A = 1")

}

if (A == 0) {

  console.log("A = 0")

}

if (B == 1) {

  console.log("B = 1")

}

seg-call `seg-call` 退出当前的 seg 块,并按顺序扫描文件中的后续 seg 块。它执行第一个条件匹配的 seg 块,然后返回到调用 seg-call 的位置继续执行。


(seg*

  (str "before seg call") (wait) (text-reset)

  (V = 3)

  (seg-call)

  (str "after seg call") (wait) (text-reset)

)

(seg (= V 2)

  (str "foo") (wait) (text-reset)

)

(seg*

  (str "bar") (wait) (text-reset)

)

(seg

  ...

)

输出:



before seg call

bar

after seg call

mes-load? `mes-load?` 将 `.mec` 文件加载到内存并执行它。 * `(mes-load? "file path" address)` 将 .mec 文件加载到指定的内存地址。 * `(mes-load? address)` 执行先前加载到该地址的 .mec 文件。


(mes-load? "b:¥mes¥system.mec" 0)

(mes-load? 0)

(mes-load? "b:¥mes¥y_a003c.mec" 4096)

(mes-load? 4096)

标签:ADV引擎, C++, PC-98, Racket, 云安全监控, 云资产清单, 代码移植, 反编译器, 复古游戏, 数据擦除, 文字冒险游戏, 日本游戏, 旧软件维护, 游戏汉化, 编译器, 脚本提取, 视听小说, 逆向工程, 静态分析