Back to Page
Revision 39 (current)
Edited by adelikat on 1/2/2022 8:14 PM
I'm here because TASing combines three big facets of my life: video games, computer science, and obsessive compulsive behavior. Sometimes I encode videos.
!!! TAS Ideas
* PSX
** Soul of the Samurai
** Delta Force: Urban Warfare
** Deception 3: Dark Delusion
** BRAHMA Force: The Assault on Beltlogger 9
** Tunnel B1
** Future Cop: LAPD
** Silent Bomber
** Tenchu (Shinobi-Gaisen?) GM%
** Jumping Flash! (Tag team w/ ezgames)
** Colony Wars (640i mode?!)
** Omega Boost
** Initial D
* Saturn
** Tunnel B1
** Initial D
* N64
** Hexen
** Forsaken
** Armorines: Project S.W.A.R.M.
** Star Wars: Shadow of the Empire
** ---Star Wars: Rogue Squadron--- ''Rejected: requires angrylion.''
** Star Wars Episode 1: Battle for Naboo
** ---Pokémon Snap--- '' Rejected: requires angrylion.''
** Wipeout 64
* SNES
** ---Ultraman: Towards the Future--- ''Rejected: forces you to wait for 40 seconds to defeat each monster, even though it takes less than 10 seconds to deplete their HP.''
* GCN
** Hitman 2: Silent Assassin
* Commodore 64
** International Karate
* Arcade
** Guerrilla War
** Karate Champ
* Linux
** ---Papers, Please--- ''Incompatible with libTAS currently.''
* DOS
** MechWarrior 2
** XCOM: Apocalypse
*** Have to replace DOS extender in Smkp.exe, Ufo2p.exe, and Tacp.exe by using sb.exe utility included with DOS32a. Otherwise JPC fails with error about Task Gate.
*** JPC still fails with GENERAL_PROTECTION exception when tactical mode is entered. Haven't figured out a workaround for this.
!!! NDS Layout Automater for AviSynth
%%SRC_EMBED avs
####################################
### Nintendo DS Layout Automater ###
####################################
# Based on layouts by Spikestuff
# Adapted by Zinfidel
#################
### Importing ###
#################
# In the importing script, the following variables must be defined before importing:
# vid (clip)
# The video dump.
# resX (int)
# Final output width.
# resY (int)
# Final output height.
# vertGap (int)
# Sets a gap between the screens in the Top and Bottom layout to simulate the actual screen separation,
# and also adds borders to the top and bottom of other layouts to keep everything aligned. This value is
# relative to the *native* size of the screens, and will be scaled to the final output resolution. Setting
# this to either 90 or 32 pixels gets the screens pretty close to lined up exactly, depending on NDS model.
# LEAVE THIS VALUE AT 0 IF YOU ARE NOT GOING TO USE TOP AND BOTTOM MODE! Unnecessary borders will be added
# to the video if you don't use that mode.
# bookGap (int)
# Sets a gap between the screens in the Book Mode layout to simulate the actual screen separation. This does
# not add any extra borders to other layouts. Can be combined with vertGap if the game uses both Book Mode and
# Top and Bottom mode with a gap. Setting this to 90 or 32 pixels gets the screens pretty close to lined up exactly.
#
# The dimensions must define a resolution with an aspect ratio of 2:1. Some examples of output resolutions are:
# - Native: 768x384 (256*3 x 192*2)
# - 4K : 3840x1920
#
# Note that the final output vertical resolution will be increased by vertGap*scaleFactor if it is greater than 0.
#############
### Usage ###
#############
# There are 7 shortcut functions defined to change the layout. They are: gt, gb, st, sb, ss, tb, and bm, which are
# Gameplay (Top), Gameplay (Bottom), Single (Top), Single (Bottom), Side by Side, Top and Bottom, and Book Mode,
# respectively. These functions automatically append to the video that they build, and each takes an integer as its
# first argument: the frame number on which to change the layout.
#
# Two of the functions (tb and bm) also take an optional second argument that overrides the gap size. This value in
# pixels is not scaled or relative to the native resolution, and is used raw. This is useful for eliminating the gap
# (by setting it to 0) for scenes that need no gap. The output dimensions are fixed based on resX, resY, vertGap, and
# bookGap - setting the gap override will adjust borders to make sure the layouts work together.
#
# These functions start with the full video being set to the last variable, and then the functions are chained to
# create the video. For example:
#
# vid = AviSource("example.avi")
# resX = 768
# resY = 384
# vertGap = 0
# bookGap = 90
# Import("dslayout.avsi")
# last = vid
# ss(0)
# tb(1000)
# gt(2000).gb(3000)
# bm(4000, 0)
#
# This would create an output video that starts in Side by Side, changes to Top and Bottom at frame 1000,
# changes to Gameplay (Top) on frame 2000, then changes to Gameplay (Bottom) on frame 3000. On frame 4000,
# the layout is changed to Book Mode, but with the gap removed by setting the override to 0. It does not
# matter if there is a line break or a dot between calls, they are functionally equivalent in AviSynth.
#############
### Setup ###
#############
cr = vid.Height / 2
global top = vid.Crop(0, 0, -0, -cr)
global bot = vid.Crop(0, cr, -0, -0)
# Calculated Screen Sizes
global screenWidth = resX / 3
global screenHeight = resY / 2
global bookWidth = (resY * 2) / 3
global bookHeight = resY
# Calculated Gap Sizes
global vGap = round((screenHeight * vertGap) / 192)
global vertBorder = vGap / 2
global bGap = round((bookWidth * bookGap) / 192)
global bookBorder = (resX - (bookWidth*2) - bGap) / 2
#############################
### Pure Layout Functions ###
#############################
function GameplayTop(clip t, clip b, int trimStart, int trimEnd) {
t = t.Trim(trimStart, trimEnd).PointResize(screenWidth*2, screenHeight*2)
b = b.Trim(trimStart, trimEnd).PointResize(screenWidth, screenHeight).AddBorders(0, screenHeight, 0, 0)
return StackHorizontal(t, b).AddBorders(0, vertBorder, 0, vertBorder)
}
function GameplayBottom(clip t, clip b, int trimStart, int trimEnd) {
t = t.Trim(trimStart, trimEnd).PointResize(screenWidth, screenHeight).AddBorders(0, 0, 0, screenHeight)
b = b.Trim(trimStart, trimEnd).PointResize(screenWidth*2, screenHeight*2)
return StackHorizontal(b, t).AddBorders(0, vertBorder, 0, vertBorder)
}
function SingleTop(clip t, clip b, int trimStart, int trimEnd) {
ret = t.Trim(trimStart, trimEnd).PointResize(screenWidth*2, screenHeight*2).AddBorders(screenWidth/2, 0, screenWidth/2, 0)
return ret.AddBorders(0, vertBorder, 0, vertBorder)
}
function SingleBottom(clip t, clip b, int trimStart, int trimEnd) {
ret = b.Trim(trimStart, trimEnd).PointResize(screenWidth*2, screenHeight*2).AddBorders(screenWidth/2, 0, screenWidth/2, 0)
return ret.AddBorders(0, vertBorder, 0, vertBorder)
}
function SideBySide(clip t, clip b, int trimStart, int trimEnd) {
t = t.Trim(trimStart, trimEnd).PointResize(screenWidth*2, screenHeight*2).LanczosResize((screenWidth*3)/2, (screenHeight*3)/2)
b = b.Trim(trimStart, trimEnd).PointResize(screenWidth*2, screenHeight*2).LanczosResize((screenWidth*3)/2, (screenHeight*3)/2)
return StackHorizontal(t, b).AddBorders(0, screenHeight/4, 0, screenHeight/4).AddBorders(0, vertBorder, 0, vertBorder)
}
function TopAndBottom(clip t, clip b, int trimStart, int trimEnd, int "gap") {
gap = defined(gap) ? gap : vGap
t = t.Trim(trimStart, trimEnd).PointResize(screenWidth, screenHeight)
b = b.Trim(trimStart, trimEnd).PointResize(screenWidth, screenHeight).AddBorders(0, gap, 0, 0)
return StackVertical(t, b).AddBorders(screenWidth, (vGap-gap)/2, screenWidth, (vGap-gap)/2)
}
function BookMode(clip t, clip b, int trimStart, int trimEnd, int "gap") {
gap = defined(gap) ? gap : bGap
t = t.Trim(trimStart, trimEnd).PointResize(screenWidth*2, screenHeight*2).LanczosResize(bookHeight, bookWidth)
b = b.Trim(trimStart, trimEnd).PointResize(screenWidth*2, screenHeight*2).LanczosResize(bookHeight, bookWidth).AddBorders(0, gap, 0 , 0)
return StackVertical(t, b).TurnLeft().AddBorders(bookBorder+(bGap-gap)/2, vertBorder, bookBorder+(bGap-gap)/2, vertBorder)
}
#######################################
### Auto-Appending Layout Shortcuts ###
#######################################
function AutoAppend(clip prev, int startFrame, string func, int "gap") {
ret = Eval(func + "(top, bot, startFrame, 0" + (defined(gap) ? ", "+string(gap) : "") + ")")
return startFrame == 0 ? ret : prev.Trim(0, startFrame - 1) + ret
}
function gt(clip prev, int startFrame) { return AutoAppend(prev, startFrame, "GameplayTop") }
function gb(clip prev, int startFrame) { return AutoAppend(prev, startFrame, "GameplayBottom") }
function st(clip prev, int startFrame) { return AutoAppend(prev, startFrame, "SingleTop") }
function sb(clip prev, int startFrame) { return AutoAppend(prev, startFrame, "SingleBottom") }
function ss(clip prev, int startFrame) { return AutoAppend(prev, startFrame, "SideBySide") }
function tb(clip prev, int startFrame, int "gap") { return AutoAppend(prev, startFrame, "TopAndBottom", gap) }
function bm(clip prev, int startFrame, int "gap") { return AutoAppend(prev, startFrame, "BookMode", gap) }
%%END_EMBED