mirror of
https://github.com/sehugg/8bitworkshop.git
synced 2024-11-21 07:33:14 +00:00
sms: added game gear
This commit is contained in:
parent
51b6f0025c
commit
e4af92927d
@ -154,6 +154,7 @@ if (window.location.host.endsWith('8bitworkshop.com')) {
|
|||||||
<li><a class="dropdown-item" href="?platform=coleco">ColecoVision</a></li>
|
<li><a class="dropdown-item" href="?platform=coleco">ColecoVision</a></li>
|
||||||
<li><a class="dropdown-item" href="?platform=sms-sg1000-libcv">Sega SG-1000</a></li>
|
<li><a class="dropdown-item" href="?platform=sms-sg1000-libcv">Sega SG-1000</a></li>
|
||||||
<li><a class="dropdown-item" href="?platform=sms-sms-libcv">Sega Master System</a></li>
|
<li><a class="dropdown-item" href="?platform=sms-sms-libcv">Sega Master System</a></li>
|
||||||
|
<li><a class="dropdown-item" href="?platform=sms-gg-libcv">Sega Game Gear</a></li>
|
||||||
<li><a class="dropdown-item" href="?platform=atari7800">Atari 7800</a></li>
|
<li><a class="dropdown-item" href="?platform=atari7800">Atari 7800</a></li>
|
||||||
<!--
|
<!--
|
||||||
<li><a class="dropdown-item" href="?platform=vectrex">Vectrex</a></li>
|
<li><a class="dropdown-item" href="?platform=vectrex">Vectrex</a></li>
|
||||||
@ -323,11 +324,17 @@ if (window.location.host.endsWith('8bitworkshop.com')) {
|
|||||||
<span class="control-def"><span class="control-key small">\</span> Select</span>
|
<span class="control-def"><span class="control-key small">\</span> Select</span>
|
||||||
<span class="control-def"><span class="control-key small">Enter</span> Start</span>
|
<span class="control-def"><span class="control-key small">Enter</span> Start</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="emucontrols-msx emucontrols-coleco emucontrols-sms text-center small control-insns" style="display:none">
|
<div class="emucontrols-msx emucontrols-coleco 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">←↑↓→</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">Space</span> Button A</span>
|
||||||
<span class="control-def"><span class="control-key small">Shift</span> Button B</span>
|
<span class="control-def"><span class="control-key small">Shift</span> Button B</span>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="emucontrols-sms 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>
|
||||||
|
<span class="control-def"><span class="control-key small">Enter</span> Start</span>
|
||||||
|
</div>
|
||||||
<div class="emucontrols-vicdual emucontrols-galaxian emucontrols-vector text-center small control-insns" style="display:none">
|
<div class="emucontrols-vicdual emucontrols-galaxian emucontrols-vector text-center small control-insns" style="display:none">
|
||||||
<span class="control-def"><span class="control-key">←↑↓→</span> Joystick</span>
|
<span class="control-def"><span class="control-key">←↑↓→</span> Joystick</span>
|
||||||
<span class="control-def"><span class="control-key small">Space</span> Button 1</span>
|
<span class="control-def"><span class="control-key small">Space</span> Button 1</span>
|
||||||
|
1
presets/sms-gg-libcv
Symbolic link
1
presets/sms-gg-libcv
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
sms-sms-libcv
|
@ -72,21 +72,23 @@ void music_play(byte index) {
|
|||||||
void music_stop() {
|
void music_stop() {
|
||||||
}
|
}
|
||||||
|
|
||||||
/*{pal:222,n:16}*/
|
#ifdef __PLATFORM_SMS_GG_LIBCV__
|
||||||
const char PALETTE0[16] = {
|
/*{pal:444,n:32}*/
|
||||||
0x30, 0x38, 0x3E, 0x3F,
|
const short PALETTE[32] = {
|
||||||
0x30, 0x38, 0x3E, 0x3F,
|
0xe00, 0xa60, 0xee3, 0xddd, 0xe00, 0xa60, 0xee3, 0xddd,
|
||||||
0x30, 0x38, 0x3E, 0x3F,
|
0xe00, 0xa60, 0xee3, 0xddd, 0xe00, 0xa60, 0xee3, 0xddd,
|
||||||
0x30, 0x38, 0x3E, 0x3F,
|
0xe00, 0x111, 0xddd, 0x43e, 0xaaaa, 0xcccc, 0xeeee, 0xffff,
|
||||||
|
0xe00, 0xa60, 0xee3, 0xddd, 0xe00, 0xa60, 0xee3, 0xddd,
|
||||||
};
|
};
|
||||||
|
#else
|
||||||
/*{pal:222,n:16}*/
|
/*{pal:222,n:32}*/
|
||||||
const char PALETTE1[16] = {
|
const char PALETTE[32] = {
|
||||||
0x30, 0x00, 0x3F, 0x03,
|
0x30, 0x38, 0x3E, 0x3F, 0x30, 0x38, 0x3E, 0x3F,
|
||||||
0x30, 0x38, 0x3E, 0x3F,
|
0x30, 0x38, 0x3E, 0x3F, 0x30, 0x38, 0x3E, 0x3F,
|
||||||
0x30, 0x38, 0x3E, 0x3F,
|
0x30, 0x00, 0x3F, 0x03, 0x30, 0x38, 0x3E, 0x3F,
|
||||||
0x30, 0x38, 0x3E, 0x3F,
|
0x30, 0x38, 0x3E, 0x3F, 0x30, 0x38, 0x3E, 0x3F
|
||||||
};
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
/// METASPRITES
|
/// METASPRITES
|
||||||
|
|
||||||
@ -750,7 +752,7 @@ void pal_bright(byte level) {
|
|||||||
byte or = PALBR_OR[level];
|
byte or = PALBR_OR[level];
|
||||||
byte and = PALBR_AND[level];
|
byte and = PALBR_AND[level];
|
||||||
for (i=0; i<16; i++) {
|
for (i=0; i<16; i++) {
|
||||||
pal[i] = PALETTE0[i] & and | or;
|
pal[i] = PALETTE[i] & and | or;
|
||||||
}
|
}
|
||||||
cvu_memtocmemcpy(0xc000, pal, 16);
|
cvu_memtocmemcpy(0xc000, pal, 16);
|
||||||
}
|
}
|
||||||
@ -799,8 +801,7 @@ void play_scene() {
|
|||||||
|
|
||||||
void setup_graphics() {
|
void setup_graphics() {
|
||||||
cvu_memtovmemcpy(PATTERN, CHR_GENERIC, sizeof(CHR_GENERIC));
|
cvu_memtovmemcpy(PATTERN, CHR_GENERIC, sizeof(CHR_GENERIC));
|
||||||
cvu_memtocmemcpy(0xc000, PALETTE0, 16);
|
cvu_memtocmemcpy(0xc000, PALETTE, sizeof(PALETTE));
|
||||||
cvu_memtocmemcpy(0xc010, PALETTE1, 16);
|
|
||||||
flip_sprite_patterns(PATTERN+0x80*32, CHR_GENERIC+0xd0*32, 0x30*32);
|
flip_sprite_patterns(PATTERN+0x80*32, CHR_GENERIC+0xd0*32, 0x30*32);
|
||||||
cv_set_left_column_blank(true);
|
cv_set_left_column_blank(true);
|
||||||
}
|
}
|
||||||
|
@ -21,17 +21,23 @@ extern uintptr_t font_bitmap_0[];
|
|||||||
#define SPRITE_PATTERNS 0x3800 // 32*32 = 1024 bytes
|
#define SPRITE_PATTERNS 0x3800 // 32*32 = 1024 bytes
|
||||||
#define SPRITES 0x3c00 // 4*32 = 128 bytes
|
#define SPRITES 0x3c00 // 4*32 = 128 bytes
|
||||||
|
|
||||||
/*{pal:222,n:16}*/
|
#ifdef __PLATFORM_SMS_GG_LIBCV__
|
||||||
const char PALETTE0[16] = {
|
/*{pal:444,n:32}*/
|
||||||
0x10, 0x03, 0x0B, 0x0F, 0x13, 0x17, 0x1B, 0x1F,
|
const short PALETTE[32] = {
|
||||||
0x22, 0x28, 0x2A, 0x2E, 0x30, 0x37, 0x3B, 0x3F,
|
0x2221, 0x4441, 0x6661, 0x8888, 0xaaaa, 0xcccc, 0xeeee, 0xffff,
|
||||||
};
|
0x2222, 0x4444, 0x6666, 0x8888, 0xaaaa, 0xcccc, 0xeeee, 0xffff,
|
||||||
|
0x2222, 0x4444, 0x6666, 0x8888, 0xaaaa, 0xcccc, 0xeeee, 0xffff,
|
||||||
/*{pal:222,n:16}*/
|
0x2222, 0x4444, 0x6666, 0x8888, 0xaaaa, 0xcccc, 0xeeee, 0xffff,
|
||||||
const char PALETTE1[16] = {
|
};
|
||||||
|
#else
|
||||||
|
/*{pal:222,n:32}*/
|
||||||
|
const char PALETTE[32] = {
|
||||||
|
0x10, 0x03, 0x0B, 0x0F, 0x13, 0x17, 0x1B, 0x1F,
|
||||||
|
0x22, 0x28, 0x2A, 0x2E, 0x30, 0x37, 0x3B, 0x3F,
|
||||||
0x10, 0x03, 0x0B, 0x0F, 0x13, 0x17, 0x1B, 0x1F,
|
0x10, 0x03, 0x0B, 0x0F, 0x13, 0x17, 0x1B, 0x1F,
|
||||||
0x22, 0x28, 0x2A, 0x2E, 0x30, 0x37, 0x3B, 0x3F,
|
0x22, 0x28, 0x2A, 0x2E, 0x30, 0x37, 0x3B, 0x3F,
|
||||||
};
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
/*{w:8,h:8,bpp:1,count:2,brev:1,np:4,pofs:1,sl:4}*/
|
/*{w:8,h:8,bpp:1,count:2,brev:1,np:4,pofs:1,sl:4}*/
|
||||||
const char PATTERNS[64] = {
|
const char PATTERNS[64] = {
|
||||||
@ -79,8 +85,7 @@ void setup_graphics() {
|
|||||||
// copy sprites to pattern table VRAM
|
// copy sprites to pattern table VRAM
|
||||||
cvu_memtovmemcpy(PATTERN+32, PATTERNS, sizeof(PATTERNS));
|
cvu_memtovmemcpy(PATTERN+32, PATTERNS, sizeof(PATTERNS));
|
||||||
// copy palettes to VRAM
|
// copy palettes to VRAM
|
||||||
cvu_memtocmemcpy(0xc000, PALETTE0, 16);
|
cvu_memtocmemcpy(0xc000, PALETTE, sizeof(PALETTE));
|
||||||
cvu_memtocmemcpy(0xc010, PALETTE1, 16);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// image table has two bytes per cell (name + attribute)
|
// image table has two bytes per cell (name + attribute)
|
||||||
|
@ -1013,3 +1013,30 @@ export class SMSVDP extends TMS9918A {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export class GameGearVDP extends SMSVDP {
|
||||||
|
cram = new Uint8Array(64); // color RAM
|
||||||
|
cram_latch = 0;
|
||||||
|
|
||||||
|
writeData(value: number) {
|
||||||
|
if (this.writeToCRAM) {
|
||||||
|
//console.log(hex(this.addressRegister), hex(value), hex(this.cram_latch));
|
||||||
|
if (this.addressRegister & 1) { // odd address?
|
||||||
|
let rgb4 = this.cram_latch + (value << 8);
|
||||||
|
let rgba = RGBA((rgb4&15)*17, ((rgb4>>4)&15)*17, ((rgb4>>8)&15)*17);
|
||||||
|
let palindex = this.addressRegister & (this.cram.length-1);
|
||||||
|
this.cram[palindex-1] = this.cram_latch;
|
||||||
|
this.cram[palindex] = value;
|
||||||
|
this.cpalette[palindex >> 1] = rgba;
|
||||||
|
this.prefetchByte = value;
|
||||||
|
this.addressRegister &= this.ramMask;
|
||||||
|
this.redrawRequired = true;
|
||||||
|
} else {
|
||||||
|
this.cram_latch = value; // even address
|
||||||
|
}
|
||||||
|
this.addressRegister++;
|
||||||
|
} else {
|
||||||
|
super.writeData(value);
|
||||||
|
}
|
||||||
|
this.latch = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -1,11 +1,9 @@
|
|||||||
|
|
||||||
import { Z80, Z80State } from "../common/cpu/ZilogZ80";
|
|
||||||
import { BasicScanlineMachine } from "../common/devices";
|
|
||||||
import { BaseZ80VDPBasedMachine } from "./vdp_z80";
|
import { BaseZ80VDPBasedMachine } from "./vdp_z80";
|
||||||
import { KeyFlags, newAddressDecoder, padBytes, Keys, makeKeycodeMap, newKeyboardHandler } from "../common/emu";
|
import { newAddressDecoder, padBytes, Keys, makeKeycodeMap } from "../common/emu";
|
||||||
import { hex, lzgmini, stringToByteArray } from "../common/util";
|
import { hex } from "../common/util";
|
||||||
import { TssChannelAdapter, MasterAudio, SN76489_Audio } from "../common/audio";
|
import { MasterAudio, SN76489_Audio } from "../common/audio";
|
||||||
import { TMS9918A, SMSVDP } from "../common/video/tms9918a";
|
import { SMSVDP, GameGearVDP } from "../common/video/tms9918a";
|
||||||
|
|
||||||
// http://www.smspower.org/Development/Index
|
// http://www.smspower.org/Development/Index
|
||||||
// http://www.smspower.org/uploads/Development/sg1000.txt
|
// http://www.smspower.org/uploads/Development/sg1000.txt
|
||||||
@ -28,6 +26,7 @@ var SG1000_KEYCODE_MAP = makeKeycodeMap([
|
|||||||
[Keys.P2_A, 1, 0x4],
|
[Keys.P2_A, 1, 0x4],
|
||||||
[Keys.P2_B, 1, 0x8],
|
[Keys.P2_B, 1, 0x8],
|
||||||
[Keys.VK_BACK_SLASH, 1, 0x10], // reset
|
[Keys.VK_BACK_SLASH, 1, 0x10], // reset
|
||||||
|
[Keys.VK_ENTER, 1, 0x80], // start/pause
|
||||||
]);
|
]);
|
||||||
|
|
||||||
export class SG1000 extends BaseZ80VDPBasedMachine {
|
export class SG1000 extends BaseZ80VDPBasedMachine {
|
||||||
@ -61,33 +60,41 @@ export class SG1000 extends BaseZ80VDPBasedMachine {
|
|||||||
setMemoryControl(v:number) { }
|
setMemoryControl(v:number) { }
|
||||||
setIOPortControl(v:number) { }
|
setIOPortControl(v:number) { }
|
||||||
|
|
||||||
|
readIO(addr:number) {
|
||||||
|
switch (addr & 0xc1) {
|
||||||
|
case 0x40: return this.getVCounter();
|
||||||
|
case 0x41: return this.getHCounter();
|
||||||
|
case 0x80: return this.vdp.readData();
|
||||||
|
case 0x81: return this.vdp.readStatus();
|
||||||
|
case 0xc0: return this.inputs[0] ^ 0xff;
|
||||||
|
case 0xc1: return this.inputs[1] ^ 0xff;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
writeIO(addr:number, val:number) {
|
||||||
|
switch (addr & 0xc1) {
|
||||||
|
case 0x00: return this.setMemoryControl(val);
|
||||||
|
case 0x01: return this.setIOPortControl(val);
|
||||||
|
case 0x40:
|
||||||
|
case 0x41: return this.psg.setData(val);
|
||||||
|
case 0x80: return this.vdp.writeData(val);
|
||||||
|
case 0x81: return this.vdp.writeAddress(val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
newIOBus() {
|
newIOBus() {
|
||||||
return {
|
return {
|
||||||
read: (addr:number) => {
|
read: (addr:number) => {
|
||||||
addr &= 0xff;
|
addr &= 0xff;
|
||||||
//console.log('IO read', hex(addr,4));
|
//console.log('IO read', hex(addr,4));
|
||||||
switch (addr & 0xc1) {
|
return this.readIO(addr);
|
||||||
case 0x40: return this.getVCounter();
|
|
||||||
case 0x41: return this.getHCounter();
|
|
||||||
case 0x80: return this.vdp.readData();
|
|
||||||
case 0x81: return this.vdp.readStatus();
|
|
||||||
case 0xc0: return this.inputs[0] ^ 0xff;
|
|
||||||
case 0xc1: return this.inputs[1] ^ 0xff;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
},
|
},
|
||||||
write: (addr:number, val:number) => {
|
write: (addr:number, val:number) => {
|
||||||
addr &= 0xff;
|
addr &= 0xff;
|
||||||
val &= 0xff;
|
val &= 0xff;
|
||||||
//console.log('IO write', hex(addr,4), hex(val,2));
|
//console.log('IO write', hex(addr,4), hex(val,2));
|
||||||
switch (addr & 0xc1) {
|
this.writeIO(addr, val);
|
||||||
case 0x00: return this.setMemoryControl(val);
|
|
||||||
case 0x01: return this.setIOPortControl(val);
|
|
||||||
case 0x40:
|
|
||||||
case 0x41: return this.psg.setData(val);
|
|
||||||
case 0x80: return this.vdp.writeData(val);
|
|
||||||
case 0x81: return this.vdp.writeAddress(val);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -223,3 +230,17 @@ export class SMS extends SG1000 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// https://segaretro.org/images/1/16/Sega_Game_Gear_Hardware_Reference_Manual.pdf
|
||||||
|
export class GameGear extends SMS {
|
||||||
|
newVDP(frameData, cru, flicker) {
|
||||||
|
return new GameGearVDP(frameData, cru, flicker);
|
||||||
|
}
|
||||||
|
readIO(addr:number) {
|
||||||
|
switch (addr & 0xc1) {
|
||||||
|
case 0x00: return (~this.inputs[1] & 0x80) | 0x40;
|
||||||
|
case 0xdc: return this.inputs[0] ^ 0xff;
|
||||||
|
case 0xdd: return this.inputs[1] ^ 0xff;
|
||||||
|
}
|
||||||
|
return super.readIO(addr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
|
|
||||||
import { SG1000, SMS } from "../machine/sms";
|
import { GameGear, SG1000, SMS } from "../machine/sms";
|
||||||
import { Platform, BaseZ80MachinePlatform } from "../common/baseplatform";
|
import { Platform, BaseZ80MachinePlatform } from "../common/baseplatform";
|
||||||
import { PLATFORMS } from "../common/emu";
|
import { PLATFORMS } from "../common/emu";
|
||||||
|
|
||||||
@ -46,7 +46,17 @@ class SMSPlatform extends BaseZ80MachinePlatform<SMS> implements Platform {
|
|||||||
readVRAMAddress(a) { return this.machine.readVRAMAddress(a); }
|
readVRAMAddress(a) { return this.machine.readVRAMAddress(a); }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class GameGearPlatform extends BaseZ80MachinePlatform<GameGear> implements Platform {
|
||||||
|
|
||||||
|
newMachine() { return new GameGear(); }
|
||||||
|
getPresets() { return SMS_PRESETS; }
|
||||||
|
getDefaultExtension() { return ".c"; };
|
||||||
|
readAddress(a) { return this.machine.read(a); }
|
||||||
|
readVRAMAddress(a) { return this.machine.readVRAMAddress(a); }
|
||||||
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
|
|
||||||
PLATFORMS['sms-sg1000-libcv'] = SG1000Platform;
|
PLATFORMS['sms-sg1000-libcv'] = SG1000Platform;
|
||||||
PLATFORMS['sms-sms-libcv'] = SMSPlatform;
|
PLATFORMS['sms-sms-libcv'] = SMSPlatform;
|
||||||
|
PLATFORMS['sms-gg-libcv'] = GameGearPlatform;
|
||||||
|
@ -388,6 +388,7 @@ var PLATFORM_PARAMS = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
PLATFORM_PARAMS['sms-sms-libcv'] = PLATFORM_PARAMS['sms-sg1000-libcv'];
|
PLATFORM_PARAMS['sms-sms-libcv'] = PLATFORM_PARAMS['sms-sg1000-libcv'];
|
||||||
|
PLATFORM_PARAMS['sms-gg-libcv'] = PLATFORM_PARAMS['sms-sms-libcv'];
|
||||||
|
|
||||||
var _t1;
|
var _t1;
|
||||||
export function starttime() { _t1 = new Date(); }
|
export function starttime() { _t1 = new Date(); }
|
||||||
@ -1060,6 +1061,8 @@ export function preprocessMCPP(step:BuildStep, filesys:string) {
|
|||||||
if (step.mainfile) {
|
if (step.mainfile) {
|
||||||
args.unshift.apply(args, ["-D", "__MAIN__"]);
|
args.unshift.apply(args, ["-D", "__MAIN__"]);
|
||||||
}
|
}
|
||||||
|
let platform_def = (platform.toUpperCase() as any).replaceAll(/[^a-zA-Z0-9]/g,'_');
|
||||||
|
args.unshift.apply(args, ["-D", `__PLATFORM_${platform_def}__`]);
|
||||||
if (params.extra_preproc_args) {
|
if (params.extra_preproc_args) {
|
||||||
args.push.apply(args, params.extra_preproc_args);
|
args.push.apply(args, params.extra_preproc_args);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user