Update to bsnes v018 release.

I began working on bsnes on October 14th, 2004. I am releasing bsnes v0.018 today to celebrate bsnes' two year anniversary. Please note that this release incurs a ~15% speed reduction since v0.017, due to IRQ and S-SMP timing improvements.
Changelog:
    - Fixed many critical errors in IRQ timing, should be *very* close to real hardware now
    - Corrected major CPU timing bug involving CPU I/O condition 4
    - Corrected bug with generic HiROM / LoROM memory maps
    - Corrected bug involving HDMA indirect channel termination [anomie]
    - OAM address reset now occurs when screen display is enabled, per recent research
    - Readded full DMA, HDMA and HDMA init bus sync timing
    - Added preliminary emulation of S-SMP $00f0 TEST register (6 of 8 bits are supported)
    - Readded emulation of known timing differences between CPU revisions 1 and 2
    - Config file can now control scanline-based PPU render position. This will only be needed until a proper dot-based PPU renderer is added
    - Removed core debugging hooks so that debugging console can remain in public releases, it now functions as a tracer and memory editor
    - Config file paths once again work correctly even if missing trailing backslash
    - Video configuration simplified, sorry in advance to those who enjoyed the profile mode used before
    - Added new configuration screen to control some emulation settings
    - Replaced bsnes program icon with a much nicer one [FitzRoy]
    - Optimized memory speed detection algorithm
    - Preliminary UPS soft-patching support (do not use this yet!)
    - Decreased memory usage and optimized generic libraries used by bsnes (/src/lib)
    - Now caching OAM by one line, somewhat similar to a real SNES. Fixes Winter Gold, but causes line rendering error in Mega lo Mania
    - Lots more, as usual
The following games have been fixed since v0.017 by the above bugfixes:
    - Battle Blaze (J, U)
    - Circuit USA (J)
    - F1 Grand Prix (J)
    - Funaki Masakatsu no Hybrid Wrestler - Tougi Denshou (J)
    - Jumbo Ozaki no Hole in One (J)
    - Mahjongg Taikai II (J)
    - RPG Tsukuru - Super Dante (J)
    - Robocop Versus The Terminator (U, E)
    - Sink or Swim (U, E)
    - Street Racer (J)
    - Touge Densetsu Saisoku Battle (J)
    - Winter Olympics (U, E)
This commit is contained in:
byuu 2006-10-14 05:34:24 +00:00
parent ccf1c00b58
commit 35fd80bde7
225 changed files with 4027 additions and 7076 deletions

BIN
cart.db

Binary file not shown.

View File

@ -1,35 +0,0 @@
bsnes License:
--------------
You are free to redistribute this software, and its source code; provided
there is no charge for the software, nor any charge for the medium used to
distribute the software. You are also free to use and modify the source code
as you desire for personal use only. No publically-released derivative works
of this program nor its source code are permitted without my permission,
though I will likely grant you permission if you ask me. You must also abide
by the terms of any additional source code licenses contained within this
program.
Simple DirectMedia Layer License:
---------------------------------
The Simple DirectMedia Layer (SDL for short) is a cross-platform library
designed to make it easy to write multi-media software, such as games and
emulators.
The Simple DirectMedia Layer library source code is available from:
http://www.libsdl.org/
This library is distributed under the terms of the GNU LGPL:
http://www.gnu.org/copyleft/lesser.html
JMA License:
------------
JMA is licensed under the GNU GPL. I have received special exemption from
Nach to use this library in bsnes.
Licensing Exemptions:
---------------------
libco is public domain. You may obtain the latest version at:
http://byuu.org/
Richard Bannister has asked for and received my permission to distribute
a binary-only port of bsnes on the Mac OS X platform.

View File

@ -1,108 +0,0 @@
bsnes
Version 0.017
Author: byuu
General
-------
bsnes is a Super Nintendo / Super Famicom emulator that began on
October 14th, 2004.
The latest version can be downloaded from:
http://byuu.org/
Please see license.txt for important licensing information.
Known Bug(s)
------------
Uniracers / Unirally
- 2-player mode sprite issues (mid-frame OAM writes not supported)
Known Limitations
-----------------
S-CPU
- Invalid DMA / HDMA transfers (eg WRAM<>WRAM) not fully emulated
- DMA / HDMA bus synchronization timing not supported
- Multiply / Divide register delays not implemented
S-SMP
- Cycle breakdown of opcodes is theoretical, but mostly correct
S-PPU
- Uses scanline-based renderer. This is very inaccurate, but very
few games rely on mid-scanline writes to function correctly
- Does not support FirstSprite+Y priority
- OAM / CGRAM accesses during active display not supported correctly
- RTO flags are not calculated on frames that are skipped when frameskipping
is enabled. This provides a major speedup, however it will cause in issues
in games that test these flags, eg the SNES Test Program Electronics Test.
Turning frameskipping off will allow RTO flag calculation on every frame
S-DSP
- Runs at 32khz. Hardware S-DSP likely runs at 1.024mhz to perform
multiple reads / writes per sample. Sound is still output at 32khz,
of course
Hardware Bugs
- CPUr1 HDMA crashing bug not emulated
- CPU<>APU communication bus conflicts not emulated
Unsupported Hardware
--------------------
SA-1
Coprocessor used in many popular games, including:
- Dragon Ball Z Hyper Dimension
- Kirby Super Star
- Kirby's Dreamland 3
- Marvelous
- SD Gundam G-NEXT
- Super Mario RPG
Super FX
Coprocessor used in many popular games, including:
- Doom
- Star Fox
- Star Fox 2 (unreleased beta)
- Super Mario World 2: Yoshi's Island
SPC7110
Coprocessor used only by the following games:
- Far East of Eden Zero
- Far East of Eden Zero: Shounen Jump no Shou
- Momotarou Densetsu Happy
- Super Power League 4
DSP-3
Coprocessor used only by SD Gundam GX
DSP-4
Coprocessor used only by Top Gear 3000
ST010 / ST011 / ST018
SETA coprocessors used by very few games
BS-X (Broadcast Satellite)
Add-on unit sold only in Japan that played specially-made games that
were downloaded via satellite
BS-X Flashcart
Flash cartridge used by BS-X, as well as some standalone games by
Asciisoft
Bandai Sufami Turbo
Special cartloader to play some Bandai games
Super Gameboy
Cartridge passthrough used for playing Gameboy games
Unsupported controllers
-----------------------
Mouse
Super Scope
Justifier
Multitap (4-port)
Multitap (5-port)

View File

@ -1,44 +0,0 @@
class APURegFlags {
private:
template<uint mask> class bit {
public:
uint data;
inline operator bool() { return bool(data & mask); }
inline bool operator = (const bool i) { (i) ? data |= mask : data &= ~mask; return bool(data & mask); }
inline bool operator |= (const bool i) { if(i)data |= mask; return bool(data & mask); }
inline bool operator ^= (const bool i) { if(i)data ^= mask; return bool(data & mask); }
inline bool operator &= (const bool i) { if(i)data &= mask; return bool(data & mask); }
};
public:
union {
uint8 data;
bit<0x80> n;
bit<0x40> v;
bit<0x20> p;
bit<0x10> b;
bit<0x08> h;
bit<0x04> i;
bit<0x02> z;
bit<0x01> c;
};
inline operator unsigned() const { return data; }
inline unsigned operator = (const uint8 i) { data = i; return data; }
inline unsigned operator |= (const uint8 i) { data |= i; return data; }
inline unsigned operator ^= (const uint8 i) { data ^= i; return data; }
inline unsigned operator &= (const uint8 i) { data &= i; return data; }
APURegFlags() : data(0) {}
};
class APURegs {
public:
uint16 pc;
union {
uint16 ya;
struct { uint8 order_lsb2(a, y); };
};
uint8 x, sp;
APURegFlags p;
};

View File

@ -1,3 +0,0 @@
cl /O2 /wd4996 bapugen.cpp
@pause
@del *.obj

View File

@ -1,256 +0,0 @@
optbl[0x7d] = &bAPU::op_mov_a_x;
optbl[0xdd] = &bAPU::op_mov_a_y;
optbl[0x5d] = &bAPU::op_mov_x_a;
optbl[0xfd] = &bAPU::op_mov_y_a;
optbl[0x9d] = &bAPU::op_mov_x_sp;
optbl[0xbd] = &bAPU::op_mov_sp_x;
optbl[0xe8] = &bAPU::op_mov_a_const;
optbl[0xcd] = &bAPU::op_mov_x_const;
optbl[0x8d] = &bAPU::op_mov_y_const;
optbl[0xe6] = &bAPU::op_mov_a_ix;
optbl[0xbf] = &bAPU::op_mov_a_ixinc;
optbl[0xe4] = &bAPU::op_mov_a_dp;
optbl[0xf8] = &bAPU::op_mov_x_dp;
optbl[0xeb] = &bAPU::op_mov_y_dp;
optbl[0xf4] = &bAPU::op_mov_a_dpx;
optbl[0xf9] = &bAPU::op_mov_x_dpy;
optbl[0xfb] = &bAPU::op_mov_y_dpx;
optbl[0xe5] = &bAPU::op_mov_a_addr;
optbl[0xe9] = &bAPU::op_mov_x_addr;
optbl[0xec] = &bAPU::op_mov_y_addr;
optbl[0xf5] = &bAPU::op_mov_a_addrx;
optbl[0xf6] = &bAPU::op_mov_a_addry;
optbl[0xe7] = &bAPU::op_mov_a_idpx;
optbl[0xf7] = &bAPU::op_mov_a_idpy;
optbl[0xfa] = &bAPU::op_mov_dp_dp;
optbl[0x8f] = &bAPU::op_mov_dp_const;
optbl[0xc6] = &bAPU::op_mov_ix_a;
optbl[0xaf] = &bAPU::op_mov_ixinc_a;
optbl[0xc4] = &bAPU::op_mov_dp_a;
optbl[0xd8] = &bAPU::op_mov_dp_x;
optbl[0xcb] = &bAPU::op_mov_dp_y;
optbl[0xd4] = &bAPU::op_mov_dpx_a;
optbl[0xd9] = &bAPU::op_mov_dpy_x;
optbl[0xdb] = &bAPU::op_mov_dpx_y;
optbl[0xc5] = &bAPU::op_mov_addr_a;
optbl[0xc9] = &bAPU::op_mov_addr_x;
optbl[0xcc] = &bAPU::op_mov_addr_y;
optbl[0xd5] = &bAPU::op_mov_addrx_a;
optbl[0xd6] = &bAPU::op_mov_addry_a;
optbl[0xc7] = &bAPU::op_mov_idpx_a;
optbl[0xd7] = &bAPU::op_mov_idpy_a;
optbl[0xba] = &bAPU::op_movw_ya_dp;
optbl[0xda] = &bAPU::op_movw_dp_ya;
optbl[0xaa] = &bAPU::op_mov1_c_bit;
optbl[0xca] = &bAPU::op_mov1_bit_c;
optbl[0x2f] = &bAPU::op_bra;
optbl[0xf0] = &bAPU::op_beq;
optbl[0xd0] = &bAPU::op_bne;
optbl[0xb0] = &bAPU::op_bcs;
optbl[0x90] = &bAPU::op_bcc;
optbl[0x70] = &bAPU::op_bvs;
optbl[0x50] = &bAPU::op_bvc;
optbl[0x30] = &bAPU::op_bmi;
optbl[0x10] = &bAPU::op_bpl;
optbl[0x03] = &bAPU::op_bbs0;
optbl[0x13] = &bAPU::op_bbc0;
optbl[0x23] = &bAPU::op_bbs1;
optbl[0x33] = &bAPU::op_bbc1;
optbl[0x43] = &bAPU::op_bbs2;
optbl[0x53] = &bAPU::op_bbc2;
optbl[0x63] = &bAPU::op_bbs3;
optbl[0x73] = &bAPU::op_bbc3;
optbl[0x83] = &bAPU::op_bbs4;
optbl[0x93] = &bAPU::op_bbc4;
optbl[0xa3] = &bAPU::op_bbs5;
optbl[0xb3] = &bAPU::op_bbc5;
optbl[0xc3] = &bAPU::op_bbs6;
optbl[0xd3] = &bAPU::op_bbc6;
optbl[0xe3] = &bAPU::op_bbs7;
optbl[0xf3] = &bAPU::op_bbc7;
optbl[0x2e] = &bAPU::op_cbne_dp;
optbl[0xde] = &bAPU::op_cbne_dpx;
optbl[0x6e] = &bAPU::op_dbnz_dp;
optbl[0xfe] = &bAPU::op_dbnz_y;
optbl[0x5f] = &bAPU::op_jmp_addr;
optbl[0x1f] = &bAPU::op_jmp_iaddrx;
optbl[0x3f] = &bAPU::op_call;
optbl[0x4f] = &bAPU::op_pcall;
optbl[0x01] = &bAPU::op_tcall_0;
optbl[0x11] = &bAPU::op_tcall_1;
optbl[0x21] = &bAPU::op_tcall_2;
optbl[0x31] = &bAPU::op_tcall_3;
optbl[0x41] = &bAPU::op_tcall_4;
optbl[0x51] = &bAPU::op_tcall_5;
optbl[0x61] = &bAPU::op_tcall_6;
optbl[0x71] = &bAPU::op_tcall_7;
optbl[0x81] = &bAPU::op_tcall_8;
optbl[0x91] = &bAPU::op_tcall_9;
optbl[0xa1] = &bAPU::op_tcall_10;
optbl[0xb1] = &bAPU::op_tcall_11;
optbl[0xc1] = &bAPU::op_tcall_12;
optbl[0xd1] = &bAPU::op_tcall_13;
optbl[0xe1] = &bAPU::op_tcall_14;
optbl[0xf1] = &bAPU::op_tcall_15;
optbl[0x0f] = &bAPU::op_brk;
optbl[0x6f] = &bAPU::op_ret;
optbl[0x7f] = &bAPU::op_reti;
optbl[0x88] = &bAPU::op_adc_a_const;
optbl[0x28] = &bAPU::op_and_a_const;
optbl[0x68] = &bAPU::op_cmp_a_const;
optbl[0xc8] = &bAPU::op_cmp_x_const;
optbl[0xad] = &bAPU::op_cmp_y_const;
optbl[0x48] = &bAPU::op_eor_a_const;
optbl[0x08] = &bAPU::op_or_a_const;
optbl[0xa8] = &bAPU::op_sbc_a_const;
optbl[0x86] = &bAPU::op_adc_a_ix;
optbl[0x26] = &bAPU::op_and_a_ix;
optbl[0x66] = &bAPU::op_cmp_a_ix;
optbl[0x46] = &bAPU::op_eor_a_ix;
optbl[0x06] = &bAPU::op_or_a_ix;
optbl[0xa6] = &bAPU::op_sbc_a_ix;
optbl[0x84] = &bAPU::op_adc_a_dp;
optbl[0x24] = &bAPU::op_and_a_dp;
optbl[0x64] = &bAPU::op_cmp_a_dp;
optbl[0x3e] = &bAPU::op_cmp_x_dp;
optbl[0x7e] = &bAPU::op_cmp_y_dp;
optbl[0x44] = &bAPU::op_eor_a_dp;
optbl[0x04] = &bAPU::op_or_a_dp;
optbl[0xa4] = &bAPU::op_sbc_a_dp;
optbl[0x94] = &bAPU::op_adc_a_dpx;
optbl[0x34] = &bAPU::op_and_a_dpx;
optbl[0x74] = &bAPU::op_cmp_a_dpx;
optbl[0x54] = &bAPU::op_eor_a_dpx;
optbl[0x14] = &bAPU::op_or_a_dpx;
optbl[0xb4] = &bAPU::op_sbc_a_dpx;
optbl[0x85] = &bAPU::op_adc_a_addr;
optbl[0x25] = &bAPU::op_and_a_addr;
optbl[0x65] = &bAPU::op_cmp_a_addr;
optbl[0x1e] = &bAPU::op_cmp_x_addr;
optbl[0x5e] = &bAPU::op_cmp_y_addr;
optbl[0x45] = &bAPU::op_eor_a_addr;
optbl[0x05] = &bAPU::op_or_a_addr;
optbl[0xa5] = &bAPU::op_sbc_a_addr;
optbl[0x95] = &bAPU::op_adc_a_addrx;
optbl[0x96] = &bAPU::op_adc_a_addry;
optbl[0x35] = &bAPU::op_and_a_addrx;
optbl[0x36] = &bAPU::op_and_a_addry;
optbl[0x75] = &bAPU::op_cmp_a_addrx;
optbl[0x76] = &bAPU::op_cmp_a_addry;
optbl[0x55] = &bAPU::op_eor_a_addrx;
optbl[0x56] = &bAPU::op_eor_a_addry;
optbl[0x15] = &bAPU::op_or_a_addrx;
optbl[0x16] = &bAPU::op_or_a_addry;
optbl[0xb5] = &bAPU::op_sbc_a_addrx;
optbl[0xb6] = &bAPU::op_sbc_a_addry;
optbl[0x87] = &bAPU::op_adc_a_idpx;
optbl[0x27] = &bAPU::op_and_a_idpx;
optbl[0x67] = &bAPU::op_cmp_a_idpx;
optbl[0x47] = &bAPU::op_eor_a_idpx;
optbl[0x07] = &bAPU::op_or_a_idpx;
optbl[0xa7] = &bAPU::op_sbc_a_idpx;
optbl[0x97] = &bAPU::op_adc_a_idpy;
optbl[0x37] = &bAPU::op_and_a_idpy;
optbl[0x77] = &bAPU::op_cmp_a_idpy;
optbl[0x57] = &bAPU::op_eor_a_idpy;
optbl[0x17] = &bAPU::op_or_a_idpy;
optbl[0xb7] = &bAPU::op_sbc_a_idpy;
optbl[0x99] = &bAPU::op_adc_ix_iy;
optbl[0x39] = &bAPU::op_and_ix_iy;
optbl[0x79] = &bAPU::op_cmp_ix_iy;
optbl[0x59] = &bAPU::op_eor_ix_iy;
optbl[0x19] = &bAPU::op_or_ix_iy;
optbl[0xb9] = &bAPU::op_sbc_ix_iy;
optbl[0x89] = &bAPU::op_adc_dp_dp;
optbl[0x29] = &bAPU::op_and_dp_dp;
optbl[0x69] = &bAPU::op_cmp_dp_dp;
optbl[0x49] = &bAPU::op_eor_dp_dp;
optbl[0x09] = &bAPU::op_or_dp_dp;
optbl[0xa9] = &bAPU::op_sbc_dp_dp;
optbl[0x98] = &bAPU::op_adc_dp_const;
optbl[0x38] = &bAPU::op_and_dp_const;
optbl[0x78] = &bAPU::op_cmp_dp_const;
optbl[0x58] = &bAPU::op_eor_dp_const;
optbl[0x18] = &bAPU::op_or_dp_const;
optbl[0xb8] = &bAPU::op_sbc_dp_const;
optbl[0x7a] = &bAPU::op_addw_ya_dp;
optbl[0x5a] = &bAPU::op_cmpw_ya_dp;
optbl[0x9a] = &bAPU::op_subw_ya_dp;
optbl[0x4a] = &bAPU::op_and1_bit;
optbl[0x6a] = &bAPU::op_and1_notbit;
optbl[0x8a] = &bAPU::op_eor1_bit;
optbl[0xea] = &bAPU::op_not1_bit;
optbl[0x0a] = &bAPU::op_or1_bit;
optbl[0x2a] = &bAPU::op_or1_notbit;
optbl[0xbc] = &bAPU::op_inc_a;
optbl[0x3d] = &bAPU::op_inc_x;
optbl[0xfc] = &bAPU::op_inc_y;
optbl[0x9c] = &bAPU::op_dec_a;
optbl[0x1d] = &bAPU::op_dec_x;
optbl[0xdc] = &bAPU::op_dec_y;
optbl[0x1c] = &bAPU::op_asl_a;
optbl[0x5c] = &bAPU::op_lsr_a;
optbl[0x3c] = &bAPU::op_rol_a;
optbl[0x7c] = &bAPU::op_ror_a;
optbl[0xab] = &bAPU::op_inc_dp;
optbl[0x8b] = &bAPU::op_dec_dp;
optbl[0x0b] = &bAPU::op_asl_dp;
optbl[0x4b] = &bAPU::op_lsr_dp;
optbl[0x2b] = &bAPU::op_rol_dp;
optbl[0x6b] = &bAPU::op_ror_dp;
optbl[0xbb] = &bAPU::op_inc_dpx;
optbl[0x9b] = &bAPU::op_dec_dpx;
optbl[0x1b] = &bAPU::op_asl_dpx;
optbl[0x5b] = &bAPU::op_lsr_dpx;
optbl[0x3b] = &bAPU::op_rol_dpx;
optbl[0x7b] = &bAPU::op_ror_dpx;
optbl[0xac] = &bAPU::op_inc_addr;
optbl[0x8c] = &bAPU::op_dec_addr;
optbl[0x0c] = &bAPU::op_asl_addr;
optbl[0x4c] = &bAPU::op_lsr_addr;
optbl[0x2c] = &bAPU::op_rol_addr;
optbl[0x6c] = &bAPU::op_ror_addr;
optbl[0x3a] = &bAPU::op_incw_dp;
optbl[0x1a] = &bAPU::op_decw_dp;
optbl[0x00] = &bAPU::op_nop;
optbl[0xef] = &bAPU::op_sleep;
optbl[0xff] = &bAPU::op_stop;
optbl[0x9f] = &bAPU::op_xcn;
optbl[0xdf] = &bAPU::op_daa;
optbl[0xbe] = &bAPU::op_das;
optbl[0x60] = &bAPU::op_clrc;
optbl[0x20] = &bAPU::op_clrp;
optbl[0x80] = &bAPU::op_setc;
optbl[0x40] = &bAPU::op_setp;
optbl[0xe0] = &bAPU::op_clrv;
optbl[0xed] = &bAPU::op_notc;
optbl[0xa0] = &bAPU::op_ei;
optbl[0xc0] = &bAPU::op_di;
optbl[0x02] = &bAPU::op_set0_dp;
optbl[0x12] = &bAPU::op_clr0_dp;
optbl[0x22] = &bAPU::op_set1_dp;
optbl[0x32] = &bAPU::op_clr1_dp;
optbl[0x42] = &bAPU::op_set2_dp;
optbl[0x52] = &bAPU::op_clr2_dp;
optbl[0x62] = &bAPU::op_set3_dp;
optbl[0x72] = &bAPU::op_clr3_dp;
optbl[0x82] = &bAPU::op_set4_dp;
optbl[0x92] = &bAPU::op_clr4_dp;
optbl[0xa2] = &bAPU::op_set5_dp;
optbl[0xb2] = &bAPU::op_clr5_dp;
optbl[0xc2] = &bAPU::op_set6_dp;
optbl[0xd2] = &bAPU::op_clr6_dp;
optbl[0xe2] = &bAPU::op_set7_dp;
optbl[0xf2] = &bAPU::op_clr7_dp;
optbl[0x0e] = &bAPU::op_tset_addr_a;
optbl[0x4e] = &bAPU::op_tclr_addr_a;
optbl[0x2d] = &bAPU::op_push_a;
optbl[0x4d] = &bAPU::op_push_x;
optbl[0x6d] = &bAPU::op_push_y;
optbl[0x0d] = &bAPU::op_push_p;
optbl[0xae] = &bAPU::op_pop_a;
optbl[0xce] = &bAPU::op_pop_x;
optbl[0xee] = &bAPU::op_pop_y;
optbl[0x8e] = &bAPU::op_pop_p;
optbl[0xcf] = &bAPU::op_mul_ya;
optbl[0x9e] = &bAPU::op_div_ya_x;

View File

@ -1,306 +0,0 @@
//virtual function, see src/cpu/dcpu.cpp
//for explanation of this function
bool APU::in_opcode() { return false; }
uint16 APU::__relb(int8 offset, int op_len) {
uint16 pc = regs.pc + op_len;
return pc + offset;
}
void APU::disassemble_opcode(char *output) {
char *s, t[512];
uint8 op, op0, op1;
uint16 opw, opdp0, opdp1;
s = output;
if(in_opcode() == true) {
strcpy(s, "..???? <APU within opcode>");
return;
}
sprintf(s, "..%0.4x ", regs.pc);
op = spcram_read(regs.pc);
op0 = spcram_read(regs.pc + 1);
op1 = spcram_read(regs.pc + 2);
opw = (op0) | (op1 << 8);
opdp0 = ((regs.p.p)?0x100:0x000) + op0;
opdp1 = ((regs.p.p)?0x100:0x000) + op1;
strcpy(t, " ");
switch(op) {
case 0x00:sprintf(t, "nop"); break;
case 0x01:sprintf(t, "tcall 0"); break;
case 0x02:sprintf(t, "set0 $%0.3x", opdp0); break;
case 0x03:sprintf(t, "bbs0 $%0.3x,$%0.4x", opdp0, __relb(op1, 3)); break;
case 0x04:sprintf(t, "or a,$%0.3x", opdp0); break;
case 0x05:sprintf(t, "or a,$%0.4x", opw); break;
case 0x06:sprintf(t, "or a,(x)"); break;
case 0x07:sprintf(t, "or a,($%0.3x+x)", opdp0); break;
case 0x08:sprintf(t, "or a,#$%0.2x", op0); break;
case 0x09:sprintf(t, "or $%0.3x,$%0.3x", opdp1, opdp0); break;
case 0x0a:sprintf(t, "or1 c,$%0.4x:%d", opw & 0x1fff, opw >> 13); break;
case 0x0b:sprintf(t, "asl $%0.3x", opdp0); break;
case 0x0c:sprintf(t, "asl $%0.4x", opw); break;
case 0x0d:sprintf(t, "push p"); break;
case 0x0e:sprintf(t, "tset $%0.4x,a", opw); break;
case 0x0f:sprintf(t, "brk"); break;
case 0x10:sprintf(t, "bpl $%0.4x", __relb(op0, 2)); break;
case 0x11:sprintf(t, "tcall 1"); break;
case 0x12:sprintf(t, "clr0 $%0.3x", opdp0); break;
case 0x13:sprintf(t, "bbc0 $%0.3x,$%0.4x", opdp0, __relb(op1, 3)); break;
case 0x14:sprintf(t, "or a,$%0.3x+x", opdp0); break;
case 0x15:sprintf(t, "or a,$%0.4x+x", opw); break;
case 0x16:sprintf(t, "or a,$%0.4x+y", opw); break;
case 0x17:sprintf(t, "or a,($%0.3x)+y", opdp0); break;
case 0x18:sprintf(t, "or $%0.3x,#$%0.2x", opdp1, op0); break;
case 0x19:sprintf(t, "or (x),(y)"); break;
case 0x1a:sprintf(t, "decw $%0.3x", opdp0); break;
case 0x1b:sprintf(t, "asl $%0.3x+x", opdp0); break;
case 0x1c:sprintf(t, "asl a"); break;
case 0x1d:sprintf(t, "dec x"); break;
case 0x1e:sprintf(t, "cmp x,$%0.4x", opw); break;
case 0x1f:sprintf(t, "jmp ($%0.4x+x)", opw); break;
case 0x20:sprintf(t, "clrp"); break;
case 0x21:sprintf(t, "tcall 2"); break;
case 0x22:sprintf(t, "set1 $%0.3x", opdp0); break;
case 0x23:sprintf(t, "bbs1 $%0.3x,$%0.4x", opdp0, __relb(op1, 3)); break;
case 0x24:sprintf(t, "and a,$%0.3x", opdp0); break;
case 0x25:sprintf(t, "and a,$%0.4x", opw); break;
case 0x26:sprintf(t, "and a,(x)"); break;
case 0x27:sprintf(t, "and a,($%0.3x+x)", opdp0); break;
case 0x28:sprintf(t, "and a,#$%0.2x", op0); break;
case 0x29:sprintf(t, "and $%0.3x,$%0.3x", opdp1, opdp0); break;
case 0x2a:sprintf(t, "or1 c,!$%0.4x:%d", opw & 0x1fff, opw >> 13); break;
case 0x2b:sprintf(t, "rol $%0.3x", opdp0); break;
case 0x2c:sprintf(t, "rol $%0.4x", opw); break;
case 0x2d:sprintf(t, "push a"); break;
case 0x2e:sprintf(t, "cbne $%0.3x,$%0.4x", opdp0, __relb(op1, 3)); break;
case 0x2f:sprintf(t, "bra $%0.4x", __relb(op0, 2)); break;
case 0x30:sprintf(t, "bmi $%0.4x", __relb(op0, 2)); break;
case 0x31:sprintf(t, "tcall 3"); break;
case 0x32:sprintf(t, "clr1 $%0.3x", opdp0); break;
case 0x33:sprintf(t, "bbc1 $%0.3x,$%0.4x", opdp0, __relb(op1, 3)); break;
case 0x34:sprintf(t, "and a,$%0.3x+x", opdp0); break;
case 0x35:sprintf(t, "and a,$%0.4x+x", opw); break;
case 0x36:sprintf(t, "and a,$%0.4x+y", opw); break;
case 0x37:sprintf(t, "and a,($%0.3x)+y", opdp0); break;
case 0x38:sprintf(t, "and $%0.3x,#$%0.2x", opdp1, op0); break;
case 0x39:sprintf(t, "and (x),(y)"); break;
case 0x3a:sprintf(t, "incw $%0.3x", opdp0); break;
case 0x3b:sprintf(t, "rol $%0.3x+x", opdp0); break;
case 0x3c:sprintf(t, "rol a"); break;
case 0x3d:sprintf(t, "inc x"); break;
case 0x3e:sprintf(t, "cmp x,$%0.3x", opdp0); break;
case 0x3f:sprintf(t, "call $%0.4x", opw); break;
case 0x40:sprintf(t, "setp"); break;
case 0x41:sprintf(t, "tcall 4"); break;
case 0x42:sprintf(t, "set2 $%0.3x", opdp0); break;
case 0x43:sprintf(t, "bbs2 $%0.3x,$%0.4x", opdp0, __relb(op1, 3)); break;
case 0x44:sprintf(t, "eor a,$%0.3x", opdp0); break;
case 0x45:sprintf(t, "eor a,$%0.4x", opw); break;
case 0x46:sprintf(t, "eor a,(x)"); break;
case 0x47:sprintf(t, "eor a,($%0.3x+x)", opdp0); break;
case 0x48:sprintf(t, "eor a,#$%0.2x", op0); break;
case 0x49:sprintf(t, "eor $%0.3x,$%0.3x", opdp1, opdp0); break;
case 0x4a:sprintf(t, "and1 c,$%0.4x:%d", opw & 0x1fff, opw >> 13); break;
case 0x4b:sprintf(t, "lsr $%0.3x", opdp0); break;
case 0x4c:sprintf(t, "lsr $%0.4x", opw); break;
case 0x4d:sprintf(t, "push x"); break;
case 0x4e:sprintf(t, "tclr $%0.4x,a", opw); break;
case 0x4f:sprintf(t, "pcall $ff%0.2x", op0); break;
case 0x50:sprintf(t, "bvc $%0.4x", __relb(op0, 2)); break;
case 0x51:sprintf(t, "tcall 5"); break;
case 0x52:sprintf(t, "clr2 $%0.3x", opdp0); break;
case 0x53:sprintf(t, "bbc2 $%0.3x,$%0.4x", opdp0, __relb(op1, 3)); break;
case 0x54:sprintf(t, "eor a,$%0.3x+x", opdp0); break;
case 0x55:sprintf(t, "eor a,$%0.4x+x", opw); break;
case 0x56:sprintf(t, "eor a,$%0.4x+y", opw); break;
case 0x57:sprintf(t, "eor a,($%0.3x)+y", opdp0); break;
case 0x58:sprintf(t, "eor $%0.3x,#$%0.2x", opdp1, op0); break;
case 0x59:sprintf(t, "eor (x),(y)"); break;
case 0x5a:sprintf(t, "cmpw ya,$%0.3x", opdp0); break;
case 0x5b:sprintf(t, "lsr $%0.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,$%0.4x", opw); break;
case 0x5f:sprintf(t, "jmp $%0.4x", opw); break;
case 0x60:sprintf(t, "clrc"); break;
case 0x61:sprintf(t, "tcall 6"); break;
case 0x62:sprintf(t, "set3 $%0.3x", opdp0); break;
case 0x63:sprintf(t, "bbs3 $%0.3x,$%0.4x", opdp0, __relb(op1, 3)); break;
case 0x64:sprintf(t, "cmp a,$%0.3x", opdp0); break;
case 0x65:sprintf(t, "cmp a,$%0.4x", opw); break;
case 0x66:sprintf(t, "cmp a,(x)"); break;
case 0x67:sprintf(t, "cmp a,($%0.3x+x)", opdp0); break;
case 0x68:sprintf(t, "cmp a,#$%0.2x", op0); break;
case 0x69:sprintf(t, "cmp $%0.3x,$%0.3x", opdp1, opdp0); break;
case 0x6a:sprintf(t, "and1 c,!$%0.4x:%d", opw & 0x1fff, opw >> 13); break;
case 0x6b:sprintf(t, "ror $%0.3x", opdp0); break;
case 0x6c:sprintf(t, "ror $%0.4x", opw); break;
case 0x6d:sprintf(t, "push y"); break;
case 0x6e:sprintf(t, "dbnz $%0.3x,$%0.4x", opdp0, __relb(op1, 3)); break;
case 0x6f:sprintf(t, "ret"); break;
case 0x70:sprintf(t, "bvs $%0.4x", __relb(op0, 2)); break;
case 0x71:sprintf(t, "tcall 7"); break;
case 0x72:sprintf(t, "clr3 $%0.3x", opdp0); break;
case 0x73:sprintf(t, "bbc3 $%0.3x,$%0.4x", opdp0, __relb(op1, 3)); break;
case 0x74:sprintf(t, "cmp a,$%0.3x+x", opdp0); break;
case 0x75:sprintf(t, "cmp a,$%0.4x+x", opw); break;
case 0x76:sprintf(t, "cmp a,$%0.4x+y", opw); break;
case 0x77:sprintf(t, "cmp a,($%0.3x)+y", opdp0); break;
case 0x78:sprintf(t, "cmp $%0.3x,#$%0.2x", opdp1, op0); break;
case 0x79:sprintf(t, "cmp (x),(y)"); break;
case 0x7a:sprintf(t, "addw ya,$%0.3x", opdp0); break;
case 0x7b:sprintf(t, "ror $%0.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,$%0.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 $%0.3x", opdp0); break;
case 0x83:sprintf(t, "bbs4 $%0.3x,$%0.4x", opdp0, __relb(op1, 3)); break;
case 0x84:sprintf(t, "adc a,$%0.3x", opdp0); break;
case 0x85:sprintf(t, "adc a,$%0.4x", opw); break;
case 0x86:sprintf(t, "adc a,(x)"); break;
case 0x87:sprintf(t, "adc a,($%0.3x+x)", opdp0); break;
case 0x88:sprintf(t, "adc a,#$%0.2x", op0); break;
case 0x89:sprintf(t, "adc $%0.3x,$%0.3x", opdp1, opdp0); break;
case 0x8a:sprintf(t, "eor1 c,$%0.4x:%d", opw & 0x1fff, opw >> 13); break;
case 0x8b:sprintf(t, "dec $%0.3x", opdp0); break;
case 0x8c:sprintf(t, "dec $%0.4x", opw); break;
case 0x8d:sprintf(t, "mov y,#$%0.2x", op0); break;
case 0x8e:sprintf(t, "pop p"); break;
case 0x8f:sprintf(t, "mov $%0.3x,#$%0.2x", opdp1, op0); break;
case 0x90:sprintf(t, "bcc $%0.4x", __relb(op0, 2)); break;
case 0x91:sprintf(t, "tcall 9"); break;
case 0x92:sprintf(t, "clr4 $%0.3x", opdp0); break;
case 0x93:sprintf(t, "bbc4 $%0.3x,$%0.4x", opdp0, __relb(op1, 3)); break;
case 0x94:sprintf(t, "adc a,$%0.3x+x", opdp0); break;
case 0x95:sprintf(t, "adc a,$%0.4x+x", opw); break;
case 0x96:sprintf(t, "adc a,$%0.4x+y", opw); break;
case 0x97:sprintf(t, "adc a,($%0.3x)+y", opdp0); break;
case 0x98:sprintf(t, "adc $%0.3x,#$%0.2x", opdp1, op0); break;
case 0x99:sprintf(t, "adc (x),(y)"); break;
case 0x9a:sprintf(t, "subw ya,$%0.3x", opdp0); break;
case 0x9b:sprintf(t, "dec $%0.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 $%0.3x", opdp0); break;
case 0xa3:sprintf(t, "bbs5 $%0.3x,$%0.4x", opdp0, __relb(op1, 3)); break;
case 0xa4:sprintf(t, "sbc a,$%0.3x", opdp0); break;
case 0xa5:sprintf(t, "sbc a,$%0.4x", opw); break;
case 0xa6:sprintf(t, "sbc a,(x)"); break;
case 0xa7:sprintf(t, "sbc a,($%0.3x+x)", opdp0); break;
case 0xa8:sprintf(t, "sbc a,#$%0.2x", op0); break;
case 0xa9:sprintf(t, "sbc $%0.3x,$%0.3x", opdp1, opdp0); break;
case 0xaa:sprintf(t, "mov1 c,$%0.4x:%d", opw & 0x1fff, opw >> 13); break;
case 0xab:sprintf(t, "inc $%0.3x", opdp0); break;
case 0xac:sprintf(t, "inc $%0.4x", opw); break;
case 0xad:sprintf(t, "cmp y,#$%0.2x", op0); break;
case 0xae:sprintf(t, "pop a"); break;
case 0xaf:sprintf(t, "mov (x)+,a"); break;
case 0xb0:sprintf(t, "bcs $%0.4x", __relb(op0, 2)); break;
case 0xb1:sprintf(t, "tcall 11"); break;
case 0xb2:sprintf(t, "clr5 $%0.3x", opdp0); break;
case 0xb3:sprintf(t, "bbc5 $%0.3x,$%0.4x", opdp0, __relb(op1, 3)); break;
case 0xb4:sprintf(t, "sbc a,$%0.3x+x", opdp0); break;
case 0xb5:sprintf(t, "sbc a,$%0.4x+x", opw); break;
case 0xb6:sprintf(t, "sbc a,$%0.4x+y", opw); break;
case 0xb7:sprintf(t, "sbc a,($%0.3x)+y", opdp0); break;
case 0xb8:sprintf(t, "sbc $%0.3x,#$%0.2x", opdp1, op0); break;
case 0xb9:sprintf(t, "sbc (x),(y)"); break;
case 0xba:sprintf(t, "movw ya,$%0.3x", opdp0); break;
case 0xbb:sprintf(t, "inc $%0.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 $%0.3x", opdp0); break;
case 0xc3:sprintf(t, "bbs6 $%0.3x,$%0.4x", opdp0, __relb(op1, 3)); break;
case 0xc4:sprintf(t, "mov $%0.3x,a", opdp0); break;
case 0xc5:sprintf(t, "mov $%0.4x,a", opw); break;
case 0xc6:sprintf(t, "mov (x),a"); break;
case 0xc7:sprintf(t, "mov ($%0.3x+x),a", opdp0); break;
case 0xc8:sprintf(t, "cmp x,#$%0.2x", op0); break;
case 0xc9:sprintf(t, "mov $%0.4x,x", opw); break;
case 0xca:sprintf(t, "mov1 $%0.4x:%d,c", opw & 0x1fff, opw >> 13); break;
case 0xcb:sprintf(t, "mov $%0.3x,y", opdp0); break;
case 0xcc:sprintf(t, "mov $%0.4x,y", opw); break;
case 0xcd:sprintf(t, "mov x,#$%0.2x", op0); break;
case 0xce:sprintf(t, "pop x"); break;
case 0xcf:sprintf(t, "mul ya"); break;
case 0xd0:sprintf(t, "bne $%0.4x", __relb(op0, 2)); break;
case 0xd1:sprintf(t, "tcall 13"); break;
case 0xd2:sprintf(t, "clr6 $%0.3x", opdp0); break;
case 0xd3:sprintf(t, "bbc6 $%0.3x,$%0.4x", opdp0, __relb(op1, 3)); break;
case 0xd4:sprintf(t, "mov $%0.3x+x,a", opdp0); break;
case 0xd5:sprintf(t, "mov $%0.4x+x,a", opw); break;
case 0xd6:sprintf(t, "mov $%0.4x+y,a", opw); break;
case 0xd7:sprintf(t, "mov ($%0.3x)+y,a", opdp0); break;
case 0xd8:sprintf(t, "mov $%0.3x,x", opdp0); break;
case 0xd9:sprintf(t, "mov $%0.3x+y,x", opdp0); break;
case 0xda:sprintf(t, "movw $%0.3x,ya", opdp0); break;
case 0xdb:sprintf(t, "mov $%0.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 $%0.3x+x,$%0.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 $%0.3x", opdp0); break;
case 0xe3:sprintf(t, "bbs7 $%0.3x,$%0.4x", opdp0, __relb(op1, 3)); break;
case 0xe4:sprintf(t, "mov a,$%0.3x", opdp0); break;
case 0xe5:sprintf(t, "mov a,$%0.4x", opw); break;
case 0xe6:sprintf(t, "mov a,(x)"); break;
case 0xe7:sprintf(t, "mov a,($%0.3x+x)", opdp0); break;
case 0xe8:sprintf(t, "mov a,#$%0.2x", op0); break;
case 0xe9:sprintf(t, "mov x,$%0.4x", opw); break;
case 0xea:sprintf(t, "not1 c,$%0.4x:%d", opw & 0x1fff, opw >> 13); break;
case 0xeb:sprintf(t, "mov y,$%0.3x", opdp0); break;
case 0xec:sprintf(t, "mov y,$%0.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 $%0.4x", __relb(op0, 2)); break;
case 0xf1:sprintf(t, "tcall 15"); break;
case 0xf2:sprintf(t, "clr7 $%0.3x", opdp0); break;
case 0xf3:sprintf(t, "bbc7 $%0.3x,$%0.4x", opdp0, __relb(op1, 3)); break;
case 0xf4:sprintf(t, "mov a,$%0.3x+x", opdp0); break;
case 0xf5:sprintf(t, "mov a,$%0.4x+x", opw); break;
case 0xf6:sprintf(t, "mov a,$%0.4x+y", opw); break;
case 0xf7:sprintf(t, "mov a,($%0.3x)+y", opdp0); break;
case 0xf8:sprintf(t, "mov x,$%0.3x", opdp0); break;
case 0xf9:sprintf(t, "mov x,$%0.3x+y", opdp0); break;
case 0xfa:sprintf(t, "mov $%0.3x,$%0.3x", opdp1, opdp0); break;
case 0xfb:sprintf(t, "mov y,$%0.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,$%0.4x", __relb(op0, 2)); break;
case 0xff:sprintf(t, "stop"); break;
}
t[strlen(t)] = ' ';
strcat(s, t);
sprintf(t, "A:%0.2x X:%0.2x Y:%0.2x SP:01%0.2x YA:%0.4x ",
regs.a, regs.x, regs.y, regs.sp, 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);
}

View File

@ -1,3 +0,0 @@
cl /O2 /wd4996 sapugen.cpp
@pause
@del *.obj

View File

@ -1,201 +0,0 @@
uint8 sAPU::spcram_read(uint16 addr) {
uint8 r;
if((addr & 0xfff0) == 0x00f0) {
//addr >= 0x00f0 && addr <= 0x00ff
#ifdef FAVOR_SPEED
co_return();
#endif
switch(addr) {
case 0xf0: //TEST -- operation unknown, supposedly returns 0x00
r = 0x00;
break;
case 0xf1: //CONTROL -- write-only register, always returns 0x00
r = 0x00;
break;
case 0xf2: //DSPADDR
r = status.dsp_addr;
break;
case 0xf3: //DSPDATA
//0x80-0xff is a read-only mirror of 0x00-0x7f
r = r_dsp->read(status.dsp_addr & 0x7f);
break;
case 0xf4: //CPUIO0
case 0xf5: //CPUIO1
case 0xf6: //CPUIO2
case 0xf7: //CPUIO3
r = r_cpu->port_read(addr & 3);
break;
case 0xf8: //???
case 0xf9: //??? -- Mapped to SPCRAM
r = spcram[addr];
break;
case 0xfa: //T0TARGET
case 0xfb: //T1TARGET
case 0xfc: //T2TARGET -- write-only registers, always return 0x00
r = 0x00;
break;
case 0xfd: //T0OUT -- 4-bit counter value
r = t0.stage3_ticks & 15;
t0.stage3_ticks = 0;
break;
case 0xfe: //T1OUT -- 4-bit counter value
r = t1.stage3_ticks & 15;
t1.stage3_ticks = 0;
break;
case 0xff: //T2OUT -- 4-bit counter value
r = t2.stage3_ticks & 15;
t2.stage3_ticks = 0;
break;
}
} else if(addr < 0xffc0) {
r = spcram[addr];
} else {
if(status.iplrom_enabled == true) {
r = iplrom[addr & 0x3f];
} else {
r = spcram[addr];
}
}
#ifdef DEBUGGER
snes->notify(SNES::SPCRAM_READ, addr, r);
#endif
return r;
}
void sAPU::spcram_write(uint16 addr, uint8 data) {
if((addr & 0xfff0) == 0x00f0) {
//addr >= 0x00f0 && addr >= 0x00ff
#ifdef FAVOR_SPEED
co_return();
#endif
switch(addr) {
case 0xf0: //TEST -- operation unknown
break;
case 0xf1: //CONTROL
status.iplrom_enabled = !!(data & 0x80);
//one-time clearing of APU port read registers,
//emulated by simulating CPU writes of 0x00
if(data & 0x20) {
r_cpu->port_write(2, 0x00);
r_cpu->port_write(3, 0x00);
}
if(data & 0x10) {
r_cpu->port_write(0, 0x00);
r_cpu->port_write(1, 0x00);
}
//0->1 transistion resets timers
if(t2.enabled == false && (data & 0x04)) {
t2.stage2_ticks = 0;
t2.stage3_ticks = 0;
}
t2.enabled = !!(data & 0x04);
if(t1.enabled == false && (data & 0x02)) {
t1.stage2_ticks = 0;
t1.stage3_ticks = 0;
}
t1.enabled = !!(data & 0x02);
if(t0.enabled == false && (data & 0x01)) {
t0.stage2_ticks = 0;
t0.stage3_ticks = 0;
}
t0.enabled = !!(data & 0x01);
break;
case 0xf2: //DSPADDR
status.dsp_addr = data;
break;
case 0xf3: //DSPDATA
//0x80-0xff is a read-only mirror of 0x00-0x7f
if(status.dsp_addr < 0x80) {
r_dsp->write(status.dsp_addr & 0x7f, data);
}
break;
case 0xf4: //CPUIO0
case 0xf5: //CPUIO1
case 0xf6: //CPUIO2
case 0xf7: //CPUIO3
port_write(addr & 3, data);
break;
case 0xf8: //???
case 0xf9: //??? - Mapped to SPCRAM
spcram[addr] = data;
break;
case 0xfa: //T0TARGET
t0.target = data;
break;
case 0xfb: //T1TARGET
t1.target = data;
break;
case 0xfc: //T2TARGET
t2.target = data;
break;
case 0xfd: //T0OUT
case 0xfe: //T1OUT
case 0xff: //T2OUT -- read-only registers
break;
}
} else {
//writes to $ffc0-$ffff always go to spcram,
//even if the iplrom is enabled.
spcram[addr] = data;
}
#ifdef DEBUGGER
snes->notify(SNES::SPCRAM_WRITE, addr, data);
#endif
}
uint8 sAPU::port_read(uint8 port) {
return spcram[0xf4 + (port & 3)];
}
void sAPU::port_write(uint8 port, uint8 data) {
spcram[0xf4 + (port & 3)] = data;
}
//
void sAPU::op_io() {
add_clocks(24);
tick_timers();
//co_return();
}
uint8 sAPU::op_read(uint16 addr) {
add_clocks(8);
#ifdef FAVOR_ACCURACY
co_return();
#endif
uint8 r = spcram_read(addr);
add_clocks(16);
tick_timers();
return r;
}
void sAPU::op_write(uint16 addr, uint8 data) {
add_clocks(24);
tick_timers();
#ifdef FAVOR_ACCURACY
co_return();
#endif
spcram_write(addr, data);
}
//
uint8 sAPU::op_readpc () { return op_read(regs.pc++); }
uint8 sAPU::op_readstack () { return op_read(0x0100 | ++regs.sp); }
void sAPU::op_writestack(uint8 data) { op_write(0x0100 | regs.sp--, data); }
uint8 sAPU::op_readaddr (uint16 addr) { return op_read(addr); }
void sAPU::op_writeaddr (uint16 addr, uint8 data) { op_write(addr, data); }
uint8 sAPU::op_readdp (uint8 addr) { return op_read((uint(regs.p.p) << 8) + addr); }
void sAPU::op_writedp (uint8 addr, uint8 data) { op_write((uint(regs.p.p) << 8) + addr, data); }

View File

@ -1,24 +0,0 @@
uint8 spcram_read (uint16 addr);
void spcram_write(uint16 addr, uint8 data);
uint8 port_read (uint8 port);
void port_write(uint8 port, uint8 data);
/*****
* core APU bus functions
*****/
inline void op_io ();
inline uint8 op_read (uint16 addr);
inline void op_write(uint16 addr, uint8 data);
/*****
* helper memory addressing functions used by APU core
*****/
inline uint8 op_readpc ();
inline uint8 op_readstack ();
inline void op_writestack(uint8 data);
inline uint8 op_readaddr (uint16 addr);
inline void op_writeaddr (uint16 addr, uint8 data);
inline uint8 op_readdp (uint8 addr);
inline void op_writedp (uint8 addr, uint8 data);

View File

@ -1,35 +0,0 @@
void sAPU::add_clocks(int clocks) {
status.clocks_executed += clocks;
}
uint32 sAPU::clocks_executed() {
uint32 r = status.clocks_executed;
status.clocks_executed = 0;
return r;
}
//occurs once every 24 clocks (once every APU opcode cycle)
void sAPU::tick_timers() {
t0.tick();
t1.tick();
t2.tick();
}
void sAPU::sAPUTimer::tick() {
//stage 1 increment
stage1_ticks++;
if(stage1_ticks < cycle_frequency)return;
stage1_ticks -= cycle_frequency;
if(enabled == false)return;
//stage 2 increment
stage2_ticks++;
if(stage2_ticks != target)return;
//stage 3 increment
stage2_ticks = 0;
stage3_ticks++;
stage3_ticks &= 15;
}

View File

@ -1,11 +0,0 @@
class sAPUTimer {
public:
uint8 cycle_frequency, target;
uint8 stage1_ticks, stage2_ticks, stage3_ticks;
bool enabled;
inline void tick();
} t0, t1, t2;
inline void add_clocks(int clocks);
inline void tick_timers();
uint32 clocks_executed();

View File

@ -1,9 +1,9 @@
#define BSNES_VERSION "0.017"
#define BSNES_VERSION "0.018"
#define BSNES_TITLE "bsnes v" BSNES_VERSION
#define MEMCORE bMemBus
#define CPUCORE sCPU
#define APUCORE sAPU
#define SMPCORE sSMP
#define DSPCORE bDSP
#define PPUCORE bPPU
@ -19,11 +19,8 @@
//enable JMA support
#define JMA_SUPPORT
//debugging extensions (~10% speed hit)
//#define DEBUGGER
//snes core polymorphism
//(allow mem/cpu/apu/ppu overriding, ~10% speed hit)
//(allow runtime cpu/smp/dsp/ppu/bus selection, ~10% speed hit)
//#define POLYMORPHISM
#if defined(PROCESSOR_X86)
@ -38,7 +35,10 @@
#include "lib/libbase.h"
#include "lib/libco_x86.h"
#include "lib/libarray.h"
#include "lib/libvector.h"
#include "lib/libfile.h"
#include "lib/libups.h"
#include "lib/libstring.h"
#include "lib/libconfig.h"
@ -60,7 +60,10 @@ namespace source {
none = 0,
debug,
cpu,
apu,
ppu,
smp,
dsp,
bus,
};
};

View File

@ -1,6 +1,8 @@
#include "../base.h"
#include "database.cpp"
Cartridge cartridge;
void Cartridge::read_dbi() {
info.srtc = false;
info.sdd1 = false;
@ -204,8 +206,17 @@ bool header = ((size & 0x7fff) == 512);
if(info.rom_size & 0x7fff) {
info.rom_size += 0x8000 - (info.rom_size & 0x7fff);
}
base_rom = rf.read(info.rom_size + (header ? 512 : 0));
rom = base_rom + (header ? 512 : 0);
uint8 *base_rom = rf.read(info.rom_size + (header ? 512 : 0));
if(header) {
memcpy(rom_header, base_rom, 512);
} else {
memset(rom_header, 0x00, 512);
}
rom = (uint8*)malloc(info.rom_size);
memcpy(rom, base_rom + (header ? 512 : 0), info.rom_size);
SafeFree(base_rom);
info.crc32 = 0xffffffff;
for(int32 i = 0; i < info.rom_size; i++) {
@ -214,6 +225,27 @@ bool header = ((size & 0x7fff) == 512);
info.crc32 = ~info.crc32;
}
void Cartridge::patch_rom(Reader &rf) {
UPS<ramfile, ramfile, ramfile> ups;
uint patchsize = rf.size();
uint8 *patchdata = rf.read();
fopen(ups.original, 0, file::mode_writeread);
fopen(ups.modified, 0, file::mode_writeread);
fopen(ups.patch.fp, 0, file::mode_writeread);
fwrite(ups.original, rom, info.rom_size);
fwrite(ups.patch.fp, patchdata, patchsize);
if(ups.apply() == true) {
info.crc32 = ups.modified_crc32;
info.rom_size = ups.modified_filesize;
rom = (uint8*)realloc(rom, info.rom_size);
fseek(ups.modified, 0, file::seek_start);
fread(ups.modified, rom, info.rom_size);
}
}
bool Cartridge::load(const char *fn) {
if(cart_loaded == true)return false;
if(strlen(fn) < 3)return false;
@ -223,6 +255,7 @@ bool Cartridge::load(const char *fn) {
strcpy(rom_fn, fn);
switch(Reader::detect(rom_fn)) {
case Reader::RF_NORMAL: {
FileReader ff(rom_fn);
if(!ff.ready()) {
@ -230,8 +263,8 @@ bool Cartridge::load(const char *fn) {
return false;
}
load_rom(ff);
break;
}
} break;
#ifdef GZIP_SUPPORT
case Reader::RF_GZ: {
GZReader gf(rom_fn);
@ -240,14 +273,14 @@ bool Cartridge::load(const char *fn) {
return false;
}
load_rom(gf);
break;
}
} break;
case Reader::RF_ZIP: {
ZipReader zf(rom_fn);
load_rom(zf);
break;
}
} break;
#endif
#ifdef JMA_SUPPORT
case Reader::RF_JMA: {
try {
@ -257,9 +290,9 @@ bool Cartridge::load(const char *fn) {
alert("Error loading image file (%s)!", rom_fn);
return false;
}
break;
}
} break;
#endif
}
//remove ROM extension
@ -275,16 +308,20 @@ bool Cartridge::load(const char *fn) {
strcat(sram_fn, ".");
strcat(sram_fn, config::fs.save_ext.sget());
//override default path (current directory)?
if(strmatch(config::fs.save_path.sget(), "") == false) {
//remove path if fs.sram_path was specified
string new_fn, parts;
stringarray save_path;
strcpy(save_path, config::fs.save_path.sget());
replace(save_path, "\\", "/");
if(strlen(save_path) && !strend(save_path, "/")) { strcat(save_path, "/"); }
if(strlen(save_path) != 0) {
//override default path (current directory)
stringarray new_fn, parts;
strcpy(new_fn, sram_fn);
replace(new_fn, "\\", "/");
split(parts, "/", new_fn);
//add new SRAM path
strcpy(new_fn, config::fs.save_path.sget());
strcpy(new_fn, save_path);
//append fs.base_path if fs.sram_path is not fully-qualified path
if(strbegin(new_fn, "./") == true) {
@ -304,11 +341,34 @@ bool Cartridge::load(const char *fn) {
strrtrim(cheat_fn, config::fs.save_ext.sget());
strrtrim(cheat_fn, ".");
strcat(cheat_fn, ".cht");
if(fexists(cheat_fn) == true) {
FileReader ff(cheat_fn);
cheat.load(ff);
}
//load patch file if it exists
strcpy(patch_fn, sram_fn);
strrtrim(patch_fn, config::fs.save_ext.sget());
strrtrim(patch_fn, ".");
strcat(patch_fn, ".ups");
if(fexists(patch_fn) == true) {
FileReader ff(patch_fn);
patch_rom(ff);
}
#ifdef GZIP_SUPPORT
else {
strrtrim(patch_fn, ".ups");
strcat(patch_fn, ".upz");
if(fexists(patch_fn) == true) {
ZipReader zf(patch_fn);
patch_rom(zf);
}
}
#endif
if(read_database() == true) {
read_dbi();
} else {
@ -328,14 +388,9 @@ bool Cartridge::unload() {
r_mem->unload_cart();
if(base_rom) {
SafeFree(base_rom);
}
if(sram) {
save_sram();
SafeFree(sram);
}
if(sram) { save_sram(); }
SafeFree(rom);
SafeFree(sram);
if(cheat.count() > 0 || fexists(cheat_fn)) {
FileWriter ff(cheat_fn);
@ -352,9 +407,8 @@ Cartridge::Cartridge() {
cart_loaded = false;
base_rom = 0;
rom = 0;
sram = 0;
rom = 0;
sram = 0;
}
Cartridge::~Cartridge() {

View File

@ -18,7 +18,7 @@ db_item dbi;
bool cart_loaded;
char rom_fn[4096], sram_fn[4096], cheat_fn[4096], patch_fn[4096];
uint8 *base_rom, *rom, *sram;
uint8 rom_header[512], *rom, *sram;
enum {
//header fields
@ -79,6 +79,7 @@ struct {
} info;
void load_rom(Reader &rf);
void patch_rom(Reader &rf);
void load_sram();
void save_sram();
void read_dbi();

View File

@ -1,5 +1,7 @@
#include "../base.h"
Cheat cheat;
/*****
* string <> binary code translation routines
* decode() "7e1234:56" -> 0x7e123456
@ -7,7 +9,7 @@
*****/
bool Cheat::decode(char *str, uint32 &addr, uint8 &data, uint8 &type) {
string t, part;
stringarray t, part;
strcpy(t, str);
strlower(t);
if(strlen(t) == 8 || (strlen(t) == 9 && strptr(t)[6] == ':')) {
@ -270,15 +272,15 @@ bool Cheat::load(Reader &rf) {
if(!rf.ready())return false;
uint8 *raw_data = rf.read();
string data;
stringarray data, line;
raw_data[rf.size()] = 0;
strcpy(data, (char*)raw_data);
SafeFree(raw_data);
replace(data, "\r\n", "\n");
string line;
split(line, "\n", data);
for(int i = 0; i < ::count(line); i++) {
string part;
stringarray part;
uint8 en = *(strptr(line[i]));
if(en == '+') {
strltrim(line[i], "+");

View File

@ -7,6 +7,8 @@
#include "../../base.h"
C4 *c4;
#include "c4data.cpp"
#include "c4fn.cpp"
#include "c4oam.cpp"

View File

@ -92,3 +92,5 @@ public:
C4();
};
extern C4 *c4;

View File

@ -1,4 +1,7 @@
#include "../../base.h"
DSP1 *dsp1;
#include "dsp1emu.cpp"
void DSP1::init() {}

View File

@ -14,3 +14,5 @@ public:
uint8 read (uint16 addr);
void write(uint16 addr, uint8 data);
};
extern DSP1 *dsp1;

View File

@ -1,4 +1,7 @@
#include "../../base.h"
DSP2 *dsp2;
#include "dsp2_op.cpp"
void DSP2::init() {}

View File

@ -39,3 +39,5 @@ struct {
DSP2();
~DSP2();
};
extern DSP2 *dsp2;

View File

@ -1,5 +1,7 @@
#include "../../base.h"
OBC1 *obc1;
void OBC1::init() {}
void OBC1::enable() {}

View File

@ -16,3 +16,5 @@ struct {
OBC1();
~OBC1();
};
extern OBC1 *obc1;

View File

@ -1,4 +1,7 @@
#include "../../base.h"
SDD1 *sdd1;
#include "sdd1emu.cpp"
void SDD1::init() {}

View File

@ -28,3 +28,5 @@ struct {
SDD1();
};
extern SDD1 *sdd1;

View File

@ -52,6 +52,8 @@
#include "../../base.h"
SRTC *srtc;
void SRTC::set_time() {
time_t rawtime;
tm *t;

View File

@ -48,3 +48,5 @@ struct {
SRTC();
};
extern SRTC *srtc;

View File

@ -2,26 +2,6 @@ Config config_file;
namespace config {
void fs_set_path(Setting &s, const char *data) {
string path;
strcpy(path, data);
strunquote(path);
replace(path, "\\", "/");
//blank path?
if(strlen(path) == 0) {
s.sset(strptr(path));
return;
}
//missing final directory marker?
if(strptr(path)[strlen(path) - 1] != '/') {
strcat(path, "/");
}
s.sset(strptr(path));
}
Setting FS::base_path(0, "fs.base_path",
"Directory that bsnes resides in", "");
Setting FS::rom_path(&config_file, "fs.rom_path",
@ -48,15 +28,33 @@ Setting SNES::gamma(&config_file, "snes.colorfilter.gamma",
"Gamma", 80, Setting::DEC);
Setting SNES::ntsc_merge_fields(&config_file, "snes.ntsc_merge_fields",
"Merge fields in NTSC video filter\n"
"Set to true if using filter at any refresh rate other than 60hz\n"
"", true, Setting::TRUE_FALSE);
"Merge fields in NTSC video filter\n"
"Set to true if using filter at any refresh rate other than 60hz\n"
"", true, Setting::TRUE_FALSE);
Setting SNES::mute(&config_file, "snes.mute", "Mutes SNES audio output when enabled",
false, Setting::TRUE_FALSE);
//do not save these settings to config_file
Setting CPU::hdma_enable(0, "cpu.hdma_enable", "Enable HDMA effects", true, Setting::TRUE_FALSE);
Setting SNES::controller_port0(&config_file, "snes.controller_port_1",
"Controller attached to SNES port 1", ::SNES::DEVICEID_JOYPAD1, Setting::DEC);
Setting SNES::controller_port1(&config_file, "snes.controller_port_2",
"Controller attached to SNES port 2", ::SNES::DEVICEID_JOYPAD2, Setting::DEC);
Setting CPU::ntsc_clock_rate(&config_file, "cpu.ntsc_clock_rate",
"NTSC S-CPU clock rate (in hz)", 21477272, Setting::DEC);
Setting CPU::pal_clock_rate(&config_file, "cpu.pal_clock_rate",
"PAL S-CPU clock rate (in hz)", 21241370, Setting::DEC);
Setting CPU::hdma_enable(0, "cpu.hdma_enable",
"Enable HDMA effects", true, Setting::TRUE_FALSE);
Setting SMP::ntsc_clock_rate(&config_file, "smp.ntsc_clock_rate",
"NTSC S-SMP clock rate (in hz)", 24576000, Setting::DEC);
Setting SMP::pal_clock_rate(&config_file, "smp.pal_clock_rate",
"PAL S-SMP clock rate (in hz)", 24576000, Setting::DEC);
Setting PPU::render_scanline_position(&config_file, "ppu.render_scanline_position",
"Approximate HCLOCK position to render at for scanline-based renderers",
256, Setting::DEC);
Setting PPU::opt_enable(0, "ppu.opt_enable", "Enable offset-per-tile effects", true, Setting::TRUE_FALSE);
Setting PPU::bg1_pri0_enable(0, "ppu.bg1_pri0_enable", "Enable BG1 Priority 0", true, Setting::TRUE_FALSE);

View File

@ -2,8 +2,6 @@ extern Config config_file;
namespace config {
void fs_set_path(Setting &s, const char *data);
extern struct FS {
static Setting base_path, rom_path, save_path;
static Setting save_ext;
@ -13,13 +11,21 @@ extern struct SNES {
static Setting gamma_ramp, sepia, grayscale, invert, contrast, brightness, gamma;
static Setting ntsc_merge_fields;
static Setting mute;
static Setting controller_port0;
static Setting controller_port1;
} snes;
extern struct CPU {
static Setting ntsc_clock_rate, pal_clock_rate;
static Setting hdma_enable;
} cpu;
extern struct SMP {
static Setting ntsc_clock_rate, pal_clock_rate;
} smp;
extern struct PPU {
static Setting render_scanline_position;
static Setting opt_enable;
static Setting bg1_pri0_enable, bg1_pri1_enable;

View File

@ -59,21 +59,21 @@ uint8 r;
r = regs.mdr & 0xfc;
if(status.joypad_strobe_latch == 1) {
r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD1, SNES::JOYPAD_B);
r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD1, SNES::JOYPAD_B);
} else {
switch(status.joypad1_read_pos) {
case 0: r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD1, SNES::JOYPAD_B); break;
case 1: r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD1, SNES::JOYPAD_Y); break;
case 2: r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD1, SNES::JOYPAD_SELECT); break;
case 3: r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD1, SNES::JOYPAD_START); break;
case 4: r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD1, SNES::JOYPAD_UP); break;
case 5: r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD1, SNES::JOYPAD_DOWN); break;
case 6: r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD1, SNES::JOYPAD_LEFT); break;
case 7: r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD1, SNES::JOYPAD_RIGHT); break;
case 8: r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD1, SNES::JOYPAD_A); break;
case 9: r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD1, SNES::JOYPAD_X); break;
case 10: r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD1, SNES::JOYPAD_L); break;
case 11: r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD1, SNES::JOYPAD_R); break;
case 0: r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD1, SNES::JOYPAD_B); break;
case 1: r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD1, SNES::JOYPAD_Y); break;
case 2: r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD1, SNES::JOYPAD_SELECT); break;
case 3: r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD1, SNES::JOYPAD_START); break;
case 4: r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD1, SNES::JOYPAD_UP); break;
case 5: r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD1, SNES::JOYPAD_DOWN); break;
case 6: r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD1, SNES::JOYPAD_LEFT); break;
case 7: r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD1, SNES::JOYPAD_RIGHT); break;
case 8: r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD1, SNES::JOYPAD_A); break;
case 9: r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD1, SNES::JOYPAD_X); break;
case 10: r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD1, SNES::JOYPAD_L); break;
case 11: r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD1, SNES::JOYPAD_R); break;
case 12: break;
case 13: break;
case 14: break;
@ -97,21 +97,21 @@ uint8 r;
r |= 0x1c;
if(status.joypad_strobe_latch == 1) {
r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD2, SNES::JOYPAD_B);
r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD2, SNES::JOYPAD_B);
} else {
switch(status.joypad2_read_pos) {
case 0: r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD2, SNES::JOYPAD_B); break;
case 1: r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD2, SNES::JOYPAD_Y); break;
case 2: r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD2, SNES::JOYPAD_SELECT); break;
case 3: r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD2, SNES::JOYPAD_START); break;
case 4: r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD2, SNES::JOYPAD_UP); break;
case 5: r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD2, SNES::JOYPAD_DOWN); break;
case 6: r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD2, SNES::JOYPAD_LEFT); break;
case 7: r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD2, SNES::JOYPAD_RIGHT); break;
case 8: r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD2, SNES::JOYPAD_A); break;
case 9: r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD2, SNES::JOYPAD_X); break;
case 10: r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD2, SNES::JOYPAD_L); break;
case 11: r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD2, SNES::JOYPAD_R); break;
case 0: r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD2, SNES::JOYPAD_B); break;
case 1: r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD2, SNES::JOYPAD_Y); break;
case 2: r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD2, SNES::JOYPAD_SELECT); break;
case 3: r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD2, SNES::JOYPAD_START); break;
case 4: r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD2, SNES::JOYPAD_UP); break;
case 5: r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD2, SNES::JOYPAD_DOWN); break;
case 6: r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD2, SNES::JOYPAD_LEFT); break;
case 7: r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD2, SNES::JOYPAD_RIGHT); break;
case 8: r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD2, SNES::JOYPAD_A); break;
case 9: r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD2, SNES::JOYPAD_X); break;
case 10: r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD2, SNES::JOYPAD_L); break;
case 11: r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD2, SNES::JOYPAD_R); break;
case 12: break;
case 13: break;
case 14: break;
@ -213,10 +213,10 @@ uint8 r = 0x00;
uint16 v = vcounter();
if(status.auto_joypad_poll == false)return 0x00; //can't read joypad if auto polling not enabled
//if(v >= 225 && v <= 227)return 0x00; //can't read joypad while SNES is polling input
r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD1, SNES::JOYPAD_A) << 7;
r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD1, SNES::JOYPAD_X) << 6;
r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD1, SNES::JOYPAD_L) << 5;
r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD1, SNES::JOYPAD_R) << 4;
r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD1, SNES::JOYPAD_A) << 7;
r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD1, SNES::JOYPAD_X) << 6;
r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD1, SNES::JOYPAD_L) << 5;
r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD1, SNES::JOYPAD_R) << 4;
return r;
}
@ -226,14 +226,14 @@ uint8 r = 0x00;
uint16 v = vcounter();
if(status.auto_joypad_poll == false)return 0x00; //can't read joypad if auto polling not enabled
//if(v >= 225 && v <= 227)return 0x00; //can't read joypad while SNES is polling input
r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD1, SNES::JOYPAD_B) << 7;
r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD1, SNES::JOYPAD_Y) << 6;
r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD1, SNES::JOYPAD_SELECT) << 5;
r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD1, SNES::JOYPAD_START) << 4;
r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD1, SNES::JOYPAD_UP) << 3;
r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD1, SNES::JOYPAD_DOWN) << 2;
r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD1, SNES::JOYPAD_LEFT) << 1;
r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD1, SNES::JOYPAD_RIGHT);
r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD1, SNES::JOYPAD_B) << 7;
r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD1, SNES::JOYPAD_Y) << 6;
r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD1, SNES::JOYPAD_SELECT) << 5;
r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD1, SNES::JOYPAD_START) << 4;
r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD1, SNES::JOYPAD_UP) << 3;
r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD1, SNES::JOYPAD_DOWN) << 2;
r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD1, SNES::JOYPAD_LEFT) << 1;
r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD1, SNES::JOYPAD_RIGHT);
return r;
}
@ -243,10 +243,10 @@ uint8 r = 0x00;
uint16 v = vcounter();
if(status.auto_joypad_poll == false)return 0x00; //can't read joypad if auto polling not enabled
//if(v >= 225 && v <= 227)return 0x00; //can't read joypad while SNES is polling input
r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD2, SNES::JOYPAD_A) << 7;
r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD2, SNES::JOYPAD_X) << 6;
r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD2, SNES::JOYPAD_L) << 5;
r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD2, SNES::JOYPAD_R) << 4;
r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD2, SNES::JOYPAD_A) << 7;
r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD2, SNES::JOYPAD_X) << 6;
r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD2, SNES::JOYPAD_L) << 5;
r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD2, SNES::JOYPAD_R) << 4;
return r;
}
@ -256,14 +256,14 @@ uint8 r = 0x00;
uint16 v = vcounter();
if(status.auto_joypad_poll == false)return 0x00; //can't read joypad if auto polling not enabled
//if(v >= 225 && v <= 227)return 0x00; //can't read joypad while SNES is polling input
r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD2, SNES::JOYPAD_B) << 7;
r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD2, SNES::JOYPAD_Y) << 6;
r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD2, SNES::JOYPAD_SELECT) << 5;
r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD2, SNES::JOYPAD_START) << 4;
r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD2, SNES::JOYPAD_UP) << 3;
r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD2, SNES::JOYPAD_DOWN) << 2;
r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD2, SNES::JOYPAD_LEFT) << 1;
r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD2, SNES::JOYPAD_RIGHT);
r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD2, SNES::JOYPAD_B) << 7;
r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD2, SNES::JOYPAD_Y) << 6;
r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD2, SNES::JOYPAD_SELECT) << 5;
r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD2, SNES::JOYPAD_START) << 4;
r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD2, SNES::JOYPAD_UP) << 3;
r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD2, SNES::JOYPAD_DOWN) << 2;
r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD2, SNES::JOYPAD_LEFT) << 1;
r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD2, SNES::JOYPAD_RIGHT);
return r;
}
@ -330,7 +330,7 @@ uint8 bCPU::mmio_r43xb(uint8 i) {
uint8 bCPU::mmio_read(uint16 addr) {
//APU
if((addr & 0xffc0) == 0x2140) { //$2140-$217f
return r_apu->port_read(addr & 3);
return r_smp->port_read(addr & 3);
}
//HDMA
@ -414,8 +414,7 @@ void bCPU::mmio_w4016(uint8 value) {
status.joypad_strobe_latch = bool(value & 1);
if(status.joypad_strobe_latch == 1) {
snes->poll_input(SNES::DEV_JOYPAD1);
snes->poll_input(SNES::DEV_JOYPAD2);
snes->poll_input();
status.joypad1_read_pos = 0;
status.joypad2_read_pos = 0;
}

View File

@ -12,7 +12,7 @@ void bCPU::cpu_c2() {
}
void bCPU::cpu_c4(uint16 x, uint16 y) {
if(!regs.p.x && (x & 0xff00) != (y & 0xff00)) {
if(!regs.p.x || (x & 0xff00) != (y & 0xff00)) {
cpu_io();
}
}

View File

@ -15,7 +15,7 @@ sta_addrx(0x9d, regs.p.m, regs.a.w),
stz_addrx(0x9e, regs.p.m, 0x0000) {
1:aa.l = op_readpc();
2:aa.h = op_readpc();
3:cpu_c4(aa.w, aa.w + regs.x.w);
3:cpu_io();
4:if($1)last_cycle();
op_writedbr(aa.w + regs.x.w, $2);
if($1)end;
@ -26,7 +26,7 @@ stz_addrx(0x9e, regs.p.m, 0x0000) {
sta_addry(0x99) {
1:aa.l = op_readpc();
2:aa.h = op_readpc();
3:cpu_c4(aa.w, aa.w + regs.y.w);
3:cpu_io();
4:if(regs.p.m)last_cycle();
op_writedbr(aa.w + regs.y.w, regs.a.l);
if(regs.p.m)end;
@ -136,7 +136,7 @@ sta_idpy(0x91) {
2:cpu_c2();
3:aa.l = op_readdp(dp);
4:aa.h = op_readdp(dp + 1);
5:cpu_c4(aa.w, aa.w + regs.y.w);
5:cpu_io();
6:if(regs.p.m)last_cycle();
op_writedbr(aa.w + regs.y.w, regs.a.l);
if(regs.p.m)end;

View File

@ -26,7 +26,7 @@
*/
uint16 bCPU::vcounter() { return time.v; }
uint16 bCPU::hcycles() { return time.hc; }
uint16 bCPU::hclock() { return time.hc; }
bool bCPU::interlace() { return time.interlace; }
bool bCPU::interlace_field() { return time.interlace_field; }
@ -193,7 +193,7 @@ uint32 r = status.cycles_executed;
void bCPU::cycle_edge() {
if(time.line_rendered == false) {
if(time.hc >= 128) {
if(time.hc >= 192) {
time.line_rendered = true;
r_ppu->render_scanline();
}
@ -259,8 +259,7 @@ void bCPU::scanline() {
update_interrupts();
if(vcounter() == (!overscan() ? 227 : 242) && status.auto_joypad_poll == true) {
snes->poll_input(SNES::DEV_JOYPAD1);
snes->poll_input(SNES::DEV_JOYPAD2);
snes->poll_input();
//When the SNES auto-polls the joypads, it writes 1, then 0 to
//$4016, then reads from each 16 times to get the joypad state
//information. As a result, the joypad read positions are set

View File

@ -48,7 +48,7 @@ struct {
inline uint16 vcounter();
inline uint16 hcounter();
inline uint16 hcycles();
inline uint16 hclock();
inline bool interlace();
inline bool interlace_field();
inline bool overscan();

View File

@ -5,4 +5,5 @@ CPU::CPU() {
cpu_version = 1;
}
CPU::~CPU() {}
CPU::~CPU() {
}

View File

@ -11,7 +11,7 @@ uint8 cpu_version;
//timing
virtual uint16 vcounter() = 0;
virtual uint16 hcounter() = 0;
virtual uint16 hcycles() = 0;
virtual uint16 hclock() = 0;
virtual bool interlace() = 0;
virtual bool interlace_field() = 0;
virtual bool overscan() = 0;

View File

@ -1,33 +1,17 @@
class CPURegFlags {
private:
template<uint mask> class bit {
public:
uint data;
inline operator bool() { return bool(data & mask); }
inline bool operator = (const bool i) { (i) ? data |= mask : data &= ~mask; return bool(data & mask); }
inline bool operator |= (const bool i) { if(i)data |= mask; return bool(data & mask); }
inline bool operator ^= (const bool i) { if(i)data ^= mask; return bool(data & mask); }
inline bool operator &= (const bool i) { if(i)data &= mask; return bool(data & mask); }
};
public:
union {
uint8 data;
bit<0x80> n;
bit<0x40> v;
bit<0x20> m, p;
bit<0x10> x, b;
bit<0x08> d;
bit<0x04> i;
bit<0x02> z;
bit<0x01> c;
struct {
uint8 order_msb8(n:1, v:1, m:1, x:1, d:1, i:1, z:1, c:1);
};
};
inline operator unsigned() const { return data; }
inline unsigned operator = (const uint8 i) { data = i; return data; }
inline unsigned operator |= (const uint8 i) { data |= i; return data; }
inline unsigned operator ^= (const uint8 i) { data ^= i; return data; }
inline unsigned operator &= (const uint8 i) { data &= i; return data; }
template<typename T> inline unsigned operator = (const T i) { data = i; return data; }
template<typename T> inline unsigned operator |= (const T i) { data |= i; return data; }
template<typename T> inline unsigned operator ^= (const T i) { data ^= i; return data; }
template<typename T> inline unsigned operator &= (const T i) { data &= i; return data; }
CPURegFlags() : data(0) {}
};

View File

@ -421,6 +421,10 @@ uint8 op2 = dreadb(pc.d);
}
strcat(s, t);
strcat(s, " ");
sprintf(t, "V:%3d H:%4d", vcounter(), hclock());
strcat(s, t);
}
/*****

View File

@ -1,3 +1,3 @@
cl /O2 scpugen.cpp
cl /nologo /O2 scpugen.cpp
@pause
@del *.obj

View File

@ -2,12 +2,6 @@
void sCPU::main() {
for(;;) {
#ifdef DEBUGGER
snes->notify(SNES::CPU_EXEC_OPCODE_BEGIN);
#endif
status.in_opcode = true;
if(event.irq) {
event.irq = false;
if(status.nmi_pending == true) {
@ -20,6 +14,10 @@ void sCPU::main() {
op_irq();
}
tracer.trace_cpuop(); //traces CPU opcode (only if tracer is enabled)
status.in_opcode = true;
switch(op_readpc()) {
#include "op_read.cpp"
#include "op_write.cpp"
@ -30,10 +28,6 @@ void sCPU::main() {
status.in_opcode = false;
#ifdef DEBUGGER
snes->notify(SNES::CPU_EXEC_OPCODE_END);
#endif
#ifdef FAVOR_SPEED
co_return();
#endif
@ -53,24 +47,24 @@ void sCPU::op_irq() {
regs.p.d = 0;
rd.h = op_read(event.irq_vector + 1);
regs.pc.w = rd.w;
#ifdef DEBUGGER
status.in_opcode = false;
snes->notify(SNES::CPU_EXEC_OPCODE_END);
status.in_opcode = true;
#endif
}
//
void sCPU::op_io_cond2() {
if(regs.d.l != 0x00)op_io();
alwaysinline void sCPU::op_io_cond2() {
if(regs.d.l != 0x00) {
op_io();
}
}
void sCPU::op_io_cond4(uint16 x, uint16 y) {
if(!regs.p.x && (x & 0xff00) != (y & 0xff00))op_io();
alwaysinline void sCPU::op_io_cond4(uint16 x, uint16 y) {
if(!regs.p.x || (x & 0xff00) != (y & 0xff00)) {
op_io();
}
}
void sCPU::op_io_cond6(uint16 addr) {
if(regs.e && (regs.pc.w & 0xff00) != (addr & 0xff00))op_io();
alwaysinline void sCPU::op_io_cond6(uint16 addr) {
if(regs.e && (regs.pc.w & 0xff00) != (addr & 0xff00)) {
op_io();
}
}

View File

@ -15,7 +15,7 @@ sta_addrx(0x9d, regs.acc_8b, regs.a.w),
stz_addrx(0x9e, regs.acc_8b, 0x0000) {
1:aa.l = op_readpc();
2:aa.h = op_readpc();
3:op_io_cond4(aa.w, aa.w + regs.x.w);
3:op_io();
4:if($1)last_cycle();
op_writedbr(aa.w + regs.x.w, $2);
if($1)end;
@ -26,7 +26,7 @@ stz_addrx(0x9e, regs.acc_8b, 0x0000) {
sta_addry(0x99) {
1:aa.l = op_readpc();
2:aa.h = op_readpc();
3:op_io_cond4(aa.w, aa.w + regs.y.w);
3:op_io();
4:if(regs.acc_8b)last_cycle();
op_writedbr(aa.w + regs.y.w, regs.a.l);
if(regs.acc_8b)end;
@ -136,7 +136,7 @@ sta_idpy(0x91) {
2:op_io_cond2();
3:aa.l = op_readdp(dp);
4:aa.h = op_readdp(dp + 1);
5:op_io_cond4(aa.w, aa.w + regs.y.w);
5:op_io();
6:if(regs.acc_8b)last_cycle();
op_writedbr(aa.w + regs.y.w, regs.a.l);
if(regs.acc_8b)end;

View File

@ -46,7 +46,7 @@ case 0x9c: {
case 0x9d: {
aa.l = op_readpc();
aa.h = op_readpc();
op_io_cond4(aa.w, aa.w + regs.x.w);
op_io();
if(regs.acc_8b)last_cycle();
op_writedbr(aa.w + regs.x.w, regs.a.w);
if(regs.acc_8b)break;
@ -58,7 +58,7 @@ case 0x9d: {
case 0x9e: {
aa.l = op_readpc();
aa.h = op_readpc();
op_io_cond4(aa.w, aa.w + regs.x.w);
op_io();
if(regs.acc_8b)last_cycle();
op_writedbr(aa.w + regs.x.w, 0x0000);
if(regs.acc_8b)break;
@ -70,7 +70,7 @@ case 0x9e: {
case 0x99: {
aa.l = op_readpc();
aa.h = op_readpc();
op_io_cond4(aa.w, aa.w + regs.y.w);
op_io();
if(regs.acc_8b)last_cycle();
op_writedbr(aa.w + regs.y.w, regs.a.l);
if(regs.acc_8b)break;
@ -241,7 +241,7 @@ case 0x91: {
op_io_cond2();
aa.l = op_readdp(dp);
aa.h = op_readdp(dp + 1);
op_io_cond4(aa.w, aa.w + regs.y.w);
op_io();
if(regs.acc_8b)last_cycle();
op_writedbr(aa.w + regs.y.w, regs.a.l);
if(regs.acc_8b)break;

View File

@ -29,6 +29,7 @@ uint8 r;
r_mem->write(abus, r);
}
status.dma_clocks += 8;
add_clocks(8);
co_return();
cycle_edge();
@ -52,7 +53,7 @@ uint8 sCPU::dma_bbus(uint8 i, uint8 index) {
}
}
uint32 sCPU::dma_addr(uint8 i) {
inline uint32 sCPU::dma_addr(uint8 i) {
uint32 r = (channel[i].srcbank << 16) | (channel[i].srcaddr);
if(channel[i].fixedxfer == false) {
@ -66,11 +67,11 @@ uint32 r = (channel[i].srcbank << 16) | (channel[i].srcaddr);
return r;
}
uint32 sCPU::hdma_addr(uint8 i) {
inline uint32 sCPU::hdma_addr(uint8 i) {
return (channel[i].srcbank << 16) | (channel[i].hdma_addr++);
}
uint32 sCPU::hdma_iaddr(uint8 i) {
inline uint32 sCPU::hdma_iaddr(uint8 i) {
return (channel[i].hdma_ibank << 16) | (channel[i].hdma_iaddr++);
}
@ -92,9 +93,8 @@ void sCPU::dma_transfertobusa(uint8 i, uint8 bbus) {
channel[i].xfersize--;
}
void sCPU::dma_write(uint8 i, uint8 index) {
//cannot use dma_transfer() directly,
//due to current S-DD1 implementation
inline void sCPU::dma_write(uint8 i, uint8 index) {
//cannot use dma_transfer() directly, due to current S-DD1 implementation
if(channel[i].direction == 0) {
dma_transfertobusb(i, index);
} else {
@ -103,10 +103,9 @@ void sCPU::dma_write(uint8 i, uint8 index) {
}
void sCPU::dma_run() {
add_clocks(18);
for(int i = 0; i < 8; i++) {
if(channel[i].dma_enabled == false)continue;
status.dma_clocks += 8;
add_clocks(8);
if(cartridge.info.sdd1 == true) {
@ -114,6 +113,15 @@ void sCPU::dma_run() {
channel[i].xfersize);
}
if(tracer.enabled() == true && tracer.cpudma_enabled() == true) {
tprintf("[DMA] channel:%d direction:%s reverse:%c fixed:%c mode:%d b_addr:$21%0.2x "
"a_addr:$%0.2x%0.4x length:$%0.4x (%5d)",
i, channel[i].direction ? "b->a" : "a->b", channel[i].reversexfer ? '1' : '0',
channel[i].fixedxfer ? '1' : '0', channel[i].xfermode, channel[i].destaddr,
channel[i].srcbank, channel[i].srcaddr,
channel[i].xfersize, channel[i].xfersize ? channel[i].xfersize : 65536);
}
uint index = 0;
do {
dma_write(i, dma_bbus(i, index++));
@ -122,18 +130,26 @@ void sCPU::dma_run() {
channel[i].dma_enabled = false;
}
set_irq_delay(24);
counter_set(counter.irq_delay, 24);
}
/*****
* HDMA functions
*****/
bool sCPU::hdma_active(uint8 i) {
inline bool sCPU::hdma_active(uint8 i) {
return (channel[i].hdma_enabled && !channel[i].hdma_completed);
}
uint8 sCPU::hdma_enabled_channels() {
inline bool sCPU::hdma_active_after(uint8 i) {
for(int n = i + 1; n < 8; n++) {
if(hdma_active(n) == true) { return true; }
}
return false;
}
inline uint8 sCPU::hdma_enabled_channels() {
uint8 r = 0;
for(int i = 0; i < 8; i++) {
if(channel[i].hdma_enabled)r++;
@ -141,7 +157,7 @@ uint8 r = 0;
return r;
}
uint8 sCPU::hdma_active_channels() {
inline uint8 sCPU::hdma_active_channels() {
uint8 r = 0;
for(int i = 0; i < 8; i++) {
if(hdma_active(i) == true)r++;
@ -153,31 +169,22 @@ void sCPU::hdma_update(uint8 i) {
channel[i].hdma_line_counter = r_mem->read(hdma_addr(i));
add_clocks(8);
channel[i].hdma_completed = (channel[i].hdma_line_counter == 0);
channel[i].hdma_do_transfer = !channel[i].hdma_completed;
if(channel[i].hdma_indirect) {
channel[i].hdma_iaddr = r_mem->read(hdma_addr(i)) << 8;
add_clocks(8);
}
if(channel[i].hdma_line_counter == 0) {
channel[i].hdma_completed = true;
channel[i].hdma_do_transfer = false;
return;
}
channel[i].hdma_do_transfer = true;
if(channel[i].hdma_indirect) {
channel[i].hdma_iaddr >>= 8;
channel[i].hdma_iaddr |= r_mem->read(hdma_addr(i)) << 8;
add_clocks(8);
if(!channel[i].hdma_completed || hdma_active_after(i)) {
channel[i].hdma_iaddr >>= 8;
channel[i].hdma_iaddr |= r_mem->read(hdma_addr(i)) << 8;
add_clocks(8);
}
}
}
void sCPU::hdma_run() {
if(hdma_active_channels() == 0)return;
add_clocks(18);
static uint8 hdma_xferlen[8] = { 1, 2, 2, 4, 4, 4, 2, 4 };
for(int i = 0; i < 8; i++) {
if(hdma_active(i) == false)continue;
@ -205,19 +212,17 @@ static uint8 hdma_xferlen[8] = { 1, 2, 2, 4, 4, 4, 2, 4 };
}
}
set_irq_delay(24);
counter_set(counter.irq_delay, 24);
}
void sCPU::hdma_init() {
void sCPU::hdma_init_reset() {
for(int i = 0; i < 8; i++) {
channel[i].hdma_completed = false;
channel[i].hdma_do_transfer = false;
}
}
if(hdma_enabled_channels() == 0)return;
add_clocks(18);
void sCPU::hdma_init() {
for(int i = 0; i < 8; i++) {
if(!channel[i].hdma_enabled)continue;
channel[i].dma_enabled = false; //HDMA init during DMA will stop DMA mid-transfer
@ -226,7 +231,7 @@ void sCPU::hdma_init() {
hdma_update(i);
}
set_irq_delay(24);
counter_set(counter.irq_delay, 24);
}
/*****

View File

@ -58,10 +58,12 @@ struct {
void dma_run();
bool hdma_active(uint8 i);
bool hdma_active_after(uint8 i);
uint8 hdma_enabled_channels();
uint8 hdma_active_channels();
void hdma_update(uint8 i);
void hdma_run();
void hdma_init_reset();
void hdma_init();
void dma_power();

View File

@ -8,6 +8,7 @@
void sCPU::op_io() {
status.clock_count = 6;
precycle_edge();
add_clocks(6);
//co_return();
cycle_edge();
@ -15,6 +16,7 @@ void sCPU::op_io() {
uint8 sCPU::op_read(uint32 addr) {
status.clock_count = r_mem->speed(addr);
precycle_edge();
add_clocks(status.clock_count - 4);
#ifdef FAVOR_ACCURACY
co_return();
@ -27,6 +29,7 @@ uint8 sCPU::op_read(uint32 addr) {
void sCPU::op_write(uint32 addr, uint8 data) {
status.clock_count = r_mem->speed(addr);
precycle_edge();
add_clocks(status.clock_count);
#ifdef FAVOR_ACCURACY
co_return();

View File

@ -17,17 +17,17 @@ uint8 apu_port[4];
*****/
uint8 op_readpc () { return op_read((regs.pc.b << 16) + regs.pc.w++); }
uint8 op_readstack() { (regs.e) ? regs.s.l++ : regs.s.w++; return op_read(regs.s.w); }
uint8 op_readaddr (uint32 addr) { return op_read(uclip<16>(addr)); }
uint8 op_readlong (uint32 addr) { return op_read(uclip<24>(addr)); }
uint8 op_readdbr (uint32 addr) { return op_read(uclip<24>((regs.db << 16) + addr)); }
uint8 op_readpbr (uint32 addr) { return op_read((regs.pc.b << 16) + uclip<16>(addr)); }
uint8 op_readdp (uint32 addr) { return op_read(uclip<16>(regs.d + uclip<16>(addr))); }
uint8 op_readsp (uint32 addr) { return op_read(uclip<16>(regs.s + uclip<16>(addr))); }
uint8 op_readaddr (uint32 addr) { return op_read(addr & 0xffff); }
uint8 op_readlong (uint32 addr) { return op_read(addr & 0xffffff); }
uint8 op_readdbr (uint32 addr) { return op_read(((regs.db << 16) + addr) & 0xffffff); }
uint8 op_readpbr (uint32 addr) { return op_read((regs.pc.b << 16) + (addr & 0xffff)); }
uint8 op_readdp (uint32 addr) { return op_read((regs.d + (addr & 0xffff)) & 0xffff); }
uint8 op_readsp (uint32 addr) { return op_read((regs.s + (addr & 0xffff)) & 0xffff); }
void op_writestack(uint8 data) { op_write(regs.s.w, data); (regs.e) ? regs.s.l-- : regs.s.w--; }
void op_writeaddr (uint32 addr, uint8 data) { op_write(uclip<16>(addr), data); }
void op_writelong (uint32 addr, uint8 data) { op_write(uclip<24>(addr), data); }
void op_writedbr (uint32 addr, uint8 data) { op_write(uclip<24>((regs.db << 16) + addr), data); }
void op_writepbr (uint32 addr, uint8 data) { op_write((regs.pc.b << 16) + uclip<16>(addr), data); }
void op_writedp (uint32 addr, uint8 data) { op_write(uclip<16>(regs.d + uclip<16>(addr)), data); }
void op_writesp (uint32 addr, uint8 data) { op_write(uclip<16>(regs.s + uclip<16>(addr)), data); }
void op_writeaddr (uint32 addr, uint8 data) { op_write(addr & 0xffff, data); }
void op_writelong (uint32 addr, uint8 data) { op_write(addr & 0xffffff, data); }
void op_writedbr (uint32 addr, uint8 data) { op_write(((regs.db << 16) + addr) & 0xffffff, data); }
void op_writepbr (uint32 addr, uint8 data) { op_write((regs.pc.b << 16) + (addr & 0xffff), data); }
void op_writedp (uint32 addr, uint8 data) { op_write((regs.d + (addr & 0xffff)) & 0xffff, data); }
void op_writesp (uint32 addr, uint8 data) { op_write((regs.s + (addr & 0xffff)) & 0xffff, data); }

View File

@ -2,21 +2,17 @@ uint8 sCPU::pio_status() {
return status.pio;
}
/*****
* WRAM data registers
*****/
//WMDATA
uint8 sCPU::mmio_r2180() {
uint8 r = r_mem->read(0x7e0000 | status.wram_addr++);
status.wram_addr &= 0x01ffff;
uint8 r = r_mem->read(0x7e0000 | status.wram_addr);
status.wram_addr = (status.wram_addr + 1) & 0x01ffff;
return r;
}
//WMDATA
void sCPU::mmio_w2180(uint8 data) {
r_mem->write(0x7e0000 | status.wram_addr++, data);
status.wram_addr &= 0x01ffff;
r_mem->write(0x7e0000 | status.wram_addr, data);
status.wram_addr = (status.wram_addr + 1) & 0x01ffff;
}
//WMADDL
@ -37,24 +33,27 @@ void sCPU::mmio_w2183(uint8 data) {
status.wram_addr &= 0x01ffff;
}
/*****
* Joypad registers
*****/
//JOYSER0
//bit 0 is shared between JOYSER0 and JOYSER1, therefore
//strobing $4016.d0 affects both controller port latches.
//$4017 bit 0 writes are ignored.
void sCPU::mmio_w4016(uint8 data) {
status.joypad_strobe_latch = !!(data & 1);
//TODO: test whether strobe latch of zero returns
//realtime or buffered status of joypadN.b
if(status.joypad_strobe_latch == 1) {
snes->poll_input();
}
}
//JOYSER0
//7-2 = MDR
//1-0 = Joypad serial data
//
//TODO: test whether strobe latch of zero returns
//realtime or buffered status of joypadN.b
uint8 sCPU::mmio_r4016() {
uint8 r = regs.mdr & 0xfc;
r |= status.joypad1_bits & 1;
if(status.joypad_strobe_latch == 0) {
status.joypad1_bits >>= 1;
status.joypad1_bits |= 0x8000;
}
r |= (uint8)snes->port_read(0);
return r;
}
@ -64,41 +63,149 @@ uint8 r = regs.mdr & 0xfc;
//1-0 = Joypad serial data
uint8 sCPU::mmio_r4017() {
uint8 r = (regs.mdr & 0xe0) | 0x1c;
r |= status.joypad2_bits & 1;
if(status.joypad_strobe_latch == 0) {
status.joypad2_bits >>= 1;
status.joypad2_bits |= 0x8000;
}
r |= (uint8)snes->port_read(1);
return r;
}
//TODO: handle reads during joypad polling (v=225-227)
//NMITIMEN
void sCPU::mmio_w4200(uint8 data) {
status.nmi_enabled = !!(data & 0x80);
status.virq_enabled = !!(data & 0x20);
status.hirq_enabled = !!(data & 0x10);
status.auto_joypad_poll = !!(data & 0x01);
uint8 sCPU::mmio_r4218() { return status.joy1l; } //JOY1L
uint8 sCPU::mmio_r4219() { return status.joy1h; } //JOY1H
uint8 sCPU::mmio_r421a() { return status.joy2l; } //JOY2L
uint8 sCPU::mmio_r421b() { return status.joy2h; } //JOY2H
uint8 sCPU::mmio_r421c() { return status.joy3l; } //JOY3L
uint8 sCPU::mmio_r421d() { return status.joy3h; } //JOY3H
uint8 sCPU::mmio_r421e() { return status.joy4l; } //JOY4L
uint8 sCPU::mmio_r421f() { return status.joy4h; } //JOY4H
if(status.nmi_read == 0) {
if(status.nmi_line == 1 && status.nmi_enabled == 1) {
status.nmi_transition = 1;
}
status.nmi_line = !status.nmi_enabled;
}
//JOYSER0
//bit 0 is shared between JOYSER0 and JOYSER1, therefore
//strobing $4016.d0 affects both controller port latches.
//$4017 bit 0 writes are ignored.
void sCPU::mmio_w4016(uint8 data) {
status.joypad_strobe_latch = bool(data & 1);
if(status.irq_read == 0) {
if(status.irq_line == 1 && (status.virq_enabled || status.hirq_enabled)) {
status.irq_transition = 1;
}
status.irq_line = !(status.virq_enabled || status.hirq_enabled);
}
if(status.joypad_strobe_latch == 1) {
run_manual_joypad_poll();
if(status.virq_enabled == true && status.hirq_enabled == false) {
status.irq_lock = false;
}
if(status.virq_enabled == false && status.hirq_enabled == false) {
status.irq_line = 1;
status.irq_read = 1;
status.irq_transition = 0;
}
update_interrupts();
counter_set(counter.irq_delay, 2);
}
//WRIO
void sCPU::mmio_w4201(uint8 data) {
if((status.pio & 0x80) && !(data & 0x80)) {
r_ppu->latch_counters();
}
status.pio = data;
}
//WRMPYA
void sCPU::mmio_w4202(uint8 data) {
status.mul_a = data;
}
//WRMPYB
void sCPU::mmio_w4203(uint8 data) {
status.mul_b = data;
status.r4216 = status.mul_a * status.mul_b;
//counter_set(counter.hw_math, 48);
}
//WRDIVL
void sCPU::mmio_w4204(uint8 data) {
status.div_a = (status.div_a & 0xff00) | (data);
}
//WRDIVH
void sCPU::mmio_w4205(uint8 data) {
status.div_a = (status.div_a & 0x00ff) | (data << 8);
}
//WRDIVB
void sCPU::mmio_w4206(uint8 data) {
status.div_b = data;
status.r4214 = (status.div_b) ? status.div_a / status.div_b : 0xffff;
status.r4216 = (status.div_b) ? status.div_a % status.div_b : status.div_a;
//counter_set(counter.hw_math, 96);
}
//HTIMEL
void sCPU::mmio_w4207(uint8 data) {
status.hirq_pos = (status.hirq_pos & ~0xff) | (data);
status.hirq_pos &= 0x01ff;
update_interrupts();
uint vpos = status.vcounter, hpos = status.hclock;
timeshift_backward(10, vpos, hpos);
if(hpos < status.hirq_trigger_pos) { status.irq_lock = false; }
}
//HTIMEH
void sCPU::mmio_w4208(uint8 data) {
status.hirq_pos = (status.hirq_pos & 0xff) | (data << 8);
status.hirq_pos &= 0x01ff;
update_interrupts();
uint vpos = status.vcounter, hpos = status.hclock;
timeshift_backward(10, vpos, hpos);
if(hpos < status.hirq_trigger_pos) { status.irq_lock = false; }
}
//VTIMEL
void sCPU::mmio_w4209(uint8 data) {
status.virq_pos = (status.virq_pos & ~0xff) | (data);
status.virq_pos &= 0x01ff;
update_interrupts();
uint vpos = status.vcounter, hpos = status.hclock;
timeshift_backward(10, vpos, hpos);
if(hpos < status.hirq_trigger_pos) { status.irq_lock = false; }
}
//VTIMEH
void sCPU::mmio_w420a(uint8 data) {
status.virq_pos = (status.virq_pos & 0xff) | (data << 8);
status.virq_pos &= 0x01ff;
update_interrupts();
uint vpos = status.vcounter, hpos = status.hclock;
timeshift_backward(10, vpos, hpos);
if(hpos < status.hirq_trigger_pos) { status.irq_lock = false; }
}
//DMAEN
void sCPU::mmio_w420b(uint8 data) {
for(int i = 0; i < 8; i++) {
channel[i].dma_enabled = !!(data & (1 << i));
}
if(data) {
status.dma_state = DMASTATE_DMASYNC;
status.dma_pending = true;
}
}
/*****
* NMI / IRQ registers
*****/
//HDMAEN
void sCPU::mmio_w420c(uint8 data) {
for(int i = 0; i < 8; i++) {
channel[i].hdma_enabled = !!(data & (1 << i));
}
}
//MEMSEL
void sCPU::mmio_w420d(uint8 data) {
r_mem->set_speed(data & 1);
}
//RDNMI
//7 = NMI acknowledge
@ -106,9 +213,9 @@ void sCPU::mmio_w4016(uint8 data) {
//3-0 = CPU (5a22) version
uint8 sCPU::mmio_r4210() {
uint8 r = (regs.mdr & 0x70);
r |= uint8(!status.nmi_read) << 7;
r |= (uint8)(!status.nmi_read) << 7;
if(!nmi_read_pos_match(0) && !nmi_read_pos_match(2)) {
if(!counter.nmi_fire) {
status.nmi_read = 1;
}
@ -121,9 +228,9 @@ uint8 r = (regs.mdr & 0x70);
//6-0 = MDR
uint8 sCPU::mmio_r4211() {
uint8 r = (regs.mdr & 0x7f);
r |= uint8(!status.irq_read) << 7;
r |= (uint8)(!status.irq_read) << 7;
if(!irq_read_pos_match(0) && !irq_read_pos_match(2)) {
if(!counter.irq_fire) {
status.irq_read = 1;
status.irq_line = 1;
status.irq_transition = 0;
@ -153,132 +260,44 @@ uint16 vs = !overscan() ? 225 : 240;
return r;
}
//NMITIMEN
void sCPU::mmio_w4200(uint8 data) {
status.nmi_enabled = bool(data & 0x80);
status.virq_enabled = bool(data & 0x20);
status.hirq_enabled = bool(data & 0x10);
status.auto_joypad_poll = bool(data & 0x01);
//if(!status.nmi_enabled)status.nmi_read=1;
if(status.nmi_read == 0) {
if(status.nmi_line == 1 && !status.nmi_enabled == 0) {
status.nmi_transition = 1;
}
status.nmi_line = !status.nmi_enabled;
}
if(status.virq_enabled == false && status.hirq_enabled == false) {
status.irq_line = 1;
status.irq_read = 1;
status.irq_transition = 0;
}
update_interrupts();
set_irq_delay(2);
}
//HTIMEL
void sCPU::mmio_w4207(uint8 data) {
status.hirq_pos = (status.hirq_pos & ~0xff) | (data);
status.hirq_pos &= 0x01ff;
update_interrupts();
}
//HTIMEH
void sCPU::mmio_w4208(uint8 data) {
status.hirq_pos = (status.hirq_pos & 0xff) | (data << 8);
status.hirq_pos &= 0x01ff;
update_interrupts();
}
//VTIMEL
void sCPU::mmio_w4209(uint8 data) {
status.virq_pos = (status.virq_pos & ~0xff) | (data);
status.virq_pos &= 0x01ff;
update_interrupts();
}
//VTIMEH
void sCPU::mmio_w420a(uint8 data) {
status.virq_pos = (status.virq_pos & 0xff) | (data << 8);
status.virq_pos &= 0x01ff;
update_interrupts();
}
/*****
* I/O registers
****/
//RDIO
uint8 sCPU::mmio_r4213() {
return status.pio;
}
//WRIO
void sCPU::mmio_w4201(uint8 data) {
if((status.pio & 0x80) && !(data & 0x80)) {
r_ppu->latch_counters();
}
status.pio = data;
}
/*****
* Math registers (multiplication and division)
*****/
//RDDIVL
uint8 sCPU::mmio_r4214() {
if(counter.hw_math) { return 0x00; }
return status.r4214;
}
//RDDIVH
uint8 sCPU::mmio_r4215() {
if(counter.hw_math) { return 0x00; }
return status.r4214 >> 8;
}
//RDMPYL
uint8 sCPU::mmio_r4216() {
if(counter.hw_math) { return 0x00; }
return status.r4216;
}
//RDMPYH
uint8 sCPU::mmio_r4217() {
if(counter.hw_math) { return 0x00; }
return status.r4216 >> 8;
}
//WRMPYA
void sCPU::mmio_w4202(uint8 data) {
status.mul_a = data;
}
//WRMPYB
void sCPU::mmio_w4203(uint8 data) {
status.mul_b = data;
status.r4216 = status.mul_a * status.mul_b;
}
//WRDIVL
void sCPU::mmio_w4204(uint8 data) {
status.div_a = (status.div_a & 0xff00) | (data);
}
//WRDIVH
void sCPU::mmio_w4205(uint8 data) {
status.div_a = (status.div_a & 0x00ff) | (data << 8);
}
//WRDIVB
void sCPU::mmio_w4206(uint8 data) {
status.div_b = data;
status.r4214 = (status.div_b) ? status.div_a / status.div_b : 0xffff;
status.r4216 = (status.div_b) ? status.div_a % status.div_b : status.div_a;
}
/*****
* DMA / HDMA registers
*****/
//TODO: handle reads during joypad polling (v=225-227)
uint8 sCPU::mmio_r4218() { return status.joy1l; } //JOY1L
uint8 sCPU::mmio_r4219() { return status.joy1h; } //JOY1H
uint8 sCPU::mmio_r421a() { return status.joy2l; } //JOY2L
uint8 sCPU::mmio_r421b() { return status.joy2h; } //JOY2H
uint8 sCPU::mmio_r421c() { return status.joy3l; } //JOY3L
uint8 sCPU::mmio_r421d() { return status.joy3h; } //JOY3H
uint8 sCPU::mmio_r421e() { return status.joy4l; } //JOY4L
uint8 sCPU::mmio_r421f() { return status.joy4h; } //JOY4H
//DMAPx
uint8 sCPU::mmio_r43x0(uint8 i) {
@ -342,34 +361,13 @@ uint8 sCPU::mmio_r43xb(uint8 i) {
return channel[i].unknown;
}
//DMAEN
//Note: DMA enable does not disable active HDMA channels
void sCPU::mmio_w420b(uint8 data) {
for(int i = 0; i < 8; i++) {
channel[i].dma_enabled = bool(data & (1 << i));
}
if(data)dma_run(); //temporary
}
//HDMAEN
void sCPU::mmio_w420c(uint8 data) {
for(int i = 0; i < 8; i++) {
channel[i].hdma_enabled = bool(data & (1 << i));
}
}
//MEMSEL
void sCPU::mmio_w420d(uint8 data) {
r_mem->set_speed(data & 1);
}
//DMAPx
void sCPU::mmio_w43x0(uint8 i, uint8 data) {
channel[i].dmap = data;
channel[i].direction = bool(data & 0x80);
channel[i].hdma_indirect = bool(data & 0x40);
channel[i].reversexfer = bool(data & 0x10);
channel[i].fixedxfer = bool(data & 0x08);
channel[i].direction = !!(data & 0x80);
channel[i].hdma_indirect = !!(data & 0x40);
channel[i].reversexfer = !!(data & 0x10);
channel[i].fixedxfer = !!(data & 0x08);
channel[i].xfermode = data & 7;
}
@ -430,10 +428,6 @@ void sCPU::mmio_w43xb(uint8 i, uint8 data) {
channel[i].unknown = data;
}
/*****
* reset / read / write
*****/
void sCPU::mmio_power() {
}
@ -488,7 +482,7 @@ uint8 sCPU::mmio_read(uint16 addr) {
#ifdef FAVOR_SPEED
co_return();
#endif
return r_apu->port_read(addr & 3);
return r_smp->port_read(addr & 3);
}
//DMA

View File

@ -14,6 +14,21 @@ struct {
uint16 irq_vector;
} event;
struct {
bool enabled;
uint irq_delay;
uint irq_fire;
uint nmi_fire;
uint hw_math;
} counter;
enum {
DMASTATE_INACTIVE,
DMASTATE_DMASYNC,
DMASTATE_RUN,
DMASTATE_CPUSYNC,
};
struct {
//core
uint8 opcode;
@ -29,21 +44,36 @@ struct {
bool interlace, interlace_field;
bool overscan;
uint16 field_lines, line_clocks;
uint16 vblstart;
bool line_rendered;
uint16 line_render_position;
bool dram_refreshed;
uint16 dram_refresh_position;
bool hdmainit_triggered;
uint16 hdmainit_trigger_position;
bool hdma_triggered;
uint16 irq_delay;
int16 nmi_read_pos, nmi_line_pos;
uint16 nmi_trigger_pos;
bool nmi_read, nmi_line, nmi_transition;
bool nmi_pending;
int16 irq_read_pos, irq_line_pos;
uint16 virq_trigger_pos, hirq_trigger_pos;
bool irq_read, irq_line, irq_transition;
bool irq_pending;
bool irq_lock, irq_pending;
//dma
uint dma_counter;
uint dma_clocks;
uint dma_state;
bool dma_pending;
bool hdma_pending;
bool hdmainit_pending;
//mmio

View File

@ -1,122 +1,60 @@
void sCPU::set_irq_delay(uint clocks) {
if(status.irq_delay < clocks) {
status.irq_delay = clocks;
}
}
void sCPU::update_interrupts() {
if(status.vcounter == (!overscan() ? 225 : 240)) {
status.nmi_read_pos = 2;
status.nmi_line_pos = 6;
status.nmi_trigger_pos = (status.vcounter == status.vblstart) ? 2 : IRQ_TRIGGER_NEVER;
if(irq_pos_valid() == true) {
status.virq_trigger_pos = status.virq_pos;
status.hirq_trigger_pos = (status.hirq_enabled) ? ((status.hirq_pos + 1) * 4) : 0;
} else {
status.nmi_read_pos = -64;
status.nmi_line_pos = -64;
}
if(irq_pos_valid() == false) {
status.irq_read_pos = -64;
status.irq_line_pos = -64;
return;
}
uint vpos = status.virq_pos;
uint hpos = (status.hirq_enabled) ? status.hirq_pos : 0;
hpos = (hpos != 0) ? ((hpos << 2) + 14) : 10;
if(hpos >= status.line_clocks) {
hpos -= status.line_clocks;
if(++vpos >= status.field_lines) {
vpos = 0;
}
}
if((status.virq_enabled == true && status.vcounter == vpos) || status.virq_enabled == false) {
status.irq_read_pos = hpos;
} else {
status.irq_read_pos = -64;
}
hpos += 4;
if(hpos >= status.line_clocks) {
hpos -= status.line_clocks;
if(++vpos >= status.field_lines) {
vpos = 0;
}
}
if((status.virq_enabled == true && status.vcounter == vpos) || status.virq_enabled == false) {
status.irq_line_pos = hpos;
} else {
status.irq_line_pos = -64;
status.virq_trigger_pos = IRQ_TRIGGER_NEVER;
status.hirq_trigger_pos = IRQ_TRIGGER_NEVER;
}
}
void sCPU::poll_interrupts(int clocks) {
int16 start, end;
if(status.hclock == 0) {
start = -1;
end = clocks;
} else {
start = status.hclock;
end = status.hclock + clocks;
}
alwaysinline void sCPU::nmi_tick() {
counter.nmi_fire -= 2;
if(counter.nmi_fire != 0) { return; }
//NMI read test
if(start < status.nmi_read_pos && status.nmi_read_pos <= end) {
//nmi_read lowers even when NMI interrupts are disabled via $4200.d7
status.nmi_read = 0;
}
//NMI line test
if(start < status.nmi_line_pos && status.nmi_line_pos <= end) {
if(status.nmi_enabled == true) {
if(status.nmi_line == 1) {
status.nmi_transition = 1;
}
status.nmi_line = 0;
}
}
//IRQ read test
if(start < status.irq_read_pos && status.irq_read_pos <= end) {
if(status.virq_enabled == true || status.hirq_enabled == true) {
status.irq_read = 0;
}
}
//IRQ line test
if(start < status.irq_line_pos && status.irq_line_pos <= end) {
if(status.virq_enabled == true || status.hirq_enabled == true) {
status.irq_line = 0;
status.irq_transition = 1;
}
if(status.nmi_enabled == true && status.nmi_line == 1) {
status.nmi_line = 0;
status.nmi_transition = 1;
}
}
bool sCPU::nmi_read_pos_match(uint offset) {
uint16 v = !overscan() ? 225 : 240;
uint16 h = 2 + offset;
return (status.vcounter == v && status.hclock == h);
alwaysinline void sCPU::irq_tick() {
counter.irq_fire -= 2;
if(counter.irq_fire != 0) { return; }
if(status.virq_enabled == true || status.hirq_enabled == true) {
status.irq_line = 0;
status.irq_transition = 1;
}
}
bool sCPU::irq_read_pos_match(uint offset) {
if(irq_pos_valid() == false)return false;
uint vpos = status.virq_pos;
uint hpos = (status.hirq_enabled) ? status.hirq_pos : 0;
hpos = (hpos != 0) ? ((hpos << 2) + 14) : 10;
hpos += offset;
if(hpos >= status.line_clocks) {
hpos -= status.line_clocks;
if(++vpos >= status.field_lines) {
vpos = 0;
}
alwaysinline void sCPU::poll_interrupts() {
if(status.hclock == status.nmi_trigger_pos) {
status.nmi_read = 0;
counter.nmi_fire = 4;
}
if((status.virq_enabled == true && status.vcounter == vpos) || status.virq_enabled == false) {
return (status.hclock == hpos);
}
if(status.hclock == 10) { status.irq_lock = false; }
return false;
if(status.hirq_trigger_pos == IRQ_TRIGGER_NEVER)return;
if(status.virq_enabled == false && status.hirq_enabled == false)return;
if(status.irq_lock == true)return;
uint vpos = status.vcounter;
uint hpos = status.hclock;
timeshift_backward(10, vpos, hpos);
bool trigger_irq = true;
if(status.virq_enabled == true && vpos != status.virq_trigger_pos)trigger_irq = false;
if(status.hirq_enabled == true && hpos != status.hirq_trigger_pos)trigger_irq = false;
if(trigger_irq == true) {
status.irq_lock = true;
status.irq_read = 0;
counter.irq_fire = 4;
}
}
bool sCPU::irq_pos_valid() {
@ -136,7 +74,7 @@ uint vlimit = region_scanlines() >> 1;
return true;
}
bool sCPU::nmi_test() {
alwaysinline bool sCPU::nmi_test() {
if(status.nmi_transition == 0)return false;
status.nmi_transition = 0;
@ -144,11 +82,11 @@ bool sCPU::nmi_test() {
return true;
}
bool sCPU::irq_test() {
alwaysinline bool sCPU::irq_test() {
if(status.irq_transition == 1)goto irq_trigger;
if(status.irq_read == 0) {
if(status.irq_line == 1 && (irq_read_pos_match(0) || irq_read_pos_match(2))) {
if(status.irq_line == 1 && counter.irq_fire) {
return false;
}
goto irq_trigger;

View File

@ -1,52 +1,8 @@
void sCPU::run_manual_joypad_poll() {
snes->poll_input(SNES::DEV_JOYPAD1);
snes->poll_input(SNES::DEV_JOYPAD2);
status.joypad1_bits = uint8(snes->get_input_status(SNES::DEV_JOYPAD1, SNES::JOYPAD_B)) << 0;
status.joypad1_bits |= uint8(snes->get_input_status(SNES::DEV_JOYPAD1, SNES::JOYPAD_Y)) << 1;
status.joypad1_bits |= uint8(snes->get_input_status(SNES::DEV_JOYPAD1, SNES::JOYPAD_SELECT)) << 2;
status.joypad1_bits |= uint8(snes->get_input_status(SNES::DEV_JOYPAD1, SNES::JOYPAD_START)) << 3;
status.joypad1_bits |= uint8(snes->get_input_status(SNES::DEV_JOYPAD1, SNES::JOYPAD_UP)) << 4;
status.joypad1_bits |= uint8(snes->get_input_status(SNES::DEV_JOYPAD1, SNES::JOYPAD_DOWN)) << 5;
status.joypad1_bits |= uint8(snes->get_input_status(SNES::DEV_JOYPAD1, SNES::JOYPAD_LEFT)) << 6;
status.joypad1_bits |= uint8(snes->get_input_status(SNES::DEV_JOYPAD1, SNES::JOYPAD_RIGHT)) << 7;
status.joypad1_bits |= uint8(snes->get_input_status(SNES::DEV_JOYPAD1, SNES::JOYPAD_A)) << 8;
status.joypad1_bits |= uint8(snes->get_input_status(SNES::DEV_JOYPAD1, SNES::JOYPAD_X)) << 9;
status.joypad1_bits |= uint8(snes->get_input_status(SNES::DEV_JOYPAD1, SNES::JOYPAD_L)) << 10;
status.joypad1_bits |= uint8(snes->get_input_status(SNES::DEV_JOYPAD1, SNES::JOYPAD_R)) << 11;
status.joypad2_bits = uint8(snes->get_input_status(SNES::DEV_JOYPAD2, SNES::JOYPAD_B)) << 0;
status.joypad2_bits |= uint8(snes->get_input_status(SNES::DEV_JOYPAD2, SNES::JOYPAD_Y)) << 1;
status.joypad2_bits |= uint8(snes->get_input_status(SNES::DEV_JOYPAD2, SNES::JOYPAD_SELECT)) << 2;
status.joypad2_bits |= uint8(snes->get_input_status(SNES::DEV_JOYPAD2, SNES::JOYPAD_START)) << 3;
status.joypad2_bits |= uint8(snes->get_input_status(SNES::DEV_JOYPAD2, SNES::JOYPAD_UP)) << 4;
status.joypad2_bits |= uint8(snes->get_input_status(SNES::DEV_JOYPAD2, SNES::JOYPAD_DOWN)) << 5;
status.joypad2_bits |= uint8(snes->get_input_status(SNES::DEV_JOYPAD2, SNES::JOYPAD_LEFT)) << 6;
status.joypad2_bits |= uint8(snes->get_input_status(SNES::DEV_JOYPAD2, SNES::JOYPAD_RIGHT)) << 7;
status.joypad2_bits |= uint8(snes->get_input_status(SNES::DEV_JOYPAD2, SNES::JOYPAD_A)) << 8;
status.joypad2_bits |= uint8(snes->get_input_status(SNES::DEV_JOYPAD2, SNES::JOYPAD_X)) << 9;
status.joypad2_bits |= uint8(snes->get_input_status(SNES::DEV_JOYPAD2, SNES::JOYPAD_L)) << 10;
status.joypad2_bits |= uint8(snes->get_input_status(SNES::DEV_JOYPAD2, SNES::JOYPAD_R)) << 11;
}
/*****
* The joypad contains a small bit shifter that has 16 bits.
* Reading from 4016 reads one bit from this buffer, then moves
* the buffer left one, and adds a '1' to the rightmost bit.
* Writing a one to $4016 will fill the buffer with the current
* joypad button states, and lock the bit shifter at position
* zero. All reads will be the first buffer state, or 'B'.
* A zero must be written back to $4016 to unlock the buffer,
* so that reads will increment the bit shifting position.
*****/
void sCPU::run_auto_joypad_poll() {
run_manual_joypad_poll();
uint16 joy1 = 0x0000, joy2 = 0x0000;
uint16 joy1 = 0, joy2 = 0;
for(int i = 0; i < 16; i++) {
joy1 |= (!!(status.joypad1_bits & (0x8000 >> i))) << i;
joy2 |= (!!(status.joypad2_bits & (0x8000 >> i))) << i;
joy1 |= (uint16)snes->port_read(0) ? (0x8000 >> i) : 0;
joy2 |= (uint16)snes->port_read(1) ? (0x8000 >> i) : 0;
}
status.joy1l = joy1;
@ -60,10 +16,4 @@ uint16 joy1 = 0x0000, joy2 = 0x0000;
status.joy4l = 0x00;
status.joy4h = 0x00;
status.joypad1_bits >>= 16;
status.joypad2_bits >>= 16;
status.joypad1_bits |= 0xffff;
status.joypad2_bits |= 0xffff;
}

View File

@ -0,0 +1,26 @@
alwaysinline void sCPU::timeshift_forward(uint clocks, uint &vtime, uint &htime) {
htime += clocks;
if(htime >= status.line_clocks) {
htime -= status.line_clocks;
if(++vtime >= status.field_lines) {
vtime = 0;
}
}
}
alwaysinline void sCPU::timeshift_backward(uint clocks, uint &vtime, uint &htime) {
if(htime >= clocks) {
htime -= clocks;
} else {
htime += 1364 - clocks;
if(status.region == SNES::NTSC && status.vcounter == 241 &&
status.interlace == false && status.interlace_field == 1)htime -= 4;
if(vtime > 0) {
vtime--;
} else {
vtime = status.region_scanlines;
if(status.interlace == true && status.interlace_field == 1)vtime++;
}
}
}

View File

@ -2,19 +2,30 @@
(status.region == SNES::NTSC && status.vcounter == 240 && \
status.interlace == false && status.interlace_field == 1)
#include "timeshift.cpp"
#include "irq.cpp"
#include "joypad.cpp"
uint16 sCPU::vcounter() { return status.vcounter; }
uint16 sCPU::hcycles() { return status.hclock; }
uint16 sCPU::hclock() { return status.hclock; }
bool sCPU::interlace() { return status.interlace; }
bool sCPU::interlace_field() { return status.interlace_field; }
bool sCPU::overscan() { return status.overscan; }
uint16 sCPU::region_scanlines() { return status.region_scanlines; }
void sCPU::set_interlace(bool r) { status.interlace = r; update_interrupts(); }
void sCPU::set_overscan (bool r) { status.overscan = r; update_interrupts(); }
uint sCPU::dma_counter() { return (status.dma_counter + status.hclock) & 7; }
void sCPU::set_interlace(bool r) {
status.interlace = r;
update_interrupts();
}
void sCPU::set_overscan (bool r) {
status.overscan = r;
status.vblstart = (status.overscan == false) ? 225 : 240;
update_interrupts();
}
/*****
* One PPU dot = 4 CPU clocks
@ -34,36 +45,41 @@ uint16 sCPU::hcounter() {
}
void sCPU::add_clocks(uint clocks) {
if(status.irq_delay) {
if(status.irq_delay >= clocks) {
status.irq_delay -= clocks;
} else {
status.irq_delay = 0;
}
}
status.clocks_executed += clocks;
poll_interrupts(clocks);
if(counter.irq_delay) {
counter.irq_delay = (counter.irq_delay > clocks) ? (counter.irq_delay - clocks) : 0;
}
if(status.hclock + clocks >= status.line_clocks) {
clocks = (status.hclock + clocks) - status.line_clocks;
status.hclock = 0;
while(status.hclock < status.line_clocks - 2) { tick(); }
scanline();
poll_interrupts(clocks);
}
status.hclock += clocks;
clocks >>= 1;
while(clocks--) { tick(); }
}
if(status.dram_refreshed == false) {
if(status.hclock >= 530) {
status.dram_refreshed = true;
add_clocks(40);
return;
}
alwaysinline void sCPU::tick() {
status.hclock += 2;
if(counter.nmi_fire) { nmi_tick(); }
if(counter.irq_fire) { irq_tick(); }
if(status.dram_refreshed == false && status.hclock >= status.dram_refresh_position) {
status.dram_refreshed = true;
add_clocks(40);
return;
}
poll_interrupts();
}
void sCPU::scanline() {
status.hclock = 0;
status.dma_counter = (status.dma_counter + status.line_clocks) & 7;
if(++status.vcounter >= status.field_lines) {
frame();
}
@ -72,9 +88,18 @@ void sCPU::scanline() {
//dram refresh occurs once every scanline
status.dram_refreshed = false;
if(cpu_version == 2) {
if(ntsc_color_burst_phase_shift_scanline() == false) {
if(status.dram_refresh_position == 534) {
status.dram_refresh_position = 538;
} else {
status.dram_refresh_position = 534;
}
}
}
//hdma triggers once every visible scanline
status.line_rendered =
status.line_rendered = false;
status.hdma_triggered = (status.vcounter <= (!overscan() ? 224 : 239)) ? false : true;
r_ppu->scanline();
@ -83,6 +108,7 @@ void sCPU::scanline() {
update_interrupts();
if(status.auto_joypad_poll == true && status.vcounter == (!overscan() ? 227 : 242)) {
snes->poll_input();
run_auto_joypad_poll();
}
}
@ -98,7 +124,13 @@ void sCPU::frame() {
//interlaced even fields have one extra scanline
//(263+262=525 NTSC, 313+312=625 PAL)
if(status.interlace == true && status.interlace_field == 0)status.field_lines++;
status.hdmainit_triggered = false;
if(cpu_version == 1) {
status.hdmainit_trigger_position = 12 + 8 - dma_counter();
} else {
status.hdmainit_trigger_position = 12 + dma_counter();
}
r_ppu->frame();
snes->frame();
@ -109,7 +141,12 @@ void sCPU::frame() {
*
* Used for DMA/HDMA bus synchronization
*****/
void sCPU::precycle_edge() {
alwaysinline void sCPU::precycle_edge() {
if(status.dma_state == DMASTATE_CPUSYNC) {
status.dma_state = DMASTATE_INACTIVE;
uint n = status.clock_count - (status.dma_clocks % status.clock_count);
add_clocks(n ? n : status.clock_count);
}
}
/*****
@ -119,23 +156,59 @@ void sCPU::precycle_edge() {
*****/
void sCPU::cycle_edge() {
if(status.line_rendered == false) {
if(status.hclock >= 128) {
if(status.hclock >= status.line_render_position) {
status.line_rendered = true;
r_ppu->render_scanline();
}
}
switch(status.dma_state) {
case DMASTATE_INACTIVE:
break;
case DMASTATE_DMASYNC:
status.dma_state = DMASTATE_RUN;
break;
case DMASTATE_RUN:
status.dma_state = DMASTATE_CPUSYNC;
status.dma_clocks = 8 - dma_counter() + 8;
add_clocks(status.dma_clocks);
if(status.hdmainit_pending) { hdma_init(); status.hdmainit_pending = false; }
if(status.hdma_pending) { hdma_run(); status.hdma_pending = false; }
if(status.dma_pending) { dma_run(); status.dma_pending = false; }
break;
}
if(status.hdmainit_triggered == false) {
if(status.hclock >= 12 || status.vcounter) {
if(status.hclock >= status.hdmainit_trigger_position || status.vcounter) {
status.hdmainit_triggered = true;
hdma_init();
hdma_init_reset();
if(hdma_enabled_channels()) {
if(status.dma_state == DMASTATE_INACTIVE) {
status.dma_state = DMASTATE_DMASYNC;
status.hdmainit_pending = true;
} else {
hdma_init();
}
}
}
}
if(status.hdma_triggered == false) {
if(status.hclock >= 1106) {
status.hdma_triggered = true;
hdma_run();
if(hdma_active_channels()) {
if(status.dma_state == DMASTATE_INACTIVE) {
status.dma_state = DMASTATE_DMASYNC;
status.hdma_pending = true;
} else {
hdma_run();
}
}
}
}
}
@ -150,7 +223,7 @@ void sCPU::cycle_edge() {
* trigger during certain events (immediately after DMA, writes to $4200, etc)
*****/
void sCPU::last_cycle() {
if(status.irq_delay)return;
if(counter.irq_delay) { return; }
status.nmi_pending |= nmi_test();
status.irq_pending |= irq_test();
@ -174,6 +247,12 @@ void sCPU::timing_power() {
}
void sCPU::timing_reset() {
counter.enabled = false;
counter.irq_delay = 0;
counter.hw_math = 0;
counter.irq_fire = 0;
counter.nmi_fire = 0;
status.clock_count = 0;
status.clocks_executed = 0;
@ -185,14 +264,21 @@ void sCPU::timing_reset() {
status.interlace_field = 0;
status.overscan = false;
status.region_scanlines = (status.region == SNES::NTSC) ? 525 : 625;
status.vblstart = 225;
status.field_lines = status.region_scanlines >> 1;
status.line_clocks = 1364;
status.line_rendered = false;
status.dram_refreshed = false;
status.hdmainit_triggered = false;
status.hdma_triggered = false;
status.line_rendered = false;
status.line_render_position = minmax<0, 1112>((uint16)config::ppu.render_scanline_position);
status.dram_refreshed = false;
status.dram_refresh_position = (cpu_version == 1) ? 530 : 538;
status.hdmainit_triggered = false;
status.hdmainit_trigger_position = 0;
status.hdma_triggered = false;
status.irq_delay = 0;
@ -204,10 +290,17 @@ void sCPU::timing_reset() {
status.irq_read = 1;
status.irq_line = 1;
status.irq_transition = 0;
status.irq_lock = false;
status.irq_pending = false;
update_interrupts();
status.dma_counter = 0;
status.dma_state = DMASTATE_INACTIVE;
status.dma_pending = false;
status.hdma_pending = false;
status.hdmainit_pending = false;
//initial latch values for $213c/$213d
//[x]0035 : [y]0000 (53.0 -> 212) [lda $2137]
//[x]0038 : [y]0000 (56.5 -> 226) [nop : lda $2137]

View File

@ -1,6 +1,6 @@
uint16 vcounter();
uint16 hcounter();
uint16 hcycles();
uint16 hclock();
bool interlace();
bool interlace_field();
@ -10,7 +10,10 @@
void set_interlace(bool r);
void set_overscan(bool r);
uint dma_counter();
void add_clocks(uint clocks);
void tick();
void scanline();
void frame();
@ -22,16 +25,23 @@
void timing_power();
void timing_reset();
void counter_set(uint &ctr, uint clocks) {
if(clocks >= ctr) { ctr = clocks; }
}
//timeshift.cpp
void timeshift_forward (uint clocks, uint &v, uint &h);
void timeshift_backward(uint clocks, uint &v, uint &h);
//irq.cpp
void set_irq_delay(uint clocks);
enum { IRQ_TRIGGER_NEVER = 0x3fff };
void update_interrupts();
void poll_interrupts(int clocks);
bool nmi_read_pos_match(uint offset);
bool irq_read_pos_match(uint offset);
void nmi_tick();
void irq_tick();
void poll_interrupts();
bool irq_pos_valid();
bool nmi_test();
bool irq_test();
//joypad.cpp
void run_manual_joypad_poll();
void run_auto_joypad_poll();

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.2 KiB

After

Width:  |  Height:  |  Size: 26 KiB

View File

Before

Width:  |  Height:  |  Size: 4.2 KiB

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

View File

@ -185,7 +185,7 @@ int n = addr & 15;
}
void bDSP::power() {
spcram = r_apu->get_spcram_handle();
spcram = r_smp->get_spcram_handle();
memset(dspram, 0x00, 128);
for(int v = 0; v < 8; v++) {

View File

@ -7,7 +7,7 @@
#define r_mem ref(deref(mem))
#define r_cpu ref(deref(cpu))
#define r_apu ref(deref(apu))
#define r_smp ref(deref(smp))
#define r_dsp ref(deref(dsp))
#define r_ppu ref(deref(ppu))
@ -22,9 +22,9 @@
#include "cpu/scpu/scpu.h"
//#include "cpu/bcpu/bcpu.h"
#include "apu/apu.h"
#include "apu/sapu/sapu.h"
//#include "apu/bapu/bapu.h"
#include "smp/smp.h"
#include "smp/ssmp/ssmp.h"
//#include "smp/bsmp/bsmp.h"
#include "dsp/dsp.h"
#include "dsp/bdsp/bdsp.h"
@ -45,52 +45,32 @@ extern MMIO mmio_unmapped;
#ifdef POLYMORPHISM
extern MemBus *deref(mem);
extern CPU *deref(cpu);
extern APU *deref(apu);
extern SMP *deref(smp);
extern DSP *deref(dsp);
extern PPU *deref(ppu);
#else
extern MEMCORE deref(mem);
extern CPUCORE deref(cpu);
extern APUCORE deref(apu);
extern SMPCORE deref(smp);
extern DSPCORE deref(dsp);
extern PPUCORE deref(ppu);
#endif
extern SNES *snes;
extern SRTC *srtc;
extern SDD1 *sdd1;
extern C4 *c4;
extern DSP1 *dsp1;
extern DSP2 *dsp2;
extern OBC1 *obc1;
#include "config/config.h"
#ifdef INTERFACE_MAIN
Cartridge cartridge;
Cheat cheat;
#include "config/config.cpp"
#ifdef POLYMORPHISM
MemBus *deref(mem);
CPU *deref(cpu);
APU *deref(apu);
DSP *deref(dsp);
PPU *deref(ppu);
#else
MEMCORE deref(mem);
CPUCORE deref(cpu);
APUCORE deref(apu);
DSPCORE deref(dsp);
PPUCORE deref(ppu);
#endif
SNES *snes;
SRTC *srtc;
SDD1 *sdd1;
C4 *c4;
DSP1 *dsp1;
DSP2 *dsp2;
OBC1 *obc1;
#include "config/config.cpp"
#ifdef POLYMORPHISM
MemBus *deref(mem);
CPU *deref(cpu);
APU *deref(smp);
DSP *deref(dsp);
PPU *deref(ppu);
#else
MEMCORE deref(mem);
CPUCORE deref(cpu);
SMPCORE deref(smp);
DSPCORE deref(dsp);
PPUCORE deref(ppu);
#endif
#endif

79
src/lib/libarray.h Normal file
View File

@ -0,0 +1,79 @@
/*
libarray : version 0.07 ~byuu (10/14/06)
*/
#ifndef __LIBARRAY
#define __LIBARRAY
template<typename T> class array {
protected:
T *pool;
uint poolsize, buffersize;
protected:
uint findsize(uint size) {
if(size <= 0x100) { return 0x100; }
if(size <= 0x400) { return 0x400; }
if(size <= 0x1000) { return 0x1000; }
if(size <= 0x4000) { return 0x4000; }
if(size <= 0x10000) { return 0x10000; }
if(size <= 0x40000) { return 0x40000; }
if(size <= 0x100000) { return 0x100000; }
return (size + 0x100000) & ~0xfffff;
}
public:
uint size() { return buffersize; }
uint capacity() { return buffersize; }
void reset() {
if(pool) {
free(pool);
pool = 0;
}
poolsize = 0;
buffersize = 0;
}
void reserve(uint size) {
if(size == poolsize)return;
if(size < poolsize) {
buffersize = size;
}
pool = static_cast<T*>(realloc(pool, sizeof(T) * size));
poolsize = size;
}
T *get(uint size = 0) {
if(size > buffersize)resize(size);
if(size > buffersize)throw "array[] out of bounds";
return pool;
}
void clear() { memset(pool, 0, sizeof(T) * buffersize); }
void resize(uint size) {
reserve(findsize(size));
buffersize = size;
}
array() {
pool = 0;
poolsize = 0;
buffersize = 0;
}
~array() { reset(); }
inline T &operator[](int index) {
if(index >= buffersize)resize(index + 1);
if(index >= buffersize)throw "array[] out of bounds";
return pool[index];
}
};
#endif

View File

@ -1,5 +1,5 @@
/*
libbase : version 0.08b ~byuu (07/30/06)
libbase : version 0.08c ~byuu (09/28/06)
*/
#ifndef __LIBBASE
@ -8,6 +8,9 @@
#if defined(_MSC_VER)
//disable libc deprecation warnings in MSVC 2k5+
#pragma warning(disable:4996)
#define ftruncate _chsize
#define vsnprintf _vsnprintf
#endif
/*****
@ -15,15 +18,15 @@
*****/
#if defined(_MSC_VER)
#define noinline __declspec(noinline)
#define inline inline
#define forceinline __forceinline
#define fastcall __fastcall
#define noinline __declspec(noinline)
#define inline inline
#define alwaysinline __forceinline
#define fastcall __fastcall
#elif defined(__GNUC__)
#define noinline
#define inline inline
#define forceinline inline
#define fastcall __attribute__((fastcall))
#define inline inline
#define alwaysinline inline
#define fastcall __attribute__((fastcall))
#else
#error "unsupported compiler"
#endif
@ -34,6 +37,7 @@
#include <string.h>
#include <time.h>
#include <math.h>
#include <io.h>
#ifndef FALSE
#define FALSE 0
@ -217,8 +221,6 @@ typedef int_t<48, int64> int48;
#define order_msb6(a,b,c,d,e,f) f,e,d,c,b,a
#define order_msb7(a,b,c,d,e,f,g) g,f,e,d,c,b,a
#define order_msb8(a,b,c,d,e,f,g,h) h,g,f,e,d,c,b,a
#define order_lsbit8(b0,b1,b2,b3,b4,b5,b6,b7) b7:1,b6:1,b5:1,b4:1,b3:1,b2:1,b1:1,b0:1
#define order_msbit8(b7,b6,b5,b4,b3,b2,b1,b0) b0:1,b1:1,b2:1,b3:1,b4:1,b5:1,b6:1,b7:1
#else
//big-endian: uint8[] { 0x01, 0x02, 0x03, 0x04 } = 0x01020304
#define order_lsb2(a,b) b,a
@ -235,15 +237,13 @@ typedef int_t<48, int64> int48;
#define order_msb6(a,b,c,d,e,f) a,b,c,d,e,f
#define order_msb7(a,b,c,d,e,f,g) a,b,c,d,e,f,g
#define order_msb8(a,b,c,d,e,f,g,h) a,b,c,d,e,f,g,h
#define order_lsbit8(b7,b6,b5,b4,b3,b2,b1,b0) b0:1,b1:1,b2:1,b3:1,b4:1,b5:1,b6:1,b7:1
#define order_msbit8(b0,b1,b2,b3,b4,b5,b6,b7) b7:1,b6:1,b5:1,b4:1,b3:1,b2:1,b1:1,b0:1
#endif
/*****
* libc extensions
*****/
inline bool fexists(const char *fn) {
static bool fexists(const char *fn) {
FILE *fp = fopen(fn, "rb");
if(!fp)return false;
fclose(fp);
@ -251,7 +251,7 @@ FILE *fp = fopen(fn, "rb");
return true;
}
inline uint32 fsize(FILE *fp) {
static uint32 fsize(FILE *fp) {
if(!fp)return 0;
uint32 pos = ftell(fp);
fseek(fp, 0, SEEK_END);
@ -260,7 +260,7 @@ uint32 size = ftell(fp);
return size;
}
inline uint32 fsize(const char *fn) {
static uint32 fsize(const char *fn) {
FILE *fp = fopen(fn, "rb");
if(!fp)return 0;
fseek(fp, 0, SEEK_END);
@ -270,6 +270,8 @@ uint32 size = ftell(fp);
return size;
}
inline int ftruncate(FILE *fp, long size) { return ftruncate(fileno(fp), size); }
/*****
* crc32 calculation
* TODO: create libhash and move this code there

View File

@ -184,7 +184,7 @@ char *buffer = (char*)malloc(fsize + 1);
return true;
}
bool Config::load(substring &fn) { return load(strptr(fn)); }
bool Config::load(string &fn) { return load(strptr(fn)); }
bool Config::save(char *fn) {
FILE *fp;
@ -209,7 +209,7 @@ FILE *fp;
return true;
}
bool Config::save(substring &fn) { return save(strptr(fn)); }
bool Config::save(string &fn) { return save(strptr(fn)); }
Config::Config() {
list_count = 0;

View File

@ -1,31 +1,15 @@
/*
libconfig : version 0.08a ~byuu (07/16/06)
libconfig : version 0.10 ~byuu (10/10/06)
*/
#ifndef __LIBCONFIG
#define __LIBCONFIG
#include "libarray.h"
#include "libstring.h"
class Config;
//operator= is the /only/ overloaded operator that isn't inherited by derived classes.
//similarly, base constructor/destructors with arguments are not inherited.
//the inclusion of the overloaded virtual function 'toggle' is to allow toggle to call
//the overloaded set() function, if it exists. for some reason, Setting::toggle() calls
//Setting::set() no matter what, even if the derived class defines set()...
//the below macro is a quick way to take care of all of these issues.
//usage example:
// class T : public Setting { public: SettingOperators(T); } t;
// t = 0; // -> t.set(0);
#define SettingOperators(__name) \
template<typename T> inline __name &operator=(const T &x) { set(x); return *this; } \
void toggle() { data ^= 1; set(data); } \
__name(Config *_parent, char *_name, char *_desc, uint _data, uint _type) : \
Setting(_parent, _name, _desc, _data, _type) {} \
__name(Config *_parent, char *_name, char *_desc, char *_data) : \
Setting(_parent, _name, _desc, _data) {}
class Setting {
friend class Config;
@ -49,7 +33,7 @@ enum {
STR = 10,
};
char *name, *desc;
substring char_data, char_def;
string char_data, char_def;
virtual void toggle();
virtual uint get();
virtual void set(uint _data);
@ -72,10 +56,11 @@ substring char_data, char_def;
class Config {
protected:
vector<Setting*> list;
array<Setting*> list;
uint list_count;
string data, line, part, subpart;
string data;
stringarray line, part, subpart;
uint string_to_uint(uint type, char *input);
char *uint_to_string(uint type, uint input);
@ -83,9 +68,9 @@ char *uint_to_string(uint type, uint input);
public:
void add(Setting *setting);
bool load(char *fn);
bool load(substring &fn);
bool load(string &fn);
bool save(char *fn);
bool save(substring &fn);
bool save(string &fn);
Config();
};

View File

@ -1,49 +0,0 @@
#include "libbase.h"
#include "libvector.h"
#include "libfile.h"
/*****
* c wrappers
*****/
void fread(file *s, uint8 *data, uint length) { s->read(data, length); }
uint8 fread(file *s) { return s->read(); }
uint8 fgetc(file *s) { return s->read(); }
void fwrite(file *s, uint8 *data, uint length) { s->write(data, length); }
void fwrite(file *s, uint8 data) { s->write(data); }
void fputc(file *s, uint8 data) { s->write(data); }
void fseek(file *s, uint offset, uint mode) { s->seek(offset, mode); }
uint foffset(file *s) { return s->offset(); }
uint ftell(file *s) { return s->offset(); }
uint fsize(file *s) { return s->size(); }
bool feof(file *s) { return s->eof(); }
bool fopen(file *s, const char *filename, uint mode) { return s->open(filename, mode); }
bool fopen(file *s) { return s->open(); }
bool fflush(file *s) { return s->flush(); }
bool fclose(file *s) { return s->close(); }
/*****
* c++ wrappers
*****/
void fread(file &s, uint8 *data, uint length) { s.read(data, length); }
uint8 fread(file &s) { return s.read(); }
uint8 fgetc(file &s) { return s.read(); }
void fwrite(file &s, uint8 *data, uint length) { s.write(data, length); }
void fwrite(file &s, uint8 data) { s.write(data); }
void fputc(file &s, uint8 data) { s.write(data); }
void fseek(file &s, uint offset, uint mode) { s.seek(offset, mode); }
uint foffset(file &s) { return s.offset(); }
uint ftell(file &s) { return s.offset(); }
uint fsize(file &s) { return s.size(); }
bool feof(file &s) { return s.eof(); }
bool fopen(file &s, const char *filename, uint mode) { return s.open(filename, mode); }
bool fopen(file &s) { return s.open(); }
bool fflush(file &s) { return s.flush(); }
bool fclose(file &s) { return s.close(); }

View File

@ -1,12 +1,12 @@
/*
libfile : version 0.02 ~byuu (06/17/06)
libfile : version 0.05 ~byuu (10/12/06)
*/
#ifndef __LIBFILE
#define __LIBFILE
/*****
* file base class
* file object
*****/
class file {
@ -19,7 +19,10 @@ enum { seek_start, seek_end, seek_back, seek_forward };
virtual void write(uint8 *data, uint length) = 0;
virtual void write(uint8 data) = 0;
virtual uint32 crc32();
virtual void seek(uint offset, uint mode = seek_start) = 0;
virtual void truncate(uint size) = 0;
virtual uint offset() = 0;
virtual uint size() = 0;
virtual bool eof() = 0;
@ -30,51 +33,128 @@ enum { seek_start, seek_end, seek_back, seek_forward };
virtual bool close() = 0;
};
/*****
* c wrappers
*****/
void fread(file *s, uint8 *data, uint length);
uint8 fread(file *s);
uint8 fgetc(file *s);
void fwrite(file *s, uint8 *data, uint length);
void fwrite(file *s, uint8 data);
void fputc(file *s, uint8 data);
void fseek(file *s, uint offset, uint mode = file::seek_start);
uint foffset(file *s);
uint ftell(file *s);
uint fsize(file *s);
bool feof(file *s);
bool fopen(file *s, const char *filename, uint mode);
bool fopen(file *s);
bool fflush(file *s);
bool fclose(file *s);
inline uint32 file::crc32() {
uint pos = offset(), i = size();
seek(0);
uint32 crc32 = 0xffffffff;
while(i--) {
crc32 = crc32_adjust(crc32, read());
}
seek(pos);
return ~crc32;
}
/*****
* c++ wrappers
*****/
void fread(file &s, uint8 *data, uint length);
uint8 fread(file &s);
uint8 fgetc(file &s);
inline void fread(file &s, uint8 *data, uint length) { s.read(data, length); }
inline uint8 fread(file &s) { return s.read(); }
inline uint8 fgetc(file &s) { return s.read(); }
void fwrite(file &s, uint8 *data, uint length);
void fwrite(file &s, uint8 data);
void fputc(file &s, uint8 data);
inline void fwrite(file &s, uint8 *data, uint length) { s.write(data, length); }
inline void fwrite(file &s, uint8 data) { s.write(data); }
inline void fputc(file &s, uint8 data) { s.write(data); }
void fseek(file &s, uint offset, uint mode = file::seek_start);
uint foffset(file &s);
uint ftell(file &s);
uint fsize(file &s);
bool feof(file &s);
inline uint32 fcrc32(file &s) { return s.crc32(); }
bool fopen(file &s, const char *filename, uint mode);
bool fopen(file &s);
bool fflush(file &s);
bool fclose(file &s);
inline void fseek(file &s, uint offset, uint mode = file::seek_start) { s.seek(offset, mode); }
inline void ftruncate(file &s, uint size) { s.truncate(size); }
inline uint ftell(file &s) { return s.offset(); }
inline uint fsize(file &s) { return s.size(); }
inline bool feof(file &s) { return s.eof(); }
inline bool fopen(file &s, const char *filename, uint mode) { return s.open(filename, mode); }
inline bool fopen(file &s) { return s.open(); }
inline bool fflush(file &s) { return s.flush(); }
inline bool fclose(file &s) { return s.close(); }
/*****
* endian wrappers
*****/
inline uint8 fgetlb(file &s) { return fgetc(s); }
inline uint8 fgetmb(file &s) { return fgetc(s); }
inline uint16 fgetlw(file &s) {
return (fgetc(s)) | (fgetc(s) << 8);
}
inline uint16 fgetmw(file &s) {
return (fgetc(s) << 8) | (fgetc(s) << 8);
}
inline uint32 fgetld(file &s) {
return (fgetc(s)) | (fgetc(s) << 8) | (fgetc(s) << 16) | (fgetc(s) << 24);
}
inline uint32 fgetmd(file &s) {
return (fgetc(s) << 24) | (fgetc(s) << 16) | (fgetc(s) << 8) | (fgetc(s));
}
inline uint64 fgetlq(file &s) {
return ((uint64)fgetc(s) << 0) | ((uint64)fgetc(s) << 8) |
((uint64)fgetc(s) << 16) | ((uint64)fgetc(s) << 24) |
((uint64)fgetc(s) << 32) | ((uint64)fgetc(s) << 40) |
((uint64)fgetc(s) << 48) | ((uint64)fgetc(s) << 56);
}
inline uint64 fgetmq(file &s) {
return ((uint64)fgetc(s) << 56) | ((uint64)fgetc(s) << 48) |
((uint64)fgetc(s) << 40) | ((uint64)fgetc(s) << 32) |
((uint64)fgetc(s) << 24) | ((uint64)fgetc(s) << 16) |
((uint64)fgetc(s) << 8) | ((uint64)fgetc(s) << 0);
}
inline void fputlb(file &s, uint8 data) { fputc(s, data); }
inline void fputmb(file &s, uint8 data) { fputc(s, data); }
inline void fputlw(file &s, uint16 data) {
fputc(s, data >> 0);
fputc(s, data >> 8);
}
inline void fputmw(file &s, uint16 data) {
fputc(s, data >> 8);
fputc(s, data >> 0);
}
inline void fputld(file &s, uint32 data) {
fputc(s, data >> 0);
fputc(s, data >> 8);
fputc(s, data >> 16);
fputc(s, data >> 24);
}
inline void fputmd(file &s, uint32 data) {
fputc(s, data >> 24);
fputc(s, data >> 16);
fputc(s, data >> 8);
fputc(s, data >> 0);
}
inline void fputlq(file &s, uint64 data) {
fputc(s, data >> 0);
fputc(s, data >> 8);
fputc(s, data >> 16);
fputc(s, data >> 24);
fputc(s, data >> 32);
fputc(s, data >> 40);
fputc(s, data >> 48);
fputc(s, data >> 56);
}
inline void fputmq(file &s, uint64 data) {
fputc(s, data >> 56);
fputc(s, data >> 48);
fputc(s, data >> 40);
fputc(s, data >> 32);
fputc(s, data >> 24);
fputc(s, data >> 16);
fputc(s, data >> 8);
fputc(s, data >> 0);
}
/*****
* ramfile
@ -83,18 +163,19 @@ bool fclose(file &s);
class ramfile : public file {
private:
FILE *fp;
vector<uint8> filedata;
array<uint8> filedata;
char filename[1024];
uint filepos;
uint filesize;
uint filemode;
bool fileopen;
bool filevirtual;
public:
void read(uint8 *data, uint length) {
if(!fileopen || filemode == mode_write) { return; }
filedata.read(filepos, data, length);
memcpy(data, filedata.get(filepos + length) + filepos, length);
filepos += length;
if(filepos > filesize)filepos = filesize;
}
@ -102,15 +183,14 @@ public:
uint8 read() {
if(!fileopen || filemode == mode_write) { return 0; }
uint8 r = filedata[filepos++];
if(filepos > filesize)filepos = filesize;
return r;
if(eof() == true) { return 0xff; }
return filedata[filepos++];
}
void write(uint8 *data, uint length) {
if(!fileopen || filemode == mode_read) { return; }
filedata.write(filepos, data, length);
memcpy(filedata.get(filepos + length) + filepos, data, length);
filepos += length;
if(filepos > filesize)filesize = filepos;
}
@ -127,7 +207,7 @@ public:
switch(mode) {
case seek_start: filepos = offset; break;
case seek_end: filepos = filesize - offset; break;
case seek_end: filepos = filesize + offset; break;
case seek_back: filepos -= offset; break;
case seek_forward: filepos += offset; break;
}
@ -139,6 +219,11 @@ public:
}
}
void truncate(uint size) {
filesize = size;
if(filepos > filesize)filepos = filesize;
}
uint offset() {
if(!fileopen) { return 0; }
@ -160,16 +245,21 @@ public:
bool open(const char *fn, uint mode) {
if(fileopen) { return false; }
strcpy(filename, fn);
strcpy(filename, fn ? fn : "");
filevirtual = (*filename == 0);
filemode = mode;
switch(filemode) {
case mode_read:
case mode_readwrite:
fp = fopen(filename, "rb");
if(!fp) { return false; }
filesize = fsize(fp);
fread(filedata.handle(filesize), 1, filesize, fp);
fclose(fp);
if(filevirtual == true) {
filesize = 0;
} else {
fp = fopen(filename, "rb");
if(!fp) { return false; }
filesize = fsize(fp);
fread(filedata.get(filesize), 1, filesize, fp);
fclose(fp);
}
break;
default:
filesize = 0;
@ -191,10 +281,12 @@ public:
case mode_readwrite:
case mode_write:
case mode_writeread:
fp = fopen(filename, "wb");
if(!fp) { return false; }
fwrite(filedata.handle(filesize), 1, filesize, fp);
fclose(fp);
if(filevirtual == false) {
fp = fopen(filename, "wb");
if(!fp) { return false; }
fwrite(filedata.get(filesize), 1, filesize, fp);
fclose(fp);
}
break;
}
return true;
@ -205,7 +297,7 @@ public:
bool result = flush();
fileopen = false;
filedata.release();
filedata.reset();
return result;
}
@ -237,6 +329,7 @@ public:
uint8 read() {
if(!fp || filemode == mode_write) { return 0; }
if(eof() == true) { return 0xff; }
return fgetc(fp);
}
@ -257,13 +350,19 @@ public:
switch(mode) {
default:
case seek_start: fseek(fp, offset, SEEK_SET); break;
case seek_end: fseek(fp, offset, SEEK_END); break;
case seek_back: fseek(fp, -offset, SEEK_CUR); break;
case seek_forward: fseek(fp, offset, SEEK_CUR); break;
case seek_start: fseek(fp, offset, SEEK_SET); break;
case seek_end: fseek(fp, offset, SEEK_END); break;
case seek_back: fseek(fp, offset, SEEK_CUR); break;
case seek_forward: fseek(fp, offset, SEEK_CUR); break;
}
}
void truncate(uint size) {
if(!fp) { return; }
ftruncate(fp, size);
}
uint offset() {
if(!fp) { return 0; }
@ -283,7 +382,12 @@ public:
bool eof() {
if(!fp) { return true; }
return feof(fp);
if(feof(fp)) {
seek(size(), seek_start);
return true;
}
return false;
}
bool open(const char *filename, uint mode) {
@ -331,4 +435,15 @@ public:
}
};
/*****
* directory object
*****/
class directory {
public:
void open(const char *path) {}
void close() {}
uint read(char *filename, uint maxlength) { return 0; }
};
#endif

View File

@ -1,38 +1,7 @@
#include "libbase.h"
#include "libstring.h"
substring::substring() {
size = 16;
s = (char*)malloc(size + 1);
*s = 0;
}
substring::~substring() {
SafeFree(s);
}
void string::addto(uint num) {
while(listcount < (num + 1)) {
list[listcount++] = new substring();
}
}
substring &string::str(uint num) {
if(listcount < (num + 1)) { addto(num); }
return *list[num];
}
string::string() {
count = 0;
listcount = 0;
addto(0);
}
string::~string() {
for(int i = listcount - 1; i >= 0; i--) {
delete((substring*)list[i]);
}
}
uint count(stringarray &str) { return str.size(); }
char chrlower(char c) {
if(c >= 'A' && c <= 'Z')return c + ('a' - 'A');
@ -44,21 +13,19 @@ char chrupper(char c) {
return c;
}
uint count(string &str) { return str.count; }
void strresize(substring &str, uint size) {
void strresize(string &str, uint size) {
str.s = (char*)realloc(str.s, size + 1);
str.s[size] = 0;
str.size = size;
}
char *strptr(substring &str) { return str.s; }
char *strptr(string &str) { return str.s; }
uint strlen(substring &str) { return strlen(strptr(str)); }
uint strlen(string &str) { return strlen(strptr(str)); }
int strcmp(substring &dest, const char *src) { return strcmp(strptr(dest), src); }
int strcmp(const char *dest, substring &src) { return strcmp(dest, strptr(src)); }
int strcmp(substring &dest, substring &src) { return strcmp(strptr(dest), strptr(src)); }
int strcmp(string &dest, const char *src) { return strcmp(strptr(dest), src); }
int strcmp(const char *dest, string &src) { return strcmp(dest, strptr(src)); }
int strcmp(string &dest, string &src) { return strcmp(strptr(dest), strptr(src)); }
int __stricmp(const char *dest, const char *src) {
while(*dest) {
@ -68,36 +35,36 @@ int __stricmp(const char *dest, const char *src) {
}
return (int)chrlower(*dest) - (int)chrlower(*src);
}
int stricmp(substring &dest, const char *src) { return __stricmp(strptr(dest), src); }
int stricmp(const char *dest, substring &src) { return __stricmp(dest, strptr(src)); }
int stricmp(substring &dest, substring &src) { return __stricmp(strptr(dest), strptr(src)); }
int stricmp(string &dest, const char *src) { return __stricmp(strptr(dest), src); }
int stricmp(const char *dest, string &src) { return __stricmp(dest, strptr(src)); }
int stricmp(string &dest, string &src) { return __stricmp(strptr(dest), strptr(src)); }
bool strmatch(const char *dest, const char *src) { return !strcmp(dest, src); }
bool strmatch(substring &dest, const char *src) { return strmatch(strptr(dest), src); }
bool strmatch(const char *dest, substring &src) { return strmatch(dest, strptr(src)); }
bool strmatch(substring &dest, substring &src) { return strmatch(strptr(dest), strptr(src)); }
bool strmatch(string &dest, const char *src) { return strmatch(strptr(dest), src); }
bool strmatch(const char *dest, string &src) { return strmatch(dest, strptr(src)); }
bool strmatch(string &dest, string &src) { return strmatch(strptr(dest), strptr(src)); }
bool strimatch(const char *dest, const char *src) { return !stricmp(dest, src); }
bool strimatch(substring &dest, const char *src) { return strimatch(strptr(dest), src); }
bool strimatch(const char *dest, substring &src) { return strimatch(dest, strptr(src)); }
bool strimatch(substring &dest, substring &src) { return strimatch(strptr(dest), strptr(src)); }
bool strimatch(string &dest, const char *src) { return strimatch(strptr(dest), src); }
bool strimatch(const char *dest, string &src) { return strimatch(dest, strptr(src)); }
bool strimatch(string &dest, string &src) { return strimatch(strptr(dest), strptr(src)); }
void strcpy(substring &dest, const char src) {
void strcpy(string &dest, const char src) {
if(1 > dest.size) { strresize(dest, 1); }
dest.s[0] = src;
dest.s[1] = 0;
}
void strcpy(substring &dest, const char *src) {
void strcpy(string &dest, const char *src) {
int srclen = strlen(src);
if(srclen > dest.size) { strresize(dest, srclen); }
strcpy(dest.s, src);
}
void strcpy(substring &dest, substring &src) { strcpy(dest, strptr(src)); }
void strcpy(string &dest, string &src) { strcpy(dest, strptr(src)); }
//this differs from libc's strncpy in that it always
//appends a null terminator to the end of a copied string
void strncpy(substring &dest, const char *src, uint32 length) {
void strncpy(string &dest, const char *src, uint32 length) {
int srclen = strlen(src);
//never copy more text than is in the string
if(srclen > length)srclen = length;
@ -105,38 +72,38 @@ int srclen = strlen(src);
strncpy(dest.s, src, srclen);
dest.s[srclen] = 0;
}
void strncpy(substring &dest, substring &src, uint32 length) { strncpy(dest, strptr(src), length); }
void strncpy(string &dest, string &src, uint32 length) { strncpy(dest, strptr(src), length); }
void strset(substring &dest, uint pos, uint8 c) {
void strset(string &dest, uint pos, uint8 c) {
if(pos > dest.size) { strresize(dest, pos); }
dest.s[pos] = c;
}
void strcat(substring &dest, const char src) {
void strcat(string &dest, const char src) {
int length = strlen(dest);
if(length + 1 > dest.size) { strresize(dest, length + 1); }
dest.s[length] = src;
dest.s[length + 1] = 0;
}
void strcat(substring &dest, const char *src) {
void strcat(string &dest, const char *src) {
int srclen = strlen(src);
int destlen = strlen(dest);
if(srclen + destlen > dest.size) { strresize(dest, srclen + destlen); }
strcat(dest.s, src);
}
void strcat(substring &dest, substring &src) { strcat(dest, strptr(src)); }
void strcat(string &dest, string &src) { strcat(dest, strptr(src)); }
void strinsert(substring &dest, const char *src, uint pos) {
static substring s;
void strinsert(string &dest, const char *src, uint pos) {
static string s;
strcpy(s, strptr(dest) + pos);
strset(dest, pos, 0);
strcat(dest, src);
strcat(dest, s);
}
void strinsert(substring &dest, substring &src, uint pos) { strinsert(dest, strptr(src), pos); }
void strinsert(string &dest, string &src, uint pos) { strinsert(dest, strptr(src), pos); }
void strremove(substring &dest, uint start, uint length) {
void strremove(string &dest, uint start, uint length) {
int destlen;
char *s;
int i, sl = strlen(dest.s);
@ -158,7 +125,7 @@ uint i = 0;
}
return str;
}
substring &strlower(substring &str) { strlower(strptr(str)); return str; }
string &strlower(string &str) { strlower(strptr(str)); return str; }
char *strupper(char *str) {
uint i = 0;
@ -168,7 +135,7 @@ uint i = 0;
}
return str;
}
substring &strupper(substring &str) { strupper(strptr(str)); return str; }
string &strupper(string &str) { strupper(strptr(str)); return str; }
bool strpos(const char *str, const char *key, uint &pos) {
int ssl = strlen(str), ksl = strlen(key);
@ -181,9 +148,9 @@ int ssl = strlen(str), ksl = strlen(key);
}
return false;
}
bool strpos(substring &str, const char *key, uint &pos) { return strpos(strptr(str), key, pos); }
bool strpos(const char *str, substring &key, uint &pos) { return strpos(str, strptr(key), pos); }
bool strpos(substring &str, substring &key, uint &pos) { return strpos(strptr(str), strptr(key), pos); }
bool strpos(string &str, const char *key, uint &pos) { return strpos(strptr(str), key, pos); }
bool strpos(const char *str, string &key, uint &pos) { return strpos(str, strptr(key), pos); }
bool strpos(string &str, string &key, uint &pos) { return strpos(strptr(str), strptr(key), pos); }
bool qstrpos(const char *str, const char *key, uint &pos) {
int ssl = strlen(str), ksl = strlen(key);
@ -204,9 +171,9 @@ int ssl = strlen(str), ksl = strlen(key);
}
return false;
}
bool qstrpos(substring &str, const char *key, uint &pos) { return qstrpos(strptr(str), key, pos); }
bool qstrpos(const char *str, substring &key, uint &pos) { return qstrpos(str, strptr(key), pos); }
bool qstrpos(substring &str, substring &key, uint &pos) { return qstrpos(strptr(str), strptr(key), pos); }
bool qstrpos(string &str, const char *key, uint &pos) { return qstrpos(strptr(str), key, pos); }
bool qstrpos(const char *str, string &key, uint &pos) { return qstrpos(str, strptr(key), pos); }
bool qstrpos(string &str, string &key, uint &pos) { return qstrpos(strptr(str), strptr(key), pos); }
void strtr(char *dest, const char *before, const char *after) {
int sl = strlen(dest), bsl = strlen(before), asl = strlen(after);
@ -220,14 +187,14 @@ int sl = strlen(dest), bsl = strlen(before), asl = strlen(after);
}
}
}
void strtr(substring &dest, const char *before, const char *after) { strtr(strptr(dest), before, after); }
void strtr(string &dest, const char *before, const char *after) { strtr(strptr(dest), before, after); }
bool strbegin(const char *str, const char *key) {
int i, ssl = strlen(str), ksl = strlen(key);
if(ksl > ssl)return false;
return (!memcmp(str, key, ksl));
}
bool strbegin(substring &str, const char *key) { return strbegin(strptr(str), key); }
bool strbegin(string &str, const char *key) { return strbegin(strptr(str), key); }
bool stribegin(const char *str, const char *key) {
int ssl = strlen(str), ksl = strlen(key);
@ -243,14 +210,14 @@ int ssl = strlen(str), ksl = strlen(key);
}
return true;
}
bool stribegin(substring &str, const char *key) { return stribegin(strptr(str), key); }
bool stribegin(string &str, const char *key) { return stribegin(strptr(str), key); }
bool strend(const char *str, const char *key) {
int ssl = strlen(str), ksl = strlen(key);
if(ksl > ssl)return false;
return (!memcmp(str + ssl - ksl, key, ksl));
}
bool strend(substring &str, const char *key) { return strend(strptr(str), key); }
bool strend(string &str, const char *key) { return strend(strptr(str), key); }
bool striend(const char *str, const char *key) {
int ssl = strlen(str), ksl = strlen(key);
@ -266,7 +233,7 @@ int ssl = strlen(str), ksl = strlen(key);
}
return true;
}
bool striend(substring &str, const char *key) { return striend(strptr(str), key); }
bool striend(string &str, const char *key) { return striend(strptr(str), key); }
void strltrim(char *str, const char *key) {
int i, ssl = strlen(str), ksl = strlen(key);
@ -276,7 +243,7 @@ int i, ssl = strlen(str), ksl = strlen(key);
str[i] = 0;
}
}
void strltrim(substring &str, const char *key) { strltrim(strptr(str), key); }
void strltrim(string &str, const char *key) { strltrim(strptr(str), key); }
void striltrim(char *str, const char *key) {
int i, ssl = strlen(str), ksl = strlen(key);
@ -286,7 +253,7 @@ int i, ssl = strlen(str), ksl = strlen(key);
str[i] = 0;
}
}
void striltrim(substring &str, const char *key) { striltrim(strptr(str), key); }
void striltrim(string &str, const char *key) { striltrim(strptr(str), key); }
void strrtrim(char *str, const char *key) {
int ssl = strlen(str), ksl = strlen(key);
@ -295,7 +262,7 @@ int ssl = strlen(str), ksl = strlen(key);
str[ssl - ksl] = 0;
}
}
void strrtrim(substring &str, const char *key) { strrtrim(strptr(str), key); }
void strrtrim(string &str, const char *key) { strrtrim(strptr(str), key); }
void strirtrim(char *str, const char *key) {
int ssl = strlen(str), ksl = strlen(key);
@ -304,11 +271,11 @@ int ssl = strlen(str), ksl = strlen(key);
str[ssl - ksl] = 0;
}
}
void strirtrim(substring &str, const char *key) { strirtrim(strptr(str), key); }
void strirtrim(string &str, const char *key) { strirtrim(strptr(str), key); }
//does not work on type char* because function increases string length
void strquote(substring &str) {
static substring t;
void strquote(string &str) {
static string t;
strcpy(t, "\"");
strcat(t, str);
strcat(t, "\"");
@ -333,7 +300,7 @@ int i, ssl = strlen(str);
return true;
}
bool strunquote(substring &str) { return strunquote(strptr(str)); }
bool strunquote(string &str) { return strunquote(strptr(str)); }
uint strhex(const char *str) {
uint r = 0, m = 0;
@ -355,7 +322,7 @@ uint8 x;
}
return r;
}
uint strhex(substring &str) { return strhex(strptr(str)); }
uint strhex(string &str) { return strhex(strptr(str)); }
int sstrhex(const char *str) {
if(str[0] == '-') {
@ -363,7 +330,7 @@ int sstrhex(const char *str) {
}
return strhex(str);
}
int sstrhex(substring &str) { return sstrhex(strptr(str)); }
int sstrhex(string &str) { return sstrhex(strptr(str)); }
uint strdec(const char *str) {
uint m = 1;
@ -381,7 +348,7 @@ uint8 x;
}
return r;
}
uint strdec(substring &str) { return strdec(strptr(str)); }
uint strdec(string &str) { return strdec(strptr(str)); }
int sstrdec(const char *str) {
if(str[0] == '-') {
@ -389,7 +356,7 @@ int sstrdec(const char *str) {
}
return strdec(str);
}
int sstrdec(substring &str) { return sstrdec(strptr(str)); }
int sstrdec(string &str) { return sstrdec(strptr(str)); }
uint strbin(const char *str) {
uint r = 0, m = 0;
@ -407,7 +374,7 @@ uint8 x;
}
return r;
}
uint strbin(substring &str) { return strbin(strptr(str)); }
uint strbin(string &str) { return strbin(strptr(str)); }
int sstrbin(const char *str) {
if(str[0] == '-') {
@ -415,7 +382,7 @@ int sstrbin(const char *str) {
}
return strbin(str);
}
int sstrbin(substring &str) { return sstrbin(strptr(str)); }
int sstrbin(string &str) { return sstrbin(strptr(str)); }
char *utoa(char *str, uint num) {
char *pstr = str;
@ -433,7 +400,7 @@ uint mask = 1000000000;
return pstr;
}
substring &utoa(substring &str, uint num) {
string &utoa(string &str, uint num) {
if(str.size < 16) { strresize(str, 16); }
utoa(strptr(str), num);
return str;
@ -450,7 +417,7 @@ char *pstr = str;
return pstr;
}
substring &itoa(substring &str, uint num) {
string &itoa(string &str, uint num) {
if(str.size < 16) { strresize(str, 16); }
itoa(strptr(str), num);
return str;
@ -473,7 +440,7 @@ uint mask = 28, r;
return pstr;
}
substring &htoa(substring &str, uint num) {
string &htoa(string &str, uint num) {
if(str.size < 16) { strresize(str, 16); }
htoa(strptr(str), num);
return str;
@ -496,7 +463,7 @@ uint mask = 28, r;
return pstr;
}
substring &uhtoa(substring &str, uint num) {
string &uhtoa(string &str, uint num) {
if(str.size < 16) { strresize(str, 16); }
uhtoa(strptr(str), num);
return str;
@ -517,13 +484,13 @@ uint mask = 0x80000000;
return pstr;
}
substring &btoa(substring &str, uint num) {
string &btoa(string &str, uint num) {
if(str.size < 48) { strresize(str, 48); }
btoa(strptr(str), num);
return str;
}
bool strfread(substring &str, const char *filename) {
bool strfread(string &str, const char *filename) {
strcpy(str, "");
FILE *fp = fopen(filename, "rb");

View File

@ -1,5 +1,5 @@
/*
libstring : version 0.11b ~byuu (07/16/06)
libstring : version 0.12 ~byuu (10/05/06)
*/
#ifndef __LIBSTRING
@ -8,188 +8,177 @@
#include "libvector.h"
class string;
class substring;
typedef linear_vector<string> stringarray;
char chrlower(char c);
char chrupper(char c);
uint count(string &str);
uint count(stringarray &str);
void strresize(substring &str, uint size);
void strresize(string &str, uint size);
char* strptr(substring &str);
char* strptr(string &str);
uint strlen(substring &str);
uint strlen(string &str);
int strcmp(substring &dest, const char *src);
int strcmp(const char *dest, substring &src);
int strcmp(substring &dest, substring &src);
int strcmp(string &dest, const char *src);
int strcmp(const char *dest, string &src);
int strcmp(string &dest, string &src);
//vc6/win32 and gcc/dos only support stricmp, whereas
//gcc/unix only supports strcasecmp. this is an attempt
//to avoid platform-specific defines...
#define stricmp __stricmp
int __stricmp(const char *dest, const char *src);
int stricmp(substring &dest, const char *src);
int stricmp(const char *dest, substring &src);
int stricmp(substring &dest, substring &src);
int stricmp(string &dest, const char *src);
int stricmp(const char *dest, string &src);
int stricmp(string &dest, string &src);
bool strmatch(const char *dest, const char *src);
bool strmatch(substring &dest, const char *src);
bool strmatch(const char *dest, substring &src);
bool strmatch(substring &dest, substring &src);
bool strmatch(string &dest, const char *src);
bool strmatch(const char *dest, string &src);
bool strmatch(string &dest, string &src);
bool strimatch(const char *dest, const char *src);
bool strimatch(substring &dest, const char *src);
bool strimatch(const char *dest, substring &src);
bool strimatch(substring &dest, substring &src);
bool strimatch(string &dest, const char *src);
bool strimatch(const char *dest, string &src);
bool strimatch(string &dest, string &src);
void strcpy(substring &dest, const char *src);
void strcpy(substring &dest, substring &src);
void strncpy(substring &dest, const char *src, uint32 length);
void strncpy(substring &dest, substring &src, uint32 length);
void strcpy(string &dest, const char *src);
void strcpy(string &dest, string &src);
void strncpy(string &dest, const char *src, uint32 length);
void strncpy(string &dest, string &src, uint32 length);
void strset(substring &dest, uint pos, uint8 c);
void strset(string &dest, uint pos, uint8 c);
void strcat(substring &dest, const char src);
void strcat(substring &dest, const char *src);
void strcat(substring &dest, substring &src);
void strcat(string &dest, const char src);
void strcat(string &dest, const char *src);
void strcat(string &dest, string &src);
void strinsert(substring &dest, const char *src, uint pos);
void strinsert(substring &dest, substring &src, uint pos);
void strinsert(string &dest, const char *src, uint pos);
void strinsert(string &dest, string &src, uint pos);
void strremove(substring &dest, uint start, uint length = 0);
void strremove(string &dest, uint start, uint length = 0);
char *strlower(char *str);
substring &strlower(substring &str);
string &strlower(string &str);
char *strupper(char *str);
substring &strupper(substring &str);
string &strupper(string &str);
bool strpos(const char *str, const char *key, uint &pos);
bool strpos(substring &str, const char *key, uint &pos);
bool strpos(const char *str, substring &key, uint &pos);
bool strpos(substring &str, substring &key, uint &pos);
bool strpos(string &str, const char *key, uint &pos);
bool strpos(const char *str, string &key, uint &pos);
bool strpos(string &str, string &key, uint &pos);
bool qstrpos(const char *str, const char *key, uint &pos);
bool qstrpos(substring &str, const char *key, uint &pos);
bool qstrpos(const char *str, substring &key, uint &pos);
bool qstrpos(substring &str, substring &key, uint &pos);
bool qstrpos(string &str, const char *key, uint &pos);
bool qstrpos(const char *str, string &key, uint &pos);
bool qstrpos(string &str, string &key, uint &pos);
void strtr(char *dest, const char *before, const char *after);
void strtr(substring &dest, const char *before, const char *after);
void strtr(string &dest, const char *before, const char *after);
bool strbegin(const char *str, const char *key);
bool strbegin(substring &str, const char *key);
bool strbegin(string &str, const char *key);
bool stribegin(const char *str, const char *key);
bool stribegin(substring &str, const char *key);
bool stribegin(string &str, const char *key);
bool strend(const char *str, const char *key);
bool strend(substring &str, const char *key);
bool strend(string &str, const char *key);
bool striend(const char *str, const char *key);
bool striend(substring &str, const char *key);
bool striend(string &str, const char *key);
void strltrim(char *str, const char *key);
void strltrim(substring &str, const char *key);
void strltrim(string &str, const char *key);
void striltrim(char *str, const char *key);
void striltrim(substring &str, const char *key);
void striltrim(string &str, const char *key);
void strrtrim(char *str, const char *key);
void strrtrim(substring &str, const char *key);
void strrtrim(string &str, const char *key);
void strirtrim(char *str, const char *key);
void strirtrim(substring &str, const char *key);
void strirtrim(string &str, const char *key);
void strquote(substring &str);
void strquote(string &str);
bool strunquote(char *str);
bool strunquote(substring &str);
bool strunquote(string &str);
uint strhex(const char *str);
uint strhex(substring &str);
uint strhex(string &str);
int sstrhex(const char *str);
int sstrhex(substring &str);
int sstrhex(string &str);
uint strdec(const char *str);
uint strdec(substring &str);
uint strdec(string &str);
int sstrdec(const char *str);
int sstrdec(substring &str);
int sstrdec(string &str);
uint strbin(const char *str);
uint strbin(substring &str);
uint strbin(string &str);
int sstrbin(const char *str);
int sstrbin(substring &str);
int sstrbin(string &str);
char *utoa(char *str, uint num);
substring &utoa(substring &str, uint num);
string &utoa(string &str, uint num);
char *itoa(char *str, uint num);
substring &itoa(substring &str, uint num);
string &itoa(string &str, uint num);
char *htoa(char *str, uint num);
substring &htoa(substring &str, uint num);
string &htoa(string &str, uint num);
char *uhtoa(char *str, uint num);
substring &uhtoa(substring &str, uint num);
string &uhtoa(string &str, uint num);
char *btoa(char *str, uint num);
substring &btoa(substring &str, uint num);
string &btoa(string &str, uint num);
bool strfread(substring &str, const char *filename);
bool strfread(string &str, const char *filename);
int strmath(const char *in_str);
int strmath(substring &in_str);
int strmath(string &in_str);
substring &replace(substring &str, const char *key, const char *token);
substring &replace(substring &str, const char *key, substring &token);
string &replace(string &str, const char *key, const char *token);
string &replace(string &str, const char *key, string &token);
substring &qreplace(substring &str, const char *key, const char *token);
substring &qreplace(substring &str, const char *key, substring &token);
string &qreplace(string &str, const char *key, const char *token);
string &qreplace(string &str, const char *key, string &token);
void split(string &dest, const char *key, const char *src);
void split(string &dest, const char *key, substring &src);
void split(stringarray &dest, const char *key, const char *src);
void split(stringarray &dest, const char *key, string &src);
void qsplit(string &dest, const char *key, const char *src);
void qsplit(string &dest, const char *key, substring &src);
void qsplit(stringarray &dest, const char *key, const char *src);
void qsplit(stringarray &dest, const char *key, string &src);
uint vsprintf(substring &str, const char *s, va_list args);
uint sprintf(substring &str, const char *s, ...);
uint vsprintf(string &str, const char *s, va_list args);
uint sprintf(string &str, const char *s, ...);
class substring {
class string {
public:
char *s;
uint size;
substring();
~substring();
};
string() {
size = 16;
s = (char*)malloc(size + 1);
*s = 0;
}
/* listcount is the actual size of list[], used for allocation
* of substrings.
* count is used by split() and count() to return the number of
* active/valid substrings. example: if string T contains 16
* substrings, and split is called, which sets three substrings,
* then count() needs to reflect that only three substrings are
* now used, but listcount still needs to reflect the true size
* of list[].
*/
class string {
public:
vector<substring*> list;
uint listcount, count;
void addto(uint num); //creates all needed strings to make list[num] valid
substring &str(uint num); //gets a substring reference, creating it + new strings if needed
~string() { SafeFree(s); }
inline operator substring&() { return str(0); }
template<typename T> inline substring& operator[](const T i) { return str(i); }
string();
~string();
void operator=(const string &p) {
SafeFree(s);
size = p.size;
s = (char*)malloc(size + 1);
strcpy(s, p.s);
}
};
#endif //__LIBSTRING

View File

@ -115,7 +115,7 @@ int strmath(const char *s) {
}
#ifdef __LIBSTRING
int strmath(substring &s) {
int strmath(string &s) {
return strmath(strptr(s));
}
#endif

View File

@ -1,4 +1,4 @@
substring &replace(substring &str, const char *key, const char *token) {
string &replace(string &str, const char *key, const char *token) {
int i, z, ksl = strlen(key), tsl = strlen(token), ssl = strlen(str);
uint replace_count = 0, size = ssl;
char *data;
@ -28,9 +28,9 @@ char *data;
free(data);
return str;
}
substring &replace(substring &str, const char *key, substring &token) { return replace(str, key, strptr(token)); }
string &replace(string &str, const char *key, string &token) { return replace(str, key, strptr(token)); }
substring &qreplace(substring &str, const char *key, const char *token) {
string &qreplace(string &str, const char *key, const char *token) {
int i, l, z, ksl = strlen(key), tsl = strlen(token), ssl = strlen(str);
uint replace_count = 0, size = ssl;
uint8 x;
@ -83,4 +83,4 @@ char *data;
free(data);
return str;
}
substring &qreplace(substring &str, const char *key, substring &token) { return qreplace(str, key, strptr(token)); }
string &qreplace(string &str, const char *key, string &token) { return qreplace(str, key, strptr(token)); }

View File

@ -1,7 +1,9 @@
void split(string &dest, const char *key, const char *src) {
int ssl = strlen(src), ksl = strlen(key);
uint lp = 0, split_count = 0;
for(int32 i = 0; i <= ssl - ksl;) {
void split(stringarray &dest, const char *key, const char *src) {
dest.reset();
int ssl = strlen(src), ksl = strlen(key);
int lp = 0, split_count = 0;
for(int i = 0; i <= ssl - ksl;) {
if(!memcmp(src + i, key, ksl)) {
strncpy(dest[split_count++], src + lp, i - lp);
i += ksl;
@ -9,14 +11,15 @@ uint lp = 0, split_count = 0;
} else i++;
}
strcpy(dest[split_count++], src + lp);
dest.count = split_count;
}
void split(string &dest, const char *key, substring &src) { split(dest, key, strptr(src)); }
void split(stringarray &dest, const char *key, string &src) { split(dest, key, strptr(src)); }
void qsplit(string &dest, const char *key, const char *src) {
int z, ssl = strlen(src), ksl = strlen(key);
uint lp = 0, split_count = 0;
for(int32 i = 0; i <= ssl - ksl;) {
void qsplit(stringarray &dest, const char *key, const char *src) {
dest.reset();
int z, ssl = strlen(src), ksl = strlen(key);
int lp = 0, split_count = 0;
for(int i = 0; i <= ssl - ksl;) {
uint8 x = src[i];
if(x == '\"' || x == '\'') {
z = i++;
@ -30,6 +33,5 @@ uint lp = 0, split_count = 0;
} else i++;
}
strcpy(dest[split_count++], src + lp);
dest.count = split_count;
}
void qsplit(string &dest, const char *key, substring &src) { qsplit(dest, key, strptr(src)); }
void qsplit(stringarray &dest, const char *key, string &src) { qsplit(dest, key, strptr(src)); }

View File

@ -1,4 +1,4 @@
uint sprintf(substring &str, const char *s, ...) {
uint sprintf(string &str, const char *s, ...) {
va_list args;
va_start(args, s);
uint length = vsprintf(str, s, args);
@ -6,7 +6,14 @@ uint length = vsprintf(str, s, args);
return length;
}
uint vsprintf(substring &str, const char *s, va_list args) {
uint vsprintf(string &str, const char *s, va_list args) {
uint length = vsnprintf(0, 0, s, args);
strresize(str, length + 1);
return vsprintf(strptr(str), s, args);
}
/*
uint vsprintf(string &str, const char *s, va_list args) {
bool leftalign;
bool showbase;
char positivesign;
@ -200,3 +207,4 @@ uint i = 0;
}
return strlen(str);
}
*/

430
src/lib/libups.h Normal file
View File

@ -0,0 +1,430 @@
/*
libups : version 0.01 ~byuu, Nach (09/30/06)
*/
#ifndef __LIBUPS
#define __LIBUPS
template<typename FT>
class UPSPatch {
public:
enum {
FLAG_INFO = 0x00000001,
};
uint32 sig;
uint16 version;
uint32 format;
uint32 flags;
uint64 original_filesize;
uint64 modified_filesize;
uint8 info_author[64 + 8];
uint8 info_version[16 + 8];
uint8 info_title[128 + 8];
uint8 info_genre[32 + 8];
uint8 info_language[32 + 8];
uint8 info_date[8 + 8];
uint8 info_website[256 + 8];
uint8 info_description[1024 + 8];
FT fp;
uint32 xmlsize;
uint32 original_crc32;
uint32 modified_crc32;
uint32 patch_crc32;
bool load();
void save_header();
void save_footer();
void close();
UPSPatch();
};
template<typename FTO, typename FTM, typename FTP>
class UPS {
public:
FTO original;
FTM modified;
UPSPatch<FTP> patch;
uint64 original_filesize;
uint64 modified_filesize;
uint64 largest_filesize;
uint32 original_crc32;
uint32 modified_crc32;
uint32 patch_crc32;
bool patch_eof;
uint ptr_read();
void ptr_write(uint ptr);
void create(const char *original_filename,
const char *modified_filename,
const char *patch_filename);
void create_linear();
bool apply(const char *original_filename,
const char *modified_filename,
const char *patch_filename);
bool apply();
void apply_linear();
};
/*****
* UPSPatch
*****/
template<typename FT>
bool UPSPatch<FT>::load() {
fseek(fp, 0, file::seek_start);
patch_crc32 = 0xffffffff;
while(ftell(fp) < fsize(fp) - 4) {
patch_crc32 = crc32_adjust(patch_crc32, fgetc(fp));
}
patch_crc32 = ~patch_crc32;
fseek(fp, -16, file::seek_end);
xmlsize = fgetld(fp);
original_crc32 = fgetld(fp);
modified_crc32 = fgetld(fp);
if(patch_crc32 != fgetld(fp)) {
fprintf(stdout, "error: patch checksum failure\n");
return false;
}
fseek(fp, 0, file::seek_start);
sig = fgetld(fp);
version = fgetlw(fp);
format = fgetld(fp);
flags = fgetld(fp);
original_filesize = fgetlq(fp);
modified_filesize = fgetlq(fp);
memset(info_author, 0, 64 + 8);
memset(info_version, 0, 16 + 8);
memset(info_title, 0, 128 + 8);
memset(info_genre, 0, 32 + 8);
memset(info_language, 0, 32 + 8);
memset(info_date, 0, 8 + 8);
memset(info_website, 0, 256 + 8);
memset(info_description, 0, 1024 + 8);
if(flags & FLAG_INFO) {
fread(fp, info_author, 64);
fread(fp, info_version, 16);
fread(fp, info_title, 128);
fread(fp, info_genre, 32);
fread(fp, info_language, 32);
fread(fp, info_date, 8);
fread(fp, info_website, 256);
fread(fp, info_description, 1024);
}
return true;
}
template<typename FT>
void UPSPatch<FT>::save_header() {
fputld(fp, sig);
fputlw(fp, version);
fputld(fp, format);
fputld(fp, flags);
fputlq(fp, original_filesize);
fputlq(fp, modified_filesize);
if(flags & FLAG_INFO) {
fwrite(fp, info_author, 64);
fwrite(fp, info_version, 16);
fwrite(fp, info_title, 128);
fwrite(fp, info_genre, 32);
fwrite(fp, info_language, 32);
fwrite(fp, info_date, 8);
fwrite(fp, info_website, 256);
fwrite(fp, info_description, 1024);
}
}
template<typename FT>
void UPSPatch<FT>::save_footer() {
fputld(fp, xmlsize);
fputld(fp, original_crc32);
fputld(fp, modified_crc32);
patch_crc32 = fcrc32(fp);
fputld(fp, patch_crc32);
}
template<typename FT>
void UPSPatch<FT>::close() {
fclose(fp);
}
template<typename FT>
UPSPatch<FT>::UPSPatch() {
sig = 0x00737075; //'ups\0'
version = 0x0001; //1.0
format = 0x00000000; //linear
flags = 0;
original_filesize = 0;
modified_filesize = 0;
memset(info_author, 0, 64 + 8);
memset(info_version, 0, 16 + 8);
memset(info_title, 0, 128 + 8);
memset(info_genre, 0, 32 + 8);
memset(info_language, 0, 32 + 8);
memset(info_date, 0, 8 + 8);
memset(info_website, 0, 256 + 8);
memset(info_description, 0, 1024 + 8);
xmlsize = 0;
original_crc32 = 0;
modified_crc32 = 0;
patch_crc32 = 0;
}
/*****
* UPS
*****/
template<typename FTO, typename FTM, typename FTP>
uint UPS<FTO, FTM, FTP>::ptr_read() {
uint len = fgetc(patch.fp);
if(len == 0xff) {
patch_eof = true;
return 0;
}
if(len <= 0xf7) {
return len;
}
len -= 0xf8;
uint ptr = 0;
for(int i = 0; i < (len + 2); i++) {
ptr |= fgetc(patch.fp) << (i << 3);
}
ptr += 0xf8;
if(len >= 1) { ptr += 0x10000; }
if(len >= 2) { ptr += 0x1000000; }
return ptr;
}
template<typename FTO, typename FTM, typename FTP>
void UPS<FTO, FTM, FTP>::ptr_write(uint ptr) {
if(ptr <= 0xf7) {
fputc(patch.fp, ptr);
return;
}
ptr -= 0xf8;
if(ptr <= 0xffff) {
fputc(patch.fp, 0xf8);
fputc(patch.fp, ptr);
fputc(patch.fp, ptr >> 8);
return;
}
ptr -= 0x10000;
if(ptr <= 0xffffff) {
fputc(patch.fp, 0xf9);
fputc(patch.fp, ptr);
fputc(patch.fp, ptr >> 8);
fputc(patch.fp, ptr >> 16);
return;
}
ptr -= 0x1000000;
fputc(patch.fp, 0xfa);
fputc(patch.fp, ptr);
fputc(patch.fp, ptr >> 8);
fputc(patch.fp, ptr >> 16);
fputc(patch.fp, ptr >> 24);
}
template<typename FTO, typename FTM, typename FTP>
void UPS<FTO, FTM, FTP>::create(
const char *original_filename,
const char *modified_filename,
const char *patch_filename
) {
fopen(original, original_filename, file::mode_read);
fopen(modified, modified_filename, file::mode_read);
fopen(patch.fp, patch_filename, file::mode_writeread);
patch.original_filesize = original_filesize = fsize(original);
patch.modified_filesize = modified_filesize = fsize(modified);
largest_filesize = (original_filesize >= modified_filesize) ?
original_filesize : modified_filesize;
patch.save_header();
switch(patch.format) {
case 0x00000000: create_linear(); break;
}
patch.original_crc32 = original_crc32 = fcrc32(original);
patch.modified_crc32 = modified_crc32 = fcrc32(modified);
patch.save_footer();
patch.close();
}
template<typename FTO, typename FTM, typename FTP>
void UPS<FTO, FTM, FTP>::create_linear() {
fseek(original, 0, file::seek_start);
fseek(modified, 0, file::seek_start);
uint last_ptr = 0, rle_count, last_out, rep_count;
for(int i = 0; i < largest_filesize;) {
uint8 r = fgetc(original) ^ fgetc(modified);
i++;
if(r == 0x00)continue;
//ptr
ptr_write((i - 1) - last_ptr);
//data
fputc(patch.fp, r);
last_out = r;
rep_count = 0;
do {
r = fgetc(original) ^ fgetc(modified);
i++;
fputc(patch.fp, r);
if(last_out != r) {
rep_count = 0;
} else {
if(++rep_count == (3 - 1)) {
rle_count = 0;
do {
r = fgetc(original) ^ fgetc(modified);
if(r != last_out || r == 0x00) { break; }
rle_count++;
} while(i < largest_filesize);
ptr_write(rle_count);
if(i < largest_filesize) { fputc(patch.fp, r); }
rep_count = 0;
}
}
last_out = r;
if(r == 0x00) { break; }
} while(i < largest_filesize);
last_ptr = i;
}
fputc(patch.fp, 0xff);
}
template<typename FTO, typename FTM, typename FTP>
bool UPS<FTO, FTM, FTP>::apply(
const char *original_filename,
const char *modified_filename,
const char *patch_filename
) {
fopen(original, original_filename, file::mode_read);
fopen(modified, modified_filename, file::mode_writeread);
fopen(patch.fp, patch_filename, file::mode_read);
return apply();
}
template<typename FTO, typename FTM, typename FTP>
bool UPS<FTO, FTM, FTP>::apply() {
patch.load();
patch_eof = false;
original_filesize = fsize(original);
original_crc32 = fcrc32(original);
if(original_filesize == patch.original_filesize &&
original_crc32 == patch.original_crc32) {
modified_filesize = patch.modified_filesize;
modified_crc32 = patch.modified_crc32;
} else if(original_filesize == patch.modified_filesize &&
original_crc32 == patch.modified_crc32) {
modified_filesize = patch.original_filesize;
modified_crc32 = patch.original_crc32;
} else {
fprintf(stdout, "error: input checksum failure\n");
return false;
}
patch_crc32 = patch.patch_crc32;
apply_linear();
patch.close();
if(modified_crc32 != fcrc32(modified)) {
fprintf(stdout, "error: output checksum failure\n");
}
return true;
}
template<typename FTO, typename FTM, typename FTP>
void UPS<FTO, FTM, FTP>::apply_linear() {
fseek(original, 0, file::seek_start);
fseek(modified, 0, file::seek_start);
for(uint i = 0; i < modified_filesize; i++) {
fputc(modified, fgetc(original));
}
fseek(original, 0, file::seek_start);
fseek(modified, 0, file::seek_start);
uint rle_count, last_in, rep_count;
while(!feof(patch.fp) && patch_eof == false && ftell(modified) < modified_filesize) {
//ptr
uint ptr = ptr_read();
if(patch_eof == true) { break; }
//data
fseek(original, ftell(original) + ptr, file::seek_start);
fseek(modified, ftell(modified) + ptr, file::seek_start);
last_in = 0;
rep_count = 0;
do {
if(ftell(modified) >= modified_filesize) { break; }
uint8 r = fgetc(patch.fp);
fputc(modified, r ^ fgetc(original));
if(r != last_in) {
rep_count = 0;
} else {
if(++rep_count == (3 - 1)) {
rle_count = ptr_read();
while(rle_count-- && ftell(modified) < modified_filesize) {
fputc(modified, r ^ fgetc(original));
}
rep_count = 0;
}
}
last_in = r;
if(r == 0x00) { break; }
} while(!feof(patch.fp) && patch_eof == false && ftell(modified) < modified_filesize);
}
}
#endif

View File

@ -1,103 +1,208 @@
/*
libvector : version 0.04a ~byuu (06/15/05)
libvector : version 0.04 ~byuu (10/14/06)
*/
/*****
* Dynamic vector allocation template class library
*
* Implements auto-allocating, auto-resizing vectors that allow for
* theoretically infinitely-sized arrays of objects.
* Array indexes are not bounds checked, and reallocate to requested size when
* accessing out of bounds.
* These class are intended only for use with objects that require
* construction. Significant overhead will result if used for raw memory
* management. See libarray for a far more suitable raw memory vector array
* class.
*
* Vectors also reserve an internal pool of memory that can be larger to
* minimize memory allocation requests, but by default the pools only grow to
* the requested vector index, as some objects may have substantial memory
* requirements per object. The reserve() function may be used to allocate
* memory in advance when possible.
*
* Two types of vectors are implemented. Their public interfaces are identical,
* however they operate very differently internally.
*
* [linear_vector]
* Works by allocating one giant heap of memory to contain all objects.
* Constructors and destructors are called during resize() as needed.
*
* Pros:
* - memory is allocated and objects are prebuilt in advance, so accessing
* array objects will be very fast.
* - all objects are in contigious memory, which helps for processor caching.
* Cons:
* - accessing object 15 will require objects 0-14 to be constructed first.
* - resizing array may invalidate pointers to member objects inside classes
* (eg object "this" pointer may change).
*
* Use when:
* You need an array of objects that do not rely on pointers to member
* variables, you have an idea of how many objects you will need, and
* speed is critical.
*
* [ptr_vector]
* Works by allocating a smaller heap of memory used as an array of pointers to
* individual objects.
*
* Pros:
* - accessing object 15 does not require objects 0-14 to be constructed first.
* - resizing array will not invalidate pointers to member objects inside
* classes.
* Cons:
* - memory for individual objects cannot be allocated in advance. Each "first"
* access to an array object will require memory allocation and object
* construction.
* - objects are not guaranteed to be aligned in contigious memory, and
* individual array indexes require two indirect memory lookups. Will affect
* speed adversely when indexing very large arrays of objects.
*
* Use when:
* Objects rely on pointers to member variables, you do not know how many
* objects you will need in advance, you need to access vector elements out of
* order and prefer not to have all previous objects constructed in advance,
* and speed is less critical.
*****/
#ifndef __LIBVECTOR
#define __LIBVECTOR
template<typename T> class vector {
private:
T *array;
int size, sizelimit;
#include <new>
//find next array size that is a power of two
int findsize(int newsize) {
int r = 1;
while(r >= 1) {
r <<= 1;
if(r > sizelimit)return sizelimit;
if(r >= newsize)return r;
}
return size;
}
template<typename T> class linear_vector {
protected:
T *pool;
uint poolsize, objectsize;
public:
void resize(int newsize) {
newsize = findsize(newsize);
uint size() { return objectsize; }
uint capacity() { return poolsize; }
if(newsize > sizelimit)newsize = sizelimit;
if(newsize == size)return;
void reset() {
for(uint i = 0; i < objectsize; i++) { pool[i].~T(); }
array = (T*)realloc(array, sizeof(T) * newsize);
if(newsize > size) {
for(int i = size; i < newsize; i += sizeof(T)) {
array[i] = (T)0;
}
if(pool) {
free(pool);
pool = 0;
}
size = newsize;
poolsize = 0;
objectsize = 0;
}
//used to free up memory used by vector, but without
//actually destroying the vector itself
void release() { resize(16); }
void reserve(uint size) {
if(size == poolsize)return;
T *handle(uint req_size = 0) {
if(req_size > size)resize(req_size);
return (T*)array;
}
void read(uint start, T *source, uint length) {
if(start + length > size)resize(start + length);
memcpy(array + start, source, length);
}
void read(T *source, uint length) { read(0, source, length); }
void write(uint start, T *dest, uint length) {
if(start + length > size)resize(start + length);
memcpy(dest, array + start, length);
}
void write(T *dest, uint length) { write(0, dest, length); }
void clear() { memset(array, 0, size * sizeof(T)); }
vector(int newsize, int newsizelimit) {
size = newsize;
sizelimit = newsizelimit;
array = (T*)malloc(size * sizeof(T));
clear();
}
vector(int newsize) {
size = newsize;
sizelimit = 1 << 24;
array = (T*)malloc(size * sizeof(T));
clear();
}
vector() {
size = 16;
sizelimit = 1 << 24;
array = (T*)malloc(size * sizeof(T));
clear();
}
~vector() {
if(array) {
free(array);
array = 0;
if(size < poolsize) {
for(uint i = size; i < objectsize; i++) { pool[i].~T(); }
objectsize = size;
}
pool = static_cast<T*>(realloc(pool, sizeof(T) * size));
poolsize = size;
}
//operator T() { return array[0]; }
void resize(int size) {
if(size == objectsize)return;
if(size > poolsize)reserve(size);
if(size < objectsize) {
for(uint i = size; i < objectsize; i++) { pool[i].~T(); }
} else {
for(uint i = objectsize; i < size; i++) { new(pool + i) T; }
}
objectsize = size;
}
linear_vector() {
pool = 0;
poolsize = 0;
objectsize = 0;
}
~linear_vector() { reset(); }
inline operator T&() {
if(objectsize == 0)resize(1);
if(objectsize == 0)throw "vector[] out of bounds";
return pool[0];
}
inline T &operator[](int index) {
if(index >= size)resize(index + 1);
if(index > sizelimit)return array[size - 1];
return array[index];
if(index >= objectsize)resize(index + 1);
if(index >= objectsize)throw "vector[] out of bounds";
return pool[index];
}
};
template<typename T> class ptr_vector {
protected:
T **pool;
uint poolsize, objectsize;
public:
uint size() { return objectsize; }
uint capacity() { return poolsize; }
void reset() {
for(uint i = 0; i < objectsize; i++) { if(pool[i])delete pool[i]; }
if(pool) {
free(pool);
pool = 0;
}
poolsize = 0;
objectsize = 0;
}
void reserve(uint size) {
if(size == poolsize)return;
if(size < poolsize) {
for(uint i = size; i < objectsize; i++) { if(pool[i])delete pool[i]; }
objectsize = size;
}
pool = static_cast<T**>(realloc(pool, sizeof(T*) * size));
if(size > poolsize) {
memset(pool + poolsize, 0, sizeof(T*) * (size - poolsize));
}
poolsize = size;
}
void resize(int size) {
if(size == objectsize)return;
if(size > poolsize)reserve(size);
if(size < objectsize) {
for(uint i = size; i < objectsize; i++) { if(pool[i])delete pool[i]; }
}
objectsize = size;
}
ptr_vector() {
pool = 0;
poolsize = 0;
objectsize = 0;
}
~ptr_vector() { reset(); }
inline operator T&() {
if(objectsize == 0)resize(1);
if(objectsize == 0)throw "vector[] out of bounds";
if(!pool[0])pool[0] = new T;
return *pool[0];
}
inline T &operator[](int index) {
if(index >= objectsize)resize(index + 1);
if(index >= objectsize)throw "vector[] out of bounds";
if(!pool[index])pool[index] = new T;
return *pool[index];
}
};

View File

@ -42,7 +42,7 @@ void HideCursor() {
}
}
void ParseStyleParam(const char *style, string &output) {
void ParseStyleParam(const char *style, stringarray &output) {
string temp;
strcpy(temp, style);
strlower(temp);
@ -95,7 +95,7 @@ libwin32_init::libwin32_init() {
WNDCLASS wc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hbrBackground = (HBRUSH)COLOR_WINDOW;
wc.hbrBackground = (HBRUSH)(COLOR_3DFACE + 1);
wc.hCursor = LoadCursor(0, IDC_ARROW);
wc.hIcon = LoadIcon(0, IDI_APPLICATION);
wc.hInstance = GetModuleHandle(0);

View File

@ -32,7 +32,7 @@ uint GetScreenWidth();
uint GetScreenHeight();
void ShowCursor();
void HideCursor();
void ParseStyleParam(const char *style, string &output);
void ParseStyleParam(const char *style, stringarray &output);
class Window;
class Control;

View File

@ -11,7 +11,7 @@ bool Button::Create(Window *parent_window, const char *style, int x, int y, int
state.width = width;
state.height = height;
string part;
stringarray part;
ParseStyleParam(style, part);
for(int i = 0; i < count(part); i++) {
if(strmatch(part[i], "visible"))state.ws |= WS_VISIBLE;

View File

@ -17,7 +17,7 @@ bool Checkbox::Create(Window *parent_window, const char *style, int x, int y, in
state.width = width;
state.height = height;
string part;
stringarray part;
ParseStyleParam(style, part);
for(int i = 0; i < count(part); i++) {
if(strmatch(part[i], "visible"))state.ws |= WS_VISIBLE;

View File

@ -35,7 +35,7 @@ bool Combobox::Create(Window *parent_window, const char *style, int x, int y, in
state.width = width;
state.height = height;
string part;
stringarray part;
ParseStyleParam(style, part);
for(int i = 0; i < count(part); i++) {
if(strmatch(part[i], "visible"))state.ws |= WS_VISIBLE;
@ -53,7 +53,7 @@ string part;
if(!hwnd)return false;
if(strmatch(text, "") == false) {
string t;
stringarray t;
split(t, "|", text);
for(int i = 0; i < ::count(t); i++) {
AddItem(strptr(t[i]));

View File

@ -16,7 +16,7 @@ bool Editbox::Create(Window *parent_window, const char *style, int x, int y, int
state.width = width;
state.height = height;
string part;
stringarray part;
ParseStyleParam(style, part);
for(int i = 0; i < count(part); i++) {
if(strmatch(part[i], "visible"))state.ws |= WS_VISIBLE;

View File

@ -8,11 +8,11 @@
* false - File was not selected
*/
bool FileOpen(Window *owner, const char *filter, const char *default_dir, char *output) {
string dir;
string dir, f;
strcpy(dir, default_dir ? default_dir : "");
replace(dir, "/", "\\");
string f, type, part;
stringarray type, part;
strcpy(f, "");
split(type, "|", filter);
for(int i = 0; i < count(type); i++) {

View File

@ -11,7 +11,7 @@ bool Groupbox::Create(Window *parent_window, const char *style, int x, int y, in
state.width = width;
state.height = height;
string part;
stringarray part;
ParseStyleParam(style, part);
for(int i = 0; i < count(part); i++) {
if(strmatch(part[i], "visible"))state.ws |= WS_VISIBLE;

View File

@ -11,7 +11,7 @@ bool Label::Create(Window *parent_window, const char *style, int x, int y, int w
state.width = width;
state.height = height;
string part;
stringarray part;
ParseStyleParam(style, part);
for(int i = 0; i < count(part); i++) {
if(strmatch(part[i], "visible"))state.ws |= WS_VISIBLE;

View File

@ -35,7 +35,7 @@ bool Listbox::Create(Window *parent_window, const char *style, int x, int y, int
state.width = width;
state.height = height;
string part;
stringarray part;
ParseStyleParam(style, part);
for(int i = 0; i < count(part); i++) {
if(strmatch(part[i], "visible"))state.ws |= WS_VISIBLE;
@ -53,7 +53,7 @@ string part;
if(!hwnd)return false;
if(strmatch(text, "") == false) {
string t;
stringarray t;
split(t, "|", text);
for(int i = 0; i < ::count(t); i++) {
AddItem(strptr(t[i]));

View File

@ -9,7 +9,7 @@ LVCOLUMN column;
}
void Listview::AddItem(const char *text) {
string t;
stringarray t;
split(t, "|", text);
LVITEM item;
@ -26,7 +26,7 @@ uint pos = ListView_GetItemCount(hwnd);
}
void Listview::SetItemText(uint id, const char *text) {
string t;
stringarray t;
split(t, "|", text);
for(int i = 0; i < count(t); i++) {
@ -72,7 +72,7 @@ bool Listview::Create(Window *parent_window, const char *style, int x, int y, in
state.width = width;
state.height = height;
string part;
stringarray part;
ParseStyleParam(style, part);
for(int i = 0; i < count(part); i++) {
if(strmatch(part[i], "visible"))state.ws |= WS_VISIBLE;

View File

@ -17,7 +17,7 @@ bool Radiobox::Create(Window *parent_window, const char *style, int x, int y, in
state.width = width;
state.height = height;
string part;
stringarray part;
ParseStyleParam(style, part);
for(int i = 0; i < count(part); i++) {
if(strmatch(part[i], "visible"))state.ws |= WS_VISIBLE;

View File

@ -25,7 +25,7 @@ bool Slider::Create(Window *parent_window, const char *style, int x, int y, int
state.width = width;
state.height = height;
string part;
stringarray part;
ParseStyleParam(style, part);
for(int i = 0; i < count(part); i++) {
if(strmatch(part[i], "visible"))state.ws |= WS_VISIBLE;

View File

@ -72,7 +72,8 @@ bool result = false;
for(int i = 0; i < control_count; i++) {
if(LOWORD(wparam) == list[i]->id) {
if((list[i]->type == Control::COMBOBOX && HIWORD(wparam) == CBN_SELCHANGE) ||
if((list[i]->type == Control::EDITBOX && HIWORD(wparam) == EN_CHANGE) ||
(list[i]->type == Control::COMBOBOX && HIWORD(wparam) == CBN_SELCHANGE) ||
(list[i]->type == Control::LISTBOX && HIWORD(wparam) == LBN_SELCHANGE)) {
info.event_id = EVENT_CHANGED;
info.control = list[i];
@ -253,7 +254,7 @@ void Window::SetStyle(const char *style) {
if(parent)state.ws |= WS_CHILD;
string part;
stringarray part;
ParseStyleParam(style, part);
for(int i = 0; i < count(part); i++) {
if(strmatch(part[i], "visible")) state.ws |= WS_VISIBLE;
@ -437,7 +438,7 @@ bool Window::Event(EventInfo &info) {
Window::Window() {
hwnd = 0;
hwnd_resize = 0;
backbrush = (HBRUSH)COLOR_WINDOW;
backbrush = (HBRUSH)(COLOR_3DFACE + 1);
control_count = 0;
event_callback = 0;

View File

@ -4,11 +4,11 @@
FILE *fp, *fph, *fpt;
string data, line, part, subpart;
string output_table, output_header, output_op;
stringarray data, line, part, subpart;
stringarray output_table, output_header, output_op;
struct _op_list {
string name, arg;
stringarray name, arg;
} op_list[64];
int32 op_count, line_num;
@ -143,7 +143,7 @@ char *buf = (char*)malloc(fsize + 1);
line_num = 0;
while(line_num < count(line)) {
while(strmatch(line[line_num], "") && line_num < count(line))line_num++;
while(line_num < count(line) && strmatch(line[line_num], ""))line_num++;
if(line_num >= count(line))break;
gen_header();

View File

@ -1,14 +1,13 @@
#include "libbase.h"
#include "libstring.h"
#include "libstring.cpp"
FILE *fp;
string data, line, part, subpart;
string output_op;
string data;
stringarray line, part, subpart, output_op;
struct _op_list {
string name, arg;
struct OpList {
stringarray name, arg;
} op_list[64];
int32 op_count, line_num;
@ -38,7 +37,7 @@ char t[4096];
for(int l = 0; l < count(part); l++) {
strcpy(op_list[z].arg[l], part[l]);
}
if(strend(line[i], " {"))break;
if(strend(line[i], " {") == true)break;
i++;
}
@ -54,7 +53,7 @@ void gen_op() {
int i = line_num, n, c;
char t[4096];
while(1) {
if(strmatch(line[i], "}"))break;
if(!strcmp(line[i], "}"))break;
//remove cycle number
n = strdec(line[i]);
@ -64,7 +63,7 @@ char t[4096];
//strcat(output_op, t);
update_line(i);
if(!strmatch(line[i], "")) {
if(strcmp(line[i], "")) {
strcat(output_op, " ");
strcat(output_op, line[i]);
strcat(output_op, "\r\n");
@ -123,7 +122,7 @@ char *buf = (char*)malloc(fsize + 1);
line_num = 0;
while(line_num < count(line)) {
while(strmatch(line[line_num], "") && line_num < count(line))line_num++;
while(line_num < count(line) && !strcmp(line[line_num], ""))line_num++;
if(line_num >= count(line))break;
gen_begin();

View File

@ -10,31 +10,11 @@ void bMemBus::load_cart() {
switch(cartridge.info.mapper) {
case Cartridge::PCB:
if(!strcmp(cartridge.info.pcb, "SHVC-1A3B-01")) { cart_map_shvc_1a3b_13(); break; }
if(!strcmp(cartridge.info.pcb, "SHVC-1A3B-11")) { cart_map_shvc_1a3b_13(); break; }
if(!strcmp(cartridge.info.pcb, "SHVC-1A3B-12")) { cart_map_shvc_1a3b_13(); break; }
if(!strcmp(cartridge.info.pcb, "SHVC-1A3B-13")) { cart_map_shvc_1a3b_13(); break; }
if(!strcmp(cartridge.info.pcb, "SHVC-1A3B-20")) { cart_map_shvc_1a3b_20(); break; }
if(!strcmp(cartridge.info.pcb, "SHVC-1A3M-10")) { cart_map_shvc_1a3m_30(); break; }
if(!strcmp(cartridge.info.pcb, "SHVC-1A3M-20")) { cart_map_shvc_1a3m_30(); break; }
if(!strcmp(cartridge.info.pcb, "SHVC-1A3M-21")) { cart_map_shvc_1a3m_30(); break; }
if(!strcmp(cartridge.info.pcb, "SHVC-1A3M-30")) { cart_map_shvc_1a3m_30(); break; }
if(!strcmp(cartridge.info.pcb, "SHVC-1J3M-01")) { cart_map_shvc_1j3m_20(); break; }
if(!strcmp(cartridge.info.pcb, "SHVC-1J3M-10")) { cart_map_shvc_1j3m_20(); break; }
if(!strcmp(cartridge.info.pcb, "SHVC-1J3M-11")) { cart_map_shvc_1j3m_20(); break; }
if(!strcmp(cartridge.info.pcb, "SHVC-1J3M-20")) { cart_map_shvc_1j3m_20(); break; }
if(!strcmp(cartridge.info.pcb, "BSC-1A5M-01")) { cart_map_bsc_1a5m_01(); break; }
if(!strcmp(cartridge.info.pcb, "BSC-1A7M-01")) { cart_map_bsc_1a7m_01(); break; }
if(!strcmp(cartridge.info.pcb, "BSC-1A7M-10")) { cart_map_bsc_1a7m_10(); break; }
dprintf("* PCB mapper not found");
return;
if(cart_map_pcb(cartridge.info.pcb) == false) {
dprintf("* PCB mapper not found, cartridge load failed");
return;
}
break;
case Cartridge::LOROM:
case Cartridge::HIROM:
@ -43,7 +23,7 @@ void bMemBus::load_cart() {
cart_map_generic(cartridge.info.mapper);
break;
default:
dprintf("* generic mapper not found");
dprintf("* Generic mapper not found, cartridge load failed");
return;
}
@ -156,17 +136,11 @@ uint8 r;
#endif
r = (this->*page_read[addr >> 8])(addr);
#ifdef DEBUGGER
snes->notify(SNES::MEM_READ, addr, r);
#endif
return r;
}
void bMemBus::write(uint32 addr, uint8 data) {
(this->*page_write[addr >> 8])(addr, data);
#ifdef DEBUGGER
snes->notify(SNES::MEM_WRITE, addr, data);
#endif
}
void bMemBus::cart_map_reset() {

View File

@ -57,6 +57,7 @@ enum { TYPE_WRAM, TYPE_MMIO, TYPE_CART };
//load_cart() helper
void calc_size(char *t, uint size) {
size *= 8; //bytes -> bits
if(size < 1024) { sprintf(t, "%dbit", size); return; }
size /= 1024;
if(size < 1024) { sprintf(t, "%dkbit", size); return; }

View File

@ -50,11 +50,11 @@ uint ram_size = cartridge.info.ram_size;
//LoROM SRAM region
//$[70-7f|f0-ff]:[0000-7fff]
//Note: WRAM is remapped over $[7e-7f]:[0000-ffff]
if(bank >= 0x70 && bank <= 0x7f && (addr & 0x8000) == 0x0000) {
if(ram_size == 0)continue;
if(type == Cartridge::LOROM || !(bank & 0x80)) {
if((bank & 0x7f) >= 0x70 && (bank & 0x7f) <= 0x7f && (addr & 0x8000) == 0x0000) {
if(!(bank & 0x80) || type == Cartridge::LOROM) {
//HiROM maps $[f0-ff]:[0000-7fff] to ROM
if(ram_size == 0)continue;
addr = ((bank & 0x7f) - 0x70) * 0x8000 + (addr & 0x7fff);
addr %= ram_size;
page_handle[page] = cartridge.sram + addr;

View File

@ -11,6 +11,33 @@ uint mask = 1 << 31;
}
}
bool bMemBus::cart_map_pcb(const char *pcb) {
if(!strcmp(pcb, "SHVC-1A3B-01")) { cart_map_shvc_1a3b_13(); return true; }
if(!strcmp(pcb, "SHVC-1A3B-11")) { cart_map_shvc_1a3b_13(); return true; }
if(!strcmp(pcb, "SHVC-1A3B-12")) { cart_map_shvc_1a3b_13(); return true; }
if(!strcmp(pcb, "SHVC-1A3B-13")) { cart_map_shvc_1a3b_13(); return true; }
if(!strcmp(pcb, "SHVC-1A3B-20")) { cart_map_shvc_1a3b_20(); return true; }
if(!strcmp(pcb, "SHVC-1A3M-10")) { cart_map_shvc_1a3m_30(); return true; }
if(!strcmp(pcb, "SHVC-1A3M-20")) { cart_map_shvc_1a3m_30(); return true; }
if(!strcmp(pcb, "SHVC-1A3M-21")) { cart_map_shvc_1a3m_30(); return true; }
if(!strcmp(pcb, "SHVC-1A3M-30")) { cart_map_shvc_1a3m_30(); return true; }
if(!strcmp(pcb, "SHVC-1J3M-01")) { cart_map_shvc_1j3m_20(); return true; }
if(!strcmp(pcb, "SHVC-1J3M-10")) { cart_map_shvc_1j3m_20(); return true; }
if(!strcmp(pcb, "SHVC-1J3M-11")) { cart_map_shvc_1j3m_20(); return true; }
if(!strcmp(pcb, "SHVC-1J3M-20")) { cart_map_shvc_1j3m_20(); return true; }
if(!strcmp(pcb, "BSC-1A5M-01")) { cart_map_bsc_1a5m_01(); return true; }
if(!strcmp(pcb, "BSC-1A7M-01")) { cart_map_bsc_1a7m_01(); return true; }
if(!strcmp(pcb, "BSC-1A7M-10")) { cart_map_bsc_1a7m_10(); return true; }
return false;
}
void bMemBus::cart_map_range(
uint mode,
uint8 bank_lo, uint8 bank_hi,

View File

@ -15,6 +15,7 @@ enum {
};
uint mirror(uint size, uint pos);
bool cart_map_pcb(const char *pcb);
void cart_map_range(uint mode, uint8 bank_lo, uint8 bank_hi, uint16 addr_lo, uint16 addr_hi, uint type, uint offset = 0);
#define mapper(name) void cart_map_##name()

View File

@ -41,7 +41,6 @@ mapper(shvc_1j3m_20) {
map(LINEAR, 0xc0, 0xff, 0x0000, 0xffff, MAP_ROM);
}
//unverified
//BSC-1A5M-01
//
//$[c0-ef]:[0000-ffff] BSX
@ -51,9 +50,9 @@ mapper(bsc_1a5m_01) {
map(LINEAR, 0x70, 0x7f, 0x0000, 0x7fff, MAP_RAM);
map(LINEAR, 0x80, 0x9f, 0x8000, 0xffff, MAP_ROM, 0x200000);
map(LINEAR, 0xa0, 0xbf, 0x8000, 0xffff, MAP_ROM, 0x100000);
map(LINEAR, 0xf0, 0xff, 0x0000, 0x7fff, MAP_RAM);
}
//unverified
//BSC-1A7M-01
//
//$[c0-ef]:[0000-ffff] BSX
@ -63,9 +62,9 @@ mapper(bsc_1a7m_01) {
map(LINEAR, 0x70, 0x7f, 0x0000, 0x7fff, MAP_RAM);
map(LINEAR, 0x80, 0x9f, 0x8000, 0xffff, MAP_ROM, 0x000000);
map(LINEAR, 0xa0, 0xbf, 0x8000, 0xffff, MAP_ROM, 0x100000);
map(LINEAR, 0xf0, 0xff, 0x0000, 0x7fff, MAP_RAM);
}
//unverified
//BSC-1A7M-10
//
//$[c0-ef]:[0000-ffff] BSX
@ -75,4 +74,5 @@ mapper(bsc_1a7m_10) {
map(LINEAR, 0x70, 0x7f, 0x0000, 0x7fff, MAP_RAM);
map(LINEAR, 0x80, 0x9f, 0x8000, 0xffff, MAP_ROM, 0x200000);
map(LINEAR, 0xa0, 0xbf, 0x8000, 0xffff, MAP_ROM, 0x100000);
map(LINEAR, 0xf0, 0xff, 0x0000, 0x7fff, MAP_RAM);
}

View File

@ -82,24 +82,9 @@ MMIO mmio_unmapped;
uint8 MMIO::mmio_read (uint16 addr) { return r_cpu->regs.mdr; }
void MMIO::mmio_write(uint16 addr, uint8 data) {}
uint8 MemBus::calc_speed(uint32 addr, bool fast) {
if((addr & 0xc00000) == 0x400000)return 8;
if((addr & 0x808000) == 0x808000)return fast ? 6 : 8;
if((addr & 0xc00000) == 0xc00000)return fast ? 6 : 8;
if((addr & 0xe000) == 0x2000)return 6;
if((addr & 0xfe00) == 0x4000)return 12;
if((addr & 0xe000) == 0x4000)return 6;
return 8;
}
void MemBus::set_speed(bool fast) {
fastROM = fast;
if(fastROM) {
speed_table = (uint8*)speed_table_fastrom;
} else {
speed_table = (uint8*)speed_table_slowrom;
}
fastROM = fast;
fastSpeed = fast ? 6 : 8;
}
void MemBus::flush_mmio_mappers() {
@ -117,12 +102,6 @@ bool MemBus::set_mmio_mapper(uint16 addr, MMIO *mapper) {
}
MemBus::MemBus() {
fastROM = false;
set_speed(false);
flush_mmio_mappers();
for(int i = 0; i < 32768; i++) {
speed_table_slowrom[i] = calc_speed(i << 9, false);
speed_table_fastrom[i] = calc_speed(i << 9, true);
}
speed_table = (uint8*)speed_table_slowrom;
}

View File

@ -19,19 +19,21 @@ class MemBus : public Memory {
public:
MMIO *mmio[0x4000]; //mapped to $[00-3f|80-bf]:[2000-5fff]
bool fastROM;
uint fastSpeed;
void flush_mmio_mappers();
bool set_mmio_mapper(uint16 addr, MMIO *mapper);
private:
//0x1000000 / 512 = 32768
//512 = 0x200, smallest block of a different-speed memory range
//ex. $4000-$41ff = 512
uint8 *speed_table,
speed_table_slowrom[32768],
speed_table_fastrom[32768];
uint8 calc_speed(uint32 addr, bool fast);
public:
uint8 speed(uint32 addr) { return speed_table[addr >> 9]; }
inline uint8 speed(uint32 addr) {
if(addr & 0x408000) {
if(addr & 0x800000) { return fastSpeed; }
return 8;
}
if((addr + 0x6000) & 0x4000) { return 8; }
if((addr - 0x4000) & 0x7e00) { return 6; }
return 12;
}
void set_speed(bool fast);
virtual void load_cart() = 0;

View File

@ -36,6 +36,8 @@ void bPPU::scanline() {
regs.mosaic_countdown--;
}
//note: this should actually occur at V=225,HC=10.
//this is a limitation of the scanline-based renderer.
if(line.y == (!r_cpu->overscan() ? 225 : 240)) {
if(regs.display_disabled == false) {
//OAM address reset
@ -62,10 +64,9 @@ void bPPU::render_scanline() {
if(status.render_output == false)return;
#endif
if(line.y > 0 && line.y < (r_cpu->overscan() ? 240 : 225)) {
if(line.y >= 0 && line.y < (r_cpu->overscan() ? 240 : 225)) {
if(status.render_output == true && line.y != 0) { render_line(); }
render_line_oam_rto();
if(status.render_output == false)return;
render_line();
}
}
@ -304,59 +305,37 @@ void bPPU::reset() {
uint8 bPPU::vram_read(uint16 addr) {
uint8 r;
r = vram[addr];
#ifdef DEBUGGER
snes->notify(SNES::VRAM_READ, addr, r);
#endif
return r;
}
void bPPU::vram_write(uint16 addr, uint8 value) {
vram[addr] = value;
#ifdef DEBUGGER
snes->notify(SNES::VRAM_WRITE, addr, value);
#endif
}
uint8 bPPU::oam_read(uint16 addr) {
uint8 r;
if(addr >= 0x0200)addr = 0x0200 | (addr & 31);
if(addr >= 0x0200) { addr = 0x0200 | (addr & 31); }
r = oam[addr];
#ifdef DEBUGGER
snes->notify(SNES::OAM_READ, addr, r);
#endif
return r;
}
void bPPU::oam_write(uint16 addr, uint8 value) {
if(addr >= 0x0200)addr = 0x0200 | (addr & 31);
if(addr >= 0x0200) { addr = 0x0200 | (addr & 31); }
oam[addr] = value;
#ifdef DEBUGGER
snes->notify(SNES::OAM_WRITE, addr, value);
#endif
}
uint8 bPPU::cgram_read(uint16 addr) {
uint8 r;
addr &= 511;
r = cgram[addr];
if(addr & 1) {
r &= 0x7f;
}
#ifdef DEBUGGER
snes->notify(SNES::CGRAM_READ, addr, r);
#endif
if(addr & 1) { r &= 0x7f; }
return r;
}
void bPPU::cgram_write(uint16 addr, uint8 value) {
addr &= 511;
if(addr & 1) {
value &= 0x7f;
}
if(addr & 1) { value &= 0x7f; }
cgram[addr] = value;
#ifdef DEBUGGER
snes->notify(SNES::CGRAM_WRITE, addr, value);
#endif
}
bPPU::bPPU() {
@ -376,18 +355,12 @@ bPPU::bPPU() {
}
for(int l = 0; l < 16; l++) {
int r, g, b;
double m = (double)l / 15.0;
for(int i = 0; i < 32768; i++) {
r = (i ) & 31;
g = (i >> 5) & 31;
b = (i >> 10) & 31;
r = minmax<0, 31>( (int)((double)r * m + 0.5) );
g = minmax<0, 31>( (int)((double)g * m + 0.5) );
b = minmax<0, 31>( (int)((double)b * m + 0.5) );
light_table[l][i] = (b << 10) | (g << 5) | (r);
for(int i = 0; i < 32 * 32; i++) {
int r = minmax<0, 31>((int)((double)((i) & 31) * m + 0.5));
int g = minmax<0, 31>((int)((double)((i >> 5) & 31) * m + 0.5));
if(i < 32)light_table_b[l][i] = (r << 10);
light_table_gr[l][i] = (g << 5) | (r);
}
}
}

View File

@ -225,7 +225,8 @@ struct {
#include "bppu_render.h"
uint16 light_table[16][32768];
uint16 light_table_b[16][32];
uint16 light_table_gr[16][32 * 32];
uint16 mosaic_table[16][4096];
void render_line();

View File

@ -22,7 +22,7 @@ uint8 bPPU::vram_mmio_read(uint16 addr) {
}
uint16 v = r_cpu->vcounter();
uint16 hc = r_cpu->hcycles();
uint16 hc = r_cpu->hclock();
uint16 ls = (r_cpu->region_scanlines() >> 1) - 1;
if(r_cpu->interlace() && !r_cpu->interlace_field())ls++;
@ -51,7 +51,7 @@ void bPPU::vram_mmio_write(uint16 addr, uint8 data) {
}
uint16 v = r_cpu->vcounter();
uint16 hc = r_cpu->hcycles();
uint16 hc = r_cpu->hclock();
if(v == 0) {
if(hc <= 4) {
vram_write(addr, data);
@ -81,6 +81,10 @@ uint16 hc = r_cpu->hcycles();
//INIDISP
void bPPU::mmio_w2100(uint8 value) {
if(regs.display_disabled == true && !!(value & 0x80) == false) {
regs.oam_addr = regs.oam_baseaddr << 1;
}
regs.display_disabled = !!(value & 0x80);
regs.display_brightness = value & 15;
}

Some files were not shown because too many files have changed in this diff Show More