summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbigbass1997 <bigbass1997.website@gmail.com>2025-04-16 21:49:22 -0500
committerbigbass1997 <bigbass1997.website@gmail.com>2025-04-16 21:49:22 -0500
commit0fb57077015001af4063a20cf8db4ce4fbf7fffc (patch)
treed053b4cf6e8933007e42bd3d69d13f46b0dda56d
parentb7e8e3d85af8dd84ee9f1c523bdd3d986b64e3d3 (diff)
downloadtasd-0fb57077015001af4063a20cf8db4ce4fbf7fffc.tar.gz
tasd-0fb57077015001af4063a20cf8db4ce4fbf7fffc.zip
Move toward a release file structure. Remove outdated tools (will be readded to a different repo).
-rw-r--r--.github/workflows/static.yml4
-rw-r--r--CONTRIBUTING.md31
-rw-r--r--LICENSE.txt30
-rw-r--r--LICENSES.txt84
-rw-r--r--Makefile6
-rw-r--r--README.md54
-rw-r--r--TODO.md7
-rw-r--r--docs/latest/tasd-spec.html (renamed from docs/tasd-spec-0001/draft-tasd-spec-0001.html)2
-rw-r--r--docs/latest/tasd-spec.txt (renamed from docs/latest/draft-tasd-spec.txt)0
-rw-r--r--docs/tasd-spec-0001/tasd-spec-0001.html (renamed from docs/latest/draft-tasd-spec.html)2
-rw-r--r--docs/tasd-spec-0001/tasd-spec-0001.txt (renamed from docs/tasd-spec-0001/draft-tasd-spec-0001.txt)0
-rw-r--r--src/docs/tasd-spec-0001.xml (renamed from src/docs/draft-tasd-spec-0001.xml)0
-rw-r--r--tools/lua/tasd-fceux-dumpscript.lua437
-rwxr-xr-xtools/tasd2r08/tasd2r08.py137
14 files changed, 71 insertions, 723 deletions
diff --git a/.github/workflows/static.yml b/.github/workflows/static.yml
index 75ab96c..669cb2c 100644
--- a/.github/workflows/static.yml
+++ b/.github/workflows/static.yml
@@ -32,9 +32,9 @@ jobs:
- name: Checkout
uses: actions/checkout@v3
- name: Copy to index.html
- run: cp docs/latest/draft-tasd-spec.html docs/latest/index.html
+ run: cp docs/latest/tasd-spec.html docs/latest/index.html
- name: Copy to index.txt
- run: cp docs/latest/draft-tasd-spec.txt docs/latest/index.txt
+ run: cp docs/latest/tasd-spec.txt docs/latest/index.txt
- name: Setup Pages
uses: actions/configure-pages@v3
- name: Upload artifact
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 92a5978..fb7f024 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -1,6 +1,27 @@
-If you wish to contribute to this project, please be aware of and follow these rules.
+## Contribution
+If you wish to contribute to this project, please be aware of and follow these rules:
+* If you make an update to this repository, please update the `CHANGELOG.md` file accordingly. The style of the `CHANGELOG.md` file is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
+* If you edit the `.xml` file in `src/docs/`, please update the changelog at the bottom of the `.xml` file. The current style is `draft [{DraftNum}] - {Year}-{Month}-{Day} {Initials} {Description}` followed by a new line, where {DraftNum} is an incrementing 2 digit decimal number (can be 00-99), {Year} is the 4 digit year number, {Month} is the 2 digit month number, {Day} is the 2 digit day number, {Initials} are some initials to help differentiate changelog editors (Vi Grey's initials are **VG**, for example), and {Description} is a description of what you changed. (These instructions may change in the future.)
-* If you make an update to this repository, please update the `CHANGELOG.md` file accordingly. The style of the `CHANGELOG.md` file is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), although currently without version numbers added.
-* If you edit the `.xml` file in `src/docs/`, please update the changelog at the bottom of the `.xml` file. The current style is `draft [{DraftNum}] - {Year}-{Month}-{Day} {Initials} {Description}` followed by a new line, where {DraftNum} is an incrementing 2 digit decimal number (can be 00-99), {Year} is the 4 digit year number, {Month} is the 2 digit month number, {Day} is the 2 digit day number, {Initials} are some initials to help differentiate changelog editors (Vi Grey's initials are **VG**, for example), and {Description} is a description of what you changed.
-* If you edit the ``.xml` file in `src/docs/`, use `make clean; make; make contribution` at the root directory of this repository to create the new document files and automatically add them to `docs/latest/` and `docs/tasd-spec-{version}/`.
-* Please (for the moment at least) try to keep individual updates relatively single-subject in nature. For instance, if you're working on fixing a bunch of typos, try to make the update essentially only about fixing typos.
+## Building
+### Dependencies
+- xml2rfc
+- make
+
+`xml2rfc` can be installed from the Python3 PIP package manager (`pip3 install xml2rfc`). Some distributions may prefer you to install programs with pipx instead of pip, like Arch Linux (`pipx install xml2rfc`).
+
+Alternatively, if using linux, xml2rfc may be available in your distribution's repositories via your package manager. For instance, `sudo apt install xml2rfc` on Ubuntu/Debian, or `pacman -S xml2rfc` on Arch Linux (AUR).
+
+### Build (temporary instructions)
+From a terminal, go to the the main directory of this project (the directory this CONTRIBUTING.md file exists in). You can then build the HTML and TXT formatted documents with:
+```sh
+make documents
+```
+After building the documentation, you should find the exported `.html` and `.txt` files in the `build/docs/` directory.
+
+The source code for the documentation can be found in `src/docs/`. The xml2rfc vocabulary of the xml file is explained in [RFC 7991](https://www.rfc-editor.org/rfc/rfc7991).
+
+To copy the generated HTML and TXT files to the final `docs/` directory, run:
+```sh
+make contribution
+```
diff --git a/LICENSE.txt b/LICENSE.txt
new file mode 100644
index 0000000..11bfc8a
--- /dev/null
+++ b/LICENSE.txt
@@ -0,0 +1,30 @@
+TASD File Format Specification Version 1
+ Copyright (c) 2021-2025, Vi Grey, Bigbass, and rasteri
+
+ All rights reserved.
+
+ Redistribution and use of this documentation in source (XML format)
+ and/or "compiled" forms (TXT, PDF, HTML, etc), with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code (XML format) of this documentation
+ must retain the above copyright notice, this list of conditions,
+ and the following disclaimer in the documentation.
+
+ 2. Redistributions in compiled form (Converted to TXT, PDF, HTML,
+ and other formats) of this documentation must reproduce the above
+ copyright notice, this list of conditions, and the following
+ disclaimer in the documentation.
+
+ THIS DOCUMENTATION IS PROVIDED BY THE AUTHOR(S) "AS IS" AND ANY
+ EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ DOCUMENTATION, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/LICENSES.txt b/LICENSES.txt
deleted file mode 100644
index c93a1f9..0000000
--- a/LICENSES.txt
+++ /dev/null
@@ -1,84 +0,0 @@
-TASD File Format Specification Version 1
- Copyright (c) 2021-2025, Vi Grey, Bigbass, and rasteri
-
- All rights reserved.
-
- Redistribution and use of this documentation in source (XML format)
- and/or "compiled" forms (TXT, PDF, HTML, etc), with or without
- modification, are permitted provided that the following conditions
- are met:
-
- 1. Redistributions of source code (XML format) of this documentation
- must retain the above copyright notice, this list of conditions,
- and the following disclaimer in the documentation.
-
- 2. Redistributions in compiled form (Converted to TXT, PDF, HTML,
- and other formats) of this documentation must reproduce the above
- copyright notice, this list of conditions, and the following
- disclaimer in the documentation.
-
- THIS DOCUMENTATION IS PROVIDED BY THE AUTHOR(S) "AS IS" AND ANY
- EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE
- FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
- BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
- OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- DOCUMENTATION, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-
-tools/lua/tasd-fceux-dumpscript.lua
- Copyright (c) 2022, Vi Grey
- All rights reserved.
-
- Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions
- are met:
-
- 1. Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
- 2. Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
-
- THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
- FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- SUCH DAMAGE.
-
-
-tools/tasd2r08/tasd2r08.py
- Copyright (c) 2022, Vi Grey
- All rights reserved.
-
- Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions
- are met:
-
- 1. Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
- 2. Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
-
- THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
- FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- SUCH DAMAGE.
diff --git a/Makefile b/Makefile
index 58973e6..88b7049 100644
--- a/Makefile
+++ b/Makefile
@@ -1,4 +1,4 @@
-# Copyright (C) 2021-2022, Vi Grey and Bigbass
+# Copyright (C) 2021-2025, Vi Grey and Bigbass
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
@@ -23,9 +23,9 @@
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
# SUCH DAMAGE.
-DOC_NAME := draft-tasd-spec-0001
+DOC_NAME := tasd-spec-0001
VERSION_DOC_NAME := tasd-spec-0001
-LATEST_DOC_NAME := draft-tasd-spec
+LATEST_DOC_NAME := tasd-spec
CURRENTDIR := $(dir $(realpath $(firstword $(MAKEFILE_LIST))))
documents:
diff --git a/README.md b/README.md
index 00c4521..8b50bbf 100644
--- a/README.md
+++ b/README.md
@@ -1,8 +1,6 @@
-# **TASD File Format Specification And Tools**
+# TASD File Format Specification
-Specification and Tools for the Tool Assisted Speedrun Dump (TASD) interchange format
-
-<ins>**IMPORTANT**</ins> - This specification is in a DRAFT phase. Expect inaccuracies, typos, and considerable changes. Nothing is set in stone.
+Specification for the Tool Assisted Speedrun Dump (TASD) interchange format
## Description:
@@ -13,52 +11,16 @@ Packets of a given type can be used multiple times or completely omitted as need
While files generated by emulator dump scripts should provide as much information as possible, they may be unable to provide everything. Since packets are optional, the file can be expanded later with any additional data as desired. No intermediary file format is necessary.
-## **Reading the Specification Documentation**
-
-The specification documentation can be found at `docs/latest/draft-tasd-spec.html`, and `docs/latest/draft-tasd-0001.txt` and is presented in a format quite similar to IETF (Internet Engineering Task Force) RFC (Request For Comment) documents.
-
-
-## **Building the Specification Documentation**
-
-### Documentation Build Dependencies
-- xml2rfc
-
-All dependencies can be installed from the Python3 PIP package manager (`pip3 install xml2rfc`). Some distributions may prefer you to install programs with pipx instead of pip, like Arch Linux (`pipx install xml2rfc`).
-
-Alternatively, if using linux, xml2rfc may be available in your distribution's repositories via your package manager. For instance, `sudo apt install xml2rfc` on Ubuntu/Debian, or `pacman -S xml2rfc` on Arch Linux (AUR).
-
-### Build the Documentation
-From a terminal, go to the the main directory of this project (the directory this README.md file exists in). You can then build the HTML and TXT formatted documents with:
-```sh
-make documents
-```
-
-After building the documentation, you should find `draft-tasd-0001.html`, and `draft-tasd-0001.txt` in the `build/docs/` directory.
-
-The source code for the documentation can be found in `src/docs/draft-tasd-0001.xml`. The xml2rfc vocabulary of the xml file is explained in [RFC 7991](https://www.rfc-editor.org/rfc/rfc7991).
-
-To copy the generated HTML and TXT files to the final `docs/` directory, run:
-```sh
-make contribution
-```
-
-
-## Tools and Scripts
-
-Included in this repository is a small set of tools, which will hopefully grow to a larger set of tools over time.
-
-A lua script to dump a FCEUX TAS to a TASD file can be found at `tools/lua/tasd-fceux-dumpscript.lua`.
-
-A tool to convert a TASD file to an r08 file can be found at `tools/tasd2r08/tasd2r08.py`.
+## Reading the Documentation
-[TASD-Edit](https://github.com/bigbass1997/TASD-Edit) is a cross-platform, CLI-based editor for TASD files. Can create/edit TASD files, and import or export legacy formats: r08, r16m, and GBI.
+The specification can be found online at https://tasd.io/ or locally at `docs/latest/tasd-spec.html` and `docs/latest/tasd-spec.txt`. It is presented in a format quite similar to IETF (Internet Engineering Task Force) RFC (Request For Comment) documents.
-## Contributing
+## Contributing and Building
-If you wish to contribute to this project, please take a look at `CONTRIBUTING.md`
+If you wish to contribute to this project or would like to build it from source, please take a look at `CONTRIBUTING.md`.
-## Licenses
+## License
-To see the licenses of the specification documentation along with any included tools, please look at `LICENSE.txt`
+`LICENSE.txt` contains the license for the TASD specification.
diff --git a/TODO.md b/TODO.md
deleted file mode 100644
index 24778d2..0000000
--- a/TODO.md
+++ /dev/null
@@ -1,7 +0,0 @@
-List of things that would probably be good to add in the future
-
-- Add valid example `.tasd` files
-- Investigate moving related tools/scripts to a different repository (providing links will still be okay, but the actual tools should live elsewhere).
- - Add dump script support for more emulators and for more consoles
- - Add more tools that make creating or editing TASD files easier
-- Add packet examples to `src/docs/draft-tasd-spec-0001.xml` (can be added post-release)
diff --git a/docs/tasd-spec-0001/draft-tasd-spec-0001.html b/docs/latest/tasd-spec.html
index 9911d27..6f5f622 100644
--- a/docs/tasd-spec-0001/draft-tasd-spec-0001.html
+++ b/docs/latest/tasd-spec.html
@@ -31,7 +31,7 @@
wcwidth 0.2.5
weasyprint 61.1
-->
-<link href="/data/projects/tasd-spec/src/docs/draft-tasd-spec-0001.xml" rel="alternate" type="application/rfc+xml">
+<link href="/data/projects/tasd-spec/src/docs/tasd-spec-0001.xml" rel="alternate" type="application/rfc+xml">
<link href="#copyright" rel="license">
<style type="text/css">/*
diff --git a/docs/latest/draft-tasd-spec.txt b/docs/latest/tasd-spec.txt
index c845dab..c845dab 100644
--- a/docs/latest/draft-tasd-spec.txt
+++ b/docs/latest/tasd-spec.txt
diff --git a/docs/latest/draft-tasd-spec.html b/docs/tasd-spec-0001/tasd-spec-0001.html
index 9911d27..6f5f622 100644
--- a/docs/latest/draft-tasd-spec.html
+++ b/docs/tasd-spec-0001/tasd-spec-0001.html
@@ -31,7 +31,7 @@
wcwidth 0.2.5
weasyprint 61.1
-->
-<link href="/data/projects/tasd-spec/src/docs/draft-tasd-spec-0001.xml" rel="alternate" type="application/rfc+xml">
+<link href="/data/projects/tasd-spec/src/docs/tasd-spec-0001.xml" rel="alternate" type="application/rfc+xml">
<link href="#copyright" rel="license">
<style type="text/css">/*
diff --git a/docs/tasd-spec-0001/draft-tasd-spec-0001.txt b/docs/tasd-spec-0001/tasd-spec-0001.txt
index c845dab..c845dab 100644
--- a/docs/tasd-spec-0001/draft-tasd-spec-0001.txt
+++ b/docs/tasd-spec-0001/tasd-spec-0001.txt
diff --git a/src/docs/draft-tasd-spec-0001.xml b/src/docs/tasd-spec-0001.xml
index 49d2642..49d2642 100644
--- a/src/docs/draft-tasd-spec-0001.xml
+++ b/src/docs/tasd-spec-0001.xml
diff --git a/tools/lua/tasd-fceux-dumpscript.lua b/tools/lua/tasd-fceux-dumpscript.lua
deleted file mode 100644
index 628864c..0000000
--- a/tools/lua/tasd-fceux-dumpscript.lua
+++ /dev/null
@@ -1,437 +0,0 @@
--- Copyright (c) 2022, Vi Grey
--- All rights reserved.
---
--- Redistribution and use in source and binary forms, with or without
--- modification, are permitted provided that the following conditions
--- are met:
---
--- 1. Redistributions of source code must retain the above copyright
--- notice, this list of conditions and the following disclaimer.
--- 2. Redistributions in binary form must reproduce the above copyright
--- notice, this list of conditions and the following disclaimer in the
--- documentation and/or other materials provided with the distribution.
---
--- THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
--- ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
--- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
--- ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
--- FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
--- DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
--- OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
--- HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
--- LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
--- OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
--- SUCH DAMAGE.
-
-local MAGIC_NUMBER = 0x54415344
-local VERSION = 0x0001
-local G_KEYLEN = 0x02
-
-local CONSOLE_TYPE = 0x0001 -- Done
-local CONSOLE_REGION = 0x0002 -- Done
-local ROM_NAME = 0x0004 -- Done
-local EMULATOR_NAME = 0x0007 -- Done
-local DUMP_CREATED = 0x000b -- Done
-local DUMP_LAST_MODIFIED = 0x000c -- Done
-local TOTAL_FRAMES = 0x000d -- Done
-local RERECORDS = 0x000e -- Done
-local MEMORY_INIT = 0x0012 -- Done
-local GAME_IDENTIFIER = 0x0013 -- Done
-local PORT_CONTROLLER = 0x00f0 -- Done (More to handle later)
-local PORT_OVERREAD = 0x00f1 -- Done
-
-local NES_LATCH_FILTER = 0x0101 -- Done
-local NES_CLOCK_FILTER = 0x0102 -- Done
-
-local INPUT_CHUNK = 0xfe01 -- Done (More to handle later)
-local TRANSITION = 0xfe03 -- Done
-local LAG_FRAME_CHUNK = 0xfe04 -- Done
-
-local EXPERIMENTAL = 0xfffe
-
-local NES_STANDARD_CONTROLLER = 0x0101
-
-local moviePlaying = false
-local resetValueLast = 0x0000
-local afterPowerOn = false
-local lagCount = 0
-local resetTransitionPackets = ""
-local cpuCyclesLastFrame = 0
-local region = ""
-
-local tasdFile
-local lastController
-
-local nesControls = {"right", "left", "down", "up", "start", "select", "B", "A"}
-
--- Convert a non negative integer (number) to a byte string of size
--- byteLen. Returns a blank string if number is too large for byteLen
--- or if number is negative.
-function intToBytes(number, byteLen)
- local byteString = ""
- if (number < 0) then
- return byteString
- elseif (number >= (256 ^ byteLen)) then
- return byteString
- end
- for x = byteLen - 1, 0, -1 do
- byteString = byteString .. string.char(math.floor(number / 256 ^ x) % 256)
- end
- return byteString
-end
-
--- Get exponent of number
-function getExponent(number)
- return math.ceil(math.log(number + 1)/math.log(256))
-end
-
--- Create a packet byte string
-function makePacket(packetKey, packetPayload)
- local packetString = intToBytes(packetKey, G_KEYLEN)
- if packetString == "" then
- return packetString
- end
- local packetPayloadLen = string.len(packetPayload)
- local packetPayloadLenExponent = getExponent(packetPayloadLen)
- packetString = packetString .. intToBytes(packetPayloadLenExponent, 1)
- packetString = packetString .. intToBytes(packetPayloadLen, packetPayloadLenExponent)
- packetString = packetString .. packetPayload
- return packetString
-end
-
-function getConsoleTypePacket()
- local packetPayload = intToBytes(0x01, 1)
- return makePacket(CONSOLE_TYPE, packetPayload)
-end
-
-function getConsoleRegionPacket()
- local regionNumber = 3
- if (region == "NTSC") then
- regionNumber = 1
- elseif (region == "PAL") then
- regionNumber = 2
- end
- local packetPayload = intToBytes(regionNumber, 1)
- return makePacket(CONSOLE_REGION, packetPayload)
-end
-
-function getROMNamePacket()
- local packetPayload = rom.getfilename() .. ".nes"
- return makePacket(ROM_NAME, packetPayload)
-end
-
-function getMemoryInitPacket(dataType, device, required, name, data)
- local packetPayload = intToBytes(dataType, 1)
- packetPayload = packetPayload .. intToBytes(device, 2)
- packetPayload = packetPayload .. intToBytes(required, 1)
- packetPayload = packetPayload .. intToBytes(string.len(name), 1)
- packetPayload = packetPayload .. name
- packetPayload = packetPayload .. data
- return makePacket(MEMORY_INIT, packetPayload)
-end
-
-function getGameIdentifierPacket()
- local packetPayload = intToBytes(0x01, 1) -- Type is MD5
- packetPayload = packetPayload .. intToBytes(0x02, 1) -- Encoding is hex
- packetPayload = packetPayload .. intToBytes(0x00, 1) -- NLEN is 0
- packetPayload = packetPayload .. rom.gethash("md5")
- return makePacket(GAME_IDENTIFIER, packetPayload)
-end
-
-function getEmulatorNamePacket()
- local packetPayload = "fceux"
- return makePacket(EMULATOR_NAME, packetPayload)
-end
-
-function getDumpCreatedPacket(unixTimestamp)
- local packetPayload = intToBytes(unixTimestamp, 8)
- return makePacket(DUMP_CREATED, packetPayload)
-end
-
-function getDumpLastModifiedPacket(unixTimestamp)
- local packetPayload = intToBytes(unixTimestamp, 8)
- return makePacket(DUMP_LAST_MODIFIED, packetPayload)
-end
-
-function getTotalFramesPacket()
- local packetPayload = intToBytes(movie.length(), 4)
- return makePacket(TOTAL_FRAMES, packetPayload)
-end
-
-function getRerecordsPacket()
- local packetPayload = intToBytes(movie.rerecordcount(), 4)
- return makePacket(RERECORDS, packetPayload)
-end
-
--- Only supports standard controllers at the moment
-function getPortControllerPacket(playerCount, controllerType)
- local finishedPackets = ""
- for x = 1, playerCount, 1 do
- local packetPayload = intToBytes(x, 1)
- packetPayload = packetPayload .. intToBytes(controllerType, 2)
- finishedPackets = finishedPackets .. makePacket(PORT_CONTROLLER, packetPayload)
- end
- return finishedPackets
-end
-
-function getPortOverreadPacket(playerCount, controllerType)
- local finishedPackets = ""
- for x = 1, playerCount, 1 do
- local packetPayload = intToBytes(x, 1)
- packetPayload = packetPayload .. intToBytes(0x00, 1)
- finishedPackets = finishedPackets .. makePacket(PORT_OVERREAD, packetPayload)
- end
- return finishedPackets
-end
-
-
-function getNESLatchFilterPacket()
- local packetPayload = intToBytes(8000, 2)
- return makePacket(NES_LATCH_FILTER, packetPayload)
-end
-
-function getNESClockFilterPacket()
- local packetPayload = intToBytes(10, 1)
- return makePacket(NES_CLOCK_FILTER, packetPayload)
-end
-
-function getInputChunkPacket(player, inputs, controllerType)
- local payloadLen = 1
- if (controllerType == NES_STANDARD_CONTROLLER) then
- payloadLen = 1
- end
- local packetPayload = intToBytes(player, 1)
- packetPayload = packetPayload .. intToBytes(inputs, payloadLen)
- return makePacket(INPUT_CHUNK, packetPayload)
-end
-
-function getLagFrameChunkPacket()
- local packetPayload = intToBytes(movie.framecount() - lagCount, 4)
- packetPayload = packetPayload .. intToBytes(lagCount, 4)
- return makePacket(LAG_FRAME_CHUNK, packetPayload)
-end
-
-function getTransitionPacket()
- local packetPayload = intToBytes(0x01, 1)
- packetPayload = packetPayload .. intToBytes(0x00, 1)
- packetPayload = packetPayload .. intToBytes(movie.framecount(), 8)
- packetPayload = packetPayload .. intToBytes(0x01, 1)
- return makePacket(TRANSITION, packetPayload)
-end
-
-function getExperimentalPacket()
- local packetPayload = intToBytes(0x01, 1)
- return makePacket(EXPERIMENTAL, packetPayload)
-end
-
--- Get TASD file header (currently TASD\x00\x01\x02)
-function getTASDFileHeader()
- local header = intToBytes(MAGIC_NUMBER, 4)
- header = header .. intToBytes(VERSION, 2)
- header = header .. intToBytes(G_KEYLEN, 1)
- return header
-end
-
--- Begin dump by creating TASD file, writing initial data to it,
--- setting the emulator speed to maximum, and starting the movie
-function startDump()
- -- Movie has not been started since the lua script started
- setupTASDFile()
- tasdFile:write(getTASDFileHeader())
- tasdFile:write(getExperimentalPacket())
- tasdFile:write(getConsoleTypePacket())
- tasdFile:write(getROMNamePacket())
- tasdFile:write(getGameIdentifierPacket())
- tasdFile:write(getEmulatorNamePacket())
- tasdFile:write(getTotalFramesPacket())
- tasdFile:write(getRerecordsPacket())
- tasdFile:write(getPortControllerPacket(2, NES_STANDARD_CONTROLLER))
- tasdFile:write(getPortOverreadPacket(2))
- tasdFile:write(getNESLatchFilterPacket())
- tasdFile:write(getNESClockFilterPacket())
- -- Rest CPU cycle count to 0
- debugger.resetcyclescount()
- movie.playbeginning()
- emu.pause()
- -- Get CPU RAM and store it in TASD file
- storeInitialCPURAM()
- -- Get Cartridge Save RAM and store it in TASD file
- storeInitialSaveData()
- emu.unpause()
- moviePlaying = true
- print("Starting movie.\n")
- print("Replay (TASD) file will not be finished writing until the movie is " ..
- "finished.\n")
- emu.speedmode("maximum")
- setResetCallback()
-end
-
--- Set and update execution callback for when the 16-bit big-endian
--- address stored at 0xfffc-0xfffd is executed. This function is
--- called frequently because some NES cartridge mappers allow the
--- data at 0xfffc-0xfffd to be changed.
-function setResetCallback()
- resetValue = memory.readbyteunsigned(0xfffd) * 256
- resetValue = resetValue + memory.readbyteunsigned(0xfffc)
- if (resetValue ~= resetValueLast) then
- -- Value at reset vector (0xfffc-0xfffd) has changed
- unsetResetCallback()
- memory.registerexec(resetValue, detectReset)
- resetValueLast = resetValue
- end
-end
-
--- Unset the execution callback for when the 16-bit big-endian address
--- stored at 0xfffc-0xfffd is executed.
-function unsetResetCallback()
- memory.registerexec(resetValueLast, nil)
-end
-
--- Add console reset to list of reset transition packets. Ignores the
--- first detected RESET, as the initial console power-on triggers
--- this function as well
-function detectReset()
- if (afterPowerOn) then
- resetTransitionPackets = resetTransitionPackets .. getTransitionPacket()
- end
- afterPowerOn = true
-end
-
--- Some cleanup after the movie has closed, including setting the
--- emulator speed back to normal
-function finishMovie()
- emu.speedmode("normal")
- unsetResetCallback()
- moviePlaying = false
- movie.close()
- emu.registerafter(nil)
- print("Movie finished.\n")
-end
-
--- Finish writing the TASD file by writing the DUMP_CREATED,
--- DUMP_LAST_MODIFIED, and CONSOLE_REGION packets and closing the
--- TASD file.
-function finishTASDFile()
- local unixTimestamp = os.time(os.date("*t"))
- tasdFile:write(getDumpCreatedPacket(unixTimestamp))
- tasdFile:write(getDumpLastModifiedPacket(unixTimestamp))
- tasdFile:write(getConsoleRegionPacket())
- tasdFile:close()
- print("Replay (TASD) file finished.\n")
-end
-
--- Converts frame input for players 1 and 2 to an INPUT_CHUNK packet
--- and writes the INPUT_CHUNK packet to the TASD file
-function handleInputs()
- for i = 1, 2, 1 do
- local controls = joypad.get(i)
- local controllerInput = 0xff
- for x = 1, #nesControls do
- if (controls[nesControls[x]]) then
- controllerInput = bit.bxor(controllerInput, bit.lshift(1, x - 1))
- end
- end
- tasdFile:write(getInputChunkPacket(i, controllerInput, NES_STANDARD_CONTROLLER))
- end
-end
-
--- Single frame handling code. Also determines the NES console's
--- region based on the amount of CPU cycles between 2 adjacent
--- frames.
-function handleFrame()
- if (region == "") then
- local cpuCyclesNow = debugger.getcyclescount()
- local cpuCyclesDif = cpuCyclesNow - cpuCyclesLastFrame
- cyclesLastFrame = cpuCyclesNow
- if (cpuCyclesDif < 36000 and cpuCyclesDif > 29000) then
- if (cpuCyclesDif < 31000) then
- -- Region is NTSC (~29780.5 cycles per frame)
- region = "NTSC"
- elseif (cpuCyclesDif > 34000) then
- -- Region is Dendy (~35464 cycles per frame)
- region = "Dendy"
- else
- -- Region is PAL (~33247.5 cycles per frame)
- region = "PAL"
- end
- end
- else
- end
- if (emu.lagged()) then
- lagCount = lagCount + 1
- else
- if (lagCount > 0) then
- tasdFile:write(getLagFrameChunkPacket())
- end
- lagCount = 0
- handleInputs()
- end
-end
-
-
--- Create TASD File from ROM file name
-function setupTASDFile()
- local fileName = movie.name():match("(.+)%..+$")
- local tasdFileName = fileName .. ".tasd"
- tasdFile = io.open(tasdFileName, "wb+")
- print("Created replay (TASD) file " .. tasdFileName .. "\n")
-end
-
--- Store initial CPU RAM (0x0000 - 0x07FF) in TASD file
-function storeInitialCPURAM()
- print("Storing initial CPU RAM")
- local cpuRAMData = ""
- for i = 0x0000, 0x07ff, 1 do
- cpuRAMData = cpuRAMData .. string.char(memory.readbyte(i))
- end
- tasdFile:write(getMemoryInitPacket(0xff, 0x0101, 0, "", cpuRAMData))
- print("Finished storing initial CPU RAM\n")
-end
-
--- Store initial cartridge save data (0x6000 - 0x7FFF) in TASD file
-function storeInitialSaveData()
- if (bit.band(rom.readbyte(6), 2)) then
- print("Storing initial save data")
- local saveRAMData = ""
- for i = 0x6000, 0x7fff, 1 do
- saveRAMData = saveRAMData .. string.char(memory.readbyte(i))
- end
- tasdFile:write(getMemoryInitPacket(0xff, 0x0102, 0, "", saveRAMData))
- print("Finished storing initial save data\n")
- end
-end
-
--- General handler for dumping TASD file (this of this essentially as
--- the main() function)
-function gameHandler()
- if (movie.active()) then
- -- Movie is loaded/active
- if (moviePlaying == false) then
- startDump()
- else
- if (movie.framecount() > movie.length()) then
- -- End of movie
- finishTASDFile()
- finishMovie()
- print("If you wish to dump another TAS, you will need to run this script again\n")
- elseif (movie.framecount() > 1) then
- setResetCallback()
- handleFrame()
- -- End of frame
- tasdFile:write(resetTransitionPackets)
- resetTransitionPackets = ""
- end
- end
- elseif (moviePlaying == true) then
- -- Error handling movie
- finishMovie()
- print("Error handling movie. Try playing the movie again.\n")
- end
-end
-
-if (movie.active() == false) then
- print("Select a movie file\n")
-end
-
-emu.registerafter(gameHandler)
-
diff --git a/tools/tasd2r08/tasd2r08.py b/tools/tasd2r08/tasd2r08.py
deleted file mode 100755
index f078840..0000000
--- a/tools/tasd2r08/tasd2r08.py
+++ /dev/null
@@ -1,137 +0,0 @@
-#!/usr/bin/env python3
-
-# Copyright (c) 2022, Vi Grey
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions
-# are met:
-#
-# 1. Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-# 2. Redistributions in binary form must reproduce the above copyright
-# notice, this list of conditions and the following disclaimer in the
-# documentation and/or other materials provided with the distribution.
-#
-# THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
-# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-# ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
-# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-# SUCH DAMAGE.
-
-
-import sys
-import os
-
-def print_help():
- print("Usage: python3 tasd2r08 <input file path> <output file path>\r\n" +
- "Example: python3 tasd2r08 ~/TAS/smb.tasd /tmp/smb.r08")
-
-def handle_packet(offset):
- init_offset = offset
- global infile_data
- global infile_len
- global tasd_g_len
- packet_type = int.from_bytes(infile_data[offset: offset + tasd_g_len],
- byteorder="big", signed=False)
- offset += tasd_g_len
- if offset >= infile_len:
- return (1, b"", offset)
- packet_exp = infile_data[offset]
- offset += 1
- if offset + packet_exp >= infile_len:
- return (1, b"", offset)
- packet_len = int.from_bytes(infile_data[offset: offset + packet_exp],
- byteorder="big", signed=False)
- offset += packet_exp
- if offset + packet_len > infile_len:
- return (1, b"", offset)
- if packet_type != 0xfe01:
- offset += packet_len
- return (1, b"", offset)
- return (infile_data[offset],
- infile_data[offset + 1: offset + packet_len],
- offset + packet_len)
-
-def main():
- global infile_data
- global infile_len
- global tasd_g_len
- if len(sys.argv) != 3:
- print_help()
- sys.exit(0)
- infile_name = sys.argv[1]
- outfile_name = sys.argv[2]
- outfile_data = b""
- try:
- infile = open(infile_name, "rb")
- infile_data = infile.read()
- infile.close()
- except:
- print("Unable to read input file " + infile_name)
- print("Exiting")
- sys.exit(1)
- if os.path.exists(outfile_name):
- print("File " + outfile_name + " already exists")
- reply = input("Overwrite file? [yes/No] ").lower()
- if reply != "yes" and reply != "y":
- print("Canceling conversion. No files were written to.")
- print("Exiting")
- sys.exit(1)
- infile_len = len(infile_data)
- if infile_len < 7:
- print("Input file is not a TASD file (File not long enough to be a" +
- "TASD file)")
- print("Exiting")
- sys.exit(1)
- if infile_data[0:4] != b"TASD":
- print("Input file is not a TASD file (Invalid file header)")
- print("Exiting")
- sys.exit(1)
- tasd_version = int.from_bytes(infile_data[4:6], byteorder="big",
- signed=False)
- tasd_g_len = infile_data[6]
- if tasd_version != 1:
- print("Input file is not using a valid TASD file version")
- print("Exiting")
- sys.exit(1)
- # set infile_offset to after TASD file header, which is 7 bytes long
- infile_offset = 7
- while infile_offset + tasd_g_len < infile_len:
- (port, data, infile_offset) = handle_packet(infile_offset)
- if len(data) > 0:
- r08Data[port] += data
- r08MaxLen = 0
- for port in r08Data:
- dataLen = len(r08Data[port])
- if dataLen > r08MaxLen:
- r08MaxLen = dataLen
- for port in r08Data:
- dataLen = len(r08Data[port])
- if dataLen < r08MaxLen:
- r08Data[port] += b"\xff" * (r08MaxLen - dataLen)
- for offset in range(r08MaxLen):
- for port in sorted(r08Data):
- outfile_data += (r08Data[port][offset]^0xFF).to_bytes(1, "big")
- try:
- outfile = open(outfile_name, "wb")
- outfile.write(outfile_data)
- outfile.close()
- except:
- print("Unable to write output file " + infile_name)
- print("Exiting")
- sys.exit(1)
- print("Finished writing " + outfile_name)
-
-infile_data = b""
-infile_len = 0
-tasd_g_len = 1
-r08Data = {1: b"", 2: b""}
-if __name__ == "__main__":
- main()