Move raster interrupt into assembly file. Set as an interruptor to
bypass C stuff.
This commit is contained in:
parent
689854ffab
commit
690f50c9f4
2 changed files with 282 additions and 214 deletions
273
src/main.c
273
src/main.c
|
@ -8,8 +8,6 @@
|
||||||
#include "c64.h"
|
#include "c64.h"
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
|
||||||
#define IRQ_STACK_SIZE 128
|
|
||||||
|
|
||||||
extern void updatepalntsc(void);
|
extern void updatepalntsc(void);
|
||||||
|
|
||||||
/* Check if system is PAL
|
/* Check if system is PAL
|
||||||
|
@ -18,16 +16,9 @@ void pal_system(void) {
|
||||||
updatepalntsc();
|
updatepalntsc();
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned char* irq_stack;
|
|
||||||
|
|
||||||
#define SCREEN_LAST_RASTER SCREEN_SPRITE_BORDER_Y_START + SCREEN_BITMAP_HEIGHT
|
|
||||||
#define SPRITE_BUFFER_LINE_COUNT 8
|
|
||||||
#define SPRITE_BUFFER_LINE_HEIGHT (SCREEN_BITMAP_HEIGHT / SPRITE_BUFFER_LINE_COUNT)
|
|
||||||
#define SCREEN_FIRST_RASTER SCREEN_SPRITE_BORDER_Y_START - SPRITE_BUFFER_LINE_HEIGHT
|
|
||||||
|
|
||||||
/** Disable the IO page
|
/** Disable the IO page
|
||||||
*/
|
*/
|
||||||
void __fastcall__ hide_io(void) {
|
void hide_io(void) {
|
||||||
*(unsigned char *)CIA1_CRA &= ~CIA1_CR_START_STOP;
|
*(unsigned char *)CIA1_CRA &= ~CIA1_CR_START_STOP;
|
||||||
|
|
||||||
*(unsigned char *)CPU_PORT &= ~CPU_PORT_BANK_IO_VISIBLE_CHARACTER_ROM_INVISIBLE;
|
*(unsigned char *)CPU_PORT &= ~CPU_PORT_BANK_IO_VISIBLE_CHARACTER_ROM_INVISIBLE;
|
||||||
|
@ -35,7 +26,7 @@ void __fastcall__ hide_io(void) {
|
||||||
|
|
||||||
/** Enable the IO page
|
/** Enable the IO page
|
||||||
*/
|
*/
|
||||||
void __fastcall__ show_io(void) {
|
void show_io(void) {
|
||||||
*(unsigned char *)CPU_PORT |= CPU_PORT_BANK_IO_VISIBLE_CHARACTER_ROM_INVISIBLE;
|
*(unsigned char *)CPU_PORT |= CPU_PORT_BANK_IO_VISIBLE_CHARACTER_ROM_INVISIBLE;
|
||||||
|
|
||||||
*(unsigned char *)CIA1_CRA |= CIA1_CR_START_STOP;
|
*(unsigned char *)CIA1_CRA |= CIA1_CR_START_STOP;
|
||||||
|
@ -71,7 +62,7 @@ void screen_init (bool clear) {
|
||||||
VIC.addr |= ((CHARACTER_START % VIC_BANK_SIZE) / VIC_VIDEO_ADR_CHAR_DIVISOR) << 1;
|
VIC.addr |= ((CHARACTER_START % VIC_BANK_SIZE) / VIC_VIDEO_ADR_CHAR_DIVISOR) << 1;
|
||||||
|
|
||||||
// Fix HLINE IRQ
|
// Fix HLINE IRQ
|
||||||
VIC.rasterline = SCREEN_FIRST_RASTER;
|
VIC.rasterline = 0xff;
|
||||||
VIC.ctrl1 &= ~VIC_CTRL1_HLINE_MSB;
|
VIC.ctrl1 &= ~VIC_CTRL1_HLINE_MSB;
|
||||||
|
|
||||||
// Switch off bitmap mode
|
// Switch off bitmap mode
|
||||||
|
@ -95,20 +86,12 @@ void screen_init (bool clear) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool is_pal = false;
|
bool is_pal = false;
|
||||||
|
bool irq_setup_done = false;
|
||||||
unsigned char setup_irq_handler(unsigned char (*handler)(void)) {
|
unsigned char setup_irq_handler(void) {
|
||||||
if(!irq_stack) {
|
irq_setup_done = true;
|
||||||
if(!(irq_stack = malloc(IRQ_STACK_SIZE))) {
|
|
||||||
return EXIT_FAILURE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
set_irq(handler, irq_stack, IRQ_STACK_SIZE);
|
|
||||||
|
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned char raster_clock = 0;
|
|
||||||
unsigned int game_clock = 0;
|
unsigned int game_clock = 0;
|
||||||
unsigned int last_updated = 0;
|
unsigned int last_updated = 0;
|
||||||
|
|
||||||
|
@ -237,25 +220,31 @@ void set_sprite_graphic(sprite_handle handle, unsigned char sheet_index) {
|
||||||
set_sprite_pointer(handle, ((unsigned int)(&s->sprites[sheet_index]) % VIC_BANK_SIZE) / VIC_SPR_SIZE);
|
set_sprite_pointer(handle, ((unsigned int)(&s->sprites[sheet_index]) % VIC_BANK_SIZE) / VIC_SPR_SIZE);
|
||||||
}
|
}
|
||||||
|
|
||||||
void set_sprite_position(sprite_handle a, unsigned int x, unsigned char y) {
|
void set_sprite_x(sprite_handle a, unsigned int x) {
|
||||||
static sprite_handle *start_handle, *comp_handle, *current_handle;
|
static sprite_handle arg;
|
||||||
static sprite_handle arg, comp;
|
|
||||||
static unsigned char index, last_index, hi_mask, comp_y, yarg;
|
|
||||||
static bool direction;
|
|
||||||
|
|
||||||
yarg = y;
|
|
||||||
arg = a;
|
arg = a;
|
||||||
|
|
||||||
comp_y = arg->lo_y;
|
|
||||||
hi_mask = 1<<(index%VIC_SPR_COUNT);
|
|
||||||
if(x>>8) {
|
if(x>>8) {
|
||||||
arg->hi_x = hi_mask;
|
arg->hi_x = arg->ena;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
arg->hi_x = 0;
|
arg->hi_x = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
arg->lo_x = (unsigned char)x;
|
arg->lo_x = (unsigned char)x;
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_sprite_y(sprite_handle a, unsigned char y) {
|
||||||
|
static sprite_handle *start_handle, *comp_handle, *current_handle;
|
||||||
|
static sprite_handle arg, comp;
|
||||||
|
static unsigned char index, last_index, hi_mask, comp_y, yarg;
|
||||||
|
static bool direction, is_last;
|
||||||
|
|
||||||
|
yarg = y;
|
||||||
|
arg = a;
|
||||||
|
|
||||||
|
comp_y = arg->lo_y;
|
||||||
if(yarg == comp_y) {
|
if(yarg == comp_y) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -288,19 +277,18 @@ void set_sprite_position(sprite_handle a, unsigned int x, unsigned char y) {
|
||||||
do {
|
do {
|
||||||
if(direction) {
|
if(direction) {
|
||||||
comp_handle = current_handle + 1;
|
comp_handle = current_handle + 1;
|
||||||
|
comp = *comp_handle;
|
||||||
|
is_last = (yarg <= comp->lo_y
|
||||||
|
|| index == last_index);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
comp_handle = current_handle - 1;
|
comp_handle = current_handle - 1;
|
||||||
|
comp = *comp_handle;
|
||||||
|
is_last = (comp->lo_y <= yarg
|
||||||
|
|| index == 0);
|
||||||
}
|
}
|
||||||
comp = *comp_handle;
|
|
||||||
if((
|
if(is_last) {
|
||||||
direction
|
|
||||||
? (yarg <= comp->lo_y
|
|
||||||
|| index == last_index)
|
|
||||||
: (comp->lo_y <= yarg
|
|
||||||
|| index == 0)
|
|
||||||
)
|
|
||||||
) {
|
|
||||||
if(current_handle == start_handle) {
|
if(current_handle == start_handle) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -326,7 +314,7 @@ void set_sprite_position(sprite_handle a, unsigned int x, unsigned char y) {
|
||||||
__asm__("sbc #%b", offsetof(struct sprite_data, multi));
|
__asm__("sbc #%b", offsetof(struct sprite_data, multi));
|
||||||
__asm__("bne loop");
|
__asm__("bne loop");
|
||||||
|
|
||||||
if(comp == arg) {
|
if(is_last) {
|
||||||
*current_handle = comp;
|
*current_handle = comp;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -336,33 +324,37 @@ void set_sprite_position(sprite_handle a, unsigned int x, unsigned char y) {
|
||||||
|
|
||||||
if(direction) {
|
if(direction) {
|
||||||
index++;
|
index++;
|
||||||
}
|
|
||||||
else {
|
|
||||||
index--;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(direction) {
|
|
||||||
current_handle++;
|
current_handle++;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
index--;
|
||||||
current_handle--;
|
current_handle--;
|
||||||
}
|
}
|
||||||
|
|
||||||
} while (true);
|
} while (true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void discard_sprite(sprite_handle handle) {
|
void discard_sprite(sprite_handle handle) {
|
||||||
set_sprite_position(handle, 0xff, 0xff);
|
|
||||||
sprite_count--;
|
sprite_count--;
|
||||||
_sprite_list[sprite_count] = NULL;
|
_sprite_list[sprite_count] = NULL;
|
||||||
|
set_sprite_x(handle, 0xff);
|
||||||
|
set_sprite_y(handle, 0xff);
|
||||||
}
|
}
|
||||||
|
|
||||||
sprite_handle new_sprite(bool dbl) {
|
sprite_handle new_sprite(bool dbl) {
|
||||||
static sprite_handle handle;
|
static sprite_handle handle;
|
||||||
|
static unsigned char hi_mask;
|
||||||
|
|
||||||
handle = &_sprite_pool[sprite_count];
|
handle = &_sprite_pool[sprite_count];
|
||||||
_sprite_list[sprite_count] = handle;
|
_sprite_list[sprite_count] = handle;
|
||||||
handle->dbl = dbl<<(sprite_count%VIC_SPR_COUNT);
|
hi_mask = 1<<(sprite_count%VIC_SPR_COUNT);
|
||||||
handle->ena = 1<<(sprite_count%VIC_SPR_COUNT);
|
handle->ena = hi_mask;
|
||||||
|
if(dbl) {
|
||||||
|
handle->dbl = hi_mask;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
handle->dbl = 0;
|
||||||
|
}
|
||||||
handle->lo_x = 0xfe;
|
handle->lo_x = 0xfe;
|
||||||
handle->lo_y = 0xfe;
|
handle->lo_y = 0xfe;
|
||||||
sprite_count++;
|
sprite_count++;
|
||||||
|
@ -370,150 +362,6 @@ sprite_handle new_sprite(bool dbl) {
|
||||||
return handle;
|
return handle;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define SPR_POINTERS SCREEN_START + 0x3F8
|
|
||||||
|
|
||||||
unsigned char main_raster_irq(void) {
|
|
||||||
static unsigned char sprite_index = 0xff;
|
|
||||||
static unsigned char vic_sprite = 0;
|
|
||||||
static unsigned char current_y = 0;
|
|
||||||
static unsigned char new_y = 0;
|
|
||||||
static unsigned char hi_mask = 0;
|
|
||||||
static sprite_handle cs;
|
|
||||||
|
|
||||||
if(!(VIC.irr & VIC_IRQ_RASTER)) {
|
|
||||||
return IRQ_NOT_HANDLED;
|
|
||||||
}
|
|
||||||
|
|
||||||
VIC.irr |= VIC_IRQ_RASTER;
|
|
||||||
if(sprite_index == 0xff) {
|
|
||||||
sprite_index = 0;
|
|
||||||
vic_sprite = 0;
|
|
||||||
|
|
||||||
// NTSC frame skip
|
|
||||||
if(is_pal) {
|
|
||||||
game_clock++;
|
|
||||||
}
|
|
||||||
else if(++raster_clock < 6) {
|
|
||||||
game_clock++;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
raster_clock = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
cs = _sprite_list[sprite_index];
|
|
||||||
new_y = cs->lo_y;
|
|
||||||
|
|
||||||
do {
|
|
||||||
current_y = new_y;
|
|
||||||
|
|
||||||
hi_mask = ~(1<<vic_sprite);
|
|
||||||
|
|
||||||
#define himasker(dest) { \
|
|
||||||
__asm__("lda %w", dest); \
|
|
||||||
__asm__("and %v", hi_mask); \
|
|
||||||
__asm__("ora (ptr1),Y"); \
|
|
||||||
__asm__("sta %w", dest); \
|
|
||||||
}
|
|
||||||
|
|
||||||
__asm__("lda %v", cs);
|
|
||||||
__asm__("ldx %v+1", cs);
|
|
||||||
__asm__("sta ptr1");
|
|
||||||
__asm__("stx ptr1+1");
|
|
||||||
__asm__("ldy #%b", offsetof(struct sprite_data, color));
|
|
||||||
|
|
||||||
__asm__("ldx %v", vic_sprite);
|
|
||||||
|
|
||||||
__asm__("lda (ptr1),Y");
|
|
||||||
__asm__("sta %w,X", VIC_SPR0_COLOR);
|
|
||||||
|
|
||||||
__asm__("iny");
|
|
||||||
__asm__("lda (ptr1),Y");
|
|
||||||
__asm__("sta %w,X", SPR_POINTERS);
|
|
||||||
|
|
||||||
__asm__("txa");
|
|
||||||
__asm__("asl");
|
|
||||||
__asm__("tax");
|
|
||||||
__asm__("iny");
|
|
||||||
__asm__("lda (ptr1),Y");
|
|
||||||
__asm__("sta %w,X", VIC_SPR0_X);
|
|
||||||
|
|
||||||
__asm__("iny");
|
|
||||||
__asm__("lda (ptr1),Y");
|
|
||||||
__asm__("sta %w,X", VIC_SPR0_Y);
|
|
||||||
__asm__("tax");
|
|
||||||
__asm__("inx");
|
|
||||||
__asm__("stx %w", VIC_HLINE);
|
|
||||||
|
|
||||||
__asm__("iny");
|
|
||||||
himasker(VIC_SPR_ENA);
|
|
||||||
|
|
||||||
__asm__("iny");
|
|
||||||
himasker(VIC_SPR_HI_X);
|
|
||||||
|
|
||||||
__asm__("iny");
|
|
||||||
himasker(VIC_SPR_EXP_X);
|
|
||||||
__asm__("sta %w", VIC_SPR_EXP_Y);
|
|
||||||
|
|
||||||
__asm__("iny");
|
|
||||||
himasker(VIC_SPR_MCOLOR);
|
|
||||||
|
|
||||||
vic_sprite++;
|
|
||||||
if(vic_sprite >= VIC_SPR_COUNT) {
|
|
||||||
vic_sprite = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// sprite_index++
|
|
||||||
__asm__("ldx %v", sprite_index);
|
|
||||||
__asm__("inx");
|
|
||||||
__asm__("txa");
|
|
||||||
|
|
||||||
// if(sprite_index == sprite_count)
|
|
||||||
__asm__("cmp %v", sprite_count);
|
|
||||||
|
|
||||||
// else
|
|
||||||
__asm__("bne moarcs");
|
|
||||||
|
|
||||||
// then
|
|
||||||
__asm__("lda #$ff");
|
|
||||||
__asm__("sta %v", sprite_index);
|
|
||||||
__asm__("sta %w", VIC_HLINE);
|
|
||||||
return IRQ_HANDLED;
|
|
||||||
|
|
||||||
// store the new sprite index
|
|
||||||
__asm__("moarcs:");
|
|
||||||
__asm__("sta %v", sprite_index);
|
|
||||||
|
|
||||||
__asm__("asl");
|
|
||||||
__asm__("tax");
|
|
||||||
|
|
||||||
// cs = _sprite_list[sprite_index]
|
|
||||||
__asm__("ldy %v,X", _sprite_list);
|
|
||||||
__asm__("sty %v", cs);
|
|
||||||
__asm__("sty ptr1");
|
|
||||||
|
|
||||||
__asm__("inx");
|
|
||||||
__asm__("ldy %v,X", _sprite_list);
|
|
||||||
__asm__("sty %v+1", cs);
|
|
||||||
__asm__("sty ptr1+1");
|
|
||||||
|
|
||||||
// new_y = cs->lo_y
|
|
||||||
__asm__("ldy #%b", offsetof(struct sprite_data, lo_y));
|
|
||||||
__asm__("lda (ptr1),Y");
|
|
||||||
__asm__("sta %v", new_y);
|
|
||||||
|
|
||||||
// if new_y >= current_y + buffer
|
|
||||||
__asm__("lda %v", current_y);
|
|
||||||
__asm__("clc");
|
|
||||||
__asm__("adc #%b", VIC_SPR_HEIGHT - 2);
|
|
||||||
__asm__("cmp %v", new_y);
|
|
||||||
__asm__("bcc exitloop");
|
|
||||||
} while(true);
|
|
||||||
__asm__("exitloop: ");
|
|
||||||
|
|
||||||
return IRQ_HANDLED;
|
|
||||||
}
|
|
||||||
|
|
||||||
#define WAW_SPRITE_COUNT 9
|
#define WAW_SPRITE_COUNT 9
|
||||||
#define WAW_SPRITE_OFFSET 0
|
#define WAW_SPRITE_OFFSET 0
|
||||||
#define WAW_COLUMNS 3
|
#define WAW_COLUMNS 3
|
||||||
|
@ -536,7 +384,8 @@ struct waw {
|
||||||
typedef struct waw waw;
|
typedef struct waw waw;
|
||||||
|
|
||||||
void init_waw(waw* w) {
|
void init_waw(waw* w) {
|
||||||
static unsigned char i, j, x, y, sprite_x, sprite_y, idx;
|
static unsigned int x, sprite_x;
|
||||||
|
static unsigned char i, j, y, sprite_y, idx;
|
||||||
static waw* waw;
|
static waw* waw;
|
||||||
static sprite_handle sprite;
|
static sprite_handle sprite;
|
||||||
static sprite_handle* sprites;
|
static sprite_handle* sprites;
|
||||||
|
@ -556,10 +405,12 @@ void init_waw(waw* w) {
|
||||||
sprite = new_sprite(true);
|
sprite = new_sprite(true);
|
||||||
set_sprite_graphic(sprite, WAW_SPRITE_OFFSET + idx);
|
set_sprite_graphic(sprite, WAW_SPRITE_OFFSET + idx);
|
||||||
if(idx == WAW_MOUTHINDEX) {
|
if(idx == WAW_MOUTHINDEX) {
|
||||||
set_sprite_position(sprite, sprite_x, sprite_y + waw->mouth_offset);
|
set_sprite_x(sprite, sprite_x);
|
||||||
|
set_sprite_y(sprite, sprite_y + waw->mouth_offset);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
set_sprite_position(sprite, sprite_x, sprite_y);
|
set_sprite_x(sprite, sprite_x);
|
||||||
|
set_sprite_y(sprite, sprite_y);
|
||||||
}
|
}
|
||||||
sprites[idx] = sprite;
|
sprites[idx] = sprite;
|
||||||
idx++;
|
idx++;
|
||||||
|
@ -568,11 +419,10 @@ void init_waw(waw* w) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void update_waw(waw* w) {
|
void update_waw(waw* w) {
|
||||||
static unsigned int sprite_x;
|
static unsigned char y;
|
||||||
static unsigned char y, sprite_y;
|
|
||||||
static unsigned char idx;
|
static unsigned char idx;
|
||||||
static signed char change_y, mouth_offset;
|
static signed char change_y, mouth_offset;
|
||||||
static sprite_handle* current_sprite;
|
static sprite_handle* sprites;
|
||||||
static sprite_handle sprite;
|
static sprite_handle sprite;
|
||||||
static waw* waw;
|
static waw* waw;
|
||||||
waw = w;
|
waw = w;
|
||||||
|
@ -613,27 +463,22 @@ void update_waw(waw* w) {
|
||||||
|
|
||||||
waw->y = y + change_y;
|
waw->y = y + change_y;
|
||||||
|
|
||||||
current_sprite = waw->sprites;
|
sprites = waw->sprites;
|
||||||
for(idx = 0; idx < WAW_SPRITE_COUNT; idx++) {
|
for(idx = 0; idx < WAW_SPRITE_COUNT; idx++) {
|
||||||
sprite = *current_sprite;
|
sprite = sprites[idx];
|
||||||
((unsigned char*)&sprite_x)[0] = sprite->lo_x;
|
|
||||||
((unsigned char*)&sprite_x)[1] = sprite->hi_x;
|
|
||||||
sprite_y = sprite->lo_y + change_y;
|
|
||||||
// Mouth
|
// Mouth
|
||||||
if(idx == WAW_MOUTHINDEX) {
|
if(idx == WAW_MOUTHINDEX) {
|
||||||
set_sprite_position(sprite, sprite_x, current_sprite[-1]->lo_y + mouth_offset);
|
set_sprite_y(sprite, sprites[idx-1]->lo_y + mouth_offset);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
set_sprite_position(sprite, sprite_x, sprite_y);
|
set_sprite_y(sprite, sprite->lo_y + change_y);
|
||||||
}
|
}
|
||||||
|
|
||||||
current_sprite++;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned char main(void) {
|
unsigned char main(void) {
|
||||||
static unsigned char err;
|
static unsigned char err;
|
||||||
//static waw waw2 = {VIC_SPR_WIDTH * WAW_COLUMNS * 2,VIC_SPR_HEIGHT * 2,0,true,true};
|
static waw waw2 = {VIC_SPR_WIDTH * WAW_COLUMNS * 2,VIC_SPR_HEIGHT * 2,0,true,true};
|
||||||
static waw waw = {0,0,0,true,true};
|
static waw waw = {0,0,0,true,true};
|
||||||
|
|
||||||
updatepalntsc();
|
updatepalntsc();
|
||||||
|
@ -646,10 +491,10 @@ unsigned char main(void) {
|
||||||
|
|
||||||
init_sprite_pool();
|
init_sprite_pool();
|
||||||
init_waw(&waw);
|
init_waw(&waw);
|
||||||
//init_waw(&waw2);
|
init_waw(&waw2);
|
||||||
|
|
||||||
character_init(true);
|
character_init(true);
|
||||||
setup_irq_handler(&main_raster_irq);
|
setup_irq_handler();
|
||||||
screen_init(true);
|
screen_init(true);
|
||||||
|
|
||||||
do {
|
do {
|
||||||
|
@ -658,7 +503,7 @@ unsigned char main(void) {
|
||||||
}
|
}
|
||||||
|
|
||||||
update_waw(&waw);
|
update_waw(&waw);
|
||||||
//update_waw(&waw2);
|
update_waw(&waw2);
|
||||||
|
|
||||||
last_updated++;
|
last_updated++;
|
||||||
} while(true);
|
} while(true);
|
||||||
|
|
223
src/main_raster_irq_asm.s
Normal file
223
src/main_raster_irq_asm.s
Normal file
|
@ -0,0 +1,223 @@
|
||||||
|
.macpack longbranch
|
||||||
|
.import __sprite_list, _irq_setup_done, _is_pal, _game_clock, _sprite_count, _main_raster_irq
|
||||||
|
.importzp ptr1
|
||||||
|
.include "c64.inc"
|
||||||
|
.interruptor raster_irq, 2
|
||||||
|
|
||||||
|
.define IRQ_NOT_HANDLED #$00
|
||||||
|
.define IRQ_HANDLED #$01
|
||||||
|
|
||||||
|
.define VIC_IRQ_RASTER #$01
|
||||||
|
|
||||||
|
; FIXME
|
||||||
|
.define SPR_POINTERS $C000+$3F8
|
||||||
|
|
||||||
|
.define VIC_SPR_COUNT #$8
|
||||||
|
.define VIC_SPR_HEIGHT #$21
|
||||||
|
|
||||||
|
|
||||||
|
; ARG A = sprite index
|
||||||
|
; SETS ptr1 and current_sprite to sprite at index in list
|
||||||
|
; SETS A and new_y to sprite's y value
|
||||||
|
.macro get_next_sprite
|
||||||
|
asl
|
||||||
|
tax
|
||||||
|
|
||||||
|
ldy __sprite_list,X
|
||||||
|
sty current_sprite
|
||||||
|
sty ptr1
|
||||||
|
|
||||||
|
inx
|
||||||
|
ldy __sprite_list,X
|
||||||
|
sty current_sprite+1
|
||||||
|
sty ptr1+1
|
||||||
|
|
||||||
|
ldy #$03 ; FIXME offsetof(lo_y)
|
||||||
|
lda (ptr1),Y
|
||||||
|
sta new_y
|
||||||
|
.endmacro
|
||||||
|
|
||||||
|
.macro himasker dest
|
||||||
|
lda dest
|
||||||
|
and hi_mask
|
||||||
|
ora (ptr1),Y
|
||||||
|
sta dest
|
||||||
|
.endmacro
|
||||||
|
|
||||||
|
.segment "DATA"
|
||||||
|
ptr1_save: .res 2
|
||||||
|
|
||||||
|
sprite_index: .byte $ff
|
||||||
|
vic_sprite: .byte $00
|
||||||
|
current_y: .byte $00
|
||||||
|
new_y: .byte $00
|
||||||
|
hi_mask: .byte $00
|
||||||
|
current_sprite: .res 2
|
||||||
|
raster_clock: .byte $06
|
||||||
|
|
||||||
|
.segment "CODE"
|
||||||
|
|
||||||
|
.proc main_raster_irq
|
||||||
|
; Make sure this is a raster interrupt and we're ready
|
||||||
|
lda _irq_setup_done
|
||||||
|
jeq unhandled
|
||||||
|
lda VIC_IRQ_RASTER
|
||||||
|
bit VIC_IRR
|
||||||
|
jeq unhandled
|
||||||
|
|
||||||
|
; set the flag so we know we've handled it
|
||||||
|
ora VIC_IRR
|
||||||
|
sta VIC_IRR
|
||||||
|
|
||||||
|
; if we're at the beginning of the sprite loop, initialize the variables
|
||||||
|
lda sprite_index
|
||||||
|
cmp #$ff
|
||||||
|
bne sprite_index_updated
|
||||||
|
lda #$00
|
||||||
|
sta sprite_index
|
||||||
|
sta vic_sprite
|
||||||
|
|
||||||
|
; If we're PAL, the game clock is already 50hz
|
||||||
|
ldx _is_pal
|
||||||
|
bne update_game_clock
|
||||||
|
|
||||||
|
; If we're NTSC, skip every 6th frame
|
||||||
|
dec raster_clock
|
||||||
|
bne update_game_clock
|
||||||
|
|
||||||
|
; Reset the raster clock
|
||||||
|
ldx #$06
|
||||||
|
stx raster_clock
|
||||||
|
jmp sprite_index_updated
|
||||||
|
update_game_clock:
|
||||||
|
inc _game_clock
|
||||||
|
bne sprite_index_updated
|
||||||
|
inc _game_clock+1
|
||||||
|
sprite_index_updated:
|
||||||
|
|
||||||
|
get_next_sprite
|
||||||
|
|
||||||
|
sprite_update_loop:
|
||||||
|
; set the current sprite y value
|
||||||
|
lda new_y
|
||||||
|
sta current_y
|
||||||
|
|
||||||
|
lda #$01
|
||||||
|
ldx vic_sprite
|
||||||
|
beq done
|
||||||
|
shift:
|
||||||
|
asl
|
||||||
|
dex
|
||||||
|
bne shift
|
||||||
|
done:
|
||||||
|
eor #$ff
|
||||||
|
sta hi_mask
|
||||||
|
|
||||||
|
; prep the pointer for struct access
|
||||||
|
lda current_sprite
|
||||||
|
ldx current_sprite+1
|
||||||
|
sta ptr1
|
||||||
|
stx ptr1+1
|
||||||
|
ldy #$00 ; FIXME offsetof(color)
|
||||||
|
|
||||||
|
; store color and pointer into arrays
|
||||||
|
ldx vic_sprite
|
||||||
|
|
||||||
|
lda (ptr1),y
|
||||||
|
sta VIC_SPR0_COLOR,X
|
||||||
|
|
||||||
|
iny
|
||||||
|
lda (ptr1),y
|
||||||
|
sta SPR_POINTERS,X
|
||||||
|
|
||||||
|
; inc vic_sprite for next loop
|
||||||
|
inx
|
||||||
|
txa
|
||||||
|
cmp VIC_SPR_COUNT
|
||||||
|
bne write_vic_sprite
|
||||||
|
lda #$00
|
||||||
|
write_vic_sprite:
|
||||||
|
sta vic_sprite
|
||||||
|
|
||||||
|
; Double the previous value of vic_sprite and use it to set the x and y
|
||||||
|
dex
|
||||||
|
|
||||||
|
txa
|
||||||
|
asl
|
||||||
|
tax
|
||||||
|
iny
|
||||||
|
lda (ptr1),y
|
||||||
|
sta VIC_SPR0_X,X
|
||||||
|
|
||||||
|
iny
|
||||||
|
lda (ptr1),Y
|
||||||
|
sta VIC_SPR0_Y,x
|
||||||
|
tax
|
||||||
|
inx
|
||||||
|
stx VIC_HLINE
|
||||||
|
|
||||||
|
iny
|
||||||
|
himasker VIC_SPR_ENA
|
||||||
|
|
||||||
|
iny
|
||||||
|
himasker VIC_SPR_HI_X
|
||||||
|
|
||||||
|
iny
|
||||||
|
himasker VIC_SPR_EXP_X
|
||||||
|
sta VIC_SPR_EXP_Y
|
||||||
|
|
||||||
|
iny
|
||||||
|
himasker VIC_SPR_MCOLOR
|
||||||
|
|
||||||
|
; inc sprite_index
|
||||||
|
ldx sprite_index
|
||||||
|
inx
|
||||||
|
txa
|
||||||
|
|
||||||
|
cmp _sprite_count
|
||||||
|
bne moarcs
|
||||||
|
|
||||||
|
; if the index equals the count, reset
|
||||||
|
lda #$ff
|
||||||
|
sta sprite_index
|
||||||
|
sta VIC_HLINE
|
||||||
|
jmp end_sprite_update_loop
|
||||||
|
moarcs:
|
||||||
|
sta sprite_index
|
||||||
|
|
||||||
|
get_next_sprite
|
||||||
|
|
||||||
|
; if new_y >= current_y + buffer
|
||||||
|
lda current_y
|
||||||
|
clc
|
||||||
|
adc VIC_SPR_HEIGHT-$2
|
||||||
|
cmp new_y
|
||||||
|
jcs sprite_update_loop
|
||||||
|
end_sprite_update_loop:
|
||||||
|
|
||||||
|
handled:
|
||||||
|
lda IRQ_HANDLED
|
||||||
|
rts
|
||||||
|
|
||||||
|
unhandled:
|
||||||
|
lda IRQ_NOT_HANDLED
|
||||||
|
rts
|
||||||
|
.endproc
|
||||||
|
|
||||||
|
.proc raster_irq
|
||||||
|
lda ptr1
|
||||||
|
ldx ptr1+1
|
||||||
|
sta ptr1_save
|
||||||
|
stx ptr1_save+1
|
||||||
|
|
||||||
|
clc
|
||||||
|
jsr main_raster_irq
|
||||||
|
; mark interrupt as handled / unhandled
|
||||||
|
lsr
|
||||||
|
|
||||||
|
lda ptr1_save
|
||||||
|
ldx ptr1_save+1
|
||||||
|
sta ptr1
|
||||||
|
stx ptr1+1
|
||||||
|
rts
|
||||||
|
.endproc
|
Loading…
Add table
Reference in a new issue