Add sprite multiplexer

This commit is contained in:
drmortalwombat 2021-12-29 20:07:13 +01:00
parent 80fea25916
commit 1fcc39acd5
20 changed files with 844 additions and 33 deletions

View File

@ -307,12 +307,11 @@ void rirq_sort(void)
{
byte ri = rasterIRQIndex[i];
byte rr = rasterIRQRows[ri];
byte j = i, rj = rasterIRQIndex[j - 1];
while (j > 0 && rr < rasterIRQRows[rj])
byte j = i, rj;
while (j > 0 && rr < rasterIRQRows[(rj = rasterIRQIndex[j - 1])])
{
rasterIRQIndex[j] = rj;
j--;
rj = rasterIRQIndex[j - 1]
}
rasterIRQIndex[j] = ri;
}

228
include/c64/sprites.c Normal file
View File

@ -0,0 +1,228 @@
#include "sprites.h"
#include "rasterirq.h"
static char * vspriteScreen;
void spr_init(char * screen)
{
vspriteScreen = screen + 0x3f8;
}
void spr_set(char sp, bool show, int xpos, int ypos, char image, char color, bool multi, bool xexpand, bool yexpand)
{
char m = 1 << sp;
if (show)
vic.spr_enable |= m;
else
vic.spr_enable &= ~m;
if (multi)
vic.spr_multi |= m;
else
vic.spr_multi &= ~m;
if (xexpand)
vic.spr_expand_x |= m;
else
vic.spr_expand_x &= ~m;
if (yexpand)
vic.spr_expand_y |= m;
else
vic.spr_expand_y &= ~m;
vic.spr_pos[sp].y = ypos;
vic.spr_pos[sp].x = xpos & 0xff;
if (xpos & 0x100)
vic.spr_msbx |= m;
else
vic.spr_msbx &= ~m;
vspriteScreen[sp] = image;
vic.spr_color[sp] = color;
}
void spr_show(char sp, bool show)
{
if (show)
vic.spr_enable |= 1 << sp;
else
vic.spr_enable &= ~(1 << sp);
}
void spr_move(char sp, int xpos, int ypos)
{
vic.spr_pos[sp].y = ypos;
vic.spr_pos[sp].x = xpos & 0xff;
if (xpos & 0x100)
vic.spr_msbx |= 1 << sp;
else
vic.spr_msbx &= ~(1 << sp);
}
void spr_image(char sp, char image)
{
vspriteScreen[sp] = image;
}
void spr_color(char sp, char color)
{
vic.spr_color[sp] = color;
}
#define NUM_SPRITES 16
static char vspriteYLow[NUM_SPRITES], vspriteXLow[NUM_SPRITES], vspriteXHigh[NUM_SPRITES];
static char vspriteImage[NUM_SPRITES], vspriteColor[NUM_SPRITES];
static char spriteOrder[16], spriteYPos[17];
static RIRQCode spirq[8], synch;
void vspr_init(char * screen)
{
vspriteScreen = screen + 0x3f8;
vic.spr_expand_x = 0;
vic.spr_expand_y = 0;
vic.spr_enable = 0xff;
for(int i=0; i<8; i++)
{
rirq_build(spirq + i, 5);
rirq_write(spirq + i, 0, &vic.spr_color[i], 0);
rirq_write(spirq + i, 1, &vic.spr_pos[i].x, 0);
rirq_write(spirq + i, 2, &vic.spr_pos[i].y, 0);
rirq_write(spirq + i, 3, &vspriteScreen[i], 0);
rirq_write(spirq + i, 4, &vic.spr_msbx, 0);
rirq_set(i, 80 + 8 * i, spirq + i);
}
rirq_build(&synch, 0);
rirq_set(8, 250, &synch);
for(int i=0; i<16; i++)
{
spriteOrder[i] = i;
vspriteYLow[i] = 0xff;
}
}
#pragma native(vspr_init)
void vspr_set(char sp, int xpos, int ypos, char image, char color)
{
vspriteYLow[sp] = (char)ypos;
vspriteXLow[sp] = (char)xpos;
vspriteXHigh[sp] = (char)(xpos >> 8);
vspriteImage[sp] = image;
vspriteColor[sp] = color;
if ((ypos & 0xff00 ) || (xpos & 0xfe00))
vspriteYLow[sp] = 0xff;
}
#pragma native(vspr_set)
void vspr_move(char sp, int xpos, int ypos)
{
char yp = (char)ypos;
if ((ypos & 0xff00 ) || (xpos & 0xfe00))
yp = 0xff;
vspriteYLow[sp] = yp;
vspriteXLow[sp] = (char)xpos;
vspriteXHigh[sp] = (char)(xpos >> 8);
}
void vspr_image(char sp, char image)
{
vspriteImage[sp] = image;
}
void vspr_color(char sp, char color)
{
vspriteColor[sp] = color;
}
void vspr_hide(char sp)
{
vspriteYLow[sp] = 0xff;
}
void vspr_sort(void)
{
spriteYPos[1] = vspriteYLow[spriteOrder[0]];
for(char i = 1; i<16; i++)
{
byte ri = spriteOrder[i];
byte rr = vspriteYLow[ri];
byte j = i, rj = spriteYPos[j];
while (rr < rj)
{
spriteYPos[j + 1] = rj;
spriteOrder[j] = spriteOrder[j - 1];
rj = spriteYPos[j - 1];
j--;
}
spriteOrder[j] = ri;
spriteYPos[j + 1] = rr;
}
}
#pragma native(vspr_sort)
void vspr_update(void)
{
char xymask = 0;
char * vsprs = vspriteScreen;
for(char ui=0; ui<8; ui++)
{
byte ri = spriteOrder[ui];
vic.spr_color[ui] = vspriteColor[ri];
vsprs[ui] = vspriteImage[ri];
xymask = ((unsigned)xymask | (vspriteXHigh[ri] << 8)) >> 1;
vic.spr_pos[ui].x = vspriteXLow[ri];
vic.spr_pos[ui].y = vspriteYLow[ri];
}
vic.spr_msbx = xymask;
if (spriteYPos[8] < 230)
{
char m = 1;
for(char ti=0; ti<8; ti++)
{
byte ri = spriteOrder[ti + 8];
xymask |= m;
if (!vspriteXHigh[ri])
xymask ^= m;
rirq_data(spirq + ti, 0, vspriteColor[ri]);
rirq_data(spirq + ti, 1, vspriteXLow[ri]);
rirq_data(spirq + ti, 2, vspriteYLow[ri]);
rirq_data(spirq + ti, 3, vspriteImage[ri]);
rirq_data(spirq + ti, 4, xymask);
rirq_move(ti, spriteYPos[ti + 1] + 21);
m <<= 1;
}
}
else
{
for(char ti=0; ti<8; ti++)
rirq_clear(ti);
}
}
#pragma native(vspr_update)

40
include/c64/sprites.h Normal file
View File

@ -0,0 +1,40 @@
#ifndef SPRITES_H
#define SPRITES_H
#include "vic.h"
void spr_init(char * screen);
void spr_set(char sp, bool show, int xpos, int ypos, char image, char color, bool multi, bool xexpand, bool yexpand);
inline void spr_show(char sp, bool show);
inline void spr_move(char sp, int xpos, int ypos);
inline void spr_image(char sp, char image);
inline void spr_color(char sp, char color);
void vspr_init(char * screen);
void vspr_set(char sp, int xpos, int ypos, char image, char color);
inline void vspr_move(char sp, int xpos, int ypos);
inline void vspr_image(char sp, char image);
inline void vspr_color(char sp, char color);
inline void vspr_hide(char sp);
void vspr_sort(void);
void vspr_update(void);
#pragma compile("sprites.c")
#endif

View File

@ -45,3 +45,37 @@ void vic_setmode(VicMode mode, char * text, char * font)
cia2.pra = (cia2.pra & 0xfc) | (((unsigned)text >> 14) ^ 0x03);
vic.memptr = (((unsigned)text >> 6) & 0xf0) | (((unsigned)font >> 10) & 0x0e);
}
void waitBottom(void)
{
while (!(vic.ctrl1 & VIC_CTRL1_RST8))
;
}
void waitTop(void)
{
while ((vic.ctrl1 & VIC_CTRL1_RST8))
;
}
void vic_waitFrame(void)
{
while ((vic.ctrl1 & VIC_CTRL1_RST8))
;
while (!(vic.ctrl1 & VIC_CTRL1_RST8))
;
}
void vic_waitLine(int line)
{
char upper = (char)(line >> 1) & VIC_CTRL1_RST8;
char lower = (char)line;
do
{
while (vic.raster != lower)
;
} while ((vic.ctrl1 & VIC_CTRL1_RST8) != upper);
}
#pragma native(vic_waitLine)

View File

@ -88,6 +88,13 @@ void vic_setmode(VicMode mode, char * text, char * font);
inline void vic_sprxy(byte s, int x, int y);
inline void vic_waitBottom(void);
inline void vic_waitTop(void);
inline void vic_waitFrame(void);
inline void vic_waitLine(int line);
#define vic (*((struct VIC *)0xd000))

View File

@ -2676,7 +2676,7 @@ static void OptimizeAddress(InterInstruction * ins, const GrowingInstructionPtrA
{
ins->mSrc[offset].mIntConst = 0;
if (ins->mSrc[offset].mTemp >= 0 && tvalue[ins->mSrc[offset].mTemp])
while (ins->mSrc[offset].mTemp >= 0 && tvalue[ins->mSrc[offset].mTemp])
{
InterInstruction* ains = tvalue[ins->mSrc[offset].mTemp];
@ -2705,6 +2705,8 @@ static void OptimizeAddress(InterInstruction * ins, const GrowingInstructionPtrA
ins->mSrc[offset].mIntConst = ains->mSrc[1].mIntConst;
ins->mSrc[offset].mTemp = ains->mSrc[0].mTemp;
}
else
break;
}
}

View File

@ -598,6 +598,31 @@ bool NativeCodeInstruction::RequiresXReg(void) const
}
void NativeCodeInstruction::ReplaceYRegWithXReg(void)
{
switch (mType)
{
case ASMIT_LDY:
mType = ASMIT_LDX;
break;
case ASMIT_STY:
mType = ASMIT_STX;
break;
case ASMIT_CPY:
mType = ASMIT_CPX;
break;
case ASMIT_TYA:
mType = ASMIT_TXA;
break;
case ASMIT_TAY:
mType = ASMIT_TAX;
break;
}
if (mMode == ASMIM_ABSOLUTE_Y)
mMode = ASMIM_ABSOLUTE_X;
}
bool NativeCodeInstruction::ChangesYReg(void) const
{
return mType == ASMIT_TAY || mType == ASMIT_LDY || mType == ASMIT_INY || mType == ASMIT_DEY || mType == ASMIT_JSR;
@ -4670,6 +4695,36 @@ void NativeCodeBasicBlock::ShiftRegisterLeft(InterCodeProcedure* proc, int reg,
}
}
void NativeCodeBasicBlock::ShiftRegisterLeftByte(InterCodeProcedure* proc, int reg, int shift)
{
if (shift == 0)
{
}
else if (shift == 1)
{
mIns.Push(NativeCodeInstruction(ASMIT_ASL, ASMIM_ZERO_PAGE, reg));
}
else if (shift >= 6)
{
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, reg));
mIns.Push(NativeCodeInstruction(ASMIT_LSR, ASMIM_IMPLIED));
for (int i = shift; i < 8; i++)
mIns.Push(NativeCodeInstruction(ASMIT_ROR, ASMIM_IMPLIED));
mIns.Push(NativeCodeInstruction(ASMIT_AND, ASMIM_IMMEDIATE, (0xff << shift) & 0xff));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, reg));
}
else
{
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, reg));
for (int i = 0; i < shift; i++)
{
mIns.Push(NativeCodeInstruction(ASMIT_ASL, ASMIM_IMPLIED));
}
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, reg));
}
}
int NativeCodeBasicBlock::ShortMultiply(InterCodeProcedure* proc, NativeCodeProcedure* nproc, const InterInstruction * ins, const InterInstruction* sins, int index, int mul)
{
mul &= 0xffff;
@ -4695,7 +4750,14 @@ int NativeCodeBasicBlock::ShortMultiply(InterCodeProcedure* proc, NativeCodeProc
{
#if 1
case 1:
ShiftRegisterLeft(proc, BC_REG_ACCU, lshift);
if (ins->mDst.IsUByte())
{
ShiftRegisterLeftByte(proc, BC_REG_ACCU, lshift);
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, 0));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 1));
}
else
ShiftRegisterLeft(proc, BC_REG_ACCU, lshift);
return BC_REG_ACCU;
case 3:
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 0));
@ -10862,6 +10924,58 @@ void NativeCodeBasicBlock::BlockSizeReduction(void)
j += 2;
i += 4;
}
else if (i + 1 < mIns.Size() &&
mIns[i + 0].mType == ASMIT_LDA && mIns[i + 0].mMode == ASMIM_ABSOLUTE_X &&
mIns[i + 1].mType == ASMIT_TAY && !(mIns[i + 1].mLive & LIVE_CPU_REG_A))
{
mIns[j] = mIns[i];
mIns[j].mType = ASMIT_LDY;
mIns[j].mLive |= LIVE_CPU_REG_Y;
j++;
i += 2;
}
else if (i + 1 < mIns.Size() &&
mIns[i + 0].mType == ASMIT_LDA && mIns[i + 0].mMode == ASMIM_ABSOLUTE_Y &&
mIns[i + 1].mType == ASMIT_TAX && !(mIns[i + 1].mLive & LIVE_CPU_REG_A))
{
mIns[j] = mIns[i];
mIns[j].mType = ASMIT_LDX;
mIns[j].mLive |= LIVE_CPU_REG_Y;
j++;
i += 2;
}
else if (i + 2 < mIns.Size() &&
mIns[i + 0].mType == ASMIT_LDY && !(mIns[i + 0].mLive & LIVE_CPU_REG_X) && (mIns[i + 0].mMode == ASMIM_ZERO_PAGE || mIns[i + 0].mMode == ASMIM_ABSOLUTE) &&
mIns[i + 1].mType == ASMIT_LDA && mIns[i + 1].mMode == ASMIM_ABSOLUTE_Y &&
mIns[i + 2].mType == ASMIT_TAY && !(mIns[i + 2].mLive & LIVE_CPU_REG_A))
{
mIns[j + 0] = mIns[i + 0];
mIns[j + 1] = mIns[i + 1];
mIns[j + 0].mType = ASMIT_LDX;
mIns[j + 0].mLive |= LIVE_CPU_REG_X;
mIns[j + 1].mType = ASMIT_LDY;
mIns[j + 1].mMode = ASMIM_ABSOLUTE_X;
mIns[j + 1].mLive |= LIVE_CPU_REG_Y;
j += 2;
i += 3;
}
else if (i + 2 < mIns.Size() &&
mIns[i + 0].mType == ASMIT_LDX && !(mIns[i + 0].mLive & LIVE_CPU_REG_Y) && (mIns[i + 0].mMode == ASMIM_ZERO_PAGE || mIns[i + 0].mMode == ASMIM_ABSOLUTE) &&
mIns[i + 1].mType == ASMIT_LDA && mIns[i + 1].mMode == ASMIM_ABSOLUTE_X &&
mIns[i + 2].mType == ASMIT_TAX && !(mIns[i + 2].mLive & LIVE_CPU_REG_A))
{
mIns[j + 0] = mIns[i + 0];
mIns[j + 1] = mIns[i + 1];
mIns[j + 0].mType = ASMIT_LDY;
mIns[j + 0].mLive |= LIVE_CPU_REG_Y;
mIns[j + 1].mType = ASMIT_LDX;
mIns[j + 1].mMode = ASMIM_ABSOLUTE_Y;
mIns[j + 1].mLive |= LIVE_CPU_REG_X;
j += 2;
i += 3;
}
else
mIns[j++] = mIns[i++];
}
@ -12583,7 +12697,7 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(int pass)
{
mIns[i + 1].mType = ASMIT_NOP; mIns[i + 1].mMode = ASMIM_IMPLIED;
mIns[i + 3].mMode = mIns[i + 0].mMode;
mIns[i + 3].mAddress= mIns[i + 0].mAddress;
mIns[i + 3].mAddress = mIns[i + 0].mAddress;
mIns[i + 3].mLinkerObject = mIns[i + 0].mLinkerObject;
mIns[i + 3].mFlags = mIns[i + 0].mFlags;
progress = true;
@ -12668,6 +12782,22 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(int pass)
progress = true;
}
#if 1
else if (
mIns[i + 0].mType == ASMIT_LDY && mIns[i + 0].mMode == ASMIM_ZERO_PAGE &&
!(mIns[i + 1].ChangesYReg() || mIns[i + 1].mMode == ASMIM_INDIRECT_Y || mIns[i + 1].RequiresXReg()) &&
mIns[i + 2].mType == ASMIT_TYA &&
mIns[i + 3].mType == ASMIT_TAX && !(mIns[i + 3].mLive & (LIVE_CPU_REG_A | LIVE_CPU_REG_Z | LIVE_CPU_REG_Y)))
{
mIns[i + 0].mType = ASMIT_LDX;
mIns[i + 0].mLive |= LIVE_CPU_REG_X;
mIns[i + 1].ReplaceYRegWithXReg();
mIns[i + 2].mType = ASMIT_NOP; mIns[i + 2].mMode = ASMIM_IMPLIED;
mIns[i + 3].mType = ASMIT_NOP; mIns[i + 3].mMode = ASMIM_IMPLIED;
progress = true;
}
#endif
#if 1
if (

View File

@ -96,6 +96,8 @@ public:
bool IsSame(const NativeCodeInstruction& ins) const;
bool IsCommutative(void) const;
bool IsShift(void) const;
void ReplaceYRegWithXReg(void);
};
class NativeCodeBasicBlock
@ -174,6 +176,7 @@ public:
void CallFunction(InterCodeProcedure* proc, NativeCodeProcedure* nproc, const InterInstruction * ins);
void ShiftRegisterLeft(InterCodeProcedure* proc, int reg, int shift);
void ShiftRegisterLeftByte(InterCodeProcedure* proc, int reg, int shift);
int ShortMultiply(InterCodeProcedure* proc, NativeCodeProcedure* nproc, const InterInstruction * ins, const InterInstruction* sins, int index, int mul);
bool CheckPredAccuStore(int reg);

95
samples/hires/bitblit.c Normal file
View File

@ -0,0 +1,95 @@
#include <c64/memmap.h>
#include <c64/vic.h>
#include <gfx/bitmap.h>
#include <string.h>
#include <conio.h>
#include <math.h>
#define Color ((char *)0xd000)
#define Hires ((char *)0xe000)
Bitmap Screen, Brush;
void init(void)
{
mmap_trampoline();
mmap_set(MMAP_RAM);
memset(Color, 0x10, 1000);
memset(Hires, 0x00, 8000);
mmap_set(MMAP_NO_ROM);
vic_setmode(VICM_HIRES, Color, Hires);
vic.color_border = VCOL_WHITE;
bm_init(&Screen, Hires, 40, 25);
}
void done(void)
{
mmap_set(MMAP_ROM);
getch();
vic_setmode(VICM_TEXT, (char *)0x0400, (char *)0x1000);
}
int poly_x[] = {0, 32, 32, 24, 40, 32, 32, 64, 52, 42, 22, 12};
int poly_y[] = {64, 0, 20, 36, 36, 20, 0, 64, 64, 44, 44, 64};
struct BlitDemo
{
const char * name;
BlitOp op;
};
BlitDemo blitDemos[11] = {
{"SET", BLTOP_SET},
{"RESET", BLTOP_RESET},
{"NOT", BLTOP_NOT},
{"XOR", BLTOP_XOR},
{"OR", BLTOP_OR},
{"AND", BLTOP_AND},
{"NAND", BLTOP_AND_NOT},
{"COPY", BLTOP_COPY},
{"NCOPY", BLTOP_NCOPY},
{"PATTERN", BLTOP_PATTERN},
{"MASKPAT", BLTOP_PATTERN_AND_SRC},
};
char pat[] = {0x6c, 0xfe, 0xfe, 0xfe, 0x7c, 0x38, 0x10, 0x00};
int main(void)
{
init();
bm_alloc(&Brush, 8, 8);
bm_fill(&Brush, 0);
ClipRect bcr = {0, 0, 64, 64};
bm_polygon_nc_fill(&Brush, &bcr, poly_x, poly_y, 12, NineShadesOfGrey[8]);
bmu_rect_pattern(&Screen, 0, 0, 320, 200, NineShadesOfGrey[2]);
ClipRect scr = {0, 0, 320, 200};
for(int i=0; i<11; i++)
{
int dx = 80 * ((i + 1) % 4);
int dy = 66 * ((i + 1) / 4);
bmu_bitblit(&Screen, dx + 8, dy + 1, &Brush, 0, 0, 64, 64, pat, blitDemos[i].op);
bm_put_string(&Screen, &scr, dx + 8, dy + 20, blitDemos[i].name, BLTOP_COPY);
}
done();
return 0;
}

View File

@ -1,7 +1,5 @@
// func3d
#include <c64/memmap.h>
#include <c64/vic.h>
#include <c64/cia.h>
#include <stdlib.h>
#include <string.h>
#include <conio.h>

68
samples/hires/lines.c Normal file
View File

@ -0,0 +1,68 @@
#include <c64/memmap.h>
#include <c64/vic.h>
#include <gfx/bitmap.h>
#include <string.h>
#include <conio.h>
#define Color ((char *)0xd000)
#define Hires ((char *)0xe000)
Bitmap Screen;
void init(void)
{
mmap_trampoline();
mmap_set(MMAP_RAM);
memset(Color, 0x01, 1000);
memset(Hires, 0x00, 8000);
mmap_set(MMAP_NO_ROM);
vic_setmode(VICM_HIRES, Color, Hires);
vic.color_border = VCOL_WHITE;
bm_init(&Screen, Hires, 40, 25);
}
void done(void)
{
mmap_set(MMAP_ROM);
getch();
vic_setmode(VICM_TEXT, (char *)0x0400, (char *)0x1000);
}
void draw(ClipRect * cr, byte pattern)
{
for(int i=0; i<40; i ++)
{
bm_line(&Screen, cr, 8 * i, 0, 319, 5 * i, pattern);
bm_line(&Screen, cr, 319, 5 * i, 319 - 8 * i, 199, pattern);
bm_line(&Screen, cr, 319 - 8 * i, 199, 0, 199 - 5 * i, pattern);
bm_line(&Screen, cr, 0, 199 - 5 * i, 8 * i, 0, pattern);
}
}
int main(void)
{
init();
ClipRect cr = {0, 0, 320, 200};
draw(&cr, 0xff);
draw(&cr, 0x00);
draw(&cr, 0xff);
draw(&cr, 0xaa);
draw(&cr, 0x88);
draw(&cr, 0x80);
draw(&cr, 0x00);
done();
return 0;
}

View File

@ -1,2 +1,5 @@
..\..\bin\oscar64 splitscreen.c
..\..\bin\oscar64 func3d.c -n
..\..\bin\oscar64 lines.c -n
..\..\bin\oscar64 polygon.c -n
..\..\bin\oscar64 bitblit.c -n

84
samples/hires/polygon.c Normal file
View File

@ -0,0 +1,84 @@
#include <c64/memmap.h>
#include <c64/vic.h>
#include <gfx/bitmap.h>
#include <string.h>
#include <conio.h>
#include <math.h>
#define Color ((char *)0xd000)
#define Hires ((char *)0xe000)
Bitmap Screen;
void init(void)
{
mmap_trampoline();
mmap_set(MMAP_RAM);
memset(Color, 0x10, 1000);
memset(Hires, 0x00, 8000);
mmap_set(MMAP_NO_ROM);
vic_setmode(VICM_HIRES, Color, Hires);
vic.color_border = VCOL_WHITE;
bm_init(&Screen, Hires, 40, 25);
}
void done(void)
{
mmap_set(MMAP_ROM);
getch();
vic_setmode(VICM_TEXT, (char *)0x0400, (char *)0x1000);
}
int main(void)
{
init();
bmu_rect_pattern(&Screen, 0, 0, 320, 200, NineShadesOfGrey[4]);
bmu_rect_clear(&Screen, 14, 14, 304, 184);
bmu_rect_fill(&Screen, 8, 8, 304, 184);
bmu_rect_clear(&Screen, 10, 10, 300, 180);
ClipRect cr = {11, 11, 309, 189};
float px[10], py[10];
for(int i=0; i<10; i++)
{
float w = i * PI / 5, c = cos(w), s = sin(w), r = (i & 1) ? 1.0 : 0.4;
px[i] = r * c; py[i] = r * s;
}
for(int i=0; i<128; i++)
{
int rpx[10], rpy[10];
float r = i + 4;
float w = i * PI / 16, c = r * cos(w), s = r * sin(w), cw = r * cos(w * 2.0), sw = r * sin(w * 2.0);
for(int j=0; j<10; j++)
{
float fx = px[j], fy = py[j];
rpx[j] = 160 + cw + fx * c + fy * s;
rpy[j] = 100 + sw - fx * s + fy * c;
}
bm_polygon_nc_fill(&Screen, &cr, rpx, rpy, 10, NineShadesOfGrey[i % 9]);
for(int j=0; j<10; j++)
{
int k = (j + 1) % 10;
bm_line(&Screen, &cr, rpx[j], rpy[j], rpx[k], rpy[k], 0xff);
}
}
done();
return 0;
}

View File

@ -34,15 +34,12 @@ int main(void)
rirq_init(true);
vic.ctrl1 = VIC_CTRL1_BMM | VIC_CTRL1_DEN | VIC_CTRL1_RSEL | 3;
vic.ctrl2 = VIC_CTRL2_CSEL;
vic.color_back = VCOL_BLACK;
memset(Color, 0x10, 1000);
memset(Hires, 0, 8000);
vic_setbank(3);
vic.memptr = 0x28;
vic_setmode(VICM_HIRES, Color, Hires);
rirq_build(&rirqtop, 2);
rirq_write(&rirqtop, 0, &vic.memptr, 0x28);

View File

@ -25,7 +25,6 @@ char charset[2048] = {
#pragma data(data)
char x;
int main(void)
{
// map the vic to the new charset

Binary file not shown.

View File

@ -51,17 +51,6 @@ const char * text =
s"invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam "
s"et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet."
inline void waitBottom(void)
{
while (!(vic.ctrl1 & VIC_CTRL1_RST8))
;
}
inline void waitTop(void)
{
while ((vic.ctrl1 & VIC_CTRL1_RST8))
;
}
int main(void)
{
@ -87,19 +76,19 @@ int main(void)
{
for(char i=0; i<2; i++)
{
waitBottom();
vic_waitBottom();
vic.ctrl2 = 4;
waitTop();
vic_waitTop();
waitBottom();
vic_waitBottom();
vic.ctrl2 = 2;
waitTop();
vic_waitTop();
waitBottom();
vic_waitBottom();
vic.ctrl2 = 0;
waitTop();
vic_waitTop();
waitBottom();
vic_waitBottom();
vic.ctrl2 = 6;
scrollLeft();

View File

@ -0,0 +1,43 @@
#include <c64/sprites.h>
#include <c64/joystick.h>
#include <string.h>
char spdata[] = {
#embed "../resources/friendlybear.bin"
};
int spx, spy;
#define SpriteData ((char *)0x0380)
int main(void)
{
memcpy(SpriteData, spdata, 128);
spr_init((char*)0x0400);
spx = 160;
spy = 100;
spr_set(0, true, spx, spy, 0x03c0 / 64, VCOL_BLACK, false, false, false);
spr_set(1, true, spx, spy, 0x0380 / 64, VCOL_ORANGE, true, false, false);
vic.spr_mcolor0 = VCOL_BROWN;
vic.spr_mcolor1 = VCOL_WHITE;
for(;;)
{
joy_poll(1);
spx += joyx[1];
spy += joyy[1];
spr_move(0, spx, spy);
spr_move(1, spx, spy);
vic_waitFrame();
}
return 0;
}

2
samples/sprites/make.bat Normal file
View File

@ -0,0 +1,2 @@
..\..\bin\oscar64 joycontrol.c
..\..\bin\oscar64 multiplexer.c -n

View File

@ -0,0 +1,90 @@
#include <c64/vic.h>
#include <c64/rasterirq.h>
#include <c64/sprites.h>
#include <math.h>
#define Screen ((char *)0x400)
// make space until 0x2000 for code and data
#pragma region( lower, 0x0a00, 0x2000, , , {code, data} )
// then space for our sprite data
#pragma section( spriteset, 0)
#pragma region( spriteset, 0x2000, 0x2800, , , {spriteset} )
// everything beyond will be code, data, bss and heap to the end
#pragma region( main, 0x2800, 0xa000, , , {code, data, bss, heap, stack} )
// spriteset at fixed location
#pragma data(spriteset)
char spriteset[2048] = {
#embed "../samples/resources/digitsprites.bin"
};
#pragma data(data)
// sinus table for circular movement
int sintab[128];
int main(void)
{
// calculate sine table
for(int i=0; i<128; i++)
sintab[i] = (int)(80 * sin(i * PI / 64));
// enable raster interrupt via kernal path
rirq_init(true);
// initialize sprite multiplexer
vspr_init(Screen);
// initalize sprites
for(int i=0; i<16; i++)
{
vspr_set(i, 30 + 16 * i, 220 - 8 * i, (unsigned)&(spriteset[0]) / 64 + i, (i & 7) + 8);
}
// initial sort and update
vspr_sort();
vspr_update();
rirq_sort();
// start raster IRQ processing
rirq_start();
// animation loop
unsigned j = 0;
for(;;)
{
// move sprites around
char k = j >> 4;
for(char i=0; i<16; i++)
{
vspr_move(i, 200 + sintab[(j + 8 * i) & 127] + sintab[k & 127], 140 + sintab[(j + 8 * i + 32) & 127] + sintab[(k + 32) & 127]);
}
j++;
// sort virtual sprites by y position
vspr_sort();
// wait for raster IRQ to reach and of frame
rirq_wait();
// update sprites back to normal and set up raster IRQ for second set
vspr_update();
// sort raster IRQs
rirq_sort();
}
return 0;
}