pce: pc engine started
This commit is contained in:
parent
d11c1d1664
commit
5bc85161eb
|
@ -208,6 +208,7 @@ body {
|
|||
<li><a class="dropdown-item" href="?platform=nes.mame">NES (MAME)</a></li>
|
||||
<hr>
|
||||
<li><a class="dropdown-item" href="?platform=williams">Williams (6809)</a></li>
|
||||
<li><a class="dropdown-item" href="?platform=pce">PC Engine</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
|
@ -313,7 +314,7 @@ body {
|
|||
<span class="control-def"><span class="control-key">←↑↓→</span> Joystick</span>
|
||||
<span class="control-def"><span class="control-key small">Space</span> Button</span>
|
||||
</div>
|
||||
<div class="emucontrols-nes emucontrols-atari7800 text-center small control-insns" style="display:none">
|
||||
<div class="emucontrols-nes emucontrols-atari7800 emucontrols-pce text-center small control-insns" style="display:none">
|
||||
<span class="control-def"><span class="control-key">←↑↓→</span> Joypad</span>
|
||||
<span class="control-def"><span class="control-key small">Space</span> Button A</span>
|
||||
<span class="control-def"><span class="control-key small">Shift</span> Button B</span>
|
||||
|
|
|
@ -0,0 +1,241 @@
|
|||
/*
|
||||
Text-based version of a Blockade-style game.
|
||||
For more information, see "Making Arcade Games in C".
|
||||
*/
|
||||
|
||||
#include <conio.h>
|
||||
#include <joystick.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#define COLS 50
|
||||
#define ROWS 28
|
||||
|
||||
typedef unsigned char byte;
|
||||
typedef signed char sbyte;
|
||||
typedef unsigned short word;
|
||||
typedef signed short sword;
|
||||
|
||||
// get the character at a specfic x/y position
|
||||
byte readcharxy(byte x, byte y) {
|
||||
gotoxy(x,y); // set cursor position
|
||||
return cpeekc();
|
||||
}
|
||||
|
||||
void delay(byte count) {
|
||||
while (count--) {
|
||||
waitvsync();
|
||||
}
|
||||
}
|
||||
|
||||
////////// GAME DATA
|
||||
|
||||
typedef struct {
|
||||
byte x;
|
||||
byte y;
|
||||
byte dir;
|
||||
word score;
|
||||
char head_attr;
|
||||
char tail_attr;
|
||||
int collided:1;
|
||||
int human:1;
|
||||
} Player;
|
||||
|
||||
Player players[2];
|
||||
|
||||
byte credits = 0;
|
||||
byte frames_per_move;
|
||||
byte gameover;
|
||||
|
||||
#define START_SPEED 12
|
||||
#define MAX_SPEED 5
|
||||
#define MAX_SCORE 7
|
||||
|
||||
///////////
|
||||
|
||||
const char BOX_CHARS[8] = { '+', '+', '+', '+',
|
||||
'-', '-', '!', '!'};
|
||||
|
||||
void draw_box(byte x, byte y, byte x2, byte y2, const char* chars) {
|
||||
byte x1 = x;
|
||||
cputcxy(x, y, chars[2]);
|
||||
cputcxy(x2, y, chars[3]);
|
||||
cputcxy(x, y2, chars[0]);
|
||||
cputcxy(x2, y2, chars[1]);
|
||||
while (++x < x2) {
|
||||
cputcxy(x, y, chars[5]);
|
||||
cputcxy(x, y2, chars[4]);
|
||||
}
|
||||
while (++y < y2) {
|
||||
cputcxy(x1, y, chars[6]);
|
||||
cputcxy(x2, y, chars[7]);
|
||||
}
|
||||
}
|
||||
|
||||
void draw_playfield() {
|
||||
draw_box(0,1,COLS-1,ROWS-1,BOX_CHARS);
|
||||
cputsxy( 0, 0, "Plyr1:");
|
||||
cputsxy(20, 0, "Plyr2:");
|
||||
cputcxy( 7, 0, players[0].score+'0');
|
||||
cputcxy(27, 0, players[1].score+'0');
|
||||
}
|
||||
|
||||
typedef enum { D_RIGHT, D_DOWN, D_LEFT, D_UP } dir_t;
|
||||
const sbyte DIR_X[4] = { 1, 0, -1, 0 };
|
||||
const sbyte DIR_Y[4] = { 0, 1, 0, -1 };
|
||||
|
||||
void init_game() {
|
||||
memset(players, 0, sizeof(players));
|
||||
players[0].head_attr = '1';
|
||||
players[1].head_attr = '2';
|
||||
players[0].tail_attr = '#';
|
||||
players[1].tail_attr = '*';
|
||||
frames_per_move = START_SPEED;
|
||||
}
|
||||
|
||||
void reset_players() {
|
||||
players[0].x = players[0].y = 5;
|
||||
players[0].dir = D_RIGHT;
|
||||
players[1].x = COLS-6;
|
||||
players[1].y = ROWS-6;
|
||||
players[1].dir = D_LEFT;
|
||||
players[0].collided = players[1].collided = 0;
|
||||
}
|
||||
|
||||
void draw_player(Player* p) {
|
||||
cputcxy(p->x, p->y, p->head_attr);
|
||||
}
|
||||
|
||||
void move_player(Player* p) {
|
||||
cputcxy(p->x, p->y, p->tail_attr);
|
||||
p->x += DIR_X[p->dir];
|
||||
p->y += DIR_Y[p->dir];
|
||||
if ((readcharxy(p->x, p->y) & 0x7f) != ' ')
|
||||
p->collided = 1;
|
||||
draw_player(p);
|
||||
}
|
||||
|
||||
void human_control(Player* p) {
|
||||
byte dir = 0xff;
|
||||
char joy;
|
||||
if (!p->human) return;
|
||||
//if (!kbhit()) return;
|
||||
joy = joy_read(0);
|
||||
if (JOY_UP(joy)) dir = D_UP;
|
||||
if (JOY_LEFT(joy)) dir = D_LEFT;
|
||||
if (JOY_RIGHT(joy)) dir = D_RIGHT;
|
||||
if (JOY_DOWN(joy)) dir = D_DOWN;
|
||||
// don't let the player reverse direction
|
||||
if (dir < 0x80 && dir != (p->dir ^ 2)) {
|
||||
p->dir = dir;
|
||||
}
|
||||
}
|
||||
|
||||
byte ai_try_dir(Player* p, dir_t dir, byte shift) {
|
||||
byte x,y;
|
||||
dir &= 3;
|
||||
x = p->x + (DIR_X[dir] << shift);
|
||||
y = p->y + (DIR_Y[dir] << shift);
|
||||
if (x < COLS && y < ROWS
|
||||
&& (readcharxy(x, y) & 0x7f) == ' ') {
|
||||
p->dir = dir;
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void ai_control(Player* p) {
|
||||
dir_t dir;
|
||||
if (p->human) return;
|
||||
dir = p->dir;
|
||||
if (!ai_try_dir(p, dir, 0)) {
|
||||
ai_try_dir(p, dir+1, 0);
|
||||
ai_try_dir(p, dir-1, 0);
|
||||
} else {
|
||||
ai_try_dir(p, dir-1, 0) && ai_try_dir(p, dir-1, 1+(rand() & 3));
|
||||
ai_try_dir(p, dir+1, 0) && ai_try_dir(p, dir+1, 1+(rand() & 3));
|
||||
ai_try_dir(p, dir, rand() & 3);
|
||||
}
|
||||
}
|
||||
|
||||
void flash_colliders() {
|
||||
byte i;
|
||||
// flash players that collided
|
||||
for (i=0; i<56; i++) {
|
||||
delay(2);
|
||||
revers(players[0].collided && (i&1));
|
||||
draw_player(&players[0]);
|
||||
revers(players[1].collided && (i&1));
|
||||
draw_player(&players[1]);
|
||||
}
|
||||
revers(0);
|
||||
}
|
||||
|
||||
void make_move() {
|
||||
byte i;
|
||||
for (i=0; i<frames_per_move; i++) {
|
||||
human_control(&players[0]);
|
||||
delay(1);
|
||||
}
|
||||
ai_control(&players[0]);
|
||||
ai_control(&players[1]);
|
||||
// if players collide, 2nd player gets the point
|
||||
textcolor(COLOR_CYAN);
|
||||
move_player(&players[1]);
|
||||
textcolor(COLOR_YELLOW);
|
||||
move_player(&players[0]);
|
||||
textcolor(COLOR_WHITE);
|
||||
}
|
||||
|
||||
void declare_winner(byte winner) {
|
||||
byte i;
|
||||
clrscr();
|
||||
for (i=0; i<ROWS/2-3; i++) {
|
||||
draw_box(i,i,COLS-1-i,ROWS-1-i,BOX_CHARS);
|
||||
delay(1);
|
||||
}
|
||||
cputsxy(12,10,"WINNER:");
|
||||
cputsxy(12,13,"PLAYER ");
|
||||
cputcxy(12+7, 13, '1'+winner);
|
||||
delay(200);
|
||||
gameover = 1;
|
||||
}
|
||||
|
||||
void play_round() {
|
||||
reset_players();
|
||||
clrscr();
|
||||
textcolor(COLOR_WHITE);
|
||||
draw_playfield();
|
||||
while (1) {
|
||||
make_move();
|
||||
if (players[0].collided || players[1].collided) break;
|
||||
}
|
||||
flash_colliders();
|
||||
// add scores to players that didn't collide
|
||||
if (players[0].collided) players[1].score++;
|
||||
if (players[1].collided) players[0].score++;
|
||||
// increase speed
|
||||
if (frames_per_move > MAX_SPEED) frames_per_move--;
|
||||
// game over?
|
||||
if (players[0].score != players[1].score) {
|
||||
if (players[0].score >= MAX_SCORE)
|
||||
declare_winner(0);
|
||||
else if (players[1].score >= MAX_SCORE)
|
||||
declare_winner(1);
|
||||
}
|
||||
}
|
||||
|
||||
void play_game() {
|
||||
gameover = 0;
|
||||
init_game();
|
||||
players[0].human = 1;
|
||||
while (!gameover) {
|
||||
play_round();
|
||||
}
|
||||
}
|
||||
|
||||
void main() {
|
||||
joy_install (joy_static_stddrv);
|
||||
play_game();
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
|
||||
#include <conio.h>
|
||||
#include <peekpoke.h>
|
||||
|
||||
int tmp; // need at least 1 variable
|
||||
|
||||
int main() {
|
||||
clrscr();
|
||||
bgcolor(COLOR_BLUE);
|
||||
textcolor(COLOR_WHITE);
|
||||
cputs("\r\n*** HELLO WORLD! ***");
|
||||
while (1) ;
|
||||
return 0;
|
||||
}
|
|
@ -18,6 +18,7 @@ export function importPlatform(name: string) : Promise<any> {
|
|||
case "msx": return import("../platform/msx");
|
||||
case "mw8080bw": return import("../platform/mw8080bw");
|
||||
case "nes": return import("../platform/nes");
|
||||
case "pce": return import("../platform/pce");
|
||||
case "script": return import("../platform/script");
|
||||
case "sms": return import("../platform/sms");
|
||||
case "sound_konami": return import("../platform/sound_konami");
|
||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
|
@ -0,0 +1,214 @@
|
|||
|
||||
var Module = typeof Module !== 'undefined' ? Module : {};
|
||||
|
||||
if (!Module.expectedDataFileDownloads) {
|
||||
Module.expectedDataFileDownloads = 0;
|
||||
}
|
||||
|
||||
Module.expectedDataFileDownloads++;
|
||||
(function() {
|
||||
// Do not attempt to redownload the virtual filesystem data when in a pthread or a Wasm Worker context.
|
||||
if (Module['ENVIRONMENT_IS_PTHREAD'] || Module['$ww']) return;
|
||||
var loadPackage = function(metadata) {
|
||||
|
||||
var PACKAGE_PATH = '';
|
||||
if (typeof window === 'object') {
|
||||
PACKAGE_PATH = window['encodeURIComponent'](window.location.pathname.toString().substring(0, window.location.pathname.toString().lastIndexOf('/')) + '/');
|
||||
} else if (typeof process === 'undefined' && typeof location !== 'undefined') {
|
||||
// web worker
|
||||
PACKAGE_PATH = encodeURIComponent(location.pathname.toString().substring(0, location.pathname.toString().lastIndexOf('/')) + '/');
|
||||
}
|
||||
var PACKAGE_NAME = '/home/pzp/8bitworkshop-compilers/output/fs/fs65-pce.data';
|
||||
var REMOTE_PACKAGE_BASE = 'fs65-pce.data';
|
||||
if (typeof Module['locateFilePackage'] === 'function' && !Module['locateFile']) {
|
||||
Module['locateFile'] = Module['locateFilePackage'];
|
||||
err('warning: you defined Module.locateFilePackage, that has been renamed to Module.locateFile (using your locateFilePackage for now)');
|
||||
}
|
||||
var REMOTE_PACKAGE_NAME = Module['locateFile'] ? Module['locateFile'](REMOTE_PACKAGE_BASE, '') : REMOTE_PACKAGE_BASE;
|
||||
var REMOTE_PACKAGE_SIZE = metadata['remote_package_size'];
|
||||
|
||||
function fetchRemotePackage(packageName, packageSize, callback, errback) {
|
||||
if (typeof process === 'object' && typeof process.versions === 'object' && typeof process.versions.node === 'string') {
|
||||
require('fs').readFile(packageName, function(err, contents) {
|
||||
if (err) {
|
||||
errback(err);
|
||||
} else {
|
||||
callback(contents.buffer);
|
||||
}
|
||||
});
|
||||
return;
|
||||
}
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open('GET', packageName, true);
|
||||
xhr.responseType = 'arraybuffer';
|
||||
xhr.onprogress = function(event) {
|
||||
var url = packageName;
|
||||
var size = packageSize;
|
||||
if (event.total) size = event.total;
|
||||
if (event.loaded) {
|
||||
if (!xhr.addedTotal) {
|
||||
xhr.addedTotal = true;
|
||||
if (!Module.dataFileDownloads) Module.dataFileDownloads = {};
|
||||
Module.dataFileDownloads[url] = {
|
||||
loaded: event.loaded,
|
||||
total: size
|
||||
};
|
||||
} else {
|
||||
Module.dataFileDownloads[url].loaded = event.loaded;
|
||||
}
|
||||
var total = 0;
|
||||
var loaded = 0;
|
||||
var num = 0;
|
||||
for (var download in Module.dataFileDownloads) {
|
||||
var data = Module.dataFileDownloads[download];
|
||||
total += data.total;
|
||||
loaded += data.loaded;
|
||||
num++;
|
||||
}
|
||||
total = Math.ceil(total * Module.expectedDataFileDownloads/num);
|
||||
if (Module['setStatus']) Module['setStatus']('Downloading data... (' + loaded + '/' + total + ')');
|
||||
} else if (!Module.dataFileDownloads) {
|
||||
if (Module['setStatus']) Module['setStatus']('Downloading data...');
|
||||
}
|
||||
};
|
||||
xhr.onerror = function(event) {
|
||||
throw new Error("NetworkError for: " + packageName);
|
||||
}
|
||||
xhr.onload = function(event) {
|
||||
if (xhr.status == 200 || xhr.status == 304 || xhr.status == 206 || (xhr.status == 0 && xhr.response)) { // file URLs can return 0
|
||||
var packageData = xhr.response;
|
||||
callback(packageData);
|
||||
} else {
|
||||
throw new Error(xhr.statusText + " : " + xhr.responseURL);
|
||||
}
|
||||
};
|
||||
xhr.send(null);
|
||||
};
|
||||
|
||||
function handleError(error) {
|
||||
console.error('package error:', error);
|
||||
};
|
||||
|
||||
var fetchedCallback = null;
|
||||
var fetched = Module['getPreloadedPackage'] ? Module['getPreloadedPackage'](REMOTE_PACKAGE_NAME, REMOTE_PACKAGE_SIZE) : null;
|
||||
|
||||
if (!fetched) fetchRemotePackage(REMOTE_PACKAGE_NAME, REMOTE_PACKAGE_SIZE, function(data) {
|
||||
if (fetchedCallback) {
|
||||
fetchedCallback(data);
|
||||
fetchedCallback = null;
|
||||
} else {
|
||||
fetched = data;
|
||||
}
|
||||
}, handleError);
|
||||
|
||||
function runWithFS() {
|
||||
|
||||
function assert(check, msg) {
|
||||
if (!check) throw msg + new Error().stack;
|
||||
}
|
||||
Module['FS_createPath']("/", "asminc", true, true);
|
||||
Module['FS_createPath']("/", "cfg", true, true);
|
||||
Module['FS_createPath']("/", "include", true, true);
|
||||
Module['FS_createPath']("/include", "arpa", true, true);
|
||||
Module['FS_createPath']("/include", "em", true, true);
|
||||
Module['FS_createPath']("/include", "geos", true, true);
|
||||
Module['FS_createPath']("/include", "joystick", true, true);
|
||||
Module['FS_createPath']("/include", "mouse", true, true);
|
||||
Module['FS_createPath']("/include", "sys", true, true);
|
||||
Module['FS_createPath']("/include", "tgi", true, true);
|
||||
Module['FS_createPath']("/", "lib", true, true);
|
||||
Module['FS_createPath']("/", "target", true, true);
|
||||
Module['FS_createPath']("/target", "pce", true, true);
|
||||
Module['FS_createPath']("/target/pce", "drv", true, true);
|
||||
Module['FS_createPath']("/target/pce/drv", "joy", true, true);
|
||||
|
||||
/** @constructor */
|
||||
function DataRequest(start, end, audio) {
|
||||
this.start = start;
|
||||
this.end = end;
|
||||
this.audio = audio;
|
||||
}
|
||||
DataRequest.prototype = {
|
||||
requests: {},
|
||||
open: function(mode, name) {
|
||||
this.name = name;
|
||||
this.requests[name] = this;
|
||||
Module['addRunDependency']('fp ' + this.name);
|
||||
},
|
||||
send: function() {},
|
||||
onload: function() {
|
||||
var byteArray = this.byteArray.subarray(this.start, this.end);
|
||||
this.finish(byteArray);
|
||||
},
|
||||
finish: function(byteArray) {
|
||||
var that = this;
|
||||
// canOwn this data in the filesystem, it is a slide into the heap that will never change
|
||||
Module['FS_createDataFile'](this.name, null, byteArray, true, true, true);
|
||||
Module['removeRunDependency']('fp ' + that.name);
|
||||
this.requests[this.name] = null;
|
||||
}
|
||||
};
|
||||
|
||||
var files = metadata['files'];
|
||||
for (var i = 0; i < files.length; ++i) {
|
||||
new DataRequest(files[i]['start'], files[i]['end'], files[i]['audio'] || 0).open('GET', files[i]['filename']);
|
||||
}
|
||||
|
||||
function processPackageData(arrayBuffer) {
|
||||
assert(arrayBuffer, 'Loading data file failed.');
|
||||
assert(arrayBuffer.constructor.name === ArrayBuffer.name, 'bad input to processPackageData');
|
||||
var byteArray = new Uint8Array(arrayBuffer);
|
||||
var curr;
|
||||
// Reuse the bytearray from the XHR as the source for file reads.
|
||||
DataRequest.prototype.byteArray = byteArray;
|
||||
var files = metadata['files'];
|
||||
for (var i = 0; i < files.length; ++i) {
|
||||
DataRequest.prototype.requests[files[i].filename].onload();
|
||||
} Module['removeRunDependency']('datafile_/home/pzp/8bitworkshop-compilers/output/fs/fs65-pce.data');
|
||||
|
||||
};
|
||||
Module['addRunDependency']('datafile_/home/pzp/8bitworkshop-compilers/output/fs/fs65-pce.data');
|
||||
|
||||
if (!Module.preloadResults) Module.preloadResults = {};
|
||||
|
||||
Module.preloadResults[PACKAGE_NAME] = {fromCache: false};
|
||||
if (fetched) {
|
||||
processPackageData(fetched);
|
||||
fetched = null;
|
||||
} else {
|
||||
fetchedCallback = processPackageData;
|
||||
}
|
||||
|
||||
}
|
||||
if (Module['calledRun']) {
|
||||
runWithFS();
|
||||
} else {
|
||||
if (!Module['preRun']) Module['preRun'] = [];
|
||||
Module["preRun"].push(runWithFS); // FS is not initialized yet, wait for it
|
||||
}
|
||||
|
||||
Module['removeRunDependency']('fs65-pce.js.metadata');
|
||||
}
|
||||
|
||||
function runMetaWithFS() {
|
||||
Module['addRunDependency']('fs65-pce.js.metadata');
|
||||
var REMOTE_METADATA_NAME = Module['locateFile'] ? Module['locateFile']('fs65-pce.js.metadata', '') : 'fs65-pce.js.metadata';
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.onreadystatechange = function() {
|
||||
if (xhr.readyState === 4 && xhr.status === 200) {
|
||||
loadPackage(JSON.parse(xhr.responseText));
|
||||
}
|
||||
}
|
||||
xhr.open('GET', REMOTE_METADATA_NAME, true);
|
||||
xhr.overrideMimeType('application/json');
|
||||
xhr.send(null);
|
||||
}
|
||||
|
||||
if (Module['calledRun']) {
|
||||
runMetaWithFS();
|
||||
} else {
|
||||
if (!Module['preRun']) Module['preRun'] = [];
|
||||
Module["preRun"].push(runMetaWithFS);
|
||||
}
|
||||
|
||||
})();
|
File diff suppressed because one or more lines are too long
|
@ -394,6 +394,12 @@ var PLATFORM_PARAMS = {
|
|||
extra_link_args: ['crt0-cpc.rel', 'cpctelera.lib'],
|
||||
extra_link_files: ['crt0-cpc.rel', 'crt0-cpc.lst', 'cpctelera.lib', 'cpctelera.lst'],
|
||||
},
|
||||
'pce': {
|
||||
arch: 'huc6280',
|
||||
define: ['__PCE__'],
|
||||
cfgfile: 'pce.cfg',
|
||||
libargs: ['pce.lib'],
|
||||
},
|
||||
};
|
||||
|
||||
PLATFORM_PARAMS['sms-sms-libcv'] = PLATFORM_PARAMS['sms-sg1000-libcv'];
|
||||
|
@ -1189,6 +1195,8 @@ var TOOL_PRELOADFS = {
|
|||
'ca65-devel': '65-none',
|
||||
'cc65-vcs': '65-atari2600',
|
||||
'ca65-vcs': '65-atari2600',
|
||||
'cc65-pce': '65-pce',
|
||||
'ca65-pce': '65-pce',
|
||||
'sdasz80': 'sdcc',
|
||||
'sdcc': 'sdcc',
|
||||
'sccz80': 'sccz80',
|
||||
|
|
Loading…
Reference in New Issue