mirror of
https://github.com/sehugg/8bitworkshop.git
synced 2024-06-07 17:29:31 +00:00
c64: updated filesystem, presets, load/save
This commit is contained in:
parent
d55576be9f
commit
f9392c5a96
32
presets/c64/cartheader.dasm
Normal file
32
presets/c64/cartheader.dasm
Normal 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
365
presets/c64/eliza.c
Normal 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");
|
||||||
|
}
|
|
@ -1,17 +1,8 @@
|
||||||
|
|
||||||
processor 6502
|
include "cartheader.dasm"
|
||||||
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
|
|
||||||
; program start
|
; program start
|
||||||
Temp equ $00
|
Temp equ $03
|
||||||
Start
|
Start
|
||||||
sei ; turn off interrupts
|
sei ; turn off interrupts
|
||||||
ldy #0
|
ldy #0
|
||||||
|
|
332
presets/c64/sidtune.dasm
Normal file
332
presets/c64/sidtune.dasm
Normal 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
10
presets/c64/skeleton.cc65
Normal 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
196
presets/c64/tgidemo.c
Normal 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;
|
||||||
|
}
|
|
@ -1117,6 +1117,7 @@ export abstract class BaseZ80MachinePlatform<T extends Machine> extends BaseMach
|
||||||
}
|
}
|
||||||
|
|
||||||
// WASM Support
|
// WASM Support
|
||||||
|
// TODO: detangle from c64
|
||||||
|
|
||||||
export class WASMMachine implements Machine {
|
export class WASMMachine implements Machine {
|
||||||
|
|
||||||
|
@ -1131,6 +1132,8 @@ export class WASMMachine implements Machine {
|
||||||
romarr : Uint8Array;
|
romarr : Uint8Array;
|
||||||
stateptr : number;
|
stateptr : number;
|
||||||
statearr : Uint8Array;
|
statearr : Uint8Array;
|
||||||
|
cpustateptr : number;
|
||||||
|
cpustatearr : Uint8Array;
|
||||||
cpu : CPU;
|
cpu : CPU;
|
||||||
audio : SampledAudioSink;
|
audio : SampledAudioSink;
|
||||||
audioarr : Float32Array;
|
audioarr : Float32Array;
|
||||||
|
@ -1147,7 +1150,6 @@ export class WASMMachine implements Machine {
|
||||||
isStable: self.isStable.bind(self),
|
isStable: self.isStable.bind(self),
|
||||||
reset: self.reset.bind(self),
|
reset: self.reset.bind(self),
|
||||||
saveState: () => {
|
saveState: () => {
|
||||||
self.exports.machine_save_state(self.sys, self.stateptr);
|
|
||||||
return self.getCPUState();
|
return self.getCPUState();
|
||||||
},
|
},
|
||||||
loadState: () => {
|
loadState: () => {
|
||||||
|
@ -1177,10 +1179,13 @@ export class WASMMachine implements Machine {
|
||||||
// init machine instance
|
// init machine instance
|
||||||
this.sys = this.exports.machine_init(cBIOSPointer);
|
this.sys = this.exports.machine_init(cBIOSPointer);
|
||||||
console.log('machine_init', this.sys);
|
console.log('machine_init', this.sys);
|
||||||
// create state buffer
|
// create state buffers
|
||||||
var statesize = this.exports.machine_get_state_size();
|
var statesize = this.exports.machine_get_state_size();
|
||||||
this.stateptr = this.exports.malloc(statesize);
|
this.stateptr = this.exports.malloc(statesize);
|
||||||
this.statearr = new Uint8Array(this.exports.memory.buffer, this.stateptr, 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
|
// create audio buffer
|
||||||
var sampbufsize = 4096*4;
|
var sampbufsize = 4096*4;
|
||||||
this.audioarr = new Float32Array(this.exports.memory.buffer, this.exports.machine_get_sample_buffer(), sampbufsize);
|
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;
|
if (this.prgstart == 0x801) this.prgstart = 0x80d;
|
||||||
}
|
}
|
||||||
// set init string
|
// set init string
|
||||||
|
// TODO: sometimes gets hung up
|
||||||
if (this.prgstart) {
|
if (this.prgstart) {
|
||||||
this.initstring = "\r\r\r\r\r\r\r\r\r\r\rSYS " + this.prgstart + "\r";
|
this.initstring = "\r\r\r\r\r\r\r\r\r\r\rSYS " + this.prgstart + "\r";
|
||||||
this.initindex = 0;
|
this.initindex = 0;
|
||||||
|
@ -1253,33 +1259,24 @@ export class WASMMachine implements Machine {
|
||||||
this.exports.machine_mem_write(this.sys, address & 0xffff, value & 0xff);
|
this.exports.machine_mem_write(this.sys, address & 0xffff, value & 0xff);
|
||||||
}
|
}
|
||||||
getCPUState() {
|
getCPUState() {
|
||||||
|
this.exports.machine_save_cpu_state(this.sys, this.cpustateptr);
|
||||||
|
var s = this.cpustatearr;
|
||||||
return {
|
return {
|
||||||
PC:this.getPC(),
|
PC:s[2] + (s[3]<<8),
|
||||||
SP:this.getSP(),
|
SP:s[9],
|
||||||
A:this.statearr[14],
|
A:s[6],
|
||||||
X:this.statearr[15],
|
X:s[7],
|
||||||
Y:this.statearr[16],
|
Y:s[8],
|
||||||
S:this.statearr[17],
|
C:s[10] & 1,
|
||||||
flags:this.statearr[18],
|
Z:s[10] & 2,
|
||||||
C:this.statearr[18] & 1,
|
I:s[10] & 4,
|
||||||
Z:this.statearr[18] & 2,
|
D:s[10] & 8,
|
||||||
I:this.statearr[18] & 4,
|
V:s[10] & 64,
|
||||||
D:this.statearr[18] & 8,
|
N:s[10] & 128,
|
||||||
V:this.statearr[18] & 64,
|
|
||||||
N:this.statearr[18] & 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() {
|
saveState() {
|
||||||
this.exports.machine_save_state(this.sys, this.stateptr);
|
this.exports.machine_save_state(this.sys, this.stateptr);
|
||||||
// TODO: take out CPU state, memory
|
|
||||||
return {
|
return {
|
||||||
c:this.getCPUState(),
|
c:this.getCPUState(),
|
||||||
state:this.statearr.slice(0)
|
state:this.statearr.slice(0)
|
||||||
|
@ -1289,11 +1286,14 @@ export class WASMMachine implements Machine {
|
||||||
this.statearr.set(state.state);
|
this.statearr.set(state.state);
|
||||||
this.exports.machine_load_state(this.sys, this.stateptr);
|
this.exports.machine_load_state(this.sys, this.stateptr);
|
||||||
}
|
}
|
||||||
|
// assume controls buffer is smaller than cpu buffer
|
||||||
saveControlsState() : any {
|
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 {
|
loadControlsState(state) : void {
|
||||||
// TODO
|
this.cpustatearr.set(state.controls);
|
||||||
|
this.exports.machine_load_controls_state(this.sys, this.cpustateptr);
|
||||||
}
|
}
|
||||||
getVideoParams() {
|
getVideoParams() {
|
||||||
return {width:392, height:272, overscan:true, videoFrequency:50}; // TODO: const
|
return {width:392, height:272, overscan:true, videoFrequency:50}; // TODO: const
|
||||||
|
|
|
@ -5,6 +5,9 @@ import { PLATFORMS } from "../common/emu";
|
||||||
|
|
||||||
const C64_PRESETS = [
|
const C64_PRESETS = [
|
||||||
{id:'hello.dasm', name:'Hello World (ASM)'},
|
{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:[
|
const C64_MEMORY_MAP = { main:[
|
||||||
|
|
File diff suppressed because one or more lines are too long
|
@ -22,11 +22,9 @@ Module.expectedDataFileDownloads++;
|
||||||
var REMOTE_PACKAGE_BASE = 'fs65-c64.data';
|
var REMOTE_PACKAGE_BASE = 'fs65-c64.data';
|
||||||
if (typeof Module['locateFilePackage'] === 'function' && !Module['locateFile']) {
|
if (typeof Module['locateFilePackage'] === 'function' && !Module['locateFile']) {
|
||||||
Module['locateFile'] = Module['locateFilePackage'];
|
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' ?
|
var REMOTE_PACKAGE_NAME = Module['locateFile'] ? Module['locateFile'](REMOTE_PACKAGE_BASE, '') : REMOTE_PACKAGE_BASE;
|
||||||
Module['locateFile'](REMOTE_PACKAGE_BASE) :
|
|
||||||
((Module['filePackagePrefixURL'] || '') + REMOTE_PACKAGE_BASE);
|
|
||||||
|
|
||||||
var REMOTE_PACKAGE_SIZE = metadata.remote_package_size;
|
var REMOTE_PACKAGE_SIZE = metadata.remote_package_size;
|
||||||
var PACKAGE_UUID = metadata.package_uuid;
|
var PACKAGE_UUID = metadata.package_uuid;
|
||||||
|
@ -102,27 +100,26 @@ Module.expectedDataFileDownloads++;
|
||||||
}
|
}
|
||||||
Module['FS_createPath']('/', 'include', true, true);
|
Module['FS_createPath']('/', 'include', true, true);
|
||||||
Module['FS_createPath']('/include', 'em', 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', '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', 'joystick', true, true);
|
||||||
|
Module['FS_createPath']('/include', 'sys', true, true);
|
||||||
Module['FS_createPath']('/', 'asminc', true, true);
|
Module['FS_createPath']('/', 'asminc', true, true);
|
||||||
Module['FS_createPath']('/', 'cfg', true, true);
|
Module['FS_createPath']('/', 'cfg', true, true);
|
||||||
Module['FS_createPath']('/', 'lib', true, true);
|
Module['FS_createPath']('/', 'lib', true, true);
|
||||||
Module['FS_createPath']('/', 'target', true, true);
|
Module['FS_createPath']('/', 'target', true, true);
|
||||||
Module['FS_createPath']('/target', 'c64', true, true);
|
Module['FS_createPath']('/target', 'c64', true, true);
|
||||||
Module['FS_createPath']('/target/c64', 'drv', 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', '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.start = start;
|
||||||
this.end = end;
|
this.end = end;
|
||||||
this.crunched = crunched;
|
|
||||||
this.audio = audio;
|
this.audio = audio;
|
||||||
}
|
}
|
||||||
DataRequest.prototype = {
|
DataRequest.prototype = {
|
||||||
|
@ -135,9 +132,7 @@ Module['FS_createPath']('/target/c64/drv', 'ser', true, true);
|
||||||
send: function() {},
|
send: function() {},
|
||||||
onload: function() {
|
onload: function() {
|
||||||
var byteArray = this.byteArray.subarray(this.start, this.end);
|
var byteArray = this.byteArray.subarray(this.start, this.end);
|
||||||
|
this.finish(byteArray);
|
||||||
this.finish(byteArray);
|
|
||||||
|
|
||||||
},
|
},
|
||||||
finish: function(byteArray) {
|
finish: function(byteArray) {
|
||||||
var that = this;
|
var that = this;
|
||||||
|
@ -151,7 +146,7 @@ Module['FS_createPath']('/target/c64/drv', 'ser', true, true);
|
||||||
|
|
||||||
var files = metadata.files;
|
var files = metadata.files;
|
||||||
for (var i = 0; i < files.length; ++i) {
|
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
|
// 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).
|
// (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);
|
var ptr = Module['getMemory'](byteArray.length);
|
||||||
Module['HEAPU8'].set(byteArray, ptr);
|
Module['HEAPU8'].set(byteArray, ptr);
|
||||||
DataRequest.prototype.byteArray = Module['HEAPU8'].subarray(ptr, ptr+byteArray.length);
|
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');
|
Module['removeRunDependency']('fs65-c64.js.metadata');
|
||||||
}
|
}
|
||||||
|
|
||||||
var REMOTE_METADATA_NAME = typeof Module['locateFile'] === 'function' ?
|
function runMetaWithFS() {
|
||||||
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() {
|
|
||||||
Module['addRunDependency']('fs65-c64.js.metadata');
|
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
|
@ -313,5 +313,11 @@ describe('Worker', function() {
|
||||||
it('should assemble CA65', function(done) {
|
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);
|
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);
|
||||||
|
});
|
||||||
|
*/
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
BIN
wasm/c64.wasm
BIN
wasm/c64.wasm
Binary file not shown.
Loading…
Reference in New Issue
Block a user