Add files to repository

This commit is contained in:
Alec Murphy
2020-02-16 18:17:17 -05:00
parent a6c2e62291
commit d4588bba42
16 changed files with 7020 additions and 0 deletions
+1
View File
@@ -1,3 +1,4 @@
uncrustify.cfg
.vscode/
ROMs/
SnesJs/
+2723
View File
File diff suppressed because it is too large Load Diff
+90
View File
@@ -0,0 +1,90 @@
extern I64 frames;
Context2D *font_ctx = LoadPNG("font.png",,,2);
Context2D *font_ch = NewContext2D(16, 16, display.bpp);
U0 FontChar2D(Context2D *ctx, I64 ch, I64 x, I64 y)
{
ch-=32;
Fill2D(font_ch, font_ch->alpha_color);
Blot2D(font_ch, -(16*(ch%8)), -(16*(ch/8)), font_ctx);
Blot2D(ctx, x, y, font_ch);
}
U0 Font2D(Context2D *ctx, I64 x, I64 y, U8 *fmt,...)
{
U8 *buf;
if (argc)
{
buf=StrPrintJoin(NULL, fmt, argc, argv);
}
else
{
buf=StrNew(fmt);
}
U8 *str=buf;
while (*str)
{
FontChar2D(ctx, *str++, x, y);
x += 16;
}
Free(buf);
}
U0 PrintPlot2D(Context2D *ctx, I64 x, I64 y, U32 color)
{
U64 i = ctx->fb;
I64 pos = (svga.width*y)*svga.bpp/8;
pos += x*svga.bpp/8;
(i+pos)(U8*)[0]=color.u8[1];
(i+pos)(U8*)[1]=color.u8[2];
(i+pos)(U8*)[2]=color.u8[3];
}
U0 PrintChar2D(Context2D *ctx, I64 x, I64 y, I64 ch, U32 fg=0xFFFFFF00, U32 bg=BLACK)
{
U64 *char=sys_font_std;
I64 xx,yy;
I64 ii=0;
for (yy=0; yy<8; yy++)
{
xx=0;
for (xx=0; xx<8; xx++)
{
if (char[ch].u8[ii] & 1<<xx)
{
PrintPlot2D(ctx, x+xx, y+yy, fg);
}
else
{
PrintPlot2D(ctx, x+xx, y+yy, bg);
}
}
ii++;
if (ii>8)
{
ch++;
ii=0;
}
}
}
U0 Print2D(Context2D *ctx, I64 x, I64 y, U32 fg=0xFFFFFFFF, U32 bg=0, U8 *fmt,...)
{
U8 *buf;
if (argc)
{
buf=StrPrintJoin(NULL, fmt, argc, argv);
}
else
{
buf=StrNew(fmt);
}
U8 *str=buf;
while (*str)
{
PrintChar2D(ctx, x, y, *str++, fg, bg);
x += 8;
}
Free(buf);
}
+148
View File
@@ -0,0 +1,148 @@
tmpdoc = DocNew;
origdoc = Fs->put_doc;
Fs->put_doc = tmpdoc;
U0 EDbgPlot2D(I64 x, I64 y, U32 color)
{
U64 i = svga.fb;
I64 pos = (svga.width*y)*svga.bpp/8;
pos += x*svga.bpp/8;
(i+pos)(U8*)[0]=color.u8[1];
(i+pos)(U8*)[1]=color.u8[2];
(i+pos)(U8*)[2]=color.u8[3];
}
U0 EDbgChar2D(I64 x, I64 y, I64 ch, U32 fg=0xFFFFFF00, U32 bg=BLACK)
{
U64 *char=sys_font_std;
I64 xx,yy;
I64 ii=0;
for (yy=0; yy<8; yy++)
{
xx=0;
for (xx=0; xx<8; xx++)
{
if (char[ch].u8[ii] & 1<<xx)
{
EDbgPlot2D(x+xx, y+yy, fg);
}
else
{
EDbgPlot2D(x+xx, y+yy, bg);
}
}
ii++;
if (ii>8)
{
ch++;
ii=0;
}
}
}
U0 EDbgPutChar(I64 ch)
{
if (!IsSingleUser) { return; };
text.raw_flags &=~RWF_SHOW_DOLLAR;
if (ch>'~' && ch!=219)
{
ch=' ';
}
I64 i,row,col;
I64 raw_pos;
I64 raw_y;
U8 *ptr,*ptr1,*ptr2;
if (!(text.raw_flags&RWF_SHOW_DOLLAR)) {
if (ch=='$$') {
if (text.raw_flags&RWF_IN_DOLLAR) {
text.raw_flags&=~RWF_IN_DOLLAR;
if (!(text.raw_flags & RWF_LAST_DOLLAR)) {
text.raw_flags&=~RWF_LAST_DOLLAR;
return;
}
} else {
text.raw_flags|=RWF_IN_DOLLAR|RWF_LAST_DOLLAR;
return;
}
}
text.raw_flags&=~RWF_LAST_DOLLAR;
if (text.raw_flags&RWF_IN_DOLLAR)
return;
}
if (ch=='\t') {
EDbgPutChar(CH_SPACE);
while (text.raw_col & 7)
EDbgPutChar(CH_SPACE);
} else if (ch==CH_BACKSPACE) {
text.raw_col--;
EDbgPutChar(CH_SPACE);
text.raw_col--;
} else if (ch=='\n') {
EDbgPutChar(CH_SPACE);
while (text.raw_col % text.cols)
EDbgPutChar(CH_SPACE);
} else if (Bt(char_bmp_displayable,ch)) {
row=text.raw_col/text.cols%text.rows;
col=text.raw_col%text.cols;
if (text.raw_flags&RWF_SCROLL && text.raw_col && !row && !col) {
for (raw_y=0; raw_y<(text.rows*8)-8; raw_y++)
{
MemCpy(svga.fb+(raw_y*svga.width*(svga.bpp/8)),
svga.fb+((raw_y+8)*svga.width*(svga.bpp/8)),
(text.cols*8)*(svga.bpp/8));
}
for (raw_y=(text.rows*8)-8; raw_y<(text.rows*8); raw_y++)
{
MemSet(svga.fb+(raw_y*svga.width*(svga.bpp/8)),
0,
(text.cols*8)*(svga.bpp/8));
}
text.raw_col-=text.cols;
row=text.rows-1;
}
EDbgChar2D(col*8, row*8, ch);
text.raw_col++;
}
}
Bool EKDRawPutKey(I64 ch,I64)
{
if (IsRaw) {
EDbgPutChar(ch);
return TRUE;
} else
return FALSE;
}
Bool EKDRawPutS(U8 *st)
{
I64 ch;
if (IsRaw) {
while (ch=*st++)
EDbgPutChar(ch);
return TRUE;
} else
return FALSE;
}
U0 RawDrNull(CTask *task=NULL)
{
}
CKeyDevEntry *tmp_kde = keydev.put_key_head;
while (tmp_kde->put_s != &KDRawPutS)
{
tmp_kde = tmp_kde->next;
}
tmp_kde->put_key = &EKDRawPutKey;
tmp_kde->put_s = &EKDRawPutS;
MemCpy(&RawDr, &RawDrNull, sizeof(RawDrNull));
Bool Debug = FALSE;
U0 resume() { Debug=FALSE; G2; };
Fs->put_doc = origdoc;
DocDel(tmpdoc);
+17
View File
@@ -0,0 +1,17 @@
class Display
{
I64 width;
I64 height;
I64 bpp;
};
Display display;
U0 DisplayInit()
{
display.width = 640;
display.height = 480;
display.bpp = 32;
}
DisplayInit;
+250
View File
@@ -0,0 +1,250 @@
class Context2D
{
I64 width;
I64 height;
I64 bpp;
I64 alpha_color;
U8 *fb;
};
Context2D *NewContext2D(I64 width, I64 height, I64 bpp=display.bpp)
{ //Create new Context2D.
switch (bpp)
{
case 32:
case 24:
break;
default:
return NULL;
break;
}
Context2D *ctx = CAlloc(sizeof(Context2D));
ctx->width = width;
ctx->height = height;
ctx->bpp = bpp;
ctx->alpha_color = 0x00FF0000;
ctx->fb = CAlloc((width*height)*bpp/8);
return ctx;
}
U0 DelContext2D(Context2D *ctx)
{
if (!ctx)
{
return;
}
Free(ctx->fb);
Free(ctx);
}
U0 Fill2D(Context2D *ctx, U32 color=U32_MAX)
{ //Fill a Context2D with color.
if (color==U32_MAX) color=ctx->alpha_color;
U64 i = ctx->fb;
I64 pos = 0;
while (pos<(ctx->width*ctx->height)*ctx->bpp/8)
{
(i+pos)(U8*)[0]=color.u8[1];
(i+pos)(U8*)[1]=color.u8[2];
(i+pos)(U8*)[2]=color.u8[3];
switch (ctx->bpp)
{
case 32:
pos+=4;
break;
case 24:
pos+=3;
break;
default:
break;
}
}
}
U32 Peek2D(Context2D *ctx, I64 x, I64 y)
{ //Return RGB value for pixel.
U32 color=0;
if (x<0 || x>ctx->width-1 || y<0 || y>ctx->height-1)
{
return 0xFFFFFFFF;
}
U64 i = ctx->fb;
I64 pos = (ctx->width*y)*(ctx->bpp/8);
pos += x*(ctx->bpp/8);
color.u8[1]=(i+pos)(U8*)[0];
color.u8[2]=(i+pos)(U8*)[1];
color.u8[3]=(i+pos)(U8*)[2];
return color;
}
U0 Plot2D(Context2D *ctx, I64 x, I64 y, U32 color)
{ //Plot a pixel.
if (x<0 || x>ctx->width-1 || y<0 || y>ctx->height-1)
{
return;
}
U64 i = ctx->fb;
I64 pos = (ctx->width*y)*(ctx->bpp/8);
pos += x*(ctx->bpp/8);
(i+pos)(U8*)[0]=color.u8[1];
(i+pos)(U8*)[1]=color.u8[2];
(i+pos)(U8*)[2]=color.u8[3];
}
U0 HLine2D(Context2D *ctx, I64 x, I64 y, I64 x2, U32 color)
{ //Draw a horizontal line.
if (x2<x)
{
return;
}
while (x<x2+1)
{
Plot2D(ctx, x, y, color);
x++;
}
}
U0 VLine2D(Context2D *ctx, I64 x, I64 y, I64 y2, U32 color)
{ //Draw a vertical line.
if (y2<y)
{
return;
}
while (y<y2+1)
{
Plot2D(ctx, x, y, color);
y++;
}
}
U0 Blot2D(Context2D *dst, I64 x, I64 y, Context2D *src, U32 color=NULL)
{
if (src==NULL || dst==NULL)
{
return;
}
U8 *chk_alpha_ptr;
U32 chk_alpha;
U64 i=dst->fb;
U64 j=src->fb;
I64 xx,yy;
I64 dx,sx;
i+=(x*dst->bpp/8)+((dst->width*y)*dst->bpp/8);
for (yy=0; yy<src->height; yy++)
{
dx=0;
sx=0;
for (xx=0; xx<src->width; xx++)
{
chk_alpha_ptr=j+dx+((src->width*yy)*src->bpp/8);
chk_alpha=0;
chk_alpha.u8[1]=chk_alpha_ptr[0];
chk_alpha.u8[2]=chk_alpha_ptr[1];
chk_alpha.u8[3]=chk_alpha_ptr[2];
if ((chk_alpha!=src->alpha_color || src->alpha_color==-1) &&
x+xx>-1 && y+yy>-1 &&
x+xx<dst->width && y+yy<dst->height)
{
if (!color)
{
MemCpy(i+sx+((dst->width*yy)*dst->bpp/8), j+dx+((src->width*yy)*src->bpp/8), 3);
}
else
{
MemSet(i+sx+((dst->width*yy)*dst->bpp/8), color.u8[1], 1);
MemSet(i+sx+((dst->width*yy)*dst->bpp/8)+1, color.u8[2], 1);
MemSet(i+sx+((dst->width*yy)*dst->bpp/8)+2, color.u8[3], 1);
}
}
switch (dst->bpp)
{
case 32:
dx+=4;
break;
case 24:
dx+=3;
break;
default:
break;
}
switch (src->bpp)
{
case 32:
sx+=4;
break;
case 24:
sx+=3;
break;
default:
break;
}
}
}
}
U0 CopyRect2D(Context2D *ctx, I64 x, I64 y, Context2D *rect)
{//Copy rect with clipping.
U8 *ctx_pos=ctx->fb;
U8 *rect_pos=rect->fb;
I64 rect_row=0;
I64 rect_y_ofs=0;
I64 rect_x_ofs=0;
I64 clip_y=0;
U8 *rect_line;
//Handle horizontal clipping left
while (x<0) { rect_x_ofs++; x++; }
//Handle vertical clipping top
while (y<0)
{
rect_pos+=(rect->width)*(display.bpp/8);
rect_y_ofs++; y++;
}
// default, clip line to copy as width-left off screen
rect_line=rect->width-rect_x_ofs;
if (-rect_x_ofs+x+rect->width>=ctx->width)
{
rect_line-=((-rect_x_ofs+x+rect->width)-ctx->width);
}
rect_pos+=(rect_x_ofs)*(display.bpp/8);
clip_y = y;
while (rect_row<(rect->height-rect_y_ofs) && clip_y<ctx->height)
{
MemCpy(ctx_pos+(y*((ctx->width)*(display.bpp/8)))+x*(display.bpp/8),rect_pos,(rect_line)*(display.bpp/8));
ctx_pos+=(ctx->width)*(display.bpp/8);
rect_pos+=(rect->width)*(display.bpp/8);
clip_y++;
rect_row++;
}
}
U0 Rect2D(Context2D *ctx, I64 x, I64 y, I64 w, I64 h, U32 color)
{ //Draw a rectangle fill.
Context2D *tmpctx=NewContext2D(Max(4, w), Max(4, h), display.bpp);
Fill2D(tmpctx, color);
//Blot2D(ctx, x, y, tmpctx);
CopyRect2D(ctx, x, y, tmpctx);
DelContext2D(tmpctx);
}
Context2D *sys_fb = CAlloc(sizeof(Context2D));
U0 SysFrameBufferInit()
{ //Init values for Context2D alias to system framebuffer.
sys_fb->width = display.width;
sys_fb->height = display.height;
sys_fb->bpp = display.bpp;
sys_fb->alpha_color = -1;
sys_fb->fb = svga.fb;
}
U0 Flip2D(Context2D *ctx)
{
MemCpy(sys_fb->fb, ctx->fb, (display.width*display.height)*display.bpp/8);
}
+56
View File
@@ -0,0 +1,56 @@
extern I64 frames;
extern U0 Print2D(Context2D *ctx, I64 x, I64 y, U32 fg=0xFFFFFFFF, U32 bg=0, U8 *fmt,...);
Bool cond(I64 val, I64 if_true, I64 if_false)
{
if (val)
{
return if_true;
}
else
{
return if_false;
}
}
Bool KeyDown(I64 sc)
{
return Bt(kbd.down_bitmap, sc);
}
U64 append(U64 str)
{
return str+StrLen(str);
}
I64 fps_frames = frames;
I64 fps_jiffies = cnts.jiffies;
U0 UpdateTOSMenuBar(Context2D *ctx)
{
if (cnts.jiffies>=fps_jiffies+1000)
{
winmgr.fps = frames-fps_frames;
fps_frames = frames;
fps_jiffies = cnts.jiffies;
}
U8 *st;
CCPU *c;
I64 i;
*wall->top_line=NULL;
WallPaper(Fs);
Rect2D(ctx, 0, 0, 640, 8, 0x0000a800);
Print2D(ctx, 0, 0,,0x0000a800, wall->top_line);
WinCalcIdles;
for (i=0;i<mp_cnt;i++) {
c=&cpu_structs[i];
if (i&1)
Print2D(ctx, 8*44+(8*(i*2)), 0,,0x0000a800, "%2tf",100.0*(1.0-c->idle_factor));
else
Print2D(ctx, 8*44+(8*(i*2)), 0,0xffff5700,0x0000a800, "%2tf",100.0*(1.0-c->idle_factor));
}
st=ScanCode2KeyName(kbd.last_down_scan_code);
Print2D(ctx,640-(18*8),0,0xffff5700,0x0000a800,"%18ts",st);
Free(st);
}
+96
View File
@@ -0,0 +1,96 @@
class CVMSVGAInfo
{
U16 io_base;
U16 width;
U16 height;
U16 bpp;
U64 fb;
};
#define VBE_IOPORT_INDEX 0x01CE
#define VBE_IOPORT_DATA 0x01CF
#define VBE_XRES 1
#define VBE_YRES 2
#define VBE_BPP 3
#define VBE_ENABLE 4
#define VMSR_FB 13
CVMSVGAInfo svga;
MemSet(&svga, 0, sizeof(CVMSVGAInfo));
U16 VBE_RegRead(U16 index)
{
OutU16(VBE_IOPORT_INDEX, index);
return InU16(VBE_IOPORT_DATA);
}
U0 VBE_RegWrite(U16 index, U16 val)
{
OutU16(VBE_IOPORT_INDEX, index);
OutU16(VBE_IOPORT_DATA, val);
}
U32 VMSVGA_RegRead(I64 index)
{
OutU32(svga.io_base, index);
return InU32(svga.io_base+1);
}
U0 VMSVGA_RegWrite(I64 index, U32 val)
{
OutU32(svga.io_base, index);
OutU32(svga.io_base+1, val);
}
U0 GetVideoRegVals()
{
svga.width = VBE_RegRead(VBE_XRES);
svga.height = VBE_RegRead(VBE_YRES);
svga.bpp = VBE_RegRead(VBE_BPP);
svga.fb = VMSVGA_RegRead(VMSR_FB);
}
U0 SetVideoRegVals()
{
VBE_RegWrite(VBE_ENABLE, 0);
VBE_RegWrite(VBE_XRES, svga.width);
VBE_RegWrite(VBE_YRES, svga.height);
VBE_RegWrite(VBE_BPP, svga.bpp);
VBE_RegWrite(VBE_ENABLE, 1);
}
U0 VMSVGA_Start(I64 w=640,I64 h=480,I64 bpp=32)
{
switch (bpp)
{
case 32:
break;
default:
"\nInvalid bpp. (must be 32)\n";
return;
break;
}
I64 j;
//Scan for device
j=PCIClassFind(0x030000,0);
if (j<0)
{
"\nVMSVGA device not found.\n";
return;
}
svga.io_base=PCIReadU16(j.u8[2],
j.u8[1],j.u8[0],0x10) & ~(0x0F);
if (!svga.io_base)
{
"\nError reading base I/O address.\n";
return;
}
GetVideoRegVals;
svga.width=w;
svga.height=h;
svga.bpp=bpp;
LBts(&sys_winmgr_task->task_flags,TASKf_SUSPENDED);
//Raw(ON);
SetVideoRegVals;
}
+1073
View File
File diff suppressed because it is too large Load Diff
+42
View File
@@ -0,0 +1,42 @@
U0 parseHeader(U8 *rom, ROMHeader *header)
{
I64 i;
header->name = CAlloc(24);
MemCpy(header->name, rom+0x7FC0, 20);
i = StrLen(header->name)-1;
while (header->name[i]==' ') { header->name[i]=NULL; i--; }
header->type = rom[0x7fd5] & 0xf;
header->speed = rom[0x7fd5] >> 4;
header->chips = rom[0x7fd6];
header->romSize = 0x400 << rom[0x7fd7];
header->ramSize = 0x400 << rom[0x7fd8];
header->hasSram = header->chips > 0;
header->banks = header->romSize / 0x8000;
header->sramSize = cond(header->hasSram, header->ramSize, 0);
if (header->hasSram) sram = MAlloc(header->ramSize);
}
U0 LoROM(U8 *filename)
{
// LoROM loader
MemSet(&header, NULL, sizeof(ROMHeader));
I64 rom_length;
rom = FileRead(filename, &rom_length);
// skip copier header
if (rom_length%1024)
{
rom += 512;
rom_length -= 512;
}
parseHeader(rom, &header);
if (header.romSize < rom_length)
{
"Incorrect romSize?\n";
return;
}
}
+106
View File
@@ -0,0 +1,106 @@
#include "Lib/VMSVGA";
#include "Lib/Display";
#include "Lib/Graphics2D";
#include "Lib/uPNG";
#include "Lib/Misc";
#include "Lib/Debugger";
Context2D *screen_ctx = NewContext2D(640, 480, 32);
Context2D *pixel_ctx = NewContext2D(512, 480, 32);
#include "Font";
#include "Snes";
#include "LoROM";
#include "MMU";
#include "CPU";
#include "PPU";
U0 cpu_task()
{
while (1) { if (!Debug && !KeyDown(SC_F1)) cycle(0); };
}
U0 gfx_task()
{
while (1)
{
if (yPos>238 && !Debug)
{
setPixels(pixel_ctx->fb);
CopyRect2D(screen_ctx, (screen_ctx->width/2)-(pixel_ctx->width/2), 0, pixel_ctx);
UpdateTOSMenuBar(screen_ctx);
Flip2D(screen_ctx);
}
}
}
U0 input_loop()
{
while (1)
{
WinMsUpdate;
KbdMsHndlr(0, 0);
if (KeyDown(SC_ESC))
{
FifoI64Flush(kbd.down_bitmap);
Debug = TRUE;
Dbg;
}
if (KeyDown(Char2ScanCode('`')))
{
cpu_reset;
ppu_reset;
}
Joypad1Update;
Sleep(1);
}
}
U0 LoadCart(U8 *filename)
{
// FIXME: Add sanity checks
LoROM(filename);
U8 *info_string=CAlloc(1024);
StrPrint(append(info_string), "Loaded ROM: \"%s\"; \n", header.name);
StrPrint(append(info_string), "Type: LoROM\n");
StrPrint(append(info_string), "Banks: %d; Sram size: 0x%04X\n", header.banks, header.sramSize);
PopUpOk(info_string);
VMSVGA_Start;
SysFrameBufferInit;
cpu_reset;
Spawn(&cpu_task,,,1);
Spawn(&gfx_task,,,2);
input_loop;
Free(info_string);
}
U0 Bahamut(U8 *filename)
{
if (IsDir(filename))
{
PopUpOk("That's a directory...");
return;
}
CDirEntry *file = FilesFind(filename);
if (file)
{
DirTreeDel(file);
LoadCart(filename);
return;
}
else
{
PopUpOk("File not found...");
return;
}
}
while (1) Bahamut(PopUpPickFile("T:/ROMs/"));
+436
View File
@@ -0,0 +1,436 @@
extern U16 br[6];
extern I32 ppu_read(I32 adr);
extern U0 ppu_write(I32 adr, I32 value);
I64 cart_read(I64 bank, I64 adr)
{
//"bank: %d, addr: %08X\n", bank, adr;
if(adr < 0x8000) {
if(bank >= 0x70 && bank < 0x7e && header.hasSram) {
// sram
return sram[
(((bank - 0x70) << 15) | (adr & 0x7fff)) & (header.sramSize - 1)
];
return NULL;
}
}
return rom[((bank & (header.banks - 1)) << 15) | (adr & 0x7fff)];
}
U0 cart_write(I64 bank, I64 adr, I64 value)
{
if(adr < 0x8000 && bank >= 0x70 && bank < 0x7e && header.hasSram) {
sram[
(((bank - 0x70) << 15) | (adr & 0x7fff)) & (header.sramSize - 1)
] = value;
}
}
I64 readReg(I64 adr)
{
I64 val;
switch(adr) {
case 0x4210: {
val = 0x1;
val |= cond(inNmi, 0x80, 0);
val |= openBus & 0x70;
inNmi = FALSE;
return val;
}
case 0x4211: {
val = cond(inIrq, 0x80, 0);
val |= openBus & 0x7f;
inIrq = FALSE;
irqWanted = FALSE;
return val;
}
case 0x4212: {
val = cond(autoJoyBusy, 0x1, 0);
val |= cond(inHblank, 0x40, 0);
val |= cond(inVblank, 0x80, 0);
val |= openBus & 0x3e;
return val;
}
case 0x4213: {
// IO read register
return cond(ppuLatch, 0x80, 0);
}
case 0x4214: {
return divResult & 0xff;
}
case 0x4215: {
return (divResult & 0xff00) >> 8;
}
case 0x4216: {
return mulResult & 0xff;
}
case 0x4217: {
return (mulResult & 0xff00) >> 8;
}
case 0x4218: {
return joypad1AutoRead & 0xff;
}
case 0x4219: {
return (joypad1AutoRead & 0xff00) >> 8;
}
case 0x421a: {
return joypad2AutoRead & 0xff;
}
case 0x421b: {
return (joypad2AutoRead & 0xff00) >> 8;
}
case 0x421c:
case 0x421d:
case 0x421e:
case 0x421f: {
// joypads 3 and 4 not emulated
return 0;
}
}
if(adr >= 0x4300 && adr < 0x4380) {
I64 channel = (adr & 0xf0) >> 4;
switch(adr & 0xff0f) {
case 0x4300: {
val = dmaMode[channel];
val |= cond(dmaFixed[channel], 0x8, 0);
val |= cond(dmaDec[channel], 0x10, 0);
val |= cond(hdmaInd[channel], 0x40, 0);
val |= cond(dmaFromB[channel], 0x80, 0);
return val;
}
case 0x4301: {
return dmaBadr[channel];
}
case 0x4302: {
return dmaAadr[channel] & 0xff;
}
case 0x4303: {
return (dmaAadr[channel] & 0xff00) >> 8;
}
case 0x4304: {
return dmaAadrBank[channel];
}
case 0x4305: {
return dmaSize[channel] & 0xff;
}
case 0x4306: {
return (dmaSize[channel] & 0xff00) >> 8;
}
case 0x4307: {
return hdmaIndBank[channel];
}
case 0x4308: {
return hdmaTableAdr[channel] & 0xff;
}
case 0x4309: {
return (hdmaTableAdr[channel] & 0xff00) >> 8;
}
case 0x430a: {
return hdmaRepCount[channel];
}
}
}
return openBus;
}
U0 writeReg(I64 adr, I64 value) {
I64 channel;
switch(adr) {
case 0x4200: {
autoJoyRead = (value & 0x1) > 0;
hIrqEnabled = (value & 0x10) > 0;
vIrqEnabled = (value & 0x20) > 0;
nmiEnabled = (value & 0x80) > 0;
return;
}
case 0x4201: {
// IO port
if(ppuLatch && (value & 0x80) == 0) {
latchedHpos = xPos >> 2;
latchedVpos = yPos;
countersLatched = TRUE;
}
ppuLatch = (value & 0x80) > 0;
return;
}
case 0x4202: {
multiplyA = value;
return;
}
case 0x4203: {
mulResult = multiplyA * value;
return;
}
case 0x4204: {
divA = (divA & 0xff00) | value;
return;
}
case 0x4205: {
divA = (divA & 0xff) | (value << 8);
return;
}
case 0x4206: {
divResult = 0xffff;
mulResult = divA;
if(value != 0) {
divResult = (divA / value) & 0xffff;
mulResult = divA % value;
}
return;
}
case 0x4207: {
hTimer = (hTimer & 0x100) | value;
return;
}
case 0x4208: {
hTimer = (hTimer & 0xff) | ((value & 0x1) << 8);
return;
}
case 0x4209: {
vTimer = (vTimer & 0x100) | value;
return;
}
case 0x420a: {
vTimer = (vTimer & 0xff) | ((value & 0x1) << 8);
return;
}
case 0x420b: {
// enable dma
dmaActive[0] = (value & 0x1) > 0;
dmaActive[1] = (value & 0x2) > 0;
dmaActive[2] = (value & 0x4) > 0;
dmaActive[3] = (value & 0x8) > 0;
dmaActive[4] = (value & 0x10) > 0;
dmaActive[5] = (value & 0x20) > 0;
dmaActive[6] = (value & 0x40) > 0;
dmaActive[7] = (value & 0x80) > 0;
dmaBusy = value > 0;
dmaTimer += cond(dmaBusy, 8, 0);
return;
}
case 0x420c: {
hdmaActive[0] = (value & 0x1) > 0;
hdmaActive[1] = (value & 0x2) > 0;
hdmaActive[2] = (value & 0x4) > 0;
hdmaActive[3] = (value & 0x8) > 0;
hdmaActive[4] = (value & 0x10) > 0;
hdmaActive[5] = (value & 0x20) > 0;
hdmaActive[6] = (value & 0x40) > 0;
hdmaActive[7] = (value & 0x80) > 0;
return;
}
case 0x420d: {
fastMem = (value & 0x1) > 0;
return;
}
}
if(adr >= 0x4300 && adr < 0x4380) {
channel = (adr & 0xf0) >> 4;
switch(adr & 0xff0f) {
case 0x4300: {
dmaMode[channel] = value & 0x7;
dmaFixed[channel] = (value & 0x08) > 0;
dmaDec[channel] = (value & 0x10) > 0;
hdmaInd[channel] = (value & 0x40) > 0;
dmaFromB[channel] = (value & 0x80) > 0;
return;
}
case 0x4301: {
dmaBadr[channel] = value;
return;
}
case 0x4302: {
dmaAadr[channel] = (dmaAadr[channel] & 0xff00) | value;
return;
}
case 0x4303: {
dmaAadr[channel] = (dmaAadr[channel] & 0xff) | (value << 8);
return;
}
case 0x4304: {
dmaAadrBank[channel] = value;
return;
}
case 0x4305: {
dmaSize[channel] = (dmaSize[channel] & 0xff00) | value;
return;
}
case 0x4306: {
dmaSize[channel] = (dmaSize[channel] & 0xff) | (value << 8);
return;
}
case 0x4307: {
hdmaIndBank[channel] = value;
return;
}
case 0x4308: {
hdmaTableAdr[channel] = (
hdmaTableAdr[channel] & 0xff00
) | value;
return;
}
case 0x4309: {
hdmaTableAdr[channel] = (
hdmaTableAdr[channel] & 0xff
) | (value << 8);
return;
}
case 0x430a: {
hdmaRepCount[channel] = value;
return;
}
}
}
}
Bool flip_fake_spc = FALSE; // FIXME: Implement sound emulation
I64 readBBus(I64 adr) {
I64 val;
if(adr > 0x33 && adr < 0x40) {
return ppu_read(adr);
}
if(adr >= 0x40 && adr < 0x80) {
// catch up the apu, then do the read
catchUpApu;
// FIXME: Implement sound emulation
if (flip_fake_spc) return br[0];
flip_fake_spc = !flip_fake_spc;
return 0xBBAA;
//return spcWritePorts[adr & 0x3];
}
if(adr == 0x80) {
val = ram[ramAdr++];
ramAdr &= 0x1ffff;
return val;
}
return openBus; // rest not readable
}
U0 writeBBus(I64 adr, I64 value) {
if(adr < 0x34) {
ppu_write(adr, value);
return;
}
if(adr >= 0x40 && adr < 0x80) {
// catch up the apu, then do the write
catchUpApu;
spcReadPorts[adr & 0x3] = value;
return;
}
switch(adr) {
case 0x80: {
ram[ramAdr++] = value;
ramAdr &= 0x1ffff;
return;
}
case 0x81: {
ramAdr = (ramAdr & 0x1ff00) | value;
return;
}
case 0x82: {
ramAdr = (ramAdr & 0x100ff) | (value << 8);
return;
}
case 0x83: {
ramAdr = (ramAdr & 0x0ffff) | ((value & 1) << 16);
return;
}
}
return;
}
I64 mem_rread(I64 adr)
{
I64 val;
adr &= 0xffffff;
I64 bank = adr >> 16;
adr &= 0xffff;
if(bank == 0x7e || bank == 0x7f) {
// banks 7e and 7f
return ram[((bank & 0x1) << 16) | adr];
return NULL;
}
if(adr < 0x8000 && (bank < 0x40 || (bank >= 0x80 && bank < 0xc0))) {
// banks 00-3f, 80-bf, $0000-$7fff
if(adr < 0x2000) {
return ram[adr & 0x1fff];
return NULL;
}
if(adr >= 0x2100 && adr < 0x2200) {
return readBBus(adr & 0xff);
return NULL;
}
// old-style controller reads
if(adr == 0x4016) {
val = joypad1Val & 0x1;
joypad1Val >>= 1;
joypad1Val |= 0x8000;
return val;
}
if(adr == 0x4017) {
val = joypad2Val & 0x1;
joypad2Val >>= 1;
joypad2Val |= 0x8000;
return val;
}
if(adr >= 0x4200 && adr < 0x4400) {
return readReg(adr);
}
return openBus; // not readable
}
return cart_read(bank, adr);
}
I64 mem_read(I64 adr, Bool dma=FALSE)
{
if(!dma) {
cpuMemOps++;
cpuCyclesLeft += getAccessTime(adr);
}
I64 val = mem_rread(adr);
openBus = val;
return val;
}
U0 mem_write(I64 adr, I64 value, Bool dma = FALSE) {
if(!dma) {
cpuMemOps++;
cpuCyclesLeft += getAccessTime(adr);
}
openBus = value;
adr &= 0xffffff;
//log("Written $" + getByteRep(value) + " to $" + getLongRep(adr));
I64 bank = adr >> 16;
adr &= 0xffff;
if(bank == 0x7e || bank == 0x7f) {
// banks 7e and 7f
ram[((bank & 0x1) << 16) | adr] = value;
}
if(adr < 0x8000 && (bank < 0x40 || (bank >= 0x80 && bank < 0xc0))) {
// banks 00-3f, 80-bf, $0000-$7fff
if(adr < 0x2000) {
ram[adr & 0x1fff] = value;
}
if(adr >= 0x2100 && adr < 0x2200) {
writeBBus(adr & 0xff, value);
}
if(adr == 0x4016) {
joypadStrobe = (value & 0x1) > 0;
}
if(adr >= 0x4200 && adr < 0x4400) {
writeReg(adr, value);
}
}
cart_write(bank, adr, value);
}
+1397
View File
File diff suppressed because it is too large Load Diff
+1
View File
@@ -0,0 +1 @@
#include "Load";
+584
View File
@@ -0,0 +1,584 @@
extern I64 mem_read(I64 adr, Bool dma=FALSE);
extern U0 mem_write(I64 adr, I64 value, Bool dma = FALSE);
extern I64 readBBus(I64 adr);
extern U0 writeBBus(I64 adr, I64 value);
extern U0 cpu_cycle();
extern U0 renderLine(I32 line);
class ROMHeader
{
U8 *name;
I64 type;
I64 speed;
I64 chips;
I64 romSize;
I64 ramSize;
Bool hasSram;
I64 banks;
I64 sramSize;
};
ROMHeader header;
U8 *ram = MAlloc(0x20000);
U8 *sram;
U8 *rom;
// ppu variables
I64 cgramAdr;
Bool cgramSecond;
I64 cgramBuffer = 0;
I64 vramInc;
I64 vramRemap;
Bool vramIncOnHigh;
I64 vramAdr;
I64 vramReadBuffer;
Bool tilemapWider[4];
Bool tilemapHigher[4];
I64 tilemapAdr[4];
I64 tileAdr[4];
I64 bgHoff[5];
I64 bgVoff[5];
I64 offPrev1;
I64 offPrev2;
I64 mode;
Bool layer3Prio;
Bool bigTiles[4];
Bool mosaicEnabled[5];
I64 mosaicSize;
I64 mosaicStartLine;
Bool mainScreenEnabled[5];
Bool subScreenEnabled[5];
Bool forcedBlank;
I64 brightness;
I64 oamAdr;
I64 oamRegAdr;
Bool oamInHigh;
Bool oamRegInHigh;
Bool objPriority;
Bool oamSecond;
U16 oamBuffer;
I64 sprAdr1;
I64 sprAdr2;
I64 objSize;
Bool rangeOver;
Bool timeOver;
Bool mode7ExBg;
Bool pseudoHires;
Bool overscan;
Bool objInterlace;
Bool interlace;
Bool frameOverscan;
Bool frameInterlace;
Bool evenFrame;
I64 latchedHpos;
I64 latchedVpos;
Bool latchHsecond;
Bool latchVsecond;
Bool countersLatched;
I64 mode7Hoff;
I64 mode7Voff;
I64 mode7A;
I64 mode7B;
I64 mode7C;
I64 mode7D;
I64 mode7X;
I64 mode7Y;
I64 mode7Prev;
I64 multResult;
Bool mode7LargeField;
Bool mode7Char0fill;
Bool mode7FlipX;
Bool mode7FlipY;
Bool window1Inversed[6];
Bool window1Enabled[6];
Bool window2Inversed[6];
Bool window2Enabled[6];
I64 windowMaskLogic[6];
I64 window1Left;
I64 window1Right;
I64 window2Left;
I64 window2Right;
Bool mainScreenWindow[6];
Bool subScreenWindow[6];
I64 colorClip;
I64 preventMath;
Bool addSub;
Bool directColor;
Bool subtractColors;
Bool halfColors;
Bool mathEnabled[6];
I64 fixedColorB;
I64 fixedColorG;
I64 fixedColorR;
I64 tilemapBuffer[4];
I64 tileBufferP1[4];
I64 tileBufferP2[4];
I64 tileBufferP3[4];
I64 tileBufferP4[4];
I64 lastTileFetchedX[4];
I64 lastTileFetchedY[4];
I64 optHorBuffer[2];
I64 optVerBuffer[2];
I64 lastOrigTileX[2];
I64 dmaOffs[32] = {
0, 0, 0, 0,
0, 1, 0, 1,
0, 0, 0, 0,
0, 0, 1, 1,
0, 1, 2, 3,
0, 1, 0, 1,
0, 0, 0, 0,
0, 0, 1, 1
};
I64 dmaOffLengths[8] = {1, 2, 2, 4, 4, 4, 2, 4};
I64 apuCyclesPerMaster = (32040 * 32) / (1364 * 262 * 60);
U8 spcWritePorts[4];
U8 spcReadPorts[6];
// for dma
U8 dmaBadr[8];
U16 dmaAadr[8];
U8 dmaAadrBank[8];
U16 dmaSize[8];
U8 hdmaIndBank[8];
U16 hdmaTableAdr[8];
U8 hdmaRepCount[8];
I64 xPos = 0;
I64 yPos = 0;
I64 frames = 0;
I64 cpuCyclesLeft = 5 * 8 + 12; // reset: 5 read cycles + 2 IO cycles
I64 cpuMemOps = 0;
I64 apuCatchCycles = 0;
I64 cyclesLeft; // moved from CPU.HC
Bool irqWanted; // moved from CPU.HC
Bool nmiWanted; // moved from CPU.HC
// for cpu-ports
I64 ramAdr = 0;
Bool hIrqEnabled = FALSE;
Bool vIrqEnabled = FALSE;
Bool nmiEnabled = FALSE;
I64 hTimer = 0x1ff;
I64 vTimer = 0x1ff;
Bool inNmi = FALSE;
Bool inIrq = FALSE;
Bool inHblank = FALSE;
Bool inVblank = FALSE;
Bool autoJoyRead = FALSE;
Bool autoJoyBusy = FALSE;
I64 autoJoyTimer = 0;
Bool ppuLatch = FALSE;
I64 joypad1Val = 0;
I64 joypad2Val = 0;
I64 joypad1AutoRead = 0;
I64 joypad2AutoRead = 0;
Bool joypadStrobe = FALSE;
I64 joypad1State = 0; // current button state
I64 joypad2State = 0; // current button state
I64 multiplyA = 0xff;
I64 divA = 0xffff;
I64 divResult = 0x101;
I64 mulResult = 0xfe01;
Bool fastMem = FALSE;
// dma and hdma
I64 dmaTimer = 0;
I64 hdmaTimer = 0;
Bool dmaBusy = FALSE;
Bool dmaActive[8] = {FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE};
Bool hdmaActive[8] = {FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE};
I64 dmaMode[8] = {0, 0, 0, 0, 0, 0, 0, 0};
Bool dmaFixed[8] = {FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE};
Bool dmaDec[8] = {FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE};
Bool hdmaInd[8] = {FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE};
Bool dmaFromB[8] = {FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE};
Bool hdmaDoTransfer[8] = {
FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE
};
Bool hdmaTerminated[8] = {
FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE
};
I64 dmaOffIndex = 0;
I64 openBus = 0;
I64 getAccessTime(I64 adr) {
adr &= 0xffffff;
I64 bank = adr >> 16;
adr &= 0xffff;
if(bank >= 0x40 && bank < 0x80) {
// banks 0x40-0x7f, all slow
return 8;
}
if(bank >= 0xc0) {
// banks 0xc0-0xff, depends on speed
return cond(fastMem, 6, 8);
}
// banks 0x00-0x3f and 0x80-0xbf
if(adr < 0x2000) {
return 8; // slow
}
if(adr < 0x4000) {
return 6; // fast
}
if(adr < 0x4200) {
return 12; // extra slow
}
if(adr < 0x6000) {
return 6; // fast
}
if(adr < 0x8000) {
return 8; // slow
}
// 0x8000-0xffff, depends on fastrom setting if in banks 0x80+
return cond((fastMem && bank >= 0x80), 6, 8);
}
U0 catchUpApu() {
I64 i;
I64 catchUpCycles = apuCatchCycles & 0xffffffff;
for(i = 0; i < catchUpCycles; i++) {
//apu_cycle;
}
apuCatchCycles -= catchUpCycles;
}
U0 handleDma() {
I64 i, tableOff;
if(dmaTimer > 0) {
dmaTimer -= 2;
return;
}
// loop over each dma channel to find the first active one
for(i = 0; i < 8; i++) {
if(dmaActive[i]) {
break;
}
}
if(i == 8) {
// no active channel left, dma is done
dmaBusy = FALSE;
dmaOffIndex = 0;
//log("Finished DMA");
return;
}
tableOff = dmaMode[i] * 4 + dmaOffIndex++;
dmaOffIndex &= 0x3;
if(dmaFromB[i]) {
mem_write(
(dmaAadrBank[i] << 16) | dmaAadr[i],
readBBus(
(dmaBadr[i] + dmaOffs[tableOff]) & 0xff
), TRUE
);
} else {
writeBBus(
(dmaBadr[i] + dmaOffs[tableOff]) & 0xff,
mem_read((dmaAadrBank[i] << 16) | dmaAadr[i], TRUE)
);
}
dmaTimer += 6;
// because this run through the function itself also costs 2 master cycles,
// we have to wait 6 more to get to 8 per byte transferred
if(!dmaFixed[i]) {
if(dmaDec[i]) {
dmaAadr[i]--;
} else {
dmaAadr[i]++;
}
}
dmaSize[i]--;
if(dmaSize[i] == 0) {
dmaOffIndex = 0;
dmaActive[i] = FALSE;
dmaTimer += 8; // 8 extra cycles overhead per channel
}
}
U0 initHdma() {
hdmaTimer = 18;
I64 i;
for(i = 0; i < 8; i++) {
if(hdmaActive[i]) {
// terminate DMA if it was busy for this channel
dmaActive[i] = FALSE;
hdmaTableAdr[i] = dmaAadr[i];
hdmaRepCount[i] = mem_read(
(dmaAadrBank[i] << 16) | hdmaTableAdr[i]++, TRUE
);
hdmaTimer += 8;
if(hdmaInd[i]) {
dmaSize[i] = mem_read(
(dmaAadrBank[i] << 16) | hdmaTableAdr[i]++, TRUE
);
dmaSize[i] |= mem_read(
(dmaAadrBank[i] << 16) | hdmaTableAdr[i]++, TRUE
) << 8;
hdmaTimer += 16;
}
hdmaDoTransfer[i] = TRUE;
} else {
hdmaDoTransfer[i] = FALSE;
}
hdmaTerminated[i] = FALSE;
}
}
U0 handleHdma() {
I64 i, j, tableOff;
hdmaTimer = 18;
for(i = 0; i < 8; i++) {
if(hdmaActive[i] && !hdmaTerminated[i]) {
// terminate dma if it is busy on this channel
dmaActive[i] = FALSE;
hdmaTimer += 8;
if(hdmaDoTransfer[i]) {
for(j = 0; j < dmaOffLengths[dmaMode[i]]; j++) {
tableOff = dmaMode[i] * 4 + j;
hdmaTimer += 8;
if(hdmaInd[i]) {
if(dmaFromB[i]) {
mem_write(
(hdmaIndBank[i] << 16) | dmaSize[i],
readBBus(
(dmaBadr[i] + dmaOffs[tableOff]) & 0xff
), TRUE
);
} else {
writeBBus(
(dmaBadr[i] + dmaOffs[tableOff]) & 0xff,
mem_read((hdmaIndBank[i] << 16) | dmaSize[i], TRUE)
);
}
dmaSize[i]++;
} else {
if(dmaFromB[i]) {
mem_write(
(dmaAadrBank[i] << 16) | hdmaTableAdr[i],
readBBus(
(dmaBadr[i] + dmaOffs[tableOff]) & 0xff
), TRUE
);
} else {
writeBBus(
(dmaBadr[i] + dmaOffs[tableOff]) & 0xff,
mem_read(
(dmaAadrBank[i] << 16) | hdmaTableAdr[i], TRUE
)
);
}
hdmaTableAdr[i]++;
}
}
}
hdmaRepCount[i]--;
hdmaDoTransfer[i] = (hdmaRepCount[i] & 0x80) > 0;
if((hdmaRepCount[i] & 0x7f) == 0) {
hdmaRepCount[i] = mem_read(
(dmaAadrBank[i] << 16) | hdmaTableAdr[i]++, TRUE
);
if(hdmaInd[i]) {
dmaSize[i] = mem_read(
(dmaAadrBank[i] << 16) | hdmaTableAdr[i]++, TRUE
);
dmaSize[i] |= mem_read(
(dmaAadrBank[i] << 16) | hdmaTableAdr[i]++, TRUE
) << 8;
hdmaTimer += 16;
}
if(hdmaRepCount[i] == 0) {
hdmaTerminated[i] = TRUE;
}
hdmaDoTransfer[i] = TRUE;
}
}
}
}
U0 doAutoJoyRead() {
I64 i, bit;
joypad1AutoRead = 0;
joypad2AutoRead = 0;
joypad1Val = joypad1State;
joypad2Val = joypad2State;
for(i = 0; i < 16; i++) {
bit = joypad1Val & 0x1;
joypad1Val >>= 1;
joypad1Val |= 0x8000;
joypad1AutoRead |= (bit << (15 - i));
bit = joypad2Val & 0x1;
joypad2Val >>= 1;
joypad2Val |= 0x8000;
joypad2AutoRead |= (bit << (15 - i));
}
}
U0 cpuCycle() {
if(cpuCyclesLeft == 0) {
cyclesLeft = 0;
cpuMemOps = 0;
cpu_cycle;
cpuCyclesLeft += (cyclesLeft + 1 - cpuMemOps) * 6;
}
cpuCyclesLeft -= 2;
}
U0 cycle(Bool noPpu)
{
apuCatchCycles += (apuCyclesPerMaster * 2);
if(joypadStrobe) {
joypad1Val = joypad1State;
joypad2Val = joypad2State;
}
if(hdmaTimer > 0) {
hdmaTimer -= 2;
} else if(dmaBusy) {
handleDma;
} else if (xPos < 536 || xPos >= 576) {
// the cpu is paused for 40 cycles starting around dot 536
cpuCycle;
}
if(yPos == vTimer && vIrqEnabled) {
if(!hIrqEnabled) {
// only v irq enabed
if(xPos == 0) {
inIrq = TRUE;
irqWanted = TRUE;
}
} else {
// v and h irq enabled
if(xPos == (hTimer * 4)) {
inIrq = TRUE;
irqWanted = TRUE;
}
}
} else if (
xPos == (hTimer * 4)
&& hIrqEnabled && !vIrqEnabled
) {
// only h irq enabled
inIrq = TRUE;
irqWanted = TRUE;
}
if(xPos == 1024) {
// start of hblank
inHblank = TRUE;
if(!inVblank) {
handleHdma;
}
} else if(xPos == 0) {
// end of hblank
inHblank = FALSE;
} else if(xPos == 512 && !noPpu) {
// render line at cycle 512 for better support
renderLine(yPos);
}
//renderLine(yPos);
if(yPos == cond(frameOverscan, 240, 225) && xPos == 0) {
// start of vblank
inNmi = TRUE;
inVblank = TRUE;
if(autoJoyRead) {
autoJoyBusy = TRUE;
autoJoyTimer = 4224;
doAutoJoyRead;
}
if(nmiEnabled) {
nmiWanted = TRUE;
}
} else if(yPos == 0 && xPos == 0) {
// end of vblank
inNmi = FALSE;
inVblank = FALSE;
initHdma;
}
if(autoJoyBusy) {
autoJoyTimer -= 2; // loop only runs every second master cycle
if(autoJoyTimer == 0) {
autoJoyBusy = FALSE;
}
}
// TODO: in non-intelace mode, line 240 on every odd frame is 1360 cycles
// and in interlace mode, every even frame is 263 lines
xPos += 2;
if(xPos == 1364) {
xPos = 0;
yPos++;
if(yPos == 262) {
// when finishing a frame, also catch up the apu
catchUpApu;
yPos = 0;
frames++;
}
}
}
#define JPAD_Y 0
#define JPAD_B 1
#define JPAD_SELECT 2
#define JPAD_START 3
#define JPAD_UP 4
#define JPAD_DOWN 5
#define JPAD_LEFT 6
#define JPAD_RIGHT 7
#define JPAD_A 8
#define JPAD_X 9
#define JPAD_L 10
#define JPAD_R 11
U0 setPad1Button(I64 num, I64 sc)
{
switch (KeyDown(sc))
{
case 0:
joypad1State &= (~(1 << num)) & 0xfff;
break;
case 1:
joypad1State |= (1 << num);
break;
}
}
U0 Joypad1Update()
{
setPad1Button(JPAD_Y, Char2ScanCode('z'));
setPad1Button(JPAD_B, Char2ScanCode('a'));
setPad1Button(JPAD_X, Char2ScanCode('s'));
setPad1Button(JPAD_A, Char2ScanCode('x'));
setPad1Button(JPAD_L, Char2ScanCode('d'));
setPad1Button(JPAD_R, Char2ScanCode('c'));
setPad1Button(JPAD_SELECT, SC_SHIFT);
setPad1Button(JPAD_START, SC_ENTER);
setPad1Button(JPAD_UP, SC_CURSOR_UP);
setPad1Button(JPAD_DOWN, SC_CURSOR_DOWN);
setPad1Button(JPAD_LEFT, SC_CURSOR_LEFT);
setPad1Button(JPAD_RIGHT, SC_CURSOR_RIGHT);
}
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB