diff --git a/index.html b/index.html
index afd04cb1..d69da0ba 100644
--- a/index.html
+++ b/index.html
@@ -206,8 +206,8 @@ div.bitmap_editor {
Atari VCS
VIC Dual
- Midway 8080 B&W
- Scramble hardware
+ Midway 8080
+ Scramble Hardware
Atari Color Vector (Z80)
Williams (Z80)
Williams Sound (Z80)
diff --git a/presets/vcs/examples/music2.a b/presets/vcs/examples/fractionalpitch.a
similarity index 100%
rename from presets/vcs/examples/music2.a
rename to presets/vcs/examples/fractionalpitch.a
diff --git a/presets/vicdual/skeleton.sdcc b/presets/vicdual/skeleton.sdcc
index 2a3fed5d..a850b24e 100644
--- a/presets/vicdual/skeleton.sdcc
+++ b/presets/vicdual/skeleton.sdcc
@@ -92,11 +92,22 @@ word rand() {
return lfsr;
}
-void wait_for_vsync() {
- while (VSYNC != 0) lfsr++; // wait for VSYNC end
- while (VSYNC == 0) lfsr++; // wait for VSYNC start
+void delay(byte msec) {
+ while (msec--) {
+ while (TIMER500HZ != 0) lfsr++;
+ while (TIMER500HZ == 0) lfsr++;
+ }
}
+#define PE(fg,bg) (((fg)<<5) | ((bg)<<1))
+
+const byte __at (0x4000) color_prom[32] = {
+ PE(7,0),PE(3,0),PE(1,0),PE(3,0),PE(6,0),PE(3,0),PE(2,0),PE(6,0),
+ PE(7,0),PE(3,0),PE(1,0),PE(3,0),PE(6,0),PE(3,0),PE(2,0),PE(6,0),
+ PE(7,0),PE(3,0),PE(1,0),PE(3,0),PE(6,0),PE(3,0),PE(2,0),PE(6,0),
+ PE(7,0),PE(3,0),PE(1,0),PE(3,0),PE(6,0),PE(3,0),PE(2,0),PE(6,0),
+};
+
#define LOCHAR 0x0
#define HICHAR 0xff
diff --git a/src/emu.js b/src/emu.js
index bdd87417..909828d0 100644
--- a/src/emu.js
+++ b/src/emu.js
@@ -626,6 +626,9 @@ var BaseZ80Platform = function() {
onBreakpointHit(debugBreakState);
}
}
+ this.wasBreakpointHit = function() {
+ return debugBreakState != null;
+ }
// TODO: lower bound of clock value
this.step = function() {
var self = this;
diff --git a/src/platform/galaxian.js b/src/platform/galaxian.js
index d600d25a..d3b128d6 100644
--- a/src/platform/galaxian.js
+++ b/src/platform/galaxian.js
@@ -2,7 +2,7 @@
var GALAXIAN_PRESETS = [
{id:'gfxtest.c', name:'Graphics Test'},
- {id:'shoot2.c', name:'Shoot-em-up Game'},
+ {id:'shoot2.c', name:'Solarian Game'},
];
var GALAXIAN_KEYCODE_MAP = makeKeycodeMap([
diff --git a/src/platform/vicdual.js b/src/platform/vicdual.js
index 6cc29713..ecacd921 100644
--- a/src/platform/vicdual.js
+++ b/src/platform/vicdual.js
@@ -5,9 +5,9 @@ var VICDUAL_PRESETS = [
{id:'hello.c', name:'Hello World'},
{id:'gfxtest.c', name:'Graphics Test'},
{id:'soundtest.c', name:'Sound Test'},
- {id:'snake1.c', name:'Snake Game (Prototype)'},
- {id:'snake2.c', name:'Snake Game (Full)'},
- {id:'music.c', name:'Music Example'},
+ {id:'snake1.c', name:'Siege Game (Prototype)'},
+ {id:'snake2.c', name:'Siege Game (Full)'},
+ {id:'music.c', name:'Music Player'},
];
var VicDualPlatform = function(mainElement) {
diff --git a/src/platform/williams.js b/src/platform/williams.js
index 27f24d68..0a17117e 100644
--- a/src/platform/williams.js
+++ b/src/platform/williams.js
@@ -310,7 +310,8 @@ var WilliamsPlatform = function(mainElement, proto) {
if (cpu.requestInterrupt)
cpu.requestInterrupt();
}
- self.runCPU(cpu, cpuCyclesPerFrame/4);
+ if (!self.wasBreakpointHit())
+ self.runCPU(cpu, cpuCyclesPerFrame/4);
video.updateFrame(0, 0, quarter*64, 0, 64, 304);
}
if (screenNeedsRefresh) {
diff --git a/src/worker/workermain.js b/src/worker/workermain.js
index 9d11393e..0abd84f7 100644
--- a/src/worker/workermain.js
+++ b/src/worker/workermain.js
@@ -84,12 +84,67 @@ function loadFilesystem(name) {
console.log("Loaded "+name+" filesystem", fsMeta[name].files.length, 'files', fsBlob[name].size, 'bytes');
}
+var ATARI_CFG =
+ "FEATURES {\nSTARTADDRESS: default = $9000;\n}\n"
++ "MEMORY {\n"
++ " ZP: start = $82, size = $7E;\n"
++ " RAM: start = $0200, size = $1e00;\n"
++ " ROM: start = $9000, size = $7000;\n"
++ " VEC: start = $FFFA, size = 6;\n"
++ "}\n"
++ "SEGMENTS {\n"
++ " CODE: load = ROM, type = ro, define = no;\n"
++ " DATA: load = RAM, type = rw, define = no;\n"
++ "ZEROPAGE: load = ZP, type = zp, define = no;\n"
+//+ " VECTORS: load = VEC, type = ro, define = yes;"
++ "}\n"
+;
+/*
++ "SYMBOLS {\n"
++ " __STACKSIZE__: type = weak, value = $0800; # 2k stack\n"
++ " __RESERVED_MEMORY__: type = weak, value = $0000;\n"
++ " __STARTADDRESS__: type = export, value = %S;\n"
++ "}\n"
++ "MEMORY {\n"
++ " ZP: file = \"\", define = yes, start = $0082, size = $007E;\n"
++ " MAIN: file = %O, define = yes, start = %S, size = $BC20 - __STACKSIZE__ - __RESERVED_MEMORY__ - %S;\n"
++ "}\n"
++ "SEGMENTS {\n"
++ " ZEROPAGE: load = ZP, type = zp, optional = yes;\n"
++ " EXTZP: load = ZP, type = zp, optional = yes;\n"
++ " STARTUP: load = MAIN, type = ro, define = yes, optional = yes;\n"
++ " LOWCODE: load = MAIN, type = ro, define = yes, optional = yes;\n"
++ " ONCE: load = MAIN, type = ro, optional = yes;\n"
++ " CODE: load = MAIN, type = ro, define = yes;\n"
++ " RODATA: load = MAIN, type = ro, optional = yes;\n"
++ " DATA: load = MAIN, type = rw, optional = yes;\n"
++ " BSS: load = MAIN, type = bss, define = yes, optional = yes;\n"
++ " INIT: load = MAIN, type = bss, optional = yes;\n"
++ "}\n"
++ "FEATURES {\n"
++ " CONDES: type = constructor,\n"
++ " label = __CONSTRUCTOR_TABLE__,\n"
++ " count = __CONSTRUCTOR_COUNT__,\n"
++ " segment = ONCE;\n"
++ " CONDES: type = destructor,\n"
++ " label = __DESTRUCTOR_TABLE__,\n"
++ " count = __DESTRUCTOR_COUNT__,\n"
++ " segment = RODATA;\n"
++ " CONDES: type = interruptor,\n"
++ " label = __INTERRUPTOR_TABLE__,\n"
++ " count = __INTERRUPTOR_COUNT__,\n"
++ " segment = RODATA,\n"
++ " import = __CALLIRQ__;\n"
++ "}\n";
+*/
+
// mount the filesystem at /share
function setupFS(FS, name) {
FS.mkdir('/share');
FS.mount(FS.filesystems['WORKERFS'], {
packages: [{ metadata: fsMeta[name], blob: fsBlob[name] }]
}, '/share');
+ FS.writeFile("/vector-ataricolor.cfg", ATARI_CFG);
}
var DASM_MAIN_FILENAME = "main.a";
@@ -413,11 +468,14 @@ function assemblelinkCA65(code, platform, warnings) {
printErr:print_fn,
});
var FS = LD65['FS'];
+ var cfgfile = '/' + platform + '.cfg';
setupFS(FS, '65');
FS.writeFile("main.o", objout, {encoding:'binary'});
LD65.callMain(['--cfg-path', '/share/cfg', '--lib-path', '/share/lib',
- '--start-addr', '0x6000', // TODO
- '-t', platform, '-o', 'main', '-m', 'main.map', 'main.o', platform+'.lib']);
+ //'--start-addr', '0x6000', // TODO
+ '-C', cfgfile,
+ '-o', 'main', '-m', 'main.map', 'main.o',
+ 'apple2.lib']);
var aout = FS.readFile("main", {encoding:'binary'});
var mapout = FS.readFile("main.map", {encoding:'utf8'});
var listing = parseCA65Listing(lstout, mapout);
@@ -456,10 +514,17 @@ function compileCC65(code, platform) {
var FS = CC65['FS'];
setupFS(FS, '65');
FS.writeFile("main.c", code, {encoding:'utf8'});
- CC65.callMain(['-v', '-T', '-g', /*'-Cl',*/ '-Oirs', '-I', '/share/include', '-t', platform, "main.c"]);
+ CC65.callMain(['-v', '-T', '-g', /*'-Cl',*/ '-Oirs', '-I', '/share/include', "main.c"]);
try {
var asmout = FS.readFile("main.s", {encoding:'utf8'});
- return assemblelinkCA65(asmout, platform, errors);
+ var result = assemblelinkCA65(asmout, platform, errors);
+/*
+ result.asmlines = result.lines;
+ result.lines = result.srclines;
+ result.srclines = null;
+*/
+//console.log(result.intermediate.listing);
+ return result;
} catch(e) {
return {errors:errors};
}
diff --git a/tools/midi2song.py b/tools/midi2song.py
index c80e165e..8b438b28 100755
--- a/tools/midi2song.py
+++ b/tools/midi2song.py
@@ -1,16 +1,29 @@
#!/usr/bin/python
-import sys, string, math
+import sys, string, math, argparse
import mido
-min_note = 21
-max_note = 21+63
-max_voices = 3
-one_voice_per_channel = 0
-tempo = 48
-compress = 0
-transpose = 0
-coutput = 1
+parser = argparse.ArgumentParser()
+parser.add_argument('-s', '--start', type=int, default=21, help="first MIDI note")
+parser.add_argument('-n', '--num', type=int, default=21+63, help="number of notes")
+parser.add_argument('-v', '--voices', type=int, default=3, help="number of voices")
+parser.add_argument('-T', '--transpose', type=int, default=0, help="transpose by half-steps")
+parser.add_argument('-t', '--tempo', type=int, default=48, help="tempo")
+parser.add_argument('-o', '--one', action="store_true", help="one voice per channel")
+parser.add_argument('-z', '--compress', action="store_true", help="compress song (experimental)")
+parser.add_argument('-H', '--hex', action="store_true", help="hex output")
+parser.add_argument('midifile', help="MIDI file")
+parser.add_argument('midichannels', nargs='?', help="comma-separated list of MIDI channels, or -")
+args = parser.parse_args()
+
+min_note = args.start
+max_note = min_note + args.num
+max_voices = args.voices
+one_voice_per_channel = args.one
+tempo = args.tempo
+compress = args.compress
+transpose = args.transpose
+coutput = not args.hex
# for 2600
#max_voices = 2
@@ -19,7 +32,7 @@ coutput = 1
#max_voices = 4
#one_voice_per_channel = 0
-fn = sys.argv[1]
+fn = args.midifile
mid = mido.MidiFile(fn)
@@ -97,7 +110,7 @@ def channels_for_track(track):
channels.add(msg.channel)
return list(channels)
-if len(sys.argv) < 3:
+if not args.midichannels:
print mid
print mid.length, 'seconds'
for i, track in enumerate(mid.tracks):
@@ -105,14 +118,12 @@ if len(sys.argv) < 3:
#for msg in track:
# print(msg)
else:
- if len(sys.argv) > 3:
- transpose = int(sys.argv[3])
gtime = 0
curtime = 0
nnotes = 0
nvoices = 0
curchans = 0
- channels = [int(x) for x in string.split(sys.argv[2], ',')]
+ channels = [int(x) for x in string.split(args.midichannels, ',')]
print
print "// %s %s" % (mid, channels)
output = []