Commit b03277e5 authored by reassembler's avatar reassembler
Browse files

First public release.

parent 54300f9f
......@@ -14,6 +14,7 @@
</style>
</head>
<body>
<center><img src="cannonball_logo.png"></center>
<hr/>
<div class="emscripten" id="status">Downloading...</div>
<div class="emscripten">
......@@ -25,6 +26,9 @@
<hr/>
<!-- Additional Controls -->
Select OutRun Rev. B Romset (ZIPPED)
<input type="file" onchange="read_roms(this)" />
<hr/>
<input type="button" id="start" value="Start CannonBall!" onclick="cannonball_main()" />
Current fps:
<input type="text" id="fps" size="5"/>
......@@ -34,8 +38,6 @@
Sound:
<input type="checkbox" id="sound" onclick="audio_enabled = !audio_enabled; set_audio(audio_enabled)">
<hr/>
<input type="file" onchange="snes_readfile(this)" />
<hr/>
<input type="button" value="Fullscreen" onclick="cannonball_set_screen_mode(0)">
<textarea class="emscripten" id="output" rows="8"></textarea>
......@@ -51,6 +53,10 @@
cpp_audio = Module.cwrap('emscripten_audio', 'number', ['number', 'number']) // funcname, return, params
cpp_setfps = Module._emscripten_setfps
cpp_framesize = Module._emscripten_set_framesize
cpp_loadzip = Module.cwrap('emscripten_loadzip', 'number', ['string'])
// Disable Start Button
document.getElementById("start").disabled=true;
// Default to 30fps
inc_fps = false
......@@ -69,7 +75,7 @@
audio_enabled = false;
audio_freq = 44100;
audio_chan = 2;
buffer_size = 512; // Must be a multiple of 2
buffer_size = 1024; // Must be a multiple of 2
// Initialize Web Audio
var AudioContext = window.AudioContext || window.webkitAudioContext;
......@@ -94,13 +100,12 @@
var left = e.outputBuffer.getChannelData(0);
var right = e.outputBuffer.getChannelData(1);
fillBuffer(left, right);
};
set_audio(audio_enabled);
};
}
else
{
audio_supported = false;
alert('Web Audio API is not supported in this browser');
Module.print('Web Audio API is not supported in this browser. Sound not available.');
}
// Toggle Audio On/Off
......@@ -180,31 +185,6 @@
fps_text=document.getElementById("fps")
frameskipped=0
}
function set_sound(n)
{
var MIN = 256;
var MAX = 4096;
if (n > 0)
{
buffer_size *= 2;
}
else if (n < 0)
{
buffer_size /= 2;
}
/*if (buffer_size > MAX)
buffer_size = 0;
else if (buffer_size < MIN)
buffer_size = MAX;*/
sound_text.value = buffer_size;
cpp_framesize(buffer_size);
update_sound = 0;
}
function set_framerate(n)
{
......@@ -236,31 +216,6 @@
inc_fps = false
}
function snes_readfile(controller)
{
if (window.File && window.FileReader && window.FileList && window.Blob) {
} else {
alert('The File APIs are not fully supported in this browser.');
}
var f=controller.files[0]
cout_print(f.name)
var reader= new FileReader()
reader.onprogress = function(e){
if (e.lengthComputable){
cout_print(Math.round((e.loaded / e.total) * 100)+"%")
}
else
count_print(e.loaded+"bytes")
document.getElementById("start").disabled=false
}
reader.onload = function(e) {
cout_print("_.smc loaded")
Module.FS_createDataFile("/", "_.smc", new Uint8Array(this.result) , true, true)
}
reader.readAsArrayBuffer(f)
}
function cannonball_main()
{
document.getElementById("start").disabled=true
......@@ -268,6 +223,7 @@
cpp_init()
cpp_framesize(buffer_size);
frames = 0;
set_audio(audio_enabled);
last_time = new Date().getTime()
cannonball_mainloop();
}
......@@ -282,6 +238,41 @@
Module.requestFullScreen(hide_cursor, notify_sdl_resize)
}
}
function read_roms(controller)
{
if (window.File && window.FileReader && window.FileList && window.Blob);
else
{
alert('The File APIs are not fully supported in this browser.');
}
var f=controller.files[0]
//Module.print(f.name)
var reader= new FileReader()
reader.onprogress = function(e)
{
if (e.lengthComputable)
Module.print(Math.round((e.loaded / e.total) * 100)+"%")
else
Module.print(e.loaded+"bytes")
// Enable Start Button
document.getElementById("start").disabled = false;
}
reader.onload = function(e)
{
Module.print("File Loaded");
// FS.createDataFile(parent, name, data, canRead, canWrite)
Module.FS_createDataFile("/", "roms.zip", new Uint8Array(this.result), true, false);
// Call C++ Code to Handle The Zip File
cpp_loadzip("roms.zip");
document.getElementById("start").disabled=false
}
reader.readAsArrayBuffer(f);
}
</script>
</body>
\ No newline at end of file
......@@ -200,6 +200,13 @@ set(src_engine_audio
"${main_cpp_base}/engine/audio/osoundint.cpp"
)
set(src_unzip
"${main_cpp_base}/unzip/ioapi.h"
"${main_cpp_base}/unzip/ioapi.c"
"${main_cpp_base}/unzip/unzip.h"
"${main_cpp_base}/unzip/unzip.c"
)
# Group files into relevant filters for Visual Studio build
SOURCE_GROUP(src FILES ${src_main})
SOURCE_GROUP(src\\frontend FILES ${src_frontend})
......@@ -221,6 +228,7 @@ set(SRCS
${src_engine}
${src_engine_audio}
${src_tracked}
${src_unzip}
)
# Add Icon For Windows Builds
......
......@@ -6,6 +6,7 @@ set(OPENGL 0)
# Supress useless compiler warnings
set(CMAKE_CXX_FLAGS "-Qunused-arguments")
set(CMAKE_C_FLAGS "-Qunused-arguments")
# XML Config not used by Emscripten
set(xml_directory ./)
......
......@@ -34,7 +34,7 @@ goto end
:convertslow
cd %WORKING_DIR%
echo Converting .bc to .js (Not Optimized)
call emcc -s EXPORTED_FUNCTIONS="['_emscripten_init', '_emscripten_tick', '_emscripten_setfps', '_emscripten_audio']" ^
call emcc -s EXPORTED_FUNCTIONS="['_emscripten_init', '_emscripten_tick', '_emscripten_setfps', '_emscripten_audio', '_emscripten_set_framesize', '_emscripten_loadzip']" ^
cannonball.bc -o cannonball.html --preload-file C:\coding\cannonball\roms@roms
cd..
......@@ -46,8 +46,9 @@ echo Converting with new html... (OPTIMIZED)
rem call emcc -O2 --llvm-lto 1 -closure 1 -s DOUBLE_MODE=0 ^
call emcc -O2 -s DOUBLE_MODE=0 -closure 1 ^
call emcc -s EXPORTED_FUNCTIONS="['_emscripten_init', '_emscripten_tick', '_emscripten_setfps', '_emscripten_audio', '_emscripten_set_framesize']" ^
cannonball.bc -o cannonball.html --preload-file C:\coding\cannonball\roms@roms
-s EXPORTED_FUNCTIONS="['_emscripten_init', '_emscripten_tick', '_emscripten_setfps', '_emscripten_audio', '_emscripten_set_framesize', '_emscripten_loadzip']" ^
cannonball.bc ../libz.bc -o cannonball.html
rem --preload-file C:\coding\cannonball\roms@roms
echo Extracting Javascript from HTML
cd..
......
File added
......@@ -349,13 +349,13 @@ void Config::set_fps(int fps)
cannonball::frame_ms = (1000 / this->fps);
#ifdef COMPILE_SOUND_CODE
/*#ifdef COMPILE_SOUND_CODE
if (config.sound.enabled)
cannonball::audio.stop_audio();
osoundint.init();
if (config.sound.enabled)
cannonball::audio.start_audio();
#endif
#endif*/
}
// Convert value to string
......
......@@ -53,6 +53,8 @@ bool cannonball::tick_frame = true;
Menu menu;
//Tracked tracked;
bool roms_loaded;
static void quit_func(int code)
{
#ifdef COMPILE_SOUND_CODE
......@@ -92,6 +94,21 @@ void emscripten_audio(float* mix_buffer_l, float* mix_buffer_r)
audio.tick(mix_buffer_l, mix_buffer_r);
}
extern "C" void emscripten_loadzip(char *) __attribute__((used));
void emscripten_loadzip(char *filename)
{
bool success = roms.open_zip(filename);
if (success)
{
roms_loaded = roms.load_revb_roms();
if (roms_loaded)
roms.close_zip();
}
else
roms_loaded = false;
}
#endif
static void process_events(void)
......@@ -167,10 +184,13 @@ static void tick()
outrun.freeze_timer = !outrun.freeze_timer;
if (input.has_pressed(Input::PAUSE))
{
pause_engine = !pause_engine;
}
if (input.has_pressed(Input::MENU))
state = STATE_INIT_MENU;
// No menu for Emscripten
//if (input.has_pressed(Input::MENU))
// state = STATE_INIT_MENU;
if (!pause_engine || input.has_pressed(Input::STEP))
{
......@@ -277,7 +297,7 @@ static int init(void)
}
// Load Roms
bool roms_loaded = roms.load_revb_roms();
//roms_loaded = roms.load_revb_roms();
//trackloader.load_level("output.bin");
if (roms_loaded)
......@@ -315,6 +335,7 @@ static int init(void)
}
else
{
std::cout << "Roms not loaded. Please use OutRun Revision B. Roms and try again." << std::endl;
quit_func(1);
}
......
......@@ -8,17 +8,10 @@
See license.txt for more details.
***************************************************************************/
#include <iostream>
#include <fstream>
#include <cstddef> // for std::size_t
//#include <boost/crc.hpp> // CRC Checking via Boost library.
#include "stdint.hpp"
#include "romloader.hpp"
#ifdef __APPLE__
#include "CoreFoundation/CoreFoundation.h"
#endif
#include <cstddef> // NULL
RomLoader::RomLoader()
{
......@@ -40,48 +33,10 @@ void RomLoader::unload(void)
delete[] rom;
}
int RomLoader::load(const char* filename, const int offset, const int length, const int expected_crc, const uint8_t interleave)
int RomLoader::load(const char* buffer, const int offset, const int length, const int expected_crc, const uint8_t interleave)
{
#ifdef __APPLE__
CFBundleRef mainBundle = CFBundleGetMainBundle();
CFURLRef resourcesURL = CFBundleCopyResourcesDirectoryURL(mainBundle);
char bundlepath[PATH_MAX];
if (!CFURLGetFileSystemRepresentation(resourcesURL, TRUE, (UInt8 *)bundlepath, PATH_MAX))
{
// error!
}
CFRelease(resourcesURL);
chdir(bundlepath);
#endif
std::string path = "roms/";
path += std::string(filename);
// Open rom file
std::ifstream src(path.c_str(), std::ios::in | std::ios::binary);
if (!src)
{
std::cout << "cannot open rom: " << filename << std::endl;
return 1; // fail
}
// Read file
char* buffer = new char[length];
src.read(buffer, length);
// Check CRC on file
// HACKED OUT
/*boost::crc_32_type result;
result.process_bytes(buffer, (size_t) src.gcount());
if (expected_crc != result.checksum())
{
std::cout << std::hex <<
filename << " has incorrect checksum.\nExpected: " << expected_crc << " Found: " << result.checksum() << std::endl;
}*/
if (buffer == NULL)
return 1;
// Interleave file as necessary
for (int i = 0; i < length; i++)
......@@ -91,6 +46,5 @@ int RomLoader::load(const char* filename, const int offset, const int length, co
// Clean Up
delete[] buffer;
src.close();
return 0; // success
}
\ No newline at end of file
......@@ -24,7 +24,8 @@ public:
RomLoader();
~RomLoader();
void init(uint32_t);
int load(const char* filename, const int offset, const int length, const int expected_crc, const uint8_t mode = NORMAL);
int load(const char* buffer, const int offset, const int length, const int expected_crc, const uint8_t mode = NORMAL);
void unload(void);
// ----------------------------------------------------------------------------
......@@ -92,5 +93,5 @@ public:
return rom[addr];
}
private:
private:
};
\ No newline at end of file
......@@ -5,6 +5,13 @@
See license.txt for more details.
***************************************************************************/
#include <iostream>
#include <fstream>
#include <cstddef> // for std::size_t
#include <cstring>
//#include <boost/crc.hpp> // CRC Checking via Boost library.
#include "stdint.hpp"
#include "roms.hpp"
......@@ -12,6 +19,7 @@ Roms roms;
Roms::Roms()
{
zip_file = NULL;
jap_rom_status = -1;
}
......@@ -19,6 +27,89 @@ Roms::~Roms(void)
{
}
bool Roms::open_zip(const char* filename)
{
zip_file = unzOpen(filename);
if (zip_file == NULL)
{
std::cout << "Error opening zip file " << filename << std::endl;
}
return (zip_file != NULL);
}
void Roms::close_zip()
{
if (zip_file != NULL)
{
unzClose(zip_file);
zip_file = NULL;
}
}
char* Roms::read_file(const char* filename, int length)
{
if (zip_file == NULL)
{
std::string path = "roms/";
path += std::string(filename);
// Open rom file
std::ifstream src(path.c_str(), std::ios::in | std::ios::binary);
if (!src)
{
std::cout << "cannot open rom: " << filename << std::endl;
return NULL; // fail
}
// Read file
char* buffer = new char[length];
src.read(buffer, length);
src.close();
return buffer;
}
else
{
//std::cout << "Loading rom from zip: " << filename << std::endl;
// Ignore case sensitivity (2)
if (unzLocateFile(zip_file, filename, 2) != UNZ_OK)
{
std::cout << "cant locate zipped rom: " << filename << std::endl;
close_zip();
return NULL;
}
unz_file_info info;
if (unzGetCurrentFileInfo(zip_file, &info, NULL, 0, NULL, 0, NULL, 0 ) != UNZ_OK)
{
std::cout << "Error getting info from file: " << filename << std::endl;
close_zip();
return NULL;
}
if (unzOpenCurrentFile(zip_file) != UNZ_OK)
{
std::cout << "Error opening zipped rom: " << filename << std::endl;
close_zip();
return NULL;
}
if (info.uncompressed_size == length)
{
char* buffer = new char[info.uncompressed_size];
int size_read = unzReadCurrentFile(zip_file, buffer, info.uncompressed_size);
return buffer;
}
else
{
std::cout << "Zipped rom has wrong file size: " << filename << " (" << info.uncompressed_size << ")" << std::endl;
close_zip();
}
return NULL;
}
}
bool Roms::load_revb_roms()
{
// If incremented, a rom has failed to load.
......@@ -26,63 +117,63 @@ bool Roms::load_revb_roms()
// Load Master CPU ROMs
rom0.init(0x40000);
status += rom0.load("epr-10381a.132", 0x20000, 0x10000, 0xbe8c412b, RomLoader::INTERLEAVE2);
status += rom0.load(read_file("epr-10381a.132", 0x10000), 0x20000, 0x10000, 0xbe8c412b, RomLoader::INTERLEAVE2);
// Try alternate filename for this rom
if (status)
{
rom0.load("epr-10381b.132", 0x20000, 0x10000, 0xbe8c412b, RomLoader::INTERLEAVE2);
rom0.load(read_file("epr-10381b.132", 0x10000), 0x20000, 0x10000, 0xbe8c412b, RomLoader::INTERLEAVE2);
status--;
}
status += rom0.load("epr-10383b.117", 0x20001, 0x10000, 0x10a2014a, RomLoader::INTERLEAVE2);
status += rom0.load("epr-10380b.133", 0x00000, 0x10000, 0x1f6cadad, RomLoader::INTERLEAVE2);
status += rom0.load("epr-10382b.118", 0x00001, 0x10000, 0xc4c3fa1a, RomLoader::INTERLEAVE2);
status += rom0.load(read_file("epr-10383b.117", 0x10000), 0x20001, 0x10000, 0x10a2014a, RomLoader::INTERLEAVE2);
status += rom0.load(read_file("epr-10380b.133", 0x10000), 0x00000, 0x10000, 0x1f6cadad, RomLoader::INTERLEAVE2);
status += rom0.load(read_file("epr-10382b.118", 0x10000), 0x00001, 0x10000, 0xc4c3fa1a, RomLoader::INTERLEAVE2);
// Load Slave CPU ROMs
rom1.init(0x40000);
status += rom1.load("epr-10327a.76", 0x00000, 0x10000, 0xe28a5baf, RomLoader::INTERLEAVE2);
status += rom1.load("epr-10329a.58", 0x00001, 0x10000, 0xda131c81, RomLoader::INTERLEAVE2);
status += rom1.load("epr-10328a.75", 0x20000, 0x10000, 0xd5ec5e5d, RomLoader::INTERLEAVE2);
status += rom1.load("epr-10330a.57", 0x20001, 0x10000, 0xba9ec82a, RomLoader::INTERLEAVE2);
status += rom1.load(read_file("epr-10327a.76", 0x10000), 0x00000, 0x10000, 0xe28a5baf, RomLoader::INTERLEAVE2);
status += rom1.load(read_file("epr-10329a.58", 0x10000), 0x00001, 0x10000, 0xda131c81, RomLoader::INTERLEAVE2);
status += rom1.load(read_file("epr-10328a.75", 0x10000), 0x20000, 0x10000, 0xd5ec5e5d, RomLoader::INTERLEAVE2);
status += rom1.load(read_file("epr-10330a.57", 0x10000), 0x20001, 0x10000, 0xba9ec82a, RomLoader::INTERLEAVE2);
// Load Non-Interleaved Tile ROMs
tiles.init(0x30000);
status += tiles.load("opr-10268.99", 0x00000, 0x08000, 0x95344b04);
status += tiles.load("opr-10232.102", 0x08000, 0x08000, 0x776ba1eb);
status += tiles.load("opr-10267.100", 0x10000, 0x08000, 0xa85bb823);
status += tiles.load("opr-10231.103", 0x18000, 0x08000, 0x8908bcbf);
status += tiles.load("opr-10266.101", 0x20000, 0x08000, 0x9f6f1a74);
status += tiles.load("opr-10230.104", 0x28000, 0x08000, 0x686f5e50);
status += tiles.load(read_file("opr-10268.99", 0x08000), 0x00000, 0x08000, 0x95344b04);
status += tiles.load(read_file("opr-10232.102", 0x08000), 0x08000, 0x08000, 0x776ba1eb);
status += tiles.load(read_file("opr-10267.100", 0x08000), 0x10000, 0x08000, 0xa85bb823);
status += tiles.load(read_file("opr-10231.103", 0x08000), 0x18000, 0x08000, 0x8908bcbf);
status += tiles.load(read_file("opr-10266.101", 0x08000), 0x20000, 0x08000, 0x9f6f1a74);
status += tiles.load(read_file("opr-10230.104", 0x08000), 0x28000, 0x08000, 0x686f5e50);
// Load Non-Interleaved Road ROMs (2 identical roms, 1 for each road)
road.init(0x10000);
status += road.load("opr-10185.11", 0x000000, 0x08000, 0x22794426);
status += road.load("opr-10186.47", 0x008000, 0x08000, 0x22794426);
status += road.load(read_file("opr-10185.11", 0x08000), 0x000000, 0x08000, 0x22794426);
status += road.load(read_file("opr-10186.47", 0x08000), 0x008000, 0x08000, 0x22794426);
// Load Interleaved Sprite ROMs
sprites.init(0x100000);
status += sprites.load("mpr-10371.9", 0x000000, 0x20000, 0x7cc86208, RomLoader::INTERLEAVE4);
status += sprites.load("mpr-10373.10", 0x000001, 0x20000, 0xb0d26ac9, RomLoader::INTERLEAVE4);
status += sprites.load("mpr-10375.11", 0x000002, 0x20000, 0x59b60bd7, RomLoader::INTERLEAVE4);
status += sprites.load("mpr-10377.12", 0x000003, 0x20000, 0x17a1b04a, RomLoader::INTERLEAVE4);
status += sprites.load("mpr-10372.13", 0x080000, 0x20000, 0xb557078c, RomLoader::INTERLEAVE4);
status += sprites.load("mpr-10374.14", 0x080001, 0x20000, 0x8051e517, RomLoader::INTERLEAVE4);
status += sprites.load("mpr-10376.15", 0x080002, 0x20000, 0xf3b8f318, RomLoader::INTERLEAVE4);
status += sprites.load("mpr-10378.16", 0x080003, 0x20000, 0xa1062984, RomLoader::INTERLEAVE4);
status += sprites.load(read_file("mpr-10371.9", 0x20000), 0x000000, 0x20000, 0x7cc86208, RomLoader::INTERLEAVE4);
status += sprites.load(read_file("mpr-10373.10", 0x20000), 0x000001, 0x20000, 0xb0d26ac9, RomLoader::INTERLEAVE4);
status += sprites.load(read_file("mpr-10375.11", 0x20000), 0x000002, 0x20000, 0x59b60bd7, RomLoader::INTERLEAVE4);
status += sprites.load(read_file("mpr-10377.12", 0x20000), 0x000003, 0x20000, 0x17a1b04a, RomLoader::INTERLEAVE4);
status += sprites.load(read_file("mpr-10372.13", 0x20000), 0x080000, 0x20000, 0xb557078c, RomLoader::INTERLEAVE4);
status += sprites.load(read_file("mpr-10374.14", 0x20000), 0x080001, 0x20000, 0x8051e517, RomLoader::INTERLEAVE4);
status += sprites.load(read_file("mpr-10376.15", 0x20000), 0x080002, 0x20000, 0xf3b8f318, RomLoader::INTERLEAVE4);
status += sprites.load(read_file("mpr-10378.16", 0x20000), 0x080003, 0x20000, 0xa1062984, RomLoader::INTERLEAVE4);
// Load Z80 Sound ROM
z80.init(0x10000);
status += z80.load("epr-10187.88", 0x0000, 0x10000, 0xa10abaa9);
status += z80.load(read_file("epr-10187.88", 0x08000), 0x0000, 0x08000, 0xa10abaa9);
// Load Sega PCM Chip Samples
pcm.init(0x60000);
status += pcm.load("opr-10193.66", 0x00000, 0x08000, 0xbcd10dde);
status += pcm.load("opr-10192.67", 0x10000, 0x08000, 0x770f1270);
status += pcm.load("opr-10191.68", 0x20000, 0x08000, 0x20a284ab);
status += pcm.load("opr-10190.69", 0x30000, 0x08000, 0x7cab70e2);
status += pcm.load("opr-10189.70", 0x40000, 0x08000, 0x01366b54);
status += pcm.load("opr-10188.71", 0x50000, 0x08000, 0xbad30ad9);
status += pcm.load(read_file("opr-10193.66", 0x08000), 0x00000, 0x08000, 0xbcd10dde);
status += pcm.load(read_file("opr-10192.67", 0x08000), 0x10000, 0x08000, 0x770f1270);
status += pcm.load(read_file("opr-10191.68", 0x08000), 0x20000, 0x08000, 0x20a284ab);
status += pcm.load(read_file("opr-10190.69", 0x08000), 0x30000, 0x08000, 0x7cab70e2);
status += pcm.load(read_file("opr-10189.70", 0x08000), 0x40000, 0x08000, 0x01366b54);
status += pcm.load(read_file("opr-10188.71", 0x08000), 0x50000, 0x08000, 0xbad30ad9);
// If status has been incremented, a rom has failed to load.
return status == 0;
......@@ -101,16 +192,16 @@ bool Roms::load_japanese_roms()
jap_rom_status = 0;
// Load Master CPU ROMs
jap_rom_status += j_rom0.load("epr-10380.133", 0x00000, 0x10000, 0xe339e87a, RomLoader::INTERLEAVE2);
jap_rom_status += j_rom0.load("epr-10382.118", 0x00001, 0x10000, 0x65248dd5, RomLoader::INTERLEAVE2);
jap_rom_status += j_rom0.load("epr-10381.132", 0x20000, 0x10000, 0xbe8c412b, RomLoader::INTERLEAVE2);
jap_rom_status += j_rom0.load("epr-10383.117", 0x20001, 0x10000, 0xdcc586e7, RomLoader::INTERLEAVE2);
jap_rom_status += j_rom0.load(read_file("epr-10380.133", 0x10000), 0x00000, 0x10000, 0xe339e87a