Understanding Memory in PICO-8

แชร์
ฝัง
  • เผยแพร่เมื่อ 24 ก.ย. 2024

ความคิดเห็น • 69

  • @lostGash
    @lostGash 4 ปีที่แล้ว +49

    I don't feel like you did hexadecimal justice here. It's not only useful because you can represent a byte in two characters, but because the method for translating back and forth to and from binary is so simple. Each hex digit can be directly transcribed to a nibble (4 bits) in binary so that each successive digit in hex corresponds directly to the next 4 binary digits in a given number. 0x8A is 1000 (8) 1010 (A). It's easy in reverse too. 11101011 is easily broken into the two four digit sections, each translated to a hex digit E (1110) B (1011). This is not only the case for a byte, but for any size binary number. This makes translating any size binary number simple and shorter to read and display. This was not immediately obvious to me when I learned hex, and knowing that made my appreciation for the format much greater.

    • @DanSanderson
      @DanSanderson 4 ปีที่แล้ว +8

      Agreed! A good example of this in PICO-8 is in understanding sprite or screen memory. As explained in the video, PICO-8 has 16 colors, which you can represent with the hexadecimal digits 0 through F, and you can store in four bits. Memory locations refer to bytes, which are eight bits. Image data stores two side-by-side pixels in a single byte, four bits for the left pixel and four bits for the right pixel. In hexadecimal, this is just two digits, one for each pixel! For computer-y reasons these pixels are stored in reverse order, so if a screen memory location has the byte value 0x8A, you know that the right pixel is color 8 (red) and the left pixel is color A (10 in decimal, yellow).
      Another example is the memory addresses themselves. Like most computer-y things, PICO-8's memory space is divided into regions whose sizes are multiples of powers of two, which are easy to express in power-of-two number systems like binary (2) or hexadecimal (2*2*2*2 = 16). Screen memory starts at memory address 0x6000, which is a nice round number in hexademical and a surprisingly weird number (24576) in decimal.
      POKE(0x6000,0x8a) -- draws a yellow pixel and a red pixel in the upper left corner of the screen

    • @KrystianMajewski
      @KrystianMajewski 4 ปีที่แล้ว +1

      @@DanSanderson 19:34

    • @KrystianMajewski
      @KrystianMajewski 4 ปีที่แล้ว

      Sure, but you translate one number system that is hard to read for humans into another number system that is also hard to read for humans. Maybe I just don't deal with binary data enough to see the big advantage.
      But since you do seem to have more experience: do you at some point get so familiar with hexadecimal that you start doing math with it? Like if you see that an are of memory goes between 0x4300 and 0x5dff can you instinctively tell how many bytes that is?

    • @DanSanderson
      @DanSanderson 4 ปีที่แล้ว +4

      @@KrystianMajewski Sort of yes! I wouldn't do the hex-to-decimal conversion in my head but I would do the subtraction problem (0x1aff) and have a sense of how much it is based on how memory usage patterns follow powers-of-two sizes. Everything aligns to those boundaries so often, not just in PICO-8 but in computer architecture in general, that it's more useful in hex form than in dec form. (I really like your memory browser app but the one view that shows six bytes per line breaks my brain a bit. :) )
      Binary alignment in computers happens because computers store values as binary, and it's most efficient to use every bit to its fullest potential. If my values go from 0 to 99, I'd need 7 bits to store a value, and I'd be wasting 28 possible values, so I might as well use the range 0 to 127. Computers routinely store memory locations as values, so it's most efficient for memory layouts to also use boundaries at multiples of large powers of two. Ultimately these values are represented as wires carrying on/off signals, and the electronics might use multiple memory chips, with the higher bits selecting a chip and the lower bits selecting an address on that chip.
      PICO-8 makes excellent use of bit boundaries in its layout. Funny to think, as a fantasy console it could have chosen a different system! 100x100 resolution, 10x10 sprites, 10 colors, 10,000 memory locations each storing a number from 0 to 99, fixed point decimal math with 4 decimal digits on each side of the decimal point (storable as 4 memory values). I suspect it'd make it more difficult for people to translate skills to other computer tasks or build tools. Better to teach people hexadecimal. :)

    • @ogrebunny4182
      @ogrebunny4182 4 ปีที่แล้ว +2

      @@KrystianMajewski math is always the same. 0x5dff - 0x4300 = 0x1aff and right away you see, that you will have 0x1aff _bytes_ of memory. You don't care about decimal system here, because everything you need to do in memory or with bytes or bits - is easier done with hex than any other system.
      And always: difference coding in memory with decimal and hexadecimal is like between coding with variable spaced font and mono spaced font. ;)

  • @Felice_Enellen
    @Felice_Enellen 4 ปีที่แล้ว +30

    For people still getting their programming legs, I want to offer some long-term advice/goals, from a multi-decade, full-stack, professional game industry engineer:
    *You **_should_** work hard to develop an internal, automatic ability to read and write hexadecimal, without needing to think or convert bit-by-bit.*
    This is similar to learning another language: ideally you want to understand the other language directly, rather than converting sentences to your first language in your head. If you don't do this, you will encumber yourself and slow yourself down in many of daily activities without realizing it.
    This means doing the kind of foundational work you did as a kid to memorize low-value multiplication tables to enable you to work through longhand multiplication of large-value numbers. Heck, you can even use the kind of rote learning tricks your teacher used with you as a kid, e.g. flash cards, etc., assuming that works for your kind of brain. Being able to see the hex digit "D" and have your brain automatically supply "13 decimal" or "1101 binary", without having to visualize the bits and add their values together, will ease your workflow in ways you might not expect:
    • The obvious case is where you want to _create_ a simple bitmask. Maybe you have a 1-bit 4x6 font glyph for "j" that you want to store in a single 24-bit value: 0x40C448. Or maybe you need to mask off, say, the bottom 6 bits by AND/&-ing with 0x3f. You can write these with binary constants in some languages, e.g. 0b010000001100010001001000 and 0b111111 but most programmers consider this bloated & cumbersome, and while easier to _write,_ much harder to _read,_ because the nybble and byte boundaries aren't obvious. You can also write them in decimal, but this becomes very unwieldy very quickly when bit counts go above 6 or 7. (Side advice: write your code with the goal of making it easier to _read,_ not just to write.)
    • The obvious complement to the first case is being able to _read_ such simple bitmasks, either created automatically by an API or another programmer in the source code you're reading. You may be writing code on your own, thinking "but I don't use/read other programmers' code," but you'll find you actually end up reading others' code much more often than you expect, maybe when researching methods, examining demos, reading white papers, looking at code you wrote more than a month ago, etc.
    • This is also very useful when it comes to debugging, and especially _post-mortem_ debugging, which is when your program has crashed, sometimes violently and in ways that do not produce useful error messages or stack traces. Examining the corpse's memory and recognizing values and patterns is key to solving the murder in such cases, and this is almost always most effective when looking at memory as values in, or pages of, _hex._ It allows you to see memory the way the CPU does, as bytes, 16-bit values, 32-bit values, etc. In time, you'll even get to the point that you will be able to recognize certain complex data types and common values thereof just by looking at them, for instance 1.0 in floating point will look like 0x3F800000, -1.0 looks like 0xBF800000, and 0.0 is conveniently 0x00000000. From that you can readily recognize larger patterns and structures, e.g. a 4x4 3D transformation matrix jumps right out at me, and from there I can deduce that the bit of memory I'm looking at is at least related to an object in my scene, and thus I can start looking for clues that might lead me to that object's specific identity.
    The main point I want to make is that these are small events that happen constantly while you're working on your program. Any one individual event is pretty insignificant and would never lead you to think "I need to learn to do this automatically to save the six seconds it took me to convert in my head", but ideally you're going to be passionate about writing games for the rest of your life, and this can mean months or years of lost time vs. the days or weeks it takes to establish this kind of rote learning. It's a _good_ investment and it's one of the most fundamental ones you can make, much like the multiplication tables I've been referencing are for working in advanced math. Someone with poor rote-learned multiplication tables will invariably be a lot slower at analyzing advanced mathematical problems than someone who made the effort, and the same is true for us in programming.
    Good luck out there! 👍
    _____
    *Disclaimer: I acknowledge that this is _not_ a small task. Internalizing hexadecimal like this takes real time and effort. It's a hassle. I'm not suggesting something here that's easy-not by any means. If you feel daunted by it, that's understandable. It takes time and active effort to build up the brain's equivalent of muscle memory. You need to throw a ball dozens or hundreds of times before it becomes reflexively accurate, and so too for reading hex and binary without needing to convert it in your head. But just as with sports, these basic abilities underpin your day-to-day activities if you want to be a "full-stack" programmer. Having an instant hex-to-decimal, decimal-to-hex, hex-to-binary, binary-to-hex, and even binary-to-decimal and decimal-to-binary interpreter sitting between your work and your analytical brain will be absolutely invaluable in the end and you will be _very_ glad you took the time to do it.

    • @DFX2KX
      @DFX2KX 2 ปีที่แล้ว

      @Alts'Alts I mean, if you showed enough interest to reply to a year old comment about learning programming, you might as well have read it.
      That said. hex converters are pretty ubiquitous. I *can* do long division and multiplication in my head too. it's helpful for understanding, but when you start talking 64-bit numbers, conversion's faster. Sans maybe bianary, but I don't think I've seen a bianary output outside of Pico-8...

    • @GrumpyStoic
      @GrumpyStoic 2 ปีที่แล้ว

      But don't do this first. First of all find out whether you enjoy coding. Otherwise you risk giving up on coding as you failed to learn how to read and write hex.

    • @Felice_Enellen
      @Felice_Enellen 2 ปีที่แล้ว +1

      @@GrumpyStoic Very true. I mean to offer the advice above to those who are already devoted to their love of programming.

    • @twoThirds_Evil
      @twoThirds_Evil 2 ปีที่แล้ว +2

      I just want everyone to appreciate the dedication this person had to write this absolute wall of text about hexadecimal numbers

    • @b4ux1t3-tech
      @b4ux1t3-tech ปีที่แล้ว +2

      Coming in two years later as a full-stack software engineer _outside_ of the games industry, and this checks out here, too.
      Learning how computers represent values often doesn't matter; a lot of the environments developers work in are sufficiently abstracted for this to not be immediately helpful. But when it _does_ matter, it matters a _lot_.

  • @microdavid7098
    @microdavid7098 2 ปีที่แล้ว +4

    this video very much applies to tic80. You very much helped me understand how tic80's memory works through this video, thank you!

  • @musicmeanslife65
    @musicmeanslife65 3 ปีที่แล้ว +6

    This video and specially your Memsplore tool are pure gold. I'm making my first game and it's a guitar hero clone. I needed to get sfx speed to be able to get the beat of the music. I solved that AND learned a whole lot more. Thanks.

    • @LazyDevs
      @LazyDevs  3 ปีที่แล้ว +2

      Glad to hear that! Yeah I learned a lot making this video and I use Memsplore myself.

  • @ogrebunny4182
    @ogrebunny4182 4 ปีที่แล้ว +5

    Hexadecimal is not only convenient for conversion between binary with less alignment problem but also because math can be done with your fingers. And even better than decimal, where you need two hands to count to ten. In hexadecimal you need only one hand to count to 0xF.

    • @LazyDevs
      @LazyDevs  4 ปีที่แล้ว

      WAT

    • @ogrebunny4182
      @ogrebunny4182 4 ปีที่แล้ว +1

      @@LazyDevs Yup.
      There are two techniques - counting to 12 and 16 (or better 0xF ;) with one hand. The fact is, that counting to 12 was waaay more popular long time ago, than count to 10. Dozen is from that time. Dozen is so convenient number in every day life... So easy to divide not once, but twice, divide by 2, 3, 4, 6... Ten is not even close to this.
      And if you don't know how to count on fingers from one hand to 12 or 16 - just open your palm and look at it very very carefully. I bet you will discover this technique quite fast.
      If not, just search for it ;)

    • @LazyDevs
      @LazyDevs  4 ปีที่แล้ว

      @@ogrebunny4182 I mean if you treat your fingers as bits you can count to 31 on one hand. That says nothing about the presumed advantages of Hexadecimal.

  • @otomichal86
    @otomichal86 หลายเดือนก่อน

    Thank you man! I really appreciate the amount of work you put into this. Your explanation is the best man!. Cheers!

  • @Riiyan
    @Riiyan 2 ปีที่แล้ว

    Lovely visual interpretation of memory and bytes explained, I thought I was coming for Pico info and I learned something that applies more broadly. Thank you!

    • @LazyDevs
      @LazyDevs  2 ปีที่แล้ว

      Glad it was helpful!

  • @StarLink149
    @StarLink149 2 ปีที่แล้ว +2

    There are 10 types of people in the world. Those who don't understand binary, those who understand binary, and those who don't expect a ternary joke. :)

    • @LazyDevs
      @LazyDevs  2 ปีที่แล้ว

      HA! I haven't heard that variant before. Love it!

  • @asliem2125
    @asliem2125 2 ปีที่แล้ว

    Dude! This video is awesome! I have a little bit of experience with microcontrollers from school and this makes so much sense, I love it.

    • @LazyDevs
      @LazyDevs  2 ปีที่แล้ว

      Glad you liked it!

  • @smellyfishstiks
    @smellyfishstiks 4 ปีที่แล้ว +1

    yay!
    PS:(Didn't know that the RAM part was empty, that explains why poking stuff doesn't change the number of coins you have etc.
    Nice to know I could use that for my stuff alot! ^_^)

  • @thatsmaik
    @thatsmaik 3 ปีที่แล้ว

    so so useful! thanks so much for this tutorial! very helpful to understand memory in pico-8 and memory in general.

    • @LazyDevs
      @LazyDevs  3 ปีที่แล้ว +1

      Glad I could help!

  • @DFX2KX
    @DFX2KX 2 ปีที่แล้ว +1

    Screen memory manipulation is how a few games did Parallax scrolling back in the day, if memory serves.

    • @LazyDevs
      @LazyDevs  2 ปีที่แล้ว

      Depends on the game I guess. Scrolling was quite hardware-intensive for early games and often relied on custom system-specific functions. For example, the NES was kinda build with scrolling in mind.

  • @cnfreitas
    @cnfreitas 2 ปีที่แล้ว

    Awesome work!! Really instructive. Your tutorials rock, man. Keep going.

    • @LazyDevs
      @LazyDevs  2 ปีที่แล้ว

      Glad you like them!

  • @vladcom95
    @vladcom95 4 ปีที่แล้ว +1

    Omg I really needed this

  • @emperorsno
    @emperorsno 4 ปีที่แล้ว

    This is soooo useful, brilliant work as always :) Thank you

  • @mmsbludhound873
    @mmsbludhound873 4 ปีที่แล้ว +3

    When I first saw Pico8 code I was reminded of how much it looked like the QBASIC code I worked with decades ago, at least on a superficial level. Now that you mention peek and poke that connection is even stronger since it I used those commands extensively in QBASIC. It's nostalgic to say the least.
    Also, what's this Doobeedoo that's often mentioned in your videos? :P

    • @rushsiteb
      @rushsiteb 3 หลายเดือนก่อน +1

      Hey sorry of this is 3 years late, but the doobeedoo is referencing the description

    • @mmsbludhound873
      @mmsbludhound873 3 หลายเดือนก่อน

      @@rushsiteb Oh I've figured that out but thanks though! 😊

  • @ChrisLeeW00
    @ChrisLeeW00 3 ปีที่แล้ว +1

    It's easier to quickly translate from binary to hex, since 16 is a power of two. One digit in hex represents 4 bits always.

    • @LazyDevs
      @LazyDevs  3 ปีที่แล้ว +1

      Translating from Spanish to Italian may be easier but that doesn't help you if you don't speak either.

  • @4bits4e47
    @4bits4e47 6 หลายเดือนก่อน

    A friendly critique of your explanations of number systems. Decimal=Base 10. That means 10 symbols and a weight of 10. Binary=Base 2. That means 2 symbols and a weight of 2. Hexadecimal is binary notation with 16 symbols and a weight of 16. See? Friendly!

    • @LazyDevs
      @LazyDevs  6 หลายเดือนก่อน

      Hexadecimal by isn't binary notation

    • @4bits4e47
      @4bits4e47 6 หลายเดือนก่อน

      If 2^4 is not binary!@@LazyDevs

    • @LazyDevs
      @LazyDevs  6 หลายเดือนก่อน

      @@4bits4e47What?

    • @4bits4e47
      @4bits4e47 6 หลายเดือนก่อน

      Hexadecimal is like ASCII. Computers don't need it, people do!@@LazyDevs

  • @garabdorje
    @garabdorje 2 ปีที่แล้ว

    This was very informative.

  • @alphaqueueop
    @alphaqueueop 10 วันที่ผ่านมา

    Picotron Memsplore would be nice.

    • @LazyDevs
      @LazyDevs  8 วันที่ผ่านมา

      Sure thing. Memory documentation is pretty spotty right now. But I will make one eventually

  • @glitchydust4015
    @glitchydust4015 3 ปีที่แล้ว +2

    22:17
    I do :)

  • @ruolbu
    @ruolbu 7 หลายเดือนก่อน

    did you ever talk about the extended map that starts from 0x8000? was that even a thing when you made this video?

    • @LazyDevs
      @LazyDevs  7 หลายเดือนก่อน +1

      It was not. I discuss it in this video:
      th-cam.com/video/LHvupeKhBAc/w-d-xo.html

  • @EBHawellsGames
    @EBHawellsGames 9 หลายเดือนก่อน

    I have "no persistent storage" error at startup using my RGB30 handheld. Saves don't work, and some games (like Poom) require persistent storage. Do you know how to fix the error? It's with the RPI Pico8 build. I am guessing I just need a folder added for the file path somewhere?

    • @LazyDevs
      @LazyDevs  9 หลายเดือนก่อน +1

      Hm, never heard of that bug. Post it in the forums on lexaloffle.com. Maybe someone knows how to solve this

    • @EBHawellsGames
      @EBHawellsGames 9 หลายเดือนก่อน

      @LazyDevs thank for the quick reply! It resolved itself by accident -oddly enough, I just needed to update each category in splore. Now the error is gone and games save the way they should.

  • @philtoa334
    @philtoa334 4 ปีที่แล้ว

    Nice

  • @claytonallen9398
    @claytonallen9398 ปีที่แล้ว

    how much memory does 8 bit doom, aka poom, require?

    • @LazyDevs
      @LazyDevs  ปีที่แล้ว

      The available memory is always the same for any cart. Poom does a lot of highly advanced tricks that I myself haven't fully understood.

  • @samuelschwager
    @samuelschwager 2 ปีที่แล้ว

    Let us not even get started with octal :P

  • @SvensPron
    @SvensPron 3 ปีที่แล้ว +1

    I love mammaries

  • @the4thsteve27
    @the4thsteve27 3 ปีที่แล้ว

    your explanation of hex and binary needs work imo
    you're not redefining what some number means, a number is worth something like n*(b^l) (this isnt 100% correct, i pulled it out of my ass, so it doesnt work for first place values), where n is your number, b is your base(decimal is base 10), and l is your location. so the 1 in decimal 100 is worth 1*(10^2), and the 1 in binary 100 is worth 1*(2^2), or 4.
    or, in other words, a value is worth the largest possible value before it plus 1- a rolling ticker, like to count milage in old cars is a good visualisation of this

  • @SSukram_
    @SSukram_ 2 ปีที่แล้ว

    Try poke(rnd(32767),rnd(255))
    It sets a random address to a random value, run it every frame on your game and see what happens

    • @LazyDevs
      @LazyDevs  2 ปีที่แล้ว

      That sounds like a recipe for fun!