mirror of
https://github.com/bsnes-emu/bsnes.git
synced 2025-02-24 07:02:27 +01:00
[No prior releases were posted to the WIP thread. -Ed.] byuu says: Super Famicom mapping system has been reworked as discussed with the mask= changes. offset becomes base, mode is gone. Also added support for comma-separated fields in the address fields, to reduce the number of map lines needed. <?xml version="1.0" encoding="UTF-8"?> <cartridge region="NTSC"> <superfx revision="2"> <rom name="program.rom" size="0x200000"/> <ram name="save.rwm" size="0x8000"/> <map id="io" address="00-3f,80-bf:3000-32ff"/> <map id="rom" address="00-3f:8000-ffff" mask="0x8000"/> <map id="rom" address="40-5f:0000-ffff"/> <map id="ram" address="00-3f,80-bf:6000-7fff" size="0x2000"/> <map id="ram" address="70-71:0000-ffff"/> </superfx> </cartridge> Or in BML: cartridge region=NTSC superfx revision=2 rom name=program.rom size=0x200000 ram name=save.rwm size=0x8000 map id=io address=00-3f,80-bf:3000-32ff map id=rom address=00-3f:8000-ffff mask=0x8000 map id=rom address=40-5f:0000-ffff map id=ram address=00-3f,80-bf:6000-7fff size=0x2000 map id=ram address=70-71:0000-ffff As a result of the changes, old mappings will no longer work. The above XML example will run Super Mario World 2: Yoshi's Island. Otherwise, you'll have to write your own. All that's left now is to work some sort of database mapping system in, so I can start dumping carts en masse. The NES changes that FitzRoy asked for are mostly in as well. Also, part of the reason I haven't released a WIP ... but fuck it, I'm not going to wait forever to post a new WIP. I've added a skeleton driver to emulate Campus Challenge '92 and Powerfest '94. There's no actual emulation, except for the stuff I can glean from looking at the pictures of the board. It has a DSP-1 (so SR/DR registers), four ROMs that map in and out, RAM, etc. I've also added preliminary mapping to upload high scores to a website, but obviously I need the ROMs first.
207 lines
5.3 KiB
C++
Executable File
207 lines
5.3 KiB
C++
Executable File
#ifndef NALL_VECTOR_HPP
|
|
#define NALL_VECTOR_HPP
|
|
|
|
#include <algorithm>
|
|
#include <initializer_list>
|
|
#include <new>
|
|
#include <type_traits>
|
|
#include <utility>
|
|
#include <nall/algorithm.hpp>
|
|
#include <nall/bit.hpp>
|
|
#include <nall/sort.hpp>
|
|
#include <nall/utility.hpp>
|
|
|
|
namespace nall {
|
|
template<typename T> struct vector {
|
|
struct exception_out_of_bounds{};
|
|
|
|
protected:
|
|
T *pool;
|
|
unsigned poolsize;
|
|
unsigned objectsize;
|
|
|
|
public:
|
|
operator bool() const { return pool; }
|
|
T* data() { return pool; }
|
|
const T* data() const { return pool; }
|
|
|
|
bool empty() const { return objectsize == 0; }
|
|
unsigned size() const { return objectsize; }
|
|
unsigned capacity() const { return poolsize; }
|
|
|
|
T* move() {
|
|
T *result = pool;
|
|
pool = nullptr;
|
|
poolsize = 0;
|
|
objectsize = 0;
|
|
return result;
|
|
}
|
|
|
|
void reset() {
|
|
if(pool) {
|
|
for(unsigned n = 0; n < objectsize; n++) pool[n].~T();
|
|
free(pool);
|
|
}
|
|
pool = nullptr;
|
|
poolsize = 0;
|
|
objectsize = 0;
|
|
}
|
|
|
|
void reserve(unsigned size) {
|
|
unsigned outputsize = min(size, objectsize);
|
|
size = bit::round(size); //amortize growth
|
|
T *copy = (T*)calloc(size, sizeof(T));
|
|
for(unsigned n = 0; n < outputsize; n++) new(copy + n) T(pool[n]);
|
|
for(unsigned n = 0; n < objectsize; n++) pool[n].~T();
|
|
free(pool);
|
|
pool = copy;
|
|
poolsize = size;
|
|
objectsize = outputsize;
|
|
}
|
|
|
|
//requires trivial constructor
|
|
void resize(unsigned size) {
|
|
if(size == objectsize) return;
|
|
if(size < objectsize) return reserve(size);
|
|
while(size > objectsize) append(T());
|
|
}
|
|
|
|
template<typename... Args>
|
|
void append(const T& data, Args&&... args) {
|
|
append(data);
|
|
append(std::forward<Args>(args)...);
|
|
}
|
|
|
|
void append(const T& data) {
|
|
if(objectsize + 1 > poolsize) reserve(objectsize + 1);
|
|
new(pool + objectsize++) T(data);
|
|
}
|
|
|
|
bool appendonce(const T& data) {
|
|
if(find(data) == true) return false;
|
|
append(data);
|
|
return true;
|
|
}
|
|
|
|
void insert(unsigned position, const T& data) {
|
|
append(data);
|
|
for(signed n = size() - 1; n > position; n--) pool[n] = pool[n - 1];
|
|
pool[position] = data;
|
|
}
|
|
|
|
void prepend(const T& data) {
|
|
insert(0, data);
|
|
}
|
|
|
|
void remove(unsigned index = ~0u, unsigned count = 1) {
|
|
if(index == ~0) index = objectsize ? objectsize - 1 : 0;
|
|
for(unsigned n = index; count + n < objectsize; n++) pool[n] = pool[count + n];
|
|
objectsize = (count + index >= objectsize) ? index : objectsize - count;
|
|
}
|
|
|
|
T take(unsigned index = ~0u) {
|
|
if(index == ~0) index = objectsize ? objectsize - 1 : 0;
|
|
if(index >= objectsize) throw exception_out_of_bounds();
|
|
T item = pool[index];
|
|
remove(index);
|
|
return item;
|
|
}
|
|
|
|
void reverse() {
|
|
unsigned pivot = size() / 2;
|
|
for(unsigned l = 0, r = size() - 1; l < pivot; l++, r--) {
|
|
std::swap(pool[l], pool[r]);
|
|
}
|
|
}
|
|
|
|
void sort() {
|
|
nall::sort(pool, objectsize);
|
|
}
|
|
|
|
template<typename Comparator> void sort(const Comparator &lessthan) {
|
|
nall::sort(pool, objectsize, lessthan);
|
|
}
|
|
|
|
optional<unsigned> find(const T& data) {
|
|
for(unsigned n = 0; n < size(); n++) if(pool[n] == data) return {true, n};
|
|
return {false, 0u};
|
|
}
|
|
|
|
T& first() {
|
|
if(objectsize == 0) throw exception_out_of_bounds();
|
|
return pool[0];
|
|
}
|
|
|
|
T& last() {
|
|
if(objectsize == 0) throw exception_out_of_bounds();
|
|
return pool[objectsize - 1];
|
|
}
|
|
|
|
//access
|
|
inline T& operator[](unsigned position) {
|
|
if(position >= objectsize) throw exception_out_of_bounds();
|
|
return pool[position];
|
|
}
|
|
|
|
inline const T& operator[](unsigned position) const {
|
|
if(position >= objectsize) throw exception_out_of_bounds();
|
|
return pool[position];
|
|
}
|
|
|
|
inline T& operator()(unsigned position) {
|
|
if(position >= poolsize) reserve(position + 1);
|
|
while(position >= objectsize) append(T());
|
|
return pool[position];
|
|
}
|
|
|
|
inline const T& operator()(unsigned position, const T& data) const {
|
|
if(position >= objectsize) return data;
|
|
return pool[position];
|
|
}
|
|
|
|
//iteration
|
|
T* begin() { return &pool[0]; }
|
|
T* end() { return &pool[objectsize]; }
|
|
const T* begin() const { return &pool[0]; }
|
|
const T* end() const { return &pool[objectsize]; }
|
|
|
|
//copy
|
|
inline vector& operator=(const vector &source) {
|
|
reset();
|
|
reserve(source.capacity());
|
|
for(auto &data : source) append(data);
|
|
return *this;
|
|
}
|
|
|
|
vector(const vector &source) : pool(nullptr), poolsize(0), objectsize(0) {
|
|
operator=(source);
|
|
}
|
|
|
|
//move
|
|
inline vector& operator=(vector &&source) {
|
|
reset();
|
|
pool = source.pool, poolsize = source.poolsize, objectsize = source.objectsize;
|
|
source.pool = nullptr, source.poolsize = 0, source.objectsize = 0;
|
|
return *this;
|
|
}
|
|
|
|
vector(vector &&source) : pool(nullptr), poolsize(0), objectsize(0) {
|
|
operator=(std::move(source));
|
|
}
|
|
|
|
//construction
|
|
vector() : pool(nullptr), poolsize(0), objectsize(0) {
|
|
}
|
|
|
|
vector(std::initializer_list<T> list) : pool(nullptr), poolsize(0), objectsize(0) {
|
|
for(auto &data : list) append(data);
|
|
}
|
|
|
|
~vector() {
|
|
reset();
|
|
}
|
|
};
|
|
}
|
|
|
|
#endif
|