2017-11-26 18:28:26 +00:00
|
|
|
//
|
|
|
|
// 9918.hpp
|
|
|
|
// Clock Signal
|
|
|
|
//
|
|
|
|
// Created by Thomas Harte on 25/11/2017.
|
|
|
|
// Copyright © 2017 Thomas Harte. All rights reserved.
|
|
|
|
//
|
|
|
|
|
|
|
|
#ifndef _918_hpp
|
|
|
|
#define _918_hpp
|
|
|
|
|
|
|
|
#include "../../Outputs/CRT/CRT.hpp"
|
|
|
|
#include "../../ClockReceiver/ClockReceiver.hpp"
|
|
|
|
|
2017-11-26 21:47:59 +00:00
|
|
|
#include <cstdint>
|
|
|
|
|
2017-11-26 18:28:26 +00:00
|
|
|
namespace TI {
|
|
|
|
|
|
|
|
class TMS9918 {
|
|
|
|
public:
|
|
|
|
enum Personality {
|
2017-11-29 02:10:30 +00:00
|
|
|
TMS9918A, // includes the 9928A; set TV standard as desired.
|
2017-11-26 18:28:26 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
/*!
|
|
|
|
Constructs an instance of the drive controller that behaves according to personality @c p.
|
|
|
|
@param p The type of controller to emulate.
|
|
|
|
*/
|
|
|
|
TMS9918(Personality p);
|
|
|
|
|
2017-11-29 02:10:30 +00:00
|
|
|
enum TVStandard {
|
|
|
|
PAL, NTSC
|
|
|
|
};
|
|
|
|
void set_tv_standard(TVStandard standard);
|
|
|
|
|
2017-11-26 18:28:26 +00:00
|
|
|
std::shared_ptr<Outputs::CRT::CRT> get_crt();
|
|
|
|
|
|
|
|
/*!
|
|
|
|
Runs the VCP for the number of cycles indicate; it is an implicit assumption of the code
|
|
|
|
that the input clock rate is 3579545 Hz — the NTSC colour clock rate.
|
|
|
|
*/
|
2017-11-27 01:07:30 +00:00
|
|
|
void run_for(const HalfCycles cycles);
|
2017-11-26 18:28:26 +00:00
|
|
|
|
2017-11-26 21:47:59 +00:00
|
|
|
void set_register(int address, uint8_t value);
|
|
|
|
uint8_t get_register(int address);
|
|
|
|
|
2017-11-30 01:31:55 +00:00
|
|
|
HalfCycles get_time_until_interrupt();
|
|
|
|
bool get_interrupt_line();
|
|
|
|
|
2017-11-26 18:28:26 +00:00
|
|
|
private:
|
|
|
|
std::shared_ptr<Outputs::CRT::CRT> crt_;
|
2017-11-27 01:01:11 +00:00
|
|
|
|
2017-11-28 00:43:33 +00:00
|
|
|
uint8_t ram_[16384];
|
2017-11-27 01:01:11 +00:00
|
|
|
|
|
|
|
uint16_t ram_pointer_ = 0;
|
|
|
|
uint8_t read_ahead_buffer_ = 0;
|
|
|
|
|
|
|
|
uint8_t status_ = 0;
|
|
|
|
|
|
|
|
bool write_phase_ = false;
|
|
|
|
uint8_t low_write_ = 0;
|
|
|
|
|
|
|
|
// The various register flags.
|
2017-11-28 00:43:33 +00:00
|
|
|
int next_screen_mode_ = 0, screen_mode_ = 0;
|
2017-12-01 03:48:07 +00:00
|
|
|
bool next_blank_screen_ = true, blank_screen_ = true;
|
2017-11-27 01:01:11 +00:00
|
|
|
bool sprites_16x16_ = false;
|
|
|
|
bool sprites_magnified_ = false;
|
|
|
|
bool generate_interrupts_ = false;
|
2017-12-07 01:24:29 +00:00
|
|
|
int sprite_height_ = 8;
|
2017-11-27 01:01:11 +00:00
|
|
|
uint16_t pattern_name_address_ = 0;
|
|
|
|
uint16_t colour_table_address_ = 0;
|
|
|
|
uint16_t pattern_generator_table_address_ = 0;
|
|
|
|
uint16_t sprite_attribute_table_address_ = 0;
|
|
|
|
uint16_t sprite_generator_table_address_ = 0;
|
2017-12-01 02:35:26 +00:00
|
|
|
|
2017-11-27 01:01:11 +00:00
|
|
|
uint8_t text_colour_ = 0;
|
|
|
|
uint8_t background_colour_ = 0;
|
|
|
|
|
2017-11-30 01:31:55 +00:00
|
|
|
HalfCycles half_cycles_into_frame_;
|
2017-11-28 02:36:12 +00:00
|
|
|
int column_ = 0, row_ = 0, output_column_ = 0;
|
2017-11-28 00:43:33 +00:00
|
|
|
int cycles_error_ = 0;
|
2017-12-03 03:13:43 +00:00
|
|
|
uint32_t *pixel_target_ = nullptr, *pixel_base_ = nullptr;
|
2017-11-28 03:05:40 +00:00
|
|
|
|
|
|
|
void output_border(int cycles);
|
2017-11-29 02:10:30 +00:00
|
|
|
|
|
|
|
// Vertical timing details.
|
|
|
|
int frame_lines_ = 262;
|
|
|
|
int first_vsync_line_ = 227;
|
|
|
|
|
|
|
|
// Horizontal selections.
|
|
|
|
enum class LineMode {
|
|
|
|
Text,
|
|
|
|
Character
|
|
|
|
} line_mode_ = LineMode::Text;
|
|
|
|
int first_pixel_column_, first_right_border_column_;
|
|
|
|
|
2017-12-05 03:18:51 +00:00
|
|
|
uint8_t pattern_names_[40];
|
2017-11-29 02:19:28 +00:00
|
|
|
uint8_t pattern_buffer_[40];
|
2017-12-01 02:35:26 +00:00
|
|
|
uint8_t colour_buffer_[40];
|
2017-12-05 03:18:51 +00:00
|
|
|
|
2017-12-09 03:12:39 +00:00
|
|
|
struct SpriteSet {
|
|
|
|
struct ActiveSprite {
|
|
|
|
int index = 0;
|
|
|
|
int row = 0;
|
2017-12-10 01:30:12 +00:00
|
|
|
|
2017-12-09 03:12:39 +00:00
|
|
|
uint8_t info[4];
|
|
|
|
uint8_t image[2];
|
2017-12-10 01:30:12 +00:00
|
|
|
|
|
|
|
int shift_position = 0;
|
2017-12-09 03:12:39 +00:00
|
|
|
} active_sprites[4];
|
|
|
|
int active_sprite_slot = 0;
|
|
|
|
} sprite_sets_[2];
|
|
|
|
int active_sprite_set_ = 0;
|
2017-12-06 03:39:03 +00:00
|
|
|
bool sprites_stopped_ = false;
|
|
|
|
|
2017-11-29 02:10:30 +00:00
|
|
|
int access_pointer_ = 0;
|
2017-12-03 03:13:43 +00:00
|
|
|
|
2017-12-06 03:39:03 +00:00
|
|
|
inline void test_sprite(int sprite_number);
|
2017-12-07 01:24:29 +00:00
|
|
|
inline void get_sprite_contents(int start, int cycles, int screen_row);
|
2017-11-26 18:28:26 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
#endif /* _918_hpp */
|