Compare commits

...

26 Commits
v022 ... v027

Author SHA1 Message Date
byuu
4c43e85141 Update to bsnes v027 release.
This version replaces libui with miu -- a new GUI wrapper library, and cleans up large portions of the source code.
Unfortunately, the GUI rewrite took far, far longer than I ever imagined. As a result, no work has gone into the core emulation for this version. But with the GUI rewrite out of the way, that should change in the near future. And thanks to the new UI library, I can now begin work on adding a cross-platform debugger to bsnes, at long last.
Changelog:
    - Major source code cleanup (lib/, ui/miu/, ui/vai/)
    - Cheat code editor was broken in v0.026, this is now fixed
    - Cheat code file format simplified for human readability
    - Makefile install target improvements [belegdol]
    - libui replaced with miu GUI library
    - Custom video / audio / input drivers replaced with vai HW library
    - ppc and ppc64 libco targets added [Vas Crabb]
    - x86 and x86-64 libco targets now work on OS X [Lucas Newman]
2007-12-22 18:26:54 +00:00
byuu
9da42c18c3 Update to bsnes v026r04? release.
Another WIP. Consider this one v0.027 RC1.

             Bugs fixed:
 - cheat code editor works once again -- cart/ was not loading or
saving the files, and memory/ was not reading from it. Yeah, it was
completely broken in v0.026
 - miu/Win supports window.set_background_color(). The trick was to
capture WM_ERASEBKGND and use FillRect to draw the background myself.
 - miu/Win menubar toggle in fullscreen mode works as expected now for
me. Testing would be appreciated. A total shot in the dark, I tried
using SWP_FRAMECHANGED when resizing the windows, and it worked. It
seems to be an issue due to having two windows that are both set to
use the same menu (I have a hidden window I use for resize-purposes
only, because AdjustWindowRect doesn't work right on multi-line menus,
but the resize window is never visible.) I'm not sure exactly why
SWP_FRAMECHANGED fixed the problem, or why it wasn't needed in libui,
but it works, so I'll take it.
 - make install target uses "install" rather than cp+chmod, but
belegdol unfortunately removed his makefile patch, and I don't recall
where $(DESTDIR) and $(PREFIX) are supposed to go, so those aren't in
there yet ... belegdol, could you please repost that? You're of course
free to change my makefile with your packages as always in case it
gets missed before v027.

             Bugs remaining:
 - D3D renderer is still acting weird. If you start at 256x224 window
size, then the point video filter never works. If you resize to a
larger window and back to 256x224, the video image is linear filtered
no matter what. I tried to fix this tonight, but I had no luck. I'm
really not sure what's wrong, I don't think it's ever really worked
right. Should I fallback on the DDraw renderer for the next release?
It lacks the point filter mode (DDraw lacks an API to control mag
filtering), but that's it. Also, mudlord, PM me if I haven't given you
my WIP URL and you wanted to look at the latest stuff. I can never
remember who I gave the link to or not.
 - system.video / audio / input are not checked, so you get the
compiled defaults only. All vai drivers have now been ported, however.

             I changed the cheat code format. It is now:
             code = status, "description" \r\n

             Or for an example:
             7e1234:56 = enabled, "Infinite Lives"
             7e1235:67 = disabled, "Infinite Health"

 A little easier to read. But maybe still not perfect. I'd really like
to unify the .cht file format with other SNES emu devs ... I don't
want to use a binary file format like ZSNES and SNES9x does.

 I tried testing log audio data -- it seems to be working for me both
on Windows and Linux. FitzRoy, maybe the file isn't going to the
folder you are expecting? Or maybe I fixed it and didn't realize it?
Hmm ...

             Anything else I'm forgetting before a new release? Anyone
see any new / show stopping bugs?

[No archive available]
2007-12-20 10:43:00 +00:00
byuu
d115c7f6aa Update to bsnes v026r03? release.
Another WIP. This one builds on Windows and Linux, and the binary has
the terminal window disabled.

             Bugs fixed:
             - Added WM_ENTERMENULOOP message. Fixes audio looping for
the 37th time since I started on bsnes.
             - Esc toggles menu properly
 - F11 fullscreen centers, but only to the screen, not to the window
(meaning when the menubar is visible, it isn't really centered) --
this is because GTK+ does not return the correct widget size after
calling gtk_window_fullscreen() for up to ~200ms after processing all
messages via gtk_main_iteration_do(), and thus I can't make a
window.get_size() function. I really hope
GetSystemMetrics(SM_CXSCREEN) and gdk_screen_width() only return the
width of the active monitor, and not both for multi-monitor setups
 - Background of main window is black on Linux only. Only one
background brush per class for Windows. It may end up staying gray on
Windows for the next release ...
 - miu/Win enable/disable works. Even for menu items now, so I can
disable features that aren't supported by certain drivers now.

             Bugs remaining:
             - bsnes/Win background in fullscreen mode is gray --
quite ugly
             - D3D still blurring images even with perfect multiplier
             - cheat code editor still doesn't load .cht files on ROM
load

             New bugs:
             - bsnes/Win menubar is ultrafucked in fullscreen mode if
you toggle it on and off with esc. I have _no_ idea what the hell is
up with that. Code to show and hide the menu is identical to
libui/bsnes v026. Not sure I can fix this one. Basically, when the
menu gets toggled back on, clicking it does nothing, and if you press
alt, it will pop up the menu, but it will be _below_ the visible
menubar, so you end up seeing two of them. And you can only access the
new menubar via keyboard. Weird stuff ... could use some help here.
Anyone ever seen or heard of anything like this before?
             - I still need to work on that makefile cp+chmod ->
install thing for belegdol, I think ...

[No archive available]
2007-12-19 14:39:00 +00:00
byuu
2efce0fd83 Update to bsnes v026r02? release.
New WIP. Much, much closer to release quality. Linux port (probably)
won't compile at the moment due to minor changes to miu and vai. I
left the console enabled for this WIP.

             Bugs fixed:
             - Windows always appear at 0,0 instead of centered
 - Input capture window doesn't actually read anything. I actually can
get this working now, I just don't like the hacky way I did it before.
             - miu doesn't send Key events, so no F11 / esc shortcut
keys.
 - miu/Win is still missing some event messages, so some controls may
appear unresponsive. miu/Linux should be complete.
             - miu/Win may still send duplicate messages in some
cases, like that old log audio option bug was doing
             - miu lacks an on_show event, so the config window can't
set focus to the listbox on show just yet
 - bsnes will no longer crash when you try and load a GZ / ZIP / JMA
file with the support not built in (it obviously won't play the games
either) [Richard Bannister]

             Bugs remaining:
             - D3D still blurring image, haven't looked at it yet
 - Cheat code list never populates when loading ROM, probably doesn't
save either (I probably removed that code when rewriting cart/ and
memory/ a while back)
 - miu doesn't emit WM_ENTERMENULOOP, meaning audio cycles when going
into the menu. I wish there were a way to make it pre-emptive like
GTK+ without needing multiple threads ...

             New bugs:
             - Esc doesn't toggle menu yet
 - F11 fullscreen doesn't center, and window background is gray. This
will be tricky, as I only have one RegisterClass() in miu, but you can
only have one HBRUSH per class. Hopefully there's a window message I
can hijack to add back window.set_background_color().
             - miu/Win enable() / disable() doesn't work -- input
config dropdowns active, despite them not working yet

 Other than that, any new bug reports would be appreciated. I hope to
have v027 out by Sunday, but I may not make it in time.

[No archive available]
2007-12-18 12:29:00 +00:00
byuu
f6732133e7 Update to bsnes v026r01? release.
Alright, it's been a full month now since the last private WIP.

 I have Direct3D, DirectSound and DirectInput all working on the
Windows port now; and Xv, GTK+ Video, libao and XInput working on the
Linux port, so now's a good time for a beta.

             Note that countless things are broken, still.
             - D3D still blurring image, haven't looked at it yet
 - Cheat code list never populates when loading ROM, probably doesn't
save either (I probably removed that code when rewriting cart/ and
memory/ a while back)
             - Windows always appear at 0,0 instead of centered
 - miu doesn't emit WM_ENTERMENULOOP, meaning audio cycles when going
into the menu. I wish there were a way to make it pre-emptive like
GTK+ without needing multiple threads ...
 - Input capture window doesn't actually read anything. I actually can
get this working now, I just don't like the hacky way I did it before.
             - miu doesn't send Key events, so no F11 / esc shortcut
keys.
 - miu/Win is still missing some event messages, so some controls may
appear unresponsive. miu/Linux should be complete.
             - miu/Win may still send duplicate messages in some
cases, like that old log audio option bug was doing
             - miu lacks an on_show event, so the config window can't
set focus to the listbox on show just yet

             Any bugs outside of this that seem serious, please tell
me about. Otherwise, I'm working on the rest still :/

[No archive available]
2007-12-16 10:08:00 +00:00
byuu
95547f4ff8 Update to bsnes v026 release.
- Major source code cleanup
    - Completely rewrote memory mapper to support runtime MMCs
    - Updated S-DD1 MMC to use new memory mapping interface
    - Improved S-DD1 emulation, thanks to information from orwannon
    - Added support for SameGame -- load via "Load Special -> Load BS-X Slotted Cart" menu option
    - Completely rewrote cartridge loader to support BS-X, BS-X slotted carts and ST carts
    - Created custom dialog windows for multicart loading
    - Improved generic memory mapper, which eliminates the need for cart.db [Nach]
    - Added BS-X slotted cart detection to generic memory mapper [Nach]
    - Linux port will now ignore keypresses when window is inactive
    - Linux port will use much less CPU power when idle
    - Added detailed compilation instructions to Makefile for Linux port
    - Added "make install" target and PNG program icon for Linux port
    - Switched Windows compiler to MinGW/GCC4
    - Windows executable is now packed with UPX to decrease filesize
    - Removed .ufo, .gd7 and .078 ROM extensions; added .bs extension
    - Added preliminary support for the BS-X base unit, BS-X base cartridge + MMC, and BS-X flash I/O
2007-11-18 21:49:20 +00:00
byuu
4f5bdfe347 Update to bsnes v025r12? release.
New WIP is up.

 I fixed PSRAM size, it's now 512kbytes. SRAM was correct before at
32kbytes. I also now save these files to "bsxbios.psr" (PSRAM) and
"bsxbios.srm" (SRAM). I honestly don't know if the PSRAM is supposed
to be battery backed or not. If it's not, it'll be easy enough to
remove. I imagine it is, because that's where you'd store your games
on if you lacked a flash cart. Would be pretty lousy to have it wiped
every time you power cycle.

 I also save the PSRAM+SRAM data only once, just as a real BS-X cart
would work, and it also makes the Ancient Tablets series work with no
file renaming needed. I may add an option later to save these files
separately per-game.

 BS-X support overall is still pitiful. bs-x.txt doc says $03 has to
be set to mirror PSRAM, SNES9x thinks it needs to be clear. Neither
know whether it affects just $60-6f or also $70-77. bs-x.txt doesn't
say to mirror hi/lo on PSRAM based on $02 setting, but SNES9x seems to
try it. LoROM doesn't map well into 64k granularity banks. Still don't
emulate $0c/$0d flash i/o register enable. Base unit is still
completely unsupported, and it's apparently needed for some games. And
I have no intentions of including an internal database of times to
manually hack the clock (even while the system is running!) ala
SNESGT. I'm just going to map the BS-X base unit RTC to the PC clock.
Some stuff like Dragon Slayer Eiyuu Densetsu work fine under regular
mapping, yet don't work with BS-X mapping. No idea why. Still don't
hack-enable headers during load, so that has to be done manually still
(do this if the game doesn't show up in cart menu. Make a backup if
you care.)

 Added SameGame support. Load it with "Load BS-X Slotted Cartridge"
(that's what it is, after all.) Unfortunately, I don't know what the
memory map is supposed to be, so the add-on cart doesn't appear to be
working. Or maybe I just can't figure out how to tell.
 Nach or anyone else, would you mind sharing that info with me? The
code in SNES9x looks identical to what I have, but loading the FEoEZ
512kbyte cart doesn't seem to do anything. Well, at least the game
itself works under this menu option now.

 Fixed config::path.save, and added realpath() for the Linux port, so
./ paths work too. Of course it won't be useful at all if you
"install" bsnes to /usr/bin, but if you keep it in its own folder,
it's helpful.

 Fixed the SRAM mapping bug affecting Fire Emblem 776. Also optimized
the file loading stuff a little more, removing a couple redundant ROM
memcpy's. Still far from perfect.

             If possible, please test this WIP a lot. I'd like to post
a new public release this weekend.

[No archive available]
2007-11-17 10:09:00 +00:00
byuu
49b0bed1a6 Update to bsnes v025r11? release.
New WIP up. Has a Windows binary this time.

 I completed the BSX cart MMIO registers. It definitely doesn't work
too well. For one, I don't override the header bit in the emulator, so
anyone testing will have to modify the bit as discussed first. It also
doesn't work on my only other BS game, BS Dragon Quest. I don't know
why, it throws a St. GIGA error (09). Maybe it needs base unit
emulation ... who knows. There's probably bugs in the cart and flash
reg support, too.







> My notes on the subject tell me it's the year of download or'd with
> other data. I haven't entirely figured out everything it's or'd with
> though.




 Well, Lancer said the BIOS makes sure d15 of $ffd5,$ffd4 is not set.
If it is, the game does not appear in the list of games you can start.
I'm guessing certain (all?) games expired after a certain date. If
that's true, then we're quite fortunate that only a header bit was
set, rather than the entire cart erased. So then, most likely all of
these games with $80 in $ffd5 appeared "blank", but were dumped and
the games retrieved.

 Sigh, such a sad fate. Really makes you wonder why Nintendo hates
their fanbase so much to go out of their way to destroy these games.

[No archive available]
2007-11-15 10:43:00 +00:00
byuu
1554170312 Update to bsnes v025r10? release.
Yeah, even if we still don't have the S-DD1 100% understood, we can at
least get all known software working properly. And now we at least
have all the registers understood, just the edge cases that need to be
tested. I'm honestly glad I was incorrect in that the original patch
worked on hardware. Given it will never be updated again, this means I
won't have to get bug reports from now unto infinity about it.

 I posted a new binary WIP. If anyone wants to play through a few
levels of SFA2 or dungeons in SO and look for corrupted graphics, it'd
be appreciated. I'm sure it'll be fine, though. Oh, and the speedhit I
reported a few days ago was wrong. The old builds ran at the same
speed. Seems I have a ~6-8fps variance in that game per reboot.

 New WIP also starts the BS-X mapping. You can map in a cart now, but
it immediately freezes because the flash I/O registers do not respond.

             ---

             Also, I'd like to get serious about emulating the
SPC7110. But to do that, I need custom-made hardware.

 I asked someone about this already, but I may as well throw it out
there publicly in case anyone else would like to help.

             Here is the PCB for one of the SPC7110 games:
             http://nsrt.edgeemu.com/INFO/chip-pix/SPC7110.JPG

 What I would need is for the top two ICs to be desoldered, and socket
IC connectors to be placed on them instead. I would also obviously
need lots of compatible EEPROMs to connect to it (just two would
suffice, more would be better as it's quite possible I'd wear out the
write cycles with lots of intense testing, or bend up the pins like I
usually do when removing socket ICs).

             I would also need software+hardware to actually flash the
EEPROMs, as I don't have anything like this presently.

 More complex solutions, such as a ROM emulator with a parallel/USB
interface to the PC would be acceptable as well. So long as it's
something I can reprogram at my relatively low skill level.

 One cart would suffice, but again, the more carts the better in case
of failure. And I'd also like to see about sending one to another
person who's been interested in the SPC7110 for a while. So, three or
four preferred.

             I can supply the cartridges and money for time +
shipping. I'd prefer someone who _knows_ they can do this well try, so
that we don't ruin any unnecessary cartridges and so that the test
cartridges are as durable as possible. Especially since they most
likely won't be encased anymore.

             So, any takers?

[No archive available]
2007-11-13 16:08:00 +00:00
byuu
ec137d6fb9 Update to bsnes v025r09? release.
I posted a new WIP last night. No binary this time,
sorry.
 It redoes the memory mapping of the cartridge and moves it into the
cartridge class -- forking each slotted cart away from the base cart
memory.
 This allows me to determine the proper sizes for each individual cart
again, so I can now map RPG Tsukuru II again correctly.

               EDIT:

               Ahahahahahah!! Finally! I figured out how the S-DD1
$4800 and $4801 registers work! :D

               Original game transfer (should transfer
compressed->decompressed):







    CC2418 LDA #$4000 A:00DA X:F458 Y:1C00 S:01FA DB:00 D:0000 P:01 e
                       CC241B PEA $00DB [0000DB] A:4000 X:F458 Y:1C00
    S:01FA DB:00 D:0000 P:01 e
                       CC241E LDX #$E8ED A:4000 X:F458 Y:1C00 S:01F8
    DB:00 D:0000 P:01 e
                       CC2421 LDY #$0800 A:4000 X:E8ED Y:1C00 S:01F8
    DB:00 D:0000 P:81 e
                       CC2424 JSR $2470 [CC2470] A:4000 X:E8ED Y:0800
    S:01F8 DB:00 D:0000 P:01 e
                       CC2470 STA $2116 [002116] A:4000 X:E8ED Y:0800
    S:01F6 DB:00 D:0000 P:01 e
                       CC2473 SEP #$20 A:4000 X:E8ED Y:0800 S:01F6
    DB:00 D:0000 P:01 e
                       ;* enable $4800 *
                       CC2475 LDA #$01 A:4000 X:E8ED Y:0800 S:01F6
    DB:00 D:0000 P:21 e
                       CC2477 STA $4800 [004800] A:4001 X:E8ED Y:0800
    S:01F6 DB:00 D:0000 P:21 e
                       CC247A LDA #$09 A:4001 X:E8ED Y:0800 S:01F6
    DB:00 D:0000 P:21 e
                       CC247C STA $4300 [004300] A:4009 X:E8ED Y:0800
    S:01F6 DB:00 D:0000 P:21 e
                       CC247F LDA #$18 A:4009 X:E8ED Y:0800 S:01F6
    DB:00 D:0000 P:21 e
                       CC2481 STA $4301 [004301] A:4018 X:E8ED Y:0800
    S:01F6 DB:00 D:0000 P:21 e
                       CC2484 STX $4302 [004302] A:4018 X:E8ED Y:0800
    S:01F6 DB:00 D:0000 P:21 e
                       CC2487 LDA $03,S [0001F9] A:4018 X:E8ED Y:0800
    S:01F6 DB:00 D:0000 P:21 e
                       CC2489 STA $4304 [004304] A:40DB X:E8ED Y:0800
    S:01F6 DB:00 D:0000 P:A1 e
                       CC248C STY $4305 [004305] A:40DB X:E8ED Y:0800
    S:01F6 DB:00 D:0000 P:A1 e
                       CC248F LDA #$01 A:40DB X:E8ED Y:0800 S:01F6
    DB:00 D:0000 P:A1 e
                       CC2491 STA $4801 [004801] A:4001 X:E8ED Y:0800
    S:01F6 DB:00 D:0000 P:21 e
                       CC2494 PHA A:4001 X:E8ED Y:0800 S:01F6 DB:00
    D:0000 P:21 e
                       CC2495 PLA A:4001 X:E8ED Y:0800 S:01F5 DB:00
    D:0000 P:21 e
                       CC2496 STA $420B [00420B] A:4001 X:E8ED Y:0800
    S:01F6 DB:00 D:0000 P:21 e
                       CC2499 STZ $4800 [004800] A:4001 X:E8ED Y:0800
    S:01F6 DB:00 D:0000 P:21 e
                       CC249C REP #$20 A:4001 X:E8ED Y:0800 S:01F6
    DB:00 D:0000 P:21 e
                       CC249E RTS A:4001 X:E8ED Y:0800 S:01F6 DB:00
    D:0000 P:01 e




               Custom transfer (should transfer
decompressed->decompressed):







    CC2428 LDA #$5008 A:00DB X:E8ED Y:0800 S:01FA DB:00 D:0000 P:01 e
                       CC242B PEA $00E9 [0000E9] A:5008 X:E8ED Y:0800
    S:01FA DB:00 D:0000 P:01 e
                       CC242E LDX #$0400 A:5008 X:E8ED Y:0800 S:01F8
    DB:00 D:0000 P:01 e
                       CC2431 LDY #$04E0 A:5008 X:0400 Y:0800 S:01F8
    DB:00 D:0000 P:01 e
                       CC2434 JSR $244C [CC244C] A:5008 X:0400 Y:04E0
    S:01F8 DB:00 D:0000 P:01 e
                       CC244C STA $2116 [002116] A:5008 X:0400 Y:04E0
    S:01F6 DB:00 D:0000 P:01 e
                       CC244F SEP #$20 A:5008 X:0400 Y:04E0 S:01F6
    DB:00 D:0000 P:01 e
                       ;* disable $4800 *
                       CC2451 STZ $4800 [004800] A:5008 X:0400 Y:04E0
    S:01F6 DB:00 D:0000 P:21 e
                       ;* $43x0.d3 (fixed transfer flag) is irrelevent
    to S-DD1 *
                       ;* can be #$01 or #$09 here *
                       CC2454 LDA #$09 A:5008 X:0400 Y:04E0 S:01F6
    DB:00 D:0000 P:21 e
                       CC2456 BRA $247C [CC247C] A:5009 X:0400 Y:04E0
    S:01F6 DB:00 D:0000 P:21 e
                       CC247C STA $4300 [004300] A:5009 X:0400 Y:04E0
    S:01F6 DB:00 D:0000 P:21 e
                       CC247F LDA #$18 A:5009 X:0400 Y:04E0 S:01F6
    DB:00 D:0000 P:21 e
                       CC2481 STA $4301 [004301] A:5018 X:0400 Y:04E0
    S:01F6 DB:00 D:0000 P:21 e
                       CC2484 STX $4302 [004302] A:5018 X:0400 Y:04E0
    S:01F6 DB:00 D:0000 P:21 e
                       CC2487 LDA $03,S [0001F9] A:5018 X:0400 Y:04E0
    S:01F6 DB:00 D:0000 P:21 e
                       CC2489 STA $4304 [004304] A:50E9 X:0400 Y:04E0
    S:01F6 DB:00 D:0000 P:A1 e
                       CC248C STY $4305 [004305] A:50E9 X:0400 Y:04E0
    S:01F6 DB:00 D:0000 P:A1 e
                       CC248F LDA #$01 A:50E9 X:0400 Y:04E0 S:01F6
    DB:00 D:0000 P:A1 e
                       CC2491 STA $4801 [004801] A:5001 X:0400 Y:04E0
    S:01F6 DB:00 D:0000 P:21 e
                       CC2494 PHA A:5001 X:0400 Y:04E0 S:01F6 DB:00
    D:0000 P:21 e
                       CC2495 PLA A:5001 X:0400 Y:04E0 S:01F5 DB:00
    D:0000 P:21 e
                       CC2496 STA $420B [00420B] A:5001 X:0400 Y:04E0
    S:01F6 DB:00 D:0000 P:21 e
                       CC2499 STZ $4800 [004800] A:5001 X:0400 Y:04E0
    S:01F6 DB:00 D:0000 P:21 e
                       CC249C REP #$20 A:5001 X:0400 Y:04E0 S:01F6
    DB:00 D:0000 P:21 e
                       CC249E RTS A:5001 X:0400 Y:04E0 S:01F6 DB:00
    D:0000 P:01 e




               Original transfer right after custom transfer:







    CC2438 LDA #$4000 A:00E9 X:0400 Y:04E0 S:01FA DB:00 D:0000 P:01 e
                       CC243B PEA $00DC [0000DC] A:4000 X:0400 Y:04E0
    S:01FA DB:00 D:0000 P:01 e
                       CC243E LDX #$E0E8 A:4000 X:0400 Y:04E0 S:01F8
    DB:00 D:0000 P:01 e
                       CC2441 LDY #$1080 A:4000 X:E0E8 Y:04E0 S:01F8
    DB:00 D:0000 P:81 e
                       CC2444 JSR $2458 [CC2458] A:4000 X:E0E8 Y:1080
    S:01F8 DB:00 D:0000 P:01 e
                       CC2458 STA $2181 [002181] A:4000 X:E0E8 Y:1080
    S:01F6 DB:00 D:0000 P:01 e
                       CC245B SEP #$20 A:4000 X:E0E8 Y:1080 S:01F6
    DB:00 D:0000 P:01 e
                       CC245D LDA #$7F A:4000 X:E0E8 Y:1080 S:01F6
    DB:00 D:0000 P:21 e
                       CC245F STA $2183 [002183] A:407F X:E0E8 Y:1080
    S:01F6 DB:00 D:0000 P:21 e
                       CC2462 LDA #$01 A:407F X:E0E8 Y:1080 S:01F6
    DB:00 D:0000 P:21 e
                       ;* $4800 enabled again *
                       CC2464 STA $4800 [004800] A:4001 X:E0E8 Y:1080
    S:01F6 DB:00 D:0000 P:21 e
                       CC2467 LDA #$08 A:4001 X:E0E8 Y:1080 S:01F6
    DB:00 D:0000 P:21 e
                       CC2469 STA $4300 [004300] A:4008 X:E0E8 Y:1080
    S:01F6 DB:00 D:0000 P:21 e
                       CC246C LDA #$80 A:4008 X:E0E8 Y:1080 S:01F6
    DB:00 D:0000 P:21 e
                       CC246E BRA $2481 [CC2481] A:4080 X:E0E8 Y:1080
    S:01F6 DB:00 D:0000 P:A1 e
                       CC2481 STA $4301 [004301] A:4080 X:E0E8 Y:1080
    S:01F6 DB:00 D:0000 P:A1 e
                       CC2484 STX $4302 [004302] A:4080 X:E0E8 Y:1080
    S:01F6 DB:00 D:0000 P:A1 e
                       CC2487 LDA $03,S [0001F9] A:4080 X:E0E8 Y:1080
    S:01F6 DB:00 D:0000 P:A1 e
                       CC2489 STA $4304 [004304] A:40DC X:E0E8 Y:1080
    S:01F6 DB:00 D:0000 P:A1 e
                       CC248C STY $4305 [004305] A:40DC X:E0E8 Y:1080
    S:01F6 DB:00 D:0000 P:A1 e
                       CC248F LDA #$01 A:40DC X:E0E8 Y:1080 S:01F6
    DB:00 D:0000 P:A1 e
                       CC2491 STA $4801 [004801] A:4001 X:E0E8 Y:1080
    S:01F6 DB:00 D:0000 P:21 e
                       CC2494 PHA A:4001 X:E0E8 Y:1080 S:01F6 DB:00
    D:0000 P:21 e
                       CC2495 PLA A:4001 X:E0E8 Y:1080 S:01F5 DB:00
    D:0000 P:21 e
                       CC2496 STA $420B [00420B] A:4001 X:E0E8 Y:1080
    S:01F6 DB:00 D:0000 P:21 e
                       CC2499 STZ $4800 [004800] A:4001 X:E0E8 Y:1080
    S:01F6 DB:00 D:0000 P:21 e
                       CC249C REP #$20 A:4001 X:E0E8 Y:1080 S:01F6
    DB:00 D:0000 P:21 e
                       CC249E RTS A:4001 X:E0E8 Y:1080 S:01F6 DB:00
    D:0000 P:01 e




 I was completely wrong, and was thrown off by ZSNES' memory remapping
magic that worked due to an oversight with $43x0.d3, or the fixed
transfer flag. I never added a check for the fixed transfer flag
because it quite honestly made no sense. Why would the S-DD1 care
about that?

               Turns out, it doesn't. What really matters is $4800.
The register everyone currently ignores completely.

               I figured out what purpose it serves: it's a sticky
toggle, whereas $4801 is a loose toggle.

 It works like this: in order for the S-DD1 to decompress a DMA
transfer, both $4800 and $4801 have to be set. Upon completion of the
transfer, $4801 is cleared. But $4800 is not.

 If you look at the above logs, it becomes clear. And it's all
contained inside the S-DD1 code. It has nothing to do with $43x0.

 Now, how can I verify this? orwannon made a flash cart for Star Ocean
and ran my old title screen patch on it. Sure enough, it did not try
and decompress the graphics data, despite the fixed transfer flag
being set. That tells us that the fixed transfer flag has nothing to
do with this.

 What's interesting is that every single S-DD1 supporting emulator
works just fine with my title screen patch. Meaning that they've all
implemented these two registers wrong.

 What was also interesting is that it's supposedly been confirmed that
the patched SO works on real hardware. That means the bug was in bsnes
after all. No excuses, I was flat out wrong. My sincere apologies.

 I've added the above changes, and bsnes now works with the original
patch, and fails with my custom patch. This mimics the behavior of
real hardware.

 Huge thanks to orwannon for the screenshot of my patch running on
real hardware. This fix wouldn't have been possible without that.

[No archive available]
2007-11-12 21:52:00 +00:00
byuu
aee683a475 Update to bsnes v025r08? release.
New WIP up.

 I spent four hours completely rewriting everything but the generic
header parsing code in src/cart. I'm now happy with the code both in
src/memory and src/cart. Hoorah.

 With the new load_cart() functionality, I made the "Load Special"
menu entries functional. For those of you stuck on Windows or without
WIP access, you can see how nice the load menus look on Linux below :)

             http://byuu.cinnamonpirate.com/bsnes/images/ui_bsx.png
             http://byuu.cinnamonpirate.com/bsnes/images/ui_st.png

 There is one bug: because of the way I map the slotted carts into one
contigious chunk of ROM (and hence update the size accordingly), it
throws off the memory mirroring on some of the BS-X slotted cart games
(like RPG Tsukuru II). I need to work on that a bit. For now, you can
play it through the normal load cartridge menu option.

 And of course, there's still that annoying Windows issue where the
main window steals focus after loading a ROM. Haven't looked into that
yet.

 And I still need to rework the file extension stuff per previous
discussions. It'd be nice to have the BS-X / ST windows only show .bs
/ .st ROMs by default.

[No archive available]
2007-11-05 07:22:00 +00:00
byuu
cdbf07b642 Update to bsnes v025r07? release.
Ok, posted the new WIP with the LoROM map corrections. This one also
modified the load special menu. They now bring up a new window that
lets you select the base cart + slot cart(s). However, the menus do
not work yet. There's also some odd issue that it loses focus when you
select a ROM from the browse button, but only on Windows. Hitting load
just hides the window. I also need to add code to automatically load /
save the BIOS filenames where applicable.

Also, forgot to mention last time, but I added a new config file
option, cpu.wram_initial_value or something like that. It's purpose
should be pretty obvious.

[No archive available]
2007-11-04 11:36:00 +00:00
byuu
8a857dada3 Update to bsnes v025r06? release.
Ok, new WIP up. Pretty much all of the credit goes to others, this
time.

             Changelog:
             - I forgot to set the region, so PAL games were running
as NTSC; this is fixed
             - Added Nach's BS-X slotted flashcart detection (added
his Ys'3 SRAM detection earlier)
 - Used BSC-1A7M-10 PCB mapper from Overload's documentation for the
generic BS-X slotted cart games; Derby Stallion '96, Sound Novel
Tsukuru and RPG Tsukuru II are all playable once again; hopefully the
rest of the slotted games work, too (sans the SA-1 game(s)). Please
test if you can
 - Added krom's (and I suppose Nach's earlier submitted) MinGW32 icon
support; so FitzRoy's wonderful icon is there now on the EXE -- still
need to add it to the window titlebar (easy on Windows), and to Linux
in general, ugh
 - Removed win-mingw4-lui target, simplifying Makefile. Use win-mingw-
lui now. Thanks again to krom's suggestion to just copy the MinGW4
-sjlj files, that worked great
             - Some more cleanup work to src/cart. Still a lot to go
here.

 Everything that was playable in the last release should now be
playable, excepting Yoshi's Island music. Please let me know if
anything is broken that wasn't before now.

 As always, I'm really thankful to everyone for their contributions.
My program would be useless if not for all the help I've gotten from
everyone else.

             ---

 Now then, I aim to support those BS-X slotted cart games as well. But
one thing I did not know until today was that you could actually
exchange those carts between games. That ruins the model I planned to
use for them (eg make romname.smc -> romname.bsf files).

 Thinking about it -- I really need to completely redesign file
loading. BS-X and Sufami Turbo stuff really throws off the "Load ROM"
paradigm that is so popular amongst emulators.

 I'm thinking ... remove the "Load Special" menu completely. Modify
the main ROM loading routine to parse what exactly is being loaded.

 If it's a BS-X slotted cart, pop up a menu that lets one optionally
select to load an additional flash cart, or cancel the menu to load
nothing in the slot. This won't be hot-swappable in-game.

 If it's a Sufami Turbo cart, assume Slot A for the cart. If this game
supports dual slotting*, pop up an additional menu to select the Slot
B game, which can also be left empty. (* perhaps popup the menu no
matter what, to more closely simulate that with real hardware, you
could stick incompatible games in both slots anyway?)

             Same deal for Same Game, G-Next, and all that other crap,
if or whenever I end up supporting those.

 I think it's best to keep the BIOS stuff in the config file, rather
than giving an optional popup menu to modify which BIOS to load. The
reason being that it will allow direct loading of BS-X games with no
need to ever show a popup menu.

 Lastly, I will have to add a new Misc menu option to generate empty
BS-X flashcart files. Though it's really easy to make one, I imagine
end users might have trouble doing that.

             Ideas or suggestions welcome.

[No archive available]
2007-11-02 09:30:00 +00:00
byuu
ab1975a6cb Update to bsnes v025r05? release.
I mentioned that it wasn't there. Exact reason was because I reloaded
Ubuntu and Windows, and I really hate installing Visual C++. It takes
forever. I posted a new WIP, and built it with MinGW4. Need to figure
out how to get the icon into the binary with MinGW.

             Anyway, new stuff in the WIP:

 - Much, much faster mirror() function; thanks to lots of help from
Nach (doesn't speed anything up, but might help with BS-X MMIO
registers)
             - Removed cart.db and all database-related code, now that
Ys3 works
             - Lots of code cleanups everywhere
             - New help information for trying to run ./configure or
make by itself
             - Cheap temporary MinGW fix for non-C99 vsnprintf

 The BS-X slot games (Derby Stallion et al) won't work on this
release. Nach gave me the code to detect those, and I'll get that
mapper in eventually before the next release. Also, Yoshi's Island
won't play audio anymore most likely.

 If anything else is broken, it's due to mapping. Please let me know
so I can fix it. If there are more than three broken games, that's
good -- please don't overwhelm me with a list of 500+ broken games in
the morning :)

             EDIT: fixed the Windows issues I was having. The Realtek
HD Audio driver software is fucking stupid. You _have_ to unplug your
speakers, reconnect them, and then select line out (rather than the
option for speakers) to get audio. This is the _only_ way to get
audio. And apparently both regular Winamp (without visualization) and
Mozilla Firefox now need DEP turned off not to crash the fuck all over
themselves constantly. Wonderful.

 EDIT2: forgot to set the region, so PAL games will run as though they
are NTSC. Most will probably give you an error splash screen. I'll fix
that.

[No archive available]
2007-10-31 10:18:00 +00:00
byuu
476a1c819a Update to bsnes v025r04? release.
New WIP up. This one's a bit better than last, but I
don't want bug reports yet. This one only maps generic LoROM and HiROM
games.

 Took about four or five hours, but I reworked most of the new memory
mapper yet again. SRAM should be working now, and I managed to gain
back the speed lost by dropping the address masking and forcing Visual
C++ to inline (__forceinline). The masking was no good anyway, because
the ROM file loaded in is definitely not always a power of two, which
means I'd have to use modulus and holy fuck no I'm not adding a
division for every memory access.

 The old memory mapper didn't have this either, as it stored a bunch
of pointers into memory chunks. The new one just stores one pointer
plus integer offsets into that pointer (a bit slower but cleaner and
necessary for abstraction), so it's really mostly the same thing.

 Man, I was looking at my old generic LoROM / HiROM mapper, and the
difference from that and what I have now is astounding ... it would
seem I've certainly gotten better at programming since then.







    /* new */
                       void sBus::map_generic() {
                       switch(cartridge.info.mapper) {
                       case Cartridge::LOROM: {
                       map(MapLinear, 0x00, 0x3f, 0x8000, 0xffff,
    memory::rom);
                       map(MapLinear, 0x80, 0xbf, 0x8000, 0xffff,
    memory::rom);
                       map(MapLinear, 0x40, 0x7f, 0x0000, 0xffff,
    memory::rom);
                       map(MapLinear, 0xc0, 0xff, 0x0000, 0xffff,
    memory::rom);
                       } break;
                       case Cartridge::HIROM: {
                       map(MapShadow, 0x00, 0x3f, 0x8000, 0xffff,
    memory::rom);
                       map(MapShadow, 0x80, 0xbf, 0x8000, 0xffff,
    memory::rom);
                       map(MapLinear, 0x40, 0x7f, 0x0000, 0xffff,
    memory::rom);
                       map(MapLinear, 0xc0, 0xff, 0x0000, 0xffff,
    memory::rom);
                       } break;
                       }

                       if(memory::sram.size() == 0) { return; }
                       map(MapLinear, 0x20, 0x3f, 0x6000, 0x7fff,
    memory::sram);
                       map(MapLinear, 0xa0, 0xbf, 0x6000, 0x7fff,
    memory::sram);
                       map(MapLinear, 0x70, 0x7f, 0x0000, 0x7fff,
    memory::sram);

                       if(cartridge.info.mapper != Cartridge::LOROM) {
    return; }
                       map(MapLinear, 0xf0, 0xff, 0x0000, 0x7fff,
    memory::sram);
                       }

                       /* old */
                       void bMemBus::cart_map_generic(uint type) {
                       uint rom_size = cartridge.info.rom_size;
                       uint ram_size = cartridge.info.ram_size;

                       for(uint page = 0x0000; page <= 0xffff; page++)
    {
                       if(memory_type(page << 8) !=
    TYPE_CART)continue;

                       uint addr = page << 8;
                       uint bank = page >> 8;

                       //RAM mapping is incorrect in several games,
    this is the most compatible
                       //layout I can create using only ROM header
    information. Additional accuracy
                       //requires PCB identification.

                       //Unmapped region
                       //$[00-1f|80-9f]:[6000-7fff]
     if((bank & 0x7f) >= 0x00 && (bank & 0x7f) <= 0x1f && (addr &
    0xe000) == 0x6000) {
                       continue;
                       }

                       //HiROM RAM region
                       //$[20-3f|a0-bf]:[6000-7fff]
     if((bank & 0x7f) >= 0x20 && (bank & 0x7f) <= 0x3f && (addr &
    0xe000) == 0x6000) {
                       if(ram_size == 0)continue;

                       addr = ((bank & 0x7f) - 0x20) * 0x2000 + ((addr
    & 0xffff) - 0x6000);
                       addr %= ram_size;
                       page_handle[page] = cartridge.ram + addr;
                       page_read [page] = &bMemBus::read_ram;
                       page_write [page] = &bMemBus::write_ram;
                       continue;
                       }

                       //LoROM RAM region
                       //$[70-7f|f0-ff]:[0000-7fff]
                       //Note: WRAM is remapped over
    $[7e-7f]:[0000-ffff]
     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.ram + addr;
                       page_read [page] = &bMemBus::read_ram;
                       page_write [page] = &bMemBus::write_ram;
                       continue;
                       }
                       }

                       //ROM region
                       switch(type) {

                       case Cartridge::LOROM: {
                       addr = (bank & 0x7f) * 0x8000 + (addr &
    0x7fff);
                       addr = mirror(rom_size, addr);
                       } break;

                       case Cartridge::HIROM: {
                       addr = mirror(rom_size, addr);
                       } break;

                       }

                       page_handle[page] = cartridge.rom + addr;
                       page_read [page] = &bMemBus::read_rom;
                       page_write [page] = &bMemBus::write_rom;
                       }
                       }




 Note that those two certainly aren't identical in function, and I'll
no doubt have some memory mapping bugs again (probably with Final
Fight, SFII and such), but it should only require minor changes to fix
that.







> byuu: is it possible there's supposed to be steam appearing there to
> create the illusion, but isn't?




               That's a lot more likely, honestly. Hopefully someone
can make it to level 5, heh. I know I sure as hell can't.

[No archive available]
2007-10-18 09:40:00 +00:00
byuu
42d3f2a37f Update to bsnes v025r03? release.
New WIP up, and this one is _not_ for playing games on.

 I replaced the memory mapper entirely with a new system that should
be infinitely easier to remap dynamically. This is a necessary step
for BS-X MMIO register emulation. It should also speed up S-DD1
emulation by eliminating the need for a special address conversion
routine to simulate its memory mapper.

 However, the new bus memory mapper is anything but complete. Right
now, it only loads really, really basic LoROM games. Stick to Super
Mario World and Zelda 3.

 Some good news is that it's ~1-2% faster with MinGW4, but the bad
news is that it's ~10% slower with Visual C++, and MS' compiler is
stupidly storing my 128kb array directly into the EXE, making the file
size bigger. And yet the ZIP of the whole thing is smaller! >_<

 Bah. I think I can fine tune most of the performance lost back out of
Visual C++ with some forced inlining, and I'll make that WRAM array
allocate at runtime.

 Surprised I was able to get any games playable in less than three
hours, replacing the entire memory mapping system like that. Lucky me.







> -O8 -mtune=prescott -ffloat-store -fforce-addr -finline-functions
> -fexpensive-optimizations -funroll-all-loops -ffast-math -fomit-
> frame-pointer




 I didn't realize you could go above -O3 ... interesting. If you want,
try building with profile guided optimizations for another ~15% speed
boost. It's pretty unstable like that, though. Maybe you'll have
better luck than me.

               The warning message is in src/cart/cart_file.cpp at the
top.

[No archive available]
2007-10-17 04:51:00 +00:00
byuu
c58e3af1b5 Update to bsnes v025r02? release.
Alright, posted a new WIP with the BS-X skeleton. The
BIOS needs to be named bsxbios.bin, and it can't have a header.

 There's also "Load Special -> Load BS-X Cartridge ...", but it
doesn't work yet. It maps the flash cart into $[c0-ff]:[0000-ffff],
but that doesn't do much good. The BIOS then detects the flash cart
and starts probing the memory mapping registers and eventually
deadlocks.

               To emulate the MMIO registers, I will have to
_completely_ rework my memory mapping code to support dynamic
remapping. Not necessarily a bad thing, I was planning to rewrite all
of that anyway (per my diagram yesterday). Might as well kill two
birds with one stone.

 Gonna take at least a few days of planning before I go at that. I
want to get it right this time, so I don't have to do this again.

               In the meantime, have fun walking around the dead St.
GIGA ghost town ;)







> Byuu, that's some sweet ass shiz. You are a man on a mission this
> week. Let me know when you feel you've supported it enough to remove
> it from the list.




 Yeah, not sure what's up. I rarely have motivation to do anything
anymore, but it always comes in bursts. So I'll take advantage of it
now, and hope it doesn't burn out soon.

 I've a long way to go with BS-X before we can remove it, sadly. I
think we can remove when I get >50-75% of games loading. I doubt we
can reach 100%. There's missing info, corrupted / hacked BS ROMs
galore, and I don't even have BS-X hardware to test with.







> byuu, you always show something cool in a new version RIGHT after
> your official releases




 Sorry about that, it's not intentional. The thing is that no BS-X
games are even playable yet. I suppose when it's stable, I'll post
another public version, assuming the core is still stable with all the
plans I have for it.







> I really enjoy following your development of bsnes. I can't wait for
> the day I have a computer that is actually fast enough to play games
> with it (I'm currently using an Athlon 1.1 GHz).




               Sorry about that :(

               ---

 Side note: I also posted v0.025a, which removes the warning message
when SRM files don't exist. Nothing else is different, though.

[No archive available]
2007-10-16 05:50:00 +00:00
byuu
8226e243b8 Update to bsnes v025a release.
My apologies, I added code to display an alert when the Sufami Turbo BIOS was not present at the last minute before the recent release. What I failed to realize was that I added the alert to the same routine that loads save RAM files. Meaning that whenever one loads a game that has not yet created a .srm file, one will get a warning that the save RAM file does not exist. Oops.
You'll never see the warning more than once, and it's harmless, but for those it annoys, and for people who haven't upgraded yet, I've posted bsnes v0.025a. This version changes absolutely nothing other than disabling the warning box in question. I'll be sure to get a proper, tested fix into the next release. Again, I apologize for any inconveniece this may have caused.

[No archive available]
2007-10-16 00:00:00 +00:00
byuu
9ab3fa6227 Update to bsnes v025r01? release.
I'll bet this will surprise you all, I already have a
private WIP for the v0.025 series up :P
 Absolutely no emulation changes, just lots of major code changes I
held off on as I didn't want to break anything last minute.

 - Polymorphism through pointers using compile-time flag is dead. It
took a ~10% speed hit, so it was never feasible to use anyway. This is
also a required step to encapsulating the entire emulator inside a
single class which can support multiple instances. r_cpu-> becomes
cpu. , r_smp-> becomes smp. , etc.
 - Greatly cleaned up interface.h as much as possible for now. Right
now, bsnes takes a lot longer than it should to compile because every
single object includes every last header for all objects. In the
future, I want to move headers so that only objects that need others
include those headers. Will increase compile speed a good bit.
               - Created chip/chip.h to start on the above.
               - Finally renamed chip/c4 to chip/cx4. Class name also
changed from C4 to Cx4.
               - Removed libsort, as it's not used (yet?). Was
needlessly slowing down compile time.
 - Created src/doc. This will be a folder that contains source code
documentation, diagrams, maps, to-do lists, etc. Started things off by
creating a _very_ basic overview of bsnes as a whole.

 Much more radical stuff to come. I don't anticipate making another
public release for quite a long time, so I should be able to go wild
here with restructuring things.







> I just checked out the new bsnes version 0.025, but I could not find
> any option in the config file to change the memory / mem via PRNG
> initialization byte, that we were talking about earlier to help get
> some old pd stuff working...




 Oh, I'm sorry about that. Didn't get a chance to add it this time. I
need to work a PRNG with a consistent seed value into the core first.
Not sure how I want to do that.

 For what it's worth, initializing RAM to 0x00 unfortunately did not
fix Sidmania's graphical issues as I had hoped. Given FitzRoy reports
the glitches occur on real hardware as well, I'm afraid there's not a
whole lot I can do about it. I will pay attention to it when working
on my cycle-based PPU in the future, though.







> On another note your emulator has inspired me to do my first
> translation for the snes "Albert Odyssey", and has been very useful
> for this purpose.




 Neat! Be sure to check out bsnes v0.013 on RHDN for its debugger.
It's the only SNES emulator with VRAM breakpoints, as far as I know.
Also be sure to try out xkas for your cross assembler :D </shameless
self-promotion>







> Oct. 14 also happens to be the 10th anniversary of the first public
> release of ZSNES, interestingly enough.




               o.O
 Holy crap, why didn't I ever hear about this before? That's really,
really interesting ... of course, the difference is that bsnes was
started on 10-14, ZSNES was first released then but obviously started
much sooner. Still cool, though.

 I wonder if anyone knows the exact date zsKnight started on ZSNES, or
Jeremy Koot on SNES9x. It would be really cool to have a history of
the SNES emulation scene. So many emulators most have never even heard
of ... RSRSNES, GrimSNES, TrepSNES, Moonlit Coalition's emulator (that
played one game, heh), Simkin's simulator thing ... heh, I wonder if
anyone here knows the name of the SNES emulator I tried (and failed)
making way before bsnes, back in 2001. Google doesn't even know of it
:)

[No archive available]
2007-10-15 05:21:00 +00:00
byuu
85fa3cc968 Update to bsnes v025 release.
bsnes is exactly three years old today. I've posted a new version which adds DSP-3 and DSP-4 special chip support. The DSP-3 is used by SD Gundam GX, and the DSP-4 is used by Top Gear 3000. Please note that the DSP-3 is not fully emulated, thusly SD Gundam GX is not fully playable. Also, due to lack of timing emulation with the DSP-4, the Top Gear 3000 track sometimes flickers in split screen mode. However, it is believed that Top Gear 3000 is fully playable.
I should also note that I have started on SuperFX emulation, as some will inevitably see said code in my source releases. What I have now is nothing more than a skeleton implementation, and absolutely nothing using it is playable yet. I am making absolutely no promises that I will ever be able to emulate this chip. It will take at least several months of work, and even then, the speed will probably be too slow to reach 60fps on any system, but ... I'm working on it. While I have no way to run tests on the actual SuperFX hardware, I will do the best I can to emulate the chip accurately. I will be emulating the caching and cycle delays as best I can, but the information I have on this chip is extremely limited, so don't expect miracles.
Lastly, as promised, I have released the special chips I have personally emulated to the public domain. See license.txt for more information if interested. I cannot release the special chips whose code I did not write to the public domain, but all of that is already available under the GPLv2 (from ZSNES) or the SNES9x license.
Changelog:
    - Added DSP-3 support, thanks to John Weidman, Kris Bleakley, Lancer, z80 gaiden
    - Added DSP-4 support, thanks to Dreamer Nom, John Weidman, Kris Bleakley, Nach, z80 gaiden
    - Started on support for SuperFX, no games playable as chip emulation is less than 1% complete
    - Unsupported special chips will now display an alert
    - Missing stbios.bin file when loading Sufami Turbo cartridges will now display an alert
    - Video settings now saved separately for windowed and fullscreen mode
    - Advanced option video<.mode>.synchronize can be enabled for vsync, but will cause sound crackling
    - Added menu option to toggle FPS counter
    - Minor source code cleanup
2007-10-15 10:03:36 +00:00
byuu
d1fcddee9c Update to bsnes v024r01? release.
New WIP up.

 This one merges the most recent DSP-3 / DSP-4 work. Not sure if it
fixes any bugs or not, but good to be up to date, right? Testing would
be appreciated.

             I also cleaned up the cart stuff a bit. Nicer enums,
removed some unused variables and such.

 Then I turned all of the special chip class object pointers into
actual objects. It was kind of stupid to dynamically create them all,
and was just wasting performance.

 I also finished adding all of the SuperFX registers, and mapped them
all to the GSU interface range ($3000-$32ff). Fixed an oversight with
the mapping, and added a new PCB database entry to get the memory map
for Yoshi's Island perfect. If you want to hear something nice, try
loading the USA version in this WIP with sound + speed regulation
enabled.

 Then I added a 'Show FPS' option to the misc menu. I also didn't
realize I was still embedding the SNES controller bitmap even though
it wasn't displayed anywhere, so for now that's been removed. Makes
the EXE and archive a bit smaller.

 Lastly, I redid the bsnes section of my site to look a little more
polished. Getting ready for 10/14. I've always hated the way SNES
emulator authors always cherry picked most of their screenshots to
show off their special chip support (jealousy because I didn't have
any for a long time), so I decided I'd do the exact same thing myself
this time :P
 Ripped off Overload yet again, this time I stole his screenshot
layout style. Sorry, Overload ... but imitation is the sincerest form
of flattery, right? :)

 Also, note that all of the ?page=bsnes_* URIs have changed to
?page=bsnes/* ... so if you get redirected to the main page from a
bookmark or something, that's why.

             Whew, busy day today ...

[No archive available]
2007-10-12 06:55:00 +00:00
byuu
9fd379613a Update to bsnes v024 release.
This is an interim release between some major changes to the video mode support, which may take a long time to complete. It also fixes a bug with CGRAM access timing, re-adds the Sufami Turbo load menu, and adds support for the ST-010 coprocessor, used by F1 Race of Champions.
To load Sufami Turbo cartridges, stbios.bin must be placed inside a folder named bios in the bsnes folder. There is not currently a warning if this file is missing.
2007-10-01 09:03:44 +00:00
byuu
aabf52d678 Update to bsnes v023r01? release.
Alright, I've posted the new WIP.

             Changelog:
             - CGRAM fix for WWF Super Wrestlemania
             - Updated to blargg's snes_ntsc library to version 0.2.2
             - Added ST and ST dual cart loading menu options (*)
             - Redesigned the video mode configuration panel a bit --
let me know what you think (**)

 (*) - You have to set path.bios to an -absolute- path, ./ is
currently broken and I need to fix that. So, set it to eg
"c:/path/to/bsnes/bios" where stbios.bin is inside that folder.
             (**) - The video menu obviously doesn't do anything, it's
just there for design advice / suggestions for now.

 You'll notice the icon is gone. This is because I built this version
with MinGW 4, and I'm not sure how to add the icon to MinGW apps.
You'll also notice it's ~6% faster on Core 2 processors as a result.

 The 16% speedup was only when PGO was enabled. But I can't enable
that, because it causes bsnes to crash randomly. GCC gets too risky
with its optimizations and ends up generating bad code (the GCC manual
states as much, I'm not just trying to blame problems in my app on GCC
here.)

 So, 6% is the best speedup we can do for now. Compare to v0.023
official if you like. You probably won't see the speedup on older
processors like the Pentium IV.

 EDIT: it seems like that MinGW vsnprintf problem is based on DLL
files on the local computer. Probably the MS VisualC runtime files.
The WIP works fine on my home PC (WinXP Pro), but not on my work PC
(Win2k). I'm going to have to stick with Visual C++ builds until I am
able to completely remove all sprintf-style calls from the emulator.

 If you get an error about memory at 0xffffffff which cannot be read,
you know why. Try building with Visual C++ if you have it, or maybe
there's some way to upgrade libc DLLs that the app is binding to.
Whatever DLL has vsnprintf is the one that needs to be updated, if at
all possible.

             Here's what the video config screen looks like at the
moment.

             [image]

 I tried putting the text at the top, that way there won't be any odd
gaps between the text and combo box dropdown, due to different sized
fonts on different platforms.

[No archive available]
2007-09-25 14:20:00 +00:00
byuu
c9ca01fe20 Update to bsnes v023 release.
I've recently fixed a bug in bsnes that I feel is serious enough to warrant a new release, even though little else has changed.
I attempted to build this release with MinGW, but ran into problems with profiling and JMA support, so this release was built with Visual C++ once again.
Changelog:
    - Fixed serious bug in S-SMP incw and decw instructions -- fixes sound bug in Emerald Dragon
    - Added Nach's MinGW fixes -- can now be compiled with MinGW/GCC3 or MinGW/GCC4
    - Fixed const char* cast warnings in GCC 4.2, thanks to [vEX] for the feedback
    - Updated source to use latest libraries for libco, libui, etc.
    - Added new advanced options to adjust aspect ratio correction
    - Cleaned up source code a bit
2007-09-16 19:30:35 +00:00
byuu
becf122aaa Update to bsnes v022r04? release.
Ok, I've posted a new WIP with the Emerald Dragon bug
fix. This time, I'm not posting the WIP publically. My last request
not to link directly to the file elsewhere was ignored, and ended up
on at least two emulation news sites (I won't mention names.) I'm not
trying to be a jerk about it, I really can't spare that kind of
bandwidth.

 If anyone has contributed any code or bug fixes, reported any
confirmed bugs, or is an emulator author I've spoken to in the past,
feel free to request a link to the WIP page from me in PM if desired.

               Sorry to everyone else. I'll have the new version out
as soon as possible.







> As for the AR advanced option, I think option 2 looks perfect.




 Done. I didn't add any sanity checks, so that people can have a
little fun with it. It's not going to be a GUI option, so only
advanced users can play with it anyway. Try setting a crazy aspect
like 3:1 and play a platform game. It's guaranteed to mess with your
mind.

 I also added the ... stuff, but I did not add the pause support back
in yet. Not sure if that'll make the next release, because it requires
some changes to the main loop functions that have been missing for a
while now. I usually like to leave more of a beta testing window
before messing with that stuff.







> byuu, you may know this, but on the front page of your web site, the
> link to your Philosophical Ramblings page is
> "http://localhost/index.php?page=articles/philosophy".




               Hahah, oops. No, I didn't notice that. I must have
copied the link from my browser instead of typing it manually.

 It's a stupid article, anyway. Didn't come out like I planned. I was
also reading some comments by Miguel de Icaza (supporting patent
pacts) and Linus Torvalds (bashing the hell out of C++ programmers),
and came across an interesting comment that got me thinking. Basically
that people who have any kind of notability really shouldn't go around
talking about things outside their specific expertise, because it
makes them look foolish when people take them too seriously (and
people do) as those two comments by de Icaza and Torvalds did. Lucky
for me I really _don't_ have any kind of notability, but it's a good
principle to adhere to anyway. Stick to talking about what I know
best. That goes against my whole personality though, so I probably
won't change at all anyway.

[No archive available]
2007-09-12 10:08:00 +00:00
byuu
1e130d7872 Update to bsnes v022r03 release.
Double post!

 I've uploaded a new WIP, which I'll make public (only to this forum,
please don't post about it anywhere else unless you mirror the file):







    http://byuu.org/files/bsnes_v022_wip03.zip




 This version adds all of Nach's MinGW fixes, updated libco, libui and
libfunctor, cleans up the code that detects if the main window has
focus or not (if not, ignore keyboard input), adds the new makefile
target win-mingw-lui, finally fixes all of the char* conversion
warnings with GCC 4.2.x (thanks [vEX]), and I'm sure there's more, but
I don't remember.

 The ZIP includes a Visual C++ generated binary, but it also works
with MinGW GCC4. It won't work with MinGW GCC3 because that one lacks
a C99-compliant vsnprintf function. You can hack your way around that
by editing src/lib/libstring_sprintf.cpp if you really want to use
MinGW GCC3.

 You may also need to change the CC / CPP variable names. I went with
the generic names mingw32-gcc and mingw32-g++, but the GCC4 binaries
have -sjlj or -dw2 appended to them. You'll also need to set
-I/path/to/directxheaders, or copy them all into
/path/to/mingw/include, since MinGW seems to ignore the include
environment variable.

 And finally, a bit of good news. It appears that MinGW GCC4 builds
binaries that are ~6% faster than Visual C++. That means with PGO
enabled, they should be at least ~16% faster than v0.022 official. If
I can figure out how to hide the ugly terminal window in the
background, I'll start making official releases with MinGW GCC4 from
now on.
2007-09-08 08:41:18 +00:00
348 changed files with 18402 additions and 11555 deletions

BIN
cart.db

Binary file not shown.

View File

@@ -1,4 +1,4 @@
bsnes (TM) Open Source Reference License
bsnes (TM) Reference License
Copyright (C) 2004 - 2007 byuu
All rights reserved
@@ -52,12 +52,35 @@ Further, respective source code files are labeled with their correct licensing
information in the header. The lack of such a header indicates said file falls
under the bsnes license.
HQ2x Filter, author: MaxST, license: LGPL
JMA, author: NSRT Team, license: GPL (*)
libco, author: byuu, license: public domain
libui, author: byuu, license: public domain
NTSC Filter, author: blargg, license: LGPL
S-DD1, author: Andreas Naive, license: public domain
zlib, license: zlib license
HQ2x filter, author: MaxST, license: LGPL
JMA decompressor, author: NSRT Team, license: GPL (*)
NTSC filter, author: blargg, license: LGPL
zlib decompressor, license: zlib license
(*) bsnes has received an exemption from the copyright holder to use this work.
The software also includes works which have been released to the public domain,
which are not bound to any licensing agreements. Below is a complete list of all
such software.
libco, author: byuu
libui, author: byuu
OBC-1 emu, author: byuu
S-DD1 emu, author: Andreas Naive
S-RTC emu, author: byuu
Any software listed above as exemptions may be relicensed individually from
bsnes under their respective terms. However, no bsnes licensed portions can be
combined with such a derivative work.
The software also includes the work of other copyright holders, which is
licensed under the terms of the bsnes license, with permission to do so from the
respective authors. Below is a complete list of all such software.
Cx4 emu, authors: anomie, Overload, zsKnight, Nach
DSP-1 emu, authors: Overload, John Weidman, Neviksti, Andreas Naive
DSP-2 emu, author: Overload
DSP-3 emu, authors: John Weidman, Kris Bleakley, Lancer, z80 gaiden
DSP-4 emu, authors: Dreamer Nom, John Weidman, Kris Bleakley, Nach, z80 gaiden
S-DSP emu, author: blargg
ST-010 emu, authors: John Weidman, Matthew Kendora, Overload, Feather

View File

@@ -1,8 +1,8 @@
bsnes
Version 0.022
Version 0.027
Author: byuu
--------
General:
--------
bsnes is a Super Nintendo / Super Famicom emulator that began on
@@ -13,16 +13,22 @@ http://byuu.org/
Please see license.txt for important licensing information.
--------------
Shortcut Keys:
--------------
Esc - Toggle menubar visibility
F11 - Toggle fullscreen mode
------------------
Known Limitations:
------------------
S-CPU
- Invalid DMA / HDMA transfers (eg WRAM<>WRAM) not fully emulated
- Invalid DMA / HDMA transfers not fully emulated
- Multiply / Divide register delays not implemented
S-PPU
- Uses scanline-based renderer. This is very inaccurate, but very few games
rely on mid-scanline writes to function correctly
- Uses scanline-based renderer. This is very inaccurate, but few (if any)
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
@@ -31,10 +37,10 @@ S-PPU
Turning frameskipping off will allow RTO flag calculation on every frame
Hardware Bugs
- CPUr1 HDMA crashing bug not emulated
- CPU<>APU communication bus conflicts not emulated
- S-CPU.r1 HDMA crashing bug not emulated
- S-CPU<>S-SMP communication bus conflicts not emulated
---------------------
Unsupported Hardware:
---------------------
SA-1
@@ -60,26 +66,16 @@ Coprocessor used only by the following games:
- Momotarou Densetsu Happy
- Super Power League 4
DSP-3
Coprocessor used only by SD Gundam GX
ST-011
SETA DSP used only by Quick-move Shogi Match with Nidan Rank-holder Morita
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
ST-018
SETA RISC CPU used only by Quick-move Shogi Match with Nidan Rank-holder Morita 2
Super Gameboy
Cartridge passthrough used for playing Gameboy games
------------------------
Unsupported Controllers:
------------------------
Mouse

View File

@@ -1,274 +1,333 @@
######################
### bsnes makefile ###
######################
ifeq ($(PLATFORM),)
_null_: help
endif
##################################
### platform-specific settings ###
##################################
ifeq ($(PLATFORM),x-gcc-lui)
OS = unix
CC = gcc
CFLAGS = -O3 -fomit-frame-pointer -ffast-math -DPLATFORM_X -DCOMPILER_GCC -DPROCESSOR_X86 -DUI_LUI `pkg-config --cflags gtk+-2.0`
AS = nasm
ASFLAGS = -f elf
LIBS = `pkg-config --libs gtk+-2.0` -lXv -lao
LIBCO = libco_x86
LIBUI = libui_gtk
endif
ifeq ($(PLATFORM),x-gcc-lui-x64)
OS = unix
CC = gcc
CFLAGS = -O3 -fomit-frame-pointer -ffast-math -DPLATFORM_X -DCOMPILER_GCC -DPROCESSOR_X86_64 -DUI_LUI `pkg-config --cflags gtk+-2.0`
AS = yasm
ASFLAGS = -f elf64
LIBS = `pkg-config --libs gtk+-2.0` -lXv -lao
LIBCO = libco_x86_64
LIBUI = libui_gtk
endif
ifeq ($(PLATFORM),win-visualc-lui)
OS = win
CC = cl
CFLAGS = /nologo /wd4996 /O2 /EHsc /DPLATFORM_WIN /DCOMPILER_VISUALC /DPROCESSOR_X86 /DUI_LUI
AS = nasm
ASFLAGS = -f win32 -DWIN32
LIBS = d3d9.lib ddraw.lib dsound.lib dinput8.lib dxguid.lib
LIBCO = libco_x86
LIBUI = libui_win
endif
ifeq ($(PLATFORM),win-visualc-lui-pgi)
OS = win
CC = cl
CFLAGS = /nologo /wd4996 /O2 /GL /EHsc /DPLATFORM_WIN /DCOMPILER_VISUALC /DPROCESSOR_X86 /DUI_LUI
AS = nasm
ASFLAGS = -f win32 -DWIN32
LIBS = d3d9.lib ddraw.lib dsound.lib dinput8.lib dxguid.lib
LINK = /link /PGD:bsnes.pgd /LTCG:PGINSTRUMENT
LIBCO = libco_x86
LIBUI = libui_win
endif
ifeq ($(PLATFORM),win-visualc-lui-pgo)
OS = win
CC = cl
CFLAGS = /nologo /wd4996 /O2 /GL /EHsc /DPLATFORM_WIN /DCOMPILER_VISUALC /DPROCESSOR_X86 /DUI_LUI
AS = nasm
ASFLAGS = -f win32 -DWIN32
LIBS = d3d9.lib ddraw.lib dsound.lib dinput8.lib dxguid.lib
LINK = /link /PGD:bsnes.pgd /LTCG:PGOPTIMIZE
LIBCO = libco_x86
LIBUI = libui_win
endif
#####################################
### compiler / assembler switches ###
#####################################
ifeq ($(CC),gcc)
OUT = -obsnes
CPP = g++
OBJ = o
CARGS = -c $< -o $@
DEFINE = -D
endif
ifeq ($(CC),cl)
OUT = /Febsnes
CPP = cl
OBJ = obj
CARGS = /c $< /Fo$@
DEFINE = /D
endif
ifeq ($(AS),nasm)
ASARGS = $< -o $@
endif
ifeq ($(AS),yasm)
ASARGS = $< -o $@
endif
###################
### OS switches ###
###################
ifeq ($(OS),unix)
RM = rm -f
endif
ifeq ($(OS),win)
OUT := $(OUT).exe
RM = del
LIBS += kernel32.lib user32.lib gdi32.lib shell32.lib winmm.lib comdlg32.lib comctl32.lib
endif
####################################
### main target and dependencies ###
####################################
OBJECTS = main.$(OBJ) $(LIBCO).$(OBJ) $(LIBUI).$(OBJ) \
libstring.$(OBJ) \
reader.$(OBJ) cart.$(OBJ) cheat.$(OBJ) memory.$(OBJ) bmemory.$(OBJ) \
cpu.$(OBJ) scpu.$(OBJ) smp.$(OBJ) ssmp.$(OBJ) bdsp.$(OBJ) ppu.$(OBJ) \
bppu.$(OBJ) snes.$(OBJ) srtc.$(OBJ) sdd1.$(OBJ) c4.$(OBJ) dsp1.$(OBJ) \
dsp2.$(OBJ) obc1.$(OBJ)
ifeq ($(GZIP_SUPPORT),true)
OBJECTS += adler32.$(OBJ) compress.$(OBJ) crc32.$(OBJ) deflate.$(OBJ) \
gzio.$(OBJ) inffast.$(OBJ) inflate.$(OBJ) inftrees.$(OBJ) ioapi.$(OBJ) \
trees.$(OBJ) unzip.$(OBJ) zip.$(OBJ) zutil.$(OBJ)
CFLAGS += $(DEFINE)GZIP_SUPPORT
endif
ifeq ($(JMA_SUPPORT),true)
OBJECTS += jma.$(OBJ) jcrc32.$(OBJ) lzmadec.$(OBJ) 7zlzma.$(OBJ) \
iiostrm.$(OBJ) inbyte.$(OBJ) lzma.$(OBJ) winout.$(OBJ)
CFLAGS += $(DEFINE)JMA_SUPPORT
endif
ifeq ($(OS),win)
ifeq ($(CC),cl)
OBJECTS += bsnes.res
endif
endif
all: $(OBJECTS)
$(CPP) $(OUT) $(CFLAGS) $(OBJECTS) $(LIBS) $(LINK)
# mt -nologo -manifest bsnes.exe.manifest -outputresource:bsnes.exe;1
######################
### implicit rules ###
######################
%.$(OBJ): $<
$(if $(filter %.asm,$<),$(AS) $(ASFLAGS) $(ASARGS))
$(if $(filter %.c,$<),$(CC) $(CFLAGS) $(CARGS))
$(if $(filter %.cpp,$<),$(CPP) $(CFLAGS) $(CARGS))
#########################
### platform-specific ###
#########################
main.$(OBJ): ui/main.cpp config/* ui/* ui/video/* ui/audio/* ui/input/* \
ui/lui/* ui/lui/settings/* \
ui/win/* ui/win/settings/* ui/win/debugger/*
bsnes.res : ui/bsnes.rc ; rc /r /fobsnes.res ui/bsnes.rc
#############
### libco ###
#############
libco_x86.$(OBJ) : lib/libco_x86.asm lib/*
libco_x86_64.$(OBJ): lib/libco_x86_64.asm lib/*
#############
### libui ###
#############
libui_gtk.$(OBJ): lib/libui_gtk.cpp lib/*
libui_win.$(OBJ): lib/libui_win.cpp lib/*
#################
### libraries ###
#################
libstring.$(OBJ): lib/libstring.cpp lib/*
#################
### utilities ###
#################
reader.$(OBJ): reader/reader.cpp reader/*
cart.$(OBJ) : cart/cart.cpp cart/*
cheat.$(OBJ) : cheat/cheat.cpp cheat/*
##############
### memory ###
##############
memory.$(OBJ) : memory/memory.cpp memory/*
bmemory.$(OBJ): memory/bmemory/bmemory.cpp memory/bmemory/* memory/bmemory/mapper/*
###########
### cpu ###
###########
cpu.$(OBJ) : cpu/cpu.cpp cpu/*
scpu.$(OBJ): cpu/scpu/scpu.cpp cpu/scpu/* cpu/scpu/core/* cpu/scpu/dma/* cpu/scpu/memory/* cpu/scpu/mmio/* cpu/scpu/timing/*
###########
### smp ###
###########
smp.$(OBJ) : smp/smp.cpp smp/*
ssmp.$(OBJ): smp/ssmp/ssmp.cpp smp/ssmp/* smp/ssmp/core/* smp/ssmp/memory/* smp/ssmp/timing/*
###########
### dsp ###
###########
adsp.$(OBJ): dsp/adsp/adsp.cpp dsp/adsp/*
bdsp.$(OBJ): dsp/bdsp/bdsp.cpp dsp/bdsp/*
###########
### ppu ###
###########
ppu.$(OBJ) : ppu/ppu.cpp ppu/*
bppu.$(OBJ): ppu/bppu/bppu.cpp ppu/bppu/*
############
### snes ###
############
snes.$(OBJ): snes/snes.cpp snes/* snes/scheduler/* snes/video/* snes/audio/* snes/input/*
#####################
### special chips ###
#####################
srtc.$(OBJ): chip/srtc/srtc.cpp chip/srtc/*
sdd1.$(OBJ): chip/sdd1/sdd1.cpp chip/sdd1/*
c4.$(OBJ) : chip/c4/c4.cpp chip/c4/*
dsp1.$(OBJ): chip/dsp1/dsp1.cpp chip/dsp1/*
dsp2.$(OBJ): chip/dsp2/dsp2.cpp chip/dsp2/*
obc1.$(OBJ): chip/obc1/obc1.cpp chip/obc1/*
############
### zlib ###
############
adler32.$(OBJ) : reader/zlib/adler32.c reader/zlib/*
compress.$(OBJ): reader/zlib/compress.c reader/zlib/*
crc32.$(OBJ) : reader/zlib/crc32.c reader/zlib/*
deflate.$(OBJ) : reader/zlib/deflate.c reader/zlib/*
gzio.$(OBJ) : reader/zlib/gzio.c reader/zlib/*
inffast.$(OBJ) : reader/zlib/inffast.c reader/zlib/*
inflate.$(OBJ) : reader/zlib/inflate.c reader/zlib/*
inftrees.$(OBJ): reader/zlib/inftrees.c reader/zlib/*
ioapi.$(OBJ) : reader/zlib/ioapi.c reader/zlib/*
trees.$(OBJ) : reader/zlib/trees.c reader/zlib/*
unzip.$(OBJ) : reader/zlib/unzip.c reader/zlib/*
zip.$(OBJ) : reader/zlib/zip.c reader/zlib/*
zutil.$(OBJ) : reader/zlib/zutil.c reader/zlib/*
###########
### jma ###
###########
jma.$(OBJ) : reader/jma/jma.cpp reader/jma/*
jcrc32.$(OBJ) : reader/jma/jcrc32.cpp reader/jma/*
lzmadec.$(OBJ): reader/jma/lzmadec.cpp reader/jma/*
7zlzma.$(OBJ) : reader/jma/7zlzma.cpp reader/jma/*
iiostrm.$(OBJ): reader/jma/iiostrm.cpp reader/jma/*
inbyte.$(OBJ) : reader/jma/inbyte.cpp reader/jma/*
lzma.$(OBJ) : reader/jma/lzma.cpp reader/jma/*
winout.$(OBJ) : reader/jma/winout.cpp reader/jma/*
####################
### misc targets ###
####################
clean:
-@$(RM) *.$(OBJ)
-@$(RM) *.res
-@$(RM) *.pgd
-@$(RM) *.pgc
-@$(RM) *.ilk
-@$(RM) *.pdb
-@$(RM) *.manifest
help:
@echo Please specify which platform to compile for with PLATFORM=platform_name
######################
### bsnes makefile ###
######################
ifeq ($(PLATFORM),)
null_: help
endif
##################################
### platform-specific settings ###
##################################
PREFIX = /usr/local
ifeq ($(PLATFORM),x-gcc-x86)
OS = unix
CC = gcc
CFLAGS = -O3 -fomit-frame-pointer -DPLATFORM_X -DCOMPILER_GCC -DPROCESSOR_X86 -DUI_MIU `pkg-config --cflags gtk+-2.0`
AS = yasm
ASFLAGS = -f elf
LIBS = `pkg-config --libs gtk+-2.0` -lXv -lao
LIBCO = libco.x86
MIU = miu.gtk
VAI = video.xv.$(OBJ) video.gtk.$(OBJ) audio.ao.$(OBJ) input.x.$(OBJ)
endif
ifeq ($(PLATFORM),x-gcc-x86-64)
OS = unix
CC = gcc
CFLAGS = -O3 -fomit-frame-pointer -DPLATFORM_X -DCOMPILER_GCC -DPROCESSOR_X86_64 -DUI_MIU `pkg-config --cflags gtk+-2.0`
AS = yasm
ASFLAGS = -f elf64
LIBS = `pkg-config --libs gtk+-2.0` -lXv -lao
LIBCO = libco.x86-64
MIU = miu.gtk
VAI = video.xv.$(OBJ) video.gtk.$(OBJ) audio.ao.$(OBJ) input.x.$(OBJ)
endif
ifeq ($(PLATFORM),win-mingw-x86)
OS = win
CC = mingw32-gcc
CFLAGS = -mwindows -O3 -fomit-frame-pointer -DPLATFORM_WIN -DCOMPILER_GCC -DPROCESSOR_X86 -DUI_MIU
AS = nasm
ASFLAGS = -f win32 -DWIN
LIBS = -ld3d9 -lddraw -ldsound -ldinput8 -ldxguid -luuid -lkernel32 -luser32 -lgdi32 -lshell32 -lwinmm -lcomdlg32 -lcomctl32
LIBCO = libco.x86
MIU = miu.win
VAI = video.direct3d.$(OBJ) video.directdraw.$(OBJ) video.gdi.$(OBJ) audio.directsound.$(OBJ) input.directinput.$(OBJ)
endif
ifeq ($(PLATFORM),win-visualc-x86)
OS = win
CC = cl
CFLAGS = /nologo /wd4996 /O2 /EHsc /DPLATFORM_WIN /DCOMPILER_VISUALC /DPROCESSOR_X86 /DUI_MIU
AS = nasm
ASFLAGS = -f win32 -DWIN
LIBS = d3d9.lib ddraw.lib dsound.lib dinput8.lib dxguid.lib kernel32.lib user32.lib gdi32.lib shell32.lib winmm.lib comdlg32.lib comctl32.lib
LIBCO = libco.x86
MIU = miu.win
VAI = video.direct3d.$(OBJ) video.directdraw.$(OBJ) video.gdi.$(OBJ) audio.directsound.$(OBJ) input.directinput.$(OBJ)
endif
#####################################
### compiler / assembler switches ###
#####################################
ifeq ($(CC),gcc)
OUT = -obsnes
CPP = g++
OBJ = o
CARGS = -c $< -o $@
DEFINE = -D
endif
ifeq ($(CC),mingw32-gcc)
OUT = -obsnes
CPP = mingw32-g++
OBJ = o
CARGS = -c $< -o $@
DEFINE = -D
endif
ifeq ($(CC),cl)
OUT = /Febsnes
CPP = cl
OBJ = obj
CARGS = /c $< /Fo$@
DEFINE = /D
endif
ifeq ($(AS),nasm)
ASARGS = $< -o $@
endif
ifeq ($(AS),yasm)
ASARGS = $< -o $@
endif
###################
### OS switches ###
###################
ifeq ($(OS),unix)
RM = rm -f
endif
ifeq ($(OS),win)
OUT := $(OUT).exe
RM = del
endif
####################################
### main target and dependencies ###
####################################
OBJECTS = main.$(OBJ) $(LIBCO).$(OBJ) $(MIU).$(OBJ) $(VAI) bstring.$(OBJ) \
reader.$(OBJ) cart.$(OBJ) cheat.$(OBJ) memory.$(OBJ) smemory.$(OBJ) \
cpu.$(OBJ) scpu.$(OBJ) smp.$(OBJ) ssmp.$(OBJ) bdsp.$(OBJ) ppu.$(OBJ) \
bppu.$(OBJ) snes.$(OBJ) bsx.$(OBJ) superfx.$(OBJ) srtc.$(OBJ) \
sdd1.$(OBJ) cx4.$(OBJ) dsp1.$(OBJ) dsp2.$(OBJ) dsp3.$(OBJ) dsp4.$(OBJ) \
obc1.$(OBJ) st010.$(OBJ)
ifeq ($(GZIP_SUPPORT),true)
OBJECTS += adler32.$(OBJ) compress.$(OBJ) crc32.$(OBJ) deflate.$(OBJ) \
gzio.$(OBJ) inffast.$(OBJ) inflate.$(OBJ) inftrees.$(OBJ) ioapi.$(OBJ) \
trees.$(OBJ) unzip.$(OBJ) zip.$(OBJ) zutil.$(OBJ)
CFLAGS += $(DEFINE)GZIP_SUPPORT
endif
ifeq ($(JMA_SUPPORT),true)
OBJECTS += jma.$(OBJ) jcrc32.$(OBJ) lzmadec.$(OBJ) 7zlzma.$(OBJ) \
iiostrm.$(OBJ) inbyte.$(OBJ) lzma.$(OBJ) winout.$(OBJ)
CFLAGS += $(DEFINE)JMA_SUPPORT
endif
ifeq ($(OS),win)
ifeq ($(CC),cl)
OBJECTS += bsnes.res
endif
ifeq ($(CC),mingw32-gcc)
OBJECTS += bsnesrc.o
endif
endif
all: $(OBJECTS)
$(CPP) $(OUT) $(CFLAGS) $(OBJECTS) $(LIBS) $(LINK)
######################
### implicit rules ###
######################
%.$(OBJ): $<
$(if $(filter %.asm,$<),$(AS) $(ASFLAGS) $(ASARGS))
$(if $(filter %.s,$<),$(AS) $(ASFLAGS) $(ASARGS))
$(if $(filter %.c,$<),$(CC) $(CFLAGS) $(CARGS))
$(if $(filter %.cpp,$<),$(CPP) $(CFLAGS) $(CARGS))
############
### main ###
############
main.$(OBJ): ui/main.cpp config/* \
ui/* ui/vai/* \
ui/miu/* ui/miu/loader/* ui/miu/settings/*
bsnes.res: ui/bsnes.rc ; rc /r /fobsnes.res ui/bsnes.rc
bsnesrc.o: ui/bsnes.rc ; windres -I data ui/bsnes.rc bsnesrc.o
##########
### ui ###
##########
video.direct3d.$(OBJ) : ui/vai/video/video.direct3d.cpp ui/vai/video/*
video.directdraw.$(OBJ) : ui/vai/video/video.directdraw.cpp ui/vai/video/*
video.gdi.$(OBJ) : ui/vai/video/video.gdi.cpp ui/vai/video/*
video.gtk.$(OBJ) : ui/vai/video/video.gtk.cpp ui/vai/video/*
video.xv.$(OBJ) : ui/vai/video/video.xv.cpp ui/vai/video/*
audio.ao.$(OBJ) : ui/vai/audio/audio.ao.cpp ui/vai/audio/*
audio.directsound.$(OBJ): ui/vai/audio/audio.directsound.cpp ui/vai/audio/*
input.directinput.$(OBJ): ui/vai/input/input.directinput.cpp ui/vai/input/*
input.x.$(OBJ) : ui/vai/input/input.x.cpp ui/vai/input/*
#############
### libco ###
#############
libco.x86.$(OBJ) : lib/libco/libco.x86.asm lib/libco/*
libco.x86-64.$(OBJ): lib/libco/libco.x86-64.asm lib/libco/*
libco.pcc.$(OBJ) : lib/libco/libco.ppc.s lib/libco/*
libco.ppc64.$(OBJ) : lib/libco/libco.ppc64.s lib/libco/*
###########
### miu ###
###########
miu.gtk.$(OBJ): lib/miu.gtk/miu.gtk.cpp lib/miu.gtk/*
miu.win.$(OBJ): lib/miu.win/miu.win.cpp lib/miu.win/*
#################
### libraries ###
#################
bstring.$(OBJ): lib/bstring.cpp lib/*
#################
### utilities ###
#################
reader.$(OBJ): reader/reader.cpp reader/*
cart.$(OBJ) : cart/cart.cpp cart/*
cheat.$(OBJ) : cheat/cheat.cpp cheat/*
##############
### memory ###
##############
memory.$(OBJ) : memory/memory.cpp memory/*
bmemory.$(OBJ): memory/bmemory/bmemory.cpp memory/bmemory/* memory/bmemory/mapper/*
smemory.$(OBJ): memory/smemory/smemory.cpp memory/smemory/* memory/smemory/mapper/*
###########
### cpu ###
###########
cpu.$(OBJ) : cpu/cpu.cpp cpu/*
scpu.$(OBJ): cpu/scpu/scpu.cpp cpu/scpu/* cpu/scpu/core/* cpu/scpu/dma/* cpu/scpu/memory/* cpu/scpu/mmio/* cpu/scpu/timing/*
###########
### smp ###
###########
smp.$(OBJ) : smp/smp.cpp smp/*
ssmp.$(OBJ): smp/ssmp/ssmp.cpp smp/ssmp/* smp/ssmp/core/* smp/ssmp/memory/* smp/ssmp/timing/*
###########
### dsp ###
###########
adsp.$(OBJ): dsp/adsp/adsp.cpp dsp/adsp/*
bdsp.$(OBJ): dsp/bdsp/bdsp.cpp dsp/bdsp/*
###########
### ppu ###
###########
ppu.$(OBJ) : ppu/ppu.cpp ppu/*
bppu.$(OBJ): ppu/bppu/bppu.cpp ppu/bppu/*
############
### snes ###
############
snes.$(OBJ): snes/snes.cpp snes/* snes/scheduler/* snes/video/* snes/audio/* snes/input/*
#####################
### special chips ###
#####################
bsx.$(OBJ) : chip/bsx/bsx.cpp chip/bsx/*
superfx.$(OBJ): chip/superfx/superfx.cpp chip/superfx/* chip/superfx/core/* chip/superfx/memory/*
srtc.$(OBJ) : chip/srtc/srtc.cpp chip/srtc/*
sdd1.$(OBJ) : chip/sdd1/sdd1.cpp chip/sdd1/*
cx4.$(OBJ) : chip/cx4/cx4.cpp chip/cx4/*
dsp1.$(OBJ) : chip/dsp1/dsp1.cpp chip/dsp1/*
dsp2.$(OBJ) : chip/dsp2/dsp2.cpp chip/dsp2/*
dsp3.$(OBJ) : chip/dsp3/dsp3.cpp chip/dsp3/*
dsp4.$(OBJ) : chip/dsp4/dsp4.cpp chip/dsp4/*
obc1.$(OBJ) : chip/obc1/obc1.cpp chip/obc1/*
st010.$(OBJ) : chip/st010/st010.cpp chip/st010/*
############
### zlib ###
############
adler32.$(OBJ) : reader/zlib/adler32.c reader/zlib/*
compress.$(OBJ): reader/zlib/compress.c reader/zlib/*
crc32.$(OBJ) : reader/zlib/crc32.c reader/zlib/*
deflate.$(OBJ) : reader/zlib/deflate.c reader/zlib/*
gzio.$(OBJ) : reader/zlib/gzio.c reader/zlib/*
inffast.$(OBJ) : reader/zlib/inffast.c reader/zlib/*
inflate.$(OBJ) : reader/zlib/inflate.c reader/zlib/*
inftrees.$(OBJ): reader/zlib/inftrees.c reader/zlib/*
ioapi.$(OBJ) : reader/zlib/ioapi.c reader/zlib/*
trees.$(OBJ) : reader/zlib/trees.c reader/zlib/*
unzip.$(OBJ) : reader/zlib/unzip.c reader/zlib/*
zip.$(OBJ) : reader/zlib/zip.c reader/zlib/*
zutil.$(OBJ) : reader/zlib/zutil.c reader/zlib/*
###########
### jma ###
###########
jma.$(OBJ) : reader/jma/jma.cpp reader/jma/*
jcrc32.$(OBJ) : reader/jma/jcrc32.cpp reader/jma/*
lzmadec.$(OBJ): reader/jma/lzmadec.cpp reader/jma/*
7zlzma.$(OBJ) : reader/jma/7zlzma.cpp reader/jma/*
iiostrm.$(OBJ): reader/jma/iiostrm.cpp reader/jma/*
inbyte.$(OBJ) : reader/jma/inbyte.cpp reader/jma/*
lzma.$(OBJ) : reader/jma/lzma.cpp reader/jma/*
winout.$(OBJ) : reader/jma/winout.cpp reader/jma/*
####################
### misc targets ###
####################
install:
install -m 775 bsnes $(PREFIX)/bin/bsnes
install -m 775 data/bsnes.png $(PREFIX)/share/icons/bsnes.png
clean:
-@$(RM) *.$(OBJ)
-@$(RM) *.res
-@$(RM) *.pgd
-@$(RM) *.pgc
-@$(RM) *.ilk
-@$(RM) *.pdb
-@$(RM) *.manifest
help:
@echo "Usage: $(MAKE) PLATFORM=platform [options]"
@echo ""
@echo "Available platform targets:"
@echo " x-gcc-x86 - Linux / BSD (x86) (requires yasm)"
@echo " x-gcc-x86-64 - Linux / BSD (x86-64) (requires yasm)"
@echo " win-mingw-x86 - Windows (x86) (requires nasm)"
@echo " win-visualc-x86 - Windows (x86) (requires nasm)"
@echo ""
@echo "Available options:"
@echo " GZIP_SUPPORT=[true|false] - Enable ZIP / GZ support (default=false)"
@echo " JMA_SUPPORT=[true|false] - Enable JMA support (default=false)"
@echo ""
@echo "Example: $(MAKE) PLATFORM=x-gcc-lui GZIP_SUPPORT=true"
@echo ""

View File

@@ -1,58 +1,54 @@
#define BSNES_VERSION "0.022"
#define BSNES_TITLE "bsnes v" BSNES_VERSION
#define MEMCORE bMemBus
#define CPUCORE sCPU
#define SMPCORE sSMP
#define DSPCORE bDSP
#define PPUCORE bPPU
//#define FAVOR_ACCURACY
#define FAVOR_SPEED
//game genie + pro action replay code support (~1-3% speed hit)
#define CHEAT_SYSTEM
//snes core polymorphism
//(allow runtime cpu/smp/dsp/ppu/bus selection, ~10% speed hit)
//#define POLYMORPHISM
#include "lib/libbase.h"
#if defined(PROCESSOR_X86)
#define ARCH_LSB
#include "lib/libco_x86.h"
#elif defined(PROCESSOR_X86_64)
#define ARCH_LSB
#include "lib/libco_x86_64.h"
#elif defined(PROCESSOR_G5)
#define ARCH_MSB
#else
#error "unsupported processor"
#endif
#include "lib/libsort.h"
#include "lib/libarray.h"
#include "lib/libvector.h"
#include "lib/libstring.h"
#include "lib/libconfig.h"
//platform-specific global functions
void alert(char*, ...);
void dprintf(char*, ...);
void dprintf(uint, char*, ...);
namespace source {
enum {
none = 0,
debug,
cpu,
ppu,
smp,
dsp,
bus,
};
};
//various class interfaces
#include "interface.h"
#define BSNES_VERSION "0.027"
#define BSNES_TITLE "bsnes v" BSNES_VERSION
#define BUSCORE sBus
#define CPUCORE sCPU
#define SMPCORE sSMP
#define DSPCORE bDSP
#define PPUCORE bPPU
//FAVOR_ACCURACY calculates RTO during frameskip, whereas FAVOR_SPEED does not
//frameskip offers near-zero speedup if RTO is calculated
//accuracy is not affected by this define when frameskipping is off
//#define FAVOR_ACCURACY
#define FAVOR_SPEED
//game genie + pro action replay code support (~1-3% speed hit)
#define CHEAT_SYSTEM
#if defined(PROCESSOR_X86) || defined(PROCESSOR_X86_64)
#define ARCH_LSB
#elif defined(PROCESSOR_PPC) || defined(PROCESSOR_PPC64)
#define ARCH_MSB
#else //guess
#define ARCH_LSB
#endif
#include "lib/libco.h"
#include "lib/bbase.h"
#include "lib/bfunction.h"
#include "lib/barray.h"
#include "lib/bvector.h"
#include "lib/bkeymap.h"
#include "lib/bstring.h"
#include "lib/bconfig.h"
//platform-specific global functions
void alert(const char*, ...);
void dprintf(const char*, ...);
void dprintf(uint, const char*, ...);
namespace source {
enum {
none = 0,
debug,
cpu,
ppu,
smp,
dsp,
bus,
};
};
#include "interface.h"

View File

@@ -1,156 +1,135 @@
#include "../base.h"
#include "database.cpp"
#include "cart_normal.cpp"
#include "cart_bsx.cpp"
#include "cart_bsc.cpp"
#include "cart_st.cpp"
#include "cart_stdual.cpp"
#include "cart_file.cpp"
#include "cart_header.cpp"
namespace memory {
MappedRAM cartrom, cartram;
MappedRAM bscram;
MappedRAM stArom, stAram;
MappedRAM stBrom, stBram;
};
Cartridge cartridge;
void Cartridge::load_begin(uint cart_type) {
if(loaded() == true)return;
Cartridge::MemoryMapper Cartridge::mapper() { return info.mapper; }
Cartridge::Region Cartridge::region() { return info.region; }
bool Cartridge::loaded() { return cart.loaded; }
void Cartridge::load_begin(CartridgeType cart_type) {
cart.rom = cart.ram = 0;
bs.ram = 0;
stA.rom = stA.ram = 0;
stB.rom = stB.ram = 0;
cart.rom_size = cart.ram_size = 0;
bs.ram_size = 0;
stA.rom_size = stA.ram_size = 0;
stB.rom_size = stB.ram_size = 0;
info.type = cart_type;
info.srtc = false;
info.sdd1 = false;
info.c4 = false;
info.dsp1 = false;
info.dsp2 = false;
info.obc1 = false;
info.bsxbase = false;
info.bsxcart = false;
info.bsxflash = false;
info.st = false;
info.dsp1_mapper = 0;
info.superfx = false;
info.sa1 = false;
info.srtc = false;
info.sdd1 = false;
info.cx4 = false;
info.dsp1 = false;
info.dsp2 = false;
info.dsp3 = false;
info.dsp4 = false;
info.obc1 = false;
info.st010 = false;
info.st011 = false;
info.st018 = false;
info.dsp1_mapper = DSP1Unmapped;
info.header_index = 0xffc0;
info.mapper = PCB;
strcpy(info.name, "");
strcpy(info.pcb, "");
info.mapper = LoROM;
info.name[0] = 0;
info.region = NTSC;
info.cart_mmio = false;
info.rom_size = 0;
info.ram_size = 0;
file.count = 0;
for(int i = 0; i < 8; i++) {
strcpy(file.rom_name[i], "");
strcpy(file.ram_name[i], "");
file.rom_size[i] = 0;
file.ram_size[i] = 0;
file.rom_data[i] = 0;
file.ram_data[i] = 0;
}
}
void Cartridge::load(const char *rom_fn) {
if(!rom_fn || !*rom_fn)return;
void Cartridge::load_end() {
memory::cartrom.map(cart.rom, cart.rom_size);
memory::cartram.map(cart.ram, cart.ram_size);
memory::bscram.map(bs.ram, bs.ram_size);
memory::stArom.map(stA.rom, stA.rom_size);
memory::stAram.map(stA.ram, stA.ram_size);
memory::stBrom.map(stB.rom, stB.rom_size);
memory::stBram.map(stB.ram, stB.ram_size);
char fn[4096], ram_fn[4096];
strcpy(fn, rom_fn);
//correct folder slashes
for(int i = strlen(fn) - 1; i >= 0; i--) {
if(fn[i] == '\\')fn[i] = '/';
}
memory::cartrom.write_protect(true);
memory::cartram.write_protect(false);
memory::bscram.write_protect(true);
memory::stArom.write_protect(true);
memory::stAram.write_protect(false);
memory::stBrom.write_protect(true);
memory::stBram.write_protect(false);
uint i = file.count++;
strcpy(file.rom_name[i], fn);
strcpy(fn, rom_fn);
//remove ROM extension
for(int i = strlen(fn) - 1; i >= 0; i--) {
if(fn[i] == '.') {
fn[i] = 0;
break;
}
}
if(i == 0) {
strcpy(file.patch_name, fn);
strcat(file.patch_name, ".ups");
}
strcpy(fn, strptr(config::file_updatepath(fn, config::path.save)));
if(i == 0) {
strcpy(file.cheat_name, fn);
strcat(file.cheat_name, ".cht");
}
strcpy(file.ram_name[i], fn);
strcat(file.ram_name[i], ".");
strcat(file.ram_name[i], config::path.save_ext);
}
bool Cartridge::load_end() {
for(int i = 0; i < file.count; i++) {
load_file(file.rom_name[i], file.rom_data[i], file.rom_size[i]);
}
if(fexists(file.cheat_name) == true) {
char fn[PATH_MAX];
strcpy(fn, cart.fn);
modify_extension(fn, "cht");
if(fexists(fn)) {
cheat.clear();
cheat.load(file.cheat_name);
cheat.load(fn);
}
switch(info.type) {
case CART_NORMAL: {
load_rom_normal();
load_ram_normal();
} break;
case CART_ST: {
load_rom_st();
load_ram_st();
} break;
case CART_STDUAL: {
load_rom_stdual();
load_ram_stdual();
} break;
}
cart_loaded = true;
r_mem->load_cart();
return true;
cart.loaded = true;
bus.load_cart();
}
bool Cartridge::unload() {
if(cart_loaded == false)return false;
if(cart.loaded == false) return false;
r_mem->unload_cart();
bus.unload_cart();
switch(info.type) {
case CART_NORMAL: {
save_ram_normal();
} break;
case CART_ST: {
save_ram_st();
} break;
case CART_STDUAL: {
save_ram_stdual();
} break;
case CartridgeNormal: unload_cart_normal(); break;
case CartridgeBSX: unload_cart_bsx(); break;
case CartridgeBSC: unload_cart_bsc(); break;
case CartridgeSufamiTurbo: unload_cart_st(); break;
}
safe_free(rom);
safe_free(ram);
safe_free(cart.rom);
safe_free(cart.ram);
safe_free(bs.ram);
safe_free(stA.rom);
safe_free(stA.ram);
safe_free(stB.rom);
safe_free(stB.ram);
if(cheat.count() > 0 || fexists(file.cheat_name) == true) {
cheat.save(file.cheat_name);
char fn[PATH_MAX];
strcpy(fn, cart.fn);
modify_extension(fn, "cht");
if(cheat.count() > 0 || fexists(fn)) {
cheat.save(fn);
cheat.clear();
}
cart_loaded = false;
cart.loaded = false;
return true;
}
Cartridge::Cartridge() {
load_database();
cart_loaded = false;
rom = 0;
ram = 0;
cart.loaded = false;
}
Cartridge::~Cartridge() {
if(cart_loaded == true) {
unload();
}
if(cart.loaded == true) unload();
}

View File

@@ -1,125 +1,142 @@
class Cartridge {
public:
enum CartridgeType {
CartridgeNormal,
CartridgeBSX,
CartridgeBSC,
CartridgeSufamiTurbo,
};
/*****
* cart database
*****/
enum HeaderField {
CART_NAME = 0x00,
MAPPER = 0x15,
ROM_TYPE = 0x16,
ROM_SIZE = 0x17,
RAM_SIZE = 0x18,
REGION = 0x19,
COMPANY = 0x1a,
VERSION = 0x1b,
ICKSUM = 0x1c,
CKSUM = 0x1e,
RESL = 0x3c,
RESH = 0x3d,
};
#include "db/db.h"
db_item dbi;
uint8 *database;
uint database_size;
uint database_blocksize;
void load_database();
bool read_database();
enum Region {
NTSC,
PAL,
};
//
enum MemoryMapper {
LoROM,
HiROM,
ExLoROM,
ExHiROM,
BSXROM,
BSCLoROM,
BSCHiROM,
STROM,
};
enum {
CART_NORMAL,
CART_ST,
CART_STDUAL,
};
enum DSP1MemoryMapper {
DSP1Unmapped,
DSP1LoROM1MB,
DSP1LoROM2MB,
DSP1HiROM,
};
bool cart_loaded;
struct {
bool loaded;
char fn[PATH_MAX];
uint8 *rom, *ram;
uint rom_size, ram_size;
} cart;
uint8 rom_header[512], *rom, *ram;
struct {
char fn[PATH_MAX];
uint8 *ram;
uint ram_size;
} bs;
enum {
//header fields
CART_NAME = 0x00,
MAPPER = 0x15,
ROM_TYPE = 0x16,
ROM_SIZE = 0x17,
RAM_SIZE = 0x18,
REGION = 0x19,
LICENSE = 0x1a,
VERSION = 0x1b,
ICKSUM = 0x1c,
CKSUM = 0x1e,
RESL = 0x3c,
RESH = 0x3d,
struct {
char fn[PATH_MAX];
uint8 *rom, *ram;
uint rom_size, ram_size;
} stA, stB;
//regions
NTSC = 0,
PAL = 1,
struct {
CartridgeType type;
//memory mappers
PCB = 0x00,
LOROM = 0x20,
HIROM = 0x21,
EXLOROM = 0x22,
EXHIROM = 0x25,
uint32 crc32;
char name[128];
//special chip memory mappers
DSP1_LOROM_1MB = 1,
DSP1_LOROM_2MB = 2,
DSP1_HIROM = 3,
};
Region region;
MemoryMapper mapper;
uint rom_size;
uint ram_size;
struct {
uint count;
char cheat_name[4096], patch_name[4096];
char rom_name[8][4096], ram_name[8][4096];
uint rom_size[8], ram_size[8];
uint8 *rom_data[8], *ram_data[8];
} file;
bool bsxbase;
bool bsxcart;
bool bsxflash;
bool st;
bool superfx;
bool sa1;
bool srtc;
bool sdd1;
bool cx4;
bool dsp1;
bool dsp2;
bool dsp3;
bool dsp4;
bool obc1;
bool st010;
bool st011;
bool st018;
struct {
uint type;
DSP1MemoryMapper dsp1_mapper;
//cart information
uint32 crc32;
char name[128];
char pcb[32];
uint header_index;
} info;
uint region;
uint mapper;
uint rom_size;
uint ram_size;
MemoryMapper mapper();
Region region();
//set to true for games that need cart MMIO mapping (c4, dsp-n, ...),
//for games that map outside the standard MMIO range of $2000-$5fff
bool cart_mmio;
bool srtc;
bool sdd1;
bool c4;
bool dsp1;
bool dsp2;
bool obc1;
void load_cart_normal(const char*);
void load_cart_bsx(const char*, const char*);
void load_cart_bsc(const char*, const char*);
void load_cart_st(const char*, const char*, const char*);
uint dsp1_mapper;
void unload_cart_normal();
void unload_cart_bsx();
void unload_cart_bsc();
void unload_cart_st();
//HiROM / LoROM specific code
uint header_index;
} info;
bool load_file(const char *fn, uint8 *&data, uint &size);
bool save_file(const char *fn, uint8 *data, uint size);
void load_rom_normal();
void load_ram_normal();
void save_ram_normal();
void load_rom_st();
void load_ram_st();
void save_ram_st();
void load_rom_stdual();
void load_ram_stdual();
void save_ram_stdual();
bool loaded();
void load_begin(CartridgeType);
void load_end();
bool unload();
void find_header();
void read_header();
void read_extended_header();
bool loaded() { return cart_loaded; }
void load_begin(uint cart_type);
void load(const char *rom_fn);
bool load_end();
bool unload();
bool load_file(const char *fn, uint8 *&data, uint &size);
bool save_file(const char *fn, uint8 *data, uint size);
char* modify_extension(char *filename, const char *extension);
char* get_save_filename(const char *source, const char *extension);
Cartridge();
~Cartridge();
private:
char savefn[PATH_MAX];
};
namespace memory {
extern MappedRAM cartrom, cartram;
extern MappedRAM bscram;
extern MappedRAM stArom, stAram;
extern MappedRAM stBrom, stBram;
};
extern Cartridge cartridge;

41
src/cart/cart_bsc.cpp Normal file
View File

@@ -0,0 +1,41 @@
void Cartridge::load_cart_bsc(const char *base, const char *slot) {
if(!base || !*base) return;
strcpy(cart.fn, base);
strcpy(bs.fn, slot ? slot : "");
load_begin(CartridgeBSC);
uint8 *data;
uint size;
load_file(cart.fn, data, size);
cart.rom = data, cart.rom_size = size;
if(*bs.fn) {
if(load_file(bs.fn, data, size) == true) {
info.bsxflash = true;
bs.ram = data, bs.ram_size = size;
}
}
find_header();
read_header();
info.mapper = cartridge.info.header_index == 0x7fc0 ? BSCLoROM : BSCHiROM;
info.region = NTSC;
if(info.ram_size > 0) {
cart.ram = (uint8*)malloc(cart.ram_size = info.ram_size);
memset(cart.ram, 0xff, cart.ram_size);
if(load_file(get_save_filename(cart.fn, "srm"), data, size) == true) {
memcpy(cart.ram, data, min(size, cart.ram_size));
safe_free(data);
}
}
load_end();
}
void Cartridge::unload_cart_bsc() {
if(cart.ram) save_file(get_save_filename(cart.fn, "srm"), cart.ram, cart.ram_size);
}

45
src/cart/cart_bsx.cpp Normal file
View File

@@ -0,0 +1,45 @@
void Cartridge::load_cart_bsx(const char *base, const char *slot) {
if(!base || !*base) return;
strcpy(cart.fn, base);
strcpy(bs.fn, slot ? slot : "");
load_begin(CartridgeBSX);
info.bsxbase = true;
info.bsxcart = true;
info.mapper = BSXROM;
info.region = NTSC;
uint8 *data;
uint size;
load_file(cart.fn, data, size);
cart.rom = data, cart.rom_size = size;
cart.ram = 0, cart.ram_size = 0;
memset(bsxcart.sram.handle (), 0x00, bsxcart.sram.size ());
memset(bsxcart.psram.handle(), 0x00, bsxcart.psram.size());
if(load_file(get_save_filename(cart.fn, "srm"), data, size) == true) {
memcpy(bsxcart.sram.handle (), data, min(bsxcart.sram.size (), size));
safe_free(data);
}
if(load_file(get_save_filename(cart.fn, "psr"), data, size) == true) {
memcpy(bsxcart.psram.handle(), data, min(bsxcart.psram.size(), size));
safe_free(data);
}
if(*bs.fn) {
if(load_file(bs.fn, data, size) == true) {
info.bsxflash = true;
bs.ram = data, bs.ram_size = size;
}
}
load_end();
}
void Cartridge::unload_cart_bsx() {
save_file(get_save_filename(cart.fn, "srm"), bsxcart.sram.handle (), bsxcart.sram.size ());
save_file(get_save_filename(cart.fn, "psr"), bsxcart.psram.handle(), bsxcart.psram.size());
}

View File

@@ -9,56 +9,91 @@
#include "../reader/jmareader.h"
#endif
char* Cartridge::modify_extension(char *filename, const char *extension) {
int i;
for(i = strlen(filename); i >= 0; i--) {
if(filename[i] == '.') break;
if(filename[i] == '/') break;
if(filename[i] == '\\') break;
}
if(i > 0 && filename[i] == '.') filename[i] = 0;
strcat(filename, ".");
strcat(filename, extension);
return filename;
}
char* Cartridge::get_save_filename(const char *source, const char *extension) {
strcpy(savefn, source);
for(char *p = savefn; *p; p++) { if(*p == '\\') *p = '/'; }
modify_extension(savefn, extension);
//override path with user-specified folder, if one was defined
if(config::path.save != "") {
lstring part;
split(part, "/", savefn);
string fn = config::path.save();
if(strend(fn, "/") == false) strcat(fn, "/");
strcat(fn, part[count(part) - 1]);
strcpy(savefn, fn);
//resolve relative path, if found
if(strbegin(fn, "./") == true) {
ltrim(fn, "./");
strcpy(savefn, config::path.base);
strcat(savefn, fn);
}
}
return savefn;
}
bool Cartridge::load_file(const char *fn, uint8 *&data, uint &size) {
dprintf("* Loading \"%s\"...", fn);
if(fexists(fn) == false) {
return false;
}
if(fexists(fn) == false) return false;
switch(Reader::detect(fn)) {
default:
case Reader::RF_NORMAL: {
FileReader ff(fn);
if(!ff.ready()) {
alert("Error loading image file (%s)!", fn);
return false;
}
size = ff.size();
data = ff.read();
} break;
case Reader::RF_NORMAL: {
FileReader ff(fn);
if(!ff.ready()) {
alert("Error loading image file (%s)!", fn);
return false;
}
size = ff.size();
data = ff.read();
} break;
#ifdef GZIP_SUPPORT
case Reader::RF_GZ: {
GZReader gf(fn);
if(!gf.ready()) {
alert("Error loading image file (%s)!", fn);
return false;
}
size = gf.size();
data = gf.read();
} break;
#ifdef GZIP_SUPPORT
case Reader::RF_GZ: {
GZReader gf(fn);
if(!gf.ready()) {
alert("Error loading image file (%s)!", fn);
return false;
}
size = gf.size();
data = gf.read();
} break;
case Reader::RF_ZIP: {
ZipReader zf(fn);
size = zf.size();
data = zf.read();
} break;
#endif
#ifdef JMA_SUPPORT
case Reader::RF_JMA: {
try {
JMAReader jf(fn);
size = jf.size();
data = jf.read();
} catch(JMA::jma_errors jma_error) {
alert("Error loading image file (%s)!", fn);
return false;
}
} break;
#endif
case Reader::RF_ZIP: {
ZipReader zf(fn);
size = zf.size();
data = zf.read();
} break;
#endif
#ifdef JMA_SUPPORT
case Reader::RF_JMA: {
try {
JMAReader jf(fn);
size = jf.size();
data = jf.read();
} catch(JMA::jma_errors jma_error) {
alert("Error loading image file (%s)!", fn);
return false;
}
} break;
#endif
}
return true;

View File

@@ -1,32 +1,46 @@
void Cartridge::read_header() {
info.srtc = false;
info.sdd1 = false;
info.c4 = false;
info.dsp1 = false;
info.dsp2 = false;
info.obc1 = false;
uint8 *rom = cart.rom;
uint index = info.header_index;
uint8 mapper = rom[index + MAPPER];
uint8 rom_type = rom[index + ROM_TYPE];
uint8 company = rom[index + COMPANY];
uint8 region = rom[index + REGION] & 0x7f;
info.dsp1_mapper = 0;
if(info.header_index == 0x7fc0 && info.rom_size >= 0x401000) {
info.mapper = EXLOROM;
strcpy(info.pcb, "UNL-EXLOROM");
} else if(info.header_index == 0x7fc0 && rom[info.header_index + MAPPER] == 0x32) {
info.mapper = EXLOROM;
strcpy(info.pcb, "UNL-EXLOROM");
} else if(info.header_index == 0x7fc0) {
info.mapper = LOROM;
strcpy(info.pcb, "UNL-LOROM");
} else if(info.header_index == 0xffc0) {
info.mapper = HIROM;
strcpy(info.pcb, "UNL-HIROM");
} else { //info.header_index == 0x40ffc0
info.mapper = EXHIROM;
strcpy(info.pcb, "UNL-EXHIROM");
//detect presence of BS-X flash cartridge connector (reads extended header information)
bool has_bsxflash = false;
if(rom[index - 14] == 'Z') {
if(rom[index - 11] == 'J') {
uint8 n13 = rom[index - 13];
if((n13 >= 'A' && n13 <= 'Z') || (n13 >= '0' && n13 <= '9')) {
if(company == 0x33 || (rom[index - 10] == 0x00 && rom[index - 4] == 0x00)) {
has_bsxflash = true;
}
}
}
}
if(has_bsxflash == true) {
info.mapper = index == 0x7fc0 ? BSCLoROM : BSCHiROM;
} else if(index == 0x7fc0 && cart.rom_size >= 0x401000) {
info.mapper = ExLoROM;
} else if(index == 0x7fc0 && mapper == 0x32) {
info.mapper = ExLoROM;
} else if(index == 0x7fc0) {
info.mapper = LoROM;
} else if(index == 0xffc0) {
info.mapper = HiROM;
} else { //index == 0x40ffc0
info.mapper = ExHiROM;
}
if(mapper == 0x20 && (rom_type == 0x13 || rom_type == 0x14 || rom_type == 0x15 || rom_type == 0x1a)) {
info.superfx = true;
}
if(mapper == 0x23 && (rom_type == 0x34 || rom_type == 0x35)) {
info.sa1 = true;
}
uint8 mapper = rom[info.header_index + MAPPER];
uint8 rom_type = rom[info.header_index + ROM_TYPE];
if(mapper == 0x35 && rom_type == 0x55) {
info.srtc = true;
}
@@ -36,14 +50,14 @@ uint8 rom_type = rom[info.header_index + ROM_TYPE];
}
if(mapper == 0x20 && rom_type == 0xf3) {
info.c4 = true;
info.cx4 = true;
}
if((mapper == 0x20 || mapper == 0x21) && rom_type == 0x03) {
info.dsp1 = true;
}
if(mapper == 0x30 && rom_type == 0x05) {
if(mapper == 0x30 && rom_type == 0x05 && company != 0xb2) {
info.dsp1 = true;
}
@@ -52,12 +66,12 @@ uint8 rom_type = rom[info.header_index + ROM_TYPE];
}
if(info.dsp1 == true) {
if((mapper & 0x2f) == 0x20 && info.rom_size <= 0x100000) {
info.dsp1_mapper = DSP1_LOROM_1MB;
if((mapper & 0x2f) == 0x20 && cart.rom_size <= 0x100000) {
info.dsp1_mapper = DSP1LoROM1MB;
} else if((mapper & 0x2f) == 0x20) {
info.dsp1_mapper = DSP1_LOROM_2MB;
info.dsp1_mapper = DSP1LoROM2MB;
} else if((mapper & 0x2f) == 0x21) {
info.dsp1_mapper = DSP1_HIROM;
info.dsp1_mapper = DSP1HiROM;
}
}
@@ -65,11 +79,28 @@ uint8 rom_type = rom[info.header_index + ROM_TYPE];
info.dsp2 = true;
}
if(mapper == 0x30 && rom_type == 0x05 && company == 0xb2) {
info.dsp3 = true;
}
if(mapper == 0x30 && rom_type == 0x03) {
info.dsp4 = true;
}
if(mapper == 0x30 && rom_type == 0x25) {
info.obc1 = true;
}
info.cart_mmio = info.c4 | info.dsp1 | info.dsp2 | info.obc1;
if(mapper == 0x30 && rom_type == 0xf6) {
//TODO: both ST010 and ST011 share the same mapper + rom_type
//need way to determine which is which
//for now, default to supported ST010
info.st010 = true;
}
if(mapper == 0x30 && rom_type == 0xf5) {
info.st018 = true;
}
if(rom[info.header_index + RAM_SIZE] & 7) {
info.ram_size = 1024 << (rom[info.header_index + RAM_SIZE] & 7);
@@ -77,6 +108,9 @@ uint8 rom_type = rom[info.header_index + ROM_TYPE];
info.ram_size = 0;
}
//0, 1, 13 = NTSC; 2 - 12 = PAL
info.region = (region <= 1 || region >= 13) ? NTSC : PAL;
memcpy(&info.name, &rom[info.header_index + CART_NAME], 21);
info.name[21] = 0;
@@ -91,8 +125,9 @@ void Cartridge::find_header() {
int32 score_lo = 0,
score_hi = 0,
score_ex = 0;
uint8 *rom = cart.rom;
if(info.rom_size < 0x010000) {
if(cart.rom_size < 0x010000) {
//cart too small to be anything but lorom
info.header_index = 0x007fc0;
return;
@@ -113,8 +148,8 @@ int32 score_lo = 0,
if(rom[0x7fc0 + REGION] < 14)score_lo++;
if(rom[0xffc0 + REGION] < 14)score_hi++;
if(rom[0x7fc0 + LICENSE] < 3)score_lo++;
if(rom[0xffc0 + LICENSE] < 3)score_hi++;
if(rom[0x7fc0 + COMPANY] < 3)score_lo++;
if(rom[0xffc0 + COMPANY] < 3)score_hi++;
if(rom[0x7fc0 + RESH] & 0x80)score_lo += 2;
if(rom[0xffc0 + RESH] & 0x80)score_hi += 2;
@@ -132,7 +167,7 @@ uint16 cksum, icksum;
score_hi += 8;
}
if(info.rom_size < 0x401000) {
if(cart.rom_size < 0x401000) {
score_ex = 0;
} else {
if(rom[0x7fc0 + MAPPER] == 0x32)score_lo++;

View File

@@ -1,66 +1,41 @@
void Cartridge::load_rom_normal() {
uint size = 0;
for(int i = 0; i < file.count; i++) {
size += file.rom_size[i] - (((file.rom_size[i] & 0x7fff) == 512) ? 512 : 0);
}
info.rom_size = size;
rom = (uint8*)malloc(info.rom_size);
memset(rom, 0, info.rom_size);
uint offset = 0;
for(int i = 0; i < file.count; i++) {
uint8 *data = file.rom_data[i] + (((file.rom_size[i] & 0x7fff) == 512) ? 512 : 0);
uint size = file.rom_size[i] - (((file.rom_size[i] & 0x7fff) == 512) ? 512 : 0);
memcpy(rom + offset, data, size);
offset += size;
safe_free(file.rom_data[i]);
}
info.crc32 = crc32_calculate(rom, info.rom_size);
if(read_database() == true) {
info.srtc = false;
info.sdd1 = false;
info.c4 = false;
info.dsp1 = false;
info.dsp2 = false;
info.obc1 = false;
info.dsp1_mapper = 0;
info.header_index = 0xffc0;
info.mapper = PCB;
strcpy(info.name, dbi.name);
strcpy(info.pcb, dbi.pcb);
info.region = NTSC;
info.cart_mmio = false;
info.rom_size = dbi.rom;
info.ram_size = dbi.ram;
} else {
find_header();
read_header();
}
}
void Cartridge::load_ram_normal() {
if(info.ram_size == 0) {
ram = 0;
return;
}
ram = (uint8*)malloc(info.ram_size);
memset(ram, 0xff, info.ram_size);
if(load_file(file.ram_name[0], file.ram_data[0], file.ram_size[0]) == true) {
memcpy(ram, file.ram_data[0], min(info.ram_size, file.ram_size[0]));
safe_free(file.ram_data[0]);
}
}
void Cartridge::save_ram_normal() {
if(info.ram_size == 0)return;
save_file(file.ram_name[0], ram, info.ram_size);
}
void Cartridge::load_cart_normal(const char *filename) {
if(!filename || !*filename) return;
uint8 *data;
uint size;
if(load_file(filename, data, size) == false) return;
strcpy(cart.fn, filename);
load_begin(CartridgeNormal);
//load ROM data, ignore 512-byte header if detected
if((size & 0x7fff) != 512) {
cart.rom = (uint8*)malloc(cart.rom_size = size);
memcpy(cart.rom, data, size);
} else {
cart.rom = (uint8*)malloc(cart.rom_size = size - 512);
memcpy(cart.rom, data + 512, size - 512);
}
safe_free(data);
info.crc32 = crc32_calculate(cart.rom, cart.rom_size);
find_header();
read_header();
if(info.ram_size > 0) {
cart.ram = (uint8*)malloc(cart.ram_size = info.ram_size);
memset(cart.ram, 0xff, cart.ram_size);
if(load_file(get_save_filename(cart.fn, "srm"), data, size) == true) {
memcpy(cart.ram, data, min(size, cart.ram_size));
safe_free(data);
}
}
load_end();
}
void Cartridge::unload_cart_normal() {
if(cart.ram) save_file(get_save_filename(cart.fn, "srm"), cart.ram, cart.ram_size);
}

View File

@@ -1,45 +1,59 @@
void Cartridge::load_rom_st() {
uint8 *data;
uint size;
string bios = config::file_updatepath("stbios.bin", config::path.bios);
info.rom_size = 0x200000;
rom = (uint8*)malloc(info.rom_size);
memset(rom, 0, info.rom_size);
load_file(strptr(bios), data, size);
memcpy(rom, data, min(size, 0x040000));
safe_free(data);
memcpy(rom + 0x100000, file.rom_data[0], min(file.rom_size[0], 0x100000));
safe_free(file.rom_data[0]);
//
strcpy(info.name, "???");
strcpy(info.pcb, "STC-SOLO");
info.mapper = PCB;
info.region = NTSC;
info.rom_size = 0x200000;
info.ram_size = 0x020000;
//
info.crc32 = crc32_calculate(rom + 0x100000, file.rom_size[0]);
if(read_database() == true) {
strcpy(info.name, dbi.name);
}
}
void Cartridge::load_ram_st() {
ram = (uint8*)malloc(info.ram_size);
memset(ram, 0xff, info.ram_size);
if(load_file(file.ram_name[0], file.ram_data[0], file.ram_size[0]) == true) {
memcpy(ram, file.ram_data[0], min(file.ram_size[0], 0x020000));
safe_free(file.ram_data[0]);
}
}
void Cartridge::save_ram_st() {
save_file(file.ram_name[0], ram, 0x020000);
}
void Cartridge::load_cart_st(const char *base, const char *slotA, const char *slotB) {
if(!base || !*base) return;
strcpy(cart.fn, base);
strcpy(stA.fn, slotA ? slotA : "");
strcpy(stB.fn, slotB ? slotB : "");
load_begin(CartridgeSufamiTurbo);
info.st = true;
info.mapper = STROM;
info.region = NTSC;
uint8 *data;
uint size;
if(load_file(cart.fn, data, size) == true) {
cart.rom = (uint8*)malloc(cart.rom_size = 0x040000);
memcpy(cart.rom, data, min(size, cart.rom_size));
safe_free(data);
}
if(*stA.fn) {
if(load_file(stA.fn, data, size) == true) {
stA.rom = (uint8*)malloc(stA.rom_size = 0x100000);
memcpy(stA.rom, data, min(size, stA.rom_size));
safe_free(data);
stA.ram = (uint8*)malloc(stA.ram_size = 0x020000);
memset(stA.ram, 0xff, stA.ram_size);
if(load_file(get_save_filename(stA.fn, "srm"), data, size) == true) {
memcpy(stA.ram, data, min(size, 0x020000));
safe_free(data);
}
}
}
if(*stB.fn) {
if(load_file(stB.fn, data, size) == true) {
stB.rom = (uint8*)malloc(stB.rom_size = 0x100000);
memcpy(stB.rom, data, min(size, stB.rom_size));
safe_free(data);
stB.ram = (uint8*)malloc(stB.ram_size = 0x020000);
memset(stB.ram, 0xff, stB.ram_size);
if(load_file(get_save_filename(stB.fn, "srm"), data, size) == true) {
memcpy(stB.ram, data, min(size, 0x020000));
safe_free(data);
}
}
}
load_end();
}
void Cartridge::unload_cart_st() {
if(stA.ram) save_file(get_save_filename(stA.fn, "srm"), stA.ram, stA.ram_size);
if(stB.ram) save_file(get_save_filename(stB.fn, "srm"), stB.ram, stB.ram_size);
}

View File

@@ -1,66 +0,0 @@
void Cartridge::load_rom_stdual() {
uint8 *data;
uint size;
string bios = config::file_updatepath("stbios.bin", config::path.bios);
info.rom_size = 0x300000;
rom = (uint8*)malloc(info.rom_size);
memset(rom, 0, info.rom_size);
load_file(strptr(bios), data, size);
memcpy(rom, data, min(size, 0x040000));
safe_free(data);
memcpy(rom + 0x100000, file.rom_data[0], min(file.rom_size[0], 0x100000));
safe_free(file.rom_data[0]);
memcpy(rom + 0x200000, file.rom_data[1], min(file.rom_size[1], 0x100000));
safe_free(file.rom_data[1]);
char name_a[4096], name_b[4096];
strcpy(name_a, "???");
strcpy(name_b, "???");
//
info.mapper = PCB;
info.region = NTSC;
info.rom_size = 0x300000;
info.ram_size = 0x040000;
//
info.crc32 = crc32_calculate(rom + 0x100000, file.rom_size[0]);
if(read_database() == true) {
strcpy(name_a, dbi.name);
}
info.crc32 = crc32_calculate(rom + 0x200000, file.rom_size[1]);
if(read_database() == true) {
strcpy(name_b, dbi.name);
}
//
info.crc32 = 0;
strcpy(info.name, name_a);
strcat(info.name, " + ");
strcat(info.name, name_b);
strcpy(info.pcb, "STC-DUAL");
}
void Cartridge::load_ram_stdual() {
ram = (uint8*)malloc(info.ram_size);
memset(ram, 0xff, info.ram_size);
if(load_file(file.ram_name[0], file.ram_data[0], file.ram_size[0]) == true) {
memcpy(ram + 0x000000, file.ram_data[0], min(file.ram_size[0], 0x020000));
safe_free(file.ram_data[0]);
}
if(load_file(file.ram_name[1], file.ram_data[1], file.ram_size[1]) == true) {
memcpy(ram + 0x020000, file.ram_data[1], min(file.ram_size[1], 0x020000));
safe_free(file.ram_data[1]);
}
}
void Cartridge::save_ram_stdual() {
save_file(file.ram_name[0], ram + 0x000000, 0x020000);
save_file(file.ram_name[1], ram + 0x020000, 0x020000);
}

View File

@@ -1,37 +0,0 @@
void Cartridge::load_database() {
database = 0;
database_size = 0;
FILE *fp;
fp = fopen("cart.db", "rb");
if(!fp)return;
uint size = fsize(fp);
if(size < 8) {
fclose(fp);
return;
}
database = (uint8*)malloc(size);
fread(database, 1, size, fp);
fclose(fp);
database_blocksize = (database[6] << 0) | (database[7] << 8);
database_size = (size - 8) / database_blocksize;
}
bool Cartridge::read_database() {
uint i, crc32;
for(i = 0; i < database_size; i++) {
uint8 *p = database + 8 + (i * database_blocksize);
crc32 = *(p++) << 0;
crc32 |= *(p++) << 8;
crc32 |= *(p++) << 16;
crc32 |= *(p++) << 24;
if(crc32 == cartridge.info.crc32)break;
}
if(i >= database_size)return false;
db_read(dbi, database + 8 + (i * database_blocksize));
return true;
}

Binary file not shown.

View File

@@ -1,113 +0,0 @@
[0xbb5c4238]
name = "Bishoujo Senshi Sailor Moon Sailor Stars - Fuwa Fuwa Panic 2 (Japan)"
pcb = "STC-????"
rom = 8mbit
ram = 32kbit
[0x8eb753f3]
name = "Crayon Shin-chan - Nagagutsu Dobon!! (Japan)"
pcb = "STC-????"
rom = 4mbit
ram = 8kbit
[0x7aedd703]
name = "Der Langrisser (Japan) [!]"
pcb = "SHVC-1A3M-30"
rom = 16mbit
ram = 64kbit
[0x19bdcb19]
name = "Derby Stallion '96 (Japan) [!]"
pcb = "BSC-1A5M-01"
rom = 24mbit
ram = 256kbit
[0x4296500d]
name = "Gegege no Kitarou - Youkai Donjara (Japan)"
pcb = "STC-????"
rom = 4mbit
ram = 16kbit
[0x14c66fca]
name = "Gekisou Sentai Car Rangers (Japan)"
pcb = "STC-????"
rom = 4mbit
ram = 8kbit
[0x32b2b3dd]
name = "Poi Poi Ninja World (Japan)"
pcb = "STC-????"
rom = 4mbit
ram = 8kbit
[0x9684526d]
name = "Romancing SaGa (Japan) (V1.1) [!]"
pcb = "SHVC-1A3B-12"
rom = 8mbit
ram = 64kbit
[0xafd74dcb]
name = "SD Gundam Generation A - Ichinen Sensouki (Japan)"
pcb = "STC-????"
rom = 4mbit
ram = 8kbit
[0x48ecae44]
name = "SD Gundam Generation B - Grips Senki (Japan)"
pcb = "STC-????"
rom = 4mbit
ram = 8kbit
[0x72b4235f]
name = "SD Gundam Generation C - Axis Senki (Japan)"
pcb = "STC-????"
rom = 4mbit
ram = 8kbit
[0x792d884c]
name = "SD Gundam Generation D - Babylonia Kenkoku Senki (Japan)"
pcb = "STC-????"
rom = 4mbit
ram = 8kbit
[0xefd3a865]
name = "SD Gundam Generation E - Zanskar Senki (Japan)"
pcb = "STC-????"
rom = 4mbit
ram = 8kbit
[0xc5dfa8fd]
name = "SD Gundam Generation F - Colony Kakutouki (Japan)"
pcb = "STC-????"
rom = 4mbit
ram = 8kbit
[0x43ad5a45]
name = "SD Ultra Battle - Seven Densetsu (Japan)"
pcb = "STC-????"
rom = 4mbit
ram = 8kbit
[0x04939d14]
name = "SD Ultra Battle - Ultra Densetsu (Japan)"
pcb = "STC-????"
rom = 4mbit
ram = 8kbit
[0xa5c0045e]
name = "Secret of Evermore (USA) [!]"
pcb = "SHVC-1J3M-20"
rom = 32mbit
ram = 64kbit
[0x5ebf7246]
name = "Sound Novel Tsukuru (Japan) [!]"
pcb = "BSC-1A7M-10"
rom = 24mbit
ram = 512kbit
[0x64a91e64]
name = "Wanderers from Ys (USA) [!]"
pcb = "SHVC-1A3B-12"
rom = 8mbit
ram = 64kbit

View File

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

View File

@@ -1 +0,0 @@
@del *.exe

View File

@@ -1,2 +0,0 @@
dbcreate
@copy cart.db ..\..\..\cart.db

View File

@@ -1,47 +0,0 @@
struct db_item {
uint32 crc32;
char name[128];
char pcb [32];
uint32 rom;
uint32 ram;
};
void db_write(FILE *fp, db_item &dbi) {
fputc(dbi.crc32 >> 0, fp);
fputc(dbi.crc32 >> 8, fp);
fputc(dbi.crc32 >> 16, fp);
fputc(dbi.crc32 >> 24, fp);
fwrite(dbi.name, 1, 128, fp);
fwrite(dbi.pcb, 1, 32, fp);
fputc(dbi.rom >> 0, fp);
fputc(dbi.rom >> 8, fp);
fputc(dbi.rom >> 16, fp);
fputc(dbi.rom >> 24, fp);
fputc(dbi.ram >> 0, fp);
fputc(dbi.ram >> 8, fp);
fputc(dbi.ram >> 16, fp);
fputc(dbi.ram >> 24, fp);
}
void db_read(db_item &dbi, uint8 *data) {
dbi.crc32 = (*data++) << 0;
dbi.crc32 |= (*data++) << 8;
dbi.crc32 |= (*data++) << 16;
dbi.crc32 |= (*data++) << 24;
memcpy(dbi.name, data, 128); dbi.name[127] = 0; data += 128;
memcpy(dbi.pcb, data, 32); dbi.pcb [ 31] = 0; data += 32;
dbi.rom = (*data++) << 0;
dbi.rom |= (*data++) << 8;
dbi.rom |= (*data++) << 16;
dbi.rom |= (*data++) << 24;
dbi.ram = (*data++) << 0;
dbi.ram |= (*data++) << 8;
dbi.ram |= (*data++) << 16;
dbi.ram |= (*data++) << 24;
}

View File

@@ -1,117 +0,0 @@
#include "../../lib/libbase.h"
#include "../../lib/libvector.h"
#include "../../lib/libstring.h"
#include "../../lib/libstring.cpp"
#include "db.h"
FILE *fp;
uint decode_size(string &str) {
//hex encoding
if(strbegin(str, "0x")) {
strltrim(str, "0x");
return strhex(str);
}
//mbit encoding
if(strend(str, "mbit")) {
strrtrim(str, "mbit");
return strdec(str) * 1024 * 1024 / 8;
}
//kbit encoding
if(strend(str, "kbit")) {
strrtrim(str, "kbit");
return strdec(str) * 1024 / 8;
}
//decimal encoding
return strdec(str);
}
void build_block(string &block) {
stringarray line, hashpart, part;
split(line, "\n", block);
if(strbegin(line[0], "[") == false) {
printf("error: invalid block detected: '%s'\n", strptr(line[0]));
return;
}
strltrim(line[0], "[");
strrtrim(line[0], "]");
replace(line[0], "0x", "");
split(hashpart, ",", line[0]);
db_item dbi;
dbi.crc32 = 0;
*dbi.name = 0;
*dbi.pcb = 0;
dbi.rom = 0;
dbi.ram = 0;
for(int i = 1; i < count(line); i++) {
uint pos;
if(strpos(line[i], ";", pos) == true) {
strset(line[i], pos, 0);
}
if(line[i] == "")continue;
split(part, "=", line[i]);
strunquote(part[1]);
if(part[0] == "name") {
strncpy(dbi.name, strptr(part[1]), 128);
dbi.name[128] = 0;
}
if(part[0] == "pcb") {
strncpy(dbi.pcb, strptr(part[1]), 32);
dbi.pcb[31] = 0;
}
if(part[0] == "rom") {
dbi.rom = decode_size(part[1]);
}
if(part[0] == "ram") {
dbi.ram = decode_size(part[1]);
}
}
for(int i = 0; i < count(hashpart); i++) {
dbi.crc32 = strhex(hashpart[i]);
db_write(fp, dbi);
}
}
void build_database() {
stringarray data, block;
if(strfread(data, "cartdb.txt") == false)return;
fp = fopen("cart.db", "wb");
fprintf(fp, "SNESDB");
uint blocksize = 4 + 128 + 32 + 4 + 4;
fputc(blocksize >> 0, fp);
fputc(blocksize >> 8, fp);
replace (data, "\r", "");
qreplace(data, " ", "");
qreplace(data, "\t", "");
split(block, "\n\n", data);
for(int i = 0; i < count(block); i++) {
build_block(block[i]);
}
fclose(fp);
}
int main() {
build_database();
return 0;
}

View File

@@ -1,3 +1,6 @@
@make -r PLATFORM=win-visualc-lui
@make -r PLATFORM=win-mingw-x86
::@make -r PLATFORM=win-mingw-x86 GZIP_SUPPORT=true JMA_SUPPORT=true
::@make -r PLATFORM=win-visualc-x86
::@make -r PLATFORM=win-visualc-x86 GZIP_SUPPORT=true JMA_SUPPORT=true
@move bsnes.exe ../bsnes.exe>nul
@pause

View File

@@ -1,2 +1 @@
#!/bin/sh
make PLATFORM=x-gcc-lui
make PLATFORM=x-gcc-x86

View File

@@ -10,17 +10,17 @@ Cheat cheat;
*****/
bool Cheat::decode(char *str, uint32 &addr, uint8 &data, uint8 &type) {
stringarray t, part;
string t, part;
strcpy(t, str);
strlower(t);
if(strlen(t) == 8 || (strlen(t) == 9 && strptr(t)[6] == ':')) {
strlower(t());
if(strlen(t) == 8 || (strlen(t) == 9 && t()[6] == ':')) {
type = CT_PRO_ACTION_REPLAY;
replace(t, ":", "");
uint32 r = strhex(t);
addr = r >> 8;
data = r & 0xff;
return true;
} else if(strlen(t) == 9 && strptr(t)[4] == '-') {
} else if(strlen(t) == 9 && t()[4] == '-') {
type = CT_GAME_GENIE;
replace(t, "-", "");
strtr(t, "df4709156bc8a23e", "0123456789abcdef");
@@ -269,51 +269,40 @@ void Cheat::disable(uint32 n) {
* cheat file manipulation routines
*****/
/* file format: */
/* nnnn-nnnn = status, "description" \r\n */
/* ... */
bool Cheat::load(const char *fn) {
FileReader rf(fn);
if(!rf.ready())return false;
uint8 *raw_data = rf.read();
stringarray data, line;
raw_data[rf.size()] = 0;
strcpy(data, (char*)raw_data);
safe_free(raw_data);
string data;
if(!fread(data, fn)) return false;
replace(data, "\r\n", "\n");
qreplace(data, "=", ",");
qreplace(data, " ", "");
lstring line;
split(line, "\n", data);
for(int i = 0; i < ::count(line); i++) {
stringarray part;
uint8 en = *(strptr(line[i]));
if(en == '+') {
strltrim(line[i], "+");
} else if(en == '-') {
strltrim(line[i], "-");
} else {
continue;
}
qreplace(line[i], " ", "");
qsplit(part, ",", line[i]);
if(::count(part) != 2)continue;
strunquote(part[1]);
add(en == '+', strptr(part[0]), strptr(part[1]));
lstring part;
split(part, ",", line[i]);
if(::count(part) != 3) continue;
trim(part[2], "\"");
add(part[1] == "enabled", part[0](), part[2]());
}
return true;
}
bool Cheat::save(const char *fn) {
FileWriter wf(fn);
if(!wf.ready())return false;
string data;
char t[4096];
strcpy(data, "");
FILE *fp = fopen(fn, "wb");
if(!fp) return false;
for(int i = 0; i < cheat_count; i++) {
sprintf(t, "%c%s, \"%s\"\r\n", index[i].enabled ? '+' : '-', index[i].code, index[i].desc);
strcat(data, t);
fprintf(fp, "%9s = %8s, \"%s\"\r\n",
index[i].code,
index[i].enabled ? "enabled" : "disabled",
index[i].desc);
}
wf.write((uint8*)strptr(data), strlen(data));
fclose(fp);
return true;
}
@@ -323,12 +312,12 @@ char t[4096];
void Cheat::clear() {
cheat_enabled = false;
cheat_count = 0;
cheat_count = 0;
memset(mask, 0, 0x200000);
for(int i = 0; i < CHEAT_LIMIT + 1; i++) {
for(int i = 0; i <= CHEAT_LIMIT; i++) {
index[i].enabled = false;
index[i].addr = 0x000000;
index[i].data = 0x00;
index[i].addr = 0x000000;
index[i].data = 0x00;
strcpy(index[i].code, "");
strcpy(index[i].desc, "");
}

5
src/chip/bsx/bsx.cpp Normal file
View File

@@ -0,0 +1,5 @@
#include "../../base.h"
#include "bsx_base.cpp"
#include "bsx_cart.cpp"
#include "bsx_flash.cpp"

77
src/chip/bsx/bsx.h Normal file
View File

@@ -0,0 +1,77 @@
class BSXBase : public MMIO {
public:
void init();
void enable();
void power();
void reset();
uint8 mmio_read(uint addr);
void mmio_write(uint addr, uint8 data);
private:
struct {
uint8 r2188, r2189, r218a, r218b;
uint8 r218c, r218d, r218e, r218f;
uint8 r2190, r2191, r2192, r2193;
uint8 r2194, r2195, r2196, r2197;
uint8 r2198, r2199, r219a, r219b;
uint8 r219c, r219d, r219e, r219f;
uint8 r2192_counter;
uint8 r2192_hour, r2192_minute, r2192_second;
} regs;
};
class BSXCart : public MMIO {
public:
void init();
void enable();
void power();
void reset();
uint8 mmio_read(uint addr);
void mmio_write(uint addr, uint8 data);
MappedRAM sram;
MappedRAM psram;
BSXCart();
~BSXCart();
private:
uint8 *sram_data; //256kbit SRAM
uint8 *psram_data; // 4mbit PSRAM
struct {
uint8 r[16];
} regs;
void update_memory_map();
};
class BSXFlash : public Memory {
public:
void init();
void enable();
void power();
void reset();
uint size();
uint8 read(uint addr);
void write(uint addr, uint8 data);
private:
struct {
uint command;
uint8 write_old;
uint8 write_new;
bool flash_enable;
bool read_enable;
bool write_enable;
} regs;
};
extern BSXBase bsxbase;
extern BSXCart bsxcart;
extern BSXFlash bsxflash;

133
src/chip/bsx/bsx_base.cpp Normal file
View File

@@ -0,0 +1,133 @@
void BSXBase::init() {
}
void BSXBase::enable() {
for(uint16 i = 0x2188; i <= 0x219f; i++) memory::mmio.map(i, *this);
}
void BSXBase::power() {
reset();
}
void BSXBase::reset() {
memset(&regs, 0x00, sizeof regs);
}
uint8 BSXBase::mmio_read(uint addr) {
addr &= 0xffff;
switch(addr) {
case 0x2188: return regs.r2188;
case 0x2189: return regs.r2189;
case 0x218a: return regs.r218a;
case 0x218c: return regs.r218c;
case 0x218e: return regs.r218e;
case 0x218f: return regs.r218f;
case 0x2190: return regs.r2190;
case 0x2192: {
uint counter = regs.r2192_counter++;
if(regs.r2192_counter >= 18) regs.r2192_counter = 0;
if(counter == 0) {
time_t rawtime;
time(&rawtime);
tm *t = localtime(&rawtime);
regs.r2192_hour = t->tm_hour;
regs.r2192_minute = t->tm_min;
regs.r2192_second = t->tm_sec;
}
switch(counter) {
case 0: return 0x00; //???
case 1: return 0x00; //???
case 2: return 0x00; //???
case 3: return 0x00; //???
case 4: return 0x00; //???
case 5: return 0x01;
case 6: return 0x01;
case 7: return 0x00;
case 8: return 0x00;
case 9: return 0x00;
case 10: return regs.r2192_second;
case 11: return regs.r2192_minute;
case 12: return regs.r2192_hour;
case 13: return 0x00; //???
case 14: return 0x00; //???
case 15: return 0x00; //???
case 16: return 0x00; //???
case 17: return 0x00; //???
}
} break;
case 0x2193: return regs.r2193 & ~0x0c;
case 0x2194: return regs.r2194;
case 0x2196: return regs.r2196;
case 0x2197: return regs.r2197;
case 0x2199: return regs.r2199;
}
return cpu.regs.mdr;
}
void BSXBase::mmio_write(uint addr, uint8 data) {
addr &= 0xffff;
switch(addr) {
case 0x2188: {
regs.r2188 = data;
} break;
case 0x2189: {
regs.r2189 = data;
} break;
case 0x218a: {
regs.r218a = data;
} break;
case 0x218b: {
regs.r218b = data;
} break;
case 0x218c: {
regs.r218c = data;
} break;
case 0x218e: {
regs.r218e = data;
} break;
case 0x218f: {
regs.r218e >>= 1;
regs.r218e = regs.r218f - regs.r218e;
regs.r218f >>= 1;
} break;
case 0x2191: {
regs.r2191 = data;
regs.r2192_counter = 0;
} break;
case 0x2192: {
regs.r2190 = 0x80;
} break;
case 0x2193: {
regs.r2193 = data;
} break;
case 0x2194: {
regs.r2194 = data;
} break;
case 0x2197: {
regs.r2197 = data;
} break;
case 0x2199: {
regs.r2199 = data;
} break;
}
}

95
src/chip/bsx/bsx_cart.cpp Normal file
View File

@@ -0,0 +1,95 @@
void BSXCart::init() {
}
void BSXCart::enable() {
for(uint16 i = 0x5000; i <= 0x5fff; i++) memory::mmio.map(i, *this);
}
void BSXCart::power() {
reset();
}
void BSXCart::reset() {
for(uint i = 0; i < 16; i++) regs.r[i] = 0x00;
regs.r[0x07] = 0x80;
regs.r[0x08] = 0x80;
update_memory_map();
}
void BSXCart::update_memory_map() {
Memory &cart = (regs.r[0x01] & 0x80) == 0x00 ? (Memory&)bsxflash : (Memory&)psram;
if((regs.r[0x02] & 0x80) == 0x00) { //LoROM mapping
bus.map(Bus::MapLinear, 0x00, 0x7d, 0x8000, 0xffff, cart);
bus.map(Bus::MapLinear, 0x80, 0xff, 0x8000, 0xffff, cart);
} else { //HiROM mapping
bus.map(Bus::MapShadow, 0x00, 0x3f, 0x8000, 0xffff, cart);
bus.map(Bus::MapLinear, 0x40, 0x7d, 0x0000, 0xffff, cart);
bus.map(Bus::MapShadow, 0x80, 0xbf, 0x8000, 0xffff, cart);
bus.map(Bus::MapLinear, 0xc0, 0xff, 0x0000, 0xffff, cart);
}
if(regs.r[0x03] & 0x80) {
bus.map(Bus::MapLinear, 0x60, 0x6f, 0x0000, 0xffff, psram);
//bus.map(Bus::MapLinear, 0x70, 0x77, 0x0000, 0xffff, psram);
}
if((regs.r[0x05] & 0x80) == 0x00) {
bus.map(Bus::MapLinear, 0x40, 0x4f, 0x0000, 0xffff, psram);
}
if((regs.r[0x06] & 0x80) == 0x00) {
bus.map(Bus::MapLinear, 0x50, 0x5f, 0x0000, 0xffff, psram);
}
if(regs.r[0x07] & 0x80) {
bus.map(Bus::MapLinear, 0x00, 0x1f, 0x8000, 0xffff, memory::cartrom);
}
if(regs.r[0x08] & 0x80) {
bus.map(Bus::MapLinear, 0x80, 0x9f, 0x8000, 0xffff, memory::cartrom);
}
bus.map(Bus::MapShadow, 0x20, 0x3f, 0x6000, 0x7fff, psram);
bus.map(Bus::MapLinear, 0x70, 0x77, 0x0000, 0xffff, psram);
}
uint8 BSXCart::mmio_read(uint addr) {
if((addr & 0xf0ffff) == 0x005000) { //$[00-0f]:5000 MMIO
uint8 n = (addr >> 16) & 15;
return regs.r[n];
}
if((addr & 0xf8f000) == 0x105000) { //$[10-17]:[5000-5fff] SRAM
return sram.read(((addr >> 16) & 7) * 0x1000 + (addr & 0xfff));
}
return 0x00;
}
void BSXCart::mmio_write(uint addr, uint8 data) {
if((addr & 0xf0ffff) == 0x005000) { //$[00-0f]:5000 MMIO
uint8 n = (addr >> 16) & 15;
regs.r[n] = data;
if(n == 0x0e && data & 0x80) update_memory_map();
return;
}
if((addr & 0xf8f000) == 0x105000) { //$[10-17]:[5000-5fff] SRAM
return sram.write(((addr >> 16) & 7) * 0x1000 + (addr & 0xfff), data);
}
}
BSXCart::BSXCart() {
sram_data = (uint8*)malloc( 32 * 1024);
psram_data = (uint8*)malloc(512 * 1024);
sram.map (sram_data, 32 * 1024);
psram.map(psram_data, 512 * 1024);
}
BSXCart::~BSXCart() {
safe_free(sram_data);
safe_free(psram_data);
}

109
src/chip/bsx/bsx_flash.cpp Normal file
View File

@@ -0,0 +1,109 @@
void BSXFlash::init() {}
void BSXFlash::enable() {}
void BSXFlash::power() {
reset();
}
void BSXFlash::reset() {
regs.command = 0;
regs.write_old = 0x00;
regs.write_new = 0x00;
regs.flash_enable = false;
regs.read_enable = false;
regs.write_enable = false;
}
uint BSXFlash::size() {
return memory::bscram.size();
}
uint8 BSXFlash::read(uint addr) {
if(addr == 0x0002) {
if(regs.flash_enable) return 0x80;
}
if(addr == 0x5555) {
if(regs.flash_enable) return 0x80;
}
if(regs.read_enable && addr >= 0xff00 && addr <= 0xff13) {
//read flash cartridge vendor information
switch(addr - 0xff00) {
case 0x00: return 0x4d;
case 0x01: return 0x00;
case 0x02: return 0x50;
case 0x03: return 0x00;
case 0x04: return 0x00;
case 0x05: return 0x00;
case 0x06: return 0x2a; //0x2a = 8mbit, 0x2b = 16mbit (not known to exist, though BIOS recognizes ID)
case 0x07: return 0x00;
default: return 0x00;
}
}
return memory::bscram.read(addr);
}
void BSXFlash::write(uint addr, uint8 data) {
//there exist both read-only and read-write BS-X flash cartridges ...
//unfortunately, the vendor info is not stored inside memory dumps
//of BS-X flashcarts, so it is impossible to determine whether a
//given flashcart is writeable.
//however, it has been observed that LoROM-mapped BS-X carts always
//use read-write flashcarts, and HiROM-mapped BS-X carts always use
//read-only flashcarts.
//below is an unfortunately necessary workaround to this problem.
if(cartridge.mapper() == Cartridge::BSCHiROM) return;
if((addr & 0xff0000) == 0) {
regs.write_old = regs.write_new;
regs.write_new = data;
if(regs.write_enable && regs.write_old == regs.write_new) {
return memory::bscram.write(addr, data);
}
} else {
if(regs.write_enable) {
return memory::bscram.write(addr, data);
}
}
if(addr == 0x0000) {
regs.command <<= 8;
regs.command |= data;
if((regs.command & 0xffff) == 0x38d0) {
regs.flash_enable = true;
regs.read_enable = true;
}
}
if(addr == 0x2aaa) {
regs.command <<= 8;
regs.command |= data;
}
if(addr == 0x5555) {
regs.command <<= 8;
regs.command |= data;
if((regs.command & 0xffffff) == 0xaa5570) {
regs.write_enable = false;
}
if((regs.command & 0xffffff) == 0xaa55a0) {
regs.write_old = 0x00;
regs.write_new = 0x00;
regs.flash_enable = true;
regs.write_enable = true;
}
if((regs.command & 0xffffff) == 0xaa55f0) {
regs.flash_enable = false;
regs.read_enable = false;
regs.write_enable = false;
}
}
}

11
src/chip/chip.h Normal file
View File

@@ -0,0 +1,11 @@
#include "bsx/bsx.h"
#include "superfx/superfx.h"
#include "srtc/srtc.h"
#include "sdd1/sdd1.h"
#include "cx4/cx4.h"
#include "dsp1/dsp1.h"
#include "dsp2/dsp2.h"
#include "dsp3/dsp3.h"
#include "dsp4/dsp4.h"
#include "obc1/obc1.h"
#include "st010/st010.h"

View File

@@ -7,29 +7,27 @@
#include "../../base.h"
C4 *c4;
#include "cx4data.cpp"
#include "cx4fn.cpp"
#include "cx4oam.cpp"
#include "cx4ops.cpp"
#include "c4data.cpp"
#include "c4fn.cpp"
#include "c4oam.cpp"
#include "c4ops.cpp"
void Cx4::init() {}
void Cx4::enable() {}
void C4::init() {}
void C4::enable() {}
uint32 C4::ldr(uint8 r) {
uint32 Cx4::ldr(uint8 r) {
uint16 addr = 0x0080 + (r * 3);
return (reg[addr]) | (reg[addr + 1] << 8) | (reg[addr + 2] << 16);
}
void C4::str(uint8 r, uint32 data) {
void Cx4::str(uint8 r, uint32 data) {
uint16 addr = 0x0080 + (r * 3);
reg[addr ] = (data);
reg[addr + 1] = (data >> 8);
reg[addr + 2] = (data >> 16);
}
void C4::mul(uint32 x, uint32 y, uint32 &rl, uint32 &rh) {
void Cx4::mul(uint32 x, uint32 y, uint32 &rl, uint32 &rh) {
int64 rx = x & 0xffffff;
int64 ry = y & 0xffffff;
if(rx & 0x800000)rx |= ~0x7fffff;
@@ -41,7 +39,7 @@ int64 ry = y & 0xffffff;
rh = (rx >> 24) & 0xffffff;
}
uint32 C4::sin(uint32 rx) {
uint32 Cx4::sin(uint32 rx) {
r0 = rx & 0x1ff;
if(r0 & 0x100)r0 ^= 0x1ff;
if(r0 & 0x080)r0 ^= 0x0ff;
@@ -52,13 +50,13 @@ uint32 C4::sin(uint32 rx) {
}
}
uint32 C4::cos(uint32 rx) {
uint32 Cx4::cos(uint32 rx) {
return sin(rx + 0x080);
}
void C4::immediate_reg(uint32 start) {
void Cx4::immediate_reg(uint32 start) {
r0 = ldr(0);
for(uint32 i=start;i<48;i++) {
for(uint32 i = start; i < 48; i++) {
if((r0 & 0x0fff) < 0x0c00) {
ram[r0 & 0x0fff] = immediate_data[i];
}
@@ -67,7 +65,7 @@ void C4::immediate_reg(uint32 start) {
str(0, r0);
}
void C4::transfer_data() {
void Cx4::transfer_data() {
uint32 src;
uint16 dest, count;
src = (reg[0x40]) | (reg[0x41] << 8) | (reg[0x42] << 16);
@@ -75,11 +73,11 @@ uint16 dest, count;
dest = (reg[0x45]) | (reg[0x46] << 8);
for(uint32 i=0;i<count;i++) {
write(dest++, r_mem->read(src++));
write(dest++, bus.read(src++));
}
}
void C4::write(uint16 addr, uint8 data) {
void Cx4::write(uint addr, uint8 data) {
addr &= 0x1fff;
if(addr < 0x0c00) {
@@ -111,57 +109,57 @@ void C4::write(uint16 addr, uint8 data) {
}
switch(data) {
case 0x00:op00();break;
case 0x01:op01();break;
case 0x05:op05();break;
case 0x0d:op0d();break;
case 0x10:op10();break;
case 0x13:op13();break;
case 0x15:op15();break;
case 0x1f:op1f();break;
case 0x22:op22();break;
case 0x25:op25();break;
case 0x2d:op2d();break;
case 0x40:op40();break;
case 0x54:op54();break;
case 0x5c:op5c();break;
case 0x5e:op5e();break;
case 0x60:op60();break;
case 0x62:op62();break;
case 0x64:op64();break;
case 0x66:op66();break;
case 0x68:op68();break;
case 0x6a:op6a();break;
case 0x6c:op6c();break;
case 0x6e:op6e();break;
case 0x70:op70();break;
case 0x72:op72();break;
case 0x74:op74();break;
case 0x76:op76();break;
case 0x78:op78();break;
case 0x7a:op7a();break;
case 0x7c:op7c();break;
case 0x89:op89();break;
case 0x00: op00(); break;
case 0x01: op01(); break;
case 0x05: op05(); break;
case 0x0d: op0d(); break;
case 0x10: op10(); break;
case 0x13: op13(); break;
case 0x15: op15(); break;
case 0x1f: op1f(); break;
case 0x22: op22(); break;
case 0x25: op25(); break;
case 0x2d: op2d(); break;
case 0x40: op40(); break;
case 0x54: op54(); break;
case 0x5c: op5c(); break;
case 0x5e: op5e(); break;
case 0x60: op60(); break;
case 0x62: op62(); break;
case 0x64: op64(); break;
case 0x66: op66(); break;
case 0x68: op68(); break;
case 0x6a: op6a(); break;
case 0x6c: op6c(); break;
case 0x6e: op6e(); break;
case 0x70: op70(); break;
case 0x72: op72(); break;
case 0x74: op74(); break;
case 0x76: op76(); break;
case 0x78: op78(); break;
case 0x7a: op7a(); break;
case 0x7c: op7c(); break;
case 0x89: op89(); break;
}
}
}
void C4::writeb(uint16 addr, uint8 data) {
void Cx4::writeb(uint16 addr, uint8 data) {
write(addr, data);
}
void C4::writew(uint16 addr, uint16 data) {
void Cx4::writew(uint16 addr, uint16 data) {
write(addr, data);
write(addr + 1, data >> 8);
}
void C4::writel(uint16 addr, uint32 data) {
void Cx4::writel(uint16 addr, uint32 data) {
write(addr, data);
write(addr + 1, data >> 8);
write(addr + 2, data >> 16);
}
uint8 C4::read(uint16 addr) {
uint8 Cx4::read(uint addr) {
addr &= 0x1fff;
if(addr < 0x0c00) {
@@ -172,28 +170,26 @@ uint8 C4::read(uint16 addr) {
return reg[addr & 0xff];
}
return r_cpu->regs.mdr;
return cpu.regs.mdr;
}
uint8 C4::readb(uint16 addr) {
uint8 Cx4::readb(uint16 addr) {
return read(addr);
}
uint16 C4::readw(uint16 addr) {
uint16 Cx4::readw(uint16 addr) {
return read(addr) | (read(addr + 1) << 8);
}
uint32 C4::readl(uint16 addr) {
uint32 Cx4::readl(uint16 addr) {
return read(addr) | (read(addr + 1) << 8) + (read(addr + 2) << 16);
}
void C4::power() {
void Cx4::power() {
reset();
}
void C4::reset() {
void Cx4::reset() {
memset(ram, 0, 0x0c00);
memset(reg, 0, 0x0100);
}
C4::C4() {}

View File

@@ -1,29 +1,29 @@
class C4 {
class Cx4 : public Memory {
private:
uint8 ram[0x0c00];
uint8 reg[0x0100];
uint32 r0, r1, r2, r3, r4, r5, r6, r7,
r8, r9, r10, r11, r12, r13, r14, r15;
uint8 ram[0x0c00];
uint8 reg[0x0100];
uint32 r0, r1, r2, r3, r4, r5, r6, r7,
r8, r9, r10, r11, r12, r13, r14, r15;
static const uint8 immediate_data[48];
static const uint16 wave_data[40];
static const uint32 sin_table[256];
static const uint8 immediate_data[48];
static const uint16 wave_data[40];
static const uint32 sin_table[256];
static const int16 SinTable[512];
static const int16 CosTable[512];
static const int16 SinTable[512];
static const int16 CosTable[512];
int16 C4WFXVal, C4WFYVal, C4WFZVal, C4WFX2Val, C4WFY2Val, C4WFDist, C4WFScale;
int16 C41FXVal, C41FYVal, C41FAngleRes, C41FDist, C41FDistVal;
int16 C4WFXVal, C4WFYVal, C4WFZVal, C4WFX2Val, C4WFY2Val, C4WFDist, C4WFScale;
int16 C41FXVal, C41FYVal, C41FAngleRes, C41FDist, C41FDistVal;
double tanval;
double c4x,c4y,c4z, c4x2,c4y2,c4z2;
double tanval;
double c4x,c4y,c4z, c4x2,c4y2,c4z2;
void C4TransfWireFrame();
void C4TransfWireFrame2();
void C4CalcWireFrame();
void C4DrawLine(int32 X1, int32 Y1, int16 Z1, int32 X2, int32 Y2, int16 Z2, uint8 Color);
void C4DrawWireFrame();
void C4DoScaleRotate(int row_padding);
void C4TransfWireFrame();
void C4TransfWireFrame2();
void C4CalcWireFrame();
void C4DrawLine(int32 X1, int32 Y1, int16 Z1, int32 X2, int32 Y2, int16 Z2, uint8 Color);
void C4DrawWireFrame();
void C4DoScaleRotate(int row_padding);
public:
uint32 ldr(uint8 r);
@@ -75,22 +75,23 @@ public:
void op7c();
void op89();
uint8 readb(uint16 addr);
uint16 readw(uint16 addr);
uint32 readl(uint16 addr);
void writeb(uint16 addr, uint8 data);
void writew(uint16 addr, uint16 data);
void writel(uint16 addr, uint32 data);
//
void init();
void enable();
void power();
void reset();
void write (uint16 addr, uint8 data);
void writeb(uint16 addr, uint8 data);
void writew(uint16 addr, uint16 data);
void writel(uint16 addr, uint32 data);
uint8 read (uint16 addr);
uint8 readb(uint16 addr);
uint16 readw(uint16 addr);
uint32 readl(uint16 addr);
C4();
uint8 read (uint addr);
void write(uint addr, uint8 data);
};
extern C4 *c4;
extern Cx4 cx4;

View File

@@ -1,11 +1,11 @@
const uint8 C4::immediate_data[48] = {
const uint8 Cx4::immediate_data[48] = {
0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff,
0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x80, 0xff, 0xff, 0x7f,
0x00, 0x80, 0x00, 0xff, 0x7f, 0x00, 0xff, 0x7f, 0xff, 0x7f, 0xff, 0xff,
0x00, 0x00, 0x01, 0xff, 0xff, 0xfe, 0x00, 0x01, 0x00, 0xff, 0xfe, 0x00
};
const uint16 C4::wave_data[40] = {
const uint16 Cx4::wave_data[40] = {
0x0000, 0x0002, 0x0004, 0x0006, 0x0008, 0x000a, 0x000c, 0x000e,
0x0200, 0x0202, 0x0204, 0x0206, 0x0208, 0x020a, 0x020c, 0x020e,
0x0400, 0x0402, 0x0404, 0x0406, 0x0408, 0x040a, 0x040c, 0x040e,
@@ -13,7 +13,7 @@ const uint16 C4::wave_data[40] = {
0x0800, 0x0802, 0x0804, 0x0806, 0x0808, 0x080a, 0x080c, 0x080e
};
const uint32 C4::sin_table[256] = {
const uint32 Cx4::sin_table[256] = {
0x000000, 0x000324, 0x000648, 0x00096c, 0x000c8f, 0x000fb2, 0x0012d5, 0x0015f6,
0x001917, 0x001c37, 0x001f56, 0x002273, 0x002590, 0x0028aa, 0x002bc4, 0x002edb,
0x0031f1, 0x003505, 0x003817, 0x003b26, 0x003e33, 0x00413e, 0x004447, 0x00474d,
@@ -48,7 +48,7 @@ const uint32 C4::sin_table[256] = {
0xff013b, 0xff00f1, 0xff00b1, 0xff007b, 0xff004e, 0xff002c, 0xff0013, 0xff0004
};
const int16 C4::SinTable[512] = {
const int16 Cx4::SinTable[512] = {
0, 402, 804, 1206, 1607, 2009, 2410, 2811,
3211, 3611, 4011, 4409, 4808, 5205, 5602, 5997,
6392, 6786, 7179, 7571, 7961, 8351, 8739, 9126,
@@ -115,7 +115,7 @@ const int16 C4::SinTable[512] = {
-3211, -2811, -2410, -2009, -1607, -1206, -804, -402
};
const int16 C4::CosTable[512] = {
const int16 Cx4::CosTable[512] = {
32767, 32765, 32758, 32745, 32728, 32706, 32679, 32647,
32610, 32568, 32521, 32469, 32413, 32351, 32285, 32214,
32138, 32057, 31971, 31881, 31785, 31685, 31581, 31471,

View File

@@ -7,7 +7,7 @@
#define PI 3.1415926535897932384626433832795
//Wireframe Helpers
void C4::C4TransfWireFrame() {
void Cx4::C4TransfWireFrame() {
c4x = (double)C4WFXVal;
c4y = (double)C4WFYVal;
c4z = (double)C4WFZVal - 0x95;
@@ -32,7 +32,7 @@ void C4::C4TransfWireFrame() {
C4WFYVal = (int16)(c4y * C4WFScale / (0x90 * (c4z + 0x95)) * 0x95);
}
void C4::C4CalcWireFrame() {
void Cx4::C4CalcWireFrame() {
C4WFXVal = C4WFX2Val - C4WFXVal;
C4WFYVal = C4WFY2Val - C4WFYVal;
@@ -49,7 +49,7 @@ void C4::C4CalcWireFrame() {
}
}
void C4::C4TransfWireFrame2() {
void Cx4::C4TransfWireFrame2() {
c4x = (double)C4WFXVal;
c4y = (double)C4WFYVal;
c4z = (double)C4WFZVal;
@@ -74,34 +74,34 @@ void C4::C4TransfWireFrame2() {
C4WFYVal = (int16)(c4y * C4WFScale / 0x100);
}
void C4::C4DrawWireFrame() {
void Cx4::C4DrawWireFrame() {
uint32 line = readl(0x1f80);
uint32 point1, point2;
int16 X1, Y1, Z1;
int16 X2, Y2, Z2;
uint8 Color;
for(int32 i = ram[0x0295]; i > 0; i--, line += 5) {
if(r_mem->read(line) == 0xff && r_mem->read(line + 1) == 0xff) {
if(bus.read(line) == 0xff && bus.read(line + 1) == 0xff) {
int32 tmp = line - 5;
while(r_mem->read(tmp + 2) == 0xff && r_mem->read(tmp + 3) == 0xff && (tmp + 2) >= 0) { tmp -= 5; }
point1 = (read(0x1f82) << 16) | (r_mem->read(tmp + 2) << 8) | r_mem->read(tmp + 3);
while(bus.read(tmp + 2) == 0xff && bus.read(tmp + 3) == 0xff && (tmp + 2) >= 0) { tmp -= 5; }
point1 = (read(0x1f82) << 16) | (bus.read(tmp + 2) << 8) | bus.read(tmp + 3);
} else {
point1 = (read(0x1f82) << 16) | (r_mem->read(line) << 8) | r_mem->read(line + 1);
point1 = (read(0x1f82) << 16) | (bus.read(line) << 8) | bus.read(line + 1);
}
point2 = (read(0x1f82) << 16) | (r_mem->read(line + 2) << 8) | r_mem->read(line + 3);
point2 = (read(0x1f82) << 16) | (bus.read(line + 2) << 8) | bus.read(line + 3);
X1=(r_mem->read(point1 + 0) << 8) | r_mem->read(point1 + 1);
Y1=(r_mem->read(point1 + 2) << 8) | r_mem->read(point1 + 3);
Z1=(r_mem->read(point1 + 4) << 8) | r_mem->read(point1 + 5);
X2=(r_mem->read(point2 + 0) << 8) | r_mem->read(point2 + 1);
Y2=(r_mem->read(point2 + 2) << 8) | r_mem->read(point2 + 3);
Z2=(r_mem->read(point2 + 4) << 8) | r_mem->read(point2 + 5);
Color = r_mem->read(line + 4);
X1=(bus.read(point1 + 0) << 8) | bus.read(point1 + 1);
Y1=(bus.read(point1 + 2) << 8) | bus.read(point1 + 3);
Z1=(bus.read(point1 + 4) << 8) | bus.read(point1 + 5);
X2=(bus.read(point2 + 0) << 8) | bus.read(point2 + 1);
Y2=(bus.read(point2 + 2) << 8) | bus.read(point2 + 3);
Z2=(bus.read(point2 + 4) << 8) | bus.read(point2 + 5);
Color = bus.read(line + 4);
C4DrawLine(X1, Y1, Z1, X2, Y2, Z2, Color);
}
}
void C4::C4DrawLine(int32 X1, int32 Y1, int16 Z1, int32 X2, int32 Y2, int16 Z2, uint8 Color) {
void Cx4::C4DrawLine(int32 X1, int32 Y1, int16 Z1, int32 X2, int32 Y2, int16 Z2, uint8 Color) {
//Transform coordinates
C4WFXVal = (int16)X1;
C4WFYVal = (int16)Y1;
@@ -145,7 +145,7 @@ void C4::C4DrawLine(int32 X1, int32 Y1, int16 Z1, int32 X2, int32 Y2, int16 Z2,
}
}
void C4::C4DoScaleRotate(int row_padding) {
void Cx4::C4DoScaleRotate(int row_padding) {
int16 A, B, C, D;
//Calculate matrix

View File

@@ -1,5 +1,5 @@
//Build OAM
void C4::op00_00() {
void Cx4::op00_00() {
uint32 oamptr = ram[0x626] << 2;
for(int32 i = 0x1fd; i > oamptr && i >= 0; i -= 4) {
//clear oam-to-be
@@ -27,28 +27,28 @@ uint32 srcptr = 0x220;
sprattr = ram[srcptr + 4] | ram[srcptr + 6];
uint32 spraddr = readl(srcptr + 7);
if(r_mem->read(spraddr)) {
if(bus.read(spraddr)) {
int16 x, y;
for(int sprcnt = r_mem->read(spraddr++); sprcnt > 0 && sprcount > 0; sprcnt--, spraddr += 4) {
x = (int8)r_mem->read(spraddr + 1);
for(int sprcnt = bus.read(spraddr++); sprcnt > 0 && sprcount > 0; sprcnt--, spraddr += 4) {
x = (int8)bus.read(spraddr + 1);
if(sprattr & 0x40) {
x = -x - ((r_mem->read(spraddr) & 0x20) ? 16 : 8);
x = -x - ((bus.read(spraddr) & 0x20) ? 16 : 8);
}
x += sprx;
if(x >= -16 && x <= 272) {
y = (int8)r_mem->read(spraddr + 2);
y = (int8)bus.read(spraddr + 2);
if(sprattr & 0x80) {
y = -y - ((r_mem->read(spraddr) & 0x20) ? 16 : 8);
y = -y - ((bus.read(spraddr) & 0x20) ? 16 : 8);
}
y += spry;
if(y >= -16 && y <= 224) {
ram[oamptr ] = (uint8)x;
ram[oamptr + 1] = (uint8)y;
ram[oamptr + 2] = sprname + r_mem->read(spraddr + 3);
ram[oamptr + 3] = sprattr ^ (r_mem->read(spraddr) & 0xc0);
ram[oamptr + 2] = sprname + bus.read(spraddr + 3);
ram[oamptr + 3] = sprattr ^ (bus.read(spraddr) & 0xc0);
ram[oamptr2] &= ~(3 << offset);
if(x & 0x100)ram[oamptr2] |= 1 << offset;
if(r_mem->read(spraddr) & 0x20)ram[oamptr2] |= 2 << offset;
if(bus.read(spraddr) & 0x20)ram[oamptr2] |= 2 << offset;
oamptr += 4;
sprcount--;
offset = (offset + 2) & 6;
@@ -73,12 +73,12 @@ uint32 srcptr = 0x220;
}
//Scale and Rotate
void C4::op00_03() {
void Cx4::op00_03() {
C4DoScaleRotate(0);
}
//Transform Lines
void C4::op00_05() {
void Cx4::op00_05() {
C4WFX2Val = read(0x1f83);
C4WFY2Val = read(0x1f86);
C4WFDist = read(0x1f89);
@@ -119,17 +119,17 @@ uint32 ptr2 = 0;
}
//Scale and Rotate
void C4::op00_07() {
void Cx4::op00_07() {
C4DoScaleRotate(64);
}
//Draw Wireframe
void C4::op00_08() {
void Cx4::op00_08() {
C4DrawWireFrame();
}
//Disintegrate
void C4::op00_0b() {
void Cx4::op00_0b() {
uint8 width, height;
uint32 startx, starty;
uint32 srcptr;
@@ -169,7 +169,7 @@ int32 i, j;
}
//Bitplane Wave
void C4::op00_0c() {
void Cx4::op00_0c() {
uint32 destptr = 0;
uint32 waveptr = read(0x1f83);
uint16 mask1 = 0xc0c0;

View File

@@ -1,5 +1,5 @@
//Sprite Functions
void C4::op00() {
void Cx4::op00() {
switch(reg[0x4d]) {
case 0x00:op00_00();break;
case 0x03:op00_03();break;
@@ -12,13 +12,13 @@ void C4::op00() {
}
//Draw Wireframe
void C4::op01() {
void Cx4::op01() {
memset(ram + 0x300, 0, 2304);
C4DrawWireFrame();
}
//Propulsion
void C4::op05() {
void Cx4::op05() {
int32 temp = 0x10000;
if(readw(0x1f83)) {
temp = sar((temp / readw(0x1f83)) * readw(0x1f81), 8);
@@ -27,7 +27,7 @@ int32 temp = 0x10000;
}
//Set Vector length
void C4::op0d() {
void Cx4::op0d() {
C41FXVal = readw(0x1f80);
C41FYVal = readw(0x1f83);
C41FDistVal = readw(0x1f86);
@@ -40,7 +40,7 @@ void C4::op0d() {
}
//Triangle
void C4::op10() {
void Cx4::op10() {
r0 = ldr(0);
r1 = ldr(1);
@@ -64,7 +64,7 @@ void C4::op10() {
}
//Triangle
void C4::op13() {
void Cx4::op13() {
r0 = ldr(0);
r1 = ldr(1);
@@ -87,7 +87,7 @@ void C4::op13() {
}
//Pythagorean
void C4::op15() {
void Cx4::op15() {
C41FXVal = readw(0x1f80);
C41FYVal = readw(0x1f83);
C41FDist = (int16)sqrt((double)C41FXVal * (double)C41FXVal + (double)C41FYVal * (double)C41FYVal);
@@ -95,7 +95,7 @@ void C4::op15() {
}
//Calculate distance
void C4::op1f() {
void Cx4::op1f() {
C41FXVal = readw(0x1f80);
C41FYVal = readw(0x1f83);
if(!C41FXVal) {
@@ -113,7 +113,7 @@ void C4::op1f() {
}
//Trapezoid
void C4::op22() {
void Cx4::op22() {
int16 angle1 = readw(0x1f8c) & 0x1ff;
int16 angle2 = readw(0x1f8f) & 0x1ff;
int32 tan1 = Tan(angle1);
@@ -152,7 +152,7 @@ int16 left, right;
}
//Multiply
void C4::op25() {
void Cx4::op25() {
r0 = ldr(0);
r1 = ldr(1);
mul(r0, r1, r0, r1);
@@ -161,7 +161,7 @@ void C4::op25() {
}
//Transform Coords
void C4::op2d() {
void Cx4::op2d() {
C4WFXVal = readw(0x1f81);
C4WFYVal = readw(0x1f84);
C4WFZVal = readw(0x1f87);
@@ -175,7 +175,7 @@ void C4::op2d() {
}
//Sum
void C4::op40() {
void Cx4::op40() {
r0 = 0;
for(uint32 i=0;i<0x800;i++) {
r0 += ram[i];
@@ -184,7 +184,7 @@ void C4::op40() {
}
//Square
void C4::op54() {
void Cx4::op54() {
r0 = ldr(0);
mul(r0, r0, r1, r2);
str(1, r1);
@@ -192,31 +192,31 @@ void C4::op54() {
}
//Immediate Register
void C4::op5c() {
void Cx4::op5c() {
str(0, 0x000000);
immediate_reg(0);
}
//Immediate Register (Multiple)
void C4::op5e() { immediate_reg( 0); }
void C4::op60() { immediate_reg( 3); }
void C4::op62() { immediate_reg( 6); }
void C4::op64() { immediate_reg( 9); }
void C4::op66() { immediate_reg(12); }
void C4::op68() { immediate_reg(15); }
void C4::op6a() { immediate_reg(18); }
void C4::op6c() { immediate_reg(21); }
void C4::op6e() { immediate_reg(24); }
void C4::op70() { immediate_reg(27); }
void C4::op72() { immediate_reg(30); }
void C4::op74() { immediate_reg(33); }
void C4::op76() { immediate_reg(36); }
void C4::op78() { immediate_reg(39); }
void C4::op7a() { immediate_reg(42); }
void C4::op7c() { immediate_reg(45); }
void Cx4::op5e() { immediate_reg( 0); }
void Cx4::op60() { immediate_reg( 3); }
void Cx4::op62() { immediate_reg( 6); }
void Cx4::op64() { immediate_reg( 9); }
void Cx4::op66() { immediate_reg(12); }
void Cx4::op68() { immediate_reg(15); }
void Cx4::op6a() { immediate_reg(18); }
void Cx4::op6c() { immediate_reg(21); }
void Cx4::op6e() { immediate_reg(24); }
void Cx4::op70() { immediate_reg(27); }
void Cx4::op72() { immediate_reg(30); }
void Cx4::op74() { immediate_reg(33); }
void Cx4::op76() { immediate_reg(36); }
void Cx4::op78() { immediate_reg(39); }
void Cx4::op7a() { immediate_reg(42); }
void Cx4::op7c() { immediate_reg(45); }
//Immediate ROM
void C4::op89() {
void Cx4::op89() {
str(0, 0x054336);
str(1, 0xffffff);
}

View File

@@ -1,7 +1,5 @@
#include "../../base.h"
DSP1 *dsp1;
#include "dsp1emu.cpp"
void DSP1::init() {}
@@ -28,29 +26,30 @@ void DSP1::reset() {
*****/
bool DSP1::addr_decode(uint16 addr) {
switch(cartridge.info.dsp1_mapper) {
case Cartridge::DSP1LoROM1MB: {
//$[20-3f]:[8000-bfff] = DR, $[20-3f]:[c000-ffff] = SR
return (addr >= 0xc000);
}
case Cartridge::DSP1_LOROM_1MB:
//$[20-3f]:[8000-bfff] = DR, $[20-3f]:[c000-ffff] = SR
return (addr >= 0xc000);
case Cartridge::DSP1_LOROM_2MB:
//$[60-6f]:[0000-3fff] = DR, $[60-6f]:[4000-7fff] = SR
return (addr >= 0x4000);
case Cartridge::DSP1_HIROM:
//$[00-1f]:[6000-6fff] = DR, $[00-1f]:[7000-7fff] = SR
return (addr >= 0x7000);
case Cartridge::DSP1LoROM2MB: {
//$[60-6f]:[0000-3fff] = DR, $[60-6f]:[4000-7fff] = SR
return (addr >= 0x4000);
}
case Cartridge::DSP1HiROM: {
//$[00-1f]:[6000-6fff] = DR, $[00-1f]:[7000-7fff] = SR
return (addr >= 0x7000);
}
}
return 0;
}
uint8 DSP1::read(uint16 addr) {
uint8 DSP1::read(uint addr) {
return (addr_decode(addr) == 0) ? dsp1.getDr() : dsp1.getSr();
}
void DSP1::write(uint16 addr, uint8 data) {
void DSP1::write(uint addr, uint8 data) {
if(addr_decode(addr) == 0) {
dsp1.setDr(data);
}

View File

@@ -1,18 +1,18 @@
#include "dsp1emu.h"
class DSP1 {
class DSP1 : public Memory {
private:
Dsp1 dsp1;
Dsp1 dsp1;
bool addr_decode(uint16 addr);
public:
void init();
void enable();
void power();
void reset();
void init();
void enable();
void power();
void reset();
bool addr_decode(uint16 addr);
uint8 read (uint16 addr);
void write(uint16 addr, uint8 data);
uint8 read(uint addr);
void write(uint addr, uint8 data);
};
extern DSP1 *dsp1;
extern DSP1 dsp1;

View File

@@ -1,7 +1,5 @@
#include "../../base.h"
DSP2 *dsp2;
#include "dsp2_op.cpp"
void DSP2::init() {}
@@ -30,7 +28,7 @@ void DSP2::reset() {
status.op0dinlen = 0;
}
uint8 DSP2::read(uint16 addr) {
uint8 DSP2::read(uint addr) {
uint8 r = 0xff;
if(status.out_count) {
r = status.output[status.out_index++];
@@ -42,7 +40,7 @@ uint8 r = 0xff;
return r;
}
void DSP2::write(uint16 addr, uint8 data) {
void DSP2::write(uint addr, uint8 data) {
if(status.waiting_for_command) {
status.command = data;
status.in_index = 0;

View File

@@ -1,43 +1,44 @@
class DSP2 {
class DSP2 : public Memory {
public:
struct {
bool waiting_for_command;
uint command;
uint in_count, in_index;
uint out_count, out_index;
struct {
bool waiting_for_command;
uint command;
uint in_count, in_index;
uint out_count, out_index;
uint8 parameters[512];
uint8 output[512];
uint8 parameters[512];
uint8 output[512];
uint8 op05transparent;
bool op05haslen;
int op05len;
bool op06haslen;
int op06len;
uint16 op09word1;
uint16 op09word2;
bool op0dhaslen;
int op0doutlen;
int op0dinlen;
} status;
uint8 op05transparent;
bool op05haslen;
int op05len;
bool op06haslen;
int op06len;
uint16 op09word1;
uint16 op09word2;
bool op0dhaslen;
int op0doutlen;
int op0dinlen;
} status;
void init();
void enable();
void power();
void reset();
void init();
void enable();
void power();
void reset();
void op01();
void op03();
void op05();
void op06();
void op09();
void op0d();
uint8 read (uint16 addr);
void write(uint16 addr, uint8 data);
uint8 read(uint addr);
void write(uint addr, uint8 data);
DSP2();
~DSP2();
protected:
void op01();
void op03();
void op05();
void op06();
void op09();
void op0d();
};
extern DSP2 *dsp2;
extern DSP2 dsp2;

33
src/chip/dsp3/dsp3.cpp Normal file
View File

@@ -0,0 +1,33 @@
#include "../../base.h"
namespace DSP3i {
#define bool8 uint8
#include "dsp3emu.c"
#undef bool8
};
void DSP3::init() {
}
void DSP3::enable() {
}
void DSP3::power() {
reset();
}
void DSP3::reset() {
DSP3i::DSP3_Reset();
}
uint8 DSP3::read(uint addr) {
DSP3i::dsp3_address = addr & 0xffff;
DSP3i::DSP3GetByte();
return DSP3i::dsp3_byte;
}
void DSP3::write(uint addr, uint8 data) {
DSP3i::dsp3_address = addr & 0xffff;
DSP3i::dsp3_byte = data;
DSP3i::DSP3SetByte();
}

12
src/chip/dsp3/dsp3.h Normal file
View File

@@ -0,0 +1,12 @@
class DSP3 : public Memory {
public:
void init();
void enable();
void power();
void reset();
uint8 read (uint addr);
void write(uint addr, uint8 data);
};
extern DSP3 dsp3;

1142
src/chip/dsp3/dsp3emu.c Normal file

File diff suppressed because it is too large Load Diff

53
src/chip/dsp4/dsp4.cpp Normal file
View File

@@ -0,0 +1,53 @@
#include "../../base.h"
namespace DSP4i {
inline uint16 READ_WORD(uint8 *addr) {
return (addr[0]) + (addr[1] << 8);
}
inline uint32 READ_DWORD(uint8 *addr) {
return (addr[0]) + (addr[1] << 8) + (addr[2] << 16) + (addr[3] << 24);
}
inline void WRITE_WORD(uint8 *addr, uint16 data) {
addr[0] = data;
addr[1] = data >> 8;
}
#define bool8 uint8
#include "dsp4emu.c"
#undef bool8
};
void DSP4::init() {
}
void DSP4::enable() {
}
void DSP4::power() {
reset();
}
void DSP4::reset() {
DSP4i::InitDSP4();
}
uint8 DSP4::read(uint addr) {
addr &= 0xffff;
if(addr < 0xc000) {
DSP4i::dsp4_address = addr;
DSP4i::DSP4GetByte();
return DSP4i::dsp4_byte;
}
return 0x80;
}
void DSP4::write(uint addr, uint8 data) {
addr &= 0xffff;
if(addr < 0xc000) {
DSP4i::dsp4_address = addr;
DSP4i::dsp4_byte = data;
DSP4i::DSP4SetByte();
}
}

12
src/chip/dsp4/dsp4.h Normal file
View File

@@ -0,0 +1,12 @@
class DSP4 : public Memory {
public:
void init();
void enable();
void power();
void reset();
uint8 read (uint addr);
void write(uint addr, uint8 data);
};
extern DSP4 dsp4;

2146
src/chip/dsp4/dsp4emu.c Normal file

File diff suppressed because it is too large Load Diff

108
src/chip/dsp4/dsp4emu.h Normal file
View File

@@ -0,0 +1,108 @@
//DSP-4 emulator code
//Copyright (c) 2004-2006 Dreamer Nom, John Weidman, Kris Bleakley, Nach, z80 gaiden
#ifndef DSP4EMU_H
#define DSP4EMU_H
#undef TRUE
#undef FALSE
#define TRUE true
#define FALSE false
struct DSP4_t
{
bool8 waiting4command;
bool8 half_command;
uint16 command;
uint32 in_count;
uint32 in_index;
uint32 out_count;
uint32 out_index;
uint8 parameters[512];
uint8 output[512];
};
extern struct DSP4_t DSP4;
struct DSP4_vars_t
{
// op control
int8 DSP4_Logic; // controls op flow
// projection format
int16 lcv; // loop-control variable
int16 distance; // z-position into virtual world
int16 raster; // current raster line
int16 segments; // number of raster lines drawn
// 1.15.16 or 1.15.0 [sign, integer, fraction]
int32 world_x; // line of x-projection in world
int32 world_y; // line of y-projection in world
int32 world_dx; // projection line x-delta
int32 world_dy; // projection line y-delta
int16 world_ddx; // x-delta increment
int16 world_ddy; // y-delta increment
int32 world_xenv; // world x-shaping factor
int16 world_yofs; // world y-vertical scroll
int16 view_x1; // current viewer-x
int16 view_y1; // current viewer-y
int16 view_x2; // future viewer-x
int16 view_y2; // future viewer-y
int16 view_dx; // view x-delta factor
int16 view_dy; // view y-delta factor
int16 view_xofs1; // current viewer x-vertical scroll
int16 view_yofs1; // current viewer y-vertical scroll
int16 view_xofs2; // future viewer x-vertical scroll
int16 view_yofs2; // future viewer y-vertical scroll
int16 view_yofsenv; // y-scroll shaping factor
int16 view_turnoff_x; // road turnoff data
int16 view_turnoff_dx; // road turnoff delta factor
// drawing area
int16 viewport_cx; // x-center of viewport window
int16 viewport_cy; // y-center of render window
int16 viewport_left; // x-left of viewport
int16 viewport_right; // x-right of viewport
int16 viewport_top; // y-top of viewport
int16 viewport_bottom; // y-bottom of viewport
// sprite structure
int16 sprite_x; // projected x-pos of sprite
int16 sprite_y; // projected y-pos of sprite
int16 sprite_attr; // obj attributes
bool8 sprite_size; // sprite size: 8x8 or 16x16
int16 sprite_clipy; // visible line to clip pixels off
int16 sprite_count;
// generic projection variables designed for
// two solid polygons + two polygon sides
int16 poly_clipLf[2][2]; // left clip boundary
int16 poly_clipRt[2][2]; // right clip boundary
int16 poly_ptr[2][2]; // HDMA structure pointers
int16 poly_raster[2][2]; // current raster line below horizon
int16 poly_top[2][2]; // top clip boundary
int16 poly_bottom[2][2]; // bottom clip boundary
int16 poly_cx[2][2]; // center for left/right points
int16 poly_start[2]; // current projection points
int16 poly_plane[2]; // previous z-plane distance
// OAM
int16 OAM_attr[16]; // OAM (size,MSB) data
int16 OAM_index; // index into OAM table
int16 OAM_bits; // offset into OAM table
int16 OAM_RowMax; // maximum number of tiles per 8 aligned pixels (row)
int16 OAM_Row[32]; // current number of tiles per row
};
extern struct DSP4_vars_t DSP4_vars;
#endif

View File

@@ -1,7 +1,5 @@
#include "../../base.h"
OBC1 *obc1;
void OBC1::init() {}
void OBC1::enable() {}
@@ -10,81 +8,82 @@ void OBC1::power() {
}
void OBC1::reset() {
memset(cartridge.ram, 0xff, 0x2000);
status.baseptr = (cartridge.ram[0x1ff5] & 1) ? 0x1800 : 0x1c00;
status.address = (cartridge.ram[0x1ff6] & 0x7f);
status.shift = (cartridge.ram[0x1ff6] & 3) << 1;
for(uint i = 0x0000; i <= 0x1fff; i++) ram_write(i, 0xff);
status.baseptr = (ram_read(0x1ff5) & 1) ? 0x1800 : 0x1c00;
status.address = (ram_read(0x1ff6) & 0x7f);
status.shift = (ram_read(0x1ff6) & 3) << 1;
}
uint8 OBC1::read(uint16 addr) {
uint8 OBC1::read(uint addr) {
addr &= 0x1fff;
if((addr & 0x1ff8) != 0x1ff0) {
return cartridge.ram[addr];
}
if((addr & 0x1ff8) != 0x1ff0) return ram_read(addr);
switch(addr) {
case 0x1ff0:
return cartridge.ram[status.baseptr + (status.address << 2) + 0];
return ram_read(status.baseptr + (status.address << 2) + 0);
case 0x1ff1:
return cartridge.ram[status.baseptr + (status.address << 2) + 1];
return ram_read(status.baseptr + (status.address << 2) + 1);
case 0x1ff2:
return cartridge.ram[status.baseptr + (status.address << 2) + 2];
return ram_read(status.baseptr + (status.address << 2) + 2);
case 0x1ff3:
return cartridge.ram[status.baseptr + (status.address << 2) + 3];
return ram_read(status.baseptr + (status.address << 2) + 3);
case 0x1ff4:
return cartridge.ram[status.baseptr + (status.address >> 2) + 0x200];
return ram_read(status.baseptr + (status.address >> 2) + 0x200);
case 0x1ff5:
case 0x1ff6:
case 0x1ff7:
return cartridge.ram[addr];
return ram_read(addr);
}
//never used, blocks compiler warning
return 0x00;
return 0x00; //never used, avoids compiler warning
}
void OBC1::write(uint16 addr, uint8 data) {
void OBC1::write(uint addr, uint8 data) {
addr &= 0x1fff;
if((addr & 0x1ff8) != 0x1ff0) {
cartridge.ram[addr] = data;
return;
}
if((addr & 0x1ff8) != 0x1ff0) return ram_write(addr, data);
switch(addr) {
case 0x1ff0:
cartridge.ram[status.baseptr + (status.address << 2) + 0] = data;
ram_write(status.baseptr + (status.address << 2) + 0, data);
break;
case 0x1ff1:
cartridge.ram[status.baseptr + (status.address << 2) + 1] = data;
ram_write(status.baseptr + (status.address << 2) + 1, data);
break;
case 0x1ff2:
cartridge.ram[status.baseptr + (status.address << 2) + 2] = data;
ram_write(status.baseptr + (status.address << 2) + 2, data);
break;
case 0x1ff3:
cartridge.ram[status.baseptr + (status.address << 2) + 3] = data;
ram_write(status.baseptr + (status.address << 2) + 3, data);
break;
case 0x1ff4: {
uint8 temp;
temp = cartridge.ram[status.baseptr + (status.address >> 2) + 0x200];
temp = ram_read(status.baseptr + (status.address >> 2) + 0x200);
temp = (temp & ~(3 << status.shift)) | ((data & 3) << status.shift);
cartridge.ram[status.baseptr + (status.address >> 2) + 0x200] = temp;
ram_write(status.baseptr + (status.address >> 2) + 0x200, temp);
} break;
case 0x1ff5:
status.baseptr = (data & 1) ? 0x1800 : 0x1c00;
cartridge.ram[addr] = data;
ram_write(addr, data);
break;
case 0x1ff6:
status.address = (data & 0x7f);
status.shift = (data & 3) << 1;
cartridge.ram[addr] = data;
ram_write(addr, data);
break;
case 0x1ff7:
cartridge.ram[addr] = data;
ram_write(addr, data);
break;
}
}
uint8 OBC1::ram_read(uint addr) {
return memory::cartram.read(addr & 0x1fff);
}
void OBC1::ram_write(uint addr, uint8 data) {
memory::cartram.write(addr & 0x1fff, data);
}
OBC1::OBC1() {}
OBC1::~OBC1() {}

View File

@@ -1,20 +1,25 @@
class OBC1 {
class OBC1 : public Memory {
public:
struct {
uint16 address;
uint16 baseptr;
uint16 shift;
} status;
void init();
void enable();
void power();
void reset();
void init();
void enable();
void power();
void reset();
uint8 read (uint16 addr);
void write(uint16 addr, uint8 data);
uint8 read(uint addr);
void write(uint addr, uint8 data);
OBC1();
~OBC1();
private:
uint8 ram_read(uint addr);
void ram_write(uint addr, uint8 data);
struct {
uint16 address;
uint16 baseptr;
uint16 shift;
} status;
};
extern OBC1 *obc1;
extern OBC1 obc1;

View File

@@ -1,15 +1,11 @@
#include "../../base.h"
SDD1 *sdd1;
#include "sdd1emu.cpp"
void SDD1::init() {}
void SDD1::enable() {
for(int i = 0x4800; i <= 0x4807; i++) {
r_mem->set_mmio_mapper(i, this);
}
for(int i = 0x4800; i <= 0x4807; i++) memory::mmio.map(i, *this);
}
void SDD1::power() {
@@ -17,59 +13,80 @@ void SDD1::power() {
}
void SDD1::reset() {
sdd1.index[0] = 0x000000;
sdd1.index[1] = 0x100000;
sdd1.index[2] = 0x200000;
sdd1.index[3] = 0x300000;
for(int i=0;i<8;i++) {
sdd1.active[i] = false;
}
sdd1.dma_active = false;
regs.r4800 = 0x00;
regs.r4801 = 0x00;
regs.r4804 = 0x00;
regs.r4805 = 0x01;
regs.r4806 = 0x02;
regs.r4807 = 0x03;
bus.map(Bus::MapLinear, 0xc0, 0xcf, 0x0000, 0xffff, memory::cartrom, (regs.r4804 & 7) << 20);
bus.map(Bus::MapLinear, 0xd0, 0xdf, 0x0000, 0xffff, memory::cartrom, (regs.r4805 & 7) << 20);
bus.map(Bus::MapLinear, 0xe0, 0xef, 0x0000, 0xffff, memory::cartrom, (regs.r4806 & 7) << 20);
bus.map(Bus::MapLinear, 0xf0, 0xff, 0x0000, 0xffff, memory::cartrom, (regs.r4807 & 7) << 20);
}
uint32 SDD1::offset(uint32 addr) {
uint8 b = (addr >> 16) & 0xff;
if(b <= 0xbf)return 0;
b -= 0xc0; //b = 0x00-0x3f
b >>= 4; //b = 0-3
b &= 3; //bitmask
return sdd1.index[b] + (addr & 0x0fffff);
}
uint8 SDD1::mmio_read(uint16 addr) {
switch(addr) {
//>>20 == 0x100000 == 1mb
case 0x4804:return (sdd1.index[0] >> 20) & 7;
case 0x4805:return (sdd1.index[1] >> 20) & 7;
case 0x4806:return (sdd1.index[2] >> 20) & 7;
case 0x4807:return (sdd1.index[3] >> 20) & 7;
uint8 SDD1::mmio_read(uint addr) {
switch(addr & 0xffff) {
case 0x4804: return regs.r4804;
case 0x4805: return regs.r4805;
case 0x4806: return regs.r4806;
case 0x4807: return regs.r4807;
}
return r_cpu->regs.mdr;
return cpu.regs.mdr;
}
void SDD1::mmio_write(uint16 addr, uint8 data) {
switch(addr) {
case 0x4801:
for(int i = 0; i < 8; i++) {
sdd1.active[i] = !!(data & (1 << i));
}
break;
//<<20 == 0x100000 == 1mb
case 0x4804:sdd1.index[0] = (data & 7) << 20;break;
case 0x4805:sdd1.index[1] = (data & 7) << 20;break;
case 0x4806:sdd1.index[2] = (data & 7) << 20;break;
case 0x4807:sdd1.index[3] = (data & 7) << 20;break;
void SDD1::mmio_write(uint addr, uint8 data) {
switch(addr & 0xffff) {
case 0x4800: {
regs.r4800 = data;
} break;
case 0x4801: {
regs.r4801 = data;
} break;
case 0x4804: {
if(regs.r4804 != data) {
regs.r4804 = data;
bus.map(Bus::MapLinear, 0xc0, 0xcf, 0x0000, 0xffff,
memory::cartrom, (regs.r4804 & 7) << 20);
}
} break;
case 0x4805: {
if(regs.r4805 != data) {
regs.r4805 = data;
bus.map(Bus::MapLinear, 0xd0, 0xdf, 0x0000, 0xffff,
memory::cartrom, (regs.r4805 & 7) << 20);
}
} break;
case 0x4806: {
if(regs.r4806 != data) {
regs.r4806 = data;
bus.map(Bus::MapLinear, 0xe0, 0xef, 0x0000, 0xffff,
memory::cartrom, (regs.r4806 & 7) << 20);
}
} break;
case 0x4807: {
if(regs.r4807 != data) {
regs.r4807 = data;
bus.map(Bus::MapLinear, 0xf0, 0xff, 0x0000, 0xffff,
memory::cartrom, (regs.r4807 & 7) << 20);
}
} break;
}
}
void SDD1::dma_begin(uint8 channel, uint32 addr, uint16 length) {
if(sdd1.active[channel] == true) {
sdd1.active[channel] = false;
if(regs.r4800 & (1 << channel) && regs.r4801 & (1 << channel)) {
regs.r4801 &= ~(1 << channel);
sdd1.dma_active = true;
sdd1.buffer_index = 0;
sdd1.buffer_size = length;
@@ -82,9 +99,7 @@ bool SDD1::dma_active() {
}
uint8 SDD1::dma_read() {
if(--sdd1.buffer_size == 0) {
sdd1.dma_active = false;
}
if(--sdd1.buffer_size == 0) sdd1.dma_active = false;
//sdd1.buffer[] is 65536 bytes, and sdd1.buffer_index
//is of type uint16, so no buffer overflow is possible

View File

@@ -2,31 +2,38 @@
class SDD1 : public MMIO {
public:
SDD1emu sdd1emu;
void init();
void enable();
void power();
void reset();
struct {
uint32 index[4]; //memory mapping registers
uint8 buffer[65536]; //pointer to decompressed S-DD1 data,
//max. DMA length is 65536
uint16 buffer_index; //DMA read index into S-DD1 decompression buffer
uint16 buffer_size;
bool active[8]; //true when DMA channel should pass through S-DD1
bool dma_active;
} sdd1;
void init();
void enable();
void power();
void reset();
uint32 offset(uint32 addr);
uint8 mmio_read (uint addr);
void mmio_write(uint addr, uint8 data);
void dma_begin(uint8 channel, uint32 addr, uint16 length);
bool dma_active();
uint8 dma_read();
uint8 mmio_read (uint16 addr);
void mmio_write(uint16 addr, uint8 data);
void dma_begin(uint8 channel, uint32 addr, uint16 length);
bool dma_active();
uint8 dma_read();
SDD1();
private:
SDD1emu sdd1emu;
struct {
uint8 buffer[65536]; //pointer to decompressed S-DD1 data, max DMA length is 65536
uint16 buffer_index; //DMA read index into S-DD1 decompression buffer
uint16 buffer_size;
bool dma_active;
} sdd1;
struct {
uint8 r4800;
uint8 r4801;
uint8 r4804;
uint8 r4805;
uint8 r4806;
uint8 r4807;
} regs;
};
extern SDD1 *sdd1;
extern SDD1 sdd1;

View File

@@ -28,7 +28,7 @@ understood.
************************************************************************/
#define SDD1_read(__addr) (r_mem->read(__addr))
#define SDD1_read(__addr) (bus.read(__addr))
////////////////////////////////////////////////////

View File

@@ -52,8 +52,6 @@
#include "../../base.h"
SRTC *srtc;
void SRTC::set_time() {
time_t rawtime;
tm *t;
@@ -79,8 +77,8 @@ tm *t;
void SRTC::init() {}
void SRTC::enable() {
r_mem->set_mmio_mapper(0x2800, this);
r_mem->set_mmio_mapper(0x2801, this);
memory::mmio.map(0x2800, *this);
memory::mmio.map(0x2801, *this);
}
void SRTC::power() {
@@ -93,8 +91,8 @@ void SRTC::reset() {
srtc.mode = SRTC_READ;
}
uint8 SRTC::mmio_read(uint16 addr) {
switch(addr) {
uint8 SRTC::mmio_read(uint addr) {
switch(addr & 0xffff) {
case 0x2800: {
if(srtc.mode == SRTC_READ) {
@@ -118,7 +116,7 @@ uint8 SRTC::mmio_read(uint16 addr) {
}
return r_cpu->regs.mdr;
return cpu.regs.mdr;
}
//Please see notes above about the implementation of the S-RTC
@@ -126,8 +124,8 @@ uint8 SRTC::mmio_read(uint16 addr) {
//as reads will refresh the data array with the current system
//time. The write method is only here for the sake of faux
//emulation of the real hardware.
void SRTC::mmio_write(uint16 addr, uint8 data) {
switch(addr) {
void SRTC::mmio_write(uint addr, uint8 data) {
switch(addr & 0xffff) {
case 0x2800: {
} break;

View File

@@ -43,10 +43,10 @@ struct {
void power();
void reset();
uint8 mmio_read (uint16 addr);
void mmio_write(uint16 addr, uint8 data);
uint8 mmio_read (uint addr);
void mmio_write(uint addr, uint8 data);
SRTC();
};
extern SRTC *srtc;
extern SRTC srtc;

84
src/chip/st010/st010.cpp Normal file
View File

@@ -0,0 +1,84 @@
#include "../../base.h"
#include "st010_data.h"
#include "st010_op.cpp"
int16 ST010::sin(int16 theta) {
return sin_table[(theta >> 8) & 0xff];
}
int16 ST010::cos(int16 theta) {
return sin_table[((theta + 0x4000) >> 8) & 0xff];
}
uint8 ST010::readb(uint16 addr) {
return ram[addr & 0xfff];
}
uint16 ST010::readw(uint16 addr) {
return (readb(addr + 0) << 0) |
(readb(addr + 1) << 8);
}
uint32 ST010::readd(uint16 addr) {
return (readb(addr + 0) << 0) |
(readb(addr + 1) << 8) |
(readb(addr + 2) << 16) |
(readb(addr + 3) << 24);
}
void ST010::writeb(uint16 addr, uint8 data) {
ram[addr & 0xfff] = data;
}
void ST010::writew(uint16 addr, uint16 data) {
writeb(addr + 0, data);
writeb(addr + 1, data >> 8);
}
void ST010::writed(uint16 addr, uint32 data) {
writeb(addr + 0, data);
writeb(addr + 1, data >> 8);
writeb(addr + 2, data >> 16);
writeb(addr + 3, data >> 24);
}
//
void ST010::init() {
}
void ST010::enable() {
}
void ST010::power() {
reset();
}
void ST010::reset() {
memset(ram, 0x00, sizeof ram);
}
//
uint8 ST010::read(uint addr) {
return readb(addr);
}
void ST010::write(uint addr, uint8 data) {
writeb(addr, data);
if((addr & 0xfff) == 0x0021 && (data & 0x80)) {
switch(ram[0x0020]) {
case 0x01: op_01(); break;
case 0x02: op_02(); break;
case 0x03: op_03(); break;
case 0x04: op_04(); break;
case 0x05: op_05(); break;
case 0x06: op_06(); break;
case 0x07: op_07(); break;
case 0x08: op_08(); break;
}
ram[0x0021] &= ~0x80;
}
}

42
src/chip/st010/st010.h Normal file
View File

@@ -0,0 +1,42 @@
class ST010 : public Memory {
public:
void init();
void enable();
void power();
void reset();
uint8 read (uint addr);
void write(uint addr, uint8 data);
private:
uint8 ram[0x1000];
static const int16 sin_table[256];
static const int16 mode7_scale[176];
static const uint8 arctan[32][32];
//interfaces to sin table
int16 sin(int16 theta);
int16 cos(int16 theta);
//interfaces to ram buffer
uint8 readb (uint16 addr);
uint16 readw (uint16 addr);
uint32 readd (uint16 addr);
void writeb(uint16 addr, uint8 data);
void writew(uint16 addr, uint16 data);
void writed(uint16 addr, uint32 data);
//opcodes
void op_01();
void op_02();
void op_03();
void op_04();
void op_05();
void op_06();
void op_07();
void op_08();
void op_01(int16 x0, int16 y0, int16 &x1, int16 &y1, int16 &quadrant, int16 &theta);
};
extern ST010 st010;

126
src/chip/st010/st010_data.h Normal file
View File

@@ -0,0 +1,126 @@
const int16 ST010::sin_table[256] = {
0x0000, 0x0324, 0x0648, 0x096a, 0x0c8c, 0x0fab, 0x12c8, 0x15e2,
0x18f9, 0x1c0b, 0x1f1a, 0x2223, 0x2528, 0x2826, 0x2b1f, 0x2e11,
0x30fb, 0x33df, 0x36ba, 0x398c, 0x3c56, 0x3f17, 0x41ce, 0x447a,
0x471c, 0x49b4, 0x4c3f, 0x4ebf, 0x5133, 0x539b, 0x55f5, 0x5842,
0x5a82, 0x5cb3, 0x5ed7, 0x60eb, 0x62f1, 0x64e8, 0x66cf, 0x68a6,
0x6a6d, 0x6c23, 0x6dc9, 0x6f5e, 0x70e2, 0x7254, 0x73b5, 0x7504,
0x7641, 0x776b, 0x7884, 0x7989, 0x7a7c, 0x7b5c, 0x7c29, 0x7ce3,
0x7d89, 0x7e1d, 0x7e9c, 0x7f09, 0x7f61, 0x7fa6, 0x7fd8, 0x7ff5,
0x7fff, 0x7ff5, 0x7fd8, 0x7fa6, 0x7f61, 0x7f09, 0x7e9c, 0x7e1d,
0x7d89, 0x7ce3, 0x7c29, 0x7b5c, 0x7a7c, 0x7989, 0x7884, 0x776b,
0x7641, 0x7504, 0x73b5, 0x7254, 0x70e2, 0x6f5e, 0x6dc9, 0x6c23,
0x6a6d, 0x68a6, 0x66cf, 0x64e8, 0x62f1, 0x60eb, 0x5ed7, 0x5cb3,
0x5a82, 0x5842, 0x55f5, 0x539b, 0x5133, 0x4ebf, 0x4c3f, 0x49b4,
0x471c, 0x447a, 0x41ce, 0x3f17, 0x3c56, 0x398c, 0x36ba, 0x33df,
0x30fb, 0x2e11, 0x2b1f, 0x2826, 0x2528, 0x2223, 0x1f1a, 0x1c0b,
0x18f8, 0x15e2, 0x12c8, 0x0fab, 0x0c8c, 0x096a, 0x0648, 0x0324,
0x0000, -0x0324, -0x0648, -0x096b, -0x0c8c, -0x0fab, -0x12c8, -0x15e2,
-0x18f9, -0x1c0b, -0x1f1a, -0x2223, -0x2528, -0x2826, -0x2b1f, -0x2e11,
-0x30fb, -0x33df, -0x36ba, -0x398d, -0x3c56, -0x3f17, -0x41ce, -0x447a,
-0x471c, -0x49b4, -0x4c3f, -0x4ebf, -0x5133, -0x539b, -0x55f5, -0x5842,
-0x5a82, -0x5cb3, -0x5ed7, -0x60ec, -0x62f1, -0x64e8, -0x66cf, -0x68a6,
-0x6a6d, -0x6c23, -0x6dc9, -0x6f5e, -0x70e2, -0x7254, -0x73b5, -0x7504,
-0x7641, -0x776b, -0x7884, -0x7989, -0x7a7c, -0x7b5c, -0x7c29, -0x7ce3,
-0x7d89, -0x7e1d, -0x7e9c, -0x7f09, -0x7f61, -0x7fa6, -0x7fd8, -0x7ff5,
-0x7fff, -0x7ff5, -0x7fd8, -0x7fa6, -0x7f61, -0x7f09, -0x7e9c, -0x7e1d,
-0x7d89, -0x7ce3, -0x7c29, -0x7b5c, -0x7a7c, -0x7989, -0x7883, -0x776b,
-0x7641, -0x7504, -0x73b5, -0x7254, -0x70e2, -0x6f5e, -0x6dc9, -0x6c23,
-0x6a6d, -0x68a6, -0x66cf, -0x64e8, -0x62f1, -0x60eb, -0x5ed7, -0x5cb3,
-0x5a82, -0x5842, -0x55f5, -0x539a, -0x5133, -0x4ebf, -0x4c3f, -0x49b3,
-0x471c, -0x447a, -0x41cd, -0x3f17, -0x3c56, -0x398c, -0x36b9, -0x33de,
-0x30fb, -0x2e10, -0x2b1f, -0x2826, -0x2527, -0x2223, -0x1f19, -0x1c0b,
-0x18f8, -0x15e2, -0x12c8, -0x0fab, -0x0c8b, -0x096a, -0x0647, -0x0324
};
const int16 ST010::mode7_scale[176] = {
0x0380, 0x0325, 0x02da, 0x029c, 0x0268, 0x023b, 0x0215, 0x01f3,
0x01d5, 0x01bb, 0x01a3, 0x018e, 0x017b, 0x016a, 0x015a, 0x014b,
0x013e, 0x0132, 0x0126, 0x011c, 0x0112, 0x0109, 0x0100, 0x00f8,
0x00f0, 0x00e9, 0x00e3, 0x00dc, 0x00d6, 0x00d1, 0x00cb, 0x00c6,
0x00c1, 0x00bd, 0x00b8, 0x00b4, 0x00b0, 0x00ac, 0x00a8, 0x00a5,
0x00a2, 0x009e, 0x009b, 0x0098, 0x0095, 0x0093, 0x0090, 0x008d,
0x008b, 0x0088, 0x0086, 0x0084, 0x0082, 0x0080, 0x007e, 0x007c,
0x007a, 0x0078, 0x0076, 0x0074, 0x0073, 0x0071, 0x006f, 0x006e,
0x006c, 0x006b, 0x0069, 0x0068, 0x0067, 0x0065, 0x0064, 0x0063,
0x0062, 0x0060, 0x005f, 0x005e, 0x005d, 0x005c, 0x005b, 0x005a,
0x0059, 0x0058, 0x0057, 0x0056, 0x0055, 0x0054, 0x0053, 0x0052,
0x0051, 0x0051, 0x0050, 0x004f, 0x004e, 0x004d, 0x004d, 0x004c,
0x004b, 0x004b, 0x004a, 0x0049, 0x0048, 0x0048, 0x0047, 0x0047,
0x0046, 0x0045, 0x0045, 0x0044, 0x0044, 0x0043, 0x0042, 0x0042,
0x0041, 0x0041, 0x0040, 0x0040, 0x003f, 0x003f, 0x003e, 0x003e,
0x003d, 0x003d, 0x003c, 0x003c, 0x003b, 0x003b, 0x003a, 0x003a,
0x003a, 0x0039, 0x0039, 0x0038, 0x0038, 0x0038, 0x0037, 0x0037,
0x0036, 0x0036, 0x0036, 0x0035, 0x0035, 0x0035, 0x0034, 0x0034,
0x0034, 0x0033, 0x0033, 0x0033, 0x0032, 0x0032, 0x0032, 0x0031,
0x0031, 0x0031, 0x0030, 0x0030, 0x0030, 0x0030, 0x002f, 0x002f,
0x002f, 0x002e, 0x002e, 0x002e, 0x002e, 0x002d, 0x002d, 0x002d,
0x002d, 0x002c, 0x002c, 0x002c, 0x002c, 0x002b, 0x002b, 0x002b
};
const uint8 ST010::arctan[32][32] = {
{ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80 },
{ 0x80, 0xa0, 0xad, 0xb3, 0xb6, 0xb8, 0xb9, 0xba, 0xbb, 0xbb, 0xbc, 0xbc, 0xbd, 0xbd, 0xbd, 0xbd,
0xbd, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbf, 0xbf, 0xbf, 0xbf },
{ 0x80, 0x93, 0xa0, 0xa8, 0xad, 0xb0, 0xb3, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xb9, 0xba, 0xba, 0xbb,
0xbb, 0xbb, 0xbb, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd },
{ 0x80, 0x8d, 0x98, 0xa0, 0xa6, 0xaa, 0xad, 0xb0, 0xb1, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb7, 0xb8,
0xb8, 0xb9, 0xb9, 0xba, 0xba, 0xba, 0xba, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbc, 0xbc, 0xbc, 0xbc },
{ 0x80, 0x8a, 0x93, 0x9a, 0xa0, 0xa5, 0xa8, 0xab, 0xad, 0xaf, 0xb0, 0xb2, 0xb3, 0xb4, 0xb5, 0xb5,
0xb6, 0xb7, 0xb7, 0xb8, 0xb8, 0xb8, 0xb9, 0xb9, 0xb9, 0xba, 0xba, 0xba, 0xba, 0xba, 0xbb, 0xbb },
{ 0x80, 0x88, 0x90, 0x96, 0x9b, 0xa0, 0xa4, 0xa7, 0xa9, 0xab, 0xad, 0xaf, 0xb0, 0xb1, 0xb2, 0xb3,
0xb4, 0xb4, 0xb5, 0xb6, 0xb6, 0xb6, 0xb7, 0xb7, 0xb8, 0xb8, 0xb8, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9 },
{ 0x80, 0x87, 0x8d, 0x93, 0x98, 0x9c, 0xa0, 0xa3, 0xa6, 0xa8, 0xaa, 0xac, 0xad, 0xae, 0xb0, 0xb0,
0xb1, 0xb2, 0xb3, 0xb4, 0xb4, 0xb5, 0xb5, 0xb6, 0xb6, 0xb6, 0xb7, 0xb7, 0xb7, 0xb8, 0xb8, 0xb8 },
{ 0x80, 0x86, 0x8b, 0x90, 0x95, 0x99, 0x9d, 0xa0, 0xa3, 0xa5, 0xa7, 0xa9, 0xaa, 0xac, 0xad, 0xae,
0xaf, 0xb0, 0xb1, 0xb2, 0xb2, 0xb3, 0xb3, 0xb4, 0xb4, 0xb5, 0xb5, 0xb6, 0xb6, 0xb6, 0xb7, 0xb7 },
{ 0x80, 0x85, 0x8a, 0x8f, 0x93, 0x97, 0x9a, 0x9d, 0xa0, 0xa2, 0xa5, 0xa6, 0xa8, 0xaa, 0xab, 0xac,
0xad, 0xae, 0xaf, 0xb0, 0xb0, 0xb1, 0xb2, 0xb2, 0xb3, 0xb3, 0xb4, 0xb4, 0xb5, 0xb5, 0xb5, 0xb5 },
{ 0x80, 0x85, 0x89, 0x8d, 0x91, 0x95, 0x98, 0x9b, 0x9e, 0xa0, 0xa0, 0xa4, 0xa6, 0xa7, 0xa9, 0xaa,
0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb0, 0xb1, 0xb1, 0xb2, 0xb2, 0xb3, 0xb3, 0xb4, 0xb4, 0xb4 },
{ 0x80, 0x84, 0x88, 0x8c, 0x90, 0x93, 0x96, 0x99, 0x9b, 0x9e, 0xa0, 0xa2, 0xa4, 0xa5, 0xa7, 0xa8,
0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xaf, 0xb0, 0xb0, 0xb1, 0xb2, 0xb2, 0xb2, 0xb3, 0xb3 },
{ 0x80, 0x84, 0x87, 0x8b, 0x8e, 0x91, 0x94, 0x97, 0x9a, 0x9c, 0x9e, 0xa0, 0xa2, 0xa3, 0xa5, 0xa6,
0xa7, 0xa9, 0xaa, 0xab, 0xac, 0xac, 0xad, 0xae, 0xae, 0xaf, 0xb0, 0xb0, 0xb1, 0xb1, 0xb2, 0xb2 },
{ 0x80, 0x83, 0x87, 0x8a, 0x8d, 0x90, 0x93, 0x96, 0x98, 0x9a, 0x9c, 0x9e, 0xa0, 0xa2, 0xa3, 0xa5,
0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xac, 0xad, 0xae, 0xae, 0xaf, 0xb0, 0xb0, 0xb0, 0xb1 },
{ 0x80, 0x83, 0x86, 0x89, 0x8c, 0x8f, 0x92, 0x94, 0x96, 0x99, 0x9b, 0x9d, 0x9e, 0xa0, 0xa2, 0xa3,
0xa4, 0xa5, 0xa7, 0xa8, 0xa9, 0xa9, 0xaa, 0xab, 0xac, 0xac, 0xad, 0xae, 0xae, 0xaf, 0xaf, 0xb0 },
{ 0x80, 0x83, 0x86, 0x89, 0x8b, 0x8e, 0x90, 0x93, 0x95, 0x97, 0x99, 0x9b, 0x9d, 0x9e, 0xa0, 0xa1,
0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xaa, 0xab, 0xac, 0xad, 0xad, 0xae, 0xae, 0xaf },
{ 0x80, 0x83, 0x85, 0x88, 0x8b, 0x8d, 0x90, 0x92, 0x94, 0x96, 0x98, 0x9a, 0x9b, 0x9d, 0x9f, 0xa0,
0xa1, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa8, 0xa9, 0xaa, 0xab, 0xab, 0xac, 0xad, 0xad, 0xae },
{ 0x80, 0x83, 0x85, 0x88, 0x8a, 0x8c, 0x8f, 0x91, 0x93, 0x95, 0x97, 0x99, 0x9a, 0x9c, 0x9d, 0x9f,
0xa0, 0xa1, 0xa2, 0xa3, 0xa5, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xaa, 0xab, 0xab, 0xac, 0xad },
{ 0x80, 0x82, 0x85, 0x87, 0x89, 0x8c, 0x8e, 0x90, 0x92, 0x94, 0x96, 0x97, 0x99, 0x9b, 0x9c, 0x9d,
0x9f, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa8, 0xa9, 0xaa, 0xaa, 0xab, 0xac },
{ 0x80, 0x82, 0x85, 0x87, 0x89, 0x8b, 0x8d, 0x8f, 0x91, 0x93, 0x95, 0x96, 0x98, 0x99, 0x9b, 0x9c,
0x9e, 0x9f, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa7, 0xa8, 0xa9, 0xa9, 0xaa, 0xab },
{ 0x80, 0x82, 0x84, 0x86, 0x88, 0x8a, 0x8c, 0x8e, 0x90, 0x92, 0x94, 0x95, 0x97, 0x98, 0x9a, 0x9b,
0x9d, 0x9e, 0x9f, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa6, 0xa7, 0xa8, 0xa8, 0xa9, 0xaa },
{ 0x80, 0x82, 0x84, 0x86, 0x88, 0x8a, 0x8c, 0x8e, 0x90, 0x91, 0x93, 0x94, 0x96, 0x97, 0x99, 0x9a,
0x9b, 0x9d, 0x9e, 0x9f, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa5, 0xa6, 0xa7, 0xa7, 0xa8, 0xa9 },
{ 0x80, 0x82, 0x84, 0x86, 0x88, 0x8a, 0x8b, 0x8d, 0x8f, 0x90, 0x92, 0x94, 0x95, 0x97, 0x98, 0x99,
0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa4, 0xa5, 0xa6, 0xa6, 0xa7, 0xa8 },
{ 0x80, 0x82, 0x84, 0x86, 0x87, 0x89, 0x8b, 0x8d, 0x8e, 0x90, 0x91, 0x93, 0x94, 0x96, 0x97, 0x98,
0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xa0, 0xa1, 0xa2, 0xa3, 0xa3, 0xa4, 0xa5, 0xa6, 0xa6, 0xa7 },
{ 0x80, 0x82, 0x84, 0x85, 0x87, 0x89, 0x8a, 0x8c, 0x8e, 0x8f, 0x91, 0x92, 0x94, 0x95, 0x96, 0x98,
0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xa0, 0xa1, 0xa2, 0xa2, 0xa3, 0xa4, 0xa5, 0xa5, 0xa6 },
{ 0x80, 0x82, 0x83, 0x85, 0x87, 0x88, 0x8a, 0x8c, 0x8d, 0x8f, 0x90, 0x92, 0x93, 0x94, 0x96, 0x97,
0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xa0, 0xa1, 0xa2, 0xa2, 0xa3, 0xa4, 0xa5, 0xa5 },
{ 0x80, 0x82, 0x83, 0x85, 0x86, 0x88, 0x8a, 0x8b, 0x8d, 0x8e, 0x90, 0x91, 0x92, 0x94, 0x95, 0x96,
0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xa0, 0xa1, 0xa2, 0xa2, 0xa3, 0xa4, 0xa4 },
{ 0x80, 0x82, 0x83, 0x85, 0x86, 0x88, 0x89, 0x8b, 0x8c, 0x8e, 0x8f, 0x90, 0x92, 0x93, 0x94, 0x95,
0x96, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9e, 0x9f, 0xa0, 0xa1, 0xa2, 0xa2, 0xa3, 0xa4 },
{ 0x80, 0x82, 0x83, 0x85, 0x86, 0x87, 0x89, 0x8a, 0x8c, 0x8d, 0x8e, 0x90, 0x91, 0x92, 0x93, 0x95,
0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9e, 0x9f, 0xa0, 0xa1, 0xa1, 0xa2, 0xa3 },
{ 0x80, 0x81, 0x83, 0x84, 0x86, 0x87, 0x89, 0x8a, 0x8b, 0x8d, 0x8e, 0x8f, 0x90, 0x92, 0x93, 0x94,
0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9e, 0x9f, 0xa0, 0xa1, 0xa1, 0xa2 },
{ 0x80, 0x81, 0x83, 0x84, 0x86, 0x87, 0x88, 0x8a, 0x8b, 0x8c, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93,
0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0x9f, 0xa0, 0xa1, 0xa1 },
{ 0x80, 0x81, 0x83, 0x84, 0x85, 0x87, 0x88, 0x89, 0x8b, 0x8c, 0x8d, 0x8e, 0x90, 0x91, 0x92, 0x93,
0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0x9f, 0xa0, 0xa1 },
{ 0x80, 0x81, 0x83, 0x84, 0x85, 0x87, 0x88, 0x89, 0x8a, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92,
0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9c, 0x9d, 0x9e, 0x9f, 0x9f, 0xa0 }
};

257
src/chip/st010/st010_op.cpp Normal file
View File

@@ -0,0 +1,257 @@
//ST-010 emulation code - Copyright (C) 2003 The Dumper, Matthew Kendora, Overload, Feather
//bsnes port - Copyright (C) 2007 byuu
void ST010::op_01(int16 x0, int16 y0, int16 &x1, int16 &y1, int16 &quadrant, int16 &theta) {
if((x0 < 0) && (y0 < 0)) {
x1 = -x0;
y1 = -y0;
quadrant = -0x8000;
} else if(x0 < 0) {
x1 = y0;
y1 = -x0;
quadrant = -0x4000;
} else if(y0 < 0) {
x1 = -y0;
y1 = x0;
quadrant = 0x4000;
} else {
x1 = x0;
y1 = y0;
quadrant = 0x0000;
}
while((x1 > 0x1f) || (y1 > 0x1f)) {
if(x1 > 1) { x1 >>= 1; }
if(y1 > 1) { y1 >>= 1; }
}
if(y1 == 0) { quadrant += 0x4000; }
theta = (arctan[y1][x1] << 8) ^ quadrant;
}
//
void ST010::op_01() {
int16 x0 = readw(0x0000);
int16 y0 = readw(0x0002);
int16 x1, y1, quadrant, theta;
op_01(x0, y0, x1, y1, quadrant, theta);
writew(0x0000, x1);
writew(0x0002, y1);
writew(0x0004, quadrant);
//writew(0x0006, y0); //Overload's docs note this write occurs, SNES9x disagrees
writew(0x0010, theta);
}
void ST010::op_02() {
int16 positions = readw(0x0024);
uint16 *places = (uint16*)(ram + 0x0040);
uint16 *drivers = (uint16*)(ram + 0x0080);
bool sorted;
uint16 temp;
if(positions > 1) {
do {
sorted = true;
for(int i = 0; i < positions - 1; i++) {
if(places[i] < places[i + 1]) {
temp = places[i + 1];
places[i + 1] = places[i];
places[i] = temp;
temp = drivers[i + 1];
drivers[i + 1] = drivers[i];
drivers[i] = temp;
sorted = false;
}
}
positions--;
} while(!sorted);
}
}
void ST010::op_03() {
int16 x0 = readw(0x0000);
int16 y0 = readw(0x0002);
int16 multiplier = readw(0x0004);
int32 x1, y1;
x1 = x0 * multiplier << 1;
y1 = y0 * multiplier << 1;
writed(0x0010, x1);
writed(0x0014, y1);
}
void ST010::op_04() {
int16 x = readw(0x0000);
int16 y = readw(0x0002);
int16 square;
//calculate the vector length of (x,y)
square = (int16)sqrt((double)(y * y + x * x));
writew(0x0010, square);
}
void ST010::op_05() {
int32 dx, dy;
int16 a1, b1, c1;
uint16 o1;
bool wrap = false;
//target (x,y) coordinates
int16 ypos_max = readw(0x00c0);
int16 xpos_max = readw(0x00c2);
//current coordinates and direction
int32 ypos = readd(0x00c4);
int32 xpos = readd(0x00c8);
uint16 rot = readw(0x00cc);
//physics
uint16 speed = readw(0x00d4);
uint16 accel = readw(0x00d6);
uint16 speed_max = readw(0x00d8);
//special condition acknowledgement
int16 system = readw(0x00da);
int16 flags = readw(0x00dc);
//new target coordinates
int16 ypos_new = readw(0x00de);
int16 xpos_new = readw(0x00e0);
//mask upper bit
xpos_new &= 0x7fff;
//get the current distance
dx = xpos_max - (xpos >> 16);
dy = ypos_max - (ypos >> 16);
//quirk: clear and move in9
writew(0x00d2, 0xffff);
writew(0x00da, 0x0000);
//grab the target angle
op_01(dy, dx, a1, b1, c1, (int16&)o1);
//check for wrapping
if(abs(o1 - rot) > 0x8000) {
o1 += 0x8000;
rot += 0x8000;
wrap = true;
}
uint16 old_speed = speed;
//special case
if(abs(o1 - rot) == 0x8000) {
speed = 0x100;
}
//slow down for sharp curves
else if(abs(o1 - rot) >= 0x1000) {
uint32 slow = abs(o1 - rot);
slow >>= 4; //scaling
speed -= slow;
}
//otherwise accelerate
else {
speed += accel;
if(speed > speed_max) {
speed = speed_max; //clip speed
}
}
//prevent negative/positive overflow
if(abs(old_speed - speed) > 0x8000) {
if(old_speed < speed) { speed = 0; }
else speed = 0xff00;
}
//adjust direction by so many degrees
//be careful of negative adjustments
if((o1 > rot && (o1 - rot) > 0x80) || (o1 < rot && (rot - o1) >= 0x80)) {
if(o1 < rot) { rot -= 0x280; }
else if(o1 > rot) { rot += 0x280; }
}
//turn of wrapping
if(wrap) { rot -= 0x8000; }
//now check the distances (store for later)
dx = (xpos_max << 16) - xpos;
dy = (ypos_max << 16) - ypos;
dx >>= 16;
dy >>= 16;
//if we're in so many units of the target, signal it
if((system && (dy <= 6 && dy >= -8) && (dx <= 126 && dx >= -128)) || (!system && (dx <= 6 && dx >= -8) && (dy <= 126 && dy >= -128))) {
//announce our new destination and flag it
xpos_max = xpos_new & 0x7fff;
ypos_max = ypos_new;
flags |= 0x08;
}
//update position
xpos -= (cos(rot) * 0x400 >> 15) * (speed >> 8) << 1;
ypos -= (sin(rot) * 0x400 >> 15) * (speed >> 8) << 1;
//quirk: mask upper byte
xpos &= 0x1fffffff;
ypos &= 0x1fffffff;
writew(0x00c0, ypos_max);
writew(0x00c2, xpos_max);
writed(0x00c4, ypos);
writed(0x00c8, xpos);
writew(0x00cc, rot);
writew(0x00d4, speed);
writew(0x00dc, flags);
}
void ST010::op_06() {
int16 multiplicand = readw(0x0000);
int16 multiplier = readw(0x0002);
int32 product;
product = multiplicand * multiplier << 1;
writed(0x0010, product);
}
void ST010::op_07() {
int16 theta = readw(0x0000);
int16 data;
for(int i = 0, offset = 0; i < 176; i++) {
data = mode7_scale[i] * cos(theta) >> 15;
writew(0x00f0 + offset, data);
writew(0x0510 + offset, data);
data = mode7_scale[i] * sin(theta) >> 15;
writew(0x0250 + offset, data);
if(data) { data = ~data; }
writew(0x03b0 + offset, data);
offset += 2;
}
}
void ST010::op_08() {
int16 x0 = readw(0x0000);
int16 y0 = readw(0x0002);
int16 theta = readw(0x0004);
int16 x1, y1;
x1 = (y0 * sin(theta) >> 15) + (x0 * cos(theta) >> 15);
y1 = (y0 * cos(theta) >> 15) - (x0 * sin(theta) >> 15);
writew(0x0010, x1);
writew(0x0012, y1);
}

View File

@@ -0,0 +1,3 @@
void op_unknown() {}
void op_00();

View File

@@ -0,0 +1,7 @@
//STOP
void SuperFX::op_00() {
regs.sfr.g = 0;
regs.sfr.b = 0;
regs.sfr.alt1 = 0;
regs.sfr.alt2 = 0;
}

View File

@@ -0,0 +1,66 @@
uint8 SuperFX::mmio_read(uint addr) {
addr &= 0xffff;
switch(addr) {
case 0x3000: return regs.r0.l;
case 0x3001: return regs.r0.h;
case 0x3002: return regs.r1.l;
case 0x3003: return regs.r1.h;
case 0x3004: return regs.r2.l;
case 0x3005: return regs.r2.h;
case 0x3006: return regs.r3.l;
case 0x3007: return regs.r3.h;
case 0x3008: return regs.r4.l;
case 0x3009: return regs.r4.h;
case 0x300a: return regs.r5.l;
case 0x300b: return regs.r5.h;
case 0x300c: return regs.r6.l;
case 0x300d: return regs.r6.h;
case 0x300e: return regs.r7.l;
case 0x300f: return regs.r7.h;
case 0x3010: return regs.r8.l;
case 0x3011: return regs.r8.h;
case 0x3012: return regs.r9.l;
case 0x3013: return regs.r9.h;
case 0x3014: return regs.r10.l;
case 0x3015: return regs.r10.h;
case 0x3016: return regs.r11.l;
case 0x3017: return regs.r11.h;
case 0x3018: return regs.r12.l;
case 0x3019: return regs.r12.h;
case 0x301a: return regs.r13.l;
case 0x301b: return regs.r13.h;
case 0x301c: return regs.r14.l;
case 0x301d: return regs.r14.h;
case 0x301e: return regs.r15.l;
case 0x301f: return regs.r15.h;
//0x3020 - 0x302f unused
case 0x3030: return regs.sfr;
case 0x3031: return regs.sfr >> 8;
case 0x3032: return 0x00; //unused
case 0x3033: return 0x00; //BRAMR (write only)
case 0x3034: return regs.pbr;
case 0x3035: return 0x00; //unused
case 0x3036: return regs.rombr;
case 0x3037: return 0x00; //CFGR (write only)
case 0x3038: return 0x00; //SCBR (write only)
case 0x3039: return 0x00; //CLSR (write only)
case 0x303a: return 0x00; //SCMR (write only)
case 0x303b: return regs.vcr;
case 0x303c: return regs.rambr;
case 0x303d: return 0x00; //unused
case 0x303e: return regs.cbr;
case 0x303f: return regs.cbr >> 8;
//0x3040 - 0x30ff unused
}
if(addr >= 0x3100 && addr <= 0x32ff) {
return cache[addr - 0x3100];
}
return 0x00;
}

View File

@@ -0,0 +1,65 @@
void SuperFX::mmio_write(uint addr, uint8 data) {
addr &= 0xffff;
switch(addr) {
case 0x3000: regs.r0.l = data; return;
case 0x3001: regs.r0.h = data; return;
case 0x3002: regs.r1.l = data; return;
case 0x3003: regs.r1.h = data; return;
case 0x3004: regs.r2.l = data; return;
case 0x3005: regs.r2.h = data; return;
case 0x3006: regs.r3.l = data; return;
case 0x3007: regs.r3.h = data; return;
case 0x3008: regs.r4.l = data; return;
case 0x3009: regs.r4.h = data; return;
case 0x300a: regs.r5.l = data; return;
case 0x300b: regs.r5.h = data; return;
case 0x300c: regs.r6.l = data; return;
case 0x300d: regs.r6.h = data; return;
case 0x300e: regs.r7.l = data; return;
case 0x300f: regs.r7.h = data; return;
case 0x3010: regs.r8.l = data; return;
case 0x3011: regs.r8.h = data; return;
case 0x3012: regs.r9.l = data; return;
case 0x3013: regs.r9.h = data; return;
case 0x3014: regs.r10.l = data; return;
case 0x3015: regs.r10.h = data; return;
case 0x3016: regs.r11.l = data; return;
case 0x3017: regs.r11.h = data; return;
case 0x3018: regs.r12.l = data; return;
case 0x3019: regs.r12.h = data; return;
case 0x301a: regs.r13.l = data; return;
case 0x301b: regs.r13.h = data; return;
case 0x301c: regs.r14.l = data; return;
case 0x301d: regs.r14.h = data; return;
case 0x301e: regs.r15.l = data; return;
case 0x301f: regs.r15.h = data; return;
//0x3020 - 0x302f unused
case 0x3030: regs.sfr.l = data & 0x7e; return; //mask invalid bits
case 0x3031: regs.sfr.h = data & 0x9f; return; //mask invalid bits
case 0x3032: return; //unused
case 0x3033: regs.bramr = data; return;
case 0x3034: regs.pbr = data; return;
case 0x3035: return; //unused
case 0x3036: return; //ROMBR (read only)
case 0x3037: regs.cfgr = data; return;
case 0x3038: regs.scbr = data; return;
case 0x3039: regs.clsr = data; return;
case 0x303a: regs.scmr = data; return;
case 0x303b: return; //VCR (read only)
case 0x303c: return; //RAMBR (read only)
case 0x303d: return; //unused
case 0x303e: return; //CBR low (read only)
case 0x303f: return; //CBR high (read only)
//0x3040 - 0x30ff unused
}
if(addr >= 0x3100 && addr <= 0x32ff) {
cache[addr - 0x3100] = data;
return;
}
}

174
src/chip/superfx/regs.h Normal file
View File

@@ -0,0 +1,174 @@
struct Reg16 {
union {
uint16 w;
struct { uint8 order_lsb2(l, h); };
};
inline operator unsigned() const { return w; }
inline unsigned operator=(const unsigned i) { return w = i; }
Reg16() : w(0) {}
};
template<int bit> struct RegFlag8 {
uint8 data;
inline operator bool() const { return data & bit; }
inline bool operator=(const bool i) { i ? data |= bit : data &= ~bit; return i; }
};
template<int bit> struct RegFlag16 {
uint16 data;
inline operator bool() const { return data & bit; }
inline bool operator=(const bool i) { i ? data |= bit : data &= ~bit; return i; }
};
struct SFR {
union {
uint16 w;
struct { uint8 order_lsb2(l, h); };
RegFlag16<0x0002> z; //zero flag
RegFlag16<0x0004> c; //carry flag
RegFlag16<0x0008> s; //sign flag
RegFlag16<0x0010> v; //overflow flag
RegFlag16<0x0020> g; //go flag
RegFlag16<0x0040> r; //ROM read using r14 flag
RegFlag16<0x0100> alt1; //alternate instruction 1 flag
RegFlag16<0x0200> alt2; //alternate instruction 2 flag
RegFlag16<0x0400> il; //immediate lower 8-bit flag
RegFlag16<0x0800> ih; //immediate upper 8-bit flag
RegFlag16<0x1000> b; //WITH instruction flag
RegFlag16<0x8000> irq; //interrupt flag
};
inline operator unsigned() const { return w & 0x9f7e; } //invalid flag bits always return 0 when read
inline unsigned operator=(const unsigned i) { return w = i & 0x9f7e; }
SFR() : w(0) {}
};
struct RAMBR {
union {
uint8 b;
RegFlag8<0x01> bank;
};
inline operator unsigned() const { return b & 0x01; }
inline unsigned operator=(const unsigned i) { return b = i & 0x01; }
RAMBR() : b(0) {}
};
struct CBR {
uint16 w;
inline operator unsigned() const { return w & 0xfff0; }
inline unsigned operator=(const unsigned i) { return w = i & 0xfff0; }
CBR() : w(0) {}
};
struct SCMR {
union {
uint8 b;
RegFlag8<0x01> md0; //color mode low
RegFlag8<0x02> md1; //color mode high
RegFlag8<0x04> ht0; //height low
RegFlag8<0x08> ran; //ram enable
RegFlag8<0x10> ron; //rom enable
RegFlag8<0x20> ht1; //height high
};
inline operator unsigned() const { return b; }
inline unsigned operator=(const unsigned i) { return b = i; }
SCMR() : b(0) {}
};
struct BRAMR {
union {
uint8 b;
RegFlag8<0x01> flag;
};
inline operator unsigned() const { return b; }
inline unsigned operator=(const unsigned i) { return b = i; }
BRAMR() : b(0) {}
};
struct CFGR {
union {
uint8 b;
RegFlag8<0x20> ms0; //multiplier speed selection
RegFlag8<0x80> irq; //irq mask flag
};
inline operator unsigned() const { return b; }
inline unsigned operator=(const unsigned i) { return b = i; }
CFGR() : b(0) {}
};
struct CLSR {
union {
uint8 b;
RegFlag8<0x01> flag;
};
inline operator unsigned() const { return b; }
inline unsigned operator=(const unsigned i) { return b = i; }
CLSR() : b(0) {}
};
struct POR {
union {
uint8 b;
RegFlag8<0x01> transparent; //transparent flag
RegFlag8<0x02> dither; //dither flag
RegFlag8<0x04> highnibble; //high nibble flag
RegFlag8<0x08> freezehigh; //freeze high flag
RegFlag8<0x10> obj; //OBJ flag
};
inline operator unsigned() const { return b; }
inline unsigned operator=(const unsigned i) { return b = i; }
POR() : b(0) {}
};
struct Regs {
Reg16 r0; //default source/destination register
Reg16 r1; //pixel plot X position register
Reg16 r2; //pixel plot Y position register
Reg16 r3;
Reg16 r4; //lower 16-bit result of lmult
Reg16 r5;
Reg16 r6; //multiplier for fmult and lmult
Reg16 r7; //fixed point texel X position for merge
Reg16 r8; //fixed point texel Y position for merge
Reg16 r9;
Reg16 r10;
Reg16 r11; //return address set by link
Reg16 r12; //loop counter
Reg16 r13; //loop point address
Reg16 r14; //rom address for getb, getbh, getbl, getbs
Reg16 r15; //program counter
SFR sfr; //status/flag register
uint8 pbr; //program bank register
uint8 rombr; //rom bank register
RAMBR rambr; //ram bank register
CBR cbr; //cache base register
uint8 scbr; //screen base register
SCMR scmr; //screen mode register
BRAMR bramr; //backup ram register
uint8 vcr; //version code register
CFGR cfgr; //config register
CLSR clsr; //clock select register
uint8 colr; //color register
POR por; //plot option register
} regs;

View File

@@ -0,0 +1,42 @@
#include "../../base.h"
#include "core/op0x.cpp"
#include "memory/read.cpp"
#include "memory/write.cpp"
void SuperFX::init() {
}
void SuperFX::enable() {
for(uint i = 0x3000; i <= 0x32ff; i++) {
memory::mmio.map(i, *this);
}
}
void SuperFX::power() {
reset();
}
void SuperFX::reset() {
regs.r0 = 0;
regs.r1 = 0;
regs.r2 = 0;
regs.r3 = 0;
regs.r4 = 0;
regs.r5 = 0;
regs.r6 = 0;
regs.r7 = 0;
regs.r8 = 0;
regs.r9 = 0;
regs.r10 = 0;
regs.r11 = 0;
regs.r12 = 0;
regs.r13 = 0;
regs.r14 = 0;
regs.r15 = 0;
regs.sfr = 0;
memset(cache, 0, sizeof cache);
}

View File

@@ -0,0 +1,17 @@
class SuperFX : public MMIO { public:
#include "core/core.h"
void init();
void enable();
void power();
void reset();
uint8 mmio_read (uint addr);
void mmio_write(uint addr, uint8 data);
private:
#include "regs.h"
uint8 cache[512]; //cache RAM
};
extern SuperFX superfx;

View File

@@ -1 +1,2 @@
@make PLATFORM=win-visualc-lui clean
@make PLATFORM=win-mingw-x86 clean
::@make PLATFORM=win-visualc-x86 clean

View File

@@ -1,2 +1 @@
#!/bin/sh
make PLATFORM=x-gcc-lui clean
make PLATFORM=x-gcc-x86 clean

View File

@@ -1,7 +1,10 @@
Config config_file;
namespace config {
Config& config() {
static Config config;
return config;
}
string file_updatepath(const char *req_file, const char *req_path) {
string file(req_file);
replace(file, "\\", "/");
@@ -12,84 +15,91 @@ string path(req_path);
if(!strend(path, "/")) { strcat(path, "/"); }
if(strbegin(path, "./")) {
strltrim(path, "./");
ltrim(path(), "./");
string temp;
strcpy(temp, config::path.base);
strcat(temp, path);
strcpy(path, temp);
}
stringarray part;
lstring part;
split(part, "/", file);
strcat(path, part[count(part) - 1]);
return path;
}
StringSetting Path::base(0, "fs.base_path",
StringSetting Path::base(0, "path.base",
"Path that bsnes resides in", "");
StringSetting Path::rom(&config_file, "path.rom",
StringSetting Path::rom(&config(), "path.rom",
"Default path to look for ROM files in (\"\" = use default directory)", "");
StringSetting Path::save(&config_file, "path.save",
StringSetting Path::save(&config(), "path.save",
"Default path for all save RAM and cheat files (\"\" = use current directory)", "");
StringSetting Path::bios(&config_file, "path.bios",
"Path where BIOS file(s) are located\n"
"Supported BIOS files:\n"
"stbios.bin - Bandai Sufami Turbo"
"", "./bios");
StringSetting Path::bsx(&config(), "path.bsx", "", "");
StringSetting Path::st(&config(), "path.st", "", "");
StringSetting Path::save_ext(&config_file, "path.save_ext",
"Extension to be used for all save RAM files", "srm");
IntegerSetting SNES::gamma_ramp(&config_file, "snes.colorfilter.gamma_ramp",
IntegerSetting SNES::gamma_ramp(&config(), "snes.colorfilter.gamma_ramp",
"Use precalculated TV-style gamma ramp", IntegerSetting::Boolean, true);
IntegerSetting SNES::sepia(&config_file, "snes.colorfilter.sepia",
IntegerSetting SNES::sepia(&config(), "snes.colorfilter.sepia",
"Convert color to sepia tone", IntegerSetting::Boolean, false);
IntegerSetting SNES::grayscale(&config_file, "snes.colorfilter.grayscale",
IntegerSetting SNES::grayscale(&config(), "snes.colorfilter.grayscale",
"Convert color to grayscale tone", IntegerSetting::Boolean, false);
IntegerSetting SNES::invert(&config_file, "snes.colorfilter.invert",
IntegerSetting SNES::invert(&config(), "snes.colorfilter.invert",
"Invert output image colors", IntegerSetting::Boolean, false);
IntegerSetting SNES::contrast(&config_file, "snes.colorfilter.contrast",
IntegerSetting SNES::contrast(&config(), "snes.colorfilter.contrast",
"Contrast", IntegerSetting::Decimal, 0);
IntegerSetting SNES::brightness(&config_file, "snes.colorfilter.brightness",
IntegerSetting SNES::brightness(&config(), "snes.colorfilter.brightness",
"Brightness", IntegerSetting::Decimal, 0);
IntegerSetting SNES::gamma(&config_file, "snes.colorfilter.gamma",
IntegerSetting SNES::gamma(&config(), "snes.colorfilter.gamma",
"Gamma", IntegerSetting::Decimal, 80);
IntegerSetting SNES::ntsc_merge_fields(&config_file, "snes.ntsc_merge_fields",
IntegerSetting SNES::ntsc_merge_fields(&config(), "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"
"", IntegerSetting::Boolean, true);
IntegerSetting SNES::mute(&config_file, "snes.mute", "Mutes SNES audio output when enabled",
IntegerSetting SNES::mute(&config(), "snes.mute", "Mutes SNES audio output when enabled",
IntegerSetting::Boolean, false);
IntegerSetting SNES::controller_port0(&config_file, "snes.controller_port_1",
IntegerSetting SNES::controller_port0(&config(), "snes.controller_port_1",
"Controller attached to SNES port 1", IntegerSetting::Decimal, ::SNES::DEVICEID_JOYPAD1);
IntegerSetting SNES::controller_port1(&config_file, "snes.controller_port_2",
IntegerSetting SNES::controller_port1(&config(), "snes.controller_port_2",
"Controller attached to SNES port 2", IntegerSetting::Decimal, ::SNES::DEVICEID_JOYPAD2);
IntegerSetting CPU::ntsc_clock_rate(&config_file, "cpu.ntsc_clock_rate",
IntegerSetting CPU::ntsc_clock_rate(&config(), "cpu.ntsc_clock_rate",
"NTSC S-CPU clock rate (in hz)", IntegerSetting::Decimal, 21477272);
IntegerSetting CPU::pal_clock_rate(&config_file, "cpu.pal_clock_rate",
IntegerSetting CPU::pal_clock_rate(&config(), "cpu.pal_clock_rate",
"PAL S-CPU clock rate (in hz)", IntegerSetting::Decimal, 21281370);
IntegerSetting CPU::wram_init_value(&config(), "cpu.wram_init_value",
"Value to initialize 128k WRAM to upon power cycle.\n"
"Note that on real hardware, this value is undefined; meaning it can vary\n"
"per power-on, and per SNES unit. Such randomness is undesirable for an\n"
"emulator, so a static value is needed. There is also some form of pattern\n"
"to the randomness that has yet to be determined, which some games rely upon.\n"
"A value of 0x55 is safe for all known commercial software, and should be used.\n"
"However, some software written for SNES copiers, or backup units, relies on\n"
"WRAM being initialized to 0x00; which was a side-effect of the BIOS program\n"
"which executed on these copiers. Using 0x00 will therefore fix many homebrew\n"
"programs, but *will* break some poorly programmed commercial software titles,\n"
"which do not properly initialize WRAM upon power cycle.\n",
IntegerSetting::Hex, 0x55);
IntegerSetting CPU::hdma_enable(0, "cpu.hdma_enable",
"Enable HDMA effects", IntegerSetting::Boolean, true);
IntegerSetting SMP::ntsc_clock_rate(&config_file, "smp.ntsc_clock_rate",
IntegerSetting SMP::ntsc_clock_rate(&config(), "smp.ntsc_clock_rate",
"NTSC S-SMP clock rate (in hz)", IntegerSetting::Decimal, 24606720);
IntegerSetting SMP::pal_clock_rate(&config_file, "smp.pal_clock_rate",
IntegerSetting SMP::pal_clock_rate(&config(), "smp.pal_clock_rate",
"PAL S-SMP clock rate (in hz)", IntegerSetting::Decimal, 24606720);
IntegerSetting PPU::Hack::render_scanline_position(&config_file, "ppu.hack.render_scanline_position",
IntegerSetting PPU::Hack::render_scanline_position(&config(), "ppu.hack.render_scanline_position",
"Approximate HCLOCK position to render at for scanline-based renderers",
IntegerSetting::Decimal, 512);
IntegerSetting PPU::Hack::obj_cache(&config_file, "ppu.hack.obj_cache",
IntegerSetting PPU::Hack::obj_cache(&config(), "ppu.hack.obj_cache",
"Cache OAM OBJ attributes one scanline before rendering\n"
"This is technically closer to the actual operation of the SNES,\n"
"but can cause problems in some games if enabled",
IntegerSetting::Boolean, false);
IntegerSetting PPU::Hack::oam_address_invalidation(&config_file, "ppu.hack.oam_address_invalidation",
IntegerSetting PPU::Hack::oam_address_invalidation(&config(), "ppu.hack.oam_address_invalidation",
"OAM access address changes during active display, as the S-PPU reads\n"
"data to render the display. Thusly, the address retrieved when accessing\n"
"OAM during active display is unpredictable. Unfortunately, the exact\n"
@@ -97,7 +107,7 @@ IntegerSetting PPU::Hack::oam_address_invalidation(&config_file, "ppu.hack.oam_a
"accurate to enable this setting, but one must *not* rely on the actual\n"
"address to match hardware under emulation.",
IntegerSetting::Boolean, true);
IntegerSetting PPU::Hack::cgram_address_invalidation(&config_file, "ppu.hack.cgram_address_invalidation",
IntegerSetting PPU::Hack::cgram_address_invalidation(&config(), "ppu.hack.cgram_address_invalidation",
"CGRAM access address changes during active display (excluding hblank), as\n"
"the S-PPU reads data to render the display. Thusly, as with OAM, the access\n"
"address is unpredictable. Again, enabling this setting is more hardware\n"

View File

@@ -1,12 +1,12 @@
extern Config config_file;
namespace config {
extern Config& config();
string file_updatepath(const char *, const char *);
extern struct Path {
static StringSetting base, rom, save, bios;
static StringSetting save_ext;
static StringSetting base, rom, save;
static StringSetting bsx, st;
} path;
extern struct SNES {
@@ -19,6 +19,7 @@ extern struct SNES {
extern struct CPU {
static IntegerSetting ntsc_clock_rate, pal_clock_rate;
static IntegerSetting wram_init_value;
static IntegerSetting hdma_enable;
} cpu;

View File

@@ -4,7 +4,7 @@ uint8 CPU::dreadb(uint32 addr) {
//do not read MMIO registers within debugger
return 0x00;
}
return r_mem->read(addr);
return bus.read(addr);
}
uint16 CPU::dreadw(uint32 addr) {

View File

@@ -19,19 +19,19 @@ uint8 r;
(abus & 0x40ffff) == 0x420b || (abus & 0x40ffff) == 0x420c) {
r = regs.mdr;
} else {
r = r_mem->read(abus);
r = bus.read(abus);
}
r_mem->write(0x2100 | bbus, r);
bus.write(0x2100 | bbus, r);
} else { //b->a
if(bbus == 0x80 && ((abus & 0x7e0000) == 0x7e0000 || (abus & 0x40e000) == 0x0000)) {
//prevent WRAM->WRAM transfers
r = regs.mdr;
} else {
r = r_mem->read(0x2100 | bbus);
r = bus.read(0x2100 | bbus);
}
if((abus & 0x40ff00) == 0x2100 || (abus & 0x40ff80) == 0x4300 ||
(abus & 0x40ffff) == 0x420b || (abus & 0x40ffff) == 0x420c)return;
r_mem->write(abus, r);
bus.write(abus, r);
}
dma_add_clocks(8);
@@ -83,8 +83,8 @@ inline uint32 sCPU::hdma_iaddr(uint8 i) {
*****/
void sCPU::dma_transfertobusb(uint8 i, uint8 bbus) {
if(cartridge.info.sdd1 == true && sdd1->dma_active() == true) {
r_mem->write(0x2100 | bbus, sdd1->dma_read());
if(cartridge.info.sdd1 == true && sdd1.dma_active() == true) {
bus.write(0x2100 | bbus, sdd1.dma_read());
} else {
dma_transfer(0, bbus, dma_addr(i));
}
@@ -111,8 +111,7 @@ void sCPU::dma_run() {
dma_add_clocks(8);
if(cartridge.info.sdd1 == true) {
sdd1->dma_begin(i, (channel[i].srcbank << 16) | (channel[i].srcaddr),
channel[i].xfersize);
sdd1.dma_begin(i, (channel[i].srcbank << 16) | (channel[i].srcaddr), channel[i].xfersize);
}
if(tracer.enabled() == true && tracer.cpudma_enabled() == true) {
@@ -168,19 +167,19 @@ uint8 r = 0;
}
void sCPU::hdma_update(uint8 i) {
channel[i].hdma_line_counter = r_mem->read(hdma_addr(i));
channel[i].hdma_line_counter = bus.read(hdma_addr(i));
dma_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;
channel[i].hdma_iaddr = bus.read(hdma_addr(i)) << 8;
dma_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;
channel[i].hdma_iaddr |= bus.read(hdma_addr(i)) << 8;
dma_add_clocks(8);
}
}

View File

@@ -14,21 +14,21 @@ void sCPU::op_io() {
}
uint8 sCPU::op_read(uint32 addr) {
status.clock_count = r_mem->speed(addr);
status.clock_count = bus.speed(addr);
precycle_edge();
add_clocks(status.clock_count - 4);
regs.mdr = r_mem->read(addr);
regs.mdr = bus.read(addr);
add_clocks(4);
cycle_edge();
return regs.mdr;
}
void sCPU::op_write(uint32 addr, uint8 data) {
status.clock_count = r_mem->speed(addr);
status.clock_count = bus.speed(addr);
precycle_edge();
add_clocks(status.clock_count);
regs.mdr = data;
r_mem->write(addr, regs.mdr);
bus.write(addr, regs.mdr);
cycle_edge();
}

View File

@@ -4,14 +4,14 @@ uint8 sCPU::pio_status() {
//WMDATA
uint8 sCPU::mmio_r2180() {
uint8 r = r_mem->read(0x7e0000 | status.wram_addr);
uint8 r = bus.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);
bus.write(0x7e0000 | status.wram_addr, data);
status.wram_addr = (status.wram_addr + 1) & 0x01ffff;
}
@@ -76,7 +76,7 @@ void sCPU::mmio_w4200(uint8 data) {
//WRIO
void sCPU::mmio_w4201(uint8 data) {
if((status.pio & 0x80) && !(data & 0x80)) {
r_ppu->latch_counters();
ppu.latch_counters();
}
status.pio = data;
}
@@ -159,7 +159,7 @@ void sCPU::mmio_w420c(uint8 data) {
//MEMSEL
void sCPU::mmio_w420d(uint8 data) {
r_mem->set_speed(data & 1);
bus.set_speed(data & 1);
}
//RDNMI
@@ -419,11 +419,13 @@ void sCPU::mmio_reset() {
status.joy4h = 0x00;
}
uint8 sCPU::mmio_read(uint16 addr) {
uint8 sCPU::mmio_read(uint addr) {
addr &= 0xffff;
//APU
if((addr & 0xffc0) == 0x2140) { //$2140-$217f
scheduler.sync_cpusmp();
return r_smp->port_read(addr & 3);
return smp.port_read(addr & 3);
}
//DMA
@@ -474,7 +476,9 @@ uint8 sCPU::mmio_read(uint16 addr) {
return regs.mdr;
}
void sCPU::mmio_write(uint16 addr, uint8 data) {
void sCPU::mmio_write(uint addr, uint8 data) {
addr &= 0xffff;
//APU
if((addr & 0xffc0) == 0x2140) { //$2140-$217f
scheduler.sync_cpusmp();

View File

@@ -1,7 +1,7 @@
void mmio_power();
void mmio_reset();
uint8 mmio_read (uint16 addr);
void mmio_write(uint16 addr, uint8 data);
uint8 mmio_read (uint addr);
void mmio_write(uint addr, uint8 data);
uint8 pio_status();

View File

@@ -21,8 +21,8 @@ void sCPU::power() {
void sCPU::reset() {
regs.pc.d = 0x000000;
regs.pc.l = r_mem->read(0xfffc);
regs.pc.h = r_mem->read(0xfffd);
regs.pc.l = bus.read(0xfffc);
regs.pc.h = bus.read(0xfffd);
//note: some registers are not fully reset by SNES
regs.x.h = 0x00;

View File

@@ -1,8 +1,6 @@
class sCPU : public CPU {
public:
class sCPU : public CPU { public:
void enter();
public:
#include "core/core.h"
#include "dma/dma.h"
#include "memory/memory.h"

View File

@@ -90,7 +90,7 @@ void sCPU::scanline() {
status.line_rendered = false;
status.hdma_triggered = (status.vcounter <= (!overscan() ? 224 : 239)) ? false : true;
r_ppu->scanline();
ppu.scanline();
snes.scanline();
update_interrupts();
@@ -117,7 +117,7 @@ void sCPU::frame() {
status.hdmainit_trigger_position = 12 + dma_counter();
}
r_ppu->frame();
ppu.frame();
snes.frame();
}
@@ -143,7 +143,7 @@ void sCPU::cycle_edge() {
if(status.line_rendered == false) {
if(status.hclock >= status.line_render_position) {
status.line_rendered = true;
r_ppu->render_scanline();
ppu.render_scanline();
}
}

BIN
src/data/bsnes.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

BIN
src/doc/base.dia Normal file

Binary file not shown.

View File

@@ -660,7 +660,7 @@ static uint8 const initial_regs [bDSP::register_count] =
void bDSP::power()
{
ram = (uint8*) r_smp->get_spcram_handle();
ram = (uint8*) smp.get_spcram_handle();
memset( &m, 0, sizeof m );
//memcpy( m.regs, initial_regs, sizeof m.regs );
memset(m.regs, 0, sizeof m.regs);

View File

@@ -10,7 +10,12 @@ public:
bDSP();
~bDSP();
template<int n, typename T> inline T asr(const T x) {
enum { bits = (sizeof(T) << 3) - n };
return sclip<bits>(x >> n);
}
public:
enum { echo_hist_size = 8 };

View File

@@ -1,75 +1,37 @@
#ifdef POLYMORPHISM
#define ref(x) x
#else
#define ref(x) (&x)
#endif
#define deref(x) __##x
#define r_mem ref(deref(mem))
#define r_cpu ref(deref(cpu))
#define r_smp ref(deref(smp))
#define r_dsp ref(deref(dsp))
#define r_ppu ref(deref(ppu))
#include "reader/reader.h"
#include "cart/cart.h"
#include "cheat/cheat.h"
#include "memory/memory.h"
#include "memory/bmemory/bmemory.h"
#include "cpu/cpu.h"
#include "cpu/scpu/scpu.h"
#include "smp/smp.h"
#include "smp/ssmp/ssmp.h"
#include "dsp/dsp.h"
//#include "dsp/adsp/adsp.h"
#include "dsp/bdsp/bdsp.h"
#include "ppu/ppu.h"
#include "ppu/bppu/bppu.h"
#include "snes/snes.h"
#include "chip/srtc/srtc.h"
#include "chip/sdd1/sdd1.h"
#include "chip/c4/c4.h"
#include "chip/dsp1/dsp1.h"
#include "chip/dsp2/dsp2.h"
#include "chip/obc1/obc1.h"
extern MMIO mmio_unmapped;
#ifdef POLYMORPHISM
extern MemBus *deref(mem);
extern CPU *deref(cpu);
extern SMP *deref(smp);
extern DSP *deref(dsp);
extern PPU *deref(ppu);
#else
extern MEMCORE deref(mem);
extern CPUCORE deref(cpu);
extern SMPCORE deref(smp);
extern DSPCORE deref(dsp);
extern PPUCORE deref(ppu);
#endif
#include "config/config.h"
#ifdef INTERFACE_MAIN
#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
#include "reader/reader.h"
#include "cheat/cheat.h"
#include "config/config.h"
#include "memory/memory.h"
#include "memory/smemory/smemory.h"
#include "cart/cart.h"
#include "cpu/cpu.h"
#include "cpu/scpu/scpu.h"
#include "smp/smp.h"
#include "smp/ssmp/ssmp.h"
#include "dsp/dsp.h"
//#include "dsp/adsp/adsp.h"
#include "dsp/bdsp/bdsp.h"
#include "ppu/ppu.h"
#include "ppu/bppu/bppu.h"
#include "snes/snes.h"
#include "chip/chip.h"
#ifdef INTERFACE_MAIN
#include "config/config.cpp"
#define extern
#endif
extern BUSCORE bus;
extern CPUCORE cpu;
extern SMPCORE smp;
extern DSPCORE dsp;
extern PPUCORE ppu;
#undef extern

87
src/lib/barray.h Normal file
View File

@@ -0,0 +1,87 @@
/*
barray : version 0.10 ~byuu (2007-11-29)
license: public domain
*/
#ifndef BARRAY_H
#define BARRAY_H
template<typename T> class array {
protected:
T *pool;
uint poolsize, buffersize;
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 poolsize; }
void reset() {
safe_free(pool);
poolsize = 0;
buffersize = 0;
}
void reserve(uint size) {
if(size == poolsize) return;
if(size < poolsize) buffersize = size;
pool = (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 add(T data) {
operator[](buffersize) = data;
}
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(); }
array& operator=(array &source) {
safe_free(pool);
buffersize = source.buffersize;
poolsize = source.poolsize;
pool = (T*)realloc(pool, sizeof(T) * poolsize); //allocate entire pool size ...
memcpy(pool, source.pool, sizeof(T) * buffersize); //... but only copy used pool objects
return *this;
}
inline T& operator[](int index) {
if(index >= buffersize) resize(index + 1);
if(index >= buffersize) throw "array[] out of bounds";
return pool[index];
}
};
#endif //ifndef BARRAY_H

View File

@@ -1,10 +1,10 @@
/*
libbase : version 0.10 ~byuu (2007-06-04)
bbase : version 0.12 ~byuu (2007-12-12)
license: public domain
*/
#ifndef LIBBASE_H
#define LIBBASE_H
#ifndef BBASE_H
#define BBASE_H
#include <assert.h>
#include <limits.h>
@@ -18,7 +18,7 @@
#include <new>
#if defined(_MSC_VER)
#if defined(_MSC_VER) || defined(__MINGW32__)
#include <io.h>
#include <direct.h>
#include <shlobj.h>
@@ -34,6 +34,10 @@
#define NOMINMAX
#define PATH_MAX _MAX_PATH
#define va_copy(dst, src) ((dst) = (src))
#endif
#if defined(_MSC_VER) || defined(__MINGW32__)
#define getcwd _getcwd
#define ftruncate _chsize
#define mkdir _mkdir
@@ -41,11 +45,10 @@
#define rmdir _rmdir
#define vsnprintf _vsnprintf
#define va_copy(dst, src) ((dst) = (src))
static char *realpath(const char *file_name, char *resolved_name) {
return _fullpath(resolved_name, file_name, PATH_MAX);
}
#elif defined(__GNUC__)
#else
#define mkdir(path) (mkdir)(path, 0755);
#endif
@@ -90,13 +93,13 @@ typedef int64_t int64;
//userpath(output) retrieves path to user's home folder
//output must be at least as large as PATH_MAX
#if defined(_MSC_VER)
#if defined(_MSC_VER) || defined(__MINGW32__)
static char *userpath(char *output) {
strcpy(output, "."); //failsafe
SHGetFolderPath(0, CSIDL_APPDATA | CSIDL_FLAG_CREATE, 0, 0, output);
return output;
}
#elif defined(__GNUC__)
#else
static char *userpath(char *output) {
strcpy(output, "."); //failsafe
struct passwd *userinfo = getpwuid(getuid());
@@ -106,7 +109,27 @@ struct passwd *userinfo = getpwuid(getuid());
#endif
/*****
* templates
* template classes
*****/
class noncopyable {
protected:
noncopyable() {}
~noncopyable() {}
private:
noncopyable(const noncopyable&);
const noncopyable& operator=(const noncopyable&);
};
template<typename T>
struct base_from_member {
T value;
base_from_member(T value_) : value(value_) {}
};
/*****
* template functions
*****/
template<typename T> inline void safe_free(T &handle) {
@@ -136,14 +159,10 @@ T z = x;
y = z;
}
#ifdef min
#undef min
#endif
#define min(x, y) (((x) < (y)) ? (x) : (y))
#ifdef max
#undef max
#endif
#define max(x, y) (((x) > (y)) ? (x) : (y))
template<int min, int max, typename T> inline T minmax(const T x) {
@@ -170,34 +189,6 @@ enum { b = 1U << (bits - 1), m = (1U << bits) - 1 };
return ((x & m) ^ b) - b;
}
template<int n, typename T> inline T rol(const T x) {
enum { s = (sizeof(T) << 3) - n };
return (x << n) | (x >> s);
}
template<int n, typename T> inline T ror(const T x) {
enum { s = (sizeof(T) << 3) - n };
return (x >> n) | (x << s);
}
template<int n, typename T> inline T asl(const T x) {
return (x << n);
}
template<int n, typename T> inline T asr(const T x) {
enum { bits = (sizeof(T) << 3) - n };
return sclip<bits>(x >> n);
}
template<int n, typename T> inline T lsl(const T x) {
return (x << n);
}
template<int n, typename T> inline T lsr(const T x) {
enum { bits = (sizeof(T) << 3) - n };
return uclip<bits>(x >> n);
}
/*****
* endian wrappers
*****/
@@ -240,6 +231,11 @@ enum { bits = (sizeof(T) << 3) - n };
* libc extensions
*****/
//static uint random() {
//static uint n = 0;
// return n = (n >> 1) ^ (((n & 1) - 1) & 0xedb88320);
//}
static uint64 fget(FILE *fp, uint length = 1) {
uint64 data = 0;
for(uint i = 0; i < length; i++) {
@@ -348,4 +344,4 @@ uint32 crc32 = ~0;
return ~crc32;
}
#endif
#endif //ifndef BBASE_H

View File

@@ -1,54 +1,52 @@
/*
libconfig : version 0.14 ~byuu (2007-06-12)
bconfig : version 0.16 ~byuu (2007-11-28)
license: public domain
*/
#ifndef LIBCONFIG_H
#define LIBCONFIG_H
#ifndef BCONFIG_H
#define BCONFIG_H
#include "libbase.h"
#include "libarray.h"
#include "libstring.h"
#include "bbase.h"
#include "barray.h"
#include "bstring.h"
class Setting;
class Config { public:
array<Setting*> list;
uint list_count;
class Config {
public:
array<Setting*> list;
uint list_count;
string data;
stringarray line, part, subpart;
string data;
lstring line, part, subpart;
bool load(const char *fn);
bool save(const char *fn);
bool load(const string &fn) { return load(strptr(fn)); }
bool save(const string &fn) { return save(strptr(fn)); }
void add(Setting *setting) { list[list_count++] = setting; }
Config() : list_count(0) {}
};
class Setting { public:
uint type;
char *name, *desc, *def;
enum Type {
Integer,
String,
};
class Setting {
public:
enum Type {
Integer,
String,
} type;
char *name, *desc, *def;
virtual void set(const char *input) = 0;
virtual void get(string &output) = 0;
};
class IntegerSetting : public Setting { public:
uint ifmt, data, idef;
enum Format {
Boolean,
Decimal,
Hex,
};
class IntegerSetting : public Setting {
public:
enum Format {
Boolean,
Decimal,
Hex,
} ifmt;
uint data, idef;
void set(const char *input) {
if(ifmt == Boolean) { data = !strcmp(input, "true"); }
@@ -57,9 +55,10 @@ enum Format {
}
void get(string &output) {
if(ifmt == Boolean) { sprintf(output, "%s", data ? "true" : "false"); }
if(ifmt == Decimal) { sprintf(output, "%d", data); }
if(ifmt == Hex) { sprintf(output, "%x", data); }
output.reserve(64);
if(ifmt == Boolean) { sprintf(output(), "%s", data ? "true" : "false"); }
if(ifmt == Decimal) { sprintf(output(), "%d", data); }
if(ifmt == Hex) { sprintf(output(), "0x%x", data); }
}
uint operator()() { return data; }
@@ -72,7 +71,7 @@ enum Format {
template<typename T> bool operator<=(T x) { return (T(data) <= x); }
template<typename T> bool operator< (T x) { return (T(data) < x); }
IntegerSetting(Config *parent, const char *r_name, const char *r_desc, uint r_format, uint r_data) {
IntegerSetting(Config *parent, const char *r_name, const char *r_desc, Format r_format, uint r_data) {
type = Setting::Integer;
name = strdup(r_name);
desc = strdup(r_desc);
@@ -80,25 +79,26 @@ enum Format {
data = idef = r_data;
string t;
get(t);
def = strdup(strptr(t));
def = strdup(t);
if(parent) { parent->add(this); }
}
~IntegerSetting() {
free(name);
free(desc);
free(def);
safe_free(name);
safe_free(desc);
safe_free(def);
}
};
class StringSetting : public Setting { public:
string data;
void set(const char *input) { data = input; strunquote(data); }
void get(string &output) { output = data; strquote(output); }
class StringSetting : public Setting {
public:
string data;
void set(const char *input) { data = input; trim(data(), "\""); }
void get(string &output) { output = string() << "\"" << data << "\""; }
const char* operator()() { return strptr(data); }
operator const char*() { return strptr(data); }
char* operator()() { return data(); }
operator const char*() { return data; }
StringSetting &operator=(const char *x) { data = x; return *this; }
bool operator==(const char *x) { return !strcmp(data, x); }
bool operator!=(const char *x) { return strcmp(data, x); }
@@ -110,15 +110,15 @@ string data;
data = r_data;
string t;
get(t);
def = strdup(strptr(t));
def = strdup(t);
if(parent) { parent->add(this); }
}
~StringSetting() {
free(name);
free(desc);
free(def);
safe_free(name);
safe_free(desc);
safe_free(def);
}
};
@@ -145,12 +145,12 @@ char *buffer = (char*)malloc(fsize + 1);
for(int i = 0; i < count(line); i++) {
if(strlen(line[i]) == 0)continue;
if(*strptr(line[i]) == '#')continue;
if(*line[i] == '#')continue;
qsplit(part, "=", line[i]);
for(int l = 0; l < list_count; l++) {
if(!strcmp(list[l]->name, part[0])) {
list[l]->set(strptr(part[1]));
list[l]->set(part[1]);
break;
}
}
@@ -170,16 +170,16 @@ string t;
replace(data, "\r\n", "\n");
split(line, "\n", data);
for(int l = 0; l < count(line); l++) {
if(line[l] != "") { fprintf(fp, "# %s\r\n", strptr(line[l])); }
if(line[l] != "") { fprintf(fp, "# %s\r\n", line[l]()); }
}
fprintf(fp, "# (default = %s)\r\n", list[i]->def);
list[i]->get(t);
fprintf(fp, "%s = %s\r\n\r\n", list[i]->name, strptr(t));
fprintf(fp, "%s = %s\r\n\r\n", list[i]->name, t());
}
fclose(fp);
return true;
}
#endif
#endif //ifndef BCONFIG_H

183
src/lib/bfunction.h Normal file
View File

@@ -0,0 +1,183 @@
/*
bfunction : version 0.06 ~byuu (2007-10-14)
license: public domain
*/
#ifndef BFUNCTION_H
#define BFUNCTION_H
//prologue
#define TN typename
template<typename T> class function;
//parameters = 0
#define cat(n) n
#define TL typename R
#define PL
#define CL
#include "bfunction.h"
//parameters = 1
#define cat(n) , n
#define TL TN R, TN P1
#define PL P1 p1
#define CL p1
#include "bfunction.h"
//parameters = 2
#define cat(n) , n
#define TL TN R, TN P1, TN P2
#define PL P1 p1, P2 p2
#define CL p1, p2
#include "bfunction.h"
//parameters = 3
#define cat(n) , n
#define TL TN R, TN P1, TN P2, TN P3
#define PL P1 p1, P2 p2, P3 p3
#define CL p1, p2, p3
#include "bfunction.h"
//parameters = 4
#define cat(n) , n
#define TL TN R, TN P1, TN P2, TN P3, TN P4
#define PL P1 p1, P2 p2, P3 p3, P4 p4
#define CL p1, p2, p3, p4
#include "bfunction.h"
//parameters = 5
#define cat(n) , n
#define TL TN R, TN P1, TN P2, TN P3, TN P4, TN P5
#define PL P1 p1, P2 p2, P3 p3, P4 p4, P5 p5
#define CL p1, p2, p3, p4, p5
#include "bfunction.h"
//parameters = 6
#define cat(n) , n
#define TL TN R, TN P1, TN P2, TN P3, TN P4, TN P5, TN P6
#define PL P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6
#define CL p1, p2, p3, p4, p5, p6
#include "bfunction.h"
//parameters = 7
#define cat(n) , n
#define TL TN R, TN P1, TN P2, TN P3, TN P4, TN P5, TN P6, TN P7
#define PL P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7
#define CL p1, p2, p3, p4, p5, p6, p7
#include "bfunction.h"
//parameters = 8
#define cat(n) , n
#define TL TN R, TN P1, TN P2, TN P3, TN P4, TN P5, TN P6, TN P7, TN P8
#define PL P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7, P8 p8
#define CL p1, p2, p3, p4, p5, p6, p7, p8
#include "bfunction.h"
//epilogue
#undef TN
#define BFUNCTION_TH
#elif !defined(BFUNCTION_TH)
//function implementation template class
template<TL>
class function<R (PL)> {
private:
struct base1 { virtual void func1(PL) {} };
struct base2 { virtual void func2(PL) {} };
struct derived : base1, virtual base2 {};
struct data_t {
R (*fn_call)(const data_t& cat(PL));
union {
R (*fn_global)(PL);
struct {
R (derived::*fn_member)(PL);
void *object;
};
};
} data;
static R fn_call_global(const data_t &d cat(PL)) {
return d.fn_global(CL);
}
template<typename C>
static R fn_call_member(const data_t &d cat(PL)) {
return (((C*)d.object)->*((R (C::*&)(PL))d.fn_member))(CL);
}
public:
R operator()(PL) const { return data.fn_call(data cat(CL)); }
operator bool() const { return data.fn_call; }
function() { data.fn_call = 0; }
function(R (*fn)(PL)) {
data.fn_call = &fn_call_global;
data.fn_global = fn;
}
template<typename C>
function(R (C::*fn)(PL), C *obj) {
data.fn_call = &fn_call_member<C>;
(R (C::*&)(PL))data.fn_member = fn;
assert(sizeof data.fn_member >= sizeof fn);
data.object = obj;
}
template<typename C>
function(R (C::*fn)(PL) const, C *obj) {
data.fn_call = &fn_call_member<C>;
(R (C::*&)(PL))data.fn_member = (R (C::*&)(PL))fn;
assert(sizeof data.fn_member >= sizeof fn);
data.object = obj;
}
function &operator=(const function &source) { memcpy(&data, &source.data, sizeof(data_t)); return *this; }
function(const function &source) { memcpy(&data, &source.data, sizeof(data_t)); }
};
template<TL>
function<R (PL)> bind(R (*fn)(PL)) {
return function<R (PL)>(fn);
}
template<typename C, TL>
function<R (PL)> bind(R (C::*fn)(PL), C *obj) {
return function<R (PL)>(fn, obj);
}
template<typename C, TL>
function<R (PL)> bind(R (C::*fn)(PL) const, C *obj) {
return function<R (PL)>(fn, obj);
}
#undef cat
#undef TL
#undef PL
#undef CL
#endif

View File

@@ -1,9 +1,10 @@
/*
libkeymap : version 0.02 ~byuu (2007-05-28)
bkeymap : version 0.02 ~byuu (2007-05-28)
license: public domain
*/
#ifndef LIBKEYMAP_H
#define LIBKEYMAP_H
#ifndef BKEYMAP_H
#define BKEYMAP_H
namespace keymap {
@@ -306,4 +307,4 @@ static const char *find(uint16 key) {
};
#endif
#endif //ifndef BKEYMAP_H

95
src/lib/bstring.cpp Normal file
View File

@@ -0,0 +1,95 @@
#include "bstring.h"
#include "bstring/bstring.list.cpp"
#include "bstring/bstring.strl.cpp"
#include "bstring/bstring.math.cpp"
#include "bstring/bstring.misc.cpp"
#include "bstring/bstring.replace.cpp"
#include "bstring/bstring.split.cpp"
#include "bstring/bstring.trim.cpp"
void string::reserve(uint size_) {
if(size_ > size) {
size = size_;
data = (char*)realloc(data, size + 1);
data[size] = 0;
}
}
//implicit-conversion, read-only
string::operator const char*() const {
return data;
}
//explicit-coversion, read-write
char* string::operator()() {
return data;
}
//index, read-write
char& string::operator[](const uint index) {
reserve(index);
return data[index];
}
string& string::operator=(const int num) {
itoa(*this, num);
return *this;
}
string& string::operator=(const char *str) {
strcpy(*this, str);
return *this;
}
string& string::operator=(const string &str) {
strcpy(*this, str);
return *this;
}
string& string::operator<<(const int num) {
string temp(num);
strcat(*this, temp);
return *this;
}
string& string::operator<<(const char *str) {
strcat(*this, str);
return *this;
}
bool string::operator==(const char *str) { return strcmp(data, str) == 0; }
bool string::operator!=(const char *str) { return strcmp(data, str) != 0; }
bool string::operator< (const char *str) { return strcmp(data, str) < 0; }
bool string::operator<=(const char *str) { return strcmp(data, str) <= 0; }
bool string::operator> (const char *str) { return strcmp(data, str) > 0; }
bool string::operator>=(const char *str) { return strcmp(data, str) >= 0; }
string::string() {
size = 64;
data = (char*)malloc(size + 1);
*data = 0;
}
string::string(const int source) {
size = 64;
data = (char*)malloc(size + 1);
*data = 0;
itoa(*this, source);
}
string::string(const char *source) {
size = strlen(source);
data = (char*)malloc(size + 1);
strcpy(data, source);
}
string::string(const string &source) {
size = strlen(source);
data = (char*)malloc(size + 1);
strcpy(data, source);
}
string::~string() {
safe_free(data);
}

99
src/lib/bstring.h Normal file
View File

@@ -0,0 +1,99 @@
/*
bstring : version 0.01a ~byuu (2007-12-12)
license: public domain
*/
#ifndef BSTRING_H
#define BSTRING_H
#include "bbase.h"
#include "bvector.h"
class string;
typedef linear_vector<string> lstring;
uint count(lstring&);
int find(lstring &str, const char *key);
uint strlcpy(char *dest, const char *src, uint length);
uint strlcat(char *dest, const char *src, uint length);
uint strlcpy(string &dest, const char *src, uint length);
uint strlcat(string &dest, const char *src, uint length);
int strmath(const char *str);
char chrlower(char c);
char chrupper(char c);
int stricmp(const char *dest, const char *src);
void strcpy(string &dest, const char *src);
void strcat(string &dest, const char *src);
string substr(string &dest, const char *src, uint start = 0, uint length = 0);
char* strlower(char *str);
char* strupper(char *str);
string& strlower(string &str);
string& strupper(string &str);
int strpos(const char *str, const char *key);
int qstrpos(const char *str, const char *key);
char* strtr(char *dest, const char *before, const char *after);
string& strtr(string &dest, const char *before, const char *after);
bool strbegin(const char *str, const char *key);
bool stribegin(const char *str, const char *key);
bool strend(const char *str, const char *key);
bool striend(const char *str, const char *key);
uint strhex(const char *str);
uint strdec(const char *str);
uint strbin(const char *str);
string& utoa(string &str, uint num);
string& itoa(string &str, uint num);
string& htoa(string &str, uint num);
string& btoa(string &str, uint num);
bool fread(string &str, const char *filename);
string& replace(string &str, const char *key, const char *token);
string& qreplace(string &str, const char *key, const char *token);
void split(lstring &dest, const char *key, const char *src);
void qsplit(lstring &dest, const char *key, const char *src);
char* ltrim(char *str, const char *key = " ");
char* rtrim(char *str, const char *key = " ");
char* trim(char *str, const char *key = " ");
string& ltrim(string &str, const char *key = " ");
string& rtrim(string &str, const char *key = " ");
string& trim(string &str, const char *key = " ");
class string {
public:
char *data;
uint size;
void reserve(uint size_);
operator const char*() const;
char* operator()();
char& operator[](const uint);
string& operator=(const int num);
string& operator=(const char *str);
string& operator=(const string &str);
string& operator<<(const int num);
string& operator<<(const char *str);
bool operator==(const char *str);
bool operator!=(const char *str);
bool operator< (const char *str);
bool operator<=(const char *str);
bool operator> (const char *str);
bool operator>=(const char *str);
string();
string(const int num);
string(const char *source);
string(const string &source);
~string();
};
#endif //ifndef BSTRING_H

View File

@@ -0,0 +1,14 @@
#ifdef BSTRING_H
uint count(lstring &str) {
return str.size();
}
int find(lstring &str, const char *key) {
for(uint i = 0; i < count(str); i++) {
if(str[i] == key) return i;
}
return -1;
}
#endif //ifdef BSTRING_H

View File

@@ -1,121 +1,194 @@
/*
c-style Math Evaluator v1.0 (07/03/2006)
Algorithm: Recursive Descent Processor
Written by: gladius
Optimized by: gladius and byuu
Public Domain
*/
#define maxlevel 12
int strmath_rdp(const char *&s, int level = 0) {
if(level == maxlevel) {
if(*s == '(') {
int result = strmath_rdp(++s, 0);
s++;
return result;
} else if(*s == '+') {
return +strmath_rdp(++s, maxlevel);
} else if(*s == '-') {
return -strmath_rdp(++s, maxlevel);
} else if(*s == '!') {
return !strmath_rdp(++s, maxlevel);
} else if(*s == '~') {
return ~strmath_rdp(++s, maxlevel);
} else if(*s >= '0' && *s <= '9') {
int num, len;
sscanf(s, "%d%n", &num, &len);
s += len;
return num;
}
}
int lhs = strmath_rdp(s, level + 1);
while(*s) {
int a = *s;
int b = *s ? *(s + 1) : 0;
switch(level) {
case 0:
if(a == '?')break;
return lhs;
case 1:
if(a == '|' && b == '|') { s++; break; }
return lhs;
case 2:
if(a == '^' && b == '^') { s++; break; }
return lhs;
case 3:
if(a == '&' && b == '&') { s++; break; }
return lhs;
case 4:
if(a == '|' && b != '|')break;
return lhs;
case 5:
if(a == '^' && b != '^')break;
return lhs;
case 6:
if(a == '&' && b != '&')break;
return lhs;
case 7:
if(a == '=' && b == '=') { s++; break; }
if(a == '!' && b == '=') { s++; break; }
return lhs;
case 8:
if(a == '<' && b == '=') { s++; break; }
if(a == '>' && b == '=') { s++; break; }
if(a == '<')break;
if(a == '>')break;
return lhs;
case 9:
if(a == '<' && b == '<') { s++; break; }
if(a == '>' && b == '>') { s++; break; }
return lhs;
case 10:
if(a == '+')break;
if(a == '-')break;
return lhs;
case 11:
if(a == '*')break;
if(a == '/')break;
if(a == '%')break;
return lhs;
}
if(a == '?') {
int tr = strmath_rdp(++s, level);
int fr = strmath_rdp(++s, level);
lhs = (lhs) ? tr : fr;
} else {
int rhs = strmath_rdp(++s, level + 1);
if (a == '|' && b == '|') lhs = (lhs || rhs);
else if(a == '^' && b == '^') lhs = (!lhs != !rhs);
else if(a == '&' && b == '&') lhs = (lhs && rhs);
else if(a == '|' && b != '|') lhs |= rhs;
else if(a == '^' && b != '^') lhs ^= rhs;
else if(a == '&' && b != '&') lhs &= rhs;
else if(a == '=' && b == '=') lhs = (lhs == rhs);
else if(a == '!' && b == '=') lhs = (lhs != rhs);
else if(a == '<' && b == '=') lhs = (lhs <= rhs);
else if(a == '>' && b == '=') lhs = (lhs >= rhs);
else if(a == '<' && b != '<') lhs = (lhs < rhs);
else if(a == '>' && b != '>') lhs = (lhs > rhs);
else if(a == '<' && b == '<') lhs <<= rhs;
else if(a == '>' && b == '>') lhs >>= rhs;
else if(a == '+') lhs += rhs;
else if(a == '-') lhs -= rhs;
else if(a == '*') lhs *= rhs;
else if(a == '/') lhs /= rhs;
else if(a == '%') lhs %= rhs;
}
}
return lhs;
}
#undef maxlevel
int strmath(const char *str) {
return strmath_rdp(str);
}
#ifdef __LIBSTRING
int strmath(const string &str) {
return strmath(strptr(str));
}
#endif
#ifdef BSTRING_H
/*
recursive descent math processor v0.02 (2007-11-28)
authors: gladius, byuu
license: public domain
*/
void strmath_space(const char *&s) {
while(*s == ' ' || *s == '\t')s++;
}
int strmath_number(const char *&s) {
int result = 0;
enum type { dec, hex, bin, oct };
type t = dec;
if(*s == '0') {
s++;
if(*s == 'x' || *s == 'X') { s++; t = hex; }
else if(*s == 'b' || *s == 'B') { s++; t = bin; }
else { t = oct; }
} else if(*s == '$') {
s++;
t = hex;
} else if(*s == '%') {
s++;
t = bin;
}
switch(t) {
case dec: {
while(true) {
char x = *s;
if(x >= '0' && x <= '9')x = x - '0';
else break;
result = result * 10 + x;
s++;
}
} break;
case hex: {
while(true) {
char x = *s;
if(x >= '0' && x <= '9')x = x - '0';
else if(x >= 'a' && x <= 'f')x = x - 'a' + 0x0a;
else if(x >= 'A' && x <= 'F')x = x - 'A' + 0x0a;
else break;
result = result * 16 + x;
s++;
}
} break;
case bin: {
while(true) {
char x = *s;
if(x >= '0' && x <= '1')x = x - '0';
else break;
result = result * 2 + x;
s++;
}
} break;
case oct: {
while(true) {
char x = *s;
if(x >= '0' && x <= '7')x = x - '0';
else break;
result = result * 8 + x;
s++;
}
} break;
}
return result;
int num, len;
sscanf(s, "%d%n", &num, &len);
s += len;
return num;
}
#define maxlevel 12
int strmath_rdp(const char *&s, int level = 0) {
strmath_space(s);
if(level == maxlevel) {
if(*s == '(') {
int result = strmath_rdp(++s, 0);
s++;
return result;
} else if(*s == '+') {
return +strmath_rdp(++s, maxlevel);
} else if(*s == '-') {
return -strmath_rdp(++s, maxlevel);
} else if(*s == '!') {
return !strmath_rdp(++s, maxlevel);
} else if(*s == '~') {
return ~strmath_rdp(++s, maxlevel);
} else if((*s >= '0' && *s <= '9') || *s == '$' || *s == '%') {
return strmath_number(s);
} else {
return 0; //error
}
}
int lhs = strmath_rdp(s, level + 1);
strmath_space(s);
while(*s) {
int a = *s;
int b = *s ? *(s + 1) : 0;
switch(level) {
case 0:
if(a == '?')break;
return lhs;
case 1:
if(a == '|' && b == '|') { s++; break; }
return lhs;
case 2:
if(a == '^' && b == '^') { s++; break; }
return lhs;
case 3:
if(a == '&' && b == '&') { s++; break; }
return lhs;
case 4:
if(a == '|' && b != '|')break;
return lhs;
case 5:
if(a == '^' && b != '^')break;
return lhs;
case 6:
if(a == '&' && b != '&')break;
return lhs;
case 7:
if(a == '=' && b == '=') { s++; break; }
if(a == '!' && b == '=') { s++; break; }
return lhs;
case 8:
if(a == '<' && b == '=') { s++; break; }
if(a == '>' && b == '=') { s++; break; }
if(a == '<')break;
if(a == '>')break;
return lhs;
case 9:
if(a == '<' && b == '<') { s++; break; }
if(a == '>' && b == '>') { s++; break; }
return lhs;
case 10:
if(a == '+')break;
if(a == '-')break;
return lhs;
case 11:
if(a == '*')break;
if(a == '/')break;
if(a == '%')break;
return lhs;
}
if(a == '?') {
int tr = strmath_rdp(++s, level);
int fr = strmath_rdp(++s, level);
lhs = (lhs) ? tr : fr;
} else {
int rhs = strmath_rdp(++s, level + 1);
if (a == '|' && b == '|') lhs = (lhs || rhs);
else if(a == '^' && b == '^') lhs = (!lhs != !rhs);
else if(a == '&' && b == '&') lhs = (lhs && rhs);
else if(a == '|' && b != '|') lhs |= rhs;
else if(a == '^' && b != '^') lhs ^= rhs;
else if(a == '&' && b != '&') lhs &= rhs;
else if(a == '=' && b == '=') lhs = (lhs == rhs);
else if(a == '!' && b == '=') lhs = (lhs != rhs);
else if(a == '<' && b == '=') lhs = (lhs <= rhs);
else if(a == '>' && b == '=') lhs = (lhs >= rhs);
else if(a == '<' && b != '<') lhs = (lhs < rhs);
else if(a == '>' && b != '>') lhs = (lhs > rhs);
else if(a == '<' && b == '<') lhs <<= rhs;
else if(a == '>' && b == '>') lhs >>= rhs;
else if(a == '+') lhs += rhs;
else if(a == '-') lhs -= rhs;
else if(a == '*') lhs *= rhs;
else if(a == '/') lhs /= rhs;
else if(a == '%') lhs %= rhs;
}
}
return lhs;
}
#undef maxlevel
int strmath(const char *str) {
return strmath_rdp(str);
}
#endif //ifdef BSTRING_H

View File

@@ -0,0 +1,277 @@
#ifdef BSTRING_H
char chrlower(char c) {
return (c >= 'A' && c <= 'Z') ? c + ('a' - 'A') : c;
}
char chrupper(char c) {
return (c >= 'a' && c <= 'z') ? c - ('a' - 'A') : c;
}
int stricmp(const char *dest, const char *src) {
while(*dest) {
if(chrlower(*dest) != chrlower(*src)) break;
dest++;
src++;
}
return (int)chrlower(*dest) - (int)chrlower(*src);
}
void strcpy(string &dest, const char *src) {
int srclen = strlen(src);
dest.reserve(srclen);
strcpy(dest(), src);
}
void strcat(string &dest, const char *src) {
int srclen = strlen(src);
int destlen = strlen(dest);
dest.reserve(srclen + destlen);
strcat(dest(), src);
}
string substr(const char *src, uint start, uint length) {
string dest;
if(length == 0) {
//copy entire string
strcpy(dest, src + start);
} else {
//copy partial string
strlcpy(dest, src + start, length + 1);
}
return dest;
}
char* strlower(char *str) {
uint i = 0;
while(str[i]) {
str[i] = chrlower(str[i]);
i++;
}
return str;
}
char* strupper(char *str) {
uint i = 0;
while(str[i]) {
str[i] = chrupper(str[i]);
i++;
}
return str;
}
string& strlower(string &str) {
strlower(str());
return str;
}
string& strupper(string &str) {
strupper(str());
return str;
}
int strpos(const char *str, const char *key) {
int ssl = strlen(str), ksl = strlen(key);
if(ksl > ssl) return -1;
for(int i = 0; i <= ssl - ksl; i++) {
if(!memcmp(str + i, key, ksl)) {
return i;
}
}
return -1;
}
int qstrpos(const char *str, const char *key) {
int ssl = strlen(str), ksl = strlen(key);
if(ksl > ssl) return -1;
for(int i = 0; i <= ssl - ksl;) {
uint8 x = str[i];
if(x == '\"' || x == '\'') {
uint8 z = i++;
while(str[i] != x && i < ssl) i++;
if(i >= ssl) i = z;
}
if(!memcmp(str + i, key, ksl)) {
return i;
} else {
i++;
}
}
return -1;
}
char* strtr(char *dest, const char *before, const char *after) {
int sl = strlen(dest), bsl = strlen(before), asl = strlen(after);
if(bsl != asl || bsl == 0) return dest; //patterns must be the same length for 1:1 replace
for(int i = 0; i < sl; i++) {
for(int l = 0; l < bsl; l++) {
if(dest[i] == before[l]) {
dest[i] = after[l];
break;
}
}
}
return dest;
}
string& strtr(string &dest, const char *before, const char *after) {
strtr(dest(), before, after);
return dest;
}
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 stribegin(const char *str, const char *key) {
int ssl = strlen(str), ksl = strlen(key);
if(ksl > ssl)return false;
for(int i = 0; i < ksl; i++) {
if(str[i] >= 'A' && str[i] <= 'Z') {
if(str[i] != key[i] && str[i]+0x20 != key[i])return false;
} else if(str[i] >= 'a' && str[i] <= 'z') {
if(str[i] != key[i] && str[i]-0x20 != key[i])return false;
} else {
if(str[i] != key[i])return false;
}
}
return true;
}
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 striend(const char *str, const char *key) {
int ssl = strlen(str), ksl = strlen(key);
if(ksl > ssl)return false;
for(int i = ssl - ksl, z = 0; i < ssl; i++, z++) {
if(str[i] >= 'A' && str[i] <= 'Z') {
if(str[i] != key[z] && str[i]+0x20 != key[z])return false;
} else if(str[i] >= 'a' && str[i] <= 'z') {
if(str[i] != key[z] && str[i]-0x20 != key[z])return false;
} else {
if(str[i] != key[z])return false;
}
}
return true;
}
uint strhex(const char *str) {
uint r = 0, m = 0;
int i = 0, ssl = strlen(str);
uint8 x;
bool negate = (str[0] == '-');
if(negate)i++;
for(; i < ssl; i++) {
if(str[i] >= '0' && str[i] <= '9');
else if(str[i] >= 'A' && str[i] <= 'F');
else if(str[i] >= 'a' && str[i] <= 'f');
else break;
}
for(--i; i >= 0; i--, m += 4) {
x = str[i];
if(x >= '0' && x <= '9')x -= '0';
else if(x >= 'A' && x <= 'F')x -= 'A' - 0x0a;
else if(x >= 'a' && x <= 'f')x -= 'a' - 0x0a;
else break;
r |= x << m;
}
return !negate ? r : (uint)-r;
}
uint strdec(const char *str) {
uint m = 1;
int i = 0, r = 0, ssl = strlen(str);
uint8 x;
bool negate = (str[0] == '-');
if(negate)i++;
for(; i < ssl; i++) {
if(str[i] >= '0' && str[i] <= '9');
else break;
}
for(--i; i >= 0; i--, m *= 10) {
x = str[i];
if(x >= '0' && x <= '9')x -= '0';
else break;
r += x * m;
}
return !negate ? r : (uint)-r;
}
uint strbin(const char *str) {
uint r = 0, m = 0;
int i = 0, ssl = strlen(str);
uint8 x;
bool negate = (str[0] == '-');
if(negate)i++;
for(; i < ssl; i++) {
if(str[i] == '0' || str[i] == '1');
else break;
}
for(--i; i >= 0; i--, m++) {
x = str[i];
if(str[i] == '0' || str[i] == '1')x -= '0';
else break;
r |= x << m;
}
return !negate ? r : (uint)-r;
}
string &utoa(string &str, uint num) {
str.reserve(16);
sprintf(str(), "%u", num);
return str;
}
string &itoa(string &str, uint num) {
str.reserve(16);
sprintf(str(), "%d", num);
return str;
}
string &htoa(string &str, uint num) {
str.reserve(16);
sprintf(str(), "%x", num);
return str;
}
string &btoa(string &str, uint num) {
str.reserve(64);
char *pstr = str();
uint mask = 0x80000000;
while(mask && (num & mask) == 0)mask >>= 1;
while(mask > 1) {
*pstr++ = (num & mask) ? '1' : '0';
mask >>= 1;
}
*pstr++ = (num & mask) ? '1' : '0';
*pstr = 0;
return str;
}
bool fread(string &str, const char *filename) {
strcpy(str, "");
FILE *fp = fopen(filename, "rb");
if(!fp)return false;
uint size = fsize(fp);
char *fdata = (char*)malloc(size + 1);
fread(fdata, 1, size, fp);
fclose(fp);
fdata[size] = 0;
strcpy(str, fdata);
free(fdata);
return true;
}
#endif //ifdef BSTRING_H

View File

@@ -1,86 +1,88 @@
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;
if(ksl > ssl)return str;
if(tsl > ksl) { //the new string may be longer than the old string...
for(i = 0; i <= ssl - ksl;) { //so let's find out how big of a string we'll need...
if(!memcmp(str.s + i, key, ksl)) {
replace_count++;
i += ksl;
} else i++;
}
size = ssl + ((tsl - ksl) * replace_count);
str.reserve(size);
}
data = (char*)malloc(size + 1);
for(i = z = 0; i < ssl;) {
if(i <= ssl - ksl) {
if(!memcmp(str.s + i, key, ksl)) {
memcpy(data + z, token, tsl);
z += tsl;
i += ksl;
} else data[z++] = str.s[i++];
} else data[z++] = str.s[i++];
}
data[z] = 0;
strcpy(str, data);
free(data);
return str;
}
string &replace(string &str, const char *key, const string &token) { return replace(str, key, strptr(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;
char *data;
if(ksl > ssl)return str;
if(tsl > ksl) {
for(i = 0; i <= ssl - ksl;) {
x = str.s[i];
if(x == '\"' || x == '\'') {
l = i;
i++;
while(str.s[i++] != x) {
if(i == ssl) {
i = l;
break;
}
}
}
if(!memcmp(str.s + i, key, ksl)) {
replace_count++;
i += ksl;
} else i++;
}
size = ssl + ((tsl - ksl) * replace_count);
str.reserve(size);
}
data = (char*)malloc(size + 1);
for(i = z = 0; i < ssl;) {
x = str.s[i];
if(x == '\"' || x == '\'') {
l = i++;
while(str.s[i] != x && i < ssl)i++;
if(i >= ssl)i = l;
else {
memcpy(data + z, str.s + l, i - l);
z += i - l;
}
}
if(i <= ssl - ksl) {
if(!memcmp(str.s + i, key, ksl)) {
memcpy(data + z, token, tsl);
z += tsl;
i += ksl;
replace_count++;
} else data[z++] = str.s[i++];
} else data[z++] = str.s[i++];
}
data[z] = 0;
strcpy(str, data);
free(data);
return str;
}
string &qreplace(string &str, const char *key, const string &token) { return qreplace(str, key, strptr(token)); }
#ifdef BSTRING_H
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;
if(ksl > ssl)return str;
if(tsl > ksl) { //the new string may be longer than the old string...
for(i = 0; i <= ssl - ksl;) { //so let's find out how big of a string we'll need...
if(!memcmp(str() + i, key, ksl)) {
replace_count++;
i += ksl;
} else i++;
}
size = ssl + ((tsl - ksl) * replace_count);
str.reserve(size);
}
data = (char*)malloc(size + 1);
for(i = z = 0; i < ssl;) {
if(i <= ssl - ksl) {
if(!memcmp(str() + i, key, ksl)) {
memcpy(data + z, token, tsl);
z += tsl;
i += ksl;
} else data[z++] = str()[i++];
} else data[z++] = str()[i++];
}
data[z] = 0;
strcpy(str, data);
free(data);
return str;
}
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;
char *data;
if(ksl > ssl)return str;
if(tsl > ksl) {
for(i = 0; i <= ssl - ksl;) {
x = str()[i];
if(x == '\"' || x == '\'') {
l = i;
i++;
while(str()[i++] != x) {
if(i == ssl) {
i = l;
break;
}
}
}
if(!memcmp(str() + i, key, ksl)) {
replace_count++;
i += ksl;
} else i++;
}
size = ssl + ((tsl - ksl) * replace_count);
str.reserve(size);
}
data = (char*)malloc(size + 1);
for(i = z = 0; i < ssl;) {
x = str()[i];
if(x == '\"' || x == '\'') {
l = i++;
while(str()[i] != x && i < ssl)i++;
if(i >= ssl)i = l;
else {
memcpy(data + z, str() + l, i - l);
z += i - l;
}
}
if(i <= ssl - ksl) {
if(!memcmp(str() + i, key, ksl)) {
memcpy(data + z, token, tsl);
z += tsl;
i += ksl;
replace_count++;
} else data[z++] = str()[i++];
} else data[z++] = str()[i++];
}
data[z] = 0;
strcpy(str, data);
free(data);
return str;
}
#endif //ifdef BSTRING_H

View File

@@ -1,37 +1,39 @@
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)) {
strlcpy(dest[split_count++], src + lp, i - lp + 1);
i += ksl;
lp = i;
} else i++;
}
strcpy(dest[split_count++], src + lp);
}
void split(stringarray &dest, const char *key, const string &src) { split(dest, key, strptr(src)); }
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++;
while(src[i] != x && i < ssl)i++;
if(i >= ssl)i = z;
}
if(!memcmp(src + i, key, ksl)) {
strlcpy(dest[split_count++], src + lp, i - lp + 1);
i += ksl;
lp = i;
} else i++;
}
strcpy(dest[split_count++], src + lp);
}
void qsplit(stringarray &dest, const char *key, const string &src) { qsplit(dest, key, strptr(src)); }
#ifdef BSTRING_H
void split(lstring &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)) {
strlcpy(dest[split_count++], src + lp, i - lp + 1);
i += ksl;
lp = i;
} else i++;
}
strcpy(dest[split_count++], src + lp);
}
void qsplit(lstring &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++;
while(src[i] != x && i < ssl)i++;
if(i >= ssl)i = z;
}
if(!memcmp(src + i, key, ksl)) {
strlcpy(dest[split_count++], src + lp, i - lp + 1);
i += ksl;
lp = i;
} else i++;
}
strcpy(dest[split_count++], src + lp);
}
#endif //ifdef BSTRING_H

View File

@@ -0,0 +1,31 @@
#ifdef BSTRING_H
uint strlcpy(char *dest, const char *src, uint length) {
uint srclen = strlen(src);
length--;
if(length > srclen) length = srclen;
memcpy(dest, src, length);
dest[length] = 0;
return srclen;
}
uint strlcat(char *dest, const char *src, uint length) {
uint destlen = strlen(dest), srclen = strlen(src);
length--;
if(length > destlen + srclen) length = destlen + srclen;
memcpy(dest + destlen, src, length - destlen);
dest[length] = 0;
return destlen + srclen;
}
uint strlcpy(string &dest, const char *src, uint length) {
dest.reserve(length);
return strlcpy(dest(), src, length);
}
uint strlcat(string &dest, const char *src, uint length) {
dest.reserve(length);
return strlcat(dest(), src, length);
}
#endif //ifdef BSTRING_H

View File

@@ -0,0 +1,39 @@
#ifdef BSTRING_H
char* ltrim(char *str, const char *key) {
if(!key || !*key) return str;
while(strbegin(str, key)) {
string temp = str;
strcpy(str, temp() + strlen(key));
}
return str;
}
char* rtrim(char *str, const char *key) {
if(!key || !*key) return str;
while(strend(str, key)) {
str[strlen(str) - strlen(key)] = 0;
}
return str;
}
char* trim(char *str, const char *key) {
return ltrim(rtrim(str, key), key);
}
string& ltrim(string &str, const char *key) {
ltrim(str(), key);
return str;
}
string& rtrim(string &str, const char *key) {
rtrim(str(), key);
return str;
}
string& trim(string &str, const char *key) {
trim(str(), key);
return str;
}
#endif //ifdef BSTRING_H

View File

@@ -1,5 +1,6 @@
/*
libvector : version 0.05 ~byuu (2006-12-16)
bvector : version 0.05 ~byuu (2006-12-16)
license: public domain
*/
/*****
@@ -64,8 +65,8 @@
* and speed is less critical.
*****/
#ifndef LIBVECTOR_H
#define LIBVECTOR_H
#ifndef BVECTOR_H
#define BVECTOR_H
template<typename T> class linear_vector {
protected:
@@ -204,4 +205,4 @@ public:
}
};
#endif
#endif //ifndef BVECTOR_H

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