Retro Programming on the C64 Episode 4 - Raster Interrupts and How to Play SID Music in Your Code. 00:00 Intro 00:30 What are Interrupts 00:52 Why use Interrupts 01:22 How to Configure a Raster Interrupt 05:28 How to Configure Multiple Raster Interrupts 07:09 Cleaning up the Code with a Macro 10:16 SID Files Intro and Downloads 11:28 How to Play Back a SID File in Code 15:04 How to Relocate a SID File to Other Place in Memory 17:57 Thanks for Watching Project Download: www.dropbox.com/s/omwzg8q8s0k3oj1/Episode4.zip?dl=0 High Voltage SID Collection: hvsc.c64.org/ SidPlay2 Download: csdb.dk/release/?id=103781 Sidreloc Documentation: www.linusakesson.net/software/sidreloc/ Sidreloc Download: csdb.dk/release/?id=109000 CBM prg Studio v3.13.0: www.dropbox.com/s/dk1d5e2hdgk4rzu/CBMprgStudio3_13_0_Setup.exe?dl=0 Commodore 64 Memory Map: sta.c64.org/cbm64mem.html Episode 1: th-cam.com/video/7IqVjcau8x8/w-d-xo.html Episode 2: th-cam.com/video/trLv4HFLHO4/w-d-xo.html Episode 3 th-cam.com/video/Pfy2vHygRaI/w-d-xo.html
Thanks for these C=64 programming tutorials. When I was a kid, I wasn't able to wrap my head around the c64 assembler, but it seems so much easier now.
Awesome! This actually helped me fix a random raster interrupt crash in my sprite multiplexer that i was getting in a game i'm working on. It was driving me crazy! In my code i changed asl $D019 to inc $D019 and also added the lda #$7f and $D011 sta $D011 part before changing $D012. Now it is working like a charm :) Thanks for the video! :)
I really enjoyed your little 101-asm-bootcamp. I worked through 3 others (that are much longer) before and yours is by far the best. You are a natural talent to teach stuff! Please continue the series.
This is a cool tutorial! I discovered that if you don't disable CIA timer interrupts, are selective about only calling the play routine on raster interrupts, and you jump to the standard IRQ handler afterwards, you can have the music playing in the background while running a BASIC program (you do need to alter top of BASIC so it doesn't clobber your ML routine though).
Thanks, you just need to jump to $ea31 (instead of $ea81) in the last interrupt each screen update, that will perform the kernal keyboard scan and update the cursor, then you can return to basic while your interrupt code keeps running. Cheers, Jake
Great tutorial! I just love the c64! As a kid there was a lot I never understood fully when it comes to assembly, but it makes more sense now , almost 40 years later 😀
Thank you, I have been looking forward to another episode on programming the C64. This is the clearest explanation I have seen on programming raster interrupts and with the examples you provided it is really easy to understand. I also like the explanation of the term "endian" I had no idea it was from a famous book publication. Excellent stuff, I am looking forward to the next episode when you have time to make it. Thanks again ;)
Great tutorial! Imagine if we had had this kind of info plus these tools when the C64 came out. There would probably have been way more games available for it, not that I'm complaining. On second thought, the potential game developers would probably have skipped the C64 and gone straight to Intel Core i7 with the graphics cards that are available now 😊.
It's worth mentioning that there are several different types of interrupts supported on the C64 in addition to raster ones. The system timer, keyboard and user port can also generate interrupts that your program can respond to, though for game programmers raster interrupts will be the main one you'd use. I believe the 1541 can also cause interrupts, but that may be limited to its own internal memory and processes. Not 100% sure on that though. On the SID playing, I wonder how much trouble it would be to write a small program that uses those SID properties to analyze the SID file and change all of the absolute jumps to a new address of your choosing (but still maintaining the relative jump distances from the original) in case the default location is incompatible with your code. For example, maybe your main code is larger than expected and the default loading location is inside your code space, or you just need to move it for some other reason. [edit: Whoops! I guess I should have watched the whole video before commenting! LOL] [Also, if possible, always try to get the permission of the SID author before using it in your own program. They will almost always say yes as long as you give them the proper credit in the game credits.]
Thanks, I'm planning an episode dedicated to sprites including joystick control, collision detection and multiplexing plus perhaps how to design a small physics engine for a basic platformer. Cheers, Jake
Very cool thanks! I haven't looked at the code for SID music...but is it pretty much accepted that there's a standard optimised way of paying music and all SID files use same method? Or does it vary from file to file?
Thanks, the SID player code is typically different for each piece of music, in most cases the player code is generated to be part of the music instead of having separate player code and music data. However the approach is depends on what tracker the music was composed in. SID music isn't very standardized. Cheers, Jake
Could you please make a video on the movement of the sprites at the start of Episode 3? I am trying to make a loop to move my sprites in a cool way, but get stuck when trying to figure out the loop structure. Would love to see the code you wrote for that movement if you could share it also.
Indeed, the way I usually do it is to have a delay table, on PAL it's easy you can use the values 8,8,8,8,8,8,8,1 so you do 8 delays on normal lines and then a single delay on the lines when the VIC chip is making the 6510 CPU sleep while it's accessing the memory. Cheers, Jake
Great video, so good. I have tried to add this example to my code but it isn't allowing me to enter the loop that looks for a keypress. I entered the loop where it says to do this, and the code has largely been untouched from your example. Not sure what I am doing wrong. HELP!
Hi James, did you try download the example project and run it? Does that work for you? Keep in mind when the interrupt code uses JMP $EA81 it will not scan for keyboard input. However you can change one of the interrupt returns to JMP $EA31, then it will include a keyboard scan. Also keep in mind if you want to return to the basic prompt then you should remove the custom interrupt code first by restoring the pointers otherwise it will likely crash. Cheers, Jake
what are those addresses $0314 and $0315 ? Who defined these addresses to have anything to do with "raster lines" ?! It aint any VIC2 nor CIA/VIA (hardware) registers. So whats happening there and why (or of whom).
As I describe in the video $0314 and $0315 are interrupt pointers/vectors. Whenever an interrupt occurs the code these addresses are pointing to will be executed, this is not specific for raster interrupts, it's for all maskable interrupts. These addresses are controlled by the KERNAL. If you bank switch the KERNAL out then you need to use $fffe and $ffff instead (these are the actual 6510 pointer for interrupts), however in this case you have to save and restore all the registers yourself and return with the RTI instruction. Cheers, Jake
Meanwhile I found an excellent documentation explaining this. While there can only be one single real (hard wired) interrupt vector on a 6510/6502 CPU at $fffe, the makers of the Kernel ROM designed in a "hook" to intercept the regular ROM ISR with user code. The users ISR jump address therefore is looked up at $0314 and $0315 and jumped to.
Retro Programming on the C64 Episode 4 - Raster Interrupts and How to Play SID Music in Your Code.
00:00 Intro
00:30 What are Interrupts
00:52 Why use Interrupts
01:22 How to Configure a Raster Interrupt
05:28 How to Configure Multiple Raster Interrupts
07:09 Cleaning up the Code with a Macro
10:16 SID Files Intro and Downloads
11:28 How to Play Back a SID File in Code
15:04 How to Relocate a SID File to Other Place in Memory
17:57 Thanks for Watching
Project Download:
www.dropbox.com/s/omwzg8q8s0k3oj1/Episode4.zip?dl=0
High Voltage SID Collection:
hvsc.c64.org/
SidPlay2 Download:
csdb.dk/release/?id=103781
Sidreloc Documentation:
www.linusakesson.net/software/sidreloc/
Sidreloc Download:
csdb.dk/release/?id=109000
CBM prg Studio v3.13.0:
www.dropbox.com/s/dk1d5e2hdgk4rzu/CBMprgStudio3_13_0_Setup.exe?dl=0
Commodore 64 Memory Map:
sta.c64.org/cbm64mem.html
Episode 1:
th-cam.com/video/7IqVjcau8x8/w-d-xo.html
Episode 2:
th-cam.com/video/trLv4HFLHO4/w-d-xo.html
Episode 3
th-cam.com/video/Pfy2vHygRaI/w-d-xo.html
been looking all over just trying to figure out how to play a sid on windows 10, so thank you for the reference to Sidplay ^_^
Thanks for these C=64 programming tutorials. When I was a kid, I wasn't able to wrap my head around the c64 assembler, but it seems so much easier now.
Yeah, it was a lot harder back in the day, unless you knew someone to help teach you, all you had were some pretty dry books.
Cheers,
Jake
Awesome! This actually helped me fix a random raster interrupt crash in my sprite multiplexer that i was getting in a game i'm working on. It was driving me crazy!
In my code i changed
asl $D019 to inc $D019
and also added the
lda #$7f
and $D011
sta $D011
part before changing $D012.
Now it is working like a charm :)
Thanks for the video! :)
Thanks, good to hear it was useful and good luck on your game.
Cheers,
Jake
I've used big/little endian terminology since the 70s, today, for the first time, I learned it's Lilliputian origins. Thank you !
Thank you so much for this video. This is the best explanation I have ever seen about raster interrupts. Finally I understand how it works.
I really enjoyed your little 101-asm-bootcamp. I worked through 3 others (that are much longer) before and yours is by far the best. You are a natural talent to teach stuff! Please continue the series.
Thanks much appreciated, I will do more of them in the future when I have more time.
Cheers,
Jake
Yes please!
This is a cool tutorial! I discovered that if you don't disable CIA timer interrupts, are selective about only calling the play routine on raster interrupts, and you jump to the standard IRQ handler afterwards, you can have the music playing in the background while running a BASIC program (you do need to alter top of BASIC so it doesn't clobber your ML routine though).
Thanks, you just need to jump to $ea31 (instead of $ea81) in the last interrupt each screen update, that will perform the kernal keyboard scan and update the cursor, then you can return to basic while your interrupt code keeps running.
Cheers,
Jake
Great tutorial! I just love the c64! As a kid there was a lot I never understood fully when it comes to assembly, but it makes more sense now , almost 40 years later 😀
Excellent clear demonstration on something i’ve struggled with for some time… thanks!
Very good step by step explanation how to use sid files from assembly. Thx 😃
You are TALENTED for these programming tutorials. Thanks for providing these precious info!
Thanks, much appreciated.
That raster interrupt setting macro is a killer gem! Thank you for sharing.
Lots of good useful info. Good job!
Thanks for the links in the description, not everyone does that...
Cheers,
Great series of programming videos, please do some more!
Thank you, I have been looking forward to another episode on programming the C64. This is the clearest explanation I have seen on programming raster interrupts and with the examples you provided it is really easy to understand. I also like the explanation of the term "endian" I had no idea it was from a famous book publication. Excellent stuff, I am looking forward to the next episode when you have time to make it. Thanks again ;)
any chance we'll get more of these? theyre amazing tutorials and its been fun to follow along
this a fantastic tutorial, I hope you will go on with this series as it is one of the best I could ever find!
I wish you did more commodore tutorials - certainly regarding graphics (sprites), etc
Great tutorial!
Imagine if we had had this kind of info plus these tools when the C64 came out.
There would probably have been way more games available for it, not that I'm complaining.
On second thought, the potential game developers would probably have skipped the C64 and gone straight to Intel Core i7 with the graphics cards that are available now 😊.
It's worth mentioning that there are several different types of interrupts supported on the C64 in addition to raster ones. The system timer, keyboard and user port can also generate interrupts that your program can respond to, though for game programmers raster interrupts will be the main one you'd use. I believe the 1541 can also cause interrupts, but that may be limited to its own internal memory and processes. Not 100% sure on that though.
On the SID playing, I wonder how much trouble it would be to write a small program that uses those SID properties to analyze the SID file and change all of the absolute jumps to a new address of your choosing (but still maintaining the relative jump distances from the original) in case the default location is incompatible with your code. For example, maybe your main code is larger than expected and the default loading location is inside your code space, or you just need to move it for some other reason. [edit: Whoops! I guess I should have watched the whole video before commenting! LOL]
[Also, if possible, always try to get the permission of the SID author before using it in your own program. They will almost always say yes as long as you give them the proper credit in the game credits.]
Now we just need to see how to bring a sprite over from the petscii web app (by itself) and move it around with a joystick ;) I love your tutorials!
Thanks, I'm planning an episode dedicated to sprites including joystick control, collision detection and multiplexing plus perhaps how to design a small physics engine for a basic platformer.
Cheers,
Jake
@@TheStuffMade Wow. That would we AWESOME!
Fantastic video!
Very informative video!. How can you play 2x speed SID files though?
Thanks, you can just call the play routine twice per screen update. e.g. jsr x003 twice.
Cheers,
Jake
@@TheStuffMade Thank you! Can you please elaborate on that more? I can't seem to make it work :(
Great explanation. Thanks
Very cool thanks! I haven't looked at the code for SID music...but is it pretty much accepted that there's a standard optimised way of paying music and all SID files use same method? Or does it vary from file to file?
Thanks, the SID player code is typically different for each piece of music, in most cases the player code is generated to be part of the music instead of having separate player code and music data. However the approach is depends on what tracker the music was composed in. SID music isn't very standardized.
Cheers,
Jake
excellent work
Really nice explained thank you!!. What about to fade down the volumen of the sid? it's that possible?
Could you please make a video on the movement of the sprites at the start of Episode 3? I am trying to make a loop to move my sprites in a cool way, but get stuck when trying to figure out the loop structure.
Would love to see the code you wrote for that movement if you could share it also.
Guess you had to deal with badlines and stable raster techinques to achieve that results..
Indeed, the way I usually do it is to have a delay table, on PAL it's easy you can use the values 8,8,8,8,8,8,8,1 so you do 8 delays on normal lines and then a single delay on the lines when the VIC chip is making the 6510 CPU sleep while it's accessing the memory.
Cheers,
Jake
Great video, so good. I have tried to add this example to my code but it isn't allowing me to enter the loop that looks for a keypress. I entered the loop where it says to do this, and the code has largely been untouched from your example. Not sure what I am doing wrong. HELP!
Hi James, did you try download the example project and run it? Does that work for you?
Keep in mind when the interrupt code uses JMP $EA81 it will not scan for keyboard input. However you can change one of the interrupt returns to JMP $EA31, then it will include a keyboard scan.
Also keep in mind if you want to return to the basic prompt then you should remove the custom interrupt code first by restoring the pointers otherwise it will likely crash.
Cheers,
Jake
Nice!
Shouldn't SEI enable interrupts and CLI disable or is it inverted on 6510 in contrast to Arduino?
The Arduino macros are inverted compared to the 6502/6510 instructions.
Cheers,
Jake
@@TheStuffMade That makes it a lot of confusing.
what are those addresses $0314 and $0315 ? Who defined these addresses to have anything to do with "raster lines" ?! It aint any VIC2 nor CIA/VIA (hardware) registers. So whats happening there and why (or of whom).
As I describe in the video $0314 and $0315 are interrupt pointers/vectors. Whenever an interrupt occurs the code these addresses are pointing to will be executed, this is not specific for raster interrupts, it's for all maskable interrupts. These addresses are controlled by the KERNAL. If you bank switch the KERNAL out then you need to use $fffe and $ffff instead (these are the actual 6510 pointer for interrupts), however in this case you have to save and restore all the registers yourself and return with the RTI instruction.
Cheers,
Jake
Meanwhile I found an excellent documentation explaining this. While there can only be one single real (hard wired) interrupt vector on a 6510/6502 CPU at $fffe, the makers of the Kernel ROM designed in a "hook" to intercept the regular ROM ISR with user code. The users ISR jump address therefore is looked up at $0314 and $0315 and jumped to.