mirror of
https://github.com/bsnes-emu/bsnes.git
synced 2025-09-21 00:31:33 +02:00
Compare commits
15 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
5fc86eae6d | ||
|
927c97eb06 | ||
|
cf09d41669 | ||
|
724747ac9e | ||
|
e1e275eb38 | ||
|
e30fcade43 | ||
|
42dbf73d18 | ||
|
2a90e12999 | ||
|
d129b72ced | ||
|
bc0b86891a | ||
|
52443936e6 | ||
|
6694a1c986 | ||
|
7ffaeb2ac1 | ||
|
67e6a6e742 | ||
|
9a3650c6ab |
@@ -1,7 +1,7 @@
|
||||
include nall/Makefile
|
||||
snes := snes
|
||||
gameboy := gameboy
|
||||
profile := accuracy
|
||||
profile := compatibility
|
||||
ui := ui
|
||||
|
||||
# debugger
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -1,5 +1,6 @@
|
||||
class Interface {
|
||||
public:
|
||||
virtual void lcd_scanline() {}
|
||||
virtual void joyp_write(bool p15, bool p14) {}
|
||||
|
||||
virtual void video_refresh(const uint8_t *data) {}
|
||||
|
@@ -75,6 +75,7 @@ void LCD::render() {
|
||||
|
||||
uint8_t *output = screen + status.ly * 160;
|
||||
for(unsigned n = 0; n < 160; n++) output[n] = (3 - line[n]) * 0x55;
|
||||
system.interface->lcd_scanline();
|
||||
}
|
||||
|
||||
uint16 LCD::read_tile(bool select, unsigned x, unsigned y) {
|
||||
|
@@ -42,20 +42,21 @@ struct directory {
|
||||
if(wcscmp(data.cFileName, L".") && wcscmp(data.cFileName, L"..")) {
|
||||
if(data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
|
||||
string name = (const char*)utf8_t(data.cFileName);
|
||||
if(wildcard(name, pattern)) list.append(string(name, "/"));
|
||||
if(wildcard(name, pattern)) list.append(name);
|
||||
}
|
||||
}
|
||||
while(FindNextFile(handle, &data) != false) {
|
||||
if(wcscmp(data.cFileName, L".") && wcscmp(data.cFileName, L"..")) {
|
||||
if(data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
|
||||
string name = (const char*)utf8_t(data.cFileName);
|
||||
if(wildcard(name, pattern)) list.append(string(name, "/"));
|
||||
if(wildcard(name, pattern)) list.append(name);
|
||||
}
|
||||
}
|
||||
}
|
||||
FindClose(handle);
|
||||
}
|
||||
if(list.size() > 0) sort(&list[0], list.size());
|
||||
foreach(name, list) name.append("/"); //must append after sorting
|
||||
return list;
|
||||
}
|
||||
|
||||
@@ -109,14 +110,14 @@ struct directory {
|
||||
if(!strcmp(ep->d_name, ".")) continue;
|
||||
if(!strcmp(ep->d_name, "..")) continue;
|
||||
if(ep->d_type & DT_DIR) {
|
||||
if(wildcard(ep->d_name, pattern)) list.append(string(ep->d_name, "/"));
|
||||
if(wildcard(ep->d_name, pattern)) list.append(ep->d_name);
|
||||
}
|
||||
}
|
||||
closedir(dp);
|
||||
}
|
||||
if(list.size() > 0) sort(&list[0], list.size());
|
||||
foreach(name, list) name.append("/"); //must append after sorting
|
||||
return list;
|
||||
|
||||
}
|
||||
|
||||
inline lstring directory::files(const string &pathname, const string &pattern) {
|
||||
|
@@ -1,15 +1,7 @@
|
||||
#ifndef NALL_FILE_HPP
|
||||
#define NALL_FILE_HPP
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#if !defined(_WIN32)
|
||||
#include <unistd.h>
|
||||
#else
|
||||
#include <io.h>
|
||||
#endif
|
||||
|
||||
#include <nall/platform.hpp>
|
||||
#include <nall/stdint.hpp>
|
||||
#include <nall/string.hpp>
|
||||
#include <nall/utf8.hpp>
|
||||
@@ -28,6 +20,7 @@ namespace nall {
|
||||
public:
|
||||
enum class mode : unsigned { read, write, readwrite, writeread };
|
||||
enum class index : unsigned { absolute, relative };
|
||||
enum class time : unsigned { create, modify, access };
|
||||
|
||||
uint8_t read() {
|
||||
if(!fp) return 0xff; //file not open
|
||||
@@ -142,52 +135,60 @@ namespace nall {
|
||||
return file_offset >= file_size;
|
||||
}
|
||||
|
||||
static bool exists(const char *fn) {
|
||||
static bool exists(const char *filename) {
|
||||
#if !defined(_WIN32)
|
||||
FILE *fp = fopen(fn, "rb");
|
||||
struct stat64 data;
|
||||
return stat64(filename, &data) == 0;
|
||||
#else
|
||||
FILE *fp = _wfopen(utf16_t(fn), L"rb");
|
||||
struct __stat64 data;
|
||||
return _wstat64(utf16_t(filename), &data) == 0;
|
||||
#endif
|
||||
if(fp) {
|
||||
fclose(fp);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static unsigned size(const char *fn) {
|
||||
static uintmax_t size(const char *filename) {
|
||||
#if !defined(_WIN32)
|
||||
FILE *fp = fopen(fn, "rb");
|
||||
struct stat64 data;
|
||||
stat64(filename, &data);
|
||||
#else
|
||||
FILE *fp = _wfopen(utf16_t(fn), L"rb");
|
||||
struct __stat64 data;
|
||||
_wstat64(utf16_t(filename), &data);
|
||||
#endif
|
||||
unsigned filesize = 0;
|
||||
if(fp) {
|
||||
fseek(fp, 0, SEEK_END);
|
||||
filesize = ftell(fp);
|
||||
fclose(fp);
|
||||
return S_ISREG(data.st_mode) ? data.st_size : 0u;
|
||||
}
|
||||
|
||||
static time_t timestamp(const char *filename, file::time mode = file::time::create) {
|
||||
#if !defined(_WIN32)
|
||||
struct stat64 data;
|
||||
stat64(filename, &data);
|
||||
#else
|
||||
struct __stat64 data;
|
||||
_wstat64(utf16_t(filename), &data);
|
||||
#endif
|
||||
switch(mode) { default:
|
||||
case file::time::create: return data.st_ctime;
|
||||
case file::time::modify: return data.st_mtime;
|
||||
case file::time::access: return data.st_atime;
|
||||
}
|
||||
return filesize;
|
||||
}
|
||||
|
||||
bool open() {
|
||||
return fp;
|
||||
}
|
||||
|
||||
bool open(const char *fn, mode mode_) {
|
||||
bool open(const char *filename, mode mode_) {
|
||||
if(fp) return false;
|
||||
|
||||
switch(file_mode = mode_) {
|
||||
#if !defined(_WIN32)
|
||||
case mode::read: fp = fopen(fn, "rb"); break;
|
||||
case mode::write: fp = fopen(fn, "wb+"); break; //need read permission for buffering
|
||||
case mode::readwrite: fp = fopen(fn, "rb+"); break;
|
||||
case mode::writeread: fp = fopen(fn, "wb+"); break;
|
||||
case mode::read: fp = fopen(filename, "rb" ); break;
|
||||
case mode::write: fp = fopen(filename, "wb+"); break; //need read permission for buffering
|
||||
case mode::readwrite: fp = fopen(filename, "rb+"); break;
|
||||
case mode::writeread: fp = fopen(filename, "wb+"); break;
|
||||
#else
|
||||
case mode::read: fp = _wfopen(utf16_t(fn), L"rb"); break;
|
||||
case mode::write: fp = _wfopen(utf16_t(fn), L"wb+"); break;
|
||||
case mode::readwrite: fp = _wfopen(utf16_t(fn), L"rb+"); break;
|
||||
case mode::writeread: fp = _wfopen(utf16_t(fn), L"wb+"); break;
|
||||
case mode::read: fp = _wfopen(utf16_t(filename), L"rb" ); break;
|
||||
case mode::write: fp = _wfopen(utf16_t(filename), L"wb+"); break;
|
||||
case mode::readwrite: fp = _wfopen(utf16_t(filename), L"rb+"); break;
|
||||
case mode::writeread: fp = _wfopen(utf16_t(filename), L"wb+"); break;
|
||||
#endif
|
||||
}
|
||||
if(!fp) return false;
|
||||
|
@@ -1,6 +1,12 @@
|
||||
#ifndef NALL_PLATFORM_HPP
|
||||
#define NALL_PLATFORM_HPP
|
||||
|
||||
#if defined(_WIN32)
|
||||
//minimum version needed for _wstat64, etc
|
||||
#undef __MSVCRT_VERSION__
|
||||
#define __MSVCRT_VERSION__ 0x0601
|
||||
#endif
|
||||
|
||||
#include <nall/utf8.hpp>
|
||||
|
||||
//=========================
|
||||
@@ -18,16 +24,19 @@
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#if defined(_WIN32)
|
||||
#include <io.h>
|
||||
#include <direct.h>
|
||||
#include <shlobj.h>
|
||||
#include <wchar.h>
|
||||
#undef interface
|
||||
#define dllexport __declspec(dllexport)
|
||||
#else
|
||||
#include <unistd.h>
|
||||
#include <pwd.h>
|
||||
#include <sys/stat.h>
|
||||
#define dllexport
|
||||
#endif
|
||||
|
||||
@@ -53,11 +62,11 @@
|
||||
#if defined(_WIN32)
|
||||
#define getcwd _getcwd
|
||||
#define ftruncate _chsize
|
||||
#define putenv _putenv
|
||||
#define mkdir(n, m) _wmkdir(nall::utf16_t(n))
|
||||
#define putenv _putenv
|
||||
#define rmdir _rmdir
|
||||
#define vsnprintf _vsnprintf
|
||||
#define usleep(n) Sleep(n / 1000)
|
||||
#define vsnprintf _vsnprintf
|
||||
#endif
|
||||
|
||||
//================
|
||||
|
@@ -125,7 +125,7 @@ SNESCartridge::SNESCartridge(const uint8_t *data, unsigned size) {
|
||||
if(type == TypeGameBoy) {
|
||||
xml << "<cartridge rtc='" << gameboy_has_rtc(data, size) << "'>\n";
|
||||
if(gameboy_ram_size(data, size) > 0) {
|
||||
xml << " <ram size='" << hex(gameboy_ram_size(data, size)) << "'/>\n";
|
||||
xml << " <ram size='0x" << hex(gameboy_ram_size(data, size)) << "'/>\n";
|
||||
}
|
||||
xml << "</cartridge>\n";
|
||||
xmlMemoryMap = xml.transform("'", "\"");
|
||||
@@ -158,6 +158,17 @@ SNESCartridge::SNESCartridge(const uint8_t *data, unsigned size) {
|
||||
xml << " <map address='00-3f:6000-7fff'/>\n";
|
||||
xml << " <map address='80-bf:6000-7fff'/>\n";
|
||||
xml << " </icd2>\n";
|
||||
} else if(has_cx4) {
|
||||
xml << " <hitachidsp model='HG51B169' frequency='20000000' data='cx4.bin' sha256='ae8d4d1961b93421ff00b3caa1d0f0ce7783e749772a3369c36b3dbf0d37ef18'>\n";
|
||||
xml << " <rom>\n";
|
||||
xml << " <map mode='linear' address='00-7f:8000-ffff'/>\n";
|
||||
xml << " <map mode='linear' address='80-ff:8000-ffff'/>\n";
|
||||
xml << " </rom>\n";
|
||||
xml << " <mmio>\n";
|
||||
xml << " <map address='00-3f:6000-7fff'/>\n";
|
||||
xml << " <map address='80-bf:6000-7fff'/>\n";
|
||||
xml << " </mmio>\n";
|
||||
xml << " </hitachidsp>\n";
|
||||
} else if(has_spc7110) {
|
||||
xml << " <rom>\n";
|
||||
xml << " <map mode='shadow' address='00-0f:8000-ffff'/>\n";
|
||||
@@ -167,9 +178,9 @@ SNESCartridge::SNESCartridge(const uint8_t *data, unsigned size) {
|
||||
|
||||
xml << " <spc7110>\n";
|
||||
xml << " <mcu>\n";
|
||||
xml << " <map address='d0-ff:0000-ffff' offset='100000' size='" << hex(size - 0x100000) << "'/>\n";
|
||||
xml << " <map address='d0-ff:0000-ffff' offset='0x100000' size='0x" << hex(size - 0x100000) << "'/>\n";
|
||||
xml << " </mcu>\n";
|
||||
xml << " <ram size='" << hex(ram_size) << "'>\n";
|
||||
xml << " <ram size='0x" << hex(ram_size) << "'>\n";
|
||||
xml << " <map mode='linear' address='00:6000-7fff'/>\n";
|
||||
xml << " <map mode='linear' address='30:6000-7fff'/>\n";
|
||||
xml << " </ram>\n";
|
||||
@@ -194,7 +205,7 @@ SNESCartridge::SNESCartridge(const uint8_t *data, unsigned size) {
|
||||
xml << " </rom>\n";
|
||||
|
||||
if(ram_size > 0) {
|
||||
xml << " <ram size='" << hex(ram_size) << "'>\n";
|
||||
xml << " <ram size='0x" << hex(ram_size) << "'>\n";
|
||||
xml << " <map mode='linear' address='20-3f:6000-7fff'/>\n";
|
||||
xml << " <map mode='linear' address='a0-bf:6000-7fff'/>\n";
|
||||
if((rom_size > 0x200000) || (ram_size > 32 * 1024)) {
|
||||
@@ -215,7 +226,7 @@ SNESCartridge::SNESCartridge(const uint8_t *data, unsigned size) {
|
||||
xml << " </rom>\n";
|
||||
|
||||
if(ram_size > 0) {
|
||||
xml << " <ram size='" << hex(ram_size) << "'>\n";
|
||||
xml << " <ram size='0x" << hex(ram_size) << "'>\n";
|
||||
xml << " <map mode='linear' address='20-3f:6000-7fff'/>\n";
|
||||
xml << " <map mode='linear' address='a0-bf:6000-7fff'/>\n";
|
||||
if((rom_size > 0x200000) || (ram_size > 32 * 1024)) {
|
||||
@@ -233,7 +244,7 @@ SNESCartridge::SNESCartridge(const uint8_t *data, unsigned size) {
|
||||
xml << " </rom>\n";
|
||||
|
||||
if(ram_size > 0) {
|
||||
xml << " <ram size='" << hex(ram_size) << "'>\n";
|
||||
xml << " <ram size='0x" << hex(ram_size) << "'>\n";
|
||||
xml << " <map mode='linear' address='20-3f:6000-7fff'/>\n";
|
||||
xml << " <map mode='linear' address='a0-bf:6000-7fff'/>\n";
|
||||
xml << " <map mode='linear' address='70-7f:0000-7fff'/>\n";
|
||||
@@ -241,14 +252,14 @@ SNESCartridge::SNESCartridge(const uint8_t *data, unsigned size) {
|
||||
}
|
||||
} else if(mapper == ExHiROM) {
|
||||
xml << " <rom>\n";
|
||||
xml << " <map mode='shadow' address='00-3f:8000-ffff' offset='400000'/>\n";
|
||||
xml << " <map mode='linear' address='40-7f:0000-ffff' offset='400000'/>\n";
|
||||
xml << " <map mode='shadow' address='80-bf:8000-ffff' offset='000000'/>\n";
|
||||
xml << " <map mode='linear' address='c0-ff:0000-ffff' offset='000000'/>\n";
|
||||
xml << " <map mode='shadow' address='00-3f:8000-ffff' offset='0x400000'/>\n";
|
||||
xml << " <map mode='linear' address='40-7f:0000-ffff' offset='0x400000'/>\n";
|
||||
xml << " <map mode='shadow' address='80-bf:8000-ffff' offset='0x000000'/>\n";
|
||||
xml << " <map mode='linear' address='c0-ff:0000-ffff' offset='0x000000'/>\n";
|
||||
xml << " </rom>\n";
|
||||
|
||||
if(ram_size > 0) {
|
||||
xml << " <ram size='" << hex(ram_size) << "'>\n";
|
||||
xml << " <ram size='0x" << hex(ram_size) << "'>\n";
|
||||
xml << " <map mode='linear' address='20-3f:6000-7fff'/>\n";
|
||||
xml << " <map mode='linear' address='a0-bf:6000-7fff'/>\n";
|
||||
if((rom_size > 0x200000) || (ram_size > 32 * 1024)) {
|
||||
@@ -266,10 +277,10 @@ SNESCartridge::SNESCartridge(const uint8_t *data, unsigned size) {
|
||||
xml << " <map mode='linear' address='80-bf:8000-ffff'/>\n";
|
||||
xml << " <map mode='linear' address='c0-df:0000-ffff'/>\n";
|
||||
xml << " </rom>\n";
|
||||
xml << " <ram size='" << hex(ram_size) << "'>\n";
|
||||
xml << " <map mode='linear' address='00-3f:6000-7fff' size='2000'/>\n";
|
||||
xml << " <ram size='0x" << hex(ram_size) << "'>\n";
|
||||
xml << " <map mode='linear' address='00-3f:6000-7fff' size='0x2000'/>\n";
|
||||
xml << " <map mode='linear' address='60-7f:0000-ffff'/>\n";
|
||||
xml << " <map mode='linear' address='80-bf:6000-7fff' size='2000'/>\n";
|
||||
xml << " <map mode='linear' address='80-bf:6000-7fff' size='0x2000'/>\n";
|
||||
xml << " <map mode='linear' address='e0-ff:0000-ffff'/>\n";
|
||||
xml << " </ram>\n";
|
||||
xml << " <mmio>\n";
|
||||
@@ -290,11 +301,11 @@ SNESCartridge::SNESCartridge(const uint8_t *data, unsigned size) {
|
||||
xml << " <map mode='direct' address='80-bf:6000-7fff'/>\n";
|
||||
xml << " </ram>\n";
|
||||
xml << " </mcu>\n";
|
||||
xml << " <iram size='800'>\n";
|
||||
xml << " <iram size='0x800'>\n";
|
||||
xml << " <map mode='linear' address='00-3f:3000-37ff'/>\n";
|
||||
xml << " <map mode='linear' address='80-bf:3000-37ff'/>\n";
|
||||
xml << " </iram>\n";
|
||||
xml << " <bwram size='" << hex(ram_size) << "'>\n";
|
||||
xml << " <bwram size='0x" << hex(ram_size) << "'>\n";
|
||||
xml << " <map mode='linear' address='40-4f:0000-ffff'/>\n";
|
||||
xml << " </bwram>\n";
|
||||
xml << " <mmio>\n";
|
||||
@@ -304,12 +315,12 @@ SNESCartridge::SNESCartridge(const uint8_t *data, unsigned size) {
|
||||
xml << " </sa1>\n";
|
||||
} else if(mapper == BSCLoROM) {
|
||||
xml << " <rom>\n";
|
||||
xml << " <map mode='linear' address='00-1f:8000-ffff' offset='000000'/>\n";
|
||||
xml << " <map mode='linear' address='20-3f:8000-ffff' offset='100000'/>\n";
|
||||
xml << " <map mode='linear' address='80-9f:8000-ffff' offset='200000'/>\n";
|
||||
xml << " <map mode='linear' address='a0-bf:8000-ffff' offset='100000'/>\n";
|
||||
xml << " <map mode='linear' address='00-1f:8000-ffff' offset='0x000000'/>\n";
|
||||
xml << " <map mode='linear' address='20-3f:8000-ffff' offset='0x100000'/>\n";
|
||||
xml << " <map mode='linear' address='80-9f:8000-ffff' offset='0x200000'/>\n";
|
||||
xml << " <map mode='linear' address='a0-bf:8000-ffff' offset='0x100000'/>\n";
|
||||
xml << " </rom>\n";
|
||||
xml << " <ram size='" << hex(ram_size) << "'>\n";
|
||||
xml << " <ram size='0x" << hex(ram_size) << "'>\n";
|
||||
xml << " <map mode='linear' address='70-7f:0000-7fff'/>\n";
|
||||
xml << " <map mode='linear' address='f0-ff:0000-7fff'/>\n";
|
||||
xml << " </ram>\n";
|
||||
@@ -325,7 +336,7 @@ SNESCartridge::SNESCartridge(const uint8_t *data, unsigned size) {
|
||||
xml << " <map mode='shadow' address='80-9f:8000-ffff'/>\n";
|
||||
xml << " <map mode='linear' address='c0-df:0000-ffff'/>\n";
|
||||
xml << " </rom>\n";
|
||||
xml << " <ram size='" << hex(ram_size) << "'>\n";
|
||||
xml << " <ram size='0x" << hex(ram_size) << "'>\n";
|
||||
xml << " <map mode='linear' address='20-3f:6000-7fff'/>\n";
|
||||
xml << " <map mode='linear' address='a0-bf:6000-7fff'/>\n";
|
||||
xml << " </ram>\n";
|
||||
@@ -362,7 +373,7 @@ SNESCartridge::SNESCartridge(const uint8_t *data, unsigned size) {
|
||||
xml << " <map mode='linear' address='20-3f:8000-ffff'/>\n";
|
||||
xml << " <map mode='linear' address='a0-bf:8000-ffff'/>\n";
|
||||
xml << " </rom>\n";
|
||||
xml << " <ram size='20000'>\n";
|
||||
xml << " <ram size='0x20000'>\n";
|
||||
xml << " <map mode='linear' address='60-63:8000-ffff'/>\n";
|
||||
xml << " <map mode='linear' address='e0-e3:8000-ffff'/>\n";
|
||||
xml << " </ram>\n";
|
||||
@@ -372,7 +383,7 @@ SNESCartridge::SNESCartridge(const uint8_t *data, unsigned size) {
|
||||
xml << " <map mode='linear' address='40-5f:8000-ffff'/>\n";
|
||||
xml << " <map mode='linear' address='c0-df:8000-ffff'/>\n";
|
||||
xml << " </rom>\n";
|
||||
xml << " <ram size='20000'>\n";
|
||||
xml << " <ram size='0x20000'>\n";
|
||||
xml << " <map mode='linear' address='70-73:8000-ffff'/>\n";
|
||||
xml << " <map mode='linear' address='f0-f3:8000-ffff'/>\n";
|
||||
xml << " </ram>\n";
|
||||
@@ -399,15 +410,8 @@ SNESCartridge::SNESCartridge(const uint8_t *data, unsigned size) {
|
||||
xml << " </sdd1>\n";
|
||||
}
|
||||
|
||||
if(has_cx4) {
|
||||
xml << " <cx4>\n";
|
||||
xml << " <map address='00-3f:6000-7fff'/>\n";
|
||||
xml << " <map address='80-bf:6000-7fff'/>\n";
|
||||
xml << " </cx4>\n";
|
||||
}
|
||||
|
||||
if(has_dsp1) {
|
||||
xml << " <necdsp revision='upd7725' frequency='8000000' program='dsp1b.bin' sha256='4d42db0f36faef263d6b93f508e8c1c4ae8fc2605fd35e3390ecc02905cd420c'>\n";
|
||||
xml << " <necdsp model='uPD7725' frequency='8000000' program='dsp1b.bin' sha256='4d42db0f36faef263d6b93f508e8c1c4ae8fc2605fd35e3390ecc02905cd420c'>\n";
|
||||
if(dsp1_mapper == DSP1LoROM1MB) {
|
||||
xml << " <dr>\n";
|
||||
xml << " <map address='20-3f:8000-bfff'/>\n";
|
||||
@@ -440,7 +444,7 @@ SNESCartridge::SNESCartridge(const uint8_t *data, unsigned size) {
|
||||
}
|
||||
|
||||
if(has_dsp2) {
|
||||
xml << " <necdsp revision='upd7725' frequency='8000000' program='dsp2.bin' sha256='5efbdf96ed0652790855225964f3e90e6a4d466cfa64df25b110933c6cf94ea1'>\n";
|
||||
xml << " <necdsp model='uPD7725' frequency='8000000' program='dsp2.bin' sha256='5efbdf96ed0652790855225964f3e90e6a4d466cfa64df25b110933c6cf94ea1'>\n";
|
||||
xml << " <dr>\n";
|
||||
xml << " <map address='20-3f:8000-bfff'/>\n";
|
||||
xml << " <map address='a0-bf:8000-bfff'/>\n";
|
||||
@@ -453,7 +457,7 @@ SNESCartridge::SNESCartridge(const uint8_t *data, unsigned size) {
|
||||
}
|
||||
|
||||
if(has_dsp3) {
|
||||
xml << " <necdsp revision='upd7725' frequency='8000000' program='dsp3.bin' sha256='2e635f72e4d4681148bc35429421c9b946e4f407590e74e31b93b8987b63ba90'>\n";
|
||||
xml << " <necdsp model='uPD7725' frequency='8000000' program='dsp3.bin' sha256='2e635f72e4d4681148bc35429421c9b946e4f407590e74e31b93b8987b63ba90'>\n";
|
||||
xml << " <dr>\n";
|
||||
xml << " <map address='20-3f:8000-bfff'/>\n";
|
||||
xml << " <map address='a0-bf:8000-bfff'/>\n";
|
||||
@@ -466,7 +470,7 @@ SNESCartridge::SNESCartridge(const uint8_t *data, unsigned size) {
|
||||
}
|
||||
|
||||
if(has_dsp4) {
|
||||
xml << " <necdsp revision='upd7725' frequency='8000000' program='dsp4.bin' sha256='63ede17322541c191ed1fdf683872554a0a57306496afc43c59de7c01a6e764a'>\n";
|
||||
xml << " <necdsp model='uPD7725' frequency='8000000' program='dsp4.bin' sha256='63ede17322541c191ed1fdf683872554a0a57306496afc43c59de7c01a6e764a'>\n";
|
||||
xml << " <dr>\n";
|
||||
xml << " <map address='30-3f:8000-bfff'/>\n";
|
||||
xml << " <map address='b0-bf:8000-bfff'/>\n";
|
||||
@@ -486,7 +490,7 @@ SNESCartridge::SNESCartridge(const uint8_t *data, unsigned size) {
|
||||
}
|
||||
|
||||
if(has_st010) {
|
||||
xml << " <necdsp revision='upd96050' frequency='10000000' program='st0010.bin' sha256='55c697e864562445621cdf8a7bf6e84ae91361e393d382a3704e9aa55559041e'>\n";
|
||||
xml << " <necdsp model='uPD96050' frequency='10000000' program='st0010.bin' sha256='55c697e864562445621cdf8a7bf6e84ae91361e393d382a3704e9aa55559041e'>\n";
|
||||
xml << " <dr>\n";
|
||||
xml << " <map address='60:0000'/>\n";
|
||||
xml << " <map address='e0:0000'/>\n";
|
||||
@@ -503,7 +507,7 @@ SNESCartridge::SNESCartridge(const uint8_t *data, unsigned size) {
|
||||
}
|
||||
|
||||
if(has_st011) {
|
||||
xml << " <necdsp revision='upd96050' frequency='15000000' program='st0011.bin' sha256='651b82a1e26c4fa8dd549e91e7f923012ed2ca54c1d9fd858655ab30679c2f0e'>\n";
|
||||
xml << " <necdsp model='uPD96050' frequency='15000000' program='st0011.bin' sha256='651b82a1e26c4fa8dd549e91e7f923012ed2ca54c1d9fd858655ab30679c2f0e'>\n";
|
||||
xml << " <dr>\n";
|
||||
xml << " <map address='60:0000'/>\n";
|
||||
xml << " <map address='e0:0000'/>\n";
|
||||
|
@@ -6,8 +6,10 @@ namespace nall {
|
||||
//this is needed, as C++0x does not support explicit template specialization inside classes
|
||||
template<> inline const char* to_string<bool> (bool v) { return v ? "true" : "false"; }
|
||||
template<> inline const char* to_string<signed int> (signed int v) { static char temp[256]; snprintf(temp, 255, "%+d", v); return temp; }
|
||||
template<> inline const char* to_string<unsigned int> (unsigned int v) { static char temp[256]; snprintf(temp, 255, "%u", v); return temp; }
|
||||
template<> inline const char* to_string<double> (double v) { static char temp[256]; snprintf(temp, 255, "%f", v); return temp; }
|
||||
template<> inline const char* to_string<unsigned int> (unsigned int v) { static char temp[256]; snprintf(temp, 255, "%u", v); return temp; }
|
||||
template<> inline const char* to_string<intmax_t> (intmax_t v) { static char temp[256]; snprintf(temp, 255, "%+lld", (long long)v); return temp; }
|
||||
template<> inline const char* to_string<uintmax_t> (uintmax_t v) { static char temp[256]; snprintf(temp, 255, "%llu", (unsigned long long)v); return temp; }
|
||||
template<> inline const char* to_string<double> (double v) { static char temp[256]; snprintf(temp, 255, "%f", v); return temp; }
|
||||
template<> inline const char* to_string<char*> (char *v) { return v; }
|
||||
template<> inline const char* to_string<const char*> (const char *v) { return v; }
|
||||
template<> inline const char* to_string<string> (string v) { return v; }
|
||||
|
@@ -34,6 +34,10 @@ void Font::setSize(unsigned size) { state.size = size; return p.setSize(size); }
|
||||
void Font::setUnderline(bool underline) { state.underline = underline; return p.setUnderline(underline); }
|
||||
Font::Font() : state(*new State), p(*new pFont(*this)) { p.constructor(); }
|
||||
|
||||
void Timer::setEnabled(bool enabled) { state.enabled = enabled; return p.setEnabled(enabled); }
|
||||
void Timer::setInterval(unsigned milliseconds) { state.milliseconds = milliseconds; return p.setInterval(milliseconds); }
|
||||
Timer::Timer() : state(*new State), p(*new pTimer(*this)) { p.constructor(); }
|
||||
|
||||
MessageWindow::Response MessageWindow::information(Window &parent, const string &text, MessageWindow::Buttons buttons) { return pMessageWindow::information(parent, text, buttons); }
|
||||
MessageWindow::Response MessageWindow::question(Window &parent, const string &text, MessageWindow::Buttons buttons) { return pMessageWindow::question(parent, text, buttons); }
|
||||
MessageWindow::Response MessageWindow::warning(Window &parent, const string &text, MessageWindow::Buttons buttons) { return pMessageWindow::warning(parent, text, buttons); }
|
||||
|
@@ -6,6 +6,7 @@ struct Widget;
|
||||
|
||||
struct pOS;
|
||||
struct pFont;
|
||||
struct pTimer;
|
||||
struct pWindow;
|
||||
struct pAction;
|
||||
struct pMenu;
|
||||
@@ -82,6 +83,18 @@ struct Font : Object {
|
||||
pFont &p;
|
||||
};
|
||||
|
||||
struct Timer : Object {
|
||||
nall::function<void ()> onTimeout;
|
||||
|
||||
void setEnabled(bool enabled = true);
|
||||
void setInterval(unsigned milliseconds);
|
||||
|
||||
Timer();
|
||||
struct State;
|
||||
State &state;
|
||||
pTimer &p;
|
||||
};
|
||||
|
||||
struct MessageWindow : Object {
|
||||
enum class Buttons : unsigned {
|
||||
Ok,
|
||||
|
@@ -13,6 +13,16 @@ struct Font::State {
|
||||
}
|
||||
};
|
||||
|
||||
struct Timer::State {
|
||||
bool enabled;
|
||||
unsigned milliseconds;
|
||||
|
||||
State() {
|
||||
enabled = false;
|
||||
milliseconds = 0;
|
||||
}
|
||||
};
|
||||
|
||||
struct Window::State {
|
||||
bool backgroundColor;
|
||||
unsigned backgroundColorRed, backgroundColorGreen, backgroundColorBlue;
|
||||
|
@@ -2,6 +2,7 @@
|
||||
|
||||
#include "settings.cpp"
|
||||
#include "font.cpp"
|
||||
#include "timer.cpp"
|
||||
#include "message-window.cpp"
|
||||
#include "window.cpp"
|
||||
|
||||
@@ -31,10 +32,29 @@
|
||||
Font pOS::defaultFont;
|
||||
|
||||
Geometry pOS::availableGeometry() {
|
||||
//TODO: is there a GTK+ function for this?
|
||||
//should return desktopGeometry() sans panels, toolbars, docks, etc.
|
||||
Geometry geometry = desktopGeometry();
|
||||
return { geometry.x + 64, geometry.y + 64, geometry.width - 128, geometry.height - 128 };
|
||||
Display *display = XOpenDisplay(0);
|
||||
int screen = DefaultScreen(display);
|
||||
|
||||
static Atom atom = X11None;
|
||||
if(atom == X11None) atom = XInternAtom(display, "_NET_WORKAREA", True);
|
||||
|
||||
int format;
|
||||
unsigned char *data = 0;
|
||||
unsigned long items, after;
|
||||
Atom returnAtom;
|
||||
|
||||
int result = XGetWindowProperty(
|
||||
display, RootWindow(display, screen), atom, 0, 4, False, XA_CARDINAL, &returnAtom, &format, &items, &after, &data
|
||||
);
|
||||
|
||||
XCloseDisplay(display);
|
||||
|
||||
if(result == Success && returnAtom == XA_CARDINAL && format == 32 && items == 4) {
|
||||
unsigned long *workarea = (unsigned long*)data;
|
||||
return { (signed)workarea[0], (signed)workarea[1], (unsigned)workarea[2], (unsigned)workarea[3] };
|
||||
}
|
||||
|
||||
return desktopGeometry();
|
||||
}
|
||||
|
||||
Geometry pOS::desktopGeometry() {
|
||||
|
@@ -57,6 +57,16 @@ struct pFont : public pObject {
|
||||
void constructor();
|
||||
};
|
||||
|
||||
struct pTimer : public pObject {
|
||||
Timer &timer;
|
||||
|
||||
void setEnabled(bool enabled);
|
||||
void setInterval(unsigned milliseconds);
|
||||
|
||||
pTimer(Timer &timer) : timer(timer) {}
|
||||
void constructor();
|
||||
};
|
||||
|
||||
struct pMessageWindow : public pObject {
|
||||
static MessageWindow::Response information(Window &parent, const string &text, MessageWindow::Buttons buttons);
|
||||
static MessageWindow::Response question(Window &parent, const string &text, MessageWindow::Buttons buttons);
|
||||
|
24
bsnes/phoenix/gtk/timer.cpp
Executable file
24
bsnes/phoenix/gtk/timer.cpp
Executable file
@@ -0,0 +1,24 @@
|
||||
static guint Timer_trigger(pTimer *self) {
|
||||
//timer may have been disabled prior to triggering, so check state
|
||||
if(self->timer.state.enabled) {
|
||||
if(self->timer.onTimeout) self->timer.onTimeout();
|
||||
}
|
||||
//callback may have disabled timer, so check state again
|
||||
if(self->timer.state.enabled) {
|
||||
g_timeout_add(self->timer.state.milliseconds, (GSourceFunc)Timer_trigger, (gpointer)self);
|
||||
}
|
||||
//kill this timer instance (it is spawned above if needed again)
|
||||
return false;
|
||||
}
|
||||
|
||||
void pTimer::setEnabled(bool enabled) {
|
||||
if(enabled) {
|
||||
g_timeout_add(timer.state.milliseconds, (GSourceFunc)Timer_trigger, (gpointer)this);
|
||||
}
|
||||
}
|
||||
|
||||
void pTimer::setInterval(unsigned milliseconds) {
|
||||
}
|
||||
|
||||
void pTimer::constructor() {
|
||||
}
|
@@ -1,3 +1,6 @@
|
||||
#ifndef PHOENIX_CPP
|
||||
#define PHOENIX_CPP
|
||||
|
||||
#if defined(PHOENIX_WINDOWS)
|
||||
#define UNICODE
|
||||
#define WINVER 0x0501
|
||||
@@ -14,13 +17,15 @@
|
||||
#include <QApplication>
|
||||
#include <QtGui>
|
||||
#elif defined(PHOENIX_GTK)
|
||||
#define None X11None
|
||||
#define None
|
||||
#define Window X11Window
|
||||
#define X11None 0L
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
#include <gdk/gdkx.h>
|
||||
#include <cairo.h>
|
||||
#include <gdk/gdkkeysyms.h>
|
||||
#include <X11/Xatom.h>
|
||||
|
||||
#undef None
|
||||
#undef Window
|
||||
@@ -35,3 +40,5 @@ using namespace nall;
|
||||
namespace phoenix {
|
||||
#include "core/core.cpp"
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@@ -1,3 +1,6 @@
|
||||
#ifndef PHOENIX_HPP
|
||||
#define PHOENIX_HPP
|
||||
|
||||
#include <nall/array.hpp>
|
||||
#include <nall/config.hpp>
|
||||
#include <nall/foreach.hpp>
|
||||
@@ -11,3 +14,5 @@
|
||||
namespace phoenix {
|
||||
#include "core/core.hpp"
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@@ -3,6 +3,7 @@
|
||||
|
||||
#include "settings.cpp"
|
||||
#include "font.cpp"
|
||||
#include "timer.cpp"
|
||||
#include "message-window.cpp"
|
||||
#include "window.cpp"
|
||||
|
||||
|
@@ -1,7 +1,7 @@
|
||||
/****************************************************************************
|
||||
** Meta object code from reading C++ file 'qt.moc.hpp'
|
||||
**
|
||||
** Created: Wed Mar 23 16:17:23 2011
|
||||
** Created: Tue May 24 19:33:16 2011
|
||||
** by: The Qt Meta Object Compiler version 62 (Qt 4.7.0)
|
||||
**
|
||||
** WARNING! All changes made in this file will be lost!
|
||||
@@ -16,6 +16,67 @@
|
||||
#endif
|
||||
|
||||
QT_BEGIN_MOC_NAMESPACE
|
||||
static const uint qt_meta_data_pTimer[] = {
|
||||
|
||||
// content:
|
||||
5, // revision
|
||||
0, // classname
|
||||
0, 0, // classinfo
|
||||
1, 14, // methods
|
||||
0, 0, // properties
|
||||
0, 0, // enums/sets
|
||||
0, 0, // constructors
|
||||
0, // flags
|
||||
0, // signalCount
|
||||
|
||||
// slots: signature, parameters, type, tag, flags
|
||||
8, 7, 7, 7, 0x0a,
|
||||
|
||||
0 // eod
|
||||
};
|
||||
|
||||
static const char qt_meta_stringdata_pTimer[] = {
|
||||
"pTimer\0\0onTimeout()\0"
|
||||
};
|
||||
|
||||
const QMetaObject pTimer::staticMetaObject = {
|
||||
{ &QObject::staticMetaObject, qt_meta_stringdata_pTimer,
|
||||
qt_meta_data_pTimer, 0 }
|
||||
};
|
||||
|
||||
#ifdef Q_NO_DATA_RELOCATION
|
||||
const QMetaObject &pTimer::getStaticMetaObject() { return staticMetaObject; }
|
||||
#endif //Q_NO_DATA_RELOCATION
|
||||
|
||||
const QMetaObject *pTimer::metaObject() const
|
||||
{
|
||||
return QObject::d_ptr->metaObject ? QObject::d_ptr->metaObject : &staticMetaObject;
|
||||
}
|
||||
|
||||
void *pTimer::qt_metacast(const char *_clname)
|
||||
{
|
||||
if (!_clname) return 0;
|
||||
if (!strcmp(_clname, qt_meta_stringdata_pTimer))
|
||||
return static_cast<void*>(const_cast< pTimer*>(this));
|
||||
if (!strcmp(_clname, "pObject"))
|
||||
return static_cast< pObject*>(const_cast< pTimer*>(this));
|
||||
return QObject::qt_metacast(_clname);
|
||||
}
|
||||
|
||||
int pTimer::qt_metacall(QMetaObject::Call _c, int _id, void **_a)
|
||||
{
|
||||
_id = QObject::qt_metacall(_c, _id, _a);
|
||||
if (_id < 0)
|
||||
return _id;
|
||||
if (_c == QMetaObject::InvokeMetaMethod) {
|
||||
switch (_id) {
|
||||
case 0: onTimeout(); break;
|
||||
default: ;
|
||||
}
|
||||
_id -= 1;
|
||||
}
|
||||
return _id;
|
||||
}
|
||||
static const uint qt_meta_data_pWindow[] = {
|
||||
|
||||
// content:
|
||||
|
@@ -56,6 +56,23 @@ struct pFont : public pObject {
|
||||
void update();
|
||||
};
|
||||
|
||||
struct pTimer : public QObject, public pObject {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
Timer &timer;
|
||||
QTimer *qtTimer;
|
||||
|
||||
void setEnabled(bool enabled);
|
||||
void setInterval(unsigned milliseconds);
|
||||
|
||||
pTimer(Timer &timer) : timer(timer) {}
|
||||
void constructor();
|
||||
|
||||
public slots:
|
||||
void onTimeout();
|
||||
};
|
||||
|
||||
struct pMessageWindow : public pObject {
|
||||
static MessageWindow::Response information(Window &parent, const string &text, MessageWindow::Buttons buttons);
|
||||
static MessageWindow::Response question(Window &parent, const string &text, MessageWindow::Buttons buttons);
|
||||
|
21
bsnes/phoenix/qt/timer.cpp
Executable file
21
bsnes/phoenix/qt/timer.cpp
Executable file
@@ -0,0 +1,21 @@
|
||||
void pTimer::setEnabled(bool enabled) {
|
||||
if(enabled) {
|
||||
qtTimer->start();
|
||||
} else {
|
||||
qtTimer->stop();
|
||||
}
|
||||
}
|
||||
|
||||
void pTimer::setInterval(unsigned milliseconds) {
|
||||
qtTimer->setInterval(milliseconds);
|
||||
}
|
||||
|
||||
void pTimer::constructor() {
|
||||
qtTimer = new QTimer;
|
||||
qtTimer->setInterval(0);
|
||||
connect(qtTimer, SIGNAL(timeout()), SLOT(onTimeout()));
|
||||
}
|
||||
|
||||
void pTimer::onTimeout() {
|
||||
if(timer.onTimeout) timer.onTimeout();
|
||||
}
|
@@ -1,3 +1,7 @@
|
||||
Geometry pFont::geometry(const string &text) {
|
||||
return { 0, 0, 0, 0 };
|
||||
}
|
||||
|
||||
void pFont::setBold(bool bold) {
|
||||
}
|
||||
|
||||
|
@@ -1,6 +1,7 @@
|
||||
#include "reference.hpp"
|
||||
|
||||
#include "font.cpp"
|
||||
#include "timer.cpp"
|
||||
#include "message-window.cpp"
|
||||
#include "window.cpp"
|
||||
|
||||
@@ -13,6 +14,7 @@
|
||||
|
||||
#include "widget/widget.cpp"
|
||||
#include "widget/button.cpp"
|
||||
#include "widget/canvas.cpp"
|
||||
#include "widget/check-box.cpp"
|
||||
#include "widget/combo-box.cpp"
|
||||
#include "widget/hex-edit.cpp"
|
||||
|
@@ -29,6 +29,7 @@ struct pOS : public pObject {
|
||||
struct pFont : public pObject {
|
||||
Font &font;
|
||||
|
||||
Geometry geometry(const string &text);
|
||||
void setBold(bool bold);
|
||||
void setFamily(const string &family);
|
||||
void setItalic(bool italic);
|
||||
@@ -39,6 +40,16 @@ struct pFont : public pObject {
|
||||
void constructor();
|
||||
};
|
||||
|
||||
struct pTimer : public pObject {
|
||||
Timer &timer;
|
||||
|
||||
void setEnabled(bool enabled);
|
||||
void setInterval(unsigned milliseconds);
|
||||
|
||||
pTimer(Timer &timer) : timer(timer) {}
|
||||
void constructor();
|
||||
};
|
||||
|
||||
struct pMessageWindow : public pObject {
|
||||
static MessageWindow::Response information(Window &parent, const string &text, MessageWindow::Buttons buttons);
|
||||
static MessageWindow::Response question(Window &parent, const string &text, MessageWindow::Buttons buttons);
|
||||
@@ -136,6 +147,8 @@ struct pWidget : public pObject {
|
||||
Widget &widget;
|
||||
|
||||
bool enabled();
|
||||
Font& font();
|
||||
Geometry minimumGeometry();
|
||||
void setEnabled(bool enabled);
|
||||
void setFocused();
|
||||
void setFont(Font &font);
|
||||
@@ -155,6 +168,16 @@ struct pButton : public pWidget {
|
||||
void constructor();
|
||||
};
|
||||
|
||||
struct pCanvas : public pWidget {
|
||||
Canvas &canvas;
|
||||
|
||||
uint32_t* buffer();
|
||||
void update();
|
||||
|
||||
pCanvas(Canvas &canvas) : pWidget(canvas), canvas(canvas) {}
|
||||
void constructor();
|
||||
};
|
||||
|
||||
struct pCheckBox : public pWidget {
|
||||
CheckBox &checkBox;
|
||||
|
||||
|
8
bsnes/phoenix/reference/timer.cpp
Executable file
8
bsnes/phoenix/reference/timer.cpp
Executable file
@@ -0,0 +1,8 @@
|
||||
void pTimer::setEnabled(bool enabled) {
|
||||
}
|
||||
|
||||
void pTimer::setInterval(unsigned milliseconds) {
|
||||
}
|
||||
|
||||
void pTimer::constructor() {
|
||||
}
|
9
bsnes/phoenix/reference/widget/canvas.cpp
Executable file
9
bsnes/phoenix/reference/widget/canvas.cpp
Executable file
@@ -0,0 +1,9 @@
|
||||
uint32_t* pCanvas::buffer() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
void pCanvas::update() {
|
||||
}
|
||||
|
||||
void pCanvas::constructor() {
|
||||
}
|
@@ -2,6 +2,14 @@ bool pWidget::enabled() {
|
||||
return false;
|
||||
}
|
||||
|
||||
Font& pWidget::font() {
|
||||
throw;
|
||||
}
|
||||
|
||||
Geometry pWidget::minimumGeometry() {
|
||||
return { 0, 0, 0, 0 };
|
||||
}
|
||||
|
||||
void pWidget::setEnabled(bool enabled) {
|
||||
}
|
||||
|
||||
|
31
bsnes/phoenix/windows/timer.cpp
Executable file
31
bsnes/phoenix/windows/timer.cpp
Executable file
@@ -0,0 +1,31 @@
|
||||
static linear_vector<pTimer*> timers;
|
||||
|
||||
static void CALLBACK Timer_timeoutProc(HWND hwnd, UINT msg, UINT_PTR timerID, DWORD time) {
|
||||
foreach(timer, timers) {
|
||||
if(timer->htimer == timerID) {
|
||||
if(timer->timer.onTimeout) timer->timer.onTimeout();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void pTimer::setEnabled(bool enabled) {
|
||||
if(htimer) {
|
||||
KillTimer(NULL, htimer);
|
||||
htimer = 0;
|
||||
}
|
||||
|
||||
if(enabled == true) {
|
||||
htimer = SetTimer(NULL, 0U, timer.state.milliseconds, Timer_timeoutProc);
|
||||
}
|
||||
}
|
||||
|
||||
void pTimer::setInterval(unsigned milliseconds) {
|
||||
//destroy and recreate timer if interval changed
|
||||
setEnabled(timer.state.enabled);
|
||||
}
|
||||
|
||||
void pTimer::constructor() {
|
||||
timers.append(this);
|
||||
htimer = 0;
|
||||
}
|
@@ -36,8 +36,11 @@ Geometry pWindow::frameMargin() {
|
||||
|
||||
Geometry pWindow::geometry() {
|
||||
Geometry margin = frameMargin();
|
||||
RECT rc;
|
||||
GetWindowRect(hwnd, &rc);
|
||||
|
||||
//note: GetWindowRect returns -32000(x),-32000(y) when window is minimized
|
||||
WINDOWPLACEMENT wp;
|
||||
GetWindowPlacement(hwnd, &wp);
|
||||
RECT rc = wp.rcNormalPosition;
|
||||
|
||||
signed x = rc.left + margin.x;
|
||||
signed y = rc.top + margin.y;
|
||||
|
@@ -2,6 +2,7 @@
|
||||
|
||||
#include "object.cpp"
|
||||
#include "font.cpp"
|
||||
#include "timer.cpp"
|
||||
#include "message-window.cpp"
|
||||
#include "window.cpp"
|
||||
|
||||
|
@@ -49,6 +49,17 @@ struct pFont : public pObject {
|
||||
void constructor();
|
||||
};
|
||||
|
||||
struct pTimer : public pObject {
|
||||
Timer &timer;
|
||||
UINT_PTR htimer;
|
||||
|
||||
void setEnabled(bool enabled);
|
||||
void setInterval(unsigned milliseconds);
|
||||
|
||||
pTimer(Timer &timer) : timer(timer) {}
|
||||
void constructor();
|
||||
};
|
||||
|
||||
struct pMessageWindow : public pObject {
|
||||
static MessageWindow::Response information(Window &parent, const string &text, MessageWindow::Buttons buttons);
|
||||
static MessageWindow::Response question(Window &parent, const string &text, MessageWindow::Buttons buttons);
|
||||
|
@@ -1,11 +1,11 @@
|
||||
snes_objects := snes-system
|
||||
snes_objects := snes-system snes-controller
|
||||
snes_objects += snes-cartridge snes-cheat
|
||||
snes_objects += snes-memory snes-cpucore snes-smpcore
|
||||
snes_objects += snes-cpu snes-smp snes-dsp snes-ppu
|
||||
snes_objects += snes-icd2 snes-superfx snes-sa1 snes-necdsp
|
||||
snes_objects += snes-bsx snes-srtc snes-sdd1 snes-spc7110 snes-cx4
|
||||
snes_objects += snes-nss snes-icd2 snes-superfx snes-sa1 snes-necdsp snes-hitachidsp
|
||||
snes_objects += snes-bsx snes-srtc snes-sdd1 snes-spc7110
|
||||
snes_objects += snes-obc1 snes-st0018 snes-sufamiturbo
|
||||
snes_objects += snes-msu1 snes-serial
|
||||
snes_objects += snes-msu1 snes-link
|
||||
objects += $(snes_objects)
|
||||
|
||||
ifeq ($(profile),accuracy)
|
||||
@@ -23,33 +23,35 @@ else ifeq ($(profile),compatibility)
|
||||
else ifeq ($(profile),performance)
|
||||
flags += -DPROFILE_PERFORMANCE
|
||||
snescpu := $(snes)/alt/cpu
|
||||
snessmp := $(snes)/smp
|
||||
snessmp := $(snes)/alt/smp
|
||||
snesdsp := $(snes)/alt/dsp
|
||||
snesppu := $(snes)/alt/ppu-performance
|
||||
endif
|
||||
|
||||
obj/snes-system.o : $(snes)/system/system.cpp $(call rwildcard,$(snes)/system/) $(call rwildcard,$(snes)/video/)
|
||||
obj/snes-memory.o : $(snes)/memory/memory.cpp $(call rwildcard,$(snes)/memory/)
|
||||
obj/snes-cpucore.o : $(snes)/cpu/core/core.cpp $(call rwildcard,$(snes)/cpu/core/)
|
||||
obj/snes-smpcore.o : $(snes)/smp/core/core.cpp $(call rwildcard,$(snes)/smp/core/)
|
||||
obj/snes-cpu.o : $(snescpu)/cpu.cpp $(call rwildcard,$(snescpu)/)
|
||||
obj/snes-smp.o : $(snessmp)/smp.cpp $(call rwildcard,$(snessmp)/)
|
||||
obj/snes-dsp.o : $(snesdsp)/dsp.cpp $(call rwildcard,$(snesdsp)/)
|
||||
obj/snes-ppu.o : $(snesppu)/ppu.cpp $(call rwildcard,$(snesppu)/)
|
||||
obj/snes-cartridge.o: $(snes)/cartridge/cartridge.cpp $(snes)/cartridge/*
|
||||
obj/snes-cheat.o : $(snes)/cheat/cheat.cpp $(snes)/cheat/*
|
||||
obj/snes-system.o : $(snes)/system/system.cpp $(call rwildcard,$(snes)/system/) $(call rwildcard,$(snes)/video/) $(call rwildcard,$(snes)/audio/) $(call rwildcard,$(snes)/input/)
|
||||
obj/snes-controller.o: $(snes)/controller/controller.cpp $(call rwildcard,$(snes)/controller/)
|
||||
obj/snes-memory.o : $(snes)/memory/memory.cpp $(call rwildcard,$(snes)/memory/)
|
||||
obj/snes-cpucore.o : $(snes)/cpu/core/core.cpp $(call rwildcard,$(snes)/cpu/core/)
|
||||
obj/snes-smpcore.o : $(snes)/smp/core/core.cpp $(call rwildcard,$(snes)/smp/core/)
|
||||
obj/snes-cpu.o : $(snescpu)/cpu.cpp $(call rwildcard,$(snescpu)/)
|
||||
obj/snes-smp.o : $(snessmp)/smp.cpp $(call rwildcard,$(snessmp)/)
|
||||
obj/snes-dsp.o : $(snesdsp)/dsp.cpp $(call rwildcard,$(snesdsp)/)
|
||||
obj/snes-ppu.o : $(snesppu)/ppu.cpp $(call rwildcard,$(snesppu)/)
|
||||
obj/snes-cartridge.o : $(snes)/cartridge/cartridge.cpp $(snes)/cartridge/*
|
||||
obj/snes-cheat.o : $(snes)/cheat/cheat.cpp $(snes)/cheat/*
|
||||
|
||||
obj/snes-nss.o : $(snes)/chip/nss/nss.cpp $(call rwildcard,$(snes)/chip/nss/)
|
||||
obj/snes-icd2.o : $(snes)/chip/icd2/icd2.cpp $(call rwildcard,$(snes)/chip/icd2/)
|
||||
obj/snes-superfx.o : $(snes)/chip/superfx/superfx.cpp $(call rwildcard,$(snes)/chip/superfx/)
|
||||
obj/snes-sa1.o : $(snes)/chip/sa1/sa1.cpp $(call rwildcard,$(snes)/chip/sa1/)
|
||||
obj/snes-necdsp.o : $(snes)/chip/necdsp/necdsp.cpp $(call rwildcard,$(snes)/chip/necdsp/)
|
||||
obj/snes-hitachidsp.o : $(snes)/chip/hitachidsp/hitachidsp.cpp $(call rwildcard,$(snes)/chip/hitachidsp/)
|
||||
obj/snes-bsx.o : $(snes)/chip/bsx/bsx.cpp $(call rwildcard,$(snes)/chip/bsx/)
|
||||
obj/snes-srtc.o : $(snes)/chip/srtc/srtc.cpp $(snes)/chip/srtc/*
|
||||
obj/snes-sdd1.o : $(snes)/chip/sdd1/sdd1.cpp $(snes)/chip/sdd1/*
|
||||
obj/snes-spc7110.o : $(snes)/chip/spc7110/spc7110.cpp $(snes)/chip/spc7110/*
|
||||
obj/snes-cx4.o : $(snes)/chip/cx4/cx4.cpp $(snes)/chip/cx4/*
|
||||
obj/snes-obc1.o : $(snes)/chip/obc1/obc1.cpp $(snes)/chip/obc1/*
|
||||
obj/snes-st0018.o : $(snes)/chip/st0018/st0018.cpp $(snes)/chip/st0018/*
|
||||
obj/snes-sufamiturbo.o: $(snes)/chip/sufamiturbo/sufamiturbo.cpp $(snes)/chip/sufamiturbo/*
|
||||
obj/snes-msu1.o : $(snes)/chip/msu1/msu1.cpp $(snes)/chip/msu1/*
|
||||
obj/snes-serial.o : $(snes)/chip/serial/serial.cpp $(snes)/chip/serial/*
|
||||
obj/snes-link.o : $(snes)/chip/link/link.cpp $(snes)/chip/link/*
|
||||
|
@@ -23,6 +23,9 @@ void CPU::step(unsigned clocks) {
|
||||
Processor &chip = *coprocessors[i];
|
||||
chip.clock -= clocks * (uint64)chip.frequency;
|
||||
}
|
||||
input.port1->clock -= clocks * (uint64)input.port1->frequency;
|
||||
input.port2->clock -= clocks * (uint64)input.port2->frequency;
|
||||
synchronize_controllers();
|
||||
}
|
||||
|
||||
void CPU::synchronize_smp() {
|
||||
@@ -41,13 +44,18 @@ void CPU::synchronize_ppu() {
|
||||
}
|
||||
}
|
||||
|
||||
void CPU::synchronize_coprocessor() {
|
||||
void CPU::synchronize_coprocessors() {
|
||||
for(unsigned i = 0; i < coprocessors.size(); i++) {
|
||||
Processor &chip = *coprocessors[i];
|
||||
if(chip.clock < 0) co_switch(chip.thread);
|
||||
}
|
||||
}
|
||||
|
||||
void CPU::synchronize_controllers() {
|
||||
if(input.port1->clock < 0) co_switch(input.port1->thread);
|
||||
if(input.port2->clock < 0) co_switch(input.port2->thread);
|
||||
}
|
||||
|
||||
void CPU::Enter() { cpu.enter(); }
|
||||
|
||||
void CPU::enter() {
|
||||
|
@@ -7,7 +7,8 @@ public:
|
||||
alwaysinline void step(unsigned clocks);
|
||||
alwaysinline void synchronize_smp();
|
||||
void synchronize_ppu();
|
||||
void synchronize_coprocessor();
|
||||
void synchronize_coprocessors();
|
||||
void synchronize_controllers();
|
||||
|
||||
uint8 pio();
|
||||
bool joylatch();
|
||||
@@ -41,7 +42,6 @@ private:
|
||||
enum : unsigned {
|
||||
DramRefresh,
|
||||
HdmaRun,
|
||||
ControllerLatch,
|
||||
};
|
||||
};
|
||||
nall::priority_queue<unsigned> queue;
|
||||
|
@@ -15,13 +15,13 @@ uint8 CPU::mmio_read(unsigned addr) {
|
||||
|
||||
case 0x4016: {
|
||||
uint8 result = regs.mdr & 0xfc;
|
||||
result |= input.port_read(0) & 3;
|
||||
result |= input.port1->data() & 3;
|
||||
return result;
|
||||
}
|
||||
|
||||
case 0x4017: {
|
||||
uint8 result = (regs.mdr & 0xe0) | 0x1c;
|
||||
result |= input.port_read(1) & 3;
|
||||
result |= input.port2->data() & 3;
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -127,10 +127,8 @@ void CPU::mmio_write(unsigned addr, uint8 data) {
|
||||
}
|
||||
|
||||
case 0x4016: {
|
||||
bool old_latch = status.joypad_strobe_latch;
|
||||
bool new_latch = data & 1;
|
||||
status.joypad_strobe_latch = new_latch;
|
||||
if(old_latch != new_latch) input.poll();
|
||||
input.port1->latch(data & 1);
|
||||
input.port2->latch(data & 1);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@@ -4,7 +4,6 @@ void CPU::queue_event(unsigned id) {
|
||||
switch(id) {
|
||||
case QueueEvent::DramRefresh: return add_clocks(40);
|
||||
case QueueEvent::HdmaRun: return hdma_run();
|
||||
case QueueEvent::ControllerLatch: return ppu.latch_counters();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -62,7 +61,7 @@ void CPU::add_clocks(unsigned clocks) {
|
||||
void CPU::scanline() {
|
||||
synchronize_smp();
|
||||
synchronize_ppu();
|
||||
synchronize_coprocessor();
|
||||
synchronize_coprocessors();
|
||||
system.scanline();
|
||||
|
||||
if(vcounter() == 0) hdma_init();
|
||||
@@ -73,10 +72,6 @@ void CPU::scanline() {
|
||||
queue.enqueue(1104 + 8, QueueEvent::HdmaRun);
|
||||
}
|
||||
|
||||
if(vcounter() == input.latchy) {
|
||||
queue.enqueue(input.latchx, QueueEvent::ControllerLatch);
|
||||
}
|
||||
|
||||
bool nmi_valid = status.nmi_valid;
|
||||
status.nmi_valid = vcounter() >= (ppu.overscan() == false ? 225 : 240);
|
||||
if(!nmi_valid && status.nmi_valid) {
|
||||
@@ -87,16 +82,20 @@ void CPU::scanline() {
|
||||
}
|
||||
|
||||
if(status.auto_joypad_poll_enabled && vcounter() == (ppu.overscan() == false ? 227 : 242)) {
|
||||
input.poll();
|
||||
run_auto_joypad_poll();
|
||||
}
|
||||
}
|
||||
|
||||
void CPU::run_auto_joypad_poll() {
|
||||
input.port1->latch(1);
|
||||
input.port2->latch(1);
|
||||
input.port1->latch(0);
|
||||
input.port2->latch(0);
|
||||
|
||||
uint16 joy1 = 0, joy2 = 0, joy3 = 0, joy4 = 0;
|
||||
for(unsigned i = 0; i < 16; i++) {
|
||||
uint8 port0 = input.port_read(0);
|
||||
uint8 port1 = input.port_read(1);
|
||||
uint8 port0 = input.port1->data();
|
||||
uint8 port1 = input.port2->data();
|
||||
|
||||
joy1 |= (port0 & 1) ? (0x8000 >> i) : 0;
|
||||
joy2 |= (port1 & 1) ? (0x8000 >> i) : 0;
|
||||
|
122
bsnes/snes/alt/smp/algorithms.cpp
Executable file
122
bsnes/snes/alt/smp/algorithms.cpp
Executable file
@@ -0,0 +1,122 @@
|
||||
uint8 SMP::op_adc(uint8 x, uint8 y) {
|
||||
int r = x + y + regs.p.c;
|
||||
regs.p.n = r & 0x80;
|
||||
regs.p.v = ~(x ^ y) & (x ^ r) & 0x80;
|
||||
regs.p.h = (x ^ y ^ r) & 0x10;
|
||||
regs.p.z = (uint8)r == 0;
|
||||
regs.p.c = r > 0xff;
|
||||
return r;
|
||||
}
|
||||
|
||||
uint16 SMP::op_addw(uint16 x, uint16 y) {
|
||||
uint16 r;
|
||||
regs.p.c = 0;
|
||||
r = op_adc(x, y);
|
||||
r |= op_adc(x >> 8, y >> 8) << 8;
|
||||
regs.p.z = r == 0;
|
||||
return r;
|
||||
}
|
||||
|
||||
uint8 SMP::op_and(uint8 x, uint8 y) {
|
||||
x &= y;
|
||||
regs.p.n = x & 0x80;
|
||||
regs.p.z = x == 0;
|
||||
return x;
|
||||
}
|
||||
|
||||
uint8 SMP::op_cmp(uint8 x, uint8 y) {
|
||||
int r = x - y;
|
||||
regs.p.n = r & 0x80;
|
||||
regs.p.z = (uint8)r == 0;
|
||||
regs.p.c = r >= 0;
|
||||
return x;
|
||||
}
|
||||
|
||||
uint16 SMP::op_cmpw(uint16 x, uint16 y) {
|
||||
int r = x - y;
|
||||
regs.p.n = r & 0x8000;
|
||||
regs.p.z = (uint16)r == 0;
|
||||
regs.p.c = r >= 0;
|
||||
return x;
|
||||
}
|
||||
|
||||
uint8 SMP::op_eor(uint8 x, uint8 y) {
|
||||
x ^= y;
|
||||
regs.p.n = x & 0x80;
|
||||
regs.p.z = x == 0;
|
||||
return x;
|
||||
}
|
||||
|
||||
uint8 SMP::op_or(uint8 x, uint8 y) {
|
||||
x |= y;
|
||||
regs.p.n = x & 0x80;
|
||||
regs.p.z = x == 0;
|
||||
return x;
|
||||
}
|
||||
|
||||
uint8 SMP::op_sbc(uint8 x, uint8 y) {
|
||||
int r = x - y - !regs.p.c;
|
||||
regs.p.n = r & 0x80;
|
||||
regs.p.v = (x ^ y) & (x ^ r) & 0x80;
|
||||
regs.p.h = !((x ^ y ^ r) & 0x10);
|
||||
regs.p.z = (uint8)r == 0;
|
||||
regs.p.c = r >= 0;
|
||||
return r;
|
||||
}
|
||||
|
||||
uint16 SMP::op_subw(uint16 x, uint16 y) {
|
||||
uint16 r;
|
||||
regs.p.c = 1;
|
||||
r = op_sbc(x, y);
|
||||
r |= op_sbc(x >> 8, y >> 8) << 8;
|
||||
regs.p.z = r == 0;
|
||||
return r;
|
||||
}
|
||||
|
||||
uint8 SMP::op_inc(uint8 x) {
|
||||
x++;
|
||||
regs.p.n = x & 0x80;
|
||||
regs.p.z = x == 0;
|
||||
return x;
|
||||
}
|
||||
|
||||
uint8 SMP::op_dec(uint8 x) {
|
||||
x--;
|
||||
regs.p.n = x & 0x80;
|
||||
regs.p.z = x == 0;
|
||||
return x;
|
||||
}
|
||||
|
||||
uint8 SMP::op_asl(uint8 x) {
|
||||
regs.p.c = x & 0x80;
|
||||
x <<= 1;
|
||||
regs.p.n = x & 0x80;
|
||||
regs.p.z = x == 0;
|
||||
return x;
|
||||
}
|
||||
|
||||
uint8 SMP::op_lsr(uint8 x) {
|
||||
regs.p.c = x & 0x01;
|
||||
x >>= 1;
|
||||
regs.p.n = x & 0x80;
|
||||
regs.p.z = x == 0;
|
||||
return x;
|
||||
}
|
||||
|
||||
uint8 SMP::op_rol(uint8 x) {
|
||||
unsigned carry = (unsigned)regs.p.c;
|
||||
regs.p.c = x & 0x80;
|
||||
x = (x << 1) | carry;
|
||||
regs.p.n = x & 0x80;
|
||||
regs.p.z = x == 0;
|
||||
return x;
|
||||
}
|
||||
|
||||
uint8 SMP::op_ror(uint8 x) {
|
||||
unsigned carry = (unsigned)regs.p.c << 7;
|
||||
regs.p.c = x & 0x01;
|
||||
x = carry | (x >> 1);
|
||||
regs.p.n = x & 0x80;
|
||||
regs.p.z = x == 0;
|
||||
return x;
|
||||
}
|
105
bsnes/snes/alt/smp/core.cpp
Executable file
105
bsnes/snes/alt/smp/core.cpp
Executable file
@@ -0,0 +1,105 @@
|
||||
void SMP::tick() {
|
||||
timer0.tick();
|
||||
timer1.tick();
|
||||
timer2.tick();
|
||||
|
||||
clock += cycle_step_cpu;
|
||||
dsp.clock -= 24;
|
||||
synchronize_dsp();
|
||||
}
|
||||
|
||||
void SMP::op_io() {
|
||||
#if defined(CYCLE_ACCURATE)
|
||||
tick();
|
||||
#endif
|
||||
}
|
||||
|
||||
uint8 SMP::op_read(uint16 addr) {
|
||||
#if defined(CYCLE_ACCURATE)
|
||||
tick();
|
||||
#endif
|
||||
if((addr & 0xfff0) == 0x00f0) return mmio_read(addr);
|
||||
if(addr >= 0xffc0 && status.iplrom_enable) return iplrom[addr & 0x3f];
|
||||
return apuram[addr];
|
||||
}
|
||||
|
||||
void SMP::op_write(uint16 addr, uint8 data) {
|
||||
#if defined(CYCLE_ACCURATE)
|
||||
tick();
|
||||
#endif
|
||||
if((addr & 0xfff0) == 0x00f0) mmio_write(addr, data);
|
||||
apuram[addr] = data; //all writes go to RAM, even MMIO writes
|
||||
}
|
||||
|
||||
void SMP::op_step() {
|
||||
#define op_readpc() op_read(regs.pc++)
|
||||
#define op_readdp(addr) op_read((regs.p.p << 8) + addr)
|
||||
#define op_writedp(addr, data) op_write((regs.p.p << 8) + addr, data)
|
||||
#define op_readaddr(addr) op_read(addr)
|
||||
#define op_writeaddr(addr, data) op_write(addr, data)
|
||||
#define op_readstack() op_read(0x0100 | ++regs.sp)
|
||||
#define op_writestack(data) op_write(0x0100 | regs.sp--, data)
|
||||
static unsigned rd, wr, dp, sp, ya, bit;
|
||||
|
||||
#if defined(CYCLE_ACCURATE)
|
||||
|
||||
if(opcode_cycle == 0) {
|
||||
opcode_number = op_readpc();
|
||||
opcode_cycle++;
|
||||
} else switch(opcode_number) {
|
||||
#include "core/opcycle_misc.cpp"
|
||||
#include "core/opcycle_mov.cpp"
|
||||
#include "core/opcycle_pc.cpp"
|
||||
#include "core/opcycle_read.cpp"
|
||||
#include "core/opcycle_rmw.cpp"
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
unsigned opcode = op_readpc();
|
||||
switch(opcode) {
|
||||
#include "core/op_misc.cpp"
|
||||
#include "core/op_mov.cpp"
|
||||
#include "core/op_pc.cpp"
|
||||
#include "core/op_read.cpp"
|
||||
#include "core/op_rmw.cpp"
|
||||
}
|
||||
|
||||
//TODO: untaken branches should consume less cycles
|
||||
|
||||
timer0.tick(cycle_count_table[opcode]);
|
||||
timer1.tick(cycle_count_table[opcode]);
|
||||
timer2.tick(cycle_count_table[opcode]);
|
||||
|
||||
clock += cycle_table_cpu[opcode];
|
||||
dsp.clock -= cycle_table_dsp[opcode];
|
||||
synchronize_dsp();
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
const unsigned SMP::cycle_count_table[256] = {
|
||||
#define c 12
|
||||
//0 1 2 3 4 5 6 7 8 9 A B C D E F
|
||||
2,8,4,7, 3,4,3,6, 2,6,5,4, 5,4,6,8, //0
|
||||
4,8,4,7, 4,5,5,6, 5,5,6,5, 2,2,4,6, //1
|
||||
2,8,4,7, 3,4,3,6, 2,6,5,4, 5,4,7,4, //2
|
||||
4,8,4,7, 4,5,5,6, 5,5,6,5, 2,2,3,8, //3
|
||||
|
||||
2,8,4,7, 3,4,3,6, 2,6,4,4, 5,4,6,6, //4
|
||||
4,8,4,7, 4,5,5,6, 5,5,4,5, 2,2,4,3, //5
|
||||
2,8,4,7, 3,4,3,6, 2,6,4,4, 5,4,7,5, //6
|
||||
4,8,4,7, 4,5,5,6, 5,5,5,5, 2,2,3,6, //7
|
||||
|
||||
2,8,4,7, 3,4,3,6, 2,6,5,4, 5,2,4,5, //8
|
||||
4,8,4,7, 4,5,5,6, 5,5,5,5, 2,2,c,5, //9
|
||||
3,8,4,7, 3,4,3,6, 2,6,4,4, 5,2,4,4, //A
|
||||
4,8,4,7, 4,5,5,6, 5,5,5,5, 2,2,3,4, //B
|
||||
|
||||
3,8,4,7, 4,5,4,7, 2,5,6,4, 5,2,4,9, //C
|
||||
4,8,4,7, 5,6,6,7, 4,5,5,5, 2,2,8,3, //D
|
||||
2,8,4,7, 3,4,3,6, 2,4,5,3, 4,3,4,1, //E
|
||||
4,8,4,7, 4,5,5,6, 3,4,5,4, 2,2,6,1, //F
|
||||
|
||||
#undef c
|
||||
};
|
1
bsnes/snes/alt/smp/core/cc.sh
Executable file
1
bsnes/snes/alt/smp/core/cc.sh
Executable file
@@ -0,0 +1 @@
|
||||
g++-4.5 -std=gnu++0x -I../../../.. -o generate generate.cpp
|
154
bsnes/snes/alt/smp/core/generate.cpp
Executable file
154
bsnes/snes/alt/smp/core/generate.cpp
Executable file
@@ -0,0 +1,154 @@
|
||||
#include <nall/file.hpp>
|
||||
#include <nall/stdint.hpp>
|
||||
#include <nall/string.hpp>
|
||||
using namespace nall;
|
||||
|
||||
static bool cycle_accurate;
|
||||
|
||||
struct opcode_t {
|
||||
string name;
|
||||
lstring args;
|
||||
unsigned opcode;
|
||||
};
|
||||
|
||||
void generate(const char *sourceFilename, const char *targetFilename) {
|
||||
file fp;
|
||||
fp.open(targetFilename, file::mode::write);
|
||||
|
||||
string filedata;
|
||||
filedata.readfile(sourceFilename);
|
||||
filedata.replace("\r", "");
|
||||
|
||||
lstring block;
|
||||
block.split("\n\n", filedata);
|
||||
|
||||
foreach(data, block) {
|
||||
lstring lines;
|
||||
lines.split("\n", data);
|
||||
|
||||
linear_vector<opcode_t> array;
|
||||
|
||||
unsigned sourceStart = 0;
|
||||
foreach(line, lines, currentLine) {
|
||||
line.transform("()", "``");
|
||||
lstring part;
|
||||
part.split("`", line);
|
||||
lstring arguments;
|
||||
arguments.split(", ", part[1]);
|
||||
|
||||
opcode_t opcode;
|
||||
opcode.name = part[0];
|
||||
opcode.args = arguments;
|
||||
opcode.opcode = hex(arguments[0]);
|
||||
array.append(opcode);
|
||||
|
||||
line.rtrim<1>(",");
|
||||
if(line.endswith(" {")) {
|
||||
line.rtrim<1>("{ ");
|
||||
sourceStart = currentLine + 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(cycle_accurate == false) {
|
||||
foreach(opcode, array) {
|
||||
fp.print("case 0x", hex<2>(opcode.opcode), ": {\n");
|
||||
|
||||
for(unsigned n = sourceStart; n < lines.size(); n++) {
|
||||
if(lines[n] == "}") break;
|
||||
|
||||
string output;
|
||||
|
||||
if(lines[n].beginswith(" ")) {
|
||||
output = lines[n];
|
||||
} else {
|
||||
lstring part;
|
||||
part.split<1>(":", lines[n]);
|
||||
output = { " ", part[1] };
|
||||
}
|
||||
|
||||
output.replace("$1", opcode.args[1]);
|
||||
output.replace("$2", opcode.args[2]);
|
||||
output.replace("$3", opcode.args[3]);
|
||||
output.replace("$4", opcode.args[4]);
|
||||
output.replace("$5", opcode.args[5]);
|
||||
output.replace("$6", opcode.args[6]);
|
||||
output.replace("$7", opcode.args[7]);
|
||||
output.replace("$8", opcode.args[8]);
|
||||
output.replace("end;", "break;");
|
||||
|
||||
fp.print(output, "\n");
|
||||
}
|
||||
|
||||
fp.print(" break;\n");
|
||||
fp.print("}\n\n");
|
||||
}
|
||||
} else {
|
||||
foreach(opcode, array) {
|
||||
fp.print("case 0x", hex<2>(opcode.opcode), ": {\n");
|
||||
fp.print(" switch(opcode_cycle++) {\n");
|
||||
|
||||
for(unsigned n = sourceStart; n < lines.size(); n++) {
|
||||
if(lines[n] == "}") break;
|
||||
|
||||
bool nextLineEndsCycle = false;
|
||||
if(lines[n + 1] == "}") nextLineEndsCycle = true;
|
||||
if(lines[n + 1].beginswith(" ") == false) nextLineEndsCycle = true;
|
||||
|
||||
string output;
|
||||
|
||||
if(lines[n].beginswith(" ")) {
|
||||
output = { " ", lines[n] };
|
||||
} else {
|
||||
lstring part;
|
||||
part.split<1>(":", lines[n]);
|
||||
fp.print(" case ", (unsigned)decimal(part[0]), ":\n");
|
||||
output = { " ", part[1] };
|
||||
}
|
||||
|
||||
output.replace("$1", opcode.args[1]);
|
||||
output.replace("$2", opcode.args[2]);
|
||||
output.replace("$3", opcode.args[3]);
|
||||
output.replace("$4", opcode.args[4]);
|
||||
output.replace("$5", opcode.args[5]);
|
||||
output.replace("$6", opcode.args[6]);
|
||||
output.replace("$7", opcode.args[7]);
|
||||
output.replace("$8", opcode.args[8]);
|
||||
output.replace("end;", "{ opcode_cycle = 0; break; }");
|
||||
|
||||
fp.print(output, "\n");
|
||||
if(nextLineEndsCycle) {
|
||||
if(lines[n + 1].beginswith("}")) {
|
||||
fp.print(" opcode_cycle = 0;\n");
|
||||
}
|
||||
fp.print(" break;\n");
|
||||
}
|
||||
}
|
||||
|
||||
fp.print(" }\n");
|
||||
fp.print(" break;\n");
|
||||
fp.print("}\n\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fp.close();
|
||||
}
|
||||
|
||||
int main() {
|
||||
cycle_accurate = false;
|
||||
generate("op_misc.b", "op_misc.cpp");
|
||||
generate("op_mov.b", "op_mov.cpp" );
|
||||
generate("op_pc.b", "op_pc.cpp" );
|
||||
generate("op_read.b", "op_read.cpp");
|
||||
generate("op_rmw.b", "op_rmw.cpp" );
|
||||
|
||||
cycle_accurate = true;
|
||||
generate("op_misc.b", "opcycle_misc.cpp");
|
||||
generate("op_mov.b", "opcycle_mov.cpp" );
|
||||
generate("op_pc.b", "opcycle_pc.cpp" );
|
||||
generate("op_read.b", "opcycle_read.cpp");
|
||||
generate("op_rmw.b", "opcycle_rmw.cpp" );
|
||||
|
||||
return 0;
|
||||
}
|
163
bsnes/snes/alt/smp/core/op_misc.b
Executable file
163
bsnes/snes/alt/smp/core/op_misc.b
Executable file
@@ -0,0 +1,163 @@
|
||||
nop(0x00) {
|
||||
1:op_io();
|
||||
}
|
||||
|
||||
sleep(0xef),
|
||||
stop(0xff) {
|
||||
1:op_io();
|
||||
2:op_io();
|
||||
regs.pc--;
|
||||
}
|
||||
|
||||
xcn(0x9f) {
|
||||
1:op_io();
|
||||
2:op_io();
|
||||
3:op_io();
|
||||
4:op_io();
|
||||
regs.a = (regs.a >> 4) | (regs.a << 4);
|
||||
regs.p.n = !!(regs.a & 0x80);
|
||||
regs.p.z = (regs.a == 0);
|
||||
}
|
||||
|
||||
daa(0xdf) {
|
||||
1:op_io();
|
||||
2:op_io();
|
||||
if(regs.p.c || (regs.a) > 0x99) {
|
||||
regs.a += 0x60;
|
||||
regs.p.c = 1;
|
||||
}
|
||||
if(regs.p.h || (regs.a & 15) > 0x09) {
|
||||
regs.a += 0x06;
|
||||
}
|
||||
regs.p.n = !!(regs.a & 0x80);
|
||||
regs.p.z = (regs.a == 0);
|
||||
}
|
||||
|
||||
das(0xbe) {
|
||||
1:op_io();
|
||||
2:op_io();
|
||||
if(!regs.p.c || (regs.a) > 0x99) {
|
||||
regs.a -= 0x60;
|
||||
regs.p.c = 0;
|
||||
}
|
||||
if(!regs.p.h || (regs.a & 15) > 0x09) {
|
||||
regs.a -= 0x06;
|
||||
}
|
||||
regs.p.n = !!(regs.a & 0x80);
|
||||
regs.p.z = (regs.a == 0);
|
||||
}
|
||||
|
||||
clrc(0x60, regs.p.c = 0),
|
||||
clrp(0x20, regs.p.p = 0),
|
||||
setc(0x80, regs.p.c = 1),
|
||||
setp(0x40, regs.p.p = 1) {
|
||||
1:op_io();
|
||||
$1;
|
||||
}
|
||||
|
||||
clrv(0xe0) {
|
||||
1:op_io();
|
||||
regs.p.v = 0;
|
||||
regs.p.h = 0;
|
||||
}
|
||||
|
||||
notc(0xed) {
|
||||
1:op_io();
|
||||
2:op_io();
|
||||
regs.p.c = !regs.p.c;
|
||||
}
|
||||
|
||||
ei(0xa0, 1),
|
||||
di(0xc0, 0) {
|
||||
1:op_io();
|
||||
2:op_io();
|
||||
regs.p.i = $1;
|
||||
}
|
||||
|
||||
set0_dp(0x02, rd |= 0x01),
|
||||
clr0_dp(0x12, rd &= ~0x01),
|
||||
set1_dp(0x22, rd |= 0x02),
|
||||
clr1_dp(0x32, rd &= ~0x02),
|
||||
set2_dp(0x42, rd |= 0x04),
|
||||
clr2_dp(0x52, rd &= ~0x04),
|
||||
set3_dp(0x62, rd |= 0x08),
|
||||
clr3_dp(0x72, rd &= ~0x08),
|
||||
set4_dp(0x82, rd |= 0x10),
|
||||
clr4_dp(0x92, rd &= ~0x10),
|
||||
set5_dp(0xa2, rd |= 0x20),
|
||||
clr5_dp(0xb2, rd &= ~0x20),
|
||||
set6_dp(0xc2, rd |= 0x40),
|
||||
clr6_dp(0xd2, rd &= ~0x40),
|
||||
set7_dp(0xe2, rd |= 0x80),
|
||||
clr7_dp(0xf2, rd &= ~0x80) {
|
||||
1:dp = op_readpc();
|
||||
2:rd = op_readdp(dp);
|
||||
3:$1;
|
||||
op_writedp(dp, rd);
|
||||
}
|
||||
|
||||
push_a(0x2d, a),
|
||||
push_x(0x4d, x),
|
||||
push_y(0x6d, y),
|
||||
push_p(0x0d, p) {
|
||||
1:op_io();
|
||||
2:op_io();
|
||||
3:op_writestack(regs.$1);
|
||||
}
|
||||
|
||||
pop_a(0xae, a),
|
||||
pop_x(0xce, x),
|
||||
pop_y(0xee, y),
|
||||
pop_p(0x8e, p) {
|
||||
1:op_io();
|
||||
2:op_io();
|
||||
3:regs.$1 = op_readstack();
|
||||
}
|
||||
|
||||
mul_ya(0xcf) {
|
||||
1:op_io();
|
||||
2:op_io();
|
||||
3:op_io();
|
||||
4:op_io();
|
||||
5:op_io();
|
||||
6:op_io();
|
||||
7:op_io();
|
||||
8:op_io();
|
||||
ya = regs.y * regs.a;
|
||||
regs.a = ya;
|
||||
regs.y = ya >> 8;
|
||||
//result is set based on y (high-byte) only
|
||||
regs.p.n = !!(regs.y & 0x80);
|
||||
regs.p.z = (regs.y == 0);
|
||||
}
|
||||
|
||||
div_ya_x(0x9e) {
|
||||
1:op_io();
|
||||
2:op_io();
|
||||
3:op_io();
|
||||
4:op_io();
|
||||
5:op_io();
|
||||
6:op_io();
|
||||
7:op_io();
|
||||
8:op_io();
|
||||
9:op_io();
|
||||
10:op_io();
|
||||
11:op_io();
|
||||
ya = regs.ya;
|
||||
//overflow set if quotient >= 256
|
||||
regs.p.v = !!(regs.y >= regs.x);
|
||||
regs.p.h = !!((regs.y & 15) >= (regs.x & 15));
|
||||
if(regs.y < (regs.x << 1)) {
|
||||
//if quotient is <= 511 (will fit into 9-bit result)
|
||||
regs.a = ya / regs.x;
|
||||
regs.y = ya % regs.x;
|
||||
} else {
|
||||
//otherwise, the quotient won't fit into regs.p.v + regs.a
|
||||
//this emulates the odd behavior of the S-SMP in this case
|
||||
regs.a = 255 - (ya - (regs.x << 9)) / (256 - regs.x);
|
||||
regs.y = regs.x + (ya - (regs.x << 9)) % (256 - regs.x);
|
||||
}
|
||||
//result is set based on a (quotient) only
|
||||
regs.p.n = !!(regs.a & 0x80);
|
||||
regs.p.z = (regs.a == 0);
|
||||
}
|
346
bsnes/snes/alt/smp/core/op_misc.cpp
Executable file
346
bsnes/snes/alt/smp/core/op_misc.cpp
Executable file
@@ -0,0 +1,346 @@
|
||||
case 0x00: {
|
||||
op_io();
|
||||
break;
|
||||
}
|
||||
|
||||
case 0xef: {
|
||||
op_io();
|
||||
op_io();
|
||||
regs.pc--;
|
||||
break;
|
||||
}
|
||||
|
||||
case 0xff: {
|
||||
op_io();
|
||||
op_io();
|
||||
regs.pc--;
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x9f: {
|
||||
op_io();
|
||||
op_io();
|
||||
op_io();
|
||||
op_io();
|
||||
regs.a = (regs.a >> 4) | (regs.a << 4);
|
||||
regs.p.n = !!(regs.a & 0x80);
|
||||
regs.p.z = (regs.a == 0);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0xdf: {
|
||||
op_io();
|
||||
op_io();
|
||||
if(regs.p.c || (regs.a) > 0x99) {
|
||||
regs.a += 0x60;
|
||||
regs.p.c = 1;
|
||||
}
|
||||
if(regs.p.h || (regs.a & 15) > 0x09) {
|
||||
regs.a += 0x06;
|
||||
}
|
||||
regs.p.n = !!(regs.a & 0x80);
|
||||
regs.p.z = (regs.a == 0);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0xbe: {
|
||||
op_io();
|
||||
op_io();
|
||||
if(!regs.p.c || (regs.a) > 0x99) {
|
||||
regs.a -= 0x60;
|
||||
regs.p.c = 0;
|
||||
}
|
||||
if(!regs.p.h || (regs.a & 15) > 0x09) {
|
||||
regs.a -= 0x06;
|
||||
}
|
||||
regs.p.n = !!(regs.a & 0x80);
|
||||
regs.p.z = (regs.a == 0);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x60: {
|
||||
op_io();
|
||||
regs.p.c = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x20: {
|
||||
op_io();
|
||||
regs.p.p = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x80: {
|
||||
op_io();
|
||||
regs.p.c = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x40: {
|
||||
op_io();
|
||||
regs.p.p = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
case 0xe0: {
|
||||
op_io();
|
||||
regs.p.v = 0;
|
||||
regs.p.h = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
case 0xed: {
|
||||
op_io();
|
||||
op_io();
|
||||
regs.p.c = !regs.p.c;
|
||||
break;
|
||||
}
|
||||
|
||||
case 0xa0: {
|
||||
op_io();
|
||||
op_io();
|
||||
regs.p.i = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
case 0xc0: {
|
||||
op_io();
|
||||
op_io();
|
||||
regs.p.i = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x02: {
|
||||
dp = op_readpc();
|
||||
rd = op_readdp(dp);
|
||||
rd |= 0x01;
|
||||
op_writedp(dp, rd);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x12: {
|
||||
dp = op_readpc();
|
||||
rd = op_readdp(dp);
|
||||
rd &= ~0x01;
|
||||
op_writedp(dp, rd);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x22: {
|
||||
dp = op_readpc();
|
||||
rd = op_readdp(dp);
|
||||
rd |= 0x02;
|
||||
op_writedp(dp, rd);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x32: {
|
||||
dp = op_readpc();
|
||||
rd = op_readdp(dp);
|
||||
rd &= ~0x02;
|
||||
op_writedp(dp, rd);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x42: {
|
||||
dp = op_readpc();
|
||||
rd = op_readdp(dp);
|
||||
rd |= 0x04;
|
||||
op_writedp(dp, rd);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x52: {
|
||||
dp = op_readpc();
|
||||
rd = op_readdp(dp);
|
||||
rd &= ~0x04;
|
||||
op_writedp(dp, rd);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x62: {
|
||||
dp = op_readpc();
|
||||
rd = op_readdp(dp);
|
||||
rd |= 0x08;
|
||||
op_writedp(dp, rd);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x72: {
|
||||
dp = op_readpc();
|
||||
rd = op_readdp(dp);
|
||||
rd &= ~0x08;
|
||||
op_writedp(dp, rd);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x82: {
|
||||
dp = op_readpc();
|
||||
rd = op_readdp(dp);
|
||||
rd |= 0x10;
|
||||
op_writedp(dp, rd);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x92: {
|
||||
dp = op_readpc();
|
||||
rd = op_readdp(dp);
|
||||
rd &= ~0x10;
|
||||
op_writedp(dp, rd);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0xa2: {
|
||||
dp = op_readpc();
|
||||
rd = op_readdp(dp);
|
||||
rd |= 0x20;
|
||||
op_writedp(dp, rd);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0xb2: {
|
||||
dp = op_readpc();
|
||||
rd = op_readdp(dp);
|
||||
rd &= ~0x20;
|
||||
op_writedp(dp, rd);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0xc2: {
|
||||
dp = op_readpc();
|
||||
rd = op_readdp(dp);
|
||||
rd |= 0x40;
|
||||
op_writedp(dp, rd);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0xd2: {
|
||||
dp = op_readpc();
|
||||
rd = op_readdp(dp);
|
||||
rd &= ~0x40;
|
||||
op_writedp(dp, rd);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0xe2: {
|
||||
dp = op_readpc();
|
||||
rd = op_readdp(dp);
|
||||
rd |= 0x80;
|
||||
op_writedp(dp, rd);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0xf2: {
|
||||
dp = op_readpc();
|
||||
rd = op_readdp(dp);
|
||||
rd &= ~0x80;
|
||||
op_writedp(dp, rd);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x2d: {
|
||||
op_io();
|
||||
op_io();
|
||||
op_writestack(regs.a);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x4d: {
|
||||
op_io();
|
||||
op_io();
|
||||
op_writestack(regs.x);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x6d: {
|
||||
op_io();
|
||||
op_io();
|
||||
op_writestack(regs.y);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x0d: {
|
||||
op_io();
|
||||
op_io();
|
||||
op_writestack(regs.p);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0xae: {
|
||||
op_io();
|
||||
op_io();
|
||||
regs.a = op_readstack();
|
||||
break;
|
||||
}
|
||||
|
||||
case 0xce: {
|
||||
op_io();
|
||||
op_io();
|
||||
regs.x = op_readstack();
|
||||
break;
|
||||
}
|
||||
|
||||
case 0xee: {
|
||||
op_io();
|
||||
op_io();
|
||||
regs.y = op_readstack();
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x8e: {
|
||||
op_io();
|
||||
op_io();
|
||||
regs.p = op_readstack();
|
||||
break;
|
||||
}
|
||||
|
||||
case 0xcf: {
|
||||
op_io();
|
||||
op_io();
|
||||
op_io();
|
||||
op_io();
|
||||
op_io();
|
||||
op_io();
|
||||
op_io();
|
||||
op_io();
|
||||
ya = regs.y * regs.a;
|
||||
regs.a = ya;
|
||||
regs.y = ya >> 8;
|
||||
//result is set based on y (high-byte) only
|
||||
regs.p.n = !!(regs.y & 0x80);
|
||||
regs.p.z = (regs.y == 0);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x9e: {
|
||||
op_io();
|
||||
op_io();
|
||||
op_io();
|
||||
op_io();
|
||||
op_io();
|
||||
op_io();
|
||||
op_io();
|
||||
op_io();
|
||||
op_io();
|
||||
op_io();
|
||||
op_io();
|
||||
ya = regs.ya;
|
||||
//overflow set if quotient >= 256
|
||||
regs.p.v = !!(regs.y >= regs.x);
|
||||
regs.p.h = !!((regs.y & 15) >= (regs.x & 15));
|
||||
if(regs.y < (regs.x << 1)) {
|
||||
//if quotient is <= 511 (will fit into 9-bit result)
|
||||
regs.a = ya / regs.x;
|
||||
regs.y = ya % regs.x;
|
||||
} else {
|
||||
//otherwise, the quotient won't fit into regs.p.v + regs.a
|
||||
//this emulates the odd behavior of the S-SMP in this case
|
||||
regs.a = 255 - (ya - (regs.x << 9)) / (256 - regs.x);
|
||||
regs.y = regs.x + (ya - (regs.x << 9)) % (256 - regs.x);
|
||||
}
|
||||
//result is set based on a (quotient) only
|
||||
regs.p.n = !!(regs.a & 0x80);
|
||||
regs.p.z = (regs.a == 0);
|
||||
break;
|
||||
}
|
||||
|
217
bsnes/snes/alt/smp/core/op_mov.b
Executable file
217
bsnes/snes/alt/smp/core/op_mov.b
Executable file
@@ -0,0 +1,217 @@
|
||||
mov_a_x(0x7d, a, x),
|
||||
mov_a_y(0xdd, a, y),
|
||||
mov_x_a(0x5d, x, a),
|
||||
mov_y_a(0xfd, y, a),
|
||||
mov_x_sp(0x9d, x, sp) {
|
||||
1:op_io();
|
||||
regs.$1 = regs.$2;
|
||||
regs.p.n = !!(regs.$1 & 0x80);
|
||||
regs.p.z = (regs.$1 == 0);
|
||||
}
|
||||
|
||||
mov_sp_x(0xbd, sp, x) {
|
||||
1:op_io();
|
||||
regs.$1 = regs.$2;
|
||||
}
|
||||
|
||||
mov_a_const(0xe8, a),
|
||||
mov_x_const(0xcd, x),
|
||||
mov_y_const(0x8d, y) {
|
||||
1:regs.$1 = op_readpc();
|
||||
regs.p.n = !!(regs.$1 & 0x80);
|
||||
regs.p.z = (regs.$1 == 0);
|
||||
}
|
||||
|
||||
mov_a_ix(0xe6) {
|
||||
1:op_io();
|
||||
2:regs.a = op_readdp(regs.x);
|
||||
regs.p.n = !!(regs.a & 0x80);
|
||||
regs.p.z = (regs.a == 0);
|
||||
}
|
||||
|
||||
mov_a_ixinc(0xbf) {
|
||||
1:op_io();
|
||||
2:regs.a = op_readdp(regs.x++);
|
||||
3:op_io();
|
||||
regs.p.n = !!(regs.a & 0x80);
|
||||
regs.p.z = (regs.a == 0);
|
||||
}
|
||||
|
||||
mov_a_dp(0xe4, a),
|
||||
mov_x_dp(0xf8, x),
|
||||
mov_y_dp(0xeb, y) {
|
||||
1:sp = op_readpc();
|
||||
2:regs.$1 = op_readdp(sp);
|
||||
regs.p.n = !!(regs.$1 & 0x80);
|
||||
regs.p.z = (regs.$1 == 0);
|
||||
}
|
||||
|
||||
mov_a_dpx(0xf4, a, x),
|
||||
mov_x_dpy(0xf9, x, y),
|
||||
mov_y_dpx(0xfb, y, x) {
|
||||
1:sp = op_readpc();
|
||||
2:op_io();
|
||||
3:regs.$1 = op_readdp(sp + regs.$2);
|
||||
regs.p.n = !!(regs.$1 & 0x80);
|
||||
regs.p.z = (regs.$1 == 0);
|
||||
}
|
||||
|
||||
mov_a_addr(0xe5, a),
|
||||
mov_x_addr(0xe9, x),
|
||||
mov_y_addr(0xec, y) {
|
||||
1:sp = op_readpc();
|
||||
2:sp |= op_readpc() << 8;
|
||||
3:regs.$1 = op_readaddr(sp);
|
||||
regs.p.n = !!(regs.$1 & 0x80);
|
||||
regs.p.z = (regs.$1 == 0);
|
||||
}
|
||||
|
||||
mov_a_addrx(0xf5, x),
|
||||
mov_a_addry(0xf6, y) {
|
||||
1:sp = op_readpc();
|
||||
2:sp |= op_readpc() << 8;
|
||||
3:op_io();
|
||||
4:regs.a = op_readaddr(sp + regs.$1);
|
||||
regs.p.n = !!(regs.a & 0x80);
|
||||
regs.p.z = (regs.a == 0);
|
||||
}
|
||||
|
||||
mov_a_idpx(0xe7) {
|
||||
1:dp = op_readpc() + regs.x;
|
||||
2:op_io();
|
||||
3:sp = op_readdp(dp);
|
||||
4:sp |= op_readdp(dp + 1) << 8;
|
||||
5:regs.a = op_readaddr(sp);
|
||||
regs.p.n = !!(regs.a & 0x80);
|
||||
regs.p.z = (regs.a == 0);
|
||||
}
|
||||
|
||||
mov_a_idpy(0xf7) {
|
||||
1:dp = op_readpc();
|
||||
2:op_io();
|
||||
3:sp = op_readdp(dp);
|
||||
4:sp |= op_readdp(dp + 1) << 8;
|
||||
5:regs.a = op_readaddr(sp + regs.y);
|
||||
regs.p.n = !!(regs.a & 0x80);
|
||||
regs.p.z = (regs.a == 0);
|
||||
}
|
||||
|
||||
mov_dp_dp(0xfa) {
|
||||
1:sp = op_readpc();
|
||||
2:rd = op_readdp(sp);
|
||||
3:dp = op_readpc();
|
||||
4:op_writedp(dp, rd);
|
||||
}
|
||||
|
||||
mov_dp_const(0x8f) {
|
||||
1:rd = op_readpc();
|
||||
2:dp = op_readpc();
|
||||
3:op_readdp(dp);
|
||||
4:op_writedp(dp, rd);
|
||||
}
|
||||
|
||||
mov_ix_a(0xc6) {
|
||||
1:op_io();
|
||||
2:op_readdp(regs.x);
|
||||
3:op_writedp(regs.x, regs.a);
|
||||
}
|
||||
|
||||
mov_ixinc_a(0xaf) {
|
||||
1:op_io();
|
||||
2:op_io();
|
||||
3:op_writedp(regs.x++, regs.a);
|
||||
}
|
||||
|
||||
mov_dp_a(0xc4, a),
|
||||
mov_dp_x(0xd8, x),
|
||||
mov_dp_y(0xcb, y) {
|
||||
1:dp = op_readpc();
|
||||
2:op_readdp(dp);
|
||||
3:op_writedp(dp, regs.$1);
|
||||
}
|
||||
|
||||
mov_dpx_a(0xd4, x, a),
|
||||
mov_dpy_x(0xd9, y, x),
|
||||
mov_dpx_y(0xdb, x, y) {
|
||||
1:dp = op_readpc();
|
||||
2:op_io();
|
||||
dp += regs.$1;
|
||||
3:op_readdp(dp);
|
||||
4:op_writedp(dp, regs.$2);
|
||||
}
|
||||
|
||||
mov_addr_a(0xc5, a),
|
||||
mov_addr_x(0xc9, x),
|
||||
mov_addr_y(0xcc, y) {
|
||||
1:dp = op_readpc();
|
||||
2:dp |= op_readpc() << 8;
|
||||
3:op_readaddr(dp);
|
||||
4:op_writeaddr(dp, regs.$1);
|
||||
}
|
||||
|
||||
mov_addrx_a(0xd5, x),
|
||||
mov_addry_a(0xd6, y) {
|
||||
1:dp = op_readpc();
|
||||
2:dp |= op_readpc() << 8;
|
||||
3:op_io();
|
||||
dp += regs.$1;
|
||||
4:op_readaddr(dp);
|
||||
5:op_writeaddr(dp, regs.a);
|
||||
}
|
||||
|
||||
mov_idpx_a(0xc7) {
|
||||
1:sp = op_readpc();
|
||||
2:op_io();
|
||||
sp += regs.x;
|
||||
3:dp = op_readdp(sp);
|
||||
4:dp |= op_readdp(sp + 1) << 8;
|
||||
5:op_readaddr(dp);
|
||||
6:op_writeaddr(dp, regs.a);
|
||||
}
|
||||
|
||||
mov_idpy_a(0xd7) {
|
||||
1:sp = op_readpc();
|
||||
2:dp = op_readdp(sp);
|
||||
3:dp |= op_readdp(sp + 1) << 8;
|
||||
4:op_io();
|
||||
dp += regs.y;
|
||||
5:op_readaddr(dp);
|
||||
6:op_writeaddr(dp, regs.a);
|
||||
}
|
||||
|
||||
movw_ya_dp(0xba) {
|
||||
1:sp = op_readpc();
|
||||
2:regs.a = op_readdp(sp);
|
||||
3:op_io();
|
||||
4:regs.y = op_readdp(sp + 1);
|
||||
regs.p.n = !!(regs.ya & 0x8000);
|
||||
regs.p.z = (regs.ya == 0);
|
||||
}
|
||||
|
||||
movw_dp_ya(0xda) {
|
||||
1:dp = op_readpc();
|
||||
2:op_readdp(dp);
|
||||
3:op_writedp(dp, regs.a);
|
||||
4:op_writedp(dp + 1, regs.y);
|
||||
}
|
||||
|
||||
mov1_c_bit(0xaa) {
|
||||
1:sp = op_readpc();
|
||||
2:sp |= op_readpc() << 8;
|
||||
3:bit = sp >> 13;
|
||||
sp &= 0x1fff;
|
||||
rd = op_readaddr(sp);
|
||||
regs.p.c = !!(rd & (1 << bit));
|
||||
}
|
||||
|
||||
mov1_bit_c(0xca) {
|
||||
1:dp = op_readpc();
|
||||
2:dp |= op_readpc() << 8;
|
||||
3:bit = dp >> 13;
|
||||
dp &= 0x1fff;
|
||||
rd = op_readaddr(dp);
|
||||
if(regs.p.c)rd |= (1 << bit);
|
||||
else rd &= ~(1 << bit);
|
||||
4:op_io();
|
||||
5:op_writeaddr(dp, rd);
|
||||
}
|
389
bsnes/snes/alt/smp/core/op_mov.cpp
Executable file
389
bsnes/snes/alt/smp/core/op_mov.cpp
Executable file
@@ -0,0 +1,389 @@
|
||||
case 0x7d: {
|
||||
op_io();
|
||||
regs.a = regs.x;
|
||||
regs.p.n = !!(regs.a & 0x80);
|
||||
regs.p.z = (regs.a == 0);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0xdd: {
|
||||
op_io();
|
||||
regs.a = regs.y;
|
||||
regs.p.n = !!(regs.a & 0x80);
|
||||
regs.p.z = (regs.a == 0);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x5d: {
|
||||
op_io();
|
||||
regs.x = regs.a;
|
||||
regs.p.n = !!(regs.x & 0x80);
|
||||
regs.p.z = (regs.x == 0);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0xfd: {
|
||||
op_io();
|
||||
regs.y = regs.a;
|
||||
regs.p.n = !!(regs.y & 0x80);
|
||||
regs.p.z = (regs.y == 0);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x9d: {
|
||||
op_io();
|
||||
regs.x = regs.sp;
|
||||
regs.p.n = !!(regs.x & 0x80);
|
||||
regs.p.z = (regs.x == 0);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0xbd: {
|
||||
op_io();
|
||||
regs.sp = regs.x;
|
||||
break;
|
||||
}
|
||||
|
||||
case 0xe8: {
|
||||
regs.a = op_readpc();
|
||||
regs.p.n = !!(regs.a & 0x80);
|
||||
regs.p.z = (regs.a == 0);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0xcd: {
|
||||
regs.x = op_readpc();
|
||||
regs.p.n = !!(regs.x & 0x80);
|
||||
regs.p.z = (regs.x == 0);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x8d: {
|
||||
regs.y = op_readpc();
|
||||
regs.p.n = !!(regs.y & 0x80);
|
||||
regs.p.z = (regs.y == 0);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0xe6: {
|
||||
op_io();
|
||||
regs.a = op_readdp(regs.x);
|
||||
regs.p.n = !!(regs.a & 0x80);
|
||||
regs.p.z = (regs.a == 0);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0xbf: {
|
||||
op_io();
|
||||
regs.a = op_readdp(regs.x++);
|
||||
op_io();
|
||||
regs.p.n = !!(regs.a & 0x80);
|
||||
regs.p.z = (regs.a == 0);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0xe4: {
|
||||
sp = op_readpc();
|
||||
regs.a = op_readdp(sp);
|
||||
regs.p.n = !!(regs.a & 0x80);
|
||||
regs.p.z = (regs.a == 0);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0xf8: {
|
||||
sp = op_readpc();
|
||||
regs.x = op_readdp(sp);
|
||||
regs.p.n = !!(regs.x & 0x80);
|
||||
regs.p.z = (regs.x == 0);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0xeb: {
|
||||
sp = op_readpc();
|
||||
regs.y = op_readdp(sp);
|
||||
regs.p.n = !!(regs.y & 0x80);
|
||||
regs.p.z = (regs.y == 0);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0xf4: {
|
||||
sp = op_readpc();
|
||||
op_io();
|
||||
regs.a = op_readdp(sp + regs.x);
|
||||
regs.p.n = !!(regs.a & 0x80);
|
||||
regs.p.z = (regs.a == 0);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0xf9: {
|
||||
sp = op_readpc();
|
||||
op_io();
|
||||
regs.x = op_readdp(sp + regs.y);
|
||||
regs.p.n = !!(regs.x & 0x80);
|
||||
regs.p.z = (regs.x == 0);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0xfb: {
|
||||
sp = op_readpc();
|
||||
op_io();
|
||||
regs.y = op_readdp(sp + regs.x);
|
||||
regs.p.n = !!(regs.y & 0x80);
|
||||
regs.p.z = (regs.y == 0);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0xe5: {
|
||||
sp = op_readpc();
|
||||
sp |= op_readpc() << 8;
|
||||
regs.a = op_readaddr(sp);
|
||||
regs.p.n = !!(regs.a & 0x80);
|
||||
regs.p.z = (regs.a == 0);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0xe9: {
|
||||
sp = op_readpc();
|
||||
sp |= op_readpc() << 8;
|
||||
regs.x = op_readaddr(sp);
|
||||
regs.p.n = !!(regs.x & 0x80);
|
||||
regs.p.z = (regs.x == 0);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0xec: {
|
||||
sp = op_readpc();
|
||||
sp |= op_readpc() << 8;
|
||||
regs.y = op_readaddr(sp);
|
||||
regs.p.n = !!(regs.y & 0x80);
|
||||
regs.p.z = (regs.y == 0);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0xf5: {
|
||||
sp = op_readpc();
|
||||
sp |= op_readpc() << 8;
|
||||
op_io();
|
||||
regs.a = op_readaddr(sp + regs.x);
|
||||
regs.p.n = !!(regs.a & 0x80);
|
||||
regs.p.z = (regs.a == 0);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0xf6: {
|
||||
sp = op_readpc();
|
||||
sp |= op_readpc() << 8;
|
||||
op_io();
|
||||
regs.a = op_readaddr(sp + regs.y);
|
||||
regs.p.n = !!(regs.a & 0x80);
|
||||
regs.p.z = (regs.a == 0);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0xe7: {
|
||||
dp = op_readpc() + regs.x;
|
||||
op_io();
|
||||
sp = op_readdp(dp);
|
||||
sp |= op_readdp(dp + 1) << 8;
|
||||
regs.a = op_readaddr(sp);
|
||||
regs.p.n = !!(regs.a & 0x80);
|
||||
regs.p.z = (regs.a == 0);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0xf7: {
|
||||
dp = op_readpc();
|
||||
op_io();
|
||||
sp = op_readdp(dp);
|
||||
sp |= op_readdp(dp + 1) << 8;
|
||||
regs.a = op_readaddr(sp + regs.y);
|
||||
regs.p.n = !!(regs.a & 0x80);
|
||||
regs.p.z = (regs.a == 0);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0xfa: {
|
||||
sp = op_readpc();
|
||||
rd = op_readdp(sp);
|
||||
dp = op_readpc();
|
||||
op_writedp(dp, rd);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x8f: {
|
||||
rd = op_readpc();
|
||||
dp = op_readpc();
|
||||
op_readdp(dp);
|
||||
op_writedp(dp, rd);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0xc6: {
|
||||
op_io();
|
||||
op_readdp(regs.x);
|
||||
op_writedp(regs.x, regs.a);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0xaf: {
|
||||
op_io();
|
||||
op_io();
|
||||
op_writedp(regs.x++, regs.a);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0xc4: {
|
||||
dp = op_readpc();
|
||||
op_readdp(dp);
|
||||
op_writedp(dp, regs.a);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0xd8: {
|
||||
dp = op_readpc();
|
||||
op_readdp(dp);
|
||||
op_writedp(dp, regs.x);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0xcb: {
|
||||
dp = op_readpc();
|
||||
op_readdp(dp);
|
||||
op_writedp(dp, regs.y);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0xd4: {
|
||||
dp = op_readpc();
|
||||
op_io();
|
||||
dp += regs.x;
|
||||
op_readdp(dp);
|
||||
op_writedp(dp, regs.a);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0xd9: {
|
||||
dp = op_readpc();
|
||||
op_io();
|
||||
dp += regs.y;
|
||||
op_readdp(dp);
|
||||
op_writedp(dp, regs.x);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0xdb: {
|
||||
dp = op_readpc();
|
||||
op_io();
|
||||
dp += regs.x;
|
||||
op_readdp(dp);
|
||||
op_writedp(dp, regs.y);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0xc5: {
|
||||
dp = op_readpc();
|
||||
dp |= op_readpc() << 8;
|
||||
op_readaddr(dp);
|
||||
op_writeaddr(dp, regs.a);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0xc9: {
|
||||
dp = op_readpc();
|
||||
dp |= op_readpc() << 8;
|
||||
op_readaddr(dp);
|
||||
op_writeaddr(dp, regs.x);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0xcc: {
|
||||
dp = op_readpc();
|
||||
dp |= op_readpc() << 8;
|
||||
op_readaddr(dp);
|
||||
op_writeaddr(dp, regs.y);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0xd5: {
|
||||
dp = op_readpc();
|
||||
dp |= op_readpc() << 8;
|
||||
op_io();
|
||||
dp += regs.x;
|
||||
op_readaddr(dp);
|
||||
op_writeaddr(dp, regs.a);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0xd6: {
|
||||
dp = op_readpc();
|
||||
dp |= op_readpc() << 8;
|
||||
op_io();
|
||||
dp += regs.y;
|
||||
op_readaddr(dp);
|
||||
op_writeaddr(dp, regs.a);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0xc7: {
|
||||
sp = op_readpc();
|
||||
op_io();
|
||||
sp += regs.x;
|
||||
dp = op_readdp(sp);
|
||||
dp |= op_readdp(sp + 1) << 8;
|
||||
op_readaddr(dp);
|
||||
op_writeaddr(dp, regs.a);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0xd7: {
|
||||
sp = op_readpc();
|
||||
dp = op_readdp(sp);
|
||||
dp |= op_readdp(sp + 1) << 8;
|
||||
op_io();
|
||||
dp += regs.y;
|
||||
op_readaddr(dp);
|
||||
op_writeaddr(dp, regs.a);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0xba: {
|
||||
sp = op_readpc();
|
||||
regs.a = op_readdp(sp);
|
||||
op_io();
|
||||
regs.y = op_readdp(sp + 1);
|
||||
regs.p.n = !!(regs.ya & 0x8000);
|
||||
regs.p.z = (regs.ya == 0);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0xda: {
|
||||
dp = op_readpc();
|
||||
op_readdp(dp);
|
||||
op_writedp(dp, regs.a);
|
||||
op_writedp(dp + 1, regs.y);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0xaa: {
|
||||
sp = op_readpc();
|
||||
sp |= op_readpc() << 8;
|
||||
bit = sp >> 13;
|
||||
sp &= 0x1fff;
|
||||
rd = op_readaddr(sp);
|
||||
regs.p.c = !!(rd & (1 << bit));
|
||||
break;
|
||||
}
|
||||
|
||||
case 0xca: {
|
||||
dp = op_readpc();
|
||||
dp |= op_readpc() << 8;
|
||||
bit = dp >> 13;
|
||||
dp &= 0x1fff;
|
||||
rd = op_readaddr(dp);
|
||||
if(regs.p.c)rd |= (1 << bit);
|
||||
else rd &= ~(1 << bit);
|
||||
op_io();
|
||||
op_writeaddr(dp, rd);
|
||||
break;
|
||||
}
|
||||
|
179
bsnes/snes/alt/smp/core/op_pc.b
Executable file
179
bsnes/snes/alt/smp/core/op_pc.b
Executable file
@@ -0,0 +1,179 @@
|
||||
bra(0x2f, 0),
|
||||
beq(0xf0, !regs.p.z),
|
||||
bne(0xd0, regs.p.z),
|
||||
bcs(0xb0, !regs.p.c),
|
||||
bcc(0x90, regs.p.c),
|
||||
bvs(0x70, !regs.p.v),
|
||||
bvc(0x50, regs.p.v),
|
||||
bmi(0x30, !regs.p.n),
|
||||
bpl(0x10, regs.p.n) {
|
||||
1:rd = op_readpc();
|
||||
if($1)end;
|
||||
2:op_io();
|
||||
3:op_io();
|
||||
regs.pc += (int8)rd;
|
||||
}
|
||||
|
||||
bbs0(0x03, 0x01, !=),
|
||||
bbc0(0x13, 0x01, ==),
|
||||
bbs1(0x23, 0x02, !=),
|
||||
bbc1(0x33, 0x02, ==),
|
||||
bbs2(0x43, 0x04, !=),
|
||||
bbc2(0x53, 0x04, ==),
|
||||
bbs3(0x63, 0x08, !=),
|
||||
bbc3(0x73, 0x08, ==),
|
||||
bbs4(0x83, 0x10, !=),
|
||||
bbc4(0x93, 0x10, ==),
|
||||
bbs5(0xa3, 0x20, !=),
|
||||
bbc5(0xb3, 0x20, ==),
|
||||
bbs6(0xc3, 0x40, !=),
|
||||
bbc6(0xd3, 0x40, ==),
|
||||
bbs7(0xe3, 0x80, !=),
|
||||
bbc7(0xf3, 0x80, ==) {
|
||||
1:dp = op_readpc();
|
||||
2:sp = op_readdp(dp);
|
||||
3:rd = op_readpc();
|
||||
4:op_io();
|
||||
if((sp & $1) $2 $1)end;
|
||||
5:op_io();
|
||||
6:op_io();
|
||||
regs.pc += (int8)rd;
|
||||
}
|
||||
|
||||
cbne_dp(0x2e) {
|
||||
1:dp = op_readpc();
|
||||
2:sp = op_readdp(dp);
|
||||
3:rd = op_readpc();
|
||||
4:op_io();
|
||||
if(regs.a == sp)end;
|
||||
5:op_io();
|
||||
6:op_io();
|
||||
regs.pc += (int8)rd;
|
||||
}
|
||||
|
||||
cbne_dpx(0xde) {
|
||||
1:dp = op_readpc();
|
||||
2:op_io();
|
||||
3:sp = op_readdp(dp + regs.x);
|
||||
4:rd = op_readpc();
|
||||
5:op_io();
|
||||
if(regs.a == sp)end;
|
||||
6:op_io();
|
||||
7:op_io();
|
||||
regs.pc += (int8)rd;
|
||||
}
|
||||
|
||||
dbnz_dp(0x6e) {
|
||||
1:dp = op_readpc();
|
||||
2:wr = op_readdp(dp);
|
||||
3:op_writedp(dp, --wr);
|
||||
4:rd = op_readpc();
|
||||
if(wr == 0x00)end;
|
||||
5:op_io();
|
||||
6:op_io();
|
||||
regs.pc += (int8)rd;
|
||||
}
|
||||
|
||||
dbnz_y(0xfe) {
|
||||
1:rd = op_readpc();
|
||||
2:op_io();
|
||||
regs.y--;
|
||||
3:op_io();
|
||||
if(regs.y == 0x00)end;
|
||||
4:op_io();
|
||||
5:op_io();
|
||||
regs.pc += (int8)rd;
|
||||
}
|
||||
|
||||
jmp_addr(0x5f) {
|
||||
1:rd = op_readpc();
|
||||
2:rd |= op_readpc() << 8;
|
||||
regs.pc = rd;
|
||||
}
|
||||
|
||||
jmp_iaddrx(0x1f) {
|
||||
1:dp = op_readpc();
|
||||
2:dp |= op_readpc() << 8;
|
||||
3:op_io();
|
||||
dp += regs.x;
|
||||
4:rd = op_readaddr(dp);
|
||||
5:rd |= op_readaddr(dp + 1) << 8;
|
||||
regs.pc = rd;
|
||||
}
|
||||
|
||||
call(0x3f) {
|
||||
1:rd = op_readpc();
|
||||
2:rd |= op_readpc() << 8;
|
||||
3:op_io();
|
||||
4:op_io();
|
||||
5:op_io();
|
||||
6:op_writestack(regs.pc >> 8);
|
||||
7:op_writestack(regs.pc);
|
||||
regs.pc = rd;
|
||||
}
|
||||
|
||||
pcall(0x4f) {
|
||||
1:rd = op_readpc();
|
||||
2:op_io();
|
||||
3:op_io();
|
||||
4:op_writestack(regs.pc >> 8);
|
||||
5:op_writestack(regs.pc);
|
||||
regs.pc = 0xff00 | rd;
|
||||
}
|
||||
|
||||
tcall_0(0x01, 0),
|
||||
tcall_1(0x11, 1),
|
||||
tcall_2(0x21, 2),
|
||||
tcall_3(0x31, 3),
|
||||
tcall_4(0x41, 4),
|
||||
tcall_5(0x51, 5),
|
||||
tcall_6(0x61, 6),
|
||||
tcall_7(0x71, 7),
|
||||
tcall_8(0x81, 8),
|
||||
tcall_9(0x91, 9),
|
||||
tcall_10(0xa1, 10),
|
||||
tcall_11(0xb1, 11),
|
||||
tcall_12(0xc1, 12),
|
||||
tcall_13(0xd1, 13),
|
||||
tcall_14(0xe1, 14),
|
||||
tcall_15(0xf1, 15) {
|
||||
1:dp = 0xffde - ($1 << 1);
|
||||
rd = op_readaddr(dp);
|
||||
2:rd |= op_readaddr(dp + 1) << 8;
|
||||
3:op_io();
|
||||
4:op_io();
|
||||
5:op_io();
|
||||
6:op_writestack(regs.pc >> 8);
|
||||
7:op_writestack(regs.pc);
|
||||
regs.pc = rd;
|
||||
}
|
||||
|
||||
brk(0x0f) {
|
||||
1:rd = op_readaddr(0xffde);
|
||||
2:rd |= op_readaddr(0xffdf) << 8;
|
||||
3:op_io();
|
||||
4:op_io();
|
||||
5:op_writestack(regs.pc >> 8);
|
||||
6:op_writestack(regs.pc);
|
||||
7:op_writestack(regs.p);
|
||||
regs.pc = rd;
|
||||
regs.p.b = 1;
|
||||
regs.p.i = 0;
|
||||
}
|
||||
|
||||
ret(0x6f) {
|
||||
1:rd = op_readstack();
|
||||
2:rd |= op_readstack() << 8;
|
||||
3:op_io();
|
||||
4:op_io();
|
||||
regs.pc = rd;
|
||||
}
|
||||
|
||||
reti(0x7f) {
|
||||
1:regs.p = op_readstack();
|
||||
2:rd = op_readstack();
|
||||
3:rd |= op_readstack() << 8;
|
||||
4:op_io();
|
||||
5:op_io();
|
||||
regs.pc = rd;
|
||||
}
|
603
bsnes/snes/alt/smp/core/op_pc.cpp
Executable file
603
bsnes/snes/alt/smp/core/op_pc.cpp
Executable file
@@ -0,0 +1,603 @@
|
||||
case 0x2f: {
|
||||
rd = op_readpc();
|
||||
if(0)break;
|
||||
op_io();
|
||||
op_io();
|
||||
regs.pc += (int8)rd;
|
||||
break;
|
||||
}
|
||||
|
||||
case 0xf0: {
|
||||
rd = op_readpc();
|
||||
if(!regs.p.z)break;
|
||||
op_io();
|
||||
op_io();
|
||||
regs.pc += (int8)rd;
|
||||
break;
|
||||
}
|
||||
|
||||
case 0xd0: {
|
||||
rd = op_readpc();
|
||||
if(regs.p.z)break;
|
||||
op_io();
|
||||
op_io();
|
||||
regs.pc += (int8)rd;
|
||||
break;
|
||||
}
|
||||
|
||||
case 0xb0: {
|
||||
rd = op_readpc();
|
||||
if(!regs.p.c)break;
|
||||
op_io();
|
||||
op_io();
|
||||
regs.pc += (int8)rd;
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x90: {
|
||||
rd = op_readpc();
|
||||
if(regs.p.c)break;
|
||||
op_io();
|
||||
op_io();
|
||||
regs.pc += (int8)rd;
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x70: {
|
||||
rd = op_readpc();
|
||||
if(!regs.p.v)break;
|
||||
op_io();
|
||||
op_io();
|
||||
regs.pc += (int8)rd;
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x50: {
|
||||
rd = op_readpc();
|
||||
if(regs.p.v)break;
|
||||
op_io();
|
||||
op_io();
|
||||
regs.pc += (int8)rd;
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x30: {
|
||||
rd = op_readpc();
|
||||
if(!regs.p.n)break;
|
||||
op_io();
|
||||
op_io();
|
||||
regs.pc += (int8)rd;
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x10: {
|
||||
rd = op_readpc();
|
||||
if(regs.p.n)break;
|
||||
op_io();
|
||||
op_io();
|
||||
regs.pc += (int8)rd;
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x03: {
|
||||
dp = op_readpc();
|
||||
sp = op_readdp(dp);
|
||||
rd = op_readpc();
|
||||
op_io();
|
||||
if((sp & 0x01) != 0x01)break;
|
||||
op_io();
|
||||
op_io();
|
||||
regs.pc += (int8)rd;
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x13: {
|
||||
dp = op_readpc();
|
||||
sp = op_readdp(dp);
|
||||
rd = op_readpc();
|
||||
op_io();
|
||||
if((sp & 0x01) == 0x01)break;
|
||||
op_io();
|
||||
op_io();
|
||||
regs.pc += (int8)rd;
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x23: {
|
||||
dp = op_readpc();
|
||||
sp = op_readdp(dp);
|
||||
rd = op_readpc();
|
||||
op_io();
|
||||
if((sp & 0x02) != 0x02)break;
|
||||
op_io();
|
||||
op_io();
|
||||
regs.pc += (int8)rd;
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x33: {
|
||||
dp = op_readpc();
|
||||
sp = op_readdp(dp);
|
||||
rd = op_readpc();
|
||||
op_io();
|
||||
if((sp & 0x02) == 0x02)break;
|
||||
op_io();
|
||||
op_io();
|
||||
regs.pc += (int8)rd;
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x43: {
|
||||
dp = op_readpc();
|
||||
sp = op_readdp(dp);
|
||||
rd = op_readpc();
|
||||
op_io();
|
||||
if((sp & 0x04) != 0x04)break;
|
||||
op_io();
|
||||
op_io();
|
||||
regs.pc += (int8)rd;
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x53: {
|
||||
dp = op_readpc();
|
||||
sp = op_readdp(dp);
|
||||
rd = op_readpc();
|
||||
op_io();
|
||||
if((sp & 0x04) == 0x04)break;
|
||||
op_io();
|
||||
op_io();
|
||||
regs.pc += (int8)rd;
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x63: {
|
||||
dp = op_readpc();
|
||||
sp = op_readdp(dp);
|
||||
rd = op_readpc();
|
||||
op_io();
|
||||
if((sp & 0x08) != 0x08)break;
|
||||
op_io();
|
||||
op_io();
|
||||
regs.pc += (int8)rd;
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x73: {
|
||||
dp = op_readpc();
|
||||
sp = op_readdp(dp);
|
||||
rd = op_readpc();
|
||||
op_io();
|
||||
if((sp & 0x08) == 0x08)break;
|
||||
op_io();
|
||||
op_io();
|
||||
regs.pc += (int8)rd;
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x83: {
|
||||
dp = op_readpc();
|
||||
sp = op_readdp(dp);
|
||||
rd = op_readpc();
|
||||
op_io();
|
||||
if((sp & 0x10) != 0x10)break;
|
||||
op_io();
|
||||
op_io();
|
||||
regs.pc += (int8)rd;
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x93: {
|
||||
dp = op_readpc();
|
||||
sp = op_readdp(dp);
|
||||
rd = op_readpc();
|
||||
op_io();
|
||||
if((sp & 0x10) == 0x10)break;
|
||||
op_io();
|
||||
op_io();
|
||||
regs.pc += (int8)rd;
|
||||
break;
|
||||
}
|
||||
|
||||
case 0xa3: {
|
||||
dp = op_readpc();
|
||||
sp = op_readdp(dp);
|
||||
rd = op_readpc();
|
||||
op_io();
|
||||
if((sp & 0x20) != 0x20)break;
|
||||
op_io();
|
||||
op_io();
|
||||
regs.pc += (int8)rd;
|
||||
break;
|
||||
}
|
||||
|
||||
case 0xb3: {
|
||||
dp = op_readpc();
|
||||
sp = op_readdp(dp);
|
||||
rd = op_readpc();
|
||||
op_io();
|
||||
if((sp & 0x20) == 0x20)break;
|
||||
op_io();
|
||||
op_io();
|
||||
regs.pc += (int8)rd;
|
||||
break;
|
||||
}
|
||||
|
||||
case 0xc3: {
|
||||
dp = op_readpc();
|
||||
sp = op_readdp(dp);
|
||||
rd = op_readpc();
|
||||
op_io();
|
||||
if((sp & 0x40) != 0x40)break;
|
||||
op_io();
|
||||
op_io();
|
||||
regs.pc += (int8)rd;
|
||||
break;
|
||||
}
|
||||
|
||||
case 0xd3: {
|
||||
dp = op_readpc();
|
||||
sp = op_readdp(dp);
|
||||
rd = op_readpc();
|
||||
op_io();
|
||||
if((sp & 0x40) == 0x40)break;
|
||||
op_io();
|
||||
op_io();
|
||||
regs.pc += (int8)rd;
|
||||
break;
|
||||
}
|
||||
|
||||
case 0xe3: {
|
||||
dp = op_readpc();
|
||||
sp = op_readdp(dp);
|
||||
rd = op_readpc();
|
||||
op_io();
|
||||
if((sp & 0x80) != 0x80)break;
|
||||
op_io();
|
||||
op_io();
|
||||
regs.pc += (int8)rd;
|
||||
break;
|
||||
}
|
||||
|
||||
case 0xf3: {
|
||||
dp = op_readpc();
|
||||
sp = op_readdp(dp);
|
||||
rd = op_readpc();
|
||||
op_io();
|
||||
if((sp & 0x80) == 0x80)break;
|
||||
op_io();
|
||||
op_io();
|
||||
regs.pc += (int8)rd;
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x2e: {
|
||||
dp = op_readpc();
|
||||
sp = op_readdp(dp);
|
||||
rd = op_readpc();
|
||||
op_io();
|
||||
if(regs.a == sp)break;
|
||||
op_io();
|
||||
op_io();
|
||||
regs.pc += (int8)rd;
|
||||
break;
|
||||
}
|
||||
|
||||
case 0xde: {
|
||||
dp = op_readpc();
|
||||
op_io();
|
||||
sp = op_readdp(dp + regs.x);
|
||||
rd = op_readpc();
|
||||
op_io();
|
||||
if(regs.a == sp)break;
|
||||
op_io();
|
||||
op_io();
|
||||
regs.pc += (int8)rd;
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x6e: {
|
||||
dp = op_readpc();
|
||||
wr = op_readdp(dp);
|
||||
op_writedp(dp, --wr);
|
||||
rd = op_readpc();
|
||||
if(wr == 0x00)break;
|
||||
op_io();
|
||||
op_io();
|
||||
regs.pc += (int8)rd;
|
||||
break;
|
||||
}
|
||||
|
||||
case 0xfe: {
|
||||
rd = op_readpc();
|
||||
op_io();
|
||||
regs.y--;
|
||||
op_io();
|
||||
if(regs.y == 0x00)break;
|
||||
op_io();
|
||||
op_io();
|
||||
regs.pc += (int8)rd;
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x5f: {
|
||||
rd = op_readpc();
|
||||
rd |= op_readpc() << 8;
|
||||
regs.pc = rd;
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x1f: {
|
||||
dp = op_readpc();
|
||||
dp |= op_readpc() << 8;
|
||||
op_io();
|
||||
dp += regs.x;
|
||||
rd = op_readaddr(dp);
|
||||
rd |= op_readaddr(dp + 1) << 8;
|
||||
regs.pc = rd;
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x3f: {
|
||||
rd = op_readpc();
|
||||
rd |= op_readpc() << 8;
|
||||
op_io();
|
||||
op_io();
|
||||
op_io();
|
||||
op_writestack(regs.pc >> 8);
|
||||
op_writestack(regs.pc);
|
||||
regs.pc = rd;
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x4f: {
|
||||
rd = op_readpc();
|
||||
op_io();
|
||||
op_io();
|
||||
op_writestack(regs.pc >> 8);
|
||||
op_writestack(regs.pc);
|
||||
regs.pc = 0xff00 | rd;
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x01: {
|
||||
dp = 0xffde - (0 << 1);
|
||||
rd = op_readaddr(dp);
|
||||
rd |= op_readaddr(dp + 1) << 8;
|
||||
op_io();
|
||||
op_io();
|
||||
op_io();
|
||||
op_writestack(regs.pc >> 8);
|
||||
op_writestack(regs.pc);
|
||||
regs.pc = rd;
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x11: {
|
||||
dp = 0xffde - (1 << 1);
|
||||
rd = op_readaddr(dp);
|
||||
rd |= op_readaddr(dp + 1) << 8;
|
||||
op_io();
|
||||
op_io();
|
||||
op_io();
|
||||
op_writestack(regs.pc >> 8);
|
||||
op_writestack(regs.pc);
|
||||
regs.pc = rd;
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x21: {
|
||||
dp = 0xffde - (2 << 1);
|
||||
rd = op_readaddr(dp);
|
||||
rd |= op_readaddr(dp + 1) << 8;
|
||||
op_io();
|
||||
op_io();
|
||||
op_io();
|
||||
op_writestack(regs.pc >> 8);
|
||||
op_writestack(regs.pc);
|
||||
regs.pc = rd;
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x31: {
|
||||
dp = 0xffde - (3 << 1);
|
||||
rd = op_readaddr(dp);
|
||||
rd |= op_readaddr(dp + 1) << 8;
|
||||
op_io();
|
||||
op_io();
|
||||
op_io();
|
||||
op_writestack(regs.pc >> 8);
|
||||
op_writestack(regs.pc);
|
||||
regs.pc = rd;
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x41: {
|
||||
dp = 0xffde - (4 << 1);
|
||||
rd = op_readaddr(dp);
|
||||
rd |= op_readaddr(dp + 1) << 8;
|
||||
op_io();
|
||||
op_io();
|
||||
op_io();
|
||||
op_writestack(regs.pc >> 8);
|
||||
op_writestack(regs.pc);
|
||||
regs.pc = rd;
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x51: {
|
||||
dp = 0xffde - (5 << 1);
|
||||
rd = op_readaddr(dp);
|
||||
rd |= op_readaddr(dp + 1) << 8;
|
||||
op_io();
|
||||
op_io();
|
||||
op_io();
|
||||
op_writestack(regs.pc >> 8);
|
||||
op_writestack(regs.pc);
|
||||
regs.pc = rd;
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x61: {
|
||||
dp = 0xffde - (6 << 1);
|
||||
rd = op_readaddr(dp);
|
||||
rd |= op_readaddr(dp + 1) << 8;
|
||||
op_io();
|
||||
op_io();
|
||||
op_io();
|
||||
op_writestack(regs.pc >> 8);
|
||||
op_writestack(regs.pc);
|
||||
regs.pc = rd;
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x71: {
|
||||
dp = 0xffde - (7 << 1);
|
||||
rd = op_readaddr(dp);
|
||||
rd |= op_readaddr(dp + 1) << 8;
|
||||
op_io();
|
||||
op_io();
|
||||
op_io();
|
||||
op_writestack(regs.pc >> 8);
|
||||
op_writestack(regs.pc);
|
||||
regs.pc = rd;
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x81: {
|
||||
dp = 0xffde - (8 << 1);
|
||||
rd = op_readaddr(dp);
|
||||
rd |= op_readaddr(dp + 1) << 8;
|
||||
op_io();
|
||||
op_io();
|
||||
op_io();
|
||||
op_writestack(regs.pc >> 8);
|
||||
op_writestack(regs.pc);
|
||||
regs.pc = rd;
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x91: {
|
||||
dp = 0xffde - (9 << 1);
|
||||
rd = op_readaddr(dp);
|
||||
rd |= op_readaddr(dp + 1) << 8;
|
||||
op_io();
|
||||
op_io();
|
||||
op_io();
|
||||
op_writestack(regs.pc >> 8);
|
||||
op_writestack(regs.pc);
|
||||
regs.pc = rd;
|
||||
break;
|
||||
}
|
||||
|
||||
case 0xa1: {
|
||||
dp = 0xffde - (10 << 1);
|
||||
rd = op_readaddr(dp);
|
||||
rd |= op_readaddr(dp + 1) << 8;
|
||||
op_io();
|
||||
op_io();
|
||||
op_io();
|
||||
op_writestack(regs.pc >> 8);
|
||||
op_writestack(regs.pc);
|
||||
regs.pc = rd;
|
||||
break;
|
||||
}
|
||||
|
||||
case 0xb1: {
|
||||
dp = 0xffde - (11 << 1);
|
||||
rd = op_readaddr(dp);
|
||||
rd |= op_readaddr(dp + 1) << 8;
|
||||
op_io();
|
||||
op_io();
|
||||
op_io();
|
||||
op_writestack(regs.pc >> 8);
|
||||
op_writestack(regs.pc);
|
||||
regs.pc = rd;
|
||||
break;
|
||||
}
|
||||
|
||||
case 0xc1: {
|
||||
dp = 0xffde - (12 << 1);
|
||||
rd = op_readaddr(dp);
|
||||
rd |= op_readaddr(dp + 1) << 8;
|
||||
op_io();
|
||||
op_io();
|
||||
op_io();
|
||||
op_writestack(regs.pc >> 8);
|
||||
op_writestack(regs.pc);
|
||||
regs.pc = rd;
|
||||
break;
|
||||
}
|
||||
|
||||
case 0xd1: {
|
||||
dp = 0xffde - (13 << 1);
|
||||
rd = op_readaddr(dp);
|
||||
rd |= op_readaddr(dp + 1) << 8;
|
||||
op_io();
|
||||
op_io();
|
||||
op_io();
|
||||
op_writestack(regs.pc >> 8);
|
||||
op_writestack(regs.pc);
|
||||
regs.pc = rd;
|
||||
break;
|
||||
}
|
||||
|
||||
case 0xe1: {
|
||||
dp = 0xffde - (14 << 1);
|
||||
rd = op_readaddr(dp);
|
||||
rd |= op_readaddr(dp + 1) << 8;
|
||||
op_io();
|
||||
op_io();
|
||||
op_io();
|
||||
op_writestack(regs.pc >> 8);
|
||||
op_writestack(regs.pc);
|
||||
regs.pc = rd;
|
||||
break;
|
||||
}
|
||||
|
||||
case 0xf1: {
|
||||
dp = 0xffde - (15 << 1);
|
||||
rd = op_readaddr(dp);
|
||||
rd |= op_readaddr(dp + 1) << 8;
|
||||
op_io();
|
||||
op_io();
|
||||
op_io();
|
||||
op_writestack(regs.pc >> 8);
|
||||
op_writestack(regs.pc);
|
||||
regs.pc = rd;
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x0f: {
|
||||
rd = op_readaddr(0xffde);
|
||||
rd |= op_readaddr(0xffdf) << 8;
|
||||
op_io();
|
||||
op_io();
|
||||
op_writestack(regs.pc >> 8);
|
||||
op_writestack(regs.pc);
|
||||
op_writestack(regs.p);
|
||||
regs.pc = rd;
|
||||
regs.p.b = 1;
|
||||
regs.p.i = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x6f: {
|
||||
rd = op_readstack();
|
||||
rd |= op_readstack() << 8;
|
||||
op_io();
|
||||
op_io();
|
||||
regs.pc = rd;
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x7f: {
|
||||
regs.p = op_readstack();
|
||||
rd = op_readstack();
|
||||
rd |= op_readstack() << 8;
|
||||
op_io();
|
||||
op_io();
|
||||
regs.pc = rd;
|
||||
break;
|
||||
}
|
||||
|
205
bsnes/snes/alt/smp/core/op_read.b
Executable file
205
bsnes/snes/alt/smp/core/op_read.b
Executable file
@@ -0,0 +1,205 @@
|
||||
adc_a_const(0x88, adc, a),
|
||||
and_a_const(0x28, and, a),
|
||||
cmp_a_const(0x68, cmp, a),
|
||||
cmp_x_const(0xc8, cmp, x),
|
||||
cmp_y_const(0xad, cmp, y),
|
||||
eor_a_const(0x48, eor, a),
|
||||
or_a_const(0x08, or, a),
|
||||
sbc_a_const(0xa8, sbc, a) {
|
||||
1:rd = op_readpc();
|
||||
regs.$2 = op_$1(regs.$2, rd);
|
||||
}
|
||||
|
||||
adc_a_ix(0x86, adc),
|
||||
and_a_ix(0x26, and),
|
||||
cmp_a_ix(0x66, cmp),
|
||||
eor_a_ix(0x46, eor),
|
||||
or_a_ix(0x06, or),
|
||||
sbc_a_ix(0xa6, sbc) {
|
||||
1:op_io();
|
||||
2:rd = op_readdp(regs.x);
|
||||
regs.a = op_$1(regs.a, rd);
|
||||
}
|
||||
|
||||
adc_a_dp(0x84, adc, a),
|
||||
and_a_dp(0x24, and, a),
|
||||
cmp_a_dp(0x64, cmp, a),
|
||||
cmp_x_dp(0x3e, cmp, x),
|
||||
cmp_y_dp(0x7e, cmp, y),
|
||||
eor_a_dp(0x44, eor, a),
|
||||
or_a_dp(0x04, or, a),
|
||||
sbc_a_dp(0xa4, sbc, a) {
|
||||
1:dp = op_readpc();
|
||||
2:rd = op_readdp(dp);
|
||||
regs.$2 = op_$1(regs.$2, rd);
|
||||
}
|
||||
|
||||
adc_a_dpx(0x94, adc),
|
||||
and_a_dpx(0x34, and),
|
||||
cmp_a_dpx(0x74, cmp),
|
||||
eor_a_dpx(0x54, eor),
|
||||
or_a_dpx(0x14, or),
|
||||
sbc_a_dpx(0xb4, sbc) {
|
||||
1:dp = op_readpc();
|
||||
2:op_io();
|
||||
3:rd = op_readdp(dp + regs.x);
|
||||
regs.a = op_$1(regs.a, rd);
|
||||
}
|
||||
|
||||
adc_a_addr(0x85, adc, a),
|
||||
and_a_addr(0x25, and, a),
|
||||
cmp_a_addr(0x65, cmp, a),
|
||||
cmp_x_addr(0x1e, cmp, x),
|
||||
cmp_y_addr(0x5e, cmp, y),
|
||||
eor_a_addr(0x45, eor, a),
|
||||
or_a_addr(0x05, or, a),
|
||||
sbc_a_addr(0xa5, sbc, a) {
|
||||
1:dp = op_readpc();
|
||||
2:dp |= op_readpc() << 8;
|
||||
3:rd = op_readaddr(dp);
|
||||
regs.$2 = op_$1(regs.$2, rd);
|
||||
}
|
||||
|
||||
adc_a_addrx(0x95, adc, x),
|
||||
adc_a_addry(0x96, adc, y),
|
||||
and_a_addrx(0x35, and, x),
|
||||
and_a_addry(0x36, and, y),
|
||||
cmp_a_addrx(0x75, cmp, x),
|
||||
cmp_a_addry(0x76, cmp, y),
|
||||
eor_a_addrx(0x55, eor, x),
|
||||
eor_a_addry(0x56, eor, y),
|
||||
or_a_addrx(0x15, or, x),
|
||||
or_a_addry(0x16, or, y),
|
||||
sbc_a_addrx(0xb5, sbc, x),
|
||||
sbc_a_addry(0xb6, sbc, y) {
|
||||
1:dp = op_readpc();
|
||||
2:dp |= op_readpc() << 8;
|
||||
3:op_io();
|
||||
4:rd = op_readaddr(dp + regs.$2);
|
||||
regs.a = op_$1(regs.a, rd);
|
||||
}
|
||||
|
||||
adc_a_idpx(0x87, adc),
|
||||
and_a_idpx(0x27, and),
|
||||
cmp_a_idpx(0x67, cmp),
|
||||
eor_a_idpx(0x47, eor),
|
||||
or_a_idpx(0x07, or),
|
||||
sbc_a_idpx(0xa7, sbc) {
|
||||
1:dp = op_readpc() + regs.x;
|
||||
2:op_io();
|
||||
3:sp = op_readdp(dp);
|
||||
4:sp |= op_readdp(dp + 1) << 8;
|
||||
5:rd = op_readaddr(sp);
|
||||
regs.a = op_$1(regs.a, rd);
|
||||
}
|
||||
|
||||
adc_a_idpy(0x97, adc),
|
||||
and_a_idpy(0x37, and),
|
||||
cmp_a_idpy(0x77, cmp),
|
||||
eor_a_idpy(0x57, eor),
|
||||
or_a_idpy(0x17, or),
|
||||
sbc_a_idpy(0xb7, sbc) {
|
||||
1:dp = op_readpc();
|
||||
2:op_io();
|
||||
3:sp = op_readdp(dp);
|
||||
4:sp |= op_readdp(dp + 1) << 8;
|
||||
5:rd = op_readaddr(sp + regs.y);
|
||||
regs.a = op_$1(regs.a, rd);
|
||||
}
|
||||
|
||||
adc_ix_iy(0x99, adc, 1),
|
||||
and_ix_iy(0x39, and, 1),
|
||||
cmp_ix_iy(0x79, cmp, 0),
|
||||
eor_ix_iy(0x59, eor, 1),
|
||||
or_ix_iy(0x19, or, 1),
|
||||
sbc_ix_iy(0xb9, sbc, 1) {
|
||||
1:op_io();
|
||||
2:rd = op_readdp(regs.y);
|
||||
3:wr = op_readdp(regs.x);
|
||||
wr = op_$1(wr, rd);
|
||||
4:($2) ? op_writedp(regs.x, wr) : op_io();
|
||||
}
|
||||
|
||||
adc_dp_dp(0x89, adc, 1),
|
||||
and_dp_dp(0x29, and, 1),
|
||||
cmp_dp_dp(0x69, cmp, 0),
|
||||
eor_dp_dp(0x49, eor, 1),
|
||||
or_dp_dp(0x09, or, 1),
|
||||
sbc_dp_dp(0xa9, sbc, 1) {
|
||||
1:sp = op_readpc();
|
||||
2:rd = op_readdp(sp);
|
||||
3:dp = op_readpc();
|
||||
4:wr = op_readdp(dp);
|
||||
5:wr = op_$1(wr, rd);
|
||||
($2) ? op_writedp(dp, wr) : op_io();
|
||||
}
|
||||
|
||||
adc_dp_const(0x98, adc, 1),
|
||||
and_dp_const(0x38, and, 1),
|
||||
cmp_dp_const(0x78, cmp, 0),
|
||||
eor_dp_const(0x58, eor, 1),
|
||||
or_dp_const(0x18, or, 1),
|
||||
sbc_dp_const(0xb8, sbc, 1) {
|
||||
1:rd = op_readpc();
|
||||
2:dp = op_readpc();
|
||||
3:wr = op_readdp(dp);
|
||||
4:wr = op_$1(wr, rd);
|
||||
($2) ? op_writedp(dp, wr) : op_io();
|
||||
}
|
||||
|
||||
addw_ya_dp(0x7a, addw),
|
||||
subw_ya_dp(0x9a, subw) {
|
||||
1:dp = op_readpc();
|
||||
2:rd = op_readdp(dp);
|
||||
3:op_io();
|
||||
4:rd |= op_readdp(dp + 1) << 8;
|
||||
regs.ya = op_$1(regs.ya, rd);
|
||||
}
|
||||
|
||||
cmpw_ya_dp(0x5a) {
|
||||
1:dp = op_readpc();
|
||||
2:rd = op_readdp(dp);
|
||||
3:rd |= op_readdp(dp + 1) << 8;
|
||||
op_cmpw(regs.ya, rd);
|
||||
}
|
||||
|
||||
and1_bit(0x4a, !!),
|
||||
and1_notbit(0x6a, !) {
|
||||
1:dp = op_readpc();
|
||||
2:dp |= op_readpc() << 8;
|
||||
3:bit = dp >> 13;
|
||||
dp &= 0x1fff;
|
||||
rd = op_readaddr(dp);
|
||||
regs.p.c = regs.p.c & $1(rd & (1 << bit));
|
||||
}
|
||||
|
||||
eor1_bit(0x8a) {
|
||||
1:dp = op_readpc();
|
||||
2:dp |= op_readpc() << 8;
|
||||
3:bit = dp >> 13;
|
||||
dp &= 0x1fff;
|
||||
rd = op_readaddr(dp);
|
||||
4:op_io();
|
||||
regs.p.c = regs.p.c ^ !!(rd & (1 << bit));
|
||||
}
|
||||
|
||||
not1_bit(0xea) {
|
||||
1:dp = op_readpc();
|
||||
2:dp |= op_readpc() << 8;
|
||||
3:bit = dp >> 13;
|
||||
dp &= 0x1fff;
|
||||
rd = op_readaddr(dp);
|
||||
rd ^= (1 << bit);
|
||||
4:op_writeaddr(dp, rd);
|
||||
}
|
||||
|
||||
or1_bit(0x0a, !!),
|
||||
or1_notbit(0x2a, !) {
|
||||
1:dp = op_readpc();
|
||||
2:dp |= op_readpc() << 8;
|
||||
3:bit = dp >> 13;
|
||||
dp &= 0x1fff;
|
||||
rd = op_readaddr(dp);
|
||||
4:op_io();
|
||||
regs.p.c = regs.p.c | $1(rd & (1 << bit));
|
||||
}
|
744
bsnes/snes/alt/smp/core/op_read.cpp
Executable file
744
bsnes/snes/alt/smp/core/op_read.cpp
Executable file
@@ -0,0 +1,744 @@
|
||||
case 0x88: {
|
||||
rd = op_readpc();
|
||||
regs.a = op_adc(regs.a, rd);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x28: {
|
||||
rd = op_readpc();
|
||||
regs.a = op_and(regs.a, rd);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x68: {
|
||||
rd = op_readpc();
|
||||
regs.a = op_cmp(regs.a, rd);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0xc8: {
|
||||
rd = op_readpc();
|
||||
regs.x = op_cmp(regs.x, rd);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0xad: {
|
||||
rd = op_readpc();
|
||||
regs.y = op_cmp(regs.y, rd);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x48: {
|
||||
rd = op_readpc();
|
||||
regs.a = op_eor(regs.a, rd);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x08: {
|
||||
rd = op_readpc();
|
||||
regs.a = op_or(regs.a, rd);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0xa8: {
|
||||
rd = op_readpc();
|
||||
regs.a = op_sbc(regs.a, rd);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x86: {
|
||||
op_io();
|
||||
rd = op_readdp(regs.x);
|
||||
regs.a = op_adc(regs.a, rd);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x26: {
|
||||
op_io();
|
||||
rd = op_readdp(regs.x);
|
||||
regs.a = op_and(regs.a, rd);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x66: {
|
||||
op_io();
|
||||
rd = op_readdp(regs.x);
|
||||
regs.a = op_cmp(regs.a, rd);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x46: {
|
||||
op_io();
|
||||
rd = op_readdp(regs.x);
|
||||
regs.a = op_eor(regs.a, rd);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x06: {
|
||||
op_io();
|
||||
rd = op_readdp(regs.x);
|
||||
regs.a = op_or(regs.a, rd);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0xa6: {
|
||||
op_io();
|
||||
rd = op_readdp(regs.x);
|
||||
regs.a = op_sbc(regs.a, rd);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x84: {
|
||||
dp = op_readpc();
|
||||
rd = op_readdp(dp);
|
||||
regs.a = op_adc(regs.a, rd);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x24: {
|
||||
dp = op_readpc();
|
||||
rd = op_readdp(dp);
|
||||
regs.a = op_and(regs.a, rd);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x64: {
|
||||
dp = op_readpc();
|
||||
rd = op_readdp(dp);
|
||||
regs.a = op_cmp(regs.a, rd);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x3e: {
|
||||
dp = op_readpc();
|
||||
rd = op_readdp(dp);
|
||||
regs.x = op_cmp(regs.x, rd);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x7e: {
|
||||
dp = op_readpc();
|
||||
rd = op_readdp(dp);
|
||||
regs.y = op_cmp(regs.y, rd);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x44: {
|
||||
dp = op_readpc();
|
||||
rd = op_readdp(dp);
|
||||
regs.a = op_eor(regs.a, rd);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x04: {
|
||||
dp = op_readpc();
|
||||
rd = op_readdp(dp);
|
||||
regs.a = op_or(regs.a, rd);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0xa4: {
|
||||
dp = op_readpc();
|
||||
rd = op_readdp(dp);
|
||||
regs.a = op_sbc(regs.a, rd);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x94: {
|
||||
dp = op_readpc();
|
||||
op_io();
|
||||
rd = op_readdp(dp + regs.x);
|
||||
regs.a = op_adc(regs.a, rd);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x34: {
|
||||
dp = op_readpc();
|
||||
op_io();
|
||||
rd = op_readdp(dp + regs.x);
|
||||
regs.a = op_and(regs.a, rd);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x74: {
|
||||
dp = op_readpc();
|
||||
op_io();
|
||||
rd = op_readdp(dp + regs.x);
|
||||
regs.a = op_cmp(regs.a, rd);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x54: {
|
||||
dp = op_readpc();
|
||||
op_io();
|
||||
rd = op_readdp(dp + regs.x);
|
||||
regs.a = op_eor(regs.a, rd);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x14: {
|
||||
dp = op_readpc();
|
||||
op_io();
|
||||
rd = op_readdp(dp + regs.x);
|
||||
regs.a = op_or(regs.a, rd);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0xb4: {
|
||||
dp = op_readpc();
|
||||
op_io();
|
||||
rd = op_readdp(dp + regs.x);
|
||||
regs.a = op_sbc(regs.a, rd);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x85: {
|
||||
dp = op_readpc();
|
||||
dp |= op_readpc() << 8;
|
||||
rd = op_readaddr(dp);
|
||||
regs.a = op_adc(regs.a, rd);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x25: {
|
||||
dp = op_readpc();
|
||||
dp |= op_readpc() << 8;
|
||||
rd = op_readaddr(dp);
|
||||
regs.a = op_and(regs.a, rd);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x65: {
|
||||
dp = op_readpc();
|
||||
dp |= op_readpc() << 8;
|
||||
rd = op_readaddr(dp);
|
||||
regs.a = op_cmp(regs.a, rd);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x1e: {
|
||||
dp = op_readpc();
|
||||
dp |= op_readpc() << 8;
|
||||
rd = op_readaddr(dp);
|
||||
regs.x = op_cmp(regs.x, rd);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x5e: {
|
||||
dp = op_readpc();
|
||||
dp |= op_readpc() << 8;
|
||||
rd = op_readaddr(dp);
|
||||
regs.y = op_cmp(regs.y, rd);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x45: {
|
||||
dp = op_readpc();
|
||||
dp |= op_readpc() << 8;
|
||||
rd = op_readaddr(dp);
|
||||
regs.a = op_eor(regs.a, rd);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x05: {
|
||||
dp = op_readpc();
|
||||
dp |= op_readpc() << 8;
|
||||
rd = op_readaddr(dp);
|
||||
regs.a = op_or(regs.a, rd);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0xa5: {
|
||||
dp = op_readpc();
|
||||
dp |= op_readpc() << 8;
|
||||
rd = op_readaddr(dp);
|
||||
regs.a = op_sbc(regs.a, rd);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x95: {
|
||||
dp = op_readpc();
|
||||
dp |= op_readpc() << 8;
|
||||
op_io();
|
||||
rd = op_readaddr(dp + regs.x);
|
||||
regs.a = op_adc(regs.a, rd);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x96: {
|
||||
dp = op_readpc();
|
||||
dp |= op_readpc() << 8;
|
||||
op_io();
|
||||
rd = op_readaddr(dp + regs.y);
|
||||
regs.a = op_adc(regs.a, rd);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x35: {
|
||||
dp = op_readpc();
|
||||
dp |= op_readpc() << 8;
|
||||
op_io();
|
||||
rd = op_readaddr(dp + regs.x);
|
||||
regs.a = op_and(regs.a, rd);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x36: {
|
||||
dp = op_readpc();
|
||||
dp |= op_readpc() << 8;
|
||||
op_io();
|
||||
rd = op_readaddr(dp + regs.y);
|
||||
regs.a = op_and(regs.a, rd);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x75: {
|
||||
dp = op_readpc();
|
||||
dp |= op_readpc() << 8;
|
||||
op_io();
|
||||
rd = op_readaddr(dp + regs.x);
|
||||
regs.a = op_cmp(regs.a, rd);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x76: {
|
||||
dp = op_readpc();
|
||||
dp |= op_readpc() << 8;
|
||||
op_io();
|
||||
rd = op_readaddr(dp + regs.y);
|
||||
regs.a = op_cmp(regs.a, rd);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x55: {
|
||||
dp = op_readpc();
|
||||
dp |= op_readpc() << 8;
|
||||
op_io();
|
||||
rd = op_readaddr(dp + regs.x);
|
||||
regs.a = op_eor(regs.a, rd);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x56: {
|
||||
dp = op_readpc();
|
||||
dp |= op_readpc() << 8;
|
||||
op_io();
|
||||
rd = op_readaddr(dp + regs.y);
|
||||
regs.a = op_eor(regs.a, rd);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x15: {
|
||||
dp = op_readpc();
|
||||
dp |= op_readpc() << 8;
|
||||
op_io();
|
||||
rd = op_readaddr(dp + regs.x);
|
||||
regs.a = op_or(regs.a, rd);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x16: {
|
||||
dp = op_readpc();
|
||||
dp |= op_readpc() << 8;
|
||||
op_io();
|
||||
rd = op_readaddr(dp + regs.y);
|
||||
regs.a = op_or(regs.a, rd);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0xb5: {
|
||||
dp = op_readpc();
|
||||
dp |= op_readpc() << 8;
|
||||
op_io();
|
||||
rd = op_readaddr(dp + regs.x);
|
||||
regs.a = op_sbc(regs.a, rd);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0xb6: {
|
||||
dp = op_readpc();
|
||||
dp |= op_readpc() << 8;
|
||||
op_io();
|
||||
rd = op_readaddr(dp + regs.y);
|
||||
regs.a = op_sbc(regs.a, rd);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x87: {
|
||||
dp = op_readpc() + regs.x;
|
||||
op_io();
|
||||
sp = op_readdp(dp);
|
||||
sp |= op_readdp(dp + 1) << 8;
|
||||
rd = op_readaddr(sp);
|
||||
regs.a = op_adc(regs.a, rd);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x27: {
|
||||
dp = op_readpc() + regs.x;
|
||||
op_io();
|
||||
sp = op_readdp(dp);
|
||||
sp |= op_readdp(dp + 1) << 8;
|
||||
rd = op_readaddr(sp);
|
||||
regs.a = op_and(regs.a, rd);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x67: {
|
||||
dp = op_readpc() + regs.x;
|
||||
op_io();
|
||||
sp = op_readdp(dp);
|
||||
sp |= op_readdp(dp + 1) << 8;
|
||||
rd = op_readaddr(sp);
|
||||
regs.a = op_cmp(regs.a, rd);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x47: {
|
||||
dp = op_readpc() + regs.x;
|
||||
op_io();
|
||||
sp = op_readdp(dp);
|
||||
sp |= op_readdp(dp + 1) << 8;
|
||||
rd = op_readaddr(sp);
|
||||
regs.a = op_eor(regs.a, rd);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x07: {
|
||||
dp = op_readpc() + regs.x;
|
||||
op_io();
|
||||
sp = op_readdp(dp);
|
||||
sp |= op_readdp(dp + 1) << 8;
|
||||
rd = op_readaddr(sp);
|
||||
regs.a = op_or(regs.a, rd);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0xa7: {
|
||||
dp = op_readpc() + regs.x;
|
||||
op_io();
|
||||
sp = op_readdp(dp);
|
||||
sp |= op_readdp(dp + 1) << 8;
|
||||
rd = op_readaddr(sp);
|
||||
regs.a = op_sbc(regs.a, rd);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x97: {
|
||||
dp = op_readpc();
|
||||
op_io();
|
||||
sp = op_readdp(dp);
|
||||
sp |= op_readdp(dp + 1) << 8;
|
||||
rd = op_readaddr(sp + regs.y);
|
||||
regs.a = op_adc(regs.a, rd);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x37: {
|
||||
dp = op_readpc();
|
||||
op_io();
|
||||
sp = op_readdp(dp);
|
||||
sp |= op_readdp(dp + 1) << 8;
|
||||
rd = op_readaddr(sp + regs.y);
|
||||
regs.a = op_and(regs.a, rd);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x77: {
|
||||
dp = op_readpc();
|
||||
op_io();
|
||||
sp = op_readdp(dp);
|
||||
sp |= op_readdp(dp + 1) << 8;
|
||||
rd = op_readaddr(sp + regs.y);
|
||||
regs.a = op_cmp(regs.a, rd);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x57: {
|
||||
dp = op_readpc();
|
||||
op_io();
|
||||
sp = op_readdp(dp);
|
||||
sp |= op_readdp(dp + 1) << 8;
|
||||
rd = op_readaddr(sp + regs.y);
|
||||
regs.a = op_eor(regs.a, rd);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x17: {
|
||||
dp = op_readpc();
|
||||
op_io();
|
||||
sp = op_readdp(dp);
|
||||
sp |= op_readdp(dp + 1) << 8;
|
||||
rd = op_readaddr(sp + regs.y);
|
||||
regs.a = op_or(regs.a, rd);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0xb7: {
|
||||
dp = op_readpc();
|
||||
op_io();
|
||||
sp = op_readdp(dp);
|
||||
sp |= op_readdp(dp + 1) << 8;
|
||||
rd = op_readaddr(sp + regs.y);
|
||||
regs.a = op_sbc(regs.a, rd);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x99: {
|
||||
op_io();
|
||||
rd = op_readdp(regs.y);
|
||||
wr = op_readdp(regs.x);
|
||||
wr = op_adc(wr, rd);
|
||||
(1) ? op_writedp(regs.x, wr) : op_io();
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x39: {
|
||||
op_io();
|
||||
rd = op_readdp(regs.y);
|
||||
wr = op_readdp(regs.x);
|
||||
wr = op_and(wr, rd);
|
||||
(1) ? op_writedp(regs.x, wr) : op_io();
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x79: {
|
||||
op_io();
|
||||
rd = op_readdp(regs.y);
|
||||
wr = op_readdp(regs.x);
|
||||
wr = op_cmp(wr, rd);
|
||||
(0) ? op_writedp(regs.x, wr) : op_io();
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x59: {
|
||||
op_io();
|
||||
rd = op_readdp(regs.y);
|
||||
wr = op_readdp(regs.x);
|
||||
wr = op_eor(wr, rd);
|
||||
(1) ? op_writedp(regs.x, wr) : op_io();
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x19: {
|
||||
op_io();
|
||||
rd = op_readdp(regs.y);
|
||||
wr = op_readdp(regs.x);
|
||||
wr = op_or(wr, rd);
|
||||
(1) ? op_writedp(regs.x, wr) : op_io();
|
||||
break;
|
||||
}
|
||||
|
||||
case 0xb9: {
|
||||
op_io();
|
||||
rd = op_readdp(regs.y);
|
||||
wr = op_readdp(regs.x);
|
||||
wr = op_sbc(wr, rd);
|
||||
(1) ? op_writedp(regs.x, wr) : op_io();
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x89: {
|
||||
sp = op_readpc();
|
||||
rd = op_readdp(sp);
|
||||
dp = op_readpc();
|
||||
wr = op_readdp(dp);
|
||||
wr = op_adc(wr, rd);
|
||||
(1) ? op_writedp(dp, wr) : op_io();
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x29: {
|
||||
sp = op_readpc();
|
||||
rd = op_readdp(sp);
|
||||
dp = op_readpc();
|
||||
wr = op_readdp(dp);
|
||||
wr = op_and(wr, rd);
|
||||
(1) ? op_writedp(dp, wr) : op_io();
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x69: {
|
||||
sp = op_readpc();
|
||||
rd = op_readdp(sp);
|
||||
dp = op_readpc();
|
||||
wr = op_readdp(dp);
|
||||
wr = op_cmp(wr, rd);
|
||||
(0) ? op_writedp(dp, wr) : op_io();
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x49: {
|
||||
sp = op_readpc();
|
||||
rd = op_readdp(sp);
|
||||
dp = op_readpc();
|
||||
wr = op_readdp(dp);
|
||||
wr = op_eor(wr, rd);
|
||||
(1) ? op_writedp(dp, wr) : op_io();
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x09: {
|
||||
sp = op_readpc();
|
||||
rd = op_readdp(sp);
|
||||
dp = op_readpc();
|
||||
wr = op_readdp(dp);
|
||||
wr = op_or(wr, rd);
|
||||
(1) ? op_writedp(dp, wr) : op_io();
|
||||
break;
|
||||
}
|
||||
|
||||
case 0xa9: {
|
||||
sp = op_readpc();
|
||||
rd = op_readdp(sp);
|
||||
dp = op_readpc();
|
||||
wr = op_readdp(dp);
|
||||
wr = op_sbc(wr, rd);
|
||||
(1) ? op_writedp(dp, wr) : op_io();
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x98: {
|
||||
rd = op_readpc();
|
||||
dp = op_readpc();
|
||||
wr = op_readdp(dp);
|
||||
wr = op_adc(wr, rd);
|
||||
(1) ? op_writedp(dp, wr) : op_io();
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x38: {
|
||||
rd = op_readpc();
|
||||
dp = op_readpc();
|
||||
wr = op_readdp(dp);
|
||||
wr = op_and(wr, rd);
|
||||
(1) ? op_writedp(dp, wr) : op_io();
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x78: {
|
||||
rd = op_readpc();
|
||||
dp = op_readpc();
|
||||
wr = op_readdp(dp);
|
||||
wr = op_cmp(wr, rd);
|
||||
(0) ? op_writedp(dp, wr) : op_io();
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x58: {
|
||||
rd = op_readpc();
|
||||
dp = op_readpc();
|
||||
wr = op_readdp(dp);
|
||||
wr = op_eor(wr, rd);
|
||||
(1) ? op_writedp(dp, wr) : op_io();
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x18: {
|
||||
rd = op_readpc();
|
||||
dp = op_readpc();
|
||||
wr = op_readdp(dp);
|
||||
wr = op_or(wr, rd);
|
||||
(1) ? op_writedp(dp, wr) : op_io();
|
||||
break;
|
||||
}
|
||||
|
||||
case 0xb8: {
|
||||
rd = op_readpc();
|
||||
dp = op_readpc();
|
||||
wr = op_readdp(dp);
|
||||
wr = op_sbc(wr, rd);
|
||||
(1) ? op_writedp(dp, wr) : op_io();
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x7a: {
|
||||
dp = op_readpc();
|
||||
rd = op_readdp(dp);
|
||||
op_io();
|
||||
rd |= op_readdp(dp + 1) << 8;
|
||||
regs.ya = op_addw(regs.ya, rd);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x9a: {
|
||||
dp = op_readpc();
|
||||
rd = op_readdp(dp);
|
||||
op_io();
|
||||
rd |= op_readdp(dp + 1) << 8;
|
||||
regs.ya = op_subw(regs.ya, rd);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x5a: {
|
||||
dp = op_readpc();
|
||||
rd = op_readdp(dp);
|
||||
rd |= op_readdp(dp + 1) << 8;
|
||||
op_cmpw(regs.ya, rd);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x4a: {
|
||||
dp = op_readpc();
|
||||
dp |= op_readpc() << 8;
|
||||
bit = dp >> 13;
|
||||
dp &= 0x1fff;
|
||||
rd = op_readaddr(dp);
|
||||
regs.p.c = regs.p.c & !!(rd & (1 << bit));
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x6a: {
|
||||
dp = op_readpc();
|
||||
dp |= op_readpc() << 8;
|
||||
bit = dp >> 13;
|
||||
dp &= 0x1fff;
|
||||
rd = op_readaddr(dp);
|
||||
regs.p.c = regs.p.c & !(rd & (1 << bit));
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x8a: {
|
||||
dp = op_readpc();
|
||||
dp |= op_readpc() << 8;
|
||||
bit = dp >> 13;
|
||||
dp &= 0x1fff;
|
||||
rd = op_readaddr(dp);
|
||||
op_io();
|
||||
regs.p.c = regs.p.c ^ !!(rd & (1 << bit));
|
||||
break;
|
||||
}
|
||||
|
||||
case 0xea: {
|
||||
dp = op_readpc();
|
||||
dp |= op_readpc() << 8;
|
||||
bit = dp >> 13;
|
||||
dp &= 0x1fff;
|
||||
rd = op_readaddr(dp);
|
||||
rd ^= (1 << bit);
|
||||
op_writeaddr(dp, rd);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x0a: {
|
||||
dp = op_readpc();
|
||||
dp |= op_readpc() << 8;
|
||||
bit = dp >> 13;
|
||||
dp &= 0x1fff;
|
||||
rd = op_readaddr(dp);
|
||||
op_io();
|
||||
regs.p.c = regs.p.c | !!(rd & (1 << bit));
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x2a: {
|
||||
dp = op_readpc();
|
||||
dp |= op_readpc() << 8;
|
||||
bit = dp >> 13;
|
||||
dp &= 0x1fff;
|
||||
rd = op_readaddr(dp);
|
||||
op_io();
|
||||
regs.p.c = regs.p.c | !(rd & (1 << bit));
|
||||
break;
|
||||
}
|
||||
|
74
bsnes/snes/alt/smp/core/op_rmw.b
Executable file
74
bsnes/snes/alt/smp/core/op_rmw.b
Executable file
@@ -0,0 +1,74 @@
|
||||
inc_a(0xbc, inc, a),
|
||||
inc_x(0x3d, inc, x),
|
||||
inc_y(0xfc, inc, y),
|
||||
dec_a(0x9c, dec, a),
|
||||
dec_x(0x1d, dec, x),
|
||||
dec_y(0xdc, dec, y),
|
||||
asl_a(0x1c, asl, a),
|
||||
lsr_a(0x5c, lsr, a),
|
||||
rol_a(0x3c, rol, a),
|
||||
ror_a(0x7c, ror, a) {
|
||||
1:op_io();
|
||||
regs.$2 = op_$1(regs.$2);
|
||||
}
|
||||
|
||||
inc_dp(0xab, inc),
|
||||
dec_dp(0x8b, dec),
|
||||
asl_dp(0x0b, asl),
|
||||
lsr_dp(0x4b, lsr),
|
||||
rol_dp(0x2b, rol),
|
||||
ror_dp(0x6b, ror) {
|
||||
1:dp = op_readpc();
|
||||
2:rd = op_readdp(dp);
|
||||
3:rd = op_$1(rd);
|
||||
op_writedp(dp, rd);
|
||||
}
|
||||
|
||||
inc_dpx(0xbb, inc),
|
||||
dec_dpx(0x9b, dec),
|
||||
asl_dpx(0x1b, asl),
|
||||
lsr_dpx(0x5b, lsr),
|
||||
rol_dpx(0x3b, rol),
|
||||
ror_dpx(0x7b, ror) {
|
||||
1:dp = op_readpc();
|
||||
2:op_io();
|
||||
3:rd = op_readdp(dp + regs.x);
|
||||
4:rd = op_$1(rd);
|
||||
op_writedp(dp + regs.x, rd);
|
||||
}
|
||||
|
||||
inc_addr(0xac, inc),
|
||||
dec_addr(0x8c, dec),
|
||||
asl_addr(0x0c, asl),
|
||||
lsr_addr(0x4c, lsr),
|
||||
rol_addr(0x2c, rol),
|
||||
ror_addr(0x6c, ror) {
|
||||
1:dp = op_readpc();
|
||||
2:dp |= op_readpc() << 8;
|
||||
3:rd = op_readaddr(dp);
|
||||
4:rd = op_$1(rd);
|
||||
op_writeaddr(dp, rd);
|
||||
}
|
||||
|
||||
tset_addr_a(0x0e, |),
|
||||
tclr_addr_a(0x4e, &~) {
|
||||
1:dp = op_readpc();
|
||||
2:dp |= op_readpc() << 8;
|
||||
3:rd = op_readaddr(dp);
|
||||
regs.p.n = !!((regs.a - rd) & 0x80);
|
||||
regs.p.z = ((regs.a - rd) == 0);
|
||||
4:op_readaddr(dp);
|
||||
5:op_writeaddr(dp, rd $1 regs.a);
|
||||
}
|
||||
|
||||
incw_dp(0x3a, ++),
|
||||
decw_dp(0x1a, --) {
|
||||
1:dp = op_readpc();
|
||||
2:rd = op_readdp(dp);
|
||||
rd$1;
|
||||
3:op_writedp(dp++, rd);
|
||||
4:rd += op_readdp(dp) << 8;
|
||||
5:op_writedp(dp, rd >> 8);
|
||||
regs.p.n = !!(rd & 0x8000);
|
||||
regs.p.z = (rd == 0);
|
||||
}
|
262
bsnes/snes/alt/smp/core/op_rmw.cpp
Executable file
262
bsnes/snes/alt/smp/core/op_rmw.cpp
Executable file
@@ -0,0 +1,262 @@
|
||||
case 0xbc: {
|
||||
op_io();
|
||||
regs.a = op_inc(regs.a);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x3d: {
|
||||
op_io();
|
||||
regs.x = op_inc(regs.x);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0xfc: {
|
||||
op_io();
|
||||
regs.y = op_inc(regs.y);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x9c: {
|
||||
op_io();
|
||||
regs.a = op_dec(regs.a);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x1d: {
|
||||
op_io();
|
||||
regs.x = op_dec(regs.x);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0xdc: {
|
||||
op_io();
|
||||
regs.y = op_dec(regs.y);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x1c: {
|
||||
op_io();
|
||||
regs.a = op_asl(regs.a);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x5c: {
|
||||
op_io();
|
||||
regs.a = op_lsr(regs.a);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x3c: {
|
||||
op_io();
|
||||
regs.a = op_rol(regs.a);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x7c: {
|
||||
op_io();
|
||||
regs.a = op_ror(regs.a);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0xab: {
|
||||
dp = op_readpc();
|
||||
rd = op_readdp(dp);
|
||||
rd = op_inc(rd);
|
||||
op_writedp(dp, rd);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x8b: {
|
||||
dp = op_readpc();
|
||||
rd = op_readdp(dp);
|
||||
rd = op_dec(rd);
|
||||
op_writedp(dp, rd);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x0b: {
|
||||
dp = op_readpc();
|
||||
rd = op_readdp(dp);
|
||||
rd = op_asl(rd);
|
||||
op_writedp(dp, rd);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x4b: {
|
||||
dp = op_readpc();
|
||||
rd = op_readdp(dp);
|
||||
rd = op_lsr(rd);
|
||||
op_writedp(dp, rd);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x2b: {
|
||||
dp = op_readpc();
|
||||
rd = op_readdp(dp);
|
||||
rd = op_rol(rd);
|
||||
op_writedp(dp, rd);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x6b: {
|
||||
dp = op_readpc();
|
||||
rd = op_readdp(dp);
|
||||
rd = op_ror(rd);
|
||||
op_writedp(dp, rd);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0xbb: {
|
||||
dp = op_readpc();
|
||||
op_io();
|
||||
rd = op_readdp(dp + regs.x);
|
||||
rd = op_inc(rd);
|
||||
op_writedp(dp + regs.x, rd);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x9b: {
|
||||
dp = op_readpc();
|
||||
op_io();
|
||||
rd = op_readdp(dp + regs.x);
|
||||
rd = op_dec(rd);
|
||||
op_writedp(dp + regs.x, rd);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x1b: {
|
||||
dp = op_readpc();
|
||||
op_io();
|
||||
rd = op_readdp(dp + regs.x);
|
||||
rd = op_asl(rd);
|
||||
op_writedp(dp + regs.x, rd);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x5b: {
|
||||
dp = op_readpc();
|
||||
op_io();
|
||||
rd = op_readdp(dp + regs.x);
|
||||
rd = op_lsr(rd);
|
||||
op_writedp(dp + regs.x, rd);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x3b: {
|
||||
dp = op_readpc();
|
||||
op_io();
|
||||
rd = op_readdp(dp + regs.x);
|
||||
rd = op_rol(rd);
|
||||
op_writedp(dp + regs.x, rd);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x7b: {
|
||||
dp = op_readpc();
|
||||
op_io();
|
||||
rd = op_readdp(dp + regs.x);
|
||||
rd = op_ror(rd);
|
||||
op_writedp(dp + regs.x, rd);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0xac: {
|
||||
dp = op_readpc();
|
||||
dp |= op_readpc() << 8;
|
||||
rd = op_readaddr(dp);
|
||||
rd = op_inc(rd);
|
||||
op_writeaddr(dp, rd);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x8c: {
|
||||
dp = op_readpc();
|
||||
dp |= op_readpc() << 8;
|
||||
rd = op_readaddr(dp);
|
||||
rd = op_dec(rd);
|
||||
op_writeaddr(dp, rd);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x0c: {
|
||||
dp = op_readpc();
|
||||
dp |= op_readpc() << 8;
|
||||
rd = op_readaddr(dp);
|
||||
rd = op_asl(rd);
|
||||
op_writeaddr(dp, rd);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x4c: {
|
||||
dp = op_readpc();
|
||||
dp |= op_readpc() << 8;
|
||||
rd = op_readaddr(dp);
|
||||
rd = op_lsr(rd);
|
||||
op_writeaddr(dp, rd);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x2c: {
|
||||
dp = op_readpc();
|
||||
dp |= op_readpc() << 8;
|
||||
rd = op_readaddr(dp);
|
||||
rd = op_rol(rd);
|
||||
op_writeaddr(dp, rd);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x6c: {
|
||||
dp = op_readpc();
|
||||
dp |= op_readpc() << 8;
|
||||
rd = op_readaddr(dp);
|
||||
rd = op_ror(rd);
|
||||
op_writeaddr(dp, rd);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x0e: {
|
||||
dp = op_readpc();
|
||||
dp |= op_readpc() << 8;
|
||||
rd = op_readaddr(dp);
|
||||
regs.p.n = !!((regs.a - rd) & 0x80);
|
||||
regs.p.z = ((regs.a - rd) == 0);
|
||||
op_readaddr(dp);
|
||||
op_writeaddr(dp, rd | regs.a);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x4e: {
|
||||
dp = op_readpc();
|
||||
dp |= op_readpc() << 8;
|
||||
rd = op_readaddr(dp);
|
||||
regs.p.n = !!((regs.a - rd) & 0x80);
|
||||
regs.p.z = ((regs.a - rd) == 0);
|
||||
op_readaddr(dp);
|
||||
op_writeaddr(dp, rd &~ regs.a);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x3a: {
|
||||
dp = op_readpc();
|
||||
rd = op_readdp(dp);
|
||||
rd++;
|
||||
op_writedp(dp++, rd);
|
||||
rd += op_readdp(dp) << 8;
|
||||
op_writedp(dp, rd >> 8);
|
||||
regs.p.n = !!(rd & 0x8000);
|
||||
regs.p.z = (rd == 0);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x1a: {
|
||||
dp = op_readpc();
|
||||
rd = op_readdp(dp);
|
||||
rd--;
|
||||
op_writedp(dp++, rd);
|
||||
rd += op_readdp(dp) << 8;
|
||||
op_writedp(dp, rd >> 8);
|
||||
regs.p.n = !!(rd & 0x8000);
|
||||
regs.p.z = (rd == 0);
|
||||
break;
|
||||
}
|
||||
|
696
bsnes/snes/alt/smp/core/opcycle_misc.cpp
Executable file
696
bsnes/snes/alt/smp/core/opcycle_misc.cpp
Executable file
@@ -0,0 +1,696 @@
|
||||
case 0x00: {
|
||||
switch(opcode_cycle++) {
|
||||
case 1:
|
||||
op_io();
|
||||
opcode_cycle = 0;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 0xef: {
|
||||
switch(opcode_cycle++) {
|
||||
case 1:
|
||||
op_io();
|
||||
break;
|
||||
case 2:
|
||||
op_io();
|
||||
regs.pc--;
|
||||
opcode_cycle = 0;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 0xff: {
|
||||
switch(opcode_cycle++) {
|
||||
case 1:
|
||||
op_io();
|
||||
break;
|
||||
case 2:
|
||||
op_io();
|
||||
regs.pc--;
|
||||
opcode_cycle = 0;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x9f: {
|
||||
switch(opcode_cycle++) {
|
||||
case 1:
|
||||
op_io();
|
||||
break;
|
||||
case 2:
|
||||
op_io();
|
||||
break;
|
||||
case 3:
|
||||
op_io();
|
||||
break;
|
||||
case 4:
|
||||
op_io();
|
||||
regs.a = (regs.a >> 4) | (regs.a << 4);
|
||||
regs.p.n = !!(regs.a & 0x80);
|
||||
regs.p.z = (regs.a == 0);
|
||||
opcode_cycle = 0;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 0xdf: {
|
||||
switch(opcode_cycle++) {
|
||||
case 1:
|
||||
op_io();
|
||||
break;
|
||||
case 2:
|
||||
op_io();
|
||||
if(regs.p.c || (regs.a) > 0x99) {
|
||||
regs.a += 0x60;
|
||||
regs.p.c = 1;
|
||||
}
|
||||
if(regs.p.h || (regs.a & 15) > 0x09) {
|
||||
regs.a += 0x06;
|
||||
}
|
||||
regs.p.n = !!(regs.a & 0x80);
|
||||
regs.p.z = (regs.a == 0);
|
||||
opcode_cycle = 0;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 0xbe: {
|
||||
switch(opcode_cycle++) {
|
||||
case 1:
|
||||
op_io();
|
||||
break;
|
||||
case 2:
|
||||
op_io();
|
||||
if(!regs.p.c || (regs.a) > 0x99) {
|
||||
regs.a -= 0x60;
|
||||
regs.p.c = 0;
|
||||
}
|
||||
if(!regs.p.h || (regs.a & 15) > 0x09) {
|
||||
regs.a -= 0x06;
|
||||
}
|
||||
regs.p.n = !!(regs.a & 0x80);
|
||||
regs.p.z = (regs.a == 0);
|
||||
opcode_cycle = 0;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x60: {
|
||||
switch(opcode_cycle++) {
|
||||
case 1:
|
||||
op_io();
|
||||
regs.p.c = 0;
|
||||
opcode_cycle = 0;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x20: {
|
||||
switch(opcode_cycle++) {
|
||||
case 1:
|
||||
op_io();
|
||||
regs.p.p = 0;
|
||||
opcode_cycle = 0;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x80: {
|
||||
switch(opcode_cycle++) {
|
||||
case 1:
|
||||
op_io();
|
||||
regs.p.c = 1;
|
||||
opcode_cycle = 0;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x40: {
|
||||
switch(opcode_cycle++) {
|
||||
case 1:
|
||||
op_io();
|
||||
regs.p.p = 1;
|
||||
opcode_cycle = 0;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 0xe0: {
|
||||
switch(opcode_cycle++) {
|
||||
case 1:
|
||||
op_io();
|
||||
regs.p.v = 0;
|
||||
regs.p.h = 0;
|
||||
opcode_cycle = 0;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 0xed: {
|
||||
switch(opcode_cycle++) {
|
||||
case 1:
|
||||
op_io();
|
||||
break;
|
||||
case 2:
|
||||
op_io();
|
||||
regs.p.c = !regs.p.c;
|
||||
opcode_cycle = 0;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 0xa0: {
|
||||
switch(opcode_cycle++) {
|
||||
case 1:
|
||||
op_io();
|
||||
break;
|
||||
case 2:
|
||||
op_io();
|
||||
regs.p.i = 1;
|
||||
opcode_cycle = 0;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 0xc0: {
|
||||
switch(opcode_cycle++) {
|
||||
case 1:
|
||||
op_io();
|
||||
break;
|
||||
case 2:
|
||||
op_io();
|
||||
regs.p.i = 0;
|
||||
opcode_cycle = 0;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x02: {
|
||||
switch(opcode_cycle++) {
|
||||
case 1:
|
||||
dp = op_readpc();
|
||||
break;
|
||||
case 2:
|
||||
rd = op_readdp(dp);
|
||||
break;
|
||||
case 3:
|
||||
rd |= 0x01;
|
||||
op_writedp(dp, rd);
|
||||
opcode_cycle = 0;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x12: {
|
||||
switch(opcode_cycle++) {
|
||||
case 1:
|
||||
dp = op_readpc();
|
||||
break;
|
||||
case 2:
|
||||
rd = op_readdp(dp);
|
||||
break;
|
||||
case 3:
|
||||
rd &= ~0x01;
|
||||
op_writedp(dp, rd);
|
||||
opcode_cycle = 0;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x22: {
|
||||
switch(opcode_cycle++) {
|
||||
case 1:
|
||||
dp = op_readpc();
|
||||
break;
|
||||
case 2:
|
||||
rd = op_readdp(dp);
|
||||
break;
|
||||
case 3:
|
||||
rd |= 0x02;
|
||||
op_writedp(dp, rd);
|
||||
opcode_cycle = 0;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x32: {
|
||||
switch(opcode_cycle++) {
|
||||
case 1:
|
||||
dp = op_readpc();
|
||||
break;
|
||||
case 2:
|
||||
rd = op_readdp(dp);
|
||||
break;
|
||||
case 3:
|
||||
rd &= ~0x02;
|
||||
op_writedp(dp, rd);
|
||||
opcode_cycle = 0;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x42: {
|
||||
switch(opcode_cycle++) {
|
||||
case 1:
|
||||
dp = op_readpc();
|
||||
break;
|
||||
case 2:
|
||||
rd = op_readdp(dp);
|
||||
break;
|
||||
case 3:
|
||||
rd |= 0x04;
|
||||
op_writedp(dp, rd);
|
||||
opcode_cycle = 0;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x52: {
|
||||
switch(opcode_cycle++) {
|
||||
case 1:
|
||||
dp = op_readpc();
|
||||
break;
|
||||
case 2:
|
||||
rd = op_readdp(dp);
|
||||
break;
|
||||
case 3:
|
||||
rd &= ~0x04;
|
||||
op_writedp(dp, rd);
|
||||
opcode_cycle = 0;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x62: {
|
||||
switch(opcode_cycle++) {
|
||||
case 1:
|
||||
dp = op_readpc();
|
||||
break;
|
||||
case 2:
|
||||
rd = op_readdp(dp);
|
||||
break;
|
||||
case 3:
|
||||
rd |= 0x08;
|
||||
op_writedp(dp, rd);
|
||||
opcode_cycle = 0;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x72: {
|
||||
switch(opcode_cycle++) {
|
||||
case 1:
|
||||
dp = op_readpc();
|
||||
break;
|
||||
case 2:
|
||||
rd = op_readdp(dp);
|
||||
break;
|
||||
case 3:
|
||||
rd &= ~0x08;
|
||||
op_writedp(dp, rd);
|
||||
opcode_cycle = 0;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x82: {
|
||||
switch(opcode_cycle++) {
|
||||
case 1:
|
||||
dp = op_readpc();
|
||||
break;
|
||||
case 2:
|
||||
rd = op_readdp(dp);
|
||||
break;
|
||||
case 3:
|
||||
rd |= 0x10;
|
||||
op_writedp(dp, rd);
|
||||
opcode_cycle = 0;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x92: {
|
||||
switch(opcode_cycle++) {
|
||||
case 1:
|
||||
dp = op_readpc();
|
||||
break;
|
||||
case 2:
|
||||
rd = op_readdp(dp);
|
||||
break;
|
||||
case 3:
|
||||
rd &= ~0x10;
|
||||
op_writedp(dp, rd);
|
||||
opcode_cycle = 0;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 0xa2: {
|
||||
switch(opcode_cycle++) {
|
||||
case 1:
|
||||
dp = op_readpc();
|
||||
break;
|
||||
case 2:
|
||||
rd = op_readdp(dp);
|
||||
break;
|
||||
case 3:
|
||||
rd |= 0x20;
|
||||
op_writedp(dp, rd);
|
||||
opcode_cycle = 0;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 0xb2: {
|
||||
switch(opcode_cycle++) {
|
||||
case 1:
|
||||
dp = op_readpc();
|
||||
break;
|
||||
case 2:
|
||||
rd = op_readdp(dp);
|
||||
break;
|
||||
case 3:
|
||||
rd &= ~0x20;
|
||||
op_writedp(dp, rd);
|
||||
opcode_cycle = 0;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 0xc2: {
|
||||
switch(opcode_cycle++) {
|
||||
case 1:
|
||||
dp = op_readpc();
|
||||
break;
|
||||
case 2:
|
||||
rd = op_readdp(dp);
|
||||
break;
|
||||
case 3:
|
||||
rd |= 0x40;
|
||||
op_writedp(dp, rd);
|
||||
opcode_cycle = 0;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 0xd2: {
|
||||
switch(opcode_cycle++) {
|
||||
case 1:
|
||||
dp = op_readpc();
|
||||
break;
|
||||
case 2:
|
||||
rd = op_readdp(dp);
|
||||
break;
|
||||
case 3:
|
||||
rd &= ~0x40;
|
||||
op_writedp(dp, rd);
|
||||
opcode_cycle = 0;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 0xe2: {
|
||||
switch(opcode_cycle++) {
|
||||
case 1:
|
||||
dp = op_readpc();
|
||||
break;
|
||||
case 2:
|
||||
rd = op_readdp(dp);
|
||||
break;
|
||||
case 3:
|
||||
rd |= 0x80;
|
||||
op_writedp(dp, rd);
|
||||
opcode_cycle = 0;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 0xf2: {
|
||||
switch(opcode_cycle++) {
|
||||
case 1:
|
||||
dp = op_readpc();
|
||||
break;
|
||||
case 2:
|
||||
rd = op_readdp(dp);
|
||||
break;
|
||||
case 3:
|
||||
rd &= ~0x80;
|
||||
op_writedp(dp, rd);
|
||||
opcode_cycle = 0;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x2d: {
|
||||
switch(opcode_cycle++) {
|
||||
case 1:
|
||||
op_io();
|
||||
break;
|
||||
case 2:
|
||||
op_io();
|
||||
break;
|
||||
case 3:
|
||||
op_writestack(regs.a);
|
||||
opcode_cycle = 0;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x4d: {
|
||||
switch(opcode_cycle++) {
|
||||
case 1:
|
||||
op_io();
|
||||
break;
|
||||
case 2:
|
||||
op_io();
|
||||
break;
|
||||
case 3:
|
||||
op_writestack(regs.x);
|
||||
opcode_cycle = 0;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x6d: {
|
||||
switch(opcode_cycle++) {
|
||||
case 1:
|
||||
op_io();
|
||||
break;
|
||||
case 2:
|
||||
op_io();
|
||||
break;
|
||||
case 3:
|
||||
op_writestack(regs.y);
|
||||
opcode_cycle = 0;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x0d: {
|
||||
switch(opcode_cycle++) {
|
||||
case 1:
|
||||
op_io();
|
||||
break;
|
||||
case 2:
|
||||
op_io();
|
||||
break;
|
||||
case 3:
|
||||
op_writestack(regs.p);
|
||||
opcode_cycle = 0;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 0xae: {
|
||||
switch(opcode_cycle++) {
|
||||
case 1:
|
||||
op_io();
|
||||
break;
|
||||
case 2:
|
||||
op_io();
|
||||
break;
|
||||
case 3:
|
||||
regs.a = op_readstack();
|
||||
opcode_cycle = 0;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 0xce: {
|
||||
switch(opcode_cycle++) {
|
||||
case 1:
|
||||
op_io();
|
||||
break;
|
||||
case 2:
|
||||
op_io();
|
||||
break;
|
||||
case 3:
|
||||
regs.x = op_readstack();
|
||||
opcode_cycle = 0;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 0xee: {
|
||||
switch(opcode_cycle++) {
|
||||
case 1:
|
||||
op_io();
|
||||
break;
|
||||
case 2:
|
||||
op_io();
|
||||
break;
|
||||
case 3:
|
||||
regs.y = op_readstack();
|
||||
opcode_cycle = 0;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x8e: {
|
||||
switch(opcode_cycle++) {
|
||||
case 1:
|
||||
op_io();
|
||||
break;
|
||||
case 2:
|
||||
op_io();
|
||||
break;
|
||||
case 3:
|
||||
regs.p = op_readstack();
|
||||
opcode_cycle = 0;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 0xcf: {
|
||||
switch(opcode_cycle++) {
|
||||
case 1:
|
||||
op_io();
|
||||
break;
|
||||
case 2:
|
||||
op_io();
|
||||
break;
|
||||
case 3:
|
||||
op_io();
|
||||
break;
|
||||
case 4:
|
||||
op_io();
|
||||
break;
|
||||
case 5:
|
||||
op_io();
|
||||
break;
|
||||
case 6:
|
||||
op_io();
|
||||
break;
|
||||
case 7:
|
||||
op_io();
|
||||
break;
|
||||
case 8:
|
||||
op_io();
|
||||
ya = regs.y * regs.a;
|
||||
regs.a = ya;
|
||||
regs.y = ya >> 8;
|
||||
//result is set based on y (high-byte) only
|
||||
regs.p.n = !!(regs.y & 0x80);
|
||||
regs.p.z = (regs.y == 0);
|
||||
opcode_cycle = 0;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x9e: {
|
||||
switch(opcode_cycle++) {
|
||||
case 1:
|
||||
op_io();
|
||||
break;
|
||||
case 2:
|
||||
op_io();
|
||||
break;
|
||||
case 3:
|
||||
op_io();
|
||||
break;
|
||||
case 4:
|
||||
op_io();
|
||||
break;
|
||||
case 5:
|
||||
op_io();
|
||||
break;
|
||||
case 6:
|
||||
op_io();
|
||||
break;
|
||||
case 7:
|
||||
op_io();
|
||||
break;
|
||||
case 8:
|
||||
op_io();
|
||||
break;
|
||||
case 9:
|
||||
op_io();
|
||||
break;
|
||||
case 10:
|
||||
op_io();
|
||||
break;
|
||||
case 11:
|
||||
op_io();
|
||||
ya = regs.ya;
|
||||
//overflow set if quotient >= 256
|
||||
regs.p.v = !!(regs.y >= regs.x);
|
||||
regs.p.h = !!((regs.y & 15) >= (regs.x & 15));
|
||||
if(regs.y < (regs.x << 1)) {
|
||||
//if quotient is <= 511 (will fit into 9-bit result)
|
||||
regs.a = ya / regs.x;
|
||||
regs.y = ya % regs.x;
|
||||
} else {
|
||||
//otherwise, the quotient won't fit into regs.p.v + regs.a
|
||||
//this emulates the odd behavior of the S-SMP in this case
|
||||
regs.a = 255 - (ya - (regs.x << 9)) / (256 - regs.x);
|
||||
regs.y = regs.x + (ya - (regs.x << 9)) % (256 - regs.x);
|
||||
}
|
||||
//result is set based on a (quotient) only
|
||||
regs.p.n = !!(regs.a & 0x80);
|
||||
regs.p.z = (regs.a == 0);
|
||||
opcode_cycle = 0;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
806
bsnes/snes/alt/smp/core/opcycle_mov.cpp
Executable file
806
bsnes/snes/alt/smp/core/opcycle_mov.cpp
Executable file
@@ -0,0 +1,806 @@
|
||||
case 0x7d: {
|
||||
switch(opcode_cycle++) {
|
||||
case 1:
|
||||
op_io();
|
||||
regs.a = regs.x;
|
||||
regs.p.n = !!(regs.a & 0x80);
|
||||
regs.p.z = (regs.a == 0);
|
||||
opcode_cycle = 0;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 0xdd: {
|
||||
switch(opcode_cycle++) {
|
||||
case 1:
|
||||
op_io();
|
||||
regs.a = regs.y;
|
||||
regs.p.n = !!(regs.a & 0x80);
|
||||
regs.p.z = (regs.a == 0);
|
||||
opcode_cycle = 0;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x5d: {
|
||||
switch(opcode_cycle++) {
|
||||
case 1:
|
||||
op_io();
|
||||
regs.x = regs.a;
|
||||
regs.p.n = !!(regs.x & 0x80);
|
||||
regs.p.z = (regs.x == 0);
|
||||
opcode_cycle = 0;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 0xfd: {
|
||||
switch(opcode_cycle++) {
|
||||
case 1:
|
||||
op_io();
|
||||
regs.y = regs.a;
|
||||
regs.p.n = !!(regs.y & 0x80);
|
||||
regs.p.z = (regs.y == 0);
|
||||
opcode_cycle = 0;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x9d: {
|
||||
switch(opcode_cycle++) {
|
||||
case 1:
|
||||
op_io();
|
||||
regs.x = regs.sp;
|
||||
regs.p.n = !!(regs.x & 0x80);
|
||||
regs.p.z = (regs.x == 0);
|
||||
opcode_cycle = 0;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 0xbd: {
|
||||
switch(opcode_cycle++) {
|
||||
case 1:
|
||||
op_io();
|
||||
regs.sp = regs.x;
|
||||
opcode_cycle = 0;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 0xe8: {
|
||||
switch(opcode_cycle++) {
|
||||
case 1:
|
||||
regs.a = op_readpc();
|
||||
regs.p.n = !!(regs.a & 0x80);
|
||||
regs.p.z = (regs.a == 0);
|
||||
opcode_cycle = 0;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 0xcd: {
|
||||
switch(opcode_cycle++) {
|
||||
case 1:
|
||||
regs.x = op_readpc();
|
||||
regs.p.n = !!(regs.x & 0x80);
|
||||
regs.p.z = (regs.x == 0);
|
||||
opcode_cycle = 0;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x8d: {
|
||||
switch(opcode_cycle++) {
|
||||
case 1:
|
||||
regs.y = op_readpc();
|
||||
regs.p.n = !!(regs.y & 0x80);
|
||||
regs.p.z = (regs.y == 0);
|
||||
opcode_cycle = 0;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 0xe6: {
|
||||
switch(opcode_cycle++) {
|
||||
case 1:
|
||||
op_io();
|
||||
break;
|
||||
case 2:
|
||||
regs.a = op_readdp(regs.x);
|
||||
regs.p.n = !!(regs.a & 0x80);
|
||||
regs.p.z = (regs.a == 0);
|
||||
opcode_cycle = 0;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 0xbf: {
|
||||
switch(opcode_cycle++) {
|
||||
case 1:
|
||||
op_io();
|
||||
break;
|
||||
case 2:
|
||||
regs.a = op_readdp(regs.x++);
|
||||
break;
|
||||
case 3:
|
||||
op_io();
|
||||
regs.p.n = !!(regs.a & 0x80);
|
||||
regs.p.z = (regs.a == 0);
|
||||
opcode_cycle = 0;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 0xe4: {
|
||||
switch(opcode_cycle++) {
|
||||
case 1:
|
||||
sp = op_readpc();
|
||||
break;
|
||||
case 2:
|
||||
regs.a = op_readdp(sp);
|
||||
regs.p.n = !!(regs.a & 0x80);
|
||||
regs.p.z = (regs.a == 0);
|
||||
opcode_cycle = 0;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 0xf8: {
|
||||
switch(opcode_cycle++) {
|
||||
case 1:
|
||||
sp = op_readpc();
|
||||
break;
|
||||
case 2:
|
||||
regs.x = op_readdp(sp);
|
||||
regs.p.n = !!(regs.x & 0x80);
|
||||
regs.p.z = (regs.x == 0);
|
||||
opcode_cycle = 0;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 0xeb: {
|
||||
switch(opcode_cycle++) {
|
||||
case 1:
|
||||
sp = op_readpc();
|
||||
break;
|
||||
case 2:
|
||||
regs.y = op_readdp(sp);
|
||||
regs.p.n = !!(regs.y & 0x80);
|
||||
regs.p.z = (regs.y == 0);
|
||||
opcode_cycle = 0;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 0xf4: {
|
||||
switch(opcode_cycle++) {
|
||||
case 1:
|
||||
sp = op_readpc();
|
||||
break;
|
||||
case 2:
|
||||
op_io();
|
||||
break;
|
||||
case 3:
|
||||
regs.a = op_readdp(sp + regs.x);
|
||||
regs.p.n = !!(regs.a & 0x80);
|
||||
regs.p.z = (regs.a == 0);
|
||||
opcode_cycle = 0;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 0xf9: {
|
||||
switch(opcode_cycle++) {
|
||||
case 1:
|
||||
sp = op_readpc();
|
||||
break;
|
||||
case 2:
|
||||
op_io();
|
||||
break;
|
||||
case 3:
|
||||
regs.x = op_readdp(sp + regs.y);
|
||||
regs.p.n = !!(regs.x & 0x80);
|
||||
regs.p.z = (regs.x == 0);
|
||||
opcode_cycle = 0;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 0xfb: {
|
||||
switch(opcode_cycle++) {
|
||||
case 1:
|
||||
sp = op_readpc();
|
||||
break;
|
||||
case 2:
|
||||
op_io();
|
||||
break;
|
||||
case 3:
|
||||
regs.y = op_readdp(sp + regs.x);
|
||||
regs.p.n = !!(regs.y & 0x80);
|
||||
regs.p.z = (regs.y == 0);
|
||||
opcode_cycle = 0;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 0xe5: {
|
||||
switch(opcode_cycle++) {
|
||||
case 1:
|
||||
sp = op_readpc();
|
||||
break;
|
||||
case 2:
|
||||
sp |= op_readpc() << 8;
|
||||
break;
|
||||
case 3:
|
||||
regs.a = op_readaddr(sp);
|
||||
regs.p.n = !!(regs.a & 0x80);
|
||||
regs.p.z = (regs.a == 0);
|
||||
opcode_cycle = 0;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 0xe9: {
|
||||
switch(opcode_cycle++) {
|
||||
case 1:
|
||||
sp = op_readpc();
|
||||
break;
|
||||
case 2:
|
||||
sp |= op_readpc() << 8;
|
||||
break;
|
||||
case 3:
|
||||
regs.x = op_readaddr(sp);
|
||||
regs.p.n = !!(regs.x & 0x80);
|
||||
regs.p.z = (regs.x == 0);
|
||||
opcode_cycle = 0;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 0xec: {
|
||||
switch(opcode_cycle++) {
|
||||
case 1:
|
||||
sp = op_readpc();
|
||||
break;
|
||||
case 2:
|
||||
sp |= op_readpc() << 8;
|
||||
break;
|
||||
case 3:
|
||||
regs.y = op_readaddr(sp);
|
||||
regs.p.n = !!(regs.y & 0x80);
|
||||
regs.p.z = (regs.y == 0);
|
||||
opcode_cycle = 0;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 0xf5: {
|
||||
switch(opcode_cycle++) {
|
||||
case 1:
|
||||
sp = op_readpc();
|
||||
break;
|
||||
case 2:
|
||||
sp |= op_readpc() << 8;
|
||||
break;
|
||||
case 3:
|
||||
op_io();
|
||||
break;
|
||||
case 4:
|
||||
regs.a = op_readaddr(sp + regs.x);
|
||||
regs.p.n = !!(regs.a & 0x80);
|
||||
regs.p.z = (regs.a == 0);
|
||||
opcode_cycle = 0;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 0xf6: {
|
||||
switch(opcode_cycle++) {
|
||||
case 1:
|
||||
sp = op_readpc();
|
||||
break;
|
||||
case 2:
|
||||
sp |= op_readpc() << 8;
|
||||
break;
|
||||
case 3:
|
||||
op_io();
|
||||
break;
|
||||
case 4:
|
||||
regs.a = op_readaddr(sp + regs.y);
|
||||
regs.p.n = !!(regs.a & 0x80);
|
||||
regs.p.z = (regs.a == 0);
|
||||
opcode_cycle = 0;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 0xe7: {
|
||||
switch(opcode_cycle++) {
|
||||
case 1:
|
||||
dp = op_readpc() + regs.x;
|
||||
break;
|
||||
case 2:
|
||||
op_io();
|
||||
break;
|
||||
case 3:
|
||||
sp = op_readdp(dp);
|
||||
break;
|
||||
case 4:
|
||||
sp |= op_readdp(dp + 1) << 8;
|
||||
break;
|
||||
case 5:
|
||||
regs.a = op_readaddr(sp);
|
||||
regs.p.n = !!(regs.a & 0x80);
|
||||
regs.p.z = (regs.a == 0);
|
||||
opcode_cycle = 0;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 0xf7: {
|
||||
switch(opcode_cycle++) {
|
||||
case 1:
|
||||
dp = op_readpc();
|
||||
break;
|
||||
case 2:
|
||||
op_io();
|
||||
break;
|
||||
case 3:
|
||||
sp = op_readdp(dp);
|
||||
break;
|
||||
case 4:
|
||||
sp |= op_readdp(dp + 1) << 8;
|
||||
break;
|
||||
case 5:
|
||||
regs.a = op_readaddr(sp + regs.y);
|
||||
regs.p.n = !!(regs.a & 0x80);
|
||||
regs.p.z = (regs.a == 0);
|
||||
opcode_cycle = 0;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 0xfa: {
|
||||
switch(opcode_cycle++) {
|
||||
case 1:
|
||||
sp = op_readpc();
|
||||
break;
|
||||
case 2:
|
||||
rd = op_readdp(sp);
|
||||
break;
|
||||
case 3:
|
||||
dp = op_readpc();
|
||||
break;
|
||||
case 4:
|
||||
op_writedp(dp, rd);
|
||||
opcode_cycle = 0;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x8f: {
|
||||
switch(opcode_cycle++) {
|
||||
case 1:
|
||||
rd = op_readpc();
|
||||
break;
|
||||
case 2:
|
||||
dp = op_readpc();
|
||||
break;
|
||||
case 3:
|
||||
op_readdp(dp);
|
||||
break;
|
||||
case 4:
|
||||
op_writedp(dp, rd);
|
||||
opcode_cycle = 0;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 0xc6: {
|
||||
switch(opcode_cycle++) {
|
||||
case 1:
|
||||
op_io();
|
||||
break;
|
||||
case 2:
|
||||
op_readdp(regs.x);
|
||||
break;
|
||||
case 3:
|
||||
op_writedp(regs.x, regs.a);
|
||||
opcode_cycle = 0;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 0xaf: {
|
||||
switch(opcode_cycle++) {
|
||||
case 1:
|
||||
op_io();
|
||||
break;
|
||||
case 2:
|
||||
op_io();
|
||||
break;
|
||||
case 3:
|
||||
op_writedp(regs.x++, regs.a);
|
||||
opcode_cycle = 0;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 0xc4: {
|
||||
switch(opcode_cycle++) {
|
||||
case 1:
|
||||
dp = op_readpc();
|
||||
break;
|
||||
case 2:
|
||||
op_readdp(dp);
|
||||
break;
|
||||
case 3:
|
||||
op_writedp(dp, regs.a);
|
||||
opcode_cycle = 0;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 0xd8: {
|
||||
switch(opcode_cycle++) {
|
||||
case 1:
|
||||
dp = op_readpc();
|
||||
break;
|
||||
case 2:
|
||||
op_readdp(dp);
|
||||
break;
|
||||
case 3:
|
||||
op_writedp(dp, regs.x);
|
||||
opcode_cycle = 0;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 0xcb: {
|
||||
switch(opcode_cycle++) {
|
||||
case 1:
|
||||
dp = op_readpc();
|
||||
break;
|
||||
case 2:
|
||||
op_readdp(dp);
|
||||
break;
|
||||
case 3:
|
||||
op_writedp(dp, regs.y);
|
||||
opcode_cycle = 0;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 0xd4: {
|
||||
switch(opcode_cycle++) {
|
||||
case 1:
|
||||
dp = op_readpc();
|
||||
break;
|
||||
case 2:
|
||||
op_io();
|
||||
dp += regs.x;
|
||||
break;
|
||||
case 3:
|
||||
op_readdp(dp);
|
||||
break;
|
||||
case 4:
|
||||
op_writedp(dp, regs.a);
|
||||
opcode_cycle = 0;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 0xd9: {
|
||||
switch(opcode_cycle++) {
|
||||
case 1:
|
||||
dp = op_readpc();
|
||||
break;
|
||||
case 2:
|
||||
op_io();
|
||||
dp += regs.y;
|
||||
break;
|
||||
case 3:
|
||||
op_readdp(dp);
|
||||
break;
|
||||
case 4:
|
||||
op_writedp(dp, regs.x);
|
||||
opcode_cycle = 0;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 0xdb: {
|
||||
switch(opcode_cycle++) {
|
||||
case 1:
|
||||
dp = op_readpc();
|
||||
break;
|
||||
case 2:
|
||||
op_io();
|
||||
dp += regs.x;
|
||||
break;
|
||||
case 3:
|
||||
op_readdp(dp);
|
||||
break;
|
||||
case 4:
|
||||
op_writedp(dp, regs.y);
|
||||
opcode_cycle = 0;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 0xc5: {
|
||||
switch(opcode_cycle++) {
|
||||
case 1:
|
||||
dp = op_readpc();
|
||||
break;
|
||||
case 2:
|
||||
dp |= op_readpc() << 8;
|
||||
break;
|
||||
case 3:
|
||||
op_readaddr(dp);
|
||||
break;
|
||||
case 4:
|
||||
op_writeaddr(dp, regs.a);
|
||||
opcode_cycle = 0;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 0xc9: {
|
||||
switch(opcode_cycle++) {
|
||||
case 1:
|
||||
dp = op_readpc();
|
||||
break;
|
||||
case 2:
|
||||
dp |= op_readpc() << 8;
|
||||
break;
|
||||
case 3:
|
||||
op_readaddr(dp);
|
||||
break;
|
||||
case 4:
|
||||
op_writeaddr(dp, regs.x);
|
||||
opcode_cycle = 0;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 0xcc: {
|
||||
switch(opcode_cycle++) {
|
||||
case 1:
|
||||
dp = op_readpc();
|
||||
break;
|
||||
case 2:
|
||||
dp |= op_readpc() << 8;
|
||||
break;
|
||||
case 3:
|
||||
op_readaddr(dp);
|
||||
break;
|
||||
case 4:
|
||||
op_writeaddr(dp, regs.y);
|
||||
opcode_cycle = 0;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 0xd5: {
|
||||
switch(opcode_cycle++) {
|
||||
case 1:
|
||||
dp = op_readpc();
|
||||
break;
|
||||
case 2:
|
||||
dp |= op_readpc() << 8;
|
||||
break;
|
||||
case 3:
|
||||
op_io();
|
||||
dp += regs.x;
|
||||
break;
|
||||
case 4:
|
||||
op_readaddr(dp);
|
||||
break;
|
||||
case 5:
|
||||
op_writeaddr(dp, regs.a);
|
||||
opcode_cycle = 0;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 0xd6: {
|
||||
switch(opcode_cycle++) {
|
||||
case 1:
|
||||
dp = op_readpc();
|
||||
break;
|
||||
case 2:
|
||||
dp |= op_readpc() << 8;
|
||||
break;
|
||||
case 3:
|
||||
op_io();
|
||||
dp += regs.y;
|
||||
break;
|
||||
case 4:
|
||||
op_readaddr(dp);
|
||||
break;
|
||||
case 5:
|
||||
op_writeaddr(dp, regs.a);
|
||||
opcode_cycle = 0;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 0xc7: {
|
||||
switch(opcode_cycle++) {
|
||||
case 1:
|
||||
sp = op_readpc();
|
||||
break;
|
||||
case 2:
|
||||
op_io();
|
||||
sp += regs.x;
|
||||
break;
|
||||
case 3:
|
||||
dp = op_readdp(sp);
|
||||
break;
|
||||
case 4:
|
||||
dp |= op_readdp(sp + 1) << 8;
|
||||
break;
|
||||
case 5:
|
||||
op_readaddr(dp);
|
||||
break;
|
||||
case 6:
|
||||
op_writeaddr(dp, regs.a);
|
||||
opcode_cycle = 0;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 0xd7: {
|
||||
switch(opcode_cycle++) {
|
||||
case 1:
|
||||
sp = op_readpc();
|
||||
break;
|
||||
case 2:
|
||||
dp = op_readdp(sp);
|
||||
break;
|
||||
case 3:
|
||||
dp |= op_readdp(sp + 1) << 8;
|
||||
break;
|
||||
case 4:
|
||||
op_io();
|
||||
dp += regs.y;
|
||||
break;
|
||||
case 5:
|
||||
op_readaddr(dp);
|
||||
break;
|
||||
case 6:
|
||||
op_writeaddr(dp, regs.a);
|
||||
opcode_cycle = 0;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 0xba: {
|
||||
switch(opcode_cycle++) {
|
||||
case 1:
|
||||
sp = op_readpc();
|
||||
break;
|
||||
case 2:
|
||||
regs.a = op_readdp(sp);
|
||||
break;
|
||||
case 3:
|
||||
op_io();
|
||||
break;
|
||||
case 4:
|
||||
regs.y = op_readdp(sp + 1);
|
||||
regs.p.n = !!(regs.ya & 0x8000);
|
||||
regs.p.z = (regs.ya == 0);
|
||||
opcode_cycle = 0;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 0xda: {
|
||||
switch(opcode_cycle++) {
|
||||
case 1:
|
||||
dp = op_readpc();
|
||||
break;
|
||||
case 2:
|
||||
op_readdp(dp);
|
||||
break;
|
||||
case 3:
|
||||
op_writedp(dp, regs.a);
|
||||
break;
|
||||
case 4:
|
||||
op_writedp(dp + 1, regs.y);
|
||||
opcode_cycle = 0;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 0xaa: {
|
||||
switch(opcode_cycle++) {
|
||||
case 1:
|
||||
sp = op_readpc();
|
||||
break;
|
||||
case 2:
|
||||
sp |= op_readpc() << 8;
|
||||
break;
|
||||
case 3:
|
||||
bit = sp >> 13;
|
||||
sp &= 0x1fff;
|
||||
rd = op_readaddr(sp);
|
||||
regs.p.c = !!(rd & (1 << bit));
|
||||
opcode_cycle = 0;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 0xca: {
|
||||
switch(opcode_cycle++) {
|
||||
case 1:
|
||||
dp = op_readpc();
|
||||
break;
|
||||
case 2:
|
||||
dp |= op_readpc() << 8;
|
||||
break;
|
||||
case 3:
|
||||
bit = dp >> 13;
|
||||
dp &= 0x1fff;
|
||||
rd = op_readaddr(dp);
|
||||
if(regs.p.c)rd |= (1 << bit);
|
||||
else rd &= ~(1 << bit);
|
||||
break;
|
||||
case 4:
|
||||
op_io();
|
||||
break;
|
||||
case 5:
|
||||
op_writeaddr(dp, rd);
|
||||
opcode_cycle = 0;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
1347
bsnes/snes/alt/smp/core/opcycle_pc.cpp
Executable file
1347
bsnes/snes/alt/smp/core/opcycle_pc.cpp
Executable file
File diff suppressed because it is too large
Load Diff
1599
bsnes/snes/alt/smp/core/opcycle_read.cpp
Executable file
1599
bsnes/snes/alt/smp/core/opcycle_read.cpp
Executable file
File diff suppressed because it is too large
Load Diff
550
bsnes/snes/alt/smp/core/opcycle_rmw.cpp
Executable file
550
bsnes/snes/alt/smp/core/opcycle_rmw.cpp
Executable file
@@ -0,0 +1,550 @@
|
||||
case 0xbc: {
|
||||
switch(opcode_cycle++) {
|
||||
case 1:
|
||||
op_io();
|
||||
regs.a = op_inc(regs.a);
|
||||
opcode_cycle = 0;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x3d: {
|
||||
switch(opcode_cycle++) {
|
||||
case 1:
|
||||
op_io();
|
||||
regs.x = op_inc(regs.x);
|
||||
opcode_cycle = 0;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 0xfc: {
|
||||
switch(opcode_cycle++) {
|
||||
case 1:
|
||||
op_io();
|
||||
regs.y = op_inc(regs.y);
|
||||
opcode_cycle = 0;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x9c: {
|
||||
switch(opcode_cycle++) {
|
||||
case 1:
|
||||
op_io();
|
||||
regs.a = op_dec(regs.a);
|
||||
opcode_cycle = 0;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x1d: {
|
||||
switch(opcode_cycle++) {
|
||||
case 1:
|
||||
op_io();
|
||||
regs.x = op_dec(regs.x);
|
||||
opcode_cycle = 0;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 0xdc: {
|
||||
switch(opcode_cycle++) {
|
||||
case 1:
|
||||
op_io();
|
||||
regs.y = op_dec(regs.y);
|
||||
opcode_cycle = 0;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x1c: {
|
||||
switch(opcode_cycle++) {
|
||||
case 1:
|
||||
op_io();
|
||||
regs.a = op_asl(regs.a);
|
||||
opcode_cycle = 0;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x5c: {
|
||||
switch(opcode_cycle++) {
|
||||
case 1:
|
||||
op_io();
|
||||
regs.a = op_lsr(regs.a);
|
||||
opcode_cycle = 0;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x3c: {
|
||||
switch(opcode_cycle++) {
|
||||
case 1:
|
||||
op_io();
|
||||
regs.a = op_rol(regs.a);
|
||||
opcode_cycle = 0;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x7c: {
|
||||
switch(opcode_cycle++) {
|
||||
case 1:
|
||||
op_io();
|
||||
regs.a = op_ror(regs.a);
|
||||
opcode_cycle = 0;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 0xab: {
|
||||
switch(opcode_cycle++) {
|
||||
case 1:
|
||||
dp = op_readpc();
|
||||
break;
|
||||
case 2:
|
||||
rd = op_readdp(dp);
|
||||
break;
|
||||
case 3:
|
||||
rd = op_inc(rd);
|
||||
op_writedp(dp, rd);
|
||||
opcode_cycle = 0;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x8b: {
|
||||
switch(opcode_cycle++) {
|
||||
case 1:
|
||||
dp = op_readpc();
|
||||
break;
|
||||
case 2:
|
||||
rd = op_readdp(dp);
|
||||
break;
|
||||
case 3:
|
||||
rd = op_dec(rd);
|
||||
op_writedp(dp, rd);
|
||||
opcode_cycle = 0;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x0b: {
|
||||
switch(opcode_cycle++) {
|
||||
case 1:
|
||||
dp = op_readpc();
|
||||
break;
|
||||
case 2:
|
||||
rd = op_readdp(dp);
|
||||
break;
|
||||
case 3:
|
||||
rd = op_asl(rd);
|
||||
op_writedp(dp, rd);
|
||||
opcode_cycle = 0;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x4b: {
|
||||
switch(opcode_cycle++) {
|
||||
case 1:
|
||||
dp = op_readpc();
|
||||
break;
|
||||
case 2:
|
||||
rd = op_readdp(dp);
|
||||
break;
|
||||
case 3:
|
||||
rd = op_lsr(rd);
|
||||
op_writedp(dp, rd);
|
||||
opcode_cycle = 0;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x2b: {
|
||||
switch(opcode_cycle++) {
|
||||
case 1:
|
||||
dp = op_readpc();
|
||||
break;
|
||||
case 2:
|
||||
rd = op_readdp(dp);
|
||||
break;
|
||||
case 3:
|
||||
rd = op_rol(rd);
|
||||
op_writedp(dp, rd);
|
||||
opcode_cycle = 0;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x6b: {
|
||||
switch(opcode_cycle++) {
|
||||
case 1:
|
||||
dp = op_readpc();
|
||||
break;
|
||||
case 2:
|
||||
rd = op_readdp(dp);
|
||||
break;
|
||||
case 3:
|
||||
rd = op_ror(rd);
|
||||
op_writedp(dp, rd);
|
||||
opcode_cycle = 0;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 0xbb: {
|
||||
switch(opcode_cycle++) {
|
||||
case 1:
|
||||
dp = op_readpc();
|
||||
break;
|
||||
case 2:
|
||||
op_io();
|
||||
break;
|
||||
case 3:
|
||||
rd = op_readdp(dp + regs.x);
|
||||
break;
|
||||
case 4:
|
||||
rd = op_inc(rd);
|
||||
op_writedp(dp + regs.x, rd);
|
||||
opcode_cycle = 0;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x9b: {
|
||||
switch(opcode_cycle++) {
|
||||
case 1:
|
||||
dp = op_readpc();
|
||||
break;
|
||||
case 2:
|
||||
op_io();
|
||||
break;
|
||||
case 3:
|
||||
rd = op_readdp(dp + regs.x);
|
||||
break;
|
||||
case 4:
|
||||
rd = op_dec(rd);
|
||||
op_writedp(dp + regs.x, rd);
|
||||
opcode_cycle = 0;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x1b: {
|
||||
switch(opcode_cycle++) {
|
||||
case 1:
|
||||
dp = op_readpc();
|
||||
break;
|
||||
case 2:
|
||||
op_io();
|
||||
break;
|
||||
case 3:
|
||||
rd = op_readdp(dp + regs.x);
|
||||
break;
|
||||
case 4:
|
||||
rd = op_asl(rd);
|
||||
op_writedp(dp + regs.x, rd);
|
||||
opcode_cycle = 0;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x5b: {
|
||||
switch(opcode_cycle++) {
|
||||
case 1:
|
||||
dp = op_readpc();
|
||||
break;
|
||||
case 2:
|
||||
op_io();
|
||||
break;
|
||||
case 3:
|
||||
rd = op_readdp(dp + regs.x);
|
||||
break;
|
||||
case 4:
|
||||
rd = op_lsr(rd);
|
||||
op_writedp(dp + regs.x, rd);
|
||||
opcode_cycle = 0;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x3b: {
|
||||
switch(opcode_cycle++) {
|
||||
case 1:
|
||||
dp = op_readpc();
|
||||
break;
|
||||
case 2:
|
||||
op_io();
|
||||
break;
|
||||
case 3:
|
||||
rd = op_readdp(dp + regs.x);
|
||||
break;
|
||||
case 4:
|
||||
rd = op_rol(rd);
|
||||
op_writedp(dp + regs.x, rd);
|
||||
opcode_cycle = 0;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x7b: {
|
||||
switch(opcode_cycle++) {
|
||||
case 1:
|
||||
dp = op_readpc();
|
||||
break;
|
||||
case 2:
|
||||
op_io();
|
||||
break;
|
||||
case 3:
|
||||
rd = op_readdp(dp + regs.x);
|
||||
break;
|
||||
case 4:
|
||||
rd = op_ror(rd);
|
||||
op_writedp(dp + regs.x, rd);
|
||||
opcode_cycle = 0;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 0xac: {
|
||||
switch(opcode_cycle++) {
|
||||
case 1:
|
||||
dp = op_readpc();
|
||||
break;
|
||||
case 2:
|
||||
dp |= op_readpc() << 8;
|
||||
break;
|
||||
case 3:
|
||||
rd = op_readaddr(dp);
|
||||
break;
|
||||
case 4:
|
||||
rd = op_inc(rd);
|
||||
op_writeaddr(dp, rd);
|
||||
opcode_cycle = 0;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x8c: {
|
||||
switch(opcode_cycle++) {
|
||||
case 1:
|
||||
dp = op_readpc();
|
||||
break;
|
||||
case 2:
|
||||
dp |= op_readpc() << 8;
|
||||
break;
|
||||
case 3:
|
||||
rd = op_readaddr(dp);
|
||||
break;
|
||||
case 4:
|
||||
rd = op_dec(rd);
|
||||
op_writeaddr(dp, rd);
|
||||
opcode_cycle = 0;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x0c: {
|
||||
switch(opcode_cycle++) {
|
||||
case 1:
|
||||
dp = op_readpc();
|
||||
break;
|
||||
case 2:
|
||||
dp |= op_readpc() << 8;
|
||||
break;
|
||||
case 3:
|
||||
rd = op_readaddr(dp);
|
||||
break;
|
||||
case 4:
|
||||
rd = op_asl(rd);
|
||||
op_writeaddr(dp, rd);
|
||||
opcode_cycle = 0;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x4c: {
|
||||
switch(opcode_cycle++) {
|
||||
case 1:
|
||||
dp = op_readpc();
|
||||
break;
|
||||
case 2:
|
||||
dp |= op_readpc() << 8;
|
||||
break;
|
||||
case 3:
|
||||
rd = op_readaddr(dp);
|
||||
break;
|
||||
case 4:
|
||||
rd = op_lsr(rd);
|
||||
op_writeaddr(dp, rd);
|
||||
opcode_cycle = 0;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x2c: {
|
||||
switch(opcode_cycle++) {
|
||||
case 1:
|
||||
dp = op_readpc();
|
||||
break;
|
||||
case 2:
|
||||
dp |= op_readpc() << 8;
|
||||
break;
|
||||
case 3:
|
||||
rd = op_readaddr(dp);
|
||||
break;
|
||||
case 4:
|
||||
rd = op_rol(rd);
|
||||
op_writeaddr(dp, rd);
|
||||
opcode_cycle = 0;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x6c: {
|
||||
switch(opcode_cycle++) {
|
||||
case 1:
|
||||
dp = op_readpc();
|
||||
break;
|
||||
case 2:
|
||||
dp |= op_readpc() << 8;
|
||||
break;
|
||||
case 3:
|
||||
rd = op_readaddr(dp);
|
||||
break;
|
||||
case 4:
|
||||
rd = op_ror(rd);
|
||||
op_writeaddr(dp, rd);
|
||||
opcode_cycle = 0;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x0e: {
|
||||
switch(opcode_cycle++) {
|
||||
case 1:
|
||||
dp = op_readpc();
|
||||
break;
|
||||
case 2:
|
||||
dp |= op_readpc() << 8;
|
||||
break;
|
||||
case 3:
|
||||
rd = op_readaddr(dp);
|
||||
regs.p.n = !!((regs.a - rd) & 0x80);
|
||||
regs.p.z = ((regs.a - rd) == 0);
|
||||
break;
|
||||
case 4:
|
||||
op_readaddr(dp);
|
||||
break;
|
||||
case 5:
|
||||
op_writeaddr(dp, rd | regs.a);
|
||||
opcode_cycle = 0;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x4e: {
|
||||
switch(opcode_cycle++) {
|
||||
case 1:
|
||||
dp = op_readpc();
|
||||
break;
|
||||
case 2:
|
||||
dp |= op_readpc() << 8;
|
||||
break;
|
||||
case 3:
|
||||
rd = op_readaddr(dp);
|
||||
regs.p.n = !!((regs.a - rd) & 0x80);
|
||||
regs.p.z = ((regs.a - rd) == 0);
|
||||
break;
|
||||
case 4:
|
||||
op_readaddr(dp);
|
||||
break;
|
||||
case 5:
|
||||
op_writeaddr(dp, rd &~ regs.a);
|
||||
opcode_cycle = 0;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x3a: {
|
||||
switch(opcode_cycle++) {
|
||||
case 1:
|
||||
dp = op_readpc();
|
||||
break;
|
||||
case 2:
|
||||
rd = op_readdp(dp);
|
||||
rd++;
|
||||
break;
|
||||
case 3:
|
||||
op_writedp(dp++, rd);
|
||||
break;
|
||||
case 4:
|
||||
rd += op_readdp(dp) << 8;
|
||||
break;
|
||||
case 5:
|
||||
op_writedp(dp, rd >> 8);
|
||||
regs.p.n = !!(rd & 0x8000);
|
||||
regs.p.z = (rd == 0);
|
||||
opcode_cycle = 0;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x1a: {
|
||||
switch(opcode_cycle++) {
|
||||
case 1:
|
||||
dp = op_readpc();
|
||||
break;
|
||||
case 2:
|
||||
rd = op_readdp(dp);
|
||||
rd--;
|
||||
break;
|
||||
case 3:
|
||||
op_writedp(dp++, rd);
|
||||
break;
|
||||
case 4:
|
||||
rd += op_readdp(dp) << 8;
|
||||
break;
|
||||
case 5:
|
||||
op_writedp(dp, rd >> 8);
|
||||
regs.p.n = !!(rd & 0x8000);
|
||||
regs.p.z = (rd == 0);
|
||||
opcode_cycle = 0;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
75
bsnes/snes/alt/smp/debugger/debugger.cpp
Executable file
75
bsnes/snes/alt/smp/debugger/debugger.cpp
Executable file
@@ -0,0 +1,75 @@
|
||||
#ifdef SMP_CPP
|
||||
|
||||
void SMPDebugger::op_step() {
|
||||
bool break_event = false;
|
||||
|
||||
usage[regs.pc] |= UsageExec;
|
||||
opcode_pc = regs.pc;
|
||||
|
||||
opcode_edge = true;
|
||||
debugger.breakpoint_test(Debugger::Breakpoint::Source::APURAM, Debugger::Breakpoint::Mode::Exec, regs.pc, 0x00);
|
||||
if(step_event && step_event() == true) {
|
||||
debugger.break_event = Debugger::BreakEvent::SMPStep;
|
||||
scheduler.exit(Scheduler::ExitReason::DebuggerEvent);
|
||||
}
|
||||
opcode_edge = false;
|
||||
|
||||
SMP::op_step();
|
||||
synchronize_cpu();
|
||||
}
|
||||
|
||||
uint8 SMPDebugger::op_read(uint16 addr) {
|
||||
uint8 data = SMP::op_read(addr);
|
||||
usage[addr] |= UsageRead;
|
||||
debugger.breakpoint_test(Debugger::Breakpoint::Source::APURAM, Debugger::Breakpoint::Mode::Read, addr, data);
|
||||
return data;
|
||||
}
|
||||
|
||||
void SMPDebugger::op_write(uint16 addr, uint8 data) {
|
||||
SMP::op_write(addr, data);
|
||||
usage[addr] |= UsageWrite;
|
||||
usage[addr] &= ~UsageExec;
|
||||
debugger.breakpoint_test(Debugger::Breakpoint::Source::APURAM, Debugger::Breakpoint::Mode::Write, addr, data);
|
||||
}
|
||||
|
||||
SMPDebugger::SMPDebugger() {
|
||||
usage = new uint8[1 << 16]();
|
||||
opcode_pc = 0xffc0;
|
||||
opcode_edge = false;
|
||||
}
|
||||
|
||||
SMPDebugger::~SMPDebugger() {
|
||||
delete[] usage;
|
||||
}
|
||||
|
||||
bool SMPDebugger::property(unsigned id, string &name, string &value) {
|
||||
unsigned n = 0;
|
||||
|
||||
#define item(name_, value_) \
|
||||
if(id == n++) { \
|
||||
name = name_; \
|
||||
value = value_; \
|
||||
return true; \
|
||||
}
|
||||
|
||||
//$00f0
|
||||
item("$00f0", "");
|
||||
item("Clock Speed", (unsigned)status.clock_speed);
|
||||
item("Timers Enable", status.timers_enable);
|
||||
item("RAM Disable", status.ram_disable);
|
||||
item("RAM Writable", status.ram_writable);
|
||||
item("Timers Disable", status.timers_disable);
|
||||
|
||||
//$00f1
|
||||
item("$00f1", "");
|
||||
item("IPLROM Enable", status.iplrom_enable);
|
||||
|
||||
//$00f2
|
||||
item("$00f2", "");
|
||||
item("DSP Address", string("0x", hex<2>(status.dsp_addr)));
|
||||
|
||||
#undef item
|
||||
return false;
|
||||
}
|
||||
|
||||
#endif
|
27
bsnes/snes/alt/smp/debugger/debugger.hpp
Executable file
27
bsnes/snes/alt/smp/debugger/debugger.hpp
Executable file
@@ -0,0 +1,27 @@
|
||||
class SMPDebugger : public SMP, public ChipDebugger {
|
||||
public:
|
||||
bool property(unsigned id, string &name, string &value);
|
||||
|
||||
function<bool ()> step_event;
|
||||
|
||||
enum Usage {
|
||||
UsageRead = 0x80,
|
||||
UsageWrite = 0x40,
|
||||
UsageExec = 0x20,
|
||||
};
|
||||
uint8 *usage;
|
||||
uint16 opcode_pc;
|
||||
bool opcode_edge;
|
||||
|
||||
void op_step();
|
||||
uint8 op_read(uint16 addr);
|
||||
void op_write(uint16 addr, uint8 data);
|
||||
|
||||
SMPDebugger();
|
||||
~SMPDebugger();
|
||||
|
||||
//disassembler
|
||||
void disassemble_opcode(char *output, uint16 addr);
|
||||
inline uint8 disassemble_read(uint16 addr);
|
||||
inline uint16 relb(int8 offset, int op_len);
|
||||
};
|
304
bsnes/snes/alt/smp/debugger/disassembler.cpp
Executable file
304
bsnes/snes/alt/smp/debugger/disassembler.cpp
Executable file
@@ -0,0 +1,304 @@
|
||||
uint8 SMP::disassemble_read(uint16 addr) {
|
||||
if(addr >= 0xffc0) return smp.iplrom[addr & 0x3f];
|
||||
return smp.apuram[addr];
|
||||
}
|
||||
|
||||
uint16 SMP::relb(int8 offset, int op_len) {
|
||||
uint16 pc = regs.pc + op_len;
|
||||
return pc + offset;
|
||||
}
|
||||
|
||||
void SMP::disassemble_opcode(char *output, uint16 addr) {
|
||||
char *s, t[512];
|
||||
uint8 op, op0, op1;
|
||||
uint16 opw, opdp0, opdp1;
|
||||
s = output;
|
||||
|
||||
sprintf(s, "..%.4x ", addr);
|
||||
|
||||
op = disassemble_read(addr + 0);
|
||||
op0 = disassemble_read(addr + 1);
|
||||
op1 = disassemble_read(addr + 2);
|
||||
opw = (op0) | (op1 << 8);
|
||||
opdp0 = ((unsigned)regs.p.p << 8) + op0;
|
||||
opdp1 = ((unsigned)regs.p.p << 8) + op1;
|
||||
|
||||
strcpy(t, " ");
|
||||
|
||||
switch(op) {
|
||||
case 0x00: sprintf(t, "nop"); break;
|
||||
case 0x01: sprintf(t, "tcall 0"); break;
|
||||
case 0x02: sprintf(t, "set0 $%.3x", opdp0); break;
|
||||
case 0x03: sprintf(t, "bbs0 $%.3x,$%.4x", opdp0, relb(op1, 3)); break;
|
||||
case 0x04: sprintf(t, "or a,$%.3x", opdp0); break;
|
||||
case 0x05: sprintf(t, "or a,$%.4x", opw); break;
|
||||
case 0x06: sprintf(t, "or a,(x)"); break;
|
||||
case 0x07: sprintf(t, "or a,($%.3x+x)", opdp0); break;
|
||||
case 0x08: sprintf(t, "or a,#$%.2x", op0); break;
|
||||
case 0x09: sprintf(t, "or $%.3x,$%.3x", opdp1, opdp0); break;
|
||||
case 0x0a: sprintf(t, "or1 c,$%.4x:%d", opw & 0x1fff, opw >> 13); break;
|
||||
case 0x0b: sprintf(t, "asl $%.3x", opdp0); break;
|
||||
case 0x0c: sprintf(t, "asl $%.4x", opw); break;
|
||||
case 0x0d: sprintf(t, "push p"); break;
|
||||
case 0x0e: sprintf(t, "tset $%.4x,a", opw); break;
|
||||
case 0x0f: sprintf(t, "brk"); break;
|
||||
case 0x10: sprintf(t, "bpl $%.4x", relb(op0, 2)); break;
|
||||
case 0x11: sprintf(t, "tcall 1"); break;
|
||||
case 0x12: sprintf(t, "clr0 $%.3x", opdp0); break;
|
||||
case 0x13: sprintf(t, "bbc0 $%.3x,$%.4x", opdp0, relb(op1, 3)); break;
|
||||
case 0x14: sprintf(t, "or a,$%.3x+x", opdp0); break;
|
||||
case 0x15: sprintf(t, "or a,$%.4x+x", opw); break;
|
||||
case 0x16: sprintf(t, "or a,$%.4x+y", opw); break;
|
||||
case 0x17: sprintf(t, "or a,($%.3x)+y", opdp0); break;
|
||||
case 0x18: sprintf(t, "or $%.3x,#$%.2x", opdp1, op0); break;
|
||||
case 0x19: sprintf(t, "or (x),(y)"); break;
|
||||
case 0x1a: sprintf(t, "decw $%.3x", opdp0); break;
|
||||
case 0x1b: sprintf(t, "asl $%.3x+x", opdp0); break;
|
||||
case 0x1c: sprintf(t, "asl a"); break;
|
||||
case 0x1d: sprintf(t, "dec x"); break;
|
||||
case 0x1e: sprintf(t, "cmp x,$%.4x", opw); break;
|
||||
case 0x1f: sprintf(t, "jmp ($%.4x+x)", opw); break;
|
||||
case 0x20: sprintf(t, "clrp"); break;
|
||||
case 0x21: sprintf(t, "tcall 2"); break;
|
||||
case 0x22: sprintf(t, "set1 $%.3x", opdp0); break;
|
||||
case 0x23: sprintf(t, "bbs1 $%.3x,$%.4x", opdp0, relb(op1, 3)); break;
|
||||
case 0x24: sprintf(t, "and a,$%.3x", opdp0); break;
|
||||
case 0x25: sprintf(t, "and a,$%.4x", opw); break;
|
||||
case 0x26: sprintf(t, "and a,(x)"); break;
|
||||
case 0x27: sprintf(t, "and a,($%.3x+x)", opdp0); break;
|
||||
case 0x28: sprintf(t, "and a,#$%.2x", op0); break;
|
||||
case 0x29: sprintf(t, "and $%.3x,$%.3x", opdp1, opdp0); break;
|
||||
case 0x2a: sprintf(t, "or1 c,!$%.4x:%d", opw & 0x1fff, opw >> 13); break;
|
||||
case 0x2b: sprintf(t, "rol $%.3x", opdp0); break;
|
||||
case 0x2c: sprintf(t, "rol $%.4x", opw); break;
|
||||
case 0x2d: sprintf(t, "push a"); break;
|
||||
case 0x2e: sprintf(t, "cbne $%.3x,$%.4x", opdp0, relb(op1, 3)); break;
|
||||
case 0x2f: sprintf(t, "bra $%.4x", relb(op0, 2)); break;
|
||||
case 0x30: sprintf(t, "bmi $%.4x", relb(op0, 2)); break;
|
||||
case 0x31: sprintf(t, "tcall 3"); break;
|
||||
case 0x32: sprintf(t, "clr1 $%.3x", opdp0); break;
|
||||
case 0x33: sprintf(t, "bbc1 $%.3x,$%.4x", opdp0, relb(op1, 3)); break;
|
||||
case 0x34: sprintf(t, "and a,$%.3x+x", opdp0); break;
|
||||
case 0x35: sprintf(t, "and a,$%.4x+x", opw); break;
|
||||
case 0x36: sprintf(t, "and a,$%.4x+y", opw); break;
|
||||
case 0x37: sprintf(t, "and a,($%.3x)+y", opdp0); break;
|
||||
case 0x38: sprintf(t, "and $%.3x,#$%.2x", opdp1, op0); break;
|
||||
case 0x39: sprintf(t, "and (x),(y)"); break;
|
||||
case 0x3a: sprintf(t, "incw $%.3x", opdp0); break;
|
||||
case 0x3b: sprintf(t, "rol $%.3x+x", opdp0); break;
|
||||
case 0x3c: sprintf(t, "rol a"); break;
|
||||
case 0x3d: sprintf(t, "inc x"); break;
|
||||
case 0x3e: sprintf(t, "cmp x,$%.3x", opdp0); break;
|
||||
case 0x3f: sprintf(t, "call $%.4x", opw); break;
|
||||
case 0x40: sprintf(t, "setp"); break;
|
||||
case 0x41: sprintf(t, "tcall 4"); break;
|
||||
case 0x42: sprintf(t, "set2 $%.3x", opdp0); break;
|
||||
case 0x43: sprintf(t, "bbs2 $%.3x,$%.4x", opdp0, relb(op1, 3)); break;
|
||||
case 0x44: sprintf(t, "eor a,$%.3x", opdp0); break;
|
||||
case 0x45: sprintf(t, "eor a,$%.4x", opw); break;
|
||||
case 0x46: sprintf(t, "eor a,(x)"); break;
|
||||
case 0x47: sprintf(t, "eor a,($%.3x+x)", opdp0); break;
|
||||
case 0x48: sprintf(t, "eor a,#$%.2x", op0); break;
|
||||
case 0x49: sprintf(t, "eor $%.3x,$%.3x", opdp1, opdp0); break;
|
||||
case 0x4a: sprintf(t, "and1 c,$%.4x:%d", opw & 0x1fff, opw >> 13); break;
|
||||
case 0x4b: sprintf(t, "lsr $%.3x", opdp0); break;
|
||||
case 0x4c: sprintf(t, "lsr $%.4x", opw); break;
|
||||
case 0x4d: sprintf(t, "push x"); break;
|
||||
case 0x4e: sprintf(t, "tclr $%.4x,a", opw); break;
|
||||
case 0x4f: sprintf(t, "pcall $ff%.2x", op0); break;
|
||||
case 0x50: sprintf(t, "bvc $%.4x", relb(op0, 2)); break;
|
||||
case 0x51: sprintf(t, "tcall 5"); break;
|
||||
case 0x52: sprintf(t, "clr2 $%.3x", opdp0); break;
|
||||
case 0x53: sprintf(t, "bbc2 $%.3x,$%.4x", opdp0, relb(op1, 3)); break;
|
||||
case 0x54: sprintf(t, "eor a,$%.3x+x", opdp0); break;
|
||||
case 0x55: sprintf(t, "eor a,$%.4x+x", opw); break;
|
||||
case 0x56: sprintf(t, "eor a,$%.4x+y", opw); break;
|
||||
case 0x57: sprintf(t, "eor a,($%.3x)+y", opdp0); break;
|
||||
case 0x58: sprintf(t, "eor $%.3x,#$%.2x", opdp1, op0); break;
|
||||
case 0x59: sprintf(t, "eor (x),(y)"); break;
|
||||
case 0x5a: sprintf(t, "cmpw ya,$%.3x", opdp0); break;
|
||||
case 0x5b: sprintf(t, "lsr $%.3x+x", opdp0); break;
|
||||
case 0x5c: sprintf(t, "lsr a"); break;
|
||||
case 0x5d: sprintf(t, "mov x,a"); break;
|
||||
case 0x5e: sprintf(t, "cmp y,$%.4x", opw); break;
|
||||
case 0x5f: sprintf(t, "jmp $%.4x", opw); break;
|
||||
case 0x60: sprintf(t, "clrc"); break;
|
||||
case 0x61: sprintf(t, "tcall 6"); break;
|
||||
case 0x62: sprintf(t, "set3 $%.3x", opdp0); break;
|
||||
case 0x63: sprintf(t, "bbs3 $%.3x,$%.4x", opdp0, relb(op1, 3)); break;
|
||||
case 0x64: sprintf(t, "cmp a,$%.3x", opdp0); break;
|
||||
case 0x65: sprintf(t, "cmp a,$%.4x", opw); break;
|
||||
case 0x66: sprintf(t, "cmp a,(x)"); break;
|
||||
case 0x67: sprintf(t, "cmp a,($%.3x+x)", opdp0); break;
|
||||
case 0x68: sprintf(t, "cmp a,#$%.2x", op0); break;
|
||||
case 0x69: sprintf(t, "cmp $%.3x,$%.3x", opdp1, opdp0); break;
|
||||
case 0x6a: sprintf(t, "and1 c,!$%.4x:%d", opw & 0x1fff, opw >> 13); break;
|
||||
case 0x6b: sprintf(t, "ror $%.3x", opdp0); break;
|
||||
case 0x6c: sprintf(t, "ror $%.4x", opw); break;
|
||||
case 0x6d: sprintf(t, "push y"); break;
|
||||
case 0x6e: sprintf(t, "dbnz $%.3x,$%.4x", opdp0, relb(op1, 3)); break;
|
||||
case 0x6f: sprintf(t, "ret"); break;
|
||||
case 0x70: sprintf(t, "bvs $%.4x", relb(op0, 2)); break;
|
||||
case 0x71: sprintf(t, "tcall 7"); break;
|
||||
case 0x72: sprintf(t, "clr3 $%.3x", opdp0); break;
|
||||
case 0x73: sprintf(t, "bbc3 $%.3x,$%.4x", opdp0, relb(op1, 3)); break;
|
||||
case 0x74: sprintf(t, "cmp a,$%.3x+x", opdp0); break;
|
||||
case 0x75: sprintf(t, "cmp a,$%.4x+x", opw); break;
|
||||
case 0x76: sprintf(t, "cmp a,$%.4x+y", opw); break;
|
||||
case 0x77: sprintf(t, "cmp a,($%.3x)+y", opdp0); break;
|
||||
case 0x78: sprintf(t, "cmp $%.3x,#$%.2x", opdp1, op0); break;
|
||||
case 0x79: sprintf(t, "cmp (x),(y)"); break;
|
||||
case 0x7a: sprintf(t, "addw ya,$%.3x", opdp0); break;
|
||||
case 0x7b: sprintf(t, "ror $%.3x+x", opdp0); break;
|
||||
case 0x7c: sprintf(t, "ror a"); break;
|
||||
case 0x7d: sprintf(t, "mov a,x"); break;
|
||||
case 0x7e: sprintf(t, "cmp y,$%.3x", opdp0); break;
|
||||
case 0x7f: sprintf(t, "reti"); break;
|
||||
case 0x80: sprintf(t, "setc"); break;
|
||||
case 0x81: sprintf(t, "tcall 8"); break;
|
||||
case 0x82: sprintf(t, "set4 $%.3x", opdp0); break;
|
||||
case 0x83: sprintf(t, "bbs4 $%.3x,$%.4x", opdp0, relb(op1, 3)); break;
|
||||
case 0x84: sprintf(t, "adc a,$%.3x", opdp0); break;
|
||||
case 0x85: sprintf(t, "adc a,$%.4x", opw); break;
|
||||
case 0x86: sprintf(t, "adc a,(x)"); break;
|
||||
case 0x87: sprintf(t, "adc a,($%.3x+x)", opdp0); break;
|
||||
case 0x88: sprintf(t, "adc a,#$%.2x", op0); break;
|
||||
case 0x89: sprintf(t, "adc $%.3x,$%.3x", opdp1, opdp0); break;
|
||||
case 0x8a: sprintf(t, "eor1 c,$%.4x:%d", opw & 0x1fff, opw >> 13); break;
|
||||
case 0x8b: sprintf(t, "dec $%.3x", opdp0); break;
|
||||
case 0x8c: sprintf(t, "dec $%.4x", opw); break;
|
||||
case 0x8d: sprintf(t, "mov y,#$%.2x", op0); break;
|
||||
case 0x8e: sprintf(t, "pop p"); break;
|
||||
case 0x8f: sprintf(t, "mov $%.3x,#$%.2x", opdp1, op0); break;
|
||||
case 0x90: sprintf(t, "bcc $%.4x", relb(op0, 2)); break;
|
||||
case 0x91: sprintf(t, "tcall 9"); break;
|
||||
case 0x92: sprintf(t, "clr4 $%.3x", opdp0); break;
|
||||
case 0x93: sprintf(t, "bbc4 $%.3x,$%.4x", opdp0, relb(op1, 3)); break;
|
||||
case 0x94: sprintf(t, "adc a,$%.3x+x", opdp0); break;
|
||||
case 0x95: sprintf(t, "adc a,$%.4x+x", opw); break;
|
||||
case 0x96: sprintf(t, "adc a,$%.4x+y", opw); break;
|
||||
case 0x97: sprintf(t, "adc a,($%.3x)+y", opdp0); break;
|
||||
case 0x98: sprintf(t, "adc $%.3x,#$%.2x", opdp1, op0); break;
|
||||
case 0x99: sprintf(t, "adc (x),(y)"); break;
|
||||
case 0x9a: sprintf(t, "subw ya,$%.3x", opdp0); break;
|
||||
case 0x9b: sprintf(t, "dec $%.3x+x", opdp0); break;
|
||||
case 0x9c: sprintf(t, "dec a"); break;
|
||||
case 0x9d: sprintf(t, "mov x,sp"); break;
|
||||
case 0x9e: sprintf(t, "div ya,x"); break;
|
||||
case 0x9f: sprintf(t, "xcn a"); break;
|
||||
case 0xa0: sprintf(t, "ei"); break;
|
||||
case 0xa1: sprintf(t, "tcall 10"); break;
|
||||
case 0xa2: sprintf(t, "set5 $%.3x", opdp0); break;
|
||||
case 0xa3: sprintf(t, "bbs5 $%.3x,$%.4x", opdp0, relb(op1, 3)); break;
|
||||
case 0xa4: sprintf(t, "sbc a,$%.3x", opdp0); break;
|
||||
case 0xa5: sprintf(t, "sbc a,$%.4x", opw); break;
|
||||
case 0xa6: sprintf(t, "sbc a,(x)"); break;
|
||||
case 0xa7: sprintf(t, "sbc a,($%.3x+x)", opdp0); break;
|
||||
case 0xa8: sprintf(t, "sbc a,#$%.2x", op0); break;
|
||||
case 0xa9: sprintf(t, "sbc $%.3x,$%.3x", opdp1, opdp0); break;
|
||||
case 0xaa: sprintf(t, "mov1 c,$%.4x:%d", opw & 0x1fff, opw >> 13); break;
|
||||
case 0xab: sprintf(t, "inc $%.3x", opdp0); break;
|
||||
case 0xac: sprintf(t, "inc $%.4x", opw); break;
|
||||
case 0xad: sprintf(t, "cmp y,#$%.2x", op0); break;
|
||||
case 0xae: sprintf(t, "pop a"); break;
|
||||
case 0xaf: sprintf(t, "mov (x)+,a"); break;
|
||||
case 0xb0: sprintf(t, "bcs $%.4x", relb(op0, 2)); break;
|
||||
case 0xb1: sprintf(t, "tcall 11"); break;
|
||||
case 0xb2: sprintf(t, "clr5 $%.3x", opdp0); break;
|
||||
case 0xb3: sprintf(t, "bbc5 $%.3x,$%.4x", opdp0, relb(op1, 3)); break;
|
||||
case 0xb4: sprintf(t, "sbc a,$%.3x+x", opdp0); break;
|
||||
case 0xb5: sprintf(t, "sbc a,$%.4x+x", opw); break;
|
||||
case 0xb6: sprintf(t, "sbc a,$%.4x+y", opw); break;
|
||||
case 0xb7: sprintf(t, "sbc a,($%.3x)+y", opdp0); break;
|
||||
case 0xb8: sprintf(t, "sbc $%.3x,#$%.2x", opdp1, op0); break;
|
||||
case 0xb9: sprintf(t, "sbc (x),(y)"); break;
|
||||
case 0xba: sprintf(t, "movw ya,$%.3x", opdp0); break;
|
||||
case 0xbb: sprintf(t, "inc $%.3x+x", opdp0); break;
|
||||
case 0xbc: sprintf(t, "inc a"); break;
|
||||
case 0xbd: sprintf(t, "mov sp,x"); break;
|
||||
case 0xbe: sprintf(t, "das a"); break;
|
||||
case 0xbf: sprintf(t, "mov a,(x)+"); break;
|
||||
case 0xc0: sprintf(t, "di"); break;
|
||||
case 0xc1: sprintf(t, "tcall 12"); break;
|
||||
case 0xc2: sprintf(t, "set6 $%.3x", opdp0); break;
|
||||
case 0xc3: sprintf(t, "bbs6 $%.3x,$%.4x", opdp0, relb(op1, 3)); break;
|
||||
case 0xc4: sprintf(t, "mov $%.3x,a", opdp0); break;
|
||||
case 0xc5: sprintf(t, "mov $%.4x,a", opw); break;
|
||||
case 0xc6: sprintf(t, "mov (x),a"); break;
|
||||
case 0xc7: sprintf(t, "mov ($%.3x+x),a", opdp0); break;
|
||||
case 0xc8: sprintf(t, "cmp x,#$%.2x", op0); break;
|
||||
case 0xc9: sprintf(t, "mov $%.4x,x", opw); break;
|
||||
case 0xca: sprintf(t, "mov1 $%.4x:%d,c", opw & 0x1fff, opw >> 13); break;
|
||||
case 0xcb: sprintf(t, "mov $%.3x,y", opdp0); break;
|
||||
case 0xcc: sprintf(t, "mov $%.4x,y", opw); break;
|
||||
case 0xcd: sprintf(t, "mov x,#$%.2x", op0); break;
|
||||
case 0xce: sprintf(t, "pop x"); break;
|
||||
case 0xcf: sprintf(t, "mul ya"); break;
|
||||
case 0xd0: sprintf(t, "bne $%.4x", relb(op0, 2)); break;
|
||||
case 0xd1: sprintf(t, "tcall 13"); break;
|
||||
case 0xd2: sprintf(t, "clr6 $%.3x", opdp0); break;
|
||||
case 0xd3: sprintf(t, "bbc6 $%.3x,$%.4x", opdp0, relb(op1, 3)); break;
|
||||
case 0xd4: sprintf(t, "mov $%.3x+x,a", opdp0); break;
|
||||
case 0xd5: sprintf(t, "mov $%.4x+x,a", opw); break;
|
||||
case 0xd6: sprintf(t, "mov $%.4x+y,a", opw); break;
|
||||
case 0xd7: sprintf(t, "mov ($%.3x)+y,a", opdp0); break;
|
||||
case 0xd8: sprintf(t, "mov $%.3x,x", opdp0); break;
|
||||
case 0xd9: sprintf(t, "mov $%.3x+y,x", opdp0); break;
|
||||
case 0xda: sprintf(t, "movw $%.3x,ya", opdp0); break;
|
||||
case 0xdb: sprintf(t, "mov $%.3x+x,y", opdp0); break;
|
||||
case 0xdc: sprintf(t, "dec y"); break;
|
||||
case 0xdd: sprintf(t, "mov a,y"); break;
|
||||
case 0xde: sprintf(t, "cbne $%.3x+x,$%.4x", opdp0, relb(op1, 3)); break;
|
||||
case 0xdf: sprintf(t, "daa a"); break;
|
||||
case 0xe0: sprintf(t, "clrv"); break;
|
||||
case 0xe1: sprintf(t, "tcall 14"); break;
|
||||
case 0xe2: sprintf(t, "set7 $%.3x", opdp0); break;
|
||||
case 0xe3: sprintf(t, "bbs7 $%.3x,$%.4x", opdp0, relb(op1, 3)); break;
|
||||
case 0xe4: sprintf(t, "mov a,$%.3x", opdp0); break;
|
||||
case 0xe5: sprintf(t, "mov a,$%.4x", opw); break;
|
||||
case 0xe6: sprintf(t, "mov a,(x)"); break;
|
||||
case 0xe7: sprintf(t, "mov a,($%.3x+x)", opdp0); break;
|
||||
case 0xe8: sprintf(t, "mov a,#$%.2x", op0); break;
|
||||
case 0xe9: sprintf(t, "mov x,$%.4x", opw); break;
|
||||
case 0xea: sprintf(t, "not1 c,$%.4x:%d", opw & 0x1fff, opw >> 13); break;
|
||||
case 0xeb: sprintf(t, "mov y,$%.3x", opdp0); break;
|
||||
case 0xec: sprintf(t, "mov y,$%.4x", opw); break;
|
||||
case 0xed: sprintf(t, "notc"); break;
|
||||
case 0xee: sprintf(t, "pop y"); break;
|
||||
case 0xef: sprintf(t, "sleep"); break;
|
||||
case 0xf0: sprintf(t, "beq $%.4x", relb(op0, 2)); break;
|
||||
case 0xf1: sprintf(t, "tcall 15"); break;
|
||||
case 0xf2: sprintf(t, "clr7 $%.3x", opdp0); break;
|
||||
case 0xf3: sprintf(t, "bbc7 $%.3x,$%.4x", opdp0, relb(op1, 3)); break;
|
||||
case 0xf4: sprintf(t, "mov a,$%.3x+x", opdp0); break;
|
||||
case 0xf5: sprintf(t, "mov a,$%.4x+x", opw); break;
|
||||
case 0xf6: sprintf(t, "mov a,$%.4x+y", opw); break;
|
||||
case 0xf7: sprintf(t, "mov a,($%.3x)+y", opdp0); break;
|
||||
case 0xf8: sprintf(t, "mov x,$%.3x", opdp0); break;
|
||||
case 0xf9: sprintf(t, "mov x,$%.3x+y", opdp0); break;
|
||||
case 0xfa: sprintf(t, "mov $%.3x,$%.3x", opdp1, opdp0); break;
|
||||
case 0xfb: sprintf(t, "mov y,$%.3x+x", opdp0); break;
|
||||
case 0xfc: sprintf(t, "inc y"); break;
|
||||
case 0xfd: sprintf(t, "mov y,a"); break;
|
||||
case 0xfe: sprintf(t, "dbnz y,$%.4x", relb(op0, 2)); break;
|
||||
case 0xff: sprintf(t, "stop"); break;
|
||||
}
|
||||
|
||||
t[strlen(t)] = ' ';
|
||||
strcat(s, t);
|
||||
|
||||
sprintf(t, "A:%.2x X:%.2x Y:%.2x SP:01%.2x YA:%.4x ",
|
||||
regs.a, regs.x, regs.y, regs.sp, (uint16)regs.ya);
|
||||
strcat(s, t);
|
||||
|
||||
sprintf(t, "%c%c%c%c%c%c%c%c",
|
||||
regs.p.n ? 'N' : 'n',
|
||||
regs.p.v ? 'V' : 'v',
|
||||
regs.p.p ? 'P' : 'p',
|
||||
regs.p.b ? 'B' : 'b',
|
||||
regs.p.h ? 'H' : 'h',
|
||||
regs.p.i ? 'I' : 'i',
|
||||
regs.p.z ? 'Z' : 'z',
|
||||
regs.p.c ? 'C' : 'c');
|
||||
strcat(s, t);
|
||||
}
|
44
bsnes/snes/alt/smp/iplrom.cpp
Executable file
44
bsnes/snes/alt/smp/iplrom.cpp
Executable file
@@ -0,0 +1,44 @@
|
||||
#ifdef SMP_CPP
|
||||
|
||||
//this is the IPLROM for the S-SMP coprocessor.
|
||||
//the S-SMP does not allow writing to the IPLROM.
|
||||
//all writes are instead mapped to the extended
|
||||
//RAM region, accessible when $f1.d7 is clear.
|
||||
|
||||
const uint8 SMP::iplrom[64] = {
|
||||
/*ffc0*/ 0xcd, 0xef, //mov x,#$ef
|
||||
/*ffc2*/ 0xbd, //mov sp,x
|
||||
/*ffc3*/ 0xe8, 0x00, //mov a,#$00
|
||||
/*ffc5*/ 0xc6, //mov (x),a
|
||||
/*ffc6*/ 0x1d, //dec x
|
||||
/*ffc7*/ 0xd0, 0xfc, //bne $ffc5
|
||||
/*ffc9*/ 0x8f, 0xaa, 0xf4, //mov $f4,#$aa
|
||||
/*ffcc*/ 0x8f, 0xbb, 0xf5, //mov $f5,#$bb
|
||||
/*ffcf*/ 0x78, 0xcc, 0xf4, //cmp $f4,#$cc
|
||||
/*ffd2*/ 0xd0, 0xfb, //bne $ffcf
|
||||
/*ffd4*/ 0x2f, 0x19, //bra $ffef
|
||||
/*ffd6*/ 0xeb, 0xf4, //mov y,$f4
|
||||
/*ffd8*/ 0xd0, 0xfc, //bne $ffd6
|
||||
/*ffda*/ 0x7e, 0xf4, //cmp y,$f4
|
||||
/*ffdc*/ 0xd0, 0x0b, //bne $ffe9
|
||||
/*ffde*/ 0xe4, 0xf5, //mov a,$f5
|
||||
/*ffe0*/ 0xcb, 0xf4, //mov $f4,y
|
||||
/*ffe2*/ 0xd7, 0x00, //mov ($00)+y,a
|
||||
/*ffe4*/ 0xfc, //inc y
|
||||
/*ffe5*/ 0xd0, 0xf3, //bne $ffda
|
||||
/*ffe7*/ 0xab, 0x01, //inc $01
|
||||
/*ffe9*/ 0x10, 0xef, //bpl $ffda
|
||||
/*ffeb*/ 0x7e, 0xf4, //cmp y,$f4
|
||||
/*ffed*/ 0x10, 0xeb, //bpl $ffda
|
||||
/*ffef*/ 0xba, 0xf6, //movw ya,$f6
|
||||
/*fff1*/ 0xda, 0x00, //movw $00,ya
|
||||
/*fff3*/ 0xba, 0xf4, //movw ya,$f4
|
||||
/*fff5*/ 0xc4, 0xf4, //mov $f4,a
|
||||
/*fff7*/ 0xdd, //mov a,y
|
||||
/*fff8*/ 0x5d, //mov x,a
|
||||
/*fff9*/ 0xd0, 0xdb, //bne $ffd6
|
||||
/*fffb*/ 0x1f, 0x00, 0x00, //jmp ($0000+x)
|
||||
/*fffe*/ 0xc0, 0xff //reset vector location ($ffc0)
|
||||
};
|
||||
|
||||
#endif
|
130
bsnes/snes/alt/smp/memory.cpp
Executable file
130
bsnes/snes/alt/smp/memory.cpp
Executable file
@@ -0,0 +1,130 @@
|
||||
unsigned SMP::port_read(unsigned addr) {
|
||||
return apuram[0xf4 + (addr & 3)];
|
||||
}
|
||||
|
||||
void SMP::port_write(unsigned addr, unsigned data) {
|
||||
apuram[0xf4 + (addr & 3)] = data;
|
||||
}
|
||||
|
||||
unsigned SMP::mmio_read(unsigned addr) {
|
||||
switch(addr) {
|
||||
|
||||
case 0xf2:
|
||||
return status.dsp_addr;
|
||||
|
||||
case 0xf3:
|
||||
return dsp.read(status.dsp_addr & 0x7f);
|
||||
|
||||
case 0xf4:
|
||||
case 0xf5:
|
||||
case 0xf6:
|
||||
case 0xf7:
|
||||
synchronize_cpu();
|
||||
return cpu.port_read(addr);
|
||||
|
||||
case 0xf8:
|
||||
return status.ram00f8;
|
||||
|
||||
case 0xf9:
|
||||
return status.ram00f9;
|
||||
|
||||
case 0xfd: {
|
||||
unsigned result = timer0.stage3_ticks & 15;
|
||||
timer0.stage3_ticks = 0;
|
||||
return result;
|
||||
}
|
||||
|
||||
case 0xfe: {
|
||||
unsigned result = timer1.stage3_ticks & 15;
|
||||
timer1.stage3_ticks = 0;
|
||||
return result;
|
||||
}
|
||||
|
||||
case 0xff: {
|
||||
unsigned result = timer2.stage3_ticks & 15;
|
||||
timer2.stage3_ticks = 0;
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return 0x00;
|
||||
}
|
||||
|
||||
void SMP::mmio_write(unsigned addr, unsigned data) {
|
||||
switch(addr) {
|
||||
|
||||
case 0xf1:
|
||||
status.iplrom_enable = data & 0x80;
|
||||
|
||||
if(data & 0x30) {
|
||||
synchronize_cpu();
|
||||
if(data & 0x20) {
|
||||
cpu.port_write(3, 0x00);
|
||||
cpu.port_write(2, 0x00);
|
||||
}
|
||||
if(data & 0x10) {
|
||||
cpu.port_write(1, 0x00);
|
||||
cpu.port_write(0, 0x00);
|
||||
}
|
||||
}
|
||||
|
||||
if(timer2.enable == false && (data & 0x04)) {
|
||||
timer2.stage2_ticks = 0;
|
||||
timer2.stage3_ticks = 0;
|
||||
}
|
||||
timer2.enable = data & 0x04;
|
||||
|
||||
if(timer1.enable == false && (data & 0x02)) {
|
||||
timer1.stage2_ticks = 0;
|
||||
timer1.stage3_ticks = 0;
|
||||
}
|
||||
timer1.enable = data & 0x02;
|
||||
|
||||
if(timer0.enable == false && (data & 0x01)) {
|
||||
timer0.stage2_ticks = 0;
|
||||
timer0.stage3_ticks = 0;
|
||||
}
|
||||
timer0.enable = data & 0x01;
|
||||
|
||||
break;
|
||||
|
||||
case 0xf2:
|
||||
status.dsp_addr = data;
|
||||
break;
|
||||
|
||||
case 0xf3:
|
||||
if(status.dsp_addr & 0x80) break;
|
||||
dsp.write(status.dsp_addr, data);
|
||||
break;
|
||||
|
||||
case 0xf4:
|
||||
case 0xf5:
|
||||
case 0xf6:
|
||||
case 0xf7:
|
||||
synchronize_cpu();
|
||||
port_write(addr, data);
|
||||
break;
|
||||
|
||||
case 0xf8:
|
||||
status.ram00f8 = data;
|
||||
break;
|
||||
|
||||
case 0xf9:
|
||||
status.ram00f9 = data;
|
||||
break;
|
||||
|
||||
case 0xfa:
|
||||
timer0.target = data;
|
||||
break;
|
||||
|
||||
case 0xfb:
|
||||
timer1.target = data;
|
||||
break;
|
||||
|
||||
case 0xfc:
|
||||
timer2.target = data;
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
147
bsnes/snes/alt/smp/smp.cpp
Executable file
147
bsnes/snes/alt/smp/smp.cpp
Executable file
@@ -0,0 +1,147 @@
|
||||
#define CYCLE_ACCURATE
|
||||
|
||||
#include <snes/snes.hpp>
|
||||
|
||||
#define SMP_CPP
|
||||
namespace SNES {
|
||||
|
||||
#if defined(DEBUGGER)
|
||||
#include "debugger/debugger.cpp"
|
||||
#include "debugger/disassembler.cpp"
|
||||
SMPDebugger smp;
|
||||
#else
|
||||
SMP smp;
|
||||
#endif
|
||||
|
||||
#include "algorithms.cpp"
|
||||
#include "core.cpp"
|
||||
#include "iplrom.cpp"
|
||||
#include "memory.cpp"
|
||||
#include "timing.cpp"
|
||||
|
||||
void SMP::synchronize_cpu() {
|
||||
if(CPU::Threaded == true) {
|
||||
//if(clock >= 0 && scheduler.sync != Scheduler::SynchronizeMode::All) co_switch(cpu.thread);
|
||||
} else {
|
||||
while(clock >= 0) cpu.enter();
|
||||
}
|
||||
}
|
||||
|
||||
void SMP::synchronize_dsp() {
|
||||
if(DSP::Threaded == true) {
|
||||
//if(dsp.clock < 0 && scheduler.sync != Scheduler::SynchronizeMode::All) co_switch(dsp.thread);
|
||||
} else {
|
||||
while(dsp.clock < 0) dsp.enter();
|
||||
}
|
||||
}
|
||||
|
||||
void SMP::enter() {
|
||||
while(clock < 0) op_step();
|
||||
}
|
||||
|
||||
void SMP::power() {
|
||||
Processor::frequency = system.apu_frequency();
|
||||
Processor::clock = 0;
|
||||
|
||||
timer0.target = 0;
|
||||
timer1.target = 0;
|
||||
timer2.target = 0;
|
||||
|
||||
for(unsigned n = 0; n < 256; n++) {
|
||||
cycle_table_dsp[n] = (cycle_count_table[n] * 24);
|
||||
cycle_table_cpu[n] = (cycle_count_table[n] * 24) * cpu.frequency;
|
||||
}
|
||||
|
||||
cycle_step_cpu = 24 * cpu.frequency;
|
||||
|
||||
reset();
|
||||
}
|
||||
|
||||
void SMP::reset() {
|
||||
for(unsigned n = 0x0000; n <= 0xffff; n++) apuram[n] = 0x00;
|
||||
|
||||
opcode_number = 0;
|
||||
opcode_cycle = 0;
|
||||
|
||||
regs.pc = 0xffc0;
|
||||
regs.sp = 0xef;
|
||||
regs.a = 0x00;
|
||||
regs.x = 0x00;
|
||||
regs.y = 0x00;
|
||||
regs.p = 0x02;
|
||||
|
||||
//$00f1
|
||||
status.iplrom_enable = true;
|
||||
|
||||
//$00f2
|
||||
status.dsp_addr = 0x00;
|
||||
|
||||
//$00f8,$00f9
|
||||
status.ram00f8 = 0x00;
|
||||
status.ram00f9 = 0x00;
|
||||
|
||||
//timers
|
||||
timer0.enable = timer1.enable = timer2.enable = false;
|
||||
timer0.stage1_ticks = timer1.stage1_ticks = timer2.stage1_ticks = 0;
|
||||
timer0.stage2_ticks = timer1.stage2_ticks = timer2.stage2_ticks = 0;
|
||||
timer0.stage3_ticks = timer1.stage3_ticks = timer2.stage3_ticks = 0;
|
||||
}
|
||||
|
||||
void SMP::serialize(serializer &s) {
|
||||
Processor::serialize(s);
|
||||
|
||||
s.array(apuram, 64 * 1024);
|
||||
|
||||
s.integer(opcode_number);
|
||||
s.integer(opcode_cycle);
|
||||
|
||||
s.integer(regs.pc);
|
||||
s.integer(regs.sp);
|
||||
s.integer(regs.a);
|
||||
s.integer(regs.x);
|
||||
s.integer(regs.y);
|
||||
|
||||
s.integer(regs.p.n);
|
||||
s.integer(regs.p.v);
|
||||
s.integer(regs.p.p);
|
||||
s.integer(regs.p.b);
|
||||
s.integer(regs.p.h);
|
||||
s.integer(regs.p.i);
|
||||
s.integer(regs.p.z);
|
||||
s.integer(regs.p.c);
|
||||
|
||||
s.integer(status.iplrom_enable);
|
||||
|
||||
s.integer(status.dsp_addr);
|
||||
|
||||
s.integer(status.ram00f8);
|
||||
s.integer(status.ram00f9);
|
||||
|
||||
s.integer(timer0.enable);
|
||||
s.integer(timer0.target);
|
||||
s.integer(timer0.stage1_ticks);
|
||||
s.integer(timer0.stage2_ticks);
|
||||
s.integer(timer0.stage3_ticks);
|
||||
|
||||
s.integer(timer1.enable);
|
||||
s.integer(timer1.target);
|
||||
s.integer(timer1.stage1_ticks);
|
||||
s.integer(timer1.stage2_ticks);
|
||||
s.integer(timer1.stage3_ticks);
|
||||
|
||||
s.integer(timer2.enable);
|
||||
s.integer(timer2.target);
|
||||
|
||||
s.integer(timer2.stage1_ticks);
|
||||
s.integer(timer2.stage2_ticks);
|
||||
s.integer(timer2.stage3_ticks);
|
||||
}
|
||||
|
||||
SMP::SMP() {
|
||||
apuram = new uint8[64 * 1024];
|
||||
}
|
||||
|
||||
SMP::~SMP() {
|
||||
}
|
||||
|
||||
}
|
118
bsnes/snes/alt/smp/smp.hpp
Executable file
118
bsnes/snes/alt/smp/smp.hpp
Executable file
@@ -0,0 +1,118 @@
|
||||
class SMP : public Processor {
|
||||
public:
|
||||
static const uint8 iplrom[64];
|
||||
uint8 *apuram;
|
||||
|
||||
enum : bool { Threaded = false };
|
||||
alwaysinline void synchronize_cpu();
|
||||
alwaysinline void synchronize_dsp();
|
||||
|
||||
unsigned port_read(unsigned port);
|
||||
void port_write(unsigned port, unsigned data);
|
||||
|
||||
unsigned mmio_read(unsigned addr);
|
||||
void mmio_write(unsigned addr, unsigned data);
|
||||
|
||||
void enter();
|
||||
void power();
|
||||
void reset();
|
||||
|
||||
void serialize(serializer&);
|
||||
SMP();
|
||||
~SMP();
|
||||
|
||||
//private:
|
||||
struct Flags {
|
||||
bool n, v, p, b, h, i, z, c;
|
||||
|
||||
alwaysinline operator unsigned() const {
|
||||
return (n << 7) | (v << 6) | (p << 5) | (b << 4)
|
||||
| (h << 3) | (i << 2) | (z << 1) | (c << 0);
|
||||
};
|
||||
|
||||
alwaysinline unsigned operator=(unsigned data) {
|
||||
n = data & 0x80; v = data & 0x40; p = data & 0x20; b = data & 0x10;
|
||||
h = data & 0x08; i = data & 0x04; z = data & 0x02; c = data & 0x01;
|
||||
return data;
|
||||
}
|
||||
|
||||
alwaysinline unsigned operator|=(unsigned data) { return operator=(operator unsigned() | data); }
|
||||
alwaysinline unsigned operator^=(unsigned data) { return operator=(operator unsigned() ^ data); }
|
||||
alwaysinline unsigned operator&=(unsigned data) { return operator=(operator unsigned() & data); }
|
||||
};
|
||||
|
||||
unsigned opcode_number;
|
||||
unsigned opcode_cycle;
|
||||
|
||||
struct Regs {
|
||||
uint16 pc;
|
||||
uint8 sp;
|
||||
union {
|
||||
uint16 ya;
|
||||
struct { uint8 order_lsb2(a, y); };
|
||||
};
|
||||
uint8 x;
|
||||
Flags p;
|
||||
} regs;
|
||||
|
||||
struct Status {
|
||||
//$00f1
|
||||
bool iplrom_enable;
|
||||
|
||||
//$00f2
|
||||
unsigned dsp_addr;
|
||||
|
||||
//$00f8,$00f9
|
||||
unsigned ram00f8;
|
||||
unsigned ram00f9;
|
||||
} status;
|
||||
|
||||
template<unsigned frequency>
|
||||
struct Timer {
|
||||
bool enable;
|
||||
uint8 target;
|
||||
uint8 stage1_ticks;
|
||||
uint8 stage2_ticks;
|
||||
uint8 stage3_ticks;
|
||||
|
||||
void tick();
|
||||
void tick(unsigned clocks);
|
||||
};
|
||||
|
||||
Timer<128> timer0;
|
||||
Timer<128> timer1;
|
||||
Timer< 16> timer2;
|
||||
|
||||
void tick();
|
||||
alwaysinline void op_io();
|
||||
debugvirtual alwaysinline uint8 op_read(uint16 addr);
|
||||
debugvirtual alwaysinline void op_write(uint16 addr, uint8 data);
|
||||
debugvirtual alwaysinline void op_step();
|
||||
static const unsigned cycle_count_table[256];
|
||||
uint64 cycle_table_cpu[256];
|
||||
unsigned cycle_table_dsp[256];
|
||||
uint64 cycle_step_cpu;
|
||||
|
||||
uint8 op_adc (uint8 x, uint8 y);
|
||||
uint16 op_addw(uint16 x, uint16 y);
|
||||
uint8 op_and (uint8 x, uint8 y);
|
||||
uint8 op_cmp (uint8 x, uint8 y);
|
||||
uint16 op_cmpw(uint16 x, uint16 y);
|
||||
uint8 op_eor (uint8 x, uint8 y);
|
||||
uint8 op_inc (uint8 x);
|
||||
uint8 op_dec (uint8 x);
|
||||
uint8 op_or (uint8 x, uint8 y);
|
||||
uint8 op_sbc (uint8 x, uint8 y);
|
||||
uint16 op_subw(uint16 x, uint16 y);
|
||||
uint8 op_asl (uint8 x);
|
||||
uint8 op_lsr (uint8 x);
|
||||
uint8 op_rol (uint8 x);
|
||||
uint8 op_ror (uint8 x);
|
||||
};
|
||||
|
||||
#if defined(DEBUGGER)
|
||||
#include "debugger/debugger.hpp"
|
||||
extern SMPDebugger smp;
|
||||
#else
|
||||
extern SMP smp;
|
||||
#endif
|
26
bsnes/snes/alt/smp/timing.cpp
Executable file
26
bsnes/snes/alt/smp/timing.cpp
Executable file
@@ -0,0 +1,26 @@
|
||||
template<unsigned cycle_frequency>
|
||||
void SMP::Timer<cycle_frequency>::tick() {
|
||||
if(++stage1_ticks < cycle_frequency) return;
|
||||
|
||||
stage1_ticks = 0;
|
||||
if(enable == false) return;
|
||||
|
||||
if(++stage2_ticks != target) return;
|
||||
|
||||
stage2_ticks = 0;
|
||||
stage3_ticks = (stage3_ticks + 1) & 15;
|
||||
}
|
||||
|
||||
template<unsigned cycle_frequency>
|
||||
void SMP::Timer<cycle_frequency>::tick(unsigned clocks) {
|
||||
stage1_ticks += clocks;
|
||||
if(stage1_ticks < cycle_frequency) return;
|
||||
|
||||
stage1_ticks -= cycle_frequency;
|
||||
if(enable == false) return;
|
||||
|
||||
if(++stage2_ticks != target) return;
|
||||
|
||||
stage2_ticks = 0;
|
||||
stage3_ticks = (stage3_ticks + 1) & 15;
|
||||
}
|
@@ -17,23 +17,24 @@ void Cartridge::load(Mode cartridge_mode, const lstring &xml_list) {
|
||||
ram_size = 0;
|
||||
|
||||
has_bsx_slot = false;
|
||||
has_nss_dip = false;
|
||||
has_superfx = false;
|
||||
has_sa1 = false;
|
||||
has_necdsp = false;
|
||||
has_hitachidsp = false;
|
||||
has_srtc = false;
|
||||
has_sdd1 = false;
|
||||
has_spc7110 = false;
|
||||
has_spc7110rtc = false;
|
||||
has_cx4 = false;
|
||||
has_obc1 = false;
|
||||
has_st0018 = false;
|
||||
has_msu1 = false;
|
||||
has_serial = false;
|
||||
has_link = false;
|
||||
|
||||
nvram.reset();
|
||||
|
||||
parse_xml(xml_list);
|
||||
//print(xml_list[0], "\n\n");
|
||||
print(xml_list[0], "\n\n");
|
||||
|
||||
if(ram_size > 0) {
|
||||
ram.map(allocate<uint8>(ram_size, 0xff), ram_size);
|
||||
|
@@ -34,18 +34,19 @@ public:
|
||||
readonly<unsigned> ram_size;
|
||||
|
||||
readonly<bool> has_bsx_slot;
|
||||
readonly<bool> has_nss_dip;
|
||||
readonly<bool> has_superfx;
|
||||
readonly<bool> has_sa1;
|
||||
readonly<bool> has_necdsp;
|
||||
readonly<bool> has_hitachidsp;
|
||||
readonly<bool> has_srtc;
|
||||
readonly<bool> has_sdd1;
|
||||
readonly<bool> has_spc7110;
|
||||
readonly<bool> has_spc7110rtc;
|
||||
readonly<bool> has_cx4;
|
||||
readonly<bool> has_obc1;
|
||||
readonly<bool> has_st0018;
|
||||
readonly<bool> has_msu1;
|
||||
readonly<bool> has_serial;
|
||||
readonly<bool> has_link;
|
||||
|
||||
struct NonVolatileRAM {
|
||||
const string id;
|
||||
@@ -75,6 +76,13 @@ public:
|
||||
};
|
||||
linear_vector<Mapping> mapping;
|
||||
|
||||
struct Information {
|
||||
struct NSS {
|
||||
lstring setting;
|
||||
lstring option[16];
|
||||
} nss;
|
||||
} information;
|
||||
|
||||
void load(Mode, const lstring&);
|
||||
void unload();
|
||||
|
||||
@@ -91,22 +99,25 @@ private:
|
||||
|
||||
void xml_parse_rom(xml_element&);
|
||||
void xml_parse_ram(xml_element&);
|
||||
void xml_parse_nss(xml_element&);
|
||||
void xml_parse_icd2(xml_element&);
|
||||
void xml_parse_superfx(xml_element&);
|
||||
void xml_parse_sa1(xml_element&);
|
||||
void xml_parse_necdsp(xml_element&);
|
||||
void xml_parse_hitachidsp(xml_element&);
|
||||
void xml_parse_bsx(xml_element&);
|
||||
void xml_parse_sufamiturbo(xml_element&);
|
||||
void xml_parse_supergameboy(xml_element&);
|
||||
void xml_parse_srtc(xml_element&);
|
||||
void xml_parse_sdd1(xml_element&);
|
||||
void xml_parse_spc7110(xml_element&);
|
||||
void xml_parse_cx4(xml_element&);
|
||||
void xml_parse_obc1(xml_element&);
|
||||
void xml_parse_setarisc(xml_element&);
|
||||
void xml_parse_msu1(xml_element&);
|
||||
void xml_parse_serial(xml_element&);
|
||||
void xml_parse_link(xml_element&);
|
||||
|
||||
unsigned xml_parse_hex(const string&);
|
||||
unsigned xml_parse_unsigned(const string&);
|
||||
void xml_parse_address(Mapping&, const string&);
|
||||
void xml_parse_mode(Mapping&, const string&);
|
||||
};
|
||||
|
@@ -17,6 +17,9 @@ void Cartridge::parse_xml(const lstring &list) {
|
||||
}
|
||||
|
||||
void Cartridge::parse_xml_cartridge(const char *data) {
|
||||
//reset cartridge information
|
||||
information.nss.setting.reset();
|
||||
|
||||
xml_element document = xml_parse(data);
|
||||
if(document.element.size() == 0) return;
|
||||
|
||||
@@ -32,20 +35,21 @@ void Cartridge::parse_xml_cartridge(const char *data) {
|
||||
foreach(node, head.element) {
|
||||
if(node.name == "rom") xml_parse_rom(node);
|
||||
if(node.name == "ram") xml_parse_ram(node);
|
||||
if(node.name == "nss") xml_parse_nss(node);
|
||||
if(node.name == "icd2") xml_parse_icd2(node);
|
||||
if(node.name == "superfx") xml_parse_superfx(node);
|
||||
if(node.name == "sa1") xml_parse_sa1(node);
|
||||
if(node.name == "necdsp") xml_parse_necdsp(node);
|
||||
if(node.name == "hitachidsp") xml_parse_hitachidsp(node);
|
||||
if(node.name == "bsx") xml_parse_bsx(node);
|
||||
if(node.name == "sufamiturbo") xml_parse_sufamiturbo(node);
|
||||
if(node.name == "srtc") xml_parse_srtc(node);
|
||||
if(node.name == "sdd1") xml_parse_sdd1(node);
|
||||
if(node.name == "spc7110") xml_parse_spc7110(node);
|
||||
if(node.name == "cx4") xml_parse_cx4(node);
|
||||
if(node.name == "obc1") xml_parse_obc1(node);
|
||||
if(node.name == "setarisc") xml_parse_setarisc(node);
|
||||
if(node.name == "msu1") xml_parse_msu1(node);
|
||||
if(node.name == "serial") xml_parse_serial(node);
|
||||
if(node.name == "link") xml_parse_link(node);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -68,8 +72,8 @@ void Cartridge::xml_parse_rom(xml_element &root) {
|
||||
foreach(attr, leaf.attribute) {
|
||||
if(attr.name == "address") xml_parse_address(m, attr.content);
|
||||
if(attr.name == "mode") xml_parse_mode(m, attr.content);
|
||||
if(attr.name == "offset") m.offset = hex(attr.content);
|
||||
if(attr.name == "size") m.size = hex(attr.content);
|
||||
if(attr.name == "offset") m.offset = xml_parse_hex(attr.content);
|
||||
if(attr.name == "size") m.size = xml_parse_hex(attr.content);
|
||||
}
|
||||
if(m.size == 0) m.size = rom.size();
|
||||
mapping.append(m);
|
||||
@@ -79,7 +83,7 @@ void Cartridge::xml_parse_rom(xml_element &root) {
|
||||
|
||||
void Cartridge::xml_parse_ram(xml_element &root) {
|
||||
foreach(attr, root.attribute) {
|
||||
if(attr.name == "size") ram_size = hex(attr.content);
|
||||
if(attr.name == "size") ram_size = xml_parse_hex(attr.content);
|
||||
}
|
||||
|
||||
foreach(leaf, root.element) {
|
||||
@@ -88,8 +92,8 @@ void Cartridge::xml_parse_ram(xml_element &root) {
|
||||
foreach(attr, leaf.attribute) {
|
||||
if(attr.name == "address") xml_parse_address(m, attr.content);
|
||||
if(attr.name == "mode") xml_parse_mode(m, attr.content);
|
||||
if(attr.name == "offset") m.offset = hex(attr.content);
|
||||
if(attr.name == "size") m.size = hex(attr.content);
|
||||
if(attr.name == "offset") m.offset = xml_parse_hex(attr.content);
|
||||
if(attr.name == "size") m.size = xml_parse_hex(attr.content);
|
||||
}
|
||||
if(m.size == 0) m.size = ram_size;
|
||||
mapping.append(m);
|
||||
@@ -97,6 +101,33 @@ void Cartridge::xml_parse_ram(xml_element &root) {
|
||||
}
|
||||
}
|
||||
|
||||
void Cartridge::xml_parse_nss(xml_element &root) {
|
||||
has_nss_dip = true;
|
||||
|
||||
foreach(node, root.element) {
|
||||
if(node.name == "setting") {
|
||||
unsigned number = information.nss.setting.size();
|
||||
if(number >= 16) break; //more than 16 DIP switches is not possible
|
||||
|
||||
information.nss.option[number].reset();
|
||||
foreach(attr, node.attribute) {
|
||||
if(attr.name == "name") {
|
||||
information.nss.setting[number] = attr.parse();
|
||||
}
|
||||
}
|
||||
foreach(leaf, node.element) {
|
||||
string name;
|
||||
unsigned value = 0x0000;
|
||||
foreach(attr, leaf.attribute) {
|
||||
if(attr.name == "name") name = attr.parse();
|
||||
if(attr.name == "value") value = (uint16)xml_parse_hex(attr.content);
|
||||
}
|
||||
information.nss.option[number].append({ hex<4>(value), ":", name });
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Cartridge::xml_parse_icd2(xml_element &root) {
|
||||
if(mode != Mode::SuperGameBoy) return;
|
||||
icd2.revision = 1;
|
||||
@@ -130,15 +161,15 @@ void Cartridge::xml_parse_superfx(xml_element &root) {
|
||||
foreach(attr, leaf.attribute) {
|
||||
if(attr.name == "address") xml_parse_address(m, attr.content);
|
||||
if(attr.name == "mode") xml_parse_mode(m, attr.content);
|
||||
if(attr.name == "offset") m.offset = hex(attr.content);
|
||||
if(attr.name == "size") m.size = hex(attr.content);
|
||||
if(attr.name == "offset") m.offset = xml_parse_hex(attr.content);
|
||||
if(attr.name == "size") m.size = xml_parse_hex(attr.content);
|
||||
}
|
||||
mapping.append(m);
|
||||
}
|
||||
}
|
||||
} else if(node.name == "ram") {
|
||||
foreach(attr, node.attribute) {
|
||||
if(attr.name == "size") ram_size = hex(attr.content);
|
||||
if(attr.name == "size") ram_size = xml_parse_hex(attr.content);
|
||||
}
|
||||
|
||||
foreach(leaf, node.element) {
|
||||
@@ -147,8 +178,8 @@ void Cartridge::xml_parse_superfx(xml_element &root) {
|
||||
foreach(attr, leaf.attribute) {
|
||||
if(attr.name == "address") xml_parse_address(m, attr.content);
|
||||
if(attr.name == "mode") xml_parse_mode(m, attr.content);
|
||||
if(attr.name == "offset") m.offset = hex(attr.content);
|
||||
if(attr.name == "size") m.size = hex(attr.content);
|
||||
if(attr.name == "offset") m.offset = xml_parse_hex(attr.content);
|
||||
if(attr.name == "size") m.size = xml_parse_hex(attr.content);
|
||||
}
|
||||
if(m.size == 0) m.size = ram_size;
|
||||
mapping.append(m);
|
||||
@@ -181,8 +212,8 @@ void Cartridge::xml_parse_sa1(xml_element &root) {
|
||||
foreach(attr, leaf.attribute) {
|
||||
if(attr.name == "address") xml_parse_address(m, attr.content);
|
||||
if(attr.name == "mode") xml_parse_mode(m, attr.content);
|
||||
if(attr.name == "offset") m.offset = hex(attr.content);
|
||||
if(attr.name == "size") m.size = hex(attr.content);
|
||||
if(attr.name == "offset") m.offset = xml_parse_hex(attr.content);
|
||||
if(attr.name == "size") m.size = xml_parse_hex(attr.content);
|
||||
}
|
||||
mapping.append(m);
|
||||
}
|
||||
@@ -206,8 +237,8 @@ void Cartridge::xml_parse_sa1(xml_element &root) {
|
||||
foreach(attr, leaf.attribute) {
|
||||
if(attr.name == "address") xml_parse_address(m, attr.content);
|
||||
if(attr.name == "mode") xml_parse_mode(m, attr.content);
|
||||
if(attr.name == "offset") m.offset = hex(attr.content);
|
||||
if(attr.name == "size") m.size = hex(attr.content);
|
||||
if(attr.name == "offset") m.offset = xml_parse_hex(attr.content);
|
||||
if(attr.name == "size") m.size = xml_parse_hex(attr.content);
|
||||
}
|
||||
if(m.size == 0) m.size = 2048;
|
||||
mapping.append(m);
|
||||
@@ -215,7 +246,7 @@ void Cartridge::xml_parse_sa1(xml_element &root) {
|
||||
}
|
||||
} else if(node.name == "bwram") {
|
||||
foreach(attr, node.attribute) {
|
||||
if(attr.name == "size") ram_size = hex(attr.content);
|
||||
if(attr.name == "size") ram_size = xml_parse_hex(attr.content);
|
||||
}
|
||||
|
||||
foreach(leaf, node.element) {
|
||||
@@ -224,8 +255,8 @@ void Cartridge::xml_parse_sa1(xml_element &root) {
|
||||
foreach(attr, leaf.attribute) {
|
||||
if(attr.name == "address") xml_parse_address(m, attr.content);
|
||||
if(attr.name == "mode") xml_parse_mode(m, attr.content);
|
||||
if(attr.name == "offset") m.offset = hex(attr.content);
|
||||
if(attr.name == "size") m.size = hex(attr.content);
|
||||
if(attr.name == "offset") m.offset = xml_parse_hex(attr.content);
|
||||
if(attr.name == "size") m.size = xml_parse_hex(attr.content);
|
||||
}
|
||||
if(m.size == 0) m.size = ram_size;
|
||||
mapping.append(m);
|
||||
@@ -257,11 +288,11 @@ void Cartridge::xml_parse_necdsp(xml_element &root) {
|
||||
string sha256;
|
||||
|
||||
foreach(attr, root.attribute) {
|
||||
if(attr.name == "revision") {
|
||||
if(attr.content == "upd7725" ) necdsp.revision = NECDSP::Revision::uPD7725;
|
||||
if(attr.content == "upd96050") necdsp.revision = NECDSP::Revision::uPD96050;
|
||||
if(attr.name == "model") {
|
||||
if(attr.content == "uPD7725" ) necdsp.revision = NECDSP::Revision::uPD7725;
|
||||
if(attr.content == "uPD96050") necdsp.revision = NECDSP::Revision::uPD96050;
|
||||
} else if(attr.name == "frequency") {
|
||||
necdsp.frequency = decimal(attr.content);
|
||||
necdsp.frequency = xml_parse_unsigned(attr.content);
|
||||
} else if(attr.name == "program") {
|
||||
program = attr.content;
|
||||
} else if(attr.name == "sha256") {
|
||||
@@ -340,6 +371,85 @@ void Cartridge::xml_parse_necdsp(xml_element &root) {
|
||||
}
|
||||
}
|
||||
|
||||
void Cartridge::xml_parse_hitachidsp(xml_element &root) {
|
||||
has_hitachidsp = true;
|
||||
hitachidsp.frequency = 20000000;
|
||||
|
||||
for(unsigned n = 0; n < 1024; n++) hitachidsp.dataROM[n] = 0x000000;
|
||||
|
||||
string dataROM, sha256;
|
||||
|
||||
foreach(attr, root.attribute) {
|
||||
if(attr.name == "frequency") {
|
||||
hitachidsp.frequency = xml_parse_unsigned(attr.content);
|
||||
} else if(attr.name == "data") {
|
||||
dataROM = attr.content;
|
||||
} else if(attr.name == "sha256") {
|
||||
sha256 = attr.content;
|
||||
}
|
||||
}
|
||||
|
||||
string path = { dir(system.interface->path(Slot::Base, ".dsp")), dataROM };
|
||||
file fp;
|
||||
if(fp.open(path, file::mode::read) == false) {
|
||||
system.interface->message({ "Warning: Hitachi DSP data ", dataROM, " is missing." });
|
||||
} else if(fp.size() != 1024 * 3) {
|
||||
system.interface->message({ "Warning: Hitachi DSP data ", dataROM, " is of the wrong file size." });
|
||||
fp.close();
|
||||
} else {
|
||||
for(unsigned n = 0; n < 1024; n++) hitachidsp.dataROM[n] = fp.readl(3);
|
||||
|
||||
if(sha256 != "") {
|
||||
//XML file specified SHA256 sum for program. Verify file matches the hash.
|
||||
fp.seek(0);
|
||||
uint8 data[3072];
|
||||
fp.read(data, 3072);
|
||||
|
||||
sha256_ctx sha;
|
||||
uint8 hash[32];
|
||||
sha256_init(&sha);
|
||||
sha256_chunk(&sha, data, 3072);
|
||||
sha256_final(&sha);
|
||||
sha256_hash(&sha, hash);
|
||||
|
||||
string filehash;
|
||||
foreach(n, hash) filehash.append(hex<2>(n));
|
||||
|
||||
if(sha256 != filehash) {
|
||||
system.interface->message({ "Warning: Hitachi DSP data ", dataROM, " SHA256 sum is incorrect." });
|
||||
}
|
||||
}
|
||||
|
||||
fp.close();
|
||||
}
|
||||
|
||||
foreach(node, root.element) {
|
||||
if(node.name == "rom") {
|
||||
foreach(leaf, node.element) {
|
||||
if(leaf.name == "map") {
|
||||
Mapping m({ &HitachiDSP::rom_read, &hitachidsp }, { &HitachiDSP::rom_write, &hitachidsp });
|
||||
foreach(attr, leaf.attribute) {
|
||||
if(attr.name == "address") xml_parse_address(m, attr.content);
|
||||
if(attr.name == "mode") xml_parse_mode(m, attr.content);
|
||||
if(attr.name == "offset") m.offset = xml_parse_hex(attr.content);
|
||||
if(attr.name == "size") m.size = xml_parse_hex(attr.content);
|
||||
}
|
||||
mapping.append(m);
|
||||
}
|
||||
}
|
||||
}
|
||||
if(node.name == "mmio") {
|
||||
foreach(leaf, node.element) {
|
||||
Mapping m({ &HitachiDSP::dsp_read, &hitachidsp }, { &HitachiDSP::dsp_write, &hitachidsp });
|
||||
foreach(attr, leaf.attribute) {
|
||||
if(attr.name == "address") xml_parse_address(m, attr.content);
|
||||
}
|
||||
mapping.append(m);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Cartridge::xml_parse_bsx(xml_element &root) {
|
||||
if(mode != Mode::BsxSlotted && mode != Mode::Bsx) return;
|
||||
|
||||
@@ -351,8 +461,8 @@ void Cartridge::xml_parse_bsx(xml_element &root) {
|
||||
foreach(attr, leaf.attribute) {
|
||||
if(attr.name == "address") xml_parse_address(m, attr.content);
|
||||
if(attr.name == "mode") xml_parse_mode(m, attr.content);
|
||||
if(attr.name == "offset") m.offset = hex(attr.content);
|
||||
if(attr.name == "size") m.size = hex(attr.content);
|
||||
if(attr.name == "offset") m.offset = xml_parse_hex(attr.content);
|
||||
if(attr.name == "size") m.size = xml_parse_hex(attr.content);
|
||||
}
|
||||
mapping.append(m);
|
||||
}
|
||||
@@ -403,8 +513,8 @@ void Cartridge::xml_parse_sufamiturbo(xml_element &root) {
|
||||
foreach(attr, leaf.attribute) {
|
||||
if(attr.name == "address") xml_parse_address(m, attr.content);
|
||||
if(attr.name == "mode") xml_parse_mode(m, attr.content);
|
||||
if(attr.name == "offset") m.offset = hex(attr.content);
|
||||
if(attr.name == "size") m.size = hex(attr.content);
|
||||
if(attr.name == "offset") m.offset = xml_parse_hex(attr.content);
|
||||
if(attr.name == "size") m.size = xml_parse_hex(attr.content);
|
||||
}
|
||||
if(m.size == 0) m.size = memory.size();
|
||||
if(m.size) mapping.append(m);
|
||||
@@ -414,7 +524,7 @@ void Cartridge::xml_parse_sufamiturbo(xml_element &root) {
|
||||
unsigned ram_size = 0;
|
||||
|
||||
foreach(attr, slot.attribute) {
|
||||
if(attr.name == "size") ram_size = hex(attr.content);
|
||||
if(attr.name == "size") ram_size = xml_parse_hex(attr.content);
|
||||
}
|
||||
|
||||
foreach(leaf, slot.element) {
|
||||
@@ -424,8 +534,8 @@ void Cartridge::xml_parse_sufamiturbo(xml_element &root) {
|
||||
foreach(attr, leaf.attribute) {
|
||||
if(attr.name == "address") xml_parse_address(m, attr.content);
|
||||
if(attr.name == "mode") xml_parse_mode(m, attr.content);
|
||||
if(attr.name == "offset") m.offset = hex(attr.content);
|
||||
if(attr.name == "size") m.size = hex(attr.content);
|
||||
if(attr.name == "offset") m.offset = xml_parse_hex(attr.content);
|
||||
if(attr.name == "size") m.size = xml_parse_hex(attr.content);
|
||||
}
|
||||
if(m.size == 0) m.size = ram_size;
|
||||
if(m.size) mapping.append(m);
|
||||
@@ -500,7 +610,7 @@ void Cartridge::xml_parse_spc7110(xml_element &root) {
|
||||
Mapping m({ &SPC7110::mcu_read, &spc7110 }, { &SPC7110::mcu_write, &spc7110 });
|
||||
foreach(attr, leaf.attribute) {
|
||||
if(attr.name == "address") xml_parse_address(m, attr.content);
|
||||
if(attr.name == "offset") spc7110.data_rom_offset = hex(attr.content);
|
||||
if(attr.name == "offset") spc7110.data_rom_offset = xml_parse_hex(attr.content);
|
||||
}
|
||||
mapping.append(m);
|
||||
}
|
||||
@@ -517,7 +627,7 @@ void Cartridge::xml_parse_spc7110(xml_element &root) {
|
||||
}
|
||||
} else if(node.name == "ram") {
|
||||
foreach(attr, node.attribute) {
|
||||
if(attr.name == "size") ram_size = hex(attr.content);
|
||||
if(attr.name == "size") ram_size = xml_parse_hex(attr.content);
|
||||
}
|
||||
|
||||
foreach(leaf, node.element) {
|
||||
@@ -526,8 +636,8 @@ void Cartridge::xml_parse_spc7110(xml_element &root) {
|
||||
foreach(attr, leaf.attribute) {
|
||||
if(attr.name == "address") xml_parse_address(m, attr.content);
|
||||
if(attr.name == "mode") xml_parse_mode(m, attr.content);
|
||||
if(attr.name == "offset") m.offset = hex(attr.content);
|
||||
if(attr.name == "size") m.size = hex(attr.content);
|
||||
if(attr.name == "offset") m.offset = xml_parse_hex(attr.content);
|
||||
if(attr.name == "size") m.size = xml_parse_hex(attr.content);
|
||||
}
|
||||
mapping.append(m);
|
||||
}
|
||||
@@ -548,20 +658,6 @@ void Cartridge::xml_parse_spc7110(xml_element &root) {
|
||||
}
|
||||
}
|
||||
|
||||
void Cartridge::xml_parse_cx4(xml_element &root) {
|
||||
has_cx4 = true;
|
||||
|
||||
foreach(node, root.element) {
|
||||
if(node.name == "map") {
|
||||
Mapping m({ &Cx4::read, &cx4 }, { &Cx4::write, &cx4 });
|
||||
foreach(attr, node.attribute) {
|
||||
if(attr.name == "address") xml_parse_address(m, attr.content);
|
||||
}
|
||||
mapping.append(m);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Cartridge::xml_parse_obc1(xml_element &root) {
|
||||
has_obc1 = true;
|
||||
|
||||
@@ -604,8 +700,34 @@ void Cartridge::xml_parse_msu1(xml_element &root) {
|
||||
}
|
||||
}
|
||||
|
||||
void Cartridge::xml_parse_serial(xml_element &root) {
|
||||
has_serial = true;
|
||||
void Cartridge::xml_parse_link(xml_element &root) {
|
||||
has_link = true;
|
||||
link.frequency = 1;
|
||||
link.program = "";
|
||||
|
||||
foreach(attr, root.attribute) {
|
||||
if(attr.name == "frequency") link.frequency = xml_parse_unsigned(attr.content);
|
||||
if(attr.name == "program") link.program = attr.content;
|
||||
}
|
||||
|
||||
foreach(node, root.element) {
|
||||
if(node.name == "map") {
|
||||
Mapping m({ &Link::read, &link }, { &Link::write, &link });
|
||||
foreach(attr, node.attribute) {
|
||||
if(attr.name == "address") xml_parse_address(m, attr.content);
|
||||
}
|
||||
mapping.append(m);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unsigned Cartridge::xml_parse_hex(const string &s) {
|
||||
return hex(s);
|
||||
}
|
||||
|
||||
unsigned Cartridge::xml_parse_unsigned(const string &s) {
|
||||
if(s.beginswith("0x")) return hex(s);
|
||||
return integer(s);
|
||||
}
|
||||
|
||||
void Cartridge::xml_parse_address(Mapping &m, const string &data) {
|
||||
|
@@ -15,7 +15,7 @@ void Cheat::enable(bool state) {
|
||||
}
|
||||
|
||||
void Cheat::synchronize() {
|
||||
memcpy(bus.lookup, lookup, 16 * 1024 * 1024);
|
||||
memset(override, 0x00, 16 * 1024 * 1024);
|
||||
code_enabled = false;
|
||||
|
||||
for(unsigned i = 0; i < size(); i++) {
|
||||
@@ -26,16 +26,16 @@ void Cheat::synchronize() {
|
||||
code_enabled = true;
|
||||
|
||||
unsigned addr = mirror(code.addr[n]);
|
||||
bus.lookup[addr] = 0xff;
|
||||
override[addr] = true;
|
||||
if((addr & 0xffe000) == 0x7e0000) {
|
||||
//mirror $7e:0000-1fff to $00-3f|80-bf:0000-1fff
|
||||
unsigned mirroraddr;
|
||||
for(unsigned x = 0; x <= 0x3f; x++) {
|
||||
mirroraddr = ((0x00 + x) << 16) + (addr & 0x1fff);
|
||||
bus.lookup[mirroraddr] = 0xff;
|
||||
override[mirroraddr] = true;
|
||||
|
||||
mirroraddr = ((0x80 + x) << 16) + (addr & 0x1fff);
|
||||
bus.lookup[mirroraddr] = 0xff;
|
||||
override[mirroraddr] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -62,25 +62,16 @@ uint8 Cheat::read(unsigned addr) const {
|
||||
}
|
||||
|
||||
void Cheat::init() {
|
||||
bus.reader[0xff] = [](unsigned addr) {
|
||||
bus.reader[cheat.lookup[addr]](bus.target[addr]);
|
||||
return cheat.read(addr);
|
||||
};
|
||||
|
||||
bus.writer[0xff] = [](unsigned addr, uint8 data) {
|
||||
return bus.writer[cheat.lookup[addr]](bus.target[addr], data);
|
||||
};
|
||||
|
||||
memcpy(lookup, bus.lookup, 16 * 1024 * 1024);
|
||||
memset(override, 0x00, 16 * 1024 * 1024);
|
||||
}
|
||||
|
||||
Cheat::Cheat() {
|
||||
lookup = new uint8[16 * 1024 * 1024];
|
||||
override = new uint8[16 * 1024 * 1024];
|
||||
system_enabled = true;
|
||||
}
|
||||
|
||||
Cheat::~Cheat() {
|
||||
delete[] lookup;
|
||||
delete[] override;
|
||||
}
|
||||
|
||||
//===============
|
||||
|
@@ -10,6 +10,7 @@ struct CheatCode {
|
||||
class Cheat : public linear_vector<CheatCode> {
|
||||
public:
|
||||
enum class Type : unsigned { ProActionReplay, GameGenie };
|
||||
uint8 *override;
|
||||
|
||||
bool enabled() const;
|
||||
void enable(bool);
|
||||
@@ -24,7 +25,6 @@ public:
|
||||
static bool encode(string&, unsigned, uint8, Type);
|
||||
|
||||
private:
|
||||
uint8 *lookup;
|
||||
bool system_enabled;
|
||||
bool code_enabled;
|
||||
bool cheat_enabled;
|
||||
|
@@ -3,20 +3,21 @@ struct Coprocessor : Processor {
|
||||
alwaysinline void synchronize_cpu();
|
||||
};
|
||||
|
||||
#include <snes/chip/nss/nss.hpp>
|
||||
#include <snes/chip/icd2/icd2.hpp>
|
||||
#include <snes/chip/superfx/superfx.hpp>
|
||||
#include <snes/chip/sa1/sa1.hpp>
|
||||
#include <snes/chip/necdsp/necdsp.hpp>
|
||||
#include <snes/chip/hitachidsp/hitachidsp.hpp>
|
||||
#include <snes/chip/bsx/bsx.hpp>
|
||||
#include <snes/chip/srtc/srtc.hpp>
|
||||
#include <snes/chip/sdd1/sdd1.hpp>
|
||||
#include <snes/chip/spc7110/spc7110.hpp>
|
||||
#include <snes/chip/cx4/cx4.hpp>
|
||||
#include <snes/chip/obc1/obc1.hpp>
|
||||
#include <snes/chip/st0018/st0018.hpp>
|
||||
#include <snes/chip/sufamiturbo/sufamiturbo.hpp>
|
||||
#include <snes/chip/msu1/msu1.hpp>
|
||||
#include <snes/chip/serial/serial.hpp>
|
||||
#include <snes/chip/link/link.hpp>
|
||||
|
||||
void Coprocessor::step(unsigned clocks) {
|
||||
clock += clocks * (uint64)cpu.frequency;
|
||||
|
@@ -1,211 +0,0 @@
|
||||
//=============
|
||||
//Cx4 emulation
|
||||
//=============
|
||||
//Used in Rockman X2/X3 (Megaman X2/X3)
|
||||
//Portions (c) anomie, Overload, zsKnight, Nach, byuu
|
||||
|
||||
#include <snes/snes.hpp>
|
||||
|
||||
#define CX4_CPP
|
||||
namespace SNES {
|
||||
|
||||
Cx4 cx4;
|
||||
|
||||
#include "serialization.cpp"
|
||||
#include "data.cpp"
|
||||
#include "functions.cpp"
|
||||
#include "oam.cpp"
|
||||
#include "opcodes.cpp"
|
||||
|
||||
void Cx4::init() {
|
||||
}
|
||||
|
||||
void Cx4::load() {
|
||||
}
|
||||
|
||||
void Cx4::unload() {
|
||||
}
|
||||
|
||||
uint32 Cx4::ldr(uint8 r) {
|
||||
uint16 addr = 0x0080 + (r * 3);
|
||||
return (reg[addr + 0] << 0)
|
||||
| (reg[addr + 1] << 8)
|
||||
| (reg[addr + 2] << 16);
|
||||
}
|
||||
|
||||
void Cx4::str(uint8 r, uint32 data) {
|
||||
uint16 addr = 0x0080 + (r * 3);
|
||||
reg[addr + 0] = (data >> 0);
|
||||
reg[addr + 1] = (data >> 8);
|
||||
reg[addr + 2] = (data >> 16);
|
||||
}
|
||||
|
||||
void Cx4::mul(uint32 x, uint32 y, uint32 &rl, uint32 &rh) {
|
||||
int64 rx = x & 0xffffff;
|
||||
int64 ry = y & 0xffffff;
|
||||
if(rx & 0x800000)rx |= ~0x7fffff;
|
||||
if(ry & 0x800000)ry |= ~0x7fffff;
|
||||
|
||||
rx *= ry;
|
||||
|
||||
rl = (rx) & 0xffffff;
|
||||
rh = (rx >> 24) & 0xffffff;
|
||||
}
|
||||
|
||||
uint32 Cx4::sin(uint32 rx) {
|
||||
r0 = rx & 0x1ff;
|
||||
if(r0 & 0x100)r0 ^= 0x1ff;
|
||||
if(r0 & 0x080)r0 ^= 0x0ff;
|
||||
if(rx & 0x100) {
|
||||
return sin_table[r0 + 0x80];
|
||||
} else {
|
||||
return sin_table[r0];
|
||||
}
|
||||
}
|
||||
|
||||
uint32 Cx4::cos(uint32 rx) {
|
||||
return sin(rx + 0x080);
|
||||
}
|
||||
|
||||
void Cx4::immediate_reg(uint32 start) {
|
||||
r0 = ldr(0);
|
||||
for(uint32 i = start; i < 48; i++) {
|
||||
if((r0 & 0x0fff) < 0x0c00) {
|
||||
ram[r0 & 0x0fff] = immediate_data[i];
|
||||
}
|
||||
r0++;
|
||||
}
|
||||
str(0, r0);
|
||||
}
|
||||
|
||||
void Cx4::transfer_data() {
|
||||
uint32 src;
|
||||
uint16 dest, count;
|
||||
|
||||
src = (reg[0x40]) | (reg[0x41] << 8) | (reg[0x42] << 16);
|
||||
count = (reg[0x43]) | (reg[0x44] << 8);
|
||||
dest = (reg[0x45]) | (reg[0x46] << 8);
|
||||
|
||||
for(uint32 i=0;i<count;i++) {
|
||||
write(dest++, bus.read(src++));
|
||||
}
|
||||
}
|
||||
|
||||
void Cx4::write(unsigned addr, uint8 data) {
|
||||
addr &= 0x1fff;
|
||||
|
||||
if(addr < 0x0c00) {
|
||||
//ram
|
||||
ram[addr] = data;
|
||||
return;
|
||||
}
|
||||
|
||||
if(addr < 0x1f00) {
|
||||
//unmapped
|
||||
return;
|
||||
}
|
||||
|
||||
//command register
|
||||
reg[addr & 0xff] = data;
|
||||
|
||||
if(addr == 0x1f47) {
|
||||
//memory transfer
|
||||
transfer_data();
|
||||
return;
|
||||
}
|
||||
|
||||
if(addr == 0x1f4f) {
|
||||
//c4 command
|
||||
if(reg[0x4d] == 0x0e && !(data & 0xc3)) {
|
||||
//c4 test command
|
||||
reg[0x80] = data >> 2;
|
||||
return;
|
||||
}
|
||||
|
||||
switch(data) {
|
||||
case 0x00: op00(); break;
|
||||
case 0x01: op01(); break;
|
||||
case 0x05: op05(); break;
|
||||
case 0x0d: op0d(); break;
|
||||
case 0x10: op10(); break;
|
||||
case 0x13: op13(); break;
|
||||
case 0x15: op15(); break;
|
||||
case 0x1f: op1f(); break;
|
||||
case 0x22: op22(); break;
|
||||
case 0x25: op25(); break;
|
||||
case 0x2d: op2d(); break;
|
||||
case 0x40: op40(); break;
|
||||
case 0x54: op54(); break;
|
||||
case 0x5c: op5c(); break;
|
||||
case 0x5e: op5e(); break;
|
||||
case 0x60: op60(); break;
|
||||
case 0x62: op62(); break;
|
||||
case 0x64: op64(); break;
|
||||
case 0x66: op66(); break;
|
||||
case 0x68: op68(); break;
|
||||
case 0x6a: op6a(); break;
|
||||
case 0x6c: op6c(); break;
|
||||
case 0x6e: op6e(); break;
|
||||
case 0x70: op70(); break;
|
||||
case 0x72: op72(); break;
|
||||
case 0x74: op74(); break;
|
||||
case 0x76: op76(); break;
|
||||
case 0x78: op78(); break;
|
||||
case 0x7a: op7a(); break;
|
||||
case 0x7c: op7c(); break;
|
||||
case 0x89: op89(); break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Cx4::writeb(uint16 addr, uint8 data) {
|
||||
write(addr, data);
|
||||
}
|
||||
|
||||
void Cx4::writew(uint16 addr, uint16 data) {
|
||||
write(addr + 0, data >> 0);
|
||||
write(addr + 1, data >> 8);
|
||||
}
|
||||
|
||||
void Cx4::writel(uint16 addr, uint32 data) {
|
||||
write(addr + 0, data >> 0);
|
||||
write(addr + 1, data >> 8);
|
||||
write(addr + 2, data >> 16);
|
||||
}
|
||||
|
||||
uint8 Cx4::read(unsigned addr) {
|
||||
addr &= 0x1fff;
|
||||
|
||||
if(addr < 0x0c00) {
|
||||
return ram[addr];
|
||||
}
|
||||
|
||||
if(addr >= 0x1f00) {
|
||||
return reg[addr & 0xff];
|
||||
}
|
||||
|
||||
return cpu.regs.mdr;
|
||||
}
|
||||
|
||||
uint8 Cx4::readb(uint16 addr) {
|
||||
return read(addr);
|
||||
}
|
||||
|
||||
uint16 Cx4::readw(uint16 addr) {
|
||||
return read(addr) | (read(addr + 1) << 8);
|
||||
}
|
||||
|
||||
uint32 Cx4::readl(uint16 addr) {
|
||||
return read(addr) | (read(addr + 1) << 8) + (read(addr + 2) << 16);
|
||||
}
|
||||
|
||||
void Cx4::power() {
|
||||
reset();
|
||||
}
|
||||
|
||||
void Cx4::reset() {
|
||||
memset(ram, 0, 0x0c00);
|
||||
memset(reg, 0, 0x0100);
|
||||
}
|
||||
|
||||
};
|
@@ -1,96 +0,0 @@
|
||||
class Cx4 {
|
||||
public:
|
||||
void init();
|
||||
void load();
|
||||
void unload();
|
||||
void power();
|
||||
void reset();
|
||||
|
||||
uint8 read(unsigned addr);
|
||||
void write(unsigned addr, uint8 data);
|
||||
|
||||
void serialize(serializer&);
|
||||
|
||||
private:
|
||||
uint8 ram[0x0c00];
|
||||
uint8 reg[0x0100];
|
||||
uint32 r0, r1, r2, r3, r4, r5, r6, r7,
|
||||
r8, r9, r10, r11, r12, r13, r14, r15;
|
||||
|
||||
static const uint8 immediate_data[48];
|
||||
static const uint16 wave_data[40];
|
||||
static const uint32 sin_table[256];
|
||||
|
||||
static const int16 SinTable[512];
|
||||
static const int16 CosTable[512];
|
||||
|
||||
int16 C4WFXVal, C4WFYVal, C4WFZVal, C4WFX2Val, C4WFY2Val, C4WFDist, C4WFScale;
|
||||
int16 C41FXVal, C41FYVal, C41FAngleRes, C41FDist, C41FDistVal;
|
||||
|
||||
void C4TransfWireFrame();
|
||||
void C4TransfWireFrame2();
|
||||
void C4CalcWireFrame();
|
||||
void C4DrawLine(int32 X1, int32 Y1, int16 Z1, int32 X2, int32 Y2, int16 Z2, uint8 Color);
|
||||
void C4DrawWireFrame();
|
||||
void C4DoScaleRotate(int row_padding);
|
||||
|
||||
public:
|
||||
uint32 ldr(uint8 r);
|
||||
void str(uint8 r, uint32 data);
|
||||
void mul(uint32 x, uint32 y, uint32 &rl, uint32 &rh);
|
||||
uint32 sin(uint32 rx);
|
||||
uint32 cos(uint32 rx);
|
||||
|
||||
void transfer_data();
|
||||
void immediate_reg(uint32 num);
|
||||
|
||||
void op00_00();
|
||||
void op00_03();
|
||||
void op00_05();
|
||||
void op00_07();
|
||||
void op00_08();
|
||||
void op00_0b();
|
||||
void op00_0c();
|
||||
|
||||
void op00();
|
||||
void op01();
|
||||
void op05();
|
||||
void op0d();
|
||||
void op10();
|
||||
void op13();
|
||||
void op15();
|
||||
void op1f();
|
||||
void op22();
|
||||
void op25();
|
||||
void op2d();
|
||||
void op40();
|
||||
void op54();
|
||||
void op5c();
|
||||
void op5e();
|
||||
void op60();
|
||||
void op62();
|
||||
void op64();
|
||||
void op66();
|
||||
void op68();
|
||||
void op6a();
|
||||
void op6c();
|
||||
void op6e();
|
||||
void op70();
|
||||
void op72();
|
||||
void op74();
|
||||
void op76();
|
||||
void op78();
|
||||
void op7a();
|
||||
void op7c();
|
||||
void op89();
|
||||
|
||||
uint8 readb(uint16 addr);
|
||||
uint16 readw(uint16 addr);
|
||||
uint32 readl(uint16 addr);
|
||||
|
||||
void writeb(uint16 addr, uint8 data);
|
||||
void writew(uint16 addr, uint16 data);
|
||||
void writel(uint16 addr, uint32 data);
|
||||
};
|
||||
|
||||
extern Cx4 cx4;
|
@@ -1,187 +0,0 @@
|
||||
#ifdef CX4_CPP
|
||||
|
||||
const uint8 Cx4::immediate_data[48] = {
|
||||
0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff,
|
||||
0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x80, 0xff, 0xff, 0x7f,
|
||||
0x00, 0x80, 0x00, 0xff, 0x7f, 0x00, 0xff, 0x7f, 0xff, 0x7f, 0xff, 0xff,
|
||||
0x00, 0x00, 0x01, 0xff, 0xff, 0xfe, 0x00, 0x01, 0x00, 0xff, 0xfe, 0x00
|
||||
};
|
||||
|
||||
const uint16 Cx4::wave_data[40] = {
|
||||
0x0000, 0x0002, 0x0004, 0x0006, 0x0008, 0x000a, 0x000c, 0x000e,
|
||||
0x0200, 0x0202, 0x0204, 0x0206, 0x0208, 0x020a, 0x020c, 0x020e,
|
||||
0x0400, 0x0402, 0x0404, 0x0406, 0x0408, 0x040a, 0x040c, 0x040e,
|
||||
0x0600, 0x0602, 0x0604, 0x0606, 0x0608, 0x060a, 0x060c, 0x060e,
|
||||
0x0800, 0x0802, 0x0804, 0x0806, 0x0808, 0x080a, 0x080c, 0x080e
|
||||
};
|
||||
|
||||
const uint32 Cx4::sin_table[256] = {
|
||||
0x000000, 0x000324, 0x000648, 0x00096c, 0x000c8f, 0x000fb2, 0x0012d5, 0x0015f6,
|
||||
0x001917, 0x001c37, 0x001f56, 0x002273, 0x002590, 0x0028aa, 0x002bc4, 0x002edb,
|
||||
0x0031f1, 0x003505, 0x003817, 0x003b26, 0x003e33, 0x00413e, 0x004447, 0x00474d,
|
||||
0x004a50, 0x004d50, 0x00504d, 0x005347, 0x00563e, 0x005931, 0x005c22, 0x005f0e,
|
||||
0x0061f7, 0x0064dc, 0x0067bd, 0x006a9b, 0x006d74, 0x007049, 0x007319, 0x0075e5,
|
||||
0x0078ad, 0x007b70, 0x007e2e, 0x0080e7, 0x00839c, 0x00864b, 0x0088f5, 0x008b9a,
|
||||
0x008e39, 0x0090d3, 0x009368, 0x0095f6, 0x00987f, 0x009b02, 0x009d7f, 0x009ff6,
|
||||
0x00a267, 0x00a4d2, 0x00a736, 0x00a994, 0x00abeb, 0x00ae3b, 0x00b085, 0x00b2c8,
|
||||
0x00b504, 0x00b73a, 0x00b968, 0x00bb8f, 0x00bdae, 0x00bfc7, 0x00c1d8, 0x00c3e2,
|
||||
0x00c5e4, 0x00c7de, 0x00c9d1, 0x00cbbb, 0x00cd9f, 0x00cf7a, 0x00d14d, 0x00d318,
|
||||
0x00d4db, 0x00d695, 0x00d848, 0x00d9f2, 0x00db94, 0x00dd2d, 0x00debe, 0x00e046,
|
||||
0x00e1c5, 0x00e33c, 0x00e4aa, 0x00e60f, 0x00e76b, 0x00e8bf, 0x00ea09, 0x00eb4b,
|
||||
0x00ec83, 0x00edb2, 0x00eed8, 0x00eff5, 0x00f109, 0x00f213, 0x00f314, 0x00f40b,
|
||||
0x00f4fa, 0x00f5de, 0x00f6ba, 0x00f78b, 0x00f853, 0x00f912, 0x00f9c7, 0x00fa73,
|
||||
0x00fb14, 0x00fbac, 0x00fc3b, 0x00fcbf, 0x00fd3a, 0x00fdab, 0x00fe13, 0x00fe70,
|
||||
0x00fec4, 0x00ff0e, 0x00ff4e, 0x00ff84, 0x00ffb1, 0x00ffd3, 0x00ffec, 0x00fffb,
|
||||
0x000000, 0xfffcdb, 0xfff9b7, 0xfff693, 0xfff370, 0xfff04d, 0xffed2a, 0xffea09,
|
||||
0xffe6e8, 0xffe3c8, 0xffe0a9, 0xffdd8c, 0xffda6f, 0xffd755, 0xffd43b, 0xffd124,
|
||||
0xffce0e, 0xffcafa, 0xffc7e8, 0xffc4d9, 0xffc1cc, 0xffbec1, 0xffbbb8, 0xffb8b2,
|
||||
0xffb5af, 0xffb2af, 0xffafb2, 0xffacb8, 0xffa9c1, 0xffa6ce, 0xffa3dd, 0xffa0f1,
|
||||
0xff9e08, 0xff9b23, 0xff9842, 0xff9564, 0xff928b, 0xff8fb6, 0xff8ce6, 0xff8a1a,
|
||||
0xff8752, 0xff848f, 0xff81d1, 0xff7f18, 0xff7c63, 0xff79b4, 0xff770a, 0xff7465,
|
||||
0xff71c6, 0xff6f2c, 0xff6c97, 0xff6a09, 0xff6780, 0xff64fd, 0xff6280, 0xff6009,
|
||||
0xff5d98, 0xff5b2d, 0xff58c9, 0xff566b, 0xff5414, 0xff51c4, 0xff4f7a, 0xff4d37,
|
||||
0xff4afb, 0xff48c5, 0xff4697, 0xff4470, 0xff4251, 0xff4038, 0xff3e27, 0xff3c1e,
|
||||
0xff3a1b, 0xff3821, 0xff362e, 0xff3444, 0xff3260, 0xff3085, 0xff2eb2, 0xff2ce7,
|
||||
0xff2b24, 0xff296a, 0xff27b7, 0xff260d, 0xff246b, 0xff22d2, 0xff2141, 0xff1fb9,
|
||||
0xff1e3a, 0xff1cc3, 0xff1b55, 0xff19f0, 0xff1894, 0xff1740, 0xff15f6, 0xff14b4,
|
||||
0xff137c, 0xff124d, 0xff1127, 0xff100a, 0xff0ef6, 0xff0dec, 0xff0ceb, 0xff0bf4,
|
||||
0xff0b05, 0xff0a21, 0xff0945, 0xff0874, 0xff07ac, 0xff06ed, 0xff0638, 0xff058d,
|
||||
0xff04eb, 0xff0453, 0xff03c4, 0xff0340, 0xff02c5, 0xff0254, 0xff01ec, 0xff018f,
|
||||
0xff013b, 0xff00f1, 0xff00b1, 0xff007b, 0xff004e, 0xff002c, 0xff0013, 0xff0004
|
||||
};
|
||||
|
||||
const int16 Cx4::SinTable[512] = {
|
||||
0, 402, 804, 1206, 1607, 2009, 2410, 2811,
|
||||
3211, 3611, 4011, 4409, 4808, 5205, 5602, 5997,
|
||||
6392, 6786, 7179, 7571, 7961, 8351, 8739, 9126,
|
||||
9512, 9896, 10278, 10659, 11039, 11416, 11793, 12167,
|
||||
12539, 12910, 13278, 13645, 14010, 14372, 14732, 15090,
|
||||
15446, 15800, 16151, 16499, 16846, 17189, 17530, 17869,
|
||||
18204, 18537, 18868, 19195, 19519, 19841, 20159, 20475,
|
||||
20787, 21097, 21403, 21706, 22005, 22301, 22594, 22884,
|
||||
23170, 23453, 23732, 24007, 24279, 24547, 24812, 25073,
|
||||
25330, 25583, 25832, 26077, 26319, 26557, 26790, 27020,
|
||||
27245, 27466, 27684, 27897, 28106, 28310, 28511, 28707,
|
||||
28898, 29086, 29269, 29447, 29621, 29791, 29956, 30117,
|
||||
30273, 30425, 30572, 30714, 30852, 30985, 31114, 31237,
|
||||
31357, 31471, 31581, 31685, 31785, 31881, 31971, 32057,
|
||||
32138, 32214, 32285, 32351, 32413, 32469, 32521, 32568,
|
||||
32610, 32647, 32679, 32706, 32728, 32745, 32758, 32765,
|
||||
32767, 32765, 32758, 32745, 32728, 32706, 32679, 32647,
|
||||
32610, 32568, 32521, 32469, 32413, 32351, 32285, 32214,
|
||||
32138, 32057, 31971, 31881, 31785, 31685, 31581, 31471,
|
||||
31357, 31237, 31114, 30985, 30852, 30714, 30572, 30425,
|
||||
30273, 30117, 29956, 29791, 29621, 29447, 29269, 29086,
|
||||
28898, 28707, 28511, 28310, 28106, 27897, 27684, 27466,
|
||||
27245, 27020, 26790, 26557, 26319, 26077, 25832, 25583,
|
||||
25330, 25073, 24812, 24547, 24279, 24007, 23732, 23453,
|
||||
23170, 22884, 22594, 22301, 22005, 21706, 21403, 21097,
|
||||
20787, 20475, 20159, 19841, 19519, 19195, 18868, 18537,
|
||||
18204, 17869, 17530, 17189, 16846, 16499, 16151, 15800,
|
||||
15446, 15090, 14732, 14372, 14010, 13645, 13278, 12910,
|
||||
12539, 12167, 11793, 11416, 11039, 10659, 10278, 9896,
|
||||
9512, 9126, 8739, 8351, 7961, 7571, 7179, 6786,
|
||||
6392, 5997, 5602, 5205, 4808, 4409, 4011, 3611,
|
||||
3211, 2811, 2410, 2009, 1607, 1206, 804, 402,
|
||||
0, -402, -804, -1206, -1607, -2009, -2410, -2811,
|
||||
-3211, -3611, -4011, -4409, -4808, -5205, -5602, -5997,
|
||||
-6392, -6786, -7179, -7571, -7961, -8351, -8739, -9126,
|
||||
-9512, -9896, -10278, -10659, -11039, -11416, -11793, -12167,
|
||||
-12539, -12910, -13278, -13645, -14010, -14372, -14732, -15090,
|
||||
-15446, -15800, -16151, -16499, -16846, -17189, -17530, -17869,
|
||||
-18204, -18537, -18868, -19195, -19519, -19841, -20159, -20475,
|
||||
-20787, -21097, -21403, -21706, -22005, -22301, -22594, -22884,
|
||||
-23170, -23453, -23732, -24007, -24279, -24547, -24812, -25073,
|
||||
-25330, -25583, -25832, -26077, -26319, -26557, -26790, -27020,
|
||||
-27245, -27466, -27684, -27897, -28106, -28310, -28511, -28707,
|
||||
-28898, -29086, -29269, -29447, -29621, -29791, -29956, -30117,
|
||||
-30273, -30425, -30572, -30714, -30852, -30985, -31114, -31237,
|
||||
-31357, -31471, -31581, -31685, -31785, -31881, -31971, -32057,
|
||||
-32138, -32214, -32285, -32351, -32413, -32469, -32521, -32568,
|
||||
-32610, -32647, -32679, -32706, -32728, -32745, -32758, -32765,
|
||||
-32767, -32765, -32758, -32745, -32728, -32706, -32679, -32647,
|
||||
-32610, -32568, -32521, -32469, -32413, -32351, -32285, -32214,
|
||||
-32138, -32057, -31971, -31881, -31785, -31685, -31581, -31471,
|
||||
-31357, -31237, -31114, -30985, -30852, -30714, -30572, -30425,
|
||||
-30273, -30117, -29956, -29791, -29621, -29447, -29269, -29086,
|
||||
-28898, -28707, -28511, -28310, -28106, -27897, -27684, -27466,
|
||||
-27245, -27020, -26790, -26557, -26319, -26077, -25832, -25583,
|
||||
-25330, -25073, -24812, -24547, -24279, -24007, -23732, -23453,
|
||||
-23170, -22884, -22594, -22301, -22005, -21706, -21403, -21097,
|
||||
-20787, -20475, -20159, -19841, -19519, -19195, -18868, -18537,
|
||||
-18204, -17869, -17530, -17189, -16846, -16499, -16151, -15800,
|
||||
-15446, -15090, -14732, -14372, -14010, -13645, -13278, -12910,
|
||||
-12539, -12167, -11793, -11416, -11039, -10659, -10278, -9896,
|
||||
-9512, -9126, -8739, -8351, -7961, -7571, -7179, -6786,
|
||||
-6392, -5997, -5602, -5205, -4808, -4409, -4011, -3611,
|
||||
-3211, -2811, -2410, -2009, -1607, -1206, -804, -402
|
||||
};
|
||||
|
||||
const int16 Cx4::CosTable[512] = {
|
||||
32767, 32765, 32758, 32745, 32728, 32706, 32679, 32647,
|
||||
32610, 32568, 32521, 32469, 32413, 32351, 32285, 32214,
|
||||
32138, 32057, 31971, 31881, 31785, 31685, 31581, 31471,
|
||||
31357, 31237, 31114, 30985, 30852, 30714, 30572, 30425,
|
||||
30273, 30117, 29956, 29791, 29621, 29447, 29269, 29086,
|
||||
28898, 28707, 28511, 28310, 28106, 27897, 27684, 27466,
|
||||
27245, 27020, 26790, 26557, 26319, 26077, 25832, 25583,
|
||||
25330, 25073, 24812, 24547, 24279, 24007, 23732, 23453,
|
||||
23170, 22884, 22594, 22301, 22005, 21706, 21403, 21097,
|
||||
20787, 20475, 20159, 19841, 19519, 19195, 18868, 18537,
|
||||
18204, 17869, 17530, 17189, 16846, 16499, 16151, 15800,
|
||||
15446, 15090, 14732, 14372, 14010, 13645, 13278, 12910,
|
||||
12539, 12167, 11793, 11416, 11039, 10659, 10278, 9896,
|
||||
9512, 9126, 8739, 8351, 7961, 7571, 7179, 6786,
|
||||
6392, 5997, 5602, 5205, 4808, 4409, 4011, 3611,
|
||||
3211, 2811, 2410, 2009, 1607, 1206, 804, 402,
|
||||
0, -402, -804, -1206, -1607, -2009, -2410, -2811,
|
||||
-3211, -3611, -4011, -4409, -4808, -5205, -5602, -5997,
|
||||
-6392, -6786, -7179, -7571, -7961, -8351, -8739, -9126,
|
||||
-9512, -9896, -10278, -10659, -11039, -11416, -11793, -12167,
|
||||
-12539, -12910, -13278, -13645, -14010, -14372, -14732, -15090,
|
||||
-15446, -15800, -16151, -16499, -16846, -17189, -17530, -17869,
|
||||
-18204, -18537, -18868, -19195, -19519, -19841, -20159, -20475,
|
||||
-20787, -21097, -21403, -21706, -22005, -22301, -22594, -22884,
|
||||
-23170, -23453, -23732, -24007, -24279, -24547, -24812, -25073,
|
||||
-25330, -25583, -25832, -26077, -26319, -26557, -26790, -27020,
|
||||
-27245, -27466, -27684, -27897, -28106, -28310, -28511, -28707,
|
||||
-28898, -29086, -29269, -29447, -29621, -29791, -29956, -30117,
|
||||
-30273, -30425, -30572, -30714, -30852, -30985, -31114, -31237,
|
||||
-31357, -31471, -31581, -31685, -31785, -31881, -31971, -32057,
|
||||
-32138, -32214, -32285, -32351, -32413, -32469, -32521, -32568,
|
||||
-32610, -32647, -32679, -32706, -32728, -32745, -32758, -32765,
|
||||
-32767, -32765, -32758, -32745, -32728, -32706, -32679, -32647,
|
||||
-32610, -32568, -32521, -32469, -32413, -32351, -32285, -32214,
|
||||
-32138, -32057, -31971, -31881, -31785, -31685, -31581, -31471,
|
||||
-31357, -31237, -31114, -30985, -30852, -30714, -30572, -30425,
|
||||
-30273, -30117, -29956, -29791, -29621, -29447, -29269, -29086,
|
||||
-28898, -28707, -28511, -28310, -28106, -27897, -27684, -27466,
|
||||
-27245, -27020, -26790, -26557, -26319, -26077, -25832, -25583,
|
||||
-25330, -25073, -24812, -24547, -24279, -24007, -23732, -23453,
|
||||
-23170, -22884, -22594, -22301, -22005, -21706, -21403, -21097,
|
||||
-20787, -20475, -20159, -19841, -19519, -19195, -18868, -18537,
|
||||
-18204, -17869, -17530, -17189, -16846, -16499, -16151, -15800,
|
||||
-15446, -15090, -14732, -14372, -14010, -13645, -13278, -12910,
|
||||
-12539, -12167, -11793, -11416, -11039, -10659, -10278, -9896,
|
||||
-9512, -9126, -8739, -8351, -7961, -7571, -7179, -6786,
|
||||
-6392, -5997, -5602, -5205, -4808, -4409, -4011, -3611,
|
||||
-3211, -2811, -2410, -2009, -1607, -1206, -804, -402,
|
||||
0, 402, 804, 1206, 1607, 2009, 2410, 2811,
|
||||
3211, 3611, 4011, 4409, 4808, 5205, 5602, 5997,
|
||||
6392, 6786, 7179, 7571, 7961, 8351, 8739, 9126,
|
||||
9512, 9896, 10278, 10659, 11039, 11416, 11793, 12167,
|
||||
12539, 12910, 13278, 13645, 14010, 14372, 14732, 15090,
|
||||
15446, 15800, 16151, 16499, 16846, 17189, 17530, 17869,
|
||||
18204, 18537, 18868, 19195, 19519, 19841, 20159, 20475,
|
||||
20787, 21097, 21403, 21706, 22005, 22301, 22594, 22884,
|
||||
23170, 23453, 23732, 24007, 24279, 24547, 24812, 25073,
|
||||
25330, 25583, 25832, 26077, 26319, 26557, 26790, 27020,
|
||||
27245, 27466, 27684, 27897, 28106, 28310, 28511, 28707,
|
||||
28898, 29086, 29269, 29447, 29621, 29791, 29956, 30117,
|
||||
30273, 30425, 30572, 30714, 30852, 30985, 31114, 31237,
|
||||
31357, 31471, 31581, 31685, 31785, 31881, 31971, 32057,
|
||||
32138, 32214, 32285, 32351, 32413, 32469, 32521, 32568,
|
||||
32610, 32647, 32679, 32706, 32728, 32745, 32758, 32765
|
||||
};
|
||||
|
||||
#endif
|
@@ -1,251 +0,0 @@
|
||||
#ifdef CX4_CPP
|
||||
|
||||
#include <math.h>
|
||||
#define Tan(a) (CosTable[a] ? ((((int32)SinTable[a]) << 16) / CosTable[a]) : 0x80000000)
|
||||
#define sar(b, n) ((b) >> (n))
|
||||
#ifdef PI
|
||||
#undef PI
|
||||
#endif
|
||||
#define PI 3.1415926535897932384626433832795
|
||||
|
||||
//Wireframe Helpers
|
||||
void Cx4::C4TransfWireFrame() {
|
||||
double c4x = (double)C4WFXVal;
|
||||
double c4y = (double)C4WFYVal;
|
||||
double c4z = (double)C4WFZVal - 0x95;
|
||||
double tanval, c4x2, c4y2, c4z2;
|
||||
|
||||
//Rotate X
|
||||
tanval = -(double)C4WFX2Val * PI * 2 / 128;
|
||||
c4y2 = c4y * ::cos(tanval) - c4z * ::sin(tanval);
|
||||
c4z2 = c4y * ::sin(tanval) + c4z * ::cos(tanval);
|
||||
|
||||
//Rotate Y
|
||||
tanval = -(double)C4WFY2Val * PI * 2 / 128;
|
||||
c4x2 = c4x * ::cos(tanval) + c4z2 * ::sin(tanval);
|
||||
c4z = c4x * -::sin(tanval) + c4z2 * ::cos(tanval);
|
||||
|
||||
//Rotate Z
|
||||
tanval = -(double)C4WFDist * PI * 2 / 128;
|
||||
c4x = c4x2 * ::cos(tanval) - c4y2 * ::sin(tanval);
|
||||
c4y = c4x2 * ::sin(tanval) + c4y2 * ::cos(tanval);
|
||||
|
||||
//Scale
|
||||
C4WFXVal = (int16)(c4x * C4WFScale / (0x90 * (c4z + 0x95)) * 0x95);
|
||||
C4WFYVal = (int16)(c4y * C4WFScale / (0x90 * (c4z + 0x95)) * 0x95);
|
||||
}
|
||||
|
||||
void Cx4::C4CalcWireFrame() {
|
||||
C4WFXVal = C4WFX2Val - C4WFXVal;
|
||||
C4WFYVal = C4WFY2Val - C4WFYVal;
|
||||
|
||||
if(abs(C4WFXVal) > abs(C4WFYVal)) {
|
||||
C4WFDist = abs(C4WFXVal) + 1;
|
||||
C4WFYVal = (256 * (long)C4WFYVal) / abs(C4WFXVal);
|
||||
C4WFXVal = (C4WFXVal < 0) ? -256 : 256;
|
||||
} else if(C4WFYVal != 0) {
|
||||
C4WFDist = abs(C4WFYVal) + 1;
|
||||
C4WFXVal = (256 * (long)C4WFXVal) / abs(C4WFYVal);
|
||||
C4WFYVal = (C4WFYVal < 0) ? -256 : 256;
|
||||
} else {
|
||||
C4WFDist = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void Cx4::C4TransfWireFrame2() {
|
||||
double c4x = (double)C4WFXVal;
|
||||
double c4y = (double)C4WFYVal;
|
||||
double c4z = (double)C4WFZVal;
|
||||
double tanval, c4x2, c4y2, c4z2;
|
||||
|
||||
//Rotate X
|
||||
tanval = -(double)C4WFX2Val * PI * 2 / 128;
|
||||
c4y2 = c4y * ::cos(tanval) - c4z * ::sin(tanval);
|
||||
c4z2 = c4y * ::sin(tanval) + c4z * ::cos(tanval);
|
||||
|
||||
//Rotate Y
|
||||
tanval = -(double)C4WFY2Val * PI * 2 / 128;
|
||||
c4x2 = c4x * ::cos(tanval) + c4z2 * ::sin(tanval);
|
||||
c4z = c4x * -::sin(tanval) + c4z2 * ::cos(tanval);
|
||||
|
||||
//Rotate Z
|
||||
tanval = -(double)C4WFDist * PI * 2 / 128;
|
||||
c4x = c4x2 * ::cos(tanval) - c4y2 * ::sin(tanval);
|
||||
c4y = c4x2 * ::sin(tanval) + c4y2 * ::cos(tanval);
|
||||
|
||||
//Scale
|
||||
C4WFXVal = (int16)(c4x * C4WFScale / 0x100);
|
||||
C4WFYVal = (int16)(c4y * C4WFScale / 0x100);
|
||||
}
|
||||
|
||||
void Cx4::C4DrawWireFrame() {
|
||||
uint32 line = readl(0x1f80);
|
||||
uint32 point1, point2;
|
||||
int16 X1, Y1, Z1;
|
||||
int16 X2, Y2, Z2;
|
||||
uint8 Color;
|
||||
|
||||
for(int32 i = ram[0x0295]; i > 0; i--, line += 5) {
|
||||
if(bus.read(line) == 0xff && bus.read(line + 1) == 0xff) {
|
||||
int32 tmp = line - 5;
|
||||
while(bus.read(tmp + 2) == 0xff && bus.read(tmp + 3) == 0xff && (tmp + 2) >= 0) { tmp -= 5; }
|
||||
point1 = (read(0x1f82) << 16) | (bus.read(tmp + 2) << 8) | bus.read(tmp + 3);
|
||||
} else {
|
||||
point1 = (read(0x1f82) << 16) | (bus.read(line) << 8) | bus.read(line + 1);
|
||||
}
|
||||
point2 = (read(0x1f82) << 16) | (bus.read(line + 2) << 8) | bus.read(line + 3);
|
||||
|
||||
X1=(bus.read(point1 + 0) << 8) | bus.read(point1 + 1);
|
||||
Y1=(bus.read(point1 + 2) << 8) | bus.read(point1 + 3);
|
||||
Z1=(bus.read(point1 + 4) << 8) | bus.read(point1 + 5);
|
||||
X2=(bus.read(point2 + 0) << 8) | bus.read(point2 + 1);
|
||||
Y2=(bus.read(point2 + 2) << 8) | bus.read(point2 + 3);
|
||||
Z2=(bus.read(point2 + 4) << 8) | bus.read(point2 + 5);
|
||||
Color = bus.read(line + 4);
|
||||
C4DrawLine(X1, Y1, Z1, X2, Y2, Z2, Color);
|
||||
}
|
||||
}
|
||||
|
||||
void Cx4::C4DrawLine(int32 X1, int32 Y1, int16 Z1, int32 X2, int32 Y2, int16 Z2, uint8 Color) {
|
||||
//Transform coordinates
|
||||
C4WFXVal = (int16)X1;
|
||||
C4WFYVal = (int16)Y1;
|
||||
C4WFZVal = Z1;
|
||||
C4WFScale = read(0x1f90);
|
||||
C4WFX2Val = read(0x1f86);
|
||||
C4WFY2Val = read(0x1f87);
|
||||
C4WFDist = read(0x1f88);
|
||||
C4TransfWireFrame2();
|
||||
X1 = (C4WFXVal + 48) << 8;
|
||||
Y1 = (C4WFYVal + 48) << 8;
|
||||
|
||||
C4WFXVal = (int16)X2;
|
||||
C4WFYVal = (int16)Y2;
|
||||
C4WFZVal = Z2;
|
||||
C4TransfWireFrame2();
|
||||
X2 = (C4WFXVal + 48) << 8;
|
||||
Y2 = (C4WFYVal + 48) << 8;
|
||||
|
||||
//Get line info
|
||||
C4WFXVal = (int16)(X1 >> 8);
|
||||
C4WFYVal = (int16)(Y1 >> 8);
|
||||
C4WFX2Val = (int16)(X2 >> 8);
|
||||
C4WFY2Val = (int16)(Y2 >> 8);
|
||||
C4CalcWireFrame();
|
||||
X2 = (int16)C4WFXVal;
|
||||
Y2 = (int16)C4WFYVal;
|
||||
|
||||
//Render line
|
||||
for(int32 i = C4WFDist ? C4WFDist : 1; i > 0; i--) {
|
||||
if(X1 > 0xff && Y1 > 0xff && X1 < 0x6000 && Y1 < 0x6000) {
|
||||
uint16 addr = (((Y1 >> 8) >> 3) << 8) - (((Y1 >> 8) >> 3) << 6) + (((X1 >> 8) >> 3) << 4) + ((Y1 >> 8) & 7) * 2;
|
||||
uint8 bit = 0x80 >> ((X1 >> 8) & 7);
|
||||
ram[addr + 0x300] &= ~bit;
|
||||
ram[addr + 0x301] &= ~bit;
|
||||
if(Color & 1) ram[addr + 0x300] |= bit;
|
||||
if(Color & 2) ram[addr + 0x301] |= bit;
|
||||
}
|
||||
X1 += X2;
|
||||
Y1 += Y2;
|
||||
}
|
||||
}
|
||||
|
||||
void Cx4::C4DoScaleRotate(int row_padding) {
|
||||
int16 A, B, C, D;
|
||||
|
||||
//Calculate matrix
|
||||
int32 XScale = readw(0x1f8f);
|
||||
int32 YScale = readw(0x1f92);
|
||||
|
||||
if(XScale & 0x8000)XScale = 0x7fff;
|
||||
if(YScale & 0x8000)YScale = 0x7fff;
|
||||
|
||||
if(readw(0x1f80) == 0) { //no rotation
|
||||
A = (int16)XScale;
|
||||
B = 0;
|
||||
C = 0;
|
||||
D = (int16)YScale;
|
||||
} else if(readw(0x1f80) == 128) { //90 degree rotation
|
||||
A = 0;
|
||||
B = (int16)(-YScale);
|
||||
C = (int16)XScale;
|
||||
D = 0;
|
||||
} else if(readw(0x1f80) == 256) { //180 degree rotation
|
||||
A = (int16)(-XScale);
|
||||
B = 0;
|
||||
C = 0;
|
||||
D = (int16)(-YScale);
|
||||
} else if(readw(0x1f80) == 384) { //270 degree rotation
|
||||
A = 0;
|
||||
B = (int16)YScale;
|
||||
C = (int16)(-XScale);
|
||||
D = 0;
|
||||
} else {
|
||||
A = (int16) sar(CosTable[readw(0x1f80) & 0x1ff] * XScale, 15);
|
||||
B = (int16)(-sar(SinTable[readw(0x1f80) & 0x1ff] * YScale, 15));
|
||||
C = (int16) sar(SinTable[readw(0x1f80) & 0x1ff] * XScale, 15);
|
||||
D = (int16) sar(CosTable[readw(0x1f80) & 0x1ff] * YScale, 15);
|
||||
}
|
||||
|
||||
//Calculate Pixel Resolution
|
||||
uint8 w = read(0x1f89) & ~7;
|
||||
uint8 h = read(0x1f8c) & ~7;
|
||||
|
||||
//Clear the output RAM
|
||||
memset(ram, 0, (w + row_padding / 4) * h / 2);
|
||||
|
||||
int32 Cx = (int16)readw(0x1f83);
|
||||
int32 Cy = (int16)readw(0x1f86);
|
||||
|
||||
//Calculate start position (i.e. (Ox, Oy) = (0, 0))
|
||||
//The low 12 bits are fractional, so (Cx<<12) gives us the Cx we want in
|
||||
//the function. We do Cx*A etc normally because the matrix parameters
|
||||
//already have the fractional parts.
|
||||
int32 LineX = (Cx << 12) - Cx * A - Cx * B;
|
||||
int32 LineY = (Cy << 12) - Cy * C - Cy * D;
|
||||
|
||||
//Start loop
|
||||
uint32 X, Y;
|
||||
uint8 byte;
|
||||
int32 outidx = 0;
|
||||
uint8 bit = 0x80;
|
||||
|
||||
for(int32 y = 0; y < h; y++) {
|
||||
X = LineX;
|
||||
Y = LineY;
|
||||
for(int32 x = 0; x < w; x++) {
|
||||
if((X >> 12) >= w || (Y >> 12) >= h) {
|
||||
byte = 0;
|
||||
} else {
|
||||
uint32 addr = (Y >> 12) * w + (X >> 12);
|
||||
byte = read(0x600 + (addr >> 1));
|
||||
if(addr & 1) { byte >>= 4; }
|
||||
}
|
||||
|
||||
//De-bitplanify
|
||||
if(byte & 1) ram[outidx ] |= bit;
|
||||
if(byte & 2) ram[outidx + 1] |= bit;
|
||||
if(byte & 4) ram[outidx + 16] |= bit;
|
||||
if(byte & 8) ram[outidx + 17] |= bit;
|
||||
|
||||
bit >>= 1;
|
||||
if(!bit) {
|
||||
bit = 0x80;
|
||||
outidx += 32;
|
||||
}
|
||||
|
||||
X += A; //Add 1 to output x => add an A and a C
|
||||
Y += C;
|
||||
}
|
||||
outidx += 2 + row_padding;
|
||||
if(outidx & 0x10) {
|
||||
outidx &= ~0x10;
|
||||
} else {
|
||||
outidx -= w * 4 + row_padding;
|
||||
}
|
||||
LineX += B; //Add 1 to output y => add a B and a D
|
||||
LineY += D;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
@@ -1,228 +0,0 @@
|
||||
#ifdef CX4_CPP
|
||||
|
||||
//Build OAM
|
||||
void Cx4::op00_00() {
|
||||
uint32 oamptr = ram[0x626] << 2;
|
||||
for(int32 i = 0x1fd; i > oamptr && i >= 0; i -= 4) {
|
||||
//clear oam-to-be
|
||||
if(i >= 0) ram[i] = 0xe0;
|
||||
}
|
||||
|
||||
uint16 globalx, globaly;
|
||||
uint32 oamptr2;
|
||||
int16 sprx, spry;
|
||||
uint8 sprname, sprattr;
|
||||
uint8 sprcount;
|
||||
|
||||
globalx = readw(0x621);
|
||||
globaly = readw(0x623);
|
||||
oamptr2 = 0x200 + (ram[0x626] >> 2);
|
||||
|
||||
if(!ram[0x620]) return;
|
||||
|
||||
sprcount = 128 - ram[0x626];
|
||||
uint8 offset = (ram[0x626] & 3) * 2;
|
||||
uint32 srcptr = 0x220;
|
||||
|
||||
for(int i = ram[0x620]; i > 0 && sprcount > 0; i--, srcptr += 16) {
|
||||
sprx = readw(srcptr) - globalx;
|
||||
spry = readw(srcptr + 2) - globaly;
|
||||
sprname = ram[srcptr + 5];
|
||||
sprattr = ram[srcptr + 4] | ram[srcptr + 6];
|
||||
|
||||
uint32 spraddr = readl(srcptr + 7);
|
||||
if(bus.read(spraddr)) {
|
||||
int16 x, y;
|
||||
for(int sprcnt = bus.read(spraddr++); sprcnt > 0 && sprcount > 0; sprcnt--, spraddr += 4) {
|
||||
x = (int8)bus.read(spraddr + 1);
|
||||
if(sprattr & 0x40) {
|
||||
x = -x - ((bus.read(spraddr) & 0x20) ? 16 : 8);
|
||||
}
|
||||
x += sprx;
|
||||
if(x >= -16 && x <= 272) {
|
||||
y = (int8)bus.read(spraddr + 2);
|
||||
if(sprattr & 0x80) {
|
||||
y = -y - ((bus.read(spraddr) & 0x20) ? 16 : 8);
|
||||
}
|
||||
y += spry;
|
||||
if(y >= -16 && y <= 224) {
|
||||
ram[oamptr ] = (uint8)x;
|
||||
ram[oamptr + 1] = (uint8)y;
|
||||
ram[oamptr + 2] = sprname + bus.read(spraddr + 3);
|
||||
ram[oamptr + 3] = sprattr ^ (bus.read(spraddr) & 0xc0);
|
||||
ram[oamptr2] &= ~(3 << offset);
|
||||
if(x & 0x100) ram[oamptr2] |= 1 << offset;
|
||||
if(bus.read(spraddr) & 0x20) ram[oamptr2] |= 2 << offset;
|
||||
oamptr += 4;
|
||||
sprcount--;
|
||||
offset = (offset + 2) & 6;
|
||||
if(!offset)oamptr2++;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if(sprcount > 0) {
|
||||
ram[oamptr ] = (uint8)sprx;
|
||||
ram[oamptr + 1] = (uint8)spry;
|
||||
ram[oamptr + 2] = sprname;
|
||||
ram[oamptr + 3] = sprattr;
|
||||
ram[oamptr2] &= ~(3 << offset);
|
||||
if(sprx & 0x100) ram[oamptr2] |= 3 << offset;
|
||||
else ram[oamptr2] |= 2 << offset;
|
||||
oamptr += 4;
|
||||
sprcount--;
|
||||
offset = (offset + 2) & 6;
|
||||
if(!offset) oamptr2++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Scale and Rotate
|
||||
void Cx4::op00_03() {
|
||||
C4DoScaleRotate(0);
|
||||
}
|
||||
|
||||
//Transform Lines
|
||||
void Cx4::op00_05() {
|
||||
C4WFX2Val = read(0x1f83);
|
||||
C4WFY2Val = read(0x1f86);
|
||||
C4WFDist = read(0x1f89);
|
||||
C4WFScale = read(0x1f8c);
|
||||
|
||||
//Transform Vertices
|
||||
uint32 ptr = 0;
|
||||
for(int32 i = readw(0x1f80); i > 0; i--, ptr += 0x10) {
|
||||
C4WFXVal = readw(ptr + 1);
|
||||
C4WFYVal = readw(ptr + 5);
|
||||
C4WFZVal = readw(ptr + 9);
|
||||
C4TransfWireFrame();
|
||||
|
||||
//Displace
|
||||
writew(ptr + 1, C4WFXVal + 0x80);
|
||||
writew(ptr + 5, C4WFYVal + 0x50);
|
||||
}
|
||||
|
||||
writew(0x600, 23);
|
||||
writew(0x602, 0x60);
|
||||
writew(0x605, 0x40);
|
||||
writew(0x600 + 8, 23);
|
||||
writew(0x602 + 8, 0x60);
|
||||
writew(0x605 + 8, 0x40);
|
||||
|
||||
ptr = 0xb02;
|
||||
uint32 ptr2 = 0;
|
||||
|
||||
for(int32 i = readw(0xb00); i > 0; i--, ptr += 2, ptr2 += 8) {
|
||||
C4WFXVal = readw((read(ptr + 0) << 4) + 1);
|
||||
C4WFYVal = readw((read(ptr + 0) << 4) + 5);
|
||||
C4WFX2Val = readw((read(ptr + 1) << 4) + 1);
|
||||
C4WFY2Val = readw((read(ptr + 1) << 4) + 5);
|
||||
C4CalcWireFrame();
|
||||
writew(ptr2 + 0x600, C4WFDist ? C4WFDist : 1);
|
||||
writew(ptr2 + 0x602, C4WFXVal);
|
||||
writew(ptr2 + 0x605, C4WFYVal);
|
||||
}
|
||||
}
|
||||
|
||||
//Scale and Rotate
|
||||
void Cx4::op00_07() {
|
||||
C4DoScaleRotate(64);
|
||||
}
|
||||
|
||||
//Draw Wireframe
|
||||
void Cx4::op00_08() {
|
||||
C4DrawWireFrame();
|
||||
}
|
||||
|
||||
//Disintegrate
|
||||
void Cx4::op00_0b() {
|
||||
uint8 width, height;
|
||||
uint32 startx, starty;
|
||||
uint32 srcptr;
|
||||
uint32 x, y;
|
||||
int32 scalex, scaley;
|
||||
int32 cx, cy;
|
||||
int32 i, j;
|
||||
|
||||
width = read(0x1f89);
|
||||
height = read(0x1f8c);
|
||||
cx = readw(0x1f80);
|
||||
cy = readw(0x1f83);
|
||||
|
||||
scalex = (int16)readw(0x1f86);
|
||||
scaley = (int16)readw(0x1f8f);
|
||||
startx = -cx * scalex + (cx << 8);
|
||||
starty = -cy * scaley + (cy << 8);
|
||||
srcptr = 0x600;
|
||||
|
||||
for(i = 0; i < (width * height) >> 1; i++) {
|
||||
write(i, 0);
|
||||
}
|
||||
|
||||
for(y = starty, i = 0;i < height; i++, y += scaley) {
|
||||
for(x = startx, j = 0;j < width; j++, x += scalex) {
|
||||
if((x >> 8) < width && (y >> 8) < height && (y >> 8) * width + (x >> 8) < 0x2000) {
|
||||
uint8 pixel = (j & 1) ? (ram[srcptr] >> 4) : (ram[srcptr]);
|
||||
int32 index = (y >> 11) * width * 4 + (x >> 11) * 32 + ((y >> 8) & 7) * 2;
|
||||
uint8 mask = 0x80 >> ((x >> 8) & 7);
|
||||
|
||||
if(pixel & 1) ram[index ] |= mask;
|
||||
if(pixel & 2) ram[index + 1] |= mask;
|
||||
if(pixel & 4) ram[index + 16] |= mask;
|
||||
if(pixel & 8) ram[index + 17] |= mask;
|
||||
}
|
||||
if(j & 1) srcptr++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Bitplane Wave
|
||||
void Cx4::op00_0c() {
|
||||
uint32 destptr = 0;
|
||||
uint32 waveptr = read(0x1f83);
|
||||
uint16 mask1 = 0xc0c0;
|
||||
uint16 mask2 = 0x3f3f;
|
||||
|
||||
for(int j = 0; j < 0x10; j++) {
|
||||
do {
|
||||
int16 height = -((int8)read(waveptr + 0xb00)) - 16;
|
||||
for(int i = 0; i < 40; i++) {
|
||||
uint16 temp = readw(destptr + wave_data[i]) & mask2;
|
||||
if(height >= 0) {
|
||||
if(height < 8) {
|
||||
temp |= mask1 & readw(0xa00 + height * 2);
|
||||
} else {
|
||||
temp |= mask1 & 0xff00;
|
||||
}
|
||||
}
|
||||
writew(destptr + wave_data[i], temp);
|
||||
height++;
|
||||
}
|
||||
waveptr = (waveptr + 1) & 0x7f;
|
||||
mask1 = (mask1 >> 2) | (mask1 << 6);
|
||||
mask2 = (mask2 >> 2) | (mask2 << 6);
|
||||
} while(mask1 != 0xc0c0);
|
||||
destptr += 16;
|
||||
|
||||
do {
|
||||
int16 height = -((int8)read(waveptr + 0xb00)) - 16;
|
||||
for(int i = 0; i < 40; i++) {
|
||||
uint16 temp = readw(destptr + wave_data[i]) & mask2;
|
||||
if(height >= 0) {
|
||||
if(height < 8) {
|
||||
temp |= mask1 & readw(0xa10 + height * 2);
|
||||
} else {
|
||||
temp |= mask1 & 0xff00;
|
||||
}
|
||||
}
|
||||
writew(destptr + wave_data[i], temp);
|
||||
height++;
|
||||
}
|
||||
waveptr = (waveptr + 1) & 0x7f;
|
||||
mask1 = (mask1 >> 2) | (mask1 << 6);
|
||||
mask2 = (mask2 >> 2) | (mask2 << 6);
|
||||
} while(mask1 != 0xc0c0);
|
||||
destptr += 16;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
@@ -1,228 +0,0 @@
|
||||
#ifdef CX4_CPP
|
||||
|
||||
//Sprite Functions
|
||||
void Cx4::op00() {
|
||||
switch(reg[0x4d]) {
|
||||
case 0x00: op00_00(); break;
|
||||
case 0x03: op00_03(); break;
|
||||
case 0x05: op00_05(); break;
|
||||
case 0x07: op00_07(); break;
|
||||
case 0x08: op00_08(); break;
|
||||
case 0x0b: op00_0b(); break;
|
||||
case 0x0c: op00_0c(); break;
|
||||
}
|
||||
}
|
||||
|
||||
//Draw Wireframe
|
||||
void Cx4::op01() {
|
||||
memset(ram + 0x300, 0, 2304);
|
||||
C4DrawWireFrame();
|
||||
}
|
||||
|
||||
//Propulsion
|
||||
void Cx4::op05() {
|
||||
int32 temp = 0x10000;
|
||||
if(readw(0x1f83)) {
|
||||
temp = sar((temp / readw(0x1f83)) * readw(0x1f81), 8);
|
||||
}
|
||||
writew(0x1f80, temp);
|
||||
}
|
||||
|
||||
//Set Vector length
|
||||
void Cx4::op0d() {
|
||||
C41FXVal = readw(0x1f80);
|
||||
C41FYVal = readw(0x1f83);
|
||||
C41FDistVal = readw(0x1f86);
|
||||
double tanval = sqrt(((double)C41FYVal) * ((double)C41FYVal) + ((double)C41FXVal) * ((double)C41FXVal));
|
||||
tanval = (double)C41FDistVal / tanval;
|
||||
C41FYVal = (int16)(((double)C41FYVal * tanval) * 0.99);
|
||||
C41FXVal = (int16)(((double)C41FXVal * tanval) * 0.98);
|
||||
writew(0x1f89, C41FXVal);
|
||||
writew(0x1f8c, C41FYVal);
|
||||
}
|
||||
|
||||
//Triangle
|
||||
void Cx4::op10() {
|
||||
r0 = ldr(0);
|
||||
r1 = ldr(1);
|
||||
|
||||
r4 = r0 & 0x1ff;
|
||||
if(r1 & 0x8000)r1 |= ~0x7fff;
|
||||
else r1 &= 0x7fff;
|
||||
|
||||
mul(cos(r4), r1, r5, r2);
|
||||
r5 = (r5 >> 16) & 0xff;
|
||||
r2 = (r2 << 8) + r5;
|
||||
|
||||
mul(sin(r4), r1, r5, r3);
|
||||
r5 = (r5 >> 16) & 0xff;
|
||||
r3 = (r3 << 8) + r5;
|
||||
|
||||
str(0, r0);
|
||||
str(1, r1);
|
||||
str(2, r2);
|
||||
str(3, r3);
|
||||
str(4, r4);
|
||||
str(5, r5);
|
||||
}
|
||||
|
||||
//Triangle
|
||||
void Cx4::op13() {
|
||||
r0 = ldr(0);
|
||||
r1 = ldr(1);
|
||||
|
||||
r4 = r0 & 0x1ff;
|
||||
|
||||
mul(cos(r4), r1, r5, r2);
|
||||
r5 = (r5 >> 8) & 0xffff;
|
||||
r2 = (r2 << 16) + r5;
|
||||
|
||||
mul(sin(r4), r1, r5, r3);
|
||||
r5 = (r5 >> 8) & 0xffff;
|
||||
r3 = (r3 << 16) + r5;
|
||||
|
||||
str(0, r0);
|
||||
str(1, r1);
|
||||
str(2, r2);
|
||||
str(3, r3);
|
||||
str(4, r4);
|
||||
str(5, r5);
|
||||
}
|
||||
|
||||
//Pythagorean
|
||||
void Cx4::op15() {
|
||||
C41FXVal = readw(0x1f80);
|
||||
C41FYVal = readw(0x1f83);
|
||||
C41FDist = (int16)sqrt((double)C41FXVal * (double)C41FXVal + (double)C41FYVal * (double)C41FYVal);
|
||||
writew(0x1f80, C41FDist);
|
||||
}
|
||||
|
||||
//Calculate distance
|
||||
void Cx4::op1f() {
|
||||
C41FXVal = readw(0x1f80);
|
||||
C41FYVal = readw(0x1f83);
|
||||
if(!C41FXVal) {
|
||||
C41FAngleRes = (C41FYVal > 0) ? 0x080 : 0x180;
|
||||
} else {
|
||||
double tanval = ((double)C41FYVal) / ((double)C41FXVal);
|
||||
C41FAngleRes = (short)(atan(tanval) / (PI * 2) * 512);
|
||||
C41FAngleRes = C41FAngleRes;
|
||||
if(C41FXVal < 0) {
|
||||
C41FAngleRes += 0x100;
|
||||
}
|
||||
C41FAngleRes &= 0x1ff;
|
||||
}
|
||||
writew(0x1f86, C41FAngleRes);
|
||||
}
|
||||
|
||||
//Trapezoid
|
||||
void Cx4::op22() {
|
||||
int16 angle1 = readw(0x1f8c) & 0x1ff;
|
||||
int16 angle2 = readw(0x1f8f) & 0x1ff;
|
||||
int32 tan1 = Tan(angle1);
|
||||
int32 tan2 = Tan(angle2);
|
||||
int16 y = readw(0x1f83) - readw(0x1f89);
|
||||
int16 left, right;
|
||||
|
||||
for(int32 j = 0; j < 225; j++, y++) {
|
||||
if(y >= 0) {
|
||||
left = sar((int32)tan1 * y, 16) - readw(0x1f80) + readw(0x1f86);
|
||||
right = sar((int32)tan2 * y, 16) - readw(0x1f80) + readw(0x1f86) + readw(0x1f93);
|
||||
|
||||
if(left < 0 && right < 0) {
|
||||
left = 1;
|
||||
right = 0;
|
||||
} else if(left < 0) {
|
||||
left = 0;
|
||||
} else if(right < 0) {
|
||||
right = 0;
|
||||
}
|
||||
|
||||
if(left > 255 && right > 255) {
|
||||
left = 255;
|
||||
right = 254;
|
||||
} else if(left > 255) {
|
||||
left = 255;
|
||||
} else if(right > 255) {
|
||||
right = 255;
|
||||
}
|
||||
} else {
|
||||
left = 1;
|
||||
right = 0;
|
||||
}
|
||||
ram[j + 0x800] = (uint8)left;
|
||||
ram[j + 0x900] = (uint8)right;
|
||||
}
|
||||
}
|
||||
|
||||
//Multiply
|
||||
void Cx4::op25() {
|
||||
r0 = ldr(0);
|
||||
r1 = ldr(1);
|
||||
mul(r0, r1, r0, r1);
|
||||
str(0, r0);
|
||||
str(1, r1);
|
||||
}
|
||||
|
||||
//Transform Coords
|
||||
void Cx4::op2d() {
|
||||
C4WFXVal = readw(0x1f81);
|
||||
C4WFYVal = readw(0x1f84);
|
||||
C4WFZVal = readw(0x1f87);
|
||||
C4WFX2Val = read (0x1f89);
|
||||
C4WFY2Val = read (0x1f8a);
|
||||
C4WFDist = read (0x1f8b);
|
||||
C4WFScale = readw(0x1f90);
|
||||
C4TransfWireFrame2();
|
||||
writew(0x1f80, C4WFXVal);
|
||||
writew(0x1f83, C4WFYVal);
|
||||
}
|
||||
|
||||
//Sum
|
||||
void Cx4::op40() {
|
||||
r0 = 0;
|
||||
for(uint32 i=0;i<0x800;i++) {
|
||||
r0 += ram[i];
|
||||
}
|
||||
str(0, r0);
|
||||
}
|
||||
|
||||
//Square
|
||||
void Cx4::op54() {
|
||||
r0 = ldr(0);
|
||||
mul(r0, r0, r1, r2);
|
||||
str(1, r1);
|
||||
str(2, r2);
|
||||
}
|
||||
|
||||
//Immediate Register
|
||||
void Cx4::op5c() {
|
||||
str(0, 0x000000);
|
||||
immediate_reg(0);
|
||||
}
|
||||
|
||||
//Immediate Register (Multiple)
|
||||
void Cx4::op5e() { immediate_reg( 0); }
|
||||
void Cx4::op60() { immediate_reg( 3); }
|
||||
void Cx4::op62() { immediate_reg( 6); }
|
||||
void Cx4::op64() { immediate_reg( 9); }
|
||||
void Cx4::op66() { immediate_reg(12); }
|
||||
void Cx4::op68() { immediate_reg(15); }
|
||||
void Cx4::op6a() { immediate_reg(18); }
|
||||
void Cx4::op6c() { immediate_reg(21); }
|
||||
void Cx4::op6e() { immediate_reg(24); }
|
||||
void Cx4::op70() { immediate_reg(27); }
|
||||
void Cx4::op72() { immediate_reg(30); }
|
||||
void Cx4::op74() { immediate_reg(33); }
|
||||
void Cx4::op76() { immediate_reg(36); }
|
||||
void Cx4::op78() { immediate_reg(39); }
|
||||
void Cx4::op7a() { immediate_reg(42); }
|
||||
void Cx4::op7c() { immediate_reg(45); }
|
||||
|
||||
//Immediate ROM
|
||||
void Cx4::op89() {
|
||||
str(0, 0x054336);
|
||||
str(1, 0xffffff);
|
||||
}
|
||||
|
||||
#endif
|
@@ -1,39 +0,0 @@
|
||||
#ifdef CX4_CPP
|
||||
|
||||
void Cx4::serialize(serializer &s) {
|
||||
s.array(ram);
|
||||
s.array(reg);
|
||||
|
||||
s.integer(r0);
|
||||
s.integer(r1);
|
||||
s.integer(r2);
|
||||
s.integer(r3);
|
||||
s.integer(r4);
|
||||
s.integer(r5);
|
||||
s.integer(r6);
|
||||
s.integer(r7);
|
||||
s.integer(r8);
|
||||
s.integer(r9);
|
||||
s.integer(r10);
|
||||
s.integer(r11);
|
||||
s.integer(r12);
|
||||
s.integer(r13);
|
||||
s.integer(r14);
|
||||
s.integer(r15);
|
||||
|
||||
s.integer(C4WFXVal);
|
||||
s.integer(C4WFYVal);
|
||||
s.integer(C4WFZVal);
|
||||
s.integer(C4WFX2Val);
|
||||
s.integer(C4WFY2Val);
|
||||
s.integer(C4WFDist);
|
||||
s.integer(C4WFScale);
|
||||
|
||||
s.integer(C41FXVal);
|
||||
s.integer(C41FYVal);
|
||||
s.integer(C41FAngleRes);
|
||||
s.integer(C41FDist);
|
||||
s.integer(C41FDistVal);
|
||||
}
|
||||
|
||||
#endif
|
79
bsnes/snes/chip/hitachidsp/hitachidsp.cpp
Executable file
79
bsnes/snes/chip/hitachidsp/hitachidsp.cpp
Executable file
@@ -0,0 +1,79 @@
|
||||
#include <snes/snes.hpp>
|
||||
|
||||
#define HITACHIDSP_CPP
|
||||
namespace SNES {
|
||||
|
||||
#include "memory.cpp"
|
||||
#include "opcodes.cpp"
|
||||
#include "registers.cpp"
|
||||
#include "serialization.cpp"
|
||||
HitachiDSP hitachidsp;
|
||||
|
||||
void HitachiDSP::Enter() { hitachidsp.enter(); }
|
||||
|
||||
void HitachiDSP::enter() {
|
||||
while(true) {
|
||||
if(scheduler.sync == Scheduler::SynchronizeMode::All) {
|
||||
scheduler.exit(Scheduler::ExitReason::SynchronizeEvent);
|
||||
}
|
||||
|
||||
switch(state) {
|
||||
case State::Idle:
|
||||
step(1);
|
||||
break;
|
||||
case State::DMA:
|
||||
for(unsigned n = 0; n < regs.dma_length; n++) {
|
||||
bus.write(regs.dma_target + n, bus.read(regs.dma_source + n));
|
||||
step(2);
|
||||
}
|
||||
state = State::Idle;
|
||||
break;
|
||||
case State::Execute:
|
||||
unsigned offset = regs.program_offset + regs.pc * 2;
|
||||
opcode = bus_read(offset + 0) << 0;
|
||||
opcode |= bus_read(offset + 1) << 8;
|
||||
regs.pc = (regs.pc & 0xffff00) | ((regs.pc + 1) & 0x0000ff);
|
||||
exec();
|
||||
step(1);
|
||||
break;
|
||||
}
|
||||
|
||||
synchronize_cpu();
|
||||
}
|
||||
}
|
||||
|
||||
void HitachiDSP::init() {
|
||||
}
|
||||
|
||||
void HitachiDSP::load() {
|
||||
}
|
||||
|
||||
void HitachiDSP::unload() {
|
||||
}
|
||||
|
||||
void HitachiDSP::power() {
|
||||
reset();
|
||||
}
|
||||
|
||||
void HitachiDSP::reset() {
|
||||
create(HitachiDSP::Enter, frequency);
|
||||
state = State::Idle;
|
||||
|
||||
regs.n = 0;
|
||||
regs.z = 0;
|
||||
regs.c = 0;
|
||||
|
||||
regs.dma_source = 0x000000;
|
||||
regs.dma_length = 0x0000;
|
||||
regs.dma_target = 0x000000;
|
||||
regs.r1f48 = 0x00;
|
||||
regs.program_offset = 0x000000;
|
||||
regs.r1f4c = 0x00;
|
||||
regs.page_number = 0x0000;
|
||||
regs.program_counter = 0x00;
|
||||
regs.r1f50 = 0x33;
|
||||
regs.r1f51 = 0x00;
|
||||
regs.r1f52 = 0x01;
|
||||
}
|
||||
|
||||
}
|
48
bsnes/snes/chip/hitachidsp/hitachidsp.hpp
Executable file
48
bsnes/snes/chip/hitachidsp/hitachidsp.hpp
Executable file
@@ -0,0 +1,48 @@
|
||||
//Hitachi HG51B169
|
||||
|
||||
class HitachiDSP : public Coprocessor {
|
||||
public:
|
||||
unsigned frequency;
|
||||
//uint16 programROM[2][256];
|
||||
uint24 dataROM[1024];
|
||||
uint8 dataRAM[3072];
|
||||
uint24 stack[8];
|
||||
uint16 opcode;
|
||||
enum class State : unsigned { Idle, DMA, Execute } state;
|
||||
#include "registers.hpp"
|
||||
|
||||
static void Enter();
|
||||
void enter();
|
||||
|
||||
void init();
|
||||
void load();
|
||||
void unload();
|
||||
void power();
|
||||
void reset();
|
||||
|
||||
//memory.cpp
|
||||
uint8 bus_read(unsigned addr);
|
||||
void bus_write(unsigned addr, uint8 data);
|
||||
|
||||
uint8 rom_read(unsigned addr);
|
||||
void rom_write(unsigned addr, uint8 data);
|
||||
|
||||
uint8 dsp_read(unsigned addr);
|
||||
void dsp_write(unsigned addr, uint8 data);
|
||||
|
||||
//opcodes.cpp
|
||||
void push();
|
||||
void pull();
|
||||
unsigned sa();
|
||||
unsigned ri();
|
||||
unsigned np();
|
||||
void exec();
|
||||
|
||||
//registers.cpp
|
||||
unsigned reg_read(unsigned n) const;
|
||||
void reg_write(unsigned n, unsigned data);
|
||||
|
||||
void serialize(serializer&);
|
||||
};
|
||||
|
||||
extern HitachiDSP hitachidsp;
|
133
bsnes/snes/chip/hitachidsp/memory.cpp
Executable file
133
bsnes/snes/chip/hitachidsp/memory.cpp
Executable file
@@ -0,0 +1,133 @@
|
||||
#ifdef HITACHIDSP_CPP
|
||||
|
||||
uint8 HitachiDSP::bus_read(unsigned addr) {
|
||||
if((addr & 0x408000) == 0x008000) return bus.read(addr);
|
||||
return 0x00;
|
||||
}
|
||||
|
||||
void HitachiDSP::bus_write(unsigned addr, uint8 data) {
|
||||
if((addr & 0x40e000) == 0x006000) return bus.write(addr, data);
|
||||
}
|
||||
|
||||
uint8 HitachiDSP::rom_read(unsigned addr) {
|
||||
if(co_active() == cpu.thread) {
|
||||
if(state == State::Idle) return cartridge.rom.read(addr);
|
||||
if((addr & 0x40ffe0) == 0x00ffe0) return regs.vector[addr & 0x1f];
|
||||
return cpu.regs.mdr;
|
||||
}
|
||||
if(co_active() == hitachidsp.thread) {
|
||||
return cartridge.rom.read(addr);
|
||||
}
|
||||
return cpu.regs.mdr;
|
||||
}
|
||||
|
||||
void HitachiDSP::rom_write(unsigned addr, uint8 data) {
|
||||
}
|
||||
|
||||
uint8 HitachiDSP::dsp_read(unsigned addr) {
|
||||
addr &= 0x1fff;
|
||||
|
||||
//Data RAM
|
||||
if((addr >= 0x0000 && addr <= 0x0bff) || (addr >= 0x1000 && addr <= 0x1bff)) {
|
||||
return dataRAM[addr & 0x0fff];
|
||||
}
|
||||
|
||||
//MMIO
|
||||
switch(addr) {
|
||||
case 0x1f40: return regs.dma_source >> 0;
|
||||
case 0x1f41: return regs.dma_source >> 8;
|
||||
case 0x1f42: return regs.dma_source >> 16;
|
||||
case 0x1f43: return regs.dma_length >> 0;
|
||||
case 0x1f44: return regs.dma_length >> 8;
|
||||
case 0x1f45: return regs.dma_target >> 0;
|
||||
case 0x1f46: return regs.dma_target >> 8;
|
||||
case 0x1f47: return regs.dma_target >> 16;
|
||||
case 0x1f48: return regs.r1f48;
|
||||
case 0x1f49: return regs.program_offset >> 0;
|
||||
case 0x1f4a: return regs.program_offset >> 8;
|
||||
case 0x1f4b: return regs.program_offset >> 16;
|
||||
case 0x1f4c: return regs.r1f4c;
|
||||
case 0x1f4d: return regs.page_number >> 0;
|
||||
case 0x1f4e: return regs.page_number >> 8;
|
||||
case 0x1f4f: return regs.program_counter;
|
||||
case 0x1f50: return regs.r1f50;
|
||||
case 0x1f51: return regs.r1f51;
|
||||
case 0x1f52: return regs.r1f52;
|
||||
case 0x1f53: case 0x1f54: case 0x1f55: case 0x1f56:
|
||||
case 0x1f57: case 0x1f58: case 0x1f59: case 0x1f5a:
|
||||
case 0x1f5b: case 0x1f5c: case 0x1f5d: case 0x1f5e:
|
||||
case 0x1f5f: return ((state != State::Idle) << 6) | ((state == State::Idle) << 1);
|
||||
}
|
||||
|
||||
//Vector
|
||||
if(addr >= 0x1f60 && addr <= 0x1f7f) {
|
||||
return regs.vector[addr & 0x1f];
|
||||
}
|
||||
|
||||
//GPRs
|
||||
if((addr >= 0x1f80 && addr <= 0x1faf) || (addr >= 0x1fc0 && addr <= 0x1fef)) {
|
||||
unsigned index = (addr & 0x3f) / 3; //0..15
|
||||
unsigned shift = ((addr & 0x3f) % 3) * 8; //0, 8, 16
|
||||
return regs.gpr[index] >> shift;
|
||||
}
|
||||
|
||||
return 0x00;
|
||||
}
|
||||
|
||||
void HitachiDSP::dsp_write(unsigned addr, uint8 data) {
|
||||
addr &= 0x1fff;
|
||||
|
||||
//Data RAM
|
||||
if((addr >= 0x0000 && addr <= 0x0bff) || (addr >= 0x1000 && addr <= 0x1bff)) {
|
||||
dataRAM[addr & 0x0fff] = data;
|
||||
return;
|
||||
}
|
||||
|
||||
//MMIO
|
||||
switch(addr) {
|
||||
case 0x1f40: regs.dma_source = (regs.dma_source & 0xffff00) | (data << 0); return;
|
||||
case 0x1f41: regs.dma_source = (regs.dma_source & 0xff00ff) | (data << 8); return;
|
||||
case 0x1f42: regs.dma_source = (regs.dma_source & 0x00ffff) | (data << 16); return;
|
||||
case 0x1f43: regs.dma_length = (regs.dma_length & 0xff00) | (data << 0); return;
|
||||
case 0x1f44: regs.dma_length = (regs.dma_length & 0x00ff) | (data << 8); return;
|
||||
case 0x1f45: regs.dma_target = (regs.dma_target & 0xffff00) | (data << 0); return;
|
||||
case 0x1f46: regs.dma_target = (regs.dma_target & 0xff00ff) | (data << 8); return;
|
||||
case 0x1f47: regs.dma_target = (regs.dma_target & 0x00ffff) | (data << 16);
|
||||
if(state == State::Idle) state = State::DMA;
|
||||
return;
|
||||
case 0x1f48: regs.r1f48 = data & 0x01; return;
|
||||
case 0x1f49: regs.program_offset = (regs.program_offset & 0xffff00) | (data << 0); return;
|
||||
case 0x1f4a: regs.program_offset = (regs.program_offset & 0xff00ff) | (data << 8); return;
|
||||
case 0x1f4b: regs.program_offset = (regs.program_offset & 0x00ffff) | (data << 16); return;
|
||||
case 0x1f4c: regs.r1f4c = data & 0x03; return;
|
||||
case 0x1f4d: regs.page_number = (regs.page_number & 0x7f00) | ((data & 0xff) << 0); return;
|
||||
case 0x1f4e: regs.page_number = (regs.page_number & 0x00ff) | ((data & 0x7f) << 8); return;
|
||||
case 0x1f4f: regs.program_counter = data;
|
||||
if(state == State::Idle) {
|
||||
regs.pc = regs.page_number * 256 + regs.program_counter;
|
||||
state = State::Execute;
|
||||
}
|
||||
return;
|
||||
case 0x1f50: regs.r1f50 = data & 0x77; return;
|
||||
case 0x1f51: regs.r1f51 = data & 0x01; return;
|
||||
case 0x1f52: regs.r1f52 = data & 0x01; return;
|
||||
}
|
||||
|
||||
//Vector
|
||||
if(addr >= 0x1f60 && addr <= 0x1f7f) {
|
||||
regs.vector[addr & 0x1f] = data;
|
||||
return;
|
||||
}
|
||||
|
||||
//GPRs
|
||||
if((addr >= 0x1f80 && addr <= 0x1faf) || (addr >= 0x1fc0 && addr <= 0x1fef)) {
|
||||
unsigned index = (addr & 0x3f) / 3;
|
||||
switch((addr & 0x3f) % 3) {
|
||||
case 0: regs.gpr[index] = (regs.gpr[index] & 0xffff00) | (data << 0); return;
|
||||
case 1: regs.gpr[index] = (regs.gpr[index] & 0xff00ff) | (data << 8); return;
|
||||
case 2: regs.gpr[index] = (regs.gpr[index] & 0x00ffff) | (data << 16); return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
356
bsnes/snes/chip/hitachidsp/opcodes.cpp
Executable file
356
bsnes/snes/chip/hitachidsp/opcodes.cpp
Executable file
@@ -0,0 +1,356 @@
|
||||
#ifdef HITACHIDSP_CPP
|
||||
|
||||
void HitachiDSP::push() {
|
||||
stack[7] = stack[6];
|
||||
stack[6] = stack[5];
|
||||
stack[5] = stack[4];
|
||||
stack[4] = stack[3];
|
||||
stack[3] = stack[2];
|
||||
stack[2] = stack[1];
|
||||
stack[1] = stack[0];
|
||||
stack[0] = regs.pc;
|
||||
}
|
||||
|
||||
void HitachiDSP::pull() {
|
||||
regs.pc = stack[0];
|
||||
stack[0] = stack[1];
|
||||
stack[1] = stack[2];
|
||||
stack[2] = stack[3];
|
||||
stack[3] = stack[4];
|
||||
stack[4] = stack[5];
|
||||
stack[5] = stack[6];
|
||||
stack[6] = stack[7];
|
||||
stack[7] = 0x0000;
|
||||
}
|
||||
|
||||
//Shift-A: math opcodes can shift A register prior to ALU operation
|
||||
unsigned HitachiDSP::sa() {
|
||||
switch(opcode & 0x0300) { default:
|
||||
case 0x0000: return regs.a << 0;
|
||||
case 0x0100: return regs.a << 1;
|
||||
case 0x0200: return regs.a << 8;
|
||||
case 0x0300: return regs.a << 16;
|
||||
}
|
||||
}
|
||||
|
||||
//Register-or-Immediate: most opcodes can load from a register or immediate
|
||||
unsigned HitachiDSP::ri() {
|
||||
if(opcode & 0x0400) return opcode & 0xff;
|
||||
return reg_read(opcode & 0xff);
|
||||
}
|
||||
|
||||
//New-PC: determine jump target address; opcode.d9 = long jump flag (1 = yes)
|
||||
unsigned HitachiDSP::np() {
|
||||
if(opcode & 0x0200) return (regs.p << 8) | (opcode & 0xff);
|
||||
return (regs.pc & 0xffff00) | (opcode & 0xff);
|
||||
}
|
||||
|
||||
void HitachiDSP::exec() {
|
||||
if((opcode & 0xffff) == 0x0000) {
|
||||
//0000 0000 0000 0000
|
||||
//nop
|
||||
}
|
||||
|
||||
else if((opcode & 0xdd00) == 0x0800) {
|
||||
//00.0 10.0 .... ....
|
||||
//jump i
|
||||
if(opcode & 0x2000) push();
|
||||
regs.pc = np();
|
||||
}
|
||||
|
||||
else if((opcode & 0xdd00) == 0x0c00) {
|
||||
//00.0 11.0 .... ....
|
||||
//jumpeq i
|
||||
if(regs.z) {
|
||||
if(opcode & 0x2000) push();
|
||||
regs.pc = np();
|
||||
}
|
||||
}
|
||||
|
||||
else if((opcode & 0xdd00) == 0x1000) {
|
||||
//00.1 00.0 .... ....
|
||||
//jumpge i
|
||||
if(regs.c) {
|
||||
if(opcode & 0x2000) push();
|
||||
regs.pc = np();
|
||||
}
|
||||
}
|
||||
|
||||
else if((opcode & 0xdd00) == 0x1400) {
|
||||
//00.1 01.0 .... ....
|
||||
//jumpmi i
|
||||
if(regs.n) {
|
||||
if(opcode & 0x2000) push();
|
||||
regs.pc = np();
|
||||
}
|
||||
}
|
||||
|
||||
else if((opcode & 0xffff) == 0x1c00) {
|
||||
//0001 1100 0000 0000
|
||||
//loop?
|
||||
}
|
||||
|
||||
else if((opcode & 0xfffe) == 0x2500) {
|
||||
//0010 0101 0000 000.
|
||||
//skiplt/skipge
|
||||
if(regs.c == (opcode & 1)) regs.pc++;
|
||||
}
|
||||
|
||||
else if((opcode & 0xfffe) == 0x2600) {
|
||||
//0010 0110 0000 000.
|
||||
//skipne/skipeq
|
||||
if(regs.z == (opcode & 1)) regs.pc++;
|
||||
}
|
||||
|
||||
else if((opcode & 0xfffe) == 0x2700) {
|
||||
//0010 0111 0000 000.
|
||||
//skipmi/skippl
|
||||
if(regs.n == (opcode & 1)) regs.pc++;
|
||||
}
|
||||
|
||||
else if((opcode & 0xffff) == 0x3c00) {
|
||||
//0011 1100 0000 0000
|
||||
//ret
|
||||
pull();
|
||||
}
|
||||
|
||||
else if((opcode & 0xffff) == 0x4000) {
|
||||
//0100 0000 0000 0000
|
||||
//rdbus
|
||||
regs.busdata = bus_read(regs.busaddr++);
|
||||
}
|
||||
|
||||
else if((opcode & 0xf800) == 0x4800) {
|
||||
//0100 1... .... ....
|
||||
//cmpr a<<n,ri
|
||||
int result = ri() - sa();
|
||||
regs.n = result & 0x800000;
|
||||
regs.z = (uint24)result == 0;
|
||||
regs.c = result >= 0;
|
||||
}
|
||||
|
||||
else if((opcode & 0xf800) == 0x5000) {
|
||||
//0101 0... .... ....
|
||||
//cmp a<<n,ri
|
||||
int result = sa() - ri();
|
||||
regs.n = result & 0x800000;
|
||||
regs.z = (uint24)result == 0;
|
||||
regs.c = result >= 0;
|
||||
}
|
||||
|
||||
else if((opcode & 0xfb00) == 0x5900) {
|
||||
//0101 1.01 .... ....
|
||||
//sxb
|
||||
regs.a = (int8)ri();
|
||||
}
|
||||
|
||||
else if((opcode & 0xfb00) == 0x5a00) {
|
||||
//0101 1.10 .... ....
|
||||
//sxw
|
||||
regs.a = (int16)ri();
|
||||
}
|
||||
|
||||
else if((opcode & 0xfb00) == 0x6000) {
|
||||
//0110 0.00 .... ....
|
||||
//ld a,ri
|
||||
regs.a = ri();
|
||||
}
|
||||
|
||||
else if((opcode & 0xfb00) == 0x6100) {
|
||||
//0110 0.01 .... ....
|
||||
//ld ?,ri
|
||||
}
|
||||
|
||||
else if((opcode & 0xfb00) == 0x6300) {
|
||||
//0110 0.11 .... ....
|
||||
//ld p,ri
|
||||
regs.p = ri();
|
||||
}
|
||||
|
||||
else if((opcode & 0xfb00) == 0x6800) {
|
||||
//0110 1.00 .... ....
|
||||
//rdraml
|
||||
uint24 target = ri() + (opcode & 0x0400 ? regs.ramaddr : (uint24)0);
|
||||
if(target < 0xc00) regs.ramdata = (regs.ramdata & 0xffff00) | (dataRAM[target] << 0);
|
||||
}
|
||||
|
||||
else if((opcode & 0xfb00) == 0x6900) {
|
||||
//0110 1.01 .... ....
|
||||
//rdramh
|
||||
uint24 target = ri() + (opcode & 0x0400 ? regs.ramaddr : (uint24)0);
|
||||
if(target < 0xc00) regs.ramdata = (regs.ramdata & 0xff00ff) | (dataRAM[target] << 8);
|
||||
}
|
||||
|
||||
else if((opcode & 0xfb00) == 0x6a00) {
|
||||
//0110 1.10 .... ....
|
||||
//rdramb
|
||||
uint24 target = ri() + (opcode & 0x0400 ? regs.ramaddr : (uint24)0);
|
||||
if(target < 0xc00) regs.ramdata = (regs.ramdata & 0x00ffff) | (dataRAM[target] << 16);
|
||||
}
|
||||
|
||||
else if((opcode & 0xffff) == 0x7000) {
|
||||
//0111 0000 0000 0000
|
||||
//rdrom
|
||||
regs.romdata = dataROM[regs.a & 0x3ff];
|
||||
}
|
||||
|
||||
else if((opcode & 0xff00) == 0x7c00) {
|
||||
//0111 1100 .... ....
|
||||
//ld pl,i
|
||||
regs.p = (regs.p & 0xff00) | ((opcode & 0xff) << 0);
|
||||
}
|
||||
|
||||
else if((opcode & 0xff00) == 0x7d00) {
|
||||
//0111 1101 .... ....
|
||||
//ld ph,i
|
||||
regs.p = (regs.p & 0x00ff) | ((opcode & 0xff) << 8);
|
||||
}
|
||||
|
||||
else if((opcode & 0xf800) == 0x8000) {
|
||||
//1000 0... .... ....
|
||||
//add a<<n,ri
|
||||
int result = sa() + ri();
|
||||
regs.a = result;
|
||||
regs.n = regs.a & 0x800000;
|
||||
regs.z = regs.a == 0;
|
||||
regs.c = result > 0xffffff;
|
||||
}
|
||||
|
||||
else if((opcode & 0xf800) == 0x8800) {
|
||||
//1000 1... .... ....
|
||||
//subr a<<n,ri
|
||||
int result = ri() - sa();
|
||||
regs.a = result;
|
||||
regs.n = regs.a & 0x800000;
|
||||
regs.z = regs.a == 0;
|
||||
regs.c = result >= 0;
|
||||
}
|
||||
|
||||
else if((opcode & 0xf800) == 0x9000) {
|
||||
//1001 0... .... ....
|
||||
//sub a<<n,ri
|
||||
int result = sa() - ri();
|
||||
regs.a = result;
|
||||
regs.n = regs.a & 0x800000;
|
||||
regs.z = regs.a == 0;
|
||||
regs.c = result >= 0;
|
||||
}
|
||||
|
||||
else if((opcode & 0xfb00) == 0x9800) {
|
||||
//1001 1.00 .... ....
|
||||
//mul a,ri
|
||||
int64 x = (int24)regs.a;
|
||||
int64 y = (int24)ri();
|
||||
x *= y;
|
||||
regs.accl = x >> 0ull;
|
||||
regs.acch = x >> 24ull;
|
||||
regs.n = regs.acch & 0x800000;
|
||||
regs.z = x == 0;
|
||||
}
|
||||
|
||||
else if((opcode & 0xf800) == 0xa800) {
|
||||
//1010 1... .... ....
|
||||
//xor a<<n,ri
|
||||
regs.a = sa() ^ ri();
|
||||
regs.n = regs.a & 0x800000;
|
||||
regs.z = regs.a == 0;
|
||||
}
|
||||
|
||||
else if((opcode & 0xf800) == 0xb000) {
|
||||
//1011 0... .... ....
|
||||
//and a<<n,ri
|
||||
regs.a = sa() & ri();
|
||||
regs.n = regs.a & 0x800000;
|
||||
regs.z = regs.a == 0;
|
||||
}
|
||||
|
||||
else if((opcode & 0xf800) == 0xb800) {
|
||||
//1011 1... .... ....
|
||||
//or a<<n,ri
|
||||
regs.a = sa() | ri();
|
||||
regs.n = regs.a & 0x800000;
|
||||
regs.z = regs.a == 0;
|
||||
}
|
||||
|
||||
else if((opcode & 0xfb00) == 0xc000) {
|
||||
//1100 0.00 .... ....
|
||||
//shr a,ri
|
||||
regs.a = regs.a >> ri();
|
||||
regs.n = regs.a & 0x800000;
|
||||
regs.z = regs.a == 0;
|
||||
}
|
||||
|
||||
else if((opcode & 0xfb00) == 0xc800) {
|
||||
//1100 1.00 .... ....
|
||||
//asr a,ri
|
||||
regs.a = (int24)regs.a >> ri();
|
||||
regs.n = regs.a & 0x800000;
|
||||
regs.z = regs.a == 0;
|
||||
}
|
||||
|
||||
else if((opcode & 0xfb00) == 0xd000) {
|
||||
//1101 0.00 .... ....
|
||||
//ror a,ri
|
||||
uint24 length = ri();
|
||||
regs.a = (regs.a >> length) | (regs.a << (24 - length));
|
||||
regs.n = regs.a & 0x800000;
|
||||
regs.z = regs.a == 0;
|
||||
}
|
||||
|
||||
else if((opcode & 0xfb00) == 0xd800) {
|
||||
//1101 1.00 .... ....
|
||||
//shl a,ri
|
||||
regs.a = regs.a << ri();
|
||||
regs.n = regs.a & 0x800000;
|
||||
regs.z = regs.a == 0;
|
||||
}
|
||||
|
||||
else if((opcode & 0xff00) == 0xe000) {
|
||||
//1110 0000 .... ....
|
||||
//st r,a
|
||||
reg_write(opcode & 0xff, regs.a);
|
||||
}
|
||||
|
||||
else if((opcode & 0xfb00) == 0xe800) {
|
||||
//1110 1.00 .... ....
|
||||
//wrraml
|
||||
uint24 target = ri() + (opcode & 0x0400 ? regs.ramaddr : (uint24)0);
|
||||
if(target < 0xc00) dataRAM[target] = regs.ramdata >> 0;
|
||||
}
|
||||
|
||||
else if((opcode & 0xfb00) == 0xe900) {
|
||||
//1110 1.01 .... ....
|
||||
//wrramh
|
||||
uint24 target = ri() + (opcode & 0x0400 ? regs.ramaddr : (uint24)0);
|
||||
if(target < 0xc00) dataRAM[target] = regs.ramdata >> 8;
|
||||
}
|
||||
|
||||
else if((opcode & 0xfb00) == 0xea00) {
|
||||
//1110 1.10 .... ....
|
||||
//wrramb
|
||||
uint24 target = ri() + (opcode & 0x0400 ? regs.ramaddr : (uint24)0);
|
||||
if(target < 0xc00) dataRAM[target] = regs.ramdata >> 16;
|
||||
}
|
||||
|
||||
else if((opcode & 0xff00) == 0xf000) {
|
||||
//1111 0000 .... ....
|
||||
//swap a,r
|
||||
uint24 source = reg_read(opcode & 0xff);
|
||||
uint24 target = regs.a;
|
||||
regs.a = source;
|
||||
reg_write(opcode & 0xff, target);
|
||||
}
|
||||
|
||||
else if((opcode & 0xffff) == 0xfc00) {
|
||||
//1111 1100 0000 0000
|
||||
//halt
|
||||
state = State::Idle;
|
||||
}
|
||||
|
||||
else {
|
||||
print("Hitachi DSP: invalid opcode @ ", hex<4>(regs.pc - 1), " = ", hex<4>(opcode), "\n");
|
||||
state = State::Idle;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
78
bsnes/snes/chip/hitachidsp/registers.cpp
Executable file
78
bsnes/snes/chip/hitachidsp/registers.cpp
Executable file
@@ -0,0 +1,78 @@
|
||||
#ifdef HITACHIDSP_CPP
|
||||
|
||||
unsigned HitachiDSP::reg_read(unsigned n) const {
|
||||
switch(n) {
|
||||
case 0x00: return regs.a;
|
||||
case 0x01: return regs.acch;
|
||||
case 0x02: return regs.accl;
|
||||
case 0x03: return regs.busdata;
|
||||
case 0x08: return regs.romdata;
|
||||
case 0x0c: return regs.ramdata;
|
||||
case 0x13: return regs.busaddr;
|
||||
case 0x1c: return regs.ramaddr;
|
||||
case 0x50: return 0x000000;
|
||||
case 0x51: return 0xffffff;
|
||||
case 0x52: return 0x00ff00;
|
||||
case 0x53: return 0xff0000;
|
||||
case 0x54: return 0x00ffff;
|
||||
case 0x55: return 0xffff00;
|
||||
case 0x56: return 0x800000;
|
||||
case 0x57: return 0x7fffff;
|
||||
case 0x58: return 0x008000;
|
||||
case 0x59: return 0x007fff;
|
||||
case 0x5a: return 0xff7fff;
|
||||
case 0x5b: return 0xffff7f;
|
||||
case 0x5c: return 0x010000;
|
||||
case 0x5d: return 0xfeffff;
|
||||
case 0x5e: return 0x000100;
|
||||
case 0x5f: return 0x00feff;
|
||||
case 0x60: return regs.gpr[ 0];
|
||||
case 0x61: return regs.gpr[ 1];
|
||||
case 0x62: return regs.gpr[ 2];
|
||||
case 0x63: return regs.gpr[ 3];
|
||||
case 0x64: return regs.gpr[ 4];
|
||||
case 0x65: return regs.gpr[ 5];
|
||||
case 0x66: return regs.gpr[ 6];
|
||||
case 0x67: return regs.gpr[ 7];
|
||||
case 0x68: return regs.gpr[ 8];
|
||||
case 0x69: return regs.gpr[ 9];
|
||||
case 0x6a: return regs.gpr[10];
|
||||
case 0x6b: return regs.gpr[11];
|
||||
case 0x6c: return regs.gpr[12];
|
||||
case 0x6d: return regs.gpr[13];
|
||||
case 0x6e: return regs.gpr[14];
|
||||
case 0x6f: return regs.gpr[15];
|
||||
}
|
||||
return 0x000000;
|
||||
}
|
||||
|
||||
void HitachiDSP::reg_write(unsigned n, unsigned data) {
|
||||
switch(n) {
|
||||
case 0x00: regs.a = data; return;
|
||||
case 0x01: regs.acch = data; return;
|
||||
case 0x02: regs.accl = data; return;
|
||||
case 0x03: regs.busdata = data; return;
|
||||
case 0x08: regs.romdata = data; return;
|
||||
case 0x0c: regs.ramdata = data; return;
|
||||
case 0x13: regs.busaddr = data; return;
|
||||
case 0x1c: regs.ramaddr = data; return;
|
||||
case 0x60: regs.gpr[ 0] = data; return;
|
||||
case 0x61: regs.gpr[ 1] = data; return;
|
||||
case 0x62: regs.gpr[ 2] = data; return;
|
||||
case 0x63: regs.gpr[ 3] = data; return;
|
||||
case 0x64: regs.gpr[ 4] = data; return;
|
||||
case 0x65: regs.gpr[ 5] = data; return;
|
||||
case 0x66: regs.gpr[ 6] = data; return;
|
||||
case 0x67: regs.gpr[ 7] = data; return;
|
||||
case 0x68: regs.gpr[ 8] = data; return;
|
||||
case 0x69: regs.gpr[ 9] = data; return;
|
||||
case 0x6a: regs.gpr[10] = data; return;
|
||||
case 0x6b: regs.gpr[11] = data; return;
|
||||
case 0x6c: regs.gpr[12] = data; return;
|
||||
case 0x6d: regs.gpr[13] = data; return;
|
||||
case 0x6e: regs.gpr[14] = data; return;
|
||||
case 0x6f: regs.gpr[15] = data; return;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
31
bsnes/snes/chip/hitachidsp/registers.hpp
Executable file
31
bsnes/snes/chip/hitachidsp/registers.hpp
Executable file
@@ -0,0 +1,31 @@
|
||||
struct Registers {
|
||||
uint24 pc;
|
||||
uint16 p;
|
||||
bool n;
|
||||
bool z;
|
||||
bool c;
|
||||
|
||||
uint24 a;
|
||||
uint24 acch;
|
||||
uint24 accl;
|
||||
uint24 busdata;
|
||||
uint24 romdata;
|
||||
uint24 ramdata;
|
||||
uint24 busaddr;
|
||||
uint24 ramaddr;
|
||||
uint24 gpr[16];
|
||||
|
||||
//MMIO
|
||||
uint24 dma_source; //$1f40-$1f42
|
||||
uint24 dma_length; //$1f43-$1f44
|
||||
uint24 dma_target; //$1f45-$1f47
|
||||
uint8 r1f48; //$1f48
|
||||
uint24 program_offset; //$1f49-$1f4b
|
||||
uint8 r1f4c; //$1f4c
|
||||
uint16 page_number; //$1f4d-$1f4e
|
||||
uint8 program_counter; //$1f4f
|
||||
uint8 r1f50; //$1f50
|
||||
uint8 r1f51; //$1f51
|
||||
uint8 r1f52; //$1f52
|
||||
uint8 vector[32]; //$1f60-$1f7f
|
||||
} regs;
|
41
bsnes/snes/chip/hitachidsp/serialization.cpp
Executable file
41
bsnes/snes/chip/hitachidsp/serialization.cpp
Executable file
@@ -0,0 +1,41 @@
|
||||
#ifdef HITACHIDSP_CPP
|
||||
|
||||
void HitachiDSP::serialize(serializer &s) {
|
||||
Processor::serialize(s);
|
||||
|
||||
s.array(dataRAM);
|
||||
foreach(n, stack) s.integer(n);
|
||||
s.integer(opcode);
|
||||
s.integer((unsigned&)state);
|
||||
|
||||
s.integer(regs.pc);
|
||||
s.integer(regs.p);
|
||||
s.integer(regs.n);
|
||||
s.integer(regs.z);
|
||||
s.integer(regs.c);
|
||||
|
||||
s.integer(regs.a);
|
||||
s.integer(regs.acch);
|
||||
s.integer(regs.accl);
|
||||
s.integer(regs.busdata);
|
||||
s.integer(regs.romdata);
|
||||
s.integer(regs.ramdata);
|
||||
s.integer(regs.busaddr);
|
||||
s.integer(regs.ramaddr);
|
||||
foreach(n, regs.gpr) s.integer(n);
|
||||
|
||||
s.integer(regs.dma_source);
|
||||
s.integer(regs.dma_length);
|
||||
s.integer(regs.dma_target);
|
||||
s.integer(regs.r1f48);
|
||||
s.integer(regs.program_offset);
|
||||
s.integer(regs.r1f4c);
|
||||
s.integer(regs.page_number);
|
||||
s.integer(regs.program_counter);
|
||||
s.integer(regs.r1f50);
|
||||
s.integer(regs.r1f51);
|
||||
s.integer(regs.r1f52);
|
||||
s.array(regs.vector);
|
||||
}
|
||||
|
||||
#endif
|
@@ -33,10 +33,6 @@ void ICD2::init() {
|
||||
}
|
||||
|
||||
void ICD2::load() {
|
||||
bus.map(Bus::MapMode::Direct, 0x00, 0x3f, 0x2181, 0x2182, { &ICD2::mmio_read, &icd2 }, { &ICD2::mmio_write, &icd2 });
|
||||
bus.map(Bus::MapMode::Direct, 0x00, 0x3f, 0x420b, 0x420b, { &ICD2::mmio_read, &icd2 }, { &ICD2::mmio_write, &icd2 });
|
||||
bus.map(Bus::MapMode::Direct, 0x80, 0xbf, 0x2181, 0x2182, { &ICD2::mmio_read, &icd2 }, { &ICD2::mmio_write, &icd2 });
|
||||
bus.map(Bus::MapMode::Direct, 0x80, 0xbf, 0x420b, 0x420b, { &ICD2::mmio_read, &icd2 }, { &ICD2::mmio_write, &icd2 });
|
||||
}
|
||||
|
||||
void ICD2::unload() {
|
||||
@@ -52,10 +48,8 @@ void ICD2::power() {
|
||||
void ICD2::reset() {
|
||||
create(ICD2::Enter, cpu.frequency / 5);
|
||||
|
||||
r2181 = 0x00;
|
||||
r2182 = 0x00;
|
||||
|
||||
r6000 = 0x00;
|
||||
r6000_ly = 0x00;
|
||||
r6000_row = 0x00;
|
||||
r6003 = 0x00;
|
||||
r6004 = 0xff;
|
||||
r6005 = 0xff;
|
||||
@@ -65,7 +59,9 @@ void ICD2::reset() {
|
||||
r7800 = 0x0000;
|
||||
mlt_req = 0;
|
||||
|
||||
for(unsigned n = 0; n < 320; n++) vram[n] = 0xff;
|
||||
foreach(byte, lcd.buffer) byte = 0xff;
|
||||
foreach(byte, lcd.output) byte = 0xff;
|
||||
lcd.row = 0;
|
||||
|
||||
packetsize = 0;
|
||||
joyp_id = 3;
|
||||
|
@@ -1,5 +1,15 @@
|
||||
#ifdef ICD2_CPP
|
||||
|
||||
//called on rendered lines 0-143 (not on Vblank lines 144-153)
|
||||
void ICD2::lcd_scanline() {
|
||||
if((GameBoy::lcd.status.ly & 7) == 0) {
|
||||
lcd.row = (lcd.row + 1) & 3;
|
||||
}
|
||||
|
||||
unsigned offset = (lcd.row * 160 * 8) + ((GameBoy::lcd.status.ly & 7) * 160);
|
||||
memcpy(lcd.buffer + offset, GameBoy::lcd.screen + GameBoy::lcd.status.ly * 160, 160);
|
||||
}
|
||||
|
||||
void ICD2::joyp_write(bool p15, bool p14) {
|
||||
//joypad handling
|
||||
if(p15 == 1 && p14 == 1) {
|
||||
|
@@ -1,3 +1,4 @@
|
||||
void lcd_scanline();
|
||||
void joyp_write(bool p15, bool p14);
|
||||
void video_refresh(const uint8_t *data);
|
||||
void audio_sample(int16_t center, int16_t left, int16_t right);
|
||||
|
@@ -1,38 +1,19 @@
|
||||
#ifdef ICD2_CPP
|
||||
|
||||
uint8 ICD2::mmio_read(unsigned addr) {
|
||||
if((uint16)addr == 0x2181) return cpu.mmio_read(addr);
|
||||
if((uint16)addr == 0x2182) return cpu.mmio_read(addr);
|
||||
if((uint16)addr == 0x420b) return cpu.mmio_read(addr);
|
||||
return 0x00;
|
||||
}
|
||||
//convert linear pixel data { 0x00, 0x55, 0xaa, 0xff } to 2bpp planar tiledata
|
||||
void ICD2::render(const uint8 *source) {
|
||||
memset(lcd.output, 0x00, 320);
|
||||
|
||||
void ICD2::mmio_write(unsigned addr, uint8 data) {
|
||||
if((uint16)addr == 0x420b && data == 0x10) {
|
||||
unsigned offset = (r2182 << 8) | (r2181 << 0);
|
||||
r7800 = 0;
|
||||
unsigned row = 0;
|
||||
if(offset >= 0x5000 && offset <= 0x6540) row = (offset - 0x5000) / 320;
|
||||
if(offset >= 0x6800 && offset <= 0x7d40) row = (offset - 0x6800) / 320;
|
||||
for(unsigned y = 0; y < 8; y++) {
|
||||
for(unsigned x = 0; x < 160; x++) {
|
||||
unsigned pixel = *source++ / 0x55;
|
||||
pixel ^= 3;
|
||||
|
||||
uint8 *source = GameBoy::lcd.screen + row * 160 * 8;
|
||||
memset(vram, 0x00, 320);
|
||||
|
||||
for(unsigned y = row * 8; y < row * 8 + 8; y++) {
|
||||
for(unsigned x = 0; x < 160; x++) {
|
||||
unsigned pixel = *source++ / 0x55;
|
||||
pixel ^= 3;
|
||||
|
||||
unsigned addr = (x / 8 * 16) + ((y & 7) * 2);
|
||||
vram[addr + 0] |= ((pixel & 1) >> 0) << (7 - (x & 7));
|
||||
vram[addr + 1] |= ((pixel & 2) >> 1) << (7 - (x & 7));
|
||||
}
|
||||
unsigned addr = y * 2 + (x / 8 * 16);
|
||||
lcd.output[addr + 0] |= ((pixel & 1) >> 0) << (7 - (x & 7));
|
||||
lcd.output[addr + 1] |= ((pixel & 2) >> 1) << (7 - (x & 7));
|
||||
}
|
||||
}
|
||||
|
||||
if((uint16)addr == 0x2181) return cpu.mmio_write(addr, r2181 = data);
|
||||
if((uint16)addr == 0x2182) return cpu.mmio_write(addr, r2182 = data);
|
||||
if((uint16)addr == 0x420b) return cpu.mmio_write(addr, data);
|
||||
}
|
||||
|
||||
uint8 ICD2::read(unsigned addr) {
|
||||
@@ -40,7 +21,9 @@ uint8 ICD2::read(unsigned addr) {
|
||||
|
||||
//LY counter
|
||||
if(addr == 0x6000) {
|
||||
return GameBoy::lcd.status.ly;
|
||||
r6000_ly = GameBoy::lcd.status.ly;
|
||||
r6000_row = lcd.row;
|
||||
return r6000_ly;
|
||||
}
|
||||
|
||||
//command ready port
|
||||
@@ -66,7 +49,7 @@ uint8 ICD2::read(unsigned addr) {
|
||||
|
||||
//VRAM port
|
||||
if(addr == 0x7800) {
|
||||
uint8 data = vram[r7800];
|
||||
uint8 data = lcd.output[r7800];
|
||||
r7800 = (r7800 + 1) % 320;
|
||||
return data;
|
||||
}
|
||||
@@ -77,6 +60,17 @@ uint8 ICD2::read(unsigned addr) {
|
||||
void ICD2::write(unsigned addr, uint8 data) {
|
||||
addr &= 0xffff;
|
||||
|
||||
//VRAM port
|
||||
if(addr == 0x6001) {
|
||||
r6001 = data;
|
||||
r7800 = 0;
|
||||
|
||||
unsigned offset = (r6000_row - (4 - (r6001 - (r6000_ly & 3)))) & 3;
|
||||
render(lcd.buffer + offset * 160 * 8);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
//control port
|
||||
//d7: 0 = halt, 1 = reset
|
||||
//d5,d4: 0 = 1-player, 1 = 2-player, 2 = 4-player, 3 = ???
|
||||
|
@@ -1,16 +1,19 @@
|
||||
uint8 r2181;
|
||||
uint8 r2182;
|
||||
uint8 mmio_read(unsigned addr);
|
||||
void mmio_write(unsigned addr, uint8 data);
|
||||
void render(const uint8 *source);
|
||||
|
||||
uint8 r6000;
|
||||
uint8 r6003;
|
||||
uint8 r6004;
|
||||
uint8 r6005;
|
||||
uint8 r6006;
|
||||
uint8 r6007;
|
||||
uint8 r7000[16];
|
||||
unsigned r7800;
|
||||
uint8 mlt_req;
|
||||
uint8 r6000_ly; //SGB BIOS' cache of LY
|
||||
uint8 r6000_row; //SGB BIOS' cache of ROW
|
||||
uint8 r6001; //VRAM conversion
|
||||
uint8 r6003; //control port
|
||||
uint8 r6004; //joypad 1
|
||||
uint8 r6005; //joypad 2
|
||||
uint8 r6006; //joypad 3
|
||||
uint8 r6007; //joypad 4
|
||||
uint8 r7000[16]; //JOYP packet data
|
||||
unsigned r7800; //VRAM offset
|
||||
uint8 mlt_req; //number of active joypads
|
||||
|
||||
uint8 vram[320];
|
||||
struct LCD {
|
||||
uint8 buffer[4 * 160 * 8]; //four tile rows of linear video data
|
||||
uint8 output[320]; //one tile row of 2bpp video data
|
||||
unsigned row; //active ICD2 rendering tile row
|
||||
} lcd;
|
||||
|
@@ -18,10 +18,9 @@ void ICD2::serialize(serializer &s) {
|
||||
s.integer(bitdata);
|
||||
s.integer(bitoffset);
|
||||
|
||||
s.integer(r2181);
|
||||
s.integer(r2182);
|
||||
|
||||
s.integer(r6000);
|
||||
s.integer(r6000_ly);
|
||||
s.integer(r6000_row);
|
||||
s.integer(r6001);
|
||||
s.integer(r6003);
|
||||
s.integer(r6004);
|
||||
s.integer(r6005);
|
||||
@@ -31,7 +30,9 @@ void ICD2::serialize(serializer &s) {
|
||||
s.integer(r7800);
|
||||
s.integer(mlt_req);
|
||||
|
||||
s.array(vram);
|
||||
s.array(lcd.buffer);
|
||||
s.array(lcd.output);
|
||||
s.integer(lcd.row);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
60
bsnes/snes/chip/link/link.cpp
Executable file
60
bsnes/snes/chip/link/link.cpp
Executable file
@@ -0,0 +1,60 @@
|
||||
#include <snes/snes.hpp>
|
||||
|
||||
#define LINK_HPP
|
||||
namespace SNES {
|
||||
|
||||
Link link;
|
||||
|
||||
void Link::Enter() { link.enter(); }
|
||||
|
||||
void Link::enter() {
|
||||
while(true) {
|
||||
cpu.synchronize_coprocessors();
|
||||
unsigned clocks = 1;
|
||||
if(link_run) clocks = link_run();
|
||||
step(clocks);
|
||||
synchronize_cpu();
|
||||
}
|
||||
}
|
||||
|
||||
void Link::init() {
|
||||
}
|
||||
|
||||
void Link::load() {
|
||||
if(opened()) close();
|
||||
string basename = system.interface->path(Cartridge::Slot::Base, "");
|
||||
string name = program != "" ? program : notdir(basename);
|
||||
string path = dir(basename);
|
||||
if(open(name, path)) {
|
||||
link_power = sym("link_power");
|
||||
link_reset = sym("link_reset");
|
||||
link_run = sym("link_run" );
|
||||
link_read = sym("link_read" );
|
||||
link_write = sym("link_write");
|
||||
}
|
||||
}
|
||||
|
||||
void Link::unload() {
|
||||
if(opened()) close();
|
||||
}
|
||||
|
||||
void Link::power() {
|
||||
if(link_power) link_power();
|
||||
create(Link::Enter, frequency);
|
||||
}
|
||||
|
||||
void Link::reset() {
|
||||
if(link_reset) link_reset();
|
||||
create(Link::Enter, frequency);
|
||||
}
|
||||
|
||||
uint8 Link::read(unsigned addr) {
|
||||
if(link_read) return link_read(addr);
|
||||
return cpu.regs.mdr;
|
||||
}
|
||||
|
||||
void Link::write(unsigned addr, uint8 data) {
|
||||
if(link_write) return link_write(addr, data);
|
||||
}
|
||||
|
||||
}
|
24
bsnes/snes/chip/link/link.hpp
Executable file
24
bsnes/snes/chip/link/link.hpp
Executable file
@@ -0,0 +1,24 @@
|
||||
class Link : public Coprocessor, public library {
|
||||
public:
|
||||
string program;
|
||||
|
||||
static void Enter();
|
||||
void enter();
|
||||
void init();
|
||||
void load();
|
||||
void unload();
|
||||
void power();
|
||||
void reset();
|
||||
|
||||
uint8 read(unsigned addr);
|
||||
void write(unsigned addr, uint8 data);
|
||||
|
||||
private:
|
||||
function<void ()> link_power;
|
||||
function<void ()> link_reset;
|
||||
function<unsigned ()> link_run;
|
||||
function<uint8 (unsigned)> link_read;
|
||||
function<void (unsigned, uint8)> link_write;
|
||||
};
|
||||
|
||||
extern Link link;
|
@@ -1,16 +1,16 @@
|
||||
#ifdef NECDSP_CPP
|
||||
|
||||
uint8 NECDSP::sr_read(unsigned) {
|
||||
cpu.synchronize_coprocessor();
|
||||
cpu.synchronize_coprocessors();
|
||||
return regs.sr >> 8;
|
||||
}
|
||||
|
||||
void NECDSP::sr_write(unsigned, uint8 data) {
|
||||
cpu.synchronize_coprocessor();
|
||||
cpu.synchronize_coprocessors();
|
||||
}
|
||||
|
||||
uint8 NECDSP::dr_read(unsigned) {
|
||||
cpu.synchronize_coprocessor();
|
||||
cpu.synchronize_coprocessors();
|
||||
if(regs.sr.drc == 0) {
|
||||
//16-bit
|
||||
if(regs.sr.drs == 0) {
|
||||
@@ -29,7 +29,7 @@ uint8 NECDSP::dr_read(unsigned) {
|
||||
}
|
||||
|
||||
void NECDSP::dr_write(unsigned, uint8 data) {
|
||||
cpu.synchronize_coprocessor();
|
||||
cpu.synchronize_coprocessors();
|
||||
if(regs.sr.drc == 0) {
|
||||
//16-bit
|
||||
if(regs.sr.drs == 0) {
|
||||
@@ -48,7 +48,7 @@ void NECDSP::dr_write(unsigned, uint8 data) {
|
||||
}
|
||||
|
||||
uint8 NECDSP::dp_read(unsigned addr) {
|
||||
cpu.synchronize_coprocessor();
|
||||
cpu.synchronize_coprocessors();
|
||||
bool hi = addr & 1;
|
||||
addr = (addr >> 1) & 2047;
|
||||
|
||||
@@ -60,7 +60,7 @@ uint8 NECDSP::dp_read(unsigned addr) {
|
||||
}
|
||||
|
||||
void NECDSP::dp_write(unsigned addr, uint8 data) {
|
||||
cpu.synchronize_coprocessor();
|
||||
cpu.synchronize_coprocessors();
|
||||
bool hi = addr & 1;
|
||||
addr = (addr >> 1) & 2047;
|
||||
|
||||
|
@@ -1,3 +1,6 @@
|
||||
//NEC uPD7725
|
||||
//NEC uPD96050
|
||||
|
||||
class NECDSP : public Coprocessor {
|
||||
public:
|
||||
enum class Revision : unsigned { uPD7725, uPD96050 } revision;
|
||||
|
@@ -1,6 +1,8 @@
|
||||
#ifdef NECDSP_CPP
|
||||
|
||||
void NECDSP::serialize(serializer &s) {
|
||||
Processor::serialize(s);
|
||||
|
||||
s.array(dataRAM);
|
||||
|
||||
s.array(regs.stack);
|
||||
|
39
bsnes/snes/chip/nss/nss.cpp
Executable file
39
bsnes/snes/chip/nss/nss.cpp
Executable file
@@ -0,0 +1,39 @@
|
||||
#include <snes/snes.hpp>
|
||||
|
||||
#define NSS_CPP
|
||||
namespace SNES {
|
||||
|
||||
NSS nss;
|
||||
|
||||
void NSS::init() {
|
||||
}
|
||||
|
||||
void NSS::load() {
|
||||
dip = 0x0000;
|
||||
bus.map(Bus::MapMode::Direct, 0x00, 0x3f, 0x4100, 0x4101, { &NSS::read, this }, { &NSS::write, this });
|
||||
bus.map(Bus::MapMode::Direct, 0x80, 0xbf, 0x4100, 0x4101, { &NSS::read, this }, { &NSS::write, this });
|
||||
}
|
||||
|
||||
void NSS::unload() {
|
||||
}
|
||||
|
||||
void NSS::power() {
|
||||
}
|
||||
|
||||
void NSS::reset() {
|
||||
}
|
||||
|
||||
void NSS::set_dip(uint16 dip) {
|
||||
this->dip = dip;
|
||||
}
|
||||
|
||||
uint8 NSS::read(unsigned addr) {
|
||||
if((addr & 0x40ffff) == 0x004100) return dip >> 0;
|
||||
if((addr & 0x40ffff) == 0x004101) return dip >> 8;
|
||||
return cpu.regs.mdr;
|
||||
}
|
||||
|
||||
void NSS::write(unsigned addr, uint8 data) {
|
||||
}
|
||||
|
||||
}
|
17
bsnes/snes/chip/nss/nss.hpp
Executable file
17
bsnes/snes/chip/nss/nss.hpp
Executable file
@@ -0,0 +1,17 @@
|
||||
class NSS {
|
||||
public:
|
||||
void init();
|
||||
void load();
|
||||
void unload();
|
||||
void power();
|
||||
void reset();
|
||||
|
||||
void set_dip(uint16 dip);
|
||||
uint8 read(unsigned addr);
|
||||
void write(unsigned addr, uint8 data);
|
||||
|
||||
private:
|
||||
uint16 dip;
|
||||
};
|
||||
|
||||
extern NSS nss;
|
@@ -3,9 +3,8 @@
|
||||
#define OBC1_CPP
|
||||
namespace SNES {
|
||||
|
||||
OBC1 obc1;
|
||||
|
||||
#include "serialization.cpp"
|
||||
OBC1 obc1;
|
||||
|
||||
void OBC1::init() {
|
||||
}
|
||||
@@ -30,45 +29,46 @@ void OBC1::reset() {
|
||||
|
||||
uint8 OBC1::read(unsigned addr) {
|
||||
addr &= 0x1fff;
|
||||
if((addr & 0x1ff8) != 0x1ff0) return ram_read(addr);
|
||||
|
||||
switch(addr) { default: //never used, avoids compiler warning
|
||||
case 0x1ff0: return ram_read(status.baseptr + (status.address << 2) + 0);
|
||||
case 0x1ff1: return ram_read(status.baseptr + (status.address << 2) + 1);
|
||||
case 0x1ff2: return ram_read(status.baseptr + (status.address << 2) + 2);
|
||||
case 0x1ff3: return ram_read(status.baseptr + (status.address << 2) + 3);
|
||||
case 0x1ff4: return ram_read(status.baseptr + (status.address >> 2) + 0x200);
|
||||
case 0x1ff5: case 0x1ff6: case 0x1ff7: return ram_read(addr);
|
||||
switch(addr) {
|
||||
case 0x1ff0: return ram_read(status.baseptr + (status.address << 2) + 0);
|
||||
case 0x1ff1: return ram_read(status.baseptr + (status.address << 2) + 1);
|
||||
case 0x1ff2: return ram_read(status.baseptr + (status.address << 2) + 2);
|
||||
case 0x1ff3: return ram_read(status.baseptr + (status.address << 2) + 3);
|
||||
case 0x1ff4: return ram_read(status.baseptr + (status.address >> 2) + 0x200);
|
||||
}
|
||||
|
||||
return ram_read(addr);
|
||||
}
|
||||
|
||||
void OBC1::write(unsigned addr, uint8 data) {
|
||||
addr &= 0x1fff;
|
||||
if((addr & 0x1ff8) != 0x1ff0) return ram_write(addr, data);
|
||||
|
||||
switch(addr) {
|
||||
case 0x1ff0: ram_write(status.baseptr + (status.address << 2) + 0, data); break;
|
||||
case 0x1ff1: ram_write(status.baseptr + (status.address << 2) + 1, data); break;
|
||||
case 0x1ff2: ram_write(status.baseptr + (status.address << 2) + 2, data); break;
|
||||
case 0x1ff3: ram_write(status.baseptr + (status.address << 2) + 3, data); break;
|
||||
case 0x1ff4: {
|
||||
uint8 temp = ram_read(status.baseptr + (status.address >> 2) + 0x200);
|
||||
temp = (temp & ~(3 << status.shift)) | ((data & 3) << status.shift);
|
||||
ram_write(status.baseptr + (status.address >> 2) + 0x200, temp);
|
||||
} break;
|
||||
case 0x1ff5: {
|
||||
status.baseptr = (data & 1) ? 0x1800 : 0x1c00;
|
||||
ram_write(addr, data);
|
||||
} break;
|
||||
case 0x1ff6: {
|
||||
status.address = (data & 0x7f);
|
||||
status.shift = (data & 3) << 1;
|
||||
ram_write(addr, data);
|
||||
} break;
|
||||
case 0x1ff7: {
|
||||
ram_write(addr, data);
|
||||
} break;
|
||||
case 0x1ff0: ram_write(status.baseptr + (status.address << 2) + 0, data); return;
|
||||
case 0x1ff1: ram_write(status.baseptr + (status.address << 2) + 1, data); return;
|
||||
case 0x1ff2: ram_write(status.baseptr + (status.address << 2) + 2, data); return;
|
||||
case 0x1ff3: ram_write(status.baseptr + (status.address << 2) + 3, data); return;
|
||||
case 0x1ff4: {
|
||||
uint8 temp = ram_read(status.baseptr + (status.address >> 2) + 0x200);
|
||||
temp = (temp & ~(3 << status.shift)) | ((data & 3) << status.shift);
|
||||
ram_write(status.baseptr + (status.address >> 2) + 0x200, temp);
|
||||
} return;
|
||||
case 0x1ff5:
|
||||
status.baseptr = (data & 1) ? 0x1800 : 0x1c00;
|
||||
ram_write(addr, data);
|
||||
return;
|
||||
case 0x1ff6:
|
||||
status.address = (data & 0x7f);
|
||||
status.shift = (data & 3) << 1;
|
||||
ram_write(addr, data);
|
||||
return;
|
||||
case 0x1ff7:
|
||||
ram_write(addr, data);
|
||||
return;
|
||||
}
|
||||
|
||||
return ram_write(addr, data);
|
||||
}
|
||||
|
||||
uint8 OBC1::ram_read(unsigned addr) {
|
||||
@@ -79,7 +79,4 @@ void OBC1::ram_write(unsigned addr, uint8 data) {
|
||||
cartridge.ram.write(addr & 0x1fff, data);
|
||||
}
|
||||
|
||||
OBC1::OBC1() {}
|
||||
OBC1::~OBC1() {}
|
||||
|
||||
}
|
||||
|
@@ -10,8 +10,6 @@ public:
|
||||
void write(unsigned addr, uint8 data);
|
||||
|
||||
void serialize(serializer&);
|
||||
OBC1();
|
||||
~OBC1();
|
||||
|
||||
private:
|
||||
uint8 ram_read(unsigned addr);
|
||||
|
@@ -7,12 +7,12 @@ unsigned SA1::CPUIRAM::size() const {
|
||||
}
|
||||
|
||||
uint8 SA1::CPUIRAM::read(unsigned addr) {
|
||||
cpu.synchronize_coprocessor();
|
||||
cpu.synchronize_coprocessors();
|
||||
return sa1.iram.read(addr);
|
||||
}
|
||||
|
||||
void SA1::CPUIRAM::write(unsigned addr, uint8 data) {
|
||||
cpu.synchronize_coprocessor();
|
||||
cpu.synchronize_coprocessors();
|
||||
sa1.iram.write(addr, data);
|
||||
}
|
||||
|
||||
@@ -21,13 +21,13 @@ unsigned SA1::CPUBWRAM::size() const {
|
||||
}
|
||||
|
||||
uint8 SA1::CPUBWRAM::read(unsigned addr) {
|
||||
cpu.synchronize_coprocessor();
|
||||
cpu.synchronize_coprocessors();
|
||||
if(dma) return sa1.dma_cc1_read(addr);
|
||||
return cartridge.ram.read(addr);
|
||||
}
|
||||
|
||||
void SA1::CPUBWRAM::write(unsigned addr, uint8 data) {
|
||||
cpu.synchronize_coprocessor();
|
||||
cpu.synchronize_coprocessors();
|
||||
cartridge.ram.write(addr, data);
|
||||
}
|
||||
|
||||
|
@@ -178,13 +178,13 @@ void SA1::mmc_write(unsigned addr, uint8 data) {
|
||||
}
|
||||
|
||||
uint8 SA1::mmc_cpu_read(unsigned addr) {
|
||||
cpu.synchronize_coprocessor();
|
||||
cpu.synchronize_coprocessors();
|
||||
addr = bus.mirror(mmio.sbm * 0x2000 + (addr & 0x1fff), cpubwram.size());
|
||||
return cpubwram.read(addr);
|
||||
}
|
||||
|
||||
void SA1::mmc_cpu_write(unsigned addr, uint8 data) {
|
||||
cpu.synchronize_coprocessor();
|
||||
cpu.synchronize_coprocessors();
|
||||
addr = bus.mirror(mmio.sbm * 0x2000 + (addr & 0x1fff), cpubwram.size());
|
||||
cpubwram.write(addr, data);
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user