#!/bin/sh #|-*- mode:lisp -*-|# #| exec ros -Q -- $0 "$@" |# (progn ;;init forms (ros:ensure-asdf) #+quicklisp (ql:quickload '(:plump :uiop :trivia :clss :iterate :alexandria) :silent t) ) (defpackage :ecuflash-romraider (:use :cl :plump :trivia :iterate :alexandria)) (in-package :ecuflash-romraider) (defvar *root*) (defvar *rom*) (defun rename-attribute (node attr-from attr-to &optional (converter #'identity)) (multiple-value-bind (value found) (attribute node attr-from) (when found (remove-attribute node attr-from) (setf (attribute node attr-to) (funcall converter value))))) ;; dtd at https://github.com/RomRaider/RomRaider/blob/master/ecu_defs.dtd --- is hugely outdated (defun transform-scaling (table) (let* ((scaling-id (attribute table "scaling")) (scaling (first-elt (clss:select (format nil "scaling[name=~a]" scaling-id) *rom*)))) (rename-attribute scaling "toexpr" "expression" (lambda (original) (match original ;; convert lambda into A/F ("1/(1+(x/100))" "14.7/(1+(x/100))") (_ original)))) (rename-attribute scaling "frexpr" "to_byte" (lambda (original) (match original ;; convert lambda into A/F ("((1/x)-1)*100" "(14.7/x-1)*100") (_ original)))) (rename-attribute scaling "format" "format" (lambda (original) (ematch original ;; convert lambda into A/F ("%0.3f" "0.00") ("%d" "0")))) (setf (attribute table "storagetype") (attribute scaling "storagetype")) (remove-attribute scaling "storagetype") (remove-attribute scaling "name") (remove-attribute table "scaling") (setf (values (attribute scaling "fineincrement") (attribute scaling "coarseincrement")) (if (attribute scaling "inc") (values (princ-to-string (* 0.1 (read-from-string (attribute scaling "inc")))) (attribute scaling "inc")) (if (equal "0" (attribute scaling "format")) (values "1" "5") (values "0.1" "1.0")))) (remove-child scaling) (append-child table scaling) scaling)) (defun to-capital-hex (original) (format nil "0x~:@(~a~)" original)) (defun transform-1d (table) (rename-attribute table "level" "userlevel") (rename-attribute table "address" "storageaddress" #'to-capital-hex) (transform-scaling table) (setf (attribute table "sizey") "1")) (defun transform-2d (table) (rename-attribute table "level" "userlevel") (rename-attribute table "address" "storageaddress" #'to-capital-hex) (remove-attribute table "elements") (transform-scaling table) (let ((y-axis (first-elt (clss:select "table[type=Y Axis]" table)))) (rename-attribute y-axis "address" "storageaddress" #'to-capital-hex) (setf (attribute table "sizey") (attribute y-axis "elements")) (transform-scaling y-axis))) (defun transform-3d (table) (rename-attribute table "level" "userlevel") (rename-attribute table "address" "storageaddress" (lambda (original) (format nil "0x~:@(~a~)" original))) (remove-attribute table "elements") (transform-scaling table) (let ((x-axis (first-elt (clss:select "table[type=X Axis]" table))) (y-axis (first-elt (clss:select "table[type=Y Axis]" table)))) (when (equal (attribute table "swapxy") "true") (remove-attribute table "swapxy") (setf (attribute x-axis "type") "Y Axis") (setf (attribute y-axis "type") "X Axis") (rotatef x-axis y-axis)) (setf (attribute table "sizex") (attribute x-axis "elements") (attribute table "sizey") (attribute y-axis "elements")) (rename-attribute x-axis "address" "storageaddress" #'to-capital-hex) (rename-attribute y-axis "address" "storageaddress" #'to-capital-hex) (transform-scaling x-axis) (transform-scaling y-axis))) (defun transform-rom (*rom*) (map nil #'transform-1d (clss:select "[type=1D]" *rom*)) (map nil #'transform-2d (clss:select "[type=2D]" *rom*)) (map nil #'transform-3d (clss:select "[type=3D]" *rom*))) (defun transform (*root*) (map nil #'transform-rom (clss:select "rom" *root*)) *root*) (defun main (in out &rest argv) (declare (ignorable argv)) (uiop:with-input-file (sin in) (uiop:with-output-file (sout out :if-exists :supersede :if-does-not-exist :create) (serialize (transform (parse sin)) sout)))) ;;; vim: set ft=lisp lisp: