what's up what's up welcome back uh
today we're working on my operating
system it's an x86 operating system
titled stream
OS um it's an operating system that
we're kind of writing for fun SL
learning trying to get like a better
intuition about how operating systems
work um we're kind of just like
implementing whatever we need to do to
accomplish whatever we feel like doing
and with that is at this point is we're
trying to play Doom in our operating
system so
let me just pop open in a demo real
quick uh let me just pop my development
environment I think I forgot to set this
up before stream started so just give me
two
seconds just got to wait for it to start
up there we
go uh let me just make sure that we
committed everything from last time so
we say this is from end of stream on
November
22nd and let's check out our Master
branch and give a quick little
demo uh so what we're doing here is
we're building our kernel uh oops sorry
just a second forgot to sore some
environment stuff we're building our
kernel and it's going to launch in a
virtual machine called Kimu and this is
like the operating system as we know it
today so it has like keyboard support
mouse support we're like rendering this
like game to the screen uh and in
parallel we're running like this web
server so we can go over here and say
like hello hello and it'll like send us
stuff back
um it's like logging to us through
serial which qyu the virtual machine
very like helpfully forwards to us as
like just standard input output and we
have some like proof that we're like
doing some interesting stuff like
talking to the ethernet card and talking
to the clock and like doing memory
allocation and stuff like that as well
as like multicore we're doing like cpu1
cpu3 servicing stuff where it needs to
get
serviced uh yeah so that's where we're
at right now and what we're working on
is trying to get Doom to
run so what we did last last stream was
we got to the point where uh we pulled
in this project Doom
generic which is this
like a version of an open- Source Doom
engine uh that is kind of built for
porting uh because like you know it's
like a big meme to Port Doom to whatever
which is why we're doing this in the
first place and it's it promisees you
implement a few functions and everything
works um so what we've got
so far is like when we pulled this in we
found out that we uh were missing a lot
of like standard Library functions right
so if you try to call like print F like
we have to implement that for that to
work so we kind of went through one by
one and we fixed up all of the different
cases of uh it trying to use the
standard library that we had run into
until we got to here so we've
implemented kind of like this like draw
frame by just copy pasting what they
render into like our frame buffer uh
We've implemented like a little bit of
like time but other than that we haven't
really done
anything uh so we can't like play this
game at all right I like slam on my
keyboard nothing happens uh but we do
have like proof that the engine is kind
of working correctly and so what we want
to do today is like actually get playing
right so Implement any like keyboard
control and then kind of figure out
there's like other things that like
might we haven't implemented yet that
might come up when we actually start
playing right if that's just like a
pre-recorded video then we might not be
hitting all of the edge cases so hold on
just let me pull
open here like if I go into our lib
implementation there's a lot of stuff in
here that we still haven't implemented
right we haven't implemented like fa abs
and I'm surprised that that isn't
causing problems right
now uh so that's what we're going to
work on first is we're going to work on
uh getting like keyboard control
setup um we also spent a lot of time
leading up to this implementing Mouse
control and so uh I think that the Doom
generic source code doesn't support
Mouse as is so we're going to have to
maybe like like take a quick look to see
if we can Implement that otherwise it'll
be hard to control and yeah we'll just
kind of see where we
get uh so the first thing to do would be
to implement uh DG get
key and so let's just look at that so
Doom
generic uh in it's read me it says I
should Implement DG get key to provide
keyboard events and so let's look at
like an example of one of their ports to
like Linux so we can look at like Doom
generic
xli and this can tell us like oh here's
what they expect to see
so they take in a
key they reassign it and they return it
and so they convert they're basically
converting
from uh xlib Keys like X window system
key presses
into um keys for that are probably
defined in like the Doom generic source
code and here they add key to this like
they add the key to the Q and then
probably when they get the key they read
the key from the queue
and then do some like shifting of
stuff okay so it looks like they're also
expecting like a return one on success
and a return zero on uh nothing to
do so let's maybe take a look at
uh who calls DG get
key who calls
this um none of these guys don't look
for this guy okay so while this guy
returns
nonzero he updates shift status okay
which is
what if key equals key right shift okay
sure um change change is equal to one or
negative 1
depending and here he assign equals
shift down which is like I guess a
global variable is the shift key
currently down sure okay
so I see so they check if right shift
was pressed and update their Global
State cool nothing too interesting
there
uh then they check if a key was
pressed and if it was they do some like
translation
otherwise it was not pressed it was
released and they do some other
translation um and it looks like they
had some like mouse support code that
they uh stubbed out so that that'll be
helpful
later okay
so where is this translate
key he does nothing
okay uh it would be nice ni to find like
these definitions that they were using
of like key up key down it would be also
be interesting to know what is like this
guing so press I guess is just uh zero
or one it looks like is what they're
expecting here right they're looking for
or zero or nonzero is really all they
care
about so it looks like maybe the xlo
implementation was just packing that
into the
data um and then the key is just a
character like a two 8bit character so
where is this like to
finded uh these must
be
here no these
where key Escape like where is this guy
set he must be in a header somewhere
Doom Keys here is what we're looking
for okay so this is
is the definitions that we're looking
for I
see and so I guess we just want to go
through each of these and convert them
from like our key codes in our operating
system
okay so we can go
into our code hello hello what's
up um and we can and start
implementing
DG what was it get
key DG get
key uh whose function is like this and
we'll just quickly convert him so this
is the function press is
a
pointer to an i32 and doom key is a
pointer to an unside car
which is a u8 in our world and it
returns an
i32
okay and these actually are mutable
because we're these are out
parameters and for now we'll just return
nothing what would be nice is to like
check if something was
pressed um and here's where it gets kind
of interesting
so let's look at our keyboard driver I
actually don't remember how this works
so our keyboard driver in our operating
system uses
PS2 uh which is this like old ass
Port uh that is basically like a Serial
device um
and basically he looks for scan codes to
come in and that's it so we just like
read the data that comes in on that port
and we say like what number is it
essentially and I think that this guy
was written with async in mind so it
looks like he has like a read function
that just waits for a key to be
pressed and that's kind of it um so this
pole read future I guess is probably
waiting for something to happen yeah so
he waits for the status to
change
on uh yeah I guess it just waits for
like a status register to change when
it's set then it reads the key we
pressed so what's kind of odd here is
that like our implementation of DG get
key isn't in like async code and we
haven't even like set up anything async
at all so I wonder how we want to handle
this
um I guess we could set
up
Doom the Doom
code as a like a future that will just
run on one core and will never return
and then maybe we can like do something
else in parallel on another
core and that core can just like pull
this read or maybe we don't need we
might not need an Executor to handle
this
actually we might be able to say
like let read future is equal to uh we
need to get our like reference the
static kernel so let's just gra get a
reference to our driver really quick PS2
is the best port ever made you can break
pins just watching
it oh did it were they did they break a
lot I feel like I I remember having a PS
keyboard and I don't remember it being
like
problematic uh but maybe I didn't unplug
it that
much okay so let's just try getting like
a reference you broke a lot of them all
right all right I can see
it
um so I guess on each call to this guy
we might want to like hold on to a
future over time so maybe we want like a
static
um we'll figure this out in a second
let's just see what how to get a
reference this guy so is my language
server set up am I in the right context
it is so I should be able to say Kel
nice do
PS2 do
read and this will give me like a future
and I can like check this future to see
if anything's happened
um and if it
hasn't that should be okay so I think I
just be able to call like if I pin this
let read pinned I should be able to
call
uh uh What's this called core pin pin
read
Fe and maybe I'll just rename this like
this and I think may I have to say this
is mutable and if I say read.
pole I think I should be able to just
check if something's
happened I remember learning how all
that work all that working I think for
some companies for a while some
companies made PS2
keyboards due to them having lower
latency compared to USB I could see that
actually cuz the implementation of the
driver of this guy is like interrupt
based when I press the button like an
interrupt fires on my PC like
immediately and USB from our USB
implementation looked like it had like a
maximum or like a minimum latency of
like 1
millisecond because you're supposed to
pull once per millisecond and so I could
totally see that being true but I don't
I don't I kind of figured that I must
not understand something on the USB side
correctly uh because we use USB gaming
mice now and I I find it hard to believe
that like people wouldn't care about 1
millisecond latency for like super
competitive
Shooters but who
knows okay so let's try to pull this guy
and he's obviously going to [ __ ]
cu uh it doesn't work uh let's export my
cross compiler I forgot to do that and
let's just kind of see what we
see so we look for an error he complains
that uh we we're not we don't have the
future trait which makes sense so we'll
just use future trait somewhere future
future and so now we should have this
poll method
available and now we have to pass in a
context so I guess we have to make a
context and how do I do that
from Waker I guess and we pass in a
Waker and so that means we need a
Waker uh which means that we need
to con like create
that and in our case our Waker is going
to do
nothing
uh because we we're not actually ever
planning on pulling this again I think
that we can get away with just calling
this future one time like right now and
then dropping it if it doesn't ready so
which means that I think that our Waker
can just be [ __ ] so how do I create
a Waker again Waker is in Rust standard
library and how do we like create one we
have to make a raw wicker
first
okay uh which we create a raw Waker V
table here we go this what I'm look for
so let raw w wer V table is equal
to uh raw Waker V table new and then we
pass in this
[ __ ] uh and all of these guys are just
going to
do
nothing I
think uh
okay so I think this is static raw W
review
table
and he's going to be a raw Waker V
table and he's going to need to take in
some functions that have these apis so
we'll just check this here I think I've
actually done this before and uh in like
the future stuff way back but I think I
lost it so I think we have to do it
again so this is an unsa function clone
and he takes in data and returns raw
Waker so we'll figure that out in a
second this is unsave function wake and
he takes
in data and returns nothing this is
unsafe function wake by ref and he takes
in data and does
nothing and
drop I guess we can just say null
future fun
function and do nothing and just pass
this to all three and all I have to
figure out is clone so clone must just
say raw
Waker I guess we'll make our V table up
here and we'll just pass him plone null
future function null future function
null future function nothing's going to
happen cuz we're not actually trying to
do anything here we're just trying to
get the API to
work
um raw Waker V table could be con
instead of static that seems reasonable
I think that's
true and then in Clone we need to make
the raw Waker which is the same thing
we're trying to do here so we have raw
Waker which we need to import we
construct this guy with uh core pointer
null right we have data we're not
actually going to do anything with that
data and then we pass in raw Waker V
table and then this guy is the same
thing and then we need let Waker is
equal to Waker from raw Waker ooo what a
pain but I think we're good to go and
now we can pass the context I think this
has to be mutable and so we press and
mute I
think cool and so we can say uh let's
see if this read future is ready and we
can say if we got
something uh we will get pole
ready and we'll return the value and if
we get pole pending
uh we can just return zero like nothing
happened so I guess return let's double
check what the xli implementation did so
in Doom generic
xli uh they return zero if the keys
empty so yeah we just return zero
nothing has happened no key has been
pressed uh and then we say Here let scan
code isal to
this and then all we all have to do
later here is match scan codes to
keys so we'll say uh rest is equal to
one and doom key is equal
to match scan code and we'll just
return we'll have to figure
out what to do later
here yeah that seems reasonable that
seems
reasonable so maybe now all we have to
do is maybe we should like log our scan
codes and we can just start like
stubbing out what they should be so
we'll say uh got scan code this and
we'll print out the scan
code and then we'll just press buttons
and see what they match up
with I think that that'll be all we need
so let's see where it's complaining so
it doesn't like that scan code could not
be format with default formatter because
uh it doesn't think
think that it's a number for some
reason
um so what's going on
there yeah so he thinks that this is
nothing so why is
that what's v here V is a
u8 so shouldn't this think that it's a
u8 like why doesn't this
work uh let's
see
let's C check in watching all this
really makes me want to make a custom
kernel again I'm getting into the laptop
I'm getting my laptop back tomorrow so I
might look into picking that exact
project back up again yeah it's pretty
fun it's really like there's something
really what's the right word um like
satisfying or like calming I guess about
it you just kind of you know you you you
there's so much progress to make so
quickly for something that's so new and
so and and it's really satisfying when
you get it to work so it's pretty
cool
cool uh okay so he doesn't like that
Colonel is an ampersand reference but it
needs to be an ampersand mute so I think
I can just stay here get
mute uh and I think this guy needs to be
mutable as
well and then I think
now this will
work let's see yes that compiles and so
now we can probably just start like
pressing keys and seeing what happens
um so actually it still doesn't like
that what's it complaining about now uh
we have duplicate definition of DG get
key because we had our dummy imp
Plantation over here so we just delete
that
easy and come on I guess compiling in
release mode is just going to make my
compile times longer for no real major
benefit right now so I'll just sub that
out all right so we're launching doom
and if I press a button so pressing it
gives me 28 releasing givs me
156 and I guess maybe I should just
start I should probably write down a
bunch of these at once so that I don't
have to do this over and over again so
uh I guess I'll write them over
here uh so let's press enter is 28
1556 and we'll probably want up up
oopsies I'm pressing the wrong window up
is
72 oh
it's kind of two numbers
22472 oh I think I read somewhere that
there are like composite scan
codes so when I press up and down I
think that I'm probably getting like 224
for something let's see if we can look
up uh that again so under PS2 scan codes
OS maybe is where I saw
this
um special
bytes no that's not what I'm like for
there were like scan code sets here we
go yeah yeah yeah yeah scan code sets
and I think I'm using scan code set
one which probably means that I actually
don't need to manually press these
buttons at all um let's look at like
this so enter press is 1 C which is I
got 28 so 1 C is 6 16 plus uh 10 11 12
which is 28
nice um and let's look for
like let's see up
arrow is up arrow in this scan code list
up e0 48 so that's probably what we're
seeing assuming that by cursor they mean
the arrow
keys uh we can probably Dodge this by
just not using up down left right I
don't really want to handle composite
keys right now so we'll just use wda
instead uh and I guess we'll just
instead of pressing them one by one
we'll just use the
stable uh was there there was is there
like a conversion from press to
release it does look like they just have
those scan codes manually here as well
okay all
right um
cool what did I do in my like game
class here
I I see I like checked for down and up
presses and then as I like kept those in
my head so I guess that we probably have
to do the same thing here we'll see
though I'm assuming that in Doom generic
what was it Doom I input or something
like like do they hold the state are
they looking for key events like press
and release or are they looking for Key
State and it looks like they're looking
for key events which is sick so I don't
have to do any State Management on on my
side um so here I actually shouldn't be
unconditionally setting press to one
here it depends on what key I
get so let's start with just
enter so zx1 C we go press is equal
one and the key is where do these come
from Doom
keys. key
enter which is
13 uh so Doom key is equal to 18 no why
am I saying 18
13
okay and on
release we're going to
say
ZX
9C this is press equal zero Doom key is
13
okay
cool and let's see ohoh
error uh because I didn't match
everything so in
here we'll just do nothing if for any
other case is that just top bits is zero
and press and one release that seems
like very likely I noticed that as well
but I wasn't sure so I didn't say it but
you're right I I think there's a good
chance okay so we press enter now stuff
happens we're in the
game and now we just have to
implement some other stuff cool cool
cool cool
cool
um so I guess we'll just copy paste
These Guys these are the important ones
probably and we'll just kind of stick
them here in a Block in a comment just
so that we have uh them written down and
really it's kind of silly to do it this
way one I could really I should probably
be using these by name um so we'll just
quickly say delete this turn it into a
const uh this is now going to be a
u8
and
he's equal to the value here and we'll
do that a few times and we'll pre
preface this with doom uh so that we are
know which where we're
going and did I already Define scan code
somewhere input keyboard a up I do have
these written down somewhere
so let's kind of just pull these guys in
as
well
uh and start matching them so we'll say
w down is goes to
uh press is one Doom key is equal to
Doom key up
Arrow
uh W up goes to do press do the same
thing but press a
zero and now we replace W down with a
down and we move to the
right like this
and we do the same thing
for
D but this
is down
arrow and almost
certainly uh I don't know you know you
could argue that there's a lot of
duplication going on here and I would
agree but the question is how would we
is there like a better way to structure
this you could maybe like do it with a
macro in some way right like generate
this switch case you could also do it
with like a jump table by like dropping
all of this into
a uh like a vector that you like jump
you specify the with a scan code and
that like automatically Maps but I think
this is like fine um I don't know why I
thought a was right so let's just fix
that a should be left D should
be
right and S should be down
Okay so let's quickly run
this I can see a sparse array if you can
do that in rest yeah or like a hash map
which is like close but not quite so
here I can move these guys I can start a
game and I can move around which is
pretty
sick uh and now I just shoot and I guess
we're probably playing at that
point I guess do do I need jump how do I
get around here probably not I guess
there was no jump in
Doom I'm surprised that this is
working this well already okay so I
guess we'll just add shoot and that's is
that all we
need uh use as well okay so for use
we'll use
e
um
so where is E on
here I guess it is probably F like it
could actually be faster for me just
press the buttons
a especially if that top bit is State
then that could just be mask and the
rest could be mapped yeah that seems
reasonable uh I guess we can
check
uh so
maybe
we could let's we could try it
so this these are definitely all just
setting the top bit for
sure
um so maybe we will do that we'll say
here are down Keys we'll check our e
down as well e press oh [ __ ] e pressed
in SC go set one is oh that's
Escape e press Z one
too is
this and I guess you could like do
something
like uh zerox1 one W down goes to Doom
key up
arrow and then we just say as s
d this this goes to left
arrow down
arrow and right
[Music]
arrow uh what else we have we have e
down so we'll turn this to
down e down goes to Doom key
use and is control a composite code or
is that
easy
control press nice zx1
D so we'll
say control down is
0x1d and we'll map control down to Doom
key
fire okay so maybe we'll start with that
and we'll just say into and we'll make a
hatch map here so we'll say
let key
mapping match on scalers has got
optimized a jump tail by Russy yeah I
guess it you could argue that
like
uh if I did like a hashmap here that is
technically
worse um really I want like
indexes like you could make
like it's not too it's not super trivial
eh where like the the scan code version
I guess is technically better I wonder
if you could uh let's just try something
if you define a macro that says
like
set
key I think put the exclamation mark
here or maybe
here you could take in like a
from from exper to two exper
and could you just like emit this
code so you could say
like
um right like sorry let's think about
[Music]
this here we
go uh W down blah blah blah oh yeah if
that's the case you could break into a
function that just takes in the key code
and returns to the map key the match
TXS yeah that does just seem better huh
yeah I like that you're right so you
would just
say like this turns into a let Doom key
is equal to match
this
essentially
uh and we just have to do a quick
little conversion here so we
say this guy goes to this
yeah that does seem a lot nicer uh so
this is match scan
code yeah that does that seems like it
would work well and then we can say uh
press is equal to Doom key shifted right
by
8 or scan code sorry scan code shifted
right by
eight and doom key with the Doom
key yeah that looks a lot nicer and what
was the last one we had zx1 C is
enter Doom key
enter what did I not match this oh I
just didn't have that copyed so we can
look at Doom keys. H and we can Define
Doom key ENT
13
and we can say cons enter
down u8 is equal to
0x1c
okay doesn't the key still need to be
masked uh oh yeah you're right this is
and
z7f there we
go
okay so that looks a lot nicer a lot
nicer and uh it doesn't compile so let's
just fix that real quick so Doom key
equals Doom key oh because I've reused
the I guess we just do this star Doom
key is equal to this instead of doing
like a light out like that there we go
does that compile almost
error scan code shifted left by 8
expected i32 found you8 is scan code
really a you
a a integer it's a
u8 scan code oh it's pressed an i32 yeah
I
see as
i32 we're close uh we forgot to say that
anything
else we'll just map to zero or
something and
and what's it bitching about now uh scan
code attempt to shift right by 8 i32 oh
I'm just an idiot this should be
seven okay let's see if that does
it okay
so looks like that's
working and I
can okay definitely
uh we're not
releasing
correctly we're actually yeah we I think
we're our releasing is wrong so let's
just uh print
line
uh scan code and
press like this and let's just double
check that we're not like heavily
[ __ ]
up uh oh I've just got my press
inverted uh this should
be uh I guess we just do one minus
this and that will fix
it I think we'll
see
okay so we start game I press forward
backwards right left
shoot how come shooting isn't do
anything okay uh did I get use is this a
door yeah that's a door I can open the
door so I just can't shoot which is kind
of weird oh okay so uh on my keyboard
I've got caps lock and control swapped
and so it looks like the VM is actually
using the real control instead of the
swap version of control so I should see
seeing that coming and can I like play
the game shoot shoot shoot shoot shoot
shoot okay
cool and I guess
shockingly that's it like are we done I
really thought that this would be harder
than
that which is kind of holy [ __ ] how much
health does that thing
have um I guess we're not we don't have
Escape yet so we'll just map that one as
well
um music now [ __ ] okay so we're far from
that uh I have like no audio driver but
you're right I should get
that I can't really consider this done
until that point so maybe that's what's
up next I haven't really decided so
there there's a good chance that we'll
come back to it with music um I guess
what I wanted to do is mouse so I guess
let's just map in the Escape key now
just to make sure like just to save that
we're we've kind of got everything so
Escape was 27 Oh we have that
already Doom driven development I like
it so key uh Escape down will make this
Doom key
escape this meme is taking a lot of time
hey this is the life
man this is this is how you this is how
you do
it you you let yourself get distracted
and then just go down the rabbit hole
forever ZX 81 is
escape so Escape
down what did I say it was I already
forgot
z76 uh and we'll run just double
check DDD after nnn Doom driven
development after
[Music]
I don't know what the ends are I can't I
can't figure it
out uh oh no I'm getting one I must have
been on the wrong table so this
is
one give it a
sec all right new game hit escape to get
the menu back up sick okay so I think
that we can call that
basically
done and we can say that the next thing
to do is mouse
support so we support kind of inter
kernel Mouse we don't we have to uh
enable a bunch of code to get back to
the point where our USB system is
running but like theoretically we do
have support for the mouse uh Doom
doesn't uh well sorry Doom does in some
engines um but it looks like they kind
of comment that out here so if you go to
I
input they have like the the engine has
support for like Mouse movement with
relative movements like this um but the
conversion code for Doom generic does
not
so I guess what we could do is we could
either Implement a new function that's
like DG get mouse or uh we could do
something we could like hack in a type
of key output that's like
mapped to Mouse movement but I guess
like if we want sensitivity of the mouse
uh we need more outputs than just the
keys so probably like a new function
makes a lot of
sense LEL content Ador now just running
games in G do is in search for some
level fun what are you guys doing around
here usually um yeah Okay so we've kind
of gone through start to end uh We've
like we started from nothing and now
we're at the point where we have like an
operating system that like boots and
runs um well I should say a kernel the
boots and runs uh has like a web server
and like keyboard mouse drivers Graphics
to some extent and now we're trying to
say hey let's get Doom running because
this guy on the internet said I couldn't
well he didn't even say that he said do
you and I'm like I take offense to that
um so that's what we're doing now is
we're like injecting Doom into our
operating system and see if we seeing
what we can get
going uh yeah so next up mouse let's do
that so I guess yeah well let's start by
trying to get the mouse subsystem up and
running so before we had was we had this
like demo function that spawned like all
this async
[ __ ] and then ran this like executor
that ran the ran all of us [ __ ] the [ __ ]
in our
kernel
um then what's
like we commented all this out to get
Doom generic running on our like single
core but and so like either what we
could try to do is we could try to
convert this like Doom generic Loop into
something that's as compatible which
seems like it should be possible to do
right because like Doom generic tick is
like give me one frame and then all we'd
have to do is like wait after that
frame using a like async
sleep or we
could uh just let the Doom generic code
run on One Core never return from the
future and just run everything else on
the other core so let's look at like
Doom generic tick and see where that
comes from sry it's Doom
generic
tick
and he returns nothing it would be nice
if we could
like find
out how long to sleep cuz like who's
calling there's also like a sleep
implementation that we're supposed to
provide back to Doom generic um DG sleep
something what was it called it was
called Sleep Ms so let's see like who
calls
that and if we can like pull that out to
the top level
essentially so he
has just a timer function is the only
place that's used it looks
like but this this guy must be called
all over the place maybe I
sleep where okay so he's
called block until
start where what's
this D
display what happens in like the tick I
guess I want to know
like Doom generic tick what does he
do he starts the frame tries to run
tick then runs D
display
okay with next frame with current slate
so who
decides who decides uh when we should
wait between frames cuz I'm assuming
that frames don't have to be drawn I'm
assuming there's this like running out a
frame rate but I guess that's like a
pretty crazy assumption right I'm
assuming that uh the game the game
engine is
targeting 60 frames per second or
something but maybe it's just rendering
like as fast as it [ __ ]
can uh that seems also possible what
happens in try run
ticks uh oops try run ticks
wrong thing here and the Doom
Loop um so he checks the
time
jeez
okay interesting interesting interesting
I'm guessing monolithic kernel yeah it's
all all happening in one one binary
right
now I guess what we could do is we could
count how many times we do
this
uh and see if they're sleeping because
it does look like the I sleep function
is not really being called with like a
variable time trying to get a certain
frame
rate so it does seem like we could put a
like targeted frame rate
here and
sleep in between
frames uh which could be maybe a little
bit interesting
so let's see what our like current FPS
is
so
I guess we'll say let frame counter is
equal to zero here we'll increment the
frame
counter every once in a
while
and every every some amount of time we
should find out if that's good or not so
we can say let kernel is equal to our
static
kernel we lock it because it's in static
name space and we say uh let kernel is
equal to Kernel get me
mute and we can look at the time in here
so we can say kernel mon time what's it
called what is this type this is a
option M kernel so we just unwrap we
have kernel monotonic
time and we can get time and we can say
let mute
last FPS print was at
zero um and we can say we want to print
the frame rate
[Music]
every
second I guess um so we can
say let FPS let one let num ticks per
second is equal to Kernel monotonic time
tick frequency which is number of tick
per
second um and so we just say
if that now is this we say if now is
greater than last FPS Print Plus num TI
percent
second print line FPS is equal to
approximately frame counter this is like
we're we're skip skipping some details
where you know maybe this took too long
and that's not fair uh but we'll just
we'll just print it like this and assume
that we're doing it close enough and
then we'll say frame counter is equal to
zero reset it and last FPS print is
equal to
now okay so now that will give us a clue
upsies
uh for if we can like handle a frame
rate cap externally in this
Loop um this should be as
i32 let's give a quick look still is mad
at me what's he bitching about uh
expected zero found uze yeah that makes
sense uh so last FPS
print this should be as youze I guess
and I think then everybody else all the
types work out yeah nice
nice nice
nice so we give it a sec to get
moving and we're running at like 45
frames per second I wonder if I run in
release
mode um if we're going to start getting
a lot faster because there's a good
chance that we're losing a lot of time
in these like frame buffer copies we're
also we also haven't optimized the Doom
source code at all I think the compiler
flags that we're sending just have no
optimizations on so we should probably
fix that as
well
let's just take a quick
look yeah it does look like there's no
real cap it's also kind of funny that
the maximum frame rate we can run here
is 70 frames per second that's crazy um
but let's try turning on optimizations
for the Doom
code uh so somewhere in here we can just
say like opt level
two and let's see if that fixes
anything
I sorry I shouldn't say fix let's see if
that makes it go faster I there's a
chance that we start like crashing again
because we start calling different
functions because of the
optimizer we'll
see
H is my CPU just like [ __ ] railed or
is this
really it is interesting so I guess that
that's just like the max that I can play
at and I guess uh if we wanted to limit
it this to 30
FPS uh we could just in
here we
could we could like halt until we get to
the right time so we could say
like let
Target Target end is equal to Nom tis
per
second uh Let's see we were trying to go
from
like trying to go from like
0 3 033 for 30 FPS times this is in
seconds time 6 per second gives us like
a number of
Ticks Plus
now okay and we can just
say
um we'll say that like let me last frame
is equal
zero and we can say if now is greater
than Target and last frame
now uh no we just want a while loop here
we want say while now is less than
Target
end uh
halt or Arch
ASM
alt I think that that should limit us
down to 30 FPS I
think there's a good chance that I
[ __ ] something up there but let's
see oh now needs to be updated that's a
really good
call that's a really good
call let's give a
sec
all
right so that okay all of this is to
say uh all this is to say that it looks
like we could integrate this with async
code pretty easily right because my
concern was if is if we made this like
if we made the Doom Loop async um the
way that our like multiprocessing works
right now is it uses like the rust
ay8 um is there
like uh anyways the point is it's called
like Cooperative multitasking and so
like each chunk of work uh he doesn't do
anything or he he sorry he doesn't let
go until he's like decided that he's got
a point to let go and so if we were to
just like say Loop Doom generic
tick uh we would never release the
executor and so like if we're in like
you know if we have like eight cores
that's fine but if we have one core that
means that like the Doom the Doom thing
will block everything that happens
forever um but it looks like since we
don't have like uh the frame rate
handling is can be done by us we can
just say oh we'll asyn sleep so whenever
we're like we're waiting for the next
frame to happen we'll just like say okay
you can go do something else
now which is pretty sick which means
that we can actually integrate this into
our like normal kernel demo which will
make everything else a lot
easier
um yeah let's do
that uh so the only problem here is that
we have like put our kernel in this like
static name space and locked him with a
spin
lock uh but that's clearly going to be a
problem if we're running our kernel demo
which would also need to lock that lock
so I think what we'll just do will just
not do
that I'm pretty sure that we can get
away with that so instead of this like
once cell that we're using to create the
kernel
um we can just use a unsafe cell here
instead because uh I don't you know uh
it might not be right but it'll
work uh and so then we can just say that
the initial state is Maybe be like we'll
say it's an option kernel so that we can
assign It To None
initially I think I do this on new
none damn I know Russ is rising
popularity but hardcore guys like you
adopting it makes gets me wondering I
was really in doubt of using cc++ for
future open jail related projects should
I really switch to rust ml engineer here
haven't used cc++ in this
college uh okay so my take on this uh I
think rust is for like a pretty specific
subset of people um I think that if
you're somebody who's like pretty you
know if you're like especially if you're
an ML and you're like coming from python
land um Python's kind of like do
whatever the [ __ ] you feel like and if
it works it works and that's
great um and C C I think is a lot closer
to that except that c kind of lacks the
like Library support that python has
right python if you want to do something
you can like just like pip install
whatever the [ __ ] and like it already
exists um rust I feel like is for
like how do you call it like how would I
explain this like purists almost like
people who really really want
like like almost like me like to the
point of like OCD like correct apis
right like if you want if you're the
type of person who's going to spend like
a lot a lot of time designing like a
class for something and you want like
the API to be perfect right rust is like
really like
facilitates that type of user in that
like you have like because of the way
that the language forces you to write
code you almost have to like overanalyze
and create really strict
apis um which means that like once those
apis are created it's often like very
nice to use and like then you get into
this case this state where you're like
oh now that the type system is like
perfectly told me what I want to do like
you can write code that like almost like
writes itself to the C like right you
just like kind of like do what the types
tell you to do and then you get to the
end you have like this like perfectly
handled error code
base um but I would say like if you're
trying to like get [ __ ]
done uh and you just want to like
prototype something and bang something
out which is like pretty common in
Python
land uh you might get frustrated by rust
like it it tries to force you to handle
all cases and force you to like think
about things and often you don't want to
get bogged down by those details you're
just like [ __ ] [ __ ] off just let me do
what I want and like Let It crash let it
be wrong and so I think it's like hard
to write wrong rust code like you have
to go out of your way to do it I guess
or I shouldn't say that
it's your the code will I I let's just
say that in Rust often I spend a lot
more time upfront writing something for
and then have it work the first time
versus in like cc++ where you like write
something you bang it out quick and then
you have to like handle all these like
Edge crash cases so it just depends on
what you
like rust is like haskal but it really
works I've never written haskal but uh
that makes sense to me I agree with
that okay and so well what I've been
doing when I'm writing it for the
colonel is I've kind of just been like
you know you'll see a lot of me just
typing unsafe and like break rust
guarantees to get the to bang something
out uh but that's not normal people
don't do that very often uh yeah okay so
we're back here I'm going to trying to
get make my unsafe cell colel because I
want to just like initialize it once and
then be guaranteed that it's initialized
for the rest of
time uh maybe I can do
like maybe UN in it might make more
sense
and then I can put in maybe UN in it UN
in
it
and then everywhere where I was like
locking the kernel before I'm going to
have to like rewrite that code so let's
just look for errors and holy [ __ ] These
Warnings are starting to really bother
me so I might actually fix that cuz I I
want to actually see my errors so I
wonder if there's like a way to just GCC
disable all warnings just for now
DW is minor W so in my build
script I can go and say flag
DW and hopefully that'll do
it the Win It web GPU General guey c r
is getting really neat while a lot of
the guoy framings are still young their
portability is outstanding must be
buildt everywhere minimal effort yeah
it's pretty I will say that like writing
a like you I in something like rust and
igui is so much nicer than trying to
write something in like C++ and QT there
are again tradeoffs but yeah there is
something that's really sick about like
the the forced immediate mode gooey
Paradigm yeah it it feels
good and I'll I'll say that in C++ with
QT like if I'm writing like QT C++ uh
when something doesn't work or the way I
want it's like a massive pain in the ass
where with the young gooey Frameworks
it's kind of nice where that like when
something doesn't work it's really easy
just bang out your own widget uh which I
found a lot harder in like other
languages um okay what's getting what
does he
like cannot find the type May on in it
so let's just import that so I think
that's from core May uh
core I don't know where that's from
actually
maybe UN in it and
rust core
M
okay uh this cannot be shared between
threads oh that's
annoying so I guess we'll say we'll just
wrap this in a type that can be so we'll
say Pub struct static kernel is just
this
thing and we'll just mark it as sync
we'll say
uh unsafe imple sync for static
kernel it's probably fine and then here
I'll just make this a static kernel and
this is static kernel unsafe cell maybe
on in it there we
go okay so now he's getting a bit mad
because before we had this mutex
locked and uh we don't want to do that
anymore so I think we can just
say uh let's make like a function on
this to make it E easier and maybe we
can oh yeah we'll just say imple static
kernel and we'll say function get takes
in self by mutable reference and
returns a reference to a
kernel and all we have to do here is do
self. z.
getet and then we St it and
uh assume in
it and this all is on
save all
right okay so what did we just like what
the [ __ ] did I just type here uh this
self. Z doget will return a pointer to a
maybe UN in it and then I do reference
that and assume in it and get back the
kernel does rust have async Prague um
rust has like an
async keyword that lets you you
uh like construct functions that will
automatically generate like yield points
like similar to like python generators
or something like that and then they
have like these run times that you can
use
to uh like move those pieces of work
forward so like yeah it does have some
form of like async um but I don't know
it depends on what you mean by async
it's not as simple as like in JavaScript
if you just type like a wait it's a
little bit more complicated than that
but not by
much
um okay so now all these places where
we're locking the kernel we can say
kernel.
getet and we going do the same thing
here kernel
doget and here we can say
get uh this guy should actually
return does uh why does this guy have to
be mutable does he have to we'll see
this is we have to do this it ourselves
so we'll come back to this and this is
Colonel get
um this doesn't
like that it's a reference to Temporary
value um so can I
like let kernel is equal to or let maybe
uninit kernel is star self. z.
get and then can I do this like assume
it uh no cannot move out of raw pointer
so I need to borrow here I
guess and probably I need like an assume
in it ref or
something yeah yeah yeah assume and it
ref okay and so now it's he's
complaining that the colonel cannot be
borrowed as mutable and so this is like
probably a problem uh so I guess what
we'll do is we'll just make our PS2
keyboard we'll like put him behind a mut
text or
something so that I can read
him without having to get a mutable
kernel because we're going to have
multiple people trying to use the kernel
at the same
time uh which is
annoying so I guess here we will say
mutex PS2
keyboard and that's fine and we'll
just lock them up here uh so here when
we have PS2 this is a now needs to be
mutex locked so we
write mutex
new and here we have this like all we
have our brick breaker game that we were
working with before and I'm just going
to comment out the whole brick breaker
game we don't need him which makes this
whole thing
simpler uh no method read for this guy
so you have to just say uh let PS2 is
Colonel PS2
lock and this is the PS2 read and this
has to be
mutable
and awaiting the future and calling
output a wait he is so I think that
that's fine that's just warnings that we
can probably
ignore oh
[ __ ] uh sorry I was supposed to lock
this mutex with from an async context
but we're not in an async context we're
in a synchronized context so we'll use a
spin lock here instead which will just
make this easier for now even though
it's not the way I would want this
organized
later okay so I think we're back to
compiling which is pretty cool pretty
cool and so now all now we can probably
start integrating our game here so we
can make our Doom
Loop let Doom is an async
block
and he's basically just going to
call where is my Doom stuff Doom
DG where is all this
stuff here here we go he's going to call
Doom generic
create and he's going to have a loop
where he does a
tick and we'll just say let start is
equal to self
dot uh
time now or get I
guess and we'll say let end is equal
to start
plus uh
0.333 times for 33 milliseconds for 30
frames per second
times uh the monotonic
time tick frequency and this should be
factored out we only want to call this
once so we'll
say Here let frame time is equal to
this start and so the end should be
start plus frame
time and then we
say
sleep
for
uh oh I
guess sleep is in
seconds so we actually need to check how
long we've spent which is
different um so let's say tick freak is
this
guy and instead we want to do let end is
self monotonic time
get
and here we have to convert that into uh
a sleep time so we'll say 0.033 minus
end minus start
times or divided by The Tick
freak and I'm pretty sure that's right
so we can actually do a 1.0 over this
now and then do a multiplication which I
think is faster if I remember correctly
if I remember
correctly and we just say this is as if
do and then we can do a crate sleep
sleep for this amount of
time uh but passing in a reference to
self. monotonic time and self. wakeup
requester and then we wait this and we
should have like an async sleep in here
now which is pretty sick and then all we
have to do is throw in a spawn to
Doom
cool uh why is that
okay and so now I think all we have to
do all we're missing now is uh
initialization of our kernel with our
new thing so we'll just
say uh kernel Z get which gives us a
star to maybe an init and we'll just say
uh
right
and here we pass in the initialized
kernel I
guess he doesn't like that so let's see
what he's bitching about uh he expects a
maybe an in it colonel how do I like set
this guy maybe an in
it
um oh I say maybe I didn't
new um I see I see so I
say this
guy is equal to maybe on in it
new and then I pass him the
kernel I don't know if anybody in the
kernel is expecting to have like stable
memory addresses so this might actually
start [ __ ] [ __ ] up but we'll find
out let's try running our demo and just
see what
happens um so here we can say
colonel. get.
demo and I guess our demo takes in mute
self so that's going to be a pain in the
ass I guess this guy also has to be
immutable reference to
self which is going to [ __ ] up all of
this that's so
annoying
H uh okay well uh what we'll do now is
we're just going to lie we're just going
to lie and say that this is takes
returns a mute
kernel and uh
that's maybe going to cause a problem
but that's
okay we'll see mutable borrow from
immutable
input
um why he doesn't like that
interesting I thought that would be
allowed do is it because like the
lifetimes are tied together if I say
like Dash A and D B can I say these are
separate things don't worry about
it I
can all
right let's take a
look
I wonder if this is going to like run at
all I guess we'll find
out uh so we're
[Music]
booting nothing's oh okay so the Doom
stuff is
running and is my web server running oh
yeah all this other stuff is running too
which is
interesting so here if I like go to my
web server now on this guy is he
running oh that's pretty cool okay okay
so we are I think we're in a state now
where uh Doom is running from our like
async context which means that now if I
start like moving the mouse around we
should actually be able to
like get that piece of information so in
our cursor
service maybe I can just write
down uh position
is
position
um and I guess we can actually start
using like infl logs and stuff too
here taking a look taking a look and so
may maybe now if I start like w wiggling
my curse around we'll start to see
movement on
it sick Okay so we've got Doom running
and we have mous movement
which is sick I guess technically we
don't want to use the cursor here we
actually probably want the uh we only
care about
the relative movement which comes from
the mouse
driver um so in our Doom kernel or not
our Doom our Doom section we're going to
want to like somehow retrieve
updates from the
mouse uh
okay
let's think about this let's think about
this I guess like in theory you could
get around some of this like [ __ ] of
like this kernel having to be in static
memory by making like static channels
that you pushed to and that the Doom
functions readed from then you can
handle everything like in normal asent
code from the kernel um but we can skip
that for now but like I think that like
probably what I would do if I were to
like try to do this for real
is in my
like Mouse code I would like push to
some cue that the Doom callbacks read
from and then I wouldn't have to have
this kernel in static memory but I guess
eventually the kernel will probably have
to be in static memory anyways because
uh eventually when if we do like user
space to Kernel space I think that th
those are all like
parameterless like CIS calls we would
have to have like a Statics of the
kernel anyway so I don't know stuff to
think about for the future um um but for
now all we want to do is we want to look
at our Mouse
stuff
so where does that come from we have
like a USB server somewhere we have a
mouse movement
writer and so I guess we almost
certainly have a mouse
movement reader as well where does this
mouse move TX get
used ah nice okay so when we construct
our Mouse we give it a channel just like
write movements into
and uh we can say
let we can just instead of trying to
like pass the mouse movements to the
cursor which is like a absolute position
thing we can say let Mouse move TX Mouse
move RX is equal
to what just like a channel what does
our Mouse drivers expect our Mouse
driver tries to sends send things to an
async Channel yeah so this is just uh
async
channel
channel and now the question is how do
we like get the reader side into rust s
do you know how fuchsia OS works on CIS
calls no I've actually never looked at
fuchsia OS at all what is it that's like
Google's OS
right f u s c h i a
o you used to work on future oh that's
pretty cool was it fun
how does it
look
[Music]
fuchsia CIS
calls oh did I get it wrong f u CSF
[ __ ] huh all right future export a huge
vdso like the link one you get this
closer dude I was actually thinking
about that the other day I was thinking
that's how I would want to do it that's
so sick did it does like is performance
better when you do it that
way I imagined it would be but I like
that that's actually so cool that's like
I was thinking about that exact
thing that's pretty
sick
um okay getting distracted
though um so we want to somehow pass
this channel around to these like
callbacks that have no parameters with
them so we could probably just like put
them in like a static variable somewhere
for now so we have DG get
key or I guess since we're injecting the
mouse Movement we can do whatever the
[ __ ] we feel
like um and so what I feel like doing is
I feel like not doing it with these
callbacks I feel like injecting it
directly into the Doom code so what we
can do is our in our Doom
stuff um
um how would I handle this uh so in here
we have Doom somewhere let Doom is equal
this and here we could like pull the the
mouse movements we could just say while
movement is equal to Mouse move RX
do what does this guy have on him I'm
sure he has like a a non or
read but let's just see
receiver uh he does not but we can just
have we can just add one we can just add
a function try receive that takes an
option that returns an
option
and we can lock the thing
inside oh this still need to be an asnc
function because the M Tex is a
sync and
uh
what does this guy
do we can just lock and then pop from
the inner thing
so this inner is has a VC DQ so we can
just say Q pop
front
cool cool cool cool cool which means
here we can just
say uh
loop and try to pull a mouse
movement uh Mouse move RX is defined
about below so we'll just kind of swap
these guys
here and we say match let movement is
equal to match
movement if it's something we we could
propagate if it's none we
break and then all we have to do here is
like Doom
generic uh and we have to write a
function that will like move the
mouse uh but that should be pretty easy
should be pretty easy where is this
bitching about me he doesn't like that
uh oh it's util acing channel channel
there you
go uh here I forgot to
await which is fine let's do that real
quick
and there we
go yeah the biggest thing you with the
vdso compatibility is if you decide you
want to rework this is call ABI you can
just shim whatever you need into version
vdso oh that's pretty cool so like your
your your kernel keeps all of the
vdso
forever um like in the same way that
when you update GCC you have like
versioned symbols for each lib C call
you just do the same thing with the the
vdso so you just like keep the old AI
around in case people linked with
it and then update and have the new
one uh cool
cool um okay so I'm going to look at
this movement I'm going to have to find
a way to inject it in so in Doom generic
I can just go to the i input. c and
uh somewhere we could just call like
uh void
DG insert or Doom generic push
Mouse and then all we have to do is run
this
stuff and so we just need to figure out
what these like inputs are going to
be
so we're going to have XR as a float
probably
and why ra is a
float and is that really it I guess we
just Define an event somewhere so here
we need event T
event and I wonder if that's
it uh I guess here we just replace this
XR and
yr and then all we have to do here is is
we say uh Doom generic push Mouse and we
pass in the movement. X and movement.
Y and I bet you I bet you that's pretty
close to
working so we'll just make our Doom
generic push Mouse function definition
here and we're going to have the uh X is
an F32 and Y is an
F32 and I wonder if that'll
work it seems
possible
it also seems like it might not work but
we'll see okay so uh Mouse button State
he didn't like that uh so we'll just put
that as
zero because we're not handling the
buttons we're just handling the
movement uh so here he doesn't like the
type here he says type has to be
known
how is that not
known why would to yeah this should just
be a movement right like cursor movement
so what's the
problem weird I don't understand why the
type resolution wouldn't handle that for
me um so he's saying Doom generic push
out undefined reference to accelerate
Mouse oh interesting
okay so that function just was commented
out here but doesn't exist so I guess we
have to look for Ev Mouse and see who
uses that guy and see what the
like
uh what that should be so this is data 2
Mouse X Mouse y it just looks like it's
like movement so I guess I just don't
have to handle I can just punch these
guys directly and see what they look
like zombie code
yeah all right so we compile we
run and I guess I will start a game and
see if when I rotate my guy's Mouse I'm
seeing nothing happen so what we should
probably do is we can maybe check that
we're pushing Mouse movements so we'll
say here info pushing Mouse movement and
we'll sa the movement because there's a
good chance that uh I [ __ ] that up and
I guess this shouldn't be a cursor
movement actually uh oh wait maybe it
should cursor movement yeah that seems
reasonable it's relative X relative Y
and he can't be printed so let's just
quickly throw a debug thing on
[Music]
him
take a quick
look okay and I guess I have to wait
here okay so I am pushing Mouse
movements but I wonder if they're just
super super
small uh so I wonder if I like pay a lot
of attention I just move this a
lot uh no it does seem like that's doing
like literally nothing I wonder if I
need to enable mouse
movement
it no
okay
so I
wonder I wonder let's look at DST event
or I guess where where did I say that I
saw the uh
EV EV Mouse yeah the what range does
want yeah we have all sorts of questions
that we want to answer here so let's
just first let's make sure that we're
setting this all so we'll say print line
uh print
F handling Mouse
movement and we'll say that we
got these
movements from EV data 2 and EV data
3 first of all what is the type of EV
data right like if I'm assigning floats
this is that is that what they
want uh so where is uh EV data
2 EV oh sorry it's data 2 is what it's
called and do you think it's a float
maybe
in uh this has got to be like in a
structure
somewhere where I guess this is we can
look at the type of event event is
a struct
event event T where does this event T
come from here we go so these are inss
so the fact that I'm casting my
normalized 0 to one float to an INT is
almost certainly [ __ ] right uh so
probably I just need to like multiply
this by a
lot like a lot a
lot
uh so somewhere where I push these can I
just like times
100 yeah maybe the screen space or
something it's com to use pixel counts
or some such
interesting I wouldn't have expected
that but we will find out so here
uh unhandled size unhandled to size in
handling M
[ __ ] oops uh I tried to print the
movement and uh we just don't support
floats in our print def implementation
so it just immediately crashed
[ __ ] that's pretty funny that's funny so
let's
just also they weren't floats so it was
just like [ __ ] wrong in a bunch of
ways
okay so let's try
[Music]
again oh oh sick okay so it's very
[ __ ] still uh 100 wasn't enough
but uh that's definitely doing
something
and the suggestion that it's in screen
space seems pretty
reasonable so it' be kind of interesting
to try multiplying by 640 and
480 just to see if the movement is more
reasonable and we give it a second to
boot
up all right
it feels like we're missing
movements which is interesting
um let's crank this up a little
bit yeah it does feel like when I push
multiple per
frame uh it actually doesn't like
that right like I can see like jerkiness
in the motion which is kind of
odd uh
but let's
try FPS cap oh like maybe I'm missing
but like all of these things should be
coming into a queue and we should be
pushing like the addition like of all of
them together that's kind of what I was
assuming would happen right cuz like we
have like a queue of things that come in
and I don't think we're hitting the end
of our queue maybe we
are yeah that does seem possible maybe
like we're just getting too many mo
motions per frame and we're like running
out and we we're not logging if we run
out
oh no maybe that's okay it could just be
that a
thousand like the their units are really
low that doesn't feel so bad let me try
uh maybe disabling all these prints they
might be making things
slower um so pushing pushing Mouse
movement let's just kind of get this guy
away and
let's just double
check is there anything else I wanted to
look at I wanted to see if the if we
what happens when we push and we don't
have anything so let's look at the mouse
driver
and he pushes to this pause
TX who is a sender who is backed by a v
DQ so we should just grow this
infinitely until we run memory so I
don't think I'm really worried about
losing events but maybe on the Doom
generic side that's
possible
um so what we could do is we could send
one movement and add them all
up that seems kind of
reasonable so we could uh just in case
like on the other side there's a cap for
how many events that they can take at
once we can convert this into one
massive event so we can
say let movement oopsies
this guy is going to be mutable and he's
going to be
a cursor
movement X
0.0 y
0.0 and we'll just accumulate these so
we'll
say movement dox plus
equals uh let this movement I guess
we'll call
it and we'll say movement. X+ equals
this movement movement
dox uh so he doesn't like something here
because this should say
this and then before we tick we'll just
push one
movement
okay let's see if that feels any
smoother
oh yeah that feels pretty
good that feels really
good that's sick that's so
cool
okay well that's super
sick um I guess oh okay we I can't call
it a day until I set up strafing to work
correctly so we'll do that really quick
here did I resolve the tearing uh if you
were the tearing was coming I think if
you're talking about like the from last
stream or from earlier today were you
here earlier yeah you were
um oh tearing is [ __ ] not doing vsync I
actually don't see tearing for me so uh
unless I'm just not noticing it I
usually I'm usually pretty upset by that
so so I think i' noticed but I'll I'll
double check next time we beot it um but
I would bet I would guess that that's a
artifact something else but I I'll
double
check um okay so what was I trying to do
I was trying to make a and d strafe
instead of turn so that would be in DG
get get
key which is implemented here we just
need to change these mapping to do
straths instead of
turns so here we'll say a is strafe left
and right is strafe
right and we'll run it one more
time
and I think that that will feel pretty
damn
good let's
see oh
baby oh yeah oh yeah and I guess since
uh somebody was complaining that there's
no music we just
go
that's sick all right I'm pretty happy
with that I think that we've got
like that's super
playable that's super cool I'm yeah I'm
pretty happy with
that um okay uh thanks for
watching
um yeah if you like what you saw uh I
stream most days between 1 and 2:00
Pacific time uh for around 1 or two
hours um I'm not sure what's going to
happen next uh probably I think I'm
probably going to take a day off
tomorrow and come back the day after and
I think probably the the next thing I
want to work on is uh I did want to
start trying to like boot in other
virtual machines so I might work on that
I've also been thinking about like file
system support in terms of like dog
fooding um it would be kind of cool if I
had a file system I could probably run
like a real web server on this thing and
like use it for some of my like little
local Damons that I run to do [ __ ] and
that would be kind of fun cuz then I can
start dog fooding and see you know start
finding real
bugs um yeah I'm not really sure so
we'll see the Doom Saga I think I'm
going to call this done right and I I
don't know if I'm going
to I don't know how much of this I'm
going to try to salvage into real code I
took a lot of shortcuts um in terms of
like the Liv C implementation so I'll
probably keep the branch around just to
like reference for later but I don't
know if I'll like commit any of that to
the master Branch yeah okay so we'll be
back in a couple days uh thanks for
watching if you're watching on Twitch uh
and you missed stuff there's a YouTube
link in the twitch description if you're
watching on YouTube and you want to come
by say hi chat whatever um there's a
twitch Link in the YouTube description
uh people in chat seem to
be looking asking about Discord
so uh I have I don't have one but I
guess it's probably worth trying to set
one up so I'll try to work on that soon
oh yeah thanks for watching catch you
guys on the next one bye