summaryrefslogtreecommitdiffstats
path: root/2020/info/27.md
blob: 9740bd07e8b9d64abd254ef489c80050ef0420fd (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
# State of Retro Gaming in Emacs
Vasilij "wasamasa" Schneidermann

[[!template vidid=mainVideo id=vid src="https://mirror.csclub.uwaterloo.ca/emacsconf/2020/emacsconf-2020--27-state-of-retro-gaming-in-emacs-chip8--vasilij-wasamasa-schneidermann.webm" subtitles="/2020/subtitles/emacsconf-2020--27-state-of-retro-gaming-in-emacs-chip8--vasilij-wasamasa-schneidermann.vtt"]]  
[Download compressed .webm video (7.2M)](https://mirror.csclub.uwaterloo.ca/emacsconf/2020/smaller/emacsconf-2020--27-state-of-retro-gaming-in-emacs-chip8--vasilij-wasamasa-schneidermann--vp9-q56-video-original-audio.webm)  
[View transcript](#transcript)

- [chip8 demo - alien, .webm video, 720p, 2M](https://mirror.csclub.uwaterloo.ca/emacsconf/2020/emacsconf-2020--27-state-of-retro-gaming-in-emacs-chip8-demo-alien--vasilij-wasamasa-schneidermann.webm)
- [chip8 demo - brix, .webm video, 720p, 1M](https://mirror.csclub.uwaterloo.ca/emacsconf/2020/emacsconf-2020--27-state-of-retro-gaming-in-emacs-chip8-demo-brix--vasilij-wasamasa-schneidermann.webm)
- [chip8 demo - car, .webm, 720p, 1M](https://mirror.csclub.uwaterloo.ca/emacsconf/2020/emacsconf-2020--27-state-of-retro-gaming-in-emacs-chip8-demo-car--vasilij-wasamasa-schneidermann.webm)
- [chip8 demo - joust, .webm video, 720p, 2M](https://mirror.csclub.uwaterloo.ca/emacsconf/2020/emacsconf-2020--27-state-of-retro-gaming-in-emacs-chip8-demo-joust--vasilij-wasamasa-schneidermann.webm)
- [chip8 demo - kaleidoscope, video, 720p, 2M](https://mirror.csclub.uwaterloo.ca/emacsconf/2020/emacsconf-2020--27-state-of-retro-gaming-in-emacs-chip8-demo-kaleidoscope--vasilij-wasamasa-schneidermann.webm)
- [chip8 demo - sierpinski, video, 720p, 357K](https://mirror.csclub.uwaterloo.ca/emacsconf/2020/emacsconf-2020--27-state-of-retro-gaming-in-emacs-chip8-demo-sierpinski--vasilij-wasamasa-schneidermann.webm)
- [chip8 demo - tetris, video, 720p, 843K](https://mirror.csclub.uwaterloo.ca/emacsconf/2020/emacsconf-2020--27-state-of-retro-gaming-in-emacs-chip8-demo-tetris--vasilij-wasamasa-schneidermann.webm)

Many jokes have been made about the true nature of Emacs, such as it
being a fully-fledged operating system.  This talk will demonstrate
its suitability for playing retro games, then explore the inner
workings of a [CHIP-8](https://en.wikipedia.org/wiki/CHIP-8) emulator capable of smooth video game emulation.

[1]: <https://depp.brause.cc/talks/chicken-saar/>
[2]: <https://depp.brause.cc/talks/openchaos-2019-11/>

<!-- from the pad --->

- Actual start and end time (EST): Start: 2020-11-29T13.23.01; End:
  2020-11-29T13.33.00
- Alternative stream for extended talk:
  <http://live.emacsconf.org/alt.html> or
  <http://live0.emacsconf.org/alt.webm>.

# Questions

## Q5: Do you think would be possible to write some compiler in order to write chip-8 games on elisp?
It could be possible if you restrict yourself to some very limited
Elisp subset or lispy assembler. For the latter, here's some projects
to draw inspiration from:

- <https://ahefner.livejournal.com/20528.html>.
- <http://www.dustmop.io/blog/2019/09/10/what-remains-technical-breakdown/>
  ->
  <http://www.pawfal.org/dave/blog/2016/05/a-6502-lisp-compiler-sprite-animation-and-the-nesfamicom/>.
- <https://en.wikipedia.org/wiki/Game_Oriented_Assembly_Lisp> ->
  <https://blog.jakspeedruns.com/opengoal-project-update-september-2020/>.

## Q4: What's the biggest perf bottleneck for your emulator? does it spend time executing your Lisp or something else in the Emacs infrastructure (eg redisplay)?
Redisplay was super slow, it's like 3-4x as slow as executing the CPU
cycles.

- Okay that's the reason why GCCEmacs does not help :)

## Q3: Do you think that you make our tiny console based in the chip ATMega like Arduboy?
I'm sorry, I didn't quite understand the question, could you please
clarify it? I'm not exactly a hardware person, might have to defer it
to someone else.

I've looked at Arduboy and I believe the DEFCON CHIP-8 Badge is the
closest to this:
<https://hackaday.io/project/19121-andxor-dc25-badge/log/53223-chip8-schip-game-emulation>

## Q2: Any tutorial to start? I want to make my game now, no, for chip8
I'm not aware of tutorials, but there's CHIP-8 resources online. You
can of course study the assembly of existing games, that's how I
figured out the tricks that broke my emulator :>

## Q1: How did you manage to present a game engine without showing any game? :-) Show us!!
See the alt stream, it has several demos not shown due to time
constraints.

# Notes
- Slides available at <https://depp.brause.cc/talks/emacsconf-2020/>.
- Repository available at <https://depp.brause.cc/chip8.el/>.
- Blog post available at
  <https://emacsninja.com/posts/smooth-video-game-emulation-in-emacs.html>.

<a name="transcript"></a>
# Transcript

[[!template new="1" text="Hello everyone and welcome to my talk, &quot;The State of Retro Gaming and Emacs.&quot;" start="00:00:00.880" video="mainVideo" id=subtitle]]
[[!template text="First of all, a little bit about myself." start="00:00:06.960" video="mainVideo" id=subtitle]]
[[!template text="My name is Vasilij Schneidermann. I'm 28 years old." start="00:00:08.639" video="mainVideo" id=subtitle]]
[[!template text="I work as a cyber security consultant at msg systems," start="00:00:12.000" video="mainVideo" id=subtitle]]
[[!template text="and test other people's web applications" start="00:00:14.719" video="mainVideo" id=subtitle]]
[[!template text="and review the source code for security problems." start="00:00:17.359" video="mainVideo" id=subtitle]]
[[!template text="You can reach me by email." start="00:00:20.160" video="mainVideo" id=subtitle]]
[[!template text="I have my own self-hosted git repositories," start="00:00:22.080" video="mainVideo" id=subtitle]]
[[!template text="and I have a blog where you can occasionally find new posts by me" start="00:00:25.039" video="mainVideo" id=subtitle]]
[[!template text="on all kinds of things, not just Emacs things." start="00:00:28.160" video="mainVideo" id=subtitle]]
[[!template new="1" text="The motivation about this one..." start="00:00:32.160" video="mainVideo" id=subtitle]]
[[!template text="I found that Emacs is the ultimate procrastination machine," start="00:00:34.559" video="mainVideo" id=subtitle]]
[[!template text="and there are lots of fun demonstrations." start="00:00:37.600" video="mainVideo" id=subtitle]]
[[!template text="I'll go over a few of them." start="00:00:39.600" video="mainVideo" id=subtitle]]
[[!template text="For example, someone made a thing to order salad for himself online," start="00:00:41.200" video="mainVideo" id=subtitle]]
[[!template text="so he doesn't have to walk over to the shop." start="00:00:45.840" video="mainVideo" id=subtitle]]
[[!template text="There's plenty of IRC bots. There's some game things." start="00:00:48.239" video="mainVideo" id=subtitle]]
[[!template text="There's an emulator for the Z-machine which you can use to play zork." start="00:00:51.760" video="mainVideo" id=subtitle]]
[[!template new="1" text="And so I asked myself, at this point," start="00:00:55.600" video="mainVideo" id=subtitle]]
[[!template text="can you actually emulate retro games at 60fps?" start="00:00:57.440" video="mainVideo" id=subtitle]]
[[!template text="I looked around a bit and found some projects," start="00:00:59.920" video="mainVideo" id=subtitle]]
[[!template text="but none that were actually able to do it at 60fps." start="00:01:02.079" video="mainVideo" id=subtitle]]
[[!template text="So I set out to do my own one," start="00:01:06.159" video="mainVideo" id=subtitle]]
[[!template text="and looked out for a console" start="00:01:08.000" video="mainVideo" id=subtitle]]
[[!template text="that you can actually emulate at that speed," start="00:01:09.200" video="mainVideo" id=subtitle]]
[[!template text="using Emacs with its very, very limited rendering." start="00:01:11.119" video="mainVideo" id=subtitle]]
[[!template new="1" text="And here's the project, chip8.el." start="00:01:16.320" video="mainVideo" id=subtitle]]
[[!template text="It's pretty much finished." start="00:01:19.200" video="mainVideo" id=subtitle]]
[[!template text="It clocks into under 1000 source lines of code." start="00:01:20.560" video="mainVideo" id=subtitle]]
[[!template text="It supports the superchip 8 extensions." start="00:01:24.000" video="mainVideo" id=subtitle]]
[[!template text="It runs at full speed." start="00:01:26.159" video="mainVideo" id=subtitle]]
[[!template text="All games behave okay, as far as I'm concerned," start="00:01:27.280" video="mainVideo" id=subtitle]]
[[!template text="and yeah, I'm pretty happy with it." start="00:01:29.600" video="mainVideo" id=subtitle]]
[[!template text="It's very much the hello world of emulation," start="00:01:31.680" video="mainVideo" id=subtitle]]
[[!template text="and I might, maybe, do some other emulation projects in the future." start="00:01:34.479" video="mainVideo" id=subtitle]]
[[!template new="1" text="Now, for the section which is the longest:" start="00:01:40.880" video="mainVideo" id=subtitle]]
[[!template text="bunch of fun facts about chip8.el" start="00:01:43.360" video="mainVideo" id=subtitle]]
[[!template text="which I've learned during this project." start="00:01:45.439" video="mainVideo" id=subtitle]]
[[!template text="So what the hell is chip8 anyway?" start="00:01:49.200" video="mainVideo" id=subtitle]]
[[!template text="First of all, unlike many other emulation game things," start="00:01:51.759" video="mainVideo" id=subtitle]]
[[!template text="it's not a console, but a VM." start="00:01:54.960" video="mainVideo" id=subtitle]]
[[!template text="It was designed for easy porting of home computer games." start="00:01:56.799" video="mainVideo" id=subtitle]]
[[!template text="It wasn't terribly successful," start="00:02:00.000" video="mainVideo" id=subtitle]]
[[!template text="but there's still a small community of enthusiasts writing games for it," start="00:02:02.320" video="mainVideo" id=subtitle]]
[[!template text="and there are even a few demos." start="00:02:05.439" video="mainVideo" id=subtitle]]
[[!template text="This VM has system specs." start="00:02:09.119" video="mainVideo" id=subtitle]]
[[!template text="It has a very, very simple 8-bit cpu with 16 registers," start="00:02:11.039" video="mainVideo" id=subtitle]]
[[!template text="and 36 fixed-size instructions." start="00:02:14.720" video="mainVideo" id=subtitle]]
[[!template text="You have a whole 4 kilobyte of RAM." start="00:02:17.280" video="mainVideo" id=subtitle]]
[[!template text="You have a stack with 16 return addresses." start="00:02:19.680" video="mainVideo" id=subtitle]]
[[!template text="The resolution is 64 by 32 black/white pixels." start="00:02:22.080" video="mainVideo" id=subtitle]]
[[!template new="1" text="Rendering is done by drawing sprites." start="00:02:25.760" video="mainVideo" id=subtitle]]
[[!template text="These are drawn in XOR mode," start="00:02:28.000" video="mainVideo" id=subtitle]]
[[!template text="meaning that if you draw a sprite and set a bit," start="00:02:29.200" video="mainVideo" id=subtitle]]
[[!template text="it just flips over from black to white or white to black." start="00:02:31.840" video="mainVideo" id=subtitle]]
[[!template text="For sound, you have a monotone buzzer that can just beep at one frequency." start="00:02:35.040" video="mainVideo" id=subtitle]]
[[!template text="Most unusually, there's a hexadecimal keypad as input," start="00:02:39.360" video="mainVideo" id=subtitle]]
[[!template text="so the keys are basically zero to nine and a to f." start="00:02:43.120" video="mainVideo" id=subtitle]]
[[!template text="So how does this whole thing work?" start="00:02:48.480" video="mainVideo" id=subtitle]]
[[!template text="It runs at an unspecified speed." start="00:02:50.720" video="mainVideo" id=subtitle]]
[[!template text="You'll probably have to do some fine-tuning" start="00:02:52.400" video="mainVideo" id=subtitle]]
[[!template text="to find the speed you're happy with." start="00:02:53.040" video="mainVideo" id=subtitle]]
[[!template new="1" text="Sound and delay timers exist." start="00:02:56.080" video="mainVideo" id=subtitle]]
[[!template text="They count down at 60fps down to 0." start="00:02:58.080" video="mainVideo" id=subtitle]]
[[!template text="This is done so that you can play a sound at some specific time." start="00:03:01.120" video="mainVideo" id=subtitle]]
[[!template text="The game itself is loaded with a fixed offset into RAM." start="00:03:05.120" video="mainVideo" id=subtitle]]
[[!template text="The program counter is set to exactly that offset," start="00:03:07.840" video="mainVideo" id=subtitle]]
[[!template text="and from there it enters the game loop" start="00:03:10.480" video="mainVideo" id=subtitle]]
[[!template text="where it decodes an instruction," start="00:03:11.920" video="mainVideo" id=subtitle]]
[[!template text="executes it for the side effects," start="00:03:13.280" video="mainVideo" id=subtitle]]
[[!template text="and just loops and does this ad infinitum." start="00:03:14.800" video="mainVideo" id=subtitle]]
[[!template new="1" text="So the game loop was the first thing where we ran into problems." start="00:03:19.599" video="mainVideo" id=subtitle]]
[[!template text="The usual game approach is to do stuff," start="00:03:22.720" video="mainVideo" id=subtitle]]
[[!template text="figure out how long to wait," start="00:03:25.120" video="mainVideo" id=subtitle]]
[[!template text="wait for exactly that much, and repeat." start="00:03:26.640" video="mainVideo" id=subtitle]]
[[!template text="This doesn't work well in Emacs at all, because, well," start="00:03:29.280" video="mainVideo" id=subtitle]]
[[!template text="user input, basically." start="00:03:31.680" video="mainVideo" id=subtitle]]
[[!template text="Emacs is designed to just do whatever it needs to do" start="00:03:34.959" video="mainVideo" id=subtitle]]
[[!template text="whenever you enter user input" start="00:03:37.760" video="mainVideo" id=subtitle]]
[[!template text="instead of doing things at one specific time." start="00:03:39.040" video="mainVideo" id=subtitle]]
[[!template text="If you try to do interruptable sleep, well, you get unpredictable behavior." start="00:03:42.319" video="mainVideo" id=subtitle]]
[[!template text="For example, it can be the timer doesn't run at all at the next time" start="00:03:46.640" video="mainVideo" id=subtitle]]
[[!template text="because you've accidentally cancelled it." start="00:03:50.480" video="mainVideo" id=subtitle]]
[[!template text="If you do uninterruptable sleep, it freezes instead ," start="00:03:52.560" video="mainVideo" id=subtitle]]
[[!template text="which isn't what we want either." start="00:03:55.120" video="mainVideo" id=subtitle]]
[[!template new="1" text="So I went for timers, which forced me to do inversion of control," start="00:03:56.720" video="mainVideo" id=subtitle]]
[[!template text="meaning that I have to write code in the style" start="00:04:00.560" video="mainVideo" id=subtitle]]
[[!template text="where it just calls timer," start="00:04:02.560" video="mainVideo" id=subtitle]]
[[!template text="and this allows this input to happen" start="00:04:04.879" video="mainVideo" id=subtitle]]
[[!template text="and for things to progress at roughly the speed I want to." start="00:04:06.560" video="mainVideo" id=subtitle]]
[[!template text="So there's the timer function which is called at 60fps" start="00:04:11.040" video="mainVideo" id=subtitle]]
[[!template text="and I have to be very careful to not do too much in it." start="00:04:14.159" video="mainVideo" id=subtitle]]
[[!template text="And, say, this function executes CPU cycles," start="00:04:17.359" video="mainVideo" id=subtitle]]
[[!template text="decrement the sound/delay registers, and redraw the screen." start="00:04:21.305" video="mainVideo" id=subtitle]]
[[!template new="1" text="So to map this whole system to Emacs Lisp," start="00:04:26.479" video="mainVideo" id=subtitle]]
[[!template text="I've used just integers and vectors" start="00:04:28.800" video="mainVideo" id=subtitle]]
[[!template text="which contain even more integers." start="00:04:31.199" video="mainVideo" id=subtitle]]
[[!template text="This is used for the RAM, registers," start="00:04:33.120" video="mainVideo" id=subtitle]]
[[!template text="return stack, key state, screen," start="00:04:35.040" video="mainVideo" id=subtitle]]
[[!template text="and so on and so forth." start="00:04:37.040" video="mainVideo" id=subtitle]]
[[!template text="Basically, what you would do if you were writing C." start="00:04:38.508" video="mainVideo" id=subtitle]]
[[!template text="All of this is stored in global variables." start="00:04:41.520" video="mainVideo" id=subtitle]]
[[!template text="I'm not using any lists at all." start="00:04:43.360" video="mainVideo" id=subtitle]]
[[!template text="As a side effect, there's no consing going on at all." start="00:04:45.600" video="mainVideo" id=subtitle]]
[[!template text="There are no extra objects created" start="00:04:48.400" video="mainVideo" id=subtitle]]
[[!template text="which would trigger garbage collection processes." start="00:04:50.080" video="mainVideo" id=subtitle]]
[[!template text="Getting this right was rather tricky, actually," start="00:04:53.199" video="mainVideo" id=subtitle]]
[[!template text="and there were some hidden garbage collection problems" start="00:04:55.600" video="mainVideo" id=subtitle]]
[[!template text="which I had to resolve over time." start="00:04:58.240" video="mainVideo" id=subtitle]]
[[!template new="1" text="So, decoding instructions." start="00:05:01.759" video="mainVideo" id=subtitle]]
[[!template text="For this, you have to know that all instructions are two bytes long," start="00:05:03.759" video="mainVideo" id=subtitle]]
[[!template text="and the arguments are encoded inside them." start="00:05:06.800" video="mainVideo" id=subtitle]]
[[!template text="For example, the jump to address instruction" start="00:05:08.880" video="mainVideo" id=subtitle]]
[[!template text="is encoded as one and three hex digits." start="00:05:11.440" video="mainVideo" id=subtitle]]
[[!template text="The type is extracted masking with #xF000" start="00:05:15.120" video="mainVideo" id=subtitle]]
[[!template text="and then shifting it by 12 bits." start="00:05:18.400" video="mainVideo" id=subtitle]]
[[!template text="Mask means you perform the binary AND." start="00:05:20.400" video="mainVideo" id=subtitle]]
[[!template text="You can do the same with the argument by masking with #0xFFF and no shift." start="00:05:23.520" video="mainVideo" id=subtitle]]
[[!template text="If you do this long enough, you'll find common patterns." start="00:05:28.400" video="mainVideo" id=subtitle]]
[[!template text="For example, addresses are always encoded like this" start="00:05:30.560" video="mainVideo" id=subtitle]]
[[!template text="using the last three nibbles." start="00:05:32.639" video="mainVideo" id=subtitle]]
[[!template text="In the code, you'll find a big cond" start="00:05:34.880" video="mainVideo" id=subtitle]]
[[!template text="which dispatches on the type and executes it for the side effects." start="00:05:36.160" video="mainVideo" id=subtitle]]
[[!template new="1" text="For testing, I've initially just executed the ROM until I've hit C-g," start="00:05:41.440" video="mainVideo" id=subtitle]]
[[!template text="and then use the debug command to render the screen to a buffer." start="00:05:45.919" video="mainVideo" id=subtitle]]
[[!template text="Later on, I found tiny ROMs that just display a static test screen," start="00:05:49.039" video="mainVideo" id=subtitle]]
[[!template text="for example, logo, and looked whether it looked right." start="00:05:53.199" video="mainVideo" id=subtitle]]
[[!template text="I added instructions as needed" start="00:05:57.280" video="mainVideo" id=subtitle]]
[[!template text="and went through more and more and more ROMs." start="00:05:58.800" video="mainVideo" id=subtitle]]
[[!template text="And later I wrote a unit test suite as a safety net." start="00:06:00.720" video="mainVideo" id=subtitle]]
[[!template text="This unit test suite, it just sets up an empty emulator state," start="00:06:04.000" video="mainVideo" id=subtitle]]
[[!template text="executes some instructions," start="00:06:07.840" video="mainVideo" id=subtitle]]
[[!template text="and then looks whether the expected side effects have happened." start="00:06:09.199" video="mainVideo" id=subtitle]]
[[!template new="1" text="For debugging, I usually use edebug, but this was super ineffective," start="00:06:14.880" video="mainVideo" id=subtitle]]
[[!template text="because, well, you don't really want to step through big cons" start="00:06:18.319" video="mainVideo" id=subtitle]]
[[!template text="doing side effects for every single cycle," start="00:06:21.600" video="mainVideo" id=subtitle]]
[[!template text="when it can take like 100 cycles for things to happen." start="00:06:23.680" video="mainVideo" id=subtitle]]
[[!template text="Therefore I've set up logging." start="00:06:26.880" video="mainVideo" id=subtitle]]
[[!template text="Whenever I logged something and couldn't figure out the error," start="00:06:29.680" video="mainVideo" id=subtitle]]
[[!template text="I compared my log output with the instrumented version of another emulator," start="00:06:32.639" video="mainVideo" id=subtitle]]
[[!template text="and if the logs diverge, then I have figured out where the bug lies" start="00:06:37.039" video="mainVideo" id=subtitle]]
[[!template text="and could look deeper into it." start="00:06:40.479" video="mainVideo" id=subtitle]]
[[!template text="Future project idea might be a chip 8 debugger," start="00:06:42.720" video="mainVideo" id=subtitle]]
[[!template text="but I doubt I'll ever go into it." start="00:06:44.960" video="mainVideo" id=subtitle]]
[[!template new="1" text="For analysis, I initially wrote a disassembler," start="00:06:49.440" video="mainVideo" id=subtitle]]
[[!template text="which is a very simple thing but super tedious," start="00:06:51.759" video="mainVideo" id=subtitle]]
[[!template text="especially if you wanted to add advanced functionality," start="00:06:54.400" video="mainVideo" id=subtitle]]
[[!template text="for example, analysis or thinking of what part is data," start="00:06:56.639" video="mainVideo" id=subtitle]]
[[!template text="what part is code." start="00:06:58.720" video="mainVideo" id=subtitle]]
[[!template text="I had this great idea for using the radare 2 framework" start="00:07:00.000" video="mainVideo" id=subtitle]]
[[!template text="and adding analysis and disassembly plug-in for it." start="00:07:03.360" video="mainVideo" id=subtitle]]
[[!template text="So I looked into this. Found, okay," start="00:07:06.479" video="mainVideo" id=subtitle]]
[[!template text="you can write plugins in C" start="00:07:08.400" video="mainVideo" id=subtitle]]
[[!template text="but also in Python, so I wrote one in Python," start="00:07:10.319" video="mainVideo" id=subtitle]]
[[!template text="and then discovered there's actually an existing one in core," start="00:07:12.639" video="mainVideo" id=subtitle]]
[[!template text="which you have to enable explicitly by passing an extra argument." start="00:07:14.720" video="mainVideo" id=subtitle]]
[[!template text="I've tried it and found it's not exactly as good as my own one," start="00:07:18.400" video="mainVideo" id=subtitle]]
[[!template text="so I improved this one and submitted pull requests" start="00:07:21.680" video="mainVideo" id=subtitle]]
[[!template text="until it was at the same level." start="00:07:24.160" video="mainVideo" id=subtitle]]
[[!template new="1" text="Rendering was the trickiest part of this whole thing," start="00:07:28.080" video="mainVideo" id=subtitle]]
[[!template text="because, well, I decided against using a library." start="00:07:30.720" video="mainVideo" id=subtitle]]
[[!template text="Not like there would have been any usable library for this." start="00:07:34.319" video="mainVideo" id=subtitle]]
[[!template text="My usual approach of creating SVG files was too expensive." start="00:07:37.120" video="mainVideo" id=subtitle]]
[[!template text="It just created too much garbage and took too long time." start="00:07:40.880" video="mainVideo" id=subtitle]]
[[!template text="I then tried creating mutating strings." start="00:07:45.120" video="mainVideo" id=subtitle]]
[[!template text="This was either too expensive, just like SVGs, or too complicated." start="00:07:47.360" video="mainVideo" id=subtitle]]
[[!template text="I tried changing SVG tiles, which created gaps between the lines." start="00:07:52.479" video="mainVideo" id=subtitle]]
[[!template text="Then I tried to create an xpm file which was backed by a bool vector" start="00:07:57.280" video="mainVideo" id=subtitle]]
[[!template text="and mutating this bool vector," start="00:08:00.720" video="mainVideo" id=subtitle]]
[[!template text="but the image caching effect" start="00:08:02.400" video="mainVideo" id=subtitle]]
[[!template text="made it just every nth frame to appear," start="00:08:04.000" video="mainVideo" id=subtitle]]
[[!template text="which wasn't good either." start="00:08:06.479" video="mainVideo" id=subtitle]]
[[!template text="Then I had the idea to just use plain text" start="00:08:08.879" video="mainVideo" id=subtitle]]
[[!template text="and paint the individual characters" start="00:08:11.440" video="mainVideo" id=subtitle]]
[[!template text="with a different background color." start="00:08:13.120" video="mainVideo" id=subtitle]]
[[!template text="This had perfect, perfect performance." start="00:08:14.800" video="mainVideo" id=subtitle]]
[[!template text="There were many optimization attempts until I got there," start="00:08:17.120" video="mainVideo" id=subtitle]]
[[!template text="and it was very, very stressful." start="00:08:19.280" video="mainVideo" id=subtitle]]
[[!template text="I wasn't sure whether I would ever get to accept the performance at all." start="00:08:21.199" video="mainVideo" id=subtitle]]
[[!template new="1" text="For sound, you only need to do a single beep," start="00:08:26.160" video="mainVideo" id=subtitle]]
[[!template text="so technically, it shouldn't be difficult to emulate it." start="00:08:28.560" video="mainVideo" id=subtitle]]
[[!template text="However, doing this is hard because" start="00:08:31.280" video="mainVideo" id=subtitle]]
[[!template text="Emacs officially only supports synchronous playback of sounds." start="00:08:33.039" video="mainVideo" id=subtitle]]
[[!template text="But there's also Emacs process, which you can launch in asynchronous way." start="00:08:37.200" video="mainVideo" id=subtitle]]
[[!template text="So I looked into it and found that mplayer has a slave mode" start="00:08:41.360" video="mainVideo" id=subtitle]]
[[!template text="and mpv supports listing on the fifo for commands." start="00:08:44.720" video="mainVideo" id=subtitle]]
[[!template text="So I've created a pipe, started a paused MPV in loop mode," start="00:08:48.640" video="mainVideo" id=subtitle]]
[[!template text="and always send in pause and unpause command to the FIFO," start="00:08:53.760" video="mainVideo" id=subtitle]]
[[!template text="and that way I could control" start="00:08:56.560" video="mainVideo" id=subtitle]]
[[!template text="when to start beeping and stop beeping." start="00:08:58.000" video="mainVideo" id=subtitle]]
[[!template new="1" text="So yeah, that's it so far." start="00:09:02.640" video="mainVideo" id=subtitle]]
[[!template text="It was a very educational experience." start="00:09:04.160" video="mainVideo" id=subtitle]]
[[!template text="I have tried out a bunch of games which were," start="00:09:07.200" video="mainVideo" id=subtitle]]
[[!template text="well, I almost say the worst ports of classic games I've ever tried." start="00:09:10.320" video="mainVideo" id=subtitle]]
[[!template text="It wasn't terribly fun to play them," start="00:09:14.320" video="mainVideo" id=subtitle]]
[[!template text="but was fun to improve the emulator" start="00:09:15.680" video="mainVideo" id=subtitle]]
[[!template text="until, well, things worked good enough." start="00:09:18.555" video="mainVideo" id=subtitle]]
[[!template text="I've learned a lot about how computers work at this level," start="00:09:21.760" video="mainVideo" id=subtitle]]
[[!template text="so, maybe, maybe I'll in the future make another emulator," start="00:09:25.120" video="mainVideo" id=subtitle]]
[[!template text="but I'm not sure whether anything more advanced, like an Intel 8080 emulator," start="00:09:28.880" video="mainVideo" id=subtitle]]
[[!template text="will actually run in Emacs fast enough," start="00:09:34.000" video="mainVideo" id=subtitle]]
[[!template text="but it's still an interesting idea," start="00:09:36.560" video="mainVideo" id=subtitle]]
[[!template text="because then you could actually have an OS inside Emacs" start="00:09:37.839" video="mainVideo" id=subtitle]]
[[!template text="and fulfill that one specific meme." start="00:09:40.800" video="mainVideo" id=subtitle]]
[[!template text="But if I try to do most serious stuff," start="00:09:43.120" video="mainVideo" id=subtitle]]
[[!template text="I'll probably use Chicken Scheme," start="00:09:45.440" video="mainVideo" id=subtitle]]
[[!template text="which is my preferred language for serious projects," start="00:09:47.040" video="mainVideo" id=subtitle]]
[[!template text="and write a NES game emulator." start="00:09:49.920" video="mainVideo" id=subtitle]]
[[!template text="And that's it. Thank you." start="00:09:53.279" video="mainVideo" id=subtitle]]