/[VRac]/M6502/M6502.xs
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Diff of /M6502/M6502.xs

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 86 by dpavlin, Wed Aug 1 22:25:37 2007 UTC revision 195 by dpavlin, Sun Apr 13 00:32:39 2008 UTC
# Line 7  Line 7 
7  #include "M6502.h"  #include "M6502.h"
8  #include "config.h"  #include "config.h"
9    
10  M6502 *R;  M6502 *R = NULL;
11    int debug = 0;
12    
13  void  // same as memory size
14  run (void) {  #define CACHE_SIZE 0xffff
15          debugf(("M6502::run"));  byte opCache[CACHE_SIZE];
16          run_forever();  
17    #define CALLBACK_READ_SKIP      0x00
18    #define CALLBACK_READ_ONCE      0x01
19    #define CALLBACK_READ_ALWAYS    0x02
20    #define CALLBACK_READ_MASK      0x0f
21    #define CALLBACK_WRITE_SKIP     0x00
22    #define CALLBACK_WRITE_ONCE     0x10
23    #define CALLBACK_WRITE_ALWAYS   0x20
24    #define CALLBACK_WRITE_MASK     0xf0
25    byte perlCallBack[CACHE_SIZE];
26    
27    void update_C_R(void) {
28            R->A = SvIV( get_sv("M6502::A", FALSE) );
29            R->P = SvIV( get_sv("M6502::P", FALSE) );
30            R->X = SvIV( get_sv("M6502::X", FALSE) );
31            R->Y = SvIV( get_sv("M6502::Y", FALSE) );
32            R->S = SvIV( get_sv("M6502::S", FALSE) );
33            R->PC.W = SvIV( get_sv("M6502::PC", FALSE) );
34            R->IPeriod = SvIV( get_sv("M6502::IPeriod", FALSE) );
35            R->IRequest = SvIV( get_sv("M6502::IRequest", FALSE) );
36            R->IAutoReset = SvIV( get_sv("M6502::IAutoReset", FALSE) );
37            R->TrapBadOps = SvIV( get_sv("M6502::TrapBadOps", FALSE) );
38            R->Trap = SvIV( get_sv("M6502::Trap", FALSE) );
39            R->Trace = SvIV( get_sv("M6502::Trace", FALSE) );
40            debugf(("pull_R finished"));
41            dump_R;
42    }
43    
44    void update_perl_R(void) {
45            debugf(("update_perl_R"));
46            dSP;
47            ENTER;
48            SAVETMPS;
49            PUSHMARK(SP);
50            XPUSHs( sv_2mortal( newSViv( R->A ) ) );
51            XPUSHs( sv_2mortal( newSViv( R->P ) ) );
52            XPUSHs( sv_2mortal( newSViv( R->X ) ) );
53            XPUSHs( sv_2mortal( newSViv( R->Y ) ) );
54            XPUSHs( sv_2mortal( newSViv( R->S ) ) );
55            XPUSHs( sv_2mortal( newSViv( R->PC.W ) ) );
56            XPUSHs( sv_2mortal( newSViv( R->IPeriod ) ) );
57            XPUSHs( sv_2mortal( newSViv( R->ICount ) ) );
58            XPUSHs( sv_2mortal( newSViv( R->IRequest ) ) );
59            XPUSHs( sv_2mortal( newSViv( R->IAutoReset ) ) );
60            XPUSHs( sv_2mortal( newSViv( R->TrapBadOps ) ) );
61            XPUSHs( sv_2mortal( newSViv( R->Trap ) ) );
62            XPUSHs( sv_2mortal( newSViv( R->Trace ) ) );
63            PUTBACK;
64            call_pv("M6502::_update_perl_R", G_DISCARD );
65            debugf(("_update_perl_R returned to C"));
66            dump_R;
67            FREETMPS;
68            LEAVE;
69    }
70    
71    /** Debug6502() **********************************************/
72    
73    byte Debug6502(M6502 *R) {
74            dump_R;
75            return 1; // continue emulation
76    }
77    
78    /** Rd6502()/Wr6502/Op6502() *********************************/
79    /** These functions are called when access to RAM occurs.   **/
80    /** They allow to control memory access. Op6502 is the same **/
81    /** as Rd6502, but used to read *opcodes* only, when many   **/
82    /** checks can be skipped to make it fast. It is only       **/
83    /** required if there is a #define FAST_RDOP.               **/
84    /************************************ TO BE WRITTEN BY USER **/
85    
86    byte mem(register word Addr) {
87    
88            if ( perlCallBack[Addr] & CALLBACK_READ_MASK == CALLBACK_READ_SKIP )
89                    return opCache[Addr];
90            if ( perlCallBack[Addr] & CALLBACK_READ_MASK == CALLBACK_READ_ONCE )
91                    perlCallBack[Addr] = perlCallBack[Addr] & CALLBACK_WRITE_MASK | CALLBACK_READ_SKIP;
92    
93            byte byte;
94            int count;
95            debugf(("mem(%04x)", Addr));
96            dSP;
97            ENTER;
98            SAVETMPS;
99            PUSHMARK(SP);
100            XPUSHs( sv_2mortal( newSViv( Addr ) ) );
101            PUTBACK;
102            count = call_pv("M6502::_read", G_ARRAY | G_EVAL );
103            debugf(("got %d values", count));
104            SPAGAIN;
105            if (SvTRUE(ERRSV)) {
106                    printf("ERROR: %s", SvPV_nolen( ERRSV ) );
107                    exit(1);
108            }
109            if ( count != 1 ) {
110                    printf("expect 1 return value, got %d", count);
111                    exit(1);
112            }
113            SV *sv;
114            sv = POPs;
115            byte = SvIV(sv);
116            FREETMPS;
117            LEAVE;
118            debugf(("mem(%04x) = %02x", Addr, byte));
119            opCache[Addr] = byte;
120            return byte;
121    }
122    
123    byte Rd6502(register word Addr) {
124            byte Value;
125            Value = mem(Addr);
126            debugf(("Rd6502(%04x) = %02x", Addr, Value));
127            return Value;
128    }
129    
130    void Wr6502(register word Addr,register byte Value) {
131            debugf(("Wr6502(%04x,%02x)", Addr, Value));
132            opCache[Addr] = Value;
133            if ( perlCallBack[Addr] & CALLBACK_WRITE_MASK == CALLBACK_WRITE_SKIP ) return;
134            if ( perlCallBack[Addr] & CALLBACK_WRITE_MASK == CALLBACK_WRITE_ONCE )
135                    perlCallBack[Addr] = perlCallBack[Addr] & CALLBACK_READ_MASK | CALLBACK_WRITE_SKIP;
136            dSP;
137            ENTER;
138            SAVETMPS;
139            PUSHMARK(SP);
140            XPUSHs( sv_2mortal( newSViv( Addr ) ) );
141            XPUSHs( sv_2mortal( newSViv( Value ) ) );
142            PUTBACK;
143            call_pv("M6502::_write", G_DISCARD );
144            FREETMPS;
145            LEAVE;
146    }
147    
148    byte Op6502(register word Addr) {
149            byte Op;
150            Op = mem(Addr);
151            debugf(("Op6502(%04x,%02x) PC:%04x", Addr, Op, R->PC.W));
152            return Op;
153    }
154    
155    /** Loop6502() ***********************************************/
156    /** 6502 emulation calls this function periodically to      **/
157    /** check if the system hardware requires any interrupts.   **/
158    /** This function must return one of following values:      **/
159    /** INT_NONE, INT_IRQ, INT_NMI, or INT_QUIT to exit the     **/
160    /** emulation loop.                                         **/
161    /************************************ TO BE WRITTEN BY USER **/
162    
163    int hw_int = INT_NONE;
164    
165    byte Loop6502(register M6502 *R) {
166            debugf(("Loop6502"));
167            dump_R;
168            return hw_int;
169    }
170    
171    /** Patch6502() **********************************************/
172    /** Emulation calls this function when it encounters an     **/
173    /** unknown opcode. This can be used to patch the code to   **/
174    /** emulate BIOS calls, such as disk and tape access. The   **/
175    /** function should return 1 if the exception was handled,  **/
176    /** or 0 if the opcode was truly illegal.                   **/
177    /************************************ TO BE WRITTEN BY USER **/
178    byte Patch6502(register byte Op,register M6502 *R) {
179            debugf(("Patch6502(%02x)", Op));
180            dump_R;
181            hw_int = INT_QUIT;
182            return 0;
183  }  }
184    
185    /*************************************************************/
186    
187  int  int
188  reset (void) {  reset (void) {
189          debugf(("M6502::reset called"));          debugf(("M6502::reset called"));
# Line 22  reset (void) { Line 191  reset (void) {
191                  debugf(("allocating space for R"));                  debugf(("allocating space for R"));
192                  R = malloc(sizeof(M6502));                  R = malloc(sizeof(M6502));
193                  if (!R) {                  if (!R) {
194                          printf("can't alloc %d bytes for M6502", sizeof(M6502));                          PerlIO_stdoutf("can't alloc %d bytes for M6502", sizeof(M6502));
195                          exit(1);                          exit(1);
196                  }                  }
197                    memset( opCache, 0, CACHE_SIZE );
198                    memset( perlCallBack, CALLBACK_READ_ALWAYS | CALLBACK_WRITE_ALWAYS, CACHE_SIZE );
199          }          }
200          Reset6502(R);          Reset6502(R);
201          debugf(("Reset6502 over"));          debugf(("Reset6502 over"));
202          push_R();          update_perl_R();
203          dump_R;          dump_R;
204          return 1;          return 1;
205  }  }
206    
207    int exec(int cycles) {
208            int left;
209            debugf(("exec for %d cycles", cycles));
210    
211            if (!R) reset();
212    
213            update_C_R();
214            left = Exec6502(R, cycles);
215            update_perl_R();
216            debugf(("end of %d cycles CPU run\n", cycles));
217            return left;
218    }
219    
220    int set_debug(int state) {
221            debug = state;
222            return debug;
223    }
224    
225    int get_debug(void) {
226            return debug;
227    }
228    
229    /* FIXME somehow check if Addr will fit in int on current platform */
230    void set_read_callback(int Addr) {
231            perlCallBack[Addr] == perlCallBack[Addr] & CALLBACK_WRITE_MASK | CALLBACK_READ_ALWAYS;
232    }
233    
234    void set_write_callback(int Addr) {
235            perlCallBack[Addr] == perlCallBack[Addr] & CALLBACK_READ_MASK | CALLBACK_WRITE_ALWAYS;
236    }
237    
238    /* we fake here, since we will need to call perl at least once to get initial value... */
239    int disable_all_callbacks(void) {
240            memset( perlCallBack, CALLBACK_READ_ONCE | CALLBACK_WRITE_ONCE, CACHE_SIZE );
241            return perlCallBack[0];
242    }
243    
244    
245  MODULE = M6502          PACKAGE = M6502  MODULE = M6502          PACKAGE = M6502
246    
247  PROTOTYPES: DISABLE  PROTOTYPES: DISABLE
248    
249  void  int
250  run()  set_debug(int state)
251    
252    int
253    get_debug()
254    
255  int  int
256  reset()  reset()
257    
258    void
259    update_C_R()
260    
261    void
262    update_perl_R()
263    
264    int
265    exec(int cycles)
266    
267    void
268    set_read_callback(int Addr)
269    
270    void
271    set_write_callback(int Addr)
272    
273    int
274    disable_all_callbacks()
275    

Legend:
Removed from v.86  
changed lines
  Added in v.195

  ViewVC Help
Powered by ViewVC 1.1.26