Permalink
Browse files

initial checkin

  • Loading branch information...
0 parents commit 965c947dcc1cec630c5da4e67cada2ab92c1b54f @simmons committed Mar 28, 2012
19 LICENSE
@@ -0,0 +1,19 @@
+/*
+ * Valence 64 - The input-only VNC client for the Commodore 64.
+ *
+ * Copyright 2012 David Simmons
+ * http://cafbit.com/
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
@@ -0,0 +1,35 @@
+
+all: valence64.prg setup.prg hello.prg vncclient/vncclient.c64 combined.prg disk
+
+clean:
+ $(MAKE) TARGET=c64 -C vncclient sterile
+ rm -f valence64.prg
+ rm -f combined.prg
+ rm -f setup.prg
+ rm -f valence64.d64
+ rm -f hello.o hello.prg
+
+vncclient/vncclient.c64:
+ $(MAKE) TARGET=c64 -C vncclient build
+
+combined.prg: valence64.prg vncclient/vncclient.c64
+ ./combine.pl valence64.prg vncclient/vncclient.c64 vncclient/contiki-c64.map > combined.prg
+
+%.o: %.asm
+ ca65 -o $@ $<
+
+%.prg: %.o %.cfg
+ ld65 -C $(lastword $^) -o $@ $<
+
+%.prg: %.bas
+ petcat -c -w2 -o $@ -- $<
+
+disk:
+ c1541 -format valence64,00 d64 valence64.d64
+ c1541 -attach valence64.d64 -write combined.prg valence64,p
+ c1541 -attach valence64.d64 -write setup.prg setup,p
+ c1541 -attach valence64.d64 -write assets/contiki.cfg contiki.cfg,u
+ c1541 -attach valence64.d64 -write assets/valence.cfg valence.cfg,u
+ c1541 -attach valence64.d64 -write vncclient/cs8900a.eth cs8900a.eth,u
+ c1541 -attach valence64.d64 -write vncclient/lan91c96.eth lan91c96.eth,u
+ #./randomizesrcport.pl
97 README
@@ -0,0 +1,97 @@
+
+Valence64: The input-only VNC client for the Commodore 64
+======================================================================
+
+(c) 2012 David Simmons
+Licensed under the Apache License, Version 2.0
+
+http://cafbit.com/entry/valence64
+
+Valence64 is a simple proof-of-concept application for controlling a
+remote computer using a networked Commodore 64. It was developed as
+a way for me to learn the Contiki framework and the uIP TCP/IP stack,
+both of which are used in actual modern-day embedded systems.
+
+
+Using Valence64
+----------------------------------------
+
+The easiest way to use Valence64 is to obtain a prebuilt version of the
+valence.d64 disk image from the above web site. Attach the disk image
+to your C64 emulator, or write the image to a 1541 5.25" disk for use on
+an actual C64.
+
+Run the SETUP program to configure your TCP/IP settings, select an
+ethernet driver, and indicate the VNC server address of the host you
+want to control:
+
+LOAD "SETUP",8
+RUN
+
+Then, load and run Valence64:
+
+LOAD "VALENCE64",8
+RUN
+
+Press F1 to connect to the VNC server. By default, the program is in
+"mouse mode" -- CRSR keys will be used to move the mouse, and RETURN
+will send a mouse click. Press F7 to toggle "keyboard mode" for typing.
+A joystick in control port 2 can also be used to operate the mouse
+pointer.
+
+
+Building Valence64
+----------------------------------------
+
+Requirements:
+ Linux development machine.
+ (It could be made to work with other platforms.)
+ Contiki 2.5
+ The cc65 compiler/assembler (cc65-c64-2.13.2-1)
+
+You must have a copy of the Contiki 2.5 source code located in the
+../contiki-2.5 directory relative to the root of the Valence64 source.
+Patch the Contiki source with the supplied contiki-2.5-autostart.patch
+file:
+
+$ cd ../contiki-2.5
+$ patch -p1 < ../valence64/contiki-2.5-autostart.patch
+
+If you want to use my randomizesrcport.pl script to randomize the
+initial source port number (which is useful during development), then
+also apply this patch (and uncomment ./randomizesrcport.pl from the disk
+target of the Makefile):
+
+$ patch -p1 < ../valence64/contiki-2.5-randomsrcport.patch
+
+You must also have the cc65 compiler/assembler package installed in
+/usr/local/bin. (Or edit the CC65_HOME value in vncclient/Makefile to
+point to the location.)
+
+Type "make".
+
+
+Build concept
+----------------------------------------
+
+Valence64 uses a somewhat convoluted process to produce the final
+product, due to it being a BASIC/ML hybrid program. In the final
+output, the binary 6502 executable code ("ML code") is appended to the
+end of the BASIC program, and launched from BASIC via a SYS call. This
+poses several challenges:
+
+1. The ML link step needs knowledge of the final memory location of the
+program for proper linking. This location will change every time the
+BASIC program is modified, since the starting address will be at the end
+of the BASIC code.
+2. The BASIC program doesn't know the memory locations to SYS until the
+ML code is compiled/assembled/linked.
+
+To work around this, I use scripts for post-processing. This allows the
+BASIC program to SYS with placeholder addresses, which are filled in
+based on the symbol table used by the linker. During linking, which
+happens after the BASIC program has been rendered into a tight PRG file,
+a script inspects the PRG file and determines the ML starting address.
+A linker configuration is dynamically built from this information using
+a template.
+
Binary file not shown.
@@ -0,0 +1 @@
+���
@@ -0,0 +1,106 @@
+#!/usr/bin/perl
+######################################################################
+#
+# combine
+#
+# Merge a BASIC program and a 6502 machine language program into one
+# file for convenience and fast loading. The ML code should be linked
+# for a starting address just after the end of the BASIC program.
+#
+# (c) 2012 David Simmons
+#
+# usage: combine.pl basicprogram.prg mlprog.prg > combinedprog.prg
+#
+######################################################################
+
+use strict;
+use warnings;
+use bytes;
+
+if (@ARGV < 2) {
+ die "usage: combine.pl basicprogram.prg mlprog.prg [symbol.map]\n";
+}
+
+my ($bas, $ml);
+
+# read BASIC file
+open(BAS, $ARGV[0]) || die "cannot open basic file: $!\n";
+{
+ local $/;
+ $bas = <BAS>;
+}
+close(BAS);
+
+# read ML file
+open(ML, $ARGV[1]) || die "cannot open ml file: $!\n";
+{
+ local $/;
+ $ml = <ML>;
+}
+close(ML);
+
+# read symbol table, if available
+my $exports;
+if (@ARGV >= 3) {
+ my $in = 0;
+ open(MAP, $ARGV[2]) || die "cannot open symbol map: $!\n";
+ while (<MAP>) {
+ chomp;
+ if (/^Exports list:$/) {
+ $in = 1; next;
+ }
+ if ($in) {
+ if (/^$/) {
+ $in = 0; next;
+ }
+ if (/^\s*(\S+)\s+(\S+)\s+\S+\s+(\S+)\s+(\S+)\s+\S+\s*$/) {
+ $exports->{$1} = hex($2);
+ $exports->{$3} = hex($4);
+ } elsif (/^\s*(\S+)\s+(\S+)\s+\S+\s*$/) {
+ $exports->{$1} = hex($2);
+ }
+ }
+
+ }
+ close(MAP);
+}
+
+my $jumpaddr = sprintf("%05d", 0x7FF+length($bas));
+
+# write the actual jump addresses into the basic program,
+# replacing the placeholder 'SYS "symbol"' calls.
+sub translate {
+ my $symbol = shift;
+ my $address;
+ if ($symbol eq 'JUMPSTART') {
+ $address = $jumpaddr;
+ } else {
+ $address = $exports->{lc $symbol};
+ }
+ printf(STDERR "TRANSLATE $symbol -> $address\n");
+ return $address;
+}
+my $l1 = bytes::length($bas);
+$bas =~ s/\x9e "(\S+)"(.*?)\x00/sprintf("\x9e %d%s\x00",&translate($1),$2)/ge;
+my $l2 = length($bas);
+if ($l1 < $l2) {
+ die "symbol name substitution made the program larger\n";
+} elsif ($l1 > $l2) {
+ # apply padding
+ #printf STDERR "PADDING: ".($l1-$l2)."\n";
+ $bas .= ("\xff" x ($l1-$l2));
+}
+
+# trim the first 14 bytes from the ML file. This contains
+# the 2-byte starting address, and 12 bytes of needless
+# BASIC bootstrap code.
+$ml = substr($ml,14);
+
+# while we're here, hack out the cc65 runtime's annoying
+# shift to the upper/lowercase character set
+$ml =~ s/\xa9\x0e\x20\xd2\xff/\xa9\x8e\x20\xd2\xff/g;
+
+# combine and deliver to stdout
+print $bas;
+print $ml;
+
@@ -0,0 +1,38 @@
+diff -Nru contiki-2.5.orig/platform/c64/contiki-main.c contiki-2.5/platform/c64/contiki-main.c
+--- contiki-2.5.orig/platform/c64/contiki-main.c 2011-09-06 15:43:39.000000000 -0600
++++ contiki-2.5/platform/c64/contiki-main.c 2012-02-13 00:40:44.171722661 -0700
+@@ -63,6 +63,7 @@
+ main(void)
+ {
+ struct ethernet_config *ethernet_config;
++ struct process *vncclient_process = NULL;
+
+ process_init();
+
+@@ -120,6 +121,26 @@
+ process_run();
+
+ etimer_request_poll();
++
++ if (! vncclient_process) {
++ // look for vncclient
++ struct process *q;
++ for (q = PROCESS_LIST(); q != NULL; q = q->next) {
++ if (strcmp(q->name, "vncclient")==0) {
++ vncclient_process = q;
++ break;
++ }
++ }
++ } else {
++ struct process *q;
++ for (q = PROCESS_LIST(); q != vncclient_process && q != NULL; q = q->next);
++ if (q == NULL) {
++ // time to leave
++ break;
++ }
++ }
++
++
+ }
+ }
+ /*-----------------------------------------------------------------------------------*/
@@ -0,0 +1,16 @@
+--- contiki-2.5.orig/core/net/uip.c 2011-09-06 15:43:39.000000000 -0600
++++ contiki-2.5/core/net/uip.c 2012-02-15 23:15:18.413803065 -0700
+@@ -377,7 +377,12 @@
+ uip_conns[c].tcpstateflags = UIP_CLOSED;
+ }
+ #if UIP_ACTIVE_OPEN || UIP_UDP
+- lastport = 1024;
++
++{
++ // simmons-hack: marker for initial source-port
++ u16_t x[5] = {0xdead, 0xbeef, 0x0000, 0xdead, 0xbeef};
++ lastport = 1024 + x[2];
++}
+ #endif /* UIP_ACTIVE_OPEN || UIP_UDP */
+
+ #if UIP_UDP
@@ -0,0 +1,29 @@
+
+;set up some helpful labels
+CLEAR = $E544
+CHROUT = $FFD2
+
+.segment "BASICSTUB"
+
+.byte $00
+.byte $C0
+
+.code
+main:
+ jsr CLEAR
+ ldx #0
+loop:
+ lda greeting,x
+ cmp #0
+ beq finish
+ jsr CHROUT
+ inx
+ jmp loop
+finish:
+ rts
+
+.data
+greeting:
+ .byte "HELLO, WORLD!"
+ .byte $00
+
@@ -0,0 +1,8 @@
+MEMORY {
+ RAM: start = $BFFE, size = $1002, file = %O, define = yes;
+}
+SEGMENTS {
+ BASICSTUB: load = RAM, type = ro;
+ CODE: load = RAM, type = ro;
+ DATA: load = RAM, type = rw;
+}
Oops, something went wrong.

0 comments on commit 965c947

Please sign in to comment.