mirror of
https://github.com/sehugg/8bitworkshop.git
synced 2024-11-26 10:49:17 +00:00
200 lines
4.0 KiB
C
200 lines
4.0 KiB
C
|
|
#include <string.h>
|
|
|
|
#include "scrolling.h"
|
|
|
|
sbyte scroll_fine_x;
|
|
sbyte scroll_fine_y;
|
|
byte origin_x;
|
|
byte origin_y;
|
|
byte* hidbuf;
|
|
byte* visbuf;
|
|
byte colorbuf[COLS*ROWS];
|
|
byte swap_needed;
|
|
byte copy_needed;
|
|
|
|
//
|
|
|
|
void scroll_swap() {
|
|
byte* tmp;
|
|
// swap hidden and visible buffers
|
|
tmp = hidbuf;
|
|
hidbuf = visbuf;
|
|
visbuf = tmp;
|
|
// set VIC bank address
|
|
SET_VIC_SCREEN((word)visbuf);
|
|
}
|
|
|
|
void copy_color_ram_slow() {
|
|
memcpy(COLOR_RAM, colorbuf, COLS*ROWS);
|
|
}
|
|
|
|
void copy_color_ram_fast() {
|
|
// fast copy loop for upper 1/2 of color ram
|
|
asm("ldy #0");
|
|
asm("@loop:");
|
|
asm("lda %v,y", colorbuf);
|
|
asm("sta $d800,y");
|
|
asm("lda %v + $100,y", colorbuf);
|
|
asm("sta $d900,y");
|
|
asm("iny");
|
|
asm("bne @loop");
|
|
// second loop for lower 1/2 of color ram
|
|
asm("@loop2:");
|
|
asm("lda %v + $200,y", colorbuf);
|
|
asm("sta $da00,y");
|
|
asm("lda %v + $300,y", colorbuf);
|
|
asm("sta $db00,y");
|
|
asm("@skip: iny");
|
|
asm("bne @loop2");
|
|
}
|
|
|
|
void copy_to_hidden_buffer_slow() {
|
|
memcpy(hidbuf, visbuf, COLS*ROWS);
|
|
}
|
|
|
|
void copy_to_hidden_buffer_fast() {
|
|
// self-modifying code
|
|
asm("ldy %v+1", visbuf);
|
|
asm("sty @loop+2+6*0");
|
|
asm("iny");
|
|
asm("sty @loop+2+6*1");
|
|
asm("iny");
|
|
asm("sty @loop+2+6*2");
|
|
asm("iny");
|
|
asm("sty @skip-1-3");
|
|
asm("ldy %v+1", hidbuf);
|
|
asm("sty @loop+5+6*0");
|
|
asm("iny");
|
|
asm("sty @loop+5+6*1");
|
|
asm("iny");
|
|
asm("sty @loop+5+6*2");
|
|
asm("iny");
|
|
asm("sty @skip-1");
|
|
// fast copy loop
|
|
asm("ldy #0");
|
|
asm("@loop:");
|
|
asm("lda $8000,y");
|
|
asm("sta $8000,y");
|
|
asm("lda $8100,y");
|
|
asm("sta $8100,y");
|
|
asm("lda $8200,y");
|
|
asm("sta $8200,y");
|
|
asm("cpy #$e8");
|
|
asm("bcs @skip");
|
|
asm("lda $8300,y");
|
|
asm("sta $8300,y");
|
|
asm("@skip: iny");
|
|
asm("bne @loop");
|
|
}
|
|
|
|
void copy_if_needed() {
|
|
if (copy_needed) {
|
|
copy_to_hidden_buffer_fast();
|
|
copy_needed = false;
|
|
}
|
|
}
|
|
|
|
void scroll_update() {
|
|
SET_SCROLL_X(scroll_fine_x);
|
|
SET_SCROLL_Y(scroll_fine_y);
|
|
if (swap_needed) {
|
|
scroll_swap();
|
|
copy_color_ram_fast();
|
|
swap_needed = false;
|
|
copy_needed = true;
|
|
} else {
|
|
copy_if_needed();
|
|
}
|
|
}
|
|
|
|
static void scroll_left() {
|
|
copy_if_needed();
|
|
memmove(hidbuf, hidbuf+1, COLS*ROWS-1);
|
|
memmove(colorbuf, colorbuf+1, COLS*ROWS-1);
|
|
++origin_x;
|
|
scroll_draw_column(COLS-1);
|
|
swap_needed = true;
|
|
}
|
|
|
|
static void scroll_up() {
|
|
copy_if_needed();
|
|
memmove(hidbuf, hidbuf+COLS, COLS*(ROWS-1));
|
|
memmove(colorbuf, colorbuf+COLS, COLS*(ROWS-1));
|
|
++origin_y;
|
|
scroll_draw_row(ROWS-1);
|
|
swap_needed = true;
|
|
}
|
|
|
|
static void scroll_right() {
|
|
copy_if_needed();
|
|
memmove(hidbuf+1, hidbuf, COLS*ROWS-1);
|
|
memmove(colorbuf+1, colorbuf, COLS*ROWS-1);
|
|
--origin_x;
|
|
scroll_draw_column(0);
|
|
swap_needed = true;
|
|
}
|
|
|
|
static void scroll_down() {
|
|
copy_if_needed();
|
|
memmove(hidbuf+COLS, hidbuf, COLS*(ROWS-1));
|
|
memmove(colorbuf+COLS, colorbuf, COLS*(ROWS-1));
|
|
--origin_y;
|
|
scroll_draw_row(0);
|
|
swap_needed = true;
|
|
}
|
|
|
|
void scroll_horiz(sbyte delta_x) {
|
|
scroll_fine_x += delta_x;
|
|
while (scroll_fine_x < 0) {
|
|
scroll_fine_x += 8;
|
|
scroll_left();
|
|
}
|
|
while (scroll_fine_x >= 8) {
|
|
scroll_fine_x -= 8;
|
|
scroll_right();
|
|
}
|
|
}
|
|
|
|
void scroll_vert(sbyte delta_y) {
|
|
scroll_fine_y += delta_y;
|
|
while (scroll_fine_y < 0) {
|
|
scroll_fine_y += 8;
|
|
scroll_up();
|
|
}
|
|
while (scroll_fine_y >= 8) {
|
|
scroll_fine_y -= 8;
|
|
scroll_down();
|
|
}
|
|
}
|
|
|
|
void scroll_xy(sbyte delta_x, sbyte delta_y) {
|
|
if (delta_x) scroll_horiz(delta_x);
|
|
if (delta_y) scroll_vert(delta_y);
|
|
}
|
|
|
|
void scroll_setup() {
|
|
scroll_fine_x = scroll_fine_y = 0;
|
|
origin_x = origin_y = 0;
|
|
swap_needed = true;
|
|
copy_needed = true;
|
|
|
|
// setup screen buffer addresses
|
|
hidbuf = (byte*) 0x8000;
|
|
visbuf = (byte*) 0x8400;
|
|
|
|
// copy existing screen contents to hidden buffer
|
|
memcpy(hidbuf, (byte*)0x400, COLS*ROWS);
|
|
// copy also to hidden buffer
|
|
memcpy(visbuf, hidbuf, COLS*ROWS);
|
|
|
|
// set VIC bank ($8000-$BFFF)
|
|
// https://www.c64-wiki.com/wiki/VIC_bank
|
|
SET_VIC_BANK(0x8000);
|
|
|
|
// set up 24 line / 38 column mode to hide edges
|
|
VIC.ctrl1 &= ~0x08; // 24 lines
|
|
VIC.ctrl2 &= ~0x08; // 38 columns
|
|
}
|
|
|