00001 #include "openem.h"
00002 #include "cpu/debug/cpudbg.h"
00003 #include "cpu/M65C02/M65C02.h"
00004 #include "arch/nes/ppu.h"
00005 #include "arch/nes/mmc.h"
00006 #include "arch/nes/joypad.h"
00007 #include "arch/nes/nes.h"
00008 #include <stdlib.h>
00009 #include <stdio.h>
00010 #include <string.h>
00011
00012 void NES::pass_message(OE_MESSAGE *mes)
00013 {
00014 }
00015
00016 void NES::dumpdebug(void)
00017 {
00018
00019 CPU_DEBUG_LIST *dlist = &m6502.dbg.list;
00020 char *tr;
00021 dlist->seek_first();
00022 if (dlist->getcur() == NULL) return;
00023 printf("\n");
00024 for (;;) {
00025 tr = m6502.debug_str((CPU_M65C02_DEBUG_STATE *)dlist->getcur()->cstate);
00026 printf("\n%s",tr);
00027 free(tr);
00028 dlist->seek_next();
00029 if (dlist->getcur() == dlist->getlast()) { break; }
00030 }
00031 dlist->clear();
00032 }
00033
00034 NES *curnes;
00035
00036 void writereg(void *ref, dword addr, byte data)
00037 {
00038 curnes->ppu.writereg(addr,data);
00039 }
00040
00041 byte readreg(void *ref, dword addr)
00042 {
00043 return curnes->ppu.readreg(addr);
00044 }
00045
00046
00047 void write8(void *ref, dword addr, byte data)
00048 {
00049 }
00050
00051 byte read8(void *ref, dword addr)
00052 {
00053 return 0;
00054 }
00055
00056
00057
00058 void writeodd(void *ref, dword addr, byte data)
00059 {
00060 if (addr == 0x4014)
00061 curnes->ppu.writereg(addr,data);
00062 if (addr == 0x4016)
00063 curnes->jpad1.writereg(data);
00064 if (addr == 0x4017)
00065 curnes->jpad2.writereg(data);
00066 }
00067
00068 byte readodd(void *ref, dword addr)
00069 {
00070 if (addr == 0x4016)
00071 return curnes->jpad1.readreg();
00072 if (addr == 0x4017)
00073 return curnes->jpad2.readreg();
00074 return 0;
00075 }
00076
00077
00078 void writerom(void *ref, dword addr, byte data)
00079 {
00080 }
00081
00082 void NES::reset(void)
00083 {
00084 m6502.reset();
00085 }
00086
00087
00088 void NES::doframe(void)
00089 {
00090 curnes = this;
00091
00092 ppu.start_frame();
00093 uint32 i;
00094
00095 for (i = 0; i < 262; i++) {
00096 ppu.set_scanline(i);
00097 m6502.NMI = ppu.NMI;
00098 m6502.cycle(114);
00099 ppu.draw_scanline(i);
00100 }
00101
00102 ppu.end_frame();
00103 }
00104
00105 int NES::load_rom(char *fill)
00106 {
00107 FILE *fil = 0;
00108 char *yo;
00109 int er = 0;
00110 byte *curbank;
00111 byte mnum;
00112
00113 yo = (char *)malloc(100);
00114
00115 fil = fopen(fill,"rb");
00116 if (!fil) { printf("nofileopen"); er = -1; goto efunc; }
00117
00118
00119 fread(yo,1,4,fil);
00120 if ((*yo != 'N') && (*(yo+1) != 'E') && (*(yo+2) != 'S') && (*(yo+3) != 0x1A)) { printf("wrongfiletype"); er = -2; goto efunc; }
00121
00122
00123 fread(yo,1,2,fil);
00124 numrombanks = *yo;
00125 numvrombanks = *(yo+1);
00126
00127 romb = (byte *)malloc(0x4000 * numrombanks);
00128 vromb = (byte *)malloc(0x2000 * numvrombanks);
00129
00130
00131 fread(yo,1,2,fil);
00132 if (*yo & 1) { ppu.mirrormode = MIRROR_VERTICAL; } else { ppu.mirrormode = MIRROR_HORIZONTAL; }
00133 if (*yo & 2) { sram = true; } else { sram = false; }
00134 if (*yo & 8) { ppu.mirrormode = MIRROR_FOURWAY; }
00135
00136 mnum = (((*yo) >> 4) << 4) | (*(yo+1));
00137
00138
00139 fread(yo,1,8,fil);
00140
00141
00142 curbank = romb;
00143 int i;
00144 for (i = 0; i < numrombanks; i++) {
00145 fread(curbank,1,0x4000,fil);
00146 curbank += 0x4000;
00147 }
00148
00149
00150 curbank = vromb;
00151 for (i = 0; i < numvrombanks; i++) {
00152 fread(curbank,1,0x2000,fil);
00153 curbank += 0x2000;
00154 }
00155
00156
00157 curbank = romb;
00158 if (numrombanks == 1) {
00159
00160
00161 memcpy((mem+0x8000),romb,0x4000);
00162 memcpy((mem+0xC000),romb,0x4000);
00163 }
00164 else {
00165
00166
00167 memcpy((mem+0x8000),romb,0x4000);
00168 memcpy((mem+0xC000),(romb+0x4000),0x4000);
00169 }
00170
00171 if (numvrombanks == 1) {
00172 memcpy(ppu.vram,vromb,0x2000);
00173 }
00174
00175 ppu.setmapper();
00176
00177 efunc:
00178 if (fil) fclose(fil);
00179 free(yo);
00180 return er;
00181 }
00182
00183 void NES::init(void)
00184 {
00185
00186 m6502.init();
00187 m6502.set_mode(M65C02_MODE_2A03, false);
00188
00189
00190 jpad1.set_type(0, NESJTYPE_REGULAR, 1);
00191 jpad2.set_type(1, NESJTYPE_REGULAR, 0);
00192
00193 mem = (byte *)malloc(65536);
00194 ppu.mem = mem;
00195 ppu.init();
00196 ppu.mycpu = &m6502;
00197
00198 curnes = this;
00199 romloaded = false;
00200 vromyes = false;
00201
00202
00203 m6502.mem.create_pagetable(256,256);
00204 dword i;
00205
00206
00207 oe_pagetable_ptrtable *calls = m6502.mem.calls;
00208 OE_PT_FLAG *flags = m6502.mem.flags;
00209 byte *mptr = mem;
00210 byte **e = (byte **)m6502.mem.mem;
00211
00212 for (i = 0; i < 0x08; i++) {
00213 *flags = *(flags+8) = *(flags+16) = *(flags+24) = (OE_PT_FLAG_READABLE | OE_PT_FLAG_WRITEABLE);
00214 *e = *(e+8) = *(e+16) = *(e+24) = mptr;
00215 calls->rm8 = (calls+8)->rm8 = (calls+16)->rm8 = (calls+24)->rm8 = &read8;
00216 calls->wm8 = (calls+8)->wm8 = (calls+16)->wm8 = (calls+24)->wm8 = &write8;
00217 mptr+=256;
00218 e++;
00219 flags++;
00220 calls++;
00221 }
00222
00223
00224 flags = (m6502.mem.flags+0x20);
00225 mptr = (mem+(256*0x20));
00226 e = (byte **)(m6502.mem.mem + 0x20);
00227 calls = (m6502.mem.calls+0x20);
00228
00229 for (i = 0x20; i < 0x40; i++) {
00230 *flags = 0;
00231 *e = mptr;
00232 calls->rm8 = &readreg;
00233 calls->wm8 = &writereg;
00234 mptr+=256;
00235 e++;
00236 flags++;
00237 calls++;
00238 }
00239
00240
00241 for (i = 0x40; i< 0x60; i++) {
00242 *flags = 0;
00243 *e = mptr;
00244 calls->rm8 = &readodd;
00245 calls->wm8 = &writeodd;
00246 mptr+=256;
00247 e++;
00248 flags++;
00249 calls++;
00250 }
00251
00252
00253 for (i = 0x60; i< 0x80; i++) {
00254 *flags = OE_PT_FLAG_READABLE | OE_PT_FLAG_WRITEABLE;
00255 *e = mptr;
00256 calls->rm8 = &read8;
00257 calls->wm8 = &write8;
00258 mptr+=256;
00259 e++;
00260 flags++;
00261 calls++;
00262 }
00263
00264
00265 for (i = 0x80; i< 0x100; i++) {
00266 *flags = OE_PT_FLAG_READABLE;
00267 *e = mptr;
00268 calls->rm8 = &read8;
00269 calls->wm8 = &writerom;
00270 mptr+=256;
00271 e++;
00272 flags++;
00273 calls++;
00274 }
00275
00276
00277 mmc.myppu = &ppu;
00278
00279
00280
00281
00282 }
00283
00284 void NES::uninit(void)
00285 {
00286 free(mem);
00287 if (vromyes) free(vromb);
00288 if (romloaded) free(romb);
00289 ppu.uninit();
00290 }