diff --git a/include/c64/rasterirq.c b/include/c64/rasterirq.c index bf23c26..5643093 100644 --- a/include/c64/rasterirq.c +++ b/include/c64/rasterirq.c @@ -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; } diff --git a/include/c64/sprites.c b/include/c64/sprites.c new file mode 100644 index 0000000..0ca0460 --- /dev/null +++ b/include/c64/sprites.c @@ -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) diff --git a/include/c64/sprites.h b/include/c64/sprites.h new file mode 100644 index 0000000..24c956f --- /dev/null +++ b/include/c64/sprites.h @@ -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 diff --git a/include/c64/vic.c b/include/c64/vic.c index 2314e9f..d9079ce 100644 --- a/include/c64/vic.c +++ b/include/c64/vic.c @@ -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) diff --git a/include/c64/vic.h b/include/c64/vic.h index a1ee2d8..7198533 100644 --- a/include/c64/vic.h +++ b/include/c64/vic.h @@ -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)) diff --git a/oscar64/InterCode.cpp b/oscar64/InterCode.cpp index d591834..3701440 100644 --- a/oscar64/InterCode.cpp +++ b/oscar64/InterCode.cpp @@ -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; } } diff --git a/oscar64/NativeCodeGenerator.cpp b/oscar64/NativeCodeGenerator.cpp index 50aa266..1594749 100644 --- a/oscar64/NativeCodeGenerator.cpp +++ b/oscar64/NativeCodeGenerator.cpp @@ -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++]; } @@ -12574,7 +12688,7 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(int pass) progress = true; } else if ( - mIns[i + 0].mType == ASMIT_LDA && + mIns[i + 0].mType == ASMIT_LDA && mIns[i + 1].mType == ASMIT_STA && mIns[i + 1].mMode == ASMIM_ZERO_PAGE && mIns[i + 3].mMode == ASMIM_ZERO_PAGE && mIns[i + 1].mAddress && mIns[i + 3].mAddress && mIns[i + 2].mMode == ASMIM_IMPLIED && !(mIns[i + 3].mLive & LIVE_MEM) && @@ -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 ( diff --git a/oscar64/NativeCodeGenerator.h b/oscar64/NativeCodeGenerator.h index 40f7144..311f25b 100644 --- a/oscar64/NativeCodeGenerator.h +++ b/oscar64/NativeCodeGenerator.h @@ -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); diff --git a/samples/hires/bitblit.c b/samples/hires/bitblit.c new file mode 100644 index 0000000..6a365b1 --- /dev/null +++ b/samples/hires/bitblit.c @@ -0,0 +1,95 @@ +#include +#include +#include +#include +#include +#include + +#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; +} diff --git a/samples/hires/func3d.c b/samples/hires/func3d.c index ffe6607..bceeec5 100644 --- a/samples/hires/func3d.c +++ b/samples/hires/func3d.c @@ -1,7 +1,5 @@ -// func3d #include #include -#include #include #include #include diff --git a/samples/hires/lines.c b/samples/hires/lines.c new file mode 100644 index 0000000..f6f5d6f --- /dev/null +++ b/samples/hires/lines.c @@ -0,0 +1,68 @@ +#include +#include +#include +#include +#include + + +#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; +} diff --git a/samples/hires/make.bat b/samples/hires/make.bat index c8949ff..c865a37 100644 --- a/samples/hires/make.bat +++ b/samples/hires/make.bat @@ -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 diff --git a/samples/hires/polygon.c b/samples/hires/polygon.c new file mode 100644 index 0000000..46a301c --- /dev/null +++ b/samples/hires/polygon.c @@ -0,0 +1,84 @@ +#include +#include +#include +#include +#include +#include + +#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; +} diff --git a/samples/hires/splitscreen.c b/samples/hires/splitscreen.c index 1cb06b7..a26c5da 100644 --- a/samples/hires/splitscreen.c +++ b/samples/hires/splitscreen.c @@ -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); diff --git a/samples/memmap/charsetlo.c b/samples/memmap/charsetlo.c index d262d66..7e41ce6 100644 --- a/samples/memmap/charsetlo.c +++ b/samples/memmap/charsetlo.c @@ -25,7 +25,6 @@ char charset[2048] = { #pragma data(data) -char x; int main(void) { // map the vic to the new charset diff --git a/samples/resources/digitsprites.bin b/samples/resources/digitsprites.bin new file mode 100644 index 0000000..5ce3925 Binary files /dev/null and b/samples/resources/digitsprites.bin differ diff --git a/samples/scrolling/bigfont.c b/samples/scrolling/bigfont.c index 0bede60..4107091 100644 --- a/samples/scrolling/bigfont.c +++ b/samples/scrolling/bigfont.c @@ -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(); diff --git a/samples/sprites/joycontrol.c b/samples/sprites/joycontrol.c new file mode 100644 index 0000000..6d816ac --- /dev/null +++ b/samples/sprites/joycontrol.c @@ -0,0 +1,43 @@ +#include +#include +#include + +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; +} + diff --git a/samples/sprites/make.bat b/samples/sprites/make.bat new file mode 100644 index 0000000..df6d145 --- /dev/null +++ b/samples/sprites/make.bat @@ -0,0 +1,2 @@ +..\..\bin\oscar64 joycontrol.c +..\..\bin\oscar64 multiplexer.c -n diff --git a/samples/sprites/multiplexer.c b/samples/sprites/multiplexer.c new file mode 100644 index 0000000..b88554f --- /dev/null +++ b/samples/sprites/multiplexer.c @@ -0,0 +1,90 @@ +#include +#include +#include +#include + +#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; + +}