mirror of
https://github.com/bradgrantham/apple2e.git
synced 2025-01-30 09:30:08 +00:00
add clock text box
This commit is contained in:
parent
0b61b25667
commit
fd1e15a595
54
apple2e.cpp
54
apple2e.cpp
@ -1592,6 +1592,42 @@ void print_cpu_state(const CPU6502<CLK, BUS>& cpu)
|
||||
printf("S:%02X (%02X %02X %02X ...) PC:%04X (%02X %02X %02X ...)\n", cpu.s, s0, s1, s2, cpu.pc, pc0, pc1, pc2);
|
||||
}
|
||||
|
||||
template <class TYPE, unsigned int LENGTH>
|
||||
struct averaged_sequence
|
||||
{
|
||||
int where;
|
||||
TYPE sum;
|
||||
TYPE list[LENGTH];
|
||||
|
||||
averaged_sequence() :
|
||||
where(-1)
|
||||
{
|
||||
for(int i = 0; i < LENGTH; i++)
|
||||
list[i] = 0;
|
||||
sum = 0;
|
||||
}
|
||||
|
||||
void add(TYPE value)
|
||||
{
|
||||
if(where == -1) {
|
||||
for(int i = 0; i < LENGTH; i++)
|
||||
list[i] = value;
|
||||
sum = value * LENGTH;
|
||||
where = 0;
|
||||
} else {
|
||||
sum -= list[where];
|
||||
list[where] = value;
|
||||
sum += list[where];
|
||||
where = (where + 1) % LENGTH;
|
||||
}
|
||||
}
|
||||
|
||||
TYPE get() const
|
||||
{
|
||||
return sum / LENGTH;
|
||||
}
|
||||
};
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
char *progname = argv[0];
|
||||
@ -1734,6 +1770,9 @@ int main(int argc, char **argv)
|
||||
APPLE2Einterface::start(run_fast, diskII_rom_name != NULL, floppy1_name != NULL, floppy2_name != NULL);
|
||||
|
||||
chrono::time_point<chrono::system_clock> then = std::chrono::system_clock::now();
|
||||
chrono::time_point<chrono::system_clock> cpu_speed_then = std::chrono::system_clock::now();
|
||||
clk_t cpu_previous_cycles = 0;
|
||||
averaged_sequence<float, 20> cpu_speed_averaged;
|
||||
|
||||
while(1) {
|
||||
if(!debugging) {
|
||||
@ -1772,7 +1811,18 @@ int main(int argc, char **argv)
|
||||
}
|
||||
mainboard->sync();
|
||||
|
||||
APPLE2Einterface::iterate(mode_history, clk.clock_cpu);
|
||||
chrono::time_point<chrono::system_clock> cpu_speed_now = std::chrono::system_clock::now();
|
||||
|
||||
auto cpu_elapsed_seconds = chrono::duration_cast<chrono::duration<float> >(cpu_speed_now - cpu_speed_then);
|
||||
cpu_speed_then = cpu_speed_now;
|
||||
|
||||
clk_t cpu_elapsed_cycles = clk.clock_cpu - cpu_previous_cycles;
|
||||
cpu_previous_cycles = clk.clock_cpu;
|
||||
|
||||
float cpu_speed = cpu_elapsed_cycles / cpu_elapsed_seconds.count();
|
||||
cpu_speed_averaged.add(cpu_speed);
|
||||
|
||||
APPLE2Einterface::iterate(mode_history, clk.clock_cpu, cpu_speed_averaged.get() / 1000000.0f);
|
||||
mode_history.clear();
|
||||
|
||||
chrono::time_point<chrono::system_clock> now = std::chrono::system_clock::now();
|
||||
@ -1838,7 +1888,7 @@ int main(int argc, char **argv)
|
||||
}
|
||||
mainboard->sync();
|
||||
|
||||
APPLE2Einterface::iterate(mode_history, clk.clock_cpu);
|
||||
APPLE2Einterface::iterate(mode_history, clk.clock_cpu, 1.023);
|
||||
mode_history.clear();
|
||||
}
|
||||
}
|
||||
|
@ -128,19 +128,31 @@ bool CheckProgramLink(GLuint program)
|
||||
return false;
|
||||
}
|
||||
|
||||
void opengl_texture::load(int w_, int h_, unsigned char *pixels)
|
||||
{
|
||||
w = w_;
|
||||
h = h_;
|
||||
glBindTexture(GL_TEXTURE_2D, t);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, w, h, 0, GL_RED, GL_UNSIGNED_BYTE, pixels);
|
||||
glBindTexture(GL_TEXTURE_2D, GL_NONE);
|
||||
}
|
||||
|
||||
opengl_texture initialize_texture(int w, int h, unsigned char *pixels)
|
||||
{
|
||||
GLuint tex;
|
||||
|
||||
glGenTextures(1, &tex);
|
||||
|
||||
opengl_texture t = {w, h, tex};
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, tex);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
||||
CheckOpenGL(__FILE__, __LINE__);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, w, h, 0, GL_RED, GL_UNSIGNED_BYTE, pixels);
|
||||
t.load(w, h, pixels);
|
||||
CheckOpenGL(__FILE__, __LINE__);
|
||||
return {w, h, tex};
|
||||
return t;
|
||||
}
|
||||
|
||||
GLuint GenerateProgram(const std::string& shader_name, const std::string& vertex_shader_text, const std::string& fragment_shader_text)
|
||||
|
@ -98,6 +98,7 @@ struct opengl_texture
|
||||
int h;
|
||||
GLuint t;
|
||||
operator GLuint() const { return t; }
|
||||
void load(int w, int h, unsigned char *pixels = NULL);
|
||||
};
|
||||
|
||||
opengl_texture initialize_texture(int w, int h, unsigned char *pixels = NULL);
|
||||
|
@ -753,12 +753,9 @@ struct text_widget : public widget
|
||||
float fg[4];
|
||||
float bg[4];
|
||||
|
||||
text_widget(const string& content_) :
|
||||
content(content_)
|
||||
void set_content(const string& content_)
|
||||
{
|
||||
set(fg, 1, 1, 1, 0);
|
||||
set(bg, 0, 0, 0, 0);
|
||||
|
||||
content = content_;
|
||||
// construct string texture
|
||||
unique_ptr<unsigned char> bytes(new unsigned char[content.size() + 1]);
|
||||
int i = 0;
|
||||
@ -773,10 +770,21 @@ struct text_widget : public widget
|
||||
bytes.get()[i] = 255;
|
||||
i++;
|
||||
}
|
||||
string_texture = initialize_texture(i, 1, bytes.get());
|
||||
string_texture.load(i, 1, bytes.get());
|
||||
rectangle.clear();
|
||||
rectangle.push_back({make_rectangle_array_buffer(0, 0, i * 7, 8), raster_coords_attrib, 2, GL_FLOAT, GL_FALSE, 0});
|
||||
}
|
||||
|
||||
text_widget(const string& content_) :
|
||||
content(content_)
|
||||
{
|
||||
set(fg, 1, 1, 1, 0);
|
||||
set(bg, 0, 0, 0, 0);
|
||||
|
||||
string_texture = initialize_texture(1, 1, NULL);
|
||||
set_content(content_);
|
||||
}
|
||||
|
||||
virtual width_height get_min_dimensions() const
|
||||
{
|
||||
return {content.size() * 7, 8};
|
||||
@ -967,10 +975,50 @@ struct toggle : public text_widget
|
||||
}
|
||||
};
|
||||
|
||||
struct textbox : public text_widget
|
||||
{
|
||||
textbox(const string& content_):
|
||||
text_widget(content_)
|
||||
{
|
||||
set(fg, 1, 1, 1, 1);
|
||||
set(bg, 0, 0, 0, 1);
|
||||
}
|
||||
|
||||
virtual width_height get_min_dimensions() const
|
||||
{
|
||||
float w, h;
|
||||
tie(w, h) = text_widget::get_min_dimensions();
|
||||
return {w + 3 * 2, h + 3 * 2};
|
||||
}
|
||||
|
||||
virtual void draw(double now, float to_screen[9], float x, float y, float w, float h)
|
||||
{
|
||||
// draw lines 2 pixels around
|
||||
// draw lines 1 pixels around
|
||||
// blank area 0 pixels around
|
||||
|
||||
text_widget::draw(now, to_screen, x + 3, y + 3, w - 6, h - 6);
|
||||
}
|
||||
|
||||
virtual bool click(double now, float x, float y)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual void drag(double now, float x, float y)
|
||||
{
|
||||
}
|
||||
|
||||
virtual void release(double now, float x, float y)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
widget *ui;
|
||||
widget *screen_only;
|
||||
toggle *caps_toggle;
|
||||
toggle *record_toggle;
|
||||
textbox *speed_textbox;
|
||||
|
||||
void initialize_gl(void)
|
||||
{
|
||||
@ -1264,8 +1312,9 @@ void initialize_widgets(bool run_fast, bool add_floppies, bool floppy0_inserted,
|
||||
toggle *color_toggle = new toggle("COLOR", false, [](){draw_using_color = true;}, [](){draw_using_color = false;});
|
||||
toggle *pause_toggle = new toggle("PAUSE", false, [](){event_queue.push_back({PAUSE, 1});}, [](){event_queue.push_back({PAUSE, 0});});
|
||||
record_toggle = new toggle("RECORD", false, [](){start_record();}, [](){stop_record();});
|
||||
speed_textbox = new textbox("X.YYY MHz");
|
||||
|
||||
vector<widget*> controls = {reset_momentary, reboot_momentary, fast_toggle, caps_toggle, color_toggle, pause_toggle, record_toggle};
|
||||
vector<widget*> controls = {reset_momentary, reboot_momentary, fast_toggle, caps_toggle, color_toggle, pause_toggle, record_toggle, speed_textbox};
|
||||
if(add_floppies) {
|
||||
floppy0_icon = new floppy_icon(0, floppy0_inserted);
|
||||
floppy1_icon = new floppy_icon(1, floppy1_inserted);
|
||||
@ -1684,8 +1733,24 @@ void map_history_to_lines(const ModeHistory& history, unsigned long long current
|
||||
map_mode_to_lines(most_recent_modepoint, current_byte);
|
||||
}
|
||||
|
||||
void iterate(const ModeHistory& history, unsigned long long current_byte)
|
||||
void iterate(const ModeHistory& history, unsigned long long current_byte, float megahertz)
|
||||
{
|
||||
static char speed_cstr[10];
|
||||
if(megahertz >= 100000.0) {
|
||||
sprintf(speed_cstr, "very fast");
|
||||
} else if(megahertz >= 10000.0) {
|
||||
sprintf(speed_cstr, "%5.2f GHz", megahertz);
|
||||
} else if(megahertz >= 1000.0) {
|
||||
sprintf(speed_cstr, "%5.3f GHz", megahertz);
|
||||
} else if(megahertz >= 100.0) {
|
||||
sprintf(speed_cstr, "%5.1f MHz", megahertz);
|
||||
} else if(megahertz >= 10.0) {
|
||||
sprintf(speed_cstr, "%5.2f MHz", megahertz);
|
||||
} else {
|
||||
sprintf(speed_cstr, "%5.3f MHz", megahertz);
|
||||
}
|
||||
speed_textbox->set_content(speed_cstr);
|
||||
|
||||
apply_writes();
|
||||
|
||||
CheckOpenGL(__FILE__, __LINE__);
|
||||
|
@ -95,7 +95,7 @@ void show_floppy_activity(int number, bool activity);
|
||||
void enqueue_audio_samples(char *buf, size_t sz);
|
||||
|
||||
void start(bool run_fast, bool add_floppies, bool floppy0_inserted, bool floppy1_inserted);
|
||||
void iterate(const ModeHistory& history, unsigned long long current_byte_in_frame); // display
|
||||
void iterate(const ModeHistory& history, unsigned long long current_byte_in_frame, float megahertz); // display
|
||||
void shutdown();
|
||||
|
||||
};
|
||||
|
Loading…
x
Reference in New Issue
Block a user