Skip to content

Instantly share code, notes, and snippets.

@JettMonstersGoBoom
Last active October 19, 2021 21:21
Show Gist options
  • Save JettMonstersGoBoom/02f86053fb05f5422123245bf3404ae6 to your computer and use it in GitHub Desktop.
Save JettMonstersGoBoom/02f86053fb05f5422123245bf3404ae6 to your computer and use it in GitHub Desktop.
C64 screen mode for DOSLIKE
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include "dos.h"
#define VIC_IMPL
#include "vic.h"
unsigned char raster_colours[] = {
0x6, 0x6, 0x6, 0xe, 0x6, 0xe,
0xe, 0x6, 0xe, 0xe, 0xe, 0x3,
0xe, 0x3, 0x3, 0xe, 0x3, 0x3,
0x3, 0x1, 0x3, 0x1, 0x1, 0x3,
0x1, 0x1, 0x1, 0x3, 0x1, 0x1,
0x3, 0x1, 0x3, 0x3, 0x3, 0xe,
0x3, 0x3, 0xe, 0x3, 0xe, 0xe,
0xe, 0x6, 0xe, 0xe, 0x6, 0xe,
0x6, 0x6, 0x6, 0x0, 0x0, 0x0
};
int main(int argc, char *argv[])
{
float t=0;
setvideomode( videomode_320x200 );
setdoublebuffer(1);
for (int q=0;q<1000;q++)
{
VIC.Colors[q]=(q/10)&0xf;
VIC.Screen[q]=q&0xff;
}
VIC.horizontal_offset = VIC.vertical_offset = 0; // reset scroll
VIC.Mode = 1; // text with MC
VIC.D021 = 0xb; //
VIC.D022 = 0xf; //
VIC.D023 = 0x1; //
VIC.D026 = 0;
VIC.D027 = 1;
VIC.SpriteMCM = 0b111111111;
VIC.SpriteENA = 0b111111111;
// load charpad data
// from Saul Cross
VIC.CharData=(unsigned char *)malloc(2048);
VIC.SpriteData=(unsigned char *)malloc(16384);
// from CHARPAD
// REAL C64 data
FILE *fp = fopen("files/Bruce Lee Updated (1x1) - Chars.bin","rb");
fread(&VIC.CharData[0],2048,1,fp);
fclose(fp);
// SPRITE's from SPRITEPAD
// fp = fopen("files/invaders - Sprites.bin","rb");
// fread(&VIC.SpriteData[0],2048,1,fp);
// fclose(fp);
fp = fopen("files/Bruce Lee Updated (1x1) - Map (8bpc, 40x25).bin","rb");
fread(&VIC.Screen[0],1000,1,fp);
fclose(fp);
unsigned char attribs[256];
fp = fopen("files/Bruce Lee Updated (1x1) - CharAttribs_L1.bin","rb");
fread(&attribs[0],256,1,fp);
fclose(fp);
// set attribs
for (int q=0;q<1000;q++)
{
unsigned char c = VIC.Screen[q];
VIC.Colors[q] = attribs[c];
}
unsigned char* buffer = screenbuffer();
while(!shuttingdown())
{
waitvbl();
for (int q=0;q<8;q++)
{
VIC.SpriteX[q] = 160+(sin(t+q)*140);
VIC.SpriteY[q] = 100+(cos(t+q)*80);
VIC.SpriteColor[q] = q + t;
VIC.SpriteID[q] = q;
}
t+=0.01f;
// draw 200 scanlines
// adjusting VIC.D021 as we go for raster effects
for (int y=0;y<200;y++)
{
VIC.D021 = raster_colours[(int)(y+(t*32)) % sizeof(raster_colours)];
VIC_PaintScanline(buffer,y);
}
buffer = swapbuffers();
if( keystate( KEY_ESCAPE ) ) {
break;
}
}
free(VIC.CharData);
free(VIC.SpriteData);
return(0);
}
enum vic_mode_t {
vic_hires,vic_mcm
};
struct
{
unsigned char Screen[40*25];
unsigned char Colors[40*25];
unsigned char SpriteMCM;
unsigned char SpriteENA;
unsigned short SpriteX[8];
unsigned char SpriteY[8];
unsigned char SpriteColor[8];
unsigned char SpriteID[8];
unsigned char *CharData;
unsigned char *SpriteData;
unsigned char D020;
unsigned char D021;
unsigned char D022;
unsigned char D023;
unsigned char D026;
unsigned char D027;
unsigned char Mode,horizontal_offset,vertical_offset;
} VIC;
static unsigned int VIC_Palette[16] =
{
0x000000, 0xFFFFFF, 0x813338,
0x75cec8, 0x8e3c97, 0x56ac4d,
0x2e2c9b, 0xedf171, 0x8e5029,
0x553800, 0xc46c71, 0x4a4a4a,
0x7b7b7b, 0xa9ff9f, 0x706deb,
0xb2b2b2
};
#ifdef VIC_IMPL
void VIC_PaintScanline(unsigned char *buffer,unsigned char scanline)
{
unsigned char *ptr = &buffer[0];
if (VIC.CharData==NULL) return;
// clamp scroll
VIC.horizontal_offset&=7;
VIC.vertical_offset&=7;
// update pal
for (int q=0;q<16;q++)
setpal( q, (VIC_Palette[q]>>18)&0xff,(VIC_Palette[q]>>10)&0xff,(VIC_Palette[q]>>2)&0xff);
//
{
int ay = scanline + VIC.vertical_offset;
unsigned char py = ay&7;
for (int x=0;x<320;x++)
{
int ax = x + VIC.horizontal_offset;
unsigned char px = ax&7;
unsigned char color = VIC.Colors[(ax>>3)+((ay>>3)*40)]; // color memory
unsigned char cell = VIC.Screen[(ax>>3)+((ay>>3)*40)];// screen memory
unsigned char chr = VIC.CharData[(cell<<3)+py]; // tile memory
// set background pixel
buffer[x+(scanline*320)]=VIC.D021;
// depends on mode
switch(VIC.Mode)
{
case vic_hires:
{
if ((chr>>(7-px))&1)
buffer[x+(scanline*320)]=color;
}
break;
case vic_mcm: // multi color mode
{
if ((color&0x8)==0) // bottom 8 colors is hires
{
if ((chr>>(7-px))&1)
buffer[x+(scanline*320)]=color;
}
else // top 8 is 2 bits per pixel
{
unsigned char mask = (7-px)&6;
unsigned char cc = (chr>>mask)&3;
if (cc==1) buffer[x+(scanline*320)]=VIC.D022;
if (cc==2) buffer[x+(scanline*320)]=VIC.D023;
if (cc==3) buffer[x+(scanline*320)]=color&7;
}
}
break;
}
}
// sprites
for (int sid=0;sid<8;sid++)
{
unsigned char mode = (VIC.SpriteMCM>>(sid))&1;
unsigned char enabled = (VIC.SpriteENA>>(sid))&1;
if (enabled==1)
{
if ((scanline>=VIC.SpriteY[sid]) && (scanline<VIC.SpriteY[sid]+21))
{
unsigned char yoff = (scanline-VIC.SpriteY[sid])*3;
unsigned char *ptr = &VIC.SpriteData[(VIC.SpriteID[sid]*64)+yoff];
for (int x=0;x<24;x++)
{
unsigned char px = x&7;
unsigned char chr = ptr[x>>3]; // tile memory
if (mode==0)
{
if ((chr>>(7-px))&1)
buffer[VIC.SpriteX[sid]+x+(scanline*320)]=VIC.SpriteColor[sid];
}
else
{
unsigned char mask = (7-px)&6;
unsigned char cc = (chr>>mask)&3;
if (cc==1) buffer[VIC.SpriteX[sid]+x+(scanline*320)]=VIC.D026;
if (cc==3) buffer[VIC.SpriteX[sid]+x+(scanline*320)]=VIC.D027;
if (cc==2) buffer[VIC.SpriteX[sid]+x+(scanline*320)]=VIC.SpriteColor[sid];
}
}
}
}
}
}
}
#else
void VIC_PaintScanline(unsigned char *buffer,unsigned char scanline);
#endif
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment