Commit dd989809 authored by reassembler's avatar reassembler
Browse files

First checkin,

parent 1ec4f31b
......@@ -67,6 +67,12 @@ set(src_frontend
"${main_cpp_base}/frontend/menu.cpp"
"${main_cpp_base}/frontend/ttrial.cpp"
)
set(src_tracked
"${main_cpp_base}/tracked/tracked.hpp"
"${main_cpp_base}/tracked/tracked.cpp"
)
set(src_hwvideo
"${main_cpp_base}/hwvideo/hwroad.hpp"
......@@ -180,6 +186,7 @@ SOURCE_GROUP(src\\sdl FILES ${src_sdl})
SOURCE_GROUP(src\\directx FILES ${src_directx})
SOURCE_GROUP(src\\engine FILES ${src_engine})
SOURCE_GROUP(src\\engine\\audio FILES ${src_engine_audio})
SOURCE_GROUP(src\\tracked FILES ${src_tracked})
set(SRCS
${src_main}
......@@ -190,6 +197,7 @@ set(SRCS
${src_directx}
${src_engine}
${src_engine_audio}
${src_tracked}
)
# Add Icon For Windows Builds
......
......@@ -252,13 +252,7 @@ void OInitEngine::update_engine()
// Setup the shadow offset based on how much we've scrolled left/right. Lovely and subtle!
// ------------------------------------------------------------------------
int16_t shadow_off = oroad.tilemap_h_target & 0x3FF;
if (shadow_off > 0x1FF)
shadow_off = -shadow_off + 0x3FF;
shadow_off >>= 2;
if (oroad.tilemap_h_target & BIT_A)
shadow_off = -shadow_off; // reverse direction of shadow
osprites.shadow_offset = shadow_off;
update_shadow_offset();
// ------------------------------------------------------------------------
// Main Car Logic Block
......@@ -281,15 +275,7 @@ void OInitEngine::update_engine()
// Setup New Sprite Scroll Speed. Based On Granular Difference.
// ------------------------------------------------------------------------
set_granular_position();
uint16_t d0 = oroad.pos_fine - pos_fine_old;
if (d0 > 0xF)
d0 = 0xF;
d0 <<= 0xB;
osprites.sprite_scroll_speed = d0;
pos_fine_old = oroad.pos_fine;
set_fine_position();
// Draw Speed & Hud Stuff
if (outrun.game_state >= GS_START1 && outrun.game_state <= GS_BONUS)
......@@ -318,6 +304,17 @@ void OInitEngine::update_engine()
opalette.setup_sky_cycle();
}
void OInitEngine::update_shadow_offset()
{
int16_t shadow_off = oroad.tilemap_h_target & 0x3FF;
if (shadow_off > 0x1FF)
shadow_off = -shadow_off + 0x3FF;
shadow_off >>= 2;
if (oroad.tilemap_h_target & BIT_A)
shadow_off = -shadow_off; // reverse direction of shadow
osprites.shadow_offset = shadow_off;
}
// Check for Road Split
//
// - Checks position in level and determine whether to init road split
......@@ -836,6 +833,18 @@ void OInitEngine::set_granular_position()
oroad.pos_fine += result;
}
void OInitEngine::set_fine_position()
{
uint16_t d0 = oroad.pos_fine - pos_fine_old;
if (d0 > 0xF)
d0 = 0xF;
d0 <<= 0xB;
osprites.sprite_scroll_speed = d0;
pos_fine_old = oroad.pos_fine;
}
// Check whether to initalize crash or bonus sequence code
//
// Source: 0x984E
......
......@@ -146,7 +146,9 @@ public:
void init_crash_bonus();
void update_road();
void update_engine();
void update_shadow_offset();
void set_granular_position();
void set_fine_position();
void init_bonus(); // moved here for debugging purposes
......
......@@ -71,8 +71,6 @@ void Outrun::init()
select_course(config.engine.jap != 0, config.engine.prototype != 0);
video.clear_text_ram();
frame = 0;
tick_frame = true;
tick_counter = 0;
ohiscore.init_def_scores(); // Initialize default hi-score entries
config.load_scores(); // Load saved hi-score entries
......@@ -84,8 +82,10 @@ void Outrun::init()
}
void Outrun::tick()
void Outrun::tick(bool tick_frame)
{
this->tick_frame = tick_frame;
/*if (input.has_pressed(Input::LEFT))
{
game_state = GS_INIT_BONUS;
......@@ -96,19 +96,7 @@ void Outrun::tick()
oinitengine.init_bonus();
}*/
frame++;
// Non standard FPS.
// Determine whether to tick the current frame.
if (config.fps != 30)
{
if (config.fps == 60)
tick_frame = frame & 1;
else if (config.fps == 120)
tick_frame = (frame & 3) == 1;
}
if (tick_frame)
if (cannonball::tick_frame)
{
tick_counter++;
controls(); // Analogue Controls
......@@ -135,7 +123,7 @@ void Outrun::tick()
// Updates V-Blank 1/1 frames
else if (config.fps == 60 && config.tick_fps == 30)
{
if (tick_frame)
if (cannonball::tick_frame)
{
jump_table();
oroad.tick();
......@@ -160,7 +148,7 @@ void Outrun::vint()
osprites.update_sprites();
otiles.update_tilemaps();
if (config.fps < 120 || (frame & 1))
if (config.fps < 120 || (cannonball::frame & 1))
{
opalette.cycle_sky_palette();
opalette.fade_palette();
......@@ -224,7 +212,7 @@ void Outrun::jump_table()
// Core Game Engine Routines
// ----------------------------------------------------------------------------------------
case GS_LOGO:
if (!outrun.tick_frame)
if (!cannonball::tick_frame)
ologo.blit();
default:
......
......@@ -186,9 +186,6 @@ public:
// Service Mode Toggle: Not implemented yet.
bool service_mode;
// Frame counter
uint32_t frame;
// Tick Logic. Used when running at non-standard > 30 fps
bool tick_frame;
......@@ -204,7 +201,7 @@ public:
Outrun();
~Outrun();
void init();
void tick();
void tick(bool tick_frame);
void vint();
void select_course(const bool jap, const bool prototype);
......
......@@ -349,8 +349,8 @@ std::string Config::to_string(char c)
}
// Convert value to string
template<class T>
std::string Config::to_hex_string(T i)
//template<class T>
std::string Config::to_hex_string(int i)
{
std::stringstream ss;
ss << std::hex << i;
......
......@@ -123,10 +123,10 @@ public:
void set_fps(int fps);
std::string to_string(int i);
std::string to_string(char c);
std::string to_hex_string(int i);
private:
// Conversions
template<class T> std::string to_hex_string(T i);
uint32_t from_hex_string(std::string s);
};
......
......@@ -26,6 +26,7 @@
#include "engine/outrun.hpp"
#include "frontend/config.hpp"
#include "frontend/menu.hpp"
#include "tracked/tracked.hpp"
// Direct X Haptic Support.
// Fine to include on non-windows builds as dummy functions used.
......@@ -34,14 +35,17 @@
// Initialize Shared Variables
using namespace cannonball;
int cannonball::state = STATE_BOOT;
int cannonball::frame_ms = 0;
int cannonball::state = STATE_BOOT;
int cannonball::frame_ms = 0;
int cannonball::frame = 0;
bool cannonball::tick_frame = true;
#ifdef COMPILE_SOUND_CODE
Audio cannonball::audio;
#endif
Menu menu;
Tracked tracked;
static void quit_func(int code)
{
......@@ -100,6 +104,18 @@ bool pause_engine;
static void tick()
{
frame++;
// Non standard FPS.
// Determine whether to tick the current frame.
if (config.fps != 30)
{
if (config.fps == 60)
tick_frame = frame & 1;
else if (config.fps == 120)
tick_frame = (frame & 3) == 1;
}
process_events();
switch(state)
......@@ -117,7 +133,7 @@ static void tick()
if (!pause_engine || input.has_pressed(Input::STEP))
{
outrun.tick();
outrun.tick(tick_frame);
input.frame_done(); // Denote keys read
#ifdef COMPILE_SOUND_CODE
......@@ -163,6 +179,10 @@ static void tick()
menu.init();
state = STATE_MENU;
break;
case STATE_TRACKED:
tracked.tick();
break;
}
// Draw SDL Video
video.draw_frame();
......@@ -225,7 +245,8 @@ int main(int argc, char* argv[])
#ifdef COMPILE_SOUND_CODE
audio.init();
#endif
state = config.menu.enabled ? STATE_INIT_MENU : STATE_INIT_GAME;
//state = config.menu.enabled ? STATE_INIT_MENU : STATE_INIT_GAME;
state = STATE_TRACKED;
// Initalize controls
input.init(config.controls.keyconfig, config.controls.padconfig,
......
......@@ -12,6 +12,12 @@ namespace cannonball
extern Audio audio;
#endif
// Frame counter
extern int frame;
// Tick Logic. Used when running at non-standard > 30 fps
extern bool tick_frame;
// Millisecond Time Per Frame
extern int frame_ms;
......@@ -25,6 +31,7 @@ namespace cannonball
STATE_MENU,
STATE_INIT_GAME,
STATE_GAME,
STATE_TRACKED,
STATE_QUIT
};
}
\ No newline at end of file
#include <iostream>
#include <sstream>
#include "main.hpp"
#include "sdl/input.hpp"
#include "sdl/video.hpp"
#include "frontend/config.hpp"
#include "tracked/tracked.hpp"
#include "engine/outrun.hpp"
#include "engine/ohud.hpp"
#include "engine/olevelobjs.hpp"
#include "engine/otiles.hpp"
Tracked::Tracked(void)
{
}
Tracked::~Tracked(void)
{
}
void Tracked::init()
{
state = INIT;
}
void Tracked::tick()
{
switch (state)
{
case INIT:
outrun.init();
video.enabled = true;
cannonball::frame = 0;
outrun.game_state = GS_INGAME;
state = TICK;
break;
case TICK:
if (cannonball::tick_frame) controls();
tick_track();
video.clear_text_ram();
display_sprite_info();
break;
}
}
void Tracked::tick_track()
{
// CPU 1
if (cannonball::tick_frame)
{
oinitengine.update_road();
oinitengine.update_shadow_offset();
uint32_t result = 0x12F * (oinitengine.car_increment >> 16);
oroad.road_pos_change = result;
oroad.road_pos += result;
oinitengine.set_granular_position();
oinitengine.set_fine_position();
oroad.road_width_bak = oroad.road_width >> 16;
oroad.car_x_bak = oroad.road_width_bak;
oinitengine.car_x_pos = oroad.car_x_bak;
}
osprites.tick();
olevelobjs.do_sprite_routine();
osprites.sprite_copy();
// CPU 2
oroad.tick();
// Vertical Int
otiles.write_tilemap_hw();
osprites.update_sprites();
otiles.update_tilemaps();
oinitengine.set_granular_position();
}
void Tracked::display_sprite_info()
{
static const int TX = 16;
uint16_t road_pos = oroad.road_pos >> 16;
if (road_pos < 8) return;
uint32_t sprite_adr = oinitengine.road_seg_addr1 - 4;
uint16_t block_start = roms.rom0p->read16(&sprite_adr);
uint16_t block_end = roms.rom0p->read16(oinitengine.road_seg_addr1);
uint8_t total_spr = roms.rom0p->read8(&sprite_adr);
uint8_t sprite_id = roms.rom0p->read8(&sprite_adr);
// Master Sprite Table
//
// Each one of the following addresses contains the following:
// [+0] Sprite Frequency Value Bitmask [Word]
// [+2] Reload Value For Sprite Info Offset [Word]
// [+4] Start of table with x,y,type,palette etc.
uint32_t master_adr = roms.rom0p->read32(outrun.adr.sprite_master_table + (sprite_id * 4));
uint16_t seg_sprite_freq = roms.rom0p->read16(master_adr);
uint16_t seg_spr_offset2 = roms.rom0p->read16(master_adr + 2);
uint32_t xy_table_adr = master_adr + 4;
// Sprite Properties Table
//
// [+0] [Byte] Bit 0 = H-Flip Sprite
// Bit 1 = Enable Shadows
//
// Bits 4-7 = Routine Draw Number
// [+1] [Byte] Sprite X World Position
// [+2] [Word] Sprite Y World Position
// [+5] [Byte] Sprite Type
// [+7] [Byte] Sprite Palette
uint16_t sprite_x = roms.rom0p->read8 (xy_table_adr + 1);// << 4;
uint16_t sprite_y = roms.rom0p->read16(xy_table_adr + 2);// << 7;
uint8_t sprite_t = roms.rom0p->read8 (xy_table_adr + 5);// << 2;
uint8_t sprite_p = roms.rom0p->read8 (xy_table_adr + 7);
ohud.blit_text_new(0, 0, "ROAD POS", OHud::GREEN);
ohud.blit_text_new(TX, 0, config.to_hex_string(road_pos).c_str(), OHud::GREEN);
ohud.blit_text_new(0, 2, "SPRITE INFORMATION", OHud::PINK);
ohud.blit_text_new(0, 3, "BLOCK START");
ohud.blit_text_new(TX, 3, config.to_hex_string(block_start).c_str());
ohud.blit_text_new(0, 4, "BLOCK END");
ohud.blit_text_new(TX, 4, config.to_hex_string(block_end).c_str());
ohud.blit_text_new(0, 5, "TOTAL");
ohud.blit_text_new(TX, 5, config.to_hex_string(total_spr).c_str());
ohud.blit_text_new(0, 6, "MASTER INDEX");
ohud.blit_text_new(TX, 6, config.to_hex_string(sprite_id).c_str());
ohud.blit_text_new(0, 7, "ADDRESS");
ohud.blit_text_new(TX, 7, config.to_hex_string(master_adr).c_str());
ohud.blit_text_new(0, 9, "FREQUENCY TABLE", OHud::PINK);
ohud.blit_text_new(0, 10, "FREQUENCY");
ohud.blit_text_new(TX, 10, dec_to_bin(seg_sprite_freq).c_str());
ohud.blit_text_new(0, 11, "SPRITES DEFINED"); // Number of sprites in this particular block of data
ohud.blit_text_new(TX, 11, config.to_hex_string(seg_spr_offset2 / 8).c_str()); // 0 to this is the sprite address of block
ohud.blit_text_new(0, 12, "SPRITE ADDRESS");
ohud.blit_text_new(TX, 12, config.to_hex_string(xy_table_adr).c_str()); // 0 to this is the sprite address of block
ohud.blit_text_new(0, 14, "SPRITE PROPERTIES", OHud::PINK);
ohud.blit_text_new(0, 15, "X Y");
ohud.blit_text_new(TX, 15, config.to_hex_string(sprite_x).c_str());
ohud.blit_text_new(TX + 3, 15, config.to_hex_string(sprite_y).c_str());
ohud.blit_text_new(0, 16, "TYPE");
ohud.blit_text_new(TX, 16, config.to_hex_string(sprite_t).c_str());
ohud.blit_text_new(0, 17, "PALETTE");
ohud.blit_text_new(TX, 17, config.to_hex_string(sprite_p).c_str());
}
std::string Tracked::dec_to_bin(int nValue, bool bReverse)
{
std::string sBin;
while(nValue != 0)
{
sBin += (nValue & 1) ? '1' : '0';
nValue >>= 1;
}
if(!bReverse)
std::reverse(sBin.begin(),sBin.end());
return sBin;
}
void Tracked::controls()
{
if (input.is_pressed(Input::LEFT))
oinitengine.camera_x_off += 5;
if (input.is_pressed(Input::RIGHT))
oinitengine.camera_x_off -= 5;
// Start/Stop
if (input.has_pressed(Input::GEAR))
{
if (oinitengine.car_increment != 0x80 << 16)
oinitengine.car_increment = 0x80 << 16;
else
oinitengine.car_increment = 0;
}
if (input.is_pressed(Input::UP))
oinitengine.car_increment = 0x20 << 16;
else if (oinitengine.car_increment != 0x80 << 16)
oinitengine.car_increment = 0;
if (input.is_pressed(Input::ACCEL))
{
oroad.horizon_base += -20;
if (oroad.horizon_base < 0x100)
oroad.horizon_base = 0x100;
}
if (input.is_pressed(Input::BRAKE))
{
oroad.horizon_base += 20;
if (oroad.horizon_base > 0x6A0)
oroad.horizon_base = 0x6A0;
}
input.frame_done();
}
\ No newline at end of file
#pragma once
#include "stdint.hpp"
class Tracked
{
public:
Tracked(void);
~Tracked(void);
void init();
void tick();
private:
enum states
{
INIT = 0,
TICK = 1,
};
uint8_t state;
void tick_track();
void controls();
void display_sprite_info();
std::string dec_to_bin(int nValue, bool bReverse = false);
};
\ No newline at end of file
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment