so Matt we have had to chat with you
before about assembler and the game that
you're writing so what we can look at
today we're going to write some basic
game logic and assembly language first
I'm going to show the basics of the CPU
from a programmers point of view so
let's invent a CPU it's going to have a
logic core and because we're programmers
we don't concern ourselves too much with
that what we do care about the registers
and registers are very tiny typically
four to eight bytes of storage inside
the CPU itself for the logic court to
operate on so it's imagine we've got a
register one a registered to and we've
got the pc the pc is the program counter
and that stores the currently executing
line of code so if you imagine back to
your basic days we would have something
like 10 print hello 20 go to 10 so the
1020 are the currently executing lines
of code and basic obviously base it
would have a software solution for this
but the principle applies the pc would
hold the 10 so the logic core would
fetch that line of code to execute it
would then advance the program counter
to 20 and then execute that line of code
but this go to routine would inject 10
back into the program counter so the
next line of code would then be 10 again
so this logic call let's imagine it's
attached to some pseudo rom some ram
maybe a graphics processor or something
along physical wires and this is what we
call the bus so the logical can fetch
memory about using an hour bus when it
initializes it's going to immediately
start executing code the program
characters could be initialized to 0 at
which point SAT rom in our pseudo memory
map it's going to immediately start
executing code from the top of ROM so
let's write some assembly we can
interact with the other two registers
then so the first thing we want to do is
put some basic values in these two so
let's do a move command so we've got
address 0 which is the top of run and
this instruction is going to move the
literal value 8 into register r1 so
that's what that command would look like
next line of code let's imagine these
lines of code are two bytes wide address
number two we're going to move the
literal value for into register r2 and
then as a third line
address for we're going to add the two
together so we'll perform an ab command
we're going to add eight and four
together which we're in r1 and r2 so we
add r1 and r2 together and the result
would be stored in our two so what's
going to happen when the cpu starts up
its going to initialize the pc 20 which
is address 0 in the run where our code
is address 0 is going to move the
literal value 8 into register r1 it's
then going to advance the program
counter 22 which is going to move the
literal value for into register r2 then
it's going to advance the program
counter 24 and that's going to add
register one to register to it's going
to store the value into register two so
we would expect 12 and register at this
point just like basic using the go to
Thurmond go and you can jump the pc
around so let's perform that out
operation again so on a dress 6 i'm
going to jump back up to address for and
that's going to perform the add again so
once this instruction is completed is
going to jump to 6 and that is going to
inject address for into the pc so that
the next executing line of code is going
to be back to four again so we're going
to again add r1 to r2 which would give
us 20 so that would add what was still
in r12 what was now in our to after the
last ad yes yes changes are explicit you
tell the CPU exactly what to do is not
going to change these register values
outside of the code you've written here
this looks really good for you know the
basics of doing some sums and things now
how's this blow when you get into a game
and I can see this being a good good way
for adding up the scores but yep
certainly we are going to look at some
very basic platforming code so we're
going to have a pseudo player that's
awful start a blank page let me first
translate this to 68,000 assembler
actually that's what I was going to do
okay so the 68,000 CPU which is in the
sega megadrive is slightly different to
the cpu we invented here it's got 18
registers which run from d0 to d7 for
the general purpose registers those is
used for a lot of logic and arithmetic
we've also got a0 to a7 which are
address registers which we use for
accessing
parts of memory rom ram other
peripherals on the bus 68,000 logical
we've got d0 to d7 registers we've got
the a 0 to a 7 registers we've got the
pc just like our fake cpu and the status
register here the status register stores
the state of the CPU after the last
operation it'll have flags inside it
called the Zed flag and the carry flag
the Zed flag is used to determine if the
result of the last operation was 0 so if
we had four in our 14 and r2 and
subtracted the to the result would be 0
it would then set the carry flag we can
use that to compare two numbers to see
if they're equivalent it's also got the
carry register which tells us if the
result of the last operation was a
positive number going negative so if we
had seven in our one we had a 12 in r2
and we subtracted are two from our 112
is greater than 7 the result is going to
go negative is going to set that carry
flag and we can use that for comparison
so we can compare two numbers and we can
perform logic jump around to different
parts of code depending on the state of
the flags and the status register okay
so we're going to translate our pseudo
example here into real 68,000 assembly
so the first command the move aight into
register r1 will be a move and we need
to add the size of the operation here
and that can be a biter word or a long
for simplicity's sake i'm going to use
along a byte is eight bits a word is 16
bits and a long word is 32 bits so we're
going to move a long word worth of data
32 bits it's going to be a literal value
eight and we're going to use these d
registers which are the general purpose
or rhythmic registers so let's use d0
next slime we're going to move another
long word literal for into registered d1
and add together we're going to add two
long words worth of data register d 0 to
D 1 i've used long list for simplicity a
bite would only write the eight into the
lower bite and this would be whatever
was last in the upper bikes of that
register if we were to write it as a
word we would get 08 into the lower half
of the reg
and whatever was last used in the
register would be in the upper half but
I always really work with long words so
this register would contain 0008 and the
same goes for the add operation we're
going to add 32 bits of data so the
entire register is going to be added
with the entirety of another register
I'm going to type this back up into the
pburg ER and I'm going to show this
running in the debugger so we can
evaluate evaluate each step as it's
running and then we get to add to it
with some basic platform player logic
let's go some basic assembly language
then I've got environment setup for 68 k
assembler for the sega megadrive which
includes a basic skeleton here the first
thing we do is we define the start and
the end of the ROM file for including in
the head or later we're going to include
the header file here and previously
explained that the pseudo CPU that we
made was going to start executing code
from address 0 for 68 k it's very
slightly different the CPUs not going to
look for code when it starts up it's
going to look for this table in the
first 512 bytes of memory so the first
thing it's going to look for is the
address to initialize the stack value to
and this is the one we're interested in
here is the CPU entry point so it's
going to start executing code from the
address that it finds in this entry of
the table rather than immediately stream
address 0 so we can define a label here
a CPU entry point and then back in our
code file here we can start executing
code from here because this is a
debugger it's very slightly different to
a standard program we have to initialize
the connection to the debugger using
this subroutine but don't worry too much
about it so we can then start typing our
code out so our example before was to
move a long word literal eight into
register d0 we were then going to move a
long word little forward to reg D 1 and
then we're going out of the two together
so add long word worth of data d 0 to D
1 and that should assemble and we can
fire that up them ok so let's switch the
devkit on load up the debugger and then
we'll load our executable we have done a
video on the dev kit for anyone who's
interested oh just give people a kind of
one sentence on what this dev kit is its
a sega mega-cd development kit which has
a snazzy
board inside 468 keightley bugging on
top of that it's got the Mega Drive
daughter board on top of that it's got
the mega-cd daughter board this is
connected to the back of the pc by a
scuzzy cable to a nicer card which can
interact with the debugger here we've
got an old ms-dos based debugger ready
to debug code so it slowly executable
the first thing we want to do is reset
the CPU and then we can bring up a
source window here ok so we can set a
breakpoint on the first line as f9 to go
so that executables now running on the
debug get here and it's showing us in
real time the results of that operation
so we're on this breakpoint here so the
first instruction was going to move the
little eight and to register d0 so if we
step we can see the result of that
operation here the next line was going
to move a little for into register d1 we
can see the results of that here and
then we're going to add the two together
the d 0 plus d 1 and the result is going
to be in d1 so that gives us 12 in
hexadecimal here so that's all working
if you didn't use this literal word you
might be just overwriting some part of
that memory yeah you can write a long
word a word or a byte of data which will
use the first bite two mics or four
bikes for the register the same goes for
add divide multiply subtract etc you
have to specify how much the registers
you're going to deal with that includes
wrapping so if you're doing a bike tad
255 would wrap around 20 if you're doing
a word size at 65 k we're at 64 k would
wrap around 20 again and it's not useful
those things are useful in certain
circumstances on yes tis yes because a
smaller the operation the faster it
executes on the CPU so you can do a lot
of optimizations by doing by size
operations instead of words or long
words ok so we're going to write some
basic platforming code imagine we've got
a player at a floor and he has a
positive x velocity and a positive y
velocity so he is running and jumping
and we're going to handle the logic back
to move the player the first thing we
want to do is to designate some
registers for the player x and y
position so if we initialize the players
exposition a zero and to register d0 so
play it x plus we can initialize the
players y position zero and use d1 for
that and then we can initialize the
velocity values so in d2 let's store the
X velocity something like 16 in 2d too
so player X velocity and we're going to
initialize the player y velocity to
something positive because he's jumping
so 8 in 2d three player y velocity okay
so now we need a game loop so let's
write a label for the top of the game
loop let's call it player update and
then we can start moving the player
using the velocity so we would need to
add players X velocity to the players
backs cause so we're going to add do 220
we're going to add the players y
velocity the players y position so we're
going to add d3 to do one so then we're
going to loop back up to the player
update start so if we do a jump back to
player okay that's going to continue
looping forever so let's save and
assemble that and see it in action so
this is a discreet bit of code for
handling where that player is would that
be right yes this is a very tiny game
loop which would handle the velocity
applying to reply x and y position
obviously stuff would wrap around this
for drawing the character and all yeah
there will be extras here for the
graphics once you calculate the players
x and y position you would send it to
the sprocket X on Y position that's a
subject for another day though okay so
let's break on this line will run again
and then we can break here so let's
initialize d0 to the play x position 0
will initialize the player why pulse 20
we're then going to initialize the place
X velocity to 16 I'm going to initialize
the y velocity 28 and then going to
enter this infinite loop here so we're
going to add the players X velocity 2z0
going to add the players y velocity to
d1 and I'm going to jump back up and I'm
going to continue doing this forever and
the loop would just basically make him
move it will make a move for
so he'll continue to move right he'll
continue to jump up so he's jetpacking
news jetpacking so let's add to it let's
define gravity we would use the equate
label and we'll have gravity as
something like 8 let's define the floor
height as something like seven I haven't
use an odd number yet so in the player
update before we apply the y velocity we
want to apply the gravity to it so we
can subtract long word it's a little so
we need the hash again gravity from the
player y velocity here before we apply
it once the position has advanced we
want to check if we've hit the floor so
to do comparisons you want to watch the
status register to look at the last
state of the CPU for the last operation
so if we do the subtraction one number
from the other the status register will
have a flag in it to tell us whether
that number had become zero or had
become a negative number so you want to
compare the floor height with the
players current white position if the
result of that comparison was a negative
number the player is below the floor so
to do a comparison we would compare the
literal floor height with the players
wide position do you want and then we
would jump to a separate part of the
code if that condition was met so we do
branch if greater than there's also
branch of less than this beqa branch of
equal there's also equivalent for
unsigned numbers as well so that's
basically saying if this certain thing
is true then go to a different bit of
code yes exactly so we start by
comparing the floor height with a d1
which in the background would perform a
subtraction operation but without
writing results when he registers it
would only set the flags in the status
register state say if the result of that
operation would have been 0 or would
have gone negative and then we can check
those flags with the BGT branch if
greater than so that's just going to
check if the value for the carry flag is
one or zero so branch is greater than
and then we jump to another label so
we'll call this
floor and then we'll define that label
here above floor so we compare the full
height with d 1 if that was greater than
then we are above the floor and we're
going to skip this line of code we're
about to write and head straight to
above floor so if that condition was met
we are below the floor and in that case
we want to snap back the players white
position to the floor height so we move
the floor height to the players y
position which is d1 we also want to
null out the velocity because once we
hit the floor we don't want to carry on
going down so we reset that register to
their player what y velocity will be 0
in that case so let's assemble and run
that and we can step through at one at a
time so back in the debugger I've
changed the initial x and y Paul so he's
already above the floor for this
demonstration so let's run this then
initialize the exposition 28 we're going
to initialize the y position 28 we've
initialized the X velocity to 16 and the
y velocity 28 so this time the first
thing we're going to do is subtract
gravity from the player y velocity so
that sin that's down to four before we
apply the x and y velocity so add d 2 to
the 0 at d 3 to do one and then we're
going to check if we are still above the
floor so we're going to compare the
floor height to the new white position
and we're going to branch if it's above
the floor which is still is so we skip
straight to this line and then we jump
back up the player update once again we
subtract gravity from d3 which sends it
0 which means we've hit the apex of the
jump we're going to add the x la citty
at the y velocity compare a
four-syllable the floor which we still
are once again we subtract gravity to d3
and this now goes negative which means
we're past the apex of the jump we're
going to start applying downward
velocity instead of upward velocity so
once again apply the X velocity to the
exposition the y velocity to the light
position i'm going to start moving
downwards instead and we're going to
keep going until we are below the floor
here so the floor height was set to
seven the white position is now zero so
this comparison is going to ring true
branch is greater than above the floor
which will fail there we go so we are
now below the floor we need to snap back
up to the floor height so we set the
full height into the Y position you want
and then we know the player y velocity
qui don't want to carry on going down so
the y velocity is now zero and then back
at the player update and then forever we
will always snap back up to that floor
height and we are always on the floor so
now he's still moving to the side but
he's just staying on the floor here's
just stay on the floor yes because
gravity's are basically clamping him to
the floor right yeah indeed from here on
it's not tricky to add things like
acceleration deceleration in air drag
things like that and once you start
getting into control pad input and stuff
like that that you can then apply the
acceleration to the current velocity and
then have basic pad inputs we've seen on
your game in the previous video that
you've got bouncing balls in it and is
that just an extension of this there's a
very basic physics engine in there which
is just an extension of all of this very
basic collision detection is just
comparison of numbers applying clamps or
bounce or restitution etc you can build
it all up like Lego blocks like this
just learn one thing at the time and if
somebody out there wants to learn this
kind of stuff and they obviously haven't
got the dev kit and all this old kit
lying around where would you suggest
they start to sort of learn these these
basic bits and pieces you can do exactly
the same thing using an emulator and
there are some freeware assemblers out
there you just need a text editor
assembler and an emulation off you go
some are better than others find one
with a debugger built-in obviously
otherwise you'll get a bit lost but all
the principles are essentially the same
is this whereas
what's cuz he is yeah it pronounced
scuzzy I didn't realize that it was such
a widespread terminology I thought I'd
get laughed at saying scuzzy so I said
se SI but whatever thank you internet