X-Git-Url: http://git.hungrycats.org/cgi-bin/gitweb.cgi?p=xscreensaver;a=blobdiff_plain;f=hacks%2Fasm6502.c;h=101ee5a6a416a98fbeadf7b0abca1b23f91d82a5;hp=aeda48267efaf7b95d0ba5f5fe92d726926cc0e4;hb=6b1c86cf395f59389e4ece4ea8f4bea2c332745b;hpb=c8c6deae79b408cffbc88043c766b3bc12cf0f13 diff --git a/hacks/asm6502.c b/hacks/asm6502.c index aeda4826..101ee5a6 100644 --- a/hacks/asm6502.c +++ b/hacks/asm6502.c @@ -1,3 +1,4 @@ +/*-*- indent-tabs-mode:nil -*- */ /* Copyright (C) 2007 Jeremy English * * Permission to use, copy, modify, distribute, and sell this software and its @@ -35,6 +36,10 @@ #include "asm6502.h" +#ifdef DEBUGGER +# define random rand +#endif + typedef enum{ LEFT, RIGHT } Side; @@ -179,10 +184,11 @@ static Bit8 stackPop(machine_6502 *machine) { } static void pushByte(machine_6502 *machine, Bit32 value ) { - Bit32 address = 0x600 + machine->codeLen; + Bit32 address = machine->defaultCodePC; checkAddress(address); - machine->memory[0x600 + machine->codeLen] = value & 0xff; + machine->memory[address] = value & 0xff; machine->codeLen++; + machine->defaultCodePC++; } /* @@ -295,9 +301,9 @@ static BOOL peekValue(machine_6502 *machine, AddrMode adm, Pointer *pointer, Bit pointer->value = memReadByte(machine, PC); return TRUE; case INDIRECT_X: - zp = memReadByte(machine, PC); + zp = memReadByte(machine, PC) + machine->regX; pointer->addr = memReadByte(machine,zp) + - (memReadByte(machine,zp+1)<<8) + machine->regX; + (memReadByte(machine,zp+1)<<8); pointer->value = memReadByte(machine, pointer->addr); return TRUE; case INDIRECT_Y: @@ -360,9 +366,9 @@ static BOOL getValue(machine_6502 *machine, AddrMode adm, Pointer *pointer){ pointer->value = popByte(machine); return TRUE; case INDIRECT_X: - zp = popByte(machine); + zp = popByte(machine) + machine->regX; pointer->addr = memReadByte(machine,zp) + - (memReadByte(machine,zp+1)<<8) + machine->regX; + (memReadByte(machine,zp+1)<<8); pointer->value = memReadByte(machine, pointer->addr); return TRUE; case INDIRECT_Y: @@ -408,6 +414,64 @@ static BOOL getValue(machine_6502 *machine, AddrMode adm, Pointer *pointer){ } +static void dismem(machine_6502 *machine, AddrMode adm, char *output){ + Bit8 zp; + Bit16 n; + switch(adm){ + case SINGLE: + output = ""; + break; + case IMMEDIATE_LESS: + case IMMEDIATE_GREAT: + case IMMEDIATE_VALUE: + n = popByte(machine); + sprintf(output,"#$%x",n); + break; + case INDIRECT_X: + zp = popByte(machine); + n = memReadByte(machine,zp) + + (memReadByte(machine,zp+1)<<8); + sprintf(output,"($%x,x)",n); + break; + case INDIRECT_Y: + zp = popByte(machine); + n = memReadByte(machine,zp) + + (memReadByte(machine,zp+1)<<8); + sprintf(output,"($%x),y",n); + break; + case ABS_OR_BRANCH: + case ZERO: + n = popByte(machine); + sprintf(output,"$%x",n); + break; + case ZERO_X: + n = popByte(machine); + sprintf(output,"$%x,x",n); + break; + case ZERO_Y: + n = popByte(machine); + sprintf(output,"$%x,y",n); + break; + case ABS_VALUE: + n = popWord(machine); + sprintf(output,"$%x",n); + break; + case ABS_LABEL_X: + case ABS_X: + n = popWord(machine); + sprintf(output,"$%x,x",n); + break; + case ABS_LABEL_Y: + case ABS_Y: + n = popWord(machine); + sprintf(output,"$%x,x",n); + break; + case DCB_PARAM: + output = ""; + break; + } +} + /* manZeroNeg - Manage the negative and zero flags */ static void manZeroNeg(machine_6502 *machine, Bit8 value){ machine->regP = setBit(machine->regP, ZERO_FL, (value == 0)); @@ -867,7 +931,7 @@ static void jmpSBC(machine_6502 *machine, AddrMode adm){ Bit8 ar = nibble(machine->regA, RIGHT); Bit8 br = nibble(ptr.value, RIGHT); Bit8 al = nibble(machine->regA, LEFT); - Bit8 bl = nibble(machine->regA, LEFT); + Bit8 bl = nibble(ptr.value, LEFT); tmp = 0xf + ar - br + c; if ( tmp < 0x10){ @@ -1260,15 +1324,24 @@ static BOOL ishexdigit(char c){ } } +/* isCmdChar() - Is this a valid character for a command. All of the + command are alpha except for the entry point code that is "*=" */ +static BOOL isCmdChar(char c){ + return (isalpha(c) || c == '*' || c == '='); +} + + /* command() - parse a command from the source code. We pass along a machine so the opcode can be validated. */ static BOOL command(machine_6502 *machine, char **s, char **cmd){ int i = 0; skipSpace(s); - for(;isalpha(**s) && i < MAX_CMD_LEN; (*s)++) + for(;isCmdChar(**s) && i < MAX_CMD_LEN; (*s)++) (*cmd)[i++] = **s; if (i == 0) return TRUE; /* Could be a blank line. */ + else if (strcmp(*cmd,"*=") == 0) + return TRUE; /* This is an entry point. */ else return isCommand(machine,*cmd); } @@ -1619,7 +1692,7 @@ static AsmLine *parseAssembly(machine_6502 *machine, BOOL *codeOk, const char *c } /* fileToBuffer() - Allocates a buffer and loads all of the file into memory. */ -static char *fileToBuffer(char *filename){ +static char *fileToBuffer(const char *filename){ const int defaultSize = 1024; FILE *ifp; int c; @@ -1675,7 +1748,7 @@ static void reset(machine_6502 *machine){ machine->regX = 0; machine->regY = 0; machine->regP = setBit(machine->regP, FUTURE_FL, 1); - machine->regPC = 0x600; + machine->defaultCodePC = machine->regPC = PROG_START; machine->regSP = STACK_TOP; machine->runForever = FALSE; machine->labelPtr = 0; @@ -1696,24 +1769,25 @@ void hexDump(machine_6502 *machine, Bit16 start, Bit16 numbytes, FILE *output){ fprintf(output,"%s\n",(i&1)?"--":""); } -void save_program(machine_6502 *machine, char *filename){ - FILE *ofp; - Bit16 pc = 0x600; - Bit16 end = pc + machine->codeLen; - Bit16 n; - ofp = fopen(filename, "w"); - if (ofp == NULL) - eprintf("Could not open file."); +/* XXX */ +/* void save_program(machine_6502 *machine, char *filename){ */ +/* FILE *ofp; */ +/* Bit16 pc = PROG_START; */ +/* Bit16 end = pc + machine->codeLen; */ +/* Bit16 n; */ +/* ofp = fopen(filename, "w"); */ +/* if (ofp == NULL) */ +/* eprintf("Could not open file."); */ - fprintf(ofp,"Bit8 prog[%d] =\n{",machine->codeLen); - n = 1; - while(pc < end) - fprintf(ofp,"0x%.2x,%s",machine->memory[pc++],n++%10?" ":"\n"); - fseek(ofp,-2,SEEK_CUR); - fprintf(ofp,"};\n"); +/* fprintf(ofp,"Bit8 prog[%d] =\n{",machine->codeLen); */ +/* n = 1; */ +/* while(pc < end) */ +/* fprintf(ofp,"0x%.2x,%s",machine->memory[pc++],n++%10?" ":"\n"); */ +/* fseek(ofp,-2,SEEK_CUR); */ +/* fprintf(ofp,"};\n"); */ - fclose(ofp); -} +/* fclose(ofp); */ +/* } */ static BOOL translate(Opcodes *op,Param *param, machine_6502 *machine){ switch(param->type){ @@ -1738,7 +1812,7 @@ static BOOL translate(Opcodes *op,Param *param, machine_6502 *machine){ case IMMEDIATE_GREAT: if (op->Imm) { pushByte(machine, op->Imm); - pushByte(machine, param->lbladdr / 0xFF); + pushByte(machine, param->lbladdr >> 8); break; } else { @@ -1823,7 +1897,7 @@ static BOOL translate(Opcodes *op,Param *param, machine_6502 *machine){ else { if (op->BRA) { pushByte(machine, op->BRA); - if (param->lbladdr < (machine->codeLen + 0x600)) + if (param->lbladdr < (machine->codeLen + PROG_START)) pushByte(machine, (0xff - (machine->codeLen-param->lbladdr)) & 0xff); else @@ -1889,8 +1963,10 @@ static BOOL compileLine(AsmLine *asmline, void *args){ machine_6502 *machine; machine = args; if (isBlank(asmline->command)) return TRUE; - - if (strcmp("DCB",asmline->command) == 0){ + if (strcmp("*=",asmline->command) == 0){ + machine->defaultCodePC = asmline->param->value[0]; + } + else if (strcmp("DCB",asmline->command) == 0){ int i; for(i = 0; i < asmline->param->vp; i++) pushByte(machine, asmline->param->value[i]); @@ -1955,7 +2031,7 @@ static BOOL compileCode(machine_6502 *machine, const char *code){ AsmLine *asmlist; reset(machine); - machine->regPC = 0x600; + machine->defaultCodePC = machine->regPC = PROG_START; asmlist = parseAssembly(machine, &codeOk, code); if(codeOk){ @@ -1966,11 +2042,15 @@ static BOOL compileCode(machine_6502 *machine, const char *code){ linkLabels(asmlist); /* Second pass: translate the instructions */ machine->codeLen = 0; + /* Link label call push_byte which increments defaultCodePC. + We need to reset it so the compiled code goes in the + correct spot. */ + machine->defaultCodePC = PROG_START; if (!apply(asmlist, compileLine, machine)) return FALSE; - if (machine->codeLen > 0 ){ - machine->memory[0x600+machine->codeLen] = 0x00; + if (machine->defaultCodePC > PROG_START ){ + machine->memory[machine->defaultCodePC] = 0x00; codeOk = TRUE; } else{ @@ -2011,8 +2091,7 @@ static void execute(machine_6502 *machine){ fprintf(stderr,"Invalid opcode!\n"); } if( (machine->regPC == 0) || - (!machine->codeRunning) || - (machine->regPC > (machine->codeLen+0x600)) ) { + (!machine->codeRunning) ) { machine->codeRunning = FALSE; } } @@ -2060,13 +2139,37 @@ void trace(machine_6502 *machine, FILE *output){ } fprintf(output,"STACK:"); hexDump(machine,(STACK_TOP - stacksz) + 1, stacksz, output); - fprintf(output,"\n================================================================================\n"); } - +void disassemble(machine_6502 *machine, FILE *output){ + /* Read the opcode + increment the program counter + print the opcode + loop until end of program. */ + AddrMode adm; + Bit16 addr; + Bit8 opcode; + int opidx; + char *mem; + int i; + Bit16 opc = machine->regPC; + mem = calloc(20,sizeof(char)); + machine->regPC = PROG_START; + do{ + addr = machine->regPC; + opcode = popByte(machine); + opidx = opIndex(machine,opcode,&adm); + for (i = 0; i < 20; i++) mem[i] = '\0'; + dismem(machine, adm, mem); + fprintf(output,"%x\t%s\t%s\n", + addr,machine->opcodes[opidx].name,mem); + }while((machine->regPC - PROG_START) < machine->codeLen); /*XXX - may need to change since defaultCodePC */ + free(mem); + machine->regPC = opc; +} -void eval_file(machine_6502 *machine, char *filename, Plotter plot, void *plotterState){ +void eval_file(machine_6502 *machine, const char *filename, Plotter plot, void *plotterState){ char *code = NULL; machine->plot = plot; @@ -2080,7 +2183,7 @@ void eval_file(machine_6502 *machine, char *filename, Plotter plot, void *plotte free(code); - machine->regPC = 0x600; + machine->defaultCodePC = machine->regPC = PROG_START; machine->codeRunning = TRUE; do{ sleep(0); /* XXX */ @@ -2088,12 +2191,10 @@ void eval_file(machine_6502 *machine, char *filename, Plotter plot, void *plotte trace(machine); #endif execute(machine); - if (!machine->codeRunning) - break; - }while((machine->regPC - 0x600) < machine->codeLen); + }while(machine->codeRunning); } -void start_eval_file(machine_6502 *machine, char *filename, Plotter plot, void *plotterState){ +void start_eval_file(machine_6502 *machine, const char *filename, Plotter plot, void *plotterState){ char *code = NULL; reset(machine); @@ -2108,36 +2209,52 @@ void start_eval_file(machine_6502 *machine, char *filename, Plotter plot, void * free(code); - machine->regPC = 0x600; + machine->defaultCodePC = machine->regPC = PROG_START; machine->codeRunning = TRUE; execute(machine); } -void start_eval_binary(machine_6502 *machine, Bit8 *program, - unsigned int proglen, +void start_eval_string(machine_6502 *machine, const char *code, Plotter plot, void *plotterState){ - unsigned int pc, n; reset(machine); + machine->plot = plot; machine->plotterState = plotterState; - machine->regPC = 0x600; - pc = machine->regPC; - machine->codeLen = proglen; - n = 0; - while (n < proglen){ - machine->memory[pc++] = program[n++]; + if (! compileCode(machine, code) ){ + fprintf(stderr,"Could not compile code.\n"); } + + machine->defaultCodePC = machine->regPC = PROG_START; machine->codeRunning = TRUE; execute(machine); } +/* void start_eval_binary(machine_6502 *machine, Bit8 *program, */ +/* unsigned int proglen, */ +/* Plotter plot, void *plotterState){ */ +/* unsigned int pc, n; */ +/* reset(machine); */ +/* machine->plot = plot; */ +/* machine->plotterState = plotterState; */ + +/* machine->regPC = PROG_START; */ +/* pc = machine->regPC; */ +/* machine->codeLen = proglen; */ +/* n = 0; */ +/* while (n < proglen){ */ +/* machine->memory[pc++] = program[n++]; */ +/* } */ +/* machine->codeRunning = TRUE; */ +/* execute(machine); */ +/* } */ + void next_eval(machine_6502 *machine, int insno){ int i = 0; for (i = 1; i < insno; i++){ - if (machine->codeRunning){/* && ((machine->regPC - 0x600) < machine->codeLen))*/ + if (machine->codeRunning){ #if 0 - trace(machine); + trace(machine, stdout); #endif execute(machine); }