Machine Language 10 PRINT Size-Optimized for Commodore 64

Sdílet
Vložit
  • čas přidán 31. 07. 2024
  • Can we write a machine language version of the famous 10 PRINT BASIC program for the Commodore 64? How short can we make it? Thanks to viewer Peter for prompting this episode.
    To support 8-Bit Show And Tell:
    Become a patron: / 8bitshowandtell
    One-time donation: paypal.me/8BitShowAndTell
    2nd channel: / @8-bitshowandtell247
    Download work disk:
    8bitshowandtell.com/downloads...
    End credits song is "53280" by Bedford Level Experiment. Check out the music video here: • 53280 (Commodore 64)
    Index:
    0:00 10 PRINT again??
    2:01 ML1: Machine Language 10 PRINT
    7:57 ML2: Some optimizations
    10:32 Cheating with Carry?
    12:47 ML3: Random ROM?
    18:14 ML4: Raster Register Randomness
    20:48 ML5: CIA Timer
    23:00 ML6: Further failed optimization ideas
    25:59 Thanks to Peter, Patrons, and You
  • Věda a technologie

Komentáře • 201

  • @peterszabo3584
    @peterszabo3584 Před 2 lety +39

    9 byte version.
    Hi. I just sent a detailed explanation yesterday about my 11 byte version (with full legal opcodes) to you Robin,
    but since yesterday I further optimized it into 9 bytes:
    .C:2f00 68 PLA
    .C:2f01 6e 04 dc ROR $dc04
    .C:2f04 69 87 ADC #$87
    .C:2f06 20 17 e7 JSR $e717
    Some notes:
    The location of the code is important. That last JSR will push the "$2f, $08" sequence to the stack. I jumped into the KERNEL routine in a way that I skip the first PHA there.
    This way the last PLA before the RTS will remove the "$08" from the stack.
    The original sys routine around $e12f pushes the address $e1, $46 to the stack (return address to the sys command).
    With he first PLA I remove the 0x46 from the stack and using it also as a constant value to initialize the addition (adc #$87 will give you 205 or 206 this way).
    After jumping into the JSR the stack looks like this: $e1, $2f, $08. (Leftmost is the top of the stack). Inside the JSR $08 will be removed by pla before RTS so RTS will return
    back to the original SYS just before it calls our routine. ($e130).

    • @8_Bit
      @8_Bit  Před 2 lety +9

      Fantastic work!!

    • @peterszabo3584
      @peterszabo3584 Před 2 lety +4

      @@8_Bit Thanks. I really love your videos, inspiring and thorough content! Keep it up!

    • @paulkocyla1343
      @paulkocyla1343 Před 2 lety +2

      That´s genious - that´s really really good!

    • @PSL1969
      @PSL1969 Před 2 lety +4

      Wow, that's amazing trickery. I think we have a winner 🥇😎👍

    • @paulkocyla1343
      @paulkocyla1343 Před 2 lety +8

      8 BYTES - using color ram as random source
      ----------------------------------------
      Slight modification to Peter´s version:
      Using the colorram address under the cursor ($F3/$F4) to randomly change carry, the ZP access saves one byte.
      The colorram has no upper nibble - the four upper bits are floating and give random values when read!
      Tried on VICE, would be nice to know if it works on real hardware :)
      adc ($f3),y ;2b
      pla ;1b
      adc #$87 ;2b
      jsr $e717 ;3b

  • @thedigitalemotion
    @thedigitalemotion Před 2 lety +94

    Thank you for keeping Commodore alive. Being 45 and in a stressful grown up world full of doubt, it’s so nice to relax with a bottle of wine and come back to my 80s youth. That’s always been my happiest place. I’m so pleased people like you exist. 🙏🏼🙌🏼🙏🏼🙌🏼

    • @CubicleNate
      @CubicleNate Před 2 lety +7

      I agree. These things take us back to a more golden age, I would say. Though, I try to stay fixed on the good things out there to keep my head in a positive place. Watching things like this is good for my soul.

    • @stephenelliott7071
      @stephenelliott7071 Před 2 lety +3

      I completely agree, the early 80's were an exciting time for the first home computers. In the UK computers like the Sinclair ZX81, ZX Spectrum, Commodore 64 and BBC Micro were the most popular. It's great to grab a drink and fire-up those old computers plugged into time appropriate CRT's (thanks to Ebay) and remember those times fondly. Happy times!

    • @G1itcher
      @G1itcher Před 2 lety +4

      I'm 34 and I think computers were better in the 80s!

    • @d-h4ck401
      @d-h4ck401 Před 2 lety +1

      @@G1itcher thats correct. Computers of 80s had a standing and were built to keep running for long years..not like today's technology which is developed to self-destroy in at most 3 or 4 years to make people always consume more.

    • @bob-ny6kn
      @bob-ny6kn Před 2 lety +1

      @@G1itcher I began the rest of my life from PET, Apple][e and C64. It always has been my playground. I am now playing with Arduino. Small cost and footprint. Tinkerland, robust. They even have cloud programming and simulators (drag-drop resistors, sensors, LEDs, et c.) similar to C64 User port. Keep having fun! Never grow up! Pleased to meet you, all.

  • @MichaelDoornbos
    @MichaelDoornbos Před 2 lety +12

    22:46 oh that one is clever, I was trying to figure out what was left to do at this point and hadn't thought of this
    24:30 always something to learn from things that don't work, glad you included it

  • @Qba474
    @Qba474 Před 2 lety +8

    Hey! Just wanted to say, that in my country C64 and Amigas were still quite popular in the early 2000's. As a child back then, the C64 was my first computer, even though some of my friends already had a modern PC. Unfortunately, my C64 from back then didn't last. I managed to buy well preserved C64C last friday. Your videos are very informative and really inspiring! It just makes me to have some productive time with my Commodore like I've never had before. :D Thanks!

  • @LeftoverBeefcake
    @LeftoverBeefcake Před 2 lety +13

    Having gone through a couple books and having watched a couple other videos on ML, I could follow along and knew what most of the stuff was doing. (yay!) The extra knowledge doesn't diminish my amazement with what people can squeeze out of this machine with the relative handful of instructions and registers, if anything, I have even more respect. Some good stuff shown here and I can't wait to learn more!

  • @bald_engineer
    @bald_engineer Před 2 lety +5

    Thanks Robin. I really like these in-depth "step-by-step" episodes. I do not pick up many details on my first viewing. But these are the kind I come back to several times because I learn something on each repeat!

  • @JosipRetroBits
    @JosipRetroBits Před 2 lety +4

    Nice video, I really like 10 print maze, also did a video about it myself. People still develop different versions of this one-liner (orthogonal version) and make it smaller and smaller... and it is amazing how much amusement we get from this fascinating small piece of code.

  • @espenskog8745
    @espenskog8745 Před 2 lety +7

    Loved the optimizations and your step by step walk through. It's like we're 16 again :)

  • @DavidYoud
    @DavidYoud Před 2 lety +6

    This is a completely on-brand episode!
    24:00 I had a moment of false hope for your divide-by-two approach, by using equivalent petscii values 109/110 instead of 205/206, but alas, it's still odd/even, not even/odd.

  • @lordanthrax2417
    @lordanthrax2417 Před 2 lety +1

    Great video as always! I also like your "learning with music" stuff. Something me and my family did when i was younger! I like it a lot!

  • @paulvanderlaak700
    @paulvanderlaak700 Před 2 lety +1

    Love to see this play with random in machine code. I have been doing this a few years ago with ‘random runner’. Thanx for sharing Robin. 👍

  • @igorwollersheim464
    @igorwollersheim464 Před rokem

    Again a great video with lots of information. Again learned a lot from your video..

  • @NotaWizard
    @NotaWizard Před 2 lety +1

    awesome. And love the maze behind the patron list in the outro. Classic Robin subtle brilliance. :)

  • @geehaf
    @geehaf Před 2 lety +3

    Great video - I really like the way you go from the BASIC solution and iterate through the ML alternatives, including the "if it wasn't for bad luck" attempt too. I've tried but cannot optimise it any smaller. Cheers.

  • @PSL1969
    @PSL1969 Před 2 lety +1

    Hey Robin, great episode! 😎 Cool to see all the attempts, and how you explained it all was great! 👍👍👍

    • @8_Bit
      @8_Bit  Před 2 lety +1

      Thanks Peter for your great ideas!

    • @PSL1969
      @PSL1969 Před 2 lety

      @@8_Bit I only had them because of your own great ideas :) And a great challenge to everyone, to improve upon it 👍👍👍

  • @CityXen
    @CityXen Před 2 lety

    Always proving there is more than one way to do something. Excellent vid. Cheers

  • @tYNS
    @tYNS Před 2 lety +2

    That outro tune is very soothing ;)

  • @agranero6
    @agranero6 Před 2 lety +1

    There is a book about this program. It is called 10 PRINT ... (in fact the title is the entire program).

  • @byteforever7829
    @byteforever7829 Před 2 lety

    love this that you do the assembly editing and run on real C64, and great that we can follow along using the disk file :) hope for more like this

  • @indiocolifa
    @indiocolifa Před 2 lety

    Unmatched wisdom, as always. Top notch!

  • @MattKasdorf
    @MattKasdorf Před 2 lety

    Impressive tutorial, thank you.

  • @phlogicali
    @phlogicali Před 2 lety +9

    I think I found a 11-byte-solution, which should work after a coldstart or reset:
    loop: jsr $e0be
    txa
    sbc $25
    jsr $ffd2
    bcc loop
    explanation:
    - calling subroutine $e0be of the BASIC RND() routine creates a pseudo-random value while the carry flag is also set randomly
    - the routine always returns with X-register = 139 (this value is set at address $e0f2 of the RND() routine)
    - txa transferes the value in X to the accumulator
    - after a reset the value at zeropage address $25 is always 189 (this is set at address $be0d when printing the " BYTES FREE" value using a subroutine call at $e43a)
    - sbc performs the following subtraction: 139-189-carryflag, which results in 205 or 206
    The machine code has 11 bytes: 20 BE E0 8A E5 25 20 D2 FF 90 F5
    Greetings
    Michael

    • @PSL1969
      @PSL1969 Před 2 lety

      Interesting!

    • @8_Bit
      @8_Bit  Před 2 lety +2

      Nice, I will give this a try!

    • @8_Bit
      @8_Bit  Před 2 lety +7

      This seems like a great solution! I think the SBC $25 could just be SBC #189 or even ADC #66, couldn't it? The real magic is discovering that $E0BE always returns a constant number in X, that's great!

    • @phlogicali
      @phlogicali Před 2 lety +2

      @@8_BitYes, immediate addressing mode is the better option. I was too fixated on finding a zeropage solution and have not seen this much easier solution. :-)

    • @paulkocyla1343
      @paulkocyla1343 Před 2 lety +1

      WOW, respect! That´s damn smart!

  • @Bianchi77
    @Bianchi77 Před 2 lety

    Nice video, like it, thanks for sharing :)

  • @michaelstoliker971
    @michaelstoliker971 Před 10 měsíci

    Just for fun I cobbled up the 10 Print program on the Atari. You really only have to change the 205.5 to 6.5 and away it goes. The speedup tricks don't work on the Atari due to differences in the Basics, but it's pretty close. The forward and back slashes are ATASCII characters so they look nearly identical to the C64's PETSCII characters.

  • @ZXAtari
    @ZXAtari Před 2 lety +2

    Love this episode. Imagine somebody (more likely thousands of somebodys) spending time to optimize windows 10 code or rewrite it in pure machine code. Whole system on several 3.5 inch floppies again.....

  • @raoullangner-macmillan7655

    Thanks for the great video.

  • @warmCabin
    @warmCabin Před 2 lety

    You could speed that RAM scanner up by a lot with a sliding window. First, compute the cumulative score for $E000-$E0FF, then for each subsequent byte, you only have to add its score and subtract the score of the previous byte. 2 operations instead of 256.
    So for example, you start with the score from $E000-$E0FF, then you can easily find the score from $E001-$E100 by just subtracting score($E000) and adding score($E100).

  • @damienretro4416
    @damienretro4416 Před 2 lety +1

    Love it

  • @neurogate459
    @neurogate459 Před 2 lety

    Cool, thank you

  • @gwivongalois6169
    @gwivongalois6169 Před 2 lety

    Loved the implementation that used the SID as a source of randomness.

  • @londongaz2
    @londongaz2 Před 2 lety +1

    Love the end song!

  • @midtskogen
    @midtskogen Před 2 lety

    A really fast implementation would scroll more than a full screen for each screen refresh, so you would get the same result if you store the character directly to screen memory, simply looping over it, and you would get an "optimised" version with just a few extra instructions.

  • @eekee6034
    @eekee6034 Před 2 lety +1

    I like the adc #0 instead of a jcc. Haha! of course you could get rid of the lda though. :)
    Every time I see 10print running, I want to write a maze solver for it. :) Perhaps the solver should try every entrance until it finds the longest (most interesting) path.
    Optimizing for speed doesn't seem hard to me. Write straight to the screen RAM with an indexed address. Don't even try to scroll, just limit the number of iterations. Ignore the cursor, just pick the starting address to avoid the next prompt. (I'm assuming that the C64 text mode maps RAM to screen without any gaps.) EDIT: I'm also assuming you can ignore color RAM, wherever that is. I'm an Atari guy, our mode 0 is monochrome. :-J
    The reason I bring it up is really for my own sake. I've often thought "I don't want to rewrite that" without realising the only reason "that" is complex is because it's featureful. Only recently have I learned that taking a different approach, changing the requirements a little, can make huge simplifications. I've been limiting myself unnecessarily. :)

  • @argoneum
    @argoneum Před 2 lety +3

    (not only) for Linux users, works best in xterm:
    while :; do printf "\e[44;36;1m\e#6" && for i in {1..40}; do printf "\\$((57+77*($RANDOM % 2)))" && sleep 0.01; done; echo; done
    Not sure if other terminal emulators support double-width characters or DEC sequences for them. Slightly off-topic 😸

  • @JamsterJules
    @JamsterJules Před 2 lety +2

    Love it! How about getting it to run as fast as you can by rewriting the system library?

  • @IsaacKuo
    @IsaacKuo Před 2 lety +4

    Huh, my optimizations mostly revolved around figuring out how the heck to get the thing to autorun and ... actually work and not crash. The most compact form of autorun I figured out stuck the code on the stack, so it was really touchy preventing other stuff from accidentally overwriting it eventually.
    (A BASIC stub with SYS to execute the machine code took up way too many bytes.)

    • @8_Bit
      @8_Bit  Před 2 lety +1

      Yes, making it either RUNnable or auto-running is pretty much its own topic which I just avoided here. I think I fretted enough over it in the video about 10 PRINT Orthogonal :)

  • @rotordave81
    @rotordave81 Před 2 lety

    I enjoy the smart alec self deprecation :) What if you pointed it at video memory for randomness?
    You made it a really interesting video with the boundary pushing approach.

  • @HannesEder
    @HannesEder Před 2 lety +1

    Re: 17:00 Random ROM: you could use a sliding window to not scan over the same 255 bytes again, i.e. inspect the first 255 bytes and then in a loop add the next byte, but remove the first byte that goes out of the window. that should be a lot faster.

  • @AmstradExin
    @AmstradExin Před 2 lety +1

    I wonder if that 10 Print program is useful for finding more of these 'pleasing shapes' for making games with randomized levels. They still have some structure in them without a tailor-made randomizer for each level.

  • @daveloomis
    @daveloomis Před 2 lety +1

    "Since last year!" Instant like.

    • @8_Bit
      @8_Bit  Před 2 lety +1

      Gotta use that dad joke every year.

  • @properjob2311
    @properjob2311 Před 2 lety +1

    what it you use a lookup table for the characters and then use the lower bit of the sound oscillator as the index offset? would that be quicker/smaller?

  • @BenderdickCumbersnatch
    @BenderdickCumbersnatch Před 2 lety +1

    20:57 I knew it!! I knew the CIA was involved!,!

  • @paulkocyla1343
    @paulkocyla1343 Před 2 lety +2

    That´s a great brain-squeezer. Your solution looks pretty optimal, I don´t think it can be done any smaller.
    But maybe there´s a voodoo trick 😀.

  • @saganandroid4175
    @saganandroid4175 Před 2 lety

    Thank you for remembering us decimal guys sometimes. 13:58 Pseudo-random: What if instead of starting the indexed reading from ROM, maybe a screen RAM address on the left edge of the screen? There will be a feedback effect.

  • @mrmimeisfunny
    @mrmimeisfunny Před 2 lety +5

    In the ml2 you could save 2 bytes by doing
    LDA #$80
    STA #$d40f
    STA #$d412
    Considering the character printing routine is slow. halving the frequency won't change much.
    In ML3 the zeropage is filled with random OS junk. So if you don't care about having exactly 128 1s to 128 0s (which true randomness won't do anyway) you can save a byte using lda 00,x or even (00,x)

  • @cairsahrstjoseph996
    @cairsahrstjoseph996 Před 2 lety

    This routine can be used to generate mazes for a game. Perhaps it can be a 16 screens in a 4x4 grid which can scroll in all directions (but a "wall" would have to be drawn around it). One might start at the bottom left and make your way to the top right. Sprites can be used to make tentacled Cthulu things going about randomly looking for you; perhaps there can be a few rocks here and there in the maze which your character can pick up and throw at them to stop them for a time so you can go past them. It's a silly idea, but why not : )

    • @BillAnt
      @BillAnt Před 11 měsíci +2

      For games an LFSR (Linear-Feedback-Shift-Register) routine works better. It's random, but allows you to go back and forth different rooms or scrolling panes while maintaining the previously random generated data. ;)

  • @bgone5520
    @bgone5520 Před 2 lety +2

    Write a version writing directly to screen memory at $0400. You will need to also write color ram too and handle scrolling to and last position wrote to the screen. Should be much faster than kernal rountines. Won't be smaller.

  • @eugenetswong
    @eugenetswong Před 2 lety

    Hello, from British Columbia!
    6:30 Wow! I can't believe that I understood all/most of the explanation of the rotating and the carry and the kernel routine.
    18:14 If I understand you, the raster register and CIA are changing in real time, whereas the $F002 technique is a static list of numbers, right?

  • @d.j.peters
    @d.j.peters Před 2 lety +2

    Well done, you could poke the char in the video ram and make the last row hidden and do a softscroll pixel row by row :-)

  • @paulkocyla1343
    @paulkocyla1343 Před 2 lety +3

    I made a 10 byter that uses values in stack as randomness and the illegal opcode RLA to lower the range of numbers.
    Couldn´t get the classic maze pattern to work, but two other ones that look kind of good:
    byte $2f, $f3, $01 ;RLA {adr}:={adr}rol A:=A and {adr} absolute
    jsr $e716
    sbc #$1A ;$1a for random waves, $16 for random grid
    bcc loop

    • @PSL1969
      @PSL1969 Před 2 lety +1

      Interesting. I had an 11 byte one, that used "-" and "|" 👍
      Edit: I tried your code, but am I doing something wrong here?
      .C:0900 2F F3 01 RLA $01F3
      .C:0903 20 16 E7 JSR $E716
      .C:0906 E5 1A SBC $1A
      .C:0908 50 F6 BCC $0900 (tried with BVC as well).
      I just get a cursor.

    • @paulkocyla1343
      @paulkocyla1343 Před 2 lety +1

      @@PSL1969 I assembled to $080d, maybe it´s that. And I run on VICE emulator by injecting into memory.
      However, Peter Szabo ^^ made a 9 byte version that displays the original - that´s black magic to get this idea :)

    • @PSL1969
      @PSL1969 Před 2 lety +1

      @@paulkocyla1343 I'll try that 👍 9 byte that's crazy. I'll have to check that out as well.

    • @paulkocyla1343
      @paulkocyla1343 Před 2 lety +2

      ​@@PSL1969 Hi, I just got an 8-byter to work. Posted it in the pinned comment.
      The print routine writes a color-ram address to ZP, where you can read it out with a 2-bytes command.
      The read will give a random value, because the colorram is connected with only 4-bits instead of eight.

    • @PSL1969
      @PSL1969 Před 2 lety +1

      @@paulkocyla1343 Nice, I will check it out. This is getting crazy! :)

  • @TheBookaroo
    @TheBookaroo Před 2 lety

    Hi, one though would be to search in rom for part of the code with a subroutine return just after and just called subroutines?

  • @theosib
    @theosib Před 5 měsíci

    How do you make sure basic doesn't stomp on the memory used by the assembler or you asm program?

  • @VulpisFoxfire
    @VulpisFoxfire Před 2 lety

    Just as a side note..the jiffy clock is useful for random numbers, but in order to do so, it needs the human element...if you check it after a pause for input of some sort. then usually the variation in delay is enough to be 'sufficiently' random for many purposes. Of course, in an application like this where there's no outside input at all, it's pretty much useless. (and if you're one of those who is, pun intended, inhumanly fast/consistant with your keypress speed, that also defeats it).

  • @andreroussel
    @andreroussel Před rokem +1

    I'm really enjoying how well you explain things in your videos. Thanks for making those for us. One question I have is what is the deal with using characters 205 and 206? I find using characters such as 182 and 184 to look much more like a traditional maze. If you wanted to use your 11 Byte method you could use characters 182 and 183 which I personnaly still find looks more like a traditional maze. Just curious as to the appeal of using diagonal lines. Thanks

    • @TheUtuber999
      @TheUtuber999 Před rokem +1

      I tried your suggestion and you are so right, it really *does* look more like a real maze using those two chars.

  • @LynxSnowCat
    @LynxSnowCat Před 2 lety +2

    Didn't realise that you needed to recount the low bits incase the ROM changes when incrementing the address. 😼
    I think I spotted a repeating club shape formed by an "e" shaped head on two perpendicular dominoes. That might be avoidable by switching through address windows, or finding one larger than the screen size.
    Would it be practical to do an initial count, then { decrement if a low bit is leaving the address window, and increment when one enters the address window } while scanning for a larger window ?

  • @williamsquires3070
    @williamsquires3070 Před 2 lety

    Also, one thing you could do would be to make an inner loop in which you ROR 8 times, thus using all the bits in the byte (wherever you get it from). You could also try this in a machine with only - say - 16k of RAM and pull a byte from an address where there’s no RAM, ROM, or hardware and see if it reads “noise” values. So, maybe a VIC-20. Also, what happens if you try to read the joystick and none is connected? Or read the cassette input? Are bits other than bit 0 any more/less “random” than bit 0? Will this work on a C128?

  • @Eightbitswide
    @Eightbitswide Před 2 lety +1

    Hey Robin, Really enjoying the exploration into simple assembly code programs! Question, I'm pretty sure that you covered the use of the Assembler (commands, differences between the REU version and the one you used today.) you are using fairly extensively in another video. Do you remember offhand which video?

    • @8_Bit
      @8_Bit  Před 2 lety +1

      Hi Jeff, nice to hear from you! I've got a playlist of the assembly videos here, and you're probably thinking of the first two videos in the list: czcams.com/play/PLvW2ZMbxgP9z9Un4LXivII_D1Hh5gZ7r9.html

    • @MrWaalkman
      @MrWaalkman Před 2 lety

      OBC! :)

  • @kurtreber9813
    @kurtreber9813 Před rokem

    How would one get the output to scroll smoothly?

  • @karlramberg
    @karlramberg Před 2 lety +5

    Would be cool to see a episode of this where you optimize for speed

    • @MrRobbyvent
      @MrRobbyvent Před 2 lety

      very unlikely: the routine at $ffD2 has a lot of stuff to do!

    • @DavidYoud
      @DavidYoud Před 2 lety +2

      @@MrRobbyvent Pretty sure we could make a special-purpose print routine that's faster than $FFD2

    • @MrRobbyvent
      @MrRobbyvent Před 2 lety

      @@DavidYoud I'm pretty sure you could'nt

    • @DavidYoud
      @DavidYoud Před 2 lety

      Tell ya what, if Robin makes a video optimizing for speed, I'll submit a faster maze draw routine (which I'm sure clever people could even further optimize).

    • @DavidYoud
      @DavidYoud Před 2 lety

      CZcams ate my post with a link, but check out disassembly of $E716, lots of unnecessary processing to be removed

  • @dougjohnson4266
    @dougjohnson4266 Před 2 lety

    Do all the Kernals act the same for CHROUT? (Jiffydos, Keernal v1,2,3 etc) Can you call the BASIC RND function and save any bytes? Kinda slow?

  • @andresbravo2003
    @andresbravo2003 Před 2 lety

    Well, I know about machine language because it’s quite an impressive way to build and compile faster.

  • @saganandroid4175
    @saganandroid4175 Před rokem

    11:34 Int Disable and Print Char during Int code... very scary.

  • @BlackGymkhana
    @BlackGymkhana Před 2 lety

    I wish this type of skills and optimizations applied to modern operating systems...

  • @bob-ny6kn
    @bob-ny6kn Před 2 lety

    205/206 dec is 1100 1101 bin. Would NOTing the two LSBs reduce cycles of transferring bytes?

  • @gertlynge
    @gertlynge Před 2 lety

    What about bit 0 from the pot pin in the jjoystick port. That mest be kind of random?

  • @8BitNaptime
    @8BitNaptime Před 2 lety +1

    I wonder if reading unmapped memory is random enough? Like if there's nothing in the expansion port, and you read a IO2 address? I suspect the data bus has enough capacitance to simply hold the last value. Not so random after all I guess. Or what about the upper nybble of color RAM?

  • @antonnym214
    @antonnym214 Před 2 lety +1

    On the Z80, the R register was the 16-bit address of the Dynamic RAM address being refreshed. When we needed a random number on the Z80, we just loaded A with the R register and AND with the mask for the bits we wanted from that. But I think that's clever, you pre-surveyed that section of ROM to get your result. Does not the 6502 have a RAM refresh register?

    • @fnjesusfreak
      @fnjesusfreak Před 2 lety

      Nope, only A, X, Y, P, S and the instruction pointer.

  • @stefanguhren1036
    @stefanguhren1036 Před 2 lety +1

    A bit off topic, but anyway I wanted to ask. What's the smallest possible code, in basic, to program a TRUE random generator on the C64?
    I remember back in the days when I tried to create a D&D character generator program, using the standard rnd command, the program would always give back the same values from run to run, if you get my point. The only documentation I had available at the time (the standard C64 manual) didn't give any clues to this as far as I can remember. I can see some things that would more or less allow for a 'true' rnd generator based on timings, as explained by you in this video.
    How would you write a simple basic program that would allow for TRUE rnd generation without any specific inputs and such?

    • @r3jjs
      @r3jjs Před 2 lety

      Short answer:
      You don't get true random numbers out of a computer without specialized hardware.
      Your choices are:
      * Do some math involving a seed value. Start with the same seed, get the same random values. Try to randomize the seed.
      * Do something that involves hardware. A box to detect radiation counts and feeds that back to the computer, for instance.

  • @HeffeJeffe78
    @HeffeJeffe78 Před 2 lety

    A friend of mine used to joke that a true test for randomness is to sample if a man is spitting on the sidewalk in Tulsa on that cycle.

  • @retrobytes.v65
    @retrobytes.v65 Před 2 lety +1

    Hello
    Does anyone recognise the Disk Emulator / SD Card adaptor that Robin is using ?

    • @8_Bit
      @8_Bit  Před 2 lety +1

      I do! :)
      It's the uIEC/SD, sold by RETRO Innovations.

  • @lordanthrax2417
    @lordanthrax2417 Před 2 lety

    Do you know 10 print racer revamp?
    Lovely little game

  • @DAVIDGREGORYKERR
    @DAVIDGREGORYKERR Před 2 lety

    can the rnd() not be based on DES64

  • @JohnnyWednesday
    @JohnnyWednesday Před 2 lety +1

    In regards to the 204/205 bad luck? how about putting character 206 into 204? then you could use that alternate technique - but how expensive would it be to replace the char? alternatively replace character 0 and 1 then do away with any addition? can you 'offset' the pointer to the start of character ROM? perhaps shift it up so 205 is 0?

    • @JeremyNasmith
      @JeremyNasmith Před 2 lety +1

      I'm not sure about this, but my intuition says that the pointer to the charset would need to point to the start of a page (xx00), in which case offsetting it by one wouldn't work. Also, since the goal was to optimize for size the preparation needed to move the charset pointer adds more bytes than it saves. But, if optimizing for speed, redefining a character is fine as an initial setup cost if it saves cycles by tightening the loop.

    • @JohnnyWednesday
      @JohnnyWednesday Před 2 lety

      @@JeremyNasmith - I was reading and you can change the pointer to where the character glyphs start but I am unaware if it's restricted to the start of a page - it's a VICII register that's set so I don't know if that hints at any indication.
      Well if the pointer isn't fixed to the start of a page? you could get rid of combining the random value with the 205/206 and print 0 or 1 directly - but you sound like you know it'd still be more expensive :P

  • @paulkocyla1343
    @paulkocyla1343 Před 2 lety

    8 BYTES
    ----------------------------------------
    Using the colorram address under the cursor ($F3/$F4) to randomly change carry, the ZP access saves one byte.
    The colorram has no upper nibble - the four upper bits are floating and give random values when read!
    Modified version of Peter Szabo.
    adc ($f3),y ;2b
    pla ;1b
    adc #$87 ;2b
    jsr $e717 ;3b

    • @peterszabo3584
      @peterszabo3584 Před 2 lety

      Sadly it only works with a poke 780,128 before the sys. The original routine resets the A register from this memory address at each iteration. (0 by default I guess)

    • @paulkocyla1343
      @paulkocyla1343 Před 2 lety

      @@peterszabo3584 Thanx for the info. I only tried it on VICE. It works out of the box there.
      When I get some more time, I´ll try to tinker it on a real C64.

    • @peterszabo3584
      @peterszabo3584 Před 2 lety

      @@paulkocyla1343 I also tried on VICE and it did not work after reset. But in the pinned post I added a modification that will solve the issue.

  • @TheUtuber999
    @TheUtuber999 Před rokem

    21:46 Wouldn't rotating the CIA timer low byte mess up stability of the system?

  • @saveddijon
    @saveddijon Před 2 lety +4

    You can optimize the ROM searcher program as well. After summing the LSBs of $F000-$F0FF, you can sum $F001-$F100 by subtracting the LSB at $F000 and adding the LSB at $F100, etc.

  • @SteveGuidi
    @SteveGuidi Před rokem

    I was recently brushing up on ML and using random numbers, when this video came to mind! I'd like to generate a two-byte random number, but as you noted, using the SID is not suitable without introducing a delay. There is an example in Compute!'s "Programing the Commodore 64" of a routine at $E0BE that produces 4 bytes, but this appears to be slower than calling RND() in BASIC! Maybe I'm doing something wrong, but do you have a suggestion on how to generate two random bytes without introducing a delay?

    • @8_Bit
      @8_Bit  Před rokem

      If you set the SID frequency to $FFFF then you only have to wait 17 cycles to guarantee it changes, so I'd suggest just grabbing a byte, do some initialization or whatever (you can probably think of something useful your code could be doing) and then grab the second byte. Even if you just waste the 17 cycles, it's probably not all that bad.
      If that's not acceptable, then I'd suggest using a large-ish software LFSR, maybe 16 bits or more. But that would probably take 17 cycles or more anyway to generate the next number in the sequence.

    • @SteveGuidi
      @SteveGuidi Před rokem

      @@8_Bit These are great suggestions -- thank you! I was goofing around and cheated: I moved the LDA $D41B instruction to a subroutine with an NOP before the RTS -- the total time to call it with JSR is (i think) 16 cycles, which is good enough for my academic exercise.

  • @JustWasted3HoursHere
    @JustWasted3HoursHere Před 2 lety +2

    Robin, do you know why the 'Restore' button has to be tapped quickly for the 'Run/Stop Restore' break function to work? In other words, if you just press Run/Stop and the Restore button normally the break won't happen. Is this a function of how the Restore button is read or is that button actually somehow physically different from the others so that it ONLY works if it's tapped quickly? Always wondered about that.

    • @Curt_Sampson
      @Curt_Sampson Před 2 lety +2

      The RESTORE key is certainly very different from the rest of the keys on the keyboard. It's not part of the standard keyboard matrix that's scanned via the PIO lines of CIA1 but is instead connected to the NMI line. (It goes through a 555 circuit that debounces it.) So unlike any other key, where the computer knows about it when it decides to scan the keyboard, pressing RESTORE immediately halts whatever the computer is doing and jumps to the NMI routine. (That routine scans the keyboard to see if RUN/STOP is being held down as this routine executes.)
      I'm not clear on why you're having issues with what sounds like different lengths of key press, though. I wonder if it could be a problem related to the debouncing of that switch? It would be interesting to put an oscilloscope on the relevant signals on a C64 known to be working properly and on yours and see if there's any difference.

    • @8_Bit
      @8_Bit  Před 2 lety

      In addition to what Curt said, I've heard that many (mostly breadbin?) C64s have the incorrect value of capacitor (or resistor?) on the Restore key line and so they need a sharper thwack to get the signal through?

    • @JustWasted3HoursHere
      @JustWasted3HoursHere Před 2 lety

      @@8_Bit Yep, the C64 I had back in the day was indeed the old breadbin style and I remember on several occasions trying to just hold the Run/Stop and Restore keys like a normal combination (such as Shift-Return or whatever) and it did not have the desired effect. Had to thwack it hard and quick to do the deed. I had no idea that other C64 versions didn't need that sort of thwacking. I just figured it was designed that way to prevent accidental resets, etc. Interesting!

    • @JustWasted3HoursHere
      @JustWasted3HoursHere Před 2 lety

      @@Curt_Sampson I guess Commodore modified the motherboard slightly in later versions to fix this issue?

    • @8_Bit
      @8_Bit  Před 2 lety

      ​@@JustWasted3HoursHere Yeah, it seems like it's by design to me too, though some people say it was the incorrect value. I'm not sure what proof they have of this, maybe just that it doesn't match the schematics included in the C64 Programmer's Reference Guide? Well, those schematics have several errors, so I don't see it as fully authoritative. And even if the schematic says something else, it's possible they deliberately changed the value during production.

  • @josefjelinek
    @josefjelinek Před 2 lety +1

    Are the end songs available somewhere to listen to?

    • @8_Bit
      @8_Bit  Před 2 lety +1

      This episode's song has a video here: czcams.com/video/lHOxmXCSqAs/video.html Some of the other songs are on that channel too. Thanks for the interest, I added the link to the video description now too, which I often forget to do.

    • @josefjelinek
      @josefjelinek Před 2 lety

      @@8_Bit very cool, thanks; subscribed

  • @cairsahrstjoseph996
    @cairsahrstjoseph996 Před 2 lety

    Has it really been that long ? Not since last year ? I've forgotten whatever the program was about.

  • @petesapwell
    @petesapwell Před 5 měsíci

    Incredible ideas there and a useful tip about $ffd2

  • @csbruce
    @csbruce Před 2 lety +4

    1:30 Is Turbo Macro Pro free to redistribute?
    5:12 (At this point in watching the video): Is this the final version? The main loop could be shortened to: - LDA $D41B : AND #1 : ADC #205 : JSR $FFD2 : BCC - after putting a CLC in the initialization code.
    8:15 It'd be fun to "POKE" the characters on the screen (do the screen codes have a similar pattern?) with STA (ptr),Y and then go back to the start of the screen RAM instead of scrolling. That would show how fast Machine Language is compared to BASIC.
    In BASIC, you could PRINT "{HOME}" : FOR I=1 TO 999 : print char : NEXT.
    9:55 Okay, this looks familiar!
    11:31 You could also read the CHROUT documentation: .CS=error, .CC=success.
    12:56 (At this point in watching the video): You could also use the low byte of the CIA IRQ countdown timer. This is effectively what +RND(.) is doing (except that's using the high bit).
    21:25 Why are you using ROR instead of LDA : AND #1? ROR will write the rotated result back out to the timer register, which will presumably change the range of the countdown.
    21:59 When you were doing that Transactor memory-scan program, you found some areas apparently in the I/O space that seemed to show continuously changing random values. Would one of those locations be usable?

    • @8_Bit
      @8_Bit  Před 2 lety +1

      I don't know if Turbo Macro Pro is truly free to distribute. TMP, and its predecessor Turbo Assembler, were both commercial products of a German company called Omikron in the 1980s. Both programs have been modified and distributed by probably dozens of different scene groups over the last 30-whatever years without any challenge that I'm aware of; this version by Style has been "re-sourced" and re-assembled with many bug fixes and new features. For example, the REU support wasn't in the original at all.

    • @8_Bit
      @8_Bit  Před 2 lety +1

      re: CHROUT .CS=error, .CC=success, I actually went looking for that in the C64 Programmer's Reference Guide while preparing for this episode, as I thought there was a success/error indicator. However, on page 278, the description of CHROUT, says "Error returns: 0 (See READST)" and doesn't mention carry at all. Any ideas on where this carry functionality is documented?

    • @8_Bit
      @8_Bit  Před 2 lety

      re: using ROR instead of LDA : AND #1, it was part of that (unsuccessful) multiply-by-two approach I show at the end and since it didn't seem to negatively affect the apparent randomness in this application, it stuck around in this version. But yes, it very likely is messing with the countdown. It just didn't seem to make the bits that end up in carry any less "random-ish" which is all I was concerned about.

    • @wChris_
      @wChris_ Před 2 lety

      @@8_Bit you might be in luck, as computer programs (or 1:1 'programs for data processing'), were added after 1985, which means they did not have any copyright before (but the source was protected!). But dont quote me, im not a lawyer!

    • @csbruce
      @csbruce Před 2 lety +2

      @@8_Bit: C64 PRG page 271: "ERROR RETURNS: A return from a KERNAL routine with the CARRY set indicates that an error was encountered in processing. The accumulator will contain the number of the error."

  • @nathanjohnson9715
    @nathanjohnson9715 Před rokem

    does anyone know how to get back to bank 0 in TMP w/ REU after you've switched to another bank? I've looked through the docs, and there doesn't seem to be a way to do it. There's a bank switching option, but it only allows you to switch to banks 2-7 for whatever reason.

    • @8_Bit
      @8_Bit  Před rokem

      I just tried it and you're right. That seems pretty bizarre; not sure if that's a bug or oversight or something by design that I don't understand the reason for. A potential work-around is to exit to basic with back arrow 1, type new, load"TMP+REU*",8,1 then sys32768 to re-enter. You should be back in source bank 0 and your code should still be there. Worked for me just now, anyway.

    • @nathanjohnson9715
      @nathanjohnson9715 Před rokem

      @@8_Bit Thanks for the response! So that didn't quite work. I got an "out of memory" error. (I'm guessing I must've overwritten something I shouldn't have in my code). Luckily I took your advice in one of your other videos and I have a reset button at the ready, and after resetting, I was able to run TMP again and get my code back on bank 0. Wheww. Thanks for your help!

    • @8_Bit
      @8_Bit  Před rokem

      @@nathanjohnson9715 Did you do the NEW command before the LOAD? Capitalized this time to stand out more :)

    • @nathanjohnson9715
      @nathanjohnson9715 Před rokem

      @@8_Bit ha, nope, I sure didn't. Worked beautifully once I actually followed instructions.

  • @williamsquires3070
    @williamsquires3070 Před 2 lety +1

    Hi. What happens if you eliminate the “LDA #$80” line in the initialization section? Since you still have 0xFF in the accumulator, bit 7 is still set, which is what you want in 0xD412. Would the extra ‘1’ bits (bits 0-6) cause a problem here?

  • @wasserwasser5555
    @wasserwasser5555 Před 2 lety

    i think it would be nice to have this in graphics mode without the character routine

  • @dwhxyz
    @dwhxyz Před 2 lety +3

    For small (256 bytes) machine code programs which includes some "randomness" this still amazes me - czcams.com/video/sWblpsLZ-O8/video.html . The code and how it works could make for an interesting video.

  • @rosiefay7283
    @rosiefay7283 Před 2 lety

    Cute. But how small can you golf a program which outputs a maze where there is guaranteed exactly one route between any two locations? No walls that completely wall off one area from another. No loops.

  • @stevethepocket
    @stevethepocket Před 2 lety

    That's a lot slower than I was expecting a machine-language program to be. And you say most of that is CHROUT being the bottleneck? That's... actually not surprising now that I think about what all has to be done between reading an ASCII code and actually getting it onto the screen. In particular, the process of checking for every possible control character and converting what's left from ASCII to a character code probably requires a laundry list of compares (I wonder if 205/206 was picked over 109/110 initially because it somehow bypasses some of them), all of which could be done away with when you know you're only going to by outputting one of two characters. Even the value of register 646 could possibly be stored permanently in a CPU register since you only need to retrieve it at the beginning.

    • @csbruce
      @csbruce Před 2 lety +2

      The bulk of the overall CHROUT time is probably spent scrolling the screen.

    • @Curt_Sampson
      @Curt_Sampson Před 2 lety +1

      As well as the character to screen code conversion process and scrolling, there's also the overhead of figuring out which channels have been opened for output and sending the character to each one. There's really a fair amount of overhead in that CHROUT routine as compared to simpler microcomputer ROMs where the commonly used routine simply prints to the screen and that's it.

    • @stevethepocket
      @stevethepocket Před 2 lety +2

      @@Curt_Sampson You'd think the part that outputs to the screen specifically would be a subroutine that coders could just JSR to directly and cut out the middleman. I remember _Mapping the C64_ mentioning that some Kernal routines work like that.
      EDIT: OK, yeah, it turns out there is, at $E716. Glad I went to the trouble of converting that whole book to searchable text now.

    • @Curt_Sampson
      @Curt_Sampson Před 2 lety

      @@stevethepocket Yup, and nice work on digging that up. The only thing to check there is whether the code that delays after a newline when you're holding down CTRL is part of the generic routine or the $E716 routine.

    • @stevethepocket
      @stevethepocket Před 2 lety

      @@Curt_Sampson Already tried it and yes it is. But I think csbruce was right about the scrolling being the real bottleneck because I didn't notice any difference (and I can't imagine scrolling the entire screen would be something you could easily speed up, nor would you really want to). I'd have to record the footage and go over it frame by frame to see if the initial screen fill is any faster; they both go by too fast to really tell.

  • @stoif76
    @stoif76 Před 2 lety

    Now do it with the Super CPU 👍😁👍

  • @GoatTheGoat
    @GoatTheGoat Před 2 lety

    7:24 Eighty or forty characters per line?

    • @GoatTheGoat
      @GoatTheGoat Před 2 lety

      @Mr Guru Ah, it scrolls two lines at a time, therefore eighty characters per scroll event. Got it.

  • @dr.ignacioglez.9677
    @dr.ignacioglez.9677 Před 2 lety

    I LOVE C64 👍🥂🎩

  • @EmilOppelnBronikowski
    @EmilOppelnBronikowski Před 2 lety

    I knew this thing is coming. What's the next power play from Robin? 10 PRINT in IC form?

  • @jesperlundbyrasmussen7844

    Anyone up for making this to a vertical scroll with a sweet SID tune?

  • @royalestel
    @royalestel Před rokem

    Call me dumb, but after this assembles to machine code, isn't it 14 bytes? I'm going to noodle over this. Not sure I know enough to do anything

  • @SIDCIAVIC
    @SIDCIAVIC Před 2 lety

    You can't read the raster register during badlines.

  • @gettingpast4391
    @gettingpast4391 Před rokem

    For the basic version, try this: 0 PRINT CHR$(RND(.)+I);:GOTO (set i to 205.5 then type goto 0). Notice INT() has been removed and 205.5 is a variable

  • @DasIllu
    @DasIllu Před 2 lety +3

    That is simply "a maze thing"
    ...
    sorry

  • @TheUtuber999
    @TheUtuber999 Před rokem

    This video motivated me to make a smooth scrolling version of the pseudo maze generator for the C64...
    10 forx=49152to49461
    20 readn:pokex,n:next
    30 sys49152
    100 data 169,0,141,33,208,169,11,141
    110 data 32,208,169,5,141,134,2,169
    120 data 147,32,210,255,173,17,208,41
    130 data 247,141,17,208,169,255,141,15
    140 data 212,169,128,141,18,212,160,7
    150 data 140,12,193,32,110,192,32,6
    160 data 193,173,17,208,41,240,13,12
    170 data 193,141,17,208,206,12,193,172
    180 data 12,193,192,255,208,229,32,131
    190 data 192,32,228,255,240,216,32,246
    200 data 192,169,27,141,17,208,162,24
    210 data 160,0,24,32,240,255,162,0
    220 data 188,13,193,136,152,32,210,255
    230 data 232,224,41,208,243,96,160,0
    240 data 173,27,212,41,1,105,205,153
    250 data 192,7,153,192,35,200,192,40
    260 data 208,238,96,169,4,205,136,2
    270 data 208,6,32,148,192,76,147,192
    280 data 32,205,192,96,160,0,185,40
    290 data 4,153,0,32,185,40,5,153
    300 data 0,33,185,40,6,153,0,34
    310 data 185,40,7,153,0,35,200,208
    320 data 229,169,32,160,0,153,192,35
    330 data 200,192,40,208,248,32,6,193
    340 data 120,169,32,141,136,2,169,133
    350 data 141,24,208,88,96,160,0,185
    360 data 40,32,153,0,4,185,40,33
    370 data 153,0,5,185,40,34,153,0
    380 data 6,185,40,35,153,0,7,200
    390 data 208,229,169,32,160,0,153,192
    400 data 7,200,192,40,208,248,32,6
    410 data 193,120,169,4,141,136,2,169
    420 data 21,141,24,208,88,96,173,17
    430 data 208,16,251,96,0,18,81,84
    440 data 70,86,69,80,33,78,66,91
    450 data 70,33,84,68,83,80,77,77
    460 data 70,83,33,67,90,33,76,70
    470 data 87,74,79,33,76,83,66,86
    480 data 84,79,74,68,76,33

  • @TheUtuber999
    @TheUtuber999 Před rokem

    On the Commander X16, the page of memory starting at address $C000 looks pretty "random" while viewing its contents in the monitor. The pattern generated from the following code looks fairly good, too...
    _Standard version..._
    .,8000 A0 00 LDY #$00
    .,8002 B9 00 C0 LDA $C000,Y
    .,8005 29 01 AND #$01
    .,8007 69 CD ADC #$CD
    .,8009 20 D2 FF JSR $FFD2
    .,800c C8 INY
    .,800d 20 E4 FF JSR $FFE4
    .,8010 F0 F0 BEQ $8002
    .,8012 60 RTS
    _Slanted version..._
    .,8000 A0 00 LDY #$00
    .,8002 A2 CD LDX #$CD
    .,8004 B9 00 C0 LDA $C000,Y
    .,8007 C8 INY
    .,8008 C9 55 CMP #$55
    .,800a 90 01 BCC $800D
    .,800c E8 INX
    .,800d 8A TXA
    .,800e 20 D2 FF JSR $FFD2
    .,8011 20 E4 FF JSR $FFE4
    .,8014 F0 EC BEQ $8002
    .,8016 60 RTS

  • @christianknechtel8683
    @christianknechtel8683 Před 2 lety

    Is using a different Charset cheating?

    • @tmilker
      @tmilker Před 2 lety

      If you're going for size, the setup to change the character set would make the program exceed 12 bytes.

    • @christianknechtel8683
      @christianknechtel8683 Před 2 lety

      @@tmilker Makes sense.I forgot it´s about size.