--- M6502/M6502.xs 2007/08/02 11:08:10 87 +++ M6502/M6502.xs 2007/08/02 12:01:09 89 @@ -7,7 +7,7 @@ #include "M6502.h" #include "config.h" -M6502 *R; +M6502 *R = NULL; int debug = 0; void update_C_R(void) { @@ -54,6 +54,112 @@ LEAVE; } +/** Debug6502() **********************************************/ + +byte Debug6502(M6502 *R) { + dump_R; + return 1; // continue emulation +} + +/** Rd6502()/Wr6502/Op6502() *********************************/ +/** These functions are called when access to RAM occurs. **/ +/** They allow to control memory access. Op6502 is the same **/ +/** as Rd6502, but used to read *opcodes* only, when many **/ +/** checks can be skipped to make it fast. It is only **/ +/** required if there is a #define FAST_RDOP. **/ +/************************************ TO BE WRITTEN BY USER **/ + +byte mem(word Addr) { + byte byte; + int count; + debugf(("mem(%04x)", Addr)); + dSP; + ENTER; + SAVETMPS; + PUSHMARK(SP); + XPUSHs( sv_2mortal( newSViv( Addr ) ) ); + PUTBACK; + count = call_pv("M6502::_read", G_ARRAY | G_EVAL ); + debugf(("got %d values", count)); + SPAGAIN; + if (SvTRUE(ERRSV)) { + printf("ERROR: %s", SvPV_nolen( ERRSV ) ); + exit(1); + } + if ( count != 1 ) { + printf("expect 1 return value, got %d", count); + exit(1); + } + SV *sv; + sv = POPs; + byte = SvIV(sv); + FREETMPS; + LEAVE; + debugf(("mem(%04x) = %02x", Addr, byte)); + return byte; +} + +byte Rd6502(register word Addr) { + byte Value; + Value = mem(Addr); +// Value = 0x42; + debugf(("Rd6502(%04x) = %02x", Addr, Value)); + return Value; +} + +void Wr6502(register word Addr,register byte Value) { + debugf(("Wr6502(%04x,%02x)", Addr, Value)); + dSP; + ENTER; + SAVETMPS; + PUSHMARK(SP); + XPUSHs( sv_2mortal( newSViv( Addr ) ) ); + XPUSHs( sv_2mortal( newSViv( Value ) ) ); + PUTBACK; + call_pv("M6502::_write", G_DISCARD ); + FREETMPS; + LEAVE; +} + +byte Op6502(register word Addr) { + byte Op; + Op = mem(Addr); + debugf(("Op6502(%04x,%02x) PC:%04x", Addr, Op, R->PC.W)); + return Op; +} + +/** Loop6502() ***********************************************/ +/** 6502 emulation calls this function periodically to **/ +/** check if the system hardware requires any interrupts. **/ +/** This function must return one of following values: **/ +/** INT_NONE, INT_IRQ, INT_NMI, or INT_QUIT to exit the **/ +/** emulation loop. **/ +/************************************ TO BE WRITTEN BY USER **/ + +int hw_int = INT_NONE; + +byte Loop6502(register M6502 *R) { + debugf(("Loop6502")); + dump_R; + return hw_int; +} + +/** Patch6502() **********************************************/ +/** Emulation calls this function when it encounters an **/ +/** unknown opcode. This can be used to patch the code to **/ +/** emulate BIOS calls, such as disk and tape access. The **/ +/** function should return 1 if the exception was handled, **/ +/** or 0 if the opcode was truly illegal. **/ +/************************************ TO BE WRITTEN BY USER **/ +byte Patch6502(register byte Op,register M6502 *R) { + debugf(("Patch6502(%02x)", Op)); + dump_R; + hw_int = INT_QUIT; + return 0; +} + +/*************************************************************/ + int reset (void) { debugf(("M6502::reset called")); @@ -61,7 +167,7 @@ debugf(("allocating space for R")); R = malloc(sizeof(M6502)); if (!R) { - PerlIO_stderrf("can't alloc %d bytes for M6502", sizeof(M6502)); + PerlIO_stdoutf("can't alloc %d bytes for M6502", sizeof(M6502)); exit(1); } } @@ -72,6 +178,17 @@ return 1; } +void exec(int cycles) { + debugf(("exec for %d cycles", cycles)); + + if (!R) reset(); + + update_C_R(); + Exec6502(R, cycles); + update_perl_R(); + debugf(("end of %d cycles CPU run\n", cycles)); +} + int set_debug(int state) { debug = state; return debug;