Compare commits

...
19 Commits
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
327 changed files with 12743 additions and 11109 deletions

No files matched your search

BIN
View File
Binary file not shown.
+1 -1
View File
@@ -1,4 +1,4 @@
bsnes (TM) Open Source Reference License
bsnes (TM) Reference License
Copyright (C) 2004 - 2007 byuu
All rights reserved
+1 -8
View File
@@ -1,5 +1,5 @@
bsnes
Version 0.025
Version 0.027
Author: byuu
--------
@@ -72,13 +72,6 @@ SETA DSP used only by Quick-move Shogi Match with Nidan Rank-holder Morita
ST-018
SETA RISC CPU used only by Quick-move Shogi Match with Nidan Rank-holder Morita 2
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
Super Gameboy
Cartridge passthrough used for playing Gameboy games
+333 -315
View File
@@ -1,315 +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 -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 -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 kernel32.lib user32.lib gdi32.lib shell32.lib winmm.lib comdlg32.lib comctl32.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 kernel32.lib user32.lib gdi32.lib shell32.lib winmm.lib comdlg32.lib comctl32.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 kernel32.lib user32.lib gdi32.lib shell32.lib winmm.lib comdlg32.lib comctl32.lib
LINK = /link /PGD:bsnes.pgd /LTCG:PGOPTIMIZE
LIBCO = libco_x86
LIBUI = libui_win
endif
ifeq ($(PLATFORM),win-mingw-lui)
OS = win
CC = mingw32-gcc
CFLAGS = -mwindows -O3 -fomit-frame-pointer -DPLATFORM_WIN -DCOMPILER_GCC -DPROCESSOR_X86 -DUI_LUI
AS = nasm
ASFLAGS = -f win32 -DWIN32
LIBS = -ld3d9 -lddraw -ldsound -ldinput8 -ldxguid -luuid -lkernel32 -luser32 -lgdi32 -lshell32 -lwinmm -lcomdlg32 -lcomctl32
LIBCO = libco_x86
LIBUI = libui_win
endif
ifeq ($(PLATFORM),win-mingw4-lui)
OS = win
CC = mingw32-gcc-sjlj
CFLAGS = -mconsole -O3 -fomit-frame-pointer -DPLATFORM_WIN -DCOMPILER_GCC -DPROCESSOR_X86 -DUI_LUI
AS = nasm
ASFLAGS = -f win32 -DWIN32
LIBS = -ld3d9 -lddraw -ldsound -ldinput8 -ldxguid -luuid -lkernel32 -luser32 -lgdi32 -lshell32 -lwinmm -lcomdlg32 -lcomctl32
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),mingw32-gcc)
OUT = -obsnes
CPP = mingw32-g++
OBJ = o
CARGS = -c $< -o $@
DEFINE = -D
endif
ifeq ($(CC),mingw32-gcc-sjlj)
OUT = -obsnes
CPP = mingw32-g++-sjlj
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) $(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) superfx.$(OBJ) srtc.$(OBJ) sdd1.$(OBJ) c4.$(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
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 ###
#####################
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/*
c4.$(OBJ) : chip/c4/c4.cpp chip/c4/*
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 ###
####################
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 ""
+54 -59
View File
@@ -1,59 +1,54 @@
#define BSNES_VERSION "0.025"
#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/libfunctor.h"
#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(const char*, ...);
void dprintf(const char*, ...);
void dprintf(uint, const 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"
+75 -102
View File
@@ -1,25 +1,50 @@
#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;
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) {
if(loaded() == true)return;
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.bsxbase = false;
info.bsxcart = false;
info.bsxflash = false;
info.st = false;
info.superfx = false;
info.sa1 = false;
info.srtc = false;
info.sdd1 = false;
info.c4 = false;
info.cx4 = false;
info.dsp1 = false;
info.dsp2 = false;
info.dsp3 = false;
@@ -29,134 +54,82 @@ void Cartridge::load_begin(CartridgeType cart_type) {
info.st011 = false;
info.st018 = false;
info.dsp1_mapper = 0;
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.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 CartridgeNormal: {
load_rom_normal();
load_ram_normal();
} break;
case CartridgeSufamiTurbo: {
load_rom_st();
load_ram_st();
} break;
case CartridgeSufamiTurboDual: {
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 CartridgeNormal: {
save_ram_normal();
} break;
case CartridgeSufamiTurbo: {
save_ram_st();
} break;
case CartridgeSufamiTurboDual: {
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();
}
+113 -100
View File
@@ -1,129 +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 CartridgeType {
CartridgeNormal,
CartridgeSufamiTurbo,
CartridgeSufamiTurboDual,
};
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,
COMPANY = 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();
bool superfx;
bool sa1;
bool srtc;
bool sdd1;
bool c4;
bool dsp1;
bool dsp2;
bool dsp3;
bool dsp4;
bool obc1;
bool st010;
bool st011;
bool st018;
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(CartridgeType 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
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
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());
}
+77 -43
View File
@@ -9,57 +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) {
alert("Error: file '%s' not found!", fn);
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;
+42 -25
View File
@@ -1,24 +1,37 @@
void Cartridge::read_header() {
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");
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;
//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;
}
}
}
}
uint8 mapper = rom[info.header_index + MAPPER];
uint8 rom_type = rom[info.header_index + ROM_TYPE];
uint8 company = rom[info.header_index + COMPANY];
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;
@@ -37,7 +50,7 @@ uint8 company = rom[info.header_index + COMPANY];
}
if(mapper == 0x20 && rom_type == 0xf3) {
info.c4 = true;
info.cx4 = true;
}
if((mapper == 0x20 || mapper == 0x21) && rom_type == 0x03) {
@@ -53,12 +66,12 @@ uint8 company = rom[info.header_index + COMPANY];
}
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;
}
}
@@ -95,6 +108,9 @@ uint8 company = rom[info.header_index + COMPANY];
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;
@@ -109,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;
@@ -150,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++;
+41 -56
View File
@@ -1,56 +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.header_index = 0xffc0;
info.mapper = PCB;
strcpy(info.name, dbi.name);
strcpy(info.pcb, dbi.pcb);
info.region = NTSC;
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);
}
+59 -45
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);
}
-66
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);
}
-37
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.
-119
View File
@@ -1,119 +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
[0xcf98ddaa]
name = "Super Mario World 2: Yoshi's Island (USA)"
pcb = "SHVC-1CB5B-01"
rom = 16mbit
ram = 256kbit
[0x64a91e64]
name = "Wanderers from Ys (USA) [!]"
pcb = "SHVC-1A3B-12"
rom = 8mbit
ram = 64kbit
-3
View File
@@ -1,3 +0,0 @@
cl /nologo /O2 dbcreate.cpp
@pause
@del *.obj
-1
View File
@@ -1 +0,0 @@
@del *.exe
-2
View File
@@ -1,2 +0,0 @@
dbcreate
@copy cart.db ..\..\..\cart.db
-47
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;
}
-117
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++) {
int pos = strpos(line[i], ";");
if(pos >= 0) {
strptr(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;
}
+4 -3
View File
@@ -1,5 +1,6 @@
::@make -r PLATFORM=win-mingw4-lui
::@make -r PLATFORM=win-visualc-lui
@make -r PLATFORM=win-visualc-lui GZIP_SUPPORT=true JMA_SUPPORT=true
@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
+1 -2
View File
@@ -1,2 +1 @@
#!/bin/sh
make PLATFORM=x-gcc-lui
make PLATFORM=x-gcc-x86
+29 -40
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
View File
@@ -0,0 +1,5 @@
#include "../../base.h"
#include "bsx_base.cpp"
#include "bsx_cart.cpp"
#include "bsx_flash.cpp"
+77
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
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
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
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
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"
+57 -59
View File
@@ -7,27 +7,27 @@
#include "../../base.h"
#include "c4data.cpp"
#include "c4fn.cpp"
#include "c4oam.cpp"
#include "c4ops.cpp"
#include "cx4data.cpp"
#include "cx4fn.cpp"
#include "cx4oam.cpp"
#include "cx4ops.cpp"
void C4::init() {}
void C4::enable() {}
void Cx4::init() {}
void Cx4::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;
@@ -39,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;
@@ -50,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];
}
@@ -65,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);
@@ -73,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) {
@@ -109,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) {
@@ -170,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() {}
+33 -32
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;
@@ -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,
+18 -18
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
@@ -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;
@@ -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);
}
+14 -13
View File
@@ -26,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);
}
+9 -9
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;
+2 -2
View File
@@ -28,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++];
@@ -40,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;
+34 -32
View File
@@ -1,42 +1,44 @@
class DSP2 { public:
struct {
bool waiting_for_command;
uint command;
uint in_count, in_index;
uint out_count, out_index;
class DSP2 : public Memory {
public:
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;
+5 -5
View File
@@ -1,7 +1,7 @@
#include "../../base.h"
namespace DSP3i {
#define bool8 bool
#define bool8 uint8
#include "dsp3emu.c"
#undef bool8
};
@@ -20,14 +20,14 @@ void DSP3::reset() {
DSP3i::DSP3_Reset();
}
uint8 DSP3::read(uint16 addr) {
DSP3i::dsp3_address = addr;
uint8 DSP3::read(uint addr) {
DSP3i::dsp3_address = addr & 0xffff;
DSP3i::DSP3GetByte();
return DSP3i::dsp3_byte;
}
void DSP3::write(uint16 addr, uint8 data) {
DSP3i::dsp3_address = addr;
void DSP3::write(uint addr, uint8 data) {
DSP3i::dsp3_address = addr & 0xffff;
DSP3i::dsp3_byte = data;
DSP3i::DSP3SetByte();
}
+4 -3
View File
@@ -1,11 +1,12 @@
class DSP3 { public:
class DSP3 : public Memory {
public:
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);
};
extern DSP3 dsp3;
+5 -3
View File
@@ -14,7 +14,7 @@ namespace DSP4i {
addr[1] = data >> 8;
}
#define bool8 bool
#define bool8 uint8
#include "dsp4emu.c"
#undef bool8
};
@@ -33,7 +33,8 @@ void DSP4::reset() {
DSP4i::InitDSP4();
}
uint8 DSP4::read(uint16 addr) {
uint8 DSP4::read(uint addr) {
addr &= 0xffff;
if(addr < 0xc000) {
DSP4i::dsp4_address = addr;
DSP4i::DSP4GetByte();
@@ -42,7 +43,8 @@ uint8 DSP4::read(uint16 addr) {
return 0x80;
}
void DSP4::write(uint16 addr, uint8 data) {
void DSP4::write(uint addr, uint8 data) {
addr &= 0xffff;
if(addr < 0xc000) {
DSP4i::dsp4_address = addr;
DSP4i::dsp4_byte = data;
+4 -3
View File
@@ -1,11 +1,12 @@
class DSP4 { public:
class DSP4 : public Memory {
public:
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);
};
extern DSP4 dsp4;
+33 -32
View File
@@ -8,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() {}
+17 -12
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;
+65 -48
View File
@@ -5,9 +5,7 @@
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() {
@@ -15,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;
@@ -80,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
+28 -21
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;
+1 -1
View File
@@ -28,7 +28,7 @@ understood.
************************************************************************/
#define SDD1_read(__addr) (r_mem->read(__addr))
#define SDD1_read(__addr) (bus.read(__addr))
////////////////////////////////////////////////////
+7 -7
View File
@@ -77,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() {
@@ -91,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) {
@@ -116,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
@@ -124,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;
+2 -2
View File
@@ -43,8 +43,8 @@ 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();
};
+11 -11
View File
@@ -60,23 +60,23 @@ void ST010::reset() {
//
uint8 ST010::read(uint16 addr) {
uint8 ST010::read(uint addr) {
return readb(addr);
}
void ST010::write(uint16 addr, uint8 data) {
void ST010::write(uint addr, uint8 data) {
writeb(addr, data);
if(addr == 0x0021 && data & 0x80) {
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;
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;
+16 -14
View File
@@ -1,8 +1,19 @@
class ST010 { public:
uint8 ram[0x1000];
static const int16 sin_table[256];
static const int16 mode7_scale[176];
static const uint8 arctan[32][32];
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);
@@ -26,15 +37,6 @@ static const uint8 arctan[32][32];
void op_08();
void op_01(int16 x0, int16 y0, int16 &x1, int16 &y1, int16 &quadrant, int16 &theta);
//base
void init();
void enable();
void power();
void reset();
uint8 read (uint16 addr);
void write(uint16 addr, uint8 data);
};
extern ST010 st010;
+3 -1
View File
@@ -1,4 +1,6 @@
uint8 SuperFX::mmio_read(uint16 addr) {
uint8 SuperFX::mmio_read(uint addr) {
addr &= 0xffff;
switch(addr) {
case 0x3000: return regs.r0.l;
case 0x3001: return regs.r0.h;
+3 -1
View File
@@ -1,4 +1,6 @@
void SuperFX::mmio_write(uint16 addr, uint8 data) {
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;
+1 -1
View File
@@ -10,7 +10,7 @@ void SuperFX::init() {
void SuperFX::enable() {
for(uint i = 0x3000; i <= 0x32ff; i++) {
r_mem->set_mmio_mapper(i, this);
memory::mmio.map(i, *this);
}
}
+2 -2
View File
@@ -6,8 +6,8 @@ class SuperFX : public MMIO { public:
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);
private:
#include "regs.h"
+2 -2
View File
@@ -1,2 +1,2 @@
::@make PLATFORM=win-mingw4-lui clean
@make PLATFORM=win-visualc-lui clean
@make PLATFORM=win-mingw-x86 clean
::@make PLATFORM=win-visualc-x86 clean
+1 -2
View File
@@ -1,2 +1 @@
#!/bin/sh
make PLATFORM=x-gcc-lui clean
make PLATFORM=x-gcc-x86 clean
+18 -11
View File
@@ -15,33 +15,27 @@ 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(), "path.rom",
"Default path to look for ROM files in (\"\" = use default directory)", "");
StringSetting Path::save(&config(), "path.save",
"Default path for all save RAM and cheat files (\"\" = use current directory)", "");
StringSetting Path::bios(&config(), "path.bios",
"Path where BIOS file(s) are located\n"
"Supported BIOS files:\n"
"stbios.bin - Bandai Sufami Turbo"
"", "./bios");
StringSetting Path::save_ext(&config(), "path.save_ext",
"Extension to be used for all save RAM files", "srm");
StringSetting Path::bsx(&config(), "path.bsx", "", "");
StringSetting Path::st(&config(), "path.st", "", "");
IntegerSetting SNES::gamma_ramp(&config(), "snes.colorfilter.gamma_ramp",
"Use precalculated TV-style gamma ramp", IntegerSetting::Boolean, true);
@@ -75,6 +69,19 @@ 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(), "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);
+3 -2
View File
@@ -5,8 +5,8 @@ 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;
+1 -1
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) {
+8 -8
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);
@@ -84,7 +84,7 @@ 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());
bus.write(0x2100 | bbus, sdd1.dma_read());
} else {
dma_transfer(0, bbus, dma_addr(i));
}
@@ -167,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);
}
}
+4 -4
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();
}
+11 -7
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();
+2 -2
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();
+2 -2
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;
+3 -3
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();
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

BIN
View File
Binary file not shown.
+1 -1
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);
+6 -1
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 };
+37 -79
View File
@@ -1,79 +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/superfx/superfx.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/dsp3/dsp3.h"
#include "chip/dsp4/dsp4.h"
#include "chip/obc1/obc1.h"
#include "chip/st010/st010.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
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
+30 -35
View File
@@ -1,10 +1,10 @@
/*
libbase : version 0.11 ~byuu (2007-09-08)
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>
@@ -109,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) {
@@ -169,36 +189,6 @@ enum { b = 1U << (bits - 1), m = (1U << bits) - 1 };
return ((x & m) ^ b) - b;
}
//bit shifting functions are deprecated
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
*****/
@@ -241,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++) {
@@ -349,4 +344,4 @@ uint32 crc32 = ~0;
return ~crc32;
}
#endif
#endif //ifndef BBASE_H
+52 -52
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
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
+5 -4
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
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
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
+14
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
@@ -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
+277
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
@@ -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
@@ -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
+31
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
+39
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
+5 -4
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
-86
View File
@@ -1,86 +0,0 @@
/*
libarray : version 0.09 ~byuu (2007-03-06)
*/
#ifndef LIBARRAY_H
#define LIBARRAY_H
template<typename T> class array {
protected:
T *pool;
uint poolsize, buffersize;
protected:
uint findsize(uint size) {
if(size <= 0x100) { return 0x100; }
if(size <= 0x400) { return 0x400; }
if(size <= 0x1000) { return 0x1000; }
if(size <= 0x4000) { return 0x4000; }
if(size <= 0x10000) { return 0x10000; }
if(size <= 0x40000) { return 0x40000; }
if(size <= 0x100000) { return 0x100000; }
return (size + 0x100000) & ~0xfffff;
}
public:
uint size() { return buffersize; }
uint capacity() { return 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 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;
//allocate entire pool size ...
pool = (T*)realloc(pool, sizeof(T) * poolsize);
//... but only copy used pool objects
memcpy(pool, source.pool, sizeof(T) * buffersize);
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
+37
View File
@@ -0,0 +1,37 @@
/*
libco
version: 0.11 (2007-12-11)
license: public domain
*/
#ifndef LIBCO_H
#define LIBCO_H
#ifdef __cplusplus
extern "C" {
#endif
#if defined(__i386__)
#if defined(__GNUC__)
#define calltype __attribute__((fastcall))
#elif defined(_MSC_VER)
#define calltype __fastcall
#endif
#else
#define calltype
#endif
typedef void* cothread_t;
cothread_t calltype co_active();
cothread_t calltype co_create(unsigned int heapsize, void (*coentry)());
void calltype co_delete(cothread_t cothread);
void calltype co_switch(cothread_t cothread);
#undef calltype
#ifdef __cplusplus
} //extern "C"
#endif
#endif //ifndef LIBCO_H
+478
View File
@@ -0,0 +1,478 @@
;*****
;libco.ppc (2007-11-29)
;author: Vas Crabb
;license: public domain
;
;cross-platform PowerPC implementation of libco
;special thanks to byuu for writing the original version
;
;[ABI compatibility]
;- gcc; mac os x; ppc
;
;[nonvolatile registers]
;- GPR1, GPR13 - GPR31
;- FPR14 - FPR31
;- V20 - V31
;- VRSAVE, CR2 - CR4
;
;[volatile registers]
;- GPR0, GPR2 - GPR12
;- FPR0 - FPR13
;- V0 - V19
;- LR, CTR, XER, CR0, CR1, CR5 - CR7
;*****
;Declare some target-specific stuff
.section __TEXT,__text,regular,pure_instructions
.section __TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32
.machine ppc
;Constants
.cstring
.align 2
_sysctl_altivec:
.ascii "hw.optional.altivec\0"
;Declare space for variables
.lcomm _co_environ,4,2 ;bit 0 = initialised, bit 1 = have Altivec/VMX
.lcomm _co_primary_buffer,1024,2 ;buffer (will be zeroed by loader)
.data
.align 2
_co_active_context:
.long _co_primary_buffer
.text
.align 2
;Declare exported names
.globl _co_active
.globl _co_create
.globl _co_delete
.globl _co_switch
;*****
;extern "C" cothread_t co_active();
;return = GPR3
;*****
_co_active:
mflr r0 ;GPR0 = return address
bcl 20,31,L_co_active$spb
L_co_active$spb:
mflr r2 ;GPR2 set for position-independance
addis r3,r2,ha16(_co_active_context-L_co_active$spb) ;get value in GPR3
lwz r3,lo16(_co_active_context-L_co_active$spb)(r3)
mtlr r0 ;LR = return address
blr ;return
;*****
;extern "C" cothread_t co_create(unsigned int heapsize, void (*coentry)());
;GPR3 = heapsize
;GPR4 = coentry
;return = GPR3
;*****
_co_create:
mflr r0 ;GPR0 = return address
stmw r30,-8(r1) ;save GPR30 and GPR31
stw r0,8(r1) ;save return address
stwu r1,-(2*4+16+24)(r1) ;allocate 16 bytes for locals/parameters
;create heap space (stack + register storage)
addi r31,r3,1024-24 ;subtract space for linkage
mr r30,r4 ;GPR30 = coentry
addi r3,r3,1024 ;allocate extra memory for contextual info
bl L_malloc$stub ;GPR3 = malloc(heapsize + 1024)
add r4,r3,r31 ;GPR4 points to top-of-stack
rlwinm r5,r4,0,0,27 ;force 16-byte alignment
;store thread entry point + registers, so that first call to co_switch will execute coentry
stw r30,8(r5) ;store entry point
addi r6,0,2+19+18*2+12*4+1 ;clear for CR, old GPR1, 19 GPRs, 18 FPRs, 12 VRs, VRSAVE
addi r0,0,0
addi r7,0,4 ;start at 4(GPR5)
mtctr r6
L_co_create$clear_loop:
stwx r0,r5,r7 ;clear a word
addi r7,r7,-4 ;increment pointer
bdnz L_co_create$clear_loop ;loop
stwu r5,-448(r5) ;store top of stack
;initialize context memory heap and return
stw r5,0(r3) ;*cothread_t = stack heap pointer (GPR1)
lwz r1,0(r1) ;deallocate stack frame
lwz r8,8(r1) ;fetch return address
lmw r30,-8(r1) ;restore GPR30 and GPR31
mtlr r8 ;return address in LR
blr ;return
;*****
;extern "C" void co_delete(cothread_t cothread);
;GPR3 = cothread
;*****
_co_delete:
b L_free$stub ;free(GPR3)
;*****
;extern "C" void co_switch(cothread_t cothread);
;GPR3 = cothread
;*****
;
;Frame looks like:
;
;Old New Value
; 8(r1) 456(r1) Saved LR
; 4(r1) 452(r1) Saved CR
; 0(r1) 448(r1) Old GPR1
; -4(r1) 444(r1) Saved GPR31
; -8(r1) 440(r1) Saved GPR30
;... ... ...
; -72(r1) 376(r1) Saved GPR14
; -76(r1) 372(r1) Saved GPR13
; -80(r1) 368(r1) Saved VRSAVE
; -84(r1) 364(r1) +++
; -88(r1) 360(r1) Saved FPR31
; -92(r1) 356(r1) +++
; -96(r1) 352(r1) Saved FPR30
;... ... ...
;-212(r1) 236(r1) +++
;-216(r1) 232(r1) Saved FPR15
;-220(r1) 228(r1) +++
;-224(r1) 224(r1) Saved FPR14
;-228(r1) 220(r1) +++ value
;-232(r1) 216(r1) +++ len
;-236(r1) 212(r1) +++
;-240(r1) 208(r1) Saved VR31
;-244(r1) 204(r1) +++
;-248(r1) 200(r1) +++
;-252(r1) 196(r1) +++
;-256(r1) 192(r1) Saved VR30
;... ... ...
;-388(r1) 60(r1) +++
;-392(r1) 56(r1) +++
;-396(r1) 52(r1) +++
;-400(r1) 48(r1) Saved VR21
;-404(r1) 44(r1) +++
;-408(r1) 40(r1) +++ Param 5 (GPR7)
;-412(r1) 36(r1) +++ Param 4 (GPR6)
;-416(r1) 32(r1) Saved VR20 Param 3 (GPR5)
;-420(r1) 28(r1) - Param 2 (GPR4)
;-424(r1) 24(r1) - Param 1 (GPR3)
;-428(r1) 20(r1) - Reserved
;-432(r1) 16(r1) - Reserved
;-436(r1) 12(r1) - Reserved
;-440(r1) 8(r1) - New LR
;-444(r1) 4(r1) - New CR
;-448(r1) 0(r1) Saved GPR1
_co_switch:
stmw r13,-76(r1) ;save preserved GPRs
stfd f14,-224(r1) ;save preserved FPRs
stfd f15,-216(r1)
stfd f16,-208(r1)
stfd f17,-200(r1)
stfd f18,-192(r1)
stfd f19,-184(r1)
stfd f20,-176(r1)
stfd f21,-168(r1)
stfd f22,-160(r1)
stfd f23,-152(r1)
stfd f24,-144(r1)
stfd f25,-136(r1)
stfd f26,-128(r1)
stfd f27,-120(r1)
stfd f28,-112(r1)
stfd f29,-104(r1)
stfd f30,-96(r1)
stfd f31,-88(r1)
mflr r0 ;save return address
stw r0,8(r1)
mfcr r2 ;save condition codes
stw r2,4(r1)
stwu r1,-448(r1) ;create stack frame (save 19 GPRs, 18 FRPs, 12 VRs, VRSAVE)
mr r30,r3 ;save new context pointer
bcl 20,31,L_co_switch$spb ;get address of co_active_context
L_co_switch$spb:
mflr r31
addis r29,r31,ha16(_co_environ-L_co_switch$spb) ;get environment flags
lwz r8,lo16(_co_environ-L_co_switch$spb)(r29)
andis. r9,r8,0x8000 ;is it initialised?
bne+ L_co_switch$initialised
addi r0,0,4 ;len = sizeof(int)
stw r0,216(r1)
addis r3,r31,ha16(_sysctl_altivec-L_co_switch$spb) ;GPR3 = "hw.optional.altivec"
addi r3,r3,lo16(_sysctl_altivec-L_co_switch$spb)
addi r4,r1,220 ;GPR4 = &value
addi r5,r1,216 ;GPR5 = &len
addi r6,0,0 ;newp = 0
addi r7,0,0 ;newlen = 0
bl L_sysctlbyname$stub ;call sysctlbyname
lwz r2,220(r1) ;fetch result
addis r8,0,0x8000 ;set initialised bit
cmpwi cr5,r3,0 ;assume error means not present
cmpwi cr6,r2,0 ;test result
blt- cr5,L_co_switch$store_environ
beq cr6,L_co_switch$store_environ
oris r8,r8,0x4000 ;set the flag to say we have it!
L_co_switch$store_environ:
stw r8,lo16(_co_environ-L_co_switch$spb)(r29) ;store environment flags
L_co_switch$initialised:
andis. r10,r8,0x4000 ;do we have Altivec/VMX?
beq L_co_switch$save_no_vmx
mfspr r11,256 ;save VRSAVE
andi. r0,r11,0x0FFF ;short-circuit if it's zero
stw r11,368(r1)
beq L_co_switch$save_no_vmx
andi. r0,r11,0x0800 ;check bit 20
addi r2,0,32 ;starting index
beq L_co_switch$save_skip_vr20
stvx v20,r1,r2 ;save VR20
L_co_switch$save_skip_vr20:
addi r2,r2,16 ;stride
andi. r0,r11,0x0400 ;check bit 21
beq L_co_switch$save_skip_vr21
stvx v21,r1,r2 ;save VR21
L_co_switch$save_skip_vr21:
addi r2,r2,16 ;stride
andi. r0,r11,0x0200 ;check bit 22
beq L_co_switch$save_skip_vr22
stvx v22,r1,r2 ;save VR22
L_co_switch$save_skip_vr22:
addi r2,r2,16 ;stride
andi. r0,r11,0x0100 ;check bit 23
beq L_co_switch$save_skip_vr23
stvx v23,r1,r2 ;save VR23
L_co_switch$save_skip_vr23:
addi r2,r2,16 ;stride
andi. r0,r11,0x0080 ;check bit 24
beq L_co_switch$save_skip_vr24
stvx v24,r1,r2 ;save VR24
L_co_switch$save_skip_vr24:
addi r2,r2,16 ;stride
andi. r0,r11,0x0040 ;check bit 25
beq L_co_switch$save_skip_vr25
stvx v25,r1,r2 ;save VR25
L_co_switch$save_skip_vr25:
addi r2,r2,16 ;stride
andi. r0,r11,0x0020 ;check bit 26
beq L_co_switch$save_skip_vr26
stvx v26,r1,r2 ;save VR26
L_co_switch$save_skip_vr26:
addi r2,r2,16 ;stride
andi. r0,r11,0x0010 ;check bit 27
beq L_co_switch$save_skip_vr27
stvx v27,r1,r2 ;save VR27
L_co_switch$save_skip_vr27:
addi r2,r2,16 ;stride
andi. r0,r11,0x0008 ;check bit 28
beq L_co_switch$save_skip_vr28
stvx v28,r1,r2 ;save VR28
L_co_switch$save_skip_vr28:
addi r2,r2,16 ;stride
andi. r0,r11,0x0004 ;check bit 29
beq L_co_switch$save_skip_vr29
stvx v29,r1,r2 ;save VR29
L_co_switch$save_skip_vr29:
addi r2,r2,16 ;stride
andi. r0,r11,0x0002 ;check bit 30
beq L_co_switch$save_skip_vr30
stvx v30,r1,r2 ;save VR30
L_co_switch$save_skip_vr30:
addi r2,r2,16 ;stride
andi. r0,r11,0x0001 ;check bit 31
beq L_co_switch$save_skip_vr31
stvx v31,r1,r2 ;save VR31
L_co_switch$save_skip_vr31:
L_co_switch$save_no_vmx:
addis r4,r31,ha16(_co_active_context-L_co_switch$spb) ;save current context
lwz r5,lo16(_co_active_context-L_co_switch$spb)(r4)
stw r30,lo16(_co_active_context-L_co_switch$spb)(r4);set new context
stw r1,0(r5) ;save current stack pointer
lwz r1,0(r30) ;get new stack pointer
andis. r10,r8,0x4000 ;do we have Altivec/VMX?
beq L_co_switch$restore_no_vmx
lwz r11,368(r1) ;restore VRSAVE
andi. r0,r11,0x0FFF ;short-circuit if it's zero
mtspr 256,r11
beq L_co_switch$restore_no_vmx
andi. r0,r11,0x0800 ;check bit 20
addi r2,0,32 ;starting index
beq L_co_switch$restore_skip_vr20
lvx v20,r1,r2 ;restore VR20
L_co_switch$restore_skip_vr20:
addi r2,r2,16 ;stride
andi. r0,r11,0x0400 ;check bit 21
beq L_co_switch$restore_skip_vr21
lvx v21,r1,r2 ;restore VR21
L_co_switch$restore_skip_vr21:
addi r2,r2,16 ;stride
andi. r0,r11,0x0200 ;check bit 22
beq L_co_switch$restore_skip_vr22
lvx v22,r1,r2 ;restore VR22
L_co_switch$restore_skip_vr22:
addi r2,r2,16 ;stride
andi. r0,r11,0x0100 ;check bit 23
beq L_co_switch$restore_skip_vr23
lvx v23,r1,r2 ;restore VR23
L_co_switch$restore_skip_vr23:
addi r2,r2,16 ;stride
andi. r0,r11,0x0080 ;check bit 24
beq L_co_switch$restore_skip_vr24
lvx v24,r1,r2 ;restore VR24
L_co_switch$restore_skip_vr24:
addi r2,r2,16 ;stride
andi. r0,r11,0x0040 ;check bit 25
beq L_co_switch$restore_skip_vr25
lvx v25,r1,r2 ;restore VR25
L_co_switch$restore_skip_vr25:
addi r2,r2,16 ;stride
andi. r0,r11,0x0020 ;check bit 26
beq L_co_switch$restore_skip_vr26
lvx v26,r1,r2 ;restore VR26
L_co_switch$restore_skip_vr26:
addi r2,r2,16 ;stride
andi. r0,r11,0x0010 ;check bit 27
beq L_co_switch$restore_skip_vr27
lvx v27,r1,r2 ;restore VR27
L_co_switch$restore_skip_vr27:
addi r2,r2,16 ;stride
andi. r0,r11,0x0008 ;check bit 28
beq L_co_switch$restore_skip_vr28
lvx v28,r1,r2 ;restore VR28
L_co_switch$restore_skip_vr28:
addi r2,r2,16 ;stride
andi. r0,r11,0x0004 ;check bit 29
beq L_co_switch$restore_skip_vr29
lvx v29,r1,r2 ;restore VR29
L_co_switch$restore_skip_vr29:
addi r2,r2,16 ;stride
andi. r0,r11,0x0002 ;check bit 30
beq L_co_switch$restore_skip_vr30
lvx v30,r1,r2 ;restore VR30
L_co_switch$restore_skip_vr30:
addi r2,r2,16 ;stride
andi. r0,r11,0x0001 ;check bit 31
beq L_co_switch$restore_skip_vr31
lvx v31,r1,r2 ;restore VR31
L_co_switch$restore_skip_vr31:
L_co_switch$restore_no_vmx:
lwz r1,0(r1) ;deallocate stack frame
lwz r6,8(r1) ;return address in GPR6
lwz r7,4(r1) ;condition codes in GPR7
addi r0,0,0 ;make thread main crash if it returns
lmw r13,-76(r1) ;restore preserved GPRs
lfd f14,-224(r1) ;restore preserved FPRs
lfd f15,-216(r1)
lfd f16,-208(r1)
lfd f17,-200(r1)
lfd f18,-192(r1)
lfd f19,-184(r1)
lfd f20,-176(r1)
lfd f21,-168(r1)
lfd f22,-160(r1)
lfd f23,-152(r1)
lfd f24,-144(r1)
lfd f25,-136(r1)
lfd f26,-128(r1)
lfd f27,-120(r1)
lfd f28,-112(r1)
lfd f29,-104(r1)
lfd f30,-96(r1)
lfd f31,-88(r1)
mtlr r0
mtctr r6 ;restore return address
mtcrf 32,r7 ;restore preserved condition codes
mtcrf 16,r7
mtcrf 8,r7
bctr ;return
;Import external functions
.section __TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32
.align 5
L_malloc$stub:
.indirect_symbol _malloc
mflr r0
bcl 20,31,L_malloc$spb
L_malloc$spb:
mflr r11
addis r11,r11,ha16(L_malloc$lazy_ptr-L_malloc$spb)
mtlr r0
lwzu r12,lo16(L_malloc$lazy_ptr-L_malloc$spb)(r11)
mtctr r12
bctr
.lazy_symbol_pointer
L_malloc$lazy_ptr:
.indirect_symbol _malloc
.long dyld_stub_binding_helper
.section __TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32
.align 5
L_free$stub:
.indirect_symbol _free
mflr r0
bcl 20,31,L_free$spb
L_free$spb:
mflr r11
addis r11,r11,ha16(L_free$lazy_ptr-L_free$spb)
mtlr r0
lwzu r12,lo16(L_free$lazy_ptr-L_free$spb)(r11)
mtctr r12
bctr
.lazy_symbol_pointer
L_free$lazy_ptr:
.indirect_symbol _free
.long dyld_stub_binding_helper
.section __TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32
.align 5
L_sysctlbyname$stub:
.indirect_symbol _sysctlbyname
mflr r0
bcl 20,31,L_sysctlbyname$spb
L_sysctlbyname$spb:
mflr r11
addis r11,r11,ha16(L_sysctlbyname$lazy_ptr-L_sysctlbyname$spb)
mtlr r0
lwzu r12,lo16(L_sysctlbyname$lazy_ptr-L_sysctlbyname$spb)(r11)
mtctr r12
bctr
.lazy_symbol_pointer
L_sysctlbyname$lazy_ptr:
.indirect_symbol _sysctlbyname
.long dyld_stub_binding_helper
;This needs to be here!
.subsections_via_symbols
+513
View File
@@ -0,0 +1,513 @@
;*****
;libco.ppc64 (2007-12-05)
;author: Vas Crabb
;license: public domain
;
;cross-platform 64-bit PowerPC implementation of libco
;special thanks to byuu for writing the original version
;
;[ABI compatibility]
;- gcc; mac os x; ppc64
;
;[nonvolatile registers]
;- GPR1, GPR13 - GPR31
;- FPR14 - FPR31
;- V20 - V31
;- VRSAVE, CR2 - CR4
;
;[volatile registers]
;- GPR0, GPR2 - GPR12
;- FPR0 - FPR13
;- V0 - V19
;- LR, CTR, XER, CR0, CR1, CR5 - CR7
;*****
;Declare some target-specific stuff
.section __TEXT,__text,regular,pure_instructions
.section __TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32
.machine ppc64
;Constants
.cstring
.align 3
_sysctl_altivec:
.ascii "hw.optional.altivec\0"
;Declare space for variables
.lcomm _co_environ,4,2 ;bit 0 = initialised, bit 1 = have Altivec/VMX
.lcomm _co_primary_buffer,1024,3 ;buffer (will be zeroed by loader)
.data
.align 3
_co_active_context:
.quad _co_primary_buffer
.text
.align 2
;Declare exported names
.globl _co_active
.globl _co_create
.globl _co_delete
.globl _co_switch
;*****
;extern "C" cothread_t co_active();
;return = GPR3
;*****
_co_active:
mflr r0 ;GPR0 = return address
bcl 20,31,L_co_active$spb
L_co_active$spb:
mflr r2 ;GPR2 set for position-independance
addis r3,r2,ha16(_co_active_context-L_co_active$spb) ;get value in GPR3
ld r3,lo16(_co_active_context-L_co_active$spb)(r3)
mtlr r0 ;LR = return address
blr ;return
;*****
;extern "C" cothread_t co_create(unsigned int heapsize, void (*coentry)());
;GPR3 = heapsize
;GPR4 = coentry
;return = GPR3
;*****
_co_create:
mflr r0 ;GPR0 = return address
std r30,-16(r1) ;save GPR30 and GPR31
std r31,-8(r1)
std r0,16(r1) ;save return address
stdu r1,-(2*8+16+48)(r1) ;allocate 16 bytes for locals/parameters
;create heap space (stack + register storage)
addi r31,r3,1024-48 ;subtract space for linkage
mr r30,r4 ;GPR30 = coentry
addi r3,r3,1024 ;allocate extra memory for contextual info
bl L_malloc$stub ;GPR3 = malloc(heapsize + 1024)
add r4,r3,r31 ;GPR4 points to top-of-stack
rldicr r5,r4,0,59 ;force 16-byte alignment
;store thread entry point + registers, so that first call to co_switch will execute coentry
std r30,16(r5) ;store entry point
addi r6,0,2+19+18+12*2+1 ;clear for CR, old GPR1, 19 GPRs, 18 FPRs, 12 VRs, VRSAVE
addi r0,0,0
addi r7,0,8 ;start at 8(GPR5)
mtctr r6
L_co_create$clear_loop:
stdx r0,r5,r7 ;clear a double
addi r7,r7,-8 ;increment pointer
bdnz L_co_create$clear_loop ;loop
stdu r5,-544(r5) ;store top of stack
;initialize context memory heap and return
addis r9,0,0x8000 ;GPR13 not set (system TLS)
std r5,0(r3) ;*cothread_t = stack heap pointer (GPR1)
stw r9,8(r3) ;this is a flag word
ld r1,0(r1) ;deallocate stack frame
ld r8,16(r1) ;fetch return address
ld r30,-16(r1) ;restore GPR30 and GPR31
ld r31,-8(r1)
mtlr r8 ;return address in LR
blr ;return
;*****
;extern "C" void co_delete(cothread_t cothread);
;GPR3 = cothread
;*****
_co_delete:
b L_free$stub ;free(GPR3)
;*****
;extern "C" void co_switch(cothread_t cothread);
;GPR3 = cothread
;*****
;
;Frame looks like:
;
;Old New Value
; 16(r1) 560(r1) Saved LR
; 8(r1) 552(r1) Saved CR
; 0(r1) 544(r1) Old GPR1
; -8(r1) 536(r1) Saved GPR31
; -16(r1) 528(r1) Saved GPR30
;... ... ...
;-144(r1) 400(r1) Saved GPR14
;-152(r1) 392(r1) Saved GPR13
;-160(r1) 384(r1) Saved FPR31
;-168(r1) 376(r1) Saved FPR30
;... ... ...
;-288(r1) 256(r1) Saved FPR15
;-296(r1) 248(r1) Saved FPR14
;-304(r1) 240(r1) Saved VRSAVE
;-312(r1) 232(r1) +++ value
;-320(r1) 224(r1) Saved VR31 len
;-328(r1) 216(r1) +++
;-336(r1) 208(r1) Saved VR30
;... ... ...
;-456(r1) 88(r1) +++
;-464(r1) 80(r1) Saved VR22 Param 5 (GPR7)
;-472(r1) 72(r1) +++ Param 4 (GPR6)
;-480(r1) 64(r1) Saved VR21 Param 3 (GPR5)
;-488(r1) 56(r1) +++ Param 2 (GPR4)
;-496(r1) 48(r1) Saved VR20 Param 1 (GPR3)
;-504(r1) 40(r1) - Reserved
;-512(r1) 32(r1) - Reserved
;-520(r1) 24(r1) - Reserved
;-528(r1) 16(r1) - New LR
;-536(r1) 8(r1) - New CR
;-544(r1) 0(r1) Saved GPR1
_co_switch:
std r13,-152(r1) ;save preserved GPRs
std r14,-144(r1)
std r15,-136(r1)
std r16,-128(r1)
std r17,-120(r1)
std r18,-112(r1)
std r19,-104(r1)
std r20,-96(r1)
std r21,-88(r1)
std r22,-80(r1)
std r23,-72(r1)
std r24,-64(r1)
std r25,-56(r1)
std r26,-48(r1)
std r27,-40(r1)
std r28,-32(r1)
std r29,-24(r1)
std r30,-16(r1)
std r31,-8(r1)
mflr r0 ;save return address
std r0,16(r1)
mfcr r2 ;save condition codes
stw r2,8(r1)
stdu r1,-544(r1) ;create stack frame (save 19 GPRs, 18 FRPs, 12 VRs, VRSAVE)
stfd f14,248(r1) ;save preserved FPRs
stfd f15,256(r1)
stfd f16,264(r1)
stfd f17,272(r1)
stfd f18,280(r1)
stfd f19,288(r1)
stfd f20,296(r1)
stfd f21,304(r1)
stfd f22,312(r1)
stfd f23,320(r1)
stfd f24,328(r1)
stfd f25,336(r1)
stfd f26,344(r1)
stfd f27,352(r1)
stfd f28,360(r1)
stfd f29,368(r1)
stfd f30,376(r1)
stfd f31,384(r1)
mr r30,r3 ;save new context pointer
bcl 20,31,L_co_switch$spb ;get address of co_active_context
L_co_switch$spb:
mflr r31
addis r29,r31,ha16(_co_environ-L_co_switch$spb) ;get environment flags
lwz r8,lo16(_co_environ-L_co_switch$spb)(r29)
andis. r9,r8,0x8000 ;is it initialised?
bne+ L_co_switch$initialised
addi r0,0,4 ;len = sizeof(int)
std r0,224(r1)
addis r3,r31,ha16(_sysctl_altivec-L_co_switch$spb) ;GPR3 = "hw.optional.altivec"
addi r3,r3,lo16(_sysctl_altivec-L_co_switch$spb)
addi r4,r1,232 ;GPR4 = &value
addi r5,r1,224 ;GPR5 = &len
addi r6,0,0 ;newp = 0
addi r7,0,0 ;newlen = 0
bl L_sysctlbyname$stub ;call sysctlbyname
lwz r2,232(r1) ;fetch result
addis r8,0,0x8000 ;set initialised bit
cmpdi cr5,r3,0 ;assume error means not present
cmpwi cr6,r2,0 ;test result
blt- cr5,L_co_switch$store_environ
beq cr6,L_co_switch$store_environ
oris r8,r8,0x4000 ;set the flag to say we have it!
L_co_switch$store_environ:
stw r8,lo16(_co_environ-L_co_switch$spb)(r29) ;store environment flags
L_co_switch$initialised:
andis. r10,r8,0x4000 ;do we have Altivec/VMX?
beq L_co_switch$save_no_vmx
mfspr r11,256 ;save VRSAVE
andi. r0,r11,0x0FFF ;short-circuit if it's zero
stw r11,240(r1)
beq L_co_switch$save_no_vmx
andi. r0,r11,0x0800 ;check bit 20
addi r2,0,48 ;starting index
beq L_co_switch$save_skip_vr20
stvx v20,r1,r2 ;save VR20
L_co_switch$save_skip_vr20:
addi r2,r2,16 ;stride
andi. r0,r11,0x0400 ;check bit 21
beq L_co_switch$save_skip_vr21
stvx v21,r1,r2 ;save VR21
L_co_switch$save_skip_vr21:
addi r2,r2,16 ;stride
andi. r0,r11,0x0200 ;check bit 22
beq L_co_switch$save_skip_vr22
stvx v22,r1,r2 ;save VR22
L_co_switch$save_skip_vr22:
addi r2,r2,16 ;stride
andi. r0,r11,0x0100 ;check bit 23
beq L_co_switch$save_skip_vr23
stvx v23,r1,r2 ;save VR23
L_co_switch$save_skip_vr23:
addi r2,r2,16 ;stride
andi. r0,r11,0x0080 ;check bit 24
beq L_co_switch$save_skip_vr24
stvx v24,r1,r2 ;save VR24
L_co_switch$save_skip_vr24:
addi r2,r2,16 ;stride
andi. r0,r11,0x0040 ;check bit 25
beq L_co_switch$save_skip_vr25
stvx v25,r1,r2 ;save VR25
L_co_switch$save_skip_vr25:
addi r2,r2,16 ;stride
andi. r0,r11,0x0020 ;check bit 26
beq L_co_switch$save_skip_vr26
stvx v26,r1,r2 ;save VR26
L_co_switch$save_skip_vr26:
addi r2,r2,16 ;stride
andi. r0,r11,0x0010 ;check bit 27
beq L_co_switch$save_skip_vr27
stvx v27,r1,r2 ;save VR27
L_co_switch$save_skip_vr27:
addi r2,r2,16 ;stride
andi. r0,r11,0x0008 ;check bit 28
beq L_co_switch$save_skip_vr28
stvx v28,r1,r2 ;save VR28
L_co_switch$save_skip_vr28:
addi r2,r2,16 ;stride
andi. r0,r11,0x0004 ;check bit 29
beq L_co_switch$save_skip_vr29
stvx v29,r1,r2 ;save VR29
L_co_switch$save_skip_vr29:
addi r2,r2,16 ;stride
andi. r0,r11,0x0002 ;check bit 30
beq L_co_switch$save_skip_vr30
stvx v30,r1,r2 ;save VR30
L_co_switch$save_skip_vr30:
addi r2,r2,16 ;stride
andi. r0,r11,0x0001 ;check bit 31
beq L_co_switch$save_skip_vr31
stvx v31,r1,r2 ;save VR31
L_co_switch$save_skip_vr31:
L_co_switch$save_no_vmx:
addis r4,r31,ha16(_co_active_context-L_co_switch$spb) ;save current context
ld r5,lo16(_co_active_context-L_co_switch$spb)(r4)
std r30,lo16(_co_active_context-L_co_switch$spb)(r4);set new context
std r1,0(r5) ;save current stack pointer
ld r1,0(r30) ;get new stack pointer
lwz r12,8(r30) ;have we already set GPR13 (system TLS)?
andis. r0,r12,0x8000
beq+ L_co_switch$gpr13_set
std r13,392(r1)
xoris r12,r12,0x8000
stw r12,8(r30)
L_co_switch$gpr13_set:
andis. r10,r8,0x4000 ;do we have Altivec/VMX?
beq L_co_switch$restore_no_vmx
lwz r11,240(r1) ;restore VRSAVE
andi. r0,r11,0x0FFF ;short-circuit if it's zero
mtspr 256,r11
beq L_co_switch$restore_no_vmx
andi. r0,r11,0x0800 ;check bit 20
addi r2,0,48 ;starting index
beq L_co_switch$restore_skip_vr20
lvx v20,r1,r2 ;restore VR20
L_co_switch$restore_skip_vr20:
addi r2,r2,16 ;stride
andi. r0,r11,0x0400 ;check bit 21
beq L_co_switch$restore_skip_vr21
lvx v21,r1,r2 ;restore VR21
L_co_switch$restore_skip_vr21:
addi r2,r2,16 ;stride
andi. r0,r11,0x0200 ;check bit 22
beq L_co_switch$restore_skip_vr22
lvx v22,r1,r2 ;restore VR22
L_co_switch$restore_skip_vr22:
addi r2,r2,16 ;stride
andi. r0,r11,0x0100 ;check bit 23
beq L_co_switch$restore_skip_vr23
lvx v23,r1,r2 ;restore VR23
L_co_switch$restore_skip_vr23:
addi r2,r2,16 ;stride
andi. r0,r11,0x0080 ;check bit 24
beq L_co_switch$restore_skip_vr24
lvx v24,r1,r2 ;restore VR24
L_co_switch$restore_skip_vr24:
addi r2,r2,16 ;stride
andi. r0,r11,0x0040 ;check bit 25
beq L_co_switch$restore_skip_vr25
lvx v25,r1,r2 ;restore VR25
L_co_switch$restore_skip_vr25:
addi r2,r2,16 ;stride
andi. r0,r11,0x0020 ;check bit 26
beq L_co_switch$restore_skip_vr26
lvx v26,r1,r2 ;restore VR26
L_co_switch$restore_skip_vr26:
addi r2,r2,16 ;stride
andi. r0,r11,0x0010 ;check bit 27
beq L_co_switch$restore_skip_vr27
lvx v27,r1,r2 ;restore VR27
L_co_switch$restore_skip_vr27:
addi r2,r2,16 ;stride
andi. r0,r11,0x0008 ;check bit 28
beq L_co_switch$restore_skip_vr28
lvx v28,r1,r2 ;restore VR28
L_co_switch$restore_skip_vr28:
addi r2,r2,16 ;stride
andi. r0,r11,0x0004 ;check bit 29
beq L_co_switch$restore_skip_vr29
lvx v29,r1,r2 ;restore VR29
L_co_switch$restore_skip_vr29:
addi r2,r2,16 ;stride
andi. r0,r11,0x0002 ;check bit 30
beq L_co_switch$restore_skip_vr30
lvx v30,r1,r2 ;restore VR30
L_co_switch$restore_skip_vr30:
addi r2,r2,16 ;stride
andi. r0,r11,0x0001 ;check bit 31
beq L_co_switch$restore_skip_vr31
lvx v31,r1,r2 ;restore VR31
L_co_switch$restore_skip_vr31:
L_co_switch$restore_no_vmx:
lfd f14,248(r1) ;restore preserved FPRs
lfd f15,256(r1)
lfd f16,264(r1)
lfd f17,272(r1)
lfd f18,280(r1)
lfd f19,288(r1)
lfd f20,296(r1)
lfd f21,304(r1)
lfd f22,312(r1)
lfd f23,320(r1)
lfd f24,328(r1)
lfd f25,336(r1)
lfd f26,344(r1)
lfd f27,352(r1)
lfd f28,360(r1)
lfd f29,368(r1)
lfd f30,376(r1)
lfd f31,384(r1)
addi r0,0,0 ;make thread main crash if it returns
ld r1,0(r1) ;deallocate stack frame
ld r6,16(r1) ;return address in GPR6
lwz r7,8(r1) ;condition codes in GPR7
ld r13,-152(r1) ;restore preserved GPRs
ld r14,-144(r1)
ld r15,-136(r1)
ld r16,-128(r1)
ld r17,-120(r1)
ld r18,-112(r1)
ld r19,-104(r1)
ld r20,-96(r1)
ld r21,-88(r1)
ld r22,-80(r1)
ld r23,-72(r1)
ld r24,-64(r1)
ld r25,-56(r1)
ld r26,-48(r1)
ld r27,-40(r1)
ld r28,-32(r1)
ld r29,-24(r1)
ld r30,-16(r1)
ld r31,-8(r1)
mtlr r0
mtctr r6 ;restore return address
mtcrf 32,r7 ;restore preserved condition codes
mtcrf 16,r7
mtcrf 8,r7
bctr ;return
;Import external functions
.section __TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32
.align 5
L_malloc$stub:
.indirect_symbol _malloc
mflr r0
bcl 20,31,L_malloc$spb
L_malloc$spb:
mflr r11
addis r11,r11,ha16(L_malloc$lazy_ptr-L_malloc$spb)
mtlr r0
ldu r12,lo16(L_malloc$lazy_ptr-L_malloc$spb)(r11)
mtctr r12
bctr
.lazy_symbol_pointer
L_malloc$lazy_ptr:
.indirect_symbol _malloc
.quad dyld_stub_binding_helper
.section __TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32
.align 5
L_free$stub:
.indirect_symbol _free
mflr r0
bcl 20,31,L_free$spb
L_free$spb:
mflr r11
addis r11,r11,ha16(L_free$lazy_ptr-L_free$spb)
mtlr r0
ldu r12,lo16(L_free$lazy_ptr-L_free$spb)(r11)
mtctr r12
bctr
.lazy_symbol_pointer
L_free$lazy_ptr:
.indirect_symbol _free
.quad dyld_stub_binding_helper
.section __TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32
.align 5
L_sysctlbyname$stub:
.indirect_symbol _sysctlbyname
mflr r0
bcl 20,31,L_sysctlbyname$spb
L_sysctlbyname$spb:
mflr r11
addis r11,r11,ha16(L_sysctlbyname$lazy_ptr-L_sysctlbyname$spb)
mtlr r0
ldu r12,lo16(L_sysctlbyname$lazy_ptr-L_sysctlbyname$spb)(r11)
mtctr r12
bctr
.lazy_symbol_pointer
L_sysctlbyname$lazy_ptr:
.indirect_symbol _sysctlbyname
.quad dyld_stub_binding_helper
;This needs to be here!
.subsections_via_symbols
+80
View File
@@ -0,0 +1,80 @@
/*
libco.ucontext (2007-09-08)
author: byuu
license: public domain
*/
#include <stdlib.h>
#include <ucontext.h>
#include "../libco.h"
//WARNING: the overhead of POSIX ucontext is very high,
//averaging ~450x that of standard subroutine calls.
//(tested on FreeBSD 6.2-RELEASE)
//By contrast, on the same system, libco_x86's overhead
//is ~7.25x standard subroutine calls; or fifty times faster.
//
//This library only exists for two reasons:
//1 - as an initial test for the viability of a ucontext implementation
//2 - to demonstrate the power and speed of libco over existing implementations,
// such as pth (which defaults to wrapping ucontext on unix targets)
//
//Use this library only as a *last resort*
struct cothread_struct {
ucontext_t cohandle;
void (*coentry)();
};
cothread_t __co_active = 0, __co_primary = 0;
void co_entrypoint(cothread_t cothread);
void co_init();
/*****
* library functions
*****/
cothread_t co_active() {
if(__co_primary == 0)co_init();
return __co_active;
}
cothread_t co_create(unsigned int heapsize, void (*coentry)()) {
if(__co_primary == 0)co_init();
cothread_struct *thread = (cothread_struct*)malloc(sizeof(cothread_struct));
thread->coentry = coentry;
getcontext(&thread->cohandle);
heapsize += 512;
thread->cohandle.uc_stack.ss_sp = (char*)malloc(heapsize);
thread->cohandle.uc_stack.ss_size = heapsize;
makecontext(&thread->cohandle, (void (*)())co_entrypoint, 1, thread);
return (cothread_t)thread;
}
void co_delete(cothread_t cothread) {
cothread_struct *thread = (cothread_struct*)cothread;
free(thread->cohandle.uc_stack.ss_sp);
free(thread);
}
void co_switch(cothread_t cothread) {
cothread_struct *active = (cothread_struct*)__co_active;
cothread_struct *swap = (cothread_struct*)cothread;
__co_active = cothread;
swapcontext(&active->cohandle, &swap->cohandle);
}
/*****
* internal functions
*****/
void co_entrypoint(cothread_t cothread) {
((cothread_struct*)cothread)->coentry();
}
void co_init() {
cothread_struct *thread = (cothread_struct*)malloc(sizeof(cothread_struct));
thread->coentry = 0;
getcontext(&thread->cohandle);
__co_active = __co_primary = (cothread_t)thread;
}
+66
View File
@@ -0,0 +1,66 @@
/*
libco.win (2007-09-08)
author: byuu
license: public domain
*/
#define WINVER 0x0400
#define _WIN32_WINNT 0x0400
#include <windows.h>
#include "../libco.h"
struct cothread_struct {
void *cohandle;
void (*coentry)();
};
cothread_t __co_active = 0, __co_primary = 0;
void __stdcall co_entryproc(void*);
cothread_t co_init();
/*****
* library functions
*****/
cothread_t co_active() {
if(__co_primary == 0)co_init();
return __co_active;
}
cothread_t co_create(unsigned int heapsize, void (*coentry)()) {
if(__co_primary == 0)co_init();
cothread_struct *s = (cothread_struct*)malloc(sizeof(cothread_struct));
s->coentry = coentry;
s->cohandle = CreateFiber(heapsize + 512, co_entryproc, (void*)s);
return (cothread_t)s;
}
void co_delete(cothread_t cothread) {
cothread_struct *s = (cothread_struct*)cothread;
DeleteFiber(s->cohandle);
free(cothread);
}
void co_switch(cothread_t cothread) {
__co_active = cothread;
cothread_struct *s = (cothread_struct*)cothread;
SwitchToFiber(s->cohandle);
}
/*****
* internal functions
*****/
void __stdcall co_entryproc(void *cothread) {
((cothread_struct*)cothread)->coentry();
}
cothread_t co_init() {
ConvertThreadToFiber(0);
cothread_struct *s = (cothread_struct*)malloc(sizeof(cothread_struct));
s->coentry = 0;
s->cohandle = GetCurrentFiber();
__co_active = __co_primary = (cothread_t)s;
return __co_active;
}
@@ -1,123 +1,146 @@
;*****
;libco_x86_64 : version 0.10 ~byuu (2007-09-08)
;cross-platform x86-64 implementation of libco
;special thanks to Aaron Giles and Joel Yliluoma for various optimizations
;
;[ABI compatibility]
;- SystemV ( http://refspecs.freestandards.org/elf/x86_64-SysV-psABI.pdf )
;- gcc; linux; x86-64
;- gcc; freebsd; x86-64
;
;[nonvolatile registers]
;- rsp, rbp, rbx, r12, r13, r14, r15
;
;[volatile registers]
;- rax, rcx, rdx, r8, r9, r10, r11, rdi, rsi
;- st0 - st7
;- xmm0 - xmm15
;*****
bits 64
section .bss
align 8
co_primary_buffer resb 512
section .data
align 8
co_active_context dq co_primary_buffer
section .text
extern malloc
extern free
global co_active
global co_create
global co_delete
global co_switch
;*****
;extern "C" cothread_t co_active();
;return = rax
;*****
align 16
co_active:
mov rax,[co_active_context wrt rip]
ret
;*****
;extern "C" cothread_t co_create(unsigned int heapsize, void (*coentry)());
;rdi = heapsize
;rsi = coentry
;return = rax
;*****
align 16
co_create:
;create heap space (stack + register storage)
add rdi,512 ;allocate extra memory for contextual info
push rdi
push rsi
call malloc ;rax = malloc(rdi)
pop rsi
pop rdi
add rdi,rax ;set rsi to point to top of stack heap
and rdi,-16 ;force 16-byte alignment of stack heap
;store thread entry point + registers, so that first call to co_switch will execute coentry
mov qword[rdi-8],rsi ;entry point
mov qword[rdi-16],0 ;r15
mov qword[rdi-24],0 ;r14
mov qword[rdi-32],0 ;r13
mov qword[rdi-40],0 ;r12
mov qword[rdi-48],0 ;rbx
mov qword[rdi-56],0 ;rbp
sub rdi,56
;initialize context memory heap and return
mov [rax],rdi ;*cothread_t = stack heap pointer (rsp)
ret ;return allocated memory block as thread handle
;*****
;extern "C" void co_delete(cothread_t cothread);
;rdi = cothread
;*****
align 16
co_delete:
jmp free ;free(rdi)
;*****
;extern "C" void co_switch(cothread_t cothread);
;rdi = cothread
;*****
align 16
co_switch:
mov rax,[co_active_context wrt rip] ;backup current context
mov [co_active_context wrt rip],rdi ;set new active context
push rbp
push rbx
push r12
push r13
push r14
push r15
mov [rax],rsp
mov rsp,[rdi]
pop r15
pop r14
pop r13
pop r12
pop rbx
pop rbp
ret
;*****
;libco.x86-64 (2007-12-11)
;author: byuu
;license: public domain
;
;cross-platform x86-64 implementation of libco
;thanks to Aaron Giles and Joel Yliluoma for various optimizations
;thanks to Lucas Newman and Vas Crabb for assistance with OS X support
;
;[ABI compatibility]
;- SystemV ( http://refspecs.freestandards.org/elf/x86_64-SysV-psABI.pdf )
;- gcc; mac os x; x86-64
;- gcc; linux; x86-64
;- gcc; freebsd; x86-64
;
;[nonvolatile registers]
;- rsp, rbp, rbx, r12, r13, r14, r15
;
;[volatile registers]
;- rax, rcx, rdx, r8, r9, r10, r11, rdi, rsi
;- st0 - st7
;- xmm0 - xmm15
;*****
;*****
;linker-specific name decorations
;*****
%ifdef OSX
%define malloc _malloc
%define free _free
%define co_active _co_active
%define co_create _co_create
%define co_delete _co_delete
%define co_switch _co_switch
%endif
bits 64
section .bss
align 8
co_primary_buffer resb 512
section .data
align 8
co_active_context dq co_primary_buffer
section .text
extern malloc
extern free
global co_active
global co_create
global co_delete
global co_switch
;*****
;extern "C" cothread_t co_active();
;return = rax
;*****
align 16
co_active:
mov rax,[co_active_context wrt rip]
ret
;*****
;extern "C" cothread_t co_create(unsigned int heapsize, void (*coentry)());
;rdi = heapsize
;rsi = coentry
;return = rax
;*****
align 16
co_create:
;create heap space (stack + context)
add rdi,512 ;allocate extra memory for contextual info
push rdi ;backup volatile registers before malloc call
push rsi
sub rsp,8 ;SSE 16-byte stack alignment
call malloc ;rax = malloc(rdi)
add rsp,8
pop rsi ;restore volatile registers
pop rdi
add rdi,rax ;set rdi to point to top of stack heap
and rdi,-16 ;force 16-byte alignment of stack heap
;store thread entry point + registers, so that first call to co_switch will execute coentry
mov qword[rdi-8],0 ;crash if entry point returns
mov qword[rdi-16],rsi ;entry point
mov qword[rdi-24],0 ;r15
mov qword[rdi-32],0 ;r14
mov qword[rdi-40],0 ;r13
mov qword[rdi-48],0 ;r12
mov qword[rdi-56],0 ;rbx
mov qword[rdi-64],0 ;rbp
sub rdi,64
;initialize context memory heap and return
mov [rax],rdi ;*cothread_t = stack heap pointer (rsp)
ret ;return allocated memory block as thread handle
;*****
;extern "C" void co_delete(cothread_t cothread);
;rdi = cothread
;*****
align 16
co_delete:
jmp free ;free(rdi)
;*****
;extern "C" void co_switch(cothread_t cothread);
;rdi = cothread
;*****
align 16
co_switch:
mov rax,[co_active_context wrt rip] ;backup current context
mov [co_active_context wrt rip],rdi ;set new active context
push rbp
push rbx
push r12
push r13
push r14
push r15
mov [rax],rsp
mov rsp,[rdi]
pop r15
pop r14
pop r13
pop r12
pop rbx
pop rbp
ret
@@ -1,148 +1,155 @@
;*****
;libco_x86 : version 0.10 ~byuu (2007-09-08)
;cross-platform x86 implementation of libco
;special thanks to Aaron Giles and Joel Yliluoma for various optimizations
;
;[ABI compatibility]
;- visual c++; windows; x86
;- mingw; windows; x86
;- gcc; mac os x; x86
;- gcc; linux; x86
;- gcc; freebsd; x86
;
;[nonvolatile registers]
;- esp, ebp, edi, esi, ebx
;
;[volatile registers]
;- eax, ecx, edx
;- st0 - st7
;- xmm0 - xmm15
;*****
;*****
;linker-specific name decorations
;*****
%ifdef WIN32
%define malloc _malloc
%define free _free
%define co_active @co_active@0
%define co_create @co_create@8
%define co_delete @co_delete@4
%define co_switch @co_switch@4
%endif
%ifdef OSX86
%define malloc _malloc
%define free _free
%define co_active _co_active
%define co_create _co_create
%define co_delete _co_delete
%define co_switch _co_switch
%endif
bits 32
section .bss
align 4
co_primary_buffer resb 512
section .data
align 4
co_active_context dd co_primary_buffer
section .text
extern malloc
extern free
global co_active
global co_create
global co_delete
global co_switch
;*****
;extern "C" cothread_t fastcall co_active();
;return = eax
;*****
align 16
co_active:
mov eax,[co_active_context]
ret
;*****
;extern "C" cothread_t fastcall co_create(unsigned int heapsize, void (*coentry)());
;ecx = heapsize
;edx = coentry
;return = eax
;*****
align 16
co_create:
;create heap space (stack + register storage)
add ecx,512 ;allocate extra memory for contextual info
push ecx
push edx
push ecx
call malloc ;eax = malloc(edx)
add esp,4
pop edx
pop ecx
add ecx,eax ;set edx to point to top of stack heap
and ecx,-16 ;force 16-byte alignment of stack heap
;store thread entry point + registers, so that first call to co_switch will execute coentry
mov dword[ecx-4],edx ;entry point
mov dword[ecx-8],0 ;ebp
mov dword[ecx-12],0 ;esi
mov dword[ecx-16],0 ;edi
mov dword[ecx-20],0 ;ebx
sub ecx,20
;initialize context memory heap and return
mov [eax],ecx ;*cothread_t = stack heap pointer (esp)
ret ;return allocated memory block as thread handle
;*****
;extern "C" void fastcall co_delete(cothread_t cothread);
;ecx = cothread
;*****
align 16
co_delete:
push ecx
call free ;free(ecx)
add esp,4
ret
;*****
;extern "C" void fastcall co_switch(cothread_t cothread);
;ecx = cothread
;*****
align 16
co_switch:
mov eax,[co_active_context] ;backup current context
mov [co_active_context],ecx ;set new active context
push ebp
push esi
push edi
push ebx
mov [eax],esp
mov esp,[ecx]
pop ebx
pop edi
pop esi
pop ebp
ret
;*****
;libco.x86 (2007-12-11)
;author: byuu
;license: public domain
;
;cross-platform x86 implementation of libco
;thanks to Aaron Giles and Joel Yliluoma for various optimizations
;thanks to Lucas Newman and Vas Crabb for assistance with OS X support
;
;[ABI compatibility]
;- visual c++; windows; x86
;- mingw; windows; x86
;- gcc; mac os x; x86
;- gcc; linux; x86
;- gcc; freebsd; x86
;
;[nonvolatile registers]
;- esp, ebp, edi, esi, ebx
;
;[volatile registers]
;- eax, ecx, edx
;- st0 - st7
;- xmm0 - xmm15
;*****
;*****
;linker-specific name decorations
;*****
%ifdef WIN
%define malloc _malloc
%define free _free
%define co_active @co_active@0
%define co_create @co_create@8
%define co_delete @co_delete@4
%define co_switch @co_switch@4
%endif
%ifdef OSX
%define malloc _malloc
%define free _free
%define co_active _co_active
%define co_create _co_create
%define co_delete _co_delete
%define co_switch _co_switch
%endif
bits 32
section .bss
align 4
co_primary_buffer resb 512
section .data
align 4
co_active_context dd co_primary_buffer
section .text
extern malloc
extern free
global co_active
global co_create
global co_delete
global co_switch
;*****
;extern "C" cothread_t fastcall co_active();
;return = eax
;*****
align 16
co_active:
mov eax,[co_active_context]
ret
;*****
;extern "C" cothread_t fastcall co_create(unsigned int heapsize, void (*coentry)());
;ecx = heapsize
;edx = coentry
;return = eax
;*****
align 16
co_create:
;create heap space (stack + context)
add ecx,512 ;allocate extra memory for contextual info
push ecx ;backup volatile registers before malloc call
push edx
push ecx
call malloc ;eax = malloc(ecx)
add esp,4
pop edx ;restore volatile registers
pop ecx
add ecx,eax ;set edx to point to top of stack heap
and ecx,-16 ;force 16-byte alignment of stack heap
;store thread entry point + registers, so that first call to co_switch will execute coentry
mov dword[ecx-4],0 ;crash if entry point returns
mov dword[ecx-8],edx ;entry point
mov dword[ecx-12],0 ;ebp
mov dword[ecx-16],0 ;esi
mov dword[ecx-20],0 ;edi
mov dword[ecx-24],0 ;ebx
sub ecx,24
;initialize context memory heap and return
mov [eax],ecx ;*cothread_t = stack heap pointer (esp)
ret ;return allocated memory block as thread handle
;*****
;extern "C" void fastcall co_delete(cothread_t cothread);
;ecx = cothread
;*****
align 16
co_delete:
sub esp,8 ;SSE 16-byte stack alignment
push ecx
call free ;free(ecx)
add esp,4+8
ret
;*****
;extern "C" void fastcall co_switch(cothread_t cothread);
;ecx = cothread
;*****
align 16
co_switch:
mov eax,[co_active_context] ;backup current context
mov [co_active_context],ecx ;set new active context
push ebp
push esi
push edi
push ebx
mov [eax],esp
mov esp,[ecx]
pop ebx
pop edi
pop esi
pop ebp
ret
-26
View File
@@ -1,26 +0,0 @@
/*
libco_x86 : version 0.10 ~byuu (2007-09-08)
license: public domain
*/
#ifndef LIBCO_H
#define LIBCO_H
#if !defined(fastcall)
#if defined(_MSC_VER)
#define fastcall __fastcall
#elif defined(__GNUC__)
#define fastcall __attribute__((fastcall))
#else
#error "fastcall undefined"
#endif
#endif
typedef void *cothread_t;
extern "C" cothread_t fastcall co_active();
extern "C" cothread_t fastcall co_create(unsigned int heapsize, void (*coentry)());
extern "C" void fastcall co_delete(cothread_t cothread);
extern "C" void fastcall co_switch(cothread_t cothread);
#endif
-16
View File
@@ -1,16 +0,0 @@
/*
libco_x86_64 : version 0.10 ~byuu (2007-09-08)
license: public domain
*/
#ifndef LIBCO_H
#define LIBCO_H
typedef void *cothread_t;
extern "C" cothread_t co_active();
extern "C" cothread_t co_create(unsigned int heapsize, void (*coentry)());
extern "C" void co_delete(cothread_t cothread);
extern "C" void co_switch(cothread_t cothread);
#endif
-100
View File
@@ -1,100 +0,0 @@
/*
libfunctor : version 0.05 ~byuu (2007-09-08)
license: public domain
*/
#ifndef LIBFUNCTOR_H
#define LIBFUNCTOR_H
//prologue
#define TN typename
template<typename T> class functor;
//parameters = 0
#define cat(n) n
#define TL typename R
#define PL
#define CL
#include "libfunctor_impl.h"
//parameters = 1
#define cat(n) , n
#define TL TN R, TN P1
#define PL P1 p1
#define CL p1
#include "libfunctor_impl.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 "libfunctor_impl.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 "libfunctor_impl.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 "libfunctor_impl.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 "libfunctor_impl.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 "libfunctor_impl.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 "libfunctor_impl.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 "libfunctor_impl.h"
//epilogue
#undef TN
#endif
Loaded 100 of 327 files, more files were not shown because too many files have changed in this diff. Show more