c64: updated filesystem, presets, load/save

This commit is contained in:
Steven Hugg 2019-12-18 19:06:00 -06:00
parent d55576be9f
commit f9392c5a96
13 changed files with 22344 additions and 17823 deletions

View File

@ -0,0 +1,32 @@
processor 6502
org $7ffe
; 2-byte load address for ROM image
word $8000
; http://swut.net/c64cart-howto.html
; https://codebase64.org/doku.php?id=base:assembling_your_own_cart_rom_image
.word CartKReset ; cold start vector
.word CartWStart ; warm start vector
.byte $c3, $c2, $cd, $38, $30 ; "CBM80"
CartKReset
STX $D016 ; Turn on VIC for PAL / NTSC check
JSR $FDA3 ; IOINIT - Init CIA chips
JSR $FD50 ; RANTAM - Clear/test system RAM
JSR $FD15 ; RESTOR - Init KERNAL RAM vectors
JSR $FF5B ; CINT - Init VIC and screen editor
CLI ; Re-enable IRQ interrupts
CartBReset
; init BASIC?
IFCONST CART_INIT_BASIC
JSR $E453 ; Init BASIC RAM vectors
JSR $E3BF ; Main BASIC RAM Init routine
JSR $E422 ; Power-up message / NEW command
LDX #$FB
TXS ; Reduce stack pointer for BASIC
; don't init BASIC, just NOP
ELSE
REPEAT 12
NOP
REPEND
ENDIF
CartWStart
; should be * = $x025

365
presets/c64/eliza.c Normal file
View File

@ -0,0 +1,365 @@
/* eliza.c
* ys
* original code by Weizenbaum, 1966
* this rendition based on Charles Hayden's Java implementation from http://chayden.net/eliza/Eliza.html
*
* Note: There are certainly far more optimal and elegant ways to code this... we kept this
* structure to be faithful to the original. -scaz
*/
#include <ctype.h>
#include <stdio.h>
#include <string.h>
#include <conio.h>
#include <cbm_petscii_charmap.h>
#define NUMKEYWORDS 37
#define MAXLINELEN 40
#define NUMSWAPS 14
const char *keywords[]= {
"CAN YOU","CAN I","YOU ARE","YOURE","I DONT","I FEEL",
"WHY DONT YOU","WHY CANT I","ARE YOU","I CANT","I AM","IM ",
"YOU ","I WANT","WHAT","HOW","WHO","WHERE",
"WHEN","WHY",
"NAME","CAUSE","SORRY","DREAM","HELLO","HI ","MAYBE",
" NO","YOUR","ALWAYS","THINK","ALIKE","YES","FRIEND",
"COMPUTER","CAR","NOKEYFOUND"};
const char *SWAPS[NUMSWAPS][2] = {
{"ARE","AM"},
{"WERE", "WAS"},
{"YOU","I"},
{"YOUR", "MY"},
{"IVE", "YOU'VE"},
{"IM", "YOU'RE"},
{"YOU", "ME"},
{"ME", "YOU"},
{"AM","ARE"},
{"WAS", "WERE"},
{"I","YOU"},
{"MY", "YOUR"},
{"YOUVE", "I'VE"},
{"YOURE", "I'M"}
};
int ResponsesPerKeyword[NUMKEYWORDS]= {
3,2,4,4,4,3,
3,2,3,3,4,4,
3,5,9,9,9,9,
9,9,
2,4,4,4,1,1,5,
5,2,4,3,7,3,6,
7,5,6};
const char *responses[NUMKEYWORDS][9] = {
{ "DON'T YOU BELIEVE THAT I CAN*",
"PERHAPS YOU WOULD LIKE TO BE ABLE TO*",
"YOU WANT ME TO BE ABLE TO*"},
{ "PERHAPS YOU DON'T WANT TO*",
"DO YOU WANT TO BE ABLE TO*"},
{ "WHAT MAKES YOU THINK I AM*",
"DOES IT PLEASE YOU TO BELIEVE I AM*",
"PERHAPS YOU WOULD LIKE TO BE*",
"DO YOU SOMETIMES WISH YOU WERE*"},
{ "WHAT MAKES YOU THINK I AM*",
"DOES IT PLEASE YOU TO BELIEVE I AM*",
"PERHAPS YOU WOULD LIKE TO BE*",
"DO YOU SOMETIMES WISH YOU WERE*"},
{ "DON'T YOU REALLY*",
"WHY DON'T YOU*",
"DO YOU WISH TO BE ABLE TO*",
"DOES THAT TROUBLE YOU?"},
{ "TELL ME MORE ABOUT SUCH FEELINGS.",
"DO YOU OFTEN FEEL*",
"DO YOU ENJOY FEELING*"},
{ "DO YOU REALLY BELIEVE I DON'T*",
"PERHAPS IN GOOD TIME I WILL*",
"DO YOU WANT ME TO*"},
{ "DO YOU THINK YOU SHOULD BE ABLE TO*",
"WHY CAN'T YOU*"},
{ "WHY ARE YOU INTERESTED IN WHETHER OR NOT I AM*",
"WOULD YOU PREFER IF I WERE NOT*",
"PERHAPS IN YOUR FANTASIES I AM*"},
{ "HOW DO YOU KNOW YOU CAN'T*",
"HAVE YOU TRIED?",
"PERHAPS YOU CAN NOW*"},
{ "DID YOU COME TO ME BECAUSE YOU ARE*",
"HOW LONG HAVE YOU BEEN*",
"DO YOU BELIEVE IT IS NORMAL TO BE*",
"DO YOU ENJOY BEING*"},
{ "DID YOU COME TO ME BECAUSE YOU ARE*",
"HOW LONG HAVE YOU BEEN*",
"DO YOU BELIEVE IT IS NORMAL TO BE*",
"DO YOU ENJOY BEING*"},
{ "WE WERE DISCUSSING YOU-- NOT ME.",
"OH, I*",
"YOU'RE NOT REALLY TALKING ABOUT ME, ARE YOU?"},
{ "WHAT WOULD IT MEAN TO YOU IF YOU GOT*",
"WHY DO YOU WANT*",
"SUPPOSE YOU SOON GOT*",
"WHAT IF YOU NEVER GOT*",
"I SOMETIMES ALSO WANT*"},
{ "WHY DO YOU ASK?",
"DOES THAT QUESTION INTEREST YOU?",
"WHAT ANSWER WOULD PLEASE YOU THE MOST?",
"WHAT DO YOU THINK?",
"ARE SUCH QUESTIONS ON YOUR MIND OFTEN?",
"WHAT IS IT THAT YOU REALLY WANT TO KNOW?",
"HAVE YOU ASKED ANYONE ELSE?",
"HAVE YOU ASKED SUCH QUESTIONS BEFORE?",
"WHAT ELSE COMES TO MIND WHEN YOU ASK THAT?"},
{ "WHY DO YOU ASK?",
"DOES THAT QUESTION INTEREST YOU?",
"WHAT ANSWER WOULD PLEASE YOU THE MOST?",
"WHAT DO YOU THINK?",
"ARE SUCH QUESTIONS ON YOUR MIND OFTEN?",
"WHAT IS IT THAT YOU REALLY WANT TO KNOW?",
"HAVE YOU ASKED ANYONE ELSE?",
"HAVE YOU ASKED SUCH QUESTIONS BEFORE?",
"WHAT ELSE COMES TO MIND WHEN YOU ASK THAT?"},
{ "WHY DO YOU ASK?",
"DOES THAT QUESTION INTEREST YOU?",
"WHAT ANSWER WOULD PLEASE YOU THE MOST?",
"WHAT DO YOU THINK?",
"ARE SUCH QUESTIONS ON YOUR MIND OFTEN?",
"WHAT IS IT THAT YOU REALLY WANT TO KNOW?",
"HAVE YOU ASKED ANYONE ELSE?",
"HAVE YOU ASKED SUCH QUESTIONS BEFORE?",
"WHAT ELSE COMES TO MIND WHEN YOU ASK THAT?"},
{ "WHY DO YOU ASK?",
"DOES THAT QUESTION INTEREST YOU?",
"WHAT ANSWER WOULD PLEASE YOU THE MOST?",
"WHAT DO YOU THINK?",
"ARE SUCH QUESTIONS ON YOUR MIND OFTEN?",
"WHAT IS IT THAT YOU REALLY WANT TO KNOW?",
"HAVE YOU ASKED ANYONE ELSE?",
"HAVE YOU ASKED SUCH QUESTIONS BEFORE?",
"WHAT ELSE COMES TO MIND WHEN YOU ASK THAT?"},
{ "WHY DO YOU ASK?",
"DOES THAT QUESTION INTEREST YOU?",
"WHAT ANSWER WOULD PLEASE YOU THE MOST?",
"WHAT DO YOU THINK?",
"ARE SUCH QUESTIONS ON YOUR MIND OFTEN?",
"WHAT IS IT THAT YOU REALLY WANT TO KNOW?",
"HAVE YOU ASKED ANYONE ELSE?",
"HAVE YOU ASKED SUCH QUESTIONS BEFORE?",
"WHAT ELSE COMES TO MIND WHEN YOU ASK THAT?"},
{ "WHY DO YOU ASK?",
"DOES THAT QUESTION INTEREST YOU?",
"WHAT ANSWER WOULD PLEASE YOU THE MOST?",
"WHAT DO YOU THINK?",
"ARE SUCH QUESTIONS ON YOUR MIND OFTEN?",
"WHAT IS IT THAT YOU REALLY WANT TO KNOW?",
"HAVE YOU ASKED ANYONE ELSE?",
"HAVE YOU ASKED SUCH QUESTIONS BEFORE?",
"WHAT ELSE COMES TO MIND WHEN YOU ASK THAT?"},
{ "NAMES DON'T INTEREST ME.",
"I DON'T CARE ABOUT NAMES-- PLEASE GO ON."},
{ "IS THAT THE REAL REASON?",
"DON'T ANY OTHER REASONS COME TO MIND?",
"DOES THAT REASON EXPLAIN ANY THING ELSE?",
"WHAT OTHER REASONS MIGHT THERE BE?"},
{ "PLEASE DON'T APOLOGIZE.",
"APOLOGIES ARE NOT NECESSARY.",
"WHAT FEELINGS DO YOU HAVE WHEN YOU APOLOGIZE?",
"DON'T BE SO DEFENSIVE!"},
{ "WHAT DOES THAT DREAM SUGGEST TO YOU?",
"DO YOU DREAM OFTEN?",
"WHAT PERSONS APPEAR IN YOUR DREAMS?",
"ARE YOU DISTURBED BY YOUR DREAMS?"},
{ "HOW DO YOU DO--PLEASE STATE YOUR PROBLEM."},
{ "HOW DO YOU DO--PLEASE STATE YOUR PROBLEM."},
{ "YOU DON'T SEEM QUITE CERTAIN.",
"WHY THE UNCERTAIN TONE?",
"CAN'T YOU BE MORE POSITIVE?",
"YOU AREN'T SURE?",
"DON'T YOU KNOW?"},
{ "ARE YOU SAYING NO JUST TO BE NEGATIVE?",
"YOU ARE BEING A BIT NEGATIVE.",
"WHY NOT?",
"ARE YOU SURE?",
"WHY NO?"},
{ "WHY ARE YOU CONCERNED ABOUT MY*",
"WHAT ABOUT YOUR OWN*"},
{ "CAN YOU THINK OF A SPECIFIC EXAMPLE?",
"WHEN?",
"WHAT ARE YOU THINKING OF?",
"REALLY, ALWAYS?"},
{ "DO YOU REALLY THINK SO?",
"BUT YOU ARE NOT SURE YOU*",
"DO YOU DOUBT YOU*"},
{ "IN WHAT WAY?",
"WHAT RESEMBLANCE DO YOU SEE?",
"WHAT DOES THE SIMILARITY SUGGEST TO YOU?",
"WHAT OTHER CONNECTIONS DO YOU SEE?",
"COULD THERE REALLY BE SOME CONNECTION?",
"HOW?"},
{ "YOU SEEM QUITE POSITIVE.",
"ARE YOU SURE?",
"I SEE.",
"I UNDERSTAND."},
{ "WHY DO YOU BRING UP THE TOPIC OF FRIENDS?",
"DO YOUR FRIENDS WORRY YOU?",
"DO YOUR FRIENDS PICK ON YOU?",
"ARE YOU SURE YOU HAVE ANY FRIENDS?",
"DO YOU IMPOSE ON YOUR FRIENDS?",
"PERHAPS YOUR LOVE FOR FRIENDS WORRIES YOU?"},
{ "DO COMPUTERS WORRY YOU?",
"ARE YOU TALKING ABOUT ME IN PARTICULAR?",
"ARE YOU FRIGHTENED BY MACHINES?",
"WHY DO YOU MENTION COMPUTERS?",
"WHAT DO YOU THINK MACHINES HAVE TO DO WITH YOUR PROBLEM?",
"DON'T YOU THINK COMPUTERS CAN HELP PEOPLE?",
"WHAT IS IT ABOUT MACHINES THAT WORRIES YOU?"},
{ "OH, DO YOU LIKE CARS?",
"MY FAVORITE CAR IS A LAMBORGINI COUNTACH. WHAT IS YOUR FAVORITE CAR?",
"MY FAVORITE CAR COMPANY IS FERRARI. WHAT IS YOURS?",
"DO YOU LIKE PORSCHES?",
"DO YOU LIKE PORSCHE TURBO CARRERAS?"},
{ "SAY, DO YOU HAVE ANY PSYCHOLOGICAL PROBLEMS?",
"WHAT DOES THAT SUGGEST TO YOU?",
"I SEE.",
"I'M NOT SURE I UNDERSTAND YOU FULLY.",
"COME, COME ELUCIDATE YOUR THOUGHTS.",
"CAN YOU ELABORATE ON THAT?",
"THAT IS QUITE INTERESTING."}
};
void print_center(const char *msg) {
int numspaces=(MAXLINELEN-strlen(msg))/2;
int i;
for(i=0;i<numspaces;i++)
printf(" ");
printf("%s\n", msg);
return;
}
void print_title () {
printf("\n\n");
print_center("*** ELIZA ***");
print_center("Original code by Weizenbaum, 1966");
print_center("To stop Eliza, type 'bye'");
printf("\n\n");
printf("HI! I'M ELIZA. WHAT'S YOUR PROBLEM?\n");
}
void readline(char *instr) {
char c;
int slen=0;
c=getchar();
while (c != '\n')
{
// removes punctuation and sets to uppercase
if(isalpha(c) || isspace(c))
instr[slen++]=toupper(c);
if(slen>MAXLINELEN-1)
{
printf("Exceeded Max Line Length\n");
}
c=getchar();
}
instr[slen]='\0';
}
void main()
{
int k,baseLength;
int whichReply[NUMKEYWORDS];
char lastinput[MAXLINELEN];
char reply[MAXLINELEN];
char *baseResponse, *token;
const char separator[2]=" ";
char inputstr[MAXLINELEN];
int x,s;
char *location;
// use the first reply for each keyword match the first time you see that keyword
for (x=0;x<NUMKEYWORDS; x++) {
whichReply[x] = 0;
}
// print a nice centered title screen
clrscr();
print_title();
lastinput[0]='\0';
while (1) {
printf(">");
readline(inputstr);
printf("\n");
// check for termination
if (strcmp(inputstr,"BYE")==0)
break;
// check for repeated entries
if (strcmp(lastinput,inputstr)==0)
{
printf("PLEASE DON'T REPEAT YOURSELF!\n");
continue;
}
strncpy(lastinput,inputstr,strlen(inputstr)+1);
// see if any of the keywords is contained in the input
// if not, we use the last element of keywords as our default responses
strcpy(reply,"");
for(k=0;k<NUMKEYWORDS-1;k++)
{
location=strstr(inputstr, keywords[k]);
if(location != NULL)
break;
}
// Build Eliza's response
// start with Eliza's canned response, based on the keyword match
baseResponse = (char *) responses[k][whichReply[k]];
baseLength = strlen(baseResponse);
if(baseResponse[baseLength-1] != '*')
{
// if we have a baseResponse without an asterix, just use it as-is
strcat(reply, baseResponse);
}
else
{
// if we do have an asterix, fill in the remaining with the user input
// use all but the last character of the base response
strncat(reply, baseResponse, baseLength-1);
// now add in the rest of the user's input, starting at <location>
// but skip over the keyword itself
location+=strlen(keywords[k]);
// take them one word at a time, so that we can substitute pronouns
token = strtok(location, separator);
while(token != NULL)
{
for(s=0;s<NUMSWAPS;s++)
{
if(strcmp(SWAPS[s][0], token) == 0)
{
token = (char *) SWAPS[s][1];
break;
}
}
strcat(reply," ");
strcat(reply, token);
token=strtok(NULL, separator);
};
strcat(reply, "?");
}
printf("%s\n", reply);
// next time, use the next appropriate reply for that keyword
whichReply[k]++;
if ( whichReply[k] >= ResponsesPerKeyword[k])
whichReply[k] = 0;
}
printf( "GOODBYE! THANKS FOR VISITING WITH ME...\n");
}

View File

@ -1,17 +1,8 @@
processor 6502
org $7ffe
word $8000 ; load address
; cartridge header (http://swut.net/c64cart-howto.html)
.byte $09, $80, $25, $80
.byte $c3, $c2, $cd, $38, $30
.byte $8e, $16, $d0, $20, $a3, $fd, $20
.byte $50, $fd, $20, $15, $fd, $20, $5b
.byte $ff, $58
.byte $ea, $ea, $ea, $ea, $ea, $ea, $ea
.byte $ea, $ea, $ea, $ea, $ea
include "cartheader.dasm"
; program start
Temp equ $00
Temp equ $03
Start
sei ; turn off interrupts
ldy #0

332
presets/c64/sidtune.dasm Normal file
View File

@ -0,0 +1,332 @@
; Title: "NewKidOnTheBlock"
; Chip: 6581 C64 used when composing.
; Author: Frantic/Hack'n'Trade
; https://codebase64.org/doku.php?id=base:256_bytes_tune_player
;---------------------------------
; CONSTANTS
;
DEBUG = 1
NUMBEROFVOICES = 3 ;Using all three Voices
S = $10 ;Song "speed"
;---------------------------------
; ZERO PAGE ADDRESSES
;
TICKCOUNTERS = $02 ;Use zp for tickcounters.. TICKCOUNTERS+0, TICKCOUNTERS+7,
;TICKCOUNTERS+14 will be used.
DATAPOS = $03 ;Use zp for SONGPOSITIONS... 0, 7, 14..
FILTERHI = $23
;---------------------------------
; CODE
;
include "cartheader.dasm"
Start: sei
ldy #$02 ;Set it to $02 so the first incorrectly timed
;iteration won't affect anything
sty FILTERHI ;Init filtersweep to make it a bit more deterministic.
;Init counters and sonpositions
lda #(NUMBEROFVOICES-1)*7 ;Voice indeX
_initlp: tax
sta DATAPOS,x ;Init datapos+0 to 0, datapos+7 to 7 and datapos+14 to 14.
sty TICKCOUNTERS,x ;y can be anything.. doesn't matter, but now I happen to
;init the filter so set it to $01 too
sec
sbc #7
bpl _initlp
;--
; Main player loop
_outerloop:
_wrast: cpx $d012 ;After the loop, x is a negative number, thus well above $3e
;(or whatever the critical raster value is again..)
bne _wrast ;First iteration won't be correct though, but since the
;counters are set to 2 initially it doesn't matter.
#if DEBUG
lda #1
sta $d020
sta $d021
#endif
jsr sweep
stx $d416 ;filter hi
ldx #(NUMBEROFVOICES-1)*7 ;Voice indeX
;Right here is a good place for Voice specific code, if there is any reason for that.
_innerloop:
dec TICKCOUNTERS,x
bne _loopend
;Time for new sound settings, turn gate and oscillator off..
lda #8
sta $d404,x
;Turn on global volume to make sure we'll hear anything at all.
;Reason for having this code *inside* the loop:
; To make sure the player won't run too fast and get executed
; twice on the same rasterline.
lda #$5f ;Hi-pass + Lo-pass filter on.
sta $d418
lda #$a2 ;Filter used on middle (melody) voice.
sta $d417
;Parse data sequence data
ldy DATAPOS,x
_newseq:
iny
lda _musicdata-1,y ;Get databyte
bne _nonewseq
lda _musicdata-0,y ;Get jumpval if it's jumptime
tay ;..and use new one instead
bpl _newseq ;This means data may not be larger than $80 bytes
_nonewseq:
sty DATAPOS,x
pha
and #$0f ;Note value
tay
lda _freqhi,y
sta $d401,x ;Freq hi
lda _freqlo,y
sta $d400,x ;Freq lo
pla
lsr
lsr
lsr
lsr
tay
lda adtab,y
sta $d405,x
lda durtab,y
sta TICKCOUNTERS,x
lda ctrltab,y
sta $d404,x
_loopend:
txa
.byte $cb,7 ;axs #7 / sbx #7 / whatever..
bpl _innerloop
#if DEBUG
dec $d020
dec $d021
jmp _outerloop
#endif
bmi _outerloop
sweep
inc $23
ldx $23
ldy #$00
rts
;---------------------------------
; "Instruments"
;
; Using AD only to save space. (SR is set to 00 as default)
;
; A pattern is S*8 ticks long, so using "instrument" 5 we
; can represent a whole empty pattern by just one byte in
; the sequence data. At the same time, this format allows
; for changes to the waveform every tick, which means we
; can also make drums and such things. But, not in this
; tune. Perhaps in the next one..
;
; 00 01 02 03 04 05 06
adtab: .byte $1c, $1b, $cd, $2b, $1a, $00, $ad
ctrltab: .byte $11, $11, $21, $21, $21, $00, $21
durtab: .byte S*1, S*3, S*6, S*2, S*1, S*8, S*8
;---------------------------------
; Sequence data
;
; Voc0 starts at 0
; Voc1 starts at 7
; Voc2 starts at 14
;
; Note and duration stored in one byte and the byte following a $00 (JP)
; byte is interpreted as the destination of a jump to another place in
; the data.
_musicdata:
_Voc0start:
.byte $00 | G4
.byte $00 | Az4
.byte $00 | C5
.byte $00 | D5
.byte $00 | Dz5
.byte JP
.byte <(_Voc0komp-_musicdata)
_Voc1start:
.byte $20 | D5
.byte $30 | Dz5
.byte $20 | D5
.byte $40 | A4
.byte $40 | Az4
.byte JP
.byte <(_Voc1melody-_musicdata)
_Voc2start:
;-
.byte $50 | 0
.byte $50 | 0
.byte $50 | 0
.byte $50 | 0
;-
.byte $50 | 0
_Voc2loop:
.byte $50 | 0
.byte $50 | 0
.byte $20 | C5
.byte $40 | Dz4
.byte $40 | F4
;-
.byte $50 | 0
.byte $60 | D5
.byte $20 | Dz5
.byte $30 | Az4
.byte $20 | A4
.byte $30 | F4
;-
.byte $60 | G4
.byte $50 | 0
.byte $50 | 0
.byte $60 | C5
;-
.byte $50 | 0
.byte $60 | D5
.byte $60 | Dz5
.byte $60 | F5
;-
.byte $60 | G5
.byte JP
.byte <(_Voc2loop-_musicdata)
_Voc0komp:
.byte $10 | G5
.byte $00 | D4
.byte $00 | Fz4
.byte $00 | A4
.byte $00 | Az4
.byte $00 | C5
.byte $10 | D5
.byte $00 | Dz4
.byte $00 | F4
.byte $00 | G4
.byte $00 | Az4
.byte $00 | C5
.byte $10 | Dz5
.byte $00 | F4
.byte $00 | A4
.byte $00 | C5
.byte $00 | D5
.byte $00 | Dz5
.byte $10 | F5
.byte JP
.byte <(_Voc0start-_musicdata)
_Voc1melody:
.byte $20 | C5
.byte $30 | Az4
.byte $20 | A4
.byte $30 | F4
;-
.byte $60 | G4
.byte $50 | 0
.byte $20 | F4
.byte $30 | Dz4
.byte $20 | F4
.byte $30 | Dz4
;-
.byte $20 | D4
.byte $30 | Dz4
.byte $20 | D4
.byte $30 | Fz4
.byte $20 | G4
.byte $30 | Dz4
.byte $00 | C4
.byte $00 | Dz4
.byte $00 | F4
.byte $00 | G4
.byte $00 | A4
.byte $00 | C5
.byte $00 | G5
.byte $00 | F5
.byte JP
.byte <(_Voc1start-_musicdata)
;---------------------------------
;Note freq data
;
; Only using needed notes.
JP = 0
C4 = 1
D4 = 2
Dz4 = 3
;E4 = 2;Not used
F4 = 4
Fz4 = 5
G4 = 6
;Gz4 = 6;Not used
A4 = 7
Az4 = 8
;B4 = 8;Not used
C5 = 9
;Cz5 = 9;Not used
D5 = 10
Dz5 = 11
;E5 = 11;Not used
F5 = 12
;Fz5 = 13;Not used
G5 = 13
;Gz5 ;Not used
;A5 ;Not used
;Az5 = 14;Not used
_freqlo = *-1 ;-1 to exclude the corresponding first byte (in _freqhi) used as a "wrap flag"
.byte $77
.byte $61,$e1
.byte $f7,$8f,$30
.byte $8f,$4e
.byte $ef
.byte $c3,$c3
.byte $ef
.byte $60
_freqhi:
.byte $00 ;WRAP
.byte $07
.byte $08,$08
.byte $09,$0a,$0b
.byte $0c,$0d
.byte $0e
.byte $10,$11
.byte $13
.byte $16

10
presets/c64/skeleton.cc65 Normal file
View File

@ -0,0 +1,10 @@
#include <stdio.h>
#include <conio.h>
#include <c64.h>
#include <cbm_petscii_charmap.h>
void main(void) {
clrscr();
printf("\r\nHello World!\r\n");
}

196
presets/c64/tgidemo.c Normal file
View File

@ -0,0 +1,196 @@
#include <stdio.h>
#include <stdlib.h>
#include <cc65.h>
#include <conio.h>
#include <ctype.h>
#include <modload.h>
#include <tgi.h>
#include <c64.h>
#define COLOR_BACK TGI_COLOR_BLACK
#define COLOR_FORE TGI_COLOR_WHITE
/*****************************************************************************/
/* Data */
/*****************************************************************************/
/* Driver stuff */
static unsigned MaxX;
static unsigned MaxY;
static unsigned AspectRatio;
/*****************************************************************************/
/* Code */
/*****************************************************************************/
static void CheckError (const char* S)
{
unsigned char Error = tgi_geterror ();
if (Error != TGI_ERR_OK) {
printf ("%s: %d\n", S, Error);
if (doesclrscrafterexit ()) {
cgetc ();
}
exit (EXIT_FAILURE);
}
}
#if DYN_DRV
static void DoWarning (void)
/* Warn the user that the dynamic TGI driver is needed for this program */
{
printf ("Warning: This program needs the TGI\n"
"driver on disk! Press 'y' if you have\n"
"it - any other key exits.\n");
if (tolower (cgetc ()) != 'y') {
exit (EXIT_SUCCESS);
}
printf ("OK. Please wait patiently...\n");
}
#endif
static void DoCircles (void)
{
static const unsigned char Palette[2] = { TGI_COLOR_WHITE, TGI_COLOR_ORANGE };
unsigned char I;
unsigned char Color = COLOR_FORE;
unsigned X = MaxX / 2;
unsigned Y = MaxY / 2;
tgi_setpalette (Palette);
{
tgi_setcolor (COLOR_FORE);
tgi_line (0, 0, MaxX, MaxY);
tgi_line (0, MaxY, MaxX, 0);
tgi_setcolor (Color);
for (I = 10; I < 240; I += 10) {
tgi_ellipse (X, Y, I, tgi_imulround (I, AspectRatio));
}
Color = Color == COLOR_FORE ? COLOR_BACK : COLOR_FORE;
}
}
static void DoCheckerboard (void)
{
static const unsigned char Palette[2] = { TGI_COLOR_WHITE, TGI_COLOR_BLACK };
unsigned X, Y;
unsigned char Color;
tgi_setpalette (Palette);
Color = COLOR_BACK;
{
for (Y = 0; Y <= MaxY; Y += 10) {
for (X = 0; X <= MaxX; X += 10) {
tgi_setcolor (Color);
tgi_bar (X, Y, X+9, Y+9);
Color = Color == COLOR_FORE ? COLOR_BACK : COLOR_FORE;
}
Color = Color == COLOR_FORE ? COLOR_BACK : COLOR_FORE;
}
Color = Color == COLOR_FORE ? COLOR_BACK : COLOR_FORE;
}
}
static void DoDiagram (void)
{
static const unsigned char Palette[2] = { TGI_COLOR_WHITE, TGI_COLOR_BLACK };
int XOrigin, YOrigin;
int Amp;
int X, Y;
unsigned I;
tgi_setpalette (Palette);
tgi_setcolor (COLOR_FORE);
tgi_clear();
/* Determine zero and aplitude */
YOrigin = MaxY / 2;
XOrigin = 10;
Amp = (MaxY - 19) / 2;
/* Y axis */
tgi_line (XOrigin, 10, XOrigin, MaxY-10);
tgi_line (XOrigin-2, 12, XOrigin, 10);
tgi_lineto (XOrigin+2, 12);
/* X axis */
tgi_line (XOrigin, YOrigin, MaxX-10, YOrigin);
tgi_line (MaxX-12, YOrigin-2, MaxX-10, YOrigin);
tgi_lineto (MaxX-12, YOrigin+2);
/* Sine */
tgi_gotoxy (XOrigin, YOrigin);
for (I = 0; I <= 360; I += 5) {
/* Calculate the next points */
X = (int) (((long) (MaxX - 19) * I) / 360);
Y = (int) (((long) Amp * -_sin (I)) / 256);
/* Draw the line */
tgi_lineto (XOrigin + X, YOrigin + Y);
}
}
static void DoLines (void)
{
static const unsigned char Palette[2] = { TGI_COLOR_WHITE, TGI_COLOR_BLACK };
unsigned X;
tgi_setpalette (Palette);
tgi_setcolor (COLOR_FORE);
for (X = 0; X <= MaxX; X += 10) {
tgi_line (0, 0, MaxY, X);
tgi_line (0, 0, X, MaxY);
tgi_line (MaxX, MaxY, 0, MaxY-X);
tgi_line (MaxX, MaxY, MaxY-X, 0);
}
}
int main (void)
{
unsigned char Border;
/* Install the driver */
tgi_install (tgi_static_stddrv);
CheckError ("tgi_install");
tgi_init ();
CheckError ("tgi_init");
tgi_clear ();
/* Get stuff from the driver */
MaxX = tgi_getmaxx ();
MaxY = tgi_getmaxy ();
AspectRatio = tgi_getaspectratio ();
/* Set the palette, set the border color */
Border = bordercolor (COLOR_BLACK);
/* Do graphics stuff */
while (!kbhit()) {
DoCircles ();
DoCheckerboard ();
DoDiagram ();
DoLines ();
}
/* Uninstall the driver */
tgi_uninstall ();
/* Reset the border */
(void) bordercolor (Border);
/* Done */
clrscr();
return EXIT_SUCCESS;
}

View File

@ -1117,6 +1117,7 @@ export abstract class BaseZ80MachinePlatform<T extends Machine> extends BaseMach
}
// WASM Support
// TODO: detangle from c64
export class WASMMachine implements Machine {
@ -1131,6 +1132,8 @@ export class WASMMachine implements Machine {
romarr : Uint8Array;
stateptr : number;
statearr : Uint8Array;
cpustateptr : number;
cpustatearr : Uint8Array;
cpu : CPU;
audio : SampledAudioSink;
audioarr : Float32Array;
@ -1147,7 +1150,6 @@ export class WASMMachine implements Machine {
isStable: self.isStable.bind(self),
reset: self.reset.bind(self),
saveState: () => {
self.exports.machine_save_state(self.sys, self.stateptr);
return self.getCPUState();
},
loadState: () => {
@ -1177,10 +1179,13 @@ export class WASMMachine implements Machine {
// init machine instance
this.sys = this.exports.machine_init(cBIOSPointer);
console.log('machine_init', this.sys);
// create state buffer
// create state buffers
var statesize = this.exports.machine_get_state_size();
this.stateptr = this.exports.malloc(statesize);
this.statearr = new Uint8Array(this.exports.memory.buffer, this.stateptr, statesize);
var cpustatesize = this.exports.machine_get_cpu_state_size();
this.cpustateptr = this.exports.malloc(cpustatesize);
this.cpustatearr = new Uint8Array(this.exports.memory.buffer, this.cpustateptr, cpustatesize);
// create audio buffer
var sampbufsize = 4096*4;
this.audioarr = new Float32Array(this.exports.memory.buffer, this.exports.machine_get_sample_buffer(), sampbufsize);
@ -1194,6 +1199,7 @@ export class WASMMachine implements Machine {
if (this.prgstart == 0x801) this.prgstart = 0x80d;
}
// set init string
// TODO: sometimes gets hung up
if (this.prgstart) {
this.initstring = "\r\r\r\r\r\r\r\r\r\r\rSYS " + this.prgstart + "\r";
this.initindex = 0;
@ -1253,33 +1259,24 @@ export class WASMMachine implements Machine {
this.exports.machine_mem_write(this.sys, address & 0xffff, value & 0xff);
}
getCPUState() {
this.exports.machine_save_cpu_state(this.sys, this.cpustateptr);
var s = this.cpustatearr;
return {
PC:this.getPC(),
SP:this.getSP(),
A:this.statearr[14],
X:this.statearr[15],
Y:this.statearr[16],
S:this.statearr[17],
flags:this.statearr[18],
C:this.statearr[18] & 1,
Z:this.statearr[18] & 2,
I:this.statearr[18] & 4,
D:this.statearr[18] & 8,
V:this.statearr[18] & 64,
N:this.statearr[18] & 128,
PC:s[2] + (s[3]<<8),
SP:s[9],
A:s[6],
X:s[7],
Y:s[8],
C:s[10] & 1,
Z:s[10] & 2,
I:s[10] & 4,
D:s[10] & 8,
V:s[10] & 64,
N:s[10] & 128,
}
}
/*
setPC(pc: number) {
this.exports.machine_save_state(this.sys, this.stateptr);
this.statearr[10] = pc & 0xff;
this.statearr[11] = pc >> 8;
this.exports.machine_load_state(this.sys, this.stateptr);
}
*/
saveState() {
this.exports.machine_save_state(this.sys, this.stateptr);
// TODO: take out CPU state, memory
return {
c:this.getCPUState(),
state:this.statearr.slice(0)
@ -1289,11 +1286,14 @@ export class WASMMachine implements Machine {
this.statearr.set(state.state);
this.exports.machine_load_state(this.sys, this.stateptr);
}
// assume controls buffer is smaller than cpu buffer
saveControlsState() : any {
// TODO
this.exports.machine_save_controls_state(this.sys, this.cpustateptr);
return { controls:this.cpustatearr.slice(0, this.exports.machine_get_controls_state_size()) }
}
loadControlsState(state) : void {
// TODO
this.cpustatearr.set(state.controls);
this.exports.machine_load_controls_state(this.sys, this.cpustateptr);
}
getVideoParams() {
return {width:392, height:272, overscan:true, videoFrequency:50}; // TODO: const

View File

@ -5,6 +5,9 @@ import { PLATFORMS } from "../common/emu";
const C64_PRESETS = [
{id:'hello.dasm', name:'Hello World (ASM)'},
{id:'sidtune.dasm', name:'SID Tune (ASM)'},
{id:'eliza.c', name:'Eliza (C)'},
{id:'tgidemo.c', name:'TGI Graphics Demo (C)'},
];
const C64_MEMORY_MAP = { main:[

File diff suppressed because one or more lines are too long

View File

@ -22,11 +22,9 @@ Module.expectedDataFileDownloads++;
var REMOTE_PACKAGE_BASE = 'fs65-c64.data';
if (typeof Module['locateFilePackage'] === 'function' && !Module['locateFile']) {
Module['locateFile'] = Module['locateFilePackage'];
Module.printErr('warning: you defined Module.locateFilePackage, that has been renamed to Module.locateFile (using your locateFilePackage for now)');
err('warning: you defined Module.locateFilePackage, that has been renamed to Module.locateFile (using your locateFilePackage for now)');
}
var REMOTE_PACKAGE_NAME = typeof Module['locateFile'] === 'function' ?
Module['locateFile'](REMOTE_PACKAGE_BASE) :
((Module['filePackagePrefixURL'] || '') + REMOTE_PACKAGE_BASE);
var REMOTE_PACKAGE_NAME = Module['locateFile'] ? Module['locateFile'](REMOTE_PACKAGE_BASE, '') : REMOTE_PACKAGE_BASE;
var REMOTE_PACKAGE_SIZE = metadata.remote_package_size;
var PACKAGE_UUID = metadata.package_uuid;
@ -102,27 +100,26 @@ Module.expectedDataFileDownloads++;
}
Module['FS_createPath']('/', 'include', true, true);
Module['FS_createPath']('/include', 'em', true, true);
Module['FS_createPath']('/include', 'mouse', true, true);
Module['FS_createPath']('/include', 'tgi', true, true);
Module['FS_createPath']('/include', 'geos', true, true);
Module['FS_createPath']('/include', 'sys', true, true);
Module['FS_createPath']('/include', 'tgi', true, true);
Module['FS_createPath']('/include', 'mouse', true, true);
Module['FS_createPath']('/include', 'joystick', true, true);
Module['FS_createPath']('/include', 'sys', true, true);
Module['FS_createPath']('/', 'asminc', true, true);
Module['FS_createPath']('/', 'cfg', true, true);
Module['FS_createPath']('/', 'lib', true, true);
Module['FS_createPath']('/', 'target', true, true);
Module['FS_createPath']('/target', 'c64', true, true);
Module['FS_createPath']('/target/c64', 'drv', true, true);
Module['FS_createPath']('/target/c64/drv', 'tgi', true, true);
Module['FS_createPath']('/target/c64/drv', 'mou', true, true);
Module['FS_createPath']('/target/c64/drv', 'emd', true, true);
Module['FS_createPath']('/target/c64/drv', 'joy', true, true);
Module['FS_createPath']('/target/c64/drv', 'ser', true, true);
Module['FS_createPath']('/target/c64/drv', 'joy', true, true);
Module['FS_createPath']('/target/c64/drv', 'tgi', true, true);
Module['FS_createPath']('/target/c64/drv', 'emd', true, true);
Module['FS_createPath']('/target/c64/drv', 'mou', true, true);
function DataRequest(start, end, crunched, audio) {
function DataRequest(start, end, audio) {
this.start = start;
this.end = end;
this.crunched = crunched;
this.audio = audio;
}
DataRequest.prototype = {
@ -135,9 +132,7 @@ Module['FS_createPath']('/target/c64/drv', 'ser', true, true);
send: function() {},
onload: function() {
var byteArray = this.byteArray.subarray(this.start, this.end);
this.finish(byteArray);
this.finish(byteArray);
},
finish: function(byteArray) {
var that = this;
@ -151,7 +146,7 @@ Module['FS_createPath']('/target/c64/drv', 'ser', true, true);
var files = metadata.files;
for (var i = 0; i < files.length; ++i) {
new DataRequest(files[i].start, files[i].end, files[i].crunched, files[i].audio).open('GET', files[i].filename);
new DataRequest(files[i].start, files[i].end, files[i].audio).open('GET', files[i].filename);
}
@ -164,7 +159,6 @@ Module['FS_createPath']('/target/c64/drv', 'ser', true, true);
// copy the entire loaded file into a spot in the heap. Files will refer to slices in that. They cannot be freed though
// (we may be allocating before malloc is ready, during startup).
if (Module['SPLIT_MEMORY']) Module.printErr('warning: you should run the file packager with --no-heap-copy when SPLIT_MEMORY is used, otherwise copying into the heap may fail due to the splitting');
var ptr = Module['getMemory'](byteArray.length);
Module['HEAPU8'].set(byteArray, ptr);
DataRequest.prototype.byteArray = Module['HEAPU8'].subarray(ptr, ptr+byteArray.length);
@ -199,22 +193,25 @@ Module['FS_createPath']('/target/c64/drv', 'ser', true, true);
Module['removeRunDependency']('fs65-c64.js.metadata');
}
var REMOTE_METADATA_NAME = typeof Module['locateFile'] === 'function' ?
Module['locateFile']('fs65-c64.js.metadata') :
((Module['filePackagePrefixURL'] || '') + 'fs65-c64.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['preRun']) Module['preRun'] = [];
Module["preRun"].push(function() {
function runMetaWithFS() {
Module['addRunDependency']('fs65-c64.js.metadata');
});
var REMOTE_METADATA_NAME = Module['locateFile'] ? Module['locateFile']('fs65-c64.js.metadata', '') : 'fs65-c64.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

View File

@ -313,5 +313,11 @@ describe('Worker', function() {
it('should assemble CA65', function(done) {
compile('ca65', ';#define LIBARGS ,\n\t.segment "HEADER"\n\t.segment "STARTUP"\n\t.segment "CHARS"\n\t.segment "VECTORS"\n\t.segment "SAMPLES"\n\t.segment "CODE"\n\tlda #0\n\tsta $1\n', 'nes', done, 131088, 2);
});
/* TODO
it('should compile C64 cc65 skeleton', function(done) {
var csource = ab2str(fs.readFileSync('presets/c64/skeleton.cc65'));
compile('cc65', csource, 'c64.wasm', done, 49152, 80, 0);
});
*/
});

Binary file not shown.