C64 Coding Intros Demos
C64 Coding Intros Demos
On The Commodore 64
An Exciting & Educational Journey Into Coding
Commodore 64 6510 Machine Language
FutureVision
Publishin
gWelcome to the rst retro coding
"Converse" from sid.oth4.com by Thomas Mogensen (DRAX). Released: 1989. Genre: Chip.
Why Did Puterman Create
This C64 Coding Doc
?
There were several things that got me started writing this document. First of all, I didn't know
of any good tutorial about demo programming on the C 64. There's Coders World, of course,
but it may not be thorough enough with the initial details. After all, the hardest problem is to
get started at all.
Another reason was that people sometimes ask me things about coding, so in a way this is
also some kind of an FAQ. Not that I've been asked about all these things, of course, I've filled
in quite a lot of gaps.
The most important reason, though, is that I want people to learn to code demos on the C 64,
and if the availability of a document like this can make someone start coding, that'd make me
very happy. The C 64 scene is slowly fading into oblivion, with fewer and fewer releases, and I
think what's missing the most is a new generation of coders who want to astonish people with
amazing effects. And if you want to do that, you have to start somewhere, and that
somewhere is, in my opinion, not with 8 8 plasmas, but with the kinds of effects that I go
through in this tutorial.
I'm not claiming to be a good coder. Not even an average one. But I know some of the basics,
and I'm trying to share that knowledge here.
Why Demos
?
It's pretty obvious why you'd want to program demos; because it's fun. You get all the
usual advantages of doing programming, that you're learning about programming and
that it's fun. You also get the added advantage that the resulting programs are cool and
nice to look at (if you're good at it). And of course, demos is more fun than most other
things you can program.
Another good thing about programming demos is that you'll learn about many different
aspects of the computer, at a very low level. To get good performance (which is very
important in demos), you need to write efficient code, and the only way to do that is to
bang directly on the hardware. You don't use any kind of libraries or abstractions when
you program demos, you do it all the hard way. So you need to understand how you
make graphics appear on the screen, music to be heard from the speakers and how to
load stuff from disk.
You also need to use interrupts, which is something you really need to know about if
you're ever going to write an operating system. It is also one of the things that is
considered to be difficult to understand. Don't let that scare you, though, it's a pretty
easy principle to understand, and as soon as you've gotten it to work once, you can
probably do it much more easily the next time.
All in all, in coding demos you learn how a computer works at a very fundamental level,
and understanding that makes lots of other things in programming easier. I'll just take
one example: novice C programmers often have lots of problems with pointers. Well, if
you've written some machine code programs you know what pointers are and that
they're not dangerous1.
Why C64
?
The second question I posed above was why you'd want to program your demos on a
C 64. There are numerous very good reasons why you should use a C 64, some of
which are applicable to some other hardware platforms as well, and some which aren't.
I'll list some of my favourite reasons here.
The CPU
The CPU in the C 64 is a 6510, which is a variant of the 6502. It's a very nice processor
to program. It has a simple instruction set, so it's easy to get started. It has been
studied a lot and there's lots of documentation available. It uses memory mapped I/O,
which means that performing I/O (like showing stuff on the screen) is no different than
putting a value at some arbitrary memory location.
Of course, the 6502 only has three registers (not counting the PC, SP and Status
register), which can make it a pain in the ass to implement complicated algorithms on,
but on the other hand, it sure makes you appreciate a modern RISC processor with
dozens of general-purpose registers.
The VIC
The VIC (the graphics chip) is very nice. The VIC has a lot of interesting
bugs (or features, depending on how you look at it), which means you
can create amazing effects that are unique to the C 64. It's all about
learning about the hardware and learning how to use it to fit your needs,
not just blindly following a specification document.
That the C 64 is old and slow might not sound like much of an advantage, but when it comes
to demo programming, it is. Why? It means that it's difficult to do stuff that requires lots of
computations. You can't just throw CPU cycles at it, and write inefficient code. You have to
think, to make it efficient. And doing really difficult things (or rather, impossible things) is what
demo programming is all about. A good programmer can write a program that does something
that seems very hard to do.
A good demo programmer can write code that does something that is completely
impossible.That's why it's meaningless to start writing demos on a modern computer: it's too
easy to make stuff that looks impressive, it's too easy to fool people into thinking that you've
done something impressive, so you really don't have the right sort of motivation to actually
write good code. Instead you're pushed in another direction, towards writing large programs,
which will require that you use abstraction, which probably means that you'll use some high
level language, and then you're not even close to programming demos.
High level languages are nice, they make it easy to create utility programs, and make them
secure and robust. But if you're writing a program that displays graphics effects, that are
written in a high level language, don't try to fool anyone that you're writing a demo. A demo is
never written in a high level language. 2
Why am I making such a strong point about this? Because a demo isn't a program, it's
something else. In what way does a demo differ from a program? A demo has to take over the
computer and bang directly on the hardware, it does not run under an operating system. This
also means that it will have to take care of the things that the operating system would take care
of, if you were writing a normal program, like interrupt handling and I/O.
I'd suggest you do the following to learn assembler: get a tutorial, and try to grasp the
general structure of it, learn some of the more important instructions, and then get a
good reference, like ``Programmer's Reference Guide''. You shouldn't read the whole
book, as most of it explains how to program the C 64 in BASIC. But the summary of the
opcodes is nice, so that's a good reason to keep the book.
There's a pretty nice assembler tutorial in the first couple of issues of Commodore
Hacking.
When you've learned some assembler, you need to know which memory addresses to
poke values into to make interesting things happen. As the C 64 uses memory mapped
I/O, you perform I/O operations just by putting values into memory locations, or reading
from memory locations. What you need is a memory map, that tells you which
addresses are special, and which ones are just RAM. ``Mapping the C 64'' is a nice and
detailed memory map.
If you think you're really smart, you shouldn't even need a tutorial on assembler, all you
need is a reference document and some examples. So let's look at some really simple
examples.
Making The
Borders Flashy
A very simple effect, that shows how you can achieve some things on the C 64, is to
make the border flash in different colours. Here's the code to do it4:
* = $1000
That was a short program, wasn't it? If you type in and run this program5, you will see
the border flashing wildly. If you're using an assembler like Turbo Assembler or
AssBlaster, you should just have to tap the RESTORE key to get back to the assembler.
Let's explain exactly what the program does. On the first line, we simply tell the
assembler that the machine code it creates should start at memory address $1000
1000 hexadecimal, which is the same as 4096 in the decimal number system). This is
Turbo Assembler syntax. If you're using some other assembler, consult the
documentation.
The second line has a label, loop, which is just a way to name that memory location, ie.
the one where the instruction inc $d020 starts. As we have told the assembler to
assemble the code to address $1000, we know that what the label loop represents is
actually $1000.
After the label comes an instruction, INC $D020, which tells means "increment whatever
value is at the address $D020 in place". This is the same thing as loading the value from
$ D020 (using the instruction LDA $D020), adding 1 to it (ADC #$01) and then storing it in
the same address (STA $D020). Why do we do this? Because the C 64 has memory
mapped I/O, and the address $D020 actually represents the border colour. So by putting
different values in $D020, we change the colour of the border. So if it was initially black
(value 0 , it will be white (value 1 after executing the instruction INC $D020.
Then we come to the last line, which says jmp loop. When the program flow reaches
this line, it jumps to the adress corresponding to the label loop and keeps executing
instructions there. In our case, it will jump back to the previous line and execute inc
$d020 again. Then it will again reach the jmp loop line, go back, increment the border
colour etc., forever. Or rather, until we press RESTORE, which will take us back to the
assembler, or if we reset the computer or whatever.
So, now you know how to flash the border. If you use some other address than $d020,
you can change other things. Some addresses will just give weird results, others will
give sane results. If you use $d021 instead of $d020, the main screen will flash instead.
* = $1000
sta $0500,x
sta $0600,x
sta $0700,x
We start by setting the border and background colours to black The value 0
.
means black and as you probably remember from the last example d020 and
, , , $
$ d021 are the addresses that control the colour of the border and the main
screen .
Now we want to remove all the characters from screen memory Screen memory
.
Note how cleverly we handle the loop index in the X register We start by setting
, .
it to 0 Then we decrement for each iteration and then compare it so 0 The first
. .
time we decrement it it will wrap around to ff and then it will go all the way down
, $ ,
to 0 again .
If there's anything about this test program that you don't understand, look up the
instructions and the various addressing modes in your 6502 assembler reference.
Note that this program won't behave very well if you just type it in and run it, because it
doesn't really end.
After the loop has finished, it will just happily get whatever is at the address after the
loop and try to execute it as an instruction. That will probably not work very well, and
something weird will happen. You will have to figure out yourself how to make it behave.
One idea is to end this program by appending the border flashing code from the
previous example.
Tools
On the other hand, if you program in a monitor, you know exactly where in memory your
code is and you know where the page borders are, something which is really important
when it comes to writing code that needs perfect timing.
Before we jump straight to demo programming, I need to introduce some tools. The
necessary tools are a monitor and/or an assembler. You can choose to do your
programming either in a monitor or an assembler. Which choice is the best is up to you.
People have different opinions, but these days most people would probably say that an
assembler is the best choice, because it makes programming more easy, as you can move
stuff around, insert code into already existing code, add comments and use labels.
Anyway, I'll try to describe how you can do some stuff with a monitor and with an assembler.
All the example code in this text is in Turbo Assembler format, so maybe it's easiest for you
to use Turbo Assembler to start with. The reason why I use Turbo Assembler format is that
most people in the scene use Turbo Assembler, and I use it myself.
Using a Monitor
The monitor I'll describe here is a pretty standardized one, and the commands
described should work on most monitors, like the ones in the Action Replay and Final
Cartridge cartridges. There are some exceptions, like S Mon, and if that's the only
monitor you have, you'll have to find out how it works on your own.
To write new code, you type in a line like
What this does is that it assembles the instruction lda #$00 and puts the resulting
machine code at the address $1000. You can now simply type the next line of code, as
the monitor itself should now give you a line that looks like this:
.a 1002
That is, the monitor itself calculates where you want to put the next instruction, so if
you want to type in a whole program, you only have to issue the a command once
yourself.
To start a program, you simply jump directly it, using the g command, eg.:
.g 1000
This will jump directly to the address $1000. To look at the code in memory, eg. the
code you've already written, use the d command, like this:
.d 1000
This will disassemble the code in memory, starting at $1000. Different monitors will
handle this differently, but most monitors should let you scroll through the code, using
the cursor keys.
There are lots of more monitor commands, but this isn't a manual for machine code
monitors, so I'll leave the rest to you.
Using an Assembler
Learning to use an assembler may be a bit more difficult than learning to use a monitor,
but most people would probably think that it's easier to use an assembler than a
monitor. When you've loaded and started Turbo Assembler (sys $9000 , you end up in
the editor, in which you write code. The syntax is just like the exemples in this text.
Most commands in Turbo Assembler are invoked by pressing , followed by some other
key. To assemble a program, use - 3. This will assemble the program, and if you press s
just after the assembly, the program is started automatically. When you're in the
program, you can get back to Turbo Assembler by pressing RESTORE7. If that doesn't
work, you can reset and type sys $9000, which should bring you back, unless you've
managed to overwrite the memory of Turbo Assembler.
- 1 - exit to basic
The best cross assemblers available for the c64 are essential for efficient programming
and optimizing code development. Utilizing these powerful tools can greatly enhance
the speed and accuracy of coding, resulting in smoother operations and improved
performance on the c64.
Below is a comprehensive list of some of the top cross assemblers that can be utilized
for coding on the c64 platform. These tools are highly recommended for efficient and
effective programming, providing a seamless experience for developers looking to
enhance their skills and create optimized code.
ACME Cross Assembler: A versatile cross assembler that supports several 8-bit
platforms including the C64, providing efficient and reliable assembly for a variety of
retro computing systems.
Kick Assembler is widely recognized as one of the top choices for C64 development
due to its robust array of features and remarkable adaptability, making it a standout tool
in the retro gaming community.
DASM, known as one of the most widely used cross assemblers in the programming
community, is favored by developers for crafting software across a multitude of
platforms, including the renowned C64 computer system that has stood the test of
time.
systems such as the iconic Commodore 64 computer that played a pivotal role in
,
You may choose to run your code in an emulator such as VICE rather than on an actual
, ,
that the emulator may not fully replicate the experience of the real hardware It is
.
By using an IDE, you can streamline your development process and ensure a more
efficient workflow. Additionally, IDEs provide a centralized platform for managing various
aspects of your project, such as version control, debugging tools, and integration with
third-party libraries.
CBM Prg Studio is a highly recommended IDE for C64 development on Windows. It is
praised for its active development, extensive feature set, and user-friendly interface.
Many developers consider it one of the best IDEs for C64 programming on Windows
due to its comprehensive toolset and regular updates.
CBM Studio is a cross-development assembler IDE for Windows that offers a range of
features tailored for C64 development. It supports debugging, sprite editing, character
map editing, and more, making it a robust choice for C64 enthusiasts and developers
on the Windows platform.
The sound in most demos is music, and playing music produced with some music
editor, like DMC or JCH's editor, is very easy. You don't really need to make the music
yourself either, you can always use someone else's music, as long as you give credit to
the person who did the music. I'll show you what to do to play a tune in an example
below, but first there are some basic concepts we need to cover, like synchronizing
things with the screen refresh.
As playing music is so easy (unless you're going to do something really fancy), we'll
concentrate on coding graphics effects, because that's really everything you need in a
demo.
Of course, if you make a multi-part demo that can't be squeezed into memory, you'll
need to load parts from disk. You don't have to write a loader yourself, though, as there
are some very good loaders around already.
$D012
Cryptic header, right? $d012 might be the most important address of them all, when it
comes to demo programming on the C 64. $d012 has two different functions:
When written it is used to set the number of the line where the next raster interrupt will
,
occur
We ll get back to raster interrupts later You need to know about d012 to understand
'
.
. $
them, so pay attention to the stuff in this section! The first item above is interesting, but
it may not be obvious why it is interesting.
The current raster line is the line that is currently being redrawn on your screen. The
whole screen is redrawn 50 times per second8. Each time it is redrawn from top to
bottom, from the left to the right. So, if you want something to happen 50 times per
second, all you have to do is to check the current value of $d012, and when it reaches a
certain value, call the routine that performs the desired task. When finished, go back to
checking $d012.
Now, there are 318 raster lines on a PAL machine, and one register can only store
values between 0 and 255, so you need another bit to represent all 318 lines. That bit is
bit 7 of $d011. So, bit 7 of $d011 is really bit 8 of $d012. Does that sound confusing? In
that case, read this paragraph a couple of more times.
you'll never get a value greater than $3f bne mainloop ; if not, keep checking
if bit 7 of $d011 is set. I'll show how you inc $d020 ; inc border colour
can use $d012 with an example: jsr $1003 ; jump to music play routine
you just need to rip a tune, or get it some other way. The code before the mainloop
just initializes the tune, ie. sets all registers to 0, and then jumps to the initialization
routine. You don't have to know what the music routine does, but what it actually does
is that it resets the registers of the SID chip.
After the initialization we move directly into the main loop. What the main loop does is
that it loads the value from $d012, compares it to $80 128 decimal, somewhere in the
middle of the screen), and if it's not $80, it jumps back to where it began, ie. to loading
the value from $d012.
Now, as soon as the raster beam reaches line $80, the inner loop is exited, and we end
up at the line that says inc $d020. What we do is that we increment the border colour,
jump to the music play routine, which executes and returns, and then we decrement
the border colour and jump back to the main loop. Why do we change the border
colour? Because it's a way to visualize how much time the music player routine takes.
You'll actually not only see how much time it takes (in raster lines), but also where on
the screen you're playing it, ie. where the raster beam is when you're in the music
player routine.
We will later show that this music player routine is in no way perfect, but it's a good
illustration of some concepts, and it works pretty well. You should now be able to figure
out for yourself how to do raster bars. The trick is that you wait for a certain raster line,
then change the background colour (if you're on the normal screen, you have to
change both $d020 and $d021, if you're in the upper or lower border, you only have to
change $d020 . You need pretty good timing to do that, but with a hardcoded delay
between the colour changes, it should work well with code similar to the above
example.
Graphics
Now it's time to move on to some more interesting stuff, making things happen on the
screen. Of course, things have been happening with the screen in all the above
examples, but not in a very controlled way. Let's explore new techniques and tools to
enhance our screen interactions and create more engaging visual experiences for our
users.
As we delve deeper into the realm of screen interactions, we can uncover innovative
methods to captivate our audience and elevate the user experience to new heights. By
experimenting with cutting-edge technologies and pushing the boundaries of creativity,
we can unlock endless possibilities for creating captivating visual experiences that leave
a lasting impression on our users.
GraFX2 is a versatile bitmap editor specifically designed to cater to the C64's color
limitations, making it the perfect tool for creating and editing graphics for the system. It
is compatible with Windows, Linux, and macOS, providing users with a seamless
experience across different operating systems.
CharPad is a user-friendly charpad editor that offers both simplicity and versatility for
creating and editing character-based graphics specifically designed for the C64.
Compatible with multiple operating systems such as Windows, Linux, and macOS, this
powerful tool provides a seamless experience for all users.
Pixcen is a powerful Windows graphics editor specifically created for C64 enthusiasts.
Despite being released in an unfinished state, it still offers valuable tools and features
for creating stunning visuals. Make sure to explore the help section to get acquainted
with its capabilities and unleash your creativity.
mcDRAW - Online Pixel Editor for C64 Multicolor Bitmap Mode is a fantastic tool that
provides users with a wide range of features to enhance their editing experience. With
its Text Tool, charset fonts, and numerous fixes, users can enjoy a more efficient and
enjoyable editing process. Whether you're a beginner or a seasoned professional,
mcDRAW has everything you need to create stunning pixel art in Multicolor Bitmap
Mode on the C64.
The C64 Graphics Maker is a user-friendly graphics editor specifically developed for
Windows to provide support in the process of creating games for the Commodore 64.
With a wide range of features and tools, this software aims to streamline the graphic
design process and enhance the overall gaming experience.
PETSCII Editor is a fantastic online tool designed specifically for creating custom
Commodore 64 screens. With its unique capability to import sprites from raw byte
streams and other sprite sets, this versatile editor opens up endless possibilities for
unleashing your creativity in C64 graphics design.
ALBERT is a versatile multi-platform pixel art editor specifically designed for producing
intricate and detailed images on the Commodore 64. This powerful tool boasts a wide
range of features such as layer support, customizable color palettes, and the ability to
preview animations before finalizing your masterpiece.
PicCon is a flexible tool that works on different platforms and allows users to easily
change images into various C64 graphic formats like Koala, Hires, and FLI. It not only
enables batch conversion but also provides advanced settings for improving color
usage and dithering. This makes an essential tool for both digital artists and retro fans.
Project One is an extensive suite featuring an intuitive pixel editor and a flexible
converter specifically crafted to accommodate a wide range of C64 graphic modes. This
cutting-edge software package is poised to transform the landscape of graphic design
on the beloved Commodore 64 platform, offering unrivaled capabilities for creating and
manipulating stunning visuals.
Sprites
Sprite
Basics
Sprites can be used for lots of cool things. What's nice about them is that they can be
moved around on the screen, without affecting the background. As you probably know
already, the C 64 has 8 hardware sprites, so you can have 8 things moving around
simultaneously, or synchronize their movement to make bigger objects move around
the screen.
You probably know that there are ways to get more than 8 sprites on the screen, but
we'll go through the basics before we reveal that trick. The basics of sprites consist of
the following:
displaying them ,
There are a number of things you need to do in order to make a sprite appear on the
screen. You need to point it at a chunk of data, that defines what it should look like.
Then you need to set the x and y coordinates. Of course, you probably also want to set
the colour of the sprite.
And, last but not least, you need to turn the sprite on. This is all the stuff that is listed
above, and this is everything you need to be able to do to do some basic sprite effects,
like moving them around on the screen, animating them, etc.
Sprite Pointers
The sprite pointers, ie. the adresses that contain the pointers to where the graphics
data that is displayed on the screen as sprites, are located after the end of the screen
memory, which is usually located at $0400. The screen memory takes up exactly 1000
bytes 40 times 25 characters), so the last 24 bytes of the memory from $0400 to
$ 0800 are free . The last 8 ones of these are the sprite pointers , and the 16 bytes
before the sprite pointers aren't used at all, unless I'm completely mistaken.
So, the byte at $07f8 is the sprite pointer for the first sprite. Now, how do we fit a
pointer into one byte? To represent an address in memory, we need two bytes. But
sprite pointers are handled in a special way. First of all, you only point to sprite data that
is located in the same VIC bank as the one where you keep the screen memory. There
are four VIC banks, $0000 $3fff is the first one, the one that's used by default. A sprite
takes up 63 bytes of data, but have to be aligned to 64 bytes, so you can put sprite
data starting at adresses $0000, $0040, $0080, $00c0, $0100 etc.
So, how many sprites can you fit into one VIC bank? 256. And how many numbers can a
byte represent? 256. Aha! Now we can understand how the sprite pointers work: if you
set a sprite pointer to 0, it will point to the address $0000, in the current VIC bank. If you
set it to 1, it will point to $0040. If you set it to $80, it will point to $2000, and if you set it
to $c0, it will point to $3000.
Easy, isn't it? So, let's say you want to do a simple animation, consisting of 8 sprites,
with the sprite data placed at $2000 (up to $21ff). You start by putting the value $80
into $07f8, then change it to $81, then $82, and so on up to $87, then you'd start over
from $80.
Important Addresses
Now we move on to how you set coordinates and colours and turn on sprites. Turning
the sprites on is simple. The sprites are numbered from 0 up to 7. The sprite whose
pointer you set when you poke values into $07f8 is 0, the one at $07f9 is 1, and so on.
You turn on the sprites by setting the corresponding bits in $d015. So, to turn on sprite
number 0, you poke the value 1 into $d015. To turn on sprites 0 and 1, put 3 in $d015.
Setting the coordinates of the sprites are equally simple, with one small catch. The x
coordinate registers are $d000 (sprite 0 , $d002 (sprite 1 and so on, and the y
coordinate registers are $d001, $d003 etc. As these registers can only store one byte
each, you can only set coordinates between 0 and 255. But the visible portion of the
screen is 320 pixels wide! The solution is that there's an 8th bit for each x register in
$ d010. So, if bit 0 in $ d010 is set, sprite 0's x coordinate is 256, plus the value in $ d000.
single colour sprites, you just poke the colour sta $d027 ; Make it white
lda #$80
; set y coordinate to 40
you can do with sprites... sta $07f8 ; set pointer: sprite data at $2000
mainloop
Sprite Example lda $d012
; moving up
dex ; decrement it
stx $d001
to understand it.
jmp mainloop
down
If you type in and run the example ldx coord ; this should be familiar
stx coord
sta dir
raster line $ff, which means we'll miss it, .byte 0 ; direction: 0 = down-right, 1 = up-left
A good exercise, to get your hands dirty with some more interesting sprite programming, would
be to display several sprites at once, and make them move according to a sine table. With the
help of your friend $d012, you should also be able to make a multiplexer, if you're really
ambitious. You've got all the tools, now all you have to do is to think it up and express it in code.
Cross Platform Sprite Editors
Spritemate is a fantastic free online sprite editor that can be easily accessed through
your browser. This amazing tool offers a user-friendly interface that allows you to
effortlessly design and animate sprites specifically for the C64, making it a must-have
for anyone looking to create stunning visuals for their projects.
SpritePad is highly favored by C64 developers for its user-friendly interface and robust
features. This powerful graphics data editing tool streamlines the creation of high-
quality graphics that are fully compatible with the C64 system.
Spred64 is a highly impressive sprite editor specifically designed with the C64 user in
mind, providing a wide array of advanced features like real-time animation frame
previews and a user-friendly compositor interface for easily selecting sprites.
ALBERT is a versatile pixel art editor that is compatible with multiple platforms and
specifically designed for producing detailed images for the Commodore 64. It comes
equipped with advanced features such as layer support, customizable color palettes,
and the ability to preview animations, making it an essential tool for digital artists and
retro gaming enthusiasts alike.
HermIRES is a fantastic cross-platform hires bitmap editor specifically designed for the
C64, allowing users to effortlessly create and edit sprites with ease. This impressive
tool boasts a wide range of features, including support for multicolor sprites, character
modes, and extended background colors.
C64 Sprite Creator is an amazing iOS application designed specifically for creating high-
resolution and multicolor sprites for the C64 computer. With its user-friendly interface,
this app offers a wide range of tools and color palettes to help users design intricate
pixel art sprites with ease. Whether you are a beginner or a seasoned pixel artist, this
app provides all the necessary features to bring your creative vision to life.
Character Graphics
Sprites isn't the only way to display graphics. Our next topic is character graphics. You
might have tried to draw something using the built-in character set. That's not very
easy, and the results usually aren't all that good.
Of course, you don't have to use the built-in character set. Using a character set editor,
you can draw your own character set, and more effects than you can imagine are
implemented using character graphics. They don't even have to look like characters, if
the trick is (as it often is) to update the character set in realtime.
Before we get into those kinds of tricks, we'll do what we usually do and go through the
basics first.
The screen codes aren't the same as the PETSCII codes you use for normal text, so if
you want to prepare text that should be put on the screen, make sure you save it as
screen codes. Most demo related text editors and such already do that, so there's
nothing to worry about.
Now, putting characters on the screen is cool, but it gets even cooler if you can give
each character its own colour. You can do this by poking the colour values into colour
RAM, which is always located at $d800 (you can't move it).
So, let's say you want the letter A to appear in the upper left corner of the screen, and
you want it to be yellow. What do you do? You poke the screen code for A into screen
memory, ie. put the value 1 into memory position $0400, and put the value for yellow,
which is 7, in $d800.
Changing Character Set
The built-in character set isn't so hot, so if you're going to display text, you should
usually load your own character set. Fortunately, this is very easy, and you can control
the locations of both the character set and the screen memory with one VIC register:
$ d018. You put the upper parts of two addresses into this register: the four most
significant bits of the 14 bit9 address of the screen memory in the four high bits, and the
four most significant bits of the 14 bit address of the character set in the lower four bits.
Confused? Let's take an example...
Screen memory is $0400 bytes long, and it has to start on an address that is a multiple
of $0400, so it can start at $0000, $0400, $0800, $0c00 etc. As I said, it's located at
$ 0400 by default. A character set is $ 0800 bytes long, and has to start on an address
that is a multiple of $0800, so it can be located at $0000, $0800, $1000, $1800 etc.
Now, let's say we want screen memory to be where it usually is, at $0400, and we have
a character set at $2000.
values for the character set, but put it in the lower four bits of $d018.
A classical example of an effect that you can do by poking data into a character set is a
DYCP Different Y Character Positions). A DYCP is a scroll text where the letters move
up and down, independent of each other. You can figure out how to do it yourself, or
read the article about it in Commodore Hacking.
An easier exercise than writing a DYCP would * = $0801
use this to scroll text without using $d016, by sta $d020 ; border background colour
ROLing the char data through character sta $d021 ; screen background colour
Here's a simple example program, that doesn't clrscreen ; set all char codes to 0
really do much, except illustrate what I've just sta $0400,x ; on the screen
sta $0600,x
I'm using $d012, as always. sta $2000,x ; and set charset data to 0
dex
bne clrscreen
sta $d018
; screen at $0400, chars at $2000
RAM are of course different for every character, cmp #$ ; on raster line $ ?
see what's going on. lda $2000,x ; get byte nr x from chardata
eor #$ ; invert it
The reason why we're poking stuff into $2000 sta $2000,x ; store it back
However, if the picture you want to display is ``simple'' enough, ie. if large parts of it are
empty, or if it's highly repetitive, so that it could be drawn with a single customized
character set, you can of course just use a charset to display it, and you'll save yourself
$ 1800 bytes of memory. There are tools to convert a bitmap to a character set + a
screen memory, which of course requires that the information contained in the bitmap
will fit into a charset.
If you've understood how character graphics work, you shouldn't have any problems
understanding how to display bitmap graphics. I'll describe how you can display hires
graphics and multicolour graphics in the Koala Paint format.
Before we go into the theory of how you display a bitmap, I'll give you an example, and
then I'll explain what it does. The example requires that you have a Koala picture loaded
at $2000. Koala pictures are usually loaded to $6000, so go into your monitor and type
l ``filename'',08,2000. That will load your picture to $2000.
* = $0801
lda #$00
sta $d020
tax
copyloop:
sta $0400,x
lda $4040,x
sta $0500,x
lda $4140,x
sta $0600,x
lda $4240,x
sta $0700,x
sta $d800,x
lda $4428,x
sta $d800,x
lda $4528,x
sta $d800,x
lda $4628,x
sta $d800,x
dex
bne copyloop
sta $d011
stx $d016
sty $d018
mainloop:
As I still haven't explained everything about bitmap mode, this might not be all that clear,
but it's still a very small example program and it'll display a Koala picture just fine.
We start by making the border and background black. This isn't actually accurate, as the
background colour is stored in the Koala format, so we really should have loaded the
value from $4711 and put it in $d021, but that's not really important.
Next we start copying stuff. Why do we do that. Well, we'll keep using $0400 as screen
RAM, so we'll have to copy the screen RAM, which, in the Koala format, is located at
$ 3f40, to $ 0400. That's easy, you 've seen that one before . The same goes for colour
When we have all the data in the right places, all we need to do is to tell the VIC chip
what mode to go into, and where it should read data. We tell it to go into bitmap mode
by setting $d011 to $3b, and by setting $d016 to $18 we turn on multi-colour mode. And
then we tell it to read screen RAM at $0400 and the bitmap at $2000, by setting $d018
to $18.
The last line just loops forever, so that you get a chance to watch the picture. Hopefully
you've found a nice one.
If you don't know where to find a Koala picture, get a program like Amica Paint, Koala Paint
or Color-X16, and draw your own pictures. You can of course also rip pictures from other
people's productions, but please, don't use ripped graphics in your demos, that's lame.
The Screen Layout
The layout of the actual bitmap is a bit weird, especially if you're used to other
architectures, which have nice, linear bitmaps 10. A C 64 bitmap isn't linearly adressable,
ie. you can't just count the pixels from left to right and index into it in an easy way.
The data in a C 64 bitmap are indexed very much like a normal charset. The first byte
(in the above example $ 2000 is the top, leftmost byte . $ 2001 is the byte below that
one, $2002 below that one, and so on, until $2008, which is the one to the right of
$ 2000. So, basically, it's as if you 'd read one character from a charset, and put that
character in the top left corner of the screen, and then you read the next character and
put next to that one, and so on, until you reach character 40, which is below character
0. It's not really hard to understand, but it does make it a bit difficult to implement
efficient bitmap effects, like plotters. Think about it!
Displaying Bitmaps
Displaying a single-colour bitmap is just like displaying a multi-colour bitmap, except that
you don't use colour-RAM. Why? Because all you need is a background colour and a
foreground colour, and you can use the good old screen RAM for that.
For each byte in the screen RAM, you set the upper nybble to one colour value, and the
lower nybble to another value (or the same value, but then you won't see anything of
the bitmap).
The last paragraph might sound a bit cryptic, but just try it out. Get yourself a nice hires
bitmap (use some utility to create one, it should output a file that is 33 blocks long).
Load that bitmap to some $2000 aligned address (like $2000 , set $d011 to $3b, $d016
to $08 (single colour mode) and $d018 to $18. Then you can start poking values into
$ 0400 etc., to see what happens .
All the example programs above have suffered from one great problem: they have been
badly timed, and all movement (as well as the playback of the music) has been jerky and
inexact. We need to do something about that. You can't have a scroll text that doesn't
move smoothly, or jittering raster bars, because that's the definition of lameness.
Wizardry isn't about knowing most of what there is to know, it's about being able to
setup interrupt handlers after 20 beers (trust me, that's not easy .
So, how do we do something about it? Well, we need to know a bit about interrupts. Of
course, as a demo coder, you really need to know everything about interrupts, but
we're not going to be that complete here. We're going to be complete enough so that
you can easily learn the rest by reading your reference material and poking around in
your computer yourself, though.
Why Interrupts
I suppose we'll have to answer this question, although it might seem stupid. There
really isn't anything that keeps you from writing demos that don't use interrupts. If you
just know how to turn of the CIA interrupts, you're safe from all the jittering and
flickering we've experienced so far.
But there are more things you can do with the help of interrupts, and you really need to
know about them in order to have control over your computer. And demos are all about
control. You'll also need to know about interrupts to be able to use an IRQ-loader, and if
you're planning to ever write a demo that's bigger than what will fit in your computer's
memory, you'll need to use a loader. And there's no excuse for not using an IRQ-loader
these days.
In this text, we'll concentrate on raster interrupts, because that's what you'll use most
often in demos. We'll also go into NMIs a bit, because it's very useful to know about
them. And of course, if you've written a demo that looks great and that people love, it
can feel pretty embarrasing if you can kill it just by pressing RUN/STOP RESTORE...
What Is An Interrupt ?
A fair question to ask at this stage is what an interrupt is. They're a very simple, and
very efficient way of handling some things. They work pretty much like an alarm clock.
Let's say you're going to bed after a long night of demo coding, and you have to get up
at eight in the morning, to go to school or work.
What do you do? You set your alarm clock to ring at eight, and then you can safely go to
sleep, without having to worry, knowing that the clock will wake you up at eight. Until
then, you can sleep all you want.
That's exactly how interrupts work: you set up an interrupt to wake up the CPU at some
time and tell it to do something special, but until then the CPU can do its normal things.
So, what you do when you set up an interrupt is to define when the interrupt should
happen and what should happen when the interrupt is triggered.
On the C 64, you have some different types of interrupts to watch out for. You have
two CIAs, which can both generate timer interrupts (tell the CIA to give you an interrupt
after X clock cycles), you have the VIC, which can generate raster interrupts (generate
an interrupt when we reach a certain raster line), sprite collision interrupts (generate an
interrupt when two sprites collide) etc.
How To Implement
Interrupts Correctly
?
Yeah, so how do you set up a raster interrupt? It's actually very easy, so I'll just give you
some example code, and then explain it.
Now, if you're not used to using interrupts, that might look a bit weird. It works, though,
and I'm now going to tell you how. Well, I'll try, anyway.
We start by turning off all interrupts, with an SEI instruction. The reason why we do this
is because if we get an interrupt in the middle of setting up interrupts, things can get
messed up and the program can crash. These things happen. Ever had a demo crash
unpredictably?
Sometimes it works, sometimes it doesn't? The interrupt setup might be screwed up.
Or there can be some other reason. Read the code and see if you can find it.
So, anyway, after the SEI, the action begins. We start by turning off all CIA interrupts.
We do this by poking $7f into $dc0d and $dd0d. To find out what the value $7f means,
read some reference. At a later stage, you might be interested in finding out what the
individual bits of those registers do. We then turn on raster interrupts, by setting the
lowest bit of $d01a.
The next thing we do is to setup $d011, $d016 and $d018. You should recognize those
by now. We always have to initialize them, and I usually do it at the same time as the
interrupt setup. The only bit that's relevant in this context (interrupts) is bit 7 of $d011,
which is the 8th bit of $d012 (as we have more than 256 raster lines, but I've already
talked about that above).
So, let's move on to the next chunk of instructions, which includes $d012. We set a new
address in the interrupt vector, $0314. This address simply specifies where the
processor should keep executing code when an interrupt occurs. We point it to our
interrupt routine, int.
In the interrupt handler code, we don't do much. First we flash the border, by INC-inc
$ d020 (and of course , this happens once every frame ), then we ACK the interrupt (set
bit 0 of $d019, which I usually do with ASL $d019, for some reason (probably because
that's how it was done in the example that I learnt about interrupts from). If we forget to
do this, the interrupt will be triggered again, right after we return from this interrupt
code. So we have to tell the VIC that we've handled this interrupt, so that it is cleared.
* = $1000
lda #$7f
ldx #$01
lda #$1b
ldx #$08
ldy #$14
stx $0315
sty $d012
cli
loop:
int:
pla
tay
pla
tax
pla
Quite often you won't see exactly this code, but instead of the last six lines you'll see a
JMP to $ea31 or $ea81. $ea31 is the default interrupt handler, which does this and that
that you'll want if you're in BASIC, but you won't need that crap when you're coding
demos, so skip it. $ea81 just contains the same code as the last six lines in our program,
so exactly the same thing happens, except that we waste three clock cycles (for the
JMP) and that we save 3 bytes of memory.
So it's a trade-off, kind of, but it's not often 3 clock-cycles or 3 bytes will bother you
very much, so who cares?
Of course you can't jump to ROM routines if you've switched out kernal ROM, so it's a
good idea to use the code above anyway.
There's a modification you can do to the code above, which might be nice to try, and
give you some further insight into how interrupts work. Instead of JMPing around in the
infinite loop (JMP loop), do RTS. And add JMP $ea31 instead of the last 6 lines. If you
start the program from BASIC, you'll see that your interrupt routine starts executing, but
you're still at the BASIC prompt, and can type in BASIC commands.
Cool, huh?
In the rest of the text, I will be a bit more restrictive with explaining details. If you've
come this far and understand most of it, and have tried typing in the programs and
changing them a bit, as well as making your own routines, you should be able to cope
with a bit less detailed explanations.
If there's something you don't quite understand, consult your references, write some
code and see what happens etc. And send me an email, telling me what you don't
understand.
Using More Than One
Interrupt Per Frame
Now, pretty often (if you're coding real demos), you'll want to have several interrupts
occur each frame. Let's say you have some kind of raster bar effect, that's created by
an interrupt routine that is triggered at line $20, then you have a scroller that starts at
line $e0. You can do this in two ways (or more, but this is just an example): (i ) just use
one raster interrupt, and do the old $d012 polling to wait for $e0, or (ii ) use two
interrupts.
So, we'll go for the second approach. Let's say the label for the first interrupt routine is
intraster and the one for the second one is intscroll. In the interrupt setup we'll
put the address of intraster in the interrupt vector $0314 and set the value $20 in
$ d012 (to make the VIC generate an interrupt at line $ 20 .
That's all very well, but if we don't do anything more, the interrupt at $e0 will never
happen. What we'll have to do is change the values of $0314, $0315 and $d012 in the
interrupt routines. So, at the end of the first interrupt routine (intscroll) we set
$ 0314 and $ 0315 to the address of intscroll and $ d012 to $ e0, before we return
from the interrupt. And of course, in the second interrupt routine, we'll have to set the
values back, so that they point to the first interrupt routine, and line $20.
If this sounds confusing and you're thinking ``No, I'll just keep polling $d012 instead'',
then please read the above paragraphs again. It'll make your life so much easier.
It'd probably be a good idea to try to write a small program, using the ideas explained
here.
Write two interrupt routines that do something simple, like change the background
colour, and check so that you can make them both work. To make it more interesting,
change the values of $d012 each frame (by adding or subtracting one from the value).
That way, you can make your rasterbars move up and down.
There's nothing wrong with the first approach, except that you may want to do something
in the main loop as well (outside of the interrupts), and in that case you don't want to
sacrifice all the rastertime between the two effects by using them for polling $d012.
Stable Raster Interrupts
If you've tried out the above, especially changing the background colour on different
lines, you've probably noticed that the interrupts aren't stable; if the colour change
happens somewhere in the visible area of the screen, you'll see that it jitters a bit. It
might even jump a whole line up and down, if you're on a Bad Line.
The reason is that when an interrupt is triggered, an instruction is executing in the CPU,
and that instruction will have to finish before the jump to the interrupt handler takes
place. As you can understand, there's a variable delay here, eg. a NOP only takes two
cycles, and some memory manipulating instruction in an indexed addressing mode
might take 7 cycles.
However, you can do stuff like opening the top and bottom border, sprite multiplexers,
raster bars, scrollers, displaying FLI pictures, FLD and all kinds of stuff without having a
stable raster.
This can be pretty irritating, and it can be pretty difficult to time some routines so that they
look nice. On the other hand, you can do pretty much, although your interrupts aren't
stable. For now, it should be sufficient to know that there are ways to make the raster
completely stable. You'll need a stable raster to do some advanced effects, like splits
(raster bars that change colour in the middle of a line ) and opening the side border.
Anyway, there are different ways to get a stable raster, and you'll want to learn it
eventually, unless you want to be doomed to code simple effects or ugly-looking chunky
crap effects (which sometimes don't seem to use any timing at all) for the rest of your life.
These different techniques all have their fans, so I'll go through them quickly here:
Double interrupts This one uses two interrupts the first one sets up the second
. :
one and makes it happen when executing a NOP so that the jitter is reduced to ,
one cycle and then a simple branch instruction at exactly the right time to
, ,
remove the last cycle of jitter This technique seems to be very popular
. .
Sync with sprite This technique utilizes the way sprite data is fetched What you
. .
do is that you turn on at least one sprite and at the right time you execute some
, ,
memory manipulating instruction which is stalled by the sprite fetch which makes
, ,
it end at exactly the same time a fixed number of cycles after the sprite data fetch
,
is complete This might sound complicated but it s a lot simpler than the double
. , '
interrupts method and all you need to do is to turn on a sprite and do an INC at
,
very simple All you do is trigger a Bad Line eg by executing INC $d011 and
. ( . ),
voila you have a stable interrupt It might produce some garbage on the screen
!, . ,
but it s really simple I discovered this one while coding a FLI viewer and this is
' . ,
Syncing with a Bad Line I haven t tried this one myself I just read about it in an IRC
. ' ,
getting a stable interrupt by using an INC at the right moment on a Bad Line Try it .
out yourself .
My personal favorite is to sync with a sprite. I find it to be a very clean and nice way of
getting a stable raster, without all the hassle of using the double interrupts method.
Triggering a Bad Line probably isn't very good at all, but it simple and it works, although
it can have side-effects that aren't very nice. Syncing with a Bad Line is probably a very
good method, as Crossbow uses it.
NMIs
I won't delve too deeply into the topic of NMIs in this discussion, however, my main
focus will be on providing a detailed explanation of how you can successfully address
the problem by utilizing the RESTORE key. It is crucial to understand that NMIs cannot
be simply deactivated as they are considered non-maskable interrupts, making them
difficult to disable. Therefore, it is essential to carefully follow the steps outlined in this
explanation in order to effectively manage and resolve any issues related to NMIs that
may arise in your system.
You can establish an NMI handler in a similar manner to setting up an interrupt handler.
However, instead of configuring $0314 $0315, you need to set the address in
$ 0318 $ 0319, which corresponds to the NMI vector. Make sure to direct it towards a
routine that simply returns without any additional actions. It really is that straightforward
and easy to implement. Just remember to handle any specific conditions or
requirements that may arise during the process, and always test your implementation
thoroughly to ensure its effectiveness and reliability.
Interesting Effects
In the previous sections I have explained most of the basics that you need to know in
order to code your own demos. You might not understand exactly how everything
works, but if you've written some code, using the stuff I've explained above, you should
have a fairly good grip on the basics.
Although you have acquired a wide array of tools to produce various effects, it is
possible that you have not fully grasped their functionality. Within this section, I will
provide several illustrative examples of intriguing effects. You have the option to try
incorporating these on your own, or, better yet, utilize the underlying principles to create
something unique and innovative.
However, it is absolutely essential to highlight the fact that there are certain
responsibilities that every aspiring demo coder must take on at least once throughout
their journey. It is crucial to understand that these responsibilities play a vital role in
shaping their skills and knowledge in the field. The majority of the examples that follow
should adhere to this necessary standard in order to succeed in the competitive world
of demo coding. It is imperative for demo coders to embrace these responsibilities and
challenges as they pave their way towards excellence in the industry.
I won't provide you with the source code needed to implement all of these
functionalities. I believe it's important for you to figure out the specifics on your own, as
this process will enhance your learning experience. If you're looking for additional
guidance, you can refer to the source code and detailed explanations available in the
early editions of Commodore Hacking and all three editions of Coders World (refer to
the References section below) for more information on these effects and others.
I'll do my best to arrange these effects in a sequence based on their complexity, with the
initial ones being relatively straightforward and the subsequent ones becoming more
challenging. However, it's important to remember that everyone's experience may vary. In
any case, tasks like text scrollers and raster bars are likely to be less demanding compared
to tasks such as showcasing a FLI picture or manipulating the side border.
Text Scrollies
I'll start with this one, not just because it's a simple effect, but because it's so
fundamental in demo coding. If you can do a simple text scroller, you can then work on
making it more interesting, by adding colours, different sizes of fonts, animated fonts,
Y-moving scrollers etc.
Doing the basic scroller is easy. Of course you start by setting up an interrupt that
occurs a few lines before the actual text that should be scrolled. There you read a
variable, where you've stored the current value of $d016, which is the X-scroll register.
The three lower bits of $d016 control the X-scroll, so you have 8 steps of scrolling,
enough to scroll one whole character. With the value 0 in the three lowest bits, you'll
have your normal screen, and with the value 7, it will be scrolled 7 pixels to the right.
So, what you'll have to do is to start at the value 7, and then decrement it by 1 (or 2, 3, 4
etc., if you want a faster scroller) every frame. When you already have an X-scroll value
of 0, you can't decrement it, you'll have to reset it to 7 again. At the same time you'll
have to move the characters in screen memory one step to the left, and insert a new
character in the character at the right end of the screen.
Then you just keep going. As I've said, a text scroller is a simple effect, but writing your
first one isn't necessarily easy. So here are some suggestions from someone who can
still remember the hassle of getting a simple text scroller to work:
Start by putting some characters on the screen and make the d016 fiddling $
work The characters should move to the left for 8 frames and then flip back to
.
their original position and start moving to the left again This happens pretty fast
. ,
so it s not easy to see that everything is really correct but if you get this effect
' , ,
When you ve got that working add a loop that copies characters from teh right
' ,
to the left on one line of the screen eg the first one which starts at 0400 and
, . , $
ends at 0427 That is copy 0401 to 0400 0402 to 0401 etc And of course
$ . , $ $ , $ $ . ,
add a new value in 0427 each time You should now have a basic scroll
$ . .
Add a routine that reads from an area of memory where you ve stored your scroll
'
text Make sure it wraps at the end You can do this by eg storing the memory
. . .
position of the last character somewhere or set an end mark eg ff at the end of
, , . $ ,
the text .
When you have a basic scroller going, you can add some colours to it (by changing the
values in colour RAM, $d800 to $dbe7 . One thing that has been used a lot is to have
the outer characters have a darker colour than the central ones, which can make it look
like the characters are fading onto the screen.
You can of course to other things with colours, like move the colours with the
characters, so that each character has its own colour. Or you can have different colours
cycling through the scroller.
Then, of course, there are all sorts of things you can do with your scroller to make it
look more cool:
Use your own character set and it ll look nicer the ROM charset isn t very hot
, ' ( ' ).
Make the scroller move at different speeds by adding different values to d016
( $ .
Just make sure you move the characters at the right time so that it doesn t jitter
, ' .
Use d011 to move it up and down while it s scrolling from the left to the right You
$ ' .
can use the same concept there copying characters to make it scroll more than 7
, ,
The easiest thing is to do it in the upper or lower border. Then you'll only need to
change $d020, and there are no Bad Lines that mess things up for you. All you need to
do then is to write a loop that takes 63 cycles to execute 65 if you have an NTSC C
64 . In the loop you read a colour value from a table (indexed by the x or y register),
increment your index value, change $d020, do a delay, check if your index value has
reached a certain value, otherwise branch back to the top. You'll also need to add some
delay before the loop, to make it start at the right time.
It might seem a bit complicated to have to count the cycles that different instructions
take, but you'll learn it quickly, and it definitely pays off. Of course you'll need some trial
and error to get it to work the first times...
Some things can screw up the timing and make instructions take different amounts of
cycles. If you're using sprites, they'll steal a few cycles on each line where they're
displayed, so don't move sprites over your raster bars, at least not if they're changing Y
coordinates. That requires much more timing.
You'll also have to watch the page boundaries. A branch that crosses a page border
takes one cycle more to execute than normally. The same goes for indexed addressing
modes. Your usual LDA addr,X instruction usually takes 4 cycles. But if addr is eg.
$ 2080, and X is greater than $ 80, you 'll cross the page boundary, and it'll take 5 cycles
instead. In some cases it's much better to use a monitor, instead of an assembler, as
you know exactly where the page borders are in your code.
By using different registers to count the times you do the loop and to index into the
colour table, you can make the colours in the raster bar roll. Or use the same register,
and alter the colour table itself each frame.
Opening the Top And
Bottom Borders
This is a simple trick but it can be pretty cool to be able to put stuff in the upper and
,
lower border Of course it s even more cool to open the side borders and conceptually
. ' ,
To open the upper and lower border you have the screen set up to display 25 lines of
,
text by setting bit 3 of d011 Then on the last line of the screen on raster line f8
( $ . , ( $ ,
$ f9 or fa turn off that bit The VIC will be fooled into not checking where to turn on
$ ), .
You have to set the bit again so that the VIC will be fooled again the next frame but
, ,
you ll have to wait a couple of lines first or you ll fool yourself instead You can display
' , ' .
sprites in the upper and lower border but not normal graphics , .
The same goes for the side border However the last address in the VIC page 3fff in
. , $
the default case otherwise 7fff bfff and ffff will also be displayed in black
, $ , $ $ ) , .
So if you have another background colour than black and the value in this address is ,
not 0 you ll see a garbage pattern in the border area You can actually use this for some
, ' .
This means that $d012 and $d011 won't match on the next line. On the next line, you do
the same thing again. And then you keep going until you think it's time to display the
next text line. Of course you use a loop for this, and if you vary the number or times you
go through the loop each frame, you can make text lines scroll up and down really
easily. Combine it with a scroll text, and you'll have a scroll text that moves up and
down. Nice, eh?
And of course, you can use this routine just to get rid of Bad Lines, which can be handy
if you want to do eg. colour bars on the main screen. Just do an FLD and change $d020
and $d021 every frame, and you don't have to worry about Bad Lines.
What you have to do is to delay the next Bad Line. A Bad Line is triggered when the three
lowest bits of $d011 match the three lowest bits of $d012. So what you do is that you take
the value from $d012, add a value to it, eg. 2, set the upper five bits to 0 (by using AND
#$07), set the upper bits appropriately (ORA #$18 for text mode) and STA $d011.
Sprite Multiplexer
The concept of sprite multiplexers may appear simple at first glance, but in reality, it can
present numerous obstacles when it comes to implementation. This complex process
entails constantly modifying the Y coordinates of sprites in real-time as they are being
shown on the screen. After each sprite finishes its current display cycle, it must then be
given a new Y coordinate position, usually positioned a few lines lower than its previous
spot on the screen.
Kindly make sure that the newly updated Y coordinate is at least $15 higher than the
previous value, as a smaller increment could lead to the point being potentially invisible
during the subsequent display.
It gets even cooler if you change the sprite pointers too, but that has to be done at
exactly the right time, because you can change the sprite data in the middle of a sprite's
display, and then it'll just look weird, unless you really know what you're doing (it can be
used for some advanced effects).
Use a sinus table for the Y values, and find our where you have to change the coordinates.
Tech-Tech
You might already have figured out that you can do a simple effect by changing the
three lower bits of $d016 (the X-scroll) on every line. If you haven't tried it, you should at
least be able to understand what happens: each line will have its own X-scroll value.
By changing the X-scroll value in an ordered manner, you can make the graphics wave
back and forth. But you don't get more than 7 pixels worth of difference between the
lines, which is a pity...
You've probably seen real tech-techs (they're not so common these days as they were
around 1990 , and they definitely have a greater difference than 7 pixels. You might
think that you can do that by moving the characters in screen RAM, but you can't,
because screen RAM is only read each 8th line.
What you have to do is to change the charset (using the four lower bits of $d018 , to a
new charset, which is shifted one character to the right. You can fit 7 charsets (you
need space for the screen RAM too) into one VIC page 16 kB , which means you can
make a 56 pixels wide tech-tech.
Not bad, huh? It can be a bit tricky to get it to work the first time, though...
You can of course also change VIC bank (with $dd00 , which means you can do the
effect with graphics, not just with a charset logo, or just get a wider tech-tech.
FLI AFLI IFLI etc
, , .
FLI is a graphics mode that gives you more colours per character than a normal multi-
colour pixel. To achieve this, you need 8 different screen RAMs, with different colour
values. The effect is achieved by triggering a Bad Line on every line $d011 and
changing $d018 to point to a new screen RAM (but the same bitmap) each line. You do
this for 8 lines, then you start over again.
A normal FLI picture starts at $3c00. The area between $3c00 and $3fff is colour RAM,
which is copied to $d800 in the initialization. The area between $4000 and $5fff is
taken up by the 8 different screen RAMs, and $6000 to $7fff is the bitmap. So the
values you'll change between in $d018 are $08, $18, $28 and so on up to $78.
AFLI is exactly the same thing except that it uses hires mode. As hires doesn't use
colour RAM, an AFLI picture takes up $4000 bytes, and is laid out in the same way as a
FLI picture.
IFLI is just like FLI, except that you have two FLI pictures, which you switch between
every frame, as well as changing X scroll by 1 pixel. This is to give it the appearance of
more colours and higher resolution, by interlacing it.
In all of these formats you'll see the so called FLI bug, which means that first three
characters on every line are unusable. There's no way to get around this. In FLI and
IFLI, you just have to set the values for these characters to 0, and they'll be black. In
AFLI, they'll always be light grey, so if you want to have some other background colour,
you'll have to cover these three lines with sprites.
The FLI effect also has the side effect of giving you a stable raster, which is always nice,
of course.
Opening The Side Border
If you've got a stable raster, you can open the side border in exactly the same way as
you open the top and bottom borders. However, instead of using $d011, you should use
$ d016. Additionally, instead of doing it once every frame , you will need to do it on every
raster line where you want the border to be opened. This method allows for more
precise control over the border opening process, ensuring that your graphics are
displayed exactly as you intend them to be.
A helpful tip: start by using DEC $d016 to adjust the position, then follow up with INC
$ d016. To ensure you 're positioned correctly (near the right border), consider using
$ d021 instead of $ d016 for timing purposes . This simple adjustment can make a big
This particular effect may not be the most essential one to tackle when writing code, but if
you have already established a solid foundation with your raster, it could be worth
experimenting with. It is important to consider the potential impact that exploring different
effects can have on the overall quality and functionality of your code.
By taking the time to experiment and refine your techniques, you may discover new
ways to enhance the performance and aesthetics of your project. So don't be afraid to
step outside of your comfort zone and try out different approaches – you never know
what innovative solutions you may uncover in the process.
Plasmas Bumpmappers
, ,
4 4 is often used, and it uses a graphics mode called half-FLI, which forces a Bad Line
each 4th raster line. Combined with the right char data and two screen RAMs, this gives
you a screen with 80 50 resolution. It doesn't look very nice, but it can be a nice
programming exercise... And it's popular, although chunky graphics modes seem to be
going out of fashion. It's about time.
To do 3d effects with vector graphics, all you really need to know is how to put a pixel
on a bitmap screen and draw a line. Once you've done that, you just need to optimize
your code to make it smooth and nice.
As you might have noticed, I haven't explained stuff that's seen in many modern demos,
like plasmas, bumpmappers, 3d effects etc. I'm not very much into this type of effects,
although they can look nice sometimes. Not if they're displayed in 4 4 or 8 8, though!
These aren't specific to the C 64, and you can find information about them in lots of
places. If you can do a plasma on some other platform, you can do a plasma on the C 64.
And The Rest
...
The rest you'll have to figure out yourself, or read about in other places. As mentioned
earlier, there are numerous ways to customize these fundamental effects, and
experimenting with combining two or more can yield some truly impressive outcomes.
Being inventive and open to exploring different possibilities is key to creating captivating
demonstrations.
Always keep in mind that embarking on the journey of discovering and mastering these
effects is not only challenging but also incredibly rewarding. It will push you to break
free from conventional thinking and come up with innovative ideas that will truly
captivate your audience in ways you never thought possible before.
Do not hesitate to push the boundaries and experiment with new techniques, as innovative
ideas frequently result in the most captivating outcomes. It's important to keep in mind that
creativity is boundless, so feel free to step outside of your comfort zone and delve into
unconventional methods in order to truly make a lasting impression with your presentations.
Without a doubt, it is highly likely that there are a multitude of undiscovered VIC tricks just
waiting to be uncovered, hidden beneath the surface, yet the opportunity to come across
these valuable secrets is slowly dwindling with each passing moment that elapses.
An Exercise In
Demo Creation
As I've mentioned multiple times already, the key to mastering demo programming is
not just studying it passively. You have to actively engage in writing demos yourself.
Before diving into the intricacies of IRQ loaders and complex effects, it's crucial to begin
by creating a simple part that includes the following elements:
A logo at the top of the screen is an essential element that can be customized to
suit your preferences You have the option to create it yourself by utilizing a
.
graphics program whether you choose to work in multi colour mode for a vibrant
, -
look or opt for a single colour hires design for a more simplistic approach
- .
8 sprites moving around the screen in some sine pattern This might be a bit tricky .
the first time you try to do it but all you really have to do is to set up two tables
, ,
one for the X coordinates and one for the Y coordinates and assign each sprite ,
an offset into the tables Then change these offsets each frame and just read the
. ,
values from the tables and poke them into d000 d001 etc The easiest thing is
$ , $ .
A scrolling text located at the bottom of the screen continuously delivering real , -
time updates breaking news and essential information to keep viewers informed
, ,
Raster bars can be easily added to the top and bottom border without the need to
open it up simply adjust the value at d020 This simple adjustment allows for
; $ .
A tune playing You don t have to go through the hassle of learning to use a
. '
music editor just rip a tune from some other demo As stated earlier they re usually
, . , '
located at 1000 and are often shorter than 1000 bytes so often all you have to do
$ , $ ,
is to start the demo reset go into the monitor and save the area from 1000 to 1fff
, , $ $ .
Before diving into the program, take your time to thoroughly explore the wide array of
tools at your disposal that can truly elevate your experience. It's essential to carefully
pack and crunch the demo before loading it in order to optimize performance and
ensure smooth operation. When you're ready, simply type in 'RUN' to kickstart the
program and begin your journey. If you find yourself in need of assistance, don't
hesitate to refer to the Tools section for detailed guidance and support.
If you can create a demo like this, please share it with me! Your work would benefit
others and inspire them to code. Your contribution to the coding community would be
valuable and showcase your skills.
Cartridges
You definitely need to consider investing in one of these essential cartridges if you
want to enhance your coding experience. Having a reliable cartridge is crucial for
making your C 64 code hacking a much smoother, efficient, and ultimately more
enjoyable process. While the Action Replay series, particularly version VI, is highly
sought after these days and can greatly enhance your code hacking experience. Our
C 64 Code Hacking Software Library contains not only the popular and immensely
useful & power packed Action Replay VI but also every other iteration of that classic
cartridge as well as every other handy cart I could find during my research for this book.
There are numerous alternative options available to enhance your coding journey and
take it to the next level. In addition to considering the Final Cartridge, you can also
explore a diverse range of other code hacking carts that are part of our extensive
collection. The possibilities for expanding your coding skills are truly endless and waiting
for you to explore and utilize to their fullest potential!
The most important features are a fast loader, a monitor, and a reliable power supply. A
fast loader is essential for quick loading and efficient operation, while a monitor is crucial
for manipulating data in memory, debugging code, and overall system functionality.
Without these key components, the cart's performance may be compromised,
hindering productivity and efficiency. Additionally, a reliable power supply ensures
continuous operation and prevents unexpected interruptions, ultimately enhancing the
overall user experience and functionality of the system.
Packers and Crunchers
Before you release something, you want it load as quickly as possible, and to take as
little disk space as possible. To achieve this, you use a packer or a cruncher. For the
best possible result, you use both.
Crunchers are more advanced, slower and give better results, because they use a more
advanced algorithm, which checks for common sequences in the data, and replace
those by references to earlier identical sequences. If you think crunching takes too long
time, try getting an REU Ram Expansion Unit) and a cruncher that uses it, as that can
improve crunching speed a lot.
If you have a means to transfer stuff between your C 64 and a PC or Amiga, you might
be interested in checking out Pasi Ojala's PuCrunch, which crunches your C 64 files on
the PC or Amiga side. Of course it's very fast, and it also gives very good results.
Some packers (eg. Sledgehammer) let you link all the files that you want to pack. This
can be nice, although I prefer the method of saving the whole memory area that I use
and pack that. It's a matter of taste, I guess.
IRQ Loaders
An IRQ loader is a loader that performs loading operations within the main loop without
interrupting the execution of other routines. This allows for loading to occur seamlessly
while displaying various graphics such as scrollers, rasterbars, and sprites on the screen
without any noticeable disruptions to the viewer.
Only those with noisy drives or who pay close attention to drive LEDs may become
aware of the loading process. The efficiency of file loading is directly affected by the
amount of available raster time during the loading operation. Consequently, the more
raster time that is allocated, the faster the files will be loaded.
Most IRQ loaders operate similarly, however, there are certain loaders that may not be
compatible with all drives and others that may provide faster loading speeds.
Additionally, some loaders offer the convenience of decrunching on the fly, eliminating
the need for manual decrunching after loading a file. This allows for immediate use of
the data without any additional steps.
You typically start off with an initialization routine, which is responsible for setting up the
drive and can be replaced to free up memory. Following that, there is the loader routine,
which must be kept until the final part is loaded. Additionally, there is usually
accompanying documentation that provides instructions on how to utilize these
routines effectively. It is crucial to carefully follow the steps outlined in the
documentation to ensure smooth operation of the system. Understanding the
intricacies of each routine can help optimize performance and troubleshoot any issues
that may arise during the process.
Cross Platform Sprites
- ,
Characters Graphics
&
Editors Converters
&
Sinus Editors
You'll need a sinus editor to produce nice sine tables, to use for sprite movements,
scrollers, plasmas and what have you. Most of them offer the same features, so just
check out a few and you'll get what you want.
Some people don't use sinus editors, but write small BASIC programs instead. That
gives you more flexibility, of course. Here's a small example from BlackJack:
He also adds: "It's pretty easy to add stuff between line 40 and 60 to split a larger value into "X
div 8" and "X mod 8" for scrolling big logos or similar things."'
If you want more interesting sine movements, you'll have to change line 50 (the SIN(I) part).
Music Editors
The most popular music editors in the C 64 scene continue to be DMC and the JCH
editor. While JCH's editor functions more like a tracker, DMC follows a more traditional
C 64 music editor format, displaying one sequence at a time. Both editors provide
comprehensive sound editing features, and their respective players boast respectable
rastertime and memory usage efficiency.
Some less commonly used editors in the scene include Sidwinder by Taki/Natural Beat,
which is renowned for its highly optimized player that effectively reduces raster time
usage. Additionally, EMS by Odie/Cosine, from what I have observed, stands out as
being comparable in quality to the well-known editors DMC and JCH.
Scroll text writers are commonly utilized for, you guessed it, writing scroll texts and they
are incredibly straightforward tools with no formatting options, color or font choices. If
you require those features, you can always turn to Noters for assistance. Additionally,
many Disk Magazines rely on Noters for crafting their content, making them a versatile
choice for content creation. Noters can offer a wide range of formatting options to
enhance the design of your text-based note and make it easier to read.
Whether you are meticulously working on a scroll text for a captivating introduction,
carefully crafting content for a cutting-edge Disk Magazine, or simply striving to produce
engaging and professional-looking texts, Noters enhance and streamline your writing
experience. With their intuitive design and versatile functionality, Noters truly stand out as
the ultimate choice for coders looking to elevate their intro & demo content creation.
Graphics Stored At
$1000 or 9000
$
If you notice that your sprites (bitmaps, charsets etc.) seem to be pulling their data from
the standard CBM charset, it is likely that they have been placed in the memory ranges
between $1000 and $1fff or $9000 and $9fff. Unfortunately, using these areas for
graphics is not possible as the VIC will consistently recognize the standard charset in
these regions. Ensure that you allocate memory for your sprites outside of these ranges
to avoid any conflicts with the VIC's recognition of the standard charset data.
This explains why music is typically stored at $1000 in most cases, to avoid conflicts
with graphic data. It is important to be mindful of memory allocation and avoid
overlapping regions to ensure smooth functionality of your graphics and sound
elements in your program. Proper management of memory allocation is crucial in
maintaining the integrity and performance of your program.
By carefully organizing and allocating memory for different elements such as graphics
and sound, you can prevent conflicts and ensure that your program runs smoothly.
Additionally, being aware of potential overlapping regions in memory can help you avoid
glitches and errors that may arise from conflicting data. By following these best
practices in memory allocation, you can optimize the functionality and user experience
of your intro or demo code.
Messy Vertical Border Or
Behind Your FLD
If you happen to notice unsightly black garbage appearing in the top and bottom
borders or on the screen during your FLD process and you're unsure of how to remove
it, there's a simple solution. Just clear out the last byte of the current VIC bank, which
means $3fff for the initial bank, $7fff for the subsequent bank, and continue in this
pattern.
This quick fix should effectively eliminate the issue and allow you to proceed with your
work smoothly. Make sure to save your work before making any changes to avoid
losing any progress in case anything goes wrong. It's always better to be safe than
sorry when troubleshooting technical issues like this.
Before moving forward, it is important for you to be extremely cautious and take the time
to carefully consider the potential outcomes of proceeding with this specific course of
action. The choice to delete the contents of memory location $3fff must not be made
haphazardly, as failing to conduct a thorough evaluation may lead to a wide range of
unexpected complications and obstacles in the future. It is crucial to approach this
decision with great care and attention to detail, ensuring that all possible outcomes are
carefully weighed and analyzed before proceeding.
Additionally, it is important to note that if there is any pre-existing code stored in the
specific memory location, resetting it to zero could significantly increase the likelihood of
your demonstration crashing or malfunctioning in the near future. Therefore, it is vital to
proceed with caution and prioritize thorough planning and analysis to minimize any
potential negative impacts on the performance and functionality of your project.
Everything Works Until I
Pack It Please Help Me
, !
Do you frequently come across unusual bugs after packaging your demo? One possible
explanation could be a malfunctioning packer. Another factor to consider is the potential
of accessing uninitialized memory. It is crucial to understand that the memory state
post-packing may not align with your assumptions, as the values you expect to be zero
could have been changed.
If you have doubts about the packer or cruncher you are currently using being faulty,
consider switching to a different one for comparison. It is essential to recognize that
experimenting with various packers and crunchers can lead to a wide range of
outcomes in terms of the appearance and performance of your demo.
Exploring different tools and techniques can provide valuable insights into the potential
improvements and optimizations that can be made to enhance the overall quality and
efficiency of your work. Don't hesitate to explore new options and strategies to achieve
the best results possible.
Exploring a variety of tools and techniques can be a highly beneficial strategy, as it can
offer valuable insights and ultimately lead to more effective results. It's important to
keep in mind that each packer and cruncher comes with its own set of unique
characteristics and capabilities, so don't be afraid to experiment with different options in
order to discover the perfect fit for your specific needs. By exploring alternative
solutions, you can not only pinpoint the most suitable tools for your projects, but also
significantly elevate the overall quality of your work.
In such cases, it is advisable to rely on recommendations from others in the field.
Generally speaking, reputable tools like Sledgehammer II or The Cruncher AB are unlikely
to have bugs. These tools have been extensively used in numerous products, which
suggests that any potential bugs would have been identified and resolved by now.
A Few Words About
Optimizing Your Code
In general, it is highly recommended to make sure that the screen is updated with each
frame, particularly when incorporating effects that involve intricate calculations. Ensuring
that the visuals are constantly refreshed not only enhances the overall user experience,
but also maintains the smooth flow of the animation.
It is crucial for developers to constantly adapt and evolve their techniques in order to
stay ahead of the ever-changing technology landscape. By staying proactive and
continuously seeking new ways to optimize screen updates, developers can ensure
that their applications remain competitive and user-friendly in today's fast-paced digital
world.
If you have developed a visually stunning effect but find that the computations exceed
the allocated raster time per frame, you will need to either optimize your code for
efficiency, explore alternative techniques, or be prepared to compromise on the level of
refinement in the final product. It is crucial to strike a balance between achieving the
desired visual impact and ensuring that the performance remains optimal for a smooth
user experience.
If you ask a computer scientist, he or she will tell you that you should first improve your
algorithms, and then, if it's still necessary, improve the constant times that each iteration
takes. This makes perfect sense, if you want to sort 10000 numbers, you shouldn't
spend time optimizing your bubble sort routine, but instead implement some faster
algorithm, like quick sort or merge sort.
One common issue with demo effects is that the algorithm is often not the main
problem. The algorithm is typically quite simple, and the challenge lies in optimizing the
speed of each computation. While it may not be possible to reduce the number of
iterations, the focus should be on minimizing the time required for each iteration.
The basis of optimizing a computation is of course to decrease the time it takes, ie.
decrease the number of machine cycles that each computation takes. Each instruction
takes a few cycles to execute. You'll need a table with the timing for the different
instructions.
Removing Instructions
So the first rule of thumb would be: remove all unnecessary instructions. All instructions
take a few machine cycles to execute, so by removing some of them, you're speeding
up your code. An example of an instruction that can sometimes be removed without
affecting the result is CLC. Read through the critical section of your code and try to find
instructions to remove.
Substituting Instructions
Sometimes, by thinking outside the box and getting a little creative, you can find ways
to enhance a basic set of instructions to make them more effective. For instance,
imagine you have to modify a byte in memory by increasing it by one, and then you can
try this particular sequence to execute the operation:
ldx var
inx
stx var
This is pretty bad, especially if you're not planning on utilizing the value later on. The
code provided above is quite inefficient in terms of cycles. By opting for a
straightforward INC var instead, you could have effectively trimmed down the number
of cycles by 4! It's crucial to always consider the efficiency of your code and look for
ways to optimize it for better performance.
Loop Unrolling
Loop unrolling means that you optimize away the overhead that's inherent in all loops ,
ie . the code that changes and checks a counter and branches . Let's say you have the
loop
dex ; 2 cycles
If you count the cycles in the above code , you 'll see each iteration through the loop will
11
take 12 cycles . It's executed 256 times , which means that the total number of cycles
used for the above code is cycles . That's quite a lot of raster time !
Let's unroll the loop and see if we can get it any faster... The code will look like this :
Of course, you won't gain as much as this in the usual case, but there's a lot of time to
spare with this technique.
Using Tables
Why do people use pre-calculated sine tables? Because that means they don't have to
do the costly sine calculations in real-time. That shouldn't be news to you. But if you
think about it for a while, you might realize that you can use tables for lots of stuff.
Generally, if you have some kind of complex calculation, you can use lookup tables
somewhere. If you're writing complex stuff with lots of shifts here and there, you can
probably re-write that code to run in half the time by using a table.
Other Optimizations
The above techniques are just meant as examples of how to optimize code. The
general idea should be pretty clear by now: do everything you can to make your code
faster. Read through it and try to find ways to make it faster. Use tables, unroll loops,
remove crap that's not necessary.
Some Other Ways to Make
Your Code Even Faster
!
There's of course a lot in truth in the rule that you should first optimize your algorithms,
and then the constant factors. Don't think that there's no better way of achieving an
effect than to use brute force. You can always cheat in some smart way, use data that
makes the job easier and the code run in half the time.
Re using Stuff
-
This way, you can simply retrieve the pre-computed values when needed in the future,
saving time and improving efficiency by eliminating the need to recalculate the same
data over and over again, ultimately streamlining processes and increasing productivity.
Re-using stuff can be as simple as plotting the same point in different places on the
screen, which opens up a world of possibilities for endless creativity and versatility in
design and presentation. By exploring different ways to repurpose elements, designers
can truly unleash their creativity and create captivating visual experiences that captivate
audiences.
It is ultimately your responsibility to ensure that your code is designed to handle the
specific types of data it will encounter. Keep in mind that unnecessary complexity can
hinder functionality, so focus on addressing realistic scenarios that may arise.
And of course, if you notice that your data demands a complex routine, think of ways to
change the data in order to optimize it and develop a more efficient routine to handle it
effectively and swiftly. It is crucial to constantly reassess your data processes and adapt
them accordingly to ensure maximum efficiency and productivity in managing your data
effectively.
References
Mapping the C 64 This is a great memory map with thorough explanations of all
. ,
Programmer s Reference Guide This one has a nice table of opcodes with cycle
' . ,
counts addressing modes etc Mostly the book is pretty useless though This
, . , .
All About Your C 64 This is a document put together by Ninja The Dreams which
. / ,
can be really handy Especially the HTML version is nice to have available when
.
coding and you can t remember quite which bit it was that you had to fiddle with
, '
to achieve something This one s available from the The Dreams home page at
. ' '
http://www.the-dreams.de/.
The MOS 6567/6569 Video Controller VIC II and its Application in the C 64 ,
Christian Bauer This article should contain everything that is known about the
.
else ftp://ftp.funet.fi/pub/cbm/documents/chipdata/VIC-
):
Article.gz.
Assemble It! - Great Tutorials By Richard Bayliss: The New Dimension
Dustlayer - Nice Tutorials: dustlayer.com
6502.org - Nice set of tutorials for beginners: 6502.org
An Introduction to Programming C 64 Demos Inspired This Book): antimon.org
CodeBase64
- Docs WIth Source : https ://codebase64.org/doku .php?id=start
64Bites - Expert Series For BASIC & Assembly Coding! https://64bites.com
C64 Assembly Coding GuideProgramming
Digital Err0r C 64 Assembly
- Docs On Github: https ://github.com/spiroharvey/
On Windows: https://digitalerr0r.net
Graphics tutorials for the Commodore 64 and VIC II https blog adafruit com : :// . . /
by Pasi Albert Ojala on demo effects There s also a multipart Assembler tutorial
`` '' . '
funet:ftp://ftp.funet.fi/pub/cbm/magazines/c=hacking/ .
Discovery Magazine I ve only found three issues of this mag but it has some nice
. ' ,
demo related articles which you can learn a lot from Like C Hacking the mag
- , . ,
consists of ASCII text files that you can download off the Internet Available from
.
Coder s World This is a good resource for beginners When you ve learned a bit
' . . '
about the Commodore 64 the info in this mag may seem a bit too basic
, .
ftp://ftp.funet.fi/pub/cbm/magazines/disk/c64/.
Contact The Authors
You can contact the original author, Linus Åkerlund, by email or snail-mail. The snail-
mail address may of course change, so use email if you can. My email address is
puterman@civitas64.de. His snail-mail address is:
Linus Åkerlund
Kantorsgatan 38
S 75424 Uppsala
Sweden
Please contact Linus and tell him what you think about this book!
If you would like to get in touch with me, the author of this remastered, rebooted &
revitalized eBook, PDF, flipBook, audio book and a rather chunky printed book, swing an
email to my Inbox over at charles futurevisionpublishing com and join us in
@ .
the FutureVision Designs Demo Team, or send me a snail-mail and I'll reply with one of
our custom postcards and we can become penpals!
Snail Mail me today and I'll even send you a custom C64 disk with the entire
FutureVision Designs Old School Demo Collection Diskette !
Document License
The orignal license set by Linus was in the Public Domain in addition to that llicense I
,
well as a Fair Use License which means that while it is CopyLeft as long as you
" ", " "
You can do what you want with it, within reason. Mirror it, copy it, edit it, but you cannot
distribute it commercially. Please feel free to distribute the PDF, eBook, audiobook &
flipbook, you can even print it yourself and hand out copies to your friends, relatives,
pets and random gamer lamers.
About This Book ...
Original Title - An Introduction to Programming C 64 Demos
" "
Footnotes
... dangerous1 A couple of guys, who weren't all that good at C, were writing a
toy operating system. They got all sorts of bugs and weird
crashes, and didn't know what to do. After a while they came
any pointers at all. Don't ask me how they did it, but they did
... language.2 I've heard someone say that some PC demos these days are
... it
4
This code should be pretty assembler neutral, ie. you can
use whichever assembler you want. You can't type this stu
l ong 6
.. . See the Tools section on how to do that.
... bit9 Why 14 bits? Because the VIC can only address 16
address space.
... cycles11 Except the last one, which will only take 11 cycles,
sustain our efforts we rely on your continued support and partnership in this
,
important endeavor !
Dear supporters we kindly ask for your consideration in supporting our project
,
by purchasing our exclusive FutureVision Publishing Swag Join our family and
.
help us showcase to the World the immense value we place on our publications .
Your support means the world to us and we are grateful for every contribution .
Mouse Pad With Wrist Rest Mouse Pad (Round) Mouse Pad (Rectangular) Face Mask
$25US $15US $15US $15US
Commodore 64 In 6510
Machine Language !
coding while you learn how to code the Commodore 64 with all the
tools tips n tricks you ll need to create your own intros demos on
& ' ' ' &
You ll learn to code all of the popular graphical effects from sprite
'
Charles Xavier Grey has been coding the Commodore 64 since 89 ' ,
so you can count on him to show you everything you need to know
about the world of retro cross platform intro demo coding
- & .