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 ri = rasterIRQIndex[i];
byte rr = rasterIRQRows[ri]; byte rr = rasterIRQRows[ri];
byte j = i, rj = rasterIRQIndex[j - 1]; byte j = i, rj;
while (j > 0 && rr < rasterIRQRows[rj]) while (j > 0 && rr < rasterIRQRows[(rj = rasterIRQIndex[j - 1])])
{ {
rasterIRQIndex[j] = rj; rasterIRQIndex[j] = rj;
j--; j--;
rj = rasterIRQIndex[j - 1]
} }
rasterIRQIndex[j] = ri; 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); cia2.pra = (cia2.pra & 0xfc) | (((unsigned)text >> 14) ^ 0x03);
vic.memptr = (((unsigned)text >> 6) & 0xf0) | (((unsigned)font >> 10) & 0x0e); 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_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)) #define vic (*((struct VIC *)0xd000))

View File

@ -2676,7 +2676,7 @@ static void OptimizeAddress(InterInstruction * ins, const GrowingInstructionPtrA
{ {
ins->mSrc[offset].mIntConst = 0; 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]; 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].mIntConst = ains->mSrc[1].mIntConst;
ins->mSrc[offset].mTemp = ains->mSrc[0].mTemp; 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 bool NativeCodeInstruction::ChangesYReg(void) const
{ {
return mType == ASMIT_TAY || mType == ASMIT_LDY || mType == ASMIT_INY || mType == ASMIT_DEY || mType == ASMIT_JSR; 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) int NativeCodeBasicBlock::ShortMultiply(InterCodeProcedure* proc, NativeCodeProcedure* nproc, const InterInstruction * ins, const InterInstruction* sins, int index, int mul)
{ {
mul &= 0xffff; mul &= 0xffff;
@ -4695,7 +4750,14 @@ int NativeCodeBasicBlock::ShortMultiply(InterCodeProcedure* proc, NativeCodeProc
{ {
#if 1 #if 1
case 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; return BC_REG_ACCU;
case 3: case 3:
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 0)); mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 0));
@ -10862,6 +10924,58 @@ void NativeCodeBasicBlock::BlockSizeReduction(void)
j += 2; j += 2;
i += 4; 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 else
mIns[j++] = mIns[i++]; 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 + 1].mType = ASMIT_NOP; mIns[i + 1].mMode = ASMIM_IMPLIED;
mIns[i + 3].mMode = mIns[i + 0].mMode; 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].mLinkerObject = mIns[i + 0].mLinkerObject;
mIns[i + 3].mFlags = mIns[i + 0].mFlags; mIns[i + 3].mFlags = mIns[i + 0].mFlags;
progress = true; progress = true;
@ -12668,6 +12782,22 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(int pass)
progress = true; 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 1
if ( if (

View File

@ -96,6 +96,8 @@ public:
bool IsSame(const NativeCodeInstruction& ins) const; bool IsSame(const NativeCodeInstruction& ins) const;
bool IsCommutative(void) const; bool IsCommutative(void) const;
bool IsShift(void) const; bool IsShift(void) const;
void ReplaceYRegWithXReg(void);
}; };
class NativeCodeBasicBlock class NativeCodeBasicBlock
@ -174,6 +176,7 @@ public:
void CallFunction(InterCodeProcedure* proc, NativeCodeProcedure* nproc, const InterInstruction * ins); void CallFunction(InterCodeProcedure* proc, NativeCodeProcedure* nproc, const InterInstruction * ins);
void ShiftRegisterLeft(InterCodeProcedure* proc, int reg, int shift); 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); int ShortMultiply(InterCodeProcedure* proc, NativeCodeProcedure* nproc, const InterInstruction * ins, const InterInstruction* sins, int index, int mul);
bool CheckPredAccuStore(int reg); 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/memmap.h>
#include <c64/vic.h> #include <c64/vic.h>
#include <c64/cia.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <conio.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 splitscreen.c
..\..\bin\oscar64 func3d.c -n ..\..\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); 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; vic.color_back = VCOL_BLACK;
memset(Color, 0x10, 1000); memset(Color, 0x10, 1000);
memset(Hires, 0, 8000);
vic_setbank(3); vic_setmode(VICM_HIRES, Color, Hires);
vic.memptr = 0x28;
rirq_build(&rirqtop, 2); rirq_build(&rirqtop, 2);
rirq_write(&rirqtop, 0, &vic.memptr, 0x28); rirq_write(&rirqtop, 0, &vic.memptr, 0x28);

View File

@ -25,7 +25,6 @@ char charset[2048] = {
#pragma data(data) #pragma data(data)
char x;
int main(void) int main(void)
{ {
// map the vic to the new charset // 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"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." 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) int main(void)
{ {
@ -87,19 +76,19 @@ int main(void)
{ {
for(char i=0; i<2; i++) for(char i=0; i<2; i++)
{ {
waitBottom(); vic_waitBottom();
vic.ctrl2 = 4; vic.ctrl2 = 4;
waitTop(); vic_waitTop();
waitBottom(); vic_waitBottom();
vic.ctrl2 = 2; vic.ctrl2 = 2;
waitTop(); vic_waitTop();
waitBottom(); vic_waitBottom();
vic.ctrl2 = 0; vic.ctrl2 = 0;
waitTop(); vic_waitTop();
waitBottom(); vic_waitBottom();
vic.ctrl2 = 6; vic.ctrl2 = 6;
scrollLeft(); 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;
}