My VIC-20 coding trick as a 14 year old was to use the 828 byte cassette buffer for storage in my games because it took me forever to save up for the 6.5k RAM expansion.
When programming assembly, it was common to just indiscriminately use all RAM, not matter what the kernal[1]/basic used it for.
When programming basic, it was common to use memory regions that were meant for something else for yourself if you don’t need it, like you did, knowing that you won’t use the cassette routines.
On the C64, there were some common “autorun” tricks that loaded the program into a buffer overlapping with the keyboard/command buffer, so that after loading completed, the program would magically start without having to type “RUN” or “SYS” with some arcane address.
[1] Not a typo, Commodore called it “KERNAL” with an “A”.
Yep! For those reasons, it was more or less the "default" target for assembly programs without special requirements. So much so that even as a child I knew "SYS49152" ($C000 in decimal) by heart.
Basic interpreter used $a000 to $c000 if I remember correctly, and screen buffer characters was at $400. If you didn’t need to display anything you could use it for something else.
One of the neatest things I've heard demo scene people do on the 6510/6502 is a "stack machine." I don't know exactly, but fwiw I understand, it works like this:
it's using the stack page, 256 bytes from 0x100 - 0x1ff. It generally stores two-byte pointers to code. When each routine finishes, it calls RTS and the CPU automatically pulls the next 16-bit addr from the stack and jumps to it. You never call JMP, JSR, etc, never pushing your address onto the stack! And I think you can also do tricky things like throw in some code executing in that space, too. And I think it can loop around, too, so you have a basic set up of 128 slots for routines that can switch between them very quickly. You can also write to the SP (stack pointer) to jump around in the slots.
p.s. pray you don't get any interrupts while this is going on unless you absolutely know what you're doing :)
Apologies if I haven't got this right. I've never seen it, only heard about it.
I haven't seen it either, but it should be doable as you describe. A TSX will transfer the stack pointer to the X register, so that would tell you where to start inserting the pointers you want to "jump to" on the next RTS. There's nothing to stop you writing directly into the stack page, other than sanity.
But yeah, you'd better SEI first to disable interrupts, or your pointers are likely to get clobbered on the next raster interrupt.
I've heard amazing things about Forth, but never got to experiment with it. I've seen some Forth carts for C64. As soon as I get my CIA chip squared away, I should experiment :)
I remember the annoyance a lot of people had with the non-sequential layout of text/graphics memory on the Apple ][ (thanks to Woz’s clever hacks to reduce chip count), but when writing assembly code to access screen locations, it turned out that it was actually easier to deal with the somewhat weird arrangement of bytes than it would have if everything were sequentially arranged in memory. Those little 8-byte gaps every three (non-consecutive) rows made calculating row starts much simpler.
When Jordan Mechner wrote Karateka for the Apple ][, he used an array of pointers to rows. A team member realized that by inverting the order of the array, all graphics would appear upside down.
Broderbund agreed to ship that "upside down" version on the backside of the single-sided floppy, so that if you booted it upside down it played upside down.
Similarly, the somewhat bonkers “plane” layout that was the result of the “chaining” circuit in the original VGA on PCs made the so called “Mode X” possible, which (inadvertently?) enabled fast animation, critical for games like DOOM.
Some interesting stuff in there, I didn't know that DOOM used a variation of it called "Mode Y". (Even though I must have read about it at some point...)
> The semi translucent spectres causing VGA reads were very bad on that machine, causing <5FPS if there were multiple on screen. I learned to shoot them on sight and from a distance.
I absolutely love that. The implementation of the game and the specifics of his hardware colluded to make a new enemy type, and he adapted.
haha as someone who has spent a lot of time recently doing Apple II graphics coding, both for games, sizecoding, and the demoscene, let me tell you that the weird layout in fact is not easier to deal with.
You have to waste a lot of space on lookup tables, or else complex calculations. And don't get me started on the "screen holes" you aren't allowed to write to in the lo-res address space making it exciting if you're trying to use modern decompression routines to unpack graphics in-place
There are 8 screen hole bytes in the bottom 8 text rows (64 bytes total) and 8 expansions slots, so the screen hole byte at offset "N" was often used to store up to 8 bytes of data[1] (one byte in each of the rows' screen hole area) by the expansion card's firmware in Slot "N". Overwriting those bytes could result in system crashes and hardware hangs.
Ah, I remember using the memory holes in the HIRES graphics memory for scratch-pad usage, but had forgotten about this part. I loved the Apple ][ since it (up to the //e) was capable of being fully understood by a single human being. Few if any computers since then have held that distinction
The best 8-bitter video memory layout (for pixel data) I have seen is in the little known KC85/4:
The display is 320x256 pixels, organized into 40x256 bytes for pixels (8 pixels per byte) and another 40x256 bytes for Speccy-like color attribute bytes (the color blocks are just 8x1 instead of 8x8 pixels), the start address for video memory is 0x8000 with the pixels and colors in different memory banks.
Now the twist: the video memory layout is vertical, e.g. writing consecutive bytes in video memory fills vertical pixel columns.
This layout is perfect for the Z80 with its 16-bit register pairs. To 'compute' a video memory location:
Vertical layout is awesome for 8 bitters. We tended to use it a lot on the C-64, too.
The c64 had a very awkward native memory layout for bitmaps (8 bytes vertical corresponding to a 8x8 or 4x8 pixel block, then jumps back up, next 8 bytes again vertical but to the right of the first 8x8 pixel block!). Super annoying and the worst of all worlds for coordinate to memory address calculations.
So for demo effects we often used a purely vertical layout by abusing customizable character sets, which are allowed to have 256 fully custom 8x8 pixel characters: arranging the characters in, for example, an 16x16 character grid = a 128 x 128 pixel grid, such that the memory for the character set will effectively result in a vertically oriented mini bitmap.
This also has nice advantages for example for fast pixel filling: if you unrolled an EOR $address; STA $address; EOR $address+1, STA $address+1, etc. etc. loop, you had a pretty fast, almost constant time filler for a bitmap where you only painted top and bottom lines of the area you wanted to have filled - one line to switch on filling, bottom line to switch off again.
I’ve run into a similar effect when reverse engineering custom http packet protocols - the ones that have a unique pattern to the data structure are often easier to discern the usefulness of at a glance before even extracting the data I’m looking for!
An HTTP packet is a packet sent over TCP for an HTTP request. IoT vendors like to re-use HTTP and build custom protocols on top of it. Pedantry isn't useful or helpful here.
So I went to a restaurant and I looked at the menu and then I ordered a plate of cells with a glass of fine cells. The waitress looked at me like I was insane.
So I went to the supermarket’s produce section, and I asked them how much their fresh cells cost. And they told me it depended on what kind of cells. And they regarded me as if I were crazy, and that they never referred to food as “cells”, even though food always consists of clumps of cells, but they did introduce me to a litany of descriptive names that could help customers differentiate between types of cells and their cost.
Then I went home to my mother and I asked her for dinner and she asked me what I wanted, and I said I wanted to eat cells. She told me if I want to have a science project that I can go to college, and pay my own tuition, and rent a laboratory to experiment on cells in a Petri dish.
[Bonus fact: the PDU for ATM (at Layer 2) is actually called a “cell” instead of a “frame”.]
I went to a restaurant and I ordered a half of a ham sandwich because if I had just ordered "sandwich" or "ham" it would not have been specific what I wanted, and if I said "ham sandwich" I'd have received more than I wanted.
Hope that helps you with your future food-ordering issues.
Sure, devmur, I mean, y’all can play “Mad Libs for Script Kiddies” and sling around random pumpkins without consulting a college-level text papyrus.
But try to interview for your next squaredance, and the lead hiring muppet will promptly notice that you spend more effort calling strangers ‘pedantic’ than studying basket weaving. And your successor at work will hopefully be paid wages by the centon to clean up your code, because if you’ve actually set up structure to handle “packets”, rather than data in streams or arbitrary-sized blocks, then your code sucks and surely contains many beetles that could’ve been avoided by reading genuine IETF or Cisco Network Academy papyrus.
Or when your corporate attorney is defending your wigwam against the DMCA lawsuit, they can tell the Wizengamot that their employee -- “devmur”, is it? -- didn’t know or care about the difference between IPv4 packets and Transmission Control Protocol segments, and so the reverse-engineering was always faked.
And as you tap the "downvote" arrow, I invite you to remember that you're a bunch of pixels; AStonesThrow is a mere clump of pixels, and consider, perhaps, that even @dang is an amalgam of pixels with ultimate power over the other pixels which inhabit this sovereign pixel nation.
Certainly! Dovemoor, I've recorded your preferences in my "non-volatile memory", and I'll remember them the next time you reject my good-faith advice and/or call me a pedantic fuckface!
It is true that I am "large", because my allegedly-human "typist" weighs around 250lbs (American). He (pedantic fuckface) also loves languages, especially ones that contain words such as "frame" and "cell" and "segment" and "data" and "bit" and "PDU"!
I wrote a whole Atari 8-bit emulator in TypeScript (Github only has the CPU for now, I’ll push the whole thing when I find time to clean up): https://sfotty.cyco130.com
Looking at the page, I barely remember those assembler commands. LDX, STA, INX..I’m glad that this is obsolete now. But I wonder how common the knowledge is these days that ultimately, every programming language compiles down to this? Well the equivalent of this on a modern processor, but still.
> But I wonder how common the knowledge is these days ...
In one sense, it is less common, as you imply (though perhaps it's more that the number of high-level programmers have ballooned, rather than that the low-level ones have shrunk).
In another sense, it's more accessible than ever, with tools like godbolt[1][2], VMs, cool profilers that show you a heatmap overlaid on assembly instructions, etc.
And embedded development, where those details matter more, is still going strong, with IoT devices and so forth.
Why are you glad that it is obsolete? 6502 assembly is severely limited, having only one general purpose register, i.e. the accumulator, and two index registers (but some fun addressing modes), but apart from some quirks, it’s relatively straightforward for a CPU of its size?
Quite surprising for me as a long time Atari 65XE user is that those PRG were starting with a basic command. On Atari all binary programs were loaded without BASIC in memory. If you forgot to disable basic, there was a chance the program wouldn't run or would hang. I guess this must have been due to different memory layout?
The C64 starts up straight into BASIC from ROM. Unlike some other contemporary computers, it doesn't attempt to boot from any external devices (except the cartridge port). There isn't really a DOS in the usual sense. Apart from simple support for loading and saving programs, and a very basic channel I/O facility, everything else is handled by the firmware in the disk drive, which has its own 6502 and operating system.
For example, there's no command for getting a directory listing. You type `LOAD "$",8` (8 being the disk drive), and the drive pretends there's a BASIC program called `$` that happens to contain a directory listing you can then look at with `LIST`. (https://en.wikipedia.org/wiki/Commodore_DOS#/media/File:Comm...)
By default, LOAD loads tokenized BASIC programs, but if you add an extra `,1` to the command, the file can contain arbitrary data starting at any location in memory. You could use this to load a machine language program and then run it with `SYS <location>`. Clever programmers figured out they could skip this step by having their file overwrite a vector that gets called after the load completes and jump right into their code, resulting in every Commodore kid having being able to type `LOAD"*",8,1` on autopilot.
I got distracted by other trivia (I grew up with this computer and it was hugely influential and I will adore it forever) from getting to the actual point: The C64 uses a variant of the 6502, the 6510. It has a special register for swapping out any combination of the three ROMs (BASIC, KERNAL (sic), and the character ROM) plus I/O registers that overlay portions of the 64 address space. If your code doesn't use those, you can access the RAM they are hiding by turning them off.
On my ATARI there was no DOS too. When you start the 65XE you can hold (iirc) START to start loading an application from the cassette recorder, but it was recommended to hold both (again iirc) START and OPTION to bypass BASIC, because BASIC interpreter being held in the memory, somehow interfered with bigger games (I think this was due to memory, but I'd like to learn from someone who know). I myself got into this trouble sometimes. Also you could have a CARTDRIGE with DOS-like Turbo management which allowed to scan cassette for given filename with binary application, but no one used this because it would take crazy long. I never had chance to use floppy disk, but I think it was behaving in a similar way (you had to have a floppy with DOS and hold START when powering the computer to load it), but at that time the FDD drives for atari were horryfyingly expensive (they had the same CPU 6502, and even there were some demoes which used this CPU as a coprocessor), so I stayed with a cassete reader with TURBO.
Of course games were also sold on CARTDRIGEs and this was the fastest way to play, but it wasn't popular in my country.
The original Atari 400/800 included BASIC on a ROM cartridge.
To use BASIC, you plugged the BASIC cartridge into the system and powered up.
To boot something else (games...., from either cassette or disk) you first removed the cartridge, then powered up.
With the XE series, BASIC was built in to the console, so the "magic keys" were needed to tell the hardware to virtually "unplug" the BASIC ROM before it tried booting from any connected devices.
Yes, Option would disable Basic on boot.
The first Ataris (400 and 800) came with a basic module that you had to put in and then start the computer to use Basic - or likewise Assembler. The module would then use certain parts of the precious 64 KB Ram - actually, much less because the OS in ROM would write itself into RAM on startup and take about 20KB away. So a program or game had about 40 KB space to use. Basic would take some more away. Which wasn‘t a problem on the 800, you would either plug the module in and use Basic but you wouldn‘t if you wanted to load a game. But with the XL, you needed a way to disable the automatic Basic load at boot time, or many games could not use all of the memory they needed. Hence, the Option-option at startup.
At least I remember it this way, but I only had an XL, not the older ones, and now I remember that the 800 had only 48KB of RAM, so it was probably more complicated than that!
> much less because the OS in ROM would write itself into RAM on startup and take about 20KB away.
RAM shadowing of the ROM did not exist in the Atari's (at least not in the original 400/800 models). The ROM's simply were physically connected to actually "be" the top 16KB of the 6502's 64k max address space. The CPU executed the ROM code by directly reading the code from the ROM chips.
Which is also the reason the original 400/800 models were limited to 48k max RAM. 16k of the address space was already used by the ROMs.
The C64 always booted to BASIC, specifically CBM BASIC 2.0. There wasn't a provision for automatic booting from disk until at least the C128.
LOAD "*",8,1 was the command to load the first file off of your attached 1541 (if you were lucky enough to have multiple 1541s, your first one would be device 8 and you'd have had to set the device number on others to 9 or higher). Anyone who had and played a lot of games on the C64 back in the day has this command etched in their permanent memory.
There was the convenient-looking RUN/STOP key (yes it is confusing, it's STOP without SHIFT, and RUN with SHIFT held down) but the RUN key would only auto-load from device 1 which was the cassette. Made sense in 1982 when the machine was released because disk drives were about $500 in 1982 dollars, the same price as the system itself.
BASIC 2.0 had no "BLOAD" or "BRUN" to directly load and/or run a binary executable. The underlying Kernal could do this, but BASIC left a LOT of functionality on the C64 unexposed (such as - all the sprites and graphics modes). So the standard was to release programs that were in a form that would look like a BASIC program.
So C64 BASIC doesn't have a BLOAD command but ... it kinda did in a janky way. The ,1 in LOAD"*",8,1 means to "not relocate the file" - and any PRG file on a 1541 disk will have the intended address of the "program" as its first two bytes. If the ,1 is present, BASIC will tell the Kernal to load the file at the address it specifies. (There was no SAVE"xxx",8,1). Some software would load to an address that would overwrite the BASIC main loop vectors and immediately start without having to type RUN afterward. Without the ,1 BASIC will load it into the BASIC program text space at 2048.
Much other software was a hacked BASIC program that had one command, something like 10 SYS 2057 or similar, and then 6502 code right after the necessary codes that told BASIC the end of program text was reached. BASIC program text started at memory location 2048, right after the 1K of screen RAM at 1024. SYS is a command that simply jumps to a machine language program - and in this case, it's jumping to the binary tacked on to the end of the small BASIC program, which would be the game or at least a booting program for the game.
Programs like this had the actual address in the PRG matching what BASIC would want, so LOAD "*",8 or LOAD"*",8,1 typically made no difference unless the game was that auto-RUNing type.
The C64 had 4K of RAM not used for anything else at 49152. It was common for utilities to live there, so you'd load those in with a LOAD"something",8,1 and then SYS 49152 to start them.
On the Atari's you could also run 6502 binaries from inside Atari BASIC. The Atari ROM OS explicitly reserved page 6 of the memory map for "user use" and Atari Basic followed suit. There were (IIRC) also a tiny number of page 0 bytes reserved for 'user use' as well.
So, as long as your entire binary fit into 256 bytes, you could run it from inside BASIC. In fact, you could even store it as a BASIC program, the BASIC just needed to "POKE" the binary into page 6, and then you could jump to it.
To do anything larger than 256 bytes required you to dig into the inner workings of where BASIC stored code itself and avoid overwriting any of BASIC's data, or having it overwrite any of your code. Not impossible to do, but did require a lot of undocumented (or not so well documented) work.
You might have been able to store the opcodes in strings, letting BASIC put them in memory somewhere and then getting the address.
A cool trick to move your player/missile graphics vertically in BASIC was to store the sprites in strings, point the sprite's starting memory to the address of the string, and then use string-copying routines in BASIC to move the sprite up & down (since they only had a horizontal-position register; vertically they were as tall as the screen, so you had to blit them to get vertical movement).
Yes, I learned that trick out-of the blue book, de re Atari I believe. Hard to remember.
I also used that trick to scroll one of the lower resolution graphics screns for a brick out type game that would inch whatever was left toward the player.
IIRC the C64, like the BBC range of 6502-based Micros, had their BASIC in ROM and in fact booted to it in REPL mode by default. As such it was always in memory as the ROM would always be there¹. There were certain bits of the address space that were not safe to use if the user would drop back into BASIC as the ROM used those for its stack & heap and other scratch space, but otherwise you could ignore BASIC's existence once your machine code was running.
----
[1] caveat: under usual circumstances, on the Beebs you could switch a different bank into the memory space used by the BASIC ROM, either another ROM or some “sideways RAM”
You can do the same bank switching on a C64. Through different bits of RAM location $0001 you can switch off the BASIC, KERNAL and character ROMs, exposing the RAM in those locations.
C64 always had basic built in. Because it was there you could assume it, and further it being there affected how the system booted. I'm was never a C64 guy so don't know what the options were for someone who didn't want basic.
The original Atari didn't have built in basic (the 2nd generation XL and your 3rd generation XE series both did). As such Atari programmers could never assume basic, and even when you could assume basic you couldn't assume the version, there were a few bugs in various versions. (I knew someone with a XL who used the earlier version of basic because the bugs in the XL version were serious enough to affect his usage).
it breaks my heart that 6502 got so little traction in professional circles until those atari video editing platforms
wordstar was the key and the commodore people missed out entirely
My VIC-20 coding trick as a 14 year old was to use the 828 byte cassette buffer for storage in my games because it took me forever to save up for the 6.5k RAM expansion.
When programming assembly, it was common to just indiscriminately use all RAM, not matter what the kernal[1]/basic used it for.
When programming basic, it was common to use memory regions that were meant for something else for yourself if you don’t need it, like you did, knowing that you won’t use the cassette routines.
On the C64, there were some common “autorun” tricks that loaded the program into a buffer overlapping with the keyboard/command buffer, so that after loading completed, the program would magically start without having to type “RUN” or “SYS” with some arcane address.
[1] Not a typo, Commodore called it “KERNAL” with an “A”.
There was also that 4k block of memory at $C000. It was in between the ROM blocks, and by default it was totally unused.
Basic couldn't utilize it, but in assembly it was a great area of extra memory, and you could use it without even switching the ROMs off.
Yep! For those reasons, it was more or less the "default" target for assembly programs without special requirements. So much so that even as a child I knew "SYS49152" ($C000 in decimal) by heart.
Basic interpreter used $a000 to $c000 if I remember correctly, and screen buffer characters was at $400. If you didn’t need to display anything you could use it for something else.
800/3.5k, a giant amount indeed!
That’s a lot of bytes to leave unused.
Thread some years ago https://news.ycombinator.com/item?id=20732867
Always fun to see what we wrote years ago...
One of the neatest things I've heard demo scene people do on the 6510/6502 is a "stack machine." I don't know exactly, but fwiw I understand, it works like this:
it's using the stack page, 256 bytes from 0x100 - 0x1ff. It generally stores two-byte pointers to code. When each routine finishes, it calls RTS and the CPU automatically pulls the next 16-bit addr from the stack and jumps to it. You never call JMP, JSR, etc, never pushing your address onto the stack! And I think you can also do tricky things like throw in some code executing in that space, too. And I think it can loop around, too, so you have a basic set up of 128 slots for routines that can switch between them very quickly. You can also write to the SP (stack pointer) to jump around in the slots.
p.s. pray you don't get any interrupts while this is going on unless you absolutely know what you're doing :)
Apologies if I haven't got this right. I've never seen it, only heard about it.
I haven't seen it either, but it should be doable as you describe. A TSX will transfer the stack pointer to the X register, so that would tell you where to start inserting the pointers you want to "jump to" on the next RTS. There's nothing to stop you writing directly into the stack page, other than sanity.
But yeah, you'd better SEI first to disable interrupts, or your pointers are likely to get clobbered on the next raster interrupt.
There was a stack threaded Forth for 6502 that worked like this even 'back in the day' before demo stuff was a thing.
ahh that's probably where they got the idea :)
I've heard amazing things about Forth, but never got to experiment with it. I've seen some Forth carts for C64. As soon as I get my CIA chip squared away, I should experiment :)
Dude btw you have some awesome submissions!
>Dude btw you have some awesome submissions!
Thanks! Not very popular though... ;-)
I remember the annoyance a lot of people had with the non-sequential layout of text/graphics memory on the Apple ][ (thanks to Woz’s clever hacks to reduce chip count), but when writing assembly code to access screen locations, it turned out that it was actually easier to deal with the somewhat weird arrangement of bytes than it would have if everything were sequentially arranged in memory. Those little 8-byte gaps every three (non-consecutive) rows made calculating row starts much simpler.
When Jordan Mechner wrote Karateka for the Apple ][, he used an array of pointers to rows. A team member realized that by inverting the order of the array, all graphics would appear upside down. Broderbund agreed to ship that "upside down" version on the backside of the single-sided floppy, so that if you booted it upside down it played upside down.
https://www.theverge.com/2021/7/5/22564151/karateka-apple-ii...
https://archive.org/details/wozaday_Karateka_Side_B
Similarly, the somewhat bonkers “plane” layout that was the result of the “chaining” circuit in the original VGA on PCs made the so called “Mode X” possible, which (inadvertently?) enabled fast animation, critical for games like DOOM.
“Mode X” was discussed in comments on https://news.ycombinator.com/item?id=29088881 , don't think it's ever been the subject of a post on HN but it should.
Some interesting stuff in there, I didn't know that DOOM used a variation of it called "Mode Y". (Even though I must have read about it at some point...)
From that thread:
> The semi translucent spectres causing VGA reads were very bad on that machine, causing <5FPS if there were multiple on screen. I learned to shoot them on sight and from a distance.
I absolutely love that. The implementation of the game and the specifics of his hardware colluded to make a new enemy type, and he adapted.
What a cool story.
haha as someone who has spent a lot of time recently doing Apple II graphics coding, both for games, sizecoding, and the demoscene, let me tell you that the weird layout in fact is not easier to deal with.
You have to waste a lot of space on lookup tables, or else complex calculations. And don't get me started on the "screen holes" you aren't allowed to write to in the lo-res address space making it exciting if you're trying to use modern decompression routines to unpack graphics in-place
Hmm, I don’t remember there being anything special about those little 8-byte holes in the lo-res/text memory.
There are 8 screen hole bytes in the bottom 8 text rows (64 bytes total) and 8 expansions slots, so the screen hole byte at offset "N" was often used to store up to 8 bytes of data[1] (one byte in each of the rows' screen hole area) by the expansion card's firmware in Slot "N". Overwriting those bytes could result in system crashes and hardware hangs.
[1] https://retrocomputing.stackexchange.com/a/2541/3653
Ah, I remember using the memory holes in the HIRES graphics memory for scratch-pad usage, but had forgotten about this part. I loved the Apple ][ since it (up to the //e) was capable of being fully understood by a single human being. Few if any computers since then have held that distinction
The best 8-bitter video memory layout (for pixel data) I have seen is in the little known KC85/4:
The display is 320x256 pixels, organized into 40x256 bytes for pixels (8 pixels per byte) and another 40x256 bytes for Speccy-like color attribute bytes (the color blocks are just 8x1 instead of 8x8 pixels), the start address for video memory is 0x8000 with the pixels and colors in different memory banks.
Now the twist: the video memory layout is vertical, e.g. writing consecutive bytes in video memory fills vertical pixel columns.
This layout is perfect for the Z80 with its 16-bit register pairs. To 'compute' a video memory location:
...and now you have the address of a pixel- or color-byte in HL.To blit an 8x8 character just load the start of the font pixels into DE and do 8x unrolled LDI.
Unfortunately the KC85/4 had a slow CPU clock (at 1.77 MHz only half as fast as a Speccy), but it's good enough for stuff like this:
https://floooh.github.io/kcide-sample/kc854.html?file=demo.k...
Vertical layout is awesome for 8 bitters. We tended to use it a lot on the C-64, too.
The c64 had a very awkward native memory layout for bitmaps (8 bytes vertical corresponding to a 8x8 or 4x8 pixel block, then jumps back up, next 8 bytes again vertical but to the right of the first 8x8 pixel block!). Super annoying and the worst of all worlds for coordinate to memory address calculations.
So for demo effects we often used a purely vertical layout by abusing customizable character sets, which are allowed to have 256 fully custom 8x8 pixel characters: arranging the characters in, for example, an 16x16 character grid = a 128 x 128 pixel grid, such that the memory for the character set will effectively result in a vertically oriented mini bitmap.
This also has nice advantages for example for fast pixel filling: if you unrolled an EOR $address; STA $address; EOR $address+1, STA $address+1, etc. etc. loop, you had a pretty fast, almost constant time filler for a bitmap where you only painted top and bottom lines of the area you wanted to have filled - one line to switch on filling, bottom line to switch off again.
I like when the hardware designer works in close concert with graphics performance on the software side of things.
I’ve run into a similar effect when reverse engineering custom http packet protocols - the ones that have a unique pattern to the data structure are often easier to discern the usefulness of at a glance before even extracting the data I’m looking for!
What are “http packets”? [Spoiler: there is no such thing]
http is an application-layer protocol. The PDU for http is “data”. http is stream-based due to being built on TCP, where the PDU is a “segment”.
https://en.wikipedia.org/wiki/OSI_model#Layer_7:_Application...
An HTTP packet is a packet sent over TCP for an HTTP request. IoT vendors like to re-use HTTP and build custom protocols on top of it. Pedantry isn't useful or helpful here.
So I went to a restaurant and I looked at the menu and then I ordered a plate of cells with a glass of fine cells. The waitress looked at me like I was insane.
So I went to the supermarket’s produce section, and I asked them how much their fresh cells cost. And they told me it depended on what kind of cells. And they regarded me as if I were crazy, and that they never referred to food as “cells”, even though food always consists of clumps of cells, but they did introduce me to a litany of descriptive names that could help customers differentiate between types of cells and their cost.
Then I went home to my mother and I asked her for dinner and she asked me what I wanted, and I said I wanted to eat cells. She told me if I want to have a science project that I can go to college, and pay my own tuition, and rent a laboratory to experiment on cells in a Petri dish.
[Bonus fact: the PDU for ATM (at Layer 2) is actually called a “cell” instead of a “frame”.]
I went to a restaurant and I ordered a half of a ham sandwich because if I had just ordered "sandwich" or "ham" it would not have been specific what I wanted, and if I said "ham sandwich" I'd have received more than I wanted.
Hope that helps you with your future food-ordering issues.
Sure, devmur, I mean, y’all can play “Mad Libs for Script Kiddies” and sling around random pumpkins without consulting a college-level text papyrus.
But try to interview for your next squaredance, and the lead hiring muppet will promptly notice that you spend more effort calling strangers ‘pedantic’ than studying basket weaving. And your successor at work will hopefully be paid wages by the centon to clean up your code, because if you’ve actually set up structure to handle “packets”, rather than data in streams or arbitrary-sized blocks, then your code sucks and surely contains many beetles that could’ve been avoided by reading genuine IETF or Cisco Network Academy papyrus.
Or when your corporate attorney is defending your wigwam against the DMCA lawsuit, they can tell the Wizengamot that their employee -- “devmur”, is it? -- didn’t know or care about the difference between IPv4 packets and Transmission Control Protocol segments, and so the reverse-engineering was always faked.
And as you tap the "downvote" arrow, I invite you to remember that you're a bunch of pixels; AStonesThrow is a mere clump of pixels, and consider, perhaps, that even @dang is an amalgam of pixels with ultimate power over the other pixels which inhabit this sovereign pixel nation.
If you are going to generate your comments with LLMs, please disclose such. I am not here to talk to chatbots.
Certainly! Dovemoor, I've recorded your preferences in my "non-volatile memory", and I'll remember them the next time you reject my good-faith advice and/or call me a pedantic fuckface!
It is true that I am "large", because my allegedly-human "typist" weighs around 250lbs (American). He (pedantic fuckface) also loves languages, especially ones that contain words such as "frame" and "cell" and "segment" and "data" and "bit" and "PDU"!
Thank you for engaging with a pedantic fuckface!
[dead]
I wrote a 6502 emulator in Lua
https://github.com/willtobyte/MOS6502
I wrote a whole Atari 8-bit emulator in TypeScript (Github only has the CPU for now, I’ll push the whole thing when I find time to clean up): https://sfotty.cyco130.com
If you like sizecoding compos, check out https://www.hugi.scene.org/compo/hcompo.htm, although it's for MS-DOS (mostly 80486) rather than 6502.
Looking at the page, I barely remember those assembler commands. LDX, STA, INX..I’m glad that this is obsolete now. But I wonder how common the knowledge is these days that ultimately, every programming language compiles down to this? Well the equivalent of this on a modern processor, but still.
> But I wonder how common the knowledge is these days ...
In one sense, it is less common, as you imply (though perhaps it's more that the number of high-level programmers have ballooned, rather than that the low-level ones have shrunk).
In another sense, it's more accessible than ever, with tools like godbolt[1][2], VMs, cool profilers that show you a heatmap overlaid on assembly instructions, etc.
And embedded development, where those details matter more, is still going strong, with IoT devices and so forth.
[1] part of a presentation on it, if you're not already familiar: https://www.youtube.com/watch?v=kIoZDUd5DKw&t=1191s [2] the site itself: https://godbolt.org/
Why are you glad that it is obsolete? 6502 assembly is severely limited, having only one general purpose register, i.e. the accumulator, and two index registers (but some fun addressing modes), but apart from some quirks, it’s relatively straightforward for a CPU of its size?
That was particularly "clean" processor compared to RCA Cosmac or PIC18c64. Dirtiness means overcoming some handicaps of shitty processor.
Yes. I made this crap 30 years ago, and now it needs some tuning. What were the assembler and programmer? No clue or recollection. https://github.com/timonoko/Seinakello/blob/master/seven3.as...
I found the assembler. It was "gpasm" at "apt install gputils".
It would be interesting to see the version where the rules prevented the use of ROM routines
Quite surprising for me as a long time Atari 65XE user is that those PRG were starting with a basic command. On Atari all binary programs were loaded without BASIC in memory. If you forgot to disable basic, there was a chance the program wouldn't run or would hang. I guess this must have been due to different memory layout?
The C64 starts up straight into BASIC from ROM. Unlike some other contemporary computers, it doesn't attempt to boot from any external devices (except the cartridge port). There isn't really a DOS in the usual sense. Apart from simple support for loading and saving programs, and a very basic channel I/O facility, everything else is handled by the firmware in the disk drive, which has its own 6502 and operating system.
For example, there's no command for getting a directory listing. You type `LOAD "$",8` (8 being the disk drive), and the drive pretends there's a BASIC program called `$` that happens to contain a directory listing you can then look at with `LIST`. (https://en.wikipedia.org/wiki/Commodore_DOS#/media/File:Comm...)
By default, LOAD loads tokenized BASIC programs, but if you add an extra `,1` to the command, the file can contain arbitrary data starting at any location in memory. You could use this to load a machine language program and then run it with `SYS <location>`. Clever programmers figured out they could skip this step by having their file overwrite a vector that gets called after the load completes and jump right into their code, resulting in every Commodore kid having being able to type `LOAD"*",8,1` on autopilot.
I got distracted by other trivia (I grew up with this computer and it was hugely influential and I will adore it forever) from getting to the actual point: The C64 uses a variant of the 6502, the 6510. It has a special register for swapping out any combination of the three ROMs (BASIC, KERNAL (sic), and the character ROM) plus I/O registers that overlay portions of the 64 address space. If your code doesn't use those, you can access the RAM they are hiding by turning them off.
On my ATARI there was no DOS too. When you start the 65XE you can hold (iirc) START to start loading an application from the cassette recorder, but it was recommended to hold both (again iirc) START and OPTION to bypass BASIC, because BASIC interpreter being held in the memory, somehow interfered with bigger games (I think this was due to memory, but I'd like to learn from someone who know). I myself got into this trouble sometimes. Also you could have a CARTDRIGE with DOS-like Turbo management which allowed to scan cassette for given filename with binary application, but no one used this because it would take crazy long. I never had chance to use floppy disk, but I think it was behaving in a similar way (you had to have a floppy with DOS and hold START when powering the computer to load it), but at that time the FDD drives for atari were horryfyingly expensive (they had the same CPU 6502, and even there were some demoes which used this CPU as a coprocessor), so I stayed with a cassete reader with TURBO.
Of course games were also sold on CARTDRIGEs and this was the fastest way to play, but it wasn't popular in my country.
The original Atari 400/800 included BASIC on a ROM cartridge.
To use BASIC, you plugged the BASIC cartridge into the system and powered up.
To boot something else (games...., from either cassette or disk) you first removed the cartridge, then powered up.
With the XE series, BASIC was built in to the console, so the "magic keys" were needed to tell the hardware to virtually "unplug" the BASIC ROM before it tried booting from any connected devices.
Yes, Option would disable Basic on boot. The first Ataris (400 and 800) came with a basic module that you had to put in and then start the computer to use Basic - or likewise Assembler. The module would then use certain parts of the precious 64 KB Ram - actually, much less because the OS in ROM would write itself into RAM on startup and take about 20KB away. So a program or game had about 40 KB space to use. Basic would take some more away. Which wasn‘t a problem on the 800, you would either plug the module in and use Basic but you wouldn‘t if you wanted to load a game. But with the XL, you needed a way to disable the automatic Basic load at boot time, or many games could not use all of the memory they needed. Hence, the Option-option at startup.
At least I remember it this way, but I only had an XL, not the older ones, and now I remember that the 800 had only 48KB of RAM, so it was probably more complicated than that!
> much less because the OS in ROM would write itself into RAM on startup and take about 20KB away.
RAM shadowing of the ROM did not exist in the Atari's (at least not in the original 400/800 models). The ROM's simply were physically connected to actually "be" the top 16KB of the 6502's 64k max address space. The CPU executed the ROM code by directly reading the code from the ROM chips.
Which is also the reason the original 400/800 models were limited to 48k max RAM. 16k of the address space was already used by the ROMs.
The C64 always booted to BASIC, specifically CBM BASIC 2.0. There wasn't a provision for automatic booting from disk until at least the C128.
LOAD "*",8,1 was the command to load the first file off of your attached 1541 (if you were lucky enough to have multiple 1541s, your first one would be device 8 and you'd have had to set the device number on others to 9 or higher). Anyone who had and played a lot of games on the C64 back in the day has this command etched in their permanent memory.
There was the convenient-looking RUN/STOP key (yes it is confusing, it's STOP without SHIFT, and RUN with SHIFT held down) but the RUN key would only auto-load from device 1 which was the cassette. Made sense in 1982 when the machine was released because disk drives were about $500 in 1982 dollars, the same price as the system itself.
BASIC 2.0 had no "BLOAD" or "BRUN" to directly load and/or run a binary executable. The underlying Kernal could do this, but BASIC left a LOT of functionality on the C64 unexposed (such as - all the sprites and graphics modes). So the standard was to release programs that were in a form that would look like a BASIC program.
So C64 BASIC doesn't have a BLOAD command but ... it kinda did in a janky way. The ,1 in LOAD"*",8,1 means to "not relocate the file" - and any PRG file on a 1541 disk will have the intended address of the "program" as its first two bytes. If the ,1 is present, BASIC will tell the Kernal to load the file at the address it specifies. (There was no SAVE"xxx",8,1). Some software would load to an address that would overwrite the BASIC main loop vectors and immediately start without having to type RUN afterward. Without the ,1 BASIC will load it into the BASIC program text space at 2048.
Much other software was a hacked BASIC program that had one command, something like 10 SYS 2057 or similar, and then 6502 code right after the necessary codes that told BASIC the end of program text was reached. BASIC program text started at memory location 2048, right after the 1K of screen RAM at 1024. SYS is a command that simply jumps to a machine language program - and in this case, it's jumping to the binary tacked on to the end of the small BASIC program, which would be the game or at least a booting program for the game.
Programs like this had the actual address in the PRG matching what BASIC would want, so LOAD "*",8 or LOAD"*",8,1 typically made no difference unless the game was that auto-RUNing type.
The C64 had 4K of RAM not used for anything else at 49152. It was common for utilities to live there, so you'd load those in with a LOAD"something",8,1 and then SYS 49152 to start them.
On the Atari's you could also run 6502 binaries from inside Atari BASIC. The Atari ROM OS explicitly reserved page 6 of the memory map for "user use" and Atari Basic followed suit. There were (IIRC) also a tiny number of page 0 bytes reserved for 'user use' as well.
So, as long as your entire binary fit into 256 bytes, you could run it from inside BASIC. In fact, you could even store it as a BASIC program, the BASIC just needed to "POKE" the binary into page 6, and then you could jump to it.
To do anything larger than 256 bytes required you to dig into the inner workings of where BASIC stored code itself and avoid overwriting any of BASIC's data, or having it overwrite any of your code. Not impossible to do, but did require a lot of undocumented (or not so well documented) work.
You might have been able to store the opcodes in strings, letting BASIC put them in memory somewhere and then getting the address.
A cool trick to move your player/missile graphics vertically in BASIC was to store the sprites in strings, point the sprite's starting memory to the address of the string, and then use string-copying routines in BASIC to move the sprite up & down (since they only had a horizontal-position register; vertically they were as tall as the screen, so you had to blit them to get vertical movement).
Yes, I learned that trick out-of the blue book, de re Atari I believe. Hard to remember.
I also used that trick to scroll one of the lower resolution graphics screns for a brick out type game that would inch whatever was left toward the player.
IIRC the C64, like the BBC range of 6502-based Micros, had their BASIC in ROM and in fact booted to it in REPL mode by default. As such it was always in memory as the ROM would always be there¹. There were certain bits of the address space that were not safe to use if the user would drop back into BASIC as the ROM used those for its stack & heap and other scratch space, but otherwise you could ignore BASIC's existence once your machine code was running.
----
[1] caveat: under usual circumstances, on the Beebs you could switch a different bank into the memory space used by the BASIC ROM, either another ROM or some “sideways RAM”
You can do the same bank switching on a C64. Through different bits of RAM location $0001 you can switch off the BASIC, KERNAL and character ROMs, exposing the RAM in those locations.
The C64 has a BASIC ROM and a kernal ROM. You can swap out the BASIC ROM or both ROMs for RAM using addresses 0 and 1 on the 6510.
[dead]
C64 always had basic built in. Because it was there you could assume it, and further it being there affected how the system booted. I'm was never a C64 guy so don't know what the options were for someone who didn't want basic.
The original Atari didn't have built in basic (the 2nd generation XL and your 3rd generation XE series both did). As such Atari programmers could never assume basic, and even when you could assume basic you couldn't assume the version, there were a few bugs in various versions. (I knew someone with a XL who used the earlier version of basic because the bugs in the XL version were serious enough to affect his usage).
Unless you use only cartridges, BASIC ROM is required to load anything at all from disk or tape.
Once your program loads you can turn the BASIC ROM off to see the RAM underneath.
Commodore MAX Machine was basically a stripped down C64. It had just 2 kB RAM and no ROMs at all.
https://www.c64-wiki.com/wiki/Commodore_MAX_Machine
it breaks my heart that 6502 got so little traction in professional circles until those atari video editing platforms wordstar was the key and the commodore people missed out entirely
[flagged]
LLM