Something went wrong. Try again.
A modern, network-enabled music player platform built on Rockbox technology. rockboxd.tsiry-sandratraina.com
rust deno navidrome airplay libadwaita zig mpris snapcast mpd rockbox audio subsonic
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638/*************************************************************************** * __________ __ ___. * Open \______ \ ____ ____ | | _\_ |__ _______ ___ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ * \/ \/ \/ \/ \/ * * Orginal from Vision-8 Emulator / Copyright (C) 1997-1999 Marcel de Kogel * Modified for Archos by Blueloop (a.wenger@gmx.de) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY * KIND, either express or implied. * ****************************************************************************/#include "plugin.h"
#define EXTERN static#define STATIC static#define memset rb->memset#define memcpy rb->memcpy#define printf DEBUGF#define rand rb->rand/* #define CHIP8_DEBUG */
#if (LCD_WIDTH >= 112) && (LCD_HEIGHT >= 64)#define CHIP8_SUPER /* SCHIP even on the archos recorder (112x64) */#endif
/****************************************************************************//** (S)CHIP-8 core emulation, from Vision-8 + mods by Fdy **//** The core is completely generic and can be used outside of Rockbox, **//** thus the STATIC, EXTERN etc. Please do not modify. **//****************************************************************************//** Vision8: CHIP8 emulator *************************************************//** **//** CHIP8.h **//** **//** This file contains the portable CHIP8 emulation engine definitions **//** **//** Copyright (C) Marcel de Kogel 1997 **//** You are not allowed to distribute this software commercially **//** Please, notify me, if you make any changes to this file **//****************************************************************************/
#ifndef __CHIP8_H#define __CHIP8_H
#ifndef EXTERN#define EXTERN extern#endif
typedef unsigned char byte; /* sizeof(byte)==1 */typedef unsigned short word; /* sizeof(word)>=2 */
struct chip8_regs_struct{ byte alg[16]; /* 16 general registers */ byte delay,sound; /* delay and sound timer */ word i; /* index register */ word pc; /* program counter */ word sp; /* stack pointer */};
EXTERN struct chip8_regs_struct chip8_regs;
#ifdef CHIP8_SUPER#define CHIP8_WIDTH 128#define CHIP8_HEIGHT 64EXTERN byte chip8_super; /* != 0 if in SCHIP display mode */#else#define CHIP8_WIDTH 64#define CHIP8_HEIGHT 32#endif
EXTERN byte chip8_iperiod; /* number of opcodes per */ /* timeslice (1/50sec.) */EXTERN byte chip8_keys[16]; /* if 1, key is held down */EXTERN byte chip8_display[CHIP8_WIDTH*CHIP8_HEIGHT];/* 0xff if pixel is set, */ /* 0x00 otherwise */EXTERN byte chip8_mem[4096]; /* machine memory. program */ /* is loaded at 0x200 */EXTERN byte chip8_running; /* if 0, emulation stops */
EXTERN void chip8_execute (void); /* execute chip8_iperiod */ /* opcodes */EXTERN void chip8_reset (void); /* reset virtual machine */EXTERN void chip8 (void); /* start chip8 emulation */
EXTERN void chip8_sound_on (void); /* turn sound on */EXTERN void chip8_sound_off (void); /* turn sound off */EXTERN void chip8_interrupt (void); /* update keyboard, */ /* display, etc. */
#ifdef CHIP8_DEBUGEXTERN byte chip8_trace; /* if 1, call debugger */ /* every opcode */EXTERN word chip8_trap; /* if pc==trap, set trace */ /* flag */EXTERN void chip8_debug (word opcode,struct chip8_regs_struct *regs);#endif
#endif /* __CHIP8_H */
/** Vision8: CHIP8 emulator *************************************************//** **//** CHIP8.c **//** **//** This file contains the portable CHIP8 emulation engine **//** SCHIP emulation (C) Frederic Devernay 2005 **//** **//** Copyright (C) Marcel de Kogel 1997 **//** You are not allowed to distribute this software commercially **//** Please, notify me, if you make any changes to this file **//****************************************************************************/
/* you can #define STATIC static #define EXTERN static and include this file for single-object generation*/
#ifndef STATIC#include <stdlib.h> /* for memset, etc. */#include <string.h>#define STATIC#endif
#ifdef CHIP8_DEBUG#include <stdio.h>#define DBG_(_x) ((void)(_x))#else#define DBG_(_x) ((void)0)#endif
STATIC struct chip8_regs_struct chip8_regs;
static byte chip8_key_pressed;STATIC byte chip8_keys[16]; /* if 1, key is held down */STATIC byte chip8_display[CHIP8_WIDTH*CHIP8_HEIGHT]; /* 0xff if pixel is set, */ /* 0x00 otherwise */#ifdef CHIP8_SUPERSTATIC byte chip8_super; /* != 0 if in SCHIP display mode */#endifSTATIC byte chip8_mem[4096]; /* machine memory. program */ /* is loaded at 0x200 */
#define read_mem(a) (chip8_mem[(a)&4095])#define write_mem(a,v) (chip8_mem[(a)&4095]=(v))
STATIC byte chip8_iperiod;
STATIC byte chip8_running; /* Flag for End-of-Emulation */
#define get_reg_offset(opcode) (chip8_regs.alg+(opcode>>8))#define get_reg_value(opcode) (*get_reg_offset(opcode))#define get_reg_offset_2(opcode) (chip8_regs.alg+((opcode>>4)&0x0f))#define get_reg_value_2(opcode) (*get_reg_offset_2(opcode))
typedef void (*opcode_fn) (word opcode);typedef void (*math_fn) (byte *reg1,byte reg2);
static void op_call (word opcode){ chip8_regs.sp--; write_mem (chip8_regs.sp,chip8_regs.pc&0xff); chip8_regs.sp--; write_mem (chip8_regs.sp,chip8_regs.pc>>8); chip8_regs.pc=opcode;#ifdef CHIP8_DEBUG if(chip8_regs.sp < 0x1c0) printf("warning: more than 16 subroutine calls, sp=%x\n", chip8_regs.sp);#endif}
static void op_jmp (word opcode){ chip8_regs.pc=opcode;}
static void op_key (word opcode){#ifdef CHIP8_DEBUG static byte tested[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};#endif byte key, key_value,cp_value; if ((opcode&0xff)==0x9e) /* skp */ cp_value=1; else if ((opcode&0xff)==0xa1) /* sknp */ cp_value=0; else { DBG_(printf("unhandled key opcode 0x%x\n", opcode)); return; } key = get_reg_value(opcode)&0x0f;#ifdef CHIP8_DEBUG if (!tested[key]) { tested[key] = 1; DBG_(printf("testing key %d\n", key)); }#endif key_value=chip8_keys[key]; if (cp_value==key_value) chip8_regs.pc+=2;}
static void op_skeq_const (word opcode){ if (get_reg_value(opcode)==(opcode&0xff)) chip8_regs.pc+=2;}
static void op_skne_const (word opcode){ if (get_reg_value(opcode)!=(opcode&0xff)) chip8_regs.pc+=2;}
static void op_skeq_reg (word opcode){ if (get_reg_value(opcode)==get_reg_value_2(opcode)) chip8_regs.pc+=2;}
static void op_skne_reg (word opcode){ if (get_reg_value(opcode)!=get_reg_value_2(opcode)) chip8_regs.pc+=2;}
static void op_mov_const (word opcode){ *get_reg_offset(opcode)=opcode&0xff;}
static void op_add_const (word opcode){ *get_reg_offset(opcode)+=opcode&0xff;}
static void op_mvi (word opcode){ chip8_regs.i=opcode;}
static void op_jmi (word opcode){ chip8_regs.pc=opcode+chip8_regs.alg[0];}
static void op_rand (word opcode){ *get_reg_offset(opcode)=rand()&(opcode&0xff);}
static void math_or (byte *reg1,byte reg2){ *reg1|=reg2;}
static void math_mov (byte *reg1,byte reg2){ *reg1=reg2;}
static void math_nop (byte *reg1,byte reg2){ (void)reg1; (void)reg2; DBG_(printf("Warning: math nop!\n"));}
static void math_and (byte *reg1,byte reg2){ *reg1&=reg2;}
static void math_xor (byte *reg1,byte reg2){ *reg1^=reg2;}
static void math_add (byte *reg1,byte reg2){ word tmp; tmp=*reg1+reg2; *reg1=(byte)tmp; chip8_regs.alg[15]=tmp>>8;}
static void math_sub (byte *reg1,byte reg2){ word tmp; tmp=*reg1-reg2; *reg1=(byte)tmp; chip8_regs.alg[15]=((byte)(tmp>>8))+1;}
static void math_shr (byte *reg1,byte reg2){ (void)reg2; chip8_regs.alg[15]=*reg1&1; *reg1>>=1;}
static void math_shl (byte *reg1,byte reg2){ (void)reg2; chip8_regs.alg[15]=*reg1>>7; *reg1<<=1;}
static void math_rsb (byte *reg1,byte reg2){ word tmp; tmp=reg2-*reg1; *reg1=(byte)tmp; chip8_regs.alg[15]=((byte)(tmp>>8))+1;}
#ifdef CHIP8_SUPER/* SUPER: scroll down n lines (or half in CHIP8 mode) */static void scroll_down(word opcode){ int n = opcode & 0xf; byte *dst = chip8_display + CHIP8_WIDTH*CHIP8_HEIGHT -1; byte *src = dst - n*CHIP8_WIDTH; while(src >= chip8_display) { *dst-- = *src--; } while(dst >= chip8_display) { *dst-- = 0; }}/* SUPER: scroll 4 pixels left! */static void scroll_left(void){ byte *dst = chip8_display; byte *src = dst; byte *eol = chip8_display + CHIP8_WIDTH; byte *eoi = chip8_display + CHIP8_WIDTH*CHIP8_HEIGHT; while(eol <= eoi) { src+=4; while(src < eol) { *dst++ = *src++; } *dst++ = 0; *dst++ = 0; *dst++ = 0; *dst++ = 0; eol += CHIP8_WIDTH; }}static void scroll_right(void){ byte *dst = chip8_display + CHIP8_WIDTH*CHIP8_HEIGHT -1; byte *src = dst; byte *bol = chip8_display + CHIP8_WIDTH*(CHIP8_HEIGHT-1); while(bol >= chip8_display) { src-=4; while(src >= bol) { *dst-- = *src--; } *dst-- = 0; *dst-- = 0; *dst-- = 0; *dst-- = 0; bol -= CHIP8_WIDTH; }}#endif
static void op_system (word opcode){ switch ((byte)opcode) {#ifdef CHIP8_SUPER case 0xfb: scroll_right(); break; case 0xfc: scroll_left(); break; case 0xfd: DBG_(printf("SUPER: quit the emulator\n")); chip8_reset(); break; case 0xfe: DBG_(printf("SUPER: set CHIP-8 graphic mode\n")); memset (chip8_display,0,sizeof(chip8_display)); chip8_super = 0; break; case 0xff: DBG_(printf("SUPER: set SCHIP graphic mode\n")); memset (chip8_display,0,sizeof(chip8_display)); chip8_super = 1; break;#endif case 0xe0: memset (chip8_display,0,sizeof(chip8_display)); break; case 0xee: chip8_regs.pc=read_mem(chip8_regs.sp)<<8; chip8_regs.sp++; chip8_regs.pc+=read_mem(chip8_regs.sp); chip8_regs.sp++; break; default:#ifdef CHIP8_SUPER if ((opcode & 0xF0) == 0xC0) scroll_down(opcode); else#endif { DBG_(printf("unhandled system opcode 0x%x\n", opcode)); chip8_running = 3; } break; }}
static void op_misc (word opcode){ byte *reg,i,j;#ifdef CHIP8_DEBUG static byte firstwait = 1;#endif reg=get_reg_offset(opcode); switch ((byte)opcode) { case 0x07: /* gdelay */ *reg=chip8_regs.delay; break; case 0x0a: /* key */#ifdef CHIP8_DEBUG if(firstwait) { printf("waiting for key press\n"); firstwait = 0; }#endif if (chip8_key_pressed) *reg=chip8_key_pressed-1; else chip8_regs.pc-=2; break; case 0x15: /* sdelay */ chip8_regs.delay=*reg; break; case 0x18: /* ssound */ chip8_regs.sound=*reg; if (chip8_regs.sound) chip8_sound_on(); break; case 0x1e: /* adi */ chip8_regs.i+=(*reg); break; case 0x29: /* font */ chip8_regs.i=((word)(*reg&0x0f))*5; break;#ifdef CHIP8_SUPER case 0x30: /* xfont */ chip8_regs.i=((word)(*reg&0x0f))*10+0x50; break;#endif case 0x33: /* bcd */ i=*reg; for (j=0;i>=100;i-=100) j++; write_mem (chip8_regs.i,j); for (j=0;i>=10;i-=10) j++; write_mem (chip8_regs.i+1,j); write_mem (chip8_regs.i+2,i); break; case 0x55: /* str */ for (i=0,j=(opcode>>8)&0x0f; i<=j; ++i) write_mem(chip8_regs.i+i,chip8_regs.alg[i]); break; case 0x65: /* ldr */ for (i=0,j=(opcode>>8)&0x0f; i<=j; ++i) chip8_regs.alg[i]=read_mem(chip8_regs.i+i); break;#ifdef CHIP8_SUPER case 0x75: DBG_(printf("SUPER: save V0..V%x (X<8) in the HP48 flags\n", (opcode>>8)&0x0f)); break; case 0x85: DBG_(printf("SUPER: load V0..V%x (X<8) from the HP48 flags\n", (opcode>>8)&0x0f)); break;#endif default: DBG_(printf("unhandled misc opcode 0x%x\n", opcode)); break; }}
static void op_sprite (word opcode){ byte *q; byte n,x,x2,y,collision; word p; x=get_reg_value(opcode); y=get_reg_value_2(opcode); p=chip8_regs.i; n=opcode&0x0f;#ifdef CHIP8_SUPER if (chip8_super) { /*printf("SUPER: sprite(%x)\n", opcode);*/ x &= 128-1; y &= 64-1; q=chip8_display+y*CHIP8_WIDTH; if(n == 0) { /* 16x16 sprite */ n = 16; if (n+y>64) n=64-y; for (collision=1;n;--n,q+=CHIP8_WIDTH) { /* first 8 bits */ for (y=read_mem(p++),x2=x;y;y<<=1,x2=(x2+1)&(CHIP8_WIDTH-1)) if (y&0x80) collision&=(q[x2]^=0xff); x2=(x+8)&(CHIP8_WIDTH-1); /* last 8 bits */ for (y=read_mem(p++);y;y<<=1,x2=(x2+1)&(CHIP8_WIDTH-1)) if (y&0x80) collision&=(q[x2]^=0xff); } } else { /* 8xn sprite */ if (n+y>64) n=64-y; for (collision=1;n;--n,q+=CHIP8_WIDTH) { for (y=read_mem(p++),x2=x;y;y<<=1,x2=(x2+1)&(CHIP8_WIDTH-1)) if (y&0x80) collision&=(q[x2]^=0xff); } } } else { x &= 64-1; y &= 32-1; q=chip8_display+y*CHIP8_WIDTH*2; if(n == 0) n = 16; if (n+y>32) n=32-y; for (collision=1;n;--n,q+=CHIP8_WIDTH*2) { for (y=read_mem(p++),x2=x*2;y;y<<=1,x2=(x2+2)&(CHIP8_WIDTH-1)) if (y&0x80) { q[x2]^=0xff; q[x2+1]^=0xff; q[x2+CHIP8_WIDTH]^=0xff; q[x2+CHIP8_WIDTH+1]^=0xff; collision &= q[x2]|q[x2+1]|q[x2+CHIP8_WIDTH]|q[x2+CHIP8_WIDTH+1]; } } }#else x &= 64-1; y &= 32-1; q=chip8_display+y*CHIP8_WIDTH; if (n+y>32) n=32-y; for (collision=1;n;--n,q+=CHIP8_WIDTH) { for (y=read_mem(p++),x2=x;y;y<<=1,x2=(x2+1)&(CHIP8_WIDTH-1)) if (y&0x80) collision&=(q[x2]^=0xff); }#endif chip8_regs.alg[15]=collision^1;}
static const math_fn math_opcodes[16]={ math_mov, math_or, math_and, math_xor, math_add, math_sub, math_shr, math_rsb, math_nop, math_nop, math_nop, math_nop, math_nop, math_nop, math_shl, math_nop};
static void op_math (word opcode){ (*(math_opcodes[opcode&0x0f])) (get_reg_offset(opcode),get_reg_value_2(opcode));}
static const opcode_fn main_opcodes[16]={ op_system, op_jmp, op_call, op_skeq_const, op_skne_const, op_skeq_reg, op_mov_const, op_add_const, op_math, op_skne_reg, op_mvi, op_jmi, op_rand, op_sprite, op_key, op_misc};
#ifdef CHIP8_DEBUGSTATIC byte chip8_trace;STATIC word chip8_trap;
/****************************************************************************//* This routine is called every opcode when chip8_trace==1. It prints the *//* current register contents and the opcode being executed *//****************************************************************************/STATIC void chip8_debug (word opcode,struct chip8_regs_struct *regs){ int i; static const byte hextable[16] = "0123456789ABCDEF"; byte v1[3] = "Vx\0"; byte v2[3] = "Vx\0"; v1[1] = hextable[(opcode>>8)&0x0f]; v2[1] = hextable[(opcode>>8)&0x0f]; printf ("PC=%04X: %04X - ",regs->pc,opcode); switch (opcode>>12) { case 0: if ((opcode&0xff0) == 0xc0) { printf ("SCD %01X ; Scroll down n lines",opcode&0xf); } else switch (opcode&0xfff) { case 0xe0: printf ("CLS ; Clear screen"); break; case 0xee: printf ("RET ; Return from subroutine call"); break; case 0xfb: printf("SCR ; Scroll right"); break; case 0xfc: printf("SCL ; Scroll left"); break; case 0xfd: printf("EXIT ; Terminate the interpreter"); break; case 0xfe: printf("LOW ; Disable extended screen mode"); break; case 0xff: printf("HIGH ; Enable extended screen mode"); break; default: printf ("SYS %03X ; Unknown system call",opcode&0xff); } break; case 1: printf ("JP %03X ; Jump to address",opcode&0xfff); break; case 2: printf ("CALL %03X ; Call subroutine",opcode&0xfff); break; case 3: printf ("SE %s,%02X ; Skip if register == constant",v1,opcode&0xff); break; case 4: printf ("SNE %s,%02X ; Skip if register <> constant",v1,opcode&0xff); break; case 5: printf ("SE %s,%s ; Skip if register == register",v1,v2); break; case 6: printf ("LD %s,%02X ; Set VX = Byte",v1,opcode&0xff); break; case 7: printf ("ADD %s,%02X ; Set VX = VX + Byte",v1,opcode&0xff); break; case 8: switch (opcode&0x0f) { case 0: printf ("LD %s,%s ; Set VX = VY, VF updates",v1,v2); break; case 1: printf ("OR %s,%s ; Set VX = VX | VY, VF updates",v1,v2); break; case 2: printf ("AND %s,%s ; Set VX = VX & VY, VF updates",v1,v2); break; case 3: printf ("XOR %s,%s ; Set VX = VX ^ VY, VF updates",v1,v2); break; case 4: printf ("ADD %s,%s ; Set VX = VX + VY, VF = carry",v1,v2); break; case 5: printf ("SUB %s,%s ; Set VX = VX - VY, VF = !borrow",v1,v2); break; case 6: printf ("SHR %s,%s ; Set VX = VX >> 1, VF = carry",v1,v2); break; case 7: printf ("SUBN %s,%s ; Set VX = VY - VX, VF = !borrow",v1,v2); break; case 14: printf ("SHL %s,%s ; Set VX = VX << 1, VF = carry",v1,v2); break; default: printf ("Illegal opcode"); } break; case 9: printf ("SNE %s,%s ; Skip next instruction iv VX!=VY",v1,v2); break; case 10: printf ("LD I,%03X ; Set I = Addr",opcode&0xfff); break; case 11: printf ("JP V0,%03X ; Jump to Addr + V0",opcode&0xfff); break; case 12: printf ("RND %s,%02X ; Set VX = random & Byte",v1,opcode&0xff); break; case 13: printf ("DRW %s,%s,%X ; Draw n byte sprite stored at [i] at VX,VY. Set VF = collision",v1,v2,opcode&0x0f); break; case 14: switch (opcode&0xff) { case 0x9e: printf ("SKP %s ; Skip next instruction if key VX down",v1); break; case 0xa1: printf ("SKNP %s ; Skip next instruction if key VX up",v1); break; default: printf ("%04X ; Illegal opcode", opcode); } break; case 15: switch (opcode&0xff) { case 0x07: printf ("LD %s,DT ; Set VX = delaytimer",v1); break; case 0x0a: printf ("LD %s,K ; Set VX = key, wait for keypress",v1); break; case 0x15: printf ("LD DT,%s ; Set delaytimer = VX",v1); break; case 0x18: printf ("LD ST,%s ; Set soundtimer = VX",v1); break; case 0x1e: printf ("ADD I,%s ; Set I = I + VX",v1); break; case 0x29: printf ("LD LF,%s ; Point I to 5 byte numeric sprite for value in VX",v1); break; case 0x30: printf ("LD HF,%s ; Point I to 10 byte numeric sprite for value in VX",v1); break; case 0x33: printf ("LD B,%s ; Store BCD of VX in [I], [I+1], [I+2]",v1); break; case 0x55: printf ("LD [I],%s ; Store V0..VX in [I]..[I+X]",v1); break; case 0x65: printf ("LD %s,[I] ; Read V0..VX from [I]..[I+X]",v1); break; case 0x75: printf ("LD R,%s ; Store V0..VX in RPL user flags (X<=7)",v1); break; case 0x85: printf ("LD %s,R ; Read V0..VX from RPL user flags (X<=7)",v1); break; default: printf ("%04X ; Illegal opcode", opcode); } break; } printf ("\n; Registers: "); for (i=0;i<16;++i) printf ("%02x ",(regs->alg[i])&0xff); printf ("\n; Index: %03x Stack:%03x Delay:%02x Sound:%02x\n", regs->i&0xfff,regs->sp&0xfff,regs->delay&0xff,regs->sound&0xff);}#endif
/****************************************************************************//* Execute chip8_iperiod opcodes *//****************************************************************************/STATIC void chip8_execute(void){ byte i; byte key_pressed=0; word opcode; for (i = chip8_iperiod ; i ;--i) { /* Fetch the opcode */ opcode=(read_mem(chip8_regs.pc)<<8)+read_mem(chip8_regs.pc+1);#ifdef CHIP8_DEBUG /* Check if trap address has been reached */ if ((chip8_regs.pc&4095)==chip8_trap) chip8_trace=1; /* Call the debugger if chip8_trace!=0 */ if (chip8_trace) chip8_debug (opcode,&chip8_regs);#endif chip8_regs.pc+=2; (*(main_opcodes[opcode>>12]))(opcode&0x0fff); /* Emulate this opcode */ } /* Update timers */ if (chip8_regs.delay) --chip8_regs.delay; if (chip8_regs.sound) if (--chip8_regs.sound == 0) chip8_sound_off();
/* Update the machine status */ chip8_interrupt ();
for (i=key_pressed=0;i<16;++i) /* check if a key was first */ if (chip8_keys[i]) /* pressed */ key_pressed=i+1; if (key_pressed && key_pressed!=chip8_key_pressed) chip8_key_pressed=key_pressed; else chip8_key_pressed=0;}
/****************************************************************************//* Reset the virtual chip8 machine *//****************************************************************************/STATIC void chip8_reset(void){ static const byte chip8_sprites[0x50]= { 0xf9,0x99,0xf2,0x62,0x27, 0xf1,0xf8,0xff,0x1f,0x1f, 0x99,0xf1,0x1f,0x8f,0x1f, 0xf8,0xf9,0xff,0x12,0x44, 0xf9,0xf9,0xff,0x9f,0x1f, 0xf9,0xf9,0x9e,0x9e,0x9e, 0xf8,0x88,0xfe,0x99,0x9e, 0xf8,0xf8,0xff,0x8f,0x88, }; /* 4x5 pixel hexadecimal character font patterns */#ifdef CHIP8_SUPER static const byte schip_sprites[10*10]= { 0x3C, 0x7E, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0x7E, 0x3C, /* 0 */ 0x18, 0x38, 0x58, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3C, /* 1 */ 0x3E, 0x7F, 0xC3, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xFF, 0xFF, /* 2 */ 0x3C, 0x7E, 0xC3, 0x03, 0x0E, 0x0E, 0x03, 0xC3, 0x7E, 0x3C, /* 3 */ 0x06, 0x0E, 0x1E, 0x36, 0x66, 0xC6, 0xFF, 0xFF, 0x06, 0x06, /* 4 */ 0xFF, 0xFF, 0xC0, 0xC0, 0xFC, 0xFE, 0x03, 0xC3, 0x7E, 0x3C, /* 5 */ 0x3E, 0x7C, 0xC0, 0xC0, 0xFC, 0xFE, 0xC3, 0xC3, 0x7E, 0x3C, /* 6 */ 0xFF, 0xFF, 0x03, 0x06, 0x0C, 0x18, 0x30, 0x60, 0x60, 0x60, /* 7 */ 0x3C, 0x7E, 0xC3, 0xC3, 0x7E, 0x7E, 0xC3, 0xC3, 0x7E, 0x3C, /* 8 */ 0x3C, 0x7E, 0xC3, 0xC3, 0x7F, 0x3F, 0x03, 0x03, 0x3E, 0x7C, /* 9 */ }; /* 8x10 pixel font patterns (only 10) */#endif byte i; for (i=0;i<16*5;++i) { write_mem (i<<1,chip8_sprites[i]&0xf0); write_mem ((i<<1)+1,chip8_sprites[i]<<4); }#ifdef CHIP8_SUPER /* for (i=0; i<100; i++) write_mem (i+0x50,schip_sprites[i]); */ memcpy(chip8_mem+0x50, schip_sprites, 100); chip8_super = 0;#endif memset (chip8_regs.alg,0,sizeof(chip8_regs.alg)); memset (chip8_keys,0,sizeof(chip8_keys)); chip8_key_pressed=0; memset (chip8_display,0,sizeof(chip8_display)); chip8_regs.delay=chip8_regs.sound=chip8_regs.i=0; chip8_regs.sp=0x1e0; chip8_regs.pc=0x200; chip8_sound_off (); chip8_running=1;#ifdef CHIP8_DEBUG chip8_trace=0;#endif}
/****************************************************************************//* Start CHIP8 emulation *//****************************************************************************/STATIC void chip8 (void){ chip8_reset (); while (chip8_running==1) chip8_execute ();}
/****************************************************************************//** END OF (S)CHIP-8 core emulation, from Vision-8 + mods by Fdy **//****************************************************************************/
/* size of the displayed area */#if (CHIP8_WIDTH == 128) && (LCD_WIDTH < 128)#define CHIP8_LCDWIDTH 112#else#define CHIP8_LCDWIDTH CHIP8_WIDTH#endif
#if (LCD_WIDTH > CHIP8_LCDWIDTH)#define CHIP8_X ((LCD_WIDTH - CHIP8_LCDWIDTH)/2)#else#define CHIP8_X 0#endif#if (LCD_HEIGHT > CHIP8_HEIGHT)#define CHIP8_Y (((LCD_HEIGHT - CHIP8_HEIGHT)>>4)<<3)#else#define CHIP8_Y 0#endif
/* variable button definitions */#if (CONFIG_KEYPAD == IRIVER_H100_PAD) || \ (CONFIG_KEYPAD == IRIVER_H300_PAD)#define CHIP8_OFF BUTTON_OFF#define CHIP8_KEY2 BUTTON_UP#define CHIP8_KEY4 BUTTON_LEFT#define CHIP8_KEY5 BUTTON_SELECT#define CHIP8_KEY6 BUTTON_RIGHT#define CHIP8_KEY8 BUTTON_DOWN
#define CHIP8_RC_OFF BUTTON_RC_STOP
#elif (CONFIG_KEYPAD == IPOD_4G_PAD) || \ (CONFIG_KEYPAD == IPOD_3G_PAD) || \ (CONFIG_KEYPAD == IPOD_1G2G_PAD)#define CHIP8_OFF BUTTON_MENU#define CHIP8_KEY2 BUTTON_SCROLL_BACK#define CHIP8_KEY4 BUTTON_LEFT#define CHIP8_KEY5 BUTTON_PLAY#define CHIP8_KEY6 BUTTON_RIGHT#define CHIP8_KEY8 BUTTON_SCROLL_FWD
#elif (CONFIG_KEYPAD == IAUDIO_X5M5_PAD)#define CHIP8_OFF BUTTON_POWER#define CHIP8_KEY2 BUTTON_UP#define CHIP8_KEY4 BUTTON_LEFT#define CHIP8_KEY5 BUTTON_SELECT#define CHIP8_KEY6 BUTTON_RIGHT#define CHIP8_KEY8 BUTTON_DOWN
#elif (CONFIG_KEYPAD == GIGABEAT_PAD)#define CHIP8_OFF BUTTON_POWER#define CHIP8_KEY1 BUTTON_MENU#define CHIP8_KEY2 BUTTON_UP#define CHIP8_KEY3 BUTTON_VOL_DOWN#define CHIP8_KEY4 BUTTON_LEFT#define CHIP8_KEY5 BUTTON_SELECT#define CHIP8_KEY6 BUTTON_RIGHT#define CHIP8_KEY7 BUTTON_VOL_UP#define CHIP8_KEY8 BUTTON_DOWN#define CHIP8_KEY9 BUTTON_A
#elif CONFIG_KEYPAD == SANSA_E200_PAD || \ CONFIG_KEYPAD == SANSA_FUZE_PAD#define CHIP8_OFF BUTTON_POWER#define CHIP8_KEY2 BUTTON_SCROLL_BACK#define CHIP8_KEY4 BUTTON_LEFT#define CHIP8_KEY5 BUTTON_SELECT#define CHIP8_KEY6 BUTTON_RIGHT#define CHIP8_KEY8 BUTTON_SCROLL_FWD
#elif CONFIG_KEYPAD == SANSA_C200_PAD || \CONFIG_KEYPAD == SANSA_CLIP_PAD || \CONFIG_KEYPAD == SANSA_M200_PAD#define CHIP8_OFF BUTTON_POWER#define CHIP8_KEY2 BUTTON_UP#define CHIP8_KEY4 BUTTON_LEFT#define CHIP8_KEY5 BUTTON_SELECT#define CHIP8_KEY6 BUTTON_RIGHT#define CHIP8_KEY8 BUTTON_DOWN
#elif (CONFIG_KEYPAD == IRIVER_H10_PAD)#define CHIP8_OFF BUTTON_POWER#define CHIP8_KEY2 BUTTON_SCROLL_UP#define CHIP8_KEY4 BUTTON_LEFT#define CHIP8_KEY5 BUTTON_PLAY#define CHIP8_KEY6 BUTTON_RIGHT#define CHIP8_KEY8 BUTTON_SCROLL_DOWN
#elif (CONFIG_KEYPAD == GIGABEAT_S_PAD)#define CHIP8_OFF BUTTON_BACK#define CHIP8_KEY1 BUTTON_MENU#define CHIP8_KEY2 BUTTON_UP#define CHIP8_KEY3 BUTTON_VOL_DOWN#define CHIP8_KEY4 BUTTON_LEFT#define CHIP8_KEY5 BUTTON_SELECT#define CHIP8_KEY6 BUTTON_RIGHT#define CHIP8_KEY7 BUTTON_VOL_UP#define CHIP8_KEY8 BUTTON_DOWN#define CHIP8_KEY9 BUTTON_PLAY
#elif (CONFIG_KEYPAD == MROBE100_PAD)#define CHIP8_OFF BUTTON_POWER#define CHIP8_KEY1 BUTTON_MENU#define CHIP8_KEY2 BUTTON_UP#define CHIP8_KEY3 BUTTON_PLAY#define CHIP8_KEY4 BUTTON_LEFT#define CHIP8_KEY5 BUTTON_SELECT#define CHIP8_KEY6 BUTTON_RIGHT#define CHIP8_KEY7 BUTTON_DISPLAY#define CHIP8_KEY8 BUTTON_DOWN
#elif CONFIG_KEYPAD == IAUDIO_M3_PAD#define CHIP8_OFF BUTTON_RC_REC#define CHIP8_KEY1 BUTTON_RC_MENU#define CHIP8_KEY2 BUTTON_RC_VOL_UP#define CHIP8_KEY3 BUTTON_RC_MODE#define CHIP8_KEY4 BUTTON_RC_REW#define CHIP8_KEY5 BUTTON_RC_PLAY#define CHIP8_KEY6 BUTTON_RC_FF#define CHIP8_KEY8 BUTTON_RC_VOL_DOWN
#elif (CONFIG_KEYPAD == COWON_D2_PAD)#define CHIP8_OFF BUTTON_POWER
#elif CONFIG_KEYPAD == CREATIVE_ZENXFI3_PAD#define CHIP8_OFF BUTTON_POWER#define CHIP8_KEY1 BUTTON_VOL_UP#define CHIP8_KEY2 BUTTON_UP#define CHIP8_KEY3 BUTTON_VOL_DOWN#define CHIP8_KEY4 BUTTON_BACK#define CHIP8_KEY5 BUTTON_PLAY#define CHIP8_KEY6 BUTTON_MENU#define CHIP8_KEY8 BUTTON_DOWN
#elif CONFIG_KEYPAD == PHILIPS_HDD1630_PAD#define CHIP8_OFF BUTTON_POWER#define CHIP8_KEY1 BUTTON_MENU#define CHIP8_KEY2 BUTTON_UP#define CHIP8_KEY3 BUTTON_VOL_DOWN#define CHIP8_KEY4 BUTTON_LEFT#define CHIP8_KEY5 BUTTON_SELECT#define CHIP8_KEY6 BUTTON_RIGHT#define CHIP8_KEY7 BUTTON_VOL_UP#define CHIP8_KEY8 BUTTON_DOWN#define CHIP8_KEY9 BUTTON_VIEW
#elif CONFIG_KEYPAD == PHILIPS_HDD6330_PAD#define CHIP8_OFF BUTTON_POWER#define CHIP8_KEY1 BUTTON_PREV#define CHIP8_KEY2 BUTTON_PLAY#define CHIP8_KEY3 BUTTON_NEXT#define CHIP8_KEY4 BUTTON_LEFT#define CHIP8_KEY5 BUTTON_UP#define CHIP8_KEY6 BUTTON_RIGHT#define CHIP8_KEY7 BUTTON_MENU#define CHIP8_KEY8 BUTTON_DOWN#define CHIP8_KEY9 BUTTON_VIEW#define CHIP8_KEY0 BUTTON_VOL_DOWN
#elif CONFIG_KEYPAD == PHILIPS_SA9200_PAD#define CHIP8_OFF BUTTON_POWER#define CHIP8_KEY1 BUTTON_LEFT#define CHIP8_KEY2 BUTTON_UP#define CHIP8_KEY3 BUTTON_RIGHT#define CHIP8_KEY4 BUTTON_PREV#define CHIP8_KEY5 BUTTON_PLAY#define CHIP8_KEY6 BUTTON_NEXT#define CHIP8_KEY7 BUTTON_MENU#define CHIP8_KEY8 BUTTON_DOWN#define CHIP8_KEY9 BUTTON_VOL_UP#define CHIP8_KEY0 BUTTON_VOL_DOWN
#elif (CONFIG_KEYPAD == ONDAVX747_PAD) || \CONFIG_KEYPAD == ONDAVX777_PAD || \CONFIG_KEYPAD == MROBE500_PAD#define CHIP8_OFF BUTTON_POWER
#elif (CONFIG_KEYPAD == SAMSUNG_YH820_PAD) || \ (CONFIG_KEYPAD == SAMSUNG_YH92X_PAD)#define CHIP8_OFF BUTTON_REW#define CHIP8_KEY0 BUTTON_FFWD#define CHIP8_KEY2 BUTTON_UP#define CHIP8_KEY4 BUTTON_LEFT#define CHIP8_KEY5 BUTTON_PLAY#define CHIP8_KEY6 BUTTON_RIGHT#define CHIP8_KEY8 BUTTON_DOWN
#elif CONFIG_KEYPAD == PBELL_VIBE500_PAD#define CHIP8_OFF BUTTON_REC#define CHIP8_KEY2 BUTTON_UP#define CHIP8_KEY4 BUTTON_PREV#define CHIP8_KEY5 BUTTON_OK#define CHIP8_KEY6 BUTTON_NEXT#define CHIP8_KEY8 BUTTON_DOWN
#elif CONFIG_KEYPAD == MPIO_HD200_PAD
#define CHIP8_OFF (BUTTON_REC|BUTTON_PLAY)#define CHIP8_KEY1 BUTTON_REW#define CHIP8_KEY2 BUTTON_FF#define CHIP8_KEY3 BUTTON_FUNC#define CHIP8_KEY4 BUTTON_REC#define CHIP8_KEY5 BUTTON_PLAY#define CHIP8_KEY6 BUTTON_VOL_DOWN#define CHIP8_KEY8 BUTTON_VOL_UP
#elif CONFIG_KEYPAD == MPIO_HD300_PAD
#define CHIP8_OFF (BUTTON_MENU|BUTTON_REPEAT)#define CHIP8_KEY1 BUTTON_REW#define CHIP8_KEY2 BUTTON_FF#define CHIP8_KEY3 BUTTON_MENU#define CHIP8_KEY4 BUTTON_ENTER#define CHIP8_KEY5 BUTTON_REC#define CHIP8_KEY6 BUTTON_PLAY#define CHIP8_KEY7 BUTTON_UP#define CHIP8_KEY8 BUTTON_DOWN
#elif CONFIG_KEYPAD == SANSA_FUZEPLUS_PAD
#define CHIP8_OFF BUTTON_POWER#define CHIP8_KEY0 BUTTON_VOL_DOWN#define CHIP8_KEY1 BUTTON_BACK#define CHIP8_KEY2 BUTTON_UP#define CHIP8_KEY3 BUTTON_PLAYPAUSE#define CHIP8_KEY4 BUTTON_LEFT#define CHIP8_KEY5 BUTTON_SELECT#define CHIP8_KEY6 BUTTON_RIGHT#define CHIP8_KEY7 BUTTON_BOTTOMLEFT#define CHIP8_KEY8 BUTTON_DOWN#define CHIP8_KEY9 BUTTON_BOTTOMRIGHT#define CHIP8_KEYA BUTTON_VOL_UP
#elif CONFIG_KEYPAD == SANSA_CONNECT_PAD
#define CHIP8_OFF BUTTON_POWER#define CHIP8_KEY1 BUTTON_LEFT#define CHIP8_KEY2 BUTTON_UP#define CHIP8_KEY3 BUTTON_RIGHT#define CHIP8_KEY4 BUTTON_DOWN#define CHIP8_KEY5 BUTTON_NEXT#define CHIP8_KEY6 BUTTON_PREV#define CHIP8_KEY7 BUTTON_SELECT#define CHIP8_KEY8 BUTTON_VOL_DOWN#define CHIP8_KEY9 BUTTON_VOL_UP
#elif (CONFIG_KEYPAD == SAMSUNG_YPR0_PAD)#define CHIP8_OFF (BUTTON_BACK|BUTTON_REPEAT)#define CHIP8_KEY1 BUTTON_MENU#define CHIP8_KEY2 BUTTON_UP#define CHIP8_KEY3 BUTTON_DOWN#define CHIP8_KEY4 BUTTON_LEFT#define CHIP8_KEY5 BUTTON_SELECT#define CHIP8_KEY6 BUTTON_RIGHT#define CHIP8_KEY7 BUTTON_BACK#define CHIP8_KEY8 BUTTON_POWER#define CHIP8_KEY9 BUTTON_USER
#elif (CONFIG_KEYPAD == HM60X_PAD)#define CHIP8_OFF BUTTON_POWER#define CHIP8_KEY2 BUTTON_UP#define CHIP8_KEY4 BUTTON_DOWN#define CHIP8_KEY5 BUTTON_SELECT#define CHIP8_KEY6 BUTTON_RIGHT#define CHIP8_KEY8 BUTTON_LEFT
#elif (CONFIG_KEYPAD == SONY_NWZ_PAD)#define CHIP8_OFF BUTTON_BACK#define CHIP8_KEY2 BUTTON_UP#define CHIP8_KEY4 BUTTON_DOWN#define CHIP8_KEY5 BUTTON_PLAY#define CHIP8_KEY6 BUTTON_RIGHT#define CHIP8_KEY8 BUTTON_LEFT
#elif (CONFIG_KEYPAD == CREATIVE_ZEN_PAD)#define CHIP8_OFF BUTTON_BACK#define CHIP8_KEY2 BUTTON_UP#define CHIP8_KEY4 BUTTON_DOWN#define CHIP8_KEY5 BUTTON_SELECT#define CHIP8_KEY6 BUTTON_RIGHT#define CHIP8_KEY8 BUTTON_LEFT
#elif (CONFIG_KEYPAD == HM801_PAD)#define CHIP8_OFF (BUTTON_POWER|BUTTON_SELECT)#define CHIP8_KEY1 BUTTON_PREV#define CHIP8_KEY2 BUTTON_UP#define CHIP8_KEY3 BUTTON_DOWN#define CHIP8_KEY4 BUTTON_LEFT#define CHIP8_KEY5 BUTTON_SELECT#define CHIP8_KEY6 BUTTON_RIGHT#define CHIP8_KEY7 BUTTON_NEXT#define CHIP8_KEY8 BUTTON_PLAY#define CHIP8_KEY9 BUTTON_POWER
#elif (CONFIG_KEYPAD == DX50_PAD)#define CHIP8_OFF BUTTON_POWER
#elif CONFIG_KEYPAD == CREATIVE_ZENXFI2_PAD#define CHIP8_OFF BUTTON_POWER#define CHIP8_KEY1 BUTTON_TOPLEFT#define CHIP8_KEY2 BUTTON_TOPMIDDLE#define CHIP8_KEY3 BUTTON_TOPRIGHT#define CHIP8_KEY4 BUTTON_MIDLEFT#define CHIP8_KEY5 BUTTON_CENTER#define CHIP8_KEY6 BUTTON_MIDRIGHT#define CHIP8_KEY7 BUTTON_BOTTOMLEFT#define CHIP8_KEY8 BUTTON_BOTTOMMIDDLE#define CHIP8_KEY9 BUTTON_BOTTOMRIGHT
#elif (CONFIG_KEYPAD == AGPTEK_ROCKER_PAD)#define CHIP8_OFF BUTTON_POWER#define CHIP8_KEY2 BUTTON_UP#define CHIP8_KEY4 BUTTON_DOWN#define CHIP8_KEY5 BUTTON_SELECT#define CHIP8_KEY6 BUTTON_RIGHT#define CHIP8_KEY8 BUTTON_LEFT
#elif CONFIG_KEYPAD == XDUOO_X3_PAD || CONFIG_KEYPAD == XDUOO_X3II_PAD || CONFIG_KEYPAD == XDUOO_X20_PAD#define CHIP8_OFF BUTTON_POWER#define CHIP8_KEY2 BUTTON_HOME#define CHIP8_KEY4 BUTTON_PREV#define CHIP8_KEY5 BUTTON_PLAY#define CHIP8_KEY6 BUTTON_NEXT#define CHIP8_KEY8 BUTTON_OPTION
#elif CONFIG_KEYPAD == IHIFI_770_PAD || CONFIG_KEYPAD == IHIFI_800_PAD#define CHIP8_OFF BUTTON_POWER#define CHIP8_KEY2 BUTTON_NEXT#define CHIP8_KEY4 BUTTON_HOME#define CHIP8_KEY5 BUTTON_VOL_UP#define CHIP8_KEY6 BUTTON_VOL_DOWN#define CHIP8_KEY8 BUTTON_PREV
#elif CONFIG_KEYPAD == EROSQ_PAD#define CHIP8_OFF BUTTON_POWER#define CHIP8_KEY2 BUTTON_NEXT#define CHIP8_KEY4 BUTTON_MENU#define CHIP8_KEY5 BUTTON_PLAY#define CHIP8_KEY6 BUTTON_BACK#define CHIP8_KEY8 BUTTON_PREV
#elif CONFIG_KEYPAD == FIIO_M3K_PAD#define CHIP8_OFF BUTTON_POWER#define CHIP8_KEY2 BUTTON_MENU#define CHIP8_KEY4 BUTTON_LEFT#define CHIP8_KEY5 BUTTON_SELECT#define CHIP8_KEY6 BUTTON_RIGHT#define CHIP8_KEY8 BUTTON_BACK
#elif CONFIG_KEYPAD == SDL_PAD/* use touchscreen */#elif (CONFIG_KEYPAD == MA_PAD)#define CHIP8_OFF BUTTON_BACK#define CHIP8_KEY2 BUTTON_UP#define CHIP8_KEY4 BUTTON_DOWN#define CHIP8_KEY5 BUTTON_PLAY#define CHIP8_KEY6 BUTTON_RIGHT#define CHIP8_KEY8 BUTTON_LEFT
#elif CONFIG_KEYPAD == RG_NANO_PAD#define CHIP8_OFF BUTTON_START#define CHIP8_KEY1 BUTTON_Y#define CHIP8_KEY2 BUTTON_A#define CHIP8_KEY3 BUTTON_X#define CHIP8_KEY4 BUTTON_LEFT#define CHIP8_KEY5 BUTTON_UP#define CHIP8_KEY6 BUTTON_RIGHT#define CHIP8_KEY7 BUTTON_B#define CHIP8_KEY8 BUTTON_DOWN#define CHIP8_KEY9 BUTTON_R#define CHIP8_KEY0 BUTTON_L
#elif (CONFIG_KEYPAD == N3DS_PAD)#define CHIP8_OFF (BUTTON_BACK|BUTTON_REPEAT)#define CHIP8_KEY1 BUTTON_MENU#define CHIP8_KEY2 BUTTON_UP#define CHIP8_KEY3 BUTTON_DOWN#define CHIP8_KEY4 BUTTON_LEFT#define CHIP8_KEY5 BUTTON_SELECT#define CHIP8_KEY6 BUTTON_RIGHT#define CHIP8_KEY7 BUTTON_BACK#define CHIP8_KEY8 BUTTON_POWER#define CHIP8_KEY9 BUTTON_USER
#elif (CONFIG_KEYPAD == ECHO_R1_PAD)#define CHIP8_OFF BUTTON_POWER#define CHIP8_KEY1 BUTTON_Y#define CHIP8_KEY2 BUTTON_UP#define CHIP8_KEY3 BUTTON_B#define CHIP8_KEY4 BUTTON_LEFT#define CHIP8_KEY5 BUTTON_A#define CHIP8_KEY6 BUTTON_RIGHT#define CHIP8_KEY7 BUTTON_SELECT#define CHIP8_KEY8 BUTTON_DOWN#define CHIP8_KEY9 BUTTON_START#define CHIP8_KEYA BUTTON_X
#elif (CONFIG_KEYPAD == PSP_PAD)#define CHIP8_OFF (BUTTON_BACK|BUTTON_REPEAT)#define CHIP8_KEY1 BUTTON_MENU#define CHIP8_KEY2 BUTTON_UP#define CHIP8_KEY3 BUTTON_DOWN#define CHIP8_KEY4 BUTTON_LEFT#define CHIP8_KEY5 BUTTON_SELECT#define CHIP8_KEY6 BUTTON_RIGHT#define CHIP8_KEY7 BUTTON_BACK#define CHIP8_KEY8 BUTTON_POWER#define CHIP8_KEY9 BUTTON_USER
#elif CONFIG_KEYPAD == SHANLING_Q1_PAD || CONFIG_KEYPAD == HIBY_R3PROII_PAD || CONFIG_KEYPAD == HIDIZS_AP80MAX_PAD/* use touchscreen */
#else#error No keymap defined!#endif
#ifdef HAVE_TOUCHSCREEN#ifndef CHIP8_OFF#define CHIP8_OFF BUTTON_TOPLEFT#endif#ifndef CHIP8_KEY1#define CHIP8_KEY1 BUTTON_TOPRIGHT#endif#ifndef CHIP8_KEY2#define CHIP8_KEY2 BUTTON_TOPMIDDLE#endif#ifndef CHIP8_KEY3#define CHIP8_KEY3 BUTTON_BOTTOMLEFT#endif#ifndef CHIP8_KEY4#define CHIP8_KEY4 BUTTON_MIDLEFT#endif#ifndef CHIP8_KEY5#define CHIP8_KEY5 BUTTON_CENTER#endif#ifndef CHIP8_KEY6#define CHIP8_KEY6 BUTTON_MIDRIGHT#endif#ifndef CHIP8_KEY7#define CHIP8_KEY7 BUTTON_BOTTOMRIGHT#endif#ifndef CHIP8_KEY8#define CHIP8_KEY8 BUTTON_BOTTOMMIDDLE#endif#endif
static byte chip8_virtual_keys[16];static byte chip8_keymap[16];
static unsigned long starttimer; /* Timer value at the beginning */static unsigned long cycles; /* Number of update cycles (50Hz) */
/****************************************************************************//* Turn sound on *//****************************************************************************/static void chip8_sound_on (void){}
/****************************************************************************//* Turn sound off *//****************************************************************************/static void chip8_sound_off (void){}
/****************************************************************************//* Update the display *//****************************************************************************/static void chip8_update_display(void){ int x, y, i; byte w; byte* row; /* frame buffer in hardware fomat */ unsigned char lcd_framebuf[CHIP8_HEIGHT/8][CHIP8_LCDWIDTH];
for (y=0;y<CHIP8_HEIGHT/8;++y) { row = lcd_framebuf[y]; for (x=0;x<CHIP8_WIDTH;++x) { w = 0; for (i=0;i<8;i++) { w = w >> 1; if (chip8_display[x+(y*8+i)*CHIP8_WIDTH] != 0) { w += 128; } }#if (CHIP8_LCDWIDTH < 128) /* LCD_WIDTH between 112 and 127 */ if (x%8 == 1) { row[-1] |= w; /* overlay on */ } else#endif *row++ = w; } }#if (CONFIG_PLATFORM & PLATFORM_HOSTED) || (LCD_DEPTH >= 4) rb->lcd_set_drawmode(DRMODE_SOLID); rb->lcd_mono_bitmap(lcd_framebuf[0], CHIP8_X, CHIP8_Y, CHIP8_LCDWIDTH, CHIP8_HEIGHT); rb->lcd_update();#else rb->lcd_blit_mono(lcd_framebuf[0], CHIP8_X, CHIP8_Y>>3, CHIP8_LCDWIDTH, CHIP8_HEIGHT>>3, CHIP8_LCDWIDTH);#endif}
static void chip8_keyboard(void){ int i; int button = rb->button_get(false); switch (button) {#ifdef CHIP8_RC_OFF case CHIP8_RC_OFF:#endif case CHIP8_OFF: /* Abort Emulator */ chip8_running = 0; break;
case CHIP8_KEY2: chip8_virtual_keys[2] = 1; break; case CHIP8_KEY2 | BUTTON_REL: chip8_virtual_keys[2] = 0; break; case CHIP8_KEY4: chip8_virtual_keys[4] = 1; break; case CHIP8_KEY4 | BUTTON_REL: chip8_virtual_keys[4] = 0; break; case CHIP8_KEY6: chip8_virtual_keys[6] = 1; break; case CHIP8_KEY6 | BUTTON_REL: chip8_virtual_keys[6] = 0; break; case CHIP8_KEY8: chip8_virtual_keys[8] = 1; break; case CHIP8_KEY8 | BUTTON_REL: chip8_virtual_keys[8] = 0; break; case CHIP8_KEY5: chip8_virtual_keys[5] = 1; break; case CHIP8_KEY5 | BUTTON_REL: chip8_virtual_keys[5] = 0; break;#ifdef CHIP8_KEY1 case CHIP8_KEY1: chip8_virtual_keys[1] = 1; break; case CHIP8_KEY1 | BUTTON_REL: chip8_virtual_keys[1] = 0; break;#endif#ifdef CHIP8_KEY3 case CHIP8_KEY3: chip8_virtual_keys[3] = 1; break; case CHIP8_KEY3 | BUTTON_REL: chip8_virtual_keys[3] = 0; break;#endif#ifdef CHIP8_KEY7 case CHIP8_KEY7: chip8_virtual_keys[7] = 1; break; case CHIP8_KEY7 | BUTTON_REL: chip8_virtual_keys[7] = 0; break;#endif#ifdef CHIP8_KEY9 case CHIP8_KEY9: chip8_virtual_keys[9] = 1; break; case CHIP8_KEY9 | BUTTON_REL: chip8_virtual_keys[9] = 0; break;#endif#ifdef CHIP8_KEYA case CHIP8_KEYA: chip8_virtual_keys[10] = 1; break; case CHIP8_KEYA | BUTTON_REL: chip8_virtual_keys[10] = 0; break;#endif
default: if (rb->default_event_handler(button) == SYS_USB_CONNECTED) chip8_running = 2; /* indicates stopped because of USB */ break; } for(i=0; i<16; i++) { chip8_keys[i] = chip8_virtual_keys[chip8_keymap[i]]; }}
/****************************************************************************//* Update keyboard and display, sync emulation with VDP clock *//****************************************************************************/static void chip8_interrupt (void){ unsigned long current_tick; unsigned long timer, runtime;
chip8_update_display(); chip8_keyboard(); cycles ++; runtime = cycles * HZ / 50; timer = starttimer + runtime; current_tick = *rb->current_tick; if (TIME_AFTER(timer, current_tick)) { rb->sleep(timer - current_tick); } else { rb->yield(); }}
static bool chip8_init(const char* file){ int numread; int fd; int len; int i;
fd = rb->open(file, O_RDONLY); if (fd < 0) { rb->lcd_puts(0, 6, "File Error."); return false; } numread = rb->read(fd, chip8_mem+0x200, 4096-0x200); rb->close(fd); if (numread==-1) { rb->lcd_puts(0, 6, "I/O Error."); return false; }
/* is there a c8k file (chip8 keys) ? */ char c8kname[MAX_PATH]; rb->strcpy(c8kname, file); for(i=0; i<16; i++) { chip8_virtual_keys[i] = 0; chip8_keymap[i] = i; } len = rb->strlen(c8kname); c8kname[len-2] = '8'; c8kname[len-1] = 'k'; fd = rb->open(c8kname, O_RDONLY); if (fd >= 0) { rb->lcd_puts(0, 6, "File&Keymap OK."); numread = rb->read(fd, chip8_keymap, 16); rb->close(fd); } else { rb->lcd_puts(0, 6, "File OK."); } for(i=0; i<16; i++) { if (chip8_keymap[i] >= '0' && chip8_keymap[i] <= '9') chip8_keymap[i] -= '0'; else if (chip8_keymap[i] >= 'A' && chip8_keymap[i] <= 'F') chip8_keymap[i] -= 'A' - 10; else if (chip8_keymap[i] >= 'a' && chip8_keymap[i] <= 'f') chip8_keymap[i] -= 'a' - 10; else chip8_keymap[i] %= 16; } return true;}
static bool chip8_run(const char* file){ int ok;
rb->lcd_clear_display(); rb->lcd_puts(0, 0, "SChip8 Emulator"); rb->lcd_puts(0, 1, " (c) by "); rb->lcd_puts(0, 2, "Marcel de Kogel"); rb->lcd_puts(0, 3, " Rockbox: "); rb->lcd_puts(0, 4, " Blueloop/Fdy "); rb->lcd_puts(0, 5, "---------------"); ok = chip8_init(file); rb->lcd_update(); rb->sleep(HZ*1); if (!ok) return false; rb->lcd_clear_display();#if (CHIP8_X > 0) && (CHIP8_Y > 0) rb->lcd_drawrect(CHIP8_X-1,CHIP8_Y-1,CHIP8_LCDWIDTH+2,CHIP8_HEIGHT+2);#endif rb->lcd_update(); starttimer = *rb->current_tick;
chip8_iperiod=15; cycles = 0; chip8();
if (chip8_running == 3) { /* unsupported instruction */ rb->splash(HZ, "Error: Unsupported"#ifndef CHIP8_SUPER " CHIP-8 instruction. (maybe S-CHIP)"#else " (S)CHIP-8 instruction."#endif ); return false; }
return true;}
/***************** Plugin Entry Point *****************/
enum plugin_status plugin_start(const void* parameter){ const char* filename;
if (parameter == NULL) { rb->splash(HZ, "Play a .ch8 file!"); return PLUGIN_ERROR; } else { filename = (char*) parameter; }
/* now go ahead and have fun! */ if (chip8_run(filename)) if (chip8_running == 0) return PLUGIN_OK; else return PLUGIN_USB_CONNECTED; else return PLUGIN_ERROR;}