1
0
mirror of https://gitlab.com/camelot/kickc.git synced 2024-06-03 07:29:37 +00:00
kickc/src/test/kc/complex/new_30_years_low_resolution/new_30_years_low_resolution.c
2024-01-02 19:21:16 +01:00

145 lines
3.7 KiB
C

// The Demo collects the parts and handles overall control
#pragma target(c64)
#pragma link("demo.ld")
#pragma zp_reserve(0xfa..0xfb) // Reserved for music player
#pragma interrupt(hardware_clobber)
#pragma emulator("C64Debugger")
#include <c64.h>
#include <6502.h>
#include <string.h>
#include "demo.h"
#include "byteboozer.h"
#include "part1-happynewyear.c"
#include "part2-swingplex.c"
#pragma code_seg(Code)
#pragma data_seg(Data)
char* const DEMO_MUSIC = (char*)0xAC00;
// Pointer to procedure
typedef void (*PROC_PTR)(void);
// Pointer to the music init routine
PROC_PTR const musicInit = (PROC_PTR) DEMO_MUSIC;
// Pointer to the music play routine
PROC_PTR const musicPlay = (PROC_PTR) DEMO_MUSIC+3;
#pragma data_seg(InitDemo)
// SID tune
char DEMO_MUSIC_CRUNCHED[] = kickasm(resource "do-it-again-$AC00-$FA-8580.sid", uses DEMO_MUSIC) {{
.modify B2() {
.pc = DEMO_MUSIC "MUSIC"
.const music = LoadSid("do-it-again-$AC00-$FA-8580.sid")
.fill music.size, music.getData(i)
}
}};
#pragma data_seg(Data)
void main() {
// Initialize the demo - start the IRQ
demo_init();
// Decrunch music
byteboozer_decrunch(DEMO_MUSIC_CRUNCHED);
// Init music
asm { lda #0 }
(*musicInit)();
// Initialize the demo - start the IRQ
demo_start();
// Initialize Part 1 (Revealing "Happy New Year" logo)
part1_init();
// Start part 1 at 0:04,5
while(demo_frame_count<5*50) ;
// Run Part 1 (Revealing "Happy New Year" logo)
part1_run();
// Initialize part 2
part2_init();
// Wait for the right place to start part 2
while(demo_frame_count<16*50) ;
// Disable sparkler
sparkler_active = 0;
// Run part 2
part2_run();
for(;;) ;
}
// Initialize demo code.
// Can be called multiple times!
// Setting IRQ to the "demo" IRQ running outside the parts and
// Setting memory to IO + RAM (no kernal/basic)
void demo_init() {
SEI();
// Disable kernal & basic
*PROCPORT_DDR = PROCPORT_DDR_MEMORY_MASK;
*PROCPORT = PROCPORT_RAM_IO;
// Disable CIA 1 Timer IRQ
CIA1->INTERRUPT = CIA_INTERRUPT_CLEAR_ALL;
// Acknowledge any timer IRQ
asm { lda CIA1_INTERRUPT }
// Acknowledge any VIC IRQ
*IRQ_STATUS = 0x0f;
}
// Start the demo IRQ. Can be called multiple times!
// Setting IRQ to the "demo" IRQ running outside the parts and
// Setting memory to IO + RAM (no kernal/basic)
void demo_start() {
demo_init();
// Set raster line to 0x00
*VICII_CONTROL1 &= 0x7f;
*RASTER = 0;
// Set the IRQ routine
*HARDWARE_IRQ = &irq_demo;
// Enable Raster Interrupt
*IRQ_ENABLE = IRQ_RASTER;
CLI();
}
// Counts total demo frames
volatile unsigned int demo_frame_count = 0;
// Work to be performed every frame while the demo runs
// Assumes that I/O is enabled
void demo_work() {
// Increase frame count
demo_frame_count++;
// Play music
(*musicPlay)();
// Animate the sparkler
if(sparkler_active)
sparkler_anim();
}
// Is the sparkler active
volatile char sparkler_active = 0;
// The sparkler sprite idx
volatile char sparkler_idx = 0;
// Animate the sparkler sprite
void sparkler_anim() {
if(++sparkler_idx==30) sparkler_idx=0;
P1_SCREEN_SPRITE_PTRS[0] = toSpritePtr(P1_SPRITES)+sparkler_idx/2;
}
// IRQ running during between parts
__interrupt void irq_demo() {
// Remember processor port value
*PROCPORT_DDR = PROCPORT_DDR_MEMORY_MASK;
char port_value = *PROCPORT;
// Enable IO
*PROCPORT_DDR = PROCPORT_DDR_MEMORY_MASK;
*PROCPORT = PROCPORT_RAM_IO;
// Perform any demo work
demo_work();
// Acknowledge the IRQ
*IRQ_STATUS = IRQ_RASTER;
// Restore processor port value
*PROCPORT_DDR = PROCPORT_DDR_MEMORY_MASK;
*PROCPORT = port_value;
}