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_Bit2 жыл бұрын
Fantastic work!!
@peterszabo35842 жыл бұрын
@@8_Bit Thanks. I really love your videos, inspiring and thorough content! Keep it up!
@paulkocyla13432 жыл бұрын
That´s genious - that´s really really good!
@PSL19692 жыл бұрын
Wow, that's amazing trickery. I think we have a winner 🥇😎👍
@paulkocyla13432 жыл бұрын
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
@thedigitalemotion2 жыл бұрын
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. 🙏🏼🙌🏼🙏🏼🙌🏼
@CubicleNate2 жыл бұрын
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.
@stephenelliott70712 жыл бұрын
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!
@G1itcher2 жыл бұрын
I'm 34 and I think computers were better in the 80s!
@d-h4ck4012 жыл бұрын
@@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-ny6kn2 жыл бұрын
@@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.
@Qba4742 жыл бұрын
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!
@MichaelDoornbos2 жыл бұрын
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
@LeftoverBeefcake2 жыл бұрын
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_engineer2 жыл бұрын
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!
@DavidYoud2 жыл бұрын
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.
@espenskog87452 жыл бұрын
Loved the optimizations and your step by step walk through. It's like we're 16 again :)
@JosipRetroBits2 жыл бұрын
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.
@geehaf2 жыл бұрын
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.
@NotaWizard2 жыл бұрын
awesome. And love the maze behind the patron list in the outro. Classic Robin subtle brilliance. :)
@bierundkippen7202 жыл бұрын
"behind" is funny.
@lordanthrax24172 жыл бұрын
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!
@paulvanderlaak7002 жыл бұрын
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. 👍
@ZXAtari2 жыл бұрын
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.....
@PSL19692 жыл бұрын
Hey Robin, great episode! 😎 Cool to see all the attempts, and how you explained it all was great! 👍👍👍
@8_Bit2 жыл бұрын
Thanks Peter for your great ideas!
@PSL19692 жыл бұрын
@@8_Bit I only had them because of your own great ideas :) And a great challenge to everyone, to improve upon it 👍👍👍
@agranero62 жыл бұрын
There is a book about this program. It is called 10 PRINT ... (in fact the title is the entire program).
@phlogicali2 жыл бұрын
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
@PSL19692 жыл бұрын
Interesting!
@8_Bit2 жыл бұрын
Nice, I will give this a try!
@8_Bit2 жыл бұрын
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!
@phlogicali2 жыл бұрын
@@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. :-)
@paulkocyla13432 жыл бұрын
WOW, respect! That´s damn smart!
@igorwollersheim464 Жыл бұрын
Again a great video with lots of information. Again learned a lot from your video..
@IsaacKuo2 жыл бұрын
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_Bit2 жыл бұрын
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 :)
@michaelstoliker971 Жыл бұрын
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.
@HannesEder2 жыл бұрын
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.
@paulkocyla13432 жыл бұрын
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
@PSL19692 жыл бұрын
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.
@paulkocyla13432 жыл бұрын
@@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 :)
@PSL19692 жыл бұрын
@@paulkocyla1343 I'll try that 👍 9 byte that's crazy. I'll have to check that out as well.
@paulkocyla13432 жыл бұрын
@@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.
@PSL19692 жыл бұрын
@@paulkocyla1343 Nice, I will check it out. This is getting crazy! :)
@mrmimeisfunny2 жыл бұрын
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)
@warmCabin2 жыл бұрын
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).
@midtskogen2 жыл бұрын
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.
@byteforever78292 жыл бұрын
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
@AmstradExin2 жыл бұрын
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.
@eekee60342 жыл бұрын
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. :)
@paulkocyla13432 жыл бұрын
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 😀.
@properjob23112 жыл бұрын
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?
@CityXen2 жыл бұрын
Always proving there is more than one way to do something. Excellent vid. Cheers
@argoneum2 жыл бұрын
(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 😸
@bs_blackscout2 жыл бұрын
now x86 asm 😂
@cairsahrstjoseph9962 жыл бұрын
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 Жыл бұрын
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. ;)
@VulpisFoxfire2 жыл бұрын
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).
@bgone55202 жыл бұрын
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.
@eugenetswong2 жыл бұрын
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?
@andreroussel Жыл бұрын
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 Жыл бұрын
I tried your suggestion and you are so right, it really *does* look more like a real maze using those two chars.
@indiocolifa2 жыл бұрын
Unmatched wisdom, as always. Top notch!
@gwivongalois61692 жыл бұрын
Loved the implementation that used the SID as a source of randomness.
@LynxSnowCat2 жыл бұрын
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 ?
@d.j.peters2 жыл бұрын
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 :-)
@bierundkippen7202 жыл бұрын
That would be super fast.
@saganandroid41752 жыл бұрын
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.
@JamsterJules2 жыл бұрын
Love it! How about getting it to run as fast as you can by rewriting the system library?
@williamsquires30702 жыл бұрын
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?
@HeffeJeffe782 жыл бұрын
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.
@londongaz22 жыл бұрын
Love the end song!
@karlramberg2 жыл бұрын
Would be cool to see a episode of this where you optimize for speed
@MrRobbyvent2 жыл бұрын
very unlikely: the routine at $ffD2 has a lot of stuff to do!
@DavidYoud2 жыл бұрын
@@MrRobbyvent Pretty sure we could make a special-purpose print routine that's faster than $FFD2
@MrRobbyvent2 жыл бұрын
@@DavidYoud I'm pretty sure you could'nt
@DavidYoud2 жыл бұрын
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).
@DavidYoud2 жыл бұрын
KZbin ate my post with a link, but check out disassembly of $E716, lots of unnecessary processing to be removed
@daveloomis2 жыл бұрын
"Since last year!" Instant like.
@8_Bit2 жыл бұрын
Gotta use that dad joke every year.
@RixtronixLAB2 жыл бұрын
Nice video, like it, thanks for sharing :)
@antonnym2142 жыл бұрын
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?
@fnjesusfreak2 жыл бұрын
Nope, only A, X, Y, P, S and the instruction pointer.
@saveddijon2 жыл бұрын
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.
@dougjohnson42662 жыл бұрын
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?
@rotordave812 жыл бұрын
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.
@Eightbitswide2 жыл бұрын
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_Bit2 жыл бұрын
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: kzbin.info/aero/PLvW2ZMbxgP9z9Un4LXivII_D1Hh5gZ7r9
@MrWaalkman2 жыл бұрын
OBC! :)
@andresbravo20032 жыл бұрын
Well, I know about machine language because it’s quite an impressive way to build and compile faster.
@MattKasdorf2 жыл бұрын
Impressive tutorial, thank you.
@8BitNaptime2 жыл бұрын
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?
@csbruce2 жыл бұрын
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_Bit2 жыл бұрын
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_Bit2 жыл бұрын
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_Bit2 жыл бұрын
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_2 жыл бұрын
@@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!
@csbruce2 жыл бұрын
@@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."
@saganandroid4175 Жыл бұрын
11:34 Int Disable and Print Char during Int code... very scary.
@JohnnyWednesday2 жыл бұрын
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?
@JeremyNasmith2 жыл бұрын
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.
@JohnnyWednesday2 жыл бұрын
@@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
@SteveGuidi2 жыл бұрын
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_Bit2 жыл бұрын
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.
@SteveGuidi2 жыл бұрын
@@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.
@stefanguhren10362 жыл бұрын
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?
@r3jjs2 жыл бұрын
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.
@paulkocyla13432 жыл бұрын
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
@peterszabo35842 жыл бұрын
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)
@paulkocyla13432 жыл бұрын
@@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.
@peterszabo35842 жыл бұрын
@@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 Жыл бұрын
21:46 Wouldn't rotating the CIA timer low byte mess up stability of the system?
@BlackGymkhana2 жыл бұрын
I wish this type of skills and optimizations applied to modern operating systems...
@theosib8 ай бұрын
How do you make sure basic doesn't stomp on the memory used by the assembler or you asm program?
@dwhxyz2 жыл бұрын
For small (256 bytes) machine code programs which includes some "randomness" this still amazes me - kzbin.info/www/bejne/qYjFnaOpgb9ghZo . The code and how it works could make for an interesting video.
@lordanthrax24172 жыл бұрын
Do you know 10 print racer revamp? Lovely little game
@raoullangner-macmillan76552 жыл бұрын
Thanks for the great video.
@bob-ny6kn2 жыл бұрын
205/206 dec is 1100 1101 bin. Would NOTing the two LSBs reduce cycles of transferring bytes?
@TheBookaroo2 жыл бұрын
Hi, one though would be to search in rom for part of the code with a subroutine return just after and just called subroutines?
@rosiefay72832 жыл бұрын
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.
@stevethepocket2 жыл бұрын
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.
@csbruce2 жыл бұрын
The bulk of the overall CHROUT time is probably spent scrolling the screen.
@Curt_Sampson2 жыл бұрын
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.
@stevethepocket2 жыл бұрын
@@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_Sampson2 жыл бұрын
@@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.
@stevethepocket2 жыл бұрын
@@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.
@neurogate4592 жыл бұрын
Cool, thank you
@retrobytes.v652 жыл бұрын
Hello Does anyone recognise the Disk Emulator / SD Card adaptor that Robin is using ?
@8_Bit2 жыл бұрын
I do! :) It's the uIEC/SD, sold by RETRO Innovations.
@cairsahrstjoseph9962 жыл бұрын
Has it really been that long ? Not since last year ? I've forgotten whatever the program was about.
@JustWasted3HoursHere2 жыл бұрын
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_Sampson2 жыл бұрын
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_Bit2 жыл бұрын
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?
@JustWasted3HoursHere2 жыл бұрын
@@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!
@JustWasted3HoursHere2 жыл бұрын
@@Curt_Sampson I guess Commodore modified the motherboard slightly in later versions to fix this issue?
@8_Bit2 жыл бұрын
@@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.
@damienretro44162 жыл бұрын
Love it
@gertlynge2 жыл бұрын
What about bit 0 from the pot pin in the jjoystick port. That mest be kind of random?
@kurtreber9813 Жыл бұрын
How would one get the output to scroll smoothly?
@josefjelinek2 жыл бұрын
Are the end songs available somewhere to listen to?
@8_Bit2 жыл бұрын
This episode's song has a video here: kzbin.info/www/bejne/onmyqaCOeLikd9U 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.
@josefjelinek2 жыл бұрын
@@8_Bit very cool, thanks; subscribed
@wasserwasser55552 жыл бұрын
i think it would be nice to have this in graphics mode without the character routine
@DasIllu2 жыл бұрын
That is simply "a maze thing" ... sorry
@nathanjohnson9715 Жыл бұрын
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 Жыл бұрын
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 Жыл бұрын
@@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 Жыл бұрын
@@nathanjohnson9715 Did you do the NEW command before the LOAD? Capitalized this time to stand out more :)
@nathanjohnson9715 Жыл бұрын
@@8_Bit ha, nope, I sure didn't. Worked beautifully once I actually followed instructions.
@royalestel Жыл бұрын
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
@stoif762 жыл бұрын
Now do it with the Super CPU 👍😁👍
@gettingpast43912 жыл бұрын
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
@DAVIDGREGORYKERR2 жыл бұрын
can the rnd() not be based on DES64
@TheUtuber999 Жыл бұрын
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
@jesperlundbyrasmussen78442 жыл бұрын
Anyone up for making this to a vertical scroll with a sweet SID tune?
@EmilOppelnBronikowski2 жыл бұрын
I knew this thing is coming. What's the next power play from Robin? 10 PRINT in IC form?
@GoatTheGoat2 жыл бұрын
7:24 Eighty or forty characters per line?
@GoatTheGoat2 жыл бұрын
@Mr Guru Ah, it scrolls two lines at a time, therefore eighty characters per scroll event. Got it.
@SIDCIAVIC2 жыл бұрын
You can't read the raster register during badlines.
@deblauweschicht2 жыл бұрын
Another kind of maze can be made with 10 A=RND(1)*4:PRINTCHR$(A+171-(A>1)*5);:GOTO10 Not quite as elegant a one-liner, as the four characters involved are not all adjacent in the PETSCII table.
@dr.ignacioglez.96772 жыл бұрын
I LOVE C64 👍🥂🎩
@williamsquires30702 жыл бұрын
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?
@donwald34362 жыл бұрын
I bet you'd get a significant speed-up by inlining the print subroutine. All that pushing and popping state from stack, yuck.
@melanierhianna2 жыл бұрын
BBC BASIC Version 10REPEAT:PRINTCHR$(47+INT(0.5+RND(1))*45);:UNTILFALSE The entire program comes in at 32 bytes because REPEAT, PRINT, CHR$(, INT(, RND(, UNTIL and FALSE come out as byte each as they are tokenised. BBC Assembler Version 10 FOR N%=0 TO 3 STEP 3 20 P%=&2000 30 [ 40 OPT N% 50 .loop 60 jsr &AF51 ; &AF80 for BASIC 1 65 lda &2A 70 ror A 80 lda #47 90 bcs print 100 adc #45 110 .print 120 jsr &FFEE 130 jmp loop 140 ] 150 NEXT CALL &2000 Routine AF51 is the BASIC RND variable function. RND without braces or an argument returns a random signed 32 bit integer in zero page 2A, 2B, 2C and 2D (The Integer Work Area). We just take the lowest byte. Routine FFEE is OSWRCH i.e. OS write character. Its the operating system equivalent of PRINT CHR$(A).
@melanierhianna2 жыл бұрын
The BBC Micro, apart from Mode 7 (Teletext mode), does not have character mapped screen memory so you have to use the OS to write characters. Mode 7 has different characters in the character set to \ and / and modes 3 and 6 have 25 line screens and not 32 line screens and space them out with scan lines which are not backed by memory. So best to use one of the other screen modes.
@melanierhianna2 жыл бұрын
My optimised version. Rather than using the \ and / characters which, in ASCII, are quite far apart, I've defined a couple of user characters 128, and 129. 10 VDU23,128,&80,&40,&20,&10,8,4,2,1 20 VDU23,129,1,2,4,8,&10,&20,&40,&80 30 FOR N%=0 TO 3 STEP 3 40 P%=&2000 50 [ 60 OPT N% 70 .loop 80 jsr &AF51 ; &AF80 for BASIC 1 90 ror &2A 100 lda #128 110 adc #0 120 jsr &FFEE 130 jmp loop 140 ] 150 NEXT Since the $ as a prefix is already used in BBC BASIC (As a way of storing strings in memory, e.g. $1234="Hello world"), then & is used at the 'HEX' indicator. Also the OSWRCH routine, unlike the C64 equivalent, leaves carry in an unknown state, hence jmp.
@melanierhianna2 жыл бұрын
Okay I got it smaller! 12 bytes... 10 VDU23,128,&80,&40,&20,&10,8,4,2,1 20 VDU23,129,1,2,4,8,&10,&20,&40,&80 30 FOR N%=0 TO 3 STEP 3 40 P%=&2000 50 [ 60 OPT N% 70 .loop 80 jsr &AF51 90 lda #&81 100 and &2A 120 jsr &FFEE 130 jmp loop 140 ] 150 NEXT It basically ANDs the random value with &81 which results in either &00, &01, &80 or &81. This is a cheat. 0 is the null character which does nothing. 1 means send next character to printer (so it doesn't appear on the screen). The other two are characters 128 and 129 i.e. our maze characters.
@christianknechtel86832 жыл бұрын
Is using a different Charset cheating?
@tmilker2 жыл бұрын
If you're going for size, the setup to change the character set would make the program exceed 12 bytes.
@christianknechtel86832 жыл бұрын
@@tmilker Makes sense.I forgot it´s about size.
@petesapwell8 ай бұрын
Incredible ideas there and a useful tip about $ffd2