This page is mainly made for code snippets and should not be taken for actually working with an actual script, if you want something like that-- well this is where the homebrew happened.
BizHawk 2.9 and Newer
vid = AVISource("source.avi")
cw = vid.Width / 2
L = vid.Crop(0, 0, 380, 224).PointResize(cw*2,vid.Height * 2).Levels(0, 1, 255, 0, 167)
R = vid.Crop(384, 0, 384, 224).PointResize(cw*2,vid.Height * 2).Levels(0, 1, 255, 0, 167)
StackHorizontal(L,R).LanczosResize(768,448, taps=2).AudioDub(L)
Unless feos has a different part on how to handle it compared to when this was first made, you need this final line after merging the file.
"./programs/ffmpeg" -i encode.mkv -c copy -metadata:s:v:0 stereo_mode=1 "virtualboy.mkv"
BizHawk 2.8 and Older
vid = AVISource("source.avi")
cw = vid.Width / 2
L = vid.Crop(0, 0, 380, 224).PointResize(cw*2,vid.Height * 2).Levels(0, 1, 255, 0, 157)
R = vid.Crop(384, 0, 384, 224).PointResize(cw*2,vid.Height * 2).Levels(0, 1, 255, 0, 157)
StackHorizontal(L,R).LanczosResize(768,448, taps=2).AudioDub(L)
Unless feos has a different part on how to handle it compared to when this was first made, you need this final line after merging the file.
"./programs/ffmpeg" -i encode.mkv -c copy -metadata:s:v:0 stereo_mode=1 "virtualboy.mkv"
Don't forget to Greyscale first using Avisynth!
If Pink; Tweak(cont=1.5) |alternately| Levels(0, 1, 171, 0, 255)
If Red; Tweak(cont=2.08) |alternately| Levels(0, 1, 124, 0, 255).Levels(0, 1, 254, 0, 255)
If Blue; Tweak(cont=5.4) |alternately| Levels(0, 1, 47, 0, 255)
If Pink; Tweak(cont=1.5) |alternately| Levels(0, 1, 171, 0, 255)
If Red; Tweak(cont=2.08) |alternately| Levels(0, 1, 124, 0, 255).Levels(0, 1, 254, 0, 255)
If Blue; Tweak(cont=5.4) |alternately| Levels(0, 1, 47, 0, 255)
And if you're starting from Greyscale (Bleach) thanks to VBjin.
If Bleach; Tweak(cont=0.615) |alternately| Levels(0, 1, 255, 0, 157)
If Bleach; Tweak(cont=0.615) |alternately| Levels(0, 1, 255, 0, 157)
Cropping it's a thing to save lives.
feos has this part defaulted to BizHawk Virtual Boy as VBjin is obsolete... there is a fix now provided by feos (bit below), this is here for reference now.
VBjin
L = sauce.Crop(0, 0, 384, 224)
R = sauce.Crop(400, 0, 384, 224)
L = sauce.Crop(0, 0, 384, 224)
R = sauce.Crop(400, 0, 384, 224)
BizHawk
L = sauce.Crop(0, 0, 384, 224)
R = sauce.Crop(384, 0, 384, 224)
L = sauce.Crop(0, 0, 384, 224)
R = sauce.Crop(384, 0, 384, 224)
Actual feos: Here's all I can provide atm. The change in VB methods changed the scripts so heavily that there's no sane way to have both options.
Proper DS
Revision 2:
Revision 2:
All values can be multiplied by 10 to reach the 8k resolution without issue.
Those marked with the Hash symbol are created for the 8K in mind, since they don't scale up as cleanly.
Those marked with the Hash symbol are created for the 8K in mind, since they don't scale up as cleanly.
#FinalRes = 7680x4160
vid = AVISource("source.avi")
cr = vid.Height / 2
#Gameplay
bot = a.Crop(0, cr, -0, -0)
top = a.Crop(0, 0, -0, -cr).AddBorders(0, 0, 0, 192)
a = StackHorizontal(bot.PointResize(512,384), top).AddBorders(0, 16, 0, 16)
#Gameplay (top)
top = a.Crop(0, 0, -0, -cr)
bot = a.Crop(0, cr, -0, -0).AddBorders(0, 192, 0, 0)
a = StackHorizontal(top.PointResize(512,384), bot).AddBorders(0, 16, 0, 16)
#Single (Top)
a = a.Crop(0, 0, -0, -cr).PointResize(512,384).AddBorders(128, 16, 128, 16)
#Single (Bot)
a = a.Crop(0, cr, -0, -0).PointResize(512,384).AddBorders(128, 16, 128, 16)
#TopAndBot (NoGap)
a = a.AddBorders(256, 16, 256, 16)
#TopAndBot
top = a.Crop(0, 0, -0, -cr).AddBorders(0, 0, 0, 32)
bot = a.Crop(0, cr, -0, -0)
a = StackVertical(top,bot).AddBorders(256, 0, 256, 0)
#SideBySide
top = a.Crop(0, 0, -0, -cr)
bot = a.Crop(0, cr, -0, -0)
a = StackHorizontal(top, bot).LanczosResize(768,288).AddBorders(0, 64, 0, 64)
#StackHorizontal(top, bot).PointResize(8192,3072).LanczosResize(7680,2880,taps=2).AddBorders(0, 640, 0, 640)
#Gameplay (TASinfo)
bot = a.Crop(0, cr, -0, -0)
top = a.Crop(0, 0, -0, -cr).AddBorders(0, 0, 0, 192)
a = StackHorizontal(bot.PointResize(512,384).TextSubMod("Subs.ass"), top).AddBorders(0, 16, 0, 16)
#StackHorizontal(bot.PointResize(5120,3840).TextSubMod("Subs.ass"), top.PointResize(2560,3840)).AddBorders(0, 160, 0, 160)
heaven.
vid = AVISource("source.avi").Amplify(0.70)
#If you're using Citra add this:
.DelayAudio(3.7*4481136.0/268111856)
cw = vid.Width / 10
ch = vid.Height / 2
#Gameplay (Top)
top = vid.crop(0, 0, -0, -ch)
bot = vid.crop(cw, ch, -cw, -0).AddBorders(0, ch, 0, 0)
StackHorizontal(top.PointResize(top.width*2,top.height*2), bot)
#If you're not following the native res of 400x480 use this instead:
StackHorizontal(top, bot.LanczosResize(bot.width/2,bot.height/2))
#Gameplay (Bottom. Yes these games exists)
top = vid.crop(0, 0, -0, -ch).AddBorders(0, 0, 0, ch)
bot = vid.crop(cw, ch, -cw, -0)
StackHorizontal(bot.PointResize(bot.width*2,bot.height*2), top)
#If you're not following the native res of 400x480 use this instead:
StackHorizontal(bot, top.LanczosResize(top.width/2,top.height/2))
#Stacked
vid.AddBorders(360, 0, 360, 0)
#Single (Top)
vid.crop(0, 0, -0, -ch).PointResize(800,480).AddBorders(160, 0, 160, 0)
#Single (Bottom. There are cases where this is needed, be shocked.)
vid.crop(0, ch, -0, -0).PointResize(800,480).AddBorders(160, 0, 160, 0)
#Add this for before your rescaling:
last.AddBorders(0,5,0,5)
One of the more technical type encodes that can be done to not cover up the character, the example being used here is; [6012] NES Super Mario Bros. "arbitrary code execution" by OnehundredthCoin in 04:52.65
Major thing to give as note for these kinds of titles is that Scale X% is set to 88% in order to work (obviously adjust where need be depending on system you're encoding for).
Major thing to give as note for these kinds of titles is that Scale X% is set to 88% in order to work (obviously adjust where need be depending on system you're encoding for).
vid = AVISource("video.avi")
a = vid.PointResize(vid.width*10,vid.height*10)
vid = AVISource("video_Layeravi")
b = vid.PointResize(vid.width*10,vid.height*10)
maskclip = ColorKeyMask(b, $00FF00, 1)
t = Overlay(a.TextSub("Subtitles.ass"), b, mask=maskclip.ShowAlpha, mode="blend", opacity=1)
sourcevideo = (a.trim(0,508) + t.trim(509,1893) + a.trim(1894,0)).KillAudio().AudioDub(a).LanczosResize(2880,2160)
--you're pedantic for a "true" 30fps on a 30fps title.
Using FixFPS
(Ignore adding Logo/Subtitles steps for now if you're following this, stuff's not down 100%)
(Ignore adding Logo/Subtitles steps for now if you're following this, stuff's not down 100%)
LoadPlugin("ExactDedup.dll")
LoadPlugin("FixFPS.dll")
AVISource("N64Vid.avi")
ExactDedup(firstpass=true, dupinfo="EDD.txt", times="EDD-times.txt")
Do your first benchmark here.
LoadPlugin("ExactDedup.dll")
LoadPlugin("FixFPS.dll")
AVISource("N64Vid.avi")
ExactDedup(firstpass=false, dupinfo="EDD.txt")
FixFPS("EDD-times.txt", <half the total framecount minus 1>, 2, 1)
#Insert your logo and subtitle information here.
ExactDedup(firstpass=true, dupinfo="EDD2nd.txt", times="EDD2nd-times.txt")
Do your second benchmark here.
LoadPlugin("ExactDedup.dll")
LoadPlugin("FixFPS.dll")
AVISource("N64Vid.avi")
ExactDedup(firstpass=false, dupinfo="EDD.txt")
FixFPS("EDD-times.txt", <half the total framecount minus 1>, 2, 1)
#Insert your logo and subtitle information here.
ExactDedup(firstpass=false, dupinfo="EDD2nd.txt") #Disable this line when previewing.
#Insert your colourspace here.
In your x264 script insert this line before "output":
--tcfile-in EDD2nd-times.txt
DS 3 Screen Layout
:: Top Priority:
-filter_complex "[0:v]crop=iw:ih/2:0:0,scale=iw*2:ih*2:sws_flags=neighbor[left]; [left][0:v]hstack"
:: Bottom Priority:
-filter_complex "[0:v]crop=iw:ih/2:0:oh,scale=iw*2:ih*2:sws_flags=neighbor[left]; [left][0:v]hstack"
DS 2 Screen + Priority
:: Top Priority:
-filter_complex "[0:v]crop=iw:ih/2:0:0,scale=iw*2:ih*2:sws_flags=neighbor[left]; [0:v]crop=iw:ih/2:0:oh,pad=0:ih*2:0:ih[right]; [left][right]hstack"
:: Bottom Priority:
-filter_complex "[0:v]crop=iw:ih/2:0:oh,scale=iw*2:ih*2:sws_flags=neighbor[left]; [0:v]crop=iw:ih/2:0:0,pad=0:ih*2:0:0[right]; [left][right]hstack"
DS Scaling Extras (Cause YouTube is shit)
:: 1080p
,scale=iw*4:ih*4:sws_flags=neighbor,scale=1920:-1:flags=lanczos
:: 720p
,scale=iw*2:ih*2:sws_flags=neighbor,scale=1280:-1:flags=lanczos
3DS Top Screen Priority
:: Native Resolution:
-filter_complex "[0:v]crop=iw:ih/2:0:0,scale=iw*2:ih*2:sws_flags=neighbor[left]; [0:v]crop=((iw/5)*4):ih/2:iw/10:ih/2,pad=iw:ih*2:0:ih[right]; [left][right]hstack,pad=iw:ih+ih/48:iw/2:ih/2"
:: Non-Native Resolution:
-filter_complex "[0:v]crop=iw:ih/2:0:0[left]; [0:v]crop=((iw/5)*4):ih/2:iw/10:ih/2,pad=iw:ih*2:0:ih,scale=iw/2:ih/2:sws_flags=lanczos[right]; [left][right]hstack,pad=iw:ih+ih/48:iw/2:ih/2"
3DS Bottom Screen Priority
:: Native Resolution:
-filter_complex "[0:v]crop=((iw/5)*4):ih/2:iw/10:ih/2,scale=iw*2:ih*2:sws_flags=neighbor[left]; [0:v]crop=iw:ih/2:0:0,pad=iw:ih*2:0:0[right]; [left][right]hstack,pad=iw:ih+ih/48:iw/2:ih/2"
:: Non-Native Resolution:
-filter_complex "[0:v]crop=((iw/5)*4):ih/2:iw/10:ih/2[left]; [0:v]crop=iw:ih/2:0:0,scale=iw/2:ih/2:sws_flags=lanczos[right]; [left][right]hstack,pad=iw:ih+ih/48:iw/2:ih/2"
3DS Scaling Extras (Cause YouTube is shit)
:: Native
:: 1080p
,scale=iw*2:ih*2:sws_flags=neighbor,scale=1920:-1:flags=lanczos
:: 720p
,scale=iw*2:ih*2:sws_flags=neighbor,scale=1280:-1:flags=lanczos
:: Non-Native
:: 4K
,scale=3840:-1:flags=lanczos
:: 1080p
,scale=1920:-1:flags=lanczos
:: 720p
,scale=1280:-1:flags=lanczos
If you saw Disaster Relief Done Quick 2024 there was some little images at the start of each run that provided discord(s)/game/author(s)/commentator(s)/shortlink well this is how it was all done.
For the images, well the first part is get the images from their TAS pages themselves.
Except Gimmick! that image was requested from one of the authors.
Except Gimmick! that image was requested from one of the authors.
So, if you have AVISynth this bit should be straight forward.
- assrender - Used for the displayed text.
- FastBlur - Used for the background blurring.
- TAS Information - This has all the goods, font is Arial Rounded.
ImageSource("image.png", end=0).ConvertToRGB32()
last.PointResize(last.Width*8,last.Height*8).LanczosResize(1440,1080)
last.Levels(0, 1.0, 255, 0, 85).FastBlur(25, iterations=2, dither=true)
last.assrender("tasinfo.ass")
Now you have a 4:3 image.
Obviously this doesn't account for 1:1 or 16:9.
If there's future runs that require that, then well the only thing that would/should change is the ASS file, and that would be ammended onto this section.
Obviously this doesn't account for 1:1 or 16:9.
If there's future runs that require that, then well the only thing that would/should change is the ASS file, and that would be ammended onto this section.
As for the quick encode turnarounds this is the script I used for the event.
They don't have to be pretty since they're being rebroadcasted, so I actually did an outright avi dump then threw it into ffmpeg, instead of eternally using Hawk.
Mainly cause I wanted control on where the encodes actually ended with the "to" argument.
They don't have to be pretty since they're being rebroadcasted, so I actually did an outright avi dump then threw it into ffmpeg, instead of eternally using Hawk.
Mainly cause I wanted control on where the encodes actually ended with the "to" argument.
ffmpeg -hide_banner -i "input.avi" -vcodec libx264 -to 11:41.278 -x264opts no-deblock -vf "scale=iw*4:ih*4:sws_flags=neighbor,scale=1440:1080:flags=lanczos" -crf 15 -pix_fmt yuv420p -c:a libvorbis -aq 2 -b:a 128k "output.mp4"
Also please use the "no-deblock" argument deals with a lot of bull that exists.
Other than that, obviously adjust where need be, again because it's a broadcast you don't need to go as hard for the encode, you can make it a lil softer.
And if there's ever a GB/A TAS change that second scale to -1:1080 instead (also figure out your multiplier yourself).
And if there's ever a 16:9 TAS well change that to 1920:1080 instead (and yea, figure the mult yourself, I ain't here to do a full handholding for this, only mostly).
Other than that, obviously adjust where need be, again because it's a broadcast you don't need to go as hard for the encode, you can make it a lil softer.
And if there's ever a GB/A TAS change that second scale to -1:1080 instead (also figure out your multiplier yourself).
And if there's ever a 16:9 TAS well change that to 1920:1080 instead (and yea, figure the mult yourself, I ain't here to do a full handholding for this, only mostly).
NTSC/PAL60 PlayStation 2
TODO (for NTSC): Unique resolutions in NFS:Carbon to reverify & verify Beyond Good & Evil.
TODO (for NTSC): Unique resolutions in NFS:Carbon to reverify & verify Beyond Good & Evil.
# This section will work with goodizers as long as you scale appropriately.
# Calculation from a 256 x 224 or 512 x 224/448 or 640 x 224/448 image
cw = last.Width / 8
ch = last.Height / 14
# Calculation from a 640 x 224 image (GUNCON)
cw = last.Width / 8
ch = last.Height / 112 * 127
# Calculation from a 512 x 486 image
# Titles actually require the crop from the bottom to be correct to console.
cw = last.Width / 8
ch = last.Height / 243
vid.crop(0,0,0,-ch*4)
# Calculation from a 512 x 446 image
cw = last.Width / 8
ch = last.Height / 223 * 17
# Calculation from a 576 x 960 image (1080i)
cw = last.Width / 9
ch = last.Height / 8
# They share the same "addborders" script
vid.AddBorders(cw/2, ch/2, cw/2, ch/2)
# Calculation from a 640/512 x 416 image
cw = last.Width / 8
ch = last.Height / 13
vid.AddBorders(cw/2, ch, cw/2, ch)
# Calculation from a 638 x 480 image
cw = last.Width / 319 * 20
ch = last.Height / 160
last.crop(0,0,0,-ch)
last.AddBorders(cw + cw/cw, 0, cw, ch)
# EXTRA
# Calculation from a 640 x 224 image (GUNCON) NO BORDERS
cw = last.Width / 320 * 284
LanczosResize(cw,last.height)
Automated:
# This section is expecting natively dumped resolutions.
guncon = false
cw = last.Width == 638 ? last.Width / 319 * 20 : \
last.Width == 576 ? last.Width / 9 : \
last.Width / 8
ch = last.Height == 960 ? last.Height / 8 : \
last.Height == 486 ? last.Height / 243 : \
last.Height == 480 ? last.Height / 160 : \
last.Height == 446 ? last.Height / 223 * 17 : \
last.Height == 416 ? last.Height / 13 : \
guncon && last.Height == 224 ? last.Height / 112 * 127 : \
last.Height / 14
last.Height == 486 ? last.crop(0,0,0,-ch*4) : \
last.Height == 480 ? last.crop(0,0,0,-ch) : 0
# The numbers are reflected from the previous line.
# 480 (477) might need width scrutiny on the previous line.
last.Height == 477 ? last.AddBorders(cw + cw/cw, 0, cw, ch) : \
last.Height == 416 ? last.AddBorders(cw/2, ch, cw/2, ch) : \
last.AddBorders(cw/2, ch/2, cw/2, ch/2)
PointResize(last.width*10,last.height*10)
LanczosResize(2880,2160)
PAL PlayStation 2
# This section will work with goodizers as long as you scale appropriately.
# Calculation from a 640 x 512/256 or 512 x 512 image
cw = last.Width / 8
ch = last.Height / 8
# Calculation from a 640 x 256 image (GUNCON)
cw = last.Width / 8
ch = last.Height / 128 * 159
# Calculation from a 512 x 508 image
cw = last.Width / 8
ch = last.Height / 254 * 34
# Calculation from a 512 x 576 image
# Titles actually require the crop from the bottom to be correct to console.
cw = last.Width / 8
ch = last.Height / 288 * 5
vid.crop(0,0,0,-ch)
# Calculation from a 640 x 414 image
cw = last.Width / 8
ch = last.Height / 69 * 27
# They share the same "addborders" script
AddBorders(cw/2, ch/2, cw/2, ch/2)
# Calculation from a 640 x 448 image
cw = last.Width / 8
ch = last.Height / 7
AddBorders(cw/2, ch, cw/2, ch)
# Calculation from a 638 x 510 image
cw = last.Width / 319 * 20
ch = last.Height / 255 * 16
last.AddBorders(cw + cw/cw, ch, cw, ch)
# EXTRA
# Calculation from a 640 x 256 image (GUNCON) NO BORDERS
cw = last.Width / 320 * 284
LanczosResize(cw,last.height)
Automated:
# This section is expecting natively dumped resolutions.
guncon = false
cw = last.Width / 8
ch = last.Height == 576 ? last.Height / 288 * 5 : \
last.Height == 508 ? last.Height / 254 * 34 : \
last.Height == 448 ? last.Height / 7 : \
last.Height == 414 ? last.Height / 69 * 27 : \
guncon && last.Height == 256 ? last.Height / 128 * 159 : \
last.Height / 8
last.Height == 576 ? last.crop(0,0,0,-ch) : 0
last.Height == 448 ? last.AddBorders(cw/2, ch, cw/2, ch) : \
last.AddBorders(cw/2, ch/2, cw/2, ch/2)
PointResize(last.width*10,last.height*10)
LanczosResize(2880,2160)
NTSC/PAL60 PlayStation 2
#Look at "PlayStation 2 (PCSX2)" if you want more/better precision.
#This also doesn't implement the GUNCON stuff as that's already custom.
mult = 4
widescreen = false
PS2HD = last.Height == 960 ? true : false
# These titles must crop first before getting into Active Area.
last.Height == 486 ? last.crop(0,0,0,-last.Height / 243 * 4) : \
last.Height == 480 ? last.crop(0,0,0,-last.Height / 160) : 0
# First bit is related to any game that's in a 1080i resolution. This is hard-coded.
# 640 x 448 is a typical resolution (without Active Area), which is why it's targeted second.
# This also simplifies the script, the more overdone script is more specific (and better, imho).
PS2HD ? Eval("""
widescreen = true
cw = last.Width / 18
ch = last.Height / 16
last.AddBorders(cw, ch, cw, ch)
last.PointResize(last.width * (mult/2),last.height * (mult/2))
""") : Eval("""
last.PointResize(last.width * mult, last.height * mult) \
.LanczosResize(640 * mult, 448 * mult) \
.AddBorders(40 * mult, 16 * mult, 40 * mult, 16 * mult)
""")
widescreen ? last.LanczosResize(3840,2160) : \
last.LanczosResize(2880,2160)
PAL PlayStation 2
#Look at "PlayStation 2 (PCSX2)" if you want more/better precision.
#This also doesn't implement the GUNCON stuff as that's already custom.
mult = 4
widescreen = false
# These titles must crop first before getting into Active Area.
last.Height == 576 ? last.crop(0,0,0,-last.Height / 288 * 5) : 0
# 640 x 512 is a typical resolution (without Active Area), which is why it's targeted second.
# This also simplifies the script, the more overdone script is more specific (and better, imho).
last.PointResize(last.width * mult, last.height * mult) \
.LanczosResize(640 * mult, 512 * mult) \
.AddBorders(40 * mult, 32 * mult, 40 * mult, 32 * mult)
widescreen ? last.LanczosResize(3840,2160) : \
last.LanczosResize(2880,2160)
This only exists to point out that I have figured it out.
# Calculation from a 640x524 (Ratio: 777:524)
cw = last.Width / 160 * 9
last.AddBorders(cw, 0, cw, 0)
# Calculation from a 776x444
cw = last.Width / 194 * 21 / 2
ch = last.Height / 222 * 13 / 2
mfw = last.Width / 776
last.AddBorders(cw+mfw, ch, cw, ch)
# Calculation from a 820x448
cw = last.Width / 82 * 3 / 2
ch = last.Height / 224 * 13 / 2
mfw = last.Width / 820
last.AddBorders(cw-mfw, ch, cw, ch)
# Calculation from a 848x480
cw = last.Width / 424 * 7 / 2
chc = last.Height / 80
crop(0,chc,0,0)
AddBorders(cw, 0, cw, 0)
# Calculation from a 852x480
cw = last.Width / 213
mfw = last.Width / 426
# Calculation from a 832x480
cw = last.Width / 416 * 7
mfw = last.Width / 832
chc = last.Height / 80
crop(0,chc,0,0)
# Calculation from a 812x480
last.Width / 203 * 6
mfw = last.Width / 812
last.AddBorders(cw+mfw, 0, cw, 0)
# Calculation from a 852x448
cw = last.Width / 426 * 5
ch = last.Height / 56 * 3 / 2
mfh = last.Height / 448
last.AddBorders(cw, ch, cw, ch+mfh)
# Calculation from a 832x456
cw = last.Width / 416 * 7
ch = last.Height / 57
# ch = last.Height / 228 * 4
# (keeping this here temporarily for a different math operation if it can be used in the future).
mfw = last.Width / 832
mfh = last.Width / 456
last.AddBorders(cw+mfw, ch, cw, ch+mfh)