hello! I's Keith here and welcome to  Lesson one of my platform specific
  tutorials... and what these are going to do  is each lesson we're going to take a
  specific task and we're going to learn  how to do that on each of the different
  hardware platforms we're going to be  looking at, and obviously each system
  will have its own different firmware and  hardware requirements so that task will
  be different for each machine -  but we  were going to write common functions
  that we can call and use in the same way  on different systems... And today we're
  going to be looking at basic text and  screen functions, so what we're going to do
  is we're going to create a clear screen  function... we're going to create a locate
  function which will move the cursor... some  print character, and print string
  functions, and we're going to create a  function to read a key from the keyboard
  and we're going to do that on the Amstrad  CPC which you can see up here in the top
  left... The ZX spectrum in the middle here...  The Enterprise 64 or 128  - top right...
  bottom right we've got the MSX here and  on the bottom left we've got our most
  simple system which is the TI-83  calculator... so we're going to create one
  common piece of programming code which I'll show you here...   so this is a common
  piece of code that runs on all the  systems and just by changing....
  the compiler directives here we can  enable one of these to compile to that
  system... and the way this that we achieve  this is we have written
  specific code for those  platforms that deals with the
  intricacies of those systems, but works  in a common way so that our common code
  can use it without worrying about which  hardware we're compiling for, and that's
  really the secret of creating a good  multi-platform piece of software without
  too much debugging...  to create modules  (kind of like drivers) that will deal with
  the hardware and then just use those  drivers in the code... now we're going to
  be doing much more complex code today so unlike last time I'm not going to be
  typing in as we talk through it, because  the debugging tools on systems other
  than the Amstrad CPC aren't as easy to  use so it's probably not realistic and
  also we're going to cover a lot of  code in relatively short amount of time
  so let's begin... first of all let's just have a look at
  what our program is actually doing...  so you can see here first of all we're
  we're clearing the screen and then we're  setting the cursor position and we're
  using HL for the cursor position and H  is X and L is Y in this case and the top
  cursor corner is zero so top left is  zero on these machines
  now obviously the screen size of the  Machine... it varies quite differently. most
  of them at least 32 characters wide but on the ti-83 it's
  not even that (16x8) ... so we can't really do much about that but we can at least make sure
  that the top corner is (0,0)  and then what we're doing with doing a
  PrintString which is message and like  last time the the PrintString command
  is virtually identical to last  time... so it's character 255 terminated.
  that's our message... so we print that to  the screen, we do it three times... moving
  the cursor each time just to get this  kind of ladder effect here
  and that's just to prove that the locate  command is working correctly... and then we
  tell the user to press a key... we use  this new line command to move down a
  line then we wait for a character from  the user and we print back the character
  that the user entered and then we've got  this shutdown and start init command
  which are doing some stuff that those  systems need to get them ready for a
  text screen... Now. this tutorial is going  to be using the firmware to do all of
  these operations generally I don't  advise that if you can avoid it because
  using the firmware means that you've got  more risks involved with regards to...
  "what is the firmware doing with you registers?"  you've got memory limitations... "what banks
  can I page in and out?" and thing...s but for  this kind of beginner lesson we want to
  be able to get things working as fast as  possible so we're relying on the
  firmware to do most of the work for us...  later on when we get more advanced we
  will be able to create our own sprite  font... where we can create our own common
  font for all of these systems... send  graphics to the screen in a common way...
  we can create our own input routines and  if we want we can mimic
  the same names of the functions (we have here) and the  same functionality of the functions so a
  Sprite based locate routine works  identically to our firmware based locate
  routine that we're going to be learning  today
  so starting simply with the firmware and  then once we're more confident...
  once we've got more skill, and more  software we can break out into a much
  more advanced routine that uses sprites  to do the fonts in the same way... so I
  don't think it's too much of a problem  that we're starting using the firmware
  today... let's begin anyway and let's have  a look at the Amstrad CPC version
  so I've created a kind of structure for my  directories here so if we have a look
  you'll see you've got these SRC folders  and these are the source and these are
  what we're going to be looking at today...  RES stands for resource there aren't
  really any of these but that would be  things like sprites or music... BLD is
  temporary files relating to the  compilation (build) of the code and then REL is
  for release which is the final disc  images... the final tape images for the
  software itself...  now the compilation scripts I'm using
  here I'm going to try and make available to  you unfortunately they're not quite
  finished yet because it's taking a lot  of testing and configuring to get it to
  it working right on everyone's machines  but I will make this available to you so
  please look at my website... because I'm  hoping it will be on the website within
  the next week or two so... anyway so we're  going to go into SrcCPC here and the
  the one we're going to look at is  "functions" because this is doing all of
  our basic firmware functions that we're  going to look at today... so here is the start
  of the file and you can see with regard  to the CLS command we're actually just
  using a firmware function call at &BC14  and because we're calling this rather
  than creating a label and a CALL command  we're actually just using a symbol
  here and defining CLS as being memory  address &BC14 in the firmware and that
  will do the job and PrintChar as well is  the same we're just using this &BB5A
  function call and WaitChar as well... we're  using &BB06 so yeah... we've got three
  of our tasks done immediately with just  three lines and no real code at all
  just definitions!  now, locate the firmware  call is slightly different... the top
  corner is actually (1,1)   because we want it to be (0,0)
  we're having to INC H and L  before we call the firmware function
  call and then we've got this push pop  here just to protect the value of HL so
  that when we return back to the code  ...that required change by the
  firmware has been hidden from the  program itself... and then NewLine on the
  Amstrad CPC... as most systems we use a  character 13 and a character 10 which is
  carriage return a new line and there we  go! and then with PrintString... this is
  exactly the same that our previous  time that we've looked at this
  routine in the main beginner lessons... so  we just loop through the
  memory just passed was in HL... we print  each character until we come to a
  character 255 at which point we return.  And that's everything that the Amstrad
  CPC version requires! Bow, part of the  reason it's so simple on the Amstrad CPC
  is because i write all of my code first  on the Amstrad CPC, because as i've said
  before... I found WinAPE the easiest  assembler debugger and emulator for a
  beginner to use with programming so I  try and make it easy on myself I work on
  the Amstrad CPC first and then a branch  out onto the other systems where maybe
  the debuggers aren't quite as powerful...  and certainly there isn't a built in
  assembler! so let's move on from the  Amstrad CPC now, and let's have a look at...
  Let's have a look at the Enterprise next
  so here's the Enterprise version... now the  enterprise is here.... this is a rather
  obscure 8-bit system from the 80s... it  didn't it wasn't very successful in the
  UK but it probably should have been  because it's quite powerful! so I've
  been trying to have a look at it, and I'm  hoping to include it into these lessons...
  and I'm hoping to release my game on it  one day! so let's have a look at it now...
  The enterprise has a fairly advanced  operating system built into it and it
  works in something called "channels"  which is where you open a connection to
  a device (such as the keyboard and/or the  screen) and you send data to
  it or read data from it it very much like  the sort of a dotnet (eg C#) stream
  functionality... so it's quite  different to the Amstrad CPC version
  there's a lot more code and there is a  large init routine for getting the
  screen working which we're not going to  look at today... but anyway let's make a
  start on the functions we are going to  look at... so the init routine will have
  loaded up channel 10 as being the screen  and channel 11 as being the keyboard so
  just bear in mind that you would need to  look at that init routine as well if you
  wanted to see this... and all of the source  code will be available my website... if
  you really want to get into the detail  of how to get the enterprise screen
  working please look at that, or just look  at my "Enterprise hello world example" which uses the
  same code that I have put onto YouTube  before... so PrintChar... we protect BC
  because we need that to stay the same  to maintain comparable
  functionality to the Amstrad version...  then we load the character that we want
  to print to the screen into the register  B we load A with the channel number and
  then we call RST 6 which is sometimes  called EXOS in
  people's examples and even the debugger  actually does that the reason for that
  is they've created a macro to replace EXOS with rst 6... now I don't tend to do that
  because I want to show the real commands  that are running... but that's just
  something to bear in mind if you see  other people's examples you might see
  RST 6 called EXOS... so we just call  that and then the Byte afterwards is a
  command number and so command number 7 says
  "Write a byte to channel A" and that's all  we do for PrintChar that's not
  too bad... PrintString is basically the  same as before the only difference is
  the PringChar command I've replaced  with these commands here and
  that's just to do the equivalent of this...  but I've embedded it in the print string
  command so that we don't do more push  pops than we need to... so that's just a
  slight change I've made  there... and now next we've got the NewLine
  command... now on the enterprise new line  is basically the same as the Amstrad CPC
  we send character 13 and then character  10... now just to kind of speed things up a
  bit rather than calling the print char
  command twice I've actually created a  string of the characters here
  and I'm using the WriteBlock command  where we can specify the number of bytes
  in BC and this maybe is a little bit  faster (maybe it's not I haven't tested
  it) but at least it does allow us to show  you the use of the WriteBlock command
  which is where you send a number of  successive bytes to a channel on the
  enterprise...  now WaitChar... we'll wait for the user
  to press a key and return it in A...  on the enterprise
  we've got channel 11 as the keyboard and  command 5 will read a byte from the
  channel and store the result in B... now  because our Amstrad CPC version needed the
  byte returned in A I have had to copy  B to a and then I'm using this Push Pop
  here to just protect the BC register  from being affected so that this version
  matches the Amstrad CPC version... it's  quite nice actually the enterprise
  operating system... this EXOS call doesn't  alter any of the registers at all which
  makes our life very easy but  unfortunately because you're
  having to use A for the channel number  and then B for the data... even
  though it's not altering any of the  other registers it is affecting more
  registers than the Amstrad CPC version  did (which didn't affect any at all and)
  when we're working with code we're going  to use in a common way across multiple
  platforms we need to make sure we know  which registers are being altered... which
  have been corrupted and which are being  kept the same because....
  we need to know which ones we can rely  not having been changed by the functions
  we were calling.... okay so that's our  WaitChar routine now our CLS (clear screen)
  routine is a little bit obscure... this is  again done by sending text characters to
  the screen and it's kind of some  function characters so we send the
  escape and then this CTRL-Z  character here which are represented by
  &1B and &1A so just like we did  with the newline we're sending a block
  of two characters to the screen on  channel 10 and that will have the effect
  of clearing the screen... a little bit  strange! but it does work just fine. now
  here we've got a definition of our WriteBlock   command here... probably actually
  not worth calling that - I could have just  put that in there, but I copied this from
  another example so it's ended up in  there like that.
  now our Locate command... a little bit more  hectic here, maybe. In the same way as the
  clear screen command... we do the locate by sending a string of four characters to
  the screen... so the first one is this  escape code and then actually it's an
  "=" symbol... but it never actually  appears as an equal symbol...
  The screen channel will process it and know that it's a re-location command so
  the equals will never appear and neither  will the numbers we send following... so we
  send "ESC =" and then Y and then X  and that will ....
  move the cursor to the correct location  on-screen, and then show following text
  in that location... so because we having to  to send four characters rather than
  doing four print char commands (which  would be quite wasteful) we've done this
  WriteBlock of we are four bytes and  then we and then that will do it but
  because we've used so many  different registers here now we are
  actually having to protect quite a lot  here.. so yes that's that's not ideal but
  never mind! and also quite strangely,  there's some special rules
  for the locate command on the enterprise...  so on the enterprise we add &21 and
  that will make the enterprise locate  command work the same as the Amstrad CPC
  locate command, which is what we want to  do...
  for this sub function to work with in  the same way with our other systems... and
  here we've actually got all of the rest  which I'm not going to cover today this
  is all relating to initializing the the  enterprise screen memory... I did cover
  this a little bit more in my "hello world  on the enterprise" example and we will
  probably look at it later in more detail  but today I just want to focus on these
  common commands on all the systems... so that's the enterprise version... let's have
  a look at the MSX version.... now so on the  MSX you can see we've got PrintChar
  which is just a firmware function at &A2 which is in the low memory area
  and then we've got WaitChar which is  at &9F... again two very simple commands
  which actually do the exact same things  on the Amstrad CPC so we're sorted very
  quickly there... and screen isn't too  bad either... the only thing with the clear
  screen command is it requires the  accumulator to be 0 so we've done XOR of
  the accumulator... which is our quick way of loading the accumulator with 0... then we
  jump to &00C3 which is the CLS command so... that's quite easy! &00C6 is the locate
  command... but just like on the CPC...the top cursor co-ordinate
  is (1,1) so to match our expected  functionality of (0,0) we
  INC H and L and then we're just  calling that firmware function and then
  we're protecting H and L just to make  sure that they return from this locate
  command in the same state as we sent  them... NewLine on the MSX is a
  character 13 and a character 10.. so we're  just using PrintChar to do that and
  PrintString - very simple - just using  PrintChar over and over again... that's it!
  so that's nice and easy... shutdown is  disabling interrupts and halting that's
  to stop the system and that's because on  the cartridge based systems we can't
  return to basic  - nothing too
  exciting on the MSX... so let's have  a look at the TI-83 calculator and a TI
  calculator is our most limited system  we're covering (it's fallen asleep so lets
  to turn it back on)... so this is the most  limited system and you can see it's
  screen is actually very small (Confirmed: 16x8 characters)
  its a very small screen, so obviously
  we can't make it work exactly the same  as the other systems but we can at least
  give ourselves a start by making the  commands we've defined work in the same
  way... so on the on the TI-83 calculator   this RST 5 is often referred to
  as BCALL and this is actually why I  don't like using these defined macros
  because everywhere I went online I saw  the command BCALL being used which is
  not a Z80 command and they they kept  referring to this BCALLl and I couldn't
  find it!... and I had to search around for  half an hour to find the Include file
  that defined what BCALL was... so rather than using
  macros and include files, I try for these  basic tutorials to just actually use the
  z80 commands... so that there's no possible confusion when you're looking at this..
  you know exactly what this z80 is  really doing... if you want to use those
  kind of macros I'm not against them, but  for these basic tutorials I want to show
  you the real commands... so RST 5 is a BCALL... it's a far call what it does
  is...I believe it pages in the ROM of the
  calculator and then calls this memory  address in that ROM... so it reads the two
  bytes after the RST uses them as a  jump address... switches the ROM back off
  and then returns to your program... so  these two bytes are kind of swallowed in
  by the RST 5... but it's effectively  calling this address in firmware... so that
  address in firmware will clear the TI-83 screen... and then our Locate command here...
  well the locate commands very different...  we don't call anything at all there are
  two variables in memory at these  addresses for the Y and X location of
  the cursor we just load them in and that  does it all for us... so I guess next time we
  do a print command, the TI-83 firmware  will look at those addresses and go "well
  that's where I was printing to last"  so that actually does the job!
  for PrintChar we've got this  command  which does do the job... and we just
  need to protect all of our registers  because the firmware will overwrite them
  if we don't... so to make sure when we  return back to our program we
  have common functionality with that  print char command on all of
  systems we need to protect these  registers... WaitChar as well... there's a
  nice sub firmware function here...  unfortunately though because of the odd
  way the TI-83 calculator's  keyboard works you pressing number one
  won't necessarily come up with a number  one and things like the letter A you
  actually have to press shift and press  it... you would actually have to process
  the commands more thoroughly... you'd have to read back what the key had been press
  and then translate it based on what  numbers whether you expected... numbers or
  letters... so we're kind of doing a very  crude job here but I thought it was
  enough just to get started and on a  later lesson I've actually written a
  joystick input routine which works on  the TI-83 calculator and which has a
  redefined Keys function... and then  emulates a joystick. so if we're looking
  to do gaming then we don't need it... but  if we were looking to do text input then
  you would need to have some handling of  that some alpha shift key to allow you
  to get text or numbers depending on what  you needed to do... so a NewLine... we've got
  a special new line function here sending  character 13,10 does not work... sending
  character 13 doesn't work... you have to  use this special NewLine function so
  that's a good reason; on the TI-83 calculator; why we've got a
  function to do our NewLine command and  not some kind of defined
  character string that we sent to the  PrintString command because on the
  TI-83 the PrintString command cannot do a  newline character... and then here we got
  our PrintString command... which just does  the exact same as on the other systems
  just repeatedly uses the PrintChar  command to get the the text on the
  screen and there we go! that's the TI-83 calculator... now, considering what a
  strange system it is compared to others  and what a limited system it is it's
  actually quite minimal, the  amount of code we've had to do to get it
  to work... it seems to have a quite  powerful firmware even if it is heavily
  limited in screen space and RAM... so  finally let's have a look at the ZX
  Spectrum... so on the spectrum we have a  firmware call to do a clear screen
  it's at &0D6B... the locate command is  very much like the Enterprise version,
  we're sending special character codes to  the screen
  and the first one we have to do is send  character code 22 which... it's rather
  strange on the spectrum... you may  have seen a spectrum keyboard that it
  has these... I'll show you... so you'll see on  the spectrum the keys actually have
  these commands on them and each  of these commands is actually a
  character in the character set... which is  kind of odd but that is the way it has
  been programmed to work so what we're  sending is character 22 which is
  actually defined as the "AT" character if  you will... so the screen firmware
  reads that character and then understands  that the next two characters that are
  sent are actually going to be a screen  location and then moves the text cursor
  to it and that's what we're doing here...  and then again we're just protecting all
  of our registers so that we don't  cause any negative effects
  to the rest of the program when we're  compiling for the spectrum version...
  now. NewLine on the spectrum is just a  character 13... there's no character 10
  it doesn't like receiving a character 10... so  what we do is we load A with 13 here and
  then you'll notice there's no jump to  PrintChar or CALL PrintChar... because PrintChar
  is actually next ... so we're just kind of  letting execution flow through into
  PrintChar and that saves us a jump  command so that's quite nice and then
  PrintChar... we have to open the stream  number, we have to open channel 2 on the
  spectrum... there are two channels  for the screen... there's the top screen
  which is the main bulk of the screen and  then there's a one line bottom screen
  which I believe is down to the  spectrum  48k where memory was limited and the the
  bottom screen was used for data entry and the top screen was
  used for showing your program that you  are working on... so we're selecting the
  top screen which is the main one and  then we're sending the character with
  RST 2 here... and that will do the  job for us... and PrintString is the same
  we're just using that same  channel open by
  selecting channel 2... we call this function  here which will open the channel and
  then we're doing a loop here and  we just repeatedly running RST 2 to
  send the characters to the channel and  then when we're done we just restore our
  registers here and then we turn back to  the program we were running.. now
  WaitChar is kind of similar... you'll see  here we're protecting our registers as
  always we're loading a different stream (channel) ...  stream (channel) zero is the both the bottom
  screen when you're writing to it.. or the  keyboard when you're reading from it so
  we select stream  (channel)  zero and then we open the channel... and then we just call this
  Read Byte command which will read a  single character into a and then we go
  back to our program... and that's the  spectrum version done! so there we go!
  now you can see here that we've got a  few different ways of working with
  things.. the spectrum and the  enterprise have this kind of channel
  stream kind of concept of opening  connections to devices and then sending
  data to them or reading data from them ... whereas the MSX and the Amstrad at
  least don't present that to us... from in  the firmware sense, we have these very
  simple firmware functions that do all  the work for us
  and then the TI-83 calculator is a bit  different again... it's basically the same
  way the firmware does it all for us  there's just a few slight oddities on
  the TI-83 and I think there is  really just down to the fact that it's a
  very limited system with very little  memory so it just has to sort of make a
  few changes to the way it works to  accommodate that but they're all very
  good... now what I haven't done is I  haven't shown you the program working so
  let's just give it a go now... so we're  running it from the disk because this
  the script create onto the disk and into  memory simultaneously... so you can see
  we've got this ladder of hello worlds  and then we if we just press the 8 key,
  you're say see it you says you pressed  8... okay so that's the that's the CPC
  version well let's just have a look  right here let's recompile the TI-83
  version and just to prove it's actually  compiling I'm going to change this to
  "hello world 777"... so we'll just compile  that so you can see saved to Bld'TI\Program.bin
   
  and now if I get up my virtual Z drive  here and then if I run TI_Go... I just hit enter
  here  hello world 777...
  okay so you can see that the  re-compiling has just worked and then
  if I press the eight key you can see it  doesn't come up as an eight and that's
  because it's coming up as a key code... so  you'd probably need to create some kind
  of translation table here... but anyway I  think that was an adequate beginner
  example of how to read the ti-83...  let's just do the Enterprise version
  here as well... so if I just rem out this  TI-83 and then this build
  Enterprise and we've got two options  here to run from a disk image or from a
  from file emulation... so we'll run the  disk image and "hello world" .... you press
  V... so there we go it's like that that  works as well... and again the
  important thing to just understand is  all I'm doing here is removing the
  comment from one of the lines in this  listlike the ZX spectrum here here
  commenting out the others... and that tells  these scripts here to load
  in the correct functions to control  that systems firmware... and because those
  functions work in a common way all of  this code here is absolutely identical -
  never changes - and that allows us to  write one program that works on multiple
  systems in the same way, and that's going  to be essential if you want to develop a
  game for multiple systems because it's  going to reduce your debugging time...
  and your development time just by miles  and miles... so it's definitely the way you
  want to try and program if you want to  program for multiple systems, and I mean
  of course you're going to have your own  time constraints.. and your own
  goals in programming. But for me... if I can  write one program and release it on five
  systems then ...... that  increases the value overall of the
  development time that I have to invest...  in that  the result is five times
  (that of) if I've done it for any one  system... but the development time is
  probably only two times the actual  development time of just working for one
  system... so for in my opinion for me it's  definitely worth aiming for more systems
  if you can (if you're interested in it  of course!) there's no point if you
  don't like these other systems... but I  think it's good and the other thing is
  if you've written your code in a way  that works on five systems you can be
  pretty confident that your code is it's  designed solidly... that it's bug free
  because you're kind of putting it under  a stress test ... where if you've made any
  mistakes in your code, if your design has  any flaws in it - any weaknesses in it.. you
  will find them because you will be  unable to get it to work on the more
  limited systems ...or your code that  worked fine on the Amstrad...  maybe it was
  corrupting a piece of memory you didn't  know about and that piece of memory may
  be far more important on the spectrum... so by developing for these multiple systems
  you will really push yourself and you'll  really see if you your code was as
  robust as you thought it was.. because you  will find out that - well it doesn't work
  as you expected!... Now as always, the source code for today's lessons is going to be
  available on my website and very soon I  plan to make all of the development
  tools available on my website.... I just  haven't finished the debugging yet so
  please visit my website... there's a new  page for these tutorials they are split
  off and the main ones.... these are called  the "platform specific series" and the
  the documentation is very much the same  as before so we've got
  all of the versions of the program here  with details of how they work just like
  we've covered today... so please go and  take a look at that... please download the
  source code.. let me know what you think!  I'm planning to do more of these as soon
  as I can... but they are very time  consuming, because I'm essentially having
  to develop and test five times for all  of these different systems that I'm
  covering!  It won't be possible to cover  the TI-83 in all cases because it's
  such a limited system... but the other  systems I am going to cover every time
  so when we come to disk loading or  sprite showing you will get an Amstrad
  CPC routine, a spectrum routine, an MSX  routine and an enterprise routine... that
  will work in the same way and that will  allow you to target all of these systems
  very easily.. and also hopefully I'm  hoping that this website will become
  good easy access point for people who  are looking to do the basics on these
  systems... when it came to me looking up  the locate command on their ZX
  spectrum I had to spend about half an  hour searching Google for it for some
  reason (I'm sure it's on every website  out there but I just couldn't find it)
  and I ended up finding my own website  before I actually found the answer!... so
  I'm hoping that I can make the platform  specific series answer the beginners
  questions on programming these platforms.. you know how do you do this on the
  spectrum... how do you do on the MSX... I'm  going to make the answers all there as
  easily as possible.... please like this  video and follow my channel! If you want
  to let me know what stuff you want me to  cover in the future in the comments... I'll
  always do my best but of course it  is very time consuming... so I may not be
  able to -  I can't do really crazy complex  things, especially if I don't already
  know the answer! which in a lot of cases  that could be the case!... so anyway thanks
  for listening today! and goodbye!
     
Không có nhận xét nào:
Đăng nhận xét