Of course. It's a business; you pay to be entertained by the illusion of having a chance. Just like you go to a magician's show for the illusion that magic exists.
Yeah, all of that works. But it's highly redundant - you already set last with a single line of "AVISynth(...)".
"return last" looks like "i = i + 1;" to a C programmer.
When writing functions that take a clip as their first parameter, I (almost) always put the clip variable on its own line to make it the "current" clip. So yes, it does work.
There is no motion blur because it works spatially (in 2D), not temporally. The problem is that games with very small text will have that blurred.
Example: Castlevania
Language: AviSynth
Open("castlevaniasotn-tas-maria-arandomgametaser.mkv")
sh1 = StackHorizontal(Method_0.RightBorder, Method_1.RightBorder, Method_2).BottomBorder
sh2 = StackHorizontal(Method_3.RightBorder, Method_4.RightBorder, Method_5)
StackVertical(sh1, sh2)
FullScreen(1920, 1080) # enter your screen size; intended for viewing with MPC-HC (or other players) in fullscreen
function Method_0(clip c) {c .PointResize(c.Width * 2, c.Height * 2).Subtitle("original (no change)" , text_color=$FFFFFF)}
function Method_1(clip c) {c.Layer(c, level=128, x=1) .PointResize(c.Width * 2, c.Height * 2).Subtitle("method 1 (add left neighbor pixel at 4/8 intensity)" , text_color=$FFFFFF)}
function Method_2(clip c) {c.Layer(c, op="lighten", level=160, x=1) .PointResize(c.Width * 2, c.Height * 2).Subtitle("method 2 (lighten with left neighbor pixel at 5/8 intensity)" , text_color=$FFFFFF)}
function Method_3(clip c) {c.Layer(c, op="lighten", level= 64, x=1).Layer(c, op="lighten", level= 64, x=-1).PointResize(c.Width * 2, c.Height * 2).Subtitle("method 3 (lighten with left and right pixels at 2/8 intensity)", text_color=$FFFFFF)}
function Method_4(clip c) {c.Layer(c, op="lighten", level= 96, x=1).Layer(c, op="lighten", level= 96, x=-1).PointResize(c.Width * 2, c.Height * 2).Subtitle("method 4 (lighten with left and right pixels at 3/8 intensity)", text_color=$FFFFFF)}
function Method_5(clip c) {c.Layer(c, op="lighten", level=128, x=1).Layer(c, op="lighten", level=128, x=-1).PointResize(c.Width * 2, c.Height * 2).Subtitle("method 5 (lighten with left and right pixels at 4/8 intensity)", text_color=$FFFFFF)}
function FullScreen(clip c, int Screen_Width, int Screen_Height) {
c
x = (Screen_Width - Width ) / 2
y = (Screen_Height - Height) / 2
AddBorders(x, y, x, y)
}
function Open(string f) {
v = DSS2(f, pixel_type="RGB32")
a = DirectShowSource(f, video=false)
AudioDub(v, a)
}
function BottomBorder(clip c) {c.Crop(0, 0, 0, -1).AddBorders(0, 0, 0, 1, color=$FFFFFF)}
function RightBorder(clip c) {c.Crop(0, 0, -1, 0).AddBorders(0, 0, 1, 0, color=$FFFFFF)}
function Show(clip a, clip b, string "text_a", string "text_b") {
text_a = default(text_a, "")
text_b = default(text_b, "")
a = a.ConvertToRGB32
b = b.ConvertToRGB32
c = Subtract(a, b)
x = a.Width / 2
y = a.Height / 2
a1 = a.Crop(0, 0, 0, -y).Crop(1, 1, -1, -1).AddBorders(1, 1, +1, +1, $FF0000).Subtitle(text_a, text_color=$FFFFFF)
a2 = a.Crop(0, +y, 0, 0).Crop(1, 1, -1, -1).AddBorders(1, 1, +1, +1, $0000FF)
b1 = b.Crop(0, 0, 0, -y).Crop(1, 1, -1, -1).AddBorders(1, 1, +1, +1, $FF0000).Subtitle(text_b, text_color=$FFFFFF)
b2 = b.Crop(0, +y, 0, 0).Crop(1, 1, -1, -1).AddBorders(1, 1, +1, +1, $0000FF)
c1 = c.Crop(0, 0, 0, -y).Crop(1, 1, -1, -1).AddBorders(1, 1, +1, +1, $FF0000).Subtitle("top" , text_color=$FFFFFF, halo_color=$FF0000)
c2 = c.Crop(0, +y, 0, 0).Crop(1, 1, -1, -1).AddBorders(1, 1, +1, +1, $0000FF).Subtitle("bottom", text_color=$FFFFFF, halo_color=$0000FF)
a = StackVertical (a1, a2)
b = StackVertical (b1, b2)
c = StackHorizontal(c1, c2)
StackVertical(StackHorizontal(a, b), c)
}
Result (view in fullscreen / download and view with fullscreen viewers like IrfanView)
[Picture 01] Method_1 completely removes the mesh but blurs the small text (e.g. the "START" button).
[Picture 02] The "lighten" methods preserve the text, but cannot remove the mesh completely. (They also make the picture a little bit brighter.)
[Picture 04] As you can see the algorithm works purely horizontally.
[Picture 05] Removing static meshes is the most important job of such a filter. As said above the "lighten" filters fail here.
For games where the meshes are only used for small, fast-moving objects (like Maria in the examples) I wouldn't apply a filter.
I suspect that what we'd need is a "bloom" filter which makes only the bright pixels bleed into the dark pixels.
Most of the run looks "similar" to the previous versions as well. I know it's technically redone, but after watching the 5th or so versions they all start appearing "similar".
I dunno, after watching some Super Metroid runs I can see more differences.
So, in principle, if you receive a letter claiming infringement, you can always reply with another one saying that you're sorry they think their rights are being violated, but that you are not doing anything wrong for whatever reason, and state that you will "troll them back" in court if they move forward. Even simple cases take years to be decided in court, and are very expensive for the people stating the claim, so I really don't see any copyright holder pushing forward unless you are hurting their sales by a significant margin.
I've been wondering about this. What skills and knowledge does one need to learn to be able to code an emulator, or at least understand what is going on in the source code?
Divide the problem into sub-problems until the problems become trivial; then put the solutions together. This means that if you want to create your own emulator, after learning about the console you must start at the bottom (the CPU) and work your way up. Don't start at the GUI and "work your way down". Anyway, here's a short introduction:
An emulator recreates a video game console. It does that by simulating the functions of the hardware components.
(Video game consoles are just computers - though not IBM compatible - they have microprocessors (CPU) and memory chips (ROM, RAM) and digital signal processors (DSP) and digital-to-analog converters (DAC) just like a PC.)
It turns out that the CPU is the most important piece, and about the most important thing it can do is adding two numbers.
→ These two numbers are stored in registers; find out what registers exactly are available on your console's CPU.
→ Oops, first you need to know what CPU you're dealing with.
→ Looks like a CPU can only add numbers of a certain length, like 8, 16, 32 or 64 bits. (This is so important that we've named entire video game console generations after them.)
→ Note that they can also detect if the result overflows the allowed number of bits.
CPUs can also compare numbers; they just subtract them and look if the result was zero. (There's more stuff you can do with the result, like finding out which number was larger.)
Adding or subtracting only the same two numbers all the time is boring, so there's a whole infrastructure for feeding new values to the CPU. On the CPU there's usually one physical pin per bit, and the voltage level on that pin determines if it's 0 or 1. (Note that this may be inverted.) This set of pins is the data bus.
Theoretically the data bus could be connected to anything, but in practice each data bus line is connected to a memory chip that provides the numbers to the CPU. This chip also needs a number to select one of its memory cells, so there's a second set of lines (the address bus) going into the memory chip.
→ The number of lines in the address bus roughly determines how much memory can be used by the system. It can (and often is) different from the data bus width.
You might think that with all these pins you could directly select a cell in the memory chip and directly instruct the CPU what to do with the number going into (or out of) the CPU; turns out that it's much faster to also give the CPU address bus pins, connect the memory chip's address bus to these pins, and store instructions for the CPU in the memory chip alongside the data.
→ The instructions are called opcodes, and the CPU has a special register called program counter (PC) to keep track of its position in the instruction stream.
The opcodes (which are themselves just numbers, most often 1 byte in size) plus their operands form the machine language of the CPU. Writings programs in this machine language is extremely tedious (basically it would amount to putting a sequence of hex numbers into memory), but this is in fact what is involved in creating an ACE TAS.
→ The human-readable translation of machine language is assembly code (ASM), and this is what people used to write their games in. (At least until about the 32-bit era.)
→ When you look at a game's ROM file in a hex editor, you see its machine language code. It can be automatically translated ("disassembled") back to ASM, but the original identifiers are lost and making sense of the code takes lots of time.
You'll see that the game code seems to read from and write to special addresses. The truth is that there are often much more addresses available to the CPU than how much memory is installed in the system. In fact the address bus and the data bus are not only connected to "the memory chip" mentioned above, but also to other devices like RAM chips, video chips, audio chips, or even the controller port connectors.
→ These extra addresses are listed in video game console-specific memory maps.
→ What numbers can be sent to or received from these addresses, and when, is discussed in the programming manual for a particular video game console, written by the manufacturer (or by hackers).
Emulating a game means creating variables to record the state of every component in the system, and then looking at the game's instruction stream and changing those variables accordingly. The GUI sets the variables that record the state of the input devices, and reads out the variables that record the state of the video/audio output.
ClearSky wrote:
Do you need to be a computer scientist or a software engineer to be able to do that?
No. If you can write programs and if you can understand the programming manuals for your chosen console then you can in theory also write an emulator.